Unverified Commit 297a5fe7 authored by Stephen Boyd's avatar Stephen Boyd
Browse files

Merge tag 'spacemit-clk-for-6.17-1' of https://github.com/spacemit-com/linux into clk-spacemit

Pull SpacemiT clk driver updates from Yixun Lan:

 - Mark SpacemiT pll1_d8 clk as critical
 - Add reset support for SpacemiT K1 SoC

* tag 'spacemit-clk-for-6.17-1' of https://github.com/spacemit-com/linux:
  reset: spacemit: add support for SpacemiT CCU resets
  clk: spacemit: mark K1 pll1_d8 as critical
  clk: spacemit: define three reset-only CCUs
  clk: spacemit: set up reset auxiliary devices
  soc: spacemit: create a header for clock/reset registers
  dt-bindings: soc: spacemit: define spacemit,k1-ccu resets
parents 19272b37 c79550f6
Loading
Loading
Loading
Loading
+21 −6
Original line number Diff line number Diff line
@@ -19,6 +19,9 @@ properties:
      - spacemit,k1-syscon-apbc
      - spacemit,k1-syscon-apmu
      - spacemit,k1-syscon-mpmu
      - spacemit,k1-syscon-rcpu
      - spacemit,k1-syscon-rcpu2
      - spacemit,k1-syscon-apbc2

  reg:
    maxItems: 1
@@ -47,9 +50,6 @@ properties:
required:
  - compatible
  - reg
  - clocks
  - clock-names
  - "#clock-cells"
  - "#reset-cells"

allOf:
@@ -57,13 +57,28 @@ allOf:
      properties:
        compatible:
          contains:
            const: spacemit,k1-syscon-apbc
            enum:
              - spacemit,k1-syscon-apmu
              - spacemit,k1-syscon-mpmu
    then:
      required:
        - "#power-domain-cells"
    else:
      properties:
        "#power-domain-cells": false
    else:
  - if:
      properties:
        compatible:
          contains:
            enum:
              - spacemit,k1-syscon-apbc
              - spacemit,k1-syscon-apmu
              - spacemit,k1-syscon-mpmu
    then:
      required:
        - "#power-domain-cells"
        - clocks
        - clock-names
        - "#clock-cells"

additionalProperties: false

+1 −0
Original line number Diff line number Diff line
@@ -3,6 +3,7 @@
config SPACEMIT_CCU
	tristate "Clock support for SpacemiT SoCs"
	depends on ARCH_SPACEMIT || COMPILE_TEST
	select AUXILIARY_BUS
	select MFD_SYSCON
	help
	  Say Y to enable clock controller unit support for SpacemiT SoCs.
+121 −121
Original line number Diff line number Diff line
@@ -5,12 +5,16 @@
 */

#include <linux/array_size.h>
#include <linux/auxiliary_bus.h>
#include <linux/clk-provider.h>
#include <linux/delay.h>
#include <linux/idr.h>
#include <linux/mfd/syscon.h>
#include <linux/minmax.h>
#include <linux/module.h>
#include <linux/platform_device.h>
#include <linux/slab.h>
#include <soc/spacemit/k1-syscon.h>

#include "ccu_common.h"
#include "ccu_pll.h"
@@ -19,121 +23,14 @@

#include <dt-bindings/clock/spacemit,k1-syscon.h>

/* APBS register offset */
#define APBS_PLL1_SWCR1			0x100
#define APBS_PLL1_SWCR2			0x104
#define APBS_PLL1_SWCR3			0x108
#define APBS_PLL2_SWCR1			0x118
#define APBS_PLL2_SWCR2			0x11c
#define APBS_PLL2_SWCR3			0x120
#define APBS_PLL3_SWCR1			0x124
#define APBS_PLL3_SWCR2			0x128
#define APBS_PLL3_SWCR3			0x12c

