From 3ee5f8ab5e718afdde9984a089137360bdfc66eb Mon Sep 17 00:00:00 2001 From: Jernej Skrabec Date: Sat, 14 Sep 2019 15:51:00 +0200 Subject: clk: sunxi-ng: h6: Use sigma-delta modulation for audio PLL Audio devices needs exact clock rates in order to correctly reproduce the sound. Until now, only integer factors were used to configure H6 audio PLL which resulted in inexact rates. Fix that by adding support for fractional factors using sigma-delta modulation look-up table. It contains values for two most commonly used audio base frequencies. Signed-off-by: Jernej Skrabec Acked-by: Chen-Yu Tsai Signed-off-by: Maxime Ripard --- drivers/clk/sunxi-ng/ccu-sun50i-h6.c | 21 +++++++++++++++------ 1 file changed, 15 insertions(+), 6 deletions(-) (limited to 'drivers/clk') diff --git a/drivers/clk/sunxi-ng/ccu-sun50i-h6.c b/drivers/clk/sunxi-ng/ccu-sun50i-h6.c index d89353a3cdec..ed6338d74474 100644 --- a/drivers/clk/sunxi-ng/ccu-sun50i-h6.c +++ b/drivers/clk/sunxi-ng/ccu-sun50i-h6.c @@ -203,12 +203,21 @@ static struct ccu_nkmp pll_hsic_clk = { * hardcode it to match with the clock names. */ #define SUN50I_H6_PLL_AUDIO_REG 0x078 + +static struct ccu_sdm_setting pll_audio_sdm_table[] = { + { .rate = 541900800, .pattern = 0xc001288d, .m = 1, .n = 22 }, + { .rate = 589824000, .pattern = 0xc00126e9, .m = 1, .n = 24 }, +}; + static struct ccu_nm pll_audio_base_clk = { .enable = BIT(31), .lock = BIT(28), .n = _SUNXI_CCU_MULT_MIN(8, 8, 12), .m = _SUNXI_CCU_DIV(1, 1), /* input divider */ + .sdm = _SUNXI_CCU_SDM(pll_audio_sdm_table, + BIT(24), 0x178, BIT(31)), .common = { + .features = CCU_FEATURE_SIGMA_DELTA_MOD, .reg = 0x078, .hw.init = CLK_HW_INIT("pll-audio-base", "osc24M", &ccu_nm_ops, @@ -753,12 +762,12 @@ static const struct clk_hw *clk_parent_pll_audio[] = { }; /* - * The divider of pll-audio is fixed to 8 now, as pll-audio-4x has a - * fixed post-divider 2. + * The divider of pll-audio is fixed to 24 for now, so 24576000 and 22579200 + * rates can be set exactly in conjunction with sigma-delta modulation. */ static CLK_FIXED_FACTOR_HWS(pll_audio_clk, "pll-audio", clk_parent_pll_audio, - 8, 1, CLK_SET_RATE_PARENT); + 24, 1, CLK_SET_RATE_PARENT); static CLK_FIXED_FACTOR_HWS(pll_audio_2x_clk, "pll-audio-2x", clk_parent_pll_audio, 4, 1, CLK_SET_RATE_PARENT); @@ -1215,12 +1224,12 @@ static int sun50i_h6_ccu_probe(struct platform_device *pdev) } /* - * Force the post-divider of pll-audio to 8 and the output divider - * of it to 1, to make the clock name represents the real frequency. + * Force the post-divider of pll-audio to 12 and the output divider + * of it to 2, so 24576000 and 22579200 rates can be set exactly. */ val = readl(reg + SUN50I_H6_PLL_AUDIO_REG); val &= ~(GENMASK(21, 16) | BIT(0)); - writel(val | (7 << 16), reg + SUN50I_H6_PLL_AUDIO_REG); + writel(val | (11 << 16) | BIT(0), reg + SUN50I_H6_PLL_AUDIO_REG); /* * First clock parent (osc32K) is unusable for CEC. But since there -- cgit v1.2.3 From 834f65e18c82d10b781bee2ad207b590574eeaf9 Mon Sep 17 00:00:00 2001 From: Jernej Skrabec Date: Tue, 1 Oct 2019 22:06:56 +0200 Subject: clk: sunxi-ng: h6: Allow GPU to change parent rate GPU PLL was designed with dynamic frequency switching in mind so driver can adjust rate based on the GPU load. Allow GPU clock to change parent rate (GPU PLL is the only possible parent of GPU clock). Signed-off-by: Jernej Skrabec Signed-off-by: Maxime Ripard --- drivers/clk/sunxi-ng/ccu-sun50i-h6.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/clk') diff --git a/drivers/clk/sunxi-ng/ccu-sun50i-h6.c b/drivers/clk/sunxi-ng/ccu-sun50i-h6.c index ed6338d74474..f2497d0a4683 100644 --- a/drivers/clk/sunxi-ng/ccu-sun50i-h6.c +++ b/drivers/clk/sunxi-ng/ccu-sun50i-h6.c @@ -299,7 +299,7 @@ static SUNXI_CCU_M_WITH_MUX_GATE(gpu_clk, "gpu", gpu_parents, 0x670, 0, 3, /* M */ 24, 1, /* mux */ BIT(31), /* gate */ - 0); + CLK_SET_RATE_PARENT); static SUNXI_CCU_GATE(bus_gpu_clk, "bus-gpu", "psi-ahb1-ahb2", 0x67c, BIT(0), 0); -- cgit v1.2.3 From 581eb61a9465e1b9fc1df1a8912100702d7c2f31 Mon Sep 17 00:00:00 2001 From: Tero Kristo Date: Thu, 12 Sep 2019 16:26:04 +0300 Subject: clk: ti: clkctrl: fix setting up clkctrl clocks Apply the proper register function for clkctrl clocks, so they get registered under the clk_hw_omap list also. This allows checking their type runtime. Signed-off-by: Tero Kristo --- drivers/clk/ti/clkctrl.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/clk') diff --git a/drivers/clk/ti/clkctrl.c b/drivers/clk/ti/clkctrl.c index 975995eea15c..a914df2e9e1b 100644 --- a/drivers/clk/ti/clkctrl.c +++ b/drivers/clk/ti/clkctrl.c @@ -622,7 +622,7 @@ static void __init _ti_omap4_clkctrl_setup(struct device_node *node) init.ops = &omap4_clkctrl_clk_ops; hw->hw.init = &init; - clk = ti_clk_register(NULL, &hw->hw, init.name); + clk = ti_clk_register_omap_hw(NULL, &hw->hw, init.name); if (IS_ERR_OR_NULL(clk)) goto cleanup; -- cgit v1.2.3 From 22a6564f716b0746b5a05add3f9f37549f89244e Mon Sep 17 00:00:00 2001 From: Tero Kristo Date: Thu, 12 Sep 2019 16:26:05 +0300 Subject: clk: ti: clkctrl: convert to use bit helper macros instead of bitops This improves the readibility of the code slightly, and makes modifying the flags bit simpler. Signed-off-by: Tero Kristo --- drivers/clk/ti/clkctrl.c | 8 ++++---- include/linux/clk/ti.h | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) (limited to 'drivers/clk') diff --git a/drivers/clk/ti/clkctrl.c b/drivers/clk/ti/clkctrl.c index a914df2e9e1b..d904a9a7626a 100644 --- a/drivers/clk/ti/clkctrl.c +++ b/drivers/clk/ti/clkctrl.c @@ -24,7 +24,7 @@ #include #include "clock.h" -#define NO_IDLEST 0x1 +#define NO_IDLEST 0 #define OMAP4_MODULEMODE_MASK 0x3 @@ -158,7 +158,7 @@ static int _omap4_clkctrl_clk_enable(struct clk_hw *hw) ti_clk_ll_ops->clk_writel(val, &clk->enable_reg); - if (clk->flags & NO_IDLEST) + if (test_bit(NO_IDLEST, &clk->flags)) return 0; /* Wait until module is enabled */ @@ -187,7 +187,7 @@ static void _omap4_clkctrl_clk_disable(struct clk_hw *hw) ti_clk_ll_ops->clk_writel(val, &clk->enable_reg); - if (clk->flags & NO_IDLEST) + if (test_bit(NO_IDLEST, &clk->flags)) goto exit; /* Wait until module is disabled */ @@ -596,7 +596,7 @@ static void __init _ti_omap4_clkctrl_setup(struct device_node *node) if (reg_data->flags & CLKF_HW_SUP) hw->enable_bit = MODULEMODE_HWCTRL; if (reg_data->flags & CLKF_NO_IDLEST) - hw->flags |= NO_IDLEST; + set_bit(NO_IDLEST, &hw->flags); if (reg_data->clkdm_name) hw->clkdm_name = reg_data->clkdm_name; diff --git a/include/linux/clk/ti.h b/include/linux/clk/ti.h index 1e8ef96555ce..bb2c5af9082a 100644 --- a/include/linux/clk/ti.h +++ b/include/linux/clk/ti.h @@ -153,7 +153,7 @@ struct clk_hw_omap { u8 fixed_div; struct clk_omap_reg enable_reg; u8 enable_bit; - u8 flags; + unsigned long flags; struct clk_omap_reg clksel_reg; struct dpll_data *dpll_data; const char *clkdm_name; -- cgit v1.2.3 From 2209b72d41993c13de220b82c830b482925322b9 Mon Sep 17 00:00:00 2001 From: Tero Kristo Date: Thu, 12 Sep 2019 16:26:06 +0300 Subject: clk: ti: clkctrl: add new exported API for checking standby info Standby status is provided for certain clkctrl clocks to see if the given module has entered standby or not. This is mostly needed by remoteproc code to see if the remoteproc has entered standby and the clock can be turned off safely. Signed-off-by: Tero Kristo --- drivers/clk/ti/clkctrl.c | 33 +++++++++++++++++++++++++++++++++ include/linux/clk/ti.h | 1 + 2 files changed, 34 insertions(+) (limited to 'drivers/clk') diff --git a/drivers/clk/ti/clkctrl.c b/drivers/clk/ti/clkctrl.c index d904a9a7626a..d6cb41b55800 100644 --- a/drivers/clk/ti/clkctrl.c +++ b/drivers/clk/ti/clkctrl.c @@ -34,6 +34,9 @@ #define OMAP4_IDLEST_MASK (0x3 << 16) #define OMAP4_IDLEST_SHIFT 16 +#define OMAP4_STBYST_MASK BIT(18) +#define OMAP4_STBYST_SHIFT 18 + #define CLKCTRL_IDLEST_FUNCTIONAL 0x0 #define CLKCTRL_IDLEST_INTERFACE_IDLE 0x2 #define CLKCTRL_IDLEST_DISABLED 0x3 @@ -647,3 +650,33 @@ cleanup: } CLK_OF_DECLARE(ti_omap4_clkctrl_clock, "ti,clkctrl", _ti_omap4_clkctrl_setup); + +/** + * ti_clk_is_in_standby - Check if clkctrl clock is in standby or not + * @clk: clock to check standby status for + * + * Finds whether the provided clock is in standby mode or not. Returns + * true if the provided clock is a clkctrl type clock and it is in standby, + * false otherwise. + */ +bool ti_clk_is_in_standby(struct clk *clk) +{ + struct clk_hw *hw; + struct clk_hw_omap *hwclk; + u32 val; + + hw = __clk_get_hw(clk); + + if (!omap2_clk_is_hw_omap(hw)) + return false; + + hwclk = to_clk_hw_omap(hw); + + val = ti_clk_ll_ops->clk_readl(&hwclk->enable_reg); + + if (val & OMAP4_STBYST_MASK) + return true; + + return false; +} +EXPORT_SYMBOL_GPL(ti_clk_is_in_standby); diff --git a/include/linux/clk/ti.h b/include/linux/clk/ti.h index bb2c5af9082a..c62f6fa6763d 100644 --- a/include/linux/clk/ti.h +++ b/include/linux/clk/ti.h @@ -298,6 +298,7 @@ struct ti_clk_features { void ti_clk_setup_features(struct ti_clk_features *features); const struct ti_clk_features *ti_clk_get_features(void); +bool ti_clk_is_in_standby(struct clk *clk); int omap3_noncore_dpll_save_context(struct clk_hw *hw); void omap3_noncore_dpll_restore_context(struct clk_hw *hw); -- cgit v1.2.3 From 25999e6172a3ec6bb4b1f5a77471532c209937cc Mon Sep 17 00:00:00 2001 From: Tero Kristo Date: Thu, 12 Sep 2019 16:26:08 +0300 Subject: clk: ti: omap5: add IVA subsystem clkctrl data Add clkctrl data for the IVA subsystem (Image and Video Accelerator.) Signed-off-by: Tero Kristo --- drivers/clk/ti/clk-54xx.c | 7 +++++++ 1 file changed, 7 insertions(+) (limited to 'drivers/clk') diff --git a/drivers/clk/ti/clk-54xx.c b/drivers/clk/ti/clk-54xx.c index e675e27f1203..b89dc0d6f836 100644 --- a/drivers/clk/ti/clk-54xx.c +++ b/drivers/clk/ti/clk-54xx.c @@ -286,6 +286,12 @@ static const struct omap_clkctrl_reg_data omap5_l4per_clkctrl_regs[] __initconst { 0 }, }; +static const struct omap_clkctrl_reg_data omap5_iva_clkctrl_regs[] __initconst = { + { OMAP5_IVA_CLKCTRL, NULL, CLKF_HW_SUP, "dpll_iva_h12x2_ck" }, + { OMAP5_SL2IF_CLKCTRL, NULL, CLKF_HW_SUP, "dpll_iva_h12x2_ck" }, + { 0 }, +}; + static const char * const omap5_dss_dss_clk_parents[] __initconst = { "dpll_per_h12x2_ck", NULL, @@ -502,6 +508,7 @@ const struct omap_clkctrl_data omap5_clkctrl_data[] __initconst = { { 0x4a008d20, omap5_l4cfg_clkctrl_regs }, { 0x4a008e20, omap5_l3instr_clkctrl_regs }, { 0x4a009020, omap5_l4per_clkctrl_regs }, + { 0x4a009220, omap5_iva_clkctrl_regs }, { 0x4a009420, omap5_dss_clkctrl_regs }, { 0x4a009520, omap5_gpu_clkctrl_regs }, { 0x4a009620, omap5_l3init_clkctrl_regs }, -- cgit v1.2.3 From 9063ea469c406fae7c60d2ea4d80f1101dd401eb Mon Sep 17 00:00:00 2001 From: Tero Kristo Date: Thu, 12 Sep 2019 16:26:09 +0300 Subject: clk: ti: dra7xx: Drop idlest polling from IPU & DSP clkctrl clocks The IPU and DSP remote processor cores and their corresponding MMUs on DRA7 SoCs have hardreset lines associated with them and are controlled by a PRCM reset line each. Any clkctrl enable/disable operations cannot be checked for module enabled/disabled status independent of the reset operation, and this causes some unwanted timeouts in the kernel and unbalanced states for these clocks. These details should be handled by the driver integration code itself. Add the CLKF_NO_IDLEST flag to both the IPU and DSP clkctrl clocks so that these module status checks are skipped. Signed-off-by: Tero Kristo --- drivers/clk/ti/clk-7xx.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'drivers/clk') diff --git a/drivers/clk/ti/clk-7xx.c b/drivers/clk/ti/clk-7xx.c index b57fe09b428b..94e69cdc2bd2 100644 --- a/drivers/clk/ti/clk-7xx.c +++ b/drivers/clk/ti/clk-7xx.c @@ -25,7 +25,7 @@ static const struct omap_clkctrl_reg_data dra7_mpu_clkctrl_regs[] __initconst = }; static const struct omap_clkctrl_reg_data dra7_dsp1_clkctrl_regs[] __initconst = { - { DRA7_DSP1_MMU0_DSP1_CLKCTRL, NULL, CLKF_HW_SUP, "dpll_dsp_m2_ck" }, + { DRA7_DSP1_MMU0_DSP1_CLKCTRL, NULL, CLKF_HW_SUP | CLKF_NO_IDLEST, "dpll_dsp_m2_ck" }, { 0 }, }; @@ -41,7 +41,7 @@ static const struct omap_clkctrl_bit_data dra7_mmu_ipu1_bit_data[] __initconst = }; static const struct omap_clkctrl_reg_data dra7_ipu1_clkctrl_regs[] __initconst = { - { DRA7_IPU1_MMU_IPU1_CLKCTRL, dra7_mmu_ipu1_bit_data, CLKF_HW_SUP, "ipu1-clkctrl:0000:24" }, + { DRA7_IPU1_MMU_IPU1_CLKCTRL, dra7_mmu_ipu1_bit_data, CLKF_HW_SUP | CLKF_NO_IDLEST, "ipu1-clkctrl:0000:24" }, { 0 }, }; @@ -137,7 +137,7 @@ static const struct omap_clkctrl_reg_data dra7_ipu_clkctrl_regs[] __initconst = }; static const struct omap_clkctrl_reg_data dra7_dsp2_clkctrl_regs[] __initconst = { - { DRA7_DSP2_MMU0_DSP2_CLKCTRL, NULL, CLKF_HW_SUP, "dpll_dsp_m2_ck" }, + { DRA7_DSP2_MMU0_DSP2_CLKCTRL, NULL, CLKF_HW_SUP | CLKF_NO_IDLEST, "dpll_dsp_m2_ck" }, { 0 }, }; @@ -164,7 +164,7 @@ static const struct omap_clkctrl_reg_data dra7_l3main1_clkctrl_regs[] __initcons }; static const struct omap_clkctrl_reg_data dra7_ipu2_clkctrl_regs[] __initconst = { - { DRA7_IPU2_MMU_IPU2_CLKCTRL, NULL, CLKF_HW_SUP, "dpll_core_h22x2_ck" }, + { DRA7_IPU2_MMU_IPU2_CLKCTRL, NULL, CLKF_HW_SUP | CLKF_NO_IDLEST, "dpll_core_h22x2_ck" }, { 0 }, }; -- cgit v1.2.3 From e1799d451a872cc9b0e0a96d820fc599e2b30a44 Mon Sep 17 00:00:00 2001 From: Suman Anna Date: Thu, 12 Sep 2019 16:26:10 +0300 Subject: clk: ti: omap4: Drop idlest polling from IPU & DSP clkctrl clocks The IPU and DSP remote processor cores and their corresponding MMUs on OMAP4 SoCs have hardreset lines associated with them and are controlled by a PRCM reset line each. Any clkctrl enable/disable operations cannot be checked for module enabled/disabled status independent of the reset operation, and this causes some unwanted timeouts in the kernel and unbalanced states for these clocks. These details should be handled by the driver integration code itself. Add the CLKF_NO_IDLEST flag to both the IPU and DSP clkctrl clocks so that these module status checks are skipped. Signed-off-by: Suman Anna Signed-off-by: Tero Kristo --- drivers/clk/ti/clk-44xx.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers/clk') diff --git a/drivers/clk/ti/clk-44xx.c b/drivers/clk/ti/clk-44xx.c index b10ed0429091..2b4dab632318 100644 --- a/drivers/clk/ti/clk-44xx.c +++ b/drivers/clk/ti/clk-44xx.c @@ -37,7 +37,7 @@ static const struct omap_clkctrl_reg_data omap4_mpuss_clkctrl_regs[] __initconst }; static const struct omap_clkctrl_reg_data omap4_tesla_clkctrl_regs[] __initconst = { - { OMAP4_DSP_CLKCTRL, NULL, CLKF_HW_SUP, "dpll_iva_m4x2_ck" }, + { OMAP4_DSP_CLKCTRL, NULL, CLKF_HW_SUP | CLKF_NO_IDLEST, "dpll_iva_m4x2_ck" }, { 0 }, }; @@ -219,7 +219,7 @@ static const struct omap_clkctrl_reg_data omap4_l3_2_clkctrl_regs[] __initconst }; static const struct omap_clkctrl_reg_data omap4_ducati_clkctrl_regs[] __initconst = { - { OMAP4_IPU_CLKCTRL, NULL, CLKF_HW_SUP, "ducati_clk_mux_ck" }, + { OMAP4_IPU_CLKCTRL, NULL, CLKF_HW_SUP | CLKF_NO_IDLEST, "ducati_clk_mux_ck" }, { 0 }, }; -- cgit v1.2.3 From 95a62bf2dbfb8c1fa44f92e2d0116628695fa9bd Mon Sep 17 00:00:00 2001 From: Suman Anna Date: Thu, 12 Sep 2019 16:26:11 +0300 Subject: clk: ti: omap5: Drop idlest polling from IPU & DSP clkctrl clocks The IPU and DSP remote processor cores and their corresponding MMUs on OMAP5 SoCs have hardreset lines associated with them and are controlled by a PRCM reset line each. Any clkctrl enable/disable operations cannot be checked for module enabled/disabled status independent of the reset operation, and this causes some unwanted timeouts in the kernel and unbalanced states for these clocks. These details should be handled by the driver integration code itself. Add the CLKF_NO_IDLEST flag to both the IPU and DSP clkctrl clocks so that these module status checks are skipped. Signed-off-by: Suman Anna Signed-off-by: Tero Kristo --- drivers/clk/ti/clk-54xx.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers/clk') diff --git a/drivers/clk/ti/clk-54xx.c b/drivers/clk/ti/clk-54xx.c index b89dc0d6f836..c9608e5d993a 100644 --- a/drivers/clk/ti/clk-54xx.c +++ b/drivers/clk/ti/clk-54xx.c @@ -31,7 +31,7 @@ static const struct omap_clkctrl_reg_data omap5_mpu_clkctrl_regs[] __initconst = }; static const struct omap_clkctrl_reg_data omap5_dsp_clkctrl_regs[] __initconst = { - { OMAP5_MMU_DSP_CLKCTRL, NULL, CLKF_HW_SUP, "dpll_iva_h11x2_ck" }, + { OMAP5_MMU_DSP_CLKCTRL, NULL, CLKF_HW_SUP | CLKF_NO_IDLEST, "dpll_iva_h11x2_ck" }, { 0 }, }; @@ -145,7 +145,7 @@ static const struct omap_clkctrl_reg_data omap5_l3main2_clkctrl_regs[] __initcon }; static const struct omap_clkctrl_reg_data omap5_ipu_clkctrl_regs[] __initconst = { - { OMAP5_MMU_IPU_CLKCTRL, NULL, CLKF_HW_SUP, "dpll_core_h22x2_ck" }, + { OMAP5_MMU_IPU_CLKCTRL, NULL, CLKF_HW_SUP | CLKF_NO_IDLEST, "dpll_core_h22x2_ck" }, { 0 }, }; -- cgit v1.2.3 From caf00b53678f172a80217d297e83346f337b427c Mon Sep 17 00:00:00 2001 From: Tero Kristo Date: Thu, 12 Sep 2019 16:26:12 +0300 Subject: clk: ti: am43xx: drop idlest polling from pruss clkctrl clock The PRUSS modules on AM43xx SoCs have a hardreset line and are controlled by a PRCM reset line. Any clkctrl enable/disable operations cannot be checked for module enabled/disabled status independent of the reset operation, and this causes some unwanted timeouts in the kernel and unbalanced states for the PRUSS clocks. These details should be handled by the driver integration code itself. Add the CLKF_NO_IDLEST flag to the PRUSS clkctrl clock so that these module status checks are skipped. Signed-off-by: Tero Kristo --- drivers/clk/ti/clk-43xx.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/clk') diff --git a/drivers/clk/ti/clk-43xx.c b/drivers/clk/ti/clk-43xx.c index 2782d91838ac..7ec8fe6aa7c1 100644 --- a/drivers/clk/ti/clk-43xx.c +++ b/drivers/clk/ti/clk-43xx.c @@ -126,7 +126,7 @@ static const struct omap_clkctrl_reg_data am4_l3s_clkctrl_regs[] __initconst = { }; static const struct omap_clkctrl_reg_data am4_pruss_ocp_clkctrl_regs[] __initconst = { - { AM4_PRUSS_OCP_PRUSS_CLKCTRL, NULL, CLKF_SW_SUP, "pruss_ocp_gclk" }, + { AM4_PRUSS_OCP_PRUSS_CLKCTRL, NULL, CLKF_SW_SUP | CLKF_NO_IDLEST, "pruss_ocp_gclk" }, { 0 }, }; -- cgit v1.2.3 From 4d0030bdb47b703bebe4796d5c16beb776c6950f Mon Sep 17 00:00:00 2001 From: Tero Kristo Date: Thu, 12 Sep 2019 16:26:13 +0300 Subject: clk: ti: am33xx: drop idlest polling from pruss clkctrl clock The PRUSS module on AM33xx SoCs has a hardreset line and is controlled by a PRCM reset line. Any clkctrl enable/disable operations cannot be checked for module enabled/disabled status independent of the reset operation, and this causes some unwanted timeouts in the kernel and unbalanced states for the PRUSS clocks. These details should be handled by the driver integration code itself. Add the CLKF_NO_IDLEST flag to the PRUSS clkctrl clock so that these module status checks are skipped. Signed-off-by: Tero Kristo --- drivers/clk/ti/clk-33xx.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/clk') diff --git a/drivers/clk/ti/clk-33xx.c b/drivers/clk/ti/clk-33xx.c index a360d3109555..935efb66b389 100644 --- a/drivers/clk/ti/clk-33xx.c +++ b/drivers/clk/ti/clk-33xx.c @@ -107,7 +107,7 @@ static const struct omap_clkctrl_reg_data am3_l4hs_clkctrl_regs[] __initconst = }; static const struct omap_clkctrl_reg_data am3_pruss_ocp_clkctrl_regs[] __initconst = { - { AM3_PRUSS_OCP_PRUSS_CLKCTRL, NULL, CLKF_SW_SUP, "pruss_ocp_gclk" }, + { AM3_PRUSS_OCP_PRUSS_CLKCTRL, NULL, CLKF_SW_SUP | CLKF_NO_IDLEST, "pruss_ocp_gclk" }, { 0 }, }; -- cgit v1.2.3 From 194071817898897c65ffb5ae59d6d686ca13452c Mon Sep 17 00:00:00 2001 From: Tero Kristo Date: Mon, 7 Oct 2019 15:26:03 +0300 Subject: clk: ti: am33xx: drop idlest polling from gfx clock Due to the way ti sysc and hardreset line control is now implemented, it is not possible to poll the clock status for gfx clock independent of hardreset line control. Thus, add a flag to prevent handling this status bit from clock driver. Correct sequencing of events is guaranteed by ti-sysc bus driver. Reported-by: Tony Lindgren Signed-off-by: Tero Kristo --- drivers/clk/ti/clk-33xx.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/clk') diff --git a/drivers/clk/ti/clk-33xx.c b/drivers/clk/ti/clk-33xx.c index 935efb66b389..e001b9bcb6bf 100644 --- a/drivers/clk/ti/clk-33xx.c +++ b/drivers/clk/ti/clk-33xx.c @@ -217,7 +217,7 @@ static const struct omap_clkctrl_reg_data am3_l4_rtc_clkctrl_regs[] __initconst }; static const struct omap_clkctrl_reg_data am3_gfx_l3_clkctrl_regs[] __initconst = { - { AM3_GFX_L3_GFX_CLKCTRL, NULL, CLKF_SW_SUP, "gfx_fck_div_ck" }, + { AM3_GFX_L3_GFX_CLKCTRL, NULL, CLKF_SW_SUP | CLKF_NO_IDLEST, "gfx_fck_div_ck" }, { 0 }, }; -- cgit v1.2.3 From ece3e465b80a05c994783c7161e3d49035064f71 Mon Sep 17 00:00:00 2001 From: Tero Kristo Date: Mon, 7 Oct 2019 15:26:04 +0300 Subject: clk: ti: am43xx: drop idlest polling from gfx clock Due to the way ti sysc and hardreset line control is now implemented, it is not possible to poll the clock status for gfx clock independent of hardreset line control. Thus, add a flag to prevent handling this status bit from clock driver. Correct sequencing of events is guaranteed by ti-sysc bus driver. Signed-off-by: Tero Kristo --- drivers/clk/ti/clk-43xx.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/clk') diff --git a/drivers/clk/ti/clk-43xx.c b/drivers/clk/ti/clk-43xx.c index 7ec8fe6aa7c1..af3e7805769e 100644 --- a/drivers/clk/ti/clk-43xx.c +++ b/drivers/clk/ti/clk-43xx.c @@ -73,7 +73,7 @@ static const struct omap_clkctrl_reg_data am4_mpu_clkctrl_regs[] __initconst = { }; static const struct omap_clkctrl_reg_data am4_gfx_l3_clkctrl_regs[] __initconst = { - { AM4_GFX_L3_GFX_CLKCTRL, NULL, CLKF_SW_SUP, "gfx_fck_div_ck" }, + { AM4_GFX_L3_GFX_CLKCTRL, NULL, CLKF_SW_SUP | CLKF_NO_IDLEST, "gfx_fck_div_ck" }, { 0 }, }; -- cgit v1.2.3 From fbbc18591585bf74031dd6474b2937f87063e959 Mon Sep 17 00:00:00 2001 From: Tero Kristo Date: Wed, 2 Oct 2019 15:06:08 +0300 Subject: clk: ti: divider: cleanup _register_divider and ti_clk_get_div_table Cleanup couple of TI divider clock internal APIs. These currently pass huge amount of parameters, which makes it difficult to track what is going on. Abstract most of these under struct clk_omap_div which gets passed over the APIs. Signed-off-by: Tero Kristo Tested-by: Adam Ford --- drivers/clk/ti/divider.c | 113 +++++++++++++++++------------------------------ 1 file changed, 41 insertions(+), 72 deletions(-) (limited to 'drivers/clk') diff --git a/drivers/clk/ti/divider.c b/drivers/clk/ti/divider.c index 6cb863c13648..1b181f89ddc6 100644 --- a/drivers/clk/ti/divider.c +++ b/drivers/clk/ti/divider.c @@ -310,47 +310,26 @@ const struct clk_ops ti_clk_divider_ops = { .restore_context = clk_divider_restore_context, }; -static struct clk *_register_divider(struct device *dev, const char *name, - const char *parent_name, - unsigned long flags, - struct clk_omap_reg *reg, - u8 shift, u8 width, s8 latch, - u8 clk_divider_flags, - const struct clk_div_table *table) +static struct clk *_register_divider(struct device_node *node, + u32 flags, + struct clk_omap_divider *div) { - struct clk_omap_divider *div; struct clk *clk; struct clk_init_data init; + const char *parent_name; - if (clk_divider_flags & CLK_DIVIDER_HIWORD_MASK) { - if (width + shift > 16) { - pr_warn("divider value exceeds LOWORD field\n"); - return ERR_PTR(-EINVAL); - } - } - - /* allocate the divider */ - div = kzalloc(sizeof(*div), GFP_KERNEL); - if (!div) - return ERR_PTR(-ENOMEM); + parent_name = of_clk_get_parent_name(node, 0); - init.name = name; + init.name = node->name; init.ops = &ti_clk_divider_ops; init.flags = flags; init.parent_names = (parent_name ? &parent_name : NULL); init.num_parents = (parent_name ? 1 : 0); - /* struct clk_divider assignments */ - memcpy(&div->reg, reg, sizeof(*reg)); - div->shift = shift; - div->width = width; - div->latch = latch; - div->flags = clk_divider_flags; div->hw.init = &init; - div->table = table; /* register the clock */ - clk = ti_clk_register(dev, &div->hw, name); + clk = ti_clk_register(NULL, &div->hw, node->name); if (IS_ERR(clk)) kfree(div); @@ -425,8 +404,8 @@ int ti_clk_parse_divider_data(int *div_table, int num_dividers, int max_div, return 0; } -static struct clk_div_table * -__init ti_clk_get_div_table(struct device_node *node) +static int __init ti_clk_get_div_table(struct device_node *node, + struct clk_omap_divider *div) { struct clk_div_table *table; const __be32 *divspec; @@ -438,7 +417,7 @@ __init ti_clk_get_div_table(struct device_node *node) divspec = of_get_property(node, "ti,dividers", &num_div); if (!divspec) - return NULL; + return 0; num_div /= 4; @@ -453,13 +432,12 @@ __init ti_clk_get_div_table(struct device_node *node) if (!valid_div) { pr_err("no valid dividers for %pOFn table\n", node); - return ERR_PTR(-EINVAL); + return -EINVAL; } table = kcalloc(valid_div + 1, sizeof(*table), GFP_KERNEL); - if (!table) - return ERR_PTR(-ENOMEM); + return -ENOMEM; valid_div = 0; @@ -472,7 +450,9 @@ __init ti_clk_get_div_table(struct device_node *node) } } - return table; + div->table = table; + + return 0; } static int _get_divider_width(struct device_node *node, @@ -520,46 +500,43 @@ static int _get_divider_width(struct device_node *node, } static int __init ti_clk_divider_populate(struct device_node *node, - struct clk_omap_reg *reg, const struct clk_div_table **table, - u32 *flags, u8 *div_flags, u8 *width, u8 *shift, s8 *latch) + struct clk_omap_divider *div, + u32 *flags) { u32 val; int ret; - ret = ti_clk_get_reg_addr(node, 0, reg); + ret = ti_clk_get_reg_addr(node, 0, &div->reg); if (ret) return ret; if (!of_property_read_u32(node, "ti,bit-shift", &val)) - *shift = val; + div->shift = val; else - *shift = 0; + div->shift = 0; - if (latch) { - if (!of_property_read_u32(node, "ti,latch-bit", &val)) - *latch = val; - else - *latch = -EINVAL; - } + if (!of_property_read_u32(node, "ti,latch-bit", &val)) + div->latch = val; + else + div->latch = -EINVAL; *flags = 0; - *div_flags = 0; + div->flags = 0; if (of_property_read_bool(node, "ti,index-starts-at-one")) - *div_flags |= CLK_DIVIDER_ONE_BASED; + div->flags |= CLK_DIVIDER_ONE_BASED; if (of_property_read_bool(node, "ti,index-power-of-two")) - *div_flags |= CLK_DIVIDER_POWER_OF_TWO; + div->flags |= CLK_DIVIDER_POWER_OF_TWO; if (of_property_read_bool(node, "ti,set-rate-parent")) *flags |= CLK_SET_RATE_PARENT; - *table = ti_clk_get_div_table(node); - - if (IS_ERR(*table)) - return PTR_ERR(*table); + ret = ti_clk_get_div_table(node, div); + if (ret) + return ret; - *width = _get_divider_width(node, *table, *div_flags); + div->width = _get_divider_width(node, div->table, div->flags); return 0; } @@ -573,24 +550,17 @@ static int __init ti_clk_divider_populate(struct device_node *node, static void __init of_ti_divider_clk_setup(struct device_node *node) { struct clk *clk; - const char *parent_name; - struct clk_omap_reg reg; - u8 clk_divider_flags = 0; - u8 width = 0; - u8 shift = 0; - s8 latch = -EINVAL; - const struct clk_div_table *table = NULL; u32 flags = 0; + struct clk_omap_divider *div; - parent_name = of_clk_get_parent_name(node, 0); + div = kzalloc(sizeof(*div), GFP_KERNEL); + if (!div) + return; - if (ti_clk_divider_populate(node, ®, &table, &flags, - &clk_divider_flags, &width, &shift, &latch)) + if (ti_clk_divider_populate(node, div, &flags)) goto cleanup; - clk = _register_divider(NULL, node->name, parent_name, flags, ®, - shift, width, latch, clk_divider_flags, table); - + clk = _register_divider(node, flags, div); if (!IS_ERR(clk)) { of_clk_add_provider(node, of_clk_src_simple_get, clk); of_ti_clk_autoidle_setup(node); @@ -598,22 +568,21 @@ static void __init of_ti_divider_clk_setup(struct device_node *node) } cleanup: - kfree(table); + kfree(div->table); + kfree(div); } CLK_OF_DECLARE(divider_clk, "ti,divider-clock", of_ti_divider_clk_setup); static void __init of_ti_composite_divider_clk_setup(struct device_node *node) { struct clk_omap_divider *div; - u32 val; + u32 tmp; div = kzalloc(sizeof(*div), GFP_KERNEL); if (!div) return; - if (ti_clk_divider_populate(node, &div->reg, &div->table, &val, - &div->flags, &div->width, &div->shift, - NULL) < 0) + if (ti_clk_divider_populate(node, div, &tmp)) goto cleanup; if (!ti_clk_add_component(node, &div->hw, CLK_COMPONENT_TYPE_DIVIDER)) -- cgit v1.2.3 From a229965cfeab8ea8bb79086d6f59ac9a57de66fe Mon Sep 17 00:00:00 2001 From: Tero Kristo Date: Wed, 2 Oct 2019 15:06:09 +0300 Subject: clk: ti: divider: cleanup ti_clk_parse_divider_data API Cleanup the ti_clk_parse_divider_data to pass the divider data struct directly instead of individual values of it. This makes it easier to modify the implementation later on. Signed-off-by: Tero Kristo Tested-by: Adam Ford --- drivers/clk/ti/clkctrl.c | 2 +- drivers/clk/ti/clock.h | 3 +-- drivers/clk/ti/divider.c | 18 +++++++----------- 3 files changed, 9 insertions(+), 14 deletions(-) (limited to 'drivers/clk') diff --git a/drivers/clk/ti/clkctrl.c b/drivers/clk/ti/clkctrl.c index d6cb41b55800..b8ae8c44d761 100644 --- a/drivers/clk/ti/clkctrl.c +++ b/drivers/clk/ti/clkctrl.c @@ -383,7 +383,7 @@ _ti_clkctrl_setup_div(struct omap_clkctrl_provider *provider, if (ti_clk_parse_divider_data((int *)div_data->dividers, 0, div_data->max_div, div_flags, - &div->width, &div->table)) { + div)) { pr_err("%s: Data parsing for %pOF:%04x:%d failed\n", __func__, node, offset, data->bit); kfree(div); diff --git a/drivers/clk/ti/clock.h b/drivers/clk/ti/clock.h index e4b8392ff63c..f6b6876dfdee 100644 --- a/drivers/clk/ti/clock.h +++ b/drivers/clk/ti/clock.h @@ -220,8 +220,7 @@ void ti_clk_latch(struct clk_omap_reg *reg, s8 shift); struct clk_hw *ti_clk_build_component_mux(struct ti_clk_mux *setup); int ti_clk_parse_divider_data(int *div_table, int num_dividers, int max_div, - u8 flags, u8 *width, - const struct clk_div_table **table); + u8 flags, struct clk_omap_divider *div); int ti_clk_get_reg_addr(struct device_node *node, int index, struct clk_omap_reg *reg); diff --git a/drivers/clk/ti/divider.c b/drivers/clk/ti/divider.c index 1b181f89ddc6..2c53096b7229 100644 --- a/drivers/clk/ti/divider.c +++ b/drivers/clk/ti/divider.c @@ -338,8 +338,7 @@ static struct clk *_register_divider(struct device_node *node, } int ti_clk_parse_divider_data(int *div_table, int num_dividers, int max_div, - u8 flags, u8 *width, - const struct clk_div_table **table) + u8 flags, struct clk_omap_divider *divider) { int valid_div = 0; u32 val; @@ -363,8 +362,7 @@ int ti_clk_parse_divider_data(int *div_table, int num_dividers, int max_div, val++; } - *width = fls(val); - *table = NULL; + divider->width = fls(val); return 0; } @@ -382,24 +380,22 @@ int ti_clk_parse_divider_data(int *div_table, int num_dividers, int max_div, num_dividers = i; tmp = kcalloc(valid_div + 1, sizeof(*tmp), GFP_KERNEL); - if (!tmp) { - *table = ERR_PTR(-ENOMEM); + if (!tmp) return -ENOMEM; - } valid_div = 0; - *width = 0; + divider->width = 0; for (i = 0; i < num_dividers; i++) if (div_table[i] > 0) { tmp[valid_div].div = div_table[i]; tmp[valid_div].val = i; valid_div++; - *width = i; + divider->width = i; } - *width = fls(*width); - *table = tmp; + divider->width = fls(divider->width); + divider->table = tmp; return 0; } -- cgit v1.2.3 From 8ffea6eef4ace7e207fc2fe852d2019d93f51d1a Mon Sep 17 00:00:00 2001 From: Tero Kristo Date: Wed, 2 Oct 2019 15:06:10 +0300 Subject: clk: ti: divider: convert to use min,max,mask instead of width The existing width field used to check divider validity does not provide enough protection against bad values. For example, if max divider value is 4, the smallest all-1 bitmask that can hold this value is 7, which allows values higher than 4 to be used. This typically causes unpredictable results with hardware. So far this issue hasn't been noticed as most of the dividers actually have maximum values which fit the whole bitfield, but there are certain clocks for which this is a problem, like dpll4_m4 divider on omap3 devices. Thus, convert the whole validity logic to use min,max and mask values for determining if a specific divider is valid or not. This prevents the odd cases where bad value would otherwise be written to a divider config register. Signed-off-by: Tero Kristo Tested-by: Adam Ford --- drivers/clk/ti/clock.h | 4 +- drivers/clk/ti/divider.c | 161 +++++++++++++++++++++-------------------------- 2 files changed, 74 insertions(+), 91 deletions(-) (limited to 'drivers/clk') diff --git a/drivers/clk/ti/clock.h b/drivers/clk/ti/clock.h index f6b6876dfdee..e6995c04001e 100644 --- a/drivers/clk/ti/clock.h +++ b/drivers/clk/ti/clock.h @@ -20,9 +20,11 @@ struct clk_omap_divider { struct clk_hw hw; struct clk_omap_reg reg; u8 shift; - u8 width; u8 flags; s8 latch; + u16 min; + u16 max; + u16 mask; const struct clk_div_table *table; u32 context; }; diff --git a/drivers/clk/ti/divider.c b/drivers/clk/ti/divider.c index 2c53096b7229..28080df92f72 100644 --- a/drivers/clk/ti/divider.c +++ b/drivers/clk/ti/divider.c @@ -26,30 +26,6 @@ #undef pr_fmt #define pr_fmt(fmt) "%s: " fmt, __func__ -#define div_mask(d) ((1 << ((d)->width)) - 1) - -static unsigned int _get_table_maxdiv(const struct clk_div_table *table) -{ - unsigned int maxdiv = 0; - const struct clk_div_table *clkt; - - for (clkt = table; clkt->div; clkt++) - if (clkt->div > maxdiv) - maxdiv = clkt->div; - return maxdiv; -} - -static unsigned int _get_maxdiv(struct clk_omap_divider *divider) -{ - if (divider->flags & CLK_DIVIDER_ONE_BASED) - return div_mask(divider); - if (divider->flags & CLK_DIVIDER_POWER_OF_TWO) - return 1 << div_mask(divider); - if (divider->table) - return _get_table_maxdiv(divider->table); - return div_mask(divider) + 1; -} - static unsigned int _get_table_div(const struct clk_div_table *table, unsigned int val) { @@ -61,6 +37,34 @@ static unsigned int _get_table_div(const struct clk_div_table *table, return 0; } +static void _setup_mask(struct clk_omap_divider *divider) +{ + u16 mask; + u32 max_val; + const struct clk_div_table *clkt; + + if (divider->table) { + max_val = 0; + + for (clkt = divider->table; clkt->div; clkt++) + if (clkt->val > max_val) + max_val = clkt->val; + } else { + max_val = divider->max; + + if (!(divider->flags & CLK_DIVIDER_ONE_BASED) && + !(divider->flags & CLK_DIVIDER_POWER_OF_TWO)) + max_val--; + } + + if (divider->flags & CLK_DIVIDER_POWER_OF_TWO) + mask = fls(max_val) - 1; + else + mask = max_val; + + divider->mask = (1 << fls(mask)) - 1; +} + static unsigned int _get_div(struct clk_omap_divider *divider, unsigned int val) { if (divider->flags & CLK_DIVIDER_ONE_BASED) @@ -101,7 +105,7 @@ static unsigned long ti_clk_divider_recalc_rate(struct clk_hw *hw, unsigned int div, val; val = ti_clk_ll_ops->clk_readl(÷r->reg) >> divider->shift; - val &= div_mask(divider); + val &= divider->mask; div = _get_div(divider, val); if (!div) { @@ -180,7 +184,7 @@ static int ti_clk_divider_bestdiv(struct clk_hw *hw, unsigned long rate, if (!rate) rate = 1; - maxdiv = _get_maxdiv(divider); + maxdiv = divider->max; if (!(clk_hw_get_flags(hw) & CLK_SET_RATE_PARENT)) { parent_rate = *best_parent_rate; @@ -219,7 +223,7 @@ static int ti_clk_divider_bestdiv(struct clk_hw *hw, unsigned long rate, } if (!bestdiv) { - bestdiv = _get_maxdiv(divider); + bestdiv = divider->max; *best_parent_rate = clk_hw_round_rate(clk_hw_get_parent(hw), 1); } @@ -249,17 +253,16 @@ static int ti_clk_divider_set_rate(struct clk_hw *hw, unsigned long rate, divider = to_clk_omap_divider(hw); div = DIV_ROUND_UP(parent_rate, rate); - value = _get_val(divider, div); - if (value > div_mask(divider)) - value = div_mask(divider); + if (div > divider->max) + div = divider->max; + if (div < divider->min) + div = divider->min; - if (divider->flags & CLK_DIVIDER_HIWORD_MASK) { - val = div_mask(divider) << (divider->shift + 16); - } else { - val = ti_clk_ll_ops->clk_readl(÷r->reg); - val &= ~(div_mask(divider) << divider->shift); - } + value = _get_val(divider, div); + + val = ti_clk_ll_ops->clk_readl(÷r->reg); + val &= ~(divider->mask << divider->shift); val |= value << divider->shift; ti_clk_ll_ops->clk_writel(val, ÷r->reg); @@ -280,7 +283,7 @@ static int clk_divider_save_context(struct clk_hw *hw) u32 val; val = ti_clk_ll_ops->clk_readl(÷r->reg) >> divider->shift; - divider->context = val & div_mask(divider); + divider->context = val & divider->mask; return 0; } @@ -297,7 +300,7 @@ static void clk_divider_restore_context(struct clk_hw *hw) u32 val; val = ti_clk_ll_ops->clk_readl(÷r->reg); - val &= ~(div_mask(divider) << divider->shift); + val &= ~(divider->mask << divider->shift); val |= divider->context << divider->shift; ti_clk_ll_ops->clk_writel(val, ÷r->reg); } @@ -341,29 +344,14 @@ int ti_clk_parse_divider_data(int *div_table, int num_dividers, int max_div, u8 flags, struct clk_omap_divider *divider) { int valid_div = 0; - u32 val; - int div; int i; struct clk_div_table *tmp; + u16 min_div = 0; if (!div_table) { - if (flags & CLKF_INDEX_STARTS_AT_ONE) - val = 1; - else - val = 0; - - div = 1; - - while (div < max_div) { - if (flags & CLKF_INDEX_POWER_OF_TWO) - div <<= 1; - else - div++; - val++; - } - - divider->width = fls(val); - + divider->min = 1; + divider->max = max_div; + _setup_mask(divider); return 0; } @@ -384,18 +372,22 @@ int ti_clk_parse_divider_data(int *div_table, int num_dividers, int max_div, return -ENOMEM; valid_div = 0; - divider->width = 0; for (i = 0; i < num_dividers; i++) if (div_table[i] > 0) { tmp[valid_div].div = div_table[i]; tmp[valid_div].val = i; valid_div++; - divider->width = i; + if (div_table[i] > max_div) + max_div = div_table[i]; + if (!min_div || div_table[i] < min_div) + min_div = div_table[i]; } - divider->width = fls(divider->width); + divider->min = min_div; + divider->max = max_div; divider->table = tmp; + _setup_mask(divider); return 0; } @@ -451,16 +443,15 @@ static int __init ti_clk_get_div_table(struct device_node *node, return 0; } -static int _get_divider_width(struct device_node *node, - const struct clk_div_table *table, - u8 flags) +static int _populate_divider_min_max(struct device_node *node, + struct clk_omap_divider *divider) { - u32 min_div; - u32 max_div; - u32 val = 0; - u32 div; + u32 min_div = 0; + u32 max_div = 0; + u32 val; + const struct clk_div_table *clkt; - if (!table) { + if (!divider->table) { /* Clk divider table not provided, determine min/max divs */ if (of_property_read_u32(node, "ti,min-div", &min_div)) min_div = 1; @@ -469,30 +460,22 @@ static int _get_divider_width(struct device_node *node, pr_err("no max-div for %pOFn!\n", node); return -EINVAL; } - - /* Determine bit width for the field */ - if (flags & CLK_DIVIDER_ONE_BASED) - val = 1; - - div = min_div; - - while (div < max_div) { - if (flags & CLK_DIVIDER_POWER_OF_TWO) - div <<= 1; - else - div++; - val++; - } } else { - div = 0; - while (table[div].div) { - val = table[div].val; - div++; + for (clkt = divider->table; clkt->div; clkt++) { + val = clkt->div; + if (val > max_div) + max_div = val; + if (!min_div || val < min_div) + min_div = val; } } - return fls(val); + divider->min = min_div; + divider->max = max_div; + _setup_mask(divider); + + return 0; } static int __init ti_clk_divider_populate(struct device_node *node, @@ -532,9 +515,7 @@ static int __init ti_clk_divider_populate(struct device_node *node, if (ret) return ret; - div->width = _get_divider_width(node, div->table, div->flags); - - return 0; + return _populate_divider_min_max(node, div); } /** -- cgit v1.2.3 From 4441b57ec27e35a86337b3197c62b3d6be9695b2 Mon Sep 17 00:00:00 2001 From: Jernej Skrabec Date: Thu, 24 Oct 2019 00:13:28 +0200 Subject: clk: sunxi-ng: h3: Export MBUS clock MBUS clock will be referenced in MBUS controller node. Export it. Acked-by: Maxime Ripard Acked-by: Rob Herring Signed-off-by: Jernej Skrabec Signed-off-by: Maxime Ripard --- drivers/clk/sunxi-ng/ccu-sun8i-h3.h | 4 ---- include/dt-bindings/clock/sun8i-h3-ccu.h | 2 +- 2 files changed, 1 insertion(+), 5 deletions(-) (limited to 'drivers/clk') diff --git a/drivers/clk/sunxi-ng/ccu-sun8i-h3.h b/drivers/clk/sunxi-ng/ccu-sun8i-h3.h index b6e2680ef354..d8c38447e11b 100644 --- a/drivers/clk/sunxi-ng/ccu-sun8i-h3.h +++ b/drivers/clk/sunxi-ng/ccu-sun8i-h3.h @@ -48,10 +48,6 @@ /* Some more module clocks are exported */ -#define CLK_MBUS 113 - -/* And the GPU module clock is exported */ - #define CLK_NUMBER_H3 (CLK_GPU + 1) #define CLK_NUMBER_H5 (CLK_BUS_SCR1 + 1) diff --git a/include/dt-bindings/clock/sun8i-h3-ccu.h b/include/dt-bindings/clock/sun8i-h3-ccu.h index c5f7e9a70968..30d2d15373a2 100644 --- a/include/dt-bindings/clock/sun8i-h3-ccu.h +++ b/include/dt-bindings/clock/sun8i-h3-ccu.h @@ -143,7 +143,7 @@ #define CLK_AVS 110 #define CLK_HDMI 111 #define CLK_HDMI_DDC 112 - +#define CLK_MBUS 113 #define CLK_GPU 114 /* New clocks imported in H5 */ -- cgit v1.2.3 From 6cdef2738db031bfd06e3bc1c7d3c8cd16846d9e Mon Sep 17 00:00:00 2001 From: Govind Singh Date: Fri, 11 Oct 2019 18:59:28 +0530 Subject: clk: qcom: Add Q6SSTOP clock controller for QCS404 Add support for the Q6SSTOP clock control used on qcs404 based devices. This would allow wcss remoteproc driver to control the required WCSS Q6SSTOP clock/reset controls to bring the subsystem out of reset and shutdown the WCSS Q6DSP. Signed-off-by: Govind Singh Link: https://lkml.kernel.org/r/20191011132928.9388-3-govinds@codeaurora.org [sboyd@kernel.org: Sort makefile] Signed-off-by: Stephen Boyd --- drivers/clk/qcom/Kconfig | 8 + drivers/clk/qcom/Makefile | 1 + drivers/clk/qcom/q6sstop-qcs404.c | 223 ++++++++++++++++++++++ include/dt-bindings/clock/qcom,q6sstopcc-qcs404.h | 18 ++ 4 files changed, 250 insertions(+) create mode 100644 drivers/clk/qcom/q6sstop-qcs404.c create mode 100644 include/dt-bindings/clock/qcom,q6sstopcc-qcs404.h (limited to 'drivers/clk') diff --git a/drivers/clk/qcom/Kconfig b/drivers/clk/qcom/Kconfig index 32dbb4f09492..5e2ef37168f7 100644 --- a/drivers/clk/qcom/Kconfig +++ b/drivers/clk/qcom/Kconfig @@ -248,6 +248,14 @@ config QCS_TURING_404 Support for the Turing Clock Controller on QCS404, provides clocks and resets for the Turing subsystem. +config QCS_Q6SSTOP_404 + tristate "QCS404 Q6SSTOP Clock Controller" + select QCS_GCC_404 + help + Support for the Q6SSTOP clock controller on QCS404 devices. + Say Y if you want to use the Q6SSTOP branch clocks of the WCSS clock + controller to reset the Q6SSTOP subsystem. + config SDM_GCC_845 tristate "SDM845 Global Clock Controller" select QCOM_GDSC diff --git a/drivers/clk/qcom/Makefile b/drivers/clk/qcom/Makefile index 4a813b4055d0..5ba05e2066c2 100644 --- a/drivers/clk/qcom/Makefile +++ b/drivers/clk/qcom/Makefile @@ -42,6 +42,7 @@ obj-$(CONFIG_QCOM_CLK_RPM) += clk-rpm.o obj-$(CONFIG_QCOM_CLK_RPMH) += clk-rpmh.o obj-$(CONFIG_QCOM_CLK_SMD_RPM) += clk-smd-rpm.o obj-$(CONFIG_QCS_GCC_404) += gcc-qcs404.o +obj-$(CONFIG_QCS_Q6SSTOP_404) += q6sstop-qcs404.o obj-$(CONFIG_QCS_TURING_404) += turingcc-qcs404.o obj-$(CONFIG_SDM_CAMCC_845) += camcc-sdm845.o obj-$(CONFIG_SDM_DISPCC_845) += dispcc-sdm845.o diff --git a/drivers/clk/qcom/q6sstop-qcs404.c b/drivers/clk/qcom/q6sstop-qcs404.c new file mode 100644 index 000000000000..723f932fbf7d --- /dev/null +++ b/drivers/clk/qcom/q6sstop-qcs404.c @@ -0,0 +1,223 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (c) 2018, The Linux Foundation. All rights reserved. + */ + +#include +#include +#include +#include +#include +#include +#include + +#include + +#include "clk-regmap.h" +#include "clk-branch.h" +#include "common.h" +#include "reset.h" + +static struct clk_branch lcc_ahbfabric_cbc_clk = { + .halt_reg = 0x1b004, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x1b004, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "lcc_ahbfabric_cbc_clk", + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch lcc_q6ss_ahbs_cbc_clk = { + .halt_reg = 0x22000, + .halt_check = BRANCH_VOTED, + .clkr = { + .enable_reg = 0x22000, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "lcc_q6ss_ahbs_cbc_clk", + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch lcc_q6ss_tcm_slave_cbc_clk = { + .halt_reg = 0x1c000, + .halt_check = BRANCH_VOTED, + .clkr = { + .enable_reg = 0x1c000, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "lcc_q6ss_tcm_slave_cbc_clk", + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch lcc_q6ss_ahbm_cbc_clk = { + .halt_reg = 0x22004, + .halt_check = BRANCH_VOTED, + .clkr = { + .enable_reg = 0x22004, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "lcc_q6ss_ahbm_cbc_clk", + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch lcc_q6ss_axim_cbc_clk = { + .halt_reg = 0x1c004, + .halt_check = BRANCH_VOTED, + .clkr = { + .enable_reg = 0x1c004, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "lcc_q6ss_axim_cbc_clk", + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch lcc_q6ss_bcr_sleep_clk = { + .halt_reg = 0x6004, + .halt_check = BRANCH_VOTED, + .clkr = { + .enable_reg = 0x6004, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "lcc_q6ss_bcr_sleep_clk", + .ops = &clk_branch2_ops, + }, + }, +}; + +/* TCSR clock */ +static struct clk_branch tcsr_lcc_csr_cbcr_clk = { + .halt_reg = 0x8008, + .halt_check = BRANCH_VOTED, + .clkr = { + .enable_reg = 0x8008, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "tcsr_lcc_csr_cbcr_clk", + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct regmap_config q6sstop_regmap_config = { + .reg_bits = 32, + .reg_stride = 4, + .val_bits = 32, + .fast_io = true, +}; + +static struct clk_regmap *q6sstop_qcs404_clocks[] = { + [LCC_AHBFABRIC_CBC_CLK] = &lcc_ahbfabric_cbc_clk.clkr, + [LCC_Q6SS_AHBS_CBC_CLK] = &lcc_q6ss_ahbs_cbc_clk.clkr, + [LCC_Q6SS_TCM_SLAVE_CBC_CLK] = &lcc_q6ss_tcm_slave_cbc_clk.clkr, + [LCC_Q6SS_AHBM_CBC_CLK] = &lcc_q6ss_ahbm_cbc_clk.clkr, + [LCC_Q6SS_AXIM_CBC_CLK] = &lcc_q6ss_axim_cbc_clk.clkr, + [LCC_Q6SS_BCR_SLEEP_CLK] = &lcc_q6ss_bcr_sleep_clk.clkr, +}; + +static const struct qcom_reset_map q6sstop_qcs404_resets[] = { + [Q6SSTOP_BCR_RESET] = { 0x6000 }, +}; + +static const struct qcom_cc_desc q6sstop_qcs404_desc = { + .config = &q6sstop_regmap_config, + .clks = q6sstop_qcs404_clocks, + .num_clks = ARRAY_SIZE(q6sstop_qcs404_clocks), + .resets = q6sstop_qcs404_resets, + .num_resets = ARRAY_SIZE(q6sstop_qcs404_resets), +}; + +static struct clk_regmap *tcsr_qcs404_clocks[] = { + [TCSR_Q6SS_LCC_CBCR_CLK] = &tcsr_lcc_csr_cbcr_clk.clkr, +}; + +static const struct qcom_cc_desc tcsr_qcs404_desc = { + .config = &q6sstop_regmap_config, + .clks = tcsr_qcs404_clocks, + .num_clks = ARRAY_SIZE(tcsr_qcs404_clocks), +}; + +static const struct of_device_id q6sstopcc_qcs404_match_table[] = { + { .compatible = "qcom,qcs404-q6sstopcc" }, + { } +}; +MODULE_DEVICE_TABLE(of, q6sstopcc_qcs404_match_table); + +static int q6sstopcc_qcs404_probe(struct platform_device *pdev) +{ + const struct qcom_cc_desc *desc; + int ret; + + pm_runtime_enable(&pdev->dev); + ret = pm_clk_create(&pdev->dev); + if (ret) + goto disable_pm_runtime; + + ret = pm_clk_add(&pdev->dev, NULL); + if (ret < 0) { + dev_err(&pdev->dev, "failed to acquire iface clock\n"); + goto destroy_pm_clk; + } + + q6sstop_regmap_config.name = "q6sstop_tcsr"; + desc = &tcsr_qcs404_desc; + + ret = qcom_cc_probe_by_index(pdev, 1, desc); + if (ret) + goto destroy_pm_clk; + + q6sstop_regmap_config.name = "q6sstop_cc"; + desc = &q6sstop_qcs404_desc; + + ret = qcom_cc_probe_by_index(pdev, 0, desc); + if (ret) + goto destroy_pm_clk; + + return 0; + +destroy_pm_clk: + pm_clk_destroy(&pdev->dev); + +disable_pm_runtime: + pm_runtime_disable(&pdev->dev); + + return ret; +} + +static int q6sstopcc_qcs404_remove(struct platform_device *pdev) +{ + pm_clk_destroy(&pdev->dev); + pm_runtime_disable(&pdev->dev); + + return 0; +} + +static const struct dev_pm_ops q6sstopcc_pm_ops = { + SET_RUNTIME_PM_OPS(pm_clk_suspend, pm_clk_resume, NULL) +}; + +static struct platform_driver q6sstopcc_qcs404_driver = { + .probe = q6sstopcc_qcs404_probe, + .remove = q6sstopcc_qcs404_remove, + .driver = { + .name = "qcs404-q6sstopcc", + .of_match_table = q6sstopcc_qcs404_match_table, + .pm = &q6sstopcc_pm_ops, + }, +}; + +module_platform_driver(q6sstopcc_qcs404_driver); + +MODULE_DESCRIPTION("QTI QCS404 Q6SSTOP Clock Controller Driver"); +MODULE_LICENSE("GPL v2"); diff --git a/include/dt-bindings/clock/qcom,q6sstopcc-qcs404.h b/include/dt-bindings/clock/qcom,q6sstopcc-qcs404.h new file mode 100644 index 000000000000..c6f5290f0914 --- /dev/null +++ b/include/dt-bindings/clock/qcom,q6sstopcc-qcs404.h @@ -0,0 +1,18 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Copyright (c) 2018, The Linux Foundation. All rights reserved. + */ + +#ifndef _DT_BINDINGS_CLK_Q6SSTOP_QCS404_H +#define _DT_BINDINGS_CLK_Q6SSTOP_QCS404_H + +#define LCC_AHBFABRIC_CBC_CLK 0 +#define LCC_Q6SS_AHBS_CBC_CLK 1 +#define LCC_Q6SS_TCM_SLAVE_CBC_CLK 2 +#define LCC_Q6SS_AHBM_CBC_CLK 3 +#define LCC_Q6SS_AXIM_CBC_CLK 4 +#define LCC_Q6SS_BCR_SLEEP_CLK 5 +#define TCSR_Q6SS_LCC_CBCR_CLK 6 + +#define Q6SSTOP_BCR_RESET 1 +#endif -- cgit v1.2.3 From 57b2364d0ece3e38cd80ad0d87ff4b7c73ec474f Mon Sep 17 00:00:00 2001 From: YueHaibing Date: Fri, 25 Oct 2019 17:33:32 +0800 Subject: clk: qcom: remove unneeded semicolon remove unneeded semicolon. Signed-off-by: YueHaibing Link: https://lkml.kernel.org/r/20191025093332.27592-1-yuehaibing@huawei.com Signed-off-by: Stephen Boyd --- drivers/clk/qcom/clk-rcg2.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers/clk') diff --git a/drivers/clk/qcom/clk-rcg2.c b/drivers/clk/qcom/clk-rcg2.c index b98b81ef43a1..99c4bfa5365f 100644 --- a/drivers/clk/qcom/clk-rcg2.c +++ b/drivers/clk/qcom/clk-rcg2.c @@ -206,7 +206,7 @@ static int _freq_tbl_determine_rate(struct clk_hw *hw, const struct freq_tbl *f, break; default: return -EINVAL; - }; + } if (!f) return -EINVAL; @@ -319,7 +319,7 @@ static int __clk_rcg2_set_rate(struct clk_hw *hw, unsigned long rate, break; default: return -EINVAL; - }; + } if (!f) return -EINVAL; -- cgit v1.2.3 From 1a1c78217a779eadc6ef75d0dfb5f33088c6b481 Mon Sep 17 00:00:00 2001 From: Taniya Das Date: Mon, 14 Oct 2019 15:53:04 +0530 Subject: clk: qcom: rcg: update the DFS macro for RCG Update the init data name for each of the dynamic frequency switch controlled clock associated with the RCG clock name, so that it can be generated as per the hardware plan. Thus update the macro accordingly. Signed-off-by: Taniya Das Link: https://lkml.kernel.org/r/20191014102308.27441-2-tdas@codeaurora.org Signed-off-by: Stephen Boyd --- drivers/clk/qcom/clk-rcg.h | 2 +- drivers/clk/qcom/gcc-sdm845.c | 96 +++++++++++++++++++++---------------------- 2 files changed, 49 insertions(+), 49 deletions(-) (limited to 'drivers/clk') diff --git a/drivers/clk/qcom/clk-rcg.h b/drivers/clk/qcom/clk-rcg.h index c25b57c3cbc8..78358b81d249 100644 --- a/drivers/clk/qcom/clk-rcg.h +++ b/drivers/clk/qcom/clk-rcg.h @@ -168,7 +168,7 @@ struct clk_rcg_dfs_data { }; #define DEFINE_RCG_DFS(r) \ - { .rcg = &r##_src, .init = &r##_init } + { .rcg = &r, .init = &r##_init } extern int qcom_cc_register_rcg_dfs(struct regmap *regmap, const struct clk_rcg_dfs_data *rcgs, diff --git a/drivers/clk/qcom/gcc-sdm845.c b/drivers/clk/qcom/gcc-sdm845.c index 95be125c3bdd..d2142fe46a8e 100644 --- a/drivers/clk/qcom/gcc-sdm845.c +++ b/drivers/clk/qcom/gcc-sdm845.c @@ -408,7 +408,7 @@ static const struct freq_tbl ftbl_gcc_qupv3_wrap0_s0_clk_src[] = { { } }; -static struct clk_init_data gcc_qupv3_wrap0_s0_clk_init = { +static struct clk_init_data gcc_qupv3_wrap0_s0_clk_src_init = { .name = "gcc_qupv3_wrap0_s0_clk_src", .parent_names = gcc_parent_names_0, .num_parents = 4, @@ -421,10 +421,10 @@ static struct clk_rcg2 gcc_qupv3_wrap0_s0_clk_src = { .hid_width = 5, .parent_map = gcc_parent_map_0, .freq_tbl = ftbl_gcc_qupv3_wrap0_s0_clk_src, - .clkr.hw.init = &gcc_qupv3_wrap0_s0_clk_init, + .clkr.hw.init = &gcc_qupv3_wrap0_s0_clk_src_init, }; -static struct clk_init_data gcc_qupv3_wrap0_s1_clk_init = { +static struct clk_init_data gcc_qupv3_wrap0_s1_clk_src_init = { .name = "gcc_qupv3_wrap0_s1_clk_src", .parent_names = gcc_parent_names_0, .num_parents = 4, @@ -437,10 +437,10 @@ static struct clk_rcg2 gcc_qupv3_wrap0_s1_clk_src = { .hid_width = 5, .parent_map = gcc_parent_map_0, .freq_tbl = ftbl_gcc_qupv3_wrap0_s0_clk_src, - .clkr.hw.init = &gcc_qupv3_wrap0_s1_clk_init, + .clkr.hw.init = &gcc_qupv3_wrap0_s1_clk_src_init, }; -static struct clk_init_data gcc_qupv3_wrap0_s2_clk_init = { +static struct clk_init_data gcc_qupv3_wrap0_s2_clk_src_init = { .name = "gcc_qupv3_wrap0_s2_clk_src", .parent_names = gcc_parent_names_0, .num_parents = 4, @@ -453,10 +453,10 @@ static struct clk_rcg2 gcc_qupv3_wrap0_s2_clk_src = { .hid_width = 5, .parent_map = gcc_parent_map_0, .freq_tbl = ftbl_gcc_qupv3_wrap0_s0_clk_src, - .clkr.hw.init = &gcc_qupv3_wrap0_s2_clk_init, + .clkr.hw.init = &gcc_qupv3_wrap0_s2_clk_src_init, }; -static struct clk_init_data gcc_qupv3_wrap0_s3_clk_init = { +static struct clk_init_data gcc_qupv3_wrap0_s3_clk_src_init = { .name = "gcc_qupv3_wrap0_s3_clk_src", .parent_names = gcc_parent_names_0, .num_parents = 4, @@ -469,10 +469,10 @@ static struct clk_rcg2 gcc_qupv3_wrap0_s3_clk_src = { .hid_width = 5, .parent_map = gcc_parent_map_0, .freq_tbl = ftbl_gcc_qupv3_wrap0_s0_clk_src, - .clkr.hw.init = &gcc_qupv3_wrap0_s3_clk_init, + .clkr.hw.init = &gcc_qupv3_wrap0_s3_clk_src_init, }; -static struct clk_init_data gcc_qupv3_wrap0_s4_clk_init = { +static struct clk_init_data gcc_qupv3_wrap0_s4_clk_src_init = { .name = "gcc_qupv3_wrap0_s4_clk_src", .parent_names = gcc_parent_names_0, .num_parents = 4, @@ -485,10 +485,10 @@ static struct clk_rcg2 gcc_qupv3_wrap0_s4_clk_src = { .hid_width = 5, .parent_map = gcc_parent_map_0, .freq_tbl = ftbl_gcc_qupv3_wrap0_s0_clk_src, - .clkr.hw.init = &gcc_qupv3_wrap0_s4_clk_init, + .clkr.hw.init = &gcc_qupv3_wrap0_s4_clk_src_init, }; -static struct clk_init_data gcc_qupv3_wrap0_s5_clk_init = { +static struct clk_init_data gcc_qupv3_wrap0_s5_clk_src_init = { .name = "gcc_qupv3_wrap0_s5_clk_src", .parent_names = gcc_parent_names_0, .num_parents = 4, @@ -501,10 +501,10 @@ static struct clk_rcg2 gcc_qupv3_wrap0_s5_clk_src = { .hid_width = 5, .parent_map = gcc_parent_map_0, .freq_tbl = ftbl_gcc_qupv3_wrap0_s0_clk_src, - .clkr.hw.init = &gcc_qupv3_wrap0_s5_clk_init, + .clkr.hw.init = &gcc_qupv3_wrap0_s5_clk_src_init, }; -static struct clk_init_data gcc_qupv3_wrap0_s6_clk_init = { +static struct clk_init_data gcc_qupv3_wrap0_s6_clk_src_init = { .name = "gcc_qupv3_wrap0_s6_clk_src", .parent_names = gcc_parent_names_0, .num_parents = 4, @@ -517,10 +517,10 @@ static struct clk_rcg2 gcc_qupv3_wrap0_s6_clk_src = { .hid_width = 5, .parent_map = gcc_parent_map_0, .freq_tbl = ftbl_gcc_qupv3_wrap0_s0_clk_src, - .clkr.hw.init = &gcc_qupv3_wrap0_s6_clk_init, + .clkr.hw.init = &gcc_qupv3_wrap0_s6_clk_src_init, }; -static struct clk_init_data gcc_qupv3_wrap0_s7_clk_init = { +static struct clk_init_data gcc_qupv3_wrap0_s7_clk_src_init = { .name = "gcc_qupv3_wrap0_s7_clk_src", .parent_names = gcc_parent_names_0, .num_parents = 4, @@ -533,10 +533,10 @@ static struct clk_rcg2 gcc_qupv3_wrap0_s7_clk_src = { .hid_width = 5, .parent_map = gcc_parent_map_0, .freq_tbl = ftbl_gcc_qupv3_wrap0_s0_clk_src, - .clkr.hw.init = &gcc_qupv3_wrap0_s7_clk_init, + .clkr.hw.init = &gcc_qupv3_wrap0_s7_clk_src_init, }; -static struct clk_init_data gcc_qupv3_wrap1_s0_clk_init = { +static struct clk_init_data gcc_qupv3_wrap1_s0_clk_src_init = { .name = "gcc_qupv3_wrap1_s0_clk_src", .parent_names = gcc_parent_names_0, .num_parents = 4, @@ -549,10 +549,10 @@ static struct clk_rcg2 gcc_qupv3_wrap1_s0_clk_src = { .hid_width = 5, .parent_map = gcc_parent_map_0, .freq_tbl = ftbl_gcc_qupv3_wrap0_s0_clk_src, - .clkr.hw.init = &gcc_qupv3_wrap1_s0_clk_init, + .clkr.hw.init = &gcc_qupv3_wrap1_s0_clk_src_init, }; -static struct clk_init_data gcc_qupv3_wrap1_s1_clk_init = { +static struct clk_init_data gcc_qupv3_wrap1_s1_clk_src_init = { .name = "gcc_qupv3_wrap1_s1_clk_src", .parent_names = gcc_parent_names_0, .num_parents = 4, @@ -565,10 +565,10 @@ static struct clk_rcg2 gcc_qupv3_wrap1_s1_clk_src = { .hid_width = 5, .parent_map = gcc_parent_map_0, .freq_tbl = ftbl_gcc_qupv3_wrap0_s0_clk_src, - .clkr.hw.init = &gcc_qupv3_wrap1_s1_clk_init, + .clkr.hw.init = &gcc_qupv3_wrap1_s1_clk_src_init, }; -static struct clk_init_data gcc_qupv3_wrap1_s2_clk_init = { +static struct clk_init_data gcc_qupv3_wrap1_s2_clk_src_init = { .name = "gcc_qupv3_wrap1_s2_clk_src", .parent_names = gcc_parent_names_0, .num_parents = 4, @@ -581,10 +581,10 @@ static struct clk_rcg2 gcc_qupv3_wrap1_s2_clk_src = { .hid_width = 5, .parent_map = gcc_parent_map_0, .freq_tbl = ftbl_gcc_qupv3_wrap0_s0_clk_src, - .clkr.hw.init = &gcc_qupv3_wrap1_s2_clk_init, + .clkr.hw.init = &gcc_qupv3_wrap1_s2_clk_src_init, }; -static struct clk_init_data gcc_qupv3_wrap1_s3_clk_init = { +static struct clk_init_data gcc_qupv3_wrap1_s3_clk_src_init = { .name = "gcc_qupv3_wrap1_s3_clk_src", .parent_names = gcc_parent_names_0, .num_parents = 4, @@ -597,10 +597,10 @@ static struct clk_rcg2 gcc_qupv3_wrap1_s3_clk_src = { .hid_width = 5, .parent_map = gcc_parent_map_0, .freq_tbl = ftbl_gcc_qupv3_wrap0_s0_clk_src, - .clkr.hw.init = &gcc_qupv3_wrap1_s3_clk_init, + .clkr.hw.init = &gcc_qupv3_wrap1_s3_clk_src_init, }; -static struct clk_init_data gcc_qupv3_wrap1_s4_clk_init = { +static struct clk_init_data gcc_qupv3_wrap1_s4_clk_src_init = { .name = "gcc_qupv3_wrap1_s4_clk_src", .parent_names = gcc_parent_names_0, .num_parents = 4, @@ -613,10 +613,10 @@ static struct clk_rcg2 gcc_qupv3_wrap1_s4_clk_src = { .hid_width = 5, .parent_map = gcc_parent_map_0, .freq_tbl = ftbl_gcc_qupv3_wrap0_s0_clk_src, - .clkr.hw.init = &gcc_qupv3_wrap1_s4_clk_init, + .clkr.hw.init = &gcc_qupv3_wrap1_s4_clk_src_init, }; -static struct clk_init_data gcc_qupv3_wrap1_s5_clk_init = { +static struct clk_init_data gcc_qupv3_wrap1_s5_clk_src_init = { .name = "gcc_qupv3_wrap1_s5_clk_src", .parent_names = gcc_parent_names_0, .num_parents = 4, @@ -629,10 +629,10 @@ static struct clk_rcg2 gcc_qupv3_wrap1_s5_clk_src = { .hid_width = 5, .parent_map = gcc_parent_map_0, .freq_tbl = ftbl_gcc_qupv3_wrap0_s0_clk_src, - .clkr.hw.init = &gcc_qupv3_wrap1_s5_clk_init, + .clkr.hw.init = &gcc_qupv3_wrap1_s5_clk_src_init, }; -static struct clk_init_data gcc_qupv3_wrap1_s6_clk_init = { +static struct clk_init_data gcc_qupv3_wrap1_s6_clk_src_init = { .name = "gcc_qupv3_wrap1_s6_clk_src", .parent_names = gcc_parent_names_0, .num_parents = 4, @@ -645,10 +645,10 @@ static struct clk_rcg2 gcc_qupv3_wrap1_s6_clk_src = { .hid_width = 5, .parent_map = gcc_parent_map_0, .freq_tbl = ftbl_gcc_qupv3_wrap0_s0_clk_src, - .clkr.hw.init = &gcc_qupv3_wrap1_s6_clk_init, + .clkr.hw.init = &gcc_qupv3_wrap1_s6_clk_src_init, }; -static struct clk_init_data gcc_qupv3_wrap1_s7_clk_init = { +static struct clk_init_data gcc_qupv3_wrap1_s7_clk_src_init = { .name = "gcc_qupv3_wrap1_s7_clk_src", .parent_names = gcc_parent_names_0, .num_parents = 4, @@ -661,7 +661,7 @@ static struct clk_rcg2 gcc_qupv3_wrap1_s7_clk_src = { .hid_width = 5, .parent_map = gcc_parent_map_0, .freq_tbl = ftbl_gcc_qupv3_wrap0_s0_clk_src, - .clkr.hw.init = &gcc_qupv3_wrap1_s7_clk_init, + .clkr.hw.init = &gcc_qupv3_wrap1_s7_clk_src_init, }; static const struct freq_tbl ftbl_gcc_sdcc2_apps_clk_src[] = { @@ -3577,22 +3577,22 @@ static const struct of_device_id gcc_sdm845_match_table[] = { MODULE_DEVICE_TABLE(of, gcc_sdm845_match_table); static const struct clk_rcg_dfs_data gcc_dfs_clocks[] = { - DEFINE_RCG_DFS(gcc_qupv3_wrap0_s0_clk), - DEFINE_RCG_DFS(gcc_qupv3_wrap0_s1_clk), - DEFINE_RCG_DFS(gcc_qupv3_wrap0_s2_clk), - DEFINE_RCG_DFS(gcc_qupv3_wrap0_s3_clk), - DEFINE_RCG_DFS(gcc_qupv3_wrap0_s4_clk), - DEFINE_RCG_DFS(gcc_qupv3_wrap0_s5_clk), - DEFINE_RCG_DFS(gcc_qupv3_wrap0_s6_clk), - DEFINE_RCG_DFS(gcc_qupv3_wrap0_s7_clk), - DEFINE_RCG_DFS(gcc_qupv3_wrap1_s0_clk), - DEFINE_RCG_DFS(gcc_qupv3_wrap1_s1_clk), - DEFINE_RCG_DFS(gcc_qupv3_wrap1_s2_clk), - DEFINE_RCG_DFS(gcc_qupv3_wrap1_s3_clk), - DEFINE_RCG_DFS(gcc_qupv3_wrap1_s4_clk), - DEFINE_RCG_DFS(gcc_qupv3_wrap1_s5_clk), - DEFINE_RCG_DFS(gcc_qupv3_wrap1_s6_clk), - DEFINE_RCG_DFS(gcc_qupv3_wrap1_s7_clk), + DEFINE_RCG_DFS(gcc_qupv3_wrap0_s0_clk_src), + DEFINE_RCG_DFS(gcc_qupv3_wrap0_s1_clk_src), + DEFINE_RCG_DFS(gcc_qupv3_wrap0_s2_clk_src), + DEFINE_RCG_DFS(gcc_qupv3_wrap0_s3_clk_src), + DEFINE_RCG_DFS(gcc_qupv3_wrap0_s4_clk_src), + DEFINE_RCG_DFS(gcc_qupv3_wrap0_s5_clk_src), + DEFINE_RCG_DFS(gcc_qupv3_wrap0_s6_clk_src), + DEFINE_RCG_DFS(gcc_qupv3_wrap0_s7_clk_src), + DEFINE_RCG_DFS(gcc_qupv3_wrap1_s0_clk_src), + DEFINE_RCG_DFS(gcc_qupv3_wrap1_s1_clk_src), + DEFINE_RCG_DFS(gcc_qupv3_wrap1_s2_clk_src), + DEFINE_RCG_DFS(gcc_qupv3_wrap1_s3_clk_src), + DEFINE_RCG_DFS(gcc_qupv3_wrap1_s4_clk_src), + DEFINE_RCG_DFS(gcc_qupv3_wrap1_s5_clk_src), + DEFINE_RCG_DFS(gcc_qupv3_wrap1_s6_clk_src), + DEFINE_RCG_DFS(gcc_qupv3_wrap1_s7_clk_src), }; static int gcc_sdm845_probe(struct platform_device *pdev) -- cgit v1.2.3 From ffe37ede0a9eb524162c683f48da8558d5323ddb Mon Sep 17 00:00:00 2001 From: Taniya Das Date: Mon, 14 Oct 2019 15:53:05 +0530 Subject: clk: qcom: common: Return NULL from clk_hw OF provider Return NULL in the cases where the clk_hw is not registered with the clock provider, but the clock consumer still requests for a clock id. Signed-off-by: Taniya Das Link: https://lkml.kernel.org/r/20191014102308.27441-3-tdas@codeaurora.org Signed-off-by: Stephen Boyd --- drivers/clk/qcom/common.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/clk') diff --git a/drivers/clk/qcom/common.c b/drivers/clk/qcom/common.c index 28ddc747d703..caba81d18c70 100644 --- a/drivers/clk/qcom/common.c +++ b/drivers/clk/qcom/common.c @@ -218,7 +218,7 @@ static struct clk_hw *qcom_cc_clk_hw_get(struct of_phandle_args *clkspec, return ERR_PTR(-EINVAL); } - return cc->rclks[idx] ? &cc->rclks[idx]->hw : ERR_PTR(-ENOENT); + return cc->rclks[idx] ? &cc->rclks[idx]->hw : NULL; } int qcom_cc_really_probe(struct platform_device *pdev, -- cgit v1.2.3 From 17269568f72670e97b19b14897137a8f5c21c09b Mon Sep 17 00:00:00 2001 From: Taniya Das Date: Mon, 14 Oct 2019 15:53:08 +0530 Subject: clk: qcom: Add Global Clock controller (GCC) driver for SC7180 Add support for the global clock controller found on SC7180 based devices. This should allow most non-multimedia device drivers to probe and control their clocks. Signed-off-by: Taniya Das Link: https://lkml.kernel.org/r/20191014102308.27441-6-tdas@codeaurora.org Signed-off-by: Stephen Boyd --- drivers/clk/qcom/Kconfig | 9 + drivers/clk/qcom/Makefile | 1 + drivers/clk/qcom/gcc-sc7180.c | 2450 +++++++++++++++++++++++++++++++++++++++++ 3 files changed, 2460 insertions(+) create mode 100644 drivers/clk/qcom/gcc-sc7180.c (limited to 'drivers/clk') diff --git a/drivers/clk/qcom/Kconfig b/drivers/clk/qcom/Kconfig index 5e2ef37168f7..5d8cc03457ca 100644 --- a/drivers/clk/qcom/Kconfig +++ b/drivers/clk/qcom/Kconfig @@ -227,6 +227,15 @@ config QCS_GCC_404 Say Y if you want to use multimedia devices or peripheral devices such as UART, SPI, I2C, USB, SD/eMMC, PCIe etc. +config SC_GCC_7180 + tristate "SC7180 Global Clock Controller" + select QCOM_GDSC + depends on COMMON_CLK_QCOM + help + Support for the global clock controller on SC7180 devices. + Say Y if you want to use peripheral devices such as UART, SPI, + I2C, USB, UFS, SDCC, etc. + config SDM_CAMCC_845 tristate "SDM845 Camera Clock Controller" select SDM_GCC_845 diff --git a/drivers/clk/qcom/Makefile b/drivers/clk/qcom/Makefile index 5ba05e2066c2..80a30976abe8 100644 --- a/drivers/clk/qcom/Makefile +++ b/drivers/clk/qcom/Makefile @@ -44,6 +44,7 @@ obj-$(CONFIG_QCOM_CLK_SMD_RPM) += clk-smd-rpm.o obj-$(CONFIG_QCS_GCC_404) += gcc-qcs404.o obj-$(CONFIG_QCS_Q6SSTOP_404) += q6sstop-qcs404.o obj-$(CONFIG_QCS_TURING_404) += turingcc-qcs404.o +obj-$(CONFIG_SC_GCC_7180) += gcc-sc7180.o obj-$(CONFIG_SDM_CAMCC_845) += camcc-sdm845.o obj-$(CONFIG_SDM_DISPCC_845) += dispcc-sdm845.o obj-$(CONFIG_SDM_GCC_660) += gcc-sdm660.o diff --git a/drivers/clk/qcom/gcc-sc7180.c b/drivers/clk/qcom/gcc-sc7180.c new file mode 100644 index 000000000000..38424e63bcae --- /dev/null +++ b/drivers/clk/qcom/gcc-sc7180.c @@ -0,0 +1,2450 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright (c) 2019, The Linux Foundation. All rights reserved. + */ + +#include +#include +#include +#include +#include +#include +#include + +#include + +#include "clk-alpha-pll.h" +#include "clk-branch.h" +#include "clk-rcg.h" +#include "clk-regmap.h" +#include "common.h" +#include "gdsc.h" +#include "reset.h" + +enum { + P_BI_TCXO, + P_CORE_BI_PLL_TEST_SE, + P_GPLL0_OUT_EVEN, + P_GPLL0_OUT_MAIN, + P_GPLL1_OUT_MAIN, + P_GPLL4_OUT_MAIN, + P_GPLL6_OUT_MAIN, + P_GPLL7_OUT_MAIN, + P_SLEEP_CLK, +}; + +static struct clk_alpha_pll gpll0 = { + .offset = 0x0, + .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_FABIA], + .clkr = { + .enable_reg = 0x52010, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gpll0", + .parent_data = &(const struct clk_parent_data){ + .fw_name = "bi_tcxo", + .name = "bi_tcxo", + }, + .num_parents = 1, + .ops = &clk_alpha_pll_fixed_fabia_ops, + }, + }, +}; + +static const struct clk_div_table post_div_table_gpll0_out_even[] = { + { 0x1, 2 }, + { } +}; + +static struct clk_alpha_pll_postdiv gpll0_out_even = { + .offset = 0x0, + .post_div_shift = 8, + .post_div_table = post_div_table_gpll0_out_even, + .num_post_div = ARRAY_SIZE(post_div_table_gpll0_out_even), + .width = 4, + .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_FABIA], + .clkr.hw.init = &(struct clk_init_data){ + .name = "gpll0_out_even", + .parent_data = &(const struct clk_parent_data){ + .hw = &gpll0.clkr.hw, + }, + .num_parents = 1, + .ops = &clk_alpha_pll_postdiv_fabia_ops, + }, +}; + +static struct clk_fixed_factor gcc_pll0_main_div_cdiv = { + .mult = 1, + .div = 2, + .hw.init = &(struct clk_init_data){ + .name = "gcc_pll0_main_div_cdiv", + .parent_data = &(const struct clk_parent_data){ + .hw = &gpll0.clkr.hw, + }, + .num_parents = 1, + .ops = &clk_fixed_factor_ops, + }, +}; + +static struct clk_alpha_pll gpll1 = { + .offset = 0x01000, + .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_FABIA], + .clkr = { + .enable_reg = 0x52010, + .enable_mask = BIT(1), + .hw.init = &(struct clk_init_data){ + .name = "gpll1", + .parent_data = &(const struct clk_parent_data){ + .fw_name = "bi_tcxo", + .name = "bi_tcxo", + }, + .num_parents = 1, + .ops = &clk_alpha_pll_fixed_fabia_ops, + }, + }, +}; + +static struct clk_alpha_pll gpll4 = { + .offset = 0x76000, + .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_FABIA], + .clkr = { + .enable_reg = 0x52010, + .enable_mask = BIT(4), + .hw.init = &(struct clk_init_data){ + .name = "gpll4", + .parent_data = &(const struct clk_parent_data){ + .fw_name = "bi_tcxo", + .name = "bi_tcxo", + }, + .num_parents = 1, + .ops = &clk_alpha_pll_fixed_fabia_ops, + }, + }, +}; + +static struct clk_alpha_pll gpll6 = { + .offset = 0x13000, + .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_FABIA], + .clkr = { + .enable_reg = 0x52010, + .enable_mask = BIT(6), + .hw.init = &(struct clk_init_data){ + .name = "gpll6", + .parent_data = &(const struct clk_parent_data){ + .fw_name = "bi_tcxo", + .name = "bi_tcxo", + }, + .num_parents = 1, + .ops = &clk_alpha_pll_fixed_fabia_ops, + }, + }, +}; + +static struct clk_alpha_pll gpll7 = { + .offset = 0x27000, + .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_FABIA], + .clkr = { + .enable_reg = 0x52010, + .enable_mask = BIT(7), + .hw.init = &(struct clk_init_data){ + .name = "gpll7", + .parent_data = &(const struct clk_parent_data){ + .fw_name = "bi_tcxo", + .name = "bi_tcxo", + }, + .num_parents = 1, + .ops = &clk_alpha_pll_fixed_fabia_ops, + }, + }, +}; + +static const struct parent_map gcc_parent_map_0[] = { + { P_BI_TCXO, 0 }, + { P_GPLL0_OUT_MAIN, 1 }, + { P_GPLL0_OUT_EVEN, 6 }, + { P_CORE_BI_PLL_TEST_SE, 7 }, +}; + +static const struct clk_parent_data gcc_parent_data_0[] = { + { .fw_name = "bi_tcxo", .name = "bi_tcxo" }, + { .hw = &gpll0.clkr.hw }, + { .hw = &gpll0_out_even.clkr.hw }, + { .fw_name = "core_bi_pll_test_se", .name = "core_bi_pll_test_se" }, +}; + +static const struct clk_parent_data gcc_parent_data_0_ao[] = { + { .fw_name = "bi_tcxo_ao", .name = "bi_tcxo_ao" }, + { .hw = &gpll0.clkr.hw }, + { .hw = &gpll0_out_even.clkr.hw }, + { .fw_name = "core_bi_pll_test_se", .name = "core_bi_pll_test_se" }, +}; + +static const struct parent_map gcc_parent_map_1[] = { + { P_BI_TCXO, 0 }, + { P_GPLL0_OUT_MAIN, 1 }, + { P_GPLL6_OUT_MAIN, 2 }, + { P_GPLL0_OUT_EVEN, 6 }, + { P_CORE_BI_PLL_TEST_SE, 7 }, +}; + +static const struct clk_parent_data gcc_parent_data_1[] = { + { .fw_name = "bi_tcxo", .name = "bi_tcxo" }, + { .hw = &gpll0.clkr.hw }, + { .hw = &gpll6.clkr.hw }, + { .hw = &gpll0_out_even.clkr.hw }, + { .fw_name = "core_bi_pll_test_se", .name = "core_bi_pll_test_se" }, +}; + +static const struct parent_map gcc_parent_map_2[] = { + { P_BI_TCXO, 0 }, + { P_GPLL0_OUT_MAIN, 1 }, + { P_GPLL1_OUT_MAIN, 4 }, + { P_GPLL4_OUT_MAIN, 5 }, + { P_GPLL0_OUT_EVEN, 6 }, + { P_CORE_BI_PLL_TEST_SE, 7 }, +}; + +static const struct clk_parent_data gcc_parent_data_2[] = { + { .fw_name = "bi_tcxo", .name = "bi_tcxo" }, + { .hw = &gpll0.clkr.hw }, + { .hw = &gpll1.clkr.hw }, + { .hw = &gpll4.clkr.hw }, + { .hw = &gpll0_out_even.clkr.hw }, + { .fw_name = "core_bi_pll_test_se", .name = "core_bi_pll_test_se" }, +}; + +static const struct parent_map gcc_parent_map_3[] = { + { P_BI_TCXO, 0 }, + { P_GPLL0_OUT_MAIN, 1 }, + { P_CORE_BI_PLL_TEST_SE, 7 }, +}; + +static const struct clk_parent_data gcc_parent_data_3[] = { + { .fw_name = "bi_tcxo", .name = "bi_tcxo" }, + { .hw = &gpll0.clkr.hw }, + { .fw_name = "core_bi_pll_test_se", .name = "core_bi_pll_test_se" }, +}; + +static const struct parent_map gcc_parent_map_4[] = { + { P_BI_TCXO, 0 }, + { P_GPLL0_OUT_MAIN, 1 }, + { P_SLEEP_CLK, 5 }, + { P_GPLL0_OUT_EVEN, 6 }, + { P_CORE_BI_PLL_TEST_SE, 7 }, +}; + +static const struct clk_parent_data gcc_parent_data_4[] = { + { .fw_name = "bi_tcxo", .name = "bi_tcxo" }, + { .hw = &gpll0.clkr.hw }, + { .fw_name = "sleep_clk", .name = "sleep_clk" }, + { .hw = &gpll0_out_even.clkr.hw }, + { .fw_name = "core_bi_pll_test_se", .name = "core_bi_pll_test_se" }, +}; + +static const struct parent_map gcc_parent_map_5[] = { + { P_BI_TCXO, 0 }, + { P_GPLL0_OUT_MAIN, 1 }, + { P_GPLL7_OUT_MAIN, 3 }, + { P_GPLL0_OUT_EVEN, 6 }, + { P_CORE_BI_PLL_TEST_SE, 7 }, +}; + +static const struct clk_parent_data gcc_parent_data_5[] = { + { .fw_name = "bi_tcxo", .name = "bi_tcxo" }, + { .hw = &gpll0.clkr.hw }, + { .hw = &gpll7.clkr.hw }, + { .hw = &gpll0_out_even.clkr.hw }, + { .fw_name = "core_bi_pll_test_se", .name = "core_bi_pll_test_se" }, +}; + +static const struct parent_map gcc_parent_map_6[] = { + { P_BI_TCXO, 0 }, + { P_GPLL0_OUT_MAIN, 1 }, + { P_SLEEP_CLK, 5 }, + { P_CORE_BI_PLL_TEST_SE, 7 }, +}; + +static const struct clk_parent_data gcc_parent_data_6[] = { + { .fw_name = "bi_tcxo", .name = "bi_tcxo" }, + { .hw = &gpll0.clkr.hw }, + { .fw_name = "sleep_clk", .name = "sleep_clk" }, + { .fw_name = "core_bi_pll_test_se", .name = "core_bi_pll_test_se" }, +}; + +static const struct freq_tbl ftbl_gcc_cpuss_ahb_clk_src[] = { + F(19200000, P_BI_TCXO, 1, 0, 0), + { } +}; + +static struct clk_rcg2 gcc_cpuss_ahb_clk_src = { + .cmd_rcgr = 0x48014, + .mnd_width = 0, + .hid_width = 5, + .parent_map = gcc_parent_map_0, + .freq_tbl = ftbl_gcc_cpuss_ahb_clk_src, + .clkr.hw.init = &(struct clk_init_data){ + .name = "gcc_cpuss_ahb_clk_src", + .parent_data = gcc_parent_data_0_ao, + .num_parents = 4, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_rcg2_ops, + }, +}; + +static const struct freq_tbl ftbl_gcc_gp1_clk_src[] = { + F(19200000, P_BI_TCXO, 1, 0, 0), + F(25000000, P_GPLL0_OUT_EVEN, 12, 0, 0), + F(50000000, P_GPLL0_OUT_EVEN, 6, 0, 0), + F(100000000, P_GPLL0_OUT_EVEN, 3, 0, 0), + F(200000000, P_GPLL0_OUT_EVEN, 1.5, 0, 0), + { } +}; + +static struct clk_rcg2 gcc_gp1_clk_src = { + .cmd_rcgr = 0x64004, + .mnd_width = 8, + .hid_width = 5, + .parent_map = gcc_parent_map_4, + .freq_tbl = ftbl_gcc_gp1_clk_src, + .clkr.hw.init = &(struct clk_init_data){ + .name = "gcc_gp1_clk_src", + .parent_data = gcc_parent_data_4, + .num_parents = 5, + .ops = &clk_rcg2_ops, + }, +}; + +static struct clk_rcg2 gcc_gp2_clk_src = { + .cmd_rcgr = 0x65004, + .mnd_width = 8, + .hid_width = 5, + .parent_map = gcc_parent_map_4, + .freq_tbl = ftbl_gcc_gp1_clk_src, + .clkr.hw.init = &(struct clk_init_data){ + .name = "gcc_gp2_clk_src", + .parent_data = gcc_parent_data_4, + .num_parents = 5, + .ops = &clk_rcg2_ops, + }, +}; + +static struct clk_rcg2 gcc_gp3_clk_src = { + .cmd_rcgr = 0x66004, + .mnd_width = 8, + .hid_width = 5, + .parent_map = gcc_parent_map_4, + .freq_tbl = ftbl_gcc_gp1_clk_src, + .clkr.hw.init = &(struct clk_init_data){ + .name = "gcc_gp3_clk_src", + .parent_data = gcc_parent_data_4, + .num_parents = 5, + .ops = &clk_rcg2_ops, + }, +}; + +static const struct freq_tbl ftbl_gcc_pdm2_clk_src[] = { + F(19200000, P_BI_TCXO, 1, 0, 0), + F(60000000, P_GPLL0_OUT_EVEN, 5, 0, 0), + { } +}; + +static struct clk_rcg2 gcc_pdm2_clk_src = { + .cmd_rcgr = 0x33010, + .mnd_width = 0, + .hid_width = 5, + .parent_map = gcc_parent_map_0, + .freq_tbl = ftbl_gcc_pdm2_clk_src, + .clkr.hw.init = &(struct clk_init_data){ + .name = "gcc_pdm2_clk_src", + .parent_data = gcc_parent_data_0, + .num_parents = 4, + .ops = &clk_rcg2_ops, + }, +}; + +static const struct freq_tbl ftbl_gcc_qspi_core_clk_src[] = { + F(75000000, P_GPLL0_OUT_EVEN, 4, 0, 0), + F(150000000, P_GPLL0_OUT_EVEN, 2, 0, 0), + F(300000000, P_GPLL0_OUT_EVEN, 1, 0, 0), + { } +}; + +static struct clk_rcg2 gcc_qspi_core_clk_src = { + .cmd_rcgr = 0x4b00c, + .mnd_width = 0, + .hid_width = 5, + .parent_map = gcc_parent_map_2, + .freq_tbl = ftbl_gcc_qspi_core_clk_src, + .clkr.hw.init = &(struct clk_init_data){ + .name = "gcc_qspi_core_clk_src", + .parent_data = gcc_parent_data_2, + .num_parents = 6, + .ops = &clk_rcg2_ops, + }, +}; + +static const struct freq_tbl ftbl_gcc_qupv3_wrap0_s0_clk_src[] = { + F(7372800, P_GPLL0_OUT_EVEN, 1, 384, 15625), + F(14745600, P_GPLL0_OUT_EVEN, 1, 768, 15625), + F(19200000, P_BI_TCXO, 1, 0, 0), + F(29491200, P_GPLL0_OUT_EVEN, 1, 1536, 15625), + F(32000000, P_GPLL0_OUT_EVEN, 1, 8, 75), + F(48000000, P_GPLL0_OUT_EVEN, 1, 4, 25), + F(64000000, P_GPLL0_OUT_EVEN, 1, 16, 75), + F(75000000, P_GPLL0_OUT_EVEN, 4, 0, 0), + F(80000000, P_GPLL0_OUT_EVEN, 1, 4, 15), + F(96000000, P_GPLL0_OUT_EVEN, 1, 8, 25), + F(100000000, P_GPLL0_OUT_EVEN, 3, 0, 0), + F(102400000, P_GPLL0_OUT_EVEN, 1, 128, 375), + F(112000000, P_GPLL0_OUT_EVEN, 1, 28, 75), + F(117964800, P_GPLL0_OUT_EVEN, 1, 6144, 15625), + F(120000000, P_GPLL0_OUT_EVEN, 2.5, 0, 0), + F(128000000, P_GPLL6_OUT_MAIN, 3, 0, 0), + { } +}; + +static struct clk_init_data gcc_qupv3_wrap0_s0_clk_src_init = { + .name = "gcc_qupv3_wrap0_s0_clk_src", + .parent_data = gcc_parent_data_0, + .num_parents = 4, + .ops = &clk_rcg2_ops, +}; + +static struct clk_rcg2 gcc_qupv3_wrap0_s0_clk_src = { + .cmd_rcgr = 0x17034, + .mnd_width = 16, + .hid_width = 5, + .parent_map = gcc_parent_map_0, + .freq_tbl = ftbl_gcc_qupv3_wrap0_s0_clk_src, + .clkr.hw.init = &gcc_qupv3_wrap0_s0_clk_src_init, +}; + +static struct clk_init_data gcc_qupv3_wrap0_s1_clk_src_init = { + .name = "gcc_qupv3_wrap0_s1_clk_src", + .parent_data = gcc_parent_data_0, + .num_parents = 4, + .ops = &clk_rcg2_ops, +}; + +static struct clk_rcg2 gcc_qupv3_wrap0_s1_clk_src = { + .cmd_rcgr = 0x17164, + .mnd_width = 16, + .hid_width = 5, + .parent_map = gcc_parent_map_0, + .freq_tbl = ftbl_gcc_qupv3_wrap0_s0_clk_src, + .clkr.hw.init = &gcc_qupv3_wrap0_s1_clk_src_init, +}; + +static struct clk_init_data gcc_qupv3_wrap0_s2_clk_src_init = { + .name = "gcc_qupv3_wrap0_s2_clk_src", + .parent_data = gcc_parent_data_0, + .num_parents = 4, + .ops = &clk_rcg2_ops, +}; + +static struct clk_rcg2 gcc_qupv3_wrap0_s2_clk_src = { + .cmd_rcgr = 0x17294, + .mnd_width = 16, + .hid_width = 5, + .parent_map = gcc_parent_map_0, + .freq_tbl = ftbl_gcc_qupv3_wrap0_s0_clk_src, + .clkr.hw.init = &gcc_qupv3_wrap0_s2_clk_src_init, +}; + +static struct clk_init_data gcc_qupv3_wrap0_s3_clk_src_init = { + .name = "gcc_qupv3_wrap0_s3_clk_src", + .parent_data = gcc_parent_data_0, + .num_parents = 4, + .ops = &clk_rcg2_ops, +}; + +static struct clk_rcg2 gcc_qupv3_wrap0_s3_clk_src = { + .cmd_rcgr = 0x173c4, + .mnd_width = 16, + .hid_width = 5, + .parent_map = gcc_parent_map_0, + .freq_tbl = ftbl_gcc_qupv3_wrap0_s0_clk_src, + .clkr.hw.init = &gcc_qupv3_wrap0_s3_clk_src_init, +}; + +static struct clk_init_data gcc_qupv3_wrap0_s4_clk_src_init = { + .name = "gcc_qupv3_wrap0_s4_clk_src", + .parent_data = gcc_parent_data_0, + .num_parents = 4, + .ops = &clk_rcg2_ops, +}; + +static struct clk_rcg2 gcc_qupv3_wrap0_s4_clk_src = { + .cmd_rcgr = 0x174f4, + .mnd_width = 16, + .hid_width = 5, + .parent_map = gcc_parent_map_0, + .freq_tbl = ftbl_gcc_qupv3_wrap0_s0_clk_src, + .clkr.hw.init = &gcc_qupv3_wrap0_s4_clk_src_init, +}; + +static struct clk_init_data gcc_qupv3_wrap0_s5_clk_src_init = { + .name = "gcc_qupv3_wrap0_s5_clk_src", + .parent_data = gcc_parent_data_0, + .num_parents = 4, + .ops = &clk_rcg2_ops, +}; + +static struct clk_rcg2 gcc_qupv3_wrap0_s5_clk_src = { + .cmd_rcgr = 0x17624, + .mnd_width = 16, + .hid_width = 5, + .parent_map = gcc_parent_map_0, + .freq_tbl = ftbl_gcc_qupv3_wrap0_s0_clk_src, + .clkr.hw.init = &gcc_qupv3_wrap0_s5_clk_src_init, +}; + +static struct clk_init_data gcc_qupv3_wrap1_s0_clk_src_init = { + .name = "gcc_qupv3_wrap1_s0_clk_src", + .parent_data = gcc_parent_data_0, + .num_parents = 4, + .ops = &clk_rcg2_ops, +}; + +static struct clk_rcg2 gcc_qupv3_wrap1_s0_clk_src = { + .cmd_rcgr = 0x18018, + .mnd_width = 16, + .hid_width = 5, + .parent_map = gcc_parent_map_0, + .freq_tbl = ftbl_gcc_qupv3_wrap0_s0_clk_src, + .clkr.hw.init = &gcc_qupv3_wrap1_s0_clk_src_init, +}; + +static struct clk_init_data gcc_qupv3_wrap1_s1_clk_src_init = { + .name = "gcc_qupv3_wrap1_s1_clk_src", + .parent_data = gcc_parent_data_0, + .num_parents = 4, + .ops = &clk_rcg2_ops, +}; + +static struct clk_rcg2 gcc_qupv3_wrap1_s1_clk_src = { + .cmd_rcgr = 0x18148, + .mnd_width = 16, + .hid_width = 5, + .parent_map = gcc_parent_map_0, + .freq_tbl = ftbl_gcc_qupv3_wrap0_s0_clk_src, + .clkr.hw.init = &gcc_qupv3_wrap1_s1_clk_src_init, +}; + +static struct clk_init_data gcc_qupv3_wrap1_s2_clk_src_init = { + .name = "gcc_qupv3_wrap1_s2_clk_src", + .parent_data = gcc_parent_data_0, + .num_parents = 4, + .ops = &clk_rcg2_ops, +}; + +static struct clk_rcg2 gcc_qupv3_wrap1_s2_clk_src = { + .cmd_rcgr = 0x18278, + .mnd_width = 16, + .hid_width = 5, + .parent_map = gcc_parent_map_0, + .freq_tbl = ftbl_gcc_qupv3_wrap0_s0_clk_src, + .clkr.hw.init = &gcc_qupv3_wrap1_s2_clk_src_init, +}; + +static struct clk_init_data gcc_qupv3_wrap1_s3_clk_src_init = { + .name = "gcc_qupv3_wrap1_s3_clk_src", + .parent_data = gcc_parent_data_0, + .num_parents = 4, + .ops = &clk_rcg2_ops, +}; + +static struct clk_rcg2 gcc_qupv3_wrap1_s3_clk_src = { + .cmd_rcgr = 0x183a8, + .mnd_width = 16, + .hid_width = 5, + .parent_map = gcc_parent_map_0, + .freq_tbl = ftbl_gcc_qupv3_wrap0_s0_clk_src, + .clkr.hw.init = &gcc_qupv3_wrap1_s3_clk_src_init, +}; + +static struct clk_init_data gcc_qupv3_wrap1_s4_clk_src_init = { + .name = "gcc_qupv3_wrap1_s4_clk_src", + .parent_data = gcc_parent_data_0, + .num_parents = 4, + .ops = &clk_rcg2_ops, +}; + +static struct clk_rcg2 gcc_qupv3_wrap1_s4_clk_src = { + .cmd_rcgr = 0x184d8, + .mnd_width = 16, + .hid_width = 5, + .parent_map = gcc_parent_map_0, + .freq_tbl = ftbl_gcc_qupv3_wrap0_s0_clk_src, + .clkr.hw.init = &gcc_qupv3_wrap1_s4_clk_src_init, +}; + +static struct clk_init_data gcc_qupv3_wrap1_s5_clk_src_init = { + .name = "gcc_qupv3_wrap1_s5_clk_src", + .parent_data = gcc_parent_data_0, + .num_parents = 4, + .ops = &clk_rcg2_ops, +}; + +static struct clk_rcg2 gcc_qupv3_wrap1_s5_clk_src = { + .cmd_rcgr = 0x18608, + .mnd_width = 16, + .hid_width = 5, + .parent_map = gcc_parent_map_0, + .freq_tbl = ftbl_gcc_qupv3_wrap0_s0_clk_src, + .clkr.hw.init = &gcc_qupv3_wrap1_s5_clk_src_init, +}; + + +static const struct freq_tbl ftbl_gcc_sdcc1_apps_clk_src[] = { + F(144000, P_BI_TCXO, 16, 3, 25), + F(400000, P_BI_TCXO, 12, 1, 4), + F(19200000, P_BI_TCXO, 1, 0, 0), + F(20000000, P_GPLL0_OUT_EVEN, 5, 1, 3), + F(25000000, P_GPLL0_OUT_EVEN, 6, 1, 2), + F(50000000, P_GPLL0_OUT_EVEN, 6, 0, 0), + F(100000000, P_GPLL0_OUT_EVEN, 3, 0, 0), + F(192000000, P_GPLL6_OUT_MAIN, 2, 0, 0), + F(384000000, P_GPLL6_OUT_MAIN, 1, 0, 0), + { } +}; + +static struct clk_rcg2 gcc_sdcc1_apps_clk_src = { + .cmd_rcgr = 0x12028, + .mnd_width = 8, + .hid_width = 5, + .parent_map = gcc_parent_map_1, + .freq_tbl = ftbl_gcc_sdcc1_apps_clk_src, + .clkr.hw.init = &(struct clk_init_data){ + .name = "gcc_sdcc1_apps_clk_src", + .parent_data = gcc_parent_data_1, + .num_parents = 5, + .ops = &clk_rcg2_ops, + }, +}; + +static const struct freq_tbl ftbl_gcc_sdcc1_ice_core_clk_src[] = { + F(100000000, P_GPLL0_OUT_EVEN, 3, 0, 0), + F(150000000, P_GPLL0_OUT_EVEN, 2, 0, 0), + F(200000000, P_GPLL0_OUT_MAIN, 3, 0, 0), + F(300000000, P_GPLL0_OUT_EVEN, 1, 0, 0), + { } +}; + +static struct clk_rcg2 gcc_sdcc1_ice_core_clk_src = { + .cmd_rcgr = 0x12010, + .mnd_width = 0, + .hid_width = 5, + .parent_map = gcc_parent_map_0, + .freq_tbl = ftbl_gcc_sdcc1_ice_core_clk_src, + .clkr.hw.init = &(struct clk_init_data){ + .name = "gcc_sdcc1_ice_core_clk_src", + .parent_data = gcc_parent_data_0, + .num_parents = 4, + .ops = &clk_rcg2_ops, + }, +}; + +static const struct freq_tbl ftbl_gcc_sdcc2_apps_clk_src[] = { + F(400000, P_BI_TCXO, 12, 1, 4), + F(9600000, P_BI_TCXO, 2, 0, 0), + F(19200000, P_BI_TCXO, 1, 0, 0), + F(25000000, P_GPLL0_OUT_EVEN, 12, 0, 0), + F(100000000, P_GPLL0_OUT_EVEN, 3, 0, 0), + F(202000000, P_GPLL7_OUT_MAIN, 4, 0, 0), + { } +}; + +static struct clk_rcg2 gcc_sdcc2_apps_clk_src = { + .cmd_rcgr = 0x1400c, + .mnd_width = 8, + .hid_width = 5, + .parent_map = gcc_parent_map_5, + .freq_tbl = ftbl_gcc_sdcc2_apps_clk_src, + .clkr.hw.init = &(struct clk_init_data){ + .name = "gcc_sdcc2_apps_clk_src", + .parent_data = gcc_parent_data_5, + .num_parents = 5, + .ops = &clk_rcg2_ops, + }, +}; + +static const struct freq_tbl ftbl_gcc_ufs_phy_axi_clk_src[] = { + F(25000000, P_GPLL0_OUT_EVEN, 12, 0, 0), + F(50000000, P_GPLL0_OUT_EVEN, 6, 0, 0), + F(100000000, P_GPLL0_OUT_EVEN, 3, 0, 0), + F(200000000, P_GPLL0_OUT_MAIN, 3, 0, 0), + F(240000000, P_GPLL0_OUT_MAIN, 2.5, 0, 0), + { } +}; + +static struct clk_rcg2 gcc_ufs_phy_axi_clk_src = { + .cmd_rcgr = 0x77020, + .mnd_width = 8, + .hid_width = 5, + .parent_map = gcc_parent_map_0, + .freq_tbl = ftbl_gcc_ufs_phy_axi_clk_src, + .clkr.hw.init = &(struct clk_init_data){ + .name = "gcc_ufs_phy_axi_clk_src", + .parent_data = gcc_parent_data_0, + .num_parents = 4, + .ops = &clk_rcg2_ops, + }, +}; + +static const struct freq_tbl ftbl_gcc_ufs_phy_ice_core_clk_src[] = { + F(37500000, P_GPLL0_OUT_EVEN, 8, 0, 0), + F(75000000, P_GPLL0_OUT_EVEN, 4, 0, 0), + F(150000000, P_GPLL0_OUT_EVEN, 2, 0, 0), + F(300000000, P_GPLL0_OUT_EVEN, 1, 0, 0), + { } +}; + +static struct clk_rcg2 gcc_ufs_phy_ice_core_clk_src = { + .cmd_rcgr = 0x77048, + .mnd_width = 0, + .hid_width = 5, + .parent_map = gcc_parent_map_0, + .freq_tbl = ftbl_gcc_ufs_phy_ice_core_clk_src, + .clkr.hw.init = &(struct clk_init_data){ + .name = "gcc_ufs_phy_ice_core_clk_src", + .parent_data = gcc_parent_data_0, + .num_parents = 4, + .ops = &clk_rcg2_ops, + }, +}; + +static const struct freq_tbl ftbl_gcc_ufs_phy_phy_aux_clk_src[] = { + F(9600000, P_BI_TCXO, 2, 0, 0), + F(19200000, P_BI_TCXO, 1, 0, 0), + { } +}; + +static struct clk_rcg2 gcc_ufs_phy_phy_aux_clk_src = { + .cmd_rcgr = 0x77098, + .mnd_width = 0, + .hid_width = 5, + .parent_map = gcc_parent_map_3, + .freq_tbl = ftbl_gcc_ufs_phy_phy_aux_clk_src, + .clkr.hw.init = &(struct clk_init_data){ + .name = "gcc_ufs_phy_phy_aux_clk_src", + .parent_data = gcc_parent_data_3, + .num_parents = 3, + .ops = &clk_rcg2_ops, + }, +}; + +static const struct freq_tbl ftbl_gcc_ufs_phy_unipro_core_clk_src[] = { + F(37500000, P_GPLL0_OUT_EVEN, 8, 0, 0), + F(75000000, P_GPLL0_OUT_EVEN, 4, 0, 0), + F(150000000, P_GPLL0_OUT_EVEN, 2, 0, 0), + { } +}; + +static struct clk_rcg2 gcc_ufs_phy_unipro_core_clk_src = { + .cmd_rcgr = 0x77060, + .mnd_width = 0, + .hid_width = 5, + .parent_map = gcc_parent_map_0, + .freq_tbl = ftbl_gcc_ufs_phy_unipro_core_clk_src, + .clkr.hw.init = &(struct clk_init_data){ + .name = "gcc_ufs_phy_unipro_core_clk_src", + .parent_data = gcc_parent_data_0, + .num_parents = 4, + .ops = &clk_rcg2_ops, + }, +}; + +static const struct freq_tbl ftbl_gcc_usb30_prim_master_clk_src[] = { + F(66666667, P_GPLL0_OUT_EVEN, 4.5, 0, 0), + F(133333333, P_GPLL0_OUT_MAIN, 4.5, 0, 0), + F(200000000, P_GPLL0_OUT_MAIN, 3, 0, 0), + F(240000000, P_GPLL0_OUT_MAIN, 2.5, 0, 0), + { } +}; + +static struct clk_rcg2 gcc_usb30_prim_master_clk_src = { + .cmd_rcgr = 0xf01c, + .mnd_width = 8, + .hid_width = 5, + .parent_map = gcc_parent_map_0, + .freq_tbl = ftbl_gcc_usb30_prim_master_clk_src, + .clkr.hw.init = &(struct clk_init_data){ + .name = "gcc_usb30_prim_master_clk_src", + .parent_data = gcc_parent_data_0, + .num_parents = 4, + .ops = &clk_rcg2_ops, + }, +}; + +static const struct freq_tbl ftbl_gcc_usb30_prim_mock_utmi_clk_src[] = { + F(19200000, P_BI_TCXO, 1, 0, 0), + F(20000000, P_GPLL0_OUT_EVEN, 15, 0, 0), + { } +}; + +static struct clk_rcg2 gcc_usb30_prim_mock_utmi_clk_src = { + .cmd_rcgr = 0xf034, + .mnd_width = 0, + .hid_width = 5, + .parent_map = gcc_parent_map_0, + .freq_tbl = ftbl_gcc_usb30_prim_mock_utmi_clk_src, + .clkr.hw.init = &(struct clk_init_data){ + .name = "gcc_usb30_prim_mock_utmi_clk_src", + .parent_data = gcc_parent_data_0, + .num_parents = 4, + .ops = &clk_rcg2_ops, + }, +}; + +static const struct freq_tbl ftbl_gcc_usb3_prim_phy_aux_clk_src[] = { + F(19200000, P_BI_TCXO, 1, 0, 0), + { } +}; + +static struct clk_rcg2 gcc_usb3_prim_phy_aux_clk_src = { + .cmd_rcgr = 0xf060, + .mnd_width = 0, + .hid_width = 5, + .parent_map = gcc_parent_map_6, + .freq_tbl = ftbl_gcc_usb3_prim_phy_aux_clk_src, + .clkr.hw.init = &(struct clk_init_data){ + .name = "gcc_usb3_prim_phy_aux_clk_src", + .parent_data = gcc_parent_data_6, + .num_parents = 4, + .ops = &clk_rcg2_ops, + }, +}; + +static struct clk_branch gcc_aggre_ufs_phy_axi_clk = { + .halt_reg = 0x82024, + .halt_check = BRANCH_HALT_DELAY, + .hwcg_reg = 0x82024, + .hwcg_bit = 1, + .clkr = { + .enable_reg = 0x82024, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_aggre_ufs_phy_axi_clk", + .parent_data = &(const struct clk_parent_data){ + .hw = &gcc_ufs_phy_axi_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_aggre_usb3_prim_axi_clk = { + .halt_reg = 0x8201c, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x8201c, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_aggre_usb3_prim_axi_clk", + .parent_data = &(const struct clk_parent_data){ + .hw = &gcc_usb30_prim_master_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_boot_rom_ahb_clk = { + .halt_reg = 0x38004, + .halt_check = BRANCH_HALT_VOTED, + .hwcg_reg = 0x38004, + .hwcg_bit = 1, + .clkr = { + .enable_reg = 0x52000, + .enable_mask = BIT(10), + .hw.init = &(struct clk_init_data){ + .name = "gcc_boot_rom_ahb_clk", + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_camera_ahb_clk = { + .halt_reg = 0xb008, + .halt_check = BRANCH_HALT, + .hwcg_reg = 0xb008, + .hwcg_bit = 1, + .clkr = { + .enable_reg = 0xb008, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_camera_ahb_clk", + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_camera_hf_axi_clk = { + .halt_reg = 0xb020, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0xb020, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_camera_hf_axi_clk", + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_camera_throttle_hf_axi_clk = { + .halt_reg = 0xb080, + .halt_check = BRANCH_HALT, + .hwcg_reg = 0xb080, + .hwcg_bit = 1, + .clkr = { + .enable_reg = 0xb080, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_camera_throttle_hf_axi_clk", + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_camera_xo_clk = { + .halt_reg = 0xb02c, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0xb02c, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_camera_xo_clk", + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_ce1_ahb_clk = { + .halt_reg = 0x4100c, + .halt_check = BRANCH_HALT_VOTED, + .hwcg_reg = 0x4100c, + .hwcg_bit = 1, + .clkr = { + .enable_reg = 0x52000, + .enable_mask = BIT(3), + .hw.init = &(struct clk_init_data){ + .name = "gcc_ce1_ahb_clk", + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_ce1_axi_clk = { + .halt_reg = 0x41008, + .halt_check = BRANCH_HALT_VOTED, + .clkr = { + .enable_reg = 0x52000, + .enable_mask = BIT(4), + .hw.init = &(struct clk_init_data){ + .name = "gcc_ce1_axi_clk", + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_ce1_clk = { + .halt_reg = 0x41004, + .halt_check = BRANCH_HALT_VOTED, + .clkr = { + .enable_reg = 0x52000, + .enable_mask = BIT(5), + .hw.init = &(struct clk_init_data){ + .name = "gcc_ce1_clk", + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_cfg_noc_usb3_prim_axi_clk = { + .halt_reg = 0x502c, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x502c, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_cfg_noc_usb3_prim_axi_clk", + .parent_data = &(const struct clk_parent_data){ + .hw = &gcc_usb30_prim_master_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +/* For CPUSS functionality the AHB clock needs to be left enabled */ +static struct clk_branch gcc_cpuss_ahb_clk = { + .halt_reg = 0x48000, + .halt_check = BRANCH_HALT_VOTED, + .clkr = { + .enable_reg = 0x52000, + .enable_mask = BIT(21), + .hw.init = &(struct clk_init_data){ + .name = "gcc_cpuss_ahb_clk", + .parent_data = &(const struct clk_parent_data){ + .hw = &gcc_cpuss_ahb_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_IS_CRITICAL | CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_cpuss_rbcpr_clk = { + .halt_reg = 0x48008, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x48008, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_cpuss_rbcpr_clk", + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_ddrss_gpu_axi_clk = { + .halt_reg = 0x4452c, + .halt_check = BRANCH_VOTED, + .clkr = { + .enable_reg = 0x4452c, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_ddrss_gpu_axi_clk", + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_disp_gpll0_clk_src = { + .halt_check = BRANCH_HALT_DELAY, + .clkr = { + .enable_reg = 0x52000, + .enable_mask = BIT(18), + .hw.init = &(struct clk_init_data){ + .name = "gcc_disp_gpll0_clk_src", + .parent_data = &(const struct clk_parent_data){ + .hw = &gpll0.clkr.hw, + }, + .num_parents = 1, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_disp_gpll0_div_clk_src = { + .halt_check = BRANCH_HALT_DELAY, + .clkr = { + .enable_reg = 0x52000, + .enable_mask = BIT(19), + .hw.init = &(struct clk_init_data){ + .name = "gcc_disp_gpll0_div_clk_src", + .parent_data = &(const struct clk_parent_data){ + .hw = &gcc_pll0_main_div_cdiv.hw, + }, + .num_parents = 1, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_disp_hf_axi_clk = { + .halt_reg = 0xb024, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0xb024, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_disp_hf_axi_clk", + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_disp_throttle_hf_axi_clk = { + .halt_reg = 0xb084, + .halt_check = BRANCH_HALT, + .hwcg_reg = 0xb084, + .hwcg_bit = 1, + .clkr = { + .enable_reg = 0xb084, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_disp_throttle_hf_axi_clk", + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_disp_xo_clk = { + .halt_reg = 0xb030, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0xb030, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_disp_xo_clk", + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_gp1_clk = { + .halt_reg = 0x64000, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x64000, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_gp1_clk", + .parent_data = &(const struct clk_parent_data){ + .hw = &gcc_gp1_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_gp2_clk = { + .halt_reg = 0x65000, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x65000, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_gp2_clk", + .parent_data = &(const struct clk_parent_data){ + .hw = &gcc_gp2_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_gp3_clk = { + .halt_reg = 0x66000, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x66000, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_gp3_clk", + .parent_data = &(const struct clk_parent_data){ + .hw = &gcc_gp3_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_gpu_gpll0_clk_src = { + .halt_check = BRANCH_HALT_DELAY, + .clkr = { + .enable_reg = 0x52000, + .enable_mask = BIT(15), + .hw.init = &(struct clk_init_data){ + .name = "gcc_gpu_gpll0_clk_src", + .parent_data = &(const struct clk_parent_data){ + .hw = &gpll0.clkr.hw, + }, + .num_parents = 1, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_gpu_gpll0_div_clk_src = { + .halt_check = BRANCH_HALT_DELAY, + .clkr = { + .enable_reg = 0x52000, + .enable_mask = BIT(16), + .hw.init = &(struct clk_init_data){ + .name = "gcc_gpu_gpll0_div_clk_src", + .parent_data = &(const struct clk_parent_data){ + .hw = &gcc_pll0_main_div_cdiv.hw, + }, + .num_parents = 1, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_gpu_memnoc_gfx_clk = { + .halt_reg = 0x7100c, + .halt_check = BRANCH_VOTED, + .clkr = { + .enable_reg = 0x7100c, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_gpu_memnoc_gfx_clk", + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_gpu_snoc_dvm_gfx_clk = { + .halt_reg = 0x71018, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x71018, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_gpu_snoc_dvm_gfx_clk", + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_npu_axi_clk = { + .halt_reg = 0x4d008, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x4d008, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_npu_axi_clk", + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_npu_bwmon_axi_clk = { + .halt_reg = 0x73008, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x73008, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_npu_bwmon_axi_clk", + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_npu_bwmon_dma_cfg_ahb_clk = { + .halt_reg = 0x73018, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x73018, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_npu_bwmon_dma_cfg_ahb_clk", + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_npu_bwmon_dsp_cfg_ahb_clk = { + .halt_reg = 0x7301c, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x7301c, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_npu_bwmon_dsp_cfg_ahb_clk", + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_npu_cfg_ahb_clk = { + .halt_reg = 0x4d004, + .halt_check = BRANCH_HALT, + .hwcg_reg = 0x4d004, + .hwcg_bit = 1, + .clkr = { + .enable_reg = 0x4d004, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_npu_cfg_ahb_clk", + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_npu_dma_clk = { + .halt_reg = 0x4d1a0, + .halt_check = BRANCH_HALT, + .hwcg_reg = 0x4d1a0, + .hwcg_bit = 1, + .clkr = { + .enable_reg = 0x4d1a0, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_npu_dma_clk", + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_npu_gpll0_clk_src = { + .halt_check = BRANCH_HALT_DELAY, + .clkr = { + .enable_reg = 0x52000, + .enable_mask = BIT(25), + .hw.init = &(struct clk_init_data){ + .name = "gcc_npu_gpll0_clk_src", + .parent_data = &(const struct clk_parent_data){ + .hw = &gpll0.clkr.hw, + }, + .num_parents = 1, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_npu_gpll0_div_clk_src = { + .halt_check = BRANCH_HALT_DELAY, + .clkr = { + .enable_reg = 0x52000, + .enable_mask = BIT(26), + .hw.init = &(struct clk_init_data){ + .name = "gcc_npu_gpll0_div_clk_src", + .parent_data = &(const struct clk_parent_data){ + .hw = &gcc_pll0_main_div_cdiv.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_pdm2_clk = { + .halt_reg = 0x3300c, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x3300c, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_pdm2_clk", + .parent_data = &(const struct clk_parent_data){ + .hw = &gcc_pdm2_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_pdm_ahb_clk = { + .halt_reg = 0x33004, + .halt_check = BRANCH_HALT, + .hwcg_reg = 0x33004, + .hwcg_bit = 1, + .clkr = { + .enable_reg = 0x33004, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_pdm_ahb_clk", + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_pdm_xo4_clk = { + .halt_reg = 0x33008, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x33008, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_pdm_xo4_clk", + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_prng_ahb_clk = { + .halt_reg = 0x34004, + .halt_check = BRANCH_HALT_VOTED, + .hwcg_reg = 0x34004, + .hwcg_bit = 1, + .clkr = { + .enable_reg = 0x52000, + .enable_mask = BIT(13), + .hw.init = &(struct clk_init_data){ + .name = "gcc_prng_ahb_clk", + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_qspi_cnoc_periph_ahb_clk = { + .halt_reg = 0x4b004, + .halt_check = BRANCH_HALT, + .hwcg_reg = 0x4b004, + .hwcg_bit = 1, + .clkr = { + .enable_reg = 0x4b004, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_qspi_cnoc_periph_ahb_clk", + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_qspi_core_clk = { + .halt_reg = 0x4b008, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x4b008, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_qspi_core_clk", + .parent_data = &(const struct clk_parent_data){ + .hw = &gcc_qspi_core_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_qupv3_wrap0_core_2x_clk = { + .halt_reg = 0x17014, + .halt_check = BRANCH_HALT_VOTED, + .clkr = { + .enable_reg = 0x52008, + .enable_mask = BIT(9), + .hw.init = &(struct clk_init_data){ + .name = "gcc_qupv3_wrap0_core_2x_clk", + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_qupv3_wrap0_core_clk = { + .halt_reg = 0x1700c, + .halt_check = BRANCH_HALT_VOTED, + .clkr = { + .enable_reg = 0x52008, + .enable_mask = BIT(8), + .hw.init = &(struct clk_init_data){ + .name = "gcc_qupv3_wrap0_core_clk", + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_qupv3_wrap0_s0_clk = { + .halt_reg = 0x17030, + .halt_check = BRANCH_HALT_VOTED, + .clkr = { + .enable_reg = 0x52008, + .enable_mask = BIT(10), + .hw.init = &(struct clk_init_data){ + .name = "gcc_qupv3_wrap0_s0_clk", + .parent_data = &(const struct clk_parent_data){ + .hw = &gcc_qupv3_wrap0_s0_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_qupv3_wrap0_s1_clk = { + .halt_reg = 0x17160, + .halt_check = BRANCH_HALT_VOTED, + .clkr = { + .enable_reg = 0x52008, + .enable_mask = BIT(11), + .hw.init = &(struct clk_init_data){ + .name = "gcc_qupv3_wrap0_s1_clk", + .parent_data = &(const struct clk_parent_data){ + .hw = &gcc_qupv3_wrap0_s1_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_qupv3_wrap0_s2_clk = { + .halt_reg = 0x17290, + .halt_check = BRANCH_HALT_VOTED, + .clkr = { + .enable_reg = 0x52008, + .enable_mask = BIT(12), + .hw.init = &(struct clk_init_data){ + .name = "gcc_qupv3_wrap0_s2_clk", + .parent_data = &(const struct clk_parent_data){ + .hw = &gcc_qupv3_wrap0_s2_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_qupv3_wrap0_s3_clk = { + .halt_reg = 0x173c0, + .halt_check = BRANCH_HALT_VOTED, + .clkr = { + .enable_reg = 0x52008, + .enable_mask = BIT(13), + .hw.init = &(struct clk_init_data){ + .name = "gcc_qupv3_wrap0_s3_clk", + .parent_data = &(const struct clk_parent_data){ + .hw = &gcc_qupv3_wrap0_s3_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_qupv3_wrap0_s4_clk = { + .halt_reg = 0x174f0, + .halt_check = BRANCH_HALT_VOTED, + .clkr = { + .enable_reg = 0x52008, + .enable_mask = BIT(14), + .hw.init = &(struct clk_init_data){ + .name = "gcc_qupv3_wrap0_s4_clk", + .parent_data = &(const struct clk_parent_data){ + .hw = &gcc_qupv3_wrap0_s4_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_qupv3_wrap0_s5_clk = { + .halt_reg = 0x17620, + .halt_check = BRANCH_HALT_VOTED, + .clkr = { + .enable_reg = 0x52008, + .enable_mask = BIT(15), + .hw.init = &(struct clk_init_data){ + .name = "gcc_qupv3_wrap0_s5_clk", + .parent_data = &(const struct clk_parent_data){ + .hw = &gcc_qupv3_wrap0_s5_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_qupv3_wrap1_core_2x_clk = { + .halt_reg = 0x18004, + .halt_check = BRANCH_HALT_VOTED, + .clkr = { + .enable_reg = 0x52008, + .enable_mask = BIT(18), + .hw.init = &(struct clk_init_data){ + .name = "gcc_qupv3_wrap1_core_2x_clk", + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_qupv3_wrap1_core_clk = { + .halt_reg = 0x18008, + .halt_check = BRANCH_HALT_VOTED, + .clkr = { + .enable_reg = 0x52008, + .enable_mask = BIT(19), + .hw.init = &(struct clk_init_data){ + .name = "gcc_qupv3_wrap1_core_clk", + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_qupv3_wrap1_s0_clk = { + .halt_reg = 0x18014, + .halt_check = BRANCH_HALT_VOTED, + .clkr = { + .enable_reg = 0x52008, + .enable_mask = BIT(22), + .hw.init = &(struct clk_init_data){ + .name = "gcc_qupv3_wrap1_s0_clk", + .parent_data = &(const struct clk_parent_data){ + .hw = &gcc_qupv3_wrap1_s0_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_qupv3_wrap1_s1_clk = { + .halt_reg = 0x18144, + .halt_check = BRANCH_HALT_VOTED, + .clkr = { + .enable_reg = 0x52008, + .enable_mask = BIT(23), + .hw.init = &(struct clk_init_data){ + .name = "gcc_qupv3_wrap1_s1_clk", + .parent_data = &(const struct clk_parent_data){ + .hw = &gcc_qupv3_wrap1_s1_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_qupv3_wrap1_s2_clk = { + .halt_reg = 0x18274, + .halt_check = BRANCH_HALT_VOTED, + .clkr = { + .enable_reg = 0x52008, + .enable_mask = BIT(24), + .hw.init = &(struct clk_init_data){ + .name = "gcc_qupv3_wrap1_s2_clk", + .parent_data = &(const struct clk_parent_data){ + .hw = &gcc_qupv3_wrap1_s2_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_qupv3_wrap1_s3_clk = { + .halt_reg = 0x183a4, + .halt_check = BRANCH_HALT_VOTED, + .clkr = { + .enable_reg = 0x52008, + .enable_mask = BIT(25), + .hw.init = &(struct clk_init_data){ + .name = "gcc_qupv3_wrap1_s3_clk", + .parent_data = &(const struct clk_parent_data){ + .hw = &gcc_qupv3_wrap1_s3_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_qupv3_wrap1_s4_clk = { + .halt_reg = 0x184d4, + .halt_check = BRANCH_HALT_VOTED, + .clkr = { + .enable_reg = 0x52008, + .enable_mask = BIT(26), + .hw.init = &(struct clk_init_data){ + .name = "gcc_qupv3_wrap1_s4_clk", + .parent_data = &(const struct clk_parent_data){ + .hw = &gcc_qupv3_wrap1_s4_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_qupv3_wrap1_s5_clk = { + .halt_reg = 0x18604, + .halt_check = BRANCH_HALT_VOTED, + .clkr = { + .enable_reg = 0x52008, + .enable_mask = BIT(27), + .hw.init = &(struct clk_init_data){ + .name = "gcc_qupv3_wrap1_s5_clk", + .parent_data = &(const struct clk_parent_data){ + .hw = &gcc_qupv3_wrap1_s5_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_qupv3_wrap_0_m_ahb_clk = { + .halt_reg = 0x17004, + .halt_check = BRANCH_HALT_VOTED, + .clkr = { + .enable_reg = 0x52008, + .enable_mask = BIT(6), + .hw.init = &(struct clk_init_data){ + .name = "gcc_qupv3_wrap_0_m_ahb_clk", + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_qupv3_wrap_0_s_ahb_clk = { + .halt_reg = 0x17008, + .halt_check = BRANCH_HALT_VOTED, + .hwcg_reg = 0x17008, + .hwcg_bit = 1, + .clkr = { + .enable_reg = 0x52008, + .enable_mask = BIT(7), + .hw.init = &(struct clk_init_data){ + .name = "gcc_qupv3_wrap_0_s_ahb_clk", + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_qupv3_wrap_1_m_ahb_clk = { + .halt_reg = 0x1800c, + .halt_check = BRANCH_HALT_VOTED, + .clkr = { + .enable_reg = 0x52008, + .enable_mask = BIT(20), + .hw.init = &(struct clk_init_data){ + .name = "gcc_qupv3_wrap_1_m_ahb_clk", + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_qupv3_wrap_1_s_ahb_clk = { + .halt_reg = 0x18010, + .halt_check = BRANCH_HALT_VOTED, + .hwcg_reg = 0x18010, + .hwcg_bit = 1, + .clkr = { + .enable_reg = 0x52008, + .enable_mask = BIT(21), + .hw.init = &(struct clk_init_data){ + .name = "gcc_qupv3_wrap_1_s_ahb_clk", + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_sdcc1_ahb_clk = { + .halt_reg = 0x12008, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x12008, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_sdcc1_ahb_clk", + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_sdcc1_apps_clk = { + .halt_reg = 0x1200c, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x1200c, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_sdcc1_apps_clk", + .parent_data = &(const struct clk_parent_data){ + .hw = &gcc_sdcc1_apps_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_sdcc1_ice_core_clk = { + .halt_reg = 0x12040, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x12040, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_sdcc1_ice_core_clk", + .parent_data = &(const struct clk_parent_data){ + .hw = &gcc_sdcc1_ice_core_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_sdcc2_ahb_clk = { + .halt_reg = 0x14008, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x14008, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_sdcc2_ahb_clk", + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_sdcc2_apps_clk = { + .halt_reg = 0x14004, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x14004, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_sdcc2_apps_clk", + .parent_data = &(const struct clk_parent_data){ + .hw = &gcc_sdcc2_apps_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +/* For CPUSS functionality the SYS NOC clock needs to be left enabled */ +static struct clk_branch gcc_sys_noc_cpuss_ahb_clk = { + .halt_reg = 0x4144, + .halt_check = BRANCH_HALT_VOTED, + .clkr = { + .enable_reg = 0x52000, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_sys_noc_cpuss_ahb_clk", + .parent_data = &(const struct clk_parent_data){ + .hw = &gcc_cpuss_ahb_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_IS_CRITICAL | CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_ufs_mem_clkref_clk = { + .halt_reg = 0x8c000, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x8c000, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_ufs_mem_clkref_clk", + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_ufs_phy_ahb_clk = { + .halt_reg = 0x77014, + .halt_check = BRANCH_HALT, + .hwcg_reg = 0x77014, + .hwcg_bit = 1, + .clkr = { + .enable_reg = 0x77014, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_ufs_phy_ahb_clk", + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_ufs_phy_axi_clk = { + .halt_reg = 0x77038, + .halt_check = BRANCH_HALT, + .hwcg_reg = 0x77038, + .hwcg_bit = 1, + .clkr = { + .enable_reg = 0x77038, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_ufs_phy_axi_clk", + .parent_data = &(const struct clk_parent_data){ + .hw = &gcc_ufs_phy_axi_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_ufs_phy_ice_core_clk = { + .halt_reg = 0x77090, + .halt_check = BRANCH_HALT, + .hwcg_reg = 0x77090, + .hwcg_bit = 1, + .clkr = { + .enable_reg = 0x77090, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_ufs_phy_ice_core_clk", + .parent_data = &(const struct clk_parent_data){ + .hw = &gcc_ufs_phy_ice_core_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_ufs_phy_phy_aux_clk = { + .halt_reg = 0x77094, + .halt_check = BRANCH_HALT, + .hwcg_reg = 0x77094, + .hwcg_bit = 1, + .clkr = { + .enable_reg = 0x77094, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_ufs_phy_phy_aux_clk", + .parent_data = &(const struct clk_parent_data){ + .hw = &gcc_ufs_phy_phy_aux_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_ufs_phy_rx_symbol_0_clk = { + .halt_reg = 0x7701c, + .halt_check = BRANCH_HALT_SKIP, + .clkr = { + .enable_reg = 0x7701c, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_ufs_phy_rx_symbol_0_clk", + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_ufs_phy_tx_symbol_0_clk = { + .halt_reg = 0x77018, + .halt_check = BRANCH_HALT_SKIP, + .clkr = { + .enable_reg = 0x77018, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_ufs_phy_tx_symbol_0_clk", + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_ufs_phy_unipro_core_clk = { + .halt_reg = 0x7708c, + .halt_check = BRANCH_HALT, + .hwcg_reg = 0x7708c, + .hwcg_bit = 1, + .clkr = { + .enable_reg = 0x7708c, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_ufs_phy_unipro_core_clk", + .parent_data = &(const struct clk_parent_data){ + .hw = &gcc_ufs_phy_unipro_core_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_usb30_prim_master_clk = { + .halt_reg = 0xf010, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0xf010, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_usb30_prim_master_clk", + .parent_data = &(const struct clk_parent_data){ + .hw = &gcc_usb30_prim_master_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_usb30_prim_mock_utmi_clk = { + .halt_reg = 0xf018, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0xf018, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_usb30_prim_mock_utmi_clk", + .parent_data = &(const struct clk_parent_data){ + .hw = + &gcc_usb30_prim_mock_utmi_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_usb30_prim_sleep_clk = { + .halt_reg = 0xf014, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0xf014, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_usb30_prim_sleep_clk", + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_usb3_prim_clkref_clk = { + .halt_reg = 0x8c010, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x8c010, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_usb3_prim_clkref_clk", + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_usb3_prim_phy_aux_clk = { + .halt_reg = 0xf050, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0xf050, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_usb3_prim_phy_aux_clk", + .parent_data = &(const struct clk_parent_data){ + .hw = &gcc_usb3_prim_phy_aux_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_usb3_prim_phy_com_aux_clk = { + .halt_reg = 0xf054, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0xf054, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_usb3_prim_phy_com_aux_clk", + .parent_data = &(const struct clk_parent_data){ + .hw = &gcc_usb3_prim_phy_aux_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_usb3_prim_phy_pipe_clk = { + .halt_reg = 0xf058, + .halt_check = BRANCH_HALT_SKIP, + .clkr = { + .enable_reg = 0xf058, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_usb3_prim_phy_pipe_clk", + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_usb_phy_cfg_ahb2phy_clk = { + .halt_reg = 0x6a004, + .halt_check = BRANCH_HALT, + .hwcg_reg = 0x6a004, + .hwcg_bit = 1, + .clkr = { + .enable_reg = 0x6a004, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_usb_phy_cfg_ahb2phy_clk", + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_video_axi_clk = { + .halt_reg = 0xb01c, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0xb01c, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_video_axi_clk", + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_video_gpll0_div_clk_src = { + .halt_check = BRANCH_HALT_DELAY, + .clkr = { + .enable_reg = 0x52000, + .enable_mask = BIT(20), + .hw.init = &(struct clk_init_data){ + .name = "gcc_video_gpll0_div_clk_src", + .parent_data = &(const struct clk_parent_data){ + .hw = &gcc_pll0_main_div_cdiv.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_video_throttle_axi_clk = { + .halt_reg = 0xb07c, + .halt_check = BRANCH_HALT, + .hwcg_reg = 0xb07c, + .hwcg_bit = 1, + .clkr = { + .enable_reg = 0xb07c, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_video_throttle_axi_clk", + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_video_xo_clk = { + .halt_reg = 0xb028, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0xb028, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_video_xo_clk", + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct gdsc ufs_phy_gdsc = { + .gdscr = 0x77004, + .pd = { + .name = "ufs_phy_gdsc", + }, + .pwrsts = PWRSTS_OFF_ON, +}; + +static struct gdsc usb30_prim_gdsc = { + .gdscr = 0x0f004, + .pd = { + .name = "usb30_prim_gdsc", + }, + .pwrsts = PWRSTS_OFF_ON, +}; + +static struct gdsc hlos1_vote_mmnoc_mmu_tbu_hf0_gdsc = { + .gdscr = 0x7d040, + .pd = { + .name = "hlos1_vote_mmnoc_mmu_tbu_hf0_gdsc", + }, + .pwrsts = PWRSTS_OFF_ON | VOTABLE, +}; + +static struct gdsc hlos1_vote_mmnoc_mmu_tbu_sf_gdsc = { + .gdscr = 0x7d044, + .pd = { + .name = "hlos1_vote_mmnoc_mmu_tbu_sf_gdsc", + }, + .pwrsts = PWRSTS_OFF_ON | VOTABLE, +}; + +static struct gdsc *gcc_sc7180_gdscs[] = { + [UFS_PHY_GDSC] = &ufs_phy_gdsc, + [USB30_PRIM_GDSC] = &usb30_prim_gdsc, + [HLOS1_VOTE_MMNOC_MMU_TBU_HF0_GDSC] = + &hlos1_vote_mmnoc_mmu_tbu_hf0_gdsc, + [HLOS1_VOTE_MMNOC_MMU_TBU_SF_GDSC] = + &hlos1_vote_mmnoc_mmu_tbu_sf_gdsc, +}; + + +static struct clk_hw *gcc_sc7180_hws[] = { + [GCC_GPLL0_MAIN_DIV_CDIV] = &gcc_pll0_main_div_cdiv.hw, +}; + +static struct clk_regmap *gcc_sc7180_clocks[] = { + [GCC_AGGRE_UFS_PHY_AXI_CLK] = &gcc_aggre_ufs_phy_axi_clk.clkr, + [GCC_AGGRE_USB3_PRIM_AXI_CLK] = &gcc_aggre_usb3_prim_axi_clk.clkr, + [GCC_BOOT_ROM_AHB_CLK] = &gcc_boot_rom_ahb_clk.clkr, + [GCC_CAMERA_AHB_CLK] = &gcc_camera_ahb_clk.clkr, + [GCC_CAMERA_HF_AXI_CLK] = &gcc_camera_hf_axi_clk.clkr, + [GCC_CAMERA_THROTTLE_HF_AXI_CLK] = &gcc_camera_throttle_hf_axi_clk.clkr, + [GCC_CAMERA_XO_CLK] = &gcc_camera_xo_clk.clkr, + [GCC_CE1_AHB_CLK] = &gcc_ce1_ahb_clk.clkr, + [GCC_CE1_AXI_CLK] = &gcc_ce1_axi_clk.clkr, + [GCC_CE1_CLK] = &gcc_ce1_clk.clkr, + [GCC_CFG_NOC_USB3_PRIM_AXI_CLK] = &gcc_cfg_noc_usb3_prim_axi_clk.clkr, + [GCC_CPUSS_AHB_CLK] = &gcc_cpuss_ahb_clk.clkr, + [GCC_CPUSS_AHB_CLK_SRC] = &gcc_cpuss_ahb_clk_src.clkr, + [GCC_CPUSS_RBCPR_CLK] = &gcc_cpuss_rbcpr_clk.clkr, + [GCC_DDRSS_GPU_AXI_CLK] = &gcc_ddrss_gpu_axi_clk.clkr, + [GCC_DISP_GPLL0_CLK_SRC] = &gcc_disp_gpll0_clk_src.clkr, + [GCC_DISP_GPLL0_DIV_CLK_SRC] = &gcc_disp_gpll0_div_clk_src.clkr, + [GCC_DISP_HF_AXI_CLK] = &gcc_disp_hf_axi_clk.clkr, + [GCC_DISP_THROTTLE_HF_AXI_CLK] = &gcc_disp_throttle_hf_axi_clk.clkr, + [GCC_DISP_XO_CLK] = &gcc_disp_xo_clk.clkr, + [GCC_GP1_CLK] = &gcc_gp1_clk.clkr, + [GCC_GP1_CLK_SRC] = &gcc_gp1_clk_src.clkr, + [GCC_GP2_CLK] = &gcc_gp2_clk.clkr, + [GCC_GP2_CLK_SRC] = &gcc_gp2_clk_src.clkr, + [GCC_GP3_CLK] = &gcc_gp3_clk.clkr, + [GCC_GP3_CLK_SRC] = &gcc_gp3_clk_src.clkr, + [GCC_GPU_GPLL0_CLK_SRC] = &gcc_gpu_gpll0_clk_src.clkr, + [GCC_GPU_GPLL0_DIV_CLK_SRC] = &gcc_gpu_gpll0_div_clk_src.clkr, + [GCC_GPU_MEMNOC_GFX_CLK] = &gcc_gpu_memnoc_gfx_clk.clkr, + [GCC_GPU_SNOC_DVM_GFX_CLK] = &gcc_gpu_snoc_dvm_gfx_clk.clkr, + [GCC_NPU_AXI_CLK] = &gcc_npu_axi_clk.clkr, + [GCC_NPU_BWMON_AXI_CLK] = &gcc_npu_bwmon_axi_clk.clkr, + [GCC_NPU_BWMON_DMA_CFG_AHB_CLK] = &gcc_npu_bwmon_dma_cfg_ahb_clk.clkr, + [GCC_NPU_BWMON_DSP_CFG_AHB_CLK] = &gcc_npu_bwmon_dsp_cfg_ahb_clk.clkr, + [GCC_NPU_CFG_AHB_CLK] = &gcc_npu_cfg_ahb_clk.clkr, + [GCC_NPU_DMA_CLK] = &gcc_npu_dma_clk.clkr, + [GCC_NPU_GPLL0_CLK_SRC] = &gcc_npu_gpll0_clk_src.clkr, + [GCC_NPU_GPLL0_DIV_CLK_SRC] = &gcc_npu_gpll0_div_clk_src.clkr, + [GCC_PDM2_CLK] = &gcc_pdm2_clk.clkr, + [GCC_PDM2_CLK_SRC] = &gcc_pdm2_clk_src.clkr, + [GCC_PDM_AHB_CLK] = &gcc_pdm_ahb_clk.clkr, + [GCC_PDM_XO4_CLK] = &gcc_pdm_xo4_clk.clkr, + [GCC_PRNG_AHB_CLK] = &gcc_prng_ahb_clk.clkr, + [GCC_QSPI_CNOC_PERIPH_AHB_CLK] = &gcc_qspi_cnoc_periph_ahb_clk.clkr, + [GCC_QSPI_CORE_CLK] = &gcc_qspi_core_clk.clkr, + [GCC_QSPI_CORE_CLK_SRC] = &gcc_qspi_core_clk_src.clkr, + [GCC_QUPV3_WRAP0_CORE_2X_CLK] = &gcc_qupv3_wrap0_core_2x_clk.clkr, + [GCC_QUPV3_WRAP0_CORE_CLK] = &gcc_qupv3_wrap0_core_clk.clkr, + [GCC_QUPV3_WRAP0_S0_CLK] = &gcc_qupv3_wrap0_s0_clk.clkr, + [GCC_QUPV3_WRAP0_S0_CLK_SRC] = &gcc_qupv3_wrap0_s0_clk_src.clkr, + [GCC_QUPV3_WRAP0_S1_CLK] = &gcc_qupv3_wrap0_s1_clk.clkr, + [GCC_QUPV3_WRAP0_S1_CLK_SRC] = &gcc_qupv3_wrap0_s1_clk_src.clkr, + [GCC_QUPV3_WRAP0_S2_CLK] = &gcc_qupv3_wrap0_s2_clk.clkr, + [GCC_QUPV3_WRAP0_S2_CLK_SRC] = &gcc_qupv3_wrap0_s2_clk_src.clkr, + [GCC_QUPV3_WRAP0_S3_CLK] = &gcc_qupv3_wrap0_s3_clk.clkr, + [GCC_QUPV3_WRAP0_S3_CLK_SRC] = &gcc_qupv3_wrap0_s3_clk_src.clkr, + [GCC_QUPV3_WRAP0_S4_CLK] = &gcc_qupv3_wrap0_s4_clk.clkr, + [GCC_QUPV3_WRAP0_S4_CLK_SRC] = &gcc_qupv3_wrap0_s4_clk_src.clkr, + [GCC_QUPV3_WRAP0_S5_CLK] = &gcc_qupv3_wrap0_s5_clk.clkr, + [GCC_QUPV3_WRAP0_S5_CLK_SRC] = &gcc_qupv3_wrap0_s5_clk_src.clkr, + [GCC_QUPV3_WRAP1_CORE_2X_CLK] = &gcc_qupv3_wrap1_core_2x_clk.clkr, + [GCC_QUPV3_WRAP1_CORE_CLK] = &gcc_qupv3_wrap1_core_clk.clkr, + [GCC_QUPV3_WRAP1_S0_CLK] = &gcc_qupv3_wrap1_s0_clk.clkr, + [GCC_QUPV3_WRAP1_S0_CLK_SRC] = &gcc_qupv3_wrap1_s0_clk_src.clkr, + [GCC_QUPV3_WRAP1_S1_CLK] = &gcc_qupv3_wrap1_s1_clk.clkr, + [GCC_QUPV3_WRAP1_S1_CLK_SRC] = &gcc_qupv3_wrap1_s1_clk_src.clkr, + [GCC_QUPV3_WRAP1_S2_CLK] = &gcc_qupv3_wrap1_s2_clk.clkr, + [GCC_QUPV3_WRAP1_S2_CLK_SRC] = &gcc_qupv3_wrap1_s2_clk_src.clkr, + [GCC_QUPV3_WRAP1_S3_CLK] = &gcc_qupv3_wrap1_s3_clk.clkr, + [GCC_QUPV3_WRAP1_S3_CLK_SRC] = &gcc_qupv3_wrap1_s3_clk_src.clkr, + [GCC_QUPV3_WRAP1_S4_CLK] = &gcc_qupv3_wrap1_s4_clk.clkr, + [GCC_QUPV3_WRAP1_S4_CLK_SRC] = &gcc_qupv3_wrap1_s4_clk_src.clkr, + [GCC_QUPV3_WRAP1_S5_CLK] = &gcc_qupv3_wrap1_s5_clk.clkr, + [GCC_QUPV3_WRAP1_S5_CLK_SRC] = &gcc_qupv3_wrap1_s5_clk_src.clkr, + [GCC_QUPV3_WRAP_0_M_AHB_CLK] = &gcc_qupv3_wrap_0_m_ahb_clk.clkr, + [GCC_QUPV3_WRAP_0_S_AHB_CLK] = &gcc_qupv3_wrap_0_s_ahb_clk.clkr, + [GCC_QUPV3_WRAP_1_M_AHB_CLK] = &gcc_qupv3_wrap_1_m_ahb_clk.clkr, + [GCC_QUPV3_WRAP_1_S_AHB_CLK] = &gcc_qupv3_wrap_1_s_ahb_clk.clkr, + [GCC_SDCC1_AHB_CLK] = &gcc_sdcc1_ahb_clk.clkr, + [GCC_SDCC1_APPS_CLK] = &gcc_sdcc1_apps_clk.clkr, + [GCC_SDCC1_APPS_CLK_SRC] = &gcc_sdcc1_apps_clk_src.clkr, + [GCC_SDCC1_ICE_CORE_CLK] = &gcc_sdcc1_ice_core_clk.clkr, + [GCC_SDCC1_ICE_CORE_CLK_SRC] = &gcc_sdcc1_ice_core_clk_src.clkr, + [GCC_SDCC2_AHB_CLK] = &gcc_sdcc2_ahb_clk.clkr, + [GCC_SDCC2_APPS_CLK] = &gcc_sdcc2_apps_clk.clkr, + [GCC_SDCC2_APPS_CLK_SRC] = &gcc_sdcc2_apps_clk_src.clkr, + [GCC_SYS_NOC_CPUSS_AHB_CLK] = &gcc_sys_noc_cpuss_ahb_clk.clkr, + [GCC_UFS_MEM_CLKREF_CLK] = &gcc_ufs_mem_clkref_clk.clkr, + [GCC_UFS_PHY_AHB_CLK] = &gcc_ufs_phy_ahb_clk.clkr, + [GCC_UFS_PHY_AXI_CLK] = &gcc_ufs_phy_axi_clk.clkr, + [GCC_UFS_PHY_AXI_CLK_SRC] = &gcc_ufs_phy_axi_clk_src.clkr, + [GCC_UFS_PHY_ICE_CORE_CLK] = &gcc_ufs_phy_ice_core_clk.clkr, + [GCC_UFS_PHY_ICE_CORE_CLK_SRC] = &gcc_ufs_phy_ice_core_clk_src.clkr, + [GCC_UFS_PHY_PHY_AUX_CLK] = &gcc_ufs_phy_phy_aux_clk.clkr, + [GCC_UFS_PHY_PHY_AUX_CLK_SRC] = &gcc_ufs_phy_phy_aux_clk_src.clkr, + [GCC_UFS_PHY_RX_SYMBOL_0_CLK] = &gcc_ufs_phy_rx_symbol_0_clk.clkr, + [GCC_UFS_PHY_TX_SYMBOL_0_CLK] = &gcc_ufs_phy_tx_symbol_0_clk.clkr, + [GCC_UFS_PHY_UNIPRO_CORE_CLK] = &gcc_ufs_phy_unipro_core_clk.clkr, + [GCC_UFS_PHY_UNIPRO_CORE_CLK_SRC] = + &gcc_ufs_phy_unipro_core_clk_src.clkr, + [GCC_USB30_PRIM_MASTER_CLK] = &gcc_usb30_prim_master_clk.clkr, + [GCC_USB30_PRIM_MASTER_CLK_SRC] = &gcc_usb30_prim_master_clk_src.clkr, + [GCC_USB30_PRIM_MOCK_UTMI_CLK] = &gcc_usb30_prim_mock_utmi_clk.clkr, + [GCC_USB30_PRIM_MOCK_UTMI_CLK_SRC] = + &gcc_usb30_prim_mock_utmi_clk_src.clkr, + [GCC_USB30_PRIM_SLEEP_CLK] = &gcc_usb30_prim_sleep_clk.clkr, + [GCC_USB3_PRIM_CLKREF_CLK] = &gcc_usb3_prim_clkref_clk.clkr, + [GCC_USB3_PRIM_PHY_AUX_CLK] = &gcc_usb3_prim_phy_aux_clk.clkr, + [GCC_USB3_PRIM_PHY_AUX_CLK_SRC] = &gcc_usb3_prim_phy_aux_clk_src.clkr, + [GCC_USB3_PRIM_PHY_COM_AUX_CLK] = &gcc_usb3_prim_phy_com_aux_clk.clkr, + [GCC_USB3_PRIM_PHY_PIPE_CLK] = &gcc_usb3_prim_phy_pipe_clk.clkr, + [GCC_USB_PHY_CFG_AHB2PHY_CLK] = &gcc_usb_phy_cfg_ahb2phy_clk.clkr, + [GCC_VIDEO_AXI_CLK] = &gcc_video_axi_clk.clkr, + [GCC_VIDEO_GPLL0_DIV_CLK_SRC] = &gcc_video_gpll0_div_clk_src.clkr, + [GCC_VIDEO_THROTTLE_AXI_CLK] = &gcc_video_throttle_axi_clk.clkr, + [GCC_VIDEO_XO_CLK] = &gcc_video_xo_clk.clkr, + [GPLL0] = &gpll0.clkr, + [GPLL0_OUT_EVEN] = &gpll0_out_even.clkr, + [GPLL6] = &gpll6.clkr, + [GPLL7] = &gpll7.clkr, + [GPLL4] = &gpll4.clkr, + [GPLL1] = &gpll1.clkr, +}; + +static const struct qcom_reset_map gcc_sc7180_resets[] = { + [GCC_QUSB2PHY_PRIM_BCR] = { 0x26000 }, + [GCC_QUSB2PHY_SEC_BCR] = { 0x26004 }, + [GCC_UFS_PHY_BCR] = { 0x77000 }, + [GCC_USB30_PRIM_BCR] = { 0xf000 }, + [GCC_USB3_PHY_PRIM_BCR] = { 0x50000 }, + [GCC_USB3PHY_PHY_PRIM_BCR] = { 0x50004 }, + [GCC_USB3_PHY_SEC_BCR] = { 0x5000c }, + [GCC_USB3_DP_PHY_PRIM_BCR] = { 0x50008 }, + [GCC_USB3PHY_PHY_SEC_BCR] = { 0x50010 }, + [GCC_USB3_DP_PHY_SEC_BCR] = { 0x50014 }, + [GCC_USB_PHY_CFG_AHB2PHY_BCR] = { 0x6a000 }, +}; + +static struct clk_rcg_dfs_data gcc_dfs_clocks[] = { + DEFINE_RCG_DFS(gcc_qupv3_wrap0_s0_clk_src), + DEFINE_RCG_DFS(gcc_qupv3_wrap0_s1_clk_src), + DEFINE_RCG_DFS(gcc_qupv3_wrap0_s2_clk_src), + DEFINE_RCG_DFS(gcc_qupv3_wrap0_s3_clk_src), + DEFINE_RCG_DFS(gcc_qupv3_wrap0_s4_clk_src), + DEFINE_RCG_DFS(gcc_qupv3_wrap0_s5_clk_src), + DEFINE_RCG_DFS(gcc_qupv3_wrap1_s0_clk_src), + DEFINE_RCG_DFS(gcc_qupv3_wrap1_s1_clk_src), + DEFINE_RCG_DFS(gcc_qupv3_wrap1_s2_clk_src), + DEFINE_RCG_DFS(gcc_qupv3_wrap1_s3_clk_src), + DEFINE_RCG_DFS(gcc_qupv3_wrap1_s4_clk_src), + DEFINE_RCG_DFS(gcc_qupv3_wrap1_s5_clk_src), +}; + +static const struct regmap_config gcc_sc7180_regmap_config = { + .reg_bits = 32, + .reg_stride = 4, + .val_bits = 32, + .max_register = 0x18208c, + .fast_io = true, +}; + +static const struct qcom_cc_desc gcc_sc7180_desc = { + .config = &gcc_sc7180_regmap_config, + .clk_hws = gcc_sc7180_hws, + .num_clk_hws = ARRAY_SIZE(gcc_sc7180_hws), + .clks = gcc_sc7180_clocks, + .num_clks = ARRAY_SIZE(gcc_sc7180_clocks), + .resets = gcc_sc7180_resets, + .num_resets = ARRAY_SIZE(gcc_sc7180_resets), + .gdscs = gcc_sc7180_gdscs, + .num_gdscs = ARRAY_SIZE(gcc_sc7180_gdscs), +}; + +static const struct of_device_id gcc_sc7180_match_table[] = { + { .compatible = "qcom,gcc-sc7180" }, + { } +}; +MODULE_DEVICE_TABLE(of, gcc_sc7180_match_table); + +static int gcc_sc7180_probe(struct platform_device *pdev) +{ + struct regmap *regmap; + int ret; + + regmap = qcom_cc_map(pdev, &gcc_sc7180_desc); + if (IS_ERR(regmap)) + return PTR_ERR(regmap); + + /* + * Disable the GPLL0 active input to MM blocks, NPU + * and GPU via MISC registers. + */ + regmap_update_bits(regmap, 0x09ffc, 0x3, 0x3); + regmap_update_bits(regmap, 0x4d110, 0x3, 0x3); + regmap_update_bits(regmap, 0x71028, 0x3, 0x3); + + /* + * Keep the clocks always-ON + * GCC_CPUSS_GNOC_CLK, GCC_VIDEO_AHB_CLK, GCC_DISP_AHB_CLK + * GCC_GPU_CFG_AHB_CLK + */ + regmap_update_bits(regmap, 0x48004, BIT(0), BIT(0)); + regmap_update_bits(regmap, 0x0b004, BIT(0), BIT(0)); + regmap_update_bits(regmap, 0x0b00c, BIT(0), BIT(0)); + regmap_update_bits(regmap, 0x71004, BIT(0), BIT(0)); + + ret = qcom_cc_register_rcg_dfs(regmap, gcc_dfs_clocks, + ARRAY_SIZE(gcc_dfs_clocks)); + if (ret) + return ret; + + return qcom_cc_really_probe(pdev, &gcc_sc7180_desc, regmap); +} + +static struct platform_driver gcc_sc7180_driver = { + .probe = gcc_sc7180_probe, + .driver = { + .name = "gcc-sc7180", + .of_match_table = gcc_sc7180_match_table, + }, +}; + +static int __init gcc_sc7180_init(void) +{ + return platform_driver_register(&gcc_sc7180_driver); +} +core_initcall(gcc_sc7180_init); + +static void __exit gcc_sc7180_exit(void) +{ + platform_driver_unregister(&gcc_sc7180_driver); +} +module_exit(gcc_sc7180_exit); + +MODULE_DESCRIPTION("QTI GCC SC7180 Driver"); +MODULE_LICENSE("GPL v2"); -- cgit v1.2.3 From eee28109f871ea43f65cb19f429ed95ddda79343 Mon Sep 17 00:00:00 2001 From: Taniya Das Date: Tue, 29 Oct 2019 23:18:19 +0530 Subject: clk: qcom: clk-rpmh: Add support for RPMHCC for SC7180 Add support for clock RPMh driver to vote for ARC and VRM managed clock resources. Signed-off-by: Taniya Das Link: https://lkml.kernel.org/r/1572371299-16774-4-git-send-email-tdas@codeaurora.org Signed-off-by: Stephen Boyd --- drivers/clk/qcom/clk-rpmh.c | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) (limited to 'drivers/clk') diff --git a/drivers/clk/qcom/clk-rpmh.c b/drivers/clk/qcom/clk-rpmh.c index 96a36f6ff667..7301c7739f29 100644 --- a/drivers/clk/qcom/clk-rpmh.c +++ b/drivers/clk/qcom/clk-rpmh.c @@ -391,6 +391,24 @@ static const struct clk_rpmh_desc clk_rpmh_sm8150 = { .num_clks = ARRAY_SIZE(sm8150_rpmh_clocks), }; +static struct clk_hw *sc7180_rpmh_clocks[] = { + [RPMH_CXO_CLK] = &sdm845_bi_tcxo.hw, + [RPMH_CXO_CLK_A] = &sdm845_bi_tcxo_ao.hw, + [RPMH_LN_BB_CLK2] = &sdm845_ln_bb_clk2.hw, + [RPMH_LN_BB_CLK2_A] = &sdm845_ln_bb_clk2_ao.hw, + [RPMH_LN_BB_CLK3] = &sdm845_ln_bb_clk3.hw, + [RPMH_LN_BB_CLK3_A] = &sdm845_ln_bb_clk3_ao.hw, + [RPMH_RF_CLK1] = &sdm845_rf_clk1.hw, + [RPMH_RF_CLK1_A] = &sdm845_rf_clk1_ao.hw, + [RPMH_RF_CLK2] = &sdm845_rf_clk2.hw, + [RPMH_RF_CLK2_A] = &sdm845_rf_clk2_ao.hw, +}; + +static const struct clk_rpmh_desc clk_rpmh_sc7180 = { + .clks = sc7180_rpmh_clocks, + .num_clks = ARRAY_SIZE(sc7180_rpmh_clocks), +}; + static struct clk_hw *of_clk_rpmh_hw_get(struct of_phandle_args *clkspec, void *data) { @@ -471,6 +489,7 @@ static int clk_rpmh_probe(struct platform_device *pdev) static const struct of_device_id clk_rpmh_match_table[] = { { .compatible = "qcom,sdm845-rpmh-clk", .data = &clk_rpmh_sdm845}, { .compatible = "qcom,sm8150-rpmh-clk", .data = &clk_rpmh_sm8150}, + { .compatible = "qcom,sc7180-rpmh-clk", .data = &clk_rpmh_sc7180}, { } }; MODULE_DEVICE_TABLE(of, clk_rpmh_match_table); -- cgit v1.2.3 From 95183d381a4445cb5e3edbc678a4b6267e50a738 Mon Sep 17 00:00:00 2001 From: Jeffrey Hugo Date: Thu, 7 Nov 2019 11:21:36 -0800 Subject: clk: qcom: Enumerate clocks and reset needed to boot the 8998 modem We need to control five additional clocks and a reset inorder to boot the modem on msm8998. If we can boot the modem, we have a place to run the wlan firmware and get wifi up and running. Signed-off-by: Jeffrey Hugo Link: https://lkml.kernel.org/r/20191107192136.5880-1-jeffrey.l.hugo@gmail.com Signed-off-by: Stephen Boyd --- drivers/clk/qcom/gcc-msm8998.c | 72 ++++++++++++++++++++++++++++ include/dt-bindings/clock/qcom,gcc-msm8998.h | 6 +++ 2 files changed, 78 insertions(+) (limited to 'drivers/clk') diff --git a/drivers/clk/qcom/gcc-msm8998.c b/drivers/clk/qcom/gcc-msm8998.c index 091acd59c1d6..cf31b5d03270 100644 --- a/drivers/clk/qcom/gcc-msm8998.c +++ b/drivers/clk/qcom/gcc-msm8998.c @@ -1266,6 +1266,72 @@ static struct clk_branch gcc_bimc_mss_q6_axi_clk = { }, }; +static struct clk_branch gcc_mss_cfg_ahb_clk = { + .halt_reg = 0x8a000, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x8a000, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_mss_cfg_ahb_clk", + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_mss_snoc_axi_clk = { + .halt_reg = 0x8a03c, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x8a03c, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_mss_snoc_axi_clk", + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_mss_mnoc_bimc_axi_clk = { + .halt_reg = 0x8a004, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x8a004, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_mss_mnoc_bimc_axi_clk", + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_boot_rom_ahb_clk = { + .halt_reg = 0x38004, + .halt_check = BRANCH_HALT_VOTED, + .hwcg_reg = 0x38004, + .hwcg_bit = 1, + .clkr = { + .enable_reg = 0x52004, + .enable_mask = BIT(10), + .hw.init = &(struct clk_init_data){ + .name = "gcc_boot_rom_ahb_clk", + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_mss_gpll0_div_clk_src = { + .halt_check = BRANCH_HALT_DELAY, + .clkr = { + .enable_reg = 0x5200c, + .enable_mask = BIT(2), + .hw.init = &(struct clk_init_data){ + .name = "gcc_mss_gpll0_div_clk_src", + .ops = &clk_branch2_ops, + }, + }, +}; + static struct clk_branch gcc_blsp1_ahb_clk = { .halt_reg = 0x17004, .halt_check = BRANCH_HALT_VOTED, @@ -2832,6 +2898,11 @@ static struct clk_regmap *gcc_msm8998_clocks[] = { [GCC_USB3_CLKREF_CLK] = &gcc_usb3_clkref_clk.clkr, [GCC_PCIE_CLKREF_CLK] = &gcc_pcie_clkref_clk.clkr, [GCC_RX1_USB2_CLKREF_CLK] = &gcc_rx1_usb2_clkref_clk.clkr, + [GCC_MSS_CFG_AHB_CLK] = &gcc_mss_cfg_ahb_clk.clkr, + [GCC_BOOT_ROM_AHB_CLK] = &gcc_boot_rom_ahb_clk.clkr, + [GCC_MSS_GPLL0_DIV_CLK_SRC] = &gcc_mss_gpll0_div_clk_src.clkr, + [GCC_MSS_SNOC_AXI_CLK] = &gcc_mss_snoc_axi_clk.clkr, + [GCC_MSS_MNOC_BIMC_AXI_CLK] = &gcc_mss_mnoc_bimc_axi_clk.clkr, }; static struct gdsc *gcc_msm8998_gdscs[] = { @@ -2928,6 +2999,7 @@ static const struct qcom_reset_map gcc_msm8998_resets[] = { [GCC_GPU_BCR] = { 0x71000 }, [GCC_SPSS_BCR] = { 0x72000 }, [GCC_OBT_ODT_BCR] = { 0x73000 }, + [GCC_MSS_RESTART] = { 0x79000 }, [GCC_VS_BCR] = { 0x7a000 }, [GCC_MSS_VS_RESET] = { 0x7a100 }, [GCC_GPU_VS_RESET] = { 0x7a104 }, diff --git a/include/dt-bindings/clock/qcom,gcc-msm8998.h b/include/dt-bindings/clock/qcom,gcc-msm8998.h index ab376262fcea..de1d8a1f5966 100644 --- a/include/dt-bindings/clock/qcom,gcc-msm8998.h +++ b/include/dt-bindings/clock/qcom,gcc-msm8998.h @@ -177,6 +177,11 @@ #define GCC_UFS_CLKREF_CLK 168 #define GCC_PCIE_CLKREF_CLK 169 #define GCC_RX1_USB2_CLKREF_CLK 170 +#define GCC_MSS_CFG_AHB_CLK 171 +#define GCC_BOOT_ROM_AHB_CLK 172 +#define GCC_MSS_GPLL0_DIV_CLK_SRC 173 +#define GCC_MSS_SNOC_AXI_CLK 174 +#define GCC_MSS_MNOC_BIMC_AXI_CLK 175 #define PCIE_0_GDSC 0 #define UFS_GDSC 1 @@ -290,5 +295,6 @@ #define GCC_MSMPU_BCR 105 #define GCC_QUSB2PHY_PRIM_BCR 106 #define GCC_QUSB2PHY_SEC_BCR 107 +#define GCC_MSS_RESTART 108 #endif -- cgit v1.2.3 From ba1d366de261981c0dd04fac44d2ce3a5eba2eaa Mon Sep 17 00:00:00 2001 From: Jeffrey Hugo Date: Thu, 7 Nov 2019 11:06:15 -0800 Subject: clk: qcom: smd: Add missing pnoc clock When MSM8998 support was added, and analysis was done to determine what clocks would be consumed. That analysis had a flaw, which caused the pnoc to be skipped. The pnoc clock needs to be on to access the uart for the console. The clock is on from boot, but has no consumer votes in the RPM. When we attempt to boot the modem, it causes the RPM to turn off pnoc, which kills our access to the console and causes CPU hangs. We need pnoc to be defined, so that clk_smd_rpm_handoff() will put in an implicit vote for linux and prevent issues when booting modem. Hopefully pnoc can be consumed by the interconnect framework in future so that Linux can rely on explicit votes. Fixes: 6131dc81211c ("clk: qcom: smd: Add support for MSM8998 rpm clocks") Signed-off-by: Jeffrey Hugo Link: https://lkml.kernel.org/r/20191107190615.5656-1-jeffrey.l.hugo@gmail.com Signed-off-by: Stephen Boyd --- drivers/clk/qcom/clk-smd-rpm.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'drivers/clk') diff --git a/drivers/clk/qcom/clk-smd-rpm.c b/drivers/clk/qcom/clk-smd-rpm.c index fef5e8157061..930fa4a4c52a 100644 --- a/drivers/clk/qcom/clk-smd-rpm.c +++ b/drivers/clk/qcom/clk-smd-rpm.c @@ -648,6 +648,7 @@ static const struct rpm_smd_clk_desc rpm_clk_qcs404 = { }; /* msm8998 */ +DEFINE_CLK_SMD_RPM(msm8998, pcnoc_clk, pcnoc_a_clk, QCOM_SMD_RPM_BUS_CLK, 0); DEFINE_CLK_SMD_RPM(msm8998, snoc_clk, snoc_a_clk, QCOM_SMD_RPM_BUS_CLK, 1); DEFINE_CLK_SMD_RPM(msm8998, cnoc_clk, cnoc_a_clk, QCOM_SMD_RPM_BUS_CLK, 2); DEFINE_CLK_SMD_RPM(msm8998, ce1_clk, ce1_a_clk, QCOM_SMD_RPM_CE_CLK, 0); @@ -670,6 +671,8 @@ DEFINE_CLK_SMD_RPM_XO_BUFFER_PINCTRL(msm8998, rf_clk2_pin, rf_clk2_a_pin, 5); DEFINE_CLK_SMD_RPM_XO_BUFFER(msm8998, rf_clk3, rf_clk3_a, 6); DEFINE_CLK_SMD_RPM_XO_BUFFER_PINCTRL(msm8998, rf_clk3_pin, rf_clk3_a_pin, 6); static struct clk_smd_rpm *msm8998_clks[] = { + [RPM_SMD_PCNOC_CLK] = &msm8998_pcnoc_clk, + [RPM_SMD_PCNOC_A_CLK] = &msm8998_pcnoc_a_clk, [RPM_SMD_SNOC_CLK] = &msm8998_snoc_clk, [RPM_SMD_SNOC_A_CLK] = &msm8998_snoc_a_clk, [RPM_SMD_CNOC_CLK] = &msm8998_cnoc_clk, -- cgit v1.2.3 From efd164b5520afd6fb2883b68e0d408a7de29c491 Mon Sep 17 00:00:00 2001 From: Jeffrey Hugo Date: Thu, 31 Oct 2019 11:57:15 -0700 Subject: clk: qcom: Allow constant ratio freq tables for rcg Some RCGs (the gfx_3d_src_clk in msm8998 for example) are basically just some constant ratio from the input across the entire frequency range. It would be great if we could specify the frequency table as a single entry constant ratio instead of a long list, ie: { .src = P_GPUPLL0_OUT_EVEN, .pre_div = 3 }, { } So, lets support that. We need to fix a corner case in qcom_find_freq() where if the freq table is non-null, but has no frequencies, we end up returning an "entry" before the table array, which is bad. Then, we need ignore the freq from the table, and instead base everything on the requested freq. Suggested-by: Stephen Boyd Signed-off-by: Jeffrey Hugo Link: https://lkml.kernel.org/r/20191031185715.15504-1-jeffrey.l.hugo@gmail.com Signed-off-by: Stephen Boyd --- drivers/clk/qcom/clk-rcg2.c | 2 ++ drivers/clk/qcom/common.c | 3 +++ 2 files changed, 5 insertions(+) (limited to 'drivers/clk') diff --git a/drivers/clk/qcom/clk-rcg2.c b/drivers/clk/qcom/clk-rcg2.c index 99c4bfa5365f..8f4b9bec2956 100644 --- a/drivers/clk/qcom/clk-rcg2.c +++ b/drivers/clk/qcom/clk-rcg2.c @@ -220,6 +220,8 @@ static int _freq_tbl_determine_rate(struct clk_hw *hw, const struct freq_tbl *f, if (clk_flags & CLK_SET_RATE_PARENT) { rate = f->freq; if (f->pre_div) { + if (!rate) + rate = req->rate; rate /= 2; rate *= f->pre_div + 1; } diff --git a/drivers/clk/qcom/common.c b/drivers/clk/qcom/common.c index caba81d18c70..60d2a78d1395 100644 --- a/drivers/clk/qcom/common.c +++ b/drivers/clk/qcom/common.c @@ -29,6 +29,9 @@ struct freq_tbl *qcom_find_freq(const struct freq_tbl *f, unsigned long rate) if (!f) return NULL; + if (!f->freq) + return f; + for (; f->freq; f++) if (rate <= f->freq) return f; -- cgit v1.2.3 From 3f7df5baa2593d86c0dd206c3e63a76fce0efa4b Mon Sep 17 00:00:00 2001 From: Jeffrey Hugo Date: Thu, 31 Oct 2019 11:57:33 -0700 Subject: clk: qcom: Add MSM8998 GPU Clock Controller (GPUCC) driver The GPUCC manages the clocks for the Adreno GPU found on MSM8998. Signed-off-by: Jeffrey Hugo Link: https://lkml.kernel.org/r/20191031185733.15553-1-jeffrey.l.hugo@gmail.com Signed-off-by: Stephen Boyd --- drivers/clk/qcom/Kconfig | 9 ++ drivers/clk/qcom/Makefile | 1 + drivers/clk/qcom/gpucc-msm8998.c | 338 +++++++++++++++++++++++++++++++++++++++ 3 files changed, 348 insertions(+) create mode 100644 drivers/clk/qcom/gpucc-msm8998.c (limited to 'drivers/clk') diff --git a/drivers/clk/qcom/Kconfig b/drivers/clk/qcom/Kconfig index 5d8cc03457ca..3b33ef129274 100644 --- a/drivers/clk/qcom/Kconfig +++ b/drivers/clk/qcom/Kconfig @@ -220,6 +220,15 @@ config MSM_GCC_8998 Say Y if you want to use peripheral devices such as UART, SPI, i2c, USB, UFS, SD/eMMC, PCIe, etc. +config MSM_GPUCC_8998 + tristate "MSM8998 Graphics Clock Controller" + select MSM_GCC_8998 + select QCOM_GDSC + help + Support for the graphics clock controller on MSM8998 devices. + Say Y if you want to support graphics controller devices and + functionality such as 3D graphics. + config QCS_GCC_404 tristate "QCS404 Global Clock Controller" help diff --git a/drivers/clk/qcom/Makefile b/drivers/clk/qcom/Makefile index 80a30976abe8..d899661d0f44 100644 --- a/drivers/clk/qcom/Makefile +++ b/drivers/clk/qcom/Makefile @@ -33,6 +33,7 @@ obj-$(CONFIG_MSM_GCC_8994) += gcc-msm8994.o obj-$(CONFIG_MSM_GCC_8996) += gcc-msm8996.o obj-$(CONFIG_MSM_LCC_8960) += lcc-msm8960.o obj-$(CONFIG_MSM_GCC_8998) += gcc-msm8998.o +obj-$(CONFIG_MSM_GPUCC_8998) += gpucc-msm8998.o obj-$(CONFIG_MSM_MMCC_8960) += mmcc-msm8960.o obj-$(CONFIG_MSM_MMCC_8974) += mmcc-msm8974.o obj-$(CONFIG_MSM_MMCC_8996) += mmcc-msm8996.o diff --git a/drivers/clk/qcom/gpucc-msm8998.c b/drivers/clk/qcom/gpucc-msm8998.c new file mode 100644 index 000000000000..e5e2492b20c5 --- /dev/null +++ b/drivers/clk/qcom/gpucc-msm8998.c @@ -0,0 +1,338 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (c) 2019, Jeffrey Hugo + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include "common.h" +#include "clk-regmap.h" +#include "clk-regmap-divider.h" +#include "clk-alpha-pll.h" +#include "clk-rcg.h" +#include "clk-branch.h" +#include "reset.h" +#include "gdsc.h" + +enum { + P_XO, + P_GPLL0, + P_GPUPLL0_OUT_EVEN, +}; + +/* Instead of going directly to the block, XO is routed through this branch */ +static struct clk_branch gpucc_cxo_clk = { + .halt_reg = 0x1020, + .clkr = { + .enable_reg = 0x1020, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gpucc_cxo_clk", + .parent_data = &(const struct clk_parent_data){ + .fw_name = "xo", + .name = "xo" + }, + .num_parents = 1, + .ops = &clk_branch2_ops, + .flags = CLK_IS_CRITICAL, + }, + }, +}; + +static const struct clk_div_table post_div_table_fabia_even[] = { + { 0x0, 1 }, + { 0x1, 2 }, + { 0x3, 4 }, + { 0x7, 8 }, + { } +}; + +static struct clk_alpha_pll gpupll0 = { + .offset = 0x0, + .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_FABIA], + .clkr.hw.init = &(struct clk_init_data){ + .name = "gpupll0", + .parent_hws = (const struct clk_hw *[]){ &gpucc_cxo_clk.clkr.hw }, + .num_parents = 1, + .ops = &clk_alpha_pll_fixed_fabia_ops, + }, +}; + +static struct clk_alpha_pll_postdiv gpupll0_out_even = { + .offset = 0x0, + .post_div_shift = 8, + .post_div_table = post_div_table_fabia_even, + .num_post_div = ARRAY_SIZE(post_div_table_fabia_even), + .width = 4, + .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_FABIA], + .clkr.hw.init = &(struct clk_init_data){ + .name = "gpupll0_out_even", + .parent_hws = (const struct clk_hw *[]){ &gpupll0.clkr.hw }, + .num_parents = 1, + .ops = &clk_alpha_pll_postdiv_fabia_ops, + }, +}; + +static const struct parent_map gpu_xo_gpll0_map[] = { + { P_XO, 0 }, + { P_GPLL0, 5 }, +}; + +static const struct clk_parent_data gpu_xo_gpll0[] = { + { .hw = &gpucc_cxo_clk.clkr.hw }, + { .fw_name = "gpll0", .name = "gpll0" }, +}; + +static const struct parent_map gpu_xo_gpupll0_map[] = { + { P_XO, 0 }, + { P_GPUPLL0_OUT_EVEN, 1 }, +}; + +static const struct clk_parent_data gpu_xo_gpupll0[] = { + { .hw = &gpucc_cxo_clk.clkr.hw }, + { .hw = &gpupll0_out_even.clkr.hw }, +}; + +static const struct freq_tbl ftbl_rbcpr_clk_src[] = { + F(19200000, P_XO, 1, 0, 0), + F(50000000, P_GPLL0, 12, 0, 0), + { } +}; + +static struct clk_rcg2 rbcpr_clk_src = { + .cmd_rcgr = 0x1030, + .hid_width = 5, + .parent_map = gpu_xo_gpll0_map, + .freq_tbl = ftbl_rbcpr_clk_src, + .clkr.hw.init = &(struct clk_init_data){ + .name = "rbcpr_clk_src", + .parent_data = gpu_xo_gpll0, + .num_parents = 2, + .ops = &clk_rcg2_ops, + }, +}; + +static const struct freq_tbl ftbl_gfx3d_clk_src[] = { + { .src = P_GPUPLL0_OUT_EVEN, .pre_div = 3 }, + { } +}; + +static struct clk_rcg2 gfx3d_clk_src = { + .cmd_rcgr = 0x1070, + .hid_width = 5, + .parent_map = gpu_xo_gpupll0_map, + .freq_tbl = ftbl_gfx3d_clk_src, + .clkr.hw.init = &(struct clk_init_data){ + .name = "gfx3d_clk_src", + .parent_data = gpu_xo_gpupll0, + .num_parents = 2, + .ops = &clk_rcg2_ops, + .flags = CLK_SET_RATE_PARENT | CLK_OPS_PARENT_ENABLE, + }, +}; + +static const struct freq_tbl ftbl_rbbmtimer_clk_src[] = { + F(19200000, P_XO, 1, 0, 0), + { } +}; + +static struct clk_rcg2 rbbmtimer_clk_src = { + .cmd_rcgr = 0x10b0, + .hid_width = 5, + .parent_map = gpu_xo_gpll0_map, + .freq_tbl = ftbl_rbbmtimer_clk_src, + .clkr.hw.init = &(struct clk_init_data){ + .name = "rbbmtimer_clk_src", + .parent_data = gpu_xo_gpll0, + .num_parents = 2, + .ops = &clk_rcg2_ops, + }, +}; + +static const struct freq_tbl ftbl_gfx3d_isense_clk_src[] = { + F(19200000, P_XO, 1, 0, 0), + F(40000000, P_GPLL0, 15, 0, 0), + F(200000000, P_GPLL0, 3, 0, 0), + F(300000000, P_GPLL0, 2, 0, 0), + { } +}; + +static struct clk_rcg2 gfx3d_isense_clk_src = { + .cmd_rcgr = 0x1100, + .hid_width = 5, + .parent_map = gpu_xo_gpll0_map, + .freq_tbl = ftbl_gfx3d_isense_clk_src, + .clkr.hw.init = &(struct clk_init_data){ + .name = "gfx3d_isense_clk_src", + .parent_data = gpu_xo_gpll0, + .num_parents = 2, + .ops = &clk_rcg2_ops, + }, +}; + +static struct clk_branch rbcpr_clk = { + .halt_reg = 0x1054, + .clkr = { + .enable_reg = 0x1054, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "rbcpr_clk", + .parent_hws = (const struct clk_hw *[]){ &rbcpr_clk_src.clkr.hw }, + .num_parents = 1, + .ops = &clk_branch2_ops, + .flags = CLK_SET_RATE_PARENT, + }, + }, +}; + +static struct clk_branch gfx3d_clk = { + .halt_reg = 0x1098, + .clkr = { + .enable_reg = 0x1098, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gfx3d_clk", + .parent_hws = (const struct clk_hw *[]){ &gfx3d_clk_src.clkr.hw }, + .num_parents = 1, + .ops = &clk_branch2_ops, + .flags = CLK_SET_RATE_PARENT, + }, + }, +}; + +static struct clk_branch rbbmtimer_clk = { + .halt_reg = 0x10d0, + .clkr = { + .enable_reg = 0x10d0, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "rbbmtimer_clk", + .parent_hws = (const struct clk_hw *[]){ &rbbmtimer_clk_src.clkr.hw }, + .num_parents = 1, + .ops = &clk_branch2_ops, + .flags = CLK_SET_RATE_PARENT, + }, + }, +}; + +static struct clk_branch gfx3d_isense_clk = { + .halt_reg = 0x1124, + .clkr = { + .enable_reg = 0x1124, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gfx3d_isense_clk", + .parent_hws = (const struct clk_hw *[]){ &gfx3d_isense_clk_src.clkr.hw }, + .num_parents = 1, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct gdsc gpu_cx_gdsc = { + .gdscr = 0x1004, + .pd = { + .name = "gpu_cx", + }, + .pwrsts = PWRSTS_OFF_ON, +}; + +static struct gdsc gpu_gx_gdsc = { + .gdscr = 0x1094, + .clamp_io_ctrl = 0x130, + .pd = { + .name = "gpu_gx", + }, + .parent = &gpu_cx_gdsc.pd, + .pwrsts = PWRSTS_OFF_ON, + .flags = CLAMP_IO | AON_RESET, +}; + +static struct clk_regmap *gpucc_msm8998_clocks[] = { + [GPUPLL0] = &gpupll0.clkr, + [GPUPLL0_OUT_EVEN] = &gpupll0_out_even.clkr, + [RBCPR_CLK_SRC] = &rbcpr_clk_src.clkr, + [GFX3D_CLK_SRC] = &gfx3d_clk_src.clkr, + [RBBMTIMER_CLK_SRC] = &rbbmtimer_clk_src.clkr, + [GFX3D_ISENSE_CLK_SRC] = &gfx3d_isense_clk_src.clkr, + [RBCPR_CLK] = &rbcpr_clk.clkr, + [GFX3D_CLK] = &gfx3d_clk.clkr, + [RBBMTIMER_CLK] = &rbbmtimer_clk.clkr, + [GFX3D_ISENSE_CLK] = &gfx3d_isense_clk.clkr, + [GPUCC_CXO_CLK] = &gpucc_cxo_clk.clkr, +}; + +static struct gdsc *gpucc_msm8998_gdscs[] = { + [GPU_CX_GDSC] = &gpu_cx_gdsc, + [GPU_GX_GDSC] = &gpu_gx_gdsc, +}; + +static const struct qcom_reset_map gpucc_msm8998_resets[] = { + [GPU_CX_BCR] = { 0x1000 }, + [RBCPR_BCR] = { 0x1050 }, + [GPU_GX_BCR] = { 0x1090 }, + [GPU_ISENSE_BCR] = { 0x1120 }, +}; + +static const struct regmap_config gpucc_msm8998_regmap_config = { + .reg_bits = 32, + .reg_stride = 4, + .val_bits = 32, + .max_register = 0x9000, + .fast_io = true, +}; + +static const struct qcom_cc_desc gpucc_msm8998_desc = { + .config = &gpucc_msm8998_regmap_config, + .clks = gpucc_msm8998_clocks, + .num_clks = ARRAY_SIZE(gpucc_msm8998_clocks), + .resets = gpucc_msm8998_resets, + .num_resets = ARRAY_SIZE(gpucc_msm8998_resets), + .gdscs = gpucc_msm8998_gdscs, + .num_gdscs = ARRAY_SIZE(gpucc_msm8998_gdscs), +}; + +static const struct of_device_id gpucc_msm8998_match_table[] = { + { .compatible = "qcom,msm8998-gpucc" }, + { } +}; +MODULE_DEVICE_TABLE(of, gpucc_msm8998_match_table); + +static int gpucc_msm8998_probe(struct platform_device *pdev) +{ + struct regmap *regmap; + + regmap = qcom_cc_map(pdev, &gpucc_msm8998_desc); + if (IS_ERR(regmap)) + return PTR_ERR(regmap); + + /* force periph logic on to avoid perf counter corruption */ + regmap_write_bits(regmap, gfx3d_clk.clkr.enable_reg, BIT(13), BIT(13)); + /* tweak droop detector (GPUCC_GPU_DD_WRAP_CTRL) to reduce leakage */ + regmap_write_bits(regmap, gfx3d_clk.clkr.enable_reg, BIT(0), BIT(0)); + + return qcom_cc_really_probe(pdev, &gpucc_msm8998_desc, regmap); +} + +static struct platform_driver gpucc_msm8998_driver = { + .probe = gpucc_msm8998_probe, + .driver = { + .name = "gpucc-msm8998", + .of_match_table = gpucc_msm8998_match_table, + }, +}; +module_platform_driver(gpucc_msm8998_driver); + +MODULE_DESCRIPTION("QCOM GPUCC MSM8998 Driver"); +MODULE_LICENSE("GPL v2"); -- cgit v1.2.3 From e620a1e061c4738e26c3edf2abaae7842532cd80 Mon Sep 17 00:00:00 2001 From: Stephen Kitt Date: Fri, 27 Sep 2019 20:51:10 +0200 Subject: drivers/clk: convert VL struct to struct_size There are a few manually-calculated variable-length struct allocations left, this converts them to use struct_size. Found with the following git grep command git grep -A1 'kzalloc.*sizeof[^_].*+' Signed-off-by: Stephen Kitt Link: https://lkml.kernel.org/r/20190927185110.29897-1-steve@sk2.org Acked-by: Gustavo A. R. Silva [sboyd@kernel.org: Add grep command] Signed-off-by: Stephen Boyd --- drivers/clk/at91/sckc.c | 3 +-- drivers/clk/imgtec/clk-boston.c | 3 +-- drivers/clk/ingenic/tcu.c | 3 +-- drivers/clk/mvebu/ap-cpu-clk.c | 4 ++-- drivers/clk/mvebu/cp110-system-controller.c | 4 ++-- drivers/clk/samsung/clk.c | 3 +-- drivers/clk/uniphier/clk-uniphier-core.c | 3 +-- 7 files changed, 9 insertions(+), 14 deletions(-) (limited to 'drivers/clk') diff --git a/drivers/clk/at91/sckc.c b/drivers/clk/at91/sckc.c index 9bfe9a28294a..5ad6180449cb 100644 --- a/drivers/clk/at91/sckc.c +++ b/drivers/clk/at91/sckc.c @@ -478,8 +478,7 @@ static void __init of_sam9x60_sckc_setup(struct device_node *np) if (IS_ERR(slow_osc)) goto unregister_slow_rc; - clk_data = kzalloc(sizeof(*clk_data) + (2 * sizeof(struct clk_hw *)), - GFP_KERNEL); + clk_data = kzalloc(struct_size(clk_data, hws, 2), GFP_KERNEL); if (!clk_data) goto unregister_slow_osc; diff --git a/drivers/clk/imgtec/clk-boston.c b/drivers/clk/imgtec/clk-boston.c index 33ab4ff61165..b00cbd045af5 100644 --- a/drivers/clk/imgtec/clk-boston.c +++ b/drivers/clk/imgtec/clk-boston.c @@ -58,8 +58,7 @@ static void __init clk_boston_setup(struct device_node *np) cpu_div = ext_field(mmcmdiv, BOSTON_PLAT_MMCMDIV_CLK1DIV); cpu_freq = mult_frac(in_freq, mul, cpu_div); - onecell = kzalloc(sizeof(*onecell) + - (BOSTON_CLK_COUNT * sizeof(struct clk_hw *)), + onecell = kzalloc(struct_size(onecell, hws, BOSTON_CLK_COUNT), GFP_KERNEL); if (!onecell) return; diff --git a/drivers/clk/ingenic/tcu.c b/drivers/clk/ingenic/tcu.c index a1a5f9cb439e..ad7daa494fd4 100644 --- a/drivers/clk/ingenic/tcu.c +++ b/drivers/clk/ingenic/tcu.c @@ -358,8 +358,7 @@ static int __init ingenic_tcu_probe(struct device_node *np) } } - tcu->clocks = kzalloc(sizeof(*tcu->clocks) + - sizeof(*tcu->clocks->hws) * TCU_CLK_COUNT, + tcu->clocks = kzalloc(struct_size(tcu->clocks, hws, TCU_CLK_COUNT), GFP_KERNEL); if (!tcu->clocks) { ret = -ENOMEM; diff --git a/drivers/clk/mvebu/ap-cpu-clk.c b/drivers/clk/mvebu/ap-cpu-clk.c index af5e5acad370..6b394302c76a 100644 --- a/drivers/clk/mvebu/ap-cpu-clk.c +++ b/drivers/clk/mvebu/ap-cpu-clk.c @@ -274,8 +274,8 @@ static int ap_cpu_clock_probe(struct platform_device *pdev) if (!ap_cpu_clk) return -ENOMEM; - ap_cpu_data = devm_kzalloc(dev, sizeof(*ap_cpu_data) + - sizeof(struct clk_hw *) * nclusters, + ap_cpu_data = devm_kzalloc(dev, struct_size(ap_cpu_data, hws, + nclusters), GFP_KERNEL); if (!ap_cpu_data) return -ENOMEM; diff --git a/drivers/clk/mvebu/cp110-system-controller.c b/drivers/clk/mvebu/cp110-system-controller.c index 808463276145..84c8900542e4 100644 --- a/drivers/clk/mvebu/cp110-system-controller.c +++ b/drivers/clk/mvebu/cp110-system-controller.c @@ -235,8 +235,8 @@ static int cp110_syscon_common_probe(struct platform_device *pdev, if (ret) return ret; - cp110_clk_data = devm_kzalloc(dev, sizeof(*cp110_clk_data) + - sizeof(struct clk_hw *) * CP110_CLK_NUM, + cp110_clk_data = devm_kzalloc(dev, struct_size(cp110_clk_data, hws, + CP110_CLK_NUM), GFP_KERNEL); if (!cp110_clk_data) return -ENOMEM; diff --git a/drivers/clk/samsung/clk.c b/drivers/clk/samsung/clk.c index e544a38106dd..dad31308c071 100644 --- a/drivers/clk/samsung/clk.c +++ b/drivers/clk/samsung/clk.c @@ -60,8 +60,7 @@ struct samsung_clk_provider *__init samsung_clk_init(struct device_node *np, struct samsung_clk_provider *ctx; int i; - ctx = kzalloc(sizeof(struct samsung_clk_provider) + - sizeof(*ctx->clk_data.hws) * nr_clks, GFP_KERNEL); + ctx = kzalloc(struct_size(ctx, clk_data.hws, nr_clks), GFP_KERNEL); if (!ctx) panic("could not allocate clock provider context.\n"); diff --git a/drivers/clk/uniphier/clk-uniphier-core.c b/drivers/clk/uniphier/clk-uniphier-core.c index c6aaca73cf86..12380236d7ab 100644 --- a/drivers/clk/uniphier/clk-uniphier-core.c +++ b/drivers/clk/uniphier/clk-uniphier-core.c @@ -64,8 +64,7 @@ static int uniphier_clk_probe(struct platform_device *pdev) for (p = data; p->name; p++) clk_num = max(clk_num, p->idx + 1); - hw_data = devm_kzalloc(dev, - sizeof(*hw_data) + clk_num * sizeof(struct clk_hw *), + hw_data = devm_kzalloc(dev, struct_size(hw_data, hws, clk_num), GFP_KERNEL); if (!hw_data) return -ENOMEM; -- cgit v1.2.3 From 3696eebd810cf084b3662d3c3b85cd84b61090f3 Mon Sep 17 00:00:00 2001 From: Andrew Jeffery Date: Thu, 10 Oct 2019 12:37:25 +1030 Subject: clk: ast2600: Add RMII RCLK gates for all four MACs RCLK is a fixed 50MHz clock derived from HPLL/HCLK that is described by a single gate for each MAC. Signed-off-by: Andrew Jeffery Link: https://lkml.kernel.org/r/20191010020725.3990-3-andrew@aj.id.au Reviewed-by: Joel Stanley Signed-off-by: Stephen Boyd --- drivers/clk/clk-ast2600.c | 47 ++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 46 insertions(+), 1 deletion(-) (limited to 'drivers/clk') diff --git a/drivers/clk/clk-ast2600.c b/drivers/clk/clk-ast2600.c index 1c1bb39bb04e..85acc7cdc83c 100644 --- a/drivers/clk/clk-ast2600.c +++ b/drivers/clk/clk-ast2600.c @@ -15,7 +15,7 @@ #include "clk-aspeed.h" -#define ASPEED_G6_NUM_CLKS 67 +#define ASPEED_G6_NUM_CLKS 71 #define ASPEED_G6_SILICON_REV 0x004 @@ -40,6 +40,9 @@ #define ASPEED_G6_STRAP1 0x500 +#define ASPEED_MAC12_CLK_DLY 0x340 +#define ASPEED_MAC34_CLK_DLY 0x350 + /* Globally visible clocks */ static DEFINE_SPINLOCK(aspeed_g6_clk_lock); @@ -485,6 +488,11 @@ static int aspeed_g6_clk_probe(struct platform_device *pdev) return PTR_ERR(hw); aspeed_g6_clk_data->hws[ASPEED_CLK_SDIO] = hw; + /* MAC1/2 RMII 50MHz RCLK */ + hw = clk_hw_register_fixed_rate(dev, "mac12rclk", "hpll", 0, 50000000); + if (IS_ERR(hw)) + return PTR_ERR(hw); + /* MAC1/2 AHB bus clock divider */ hw = clk_hw_register_divider_table(dev, "mac12", "hpll", 0, scu_g6_base + ASPEED_G6_CLK_SELECTION1, 16, 3, 0, @@ -494,6 +502,27 @@ static int aspeed_g6_clk_probe(struct platform_device *pdev) return PTR_ERR(hw); aspeed_g6_clk_data->hws[ASPEED_CLK_MAC12] = hw; + /* RMII1 50MHz (RCLK) output enable */ + hw = clk_hw_register_gate(dev, "mac1rclk", "mac12rclk", 0, + scu_g6_base + ASPEED_MAC12_CLK_DLY, 29, 0, + &aspeed_g6_clk_lock); + if (IS_ERR(hw)) + return PTR_ERR(hw); + aspeed_g6_clk_data->hws[ASPEED_CLK_MAC1RCLK] = hw; + + /* RMII2 50MHz (RCLK) output enable */ + hw = clk_hw_register_gate(dev, "mac2rclk", "mac12rclk", 0, + scu_g6_base + ASPEED_MAC12_CLK_DLY, 30, 0, + &aspeed_g6_clk_lock); + if (IS_ERR(hw)) + return PTR_ERR(hw); + aspeed_g6_clk_data->hws[ASPEED_CLK_MAC2RCLK] = hw; + + /* MAC1/2 RMII 50MHz RCLK */ + hw = clk_hw_register_fixed_rate(dev, "mac34rclk", "hclk", 0, 50000000); + if (IS_ERR(hw)) + return PTR_ERR(hw); + /* MAC3/4 AHB bus clock divider */ hw = clk_hw_register_divider_table(dev, "mac34", "hpll", 0, scu_g6_base + 0x310, 24, 3, 0, @@ -503,6 +532,22 @@ static int aspeed_g6_clk_probe(struct platform_device *pdev) return PTR_ERR(hw); aspeed_g6_clk_data->hws[ASPEED_CLK_MAC34] = hw; + /* RMII3 50MHz (RCLK) output enable */ + hw = clk_hw_register_gate(dev, "mac3rclk", "mac34rclk", 0, + scu_g6_base + ASPEED_MAC34_CLK_DLY, 29, 0, + &aspeed_g6_clk_lock); + if (IS_ERR(hw)) + return PTR_ERR(hw); + aspeed_g6_clk_data->hws[ASPEED_CLK_MAC3RCLK] = hw; + + /* RMII4 50MHz (RCLK) output enable */ + hw = clk_hw_register_gate(dev, "mac4rclk", "mac34rclk", 0, + scu_g6_base + ASPEED_MAC34_CLK_DLY, 30, 0, + &aspeed_g6_clk_lock); + if (IS_ERR(hw)) + return PTR_ERR(hw); + aspeed_g6_clk_data->hws[ASPEED_CLK_MAC4RCLK] = hw; + /* LPC Host (LHCLK) clock divider */ hw = clk_hw_register_divider_table(dev, "lhclk", "hpll", 0, scu_g6_base + ASPEED_G6_CLK_SELECTION1, 20, 3, 0, -- cgit v1.2.3 From 7f6ac72946b88b89ee44c1c527aa8591ac5ffcbe Mon Sep 17 00:00:00 2001 From: Stephen Kitt Date: Sat, 19 Oct 2019 16:06:34 +0200 Subject: clk/ti/adpll: allocate room for terminating null The buffer allocated in ti_adpll_clk_get_name doesn't account for the terminating null. This patch switches to devm_kasprintf to avoid overflowing. Signed-off-by: Stephen Kitt Link: https://lkml.kernel.org/r/20191019140634.15596-1-steve@sk2.org Acked-by: Tony Lindgren Signed-off-by: Stephen Boyd --- drivers/clk/ti/adpll.c | 11 ++--------- 1 file changed, 2 insertions(+), 9 deletions(-) (limited to 'drivers/clk') diff --git a/drivers/clk/ti/adpll.c b/drivers/clk/ti/adpll.c index fdfb90058504..bb2f2836dab2 100644 --- a/drivers/clk/ti/adpll.c +++ b/drivers/clk/ti/adpll.c @@ -194,15 +194,8 @@ static const char *ti_adpll_clk_get_name(struct ti_adpll_data *d, if (err) return NULL; } else { - const char *base_name = "adpll"; - char *buf; - - buf = devm_kzalloc(d->dev, 8 + 1 + strlen(base_name) + 1 + - strlen(postfix), GFP_KERNEL); - if (!buf) - return NULL; - sprintf(buf, "%08lx.%s.%s", d->pa, base_name, postfix); - name = buf; + name = devm_kasprintf(d->dev, GFP_KERNEL, "%08lx.adpll.%s", + d->pa, postfix); } return name; -- cgit v1.2.3 From f5790382edef4e97514dc7af75344b06b8cac3ee Mon Sep 17 00:00:00 2001 From: Stephen Boyd Date: Thu, 7 Nov 2019 13:40:18 -0800 Subject: clk: qcom: rpmh: Reuse sdm845 clks for sm8150 The SM8150 list of clks is almost the same as the list for SDM845, except there isn't an IPA clk. Just point to the SDM845 clks from the SM8150 list for now so we can reduce the amount of struct bloat in this driver. Suggested-by: Vinod Koul Cc: Taniya Das Signed-off-by: Stephen Boyd Link: https://lkml.kernel.org/r/20191107214018.184105-1-sboyd@kernel.org Reviewed-by: Vinod Koul --- drivers/clk/qcom/clk-rpmh.c | 34 ++++++++++++++-------------------- 1 file changed, 14 insertions(+), 20 deletions(-) (limited to 'drivers/clk') diff --git a/drivers/clk/qcom/clk-rpmh.c b/drivers/clk/qcom/clk-rpmh.c index 7301c7739f29..2dbbe47e8d4f 100644 --- a/drivers/clk/qcom/clk-rpmh.c +++ b/drivers/clk/qcom/clk-rpmh.c @@ -334,13 +334,14 @@ static const struct clk_ops clk_rpmh_bcm_ops = { .recalc_rate = clk_rpmh_bcm_recalc_rate, }; -/* Resource name must match resource id present in cmd-db. */ +/* Resource name must match resource id present in cmd-db */ DEFINE_CLK_RPMH_ARC(sdm845, bi_tcxo, bi_tcxo_ao, "xo.lvl", 0x3, 2); DEFINE_CLK_RPMH_VRM(sdm845, ln_bb_clk2, ln_bb_clk2_ao, "lnbclka2", 2); DEFINE_CLK_RPMH_VRM(sdm845, ln_bb_clk3, ln_bb_clk3_ao, "lnbclka3", 2); DEFINE_CLK_RPMH_VRM(sdm845, rf_clk1, rf_clk1_ao, "rfclka1", 1); DEFINE_CLK_RPMH_VRM(sdm845, rf_clk2, rf_clk2_ao, "rfclka2", 1); DEFINE_CLK_RPMH_VRM(sdm845, rf_clk3, rf_clk3_ao, "rfclka3", 1); +DEFINE_CLK_RPMH_VRM(sm8150, rf_clk3, rf_clk3_ao, "rfclka3", 1); DEFINE_CLK_RPMH_BCM(sdm845, ipa, "IP0"); static struct clk_hw *sdm845_rpmh_clocks[] = { @@ -364,26 +365,19 @@ static const struct clk_rpmh_desc clk_rpmh_sdm845 = { .num_clks = ARRAY_SIZE(sdm845_rpmh_clocks), }; -DEFINE_CLK_RPMH_ARC(sm8150, bi_tcxo, bi_tcxo_ao, "xo.lvl", 0x3, 2); -DEFINE_CLK_RPMH_VRM(sm8150, ln_bb_clk2, ln_bb_clk2_ao, "lnbclka2", 2); -DEFINE_CLK_RPMH_VRM(sm8150, ln_bb_clk3, ln_bb_clk3_ao, "lnbclka3", 2); -DEFINE_CLK_RPMH_VRM(sm8150, rf_clk1, rf_clk1_ao, "rfclka1", 1); -DEFINE_CLK_RPMH_VRM(sm8150, rf_clk2, rf_clk2_ao, "rfclka2", 1); -DEFINE_CLK_RPMH_VRM(sm8150, rf_clk3, rf_clk3_ao, "rfclka3", 1); - static struct clk_hw *sm8150_rpmh_clocks[] = { - [RPMH_CXO_CLK] = &sm8150_bi_tcxo.hw, - [RPMH_CXO_CLK_A] = &sm8150_bi_tcxo_ao.hw, - [RPMH_LN_BB_CLK2] = &sm8150_ln_bb_clk2.hw, - [RPMH_LN_BB_CLK2_A] = &sm8150_ln_bb_clk2_ao.hw, - [RPMH_LN_BB_CLK3] = &sm8150_ln_bb_clk3.hw, - [RPMH_LN_BB_CLK3_A] = &sm8150_ln_bb_clk3_ao.hw, - [RPMH_RF_CLK1] = &sm8150_rf_clk1.hw, - [RPMH_RF_CLK1_A] = &sm8150_rf_clk1_ao.hw, - [RPMH_RF_CLK2] = &sm8150_rf_clk2.hw, - [RPMH_RF_CLK2_A] = &sm8150_rf_clk2_ao.hw, - [RPMH_RF_CLK3] = &sm8150_rf_clk3.hw, - [RPMH_RF_CLK3_A] = &sm8150_rf_clk3_ao.hw, + [RPMH_CXO_CLK] = &sdm845_bi_tcxo.hw, + [RPMH_CXO_CLK_A] = &sdm845_bi_tcxo_ao.hw, + [RPMH_LN_BB_CLK2] = &sdm845_ln_bb_clk2.hw, + [RPMH_LN_BB_CLK2_A] = &sdm845_ln_bb_clk2_ao.hw, + [RPMH_LN_BB_CLK3] = &sdm845_ln_bb_clk3.hw, + [RPMH_LN_BB_CLK3_A] = &sdm845_ln_bb_clk3_ao.hw, + [RPMH_RF_CLK1] = &sdm845_rf_clk1.hw, + [RPMH_RF_CLK1_A] = &sdm845_rf_clk1_ao.hw, + [RPMH_RF_CLK2] = &sdm845_rf_clk2.hw, + [RPMH_RF_CLK2_A] = &sdm845_rf_clk2_ao.hw, + [RPMH_RF_CLK3] = &sdm845_rf_clk3.hw, + [RPMH_RF_CLK3_A] = &sdm845_rf_clk3_ao.hw, }; static const struct clk_rpmh_desc clk_rpmh_sm8150 = { -- cgit v1.2.3 From 801b787a693ba643b23608cf2bf8dcfab3608795 Mon Sep 17 00:00:00 2001 From: Andrew Jeffery Date: Thu, 10 Oct 2019 12:36:55 +1030 Subject: clk: aspeed: Add RMII RCLK gates for both AST2500 MACs RCLK is a fixed 50MHz clock derived from HPLL that is described by a single gate for each MAC. Signed-off-by: Andrew Jeffery Link: https://lkml.kernel.org/r/20191010020655.3776-3-andrew@aj.id.au Reviewed-by: Joel Stanley Signed-off-by: Stephen Boyd --- drivers/clk/clk-aspeed.c | 27 ++++++++++++++++++++++++++- 1 file changed, 26 insertions(+), 1 deletion(-) (limited to 'drivers/clk') diff --git a/drivers/clk/clk-aspeed.c b/drivers/clk/clk-aspeed.c index abf06fb6453e..411ff5fb2c07 100644 --- a/drivers/clk/clk-aspeed.c +++ b/drivers/clk/clk-aspeed.c @@ -14,7 +14,7 @@ #include "clk-aspeed.h" -#define ASPEED_NUM_CLKS 36 +#define ASPEED_NUM_CLKS 38 #define ASPEED_RESET2_OFFSET 32 @@ -28,6 +28,7 @@ #define AST2400_HPLL_BYPASS_EN BIT(17) #define ASPEED_MISC_CTRL 0x2c #define UART_DIV13_EN BIT(12) +#define ASPEED_MAC_CLK_DLY 0x48 #define ASPEED_STRAP 0x70 #define CLKIN_25MHZ_EN BIT(23) #define AST2400_CLK_SOURCE_SEL BIT(18) @@ -462,6 +463,30 @@ static int aspeed_clk_probe(struct platform_device *pdev) return PTR_ERR(hw); aspeed_clk_data->hws[ASPEED_CLK_MAC] = hw; + if (of_device_is_compatible(pdev->dev.of_node, "aspeed,ast2500-scu")) { + /* RMII 50MHz RCLK */ + hw = clk_hw_register_fixed_rate(dev, "mac12rclk", "hpll", 0, + 50000000); + if (IS_ERR(hw)) + return PTR_ERR(hw); + + /* RMII1 50MHz (RCLK) output enable */ + hw = clk_hw_register_gate(dev, "mac1rclk", "mac12rclk", 0, + scu_base + ASPEED_MAC_CLK_DLY, 29, 0, + &aspeed_clk_lock); + if (IS_ERR(hw)) + return PTR_ERR(hw); + aspeed_clk_data->hws[ASPEED_CLK_MAC1RCLK] = hw; + + /* RMII2 50MHz (RCLK) output enable */ + hw = clk_hw_register_gate(dev, "mac2rclk", "mac12rclk", 0, + scu_base + ASPEED_MAC_CLK_DLY, 30, 0, + &aspeed_clk_lock); + if (IS_ERR(hw)) + return PTR_ERR(hw); + aspeed_clk_data->hws[ASPEED_CLK_MAC2RCLK] = hw; + } + /* LPC Host (LHCLK) clock divider */ hw = clk_hw_register_divider_table(dev, "lhclk", "hpll", 0, scu_base + ASPEED_CLK_SELECTION, 20, 3, 0, -- cgit v1.2.3