From 002b831076722f3a966a58defd1dc6976a46c109 Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Mon, 26 Feb 2024 11:59:45 +0100 Subject: [PATCH 001/118] dt-bindings: clock: r9a07g043-cpg: Annotate RZ/G2UL-only core clocks The M2 (CRU main clock), M3 (LCDC Video Clock), and AT (Cortex-A55 Debug clock) core clocks are only present on RZ/G2UL, not on RZ/Five. Annotate this in the comments, like is already done for module clocks and resets. Signed-off-by: Geert Uytterhoeven Reviewed-by: Lad Prabhakar Acked-by: Rob Herring Link: https://lore.kernel.org/r/ffcdcd479c76b92f67481836a33ec86e97f85634.1708944903.git.geert+renesas@glider.be --- include/dt-bindings/clock/r9a07g043-cpg.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/include/dt-bindings/clock/r9a07g043-cpg.h b/include/dt-bindings/clock/r9a07g043-cpg.h index 77cde8effdc7..a64139fec815 100644 --- a/include/dt-bindings/clock/r9a07g043-cpg.h +++ b/include/dt-bindings/clock/r9a07g043-cpg.h @@ -16,15 +16,15 @@ #define R9A07G043_CLK_SD0 5 #define R9A07G043_CLK_SD1 6 #define R9A07G043_CLK_M0 7 -#define R9A07G043_CLK_M2 8 -#define R9A07G043_CLK_M3 9 +#define R9A07G043_CLK_M2 8 /* RZ/G2UL Only */ +#define R9A07G043_CLK_M3 9 /* RZ/G2UL Only */ #define R9A07G043_CLK_HP 10 #define R9A07G043_CLK_TSU 11 #define R9A07G043_CLK_ZT 12 #define R9A07G043_CLK_P0 13 #define R9A07G043_CLK_P1 14 #define R9A07G043_CLK_P2 15 -#define R9A07G043_CLK_AT 16 +#define R9A07G043_CLK_AT 16 /* RZ/G2UL Only */ #define R9A07G043_OSCCLK 17 #define R9A07G043_CLK_P0_DIV2 18 From c69fe2ae2e7f203bbfbd6dd1757d3b290bce8509 Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Wed, 6 Mar 2024 11:52:04 +0100 Subject: [PATCH 002/118] clk: renesas: r8a779h0: Add thermal clock MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add the module clock used by the Thermal Sensor/Chip Internal Voltage Monitor/Core Voltage Monitor (THS/CIVM/CVM) on the Renesas R-Car V4M (R8A779H0) SoC. Based on a patch in the BSP by Cong Dang. Signed-off-by: Geert Uytterhoeven Reviewed-by: Niklas Söderlund Link: https://lore.kernel.org/r/befac3e8342cd552f580d34be863ef84403c541f.1709722056.git.geert+renesas@glider.be --- drivers/clk/renesas/r8a779h0-cpg-mssr.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/clk/renesas/r8a779h0-cpg-mssr.c b/drivers/clk/renesas/r8a779h0-cpg-mssr.c index 71f67a1c86d8..5c48e645f0c3 100644 --- a/drivers/clk/renesas/r8a779h0-cpg-mssr.c +++ b/drivers/clk/renesas/r8a779h0-cpg-mssr.c @@ -192,6 +192,7 @@ static const struct mssr_mod_clk r8a779h0_mod_clks[] = { DEF_MOD("pfc0", 915, R8A779H0_CLK_CP), DEF_MOD("pfc1", 916, R8A779H0_CLK_CP), DEF_MOD("pfc2", 917, R8A779H0_CLK_CP), + DEF_MOD("tsc2:tsc1", 919, R8A779H0_CLK_CL16M), }; /* From b8ae9d344d09b73361493054fbde15b9f5ebe91a Mon Sep 17 00:00:00 2001 From: Paul Barker Date: Wed, 20 Mar 2024 08:28:30 +0000 Subject: [PATCH 003/118] clk: renesas: r9a07g043: Mark mod_clks and resets arrays as const The r9a07g043_mod_clks and r9a07g043_resets arrays describe the module clocks and reset signals (respectively) in this SoC and do not change at runtime. Signed-off-by: Paul Barker Reviewed-by: Geert Uytterhoeven Link: https://lore.kernel.org/r/20240320082831.9666-1-paul.barker.ct@bp.renesas.com Signed-off-by: Geert Uytterhoeven --- drivers/clk/renesas/r9a07g043-cpg.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/clk/renesas/r9a07g043-cpg.c b/drivers/clk/renesas/r9a07g043-cpg.c index 33532673d25d..e36d2ec2c0f5 100644 --- a/drivers/clk/renesas/r9a07g043-cpg.c +++ b/drivers/clk/renesas/r9a07g043-cpg.c @@ -149,7 +149,7 @@ static const struct cpg_core_clk r9a07g043_core_clks[] __initconst = { #endif }; -static struct rzg2l_mod_clk r9a07g043_mod_clks[] = { +static const struct rzg2l_mod_clk r9a07g043_mod_clks[] = { #ifdef CONFIG_ARM64 DEF_MOD("gic", R9A07G043_GIC600_GICCLK, R9A07G043_CLK_P1, 0x514, 0), @@ -282,7 +282,7 @@ static struct rzg2l_mod_clk r9a07g043_mod_clks[] = { 0x5ac, 0), }; -static struct rzg2l_reset r9a07g043_resets[] = { +static const struct rzg2l_reset r9a07g043_resets[] = { #ifdef CONFIG_ARM64 DEF_RST(R9A07G043_GIC600_GICRESET_N, 0x814, 0), DEF_RST(R9A07G043_GIC600_DBG_GICRESET_N, 0x814, 1), From e56321e48db4c57c9f389592ef6bbfb24affd0fd Mon Sep 17 00:00:00 2001 From: Paul Barker Date: Wed, 20 Mar 2024 08:28:31 +0000 Subject: [PATCH 004/118] clk: renesas: r9a07g044: Mark resets array as const The r9a07g044_resets array describes the reset signals in this SoC and does not change at runtime. Signed-off-by: Paul Barker Reviewed-by: Geert Uytterhoeven Link: https://lore.kernel.org/r/20240320082831.9666-2-paul.barker.ct@bp.renesas.com Signed-off-by: Geert Uytterhoeven --- drivers/clk/renesas/r9a07g044-cpg.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/clk/renesas/r9a07g044-cpg.c b/drivers/clk/renesas/r9a07g044-cpg.c index 48404cafea3f..f6df3f7a31b5 100644 --- a/drivers/clk/renesas/r9a07g044-cpg.c +++ b/drivers/clk/renesas/r9a07g044-cpg.c @@ -368,7 +368,7 @@ static const struct { #endif }; -static struct rzg2l_reset r9a07g044_resets[] = { +static const struct rzg2l_reset r9a07g044_resets[] = { DEF_RST(R9A07G044_GIC600_GICRESET_N, 0x814, 0), DEF_RST(R9A07G044_GIC600_DBG_GICRESET_N, 0x814, 1), DEF_RST(R9A07G044_IA55_RESETN, 0x818, 0), From 7fa37084061fef80dab81bc062c6ec0fa8c26b2d Mon Sep 17 00:00:00 2001 From: Sam Protsenko Date: Thu, 29 Feb 2024 19:51:16 -0600 Subject: [PATCH 005/118] clk: samsung: Implement manual PLL control for ARM64 SoCs Some ARM64 Exynos chips are capable to control PLL clocks automatically. For those chips, whether the PLL is controlled automatically or manually is chosen in PLL_CON1 register with next bits: [28] ENABLE_AUTOMATIC_CLKGATING [1] MANUAL_PLL_CTRL [0] AUTO_PLL_CTRL The bl2 bootloader sets 0x10000001 value for some PLL_CON1 registers, which means any attempt to control those PLLs manually (e.g. disabling/enabling those PLLs or changing MUX parent clocks) would lead to PLL lock timeout with error message like this: Could not lock PLL ... At the moment, all Samsung clock drivers implement manual clock control. So in order to make it possible to control PLLs, corresponding PLL_CON1 registers should be set to 0x2 first. Some older ARM64 chips don't implement the automatic clock control though. It also might be desirable to configure some PLLs for manual control, while keeping the default configuration for the rest. So it'd convenient to choose this PLL mode for each CMU separately. Introduce .manual_plls field to CMU structure to choose the PLL control mode. Because it'll be initialized with "false" in all existing CMU structures by default, it won't affect any existing clock drivers, allowing for this feature to be enabled gradually when it's needed with no change for the rest of users. In case .manual_plls is set, set PLL_CON1 registers to manual control, akin to what's already done for gate clocks in exynos_arm64_init_clocks(). Of course, PLL_CON1 registers should be added to corresponding struct samsung_cmu_info::clk_regs array to make sure they get initialized. No functional change. This patch adds a feature, but doesn't enable it for any users. Signed-off-by: Sam Protsenko Link: https://lore.kernel.org/r/20240301015118.30072-1-semen.protsenko@linaro.org Signed-off-by: Krzysztof Kozlowski --- drivers/clk/samsung/clk-exynos-arm64.c | 56 +++++++++++++++++++------- drivers/clk/samsung/clk.h | 4 ++ 2 files changed, 45 insertions(+), 15 deletions(-) diff --git a/drivers/clk/samsung/clk-exynos-arm64.c b/drivers/clk/samsung/clk-exynos-arm64.c index 6fb7194df7ab..bf7de21f329e 100644 --- a/drivers/clk/samsung/clk-exynos-arm64.c +++ b/drivers/clk/samsung/clk-exynos-arm64.c @@ -17,10 +17,17 @@ #include "clk-exynos-arm64.h" +/* PLL register bits */ +#define PLL_CON1_MANUAL BIT(1) + /* Gate register bits */ #define GATE_MANUAL BIT(20) #define GATE_ENABLE_HWACG BIT(28) +/* PLL_CONx_PLL register offsets range */ +#define PLL_CON_OFF_START 0x100 +#define PLL_CON_OFF_END 0x600 + /* Gate register offsets range */ #define GATE_OFF_START 0x2000 #define GATE_OFF_END 0x2fff @@ -38,17 +45,36 @@ struct exynos_arm64_cmu_data { struct samsung_clk_provider *ctx; }; +/* Check if the register offset is a GATE register */ +static bool is_gate_reg(unsigned long off) +{ + return off >= GATE_OFF_START && off <= GATE_OFF_END; +} + +/* Check if the register offset is a PLL_CONx register */ +static bool is_pll_conx_reg(unsigned long off) +{ + return off >= PLL_CON_OFF_START && off <= PLL_CON_OFF_END; +} + +/* Check if the register offset is a PLL_CON1 register */ +static bool is_pll_con1_reg(unsigned long off) +{ + return is_pll_conx_reg(off) && (off & 0xf) == 0x4 && !(off & 0x10); +} + /** * exynos_arm64_init_clocks - Set clocks initial configuration - * @np: CMU device tree node with "reg" property (CMU addr) - * @reg_offs: Register offsets array for clocks to init - * @reg_offs_len: Number of register offsets in reg_offs array + * @np: CMU device tree node with "reg" property (CMU addr) + * @cmu: CMU data * - * Set manual control mode for all gate clocks. + * Set manual control mode for all gate and PLL clocks. */ static void __init exynos_arm64_init_clocks(struct device_node *np, - const unsigned long *reg_offs, size_t reg_offs_len) + const struct samsung_cmu_info *cmu) { + const unsigned long *reg_offs = cmu->clk_regs; + size_t reg_offs_len = cmu->nr_clk_regs; void __iomem *reg_base; size_t i; @@ -60,14 +86,14 @@ static void __init exynos_arm64_init_clocks(struct device_node *np, void __iomem *reg = reg_base + reg_offs[i]; u32 val; - /* Modify only gate clock registers */ - if (reg_offs[i] < GATE_OFF_START || reg_offs[i] > GATE_OFF_END) - continue; - - val = readl(reg); - val |= GATE_MANUAL; - val &= ~GATE_ENABLE_HWACG; - writel(val, reg); + if (cmu->manual_plls && is_pll_con1_reg(reg_offs[i])) { + writel(PLL_CON1_MANUAL, reg); + } else if (is_gate_reg(reg_offs[i])) { + val = readl(reg); + val |= GATE_MANUAL; + val &= ~GATE_ENABLE_HWACG; + writel(val, reg); + } } iounmap(reg_base); @@ -177,7 +203,7 @@ void __init exynos_arm64_register_cmu(struct device *dev, pr_err("%s: could not enable bus clock %s; err = %d\n", __func__, cmu->clk_name, err); - exynos_arm64_init_clocks(np, cmu->clk_regs, cmu->nr_clk_regs); + exynos_arm64_init_clocks(np, cmu); samsung_cmu_register_one(np, cmu); } @@ -224,7 +250,7 @@ int __init exynos_arm64_register_cmu_pm(struct platform_device *pdev, __func__, cmu->clk_name, ret); if (set_manual) - exynos_arm64_init_clocks(np, cmu->clk_regs, cmu->nr_clk_regs); + exynos_arm64_init_clocks(np, cmu); reg_base = devm_platform_ioremap_resource(pdev, 0); if (IS_ERR(reg_base)) diff --git a/drivers/clk/samsung/clk.h b/drivers/clk/samsung/clk.h index a763309e6f12..a70bd7cce39f 100644 --- a/drivers/clk/samsung/clk.h +++ b/drivers/clk/samsung/clk.h @@ -330,6 +330,7 @@ struct samsung_clock_reg_cache { * @suspend_regs: list of clock registers to set before suspend * @nr_suspend_regs: count of clock registers in @suspend_regs * @clk_name: name of the parent clock needed for CMU register access + * @manual_plls: Enable manual control for PLL clocks */ struct samsung_cmu_info { const struct samsung_pll_clock *pll_clks; @@ -354,6 +355,9 @@ struct samsung_cmu_info { const struct samsung_clk_reg_dump *suspend_regs; unsigned int nr_suspend_regs; const char *clk_name; + + /* ARM64 Exynos CMUs */ + bool manual_plls; }; struct samsung_clk_provider *samsung_clk_init(struct device *dev, From dedf87341ad66fa6889fedcf610b6941d2d3bcb6 Mon Sep 17 00:00:00 2001 From: Sam Protsenko Date: Thu, 29 Feb 2024 19:51:17 -0600 Subject: [PATCH 006/118] clk: samsung: exynos850: Add CMU_CPUCL0 and CMU_CPUCL1 Implement support for CPU clock management units: - CMU_CPUCL0: clocks for cluster 0: 4 x Cortex-A55 (cpu0..cpu3) - CMU_CPUCL1: clocks for cluster 1: 4 x Cortex-A55 (cpu4..cpu7) CPU PLLs are generating main CPU clocks for each cluster, and there are alternate ("switch") clocks that can be used temporarily while re-configuring the PLL for a new rate. ACLK, ATCLK, PCLKDBG and PERIPHCLK clocks are driving corresponding buses. CLK_CLUSTERx_SCLK are actual leaf CPU clocks and should be used to change CPU rates. Also some CoreSight clocks can be derived from DBG_USER (debug clock). PLL table was extracted from ECT table. ECT stands for "Exynos Characteristic Table", it's a Samsung specific binary data populated by BL2 bootloader in RAM at 0x90000000 address, containing PLL tables for various CMUs and other hardware specific information. The particular PLL type used in CMU_CPUCL0 and CMU_CPUCL1 (pll0822x) is an integer PLL with middle FVCO. The equation to calculate its output rate is: fout = fin * M / (P*2^S) where: fin = 26 MHz (OSCCLK frequency) M = 64..1023 P = 1..63 S = 0..6 The PLL table tries to keep "P" value low to reduce the locking time, which for pll0822x is "t = P * 150" (in OSCCLK cycles). Signed-off-by: Sam Protsenko Link: https://lore.kernel.org/r/20240301015118.30072-2-semen.protsenko@linaro.org Signed-off-by: Krzysztof Kozlowski --- drivers/clk/samsung/clk-exynos850.c | 440 +++++++++++++++++++++++++++- 1 file changed, 439 insertions(+), 1 deletion(-) diff --git a/drivers/clk/samsung/clk-exynos850.c b/drivers/clk/samsung/clk-exynos850.c index 82cfa22c0788..6215471c4ac6 100644 --- a/drivers/clk/samsung/clk-exynos850.c +++ b/drivers/clk/samsung/clk-exynos850.c @@ -14,13 +14,16 @@ #include #include "clk.h" +#include "clk-cpu.h" #include "clk-exynos-arm64.h" /* NOTE: Must be equal to the last clock ID increased by one */ -#define CLKS_NR_TOP (CLK_DOUT_G3D_SWITCH + 1) +#define CLKS_NR_TOP (CLK_DOUT_CPUCL1_SWITCH + 1) #define CLKS_NR_APM (CLK_GOUT_SYSREG_APM_PCLK + 1) #define CLKS_NR_AUD (CLK_GOUT_AUD_CMU_AUD_PCLK + 1) #define CLKS_NR_CMGP (CLK_GOUT_SYSREG_CMGP_PCLK + 1) +#define CLKS_NR_CPUCL0 (CLK_CLUSTER0_SCLK + 1) +#define CLKS_NR_CPUCL1 (CLK_CLUSTER1_SCLK + 1) #define CLKS_NR_G3D (CLK_GOUT_G3D_SYSREG_PCLK + 1) #define CLKS_NR_HSI (CLK_GOUT_HSI_CMU_HSI_PCLK + 1) #define CLKS_NR_IS (CLK_GOUT_IS_SYSREG_PCLK + 1) @@ -47,6 +50,10 @@ #define CLK_CON_MUX_MUX_CLKCMU_CORE_CCI 0x1018 #define CLK_CON_MUX_MUX_CLKCMU_CORE_MMC_EMBD 0x101c #define CLK_CON_MUX_MUX_CLKCMU_CORE_SSS 0x1020 +#define CLK_CON_MUX_MUX_CLKCMU_CPUCL0_DBG 0x1024 +#define CLK_CON_MUX_MUX_CLKCMU_CPUCL0_SWITCH 0x1028 +#define CLK_CON_MUX_MUX_CLKCMU_CPUCL1_DBG 0x102c +#define CLK_CON_MUX_MUX_CLKCMU_CPUCL1_SWITCH 0x1030 #define CLK_CON_MUX_MUX_CLKCMU_DPU 0x1034 #define CLK_CON_MUX_MUX_CLKCMU_G3D_SWITCH 0x1038 #define CLK_CON_MUX_MUX_CLKCMU_HSI_BUS 0x103c @@ -69,6 +76,10 @@ #define CLK_CON_DIV_CLKCMU_CORE_CCI 0x1824 #define CLK_CON_DIV_CLKCMU_CORE_MMC_EMBD 0x1828 #define CLK_CON_DIV_CLKCMU_CORE_SSS 0x182c +#define CLK_CON_DIV_CLKCMU_CPUCL0_DBG 0x1830 +#define CLK_CON_DIV_CLKCMU_CPUCL0_SWITCH 0x1834 +#define CLK_CON_DIV_CLKCMU_CPUCL1_DBG 0x1838 +#define CLK_CON_DIV_CLKCMU_CPUCL1_SWITCH 0x183c #define CLK_CON_DIV_CLKCMU_DPU 0x1840 #define CLK_CON_DIV_CLKCMU_G3D_SWITCH 0x1844 #define CLK_CON_DIV_CLKCMU_HSI_BUS 0x1848 @@ -97,6 +108,10 @@ #define CLK_CON_GAT_GATE_CLKCMU_CORE_CCI 0x2020 #define CLK_CON_GAT_GATE_CLKCMU_CORE_MMC_EMBD 0x2024 #define CLK_CON_GAT_GATE_CLKCMU_CORE_SSS 0x2028 +#define CLK_CON_GAT_GATE_CLKCMU_CPUCL0_DBG 0x202c +#define CLK_CON_GAT_GATE_CLKCMU_CPUCL0_SWITCH 0x2030 +#define CLK_CON_GAT_GATE_CLKCMU_CPUCL1_DBG 0x2034 +#define CLK_CON_GAT_GATE_CLKCMU_CPUCL1_SWITCH 0x2038 #define CLK_CON_GAT_GATE_CLKCMU_DPU 0x203c #define CLK_CON_GAT_GATE_CLKCMU_G3D_SWITCH 0x2040 #define CLK_CON_GAT_GATE_CLKCMU_HSI_BUS 0x2044 @@ -130,6 +145,10 @@ static const unsigned long top_clk_regs[] __initconst = { CLK_CON_MUX_MUX_CLKCMU_CORE_CCI, CLK_CON_MUX_MUX_CLKCMU_CORE_MMC_EMBD, CLK_CON_MUX_MUX_CLKCMU_CORE_SSS, + CLK_CON_MUX_MUX_CLKCMU_CPUCL0_DBG, + CLK_CON_MUX_MUX_CLKCMU_CPUCL0_SWITCH, + CLK_CON_MUX_MUX_CLKCMU_CPUCL1_DBG, + CLK_CON_MUX_MUX_CLKCMU_CPUCL1_SWITCH, CLK_CON_MUX_MUX_CLKCMU_DPU, CLK_CON_MUX_MUX_CLKCMU_G3D_SWITCH, CLK_CON_MUX_MUX_CLKCMU_HSI_BUS, @@ -152,6 +171,10 @@ static const unsigned long top_clk_regs[] __initconst = { CLK_CON_DIV_CLKCMU_CORE_CCI, CLK_CON_DIV_CLKCMU_CORE_MMC_EMBD, CLK_CON_DIV_CLKCMU_CORE_SSS, + CLK_CON_DIV_CLKCMU_CPUCL0_DBG, + CLK_CON_DIV_CLKCMU_CPUCL0_SWITCH, + CLK_CON_DIV_CLKCMU_CPUCL1_DBG, + CLK_CON_DIV_CLKCMU_CPUCL1_SWITCH, CLK_CON_DIV_CLKCMU_DPU, CLK_CON_DIV_CLKCMU_G3D_SWITCH, CLK_CON_DIV_CLKCMU_HSI_BUS, @@ -180,6 +203,10 @@ static const unsigned long top_clk_regs[] __initconst = { CLK_CON_GAT_GATE_CLKCMU_CORE_CCI, CLK_CON_GAT_GATE_CLKCMU_CORE_MMC_EMBD, CLK_CON_GAT_GATE_CLKCMU_CORE_SSS, + CLK_CON_GAT_GATE_CLKCMU_CPUCL0_DBG, + CLK_CON_GAT_GATE_CLKCMU_CPUCL0_SWITCH, + CLK_CON_GAT_GATE_CLKCMU_CPUCL1_DBG, + CLK_CON_GAT_GATE_CLKCMU_CPUCL1_SWITCH, CLK_CON_GAT_GATE_CLKCMU_DPU, CLK_CON_GAT_GATE_CLKCMU_G3D_SWITCH, CLK_CON_GAT_GATE_CLKCMU_HSI_BUS, @@ -234,6 +261,14 @@ PNAME(mout_core_mmc_embd_p) = { "oscclk", "dout_shared0_div2", "oscclk", "oscclk" }; PNAME(mout_core_sss_p) = { "dout_shared0_div3", "dout_shared1_div3", "dout_shared0_div4", "dout_shared1_div4" }; +/* List of parent clocks for Muxes in CMU_TOP: for CMU_CPUCL0 */ +PNAME(mout_cpucl0_switch_p) = { "fout_shared0_pll", "fout_shared1_pll", + "dout_shared0_div2", "dout_shared1_div2" }; +PNAME(mout_cpucl0_dbg_p) = { "dout_shared0_div4", "dout_shared1_div4" }; +/* List of parent clocks for Muxes in CMU_TOP: for CMU_CPUCL1 */ +PNAME(mout_cpucl1_switch_p) = { "fout_shared0_pll", "fout_shared1_pll", + "dout_shared0_div2", "dout_shared1_div2" }; +PNAME(mout_cpucl1_dbg_p) = { "dout_shared0_div4", "dout_shared1_div4" }; /* List of parent clocks for Muxes in CMU_TOP: for CMU_G3D */ PNAME(mout_g3d_switch_p) = { "dout_shared0_div2", "dout_shared1_div2", "dout_shared0_div3", "dout_shared1_div3" }; @@ -300,6 +335,18 @@ static const struct samsung_mux_clock top_mux_clks[] __initconst = { MUX(CLK_MOUT_CORE_SSS, "mout_core_sss", mout_core_sss_p, CLK_CON_MUX_MUX_CLKCMU_CORE_SSS, 0, 2), + /* CPUCL0 */ + MUX(CLK_MOUT_CPUCL0_DBG, "mout_cpucl0_dbg", mout_cpucl0_dbg_p, + CLK_CON_MUX_MUX_CLKCMU_CPUCL0_DBG, 0, 1), + MUX(CLK_MOUT_CPUCL0_SWITCH, "mout_cpucl0_switch", mout_cpucl0_switch_p, + CLK_CON_MUX_MUX_CLKCMU_CPUCL0_SWITCH, 0, 2), + + /* CPUCL1 */ + MUX(CLK_MOUT_CPUCL1_DBG, "mout_cpucl1_dbg", mout_cpucl1_dbg_p, + CLK_CON_MUX_MUX_CLKCMU_CPUCL1_DBG, 0, 1), + MUX(CLK_MOUT_CPUCL1_SWITCH, "mout_cpucl1_switch", mout_cpucl1_switch_p, + CLK_CON_MUX_MUX_CLKCMU_CPUCL1_SWITCH, 0, 2), + /* DPU */ MUX(CLK_MOUT_DPU, "mout_dpu", mout_dpu_p, CLK_CON_MUX_MUX_CLKCMU_DPU, 0, 2), @@ -378,6 +425,18 @@ static const struct samsung_div_clock top_div_clks[] __initconst = { DIV(CLK_DOUT_CORE_SSS, "dout_core_sss", "gout_core_sss", CLK_CON_DIV_CLKCMU_CORE_SSS, 0, 4), + /* CPUCL0 */ + DIV(CLK_DOUT_CPUCL0_DBG, "dout_cpucl0_dbg", "gout_cpucl0_dbg", + CLK_CON_DIV_CLKCMU_CPUCL0_DBG, 0, 3), + DIV(CLK_DOUT_CPUCL0_SWITCH, "dout_cpucl0_switch", "gout_cpucl0_switch", + CLK_CON_DIV_CLKCMU_CPUCL0_SWITCH, 0, 3), + + /* CPUCL1 */ + DIV(CLK_DOUT_CPUCL1_DBG, "dout_cpucl1_dbg", "gout_cpucl1_dbg", + CLK_CON_DIV_CLKCMU_CPUCL1_DBG, 0, 3), + DIV(CLK_DOUT_CPUCL1_SWITCH, "dout_cpucl1_switch", "gout_cpucl1_switch", + CLK_CON_DIV_CLKCMU_CPUCL1_SWITCH, 0, 3), + /* DPU */ DIV(CLK_DOUT_DPU, "dout_dpu", "gout_dpu", CLK_CON_DIV_CLKCMU_DPU, 0, 4), @@ -442,6 +501,18 @@ static const struct samsung_gate_clock top_gate_clks[] __initconst = { GATE(CLK_GOUT_AUD, "gout_aud", "mout_aud", CLK_CON_GAT_GATE_CLKCMU_AUD, 21, 0, 0), + /* CPUCL0 */ + GATE(CLK_GOUT_CPUCL0_DBG, "gout_cpucl0_dbg", "mout_cpucl0_dbg", + CLK_CON_GAT_GATE_CLKCMU_CPUCL0_DBG, 21, 0, 0), + GATE(CLK_GOUT_CPUCL0_SWITCH, "gout_cpucl0_switch", "mout_cpucl0_switch", + CLK_CON_GAT_GATE_CLKCMU_CPUCL0_SWITCH, 21, 0, 0), + + /* CPUCL1 */ + GATE(CLK_GOUT_CPUCL1_DBG, "gout_cpucl1_dbg", "mout_cpucl1_dbg", + CLK_CON_GAT_GATE_CLKCMU_CPUCL1_DBG, 21, 0, 0), + GATE(CLK_GOUT_CPUCL1_SWITCH, "gout_cpucl1_switch", "mout_cpucl1_switch", + CLK_CON_GAT_GATE_CLKCMU_CPUCL1_SWITCH, 21, 0, 0), + /* DPU */ GATE(CLK_GOUT_DPU, "gout_dpu", "mout_dpu", CLK_CON_GAT_GATE_CLKCMU_DPU, 21, 0, 0), @@ -1030,6 +1101,373 @@ static const struct samsung_cmu_info cmgp_cmu_info __initconst = { .clk_name = "gout_clkcmu_cmgp_bus", }; +/* ---- CMU_CPUCL0 ---------------------------------------------------------- */ + +/* Register Offset definitions for CMU_CPUCL0 (0x10900000) */ +#define PLL_LOCKTIME_PLL_CPUCL0 0x0000 +#define PLL_CON0_PLL_CPUCL0 0x0100 +#define PLL_CON1_PLL_CPUCL0 0x0104 +#define PLL_CON3_PLL_CPUCL0 0x010c +#define PLL_CON0_MUX_CLKCMU_CPUCL0_DBG_USER 0x0600 +#define PLL_CON0_MUX_CLKCMU_CPUCL0_SWITCH_USER 0x0610 +#define CLK_CON_MUX_MUX_CLK_CPUCL0_PLL 0x100c +#define CLK_CON_DIV_DIV_CLK_CLUSTER0_ACLK 0x1800 +#define CLK_CON_DIV_DIV_CLK_CLUSTER0_ATCLK 0x1808 +#define CLK_CON_DIV_DIV_CLK_CLUSTER0_PCLKDBG 0x180c +#define CLK_CON_DIV_DIV_CLK_CLUSTER0_PERIPHCLK 0x1810 +#define CLK_CON_DIV_DIV_CLK_CPUCL0_CMUREF 0x1814 +#define CLK_CON_DIV_DIV_CLK_CPUCL0_CPU 0x1818 +#define CLK_CON_DIV_DIV_CLK_CPUCL0_PCLK 0x181c +#define CLK_CON_GAT_CLK_CPUCL0_CLUSTER0_ATCLK 0x2000 +#define CLK_CON_GAT_CLK_CPUCL0_CLUSTER0_PCLK 0x2004 +#define CLK_CON_GAT_CLK_CPUCL0_CLUSTER0_PERIPHCLK 0x2008 +#define CLK_CON_GAT_CLK_CPUCL0_CLUSTER0_SCLK 0x200c +#define CLK_CON_GAT_CLK_CPUCL0_CMU_CPUCL0_PCLK 0x2010 +#define CLK_CON_GAT_GATE_CLK_CPUCL0_CPU 0x2020 + +static const unsigned long cpucl0_clk_regs[] __initconst = { + PLL_LOCKTIME_PLL_CPUCL0, + PLL_CON0_PLL_CPUCL0, + PLL_CON1_PLL_CPUCL0, + PLL_CON3_PLL_CPUCL0, + PLL_CON0_MUX_CLKCMU_CPUCL0_DBG_USER, + PLL_CON0_MUX_CLKCMU_CPUCL0_SWITCH_USER, + CLK_CON_MUX_MUX_CLK_CPUCL0_PLL, + CLK_CON_DIV_DIV_CLK_CLUSTER0_ACLK, + CLK_CON_DIV_DIV_CLK_CLUSTER0_ATCLK, + CLK_CON_DIV_DIV_CLK_CLUSTER0_PCLKDBG, + CLK_CON_DIV_DIV_CLK_CLUSTER0_PERIPHCLK, + CLK_CON_DIV_DIV_CLK_CPUCL0_CMUREF, + CLK_CON_DIV_DIV_CLK_CPUCL0_CPU, + CLK_CON_DIV_DIV_CLK_CPUCL0_PCLK, + CLK_CON_GAT_CLK_CPUCL0_CLUSTER0_ATCLK, + CLK_CON_GAT_CLK_CPUCL0_CLUSTER0_PCLK, + CLK_CON_GAT_CLK_CPUCL0_CLUSTER0_PERIPHCLK, + CLK_CON_GAT_CLK_CPUCL0_CLUSTER0_SCLK, + CLK_CON_GAT_CLK_CPUCL0_CMU_CPUCL0_PCLK, + CLK_CON_GAT_GATE_CLK_CPUCL0_CPU, +}; + +/* List of parent clocks for Muxes in CMU_CPUCL0 */ +PNAME(mout_pll_cpucl0_p) = { "oscclk", "fout_cpucl0_pll" }; +PNAME(mout_cpucl0_switch_user_p) = { "oscclk", "dout_cpucl0_switch" }; +PNAME(mout_cpucl0_dbg_user_p) = { "oscclk", "dout_cpucl0_dbg" }; +PNAME(mout_cpucl0_pll_p) = { "mout_pll_cpucl0", + "mout_cpucl0_switch_user" }; + +static const struct samsung_pll_rate_table cpu_pll_rates[] __initconst = { + PLL_35XX_RATE(26 * MHZ, 2210000000U, 255, 3, 0), + PLL_35XX_RATE(26 * MHZ, 2106000000U, 243, 3, 0), + PLL_35XX_RATE(26 * MHZ, 2002000000U, 231, 3, 0), + PLL_35XX_RATE(26 * MHZ, 1846000000U, 213, 3, 0), + PLL_35XX_RATE(26 * MHZ, 1742000000U, 201, 3, 0), + PLL_35XX_RATE(26 * MHZ, 1586000000U, 183, 3, 0), + PLL_35XX_RATE(26 * MHZ, 1456000000U, 168, 3, 0), + PLL_35XX_RATE(26 * MHZ, 1300000000U, 150, 3, 0), + PLL_35XX_RATE(26 * MHZ, 1157000000U, 267, 3, 1), + PLL_35XX_RATE(26 * MHZ, 1053000000U, 243, 3, 1), + PLL_35XX_RATE(26 * MHZ, 949000000U, 219, 3, 1), + PLL_35XX_RATE(26 * MHZ, 806000000U, 186, 3, 1), + PLL_35XX_RATE(26 * MHZ, 650000000U, 150, 3, 1), + PLL_35XX_RATE(26 * MHZ, 546000000U, 252, 3, 2), + PLL_35XX_RATE(26 * MHZ, 442000000U, 204, 3, 2), + PLL_35XX_RATE(26 * MHZ, 351000000U, 162, 3, 2), + PLL_35XX_RATE(26 * MHZ, 247000000U, 114, 3, 2), + PLL_35XX_RATE(26 * MHZ, 182000000U, 168, 3, 3), + PLL_35XX_RATE(26 * MHZ, 130000000U, 120, 3, 3), +}; + +static const struct samsung_pll_clock cpucl0_pll_clks[] __initconst = { + PLL(pll_0822x, CLK_FOUT_CPUCL0_PLL, "fout_cpucl0_pll", "oscclk", + PLL_LOCKTIME_PLL_CPUCL0, PLL_CON3_PLL_CPUCL0, cpu_pll_rates), +}; + +static const struct samsung_mux_clock cpucl0_mux_clks[] __initconst = { + MUX_F(CLK_MOUT_PLL_CPUCL0, "mout_pll_cpucl0", mout_pll_cpucl0_p, + PLL_CON0_PLL_CPUCL0, 4, 1, + CLK_SET_RATE_PARENT | CLK_RECALC_NEW_RATES, 0), + MUX_F(CLK_MOUT_CPUCL0_SWITCH_USER, "mout_cpucl0_switch_user", + mout_cpucl0_switch_user_p, + PLL_CON0_MUX_CLKCMU_CPUCL0_SWITCH_USER, 4, 1, + CLK_SET_RATE_PARENT, 0), + MUX(CLK_MOUT_CPUCL0_DBG_USER, "mout_cpucl0_dbg_user", + mout_cpucl0_dbg_user_p, + PLL_CON0_MUX_CLKCMU_CPUCL0_DBG_USER, 4, 1), + MUX_F(CLK_MOUT_CPUCL0_PLL, "mout_cpucl0_pll", mout_cpucl0_pll_p, + CLK_CON_MUX_MUX_CLK_CPUCL0_PLL, 0, 1, CLK_SET_RATE_PARENT, 0), +}; + +static const struct samsung_div_clock cpucl0_div_clks[] __initconst = { + DIV_F(CLK_DOUT_CPUCL0_CPU, "dout_cpucl0_cpu", "mout_cpucl0_pll", + CLK_CON_DIV_DIV_CLK_CPUCL0_CPU, 0, 1, + CLK_GET_RATE_NOCACHE, CLK_DIVIDER_READ_ONLY), + DIV_F(CLK_DOUT_CPUCL0_CMUREF, "dout_cpucl0_cmuref", "dout_cpucl0_cpu", + CLK_CON_DIV_DIV_CLK_CPUCL0_CMUREF, 0, 3, + CLK_GET_RATE_NOCACHE, CLK_DIVIDER_READ_ONLY), + DIV_F(CLK_DOUT_CPUCL0_PCLK, "dout_cpucl0_pclk", "dout_cpucl0_cpu", + CLK_CON_DIV_DIV_CLK_CPUCL0_PCLK, 0, 4, + CLK_GET_RATE_NOCACHE, CLK_DIVIDER_READ_ONLY), + + /* EMBEDDED_CMU_CPUCL0 */ + DIV_F(CLK_DOUT_CLUSTER0_ACLK, "dout_cluster0_aclk", "gout_cluster0_cpu", + CLK_CON_DIV_DIV_CLK_CLUSTER0_ACLK, 0, 4, + CLK_GET_RATE_NOCACHE, CLK_DIVIDER_READ_ONLY), + DIV_F(CLK_DOUT_CLUSTER0_ATCLK, "dout_cluster0_atclk", + "gout_cluster0_cpu", CLK_CON_DIV_DIV_CLK_CLUSTER0_ATCLK, 0, 4, + CLK_GET_RATE_NOCACHE, CLK_DIVIDER_READ_ONLY), + DIV_F(CLK_DOUT_CLUSTER0_PCLKDBG, "dout_cluster0_pclkdbg", + "gout_cluster0_cpu", CLK_CON_DIV_DIV_CLK_CLUSTER0_PCLKDBG, 0, 4, + CLK_GET_RATE_NOCACHE, CLK_DIVIDER_READ_ONLY), + DIV_F(CLK_DOUT_CLUSTER0_PERIPHCLK, "dout_cluster0_periphclk", + "gout_cluster0_cpu", CLK_CON_DIV_DIV_CLK_CLUSTER0_PERIPHCLK, 0, 4, + CLK_GET_RATE_NOCACHE, CLK_DIVIDER_READ_ONLY), +}; + +static const struct samsung_gate_clock cpucl0_gate_clks[] __initconst = { + GATE(CLK_GOUT_CPUCL0_CMU_CPUCL0_PCLK, "gout_cpucl0_cmu_cpucl0_pclk", + "dout_cpucl0_pclk", + CLK_CON_GAT_CLK_CPUCL0_CMU_CPUCL0_PCLK, 21, CLK_IGNORE_UNUSED, 0), + + /* EMBEDDED_CMU_CPUCL0 */ + GATE(CLK_GOUT_CLUSTER0_CPU, "gout_cluster0_cpu", "dout_cpucl0_cpu", + CLK_CON_GAT_GATE_CLK_CPUCL0_CPU, 21, CLK_IGNORE_UNUSED, 0), + GATE(CLK_GOUT_CLUSTER0_SCLK, "gout_cluster0_sclk", "gout_cluster0_cpu", + CLK_CON_GAT_CLK_CPUCL0_CLUSTER0_SCLK, 21, CLK_IGNORE_UNUSED, 0), + GATE(CLK_GOUT_CLUSTER0_ATCLK, "gout_cluster0_atclk", + "dout_cluster0_atclk", + CLK_CON_GAT_CLK_CPUCL0_CLUSTER0_ATCLK, 21, CLK_IGNORE_UNUSED, 0), + GATE(CLK_GOUT_CLUSTER0_PERIPHCLK, "gout_cluster0_periphclk", + "dout_cluster0_periphclk", + CLK_CON_GAT_CLK_CPUCL0_CLUSTER0_PERIPHCLK, 21, + CLK_IGNORE_UNUSED, 0), + GATE(CLK_GOUT_CLUSTER0_PCLK, "gout_cluster0_pclk", + "dout_cluster0_pclkdbg", + CLK_CON_GAT_CLK_CPUCL0_CLUSTER0_PCLK, 21, CLK_IGNORE_UNUSED, 0), +}; + +/* + * Each parameter is going to be written into the corresponding DIV register. So + * the actual divider value for each parameter will be 1/(param+1). All these + * parameters must be in the range of 0..15, as the divider range for all of + * these DIV clocks is 1..16. The default values for these dividers is + * (1, 3, 3, 1). + */ +#define E850_CPU_DIV0(aclk, atclk, pclkdbg, periphclk) \ + (((aclk) << 16) | ((atclk) << 12) | ((pclkdbg) << 8) | \ + ((periphclk) << 4)) + +static const struct exynos_cpuclk_cfg_data exynos850_cluster_clk_d[] __initconst += { + { 2210000, E850_CPU_DIV0(1, 3, 3, 1) }, + { 2106000, E850_CPU_DIV0(1, 3, 3, 1) }, + { 2002000, E850_CPU_DIV0(1, 3, 3, 1) }, + { 1846000, E850_CPU_DIV0(1, 3, 3, 1) }, + { 1742000, E850_CPU_DIV0(1, 3, 3, 1) }, + { 1586000, E850_CPU_DIV0(1, 3, 3, 1) }, + { 1456000, E850_CPU_DIV0(1, 3, 3, 1) }, + { 1300000, E850_CPU_DIV0(1, 3, 3, 1) }, + { 1157000, E850_CPU_DIV0(1, 3, 3, 1) }, + { 1053000, E850_CPU_DIV0(1, 3, 3, 1) }, + { 949000, E850_CPU_DIV0(1, 3, 3, 1) }, + { 806000, E850_CPU_DIV0(1, 3, 3, 1) }, + { 650000, E850_CPU_DIV0(1, 3, 3, 1) }, + { 546000, E850_CPU_DIV0(1, 3, 3, 1) }, + { 442000, E850_CPU_DIV0(1, 3, 3, 1) }, + { 351000, E850_CPU_DIV0(1, 3, 3, 1) }, + { 247000, E850_CPU_DIV0(1, 3, 3, 1) }, + { 182000, E850_CPU_DIV0(1, 3, 3, 1) }, + { 130000, E850_CPU_DIV0(1, 3, 3, 1) }, + { 0 } +}; + +static const struct samsung_cpu_clock cpucl0_cpu_clks[] __initconst = { + CPU_CLK(CLK_CLUSTER0_SCLK, "cluster0_clk", CLK_MOUT_PLL_CPUCL0, + CLK_MOUT_CPUCL0_SWITCH_USER, 0, 0x0, CPUCLK_LAYOUT_E850_CL0, + exynos850_cluster_clk_d), +}; + +static const struct samsung_cmu_info cpucl0_cmu_info __initconst = { + .pll_clks = cpucl0_pll_clks, + .nr_pll_clks = ARRAY_SIZE(cpucl0_pll_clks), + .mux_clks = cpucl0_mux_clks, + .nr_mux_clks = ARRAY_SIZE(cpucl0_mux_clks), + .div_clks = cpucl0_div_clks, + .nr_div_clks = ARRAY_SIZE(cpucl0_div_clks), + .gate_clks = cpucl0_gate_clks, + .nr_gate_clks = ARRAY_SIZE(cpucl0_gate_clks), + .cpu_clks = cpucl0_cpu_clks, + .nr_cpu_clks = ARRAY_SIZE(cpucl0_cpu_clks), + .nr_clk_ids = CLKS_NR_CPUCL0, + .clk_regs = cpucl0_clk_regs, + .nr_clk_regs = ARRAY_SIZE(cpucl0_clk_regs), + .clk_name = "dout_cpucl0_switch", + .manual_plls = true, +}; + +static void __init exynos850_cmu_cpucl0_init(struct device_node *np) +{ + exynos_arm64_register_cmu(NULL, np, &cpucl0_cmu_info); +} + +/* Register CMU_CPUCL0 early, as CPU clocks should be available ASAP */ +CLK_OF_DECLARE(exynos850_cmu_cpucl0, "samsung,exynos850-cmu-cpucl0", + exynos850_cmu_cpucl0_init); + +/* ---- CMU_CPUCL1 ---------------------------------------------------------- */ + +/* Register Offset definitions for CMU_CPUCL1 (0x10800000) */ +#define PLL_LOCKTIME_PLL_CPUCL1 0x0000 +#define PLL_CON0_PLL_CPUCL1 0x0100 +#define PLL_CON1_PLL_CPUCL1 0x0104 +#define PLL_CON3_PLL_CPUCL1 0x010c +#define PLL_CON0_MUX_CLKCMU_CPUCL1_DBG_USER 0x0600 +#define PLL_CON0_MUX_CLKCMU_CPUCL1_SWITCH_USER 0x0610 +#define CLK_CON_MUX_MUX_CLK_CPUCL1_PLL 0x1000 +#define CLK_CON_DIV_DIV_CLK_CLUSTER1_ACLK 0x1800 +#define CLK_CON_DIV_DIV_CLK_CLUSTER1_ATCLK 0x1808 +#define CLK_CON_DIV_DIV_CLK_CLUSTER1_PCLKDBG 0x180c +#define CLK_CON_DIV_DIV_CLK_CLUSTER1_PERIPHCLK 0x1810 +#define CLK_CON_DIV_DIV_CLK_CPUCL1_CMUREF 0x1814 +#define CLK_CON_DIV_DIV_CLK_CPUCL1_CPU 0x1818 +#define CLK_CON_DIV_DIV_CLK_CPUCL1_PCLK 0x181c +#define CLK_CON_GAT_CLK_CPUCL1_CLUSTER1_ATCLK 0x2000 +#define CLK_CON_GAT_CLK_CPUCL1_CLUSTER1_PCLK 0x2004 +#define CLK_CON_GAT_CLK_CPUCL1_CLUSTER1_PERIPHCLK 0x2008 +#define CLK_CON_GAT_CLK_CPUCL1_CLUSTER1_SCLK 0x200c +#define CLK_CON_GAT_CLK_CPUCL1_CMU_CPUCL1_PCLK 0x2010 +#define CLK_CON_GAT_GATE_CLK_CPUCL1_CPU 0x2020 + +static const unsigned long cpucl1_clk_regs[] __initconst = { + PLL_LOCKTIME_PLL_CPUCL1, + PLL_CON0_PLL_CPUCL1, + PLL_CON1_PLL_CPUCL1, + PLL_CON3_PLL_CPUCL1, + PLL_CON0_MUX_CLKCMU_CPUCL1_DBG_USER, + PLL_CON0_MUX_CLKCMU_CPUCL1_SWITCH_USER, + CLK_CON_MUX_MUX_CLK_CPUCL1_PLL, + CLK_CON_DIV_DIV_CLK_CLUSTER1_ACLK, + CLK_CON_DIV_DIV_CLK_CLUSTER1_ATCLK, + CLK_CON_DIV_DIV_CLK_CLUSTER1_PCLKDBG, + CLK_CON_DIV_DIV_CLK_CLUSTER1_PERIPHCLK, + CLK_CON_DIV_DIV_CLK_CPUCL1_CMUREF, + CLK_CON_DIV_DIV_CLK_CPUCL1_CPU, + CLK_CON_DIV_DIV_CLK_CPUCL1_PCLK, + CLK_CON_GAT_CLK_CPUCL1_CLUSTER1_ATCLK, + CLK_CON_GAT_CLK_CPUCL1_CLUSTER1_PCLK, + CLK_CON_GAT_CLK_CPUCL1_CLUSTER1_PERIPHCLK, + CLK_CON_GAT_CLK_CPUCL1_CLUSTER1_SCLK, + CLK_CON_GAT_CLK_CPUCL1_CMU_CPUCL1_PCLK, + CLK_CON_GAT_GATE_CLK_CPUCL1_CPU, +}; + +/* List of parent clocks for Muxes in CMU_CPUCL0 */ +PNAME(mout_pll_cpucl1_p) = { "oscclk", "fout_cpucl1_pll" }; +PNAME(mout_cpucl1_switch_user_p) = { "oscclk", "dout_cpucl1_switch" }; +PNAME(mout_cpucl1_dbg_user_p) = { "oscclk", "dout_cpucl1_dbg" }; +PNAME(mout_cpucl1_pll_p) = { "mout_pll_cpucl1", + "mout_cpucl1_switch_user" }; + +static const struct samsung_pll_clock cpucl1_pll_clks[] __initconst = { + PLL(pll_0822x, CLK_FOUT_CPUCL1_PLL, "fout_cpucl1_pll", "oscclk", + PLL_LOCKTIME_PLL_CPUCL1, PLL_CON3_PLL_CPUCL1, cpu_pll_rates), +}; + +static const struct samsung_mux_clock cpucl1_mux_clks[] __initconst = { + MUX_F(CLK_MOUT_PLL_CPUCL1, "mout_pll_cpucl1", mout_pll_cpucl1_p, + PLL_CON0_PLL_CPUCL1, 4, 1, + CLK_SET_RATE_PARENT | CLK_RECALC_NEW_RATES, 0), + MUX_F(CLK_MOUT_CPUCL1_SWITCH_USER, "mout_cpucl1_switch_user", + mout_cpucl1_switch_user_p, + PLL_CON0_MUX_CLKCMU_CPUCL1_SWITCH_USER, 4, 1, + CLK_SET_RATE_PARENT, 0), + MUX(CLK_MOUT_CPUCL1_DBG_USER, "mout_cpucl1_dbg_user", + mout_cpucl1_dbg_user_p, + PLL_CON0_MUX_CLKCMU_CPUCL1_DBG_USER, 4, 1), + MUX_F(CLK_MOUT_CPUCL1_PLL, "mout_cpucl1_pll", mout_cpucl1_pll_p, + CLK_CON_MUX_MUX_CLK_CPUCL1_PLL, 0, 1, CLK_SET_RATE_PARENT, 0), +}; + +static const struct samsung_div_clock cpucl1_div_clks[] __initconst = { + DIV_F(CLK_DOUT_CPUCL1_CPU, "dout_cpucl1_cpu", "mout_cpucl1_pll", + CLK_CON_DIV_DIV_CLK_CPUCL1_CPU, 0, 1, + CLK_GET_RATE_NOCACHE, CLK_DIVIDER_READ_ONLY), + DIV_F(CLK_DOUT_CPUCL1_CMUREF, "dout_cpucl1_cmuref", "dout_cpucl1_cpu", + CLK_CON_DIV_DIV_CLK_CPUCL1_CMUREF, 0, 3, + CLK_GET_RATE_NOCACHE, CLK_DIVIDER_READ_ONLY), + DIV_F(CLK_DOUT_CPUCL1_PCLK, "dout_cpucl1_pclk", "dout_cpucl1_cpu", + CLK_CON_DIV_DIV_CLK_CPUCL1_PCLK, 0, 4, + CLK_GET_RATE_NOCACHE, CLK_DIVIDER_READ_ONLY), + + /* EMBEDDED_CMU_CPUCL1 */ + DIV_F(CLK_DOUT_CLUSTER1_ACLK, "dout_cluster1_aclk", "gout_cluster1_cpu", + CLK_CON_DIV_DIV_CLK_CLUSTER1_ACLK, 0, 4, + CLK_GET_RATE_NOCACHE, CLK_DIVIDER_READ_ONLY), + DIV_F(CLK_DOUT_CLUSTER1_ATCLK, "dout_cluster1_atclk", + "gout_cluster1_cpu", CLK_CON_DIV_DIV_CLK_CLUSTER1_ATCLK, 0, 4, + CLK_GET_RATE_NOCACHE, CLK_DIVIDER_READ_ONLY), + DIV_F(CLK_DOUT_CLUSTER1_PCLKDBG, "dout_cluster1_pclkdbg", + "gout_cluster1_cpu", CLK_CON_DIV_DIV_CLK_CLUSTER1_PCLKDBG, 0, 4, + CLK_GET_RATE_NOCACHE, CLK_DIVIDER_READ_ONLY), + DIV_F(CLK_DOUT_CLUSTER1_PERIPHCLK, "dout_cluster1_periphclk", + "gout_cluster1_cpu", CLK_CON_DIV_DIV_CLK_CLUSTER1_PERIPHCLK, 0, 4, + CLK_GET_RATE_NOCACHE, CLK_DIVIDER_READ_ONLY), +}; + +static const struct samsung_gate_clock cpucl1_gate_clks[] __initconst = { + GATE(CLK_GOUT_CPUCL1_CMU_CPUCL1_PCLK, "gout_cpucl1_cmu_cpucl1_pclk", + "dout_cpucl1_pclk", + CLK_CON_GAT_CLK_CPUCL1_CMU_CPUCL1_PCLK, 21, CLK_IGNORE_UNUSED, 0), + + /* EMBEDDED_CMU_CPUCL1 */ + GATE(CLK_GOUT_CLUSTER1_CPU, "gout_cluster1_cpu", "dout_cpucl1_cpu", + CLK_CON_GAT_GATE_CLK_CPUCL1_CPU, 21, CLK_IGNORE_UNUSED, 0), + GATE(CLK_GOUT_CLUSTER1_SCLK, "gout_cluster1_sclk", "gout_cluster1_cpu", + CLK_CON_GAT_CLK_CPUCL1_CLUSTER1_SCLK, 21, CLK_IGNORE_UNUSED, 0), + GATE(CLK_GOUT_CLUSTER1_ATCLK, "gout_cluster1_atclk", + "dout_cluster1_atclk", + CLK_CON_GAT_CLK_CPUCL1_CLUSTER1_ATCLK, 21, CLK_IGNORE_UNUSED, 0), + GATE(CLK_GOUT_CLUSTER1_PERIPHCLK, "gout_cluster1_periphclk", + "dout_cluster1_periphclk", + CLK_CON_GAT_CLK_CPUCL1_CLUSTER1_PERIPHCLK, 21, + CLK_IGNORE_UNUSED, 0), + GATE(CLK_GOUT_CLUSTER1_PCLK, "gout_cluster1_pclk", + "dout_cluster1_pclkdbg", + CLK_CON_GAT_CLK_CPUCL1_CLUSTER1_PCLK, 21, CLK_IGNORE_UNUSED, 0), +}; + +static const struct samsung_cpu_clock cpucl1_cpu_clks[] __initconst = { + CPU_CLK(CLK_CLUSTER1_SCLK, "cluster1_clk", CLK_MOUT_PLL_CPUCL1, + CLK_MOUT_CPUCL1_SWITCH_USER, 0, 0x0, CPUCLK_LAYOUT_E850_CL1, + exynos850_cluster_clk_d), +}; + +static const struct samsung_cmu_info cpucl1_cmu_info __initconst = { + .pll_clks = cpucl1_pll_clks, + .nr_pll_clks = ARRAY_SIZE(cpucl1_pll_clks), + .mux_clks = cpucl1_mux_clks, + .nr_mux_clks = ARRAY_SIZE(cpucl1_mux_clks), + .div_clks = cpucl1_div_clks, + .nr_div_clks = ARRAY_SIZE(cpucl1_div_clks), + .gate_clks = cpucl1_gate_clks, + .nr_gate_clks = ARRAY_SIZE(cpucl1_gate_clks), + .cpu_clks = cpucl1_cpu_clks, + .nr_cpu_clks = ARRAY_SIZE(cpucl1_cpu_clks), + .nr_clk_ids = CLKS_NR_CPUCL1, + .clk_regs = cpucl1_clk_regs, + .nr_clk_regs = ARRAY_SIZE(cpucl1_clk_regs), + .clk_name = "dout_cpucl1_switch", + .manual_plls = true, +}; + +static void __init exynos850_cmu_cpucl1_init(struct device_node *np) +{ + exynos_arm64_register_cmu(NULL, np, &cpucl1_cmu_info); +} + +/* Register CMU_CPUCL1 early, as CPU clocks should be available ASAP */ +CLK_OF_DECLARE(exynos850_cmu_cpucl1, "samsung,exynos850-cmu-cpucl1", + exynos850_cmu_cpucl1_init); + /* ---- CMU_G3D ------------------------------------------------------------- */ /* Register Offset definitions for CMU_G3D (0x11400000) */ From 98784a9d398ea5513cf571835be7e45885ba49ab Mon Sep 17 00:00:00 2001 From: Krzysztof Kozlowski Date: Tue, 12 Mar 2024 19:50:35 +0100 Subject: [PATCH 007/118] dt-bindings: clock: samsung,s3c6400-clock: convert to DT Schema Convert Samsung S3C6400/S3C6410 SoC clock controller bindings to DT schema. Acked-by: Conor Dooley Reviewed-by: Stephen Boyd Link: https://lore.kernel.org/r/20240312185035.720491-1-krzysztof.kozlowski@linaro.org Signed-off-by: Krzysztof Kozlowski --- .../bindings/clock/samsung,s3c6400-clock.yaml | 57 ++++++++++++++ .../bindings/clock/samsung,s3c64xx-clock.txt | 76 ------------------- 2 files changed, 57 insertions(+), 76 deletions(-) create mode 100644 Documentation/devicetree/bindings/clock/samsung,s3c6400-clock.yaml delete mode 100644 Documentation/devicetree/bindings/clock/samsung,s3c64xx-clock.txt diff --git a/Documentation/devicetree/bindings/clock/samsung,s3c6400-clock.yaml b/Documentation/devicetree/bindings/clock/samsung,s3c6400-clock.yaml new file mode 100644 index 000000000000..0fcc0c963f8f --- /dev/null +++ b/Documentation/devicetree/bindings/clock/samsung,s3c6400-clock.yaml @@ -0,0 +1,57 @@ +# SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/clock/samsung,s3c6400-clock.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Samsung S3C6400 SoC clock controller + +maintainers: + - Krzysztof Kozlowski + +description: | + There are several clocks that are generated outside the SoC. It is expected + that they are defined using standard clock bindings with following + clock-output-names and/or provided as clock inputs to this clock controller: + - "fin_pll" - PLL input clock (xtal/extclk) - required, + - "xusbxti" - USB xtal - required, + - "iiscdclk0" - I2S0 codec clock - optional, + - "iiscdclk1" - I2S1 codec clock - optional, + - "iiscdclk2" - I2S2 codec clock - optional, + - "pcmcdclk0" - PCM0 codec clock - optional, + - "pcmcdclk1" - PCM1 codec clock - optional, only S3C6410. + + All available clocks are defined as preprocessor macros in + include/dt-bindings/clock/samsung,s3c64xx-clock.h header. + +properties: + compatible: + enum: + - samsung,s3c6400-clock + - samsung,s3c6410-clock + + reg: + maxItems: 1 + + clocks: + maxItems: 1 + + "#clock-cells": + const: 1 + +required: + - compatible + - reg + - clocks + - "#clock-cells" + +additionalProperties: false + +examples: + - | + clock-controller@7e00f000 { + compatible = "samsung,s3c6410-clock"; + reg = <0x7e00f000 0x1000>; + #clock-cells = <1>; + clocks = <&fin_pll>; + }; diff --git a/Documentation/devicetree/bindings/clock/samsung,s3c64xx-clock.txt b/Documentation/devicetree/bindings/clock/samsung,s3c64xx-clock.txt deleted file mode 100644 index 872ee8e0f041..000000000000 --- a/Documentation/devicetree/bindings/clock/samsung,s3c64xx-clock.txt +++ /dev/null @@ -1,76 +0,0 @@ -* Samsung S3C64xx Clock Controller - -The S3C64xx clock controller generates and supplies clock to various controllers -within the SoC. The clock binding described here is applicable to all SoCs in -the S3C64xx family. - -Required Properties: - -- compatible: should be one of the following. - - "samsung,s3c6400-clock" - controller compatible with S3C6400 SoC. - - "samsung,s3c6410-clock" - controller compatible with S3C6410 SoC. - -- reg: physical base address of the controller and length of memory mapped - region. - -- #clock-cells: should be 1. - -Each clock is assigned an identifier and client nodes can use this identifier -to specify the clock which they consume. Some of the clocks are available only -on a particular S3C64xx SoC and this is specified where applicable. - -All available clocks are defined as preprocessor macros in -dt-bindings/clock/samsung,s3c64xx-clock.h header and can be used in device -tree sources. - -External clocks: - -There are several clocks that are generated outside the SoC. It is expected -that they are defined using standard clock bindings with following -clock-output-names: - - "fin_pll" - PLL input clock (xtal/extclk) - required, - - "xusbxti" - USB xtal - required, - - "iiscdclk0" - I2S0 codec clock - optional, - - "iiscdclk1" - I2S1 codec clock - optional, - - "iiscdclk2" - I2S2 codec clock - optional, - - "pcmcdclk0" - PCM0 codec clock - optional, - - "pcmcdclk1" - PCM1 codec clock - optional, only S3C6410. - -Example: Clock controller node: - - clock: clock-controller@7e00f000 { - compatible = "samsung,s3c6410-clock"; - reg = <0x7e00f000 0x1000>; - #clock-cells = <1>; - }; - -Example: Required external clocks: - - fin_pll: clock-fin-pll { - compatible = "fixed-clock"; - clock-output-names = "fin_pll"; - clock-frequency = <12000000>; - #clock-cells = <0>; - }; - - xusbxti: clock-xusbxti { - compatible = "fixed-clock"; - clock-output-names = "xusbxti"; - clock-frequency = <48000000>; - #clock-cells = <0>; - }; - -Example: UART controller node that consumes the clock generated by the clock - controller (refer to the standard clock bindings for information about - "clocks" and "clock-names" properties): - - uart0: serial@7f005000 { - compatible = "samsung,s3c6400-uart"; - reg = <0x7f005000 0x100>; - interrupt-parent = <&vic1>; - interrupts = <5>; - clock-names = "uart", "clk_uart_baud2", - "clk_uart_baud3"; - clocks = <&clock PCLK_UART0>, <&clocks PCLK_UART0>, - <&clock SCLK_UART>; - }; From b6e2c6548074d77e15af8fb6a5a7d03578f04b2f Mon Sep 17 00:00:00 2001 From: Dmitry Rokosov Date: Wed, 20 Mar 2024 18:54:45 +0300 Subject: [PATCH 008/118] clk: meson: a1: peripherals: determine maximum register in regmap config When the max_register value is not set, the regmap debugfs 'registers' file does not display the entire range of the regmap. Signed-off-by: Dmitry Rokosov Link: https://lore.kernel.org/r/20240320155512.3544-2-ddrokosov@salutedevices.com Signed-off-by: Jerome Brunet --- drivers/clk/meson/a1-peripherals.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/clk/meson/a1-peripherals.c b/drivers/clk/meson/a1-peripherals.c index e2a1f12f9175..621af1e6e4b2 100644 --- a/drivers/clk/meson/a1-peripherals.c +++ b/drivers/clk/meson/a1-peripherals.c @@ -2187,6 +2187,7 @@ static struct regmap_config a1_periphs_regmap_cfg = { .reg_bits = 32, .val_bits = 32, .reg_stride = 4, + .max_register = DMC_CLK_CTRL, }; static struct meson_clk_hw_data a1_periphs_clks = { From acc628adc363d441a4bbd05d92ed30253db006ff Mon Sep 17 00:00:00 2001 From: Dmitry Rokosov Date: Wed, 20 Mar 2024 18:54:46 +0300 Subject: [PATCH 009/118] clk: meson: a1: pll: determine maximum register in regmap config When the max_register value is not set, the regmap debugfs 'registers' file does not display the entire range of the regmap. Signed-off-by: Dmitry Rokosov Link: https://lore.kernel.org/r/20240320155512.3544-3-ddrokosov@salutedevices.com Signed-off-by: Jerome Brunet --- drivers/clk/meson/a1-pll.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/clk/meson/a1-pll.c b/drivers/clk/meson/a1-pll.c index 4325e8a6a3ef..90b0aeeb049c 100644 --- a/drivers/clk/meson/a1-pll.c +++ b/drivers/clk/meson/a1-pll.c @@ -299,6 +299,7 @@ static struct regmap_config a1_pll_regmap_cfg = { .reg_bits = 32, .val_bits = 32, .reg_stride = 4, + .max_register = ANACTRL_HIFIPLL_STS, }; static struct meson_clk_hw_data a1_pll_clks = { From 32fba1c16576324f7783d7c27b03689fa7bd9998 Mon Sep 17 00:00:00 2001 From: Dmitry Rokosov Date: Wed, 20 Mar 2024 18:54:47 +0300 Subject: [PATCH 010/118] clk: meson: s4: peripherals: determine maximum register in regmap config When the max_register value is not set, the regmap debugfs 'registers' file does not display the entire range of the regmap. Signed-off-by: Dmitry Rokosov Link: https://lore.kernel.org/r/20240320155512.3544-4-ddrokosov@salutedevices.com Signed-off-by: Jerome Brunet --- drivers/clk/meson/s4-peripherals.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/clk/meson/s4-peripherals.c b/drivers/clk/meson/s4-peripherals.c index 6c35de3d536f..1fceb93faf13 100644 --- a/drivers/clk/meson/s4-peripherals.c +++ b/drivers/clk/meson/s4-peripherals.c @@ -3751,6 +3751,7 @@ static struct regmap_config clkc_regmap_config = { .reg_bits = 32, .val_bits = 32, .reg_stride = 4, + .max_register = CLKCTRL_DEMOD_CLK_CTRL, }; static struct meson_clk_hw_data s4_periphs_clks = { From 5995a2f26f83f09d128a56a51df6d5631a274040 Mon Sep 17 00:00:00 2001 From: Dmitry Rokosov Date: Wed, 20 Mar 2024 18:54:48 +0300 Subject: [PATCH 011/118] clk: meson: s4: pll: determine maximum register in regmap config When the max_register value is not set, the regmap debugfs 'registers' file does not display the entire range of the regmap. Signed-off-by: Dmitry Rokosov Link: https://lore.kernel.org/r/20240320155512.3544-5-ddrokosov@salutedevices.com Signed-off-by: Jerome Brunet --- drivers/clk/meson/s4-pll.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/clk/meson/s4-pll.c b/drivers/clk/meson/s4-pll.c index 8dfaeccaadc2..c8a95842b14c 100644 --- a/drivers/clk/meson/s4-pll.c +++ b/drivers/clk/meson/s4-pll.c @@ -798,6 +798,7 @@ static struct regmap_config clkc_regmap_config = { .reg_bits = 32, .val_bits = 32, .reg_stride = 4, + .max_register = ANACTRL_HDMIPLL_CTRL0, }; static struct meson_clk_hw_data s4_pll_clks = { From 16182ac30a68204aeb9fb373f5cb53f995251e85 Mon Sep 17 00:00:00 2001 From: Dmitry Rokosov Date: Thu, 28 Mar 2024 22:57:29 +0300 Subject: [PATCH 012/118] clk: meson: pll: print out pll name when unable to lock it In most meson systems, multiple PLLs are present, making it difficult to identify the specific PLL that fails to lock. To address this issue, print out the name of the PLL that cannot be locked. Signed-off-by: Dmitry Rokosov Link: https://lore.kernel.org/r/20240328195733.30572-1-ddrokosov@salutedevices.com Signed-off-by: Jerome Brunet --- drivers/clk/meson/clk-pll.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/clk/meson/clk-pll.c b/drivers/clk/meson/clk-pll.c index 6fa7639a3050..78d17b2415af 100644 --- a/drivers/clk/meson/clk-pll.c +++ b/drivers/clk/meson/clk-pll.c @@ -436,8 +436,8 @@ static int meson_clk_pll_set_rate(struct clk_hw *hw, unsigned long rate, ret = meson_clk_pll_enable(hw); if (ret) { - pr_warn("%s: pll did not lock, trying to restore old rate %lu\n", - __func__, old_rate); + pr_warn("%s: pll %s didn't lock, trying to set old rate %lu\n", + __func__, clk_hw_get_name(hw), old_rate); /* * FIXME: Do we really need/want this HACK ? * It looks unsafe. what happens if the clock gets into a From 04ee3a0b44e3d18cf6b0c712d14b98624877fd26 Mon Sep 17 00:00:00 2001 From: Jaewon Kim Date: Thu, 28 Mar 2024 18:10:00 +0900 Subject: [PATCH 013/118] clk: samsung: exynosautov9: fix wrong pll clock id value All PLL id values of CMU_TOP were incorrectly set to FOUT_SHARED0_PLL. It modified to the correct PLL clock id value. Fixes: 6587c62f69dc ("clk: samsung: add top clock support for Exynos Auto v9 SoC") Signed-off-by: Jaewon Kim Reviewed-by: Sam Protsenko Link: https://lore.kernel.org/r/20240328091000.17660-1-jaewon02.kim@samsung.com Signed-off-by: Krzysztof Kozlowski --- drivers/clk/samsung/clk-exynosautov9.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/clk/samsung/clk-exynosautov9.c b/drivers/clk/samsung/clk-exynosautov9.c index e9c06eb93e66..f04bacacab2c 100644 --- a/drivers/clk/samsung/clk-exynosautov9.c +++ b/drivers/clk/samsung/clk-exynosautov9.c @@ -352,13 +352,13 @@ static const struct samsung_pll_clock top_pll_clks[] __initconst = { /* CMU_TOP_PURECLKCOMP */ PLL(pll_0822x, FOUT_SHARED0_PLL, "fout_shared0_pll", "oscclk", PLL_LOCKTIME_PLL_SHARED0, PLL_CON3_PLL_SHARED0, NULL), - PLL(pll_0822x, FOUT_SHARED0_PLL, "fout_shared1_pll", "oscclk", + PLL(pll_0822x, FOUT_SHARED1_PLL, "fout_shared1_pll", "oscclk", PLL_LOCKTIME_PLL_SHARED1, PLL_CON3_PLL_SHARED1, NULL), - PLL(pll_0822x, FOUT_SHARED0_PLL, "fout_shared2_pll", "oscclk", + PLL(pll_0822x, FOUT_SHARED2_PLL, "fout_shared2_pll", "oscclk", PLL_LOCKTIME_PLL_SHARED2, PLL_CON3_PLL_SHARED2, NULL), - PLL(pll_0822x, FOUT_SHARED0_PLL, "fout_shared3_pll", "oscclk", + PLL(pll_0822x, FOUT_SHARED3_PLL, "fout_shared3_pll", "oscclk", PLL_LOCKTIME_PLL_SHARED3, PLL_CON3_PLL_SHARED3, NULL), - PLL(pll_0822x, FOUT_SHARED0_PLL, "fout_shared4_pll", "oscclk", + PLL(pll_0822x, FOUT_SHARED4_PLL, "fout_shared4_pll", "oscclk", PLL_LOCKTIME_PLL_SHARED4, PLL_CON3_PLL_SHARED4, NULL), }; From 9c85158585214770a232ff2efdbdb0e75704743f Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Tue, 12 Mar 2024 10:01:34 +0100 Subject: [PATCH 014/118] clk: renesas: r8a779h0: Add SCIF clocks Add the module clocks used by the Serial Communication Interfaces with FIFO (SCIF) on the Renesas R-Car V4M (R8A779H0) SoC. Signed-off-by: Geert Uytterhoeven Link: https://lore.kernel.org/r/82d731edd4ae4a8cd7683368131095777f4fa172.1709741224.git.geert+renesas@glider.be --- drivers/clk/renesas/r8a779h0-cpg-mssr.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/drivers/clk/renesas/r8a779h0-cpg-mssr.c b/drivers/clk/renesas/r8a779h0-cpg-mssr.c index 5c48e645f0c3..4bc35bc91254 100644 --- a/drivers/clk/renesas/r8a779h0-cpg-mssr.c +++ b/drivers/clk/renesas/r8a779h0-cpg-mssr.c @@ -185,6 +185,10 @@ static const struct mssr_mod_clk r8a779h0_mod_clks[] = { DEF_MOD("i2c2", 520, R8A779H0_CLK_S0D6_PER), DEF_MOD("i2c3", 521, R8A779H0_CLK_S0D6_PER), DEF_MOD("rpc-if", 629, R8A779H0_CLK_RPCD2), + DEF_MOD("scif0", 702, R8A779H0_CLK_SASYNCPERD4), + DEF_MOD("scif1", 703, R8A779H0_CLK_SASYNCPERD4), + DEF_MOD("scif3", 704, R8A779H0_CLK_SASYNCPERD4), + DEF_MOD("scif4", 705, R8A779H0_CLK_SASYNCPERD4), DEF_MOD("sdhi0", 706, R8A779H0_CLK_SD0), DEF_MOD("sydm1", 709, R8A779H0_CLK_S0D6_PER), DEF_MOD("sydm2", 710, R8A779H0_CLK_S0D6_PER), From 0cd830ac3be548c920924baa84f782a763167460 Mon Sep 17 00:00:00 2001 From: Christophe JAILLET Date: Mon, 1 Apr 2024 17:31:53 +0200 Subject: [PATCH 015/118] clk: nxp: Remove an unused field in struct lpc18xx_pll In "struct lpc18xx_pll", the 'lock' field is unused. Remove it. Found with cppcheck, unusedStructMember. Signed-off-by: Christophe JAILLET Link: https://lore.kernel.org/r/6cfb0e5251c3a59a156e70bcf6a0cc74aa764faa.1711985490.git.christophe.jaillet@wanadoo.fr Acked-by: Vladimir Zapolskiy Signed-off-by: Stephen Boyd --- drivers/clk/nxp/clk-lpc18xx-cgu.c | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/clk/nxp/clk-lpc18xx-cgu.c b/drivers/clk/nxp/clk-lpc18xx-cgu.c index 69ebf65081b8..81efa885069b 100644 --- a/drivers/clk/nxp/clk-lpc18xx-cgu.c +++ b/drivers/clk/nxp/clk-lpc18xx-cgu.c @@ -250,7 +250,6 @@ static struct lpc18xx_cgu_base_clk lpc18xx_cgu_base_clks[] = { struct lpc18xx_pll { struct clk_hw hw; void __iomem *reg; - spinlock_t *lock; u8 flags; }; From 4acfeecd0062821fe66a520635adf65c6db759c3 Mon Sep 17 00:00:00 2001 From: Arnd Bergmann Date: Wed, 3 Apr 2024 10:06:29 +0200 Subject: [PATCH 016/118] clk: ti: dpll: fix incorrect #ifdef checks Building with W=1 shows warnings about unused const variables like this one: drivers/clk/ti/dpll.c:99:29: error: unused variable 'omap3_dpll_core_ck_ops' [-Werror,-Wunused-const-variable] static const struct clk_ops omap3_dpll_core_ck_ops = {}; The problem is that the #ifdef checks for some of the structures in this file have gone out of sync with the code referencing them. Update these to match the current usage. Signed-off-by: Arnd Bergmann Link: https://lore.kernel.org/r/20240403080702.3509288-12-arnd@kernel.org Reviewed-by: Tony Lindgren Signed-off-by: Stephen Boyd --- drivers/clk/ti/dpll.c | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/drivers/clk/ti/dpll.c b/drivers/clk/ti/dpll.c index 403ec81f561b..3386bd1903df 100644 --- a/drivers/clk/ti/dpll.c +++ b/drivers/clk/ti/dpll.c @@ -34,8 +34,6 @@ static const struct clk_ops dpll_m4xen_ck_ops = { .save_context = &omap3_core_dpll_save_context, .restore_context = &omap3_core_dpll_restore_context, }; -#else -static const struct clk_ops dpll_m4xen_ck_ops = {}; #endif #if defined(CONFIG_ARCH_OMAP3) || defined(CONFIG_ARCH_OMAP4) || \ @@ -95,11 +93,7 @@ static const struct clk_ops omap3_dpll_core_ck_ops = { .recalc_rate = &omap3_dpll_recalc, .round_rate = &omap2_dpll_round_rate, }; -#else -static const struct clk_ops omap3_dpll_core_ck_ops = {}; -#endif -#ifdef CONFIG_ARCH_OMAP3 static const struct clk_ops omap3_dpll_ck_ops = { .enable = &omap3_noncore_dpll_enable, .disable = &omap3_noncore_dpll_disable, @@ -137,9 +131,13 @@ static const struct clk_ops omap3_dpll_per_ck_ops = { }; #endif +#if defined(CONFIG_ARCH_OMAP4) || defined(CONFIG_SOC_OMAP5) || \ + defined(CONFIG_SOC_DRA7XX) || defined(CONFIG_SOC_AM33XX) || \ + defined(CONFIG_SOC_AM43XX) static const struct clk_ops dpll_x2_ck_ops = { .recalc_rate = &omap3_clkoutx2_recalc, }; +#endif /** * _register_dpll - low level registration of a DPLL clock From c0516eb4cf04ac61b6fe1f86cc15b2f5f024ee78 Mon Sep 17 00:00:00 2001 From: Thanh Quan Date: Tue, 2 Apr 2024 16:37:52 +0200 Subject: [PATCH 017/118] clk: renesas: r8a779h0: Add timer clocks Add the module clocks used by Timer (CMT/TMU) blocks on the Renesas R-Car V4M (R8A779H0) SoC. Signed-off-by: Thanh Quan Signed-off-by: Geert Uytterhoeven Reviewed-by: Wolfram Sang Link: https://lore.kernel.org/r/79a66e8ff84378d7f65d5f55cfb01b9b745edd12.1712068639.git.geert+renesas@glider.be --- drivers/clk/renesas/r8a779h0-cpg-mssr.c | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/drivers/clk/renesas/r8a779h0-cpg-mssr.c b/drivers/clk/renesas/r8a779h0-cpg-mssr.c index 4bc35bc91254..a7d272285db0 100644 --- a/drivers/clk/renesas/r8a779h0-cpg-mssr.c +++ b/drivers/clk/renesas/r8a779h0-cpg-mssr.c @@ -192,7 +192,16 @@ static const struct mssr_mod_clk r8a779h0_mod_clks[] = { DEF_MOD("sdhi0", 706, R8A779H0_CLK_SD0), DEF_MOD("sydm1", 709, R8A779H0_CLK_S0D6_PER), DEF_MOD("sydm2", 710, R8A779H0_CLK_S0D6_PER), + DEF_MOD("tmu0", 713, R8A779H0_CLK_SASYNCRT), + DEF_MOD("tmu1", 714, R8A779H0_CLK_SASYNCPERD2), + DEF_MOD("tmu2", 715, R8A779H0_CLK_SASYNCPERD2), + DEF_MOD("tmu3", 716, R8A779H0_CLK_SASYNCPERD2), + DEF_MOD("tmu4", 717, R8A779H0_CLK_SASYNCPERD2), DEF_MOD("wdt1:wdt0", 907, R8A779H0_CLK_R), + DEF_MOD("cmt0", 910, R8A779H0_CLK_R), + DEF_MOD("cmt1", 911, R8A779H0_CLK_R), + DEF_MOD("cmt2", 912, R8A779H0_CLK_R), + DEF_MOD("cmt3", 913, R8A779H0_CLK_R), DEF_MOD("pfc0", 915, R8A779H0_CLK_CP), DEF_MOD("pfc1", 916, R8A779H0_CLK_CP), DEF_MOD("pfc2", 917, R8A779H0_CLK_CP), From 575bc7b477e3f6c505f49c3d99d7be965594d640 Mon Sep 17 00:00:00 2001 From: Sascha Hauer Date: Fri, 5 Apr 2024 09:38:36 +0200 Subject: [PATCH 018/118] dt-bindings: clock: rockchip: add USB480M_PHY mux The USB480M clock can source from a MUX that selects the clock to come from either of the USB-phy internal 480MHz PLLs. These clocks are provided by the USB phy driver. This adds the define for it. Signed-off-by: Sascha Hauer Acked-by: Krzysztof Kozlowski Link: https://lore.kernel.org/r/20240405-clk-rk3568-usb480m-phy-mux-v1-1-6c89de20a6ff@pengutronix.de Signed-off-by: Heiko Stuebner --- include/dt-bindings/clock/rk3568-cru.h | 1 + 1 file changed, 1 insertion(+) diff --git a/include/dt-bindings/clock/rk3568-cru.h b/include/dt-bindings/clock/rk3568-cru.h index d29890865150..5263085c5b23 100644 --- a/include/dt-bindings/clock/rk3568-cru.h +++ b/include/dt-bindings/clock/rk3568-cru.h @@ -78,6 +78,7 @@ #define CPLL_333M 9 #define ARMCLK 10 #define USB480M 11 +#define USB480M_PHY 12 #define ACLK_CORE_NIU2BUS 18 #define CLK_CORE_PVTM 19 #define CLK_CORE_PVTM_CORE 20 From ca151fd56b5736a7adbdba5675b9d87d70f20b23 Mon Sep 17 00:00:00 2001 From: Shreeya Patel Date: Thu, 28 Mar 2024 04:20:52 +0530 Subject: [PATCH 019/118] dt-bindings: reset: Define reset id used for HDMI Receiver Add reset id used for HDMI Receiver in RK3588 SoCs Acked-by: Rob Herring Signed-off-by: Shreeya Patel Link: https://lore.kernel.org/r/20240327225057.672304-2-shreeya.patel@collabora.com Signed-off-by: Heiko Stuebner --- include/dt-bindings/reset/rockchip,rk3588-cru.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/include/dt-bindings/reset/rockchip,rk3588-cru.h b/include/dt-bindings/reset/rockchip,rk3588-cru.h index d4264db2a07f..e2fe4bd5f7f0 100644 --- a/include/dt-bindings/reset/rockchip,rk3588-cru.h +++ b/include/dt-bindings/reset/rockchip,rk3588-cru.h @@ -751,4 +751,6 @@ #define SRST_P_TRNG_CHK 658 #define SRST_TRNG_S 659 +#define SRST_A_HDMIRX_BIU 660 + #endif From 007bd99669eae90f23817023dc78dbb38e76437d Mon Sep 17 00:00:00 2001 From: David Jander Date: Fri, 5 Apr 2024 09:38:37 +0200 Subject: [PATCH 020/118] clk: rockchip: rk3568: Add missing USB480M_PHY mux The USB480M clock can source from a MUX that selects the clock to come from either of the USB-phy internal 480MHz PLLs. These clocks are provided by the USB phy driver. Signed-off-by: David Jander Link: https://lore.kernel.org/r/20240404-clk-rockchip-rk3568-add-usb480m-phy-mux-v1-1-e8542afd58b9@pengutronix.de Signed-off-by: Sascha Hauer Link: https://lore.kernel.org/r/20240405-clk-rk3568-usb480m-phy-mux-v1-2-6c89de20a6ff@pengutronix.de Signed-off-by: Heiko Stuebner --- drivers/clk/rockchip/clk-rk3568.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/drivers/clk/rockchip/clk-rk3568.c b/drivers/clk/rockchip/clk-rk3568.c index 8cb21d10beca..2d44bcaef046 100644 --- a/drivers/clk/rockchip/clk-rk3568.c +++ b/drivers/clk/rockchip/clk-rk3568.c @@ -215,6 +215,7 @@ static const struct rockchip_cpuclk_reg_data rk3568_cpuclk_data = { PNAME(mux_pll_p) = { "xin24m" }; PNAME(mux_usb480m_p) = { "xin24m", "usb480m_phy", "clk_rtc_32k" }; +PNAME(mux_usb480m_phy_p) = { "clk_usbphy0_480m", "clk_usbphy1_480m"}; PNAME(mux_armclk_p) = { "apll", "gpll" }; PNAME(clk_i2s0_8ch_tx_p) = { "clk_i2s0_8ch_tx_src", "clk_i2s0_8ch_tx_frac", "i2s0_mclkin", "xin_osc0_half" }; PNAME(clk_i2s0_8ch_rx_p) = { "clk_i2s0_8ch_rx_src", "clk_i2s0_8ch_rx_frac", "i2s0_mclkin", "xin_osc0_half" }; @@ -485,6 +486,9 @@ static struct rockchip_clk_branch rk3568_clk_branches[] __initdata = { MUX(USB480M, "usb480m", mux_usb480m_p, CLK_SET_RATE_PARENT, RK3568_MODE_CON0, 14, 2, MFLAGS), + MUX(USB480M_PHY, "usb480m_phy", mux_usb480m_phy_p, CLK_SET_RATE_PARENT, + RK3568_MISC_CON2, 15, 1, MFLAGS), + /* PD_CORE */ COMPOSITE(0, "sclk_core_src", apll_gpll_npll_p, CLK_IGNORE_UNUSED, RK3568_CLKSEL_CON(2), 8, 2, MFLAGS, 0, 4, DFLAGS | CLK_DIVIDER_READ_ONLY, From 7af67019cd78d028ef377df689ac103d51905518 Mon Sep 17 00:00:00 2001 From: Shreeya Patel Date: Thu, 28 Mar 2024 04:20:53 +0530 Subject: [PATCH 021/118] clk: rockchip: rk3588: Add reset line for HDMI Receiver Export hdmirx_biu reset line required by the Synopsys DesignWare HDMIRX Controller. Signed-off-by: Shreeya Patel Link: https://lore.kernel.org/r/20240327225057.672304-3-shreeya.patel@collabora.com Signed-off-by: Heiko Stuebner --- drivers/clk/rockchip/rst-rk3588.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/clk/rockchip/rst-rk3588.c b/drivers/clk/rockchip/rst-rk3588.c index e855bb8d5413..c4ebc01f1c9c 100644 --- a/drivers/clk/rockchip/rst-rk3588.c +++ b/drivers/clk/rockchip/rst-rk3588.c @@ -577,6 +577,7 @@ static const int rk3588_register_offset[] = { /* SOFTRST_CON59 */ RK3588_CRU_RESET_OFFSET(SRST_A_HDCP1_BIU, 59, 6), + RK3588_CRU_RESET_OFFSET(SRST_A_HDMIRX_BIU, 59, 7), RK3588_CRU_RESET_OFFSET(SRST_A_VO1_BIU, 59, 8), RK3588_CRU_RESET_OFFSET(SRST_H_VOP1_BIU, 59, 9), RK3588_CRU_RESET_OFFSET(SRST_H_VOP1_S_BIU, 59, 10), From bb5aa08572b5313157c093a09d53ebf2efda3dc1 Mon Sep 17 00:00:00 2001 From: Neil Armstrong Date: Wed, 3 Apr 2024 09:46:33 +0200 Subject: [PATCH 022/118] clk: meson: add vclk driver The VCLK and VCLK_DIV clocks have supplementary bits. The VCLK gate has a "SOFT RESET" bit to toggle after the whole VCLK sub-tree rate has been set, this is implemented in the gate enable callback. The VCLK_DIV clocks as enable and reset bits used to disable and reset the divider, associated with CLK_SET_RATE_GATE it ensures the rate is set while the divider is disabled and in reset mode. The VCLK_DIV enable bit isn't implemented as a gate since it's part of the divider logic and vendor does this exact sequence to ensure the divider is correctly set. Signed-off-by: Neil Armstrong Link: https://lore.kernel.org/r/20240403-amlogic-v6-4-upstream-dsi-ccf-vim3-v12-2-99ecdfdc87fc@linaro.org Signed-off-by: Jerome Brunet --- drivers/clk/meson/Kconfig | 4 ++ drivers/clk/meson/Makefile | 1 + drivers/clk/meson/vclk.c | 141 +++++++++++++++++++++++++++++++++++++ drivers/clk/meson/vclk.h | 51 ++++++++++++++ 4 files changed, 197 insertions(+) create mode 100644 drivers/clk/meson/vclk.c create mode 100644 drivers/clk/meson/vclk.h diff --git a/drivers/clk/meson/Kconfig b/drivers/clk/meson/Kconfig index 29ffd14d267b..8a9823789fa3 100644 --- a/drivers/clk/meson/Kconfig +++ b/drivers/clk/meson/Kconfig @@ -30,6 +30,10 @@ config COMMON_CLK_MESON_VID_PLL_DIV tristate select COMMON_CLK_MESON_REGMAP +config COMMON_CLK_MESON_VCLK + tristate + select COMMON_CLK_MESON_REGMAP + config COMMON_CLK_MESON_CLKC_UTILS tristate diff --git a/drivers/clk/meson/Makefile b/drivers/clk/meson/Makefile index 9ee4b954c896..9ba43fe7a07a 100644 --- a/drivers/clk/meson/Makefile +++ b/drivers/clk/meson/Makefile @@ -12,6 +12,7 @@ obj-$(CONFIG_COMMON_CLK_MESON_PLL) += clk-pll.o obj-$(CONFIG_COMMON_CLK_MESON_REGMAP) += clk-regmap.o obj-$(CONFIG_COMMON_CLK_MESON_SCLK_DIV) += sclk-div.o obj-$(CONFIG_COMMON_CLK_MESON_VID_PLL_DIV) += vid-pll-div.o +obj-$(CONFIG_COMMON_CLK_MESON_VCLK) += vclk.o # Amlogic Clock controllers diff --git a/drivers/clk/meson/vclk.c b/drivers/clk/meson/vclk.c new file mode 100644 index 000000000000..45dc216941ea --- /dev/null +++ b/drivers/clk/meson/vclk.c @@ -0,0 +1,141 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (c) 2024 Neil Armstrong + */ + +#include +#include "vclk.h" + +/* The VCLK gate has a supplementary reset bit to pulse after ungating */ + +static inline struct meson_vclk_gate_data * +clk_get_meson_vclk_gate_data(struct clk_regmap *clk) +{ + return (struct meson_vclk_gate_data *)clk->data; +} + +static int meson_vclk_gate_enable(struct clk_hw *hw) +{ + struct clk_regmap *clk = to_clk_regmap(hw); + struct meson_vclk_gate_data *vclk = clk_get_meson_vclk_gate_data(clk); + + meson_parm_write(clk->map, &vclk->enable, 1); + + /* Do a reset pulse */ + meson_parm_write(clk->map, &vclk->reset, 1); + meson_parm_write(clk->map, &vclk->reset, 0); + + return 0; +} + +static void meson_vclk_gate_disable(struct clk_hw *hw) +{ + struct clk_regmap *clk = to_clk_regmap(hw); + struct meson_vclk_gate_data *vclk = clk_get_meson_vclk_gate_data(clk); + + meson_parm_write(clk->map, &vclk->enable, 0); +} + +static int meson_vclk_gate_is_enabled(struct clk_hw *hw) +{ + struct clk_regmap *clk = to_clk_regmap(hw); + struct meson_vclk_gate_data *vclk = clk_get_meson_vclk_gate_data(clk); + + return meson_parm_read(clk->map, &vclk->enable); +} + +const struct clk_ops meson_vclk_gate_ops = { + .enable = meson_vclk_gate_enable, + .disable = meson_vclk_gate_disable, + .is_enabled = meson_vclk_gate_is_enabled, +}; +EXPORT_SYMBOL_GPL(meson_vclk_gate_ops); + +/* The VCLK Divider has supplementary reset & enable bits */ + +static inline struct meson_vclk_div_data * +clk_get_meson_vclk_div_data(struct clk_regmap *clk) +{ + return (struct meson_vclk_div_data *)clk->data; +} + +static unsigned long meson_vclk_div_recalc_rate(struct clk_hw *hw, + unsigned long prate) +{ + struct clk_regmap *clk = to_clk_regmap(hw); + struct meson_vclk_div_data *vclk = clk_get_meson_vclk_div_data(clk); + + return divider_recalc_rate(hw, prate, meson_parm_read(clk->map, &vclk->div), + vclk->table, vclk->flags, vclk->div.width); +} + +static int meson_vclk_div_determine_rate(struct clk_hw *hw, + struct clk_rate_request *req) +{ + struct clk_regmap *clk = to_clk_regmap(hw); + struct meson_vclk_div_data *vclk = clk_get_meson_vclk_div_data(clk); + + return divider_determine_rate(hw, req, vclk->table, vclk->div.width, + vclk->flags); +} + +static int meson_vclk_div_set_rate(struct clk_hw *hw, unsigned long rate, + unsigned long parent_rate) +{ + struct clk_regmap *clk = to_clk_regmap(hw); + struct meson_vclk_div_data *vclk = clk_get_meson_vclk_div_data(clk); + int ret; + + ret = divider_get_val(rate, parent_rate, vclk->table, vclk->div.width, + vclk->flags); + if (ret < 0) + return ret; + + meson_parm_write(clk->map, &vclk->div, ret); + + return 0; +}; + +static int meson_vclk_div_enable(struct clk_hw *hw) +{ + struct clk_regmap *clk = to_clk_regmap(hw); + struct meson_vclk_div_data *vclk = clk_get_meson_vclk_div_data(clk); + + /* Unreset the divider when ungating */ + meson_parm_write(clk->map, &vclk->reset, 0); + meson_parm_write(clk->map, &vclk->enable, 1); + + return 0; +} + +static void meson_vclk_div_disable(struct clk_hw *hw) +{ + struct clk_regmap *clk = to_clk_regmap(hw); + struct meson_vclk_div_data *vclk = clk_get_meson_vclk_div_data(clk); + + /* Reset the divider when gating */ + meson_parm_write(clk->map, &vclk->enable, 0); + meson_parm_write(clk->map, &vclk->reset, 1); +} + +static int meson_vclk_div_is_enabled(struct clk_hw *hw) +{ + struct clk_regmap *clk = to_clk_regmap(hw); + struct meson_vclk_div_data *vclk = clk_get_meson_vclk_div_data(clk); + + return meson_parm_read(clk->map, &vclk->enable); +} + +const struct clk_ops meson_vclk_div_ops = { + .recalc_rate = meson_vclk_div_recalc_rate, + .determine_rate = meson_vclk_div_determine_rate, + .set_rate = meson_vclk_div_set_rate, + .enable = meson_vclk_div_enable, + .disable = meson_vclk_div_disable, + .is_enabled = meson_vclk_div_is_enabled, +}; +EXPORT_SYMBOL_GPL(meson_vclk_div_ops); + +MODULE_DESCRIPTION("Amlogic vclk clock driver"); +MODULE_AUTHOR("Neil Armstrong "); +MODULE_LICENSE("GPL v2"); diff --git a/drivers/clk/meson/vclk.h b/drivers/clk/meson/vclk.h new file mode 100644 index 000000000000..20b0b181db09 --- /dev/null +++ b/drivers/clk/meson/vclk.h @@ -0,0 +1,51 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Copyright (c) 2024 Neil Armstrong + */ + +#ifndef __VCLK_H +#define __VCLK_H + +#include "clk-regmap.h" +#include "parm.h" + +/** + * struct meson_vclk_gate_data - vclk_gate regmap backed specific data + * + * @enable: vclk enable field + * @reset: vclk reset field + * @flags: hardware-specific flags + * + * Flags: + * Same as clk_gate except CLK_GATE_HIWORD_MASK which is ignored + */ +struct meson_vclk_gate_data { + struct parm enable; + struct parm reset; + u8 flags; +}; + +extern const struct clk_ops meson_vclk_gate_ops; + +/** + * struct meson_vclk_div_data - vclk_div regmap back specific data + * + * @div: divider field + * @enable: vclk divider enable field + * @reset: vclk divider reset field + * @table: array of value/divider pairs, last entry should have div = 0 + * + * Flags: + * Same as clk_divider except CLK_DIVIDER_HIWORD_MASK which is ignored + */ +struct meson_vclk_div_data { + struct parm div; + struct parm enable; + struct parm reset; + const struct clk_div_table *table; + u8 flags; +}; + +extern const struct clk_ops meson_vclk_div_ops; + +#endif /* __VCLK_H */ From b70cb1a21a54236be24c03787eecc40c451158c3 Mon Sep 17 00:00:00 2001 From: Neil Armstrong Date: Wed, 3 Apr 2024 09:46:34 +0200 Subject: [PATCH 023/118] clk: meson: g12a: make VCLK2 and ENCL clock path configurable by CCF In order to setup the DSI clock, let's make the unused VCLK2 clock path configuration via CCF. The nocache option is removed from following clocks: - vclk2_sel - vclk2_input - vclk2_div - vclk2 - vclk_div1 - vclk2_div2_en - vclk2_div4_en - vclk2_div6_en - vclk2_div12_en - vclk2_div2 - vclk2_div4 - vclk2_div6 - vclk2_div12 - cts_encl_sel vclk2 and vclk2_div uses the newly introduced vclk regmap driver to handle the enable and reset bits. In order to set a rate on cts_encl via the vclk2 clock path, the NO_REPARENT flag is set on cts_encl_sel & vclk2_sel in order to keep CCF from selection a parent. The parents of cts_encl_sel & vclk2_sel are expected to be defined in DT or manually set by the display driver at some point. The following clock scheme is to be used for DSI: xtal \_ gp0_pll_dco \_ gp0_pll |- vclk2_sel | \_ vclk2_input | \_ vclk2_div | \_ vclk2 | \_ vclk2_div1 | \_ cts_encl_sel | \_ cts_encl -> to VPU LCD Encoder |- mipi_dsi_pxclk_sel \_ mipi_dsi_pxclk_div \_ mipi_dsi_pxclk -> to DSI controller The mipi_dsi_pxclk_div is set as bypass with a single /1 entry in div_table in order to use the same GP0 for mipi_dsi_pxclk and vclk2_input. The SET_RATE_PARENT is only set on the mipi_dsi_pxclk_sel clock so the DSI bitclock is the reference base clock to calculate the vclk2_div value when pixel clock is set on the cts_encl endpoint. Signed-off-by: Neil Armstrong Link: https://lore.kernel.org/r/20240403-amlogic-v6-4-upstream-dsi-ccf-vim3-v12-3-99ecdfdc87fc@linaro.org Signed-off-by: Jerome Brunet --- drivers/clk/meson/Kconfig | 1 + drivers/clk/meson/g12a.c | 76 ++++++++++++++++++++++++++++----------- 2 files changed, 57 insertions(+), 20 deletions(-) diff --git a/drivers/clk/meson/Kconfig b/drivers/clk/meson/Kconfig index 8a9823789fa3..59a40a49f8e1 100644 --- a/drivers/clk/meson/Kconfig +++ b/drivers/clk/meson/Kconfig @@ -144,6 +144,7 @@ config COMMON_CLK_G12A select COMMON_CLK_MESON_EE_CLKC select COMMON_CLK_MESON_CPU_DYNDIV select COMMON_CLK_MESON_VID_PLL_DIV + select COMMON_CLK_MESON_VCLK select MFD_SYSCON help Support for the clock controller on Amlogic S905D2, S905X2 and S905Y2 diff --git a/drivers/clk/meson/g12a.c b/drivers/clk/meson/g12a.c index 90f4c6103014..df7e17c850d8 100644 --- a/drivers/clk/meson/g12a.c +++ b/drivers/clk/meson/g12a.c @@ -22,6 +22,7 @@ #include "clk-regmap.h" #include "clk-cpu-dyndiv.h" #include "vid-pll-div.h" +#include "vclk.h" #include "meson-eeclk.h" #include "g12a.h" @@ -3165,7 +3166,7 @@ static struct clk_regmap g12a_vclk2_sel = { .ops = &clk_regmap_mux_ops, .parent_hws = g12a_vclk_parent_hws, .num_parents = ARRAY_SIZE(g12a_vclk_parent_hws), - .flags = CLK_SET_RATE_NO_REPARENT | CLK_GET_RATE_NOCACHE, + .flags = CLK_SET_RATE_NO_REPARENT, }, }; @@ -3193,7 +3194,6 @@ static struct clk_regmap g12a_vclk2_input = { .ops = &clk_regmap_gate_ops, .parent_hws = (const struct clk_hw *[]) { &g12a_vclk2_sel.hw }, .num_parents = 1, - .flags = CLK_SET_RATE_PARENT | CLK_IGNORE_UNUSED, }, }; @@ -3215,19 +3215,32 @@ static struct clk_regmap g12a_vclk_div = { }; static struct clk_regmap g12a_vclk2_div = { - .data = &(struct clk_regmap_div_data){ - .offset = HHI_VIID_CLK_DIV, - .shift = 0, - .width = 8, + .data = &(struct meson_vclk_div_data){ + .div = { + .reg_off = HHI_VIID_CLK_DIV, + .shift = 0, + .width = 8, + }, + .enable = { + .reg_off = HHI_VIID_CLK_DIV, + .shift = 16, + .width = 1, + }, + .reset = { + .reg_off = HHI_VIID_CLK_DIV, + .shift = 17, + .width = 1, + }, + .flags = CLK_DIVIDER_ROUND_CLOSEST, }, .hw.init = &(struct clk_init_data){ .name = "vclk2_div", - .ops = &clk_regmap_divider_ops, + .ops = &meson_vclk_div_ops, .parent_hws = (const struct clk_hw *[]) { &g12a_vclk2_input.hw }, .num_parents = 1, - .flags = CLK_GET_RATE_NOCACHE, + .flags = CLK_SET_RATE_GATE, }, }; @@ -3246,16 +3259,24 @@ static struct clk_regmap g12a_vclk = { }; static struct clk_regmap g12a_vclk2 = { - .data = &(struct clk_regmap_gate_data){ - .offset = HHI_VIID_CLK_CNTL, - .bit_idx = 19, + .data = &(struct meson_vclk_gate_data){ + .enable = { + .reg_off = HHI_VIID_CLK_CNTL, + .shift = 19, + .width = 1, + }, + .reset = { + .reg_off = HHI_VIID_CLK_CNTL, + .shift = 15, + .width = 1, + }, }, .hw.init = &(struct clk_init_data) { .name = "vclk2", - .ops = &clk_regmap_gate_ops, + .ops = &meson_vclk_gate_ops, .parent_hws = (const struct clk_hw *[]) { &g12a_vclk2_div.hw }, .num_parents = 1, - .flags = CLK_SET_RATE_PARENT | CLK_IGNORE_UNUSED, + .flags = CLK_SET_RATE_PARENT, }, }; @@ -3339,7 +3360,7 @@ static struct clk_regmap g12a_vclk2_div1 = { .ops = &clk_regmap_gate_ops, .parent_hws = (const struct clk_hw *[]) { &g12a_vclk2.hw }, .num_parents = 1, - .flags = CLK_SET_RATE_PARENT | CLK_IGNORE_UNUSED, + .flags = CLK_SET_RATE_PARENT, }, }; @@ -3353,7 +3374,7 @@ static struct clk_regmap g12a_vclk2_div2_en = { .ops = &clk_regmap_gate_ops, .parent_hws = (const struct clk_hw *[]) { &g12a_vclk2.hw }, .num_parents = 1, - .flags = CLK_SET_RATE_PARENT | CLK_IGNORE_UNUSED, + .flags = CLK_SET_RATE_PARENT, }, }; @@ -3367,7 +3388,7 @@ static struct clk_regmap g12a_vclk2_div4_en = { .ops = &clk_regmap_gate_ops, .parent_hws = (const struct clk_hw *[]) { &g12a_vclk2.hw }, .num_parents = 1, - .flags = CLK_SET_RATE_PARENT | CLK_IGNORE_UNUSED, + .flags = CLK_SET_RATE_PARENT, }, }; @@ -3381,7 +3402,7 @@ static struct clk_regmap g12a_vclk2_div6_en = { .ops = &clk_regmap_gate_ops, .parent_hws = (const struct clk_hw *[]) { &g12a_vclk2.hw }, .num_parents = 1, - .flags = CLK_SET_RATE_PARENT | CLK_IGNORE_UNUSED, + .flags = CLK_SET_RATE_PARENT, }, }; @@ -3395,7 +3416,7 @@ static struct clk_regmap g12a_vclk2_div12_en = { .ops = &clk_regmap_gate_ops, .parent_hws = (const struct clk_hw *[]) { &g12a_vclk2.hw }, .num_parents = 1, - .flags = CLK_SET_RATE_PARENT | CLK_IGNORE_UNUSED, + .flags = CLK_SET_RATE_PARENT, }, }; @@ -3461,6 +3482,7 @@ static struct clk_fixed_factor g12a_vclk2_div2 = { &g12a_vclk2_div2_en.hw }, .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, }, }; @@ -3474,6 +3496,7 @@ static struct clk_fixed_factor g12a_vclk2_div4 = { &g12a_vclk2_div4_en.hw }, .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, }, }; @@ -3487,6 +3510,7 @@ static struct clk_fixed_factor g12a_vclk2_div6 = { &g12a_vclk2_div6_en.hw }, .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, }, }; @@ -3500,6 +3524,7 @@ static struct clk_fixed_factor g12a_vclk2_div12 = { &g12a_vclk2_div12_en.hw }, .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, }, }; @@ -3561,7 +3586,7 @@ static struct clk_regmap g12a_cts_encl_sel = { .ops = &clk_regmap_mux_ops, .parent_hws = g12a_cts_parent_hws, .num_parents = ARRAY_SIZE(g12a_cts_parent_hws), - .flags = CLK_SET_RATE_NO_REPARENT | CLK_GET_RATE_NOCACHE, + .flags = CLK_SET_RATE_PARENT | CLK_SET_RATE_NO_REPARENT, }, }; @@ -3717,15 +3742,26 @@ static struct clk_regmap g12a_mipi_dsi_pxclk_sel = { .ops = &clk_regmap_mux_ops, .parent_hws = g12a_mipi_dsi_pxclk_parent_hws, .num_parents = ARRAY_SIZE(g12a_mipi_dsi_pxclk_parent_hws), - .flags = CLK_SET_RATE_NO_REPARENT, + .flags = CLK_SET_RATE_NO_REPARENT | CLK_SET_RATE_PARENT, }, }; +/* + * FIXME: Force as bypass by forcing a single /1 table entry, and doensn't on boot value + * when setting a clock whith this node in the clock path, but doesn't garantee the divider + * is at /1 at boot until a rate is set. + */ +static const struct clk_div_table g12a_mipi_dsi_pxclk_div_table[] = { + { .val = 0, .div = 1 }, + { /* sentinel */ }, +}; + static struct clk_regmap g12a_mipi_dsi_pxclk_div = { .data = &(struct clk_regmap_div_data){ .offset = HHI_MIPIDSI_PHY_CLK_CNTL, .shift = 0, .width = 7, + .table = g12a_mipi_dsi_pxclk_div_table, }, .hw.init = &(struct clk_init_data){ .name = "mipi_dsi_pxclk_div", From e0892cb47351b85da8ed368c6e2cdd77614967f3 Mon Sep 17 00:00:00 2001 From: Neil Armstrong Date: Mon, 8 Apr 2024 11:17:58 +0200 Subject: [PATCH 024/118] clk: meson: fix module license to GPL only Fix the checkpatch warning: WARNING: Prefer "GPL" over "GPL v2" - see commit bf7fbeeae6db ("module: Cure the MODULE_LICENSE "GPL" vs. "GPL v2" bogosity") Signed-off-by: Neil Armstrong Reviewed-by: Martin Blumenstingl Link: https://lore.kernel.org/r/20240408-amlogic-v6-9-upstream-fix-clk-module-license-v1-1-366ddc0f3db9@linaro.org Signed-off-by: Jerome Brunet --- drivers/clk/meson/axg-aoclk.c | 2 +- drivers/clk/meson/axg-audio.c | 2 +- drivers/clk/meson/axg.c | 2 +- drivers/clk/meson/clk-cpu-dyndiv.c | 2 +- drivers/clk/meson/clk-dualdiv.c | 2 +- drivers/clk/meson/clk-mpll.c | 2 +- drivers/clk/meson/clk-phase.c | 2 +- drivers/clk/meson/clk-pll.c | 2 +- drivers/clk/meson/clk-regmap.c | 2 +- drivers/clk/meson/g12a-aoclk.c | 2 +- drivers/clk/meson/g12a.c | 2 +- drivers/clk/meson/gxbb-aoclk.c | 2 +- drivers/clk/meson/gxbb.c | 2 +- drivers/clk/meson/meson-aoclk.c | 2 +- drivers/clk/meson/meson-eeclk.c | 2 +- drivers/clk/meson/sclk-div.c | 2 +- drivers/clk/meson/vclk.c | 2 +- drivers/clk/meson/vid-pll-div.c | 2 +- 18 files changed, 18 insertions(+), 18 deletions(-) diff --git a/drivers/clk/meson/axg-aoclk.c b/drivers/clk/meson/axg-aoclk.c index d80ab4728f7a..e4d0f46f47f5 100644 --- a/drivers/clk/meson/axg-aoclk.c +++ b/drivers/clk/meson/axg-aoclk.c @@ -340,4 +340,4 @@ static struct platform_driver axg_aoclkc_driver = { }; module_platform_driver(axg_aoclkc_driver); -MODULE_LICENSE("GPL v2"); +MODULE_LICENSE("GPL"); diff --git a/drivers/clk/meson/axg-audio.c b/drivers/clk/meson/axg-audio.c index ac3482960903..e03a5bf899c0 100644 --- a/drivers/clk/meson/axg-audio.c +++ b/drivers/clk/meson/axg-audio.c @@ -1877,4 +1877,4 @@ module_platform_driver(axg_audio_driver); MODULE_DESCRIPTION("Amlogic AXG/G12A/SM1 Audio Clock driver"); MODULE_AUTHOR("Jerome Brunet "); -MODULE_LICENSE("GPL v2"); +MODULE_LICENSE("GPL"); diff --git a/drivers/clk/meson/axg.c b/drivers/clk/meson/axg.c index 5f60f2bcca59..52d610110e44 100644 --- a/drivers/clk/meson/axg.c +++ b/drivers/clk/meson/axg.c @@ -2185,4 +2185,4 @@ static struct platform_driver axg_driver = { }; module_platform_driver(axg_driver); -MODULE_LICENSE("GPL v2"); +MODULE_LICENSE("GPL"); diff --git a/drivers/clk/meson/clk-cpu-dyndiv.c b/drivers/clk/meson/clk-cpu-dyndiv.c index 8778c149d26a..aa824b030cb8 100644 --- a/drivers/clk/meson/clk-cpu-dyndiv.c +++ b/drivers/clk/meson/clk-cpu-dyndiv.c @@ -69,4 +69,4 @@ EXPORT_SYMBOL_GPL(meson_clk_cpu_dyndiv_ops); MODULE_DESCRIPTION("Amlogic CPU Dynamic Clock divider"); MODULE_AUTHOR("Neil Armstrong "); -MODULE_LICENSE("GPL v2"); +MODULE_LICENSE("GPL"); diff --git a/drivers/clk/meson/clk-dualdiv.c b/drivers/clk/meson/clk-dualdiv.c index feae49a8f6dc..d46c02b51be5 100644 --- a/drivers/clk/meson/clk-dualdiv.c +++ b/drivers/clk/meson/clk-dualdiv.c @@ -140,4 +140,4 @@ EXPORT_SYMBOL_GPL(meson_clk_dualdiv_ro_ops); MODULE_DESCRIPTION("Amlogic dual divider driver"); MODULE_AUTHOR("Neil Armstrong "); MODULE_AUTHOR("Jerome Brunet "); -MODULE_LICENSE("GPL v2"); +MODULE_LICENSE("GPL"); diff --git a/drivers/clk/meson/clk-mpll.c b/drivers/clk/meson/clk-mpll.c index 20255e129b37..eae9b7dc5a6c 100644 --- a/drivers/clk/meson/clk-mpll.c +++ b/drivers/clk/meson/clk-mpll.c @@ -177,4 +177,4 @@ EXPORT_SYMBOL_GPL(meson_clk_mpll_ops); MODULE_DESCRIPTION("Amlogic MPLL driver"); MODULE_AUTHOR("Michael Turquette "); -MODULE_LICENSE("GPL v2"); +MODULE_LICENSE("GPL"); diff --git a/drivers/clk/meson/clk-phase.c b/drivers/clk/meson/clk-phase.c index a6763439f7d2..ff3f0b1a3ed1 100644 --- a/drivers/clk/meson/clk-phase.c +++ b/drivers/clk/meson/clk-phase.c @@ -183,4 +183,4 @@ EXPORT_SYMBOL_GPL(meson_sclk_ws_inv_ops); MODULE_DESCRIPTION("Amlogic phase driver"); MODULE_AUTHOR("Jerome Brunet "); -MODULE_LICENSE("GPL v2"); +MODULE_LICENSE("GPL"); diff --git a/drivers/clk/meson/clk-pll.c b/drivers/clk/meson/clk-pll.c index 78d17b2415af..07db8b5c3000 100644 --- a/drivers/clk/meson/clk-pll.c +++ b/drivers/clk/meson/clk-pll.c @@ -486,4 +486,4 @@ EXPORT_SYMBOL_GPL(meson_clk_pll_ro_ops); MODULE_DESCRIPTION("Amlogic PLL driver"); MODULE_AUTHOR("Carlo Caione "); MODULE_AUTHOR("Jerome Brunet "); -MODULE_LICENSE("GPL v2"); +MODULE_LICENSE("GPL"); diff --git a/drivers/clk/meson/clk-regmap.c b/drivers/clk/meson/clk-regmap.c index 8ad8977cf1c2..ad116d24f700 100644 --- a/drivers/clk/meson/clk-regmap.c +++ b/drivers/clk/meson/clk-regmap.c @@ -183,4 +183,4 @@ EXPORT_SYMBOL_GPL(clk_regmap_mux_ro_ops); MODULE_DESCRIPTION("Amlogic regmap backed clock driver"); MODULE_AUTHOR("Jerome Brunet "); -MODULE_LICENSE("GPL v2"); +MODULE_LICENSE("GPL"); diff --git a/drivers/clk/meson/g12a-aoclk.c b/drivers/clk/meson/g12a-aoclk.c index c6b1d55cd7c8..58976ed8b92a 100644 --- a/drivers/clk/meson/g12a-aoclk.c +++ b/drivers/clk/meson/g12a-aoclk.c @@ -475,4 +475,4 @@ static struct platform_driver g12a_aoclkc_driver = { }; module_platform_driver(g12a_aoclkc_driver); -MODULE_LICENSE("GPL v2"); +MODULE_LICENSE("GPL"); diff --git a/drivers/clk/meson/g12a.c b/drivers/clk/meson/g12a.c index df7e17c850d8..56e66ecc306e 100644 --- a/drivers/clk/meson/g12a.c +++ b/drivers/clk/meson/g12a.c @@ -5614,4 +5614,4 @@ static struct platform_driver g12a_driver = { }; module_platform_driver(g12a_driver); -MODULE_LICENSE("GPL v2"); +MODULE_LICENSE("GPL"); diff --git a/drivers/clk/meson/gxbb-aoclk.c b/drivers/clk/meson/gxbb-aoclk.c index 4aec1740ac34..dbda563729db 100644 --- a/drivers/clk/meson/gxbb-aoclk.c +++ b/drivers/clk/meson/gxbb-aoclk.c @@ -300,4 +300,4 @@ static struct platform_driver gxbb_aoclkc_driver = { }, }; module_platform_driver(gxbb_aoclkc_driver); -MODULE_LICENSE("GPL v2"); +MODULE_LICENSE("GPL"); diff --git a/drivers/clk/meson/gxbb.c b/drivers/clk/meson/gxbb.c index 1b1279d94781..29507b8c4304 100644 --- a/drivers/clk/meson/gxbb.c +++ b/drivers/clk/meson/gxbb.c @@ -3569,4 +3569,4 @@ static struct platform_driver gxbb_driver = { }; module_platform_driver(gxbb_driver); -MODULE_LICENSE("GPL v2"); +MODULE_LICENSE("GPL"); diff --git a/drivers/clk/meson/meson-aoclk.c b/drivers/clk/meson/meson-aoclk.c index bf466fef263c..b8a9d59e6726 100644 --- a/drivers/clk/meson/meson-aoclk.c +++ b/drivers/clk/meson/meson-aoclk.c @@ -89,4 +89,4 @@ int meson_aoclkc_probe(struct platform_device *pdev) return devm_of_clk_add_hw_provider(dev, meson_clk_hw_get, (void *)&data->hw_clks); } EXPORT_SYMBOL_GPL(meson_aoclkc_probe); -MODULE_LICENSE("GPL v2"); +MODULE_LICENSE("GPL"); diff --git a/drivers/clk/meson/meson-eeclk.c b/drivers/clk/meson/meson-eeclk.c index 845ca8bfa346..3cbc7f233bba 100644 --- a/drivers/clk/meson/meson-eeclk.c +++ b/drivers/clk/meson/meson-eeclk.c @@ -58,4 +58,4 @@ int meson_eeclkc_probe(struct platform_device *pdev) return devm_of_clk_add_hw_provider(dev, meson_clk_hw_get, (void *)&data->hw_clks); } EXPORT_SYMBOL_GPL(meson_eeclkc_probe); -MODULE_LICENSE("GPL v2"); +MODULE_LICENSE("GPL"); diff --git a/drivers/clk/meson/sclk-div.c b/drivers/clk/meson/sclk-div.c index d12c45c4c261..987f5b06587c 100644 --- a/drivers/clk/meson/sclk-div.c +++ b/drivers/clk/meson/sclk-div.c @@ -251,4 +251,4 @@ EXPORT_SYMBOL_GPL(meson_sclk_div_ops); MODULE_DESCRIPTION("Amlogic Sample divider driver"); MODULE_AUTHOR("Jerome Brunet "); -MODULE_LICENSE("GPL v2"); +MODULE_LICENSE("GPL"); diff --git a/drivers/clk/meson/vclk.c b/drivers/clk/meson/vclk.c index 45dc216941ea..e886df55d6e3 100644 --- a/drivers/clk/meson/vclk.c +++ b/drivers/clk/meson/vclk.c @@ -138,4 +138,4 @@ EXPORT_SYMBOL_GPL(meson_vclk_div_ops); MODULE_DESCRIPTION("Amlogic vclk clock driver"); MODULE_AUTHOR("Neil Armstrong "); -MODULE_LICENSE("GPL v2"); +MODULE_LICENSE("GPL"); diff --git a/drivers/clk/meson/vid-pll-div.c b/drivers/clk/meson/vid-pll-div.c index daff235bc763..ee129f86794d 100644 --- a/drivers/clk/meson/vid-pll-div.c +++ b/drivers/clk/meson/vid-pll-div.c @@ -96,4 +96,4 @@ EXPORT_SYMBOL_GPL(meson_vid_pll_div_ro_ops); MODULE_DESCRIPTION("Amlogic video pll divider driver"); MODULE_AUTHOR("Neil Armstrong "); -MODULE_LICENSE("GPL v2"); +MODULE_LICENSE("GPL"); From 1aab318f1e4900fac325e0d55a0591108ea0cfbb Mon Sep 17 00:00:00 2001 From: Krzysztof Kozlowski Date: Wed, 10 Apr 2024 17:53:56 +0200 Subject: [PATCH 025/118] clk: qcom: fix module autoloading Add MODULE_DEVICE_TABLE(), so modules could be properly autoloaded based on the alias from of_device_id table. Clocks are considered core components, so usually they are built-in, however these can be built and used as modules on some generic kernel. Signed-off-by: Krzysztof Kozlowski Reviewed-by: Neil Armstrong Reviewed-by: Konrad Dybcio Link: https://lore.kernel.org/r/20240410155356.224098-1-krzk@kernel.org Signed-off-by: Bjorn Andersson --- drivers/clk/qcom/gcc-msm8917.c | 1 + drivers/clk/qcom/gcc-msm8953.c | 1 + 2 files changed, 2 insertions(+) diff --git a/drivers/clk/qcom/gcc-msm8917.c b/drivers/clk/qcom/gcc-msm8917.c index f2dd132e2fb1..f2b8729e4198 100644 --- a/drivers/clk/qcom/gcc-msm8917.c +++ b/drivers/clk/qcom/gcc-msm8917.c @@ -3278,6 +3278,7 @@ static const struct of_device_id gcc_msm8917_match_table[] = { { .compatible = "qcom,gcc-qm215", .data = &gcc_qm215_desc }, {}, }; +MODULE_DEVICE_TABLE(of, gcc_msm8917_match_table); static struct platform_driver gcc_msm8917_driver = { .probe = gcc_msm8917_probe, diff --git a/drivers/clk/qcom/gcc-msm8953.c b/drivers/clk/qcom/gcc-msm8953.c index 68359534ff25..7563bff58118 100644 --- a/drivers/clk/qcom/gcc-msm8953.c +++ b/drivers/clk/qcom/gcc-msm8953.c @@ -4227,6 +4227,7 @@ static const struct of_device_id gcc_msm8953_match_table[] = { { .compatible = "qcom,gcc-msm8953" }, {}, }; +MODULE_DEVICE_TABLE(of, gcc_msm8953_match_table); static struct platform_driver gcc_msm8953_driver = { .probe = gcc_msm8953_probe, From 0a382be005cf8e7ac1b6ed25f47c2f599b1ff6af Mon Sep 17 00:00:00 2001 From: Lorenzo Bianconi Date: Sat, 6 Apr 2024 12:43:41 +0200 Subject: [PATCH 026/118] dt-bindings: clock: airoha: add EN7581 binding Introduce Airoha EN7581 entry in Airoha EN7523 clock binding Signed-off-by: Lorenzo Bianconi Link: https://lore.kernel.org/r/99734deb28889e685a764da94418f68b55ee3bdc.1712399981.git.lorenzo@kernel.org Reviewed-by: Krzysztof Kozlowski Signed-off-by: Stephen Boyd --- .../bindings/clock/airoha,en7523-scu.yaml | 31 +++++++++++++++++-- 1 file changed, 29 insertions(+), 2 deletions(-) diff --git a/Documentation/devicetree/bindings/clock/airoha,en7523-scu.yaml b/Documentation/devicetree/bindings/clock/airoha,en7523-scu.yaml index 79b0752faa91..3f4266637733 100644 --- a/Documentation/devicetree/bindings/clock/airoha,en7523-scu.yaml +++ b/Documentation/devicetree/bindings/clock/airoha,en7523-scu.yaml @@ -29,10 +29,13 @@ description: | properties: compatible: items: - - const: airoha,en7523-scu + - enum: + - airoha,en7523-scu + - airoha,en7581-scu reg: - maxItems: 2 + minItems: 2 + maxItems: 3 "#clock-cells": description: @@ -45,6 +48,30 @@ required: - reg - '#clock-cells' +allOf: + - if: + properties: + compatible: + const: airoha,en7523-scu + then: + properties: + reg: + items: + - description: scu base address + - description: misc scu base address + + - if: + properties: + compatible: + const: airoha,en7581-scu + then: + properties: + reg: + items: + - description: scu base address + - description: misc scu base address + - description: pb scu base address + additionalProperties: false examples: From 457e74667f452d7f071ad2b2d9313ec62ebc4b02 Mon Sep 17 00:00:00 2001 From: Lorenzo Bianconi Date: Sat, 6 Apr 2024 12:43:43 +0200 Subject: [PATCH 027/118] clk: en7523: Add en_clk_soc_data data structure Introduce en_clk_soc_data data structure in order to define multiple clk_ops for each supported SoC. This is a preliminary patch to introduce EN7581 clock support. Tested-by: Zhengping Zhang Signed-off-by: Lorenzo Bianconi Link: https://lore.kernel.org/r/562a0da8d7874a02a324687c152c87a1549924bd.1712399981.git.lorenzo@kernel.org Signed-off-by: Stephen Boyd --- drivers/clk/clk-en7523.c | 34 +++++++++++++++++++++------------- 1 file changed, 21 insertions(+), 13 deletions(-) diff --git a/drivers/clk/clk-en7523.c b/drivers/clk/clk-en7523.c index 7cde328495e2..3fac049c2518 100644 --- a/drivers/clk/clk-en7523.c +++ b/drivers/clk/clk-en7523.c @@ -3,8 +3,8 @@ #include #include #include -#include #include +#include #include #define REG_PCI_CONTROL 0x88 @@ -47,6 +47,10 @@ struct en_clk_gate { struct clk_hw hw; }; +struct en_clk_soc_data { + const struct clk_ops pcie_ops; +}; + static const u32 gsw_base[] = { 400000000, 500000000 }; static const u32 emi_base[] = { 333000000, 400000000 }; static const u32 bus_base[] = { 500000000, 540000000 }; @@ -145,11 +149,6 @@ static const struct en_clk_desc en7523_base_clks[] = { } }; -static const struct of_device_id of_match_clk_en7523[] = { - { .compatible = "airoha,en7523-scu", }, - { /* sentinel */ } -}; - static unsigned int en7523_get_base_rate(void __iomem *base, unsigned int i) { const struct en_clk_desc *desc = &en7523_base_clks[i]; @@ -247,14 +246,10 @@ static void en7523_pci_unprepare(struct clk_hw *hw) static struct clk_hw *en7523_register_pcie_clk(struct device *dev, void __iomem *np_base) { - static const struct clk_ops pcie_gate_ops = { - .is_enabled = en7523_pci_is_enabled, - .prepare = en7523_pci_prepare, - .unprepare = en7523_pci_unprepare, - }; + const struct en_clk_soc_data *soc_data = device_get_match_data(dev); struct clk_init_data init = { .name = "pcie", - .ops = &pcie_gate_ops, + .ops = &soc_data->pcie_ops, }; struct en_clk_gate *cg; @@ -264,7 +259,7 @@ static struct clk_hw *en7523_register_pcie_clk(struct device *dev, cg->base = np_base; cg->hw.init = &init; - en7523_pci_unprepare(&cg->hw); + init.ops->unprepare(&cg->hw); if (clk_hw_register(dev, &cg->hw)) return NULL; @@ -333,6 +328,19 @@ static int en7523_clk_probe(struct platform_device *pdev) return r; } +static const struct en_clk_soc_data en7523_data = { + .pcie_ops = { + .is_enabled = en7523_pci_is_enabled, + .prepare = en7523_pci_prepare, + .unprepare = en7523_pci_unprepare, + }, +}; + +static const struct of_device_id of_match_clk_en7523[] = { + { .compatible = "airoha,en7523-scu", .data = &en7523_data }, + { /* sentinel */ } +}; + static struct platform_driver clk_en7523_drv = { .probe = en7523_clk_probe, .driver = { From 66bc47326ce2a319add7e933d9340215711236ac Mon Sep 17 00:00:00 2001 From: Lorenzo Bianconi Date: Sat, 6 Apr 2024 12:43:44 +0200 Subject: [PATCH 028/118] clk: en7523: Add EN7581 support Introduce EN7581 clock support to clk-en7523 driver. Add hw_init callback to en_clk_soc_data data structure. Tested-by: Zhengping Zhang Signed-off-by: Lorenzo Bianconi Link: https://lore.kernel.org/r/57b6e53ed4d2b2e38abff6a3ea56841bad6be8a9.1712399981.git.lorenzo@kernel.org Signed-off-by: Stephen Boyd --- drivers/clk/clk-en7523.c | 157 +++++++++++++++++++++++++++++++++++++-- 1 file changed, 152 insertions(+), 5 deletions(-) diff --git a/drivers/clk/clk-en7523.c b/drivers/clk/clk-en7523.c index 3fac049c2518..ccc394692671 100644 --- a/drivers/clk/clk-en7523.c +++ b/drivers/clk/clk-en7523.c @@ -10,7 +10,9 @@ #define REG_PCI_CONTROL 0x88 #define REG_PCI_CONTROL_PERSTOUT BIT(29) #define REG_PCI_CONTROL_PERSTOUT1 BIT(26) +#define REG_PCI_CONTROL_REFCLK_EN0 BIT(23) #define REG_PCI_CONTROL_REFCLK_EN1 BIT(22) +#define REG_PCI_CONTROL_PERSTOUT2 BIT(16) #define REG_GSW_CLK_DIV_SEL 0x1b4 #define REG_EMI_CLK_DIV_SEL 0x1b8 #define REG_BUS_CLK_DIV_SEL 0x1bc @@ -18,10 +20,25 @@ #define REG_SPI_CLK_FREQ_SEL 0x1c8 #define REG_NPU_CLK_DIV_SEL 0x1fc #define REG_CRYPTO_CLKSRC 0x200 -#define REG_RESET_CONTROL 0x834 +#define REG_RESET_CONTROL2 0x830 +#define REG_RESET2_CONTROL_PCIE2 BIT(27) +#define REG_RESET_CONTROL1 0x834 #define REG_RESET_CONTROL_PCIEHB BIT(29) #define REG_RESET_CONTROL_PCIE1 BIT(27) #define REG_RESET_CONTROL_PCIE2 BIT(26) +/* EN7581 */ +#define REG_PCIE0_MEM 0x00 +#define REG_PCIE0_MEM_MASK 0x04 +#define REG_PCIE1_MEM 0x08 +#define REG_PCIE1_MEM_MASK 0x0c +#define REG_PCIE2_MEM 0x10 +#define REG_PCIE2_MEM_MASK 0x14 +#define REG_PCIE_RESET_OPEN_DRAIN 0x018c +#define REG_PCIE_RESET_OPEN_DRAIN_MASK GENMASK(2, 0) +#define REG_NP_SCU_PCIC 0x88 +#define REG_NP_SCU_SSTR 0x9c +#define REG_PCIE_XSI0_SEL_MASK GENMASK(14, 13) +#define REG_PCIE_XSI1_SEL_MASK GENMASK(12, 11) struct en_clk_desc { int id; @@ -49,6 +66,8 @@ struct en_clk_gate { struct en_clk_soc_data { const struct clk_ops pcie_ops; + int (*hw_init)(struct platform_device *pdev, void __iomem *base, + void __iomem *np_base); }; static const u32 gsw_base[] = { 400000000, 500000000 }; @@ -211,14 +230,14 @@ static int en7523_pci_prepare(struct clk_hw *hw) usleep_range(1000, 2000); /* Reset to default */ - val = readl(np_base + REG_RESET_CONTROL); + val = readl(np_base + REG_RESET_CONTROL1); mask = REG_RESET_CONTROL_PCIE1 | REG_RESET_CONTROL_PCIE2 | REG_RESET_CONTROL_PCIEHB; - writel(val & ~mask, np_base + REG_RESET_CONTROL); + writel(val & ~mask, np_base + REG_RESET_CONTROL1); usleep_range(1000, 2000); - writel(val | mask, np_base + REG_RESET_CONTROL); + writel(val | mask, np_base + REG_RESET_CONTROL1); msleep(100); - writel(val & ~mask, np_base + REG_RESET_CONTROL); + writel(val & ~mask, np_base + REG_RESET_CONTROL1); usleep_range(5000, 10000); /* Release device */ @@ -259,6 +278,9 @@ static struct clk_hw *en7523_register_pcie_clk(struct device *dev, cg->base = np_base; cg->hw.init = &init; + + if (init.ops->disable) + init.ops->disable(&cg->hw); init.ops->unprepare(&cg->hw); if (clk_hw_register(dev, &cg->hw)) @@ -267,6 +289,111 @@ static struct clk_hw *en7523_register_pcie_clk(struct device *dev, return &cg->hw; } +static int en7581_pci_is_enabled(struct clk_hw *hw) +{ + struct en_clk_gate *cg = container_of(hw, struct en_clk_gate, hw); + u32 val, mask; + + mask = REG_PCI_CONTROL_REFCLK_EN0 | REG_PCI_CONTROL_REFCLK_EN1; + val = readl(cg->base + REG_PCI_CONTROL); + return (val & mask) == mask; +} + +static int en7581_pci_prepare(struct clk_hw *hw) +{ + struct en_clk_gate *cg = container_of(hw, struct en_clk_gate, hw); + void __iomem *np_base = cg->base; + u32 val, mask; + + mask = REG_RESET_CONTROL_PCIE1 | REG_RESET_CONTROL_PCIE2 | + REG_RESET_CONTROL_PCIEHB; + val = readl(np_base + REG_RESET_CONTROL1); + writel(val & ~mask, np_base + REG_RESET_CONTROL1); + val = readl(np_base + REG_RESET_CONTROL2); + writel(val & ~REG_RESET2_CONTROL_PCIE2, np_base + REG_RESET_CONTROL2); + usleep_range(5000, 10000); + + return 0; +} + +static int en7581_pci_enable(struct clk_hw *hw) +{ + struct en_clk_gate *cg = container_of(hw, struct en_clk_gate, hw); + void __iomem *np_base = cg->base; + u32 val, mask; + + mask = REG_PCI_CONTROL_REFCLK_EN0 | REG_PCI_CONTROL_REFCLK_EN1 | + REG_PCI_CONTROL_PERSTOUT1 | REG_PCI_CONTROL_PERSTOUT2 | + REG_PCI_CONTROL_PERSTOUT; + val = readl(np_base + REG_PCI_CONTROL); + writel(val | mask, np_base + REG_PCI_CONTROL); + msleep(250); + + return 0; +} + +static void en7581_pci_unprepare(struct clk_hw *hw) +{ + struct en_clk_gate *cg = container_of(hw, struct en_clk_gate, hw); + void __iomem *np_base = cg->base; + u32 val, mask; + + mask = REG_RESET_CONTROL_PCIE1 | REG_RESET_CONTROL_PCIE2 | + REG_RESET_CONTROL_PCIEHB; + val = readl(np_base + REG_RESET_CONTROL1); + writel(val | mask, np_base + REG_RESET_CONTROL1); + mask = REG_RESET_CONTROL_PCIE1 | REG_RESET_CONTROL_PCIE2; + writel(val | mask, np_base + REG_RESET_CONTROL1); + val = readl(np_base + REG_RESET_CONTROL2); + writel(val | REG_RESET_CONTROL_PCIE2, np_base + REG_RESET_CONTROL2); + msleep(100); +} + +static void en7581_pci_disable(struct clk_hw *hw) +{ + struct en_clk_gate *cg = container_of(hw, struct en_clk_gate, hw); + void __iomem *np_base = cg->base; + u32 val, mask; + + mask = REG_PCI_CONTROL_REFCLK_EN0 | REG_PCI_CONTROL_REFCLK_EN1 | + REG_PCI_CONTROL_PERSTOUT1 | REG_PCI_CONTROL_PERSTOUT2 | + REG_PCI_CONTROL_PERSTOUT; + val = readl(np_base + REG_PCI_CONTROL); + writel(val & ~mask, np_base + REG_PCI_CONTROL); + usleep_range(1000, 2000); +} + +static int en7581_clk_hw_init(struct platform_device *pdev, + void __iomem *base, + void __iomem *np_base) +{ + void __iomem *pb_base; + u32 val; + + pb_base = devm_platform_ioremap_resource(pdev, 2); + if (IS_ERR(pb_base)) + return PTR_ERR(pb_base); + + val = readl(np_base + REG_NP_SCU_SSTR); + val &= ~(REG_PCIE_XSI0_SEL_MASK | REG_PCIE_XSI1_SEL_MASK); + writel(val, np_base + REG_NP_SCU_SSTR); + val = readl(np_base + REG_NP_SCU_PCIC); + writel(val | 3, np_base + REG_NP_SCU_PCIC); + + writel(0x20000000, pb_base + REG_PCIE0_MEM); + writel(0xfc000000, pb_base + REG_PCIE0_MEM_MASK); + writel(0x24000000, pb_base + REG_PCIE1_MEM); + writel(0xfc000000, pb_base + REG_PCIE1_MEM_MASK); + writel(0x28000000, pb_base + REG_PCIE2_MEM); + writel(0xfc000000, pb_base + REG_PCIE2_MEM_MASK); + + val = readl(base + REG_PCIE_RESET_OPEN_DRAIN); + writel(val | REG_PCIE_RESET_OPEN_DRAIN_MASK, + base + REG_PCIE_RESET_OPEN_DRAIN); + + return 0; +} + static void en7523_register_clocks(struct device *dev, struct clk_hw_onecell_data *clk_data, void __iomem *base, void __iomem *np_base) { @@ -299,6 +426,7 @@ static void en7523_register_clocks(struct device *dev, struct clk_hw_onecell_dat static int en7523_clk_probe(struct platform_device *pdev) { struct device_node *node = pdev->dev.of_node; + const struct en_clk_soc_data *soc_data; struct clk_hw_onecell_data *clk_data; void __iomem *base, *np_base; int r; @@ -311,6 +439,13 @@ static int en7523_clk_probe(struct platform_device *pdev) if (IS_ERR(np_base)) return PTR_ERR(np_base); + soc_data = device_get_match_data(&pdev->dev); + if (soc_data->hw_init) { + r = soc_data->hw_init(pdev, base, np_base); + if (r) + return r; + } + clk_data = devm_kzalloc(&pdev->dev, struct_size(clk_data, hws, EN7523_NUM_CLOCKS), GFP_KERNEL); @@ -336,8 +471,20 @@ static const struct en_clk_soc_data en7523_data = { }, }; +static const struct en_clk_soc_data en7581_data = { + .pcie_ops = { + .is_enabled = en7581_pci_is_enabled, + .prepare = en7581_pci_prepare, + .enable = en7581_pci_enable, + .unprepare = en7581_pci_unprepare, + .disable = en7581_pci_disable, + }, + .hw_init = en7581_clk_hw_init, +}; + static const struct of_device_id of_match_clk_en7523[] = { { .compatible = "airoha,en7523-scu", .data = &en7523_data }, + { .compatible = "airoha,en7581-scu", .data = &en7581_data }, { /* sentinel */ } }; From bb7b3c8e7180f36de75cdea200ab7127f93f58cc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?N=C3=ADcolas=20F=2E=20R=2E=20A=2E=20Prado?= Date: Fri, 8 Mar 2024 15:29:56 -0500 Subject: [PATCH 029/118] clk: mediatek: pllfh: Don't log error for missing fhctl node MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Support for fhctl clocks in apmixedsys was introduced at a later point and to this moment only one mt6795 based platform has a fhctl DT node present. Therefore the fhctl support in apmixedsys should be seen as optional and not cause an error when it is missing. Change the message's log level to warning. The warning level is chosen so that it will still alert the fact that fhctl support might be unintentionally missing, but without implying that this is necessarily an issue. Even if the FHCTL DT nodes are added to all current platforms moving forward, since those changes won't be backported, this ensures stable kernel releases won't have live with this error. Fixes: d7964de8a8ea ("clk: mediatek: Add new clock driver to handle FHCTL hardware") Signed-off-by: Nícolas F. R. A. Prado Link: https://lore.kernel.org/r/20240308-mtk-fhctl-no-node-error-v1-1-51e446eb149a@collabora.com Reviewed-by: AngeloGioacchino Del Regno Signed-off-by: Stephen Boyd --- drivers/clk/mediatek/clk-pllfh.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/clk/mediatek/clk-pllfh.c b/drivers/clk/mediatek/clk-pllfh.c index 3a2b3f90be25..094ec8a26d66 100644 --- a/drivers/clk/mediatek/clk-pllfh.c +++ b/drivers/clk/mediatek/clk-pllfh.c @@ -68,7 +68,7 @@ void fhctl_parse_dt(const u8 *compatible_node, struct mtk_pllfh_data *pllfhs, node = of_find_compatible_node(NULL, NULL, compatible_node); if (!node) { - pr_err("cannot find \"%s\"\n", compatible_node); + pr_warn("cannot find \"%s\"\n", compatible_node); return; } From 50e45d3b03fd20d663dc8e76fc881ba722403676 Mon Sep 17 00:00:00 2001 From: Inochi Amaoto Date: Sat, 9 Mar 2024 17:02:51 +0800 Subject: [PATCH 030/118] dt-bindings: clock: sophgo: Add clock controller of SG2000 series SoC SG2000 series SoC has the same clock as CV1810 series, but the clock related to A53 is functional in SG2000 series. So a new compatible string is needed for the new SoC. Add definition for the clock controller of the SG2000 series SoC. Link: https://github.com/sophgo/sophgo-doc/releases/tag/sg2000-datasheet-v1.0-alpha Acked-by: Krzysztof Kozlowski Signed-off-by: Inochi Amaoto Link: https://lore.kernel.org/r/IA1PR20MB495368F185E018767CC6714ABB262@IA1PR20MB4953.namprd20.prod.outlook.com Signed-off-by: Stephen Boyd --- Documentation/devicetree/bindings/clock/sophgo,cv1800-clk.yaml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Documentation/devicetree/bindings/clock/sophgo,cv1800-clk.yaml b/Documentation/devicetree/bindings/clock/sophgo,cv1800-clk.yaml index c1dc24673c0d..59ef41adb539 100644 --- a/Documentation/devicetree/bindings/clock/sophgo,cv1800-clk.yaml +++ b/Documentation/devicetree/bindings/clock/sophgo,cv1800-clk.yaml @@ -4,7 +4,7 @@ $id: http://devicetree.org/schemas/clock/sophgo,cv1800-clk.yaml# $schema: http://devicetree.org/meta-schemas/core.yaml# -title: Sophgo CV1800 Series Clock Controller +title: Sophgo CV1800/SG2000 Series Clock Controller maintainers: - Inochi Amaoto @@ -14,6 +14,7 @@ properties: enum: - sophgo,cv1800-clk - sophgo,cv1810-clk + - sophgo,sg2000-clk reg: maxItems: 1 From 80fd61ec46124eb83b29de3647a565f69979e753 Mon Sep 17 00:00:00 2001 From: Inochi Amaoto Date: Sat, 9 Mar 2024 17:02:52 +0800 Subject: [PATCH 031/118] clk: sophgo: Add clock support for CV1800 SoC Add clock definition and driver code for CV1800 SoC. Signed-off-by: Inochi Amaoto Link: https://github.com/milkv-duo/duo-files/blob/6f4e9b8ecb459e017cca1a8df248a19ca70837a3/duo/datasheet/CV180X-Clock-v1.xlsx Link: https://github.com/milkv-duo/duo-files/blob/6f4e9b8ecb459e017cca1a8df248a19ca70837a3/duo/datasheet/CV1800B-CV1801B-Preliminary-Datasheet-full-en.pdf Link: https://lore.kernel.org/r/IA1PR20MB49534F37F802CAF117364D66BB262@IA1PR20MB4953.namprd20.prod.outlook.com Signed-off-by: Stephen Boyd --- drivers/clk/Kconfig | 1 + drivers/clk/Makefile | 1 + drivers/clk/sophgo/Kconfig | 11 + drivers/clk/sophgo/Makefile | 7 + drivers/clk/sophgo/clk-cv1800.c | 1327 ++++++++++++++++++++++++ drivers/clk/sophgo/clk-cv1800.h | 122 +++ drivers/clk/sophgo/clk-cv18xx-common.c | 66 ++ drivers/clk/sophgo/clk-cv18xx-common.h | 81 ++ drivers/clk/sophgo/clk-cv18xx-ip.c | 887 ++++++++++++++++ drivers/clk/sophgo/clk-cv18xx-ip.h | 261 +++++ drivers/clk/sophgo/clk-cv18xx-pll.c | 420 ++++++++ drivers/clk/sophgo/clk-cv18xx-pll.h | 118 +++ 12 files changed, 3302 insertions(+) create mode 100644 drivers/clk/sophgo/Kconfig create mode 100644 drivers/clk/sophgo/Makefile create mode 100644 drivers/clk/sophgo/clk-cv1800.c create mode 100644 drivers/clk/sophgo/clk-cv1800.h create mode 100644 drivers/clk/sophgo/clk-cv18xx-common.c create mode 100644 drivers/clk/sophgo/clk-cv18xx-common.h create mode 100644 drivers/clk/sophgo/clk-cv18xx-ip.c create mode 100644 drivers/clk/sophgo/clk-cv18xx-ip.h create mode 100644 drivers/clk/sophgo/clk-cv18xx-pll.c create mode 100644 drivers/clk/sophgo/clk-cv18xx-pll.h diff --git a/drivers/clk/Kconfig b/drivers/clk/Kconfig index 50af5fc7f570..bc28502ec3c9 100644 --- a/drivers/clk/Kconfig +++ b/drivers/clk/Kconfig @@ -489,6 +489,7 @@ source "drivers/clk/rockchip/Kconfig" source "drivers/clk/samsung/Kconfig" source "drivers/clk/sifive/Kconfig" source "drivers/clk/socfpga/Kconfig" +source "drivers/clk/sophgo/Kconfig" source "drivers/clk/sprd/Kconfig" source "drivers/clk/starfive/Kconfig" source "drivers/clk/sunxi/Kconfig" diff --git a/drivers/clk/Makefile b/drivers/clk/Makefile index 14fa8d4ecc1f..4abe16c8ccdf 100644 --- a/drivers/clk/Makefile +++ b/drivers/clk/Makefile @@ -118,6 +118,7 @@ obj-$(CONFIG_ARCH_ROCKCHIP) += rockchip/ obj-$(CONFIG_COMMON_CLK_SAMSUNG) += samsung/ obj-$(CONFIG_CLK_SIFIVE) += sifive/ obj-y += socfpga/ +obj-y += sophgo/ obj-$(CONFIG_PLAT_SPEAR) += spear/ obj-y += sprd/ obj-$(CONFIG_ARCH_STI) += st/ diff --git a/drivers/clk/sophgo/Kconfig b/drivers/clk/sophgo/Kconfig new file mode 100644 index 000000000000..1cc49be71bdb --- /dev/null +++ b/drivers/clk/sophgo/Kconfig @@ -0,0 +1,11 @@ +# SPDX-License-Identifier: GPL-2.0 +# common clock support for SOPHGO SoC family. + +config CLK_SOPHGO_CV1800 + tristate "Support for the Sophgo CV1800 series SoCs clock controller" + depends on ARCH_SOPHGO || COMPILE_TEST + help + This driver supports clock controller of Sophgo CV18XX series SoC. + The driver require a 25MHz Oscillator to function generate clock. + It includes PLLs, common clock function and some vendor clock for + IPs of CV18XX series SoC diff --git a/drivers/clk/sophgo/Makefile b/drivers/clk/sophgo/Makefile new file mode 100644 index 000000000000..a50320764200 --- /dev/null +++ b/drivers/clk/sophgo/Makefile @@ -0,0 +1,7 @@ +# SPDX-License-Identifier: GPL-2.0 +obj-$(CONFIG_CLK_SOPHGO_CV1800) += clk-sophgo-cv1800.o + +clk-sophgo-cv1800-y += clk-cv1800.o +clk-sophgo-cv1800-y += clk-cv18xx-common.o +clk-sophgo-cv1800-y += clk-cv18xx-ip.o +clk-sophgo-cv1800-y += clk-cv18xx-pll.o diff --git a/drivers/clk/sophgo/clk-cv1800.c b/drivers/clk/sophgo/clk-cv1800.c new file mode 100644 index 000000000000..6606a2701b12 --- /dev/null +++ b/drivers/clk/sophgo/clk-cv1800.c @@ -0,0 +1,1327 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (C) 2023 Inochi Amaoto + */ + +#include +#include +#include +#include +#include + +#include "clk-cv1800.h" + +#include "clk-cv18xx-common.h" +#include "clk-cv18xx-ip.h" +#include "clk-cv18xx-pll.h" + +struct cv1800_clk_ctrl; + +struct cv1800_clk_desc { + struct clk_hw_onecell_data *clks_data; + + int (*pre_init)(struct device *dev, void __iomem *base, + struct cv1800_clk_ctrl *ctrl, + const struct cv1800_clk_desc *desc); +}; + +struct cv1800_clk_ctrl { + const struct cv1800_clk_desc *desc; + spinlock_t lock; +}; + +#define CV1800_DIV_FLAG \ + (CLK_DIVIDER_ONE_BASED | CLK_DIVIDER_ROUND_CLOSEST) +static const struct clk_parent_data osc_parents[] = { + { .index = 0 }, +}; + +static const struct cv1800_clk_pll_limit pll_limits[] = { + { + .pre_div = _CV1800_PLL_LIMIT(1, 127), + .div = _CV1800_PLL_LIMIT(6, 127), + .post_div = _CV1800_PLL_LIMIT(1, 127), + .ictrl = _CV1800_PLL_LIMIT(0, 7), + .mode = _CV1800_PLL_LIMIT(0, 3), + }, + { + .pre_div = _CV1800_PLL_LIMIT(1, 127), + .div = _CV1800_PLL_LIMIT(6, 127), + .post_div = _CV1800_PLL_LIMIT(1, 127), + .ictrl = _CV1800_PLL_LIMIT(0, 7), + .mode = _CV1800_PLL_LIMIT(0, 3), + }, +}; + +static CV1800_INTEGRAL_PLL(clk_fpll, osc_parents, + REG_FPLL_CSR, + REG_PLL_G6_CTRL, 8, + REG_PLL_G6_STATUS, 2, + pll_limits, + CLK_IS_CRITICAL); + +static CV1800_INTEGRAL_PLL(clk_mipimpll, osc_parents, + REG_MIPIMPLL_CSR, + REG_PLL_G2_CTRL, 0, + REG_PLL_G2_STATUS, 0, + pll_limits, + CLK_IS_CRITICAL); + +static const struct clk_parent_data clk_mipimpll_parents[] = { + { .hw = &clk_mipimpll.common.hw }, +}; +static const struct clk_parent_data clk_bypass_mipimpll_parents[] = { + { .index = 0 }, + { .hw = &clk_mipimpll.common.hw }, +}; +static const struct clk_parent_data clk_bypass_fpll_parents[] = { + { .index = 0 }, + { .hw = &clk_fpll.common.hw }, +}; + +struct cv1800_clk_pll_synthesizer clk_mpll_synthesizer = { + .en = CV1800_CLK_BIT(REG_PLL_G6_SSC_SYN_CTRL, 2), + .clk_half = CV1800_CLK_BIT(REG_PLL_G6_SSC_SYN_CTRL, 0), + .ctrl = REG_MPLL_SSC_SYN_CTRL, + .set = REG_MPLL_SSC_SYN_SET, +}; +static CV1800_FACTIONAL_PLL(clk_mpll, clk_bypass_mipimpll_parents, + REG_MPLL_CSR, + REG_PLL_G6_CTRL, 0, + REG_PLL_G6_STATUS, 0, + pll_limits, + &clk_mpll_synthesizer, + CLK_IS_CRITICAL); + +struct cv1800_clk_pll_synthesizer clk_tpll_synthesizer = { + .en = CV1800_CLK_BIT(REG_PLL_G6_SSC_SYN_CTRL, 3), + .clk_half = CV1800_CLK_BIT(REG_PLL_G6_SSC_SYN_CTRL, 0), + .ctrl = REG_TPLL_SSC_SYN_CTRL, + .set = REG_TPLL_SSC_SYN_SET, +}; +static CV1800_FACTIONAL_PLL(clk_tpll, clk_bypass_mipimpll_parents, + REG_TPLL_CSR, + REG_PLL_G6_CTRL, 4, + REG_PLL_G6_STATUS, 1, + pll_limits, + &clk_tpll_synthesizer, + CLK_IS_CRITICAL); + +struct cv1800_clk_pll_synthesizer clk_a0pll_synthesizer = { + .en = CV1800_CLK_BIT(REG_PLL_G2_SSC_SYN_CTRL, 2), + .clk_half = CV1800_CLK_BIT(REG_PLL_G2_SSC_SYN_CTRL, 0), + .ctrl = REG_A0PLL_SSC_SYN_CTRL, + .set = REG_A0PLL_SSC_SYN_SET, +}; +static CV1800_FACTIONAL_PLL(clk_a0pll, clk_bypass_mipimpll_parents, + REG_A0PLL_CSR, + REG_PLL_G2_CTRL, 4, + REG_PLL_G2_STATUS, 1, + pll_limits, + &clk_a0pll_synthesizer, + CLK_IS_CRITICAL); + +struct cv1800_clk_pll_synthesizer clk_disppll_synthesizer = { + .en = CV1800_CLK_BIT(REG_PLL_G2_SSC_SYN_CTRL, 3), + .clk_half = CV1800_CLK_BIT(REG_PLL_G2_SSC_SYN_CTRL, 0), + .ctrl = REG_DISPPLL_SSC_SYN_CTRL, + .set = REG_DISPPLL_SSC_SYN_SET, +}; +static CV1800_FACTIONAL_PLL(clk_disppll, clk_bypass_mipimpll_parents, + REG_DISPPLL_CSR, + REG_PLL_G2_CTRL, 8, + REG_PLL_G2_STATUS, 2, + pll_limits, + &clk_disppll_synthesizer, + CLK_IS_CRITICAL); + +struct cv1800_clk_pll_synthesizer clk_cam0pll_synthesizer = { + .en = CV1800_CLK_BIT(REG_PLL_G2_SSC_SYN_CTRL, 4), + .clk_half = CV1800_CLK_BIT(REG_PLL_G2_SSC_SYN_CTRL, 0), + .ctrl = REG_CAM0PLL_SSC_SYN_CTRL, + .set = REG_CAM0PLL_SSC_SYN_SET, +}; +static CV1800_FACTIONAL_PLL(clk_cam0pll, clk_bypass_mipimpll_parents, + REG_CAM0PLL_CSR, + REG_PLL_G2_CTRL, 12, + REG_PLL_G2_STATUS, 3, + pll_limits, + &clk_cam0pll_synthesizer, + CLK_IGNORE_UNUSED); + +struct cv1800_clk_pll_synthesizer clk_cam1pll_synthesizer = { + .en = CV1800_CLK_BIT(REG_PLL_G2_SSC_SYN_CTRL, 5), + .clk_half = CV1800_CLK_BIT(REG_PLL_G2_SSC_SYN_CTRL, 0), + .ctrl = REG_CAM1PLL_SSC_SYN_CTRL, + .set = REG_CAM1PLL_SSC_SYN_SET, +}; +static CV1800_FACTIONAL_PLL(clk_cam1pll, clk_bypass_mipimpll_parents, + REG_CAM1PLL_CSR, + REG_PLL_G2_CTRL, 16, + REG_PLL_G2_STATUS, 4, + pll_limits, + &clk_cam1pll_synthesizer, + CLK_IS_CRITICAL); + +static const struct clk_parent_data clk_cam0pll_parents[] = { + { .hw = &clk_cam0pll.common.hw }, +}; + +/* G2D */ +static CV1800_FIXED_DIV(clk_cam0pll_d2, clk_cam0pll_parents, + REG_CAM0PLL_CLK_CSR, 1, + 2, + CLK_SET_RATE_PARENT | CLK_IGNORE_UNUSED); +static CV1800_FIXED_DIV(clk_cam0pll_d3, clk_cam0pll_parents, + REG_CAM0PLL_CLK_CSR, 2, + 3, + CLK_SET_RATE_PARENT | CLK_IGNORE_UNUSED); +static CV1800_FIXED_DIV(clk_mipimpll_d3, clk_mipimpll_parents, + REG_MIPIMPLL_CLK_CSR, 2, + 3, + CLK_SET_RATE_PARENT | CLK_IGNORE_UNUSED); + +/* TPU */ +static const struct clk_parent_data clk_tpu_parents[] = { + { .index = 0 }, + { .hw = &clk_tpll.common.hw }, + { .hw = &clk_a0pll.common.hw }, + { .hw = &clk_mipimpll.common.hw }, + { .hw = &clk_fpll.common.hw }, +}; + +static CV1800_BYPASS_MUX(clk_tpu, clk_tpu_parents, + REG_CLK_EN_0, 4, + REG_DIV_CLK_TPU, 16, 4, 3, CV1800_DIV_FLAG, + REG_DIV_CLK_TPU, 8, 2, + REG_CLK_BYP_0, 3, + 0); +static CV1800_GATE(clk_tpu_fab, clk_mipimpll_parents, + REG_CLK_EN_0, 5, + 0); + +/* FABRIC_AXI6 */ +static CV1800_BYPASS_DIV(clk_axi6, clk_bypass_fpll_parents, + REG_CLK_EN_2, 2, + REG_DIV_CLK_AXI6, 16, 4, 15, CV1800_DIV_FLAG, + REG_CLK_BYP_0, 20, + CLK_IS_CRITICAL); + +static const struct clk_parent_data clk_axi6_bus_parents[] = { + { .hw = &clk_axi6.div.common.hw }, +}; +static const struct clk_parent_data clk_bypass_axi6_bus_parents[] = { + { .index = 0 }, + { .hw = &clk_axi6.div.common.hw }, +}; + +/* FABRIC_AXI4 */ +static const struct clk_parent_data clk_axi4_parents[] = { + { .index = 0 }, + { .hw = &clk_fpll.common.hw }, + { .hw = &clk_disppll.common.hw }, +}; + +static CV1800_BYPASS_MUX(clk_axi4, clk_axi4_parents, + REG_CLK_EN_2, 1, + REG_DIV_CLK_AXI4, 16, 4, 5, CV1800_DIV_FLAG, + REG_DIV_CLK_AXI4, 8, 2, + REG_CLK_BYP_0, 19, + CLK_IS_CRITICAL); + +static const struct clk_parent_data clk_axi4_bus_parents[] = { + { .hw = &clk_axi4.mux.common.hw }, +}; + +/* XTAL_MISC */ +static CV1800_GATE(clk_xtal_misc, osc_parents, + REG_CLK_EN_0, 14, + CLK_IS_CRITICAL); + +static const struct clk_parent_data clk_timer_parents[] = { + { .hw = &clk_xtal_misc.common.hw }, +}; + +/* TOP */ +static const struct clk_parent_data clk_cam0_200_parents[] = { + { .index = 0 }, + { .index = 0 }, + { .hw = &clk_disppll.common.hw }, +}; + +static CV1800_BYPASS_MUX(clk_cam0_200, clk_cam0_200_parents, + REG_CLK_EN_1, 13, + REG_DIV_CLK_CAM0_200, 16, 4, 1, CV1800_DIV_FLAG, + REG_DIV_CLK_CAM0_200, 8, 2, + REG_CLK_BYP_0, 16, + CLK_IS_CRITICAL); +static CV1800_DIV(clk_1m, osc_parents, + REG_CLK_EN_3, 5, + REG_DIV_CLK_1M, 16, 6, 25, CV1800_DIV_FLAG, + CLK_IS_CRITICAL); +static CV1800_GATE(clk_pm, clk_axi6_bus_parents, + REG_CLK_EN_3, 8, + CLK_IS_CRITICAL); +static CV1800_GATE(clk_timer0, clk_timer_parents, + REG_CLK_EN_3, 9, + CLK_IS_CRITICAL); +static CV1800_GATE(clk_timer1, clk_timer_parents, + REG_CLK_EN_3, 10, + CLK_IS_CRITICAL); +static CV1800_GATE(clk_timer2, clk_timer_parents, + REG_CLK_EN_3, 11, + CLK_IS_CRITICAL); +static CV1800_GATE(clk_timer3, clk_timer_parents, + REG_CLK_EN_3, 12, + CLK_IS_CRITICAL); +static CV1800_GATE(clk_timer4, clk_timer_parents, + REG_CLK_EN_3, 13, + CLK_IS_CRITICAL); +static CV1800_GATE(clk_timer5, clk_timer_parents, + REG_CLK_EN_3, 14, + CLK_IS_CRITICAL); +static CV1800_GATE(clk_timer6, clk_timer_parents, + REG_CLK_EN_3, 15, + CLK_IS_CRITICAL); +static CV1800_GATE(clk_timer7, clk_timer_parents, + REG_CLK_EN_3, 16, + CLK_IS_CRITICAL); + +static const struct clk_parent_data clk_parents_1m[] = { + { .hw = &clk_1m.common.hw }, +}; +static const struct clk_parent_data clk_uart_parents[] = { + { .hw = &clk_cam0_200.mux.common.hw }, +}; + +/* AHB ROM */ +static CV1800_GATE(clk_ahb_rom, clk_axi4_bus_parents, + REG_CLK_EN_0, 6, + 0); + +/* RTC */ +static CV1800_GATE(clk_rtc_25m, osc_parents, + REG_CLK_EN_0, 8, + CLK_IS_CRITICAL); +static CV1800_BYPASS_DIV(clk_src_rtc_sys_0, clk_bypass_fpll_parents, + REG_CLK_EN_4, 6, + REG_DIV_CLK_RTCSYS_SRC_0, 16, 4, 5, CV1800_DIV_FLAG, + REG_CLK_BYP_1, 5, + CLK_IS_CRITICAL); + +/* TEMPSEN */ +static CV1800_GATE(clk_tempsen, osc_parents, + REG_CLK_EN_0, 9, + 0); + +/* SARADC */ +static CV1800_GATE(clk_saradc, osc_parents, + REG_CLK_EN_0, 10, + 0); + +/* EFUSE */ +static CV1800_GATE(clk_efuse, osc_parents, + REG_CLK_EN_0, 11, + 0); +static CV1800_GATE(clk_apb_efuse, osc_parents, + REG_CLK_EN_0, 12, + 0); + +/* WDT */ +static CV1800_GATE(clk_apb_wdt, osc_parents, + REG_CLK_EN_1, 7, + CLK_IS_CRITICAL); + +/* WGN */ +static CV1800_GATE(clk_wgn, osc_parents, + REG_CLK_EN_3, 22, + 0); +static CV1800_GATE(clk_wgn0, osc_parents, + REG_CLK_EN_3, 23, + 0); +static CV1800_GATE(clk_wgn1, osc_parents, + REG_CLK_EN_3, 24, + 0); +static CV1800_GATE(clk_wgn2, osc_parents, + REG_CLK_EN_3, 25, + 0); + +/* KEYSCAN */ +static CV1800_GATE(clk_keyscan, osc_parents, + REG_CLK_EN_3, 26, + 0); + +/* EMMC */ +static CV1800_GATE(clk_axi4_emmc, clk_axi4_bus_parents, + REG_CLK_EN_0, 15, + 0); +static CV1800_BYPASS_MUX(clk_emmc, clk_axi4_parents, + REG_CLK_EN_0, 16, + REG_DIV_CLK_EMMC, 16, 5, 15, CV1800_DIV_FLAG, + REG_DIV_CLK_EMMC, 8, 2, + REG_CLK_BYP_0, 5, + 0); +static CV1800_DIV(clk_emmc_100k, clk_parents_1m, + REG_CLK_EN_0, 17, + REG_DIV_CLK_EMMC_100K, 16, 8, 10, CV1800_DIV_FLAG, + 0); + +/* SD */ +static CV1800_GATE(clk_axi4_sd0, clk_axi4_bus_parents, + REG_CLK_EN_0, 18, + 0); +static CV1800_BYPASS_MUX(clk_sd0, clk_axi4_parents, + REG_CLK_EN_0, 19, + REG_DIV_CLK_SD0, 16, 5, 15, CV1800_DIV_FLAG, + REG_DIV_CLK_SD0, 8, 2, + REG_CLK_BYP_0, 6, + 0); +static CV1800_DIV(clk_sd0_100k, clk_parents_1m, + REG_CLK_EN_0, 20, + REG_DIV_CLK_SD0_100K, 16, 8, 10, CV1800_DIV_FLAG, + 0); +static CV1800_GATE(clk_axi4_sd1, clk_axi4_bus_parents, + REG_CLK_EN_0, 21, + 0); +static CV1800_BYPASS_MUX(clk_sd1, clk_axi4_parents, + REG_CLK_EN_0, 22, + REG_DIV_CLK_SD1, 16, 5, 15, CV1800_DIV_FLAG, + REG_DIV_CLK_SD1, 8, 2, + REG_CLK_BYP_0, 7, + 0); +static CV1800_DIV(clk_sd1_100k, clk_parents_1m, + REG_CLK_EN_0, 23, + REG_DIV_CLK_SD1_100K, 16, 8, 10, CV1800_DIV_FLAG, + 0); + +/* SPI NAND */ +static CV1800_BYPASS_MUX(clk_spi_nand, clk_axi4_parents, + REG_CLK_EN_0, 24, + REG_DIV_CLK_SPI_NAND, 16, 5, 8, CV1800_DIV_FLAG, + REG_DIV_CLK_SPI_NAND, 8, 2, + REG_CLK_BYP_0, 8, + 0); + +/* GPIO */ +static CV1800_DIV(clk_gpio_db, clk_parents_1m, + REG_CLK_EN_0, 31, + REG_DIV_CLK_GPIO_DB, 16, 16, 10, CV1800_DIV_FLAG, + CLK_IS_CRITICAL); +static CV1800_GATE(clk_apb_gpio, clk_axi6_bus_parents, + REG_CLK_EN_0, 29, + CLK_IS_CRITICAL); +static CV1800_GATE(clk_apb_gpio_intr, clk_axi6_bus_parents, + REG_CLK_EN_0, 30, + CLK_IS_CRITICAL); + +/* ETH */ +static CV1800_BYPASS_DIV(clk_eth0_500m, clk_bypass_fpll_parents, + REG_CLK_EN_0, 25, + REG_DIV_CLK_GPIO_DB, 16, 4, 3, CV1800_DIV_FLAG, + REG_CLK_BYP_0, 9, + 0); +static CV1800_GATE(clk_axi4_eth0, clk_axi4_bus_parents, + REG_CLK_EN_0, 26, + 0); +static CV1800_BYPASS_DIV(clk_eth1_500m, clk_bypass_fpll_parents, + REG_CLK_EN_0, 27, + REG_DIV_CLK_GPIO_DB, 16, 4, 3, CV1800_DIV_FLAG, + REG_CLK_BYP_0, 10, + 0); +static CV1800_GATE(clk_axi4_eth1, clk_axi4_bus_parents, + REG_CLK_EN_0, 28, + 0); + +/* SF */ +static CV1800_GATE(clk_ahb_sf, clk_axi4_bus_parents, + REG_CLK_EN_1, 0, + 0); +static CV1800_GATE(clk_ahb_sf1, clk_axi4_bus_parents, + REG_CLK_EN_3, 27, + 0); + +/* AUDSRC */ +static CV1800_ACLK(clk_a24m, clk_mipimpll_parents, + REG_APLL_FRAC_DIV_CTRL, 0, + REG_APLL_FRAC_DIV_CTRL, 3, + REG_APLL_FRAC_DIV_CTRL, 1, + REG_APLL_FRAC_DIV_CTRL, 2, + REG_APLL_FRAC_DIV_M, 0, 22, CV1800_DIV_FLAG, + REG_APLL_FRAC_DIV_N, 0, 22, CV1800_DIV_FLAG, + 24576000, + 0); + +static const struct clk_parent_data clk_aud_parents[] = { + { .index = 0 }, + { .hw = &clk_a0pll.common.hw }, + { .hw = &clk_a24m.common.hw }, +}; + +static CV1800_BYPASS_MUX(clk_audsrc, clk_aud_parents, + REG_CLK_EN_4, 1, + REG_DIV_CLK_AUDSRC, 16, 8, 18, CV1800_DIV_FLAG, + REG_DIV_CLK_AUDSRC, 8, 2, + REG_CLK_BYP_1, 2, + 0); +static CV1800_GATE(clk_apb_audsrc, clk_axi4_bus_parents, + REG_CLK_EN_4, 2, + 0); + +/* SDMA */ +static CV1800_GATE(clk_sdma_axi, clk_axi4_bus_parents, + REG_CLK_EN_1, 1, + 0); +static CV1800_BYPASS_MUX(clk_sdma_aud0, clk_aud_parents, + REG_CLK_EN_1, 2, + REG_DIV_CLK_SDMA_AUD0, 16, 8, 18, CV1800_DIV_FLAG, + REG_DIV_CLK_SDMA_AUD0, 8, 2, + REG_CLK_BYP_0, 11, + 0); +static CV1800_BYPASS_MUX(clk_sdma_aud1, clk_aud_parents, + REG_CLK_EN_1, 3, + REG_DIV_CLK_SDMA_AUD1, 16, 8, 18, CV1800_DIV_FLAG, + REG_DIV_CLK_SDMA_AUD1, 8, 2, + REG_CLK_BYP_0, 12, + 0); +static CV1800_BYPASS_MUX(clk_sdma_aud2, clk_aud_parents, + REG_CLK_EN_1, 3, + REG_DIV_CLK_SDMA_AUD2, 16, 8, 18, CV1800_DIV_FLAG, + REG_DIV_CLK_SDMA_AUD2, 8, 2, + REG_CLK_BYP_0, 13, + 0); +static CV1800_BYPASS_MUX(clk_sdma_aud3, clk_aud_parents, + REG_CLK_EN_1, 3, + REG_DIV_CLK_SDMA_AUD3, 16, 8, 18, CV1800_DIV_FLAG, + REG_DIV_CLK_SDMA_AUD3, 8, 2, + REG_CLK_BYP_0, 14, + 0); + +/* SPI */ +static CV1800_GATE(clk_apb_spi0, clk_axi4_bus_parents, + REG_CLK_EN_1, 9, + 0); +static CV1800_GATE(clk_apb_spi1, clk_axi4_bus_parents, + REG_CLK_EN_1, 10, + 0); +static CV1800_GATE(clk_apb_spi2, clk_axi4_bus_parents, + REG_CLK_EN_1, 11, + 0); +static CV1800_GATE(clk_apb_spi3, clk_axi4_bus_parents, + REG_CLK_EN_1, 12, + 0); +static CV1800_BYPASS_DIV(clk_spi, clk_bypass_fpll_parents, + REG_CLK_EN_3, 6, + REG_DIV_CLK_SPI, 16, 6, 8, CV1800_DIV_FLAG, + REG_CLK_BYP_0, 30, + 0); + +/* UART */ +static CV1800_GATE(clk_uart0, clk_uart_parents, + REG_CLK_EN_1, 14, + CLK_IS_CRITICAL); +static CV1800_GATE(clk_apb_uart0, clk_axi4_bus_parents, + REG_CLK_EN_1, 15, + CLK_IS_CRITICAL); +static CV1800_GATE(clk_uart1, clk_uart_parents, + REG_CLK_EN_1, 16, + 0); +static CV1800_GATE(clk_apb_uart1, clk_axi4_bus_parents, + REG_CLK_EN_1, 17, + 0); +static CV1800_GATE(clk_uart2, clk_uart_parents, + REG_CLK_EN_1, 18, + 0); +static CV1800_GATE(clk_apb_uart2, clk_axi4_bus_parents, + REG_CLK_EN_1, 19, + 0); +static CV1800_GATE(clk_uart3, clk_uart_parents, + REG_CLK_EN_1, 20, + 0); +static CV1800_GATE(clk_apb_uart3, clk_axi4_bus_parents, + REG_CLK_EN_1, 21, + 0); +static CV1800_GATE(clk_uart4, clk_uart_parents, + REG_CLK_EN_1, 22, + 0); +static CV1800_GATE(clk_apb_uart4, clk_axi4_bus_parents, + REG_CLK_EN_1, 23, + 0); + +/* I2S */ +static CV1800_GATE(clk_apb_i2s0, clk_axi4_bus_parents, + REG_CLK_EN_1, 24, + 0); +static CV1800_GATE(clk_apb_i2s1, clk_axi4_bus_parents, + REG_CLK_EN_1, 25, + 0); +static CV1800_GATE(clk_apb_i2s2, clk_axi4_bus_parents, + REG_CLK_EN_1, 26, + 0); +static CV1800_GATE(clk_apb_i2s3, clk_axi4_bus_parents, + REG_CLK_EN_1, 27, + 0); + +/* DEBUG */ +static CV1800_GATE(clk_debug, osc_parents, + REG_CLK_EN_0, 13, + CLK_IS_CRITICAL); +static CV1800_BYPASS_DIV(clk_ap_debug, clk_bypass_fpll_parents, + REG_CLK_EN_4, 5, + REG_DIV_CLK_AP_DEBUG, 16, 4, 5, CV1800_DIV_FLAG, + REG_CLK_BYP_1, 4, + CLK_IS_CRITICAL); + +/* DDR */ +static CV1800_GATE(clk_ddr_axi_reg, clk_axi6_bus_parents, + REG_CLK_EN_0, 7, + CLK_IS_CRITICAL); + +/* I2C */ +static CV1800_GATE(clk_apb_i2c, clk_axi4_bus_parents, + REG_CLK_EN_1, 6, + 0); +static CV1800_BYPASS_DIV(clk_i2c, clk_bypass_axi6_bus_parents, + REG_CLK_EN_3, 7, + REG_DIV_CLK_I2C, 16, 4, 1, CV1800_DIV_FLAG, + REG_CLK_BYP_0, 31, + 0); +static CV1800_GATE(clk_apb_i2c0, clk_axi4_bus_parents, + REG_CLK_EN_3, 17, + 0); +static CV1800_GATE(clk_apb_i2c1, clk_axi4_bus_parents, + REG_CLK_EN_3, 18, + 0); +static CV1800_GATE(clk_apb_i2c2, clk_axi4_bus_parents, + REG_CLK_EN_3, 19, + 0); +static CV1800_GATE(clk_apb_i2c3, clk_axi4_bus_parents, + REG_CLK_EN_3, 20, + 0); +static CV1800_GATE(clk_apb_i2c4, clk_axi4_bus_parents, + REG_CLK_EN_3, 21, + 0); + +/* USB */ +static CV1800_GATE(clk_axi4_usb, clk_axi4_bus_parents, + REG_CLK_EN_1, 28, + 0); +static CV1800_GATE(clk_apb_usb, clk_axi4_bus_parents, + REG_CLK_EN_1, 29, + 0); +static CV1800_BYPASS_FIXED_DIV(clk_usb_125m, clk_bypass_fpll_parents, + REG_CLK_EN_1, 30, + 12, + REG_CLK_BYP_0, 17, + CLK_SET_RATE_PARENT); +static CV1800_FIXED_DIV(clk_usb_33k, clk_parents_1m, + REG_CLK_EN_1, 31, + 3, + 0); +static CV1800_BYPASS_FIXED_DIV(clk_usb_12m, clk_bypass_fpll_parents, + REG_CLK_EN_2, 0, + 125, + REG_CLK_BYP_0, 18, + CLK_SET_RATE_PARENT); + +/* VIP SYS */ +static const struct clk_parent_data clk_vip_sys_parents[] = { + { .index = 0 }, + { .hw = &clk_mipimpll.common.hw }, + { .hw = &clk_cam0pll.common.hw }, + { .hw = &clk_disppll.common.hw }, + { .hw = &clk_fpll.common.hw }, +}; + +static CV1800_BYPASS_DIV(clk_dsi_esc, clk_bypass_axi6_bus_parents, + REG_CLK_EN_2, 3, + REG_DIV_CLK_DSI_ESC, 16, 4, 5, CV1800_DIV_FLAG, + REG_CLK_BYP_0, 21, + 0); +static CV1800_BYPASS_MUX(clk_axi_vip, clk_vip_sys_parents, + REG_CLK_EN_2, 4, + REG_DIV_CLK_AXI_VIP, 16, 4, 3, CV1800_DIV_FLAG, + REG_DIV_CLK_AXI_VIP, 8, 2, + REG_CLK_BYP_0, 22, + 0); + +static const struct clk_parent_data clk_axi_vip_bus_parents[] = { + { .hw = &clk_axi_vip.mux.common.hw }, +}; + +static CV1800_BYPASS_MUX(clk_src_vip_sys_0, clk_vip_sys_parents, + REG_CLK_EN_2, 5, + REG_DIV_CLK_SRC_VIP_SYS_0, 16, 4, 6, CV1800_DIV_FLAG, + REG_DIV_CLK_SRC_VIP_SYS_0, 8, 2, + REG_CLK_BYP_0, 23, + 0); +static CV1800_BYPASS_MUX(clk_src_vip_sys_1, clk_vip_sys_parents, + REG_CLK_EN_2, 6, + REG_DIV_CLK_SRC_VIP_SYS_1, 16, 4, 6, CV1800_DIV_FLAG, + REG_DIV_CLK_SRC_VIP_SYS_1, 8, 2, + REG_CLK_BYP_0, 24, + 0); +static CV1800_BYPASS_MUX(clk_src_vip_sys_2, clk_vip_sys_parents, + REG_CLK_EN_3, 29, + REG_DIV_CLK_SRC_VIP_SYS_2, 16, 4, 2, CV1800_DIV_FLAG, + REG_DIV_CLK_SRC_VIP_SYS_2, 8, 2, + REG_CLK_BYP_1, 1, + 0); +static CV1800_GATE(clk_csi_mac0_vip, clk_axi_vip_bus_parents, + REG_CLK_EN_2, 18, + 0); +static CV1800_GATE(clk_csi_mac1_vip, clk_axi_vip_bus_parents, + REG_CLK_EN_2, 19, + 0); +static CV1800_GATE(clk_isp_top_vip, clk_axi_vip_bus_parents, + REG_CLK_EN_2, 20, + 0); +static CV1800_GATE(clk_img_d_vip, clk_axi_vip_bus_parents, + REG_CLK_EN_2, 21, + 0); +static CV1800_GATE(clk_img_v_vip, clk_axi_vip_bus_parents, + REG_CLK_EN_2, 22, + 0); +static CV1800_GATE(clk_sc_top_vip, clk_axi_vip_bus_parents, + REG_CLK_EN_2, 23, + 0); +static CV1800_GATE(clk_sc_d_vip, clk_axi_vip_bus_parents, + REG_CLK_EN_2, 24, + 0); +static CV1800_GATE(clk_sc_v1_vip, clk_axi_vip_bus_parents, + REG_CLK_EN_2, 25, + 0); +static CV1800_GATE(clk_sc_v2_vip, clk_axi_vip_bus_parents, + REG_CLK_EN_2, 26, + 0); +static CV1800_GATE(clk_sc_v3_vip, clk_axi_vip_bus_parents, + REG_CLK_EN_2, 27, + 0); +static CV1800_GATE(clk_dwa_vip, clk_axi_vip_bus_parents, + REG_CLK_EN_2, 28, + 0); +static CV1800_GATE(clk_bt_vip, clk_axi_vip_bus_parents, + REG_CLK_EN_2, 29, + 0); +static CV1800_GATE(clk_disp_vip, clk_axi_vip_bus_parents, + REG_CLK_EN_2, 30, + 0); +static CV1800_GATE(clk_dsi_mac_vip, clk_axi_vip_bus_parents, + REG_CLK_EN_2, 31, + 0); +static CV1800_GATE(clk_lvds0_vip, clk_axi_vip_bus_parents, + REG_CLK_EN_3, 0, + 0); +static CV1800_GATE(clk_lvds1_vip, clk_axi_vip_bus_parents, + REG_CLK_EN_3, 1, + 0); +static CV1800_GATE(clk_csi0_rx_vip, clk_axi_vip_bus_parents, + REG_CLK_EN_3, 2, + 0); +static CV1800_GATE(clk_csi1_rx_vip, clk_axi_vip_bus_parents, + REG_CLK_EN_3, 3, + 0); +static CV1800_GATE(clk_pad_vi_vip, clk_axi_vip_bus_parents, + REG_CLK_EN_3, 4, + 0); +static CV1800_GATE(clk_pad_vi1_vip, clk_axi_vip_bus_parents, + REG_CLK_EN_3, 30, + 0); +static CV1800_GATE(clk_cfg_reg_vip, clk_axi6_bus_parents, + REG_CLK_EN_3, 31, + 0); +static CV1800_GATE(clk_pad_vi2_vip, clk_axi_vip_bus_parents, + REG_CLK_EN_4, 7, + 0); +static CV1800_GATE(clk_csi_be_vip, clk_axi_vip_bus_parents, + REG_CLK_EN_4, 8, + 0); +static CV1800_GATE(clk_vip_ip0, clk_axi_vip_bus_parents, + REG_CLK_EN_4, 9, + 0); +static CV1800_GATE(clk_vip_ip1, clk_axi_vip_bus_parents, + REG_CLK_EN_4, 10, + 0); +static CV1800_GATE(clk_vip_ip2, clk_axi_vip_bus_parents, + REG_CLK_EN_4, 11, + 0); +static CV1800_GATE(clk_vip_ip3, clk_axi_vip_bus_parents, + REG_CLK_EN_4, 12, + 0); +static CV1800_BYPASS_MUX(clk_src_vip_sys_3, clk_vip_sys_parents, + REG_CLK_EN_4, 15, + REG_DIV_CLK_SRC_VIP_SYS_3, 16, 4, 2, CV1800_DIV_FLAG, + REG_DIV_CLK_SRC_VIP_SYS_3, 8, 2, + REG_CLK_BYP_1, 8, + 0); +static CV1800_BYPASS_MUX(clk_src_vip_sys_4, clk_vip_sys_parents, + REG_CLK_EN_4, 16, + REG_DIV_CLK_SRC_VIP_SYS_4, 16, 4, 3, CV1800_DIV_FLAG, + REG_DIV_CLK_SRC_VIP_SYS_4, 8, 2, + REG_CLK_BYP_1, 9, + 0); +static CV1800_GATE(clk_ive_vip, clk_axi_vip_bus_parents, + REG_CLK_EN_4, 17, + 0); +static CV1800_GATE(clk_raw_vip, clk_axi_vip_bus_parents, + REG_CLK_EN_4, 18, + 0); +static CV1800_GATE(clk_osdc_vip, clk_axi_vip_bus_parents, + REG_CLK_EN_4, 19, + 0); +static CV1800_GATE(clk_csi_mac2_vip, clk_axi_vip_bus_parents, + REG_CLK_EN_4, 20, + 0); +static CV1800_GATE(clk_cam0_vip, clk_axi_vip_bus_parents, + REG_CLK_EN_4, 21, + 0); + +/* CAM OUT */ +static const struct clk_parent_data clk_cam_parents[] = { + { .hw = &clk_cam0pll.common.hw }, + { .hw = &clk_cam0pll_d2.common.hw }, + { .hw = &clk_cam0pll_d3.common.hw }, + { .hw = &clk_mipimpll_d3.common.hw }, +}; + +static CV1800_MUX(clk_cam0, clk_cam_parents, + REG_CLK_EN_2, 16, + REG_CLK_CAM0_SRC_DIV, 16, 6, 0, CV1800_DIV_FLAG, + REG_CLK_CAM0_SRC_DIV, 8, 2, + CLK_IGNORE_UNUSED); +static CV1800_MUX(clk_cam1, clk_cam_parents, + REG_CLK_EN_2, 17, + REG_CLK_CAM1_SRC_DIV, 16, 6, 0, CV1800_DIV_FLAG, + REG_CLK_CAM1_SRC_DIV, 8, 2, + CLK_IGNORE_UNUSED); + +/* VIDEO SUBSYS */ +static const struct clk_parent_data clk_axi_video_codec_parents[] = { + { .index = 0 }, + { .hw = &clk_a0pll.common.hw }, + { .hw = &clk_mipimpll.common.hw }, + { .hw = &clk_cam1pll.common.hw }, + { .hw = &clk_fpll.common.hw }, +}; +static const struct clk_parent_data clk_vc_src0_parents[] = { + { .index = 0 }, + { .hw = &clk_disppll.common.hw }, + { .hw = &clk_mipimpll.common.hw }, + { .hw = &clk_cam1pll.common.hw }, + { .hw = &clk_fpll.common.hw }, +}; +static const struct clk_parent_data clk_vc_src1_parents[] = { + { .index = 0 }, + { .hw = &clk_cam1pll.common.hw }, +}; + +static CV1800_BYPASS_MUX(clk_axi_video_codec, clk_axi_video_codec_parents, + REG_CLK_EN_2, 8, + REG_DIV_CLK_AXI_VIDEO_CODEC, 16, 4, 2, CV1800_DIV_FLAG, + REG_DIV_CLK_AXI_VIDEO_CODEC, 8, 2, + REG_CLK_BYP_0, 26, + 0); + +static const struct clk_parent_data clk_axi_video_codec_bus_parents[] = { + { .hw = &clk_axi_video_codec.mux.common.hw }, +}; + +static CV1800_BYPASS_MUX(clk_vc_src0, clk_vc_src0_parents, + REG_CLK_EN_2, 9, + REG_DIV_CLK_VC_SRC0, 16, 4, 2, CV1800_DIV_FLAG, + REG_DIV_CLK_VC_SRC0, 8, 2, + REG_CLK_BYP_0, 27, + 0); + +static CV1800_GATE(clk_h264c, clk_axi_video_codec_bus_parents, + REG_CLK_EN_2, 10, + 0); +static CV1800_GATE(clk_h265c, clk_axi_video_codec_bus_parents, + REG_CLK_EN_2, 11, + 0); +static CV1800_GATE(clk_jpeg, clk_axi_video_codec_bus_parents, + REG_CLK_EN_2, 12, + CLK_IGNORE_UNUSED); +static CV1800_GATE(clk_apb_jpeg, clk_axi6_bus_parents, + REG_CLK_EN_2, 13, + CLK_IGNORE_UNUSED); +static CV1800_GATE(clk_apb_h264c, clk_axi6_bus_parents, + REG_CLK_EN_2, 14, + 0); +static CV1800_GATE(clk_apb_h265c, clk_axi6_bus_parents, + REG_CLK_EN_2, 15, + 0); +static CV1800_BYPASS_FIXED_DIV(clk_vc_src1, clk_vc_src1_parents, + REG_CLK_EN_3, 28, + 2, + REG_CLK_BYP_1, 0, + CLK_SET_RATE_PARENT); +static CV1800_BYPASS_FIXED_DIV(clk_vc_src2, clk_bypass_fpll_parents, + REG_CLK_EN_4, 3, + 3, + REG_CLK_BYP_1, 3, + CLK_SET_RATE_PARENT); + +/* VC SYS */ +static CV1800_GATE(clk_cfg_reg_vc, clk_axi6_bus_parents, + REG_CLK_EN_4, 0, + CLK_IGNORE_UNUSED); + +/* PWM */ +static CV1800_BYPASS_MUX(clk_pwm_src, clk_axi4_parents, + REG_CLK_EN_4, 4, + REG_DIV_CLK_PWM_SRC_0, 16, 6, 10, CV1800_DIV_FLAG, + REG_DIV_CLK_PWM_SRC_0, 8, 2, + REG_CLK_BYP_0, 15, + CLK_IS_CRITICAL); + +static const struct clk_parent_data clk_pwm_parents[] = { + { .hw = &clk_pwm_src.mux.common.hw }, +}; + +static CV1800_GATE(clk_pwm, clk_pwm_parents, + REG_CLK_EN_1, 8, + CLK_IS_CRITICAL); + +/* C906 */ +static const struct clk_parent_data clk_c906_0_parents[] = { + { .index = 0 }, + { .hw = &clk_tpll.common.hw }, + { .hw = &clk_a0pll.common.hw }, + { .hw = &clk_mipimpll.common.hw }, + { .hw = &clk_mpll.common.hw }, + { .hw = &clk_fpll.common.hw }, +}; +static const struct clk_parent_data clk_c906_1_parents[] = { + { .index = 0 }, + { .hw = &clk_tpll.common.hw }, + { .hw = &clk_a0pll.common.hw }, + { .hw = &clk_disppll.common.hw }, + { .hw = &clk_mpll.common.hw }, + { .hw = &clk_fpll.common.hw }, +}; + +static const s8 clk_c906_parent2sel[] = { + -1, /* osc */ + 0, /* mux 0: clk_tpll(c906_0), clk_tpll(c906_1) */ + 0, /* mux 0: clk_a0pll(c906_0), clk_a0pll(c906_1) */ + 0, /* mux 0: clk_mipimpll(c906_0), clk_disppll(c906_1) */ + 0, /* mux 0: clk_mpll(c906_0), clk_mpll(c906_1) */ + 1 /* mux 1: clk_fpll(c906_0), clk_fpll(c906_1) */ +}; + +static const u8 clk_c906_sel2parent[2][4] = { + [0] = { + 1, + 2, + 3, + 4 + }, + [1] = { + 5, + 5, + 5, + 5 + }, +}; + +static CV1800_MMUX(clk_c906_0, clk_c906_0_parents, + REG_CLK_EN_4, 13, + REG_DIV_CLK_C906_0_0, 16, 4, 1, CV1800_DIV_FLAG, + REG_DIV_CLK_C906_0_1, 16, 4, 2, CV1800_DIV_FLAG, + REG_DIV_CLK_C906_0_0, 8, 2, + REG_DIV_CLK_C906_0_1, 8, 2, + REG_CLK_BYP_1, 6, + REG_CLK_SEL_0, 23, + clk_c906_parent2sel, + clk_c906_sel2parent[0], clk_c906_sel2parent[1], + CLK_IS_CRITICAL | CLK_GET_RATE_NOCACHE); +static CV1800_MMUX(clk_c906_1, clk_c906_1_parents, + REG_CLK_EN_4, 14, + REG_DIV_CLK_C906_1_0, 16, 4, 2, CV1800_DIV_FLAG, + REG_DIV_CLK_C906_1_1, 16, 4, 3, CV1800_DIV_FLAG, + REG_DIV_CLK_C906_1_0, 8, 2, + REG_DIV_CLK_C906_1_1, 8, 2, + REG_CLK_BYP_1, 7, + REG_CLK_SEL_0, 24, + clk_c906_parent2sel, + clk_c906_sel2parent[0], clk_c906_sel2parent[1], + CLK_IS_CRITICAL | CLK_GET_RATE_NOCACHE); + +/* A53 */ +static CV1800_BYPASS_DIV(clk_cpu_axi0, clk_axi4_parents, + REG_CLK_EN_0, 1, + REG_DIV_CLK_CPU_AXI0, 16, 4, 3, CV1800_DIV_FLAG, + REG_CLK_BYP_0, 1, + CLK_IS_CRITICAL); +static CV1800_BYPASS_DIV(clk_cpu_gic, clk_bypass_fpll_parents, + REG_CLK_EN_0, 2, + REG_DIV_CLK_CPU_GIC, 16, 4, 5, CV1800_DIV_FLAG, + REG_CLK_BYP_0, 2, + CLK_IS_CRITICAL); +static CV1800_GATE(clk_xtal_ap, osc_parents, + REG_CLK_EN_0, 3, + CLK_IS_CRITICAL); + +static const struct clk_parent_data clk_a53_parents[] = { + { .index = 0 }, + { .hw = &clk_tpll.common.hw }, + { .hw = &clk_a0pll.common.hw }, + { .hw = &clk_mipimpll.common.hw }, + { .hw = &clk_mpll.common.hw }, + { .hw = &clk_fpll.common.hw }, +}; + +static const s8 clk_a53_parent2sel[] = { + -1, /* osc */ + 0, /* mux 0: clk_tpll */ + 0, /* mux 0: clk_a0pll */ + 0, /* mux 0: clk_mipimpll */ + 0, /* mux 0: clk_mpll */ + 1 /* mux 1: clk_fpll */ +}; + +static const u8 clk_a53_sel2parent[2][4] = { + [0] = { + 1, + 2, + 3, + 4 + }, + [1] = { + 5, + 5, + 5, + 5 + }, +}; + +/* + * Clock for A53 cpu in the CV18XX/SG200X series. + * For CV180X and CV181X series, this clock is not used, but can not + * be set to bypass mode, or the SoC will hang. + */ +static CV1800_MMUX(clk_a53, clk_a53_parents, + REG_CLK_EN_0, 0, + REG_DIV_CLK_A53_0, 16, 4, 1, CV1800_DIV_FLAG, + REG_DIV_CLK_A53_1, 16, 4, 2, CV1800_DIV_FLAG, + REG_DIV_CLK_A53_0, 8, 2, + REG_DIV_CLK_A53_1, 8, 2, + REG_CLK_BYP_0, 0, + REG_CLK_SEL_0, 0, + clk_a53_parent2sel, + clk_a53_sel2parent[0], clk_a53_sel2parent[1], + CLK_IS_CRITICAL | CLK_GET_RATE_NOCACHE); + +static struct clk_hw_onecell_data cv1800_hw_clks = { + .num = CV1800_CLK_MAX, + .hws = { + [CLK_MPLL] = &clk_mpll.common.hw, + [CLK_TPLL] = &clk_tpll.common.hw, + [CLK_FPLL] = &clk_fpll.common.hw, + [CLK_MIPIMPLL] = &clk_mipimpll.common.hw, + [CLK_A0PLL] = &clk_a0pll.common.hw, + [CLK_DISPPLL] = &clk_disppll.common.hw, + [CLK_CAM0PLL] = &clk_cam0pll.common.hw, + [CLK_CAM1PLL] = &clk_cam1pll.common.hw, + + [CLK_MIPIMPLL_D3] = &clk_mipimpll_d3.common.hw, + [CLK_CAM0PLL_D2] = &clk_cam0pll_d2.common.hw, + [CLK_CAM0PLL_D3] = &clk_cam0pll_d3.common.hw, + + [CLK_TPU] = &clk_tpu.mux.common.hw, + [CLK_TPU_FAB] = &clk_tpu_fab.common.hw, + [CLK_AHB_ROM] = &clk_ahb_rom.common.hw, + [CLK_DDR_AXI_REG] = &clk_ddr_axi_reg.common.hw, + [CLK_RTC_25M] = &clk_rtc_25m.common.hw, + [CLK_SRC_RTC_SYS_0] = &clk_src_rtc_sys_0.div.common.hw, + [CLK_TEMPSEN] = &clk_tempsen.common.hw, + [CLK_SARADC] = &clk_saradc.common.hw, + [CLK_EFUSE] = &clk_efuse.common.hw, + [CLK_APB_EFUSE] = &clk_apb_efuse.common.hw, + [CLK_DEBUG] = &clk_debug.common.hw, + [CLK_AP_DEBUG] = &clk_ap_debug.div.common.hw, + [CLK_XTAL_MISC] = &clk_xtal_misc.common.hw, + [CLK_AXI4_EMMC] = &clk_axi4_emmc.common.hw, + [CLK_EMMC] = &clk_emmc.mux.common.hw, + [CLK_EMMC_100K] = &clk_emmc_100k.common.hw, + [CLK_AXI4_SD0] = &clk_axi4_sd0.common.hw, + [CLK_SD0] = &clk_sd0.mux.common.hw, + [CLK_SD0_100K] = &clk_sd0_100k.common.hw, + [CLK_AXI4_SD1] = &clk_axi4_sd1.common.hw, + [CLK_SD1] = &clk_sd1.mux.common.hw, + [CLK_SD1_100K] = &clk_sd1_100k.common.hw, + [CLK_SPI_NAND] = &clk_spi_nand.mux.common.hw, + [CLK_ETH0_500M] = &clk_eth0_500m.div.common.hw, + [CLK_AXI4_ETH0] = &clk_axi4_eth0.common.hw, + [CLK_ETH1_500M] = &clk_eth1_500m.div.common.hw, + [CLK_AXI4_ETH1] = &clk_axi4_eth1.common.hw, + [CLK_APB_GPIO] = &clk_apb_gpio.common.hw, + [CLK_APB_GPIO_INTR] = &clk_apb_gpio_intr.common.hw, + [CLK_GPIO_DB] = &clk_gpio_db.common.hw, + [CLK_AHB_SF] = &clk_ahb_sf.common.hw, + [CLK_AHB_SF1] = &clk_ahb_sf1.common.hw, + [CLK_A24M] = &clk_a24m.common.hw, + [CLK_AUDSRC] = &clk_audsrc.mux.common.hw, + [CLK_APB_AUDSRC] = &clk_apb_audsrc.common.hw, + [CLK_SDMA_AXI] = &clk_sdma_axi.common.hw, + [CLK_SDMA_AUD0] = &clk_sdma_aud0.mux.common.hw, + [CLK_SDMA_AUD1] = &clk_sdma_aud1.mux.common.hw, + [CLK_SDMA_AUD2] = &clk_sdma_aud2.mux.common.hw, + [CLK_SDMA_AUD3] = &clk_sdma_aud3.mux.common.hw, + [CLK_I2C] = &clk_i2c.div.common.hw, + [CLK_APB_I2C] = &clk_apb_i2c.common.hw, + [CLK_APB_I2C0] = &clk_apb_i2c0.common.hw, + [CLK_APB_I2C1] = &clk_apb_i2c1.common.hw, + [CLK_APB_I2C2] = &clk_apb_i2c2.common.hw, + [CLK_APB_I2C3] = &clk_apb_i2c3.common.hw, + [CLK_APB_I2C4] = &clk_apb_i2c4.common.hw, + [CLK_APB_WDT] = &clk_apb_wdt.common.hw, + [CLK_PWM_SRC] = &clk_pwm_src.mux.common.hw, + [CLK_PWM] = &clk_pwm.common.hw, + [CLK_SPI] = &clk_spi.div.common.hw, + [CLK_APB_SPI0] = &clk_apb_spi0.common.hw, + [CLK_APB_SPI1] = &clk_apb_spi1.common.hw, + [CLK_APB_SPI2] = &clk_apb_spi2.common.hw, + [CLK_APB_SPI3] = &clk_apb_spi3.common.hw, + [CLK_1M] = &clk_1m.common.hw, + [CLK_CAM0_200] = &clk_cam0_200.mux.common.hw, + [CLK_PM] = &clk_pm.common.hw, + [CLK_TIMER0] = &clk_timer0.common.hw, + [CLK_TIMER1] = &clk_timer1.common.hw, + [CLK_TIMER2] = &clk_timer2.common.hw, + [CLK_TIMER3] = &clk_timer3.common.hw, + [CLK_TIMER4] = &clk_timer4.common.hw, + [CLK_TIMER5] = &clk_timer5.common.hw, + [CLK_TIMER6] = &clk_timer6.common.hw, + [CLK_TIMER7] = &clk_timer7.common.hw, + [CLK_UART0] = &clk_uart0.common.hw, + [CLK_APB_UART0] = &clk_apb_uart0.common.hw, + [CLK_UART1] = &clk_uart1.common.hw, + [CLK_APB_UART1] = &clk_apb_uart1.common.hw, + [CLK_UART2] = &clk_uart2.common.hw, + [CLK_APB_UART2] = &clk_apb_uart2.common.hw, + [CLK_UART3] = &clk_uart3.common.hw, + [CLK_APB_UART3] = &clk_apb_uart3.common.hw, + [CLK_UART4] = &clk_uart4.common.hw, + [CLK_APB_UART4] = &clk_apb_uart4.common.hw, + [CLK_APB_I2S0] = &clk_apb_i2s0.common.hw, + [CLK_APB_I2S1] = &clk_apb_i2s1.common.hw, + [CLK_APB_I2S2] = &clk_apb_i2s2.common.hw, + [CLK_APB_I2S3] = &clk_apb_i2s3.common.hw, + [CLK_AXI4_USB] = &clk_axi4_usb.common.hw, + [CLK_APB_USB] = &clk_apb_usb.common.hw, + [CLK_USB_125M] = &clk_usb_125m.div.common.hw, + [CLK_USB_33K] = &clk_usb_33k.common.hw, + [CLK_USB_12M] = &clk_usb_12m.div.common.hw, + [CLK_AXI4] = &clk_axi4.mux.common.hw, + [CLK_AXI6] = &clk_axi6.div.common.hw, + [CLK_DSI_ESC] = &clk_dsi_esc.div.common.hw, + [CLK_AXI_VIP] = &clk_axi_vip.mux.common.hw, + [CLK_SRC_VIP_SYS_0] = &clk_src_vip_sys_0.mux.common.hw, + [CLK_SRC_VIP_SYS_1] = &clk_src_vip_sys_1.mux.common.hw, + [CLK_SRC_VIP_SYS_2] = &clk_src_vip_sys_2.mux.common.hw, + [CLK_SRC_VIP_SYS_3] = &clk_src_vip_sys_3.mux.common.hw, + [CLK_SRC_VIP_SYS_4] = &clk_src_vip_sys_4.mux.common.hw, + [CLK_CSI_BE_VIP] = &clk_csi_be_vip.common.hw, + [CLK_CSI_MAC0_VIP] = &clk_csi_mac0_vip.common.hw, + [CLK_CSI_MAC1_VIP] = &clk_csi_mac1_vip.common.hw, + [CLK_CSI_MAC2_VIP] = &clk_csi_mac2_vip.common.hw, + [CLK_CSI0_RX_VIP] = &clk_csi0_rx_vip.common.hw, + [CLK_CSI1_RX_VIP] = &clk_csi1_rx_vip.common.hw, + [CLK_ISP_TOP_VIP] = &clk_isp_top_vip.common.hw, + [CLK_IMG_D_VIP] = &clk_img_d_vip.common.hw, + [CLK_IMG_V_VIP] = &clk_img_v_vip.common.hw, + [CLK_SC_TOP_VIP] = &clk_sc_top_vip.common.hw, + [CLK_SC_D_VIP] = &clk_sc_d_vip.common.hw, + [CLK_SC_V1_VIP] = &clk_sc_v1_vip.common.hw, + [CLK_SC_V2_VIP] = &clk_sc_v2_vip.common.hw, + [CLK_SC_V3_VIP] = &clk_sc_v3_vip.common.hw, + [CLK_DWA_VIP] = &clk_dwa_vip.common.hw, + [CLK_BT_VIP] = &clk_bt_vip.common.hw, + [CLK_DISP_VIP] = &clk_disp_vip.common.hw, + [CLK_DSI_MAC_VIP] = &clk_dsi_mac_vip.common.hw, + [CLK_LVDS0_VIP] = &clk_lvds0_vip.common.hw, + [CLK_LVDS1_VIP] = &clk_lvds1_vip.common.hw, + [CLK_PAD_VI_VIP] = &clk_pad_vi_vip.common.hw, + [CLK_PAD_VI1_VIP] = &clk_pad_vi1_vip.common.hw, + [CLK_PAD_VI2_VIP] = &clk_pad_vi2_vip.common.hw, + [CLK_CFG_REG_VIP] = &clk_cfg_reg_vip.common.hw, + [CLK_VIP_IP0] = &clk_vip_ip0.common.hw, + [CLK_VIP_IP1] = &clk_vip_ip1.common.hw, + [CLK_VIP_IP2] = &clk_vip_ip2.common.hw, + [CLK_VIP_IP3] = &clk_vip_ip3.common.hw, + [CLK_IVE_VIP] = &clk_ive_vip.common.hw, + [CLK_RAW_VIP] = &clk_raw_vip.common.hw, + [CLK_OSDC_VIP] = &clk_osdc_vip.common.hw, + [CLK_CAM0_VIP] = &clk_cam0_vip.common.hw, + [CLK_AXI_VIDEO_CODEC] = &clk_axi_video_codec.mux.common.hw, + [CLK_VC_SRC0] = &clk_vc_src0.mux.common.hw, + [CLK_VC_SRC1] = &clk_vc_src1.div.common.hw, + [CLK_VC_SRC2] = &clk_vc_src2.div.common.hw, + [CLK_H264C] = &clk_h264c.common.hw, + [CLK_APB_H264C] = &clk_apb_h264c.common.hw, + [CLK_H265C] = &clk_h265c.common.hw, + [CLK_APB_H265C] = &clk_apb_h265c.common.hw, + [CLK_JPEG] = &clk_jpeg.common.hw, + [CLK_APB_JPEG] = &clk_apb_jpeg.common.hw, + [CLK_CAM0] = &clk_cam0.common.hw, + [CLK_CAM1] = &clk_cam1.common.hw, + [CLK_WGN] = &clk_wgn.common.hw, + [CLK_WGN0] = &clk_wgn0.common.hw, + [CLK_WGN1] = &clk_wgn1.common.hw, + [CLK_WGN2] = &clk_wgn2.common.hw, + [CLK_KEYSCAN] = &clk_keyscan.common.hw, + [CLK_CFG_REG_VC] = &clk_cfg_reg_vc.common.hw, + [CLK_C906_0] = &clk_c906_0.common.hw, + [CLK_C906_1] = &clk_c906_1.common.hw, + [CLK_A53] = &clk_a53.common.hw, + [CLK_CPU_AXI0] = &clk_cpu_axi0.div.common.hw, + [CLK_CPU_GIC] = &clk_cpu_gic.div.common.hw, + [CLK_XTAL_AP] = &clk_xtal_ap.common.hw, + }, +}; + +static void cv18xx_clk_disable_auto_pd(void __iomem *base) +{ + static const u16 CV1800_PD_CLK[] = { + REG_MIPIMPLL_CLK_CSR, + REG_A0PLL_CLK_CSR, + REG_DISPPLL_CLK_CSR, + REG_CAM0PLL_CLK_CSR, + REG_CAM1PLL_CLK_CSR, + }; + + u32 val; + int i; + + /* disable auto power down */ + for (i = 0; i < ARRAY_SIZE(CV1800_PD_CLK); i++) { + u32 reg = CV1800_PD_CLK[i]; + + val = readl(base + reg); + val |= GENMASK(12, 9); + val &= ~BIT(8); + writel(val, base + reg); + } +} + +static void cv18xx_clk_disable_a53(void __iomem *base) +{ + u32 val = readl(base + REG_CLK_BYP_0); + + /* Set bypass clock for clk_a53 */ + val |= BIT(0); + + /* Set bypass clock for clk_cpu_axi0 */ + val |= BIT(1); + + /* Set bypass clock for clk_cpu_gic */ + val |= BIT(2); + + writel(val, base + REG_CLK_BYP_0); +} + +static int cv1800_pre_init(struct device *dev, void __iomem *base, + struct cv1800_clk_ctrl *ctrl, + const struct cv1800_clk_desc *desc) +{ + u32 val = readl(base + REG_CLK_EN_2); + + /* disable unsupported clk_disp_src_vip */ + val &= ~BIT(7); + + writel(val, base + REG_CLK_EN_2); + + cv18xx_clk_disable_a53(base); + cv18xx_clk_disable_auto_pd(base); + + return 0; +} + +static const struct cv1800_clk_desc cv1800_desc = { + .clks_data = &cv1800_hw_clks, + .pre_init = cv1800_pre_init, +}; + +static int cv1800_clk_init_ctrl(struct device *dev, void __iomem *reg, + struct cv1800_clk_ctrl *ctrl, + const struct cv1800_clk_desc *desc) +{ + int i, ret; + + ctrl->desc = desc; + spin_lock_init(&ctrl->lock); + + for (i = 0; i < desc->clks_data->num; i++) { + struct clk_hw *hw = desc->clks_data->hws[i]; + struct cv1800_clk_common *common; + const char *name; + + if (!hw) + continue; + + name = hw->init->name; + + common = hw_to_cv1800_clk_common(hw); + common->base = reg; + common->lock = &ctrl->lock; + + ret = devm_clk_hw_register(dev, hw); + if (ret) { + dev_err(dev, "Couldn't register clock %d - %s\n", + i, name); + return ret; + } + } + + return devm_of_clk_add_hw_provider(dev, of_clk_hw_onecell_get, + desc->clks_data); +} + +static int cv1800_clk_probe(struct platform_device *pdev) +{ + struct device *dev = &pdev->dev; + void __iomem *reg; + int ret; + const struct cv1800_clk_desc *desc; + struct cv1800_clk_ctrl *ctrl; + + reg = devm_platform_ioremap_resource(pdev, 0); + if (IS_ERR(reg)) + return PTR_ERR(reg); + + desc = device_get_match_data(dev); + if (!desc) { + dev_err(dev, "no match data for platform\n"); + return -EINVAL; + } + + ctrl = devm_kzalloc(dev, sizeof(*ctrl), GFP_KERNEL); + if (!ctrl) + return -ENOMEM; + + if (desc->pre_init) { + ret = desc->pre_init(dev, reg, ctrl, desc); + if (ret) + return ret; + } + + return cv1800_clk_init_ctrl(dev, reg, ctrl, desc); +} + +static const struct of_device_id cv1800_clk_ids[] = { + { .compatible = "sophgo,cv1800-clk", .data = &cv1800_desc }, + { } +}; +MODULE_DEVICE_TABLE(of, cv1800_clk_ids); + +static struct platform_driver cv1800_clk_driver = { + .probe = cv1800_clk_probe, + .driver = { + .name = "cv1800-clk", + .suppress_bind_attrs = true, + .of_match_table = cv1800_clk_ids, + }, +}; +module_platform_driver(cv1800_clk_driver); +MODULE_LICENSE("GPL"); diff --git a/drivers/clk/sophgo/clk-cv1800.h b/drivers/clk/sophgo/clk-cv1800.h new file mode 100644 index 000000000000..1b9c04b5ac3a --- /dev/null +++ b/drivers/clk/sophgo/clk-cv1800.h @@ -0,0 +1,122 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Copyright (C) 2023 Inochi Amaoto + */ + +#ifndef _CLK_SOPHGO_CV1800_H_ +#define _CLK_SOPHGO_CV1800_H_ + +#include + +#define CV1800_CLK_MAX (CLK_XTAL_AP + 1) + +#define REG_PLL_G2_CTRL 0x800 +#define REG_PLL_G2_STATUS 0x804 +#define REG_MIPIMPLL_CSR 0x808 +#define REG_A0PLL_CSR 0x80C +#define REG_DISPPLL_CSR 0x810 +#define REG_CAM0PLL_CSR 0x814 +#define REG_CAM1PLL_CSR 0x818 +#define REG_PLL_G2_SSC_SYN_CTRL 0x840 +#define REG_A0PLL_SSC_SYN_CTRL 0x850 +#define REG_A0PLL_SSC_SYN_SET 0x854 +#define REG_A0PLL_SSC_SYN_SPAN 0x858 +#define REG_A0PLL_SSC_SYN_STEP 0x85C +#define REG_DISPPLL_SSC_SYN_CTRL 0x860 +#define REG_DISPPLL_SSC_SYN_SET 0x864 +#define REG_DISPPLL_SSC_SYN_SPAN 0x868 +#define REG_DISPPLL_SSC_SYN_STEP 0x86C +#define REG_CAM0PLL_SSC_SYN_CTRL 0x870 +#define REG_CAM0PLL_SSC_SYN_SET 0x874 +#define REG_CAM0PLL_SSC_SYN_SPAN 0x878 +#define REG_CAM0PLL_SSC_SYN_STEP 0x87C +#define REG_CAM1PLL_SSC_SYN_CTRL 0x880 +#define REG_CAM1PLL_SSC_SYN_SET 0x884 +#define REG_CAM1PLL_SSC_SYN_SPAN 0x888 +#define REG_CAM1PLL_SSC_SYN_STEP 0x88C +#define REG_APLL_FRAC_DIV_CTRL 0x890 +#define REG_APLL_FRAC_DIV_M 0x894 +#define REG_APLL_FRAC_DIV_N 0x898 +#define REG_MIPIMPLL_CLK_CSR 0x8A0 +#define REG_A0PLL_CLK_CSR 0x8A4 +#define REG_DISPPLL_CLK_CSR 0x8A8 +#define REG_CAM0PLL_CLK_CSR 0x8AC +#define REG_CAM1PLL_CLK_CSR 0x8B0 +#define REG_CLK_CAM0_SRC_DIV 0x8C0 +#define REG_CLK_CAM1_SRC_DIV 0x8C4 + +/* top_pll_g6 */ +#define REG_PLL_G6_CTRL 0x900 +#define REG_PLL_G6_STATUS 0x904 +#define REG_MPLL_CSR 0x908 +#define REG_TPLL_CSR 0x90C +#define REG_FPLL_CSR 0x910 +#define REG_PLL_G6_SSC_SYN_CTRL 0x940 +#define REG_DPLL_SSC_SYN_CTRL 0x950 +#define REG_DPLL_SSC_SYN_SET 0x954 +#define REG_DPLL_SSC_SYN_SPAN 0x958 +#define REG_DPLL_SSC_SYN_STEP 0x95C +#define REG_MPLL_SSC_SYN_CTRL 0x960 +#define REG_MPLL_SSC_SYN_SET 0x964 +#define REG_MPLL_SSC_SYN_SPAN 0x968 +#define REG_MPLL_SSC_SYN_STEP 0x96C +#define REG_TPLL_SSC_SYN_CTRL 0x970 +#define REG_TPLL_SSC_SYN_SET 0x974 +#define REG_TPLL_SSC_SYN_SPAN 0x978 +#define REG_TPLL_SSC_SYN_STEP 0x97C + +/* clkgen */ +#define REG_CLK_EN_0 0x000 +#define REG_CLK_EN_1 0x004 +#define REG_CLK_EN_2 0x008 +#define REG_CLK_EN_3 0x00C +#define REG_CLK_EN_4 0x010 +#define REG_CLK_SEL_0 0x020 +#define REG_CLK_BYP_0 0x030 +#define REG_CLK_BYP_1 0x034 + +#define REG_DIV_CLK_A53_0 0x040 +#define REG_DIV_CLK_A53_1 0x044 +#define REG_DIV_CLK_CPU_AXI0 0x048 +#define REG_DIV_CLK_CPU_GIC 0x050 +#define REG_DIV_CLK_TPU 0x054 +#define REG_DIV_CLK_EMMC 0x064 +#define REG_DIV_CLK_EMMC_100K 0x06C +#define REG_DIV_CLK_SD0 0x070 +#define REG_DIV_CLK_SD0_100K 0x078 +#define REG_DIV_CLK_SD1 0x07C +#define REG_DIV_CLK_SD1_100K 0x084 +#define REG_DIV_CLK_SPI_NAND 0x088 +#define REG_DIV_CLK_ETH0_500M 0x08C +#define REG_DIV_CLK_ETH1_500M 0x090 +#define REG_DIV_CLK_GPIO_DB 0x094 +#define REG_DIV_CLK_SDMA_AUD0 0x098 +#define REG_DIV_CLK_SDMA_AUD1 0x09C +#define REG_DIV_CLK_SDMA_AUD2 0x0A0 +#define REG_DIV_CLK_SDMA_AUD3 0x0A4 +#define REG_DIV_CLK_CAM0_200 0x0A8 +#define REG_DIV_CLK_AXI4 0x0B8 +#define REG_DIV_CLK_AXI6 0x0BC +#define REG_DIV_CLK_DSI_ESC 0x0C4 +#define REG_DIV_CLK_AXI_VIP 0x0C8 +#define REG_DIV_CLK_SRC_VIP_SYS_0 0x0D0 +#define REG_DIV_CLK_SRC_VIP_SYS_1 0x0D8 +#define REG_DIV_CLK_DISP_SRC_VIP 0x0E0 +#define REG_DIV_CLK_AXI_VIDEO_CODEC 0x0E4 +#define REG_DIV_CLK_VC_SRC0 0x0EC +#define REG_DIV_CLK_1M 0x0FC +#define REG_DIV_CLK_SPI 0x100 +#define REG_DIV_CLK_I2C 0x104 +#define REG_DIV_CLK_SRC_VIP_SYS_2 0x110 +#define REG_DIV_CLK_AUDSRC 0x118 +#define REG_DIV_CLK_PWM_SRC_0 0x120 +#define REG_DIV_CLK_AP_DEBUG 0x128 +#define REG_DIV_CLK_RTCSYS_SRC_0 0x12C +#define REG_DIV_CLK_C906_0_0 0x130 +#define REG_DIV_CLK_C906_0_1 0x134 +#define REG_DIV_CLK_C906_1_0 0x138 +#define REG_DIV_CLK_C906_1_1 0x13C +#define REG_DIV_CLK_SRC_VIP_SYS_3 0x140 +#define REG_DIV_CLK_SRC_VIP_SYS_4 0x144 + +#endif /* _CLK_SOPHGO_CV1800_H_ */ diff --git a/drivers/clk/sophgo/clk-cv18xx-common.c b/drivers/clk/sophgo/clk-cv18xx-common.c new file mode 100644 index 000000000000..cbcdd88f0e23 --- /dev/null +++ b/drivers/clk/sophgo/clk-cv18xx-common.c @@ -0,0 +1,66 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (C) 2023 Inochi Amaoto + */ + +#include +#include +#include +#include + +#include "clk-cv18xx-common.h" + +int cv1800_clk_setbit(struct cv1800_clk_common *common, + struct cv1800_clk_regbit *field) +{ + u32 mask = BIT(field->shift); + u32 value; + unsigned long flags; + + spin_lock_irqsave(common->lock, flags); + + value = readl(common->base + field->reg); + writel(value | mask, common->base + field->reg); + + spin_unlock_irqrestore(common->lock, flags); + + return 0; +} + +int cv1800_clk_clearbit(struct cv1800_clk_common *common, + struct cv1800_clk_regbit *field) +{ + u32 mask = BIT(field->shift); + u32 value; + unsigned long flags; + + spin_lock_irqsave(common->lock, flags); + + value = readl(common->base + field->reg); + writel(value & ~mask, common->base + field->reg); + + spin_unlock_irqrestore(common->lock, flags); + + return 0; +} + +int cv1800_clk_checkbit(struct cv1800_clk_common *common, + struct cv1800_clk_regbit *field) +{ + return readl(common->base + field->reg) & BIT(field->shift); +} + +#define PLL_LOCK_TIMEOUT_US (200 * 1000) + +void cv1800_clk_wait_for_lock(struct cv1800_clk_common *common, + u32 reg, u32 lock) +{ + void __iomem *addr = common->base + reg; + u32 regval; + + if (!lock) + return; + + WARN_ON(readl_relaxed_poll_timeout(addr, regval, regval & lock, + 100, PLL_LOCK_TIMEOUT_US)); +} diff --git a/drivers/clk/sophgo/clk-cv18xx-common.h b/drivers/clk/sophgo/clk-cv18xx-common.h new file mode 100644 index 000000000000..2bfda02b2064 --- /dev/null +++ b/drivers/clk/sophgo/clk-cv18xx-common.h @@ -0,0 +1,81 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Copyright (C) 2023 Inochi Amaoto + */ + +#ifndef _CLK_SOPHGO_CV18XX_IP_H_ +#define _CLK_SOPHGO_CV18XX_IP_H_ + +#include +#include +#include + +struct cv1800_clk_common { + void __iomem *base; + spinlock_t *lock; + struct clk_hw hw; + unsigned long features; +}; + +#define CV1800_CLK_COMMON(_name, _parents, _op, _flags) \ + { \ + .hw.init = CLK_HW_INIT_PARENTS_DATA(_name, _parents, \ + _op, _flags), \ + } + +static inline struct cv1800_clk_common * +hw_to_cv1800_clk_common(struct clk_hw *hw) +{ + return container_of(hw, struct cv1800_clk_common, hw); +} + +struct cv1800_clk_regbit { + u16 reg; + s8 shift; +}; + +struct cv1800_clk_regfield { + u16 reg; + u8 shift; + u8 width; + s16 initval; + unsigned long flags; +}; + +#define CV1800_CLK_BIT(_reg, _shift) \ + { \ + .reg = _reg, \ + .shift = _shift, \ + } + +#define CV1800_CLK_REG(_reg, _shift, _width, _initval, _flags) \ + { \ + .reg = _reg, \ + .shift = _shift, \ + .width = _width, \ + .initval = _initval, \ + .flags = _flags, \ + } + +#define cv1800_clk_regfield_genmask(_reg) \ + GENMASK((_reg)->shift + (_reg)->width - 1, (_reg)->shift) +#define cv1800_clk_regfield_get(_val, _reg) \ + (((_val) >> (_reg)->shift) & GENMASK((_reg)->width - 1, 0)) +#define cv1800_clk_regfield_set(_val, _new, _reg) \ + (((_val) & ~cv1800_clk_regfield_genmask((_reg))) | \ + (((_new) & GENMASK((_reg)->width - 1, 0)) << (_reg)->shift)) + +#define _CV1800_SET_FIELD(_reg, _val, _field) \ + (((_reg) & ~(_field)) | FIELD_PREP((_field), (_val))) + +int cv1800_clk_setbit(struct cv1800_clk_common *common, + struct cv1800_clk_regbit *field); +int cv1800_clk_clearbit(struct cv1800_clk_common *common, + struct cv1800_clk_regbit *field); +int cv1800_clk_checkbit(struct cv1800_clk_common *common, + struct cv1800_clk_regbit *field); + +void cv1800_clk_wait_for_lock(struct cv1800_clk_common *common, + u32 reg, u32 lock); + +#endif // _CLK_SOPHGO_CV18XX_IP_H_ diff --git a/drivers/clk/sophgo/clk-cv18xx-ip.c b/drivers/clk/sophgo/clk-cv18xx-ip.c new file mode 100644 index 000000000000..805f561725ae --- /dev/null +++ b/drivers/clk/sophgo/clk-cv18xx-ip.c @@ -0,0 +1,887 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (C) 2023 Inochi Amaoto + */ + +#include +#include +#include +#include + +#include "clk-cv18xx-ip.h" + +/* GATE */ +static inline struct cv1800_clk_gate *hw_to_cv1800_clk_gate(struct clk_hw *hw) +{ + struct cv1800_clk_common *common = hw_to_cv1800_clk_common(hw); + + return container_of(common, struct cv1800_clk_gate, common); +} + +static int gate_enable(struct clk_hw *hw) +{ + struct cv1800_clk_gate *gate = hw_to_cv1800_clk_gate(hw); + + return cv1800_clk_setbit(&gate->common, &gate->gate); +} + +static void gate_disable(struct clk_hw *hw) +{ + struct cv1800_clk_gate *gate = hw_to_cv1800_clk_gate(hw); + + cv1800_clk_clearbit(&gate->common, &gate->gate); +} + +static int gate_is_enabled(struct clk_hw *hw) +{ + struct cv1800_clk_gate *gate = hw_to_cv1800_clk_gate(hw); + + return cv1800_clk_checkbit(&gate->common, &gate->gate); +} + +static unsigned long gate_recalc_rate(struct clk_hw *hw, + unsigned long parent_rate) +{ + return parent_rate; +} + +static long gate_round_rate(struct clk_hw *hw, unsigned long rate, + unsigned long *parent_rate) +{ + return *parent_rate; +} + +static int gate_set_rate(struct clk_hw *hw, unsigned long rate, + unsigned long parent_rate) +{ + return 0; +} + +const struct clk_ops cv1800_clk_gate_ops = { + .disable = gate_disable, + .enable = gate_enable, + .is_enabled = gate_is_enabled, + + .recalc_rate = gate_recalc_rate, + .round_rate = gate_round_rate, + .set_rate = gate_set_rate, +}; + +/* DIV */ +#define _DIV_EN_CLK_DIV_FACTOR_FIELD BIT(3) + +#define DIV_GET_EN_CLK_DIV_FACTOR(_reg) \ + FIELD_GET(_DIV_EN_CLK_DIV_FACTOR_FIELD, _reg) + +#define DIV_SET_EN_DIV_FACTOR(_reg) \ + _CV1800_SET_FIELD(_reg, 1, _DIV_EN_CLK_DIV_FACTOR_FIELD) + +static inline struct cv1800_clk_div *hw_to_cv1800_clk_div(struct clk_hw *hw) +{ + struct cv1800_clk_common *common = hw_to_cv1800_clk_common(hw); + + return container_of(common, struct cv1800_clk_div, common); +} + +static int div_enable(struct clk_hw *hw) +{ + struct cv1800_clk_div *div = hw_to_cv1800_clk_div(hw); + + return cv1800_clk_setbit(&div->common, &div->gate); +} + +static void div_disable(struct clk_hw *hw) +{ + struct cv1800_clk_div *div = hw_to_cv1800_clk_div(hw); + + cv1800_clk_clearbit(&div->common, &div->gate); +} + +static int div_is_enabled(struct clk_hw *hw) +{ + struct cv1800_clk_div *div = hw_to_cv1800_clk_div(hw); + + return cv1800_clk_checkbit(&div->common, &div->gate); +} + +static int div_helper_set_rate(struct cv1800_clk_common *common, + struct cv1800_clk_regfield *div, + unsigned long val) +{ + unsigned long flags; + u32 reg; + + if (div->width == 0) + return 0; + + spin_lock_irqsave(common->lock, flags); + + reg = readl(common->base + div->reg); + reg = cv1800_clk_regfield_set(reg, val, div); + if (div->initval > 0) + reg = DIV_SET_EN_DIV_FACTOR(reg); + + writel(reg, common->base + div->reg); + + spin_unlock_irqrestore(common->lock, flags); + + return 0; +} + +static u32 div_helper_get_clockdiv(struct cv1800_clk_common *common, + struct cv1800_clk_regfield *div) +{ + u32 clockdiv = 1; + u32 reg; + + if (!div || div->initval < 0 || (div->width == 0 && div->initval <= 0)) + return 1; + + if (div->width == 0 && div->initval > 0) + return div->initval; + + reg = readl(common->base + div->reg); + + if (div->initval == 0 || DIV_GET_EN_CLK_DIV_FACTOR(reg)) + clockdiv = cv1800_clk_regfield_get(reg, div); + else if (div->initval > 0) + clockdiv = div->initval; + + return clockdiv; +} + +static u32 div_helper_round_rate(struct cv1800_clk_regfield *div, + struct clk_hw *hw, struct clk_hw *parent, + unsigned long rate, unsigned long *prate) +{ + if (div->width == 0) { + if (div->initval <= 0) + return DIV_ROUND_UP_ULL(*prate, 1); + else + return DIV_ROUND_UP_ULL(*prate, div->initval); + } + + return divider_round_rate_parent(hw, parent, rate, prate, NULL, + div->width, div->flags); +} + +static long div_round_rate(struct clk_hw *parent, unsigned long *parent_rate, + unsigned long rate, int id, void *data) +{ + struct cv1800_clk_div *div = data; + + return div_helper_round_rate(&div->div, &div->common.hw, parent, + rate, parent_rate); +} + +static bool div_is_better_rate(struct cv1800_clk_common *common, + unsigned long target, unsigned long now, + unsigned long best) +{ + if (common->features & CLK_DIVIDER_ROUND_CLOSEST) + return abs_diff(target, now) < abs_diff(target, best); + + return now <= target && now > best; +} + +static int mux_helper_determine_rate(struct cv1800_clk_common *common, + struct clk_rate_request *req, + long (*round)(struct clk_hw *, + unsigned long *, + unsigned long, + int, + void *), + void *data) +{ + unsigned long best_parent_rate = 0, best_rate = 0; + struct clk_hw *best_parent, *hw = &common->hw; + unsigned int i; + + if (clk_hw_get_flags(hw) & CLK_SET_RATE_NO_REPARENT) { + unsigned long adj_parent_rate; + + best_parent = clk_hw_get_parent(hw); + best_parent_rate = clk_hw_get_rate(best_parent); + + best_rate = round(best_parent, &adj_parent_rate, + req->rate, -1, data); + + goto find; + } + + for (i = 0; i < clk_hw_get_num_parents(hw); i++) { + unsigned long tmp_rate, parent_rate; + struct clk_hw *parent; + + parent = clk_hw_get_parent_by_index(hw, i); + if (!parent) + continue; + + parent_rate = clk_hw_get_rate(parent); + + tmp_rate = round(parent, &parent_rate, req->rate, i, data); + + if (tmp_rate == req->rate) { + best_parent = parent; + best_parent_rate = parent_rate; + best_rate = tmp_rate; + goto find; + } + + if (div_is_better_rate(common, req->rate, + tmp_rate, best_rate)) { + best_parent = parent; + best_parent_rate = parent_rate; + best_rate = tmp_rate; + } + } + + if (best_rate == 0) + return -EINVAL; + +find: + req->best_parent_hw = best_parent; + req->best_parent_rate = best_parent_rate; + req->rate = best_rate; + return 0; +} + +static int div_determine_rate(struct clk_hw *hw, + struct clk_rate_request *req) +{ + struct cv1800_clk_div *div = hw_to_cv1800_clk_div(hw); + + return mux_helper_determine_rate(&div->common, req, + div_round_rate, div); +} + +static unsigned long div_recalc_rate(struct clk_hw *hw, + unsigned long parent_rate) +{ + struct cv1800_clk_div *div = hw_to_cv1800_clk_div(hw); + unsigned long val; + + val = div_helper_get_clockdiv(&div->common, &div->div); + if (val == 0) + return 0; + + return divider_recalc_rate(hw, parent_rate, val, NULL, + div->div.flags, div->div.width); +} + +static int div_set_rate(struct clk_hw *hw, unsigned long rate, + unsigned long parent_rate) +{ + struct cv1800_clk_div *div = hw_to_cv1800_clk_div(hw); + unsigned long val; + + val = divider_get_val(rate, parent_rate, NULL, + div->div.width, div->div.flags); + + return div_helper_set_rate(&div->common, &div->div, val); +} + +const struct clk_ops cv1800_clk_div_ops = { + .disable = div_disable, + .enable = div_enable, + .is_enabled = div_is_enabled, + + .determine_rate = div_determine_rate, + .recalc_rate = div_recalc_rate, + .set_rate = div_set_rate, +}; + +static inline struct cv1800_clk_bypass_div * +hw_to_cv1800_clk_bypass_div(struct clk_hw *hw) +{ + struct cv1800_clk_div *div = hw_to_cv1800_clk_div(hw); + + return container_of(div, struct cv1800_clk_bypass_div, div); +} + +static long bypass_div_round_rate(struct clk_hw *parent, + unsigned long *parent_rate, + unsigned long rate, int id, void *data) +{ + struct cv1800_clk_bypass_div *div = data; + + if (id == -1) { + if (cv1800_clk_checkbit(&div->div.common, &div->bypass)) + return *parent_rate; + else + return div_round_rate(parent, parent_rate, rate, + -1, &div->div); + } + + if (id == 0) + return *parent_rate; + + return div_round_rate(parent, parent_rate, rate, id - 1, &div->div); +} + +static int bypass_div_determine_rate(struct clk_hw *hw, + struct clk_rate_request *req) +{ + struct cv1800_clk_bypass_div *div = hw_to_cv1800_clk_bypass_div(hw); + + return mux_helper_determine_rate(&div->div.common, req, + bypass_div_round_rate, div); +} + +static unsigned long bypass_div_recalc_rate(struct clk_hw *hw, + unsigned long parent_rate) +{ + struct cv1800_clk_bypass_div *div = hw_to_cv1800_clk_bypass_div(hw); + + if (cv1800_clk_checkbit(&div->div.common, &div->bypass)) + return parent_rate; + + return div_recalc_rate(hw, parent_rate); +} + +static int bypass_div_set_rate(struct clk_hw *hw, unsigned long rate, + unsigned long parent_rate) +{ + struct cv1800_clk_bypass_div *div = hw_to_cv1800_clk_bypass_div(hw); + + if (cv1800_clk_checkbit(&div->div.common, &div->bypass)) + return 0; + + return div_set_rate(hw, rate, parent_rate); +} + +static u8 bypass_div_get_parent(struct clk_hw *hw) +{ + struct cv1800_clk_bypass_div *div = hw_to_cv1800_clk_bypass_div(hw); + + if (cv1800_clk_checkbit(&div->div.common, &div->bypass)) + return 0; + + return 1; +} + +static int bypass_div_set_parent(struct clk_hw *hw, u8 index) +{ + struct cv1800_clk_bypass_div *div = hw_to_cv1800_clk_bypass_div(hw); + + if (index) + return cv1800_clk_clearbit(&div->div.common, &div->bypass); + + return cv1800_clk_setbit(&div->div.common, &div->bypass); +} + +const struct clk_ops cv1800_clk_bypass_div_ops = { + .disable = div_disable, + .enable = div_enable, + .is_enabled = div_is_enabled, + + .determine_rate = bypass_div_determine_rate, + .recalc_rate = bypass_div_recalc_rate, + .set_rate = bypass_div_set_rate, + + .set_parent = bypass_div_set_parent, + .get_parent = bypass_div_get_parent, +}; + +/* MUX */ +static inline struct cv1800_clk_mux *hw_to_cv1800_clk_mux(struct clk_hw *hw) +{ + struct cv1800_clk_common *common = hw_to_cv1800_clk_common(hw); + + return container_of(common, struct cv1800_clk_mux, common); +} + +static int mux_enable(struct clk_hw *hw) +{ + struct cv1800_clk_mux *mux = hw_to_cv1800_clk_mux(hw); + + return cv1800_clk_setbit(&mux->common, &mux->gate); +} + +static void mux_disable(struct clk_hw *hw) +{ + struct cv1800_clk_mux *mux = hw_to_cv1800_clk_mux(hw); + + cv1800_clk_clearbit(&mux->common, &mux->gate); +} + +static int mux_is_enabled(struct clk_hw *hw) +{ + struct cv1800_clk_mux *mux = hw_to_cv1800_clk_mux(hw); + + return cv1800_clk_checkbit(&mux->common, &mux->gate); +} + +static long mux_round_rate(struct clk_hw *parent, unsigned long *parent_rate, + unsigned long rate, int id, void *data) +{ + struct cv1800_clk_mux *mux = data; + + return div_helper_round_rate(&mux->div, &mux->common.hw, parent, + rate, parent_rate); +} + +static int mux_determine_rate(struct clk_hw *hw, + struct clk_rate_request *req) +{ + struct cv1800_clk_mux *mux = hw_to_cv1800_clk_mux(hw); + + return mux_helper_determine_rate(&mux->common, req, + mux_round_rate, mux); +} + +static unsigned long mux_recalc_rate(struct clk_hw *hw, + unsigned long parent_rate) +{ + struct cv1800_clk_mux *mux = hw_to_cv1800_clk_mux(hw); + unsigned long val; + + val = div_helper_get_clockdiv(&mux->common, &mux->div); + if (val == 0) + return 0; + + return divider_recalc_rate(hw, parent_rate, val, NULL, + mux->div.flags, mux->div.width); +} + +static int mux_set_rate(struct clk_hw *hw, unsigned long rate, + unsigned long parent_rate) +{ + struct cv1800_clk_mux *mux = hw_to_cv1800_clk_mux(hw); + unsigned long val; + + val = divider_get_val(rate, parent_rate, NULL, + mux->div.width, mux->div.flags); + + return div_helper_set_rate(&mux->common, &mux->div, val); +} + +static u8 mux_get_parent(struct clk_hw *hw) +{ + struct cv1800_clk_mux *mux = hw_to_cv1800_clk_mux(hw); + u32 reg = readl(mux->common.base + mux->mux.reg); + + return cv1800_clk_regfield_get(reg, &mux->mux); +} + +static int _mux_set_parent(struct cv1800_clk_mux *mux, u8 index) +{ + u32 reg; + + reg = readl(mux->common.base + mux->mux.reg); + reg = cv1800_clk_regfield_set(reg, index, &mux->mux); + writel(reg, mux->common.base + mux->mux.reg); + + return 0; +} + +static int mux_set_parent(struct clk_hw *hw, u8 index) +{ + struct cv1800_clk_mux *mux = hw_to_cv1800_clk_mux(hw); + unsigned long flags; + + spin_lock_irqsave(mux->common.lock, flags); + + _mux_set_parent(mux, index); + + spin_unlock_irqrestore(mux->common.lock, flags); + + return 0; +} + +const struct clk_ops cv1800_clk_mux_ops = { + .disable = mux_disable, + .enable = mux_enable, + .is_enabled = mux_is_enabled, + + .determine_rate = mux_determine_rate, + .recalc_rate = mux_recalc_rate, + .set_rate = mux_set_rate, + + .set_parent = mux_set_parent, + .get_parent = mux_get_parent, +}; + +static inline struct cv1800_clk_bypass_mux * +hw_to_cv1800_clk_bypass_mux(struct clk_hw *hw) +{ + struct cv1800_clk_mux *mux = hw_to_cv1800_clk_mux(hw); + + return container_of(mux, struct cv1800_clk_bypass_mux, mux); +} + +static long bypass_mux_round_rate(struct clk_hw *parent, + unsigned long *parent_rate, + unsigned long rate, int id, void *data) +{ + struct cv1800_clk_bypass_mux *mux = data; + + if (id == -1) { + if (cv1800_clk_checkbit(&mux->mux.common, &mux->bypass)) + return *parent_rate; + else + return mux_round_rate(parent, parent_rate, rate, + -1, &mux->mux); + } + + if (id == 0) + return *parent_rate; + + return mux_round_rate(parent, parent_rate, rate, id - 1, &mux->mux); +} + +static int bypass_mux_determine_rate(struct clk_hw *hw, + struct clk_rate_request *req) +{ + struct cv1800_clk_bypass_mux *mux = hw_to_cv1800_clk_bypass_mux(hw); + + return mux_helper_determine_rate(&mux->mux.common, req, + bypass_mux_round_rate, mux); +} + +static unsigned long bypass_mux_recalc_rate(struct clk_hw *hw, + unsigned long parent_rate) +{ + struct cv1800_clk_bypass_mux *mux = hw_to_cv1800_clk_bypass_mux(hw); + + if (cv1800_clk_checkbit(&mux->mux.common, &mux->bypass)) + return parent_rate; + + return mux_recalc_rate(hw, parent_rate); +} + +static int bypass_mux_set_rate(struct clk_hw *hw, unsigned long rate, + unsigned long parent_rate) +{ + struct cv1800_clk_bypass_mux *mux = hw_to_cv1800_clk_bypass_mux(hw); + + if (cv1800_clk_checkbit(&mux->mux.common, &mux->bypass)) + return 0; + + return mux_set_rate(hw, rate, parent_rate); +} + +static u8 bypass_mux_get_parent(struct clk_hw *hw) +{ + struct cv1800_clk_bypass_mux *mux = hw_to_cv1800_clk_bypass_mux(hw); + + if (cv1800_clk_checkbit(&mux->mux.common, &mux->bypass)) + return 0; + + return mux_get_parent(hw) + 1; +} + +static int bypass_mux_set_parent(struct clk_hw *hw, u8 index) +{ + struct cv1800_clk_bypass_mux *mux = hw_to_cv1800_clk_bypass_mux(hw); + + if (index == 0) + return cv1800_clk_setbit(&mux->mux.common, &mux->bypass); + + return cv1800_clk_clearbit(&mux->mux.common, &mux->bypass); +} + +const struct clk_ops cv1800_clk_bypass_mux_ops = { + .disable = mux_disable, + .enable = mux_enable, + .is_enabled = mux_is_enabled, + + .determine_rate = bypass_mux_determine_rate, + .recalc_rate = bypass_mux_recalc_rate, + .set_rate = bypass_mux_set_rate, + + .set_parent = bypass_mux_set_parent, + .get_parent = bypass_mux_get_parent, +}; + +/* MMUX */ +static inline struct cv1800_clk_mmux *hw_to_cv1800_clk_mmux(struct clk_hw *hw) +{ + struct cv1800_clk_common *common = hw_to_cv1800_clk_common(hw); + + return container_of(common, struct cv1800_clk_mmux, common); +} + +static u8 mmux_get_parent_id(struct cv1800_clk_mmux *mmux) +{ + struct clk_hw *hw = &mmux->common.hw; + struct clk_hw *parent = clk_hw_get_parent(hw); + unsigned int i; + + for (i = 0; i < clk_hw_get_num_parents(hw); i++) { + if (parent == clk_hw_get_parent_by_index(hw, i)) + return i; + } + + unreachable(); +} + +static int mmux_enable(struct clk_hw *hw) +{ + struct cv1800_clk_mmux *mmux = hw_to_cv1800_clk_mmux(hw); + + return cv1800_clk_setbit(&mmux->common, &mmux->gate); +} + +static void mmux_disable(struct clk_hw *hw) +{ + struct cv1800_clk_mmux *mmux = hw_to_cv1800_clk_mmux(hw); + + cv1800_clk_clearbit(&mmux->common, &mmux->gate); +} + +static int mmux_is_enabled(struct clk_hw *hw) +{ + struct cv1800_clk_mmux *mmux = hw_to_cv1800_clk_mmux(hw); + + return cv1800_clk_checkbit(&mmux->common, &mmux->gate); +} + +static long mmux_round_rate(struct clk_hw *parent, unsigned long *parent_rate, + unsigned long rate, int id, void *data) +{ + struct cv1800_clk_mmux *mmux = data; + s8 div_id; + + if (id == -1) { + if (cv1800_clk_checkbit(&mmux->common, &mmux->bypass)) + return *parent_rate; + + id = mmux_get_parent_id(mmux); + } + + div_id = mmux->parent2sel[id]; + + if (div_id < 0) + return *parent_rate; + + return div_helper_round_rate(&mmux->div[div_id], + &mmux->common.hw, parent, + rate, parent_rate); +} + +static int mmux_determine_rate(struct clk_hw *hw, + struct clk_rate_request *req) +{ + struct cv1800_clk_mmux *mmux = hw_to_cv1800_clk_mmux(hw); + + return mux_helper_determine_rate(&mmux->common, req, + mmux_round_rate, mmux); +} + +static unsigned long mmux_recalc_rate(struct clk_hw *hw, + unsigned long parent_rate) +{ + struct cv1800_clk_mmux *mmux = hw_to_cv1800_clk_mmux(hw); + unsigned long val; + struct cv1800_clk_regfield *div; + + if (cv1800_clk_checkbit(&mmux->common, &mmux->bypass)) + return parent_rate; + + if (cv1800_clk_checkbit(&mmux->common, &mmux->clk_sel)) + div = &mmux->div[0]; + else + div = &mmux->div[1]; + + val = div_helper_get_clockdiv(&mmux->common, div); + if (val == 0) + return 0; + + return divider_recalc_rate(hw, parent_rate, val, NULL, + div->flags, div->width); +} + +static int mmux_set_rate(struct clk_hw *hw, unsigned long rate, + unsigned long parent_rate) +{ + struct cv1800_clk_mmux *mmux = hw_to_cv1800_clk_mmux(hw); + struct cv1800_clk_regfield *div; + unsigned long val; + + if (cv1800_clk_checkbit(&mmux->common, &mmux->bypass)) + return parent_rate; + + if (cv1800_clk_checkbit(&mmux->common, &mmux->clk_sel)) + div = &mmux->div[0]; + else + div = &mmux->div[1]; + + val = divider_get_val(rate, parent_rate, NULL, + div->width, div->flags); + + return div_helper_set_rate(&mmux->common, div, val); +} + +static u8 mmux_get_parent(struct clk_hw *hw) +{ + struct cv1800_clk_mmux *mmux = hw_to_cv1800_clk_mmux(hw); + struct cv1800_clk_regfield *mux; + u32 reg; + s8 clk_sel; + + if (cv1800_clk_checkbit(&mmux->common, &mmux->bypass)) + return 0; + + if (cv1800_clk_checkbit(&mmux->common, &mmux->clk_sel)) + clk_sel = 0; + else + clk_sel = 1; + mux = &mmux->mux[clk_sel]; + + reg = readl(mmux->common.base + mux->reg); + + return mmux->sel2parent[clk_sel][cv1800_clk_regfield_get(reg, mux)]; +} + +static int mmux_set_parent(struct clk_hw *hw, u8 index) +{ + struct cv1800_clk_mmux *mmux = hw_to_cv1800_clk_mmux(hw); + struct cv1800_clk_regfield *mux; + unsigned long flags; + u32 reg; + s8 clk_sel = mmux->parent2sel[index]; + + if (index == 0 || clk_sel == -1) { + cv1800_clk_setbit(&mmux->common, &mmux->bypass); + goto release; + } + + cv1800_clk_clearbit(&mmux->common, &mmux->bypass); + + if (clk_sel) + cv1800_clk_clearbit(&mmux->common, &mmux->clk_sel); + else + cv1800_clk_setbit(&mmux->common, &mmux->clk_sel); + + spin_lock_irqsave(mmux->common.lock, flags); + + mux = &mmux->mux[clk_sel]; + reg = readl(mmux->common.base + mux->reg); + reg = cv1800_clk_regfield_set(reg, index, mux); + + writel(reg, mmux->common.base + mux->reg); + + spin_unlock_irqrestore(mmux->common.lock, flags); + +release: + return 0; +} + +const struct clk_ops cv1800_clk_mmux_ops = { + .disable = mmux_disable, + .enable = mmux_enable, + .is_enabled = mmux_is_enabled, + + .determine_rate = mmux_determine_rate, + .recalc_rate = mmux_recalc_rate, + .set_rate = mmux_set_rate, + + .set_parent = mmux_set_parent, + .get_parent = mmux_get_parent, +}; + +/* AUDIO CLK */ +static inline struct cv1800_clk_audio * +hw_to_cv1800_clk_audio(struct clk_hw *hw) +{ + struct cv1800_clk_common *common = hw_to_cv1800_clk_common(hw); + + return container_of(common, struct cv1800_clk_audio, common); +} + +static int aclk_enable(struct clk_hw *hw) +{ + struct cv1800_clk_audio *aclk = hw_to_cv1800_clk_audio(hw); + + cv1800_clk_setbit(&aclk->common, &aclk->src_en); + return cv1800_clk_setbit(&aclk->common, &aclk->output_en); +} + +static void aclk_disable(struct clk_hw *hw) +{ + struct cv1800_clk_audio *aclk = hw_to_cv1800_clk_audio(hw); + + cv1800_clk_clearbit(&aclk->common, &aclk->output_en); + cv1800_clk_clearbit(&aclk->common, &aclk->src_en); +} + +static int aclk_is_enabled(struct clk_hw *hw) +{ + struct cv1800_clk_audio *aclk = hw_to_cv1800_clk_audio(hw); + + return cv1800_clk_checkbit(&aclk->common, &aclk->output_en); +} + +static int aclk_determine_rate(struct clk_hw *hw, + struct clk_rate_request *req) +{ + struct cv1800_clk_audio *aclk = hw_to_cv1800_clk_audio(hw); + + req->rate = aclk->target_rate; + + return 0; +} + +static unsigned long aclk_recalc_rate(struct clk_hw *hw, + unsigned long parent_rate) +{ + struct cv1800_clk_audio *aclk = hw_to_cv1800_clk_audio(hw); + u64 rate = parent_rate; + u64 factor = 2; + u32 regval; + + if (!cv1800_clk_checkbit(&aclk->common, &aclk->div_en)) + return 0; + + regval = readl(aclk->common.base + aclk->m.reg); + factor *= cv1800_clk_regfield_get(regval, &aclk->m); + + regval = readl(aclk->common.base + aclk->n.reg); + rate *= cv1800_clk_regfield_get(regval, &aclk->n); + + return DIV64_U64_ROUND_UP(rate, factor); +} + +static void aclk_determine_mn(unsigned long parent_rate, unsigned long rate, + u32 *m, u32 *n) +{ + u32 tm = parent_rate / 2; + u32 tn = rate; + u32 tcommon = gcd(tm, tn); + *m = tm / tcommon; + *n = tn / tcommon; +} + +static int aclk_set_rate(struct clk_hw *hw, unsigned long rate, + unsigned long parent_rate) +{ + struct cv1800_clk_audio *aclk = hw_to_cv1800_clk_audio(hw); + unsigned long flags; + u32 m, n; + + aclk_determine_mn(parent_rate, rate, + &m, &n); + + spin_lock_irqsave(aclk->common.lock, flags); + + writel(m, aclk->common.base + aclk->m.reg); + writel(n, aclk->common.base + aclk->n.reg); + + cv1800_clk_setbit(&aclk->common, &aclk->div_en); + cv1800_clk_setbit(&aclk->common, &aclk->div_up); + + spin_unlock_irqrestore(aclk->common.lock, flags); + + return 0; +} + +const struct clk_ops cv1800_clk_audio_ops = { + .disable = aclk_disable, + .enable = aclk_enable, + .is_enabled = aclk_is_enabled, + + .determine_rate = aclk_determine_rate, + .recalc_rate = aclk_recalc_rate, + .set_rate = aclk_set_rate, +}; diff --git a/drivers/clk/sophgo/clk-cv18xx-ip.h b/drivers/clk/sophgo/clk-cv18xx-ip.h new file mode 100644 index 000000000000..b37ba42bfde3 --- /dev/null +++ b/drivers/clk/sophgo/clk-cv18xx-ip.h @@ -0,0 +1,261 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Copyright (C) 2023 Inochi Amaoto + */ + +#ifndef _CLK_SOPHGO_CV1800_IP_H_ +#define _CLK_SOPHGO_CV1800_IP_H_ + +#include "clk-cv18xx-common.h" + +struct cv1800_clk_gate { + struct cv1800_clk_common common; + struct cv1800_clk_regbit gate; +}; + +struct cv1800_clk_div_data { + u32 reg; + u32 mask; + u32 width; + u32 init; + u32 flags; +}; + +struct cv1800_clk_div { + struct cv1800_clk_common common; + struct cv1800_clk_regbit gate; + struct cv1800_clk_regfield div; +}; + +struct cv1800_clk_bypass_div { + struct cv1800_clk_div div; + struct cv1800_clk_regbit bypass; +}; + +struct cv1800_clk_mux { + struct cv1800_clk_common common; + struct cv1800_clk_regbit gate; + struct cv1800_clk_regfield div; + struct cv1800_clk_regfield mux; +}; + +struct cv1800_clk_bypass_mux { + struct cv1800_clk_mux mux; + struct cv1800_clk_regbit bypass; +}; + +struct cv1800_clk_mmux { + struct cv1800_clk_common common; + struct cv1800_clk_regbit gate; + struct cv1800_clk_regfield div[2]; + struct cv1800_clk_regfield mux[2]; + struct cv1800_clk_regbit bypass; + struct cv1800_clk_regbit clk_sel; + const s8 *parent2sel; + const u8 *sel2parent[2]; +}; + +struct cv1800_clk_audio { + struct cv1800_clk_common common; + struct cv1800_clk_regbit src_en; + struct cv1800_clk_regbit output_en; + struct cv1800_clk_regbit div_en; + struct cv1800_clk_regbit div_up; + struct cv1800_clk_regfield m; + struct cv1800_clk_regfield n; + u32 target_rate; +}; + +#define CV1800_GATE(_name, _parent, _gate_reg, _gate_shift, _flags) \ + struct cv1800_clk_gate _name = { \ + .common = CV1800_CLK_COMMON(#_name, _parent, \ + &cv1800_clk_gate_ops, \ + _flags), \ + .gate = CV1800_CLK_BIT(_gate_reg, _gate_shift), \ + } + +#define _CV1800_DIV(_name, _parent, _gate_reg, _gate_shift, \ + _div_reg, _div_shift, _div_width, _div_init, \ + _div_flag, _ops, _flags) \ + { \ + .common = CV1800_CLK_COMMON(#_name, _parent, \ + _ops, _flags), \ + .gate = CV1800_CLK_BIT(_gate_reg, \ + _gate_shift), \ + .div = CV1800_CLK_REG(_div_reg, _div_shift, \ + _div_width, _div_init, \ + _div_flag), \ + } + +#define _CV1800_FIXED_DIV_FLAG \ + (CLK_DIVIDER_ONE_BASED | CLK_DIVIDER_ROUND_CLOSEST) + +#define _CV1800_FIXED_DIV(_name, _parent, _gate_reg, _gate_shift, \ + _fix_div, _ops, _flags) \ + { \ + .common = CV1800_CLK_COMMON(#_name, _parent, \ + _ops, _flags), \ + .gate = CV1800_CLK_BIT(_gate_reg, \ + _gate_shift), \ + .div = CV1800_CLK_REG(0, 0, 0, \ + _fix_div, \ + _CV1800_FIXED_DIV_FLAG),\ + } + +#define CV1800_DIV(_name, _parent, _gate_reg, _gate_shift, \ + _div_reg, _div_shift, _div_width, _div_init, \ + _div_flag, _flags) \ + struct cv1800_clk_div _name = \ + _CV1800_DIV(_name, _parent, _gate_reg, _gate_shift, \ + _div_reg, _div_shift, _div_width, _div_init,\ + _div_flag, &cv1800_clk_div_ops, _flags) + +#define CV1800_BYPASS_DIV(_name, _parent, _gate_reg, _gate_shift, \ + _div_reg, _div_shift, _div_width, _div_init, \ + _div_flag, _bypass_reg, _bypass_shift, _flags)\ + struct cv1800_clk_bypass_div _name = { \ + .div = _CV1800_DIV(_name, _parent, \ + _gate_reg, _gate_shift, \ + _div_reg, _div_shift, \ + _div_width, _div_init, _div_flag, \ + &cv1800_clk_bypass_div_ops, \ + _flags), \ + .bypass = CV1800_CLK_BIT(_bypass_reg, _bypass_shift), \ + } + +#define CV1800_FIXED_DIV(_name, _parent, _gate_reg, _gate_shift, \ + _fix_div, _flags) \ + struct cv1800_clk_div _name = \ + _CV1800_FIXED_DIV(_name, _parent, \ + _gate_reg, _gate_shift, \ + _fix_div, \ + &cv1800_clk_div_ops, _flags) \ + +#define CV1800_BYPASS_FIXED_DIV(_name, _parent, _gate_reg, _gate_shift, \ + _fix_div, _bypass_reg, _bypass_shift, \ + _flags) \ + struct cv1800_clk_bypass_div _name = { \ + .div = _CV1800_FIXED_DIV(_name, _parent, \ + _gate_reg, _gate_shift, \ + _fix_div, \ + &cv1800_clk_bypass_div_ops, \ + _flags), \ + .bypass = CV1800_CLK_BIT(_bypass_reg, _bypass_shift), \ + } + +#define _CV1800_MUX(_name, _parent, _gate_reg, _gate_shift, \ + _div_reg, _div_shift, _div_width, _div_init, \ + _div_flag, \ + _mux_reg, _mux_shift, _mux_width, \ + _ops, _flags) \ + { \ + .common = CV1800_CLK_COMMON(#_name, _parent, \ + _ops, _flags), \ + .gate = CV1800_CLK_BIT(_gate_reg, \ + _gate_shift), \ + .div = CV1800_CLK_REG(_div_reg, _div_shift, \ + _div_width, _div_init, \ + _div_flag), \ + .mux = CV1800_CLK_REG(_mux_reg, _mux_shift, \ + _mux_width, 0, 0), \ + } + +#define CV1800_MUX(_name, _parent, _gate_reg, _gate_shift, \ + _div_reg, _div_shift, _div_width, _div_init, \ + _div_flag, \ + _mux_reg, _mux_shift, _mux_width, _flags) \ + struct cv1800_clk_mux _name = \ + _CV1800_MUX(_name, _parent, _gate_reg, _gate_shift, \ + _div_reg, _div_shift, _div_width, _div_init,\ + _div_flag, _mux_reg, _mux_shift, _mux_width,\ + &cv1800_clk_mux_ops, _flags) + +#define CV1800_BYPASS_MUX(_name, _parent, _gate_reg, _gate_shift, \ + _div_reg, _div_shift, _div_width, _div_init, \ + _div_flag, \ + _mux_reg, _mux_shift, _mux_width, \ + _bypass_reg, _bypass_shift, _flags) \ + struct cv1800_clk_bypass_mux _name = { \ + .mux = _CV1800_MUX(_name, _parent, \ + _gate_reg, _gate_shift, \ + _div_reg, _div_shift, _div_width, \ + _div_init, _div_flag, \ + _mux_reg, _mux_shift, _mux_width, \ + &cv1800_clk_bypass_mux_ops, \ + _flags), \ + .bypass = CV1800_CLK_BIT(_bypass_reg, _bypass_shift), \ + } + +#define CV1800_MMUX(_name, _parent, _gate_reg, _gate_shift, \ + _div0_reg, _div0_shift, _div0_width, _div0_init, \ + _div0_flag, \ + _div1_reg, _div1_shift, _div1_width, _div1_init, \ + _div1_flag, \ + _mux0_reg, _mux0_shift, _mux0_width, \ + _mux1_reg, _mux1_shift, _mux1_width, \ + _bypass_reg, _bypass_shift, \ + _clk_sel_reg, _clk_sel_shift, \ + _parent2sel, _sel2parent0, _sel2parent1, _flags) \ + struct cv1800_clk_mmux _name = { \ + .common = CV1800_CLK_COMMON(#_name, _parent, \ + &cv1800_clk_mmux_ops,\ + _flags), \ + .gate = CV1800_CLK_BIT(_gate_reg, _gate_shift),\ + .div = { \ + CV1800_CLK_REG(_div0_reg, _div0_shift, \ + _div0_width, _div0_init, \ + _div0_flag), \ + CV1800_CLK_REG(_div1_reg, _div1_shift, \ + _div1_width, _div1_init, \ + _div1_flag), \ + }, \ + .mux = { \ + CV1800_CLK_REG(_mux0_reg, _mux0_shift, \ + _mux0_width, 0, 0), \ + CV1800_CLK_REG(_mux1_reg, _mux1_shift, \ + _mux1_width, 0, 0), \ + }, \ + .bypass = CV1800_CLK_BIT(_bypass_reg, \ + _bypass_shift), \ + .clk_sel = CV1800_CLK_BIT(_clk_sel_reg, \ + _clk_sel_shift), \ + .parent2sel = _parent2sel, \ + .sel2parent = { _sel2parent0, _sel2parent1 }, \ + } + +#define CV1800_ACLK(_name, _parent, \ + _src_en_reg, _src_en_reg_shift, \ + _output_en_reg, _output_en_shift, \ + _div_en_reg, _div_en_reg_shift, \ + _div_up_reg, _div_up_reg_shift, \ + _m_reg, _m_shift, _m_width, _m_flag, \ + _n_reg, _n_shift, _n_width, _n_flag, \ + _target_rate, _flags) \ + struct cv1800_clk_audio _name = { \ + .common = CV1800_CLK_COMMON(#_name, _parent, \ + &cv1800_clk_audio_ops,\ + _flags), \ + .src_en = CV1800_CLK_BIT(_src_en_reg, \ + _src_en_reg_shift), \ + .output_en = CV1800_CLK_BIT(_output_en_reg, \ + _output_en_shift), \ + .div_en = CV1800_CLK_BIT(_div_en_reg, \ + _div_en_reg_shift), \ + .div_up = CV1800_CLK_BIT(_div_up_reg, \ + _div_up_reg_shift), \ + .m = CV1800_CLK_REG(_m_reg, _m_shift, \ + _m_width, 0, _m_flag), \ + .n = CV1800_CLK_REG(_n_reg, _n_shift, \ + _n_width, 0, _n_flag), \ + .target_rate = _target_rate, \ + } + +extern const struct clk_ops cv1800_clk_gate_ops; +extern const struct clk_ops cv1800_clk_div_ops; +extern const struct clk_ops cv1800_clk_bypass_div_ops; +extern const struct clk_ops cv1800_clk_mux_ops; +extern const struct clk_ops cv1800_clk_bypass_mux_ops; +extern const struct clk_ops cv1800_clk_mmux_ops; +extern const struct clk_ops cv1800_clk_audio_ops; + +#endif // _CLK_SOPHGO_CV1800_IP_H_ diff --git a/drivers/clk/sophgo/clk-cv18xx-pll.c b/drivers/clk/sophgo/clk-cv18xx-pll.c new file mode 100644 index 000000000000..c546dad1791c --- /dev/null +++ b/drivers/clk/sophgo/clk-cv18xx-pll.c @@ -0,0 +1,420 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (C) 2023 Inochi Amaoto + */ + +#include +#include +#include +#include + +#include "clk-cv18xx-pll.h" + +static inline struct cv1800_clk_pll *hw_to_cv1800_clk_pll(struct clk_hw *hw) +{ + struct cv1800_clk_common *common = hw_to_cv1800_clk_common(hw); + + return container_of(common, struct cv1800_clk_pll, common); +} + +static unsigned long ipll_calc_rate(unsigned long parent_rate, + unsigned long pre_div_sel, + unsigned long div_sel, + unsigned long post_div_sel) +{ + uint64_t rate = parent_rate; + + rate *= div_sel; + do_div(rate, pre_div_sel * post_div_sel); + + return rate; +} + +static unsigned long ipll_recalc_rate(struct clk_hw *hw, + unsigned long parent_rate) +{ + struct cv1800_clk_pll *pll = hw_to_cv1800_clk_pll(hw); + u32 value; + + value = readl(pll->common.base + pll->pll_reg); + + return ipll_calc_rate(parent_rate, + PLL_GET_PRE_DIV_SEL(value), + PLL_GET_DIV_SEL(value), + PLL_GET_POST_DIV_SEL(value)); +} + +static int ipll_find_rate(const struct cv1800_clk_pll_limit *limit, + unsigned long prate, unsigned long *rate, + u32 *value) +{ + unsigned long best_rate = 0; + unsigned long trate = *rate; + unsigned long pre_div_sel = 0, div_sel = 0, post_div_sel = 0; + unsigned long pre, div, post; + u32 detected = *value; + unsigned long tmp; + + for_each_pll_limit_range(pre, &limit->pre_div) { + for_each_pll_limit_range(div, &limit->div) { + for_each_pll_limit_range(post, &limit->post_div) { + tmp = ipll_calc_rate(prate, pre, div, post); + + if (tmp > trate) + continue; + + if ((trate - tmp) < (trate - best_rate)) { + best_rate = tmp; + pre_div_sel = pre; + div_sel = div; + post_div_sel = post; + } + } + } + } + + if (best_rate) { + detected = PLL_SET_PRE_DIV_SEL(detected, pre_div_sel); + detected = PLL_SET_POST_DIV_SEL(detected, post_div_sel); + detected = PLL_SET_DIV_SEL(detected, div_sel); + *value = detected; + *rate = best_rate; + return 0; + } + + return -EINVAL; +} + +static int ipll_determine_rate(struct clk_hw *hw, struct clk_rate_request *req) +{ + u32 val; + struct cv1800_clk_pll *pll = hw_to_cv1800_clk_pll(hw); + + return ipll_find_rate(pll->pll_limit, req->best_parent_rate, + &req->rate, &val); +} + +static void pll_get_mode_ctrl(unsigned long div_sel, + bool (*mode_ctrl_check)(unsigned long, + unsigned long, + unsigned long), + const struct cv1800_clk_pll_limit *limit, + u32 *value) +{ + unsigned long ictrl = 0, mode = 0; + u32 detected = *value; + + for_each_pll_limit_range(mode, &limit->mode) { + for_each_pll_limit_range(ictrl, &limit->ictrl) { + if (mode_ctrl_check(div_sel, ictrl, mode)) { + detected = PLL_SET_SEL_MODE(detected, mode); + detected = PLL_SET_ICTRL(detected, ictrl); + *value = detected; + return; + } + } + } +} + +static bool ipll_check_mode_ctrl_restrict(unsigned long div_sel, + unsigned long ictrl, + unsigned long mode) +{ + unsigned long left_rest = 20 * div_sel; + unsigned long right_rest = 35 * div_sel; + unsigned long test = 184 * (1 + mode) * (1 + ictrl) / 2; + + return test > left_rest && test <= right_rest; +} + +static int ipll_set_rate(struct clk_hw *hw, unsigned long rate, + unsigned long parent_rate) +{ + u32 regval, detected = 0; + unsigned long flags; + struct cv1800_clk_pll *pll = hw_to_cv1800_clk_pll(hw); + + ipll_find_rate(pll->pll_limit, parent_rate, &rate, &detected); + pll_get_mode_ctrl(PLL_GET_DIV_SEL(detected), + ipll_check_mode_ctrl_restrict, + pll->pll_limit, &detected); + + spin_lock_irqsave(pll->common.lock, flags); + + regval = readl(pll->common.base + pll->pll_reg); + regval = PLL_COPY_REG(regval, detected); + + writel(regval, pll->common.base + pll->pll_reg); + + spin_unlock_irqrestore(pll->common.lock, flags); + + cv1800_clk_wait_for_lock(&pll->common, pll->pll_status.reg, + BIT(pll->pll_status.shift)); + + return 0; +} + +static int pll_enable(struct clk_hw *hw) +{ + struct cv1800_clk_pll *pll = hw_to_cv1800_clk_pll(hw); + + return cv1800_clk_clearbit(&pll->common, &pll->pll_pwd); +} + +static void pll_disable(struct clk_hw *hw) +{ + struct cv1800_clk_pll *pll = hw_to_cv1800_clk_pll(hw); + + cv1800_clk_setbit(&pll->common, &pll->pll_pwd); +} + +static int pll_is_enable(struct clk_hw *hw) +{ + struct cv1800_clk_pll *pll = hw_to_cv1800_clk_pll(hw); + + return cv1800_clk_checkbit(&pll->common, &pll->pll_pwd) == 0; +} + +const struct clk_ops cv1800_clk_ipll_ops = { + .disable = pll_disable, + .enable = pll_enable, + .is_enabled = pll_is_enable, + + .recalc_rate = ipll_recalc_rate, + .determine_rate = ipll_determine_rate, + .set_rate = ipll_set_rate, +}; + +#define PLL_SYN_FACTOR_DOT_POS 26 +#define PLL_SYN_FACTOR_MINIMUM ((4 << PLL_SYN_FACTOR_DOT_POS) + 1) + +static bool fpll_is_factional_mode(struct cv1800_clk_pll *pll) +{ + return cv1800_clk_checkbit(&pll->common, &pll->pll_syn->en); +} + +static unsigned long fpll_calc_rate(unsigned long parent_rate, + unsigned long pre_div_sel, + unsigned long div_sel, + unsigned long post_div_sel, + unsigned long ssc_syn_set, + bool is_full_parent) +{ + u64 dividend = parent_rate * div_sel; + u64 factor = ssc_syn_set * pre_div_sel * post_div_sel; + unsigned long rate; + + dividend <<= PLL_SYN_FACTOR_DOT_POS - 1; + rate = dividend / factor; + dividend %= factor; + + if (is_full_parent) { + dividend <<= 1; + rate <<= 1; + } + + rate += DIV64_U64_ROUND_CLOSEST(dividend, factor); + + return rate; +} + +static unsigned long fpll_recalc_rate(struct clk_hw *hw, + unsigned long parent_rate) +{ + struct cv1800_clk_pll *pll = hw_to_cv1800_clk_pll(hw); + u32 value; + bool clk_full; + u32 syn_set; + + if (!fpll_is_factional_mode(pll)) + return ipll_recalc_rate(hw, parent_rate); + + syn_set = readl(pll->common.base + pll->pll_syn->set); + + if (syn_set == 0) + return 0; + + clk_full = cv1800_clk_checkbit(&pll->common, + &pll->pll_syn->clk_half); + + value = readl(pll->common.base + pll->pll_reg); + + return fpll_calc_rate(parent_rate, + PLL_GET_PRE_DIV_SEL(value), + PLL_GET_DIV_SEL(value), + PLL_GET_POST_DIV_SEL(value), + syn_set, clk_full); +} + +static unsigned long fpll_find_synthesizer(unsigned long parent, + unsigned long rate, + unsigned long pre_div, + unsigned long div, + unsigned long post_div, + bool is_full_parent, + u32 *ssc_syn_set) +{ + u32 test_max = U32_MAX, test_min = PLL_SYN_FACTOR_MINIMUM; + unsigned long trate; + + while (test_min < test_max) { + u32 tssc = (test_max + test_min) / 2; + + trate = fpll_calc_rate(parent, pre_div, div, post_div, + tssc, is_full_parent); + + if (trate == rate) { + test_min = tssc; + break; + } + + if (trate > rate) + test_min = tssc + 1; + else + test_max = tssc - 1; + } + + if (trate != 0) + *ssc_syn_set = test_min; + + return trate; +} + +static int fpll_find_rate(struct cv1800_clk_pll *pll, + const struct cv1800_clk_pll_limit *limit, + unsigned long prate, + unsigned long *rate, + u32 *value, u32 *ssc_syn_set) +{ + unsigned long best_rate = 0; + unsigned long pre_div_sel = 0, div_sel = 0, post_div_sel = 0; + unsigned long pre, div, post; + unsigned long trate = *rate; + u32 detected = *value; + unsigned long tmp; + bool clk_full = cv1800_clk_checkbit(&pll->common, + &pll->pll_syn->clk_half); + + for_each_pll_limit_range(pre, &limit->pre_div) { + for_each_pll_limit_range(post, &limit->post_div) { + for_each_pll_limit_range(div, &limit->div) { + tmp = fpll_find_synthesizer(prate, trate, + pre, div, post, + clk_full, + ssc_syn_set); + + if ((trate - tmp) < (trate - best_rate)) { + best_rate = tmp; + pre_div_sel = pre; + div_sel = div; + post_div_sel = post; + } + } + } + } + + if (best_rate) { + detected = PLL_SET_PRE_DIV_SEL(detected, pre_div_sel); + detected = PLL_SET_POST_DIV_SEL(detected, post_div_sel); + detected = PLL_SET_DIV_SEL(detected, div_sel); + *value = detected; + *rate = best_rate; + return 0; + } + + return -EINVAL; +} + +static int fpll_determine_rate(struct clk_hw *hw, struct clk_rate_request *req) +{ + struct cv1800_clk_pll *pll = hw_to_cv1800_clk_pll(hw); + u32 val, ssc_syn_set; + + if (!fpll_is_factional_mode(pll)) + return ipll_determine_rate(hw, req); + + fpll_find_rate(pll, &pll->pll_limit[2], req->best_parent_rate, + &req->rate, &val, &ssc_syn_set); + + return 0; +} + +static bool fpll_check_mode_ctrl_restrict(unsigned long div_sel, + unsigned long ictrl, + unsigned long mode) +{ + unsigned long left_rest = 10 * div_sel; + unsigned long right_rest = 24 * div_sel; + unsigned long test = 184 * (1 + mode) * (1 + ictrl) / 2; + + return test > left_rest && test <= right_rest; +} + +static int fpll_set_rate(struct clk_hw *hw, unsigned long rate, + unsigned long parent_rate) +{ + u32 regval; + u32 detected = 0, detected_ssc = 0; + unsigned long flags; + struct cv1800_clk_pll *pll = hw_to_cv1800_clk_pll(hw); + + if (!fpll_is_factional_mode(pll)) + return ipll_set_rate(hw, rate, parent_rate); + + fpll_find_rate(pll, &pll->pll_limit[2], parent_rate, + &rate, &detected, &detected_ssc); + pll_get_mode_ctrl(PLL_GET_DIV_SEL(detected), + fpll_check_mode_ctrl_restrict, + pll->pll_limit, &detected); + + spin_lock_irqsave(pll->common.lock, flags); + + writel(detected_ssc, pll->common.base + pll->pll_syn->set); + + regval = readl(pll->common.base + pll->pll_reg); + regval = PLL_COPY_REG(regval, detected); + + writel(regval, pll->common.base + pll->pll_reg); + + spin_unlock_irqrestore(pll->common.lock, flags); + + cv1800_clk_wait_for_lock(&pll->common, pll->pll_status.reg, + BIT(pll->pll_status.shift)); + + return 0; +} + +static u8 fpll_get_parent(struct clk_hw *hw) +{ + struct cv1800_clk_pll *pll = hw_to_cv1800_clk_pll(hw); + + if (fpll_is_factional_mode(pll)) + return 1; + + return 0; +} + +static int fpll_set_parent(struct clk_hw *hw, u8 index) +{ + struct cv1800_clk_pll *pll = hw_to_cv1800_clk_pll(hw); + + if (index) + cv1800_clk_setbit(&pll->common, &pll->pll_syn->en); + else + cv1800_clk_clearbit(&pll->common, &pll->pll_syn->en); + + return 0; +} + +const struct clk_ops cv1800_clk_fpll_ops = { + .disable = pll_disable, + .enable = pll_enable, + .is_enabled = pll_is_enable, + + .recalc_rate = fpll_recalc_rate, + .determine_rate = fpll_determine_rate, + .set_rate = fpll_set_rate, + + .set_parent = fpll_set_parent, + .get_parent = fpll_get_parent, +}; diff --git a/drivers/clk/sophgo/clk-cv18xx-pll.h b/drivers/clk/sophgo/clk-cv18xx-pll.h new file mode 100644 index 000000000000..7a33f3da2d64 --- /dev/null +++ b/drivers/clk/sophgo/clk-cv18xx-pll.h @@ -0,0 +1,118 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Copyright (C) 2023 Inochi Amaoto + */ + +#ifndef _CLK_SOPHGO_CV1800_PLL_H_ +#define _CLK_SOPHGO_CV1800_PLL_H_ + +#include "clk-cv18xx-common.h" + +struct cv1800_clk_pll_limit { + struct { + u8 min; + u8 max; + } pre_div, div, post_div, ictrl, mode; +}; + +#define _CV1800_PLL_LIMIT(_min, _max) \ + { \ + .min = _min, \ + .max = _max, \ + } \ + +#define for_each_pll_limit_range(_var, _restrict) \ + for (_var = (_restrict)->min; _var <= (_restrict)->max; _var++) + +struct cv1800_clk_pll_synthesizer { + struct cv1800_clk_regbit en; + struct cv1800_clk_regbit clk_half; + u32 ctrl; + u32 set; +}; + +#define _PLL_PRE_DIV_SEL_FIELD GENMASK(6, 0) +#define _PLL_POST_DIV_SEL_FIELD GENMASK(14, 8) +#define _PLL_SEL_MODE_FIELD GENMASK(16, 15) +#define _PLL_DIV_SEL_FIELD GENMASK(23, 17) +#define _PLL_ICTRL_FIELD GENMASK(26, 24) + +#define _PLL_ALL_FIELD_MASK \ + (_PLL_PRE_DIV_SEL_FIELD | \ + _PLL_POST_DIV_SEL_FIELD | \ + _PLL_SEL_MODE_FIELD | \ + _PLL_DIV_SEL_FIELD | \ + _PLL_ICTRL_FIELD) + +#define PLL_COPY_REG(_dest, _src) \ + (((_dest) & (~_PLL_ALL_FIELD_MASK)) | ((_src) & _PLL_ALL_FIELD_MASK)) + +#define PLL_GET_PRE_DIV_SEL(_reg) \ + FIELD_GET(_PLL_PRE_DIV_SEL_FIELD, (_reg)) +#define PLL_GET_POST_DIV_SEL(_reg) \ + FIELD_GET(_PLL_POST_DIV_SEL_FIELD, (_reg)) +#define PLL_GET_SEL_MODE(_reg) \ + FIELD_GET(_PLL_SEL_MODE_FIELD, (_reg)) +#define PLL_GET_DIV_SEL(_reg) \ + FIELD_GET(_PLL_DIV_SEL_FIELD, (_reg)) +#define PLL_GET_ICTRL(_reg) \ + FIELD_GET(_PLL_ICTRL_FIELD, (_reg)) + +#define PLL_SET_PRE_DIV_SEL(_reg, _val) \ + _CV1800_SET_FIELD((_reg), (_val), _PLL_PRE_DIV_SEL_FIELD) +#define PLL_SET_POST_DIV_SEL(_reg, _val) \ + _CV1800_SET_FIELD((_reg), (_val), _PLL_POST_DIV_SEL_FIELD) +#define PLL_SET_SEL_MODE(_reg, _val) \ + _CV1800_SET_FIELD((_reg), (_val), _PLL_SEL_MODE_FIELD) +#define PLL_SET_DIV_SEL(_reg, _val) \ + _CV1800_SET_FIELD((_reg), (_val), _PLL_DIV_SEL_FIELD) +#define PLL_SET_ICTRL(_reg, _val) \ + _CV1800_SET_FIELD((_reg), (_val), _PLL_ICTRL_FIELD) + +struct cv1800_clk_pll { + struct cv1800_clk_common common; + u32 pll_reg; + struct cv1800_clk_regbit pll_pwd; + struct cv1800_clk_regbit pll_status; + const struct cv1800_clk_pll_limit *pll_limit; + struct cv1800_clk_pll_synthesizer *pll_syn; +}; + +#define CV1800_INTEGRAL_PLL(_name, _parent, _pll_reg, \ + _pll_pwd_reg, _pll_pwd_shift, \ + _pll_status_reg, _pll_status_shift, \ + _pll_limit, _flags) \ + struct cv1800_clk_pll _name = { \ + .common = CV1800_CLK_COMMON(#_name, _parent, \ + &cv1800_clk_ipll_ops,\ + _flags), \ + .pll_reg = _pll_reg, \ + .pll_pwd = CV1800_CLK_BIT(_pll_pwd_reg, \ + _pll_pwd_shift), \ + .pll_status = CV1800_CLK_BIT(_pll_status_reg, \ + _pll_status_shift), \ + .pll_limit = _pll_limit, \ + .pll_syn = NULL, \ + } + +#define CV1800_FACTIONAL_PLL(_name, _parent, _pll_reg, \ + _pll_pwd_reg, _pll_pwd_shift, \ + _pll_status_reg, _pll_status_shift, \ + _pll_limit, _pll_syn, _flags) \ + struct cv1800_clk_pll _name = { \ + .common = CV1800_CLK_COMMON(#_name, _parent, \ + &cv1800_clk_fpll_ops,\ + _flags), \ + .pll_reg = _pll_reg, \ + .pll_pwd = CV1800_CLK_BIT(_pll_pwd_reg, \ + _pll_pwd_shift), \ + .pll_status = CV1800_CLK_BIT(_pll_status_reg, \ + _pll_status_shift), \ + .pll_limit = _pll_limit, \ + .pll_syn = _pll_syn, \ + } + +extern const struct clk_ops cv1800_clk_ipll_ops; +extern const struct clk_ops cv1800_clk_fpll_ops; + +#endif // _CLK_SOPHGO_CV1800_PLL_H_ From 3b8d2042122846e3e61b184f9d17690d31a885a4 Mon Sep 17 00:00:00 2001 From: Inochi Amaoto Date: Sat, 9 Mar 2024 17:02:53 +0800 Subject: [PATCH 032/118] clk: sophgo: Add clock support for CV1810 SoC Add clock definition and init code for CV1810 SoC. Signed-off-by: Inochi Amaoto Link: https://github.com/milkv-duo/duo-files/blob/6f4e9b8ecb459e017cca1a8df248a19ca70837a3/duo/datasheet/CV180X-Clock-v1.xlsx Link: https://lore.kernel.org/r/IA1PR20MB495357FB5EEA1623DAB08C94BB262@IA1PR20MB4953.namprd20.prod.outlook.com Signed-off-by: Stephen Boyd --- drivers/clk/sophgo/clk-cv1800.c | 195 ++++++++++++++++++++++++++++++++ drivers/clk/sophgo/clk-cv1800.h | 1 + 2 files changed, 196 insertions(+) diff --git a/drivers/clk/sophgo/clk-cv1800.c b/drivers/clk/sophgo/clk-cv1800.c index 6606a2701b12..c7d4aa6c8343 100644 --- a/drivers/clk/sophgo/clk-cv1800.c +++ b/drivers/clk/sophgo/clk-cv1800.c @@ -631,6 +631,10 @@ static const struct clk_parent_data clk_vip_sys_parents[] = { { .hw = &clk_disppll.common.hw }, { .hw = &clk_fpll.common.hw }, }; +static const struct clk_parent_data clk_disp_vip_parents[] = { + { .index = 0 }, + { .hw = &clk_disppll.common.hw }, +}; static CV1800_BYPASS_DIV(clk_dsi_esc, clk_bypass_axi6_bus_parents, REG_CLK_EN_2, 3, @@ -660,6 +664,11 @@ static CV1800_BYPASS_MUX(clk_src_vip_sys_1, clk_vip_sys_parents, REG_DIV_CLK_SRC_VIP_SYS_1, 8, 2, REG_CLK_BYP_0, 24, 0); +static CV1800_BYPASS_DIV(clk_disp_src_vip, clk_disp_vip_parents, + REG_CLK_EN_2, 7, + REG_DIV_CLK_DISP_SRC_VIP, 16, 4, 8, CV1800_DIV_FLAG, + REG_CLK_BYP_0, 25, + 0); static CV1800_BYPASS_MUX(clk_src_vip_sys_2, clk_vip_sys_parents, REG_CLK_EN_3, 29, REG_DIV_CLK_SRC_VIP_SYS_2, 16, 4, 2, CV1800_DIV_FLAG, @@ -1243,6 +1252,191 @@ static const struct cv1800_clk_desc cv1800_desc = { .pre_init = cv1800_pre_init, }; +static struct clk_hw_onecell_data cv1810_hw_clks = { + .num = CV1810_CLK_MAX, + .hws = { + [CLK_MPLL] = &clk_mpll.common.hw, + [CLK_TPLL] = &clk_tpll.common.hw, + [CLK_FPLL] = &clk_fpll.common.hw, + [CLK_MIPIMPLL] = &clk_mipimpll.common.hw, + [CLK_A0PLL] = &clk_a0pll.common.hw, + [CLK_DISPPLL] = &clk_disppll.common.hw, + [CLK_CAM0PLL] = &clk_cam0pll.common.hw, + [CLK_CAM1PLL] = &clk_cam1pll.common.hw, + + [CLK_MIPIMPLL_D3] = &clk_mipimpll_d3.common.hw, + [CLK_CAM0PLL_D2] = &clk_cam0pll_d2.common.hw, + [CLK_CAM0PLL_D3] = &clk_cam0pll_d3.common.hw, + + [CLK_TPU] = &clk_tpu.mux.common.hw, + [CLK_TPU_FAB] = &clk_tpu_fab.common.hw, + [CLK_AHB_ROM] = &clk_ahb_rom.common.hw, + [CLK_DDR_AXI_REG] = &clk_ddr_axi_reg.common.hw, + [CLK_RTC_25M] = &clk_rtc_25m.common.hw, + [CLK_SRC_RTC_SYS_0] = &clk_src_rtc_sys_0.div.common.hw, + [CLK_TEMPSEN] = &clk_tempsen.common.hw, + [CLK_SARADC] = &clk_saradc.common.hw, + [CLK_EFUSE] = &clk_efuse.common.hw, + [CLK_APB_EFUSE] = &clk_apb_efuse.common.hw, + [CLK_DEBUG] = &clk_debug.common.hw, + [CLK_AP_DEBUG] = &clk_ap_debug.div.common.hw, + [CLK_XTAL_MISC] = &clk_xtal_misc.common.hw, + [CLK_AXI4_EMMC] = &clk_axi4_emmc.common.hw, + [CLK_EMMC] = &clk_emmc.mux.common.hw, + [CLK_EMMC_100K] = &clk_emmc_100k.common.hw, + [CLK_AXI4_SD0] = &clk_axi4_sd0.common.hw, + [CLK_SD0] = &clk_sd0.mux.common.hw, + [CLK_SD0_100K] = &clk_sd0_100k.common.hw, + [CLK_AXI4_SD1] = &clk_axi4_sd1.common.hw, + [CLK_SD1] = &clk_sd1.mux.common.hw, + [CLK_SD1_100K] = &clk_sd1_100k.common.hw, + [CLK_SPI_NAND] = &clk_spi_nand.mux.common.hw, + [CLK_ETH0_500M] = &clk_eth0_500m.div.common.hw, + [CLK_AXI4_ETH0] = &clk_axi4_eth0.common.hw, + [CLK_ETH1_500M] = &clk_eth1_500m.div.common.hw, + [CLK_AXI4_ETH1] = &clk_axi4_eth1.common.hw, + [CLK_APB_GPIO] = &clk_apb_gpio.common.hw, + [CLK_APB_GPIO_INTR] = &clk_apb_gpio_intr.common.hw, + [CLK_GPIO_DB] = &clk_gpio_db.common.hw, + [CLK_AHB_SF] = &clk_ahb_sf.common.hw, + [CLK_AHB_SF1] = &clk_ahb_sf1.common.hw, + [CLK_A24M] = &clk_a24m.common.hw, + [CLK_AUDSRC] = &clk_audsrc.mux.common.hw, + [CLK_APB_AUDSRC] = &clk_apb_audsrc.common.hw, + [CLK_SDMA_AXI] = &clk_sdma_axi.common.hw, + [CLK_SDMA_AUD0] = &clk_sdma_aud0.mux.common.hw, + [CLK_SDMA_AUD1] = &clk_sdma_aud1.mux.common.hw, + [CLK_SDMA_AUD2] = &clk_sdma_aud2.mux.common.hw, + [CLK_SDMA_AUD3] = &clk_sdma_aud3.mux.common.hw, + [CLK_I2C] = &clk_i2c.div.common.hw, + [CLK_APB_I2C] = &clk_apb_i2c.common.hw, + [CLK_APB_I2C0] = &clk_apb_i2c0.common.hw, + [CLK_APB_I2C1] = &clk_apb_i2c1.common.hw, + [CLK_APB_I2C2] = &clk_apb_i2c2.common.hw, + [CLK_APB_I2C3] = &clk_apb_i2c3.common.hw, + [CLK_APB_I2C4] = &clk_apb_i2c4.common.hw, + [CLK_APB_WDT] = &clk_apb_wdt.common.hw, + [CLK_PWM_SRC] = &clk_pwm_src.mux.common.hw, + [CLK_PWM] = &clk_pwm.common.hw, + [CLK_SPI] = &clk_spi.div.common.hw, + [CLK_APB_SPI0] = &clk_apb_spi0.common.hw, + [CLK_APB_SPI1] = &clk_apb_spi1.common.hw, + [CLK_APB_SPI2] = &clk_apb_spi2.common.hw, + [CLK_APB_SPI3] = &clk_apb_spi3.common.hw, + [CLK_1M] = &clk_1m.common.hw, + [CLK_CAM0_200] = &clk_cam0_200.mux.common.hw, + [CLK_PM] = &clk_pm.common.hw, + [CLK_TIMER0] = &clk_timer0.common.hw, + [CLK_TIMER1] = &clk_timer1.common.hw, + [CLK_TIMER2] = &clk_timer2.common.hw, + [CLK_TIMER3] = &clk_timer3.common.hw, + [CLK_TIMER4] = &clk_timer4.common.hw, + [CLK_TIMER5] = &clk_timer5.common.hw, + [CLK_TIMER6] = &clk_timer6.common.hw, + [CLK_TIMER7] = &clk_timer7.common.hw, + [CLK_UART0] = &clk_uart0.common.hw, + [CLK_APB_UART0] = &clk_apb_uart0.common.hw, + [CLK_UART1] = &clk_uart1.common.hw, + [CLK_APB_UART1] = &clk_apb_uart1.common.hw, + [CLK_UART2] = &clk_uart2.common.hw, + [CLK_APB_UART2] = &clk_apb_uart2.common.hw, + [CLK_UART3] = &clk_uart3.common.hw, + [CLK_APB_UART3] = &clk_apb_uart3.common.hw, + [CLK_UART4] = &clk_uart4.common.hw, + [CLK_APB_UART4] = &clk_apb_uart4.common.hw, + [CLK_APB_I2S0] = &clk_apb_i2s0.common.hw, + [CLK_APB_I2S1] = &clk_apb_i2s1.common.hw, + [CLK_APB_I2S2] = &clk_apb_i2s2.common.hw, + [CLK_APB_I2S3] = &clk_apb_i2s3.common.hw, + [CLK_AXI4_USB] = &clk_axi4_usb.common.hw, + [CLK_APB_USB] = &clk_apb_usb.common.hw, + [CLK_USB_125M] = &clk_usb_125m.div.common.hw, + [CLK_USB_33K] = &clk_usb_33k.common.hw, + [CLK_USB_12M] = &clk_usb_12m.div.common.hw, + [CLK_AXI4] = &clk_axi4.mux.common.hw, + [CLK_AXI6] = &clk_axi6.div.common.hw, + [CLK_DSI_ESC] = &clk_dsi_esc.div.common.hw, + [CLK_AXI_VIP] = &clk_axi_vip.mux.common.hw, + [CLK_SRC_VIP_SYS_0] = &clk_src_vip_sys_0.mux.common.hw, + [CLK_SRC_VIP_SYS_1] = &clk_src_vip_sys_1.mux.common.hw, + [CLK_SRC_VIP_SYS_2] = &clk_src_vip_sys_2.mux.common.hw, + [CLK_SRC_VIP_SYS_3] = &clk_src_vip_sys_3.mux.common.hw, + [CLK_SRC_VIP_SYS_4] = &clk_src_vip_sys_4.mux.common.hw, + [CLK_CSI_BE_VIP] = &clk_csi_be_vip.common.hw, + [CLK_CSI_MAC0_VIP] = &clk_csi_mac0_vip.common.hw, + [CLK_CSI_MAC1_VIP] = &clk_csi_mac1_vip.common.hw, + [CLK_CSI_MAC2_VIP] = &clk_csi_mac2_vip.common.hw, + [CLK_CSI0_RX_VIP] = &clk_csi0_rx_vip.common.hw, + [CLK_CSI1_RX_VIP] = &clk_csi1_rx_vip.common.hw, + [CLK_ISP_TOP_VIP] = &clk_isp_top_vip.common.hw, + [CLK_IMG_D_VIP] = &clk_img_d_vip.common.hw, + [CLK_IMG_V_VIP] = &clk_img_v_vip.common.hw, + [CLK_SC_TOP_VIP] = &clk_sc_top_vip.common.hw, + [CLK_SC_D_VIP] = &clk_sc_d_vip.common.hw, + [CLK_SC_V1_VIP] = &clk_sc_v1_vip.common.hw, + [CLK_SC_V2_VIP] = &clk_sc_v2_vip.common.hw, + [CLK_SC_V3_VIP] = &clk_sc_v3_vip.common.hw, + [CLK_DWA_VIP] = &clk_dwa_vip.common.hw, + [CLK_BT_VIP] = &clk_bt_vip.common.hw, + [CLK_DISP_VIP] = &clk_disp_vip.common.hw, + [CLK_DSI_MAC_VIP] = &clk_dsi_mac_vip.common.hw, + [CLK_LVDS0_VIP] = &clk_lvds0_vip.common.hw, + [CLK_LVDS1_VIP] = &clk_lvds1_vip.common.hw, + [CLK_PAD_VI_VIP] = &clk_pad_vi_vip.common.hw, + [CLK_PAD_VI1_VIP] = &clk_pad_vi1_vip.common.hw, + [CLK_PAD_VI2_VIP] = &clk_pad_vi2_vip.common.hw, + [CLK_CFG_REG_VIP] = &clk_cfg_reg_vip.common.hw, + [CLK_VIP_IP0] = &clk_vip_ip0.common.hw, + [CLK_VIP_IP1] = &clk_vip_ip1.common.hw, + [CLK_VIP_IP2] = &clk_vip_ip2.common.hw, + [CLK_VIP_IP3] = &clk_vip_ip3.common.hw, + [CLK_IVE_VIP] = &clk_ive_vip.common.hw, + [CLK_RAW_VIP] = &clk_raw_vip.common.hw, + [CLK_OSDC_VIP] = &clk_osdc_vip.common.hw, + [CLK_CAM0_VIP] = &clk_cam0_vip.common.hw, + [CLK_AXI_VIDEO_CODEC] = &clk_axi_video_codec.mux.common.hw, + [CLK_VC_SRC0] = &clk_vc_src0.mux.common.hw, + [CLK_VC_SRC1] = &clk_vc_src1.div.common.hw, + [CLK_VC_SRC2] = &clk_vc_src2.div.common.hw, + [CLK_H264C] = &clk_h264c.common.hw, + [CLK_APB_H264C] = &clk_apb_h264c.common.hw, + [CLK_H265C] = &clk_h265c.common.hw, + [CLK_APB_H265C] = &clk_apb_h265c.common.hw, + [CLK_JPEG] = &clk_jpeg.common.hw, + [CLK_APB_JPEG] = &clk_apb_jpeg.common.hw, + [CLK_CAM0] = &clk_cam0.common.hw, + [CLK_CAM1] = &clk_cam1.common.hw, + [CLK_WGN] = &clk_wgn.common.hw, + [CLK_WGN0] = &clk_wgn0.common.hw, + [CLK_WGN1] = &clk_wgn1.common.hw, + [CLK_WGN2] = &clk_wgn2.common.hw, + [CLK_KEYSCAN] = &clk_keyscan.common.hw, + [CLK_CFG_REG_VC] = &clk_cfg_reg_vc.common.hw, + [CLK_C906_0] = &clk_c906_0.common.hw, + [CLK_C906_1] = &clk_c906_1.common.hw, + [CLK_A53] = &clk_a53.common.hw, + [CLK_CPU_AXI0] = &clk_cpu_axi0.div.common.hw, + [CLK_CPU_GIC] = &clk_cpu_gic.div.common.hw, + [CLK_XTAL_AP] = &clk_xtal_ap.common.hw, + [CLK_DISP_SRC_VIP] = &clk_disp_src_vip.div.common.hw, + }, +}; + +static int cv1810_pre_init(struct device *dev, void __iomem *base, + struct cv1800_clk_ctrl *ctrl, + const struct cv1800_clk_desc *desc) +{ + cv18xx_clk_disable_a53(base); + cv18xx_clk_disable_auto_pd(base); + + return 0; +} + +static const struct cv1800_clk_desc cv1810_desc = { + .clks_data = &cv1810_hw_clks, + .pre_init = cv1810_pre_init, +}; + static int cv1800_clk_init_ctrl(struct device *dev, void __iomem *reg, struct cv1800_clk_ctrl *ctrl, const struct cv1800_clk_desc *desc) @@ -1311,6 +1505,7 @@ static int cv1800_clk_probe(struct platform_device *pdev) static const struct of_device_id cv1800_clk_ids[] = { { .compatible = "sophgo,cv1800-clk", .data = &cv1800_desc }, + { .compatible = "sophgo,cv1810-clk", .data = &cv1810_desc }, { } }; MODULE_DEVICE_TABLE(of, cv1800_clk_ids); diff --git a/drivers/clk/sophgo/clk-cv1800.h b/drivers/clk/sophgo/clk-cv1800.h index 1b9c04b5ac3a..1e7107b5d05e 100644 --- a/drivers/clk/sophgo/clk-cv1800.h +++ b/drivers/clk/sophgo/clk-cv1800.h @@ -9,6 +9,7 @@ #include #define CV1800_CLK_MAX (CLK_XTAL_AP + 1) +#define CV1810_CLK_MAX (CLK_DISP_SRC_VIP + 1) #define REG_PLL_G2_CTRL 0x800 #define REG_PLL_G2_STATUS 0x804 From 1cce3e61af6a89aa4b01189257fba73e46244b2d Mon Sep 17 00:00:00 2001 From: Inochi Amaoto Date: Sat, 9 Mar 2024 17:02:54 +0800 Subject: [PATCH 033/118] clk: sophgo: Add clock support for SG2000 SoC Add init code for SG2000 SoC. Signed-off-by: Inochi Amaoto Link: https://github.com/sophgo/sophgo-doc/releases/tag/sg2000-datasheet-v1.0-alpha Link: https://lore.kernel.org/r/IA1PR20MB49537156E71B64483F15C0F2BB262@IA1PR20MB4953.namprd20.prod.outlook.com Signed-off-by: Stephen Boyd --- drivers/clk/sophgo/clk-cv1800.c | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/drivers/clk/sophgo/clk-cv1800.c b/drivers/clk/sophgo/clk-cv1800.c index c7d4aa6c8343..956de5b21a80 100644 --- a/drivers/clk/sophgo/clk-cv1800.c +++ b/drivers/clk/sophgo/clk-cv1800.c @@ -1437,6 +1437,20 @@ static const struct cv1800_clk_desc cv1810_desc = { .pre_init = cv1810_pre_init, }; +static int sg2000_pre_init(struct device *dev, void __iomem *base, + struct cv1800_clk_ctrl *ctrl, + const struct cv1800_clk_desc *desc) +{ + cv18xx_clk_disable_auto_pd(base); + + return 0; +} + +static const struct cv1800_clk_desc sg2000_desc = { + .clks_data = &cv1810_hw_clks, + .pre_init = sg2000_pre_init, +}; + static int cv1800_clk_init_ctrl(struct device *dev, void __iomem *reg, struct cv1800_clk_ctrl *ctrl, const struct cv1800_clk_desc *desc) @@ -1506,6 +1520,7 @@ static int cv1800_clk_probe(struct platform_device *pdev) static const struct of_device_id cv1800_clk_ids[] = { { .compatible = "sophgo,cv1800-clk", .data = &cv1800_desc }, { .compatible = "sophgo,cv1810-clk", .data = &cv1810_desc }, + { .compatible = "sophgo,sg2000-clk", .data = &sg2000_desc }, { } }; MODULE_DEVICE_TABLE(of, cv1800_clk_ids); From 0b1bfd15f3f9ffb1e36c88861e9ada3f58ccb234 Mon Sep 17 00:00:00 2001 From: Binbin Zhou Date: Thu, 11 Apr 2024 10:58:06 +0800 Subject: [PATCH 034/118] dt-bindings: clock: Add Loongson-2K expand clock index In the new Loongson-2K family of SoCs, more clock indexes are needed, such as clock gates. The patch adds these clock indexes Signed-off-by: Binbin Zhou Acked-by: Conor Dooley Link: https://lore.kernel.org/r/76844e0e4dae290425f7c8025f7f36810cb3a3a8.1712731524.git.zhoubinbin@loongson.cn Acked-by: Huacai Chen Signed-off-by: Stephen Boyd --- include/dt-bindings/clock/loongson,ls2k-clk.h | 54 ++++++++++++------- 1 file changed, 35 insertions(+), 19 deletions(-) diff --git a/include/dt-bindings/clock/loongson,ls2k-clk.h b/include/dt-bindings/clock/loongson,ls2k-clk.h index 3bc4dfc193c2..4279ba595f1e 100644 --- a/include/dt-bindings/clock/loongson,ls2k-clk.h +++ b/include/dt-bindings/clock/loongson,ls2k-clk.h @@ -7,24 +7,40 @@ #ifndef __DT_BINDINGS_CLOCK_LOONGSON2_H #define __DT_BINDINGS_CLOCK_LOONGSON2_H -#define LOONGSON2_REF_100M 0 -#define LOONGSON2_NODE_PLL 1 -#define LOONGSON2_DDR_PLL 2 -#define LOONGSON2_DC_PLL 3 -#define LOONGSON2_PIX0_PLL 4 -#define LOONGSON2_PIX1_PLL 5 -#define LOONGSON2_NODE_CLK 6 -#define LOONGSON2_HDA_CLK 7 -#define LOONGSON2_GPU_CLK 8 -#define LOONGSON2_DDR_CLK 9 -#define LOONGSON2_GMAC_CLK 10 -#define LOONGSON2_DC_CLK 11 -#define LOONGSON2_APB_CLK 12 -#define LOONGSON2_USB_CLK 13 -#define LOONGSON2_SATA_CLK 14 -#define LOONGSON2_PIX0_CLK 15 -#define LOONGSON2_PIX1_CLK 16 -#define LOONGSON2_BOOT_CLK 17 -#define LOONGSON2_CLK_END 18 +#define LOONGSON2_REF_100M 0 +#define LOONGSON2_NODE_PLL 1 +#define LOONGSON2_DDR_PLL 2 +#define LOONGSON2_DC_PLL 3 +#define LOONGSON2_PIX0_PLL 4 +#define LOONGSON2_PIX1_PLL 5 +#define LOONGSON2_NODE_CLK 6 +#define LOONGSON2_HDA_CLK 7 +#define LOONGSON2_GPU_CLK 8 +#define LOONGSON2_DDR_CLK 9 +#define LOONGSON2_GMAC_CLK 10 +#define LOONGSON2_DC_CLK 11 +#define LOONGSON2_APB_CLK 12 +#define LOONGSON2_USB_CLK 13 +#define LOONGSON2_SATA_CLK 14 +#define LOONGSON2_PIX0_CLK 15 +#define LOONGSON2_PIX1_CLK 16 +#define LOONGSON2_BOOT_CLK 17 +#define LOONGSON2_OUT0_GATE 18 +#define LOONGSON2_GMAC_GATE 19 +#define LOONGSON2_RIO_GATE 20 +#define LOONGSON2_DC_GATE 21 +#define LOONGSON2_GPU_GATE 22 +#define LOONGSON2_DDR_GATE 23 +#define LOONGSON2_HDA_GATE 24 +#define LOONGSON2_NODE_GATE 25 +#define LOONGSON2_EMMC_GATE 26 +#define LOONGSON2_PIX0_GATE 27 +#define LOONGSON2_PIX1_GATE 28 +#define LOONGSON2_OUT0_CLK 29 +#define LOONGSON2_RIO_CLK 30 +#define LOONGSON2_EMMC_CLK 31 +#define LOONGSON2_DES_CLK 32 +#define LOONGSON2_I2S_CLK 33 +#define LOONGSON2_MISC_CLK 34 #endif From 9796ec0bd04bb0e70487127d44949ca0554df5d3 Mon Sep 17 00:00:00 2001 From: Binbin Zhou Date: Thu, 11 Apr 2024 10:58:07 +0800 Subject: [PATCH 035/118] clk: clk-loongson2: Refactor driver for adding new platforms The driver only supported loongson-2K1000 at first, but the clock structure of loongson-2K0500 and loongson-2K2000 are actually similar, and I tried to refactor the whole driver to adjust to the addition of the new platform. Briefly, I have divided all clocks into three categories according to their properties and their parent clocks: Independent PLLs, clocks based on frequency scales, and clock dividers. Signed-off-by: Binbin Zhou Link: https://lore.kernel.org/r/fb020d1ca19e6f4cdcc95c87b2748869ca76b8ec.1712731524.git.zhoubinbin@loongson.cn Acked-by: Huacai Chen [sboyd@kernel.org: Drop clk.h include] Signed-off-by: Stephen Boyd --- drivers/clk/clk-loongson2.c | 490 ++++++++++++++++-------------------- 1 file changed, 214 insertions(+), 276 deletions(-) diff --git a/drivers/clk/clk-loongson2.c b/drivers/clk/clk-loongson2.c index bacdcbb287ac..749cf66aef2d 100644 --- a/drivers/clk/clk-loongson2.c +++ b/drivers/clk/clk-loongson2.c @@ -13,317 +13,254 @@ #include #include -#define LOONGSON2_PLL_MULT_SHIFT 32 -#define LOONGSON2_PLL_MULT_WIDTH 10 -#define LOONGSON2_PLL_DIV_SHIFT 26 -#define LOONGSON2_PLL_DIV_WIDTH 6 -#define LOONGSON2_APB_FREQSCALE_SHIFT 20 -#define LOONGSON2_APB_FREQSCALE_WIDTH 3 -#define LOONGSON2_USB_FREQSCALE_SHIFT 16 -#define LOONGSON2_USB_FREQSCALE_WIDTH 3 -#define LOONGSON2_SATA_FREQSCALE_SHIFT 12 -#define LOONGSON2_SATA_FREQSCALE_WIDTH 3 -#define LOONGSON2_BOOT_FREQSCALE_SHIFT 8 -#define LOONGSON2_BOOT_FREQSCALE_WIDTH 3 - -static void __iomem *loongson2_pll_base; - static const struct clk_parent_data pdata[] = { - { .fw_name = "ref_100m",}, + { .fw_name = "ref_100m", }, }; -static struct clk_hw *loongson2_clk_register(struct device *dev, - const char *name, - const char *parent_name, - const struct clk_ops *ops, - unsigned long flags) -{ - int ret; - struct clk_hw *hw; - struct clk_init_data init = { }; - - hw = devm_kzalloc(dev, sizeof(*hw), GFP_KERNEL); - if (!hw) - return ERR_PTR(-ENOMEM); - - init.name = name; - init.ops = ops; - init.flags = flags; - init.num_parents = 1; - - if (!parent_name) - init.parent_data = pdata; - else - init.parent_names = &parent_name; - - hw->init = &init; - - ret = devm_clk_hw_register(dev, hw); - if (ret) - hw = ERR_PTR(ret); - - return hw; -} - -static unsigned long loongson2_calc_pll_rate(int offset, unsigned long rate) -{ - u64 val; - u32 mult, div; - - val = readq(loongson2_pll_base + offset); - - mult = (val >> LOONGSON2_PLL_MULT_SHIFT) & - clk_div_mask(LOONGSON2_PLL_MULT_WIDTH); - div = (val >> LOONGSON2_PLL_DIV_SHIFT) & - clk_div_mask(LOONGSON2_PLL_DIV_WIDTH); - - return div_u64((u64)rate * mult, div); -} - -static unsigned long loongson2_node_recalc_rate(struct clk_hw *hw, - unsigned long parent_rate) -{ - return loongson2_calc_pll_rate(0x0, parent_rate); -} - -static const struct clk_ops loongson2_node_clk_ops = { - .recalc_rate = loongson2_node_recalc_rate, +enum loongson2_clk_type { + CLK_TYPE_PLL, + CLK_TYPE_SCALE, + CLK_TYPE_DIVIDER, + CLK_TYPE_NONE, }; -static unsigned long loongson2_ddr_recalc_rate(struct clk_hw *hw, - unsigned long parent_rate) -{ - return loongson2_calc_pll_rate(0x10, parent_rate); -} - -static const struct clk_ops loongson2_ddr_clk_ops = { - .recalc_rate = loongson2_ddr_recalc_rate, +struct loongson2_clk_provider { + void __iomem *base; + struct device *dev; + struct clk_hw_onecell_data clk_data; + spinlock_t clk_lock; /* protect access to DIV registers */ }; -static unsigned long loongson2_dc_recalc_rate(struct clk_hw *hw, - unsigned long parent_rate) -{ - return loongson2_calc_pll_rate(0x20, parent_rate); -} - -static const struct clk_ops loongson2_dc_clk_ops = { - .recalc_rate = loongson2_dc_recalc_rate, +struct loongson2_clk_data { + struct clk_hw hw; + void __iomem *reg; + u8 div_shift; + u8 div_width; + u8 mult_shift; + u8 mult_width; }; -static unsigned long loongson2_pix0_recalc_rate(struct clk_hw *hw, - unsigned long parent_rate) -{ - return loongson2_calc_pll_rate(0x30, parent_rate); -} - -static const struct clk_ops loongson2_pix0_clk_ops = { - .recalc_rate = loongson2_pix0_recalc_rate, +struct loongson2_clk_board_info { + u8 id; + enum loongson2_clk_type type; + const char *name; + const char *parent_name; + u8 reg_offset; + u8 div_shift; + u8 div_width; + u8 mult_shift; + u8 mult_width; }; -static unsigned long loongson2_pix1_recalc_rate(struct clk_hw *hw, - unsigned long parent_rate) -{ - return loongson2_calc_pll_rate(0x40, parent_rate); -} +#define CLK_DIV(_id, _name, _pname, _offset, _dshift, _dwidth) \ + { \ + .id = _id, \ + .type = CLK_TYPE_DIVIDER, \ + .name = _name, \ + .parent_name = _pname, \ + .reg_offset = _offset, \ + .div_shift = _dshift, \ + .div_width = _dwidth, \ + } -static const struct clk_ops loongson2_pix1_clk_ops = { - .recalc_rate = loongson2_pix1_recalc_rate, -}; +#define CLK_PLL(_id, _name, _offset, _mshift, _mwidth, \ + _dshift, _dwidth) \ + { \ + .id = _id, \ + .type = CLK_TYPE_PLL, \ + .name = _name, \ + .parent_name = NULL, \ + .reg_offset = _offset, \ + .mult_shift = _mshift, \ + .mult_width = _mwidth, \ + .div_shift = _dshift, \ + .div_width = _dwidth, \ + } -static unsigned long loongson2_calc_rate(unsigned long rate, - int shift, int width) -{ - u64 val; - u32 mult; - - val = readq(loongson2_pll_base + 0x50); - - mult = (val >> shift) & clk_div_mask(width); - - return div_u64((u64)rate * (mult + 1), 8); -} - -static unsigned long loongson2_boot_recalc_rate(struct clk_hw *hw, - unsigned long parent_rate) -{ - return loongson2_calc_rate(parent_rate, - LOONGSON2_BOOT_FREQSCALE_SHIFT, - LOONGSON2_BOOT_FREQSCALE_WIDTH); -} - -static const struct clk_ops loongson2_boot_clk_ops = { - .recalc_rate = loongson2_boot_recalc_rate, -}; - -static unsigned long loongson2_apb_recalc_rate(struct clk_hw *hw, - unsigned long parent_rate) -{ - return loongson2_calc_rate(parent_rate, - LOONGSON2_APB_FREQSCALE_SHIFT, - LOONGSON2_APB_FREQSCALE_WIDTH); -} - -static const struct clk_ops loongson2_apb_clk_ops = { - .recalc_rate = loongson2_apb_recalc_rate, -}; - -static unsigned long loongson2_usb_recalc_rate(struct clk_hw *hw, - unsigned long parent_rate) -{ - return loongson2_calc_rate(parent_rate, - LOONGSON2_USB_FREQSCALE_SHIFT, - LOONGSON2_USB_FREQSCALE_WIDTH); -} - -static const struct clk_ops loongson2_usb_clk_ops = { - .recalc_rate = loongson2_usb_recalc_rate, -}; - -static unsigned long loongson2_sata_recalc_rate(struct clk_hw *hw, - unsigned long parent_rate) -{ - return loongson2_calc_rate(parent_rate, - LOONGSON2_SATA_FREQSCALE_SHIFT, - LOONGSON2_SATA_FREQSCALE_WIDTH); -} - -static const struct clk_ops loongson2_sata_clk_ops = { - .recalc_rate = loongson2_sata_recalc_rate, -}; - -static inline int loongson2_check_clk_hws(struct clk_hw *clks[], unsigned int count) -{ - unsigned int i; - - for (i = 0; i < count; i++) - if (IS_ERR(clks[i])) { - pr_err("Loongson2 clk %u: register failed with %ld\n", - i, PTR_ERR(clks[i])); - return PTR_ERR(clks[i]); - } - - return 0; -} - -static int loongson2_clk_probe(struct platform_device *pdev) -{ - int ret; - struct clk_hw **hws; - struct clk_hw_onecell_data *clk_hw_data; - spinlock_t loongson2_clk_lock; - struct device *dev = &pdev->dev; - - loongson2_pll_base = devm_platform_ioremap_resource(pdev, 0); - if (IS_ERR(loongson2_pll_base)) - return PTR_ERR(loongson2_pll_base); - - clk_hw_data = devm_kzalloc(dev, struct_size(clk_hw_data, hws, LOONGSON2_CLK_END), - GFP_KERNEL); - if (WARN_ON(!clk_hw_data)) - return -ENOMEM; - - clk_hw_data->num = LOONGSON2_CLK_END; - hws = clk_hw_data->hws; - - hws[LOONGSON2_NODE_PLL] = loongson2_clk_register(dev, "node_pll", - NULL, - &loongson2_node_clk_ops, 0); - - hws[LOONGSON2_DDR_PLL] = loongson2_clk_register(dev, "ddr_pll", - NULL, - &loongson2_ddr_clk_ops, 0); - - hws[LOONGSON2_DC_PLL] = loongson2_clk_register(dev, "dc_pll", - NULL, - &loongson2_dc_clk_ops, 0); - - hws[LOONGSON2_PIX0_PLL] = loongson2_clk_register(dev, "pix0_pll", - NULL, - &loongson2_pix0_clk_ops, 0); - - hws[LOONGSON2_PIX1_PLL] = loongson2_clk_register(dev, "pix1_pll", - NULL, - &loongson2_pix1_clk_ops, 0); - - hws[LOONGSON2_BOOT_CLK] = loongson2_clk_register(dev, "boot", - NULL, - &loongson2_boot_clk_ops, 0); - - hws[LOONGSON2_NODE_CLK] = devm_clk_hw_register_divider(dev, "node", - "node_pll", 0, - loongson2_pll_base + 0x8, 0, - 6, CLK_DIVIDER_ONE_BASED, - &loongson2_clk_lock); +#define CLK_SCALE(_id, _name, _pname, _offset, \ + _dshift, _dwidth) \ + { \ + .id = _id, \ + .type = CLK_TYPE_SCALE, \ + .name = _name, \ + .parent_name = _pname, \ + .reg_offset = _offset, \ + .div_shift = _dshift, \ + .div_width = _dwidth, \ + } +static const struct loongson2_clk_board_info ls2k1000_clks[] = { + CLK_PLL(LOONGSON2_NODE_PLL, "pll_node", 0, 32, 10, 26, 6), + CLK_PLL(LOONGSON2_DDR_PLL, "pll_ddr", 0x10, 32, 10, 26, 6), + CLK_PLL(LOONGSON2_DC_PLL, "pll_dc", 0x20, 32, 10, 26, 6), + CLK_PLL(LOONGSON2_PIX0_PLL, "pll_pix0", 0x30, 32, 10, 26, 6), + CLK_PLL(LOONGSON2_PIX1_PLL, "pll_pix1", 0x40, 32, 10, 26, 6), + CLK_DIV(LOONGSON2_NODE_CLK, "clk_node", "pll_node", 0x8, 0, 6), + CLK_DIV(LOONGSON2_DDR_CLK, "clk_ddr", "pll_ddr", 0x18, 0, 6), + CLK_DIV(LOONGSON2_GPU_CLK, "clk_gpu", "pll_ddr", 0x18, 22, 6), /* * The hda clk divisor in the upper 32bits and the clk-prodiver * layer code doesn't support 64bit io operation thus a conversion * is required that subtract shift by 32 and add 4byte to the hda * address */ - hws[LOONGSON2_HDA_CLK] = devm_clk_hw_register_divider(dev, "hda", - "ddr_pll", 0, - loongson2_pll_base + 0x22, 12, - 7, CLK_DIVIDER_ONE_BASED, - &loongson2_clk_lock); + CLK_DIV(LOONGSON2_HDA_CLK, "clk_hda", "pll_ddr", 0x22, 12, 7), + CLK_DIV(LOONGSON2_DC_CLK, "clk_dc", "pll_dc", 0x28, 0, 6), + CLK_DIV(LOONGSON2_GMAC_CLK, "clk_gmac", "pll_dc", 0x28, 22, 6), + CLK_DIV(LOONGSON2_PIX0_CLK, "clk_pix0", "pll_pix0", 0x38, 0, 6), + CLK_DIV(LOONGSON2_PIX1_CLK, "clk_pix1", "pll_pix1", 0x38, 0, 6), + CLK_SCALE(LOONGSON2_BOOT_CLK, "clk_boot", NULL, 0x50, 8, 3), + CLK_SCALE(LOONGSON2_SATA_CLK, "clk_sata", "clk_gmac", 0x50, 12, 3), + CLK_SCALE(LOONGSON2_USB_CLK, "clk_usb", "clk_gmac", 0x50, 16, 3), + CLK_SCALE(LOONGSON2_APB_CLK, "clk_apb", "clk_gmac", 0x50, 20, 3), + { /* Sentinel */ }, +}; - hws[LOONGSON2_GPU_CLK] = devm_clk_hw_register_divider(dev, "gpu", - "ddr_pll", 0, - loongson2_pll_base + 0x18, 22, - 6, CLK_DIVIDER_ONE_BASED, - &loongson2_clk_lock); +static inline struct loongson2_clk_data *to_loongson2_clk(struct clk_hw *hw) +{ + return container_of(hw, struct loongson2_clk_data, hw); +} - hws[LOONGSON2_DDR_CLK] = devm_clk_hw_register_divider(dev, "ddr", - "ddr_pll", 0, - loongson2_pll_base + 0x18, 0, - 6, CLK_DIVIDER_ONE_BASED, - &loongson2_clk_lock); +static inline unsigned long loongson2_rate_part(u64 val, u8 shift, u8 width) +{ + return (val & GENMASK(shift + width - 1, shift)) >> shift; +} - hws[LOONGSON2_GMAC_CLK] = devm_clk_hw_register_divider(dev, "gmac", - "dc_pll", 0, - loongson2_pll_base + 0x28, 22, - 6, CLK_DIVIDER_ONE_BASED, - &loongson2_clk_lock); +static unsigned long loongson2_pll_recalc_rate(struct clk_hw *hw, + unsigned long parent_rate) +{ + u64 val, mult, div; + struct loongson2_clk_data *clk = to_loongson2_clk(hw); - hws[LOONGSON2_DC_CLK] = devm_clk_hw_register_divider(dev, "dc", - "dc_pll", 0, - loongson2_pll_base + 0x28, 0, - 6, CLK_DIVIDER_ONE_BASED, - &loongson2_clk_lock); + val = readq(clk->reg); + mult = loongson2_rate_part(val, clk->mult_shift, clk->mult_width); + div = loongson2_rate_part(val, clk->div_shift, clk->div_width); - hws[LOONGSON2_APB_CLK] = loongson2_clk_register(dev, "apb", - "gmac", - &loongson2_apb_clk_ops, 0); + return div_u64((u64)parent_rate * mult, div); +} - hws[LOONGSON2_USB_CLK] = loongson2_clk_register(dev, "usb", - "gmac", - &loongson2_usb_clk_ops, 0); +static const struct clk_ops loongson2_pll_recalc_ops = { + .recalc_rate = loongson2_pll_recalc_rate, +}; - hws[LOONGSON2_SATA_CLK] = loongson2_clk_register(dev, "sata", - "gmac", - &loongson2_sata_clk_ops, 0); +static unsigned long loongson2_freqscale_recalc_rate(struct clk_hw *hw, + unsigned long parent_rate) +{ + u64 val, mult; + struct loongson2_clk_data *clk = to_loongson2_clk(hw); - hws[LOONGSON2_PIX0_CLK] = clk_hw_register_divider(NULL, "pix0", - "pix0_pll", 0, - loongson2_pll_base + 0x38, 0, 6, - CLK_DIVIDER_ONE_BASED, - &loongson2_clk_lock); + val = readq(clk->reg); + mult = loongson2_rate_part(val, clk->div_shift, clk->div_width) + 1; - hws[LOONGSON2_PIX1_CLK] = clk_hw_register_divider(NULL, "pix1", - "pix1_pll", 0, - loongson2_pll_base + 0x48, 0, 6, - CLK_DIVIDER_ONE_BASED, - &loongson2_clk_lock); + return div_u64((u64)parent_rate * mult, 8); +} - ret = loongson2_check_clk_hws(hws, LOONGSON2_CLK_END); +static const struct clk_ops loongson2_freqscale_recalc_ops = { + .recalc_rate = loongson2_freqscale_recalc_rate, +}; + +static struct clk_hw *loongson2_clk_register(struct loongson2_clk_provider *clp, + const struct loongson2_clk_board_info *cld, + const struct clk_ops *ops) +{ + int ret; + struct clk_hw *hw; + struct loongson2_clk_data *clk; + struct clk_init_data init = { }; + + clk = devm_kzalloc(clp->dev, sizeof(*clk), GFP_KERNEL); + if (!clk) + return ERR_PTR(-ENOMEM); + + init.name = cld->name; + init.ops = ops; + init.flags = 0; + init.num_parents = 1; + + if (!cld->parent_name) + init.parent_data = pdata; + else + init.parent_names = &cld->parent_name; + + clk->reg = clp->base + cld->reg_offset; + clk->div_shift = cld->div_shift; + clk->div_width = cld->div_width; + clk->mult_shift = cld->mult_shift; + clk->mult_width = cld->mult_width; + clk->hw.init = &init; + + hw = &clk->hw; + ret = devm_clk_hw_register(clp->dev, hw); if (ret) - return ret; + clk = ERR_PTR(ret); - return devm_of_clk_add_hw_provider(dev, of_clk_hw_onecell_get, clk_hw_data); + return hw; +} + +static int loongson2_clk_probe(struct platform_device *pdev) +{ + int i, clks_num = 0; + struct clk_hw *hw; + struct device *dev = &pdev->dev; + struct loongson2_clk_provider *clp; + const struct loongson2_clk_board_info *p, *data; + + data = device_get_match_data(dev); + if (!data) + return -EINVAL; + + for (p = data; p->name; p++) + clks_num++; + + clp = devm_kzalloc(dev, struct_size(clp, clk_data.hws, clks_num), + GFP_KERNEL); + if (!clp) + return -ENOMEM; + + clp->base = devm_platform_ioremap_resource(pdev, 0); + if (IS_ERR(clp->base)) + return PTR_ERR(clp->base); + + spin_lock_init(&clp->clk_lock); + clp->clk_data.num = clks_num + 1; + clp->dev = dev; + + for (i = 0; i < clks_num; i++) { + p = &data[i]; + switch (p->type) { + case CLK_TYPE_PLL: + hw = loongson2_clk_register(clp, p, + &loongson2_pll_recalc_ops); + break; + case CLK_TYPE_SCALE: + hw = loongson2_clk_register(clp, p, + &loongson2_freqscale_recalc_ops); + break; + case CLK_TYPE_DIVIDER: + hw = devm_clk_hw_register_divider(dev, p->name, + p->parent_name, 0, + clp->base + p->reg_offset, + p->div_shift, p->div_width, + CLK_DIVIDER_ONE_BASED, + &clp->clk_lock); + break; + default: + return dev_err_probe(dev, -EINVAL, "Invalid clk type\n"); + } + + if (IS_ERR(hw)) + return dev_err_probe(dev, PTR_ERR(hw), + "Register clk: %s, type: %u failed!\n", + p->name, p->type); + + clp->clk_data.hws[p->id] = hw; + } + + return devm_of_clk_add_hw_provider(dev, of_clk_hw_onecell_get, &clp->clk_data); } static const struct of_device_id loongson2_clk_match_table[] = { - { .compatible = "loongson,ls2k-clk" }, + { .compatible = "loongson,ls2k-clk", .data = &ls2k1000_clks }, { } }; MODULE_DEVICE_TABLE(of, loongson2_clk_match_table); @@ -338,4 +275,5 @@ static struct platform_driver loongson2_clk_driver = { module_platform_driver(loongson2_clk_driver); MODULE_DESCRIPTION("Loongson2 clock driver"); +MODULE_AUTHOR("Loongson Technology Corporation Limited"); MODULE_LICENSE("GPL"); From 5aa9d3a79bc66f2cc9ef9e89ffe7f37a96d47ce8 Mon Sep 17 00:00:00 2001 From: Binbin Zhou Date: Thu, 11 Apr 2024 10:58:08 +0800 Subject: [PATCH 036/118] dt-bindings: clock: loongson2: Add Loongson-2K0500 compatible Add the devicetree compatible for Loongson-2K0500 clocks. Signed-off-by: Binbin Zhou Acked-by: Conor Dooley Link: https://lore.kernel.org/r/c4784102d2bb8bf6982799babe39d5827235461d.1712731524.git.zhoubinbin@loongson.cn Acked-by: Huacai Chen Signed-off-by: Stephen Boyd --- Documentation/devicetree/bindings/clock/loongson,ls2k-clk.yaml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Documentation/devicetree/bindings/clock/loongson,ls2k-clk.yaml b/Documentation/devicetree/bindings/clock/loongson,ls2k-clk.yaml index 63a59015987e..83baee40e200 100644 --- a/Documentation/devicetree/bindings/clock/loongson,ls2k-clk.yaml +++ b/Documentation/devicetree/bindings/clock/loongson,ls2k-clk.yaml @@ -16,7 +16,8 @@ description: | properties: compatible: enum: - - loongson,ls2k-clk + - loongson,ls2k0500-clk + - loongson,ls2k-clk # This is for Loongson-2K1000 reg: maxItems: 1 From 85d4daa59555182f9c8b9f5fe951049a6d0aed0f Mon Sep 17 00:00:00 2001 From: Binbin Zhou Date: Thu, 11 Apr 2024 10:58:31 +0800 Subject: [PATCH 037/118] clk: clk-loongson2: Add Loongson-2K0500 clock support The Loongson-2K0500 and Loongson-2K1000 clock is similar, we add its support by different configurations. Signed-off-by: Binbin Zhou Link: https://lore.kernel.org/r/f767a1783dc590fcd31ff7d4459df2cf80196de1.1712731524.git.zhoubinbin@loongson.cn Acked-by: Huacai Chen Signed-off-by: Stephen Boyd --- drivers/clk/clk-loongson2.c | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/drivers/clk/clk-loongson2.c b/drivers/clk/clk-loongson2.c index 749cf66aef2d..190c24b88a8c 100644 --- a/drivers/clk/clk-loongson2.c +++ b/drivers/clk/clk-loongson2.c @@ -89,6 +89,27 @@ struct loongson2_clk_board_info { .div_width = _dwidth, \ } +static const struct loongson2_clk_board_info ls2k0500_clks[] = { + CLK_PLL(LOONGSON2_NODE_PLL, "pll_node", 0, 16, 8, 8, 6), + CLK_PLL(LOONGSON2_DDR_PLL, "pll_ddr", 0x8, 16, 8, 8, 6), + CLK_PLL(LOONGSON2_DC_PLL, "pll_soc", 0x10, 16, 8, 8, 6), + CLK_PLL(LOONGSON2_PIX0_PLL, "pll_pix0", 0x18, 16, 8, 8, 6), + CLK_PLL(LOONGSON2_PIX1_PLL, "pll_pix1", 0x20, 16, 8, 8, 6), + CLK_DIV(LOONGSON2_NODE_CLK, "clk_node", "pll_node", 0, 24, 6), + CLK_DIV(LOONGSON2_DDR_CLK, "clk_ddr", "pll_ddr", 0x8, 24, 6), + CLK_DIV(LOONGSON2_HDA_CLK, "clk_hda", "pll_ddr", 0xc, 8, 6), + CLK_DIV(LOONGSON2_GPU_CLK, "clk_gpu", "pll_soc", 0x10, 24, 6), + CLK_DIV(LOONGSON2_DC_CLK, "clk_sb", "pll_soc", 0x14, 0, 6), + CLK_DIV(LOONGSON2_GMAC_CLK, "clk_gmac", "pll_soc", 0x14, 8, 6), + CLK_DIV(LOONGSON2_PIX0_CLK, "clk_pix0", "pll_pix0", 0x18, 24, 6), + CLK_DIV(LOONGSON2_PIX1_CLK, "clk_pix1", "pll_pix1", 0x20, 24, 6), + CLK_SCALE(LOONGSON2_BOOT_CLK, "clk_boot", "clk_sb", 0x28, 8, 3), + CLK_SCALE(LOONGSON2_SATA_CLK, "clk_sata", "clk_sb", 0x28, 12, 3), + CLK_SCALE(LOONGSON2_USB_CLK, "clk_usb", "clk_sb", 0x28, 16, 3), + CLK_SCALE(LOONGSON2_APB_CLK, "clk_apb", "clk_sb", 0x28, 20, 3), + { /* Sentinel */ }, +}; + static const struct loongson2_clk_board_info ls2k1000_clks[] = { CLK_PLL(LOONGSON2_NODE_PLL, "pll_node", 0, 32, 10, 26, 6), CLK_PLL(LOONGSON2_DDR_PLL, "pll_ddr", 0x10, 32, 10, 26, 6), @@ -260,6 +281,7 @@ static int loongson2_clk_probe(struct platform_device *pdev) } static const struct of_device_id loongson2_clk_match_table[] = { + { .compatible = "loongson,ls2k0500-clk", .data = &ls2k0500_clks }, { .compatible = "loongson,ls2k-clk", .data = &ls2k1000_clks }, { } }; From 267325629ee3f04b519c4070a0ac65e86354d94f Mon Sep 17 00:00:00 2001 From: Binbin Zhou Date: Thu, 11 Apr 2024 10:58:32 +0800 Subject: [PATCH 038/118] dt-bindings: clock: loongson2: Add Loongson-2K2000 compatible Add the devicetree compatible for Loongson-2K2000 clocks. Signed-off-by: Binbin Zhou Acked-by: Conor Dooley Link: https://lore.kernel.org/r/4820325406aec322ae7c062e2b03437d0c95e820.1712731524.git.zhoubinbin@loongson.cn Acked-by: Huacai Chen Signed-off-by: Stephen Boyd --- Documentation/devicetree/bindings/clock/loongson,ls2k-clk.yaml | 1 + 1 file changed, 1 insertion(+) diff --git a/Documentation/devicetree/bindings/clock/loongson,ls2k-clk.yaml b/Documentation/devicetree/bindings/clock/loongson,ls2k-clk.yaml index 83baee40e200..4f79cdb417ab 100644 --- a/Documentation/devicetree/bindings/clock/loongson,ls2k-clk.yaml +++ b/Documentation/devicetree/bindings/clock/loongson,ls2k-clk.yaml @@ -18,6 +18,7 @@ properties: enum: - loongson,ls2k0500-clk - loongson,ls2k-clk # This is for Loongson-2K1000 + - loongson,ls2k2000-clk reg: maxItems: 1 From 4f149dd4786afd5e5a023e96fb988e4f8b44e8ed Mon Sep 17 00:00:00 2001 From: Binbin Zhou Date: Thu, 11 Apr 2024 10:58:33 +0800 Subject: [PATCH 039/118] clk: clk-loongson2: Add Loongson-2K2000 clock support The Loongson-2K2000 and Loongson-2K1000 clock is similar, we add its support by different configurations. Signed-off-by: Binbin Zhou Link: https://lore.kernel.org/r/8b0b5851783acf8ebe13b50391d15b58cc181613.1712731524.git.zhoubinbin@loongson.cn Acked-by: Huacai Chen Signed-off-by: Stephen Boyd --- drivers/clk/clk-loongson2.c | 72 +++++++++++++++++++++++++++++++++++++ 1 file changed, 72 insertions(+) diff --git a/drivers/clk/clk-loongson2.c b/drivers/clk/clk-loongson2.c index 190c24b88a8c..820bb1e9e3b7 100644 --- a/drivers/clk/clk-loongson2.c +++ b/drivers/clk/clk-loongson2.c @@ -21,6 +21,8 @@ enum loongson2_clk_type { CLK_TYPE_PLL, CLK_TYPE_SCALE, CLK_TYPE_DIVIDER, + CLK_TYPE_GATE, + CLK_TYPE_FIXED, CLK_TYPE_NONE, }; @@ -45,11 +47,13 @@ struct loongson2_clk_board_info { enum loongson2_clk_type type; const char *name; const char *parent_name; + unsigned long fixed_rate; u8 reg_offset; u8 div_shift; u8 div_width; u8 mult_shift; u8 mult_width; + u8 bit_idx; }; #define CLK_DIV(_id, _name, _pname, _offset, _dshift, _dwidth) \ @@ -89,6 +93,25 @@ struct loongson2_clk_board_info { .div_width = _dwidth, \ } +#define CLK_GATE(_id, _name, _pname, _offset, _bidx) \ + { \ + .id = _id, \ + .type = CLK_TYPE_GATE, \ + .name = _name, \ + .parent_name = _pname, \ + .reg_offset = _offset, \ + .bit_idx = _bidx, \ + } + +#define CLK_FIXED(_id, _name, _pname, _rate) \ + { \ + .id = _id, \ + .type = CLK_TYPE_FIXED, \ + .name = _name, \ + .parent_name = _pname, \ + .fixed_rate = _rate, \ + } + static const struct loongson2_clk_board_info ls2k0500_clks[] = { CLK_PLL(LOONGSON2_NODE_PLL, "pll_node", 0, 16, 8, 8, 6), CLK_PLL(LOONGSON2_DDR_PLL, "pll_ddr", 0x8, 16, 8, 8, 6), @@ -137,6 +160,44 @@ static const struct loongson2_clk_board_info ls2k1000_clks[] = { { /* Sentinel */ }, }; +static const struct loongson2_clk_board_info ls2k2000_clks[] = { + CLK_PLL(LOONGSON2_DC_PLL, "pll_0", 0, 21, 9, 32, 6), + CLK_PLL(LOONGSON2_DDR_PLL, "pll_1", 0x10, 21, 9, 32, 6), + CLK_PLL(LOONGSON2_NODE_PLL, "pll_2", 0x20, 21, 9, 32, 6), + CLK_PLL(LOONGSON2_PIX0_PLL, "pll_pix0", 0x30, 21, 9, 32, 6), + CLK_PLL(LOONGSON2_PIX1_PLL, "pll_pix1", 0x40, 21, 9, 32, 6), + CLK_GATE(LOONGSON2_OUT0_GATE, "out0_gate", "pll_0", 0, 40), + CLK_GATE(LOONGSON2_GMAC_GATE, "gmac_gate", "pll_0", 0, 41), + CLK_GATE(LOONGSON2_RIO_GATE, "rio_gate", "pll_0", 0, 42), + CLK_GATE(LOONGSON2_DC_GATE, "dc_gate", "pll_1", 0x10, 40), + CLK_GATE(LOONGSON2_DDR_GATE, "ddr_gate", "pll_1", 0x10, 41), + CLK_GATE(LOONGSON2_GPU_GATE, "gpu_gate", "pll_1", 0x10, 42), + CLK_GATE(LOONGSON2_HDA_GATE, "hda_gate", "pll_2", 0x20, 40), + CLK_GATE(LOONGSON2_NODE_GATE, "node_gate", "pll_2", 0x20, 41), + CLK_GATE(LOONGSON2_EMMC_GATE, "emmc_gate", "pll_2", 0x20, 42), + CLK_GATE(LOONGSON2_PIX0_GATE, "pix0_gate", "pll_pix0", 0x30, 40), + CLK_GATE(LOONGSON2_PIX1_GATE, "pix1_gate", "pll_pix1", 0x40, 40), + CLK_DIV(LOONGSON2_OUT0_CLK, "clk_out0", "out0_gate", 0, 0, 6), + CLK_DIV(LOONGSON2_GMAC_CLK, "clk_gmac", "gmac_gate", 0, 7, 6), + CLK_DIV(LOONGSON2_RIO_CLK, "clk_rio", "rio_gate", 0, 14, 6), + CLK_DIV(LOONGSON2_DC_CLK, "clk_dc", "dc_gate", 0x10, 0, 6), + CLK_DIV(LOONGSON2_GPU_CLK, "clk_gpu", "gpu_gate", 0x10, 7, 6), + CLK_DIV(LOONGSON2_DDR_CLK, "clk_ddr", "ddr_gate", 0x10, 14, 6), + CLK_DIV(LOONGSON2_HDA_CLK, "clk_hda", "hda_gate", 0x20, 0, 6), + CLK_DIV(LOONGSON2_NODE_CLK, "clk_node", "node_gate", 0x20, 7, 6), + CLK_DIV(LOONGSON2_EMMC_CLK, "clk_emmc", "emmc_gate", 0x20, 14, 6), + CLK_DIV(LOONGSON2_PIX0_CLK, "clk_pix0", "pll_pix0", 0x30, 0, 6), + CLK_DIV(LOONGSON2_PIX1_CLK, "clk_pix1", "pll_pix1", 0x40, 0, 6), + CLK_SCALE(LOONGSON2_SATA_CLK, "clk_sata", "clk_out0", 0x50, 12, 3), + CLK_SCALE(LOONGSON2_USB_CLK, "clk_usb", "clk_out0", 0x50, 16, 3), + CLK_SCALE(LOONGSON2_APB_CLK, "clk_apb", "clk_node", 0x50, 20, 3), + CLK_SCALE(LOONGSON2_BOOT_CLK, "clk_boot", NULL, 0x50, 23, 3), + CLK_SCALE(LOONGSON2_DES_CLK, "clk_des", "clk_node", 0x50, 40, 3), + CLK_SCALE(LOONGSON2_I2S_CLK, "clk_i2s", "clk_node", 0x50, 44, 3), + CLK_FIXED(LOONGSON2_MISC_CLK, "clk_misc", NULL, 50000000), + { /* Sentinel */ }, +}; + static inline struct loongson2_clk_data *to_loongson2_clk(struct clk_hw *hw) { return container_of(hw, struct loongson2_clk_data, hw); @@ -265,6 +326,16 @@ static int loongson2_clk_probe(struct platform_device *pdev) CLK_DIVIDER_ONE_BASED, &clp->clk_lock); break; + case CLK_TYPE_GATE: + hw = devm_clk_hw_register_gate(dev, p->name, p->parent_name, 0, + clp->base + p->reg_offset, + p->bit_idx, 0, + &clp->clk_lock); + break; + case CLK_TYPE_FIXED: + hw = clk_hw_register_fixed_rate_parent_data(dev, p->name, pdata, + 0, p->fixed_rate); + break; default: return dev_err_probe(dev, -EINVAL, "Invalid clk type\n"); } @@ -283,6 +354,7 @@ static int loongson2_clk_probe(struct platform_device *pdev) static const struct of_device_id loongson2_clk_match_table[] = { { .compatible = "loongson,ls2k0500-clk", .data = &ls2k0500_clks }, { .compatible = "loongson,ls2k-clk", .data = &ls2k1000_clks }, + { .compatible = "loongson,ls2k2000-clk", .data = &ls2k2000_clks }, { } }; MODULE_DEVICE_TABLE(of, loongson2_clk_match_table); From a12069a39b33c3b4c57929f5b42c88da681496ba Mon Sep 17 00:00:00 2001 From: Inochi Amaoto Date: Fri, 12 Apr 2024 07:24:38 +0800 Subject: [PATCH 040/118] clk: sophgo: Make synthesizer struct static Let all synthesizer structs are static to make the compiler happy. Fixes: 80fd61ec4612 ("clk: sophgo: Add clock support for CV1800 SoC") Signed-off-by: Inochi Amaoto Link: https://lore.kernel.org/r/IA1PR20MB49531E437735A71A163694AEBB052@IA1PR20MB4953.namprd20.prod.outlook.com Reported-by: kernel test robot Closes: https://lore.kernel.org/oe-kbuild-all/202404120548.y9dZIi0e-lkp@intel.com/ Signed-off-by: Stephen Boyd --- drivers/clk/sophgo/clk-cv1800.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/drivers/clk/sophgo/clk-cv1800.c b/drivers/clk/sophgo/clk-cv1800.c index 956de5b21a80..2da4c24621cf 100644 --- a/drivers/clk/sophgo/clk-cv1800.c +++ b/drivers/clk/sophgo/clk-cv1800.c @@ -79,7 +79,7 @@ static const struct clk_parent_data clk_bypass_fpll_parents[] = { { .hw = &clk_fpll.common.hw }, }; -struct cv1800_clk_pll_synthesizer clk_mpll_synthesizer = { +static struct cv1800_clk_pll_synthesizer clk_mpll_synthesizer = { .en = CV1800_CLK_BIT(REG_PLL_G6_SSC_SYN_CTRL, 2), .clk_half = CV1800_CLK_BIT(REG_PLL_G6_SSC_SYN_CTRL, 0), .ctrl = REG_MPLL_SSC_SYN_CTRL, @@ -93,7 +93,7 @@ static CV1800_FACTIONAL_PLL(clk_mpll, clk_bypass_mipimpll_parents, &clk_mpll_synthesizer, CLK_IS_CRITICAL); -struct cv1800_clk_pll_synthesizer clk_tpll_synthesizer = { +static struct cv1800_clk_pll_synthesizer clk_tpll_synthesizer = { .en = CV1800_CLK_BIT(REG_PLL_G6_SSC_SYN_CTRL, 3), .clk_half = CV1800_CLK_BIT(REG_PLL_G6_SSC_SYN_CTRL, 0), .ctrl = REG_TPLL_SSC_SYN_CTRL, @@ -107,7 +107,7 @@ static CV1800_FACTIONAL_PLL(clk_tpll, clk_bypass_mipimpll_parents, &clk_tpll_synthesizer, CLK_IS_CRITICAL); -struct cv1800_clk_pll_synthesizer clk_a0pll_synthesizer = { +static struct cv1800_clk_pll_synthesizer clk_a0pll_synthesizer = { .en = CV1800_CLK_BIT(REG_PLL_G2_SSC_SYN_CTRL, 2), .clk_half = CV1800_CLK_BIT(REG_PLL_G2_SSC_SYN_CTRL, 0), .ctrl = REG_A0PLL_SSC_SYN_CTRL, @@ -121,7 +121,7 @@ static CV1800_FACTIONAL_PLL(clk_a0pll, clk_bypass_mipimpll_parents, &clk_a0pll_synthesizer, CLK_IS_CRITICAL); -struct cv1800_clk_pll_synthesizer clk_disppll_synthesizer = { +static struct cv1800_clk_pll_synthesizer clk_disppll_synthesizer = { .en = CV1800_CLK_BIT(REG_PLL_G2_SSC_SYN_CTRL, 3), .clk_half = CV1800_CLK_BIT(REG_PLL_G2_SSC_SYN_CTRL, 0), .ctrl = REG_DISPPLL_SSC_SYN_CTRL, @@ -135,7 +135,7 @@ static CV1800_FACTIONAL_PLL(clk_disppll, clk_bypass_mipimpll_parents, &clk_disppll_synthesizer, CLK_IS_CRITICAL); -struct cv1800_clk_pll_synthesizer clk_cam0pll_synthesizer = { +static struct cv1800_clk_pll_synthesizer clk_cam0pll_synthesizer = { .en = CV1800_CLK_BIT(REG_PLL_G2_SSC_SYN_CTRL, 4), .clk_half = CV1800_CLK_BIT(REG_PLL_G2_SSC_SYN_CTRL, 0), .ctrl = REG_CAM0PLL_SSC_SYN_CTRL, @@ -149,7 +149,7 @@ static CV1800_FACTIONAL_PLL(clk_cam0pll, clk_bypass_mipimpll_parents, &clk_cam0pll_synthesizer, CLK_IGNORE_UNUSED); -struct cv1800_clk_pll_synthesizer clk_cam1pll_synthesizer = { +static struct cv1800_clk_pll_synthesizer clk_cam1pll_synthesizer = { .en = CV1800_CLK_BIT(REG_PLL_G2_SSC_SYN_CTRL, 5), .clk_half = CV1800_CLK_BIT(REG_PLL_G2_SSC_SYN_CTRL, 0), .ctrl = REG_CAM1PLL_SSC_SYN_CTRL, From 239d5fb3ba79b1c2aa257569e55739a07c161c37 Mon Sep 17 00:00:00 2001 From: Gabriel Fernandez Date: Thu, 11 Apr 2024 11:24:50 +0200 Subject: [PATCH 041/118] clk: stm32mp13: use platform device APIs Convert devm_platform_ioremap_resource() and remove unnecessary dependency check with SCMI clock driver. Signed-off-by: Gabriel Fernandez Link: https://lore.kernel.org/r/20240411092453.243633-2-gabriel.fernandez@foss.st.com Signed-off-by: Stephen Boyd --- drivers/clk/stm32/clk-stm32-core.c | 11 +++-- drivers/clk/stm32/clk-stm32mp13.c | 72 +++--------------------------- 2 files changed, 10 insertions(+), 73 deletions(-) diff --git a/drivers/clk/stm32/clk-stm32-core.c b/drivers/clk/stm32/clk-stm32-core.c index 58705fcad334..1721a3ed7386 100644 --- a/drivers/clk/stm32/clk-stm32-core.c +++ b/drivers/clk/stm32/clk-stm32-core.c @@ -25,7 +25,6 @@ static int stm32_rcc_clock_init(struct device *dev, { const struct stm32_rcc_match_data *data = match->data; struct clk_hw_onecell_data *clk_data = data->hw_clks; - struct device_node *np = dev_of_node(dev); struct clk_hw **hws; int n, max_binding; @@ -64,7 +63,7 @@ static int stm32_rcc_clock_init(struct device *dev, hws[cfg_clock->id] = hw; } - return of_clk_add_hw_provider(np, of_clk_hw_onecell_get, clk_data); + return devm_of_clk_add_hw_provider(dev, of_clk_hw_onecell_get, clk_data); } int stm32_rcc_init(struct device *dev, const struct of_device_id *match_data, @@ -638,7 +637,7 @@ struct clk_hw *clk_stm32_mux_register(struct device *dev, mux->lock = lock; mux->clock_data = data->clock_data; - err = clk_hw_register(dev, hw); + err = devm_clk_hw_register(dev, hw); if (err) return ERR_PTR(err); @@ -659,7 +658,7 @@ struct clk_hw *clk_stm32_gate_register(struct device *dev, gate->lock = lock; gate->clock_data = data->clock_data; - err = clk_hw_register(dev, hw); + err = devm_clk_hw_register(dev, hw); if (err) return ERR_PTR(err); @@ -680,7 +679,7 @@ struct clk_hw *clk_stm32_div_register(struct device *dev, div->lock = lock; div->clock_data = data->clock_data; - err = clk_hw_register(dev, hw); + err = devm_clk_hw_register(dev, hw); if (err) return ERR_PTR(err); @@ -701,7 +700,7 @@ struct clk_hw *clk_stm32_composite_register(struct device *dev, composite->lock = lock; composite->clock_data = data->clock_data; - err = clk_hw_register(dev, hw); + err = devm_clk_hw_register(dev, hw); if (err) return ERR_PTR(err); diff --git a/drivers/clk/stm32/clk-stm32mp13.c b/drivers/clk/stm32/clk-stm32mp13.c index d4ecb3c34a1b..bf81d7491708 100644 --- a/drivers/clk/stm32/clk-stm32mp13.c +++ b/drivers/clk/stm32/clk-stm32mp13.c @@ -1536,77 +1536,16 @@ static const struct of_device_id stm32mp13_match_data[] = { }; MODULE_DEVICE_TABLE(of, stm32mp13_match_data); -static int stm32mp1_rcc_init(struct device *dev) -{ - void __iomem *rcc_base; - int ret = -ENOMEM; - - rcc_base = of_iomap(dev_of_node(dev), 0); - if (!rcc_base) { - dev_err(dev, "%pOFn: unable to map resource", dev_of_node(dev)); - goto out; - } - - ret = stm32_rcc_init(dev, stm32mp13_match_data, rcc_base); -out: - if (ret) { - if (rcc_base) - iounmap(rcc_base); - - of_node_put(dev_of_node(dev)); - } - - return ret; -} - -static int get_clock_deps(struct device *dev) -{ - static const char * const clock_deps_name[] = { - "hsi", "hse", "csi", "lsi", "lse", - }; - size_t deps_size = sizeof(struct clk *) * ARRAY_SIZE(clock_deps_name); - struct clk **clk_deps; - int i; - - clk_deps = devm_kzalloc(dev, deps_size, GFP_KERNEL); - if (!clk_deps) - return -ENOMEM; - - for (i = 0; i < ARRAY_SIZE(clock_deps_name); i++) { - struct clk *clk = of_clk_get_by_name(dev_of_node(dev), - clock_deps_name[i]); - - if (IS_ERR(clk)) { - if (PTR_ERR(clk) != -EINVAL && PTR_ERR(clk) != -ENOENT) - return PTR_ERR(clk); - } else { - /* Device gets a reference count on the clock */ - clk_deps[i] = devm_clk_get(dev, __clk_get_name(clk)); - clk_put(clk); - } - } - - return 0; -} - static int stm32mp1_rcc_clocks_probe(struct platform_device *pdev) { struct device *dev = &pdev->dev; - int ret = get_clock_deps(dev); + void __iomem *base; - if (!ret) - ret = stm32mp1_rcc_init(dev); + base = devm_platform_ioremap_resource(pdev, 0); + if (WARN_ON(IS_ERR(base))) + return PTR_ERR(base); - return ret; -} - -static void stm32mp1_rcc_clocks_remove(struct platform_device *pdev) -{ - struct device *dev = &pdev->dev; - struct device_node *child, *np = dev_of_node(dev); - - for_each_available_child_of_node(np, child) - of_clk_del_provider(child); + return stm32_rcc_init(dev, stm32mp13_match_data, base); } static struct platform_driver stm32mp13_rcc_clocks_driver = { @@ -1615,7 +1554,6 @@ static struct platform_driver stm32mp13_rcc_clocks_driver = { .of_match_table = stm32mp13_match_data, }, .probe = stm32mp1_rcc_clocks_probe, - .remove_new = stm32mp1_rcc_clocks_remove, }; static int __init stm32mp13_clocks_init(void) From df5df1257c9f2af6621976f1e18a088182230d06 Mon Sep 17 00:00:00 2001 From: Gabriel Fernandez Date: Thu, 11 Apr 2024 11:24:51 +0200 Subject: [PATCH 042/118] dt-bindings: clocks: stm32mp25: add description of all parents RCC driver uses '.index' to define all parent clocks instead '.names' because the use of a name to define a parent clock is discouraged. This is an ABI change, but the RCC driver has not yet merged, unlike all others drivers besides Linux. Fixes: b5be49db3d47 ("dt-bindings: stm32: add clocks and reset binding for stm32mp25 platform") Signed-off-by: Gabriel Fernandez Acked-by: Krzysztof Kozlowski Link: https://lore.kernel.org/r/20240411092453.243633-3-gabriel.fernandez@foss.st.com Signed-off-by: Stephen Boyd --- .../bindings/clock/st,stm32mp25-rcc.yaml | 170 ++++++++++++++++-- include/dt-bindings/reset/st,stm32mp25-rcc.h | 2 +- 2 files changed, 156 insertions(+), 16 deletions(-) diff --git a/Documentation/devicetree/bindings/clock/st,stm32mp25-rcc.yaml b/Documentation/devicetree/bindings/clock/st,stm32mp25-rcc.yaml index 7732e79a42b9..0929fa7e271b 100644 --- a/Documentation/devicetree/bindings/clock/st,stm32mp25-rcc.yaml +++ b/Documentation/devicetree/bindings/clock/st,stm32mp25-rcc.yaml @@ -38,14 +38,81 @@ properties: - description: CK_SCMI_MSI Low Power Internal oscillator (~ 4 MHz or ~ 16 MHz) - description: CK_SCMI_LSE Low Speed External oscillator (32 KHz) - description: CK_SCMI_LSI Low Speed Internal oscillator (~ 32 KHz) - - clock-names: - items: - - const: hse - - const: hsi - - const: msi - - const: lse - - const: lsi + - description: CK_SCMI_HSE_DIV2 CK_SCMI_HSE divided by 2 (coud be gated) + - description: CK_SCMI_ICN_HS_MCU High Speed interconnect bus clock + - description: CK_SCMI_ICN_LS_MCU Low Speed interconnect bus clock + - description: CK_SCMI_ICN_SDMMC SDMMC interconnect bus clock + - description: CK_SCMI_ICN_DDR DDR interconnect bus clock + - description: CK_SCMI_ICN_DISPLAY Display interconnect bus clock + - description: CK_SCMI_ICN_HSL HSL interconnect bus clock + - description: CK_SCMI_ICN_NIC NIC interconnect bus clock + - description: CK_SCMI_ICN_VID Video interconnect bus clock + - description: CK_SCMI_FLEXGEN_07 flexgen clock 7 + - description: CK_SCMI_FLEXGEN_08 flexgen clock 8 + - description: CK_SCMI_FLEXGEN_09 flexgen clock 9 + - description: CK_SCMI_FLEXGEN_10 flexgen clock 10 + - description: CK_SCMI_FLEXGEN_11 flexgen clock 11 + - description: CK_SCMI_FLEXGEN_12 flexgen clock 12 + - description: CK_SCMI_FLEXGEN_13 flexgen clock 13 + - description: CK_SCMI_FLEXGEN_14 flexgen clock 14 + - description: CK_SCMI_FLEXGEN_15 flexgen clock 15 + - description: CK_SCMI_FLEXGEN_16 flexgen clock 16 + - description: CK_SCMI_FLEXGEN_17 flexgen clock 17 + - description: CK_SCMI_FLEXGEN_18 flexgen clock 18 + - description: CK_SCMI_FLEXGEN_19 flexgen clock 19 + - description: CK_SCMI_FLEXGEN_20 flexgen clock 20 + - description: CK_SCMI_FLEXGEN_21 flexgen clock 21 + - description: CK_SCMI_FLEXGEN_22 flexgen clock 22 + - description: CK_SCMI_FLEXGEN_23 flexgen clock 23 + - description: CK_SCMI_FLEXGEN_24 flexgen clock 24 + - description: CK_SCMI_FLEXGEN_25 flexgen clock 25 + - description: CK_SCMI_FLEXGEN_26 flexgen clock 26 + - description: CK_SCMI_FLEXGEN_27 flexgen clock 27 + - description: CK_SCMI_FLEXGEN_28 flexgen clock 28 + - description: CK_SCMI_FLEXGEN_29 flexgen clock 29 + - description: CK_SCMI_FLEXGEN_30 flexgen clock 30 + - description: CK_SCMI_FLEXGEN_31 flexgen clock 31 + - description: CK_SCMI_FLEXGEN_32 flexgen clock 32 + - description: CK_SCMI_FLEXGEN_33 flexgen clock 33 + - description: CK_SCMI_FLEXGEN_34 flexgen clock 34 + - description: CK_SCMI_FLEXGEN_35 flexgen clock 35 + - description: CK_SCMI_FLEXGEN_36 flexgen clock 36 + - description: CK_SCMI_FLEXGEN_37 flexgen clock 37 + - description: CK_SCMI_FLEXGEN_38 flexgen clock 38 + - description: CK_SCMI_FLEXGEN_39 flexgen clock 39 + - description: CK_SCMI_FLEXGEN_40 flexgen clock 40 + - description: CK_SCMI_FLEXGEN_41 flexgen clock 41 + - description: CK_SCMI_FLEXGEN_42 flexgen clock 42 + - description: CK_SCMI_FLEXGEN_43 flexgen clock 43 + - description: CK_SCMI_FLEXGEN_44 flexgen clock 44 + - description: CK_SCMI_FLEXGEN_45 flexgen clock 45 + - description: CK_SCMI_FLEXGEN_46 flexgen clock 46 + - description: CK_SCMI_FLEXGEN_47 flexgen clock 47 + - description: CK_SCMI_FLEXGEN_48 flexgen clock 48 + - description: CK_SCMI_FLEXGEN_49 flexgen clock 49 + - description: CK_SCMI_FLEXGEN_50 flexgen clock 50 + - description: CK_SCMI_FLEXGEN_51 flexgen clock 51 + - description: CK_SCMI_FLEXGEN_52 flexgen clock 52 + - description: CK_SCMI_FLEXGEN_53 flexgen clock 53 + - description: CK_SCMI_FLEXGEN_54 flexgen clock 54 + - description: CK_SCMI_FLEXGEN_55 flexgen clock 55 + - description: CK_SCMI_FLEXGEN_56 flexgen clock 56 + - description: CK_SCMI_FLEXGEN_57 flexgen clock 57 + - description: CK_SCMI_FLEXGEN_58 flexgen clock 58 + - description: CK_SCMI_FLEXGEN_59 flexgen clock 59 + - description: CK_SCMI_FLEXGEN_60 flexgen clock 60 + - description: CK_SCMI_FLEXGEN_61 flexgen clock 61 + - description: CK_SCMI_FLEXGEN_62 flexgen clock 62 + - description: CK_SCMI_FLEXGEN_63 flexgen clock 63 + - description: CK_SCMI_ICN_APB1 Peripheral bridge 1 + - description: CK_SCMI_ICN_APB2 Peripheral bridge 2 + - description: CK_SCMI_ICN_APB3 Peripheral bridge 3 + - description: CK_SCMI_ICN_APB4 Peripheral bridge 4 + - description: CK_SCMI_ICN_APBDBG Peripheral bridge for degub + - description: CK_SCMI_TIMG1 Peripheral bridge for timer1 + - description: CK_SCMI_TIMG2 Peripheral bridge for timer2 + - description: CK_SCMI_PLL3 PLL3 clock + - description: clk_dsi_txbyte DSI byte clock required: - compatible @@ -53,7 +120,6 @@ required: - '#clock-cells' - '#reset-cells' - clocks - - clock-names additionalProperties: false @@ -66,11 +132,85 @@ examples: reg = <0x44200000 0x10000>; #clock-cells = <1>; #reset-cells = <1>; - clock-names = "hse", "hsi", "msi", "lse", "lsi"; - clocks = <&scmi_clk CK_SCMI_HSE>, - <&scmi_clk CK_SCMI_HSI>, - <&scmi_clk CK_SCMI_MSI>, - <&scmi_clk CK_SCMI_LSE>, - <&scmi_clk CK_SCMI_LSI>; + clocks = <&scmi_clk CK_SCMI_HSE>, + <&scmi_clk CK_SCMI_HSI>, + <&scmi_clk CK_SCMI_MSI>, + <&scmi_clk CK_SCMI_LSE>, + <&scmi_clk CK_SCMI_LSI>, + <&scmi_clk CK_SCMI_HSE_DIV2>, + <&scmi_clk CK_SCMI_ICN_HS_MCU>, + <&scmi_clk CK_SCMI_ICN_LS_MCU>, + <&scmi_clk CK_SCMI_ICN_SDMMC>, + <&scmi_clk CK_SCMI_ICN_DDR>, + <&scmi_clk CK_SCMI_ICN_DISPLAY>, + <&scmi_clk CK_SCMI_ICN_HSL>, + <&scmi_clk CK_SCMI_ICN_NIC>, + <&scmi_clk CK_SCMI_ICN_VID>, + <&scmi_clk CK_SCMI_FLEXGEN_07>, + <&scmi_clk CK_SCMI_FLEXGEN_08>, + <&scmi_clk CK_SCMI_FLEXGEN_09>, + <&scmi_clk CK_SCMI_FLEXGEN_10>, + <&scmi_clk CK_SCMI_FLEXGEN_11>, + <&scmi_clk CK_SCMI_FLEXGEN_12>, + <&scmi_clk CK_SCMI_FLEXGEN_13>, + <&scmi_clk CK_SCMI_FLEXGEN_14>, + <&scmi_clk CK_SCMI_FLEXGEN_15>, + <&scmi_clk CK_SCMI_FLEXGEN_16>, + <&scmi_clk CK_SCMI_FLEXGEN_17>, + <&scmi_clk CK_SCMI_FLEXGEN_18>, + <&scmi_clk CK_SCMI_FLEXGEN_19>, + <&scmi_clk CK_SCMI_FLEXGEN_20>, + <&scmi_clk CK_SCMI_FLEXGEN_21>, + <&scmi_clk CK_SCMI_FLEXGEN_22>, + <&scmi_clk CK_SCMI_FLEXGEN_23>, + <&scmi_clk CK_SCMI_FLEXGEN_24>, + <&scmi_clk CK_SCMI_FLEXGEN_25>, + <&scmi_clk CK_SCMI_FLEXGEN_26>, + <&scmi_clk CK_SCMI_FLEXGEN_27>, + <&scmi_clk CK_SCMI_FLEXGEN_28>, + <&scmi_clk CK_SCMI_FLEXGEN_29>, + <&scmi_clk CK_SCMI_FLEXGEN_30>, + <&scmi_clk CK_SCMI_FLEXGEN_31>, + <&scmi_clk CK_SCMI_FLEXGEN_32>, + <&scmi_clk CK_SCMI_FLEXGEN_33>, + <&scmi_clk CK_SCMI_FLEXGEN_34>, + <&scmi_clk CK_SCMI_FLEXGEN_35>, + <&scmi_clk CK_SCMI_FLEXGEN_36>, + <&scmi_clk CK_SCMI_FLEXGEN_37>, + <&scmi_clk CK_SCMI_FLEXGEN_38>, + <&scmi_clk CK_SCMI_FLEXGEN_39>, + <&scmi_clk CK_SCMI_FLEXGEN_40>, + <&scmi_clk CK_SCMI_FLEXGEN_41>, + <&scmi_clk CK_SCMI_FLEXGEN_42>, + <&scmi_clk CK_SCMI_FLEXGEN_43>, + <&scmi_clk CK_SCMI_FLEXGEN_44>, + <&scmi_clk CK_SCMI_FLEXGEN_45>, + <&scmi_clk CK_SCMI_FLEXGEN_46>, + <&scmi_clk CK_SCMI_FLEXGEN_47>, + <&scmi_clk CK_SCMI_FLEXGEN_48>, + <&scmi_clk CK_SCMI_FLEXGEN_49>, + <&scmi_clk CK_SCMI_FLEXGEN_50>, + <&scmi_clk CK_SCMI_FLEXGEN_51>, + <&scmi_clk CK_SCMI_FLEXGEN_52>, + <&scmi_clk CK_SCMI_FLEXGEN_53>, + <&scmi_clk CK_SCMI_FLEXGEN_54>, + <&scmi_clk CK_SCMI_FLEXGEN_55>, + <&scmi_clk CK_SCMI_FLEXGEN_56>, + <&scmi_clk CK_SCMI_FLEXGEN_57>, + <&scmi_clk CK_SCMI_FLEXGEN_58>, + <&scmi_clk CK_SCMI_FLEXGEN_59>, + <&scmi_clk CK_SCMI_FLEXGEN_60>, + <&scmi_clk CK_SCMI_FLEXGEN_61>, + <&scmi_clk CK_SCMI_FLEXGEN_62>, + <&scmi_clk CK_SCMI_FLEXGEN_63>, + <&scmi_clk CK_SCMI_ICN_APB1>, + <&scmi_clk CK_SCMI_ICN_APB2>, + <&scmi_clk CK_SCMI_ICN_APB3>, + <&scmi_clk CK_SCMI_ICN_APB4>, + <&scmi_clk CK_SCMI_ICN_APBDBG>, + <&scmi_clk CK_SCMI_TIMG1>, + <&scmi_clk CK_SCMI_TIMG2>, + <&scmi_clk CK_SCMI_PLL3>, + <&clk_dsi_txbyte>; }; ... diff --git a/include/dt-bindings/reset/st,stm32mp25-rcc.h b/include/dt-bindings/reset/st,stm32mp25-rcc.h index d5615930bcc8..748e78ae20bd 100644 --- a/include/dt-bindings/reset/st,stm32mp25-rcc.h +++ b/include/dt-bindings/reset/st,stm32mp25-rcc.h @@ -69,7 +69,7 @@ #define ADC3_R 59 #define ETH1_R 60 #define ETH2_R 61 -#define USB2_R 62 +#define USBH_R 62 #define USB2PHY1_R 63 #define USB2PHY2_R 64 #define USB3DR_R 65 From fd7a1c90ba4c6e618596eb44a69977801f9cccdd Mon Sep 17 00:00:00 2001 From: Gabriel Fernandez Date: Thu, 11 Apr 2024 11:24:52 +0200 Subject: [PATCH 043/118] clk: stm32: introduce clocks for STM32MP257 platform This driver is intended for the STM32MP25 clock family and utilizes the stm32-core API, similar to the stm32mp13 clock driver. Signed-off-by: Gabriel Fernandez Link: https://lore.kernel.org/r/20240411092453.243633-4-gabriel.fernandez@foss.st.com Signed-off-by: Stephen Boyd --- drivers/clk/stm32/Kconfig | 7 + drivers/clk/stm32/Makefile | 1 + drivers/clk/stm32/clk-stm32mp25.c | 1875 +++++++++++++++++++++++++++++ drivers/clk/stm32/reset-stm32.c | 59 +- drivers/clk/stm32/reset-stm32.h | 7 + drivers/clk/stm32/stm32mp25_rcc.h | 712 +++++++++++ 6 files changed, 2646 insertions(+), 15 deletions(-) create mode 100644 drivers/clk/stm32/clk-stm32mp25.c create mode 100644 drivers/clk/stm32/stm32mp25_rcc.h diff --git a/drivers/clk/stm32/Kconfig b/drivers/clk/stm32/Kconfig index 3c8493a94a11..dca409d52652 100644 --- a/drivers/clk/stm32/Kconfig +++ b/drivers/clk/stm32/Kconfig @@ -25,5 +25,12 @@ config COMMON_CLK_STM32MP157 help Support for stm32mp15x SoC family clocks. +config COMMON_CLK_STM32MP257 + bool "Clock driver for stm32mp25x clocks" + depends on ARM64 || COMPILE_TEST + default y + help + Support for stm32mp25x SoC family clocks. + endif diff --git a/drivers/clk/stm32/Makefile b/drivers/clk/stm32/Makefile index 5ced7fe3ddec..0a627164fcce 100644 --- a/drivers/clk/stm32/Makefile +++ b/drivers/clk/stm32/Makefile @@ -1,2 +1,3 @@ obj-$(CONFIG_COMMON_CLK_STM32MP135) += clk-stm32mp13.o clk-stm32-core.o reset-stm32.o obj-$(CONFIG_COMMON_CLK_STM32MP157) += clk-stm32mp1.o reset-stm32.o +obj-$(CONFIG_COMMON_CLK_STM32MP257) += clk-stm32mp25.o clk-stm32-core.o reset-stm32.o diff --git a/drivers/clk/stm32/clk-stm32mp25.c b/drivers/clk/stm32/clk-stm32mp25.c new file mode 100644 index 000000000000..210b75b39e50 --- /dev/null +++ b/drivers/clk/stm32/clk-stm32mp25.c @@ -0,0 +1,1875 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright (C) STMicroelectronics 2023 - All Rights Reserved + * Author: Gabriel Fernandez for STMicroelectronics. + */ + +#include +#include + +#include "clk-stm32-core.h" +#include "reset-stm32.h" +#include "stm32mp25_rcc.h" + +#include +#include + +enum { + HSE, + HSI, + MSI, + LSE, + LSI, + HSE_DIV2, + ICN_HS_MCU, + ICN_LS_MCU, + ICN_SDMMC, + ICN_DDR, + ICN_DISPLAY, + ICN_HSL, + ICN_NIC, + ICN_VID, + FLEXGEN_07, + FLEXGEN_08, + FLEXGEN_09, + FLEXGEN_10, + FLEXGEN_11, + FLEXGEN_12, + FLEXGEN_13, + FLEXGEN_14, + FLEXGEN_15, + FLEXGEN_16, + FLEXGEN_17, + FLEXGEN_18, + FLEXGEN_19, + FLEXGEN_20, + FLEXGEN_21, + FLEXGEN_22, + FLEXGEN_23, + FLEXGEN_24, + FLEXGEN_25, + FLEXGEN_26, + FLEXGEN_27, + FLEXGEN_28, + FLEXGEN_29, + FLEXGEN_30, + FLEXGEN_31, + FLEXGEN_32, + FLEXGEN_33, + FLEXGEN_34, + FLEXGEN_35, + FLEXGEN_36, + FLEXGEN_37, + FLEXGEN_38, + FLEXGEN_39, + FLEXGEN_40, + FLEXGEN_41, + FLEXGEN_42, + FLEXGEN_43, + FLEXGEN_44, + FLEXGEN_45, + FLEXGEN_46, + FLEXGEN_47, + FLEXGEN_48, + FLEXGEN_49, + FLEXGEN_50, + FLEXGEN_51, + FLEXGEN_52, + FLEXGEN_53, + FLEXGEN_54, + FLEXGEN_55, + FLEXGEN_56, + FLEXGEN_57, + FLEXGEN_58, + FLEXGEN_59, + FLEXGEN_60, + FLEXGEN_61, + FLEXGEN_62, + FLEXGEN_63, + ICN_APB1, + ICN_APB2, + ICN_APB3, + ICN_APB4, + ICN_APBDBG, + TIMG1, + TIMG2, + PLL3, + DSI_TXBYTE, +}; + +static const struct clk_parent_data adc12_src[] = { + { .index = FLEXGEN_46 }, + { .index = ICN_LS_MCU }, +}; + +static const struct clk_parent_data adc3_src[] = { + { .index = FLEXGEN_47 }, + { .index = ICN_LS_MCU }, + { .index = FLEXGEN_46 }, +}; + +static const struct clk_parent_data usb2phy1_src[] = { + { .index = FLEXGEN_57 }, + { .index = HSE_DIV2 }, +}; + +static const struct clk_parent_data usb2phy2_src[] = { + { .index = FLEXGEN_58 }, + { .index = HSE_DIV2 }, +}; + +static const struct clk_parent_data usb3pciphy_src[] = { + { .index = FLEXGEN_34 }, + { .index = HSE_DIV2 }, +}; + +static struct clk_stm32_gate ck_ker_ltdc; + +static const struct clk_parent_data dsiblane_src[] = { + { .index = DSI_TXBYTE }, + { .hw = &ck_ker_ltdc.hw }, +}; + +static const struct clk_parent_data dsiphy_src[] = { + { .index = FLEXGEN_28 }, + { .index = HSE }, +}; + +static const struct clk_parent_data lvdsphy_src[] = { + { .index = FLEXGEN_32 }, + { .index = HSE }, +}; + +static const struct clk_parent_data dts_src[] = { + { .index = HSI }, + { .index = HSE }, + { .index = MSI }, +}; + +static const struct clk_parent_data mco1_src[] = { + { .index = FLEXGEN_61 }, +}; + +static const struct clk_parent_data mco2_src[] = { + { .index = FLEXGEN_62 }, +}; + +enum enum_mux_cfg { + MUX_ADC12, + MUX_ADC3, + MUX_DSIBLANE, + MUX_DSIPHY, + MUX_DTS, + MUX_LVDSPHY, + MUX_MCO1, + MUX_MCO2, + MUX_USB2PHY1, + MUX_USB2PHY2, + MUX_USB3PCIEPHY, + MUX_NB +}; + +#define MUX_CFG(id, _offset, _shift, _witdh) \ + [id] = { \ + .offset = (_offset), \ + .shift = (_shift), \ + .width = (_witdh), \ + } + +static const struct stm32_mux_cfg stm32mp25_muxes[MUX_NB] = { + MUX_CFG(MUX_ADC12, RCC_ADC12CFGR, 12, 1), + MUX_CFG(MUX_ADC3, RCC_ADC3CFGR, 12, 2), + MUX_CFG(MUX_DSIBLANE, RCC_DSICFGR, 12, 1), + MUX_CFG(MUX_DSIPHY, RCC_DSICFGR, 15, 1), + MUX_CFG(MUX_DTS, RCC_DTSCFGR, 12, 2), + MUX_CFG(MUX_LVDSPHY, RCC_LVDSCFGR, 15, 1), + MUX_CFG(MUX_MCO1, RCC_MCO1CFGR, 0, 1), + MUX_CFG(MUX_MCO2, RCC_MCO2CFGR, 0, 1), + MUX_CFG(MUX_USB2PHY1, RCC_USB2PHY1CFGR, 15, 1), + MUX_CFG(MUX_USB2PHY2, RCC_USB2PHY2CFGR, 15, 1), + MUX_CFG(MUX_USB3PCIEPHY, RCC_USB3PCIEPHYCFGR, 15, 1), +}; + +enum enum_gate_cfg { + GATE_ADC12, + GATE_ADC3, + GATE_ADF1, + GATE_CCI, + GATE_CRC, + GATE_CRYP1, + GATE_CRYP2, + GATE_CSI, + GATE_DCMIPP, + GATE_DSI, + GATE_DTS, + GATE_ETH1, + GATE_ETH1MAC, + GATE_ETH1RX, + GATE_ETH1STP, + GATE_ETH1TX, + GATE_ETH2, + GATE_ETH2MAC, + GATE_ETH2RX, + GATE_ETH2STP, + GATE_ETH2TX, + GATE_ETHSW, + GATE_ETHSWACMCFG, + GATE_ETHSWACMMSG, + GATE_ETHSWMAC, + GATE_ETHSWREF, + GATE_FDCAN, + GATE_GPU, + GATE_HASH, + GATE_HDP, + GATE_I2C1, + GATE_I2C2, + GATE_I2C3, + GATE_I2C4, + GATE_I2C5, + GATE_I2C6, + GATE_I2C7, + GATE_I2C8, + GATE_I3C1, + GATE_I3C2, + GATE_I3C3, + GATE_I3C4, + GATE_IS2M, + GATE_IWDG1, + GATE_IWDG2, + GATE_IWDG3, + GATE_IWDG4, + GATE_IWDG5, + GATE_LPTIM1, + GATE_LPTIM2, + GATE_LPTIM3, + GATE_LPTIM4, + GATE_LPTIM5, + GATE_LPUART1, + GATE_LTDC, + GATE_LVDS, + GATE_MCO1, + GATE_MCO2, + GATE_MDF1, + GATE_OSPIIOM, + GATE_PCIE, + GATE_PKA, + GATE_RNG, + GATE_SAES, + GATE_SAI1, + GATE_SAI2, + GATE_SAI3, + GATE_SAI4, + GATE_SDMMC1, + GATE_SDMMC2, + GATE_SDMMC3, + GATE_SERC, + GATE_SPDIFRX, + GATE_SPI1, + GATE_SPI2, + GATE_SPI3, + GATE_SPI4, + GATE_SPI5, + GATE_SPI6, + GATE_SPI7, + GATE_SPI8, + GATE_TIM1, + GATE_TIM10, + GATE_TIM11, + GATE_TIM12, + GATE_TIM13, + GATE_TIM14, + GATE_TIM15, + GATE_TIM16, + GATE_TIM17, + GATE_TIM2, + GATE_TIM20, + GATE_TIM3, + GATE_TIM4, + GATE_TIM5, + GATE_TIM6, + GATE_TIM7, + GATE_TIM8, + GATE_UART4, + GATE_UART5, + GATE_UART7, + GATE_UART8, + GATE_UART9, + GATE_USART1, + GATE_USART2, + GATE_USART3, + GATE_USART6, + GATE_USBH, + GATE_USB2PHY1, + GATE_USB2PHY2, + GATE_USB3DR, + GATE_USB3PCIEPHY, + GATE_USBTC, + GATE_VDEC, + GATE_VENC, + GATE_VREF, + GATE_WWDG1, + GATE_WWDG2, + GATE_NB +}; + +#define GATE_CFG(id, _offset, _bit_idx, _offset_clr) \ + [id] = { \ + .offset = (_offset), \ + .bit_idx = (_bit_idx), \ + .set_clr = (_offset_clr), \ + } + +static const struct stm32_gate_cfg stm32mp25_gates[GATE_NB] = { + GATE_CFG(GATE_ADC12, RCC_ADC12CFGR, 1, 0), + GATE_CFG(GATE_ADC3, RCC_ADC3CFGR, 1, 0), + GATE_CFG(GATE_ADF1, RCC_ADF1CFGR, 1, 0), + GATE_CFG(GATE_CCI, RCC_CCICFGR, 1, 0), + GATE_CFG(GATE_CRC, RCC_CRCCFGR, 1, 0), + GATE_CFG(GATE_CRYP1, RCC_CRYP1CFGR, 1, 0), + GATE_CFG(GATE_CRYP2, RCC_CRYP2CFGR, 1, 0), + GATE_CFG(GATE_CSI, RCC_CSICFGR, 1, 0), + GATE_CFG(GATE_DCMIPP, RCC_DCMIPPCFGR, 1, 0), + GATE_CFG(GATE_DSI, RCC_DSICFGR, 1, 0), + GATE_CFG(GATE_DTS, RCC_DTSCFGR, 1, 0), + GATE_CFG(GATE_ETH1, RCC_ETH1CFGR, 5, 0), + GATE_CFG(GATE_ETH1MAC, RCC_ETH1CFGR, 1, 0), + GATE_CFG(GATE_ETH1RX, RCC_ETH1CFGR, 10, 0), + GATE_CFG(GATE_ETH1STP, RCC_ETH1CFGR, 4, 0), + GATE_CFG(GATE_ETH1TX, RCC_ETH1CFGR, 8, 0), + GATE_CFG(GATE_ETH2, RCC_ETH2CFGR, 5, 0), + GATE_CFG(GATE_ETH2MAC, RCC_ETH2CFGR, 1, 0), + GATE_CFG(GATE_ETH2RX, RCC_ETH2CFGR, 10, 0), + GATE_CFG(GATE_ETH2STP, RCC_ETH2CFGR, 4, 0), + GATE_CFG(GATE_ETH2TX, RCC_ETH2CFGR, 8, 0), + GATE_CFG(GATE_ETHSW, RCC_ETHSWCFGR, 5, 0), + GATE_CFG(GATE_ETHSWACMCFG, RCC_ETHSWACMCFGR, 1, 0), + GATE_CFG(GATE_ETHSWACMMSG, RCC_ETHSWACMMSGCFGR, 1, 0), + GATE_CFG(GATE_ETHSWMAC, RCC_ETHSWCFGR, 1, 0), + GATE_CFG(GATE_ETHSWREF, RCC_ETHSWCFGR, 21, 0), + GATE_CFG(GATE_FDCAN, RCC_FDCANCFGR, 1, 0), + GATE_CFG(GATE_GPU, RCC_GPUCFGR, 1, 0), + GATE_CFG(GATE_HASH, RCC_HASHCFGR, 1, 0), + GATE_CFG(GATE_HDP, RCC_HDPCFGR, 1, 0), + GATE_CFG(GATE_I2C1, RCC_I2C1CFGR, 1, 0), + GATE_CFG(GATE_I2C2, RCC_I2C2CFGR, 1, 0), + GATE_CFG(GATE_I2C3, RCC_I2C3CFGR, 1, 0), + GATE_CFG(GATE_I2C4, RCC_I2C4CFGR, 1, 0), + GATE_CFG(GATE_I2C5, RCC_I2C5CFGR, 1, 0), + GATE_CFG(GATE_I2C6, RCC_I2C6CFGR, 1, 0), + GATE_CFG(GATE_I2C7, RCC_I2C7CFGR, 1, 0), + GATE_CFG(GATE_I2C8, RCC_I2C8CFGR, 1, 0), + GATE_CFG(GATE_I3C1, RCC_I3C1CFGR, 1, 0), + GATE_CFG(GATE_I3C2, RCC_I3C2CFGR, 1, 0), + GATE_CFG(GATE_I3C3, RCC_I3C3CFGR, 1, 0), + GATE_CFG(GATE_I3C4, RCC_I3C4CFGR, 1, 0), + GATE_CFG(GATE_IS2M, RCC_IS2MCFGR, 1, 0), + GATE_CFG(GATE_IWDG1, RCC_IWDG1CFGR, 1, 0), + GATE_CFG(GATE_IWDG2, RCC_IWDG2CFGR, 1, 0), + GATE_CFG(GATE_IWDG3, RCC_IWDG3CFGR, 1, 0), + GATE_CFG(GATE_IWDG4, RCC_IWDG4CFGR, 1, 0), + GATE_CFG(GATE_IWDG5, RCC_IWDG5CFGR, 1, 0), + GATE_CFG(GATE_LPTIM1, RCC_LPTIM1CFGR, 1, 0), + GATE_CFG(GATE_LPTIM2, RCC_LPTIM2CFGR, 1, 0), + GATE_CFG(GATE_LPTIM3, RCC_LPTIM3CFGR, 1, 0), + GATE_CFG(GATE_LPTIM4, RCC_LPTIM4CFGR, 1, 0), + GATE_CFG(GATE_LPTIM5, RCC_LPTIM5CFGR, 1, 0), + GATE_CFG(GATE_LPUART1, RCC_LPUART1CFGR, 1, 0), + GATE_CFG(GATE_LTDC, RCC_LTDCCFGR, 1, 0), + GATE_CFG(GATE_LVDS, RCC_LVDSCFGR, 1, 0), + GATE_CFG(GATE_MCO1, RCC_MCO1CFGR, 8, 0), + GATE_CFG(GATE_MCO2, RCC_MCO2CFGR, 8, 0), + GATE_CFG(GATE_MDF1, RCC_MDF1CFGR, 1, 0), + GATE_CFG(GATE_OSPIIOM, RCC_OSPIIOMCFGR, 1, 0), + GATE_CFG(GATE_PCIE, RCC_PCIECFGR, 1, 0), + GATE_CFG(GATE_PKA, RCC_PKACFGR, 1, 0), + GATE_CFG(GATE_RNG, RCC_RNGCFGR, 1, 0), + GATE_CFG(GATE_SAES, RCC_SAESCFGR, 1, 0), + GATE_CFG(GATE_SAI1, RCC_SAI1CFGR, 1, 0), + GATE_CFG(GATE_SAI2, RCC_SAI2CFGR, 1, 0), + GATE_CFG(GATE_SAI3, RCC_SAI3CFGR, 1, 0), + GATE_CFG(GATE_SAI4, RCC_SAI4CFGR, 1, 0), + GATE_CFG(GATE_SDMMC1, RCC_SDMMC1CFGR, 1, 0), + GATE_CFG(GATE_SDMMC2, RCC_SDMMC2CFGR, 1, 0), + GATE_CFG(GATE_SDMMC3, RCC_SDMMC3CFGR, 1, 0), + GATE_CFG(GATE_SERC, RCC_SERCCFGR, 1, 0), + GATE_CFG(GATE_SPDIFRX, RCC_SPDIFRXCFGR, 1, 0), + GATE_CFG(GATE_SPI1, RCC_SPI1CFGR, 1, 0), + GATE_CFG(GATE_SPI2, RCC_SPI2CFGR, 1, 0), + GATE_CFG(GATE_SPI3, RCC_SPI3CFGR, 1, 0), + GATE_CFG(GATE_SPI4, RCC_SPI4CFGR, 1, 0), + GATE_CFG(GATE_SPI5, RCC_SPI5CFGR, 1, 0), + GATE_CFG(GATE_SPI6, RCC_SPI6CFGR, 1, 0), + GATE_CFG(GATE_SPI7, RCC_SPI7CFGR, 1, 0), + GATE_CFG(GATE_SPI8, RCC_SPI8CFGR, 1, 0), + GATE_CFG(GATE_TIM1, RCC_TIM1CFGR, 1, 0), + GATE_CFG(GATE_TIM10, RCC_TIM10CFGR, 1, 0), + GATE_CFG(GATE_TIM11, RCC_TIM11CFGR, 1, 0), + GATE_CFG(GATE_TIM12, RCC_TIM12CFGR, 1, 0), + GATE_CFG(GATE_TIM13, RCC_TIM13CFGR, 1, 0), + GATE_CFG(GATE_TIM14, RCC_TIM14CFGR, 1, 0), + GATE_CFG(GATE_TIM15, RCC_TIM15CFGR, 1, 0), + GATE_CFG(GATE_TIM16, RCC_TIM16CFGR, 1, 0), + GATE_CFG(GATE_TIM17, RCC_TIM17CFGR, 1, 0), + GATE_CFG(GATE_TIM2, RCC_TIM2CFGR, 1, 0), + GATE_CFG(GATE_TIM20, RCC_TIM20CFGR, 1, 0), + GATE_CFG(GATE_TIM3, RCC_TIM3CFGR, 1, 0), + GATE_CFG(GATE_TIM4, RCC_TIM4CFGR, 1, 0), + GATE_CFG(GATE_TIM5, RCC_TIM5CFGR, 1, 0), + GATE_CFG(GATE_TIM6, RCC_TIM6CFGR, 1, 0), + GATE_CFG(GATE_TIM7, RCC_TIM7CFGR, 1, 0), + GATE_CFG(GATE_TIM8, RCC_TIM8CFGR, 1, 0), + GATE_CFG(GATE_UART4, RCC_UART4CFGR, 1, 0), + GATE_CFG(GATE_UART5, RCC_UART5CFGR, 1, 0), + GATE_CFG(GATE_UART7, RCC_UART7CFGR, 1, 0), + GATE_CFG(GATE_UART8, RCC_UART8CFGR, 1, 0), + GATE_CFG(GATE_UART9, RCC_UART9CFGR, 1, 0), + GATE_CFG(GATE_USART1, RCC_USART1CFGR, 1, 0), + GATE_CFG(GATE_USART2, RCC_USART2CFGR, 1, 0), + GATE_CFG(GATE_USART3, RCC_USART3CFGR, 1, 0), + GATE_CFG(GATE_USART6, RCC_USART6CFGR, 1, 0), + GATE_CFG(GATE_USBH, RCC_USBHCFGR, 1, 0), + GATE_CFG(GATE_USB2PHY1, RCC_USB2PHY1CFGR, 1, 0), + GATE_CFG(GATE_USB2PHY2, RCC_USB2PHY2CFGR, 1, 0), + GATE_CFG(GATE_USB3DR, RCC_USB3DRCFGR, 1, 0), + GATE_CFG(GATE_USB3PCIEPHY, RCC_USB3PCIEPHYCFGR, 1, 0), + GATE_CFG(GATE_USBTC, RCC_USBTCCFGR, 1, 0), + GATE_CFG(GATE_VDEC, RCC_VDECCFGR, 1, 0), + GATE_CFG(GATE_VENC, RCC_VENCCFGR, 1, 0), + GATE_CFG(GATE_VREF, RCC_VREFCFGR, 1, 0), + GATE_CFG(GATE_WWDG1, RCC_WWDG1CFGR, 1, 0), + GATE_CFG(GATE_WWDG2, RCC_WWDG2CFGR, 1, 0), +}; + +#define CLK_HW_INIT_INDEX(_name, _parent, _ops, _flags) \ + (&(struct clk_init_data) { \ + .flags = _flags, \ + .name = _name, \ + .parent_data = (const struct clk_parent_data[]) { \ + { .index = _parent }, \ + }, \ + .num_parents = 1, \ + .ops = _ops, \ + }) + +/* ADC */ +static struct clk_stm32_gate ck_icn_p_adc12 = { + .gate_id = GATE_ADC12, + .hw.init = CLK_HW_INIT_INDEX("ck_icn_p_adc12", ICN_LS_MCU, &clk_stm32_gate_ops, 0), +}; + +static struct clk_stm32_composite ck_ker_adc12 = { + .gate_id = GATE_ADC12, + .mux_id = MUX_ADC12, + .div_id = NO_STM32_DIV, + .hw.init = CLK_HW_INIT_PARENTS_DATA("ck_ker_adc12", adc12_src, &clk_stm32_composite_ops, 0), +}; + +static struct clk_stm32_gate ck_icn_p_adc3 = { + .gate_id = GATE_ADC3, + .hw.init = CLK_HW_INIT_INDEX("ck_icn_p_adc3", ICN_LS_MCU, &clk_stm32_gate_ops, 0), +}; + +static struct clk_stm32_composite ck_ker_adc3 = { + .gate_id = GATE_ADC3, + .mux_id = MUX_ADC3, + .div_id = NO_STM32_DIV, + .hw.init = CLK_HW_INIT_PARENTS_DATA("ck_ker_adc3", adc3_src, &clk_stm32_composite_ops, 0), +}; + +/* ADF */ +static struct clk_stm32_gate ck_icn_p_adf1 = { + .gate_id = GATE_ADF1, + .hw.init = CLK_HW_INIT_INDEX("ck_icn_p_adf1", ICN_LS_MCU, &clk_stm32_gate_ops, 0), +}; + +static struct clk_stm32_gate ck_ker_adf1 = { + .gate_id = GATE_ADF1, + .hw.init = CLK_HW_INIT_INDEX("ck_ker_adf1", FLEXGEN_42, &clk_stm32_gate_ops, 0), +}; + +/* DCMI */ +static struct clk_stm32_gate ck_icn_p_cci = { + .gate_id = GATE_CCI, + .hw.init = CLK_HW_INIT_INDEX("ck_icn_p_cci", ICN_LS_MCU, &clk_stm32_gate_ops, 0), +}; + +/* CSI-HOST */ +static struct clk_stm32_gate ck_icn_p_csi = { + .gate_id = GATE_CSI, + .hw.init = CLK_HW_INIT_INDEX("ck_icn_p_csi", ICN_APB4, &clk_stm32_gate_ops, 0), +}; + +static struct clk_stm32_gate ck_ker_csi = { + .gate_id = GATE_CSI, + .hw.init = CLK_HW_INIT_INDEX("ck_ker_csi", FLEXGEN_29, &clk_stm32_gate_ops, 0), +}; + +static struct clk_stm32_gate ck_ker_csitxesc = { + .gate_id = GATE_CSI, + .hw.init = CLK_HW_INIT_INDEX("ck_ker_csitxesc", FLEXGEN_30, &clk_stm32_gate_ops, 0), +}; + +/* CSI-PHY */ +static struct clk_stm32_gate ck_ker_csiphy = { + .gate_id = GATE_CSI, + .hw.init = CLK_HW_INIT_INDEX("ck_ker_csiphy", FLEXGEN_31, &clk_stm32_gate_ops, 0), +}; + +/* DCMIPP */ +static struct clk_stm32_gate ck_icn_p_dcmipp = { + .gate_id = GATE_DCMIPP, + .hw.init = CLK_HW_INIT_INDEX("ck_icn_p_dcmipp", ICN_APB4, &clk_stm32_gate_ops, 0), +}; + +/* CRC */ +static struct clk_stm32_gate ck_icn_p_crc = { + .gate_id = GATE_CRC, + .hw.init = CLK_HW_INIT_INDEX("ck_icn_p_crc", ICN_LS_MCU, &clk_stm32_gate_ops, 0), +}; + +/* CRYP */ +static struct clk_stm32_gate ck_icn_p_cryp1 = { + .gate_id = GATE_CRYP1, + .hw.init = CLK_HW_INIT_INDEX("ck_icn_p_cryp1", ICN_LS_MCU, &clk_stm32_gate_ops, 0), +}; + +static struct clk_stm32_gate ck_icn_p_cryp2 = { + .gate_id = GATE_CRYP2, + .hw.init = CLK_HW_INIT_INDEX("ck_icn_p_cryp2", ICN_LS_MCU, &clk_stm32_gate_ops, 0), +}; + +/* DBG & TRACE*/ +/* Trace and debug clocks are managed by SCMI */ + +/* LTDC */ +static struct clk_stm32_gate ck_icn_p_ltdc = { + .gate_id = GATE_LTDC, + .hw.init = CLK_HW_INIT_INDEX("ck_icn_p_ltdc", ICN_APB4, &clk_stm32_gate_ops, 0), +}; + +static struct clk_stm32_gate ck_ker_ltdc = { + .gate_id = GATE_LTDC, + .hw.init = CLK_HW_INIT_INDEX("ck_ker_ltdc", FLEXGEN_27, &clk_stm32_gate_ops, + CLK_SET_RATE_PARENT), +}; + +/* DSI */ +static struct clk_stm32_gate ck_icn_p_dsi = { + .gate_id = GATE_DSI, + .hw.init = CLK_HW_INIT_INDEX("ck_icn_p_dsi", ICN_APB4, &clk_stm32_gate_ops, 0), +}; + +static struct clk_stm32_composite clk_lanebyte = { + .gate_id = GATE_DSI, + .mux_id = MUX_DSIBLANE, + .div_id = NO_STM32_DIV, + .hw.init = CLK_HW_INIT_PARENTS_DATA("clk_lanebyte", dsiblane_src, + &clk_stm32_composite_ops, 0), +}; + +/* LVDS */ +static struct clk_stm32_gate ck_icn_p_lvds = { + .gate_id = GATE_LVDS, + .hw.init = CLK_HW_INIT_INDEX("ck_icn_p_lvds", ICN_APB4, &clk_stm32_gate_ops, 0), +}; + +/* DSI PHY */ +static struct clk_stm32_composite clk_phy_dsi = { + .gate_id = GATE_DSI, + .mux_id = MUX_DSIPHY, + .div_id = NO_STM32_DIV, + .hw.init = CLK_HW_INIT_PARENTS_DATA("clk_phy_dsi", dsiphy_src, + &clk_stm32_composite_ops, 0), +}; + +/* LVDS PHY */ +static struct clk_stm32_composite ck_ker_lvdsphy = { + .gate_id = GATE_LVDS, + .mux_id = MUX_LVDSPHY, + .div_id = NO_STM32_DIV, + .hw.init = CLK_HW_INIT_PARENTS_DATA("ck_ker_lvdsphy", lvdsphy_src, + &clk_stm32_composite_ops, 0), +}; + +/* DTS */ +static struct clk_stm32_composite ck_ker_dts = { + .gate_id = GATE_DTS, + .mux_id = MUX_DTS, + .div_id = NO_STM32_DIV, + .hw.init = CLK_HW_INIT_PARENTS_DATA("ck_ker_dts", dts_src, + &clk_stm32_composite_ops, 0), +}; + +/* ETHERNET */ +static struct clk_stm32_gate ck_icn_p_eth1 = { + .gate_id = GATE_ETH1, + .hw.init = CLK_HW_INIT_INDEX("ck_icn_p_eth1", ICN_LS_MCU, &clk_stm32_gate_ops, 0), +}; + +static struct clk_stm32_gate ck_ker_eth1stp = { + .gate_id = GATE_ETH1STP, + .hw.init = CLK_HW_INIT_INDEX("ck_ker_eth1stp", ICN_LS_MCU, &clk_stm32_gate_ops, 0), +}; + +static struct clk_stm32_gate ck_ker_eth1 = { + .gate_id = GATE_ETH1, + .hw.init = CLK_HW_INIT_INDEX("ck_ker_eth1", FLEXGEN_54, &clk_stm32_gate_ops, 0), +}; + +static struct clk_stm32_gate ck_ker_eth1ptp = { + .gate_id = GATE_ETH1, + .hw.init = CLK_HW_INIT_INDEX("ck_ker_eth1ptp", FLEXGEN_56, &clk_stm32_gate_ops, 0), +}; + +static struct clk_stm32_gate ck_ker_eth1mac = { + .gate_id = GATE_ETH1MAC, + .hw.init = CLK_HW_INIT_INDEX("ck_ker_eth1mac", ICN_LS_MCU, &clk_stm32_gate_ops, 0), +}; + +static struct clk_stm32_gate ck_ker_eth1tx = { + .gate_id = GATE_ETH1TX, + .hw.init = CLK_HW_INIT_INDEX("ck_ker_eth1tx", ICN_LS_MCU, &clk_stm32_gate_ops, 0), +}; + +static struct clk_stm32_gate ck_ker_eth1rx = { + .gate_id = GATE_ETH1RX, + .hw.init = CLK_HW_INIT_INDEX("ck_ker_eth1rx", ICN_LS_MCU, &clk_stm32_gate_ops, 0), +}; + +static struct clk_stm32_gate ck_icn_p_eth2 = { + .gate_id = GATE_ETH2, + .hw.init = CLK_HW_INIT_INDEX("ck_icn_p_eth2", ICN_LS_MCU, &clk_stm32_gate_ops, 0), +}; + +static struct clk_stm32_gate ck_ker_eth2stp = { + .gate_id = GATE_ETH2STP, + .hw.init = CLK_HW_INIT_INDEX("ck_ker_eth2stp", ICN_LS_MCU, &clk_stm32_gate_ops, 0), +}; + +static struct clk_stm32_gate ck_ker_eth2 = { + .gate_id = GATE_ETH2, + .hw.init = CLK_HW_INIT_INDEX("ck_ker_eth2", FLEXGEN_55, &clk_stm32_gate_ops, 0), +}; + +static struct clk_stm32_gate ck_ker_eth2ptp = { + .gate_id = GATE_ETH2, + .hw.init = CLK_HW_INIT_INDEX("ck_ker_eth2ptp", FLEXGEN_56, &clk_stm32_gate_ops, 0), +}; + +static struct clk_stm32_gate ck_ker_eth2mac = { + .gate_id = GATE_ETH2MAC, + .hw.init = CLK_HW_INIT_INDEX("ck_ker_eth2mac", ICN_LS_MCU, &clk_stm32_gate_ops, 0), +}; + +static struct clk_stm32_gate ck_ker_eth2tx = { + .gate_id = GATE_ETH2TX, + .hw.init = CLK_HW_INIT_INDEX("ck_ker_eth2tx", ICN_LS_MCU, &clk_stm32_gate_ops, 0), +}; + +static struct clk_stm32_gate ck_ker_eth2rx = { + .gate_id = GATE_ETH2RX, + .hw.init = CLK_HW_INIT_INDEX("ck_ker_eth2rx", ICN_LS_MCU, &clk_stm32_gate_ops, 0), +}; + +static struct clk_stm32_gate ck_icn_p_ethsw = { + .gate_id = GATE_ETHSWMAC, + .hw.init = CLK_HW_INIT_INDEX("ck_icn_p_ethsw", ICN_LS_MCU, &clk_stm32_gate_ops, 0), +}; + +static struct clk_stm32_gate ck_ker_ethsw = { + .gate_id = GATE_ETHSW, + .hw.init = CLK_HW_INIT_INDEX("ck_ker_ethsw", FLEXGEN_54, &clk_stm32_gate_ops, 0), +}; + +static struct clk_stm32_gate ck_ker_ethswref = { + .gate_id = GATE_ETHSWREF, + .hw.init = CLK_HW_INIT_INDEX("ck_ker_ethswref", FLEXGEN_60, &clk_stm32_gate_ops, 0), +}; + +static struct clk_stm32_gate ck_icn_p_ethsw_acm_cfg = { + .gate_id = GATE_ETHSWACMCFG, + .hw.init = CLK_HW_INIT_INDEX("ck_icn_p_ethsw_acm_cfg", ICN_LS_MCU, + &clk_stm32_gate_ops, 0), +}; + +static struct clk_stm32_gate ck_icn_p_ethsw_acm_msg = { + .gate_id = GATE_ETHSWACMMSG, + .hw.init = CLK_HW_INIT_INDEX("ck_icn_p_ethsw_acm_msg", ICN_LS_MCU, + &clk_stm32_gate_ops, 0), +}; + +/* FDCAN */ +static struct clk_stm32_gate ck_icn_p_fdcan = { + .gate_id = GATE_FDCAN, + .hw.init = CLK_HW_INIT_INDEX("ck_icn_p_fdcan", ICN_APB2, &clk_stm32_gate_ops, 0), +}; + +static struct clk_stm32_gate ck_ker_fdcan = { + .gate_id = GATE_FDCAN, + .hw.init = CLK_HW_INIT_INDEX("ck_ker_fdcan", FLEXGEN_26, &clk_stm32_gate_ops, 0), +}; + +/* GPU */ +static struct clk_stm32_gate ck_icn_m_gpu = { + .gate_id = GATE_GPU, + .hw.init = CLK_HW_INIT_INDEX("ck_icn_m_gpu", FLEXGEN_59, &clk_stm32_gate_ops, 0), +}; + +static struct clk_stm32_gate ck_ker_gpu = { + .gate_id = GATE_GPU, + .hw.init = CLK_HW_INIT_INDEX("ck_ker_gpu", PLL3, &clk_stm32_gate_ops, 0), +}; + +/* HASH */ +static struct clk_stm32_gate ck_icn_p_hash = { + .gate_id = GATE_HASH, + .hw.init = CLK_HW_INIT_INDEX("ck_icn_p_hash", ICN_LS_MCU, &clk_stm32_gate_ops, 0), +}; + +/* HDP */ +static struct clk_stm32_gate ck_icn_p_hdp = { + .gate_id = GATE_HDP, + .hw.init = CLK_HW_INIT_INDEX("ck_icn_p_hdp", ICN_APB3, &clk_stm32_gate_ops, 0), +}; + +/* I2C */ +static struct clk_stm32_gate ck_icn_p_i2c8 = { + .gate_id = GATE_I2C8, + .hw.init = CLK_HW_INIT_INDEX("ck_icn_p_i2c8", ICN_LS_MCU, &clk_stm32_gate_ops, 0), +}; + +static struct clk_stm32_gate ck_icn_p_i2c1 = { + .gate_id = GATE_I2C1, + .hw.init = CLK_HW_INIT_INDEX("ck_icn_p_i2c1", ICN_APB1, &clk_stm32_gate_ops, 0), +}; + +static struct clk_stm32_gate ck_icn_p_i2c2 = { + .gate_id = GATE_I2C2, + .hw.init = CLK_HW_INIT_INDEX("ck_icn_p_i2c2", ICN_APB1, &clk_stm32_gate_ops, 0), +}; + +static struct clk_stm32_gate ck_icn_p_i2c3 = { + .gate_id = GATE_I2C3, + .hw.init = CLK_HW_INIT_INDEX("ck_icn_p_i2c3", ICN_APB1, &clk_stm32_gate_ops, 0), +}; + +static struct clk_stm32_gate ck_icn_p_i2c4 = { + .gate_id = GATE_I2C4, + .hw.init = CLK_HW_INIT_INDEX("ck_icn_p_i2c4", ICN_APB1, &clk_stm32_gate_ops, 0), +}; + +static struct clk_stm32_gate ck_icn_p_i2c5 = { + .gate_id = GATE_I2C5, + .hw.init = CLK_HW_INIT_INDEX("ck_icn_p_i2c5", ICN_APB1, &clk_stm32_gate_ops, 0), +}; + +static struct clk_stm32_gate ck_icn_p_i2c6 = { + .gate_id = GATE_I2C6, + .hw.init = CLK_HW_INIT_INDEX("ck_icn_p_i2c6", ICN_APB1, &clk_stm32_gate_ops, 0), +}; + +static struct clk_stm32_gate ck_icn_p_i2c7 = { + .gate_id = GATE_I2C7, + .hw.init = CLK_HW_INIT_INDEX("ck_icn_p_i2c7", ICN_APB1, &clk_stm32_gate_ops, 0), +}; + +static struct clk_stm32_gate ck_ker_i2c1 = { + .gate_id = GATE_I2C1, + .hw.init = CLK_HW_INIT_INDEX("ck_ker_i2c1", FLEXGEN_12, &clk_stm32_gate_ops, 0), +}; + +static struct clk_stm32_gate ck_ker_i2c2 = { + .gate_id = GATE_I2C2, + .hw.init = CLK_HW_INIT_INDEX("ck_ker_i2c2", FLEXGEN_12, &clk_stm32_gate_ops, 0), +}; + +static struct clk_stm32_gate ck_ker_i2c3 = { + .gate_id = GATE_I2C3, + .hw.init = CLK_HW_INIT_INDEX("ck_ker_i2c3", FLEXGEN_13, &clk_stm32_gate_ops, 0), +}; + +static struct clk_stm32_gate ck_ker_i2c5 = { + .gate_id = GATE_I2C5, + .hw.init = CLK_HW_INIT_INDEX("ck_ker_i2c5", FLEXGEN_13, &clk_stm32_gate_ops, 0), +}; + +static struct clk_stm32_gate ck_ker_i2c4 = { + .gate_id = GATE_I2C4, + .hw.init = CLK_HW_INIT_INDEX("ck_ker_i2c4", FLEXGEN_14, &clk_stm32_gate_ops, 0), +}; + +static struct clk_stm32_gate ck_ker_i2c6 = { + .gate_id = GATE_I2C6, + .hw.init = CLK_HW_INIT_INDEX("ck_ker_i2c6", FLEXGEN_14, &clk_stm32_gate_ops, 0), +}; + +static struct clk_stm32_gate ck_ker_i2c7 = { + .gate_id = GATE_I2C7, + .hw.init = CLK_HW_INIT_INDEX("ck_ker_i2c7", FLEXGEN_15, &clk_stm32_gate_ops, 0), +}; + +static struct clk_stm32_gate ck_ker_i2c8 = { + .gate_id = GATE_I2C8, + .hw.init = CLK_HW_INIT_INDEX("ck_ker_i2c8", FLEXGEN_38, &clk_stm32_gate_ops, 0), +}; + +/* I3C */ +static struct clk_stm32_gate ck_icn_p_i3c1 = { + .gate_id = GATE_I3C1, + .hw.init = CLK_HW_INIT_INDEX("ck_icn_p_i3c1", ICN_APB1, &clk_stm32_gate_ops, 0), +}; + +static struct clk_stm32_gate ck_icn_p_i3c2 = { + .gate_id = GATE_I3C2, + .hw.init = CLK_HW_INIT_INDEX("ck_icn_p_i3c2", ICN_APB1, &clk_stm32_gate_ops, 0), +}; + +static struct clk_stm32_gate ck_icn_p_i3c3 = { + .gate_id = GATE_I3C3, + .hw.init = CLK_HW_INIT_INDEX("ck_icn_p_i3c3", ICN_APB1, &clk_stm32_gate_ops, 0), +}; + +static struct clk_stm32_gate ck_icn_p_i3c4 = { + .gate_id = GATE_I3C4, + .hw.init = CLK_HW_INIT_INDEX("ck_icn_p_i3c4", ICN_LS_MCU, &clk_stm32_gate_ops, 0), +}; + +static struct clk_stm32_gate ck_ker_i3c1 = { + .gate_id = GATE_I3C1, + .hw.init = CLK_HW_INIT_INDEX("ck_ker_i3c1", FLEXGEN_12, &clk_stm32_gate_ops, 0), +}; + +static struct clk_stm32_gate ck_ker_i3c2 = { + .gate_id = GATE_I3C2, + .hw.init = CLK_HW_INIT_INDEX("ck_ker_i3c2", FLEXGEN_12, &clk_stm32_gate_ops, 0), +}; + +static struct clk_stm32_gate ck_ker_i3c3 = { + .gate_id = GATE_I3C3, + .hw.init = CLK_HW_INIT_INDEX("ck_ker_i3c3", FLEXGEN_13, &clk_stm32_gate_ops, 0), +}; + +static struct clk_stm32_gate ck_ker_i3c4 = { + .gate_id = GATE_I3C4, + .hw.init = CLK_HW_INIT_INDEX("ck_ker_i3c4", FLEXGEN_36, &clk_stm32_gate_ops, 0), +}; + +/* I2S */ +static struct clk_stm32_gate ck_icn_p_is2m = { + .gate_id = GATE_IS2M, + .hw.init = CLK_HW_INIT_INDEX("ck_icn_p_is2m", ICN_APB3, &clk_stm32_gate_ops, 0), +}; + +/* IWDG */ +static struct clk_stm32_gate ck_icn_p_iwdg2 = { + .gate_id = GATE_IWDG2, + .hw.init = CLK_HW_INIT_INDEX("ck_icn_p_iwdg2", ICN_APB3, &clk_stm32_gate_ops, 0), +}; + +static struct clk_stm32_gate ck_icn_p_iwdg3 = { + .gate_id = GATE_IWDG3, + .hw.init = CLK_HW_INIT_INDEX("ck_icn_p_iwdg3", ICN_APB3, &clk_stm32_gate_ops, 0), +}; + +static struct clk_stm32_gate ck_icn_p_iwdg4 = { + .gate_id = GATE_IWDG4, + .hw.init = CLK_HW_INIT_INDEX("ck_icn_p_iwdg4", ICN_APB3, &clk_stm32_gate_ops, 0), +}; + +static struct clk_stm32_gate ck_icn_p_iwdg5 = { + .gate_id = GATE_IWDG5, + .hw.init = CLK_HW_INIT_INDEX("ck_icn_p_iwdg5", ICN_LS_MCU, &clk_stm32_gate_ops, 0), +}; + +/* LPTIM */ +static struct clk_stm32_gate ck_icn_p_lptim1 = { + .gate_id = GATE_LPTIM1, + .hw.init = CLK_HW_INIT_INDEX("ck_icn_p_lptim1", ICN_APB1, &clk_stm32_gate_ops, 0), +}; + +static struct clk_stm32_gate ck_icn_p_lptim2 = { + .gate_id = GATE_LPTIM2, + .hw.init = CLK_HW_INIT_INDEX("ck_icn_p_lptim2", ICN_APB1, &clk_stm32_gate_ops, 0), +}; + +static struct clk_stm32_gate ck_icn_p_lptim3 = { + .gate_id = GATE_LPTIM3, + .hw.init = CLK_HW_INIT_INDEX("ck_icn_p_lptim3", ICN_LS_MCU, &clk_stm32_gate_ops, 0), +}; + +static struct clk_stm32_gate ck_icn_p_lptim4 = { + .gate_id = GATE_LPTIM4, + .hw.init = CLK_HW_INIT_INDEX("ck_icn_p_lptim4", ICN_LS_MCU, &clk_stm32_gate_ops, 0), +}; + +static struct clk_stm32_gate ck_icn_p_lptim5 = { + .gate_id = GATE_LPTIM5, + .hw.init = CLK_HW_INIT_INDEX("ck_icn_p_lptim5", ICN_LS_MCU, &clk_stm32_gate_ops, 0), +}; + +static struct clk_stm32_gate ck_ker_lptim1 = { + .gate_id = GATE_LPTIM1, + .hw.init = CLK_HW_INIT_INDEX("ck_ker_lptim1", FLEXGEN_07, &clk_stm32_gate_ops, 0), +}; + +static struct clk_stm32_gate ck_ker_lptim2 = { + .gate_id = GATE_LPTIM2, + .hw.init = CLK_HW_INIT_INDEX("ck_ker_lptim2", FLEXGEN_07, &clk_stm32_gate_ops, 0), +}; + +static struct clk_stm32_gate ck_ker_lptim3 = { + .gate_id = GATE_LPTIM3, + .hw.init = CLK_HW_INIT_INDEX("ck_ker_lptim3", FLEXGEN_40, &clk_stm32_gate_ops, 0), +}; + +static struct clk_stm32_gate ck_ker_lptim4 = { + .gate_id = GATE_LPTIM4, + .hw.init = CLK_HW_INIT_INDEX("ck_ker_lptim4", FLEXGEN_41, &clk_stm32_gate_ops, 0), +}; + +static struct clk_stm32_gate ck_ker_lptim5 = { + .gate_id = GATE_LPTIM5, + .hw.init = CLK_HW_INIT_INDEX("ck_ker_lptim5", FLEXGEN_41, &clk_stm32_gate_ops, 0), +}; + +/* LPUART */ +static struct clk_stm32_gate ck_icn_p_lpuart1 = { + .gate_id = GATE_LPUART1, + .hw.init = CLK_HW_INIT_INDEX("ck_icn_p_lpuart1", ICN_LS_MCU, &clk_stm32_gate_ops, 0), +}; + +static struct clk_stm32_gate ck_ker_lpuart1 = { + .gate_id = GATE_LPUART1, + .hw.init = CLK_HW_INIT_INDEX("ck_ker_lpuart1", FLEXGEN_39, &clk_stm32_gate_ops, 0), +}; + +/* MCO1 & MCO2 */ +static struct clk_stm32_composite ck_mco1 = { + .gate_id = GATE_MCO1, + .mux_id = MUX_MCO1, + .div_id = NO_STM32_DIV, + .hw.init = CLK_HW_INIT_PARENTS_DATA("ck_mco1", mco1_src, &clk_stm32_composite_ops, 0), +}; + +static struct clk_stm32_composite ck_mco2 = { + .gate_id = GATE_MCO2, + .mux_id = MUX_MCO2, + .div_id = NO_STM32_DIV, + .hw.init = CLK_HW_INIT_PARENTS_DATA("ck_mco2", mco2_src, &clk_stm32_composite_ops, 0), +}; + +/* MDF */ +static struct clk_stm32_gate ck_icn_p_mdf1 = { + .gate_id = GATE_MDF1, + .hw.init = CLK_HW_INIT_INDEX("ck_icn_p_mdf1", ICN_LS_MCU, &clk_stm32_gate_ops, 0), +}; + +static struct clk_stm32_gate ck_ker_mdf1 = { + .gate_id = GATE_MDF1, + .hw.init = CLK_HW_INIT_INDEX("ck_ker_mdf1", FLEXGEN_23, &clk_stm32_gate_ops, 0), +}; + +/* OSPI */ +static struct clk_stm32_gate ck_icn_p_ospiiom = { + .gate_id = GATE_OSPIIOM, + .hw.init = CLK_HW_INIT_INDEX("ck_icn_p_ospiiom", ICN_LS_MCU, &clk_stm32_gate_ops, 0), +}; + +/* PCIE */ +static struct clk_stm32_gate ck_icn_p_pcie = { + .gate_id = GATE_PCIE, + .hw.init = CLK_HW_INIT_INDEX("ck_icn_p_pcie", ICN_LS_MCU, &clk_stm32_gate_ops, 0), +}; + +/* SAI */ +static struct clk_stm32_gate ck_icn_p_sai1 = { + .gate_id = GATE_SAI1, + .hw.init = CLK_HW_INIT_INDEX("ck_icn_p_sai1", ICN_APB2, &clk_stm32_gate_ops, 0), +}; + +static struct clk_stm32_gate ck_icn_p_sai2 = { + .gate_id = GATE_SAI2, + .hw.init = CLK_HW_INIT_INDEX("ck_icn_p_sai2", ICN_APB2, &clk_stm32_gate_ops, 0), +}; + +static struct clk_stm32_gate ck_icn_p_sai3 = { + .gate_id = GATE_SAI3, + .hw.init = CLK_HW_INIT_INDEX("ck_icn_p_sai3", ICN_APB2, &clk_stm32_gate_ops, 0), +}; + +static struct clk_stm32_gate ck_icn_p_sai4 = { + .gate_id = GATE_SAI4, + .hw.init = CLK_HW_INIT_INDEX("ck_icn_p_sai4", ICN_APB2, &clk_stm32_gate_ops, 0), +}; + +static struct clk_stm32_gate ck_ker_sai1 = { + .gate_id = GATE_SAI1, + .hw.init = CLK_HW_INIT_INDEX("ck_ker_sai1", FLEXGEN_23, &clk_stm32_gate_ops, + CLK_SET_RATE_PARENT), +}; + +static struct clk_stm32_gate ck_ker_sai2 = { + .gate_id = GATE_SAI2, + .hw.init = CLK_HW_INIT_INDEX("ck_ker_sai2", FLEXGEN_24, &clk_stm32_gate_ops, + CLK_SET_RATE_PARENT), +}; + +static struct clk_stm32_gate ck_ker_sai3 = { + .gate_id = GATE_SAI3, + .hw.init = CLK_HW_INIT_INDEX("ck_ker_sai3", FLEXGEN_25, &clk_stm32_gate_ops, + CLK_SET_RATE_PARENT), +}; + +static struct clk_stm32_gate ck_ker_sai4 = { + .gate_id = GATE_SAI4, + .hw.init = CLK_HW_INIT_INDEX("ck_ker_sai4", FLEXGEN_25, &clk_stm32_gate_ops, + CLK_SET_RATE_PARENT), +}; + +/* SDMMC */ +static struct clk_stm32_gate ck_icn_m_sdmmc1 = { + .gate_id = GATE_SDMMC1, + .hw.init = CLK_HW_INIT_INDEX("ck_icn_m_sdmmc1", ICN_SDMMC, &clk_stm32_gate_ops, 0), +}; + +static struct clk_stm32_gate ck_icn_m_sdmmc2 = { + .gate_id = GATE_SDMMC2, + .hw.init = CLK_HW_INIT_INDEX("ck_icn_m_sdmmc2", ICN_SDMMC, &clk_stm32_gate_ops, 0), +}; + +static struct clk_stm32_gate ck_icn_m_sdmmc3 = { + .gate_id = GATE_SDMMC3, + .hw.init = CLK_HW_INIT_INDEX("ck_icn_m_sdmmc3", ICN_SDMMC, &clk_stm32_gate_ops, 0), +}; + +static struct clk_stm32_gate ck_ker_sdmmc1 = { + .gate_id = GATE_SDMMC1, + .hw.init = CLK_HW_INIT_INDEX("ck_ker_sdmmc1", FLEXGEN_51, &clk_stm32_gate_ops, 0), +}; + +static struct clk_stm32_gate ck_ker_sdmmc2 = { + .gate_id = GATE_SDMMC2, + .hw.init = CLK_HW_INIT_INDEX("ck_ker_sdmmc2", FLEXGEN_52, &clk_stm32_gate_ops, 0), +}; + +static struct clk_stm32_gate ck_ker_sdmmc3 = { + .gate_id = GATE_SDMMC3, + .hw.init = CLK_HW_INIT_INDEX("ck_ker_sdmmc3", FLEXGEN_53, &clk_stm32_gate_ops, 0), +}; + +/* SPDIF */ +static struct clk_stm32_gate ck_icn_p_spdifrx = { + .gate_id = GATE_SPDIFRX, + .hw.init = CLK_HW_INIT_INDEX("ck_icn_p_spdifrx", ICN_APB1, &clk_stm32_gate_ops, 0), +}; + +static struct clk_stm32_gate ck_ker_spdifrx = { + .gate_id = GATE_SPDIFRX, + .hw.init = CLK_HW_INIT_INDEX("ck_ker_spdifrx", FLEXGEN_11, &clk_stm32_gate_ops, 0), +}; + +/* SPI */ +static struct clk_stm32_gate ck_icn_p_spi1 = { + .gate_id = GATE_SPI1, + .hw.init = CLK_HW_INIT_INDEX("ck_icn_p_spi1", ICN_APB2, &clk_stm32_gate_ops, 0), +}; + +static struct clk_stm32_gate ck_icn_p_spi2 = { + .gate_id = GATE_SPI2, + .hw.init = CLK_HW_INIT_INDEX("ck_icn_p_spi2", ICN_APB1, &clk_stm32_gate_ops, 0), +}; + +static struct clk_stm32_gate ck_icn_p_spi3 = { + .gate_id = GATE_SPI3, + .hw.init = CLK_HW_INIT_INDEX("ck_icn_p_spi3", ICN_APB1, &clk_stm32_gate_ops, 0), +}; + +static struct clk_stm32_gate ck_icn_p_spi4 = { + .gate_id = GATE_SPI4, + .hw.init = CLK_HW_INIT_INDEX("ck_icn_p_spi4", ICN_APB2, &clk_stm32_gate_ops, 0), +}; + +static struct clk_stm32_gate ck_icn_p_spi5 = { + .gate_id = GATE_SPI5, + .hw.init = CLK_HW_INIT_INDEX("ck_icn_p_spi5", ICN_APB2, &clk_stm32_gate_ops, 0), +}; + +static struct clk_stm32_gate ck_icn_p_spi6 = { + .gate_id = GATE_SPI6, + .hw.init = CLK_HW_INIT_INDEX("ck_icn_p_spi6", ICN_APB2, &clk_stm32_gate_ops, 0), +}; + +static struct clk_stm32_gate ck_icn_p_spi7 = { + .gate_id = GATE_SPI7, + .hw.init = CLK_HW_INIT_INDEX("ck_icn_p_spi7", ICN_APB2, &clk_stm32_gate_ops, 0), +}; + +static struct clk_stm32_gate ck_icn_p_spi8 = { + .gate_id = GATE_SPI8, + .hw.init = CLK_HW_INIT_INDEX("ck_icn_p_spi8", ICN_LS_MCU, &clk_stm32_gate_ops, 0), +}; + +static struct clk_stm32_gate ck_ker_spi1 = { + .gate_id = GATE_SPI1, + .hw.init = CLK_HW_INIT_INDEX("ck_ker_spi1", FLEXGEN_16, &clk_stm32_gate_ops, + CLK_SET_RATE_PARENT), +}; + +static struct clk_stm32_gate ck_ker_spi2 = { + .gate_id = GATE_SPI2, + .hw.init = CLK_HW_INIT_INDEX("ck_ker_spi2", FLEXGEN_10, &clk_stm32_gate_ops, + CLK_SET_RATE_PARENT), +}; + +static struct clk_stm32_gate ck_ker_spi3 = { + .gate_id = GATE_SPI3, + .hw.init = CLK_HW_INIT_INDEX("ck_ker_spi3", FLEXGEN_10, &clk_stm32_gate_ops, + CLK_SET_RATE_PARENT), +}; + +static struct clk_stm32_gate ck_ker_spi4 = { + .gate_id = GATE_SPI4, + .hw.init = CLK_HW_INIT_INDEX("ck_ker_spi4", FLEXGEN_17, &clk_stm32_gate_ops, 0), +}; + +static struct clk_stm32_gate ck_ker_spi5 = { + .gate_id = GATE_SPI5, + .hw.init = CLK_HW_INIT_INDEX("ck_ker_spi5", FLEXGEN_17, &clk_stm32_gate_ops, 0), +}; + +static struct clk_stm32_gate ck_ker_spi6 = { + .gate_id = GATE_SPI6, + .hw.init = CLK_HW_INIT_INDEX("ck_ker_spi6", FLEXGEN_18, &clk_stm32_gate_ops, 0), +}; + +static struct clk_stm32_gate ck_ker_spi7 = { + .gate_id = GATE_SPI7, + .hw.init = CLK_HW_INIT_INDEX("ck_ker_spi7", FLEXGEN_18, &clk_stm32_gate_ops, 0), +}; + +static struct clk_stm32_gate ck_ker_spi8 = { + .gate_id = GATE_SPI8, + .hw.init = CLK_HW_INIT_INDEX("ck_ker_spi8", FLEXGEN_37, &clk_stm32_gate_ops, 0), +}; + +/* Timers */ +static struct clk_stm32_gate ck_icn_p_tim2 = { + .gate_id = GATE_TIM2, + .hw.init = CLK_HW_INIT_INDEX("ck_icn_p_tim2", ICN_APB1, &clk_stm32_gate_ops, 0), +}; + +static struct clk_stm32_gate ck_icn_p_tim3 = { + .gate_id = GATE_TIM3, + .hw.init = CLK_HW_INIT_INDEX("ck_icn_p_tim3", ICN_APB1, &clk_stm32_gate_ops, 0), +}; + +static struct clk_stm32_gate ck_icn_p_tim4 = { + .gate_id = GATE_TIM4, + .hw.init = CLK_HW_INIT_INDEX("ck_icn_p_tim4", ICN_APB1, &clk_stm32_gate_ops, 0), +}; + +static struct clk_stm32_gate ck_icn_p_tim5 = { + .gate_id = GATE_TIM5, + .hw.init = CLK_HW_INIT_INDEX("ck_icn_p_tim5", ICN_APB1, &clk_stm32_gate_ops, 0), +}; + +static struct clk_stm32_gate ck_icn_p_tim6 = { + .gate_id = GATE_TIM6, + .hw.init = CLK_HW_INIT_INDEX("ck_icn_p_tim6", ICN_APB1, &clk_stm32_gate_ops, 0), +}; + +static struct clk_stm32_gate ck_icn_p_tim7 = { + .gate_id = GATE_TIM7, + .hw.init = CLK_HW_INIT_INDEX("ck_icn_p_tim7", ICN_APB1, &clk_stm32_gate_ops, 0), +}; + +static struct clk_stm32_gate ck_icn_p_tim10 = { + .gate_id = GATE_TIM10, + .hw.init = CLK_HW_INIT_INDEX("ck_icn_p_tim10", ICN_APB1, &clk_stm32_gate_ops, 0), +}; + +static struct clk_stm32_gate ck_icn_p_tim11 = { + .gate_id = GATE_TIM11, + .hw.init = CLK_HW_INIT_INDEX("ck_icn_p_tim11", ICN_APB1, &clk_stm32_gate_ops, 0), +}; + +static struct clk_stm32_gate ck_icn_p_tim12 = { + .gate_id = GATE_TIM12, + .hw.init = CLK_HW_INIT_INDEX("ck_icn_p_tim12", ICN_APB1, &clk_stm32_gate_ops, 0), +}; + +static struct clk_stm32_gate ck_icn_p_tim13 = { + .gate_id = GATE_TIM13, + .hw.init = CLK_HW_INIT_INDEX("ck_icn_p_tim13", ICN_APB1, &clk_stm32_gate_ops, 0), +}; + +static struct clk_stm32_gate ck_icn_p_tim14 = { + .gate_id = GATE_TIM14, + .hw.init = CLK_HW_INIT_INDEX("ck_icn_p_tim14", ICN_APB1, &clk_stm32_gate_ops, 0), +}; + +static struct clk_stm32_gate ck_icn_p_tim1 = { + .gate_id = GATE_TIM1, + .hw.init = CLK_HW_INIT_INDEX("ck_icn_p_tim1", ICN_APB2, &clk_stm32_gate_ops, 0), +}; + +static struct clk_stm32_gate ck_icn_p_tim8 = { + .gate_id = GATE_TIM8, + .hw.init = CLK_HW_INIT_INDEX("ck_icn_p_tim8", ICN_APB2, &clk_stm32_gate_ops, 0), +}; + +static struct clk_stm32_gate ck_icn_p_tim15 = { + .gate_id = GATE_TIM15, + .hw.init = CLK_HW_INIT_INDEX("ck_icn_p_tim15", ICN_APB2, &clk_stm32_gate_ops, 0), +}; + +static struct clk_stm32_gate ck_icn_p_tim16 = { + .gate_id = GATE_TIM16, + .hw.init = CLK_HW_INIT_INDEX("ck_icn_p_tim16", ICN_APB2, &clk_stm32_gate_ops, 0), +}; + +static struct clk_stm32_gate ck_icn_p_tim17 = { + .gate_id = GATE_TIM17, + .hw.init = CLK_HW_INIT_INDEX("ck_icn_p_tim17", ICN_APB2, &clk_stm32_gate_ops, 0), +}; + +static struct clk_stm32_gate ck_icn_p_tim20 = { + .gate_id = GATE_TIM20, + .hw.init = CLK_HW_INIT_INDEX("ck_icn_p_tim20", ICN_APB2, &clk_stm32_gate_ops, 0), +}; + +static struct clk_stm32_gate ck_ker_tim2 = { + .gate_id = GATE_TIM2, + .hw.init = CLK_HW_INIT_INDEX("ck_ker_tim2", TIMG1, &clk_stm32_gate_ops, 0), +}; + +static struct clk_stm32_gate ck_ker_tim3 = { + .gate_id = GATE_TIM3, + .hw.init = CLK_HW_INIT_INDEX("ck_ker_tim3", TIMG1, &clk_stm32_gate_ops, 0), +}; + +static struct clk_stm32_gate ck_ker_tim4 = { + .gate_id = GATE_TIM4, + .hw.init = CLK_HW_INIT_INDEX("ck_ker_tim4", TIMG1, &clk_stm32_gate_ops, 0), +}; + +static struct clk_stm32_gate ck_ker_tim5 = { + .gate_id = GATE_TIM5, + .hw.init = CLK_HW_INIT_INDEX("ck_ker_tim5", TIMG1, &clk_stm32_gate_ops, 0), +}; + +static struct clk_stm32_gate ck_ker_tim6 = { + .gate_id = GATE_TIM6, + .hw.init = CLK_HW_INIT_INDEX("ck_ker_tim6", TIMG1, &clk_stm32_gate_ops, 0), +}; + +static struct clk_stm32_gate ck_ker_tim7 = { + .gate_id = GATE_TIM7, + .hw.init = CLK_HW_INIT_INDEX("ck_ker_tim7", TIMG1, &clk_stm32_gate_ops, 0), +}; + +static struct clk_stm32_gate ck_ker_tim10 = { + .gate_id = GATE_TIM10, + .hw.init = CLK_HW_INIT_INDEX("ck_ker_tim10", TIMG1, &clk_stm32_gate_ops, 0), +}; + +static struct clk_stm32_gate ck_ker_tim11 = { + .gate_id = GATE_TIM11, + .hw.init = CLK_HW_INIT_INDEX("ck_ker_tim11", TIMG1, &clk_stm32_gate_ops, 0), +}; + +static struct clk_stm32_gate ck_ker_tim12 = { + .gate_id = GATE_TIM12, + .hw.init = CLK_HW_INIT_INDEX("ck_ker_tim12", TIMG1, &clk_stm32_gate_ops, 0), +}; + +static struct clk_stm32_gate ck_ker_tim13 = { + .gate_id = GATE_TIM13, + .hw.init = CLK_HW_INIT_INDEX("ck_ker_tim13", TIMG1, &clk_stm32_gate_ops, 0), +}; + +static struct clk_stm32_gate ck_ker_tim14 = { + .gate_id = GATE_TIM14, + .hw.init = CLK_HW_INIT_INDEX("ck_ker_tim14", TIMG1, &clk_stm32_gate_ops, 0), +}; + +static struct clk_stm32_gate ck_ker_tim1 = { + .gate_id = GATE_TIM1, + .hw.init = CLK_HW_INIT_INDEX("ck_ker_tim1", TIMG2, &clk_stm32_gate_ops, 0), +}; + +static struct clk_stm32_gate ck_ker_tim8 = { + .gate_id = GATE_TIM8, + .hw.init = CLK_HW_INIT_INDEX("ck_ker_tim8", TIMG2, &clk_stm32_gate_ops, 0), +}; + +static struct clk_stm32_gate ck_ker_tim15 = { + .gate_id = GATE_TIM15, + .hw.init = CLK_HW_INIT_INDEX("ck_ker_tim15", TIMG2, &clk_stm32_gate_ops, 0), +}; + +static struct clk_stm32_gate ck_ker_tim16 = { + .gate_id = GATE_TIM16, + .hw.init = CLK_HW_INIT_INDEX("ck_ker_tim16", TIMG2, &clk_stm32_gate_ops, 0), +}; + +static struct clk_stm32_gate ck_ker_tim17 = { + .gate_id = GATE_TIM17, + .hw.init = CLK_HW_INIT_INDEX("ck_ker_tim17", TIMG2, &clk_stm32_gate_ops, 0), +}; + +static struct clk_stm32_gate ck_ker_tim20 = { + .gate_id = GATE_TIM20, + .hw.init = CLK_HW_INIT_INDEX("ck_ker_tim20", TIMG2, &clk_stm32_gate_ops, 0), +}; + +/* UART/USART */ +static struct clk_stm32_gate ck_icn_p_usart2 = { + .gate_id = GATE_USART2, + .hw.init = CLK_HW_INIT_INDEX("ck_icn_p_usart2", ICN_APB1, &clk_stm32_gate_ops, 0), +}; + +static struct clk_stm32_gate ck_icn_p_usart3 = { + .gate_id = GATE_USART3, + .hw.init = CLK_HW_INIT_INDEX("ck_icn_p_usart3", ICN_APB1, &clk_stm32_gate_ops, 0), +}; + +static struct clk_stm32_gate ck_icn_p_uart4 = { + .gate_id = GATE_UART4, + .hw.init = CLK_HW_INIT_INDEX("ck_icn_p_uart4", ICN_APB1, &clk_stm32_gate_ops, 0), +}; + +static struct clk_stm32_gate ck_icn_p_uart5 = { + .gate_id = GATE_UART5, + .hw.init = CLK_HW_INIT_INDEX("ck_icn_p_uart5", ICN_APB1, &clk_stm32_gate_ops, 0), +}; + +static struct clk_stm32_gate ck_icn_p_usart1 = { + .gate_id = GATE_USART1, + .hw.init = CLK_HW_INIT_INDEX("ck_icn_p_usart1", ICN_APB2, &clk_stm32_gate_ops, 0), +}; + +static struct clk_stm32_gate ck_icn_p_usart6 = { + .gate_id = GATE_USART6, + .hw.init = CLK_HW_INIT_INDEX("ck_icn_p_usart6", ICN_APB2, &clk_stm32_gate_ops, 0), +}; + +static struct clk_stm32_gate ck_icn_p_uart7 = { + .gate_id = GATE_UART7, + .hw.init = CLK_HW_INIT_INDEX("ck_icn_p_uart7", ICN_APB2, &clk_stm32_gate_ops, 0), +}; + +static struct clk_stm32_gate ck_icn_p_uart8 = { + .gate_id = GATE_UART8, + .hw.init = CLK_HW_INIT_INDEX("ck_icn_p_uart8", ICN_APB2, &clk_stm32_gate_ops, 0), +}; + +static struct clk_stm32_gate ck_icn_p_uart9 = { + .gate_id = GATE_UART9, + .hw.init = CLK_HW_INIT_INDEX("ck_icn_p_uart9", ICN_APB2, &clk_stm32_gate_ops, 0), +}; + +static struct clk_stm32_gate ck_ker_usart2 = { + .gate_id = GATE_USART2, + .hw.init = CLK_HW_INIT_INDEX("ck_ker_usart2", FLEXGEN_08, &clk_stm32_gate_ops, 0), +}; + +static struct clk_stm32_gate ck_ker_uart4 = { + .gate_id = GATE_UART4, + .hw.init = CLK_HW_INIT_INDEX("ck_ker_uart4", FLEXGEN_08, &clk_stm32_gate_ops, 0), +}; + +static struct clk_stm32_gate ck_ker_usart3 = { + .gate_id = GATE_USART3, + .hw.init = CLK_HW_INIT_INDEX("ck_ker_usart3", FLEXGEN_09, &clk_stm32_gate_ops, 0), +}; + +static struct clk_stm32_gate ck_ker_uart5 = { + .gate_id = GATE_UART5, + .hw.init = CLK_HW_INIT_INDEX("ck_ker_uart5", FLEXGEN_09, &clk_stm32_gate_ops, 0), +}; + +static struct clk_stm32_gate ck_ker_usart1 = { + .gate_id = GATE_USART1, + .hw.init = CLK_HW_INIT_INDEX("ck_ker_usart1", FLEXGEN_19, &clk_stm32_gate_ops, 0), +}; + +static struct clk_stm32_gate ck_ker_usart6 = { + .gate_id = GATE_USART6, + .hw.init = CLK_HW_INIT_INDEX("ck_ker_usart6", FLEXGEN_20, &clk_stm32_gate_ops, 0), +}; + +static struct clk_stm32_gate ck_ker_uart7 = { + .gate_id = GATE_UART7, + .hw.init = CLK_HW_INIT_INDEX("ck_ker_uart7", FLEXGEN_21, &clk_stm32_gate_ops, 0), +}; + +static struct clk_stm32_gate ck_ker_uart8 = { + .gate_id = GATE_UART8, + .hw.init = CLK_HW_INIT_INDEX("ck_ker_uart8", FLEXGEN_21, &clk_stm32_gate_ops, 0), +}; + +static struct clk_stm32_gate ck_ker_uart9 = { + .gate_id = GATE_UART9, + .hw.init = CLK_HW_INIT_INDEX("ck_ker_uart9", FLEXGEN_22, &clk_stm32_gate_ops, 0), +}; + +/* USB2PHY1 */ +static struct clk_stm32_composite ck_ker_usb2phy1 = { + .gate_id = GATE_USB2PHY1, + .mux_id = MUX_USB2PHY1, + .div_id = NO_STM32_DIV, + .hw.init = CLK_HW_INIT_PARENTS_DATA("ck_ker_usb2phy1", usb2phy1_src, + &clk_stm32_composite_ops, 0), +}; + +/* USB2H */ +static struct clk_stm32_gate ck_icn_m_usb2ehci = { + .gate_id = GATE_USBH, + .hw.init = CLK_HW_INIT_INDEX("ck_icn_m_usb2ehci", ICN_HSL, &clk_stm32_gate_ops, 0), +}; + +static struct clk_stm32_gate ck_icn_m_usb2ohci = { + .gate_id = GATE_USBH, + .hw.init = CLK_HW_INIT_INDEX("ck_icn_m_usb2ohci", ICN_HSL, &clk_stm32_gate_ops, 0), +}; + +/* USB2PHY2 */ +static struct clk_stm32_composite ck_ker_usb2phy2_en = { + .gate_id = GATE_USB2PHY2, + .mux_id = MUX_USB2PHY2, + .div_id = NO_STM32_DIV, + .hw.init = CLK_HW_INIT_PARENTS_DATA("ck_ker_usb2phy2_en", usb2phy2_src, + &clk_stm32_composite_ops, 0), +}; + +/* USB3 PCIe COMBOPHY */ +static struct clk_stm32_gate ck_icn_p_usb3pciephy = { + .gate_id = GATE_USB3PCIEPHY, + .hw.init = CLK_HW_INIT_INDEX("ck_icn_p_usb3pciephy", ICN_APB4, &clk_stm32_gate_ops, 0), +}; + +static struct clk_stm32_composite ck_ker_usb3pciephy = { + .gate_id = GATE_USB3PCIEPHY, + .mux_id = MUX_USB3PCIEPHY, + .div_id = NO_STM32_DIV, + .hw.init = CLK_HW_INIT_PARENTS_DATA("ck_ker_usb3pciephy", usb3pciphy_src, + &clk_stm32_composite_ops, 0), +}; + +/* USB3 DRD */ +static struct clk_stm32_gate ck_icn_m_usb3dr = { + .gate_id = GATE_USB3DR, + .hw.init = CLK_HW_INIT_INDEX("ck_icn_m_usb3dr", ICN_HSL, &clk_stm32_gate_ops, 0), +}; + +static struct clk_stm32_gate ck_ker_usb2phy2 = { + .gate_id = GATE_USB3DR, + .hw.init = CLK_HW_INIT_INDEX("ck_ker_usb2phy2", FLEXGEN_58, &clk_stm32_gate_ops, 0), +}; + +/* USBTC */ +static struct clk_stm32_gate ck_icn_p_usbtc = { + .gate_id = GATE_USBTC, + .hw.init = CLK_HW_INIT_INDEX("ck_icn_p_usbtc", ICN_APB4, &clk_stm32_gate_ops, 0), +}; + +static struct clk_stm32_gate ck_ker_usbtc = { + .gate_id = GATE_USBTC, + .hw.init = CLK_HW_INIT_INDEX("ck_ker_usbtc", FLEXGEN_35, &clk_stm32_gate_ops, 0), +}; + +/* VDEC / VENC */ +static struct clk_stm32_gate ck_icn_p_vdec = { + .gate_id = GATE_VDEC, + .hw.init = CLK_HW_INIT_INDEX("ck_icn_p_vdec", ICN_APB4, &clk_stm32_gate_ops, 0), +}; + +static struct clk_stm32_gate ck_icn_p_venc = { + .gate_id = GATE_VENC, + .hw.init = CLK_HW_INIT_INDEX("ck_icn_p_venc", ICN_APB4, &clk_stm32_gate_ops, 0), +}; + +/* VREF */ +static struct clk_stm32_gate ck_icn_p_vref = { + .gate_id = GATE_VREF, + .hw.init = CLK_HW_INIT_INDEX("ck_icn_p_vref", ICN_APB3, &clk_stm32_gate_ops, 0), +}; + +/* WWDG */ +static struct clk_stm32_gate ck_icn_p_wwdg1 = { + .gate_id = GATE_WWDG1, + .hw.init = CLK_HW_INIT_INDEX("ck_icn_p_wwdg1", ICN_APB3, &clk_stm32_gate_ops, 0), +}; + +static struct clk_stm32_gate ck_icn_p_wwdg2 = { + .gate_id = GATE_WWDG2, + .hw.init = CLK_HW_INIT_INDEX("ck_icn_p_wwdg2", ICN_LS_MCU, &clk_stm32_gate_ops, 0), +}; + +#define SECF_NONE -1 + +static const struct clock_config stm32mp25_clock_cfg[] = { + STM32_GATE_CFG(CK_BUS_ETH1, ck_icn_p_eth1, SECF_NONE), + STM32_GATE_CFG(CK_BUS_ETH2, ck_icn_p_eth2, SECF_NONE), + STM32_GATE_CFG(CK_BUS_PCIE, ck_icn_p_pcie, SECF_NONE), + STM32_GATE_CFG(CK_BUS_ETHSW, ck_icn_p_ethsw, SECF_NONE), + STM32_GATE_CFG(CK_BUS_ADC12, ck_icn_p_adc12, SECF_NONE), + STM32_GATE_CFG(CK_BUS_ADC3, ck_icn_p_adc3, SECF_NONE), + STM32_GATE_CFG(CK_BUS_CCI, ck_icn_p_cci, SECF_NONE), + STM32_GATE_CFG(CK_BUS_CRC, ck_icn_p_crc, SECF_NONE), + STM32_GATE_CFG(CK_BUS_MDF1, ck_icn_p_mdf1, SECF_NONE), + STM32_GATE_CFG(CK_BUS_OSPIIOM, ck_icn_p_ospiiom, SECF_NONE), + STM32_GATE_CFG(CK_BUS_HASH, ck_icn_p_hash, SECF_NONE), + STM32_GATE_CFG(CK_BUS_CRYP1, ck_icn_p_cryp1, SECF_NONE), + STM32_GATE_CFG(CK_BUS_CRYP2, ck_icn_p_cryp2, SECF_NONE), + STM32_GATE_CFG(CK_BUS_ADF1, ck_icn_p_adf1, SECF_NONE), + STM32_GATE_CFG(CK_BUS_SPI8, ck_icn_p_spi8, SECF_NONE), + STM32_GATE_CFG(CK_BUS_LPUART1, ck_icn_p_lpuart1, SECF_NONE), + STM32_GATE_CFG(CK_BUS_I2C8, ck_icn_p_i2c8, SECF_NONE), + STM32_GATE_CFG(CK_BUS_LPTIM3, ck_icn_p_lptim3, SECF_NONE), + STM32_GATE_CFG(CK_BUS_LPTIM4, ck_icn_p_lptim4, SECF_NONE), + STM32_GATE_CFG(CK_BUS_LPTIM5, ck_icn_p_lptim5, SECF_NONE), + STM32_GATE_CFG(CK_BUS_IWDG5, ck_icn_p_iwdg5, SECF_NONE), + STM32_GATE_CFG(CK_BUS_WWDG2, ck_icn_p_wwdg2, SECF_NONE), + STM32_GATE_CFG(CK_BUS_I3C4, ck_icn_p_i3c4, SECF_NONE), + STM32_GATE_CFG(CK_BUS_SDMMC1, ck_icn_m_sdmmc1, SECF_NONE), + STM32_GATE_CFG(CK_BUS_SDMMC2, ck_icn_m_sdmmc2, SECF_NONE), + STM32_GATE_CFG(CK_BUS_SDMMC3, ck_icn_m_sdmmc3, SECF_NONE), + STM32_GATE_CFG(CK_BUS_USB2OHCI, ck_icn_m_usb2ohci, SECF_NONE), + STM32_GATE_CFG(CK_BUS_USB2EHCI, ck_icn_m_usb2ehci, SECF_NONE), + STM32_GATE_CFG(CK_BUS_USB3DR, ck_icn_m_usb3dr, SECF_NONE), + STM32_GATE_CFG(CK_BUS_TIM2, ck_icn_p_tim2, SECF_NONE), + STM32_GATE_CFG(CK_BUS_TIM3, ck_icn_p_tim3, SECF_NONE), + STM32_GATE_CFG(CK_BUS_TIM4, ck_icn_p_tim4, SECF_NONE), + STM32_GATE_CFG(CK_BUS_TIM5, ck_icn_p_tim5, SECF_NONE), + STM32_GATE_CFG(CK_BUS_TIM6, ck_icn_p_tim6, SECF_NONE), + STM32_GATE_CFG(CK_BUS_TIM7, ck_icn_p_tim7, SECF_NONE), + STM32_GATE_CFG(CK_BUS_TIM10, ck_icn_p_tim10, SECF_NONE), + STM32_GATE_CFG(CK_BUS_TIM11, ck_icn_p_tim11, SECF_NONE), + STM32_GATE_CFG(CK_BUS_TIM12, ck_icn_p_tim12, SECF_NONE), + STM32_GATE_CFG(CK_BUS_TIM13, ck_icn_p_tim13, SECF_NONE), + STM32_GATE_CFG(CK_BUS_TIM14, ck_icn_p_tim14, SECF_NONE), + STM32_GATE_CFG(CK_BUS_LPTIM1, ck_icn_p_lptim1, SECF_NONE), + STM32_GATE_CFG(CK_BUS_LPTIM2, ck_icn_p_lptim2, SECF_NONE), + STM32_GATE_CFG(CK_BUS_SPI2, ck_icn_p_spi2, SECF_NONE), + STM32_GATE_CFG(CK_BUS_SPI3, ck_icn_p_spi3, SECF_NONE), + STM32_GATE_CFG(CK_BUS_SPDIFRX, ck_icn_p_spdifrx, SECF_NONE), + STM32_GATE_CFG(CK_BUS_USART2, ck_icn_p_usart2, SECF_NONE), + STM32_GATE_CFG(CK_BUS_USART3, ck_icn_p_usart3, SECF_NONE), + STM32_GATE_CFG(CK_BUS_UART4, ck_icn_p_uart4, SECF_NONE), + STM32_GATE_CFG(CK_BUS_UART5, ck_icn_p_uart5, SECF_NONE), + STM32_GATE_CFG(CK_BUS_I2C1, ck_icn_p_i2c1, SECF_NONE), + STM32_GATE_CFG(CK_BUS_I2C2, ck_icn_p_i2c2, SECF_NONE), + STM32_GATE_CFG(CK_BUS_I2C3, ck_icn_p_i2c3, SECF_NONE), + STM32_GATE_CFG(CK_BUS_I2C4, ck_icn_p_i2c4, SECF_NONE), + STM32_GATE_CFG(CK_BUS_I2C5, ck_icn_p_i2c5, SECF_NONE), + STM32_GATE_CFG(CK_BUS_I2C6, ck_icn_p_i2c6, SECF_NONE), + STM32_GATE_CFG(CK_BUS_I2C7, ck_icn_p_i2c7, SECF_NONE), + STM32_GATE_CFG(CK_BUS_I3C1, ck_icn_p_i3c1, SECF_NONE), + STM32_GATE_CFG(CK_BUS_I3C2, ck_icn_p_i3c2, SECF_NONE), + STM32_GATE_CFG(CK_BUS_I3C3, ck_icn_p_i3c3, SECF_NONE), + STM32_GATE_CFG(CK_BUS_TIM1, ck_icn_p_tim1, SECF_NONE), + STM32_GATE_CFG(CK_BUS_TIM8, ck_icn_p_tim8, SECF_NONE), + STM32_GATE_CFG(CK_BUS_TIM15, ck_icn_p_tim15, SECF_NONE), + STM32_GATE_CFG(CK_BUS_TIM16, ck_icn_p_tim16, SECF_NONE), + STM32_GATE_CFG(CK_BUS_TIM17, ck_icn_p_tim17, SECF_NONE), + STM32_GATE_CFG(CK_BUS_TIM20, ck_icn_p_tim20, SECF_NONE), + STM32_GATE_CFG(CK_BUS_SAI1, ck_icn_p_sai1, SECF_NONE), + STM32_GATE_CFG(CK_BUS_SAI2, ck_icn_p_sai2, SECF_NONE), + STM32_GATE_CFG(CK_BUS_SAI3, ck_icn_p_sai3, SECF_NONE), + STM32_GATE_CFG(CK_BUS_SAI4, ck_icn_p_sai4, SECF_NONE), + STM32_GATE_CFG(CK_BUS_USART1, ck_icn_p_usart1, SECF_NONE), + STM32_GATE_CFG(CK_BUS_USART6, ck_icn_p_usart6, SECF_NONE), + STM32_GATE_CFG(CK_BUS_UART7, ck_icn_p_uart7, SECF_NONE), + STM32_GATE_CFG(CK_BUS_UART8, ck_icn_p_uart8, SECF_NONE), + STM32_GATE_CFG(CK_BUS_UART9, ck_icn_p_uart9, SECF_NONE), + STM32_GATE_CFG(CK_BUS_FDCAN, ck_icn_p_fdcan, SECF_NONE), + STM32_GATE_CFG(CK_BUS_SPI1, ck_icn_p_spi1, SECF_NONE), + STM32_GATE_CFG(CK_BUS_SPI4, ck_icn_p_spi4, SECF_NONE), + STM32_GATE_CFG(CK_BUS_SPI5, ck_icn_p_spi5, SECF_NONE), + STM32_GATE_CFG(CK_BUS_SPI6, ck_icn_p_spi6, SECF_NONE), + STM32_GATE_CFG(CK_BUS_SPI7, ck_icn_p_spi7, SECF_NONE), + STM32_GATE_CFG(CK_BUS_IWDG2, ck_icn_p_iwdg2, SECF_NONE), + STM32_GATE_CFG(CK_BUS_IWDG3, ck_icn_p_iwdg3, SECF_NONE), + STM32_GATE_CFG(CK_BUS_IWDG4, ck_icn_p_iwdg4, SECF_NONE), + STM32_GATE_CFG(CK_BUS_WWDG1, ck_icn_p_wwdg1, SECF_NONE), + STM32_GATE_CFG(CK_BUS_VREF, ck_icn_p_vref, SECF_NONE), + STM32_GATE_CFG(CK_BUS_HDP, ck_icn_p_hdp, SECF_NONE), + STM32_GATE_CFG(CK_BUS_IS2M, ck_icn_p_is2m, SECF_NONE), + STM32_GATE_CFG(CK_BUS_DSI, ck_icn_p_dsi, SECF_NONE), + STM32_GATE_CFG(CK_BUS_LTDC, ck_icn_p_ltdc, SECF_NONE), + STM32_GATE_CFG(CK_BUS_CSI, ck_icn_p_csi, SECF_NONE), + STM32_GATE_CFG(CK_BUS_DCMIPP, ck_icn_p_dcmipp, SECF_NONE), + STM32_GATE_CFG(CK_BUS_LVDS, ck_icn_p_lvds, SECF_NONE), + STM32_GATE_CFG(CK_BUS_USBTC, ck_icn_p_usbtc, SECF_NONE), + STM32_GATE_CFG(CK_BUS_USB3PCIEPHY, ck_icn_p_usb3pciephy, SECF_NONE), + STM32_GATE_CFG(CK_BUS_VDEC, ck_icn_p_vdec, SECF_NONE), + STM32_GATE_CFG(CK_BUS_VENC, ck_icn_p_venc, SECF_NONE), + STM32_GATE_CFG(CK_KER_TIM2, ck_ker_tim2, SECF_NONE), + STM32_GATE_CFG(CK_KER_TIM3, ck_ker_tim3, SECF_NONE), + STM32_GATE_CFG(CK_KER_TIM4, ck_ker_tim4, SECF_NONE), + STM32_GATE_CFG(CK_KER_TIM5, ck_ker_tim5, SECF_NONE), + STM32_GATE_CFG(CK_KER_TIM6, ck_ker_tim6, SECF_NONE), + STM32_GATE_CFG(CK_KER_TIM7, ck_ker_tim7, SECF_NONE), + STM32_GATE_CFG(CK_KER_TIM10, ck_ker_tim10, SECF_NONE), + STM32_GATE_CFG(CK_KER_TIM11, ck_ker_tim11, SECF_NONE), + STM32_GATE_CFG(CK_KER_TIM12, ck_ker_tim12, SECF_NONE), + STM32_GATE_CFG(CK_KER_TIM13, ck_ker_tim13, SECF_NONE), + STM32_GATE_CFG(CK_KER_TIM14, ck_ker_tim14, SECF_NONE), + STM32_GATE_CFG(CK_KER_TIM1, ck_ker_tim1, SECF_NONE), + STM32_GATE_CFG(CK_KER_TIM8, ck_ker_tim8, SECF_NONE), + STM32_GATE_CFG(CK_KER_TIM15, ck_ker_tim15, SECF_NONE), + STM32_GATE_CFG(CK_KER_TIM16, ck_ker_tim16, SECF_NONE), + STM32_GATE_CFG(CK_KER_TIM17, ck_ker_tim17, SECF_NONE), + STM32_GATE_CFG(CK_KER_TIM20, ck_ker_tim20, SECF_NONE), + STM32_GATE_CFG(CK_KER_LPTIM1, ck_ker_lptim1, SECF_NONE), + STM32_GATE_CFG(CK_KER_LPTIM2, ck_ker_lptim2, SECF_NONE), + STM32_GATE_CFG(CK_KER_USART2, ck_ker_usart2, SECF_NONE), + STM32_GATE_CFG(CK_KER_UART4, ck_ker_uart4, SECF_NONE), + STM32_GATE_CFG(CK_KER_USART3, ck_ker_usart3, SECF_NONE), + STM32_GATE_CFG(CK_KER_UART5, ck_ker_uart5, SECF_NONE), + STM32_GATE_CFG(CK_KER_SPI2, ck_ker_spi2, SECF_NONE), + STM32_GATE_CFG(CK_KER_SPI3, ck_ker_spi3, SECF_NONE), + STM32_GATE_CFG(CK_KER_SPDIFRX, ck_ker_spdifrx, SECF_NONE), + STM32_GATE_CFG(CK_KER_I2C1, ck_ker_i2c1, SECF_NONE), + STM32_GATE_CFG(CK_KER_I2C2, ck_ker_i2c2, SECF_NONE), + STM32_GATE_CFG(CK_KER_I3C1, ck_ker_i3c1, SECF_NONE), + STM32_GATE_CFG(CK_KER_I3C2, ck_ker_i3c2, SECF_NONE), + STM32_GATE_CFG(CK_KER_I2C3, ck_ker_i2c3, SECF_NONE), + STM32_GATE_CFG(CK_KER_I2C5, ck_ker_i2c5, SECF_NONE), + STM32_GATE_CFG(CK_KER_I3C3, ck_ker_i3c3, SECF_NONE), + STM32_GATE_CFG(CK_KER_I2C4, ck_ker_i2c4, SECF_NONE), + STM32_GATE_CFG(CK_KER_I2C6, ck_ker_i2c6, SECF_NONE), + STM32_GATE_CFG(CK_KER_I2C7, ck_ker_i2c7, SECF_NONE), + STM32_GATE_CFG(CK_KER_SPI1, ck_ker_spi1, SECF_NONE), + STM32_GATE_CFG(CK_KER_SPI4, ck_ker_spi4, SECF_NONE), + STM32_GATE_CFG(CK_KER_SPI5, ck_ker_spi5, SECF_NONE), + STM32_GATE_CFG(CK_KER_SPI6, ck_ker_spi6, SECF_NONE), + STM32_GATE_CFG(CK_KER_SPI7, ck_ker_spi7, SECF_NONE), + STM32_GATE_CFG(CK_KER_USART1, ck_ker_usart1, SECF_NONE), + STM32_GATE_CFG(CK_KER_USART6, ck_ker_usart6, SECF_NONE), + STM32_GATE_CFG(CK_KER_UART7, ck_ker_uart7, SECF_NONE), + STM32_GATE_CFG(CK_KER_UART8, ck_ker_uart8, SECF_NONE), + STM32_GATE_CFG(CK_KER_UART9, ck_ker_uart9, SECF_NONE), + STM32_GATE_CFG(CK_KER_MDF1, ck_ker_mdf1, SECF_NONE), + STM32_GATE_CFG(CK_KER_SAI1, ck_ker_sai1, SECF_NONE), + STM32_GATE_CFG(CK_KER_SAI2, ck_ker_sai2, SECF_NONE), + STM32_GATE_CFG(CK_KER_SAI3, ck_ker_sai3, SECF_NONE), + STM32_GATE_CFG(CK_KER_SAI4, ck_ker_sai4, SECF_NONE), + STM32_GATE_CFG(CK_KER_FDCAN, ck_ker_fdcan, SECF_NONE), + STM32_GATE_CFG(CK_KER_CSI, ck_ker_csi, SECF_NONE), + STM32_GATE_CFG(CK_KER_CSITXESC, ck_ker_csitxesc, SECF_NONE), + STM32_GATE_CFG(CK_KER_CSIPHY, ck_ker_csiphy, SECF_NONE), + STM32_GATE_CFG(CK_KER_USBTC, ck_ker_usbtc, SECF_NONE), + STM32_GATE_CFG(CK_KER_I3C4, ck_ker_i3c4, SECF_NONE), + STM32_GATE_CFG(CK_KER_SPI8, ck_ker_spi8, SECF_NONE), + STM32_GATE_CFG(CK_KER_I2C8, ck_ker_i2c8, SECF_NONE), + STM32_GATE_CFG(CK_KER_LPUART1, ck_ker_lpuart1, SECF_NONE), + STM32_GATE_CFG(CK_KER_LPTIM3, ck_ker_lptim3, SECF_NONE), + STM32_GATE_CFG(CK_KER_LPTIM4, ck_ker_lptim4, SECF_NONE), + STM32_GATE_CFG(CK_KER_LPTIM5, ck_ker_lptim5, SECF_NONE), + STM32_GATE_CFG(CK_KER_ADF1, ck_ker_adf1, SECF_NONE), + STM32_GATE_CFG(CK_KER_SDMMC1, ck_ker_sdmmc1, SECF_NONE), + STM32_GATE_CFG(CK_KER_SDMMC2, ck_ker_sdmmc2, SECF_NONE), + STM32_GATE_CFG(CK_KER_SDMMC3, ck_ker_sdmmc3, SECF_NONE), + STM32_GATE_CFG(CK_KER_ETH1, ck_ker_eth1, SECF_NONE), + STM32_GATE_CFG(CK_ETH1_STP, ck_ker_eth1stp, SECF_NONE), + STM32_GATE_CFG(CK_KER_ETHSW, ck_ker_ethsw, SECF_NONE), + STM32_GATE_CFG(CK_KER_ETH2, ck_ker_eth2, SECF_NONE), + STM32_GATE_CFG(CK_ETH2_STP, ck_ker_eth2stp, SECF_NONE), + STM32_GATE_CFG(CK_KER_ETH1PTP, ck_ker_eth1ptp, SECF_NONE), + STM32_GATE_CFG(CK_KER_ETH2PTP, ck_ker_eth2ptp, SECF_NONE), + STM32_GATE_CFG(CK_BUS_GPU, ck_icn_m_gpu, SECF_NONE), + STM32_GATE_CFG(CK_KER_GPU, ck_ker_gpu, SECF_NONE), + STM32_GATE_CFG(CK_KER_ETHSWREF, ck_ker_ethswref, SECF_NONE), + STM32_GATE_CFG(CK_BUS_ETHSWACMCFG, ck_icn_p_ethsw_acm_cfg, SECF_NONE), + STM32_GATE_CFG(CK_BUS_ETHSWACMMSG, ck_icn_p_ethsw_acm_msg, SECF_NONE), + STM32_GATE_CFG(CK_ETH1_MAC, ck_ker_eth1mac, SECF_NONE), + STM32_GATE_CFG(CK_ETH1_TX, ck_ker_eth1tx, SECF_NONE), + STM32_GATE_CFG(CK_ETH1_RX, ck_ker_eth1rx, SECF_NONE), + STM32_GATE_CFG(CK_ETH2_MAC, ck_ker_eth2mac, SECF_NONE), + STM32_GATE_CFG(CK_ETH2_TX, ck_ker_eth2tx, SECF_NONE), + STM32_GATE_CFG(CK_ETH2_RX, ck_ker_eth2rx, SECF_NONE), + STM32_COMPOSITE_CFG(CK_MCO1, ck_mco1, SECF_NONE), + STM32_COMPOSITE_CFG(CK_MCO2, ck_mco2, SECF_NONE), + STM32_COMPOSITE_CFG(CK_KER_ADC12, ck_ker_adc12, SECF_NONE), + STM32_COMPOSITE_CFG(CK_KER_ADC3, ck_ker_adc3, SECF_NONE), + STM32_COMPOSITE_CFG(CK_KER_USB2PHY1, ck_ker_usb2phy1, SECF_NONE), + STM32_GATE_CFG(CK_KER_USB2PHY2, ck_ker_usb2phy2, SECF_NONE), + STM32_COMPOSITE_CFG(CK_KER_USB2PHY2EN, ck_ker_usb2phy2_en, SECF_NONE), + STM32_COMPOSITE_CFG(CK_KER_USB3PCIEPHY, ck_ker_usb3pciephy, SECF_NONE), + STM32_COMPOSITE_CFG(CK_KER_DSIBLANE, clk_lanebyte, SECF_NONE), + STM32_COMPOSITE_CFG(CK_KER_DSIPHY, clk_phy_dsi, SECF_NONE), + STM32_COMPOSITE_CFG(CK_KER_LVDSPHY, ck_ker_lvdsphy, SECF_NONE), + STM32_COMPOSITE_CFG(CK_KER_DTS, ck_ker_dts, SECF_NONE), + STM32_GATE_CFG(CK_KER_LTDC, ck_ker_ltdc, SECF_NONE), +}; + +#define RESET_MP25(id, _offset, _bit_idx, _set_clr) \ + [id] = &(struct stm32_reset_cfg){ \ + .offset = (_offset), \ + .bit_idx = (_bit_idx), \ + .set_clr = (_set_clr), \ + } + +static const struct stm32_reset_cfg *stm32mp25_reset_cfg[STM32MP25_LAST_RESET] = { + RESET_MP25(TIM1_R, RCC_TIM1CFGR, 0, 0), + RESET_MP25(TIM2_R, RCC_TIM2CFGR, 0, 0), + RESET_MP25(TIM3_R, RCC_TIM3CFGR, 0, 0), + RESET_MP25(TIM4_R, RCC_TIM4CFGR, 0, 0), + RESET_MP25(TIM5_R, RCC_TIM5CFGR, 0, 0), + RESET_MP25(TIM6_R, RCC_TIM6CFGR, 0, 0), + RESET_MP25(TIM7_R, RCC_TIM7CFGR, 0, 0), + RESET_MP25(TIM8_R, RCC_TIM8CFGR, 0, 0), + RESET_MP25(TIM10_R, RCC_TIM10CFGR, 0, 0), + RESET_MP25(TIM11_R, RCC_TIM11CFGR, 0, 0), + RESET_MP25(TIM12_R, RCC_TIM12CFGR, 0, 0), + RESET_MP25(TIM13_R, RCC_TIM13CFGR, 0, 0), + RESET_MP25(TIM14_R, RCC_TIM14CFGR, 0, 0), + RESET_MP25(TIM15_R, RCC_TIM15CFGR, 0, 0), + RESET_MP25(TIM16_R, RCC_TIM16CFGR, 0, 0), + RESET_MP25(TIM17_R, RCC_TIM17CFGR, 0, 0), + RESET_MP25(TIM20_R, RCC_TIM20CFGR, 0, 0), + RESET_MP25(LPTIM1_R, RCC_LPTIM1CFGR, 0, 0), + RESET_MP25(LPTIM2_R, RCC_LPTIM2CFGR, 0, 0), + RESET_MP25(LPTIM3_R, RCC_LPTIM3CFGR, 0, 0), + RESET_MP25(LPTIM4_R, RCC_LPTIM4CFGR, 0, 0), + RESET_MP25(LPTIM5_R, RCC_LPTIM5CFGR, 0, 0), + RESET_MP25(SPI1_R, RCC_SPI1CFGR, 0, 0), + RESET_MP25(SPI2_R, RCC_SPI2CFGR, 0, 0), + RESET_MP25(SPI3_R, RCC_SPI3CFGR, 0, 0), + RESET_MP25(SPI4_R, RCC_SPI4CFGR, 0, 0), + RESET_MP25(SPI5_R, RCC_SPI5CFGR, 0, 0), + RESET_MP25(SPI6_R, RCC_SPI6CFGR, 0, 0), + RESET_MP25(SPI7_R, RCC_SPI7CFGR, 0, 0), + RESET_MP25(SPI8_R, RCC_SPI8CFGR, 0, 0), + RESET_MP25(SPDIFRX_R, RCC_SPDIFRXCFGR, 0, 0), + RESET_MP25(USART1_R, RCC_USART1CFGR, 0, 0), + RESET_MP25(USART2_R, RCC_USART2CFGR, 0, 0), + RESET_MP25(USART3_R, RCC_USART3CFGR, 0, 0), + RESET_MP25(UART4_R, RCC_UART4CFGR, 0, 0), + RESET_MP25(UART5_R, RCC_UART5CFGR, 0, 0), + RESET_MP25(USART6_R, RCC_USART6CFGR, 0, 0), + RESET_MP25(UART7_R, RCC_UART7CFGR, 0, 0), + RESET_MP25(UART8_R, RCC_UART8CFGR, 0, 0), + RESET_MP25(UART9_R, RCC_UART9CFGR, 0, 0), + RESET_MP25(LPUART1_R, RCC_LPUART1CFGR, 0, 0), + RESET_MP25(IS2M_R, RCC_IS2MCFGR, 0, 0), + RESET_MP25(I2C1_R, RCC_I2C1CFGR, 0, 0), + RESET_MP25(I2C2_R, RCC_I2C2CFGR, 0, 0), + RESET_MP25(I2C3_R, RCC_I2C3CFGR, 0, 0), + RESET_MP25(I2C4_R, RCC_I2C4CFGR, 0, 0), + RESET_MP25(I2C5_R, RCC_I2C5CFGR, 0, 0), + RESET_MP25(I2C6_R, RCC_I2C6CFGR, 0, 0), + RESET_MP25(I2C7_R, RCC_I2C7CFGR, 0, 0), + RESET_MP25(I2C8_R, RCC_I2C8CFGR, 0, 0), + RESET_MP25(SAI1_R, RCC_SAI1CFGR, 0, 0), + RESET_MP25(SAI2_R, RCC_SAI2CFGR, 0, 0), + RESET_MP25(SAI3_R, RCC_SAI3CFGR, 0, 0), + RESET_MP25(SAI4_R, RCC_SAI4CFGR, 0, 0), + RESET_MP25(MDF1_R, RCC_MDF1CFGR, 0, 0), + RESET_MP25(MDF2_R, RCC_ADF1CFGR, 0, 0), + RESET_MP25(FDCAN_R, RCC_FDCANCFGR, 0, 0), + RESET_MP25(HDP_R, RCC_HDPCFGR, 0, 0), + RESET_MP25(ADC12_R, RCC_ADC12CFGR, 0, 0), + RESET_MP25(ADC3_R, RCC_ADC3CFGR, 0, 0), + RESET_MP25(ETH1_R, RCC_ETH1CFGR, 0, 0), + RESET_MP25(ETH2_R, RCC_ETH2CFGR, 0, 0), + RESET_MP25(USBH_R, RCC_USBHCFGR, 0, 0), + RESET_MP25(USB2PHY1_R, RCC_USB2PHY1CFGR, 0, 0), + RESET_MP25(USB2PHY2_R, RCC_USB2PHY2CFGR, 0, 0), + RESET_MP25(USB3DR_R, RCC_USB3DRCFGR, 0, 0), + RESET_MP25(USB3PCIEPHY_R, RCC_USB3PCIEPHYCFGR, 0, 0), + RESET_MP25(USBTC_R, RCC_USBTCCFGR, 0, 0), + RESET_MP25(ETHSW_R, RCC_ETHSWCFGR, 0, 0), + RESET_MP25(SDMMC1_R, RCC_SDMMC1CFGR, 0, 0), + RESET_MP25(SDMMC1DLL_R, RCC_SDMMC1CFGR, 16, 0), + RESET_MP25(SDMMC2_R, RCC_SDMMC2CFGR, 0, 0), + RESET_MP25(SDMMC2DLL_R, RCC_SDMMC2CFGR, 16, 0), + RESET_MP25(SDMMC3_R, RCC_SDMMC3CFGR, 0, 0), + RESET_MP25(SDMMC3DLL_R, RCC_SDMMC3CFGR, 16, 0), + RESET_MP25(GPU_R, RCC_GPUCFGR, 0, 0), + RESET_MP25(LTDC_R, RCC_LTDCCFGR, 0, 0), + RESET_MP25(DSI_R, RCC_DSICFGR, 0, 0), + RESET_MP25(LVDS_R, RCC_LVDSCFGR, 0, 0), + RESET_MP25(CSI_R, RCC_CSICFGR, 0, 0), + RESET_MP25(DCMIPP_R, RCC_DCMIPPCFGR, 0, 0), + RESET_MP25(CCI_R, RCC_CCICFGR, 0, 0), + RESET_MP25(VDEC_R, RCC_VDECCFGR, 0, 0), + RESET_MP25(VENC_R, RCC_VENCCFGR, 0, 0), + RESET_MP25(WWDG1_R, RCC_WWDG1CFGR, 0, 0), + RESET_MP25(WWDG2_R, RCC_WWDG2CFGR, 0, 0), + RESET_MP25(VREF_R, RCC_VREFCFGR, 0, 0), + RESET_MP25(DTS_R, RCC_DTSCFGR, 0, 0), + RESET_MP25(CRC_R, RCC_CRCCFGR, 0, 0), + RESET_MP25(SERC_R, RCC_SERCCFGR, 0, 0), + RESET_MP25(OSPIIOM_R, RCC_OSPIIOMCFGR, 0, 0), + RESET_MP25(I3C1_R, RCC_I3C1CFGR, 0, 0), + RESET_MP25(I3C2_R, RCC_I3C2CFGR, 0, 0), + RESET_MP25(I3C3_R, RCC_I3C3CFGR, 0, 0), + RESET_MP25(I3C4_R, RCC_I3C4CFGR, 0, 0), + RESET_MP25(IWDG2_KER_R, RCC_IWDGC1CFGSETR, 18, 1), + RESET_MP25(IWDG4_KER_R, RCC_IWDGC2CFGSETR, 18, 1), + RESET_MP25(RNG_R, RCC_RNGCFGR, 0, 0), + RESET_MP25(PKA_R, RCC_PKACFGR, 0, 0), + RESET_MP25(SAES_R, RCC_SAESCFGR, 0, 0), + RESET_MP25(HASH_R, RCC_HASHCFGR, 0, 0), + RESET_MP25(CRYP1_R, RCC_CRYP1CFGR, 0, 0), + RESET_MP25(CRYP2_R, RCC_CRYP2CFGR, 0, 0), + RESET_MP25(PCIE_R, RCC_PCIECFGR, 0, 0), +}; + +static u16 stm32mp25_cpt_gate[GATE_NB]; + +static struct clk_stm32_clock_data stm32mp25_clock_data = { + .gate_cpt = stm32mp25_cpt_gate, + .gates = stm32mp25_gates, + .muxes = stm32mp25_muxes, +}; + +static struct clk_stm32_reset_data stm32mp25_reset_data = { + .reset_lines = stm32mp25_reset_cfg, + .nr_lines = ARRAY_SIZE(stm32mp25_reset_cfg), +}; + +static const struct stm32_rcc_match_data stm32mp25_data = { + .tab_clocks = stm32mp25_clock_cfg, + .num_clocks = ARRAY_SIZE(stm32mp25_clock_cfg), + .maxbinding = STM32MP25_LAST_CLK, + .clock_data = &stm32mp25_clock_data, + .reset_data = &stm32mp25_reset_data, +}; + +static const struct of_device_id stm32mp25_match_data[] = { + { .compatible = "st,stm32mp25-rcc", .data = &stm32mp25_data, }, + { } +}; +MODULE_DEVICE_TABLE(of, stm32mp25_match_data); + +static int stm32mp25_rcc_clocks_probe(struct platform_device *pdev) +{ + struct device *dev = &pdev->dev; + void __iomem *base; + + base = devm_platform_ioremap_resource(pdev, 0); + if (IS_ERR(base)) + return PTR_ERR(base); + + return stm32_rcc_init(dev, stm32mp25_match_data, base); +} + +static struct platform_driver stm32mp25_rcc_clocks_driver = { + .driver = { + .name = "stm32mp25_rcc", + .of_match_table = stm32mp25_match_data, + }, + .probe = stm32mp25_rcc_clocks_probe, +}; + +static int __init stm32mp25_clocks_init(void) +{ + return platform_driver_register(&stm32mp25_rcc_clocks_driver); +} + +core_initcall(stm32mp25_clocks_init); diff --git a/drivers/clk/stm32/reset-stm32.c b/drivers/clk/stm32/reset-stm32.c index 14c2ee1eebee..5a8f525842ce 100644 --- a/drivers/clk/stm32/reset-stm32.c +++ b/drivers/clk/stm32/reset-stm32.c @@ -19,6 +19,7 @@ struct stm32_reset_data { struct reset_controller_dev rcdev; void __iomem *membase; u32 clear_offset; + const struct stm32_reset_cfg **reset_lines; }; static inline struct stm32_reset_data * @@ -27,22 +28,46 @@ to_stm32_reset_data(struct reset_controller_dev *rcdev) return container_of(rcdev, struct stm32_reset_data, rcdev); } +static const struct stm32_reset_cfg *stm32_get_reset_line(struct reset_controller_dev *rcdev, + unsigned long id, + struct stm32_reset_cfg *line) +{ + struct stm32_reset_data *data = to_stm32_reset_data(rcdev); + + if (!data->reset_lines) { + int reg_width = sizeof(u32); + int bank = id / (reg_width * BITS_PER_BYTE); + int offset = id % (reg_width * BITS_PER_BYTE); + + line->offset = bank * reg_width; + line->bit_idx = offset; + line->set_clr = (data->clear_offset ? true : false); + + return line; + } + + return data->reset_lines[id]; +} + static int stm32_reset_update(struct reset_controller_dev *rcdev, unsigned long id, bool assert) { struct stm32_reset_data *data = to_stm32_reset_data(rcdev); - int reg_width = sizeof(u32); - int bank = id / (reg_width * BITS_PER_BYTE); - int offset = id % (reg_width * BITS_PER_BYTE); + struct stm32_reset_cfg line_reset; + const struct stm32_reset_cfg *ptr_line; - if (data->clear_offset) { + ptr_line = stm32_get_reset_line(rcdev, id, &line_reset); + if (!ptr_line) + return -EPERM; + + if (ptr_line->set_clr) { void __iomem *addr; - addr = data->membase + (bank * reg_width); + addr = data->membase + ptr_line->offset; if (!assert) addr += data->clear_offset; - writel(BIT(offset), addr); + writel(BIT(ptr_line->bit_idx), addr); } else { unsigned long flags; @@ -50,14 +75,14 @@ static int stm32_reset_update(struct reset_controller_dev *rcdev, spin_lock_irqsave(&data->lock, flags); - reg = readl(data->membase + (bank * reg_width)); + reg = readl(data->membase + ptr_line->offset); if (assert) - reg |= BIT(offset); + reg |= BIT(ptr_line->bit_idx); else - reg &= ~BIT(offset); + reg &= ~BIT(ptr_line->bit_idx); - writel(reg, data->membase + (bank * reg_width)); + writel(reg, data->membase + ptr_line->offset); spin_unlock_irqrestore(&data->lock, flags); } @@ -81,14 +106,17 @@ static int stm32_reset_status(struct reset_controller_dev *rcdev, unsigned long id) { struct stm32_reset_data *data = to_stm32_reset_data(rcdev); - int reg_width = sizeof(u32); - int bank = id / (reg_width * BITS_PER_BYTE); - int offset = id % (reg_width * BITS_PER_BYTE); + struct stm32_reset_cfg line_reset; + const struct stm32_reset_cfg *ptr_line; u32 reg; - reg = readl(data->membase + (bank * reg_width)); + ptr_line = stm32_get_reset_line(rcdev, id, &line_reset); + if (!ptr_line) + return -EPERM; - return !!(reg & BIT(offset)); + reg = readl(data->membase + ptr_line->offset); + + return !!(reg & BIT(ptr_line->bit_idx)); } static const struct reset_control_ops stm32_reset_ops = { @@ -113,6 +141,7 @@ int stm32_rcc_reset_init(struct device *dev, struct clk_stm32_reset_data *data, reset_data->rcdev.ops = &stm32_reset_ops; reset_data->rcdev.of_node = dev_of_node(dev); reset_data->rcdev.nr_resets = data->nr_lines; + reset_data->reset_lines = data->reset_lines; reset_data->clear_offset = data->clear_offset; return reset_controller_register(&reset_data->rcdev); diff --git a/drivers/clk/stm32/reset-stm32.h b/drivers/clk/stm32/reset-stm32.h index 8cf1cc9be480..f79cad21dfd6 100644 --- a/drivers/clk/stm32/reset-stm32.h +++ b/drivers/clk/stm32/reset-stm32.h @@ -4,8 +4,15 @@ * Author: Gabriel Fernandez for STMicroelectronics. */ +struct stm32_reset_cfg { + u16 offset; + u8 bit_idx; + bool set_clr; +}; + struct clk_stm32_reset_data { const struct reset_control_ops *ops; + const struct stm32_reset_cfg **reset_lines; unsigned int nr_lines; u32 clear_offset; }; diff --git a/drivers/clk/stm32/stm32mp25_rcc.h b/drivers/clk/stm32/stm32mp25_rcc.h new file mode 100644 index 000000000000..687bc6a78627 --- /dev/null +++ b/drivers/clk/stm32/stm32mp25_rcc.h @@ -0,0 +1,712 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * Copyright (C) STMicroelectronics 2023 - All Rights Reserved + * Author: Gabriel Fernandez for STMicroelectronics. + */ + +#ifndef STM32MP25_RCC_H +#define STM32MP25_RCC_H + +#define RCC_SECCFGR0 0x0 +#define RCC_SECCFGR1 0x4 +#define RCC_SECCFGR2 0x8 +#define RCC_SECCFGR3 0xC +#define RCC_PRIVCFGR0 0x10 +#define RCC_PRIVCFGR1 0x14 +#define RCC_PRIVCFGR2 0x18 +#define RCC_PRIVCFGR3 0x1C +#define RCC_RCFGLOCKR0 0x20 +#define RCC_RCFGLOCKR1 0x24 +#define RCC_RCFGLOCKR2 0x28 +#define RCC_RCFGLOCKR3 0x2C +#define RCC_R0CIDCFGR 0x30 +#define RCC_R0SEMCR 0x34 +#define RCC_R1CIDCFGR 0x38 +#define RCC_R1SEMCR 0x3C +#define RCC_R2CIDCFGR 0x40 +#define RCC_R2SEMCR 0x44 +#define RCC_R3CIDCFGR 0x48 +#define RCC_R3SEMCR 0x4C +#define RCC_R4CIDCFGR 0x50 +#define RCC_R4SEMCR 0x54 +#define RCC_R5CIDCFGR 0x58 +#define RCC_R5SEMCR 0x5C +#define RCC_R6CIDCFGR 0x60 +#define RCC_R6SEMCR 0x64 +#define RCC_R7CIDCFGR 0x68 +#define RCC_R7SEMCR 0x6C +#define RCC_R8CIDCFGR 0x70 +#define RCC_R8SEMCR 0x74 +#define RCC_R9CIDCFGR 0x78 +#define RCC_R9SEMCR 0x7C +#define RCC_R10CIDCFGR 0x80 +#define RCC_R10SEMCR 0x84 +#define RCC_R11CIDCFGR 0x88 +#define RCC_R11SEMCR 0x8C +#define RCC_R12CIDCFGR 0x90 +#define RCC_R12SEMCR 0x94 +#define RCC_R13CIDCFGR 0x98 +#define RCC_R13SEMCR 0x9C +#define RCC_R14CIDCFGR 0xA0 +#define RCC_R14SEMCR 0xA4 +#define RCC_R15CIDCFGR 0xA8 +#define RCC_R15SEMCR 0xAC +#define RCC_R16CIDCFGR 0xB0 +#define RCC_R16SEMCR 0xB4 +#define RCC_R17CIDCFGR 0xB8 +#define RCC_R17SEMCR 0xBC +#define RCC_R18CIDCFGR 0xC0 +#define RCC_R18SEMCR 0xC4 +#define RCC_R19CIDCFGR 0xC8 +#define RCC_R19SEMCR 0xCC +#define RCC_R20CIDCFGR 0xD0 +#define RCC_R20SEMCR 0xD4 +#define RCC_R21CIDCFGR 0xD8 +#define RCC_R21SEMCR 0xDC +#define RCC_R22CIDCFGR 0xE0 +#define RCC_R22SEMCR 0xE4 +#define RCC_R23CIDCFGR 0xE8 +#define RCC_R23SEMCR 0xEC +#define RCC_R24CIDCFGR 0xF0 +#define RCC_R24SEMCR 0xF4 +#define RCC_R25CIDCFGR 0xF8 +#define RCC_R25SEMCR 0xFC +#define RCC_R26CIDCFGR 0x100 +#define RCC_R26SEMCR 0x104 +#define RCC_R27CIDCFGR 0x108 +#define RCC_R27SEMCR 0x10C +#define RCC_R28CIDCFGR 0x110 +#define RCC_R28SEMCR 0x114 +#define RCC_R29CIDCFGR 0x118 +#define RCC_R29SEMCR 0x11C +#define RCC_R30CIDCFGR 0x120 +#define RCC_R30SEMCR 0x124 +#define RCC_R31CIDCFGR 0x128 +#define RCC_R31SEMCR 0x12C +#define RCC_R32CIDCFGR 0x130 +#define RCC_R32SEMCR 0x134 +#define RCC_R33CIDCFGR 0x138 +#define RCC_R33SEMCR 0x13C +#define RCC_R34CIDCFGR 0x140 +#define RCC_R34SEMCR 0x144 +#define RCC_R35CIDCFGR 0x148 +#define RCC_R35SEMCR 0x14C +#define RCC_R36CIDCFGR 0x150 +#define RCC_R36SEMCR 0x154 +#define RCC_R37CIDCFGR 0x158 +#define RCC_R37SEMCR 0x15C +#define RCC_R38CIDCFGR 0x160 +#define RCC_R38SEMCR 0x164 +#define RCC_R39CIDCFGR 0x168 +#define RCC_R39SEMCR 0x16C +#define RCC_R40CIDCFGR 0x170 +#define RCC_R40SEMCR 0x174 +#define RCC_R41CIDCFGR 0x178 +#define RCC_R41SEMCR 0x17C +#define RCC_R42CIDCFGR 0x180 +#define RCC_R42SEMCR 0x184 +#define RCC_R43CIDCFGR 0x188 +#define RCC_R43SEMCR 0x18C +#define RCC_R44CIDCFGR 0x190 +#define RCC_R44SEMCR 0x194 +#define RCC_R45CIDCFGR 0x198 +#define RCC_R45SEMCR 0x19C +#define RCC_R46CIDCFGR 0x1A0 +#define RCC_R46SEMCR 0x1A4 +#define RCC_R47CIDCFGR 0x1A8 +#define RCC_R47SEMCR 0x1AC +#define RCC_R48CIDCFGR 0x1B0 +#define RCC_R48SEMCR 0x1B4 +#define RCC_R49CIDCFGR 0x1B8 +#define RCC_R49SEMCR 0x1BC +#define RCC_R50CIDCFGR 0x1C0 +#define RCC_R50SEMCR 0x1C4 +#define RCC_R51CIDCFGR 0x1C8 +#define RCC_R51SEMCR 0x1CC +#define RCC_R52CIDCFGR 0x1D0 +#define RCC_R52SEMCR 0x1D4 +#define RCC_R53CIDCFGR 0x1D8 +#define RCC_R53SEMCR 0x1DC +#define RCC_R54CIDCFGR 0x1E0 +#define RCC_R54SEMCR 0x1E4 +#define RCC_R55CIDCFGR 0x1E8 +#define RCC_R55SEMCR 0x1EC +#define RCC_R56CIDCFGR 0x1F0 +#define RCC_R56SEMCR 0x1F4 +#define RCC_R57CIDCFGR 0x1F8 +#define RCC_R57SEMCR 0x1FC +#define RCC_R58CIDCFGR 0x200 +#define RCC_R58SEMCR 0x204 +#define RCC_R59CIDCFGR 0x208 +#define RCC_R59SEMCR 0x20C +#define RCC_R60CIDCFGR 0x210 +#define RCC_R60SEMCR 0x214 +#define RCC_R61CIDCFGR 0x218 +#define RCC_R61SEMCR 0x21C +#define RCC_R62CIDCFGR 0x220 +#define RCC_R62SEMCR 0x224 +#define RCC_R63CIDCFGR 0x228 +#define RCC_R63SEMCR 0x22C +#define RCC_R64CIDCFGR 0x230 +#define RCC_R64SEMCR 0x234 +#define RCC_R65CIDCFGR 0x238 +#define RCC_R65SEMCR 0x23C +#define RCC_R66CIDCFGR 0x240 +#define RCC_R66SEMCR 0x244 +#define RCC_R67CIDCFGR 0x248 +#define RCC_R67SEMCR 0x24C +#define RCC_R68CIDCFGR 0x250 +#define RCC_R68SEMCR 0x254 +#define RCC_R69CIDCFGR 0x258 +#define RCC_R69SEMCR 0x25C +#define RCC_R70CIDCFGR 0x260 +#define RCC_R70SEMCR 0x264 +#define RCC_R71CIDCFGR 0x268 +#define RCC_R71SEMCR 0x26C +#define RCC_R72CIDCFGR 0x270 +#define RCC_R72SEMCR 0x274 +#define RCC_R73CIDCFGR 0x278 +#define RCC_R73SEMCR 0x27C +#define RCC_R74CIDCFGR 0x280 +#define RCC_R74SEMCR 0x284 +#define RCC_R75CIDCFGR 0x288 +#define RCC_R75SEMCR 0x28C +#define RCC_R76CIDCFGR 0x290 +#define RCC_R76SEMCR 0x294 +#define RCC_R77CIDCFGR 0x298 +#define RCC_R77SEMCR 0x29C +#define RCC_R78CIDCFGR 0x2A0 +#define RCC_R78SEMCR 0x2A4 +#define RCC_R79CIDCFGR 0x2A8 +#define RCC_R79SEMCR 0x2AC +#define RCC_R80CIDCFGR 0x2B0 +#define RCC_R80SEMCR 0x2B4 +#define RCC_R81CIDCFGR 0x2B8 +#define RCC_R81SEMCR 0x2BC +#define RCC_R82CIDCFGR 0x2C0 +#define RCC_R82SEMCR 0x2C4 +#define RCC_R83CIDCFGR 0x2C8 +#define RCC_R83SEMCR 0x2CC +#define RCC_R84CIDCFGR 0x2D0 +#define RCC_R84SEMCR 0x2D4 +#define RCC_R85CIDCFGR 0x2D8 +#define RCC_R85SEMCR 0x2DC +#define RCC_R86CIDCFGR 0x2E0 +#define RCC_R86SEMCR 0x2E4 +#define RCC_R87CIDCFGR 0x2E8 +#define RCC_R87SEMCR 0x2EC +#define RCC_R88CIDCFGR 0x2F0 +#define RCC_R88SEMCR 0x2F4 +#define RCC_R89CIDCFGR 0x2F8 +#define RCC_R89SEMCR 0x2FC +#define RCC_R90CIDCFGR 0x300 +#define RCC_R90SEMCR 0x304 +#define RCC_R91CIDCFGR 0x308 +#define RCC_R91SEMCR 0x30C +#define RCC_R92CIDCFGR 0x310 +#define RCC_R92SEMCR 0x314 +#define RCC_R93CIDCFGR 0x318 +#define RCC_R93SEMCR 0x31C +#define RCC_R94CIDCFGR 0x320 +#define RCC_R94SEMCR 0x324 +#define RCC_R95CIDCFGR 0x328 +#define RCC_R95SEMCR 0x32C +#define RCC_R96CIDCFGR 0x330 +#define RCC_R96SEMCR 0x334 +#define RCC_R97CIDCFGR 0x338 +#define RCC_R97SEMCR 0x33C +#define RCC_R98CIDCFGR 0x340 +#define RCC_R98SEMCR 0x344 +#define RCC_R99CIDCFGR 0x348 +#define RCC_R99SEMCR 0x34C +#define RCC_R100CIDCFGR 0x350 +#define RCC_R100SEMCR 0x354 +#define RCC_R101CIDCFGR 0x358 +#define RCC_R101SEMCR 0x35C +#define RCC_R102CIDCFGR 0x360 +#define RCC_R102SEMCR 0x364 +#define RCC_R103CIDCFGR 0x368 +#define RCC_R103SEMCR 0x36C +#define RCC_R104CIDCFGR 0x370 +#define RCC_R104SEMCR 0x374 +#define RCC_R105CIDCFGR 0x378 +#define RCC_R105SEMCR 0x37C +#define RCC_R106CIDCFGR 0x380 +#define RCC_R106SEMCR 0x384 +#define RCC_R107CIDCFGR 0x388 +#define RCC_R107SEMCR 0x38C +#define RCC_R108CIDCFGR 0x390 +#define RCC_R108SEMCR 0x394 +#define RCC_R109CIDCFGR 0x398 +#define RCC_R109SEMCR 0x39C +#define RCC_R110CIDCFGR 0x3A0 +#define RCC_R110SEMCR 0x3A4 +#define RCC_R111CIDCFGR 0x3A8 +#define RCC_R111SEMCR 0x3AC +#define RCC_R112CIDCFGR 0x3B0 +#define RCC_R112SEMCR 0x3B4 +#define RCC_R113CIDCFGR 0x3B8 +#define RCC_R113SEMCR 0x3BC +#define RCC_GRSTCSETR 0x400 +#define RCC_C1RSTCSETR 0x404 +#define RCC_C1P1RSTCSETR 0x408 +#define RCC_C2RSTCSETR 0x40C +#define RCC_HWRSTSCLRR 0x410 +#define RCC_C1HWRSTSCLRR 0x414 +#define RCC_C2HWRSTSCLRR 0x418 +#define RCC_C1BOOTRSTSSETR 0x41C +#define RCC_C1BOOTRSTSCLRR 0x420 +#define RCC_C2BOOTRSTSSETR 0x424 +#define RCC_C2BOOTRSTSCLRR 0x428 +#define RCC_C1SREQSETR 0x42C +#define RCC_C1SREQCLRR 0x430 +#define RCC_CPUBOOTCR 0x434 +#define RCC_STBYBOOTCR 0x438 +#define RCC_LEGBOOTCR 0x43C +#define RCC_BDCR 0x440 +#define RCC_D3DCR 0x444 +#define RCC_D3DSR 0x448 +#define RCC_RDCR 0x44C +#define RCC_C1MSRDCR 0x450 +#define RCC_PWRLPDLYCR 0x454 +#define RCC_C1CIESETR 0x458 +#define RCC_C1CIFCLRR 0x45C +#define RCC_C2CIESETR 0x460 +#define RCC_C2CIFCLRR 0x464 +#define RCC_IWDGC1FZSETR 0x468 +#define RCC_IWDGC1FZCLRR 0x46C +#define RCC_IWDGC1CFGSETR 0x470 +#define RCC_IWDGC1CFGCLRR 0x474 +#define RCC_IWDGC2FZSETR 0x478 +#define RCC_IWDGC2FZCLRR 0x47C +#define RCC_IWDGC2CFGSETR 0x480 +#define RCC_IWDGC2CFGCLRR 0x484 +#define RCC_IWDGC3CFGSETR 0x488 +#define RCC_IWDGC3CFGCLRR 0x48C +#define RCC_C3CFGR 0x490 +#define RCC_MCO1CFGR 0x494 +#define RCC_MCO2CFGR 0x498 +#define RCC_OCENSETR 0x49C +#define RCC_OCENCLRR 0x4A0 +#define RCC_OCRDYR 0x4A4 +#define RCC_HSICFGR 0x4A8 +#define RCC_MSICFGR 0x4AC +#define RCC_RTCDIVR 0x4B0 +#define RCC_APB1DIVR 0x4B4 +#define RCC_APB2DIVR 0x4B8 +#define RCC_APB3DIVR 0x4BC +#define RCC_APB4DIVR 0x4C0 +#define RCC_APBDBGDIVR 0x4C4 +#define RCC_TIMG1PRER 0x4C8 +#define RCC_TIMG2PRER 0x4CC +#define RCC_LSMCUDIVR 0x4D0 +#define RCC_DDRCPCFGR 0x4D4 +#define RCC_DDRCAPBCFGR 0x4D8 +#define RCC_DDRPHYCAPBCFGR 0x4DC +#define RCC_DDRPHYCCFGR 0x4E0 +#define RCC_DDRCFGR 0x4E4 +#define RCC_DDRITFCFGR 0x4E8 +#define RCC_SYSRAMCFGR 0x4F0 +#define RCC_VDERAMCFGR 0x4F4 +#define RCC_SRAM1CFGR 0x4F8 +#define RCC_SRAM2CFGR 0x4FC +#define RCC_RETRAMCFGR 0x500 +#define RCC_BKPSRAMCFGR 0x504 +#define RCC_LPSRAM1CFGR 0x508 +#define RCC_LPSRAM2CFGR 0x50C +#define RCC_LPSRAM3CFGR 0x510 +#define RCC_OSPI1CFGR 0x514 +#define RCC_OSPI2CFGR 0x518 +#define RCC_FMCCFGR 0x51C +#define RCC_DBGCFGR 0x520 +#define RCC_STM500CFGR 0x524 +#define RCC_ETRCFGR 0x528 +#define RCC_GPIOACFGR 0x52C +#define RCC_GPIOBCFGR 0x530 +#define RCC_GPIOCCFGR 0x534 +#define RCC_GPIODCFGR 0x538 +#define RCC_GPIOECFGR 0x53C +#define RCC_GPIOFCFGR 0x540 +#define RCC_GPIOGCFGR 0x544 +#define RCC_GPIOHCFGR 0x548 +#define RCC_GPIOICFGR 0x54C +#define RCC_GPIOJCFGR 0x550 +#define RCC_GPIOKCFGR 0x554 +#define RCC_GPIOZCFGR 0x558 +#define RCC_HPDMA1CFGR 0x55C +#define RCC_HPDMA2CFGR 0x560 +#define RCC_HPDMA3CFGR 0x564 +#define RCC_LPDMACFGR 0x568 +#define RCC_HSEMCFGR 0x56C +#define RCC_IPCC1CFGR 0x570 +#define RCC_IPCC2CFGR 0x574 +#define RCC_RTCCFGR 0x578 +#define RCC_SYSCPU1CFGR 0x580 +#define RCC_BSECCFGR 0x584 +#define RCC_IS2MCFGR 0x58C +#define RCC_PLL2CFGR1 0x590 +#define RCC_PLL2CFGR2 0x594 +#define RCC_PLL2CFGR3 0x598 +#define RCC_PLL2CFGR4 0x59C +#define RCC_PLL2CFGR5 0x5A0 +#define RCC_PLL2CFGR6 0x5A8 +#define RCC_PLL2CFGR7 0x5AC +#define RCC_PLL3CFGR1 0x5B8 +#define RCC_PLL3CFGR2 0x5BC +#define RCC_PLL3CFGR3 0x5C0 +#define RCC_PLL3CFGR4 0x5C4 +#define RCC_PLL3CFGR5 0x5C8 +#define RCC_PLL3CFGR6 0x5D0 +#define RCC_PLL3CFGR7 0x5D4 +#define RCC_HSIFMONCR 0x5E0 +#define RCC_HSIFVALR 0x5E4 +#define RCC_TIM1CFGR 0x700 +#define RCC_TIM2CFGR 0x704 +#define RCC_TIM3CFGR 0x708 +#define RCC_TIM4CFGR 0x70C +#define RCC_TIM5CFGR 0x710 +#define RCC_TIM6CFGR 0x714 +#define RCC_TIM7CFGR 0x718 +#define RCC_TIM8CFGR 0x71C +#define RCC_TIM10CFGR 0x720 +#define RCC_TIM11CFGR 0x724 +#define RCC_TIM12CFGR 0x728 +#define RCC_TIM13CFGR 0x72C +#define RCC_TIM14CFGR 0x730 +#define RCC_TIM15CFGR 0x734 +#define RCC_TIM16CFGR 0x738 +#define RCC_TIM17CFGR 0x73C +#define RCC_TIM20CFGR 0x740 +#define RCC_LPTIM1CFGR 0x744 +#define RCC_LPTIM2CFGR 0x748 +#define RCC_LPTIM3CFGR 0x74C +#define RCC_LPTIM4CFGR 0x750 +#define RCC_LPTIM5CFGR 0x754 +#define RCC_SPI1CFGR 0x758 +#define RCC_SPI2CFGR 0x75C +#define RCC_SPI3CFGR 0x760 +#define RCC_SPI4CFGR 0x764 +#define RCC_SPI5CFGR 0x768 +#define RCC_SPI6CFGR 0x76C +#define RCC_SPI7CFGR 0x770 +#define RCC_SPI8CFGR 0x774 +#define RCC_SPDIFRXCFGR 0x778 +#define RCC_USART1CFGR 0x77C +#define RCC_USART2CFGR 0x780 +#define RCC_USART3CFGR 0x784 +#define RCC_UART4CFGR 0x788 +#define RCC_UART5CFGR 0x78C +#define RCC_USART6CFGR 0x790 +#define RCC_UART7CFGR 0x794 +#define RCC_UART8CFGR 0x798 +#define RCC_UART9CFGR 0x79C +#define RCC_LPUART1CFGR 0x7A0 +#define RCC_I2C1CFGR 0x7A4 +#define RCC_I2C2CFGR 0x7A8 +#define RCC_I2C3CFGR 0x7AC +#define RCC_I2C4CFGR 0x7B0 +#define RCC_I2C5CFGR 0x7B4 +#define RCC_I2C6CFGR 0x7B8 +#define RCC_I2C7CFGR 0x7BC +#define RCC_I2C8CFGR 0x7C0 +#define RCC_SAI1CFGR 0x7C4 +#define RCC_SAI2CFGR 0x7C8 +#define RCC_SAI3CFGR 0x7CC +#define RCC_SAI4CFGR 0x7D0 +#define RCC_MDF1CFGR 0x7D8 +#define RCC_ADF1CFGR 0x7DC +#define RCC_FDCANCFGR 0x7E0 +#define RCC_HDPCFGR 0x7E4 +#define RCC_ADC12CFGR 0x7E8 +#define RCC_ADC3CFGR 0x7EC +#define RCC_ETH1CFGR 0x7F0 +#define RCC_ETH2CFGR 0x7F4 +#define RCC_USBHCFGR 0x7FC +#define RCC_USB2PHY1CFGR 0x800 +#define RCC_USB2PHY2CFGR 0x804 +#define RCC_USB3DRCFGR 0x808 +#define RCC_USB3PCIEPHYCFGR 0x80C +#define RCC_PCIECFGR 0x810 +#define RCC_USBTCCFGR 0x814 +#define RCC_ETHSWCFGR 0x818 +#define RCC_ETHSWACMCFGR 0x81C +#define RCC_ETHSWACMMSGCFGR 0x820 +#define RCC_STGENCFGR 0x824 +#define RCC_SDMMC1CFGR 0x830 +#define RCC_SDMMC2CFGR 0x834 +#define RCC_SDMMC3CFGR 0x838 +#define RCC_GPUCFGR 0x83C +#define RCC_LTDCCFGR 0x840 +#define RCC_DSICFGR 0x844 +#define RCC_LVDSCFGR 0x850 +#define RCC_CSICFGR 0x858 +#define RCC_DCMIPPCFGR 0x85C +#define RCC_CCICFGR 0x860 +#define RCC_VDECCFGR 0x864 +#define RCC_VENCCFGR 0x868 +#define RCC_RNGCFGR 0x870 +#define RCC_PKACFGR 0x874 +#define RCC_SAESCFGR 0x878 +#define RCC_HASHCFGR 0x87C +#define RCC_CRYP1CFGR 0x880 +#define RCC_CRYP2CFGR 0x884 +#define RCC_IWDG1CFGR 0x888 +#define RCC_IWDG2CFGR 0x88C +#define RCC_IWDG3CFGR 0x890 +#define RCC_IWDG4CFGR 0x894 +#define RCC_IWDG5CFGR 0x898 +#define RCC_WWDG1CFGR 0x89C +#define RCC_WWDG2CFGR 0x8A0 +#define RCC_VREFCFGR 0x8A8 +#define RCC_DTSCFGR 0x8AC +#define RCC_CRCCFGR 0x8B4 +#define RCC_SERCCFGR 0x8B8 +#define RCC_OSPIIOMCFGR 0x8BC +#define RCC_GICV2MCFGR 0x8C0 +#define RCC_I3C1CFGR 0x8C8 +#define RCC_I3C2CFGR 0x8CC +#define RCC_I3C3CFGR 0x8D0 +#define RCC_I3C4CFGR 0x8D4 +#define RCC_MUXSELCFGR 0x1000 +#define RCC_XBAR0CFGR 0x1018 +#define RCC_XBAR1CFGR 0x101C +#define RCC_XBAR2CFGR 0x1020 +#define RCC_XBAR3CFGR 0x1024 +#define RCC_XBAR4CFGR 0x1028 +#define RCC_XBAR5CFGR 0x102C +#define RCC_XBAR6CFGR 0x1030 +#define RCC_XBAR7CFGR 0x1034 +#define RCC_XBAR8CFGR 0x1038 +#define RCC_XBAR9CFGR 0x103C +#define RCC_XBAR10CFGR 0x1040 +#define RCC_XBAR11CFGR 0x1044 +#define RCC_XBAR12CFGR 0x1048 +#define RCC_XBAR13CFGR 0x104C +#define RCC_XBAR14CFGR 0x1050 +#define RCC_XBAR15CFGR 0x1054 +#define RCC_XBAR16CFGR 0x1058 +#define RCC_XBAR17CFGR 0x105C +#define RCC_XBAR18CFGR 0x1060 +#define RCC_XBAR19CFGR 0x1064 +#define RCC_XBAR20CFGR 0x1068 +#define RCC_XBAR21CFGR 0x106C +#define RCC_XBAR22CFGR 0x1070 +#define RCC_XBAR23CFGR 0x1074 +#define RCC_XBAR24CFGR 0x1078 +#define RCC_XBAR25CFGR 0x107C +#define RCC_XBAR26CFGR 0x1080 +#define RCC_XBAR27CFGR 0x1084 +#define RCC_XBAR28CFGR 0x1088 +#define RCC_XBAR29CFGR 0x108C +#define RCC_XBAR30CFGR 0x1090 +#define RCC_XBAR31CFGR 0x1094 +#define RCC_XBAR32CFGR 0x1098 +#define RCC_XBAR33CFGR 0x109C +#define RCC_XBAR34CFGR 0x10A0 +#define RCC_XBAR35CFGR 0x10A4 +#define RCC_XBAR36CFGR 0x10A8 +#define RCC_XBAR37CFGR 0x10AC +#define RCC_XBAR38CFGR 0x10B0 +#define RCC_XBAR39CFGR 0x10B4 +#define RCC_XBAR40CFGR 0x10B8 +#define RCC_XBAR41CFGR 0x10BC +#define RCC_XBAR42CFGR 0x10C0 +#define RCC_XBAR43CFGR 0x10C4 +#define RCC_XBAR44CFGR 0x10C8 +#define RCC_XBAR45CFGR 0x10CC +#define RCC_XBAR46CFGR 0x10D0 +#define RCC_XBAR47CFGR 0x10D4 +#define RCC_XBAR48CFGR 0x10D8 +#define RCC_XBAR49CFGR 0x10DC +#define RCC_XBAR50CFGR 0x10E0 +#define RCC_XBAR51CFGR 0x10E4 +#define RCC_XBAR52CFGR 0x10E8 +#define RCC_XBAR53CFGR 0x10EC +#define RCC_XBAR54CFGR 0x10F0 +#define RCC_XBAR55CFGR 0x10F4 +#define RCC_XBAR56CFGR 0x10F8 +#define RCC_XBAR57CFGR 0x10FC +#define RCC_XBAR58CFGR 0x1100 +#define RCC_XBAR59CFGR 0x1104 +#define RCC_XBAR60CFGR 0x1108 +#define RCC_XBAR61CFGR 0x110C +#define RCC_XBAR62CFGR 0x1110 +#define RCC_XBAR63CFGR 0x1114 +#define RCC_PREDIV0CFGR 0x1118 +#define RCC_PREDIV1CFGR 0x111C +#define RCC_PREDIV2CFGR 0x1120 +#define RCC_PREDIV3CFGR 0x1124 +#define RCC_PREDIV4CFGR 0x1128 +#define RCC_PREDIV5CFGR 0x112C +#define RCC_PREDIV6CFGR 0x1130 +#define RCC_PREDIV7CFGR 0x1134 +#define RCC_PREDIV8CFGR 0x1138 +#define RCC_PREDIV9CFGR 0x113C +#define RCC_PREDIV10CFGR 0x1140 +#define RCC_PREDIV11CFGR 0x1144 +#define RCC_PREDIV12CFGR 0x1148 +#define RCC_PREDIV13CFGR 0x114C +#define RCC_PREDIV14CFGR 0x1150 +#define RCC_PREDIV15CFGR 0x1154 +#define RCC_PREDIV16CFGR 0x1158 +#define RCC_PREDIV17CFGR 0x115C +#define RCC_PREDIV18CFGR 0x1160 +#define RCC_PREDIV19CFGR 0x1164 +#define RCC_PREDIV20CFGR 0x1168 +#define RCC_PREDIV21CFGR 0x116C +#define RCC_PREDIV22CFGR 0x1170 +#define RCC_PREDIV23CFGR 0x1174 +#define RCC_PREDIV24CFGR 0x1178 +#define RCC_PREDIV25CFGR 0x117C +#define RCC_PREDIV26CFGR 0x1180 +#define RCC_PREDIV27CFGR 0x1184 +#define RCC_PREDIV28CFGR 0x1188 +#define RCC_PREDIV29CFGR 0x118C +#define RCC_PREDIV30CFGR 0x1190 +#define RCC_PREDIV31CFGR 0x1194 +#define RCC_PREDIV32CFGR 0x1198 +#define RCC_PREDIV33CFGR 0x119C +#define RCC_PREDIV34CFGR 0x11A0 +#define RCC_PREDIV35CFGR 0x11A4 +#define RCC_PREDIV36CFGR 0x11A8 +#define RCC_PREDIV37CFGR 0x11AC +#define RCC_PREDIV38CFGR 0x11B0 +#define RCC_PREDIV39CFGR 0x11B4 +#define RCC_PREDIV40CFGR 0x11B8 +#define RCC_PREDIV41CFGR 0x11BC +#define RCC_PREDIV42CFGR 0x11C0 +#define RCC_PREDIV43CFGR 0x11C4 +#define RCC_PREDIV44CFGR 0x11C8 +#define RCC_PREDIV45CFGR 0x11CC +#define RCC_PREDIV46CFGR 0x11D0 +#define RCC_PREDIV47CFGR 0x11D4 +#define RCC_PREDIV48CFGR 0x11D8 +#define RCC_PREDIV49CFGR 0x11DC +#define RCC_PREDIV50CFGR 0x11E0 +#define RCC_PREDIV51CFGR 0x11E4 +#define RCC_PREDIV52CFGR 0x11E8 +#define RCC_PREDIV53CFGR 0x11EC +#define RCC_PREDIV54CFGR 0x11F0 +#define RCC_PREDIV55CFGR 0x11F4 +#define RCC_PREDIV56CFGR 0x11F8 +#define RCC_PREDIV57CFGR 0x11FC +#define RCC_PREDIV58CFGR 0x1200 +#define RCC_PREDIV59CFGR 0x1204 +#define RCC_PREDIV60CFGR 0x1208 +#define RCC_PREDIV61CFGR 0x120C +#define RCC_PREDIV62CFGR 0x1210 +#define RCC_PREDIV63CFGR 0x1214 +#define RCC_PREDIVSR1 0x1218 +#define RCC_PREDIVSR2 0x121C +#define RCC_FINDIV0CFGR 0x1224 +#define RCC_FINDIV1CFGR 0x1228 +#define RCC_FINDIV2CFGR 0x122C +#define RCC_FINDIV3CFGR 0x1230 +#define RCC_FINDIV4CFGR 0x1234 +#define RCC_FINDIV5CFGR 0x1238 +#define RCC_FINDIV6CFGR 0x123C +#define RCC_FINDIV7CFGR 0x1240 +#define RCC_FINDIV8CFGR 0x1244 +#define RCC_FINDIV9CFGR 0x1248 +#define RCC_FINDIV10CFGR 0x124C +#define RCC_FINDIV11CFGR 0x1250 +#define RCC_FINDIV12CFGR 0x1254 +#define RCC_FINDIV13CFGR 0x1258 +#define RCC_FINDIV14CFGR 0x125C +#define RCC_FINDIV15CFGR 0x1260 +#define RCC_FINDIV16CFGR 0x1264 +#define RCC_FINDIV17CFGR 0x1268 +#define RCC_FINDIV18CFGR 0x126C +#define RCC_FINDIV19CFGR 0x1270 +#define RCC_FINDIV20CFGR 0x1274 +#define RCC_FINDIV21CFGR 0x1278 +#define RCC_FINDIV22CFGR 0x127C +#define RCC_FINDIV23CFGR 0x1280 +#define RCC_FINDIV24CFGR 0x1284 +#define RCC_FINDIV25CFGR 0x1288 +#define RCC_FINDIV26CFGR 0x128C +#define RCC_FINDIV27CFGR 0x1290 +#define RCC_FINDIV28CFGR 0x1294 +#define RCC_FINDIV29CFGR 0x1298 +#define RCC_FINDIV30CFGR 0x129C +#define RCC_FINDIV31CFGR 0x12A0 +#define RCC_FINDIV32CFGR 0x12A4 +#define RCC_FINDIV33CFGR 0x12A8 +#define RCC_FINDIV34CFGR 0x12AC +#define RCC_FINDIV35CFGR 0x12B0 +#define RCC_FINDIV36CFGR 0x12B4 +#define RCC_FINDIV37CFGR 0x12B8 +#define RCC_FINDIV38CFGR 0x12BC +#define RCC_FINDIV39CFGR 0x12C0 +#define RCC_FINDIV40CFGR 0x12C4 +#define RCC_FINDIV41CFGR 0x12C8 +#define RCC_FINDIV42CFGR 0x12CC +#define RCC_FINDIV43CFGR 0x12D0 +#define RCC_FINDIV44CFGR 0x12D4 +#define RCC_FINDIV45CFGR 0x12D8 +#define RCC_FINDIV46CFGR 0x12DC +#define RCC_FINDIV47CFGR 0x12E0 +#define RCC_FINDIV48CFGR 0x12E4 +#define RCC_FINDIV49CFGR 0x12E8 +#define RCC_FINDIV50CFGR 0x12EC +#define RCC_FINDIV51CFGR 0x12F0 +#define RCC_FINDIV52CFGR 0x12F4 +#define RCC_FINDIV53CFGR 0x12F8 +#define RCC_FINDIV54CFGR 0x12FC +#define RCC_FINDIV55CFGR 0x1300 +#define RCC_FINDIV56CFGR 0x1304 +#define RCC_FINDIV57CFGR 0x1308 +#define RCC_FINDIV58CFGR 0x130C +#define RCC_FINDIV59CFGR 0x1310 +#define RCC_FINDIV60CFGR 0x1314 +#define RCC_FINDIV61CFGR 0x1318 +#define RCC_FINDIV62CFGR 0x131C +#define RCC_FINDIV63CFGR 0x1320 +#define RCC_FINDIVSR1 0x1324 +#define RCC_FINDIVSR2 0x1328 +#define RCC_FCALCOBS0CFGR 0x1340 +#define RCC_FCALCOBS1CFGR 0x1344 +#define RCC_FCALCREFCFGR 0x1348 +#define RCC_FCALCCR1 0x134C +#define RCC_FCALCCR2 0x1354 +#define RCC_FCALCSR 0x1358 +#define RCC_PLL4CFGR1 0x1360 +#define RCC_PLL4CFGR2 0x1364 +#define RCC_PLL4CFGR3 0x1368 +#define RCC_PLL4CFGR4 0x136C +#define RCC_PLL4CFGR5 0x1370 +#define RCC_PLL4CFGR6 0x1378 +#define RCC_PLL4CFGR7 0x137C +#define RCC_PLL5CFGR1 0x1388 +#define RCC_PLL5CFGR2 0x138C +#define RCC_PLL5CFGR3 0x1390 +#define RCC_PLL5CFGR4 0x1394 +#define RCC_PLL5CFGR5 0x1398 +#define RCC_PLL5CFGR6 0x13A0 +#define RCC_PLL5CFGR7 0x13A4 +#define RCC_PLL6CFGR1 0x13B0 +#define RCC_PLL6CFGR2 0x13B4 +#define RCC_PLL6CFGR3 0x13B8 +#define RCC_PLL6CFGR4 0x13BC +#define RCC_PLL6CFGR5 0x13C0 +#define RCC_PLL6CFGR6 0x13C8 +#define RCC_PLL6CFGR7 0x13CC +#define RCC_PLL7CFGR1 0x13D8 +#define RCC_PLL7CFGR2 0x13DC +#define RCC_PLL7CFGR3 0x13E0 +#define RCC_PLL7CFGR4 0x13E4 +#define RCC_PLL7CFGR5 0x13E8 +#define RCC_PLL7CFGR6 0x13F0 +#define RCC_PLL7CFGR7 0x13F4 +#define RCC_PLL8CFGR1 0x1400 +#define RCC_PLL8CFGR2 0x1404 +#define RCC_PLL8CFGR3 0x1408 +#define RCC_PLL8CFGR4 0x140C +#define RCC_PLL8CFGR5 0x1410 +#define RCC_PLL8CFGR6 0x1418 +#define RCC_PLL8CFGR7 0x141C +#define RCC_VERR 0xFFF4 +#define RCC_IDR 0xFFF8 +#define RCC_SIDR 0xFFFC + +#endif /* STM32MP25_RCC_H */ From 5723879c145255d2502a3f8f3a21a16332b24366 Mon Sep 17 00:00:00 2001 From: Frank Oltmanns Date: Sun, 10 Mar 2024 14:21:13 +0100 Subject: [PATCH 044/118] clk: sunxi-ng: nkm: Support constraints on m/n ratio and parent rate The Allwinner A64 manual lists the following constraints for the PLL-MIPI clock: - M/N <= 3 - (PLL_VIDEO0)/M >= 24MHz The PLL-MIPI clock is implemented as ccu_nkm. Therefore, add support for these constraints. Reviewed-by: Jernej Skrabec Signed-off-by: Frank Oltmanns Link: https://lore.kernel.org/r/20240310-pinephone-pll-fixes-v4-3-46fc80c83637@oltmanns.dev Signed-off-by: Jernej Skrabec --- drivers/clk/sunxi-ng/ccu_nkm.c | 21 +++++++++++++++++++++ drivers/clk/sunxi-ng/ccu_nkm.h | 2 ++ 2 files changed, 23 insertions(+) diff --git a/drivers/clk/sunxi-ng/ccu_nkm.c b/drivers/clk/sunxi-ng/ccu_nkm.c index 853f84398e2b..1168d894d636 100644 --- a/drivers/clk/sunxi-ng/ccu_nkm.c +++ b/drivers/clk/sunxi-ng/ccu_nkm.c @@ -16,6 +16,20 @@ struct _ccu_nkm { unsigned long m, min_m, max_m; }; +static bool ccu_nkm_is_valid_rate(struct ccu_common *common, unsigned long parent, + unsigned long n, unsigned long m) +{ + struct ccu_nkm *nkm = container_of(common, struct ccu_nkm, common); + + if (nkm->max_m_n_ratio && (m > nkm->max_m_n_ratio * n)) + return false; + + if (nkm->min_parent_m_ratio && (parent < nkm->min_parent_m_ratio * m)) + return false; + + return true; +} + static unsigned long ccu_nkm_find_best_with_parent_adj(struct ccu_common *common, struct clk_hw *parent_hw, unsigned long *parent, unsigned long rate, @@ -31,6 +45,10 @@ static unsigned long ccu_nkm_find_best_with_parent_adj(struct ccu_common *common unsigned long tmp_rate, tmp_parent; tmp_parent = clk_hw_round_rate(parent_hw, rate * _m / (_n * _k)); + + if (!ccu_nkm_is_valid_rate(common, tmp_parent, _n, _m)) + continue; + tmp_rate = tmp_parent * _n * _k / _m; if (ccu_is_better_rate(common, rate, tmp_rate, best_rate) || @@ -64,6 +82,9 @@ static unsigned long ccu_nkm_find_best(unsigned long parent, unsigned long rate, for (_k = nkm->min_k; _k <= nkm->max_k; _k++) { for (_n = nkm->min_n; _n <= nkm->max_n; _n++) { for (_m = nkm->min_m; _m <= nkm->max_m; _m++) { + if (!ccu_nkm_is_valid_rate(common, parent, _n, _m)) + continue; + unsigned long tmp_rate; tmp_rate = parent * _n * _k / _m; diff --git a/drivers/clk/sunxi-ng/ccu_nkm.h b/drivers/clk/sunxi-ng/ccu_nkm.h index 6601defb3f38..c409212ee40e 100644 --- a/drivers/clk/sunxi-ng/ccu_nkm.h +++ b/drivers/clk/sunxi-ng/ccu_nkm.h @@ -27,6 +27,8 @@ struct ccu_nkm { struct ccu_mux_internal mux; unsigned int fixed_post_div; + unsigned long max_m_n_ratio; + unsigned long min_parent_m_ratio; struct ccu_common common; }; From 52b1429e0c51a4ebbdf573ad97c7fb6d34f011a2 Mon Sep 17 00:00:00 2001 From: Frank Oltmanns Date: Sun, 10 Mar 2024 14:21:14 +0100 Subject: [PATCH 045/118] clk: sunxi-ng: a64: Add constraints on PLL-MIPI's n/m ratio and parent rate The Allwinner A64 manual lists the following constraints for the PLL-MIPI clock: - M/N <= 3 - (PLL_VIDEO0)/M >= 24MHz Use these constraints. Reviewed-by: Jernej Skrabec Signed-off-by: Frank Oltmanns Link: https://lore.kernel.org/r/20240310-pinephone-pll-fixes-v4-4-46fc80c83637@oltmanns.dev Signed-off-by: Jernej Skrabec --- drivers/clk/sunxi-ng/ccu-sun50i-a64.c | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/drivers/clk/sunxi-ng/ccu-sun50i-a64.c b/drivers/clk/sunxi-ng/ccu-sun50i-a64.c index 8951ffc14ff5..df679dada792 100644 --- a/drivers/clk/sunxi-ng/ccu-sun50i-a64.c +++ b/drivers/clk/sunxi-ng/ccu-sun50i-a64.c @@ -171,11 +171,13 @@ static struct ccu_nkm pll_mipi_clk = { * user manual, and by experiments the PLL doesn't work without * these bits toggled. */ - .enable = BIT(31) | BIT(23) | BIT(22), - .lock = BIT(28), - .n = _SUNXI_CCU_MULT(8, 4), - .k = _SUNXI_CCU_MULT_MIN(4, 2, 2), - .m = _SUNXI_CCU_DIV(0, 4), + .enable = BIT(31) | BIT(23) | BIT(22), + .lock = BIT(28), + .n = _SUNXI_CCU_MULT(8, 4), + .k = _SUNXI_CCU_MULT_MIN(4, 2, 2), + .m = _SUNXI_CCU_DIV(0, 4), + .max_m_n_ratio = 3, + .min_parent_m_ratio = 24000000, .common = { .reg = 0x040, .hw.init = CLK_HW_INIT("pll-mipi", "pll-video0", From c60f68047e1996bc1b2fb386d3b383aab8900c1b Mon Sep 17 00:00:00 2001 From: Krzysztof Kozlowski Date: Wed, 10 Apr 2024 17:54:20 +0200 Subject: [PATCH 046/118] clk: sunxi-ng: fix module autoloading Add MODULE_DEVICE_TABLE(), so modules could be properly autoloaded based on the alias from of_device_id table. Clocks are considered core components, so usually they are built-in, however these can be built and used as modules on some generic kernel. Signed-off-by: Krzysztof Kozlowski Acked-by: Jernej Skrabec Link: https://lore.kernel.org/r/20240410155420.224157-1-krzk@kernel.org Signed-off-by: Jernej Skrabec --- drivers/clk/sunxi-ng/ccu-sun20i-d1-r.c | 1 + drivers/clk/sunxi-ng/ccu-sun20i-d1.c | 1 + drivers/clk/sunxi-ng/ccu-sun4i-a10.c | 1 + drivers/clk/sunxi-ng/ccu-sun50i-a100-r.c | 1 + drivers/clk/sunxi-ng/ccu-sun50i-a100.c | 1 + drivers/clk/sunxi-ng/ccu-sun50i-a64.c | 1 + drivers/clk/sunxi-ng/ccu-sun50i-h6-r.c | 1 + drivers/clk/sunxi-ng/ccu-sun50i-h6.c | 1 + drivers/clk/sunxi-ng/ccu-sun50i-h616.c | 1 + drivers/clk/sunxi-ng/ccu-sun6i-a31.c | 1 + drivers/clk/sunxi-ng/ccu-sun6i-rtc.c | 1 + drivers/clk/sunxi-ng/ccu-sun8i-a23.c | 1 + drivers/clk/sunxi-ng/ccu-sun8i-a33.c | 1 + drivers/clk/sunxi-ng/ccu-sun8i-a83t.c | 1 + drivers/clk/sunxi-ng/ccu-sun8i-de2.c | 1 + drivers/clk/sunxi-ng/ccu-sun8i-h3.c | 1 + drivers/clk/sunxi-ng/ccu-sun8i-r.c | 1 + drivers/clk/sunxi-ng/ccu-sun8i-r40.c | 1 + drivers/clk/sunxi-ng/ccu-sun8i-v3s.c | 1 + drivers/clk/sunxi-ng/ccu-sun9i-a80-de.c | 1 + drivers/clk/sunxi-ng/ccu-sun9i-a80-usb.c | 1 + drivers/clk/sunxi-ng/ccu-sun9i-a80.c | 1 + drivers/clk/sunxi-ng/ccu-suniv-f1c100s.c | 1 + 23 files changed, 23 insertions(+) diff --git a/drivers/clk/sunxi-ng/ccu-sun20i-d1-r.c b/drivers/clk/sunxi-ng/ccu-sun20i-d1-r.c index 9d3ffd3fb2c1..0736f6c81269 100644 --- a/drivers/clk/sunxi-ng/ccu-sun20i-d1-r.c +++ b/drivers/clk/sunxi-ng/ccu-sun20i-d1-r.c @@ -125,6 +125,7 @@ static const struct of_device_id sun20i_d1_r_ccu_ids[] = { { .compatible = "allwinner,sun20i-d1-r-ccu" }, { } }; +MODULE_DEVICE_TABLE(of, sun20i_d1_r_ccu_ids); static struct platform_driver sun20i_d1_r_ccu_driver = { .probe = sun20i_d1_r_ccu_probe, diff --git a/drivers/clk/sunxi-ng/ccu-sun20i-d1.c b/drivers/clk/sunxi-ng/ccu-sun20i-d1.c index 48a8fb2c43b7..60756aadfad6 100644 --- a/drivers/clk/sunxi-ng/ccu-sun20i-d1.c +++ b/drivers/clk/sunxi-ng/ccu-sun20i-d1.c @@ -1394,6 +1394,7 @@ static const struct of_device_id sun20i_d1_ccu_ids[] = { { .compatible = "allwinner,sun20i-d1-ccu" }, { } }; +MODULE_DEVICE_TABLE(of, sun20i_d1_ccu_ids); static struct platform_driver sun20i_d1_ccu_driver = { .probe = sun20i_d1_ccu_probe, diff --git a/drivers/clk/sunxi-ng/ccu-sun4i-a10.c b/drivers/clk/sunxi-ng/ccu-sun4i-a10.c index 451ebb7c99a3..14f5c3da652b 100644 --- a/drivers/clk/sunxi-ng/ccu-sun4i-a10.c +++ b/drivers/clk/sunxi-ng/ccu-sun4i-a10.c @@ -1481,6 +1481,7 @@ static const struct of_device_id sun4i_a10_ccu_ids[] = { }, { } }; +MODULE_DEVICE_TABLE(of, sun4i_a10_ccu_ids); static struct platform_driver sun4i_a10_ccu_driver = { .probe = sun4i_a10_ccu_probe, diff --git a/drivers/clk/sunxi-ng/ccu-sun50i-a100-r.c b/drivers/clk/sunxi-ng/ccu-sun50i-a100-r.c index fddd6c877cec..3b983bb59bd9 100644 --- a/drivers/clk/sunxi-ng/ccu-sun50i-a100-r.c +++ b/drivers/clk/sunxi-ng/ccu-sun50i-a100-r.c @@ -202,6 +202,7 @@ static const struct of_device_id sun50i_a100_r_ccu_ids[] = { { .compatible = "allwinner,sun50i-a100-r-ccu" }, { } }; +MODULE_DEVICE_TABLE(of, sun50i_a100_r_ccu_ids); static struct platform_driver sun50i_a100_r_ccu_driver = { .probe = sun50i_a100_r_ccu_probe, diff --git a/drivers/clk/sunxi-ng/ccu-sun50i-a100.c b/drivers/clk/sunxi-ng/ccu-sun50i-a100.c index 5f93b5526e13..38aa6e5f298e 100644 --- a/drivers/clk/sunxi-ng/ccu-sun50i-a100.c +++ b/drivers/clk/sunxi-ng/ccu-sun50i-a100.c @@ -1264,6 +1264,7 @@ static const struct of_device_id sun50i_a100_ccu_ids[] = { { .compatible = "allwinner,sun50i-a100-ccu" }, { } }; +MODULE_DEVICE_TABLE(of, sun50i_a100_ccu_ids); static struct platform_driver sun50i_a100_ccu_driver = { .probe = sun50i_a100_ccu_probe, diff --git a/drivers/clk/sunxi-ng/ccu-sun50i-a64.c b/drivers/clk/sunxi-ng/ccu-sun50i-a64.c index df679dada792..56c629186bec 100644 --- a/drivers/clk/sunxi-ng/ccu-sun50i-a64.c +++ b/drivers/clk/sunxi-ng/ccu-sun50i-a64.c @@ -980,6 +980,7 @@ static const struct of_device_id sun50i_a64_ccu_ids[] = { { .compatible = "allwinner,sun50i-a64-ccu" }, { } }; +MODULE_DEVICE_TABLE(of, sun50i_a64_ccu_ids); static struct platform_driver sun50i_a64_ccu_driver = { .probe = sun50i_a64_ccu_probe, diff --git a/drivers/clk/sunxi-ng/ccu-sun50i-h6-r.c b/drivers/clk/sunxi-ng/ccu-sun50i-h6-r.c index 02b28cfc5525..e2dc29fa99e7 100644 --- a/drivers/clk/sunxi-ng/ccu-sun50i-h6-r.c +++ b/drivers/clk/sunxi-ng/ccu-sun50i-h6-r.c @@ -244,6 +244,7 @@ static const struct of_device_id sun50i_h6_r_ccu_ids[] = { }, { } }; +MODULE_DEVICE_TABLE(of, sun50i_h6_r_ccu_ids); static struct platform_driver sun50i_h6_r_ccu_driver = { .probe = sun50i_h6_r_ccu_probe, diff --git a/drivers/clk/sunxi-ng/ccu-sun50i-h6.c b/drivers/clk/sunxi-ng/ccu-sun50i-h6.c index 42568c616181..fa483bc2437a 100644 --- a/drivers/clk/sunxi-ng/ccu-sun50i-h6.c +++ b/drivers/clk/sunxi-ng/ccu-sun50i-h6.c @@ -1259,6 +1259,7 @@ static const struct of_device_id sun50i_h6_ccu_ids[] = { { .compatible = "allwinner,sun50i-h6-ccu" }, { } }; +MODULE_DEVICE_TABLE(of, sun50i_h6_ccu_ids); static struct platform_driver sun50i_h6_ccu_driver = { .probe = sun50i_h6_ccu_probe, diff --git a/drivers/clk/sunxi-ng/ccu-sun50i-h616.c b/drivers/clk/sunxi-ng/ccu-sun50i-h616.c index 21e918582aa5..45aae1ae5178 100644 --- a/drivers/clk/sunxi-ng/ccu-sun50i-h616.c +++ b/drivers/clk/sunxi-ng/ccu-sun50i-h616.c @@ -1154,6 +1154,7 @@ static const struct of_device_id sun50i_h616_ccu_ids[] = { { .compatible = "allwinner,sun50i-h616-ccu" }, { } }; +MODULE_DEVICE_TABLE(of, sun50i_h616_ccu_ids); static struct platform_driver sun50i_h616_ccu_driver = { .probe = sun50i_h616_ccu_probe, diff --git a/drivers/clk/sunxi-ng/ccu-sun6i-a31.c b/drivers/clk/sunxi-ng/ccu-sun6i-a31.c index 0762deffb33c..8cb8cbbdbafb 100644 --- a/drivers/clk/sunxi-ng/ccu-sun6i-a31.c +++ b/drivers/clk/sunxi-ng/ccu-sun6i-a31.c @@ -1271,6 +1271,7 @@ static const struct of_device_id sun6i_a31_ccu_ids[] = { { .compatible = "allwinner,sun6i-a31-ccu" }, { } }; +MODULE_DEVICE_TABLE(of, sun6i_a31_ccu_ids); static struct platform_driver sun6i_a31_ccu_driver = { .probe = sun6i_a31_ccu_probe, diff --git a/drivers/clk/sunxi-ng/ccu-sun6i-rtc.c b/drivers/clk/sunxi-ng/ccu-sun6i-rtc.c index fdc8ccc586c9..5a98c4e9e667 100644 --- a/drivers/clk/sunxi-ng/ccu-sun6i-rtc.c +++ b/drivers/clk/sunxi-ng/ccu-sun6i-rtc.c @@ -336,6 +336,7 @@ static const struct of_device_id sun6i_rtc_ccu_match[] = { }, {}, }; +MODULE_DEVICE_TABLE(of, sun6i_rtc_ccu_match); int sun6i_rtc_ccu_probe(struct device *dev, void __iomem *reg) { diff --git a/drivers/clk/sunxi-ng/ccu-sun8i-a23.c b/drivers/clk/sunxi-ng/ccu-sun8i-a23.c index e80cc3864e44..e748ad612b8f 100644 --- a/drivers/clk/sunxi-ng/ccu-sun8i-a23.c +++ b/drivers/clk/sunxi-ng/ccu-sun8i-a23.c @@ -751,6 +751,7 @@ static const struct of_device_id sun8i_a23_ccu_ids[] = { { .compatible = "allwinner,sun8i-a23-ccu" }, { } }; +MODULE_DEVICE_TABLE(of, sun8i_a23_ccu_ids); static struct platform_driver sun8i_a23_ccu_driver = { .probe = sun8i_a23_ccu_probe, diff --git a/drivers/clk/sunxi-ng/ccu-sun8i-a33.c b/drivers/clk/sunxi-ng/ccu-sun8i-a33.c index d12878a1ba9e..8a27a1777600 100644 --- a/drivers/clk/sunxi-ng/ccu-sun8i-a33.c +++ b/drivers/clk/sunxi-ng/ccu-sun8i-a33.c @@ -823,6 +823,7 @@ static const struct of_device_id sun8i_a33_ccu_ids[] = { { .compatible = "allwinner,sun8i-a33-ccu" }, { } }; +MODULE_DEVICE_TABLE(of, sun8i_a33_ccu_ids); static struct platform_driver sun8i_a33_ccu_driver = { .probe = sun8i_a33_ccu_probe, diff --git a/drivers/clk/sunxi-ng/ccu-sun8i-a83t.c b/drivers/clk/sunxi-ng/ccu-sun8i-a83t.c index 76cbd9e9e89f..93eca47935cf 100644 --- a/drivers/clk/sunxi-ng/ccu-sun8i-a83t.c +++ b/drivers/clk/sunxi-ng/ccu-sun8i-a83t.c @@ -911,6 +911,7 @@ static const struct of_device_id sun8i_a83t_ccu_ids[] = { { .compatible = "allwinner,sun8i-a83t-ccu" }, { } }; +MODULE_DEVICE_TABLE(of, sun8i_a83t_ccu_ids); static struct platform_driver sun8i_a83t_ccu_driver = { .probe = sun8i_a83t_ccu_probe, diff --git a/drivers/clk/sunxi-ng/ccu-sun8i-de2.c b/drivers/clk/sunxi-ng/ccu-sun8i-de2.c index 6a043a0a9dd6..b0b8dba239ae 100644 --- a/drivers/clk/sunxi-ng/ccu-sun8i-de2.c +++ b/drivers/clk/sunxi-ng/ccu-sun8i-de2.c @@ -337,6 +337,7 @@ static const struct of_device_id sunxi_de2_clk_ids[] = { }, { } }; +MODULE_DEVICE_TABLE(of, sunxi_de2_clk_ids); static struct platform_driver sunxi_de2_clk_driver = { .probe = sunxi_de2_clk_probe, diff --git a/drivers/clk/sunxi-ng/ccu-sun8i-h3.c b/drivers/clk/sunxi-ng/ccu-sun8i-h3.c index 74274c17efb3..ca5739fa04f7 100644 --- a/drivers/clk/sunxi-ng/ccu-sun8i-h3.c +++ b/drivers/clk/sunxi-ng/ccu-sun8i-h3.c @@ -1082,6 +1082,7 @@ static const struct of_device_id sun8i_h3_ccu_ids[] = { }, { } }; +MODULE_DEVICE_TABLE(of, sun8i_h3_ccu_ids); static struct platform_driver sun8i_h3_ccu_driver = { .probe = sun8i_h3_ccu_probe, diff --git a/drivers/clk/sunxi-ng/ccu-sun8i-r.c b/drivers/clk/sunxi-ng/ccu-sun8i-r.c index 4890a976b1a0..bac7e737db98 100644 --- a/drivers/clk/sunxi-ng/ccu-sun8i-r.c +++ b/drivers/clk/sunxi-ng/ccu-sun8i-r.c @@ -262,6 +262,7 @@ static const struct of_device_id sun8i_r_ccu_ids[] = { }, { } }; +MODULE_DEVICE_TABLE(of, sun8i_r_ccu_ids); static struct platform_driver sun8i_r_ccu_driver = { .probe = sun8i_r_ccu_probe, diff --git a/drivers/clk/sunxi-ng/ccu-sun8i-r40.c b/drivers/clk/sunxi-ng/ccu-sun8i-r40.c index 31eca0d3bc1e..3774b293e74c 100644 --- a/drivers/clk/sunxi-ng/ccu-sun8i-r40.c +++ b/drivers/clk/sunxi-ng/ccu-sun8i-r40.c @@ -1363,6 +1363,7 @@ static const struct of_device_id sun8i_r40_ccu_ids[] = { { .compatible = "allwinner,sun8i-r40-ccu" }, { } }; +MODULE_DEVICE_TABLE(of, sun8i_r40_ccu_ids); static struct platform_driver sun8i_r40_ccu_driver = { .probe = sun8i_r40_ccu_probe, diff --git a/drivers/clk/sunxi-ng/ccu-sun8i-v3s.c b/drivers/clk/sunxi-ng/ccu-sun8i-v3s.c index f3ce8664b288..994258a3ad2e 100644 --- a/drivers/clk/sunxi-ng/ccu-sun8i-v3s.c +++ b/drivers/clk/sunxi-ng/ccu-sun8i-v3s.c @@ -768,6 +768,7 @@ static const struct of_device_id sun8i_v3s_ccu_ids[] = { }, { } }; +MODULE_DEVICE_TABLE(of, sun8i_v3s_ccu_ids); static struct platform_driver sun8i_v3s_ccu_driver = { .probe = sun8i_v3s_ccu_probe, diff --git a/drivers/clk/sunxi-ng/ccu-sun9i-a80-de.c b/drivers/clk/sunxi-ng/ccu-sun9i-a80-de.c index 1d8b1ae1619d..ae7939d3f502 100644 --- a/drivers/clk/sunxi-ng/ccu-sun9i-a80-de.c +++ b/drivers/clk/sunxi-ng/ccu-sun9i-a80-de.c @@ -254,6 +254,7 @@ static const struct of_device_id sun9i_a80_de_clk_ids[] = { { .compatible = "allwinner,sun9i-a80-de-clks" }, { } }; +MODULE_DEVICE_TABLE(of, sun9i_a80_de_clk_ids); static struct platform_driver sun9i_a80_de_clk_driver = { .probe = sun9i_a80_de_clk_probe, diff --git a/drivers/clk/sunxi-ng/ccu-sun9i-a80-usb.c b/drivers/clk/sunxi-ng/ccu-sun9i-a80-usb.c index a0fb0da8f356..bfa2ff9d52a4 100644 --- a/drivers/clk/sunxi-ng/ccu-sun9i-a80-usb.c +++ b/drivers/clk/sunxi-ng/ccu-sun9i-a80-usb.c @@ -127,6 +127,7 @@ static const struct of_device_id sun9i_a80_usb_clk_ids[] = { { .compatible = "allwinner,sun9i-a80-usb-clks" }, { } }; +MODULE_DEVICE_TABLE(of, sun9i_a80_usb_clk_ids); static struct platform_driver sun9i_a80_usb_clk_driver = { .probe = sun9i_a80_usb_clk_probe, diff --git a/drivers/clk/sunxi-ng/ccu-sun9i-a80.c b/drivers/clk/sunxi-ng/ccu-sun9i-a80.c index 730fd8e28014..c05805e4ad22 100644 --- a/drivers/clk/sunxi-ng/ccu-sun9i-a80.c +++ b/drivers/clk/sunxi-ng/ccu-sun9i-a80.c @@ -1236,6 +1236,7 @@ static const struct of_device_id sun9i_a80_ccu_ids[] = { { .compatible = "allwinner,sun9i-a80-ccu" }, { } }; +MODULE_DEVICE_TABLE(of, sun9i_a80_ccu_ids); static struct platform_driver sun9i_a80_ccu_driver = { .probe = sun9i_a80_ccu_probe, diff --git a/drivers/clk/sunxi-ng/ccu-suniv-f1c100s.c b/drivers/clk/sunxi-ng/ccu-suniv-f1c100s.c index 0d5b60b123b7..76d3d070b2a7 100644 --- a/drivers/clk/sunxi-ng/ccu-suniv-f1c100s.c +++ b/drivers/clk/sunxi-ng/ccu-suniv-f1c100s.c @@ -565,6 +565,7 @@ static const struct of_device_id suniv_f1c100s_ccu_ids[] = { { .compatible = "allwinner,suniv-f1c100s-ccu" }, { } }; +MODULE_DEVICE_TABLE(of, suniv_f1c100s_ccu_ids); static struct platform_driver suniv_f1c100s_ccu_driver = { .probe = suniv_f1c100s_ccu_probe, From 0a7c2fda3448b8f11a32c3e2fe94e70bd468be33 Mon Sep 17 00:00:00 2001 From: Arnd Bergmann Date: Mon, 15 Apr 2024 15:45:20 +0200 Subject: [PATCH 047/118] clk: sophgo: avoid open-coded 64-bit division On 32-bit architectures, the 64-bit division leads to a link failure: arm-linux-gnueabi-ld: drivers/clk/sophgo/clk-cv18xx-pll.o: in function `fpll_calc_rate': clk-cv18xx-pll.c:(.text.fpll_calc_rate+0x26): undefined reference to `__aeabi_uldivmod' This one is not called in a fast path, and there is already another div_u64() variant used in the same function, so convert it to div64_u64_rem(). Fixes: 80fd61ec4612 ("clk: sophgo: Add clock support for CV1800 SoC") Signed-off-by: Arnd Bergmann Link: https://lore.kernel.org/r/20240415134532.3467817-1-arnd@kernel.org Reported-by: kernel test robot Closes: https://lore.kernel.org/oe-kbuild-all/202404122344.d5pb2N1I-lkp@intel.com/ Closes: https://lore.kernel.org/oe-kbuild-all/202404140310.QEjZKtTN-lkp@intel.com/ Reviewed-by: Inochi Amaoto Signed-off-by: Stephen Boyd --- drivers/clk/sophgo/clk-cv18xx-pll.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/drivers/clk/sophgo/clk-cv18xx-pll.c b/drivers/clk/sophgo/clk-cv18xx-pll.c index c546dad1791c..29e24098bf5f 100644 --- a/drivers/clk/sophgo/clk-cv18xx-pll.c +++ b/drivers/clk/sophgo/clk-cv18xx-pll.c @@ -205,8 +205,7 @@ static unsigned long fpll_calc_rate(unsigned long parent_rate, unsigned long rate; dividend <<= PLL_SYN_FACTOR_DOT_POS - 1; - rate = dividend / factor; - dividend %= factor; + rate = div64_u64_rem(dividend, factor, ÷nd); if (is_full_parent) { dividend <<= 1; From 4c0c087772d7e29bc2489ddb068d5167140bfc38 Mon Sep 17 00:00:00 2001 From: Alexandre Mergnat Date: Thu, 18 Apr 2024 16:17:00 +0200 Subject: [PATCH 048/118] clk: mediatek: mt8365-mm: fix DPI0 parent To have a working display through DPI, a workaround has been implemented downstream to add "mm_dpi0_dpi0" and "dpi0_sel" to the DPI node. Shortly, that add an extra clock. It seems consistent to have the "dpi0_sel" as parent. Additionnaly, "vpll_dpix" isn't used/managed. Then, set the "mm_dpi0_dpi0" parent clock to "dpi0_sel". The new clock tree is: clk26m lvdspll lvdspll_X (2, 4, 8, 16) dpi0_sel mm_dpi0_dpi0 Fixes: d46adccb7966 ("clk: mediatek: add driver for MT8365 SoC") Signed-off-by: Alexandre Mergnat Link: https://lore.kernel.org/r/20231023-display-support-v3-12-53388f3ed34b@baylibre.com Reviewed-by: AngeloGioacchino Del Regno Signed-off-by: Stephen Boyd --- drivers/clk/mediatek/clk-mt8365-mm.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/clk/mediatek/clk-mt8365-mm.c b/drivers/clk/mediatek/clk-mt8365-mm.c index 01a2ef8f594e..3f62ec750733 100644 --- a/drivers/clk/mediatek/clk-mt8365-mm.c +++ b/drivers/clk/mediatek/clk-mt8365-mm.c @@ -53,7 +53,7 @@ static const struct mtk_gate mm_clks[] = { GATE_MM0(CLK_MM_MM_DSI0, "mm_dsi0", "mm_sel", 17), GATE_MM0(CLK_MM_MM_DISP_RDMA1, "mm_disp_rdma1", "mm_sel", 18), GATE_MM0(CLK_MM_MM_MDP_RDMA1, "mm_mdp_rdma1", "mm_sel", 19), - GATE_MM0(CLK_MM_DPI0_DPI0, "mm_dpi0_dpi0", "vpll_dpix", 20), + GATE_MM0(CLK_MM_DPI0_DPI0, "mm_dpi0_dpi0", "dpi0_sel", 20), GATE_MM0(CLK_MM_MM_FAKE, "mm_fake", "mm_sel", 21), GATE_MM0(CLK_MM_MM_SMI_COMMON, "mm_smi_common", "mm_sel", 22), GATE_MM0(CLK_MM_MM_SMI_LARB0, "mm_smi_larb0", "mm_sel", 23), From 5677925ed74759be0c46bb7b6a9cfc5ebf957523 Mon Sep 17 00:00:00 2001 From: Christophe JAILLET Date: Sat, 13 Apr 2024 15:54:35 +0200 Subject: [PATCH 049/118] clk: highbank: Remove an unused field in struct hb_clk In "struct hb_clk", the 'parent_name' field is unused. Remove it. Found with cppcheck, unusedStructMember. Signed-off-by: Christophe JAILLET Link: https://lore.kernel.org/r/90b19f2af3077075d4254e01d5ae919c423d067e.1713016457.git.christophe.jaillet@wanadoo.fr Signed-off-by: Stephen Boyd --- drivers/clk/clk-highbank.c | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/clk/clk-highbank.c b/drivers/clk/clk-highbank.c index 2a0cea2946f9..6e68a41a70a1 100644 --- a/drivers/clk/clk-highbank.c +++ b/drivers/clk/clk-highbank.c @@ -37,7 +37,6 @@ struct hb_clk { struct clk_hw hw; void __iomem *reg; - char *parent_name; }; #define to_hb_clk(p) container_of(p, struct hb_clk, hw) From 8e931ef1bdc5d60c530d182eeccad8b7e1ad6ed1 Mon Sep 17 00:00:00 2001 From: Christophe JAILLET Date: Sat, 13 Apr 2024 15:46:09 +0200 Subject: [PATCH 050/118] clk: gemini: Remove an unused field in struct clk_gemini_pci In "struct clk_gemini_pci", the 'rate' field is unused. Remove it. Found with cppcheck, unusedStructMember. Signed-off-by: Christophe JAILLET Link: https://lore.kernel.org/r/556770c7701868f9f1c0569674903bee3eff30cb.1713015940.git.christophe.jaillet@wanadoo.fr Signed-off-by: Stephen Boyd --- drivers/clk/clk-gemini.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/drivers/clk/clk-gemini.c b/drivers/clk/clk-gemini.c index ba0ff01bf4dc..856b008e07c6 100644 --- a/drivers/clk/clk-gemini.c +++ b/drivers/clk/clk-gemini.c @@ -67,12 +67,10 @@ struct gemini_gate_data { * struct clk_gemini_pci - Gemini PCI clock * @hw: corresponding clock hardware entry * @map: regmap to access the registers - * @rate: current rate */ struct clk_gemini_pci { struct clk_hw hw; struct regmap *map; - unsigned long rate; }; /** From 1758c68c81b8b881818fcebaaeb91055362a82f8 Mon Sep 17 00:00:00 2001 From: Catalin Popescu Date: Mon, 15 Apr 2024 16:03:48 +0200 Subject: [PATCH 051/118] clk: rs9: fix wrong default value for clock amplitude According to 9FGV0241, 9FGV0441 & 9FGV0841 datasheets, the default value for the clock amplitude is 0.8V, while the driver assumes 0.7V. Additionally, define constants for default values for both clock amplitude and spread spectrum and use them. Fixes: 892e0ddea1aa ("clk: rs9: Add Renesas 9-series PCIe clock generator driver") Signed-off-by: Catalin Popescu Reviewed-by: Marek Vasut Link: https://lore.kernel.org/r/20240415140348.2887619-1-catalin.popescu@leica-geosystems.com Signed-off-by: Stephen Boyd --- drivers/clk/clk-renesas-pcie.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/drivers/clk/clk-renesas-pcie.c b/drivers/clk/clk-renesas-pcie.c index 53e21ac302e6..4c3a5e4eb77a 100644 --- a/drivers/clk/clk-renesas-pcie.c +++ b/drivers/clk/clk-renesas-pcie.c @@ -25,10 +25,12 @@ #define RS9_REG_SS_AMP_0V7 0x1 #define RS9_REG_SS_AMP_0V8 0x2 #define RS9_REG_SS_AMP_0V9 0x3 +#define RS9_REG_SS_AMP_DEFAULT RS9_REG_SS_AMP_0V8 #define RS9_REG_SS_AMP_MASK 0x3 #define RS9_REG_SS_SSC_100 0 #define RS9_REG_SS_SSC_M025 (1 << 3) #define RS9_REG_SS_SSC_M050 (3 << 3) +#define RS9_REG_SS_SSC_DEFAULT RS9_REG_SS_SSC_100 #define RS9_REG_SS_SSC_MASK (3 << 3) #define RS9_REG_SS_SSC_LOCK BIT(5) #define RS9_REG_SR 0x2 @@ -205,8 +207,8 @@ static int rs9_get_common_config(struct rs9_driver_data *rs9) int ret; /* Set defaults */ - rs9->pll_amplitude = RS9_REG_SS_AMP_0V7; - rs9->pll_ssc = RS9_REG_SS_SSC_100; + rs9->pll_amplitude = RS9_REG_SS_AMP_DEFAULT; + rs9->pll_ssc = RS9_REG_SS_SSC_DEFAULT; /* Output clock amplitude */ ret = of_property_read_u32(np, "renesas,out-amplitude-microvolt", @@ -247,13 +249,13 @@ static void rs9_update_config(struct rs9_driver_data *rs9) int i; /* If amplitude is non-default, update it. */ - if (rs9->pll_amplitude != RS9_REG_SS_AMP_0V7) { + if (rs9->pll_amplitude != RS9_REG_SS_AMP_DEFAULT) { regmap_update_bits(rs9->regmap, RS9_REG_SS, RS9_REG_SS_AMP_MASK, rs9->pll_amplitude); } /* If SSC is non-default, update it. */ - if (rs9->pll_ssc != RS9_REG_SS_SSC_100) { + if (rs9->pll_ssc != RS9_REG_SS_SSC_DEFAULT) { regmap_update_bits(rs9->regmap, RS9_REG_SS, RS9_REG_SS_SSC_MASK, rs9->pll_ssc); } From 810e6d2fac01ab1e189f3002a364f19bd5d0f444 Mon Sep 17 00:00:00 2001 From: Abel Vesa Date: Thu, 18 Apr 2024 16:41:32 +0300 Subject: [PATCH 052/118] clk: qcom: clk-alpha-pll: Skip reconfiguring the running Lucid Evo The PLL0 is configured by the bootloader and is the parent of the mdp_clk_src. The Trion implementation of the configure function is already skipping this step if the PLL is enabled, so lets extend the same behavior to Lucid Evo variant. Signed-off-by: Abel Vesa Reviewed-by: Bjorn Andersson Link: https://lore.kernel.org/r/20240418-clk-qcom-lucid-evo-skip-configuring-enabled-v1-1-caede5f1c7a3@linaro.org Signed-off-by: Bjorn Andersson --- drivers/clk/qcom/clk-alpha-pll.c | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/drivers/clk/qcom/clk-alpha-pll.c b/drivers/clk/qcom/clk-alpha-pll.c index 8a412ef47e16..4c5aeccff0ef 100644 --- a/drivers/clk/qcom/clk-alpha-pll.c +++ b/drivers/clk/qcom/clk-alpha-pll.c @@ -2114,6 +2114,15 @@ void clk_lucid_evo_pll_configure(struct clk_alpha_pll *pll, struct regmap *regma { u32 lval = config->l; + /* + * If the bootloader left the PLL enabled it's likely that there are + * RCGs that will lock up if we disable the PLL below. + */ + if (trion_pll_is_enabled(pll, regmap)) { + pr_debug("Lucid Evo PLL is already enabled, skipping configuration\n"); + return; + } + lval |= TRION_PLL_CAL_VAL << LUCID_EVO_PLL_CAL_L_VAL_SHIFT; clk_alpha_pll_write_config(regmap, PLL_L_VAL(pll), lval); clk_alpha_pll_write_config(regmap, PLL_ALPHA_VAL(pll), config->alpha); From 3cb55215479f04940240792479c60fad53c2d202 Mon Sep 17 00:00:00 2001 From: Christophe JAILLET Date: Sat, 13 Apr 2024 16:04:04 +0200 Subject: [PATCH 053/118] clk: qcom: rpm: Remove an unused field in struct rpm_cc In "struct rpm_cc", the 'rpm' field is unused. Remove it. Found with cppcheck, unusedStructMember. Signed-off-by: Christophe JAILLET Reviewed-by: Stephen Boyd Link: https://lore.kernel.org/r/9f92330c717e6f2dab27b1307565ffb108c304a7.1713017032.git.christophe.jaillet@wanadoo.fr Signed-off-by: Bjorn Andersson --- drivers/clk/qcom/clk-rpm.c | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/clk/qcom/clk-rpm.c b/drivers/clk/qcom/clk-rpm.c index 745026ef4d9c..9da034f8f2ff 100644 --- a/drivers/clk/qcom/clk-rpm.c +++ b/drivers/clk/qcom/clk-rpm.c @@ -98,7 +98,6 @@ struct clk_rpm { }; struct rpm_cc { - struct qcom_rpm *rpm; struct clk_rpm **clks; size_t num_clks; u32 xo_buffer_value; From 7ca07a174f3b4021ae0a2d60fed1f5c993cf4b49 Mon Sep 17 00:00:00 2001 From: Satya Priya Kakitapalli Date: Tue, 13 Feb 2024 12:17:24 +0530 Subject: [PATCH 054/118] clk: qcom: gcc-sm8150: De-register gcc_cpuss_ahb_clk_src De-register the gcc_cpuss_ahb_clk_src and its branch clocks as there is no rate setting happening on them. Signed-off-by: Satya Priya Kakitapalli Link: https://lore.kernel.org/r/20240213-gcc-ao-support-v2-1-fd2127e8d8f4@quicinc.com Signed-off-by: Bjorn Andersson --- drivers/clk/qcom/gcc-sm8150.c | 61 ----------------------------------- 1 file changed, 61 deletions(-) diff --git a/drivers/clk/qcom/gcc-sm8150.c b/drivers/clk/qcom/gcc-sm8150.c index a47ef9dfa808..1f748141d12c 100644 --- a/drivers/clk/qcom/gcc-sm8150.c +++ b/drivers/clk/qcom/gcc-sm8150.c @@ -207,28 +207,6 @@ static const struct clk_parent_data gcc_parents_7[] = { { .hw = &gpll0_out_even.clkr.hw }, }; -static const struct freq_tbl ftbl_gcc_cpuss_ahb_clk_src[] = { - F(19200000, P_BI_TCXO, 1, 0, 0), - F(50000000, P_GPLL0_OUT_MAIN, 12, 0, 0), - F(100000000, P_GPLL0_OUT_MAIN, 6, 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_parents_0, - .num_parents = ARRAY_SIZE(gcc_parents_0), - .flags = CLK_SET_RATE_PARENT, - .ops = &clk_rcg2_ops, - }, -}; - static const struct freq_tbl ftbl_gcc_emac_ptp_clk_src[] = { F(19200000, P_BI_TCXO, 1, 0, 0), F(50000000, P_GPLL0_OUT_EVEN, 6, 0, 0), @@ -1361,24 +1339,6 @@ static struct clk_branch gcc_cfg_noc_usb3_sec_axi_clk = { }, }; -static struct clk_branch gcc_cpuss_ahb_clk = { - .halt_reg = 0x48000, - .halt_check = BRANCH_HALT_VOTED, - .clkr = { - .enable_reg = 0x52004, - .enable_mask = BIT(21), - .hw.init = &(struct clk_init_data){ - .name = "gcc_cpuss_ahb_clk", - .parent_hws = (const struct clk_hw *[]){ - &gcc_cpuss_ahb_clk_src.clkr.hw }, - .num_parents = 1, - /* required for cpuss */ - .flags = CLK_IS_CRITICAL | CLK_SET_RATE_PARENT, - .ops = &clk_branch2_ops, - }, - }, -}; - static struct clk_branch gcc_cpuss_dvm_bus_clk = { .halt_reg = 0x48190, .halt_check = BRANCH_HALT, @@ -2685,24 +2645,6 @@ static struct clk_branch gcc_sdcc4_apps_clk = { }, }; -static struct clk_branch gcc_sys_noc_cpuss_ahb_clk = { - .halt_reg = 0x4819c, - .halt_check = BRANCH_HALT_VOTED, - .clkr = { - .enable_reg = 0x52004, - .enable_mask = BIT(0), - .hw.init = &(struct clk_init_data){ - .name = "gcc_sys_noc_cpuss_ahb_clk", - .parent_hws = (const struct clk_hw *[]){ - &gcc_cpuss_ahb_clk_src.clkr.hw }, - .num_parents = 1, - /* required for cpuss */ - .flags = CLK_IS_CRITICAL | CLK_SET_RATE_PARENT, - .ops = &clk_branch2_ops, - }, - }, -}; - static struct clk_branch gcc_tsif_ahb_clk = { .halt_reg = 0x36004, .halt_check = BRANCH_HALT, @@ -3550,8 +3492,6 @@ static struct clk_regmap *gcc_sm8150_clocks[] = { [GCC_CAMERA_XO_CLK] = &gcc_camera_xo_clk.clkr, [GCC_CFG_NOC_USB3_PRIM_AXI_CLK] = &gcc_cfg_noc_usb3_prim_axi_clk.clkr, [GCC_CFG_NOC_USB3_SEC_AXI_CLK] = &gcc_cfg_noc_usb3_sec_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_DVM_BUS_CLK] = &gcc_cpuss_dvm_bus_clk.clkr, [GCC_CPUSS_GNOC_CLK] = &gcc_cpuss_gnoc_clk.clkr, [GCC_CPUSS_RBCPR_CLK] = &gcc_cpuss_rbcpr_clk.clkr, @@ -3669,7 +3609,6 @@ static struct clk_regmap *gcc_sm8150_clocks[] = { [GCC_SDCC4_AHB_CLK] = &gcc_sdcc4_ahb_clk.clkr, [GCC_SDCC4_APPS_CLK] = &gcc_sdcc4_apps_clk.clkr, [GCC_SDCC4_APPS_CLK_SRC] = &gcc_sdcc4_apps_clk_src.clkr, - [GCC_SYS_NOC_CPUSS_AHB_CLK] = &gcc_sys_noc_cpuss_ahb_clk.clkr, [GCC_TSIF_AHB_CLK] = &gcc_tsif_ahb_clk.clkr, [GCC_TSIF_INACTIVITY_TIMERS_CLK] = &gcc_tsif_inactivity_timers_clk.clkr, [GCC_TSIF_REF_CLK] = &gcc_tsif_ref_clk.clkr, From 4f2bc4acbb1916b8cd2ce4bb3ba7b1cd7cb705fa Mon Sep 17 00:00:00 2001 From: Gabor Juhos Date: Mon, 11 Mar 2024 19:45:19 +0100 Subject: [PATCH 055/118] clk: qcom: clk-alpha-pll: remove invalid Stromer register offset The offset of the CONFIG_CTL_U register defined for the Stromer PLL is wrong. It is not aligned on a 4 bytes boundary which might causes errors in regmap operations. Maybe the intention behind of using the 0xff value was to indicate that the register is not implemented in the PLL, but this is not verified anywhere in the code. Moreover, this value is not used even in other register offset arrays despite that those PLLs also have unimplemented registers. Additionally, on the Stromer PLLs the current code only touches the CONFIG_CTL_U register if the result of pll_has_64bit_config() is true which condition is not affected by the change. Due to the reasons above, simply remove the CONFIG_CTL_U entry from the Stromer specific array. Fixes: e47a4f55f240 ("clk: qcom: clk-alpha-pll: Add support for Stromer PLLs") Signed-off-by: Gabor Juhos Reviewed-by: Konrad Dybcio Link: https://lore.kernel.org/r/20240311-alpha-pll-stromer-cleanup-v1-1-f7c0c5607cca@gmail.com Signed-off-by: Bjorn Andersson --- drivers/clk/qcom/clk-alpha-pll.c | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/clk/qcom/clk-alpha-pll.c b/drivers/clk/qcom/clk-alpha-pll.c index 4c5aeccff0ef..acb68ec0c579 100644 --- a/drivers/clk/qcom/clk-alpha-pll.c +++ b/drivers/clk/qcom/clk-alpha-pll.c @@ -213,7 +213,6 @@ const u8 clk_alpha_pll_regs[][PLL_OFF_MAX_REGS] = { [PLL_OFF_USER_CTL] = 0x18, [PLL_OFF_USER_CTL_U] = 0x1c, [PLL_OFF_CONFIG_CTL] = 0x20, - [PLL_OFF_CONFIG_CTL_U] = 0xff, [PLL_OFF_TEST_CTL] = 0x30, [PLL_OFF_TEST_CTL_U] = 0x34, [PLL_OFF_STATUS] = 0x28, From 8c48466cd7eda9afb37f26c8c9a68f39fae5ef32 Mon Sep 17 00:00:00 2001 From: Gabor Juhos Date: Mon, 11 Mar 2024 19:45:20 +0100 Subject: [PATCH 056/118] clk: qcom: clk-alpha-pll: reorder Stromer register offsets The register offset arrays are ordered based on the register offsets for all PLLs but the Stromer. For consistency, reorder the Stromer specific array as well. No functional changes. Signed-off-by: Gabor Juhos Reviewed-by: Konrad Dybcio Link: https://lore.kernel.org/r/20240311-alpha-pll-stromer-cleanup-v1-2-f7c0c5607cca@gmail.com Signed-off-by: Bjorn Andersson --- drivers/clk/qcom/clk-alpha-pll.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/clk/qcom/clk-alpha-pll.c b/drivers/clk/qcom/clk-alpha-pll.c index acb68ec0c579..7f0ed5bd51e3 100644 --- a/drivers/clk/qcom/clk-alpha-pll.c +++ b/drivers/clk/qcom/clk-alpha-pll.c @@ -213,9 +213,9 @@ const u8 clk_alpha_pll_regs[][PLL_OFF_MAX_REGS] = { [PLL_OFF_USER_CTL] = 0x18, [PLL_OFF_USER_CTL_U] = 0x1c, [PLL_OFF_CONFIG_CTL] = 0x20, + [PLL_OFF_STATUS] = 0x28, [PLL_OFF_TEST_CTL] = 0x30, [PLL_OFF_TEST_CTL_U] = 0x34, - [PLL_OFF_STATUS] = 0x28, }, [CLK_ALPHA_PLL_TYPE_STROMER_PLUS] = { [PLL_OFF_L_VAL] = 0x04, From 3b985489178cfb545118bd4dbefb6311f4bbfcf2 Mon Sep 17 00:00:00 2001 From: Gabor Juhos Date: Thu, 21 Mar 2024 09:59:04 +0100 Subject: [PATCH 057/118] clk: qcom: clk-alpha-pll: fix kerneldoc of struct clk_alpha_pll Add missing descriptions of the 'num_vco' and 'flags' members to clk_alpha_pll structure's documentation. Also reorder the member description entries to match the order of the declarations. Eliminates the following warnings: drivers/clk/qcom/clk-alpha-pll.h:72: info: Scanning doc for struct clk_alpha_pll drivers/clk/qcom/clk-alpha-pll.h:91: warning: Function parameter or struct member 'num_vco' not described in 'clk_alpha_pll' drivers/clk/qcom/clk-alpha-pll.h:91: warning: Function parameter or struct member 'flags' not described in 'clk_alpha_pll' No functional changes. Signed-off-by: Gabor Juhos Reviewed-by: Dmitry Baryshkov Link: https://lore.kernel.org/r/20240321-alpha-pll-kerneldoc-v1-1-0d76926b72c3@gmail.com Signed-off-by: Bjorn Andersson --- drivers/clk/qcom/clk-alpha-pll.h | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/drivers/clk/qcom/clk-alpha-pll.h b/drivers/clk/qcom/clk-alpha-pll.h index fb6d50263bb9..1bb2d031dc9f 100644 --- a/drivers/clk/qcom/clk-alpha-pll.h +++ b/drivers/clk/qcom/clk-alpha-pll.h @@ -73,8 +73,10 @@ struct pll_vco { /** * struct clk_alpha_pll - phase locked loop (PLL) * @offset: base address of registers - * @vco_table: array of VCO settings * @regs: alpha pll register map (see @clk_alpha_pll_regs) + * @vco_table: array of VCO settings + * @num_vco: number of VCO settings in @vco_table + * @flags: bitmask to indicate features supported by the hardware * @clkr: regmap clock handle */ struct clk_alpha_pll { From 1496dd413b2e0974a040fa93a2ddc51cc9847fd8 Mon Sep 17 00:00:00 2001 From: Shengjiu Wang Date: Thu, 21 Mar 2024 21:14:02 +0800 Subject: [PATCH 058/118] clk: imx: imx8mp: Add pm_runtime support for power saving Add pm_runtime support for power saving. In pm runtime suspend state the registers will be reseted, so add registers save in pm runtime suspend and restore them in pm runtime resume. Signed-off-by: Shengjiu Wang Reviewed-by: Peng Fan Reviewed-by: Marc Kleine-Budde Link: https://lore.kernel.org/r/1711026842-7268-1-git-send-email-shengjiu.wang@nxp.com Signed-off-by: Abel Vesa --- drivers/clk/imx/clk-imx8mp-audiomix.c | 157 ++++++++++++++++++++++---- 1 file changed, 136 insertions(+), 21 deletions(-) diff --git a/drivers/clk/imx/clk-imx8mp-audiomix.c b/drivers/clk/imx/clk-imx8mp-audiomix.c index 55ed211a5e0b..574a032309c1 100644 --- a/drivers/clk/imx/clk-imx8mp-audiomix.c +++ b/drivers/clk/imx/clk-imx8mp-audiomix.c @@ -7,10 +7,12 @@ #include #include +#include #include #include #include #include +#include #include @@ -18,6 +20,7 @@ #define CLKEN0 0x000 #define CLKEN1 0x004 +#define EARC 0x200 #define SAI1_MCLK_SEL 0x300 #define SAI2_MCLK_SEL 0x304 #define SAI3_MCLK_SEL 0x308 @@ -26,6 +29,11 @@ #define SAI7_MCLK_SEL 0x314 #define PDM_SEL 0x318 #define SAI_PLL_GNRL_CTL 0x400 +#define SAI_PLL_FDIVL_CTL0 0x404 +#define SAI_PLL_FDIVL_CTL1 0x408 +#define SAI_PLL_SSCG_CTL 0x40C +#define SAI_PLL_MNIT_CTL 0x410 +#define IPG_LP_CTRL 0x504 #define SAIn_MCLK1_PARENT(n) \ static const struct clk_parent_data \ @@ -182,26 +190,82 @@ static struct clk_imx8mp_audiomix_sel sels[] = { CLK_SAIn(7) }; +static const u16 audiomix_regs[] = { + CLKEN0, + CLKEN1, + EARC, + SAI1_MCLK_SEL, + SAI2_MCLK_SEL, + SAI3_MCLK_SEL, + SAI5_MCLK_SEL, + SAI6_MCLK_SEL, + SAI7_MCLK_SEL, + PDM_SEL, + SAI_PLL_GNRL_CTL, + SAI_PLL_FDIVL_CTL0, + SAI_PLL_FDIVL_CTL1, + SAI_PLL_SSCG_CTL, + SAI_PLL_MNIT_CTL, + IPG_LP_CTRL, +}; + +struct clk_imx8mp_audiomix_priv { + void __iomem *base; + u32 regs_save[ARRAY_SIZE(audiomix_regs)]; + + /* Must be last */ + struct clk_hw_onecell_data clk_data; +}; + +static void clk_imx8mp_audiomix_save_restore(struct device *dev, bool save) +{ + struct clk_imx8mp_audiomix_priv *priv = dev_get_drvdata(dev); + void __iomem *base = priv->base; + int i; + + if (save) { + for (i = 0; i < ARRAY_SIZE(audiomix_regs); i++) + priv->regs_save[i] = readl(base + audiomix_regs[i]); + } else { + for (i = 0; i < ARRAY_SIZE(audiomix_regs); i++) + writel(priv->regs_save[i], base + audiomix_regs[i]); + } +} + static int clk_imx8mp_audiomix_probe(struct platform_device *pdev) { - struct clk_hw_onecell_data *priv; + struct clk_imx8mp_audiomix_priv *priv; + struct clk_hw_onecell_data *clk_hw_data; struct device *dev = &pdev->dev; void __iomem *base; struct clk_hw *hw; - int i; + int i, ret; priv = devm_kzalloc(dev, - struct_size(priv, hws, IMX8MP_CLK_AUDIOMIX_END), + struct_size(priv, clk_data.hws, IMX8MP_CLK_AUDIOMIX_END), GFP_KERNEL); if (!priv) return -ENOMEM; - priv->num = IMX8MP_CLK_AUDIOMIX_END; + clk_hw_data = &priv->clk_data; + clk_hw_data->num = IMX8MP_CLK_AUDIOMIX_END; base = devm_platform_ioremap_resource(pdev, 0); if (IS_ERR(base)) return PTR_ERR(base); + priv->base = base; + dev_set_drvdata(dev, priv); + + /* + * pm_runtime_enable needs to be called before clk register. + * That is to make core->rpm_enabled to be true for clock + * usage. + */ + pm_runtime_get_noresume(dev); + pm_runtime_set_active(dev); + pm_runtime_enable(dev); + for (i = 0; i < ARRAY_SIZE(sels); i++) { if (sels[i].num_parents == 1) { hw = devm_clk_hw_register_gate_parent_data(dev, @@ -216,10 +280,12 @@ static int clk_imx8mp_audiomix_probe(struct platform_device *pdev) 0, NULL, NULL); } - if (IS_ERR(hw)) - return PTR_ERR(hw); + if (IS_ERR(hw)) { + ret = PTR_ERR(hw); + goto err_clk_register; + } - priv->hws[sels[i].clkid] = hw; + clk_hw_data->hws[sels[i].clkid] = hw; } /* SAI PLL */ @@ -228,39 +294,86 @@ static int clk_imx8mp_audiomix_probe(struct platform_device *pdev) ARRAY_SIZE(clk_imx8mp_audiomix_pll_parents), CLK_SET_RATE_NO_REPARENT, base + SAI_PLL_GNRL_CTL, 0, 2, 0, NULL, NULL); - priv->hws[IMX8MP_CLK_AUDIOMIX_SAI_PLL_REF_SEL] = hw; + clk_hw_data->hws[IMX8MP_CLK_AUDIOMIX_SAI_PLL_REF_SEL] = hw; hw = imx_dev_clk_hw_pll14xx(dev, "sai_pll", "sai_pll_ref_sel", base + 0x400, &imx_1443x_pll); - if (IS_ERR(hw)) - return PTR_ERR(hw); - priv->hws[IMX8MP_CLK_AUDIOMIX_SAI_PLL] = hw; + if (IS_ERR(hw)) { + ret = PTR_ERR(hw); + goto err_clk_register; + } + clk_hw_data->hws[IMX8MP_CLK_AUDIOMIX_SAI_PLL] = hw; hw = devm_clk_hw_register_mux_parent_data_table(dev, "sai_pll_bypass", clk_imx8mp_audiomix_pll_bypass_sels, ARRAY_SIZE(clk_imx8mp_audiomix_pll_bypass_sels), CLK_SET_RATE_NO_REPARENT | CLK_SET_RATE_PARENT, base + SAI_PLL_GNRL_CTL, 16, 1, 0, NULL, NULL); - if (IS_ERR(hw)) - return PTR_ERR(hw); - priv->hws[IMX8MP_CLK_AUDIOMIX_SAI_PLL_BYPASS] = hw; + if (IS_ERR(hw)) { + ret = PTR_ERR(hw); + goto err_clk_register; + } + + clk_hw_data->hws[IMX8MP_CLK_AUDIOMIX_SAI_PLL_BYPASS] = hw; hw = devm_clk_hw_register_gate(dev, "sai_pll_out", "sai_pll_bypass", 0, base + SAI_PLL_GNRL_CTL, 13, 0, NULL); - if (IS_ERR(hw)) - return PTR_ERR(hw); - priv->hws[IMX8MP_CLK_AUDIOMIX_SAI_PLL_OUT] = hw; + if (IS_ERR(hw)) { + ret = PTR_ERR(hw); + goto err_clk_register; + } + clk_hw_data->hws[IMX8MP_CLK_AUDIOMIX_SAI_PLL_OUT] = hw; hw = devm_clk_hw_register_fixed_factor(dev, "sai_pll_out_div2", "sai_pll_out", 0, 1, 2); - if (IS_ERR(hw)) - return PTR_ERR(hw); + if (IS_ERR(hw)) { + ret = PTR_ERR(hw); + goto err_clk_register; + } - return devm_of_clk_add_hw_provider(&pdev->dev, of_clk_hw_onecell_get, - priv); + ret = devm_of_clk_add_hw_provider(&pdev->dev, of_clk_hw_onecell_get, + clk_hw_data); + if (ret) + goto err_clk_register; + + pm_runtime_put_sync(dev); + return 0; + +err_clk_register: + pm_runtime_put_sync(dev); + pm_runtime_disable(dev); + return ret; } +static int clk_imx8mp_audiomix_remove(struct platform_device *pdev) +{ + pm_runtime_disable(&pdev->dev); + + return 0; +} + +static int clk_imx8mp_audiomix_runtime_suspend(struct device *dev) +{ + clk_imx8mp_audiomix_save_restore(dev, true); + + return 0; +} + +static int clk_imx8mp_audiomix_runtime_resume(struct device *dev) +{ + clk_imx8mp_audiomix_save_restore(dev, false); + + return 0; +} + +static const struct dev_pm_ops clk_imx8mp_audiomix_pm_ops = { + SET_RUNTIME_PM_OPS(clk_imx8mp_audiomix_runtime_suspend, + clk_imx8mp_audiomix_runtime_resume, NULL) + SET_NOIRQ_SYSTEM_SLEEP_PM_OPS(pm_runtime_force_suspend, + pm_runtime_force_resume) +}; + static const struct of_device_id clk_imx8mp_audiomix_of_match[] = { { .compatible = "fsl,imx8mp-audio-blk-ctrl" }, { /* sentinel */ } @@ -269,9 +382,11 @@ MODULE_DEVICE_TABLE(of, clk_imx8mp_audiomix_of_match); static struct platform_driver clk_imx8mp_audiomix_driver = { .probe = clk_imx8mp_audiomix_probe, + .remove = clk_imx8mp_audiomix_remove, .driver = { .name = "imx8mp-audio-blk-ctrl", .of_match_table = clk_imx8mp_audiomix_of_match, + .pm = &clk_imx8mp_audiomix_pm_ops, }, }; From 7b54d9113cd4923432c0b2441c5e2663873b4e5b Mon Sep 17 00:00:00 2001 From: Tudor Ambarus Date: Fri, 19 Apr 2024 10:09:14 +0000 Subject: [PATCH 059/118] clk: samsung: gs101: propagate PERIC0 USI SPI clock rate MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Introduce nMUX() for MUX clocks that can be reparented on clock rate change. "nMUX" comes from "n-to-1 selector", hopefully emphasising that the selector can change on clock rate changes. Ideally MUX/MUX_F() should change to not have the CLK_SET_RATE_NO_REPARENT flag set by default, and all their users to be updated to add the flag back (like in the case of DIV and GATE). But this is a very intrusive change and because for now only GS101 allows MUX reparenting on clock rate change, stick with nMUX(). GS101 defines MUX clocks that are dedicated for each instance of the IP. One example is USI IP (SPI, I2C, serial). The reparenting of these MUX clocks will not affect other instances of the same IP or different IPs altogether. When SPI transfer is being prepared, the spi-s3c64xx driver will call clk_set_rate() to change the rate of SPI source clock (IPCLK). But IPCLK is a gate (leaf) clock, so it must propagate the rate change up the clock tree, so that corresponding MUX/DIV clocks can actually change their values. Add CLK_SET_RATE_PARENT flag to corresponding clocks for all USI instances in GS101 PERIC0: USI{1-8, 14}. This change involves the following clocks: PERIC0 USI*: Clock Div range MUX Selection ------------------------------------------------------------------- gout_peric0_peric0_top0_ipclk_* - - dout_peric0_usi*_usi /1..16 - mout_peric0_usi*_usi_user - {24.5 MHz, 400 MHz} With input clock of 400 MHz this scheme provides the following IPCLK rate range, for each USI block: PERIC0 USI*: 1.5 MHz ... 400 MHz Accounting for internal /4 divider in SPI blocks, and because the max SPI frequency is limited at 50 MHz, it gives us next SPI SCK rates: PERIC0 USI_SPI*: 384 KHz ... 49.9 MHz Fixes: 893f133a040b ("clk: samsung: gs101: add support for cmu_peric0") Reviewed-by: Peter Griffin Acked-by: André Draszik Signed-off-by: Tudor Ambarus Link: https://lore.kernel.org/r/20240419100915.2168573-2-tudor.ambarus@linaro.org Signed-off-by: Krzysztof Kozlowski --- drivers/clk/samsung/clk-gs101.c | 135 +++++++++++++++++--------------- drivers/clk/samsung/clk.h | 11 ++- 2 files changed, 81 insertions(+), 65 deletions(-) diff --git a/drivers/clk/samsung/clk-gs101.c b/drivers/clk/samsung/clk-gs101.c index d065e343a85d..76d4d0fa1168 100644 --- a/drivers/clk/samsung/clk-gs101.c +++ b/drivers/clk/samsung/clk-gs101.c @@ -2763,33 +2763,33 @@ static const struct samsung_mux_clock peric0_mux_clks[] __initconst = { MUX(CLK_MOUT_PERIC0_USI0_UART_USER, "mout_peric0_usi0_uart_user", mout_peric0_usi0_uart_user_p, PLL_CON0_MUX_CLKCMU_PERIC0_USI0_UART_USER, 4, 1), - MUX(CLK_MOUT_PERIC0_USI14_USI_USER, - "mout_peric0_usi14_usi_user", mout_peric0_usi_usi_user_p, - PLL_CON0_MUX_CLKCMU_PERIC0_USI14_USI_USER, 4, 1), - MUX(CLK_MOUT_PERIC0_USI1_USI_USER, - "mout_peric0_usi1_usi_user", mout_peric0_usi_usi_user_p, - PLL_CON0_MUX_CLKCMU_PERIC0_USI1_USI_USER, 4, 1), - MUX(CLK_MOUT_PERIC0_USI2_USI_USER, - "mout_peric0_usi2_usi_user", mout_peric0_usi_usi_user_p, - PLL_CON0_MUX_CLKCMU_PERIC0_USI2_USI_USER, 4, 1), - MUX(CLK_MOUT_PERIC0_USI3_USI_USER, - "mout_peric0_usi3_usi_user", mout_peric0_usi_usi_user_p, - PLL_CON0_MUX_CLKCMU_PERIC0_USI3_USI_USER, 4, 1), - MUX(CLK_MOUT_PERIC0_USI4_USI_USER, - "mout_peric0_usi4_usi_user", mout_peric0_usi_usi_user_p, - PLL_CON0_MUX_CLKCMU_PERIC0_USI4_USI_USER, 4, 1), - MUX(CLK_MOUT_PERIC0_USI5_USI_USER, - "mout_peric0_usi5_usi_user", mout_peric0_usi_usi_user_p, - PLL_CON0_MUX_CLKCMU_PERIC0_USI5_USI_USER, 4, 1), - MUX(CLK_MOUT_PERIC0_USI6_USI_USER, - "mout_peric0_usi6_usi_user", mout_peric0_usi_usi_user_p, - PLL_CON0_MUX_CLKCMU_PERIC0_USI6_USI_USER, 4, 1), - MUX(CLK_MOUT_PERIC0_USI7_USI_USER, - "mout_peric0_usi7_usi_user", mout_peric0_usi_usi_user_p, - PLL_CON0_MUX_CLKCMU_PERIC0_USI7_USI_USER, 4, 1), - MUX(CLK_MOUT_PERIC0_USI8_USI_USER, - "mout_peric0_usi8_usi_user", mout_peric0_usi_usi_user_p, - PLL_CON0_MUX_CLKCMU_PERIC0_USI8_USI_USER, 4, 1), + nMUX(CLK_MOUT_PERIC0_USI14_USI_USER, + "mout_peric0_usi14_usi_user", mout_peric0_usi_usi_user_p, + PLL_CON0_MUX_CLKCMU_PERIC0_USI14_USI_USER, 4, 1), + nMUX(CLK_MOUT_PERIC0_USI1_USI_USER, + "mout_peric0_usi1_usi_user", mout_peric0_usi_usi_user_p, + PLL_CON0_MUX_CLKCMU_PERIC0_USI1_USI_USER, 4, 1), + nMUX(CLK_MOUT_PERIC0_USI2_USI_USER, + "mout_peric0_usi2_usi_user", mout_peric0_usi_usi_user_p, + PLL_CON0_MUX_CLKCMU_PERIC0_USI2_USI_USER, 4, 1), + nMUX(CLK_MOUT_PERIC0_USI3_USI_USER, + "mout_peric0_usi3_usi_user", mout_peric0_usi_usi_user_p, + PLL_CON0_MUX_CLKCMU_PERIC0_USI3_USI_USER, 4, 1), + nMUX(CLK_MOUT_PERIC0_USI4_USI_USER, + "mout_peric0_usi4_usi_user", mout_peric0_usi_usi_user_p, + PLL_CON0_MUX_CLKCMU_PERIC0_USI4_USI_USER, 4, 1), + nMUX(CLK_MOUT_PERIC0_USI5_USI_USER, + "mout_peric0_usi5_usi_user", mout_peric0_usi_usi_user_p, + PLL_CON0_MUX_CLKCMU_PERIC0_USI5_USI_USER, 4, 1), + nMUX(CLK_MOUT_PERIC0_USI6_USI_USER, + "mout_peric0_usi6_usi_user", mout_peric0_usi_usi_user_p, + PLL_CON0_MUX_CLKCMU_PERIC0_USI6_USI_USER, 4, 1), + nMUX(CLK_MOUT_PERIC0_USI7_USI_USER, + "mout_peric0_usi7_usi_user", mout_peric0_usi_usi_user_p, + PLL_CON0_MUX_CLKCMU_PERIC0_USI7_USI_USER, 4, 1), + nMUX(CLK_MOUT_PERIC0_USI8_USI_USER, + "mout_peric0_usi8_usi_user", mout_peric0_usi_usi_user_p, + PLL_CON0_MUX_CLKCMU_PERIC0_USI8_USI_USER, 4, 1), }; static const struct samsung_div_clock peric0_div_clks[] __initconst = { @@ -2798,33 +2798,42 @@ static const struct samsung_div_clock peric0_div_clks[] __initconst = { DIV(CLK_DOUT_PERIC0_USI0_UART, "dout_peric0_usi0_uart", "mout_peric0_usi0_uart_user", CLK_CON_DIV_DIV_CLK_PERIC0_USI0_UART, 0, 4), - DIV(CLK_DOUT_PERIC0_USI14_USI, - "dout_peric0_usi14_usi", "mout_peric0_usi14_usi_user", - CLK_CON_DIV_DIV_CLK_PERIC0_USI14_USI, 0, 4), - DIV(CLK_DOUT_PERIC0_USI1_USI, - "dout_peric0_usi1_usi", "mout_peric0_usi1_usi_user", - CLK_CON_DIV_DIV_CLK_PERIC0_USI1_USI, 0, 4), - DIV(CLK_DOUT_PERIC0_USI2_USI, - "dout_peric0_usi2_usi", "mout_peric0_usi2_usi_user", - CLK_CON_DIV_DIV_CLK_PERIC0_USI2_USI, 0, 4), - DIV(CLK_DOUT_PERIC0_USI3_USI, - "dout_peric0_usi3_usi", "mout_peric0_usi3_usi_user", - CLK_CON_DIV_DIV_CLK_PERIC0_USI3_USI, 0, 4), - DIV(CLK_DOUT_PERIC0_USI4_USI, - "dout_peric0_usi4_usi", "mout_peric0_usi4_usi_user", - CLK_CON_DIV_DIV_CLK_PERIC0_USI4_USI, 0, 4), - DIV(CLK_DOUT_PERIC0_USI5_USI, - "dout_peric0_usi5_usi", "mout_peric0_usi5_usi_user", - CLK_CON_DIV_DIV_CLK_PERIC0_USI5_USI, 0, 4), - DIV(CLK_DOUT_PERIC0_USI6_USI, - "dout_peric0_usi6_usi", "mout_peric0_usi6_usi_user", - CLK_CON_DIV_DIV_CLK_PERIC0_USI6_USI, 0, 4), - DIV(CLK_DOUT_PERIC0_USI7_USI, - "dout_peric0_usi7_usi", "mout_peric0_usi7_usi_user", - CLK_CON_DIV_DIV_CLK_PERIC0_USI7_USI, 0, 4), - DIV(CLK_DOUT_PERIC0_USI8_USI, - "dout_peric0_usi8_usi", "mout_peric0_usi8_usi_user", - CLK_CON_DIV_DIV_CLK_PERIC0_USI8_USI, 0, 4), + DIV_F(CLK_DOUT_PERIC0_USI14_USI, + "dout_peric0_usi14_usi", "mout_peric0_usi14_usi_user", + CLK_CON_DIV_DIV_CLK_PERIC0_USI14_USI, 0, 4, + CLK_SET_RATE_PARENT, 0), + DIV_F(CLK_DOUT_PERIC0_USI1_USI, + "dout_peric0_usi1_usi", "mout_peric0_usi1_usi_user", + CLK_CON_DIV_DIV_CLK_PERIC0_USI1_USI, 0, 4, + CLK_SET_RATE_PARENT, 0), + DIV_F(CLK_DOUT_PERIC0_USI2_USI, + "dout_peric0_usi2_usi", "mout_peric0_usi2_usi_user", + CLK_CON_DIV_DIV_CLK_PERIC0_USI2_USI, 0, 4, + CLK_SET_RATE_PARENT, 0), + DIV_F(CLK_DOUT_PERIC0_USI3_USI, + "dout_peric0_usi3_usi", "mout_peric0_usi3_usi_user", + CLK_CON_DIV_DIV_CLK_PERIC0_USI3_USI, 0, 4, + CLK_SET_RATE_PARENT, 0), + DIV_F(CLK_DOUT_PERIC0_USI4_USI, + "dout_peric0_usi4_usi", "mout_peric0_usi4_usi_user", + CLK_CON_DIV_DIV_CLK_PERIC0_USI4_USI, 0, 4, + CLK_SET_RATE_PARENT, 0), + DIV_F(CLK_DOUT_PERIC0_USI5_USI, + "dout_peric0_usi5_usi", "mout_peric0_usi5_usi_user", + CLK_CON_DIV_DIV_CLK_PERIC0_USI5_USI, 0, 4, + CLK_SET_RATE_PARENT, 0), + DIV_F(CLK_DOUT_PERIC0_USI6_USI, + "dout_peric0_usi6_usi", "mout_peric0_usi6_usi_user", + CLK_CON_DIV_DIV_CLK_PERIC0_USI6_USI, 0, 4, + CLK_SET_RATE_PARENT, 0), + DIV_F(CLK_DOUT_PERIC0_USI7_USI, + "dout_peric0_usi7_usi", "mout_peric0_usi7_usi_user", + CLK_CON_DIV_DIV_CLK_PERIC0_USI7_USI, 0, 4, + CLK_SET_RATE_PARENT, 0), + DIV_F(CLK_DOUT_PERIC0_USI8_USI, + "dout_peric0_usi8_usi", "mout_peric0_usi8_usi_user", + CLK_CON_DIV_DIV_CLK_PERIC0_USI8_USI, 0, 4, + CLK_SET_RATE_PARENT, 0), }; static const struct samsung_gate_clock peric0_gate_clks[] __initconst = { @@ -2857,11 +2866,11 @@ static const struct samsung_gate_clock peric0_gate_clks[] __initconst = { GATE(CLK_GOUT_PERIC0_PERIC0_TOP0_IPCLK_0, "gout_peric0_peric0_top0_ipclk_0", "dout_peric0_usi1_usi", CLK_CON_GAT_GOUT_BLK_PERIC0_UID_PERIC0_TOP0_IPCLKPORT_IPCLK_0, - 21, 0, 0), + 21, CLK_SET_RATE_PARENT, 0), GATE(CLK_GOUT_PERIC0_PERIC0_TOP0_IPCLK_1, "gout_peric0_peric0_top0_ipclk_1", "dout_peric0_usi2_usi", CLK_CON_GAT_GOUT_BLK_PERIC0_UID_PERIC0_TOP0_IPCLKPORT_IPCLK_1, - 21, 0, 0), + 21, CLK_SET_RATE_PARENT, 0), GATE(CLK_GOUT_PERIC0_PERIC0_TOP0_IPCLK_10, "gout_peric0_peric0_top0_ipclk_10", "dout_peric0_i3c", CLK_CON_GAT_GOUT_BLK_PERIC0_UID_PERIC0_TOP0_IPCLKPORT_IPCLK_10, @@ -2889,27 +2898,27 @@ static const struct samsung_gate_clock peric0_gate_clks[] __initconst = { GATE(CLK_GOUT_PERIC0_PERIC0_TOP0_IPCLK_2, "gout_peric0_peric0_top0_ipclk_2", "dout_peric0_usi3_usi", CLK_CON_GAT_GOUT_BLK_PERIC0_UID_PERIC0_TOP0_IPCLKPORT_IPCLK_2, - 21, 0, 0), + 21, CLK_SET_RATE_PARENT, 0), GATE(CLK_GOUT_PERIC0_PERIC0_TOP0_IPCLK_3, "gout_peric0_peric0_top0_ipclk_3", "dout_peric0_usi4_usi", CLK_CON_GAT_GOUT_BLK_PERIC0_UID_PERIC0_TOP0_IPCLKPORT_IPCLK_3, - 21, 0, 0), + 21, CLK_SET_RATE_PARENT, 0), GATE(CLK_GOUT_PERIC0_PERIC0_TOP0_IPCLK_4, "gout_peric0_peric0_top0_ipclk_4", "dout_peric0_usi5_usi", CLK_CON_GAT_GOUT_BLK_PERIC0_UID_PERIC0_TOP0_IPCLKPORT_IPCLK_4, - 21, 0, 0), + 21, CLK_SET_RATE_PARENT, 0), GATE(CLK_GOUT_PERIC0_PERIC0_TOP0_IPCLK_5, "gout_peric0_peric0_top0_ipclk_5", "dout_peric0_usi6_usi", CLK_CON_GAT_GOUT_BLK_PERIC0_UID_PERIC0_TOP0_IPCLKPORT_IPCLK_5, - 21, 0, 0), + 21, CLK_SET_RATE_PARENT, 0), GATE(CLK_GOUT_PERIC0_PERIC0_TOP0_IPCLK_6, "gout_peric0_peric0_top0_ipclk_6", "dout_peric0_usi7_usi", CLK_CON_GAT_GOUT_BLK_PERIC0_UID_PERIC0_TOP0_IPCLKPORT_IPCLK_6, - 21, 0, 0), + 21, CLK_SET_RATE_PARENT, 0), GATE(CLK_GOUT_PERIC0_PERIC0_TOP0_IPCLK_7, "gout_peric0_peric0_top0_ipclk_7", "dout_peric0_usi8_usi", CLK_CON_GAT_GOUT_BLK_PERIC0_UID_PERIC0_TOP0_IPCLKPORT_IPCLK_7, - 21, 0, 0), + 21, CLK_SET_RATE_PARENT, 0), GATE(CLK_GOUT_PERIC0_PERIC0_TOP0_IPCLK_8, "gout_peric0_peric0_top0_ipclk_8", "dout_peric0_i3c", CLK_CON_GAT_GOUT_BLK_PERIC0_UID_PERIC0_TOP0_IPCLKPORT_IPCLK_8, @@ -2990,7 +2999,7 @@ static const struct samsung_gate_clock peric0_gate_clks[] __initconst = { GATE(CLK_GOUT_PERIC0_PERIC0_TOP1_IPCLK_2, "gout_peric0_peric0_top1_ipclk_2", "dout_peric0_usi14_usi", CLK_CON_GAT_GOUT_BLK_PERIC0_UID_PERIC0_TOP1_IPCLKPORT_IPCLK_2, - 21, 0, 0), + 21, CLK_SET_RATE_PARENT, 0), /* Disabling this clock makes the system hang. Mark the clock as critical. */ GATE(CLK_GOUT_PERIC0_PERIC0_TOP1_PCLK_0, "gout_peric0_peric0_top1_pclk_0", "mout_peric0_bus_user", diff --git a/drivers/clk/samsung/clk.h b/drivers/clk/samsung/clk.h index a70bd7cce39f..fb06caa71f0a 100644 --- a/drivers/clk/samsung/clk.h +++ b/drivers/clk/samsung/clk.h @@ -133,7 +133,7 @@ struct samsung_mux_clock { .name = cname, \ .parent_names = pnames, \ .num_parents = ARRAY_SIZE(pnames), \ - .flags = (f) | CLK_SET_RATE_NO_REPARENT, \ + .flags = f, \ .offset = o, \ .shift = s, \ .width = w, \ @@ -141,9 +141,16 @@ struct samsung_mux_clock { } #define MUX(_id, cname, pnames, o, s, w) \ - __MUX(_id, cname, pnames, o, s, w, 0, 0) + __MUX(_id, cname, pnames, o, s, w, CLK_SET_RATE_NO_REPARENT, 0) #define MUX_F(_id, cname, pnames, o, s, w, f, mf) \ + __MUX(_id, cname, pnames, o, s, w, (f) | CLK_SET_RATE_NO_REPARENT, mf) + +/* Used by MUX clocks where reparenting on clock rate change is allowed. */ +#define nMUX(_id, cname, pnames, o, s, w) \ + __MUX(_id, cname, pnames, o, s, w, 0, 0) + +#define nMUX_F(_id, cname, pnames, o, s, w, f, mf) \ __MUX(_id, cname, pnames, o, s, w, f, mf) /** From 7cf0324ba0bc61a8c360d23d284e06d2994b1fef Mon Sep 17 00:00:00 2001 From: Tudor Ambarus Date: Fri, 19 Apr 2024 10:09:15 +0000 Subject: [PATCH 060/118] clk: samsung: gs101: propagate PERIC1 USI SPI clock rate MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit When SPI transfer is being prepared, the spi-s3c64xx driver will call clk_set_rate() to change the rate of SPI source clock (IPCLK). But IPCLK is a gate (leaf) clock, so it must propagate the rate change up the clock tree, so that corresponding MUX/DIV clocks can actually change their values. Add CLK_SET_RATE_PARENT flag to corresponding clocks for all USI instances in GS101 PERIC1: USI{0, 9, 10, 11, 12, 13}. This change involves the following clocks: PERIC1 USI*: Clock Div range MUX Selection ------------------------------------------------------------------- gout_peric1_peric1_top0_ipclk_* - - dout_peric1_usi*_usi /1..16 - mout_peric1_usi*_usi_user - {24.5 MHz, 400 MHz} With input clock of 400 MHz this scheme provides the following IPCLK rate range, for each USI block: PERIC1 USI*: 1.5 MHz ... 400 MHz Accounting for internal /4 divider in SPI blocks, and because the max SPI frequency is limited at 50 MHz, it gives us next SPI SCK rates: PERIC1 USI_SPI*: 384 KHz ... 49.9 MHz Which shall be fine for the applications of the SPI bus. Note that with this we allow the reparenting of the MUX_USIx clocks to OSCCLK. Each instance of the USI IP has its own MUX_USI clock, thus the reparenting of a MUX_USI clock corresponds to a single instance of the USI IP. The datasheet mentions OSCCLK just in the low-power mode context, but the downstream driver reparents too the MUX_USI clocks to OSCCLK. Follow the downstream driver and do the same. Fixes: 2999e786d7e9 ("clk: samsung: gs101: add support for cmu_peric1") Reviewed-by: Peter Griffin Acked-by: André Draszik Signed-off-by: Tudor Ambarus Link: https://lore.kernel.org/r/20240419100915.2168573-3-tudor.ambarus@linaro.org Signed-off-by: Krzysztof Kozlowski --- drivers/clk/samsung/clk-gs101.c | 90 ++++++++++++++++++--------------- 1 file changed, 48 insertions(+), 42 deletions(-) diff --git a/drivers/clk/samsung/clk-gs101.c b/drivers/clk/samsung/clk-gs101.c index 76d4d0fa1168..bd3c1b02715b 100644 --- a/drivers/clk/samsung/clk-gs101.c +++ b/drivers/clk/samsung/clk-gs101.c @@ -3239,47 +3239,53 @@ static const struct samsung_mux_clock peric1_mux_clks[] __initconst = { MUX(CLK_MOUT_PERIC1_I3C_USER, "mout_peric1_i3c_user", mout_peric1_nonbususer_p, PLL_CON0_MUX_CLKCMU_PERIC1_I3C_USER, 4, 1), - MUX(CLK_MOUT_PERIC1_USI0_USI_USER, - "mout_peric1_usi0_usi_user", mout_peric1_nonbususer_p, - PLL_CON0_MUX_CLKCMU_PERIC1_USI0_USI_USER, 4, 1), - MUX(CLK_MOUT_PERIC1_USI10_USI_USER, - "mout_peric1_usi10_usi_user", mout_peric1_nonbususer_p, - PLL_CON0_MUX_CLKCMU_PERIC1_USI10_USI_USER, 4, 1), - MUX(CLK_MOUT_PERIC1_USI11_USI_USER, - "mout_peric1_usi11_usi_user", mout_peric1_nonbususer_p, - PLL_CON0_MUX_CLKCMU_PERIC1_USI11_USI_USER, 4, 1), - MUX(CLK_MOUT_PERIC1_USI12_USI_USER, - "mout_peric1_usi12_usi_user", mout_peric1_nonbususer_p, - PLL_CON0_MUX_CLKCMU_PERIC1_USI12_USI_USER, 4, 1), - MUX(CLK_MOUT_PERIC1_USI13_USI_USER, - "mout_peric1_usi13_usi_user", mout_peric1_nonbususer_p, - PLL_CON0_MUX_CLKCMU_PERIC1_USI13_USI_USER, 4, 1), - MUX(CLK_MOUT_PERIC1_USI9_USI_USER, - "mout_peric1_usi9_usi_user", mout_peric1_nonbususer_p, - PLL_CON0_MUX_CLKCMU_PERIC1_USI9_USI_USER, 4, 1), + nMUX(CLK_MOUT_PERIC1_USI0_USI_USER, + "mout_peric1_usi0_usi_user", mout_peric1_nonbususer_p, + PLL_CON0_MUX_CLKCMU_PERIC1_USI0_USI_USER, 4, 1), + nMUX(CLK_MOUT_PERIC1_USI10_USI_USER, + "mout_peric1_usi10_usi_user", mout_peric1_nonbususer_p, + PLL_CON0_MUX_CLKCMU_PERIC1_USI10_USI_USER, 4, 1), + nMUX(CLK_MOUT_PERIC1_USI11_USI_USER, + "mout_peric1_usi11_usi_user", mout_peric1_nonbususer_p, + PLL_CON0_MUX_CLKCMU_PERIC1_USI11_USI_USER, 4, 1), + nMUX(CLK_MOUT_PERIC1_USI12_USI_USER, + "mout_peric1_usi12_usi_user", mout_peric1_nonbususer_p, + PLL_CON0_MUX_CLKCMU_PERIC1_USI12_USI_USER, 4, 1), + nMUX(CLK_MOUT_PERIC1_USI13_USI_USER, + "mout_peric1_usi13_usi_user", mout_peric1_nonbususer_p, + PLL_CON0_MUX_CLKCMU_PERIC1_USI13_USI_USER, 4, 1), + nMUX(CLK_MOUT_PERIC1_USI9_USI_USER, + "mout_peric1_usi9_usi_user", mout_peric1_nonbususer_p, + PLL_CON0_MUX_CLKCMU_PERIC1_USI9_USI_USER, 4, 1), }; static const struct samsung_div_clock peric1_div_clks[] __initconst = { DIV(CLK_DOUT_PERIC1_I3C, "dout_peric1_i3c", "mout_peric1_i3c_user", CLK_CON_DIV_DIV_CLK_PERIC1_I3C, 0, 4), - DIV(CLK_DOUT_PERIC1_USI0_USI, - "dout_peric1_usi0_usi", "mout_peric1_usi0_usi_user", - CLK_CON_DIV_DIV_CLK_PERIC1_USI0_USI, 0, 4), - DIV(CLK_DOUT_PERIC1_USI10_USI, - "dout_peric1_usi10_usi", "mout_peric1_usi10_usi_user", - CLK_CON_DIV_DIV_CLK_PERIC1_USI10_USI, 0, 4), - DIV(CLK_DOUT_PERIC1_USI11_USI, - "dout_peric1_usi11_usi", "mout_peric1_usi11_usi_user", - CLK_CON_DIV_DIV_CLK_PERIC1_USI11_USI, 0, 4), - DIV(CLK_DOUT_PERIC1_USI12_USI, - "dout_peric1_usi12_usi", "mout_peric1_usi12_usi_user", - CLK_CON_DIV_DIV_CLK_PERIC1_USI12_USI, 0, 4), - DIV(CLK_DOUT_PERIC1_USI13_USI, - "dout_peric1_usi13_usi", "mout_peric1_usi13_usi_user", - CLK_CON_DIV_DIV_CLK_PERIC1_USI13_USI, 0, 4), - DIV(CLK_DOUT_PERIC1_USI9_USI, - "dout_peric1_usi9_usi", "mout_peric1_usi9_usi_user", - CLK_CON_DIV_DIV_CLK_PERIC1_USI9_USI, 0, 4), + DIV_F(CLK_DOUT_PERIC1_USI0_USI, + "dout_peric1_usi0_usi", "mout_peric1_usi0_usi_user", + CLK_CON_DIV_DIV_CLK_PERIC1_USI0_USI, 0, 4, + CLK_SET_RATE_PARENT, 0), + DIV_F(CLK_DOUT_PERIC1_USI10_USI, + "dout_peric1_usi10_usi", "mout_peric1_usi10_usi_user", + CLK_CON_DIV_DIV_CLK_PERIC1_USI10_USI, 0, 4, + CLK_SET_RATE_PARENT, 0), + DIV_F(CLK_DOUT_PERIC1_USI11_USI, + "dout_peric1_usi11_usi", "mout_peric1_usi11_usi_user", + CLK_CON_DIV_DIV_CLK_PERIC1_USI11_USI, 0, 4, + CLK_SET_RATE_PARENT, 0), + DIV_F(CLK_DOUT_PERIC1_USI12_USI, + "dout_peric1_usi12_usi", "mout_peric1_usi12_usi_user", + CLK_CON_DIV_DIV_CLK_PERIC1_USI12_USI, 0, 4, + CLK_SET_RATE_PARENT, 0), + DIV_F(CLK_DOUT_PERIC1_USI13_USI, + "dout_peric1_usi13_usi", "mout_peric1_usi13_usi_user", + CLK_CON_DIV_DIV_CLK_PERIC1_USI13_USI, 0, 4, + CLK_SET_RATE_PARENT, 0), + DIV_F(CLK_DOUT_PERIC1_USI9_USI, + "dout_peric1_usi9_usi", "mout_peric1_usi9_usi_user", + CLK_CON_DIV_DIV_CLK_PERIC1_USI9_USI, 0, 4, + CLK_SET_RATE_PARENT, 0), }; static const struct samsung_gate_clock peric1_gate_clks[] __initconst = { @@ -3314,27 +3320,27 @@ static const struct samsung_gate_clock peric1_gate_clks[] __initconst = { GATE(CLK_GOUT_PERIC1_PERIC1_TOP0_IPCLK_1, "gout_peric1_peric1_top0_ipclk_1", "dout_peric1_usi0_usi", CLK_CON_GAT_GOUT_BLK_PERIC1_UID_PERIC1_TOP0_IPCLKPORT_IPCLK_1, - 21, 0, 0), + 21, CLK_SET_RATE_PARENT, 0), GATE(CLK_GOUT_PERIC1_PERIC1_TOP0_IPCLK_2, "gout_peric1_peric1_top0_ipclk_2", "dout_peric1_usi9_usi", CLK_CON_GAT_GOUT_BLK_PERIC1_UID_PERIC1_TOP0_IPCLKPORT_IPCLK_2, - 21, 0, 0), + 21, CLK_SET_RATE_PARENT, 0), GATE(CLK_GOUT_PERIC1_PERIC1_TOP0_IPCLK_3, "gout_peric1_peric1_top0_ipclk_3", "dout_peric1_usi10_usi", CLK_CON_GAT_GOUT_BLK_PERIC1_UID_PERIC1_TOP0_IPCLKPORT_IPCLK_3, - 21, 0, 0), + 21, CLK_SET_RATE_PARENT, 0), GATE(CLK_GOUT_PERIC1_PERIC1_TOP0_IPCLK_4, "gout_peric1_peric1_top0_ipclk_4", "dout_peric1_usi11_usi", CLK_CON_GAT_GOUT_BLK_PERIC1_UID_PERIC1_TOP0_IPCLKPORT_IPCLK_4, - 21, 0, 0), + 21, CLK_SET_RATE_PARENT, 0), GATE(CLK_GOUT_PERIC1_PERIC1_TOP0_IPCLK_5, "gout_peric1_peric1_top0_ipclk_5", "dout_peric1_usi12_usi", CLK_CON_GAT_GOUT_BLK_PERIC1_UID_PERIC1_TOP0_IPCLKPORT_IPCLK_5, - 21, 0, 0), + 21, CLK_SET_RATE_PARENT, 0), GATE(CLK_GOUT_PERIC1_PERIC1_TOP0_IPCLK_6, "gout_peric1_peric1_top0_ipclk_6", "dout_peric1_usi13_usi", CLK_CON_GAT_GOUT_BLK_PERIC1_UID_PERIC1_TOP0_IPCLKPORT_IPCLK_6, - 21, 0, 0), + 21, CLK_SET_RATE_PARENT, 0), GATE(CLK_GOUT_PERIC1_PERIC1_TOP0_IPCLK_8, "gout_peric1_peric1_top0_ipclk_8", "dout_peric1_i3c", CLK_CON_GAT_GOUT_BLK_PERIC1_UID_PERIC1_TOP0_IPCLKPORT_IPCLK_8, From 977b07f769970aec97b907cfc93fb681ecffc9fe Mon Sep 17 00:00:00 2001 From: Peng Fan Date: Mon, 1 Apr 2024 21:28:15 +0800 Subject: [PATCH 061/118] dt-bindings: clock: add i.MX95 clock header Add clock header for i.MX95 BLK CTL modules Signed-off-by: Peng Fan Acked-by: Rob Herring Link: https://lore.kernel.org/r/20240401-imx95-blk-ctl-v6-1-84d4eca1e759@nxp.com Signed-off-by: Abel Vesa --- include/dt-bindings/clock/nxp,imx95-clock.h | 28 +++++++++++++++++++++ 1 file changed, 28 insertions(+) create mode 100644 include/dt-bindings/clock/nxp,imx95-clock.h diff --git a/include/dt-bindings/clock/nxp,imx95-clock.h b/include/dt-bindings/clock/nxp,imx95-clock.h new file mode 100644 index 000000000000..782662c3e740 --- /dev/null +++ b/include/dt-bindings/clock/nxp,imx95-clock.h @@ -0,0 +1,28 @@ +/* SPDX-License-Identifier: GPL-2.0-only OR MIT */ +/* + * Copyright 2024 NXP + */ + +#ifndef __DT_BINDINGS_CLOCK_IMX95_H +#define __DT_BINDINGS_CLOCK_IMX95_H + +#define IMX95_CLK_VPUBLK_WAVE 0 +#define IMX95_CLK_VPUBLK_JPEG_ENC 1 +#define IMX95_CLK_VPUBLK_JPEG_DEC 2 + +#define IMX95_CLK_CAMBLK_CSI2_FOR0 0 +#define IMX95_CLK_CAMBLK_CSI2_FOR1 1 +#define IMX95_CLK_CAMBLK_ISP_AXI 2 +#define IMX95_CLK_CAMBLK_ISP_PIXEL 3 +#define IMX95_CLK_CAMBLK_ISP 4 + +#define IMX95_CLK_DISPMIX_LVDS_PHY_DIV 0 +#define IMX95_CLK_DISPMIX_LVDS_CH0_GATE 1 +#define IMX95_CLK_DISPMIX_LVDS_CH1_GATE 2 +#define IMX95_CLK_DISPMIX_PIX_DI0_GATE 3 +#define IMX95_CLK_DISPMIX_PIX_DI1_GATE 4 + +#define IMX95_CLK_DISPMIX_ENG0_SEL 0 +#define IMX95_CLK_DISPMIX_ENG1_SEL 1 + +#endif /* __DT_BINDINGS_CLOCK_IMX95_H */ From b773f5ad2bfd2d00bd2c5ea7022bc5b86d23a1b7 Mon Sep 17 00:00:00 2001 From: Peng Fan Date: Mon, 1 Apr 2024 21:28:16 +0800 Subject: [PATCH 062/118] dt-bindings: clock: support i.MX95 BLK CTL module i.MX95 includes BLK CTL module in several MIXes, such as VPU_CSR in VPUMIX, CAMERA_CSR in CAMERAMIX and etc. The BLK CTL module is used for various settings of a specific MIX, such as clock, QoS and etc. This patch is to add some BLK CTL modules that has clock features. Reviewed-by: Krzysztof Kozlowski Signed-off-by: Peng Fan Link: https://lore.kernel.org/r/20240401-imx95-blk-ctl-v6-2-84d4eca1e759@nxp.com Signed-off-by: Abel Vesa --- .../bindings/clock/nxp,imx95-blk-ctl.yaml | 56 +++++++++++++++++++ 1 file changed, 56 insertions(+) create mode 100644 Documentation/devicetree/bindings/clock/nxp,imx95-blk-ctl.yaml diff --git a/Documentation/devicetree/bindings/clock/nxp,imx95-blk-ctl.yaml b/Documentation/devicetree/bindings/clock/nxp,imx95-blk-ctl.yaml new file mode 100644 index 000000000000..2dffc02dcd8b --- /dev/null +++ b/Documentation/devicetree/bindings/clock/nxp,imx95-blk-ctl.yaml @@ -0,0 +1,56 @@ +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/clock/nxp,imx95-blk-ctl.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: NXP i.MX95 Block Control + +maintainers: + - Peng Fan + +properties: + compatible: + items: + - enum: + - nxp,imx95-lvds-csr + - nxp,imx95-display-csr + - nxp,imx95-camera-csr + - nxp,imx95-vpu-csr + - const: syscon + + reg: + maxItems: 1 + + power-domains: + maxItems: 1 + + clocks: + maxItems: 1 + + '#clock-cells': + const: 1 + description: + The clock consumer should specify the desired clock by having the clock + ID in its "clocks" phandle cell. See + include/dt-bindings/clock/nxp,imx95-clock.h + +required: + - compatible + - reg + - '#clock-cells' + - power-domains + - clocks + +additionalProperties: false + +examples: + - | + syscon@4c410000 { + compatible = "nxp,imx95-vpu-csr", "syscon"; + reg = <0x4c410000 0x10000>; + #clock-cells = <1>; + clocks = <&scmi_clk 114>; + power-domains = <&scmi_devpd 21>; + }; +... From c6e87b066756ec4b3f5f9061b508f3bd724ec652 Mon Sep 17 00:00:00 2001 From: Peng Fan Date: Mon, 1 Apr 2024 21:28:17 +0800 Subject: [PATCH 063/118] dt-bindings: clock: support i.MX95 Display Master CSR module i.MX95 DISPLAY_MASTER_CSR includes registers to control DSI clock settings, clock gating, and pixel link select. Add dt-schema for it. Reviewed-by: Krzysztof Kozlowski Signed-off-by: Peng Fan Link: https://lore.kernel.org/r/20240401-imx95-blk-ctl-v6-3-84d4eca1e759@nxp.com Signed-off-by: Abel Vesa --- .../clock/nxp,imx95-display-master-csr.yaml | 64 +++++++++++++++++++ 1 file changed, 64 insertions(+) create mode 100644 Documentation/devicetree/bindings/clock/nxp,imx95-display-master-csr.yaml diff --git a/Documentation/devicetree/bindings/clock/nxp,imx95-display-master-csr.yaml b/Documentation/devicetree/bindings/clock/nxp,imx95-display-master-csr.yaml new file mode 100644 index 000000000000..07f7412e7658 --- /dev/null +++ b/Documentation/devicetree/bindings/clock/nxp,imx95-display-master-csr.yaml @@ -0,0 +1,64 @@ +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/clock/nxp,imx95-display-master-csr.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: NXP i.MX95 Display Master Block Control + +maintainers: + - Peng Fan + +properties: + compatible: + items: + - const: nxp,imx95-display-master-csr + - const: syscon + + reg: + maxItems: 1 + + power-domains: + maxItems: 1 + + clocks: + maxItems: 1 + + '#clock-cells': + const: 1 + description: + The clock consumer should specify the desired clock by having the clock + ID in its "clocks" phandle cell. See + include/dt-bindings/clock/nxp,imx95-clock.h + + mux-controller: + type: object + $ref: /schemas/mux/reg-mux.yaml + +required: + - compatible + - reg + - '#clock-cells' + - mux-controller + - power-domains + - clocks + +additionalProperties: false + +examples: + - | + syscon@4c410000 { + compatible = "nxp,imx95-display-master-csr", "syscon"; + reg = <0x4c410000 0x10000>; + #clock-cells = <1>; + clocks = <&scmi_clk 62>; + power-domains = <&scmi_devpd 3>; + + mux: mux-controller { + compatible = "mmio-mux"; + #mux-control-cells = <1>; + mux-reg-masks = <0x4 0x00000001>; /* Pixel_link_sel */ + idle-states = <0>; + }; + }; +... From 5224b189462ff70df328f173b71acfd925092c3c Mon Sep 17 00:00:00 2001 From: Peng Fan Date: Mon, 1 Apr 2024 21:28:18 +0800 Subject: [PATCH 064/118] clk: imx: add i.MX95 BLK CTL clk driver i.MX95 has BLK CTL modules in various MIXes, the BLK CTL modules support clock features such as mux/gate/div. This patch is to add the clock feature of BLK CTL modules Signed-off-by: Peng Fan Reviewed-by: Abel Vesa Link: https://lore.kernel.org/r/20240401-imx95-blk-ctl-v6-4-84d4eca1e759@nxp.com Signed-off-by: Abel Vesa --- drivers/clk/imx/Kconfig | 7 + drivers/clk/imx/Makefile | 1 + drivers/clk/imx/clk-imx95-blk-ctl.c | 438 ++++++++++++++++++++++++++++ 3 files changed, 446 insertions(+) create mode 100644 drivers/clk/imx/clk-imx95-blk-ctl.c diff --git a/drivers/clk/imx/Kconfig b/drivers/clk/imx/Kconfig index db3bca5f4ec9..6da0fba68225 100644 --- a/drivers/clk/imx/Kconfig +++ b/drivers/clk/imx/Kconfig @@ -114,6 +114,13 @@ config CLK_IMX93 help Build the driver for i.MX93 CCM Clock Driver +config CLK_IMX95_BLK_CTL + tristate "IMX95 Clock Driver for BLK CTL" + depends on ARCH_MXC || COMPILE_TEST + select MXC_CLK + help + Build the clock driver for i.MX95 BLK CTL + config CLK_IMXRT1050 tristate "IMXRT1050 CCM Clock Driver" depends on SOC_IMXRT || COMPILE_TEST diff --git a/drivers/clk/imx/Makefile b/drivers/clk/imx/Makefile index d4b8e10b1970..03f2b2a1ab63 100644 --- a/drivers/clk/imx/Makefile +++ b/drivers/clk/imx/Makefile @@ -31,6 +31,7 @@ obj-$(CONFIG_CLK_IMX8MP) += clk-imx8mp.o clk-imx8mp-audiomix.o obj-$(CONFIG_CLK_IMX8MQ) += clk-imx8mq.o obj-$(CONFIG_CLK_IMX93) += clk-imx93.o +obj-$(CONFIG_CLK_IMX95_BLK_CTL) += clk-imx95-blk-ctl.o obj-$(CONFIG_MXC_CLK_SCU) += clk-imx-scu.o clk-imx-lpcg-scu.o clk-imx-acm.o clk-imx-scu-$(CONFIG_CLK_IMX8QXP) += clk-scu.o clk-imx8qxp.o \ diff --git a/drivers/clk/imx/clk-imx95-blk-ctl.c b/drivers/clk/imx/clk-imx95-blk-ctl.c new file mode 100644 index 000000000000..74f595f9e5e3 --- /dev/null +++ b/drivers/clk/imx/clk-imx95-blk-ctl.c @@ -0,0 +1,438 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright 2024 NXP + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +enum { + CLK_GATE, + CLK_DIVIDER, + CLK_MUX, +}; + +struct imx95_blk_ctl { + struct device *dev; + spinlock_t lock; + struct clk *clk_apb; + + void __iomem *base; + /* clock gate register */ + u32 clk_reg_restore; +}; + +struct imx95_blk_ctl_clk_dev_data { + const char *name; + const char * const *parent_names; + u32 num_parents; + u32 reg; + u32 bit_idx; + u32 bit_width; + u32 clk_type; + u32 flags; + u32 flags2; + u32 type; +}; + +struct imx95_blk_ctl_dev_data { + const struct imx95_blk_ctl_clk_dev_data *clk_dev_data; + u32 num_clks; + bool rpm_enabled; + u32 clk_reg_offset; +}; + +static const struct imx95_blk_ctl_clk_dev_data vpublk_clk_dev_data[] = { + [IMX95_CLK_VPUBLK_WAVE] = { + .name = "vpublk_wave_vpu", + .parent_names = (const char *[]){ "vpu", }, + .num_parents = 1, + .reg = 8, + .bit_idx = 0, + .type = CLK_GATE, + .flags = CLK_SET_RATE_PARENT, + .flags2 = CLK_GATE_SET_TO_DISABLE, + }, + [IMX95_CLK_VPUBLK_JPEG_ENC] = { + .name = "vpublk_jpeg_enc", + .parent_names = (const char *[]){ "vpujpeg", }, + .num_parents = 1, + .reg = 8, + .bit_idx = 1, + .type = CLK_GATE, + .flags = CLK_SET_RATE_PARENT, + .flags2 = CLK_GATE_SET_TO_DISABLE, + }, + [IMX95_CLK_VPUBLK_JPEG_DEC] = { + .name = "vpublk_jpeg_dec", + .parent_names = (const char *[]){ "vpujpeg", }, + .num_parents = 1, + .reg = 8, + .bit_idx = 2, + .type = CLK_GATE, + .flags = CLK_SET_RATE_PARENT, + .flags2 = CLK_GATE_SET_TO_DISABLE, + } +}; + +static const struct imx95_blk_ctl_dev_data vpublk_dev_data = { + .num_clks = ARRAY_SIZE(vpublk_clk_dev_data), + .clk_dev_data = vpublk_clk_dev_data, + .rpm_enabled = true, + .clk_reg_offset = 8, +}; + +static const struct imx95_blk_ctl_clk_dev_data camblk_clk_dev_data[] = { + [IMX95_CLK_CAMBLK_CSI2_FOR0] = { + .name = "camblk_csi2_for0", + .parent_names = (const char *[]){ "camisi", }, + .num_parents = 1, + .reg = 0, + .bit_idx = 0, + .type = CLK_GATE, + .flags = CLK_SET_RATE_PARENT, + .flags2 = CLK_GATE_SET_TO_DISABLE, + }, + [IMX95_CLK_CAMBLK_CSI2_FOR1] = { + .name = "camblk_csi2_for1", + .parent_names = (const char *[]){ "camisi", }, + .num_parents = 1, + .reg = 0, + .bit_idx = 1, + .type = CLK_GATE, + .flags = CLK_SET_RATE_PARENT, + .flags2 = CLK_GATE_SET_TO_DISABLE, + }, + [IMX95_CLK_CAMBLK_ISP_AXI] = { + .name = "camblk_isp_axi", + .parent_names = (const char *[]){ "camaxi", }, + .num_parents = 1, + .reg = 0, + .bit_idx = 4, + .type = CLK_GATE, + .flags = CLK_SET_RATE_PARENT, + .flags2 = CLK_GATE_SET_TO_DISABLE, + }, + [IMX95_CLK_CAMBLK_ISP_PIXEL] = { + .name = "camblk_isp_pixel", + .parent_names = (const char *[]){ "camisi", }, + .num_parents = 1, + .reg = 0, + .bit_idx = 5, + .type = CLK_GATE, + .flags = CLK_SET_RATE_PARENT, + .flags2 = CLK_GATE_SET_TO_DISABLE, + }, + [IMX95_CLK_CAMBLK_ISP] = { + .name = "camblk_isp", + .parent_names = (const char *[]){ "camisi", }, + .num_parents = 1, + .reg = 0, + .bit_idx = 6, + .type = CLK_GATE, + .flags = CLK_SET_RATE_PARENT, + .flags2 = CLK_GATE_SET_TO_DISABLE, + } +}; + +static const struct imx95_blk_ctl_dev_data camblk_dev_data = { + .num_clks = ARRAY_SIZE(camblk_clk_dev_data), + .clk_dev_data = camblk_clk_dev_data, + .clk_reg_offset = 0, +}; + +static const struct imx95_blk_ctl_clk_dev_data lvds_clk_dev_data[] = { + [IMX95_CLK_DISPMIX_LVDS_PHY_DIV] = { + .name = "ldb_phy_div", + .parent_names = (const char *[]){ "ldbpll", }, + .num_parents = 1, + .reg = 0, + .bit_idx = 0, + .bit_width = 1, + .type = CLK_DIVIDER, + .flags2 = CLK_DIVIDER_POWER_OF_TWO, + }, + [IMX95_CLK_DISPMIX_LVDS_CH0_GATE] = { + .name = "lvds_ch0_gate", + .parent_names = (const char *[]){ "ldb_phy_div", }, + .num_parents = 1, + .reg = 0, + .bit_idx = 1, + .bit_width = 1, + .type = CLK_GATE, + .flags = CLK_SET_RATE_PARENT, + .flags2 = CLK_GATE_SET_TO_DISABLE, + }, + [IMX95_CLK_DISPMIX_LVDS_CH1_GATE] = { + .name = "lvds_ch1_gate", + .parent_names = (const char *[]){ "ldb_phy_div", }, + .num_parents = 1, + .reg = 0, + .bit_idx = 2, + .bit_width = 1, + .type = CLK_GATE, + .flags = CLK_SET_RATE_PARENT, + .flags2 = CLK_GATE_SET_TO_DISABLE, + }, + [IMX95_CLK_DISPMIX_PIX_DI0_GATE] = { + .name = "lvds_di0_gate", + .parent_names = (const char *[]){ "ldb_pll_div7", }, + .num_parents = 1, + .reg = 0, + .bit_idx = 3, + .bit_width = 1, + .type = CLK_GATE, + .flags = CLK_SET_RATE_PARENT, + .flags2 = CLK_GATE_SET_TO_DISABLE, + }, + [IMX95_CLK_DISPMIX_PIX_DI1_GATE] = { + .name = "lvds_di1_gate", + .parent_names = (const char *[]){ "ldb_pll_div7", }, + .num_parents = 1, + .reg = 0, + .bit_idx = 4, + .bit_width = 1, + .type = CLK_GATE, + .flags = CLK_SET_RATE_PARENT, + .flags2 = CLK_GATE_SET_TO_DISABLE, + }, +}; + +static const struct imx95_blk_ctl_dev_data lvds_csr_dev_data = { + .num_clks = ARRAY_SIZE(lvds_clk_dev_data), + .clk_dev_data = lvds_clk_dev_data, + .clk_reg_offset = 0, +}; + +static const struct imx95_blk_ctl_clk_dev_data dispmix_csr_clk_dev_data[] = { + [IMX95_CLK_DISPMIX_ENG0_SEL] = { + .name = "disp_engine0_sel", + .parent_names = (const char *[]){"videopll1", "dsi_pll", "ldb_pll_div7", }, + .num_parents = 4, + .reg = 0, + .bit_idx = 0, + .bit_width = 2, + .type = CLK_MUX, + .flags = CLK_SET_RATE_NO_REPARENT | CLK_SET_RATE_PARENT, + }, + [IMX95_CLK_DISPMIX_ENG1_SEL] = { + .name = "disp_engine1_sel", + .parent_names = (const char *[]){"videopll1", "dsi_pll", "ldb_pll_div7", }, + .num_parents = 4, + .reg = 0, + .bit_idx = 2, + .bit_width = 2, + .type = CLK_MUX, + .flags = CLK_SET_RATE_NO_REPARENT | CLK_SET_RATE_PARENT, + } +}; + +static const struct imx95_blk_ctl_dev_data dispmix_csr_dev_data = { + .num_clks = ARRAY_SIZE(dispmix_csr_clk_dev_data), + .clk_dev_data = dispmix_csr_clk_dev_data, + .clk_reg_offset = 0, +}; + +static int imx95_bc_probe(struct platform_device *pdev) +{ + struct device *dev = &pdev->dev; + const struct imx95_blk_ctl_dev_data *bc_data; + struct imx95_blk_ctl *bc; + struct clk_hw_onecell_data *clk_hw_data; + struct clk_hw **hws; + void __iomem *base; + int i, ret; + + bc = devm_kzalloc(dev, sizeof(*bc), GFP_KERNEL); + if (!bc) + return -ENOMEM; + bc->dev = dev; + dev_set_drvdata(&pdev->dev, bc); + + spin_lock_init(&bc->lock); + + base = devm_platform_ioremap_resource(pdev, 0); + if (IS_ERR(base)) + return PTR_ERR(base); + + bc->base = base; + bc->clk_apb = devm_clk_get(dev, NULL); + if (IS_ERR(bc->clk_apb)) + return dev_err_probe(dev, PTR_ERR(bc->clk_apb), "failed to get APB clock\n"); + + ret = clk_prepare_enable(bc->clk_apb); + if (ret) { + dev_err(dev, "failed to enable apb clock: %d\n", ret); + return ret; + } + + bc_data = of_device_get_match_data(dev); + if (!bc_data) + return devm_of_platform_populate(dev); + + clk_hw_data = devm_kzalloc(dev, struct_size(clk_hw_data, hws, bc_data->num_clks), + GFP_KERNEL); + if (!clk_hw_data) + return -ENOMEM; + + if (bc_data->rpm_enabled) + pm_runtime_enable(&pdev->dev); + + clk_hw_data->num = bc_data->num_clks; + hws = clk_hw_data->hws; + + for (i = 0; i < bc_data->num_clks; i++) { + const struct imx95_blk_ctl_clk_dev_data *data = &bc_data->clk_dev_data[i]; + void __iomem *reg = base + data->reg; + + if (data->type == CLK_MUX) { + hws[i] = clk_hw_register_mux(dev, data->name, data->parent_names, + data->num_parents, data->flags, reg, + data->bit_idx, data->bit_width, + data->flags2, &bc->lock); + } else if (data->type == CLK_DIVIDER) { + hws[i] = clk_hw_register_divider(dev, data->name, data->parent_names[0], + data->flags, reg, data->bit_idx, + data->bit_width, data->flags2, &bc->lock); + } else { + hws[i] = clk_hw_register_gate(dev, data->name, data->parent_names[0], + data->flags, reg, data->bit_idx, + data->flags2, &bc->lock); + } + if (IS_ERR(hws[i])) { + ret = PTR_ERR(hws[i]); + dev_err(dev, "failed to register: %s:%d\n", data->name, ret); + goto cleanup; + } + } + + ret = of_clk_add_hw_provider(dev->of_node, of_clk_hw_onecell_get, clk_hw_data); + if (ret) + goto cleanup; + + ret = devm_of_platform_populate(dev); + if (ret) { + of_clk_del_provider(dev->of_node); + goto cleanup; + } + + if (pm_runtime_enabled(bc->dev)) + clk_disable_unprepare(bc->clk_apb); + + return 0; + +cleanup: + for (i = 0; i < bc_data->num_clks; i++) { + if (IS_ERR_OR_NULL(hws[i])) + continue; + clk_hw_unregister(hws[i]); + } + + if (bc_data->rpm_enabled) + pm_runtime_disable(&pdev->dev); + + return ret; +} + +#ifdef CONFIG_PM +static int imx95_bc_runtime_suspend(struct device *dev) +{ + struct imx95_blk_ctl *bc = dev_get_drvdata(dev); + + clk_disable_unprepare(bc->clk_apb); + return 0; +} + +static int imx95_bc_runtime_resume(struct device *dev) +{ + struct imx95_blk_ctl *bc = dev_get_drvdata(dev); + + return clk_prepare_enable(bc->clk_apb); +} +#endif + +#ifdef CONFIG_PM_SLEEP +static int imx95_bc_suspend(struct device *dev) +{ + struct imx95_blk_ctl *bc = dev_get_drvdata(dev); + const struct imx95_blk_ctl_dev_data *bc_data; + int ret; + + bc_data = of_device_get_match_data(dev); + if (!bc_data) + return 0; + + if (bc_data->rpm_enabled) { + ret = pm_runtime_get_sync(bc->dev); + if (ret < 0) { + pm_runtime_put_noidle(bc->dev); + return ret; + } + } + + bc->clk_reg_restore = readl(bc->base + bc_data->clk_reg_offset); + + return 0; +} + +static int imx95_bc_resume(struct device *dev) +{ + struct imx95_blk_ctl *bc = dev_get_drvdata(dev); + const struct imx95_blk_ctl_dev_data *bc_data; + + bc_data = of_device_get_match_data(dev); + if (!bc_data) + return 0; + + writel(bc->clk_reg_restore, bc->base + bc_data->clk_reg_offset); + + if (bc_data->rpm_enabled) + pm_runtime_put(bc->dev); + + return 0; +} +#endif + +static const struct dev_pm_ops imx95_bc_pm_ops = { + SET_RUNTIME_PM_OPS(imx95_bc_runtime_suspend, imx95_bc_runtime_resume, NULL) + SET_SYSTEM_SLEEP_PM_OPS(imx95_bc_suspend, imx95_bc_resume) +}; + +static const struct of_device_id imx95_bc_of_match[] = { + { .compatible = "nxp,imx95-camera-csr", .data = &camblk_dev_data }, + { .compatible = "nxp,imx95-display-master-csr", }, + { .compatible = "nxp,imx95-lvds-csr", .data = &lvds_csr_dev_data }, + { .compatible = "nxp,imx95-display-csr", .data = &dispmix_csr_dev_data }, + { .compatible = "nxp,imx95-vpu-csr", .data = &vpublk_dev_data }, + { /* Sentinel */ }, +}; +MODULE_DEVICE_TABLE(of, imx95_bc_of_match); + +static struct platform_driver imx95_bc_driver = { + .probe = imx95_bc_probe, + .driver = { + .name = "imx95-blk-ctl", + .of_match_table = imx95_bc_of_match, + .pm = &imx95_bc_pm_ops, + }, +}; +module_platform_driver(imx95_bc_driver); + +MODULE_DESCRIPTION("NXP i.MX95 blk ctl driver"); +MODULE_AUTHOR("Peng Fan "); +MODULE_LICENSE("GPL"); From 2641ee13c449ef76b0c369ae94dd8dd5dc8c2008 Mon Sep 17 00:00:00 2001 From: Cristian Marussi Date: Mon, 15 Apr 2024 17:36:45 +0100 Subject: [PATCH 065/118] clk: scmi: Allocate CLK operations dynamically SCMI Clocks descriptors expose an increasing number of properties, thing which, in turn, leads to a varying set of supported CLK operations to be associated with each clock. Providing statically pre-defined CLK operations structs for all the possible combinations of allowed clock features is becoming cumbersome and error-prone. Allocate the per-clock operations descriptors dynamically and populate it with the strictly needed set of operations depending on the advertised clock properties: one descriptor is created for each distinct combination of clock operations, so minimizing the number of clk_ops structures to the strictly minimum needed. CC: Michael Turquette CC: Stephen Boyd CC: linux-clk@vger.kernel.org Signed-off-by: Cristian Marussi Link: https://lore.kernel.org/r/20240415163649.895268-2-cristian.marussi@arm.com Reviewed-by: Sudeep Holla Signed-off-by: Stephen Boyd --- drivers/clk/clk-scmi.c | 186 ++++++++++++++++++++++++++++++----------- 1 file changed, 136 insertions(+), 50 deletions(-) diff --git a/drivers/clk/clk-scmi.c b/drivers/clk/clk-scmi.c index 8cbe24789c24..4b6c43d7f5f3 100644 --- a/drivers/clk/clk-scmi.c +++ b/drivers/clk/clk-scmi.c @@ -2,9 +2,10 @@ /* * System Control and Power Interface (SCMI) Protocol based clock driver * - * Copyright (C) 2018-2022 ARM Ltd. + * Copyright (C) 2018-2024 ARM Ltd. */ +#include #include #include #include @@ -16,6 +17,13 @@ #define NOT_ATOMIC false #define ATOMIC true +enum scmi_clk_feats { + SCMI_CLK_ATOMIC_SUPPORTED, + SCMI_CLK_FEATS_COUNT +}; + +#define SCMI_MAX_CLK_OPS BIT(SCMI_CLK_FEATS_COUNT) + static const struct scmi_clk_proto_ops *scmi_proto_clk_ops; struct scmi_clk { @@ -158,42 +166,6 @@ static int scmi_clk_atomic_is_enabled(struct clk_hw *hw) return !!enabled; } -/* - * We can provide enable/disable/is_enabled atomic callbacks only if the - * underlying SCMI transport for an SCMI instance is configured to handle - * SCMI commands in an atomic manner. - * - * When no SCMI atomic transport support is available we instead provide only - * the prepare/unprepare API, as allowed by the clock framework when atomic - * calls are not available. - * - * Two distinct sets of clk_ops are provided since we could have multiple SCMI - * instances with different underlying transport quality, so they cannot be - * shared. - */ -static const struct clk_ops scmi_clk_ops = { - .recalc_rate = scmi_clk_recalc_rate, - .round_rate = scmi_clk_round_rate, - .set_rate = scmi_clk_set_rate, - .prepare = scmi_clk_enable, - .unprepare = scmi_clk_disable, - .set_parent = scmi_clk_set_parent, - .get_parent = scmi_clk_get_parent, - .determine_rate = scmi_clk_determine_rate, -}; - -static const struct clk_ops scmi_atomic_clk_ops = { - .recalc_rate = scmi_clk_recalc_rate, - .round_rate = scmi_clk_round_rate, - .set_rate = scmi_clk_set_rate, - .enable = scmi_clk_atomic_enable, - .disable = scmi_clk_atomic_disable, - .is_enabled = scmi_clk_atomic_is_enabled, - .set_parent = scmi_clk_set_parent, - .get_parent = scmi_clk_get_parent, - .determine_rate = scmi_clk_determine_rate, -}; - static int scmi_clk_ops_init(struct device *dev, struct scmi_clk *sclk, const struct clk_ops *scmi_ops) { @@ -230,17 +202,129 @@ static int scmi_clk_ops_init(struct device *dev, struct scmi_clk *sclk, return ret; } +/** + * scmi_clk_ops_alloc() - Alloc and configure clock operations + * @dev: A device reference for devres + * @feats_key: A bitmap representing the desired clk_ops capabilities + * + * Allocate and configure a proper set of clock operations depending on the + * specifically required SCMI clock features. + * + * Return: A pointer to the allocated and configured clk_ops on success, + * or NULL on allocation failure. + */ +static const struct clk_ops * +scmi_clk_ops_alloc(struct device *dev, unsigned long feats_key) +{ + struct clk_ops *ops; + + ops = devm_kzalloc(dev, sizeof(*ops), GFP_KERNEL); + if (!ops) + return NULL; + /* + * We can provide enable/disable/is_enabled atomic callbacks only if the + * underlying SCMI transport for an SCMI instance is configured to + * handle SCMI commands in an atomic manner. + * + * When no SCMI atomic transport support is available we instead provide + * only the prepare/unprepare API, as allowed by the clock framework + * when atomic calls are not available. + */ + if (feats_key & BIT(SCMI_CLK_ATOMIC_SUPPORTED)) { + ops->enable = scmi_clk_atomic_enable; + ops->disable = scmi_clk_atomic_disable; + ops->is_enabled = scmi_clk_atomic_is_enabled; + } else { + ops->prepare = scmi_clk_enable; + ops->unprepare = scmi_clk_disable; + } + + /* Rate ops */ + ops->recalc_rate = scmi_clk_recalc_rate; + ops->round_rate = scmi_clk_round_rate; + ops->determine_rate = scmi_clk_determine_rate; + ops->set_rate = scmi_clk_set_rate; + + /* Parent ops */ + ops->get_parent = scmi_clk_get_parent; + ops->set_parent = scmi_clk_set_parent; + + return ops; +} + +/** + * scmi_clk_ops_select() - Select a proper set of clock operations + * @sclk: A reference to an SCMI clock descriptor + * @atomic_capable: A flag to indicate if atomic mode is supported by the + * transport + * @atomic_threshold_us: Platform atomic threshold value in microseconds: + * clk_ops are atomic when clock enable latency is less + * than this threshold + * @clk_ops_db: A reference to the array used as a database to store all the + * created clock operations combinations. + * @db_size: Maximum number of entries held by @clk_ops_db + * + * After having built a bitmap descriptor to represent the set of features + * needed by this SCMI clock, at first use it to lookup into the set of + * previously allocated clk_ops to check if a suitable combination of clock + * operations was already created; when no match is found allocate a brand new + * set of clk_ops satisfying the required combination of features and save it + * for future references. + * + * In this way only one set of clk_ops is ever created for each different + * combination that is effectively needed by a driver instance. + * + * Return: A pointer to the allocated and configured clk_ops on success, or + * NULL otherwise. + */ +static const struct clk_ops * +scmi_clk_ops_select(struct scmi_clk *sclk, bool atomic_capable, + unsigned int atomic_threshold_us, + const struct clk_ops **clk_ops_db, size_t db_size) +{ + const struct scmi_clock_info *ci = sclk->info; + unsigned int feats_key = 0; + const struct clk_ops *ops; + + /* + * Note that when transport is atomic but SCMI protocol did not + * specify (or support) an enable_latency associated with a + * clock, we default to use atomic operations mode. + */ + if (atomic_capable && ci->enable_latency <= atomic_threshold_us) + feats_key |= BIT(SCMI_CLK_ATOMIC_SUPPORTED); + + if (WARN_ON(feats_key >= db_size)) + return NULL; + + /* Lookup previously allocated ops */ + ops = clk_ops_db[feats_key]; + if (ops) + return ops; + + /* Did not find a pre-allocated clock_ops */ + ops = scmi_clk_ops_alloc(sclk->dev, feats_key); + if (!ops) + return NULL; + + /* Store new ops combinations */ + clk_ops_db[feats_key] = ops; + + return ops; +} + static int scmi_clocks_probe(struct scmi_device *sdev) { int idx, count, err; - unsigned int atomic_threshold; - bool is_atomic; + unsigned int atomic_threshold_us; + bool transport_is_atomic; struct clk_hw **hws; struct clk_hw_onecell_data *clk_data; struct device *dev = &sdev->dev; struct device_node *np = dev->of_node; const struct scmi_handle *handle = sdev->handle; struct scmi_protocol_handle *ph; + const struct clk_ops *scmi_clk_ops_db[SCMI_MAX_CLK_OPS] = {}; if (!handle) return -ENODEV; @@ -264,7 +348,8 @@ static int scmi_clocks_probe(struct scmi_device *sdev) clk_data->num = count; hws = clk_data->hws; - is_atomic = handle->is_transport_atomic(handle, &atomic_threshold); + transport_is_atomic = handle->is_transport_atomic(handle, + &atomic_threshold_us); for (idx = 0; idx < count; idx++) { struct scmi_clk *sclk; @@ -286,15 +371,17 @@ static int scmi_clocks_probe(struct scmi_device *sdev) sclk->dev = dev; /* - * Note that when transport is atomic but SCMI protocol did not - * specify (or support) an enable_latency associated with a - * clock, we default to use atomic operations mode. + * Note that the scmi_clk_ops_db is on the stack, not global, + * because it cannot be shared between mulitple probe-sequences + * to avoid sharing the devm_ allocated clk_ops between multiple + * SCMI clk driver instances. */ - if (is_atomic && - sclk->info->enable_latency <= atomic_threshold) - scmi_ops = &scmi_atomic_clk_ops; - else - scmi_ops = &scmi_clk_ops; + scmi_ops = scmi_clk_ops_select(sclk, transport_is_atomic, + atomic_threshold_us, + scmi_clk_ops_db, + ARRAY_SIZE(scmi_clk_ops_db)); + if (!scmi_ops) + return -ENOMEM; /* Initialize clock parent data. */ if (sclk->info->num_parents > 0) { @@ -318,8 +405,7 @@ static int scmi_clocks_probe(struct scmi_device *sdev) } else { dev_dbg(dev, "Registered clock:%s%s\n", sclk->info->name, - scmi_ops == &scmi_atomic_clk_ops ? - " (atomic ops)" : ""); + scmi_ops->enable ? " (atomic ops)" : ""); hws[idx] = &sclk->hw; } } From a1b8faf8784c434444432008b57274c8935cca5c Mon Sep 17 00:00:00 2001 From: Cristian Marussi Date: Mon, 15 Apr 2024 17:36:46 +0100 Subject: [PATCH 066/118] clk: scmi: Add support for state control restricted clocks Some exposed SCMI Clocks could be marked as non-supporting state changes. Configure a clk_ops descriptor which does not provide the state change callbacks for such clocks when registering with CLK framework. CC: Michael Turquette CC: Stephen Boyd CC: linux-clk@vger.kernel.org Signed-off-by: Cristian Marussi Link: https://lore.kernel.org/r/20240415163649.895268-3-cristian.marussi@arm.com Reviewed-by: Sudeep Holla Signed-off-by: Stephen Boyd --- drivers/clk/clk-scmi.c | 22 +++++++++++++++------- 1 file changed, 15 insertions(+), 7 deletions(-) diff --git a/drivers/clk/clk-scmi.c b/drivers/clk/clk-scmi.c index 4b6c43d7f5f3..e70708573965 100644 --- a/drivers/clk/clk-scmi.c +++ b/drivers/clk/clk-scmi.c @@ -19,6 +19,7 @@ enum scmi_clk_feats { SCMI_CLK_ATOMIC_SUPPORTED, + SCMI_CLK_STATE_CTRL_SUPPORTED, SCMI_CLK_FEATS_COUNT }; @@ -230,15 +231,19 @@ scmi_clk_ops_alloc(struct device *dev, unsigned long feats_key) * only the prepare/unprepare API, as allowed by the clock framework * when atomic calls are not available. */ - if (feats_key & BIT(SCMI_CLK_ATOMIC_SUPPORTED)) { - ops->enable = scmi_clk_atomic_enable; - ops->disable = scmi_clk_atomic_disable; - ops->is_enabled = scmi_clk_atomic_is_enabled; - } else { - ops->prepare = scmi_clk_enable; - ops->unprepare = scmi_clk_disable; + if (feats_key & BIT(SCMI_CLK_STATE_CTRL_SUPPORTED)) { + if (feats_key & BIT(SCMI_CLK_ATOMIC_SUPPORTED)) { + ops->enable = scmi_clk_atomic_enable; + ops->disable = scmi_clk_atomic_disable; + } else { + ops->prepare = scmi_clk_enable; + ops->unprepare = scmi_clk_disable; + } } + if (feats_key & BIT(SCMI_CLK_ATOMIC_SUPPORTED)) + ops->is_enabled = scmi_clk_atomic_is_enabled; + /* Rate ops */ ops->recalc_rate = scmi_clk_recalc_rate; ops->round_rate = scmi_clk_round_rate; @@ -294,6 +299,9 @@ scmi_clk_ops_select(struct scmi_clk *sclk, bool atomic_capable, if (atomic_capable && ci->enable_latency <= atomic_threshold_us) feats_key |= BIT(SCMI_CLK_ATOMIC_SUPPORTED); + if (!ci->state_ctrl_forbidden) + feats_key |= BIT(SCMI_CLK_STATE_CTRL_SUPPORTED); + if (WARN_ON(feats_key >= db_size)) return NULL; From c3ad1d0a7ef28bc503caf3d5242f2dda55df5d3f Mon Sep 17 00:00:00 2001 From: Cristian Marussi Date: Mon, 15 Apr 2024 17:36:47 +0100 Subject: [PATCH 067/118] clk: scmi: Add support for rate change restricted clocks Some exposed SCMI Clocks could be marked as non-supporting rate changes. Configure a clk_ops descriptors which does not provide the rate change callbacks for such clocks when registering with CLK framework. CC: Michael Turquette CC: Stephen Boyd CC: linux-clk@vger.kernel.org Signed-off-by: Cristian Marussi Link: https://lore.kernel.org/r/20240415163649.895268-4-cristian.marussi@arm.com Reviewed-by: Sudeep Holla Signed-off-by: Stephen Boyd --- drivers/clk/clk-scmi.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/drivers/clk/clk-scmi.c b/drivers/clk/clk-scmi.c index e70708573965..ba234b56f742 100644 --- a/drivers/clk/clk-scmi.c +++ b/drivers/clk/clk-scmi.c @@ -20,6 +20,7 @@ enum scmi_clk_feats { SCMI_CLK_ATOMIC_SUPPORTED, SCMI_CLK_STATE_CTRL_SUPPORTED, + SCMI_CLK_RATE_CTRL_SUPPORTED, SCMI_CLK_FEATS_COUNT }; @@ -248,7 +249,8 @@ scmi_clk_ops_alloc(struct device *dev, unsigned long feats_key) ops->recalc_rate = scmi_clk_recalc_rate; ops->round_rate = scmi_clk_round_rate; ops->determine_rate = scmi_clk_determine_rate; - ops->set_rate = scmi_clk_set_rate; + if (feats_key & BIT(SCMI_CLK_RATE_CTRL_SUPPORTED)) + ops->set_rate = scmi_clk_set_rate; /* Parent ops */ ops->get_parent = scmi_clk_get_parent; @@ -302,6 +304,9 @@ scmi_clk_ops_select(struct scmi_clk *sclk, bool atomic_capable, if (!ci->state_ctrl_forbidden) feats_key |= BIT(SCMI_CLK_STATE_CTRL_SUPPORTED); + if (!ci->rate_ctrl_forbidden) + feats_key |= BIT(SCMI_CLK_RATE_CTRL_SUPPORTED); + if (WARN_ON(feats_key >= db_size)) return NULL; From fa23e091236b812a6143cf0f49821d8f5a6b84fa Mon Sep 17 00:00:00 2001 From: Cristian Marussi Date: Mon, 15 Apr 2024 17:36:48 +0100 Subject: [PATCH 068/118] clk: scmi: Add support for re-parenting restricted clocks Some exposed SCMI Clocks could be marked as non-supporting re-parenting changes. Configure a clk_ops descriptor which does not provide the re-parenting callbacks for such clocks when registering with CLK framework. CC: Michael Turquette CC: Stephen Boyd CC: linux-clk@vger.kernel.org Signed-off-by: Cristian Marussi Link: https://lore.kernel.org/r/20240415163649.895268-5-cristian.marussi@arm.com Reviewed-by: Sudeep Holla Signed-off-by: Stephen Boyd --- drivers/clk/clk-scmi.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/drivers/clk/clk-scmi.c b/drivers/clk/clk-scmi.c index ba234b56f742..ce0f26ee632f 100644 --- a/drivers/clk/clk-scmi.c +++ b/drivers/clk/clk-scmi.c @@ -21,6 +21,7 @@ enum scmi_clk_feats { SCMI_CLK_ATOMIC_SUPPORTED, SCMI_CLK_STATE_CTRL_SUPPORTED, SCMI_CLK_RATE_CTRL_SUPPORTED, + SCMI_CLK_PARENT_CTRL_SUPPORTED, SCMI_CLK_FEATS_COUNT }; @@ -254,7 +255,8 @@ scmi_clk_ops_alloc(struct device *dev, unsigned long feats_key) /* Parent ops */ ops->get_parent = scmi_clk_get_parent; - ops->set_parent = scmi_clk_set_parent; + if (feats_key & BIT(SCMI_CLK_PARENT_CTRL_SUPPORTED)) + ops->set_parent = scmi_clk_set_parent; return ops; } @@ -307,6 +309,9 @@ scmi_clk_ops_select(struct scmi_clk *sclk, bool atomic_capable, if (!ci->rate_ctrl_forbidden) feats_key |= BIT(SCMI_CLK_RATE_CTRL_SUPPORTED); + if (!ci->parent_ctrl_forbidden) + feats_key |= BIT(SCMI_CLK_PARENT_CTRL_SUPPORTED); + if (WARN_ON(feats_key >= db_size)) return NULL; From 87af9481af53c041358be0c46adb103c62218b7f Mon Sep 17 00:00:00 2001 From: Cristian Marussi Date: Mon, 15 Apr 2024 17:36:49 +0100 Subject: [PATCH 069/118] clk: scmi: Add support for get/set duty_cycle operations Provide the CLK framework callbacks related to get/set clock duty cycle if the related SCMI clock supports OEM extended configurations. CC: Michael Turquette CC: Stephen Boyd CC: linux-clk@vger.kernel.org Signed-off-by: Cristian Marussi Link: https://lore.kernel.org/r/20240415163649.895268-6-cristian.marussi@arm.com Reviewed-by: Sudeep Holla Signed-off-by: Stephen Boyd --- drivers/clk/clk-scmi.c | 49 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 49 insertions(+) diff --git a/drivers/clk/clk-scmi.c b/drivers/clk/clk-scmi.c index ce0f26ee632f..d86a02563f6c 100644 --- a/drivers/clk/clk-scmi.c +++ b/drivers/clk/clk-scmi.c @@ -22,6 +22,7 @@ enum scmi_clk_feats { SCMI_CLK_STATE_CTRL_SUPPORTED, SCMI_CLK_RATE_CTRL_SUPPORTED, SCMI_CLK_PARENT_CTRL_SUPPORTED, + SCMI_CLK_DUTY_CYCLE_SUPPORTED, SCMI_CLK_FEATS_COUNT }; @@ -169,6 +170,45 @@ static int scmi_clk_atomic_is_enabled(struct clk_hw *hw) return !!enabled; } +static int scmi_clk_get_duty_cycle(struct clk_hw *hw, struct clk_duty *duty) +{ + int ret; + u32 val; + struct scmi_clk *clk = to_scmi_clk(hw); + + ret = scmi_proto_clk_ops->config_oem_get(clk->ph, clk->id, + SCMI_CLOCK_CFG_DUTY_CYCLE, + &val, NULL, false); + if (!ret) { + duty->num = val; + duty->den = 100; + } else { + dev_warn(clk->dev, + "Failed to get duty cycle for clock ID %d\n", clk->id); + } + + return ret; +} + +static int scmi_clk_set_duty_cycle(struct clk_hw *hw, struct clk_duty *duty) +{ + int ret; + u32 val; + struct scmi_clk *clk = to_scmi_clk(hw); + + /* SCMI OEM Duty Cycle is expressed as a percentage */ + val = (duty->num * 100) / duty->den; + ret = scmi_proto_clk_ops->config_oem_set(clk->ph, clk->id, + SCMI_CLOCK_CFG_DUTY_CYCLE, + val, false); + if (ret) + dev_warn(clk->dev, + "Failed to set duty cycle(%u/%u) for clock ID %d\n", + duty->num, duty->den, clk->id); + + return ret; +} + static int scmi_clk_ops_init(struct device *dev, struct scmi_clk *sclk, const struct clk_ops *scmi_ops) { @@ -258,6 +298,12 @@ scmi_clk_ops_alloc(struct device *dev, unsigned long feats_key) if (feats_key & BIT(SCMI_CLK_PARENT_CTRL_SUPPORTED)) ops->set_parent = scmi_clk_set_parent; + /* Duty cycle */ + if (feats_key & BIT(SCMI_CLK_DUTY_CYCLE_SUPPORTED)) { + ops->get_duty_cycle = scmi_clk_get_duty_cycle; + ops->set_duty_cycle = scmi_clk_set_duty_cycle; + } + return ops; } @@ -312,6 +358,9 @@ scmi_clk_ops_select(struct scmi_clk *sclk, bool atomic_capable, if (!ci->parent_ctrl_forbidden) feats_key |= BIT(SCMI_CLK_PARENT_CTRL_SUPPORTED); + if (ci->extended_config) + feats_key |= BIT(SCMI_CLK_DUTY_CYCLE_SUPPORTED); + if (WARN_ON(feats_key >= db_size)) return NULL; From 3b23118bdbd898dc2f4de8f549d598d492c42ba8 Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Tue, 16 Apr 2024 17:00:51 +0200 Subject: [PATCH 070/118] clk: renesas: r8a779a0: Fix CANFD parent clock MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit According to Figure 52A.1 ("RS-CANFD Module Block Diagram (in classical CAN mode)") in the R-Car V3U Series User’s Manual Rev. 0.5, the parent clock for the CANFD peripheral module clock is the S3D2 clock. Fixes: 9b621b6adff53346 ("clk: renesas: r8a779a0: Add CANFD module clock") Signed-off-by: Geert Uytterhoeven Link: https://lore.kernel.org/r/aef9300f44c9141b1465343f91c5cc7303249b6e.1713279523.git.geert+renesas@glider.be --- drivers/clk/renesas/r8a779a0-cpg-mssr.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/clk/renesas/r8a779a0-cpg-mssr.c b/drivers/clk/renesas/r8a779a0-cpg-mssr.c index 4c2872f45387..ff3f85e906fe 100644 --- a/drivers/clk/renesas/r8a779a0-cpg-mssr.c +++ b/drivers/clk/renesas/r8a779a0-cpg-mssr.c @@ -139,7 +139,7 @@ static const struct mssr_mod_clk r8a779a0_mod_clks[] __initconst = { DEF_MOD("avb3", 214, R8A779A0_CLK_S3D2), DEF_MOD("avb4", 215, R8A779A0_CLK_S3D2), DEF_MOD("avb5", 216, R8A779A0_CLK_S3D2), - DEF_MOD("canfd0", 328, R8A779A0_CLK_CANFD), + DEF_MOD("canfd0", 328, R8A779A0_CLK_S3D2), DEF_MOD("csi40", 331, R8A779A0_CLK_CSI0), DEF_MOD("csi41", 400, R8A779A0_CLK_CSI0), DEF_MOD("csi42", 401, R8A779A0_CLK_CSI0), From 50f0cbd5cc433bf7b22633b4f37b08de64dbfba5 Mon Sep 17 00:00:00 2001 From: Cong Dang Date: Tue, 16 Apr 2024 16:56:27 +0200 Subject: [PATCH 071/118] clk: renesas: r8a779h0: Add MSIOF clocks Add the module clocks used by the Clock-Synchronized Serial Interfaces with FIFO (MSIOF) on the Renesas R-Car V4M (R8A779H0) SoC. Signed-off-by: Cong Dang Signed-off-by: Geert Uytterhoeven Link: https://lore.kernel.org/r/86ce05ae274d384c5221bd136415a7b0a1579592.1713279332.git.geert+renesas@glider.be --- drivers/clk/renesas/r8a779h0-cpg-mssr.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/drivers/clk/renesas/r8a779h0-cpg-mssr.c b/drivers/clk/renesas/r8a779h0-cpg-mssr.c index a7d272285db0..b9ecf9091209 100644 --- a/drivers/clk/renesas/r8a779h0-cpg-mssr.c +++ b/drivers/clk/renesas/r8a779h0-cpg-mssr.c @@ -184,6 +184,12 @@ static const struct mssr_mod_clk r8a779h0_mod_clks[] = { DEF_MOD("i2c1", 519, R8A779H0_CLK_S0D6_PER), DEF_MOD("i2c2", 520, R8A779H0_CLK_S0D6_PER), DEF_MOD("i2c3", 521, R8A779H0_CLK_S0D6_PER), + DEF_MOD("msi0", 618, R8A779H0_CLK_MSO), + DEF_MOD("msi1", 619, R8A779H0_CLK_MSO), + DEF_MOD("msi2", 620, R8A779H0_CLK_MSO), + DEF_MOD("msi3", 621, R8A779H0_CLK_MSO), + DEF_MOD("msi4", 622, R8A779H0_CLK_MSO), + DEF_MOD("msi5", 623, R8A779H0_CLK_MSO), DEF_MOD("rpc-if", 629, R8A779H0_CLK_RPCD2), DEF_MOD("scif0", 702, R8A779H0_CLK_SASYNCPERD4), DEF_MOD("scif1", 703, R8A779H0_CLK_SASYNCPERD4), From ef9916d0e28297410583f89c329a8ba3940dd8fa Mon Sep 17 00:00:00 2001 From: Cong Dang Date: Tue, 16 Apr 2024 16:58:19 +0200 Subject: [PATCH 072/118] clk: renesas: r8a779h0: Add INTC-EX clock Add the module clock used by the Interrupt Controller for External Devices (INTC-EX) aka IRQC on the Renesas R-Car V4M (R8A779H0) SoC. Signed-off-by: Cong Dang Signed-off-by: Geert Uytterhoeven Link: https://lore.kernel.org/r/e260fd8eac0187c690ac6c62673b29f97e2ad5a4.1713279470.git.geert+renesas@glider.be --- drivers/clk/renesas/r8a779h0-cpg-mssr.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/clk/renesas/r8a779h0-cpg-mssr.c b/drivers/clk/renesas/r8a779h0-cpg-mssr.c index b9ecf9091209..079b55b30b23 100644 --- a/drivers/clk/renesas/r8a779h0-cpg-mssr.c +++ b/drivers/clk/renesas/r8a779h0-cpg-mssr.c @@ -184,6 +184,7 @@ static const struct mssr_mod_clk r8a779h0_mod_clks[] = { DEF_MOD("i2c1", 519, R8A779H0_CLK_S0D6_PER), DEF_MOD("i2c2", 520, R8A779H0_CLK_S0D6_PER), DEF_MOD("i2c3", 521, R8A779H0_CLK_S0D6_PER), + DEF_MOD("irqc", 611, R8A779H0_CLK_CL16M), DEF_MOD("msi0", 618, R8A779H0_CLK_MSO), DEF_MOD("msi1", 619, R8A779H0_CLK_MSO), DEF_MOD("msi2", 620, R8A779H0_CLK_MSO), From 44019387fce230beda35b83da3a2c9fc5787704e Mon Sep 17 00:00:00 2001 From: Lad Prabhakar Date: Wed, 3 Apr 2024 21:09:52 +0100 Subject: [PATCH 073/118] clk: renesas: r9a07g043: Add clock and reset entry for PLIC Add the missing clock and reset entry for PLIC. Also add R9A07G043_NCEPLIC_ACLK to the critical clocks list. Fixes: 95d48d270305ad2c ("clk: renesas: r9a07g043: Add support for RZ/Five SoC") Signed-off-by: Lad Prabhakar Reviewed-by: Geert Uytterhoeven Link: https://lore.kernel.org/r/20240403200952.633084-1-prabhakar.mahadev-lad.rj@bp.renesas.com Signed-off-by: Geert Uytterhoeven --- drivers/clk/renesas/r9a07g043-cpg.c | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/drivers/clk/renesas/r9a07g043-cpg.c b/drivers/clk/renesas/r9a07g043-cpg.c index e36d2ec2c0f5..16acc95f3c62 100644 --- a/drivers/clk/renesas/r9a07g043-cpg.c +++ b/drivers/clk/renesas/r9a07g043-cpg.c @@ -280,6 +280,10 @@ static const struct rzg2l_mod_clk r9a07g043_mod_clks[] = { 0x5a8, 1), DEF_MOD("tsu_pclk", R9A07G043_TSU_PCLK, R9A07G043_CLK_TSU, 0x5ac, 0), +#ifdef CONFIG_RISCV + DEF_MOD("nceplic_aclk", R9A07G043_NCEPLIC_ACLK, R9A07G043_CLK_P1, + 0x608, 0), +#endif }; static const struct rzg2l_reset r9a07g043_resets[] = { @@ -338,6 +342,10 @@ static const struct rzg2l_reset r9a07g043_resets[] = { DEF_RST(R9A07G043_ADC_PRESETN, 0x8a8, 0), DEF_RST(R9A07G043_ADC_ADRST_N, 0x8a8, 1), DEF_RST(R9A07G043_TSU_PRESETN, 0x8ac, 0), +#ifdef CONFIG_RISCV + DEF_RST(R9A07G043_NCEPLIC_ARESETN, 0x908, 0), +#endif + }; static const unsigned int r9a07g043_crit_mod_clks[] __initconst = { @@ -347,6 +355,7 @@ static const unsigned int r9a07g043_crit_mod_clks[] __initconst = { #endif #ifdef CONFIG_RISCV MOD_CLK_BASE + R9A07G043_IAX45_CLK, + MOD_CLK_BASE + R9A07G043_NCEPLIC_ACLK, #endif MOD_CLK_BASE + R9A07G043_DMAC_ACLK, }; From 849ed9d414d04e369bccc2278d75becde9e40e0f Mon Sep 17 00:00:00 2001 From: Luca Weiss Date: Sun, 18 Feb 2024 21:57:25 +0100 Subject: [PATCH 074/118] dt-bindings: clock: qcom,hfpll: Convert to YAML Convert the .txt documentation to .yaml with some adjustments. * APQ8064/IPQ8064/MSM8960 compatibles are dropped since their HFPLLs are a part of GCC so there is no need for a separate compat entry. * Change the MSM8974 compatible to follow the updated naming schema. Theis compatible is not used upstream yet. * Add qcs404-hfpll. QCS404 currently uses qcom,hfpll. Mark that as deprecated since every SoC appears to need different driver data so "qcom,hfpll" makes no sense to keep Signed-off-by: Luca Weiss Reviewed-by: Krzysztof Kozlowski Link: https://lore.kernel.org/r/20240218-hfpll-yaml-v2-1-31543e0d6261@z3ntu.xyz Signed-off-by: Bjorn Andersson --- .../devicetree/bindings/clock/qcom,hfpll.txt | 63 ----------------- .../devicetree/bindings/clock/qcom,hfpll.yaml | 69 +++++++++++++++++++ 2 files changed, 69 insertions(+), 63 deletions(-) delete mode 100644 Documentation/devicetree/bindings/clock/qcom,hfpll.txt create mode 100644 Documentation/devicetree/bindings/clock/qcom,hfpll.yaml diff --git a/Documentation/devicetree/bindings/clock/qcom,hfpll.txt b/Documentation/devicetree/bindings/clock/qcom,hfpll.txt deleted file mode 100644 index 5769cbbe76be..000000000000 --- a/Documentation/devicetree/bindings/clock/qcom,hfpll.txt +++ /dev/null @@ -1,63 +0,0 @@ -High-Frequency PLL (HFPLL) - -PROPERTIES - -- compatible: - Usage: required - Value type: : - shall contain only one of the following. The generic - compatible "qcom,hfpll" should be also included. - - "qcom,hfpll-ipq8064", "qcom,hfpll" - "qcom,hfpll-apq8064", "qcom,hfpll" - "qcom,hfpll-msm8974", "qcom,hfpll" - "qcom,hfpll-msm8960", "qcom,hfpll" - "qcom,msm8976-hfpll-a53", "qcom,hfpll" - "qcom,msm8976-hfpll-a72", "qcom,hfpll" - "qcom,msm8976-hfpll-cci", "qcom,hfpll" - -- reg: - Usage: required - Value type: - Definition: address and size of HPLL registers. An optional second - element specifies the address and size of the alias - register region. - -- clocks: - Usage: required - Value type: - Definition: reference to the xo clock. - -- clock-names: - Usage: required - Value type: - Definition: must be "xo". - -- clock-output-names: - Usage: required - Value type: - Definition: Name of the PLL. Typically hfpllX where X is a CPU number - starting at 0. Otherwise hfpll_Y where Y is more specific - such as "l2". - -Example: - -1) An HFPLL for the L2 cache. - - clock-controller@f9016000 { - compatible = "qcom,hfpll-ipq8064", "qcom,hfpll"; - reg = <0xf9016000 0x30>; - clocks = <&xo_board>; - clock-names = "xo"; - clock-output-names = "hfpll_l2"; - }; - -2) An HFPLL for CPU0. This HFPLL has the alias register region. - - clock-controller@f908a000 { - compatible = "qcom,hfpll-ipq8064", "qcom,hfpll"; - reg = <0xf908a000 0x30>, <0xf900a000 0x30>; - clocks = <&xo_board>; - clock-names = "xo"; - clock-output-names = "hfpll0"; - }; diff --git a/Documentation/devicetree/bindings/clock/qcom,hfpll.yaml b/Documentation/devicetree/bindings/clock/qcom,hfpll.yaml new file mode 100644 index 000000000000..8cb1c164f760 --- /dev/null +++ b/Documentation/devicetree/bindings/clock/qcom,hfpll.yaml @@ -0,0 +1,69 @@ +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/clock/qcom,hfpll.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Qualcomm High-Frequency PLL + +maintainers: + - Bjorn Andersson + +description: + The HFPLL is used as CPU PLL on various Qualcomm SoCs. + +properties: + compatible: + oneOf: + - enum: + - qcom,msm8974-hfpll + - qcom,msm8976-hfpll-a53 + - qcom,msm8976-hfpll-a72 + - qcom,msm8976-hfpll-cci + - qcom,qcs404-hfpll + - const: qcom,hfpll + deprecated: true + + reg: + items: + - description: HFPLL registers + - description: Alias register region + minItems: 1 + + '#clock-cells': + const: 0 + + clocks: + items: + - description: board XO clock + + clock-names: + items: + - const: xo + + clock-output-names: + description: + Name of the PLL. Typically hfpllX where X is a CPU number starting at 0. + Otherwise hfpll_Y where Y is more specific such as "l2". + maxItems: 1 + +required: + - compatible + - reg + - '#clock-cells' + - clocks + - clock-names + - clock-output-names + +additionalProperties: false + +examples: + - | + clock-controller@f908a000 { + compatible = "qcom,msm8974-hfpll"; + reg = <0xf908a000 0x30>, <0xf900a000 0x30>; + #clock-cells = <0>; + clock-output-names = "hfpll0"; + clocks = <&xo_board>; + clock-names = "xo"; + }; From 3db0f3b9ff5adb6a5e8564a32fadb2af1216810d Mon Sep 17 00:00:00 2001 From: Luca Weiss Date: Sun, 18 Feb 2024 21:57:26 +0100 Subject: [PATCH 075/118] clk: qcom: hfpll: Add QCS404-specific compatible It doesn't appear that the configuration is for the HFPLL is generic, so add a qcs404-specific compatible and rename the existing struct to qcs404. Keep qcom,hfpll in the driver for compatibility with old dtbs. Signed-off-by: Luca Weiss Link: https://lore.kernel.org/r/20240218-hfpll-yaml-v2-2-31543e0d6261@z3ntu.xyz Signed-off-by: Bjorn Andersson --- drivers/clk/qcom/hfpll.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/drivers/clk/qcom/hfpll.c b/drivers/clk/qcom/hfpll.c index dac27e31ef60..b0b0cb074b4a 100644 --- a/drivers/clk/qcom/hfpll.c +++ b/drivers/clk/qcom/hfpll.c @@ -14,7 +14,7 @@ #include "clk-regmap.h" #include "clk-hfpll.h" -static const struct hfpll_data hdata = { +static const struct hfpll_data qcs404 = { .mode_reg = 0x00, .l_reg = 0x04, .m_reg = 0x08, @@ -84,10 +84,12 @@ static const struct hfpll_data msm8976_cci = { }; static const struct of_device_id qcom_hfpll_match_table[] = { - { .compatible = "qcom,hfpll", .data = &hdata }, { .compatible = "qcom,msm8976-hfpll-a53", .data = &msm8976_a53 }, { .compatible = "qcom,msm8976-hfpll-a72", .data = &msm8976_a72 }, { .compatible = "qcom,msm8976-hfpll-cci", .data = &msm8976_cci }, + { .compatible = "qcom,qcs404-hfpll", .data = &qcs404 }, + /* Deprecated in bindings */ + { .compatible = "qcom,hfpll", .data = &qcs404 }, { } }; MODULE_DEVICE_TABLE(of, qcom_hfpll_match_table); From 1b1f8cc20429e27c1199d4b2846862da8665561b Mon Sep 17 00:00:00 2001 From: Christophe JAILLET Date: Sat, 13 Apr 2024 18:19:40 +0200 Subject: [PATCH 076/118] clk: renesas: r8a7740: Remove unused div4_clk.flags field In "struct div4_clk", the "flags" field is unused. Remove it, and update the "div4_clks" array accordingly. Found with cppcheck, unusedStructMember. Signed-off-by: Christophe JAILLET Reviewed-by: Geert Uytterhoeven Tested-by: Geert Uytterhoeven Link: https://lore.kernel.org/r/658e6b1b23d5b66646bb830361b8c55ccf797771.1713025170.git.christophe.jaillet@wanadoo.fr Signed-off-by: Geert Uytterhoeven --- drivers/clk/renesas/clk-r8a7740.c | 25 ++++++++++++------------- 1 file changed, 12 insertions(+), 13 deletions(-) diff --git a/drivers/clk/renesas/clk-r8a7740.c b/drivers/clk/renesas/clk-r8a7740.c index 3ee3f57e4e9a..325394b6e55e 100644 --- a/drivers/clk/renesas/clk-r8a7740.c +++ b/drivers/clk/renesas/clk-r8a7740.c @@ -32,22 +32,21 @@ struct div4_clk { const char *name; unsigned int reg; unsigned int shift; - int flags; }; static struct div4_clk div4_clks[] = { - { "i", CPG_FRQCRA, 20, CLK_ENABLE_ON_INIT }, - { "zg", CPG_FRQCRA, 16, CLK_ENABLE_ON_INIT }, - { "b", CPG_FRQCRA, 8, CLK_ENABLE_ON_INIT }, - { "m1", CPG_FRQCRA, 4, CLK_ENABLE_ON_INIT }, - { "hp", CPG_FRQCRB, 4, 0 }, - { "hpp", CPG_FRQCRC, 20, 0 }, - { "usbp", CPG_FRQCRC, 16, 0 }, - { "s", CPG_FRQCRC, 12, 0 }, - { "zb", CPG_FRQCRC, 8, 0 }, - { "m3", CPG_FRQCRC, 4, 0 }, - { "cp", CPG_FRQCRC, 0, 0 }, - { NULL, 0, 0, 0 }, + { "i", CPG_FRQCRA, 20 }, + { "zg", CPG_FRQCRA, 16 }, + { "b", CPG_FRQCRA, 8 }, + { "m1", CPG_FRQCRA, 4 }, + { "hp", CPG_FRQCRB, 4 }, + { "hpp", CPG_FRQCRC, 20 }, + { "usbp", CPG_FRQCRC, 16 }, + { "s", CPG_FRQCRC, 12 }, + { "zb", CPG_FRQCRC, 8 }, + { "m3", CPG_FRQCRC, 4 }, + { "cp", CPG_FRQCRC, 0 }, + { NULL, 0, 0 }, }; static const struct clk_div_table div4_div_table[] = { From d0d4585222d0e652ca33f03921d5574963d372ec Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Thu, 25 Apr 2024 10:03:18 +0200 Subject: [PATCH 077/118] clk: renesas: shmobile: Remove unused CLK_ENABLE_ON_INIT CLK_ENABLE_ON_INIT is a relic from the old SH clock framework. It is not used on SH/R-Mobile ARM drivers. Signed-off-by: Geert Uytterhoeven Link: https://lore.kernel.org/r/f01e60a1007afe9385ddc10c4665752857ba4135.1714032122.git.geert+renesas@glider.be --- drivers/clk/renesas/clk-r8a73a4.c | 2 -- drivers/clk/renesas/clk-r8a7740.c | 2 -- drivers/clk/renesas/clk-sh73a0.c | 2 -- 3 files changed, 6 deletions(-) diff --git a/drivers/clk/renesas/clk-r8a73a4.c b/drivers/clk/renesas/clk-r8a73a4.c index f45c2c45808b..4b1815147f77 100644 --- a/drivers/clk/renesas/clk-r8a73a4.c +++ b/drivers/clk/renesas/clk-r8a73a4.c @@ -30,8 +30,6 @@ struct r8a73a4_cpg { #define CPG_PLL2HCR 0xe4 #define CPG_PLL2SCR 0xf4 -#define CLK_ENABLE_ON_INIT BIT(0) - struct div4_clk { const char *name; unsigned int reg; diff --git a/drivers/clk/renesas/clk-r8a7740.c b/drivers/clk/renesas/clk-r8a7740.c index 325394b6e55e..22e9be7240bb 100644 --- a/drivers/clk/renesas/clk-r8a7740.c +++ b/drivers/clk/renesas/clk-r8a7740.c @@ -26,8 +26,6 @@ struct r8a7740_cpg { #define CPG_USBCKCR 0x8c #define CPG_FRQCRC 0xe0 -#define CLK_ENABLE_ON_INIT BIT(0) - struct div4_clk { const char *name; unsigned int reg; diff --git a/drivers/clk/renesas/clk-sh73a0.c b/drivers/clk/renesas/clk-sh73a0.c index 8c51090f13e1..47fc99ccd283 100644 --- a/drivers/clk/renesas/clk-sh73a0.c +++ b/drivers/clk/renesas/clk-sh73a0.c @@ -34,8 +34,6 @@ struct sh73a0_cpg { #define CPG_DSI0PHYCR 0x6c #define CPG_DSI1PHYCR 0x70 -#define CLK_ENABLE_ON_INIT BIT(0) - struct div4_clk { const char *name; const char *parent; From b6cc692ac67a75b97a2d524d8e2fd2d59b20248a Mon Sep 17 00:00:00 2001 From: Claudiu Beznea Date: Mon, 22 Apr 2024 13:53:48 +0300 Subject: [PATCH 078/118] dt-bindings: clock: r9a07g043-cpg: Add power domain IDs Add power domain IDs for the RZ/G2UL (R9A07G043) SoC. Signed-off-by: Claudiu Beznea Acked-by: Rob Herring Reviewed-by: Geert Uytterhoeven Reviewed-by: Ulf Hansson Link: https://lore.kernel.org/r/20240422105355.1622177-2-claudiu.beznea.uj@bp.renesas.com Signed-off-by: Geert Uytterhoeven --- include/dt-bindings/clock/r9a07g043-cpg.h | 52 +++++++++++++++++++++++ 1 file changed, 52 insertions(+) diff --git a/include/dt-bindings/clock/r9a07g043-cpg.h b/include/dt-bindings/clock/r9a07g043-cpg.h index a64139fec815..131993343777 100644 --- a/include/dt-bindings/clock/r9a07g043-cpg.h +++ b/include/dt-bindings/clock/r9a07g043-cpg.h @@ -200,5 +200,57 @@ #define R9A07G043_AX45MP_CORE0_RESETN 78 /* RZ/Five Only */ #define R9A07G043_IAX45_RESETN 79 /* RZ/Five Only */ +/* Power domain IDs. */ +#define R9A07G043_PD_ALWAYS_ON 0 +#define R9A07G043_PD_GIC 1 /* RZ/G2UL Only */ +#define R9A07G043_PD_IA55 2 /* RZ/G2UL Only */ +#define R9A07G043_PD_MHU 3 /* RZ/G2UL Only */ +#define R9A07G043_PD_CORESIGHT 4 /* RZ/G2UL Only */ +#define R9A07G043_PD_SYC 5 /* RZ/G2UL Only */ +#define R9A07G043_PD_DMAC 6 +#define R9A07G043_PD_GTM0 7 +#define R9A07G043_PD_GTM1 8 +#define R9A07G043_PD_GTM2 9 +#define R9A07G043_PD_MTU 10 +#define R9A07G043_PD_POE3 11 +#define R9A07G043_PD_WDT0 12 +#define R9A07G043_PD_SPI 13 +#define R9A07G043_PD_SDHI0 14 +#define R9A07G043_PD_SDHI1 15 +#define R9A07G043_PD_ISU 16 /* RZ/G2UL Only */ +#define R9A07G043_PD_CRU 17 /* RZ/G2UL Only */ +#define R9A07G043_PD_LCDC 18 /* RZ/G2UL Only */ +#define R9A07G043_PD_SSI0 19 +#define R9A07G043_PD_SSI1 20 +#define R9A07G043_PD_SSI2 21 +#define R9A07G043_PD_SSI3 22 +#define R9A07G043_PD_SRC 23 +#define R9A07G043_PD_USB0 24 +#define R9A07G043_PD_USB1 25 +#define R9A07G043_PD_USB_PHY 26 +#define R9A07G043_PD_ETHER0 27 +#define R9A07G043_PD_ETHER1 28 +#define R9A07G043_PD_I2C0 29 +#define R9A07G043_PD_I2C1 30 +#define R9A07G043_PD_I2C2 31 +#define R9A07G043_PD_I2C3 32 +#define R9A07G043_PD_SCIF0 33 +#define R9A07G043_PD_SCIF1 34 +#define R9A07G043_PD_SCIF2 35 +#define R9A07G043_PD_SCIF3 36 +#define R9A07G043_PD_SCIF4 37 +#define R9A07G043_PD_SCI0 38 +#define R9A07G043_PD_SCI1 39 +#define R9A07G043_PD_IRDA 40 +#define R9A07G043_PD_RSPI0 41 +#define R9A07G043_PD_RSPI1 42 +#define R9A07G043_PD_RSPI2 43 +#define R9A07G043_PD_CANFD 44 +#define R9A07G043_PD_ADC 45 +#define R9A07G043_PD_TSU 46 +#define R9A07G043_PD_PLIC 47 /* RZ/Five Only */ +#define R9A07G043_PD_IAX45 48 /* RZ/Five Only */ +#define R9A07G043_PD_NCEPLDM 49 /* RZ/Five Only */ +#define R9A07G043_PD_NCEPLMT 50 /* RZ/Five Only */ #endif /* __DT_BINDINGS_CLOCK_R9A07G043_CPG_H__ */ From d744e4567419e26025f42e8b1f13c0b021d62819 Mon Sep 17 00:00:00 2001 From: Claudiu Beznea Date: Mon, 22 Apr 2024 13:53:49 +0300 Subject: [PATCH 079/118] dt-bindings: clock: r9a07g044-cpg: Add power domain IDs Add power domain IDs for the RZ/G2L (R9A07G044) SoC. Signed-off-by: Claudiu Beznea Reviewed-by: Geert Uytterhoeven Acked-by: Rob Herring Reviewed-by: Ulf Hansson Link: https://lore.kernel.org/r/20240422105355.1622177-3-claudiu.beznea.uj@bp.renesas.com Signed-off-by: Geert Uytterhoeven --- include/dt-bindings/clock/r9a07g044-cpg.h | 58 +++++++++++++++++++++++ 1 file changed, 58 insertions(+) diff --git a/include/dt-bindings/clock/r9a07g044-cpg.h b/include/dt-bindings/clock/r9a07g044-cpg.h index 0bb17ff1a01a..e209f96f92b7 100644 --- a/include/dt-bindings/clock/r9a07g044-cpg.h +++ b/include/dt-bindings/clock/r9a07g044-cpg.h @@ -217,4 +217,62 @@ #define R9A07G044_ADC_ADRST_N 82 #define R9A07G044_TSU_PRESETN 83 +/* Power domain IDs. */ +#define R9A07G044_PD_ALWAYS_ON 0 +#define R9A07G044_PD_GIC 1 +#define R9A07G044_PD_IA55 2 +#define R9A07G044_PD_MHU 3 +#define R9A07G044_PD_CORESIGHT 4 +#define R9A07G044_PD_SYC 5 +#define R9A07G044_PD_DMAC 6 +#define R9A07G044_PD_GTM0 7 +#define R9A07G044_PD_GTM1 8 +#define R9A07G044_PD_GTM2 9 +#define R9A07G044_PD_MTU 10 +#define R9A07G044_PD_POE3 11 +#define R9A07G044_PD_GPT 12 +#define R9A07G044_PD_POEGA 13 +#define R9A07G044_PD_POEGB 14 +#define R9A07G044_PD_POEGC 15 +#define R9A07G044_PD_POEGD 16 +#define R9A07G044_PD_WDT0 17 +#define R9A07G044_PD_WDT1 18 +#define R9A07G044_PD_SPI 19 +#define R9A07G044_PD_SDHI0 20 +#define R9A07G044_PD_SDHI1 21 +#define R9A07G044_PD_3DGE 22 +#define R9A07G044_PD_ISU 23 +#define R9A07G044_PD_VCPL4 24 +#define R9A07G044_PD_CRU 25 +#define R9A07G044_PD_MIPI_DSI 26 +#define R9A07G044_PD_LCDC 27 +#define R9A07G044_PD_SSI0 28 +#define R9A07G044_PD_SSI1 29 +#define R9A07G044_PD_SSI2 30 +#define R9A07G044_PD_SSI3 31 +#define R9A07G044_PD_SRC 32 +#define R9A07G044_PD_USB0 33 +#define R9A07G044_PD_USB1 34 +#define R9A07G044_PD_USB_PHY 35 +#define R9A07G044_PD_ETHER0 36 +#define R9A07G044_PD_ETHER1 37 +#define R9A07G044_PD_I2C0 38 +#define R9A07G044_PD_I2C1 39 +#define R9A07G044_PD_I2C2 40 +#define R9A07G044_PD_I2C3 41 +#define R9A07G044_PD_SCIF0 42 +#define R9A07G044_PD_SCIF1 43 +#define R9A07G044_PD_SCIF2 44 +#define R9A07G044_PD_SCIF3 45 +#define R9A07G044_PD_SCIF4 46 +#define R9A07G044_PD_SCI0 47 +#define R9A07G044_PD_SCI1 48 +#define R9A07G044_PD_IRDA 49 +#define R9A07G044_PD_RSPI0 50 +#define R9A07G044_PD_RSPI1 51 +#define R9A07G044_PD_RSPI2 52 +#define R9A07G044_PD_CANFD 53 +#define R9A07G044_PD_ADC 54 +#define R9A07G044_PD_TSU 55 + #endif /* __DT_BINDINGS_CLOCK_R9A07G044_CPG_H__ */ From 5b9979fda3058c786706d86b6e0ecb8e71be5a84 Mon Sep 17 00:00:00 2001 From: Claudiu Beznea Date: Mon, 22 Apr 2024 13:53:50 +0300 Subject: [PATCH 080/118] dt-bindings: clock: r9a07g054-cpg: Add power domain IDs Add power domain IDs for the RZ/V2L (R9A07G054) SoC. Signed-off-by: Claudiu Beznea Reviewed-by: Geert Uytterhoeven Acked-by: Rob Herring Reviewed-by: Ulf Hansson Link: https://lore.kernel.org/r/20240422105355.1622177-4-claudiu.beznea.uj@bp.renesas.com Signed-off-by: Geert Uytterhoeven --- include/dt-bindings/clock/r9a07g054-cpg.h | 58 +++++++++++++++++++++++ 1 file changed, 58 insertions(+) diff --git a/include/dt-bindings/clock/r9a07g054-cpg.h b/include/dt-bindings/clock/r9a07g054-cpg.h index 43f4dbda872c..2c99f89397c4 100644 --- a/include/dt-bindings/clock/r9a07g054-cpg.h +++ b/include/dt-bindings/clock/r9a07g054-cpg.h @@ -226,4 +226,62 @@ #define R9A07G054_TSU_PRESETN 83 #define R9A07G054_STPAI_ARESETN 84 +/* Power domain IDs. */ +#define R9A07G054_PD_ALWAYS_ON 0 +#define R9A07G054_PD_GIC 1 +#define R9A07G054_PD_IA55 2 +#define R9A07G054_PD_MHU 3 +#define R9A07G054_PD_CORESIGHT 4 +#define R9A07G054_PD_SYC 5 +#define R9A07G054_PD_DMAC 6 +#define R9A07G054_PD_GTM0 7 +#define R9A07G054_PD_GTM1 8 +#define R9A07G054_PD_GTM2 9 +#define R9A07G054_PD_MTU 10 +#define R9A07G054_PD_POE3 11 +#define R9A07G054_PD_GPT 12 +#define R9A07G054_PD_POEGA 13 +#define R9A07G054_PD_POEGB 14 +#define R9A07G054_PD_POEGC 15 +#define R9A07G054_PD_POEGD 16 +#define R9A07G054_PD_WDT0 17 +#define R9A07G054_PD_WDT1 18 +#define R9A07G054_PD_SPI 19 +#define R9A07G054_PD_SDHI0 20 +#define R9A07G054_PD_SDHI1 21 +#define R9A07G054_PD_3DGE 22 +#define R9A07G054_PD_ISU 23 +#define R9A07G054_PD_VCPL4 24 +#define R9A07G054_PD_CRU 25 +#define R9A07G054_PD_MIPI_DSI 26 +#define R9A07G054_PD_LCDC 27 +#define R9A07G054_PD_SSI0 28 +#define R9A07G054_PD_SSI1 29 +#define R9A07G054_PD_SSI2 30 +#define R9A07G054_PD_SSI3 31 +#define R9A07G054_PD_SRC 32 +#define R9A07G054_PD_USB0 33 +#define R9A07G054_PD_USB1 34 +#define R9A07G054_PD_USB_PHY 35 +#define R9A07G054_PD_ETHER0 36 +#define R9A07G054_PD_ETHER1 37 +#define R9A07G054_PD_I2C0 38 +#define R9A07G054_PD_I2C1 39 +#define R9A07G054_PD_I2C2 40 +#define R9A07G054_PD_I2C3 41 +#define R9A07G054_PD_SCIF0 42 +#define R9A07G054_PD_SCIF1 43 +#define R9A07G054_PD_SCIF2 44 +#define R9A07G054_PD_SCIF3 45 +#define R9A07G054_PD_SCIF4 46 +#define R9A07G054_PD_SCI0 47 +#define R9A07G054_PD_SCI1 48 +#define R9A07G054_PD_IRDA 49 +#define R9A07G054_PD_RSPI0 50 +#define R9A07G054_PD_RSPI1 51 +#define R9A07G054_PD_RSPI2 52 +#define R9A07G054_PD_CANFD 53 +#define R9A07G054_PD_ADC 54 +#define R9A07G054_PD_TSU 55 + #endif /* __DT_BINDINGS_CLOCK_R9A07G054_CPG_H__ */ From 2d03ce9cd7bdd1e29772f8ecf7769535361c7eaa Mon Sep 17 00:00:00 2001 From: Claudiu Beznea Date: Mon, 22 Apr 2024 13:53:51 +0300 Subject: [PATCH 081/118] dt-bindings: clock: r9a08g045-cpg: Add power domain IDs Add power domain IDs for the RZ/G3S (R9A08G045) SoC. Signed-off-by: Claudiu Beznea Reviewed-by: Geert Uytterhoeven Acked-by: Rob Herring Reviewed-by: Ulf Hansson Link: https://lore.kernel.org/r/20240422105355.1622177-5-claudiu.beznea.uj@bp.renesas.com Signed-off-by: Geert Uytterhoeven --- include/dt-bindings/clock/r9a08g045-cpg.h | 70 +++++++++++++++++++++++ 1 file changed, 70 insertions(+) diff --git a/include/dt-bindings/clock/r9a08g045-cpg.h b/include/dt-bindings/clock/r9a08g045-cpg.h index 410725b778a8..8281e9caf3a9 100644 --- a/include/dt-bindings/clock/r9a08g045-cpg.h +++ b/include/dt-bindings/clock/r9a08g045-cpg.h @@ -239,4 +239,74 @@ #define R9A08G045_I3C_PRESETN 92 #define R9A08G045_VBAT_BRESETN 93 +/* Power domain IDs. */ +#define R9A08G045_PD_ALWAYS_ON 0 +#define R9A08G045_PD_GIC 1 +#define R9A08G045_PD_IA55 2 +#define R9A08G045_PD_MHU 3 +#define R9A08G045_PD_CORESIGHT 4 +#define R9A08G045_PD_SYC 5 +#define R9A08G045_PD_DMAC 6 +#define R9A08G045_PD_GTM0 7 +#define R9A08G045_PD_GTM1 8 +#define R9A08G045_PD_GTM2 9 +#define R9A08G045_PD_GTM3 10 +#define R9A08G045_PD_GTM4 11 +#define R9A08G045_PD_GTM5 12 +#define R9A08G045_PD_GTM6 13 +#define R9A08G045_PD_GTM7 14 +#define R9A08G045_PD_MTU 15 +#define R9A08G045_PD_POE3 16 +#define R9A08G045_PD_GPT 17 +#define R9A08G045_PD_POEGA 18 +#define R9A08G045_PD_POEGB 19 +#define R9A08G045_PD_POEGC 20 +#define R9A08G045_PD_POEGD 21 +#define R9A08G045_PD_WDT0 22 +#define R9A08G045_PD_XSPI 23 +#define R9A08G045_PD_SDHI0 24 +#define R9A08G045_PD_SDHI1 25 +#define R9A08G045_PD_SDHI2 26 +#define R9A08G045_PD_SSI0 27 +#define R9A08G045_PD_SSI1 28 +#define R9A08G045_PD_SSI2 29 +#define R9A08G045_PD_SSI3 30 +#define R9A08G045_PD_SRC 31 +#define R9A08G045_PD_USB0 32 +#define R9A08G045_PD_USB1 33 +#define R9A08G045_PD_USB_PHY 34 +#define R9A08G045_PD_ETHER0 35 +#define R9A08G045_PD_ETHER1 36 +#define R9A08G045_PD_I2C0 37 +#define R9A08G045_PD_I2C1 38 +#define R9A08G045_PD_I2C2 39 +#define R9A08G045_PD_I2C3 40 +#define R9A08G045_PD_SCIF0 41 +#define R9A08G045_PD_SCIF1 42 +#define R9A08G045_PD_SCIF2 43 +#define R9A08G045_PD_SCIF3 44 +#define R9A08G045_PD_SCIF4 45 +#define R9A08G045_PD_SCIF5 46 +#define R9A08G045_PD_SCI0 47 +#define R9A08G045_PD_SCI1 48 +#define R9A08G045_PD_IRDA 49 +#define R9A08G045_PD_RSPI0 50 +#define R9A08G045_PD_RSPI1 51 +#define R9A08G045_PD_RSPI2 52 +#define R9A08G045_PD_RSPI3 53 +#define R9A08G045_PD_RSPI4 54 +#define R9A08G045_PD_CANFD 55 +#define R9A08G045_PD_ADC 56 +#define R9A08G045_PD_TSU 57 +#define R9A08G045_PD_OCTA 58 +#define R9A08G045_PD_PDM 59 +#define R9A08G045_PD_PCI 60 +#define R9A08G045_PD_SPDIF 61 +#define R9A08G045_PD_I3C 62 +#define R9A08G045_PD_VBAT 63 + +#define R9A08G045_PD_DDR 64 +#define R9A08G045_PD_TZCDDR 65 +#define R9A08G045_PD_OTFDE_DDR 66 + #endif /* __DT_BINDINGS_CLOCK_R9A08G045_CPG_H__ */ From f33dca9ed6f41c8acf2c17c402738deddb7d7c28 Mon Sep 17 00:00:00 2001 From: Claudiu Beznea Date: Mon, 22 Apr 2024 13:53:52 +0300 Subject: [PATCH 082/118] dt-bindings: clock: renesas,rzg2l-cpg: Update #power-domain-cells = <1> for RZ/G3S The driver will be modified (in the next commits) to be able to specify individual power domain IDs for each IP. The driver will still support #power-domain-cells = <0>, thus, previous users are not affected. The #power-domain-cells = <1> has been instantiated only for RZ/G3S at the moment, as individual platform clock drivers need to be adapted for this to be supported on the rest of the SoCs. Also, the description for #power-domain-cells is updated with links to per-SoC power domain IDs. Signed-off-by: Claudiu Beznea Reviewed-by: Rob Herring Reviewed-by: Geert Uytterhoeven Reviewed-by: Ulf Hansson Link: https://lore.kernel.org/r/20240422105355.1622177-6-claudiu.beznea.uj@bp.renesas.com Signed-off-by: Geert Uytterhoeven --- .../bindings/clock/renesas,rzg2l-cpg.yaml | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) diff --git a/Documentation/devicetree/bindings/clock/renesas,rzg2l-cpg.yaml b/Documentation/devicetree/bindings/clock/renesas,rzg2l-cpg.yaml index 80a8c7114c31..4e3b0c45124a 100644 --- a/Documentation/devicetree/bindings/clock/renesas,rzg2l-cpg.yaml +++ b/Documentation/devicetree/bindings/clock/renesas,rzg2l-cpg.yaml @@ -57,7 +57,8 @@ properties: can be power-managed through Module Standby should refer to the CPG device node in their "power-domains" property, as documented by the generic PM Domain bindings in Documentation/devicetree/bindings/power/power-domain.yaml. - const: 0 + The power domain specifiers defined in could + be used to reference individual CPG power domains. '#reset-cells': description: @@ -76,6 +77,21 @@ required: additionalProperties: false +allOf: + - if: + properties: + compatible: + contains: + const: renesas,r9a08g045-cpg + then: + properties: + '#power-domain-cells': + const: 1 + else: + properties: + '#power-domain-cells': + const: 0 + examples: - | cpg: clock-controller@11010000 { From 0c8a59b3113ef6184d1e4cf2fb911c641d5172e3 Mon Sep 17 00:00:00 2001 From: Claudiu Beznea Date: Mon, 22 Apr 2024 13:53:53 +0300 Subject: [PATCH 083/118] clk: renesas: rzg2l: Extend power domain support RZ/{G2L, V2L, G3S}-based CPG versions have support for saving extra power when clocks are disabled by activating module standby. This is done through MSTOP-specific registers that are part of CPG. Each individual module has one or more bits associated with one MSTOP register (see table "Registers for Module Standby Mode" from HW manuals). Hardware manual associates modules' clocks with one or more MSTOP bits. There are 3 mappings available (identified by researching RZ/G2L, RZ/G3S, RZ/V2L HW manuals): case 1: N clocks mapped to N MSTOP bits (with N={0, ..., X}) case 2: N clocks mapped to 1 MSTOP bit (with N={0, ..., X}) case 3: N clocks mapped to M MSTOP bits (with N={0, ..., X}, M={0, ..., Y}) Case 3 has been currently identified on RZ/V2L for the VCPL4 module. To cover all three cases, the individual platform drivers will provide the clock driver with MSTOP register offsets and associated bits in this register as a bitmask, and the clock driver will apply this bitmask to the proper MSTOP register. The MSTOP support was implemented through power domains. Platform-specific clock drivers will register an array of type struct rzg2l_cpg_pm_domain_init_data, which will be used to instantiate properly the power domains. Signed-off-by: Claudiu Beznea Reviewed-by: Geert Uytterhoeven Reviewed-by: Ulf Hansson Link: https://lore.kernel.org/r/20240422105355.1622177-7-claudiu.beznea.uj@bp.renesas.com Signed-off-by: Geert Uytterhoeven --- drivers/clk/renesas/rzg2l-cpg.c | 199 +++++++++++++++++++++++++++++--- drivers/clk/renesas/rzg2l-cpg.h | 67 +++++++++++ 2 files changed, 252 insertions(+), 14 deletions(-) diff --git a/drivers/clk/renesas/rzg2l-cpg.c b/drivers/clk/renesas/rzg2l-cpg.c index 3d2daa4ba2a4..04b78064d4e0 100644 --- a/drivers/clk/renesas/rzg2l-cpg.c +++ b/drivers/clk/renesas/rzg2l-cpg.c @@ -139,7 +139,6 @@ struct rzg2l_pll5_mux_dsi_div_param { * @num_resets: Number of Module Resets in info->resets[] * @last_dt_core_clk: ID of the last Core Clock exported to DT * @info: Pointer to platform data - * @genpd: PM domain * @mux_dsi_div_params: pll5 mux and dsi div parameters */ struct rzg2l_cpg_priv { @@ -156,8 +155,6 @@ struct rzg2l_cpg_priv { const struct rzg2l_cpg_info *info; - struct generic_pm_domain genpd; - struct rzg2l_pll5_mux_dsi_div_param mux_dsi_div_params; }; @@ -1559,9 +1556,34 @@ static bool rzg2l_cpg_is_pm_clk(struct rzg2l_cpg_priv *priv, return true; } +/** + * struct rzg2l_cpg_pm_domains - RZ/G2L PM domains data structure + * @onecell_data: cell data + * @domains: generic PM domains + */ +struct rzg2l_cpg_pm_domains { + struct genpd_onecell_data onecell_data; + struct generic_pm_domain *domains[]; +}; + +/** + * struct rzg2l_cpg_pd - RZ/G2L power domain data structure + * @genpd: generic PM domain + * @priv: pointer to CPG private data structure + * @conf: CPG PM domain configuration info + * @id: RZ/G2L power domain ID + */ +struct rzg2l_cpg_pd { + struct generic_pm_domain genpd; + struct rzg2l_cpg_priv *priv; + struct rzg2l_cpg_pm_domain_conf conf; + u16 id; +}; + static int rzg2l_cpg_attach_dev(struct generic_pm_domain *domain, struct device *dev) { - struct rzg2l_cpg_priv *priv = container_of(domain, struct rzg2l_cpg_priv, genpd); + struct rzg2l_cpg_pd *pd = container_of(domain, struct rzg2l_cpg_pd, genpd); + struct rzg2l_cpg_priv *priv = pd->priv; struct device_node *np = dev->of_node; struct of_phandle_args clkspec; bool once = true; @@ -1617,31 +1639,180 @@ static void rzg2l_cpg_detach_dev(struct generic_pm_domain *unused, struct device } static void rzg2l_cpg_genpd_remove(void *data) +{ + struct genpd_onecell_data *celldata = data; + + for (unsigned int i = 0; i < celldata->num_domains; i++) + pm_genpd_remove(celldata->domains[i]); +} + +static void rzg2l_cpg_genpd_remove_simple(void *data) { pm_genpd_remove(data); } +static int rzg2l_cpg_power_on(struct generic_pm_domain *domain) +{ + struct rzg2l_cpg_pd *pd = container_of(domain, struct rzg2l_cpg_pd, genpd); + struct rzg2l_cpg_reg_conf mstop = pd->conf.mstop; + struct rzg2l_cpg_priv *priv = pd->priv; + + /* Set MSTOP. */ + if (mstop.mask) + writel(mstop.mask << 16, priv->base + mstop.off); + + return 0; +} + +static int rzg2l_cpg_power_off(struct generic_pm_domain *domain) +{ + struct rzg2l_cpg_pd *pd = container_of(domain, struct rzg2l_cpg_pd, genpd); + struct rzg2l_cpg_reg_conf mstop = pd->conf.mstop; + struct rzg2l_cpg_priv *priv = pd->priv; + + /* Set MSTOP. */ + if (mstop.mask) + writel(mstop.mask | (mstop.mask << 16), priv->base + mstop.off); + + return 0; +} + +static int __init rzg2l_cpg_pd_setup(struct rzg2l_cpg_pd *pd, bool always_on) +{ + struct dev_power_governor *governor; + + pd->genpd.flags |= GENPD_FLAG_PM_CLK | GENPD_FLAG_ACTIVE_WAKEUP; + pd->genpd.attach_dev = rzg2l_cpg_attach_dev; + pd->genpd.detach_dev = rzg2l_cpg_detach_dev; + if (always_on) { + pd->genpd.flags |= GENPD_FLAG_ALWAYS_ON; + governor = &pm_domain_always_on_gov; + } else { + pd->genpd.power_on = rzg2l_cpg_power_on; + pd->genpd.power_off = rzg2l_cpg_power_off; + governor = &simple_qos_governor; + } + + return pm_genpd_init(&pd->genpd, governor, !always_on); +} + static int __init rzg2l_cpg_add_clk_domain(struct rzg2l_cpg_priv *priv) { struct device *dev = priv->dev; struct device_node *np = dev->of_node; - struct generic_pm_domain *genpd = &priv->genpd; + struct rzg2l_cpg_pd *pd; int ret; - genpd->name = np->name; - genpd->flags = GENPD_FLAG_PM_CLK | GENPD_FLAG_ALWAYS_ON | - GENPD_FLAG_ACTIVE_WAKEUP; - genpd->attach_dev = rzg2l_cpg_attach_dev; - genpd->detach_dev = rzg2l_cpg_detach_dev; - ret = pm_genpd_init(genpd, &pm_domain_always_on_gov, false); + pd = devm_kzalloc(dev, sizeof(*pd), GFP_KERNEL); + if (!pd) + return -ENOMEM; + + pd->genpd.name = np->name; + pd->priv = priv; + ret = rzg2l_cpg_pd_setup(pd, true); if (ret) return ret; - ret = devm_add_action_or_reset(dev, rzg2l_cpg_genpd_remove, genpd); + ret = devm_add_action_or_reset(dev, rzg2l_cpg_genpd_remove_simple, &pd->genpd); if (ret) return ret; - return of_genpd_add_provider_simple(np, genpd); + return of_genpd_add_provider_simple(np, &pd->genpd); +} + +static struct generic_pm_domain * +rzg2l_cpg_pm_domain_xlate(const struct of_phandle_args *spec, void *data) +{ + struct generic_pm_domain *domain = ERR_PTR(-ENOENT); + struct genpd_onecell_data *genpd = data; + + if (spec->args_count != 1) + return ERR_PTR(-EINVAL); + + for (unsigned int i = 0; i < genpd->num_domains; i++) { + struct rzg2l_cpg_pd *pd = container_of(genpd->domains[i], struct rzg2l_cpg_pd, + genpd); + + if (pd->id == spec->args[0]) { + domain = &pd->genpd; + break; + } + } + + return domain; +} + +static int __init rzg2l_cpg_add_pm_domains(struct rzg2l_cpg_priv *priv) +{ + const struct rzg2l_cpg_info *info = priv->info; + struct device *dev = priv->dev; + struct device_node *np = dev->of_node; + struct rzg2l_cpg_pm_domains *domains; + struct generic_pm_domain *parent; + u32 ncells; + int ret; + + ret = of_property_read_u32(np, "#power-domain-cells", &ncells); + if (ret) + return ret; + + /* For backward compatibility. */ + if (!ncells) + return rzg2l_cpg_add_clk_domain(priv); + + domains = devm_kzalloc(dev, struct_size(domains, domains, info->num_pm_domains), + GFP_KERNEL); + if (!domains) + return -ENOMEM; + + domains->onecell_data.domains = domains->domains; + domains->onecell_data.num_domains = info->num_pm_domains; + domains->onecell_data.xlate = rzg2l_cpg_pm_domain_xlate; + + ret = devm_add_action_or_reset(dev, rzg2l_cpg_genpd_remove, &domains->onecell_data); + if (ret) + return ret; + + for (unsigned int i = 0; i < info->num_pm_domains; i++) { + bool always_on = !!(info->pm_domains[i].flags & RZG2L_PD_F_ALWAYS_ON); + struct rzg2l_cpg_pd *pd; + + pd = devm_kzalloc(dev, sizeof(*pd), GFP_KERNEL); + if (!pd) + return -ENOMEM; + + pd->genpd.name = info->pm_domains[i].name; + pd->conf = info->pm_domains[i].conf; + pd->id = info->pm_domains[i].id; + pd->priv = priv; + + ret = rzg2l_cpg_pd_setup(pd, always_on); + if (ret) + return ret; + + if (always_on) { + ret = rzg2l_cpg_power_on(&pd->genpd); + if (ret) + return ret; + } + + domains->domains[i] = &pd->genpd; + /* Parent should be on the very first entry of info->pm_domains[]. */ + if (!i) { + parent = &pd->genpd; + continue; + } + + ret = pm_genpd_add_subdomain(parent, &pd->genpd); + if (ret) + return ret; + } + + ret = of_genpd_add_provider_onecell(np, &domains->onecell_data); + if (ret) + return ret; + + return 0; } static int __init rzg2l_cpg_probe(struct platform_device *pdev) @@ -1697,7 +1868,7 @@ static int __init rzg2l_cpg_probe(struct platform_device *pdev) if (error) return error; - error = rzg2l_cpg_add_clk_domain(priv); + error = rzg2l_cpg_add_pm_domains(priv); if (error) return error; diff --git a/drivers/clk/renesas/rzg2l-cpg.h b/drivers/clk/renesas/rzg2l-cpg.h index 6e38c8fc888c..ecfe7e7ea8a1 100644 --- a/drivers/clk/renesas/rzg2l-cpg.h +++ b/drivers/clk/renesas/rzg2l-cpg.h @@ -27,6 +27,18 @@ #define CPG_PL6_ETH_SSEL (0x418) #define CPG_PL5_SDIV (0x420) #define CPG_RST_MON (0x680) +#define CPG_BUS_ACPU_MSTOP (0xB60) +#define CPG_BUS_MCPU1_MSTOP (0xB64) +#define CPG_BUS_MCPU2_MSTOP (0xB68) +#define CPG_BUS_PERI_COM_MSTOP (0xB6C) +#define CPG_BUS_PERI_CPU_MSTOP (0xB70) +#define CPG_BUS_PERI_DDR_MSTOP (0xB74) +#define CPG_BUS_REG0_MSTOP (0xB7C) +#define CPG_BUS_REG1_MSTOP (0xB80) +#define CPG_BUS_TZCDDR_MSTOP (0xB84) +#define CPG_MHU_MSTOP (0xB88) +#define CPG_BUS_MCPU3_MSTOP (0xB90) +#define CPG_BUS_PERI_CPU2_MSTOP (0xB94) #define CPG_OTHERFUNC1_REG (0xBE8) #define CPG_SIPLL5_STBY_RESETB BIT(0) @@ -234,6 +246,55 @@ struct rzg2l_reset { #define DEF_RST(_id, _off, _bit) \ DEF_RST_MON(_id, _off, _bit, -1) +/** + * struct rzg2l_cpg_reg_conf - RZ/G2L register configuration data structure + * @off: register offset + * @mask: register mask + */ +struct rzg2l_cpg_reg_conf { + u16 off; + u16 mask; +}; + +#define DEF_REG_CONF(_off, _mask) ((struct rzg2l_cpg_reg_conf) { .off = (_off), .mask = (_mask) }) + +/** + * struct rzg2l_cpg_pm_domain_conf - PM domain configuration data structure + * @mstop: MSTOP register configuration + */ +struct rzg2l_cpg_pm_domain_conf { + struct rzg2l_cpg_reg_conf mstop; +}; + +/** + * struct rzg2l_cpg_pm_domain_init_data - PM domain init data + * @name: PM domain name + * @conf: PM domain configuration + * @flags: RZG2L PM domain flags (see RZG2L_PD_F_*) + * @id: PM domain ID (similar to the ones defined in + * include/dt-bindings/clock/-cpg.h) + */ +struct rzg2l_cpg_pm_domain_init_data { + const char * const name; + struct rzg2l_cpg_pm_domain_conf conf; + u32 flags; + u16 id; +}; + +#define DEF_PD(_name, _id, _mstop_conf, _flags) \ + { \ + .name = (_name), \ + .id = (_id), \ + .conf = { \ + .mstop = (_mstop_conf), \ + }, \ + .flags = (_flags), \ + } + +/* Power domain flags. */ +#define RZG2L_PD_F_ALWAYS_ON BIT(0) +#define RZG2L_PD_F_NONE (0) + /** * struct rzg2l_cpg_info - SoC-specific CPG Description * @@ -252,6 +313,8 @@ struct rzg2l_reset { * @crit_mod_clks: Array with Module Clock IDs of critical clocks that * should not be disabled without a knowledgeable driver * @num_crit_mod_clks: Number of entries in crit_mod_clks[] + * @pm_domains: PM domains init data array + * @num_pm_domains: Number of PM domains * @has_clk_mon_regs: Flag indicating whether the SoC has CLK_MON registers */ struct rzg2l_cpg_info { @@ -278,6 +341,10 @@ struct rzg2l_cpg_info { const unsigned int *crit_mod_clks; unsigned int num_crit_mod_clks; + /* Power domain. */ + const struct rzg2l_cpg_pm_domain_init_data *pm_domains; + unsigned int num_pm_domains; + bool has_clk_mon_regs; }; From 5add5ebc4e35a703a49976abfd82e708d9aea4ad Mon Sep 17 00:00:00 2001 From: Claudiu Beznea Date: Mon, 22 Apr 2024 13:53:54 +0300 Subject: [PATCH 084/118] clk: renesas: r9a08g045: Add support for power domains Instantiate power domains for the currently enabled IPs of the R9A08G045 SoC. Signed-off-by: Claudiu Beznea Reviewed-by: Geert Uytterhoeven Reviewed-by: Ulf Hansson Link: https://lore.kernel.org/r/20240422105355.1622177-8-claudiu.beznea.uj@bp.renesas.com Signed-off-by: Geert Uytterhoeven --- drivers/clk/renesas/r9a08g045-cpg.c | 41 +++++++++++++++++++++++++++++ 1 file changed, 41 insertions(+) diff --git a/drivers/clk/renesas/r9a08g045-cpg.c b/drivers/clk/renesas/r9a08g045-cpg.c index c3e6da2de197..b068733b145f 100644 --- a/drivers/clk/renesas/r9a08g045-cpg.c +++ b/drivers/clk/renesas/r9a08g045-cpg.c @@ -240,6 +240,43 @@ static const unsigned int r9a08g045_crit_mod_clks[] __initconst = { MOD_CLK_BASE + R9A08G045_DMAC_ACLK, }; +static const struct rzg2l_cpg_pm_domain_init_data r9a08g045_pm_domains[] = { + /* Keep always-on domain on the first position for proper domains registration. */ + DEF_PD("always-on", R9A08G045_PD_ALWAYS_ON, + DEF_REG_CONF(0, 0), + RZG2L_PD_F_ALWAYS_ON), + DEF_PD("gic", R9A08G045_PD_GIC, + DEF_REG_CONF(CPG_BUS_ACPU_MSTOP, BIT(3)), + RZG2L_PD_F_ALWAYS_ON), + DEF_PD("ia55", R9A08G045_PD_IA55, + DEF_REG_CONF(CPG_BUS_PERI_CPU_MSTOP, BIT(13)), + RZG2L_PD_F_ALWAYS_ON), + DEF_PD("dmac", R9A08G045_PD_DMAC, + DEF_REG_CONF(CPG_BUS_REG1_MSTOP, GENMASK(3, 0)), + RZG2L_PD_F_ALWAYS_ON), + DEF_PD("wdt0", R9A08G045_PD_WDT0, + DEF_REG_CONF(CPG_BUS_REG0_MSTOP, BIT(0)), + RZG2L_PD_F_NONE), + DEF_PD("sdhi0", R9A08G045_PD_SDHI0, + DEF_REG_CONF(CPG_BUS_PERI_COM_MSTOP, BIT(0)), + RZG2L_PD_F_NONE), + DEF_PD("sdhi1", R9A08G045_PD_SDHI1, + DEF_REG_CONF(CPG_BUS_PERI_COM_MSTOP, BIT(1)), + RZG2L_PD_F_NONE), + DEF_PD("sdhi2", R9A08G045_PD_SDHI2, + DEF_REG_CONF(CPG_BUS_PERI_COM_MSTOP, BIT(11)), + RZG2L_PD_F_NONE), + DEF_PD("eth0", R9A08G045_PD_ETHER0, + DEF_REG_CONF(CPG_BUS_PERI_COM_MSTOP, BIT(2)), + RZG2L_PD_F_NONE), + DEF_PD("eth1", R9A08G045_PD_ETHER1, + DEF_REG_CONF(CPG_BUS_PERI_COM_MSTOP, BIT(3)), + RZG2L_PD_F_NONE), + DEF_PD("scif0", R9A08G045_PD_SCIF0, + DEF_REG_CONF(CPG_BUS_MCPU2_MSTOP, BIT(1)), + RZG2L_PD_F_NONE), +}; + const struct rzg2l_cpg_info r9a08g045_cpg_info = { /* Core Clocks */ .core_clks = r9a08g045_core_clks, @@ -260,5 +297,9 @@ const struct rzg2l_cpg_info r9a08g045_cpg_info = { .resets = r9a08g045_resets, .num_resets = R9A08G045_VBAT_BRESETN + 1, /* Last reset ID + 1 */ + /* Power domains */ + .pm_domains = r9a08g045_pm_domains, + .num_pm_domains = ARRAY_SIZE(r9a08g045_pm_domains), + .has_clk_mon_regs = true, }; From d06b1043644a1831ab141bbee2669002bba15b0f Mon Sep 17 00:00:00 2001 From: Christian Marangi Date: Wed, 20 Dec 2023 23:17:22 +0100 Subject: [PATCH 085/118] clk: qcom: clk-rcg: introduce support for multiple conf for same freq Some RCG frequency can be reached by multiple configuration. We currently declare multiple configuration for the same frequency but that is not supported and always the first configuration will be taken. These multiple configuration are needed as based on the current parent configuration, it may be needed to use a different configuration to reach the same frequency. To handle this introduce 3 new macro, C, FM and FMS: - C is used to declare a freq_conf where src, pre_div, m and n are provided. - FM is used to declare a freq_multi_tbl with the frequency and an array of confs to insert all the config for the provided frequency. - FMS is used to declare a freq_multi_tbl with the frequency and an array of a single conf with the provided src, pre_div, m and n. Struct clk_rcg2 is changed to add a union type to reference a simple freq_tbl or a complex freq_multi_tbl. Signed-off-by: Christian Marangi Acked-by: Stephen Boyd Link: https://lore.kernel.org/r/20231220221724.3822-2-ansuelsmth@gmail.com Signed-off-by: Bjorn Andersson --- drivers/clk/qcom/clk-rcg.h | 23 ++++++++++++++++++++++- 1 file changed, 22 insertions(+), 1 deletion(-) diff --git a/drivers/clk/qcom/clk-rcg.h b/drivers/clk/qcom/clk-rcg.h index e6d84c8c7989..c50e6616d02c 100644 --- a/drivers/clk/qcom/clk-rcg.h +++ b/drivers/clk/qcom/clk-rcg.h @@ -17,6 +17,23 @@ struct freq_tbl { u16 n; }; +#define C(s, h, m, n) { (s), (2 * (h) - 1), (m), (n) } +#define FM(f, confs) { (f), ARRAY_SIZE(confs), (confs) } +#define FMS(f, s, h, m, n) { (f), 1, (const struct freq_conf []){ C(s, h, m, n) } } + +struct freq_conf { + u8 src; + u8 pre_div; + u16 m; + u16 n; +}; + +struct freq_multi_tbl { + unsigned long freq; + size_t num_confs; + const struct freq_conf *confs; +}; + /** * struct mn - M/N:D counter * @mnctr_en_bit: bit to enable mn counter @@ -138,6 +155,7 @@ extern const struct clk_ops clk_dyn_rcg_ops; * @safe_src_index: safe src index value * @parent_map: map from software's parent index to hardware's src_sel field * @freq_tbl: frequency table + * @freq_multi_tbl: frequency table for clocks reachable with multiple RCGs conf * @clkr: regmap clock handle * @cfg_off: defines the cfg register offset from the CMD_RCGR + CFG_REG * @parked_cfg: cached value of the CFG register for parked RCGs @@ -149,7 +167,10 @@ struct clk_rcg2 { u8 hid_width; u8 safe_src_index; const struct parent_map *parent_map; - const struct freq_tbl *freq_tbl; + union { + const struct freq_tbl *freq_tbl; + const struct freq_multi_tbl *freq_multi_tbl; + }; struct clk_regmap clkr; u8 cfg_off; u32 parked_cfg; From 89da22456af0762477d8c1345fdd17961b3ada80 Mon Sep 17 00:00:00 2001 From: Christian Marangi Date: Wed, 20 Dec 2023 23:17:23 +0100 Subject: [PATCH 086/118] clk: qcom: clk-rcg2: add support for rcg2 freq multi ops Some RCG frequency can be reached by multiple configuration. Add clk_rcg2_fm_ops ops to support these special RCG configurations. These alternative ops will select the frequency using a CEIL policy. When the correct frequency is found, the correct config is selected by calculating the final rate (by checking the defined parent and values in the config that is being checked) and deciding based on the one that is less different than the requested one. These check are skipped if there is just one config for the requested freq. qcom_find_freq_multi is added to search the freq with the new struct freq_multi_tbl. __clk_rcg2_select_conf is used to select the correct conf by simulating the final clock. If a conf can't be found due to parent not reachable, a WARN is printed and -EINVAL is returned. Tested-by: Wei Lei Signed-off-by: Christian Marangi Acked-by: Stephen Boyd Link: https://lore.kernel.org/r/20231220221724.3822-3-ansuelsmth@gmail.com Signed-off-by: Bjorn Andersson --- drivers/clk/qcom/clk-rcg.h | 1 + drivers/clk/qcom/clk-rcg2.c | 166 ++++++++++++++++++++++++++++++++++++ drivers/clk/qcom/common.c | 18 ++++ drivers/clk/qcom/common.h | 2 + 4 files changed, 187 insertions(+) diff --git a/drivers/clk/qcom/clk-rcg.h b/drivers/clk/qcom/clk-rcg.h index c50e6616d02c..d7414361e432 100644 --- a/drivers/clk/qcom/clk-rcg.h +++ b/drivers/clk/qcom/clk-rcg.h @@ -190,6 +190,7 @@ struct clk_rcg2_gfx3d { extern const struct clk_ops clk_rcg2_ops; extern const struct clk_ops clk_rcg2_floor_ops; +extern const struct clk_ops clk_rcg2_fm_ops; extern const struct clk_ops clk_rcg2_mux_closest_ops; extern const struct clk_ops clk_edp_pixel_ops; extern const struct clk_ops clk_byte_ops; diff --git a/drivers/clk/qcom/clk-rcg2.c b/drivers/clk/qcom/clk-rcg2.c index 5183c74b074f..9b3aaa7f20ac 100644 --- a/drivers/clk/qcom/clk-rcg2.c +++ b/drivers/clk/qcom/clk-rcg2.c @@ -260,6 +260,115 @@ static int _freq_tbl_determine_rate(struct clk_hw *hw, const struct freq_tbl *f, return 0; } +static const struct freq_conf * +__clk_rcg2_select_conf(struct clk_hw *hw, const struct freq_multi_tbl *f, + unsigned long req_rate) +{ + unsigned long rate_diff, best_rate_diff = ULONG_MAX; + const struct freq_conf *conf, *best_conf = NULL; + struct clk_rcg2 *rcg = to_clk_rcg2(hw); + const char *name = clk_hw_get_name(hw); + unsigned long parent_rate, rate; + struct clk_hw *p; + int index, i; + + /* Exit early if only one config is defined */ + if (f->num_confs == 1) { + best_conf = f->confs; + goto exit; + } + + /* Search in each provided config the one that is near the wanted rate */ + for (i = 0, conf = f->confs; i < f->num_confs; i++, conf++) { + index = qcom_find_src_index(hw, rcg->parent_map, conf->src); + if (index < 0) + continue; + + p = clk_hw_get_parent_by_index(hw, index); + if (!p) + continue; + + parent_rate = clk_hw_get_rate(p); + rate = calc_rate(parent_rate, conf->n, conf->m, conf->n, conf->pre_div); + + if (rate == req_rate) { + best_conf = conf; + goto exit; + } + + rate_diff = abs_diff(req_rate, rate); + if (rate_diff < best_rate_diff) { + best_rate_diff = rate_diff; + best_conf = conf; + } + } + + /* + * Very unlikely. Warn if we couldn't find a correct config + * due to parent not found in every config. + */ + if (unlikely(!best_conf)) { + WARN(1, "%s: can't find a configuration for rate %lu\n", + name, req_rate); + return ERR_PTR(-EINVAL); + } + +exit: + return best_conf; +} + +static int _freq_tbl_fm_determine_rate(struct clk_hw *hw, const struct freq_multi_tbl *f, + struct clk_rate_request *req) +{ + unsigned long clk_flags, rate = req->rate; + struct clk_rcg2 *rcg = to_clk_rcg2(hw); + const struct freq_conf *conf; + struct clk_hw *p; + int index; + + f = qcom_find_freq_multi(f, rate); + if (!f || !f->confs) + return -EINVAL; + + conf = __clk_rcg2_select_conf(hw, f, rate); + if (IS_ERR(conf)) + return PTR_ERR(conf); + index = qcom_find_src_index(hw, rcg->parent_map, conf->src); + if (index < 0) + return index; + + clk_flags = clk_hw_get_flags(hw); + p = clk_hw_get_parent_by_index(hw, index); + if (!p) + return -EINVAL; + + if (clk_flags & CLK_SET_RATE_PARENT) { + rate = f->freq; + if (conf->pre_div) { + if (!rate) + rate = req->rate; + rate /= 2; + rate *= conf->pre_div + 1; + } + + if (conf->n) { + u64 tmp = rate; + + tmp = tmp * conf->n; + do_div(tmp, conf->m); + rate = tmp; + } + } else { + rate = clk_hw_get_rate(p); + } + + req->best_parent_hw = p; + req->best_parent_rate = rate; + req->rate = f->freq; + + return 0; +} + static int clk_rcg2_determine_rate(struct clk_hw *hw, struct clk_rate_request *req) { @@ -276,6 +385,14 @@ static int clk_rcg2_determine_floor_rate(struct clk_hw *hw, return _freq_tbl_determine_rate(hw, rcg->freq_tbl, req, FLOOR); } +static int clk_rcg2_fm_determine_rate(struct clk_hw *hw, + struct clk_rate_request *req) +{ + struct clk_rcg2 *rcg = to_clk_rcg2(hw); + + return _freq_tbl_fm_determine_rate(hw, rcg->freq_multi_tbl, req); +} + static int __clk_rcg2_configure(struct clk_rcg2 *rcg, const struct freq_tbl *f, u32 *_cfg) { @@ -371,6 +488,30 @@ static int __clk_rcg2_set_rate(struct clk_hw *hw, unsigned long rate, return clk_rcg2_configure(rcg, f); } +static int __clk_rcg2_fm_set_rate(struct clk_hw *hw, unsigned long rate) +{ + struct clk_rcg2 *rcg = to_clk_rcg2(hw); + const struct freq_multi_tbl *f; + const struct freq_conf *conf; + struct freq_tbl f_tbl = {}; + + f = qcom_find_freq_multi(rcg->freq_multi_tbl, rate); + if (!f || !f->confs) + return -EINVAL; + + conf = __clk_rcg2_select_conf(hw, f, rate); + if (IS_ERR(conf)) + return PTR_ERR(conf); + + f_tbl.freq = f->freq; + f_tbl.src = conf->src; + f_tbl.pre_div = conf->pre_div; + f_tbl.m = conf->m; + f_tbl.n = conf->n; + + return clk_rcg2_configure(rcg, &f_tbl); +} + static int clk_rcg2_set_rate(struct clk_hw *hw, unsigned long rate, unsigned long parent_rate) { @@ -383,6 +524,12 @@ static int clk_rcg2_set_floor_rate(struct clk_hw *hw, unsigned long rate, return __clk_rcg2_set_rate(hw, rate, FLOOR); } +static int clk_rcg2_fm_set_rate(struct clk_hw *hw, unsigned long rate, + unsigned long parent_rate) +{ + return __clk_rcg2_fm_set_rate(hw, rate); +} + static int clk_rcg2_set_rate_and_parent(struct clk_hw *hw, unsigned long rate, unsigned long parent_rate, u8 index) { @@ -395,6 +542,12 @@ static int clk_rcg2_set_floor_rate_and_parent(struct clk_hw *hw, return __clk_rcg2_set_rate(hw, rate, FLOOR); } +static int clk_rcg2_fm_set_rate_and_parent(struct clk_hw *hw, + unsigned long rate, unsigned long parent_rate, u8 index) +{ + return __clk_rcg2_fm_set_rate(hw, rate); +} + static int clk_rcg2_get_duty_cycle(struct clk_hw *hw, struct clk_duty *duty) { struct clk_rcg2 *rcg = to_clk_rcg2(hw); @@ -505,6 +658,19 @@ const struct clk_ops clk_rcg2_floor_ops = { }; EXPORT_SYMBOL_GPL(clk_rcg2_floor_ops); +const struct clk_ops clk_rcg2_fm_ops = { + .is_enabled = clk_rcg2_is_enabled, + .get_parent = clk_rcg2_get_parent, + .set_parent = clk_rcg2_set_parent, + .recalc_rate = clk_rcg2_recalc_rate, + .determine_rate = clk_rcg2_fm_determine_rate, + .set_rate = clk_rcg2_fm_set_rate, + .set_rate_and_parent = clk_rcg2_fm_set_rate_and_parent, + .get_duty_cycle = clk_rcg2_get_duty_cycle, + .set_duty_cycle = clk_rcg2_set_duty_cycle, +}; +EXPORT_SYMBOL_GPL(clk_rcg2_fm_ops); + const struct clk_ops clk_rcg2_mux_closest_ops = { .determine_rate = __clk_mux_determine_rate_closest, .get_parent = clk_rcg2_get_parent, diff --git a/drivers/clk/qcom/common.c b/drivers/clk/qcom/common.c index 75f09e6e057e..48f81e3a5e80 100644 --- a/drivers/clk/qcom/common.c +++ b/drivers/clk/qcom/common.c @@ -41,6 +41,24 @@ struct freq_tbl *qcom_find_freq(const struct freq_tbl *f, unsigned long rate) } EXPORT_SYMBOL_GPL(qcom_find_freq); +const struct freq_multi_tbl *qcom_find_freq_multi(const struct freq_multi_tbl *f, + unsigned long rate) +{ + if (!f) + return NULL; + + if (!f->freq) + return f; + + for (; f->freq; f++) + if (rate <= f->freq) + return f; + + /* Default to our fastest rate */ + return f - 1; +} +EXPORT_SYMBOL_GPL(qcom_find_freq_multi); + const struct freq_tbl *qcom_find_freq_floor(const struct freq_tbl *f, unsigned long rate) { diff --git a/drivers/clk/qcom/common.h b/drivers/clk/qcom/common.h index 9c8f7b798d9f..2d4a8a837e6c 100644 --- a/drivers/clk/qcom/common.h +++ b/drivers/clk/qcom/common.h @@ -45,6 +45,8 @@ extern const struct freq_tbl *qcom_find_freq(const struct freq_tbl *f, unsigned long rate); extern const struct freq_tbl *qcom_find_freq_floor(const struct freq_tbl *f, unsigned long rate); +extern const struct freq_multi_tbl *qcom_find_freq_multi(const struct freq_multi_tbl *f, + unsigned long rate); extern void qcom_pll_set_fsm_mode(struct regmap *m, u32 reg, u8 bias_count, u8 lock_count); extern int qcom_find_src_index(struct clk_hw *hw, const struct parent_map *map, From e88f03230dc07aa3293b6aeb078bd27370bb2594 Mon Sep 17 00:00:00 2001 From: Christian Marangi Date: Wed, 20 Dec 2023 23:17:24 +0100 Subject: [PATCH 087/118] clk: qcom: gcc-ipq8074: rework nss_port5/6 clock to multiple conf Rework nss_port5/6 to use the new multiple configuration implementation and correctly fix the clocks for these port under some corner case. This is particularly relevant for device that have 2.5G or 10G port connected to port5 or port 6 on ipq8074. As the parent are shared across multiple port it may be required to select the correct configuration to accomplish the desired clock. Without this patch such port doesn't work in some specific ethernet speed as the clock will be set to the wrong frequency as we just select the first configuration for the related frequency instead of selecting the best one. Signed-off-by: Christian Marangi Acked-by: Stephen Boyd Link: https://lore.kernel.org/r/20231220221724.3822-4-ansuelsmth@gmail.com Signed-off-by: Bjorn Andersson --- drivers/clk/qcom/gcc-ipq8074.c | 120 +++++++++++++++++++++------------ 1 file changed, 76 insertions(+), 44 deletions(-) diff --git a/drivers/clk/qcom/gcc-ipq8074.c b/drivers/clk/qcom/gcc-ipq8074.c index 7bc679871f32..d2be56c5892d 100644 --- a/drivers/clk/qcom/gcc-ipq8074.c +++ b/drivers/clk/qcom/gcc-ipq8074.c @@ -1677,15 +1677,23 @@ static struct clk_regmap_div nss_port4_tx_div_clk_src = { }, }; -static const struct freq_tbl ftbl_nss_port5_rx_clk_src[] = { - F(19200000, P_XO, 1, 0, 0), - F(25000000, P_UNIPHY1_RX, 12.5, 0, 0), - F(25000000, P_UNIPHY0_RX, 5, 0, 0), - F(78125000, P_UNIPHY1_RX, 4, 0, 0), - F(125000000, P_UNIPHY1_RX, 2.5, 0, 0), - F(125000000, P_UNIPHY0_RX, 1, 0, 0), - F(156250000, P_UNIPHY1_RX, 2, 0, 0), - F(312500000, P_UNIPHY1_RX, 1, 0, 0), +static const struct freq_conf ftbl_nss_port5_rx_clk_src_25[] = { + C(P_UNIPHY1_RX, 12.5, 0, 0), + C(P_UNIPHY0_RX, 5, 0, 0), +}; + +static const struct freq_conf ftbl_nss_port5_rx_clk_src_125[] = { + C(P_UNIPHY1_RX, 2.5, 0, 0), + C(P_UNIPHY0_RX, 1, 0, 0), +}; + +static const struct freq_multi_tbl ftbl_nss_port5_rx_clk_src[] = { + FMS(19200000, P_XO, 1, 0, 0), + FM(25000000, ftbl_nss_port5_rx_clk_src_25), + FMS(78125000, P_UNIPHY1_RX, 4, 0, 0), + FM(125000000, ftbl_nss_port5_rx_clk_src_125), + FMS(156250000, P_UNIPHY1_RX, 2, 0, 0), + FMS(312500000, P_UNIPHY1_RX, 1, 0, 0), { } }; @@ -1712,14 +1720,14 @@ gcc_xo_uniphy0_rx_tx_uniphy1_rx_tx_ubi32_bias_map[] = { static struct clk_rcg2 nss_port5_rx_clk_src = { .cmd_rcgr = 0x68060, - .freq_tbl = ftbl_nss_port5_rx_clk_src, + .freq_multi_tbl = ftbl_nss_port5_rx_clk_src, .hid_width = 5, .parent_map = gcc_xo_uniphy0_rx_tx_uniphy1_rx_tx_ubi32_bias_map, .clkr.hw.init = &(struct clk_init_data){ .name = "nss_port5_rx_clk_src", .parent_data = gcc_xo_uniphy0_rx_tx_uniphy1_rx_tx_ubi32_bias, .num_parents = ARRAY_SIZE(gcc_xo_uniphy0_rx_tx_uniphy1_rx_tx_ubi32_bias), - .ops = &clk_rcg2_ops, + .ops = &clk_rcg2_fm_ops, }, }; @@ -1739,15 +1747,23 @@ static struct clk_regmap_div nss_port5_rx_div_clk_src = { }, }; -static const struct freq_tbl ftbl_nss_port5_tx_clk_src[] = { - F(19200000, P_XO, 1, 0, 0), - F(25000000, P_UNIPHY1_TX, 12.5, 0, 0), - F(25000000, P_UNIPHY0_TX, 5, 0, 0), - F(78125000, P_UNIPHY1_TX, 4, 0, 0), - F(125000000, P_UNIPHY1_TX, 2.5, 0, 0), - F(125000000, P_UNIPHY0_TX, 1, 0, 0), - F(156250000, P_UNIPHY1_TX, 2, 0, 0), - F(312500000, P_UNIPHY1_TX, 1, 0, 0), +static const struct freq_conf ftbl_nss_port5_tx_clk_src_25[] = { + C(P_UNIPHY1_TX, 12.5, 0, 0), + C(P_UNIPHY0_TX, 5, 0, 0), +}; + +static const struct freq_conf ftbl_nss_port5_tx_clk_src_125[] = { + C(P_UNIPHY1_TX, 2.5, 0, 0), + C(P_UNIPHY0_TX, 1, 0, 0), +}; + +static const struct freq_multi_tbl ftbl_nss_port5_tx_clk_src[] = { + FMS(19200000, P_XO, 1, 0, 0), + FM(25000000, ftbl_nss_port5_tx_clk_src_25), + FMS(78125000, P_UNIPHY1_TX, 4, 0, 0), + FM(125000000, ftbl_nss_port5_tx_clk_src_125), + FMS(156250000, P_UNIPHY1_TX, 2, 0, 0), + FMS(312500000, P_UNIPHY1_TX, 1, 0, 0), { } }; @@ -1774,14 +1790,14 @@ gcc_xo_uniphy0_tx_rx_uniphy1_tx_rx_ubi32_bias_map[] = { static struct clk_rcg2 nss_port5_tx_clk_src = { .cmd_rcgr = 0x68068, - .freq_tbl = ftbl_nss_port5_tx_clk_src, + .freq_multi_tbl = ftbl_nss_port5_tx_clk_src, .hid_width = 5, .parent_map = gcc_xo_uniphy0_tx_rx_uniphy1_tx_rx_ubi32_bias_map, .clkr.hw.init = &(struct clk_init_data){ .name = "nss_port5_tx_clk_src", .parent_data = gcc_xo_uniphy0_tx_rx_uniphy1_tx_rx_ubi32_bias, .num_parents = ARRAY_SIZE(gcc_xo_uniphy0_tx_rx_uniphy1_tx_rx_ubi32_bias), - .ops = &clk_rcg2_ops, + .ops = &clk_rcg2_fm_ops, }, }; @@ -1801,15 +1817,23 @@ static struct clk_regmap_div nss_port5_tx_div_clk_src = { }, }; -static const struct freq_tbl ftbl_nss_port6_rx_clk_src[] = { - F(19200000, P_XO, 1, 0, 0), - F(25000000, P_UNIPHY2_RX, 5, 0, 0), - F(25000000, P_UNIPHY2_RX, 12.5, 0, 0), - F(78125000, P_UNIPHY2_RX, 4, 0, 0), - F(125000000, P_UNIPHY2_RX, 1, 0, 0), - F(125000000, P_UNIPHY2_RX, 2.5, 0, 0), - F(156250000, P_UNIPHY2_RX, 2, 0, 0), - F(312500000, P_UNIPHY2_RX, 1, 0, 0), +static const struct freq_conf ftbl_nss_port6_rx_clk_src_25[] = { + C(P_UNIPHY2_RX, 5, 0, 0), + C(P_UNIPHY2_RX, 12.5, 0, 0), +}; + +static const struct freq_conf ftbl_nss_port6_rx_clk_src_125[] = { + C(P_UNIPHY2_RX, 1, 0, 0), + C(P_UNIPHY2_RX, 2.5, 0, 0), +}; + +static const struct freq_multi_tbl ftbl_nss_port6_rx_clk_src[] = { + FMS(19200000, P_XO, 1, 0, 0), + FM(25000000, ftbl_nss_port6_rx_clk_src_25), + FMS(78125000, P_UNIPHY2_RX, 4, 0, 0), + FM(125000000, ftbl_nss_port6_rx_clk_src_125), + FMS(156250000, P_UNIPHY2_RX, 2, 0, 0), + FMS(312500000, P_UNIPHY2_RX, 1, 0, 0), { } }; @@ -1831,14 +1855,14 @@ static const struct parent_map gcc_xo_uniphy2_rx_tx_ubi32_bias_map[] = { static struct clk_rcg2 nss_port6_rx_clk_src = { .cmd_rcgr = 0x68070, - .freq_tbl = ftbl_nss_port6_rx_clk_src, + .freq_multi_tbl = ftbl_nss_port6_rx_clk_src, .hid_width = 5, .parent_map = gcc_xo_uniphy2_rx_tx_ubi32_bias_map, .clkr.hw.init = &(struct clk_init_data){ .name = "nss_port6_rx_clk_src", .parent_data = gcc_xo_uniphy2_rx_tx_ubi32_bias, .num_parents = ARRAY_SIZE(gcc_xo_uniphy2_rx_tx_ubi32_bias), - .ops = &clk_rcg2_ops, + .ops = &clk_rcg2_fm_ops, }, }; @@ -1858,15 +1882,23 @@ static struct clk_regmap_div nss_port6_rx_div_clk_src = { }, }; -static const struct freq_tbl ftbl_nss_port6_tx_clk_src[] = { - F(19200000, P_XO, 1, 0, 0), - F(25000000, P_UNIPHY2_TX, 5, 0, 0), - F(25000000, P_UNIPHY2_TX, 12.5, 0, 0), - F(78125000, P_UNIPHY2_TX, 4, 0, 0), - F(125000000, P_UNIPHY2_TX, 1, 0, 0), - F(125000000, P_UNIPHY2_TX, 2.5, 0, 0), - F(156250000, P_UNIPHY2_TX, 2, 0, 0), - F(312500000, P_UNIPHY2_TX, 1, 0, 0), +static const struct freq_conf ftbl_nss_port6_tx_clk_src_25[] = { + C(P_UNIPHY2_TX, 5, 0, 0), + C(P_UNIPHY2_TX, 12.5, 0, 0), +}; + +static const struct freq_conf ftbl_nss_port6_tx_clk_src_125[] = { + C(P_UNIPHY2_TX, 1, 0, 0), + C(P_UNIPHY2_TX, 2.5, 0, 0), +}; + +static const struct freq_multi_tbl ftbl_nss_port6_tx_clk_src[] = { + FMS(19200000, P_XO, 1, 0, 0), + FM(25000000, ftbl_nss_port6_tx_clk_src_25), + FMS(78125000, P_UNIPHY1_RX, 4, 0, 0), + FM(125000000, ftbl_nss_port6_tx_clk_src_125), + FMS(156250000, P_UNIPHY1_RX, 2, 0, 0), + FMS(312500000, P_UNIPHY1_RX, 1, 0, 0), { } }; @@ -1888,14 +1920,14 @@ static const struct parent_map gcc_xo_uniphy2_tx_rx_ubi32_bias_map[] = { static struct clk_rcg2 nss_port6_tx_clk_src = { .cmd_rcgr = 0x68078, - .freq_tbl = ftbl_nss_port6_tx_clk_src, + .freq_multi_tbl = ftbl_nss_port6_tx_clk_src, .hid_width = 5, .parent_map = gcc_xo_uniphy2_tx_rx_ubi32_bias_map, .clkr.hw.init = &(struct clk_init_data){ .name = "nss_port6_tx_clk_src", .parent_data = gcc_xo_uniphy2_tx_rx_ubi32_bias, .num_parents = ARRAY_SIZE(gcc_xo_uniphy2_tx_rx_ubi32_bias), - .ops = &clk_rcg2_ops, + .ops = &clk_rcg2_fm_ops, }, }; From 5fce38e2a1a97900989d9fedebcf5a4dacdaee30 Mon Sep 17 00:00:00 2001 From: Gabor Juhos Date: Fri, 15 Mar 2024 17:16:41 +0100 Subject: [PATCH 088/118] clk: qcom: apss-ipq-pll: use stromer ops for IPQ5018 to fix boot failure Booting v6.8 results in a hang on various IPQ5018 based boards. Investigating the problem showed that the hang happens when the clk_alpha_pll_stromer_plus_set_rate() function tries to write into the PLL_MODE register of the APSS PLL. Checking the downstream code revealed that it uses [1] stromer specific operations for IPQ5018, whereas in the current code the stromer plus specific operations are used. The ops in the 'ipq_pll_stromer_plus' clock definition can't be changed since that is needed for IPQ5332, so add a new alpha pll clock declaration which uses the correct stromer ops and use this new clock for IPQ5018 to avoid the boot failure. Also, change pll_type in 'ipq5018_pll_data' to CLK_ALPHA_PLL_TYPE_STROMER to better reflect that it is a Stromer PLL and change the apss_ipq_pll_probe() function accordingly. 1. https://git.codelinaro.org/clo/qsdk/oss/kernel/linux-ipq-5.4/-/blob/NHSS.QSDK.12.4/drivers/clk/qcom/apss-ipq5018.c#L67 Cc: stable@vger.kernel.org Fixes: 50492f929486 ("clk: qcom: apss-ipq-pll: add support for IPQ5018") Signed-off-by: Gabor Juhos Tested-by: Kathiravan Thirumoorthy Reviewed-by: Kathiravan Thirumoorthy Link: https://lore.kernel.org/r/20240315-apss-ipq-pll-ipq5018-hang-v2-1-6fe30ada2009@gmail.com Signed-off-by: Bjorn Andersson --- drivers/clk/qcom/apss-ipq-pll.c | 30 +++++++++++++++++++++++++++--- 1 file changed, 27 insertions(+), 3 deletions(-) diff --git a/drivers/clk/qcom/apss-ipq-pll.c b/drivers/clk/qcom/apss-ipq-pll.c index 678b805f13d4..dfffec2f06ae 100644 --- a/drivers/clk/qcom/apss-ipq-pll.c +++ b/drivers/clk/qcom/apss-ipq-pll.c @@ -55,6 +55,29 @@ static struct clk_alpha_pll ipq_pll_huayra = { }, }; +static struct clk_alpha_pll ipq_pll_stromer = { + .offset = 0x0, + /* + * Reuse CLK_ALPHA_PLL_TYPE_STROMER_PLUS register offsets. + * Although this is a bit confusing, but the offset values + * are correct nevertheless. + */ + .regs = ipq_pll_offsets[CLK_ALPHA_PLL_TYPE_STROMER_PLUS], + .flags = SUPPORTS_DYNAMIC_UPDATE, + .clkr = { + .enable_reg = 0x0, + .enable_mask = BIT(0), + .hw.init = &(const struct clk_init_data) { + .name = "a53pll", + .parent_data = &(const struct clk_parent_data) { + .fw_name = "xo", + }, + .num_parents = 1, + .ops = &clk_alpha_pll_stromer_ops, + }, + }, +}; + static struct clk_alpha_pll ipq_pll_stromer_plus = { .offset = 0x0, .regs = ipq_pll_offsets[CLK_ALPHA_PLL_TYPE_STROMER_PLUS], @@ -144,8 +167,8 @@ struct apss_pll_data { }; static const struct apss_pll_data ipq5018_pll_data = { - .pll_type = CLK_ALPHA_PLL_TYPE_STROMER_PLUS, - .pll = &ipq_pll_stromer_plus, + .pll_type = CLK_ALPHA_PLL_TYPE_STROMER, + .pll = &ipq_pll_stromer, .pll_config = &ipq5018_pll_config, }; @@ -203,7 +226,8 @@ static int apss_ipq_pll_probe(struct platform_device *pdev) if (data->pll_type == CLK_ALPHA_PLL_TYPE_HUAYRA) clk_alpha_pll_configure(data->pll, regmap, data->pll_config); - else if (data->pll_type == CLK_ALPHA_PLL_TYPE_STROMER_PLUS) + else if (data->pll_type == CLK_ALPHA_PLL_TYPE_STROMER || + data->pll_type == CLK_ALPHA_PLL_TYPE_STROMER_PLUS) clk_stromer_pll_configure(data->pll, regmap, data->pll_config); ret = devm_clk_register_regmap(dev, &data->pll->clkr); From ac3ee364a7312517edf71b1857c0f272919f2374 Mon Sep 17 00:00:00 2001 From: Gabor Juhos Date: Thu, 28 Mar 2024 10:23:10 +0100 Subject: [PATCH 089/118] clk: qcom: apss-ipq-pll: reuse Stromer reg offsets from 'clk_alpha_pll_regs' The register offset array defined locally for the CLK_ALPHA_PLL_TYPE_STROMER_PLUS is the same as the entry defined for CLK_ALPHA_PLL_TYPE_STROMER in the 'clk_alpha_pll_regs' array. To avoid code duplication, remove the local definition and use the global one instead. No functional changes. Reviewed-by: Dmitry Baryshkov Reviewed-by: Konrad Dybcio Signed-off-by: Gabor Juhos Link: https://lore.kernel.org/r/20240328-apss-ipq-pll-cleanup-v4-1-eddbf617f0c8@gmail.com Signed-off-by: Bjorn Andersson --- drivers/clk/qcom/apss-ipq-pll.c | 24 ++++++------------------ 1 file changed, 6 insertions(+), 18 deletions(-) diff --git a/drivers/clk/qcom/apss-ipq-pll.c b/drivers/clk/qcom/apss-ipq-pll.c index dfffec2f06ae..ed3e6405f99c 100644 --- a/drivers/clk/qcom/apss-ipq-pll.c +++ b/drivers/clk/qcom/apss-ipq-pll.c @@ -24,17 +24,6 @@ static const u8 ipq_pll_offsets[][PLL_OFF_MAX_REGS] = { [PLL_OFF_TEST_CTL] = 0x30, [PLL_OFF_TEST_CTL_U] = 0x34, }, - [CLK_ALPHA_PLL_TYPE_STROMER_PLUS] = { - [PLL_OFF_L_VAL] = 0x08, - [PLL_OFF_ALPHA_VAL] = 0x10, - [PLL_OFF_ALPHA_VAL_U] = 0x14, - [PLL_OFF_USER_CTL] = 0x18, - [PLL_OFF_USER_CTL_U] = 0x1c, - [PLL_OFF_CONFIG_CTL] = 0x20, - [PLL_OFF_STATUS] = 0x28, - [PLL_OFF_TEST_CTL] = 0x30, - [PLL_OFF_TEST_CTL_U] = 0x34, - }, }; static struct clk_alpha_pll ipq_pll_huayra = { @@ -57,12 +46,7 @@ static struct clk_alpha_pll ipq_pll_huayra = { static struct clk_alpha_pll ipq_pll_stromer = { .offset = 0x0, - /* - * Reuse CLK_ALPHA_PLL_TYPE_STROMER_PLUS register offsets. - * Although this is a bit confusing, but the offset values - * are correct nevertheless. - */ - .regs = ipq_pll_offsets[CLK_ALPHA_PLL_TYPE_STROMER_PLUS], + .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_STROMER], .flags = SUPPORTS_DYNAMIC_UPDATE, .clkr = { .enable_reg = 0x0, @@ -80,7 +64,11 @@ static struct clk_alpha_pll ipq_pll_stromer = { static struct clk_alpha_pll ipq_pll_stromer_plus = { .offset = 0x0, - .regs = ipq_pll_offsets[CLK_ALPHA_PLL_TYPE_STROMER_PLUS], + /* + * The register offsets of the Stromer Plus PLL used in IPQ5332 + * are the same as the Stromer PLL's offsets. + */ + .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_STROMER], .flags = SUPPORTS_DYNAMIC_UPDATE, .clkr = { .enable_reg = 0x0, From 35a99c6ffa1e9bd8d31ddd3098e6fad7ba884928 Mon Sep 17 00:00:00 2001 From: Gabor Juhos Date: Thu, 28 Mar 2024 10:23:11 +0100 Subject: [PATCH 090/118] clk: qcom: apss-ipq-pll: move Huayra register map to 'clk_alpha_pll_regs' Move the locally defined Huayra register map to 'clk_alpha_pll_regs' in order to allow using that by other drivers, like the clk-cbf-8996. No functional changes. Reviewed-by: Dmitry Baryshkov Reviewed-by: Konrad Dybcio Signed-off-by: Gabor Juhos Link: https://lore.kernel.org/r/20240328-apss-ipq-pll-cleanup-v4-2-eddbf617f0c8@gmail.com Signed-off-by: Bjorn Andersson --- drivers/clk/qcom/apss-ipq-pll.c | 20 +------------------- drivers/clk/qcom/clk-alpha-pll.c | 10 ++++++++++ drivers/clk/qcom/clk-alpha-pll.h | 1 + 3 files changed, 12 insertions(+), 19 deletions(-) diff --git a/drivers/clk/qcom/apss-ipq-pll.c b/drivers/clk/qcom/apss-ipq-pll.c index ed3e6405f99c..8cf17374a2e2 100644 --- a/drivers/clk/qcom/apss-ipq-pll.c +++ b/drivers/clk/qcom/apss-ipq-pll.c @@ -8,27 +8,9 @@ #include "clk-alpha-pll.h" -/* - * Even though APSS PLL type is of existing one (like Huayra), its offsets - * are different from the one mentioned in the clk-alpha-pll.c, since the - * PLL is specific to APSS, so lets the define the same. - */ -static const u8 ipq_pll_offsets[][PLL_OFF_MAX_REGS] = { - [CLK_ALPHA_PLL_TYPE_HUAYRA] = { - [PLL_OFF_L_VAL] = 0x08, - [PLL_OFF_ALPHA_VAL] = 0x10, - [PLL_OFF_USER_CTL] = 0x18, - [PLL_OFF_CONFIG_CTL] = 0x20, - [PLL_OFF_CONFIG_CTL_U] = 0x24, - [PLL_OFF_STATUS] = 0x28, - [PLL_OFF_TEST_CTL] = 0x30, - [PLL_OFF_TEST_CTL_U] = 0x34, - }, -}; - static struct clk_alpha_pll ipq_pll_huayra = { .offset = 0x0, - .regs = ipq_pll_offsets[CLK_ALPHA_PLL_TYPE_HUAYRA], + .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_HUAYRA_APSS], .flags = SUPPORTS_DYNAMIC_UPDATE, .clkr = { .enable_reg = 0x0, diff --git a/drivers/clk/qcom/clk-alpha-pll.c b/drivers/clk/qcom/clk-alpha-pll.c index 7f0ed5bd51e3..236794cb3e50 100644 --- a/drivers/clk/qcom/clk-alpha-pll.c +++ b/drivers/clk/qcom/clk-alpha-pll.c @@ -83,6 +83,16 @@ const u8 clk_alpha_pll_regs[][PLL_OFF_MAX_REGS] = { [PLL_OFF_TEST_CTL_U] = 0x20, [PLL_OFF_STATUS] = 0x24, }, + [CLK_ALPHA_PLL_TYPE_HUAYRA_APSS] = { + [PLL_OFF_L_VAL] = 0x08, + [PLL_OFF_ALPHA_VAL] = 0x10, + [PLL_OFF_USER_CTL] = 0x18, + [PLL_OFF_CONFIG_CTL] = 0x20, + [PLL_OFF_CONFIG_CTL_U] = 0x24, + [PLL_OFF_STATUS] = 0x28, + [PLL_OFF_TEST_CTL] = 0x30, + [PLL_OFF_TEST_CTL_U] = 0x34, + }, [CLK_ALPHA_PLL_TYPE_BRAMMO] = { [PLL_OFF_L_VAL] = 0x04, [PLL_OFF_ALPHA_VAL] = 0x08, diff --git a/drivers/clk/qcom/clk-alpha-pll.h b/drivers/clk/qcom/clk-alpha-pll.h index 1bb2d031dc9f..c7055b6c42f1 100644 --- a/drivers/clk/qcom/clk-alpha-pll.h +++ b/drivers/clk/qcom/clk-alpha-pll.h @@ -15,6 +15,7 @@ enum { CLK_ALPHA_PLL_TYPE_DEFAULT, CLK_ALPHA_PLL_TYPE_HUAYRA, + CLK_ALPHA_PLL_TYPE_HUAYRA_APSS, CLK_ALPHA_PLL_TYPE_BRAMMO, CLK_ALPHA_PLL_TYPE_FABIA, CLK_ALPHA_PLL_TYPE_TRION, From 07570342d305d90c1c5dba6d336fb4c8301aef45 Mon Sep 17 00:00:00 2001 From: Gabor Juhos Date: Thu, 28 Mar 2024 10:23:12 +0100 Subject: [PATCH 091/118] clk: qcom: apss-ipq-pll: constify match data structures The match data structures are used only by the apss_ipq_pll_probe() function and are never modified so mark those as constant. No functional changes. Reviewed-by: Dmitry Baryshkov Reviewed-by: Konrad Dybcio Signed-off-by: Gabor Juhos Link: https://lore.kernel.org/r/20240328-apss-ipq-pll-cleanup-v4-3-eddbf617f0c8@gmail.com Signed-off-by: Bjorn Andersson --- drivers/clk/qcom/apss-ipq-pll.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/clk/qcom/apss-ipq-pll.c b/drivers/clk/qcom/apss-ipq-pll.c index 8cf17374a2e2..191b87df51bb 100644 --- a/drivers/clk/qcom/apss-ipq-pll.c +++ b/drivers/clk/qcom/apss-ipq-pll.c @@ -142,25 +142,25 @@ static const struct apss_pll_data ipq5018_pll_data = { .pll_config = &ipq5018_pll_config, }; -static struct apss_pll_data ipq5332_pll_data = { +static const struct apss_pll_data ipq5332_pll_data = { .pll_type = CLK_ALPHA_PLL_TYPE_STROMER_PLUS, .pll = &ipq_pll_stromer_plus, .pll_config = &ipq5332_pll_config, }; -static struct apss_pll_data ipq8074_pll_data = { +static const struct apss_pll_data ipq8074_pll_data = { .pll_type = CLK_ALPHA_PLL_TYPE_HUAYRA, .pll = &ipq_pll_huayra, .pll_config = &ipq8074_pll_config, }; -static struct apss_pll_data ipq6018_pll_data = { +static const struct apss_pll_data ipq6018_pll_data = { .pll_type = CLK_ALPHA_PLL_TYPE_HUAYRA, .pll = &ipq_pll_huayra, .pll_config = &ipq6018_pll_config, }; -static struct apss_pll_data ipq9574_pll_data = { +static const struct apss_pll_data ipq9574_pll_data = { .pll_type = CLK_ALPHA_PLL_TYPE_HUAYRA, .pll = &ipq_pll_huayra, .pll_config = &ipq9574_pll_config, From 4a941e436432104ce5ed75bf8c5ba2c8463b089c Mon Sep 17 00:00:00 2001 From: Gabor Juhos Date: Thu, 28 Mar 2024 10:23:13 +0100 Subject: [PATCH 092/118] clk: qcom: apss-ipq-pll: constify clk_init_data structures The clk_init_data structures are never modified, so add const qualifier to the ones where it is missing. No functional changes. Reviewed-by: Dmitry Baryshkov Reviewed-by: Konrad Dybcio Signed-off-by: Gabor Juhos Link: https://lore.kernel.org/r/20240328-apss-ipq-pll-cleanup-v4-4-eddbf617f0c8@gmail.com Signed-off-by: Bjorn Andersson --- drivers/clk/qcom/apss-ipq-pll.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/clk/qcom/apss-ipq-pll.c b/drivers/clk/qcom/apss-ipq-pll.c index 191b87df51bb..1a6f4db25379 100644 --- a/drivers/clk/qcom/apss-ipq-pll.c +++ b/drivers/clk/qcom/apss-ipq-pll.c @@ -15,7 +15,7 @@ static struct clk_alpha_pll ipq_pll_huayra = { .clkr = { .enable_reg = 0x0, .enable_mask = BIT(0), - .hw.init = &(struct clk_init_data){ + .hw.init = &(const struct clk_init_data) { .name = "a53pll", .parent_data = &(const struct clk_parent_data) { .fw_name = "xo", @@ -55,7 +55,7 @@ static struct clk_alpha_pll ipq_pll_stromer_plus = { .clkr = { .enable_reg = 0x0, .enable_mask = BIT(0), - .hw.init = &(struct clk_init_data){ + .hw.init = &(const struct clk_init_data) { .name = "a53pll", .parent_data = &(const struct clk_parent_data) { .fw_name = "xo", From f3574392290d37647821d40f89136177b28e5f34 Mon Sep 17 00:00:00 2001 From: Gabor Juhos Date: Thu, 28 Mar 2024 10:23:14 +0100 Subject: [PATCH 093/118] clk: qcom: clk-cbf-8996: use HUAYRA_APSS register map for cbf_pll The register map used for 'cbf_pll' is the same as the one defined for the CLK_ALPHA_PLL_TYPE_HUAYRA_APSS indice in the 'clk_alpha_pll_regs' array. Drop the local register map and use the global one instead to reduce code duplication. No functional changes intended. Compile tested only. Suggested-by: Dmitry Baryshkov Reviewed-by: Dmitry Baryshkov Reviewed-by: Konrad Dybcio Signed-off-by: Gabor Juhos Link: https://lore.kernel.org/r/20240328-apss-ipq-pll-cleanup-v4-5-eddbf617f0c8@gmail.com Signed-off-by: Bjorn Andersson --- drivers/clk/qcom/clk-cbf-8996.c | 13 +------------ 1 file changed, 1 insertion(+), 12 deletions(-) diff --git a/drivers/clk/qcom/clk-cbf-8996.c b/drivers/clk/qcom/clk-cbf-8996.c index fe24b4abeab4..76bf523431b8 100644 --- a/drivers/clk/qcom/clk-cbf-8996.c +++ b/drivers/clk/qcom/clk-cbf-8996.c @@ -41,17 +41,6 @@ enum { #define CBF_PLL_OFFSET 0xf000 -static const u8 cbf_pll_regs[PLL_OFF_MAX_REGS] = { - [PLL_OFF_L_VAL] = 0x08, - [PLL_OFF_ALPHA_VAL] = 0x10, - [PLL_OFF_USER_CTL] = 0x18, - [PLL_OFF_CONFIG_CTL] = 0x20, - [PLL_OFF_CONFIG_CTL_U] = 0x24, - [PLL_OFF_TEST_CTL] = 0x30, - [PLL_OFF_TEST_CTL_U] = 0x34, - [PLL_OFF_STATUS] = 0x28, -}; - static struct alpha_pll_config cbfpll_config = { .l = 72, .config_ctl_val = 0x200d4828, @@ -67,7 +56,7 @@ static struct alpha_pll_config cbfpll_config = { static struct clk_alpha_pll cbf_pll = { .offset = CBF_PLL_OFFSET, - .regs = cbf_pll_regs, + .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_HUAYRA_APSS], .flags = SUPPORTS_DYNAMIC_UPDATE | SUPPORTS_FSM_MODE, .clkr.hw.init = &(struct clk_init_data){ .name = "cbf_pll", From e801038a02ce1e8c652a0b668dd233a4ee48aeb7 Mon Sep 17 00:00:00 2001 From: Dmitry Baryshkov Date: Wed, 24 Apr 2024 04:39:29 +0300 Subject: [PATCH 094/118] clk: qcom: dispcc-sm8450: fix DisplayPort clocks On SM8450 DisplayPort link clocks use frequency tables inherited from the vendor kernel, it is not applicable in the upstream kernel. Drop frequency tables and use clk_byte2_ops for those clocks. This fixes frequency selection in the OPP core (which otherwise attempts to use invalid 810 KHz as DP link rate), also fixing the following message: msm-dp-display ae90000.displayport-controller: _opp_config_clk_single: failed to set clock rate: -22 Fixes: 16fb89f92ec4 ("clk: qcom: Add support for Display Clock Controller on SM8450") Reviewed-by: Neil Armstrong Reviewed-by: Konrad Dybcio Signed-off-by: Dmitry Baryshkov Link: https://lore.kernel.org/r/20240424-dispcc-dp-clocks-v2-1-b44038f3fa96@linaro.org Signed-off-by: Bjorn Andersson --- drivers/clk/qcom/dispcc-sm8450.c | 20 ++++---------------- 1 file changed, 4 insertions(+), 16 deletions(-) diff --git a/drivers/clk/qcom/dispcc-sm8450.c b/drivers/clk/qcom/dispcc-sm8450.c index 92e9c4e7b13d..49bb4f58c391 100644 --- a/drivers/clk/qcom/dispcc-sm8450.c +++ b/drivers/clk/qcom/dispcc-sm8450.c @@ -309,26 +309,17 @@ static struct clk_rcg2 disp_cc_mdss_dptx0_aux_clk_src = { }, }; -static const struct freq_tbl ftbl_disp_cc_mdss_dptx0_link_clk_src[] = { - F(162000, P_DP0_PHY_PLL_LINK_CLK, 1, 0, 0), - F(270000, P_DP0_PHY_PLL_LINK_CLK, 1, 0, 0), - F(540000, P_DP0_PHY_PLL_LINK_CLK, 1, 0, 0), - F(810000, P_DP0_PHY_PLL_LINK_CLK, 1, 0, 0), - { } -}; - static struct clk_rcg2 disp_cc_mdss_dptx0_link_clk_src = { .cmd_rcgr = 0x819c, .mnd_width = 0, .hid_width = 5, .parent_map = disp_cc_parent_map_3, - .freq_tbl = ftbl_disp_cc_mdss_dptx0_link_clk_src, .clkr.hw.init = &(struct clk_init_data) { .name = "disp_cc_mdss_dptx0_link_clk_src", .parent_data = disp_cc_parent_data_3, .num_parents = ARRAY_SIZE(disp_cc_parent_data_3), .flags = CLK_SET_RATE_PARENT, - .ops = &clk_rcg2_ops, + .ops = &clk_byte2_ops, }, }; @@ -382,13 +373,12 @@ static struct clk_rcg2 disp_cc_mdss_dptx1_link_clk_src = { .mnd_width = 0, .hid_width = 5, .parent_map = disp_cc_parent_map_3, - .freq_tbl = ftbl_disp_cc_mdss_dptx0_link_clk_src, .clkr.hw.init = &(struct clk_init_data) { .name = "disp_cc_mdss_dptx1_link_clk_src", .parent_data = disp_cc_parent_data_3, .num_parents = ARRAY_SIZE(disp_cc_parent_data_3), .flags = CLK_SET_RATE_PARENT, - .ops = &clk_rcg2_ops, + .ops = &clk_byte2_ops, }, }; @@ -442,13 +432,12 @@ static struct clk_rcg2 disp_cc_mdss_dptx2_link_clk_src = { .mnd_width = 0, .hid_width = 5, .parent_map = disp_cc_parent_map_3, - .freq_tbl = ftbl_disp_cc_mdss_dptx0_link_clk_src, .clkr.hw.init = &(struct clk_init_data) { .name = "disp_cc_mdss_dptx2_link_clk_src", .parent_data = disp_cc_parent_data_3, .num_parents = ARRAY_SIZE(disp_cc_parent_data_3), .flags = CLK_SET_RATE_PARENT, - .ops = &clk_rcg2_ops, + .ops = &clk_byte2_ops, }, }; @@ -502,13 +491,12 @@ static struct clk_rcg2 disp_cc_mdss_dptx3_link_clk_src = { .mnd_width = 0, .hid_width = 5, .parent_map = disp_cc_parent_map_3, - .freq_tbl = ftbl_disp_cc_mdss_dptx0_link_clk_src, .clkr.hw.init = &(struct clk_init_data) { .name = "disp_cc_mdss_dptx3_link_clk_src", .parent_data = disp_cc_parent_data_3, .num_parents = ARRAY_SIZE(disp_cc_parent_data_3), .flags = CLK_SET_RATE_PARENT, - .ops = &clk_rcg2_ops, + .ops = &clk_byte2_ops, }, }; From 1113501cfb46d5c0eb960f0a8a9f6c0f91dc6fb6 Mon Sep 17 00:00:00 2001 From: Dmitry Baryshkov Date: Wed, 24 Apr 2024 04:39:30 +0300 Subject: [PATCH 095/118] clk: qcom: dispcc-sm6350: fix DisplayPort clocks On SM6350 DisplayPort link clocks use frequency tables inherited from the vendor kernel, it is not applicable in the upstream kernel. Drop frequency tables and use clk_byte2_ops for those clocks. This fixes frequency selection in the OPP core (which otherwise attempts to use invalid 810 KHz as DP link rate), also fixing the following message: msm-dp-display ae90000.displayport-controller: _opp_config_clk_single: failed to set clock rate: -22 Fixes: 837519775f1d ("clk: qcom: Add display clock controller driver for SM6350") Reviewed-by: Neil Armstrong Tested-by: Luca Weiss Reviewed-by: Konrad Dybcio Signed-off-by: Dmitry Baryshkov Link: https://lore.kernel.org/r/20240424-dispcc-dp-clocks-v2-2-b44038f3fa96@linaro.org Signed-off-by: Bjorn Andersson --- drivers/clk/qcom/dispcc-sm6350.c | 11 +---------- 1 file changed, 1 insertion(+), 10 deletions(-) diff --git a/drivers/clk/qcom/dispcc-sm6350.c b/drivers/clk/qcom/dispcc-sm6350.c index 839435362010..e4b7464c4d0e 100644 --- a/drivers/clk/qcom/dispcc-sm6350.c +++ b/drivers/clk/qcom/dispcc-sm6350.c @@ -221,26 +221,17 @@ static struct clk_rcg2 disp_cc_mdss_dp_crypto_clk_src = { }, }; -static const struct freq_tbl ftbl_disp_cc_mdss_dp_link_clk_src[] = { - F(162000, P_DP_PHY_PLL_LINK_CLK, 1, 0, 0), - F(270000, P_DP_PHY_PLL_LINK_CLK, 1, 0, 0), - F(540000, P_DP_PHY_PLL_LINK_CLK, 1, 0, 0), - F(810000, P_DP_PHY_PLL_LINK_CLK, 1, 0, 0), - { } -}; - static struct clk_rcg2 disp_cc_mdss_dp_link_clk_src = { .cmd_rcgr = 0x10f8, .mnd_width = 0, .hid_width = 5, .parent_map = disp_cc_parent_map_0, - .freq_tbl = ftbl_disp_cc_mdss_dp_link_clk_src, .clkr.hw.init = &(struct clk_init_data){ .name = "disp_cc_mdss_dp_link_clk_src", .parent_data = disp_cc_parent_data_0, .num_parents = ARRAY_SIZE(disp_cc_parent_data_0), .flags = CLK_SET_RATE_PARENT | CLK_GET_RATE_NOCACHE, - .ops = &clk_rcg2_ops, + .ops = &clk_byte2_ops, }, }; From e90b5139da8465a15c3820b4b67ca9468dce93b4 Mon Sep 17 00:00:00 2001 From: Dmitry Baryshkov Date: Wed, 24 Apr 2024 04:39:31 +0300 Subject: [PATCH 096/118] clk: qcom: dispcc-sm8550: fix DisplayPort clocks On SM8550 DisplayPort link clocks use frequency tables inherited from the vendor kernel, it is not applicable in the upstream kernel. Drop frequency tables and use clk_byte2_ops for those clocks. This fixes frequency selection in the OPP core (which otherwise attempts to use invalid 810 KHz as DP link rate), also fixing the following message: msm-dp-display ae90000.displayport-controller: _opp_config_clk_single: failed to set clock rate: -22 Fixes: 90114ca11476 ("clk: qcom: add SM8550 DISPCC driver") Reviewed-by: Neil Armstrong Tested-by: Neil Armstrong # on SM8550-HDK Reviewed-by: Konrad Dybcio Signed-off-by: Dmitry Baryshkov Link: https://lore.kernel.org/r/20240424-dispcc-dp-clocks-v2-3-b44038f3fa96@linaro.org Signed-off-by: Bjorn Andersson --- drivers/clk/qcom/dispcc-sm8550.c | 20 ++++---------------- 1 file changed, 4 insertions(+), 16 deletions(-) diff --git a/drivers/clk/qcom/dispcc-sm8550.c b/drivers/clk/qcom/dispcc-sm8550.c index 3672c73ac11c..38ecea805503 100644 --- a/drivers/clk/qcom/dispcc-sm8550.c +++ b/drivers/clk/qcom/dispcc-sm8550.c @@ -345,26 +345,17 @@ static struct clk_rcg2 disp_cc_mdss_dptx0_aux_clk_src = { }, }; -static const struct freq_tbl ftbl_disp_cc_mdss_dptx0_link_clk_src[] = { - F(162000, P_DP0_PHY_PLL_LINK_CLK, 1, 0, 0), - F(270000, P_DP0_PHY_PLL_LINK_CLK, 1, 0, 0), - F(540000, P_DP0_PHY_PLL_LINK_CLK, 1, 0, 0), - F(810000, P_DP0_PHY_PLL_LINK_CLK, 1, 0, 0), - { } -}; - static struct clk_rcg2 disp_cc_mdss_dptx0_link_clk_src = { .cmd_rcgr = 0x8170, .mnd_width = 0, .hid_width = 5, .parent_map = disp_cc_parent_map_7, - .freq_tbl = ftbl_disp_cc_mdss_dptx0_link_clk_src, .clkr.hw.init = &(struct clk_init_data) { .name = "disp_cc_mdss_dptx0_link_clk_src", .parent_data = disp_cc_parent_data_7, .num_parents = ARRAY_SIZE(disp_cc_parent_data_7), .flags = CLK_SET_RATE_PARENT, - .ops = &clk_rcg2_ops, + .ops = &clk_byte2_ops, }, }; @@ -418,13 +409,12 @@ static struct clk_rcg2 disp_cc_mdss_dptx1_link_clk_src = { .mnd_width = 0, .hid_width = 5, .parent_map = disp_cc_parent_map_3, - .freq_tbl = ftbl_disp_cc_mdss_dptx0_link_clk_src, .clkr.hw.init = &(struct clk_init_data) { .name = "disp_cc_mdss_dptx1_link_clk_src", .parent_data = disp_cc_parent_data_3, .num_parents = ARRAY_SIZE(disp_cc_parent_data_3), .flags = CLK_SET_RATE_PARENT, - .ops = &clk_rcg2_ops, + .ops = &clk_byte2_ops, }, }; @@ -478,13 +468,12 @@ static struct clk_rcg2 disp_cc_mdss_dptx2_link_clk_src = { .mnd_width = 0, .hid_width = 5, .parent_map = disp_cc_parent_map_3, - .freq_tbl = ftbl_disp_cc_mdss_dptx0_link_clk_src, .clkr.hw.init = &(struct clk_init_data) { .name = "disp_cc_mdss_dptx2_link_clk_src", .parent_data = disp_cc_parent_data_3, .num_parents = ARRAY_SIZE(disp_cc_parent_data_3), .flags = CLK_SET_RATE_PARENT, - .ops = &clk_rcg2_ops, + .ops = &clk_byte2_ops, }, }; @@ -538,13 +527,12 @@ static struct clk_rcg2 disp_cc_mdss_dptx3_link_clk_src = { .mnd_width = 0, .hid_width = 5, .parent_map = disp_cc_parent_map_3, - .freq_tbl = ftbl_disp_cc_mdss_dptx0_link_clk_src, .clkr.hw.init = &(struct clk_init_data) { .name = "disp_cc_mdss_dptx3_link_clk_src", .parent_data = disp_cc_parent_data_3, .num_parents = ARRAY_SIZE(disp_cc_parent_data_3), .flags = CLK_SET_RATE_PARENT, - .ops = &clk_rcg2_ops, + .ops = &clk_byte2_ops, }, }; From 615a292ee4d51303246278f3fa33cc38700fe00e Mon Sep 17 00:00:00 2001 From: Dmitry Baryshkov Date: Wed, 24 Apr 2024 04:39:32 +0300 Subject: [PATCH 097/118] clk: qcom: dispcc-sm8650: fix DisplayPort clocks On SM8650 DisplayPort link clocks use frequency tables inherited from the vendor kernel, it is not applicable in the upstream kernel. Drop frequency tables and use clk_byte2_ops for those clocks. This fixes frequency selection in the OPP core (which otherwise attempts to use invalid 810 KHz as DP link rate), also fixing the following message: msm-dp-display af54000.displayport-controller: _opp_config_clk_single: failed to set clock rate: -22 Fixes: 9e939f008338 ("clk: qcom: add the SM8650 Display Clock Controller driver") Reviewed-by: Neil Armstrong Tested-by: Neil Armstrong # on SM8650-HDK Reviewed-by: Konrad Dybcio Signed-off-by: Dmitry Baryshkov Link: https://lore.kernel.org/r/20240424-dispcc-dp-clocks-v2-4-b44038f3fa96@linaro.org Signed-off-by: Bjorn Andersson --- drivers/clk/qcom/dispcc-sm8650.c | 20 ++++---------------- 1 file changed, 4 insertions(+), 16 deletions(-) diff --git a/drivers/clk/qcom/dispcc-sm8650.c b/drivers/clk/qcom/dispcc-sm8650.c index 9539db0d9114..3eb64bcad487 100644 --- a/drivers/clk/qcom/dispcc-sm8650.c +++ b/drivers/clk/qcom/dispcc-sm8650.c @@ -343,26 +343,17 @@ static struct clk_rcg2 disp_cc_mdss_dptx0_aux_clk_src = { }, }; -static const struct freq_tbl ftbl_disp_cc_mdss_dptx0_link_clk_src[] = { - F(162000, P_DP0_PHY_PLL_LINK_CLK, 1, 0, 0), - F(270000, P_DP0_PHY_PLL_LINK_CLK, 1, 0, 0), - F(540000, P_DP0_PHY_PLL_LINK_CLK, 1, 0, 0), - F(810000, P_DP0_PHY_PLL_LINK_CLK, 1, 0, 0), - { } -}; - static struct clk_rcg2 disp_cc_mdss_dptx0_link_clk_src = { .cmd_rcgr = 0x8170, .mnd_width = 0, .hid_width = 5, .parent_map = disp_cc_parent_map_7, - .freq_tbl = ftbl_disp_cc_mdss_dptx0_link_clk_src, .clkr.hw.init = &(const struct clk_init_data) { .name = "disp_cc_mdss_dptx0_link_clk_src", .parent_data = disp_cc_parent_data_7, .num_parents = ARRAY_SIZE(disp_cc_parent_data_7), .flags = CLK_SET_RATE_PARENT, - .ops = &clk_rcg2_ops, + .ops = &clk_byte2_ops, }, }; @@ -416,13 +407,12 @@ static struct clk_rcg2 disp_cc_mdss_dptx1_link_clk_src = { .mnd_width = 0, .hid_width = 5, .parent_map = disp_cc_parent_map_3, - .freq_tbl = ftbl_disp_cc_mdss_dptx0_link_clk_src, .clkr.hw.init = &(const struct clk_init_data) { .name = "disp_cc_mdss_dptx1_link_clk_src", .parent_data = disp_cc_parent_data_3, .num_parents = ARRAY_SIZE(disp_cc_parent_data_3), .flags = CLK_SET_RATE_PARENT, - .ops = &clk_rcg2_ops, + .ops = &clk_byte2_ops, }, }; @@ -476,13 +466,12 @@ static struct clk_rcg2 disp_cc_mdss_dptx2_link_clk_src = { .mnd_width = 0, .hid_width = 5, .parent_map = disp_cc_parent_map_3, - .freq_tbl = ftbl_disp_cc_mdss_dptx0_link_clk_src, .clkr.hw.init = &(const struct clk_init_data) { .name = "disp_cc_mdss_dptx2_link_clk_src", .parent_data = disp_cc_parent_data_3, .num_parents = ARRAY_SIZE(disp_cc_parent_data_3), .flags = CLK_SET_RATE_PARENT, - .ops = &clk_rcg2_ops, + .ops = &clk_byte2_ops, }, }; @@ -536,13 +525,12 @@ static struct clk_rcg2 disp_cc_mdss_dptx3_link_clk_src = { .mnd_width = 0, .hid_width = 5, .parent_map = disp_cc_parent_map_3, - .freq_tbl = ftbl_disp_cc_mdss_dptx0_link_clk_src, .clkr.hw.init = &(const struct clk_init_data) { .name = "disp_cc_mdss_dptx3_link_clk_src", .parent_data = disp_cc_parent_data_3, .num_parents = ARRAY_SIZE(disp_cc_parent_data_3), .flags = CLK_SET_RATE_PARENT, - .ops = &clk_rcg2_ops, + .ops = &clk_byte2_ops, }, }; From e20ae5ae9f0c843aded4f06f3d1cab7384789e92 Mon Sep 17 00:00:00 2001 From: Marc Gonzalez Date: Thu, 25 Apr 2024 17:07:07 +0200 Subject: [PATCH 098/118] clk: qcom: mmcc-msm8998: fix venus clock issue Right now, msm8998 video decoder (venus) is non-functional: $ time mpv --hwdec=v4l2m2m-copy --vd-lavc-software-fallback=no --vo=null --no-audio --untimed --length=30 --quiet demo-480.webm (+) Video --vid=1 (*) (vp9 854x480 29.970fps) Audio --aid=1 --alang=eng (*) (opus 2ch 48000Hz) [ffmpeg/video] vp9_v4l2m2m: output VIDIOC_REQBUFS failed: Connection timed out [ffmpeg/video] vp9_v4l2m2m: no v4l2 output context's buffers [ffmpeg/video] vp9_v4l2m2m: can't configure decoder Could not open codec. Software decoding fallback is disabled. Exiting... (Quit) Bryan O'Donoghue suggested the proper fix: - Set required register offsets in venus GDSC structs. - Set HW_CTRL flag. $ time mpv --hwdec=v4l2m2m-copy --vd-lavc-software-fallback=no --vo=null --no-audio --untimed --length=30 --quiet demo-480.webm (+) Video --vid=1 (*) (vp9 854x480 29.970fps) Audio --aid=1 --alang=eng (*) (opus 2ch 48000Hz) [ffmpeg/video] vp9_v4l2m2m: VIDIOC_G_FMT ioctl [ffmpeg/video] vp9_v4l2m2m: VIDIOC_G_FMT ioctl ... Using hardware decoding (v4l2m2m-copy). VO: [null] 854x480 nv12 Exiting... (End of file) real 0m3.315s user 0m1.277s sys 0m0.453s NOTES: GDSC = Globally Distributed Switch Controller Use same code as mmcc-msm8996 with: s/venus_gdsc/video_top_gdsc/ s/venus_core0_gdsc/video_subcore0_gdsc/ s/venus_core1_gdsc/video_subcore1_gdsc/ https://git.codelinaro.org/clo/la/kernel/msm-4.4/-/blob/caf_migration/kernel.lnx.4.4.r38-rel/include/dt-bindings/clock/msm-clocks-hwio-8996.h https://git.codelinaro.org/clo/la/kernel/msm-4.4/-/blob/caf_migration/kernel.lnx.4.4.r38-rel/include/dt-bindings/clock/msm-clocks-hwio-8998.h 0x1024 = MMSS_VIDEO GDSCR (undocumented) 0x1028 = MMSS_VIDEO_CORE_CBCR 0x1030 = MMSS_VIDEO_AHB_CBCR 0x1034 = MMSS_VIDEO_AXI_CBCR 0x1038 = MMSS_VIDEO_MAXI_CBCR 0x1040 = MMSS_VIDEO_SUBCORE0 GDSCR (undocumented) 0x1044 = MMSS_VIDEO_SUBCORE1 GDSCR (undocumented) 0x1048 = MMSS_VIDEO_SUBCORE0_CBCR 0x104c = MMSS_VIDEO_SUBCORE1_CBCR Fixes: d14b15b5931c2b ("clk: qcom: Add MSM8998 Multimedia Clock Controller (MMCC) driver") Reviewed-by: Bryan O'Donoghue Signed-off-by: Marc Gonzalez Reviewed-by: Jeffrey Hugo Link: https://lore.kernel.org/r/ff4e2e34-a677-4c39-8c29-83655c5512ae@freebox.fr Signed-off-by: Bjorn Andersson --- drivers/clk/qcom/mmcc-msm8998.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/drivers/clk/qcom/mmcc-msm8998.c b/drivers/clk/qcom/mmcc-msm8998.c index 1180e48c687a..275fb3b71ede 100644 --- a/drivers/clk/qcom/mmcc-msm8998.c +++ b/drivers/clk/qcom/mmcc-msm8998.c @@ -2535,6 +2535,8 @@ static struct clk_branch vmem_ahb_clk = { static struct gdsc video_top_gdsc = { .gdscr = 0x1024, + .cxcs = (unsigned int []){ 0x1028, 0x1034, 0x1038 }, + .cxc_count = 3, .pd = { .name = "video_top", }, @@ -2543,20 +2545,26 @@ static struct gdsc video_top_gdsc = { static struct gdsc video_subcore0_gdsc = { .gdscr = 0x1040, + .cxcs = (unsigned int []){ 0x1048 }, + .cxc_count = 1, .pd = { .name = "video_subcore0", }, .parent = &video_top_gdsc.pd, .pwrsts = PWRSTS_OFF_ON, + .flags = HW_CTRL, }; static struct gdsc video_subcore1_gdsc = { .gdscr = 0x1044, + .cxcs = (unsigned int []){ 0x104c }, + .cxc_count = 1, .pd = { .name = "video_subcore1", }, .parent = &video_top_gdsc.pd, .pwrsts = PWRSTS_OFF_ON, + .flags = HW_CTRL, }; static struct gdsc mdss_gdsc = { From 1891e4d487554ef66350308c3603ed07b6557f17 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9=20Draszik?= Date: Fri, 26 Apr 2024 11:03:07 +0100 Subject: [PATCH 099/118] clk: samsung: gs101: add support for cmu_hsi0 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit CMU_HSI0 is the clock management unit for one of the high speed interfaces, which is used (amongst others) for USB Some notes about the clocks marked as CLK_IGNORE_UNUSED: * CLK_GOUT_HSI0_PCLK CLK_GOUT_HSI0_LHM_AXI_P_HSI0_I_CLK CLK_GOUT_HSI0_XIU_P_HSI0_ACLK need to be kept running as otherwise the system becomes unresponsive and it doesn't complete booting. * CLK_GOUT_HSI0_LHS_ACEL_D_HSI0_I_CLK CLK_GOUT_HSI0_SSMT_USB_ACLK CLK_GOUT_HSI0_SSMT_USB_PCLK CLK_GOUT_HSI0_SYSMMU_USB_CLK_S2 CLK_GOUT_HSI0_XIU_D0_HSI0_ACLK CLK_GOUT_HSI0_XIU_D1_HSI0_ACLK are needed for USB to come up properly (SSMT is for (secure) memory tagging). While at the moment we only support booting with the clk_ignore_unused kernel command line paramenter, it's still worthwhile to explicitly mark those clocks. While the usual (sed) script has been used to derive the linux clock names from the data sheet, one manual tweak was applied to fix a typo coming from the data sheet which we don't want to carry: hsi0_uspdpdbg_user -> hsi0_usbdpdbg_user (note usb vs usp). Signed-off-by: André Draszik Link: https://lore.kernel.org/r/20240426-hsi0-gs101-v2-4-2157da8b63e3@linaro.org Signed-off-by: Krzysztof Kozlowski --- drivers/clk/samsung/clk-gs101.c | 469 ++++++++++++++++++++++++++++++++ 1 file changed, 469 insertions(+) diff --git a/drivers/clk/samsung/clk-gs101.c b/drivers/clk/samsung/clk-gs101.c index bd3c1b02715b..ce0ff35f4548 100644 --- a/drivers/clk/samsung/clk-gs101.c +++ b/drivers/clk/samsung/clk-gs101.c @@ -15,10 +15,12 @@ #include "clk.h" #include "clk-exynos-arm64.h" +#include "clk-pll.h" /* NOTE: Must be equal to the last clock ID increased by one */ #define CLKS_NR_TOP (CLK_GOUT_CMU_TPU_UART + 1) #define CLKS_NR_APM (CLK_APM_PLL_DIV16_APM + 1) +#define CLKS_NR_HSI0 (CLK_GOUT_HSI0_XIU_P_HSI0_ACLK + 1) #define CLKS_NR_MISC (CLK_GOUT_MISC_XIU_D_MISC_ACLK + 1) #define CLKS_NR_PERIC0 (CLK_GOUT_PERIC0_SYSREG_PERIC0_PCLK + 1) #define CLKS_NR_PERIC1 (CLK_GOUT_PERIC1_SYSREG_PERIC1_PCLK + 1) @@ -1919,6 +1921,470 @@ static const struct samsung_cmu_info apm_cmu_info __initconst = { .nr_clk_regs = ARRAY_SIZE(apm_clk_regs), }; +/* ---- CMU_HSI0 ------------------------------------------------------------ */ + +/* Register Offset definitions for CMU_HSI0 (0x11000000) */ +#define PLL_LOCKTIME_PLL_USB 0x0004 +#define PLL_CON0_PLL_USB 0x0140 +#define PLL_CON1_PLL_USB 0x0144 +#define PLL_CON2_PLL_USB 0x0148 +#define PLL_CON3_PLL_USB 0x014c +#define PLL_CON4_PLL_USB 0x0150 +#define PLL_CON0_MUX_CLKCMU_HSI0_ALT_USER 0x0600 +#define PLL_CON1_MUX_CLKCMU_HSI0_ALT_USER 0x0604 +#define PLL_CON0_MUX_CLKCMU_HSI0_BUS_USER 0x0610 +#define PLL_CON1_MUX_CLKCMU_HSI0_BUS_USER 0x0614 +#define PLL_CON0_MUX_CLKCMU_HSI0_DPGTC_USER 0x0620 +#define PLL_CON1_MUX_CLKCMU_HSI0_DPGTC_USER 0x0624 +#define PLL_CON0_MUX_CLKCMU_HSI0_TCXO_USER 0x0630 +#define PLL_CON1_MUX_CLKCMU_HSI0_TCXO_USER 0x0634 +#define PLL_CON0_MUX_CLKCMU_HSI0_USB20_USER 0x0640 +#define PLL_CON1_MUX_CLKCMU_HSI0_USB20_USER 0x0644 +#define PLL_CON0_MUX_CLKCMU_HSI0_USB31DRD_USER 0x0650 +#define PLL_CON1_MUX_CLKCMU_HSI0_USB31DRD_USER 0x0654 +#define PLL_CON0_MUX_CLKCMU_HSI0_USPDPDBG_USER 0x0660 +#define PLL_CON1_MUX_CLKCMU_HSI0_USPDPDBG_USER 0x0664 +#define HSI0_CMU_HSI0_CONTROLLER_OPTION 0x0800 +#define CLKOUT_CON_BLK_HSI0_CMU_HSI0_CLKOUT0 0x0810 +#define CLK_CON_MUX_MUX_CLK_HSI0_BUS 0x1000 +#define CLK_CON_MUX_MUX_CLK_HSI0_USB20_REF 0x1004 +#define CLK_CON_MUX_MUX_CLK_HSI0_USB31DRD 0x1008 +#define CLK_CON_DIV_DIV_CLK_HSI0_USB31DRD 0x1800 +#define CLK_CON_GAT_CLK_BLK_HSI0_UID_HSI0_CMU_HSI0_IPCLKPORT_PCLK 0x2000 +#define CLK_CON_GAT_CLK_BLK_HSI0_UID_USB31DRD_IPCLKPORT_I_USB31DRD_SUSPEND_CLK_26 0x2004 +#define CLK_CON_GAT_CLK_HSI0_ALT 0x2008 +#define CLK_CON_GAT_GOUT_BLK_HSI0_UID_DP_LINK_IPCLKPORT_I_DP_GTC_CLK 0x200c +#define CLK_CON_GAT_GOUT_BLK_HSI0_UID_DP_LINK_IPCLKPORT_I_PCLK 0x2010 +#define CLK_CON_GAT_GOUT_BLK_HSI0_UID_D_TZPC_HSI0_IPCLKPORT_PCLK 0x2014 +#define CLK_CON_GAT_GOUT_BLK_HSI0_UID_ETR_MIU_IPCLKPORT_I_ACLK 0x2018 +#define CLK_CON_GAT_GOUT_BLK_HSI0_UID_ETR_MIU_IPCLKPORT_I_PCLK 0x201c +#define CLK_CON_GAT_GOUT_BLK_HSI0_UID_GPC_HSI0_IPCLKPORT_PCLK 0x2020 +#define CLK_CON_GAT_GOUT_BLK_HSI0_UID_LHM_AXI_G_ETR_HSI0_IPCLKPORT_I_CLK 0x2024 +#define CLK_CON_GAT_GOUT_BLK_HSI0_UID_LHM_AXI_P_AOCHSI0_IPCLKPORT_I_CLK 0x2028 +#define CLK_CON_GAT_GOUT_BLK_HSI0_UID_LHM_AXI_P_HSI0_IPCLKPORT_I_CLK 0x202c +#define CLK_CON_GAT_GOUT_BLK_HSI0_UID_LHS_ACEL_D_HSI0_IPCLKPORT_I_CLK 0x2030 +#define CLK_CON_GAT_GOUT_BLK_HSI0_UID_LHS_AXI_D_HSI0AOC_IPCLKPORT_I_CLK 0x2034 +#define CLK_CON_GAT_GOUT_BLK_HSI0_UID_PPMU_HSI0_AOC_IPCLKPORT_ACLK 0x2038 +#define CLK_CON_GAT_GOUT_BLK_HSI0_UID_PPMU_HSI0_AOC_IPCLKPORT_PCLK 0x203c +#define CLK_CON_GAT_GOUT_BLK_HSI0_UID_PPMU_HSI0_BUS0_IPCLKPORT_ACLK 0x2040 +#define CLK_CON_GAT_GOUT_BLK_HSI0_UID_PPMU_HSI0_BUS0_IPCLKPORT_PCLK 0x2044 +#define CLK_CON_GAT_GOUT_BLK_HSI0_UID_RSTNSYNC_CLK_HSI0_BUS_IPCLKPORT_CLK 0x2048 +#define CLK_CON_GAT_GOUT_BLK_HSI0_UID_SSMT_USB_IPCLKPORT_ACLK 0x204c +#define CLK_CON_GAT_GOUT_BLK_HSI0_UID_SSMT_USB_IPCLKPORT_PCLK 0x2050 +#define CLK_CON_GAT_GOUT_BLK_HSI0_UID_SYSMMU_USB_IPCLKPORT_CLK_S2 0x2054 +#define CLK_CON_GAT_GOUT_BLK_HSI0_UID_SYSREG_HSI0_IPCLKPORT_PCLK 0x2058 +#define CLK_CON_GAT_GOUT_BLK_HSI0_UID_UASC_HSI0_CTRL_IPCLKPORT_ACLK 0x205c +#define CLK_CON_GAT_GOUT_BLK_HSI0_UID_UASC_HSI0_CTRL_IPCLKPORT_PCLK 0x2060 +#define CLK_CON_GAT_GOUT_BLK_HSI0_UID_UASC_HSI0_LINK_IPCLKPORT_ACLK 0x2064 +#define CLK_CON_GAT_GOUT_BLK_HSI0_UID_UASC_HSI0_LINK_IPCLKPORT_PCLK 0x2068 +#define CLK_CON_GAT_GOUT_BLK_HSI0_UID_USB31DRD_IPCLKPORT_ACLK_PHYCTRL 0x206c +#define CLK_CON_GAT_GOUT_BLK_HSI0_UID_USB31DRD_IPCLKPORT_BUS_CLK_EARLY 0x2070 +#define CLK_CON_GAT_GOUT_BLK_HSI0_UID_USB31DRD_IPCLKPORT_I_USB20_PHY_REFCLK_26 0x2074 +#define CLK_CON_GAT_GOUT_BLK_HSI0_UID_USB31DRD_IPCLKPORT_I_USB31DRD_REF_CLK_40 0x2078 +#define CLK_CON_GAT_GOUT_BLK_HSI0_UID_USB31DRD_IPCLKPORT_I_USBDPPHY_REF_SOC_PLL 0x207c +#define CLK_CON_GAT_GOUT_BLK_HSI0_UID_USB31DRD_IPCLKPORT_I_USBDPPHY_SCL_APB_PCLK 0x2080 +#define CLK_CON_GAT_GOUT_BLK_HSI0_UID_USB31DRD_IPCLKPORT_I_USBPCS_APB_CLK 0x2084 +#define CLK_CON_GAT_GOUT_BLK_HSI0_UID_USB31DRD_IPCLKPORT_USBDPPHY_I_ACLK 0x2088 +#define CLK_CON_GAT_GOUT_BLK_HSI0_UID_USB31DRD_IPCLKPORT_USBDPPHY_UDBG_I_APB_PCLK 0x208c +#define CLK_CON_GAT_GOUT_BLK_HSI0_UID_XIU_D0_HSI0_IPCLKPORT_ACLK 0x2090 +#define CLK_CON_GAT_GOUT_BLK_HSI0_UID_XIU_D1_HSI0_IPCLKPORT_ACLK 0x2094 +#define CLK_CON_GAT_GOUT_BLK_HSI0_UID_XIU_P_HSI0_IPCLKPORT_ACLK 0x2098 +#define DMYQCH_CON_USB31DRD_QCH 0x3000 +#define DMYQCH_CON_USB31DRD_QCH_REF 0x3004 +#define PCH_CON_LHM_AXI_G_ETR_HSI0_PCH 0x3008 +#define PCH_CON_LHM_AXI_P_AOCHSI0_PCH 0x300c +#define PCH_CON_LHM_AXI_P_HSI0_PCH 0x3010 +#define PCH_CON_LHS_ACEL_D_HSI0_PCH 0x3014 +#define PCH_CON_LHS_AXI_D_HSI0AOC_PCH 0x3018 +#define QCH_CON_DP_LINK_QCH_GTC_CLK 0x301c +#define QCH_CON_DP_LINK_QCH_PCLK 0x3020 +#define QCH_CON_D_TZPC_HSI0_QCH 0x3024 +#define QCH_CON_ETR_MIU_QCH_ACLK 0x3028 +#define QCH_CON_ETR_MIU_QCH_PCLK 0x302c +#define QCH_CON_GPC_HSI0_QCH 0x3030 +#define QCH_CON_HSI0_CMU_HSI0_QCH 0x3034 +#define QCH_CON_LHM_AXI_G_ETR_HSI0_QCH 0x3038 +#define QCH_CON_LHM_AXI_P_AOCHSI0_QCH 0x303c +#define QCH_CON_LHM_AXI_P_HSI0_QCH 0x3040 +#define QCH_CON_LHS_ACEL_D_HSI0_QCH 0x3044 +#define QCH_CON_LHS_AXI_D_HSI0AOC_QCH 0x3048 +#define QCH_CON_PPMU_HSI0_AOC_QCH 0x304c +#define QCH_CON_PPMU_HSI0_BUS0_QCH 0x3050 +#define QCH_CON_SSMT_USB_QCH 0x3054 +#define QCH_CON_SYSMMU_USB_QCH 0x3058 +#define QCH_CON_SYSREG_HSI0_QCH 0x305c +#define QCH_CON_UASC_HSI0_CTRL_QCH 0x3060 +#define QCH_CON_UASC_HSI0_LINK_QCH 0x3064 +#define QCH_CON_USB31DRD_QCH_APB 0x3068 +#define QCH_CON_USB31DRD_QCH_DBG 0x306c +#define QCH_CON_USB31DRD_QCH_PCS 0x3070 +#define QCH_CON_USB31DRD_QCH_SLV_CTRL 0x3074 +#define QCH_CON_USB31DRD_QCH_SLV_LINK 0x3078 +#define QUEUE_CTRL_REG_BLK_HSI0_CMU_HSI0 0x3c00 + +static const unsigned long hsi0_clk_regs[] __initconst = { + PLL_LOCKTIME_PLL_USB, + PLL_CON0_PLL_USB, + PLL_CON1_PLL_USB, + PLL_CON2_PLL_USB, + PLL_CON3_PLL_USB, + PLL_CON4_PLL_USB, + PLL_CON0_MUX_CLKCMU_HSI0_ALT_USER, + PLL_CON1_MUX_CLKCMU_HSI0_ALT_USER, + PLL_CON0_MUX_CLKCMU_HSI0_BUS_USER, + PLL_CON1_MUX_CLKCMU_HSI0_BUS_USER, + PLL_CON0_MUX_CLKCMU_HSI0_DPGTC_USER, + PLL_CON1_MUX_CLKCMU_HSI0_DPGTC_USER, + PLL_CON0_MUX_CLKCMU_HSI0_TCXO_USER, + PLL_CON1_MUX_CLKCMU_HSI0_TCXO_USER, + PLL_CON0_MUX_CLKCMU_HSI0_USB20_USER, + PLL_CON1_MUX_CLKCMU_HSI0_USB20_USER, + PLL_CON0_MUX_CLKCMU_HSI0_USB31DRD_USER, + PLL_CON1_MUX_CLKCMU_HSI0_USB31DRD_USER, + PLL_CON0_MUX_CLKCMU_HSI0_USPDPDBG_USER, + PLL_CON1_MUX_CLKCMU_HSI0_USPDPDBG_USER, + HSI0_CMU_HSI0_CONTROLLER_OPTION, + CLKOUT_CON_BLK_HSI0_CMU_HSI0_CLKOUT0, + CLK_CON_MUX_MUX_CLK_HSI0_BUS, + CLK_CON_MUX_MUX_CLK_HSI0_USB20_REF, + CLK_CON_MUX_MUX_CLK_HSI0_USB31DRD, + CLK_CON_DIV_DIV_CLK_HSI0_USB31DRD, + CLK_CON_GAT_CLK_BLK_HSI0_UID_HSI0_CMU_HSI0_IPCLKPORT_PCLK, + CLK_CON_GAT_CLK_BLK_HSI0_UID_USB31DRD_IPCLKPORT_I_USB31DRD_SUSPEND_CLK_26, + CLK_CON_GAT_CLK_HSI0_ALT, + CLK_CON_GAT_GOUT_BLK_HSI0_UID_DP_LINK_IPCLKPORT_I_DP_GTC_CLK, + CLK_CON_GAT_GOUT_BLK_HSI0_UID_DP_LINK_IPCLKPORT_I_PCLK, + CLK_CON_GAT_GOUT_BLK_HSI0_UID_D_TZPC_HSI0_IPCLKPORT_PCLK, + CLK_CON_GAT_GOUT_BLK_HSI0_UID_ETR_MIU_IPCLKPORT_I_ACLK, + CLK_CON_GAT_GOUT_BLK_HSI0_UID_ETR_MIU_IPCLKPORT_I_PCLK, + CLK_CON_GAT_GOUT_BLK_HSI0_UID_GPC_HSI0_IPCLKPORT_PCLK, + CLK_CON_GAT_GOUT_BLK_HSI0_UID_LHM_AXI_G_ETR_HSI0_IPCLKPORT_I_CLK, + CLK_CON_GAT_GOUT_BLK_HSI0_UID_LHM_AXI_P_AOCHSI0_IPCLKPORT_I_CLK, + CLK_CON_GAT_GOUT_BLK_HSI0_UID_LHM_AXI_P_HSI0_IPCLKPORT_I_CLK, + CLK_CON_GAT_GOUT_BLK_HSI0_UID_LHS_ACEL_D_HSI0_IPCLKPORT_I_CLK, + CLK_CON_GAT_GOUT_BLK_HSI0_UID_LHS_AXI_D_HSI0AOC_IPCLKPORT_I_CLK, + CLK_CON_GAT_GOUT_BLK_HSI0_UID_PPMU_HSI0_AOC_IPCLKPORT_ACLK, + CLK_CON_GAT_GOUT_BLK_HSI0_UID_PPMU_HSI0_AOC_IPCLKPORT_PCLK, + CLK_CON_GAT_GOUT_BLK_HSI0_UID_PPMU_HSI0_BUS0_IPCLKPORT_ACLK, + CLK_CON_GAT_GOUT_BLK_HSI0_UID_PPMU_HSI0_BUS0_IPCLKPORT_PCLK, + CLK_CON_GAT_GOUT_BLK_HSI0_UID_RSTNSYNC_CLK_HSI0_BUS_IPCLKPORT_CLK, + CLK_CON_GAT_GOUT_BLK_HSI0_UID_SSMT_USB_IPCLKPORT_ACLK, + CLK_CON_GAT_GOUT_BLK_HSI0_UID_SSMT_USB_IPCLKPORT_PCLK, + CLK_CON_GAT_GOUT_BLK_HSI0_UID_SYSMMU_USB_IPCLKPORT_CLK_S2, + CLK_CON_GAT_GOUT_BLK_HSI0_UID_SYSREG_HSI0_IPCLKPORT_PCLK, + CLK_CON_GAT_GOUT_BLK_HSI0_UID_UASC_HSI0_CTRL_IPCLKPORT_ACLK, + CLK_CON_GAT_GOUT_BLK_HSI0_UID_UASC_HSI0_CTRL_IPCLKPORT_PCLK, + CLK_CON_GAT_GOUT_BLK_HSI0_UID_UASC_HSI0_LINK_IPCLKPORT_ACLK, + CLK_CON_GAT_GOUT_BLK_HSI0_UID_UASC_HSI0_LINK_IPCLKPORT_PCLK, + CLK_CON_GAT_GOUT_BLK_HSI0_UID_USB31DRD_IPCLKPORT_ACLK_PHYCTRL, + CLK_CON_GAT_GOUT_BLK_HSI0_UID_USB31DRD_IPCLKPORT_BUS_CLK_EARLY, + CLK_CON_GAT_GOUT_BLK_HSI0_UID_USB31DRD_IPCLKPORT_I_USB20_PHY_REFCLK_26, + CLK_CON_GAT_GOUT_BLK_HSI0_UID_USB31DRD_IPCLKPORT_I_USB31DRD_REF_CLK_40, + CLK_CON_GAT_GOUT_BLK_HSI0_UID_USB31DRD_IPCLKPORT_I_USBDPPHY_REF_SOC_PLL, + CLK_CON_GAT_GOUT_BLK_HSI0_UID_USB31DRD_IPCLKPORT_I_USBDPPHY_SCL_APB_PCLK, + CLK_CON_GAT_GOUT_BLK_HSI0_UID_USB31DRD_IPCLKPORT_I_USBPCS_APB_CLK, + CLK_CON_GAT_GOUT_BLK_HSI0_UID_USB31DRD_IPCLKPORT_USBDPPHY_I_ACLK, + CLK_CON_GAT_GOUT_BLK_HSI0_UID_USB31DRD_IPCLKPORT_USBDPPHY_UDBG_I_APB_PCLK, + CLK_CON_GAT_GOUT_BLK_HSI0_UID_XIU_D0_HSI0_IPCLKPORT_ACLK, + CLK_CON_GAT_GOUT_BLK_HSI0_UID_XIU_D1_HSI0_IPCLKPORT_ACLK, + CLK_CON_GAT_GOUT_BLK_HSI0_UID_XIU_P_HSI0_IPCLKPORT_ACLK, + DMYQCH_CON_USB31DRD_QCH, + DMYQCH_CON_USB31DRD_QCH_REF, + PCH_CON_LHM_AXI_G_ETR_HSI0_PCH, + PCH_CON_LHM_AXI_P_AOCHSI0_PCH, + PCH_CON_LHM_AXI_P_HSI0_PCH, + PCH_CON_LHS_ACEL_D_HSI0_PCH, + PCH_CON_LHS_AXI_D_HSI0AOC_PCH, + QCH_CON_DP_LINK_QCH_GTC_CLK, + QCH_CON_DP_LINK_QCH_PCLK, + QCH_CON_D_TZPC_HSI0_QCH, + QCH_CON_ETR_MIU_QCH_ACLK, + QCH_CON_ETR_MIU_QCH_PCLK, + QCH_CON_GPC_HSI0_QCH, + QCH_CON_HSI0_CMU_HSI0_QCH, + QCH_CON_LHM_AXI_G_ETR_HSI0_QCH, + QCH_CON_LHM_AXI_P_AOCHSI0_QCH, + QCH_CON_LHM_AXI_P_HSI0_QCH, + QCH_CON_LHS_ACEL_D_HSI0_QCH, + QCH_CON_LHS_AXI_D_HSI0AOC_QCH, + QCH_CON_PPMU_HSI0_AOC_QCH, + QCH_CON_PPMU_HSI0_BUS0_QCH, + QCH_CON_SSMT_USB_QCH, + QCH_CON_SYSMMU_USB_QCH, + QCH_CON_SYSREG_HSI0_QCH, + QCH_CON_UASC_HSI0_CTRL_QCH, + QCH_CON_UASC_HSI0_LINK_QCH, + QCH_CON_USB31DRD_QCH_APB, + QCH_CON_USB31DRD_QCH_DBG, + QCH_CON_USB31DRD_QCH_PCS, + QCH_CON_USB31DRD_QCH_SLV_CTRL, + QCH_CON_USB31DRD_QCH_SLV_LINK, + QUEUE_CTRL_REG_BLK_HSI0_CMU_HSI0, +}; + +/* List of parent clocks for Muxes in CMU_HSI0 */ +PNAME(mout_pll_usb_p) = { "oscclk", "fout_usb_pll" }; +PNAME(mout_hsi0_alt_user_p) = { "oscclk", + "gout_hsi0_clk_hsi0_alt" }; +PNAME(mout_hsi0_bus_user_p) = { "oscclk", "dout_cmu_hsi0_bus" }; +PNAME(mout_hsi0_dpgtc_user_p) = { "oscclk", "dout_cmu_hsi0_dpgtc" }; +PNAME(mout_hsi0_tcxo_user_p) = { "oscclk", "tcxo_hsi1_hsi0" }; +PNAME(mout_hsi0_usb20_user_p) = { "oscclk", "usb20phy_phy_clock" }; +PNAME(mout_hsi0_usb31drd_user_p) = { "oscclk", + "dout_cmu_hsi0_usb31drd" }; +PNAME(mout_hsi0_usbdpdbg_user_p) = { "oscclk", + "dout_cmu_hsi0_usbdpdbg" }; +PNAME(mout_hsi0_bus_p) = { "mout_hsi0_bus_user", + "mout_hsi0_alt_user" }; +PNAME(mout_hsi0_usb20_ref_p) = { "fout_usb_pll", + "mout_hsi0_tcxo_user" }; +PNAME(mout_hsi0_usb31drd_p) = { "fout_usb_pll", + "mout_hsi0_usb31drd_user", + "dout_hsi0_usb31drd", + "fout_usb_pll" }; + +static const struct samsung_pll_rate_table cmu_hsi0_usb_pll_rates[] __initconst = { + PLL_35XX_RATE(24576000, 19200000, 150, 6, 5), + { /* sentinel */ } +}; + +static const struct samsung_pll_clock cmu_hsi0_pll_clks[] __initconst = { + PLL(pll_0518x, CLK_FOUT_USB_PLL, "fout_usb_pll", "oscclk", + PLL_LOCKTIME_PLL_USB, PLL_CON3_PLL_USB, + cmu_hsi0_usb_pll_rates), +}; + +static const struct samsung_mux_clock hsi0_mux_clks[] __initconst = { + MUX(CLK_MOUT_PLL_USB, + "mout_pll_usb", mout_pll_usb_p, + PLL_CON0_PLL_USB, 4, 1), + MUX(CLK_MOUT_HSI0_ALT_USER, + "mout_hsi0_alt_user", mout_hsi0_alt_user_p, + PLL_CON0_MUX_CLKCMU_HSI0_ALT_USER, 4, 1), + MUX(CLK_MOUT_HSI0_BUS_USER, + "mout_hsi0_bus_user", mout_hsi0_bus_user_p, + PLL_CON0_MUX_CLKCMU_HSI0_BUS_USER, 4, 1), + MUX(CLK_MOUT_HSI0_DPGTC_USER, + "mout_hsi0_dpgtc_user", mout_hsi0_dpgtc_user_p, + PLL_CON0_MUX_CLKCMU_HSI0_DPGTC_USER, 4, 1), + MUX(CLK_MOUT_HSI0_TCXO_USER, + "mout_hsi0_tcxo_user", mout_hsi0_tcxo_user_p, + PLL_CON0_MUX_CLKCMU_HSI0_TCXO_USER, 4, 1), + MUX(CLK_MOUT_HSI0_USB20_USER, + "mout_hsi0_usb20_user", mout_hsi0_usb20_user_p, + PLL_CON0_MUX_CLKCMU_HSI0_USB20_USER, 4, 1), + MUX(CLK_MOUT_HSI0_USB31DRD_USER, + "mout_hsi0_usb31drd_user", mout_hsi0_usb31drd_user_p, + PLL_CON0_MUX_CLKCMU_HSI0_USB31DRD_USER, 4, 1), + MUX(CLK_MOUT_HSI0_USBDPDBG_USER, + "mout_hsi0_usbdpdbg_user", mout_hsi0_usbdpdbg_user_p, + PLL_CON0_MUX_CLKCMU_HSI0_USPDPDBG_USER, 4, 1), + MUX(CLK_MOUT_HSI0_BUS, + "mout_hsi0_bus", mout_hsi0_bus_p, + CLK_CON_MUX_MUX_CLK_HSI0_BUS, 0, 1), + MUX(CLK_MOUT_HSI0_USB20_REF, + "mout_hsi0_usb20_ref", mout_hsi0_usb20_ref_p, + CLK_CON_MUX_MUX_CLK_HSI0_USB20_REF, 0, 1), + MUX(CLK_MOUT_HSI0_USB31DRD, + "mout_hsi0_usb31drd", mout_hsi0_usb31drd_p, + CLK_CON_MUX_MUX_CLK_HSI0_USB31DRD, 0, 2), +}; + +static const struct samsung_div_clock hsi0_div_clks[] __initconst = { + DIV(CLK_DOUT_HSI0_USB31DRD, + "dout_hsi0_usb31drd", "mout_hsi0_usb20_user", + CLK_CON_DIV_DIV_CLK_HSI0_USB31DRD, 0, 3), +}; + +static const struct samsung_gate_clock hsi0_gate_clks[] __initconst = { + /* TODO: should have a driver for this */ + GATE(CLK_GOUT_HSI0_PCLK, + "gout_hsi0_hsi0_pclk", "mout_hsi0_bus", + CLK_CON_GAT_CLK_BLK_HSI0_UID_HSI0_CMU_HSI0_IPCLKPORT_PCLK, + 21, CLK_IGNORE_UNUSED, 0), + GATE(CLK_GOUT_HSI0_USB31DRD_I_USB31DRD_SUSPEND_CLK_26, + "gout_hsi0_usb31drd_i_usb31drd_suspend_clk_26", + "mout_hsi0_usb20_ref", + CLK_CON_GAT_CLK_BLK_HSI0_UID_USB31DRD_IPCLKPORT_I_USB31DRD_SUSPEND_CLK_26, + 21, 0, 0), + GATE(CLK_GOUT_HSI0_CLK_HSI0_ALT, + "gout_hsi0_clk_hsi0_alt", "ioclk_clk_hsi0_alt", + CLK_CON_GAT_CLK_HSI0_ALT, 21, 0, 0), + GATE(CLK_GOUT_HSI0_DP_LINK_I_DP_GTC_CLK, + "gout_hsi0_dp_link_i_dp_gtc_clk", "mout_hsi0_dpgtc_user", + CLK_CON_GAT_GOUT_BLK_HSI0_UID_DP_LINK_IPCLKPORT_I_DP_GTC_CLK, + 21, 0, 0), + GATE(CLK_GOUT_HSI0_DP_LINK_I_PCLK, + "gout_hsi0_dp_link_i_pclk", "mout_hsi0_bus", + CLK_CON_GAT_GOUT_BLK_HSI0_UID_DP_LINK_IPCLKPORT_I_PCLK, 21, 0, 0), + GATE(CLK_GOUT_HSI0_D_TZPC_HSI0_PCLK, + "gout_hsi0_d_tzpc_hsi0_pclk", "mout_hsi0_bus", + CLK_CON_GAT_GOUT_BLK_HSI0_UID_D_TZPC_HSI0_IPCLKPORT_PCLK, + 21, 0, 0), + GATE(CLK_GOUT_HSI0_ETR_MIU_I_ACLK, + "gout_hsi0_etr_miu_i_aclk", "mout_hsi0_bus", + CLK_CON_GAT_GOUT_BLK_HSI0_UID_ETR_MIU_IPCLKPORT_I_ACLK, 21, 0, 0), + GATE(CLK_GOUT_HSI0_ETR_MIU_I_PCLK, + "gout_hsi0_etr_miu_i_pclk", "mout_hsi0_bus", + CLK_CON_GAT_GOUT_BLK_HSI0_UID_ETR_MIU_IPCLKPORT_I_PCLK, 21, 0, 0), + GATE(CLK_GOUT_HSI0_GPC_HSI0_PCLK, + "gout_hsi0_gpc_hsi0_pclk", "mout_hsi0_bus", + CLK_CON_GAT_GOUT_BLK_HSI0_UID_GPC_HSI0_IPCLKPORT_PCLK, 21, 0, 0), + GATE(CLK_GOUT_HSI0_LHM_AXI_G_ETR_HSI0_I_CLK, + "gout_hsi0_lhm_axi_g_etr_hsi0_i_clk", "mout_hsi0_bus", + CLK_CON_GAT_GOUT_BLK_HSI0_UID_LHM_AXI_G_ETR_HSI0_IPCLKPORT_I_CLK, + 21, 0, 0), + GATE(CLK_GOUT_HSI0_LHM_AXI_P_AOCHSI0_I_CLK, + "gout_hsi0_lhm_axi_p_aochsi0_i_clk", "mout_hsi0_bus", + CLK_CON_GAT_GOUT_BLK_HSI0_UID_LHM_AXI_P_AOCHSI0_IPCLKPORT_I_CLK, + 21, 0, 0), + /* TODO: should have a driver for this */ + GATE(CLK_GOUT_HSI0_LHM_AXI_P_HSI0_I_CLK, + "gout_hsi0_lhm_axi_p_hsi0_i_clk", "mout_hsi0_bus", + CLK_CON_GAT_GOUT_BLK_HSI0_UID_LHM_AXI_P_HSI0_IPCLKPORT_I_CLK, + 21, CLK_IGNORE_UNUSED, 0), + /* TODO: should have a driver for this */ + GATE(CLK_GOUT_HSI0_LHS_ACEL_D_HSI0_I_CLK, + "gout_hsi0_lhs_acel_d_hsi0_i_clk", "mout_hsi0_bus", + CLK_CON_GAT_GOUT_BLK_HSI0_UID_LHS_ACEL_D_HSI0_IPCLKPORT_I_CLK, + 21, CLK_IGNORE_UNUSED, 0), + GATE(CLK_GOUT_HSI0_LHS_AXI_D_HSI0AOC_I_CLK, + "gout_hsi0_lhs_axi_d_hsi0aoc_i_clk", "mout_hsi0_bus", + CLK_CON_GAT_GOUT_BLK_HSI0_UID_LHS_AXI_D_HSI0AOC_IPCLKPORT_I_CLK, + 21, 0, 0), + GATE(CLK_GOUT_HSI0_PPMU_HSI0_AOC_ACLK, + "gout_hsi0_ppmu_hsi0_aoc_aclk", "mout_hsi0_bus", + CLK_CON_GAT_GOUT_BLK_HSI0_UID_PPMU_HSI0_AOC_IPCLKPORT_ACLK, + 21, 0, 0), + GATE(CLK_GOUT_HSI0_PPMU_HSI0_AOC_PCLK, + "gout_hsi0_ppmu_hsi0_aoc_pclk", "mout_hsi0_bus", + CLK_CON_GAT_GOUT_BLK_HSI0_UID_PPMU_HSI0_AOC_IPCLKPORT_PCLK, + 21, 0, 0), + GATE(CLK_GOUT_HSI0_PPMU_HSI0_BUS0_ACLK, + "gout_hsi0_ppmu_hsi0_bus0_aclk", "mout_hsi0_bus", + CLK_CON_GAT_GOUT_BLK_HSI0_UID_PPMU_HSI0_BUS0_IPCLKPORT_ACLK, + 21, 0, 0), + GATE(CLK_GOUT_HSI0_PPMU_HSI0_BUS0_PCLK, + "gout_hsi0_ppmu_hsi0_bus0_pclk", "mout_hsi0_bus", + CLK_CON_GAT_GOUT_BLK_HSI0_UID_PPMU_HSI0_BUS0_IPCLKPORT_PCLK, + 21, 0, 0), + GATE(CLK_GOUT_HSI0_CLK_HSI0_BUS_CLK, + "gout_hsi0_clk_hsi0_bus_clk", "mout_hsi0_bus", + CLK_CON_GAT_GOUT_BLK_HSI0_UID_RSTNSYNC_CLK_HSI0_BUS_IPCLKPORT_CLK, + 21, 0, 0), + /* TODO: should have a driver for this */ + GATE(CLK_GOUT_HSI0_SSMT_USB_ACLK, + "gout_hsi0_ssmt_usb_aclk", "mout_hsi0_bus", + CLK_CON_GAT_GOUT_BLK_HSI0_UID_SSMT_USB_IPCLKPORT_ACLK, + 21, CLK_IGNORE_UNUSED, 0), + /* TODO: should have a driver for this */ + GATE(CLK_GOUT_HSI0_SSMT_USB_PCLK, + "gout_hsi0_ssmt_usb_pclk", "mout_hsi0_bus", + CLK_CON_GAT_GOUT_BLK_HSI0_UID_SSMT_USB_IPCLKPORT_PCLK, + 21, CLK_IGNORE_UNUSED, 0), + /* TODO: should have a driver for this */ + GATE(CLK_GOUT_HSI0_SYSMMU_USB_CLK_S2, + "gout_hsi0_sysmmu_usb_clk_s2", "mout_hsi0_bus", + CLK_CON_GAT_GOUT_BLK_HSI0_UID_SYSMMU_USB_IPCLKPORT_CLK_S2, + 21, CLK_IGNORE_UNUSED, 0), + GATE(CLK_GOUT_HSI0_SYSREG_HSI0_PCLK, + "gout_hsi0_sysreg_hsi0_pclk", "mout_hsi0_bus", + CLK_CON_GAT_GOUT_BLK_HSI0_UID_SYSREG_HSI0_IPCLKPORT_PCLK, + 21, 0, 0), + GATE(CLK_GOUT_HSI0_UASC_HSI0_CTRL_ACLK, + "gout_hsi0_uasc_hsi0_ctrl_aclk", "mout_hsi0_bus", + CLK_CON_GAT_GOUT_BLK_HSI0_UID_UASC_HSI0_CTRL_IPCLKPORT_ACLK, + 21, 0, 0), + GATE(CLK_GOUT_HSI0_UASC_HSI0_CTRL_PCLK, + "gout_hsi0_uasc_hsi0_ctrl_pclk", "mout_hsi0_bus", + CLK_CON_GAT_GOUT_BLK_HSI0_UID_UASC_HSI0_CTRL_IPCLKPORT_PCLK, + 21, 0, 0), + GATE(CLK_GOUT_HSI0_UASC_HSI0_LINK_ACLK, + "gout_hsi0_uasc_hsi0_link_aclk", "mout_hsi0_bus", + CLK_CON_GAT_GOUT_BLK_HSI0_UID_UASC_HSI0_LINK_IPCLKPORT_ACLK, + 21, 0, 0), + GATE(CLK_GOUT_HSI0_UASC_HSI0_LINK_PCLK, + "gout_hsi0_uasc_hsi0_link_pclk", "mout_hsi0_bus", + CLK_CON_GAT_GOUT_BLK_HSI0_UID_UASC_HSI0_LINK_IPCLKPORT_PCLK, + 21, 0, 0), + GATE(CLK_GOUT_HSI0_USB31DRD_ACLK_PHYCTRL, + "gout_hsi0_usb31drd_aclk_phyctrl", "mout_hsi0_bus", + CLK_CON_GAT_GOUT_BLK_HSI0_UID_USB31DRD_IPCLKPORT_ACLK_PHYCTRL, + 21, 0, 0), + GATE(CLK_GOUT_HSI0_USB31DRD_BUS_CLK_EARLY, + "gout_hsi0_usb31drd_bus_clk_early", "mout_hsi0_bus", + CLK_CON_GAT_GOUT_BLK_HSI0_UID_USB31DRD_IPCLKPORT_BUS_CLK_EARLY, + 21, 0, 0), + GATE(CLK_GOUT_HSI0_USB31DRD_I_USB20_PHY_REFCLK_26, + "gout_hsi0_usb31drd_i_usb20_phy_refclk_26", "mout_hsi0_usb20_ref", + CLK_CON_GAT_GOUT_BLK_HSI0_UID_USB31DRD_IPCLKPORT_I_USB20_PHY_REFCLK_26, + 21, 0, 0), + GATE(CLK_GOUT_HSI0_USB31DRD_I_USB31DRD_REF_CLK_40, + "gout_hsi0_usb31drd_i_usb31drd_ref_clk_40", "mout_hsi0_usb31drd", + CLK_CON_GAT_GOUT_BLK_HSI0_UID_USB31DRD_IPCLKPORT_I_USB31DRD_REF_CLK_40, + 21, 0, 0), + GATE(CLK_GOUT_HSI0_USB31DRD_I_USBDPPHY_REF_SOC_PLL, + "gout_hsi0_usb31drd_i_usbdpphy_ref_soc_pll", + "mout_hsi0_usbdpdbg_user", + CLK_CON_GAT_GOUT_BLK_HSI0_UID_USB31DRD_IPCLKPORT_I_USBDPPHY_REF_SOC_PLL, + 21, 0, 0), + GATE(CLK_GOUT_HSI0_USB31DRD_I_USBDPPHY_SCL_APB_PCLK, + "gout_hsi0_usb31drd_i_usbdpphy_scl_apb_pclk", "mout_hsi0_bus", + CLK_CON_GAT_GOUT_BLK_HSI0_UID_USB31DRD_IPCLKPORT_I_USBDPPHY_SCL_APB_PCLK, + 21, 0, 0), + GATE(CLK_GOUT_HSI0_USB31DRD_I_USBPCS_APB_CLK, + "gout_hsi0_usb31drd_i_usbpcs_apb_clk", "mout_hsi0_bus", + CLK_CON_GAT_GOUT_BLK_HSI0_UID_USB31DRD_IPCLKPORT_I_USBPCS_APB_CLK, + 21, 0, 0), + GATE(CLK_GOUT_HSI0_USB31DRD_USBDPPHY_I_ACLK, + "gout_hsi0_usb31drd_usbdpphy_i_aclk", "mout_hsi0_bus", + CLK_CON_GAT_GOUT_BLK_HSI0_UID_USB31DRD_IPCLKPORT_USBDPPHY_I_ACLK, + 21, 0, 0), + GATE(CLK_GOUT_HSI0_USB31DRD_USBDPPHY_UDBG_I_APB_PCLK, + "gout_hsi0_usb31drd_usbdpphy_udbg_i_apb_pclk", "mout_hsi0_bus", + CLK_CON_GAT_GOUT_BLK_HSI0_UID_USB31DRD_IPCLKPORT_USBDPPHY_UDBG_I_APB_PCLK, + 21, 0, 0), + /* TODO: should have a driver for this */ + GATE(CLK_GOUT_HSI0_XIU_D0_HSI0_ACLK, + "gout_hsi0_xiu_d0_hsi0_aclk", "mout_hsi0_bus", + CLK_CON_GAT_GOUT_BLK_HSI0_UID_XIU_D0_HSI0_IPCLKPORT_ACLK, + 21, CLK_IGNORE_UNUSED, 0), + /* TODO: should have a driver for this */ + GATE(CLK_GOUT_HSI0_XIU_D1_HSI0_ACLK, + "gout_hsi0_xiu_d1_hsi0_aclk", "mout_hsi0_bus", + CLK_CON_GAT_GOUT_BLK_HSI0_UID_XIU_D1_HSI0_IPCLKPORT_ACLK, + 21, CLK_IGNORE_UNUSED, 0), + /* TODO: should have a driver for this */ + GATE(CLK_GOUT_HSI0_XIU_P_HSI0_ACLK, + "gout_hsi0_xiu_p_hsi0_aclk", "mout_hsi0_bus", + CLK_CON_GAT_GOUT_BLK_HSI0_UID_XIU_P_HSI0_IPCLKPORT_ACLK, + 21, CLK_IGNORE_UNUSED, 0), +}; + +static const struct samsung_fixed_rate_clock hsi0_fixed_clks[] __initconst = { + FRATE(0, "tcxo_hsi1_hsi0", NULL, 0, 26000000), + FRATE(0, "usb20phy_phy_clock", NULL, 0, 120000000), + /* until we implement APMGSA */ + FRATE(0, "ioclk_clk_hsi0_alt", NULL, 0, 213000000), +}; + +static const struct samsung_cmu_info hsi0_cmu_info __initconst = { + .pll_clks = cmu_hsi0_pll_clks, + .nr_pll_clks = ARRAY_SIZE(cmu_hsi0_pll_clks), + .mux_clks = hsi0_mux_clks, + .nr_mux_clks = ARRAY_SIZE(hsi0_mux_clks), + .div_clks = hsi0_div_clks, + .nr_div_clks = ARRAY_SIZE(hsi0_div_clks), + .gate_clks = hsi0_gate_clks, + .nr_gate_clks = ARRAY_SIZE(hsi0_gate_clks), + .fixed_clks = hsi0_fixed_clks, + .nr_fixed_clks = ARRAY_SIZE(hsi0_fixed_clks), + .nr_clk_ids = CLKS_NR_HSI0, + .clk_regs = hsi0_clk_regs, + .nr_clk_regs = ARRAY_SIZE(hsi0_clk_regs), + .clk_name = "bus", +}; + /* ---- CMU_MISC ------------------------------------------------------------ */ /* Register Offset definitions for CMU_MISC (0x10010000) */ @@ -3441,6 +3907,9 @@ static const struct of_device_id gs101_cmu_of_match[] = { { .compatible = "google,gs101-cmu-apm", .data = &apm_cmu_info, + }, { + .compatible = "google,gs101-cmu-hsi0", + .data = &hsi0_cmu_info, }, { .compatible = "google,gs101-cmu-peric0", .data = &peric0_cmu_info, From 093c290084a494844f1650e70755b8912292ee14 Mon Sep 17 00:00:00 2001 From: Peter Griffin Date: Mon, 29 Apr 2024 14:02:19 +0100 Subject: [PATCH 100/118] clk: samsung: gs101: add support for cmu_hsi2 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit CMU_HSI2 is the clock management unit used for the hsi2 block. HSI stands for High Speed Interface and as such it generates clocks for PCIe, UFS and MMC card. This patch adds support for the muxes, dividers, and gates in cmu_hsi2. The following clocks are marked CLK_IS_CRITICAL as disabling them results in an immediate system hang. CLK_GOUT_HSI2_HSI2_CMU_HSI2_PCLK CLK_GOUT_HSI2_LHM_AXI_P_HSI2_I_CLK The following clocks are marked CLK_IGNORE_UNUSED as they are needed for UFS to be functional. CLK_GOUT_HSI2_SSMT_HSI2_ACLK CLK_GOUT_HSI2_SSMT_HSI2_PCLK CLK_GOUT_HSI2_LHS_ACEL_D_HSI2_I_CLK CLK_GOUT_HSI2_SYSMMU_HSI2_CLK_S2 CLK_GOUT_HSI2_XIU_D_HSI2_ACLK CLK_GOUT_HSI2_XIU_P_HSI2_ACLK CLK_GOUT_HSI2_GPIO_HSI2_PCLK is marked CLK_IGNORE_UNUSED until the exynos pinctrl clock patches land then it can be removed. Some clocks in this unit have very long names. To help with this the clock name mangling strategy was updated to include removing the following sub-strings. - G4X2_DWC_PCIE_CTL_ - G4X1_DWC_PCIE_CTL_ - PCIE_SUB_CTRL_ - INST_0_ - LN05LPE_ - TM_WRAPPER_ - SF_ Signed-off-by: Peter Griffin [AD: resolve merge conflicts] Signed-off-by: André Draszik Reviewed-by: André Draszik Link: https://lore.kernel.org/r/20240429-hsi0-gs101-v3-3-f233be0a2455@linaro.org Signed-off-by: Krzysztof Kozlowski --- drivers/clk/samsung/clk-gs101.c | 507 ++++++++++++++++++++++++++++++++ 1 file changed, 507 insertions(+) diff --git a/drivers/clk/samsung/clk-gs101.c b/drivers/clk/samsung/clk-gs101.c index ce0ff35f4548..05129c3b2f68 100644 --- a/drivers/clk/samsung/clk-gs101.c +++ b/drivers/clk/samsung/clk-gs101.c @@ -21,6 +21,7 @@ #define CLKS_NR_TOP (CLK_GOUT_CMU_TPU_UART + 1) #define CLKS_NR_APM (CLK_APM_PLL_DIV16_APM + 1) #define CLKS_NR_HSI0 (CLK_GOUT_HSI0_XIU_P_HSI0_ACLK + 1) +#define CLKS_NR_HSI2 (CLK_GOUT_HSI2_XIU_P_HSI2_ACLK + 1) #define CLKS_NR_MISC (CLK_GOUT_MISC_XIU_D_MISC_ACLK + 1) #define CLKS_NR_PERIC0 (CLK_GOUT_PERIC0_SYSREG_PERIC0_PCLK + 1) #define CLKS_NR_PERIC1 (CLK_GOUT_PERIC1_SYSREG_PERIC1_PCLK + 1) @@ -2385,6 +2386,509 @@ static const struct samsung_cmu_info hsi0_cmu_info __initconst = { .clk_name = "bus", }; +/* ---- CMU_HSI2 ------------------------------------------------------------ */ + +/* Register Offset definitions for CMU_HSI2 (0x14400000) */ +#define PLL_CON0_MUX_CLKCMU_HSI2_BUS_USER 0x0600 +#define PLL_CON1_MUX_CLKCMU_HSI2_BUS_USER 0x0604 +#define PLL_CON0_MUX_CLKCMU_HSI2_MMC_CARD_USER 0x0610 +#define PLL_CON1_MUX_CLKCMU_HSI2_MMC_CARD_USER 0x0614 +#define PLL_CON0_MUX_CLKCMU_HSI2_PCIE_USER 0x0620 +#define PLL_CON1_MUX_CLKCMU_HSI2_PCIE_USER 0x0624 +#define PLL_CON0_MUX_CLKCMU_HSI2_UFS_EMBD_USER 0x0630 +#define PLL_CON1_MUX_CLKCMU_HSI2_UFS_EMBD_USER 0x0634 +#define HSI2_CMU_HSI2_CONTROLLER_OPTION 0x0800 +#define CLKOUT_CON_BLK_HSI2_CMU_HSI2_CLKOUT0 0x0810 +#define CLK_CON_GAT_CLK_BLK_HSI2_UID_PCIE_GEN4_1_IPCLKPORT_PCIE_003_PCIE_SUB_CTRL_INST_0_PHY_REFCLK_IN 0x2000 +#define CLK_CON_GAT_CLK_BLK_HSI2_UID_PCIE_GEN4_1_IPCLKPORT_PCIE_004_PCIE_SUB_CTRL_INST_0_PHY_REFCLK_IN 0x2004 +#define CLK_CON_GAT_CLK_BLK_HSI2_UID_SSMT_PCIE_IA_GEN4A_1_IPCLKPORT_ACLK 0x2008 +#define CLK_CON_GAT_CLK_BLK_HSI2_UID_SSMT_PCIE_IA_GEN4A_1_IPCLKPORT_PCLK 0x200c +#define CLK_CON_GAT_CLK_BLK_HSI2_UID_SSMT_PCIE_IA_GEN4B_1_IPCLKPORT_ACLK 0x2010 +#define CLK_CON_GAT_CLK_BLK_HSI2_UID_SSMT_PCIE_IA_GEN4B_1_IPCLKPORT_PCLK 0x2014 +#define CLK_CON_GAT_GOUT_BLK_HSI2_UID_D_TZPC_HSI2_IPCLKPORT_PCLK 0x201c +#define CLK_CON_GAT_GOUT_BLK_HSI2_UID_GPC_HSI2_IPCLKPORT_PCLK 0x2020 +#define CLK_CON_GAT_GOUT_BLK_HSI2_UID_GPIO_HSI2_IPCLKPORT_PCLK 0x2024 +#define CLK_CON_GAT_GOUT_BLK_HSI2_UID_HSI2_CMU_HSI2_IPCLKPORT_PCLK 0x2028 +#define CLK_CON_GAT_GOUT_BLK_HSI2_UID_LHM_AXI_P_HSI2_IPCLKPORT_I_CLK 0x202c +#define CLK_CON_GAT_GOUT_BLK_HSI2_UID_LHS_ACEL_D_HSI2_IPCLKPORT_I_CLK 0x2030 +#define CLK_CON_GAT_GOUT_BLK_HSI2_UID_MMC_CARD_IPCLKPORT_I_ACLK 0x2034 +#define CLK_CON_GAT_GOUT_BLK_HSI2_UID_MMC_CARD_IPCLKPORT_SDCLKIN 0x2038 +#define CLK_CON_GAT_GOUT_BLK_HSI2_UID_PCIE_GEN4_1_IPCLKPORT_PCIE_003_G4X2_DWC_PCIE_CTL_INST_0_DBI_ACLK_UG 0x203c +#define CLK_CON_GAT_GOUT_BLK_HSI2_UID_PCIE_GEN4_1_IPCLKPORT_PCIE_003_G4X2_DWC_PCIE_CTL_INST_0_MSTR_ACLK_UG 0x2040 +#define CLK_CON_GAT_GOUT_BLK_HSI2_UID_PCIE_GEN4_1_IPCLKPORT_PCIE_003_G4X2_DWC_PCIE_CTL_INST_0_SLV_ACLK_UG 0x2044 +#define CLK_CON_GAT_GOUT_BLK_HSI2_UID_PCIE_GEN4_1_IPCLKPORT_PCIE_003_PCIE_SUB_CTRL_INST_0_I_DRIVER_APB_CLK 0x2048 +#define CLK_CON_GAT_GOUT_BLK_HSI2_UID_PCIE_GEN4_1_IPCLKPORT_PCIE_004_G4X1_DWC_PCIE_CTL_INST_0_DBI_ACLK_UG 0x204c +#define CLK_CON_GAT_GOUT_BLK_HSI2_UID_PCIE_GEN4_1_IPCLKPORT_PCIE_004_G4X1_DWC_PCIE_CTL_INST_0_MSTR_ACLK_UG 0x2050 +#define CLK_CON_GAT_GOUT_BLK_HSI2_UID_PCIE_GEN4_1_IPCLKPORT_PCIE_004_G4X1_DWC_PCIE_CTL_INST_0_SLV_ACLK_UG 0x2054 +#define CLK_CON_GAT_GOUT_BLK_HSI2_UID_PCIE_GEN4_1_IPCLKPORT_PCIE_004_PCIE_SUB_CTRL_INST_0_I_DRIVER_APB_CLK 0x2058 +#define CLK_CON_GAT_GOUT_BLK_HSI2_UID_PCIE_GEN4_1_IPCLKPORT_PCS_PMA_INST_0_PHY_UDBG_I_APB_PCLK 0x205c +#define CLK_CON_GAT_GOUT_BLK_HSI2_UID_PCIE_GEN4_1_IPCLKPORT_PCS_PMA_INST_0_PIPE_PAL_PCIE_INST_0_I_APB_PCLK 0x2060 +#define CLK_CON_GAT_GOUT_BLK_HSI2_UID_PCIE_GEN4_1_IPCLKPORT_PCS_PMA_INST_0_SF_PCIEPHY210X2_LN05LPE_QCH_TM_WRAPPER_INST_0_I_APB_PCLK 0x2064 +#define CLK_CON_GAT_GOUT_BLK_HSI2_UID_PCIE_IA_GEN4A_1_IPCLKPORT_I_CLK 0x2068 +#define CLK_CON_GAT_GOUT_BLK_HSI2_UID_PCIE_IA_GEN4B_1_IPCLKPORT_I_CLK 0x206c +#define CLK_CON_GAT_GOUT_BLK_HSI2_UID_PPMU_HSI2_IPCLKPORT_ACLK 0x2070 +#define CLK_CON_GAT_GOUT_BLK_HSI2_UID_PPMU_HSI2_IPCLKPORT_PCLK 0x2074 +#define CLK_CON_GAT_GOUT_BLK_HSI2_UID_QE_MMC_CARD_HSI2_IPCLKPORT_ACLK 0x2078 +#define CLK_CON_GAT_GOUT_BLK_HSI2_UID_QE_MMC_CARD_HSI2_IPCLKPORT_PCLK 0x207c +#define CLK_CON_GAT_GOUT_BLK_HSI2_UID_QE_PCIE_GEN4A_HSI2_IPCLKPORT_ACLK 0x2080 +#define CLK_CON_GAT_GOUT_BLK_HSI2_UID_QE_PCIE_GEN4A_HSI2_IPCLKPORT_PCLK 0x2084 +#define CLK_CON_GAT_GOUT_BLK_HSI2_UID_QE_PCIE_GEN4B_HSI2_IPCLKPORT_ACLK 0x2088 +#define CLK_CON_GAT_GOUT_BLK_HSI2_UID_QE_PCIE_GEN4B_HSI2_IPCLKPORT_PCLK 0x208c +#define CLK_CON_GAT_GOUT_BLK_HSI2_UID_QE_UFS_EMBD_HSI2_IPCLKPORT_ACLK 0x2090 +#define CLK_CON_GAT_GOUT_BLK_HSI2_UID_QE_UFS_EMBD_HSI2_IPCLKPORT_PCLK 0x2094 +#define CLK_CON_GAT_GOUT_BLK_HSI2_UID_RSTNSYNC_CLK_HSI2_BUS_IPCLKPORT_CLK 0x2098 +#define CLK_CON_GAT_GOUT_BLK_HSI2_UID_RSTNSYNC_CLK_HSI2_OSCCLK_IPCLKPORT_CLK 0x209c +#define CLK_CON_GAT_GOUT_BLK_HSI2_UID_SSMT_HSI2_IPCLKPORT_ACLK 0x20a0 +#define CLK_CON_GAT_GOUT_BLK_HSI2_UID_SSMT_HSI2_IPCLKPORT_PCLK 0x20a4 +#define CLK_CON_GAT_GOUT_BLK_HSI2_UID_SYSMMU_HSI2_IPCLKPORT_CLK_S2 0x20a8 +#define CLK_CON_GAT_GOUT_BLK_HSI2_UID_SYSREG_HSI2_IPCLKPORT_PCLK 0x20ac +#define CLK_CON_GAT_GOUT_BLK_HSI2_UID_UASC_PCIE_GEN4A_DBI_1_IPCLKPORT_ACLK 0x20b0 +#define CLK_CON_GAT_GOUT_BLK_HSI2_UID_UASC_PCIE_GEN4A_DBI_1_IPCLKPORT_PCLK 0x20b4 +#define CLK_CON_GAT_GOUT_BLK_HSI2_UID_UASC_PCIE_GEN4A_SLV_1_IPCLKPORT_ACLK 0x20b8 +#define CLK_CON_GAT_GOUT_BLK_HSI2_UID_UASC_PCIE_GEN4A_SLV_1_IPCLKPORT_PCLK 0x20bc +#define CLK_CON_GAT_GOUT_BLK_HSI2_UID_UASC_PCIE_GEN4B_DBI_1_IPCLKPORT_ACLK 0x20c0 +#define CLK_CON_GAT_GOUT_BLK_HSI2_UID_UASC_PCIE_GEN4B_DBI_1_IPCLKPORT_PCLK 0x20c4 +#define CLK_CON_GAT_GOUT_BLK_HSI2_UID_UASC_PCIE_GEN4B_SLV_1_IPCLKPORT_ACLK 0x20c8 +#define CLK_CON_GAT_GOUT_BLK_HSI2_UID_UASC_PCIE_GEN4B_SLV_1_IPCLKPORT_PCLK 0x20cc +#define CLK_CON_GAT_GOUT_BLK_HSI2_UID_UFS_EMBD_IPCLKPORT_I_ACLK 0x20d0 +#define CLK_CON_GAT_GOUT_BLK_HSI2_UID_UFS_EMBD_IPCLKPORT_I_CLK_UNIPRO 0x20d4 +#define CLK_CON_GAT_GOUT_BLK_HSI2_UID_UFS_EMBD_IPCLKPORT_I_FMP_CLK 0x20d8 +#define CLK_CON_GAT_GOUT_BLK_HSI2_UID_XIU_D_HSI2_IPCLKPORT_ACLK 0x20dc +#define CLK_CON_GAT_GOUT_BLK_HSI2_UID_XIU_P_HSI2_IPCLKPORT_ACLK 0x20e0 +#define DMYQCH_CON_PCIE_GEN4_1_QCH_SCLK_1 0x3000 +#define PCH_CON_LHM_AXI_P_HSI2_PCH 0x3008 +#define PCH_CON_LHS_ACEL_D_HSI2_PCH 0x300c +#define QCH_CON_D_TZPC_HSI2_QCH 0x3010 +#define QCH_CON_GPC_HSI2_QCH 0x3014 +#define QCH_CON_GPIO_HSI2_QCH 0x3018 +#define QCH_CON_HSI2_CMU_HSI2_QCH 0x301c +#define QCH_CON_LHM_AXI_P_HSI2_QCH 0x3020 +#define QCH_CON_LHS_ACEL_D_HSI2_QCH 0x3024 +#define QCH_CON_MMC_CARD_QCH 0x3028 +#define QCH_CON_PCIE_GEN4_1_QCH_APB_1 0x302c +#define QCH_CON_PCIE_GEN4_1_QCH_APB_2 0x3030 +#define QCH_CON_PCIE_GEN4_1_QCH_AXI_1 0x3034 +#define QCH_CON_PCIE_GEN4_1_QCH_AXI_2 0x3038 +#define QCH_CON_PCIE_GEN4_1_QCH_DBG_1 0x303c +#define QCH_CON_PCIE_GEN4_1_QCH_DBG_2 0x3040 +#define QCH_CON_PCIE_GEN4_1_QCH_PCS_APB 0x3044 +#define QCH_CON_PCIE_GEN4_1_QCH_PMA_APB 0x3048 +#define QCH_CON_PCIE_GEN4_1_QCH_UDBG 0x304c +#define QCH_CON_PCIE_IA_GEN4A_1_QCH 0x3050 +#define QCH_CON_PCIE_IA_GEN4B_1_QCH 0x3054 +#define QCH_CON_PPMU_HSI2_QCH 0x3058 +#define QCH_CON_QE_MMC_CARD_HSI2_QCH 0x305c +#define QCH_CON_QE_PCIE_GEN4A_HSI2_QCH 0x3060 +#define QCH_CON_QE_PCIE_GEN4B_HSI2_QCH 0x3064 +#define QCH_CON_QE_UFS_EMBD_HSI2_QCH 0x3068 +#define QCH_CON_SSMT_HSI2_QCH 0x306c +#define QCH_CON_SSMT_PCIE_IA_GEN4A_1_QCH 0x3070 +#define QCH_CON_SSMT_PCIE_IA_GEN4B_1_QCH 0x3074 +#define QCH_CON_SYSMMU_HSI2_QCH 0x3078 +#define QCH_CON_SYSREG_HSI2_QCH 0x307c +#define QCH_CON_UASC_PCIE_GEN4A_DBI_1_QCH 0x3080 +#define QCH_CON_UASC_PCIE_GEN4A_SLV_1_QCH 0x3084 +#define QCH_CON_UASC_PCIE_GEN4B_DBI_1_QCH 0x3088 +#define QCH_CON_UASC_PCIE_GEN4B_SLV_1_QCH 0x308c +#define QCH_CON_UFS_EMBD_QCH 0x3090 +#define QCH_CON_UFS_EMBD_QCH_FMP 0x3094 +#define QUEUE_CTRL_REG_BLK_HSI2_CMU_HSI2 0x3c00 + +static const unsigned long cmu_hsi2_clk_regs[] __initconst = { + PLL_CON0_MUX_CLKCMU_HSI2_BUS_USER, + PLL_CON1_MUX_CLKCMU_HSI2_BUS_USER, + PLL_CON0_MUX_CLKCMU_HSI2_MMC_CARD_USER, + PLL_CON1_MUX_CLKCMU_HSI2_MMC_CARD_USER, + PLL_CON0_MUX_CLKCMU_HSI2_PCIE_USER, + PLL_CON1_MUX_CLKCMU_HSI2_PCIE_USER, + PLL_CON0_MUX_CLKCMU_HSI2_UFS_EMBD_USER, + PLL_CON1_MUX_CLKCMU_HSI2_UFS_EMBD_USER, + HSI2_CMU_HSI2_CONTROLLER_OPTION, + CLKOUT_CON_BLK_HSI2_CMU_HSI2_CLKOUT0, + CLK_CON_GAT_CLK_BLK_HSI2_UID_PCIE_GEN4_1_IPCLKPORT_PCIE_003_PCIE_SUB_CTRL_INST_0_PHY_REFCLK_IN, + CLK_CON_GAT_CLK_BLK_HSI2_UID_PCIE_GEN4_1_IPCLKPORT_PCIE_004_PCIE_SUB_CTRL_INST_0_PHY_REFCLK_IN, + CLK_CON_GAT_CLK_BLK_HSI2_UID_SSMT_PCIE_IA_GEN4A_1_IPCLKPORT_ACLK, + CLK_CON_GAT_CLK_BLK_HSI2_UID_SSMT_PCIE_IA_GEN4A_1_IPCLKPORT_PCLK, + CLK_CON_GAT_CLK_BLK_HSI2_UID_SSMT_PCIE_IA_GEN4B_1_IPCLKPORT_ACLK, + CLK_CON_GAT_CLK_BLK_HSI2_UID_SSMT_PCIE_IA_GEN4B_1_IPCLKPORT_PCLK, + CLK_CON_GAT_GOUT_BLK_HSI2_UID_D_TZPC_HSI2_IPCLKPORT_PCLK, + CLK_CON_GAT_GOUT_BLK_HSI2_UID_GPC_HSI2_IPCLKPORT_PCLK, + CLK_CON_GAT_GOUT_BLK_HSI2_UID_GPIO_HSI2_IPCLKPORT_PCLK, + CLK_CON_GAT_GOUT_BLK_HSI2_UID_HSI2_CMU_HSI2_IPCLKPORT_PCLK, + CLK_CON_GAT_GOUT_BLK_HSI2_UID_LHM_AXI_P_HSI2_IPCLKPORT_I_CLK, + CLK_CON_GAT_GOUT_BLK_HSI2_UID_LHS_ACEL_D_HSI2_IPCLKPORT_I_CLK, + CLK_CON_GAT_GOUT_BLK_HSI2_UID_MMC_CARD_IPCLKPORT_I_ACLK, + CLK_CON_GAT_GOUT_BLK_HSI2_UID_MMC_CARD_IPCLKPORT_SDCLKIN, + CLK_CON_GAT_GOUT_BLK_HSI2_UID_PCIE_GEN4_1_IPCLKPORT_PCIE_003_G4X2_DWC_PCIE_CTL_INST_0_DBI_ACLK_UG, + CLK_CON_GAT_GOUT_BLK_HSI2_UID_PCIE_GEN4_1_IPCLKPORT_PCIE_003_G4X2_DWC_PCIE_CTL_INST_0_MSTR_ACLK_UG, + CLK_CON_GAT_GOUT_BLK_HSI2_UID_PCIE_GEN4_1_IPCLKPORT_PCIE_003_G4X2_DWC_PCIE_CTL_INST_0_SLV_ACLK_UG, + CLK_CON_GAT_GOUT_BLK_HSI2_UID_PCIE_GEN4_1_IPCLKPORT_PCIE_003_PCIE_SUB_CTRL_INST_0_I_DRIVER_APB_CLK, + CLK_CON_GAT_GOUT_BLK_HSI2_UID_PCIE_GEN4_1_IPCLKPORT_PCIE_004_G4X1_DWC_PCIE_CTL_INST_0_DBI_ACLK_UG, + CLK_CON_GAT_GOUT_BLK_HSI2_UID_PCIE_GEN4_1_IPCLKPORT_PCIE_004_G4X1_DWC_PCIE_CTL_INST_0_MSTR_ACLK_UG, + CLK_CON_GAT_GOUT_BLK_HSI2_UID_PCIE_GEN4_1_IPCLKPORT_PCIE_004_G4X1_DWC_PCIE_CTL_INST_0_SLV_ACLK_UG, + CLK_CON_GAT_GOUT_BLK_HSI2_UID_PCIE_GEN4_1_IPCLKPORT_PCIE_004_PCIE_SUB_CTRL_INST_0_I_DRIVER_APB_CLK, + CLK_CON_GAT_GOUT_BLK_HSI2_UID_PCIE_GEN4_1_IPCLKPORT_PCS_PMA_INST_0_PHY_UDBG_I_APB_PCLK, + CLK_CON_GAT_GOUT_BLK_HSI2_UID_PCIE_GEN4_1_IPCLKPORT_PCS_PMA_INST_0_PIPE_PAL_PCIE_INST_0_I_APB_PCLK, + CLK_CON_GAT_GOUT_BLK_HSI2_UID_PCIE_GEN4_1_IPCLKPORT_PCS_PMA_INST_0_SF_PCIEPHY210X2_LN05LPE_QCH_TM_WRAPPER_INST_0_I_APB_PCLK, + CLK_CON_GAT_GOUT_BLK_HSI2_UID_PCIE_IA_GEN4A_1_IPCLKPORT_I_CLK, + CLK_CON_GAT_GOUT_BLK_HSI2_UID_PCIE_IA_GEN4B_1_IPCLKPORT_I_CLK, + CLK_CON_GAT_GOUT_BLK_HSI2_UID_PPMU_HSI2_IPCLKPORT_ACLK, + CLK_CON_GAT_GOUT_BLK_HSI2_UID_PPMU_HSI2_IPCLKPORT_PCLK, + CLK_CON_GAT_GOUT_BLK_HSI2_UID_QE_MMC_CARD_HSI2_IPCLKPORT_ACLK, + CLK_CON_GAT_GOUT_BLK_HSI2_UID_QE_MMC_CARD_HSI2_IPCLKPORT_PCLK, + CLK_CON_GAT_GOUT_BLK_HSI2_UID_QE_PCIE_GEN4A_HSI2_IPCLKPORT_ACLK, + CLK_CON_GAT_GOUT_BLK_HSI2_UID_QE_PCIE_GEN4A_HSI2_IPCLKPORT_PCLK, + CLK_CON_GAT_GOUT_BLK_HSI2_UID_QE_PCIE_GEN4B_HSI2_IPCLKPORT_ACLK, + CLK_CON_GAT_GOUT_BLK_HSI2_UID_QE_PCIE_GEN4B_HSI2_IPCLKPORT_PCLK, + CLK_CON_GAT_GOUT_BLK_HSI2_UID_QE_UFS_EMBD_HSI2_IPCLKPORT_ACLK, + CLK_CON_GAT_GOUT_BLK_HSI2_UID_QE_UFS_EMBD_HSI2_IPCLKPORT_PCLK, + CLK_CON_GAT_GOUT_BLK_HSI2_UID_RSTNSYNC_CLK_HSI2_BUS_IPCLKPORT_CLK, + CLK_CON_GAT_GOUT_BLK_HSI2_UID_RSTNSYNC_CLK_HSI2_OSCCLK_IPCLKPORT_CLK, + CLK_CON_GAT_GOUT_BLK_HSI2_UID_SSMT_HSI2_IPCLKPORT_ACLK, + CLK_CON_GAT_GOUT_BLK_HSI2_UID_SSMT_HSI2_IPCLKPORT_PCLK, + CLK_CON_GAT_GOUT_BLK_HSI2_UID_SYSMMU_HSI2_IPCLKPORT_CLK_S2, + CLK_CON_GAT_GOUT_BLK_HSI2_UID_SYSREG_HSI2_IPCLKPORT_PCLK, + CLK_CON_GAT_GOUT_BLK_HSI2_UID_UASC_PCIE_GEN4A_DBI_1_IPCLKPORT_ACLK, + CLK_CON_GAT_GOUT_BLK_HSI2_UID_UASC_PCIE_GEN4A_DBI_1_IPCLKPORT_PCLK, + CLK_CON_GAT_GOUT_BLK_HSI2_UID_UASC_PCIE_GEN4A_SLV_1_IPCLKPORT_ACLK, + CLK_CON_GAT_GOUT_BLK_HSI2_UID_UASC_PCIE_GEN4A_SLV_1_IPCLKPORT_PCLK, + CLK_CON_GAT_GOUT_BLK_HSI2_UID_UASC_PCIE_GEN4B_DBI_1_IPCLKPORT_ACLK, + CLK_CON_GAT_GOUT_BLK_HSI2_UID_UASC_PCIE_GEN4B_DBI_1_IPCLKPORT_PCLK, + CLK_CON_GAT_GOUT_BLK_HSI2_UID_UASC_PCIE_GEN4B_SLV_1_IPCLKPORT_ACLK, + CLK_CON_GAT_GOUT_BLK_HSI2_UID_UASC_PCIE_GEN4B_SLV_1_IPCLKPORT_PCLK, + CLK_CON_GAT_GOUT_BLK_HSI2_UID_UFS_EMBD_IPCLKPORT_I_ACLK, + CLK_CON_GAT_GOUT_BLK_HSI2_UID_UFS_EMBD_IPCLKPORT_I_CLK_UNIPRO, + CLK_CON_GAT_GOUT_BLK_HSI2_UID_UFS_EMBD_IPCLKPORT_I_FMP_CLK, + CLK_CON_GAT_GOUT_BLK_HSI2_UID_XIU_D_HSI2_IPCLKPORT_ACLK, + CLK_CON_GAT_GOUT_BLK_HSI2_UID_XIU_P_HSI2_IPCLKPORT_ACLK, + DMYQCH_CON_PCIE_GEN4_1_QCH_SCLK_1, + PCH_CON_LHM_AXI_P_HSI2_PCH, + PCH_CON_LHS_ACEL_D_HSI2_PCH, + QCH_CON_D_TZPC_HSI2_QCH, + QCH_CON_GPC_HSI2_QCH, + QCH_CON_GPIO_HSI2_QCH, + QCH_CON_HSI2_CMU_HSI2_QCH, + QCH_CON_LHM_AXI_P_HSI2_QCH, + QCH_CON_LHS_ACEL_D_HSI2_QCH, + QCH_CON_MMC_CARD_QCH, + QCH_CON_PCIE_GEN4_1_QCH_APB_1, + QCH_CON_PCIE_GEN4_1_QCH_APB_2, + QCH_CON_PCIE_GEN4_1_QCH_AXI_1, + QCH_CON_PCIE_GEN4_1_QCH_AXI_2, + QCH_CON_PCIE_GEN4_1_QCH_DBG_1, + QCH_CON_PCIE_GEN4_1_QCH_DBG_2, + QCH_CON_PCIE_GEN4_1_QCH_PCS_APB, + QCH_CON_PCIE_GEN4_1_QCH_PMA_APB, + QCH_CON_PCIE_GEN4_1_QCH_UDBG, + QCH_CON_PCIE_IA_GEN4A_1_QCH, + QCH_CON_PCIE_IA_GEN4B_1_QCH, + QCH_CON_PPMU_HSI2_QCH, + QCH_CON_QE_MMC_CARD_HSI2_QCH, + QCH_CON_QE_PCIE_GEN4A_HSI2_QCH, + QCH_CON_QE_PCIE_GEN4B_HSI2_QCH, + QCH_CON_QE_UFS_EMBD_HSI2_QCH, + QCH_CON_SSMT_HSI2_QCH, + QCH_CON_SSMT_PCIE_IA_GEN4A_1_QCH, + QCH_CON_SSMT_PCIE_IA_GEN4B_1_QCH, + QCH_CON_SYSMMU_HSI2_QCH, + QCH_CON_SYSREG_HSI2_QCH, + QCH_CON_UASC_PCIE_GEN4A_DBI_1_QCH, + QCH_CON_UASC_PCIE_GEN4A_SLV_1_QCH, + QCH_CON_UASC_PCIE_GEN4B_DBI_1_QCH, + QCH_CON_UASC_PCIE_GEN4B_SLV_1_QCH, + QCH_CON_UFS_EMBD_QCH, + QCH_CON_UFS_EMBD_QCH_FMP, + QUEUE_CTRL_REG_BLK_HSI2_CMU_HSI2, +}; + +PNAME(mout_hsi2_ufs_embd_p) = { "oscclk", "dout_cmu_shared0_div4", + "dout_cmu_shared2_div2", "fout_spare_pll" }; + +PNAME(mout_hsi2_pcie_p) = { "oscclk", "dout_cmu_shared2_div2" }; + +PNAME(mout_hsi2_bus_p) = { "dout_cmu_shared0_div4", + "dout_cmu_shared1_div4", + "dout_cmu_shared2_div2", + "dout_cmu_shared3_div2", + "fout_spare_pll", "oscclk", "oscclk", + "oscclk" }; + +PNAME(mout_hsi2_mmc_card_p) = { "fout_shared2_pll", "fout_shared3_pll", + "dout_cmu_shared0_div4", "fout_spare_pll" }; + +PNAME(mout_hsi2_bus_user_p) = { "oscclk", "dout_cmu_hsi2_bus" }; +PNAME(mout_hsi2_mmc_card_user_p) = { "oscclk", "dout_cmu_hsi2_mmc_card" }; +PNAME(mout_hsi2_pcie_user_p) = { "oscclk", "dout_cmu_hsi2_pcie" }; +PNAME(mout_hsi2_ufs_embd_user_p) = { "oscclk", "dout_cmu_hsi2_ufs_embd" }; + +static const struct samsung_mux_clock hsi2_mux_clks[] __initconst = { + MUX(CLK_MOUT_HSI2_BUS_USER, "mout_hsi2_bus_user", mout_hsi2_bus_user_p, + PLL_CON0_MUX_CLKCMU_HSI2_BUS_USER, 4, 1), + MUX(CLK_MOUT_HSI2_MMC_CARD_USER, "mout_hsi2_mmc_card_user", + mout_hsi2_mmc_card_user_p, PLL_CON0_MUX_CLKCMU_HSI2_MMC_CARD_USER, + 4, 1), + MUX(CLK_MOUT_HSI2_PCIE_USER, "mout_hsi2_pcie_user", + mout_hsi2_pcie_user_p, PLL_CON0_MUX_CLKCMU_HSI2_PCIE_USER, + 4, 1), + MUX(CLK_MOUT_HSI2_UFS_EMBD_USER, "mout_hsi2_ufs_embd_user", + mout_hsi2_ufs_embd_user_p, PLL_CON0_MUX_CLKCMU_HSI2_UFS_EMBD_USER, + 4, 1), +}; + +static const struct samsung_gate_clock hsi2_gate_clks[] __initconst = { + GATE(CLK_GOUT_HSI2_PCIE_GEN4_1_PCIE_003_PHY_REFCLK_IN, + "gout_hsi2_pcie_gen4_1_pcie_003_phy_refclk_in", + "mout_hsi2_pcie_user", + CLK_CON_GAT_CLK_BLK_HSI2_UID_PCIE_GEN4_1_IPCLKPORT_PCIE_003_PCIE_SUB_CTRL_INST_0_PHY_REFCLK_IN, + 21, 0, 0), + GATE(CLK_GOUT_HSI2_PCIE_GEN4_1_PCIE_004_PHY_REFCLK_IN, + "gout_hsi2_pcie_gen4_1_pcie_004_phy_refclk_in", + "mout_hsi2_pcie_user", + CLK_CON_GAT_CLK_BLK_HSI2_UID_PCIE_GEN4_1_IPCLKPORT_PCIE_004_PCIE_SUB_CTRL_INST_0_PHY_REFCLK_IN, + 21, 0, 0), + GATE(CLK_GOUT_HSI2_SSMT_PCIE_IA_GEN4A_1_ACLK, + "gout_hsi2_ssmt_pcie_ia_gen4a_1_aclk", "mout_hsi2_bus_user", + CLK_CON_GAT_CLK_BLK_HSI2_UID_SSMT_PCIE_IA_GEN4A_1_IPCLKPORT_ACLK, + 21, 0, 0), + GATE(CLK_GOUT_HSI2_SSMT_PCIE_IA_GEN4A_1_PCLK, + "gout_hsi2_ssmt_pcie_ia_gen4a_1_pclk", "mout_hsi2_bus_user", + CLK_CON_GAT_CLK_BLK_HSI2_UID_SSMT_PCIE_IA_GEN4A_1_IPCLKPORT_PCLK, + 21, 0, 0), + GATE(CLK_GOUT_HSI2_SSMT_PCIE_IA_GEN4B_1_ACLK, + "gout_hsi2_ssmt_pcie_ia_gen4b_1_aclk", "mout_hsi2_bus_user", + CLK_CON_GAT_CLK_BLK_HSI2_UID_SSMT_PCIE_IA_GEN4B_1_IPCLKPORT_ACLK, + 21, 0, 0), + GATE(CLK_GOUT_HSI2_SSMT_PCIE_IA_GEN4B_1_PCLK, + "gout_hsi2_ssmt_pcie_ia_gen4b_1_pclk", "mout_hsi2_bus_user", + CLK_CON_GAT_CLK_BLK_HSI2_UID_SSMT_PCIE_IA_GEN4B_1_IPCLKPORT_PCLK, + 21, 0, 0), + GATE(CLK_GOUT_HSI2_D_TZPC_HSI2_PCLK, + "gout_hsi2_d_tzpc_hsi2_pclk", "mout_hsi2_bus_user", + CLK_CON_GAT_GOUT_BLK_HSI2_UID_D_TZPC_HSI2_IPCLKPORT_PCLK, + 21, 0, 0), + GATE(CLK_GOUT_HSI2_GPC_HSI2_PCLK, + "gout_hsi2_gpc_hsi2_pclk", "mout_hsi2_bus_user", + CLK_CON_GAT_GOUT_BLK_HSI2_UID_GPC_HSI2_IPCLKPORT_PCLK, 21, 0, 0), + GATE(CLK_GOUT_HSI2_GPIO_HSI2_PCLK, + "gout_hsi2_gpio_hsi2_pclk", "mout_hsi2_bus_user", + CLK_CON_GAT_GOUT_BLK_HSI2_UID_GPIO_HSI2_IPCLKPORT_PCLK, 21, + CLK_IGNORE_UNUSED, 0), + /* Disabling this clock makes the system hang. Mark the clock as critical. */ + GATE(CLK_GOUT_HSI2_HSI2_CMU_HSI2_PCLK, + "gout_hsi2_hsi2_cmu_hsi2_pclk", "mout_hsi2_bus_user", + CLK_CON_GAT_GOUT_BLK_HSI2_UID_HSI2_CMU_HSI2_IPCLKPORT_PCLK, + 21, CLK_IS_CRITICAL, 0), + /* Disabling this clock makes the system hang. Mark the clock as critical. */ + GATE(CLK_GOUT_HSI2_LHM_AXI_P_HSI2_I_CLK, + "gout_hsi2_lhm_axi_p_hsi2_i_clk", "mout_hsi2_bus_user", + CLK_CON_GAT_GOUT_BLK_HSI2_UID_LHM_AXI_P_HSI2_IPCLKPORT_I_CLK, + 21, CLK_IS_CRITICAL, 0), + /* TODO: should have a driver for this */ + GATE(CLK_GOUT_HSI2_LHS_ACEL_D_HSI2_I_CLK, + "gout_hsi2_lhs_acel_d_hsi2_i_clk", "mout_hsi2_bus_user", + CLK_CON_GAT_GOUT_BLK_HSI2_UID_LHS_ACEL_D_HSI2_IPCLKPORT_I_CLK, + 21, CLK_IGNORE_UNUSED, 0), + GATE(CLK_GOUT_HSI2_MMC_CARD_I_ACLK, + "gout_hsi2_mmc_card_i_aclk", "mout_hsi2_bus_user", + CLK_CON_GAT_GOUT_BLK_HSI2_UID_MMC_CARD_IPCLKPORT_I_ACLK, + 21, 0, 0), + GATE(CLK_GOUT_HSI2_MMC_CARD_SDCLKIN, + "gout_hsi2_mmc_card_sdclkin", "mout_hsi2_mmc_card_user", + CLK_CON_GAT_GOUT_BLK_HSI2_UID_MMC_CARD_IPCLKPORT_SDCLKIN, + 21, 0, 0), + GATE(CLK_GOUT_HSI2_PCIE_GEN4_1_PCIE_003_DBI_ACLK_UG, + "gout_hsi2_pcie_gen4_1_pcie_003_dbi_aclk_ug", "mout_hsi2_bus_user", + CLK_CON_GAT_GOUT_BLK_HSI2_UID_PCIE_GEN4_1_IPCLKPORT_PCIE_003_G4X2_DWC_PCIE_CTL_INST_0_DBI_ACLK_UG, + 21, 0, 0), + GATE(CLK_GOUT_HSI2_PCIE_GEN4_1_PCIE_003_MSTR_ACLK_UG, + "gout_hsi2_pcie_gen4_1_pcie_003_mstr_aclk_ug", + "mout_hsi2_bus_user", + CLK_CON_GAT_GOUT_BLK_HSI2_UID_PCIE_GEN4_1_IPCLKPORT_PCIE_003_G4X2_DWC_PCIE_CTL_INST_0_MSTR_ACLK_UG, + 21, 0, 0), + GATE(CLK_GOUT_HSI2_PCIE_GEN4_1_PCIE_003_SLV_ACLK_UG, + "gout_hsi2_pcie_gen4_1_pcie_003_slv_aclk_ug", "mout_hsi2_bus_user", + CLK_CON_GAT_GOUT_BLK_HSI2_UID_PCIE_GEN4_1_IPCLKPORT_PCIE_003_G4X2_DWC_PCIE_CTL_INST_0_SLV_ACLK_UG, + 21, 0, 0), + GATE(CLK_GOUT_HSI2_PCIE_GEN4_1_PCIE_003_I_DRIVER_APB_CLK, + "gout_hsi2_pcie_gen4_1_pcie_003_i_driver_apb_clk", + "mout_hsi2_bus_user", + CLK_CON_GAT_GOUT_BLK_HSI2_UID_PCIE_GEN4_1_IPCLKPORT_PCIE_003_PCIE_SUB_CTRL_INST_0_I_DRIVER_APB_CLK, + 21, 0, 0), + GATE(CLK_GOUT_HSI2_PCIE_GEN4_1_PCIE_004_DBI_ACLK_UG, + "gout_hsi2_pcie_gen4_1_pcie_004_dbi_aclk_ug", "mout_hsi2_bus_user", + CLK_CON_GAT_GOUT_BLK_HSI2_UID_PCIE_GEN4_1_IPCLKPORT_PCIE_004_G4X1_DWC_PCIE_CTL_INST_0_DBI_ACLK_UG, + 21, 0, 0), + GATE(CLK_GOUT_HSI2_PCIE_GEN4_1_PCIE_004_MSTR_ACLK_UG, + "gout_hsi2_pcie_gen4_1_pcie_004_mstr_aclk_ug", + "mout_hsi2_bus_user", + CLK_CON_GAT_GOUT_BLK_HSI2_UID_PCIE_GEN4_1_IPCLKPORT_PCIE_004_G4X1_DWC_PCIE_CTL_INST_0_MSTR_ACLK_UG, + 21, 0, 0), + GATE(CLK_GOUT_HSI2_PCIE_GEN4_1_PCIE_004_SLV_ACLK_UG, + "gout_hsi2_pcie_gen4_1_pcie_004_slv_aclk_ug", "mout_hsi2_bus_user", + CLK_CON_GAT_GOUT_BLK_HSI2_UID_PCIE_GEN4_1_IPCLKPORT_PCIE_004_G4X1_DWC_PCIE_CTL_INST_0_SLV_ACLK_UG, + 21, 0, 0), + GATE(CLK_GOUT_HSI2_PCIE_GEN4_1_PCIE_004_I_DRIVER_APB_CLK, + "gout_hsi2_pcie_gen4_1_pcie_004_i_driver_apb_clk", + "mout_hsi2_bus_user", + CLK_CON_GAT_GOUT_BLK_HSI2_UID_PCIE_GEN4_1_IPCLKPORT_PCIE_004_PCIE_SUB_CTRL_INST_0_I_DRIVER_APB_CLK, + 21, 0, 0), + GATE(CLK_GOUT_HSI2_PCIE_GEN4_1_PCS_PMA_PHY_UDBG_I_APB_PCLK, + "gout_hsi2_pcie_gen4_1_pcs_pma_phy_udbg_i_apb_pclk", + "mout_hsi2_bus_user", + CLK_CON_GAT_GOUT_BLK_HSI2_UID_PCIE_GEN4_1_IPCLKPORT_PCS_PMA_INST_0_PHY_UDBG_I_APB_PCLK, + 21, 0, 0), + GATE(CLK_GOUT_HSI2_PCIE_GEN4_1_PCS_PMA_PIPE_PAL_PCIE_I_APB_PCLK, + "gout_hsi2_pcie_gen4_1_pcs_pma_pipe_pal_pcie_i_apb_pclk", + "mout_hsi2_bus_user", + CLK_CON_GAT_GOUT_BLK_HSI2_UID_PCIE_GEN4_1_IPCLKPORT_PCS_PMA_INST_0_PIPE_PAL_PCIE_INST_0_I_APB_PCLK, + 21, 0, 0), + GATE(CLK_GOUT_HSI2_PCIE_GEN4_1_PCS_PMA_PCIEPHY210X2_QCH_I_APB_PCLK, + "gout_hsi2_pcie_gen4_1_pcs_pma_pciephy210x2_qch_i_apb_pclk", + "mout_hsi2_bus_user", + CLK_CON_GAT_GOUT_BLK_HSI2_UID_PCIE_GEN4_1_IPCLKPORT_PCS_PMA_INST_0_SF_PCIEPHY210X2_LN05LPE_QCH_TM_WRAPPER_INST_0_I_APB_PCLK, + 21, 0, 0), + GATE(CLK_GOUT_HSI2_PCIE_IA_GEN4A_1_I_CLK, + "gout_hsi2_pcie_ia_gen4a_1_i_clk", "mout_hsi2_bus_user", + CLK_CON_GAT_GOUT_BLK_HSI2_UID_PCIE_IA_GEN4A_1_IPCLKPORT_I_CLK, + 21, 0, 0), + GATE(CLK_GOUT_HSI2_PCIE_IA_GEN4B_1_I_CLK, + "gout_hsi2_pcie_ia_gen4b_1_i_clk", "mout_hsi2_bus_user", + CLK_CON_GAT_GOUT_BLK_HSI2_UID_PCIE_IA_GEN4B_1_IPCLKPORT_I_CLK, + 21, 0, 0), + GATE(CLK_GOUT_HSI2_PPMU_HSI2_ACLK, + "gout_hsi2_ppmu_hsi2_aclk", "mout_hsi2_bus_user", + CLK_CON_GAT_GOUT_BLK_HSI2_UID_PPMU_HSI2_IPCLKPORT_ACLK, + 21, 0, 0), + GATE(CLK_GOUT_HSI2_PPMU_HSI2_PCLK, + "gout_hsi2_ppmu_hsi2_pclk", "mout_hsi2_bus_user", + CLK_CON_GAT_GOUT_BLK_HSI2_UID_PPMU_HSI2_IPCLKPORT_PCLK, + 21, 0, 0), + GATE(CLK_GOUT_HSI2_QE_MMC_CARD_HSI2_ACLK, + "gout_hsi2_qe_mmc_card_hsi2_aclk", "mout_hsi2_bus_user", + CLK_CON_GAT_GOUT_BLK_HSI2_UID_QE_MMC_CARD_HSI2_IPCLKPORT_ACLK, + 21, 0, 0), + GATE(CLK_GOUT_HSI2_QE_MMC_CARD_HSI2_PCLK, + "gout_hsi2_qe_mmc_card_hsi2_pclk", "mout_hsi2_bus_user", + CLK_CON_GAT_GOUT_BLK_HSI2_UID_QE_MMC_CARD_HSI2_IPCLKPORT_PCLK, + 21, 0, 0), + GATE(CLK_GOUT_HSI2_QE_PCIE_GEN4A_HSI2_ACLK, + "gout_hsi2_qe_pcie_gen4a_hsi2_aclk", "mout_hsi2_bus_user", + CLK_CON_GAT_GOUT_BLK_HSI2_UID_QE_PCIE_GEN4A_HSI2_IPCLKPORT_ACLK, + 21, 0, 0), + GATE(CLK_GOUT_HSI2_QE_PCIE_GEN4A_HSI2_PCLK, + "gout_hsi2_qe_pcie_gen4a_hsi2_pclk", "mout_hsi2_bus_user", + CLK_CON_GAT_GOUT_BLK_HSI2_UID_QE_PCIE_GEN4A_HSI2_IPCLKPORT_PCLK, + 21, 0, 0), + GATE(CLK_GOUT_HSI2_QE_PCIE_GEN4B_HSI2_ACLK, + "gout_hsi2_qe_pcie_gen4b_hsi2_aclk", "mout_hsi2_bus_user", + CLK_CON_GAT_GOUT_BLK_HSI2_UID_QE_PCIE_GEN4B_HSI2_IPCLKPORT_ACLK, + 21, 0, 0), + GATE(CLK_GOUT_HSI2_QE_PCIE_GEN4B_HSI2_PCLK, + "gout_hsi2_qe_pcie_gen4b_hsi2_pclk", "mout_hsi2_bus_user", + CLK_CON_GAT_GOUT_BLK_HSI2_UID_QE_PCIE_GEN4B_HSI2_IPCLKPORT_PCLK, + 21, 0, 0), + GATE(CLK_GOUT_HSI2_QE_UFS_EMBD_HSI2_ACLK, + "gout_hsi2_qe_ufs_embd_hsi2_aclk", "mout_hsi2_bus_user", + CLK_CON_GAT_GOUT_BLK_HSI2_UID_QE_UFS_EMBD_HSI2_IPCLKPORT_ACLK, + 21, 0, 0), + GATE(CLK_GOUT_HSI2_QE_UFS_EMBD_HSI2_PCLK, + "gout_hsi2_qe_ufs_embd_hsi2_pclk", "mout_hsi2_bus_user", + CLK_CON_GAT_GOUT_BLK_HSI2_UID_QE_UFS_EMBD_HSI2_IPCLKPORT_PCLK, + 21, 0, 0), + GATE(CLK_GOUT_HSI2_CLK_HSI2_BUS_CLK, + "gout_hsi2_clk_hsi2_bus_clk", "mout_hsi2_bus_user", + CLK_CON_GAT_GOUT_BLK_HSI2_UID_RSTNSYNC_CLK_HSI2_BUS_IPCLKPORT_CLK, + 21, CLK_IS_CRITICAL, 0), + GATE(CLK_GOUT_HSI2_CLK_HSI2_OSCCLK_CLK, + "gout_hsi2_clk_hsi2_oscclk_clk", "oscclk", + CLK_CON_GAT_GOUT_BLK_HSI2_UID_RSTNSYNC_CLK_HSI2_OSCCLK_IPCLKPORT_CLK, + 21, 0, 0), + /* TODO: should have a driver for this */ + GATE(CLK_GOUT_HSI2_SSMT_HSI2_ACLK, + "gout_hsi2_ssmt_hsi2_aclk", "mout_hsi2_bus_user", + CLK_CON_GAT_GOUT_BLK_HSI2_UID_SSMT_HSI2_IPCLKPORT_ACLK, + 21, CLK_IGNORE_UNUSED, 0), + /* TODO: should have a driver for this */ + GATE(CLK_GOUT_HSI2_SSMT_HSI2_PCLK, + "gout_hsi2_ssmt_hsi2_pclk", "mout_hsi2_bus_user", + CLK_CON_GAT_GOUT_BLK_HSI2_UID_SSMT_HSI2_IPCLKPORT_PCLK, + 21, CLK_IGNORE_UNUSED, 0), + /* TODO: should have a driver for this */ + GATE(CLK_GOUT_HSI2_SYSMMU_HSI2_CLK_S2, + "gout_hsi2_sysmmu_hsi2_clk_s2", "mout_hsi2_bus_user", + CLK_CON_GAT_GOUT_BLK_HSI2_UID_SYSMMU_HSI2_IPCLKPORT_CLK_S2, + 21, CLK_IGNORE_UNUSED, 0), + GATE(CLK_GOUT_HSI2_SYSREG_HSI2_PCLK, + "gout_hsi2_sysreg_hsi2_pclk", "mout_hsi2_bus_user", + CLK_CON_GAT_GOUT_BLK_HSI2_UID_SYSREG_HSI2_IPCLKPORT_PCLK, + 21, 0, 0), + GATE(CLK_GOUT_HSI2_UASC_PCIE_GEN4A_DBI_1_ACLK, + "gout_hsi2_uasc_pcie_gen4a_dbi_1_aclk", "mout_hsi2_bus_user", + CLK_CON_GAT_GOUT_BLK_HSI2_UID_UASC_PCIE_GEN4A_DBI_1_IPCLKPORT_ACLK, + 21, 0, 0), + GATE(CLK_GOUT_HSI2_UASC_PCIE_GEN4A_DBI_1_PCLK, + "gout_hsi2_uasc_pcie_gen4a_dbi_1_pclk", "mout_hsi2_bus_user", + CLK_CON_GAT_GOUT_BLK_HSI2_UID_UASC_PCIE_GEN4A_DBI_1_IPCLKPORT_PCLK, + 21, 0, 0), + GATE(CLK_GOUT_HSI2_UASC_PCIE_GEN4A_SLV_1_ACLK, + "gout_hsi2_uasc_pcie_gen4a_slv_1_aclk", "mout_hsi2_bus_user", + CLK_CON_GAT_GOUT_BLK_HSI2_UID_UASC_PCIE_GEN4A_SLV_1_IPCLKPORT_ACLK, + 21, 0, 0), + GATE(CLK_GOUT_HSI2_UASC_PCIE_GEN4A_SLV_1_PCLK, + "gout_hsi2_uasc_pcie_gen4a_slv_1_pclk", "mout_hsi2_bus_user", + CLK_CON_GAT_GOUT_BLK_HSI2_UID_UASC_PCIE_GEN4A_SLV_1_IPCLKPORT_PCLK, + 21, 0, 0), + GATE(CLK_GOUT_HSI2_UASC_PCIE_GEN4B_DBI_1_ACLK, + "gout_hsi2_uasc_pcie_gen4b_dbi_1_aclk", "mout_hsi2_bus_user", + CLK_CON_GAT_GOUT_BLK_HSI2_UID_UASC_PCIE_GEN4B_DBI_1_IPCLKPORT_ACLK, + 21, 0, 0), + GATE(CLK_GOUT_HSI2_UASC_PCIE_GEN4B_DBI_1_PCLK, + "gout_hsi2_uasc_pcie_gen4b_dbi_1_pclk", "mout_hsi2_bus_user", + CLK_CON_GAT_GOUT_BLK_HSI2_UID_UASC_PCIE_GEN4B_DBI_1_IPCLKPORT_PCLK, + 21, 0, 0), + GATE(CLK_GOUT_HSI2_UASC_PCIE_GEN4B_SLV_1_ACLK, + "gout_hsi2_uasc_pcie_gen4b_slv_1_aclk", "mout_hsi2_bus_user", + CLK_CON_GAT_GOUT_BLK_HSI2_UID_UASC_PCIE_GEN4B_SLV_1_IPCLKPORT_ACLK, + 21, 0, 0), + GATE(CLK_GOUT_HSI2_UASC_PCIE_GEN4B_SLV_1_PCLK, + "gout_hsi2_uasc_pcie_gen4b_slv_1_pclk", "mout_hsi2_bus_user", + CLK_CON_GAT_GOUT_BLK_HSI2_UID_UASC_PCIE_GEN4B_SLV_1_IPCLKPORT_PCLK, + 21, 0, 0), + GATE(CLK_GOUT_HSI2_UFS_EMBD_I_ACLK, + "gout_hsi2_ufs_embd_i_aclk", "mout_hsi2_bus_user", + CLK_CON_GAT_GOUT_BLK_HSI2_UID_UFS_EMBD_IPCLKPORT_I_ACLK, + 21, 0, 0), + GATE(CLK_GOUT_HSI2_UFS_EMBD_I_CLK_UNIPRO, + "gout_hsi2_ufs_embd_i_clk_unipro", "mout_hsi2_ufs_embd_user", + CLK_CON_GAT_GOUT_BLK_HSI2_UID_UFS_EMBD_IPCLKPORT_I_CLK_UNIPRO, + 21, 0, 0), + GATE(CLK_GOUT_HSI2_UFS_EMBD_I_FMP_CLK, + "gout_hsi2_ufs_embd_i_fmp_clk", "mout_hsi2_bus_user", + CLK_CON_GAT_GOUT_BLK_HSI2_UID_UFS_EMBD_IPCLKPORT_I_FMP_CLK, + 21, 0, 0), + /* TODO: should have a driver for this */ + GATE(CLK_GOUT_HSI2_XIU_D_HSI2_ACLK, + "gout_hsi2_xiu_d_hsi2_aclk", "mout_hsi2_bus_user", + CLK_CON_GAT_GOUT_BLK_HSI2_UID_XIU_D_HSI2_IPCLKPORT_ACLK, + 21, CLK_IGNORE_UNUSED, 0), + /* TODO: should have a driver for this */ + GATE(CLK_GOUT_HSI2_XIU_P_HSI2_ACLK, + "gout_hsi2_xiu_p_hsi2_aclk", "mout_hsi2_bus_user", + CLK_CON_GAT_GOUT_BLK_HSI2_UID_XIU_P_HSI2_IPCLKPORT_ACLK, + 21, CLK_IGNORE_UNUSED, 0), +}; + +static const struct samsung_cmu_info hsi2_cmu_info __initconst = { + .mux_clks = hsi2_mux_clks, + .nr_mux_clks = ARRAY_SIZE(hsi2_mux_clks), + .gate_clks = hsi2_gate_clks, + .nr_gate_clks = ARRAY_SIZE(hsi2_gate_clks), + .nr_clk_ids = CLKS_NR_HSI2, + .clk_regs = cmu_hsi2_clk_regs, + .nr_clk_regs = ARRAY_SIZE(cmu_hsi2_clk_regs), + .clk_name = "bus", +}; + /* ---- CMU_MISC ------------------------------------------------------------ */ /* Register Offset definitions for CMU_MISC (0x10010000) */ @@ -3910,6 +4414,9 @@ static const struct of_device_id gs101_cmu_of_match[] = { }, { .compatible = "google,gs101-cmu-hsi0", .data = &hsi0_cmu_info, + }, { + .compatible = "google,gs101-cmu-hsi2", + .data = &hsi2_cmu_info, }, { .compatible = "google,gs101-cmu-peric0", .data = &peric0_cmu_info, From 9368cdf90f52a68120d039887ccff74ff33b4444 Mon Sep 17 00:00:00 2001 From: Nathan Chancellor Date: Thu, 25 Apr 2024 09:55:51 -0700 Subject: [PATCH 101/118] clk: bcm: dvp: Assign ->num before accessing ->hws Commit f316cdff8d67 ("clk: Annotate struct clk_hw_onecell_data with __counted_by") annotated the hws member of 'struct clk_hw_onecell_data' with __counted_by, which informs the bounds sanitizer about the number of elements in hws, so that it can warn when hws is accessed out of bounds. As noted in that change, the __counted_by member must be initialized with the number of elements before the first array access happens, otherwise there will be a warning from each access prior to the initialization because the number of elements is zero. This occurs in clk_dvp_probe() due to ->num being assigned after ->hws has been accessed: UBSAN: array-index-out-of-bounds in drivers/clk/bcm/clk-bcm2711-dvp.c:59:2 index 0 is out of range for type 'struct clk_hw *[] __counted_by(num)' (aka 'struct clk_hw *[]') Move the ->num initialization to before the first access of ->hws, which clears up the warning. Cc: stable@vger.kernel.org Fixes: f316cdff8d67 ("clk: Annotate struct clk_hw_onecell_data with __counted_by") Signed-off-by: Nathan Chancellor Link: https://lore.kernel.org/r/20240425-cbl-bcm-assign-counted-by-val-before-access-v1-1-e2db3b82d5ef@kernel.org Reviewed-by: Kees Cook Reviewed-by: Florian Fainelli Signed-off-by: Stephen Boyd --- drivers/clk/bcm/clk-bcm2711-dvp.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/clk/bcm/clk-bcm2711-dvp.c b/drivers/clk/bcm/clk-bcm2711-dvp.c index e4fbbf3c40fe..3cb235df9d37 100644 --- a/drivers/clk/bcm/clk-bcm2711-dvp.c +++ b/drivers/clk/bcm/clk-bcm2711-dvp.c @@ -56,6 +56,8 @@ static int clk_dvp_probe(struct platform_device *pdev) if (ret) return ret; + data->num = NR_CLOCKS; + data->hws[0] = clk_hw_register_gate_parent_data(&pdev->dev, "hdmi0-108MHz", &clk_dvp_parent, 0, @@ -76,7 +78,6 @@ static int clk_dvp_probe(struct platform_device *pdev) goto unregister_clk0; } - data->num = NR_CLOCKS; ret = of_clk_add_hw_provider(pdev->dev.of_node, of_clk_hw_onecell_get, data); if (ret) From 6dc445c1905096b2ed4db1a84570375b4e00cc0f Mon Sep 17 00:00:00 2001 From: Nathan Chancellor Date: Thu, 25 Apr 2024 09:55:52 -0700 Subject: [PATCH 102/118] clk: bcm: rpi: Assign ->num before accessing ->hws Commit f316cdff8d67 ("clk: Annotate struct clk_hw_onecell_data with __counted_by") annotated the hws member of 'struct clk_hw_onecell_data' with __counted_by, which informs the bounds sanitizer about the number of elements in hws, so that it can warn when hws is accessed out of bounds. As noted in that change, the __counted_by member must be initialized with the number of elements before the first array access happens, otherwise there will be a warning from each access prior to the initialization because the number of elements is zero. This occurs in raspberrypi_discover_clocks() due to ->num being assigned after ->hws has been accessed: UBSAN: array-index-out-of-bounds in drivers/clk/bcm/clk-raspberrypi.c:374:4 index 3 is out of range for type 'struct clk_hw *[] __counted_by(num)' (aka 'struct clk_hw *[]') Move the ->num initialization to before the first access of ->hws, which clears up the warning. Cc: stable@vger.kernel.org Fixes: f316cdff8d67 ("clk: Annotate struct clk_hw_onecell_data with __counted_by") Signed-off-by: Nathan Chancellor Link: https://lore.kernel.org/r/20240425-cbl-bcm-assign-counted-by-val-before-access-v1-2-e2db3b82d5ef@kernel.org Reviewed-by: Kees Cook Reviewed-by: Florian Fainelli Signed-off-by: Stephen Boyd --- drivers/clk/bcm/clk-raspberrypi.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/clk/bcm/clk-raspberrypi.c b/drivers/clk/bcm/clk-raspberrypi.c index 829406dc44a2..4d411408e4af 100644 --- a/drivers/clk/bcm/clk-raspberrypi.c +++ b/drivers/clk/bcm/clk-raspberrypi.c @@ -371,8 +371,8 @@ static int raspberrypi_discover_clocks(struct raspberrypi_clk *rpi, if (IS_ERR(hw)) return PTR_ERR(hw); - data->hws[clks->id] = hw; data->num = clks->id + 1; + data->hws[clks->id] = hw; } clks++; From 57939f392371fc93c203b781807c951018c29606 Mon Sep 17 00:00:00 2001 From: Fabio Estevam Date: Mon, 29 Apr 2024 18:45:02 -0300 Subject: [PATCH 103/118] clk: imx: imx8mp: Switch to RUNTIME_PM_OPS() Replace SET_RUNTIME_PM_OPS() with its modern alternative RUNTIME_PM_OPS(). The combined usage of pm_ptr() and RUNTIME_PM_OPS() allows the compiler to evaluate if the suspend/resume() functions are used at buid time or are simply dead code. This fixes the following s390 allmodconfig build errors: drivers/clk/imx/clk-imx8mp-audiomix.c:363:12: error: 'clk_imx8mp_audiomix_runtime_resume' defined but not used [-Werror=unused-function] 363 | static int clk_imx8mp_audiomix_runtime_resume(struct device *dev) | ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ drivers/clk/imx/clk-imx8mp-audiomix.c:356:12: error: 'clk_imx8mp_audiomix_runtime_suspend' defined but not used [-Werror=unused-function] 356 | static int clk_imx8mp_audiomix_runtime_suspend(struct device *dev) | ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ cc1: all warnings being treated as errors Reported-by: Naresh Kamboju Closes: https://lore.kernel.org/linux-clk/CA+G9fYuP7S+a89Ep5g5_Ad69EMwRkJ8nM+MMTzbEcP+6H2oMXQ@mail.gmail.com/T/#u Fixes: 1496dd413b2e ("clk: imx: imx8mp: Add pm_runtime support for power saving") Signed-off-by: Fabio Estevam Reviewed-by: Peng Fan Link: https://lore.kernel.org/r/20240429214502.1363592-1-festevam@gmail.com Signed-off-by: Abel Vesa --- drivers/clk/imx/clk-imx8mp-audiomix.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/clk/imx/clk-imx8mp-audiomix.c b/drivers/clk/imx/clk-imx8mp-audiomix.c index 574a032309c1..6a9b48b20cd6 100644 --- a/drivers/clk/imx/clk-imx8mp-audiomix.c +++ b/drivers/clk/imx/clk-imx8mp-audiomix.c @@ -368,8 +368,8 @@ static int clk_imx8mp_audiomix_runtime_resume(struct device *dev) } static const struct dev_pm_ops clk_imx8mp_audiomix_pm_ops = { - SET_RUNTIME_PM_OPS(clk_imx8mp_audiomix_runtime_suspend, - clk_imx8mp_audiomix_runtime_resume, NULL) + RUNTIME_PM_OPS(clk_imx8mp_audiomix_runtime_suspend, + clk_imx8mp_audiomix_runtime_resume, NULL) SET_NOIRQ_SYSTEM_SLEEP_PM_OPS(pm_runtime_force_suspend, pm_runtime_force_resume) }; @@ -386,7 +386,7 @@ static struct platform_driver clk_imx8mp_audiomix_driver = { .driver = { .name = "imx8mp-audio-blk-ctrl", .of_match_table = clk_imx8mp_audiomix_of_match, - .pm = &clk_imx8mp_audiomix_pm_ops, + .pm = pm_ptr(&clk_imx8mp_audiomix_pm_ops), }, }; From f5072cffb35c122ec85d91ef327fa8814f04297b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Uwe=20Kleine-K=C3=B6nig?= Date: Tue, 23 Apr 2024 09:12:31 +0200 Subject: [PATCH 104/118] clk: imx: imx8mp: Convert to platform remove callback returning void MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The .remove() callback for a platform driver returns an int which makes many driver authors wrongly assume it's possible to do error handling by returning an error code. However the value returned is ignored (apart from emitting a warning) and this typically results in resource leaks. To improve here there is a quest to make the remove callback return void. In the first step of this quest all drivers are converted to .remove_new(), which already returns void. Eventually after all drivers are converted, .remove_new() will be renamed to .remove(). Trivially convert this driver from always returning zero in the remove callback to the void returning variant. Fixes: 1496dd413b2e ("clk: imx: imx8mp: Add pm_runtime support for power saving") Signed-off-by: Uwe Kleine-König Reviewed-by: Abel Vesa Link: https://lore.kernel.org/r/20240423071232.463201-2-u.kleine-koenig@pengutronix.de Signed-off-by: Abel Vesa --- drivers/clk/imx/clk-imx8mp-audiomix.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/drivers/clk/imx/clk-imx8mp-audiomix.c b/drivers/clk/imx/clk-imx8mp-audiomix.c index 6a9b48b20cd6..b381d6f784c8 100644 --- a/drivers/clk/imx/clk-imx8mp-audiomix.c +++ b/drivers/clk/imx/clk-imx8mp-audiomix.c @@ -346,11 +346,9 @@ static int clk_imx8mp_audiomix_probe(struct platform_device *pdev) return ret; } -static int clk_imx8mp_audiomix_remove(struct platform_device *pdev) +static void clk_imx8mp_audiomix_remove(struct platform_device *pdev) { pm_runtime_disable(&pdev->dev); - - return 0; } static int clk_imx8mp_audiomix_runtime_suspend(struct device *dev) @@ -382,7 +380,7 @@ MODULE_DEVICE_TABLE(of, clk_imx8mp_audiomix_of_match); static struct platform_driver clk_imx8mp_audiomix_driver = { .probe = clk_imx8mp_audiomix_probe, - .remove = clk_imx8mp_audiomix_remove, + .remove_new = clk_imx8mp_audiomix_remove, .driver = { .name = "imx8mp-audio-blk-ctrl", .of_match_table = clk_imx8mp_audiomix_of_match, From 6b32d7474e9b833dc7fadc1b4d4f08af9bd87fde Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9=20Draszik?= Date: Tue, 30 Apr 2024 10:54:59 +0100 Subject: [PATCH 105/118] clk: samsung: gs101: mark some apm UASC and XIU clocks critical MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The system hangs when any of these clocks are turned off. With the introduction of pinctrl clock support [1], the approach taken in this clock driver for the APM clocks to rely solely on the clk_ignore_unused kernel command line option does not work anymore and the system hangs during boot. gout_apm_func is a parent clock to the clocks that are going to be handled by the pinctrl driver [2], namely gout_apm_apbif_gpio_alive_pclk and gout_apm_apbif_gpio_far_alive_pclk. It also is the parent to the clocks marked as critical in this commit here (and some others that aren't relevant for this commit)). This means that once the pinctrl driver decides to turn off clocks, the clock framework will subsequently turn off parent clocks of those pinctrl clocks if they have no (apparent) user. Since gout_apm_func is the parent, and since no drivers are hooked up to it or any of its other children, gout_apm_func will be turned off. This will cause the system to hang, as the clocks marked as critical in this commit stop having an input. We might have to add a driver for these clocks, but in the meantime let's just ensure they stay on even if siblings are turned off. For the avoidance of doubt: This commit doesn't mean that we can boot without clk_ignore_unused. Link: https://lore.kernel.org/r/20240426-samsung-pinctrl-busclock-v3-0-adb8664b8a7e@linaro.org [1] Link: https://lore.kernel.org/r/20240429-samsung-pinctrl-busclock-dts-v1-0-5e935179f3ca@linaro.org [2] Signed-off-by: André Draszik Reviewed-by: Tudor Ambarus Link: https://lore.kernel.org/r/20240430-gs101-apm-clocks-v1-1-b2e2335e84f5@linaro.org Signed-off-by: Krzysztof Kozlowski --- drivers/clk/samsung/clk-gs101.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/clk/samsung/clk-gs101.c b/drivers/clk/samsung/clk-gs101.c index 05129c3b2f68..e2a6a1992505 100644 --- a/drivers/clk/samsung/clk-gs101.c +++ b/drivers/clk/samsung/clk-gs101.c @@ -1896,16 +1896,16 @@ static const struct samsung_gate_clock apm_gate_clks[] __initconst = { CLK_CON_GAT_GOUT_BLK_APM_UID_UASC_G_SWD_IPCLKPORT_PCLK, 21, 0, 0), GATE(CLK_GOUT_APM_UASC_P_APM_ACLK, "gout_apm_uasc_p_apm_aclk", "gout_apm_func", - CLK_CON_GAT_GOUT_BLK_APM_UID_UASC_P_APM_IPCLKPORT_ACLK, 21, 0, 0), + CLK_CON_GAT_GOUT_BLK_APM_UID_UASC_P_APM_IPCLKPORT_ACLK, 21, CLK_IS_CRITICAL, 0), GATE(CLK_GOUT_APM_UASC_P_APM_PCLK, "gout_apm_uasc_p_apm_pclk", "gout_apm_func", - CLK_CON_GAT_GOUT_BLK_APM_UID_UASC_P_APM_IPCLKPORT_PCLK, 21, 0, 0), + CLK_CON_GAT_GOUT_BLK_APM_UID_UASC_P_APM_IPCLKPORT_PCLK, 21, CLK_IS_CRITICAL, 0), GATE(CLK_GOUT_APM_WDT_APM_PCLK, "gout_apm_wdt_apm_pclk", "gout_apm_func", CLK_CON_GAT_GOUT_BLK_APM_UID_WDT_APM_IPCLKPORT_PCLK, 21, 0, 0), GATE(CLK_GOUT_APM_XIU_DP_APM_ACLK, "gout_apm_xiu_dp_apm_aclk", "gout_apm_func", - CLK_CON_GAT_GOUT_BLK_APM_UID_XIU_DP_APM_IPCLKPORT_ACLK, 21, 0, 0), + CLK_CON_GAT_GOUT_BLK_APM_UID_XIU_DP_APM_IPCLKPORT_ACLK, 21, CLK_IS_CRITICAL, 0), }; static const struct samsung_cmu_info apm_cmu_info __initconst = { From 11981485e27c7e5a630ee844a2eae1f1835ba807 Mon Sep 17 00:00:00 2001 From: Krzysztof Kozlowski Date: Wed, 10 Apr 2024 17:54:06 +0200 Subject: [PATCH 106/118] clk: meson: s4: fix module autoloading Add MODULE_DEVICE_TABLE(), so modules could be properly autoloaded based on the alias from of_device_id table. Clocks are considered core components, so usually they are built-in, however these can be built and used as modules on some generic kernel. Signed-off-by: Krzysztof Kozlowski Reviewed-by: Neil Armstrong Reviewed-by: Martin Blumenstingl Link: https://lore.kernel.org/r/20240410155406.224128-1-krzk@kernel.org Signed-off-by: Jerome Brunet --- drivers/clk/meson/s4-peripherals.c | 1 + drivers/clk/meson/s4-pll.c | 1 + 2 files changed, 2 insertions(+) diff --git a/drivers/clk/meson/s4-peripherals.c b/drivers/clk/meson/s4-peripherals.c index 1fceb93faf13..5e17ca50ab09 100644 --- a/drivers/clk/meson/s4-peripherals.c +++ b/drivers/clk/meson/s4-peripherals.c @@ -3800,6 +3800,7 @@ static const struct of_device_id clkc_match_table[] = { }, {} }; +MODULE_DEVICE_TABLE(of, clkc_match_table); static struct platform_driver s4_driver = { .probe = meson_s4_periphs_probe, diff --git a/drivers/clk/meson/s4-pll.c b/drivers/clk/meson/s4-pll.c index c8a95842b14c..d2650d96400c 100644 --- a/drivers/clk/meson/s4-pll.c +++ b/drivers/clk/meson/s4-pll.c @@ -854,6 +854,7 @@ static const struct of_device_id clkc_match_table[] = { }, {} }; +MODULE_DEVICE_TABLE(of, clkc_match_table); static struct platform_driver s4_driver = { .probe = meson_s4_pll_probe, From b3e991240ed39f8fa4f74d3a876b48ef80726f84 Mon Sep 17 00:00:00 2001 From: "Rob Herring (Arm)" Date: Tue, 30 Apr 2024 13:04:14 -0500 Subject: [PATCH 107/118] dt-bindings: clock: fixed: Define a preferred node name Define "clock-" as the preferred node name for fixed-clock and fixed-factor-clock where is the output frequency of the clock. There isn't much of an existing pattern for names of these nodes. The most frequent patterns are a prefix or suffix of "clk", but there's a bunch that don't follow any sort of pattern. We could use "clock-controller-.*", but these nodes aren't really a controller in any way. So let's at least align with part of that and use 'clock-'. For now this only serves as documentation as the schema still allows anything to avoid lots of additional warnings for something low priority to fix. Once a "no deprecated" mode is added to the tools, warnings can be enabled selectively. Signed-off-by: Rob Herring (Arm) Link: https://lore.kernel.org/r/20240430180415.657067-1-robh@kernel.org Acked-by: Conor Dooley Signed-off-by: Stephen Boyd --- Documentation/devicetree/bindings/clock/fixed-clock.yaml | 9 +++++++++ .../devicetree/bindings/clock/fixed-factor-clock.yaml | 9 +++++++++ 2 files changed, 18 insertions(+) diff --git a/Documentation/devicetree/bindings/clock/fixed-clock.yaml b/Documentation/devicetree/bindings/clock/fixed-clock.yaml index b0a4fb8256e2..90fb10660684 100644 --- a/Documentation/devicetree/bindings/clock/fixed-clock.yaml +++ b/Documentation/devicetree/bindings/clock/fixed-clock.yaml @@ -11,6 +11,15 @@ maintainers: - Stephen Boyd properties: + $nodename: + anyOf: + - description: + Preferred name is 'clock-' with being the output + frequency as defined in the 'clock-frequency' property. + pattern: "^clock-([0-9]+|[a-z0-9-]+)$" + - description: Any name allowed + deprecated: true + compatible: const: fixed-clock diff --git a/Documentation/devicetree/bindings/clock/fixed-factor-clock.yaml b/Documentation/devicetree/bindings/clock/fixed-factor-clock.yaml index 8f71ab300470..4afdb1c98f5f 100644 --- a/Documentation/devicetree/bindings/clock/fixed-factor-clock.yaml +++ b/Documentation/devicetree/bindings/clock/fixed-factor-clock.yaml @@ -11,6 +11,15 @@ maintainers: - Stephen Boyd properties: + $nodename: + anyOf: + - description: + If the frequency is fixed, the preferred name is 'clock-' with + being the output frequency. + pattern: "^clock-([0-9]+|[0-9a-z-]+)$" + - description: Any name allowed + deprecated: true + compatible: enum: - fixed-factor-clock From 947b8f2a8b5155f6e9560af07ed65b3cc9aecd75 Mon Sep 17 00:00:00 2001 From: Christophe JAILLET Date: Wed, 24 Apr 2024 16:48:29 +0200 Subject: [PATCH 108/118] clk: rockchip: Remove an unused field in struct rockchip_mmc_clock In "struct rockchip_mmc_clock", the 'id' field is unused. Remove it. Found with cppcheck, unusedStructMember. Signed-off-by: Christophe JAILLET Link: https://lore.kernel.org/r/410bc0f86c7b9f1c80f8a4e9a2a028a9a6ee1ec0.1713970085.git.christophe.jaillet@wanadoo.fr Signed-off-by: Heiko Stuebner --- drivers/clk/rockchip/clk-mmc-phase.c | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/clk/rockchip/clk-mmc-phase.c b/drivers/clk/rockchip/clk-mmc-phase.c index 975454a3dd72..91012078681b 100644 --- a/drivers/clk/rockchip/clk-mmc-phase.c +++ b/drivers/clk/rockchip/clk-mmc-phase.c @@ -14,7 +14,6 @@ struct rockchip_mmc_clock { struct clk_hw hw; void __iomem *reg; - int id; int shift; int cached_phase; struct notifier_block clk_rate_change_nb; From f513991b69885025995dcb4ca75d2ee7261e1273 Mon Sep 17 00:00:00 2001 From: Lucas Stach Date: Fri, 3 May 2024 17:33:29 +0200 Subject: [PATCH 109/118] clk: rockchip: rk3568: Add PLL rate for 724 MHz This rate allows to provide a low-jitter 72,4 MHz pixelclock for a custom eDP panel from the VPLL. Signed-off-by: Lucas Stach Link: https://lore.kernel.org/r/20240503153329.3906030-1-l.stach@pengutronix.de Signed-off-by: Heiko Stuebner --- drivers/clk/rockchip/clk-rk3568.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/clk/rockchip/clk-rk3568.c b/drivers/clk/rockchip/clk-rk3568.c index 2d44bcaef046..53d10b1c627b 100644 --- a/drivers/clk/rockchip/clk-rk3568.c +++ b/drivers/clk/rockchip/clk-rk3568.c @@ -64,6 +64,7 @@ static struct rockchip_pll_rate_table rk3568_pll_rates[] = { RK3036_PLL_RATE(912000000, 1, 76, 2, 1, 1, 0), RK3036_PLL_RATE(816000000, 1, 68, 2, 1, 1, 0), RK3036_PLL_RATE(800000000, 3, 200, 2, 1, 1, 0), + RK3036_PLL_RATE(724000000, 3, 181, 2, 1, 1, 0), RK3036_PLL_RATE(700000000, 3, 350, 4, 1, 1, 0), RK3036_PLL_RATE(696000000, 1, 116, 4, 1, 1, 0), RK3036_PLL_RATE(600000000, 1, 100, 4, 1, 1, 0), From 7c18b0a5aa46cc7e5d3a7ef3f9f8e3aa91bb780f Mon Sep 17 00:00:00 2001 From: Krzysztof Kozlowski Date: Tue, 7 May 2024 07:59:48 +0200 Subject: [PATCH 110/118] clk: samsung: gs101: drop unused HSI2 clock parent data Drop static const arrays with HSI2 clocks parent data which are not referenced by any clock. This might cause -Werror=unused-const-variable warnings. Reported-by: Stephen Boyd Closes: https://lore.kernel.org/all/8bf65df598680f0785c3d6db70acfb9a.sboyd@kernel.org/ Fixes: 093c290084a4 ("clk: samsung: gs101: add support for cmu_hsi2") Reviewed-by: Peter Griffin Link: https://lore.kernel.org/r/20240507055948.34554-1-krzysztof.kozlowski@linaro.org Signed-off-by: Krzysztof Kozlowski --- drivers/clk/samsung/clk-gs101.c | 15 --------------- 1 file changed, 15 deletions(-) diff --git a/drivers/clk/samsung/clk-gs101.c b/drivers/clk/samsung/clk-gs101.c index e2a6a1992505..ba9570f7a5fa 100644 --- a/drivers/clk/samsung/clk-gs101.c +++ b/drivers/clk/samsung/clk-gs101.c @@ -2601,21 +2601,6 @@ static const unsigned long cmu_hsi2_clk_regs[] __initconst = { QUEUE_CTRL_REG_BLK_HSI2_CMU_HSI2, }; -PNAME(mout_hsi2_ufs_embd_p) = { "oscclk", "dout_cmu_shared0_div4", - "dout_cmu_shared2_div2", "fout_spare_pll" }; - -PNAME(mout_hsi2_pcie_p) = { "oscclk", "dout_cmu_shared2_div2" }; - -PNAME(mout_hsi2_bus_p) = { "dout_cmu_shared0_div4", - "dout_cmu_shared1_div4", - "dout_cmu_shared2_div2", - "dout_cmu_shared3_div2", - "fout_spare_pll", "oscclk", "oscclk", - "oscclk" }; - -PNAME(mout_hsi2_mmc_card_p) = { "fout_shared2_pll", "fout_shared3_pll", - "dout_cmu_shared0_div4", "fout_spare_pll" }; - PNAME(mout_hsi2_bus_user_p) = { "oscclk", "dout_cmu_hsi2_bus" }; PNAME(mout_hsi2_mmc_card_user_p) = { "oscclk", "dout_cmu_hsi2_mmc_card" }; PNAME(mout_hsi2_pcie_user_p) = { "oscclk", "dout_cmu_hsi2_pcie" }; From 098c290a490d0121e209617097ea563e5e607066 Mon Sep 17 00:00:00 2001 From: Conor Dooley Date: Wed, 24 Apr 2024 09:42:08 +0100 Subject: [PATCH 111/118] clock, reset: microchip: move all mpfs reset code to the reset subsystem Stephen and Philipp, while reviewing patches, said that all of the aux device creation and the register read/write code could be moved to the reset subsystem, leaving the clock driver with no implementations of reset_* functions at all. Move them. Suggested-by: Philipp Zabel Suggested-by: Stephen Boyd Signed-off-by: Conor Dooley Link: https://lore.kernel.org/r/20240424-strangle-sharpener-34755c5e6e3e@spud Signed-off-by: Stephen Boyd --- drivers/clk/microchip/clk-mpfs.c | 92 +------------------------------ drivers/reset/reset-mpfs.c | 95 +++++++++++++++++++++++++++++--- include/soc/microchip/mpfs.h | 10 ++-- 3 files changed, 93 insertions(+), 104 deletions(-) diff --git a/drivers/clk/microchip/clk-mpfs.c b/drivers/clk/microchip/clk-mpfs.c index 22eab91a6712..28ec0da88cb3 100644 --- a/drivers/clk/microchip/clk-mpfs.c +++ b/drivers/clk/microchip/clk-mpfs.c @@ -4,12 +4,10 @@ * * Copyright (C) 2020-2022 Microchip Technology Inc. All rights reserved. */ -#include #include #include #include #include -#include #include #include @@ -361,93 +359,6 @@ static int mpfs_clk_register_periphs(struct device *dev, struct mpfs_periph_hw_c return 0; } -/* - * Peripheral clock resets - */ - -#if IS_ENABLED(CONFIG_RESET_CONTROLLER) - -u32 mpfs_reset_read(struct device *dev) -{ - struct mpfs_clock_data *clock_data = dev_get_drvdata(dev->parent); - - return readl_relaxed(clock_data->base + REG_SUBBLK_RESET_CR); -} -EXPORT_SYMBOL_NS_GPL(mpfs_reset_read, MCHP_CLK_MPFS); - -void mpfs_reset_write(struct device *dev, u32 val) -{ - struct mpfs_clock_data *clock_data = dev_get_drvdata(dev->parent); - - writel_relaxed(val, clock_data->base + REG_SUBBLK_RESET_CR); -} -EXPORT_SYMBOL_NS_GPL(mpfs_reset_write, MCHP_CLK_MPFS); - -static void mpfs_reset_unregister_adev(void *_adev) -{ - struct auxiliary_device *adev = _adev; - - auxiliary_device_delete(adev); - auxiliary_device_uninit(adev); -} - -static void mpfs_reset_adev_release(struct device *dev) -{ - struct auxiliary_device *adev = to_auxiliary_dev(dev); - - kfree(adev); -} - -static struct auxiliary_device *mpfs_reset_adev_alloc(struct mpfs_clock_data *clk_data) -{ - struct auxiliary_device *adev; - int ret; - - adev = kzalloc(sizeof(*adev), GFP_KERNEL); - if (!adev) - return ERR_PTR(-ENOMEM); - - adev->name = "reset-mpfs"; - adev->dev.parent = clk_data->dev; - adev->dev.release = mpfs_reset_adev_release; - adev->id = 666u; - - ret = auxiliary_device_init(adev); - if (ret) { - kfree(adev); - return ERR_PTR(ret); - } - - return adev; -} - -static int mpfs_reset_controller_register(struct mpfs_clock_data *clk_data) -{ - struct auxiliary_device *adev; - int ret; - - adev = mpfs_reset_adev_alloc(clk_data); - if (IS_ERR(adev)) - return PTR_ERR(adev); - - ret = auxiliary_device_add(adev); - if (ret) { - auxiliary_device_uninit(adev); - return ret; - } - - return devm_add_action_or_reset(clk_data->dev, mpfs_reset_unregister_adev, adev); -} - -#else /* !CONFIG_RESET_CONTROLLER */ - -static int mpfs_reset_controller_register(struct mpfs_clock_data *clk_data) -{ - return 0; -} - -#endif /* !CONFIG_RESET_CONTROLLER */ - static int mpfs_clk_probe(struct platform_device *pdev) { struct device *dev = &pdev->dev; @@ -499,7 +410,7 @@ static int mpfs_clk_probe(struct platform_device *pdev) if (ret) return ret; - return mpfs_reset_controller_register(clk_data); + return mpfs_reset_controller_register(dev, clk_data->base + REG_SUBBLK_RESET_CR); } static const struct of_device_id mpfs_clk_of_match_table[] = { @@ -532,3 +443,4 @@ MODULE_DESCRIPTION("Microchip PolarFire SoC Clock Driver"); MODULE_AUTHOR("Padmarao Begari "); MODULE_AUTHOR("Daire McNamara "); MODULE_AUTHOR("Conor Dooley "); +MODULE_IMPORT_NS(MCHP_CLK_MPFS); diff --git a/drivers/reset/reset-mpfs.c b/drivers/reset/reset-mpfs.c index 7f3fb2d472f4..710f9c1676f9 100644 --- a/drivers/reset/reset-mpfs.c +++ b/drivers/reset/reset-mpfs.c @@ -8,9 +8,11 @@ */ #include #include +#include #include #include #include +#include #include #include #include @@ -28,20 +30,30 @@ /* block concurrent access to the soft reset register */ static DEFINE_SPINLOCK(mpfs_reset_lock); +struct mpfs_reset { + void __iomem *base; + struct reset_controller_dev rcdev; +}; + +static inline struct mpfs_reset *to_mpfs_reset(struct reset_controller_dev *rcdev) +{ + return container_of(rcdev, struct mpfs_reset, rcdev); +} + /* * Peripheral clock resets */ - static int mpfs_assert(struct reset_controller_dev *rcdev, unsigned long id) { + struct mpfs_reset *rst = to_mpfs_reset(rcdev); unsigned long flags; u32 reg; spin_lock_irqsave(&mpfs_reset_lock, flags); - reg = mpfs_reset_read(rcdev->dev); + reg = readl(rst->base); reg |= BIT(id); - mpfs_reset_write(rcdev->dev, reg); + writel(reg, rst->base); spin_unlock_irqrestore(&mpfs_reset_lock, flags); @@ -50,14 +62,15 @@ static int mpfs_assert(struct reset_controller_dev *rcdev, unsigned long id) static int mpfs_deassert(struct reset_controller_dev *rcdev, unsigned long id) { + struct mpfs_reset *rst = to_mpfs_reset(rcdev); unsigned long flags; u32 reg; spin_lock_irqsave(&mpfs_reset_lock, flags); - reg = mpfs_reset_read(rcdev->dev); + reg = readl(rst->base); reg &= ~BIT(id); - mpfs_reset_write(rcdev->dev, reg); + writel(reg, rst->base); spin_unlock_irqrestore(&mpfs_reset_lock, flags); @@ -66,7 +79,8 @@ static int mpfs_deassert(struct reset_controller_dev *rcdev, unsigned long id) static int mpfs_status(struct reset_controller_dev *rcdev, unsigned long id) { - u32 reg = mpfs_reset_read(rcdev->dev); + struct mpfs_reset *rst = to_mpfs_reset(rcdev); + u32 reg = readl(rst->base); /* * It is safe to return here as MPFS_NUM_RESETS makes sure the sign bit @@ -121,11 +135,15 @@ static int mpfs_reset_probe(struct auxiliary_device *adev, { struct device *dev = &adev->dev; struct reset_controller_dev *rcdev; + struct mpfs_reset *rst; - rcdev = devm_kzalloc(dev, sizeof(*rcdev), GFP_KERNEL); - if (!rcdev) + rst = devm_kzalloc(dev, sizeof(*rst), GFP_KERNEL); + if (!rst) return -ENOMEM; + rst->base = (void __iomem *)adev->dev.platform_data; + + rcdev = &rst->rcdev; rcdev->dev = dev; rcdev->dev->parent = dev->parent; rcdev->ops = &mpfs_reset_ops; @@ -137,9 +155,68 @@ static int mpfs_reset_probe(struct auxiliary_device *adev, return devm_reset_controller_register(dev, rcdev); } +static void mpfs_reset_unregister_adev(void *_adev) +{ + struct auxiliary_device *adev = _adev; + + auxiliary_device_delete(adev); + auxiliary_device_uninit(adev); +} + +static void mpfs_reset_adev_release(struct device *dev) +{ + struct auxiliary_device *adev = to_auxiliary_dev(dev); + + kfree(adev); +} + +static struct auxiliary_device *mpfs_reset_adev_alloc(struct device *clk_dev) +{ + struct auxiliary_device *adev; + int ret; + + adev = kzalloc(sizeof(*adev), GFP_KERNEL); + if (!adev) + return ERR_PTR(-ENOMEM); + + adev->name = "reset-mpfs"; + adev->dev.parent = clk_dev; + adev->dev.release = mpfs_reset_adev_release; + adev->id = 666u; + + ret = auxiliary_device_init(adev); + if (ret) { + kfree(adev); + return ERR_PTR(ret); + } + + return adev; +} + +int mpfs_reset_controller_register(struct device *clk_dev, void __iomem *base) +{ + struct auxiliary_device *adev; + int ret; + + adev = mpfs_reset_adev_alloc(clk_dev); + if (IS_ERR(adev)) + return PTR_ERR(adev); + + ret = auxiliary_device_add(adev); + if (ret) { + auxiliary_device_uninit(adev); + return ret; + } + + adev->dev.platform_data = (__force void *)base; + + return devm_add_action_or_reset(clk_dev, mpfs_reset_unregister_adev, adev); +} +EXPORT_SYMBOL_NS_GPL(mpfs_reset_controller_register, MCHP_CLK_MPFS); + static const struct auxiliary_device_id mpfs_reset_ids[] = { { - .name = "clk_mpfs.reset-mpfs", + .name = "reset_mpfs.reset-mpfs", }, { } }; diff --git a/include/soc/microchip/mpfs.h b/include/soc/microchip/mpfs.h index 09722f83b0ca..d7e612b5e22e 100644 --- a/include/soc/microchip/mpfs.h +++ b/include/soc/microchip/mpfs.h @@ -43,11 +43,11 @@ struct mtd_info *mpfs_sys_controller_get_flash(struct mpfs_sys_controller *mpfs_ #endif /* if IS_ENABLED(CONFIG_POLARFIRE_SOC_SYS_CTRL) */ #if IS_ENABLED(CONFIG_MCHP_CLK_MPFS) - -u32 mpfs_reset_read(struct device *dev); - -void mpfs_reset_write(struct device *dev, u32 val); - +#if IS_ENABLED(CONFIG_RESET_CONTROLLER) +int mpfs_reset_controller_register(struct device *clk_dev, void __iomem *base); +#else +static inline int mpfs_reset_controller_register(struct device *clk_dev, void __iomem *base) { return 0; } +#endif /* if IS_ENABLED(CONFIG_RESET_CONTROLLER) */ #endif /* if IS_ENABLED(CONFIG_MCHP_CLK_MPFS) */ #endif /* __SOC_MPFS_H__ */ From 12b52b83c9276e7cad13fedbbe38bde570164775 Mon Sep 17 00:00:00 2001 From: Gabriel Fernandez Date: Fri, 19 Apr 2024 17:27:20 +0200 Subject: [PATCH 112/118] dt-bindings: clocks: stm32mp25: add access-controllers description access-controllers is an optional property that allows to refer to domain access controller. The RCC driver will be able to check if we are allowed to register clocks for a peripheral. Signed-off-by: Gabriel Fernandez Link: https://lore.kernel.org/r/20240419152723.570159-2-gabriel.fernandez@foss.st.com Acked-by: Rob Herring (Arm) Signed-off-by: Stephen Boyd --- Documentation/devicetree/bindings/clock/st,stm32mp25-rcc.yaml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/Documentation/devicetree/bindings/clock/st,stm32mp25-rcc.yaml b/Documentation/devicetree/bindings/clock/st,stm32mp25-rcc.yaml index 0929fa7e271b..88e52f10d1ec 100644 --- a/Documentation/devicetree/bindings/clock/st,stm32mp25-rcc.yaml +++ b/Documentation/devicetree/bindings/clock/st,stm32mp25-rcc.yaml @@ -114,6 +114,10 @@ properties: - description: CK_SCMI_PLL3 PLL3 clock - description: clk_dsi_txbyte DSI byte clock + access-controllers: + minItems: 1 + maxItems: 2 + required: - compatible - reg From e00f2540a581f8b8c165e5ae8afe52e4ad038550 Mon Sep 17 00:00:00 2001 From: Nathan Chancellor Date: Mon, 18 Mar 2024 08:18:10 -0700 Subject: [PATCH 113/118] clk: qcom: Fix SC_CAMCC_8280XP dependencies CONFIG_SC_GCC_8280XP depends on ARM64 but it is selected by CONFIG_SC_CAMCC_8280XP, which can be selected on ARM, resulting in a Kconfig warning. WARNING: unmet direct dependencies detected for SC_GCC_8280XP Depends on [n]: COMMON_CLK [=y] && COMMON_CLK_QCOM [=y] && (ARM64 || COMPILE_TEST [=n]) Selected by [y]: - SC_CAMCC_8280XP [=y] && COMMON_CLK [=y] && COMMON_CLK_QCOM [=y] Add the same dependencies to CONFIG_SC_CAMCC_8280XP to resolve the warning. Fixes: ff93872a9c61 ("clk: qcom: camcc-sc8280xp: Add sc8280xp CAMCC") Signed-off-by: Nathan Chancellor Reviewed-by: Dmitry Baryshkov Link: https://lore.kernel.org/r/20240318-fix-some-qcom-kconfig-deps-v1-1-ea0773e3df5a@kernel.org Signed-off-by: Bjorn Andersson --- drivers/clk/qcom/Kconfig | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/clk/qcom/Kconfig b/drivers/clk/qcom/Kconfig index 8ab08e7b5b6c..b9ff32cab329 100644 --- a/drivers/clk/qcom/Kconfig +++ b/drivers/clk/qcom/Kconfig @@ -474,6 +474,7 @@ config SC_CAMCC_7280 config SC_CAMCC_8280XP tristate "SC8280XP Camera Clock Controller" + depends on ARM64 || COMPILE_TEST select SC_GCC_8280XP help Support for the camera clock controller on Qualcomm Technologies, Inc From 07fb0a76bb757990b99fc2ab78ad7d1709cc441d Mon Sep 17 00:00:00 2001 From: Nathan Chancellor Date: Mon, 18 Mar 2024 08:18:11 -0700 Subject: [PATCH 114/118] clk: qcom: Fix SM_GPUCC_8650 dependencies CONFIG_SM_GCC_8650 depends on ARM64 but it is selected by CONFIG_SM_GPUCC_8650, which can be selected on ARM, resulting in a Kconfig warning. WARNING: unmet direct dependencies detected for SM_GCC_8650 Depends on [n]: COMMON_CLK [=y] && COMMON_CLK_QCOM [=y] && (ARM64 || COMPILE_TEST [=n]) Selected by [y]: - SM_GPUCC_8650 [=y] && COMMON_CLK [=y] && COMMON_CLK_QCOM [=y] Add the same dependencies to CONFIG_SM_GPUCC_8650 to resolve the warning. Fixes: 8676fd4f3874 ("clk: qcom: add the SM8650 GPU Clock Controller driver") Signed-off-by: Nathan Chancellor Reviewed-by: Dmitry Baryshkov Link: https://lore.kernel.org/r/20240318-fix-some-qcom-kconfig-deps-v1-2-ea0773e3df5a@kernel.org Signed-off-by: Bjorn Andersson --- drivers/clk/qcom/Kconfig | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/clk/qcom/Kconfig b/drivers/clk/qcom/Kconfig index b9ff32cab329..1bb51a058872 100644 --- a/drivers/clk/qcom/Kconfig +++ b/drivers/clk/qcom/Kconfig @@ -1095,6 +1095,7 @@ config SM_GPUCC_8550 config SM_GPUCC_8650 tristate "SM8650 Graphics Clock Controller" + depends on ARM64 || COMPILE_TEST select SM_GCC_8650 help Support for the graphics clock controller on SM8650 devices. From c55f7ee2ec239b6afd8639c7ac06493876deb0ea Mon Sep 17 00:00:00 2001 From: Gabor Juhos Date: Tue, 26 Mar 2024 14:34:11 +0100 Subject: [PATCH 115/118] clk: qcom: apss-ipq-pll: fix PLL rate for IPQ5018 According to ipq5018.dtsi, the maximum supported rate by the CPU is 1.008 GHz on the IPQ5018 platform, however the current configuration of the PLL results in 1.2 GHz rate. Change the 'L' value in the PLL configuration to limit the rate to 1.008 GHz. The downstream kernel also uses the same value [1]. Also add a comment to indicate the desired frequency. [1] https://git.codelinaro.org/clo/qsdk/oss/kernel/linux-ipq-5.4/-/blob/NHSS.QSDK.12.4/drivers/clk/qcom/apss-ipq5018.c?ref_type=heads#L151 Fixes: 50492f929486 ("clk: qcom: apss-ipq-pll: add support for IPQ5018") Signed-off-by: Gabor Juhos Reviewed-by: Konrad Dybcio Link: https://lore.kernel.org/r/20240326-fix-ipq5018-apss-pll-rate-v1-1-82ab31c9da7e@gmail.com Signed-off-by: Bjorn Andersson --- drivers/clk/qcom/apss-ipq-pll.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/clk/qcom/apss-ipq-pll.c b/drivers/clk/qcom/apss-ipq-pll.c index 1a6f4db25379..5f7f537e4ecb 100644 --- a/drivers/clk/qcom/apss-ipq-pll.c +++ b/drivers/clk/qcom/apss-ipq-pll.c @@ -66,8 +66,9 @@ static struct clk_alpha_pll ipq_pll_stromer_plus = { }, }; +/* 1.008 GHz configuration */ static const struct alpha_pll_config ipq5018_pll_config = { - .l = 0x32, + .l = 0x2a, .config_ctl_val = 0x4001075b, .config_ctl_hi_val = 0x304, .main_output_mask = BIT(0), From 3c5b3e17b8fd1f1add5a9477306c355fab126977 Mon Sep 17 00:00:00 2001 From: Gabor Juhos Date: Thu, 28 Mar 2024 08:54:31 +0100 Subject: [PATCH 116/118] clk: qcom: clk-alpha-pll: fix rate setting for Stromer PLLs The clk_alpha_pll_stromer_set_rate() function writes inproper values into the ALPHA_VAL{,_U} registers which results in wrong clock rates when the alpha value is used. The broken behaviour can be seen on IPQ5018 for example, when dynamic scaling sets the CPU frequency to 800000 KHz. In this case the CPU cores are running only at 792031 KHz: # cat /sys/devices/system/cpu/cpu0/cpufreq/scaling_cur_freq 800000 # cat /sys/devices/system/cpu/cpu0/cpufreq/cpuinfo_cur_freq 792031 This happens because the function ignores the fact that the alpha value calculated by the alpha_pll_round_rate() function is only 32 bits wide which must be extended to 40 bits if it is used on a hardware which supports 40 bits wide values. Extend the clk_alpha_pll_stromer_set_rate() function to convert the alpha value to 40 bits before wrinting that into the registers in order to ensure that the hardware really uses the requested rate. After the change the CPU frequency is correct: # cat /sys/devices/system/cpu/cpu0/cpufreq/scaling_cur_freq 800000 # cat /sys/devices/system/cpu/cpu0/cpufreq/cpuinfo_cur_freq 800000 Cc: stable@vger.kernel.org Fixes: e47a4f55f240 ("clk: qcom: clk-alpha-pll: Add support for Stromer PLLs") Reviewed-by: Dmitry Baryshkov Signed-off-by: Gabor Juhos Link: https://lore.kernel.org/r/20240328-alpha-pll-fix-stromer-set-rate-v3-1-1b79714c78bc@gmail.com Signed-off-by: Bjorn Andersson --- drivers/clk/qcom/clk-alpha-pll.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/clk/qcom/clk-alpha-pll.c b/drivers/clk/qcom/clk-alpha-pll.c index 236794cb3e50..d4227909d1fe 100644 --- a/drivers/clk/qcom/clk-alpha-pll.c +++ b/drivers/clk/qcom/clk-alpha-pll.c @@ -2508,6 +2508,8 @@ static int clk_alpha_pll_stromer_set_rate(struct clk_hw *hw, unsigned long rate, rate = alpha_pll_round_rate(rate, prate, &l, &a, ALPHA_REG_BITWIDTH); regmap_write(pll->clkr.regmap, PLL_L_VAL(pll), l); + + a <<= ALPHA_REG_BITWIDTH - ALPHA_BITWIDTH; regmap_write(pll->clkr.regmap, PLL_ALPHA_VAL(pll), a); regmap_write(pll->clkr.regmap, PLL_ALPHA_VAL_U(pll), a >> ALPHA_BITWIDTH); From bc2da26599ed800357f24fca4b7f6a8f35d87dcb Mon Sep 17 00:00:00 2001 From: Conor Dooley Date: Wed, 8 May 2024 22:33:24 +0100 Subject: [PATCH 117/118] clk, reset: microchip: mpfs: fix incorrect preprocessor conditions While moving all the reset code in the PolarFire SoC clock driver to the reset subsystem, I removed an `#if IS_ENABLED(RESET_CONTROLLER)` from the driver and moved it to the header, however this was not the correct thing to do. In the driver such a condition over-eagerly provided a complete implementation for mpfs_reset_{read,write}() when the reset subsystem was enabled without the PolarFire SoC reset driver, but in the header it meant that when the subsystem was enabled and the driver was not, no implementation for mpfs_reset_controller_register() was provided. Fix the condition so that the stub implementation of mpfs_reset_controller_register() is used when the reset driver is disabled. Fixes: 098c290a490d ("clock, reset: microchip: move all mpfs reset code to the reset subsystem") Reported-by: kernel test robot Closes: https://lore.kernel.org/oe-kbuild-all/202405082259.44DzHvaN-lkp@intel.com/ Closes: https://lore.kernel.org/oe-kbuild-all/202405082200.tBrEs5CZ-lkp@intel.com/ Signed-off-by: Conor Dooley Link: https://lore.kernel.org/r/20240508-unabashed-cheese-8f645b4f69ba@spud Signed-off-by: Stephen Boyd --- include/soc/microchip/mpfs.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/include/soc/microchip/mpfs.h b/include/soc/microchip/mpfs.h index d7e612b5e22e..0bd67e10b704 100644 --- a/include/soc/microchip/mpfs.h +++ b/include/soc/microchip/mpfs.h @@ -43,11 +43,11 @@ struct mtd_info *mpfs_sys_controller_get_flash(struct mpfs_sys_controller *mpfs_ #endif /* if IS_ENABLED(CONFIG_POLARFIRE_SOC_SYS_CTRL) */ #if IS_ENABLED(CONFIG_MCHP_CLK_MPFS) -#if IS_ENABLED(CONFIG_RESET_CONTROLLER) +#if IS_ENABLED(CONFIG_RESET_POLARFIRE_SOC) int mpfs_reset_controller_register(struct device *clk_dev, void __iomem *base); #else static inline int mpfs_reset_controller_register(struct device *clk_dev, void __iomem *base) { return 0; } -#endif /* if IS_ENABLED(CONFIG_RESET_CONTROLLER) */ +#endif /* if IS_ENABLED(CONFIG_RESET_POLARFIRE_SOC) */ #endif /* if IS_ENABLED(CONFIG_MCHP_CLK_MPFS) */ #endif /* __SOC_MPFS_H__ */ From 0dc83ad8bfc9b5d40c1207674cecf77b85f54646 Mon Sep 17 00:00:00 2001 From: Marek Szyprowski Date: Fri, 10 May 2024 08:59:01 +0200 Subject: [PATCH 118/118] clk: samsung: Don't register clkdev lookup for the fixed rate clocks Commit 4d11c62ca8d7 ("clkdev: report over-sized strings when creating clkdev entries") revealed that clock lookup is registered for all fixed clocks. The mentioned commit added a check if the registered name is not too long. This fails for some clocks registered for Exynos542x SoCs family. This lookup is a left-over from early common clock framework days, not really needed nowadays, so remove it to avoid further issues. Signed-off-by: Marek Szyprowski Reviewed-by: Sam Protsenko Tested-by: Sam Protsenko Link: https://lore.kernel.org/r/20240510065901.535124-1-m.szyprowski@samsung.com Signed-off-by: Stephen Boyd --- drivers/clk/samsung/clk.c | 11 +---------- 1 file changed, 1 insertion(+), 10 deletions(-) diff --git a/drivers/clk/samsung/clk.c b/drivers/clk/samsung/clk.c index b6701905f254..afa5760ed3a1 100644 --- a/drivers/clk/samsung/clk.c +++ b/drivers/clk/samsung/clk.c @@ -139,7 +139,7 @@ void __init samsung_clk_register_fixed_rate(struct samsung_clk_provider *ctx, unsigned int nr_clk) { struct clk_hw *clk_hw; - unsigned int idx, ret; + unsigned int idx; for (idx = 0; idx < nr_clk; idx++, list++) { clk_hw = clk_hw_register_fixed_rate(ctx->dev, list->name, @@ -151,15 +151,6 @@ void __init samsung_clk_register_fixed_rate(struct samsung_clk_provider *ctx, } samsung_clk_add_lookup(ctx, clk_hw, list->id); - - /* - * Unconditionally add a clock lookup for the fixed rate clocks. - * There are not many of these on any of Samsung platforms. - */ - ret = clk_hw_register_clkdev(clk_hw, list->name, NULL); - if (ret) - pr_err("%s: failed to register clock lookup for %s", - __func__, list->name); } }