/* MPMU register offset */
#define MPMU_POSR			0x0010
#define  POSR_PLL1_LOCK			BIT(27)
#define  POSR_PLL2_LOCK			BIT(28)
#define  POSR_PLL3_LOCK			BIT(29)
#define MPMU_SUCCR			0x0014
#define MPMU_ISCCR			0x0044
#define MPMU_WDTPCR			0x0200
#define MPMU_RIPCCR			0x0210
#define MPMU_ACGR			0x1024
#define MPMU_APBCSCR			0x1050
#define MPMU_SUCCR_1			0x10b0

/* APBC register offset */
#define APBC_UART1_CLK_RST		0x00
#define APBC_UART2_CLK_RST		0x04
#define APBC_GPIO_CLK_RST		0x08
#define APBC_PWM0_CLK_RST		0x0c
#define APBC_PWM1_CLK_RST		0x10
#define APBC_PWM2_CLK_RST		0x14
#define APBC_PWM3_CLK_RST		0x18
#define APBC_TWSI8_CLK_RST		0x20
#define APBC_UART3_CLK_RST		0x24
#define APBC_RTC_CLK_RST		0x28
#define APBC_TWSI0_CLK_RST		0x2c
#define APBC_TWSI1_CLK_RST		0x30
#define APBC_TIMERS1_CLK_RST		0x34
#define APBC_TWSI2_CLK_RST		0x38
#define APBC_AIB_CLK_RST		0x3c
#define APBC_TWSI4_CLK_RST		0x40
#define APBC_TIMERS2_CLK_RST		0x44
#define APBC_ONEWIRE_CLK_RST		0x48
#define APBC_TWSI5_CLK_RST		0x4c
#define APBC_DRO_CLK_RST		0x58
#define APBC_IR_CLK_RST			0x5c
#define APBC_TWSI6_CLK_RST		0x60
#define APBC_COUNTER_CLK_SEL		0x64
#define APBC_TWSI7_CLK_RST		0x68
#define APBC_TSEN_CLK_RST		0x6c
#define APBC_UART4_CLK_RST		0x70
#define APBC_UART5_CLK_RST		0x74
#define APBC_UART6_CLK_RST		0x78
#define APBC_SSP3_CLK_RST		0x7c
#define APBC_SSPA0_CLK_RST		0x80
#define APBC_SSPA1_CLK_RST		0x84
#define APBC_IPC_AP2AUD_CLK_RST		0x90
#define APBC_UART7_CLK_RST		0x94
#define APBC_UART8_CLK_RST		0x98
#define APBC_UART9_CLK_RST		0x9c
#define APBC_CAN0_CLK_RST		0xa0
#define APBC_PWM4_CLK_RST		0xa8
#define APBC_PWM5_CLK_RST		0xac
#define APBC_PWM6_CLK_RST		0xb0
#define APBC_PWM7_CLK_RST		0xb4
#define APBC_PWM8_CLK_RST		0xb8
#define APBC_PWM9_CLK_RST		0xbc
#define APBC_PWM10_CLK_RST		0xc0
#define APBC_PWM11_CLK_RST		0xc4
#define APBC_PWM12_CLK_RST		0xc8
#define APBC_PWM13_CLK_RST		0xcc
#define APBC_PWM14_CLK_RST		0xd0
#define APBC_PWM15_CLK_RST		0xd4
#define APBC_PWM16_CLK_RST		0xd8
#define APBC_PWM17_CLK_RST		0xdc
#define APBC_PWM18_CLK_RST		0xe0
#define APBC_PWM19_CLK_RST		0xe4

/* APMU register offset */
#define APMU_JPG_CLK_RES_CTRL		0x020
#define APMU_CSI_CCIC2_CLK_RES_CTRL	0x024
#define APMU_ISP_CLK_RES_CTRL		0x038
#define APMU_LCD_CLK_RES_CTRL1		0x044
#define APMU_LCD_SPI_CLK_RES_CTRL	0x048
#define APMU_LCD_CLK_RES_CTRL2		0x04c
#define APMU_CCIC_CLK_RES_CTRL		0x050
#define APMU_SDH0_CLK_RES_CTRL		0x054
#define APMU_SDH1_CLK_RES_CTRL		0x058
#define APMU_USB_CLK_RES_CTRL		0x05c
#define APMU_QSPI_CLK_RES_CTRL		0x060
#define APMU_DMA_CLK_RES_CTRL		0x064
#define APMU_AES_CLK_RES_CTRL		0x068
#define APMU_VPU_CLK_RES_CTRL		0x0a4
#define APMU_GPU_CLK_RES_CTRL		0x0cc
#define APMU_SDH2_CLK_RES_CTRL		0x0e0
#define APMU_PMUA_MC_CTRL		0x0e8
#define APMU_PMU_CC2_AP			0x100
#define APMU_PMUA_EM_CLK_RES_CTRL	0x104
#define APMU_AUDIO_CLK_RES_CTRL		0x14c
#define APMU_HDMI_CLK_RES_CTRL		0x1b8
#define APMU_CCI550_CLK_CTRL		0x300
#define APMU_ACLK_CLK_CTRL		0x388
#define APMU_CPU_C0_CLK_CTRL		0x38C
#define APMU_CPU_C1_CLK_CTRL		0x390
#define APMU_PCIE_CLK_RES_CTRL_0	0x3cc
#define APMU_PCIE_CLK_RES_CTRL_1	0x3d4
#define APMU_PCIE_CLK_RES_CTRL_2	0x3dc
#define APMU_EMAC0_CLK_RES_CTRL		0x3e4
#define APMU_EMAC1_CLK_RES_CTRL		0x3ec

struct spacemit_ccu_data {
	const char *reset_name;
	struct clk_hw **hws;
	size_t num;
};

static DEFINE_IDA(auxiliary_ids);

/* APBS clocks start, APBS region contains and only contains all PLL clocks */

/*
@@ -170,7 +67,8 @@ CCU_FACTOR_GATE_DEFINE(pll1_d4, CCU_PARENT_HW(pll1), APBS_PLL1_SWCR2, BIT(3), 4,
CCU_FACTOR_GATE_DEFINE(pll1_d5, CCU_PARENT_HW(pll1), APBS_PLL1_SWCR2, BIT(4), 5, 1);
CCU_FACTOR_GATE_DEFINE(pll1_d6, CCU_PARENT_HW(pll1), APBS_PLL1_SWCR2, BIT(5), 6, 1);
CCU_FACTOR_GATE_DEFINE(pll1_d7, CCU_PARENT_HW(pll1), APBS_PLL1_SWCR2, BIT(6), 7, 1);
CCU_FACTOR_GATE_DEFINE(pll1_d8, CCU_PARENT_HW(pll1), APBS_PLL1_SWCR2, BIT(7), 8, 1);
CCU_FACTOR_GATE_FLAGS_DEFINE(pll1_d8, CCU_PARENT_HW(pll1), APBS_PLL1_SWCR2, BIT(7), 8, 1,
		CLK_IS_CRITICAL);
CCU_FACTOR_GATE_DEFINE(pll1_d11_223p4, CCU_PARENT_HW(pll1), APBS_PLL1_SWCR2, BIT(15), 11, 1);
CCU_FACTOR_GATE_DEFINE(pll1_d13_189, CCU_PARENT_HW(pll1), APBS_PLL1_SWCR2, BIT(16), 13, 1);
CCU_FACTOR_GATE_DEFINE(pll1_d23_106p8, CCU_PARENT_HW(pll1), APBS_PLL1_SWCR2, BIT(20), 23, 1);
@@ -819,6 +717,7 @@ static struct clk_hw *k1_ccu_pll_hws[] = {
};

static const struct spacemit_ccu_data k1_ccu_pll_data = {
	/* The PLL CCU implements no resets */
	.hws		= k1_ccu_pll_hws,
	.num		= ARRAY_SIZE(k1_ccu_pll_hws),
};
@@ -860,6 +759,7 @@ static struct clk_hw *k1_ccu_mpmu_hws[] = {
};

static const struct spacemit_ccu_data k1_ccu_mpmu_data = {
	.reset_name	= "mpmu-reset",
	.hws		= k1_ccu_mpmu_hws,
	.num		= ARRAY_SIZE(k1_ccu_mpmu_hws),
};
@@ -968,6 +868,7 @@ static struct clk_hw *k1_ccu_apbc_hws[] = {
};

static const struct spacemit_ccu_data k1_ccu_apbc_data = {
	.reset_name	= "apbc-reset",
	.hws		= k1_ccu_apbc_hws,
	.num		= ARRAY_SIZE(k1_ccu_apbc_hws),
};
@@ -1038,10 +939,23 @@ static struct clk_hw *k1_ccu_apmu_hws[] = {
};

static const struct spacemit_ccu_data k1_ccu_apmu_data = {
	.reset_name	= "apmu-reset",
	.hws		= k1_ccu_apmu_hws,
	.num		= ARRAY_SIZE(k1_ccu_apmu_hws),
};

static const struct spacemit_ccu_data k1_ccu_rcpu_data = {
	.reset_name	= "rcpu-reset",
};

static const struct spacemit_ccu_data k1_ccu_rcpu2_data = {
	.reset_name	= "rcpu2-reset",
};

static const struct spacemit_ccu_data k1_ccu_apbc2_data = {
	.reset_name	= "apbc2-reset",
};

static int spacemit_ccu_register(struct device *dev,
				 struct regmap *regmap,
				 struct regmap *lock_regmap,
@@ -1050,6 +964,10 @@ static int spacemit_ccu_register(struct device *dev,
	struct clk_hw_onecell_data *clk_data;
	int i, ret;

	/* Nothing to do if the CCU does not implement any clocks */
	if (!data->hws)
		return 0;

	clk_data = devm_kzalloc(dev, struct_size(clk_data, hws, data->num),
				GFP_KERNEL);
	if (!clk_data)
@@ -1090,9 +1008,74 @@ static int spacemit_ccu_register(struct device *dev,
	return ret;
}

static void spacemit_cadev_release(struct device *dev)
{
	struct auxiliary_device *adev = to_auxiliary_dev(dev);

	ida_free(&auxiliary_ids, adev->id);
	kfree(to_spacemit_ccu_adev(adev));
}

static void spacemit_adev_unregister(void *data)
{
	struct auxiliary_device *adev = data;

	auxiliary_device_delete(adev);
	auxiliary_device_uninit(adev);
}

static int spacemit_ccu_reset_register(struct device *dev,
				       struct regmap *regmap,
				       const char *reset_name)
{
	struct spacemit_ccu_adev *cadev;
	struct auxiliary_device *adev;
	int ret;

	/* Nothing to do if the CCU does not implement a reset controller */
	if (!reset_name)
		return 0;

	cadev = kzalloc(sizeof(*cadev), GFP_KERNEL);
	if (!cadev)
		return -ENOMEM;

	cadev->regmap = regmap;

	adev = &cadev->adev;
	adev->name = reset_name;
	adev->dev.parent = dev;
	adev->dev.release = spacemit_cadev_release;
	adev->dev.of_node = dev->of_node;
	ret = ida_alloc(&auxiliary_ids, GFP_KERNEL);
	if (ret < 0)
		goto err_free_cadev;
	adev->id = ret;

	ret = auxiliary_device_init(adev);
	if (ret)
		goto err_free_aux_id;

	ret = auxiliary_device_add(adev);
	if (ret) {
		auxiliary_device_uninit(adev);
		return ret;
	}

	return devm_add_action_or_reset(dev, spacemit_adev_unregister, adev);

err_free_aux_id:
	ida_free(&auxiliary_ids, adev->id);
err_free_cadev:
	kfree(cadev);

	return ret;
}

static int k1_ccu_probe(struct platform_device *pdev)
{
	struct regmap *base_regmap, *lock_regmap = NULL;
	const struct spacemit_ccu_data *data;
	struct device *dev = &pdev->dev;
	int ret;

@@ -1121,11 +1104,16 @@ static int k1_ccu_probe(struct platform_device *pdev)
					     "failed to get lock regmap\n");
	}

	ret = spacemit_ccu_register(dev, base_regmap, lock_regmap,
				    of_device_get_match_data(dev));
	data = of_device_get_match_data(dev);

	ret = spacemit_ccu_register(dev, base_regmap, lock_regmap, data);
	if (ret)
		return dev_err_probe(dev, ret, "failed to register clocks\n");

	ret = spacemit_ccu_reset_register(dev, base_regmap, data->reset_name);
	if (ret)
		return dev_err_probe(dev, ret, "failed to register resets\n");

	return 0;
}

@@ -1146,6 +1134,18 @@ static const struct of_device_id of_k1_ccu_match[] = {
		.compatible	= "spacemit,k1-syscon-apmu",
		.data		= &k1_ccu_apmu_data,
	},
	{
		.compatible	= "spacemit,k1-syscon-rcpu",
		.data		= &k1_ccu_rcpu_data,
	},
	{
		.compatible	= "spacemit,k1-syscon-rcpu2",
		.data		= &k1_ccu_rcpu2_data,
	},
	{
		.compatible	= "spacemit,k1-syscon-apbc2",
		.data		= &k1_ccu_apbc2_data,
	},
	{ }
};
MODULE_DEVICE_TABLE(of, of_k1_ccu_match);
+8 −3
Original line number Diff line number Diff line
@@ -101,17 +101,22 @@ static struct ccu_mix _name = { \
	}									\
}

#define CCU_FACTOR_GATE_DEFINE(_name, _parent, _reg_ctrl, _mask_gate, _div,	\
			       _mul)						\
#define CCU_FACTOR_GATE_FLAGS_DEFINE(_name, _parent, _reg_ctrl, _mask_gate, _div,	\
			       _mul, _flags)					\
static struct ccu_mix _name = {							\
	.gate	= CCU_GATE_INIT(_mask_gate),					\
	.factor	= CCU_FACTOR_INIT(_div, _mul),					\
	.common = {								\
		.reg_ctrl	= _reg_ctrl,					\
		CCU_MIX_INITHW(_name, _parent, spacemit_ccu_factor_gate_ops, 0)	\
		CCU_MIX_INITHW(_name, _parent, spacemit_ccu_factor_gate_ops, _flags)	\
	}									\
}

#define CCU_FACTOR_GATE_DEFINE(_name, _parent, _reg_ctrl, _mask_gate, _div,	\
			       _mul)						\
	CCU_FACTOR_GATE_FLAGS_DEFINE(_name, _parent, _reg_ctrl, _mask_gate, _div,	\
			       _mul, 0)

#define CCU_MUX_GATE_DEFINE(_name, _parents, _reg_ctrl, _shift, _width,		\
			    _mask_gate, _flags)					\
static struct ccu_mix _name = {							\
+9 −0
Original line number Diff line number Diff line
@@ -270,6 +270,15 @@ config RESET_SOCFPGA
	  This enables the reset driver for the SoCFPGA ARMv7 platforms. This
	  driver gets initialized early during platform init calls.

config RESET_SPACEMIT
	tristate "SpacemiT reset driver"
	depends on ARCH_SPACEMIT || COMPILE_TEST
	select AUXILIARY_BUS
	default ARCH_SPACEMIT
	help
	  This enables the reset controller driver for SpacemiT SoCs,
	  including the K1.

config RESET_SUNPLUS
	bool "Sunplus SoCs Reset Driver" if COMPILE_TEST
	default ARCH_SUNPLUS
Loading