From a26edd3d3c286c47ad3e554922ab03816d7431fb Mon Sep 17 00:00:00 2001 From: Niklas Söderlund Date: Wed, 9 Dec 2020 20:53:40 +0100 Subject: clk: renesas: r8a7796: Add TMU clocks MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This patch adds TMU{0,1,2,3,4} clocks. Signed-off-by: Niklas Söderlund Link: https://lore.kernel.org/r/20201209195343.803120-3-niklas.soderlund+renesas@ragnatech.se Signed-off-by: Geert Uytterhoeven --- drivers/clk/renesas/r8a7796-cpg-mssr.c | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'drivers/clk') diff --git a/drivers/clk/renesas/r8a7796-cpg-mssr.c b/drivers/clk/renesas/r8a7796-cpg-mssr.c index 2cd6e3876fbd..41593c126faf 100644 --- a/drivers/clk/renesas/r8a7796-cpg-mssr.c +++ b/drivers/clk/renesas/r8a7796-cpg-mssr.c @@ -128,6 +128,11 @@ static const struct cpg_core_clk r8a7796_core_clks[] __initconst = { static struct mssr_mod_clk r8a7796_mod_clks[] __initdata = { DEF_MOD("fdp1-0", 119, R8A7796_CLK_S0D1), + DEF_MOD("tmu4", 121, R8A7796_CLK_S0D6), + DEF_MOD("tmu3", 122, R8A7796_CLK_S3D2), + DEF_MOD("tmu2", 123, R8A7796_CLK_S3D2), + DEF_MOD("tmu1", 124, R8A7796_CLK_S3D2), + DEF_MOD("tmu0", 125, R8A7796_CLK_CP), DEF_MOD("scif5", 202, R8A7796_CLK_S3D4), DEF_MOD("scif4", 203, R8A7796_CLK_S3D4), DEF_MOD("scif3", 204, R8A7796_CLK_S3D4), -- cgit v1.2.3 From e0c0d449346085f0ac71f2adef2808dc9e679fa0 Mon Sep 17 00:00:00 2001 From: Niklas Söderlund Date: Wed, 9 Dec 2020 20:53:41 +0100 Subject: clk: renesas: r8a77965: Add TMU clocks MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This patch adds TMU{0,1,2,3,4} clocks. Signed-off-by: Niklas Söderlund Link: https://lore.kernel.org/r/20201209195343.803120-4-niklas.soderlund+renesas@ragnatech.se Signed-off-by: Geert Uytterhoeven --- drivers/clk/renesas/r8a77965-cpg-mssr.c | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'drivers/clk') diff --git a/drivers/clk/renesas/r8a77965-cpg-mssr.c b/drivers/clk/renesas/r8a77965-cpg-mssr.c index 2b55a06ac5cf..46a157732759 100644 --- a/drivers/clk/renesas/r8a77965-cpg-mssr.c +++ b/drivers/clk/renesas/r8a77965-cpg-mssr.c @@ -123,6 +123,11 @@ static const struct cpg_core_clk r8a77965_core_clks[] __initconst = { static const struct mssr_mod_clk r8a77965_mod_clks[] __initconst = { DEF_MOD("fdp1-0", 119, R8A77965_CLK_S0D1), + DEF_MOD("tmu4", 121, R8A77965_CLK_S0D6), + DEF_MOD("tmu3", 122, R8A77965_CLK_S3D2), + DEF_MOD("tmu2", 123, R8A77965_CLK_S3D2), + DEF_MOD("tmu1", 124, R8A77965_CLK_S3D2), + DEF_MOD("tmu0", 125, R8A77965_CLK_CP), DEF_MOD("scif5", 202, R8A77965_CLK_S3D4), DEF_MOD("scif4", 203, R8A77965_CLK_S3D4), DEF_MOD("scif3", 204, R8A77965_CLK_S3D4), -- cgit v1.2.3 From 0f3a9265941bbcf75f870f7e1ce20e90d735862d Mon Sep 17 00:00:00 2001 From: Niklas Söderlund Date: Wed, 9 Dec 2020 20:53:42 +0100 Subject: clk: renesas: r8a77990: Add TMU clocks MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This patch adds TMU{0,1,2,3,4} clocks. Signed-off-by: Niklas Söderlund Link: https://lore.kernel.org/r/20201209195343.803120-5-niklas.soderlund+renesas@ragnatech.se Signed-off-by: Geert Uytterhoeven --- drivers/clk/renesas/r8a77990-cpg-mssr.c | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'drivers/clk') diff --git a/drivers/clk/renesas/r8a77990-cpg-mssr.c b/drivers/clk/renesas/r8a77990-cpg-mssr.c index 2b97ab61d044..2d172f80b34c 100644 --- a/drivers/clk/renesas/r8a77990-cpg-mssr.c +++ b/drivers/clk/renesas/r8a77990-cpg-mssr.c @@ -124,6 +124,11 @@ static const struct cpg_core_clk r8a77990_core_clks[] __initconst = { }; static const struct mssr_mod_clk r8a77990_mod_clks[] __initconst = { + DEF_MOD("tmu4", 121, R8A77990_CLK_S0D6C), + DEF_MOD("tmu3", 122, R8A77990_CLK_S3D2C), + DEF_MOD("tmu2", 123, R8A77990_CLK_S3D2C), + DEF_MOD("tmu1", 124, R8A77990_CLK_S3D2C), + DEF_MOD("tmu0", 125, R8A77990_CLK_CP), DEF_MOD("scif5", 202, R8A77990_CLK_S3D4C), DEF_MOD("scif4", 203, R8A77990_CLK_S3D4C), DEF_MOD("scif3", 204, R8A77990_CLK_S3D4C), -- cgit v1.2.3 From fa7f47972b13d1791494bb5019db8a8951a6fea3 Mon Sep 17 00:00:00 2001 From: Niklas Söderlund Date: Wed, 9 Dec 2020 20:53:43 +0100 Subject: clk: renesas: r8a77995: Add TMU clocks MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This patch adds TMU{0,1,2,3,4} clocks. Signed-off-by: Niklas Söderlund Link: https://lore.kernel.org/r/20201209195343.803120-6-niklas.soderlund+renesas@ragnatech.se Signed-off-by: Geert Uytterhoeven --- drivers/clk/renesas/r8a77995-cpg-mssr.c | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'drivers/clk') diff --git a/drivers/clk/renesas/r8a77995-cpg-mssr.c b/drivers/clk/renesas/r8a77995-cpg-mssr.c index 5b4691117b47..9cfd00cf4e69 100644 --- a/drivers/clk/renesas/r8a77995-cpg-mssr.c +++ b/drivers/clk/renesas/r8a77995-cpg-mssr.c @@ -111,6 +111,11 @@ static const struct cpg_core_clk r8a77995_core_clks[] __initconst = { }; static const struct mssr_mod_clk r8a77995_mod_clks[] __initconst = { + DEF_MOD("tmu4", 121, R8A77995_CLK_S1D4C), + DEF_MOD("tmu3", 122, R8A77995_CLK_S3D2C), + DEF_MOD("tmu2", 123, R8A77995_CLK_S3D2C), + DEF_MOD("tmu1", 124, R8A77995_CLK_S3D2C), + DEF_MOD("tmu0", 125, R8A77995_CLK_CP), DEF_MOD("scif5", 202, R8A77995_CLK_S3D4C), DEF_MOD("scif4", 203, R8A77995_CLK_S3D4C), DEF_MOD("scif3", 204, R8A77995_CLK_S3D4C), -- cgit v1.2.3 From 0177b5090effab70762c774b860df8d298e62ff4 Mon Sep 17 00:00:00 2001 From: Kieran Bingham Date: Wed, 16 Dec 2020 15:19:29 +0000 Subject: clk: renesas: r8a779a0: Add FCPVD clock support Add clocks for the FCP for VSP-D module. Signed-off-by: Kieran Bingham Link: https://lore.kernel.org/r/20201216151931.851547-2-kieran.bingham+renesas@ideasonboard.com Signed-off-by: Geert Uytterhoeven --- drivers/clk/renesas/r8a779a0-cpg-mssr.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'drivers/clk') diff --git a/drivers/clk/renesas/r8a779a0-cpg-mssr.c b/drivers/clk/renesas/r8a779a0-cpg-mssr.c index aa5389b04d74..8160f41191b2 100644 --- a/drivers/clk/renesas/r8a779a0-cpg-mssr.c +++ b/drivers/clk/renesas/r8a779a0-cpg-mssr.c @@ -152,6 +152,8 @@ static const struct mssr_mod_clk r8a779a0_mod_clks[] __initconst = { DEF_MOD("csi41", 400, R8A779A0_CLK_CSI0), DEF_MOD("csi42", 401, R8A779A0_CLK_CSI0), DEF_MOD("csi43", 402, R8A779A0_CLK_CSI0), + DEF_MOD("fcpvd0", 508, R8A779A0_CLK_S3D1), + DEF_MOD("fcpvd1", 509, R8A779A0_CLK_S3D1), DEF_MOD("scif0", 702, R8A779A0_CLK_S1D8), DEF_MOD("scif1", 703, R8A779A0_CLK_S1D8), DEF_MOD("scif3", 704, R8A779A0_CLK_S1D8), -- cgit v1.2.3 From ed447e7d60de9ee28763a9e0d215267db7498639 Mon Sep 17 00:00:00 2001 From: Kieran Bingham Date: Wed, 16 Dec 2020 15:19:30 +0000 Subject: clk: renesas: r8a779a0: Add VSPD clock support Add clocks for the VSPD modules on the V3U. Signed-off-by: Kieran Bingham Link: https://lore.kernel.org/r/20201216151931.851547-3-kieran.bingham+renesas@ideasonboard.com Signed-off-by: Geert Uytterhoeven --- drivers/clk/renesas/r8a779a0-cpg-mssr.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'drivers/clk') diff --git a/drivers/clk/renesas/r8a779a0-cpg-mssr.c b/drivers/clk/renesas/r8a779a0-cpg-mssr.c index 8160f41191b2..2ce31508db73 100644 --- a/drivers/clk/renesas/r8a779a0-cpg-mssr.c +++ b/drivers/clk/renesas/r8a779a0-cpg-mssr.c @@ -190,6 +190,8 @@ static const struct mssr_mod_clk r8a779a0_mod_clks[] __initconst = { DEF_MOD("vin35", 827, R8A779A0_CLK_S1D1), DEF_MOD("vin36", 828, R8A779A0_CLK_S1D1), DEF_MOD("vin37", 829, R8A779A0_CLK_S1D1), + DEF_MOD("vspd0", 830, R8A779A0_CLK_S3D1), + DEF_MOD("vspd1", 831, R8A779A0_CLK_S3D1), }; static spinlock_t cpg_lock; -- cgit v1.2.3 From 57be2dc8d4cf4791993bd3e4caf586f3adfb7f6d Mon Sep 17 00:00:00 2001 From: Kieran Bingham Date: Wed, 16 Dec 2020 15:19:31 +0000 Subject: clk: renesas: r8a779a0: Add VSPX clock support Add clocks for the VSPX. Signed-off-by: Kieran Bingham Link: https://lore.kernel.org/r/20201216151931.851547-4-kieran.bingham+renesas@ideasonboard.com Signed-off-by: Geert Uytterhoeven --- drivers/clk/renesas/r8a779a0-cpg-mssr.c | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'drivers/clk') diff --git a/drivers/clk/renesas/r8a779a0-cpg-mssr.c b/drivers/clk/renesas/r8a779a0-cpg-mssr.c index 2ce31508db73..d7825adcb19d 100644 --- a/drivers/clk/renesas/r8a779a0-cpg-mssr.c +++ b/drivers/clk/renesas/r8a779a0-cpg-mssr.c @@ -192,6 +192,10 @@ static const struct mssr_mod_clk r8a779a0_mod_clks[] __initconst = { DEF_MOD("vin37", 829, R8A779A0_CLK_S1D1), DEF_MOD("vspd0", 830, R8A779A0_CLK_S3D1), DEF_MOD("vspd1", 831, R8A779A0_CLK_S3D1), + DEF_MOD("vspx0", 1028, R8A779A0_CLK_S1D1), + DEF_MOD("vspx1", 1029, R8A779A0_CLK_S1D1), + DEF_MOD("vspx2", 1030, R8A779A0_CLK_S1D1), + DEF_MOD("vspx3", 1031, R8A779A0_CLK_S1D1), }; static spinlock_t cpg_lock; -- cgit v1.2.3 From ab2ccacd73867c6be285ba4f3c1a3e10b96e9a1d Mon Sep 17 00:00:00 2001 From: Wolfram Sang Date: Fri, 18 Dec 2020 18:37:27 +0100 Subject: clk: renesas: r8a779a0: Add RWDT clocks And introduce critical clocks, too, because RWDT is one. Signed-off-by: Wolfram Sang Link: https://lore.kernel.org/r/20201218173731.12839-3-wsa+renesas@sang-engineering.com Signed-off-by: Geert Uytterhoeven --- drivers/clk/renesas/r8a779a0-cpg-mssr.c | 9 +++++++++ 1 file changed, 9 insertions(+) (limited to 'drivers/clk') diff --git a/drivers/clk/renesas/r8a779a0-cpg-mssr.c b/drivers/clk/renesas/r8a779a0-cpg-mssr.c index d7825adcb19d..f93ba9a6cb26 100644 --- a/drivers/clk/renesas/r8a779a0-cpg-mssr.c +++ b/drivers/clk/renesas/r8a779a0-cpg-mssr.c @@ -192,6 +192,7 @@ static const struct mssr_mod_clk r8a779a0_mod_clks[] __initconst = { DEF_MOD("vin37", 829, R8A779A0_CLK_S1D1), DEF_MOD("vspd0", 830, R8A779A0_CLK_S3D1), DEF_MOD("vspd1", 831, R8A779A0_CLK_S3D1), + DEF_MOD("rwdt", 907, R8A779A0_CLK_R), DEF_MOD("vspx0", 1028, R8A779A0_CLK_S1D1), DEF_MOD("vspx1", 1029, R8A779A0_CLK_S1D1), DEF_MOD("vspx2", 1030, R8A779A0_CLK_S1D1), @@ -269,6 +270,10 @@ static struct clk * __init rcar_r8a779a0_cpg_clk_register(struct device *dev, __clk_get_name(parent), 0, mult, div); } +static const unsigned int r8a779a0_crit_mod_clks[] __initconst = { + MOD_CLK_ID(907), /* RWDT */ +}; + /* * CPG Clock Data */ @@ -319,6 +324,10 @@ const struct cpg_mssr_info r8a779a0_cpg_mssr_info __initconst = { .num_mod_clks = ARRAY_SIZE(r8a779a0_mod_clks), .num_hw_mod_clks = 15 * 32, + /* Critical Module Clocks */ + .crit_mod_clks = r8a779a0_crit_mod_clks, + .num_crit_mod_clks = ARRAY_SIZE(r8a779a0_crit_mod_clks), + /* Callbacks */ .init = r8a779a0_cpg_mssr_init, .cpg_clk_register = rcar_r8a779a0_cpg_clk_register, -- cgit v1.2.3 From 0482a4e6de19bcfc3729dcc13b7b6dde03375bdb Mon Sep 17 00:00:00 2001 From: Samuel Holland Date: Sun, 3 Jan 2021 04:00:04 -0600 Subject: clk: sunxi-ng: h6-r: Add R_APB2_RSB clock and reset While no information about the H6 RSB controller is included in the datasheet or manual, the vendor BSP and power management blob both reference the RSB clock parent and register address. These values were verified by experimentation. Since this clock/reset are added late, the specifier is added at the end to maintain the existing DT binding. The code is kept in register order. Signed-off-by: Samuel Holland Acked-by: Maxime Ripard Signed-off-by: Chen-Yu Tsai --- drivers/clk/sunxi-ng/ccu-sun50i-h6-r.c | 5 +++++ drivers/clk/sunxi-ng/ccu-sun50i-h6-r.h | 2 +- include/dt-bindings/clock/sun50i-h6-r-ccu.h | 2 ++ include/dt-bindings/reset/sun50i-h6-r-ccu.h | 1 + 4 files changed, 9 insertions(+), 1 deletion(-) (limited to 'drivers/clk') diff --git a/drivers/clk/sunxi-ng/ccu-sun50i-h6-r.c b/drivers/clk/sunxi-ng/ccu-sun50i-h6-r.c index 50f8d1bc7046..56e351b513f3 100644 --- a/drivers/clk/sunxi-ng/ccu-sun50i-h6-r.c +++ b/drivers/clk/sunxi-ng/ccu-sun50i-h6-r.c @@ -91,6 +91,8 @@ static SUNXI_CCU_GATE(r_apb2_uart_clk, "r-apb2-uart", "r-apb2", 0x18c, BIT(0), 0); static SUNXI_CCU_GATE(r_apb2_i2c_clk, "r-apb2-i2c", "r-apb2", 0x19c, BIT(0), 0); +static SUNXI_CCU_GATE(r_apb2_rsb_clk, "r-apb2-rsb", "r-apb2", + 0x1bc, BIT(0), 0); static SUNXI_CCU_GATE(r_apb1_ir_clk, "r-apb1-ir", "r-apb1", 0x1cc, BIT(0), 0); static SUNXI_CCU_GATE(r_apb1_w1_clk, "r-apb1-w1", "r-apb1", @@ -130,6 +132,7 @@ static struct ccu_common *sun50i_h6_r_ccu_clks[] = { &r_apb1_pwm_clk.common, &r_apb2_uart_clk.common, &r_apb2_i2c_clk.common, + &r_apb2_rsb_clk.common, &r_apb1_ir_clk.common, &r_apb1_w1_clk.common, &ir_clk.common, @@ -147,6 +150,7 @@ static struct clk_hw_onecell_data sun50i_h6_r_hw_clks = { [CLK_R_APB1_PWM] = &r_apb1_pwm_clk.common.hw, [CLK_R_APB2_UART] = &r_apb2_uart_clk.common.hw, [CLK_R_APB2_I2C] = &r_apb2_i2c_clk.common.hw, + [CLK_R_APB2_RSB] = &r_apb2_rsb_clk.common.hw, [CLK_R_APB1_IR] = &r_apb1_ir_clk.common.hw, [CLK_R_APB1_W1] = &r_apb1_w1_clk.common.hw, [CLK_IR] = &ir_clk.common.hw, @@ -161,6 +165,7 @@ static struct ccu_reset_map sun50i_h6_r_ccu_resets[] = { [RST_R_APB1_PWM] = { 0x13c, BIT(16) }, [RST_R_APB2_UART] = { 0x18c, BIT(16) }, [RST_R_APB2_I2C] = { 0x19c, BIT(16) }, + [RST_R_APB2_RSB] = { 0x1bc, BIT(16) }, [RST_R_APB1_IR] = { 0x1cc, BIT(16) }, [RST_R_APB1_W1] = { 0x1ec, BIT(16) }, }; diff --git a/drivers/clk/sunxi-ng/ccu-sun50i-h6-r.h b/drivers/clk/sunxi-ng/ccu-sun50i-h6-r.h index 782117dc0b28..7e290b840803 100644 --- a/drivers/clk/sunxi-ng/ccu-sun50i-h6-r.h +++ b/drivers/clk/sunxi-ng/ccu-sun50i-h6-r.h @@ -14,6 +14,6 @@ #define CLK_R_APB2 3 -#define CLK_NUMBER (CLK_W1 + 1) +#define CLK_NUMBER (CLK_R_APB2_RSB + 1) #endif /* _CCU_SUN50I_H6_R_H */ diff --git a/include/dt-bindings/clock/sun50i-h6-r-ccu.h b/include/dt-bindings/clock/sun50i-h6-r-ccu.h index 76136132a13e..890368d252c4 100644 --- a/include/dt-bindings/clock/sun50i-h6-r-ccu.h +++ b/include/dt-bindings/clock/sun50i-h6-r-ccu.h @@ -21,4 +21,6 @@ #define CLK_IR 11 #define CLK_W1 12 +#define CLK_R_APB2_RSB 13 + #endif /* _DT_BINDINGS_CLK_SUN50I_H6_R_CCU_H_ */ diff --git a/include/dt-bindings/reset/sun50i-h6-r-ccu.h b/include/dt-bindings/reset/sun50i-h6-r-ccu.h index 01c84dba49a4..7950e799c76d 100644 --- a/include/dt-bindings/reset/sun50i-h6-r-ccu.h +++ b/include/dt-bindings/reset/sun50i-h6-r-ccu.h @@ -13,5 +13,6 @@ #define RST_R_APB2_I2C 4 #define RST_R_APB1_IR 5 #define RST_R_APB1_W1 6 +#define RST_R_APB2_RSB 7 #endif /* _DT_BINDINGS_RST_SUN50I_H6_R_CCU_H_ */ -- cgit v1.2.3 From 756650820abd4770c4200763505b634a3c04e05e Mon Sep 17 00:00:00 2001 From: Andre Przywara Date: Wed, 6 Jan 2021 14:32:46 +0000 Subject: clk: sunxi-ng: h6: Fix CEC clock The CEC clock on the H6 SoC is a bit special, since it uses a fixed pre-dividier for one source clock (the PLL), but conveys the other clock (32K OSC) directly. We are using a fixed predivider array for that, but fail to use the right flag to actually activate that. Fixes: 524353ea480b ("clk: sunxi-ng: add support for the Allwinner H6 CCU") Reported-by: Jernej Skrabec Signed-off-by: Andre Przywara Acked-by: Chen-Yu Tsai Signed-off-by: Maxime Ripard Link: https://lore.kernel.org/r/20210106143246.11255-1-andre.przywara@arm.com --- drivers/clk/sunxi-ng/ccu-sun50i-h6.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/clk') diff --git a/drivers/clk/sunxi-ng/ccu-sun50i-h6.c b/drivers/clk/sunxi-ng/ccu-sun50i-h6.c index f2497d0a4683..a26dbbdff80d 100644 --- a/drivers/clk/sunxi-ng/ccu-sun50i-h6.c +++ b/drivers/clk/sunxi-ng/ccu-sun50i-h6.c @@ -682,7 +682,7 @@ static struct ccu_mux hdmi_cec_clk = { .common = { .reg = 0xb10, - .features = CCU_FEATURE_VARIABLE_PREDIV, + .features = CCU_FEATURE_FIXED_PREDIV, .hw.init = CLK_HW_INIT_PARENTS("hdmi-cec", hdmi_cec_parents, &ccu_mux_ops, -- cgit v1.2.3 From 2e16d0df87baa84485031b88b1b149badbc68810 Mon Sep 17 00:00:00 2001 From: Wolfram Sang Date: Mon, 28 Dec 2020 12:27:11 +0100 Subject: clk: renesas: r8a779a0: Add HSCIF support Signed-off-by: Wolfram Sang Link: https://lore.kernel.org/r/20201228112715.14947-5-wsa+renesas@sang-engineering.com Signed-off-by: Geert Uytterhoeven --- drivers/clk/renesas/r8a779a0-cpg-mssr.c | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'drivers/clk') diff --git a/drivers/clk/renesas/r8a779a0-cpg-mssr.c b/drivers/clk/renesas/r8a779a0-cpg-mssr.c index f93ba9a6cb26..1e222b5d8e48 100644 --- a/drivers/clk/renesas/r8a779a0-cpg-mssr.c +++ b/drivers/clk/renesas/r8a779a0-cpg-mssr.c @@ -154,6 +154,10 @@ static const struct mssr_mod_clk r8a779a0_mod_clks[] __initconst = { DEF_MOD("csi43", 402, R8A779A0_CLK_CSI0), DEF_MOD("fcpvd0", 508, R8A779A0_CLK_S3D1), DEF_MOD("fcpvd1", 509, R8A779A0_CLK_S3D1), + DEF_MOD("hscif0", 514, R8A779A0_CLK_S1D2), + DEF_MOD("hscif1", 515, R8A779A0_CLK_S1D2), + DEF_MOD("hscif2", 516, R8A779A0_CLK_S1D2), + DEF_MOD("hscif3", 517, R8A779A0_CLK_S1D2), DEF_MOD("scif0", 702, R8A779A0_CLK_S1D8), DEF_MOD("scif1", 703, R8A779A0_CLK_S1D8), DEF_MOD("scif3", 704, R8A779A0_CLK_S1D8), -- cgit v1.2.3 From 5b30be15ca262d9cb2c36b173bb488e8d1952ea0 Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Mon, 19 Oct 2020 14:06:09 +0200 Subject: clk: renesas: r8a779a0: Remove non-existent S2 clock The S2 internal core clock does not exist on R-Car V3U. Remove it. Fixes: 17bcc8035d2d19fc ("clk: renesas: cpg-mssr: Add support for R-Car V3U") Signed-off-by: Geert Uytterhoeven Reviewed-by: Yoshihiro Shimoda Tested-by: Wolfram Sang Link: https://lore.kernel.org/r/20201019120614.22149-2-geert+renesas@glider.be --- drivers/clk/renesas/r8a779a0-cpg-mssr.c | 1 - 1 file changed, 1 deletion(-) (limited to 'drivers/clk') diff --git a/drivers/clk/renesas/r8a779a0-cpg-mssr.c b/drivers/clk/renesas/r8a779a0-cpg-mssr.c index 1e222b5d8e48..312450940dbd 100644 --- a/drivers/clk/renesas/r8a779a0-cpg-mssr.c +++ b/drivers/clk/renesas/r8a779a0-cpg-mssr.c @@ -69,7 +69,6 @@ enum clk_ids { CLK_PLL5_DIV2, CLK_PLL5_DIV4, CLK_S1, - CLK_S2, CLK_S3, CLK_SDSRC, CLK_RPCSRC, -- cgit v1.2.3 From 80d3e07ec509c5098d44e4f1416cc9f133fd436f Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Mon, 19 Oct 2020 14:06:10 +0200 Subject: clk: renesas: r8a779a0: Fix parent of CBFUSA clock According to Figure 8.1.1 ("Block Diagram of CPG (R-Car V3U-AD)") in the R-Car V3U Series User's Manual Rev. 0.5, the parent of the CBFUSA clock is EXTAL. Fixes: 17bcc8035d2d19fc ("clk: renesas: cpg-mssr: Add support for R-Car V3U") Signed-off-by: Geert Uytterhoeven Reviewed-by: Yoshihiro Shimoda Tested-by: Wolfram Sang Link: https://lore.kernel.org/r/20201019120614.22149-3-geert+renesas@glider.be --- drivers/clk/renesas/r8a779a0-cpg-mssr.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/clk') diff --git a/drivers/clk/renesas/r8a779a0-cpg-mssr.c b/drivers/clk/renesas/r8a779a0-cpg-mssr.c index 312450940dbd..0beee561d424 100644 --- a/drivers/clk/renesas/r8a779a0-cpg-mssr.c +++ b/drivers/clk/renesas/r8a779a0-cpg-mssr.c @@ -136,7 +136,7 @@ static const struct cpg_core_clk r8a779a0_core_clks[] __initconst = { DEF_FIXED("icu", R8A779A0_CLK_ICU, CLK_PLL5_DIV4, 2, 1), DEF_FIXED("icud2", R8A779A0_CLK_ICUD2, CLK_PLL5_DIV4, 4, 1), DEF_FIXED("vcbus", R8A779A0_CLK_VCBUS, CLK_PLL5_DIV4, 1, 1), - DEF_FIXED("cbfusa", R8A779A0_CLK_CBFUSA, CLK_MAIN, 2, 1), + DEF_FIXED("cbfusa", R8A779A0_CLK_CBFUSA, CLK_EXTAL, 2, 1), DEF_DIV6P1("mso", R8A779A0_CLK_MSO, CLK_PLL5_DIV4, 0x87c), DEF_DIV6P1("canfd", R8A779A0_CLK_CANFD, CLK_PLL5_DIV4, 0x878), -- cgit v1.2.3 From f08b0d8498b07d9332485f3077b40cfd86cf6789 Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Mon, 19 Oct 2020 14:06:11 +0200 Subject: clk: renesas: r8a779a0: Add PFC/GPIO clocks Add the module clocks used by the Pin Function Controller (PFC) and General Purpose Input/Output (GPIO) blocks, and their parent clock CP. Signed-off-by: Geert Uytterhoeven Reviewed-by: Yoshihiro Shimoda Tested-by: Wolfram Sang Link: https://lore.kernel.org/r/20201019120614.22149-4-geert+renesas@glider.be --- drivers/clk/renesas/r8a779a0-cpg-mssr.c | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'drivers/clk') diff --git a/drivers/clk/renesas/r8a779a0-cpg-mssr.c b/drivers/clk/renesas/r8a779a0-cpg-mssr.c index 0beee561d424..1f4147254a46 100644 --- a/drivers/clk/renesas/r8a779a0-cpg-mssr.c +++ b/drivers/clk/renesas/r8a779a0-cpg-mssr.c @@ -137,6 +137,7 @@ static const struct cpg_core_clk r8a779a0_core_clks[] __initconst = { DEF_FIXED("icud2", R8A779A0_CLK_ICUD2, CLK_PLL5_DIV4, 4, 1), DEF_FIXED("vcbus", R8A779A0_CLK_VCBUS, CLK_PLL5_DIV4, 1, 1), DEF_FIXED("cbfusa", R8A779A0_CLK_CBFUSA, CLK_EXTAL, 2, 1), + DEF_FIXED("cp", R8A779A0_CLK_CP, CLK_EXTAL, 2, 1), DEF_DIV6P1("mso", R8A779A0_CLK_MSO, CLK_PLL5_DIV4, 0x87c), DEF_DIV6P1("canfd", R8A779A0_CLK_CANFD, CLK_PLL5_DIV4, 0x878), @@ -196,6 +197,10 @@ static const struct mssr_mod_clk r8a779a0_mod_clks[] __initconst = { DEF_MOD("vspd0", 830, R8A779A0_CLK_S3D1), DEF_MOD("vspd1", 831, R8A779A0_CLK_S3D1), DEF_MOD("rwdt", 907, R8A779A0_CLK_R), + DEF_MOD("pfc0", 915, R8A779A0_CLK_CP), + DEF_MOD("pfc1", 916, R8A779A0_CLK_CP), + DEF_MOD("pfc2", 917, R8A779A0_CLK_CP), + DEF_MOD("pfc3", 918, R8A779A0_CLK_CP), DEF_MOD("vspx0", 1028, R8A779A0_CLK_S1D1), DEF_MOD("vspx1", 1029, R8A779A0_CLK_S1D1), DEF_MOD("vspx2", 1030, R8A779A0_CLK_S1D1), -- cgit v1.2.3 From 010ce438e7bba81ae1b525795ec2f5313d78485a Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Tue, 17 Nov 2020 10:03:27 +0100 Subject: clk: renesas: r8a779a0: Add MSIOF clocks Add the module clocks used by the Clock-Synchronized Serial Interface with FIFO (MSIOF) instances on the Renesas R-Car V3U (r8a779a0) SoC. Signed-off-by: Geert Uytterhoeven Link: https://lore.kernel.org/r/20201117090329.2128904-3-geert+renesas@glider.be --- drivers/clk/renesas/r8a779a0-cpg-mssr.c | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'drivers/clk') diff --git a/drivers/clk/renesas/r8a779a0-cpg-mssr.c b/drivers/clk/renesas/r8a779a0-cpg-mssr.c index 1f4147254a46..067c71067fd4 100644 --- a/drivers/clk/renesas/r8a779a0-cpg-mssr.c +++ b/drivers/clk/renesas/r8a779a0-cpg-mssr.c @@ -158,6 +158,12 @@ static const struct mssr_mod_clk r8a779a0_mod_clks[] __initconst = { DEF_MOD("hscif1", 515, R8A779A0_CLK_S1D2), DEF_MOD("hscif2", 516, R8A779A0_CLK_S1D2), DEF_MOD("hscif3", 517, R8A779A0_CLK_S1D2), + DEF_MOD("msi0", 618, R8A779A0_CLK_MSO), + DEF_MOD("msi1", 619, R8A779A0_CLK_MSO), + DEF_MOD("msi2", 620, R8A779A0_CLK_MSO), + DEF_MOD("msi3", 621, R8A779A0_CLK_MSO), + DEF_MOD("msi4", 622, R8A779A0_CLK_MSO), + DEF_MOD("msi5", 623, R8A779A0_CLK_MSO), DEF_MOD("scif0", 702, R8A779A0_CLK_S1D8), DEF_MOD("scif1", 703, R8A779A0_CLK_S1D8), DEF_MOD("scif3", 704, R8A779A0_CLK_S1D8), -- cgit v1.2.3 From 97af391a6fdca679aa9863b019137332167b3fa6 Mon Sep 17 00:00:00 2001 From: Wolfram Sang Date: Sun, 27 Dec 2020 18:41:56 +0100 Subject: clk: renesas: rcar-gen3: Remove cpg_quirks access when registering SD clock We want to reuse SD clock handling for other SoCs and, thus, need to generalize it. So, don't access cpg_quirks in that realm. Signed-off-by: Wolfram Sang Link: https://lore.kernel.org/r/20201227174202.40834-3-wsa+renesas@sang-engineering.com Signed-off-by: Geert Uytterhoeven --- drivers/clk/renesas/rcar-gen3-cpg.c | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) (limited to 'drivers/clk') diff --git a/drivers/clk/renesas/rcar-gen3-cpg.c b/drivers/clk/renesas/rcar-gen3-cpg.c index 063b61151488..3b2eb46b7e58 100644 --- a/drivers/clk/renesas/rcar-gen3-cpg.c +++ b/drivers/clk/renesas/rcar-gen3-cpg.c @@ -375,15 +375,9 @@ static const struct clk_ops cpg_sd_clock_ops = { .set_rate = cpg_sd_clock_set_rate, }; -static u32 cpg_quirks __initdata; - -#define PLL_ERRATA BIT(0) /* Missing PLL0/2/4 post-divider */ -#define RCKCR_CKSEL BIT(1) /* Manual RCLK parent selection */ -#define SD_SKIP_FIRST BIT(2) /* Skip first clock in SD table */ - static struct clk * __init cpg_sd_clk_register(const char *name, void __iomem *base, unsigned int offset, const char *parent_name, - struct raw_notifier_head *notifiers) + struct raw_notifier_head *notifiers, bool skip_first) { struct clk_init_data init; struct sd_clock *clock; @@ -405,7 +399,7 @@ static struct clk * __init cpg_sd_clk_register(const char *name, clock->div_table = cpg_sd_div_table; clock->div_num = ARRAY_SIZE(cpg_sd_div_table); - if (cpg_quirks & SD_SKIP_FIRST) { + if (skip_first) { clock->div_table++; clock->div_num--; } @@ -518,6 +512,12 @@ static struct clk * __init cpg_rpcd2_clk_register(const char *name, static const struct rcar_gen3_cpg_pll_config *cpg_pll_config __initdata; static unsigned int cpg_clk_extalr __initdata; static u32 cpg_mode __initdata; +static u32 cpg_quirks __initdata; + +#define PLL_ERRATA BIT(0) /* Missing PLL0/2/4 post-divider */ +#define RCKCR_CKSEL BIT(1) /* Manual RCLK parent selection */ +#define SD_SKIP_FIRST BIT(2) /* Skip first clock in SD table */ + static const struct soc_device_attribute cpg_quirks_match[] __initconst = { { @@ -613,7 +613,8 @@ struct clk * __init rcar_gen3_cpg_clk_register(struct device *dev, case CLK_TYPE_GEN3_SD: return cpg_sd_clk_register(core->name, base, core->offset, - __clk_get_name(parent), notifiers); + __clk_get_name(parent), notifiers, + cpg_quirks & SD_SKIP_FIRST); case CLK_TYPE_GEN3_R: if (cpg_quirks & RCKCR_CKSEL) { -- cgit v1.2.3 From 8bb67d87346a36e174de4d7e5680155f627fd30d Mon Sep 17 00:00:00 2001 From: Wolfram Sang Date: Sun, 27 Dec 2020 18:41:57 +0100 Subject: clk: renesas: rcar-gen3: Factor out CPG library R-Car V3U has a CPG different enough to not be a generic Gen3 CPG but similar enough to reuse code. Introduce a new CPG library, factor out the SD clock handling and hook it to the generic Gen3 CPG driver so we have an equal state. V3U will make use of it in the next patch then. Signed-off-by: Wolfram Sang Link: https://lore.kernel.org/r/20201227174202.40834-4-wsa+renesas@sang-engineering.com Signed-off-by: Geert Uytterhoeven --- drivers/clk/renesas/Kconfig | 4 + drivers/clk/renesas/Makefile | 1 + drivers/clk/renesas/rcar-cpg-lib.c | 270 ++++++++++++++++++++++++++++++++++++ drivers/clk/renesas/rcar-cpg-lib.h | 33 +++++ drivers/clk/renesas/rcar-gen3-cpg.c | 252 +-------------------------------- 5 files changed, 309 insertions(+), 251 deletions(-) create mode 100644 drivers/clk/renesas/rcar-cpg-lib.c create mode 100644 drivers/clk/renesas/rcar-cpg-lib.h (limited to 'drivers/clk') diff --git a/drivers/clk/renesas/Kconfig b/drivers/clk/renesas/Kconfig index 18915d668a30..7e788fee6b9f 100644 --- a/drivers/clk/renesas/Kconfig +++ b/drivers/clk/renesas/Kconfig @@ -162,12 +162,16 @@ config CLK_SH73A0 # Family +config CLK_RCAR_CPG_LIB + bool "CPG/MSSR library functions" if COMPILE_TEST + config CLK_RCAR_GEN2_CPG bool "R-Car Gen2 CPG clock support" if COMPILE_TEST select CLK_RENESAS_CPG_MSSR config CLK_RCAR_GEN3_CPG bool "R-Car Gen3 and RZ/G2 CPG clock support" if COMPILE_TEST + select CLK_RCAR_CPG_LIB select CLK_RENESAS_CPG_MSSR config CLK_RCAR_USB2_CLOCK_SEL diff --git a/drivers/clk/renesas/Makefile b/drivers/clk/renesas/Makefile index c803912ef2ce..ef0d2bba92bf 100644 --- a/drivers/clk/renesas/Makefile +++ b/drivers/clk/renesas/Makefile @@ -32,6 +32,7 @@ obj-$(CONFIG_CLK_R9A06G032) += r9a06g032-clocks.o obj-$(CONFIG_CLK_SH73A0) += clk-sh73a0.o # Family +obj-$(CONFIG_CLK_RCAR_CPG_LIB) += rcar-cpg-lib.o obj-$(CONFIG_CLK_RCAR_GEN2_CPG) += rcar-gen2-cpg.o obj-$(CONFIG_CLK_RCAR_GEN3_CPG) += rcar-gen3-cpg.o obj-$(CONFIG_CLK_RCAR_USB2_CLOCK_SEL) += rcar-usb2-clock-sel.o diff --git a/drivers/clk/renesas/rcar-cpg-lib.c b/drivers/clk/renesas/rcar-cpg-lib.c new file mode 100644 index 000000000000..7e7e5d1341d5 --- /dev/null +++ b/drivers/clk/renesas/rcar-cpg-lib.c @@ -0,0 +1,270 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * R-Car Gen3 Clock Pulse Generator Library + * + * Copyright (C) 2015-2018 Glider bvba + * Copyright (C) 2019 Renesas Electronics Corp. + * + * Based on clk-rcar-gen3.c + * + * Copyright (C) 2015 Renesas Electronics Corp. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "rcar-cpg-lib.h" + +spinlock_t cpg_lock; + +void cpg_reg_modify(void __iomem *reg, u32 clear, u32 set) +{ + unsigned long flags; + u32 val; + + spin_lock_irqsave(&cpg_lock, flags); + val = readl(reg); + val &= ~clear; + val |= set; + writel(val, reg); + spin_unlock_irqrestore(&cpg_lock, flags); +}; + +static int cpg_simple_notifier_call(struct notifier_block *nb, + unsigned long action, void *data) +{ + struct cpg_simple_notifier *csn = + container_of(nb, struct cpg_simple_notifier, nb); + + switch (action) { + case PM_EVENT_SUSPEND: + csn->saved = readl(csn->reg); + return NOTIFY_OK; + + case PM_EVENT_RESUME: + writel(csn->saved, csn->reg); + return NOTIFY_OK; + } + return NOTIFY_DONE; +} + +void cpg_simple_notifier_register(struct raw_notifier_head *notifiers, + struct cpg_simple_notifier *csn) +{ + csn->nb.notifier_call = cpg_simple_notifier_call; + raw_notifier_chain_register(notifiers, &csn->nb); +} + +/* + * SDn Clock + */ +#define CPG_SD_STP_HCK BIT(9) +#define CPG_SD_STP_CK BIT(8) + +#define CPG_SD_STP_MASK (CPG_SD_STP_HCK | CPG_SD_STP_CK) +#define CPG_SD_FC_MASK (0x7 << 2 | 0x3 << 0) + +#define CPG_SD_DIV_TABLE_DATA(stp_hck, sd_srcfc, sd_fc, sd_div) \ +{ \ + .val = ((stp_hck) ? CPG_SD_STP_HCK : 0) | \ + ((sd_srcfc) << 2) | \ + ((sd_fc) << 0), \ + .div = (sd_div), \ +} + +struct sd_div_table { + u32 val; + unsigned int div; +}; + +struct sd_clock { + struct clk_hw hw; + const struct sd_div_table *div_table; + struct cpg_simple_notifier csn; + unsigned int div_num; + unsigned int cur_div_idx; +}; + +/* SDn divider + * sd_srcfc sd_fc div + * stp_hck (div) (div) = sd_srcfc x sd_fc + *--------------------------------------------------------- + * 0 0 (1) 1 (4) 4 : SDR104 / HS200 / HS400 (8 TAP) + * 0 1 (2) 1 (4) 8 : SDR50 + * 1 2 (4) 1 (4) 16 : HS / SDR25 + * 1 3 (8) 1 (4) 32 : NS / SDR12 + * 1 4 (16) 1 (4) 64 + * 0 0 (1) 0 (2) 2 + * 0 1 (2) 0 (2) 4 : SDR104 / HS200 / HS400 (4 TAP) + * 1 2 (4) 0 (2) 8 + * 1 3 (8) 0 (2) 16 + * 1 4 (16) 0 (2) 32 + * + * NOTE: There is a quirk option to ignore the first row of the dividers + * table when searching for suitable settings. This is because HS400 on + * early ES versions of H3 and M3-W requires a specific setting to work. + */ +static const struct sd_div_table cpg_sd_div_table[] = { +/* CPG_SD_DIV_TABLE_DATA(stp_hck, sd_srcfc, sd_fc, sd_div) */ + CPG_SD_DIV_TABLE_DATA(0, 0, 1, 4), + CPG_SD_DIV_TABLE_DATA(0, 1, 1, 8), + CPG_SD_DIV_TABLE_DATA(1, 2, 1, 16), + CPG_SD_DIV_TABLE_DATA(1, 3, 1, 32), + CPG_SD_DIV_TABLE_DATA(1, 4, 1, 64), + CPG_SD_DIV_TABLE_DATA(0, 0, 0, 2), + CPG_SD_DIV_TABLE_DATA(0, 1, 0, 4), + CPG_SD_DIV_TABLE_DATA(1, 2, 0, 8), + CPG_SD_DIV_TABLE_DATA(1, 3, 0, 16), + CPG_SD_DIV_TABLE_DATA(1, 4, 0, 32), +}; + +#define to_sd_clock(_hw) container_of(_hw, struct sd_clock, hw) + +static int cpg_sd_clock_enable(struct clk_hw *hw) +{ + struct sd_clock *clock = to_sd_clock(hw); + + cpg_reg_modify(clock->csn.reg, CPG_SD_STP_MASK, + clock->div_table[clock->cur_div_idx].val & + CPG_SD_STP_MASK); + + return 0; +} + +static void cpg_sd_clock_disable(struct clk_hw *hw) +{ + struct sd_clock *clock = to_sd_clock(hw); + + cpg_reg_modify(clock->csn.reg, 0, CPG_SD_STP_MASK); +} + +static int cpg_sd_clock_is_enabled(struct clk_hw *hw) +{ + struct sd_clock *clock = to_sd_clock(hw); + + return !(readl(clock->csn.reg) & CPG_SD_STP_MASK); +} + +static unsigned long cpg_sd_clock_recalc_rate(struct clk_hw *hw, + unsigned long parent_rate) +{ + struct sd_clock *clock = to_sd_clock(hw); + + return DIV_ROUND_CLOSEST(parent_rate, + clock->div_table[clock->cur_div_idx].div); +} + +static int cpg_sd_clock_determine_rate(struct clk_hw *hw, + struct clk_rate_request *req) +{ + unsigned long best_rate = ULONG_MAX, diff_min = ULONG_MAX; + struct sd_clock *clock = to_sd_clock(hw); + unsigned long calc_rate, diff; + unsigned int i; + + for (i = 0; i < clock->div_num; i++) { + calc_rate = DIV_ROUND_CLOSEST(req->best_parent_rate, + clock->div_table[i].div); + if (calc_rate < req->min_rate || calc_rate > req->max_rate) + continue; + + diff = calc_rate > req->rate ? calc_rate - req->rate + : req->rate - calc_rate; + if (diff < diff_min) { + best_rate = calc_rate; + diff_min = diff; + } + } + + if (best_rate == ULONG_MAX) + return -EINVAL; + + req->rate = best_rate; + return 0; +} + +static int cpg_sd_clock_set_rate(struct clk_hw *hw, unsigned long rate, + unsigned long parent_rate) +{ + struct sd_clock *clock = to_sd_clock(hw); + unsigned int i; + + for (i = 0; i < clock->div_num; i++) + if (rate == DIV_ROUND_CLOSEST(parent_rate, + clock->div_table[i].div)) + break; + + if (i >= clock->div_num) + return -EINVAL; + + clock->cur_div_idx = i; + + cpg_reg_modify(clock->csn.reg, CPG_SD_STP_MASK | CPG_SD_FC_MASK, + clock->div_table[i].val & + (CPG_SD_STP_MASK | CPG_SD_FC_MASK)); + + return 0; +} + +static const struct clk_ops cpg_sd_clock_ops = { + .enable = cpg_sd_clock_enable, + .disable = cpg_sd_clock_disable, + .is_enabled = cpg_sd_clock_is_enabled, + .recalc_rate = cpg_sd_clock_recalc_rate, + .determine_rate = cpg_sd_clock_determine_rate, + .set_rate = cpg_sd_clock_set_rate, +}; + +struct clk * __init cpg_sd_clk_register(const char *name, + void __iomem *base, unsigned int offset, const char *parent_name, + struct raw_notifier_head *notifiers, bool skip_first) +{ + struct clk_init_data init; + struct sd_clock *clock; + struct clk *clk; + u32 val; + + clock = kzalloc(sizeof(*clock), GFP_KERNEL); + if (!clock) + return ERR_PTR(-ENOMEM); + + init.name = name; + init.ops = &cpg_sd_clock_ops; + init.flags = CLK_SET_RATE_PARENT; + init.parent_names = &parent_name; + init.num_parents = 1; + + clock->csn.reg = base + offset; + clock->hw.init = &init; + clock->div_table = cpg_sd_div_table; + clock->div_num = ARRAY_SIZE(cpg_sd_div_table); + + if (skip_first) { + clock->div_table++; + clock->div_num--; + } + + val = readl(clock->csn.reg) & ~CPG_SD_FC_MASK; + val |= CPG_SD_STP_MASK | (clock->div_table[0].val & CPG_SD_FC_MASK); + writel(val, clock->csn.reg); + + clk = clk_register(NULL, &clock->hw); + if (IS_ERR(clk)) + goto free_clock; + + cpg_simple_notifier_register(notifiers, &clock->csn); + return clk; + +free_clock: + kfree(clock); + return clk; +} + + diff --git a/drivers/clk/renesas/rcar-cpg-lib.h b/drivers/clk/renesas/rcar-cpg-lib.h new file mode 100644 index 000000000000..d00c91b116ca --- /dev/null +++ b/drivers/clk/renesas/rcar-cpg-lib.h @@ -0,0 +1,33 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * R-Car Gen3 Clock Pulse Generator Library + * + * Copyright (C) 2015-2018 Glider bvba + * Copyright (C) 2019 Renesas Electronics Corp. + * + * Based on clk-rcar-gen3.c + * + * Copyright (C) 2015 Renesas Electronics Corp. + */ + +#ifndef __CLK_RENESAS_RCAR_CPG_LIB_H__ +#define __CLK_RENESAS_RCAR_CPG_LIB_H__ + +extern spinlock_t cpg_lock; + +struct cpg_simple_notifier { + struct notifier_block nb; + void __iomem *reg; + u32 saved; +}; + +void cpg_simple_notifier_register(struct raw_notifier_head *notifiers, + struct cpg_simple_notifier *csn); + +void cpg_reg_modify(void __iomem *reg, u32 clear, u32 set); + +struct clk * __init cpg_sd_clk_register(const char *name, + void __iomem *base, unsigned int offset, const char *parent_name, + struct raw_notifier_head *notifiers, bool skip_first); + +#endif diff --git a/drivers/clk/renesas/rcar-gen3-cpg.c b/drivers/clk/renesas/rcar-gen3-cpg.c index 3b2eb46b7e58..17826599e9dd 100644 --- a/drivers/clk/renesas/rcar-gen3-cpg.c +++ b/drivers/clk/renesas/rcar-gen3-cpg.c @@ -23,6 +23,7 @@ #include #include "renesas-cpg-mssr.h" +#include "rcar-cpg-lib.h" #include "rcar-gen3-cpg.h" #define CPG_PLL0CR 0x00d8 @@ -31,52 +32,6 @@ #define CPG_RCKCR_CKSEL BIT(15) /* RCLK Clock Source Select */ -static spinlock_t cpg_lock; - -static void cpg_reg_modify(void __iomem *reg, u32 clear, u32 set) -{ - unsigned long flags; - u32 val; - - spin_lock_irqsave(&cpg_lock, flags); - val = readl(reg); - val &= ~clear; - val |= set; - writel(val, reg); - spin_unlock_irqrestore(&cpg_lock, flags); -}; - -struct cpg_simple_notifier { - struct notifier_block nb; - void __iomem *reg; - u32 saved; -}; - -static int cpg_simple_notifier_call(struct notifier_block *nb, - unsigned long action, void *data) -{ - struct cpg_simple_notifier *csn = - container_of(nb, struct cpg_simple_notifier, nb); - - switch (action) { - case PM_EVENT_SUSPEND: - csn->saved = readl(csn->reg); - return NOTIFY_OK; - - case PM_EVENT_RESUME: - writel(csn->saved, csn->reg); - return NOTIFY_OK; - } - return NOTIFY_DONE; -} - -static void cpg_simple_notifier_register(struct raw_notifier_head *notifiers, - struct cpg_simple_notifier *csn) -{ - csn->nb.notifier_call = cpg_simple_notifier_call; - raw_notifier_chain_register(notifiers, &csn->nb); -} - /* * Z Clock & Z2 Clock * @@ -215,211 +170,6 @@ static struct clk * __init cpg_z_clk_register(const char *name, return clk; } -/* - * SDn Clock - */ -#define CPG_SD_STP_HCK BIT(9) -#define CPG_SD_STP_CK BIT(8) - -#define CPG_SD_STP_MASK (CPG_SD_STP_HCK | CPG_SD_STP_CK) -#define CPG_SD_FC_MASK (0x7 << 2 | 0x3 << 0) - -#define CPG_SD_DIV_TABLE_DATA(stp_hck, sd_srcfc, sd_fc, sd_div) \ -{ \ - .val = ((stp_hck) ? CPG_SD_STP_HCK : 0) | \ - ((sd_srcfc) << 2) | \ - ((sd_fc) << 0), \ - .div = (sd_div), \ -} - -struct sd_div_table { - u32 val; - unsigned int div; -}; - -struct sd_clock { - struct clk_hw hw; - const struct sd_div_table *div_table; - struct cpg_simple_notifier csn; - unsigned int div_num; - unsigned int cur_div_idx; -}; - -/* SDn divider - * sd_srcfc sd_fc div - * stp_hck (div) (div) = sd_srcfc x sd_fc - *--------------------------------------------------------- - * 0 0 (1) 1 (4) 4 : SDR104 / HS200 / HS400 (8 TAP) - * 0 1 (2) 1 (4) 8 : SDR50 - * 1 2 (4) 1 (4) 16 : HS / SDR25 - * 1 3 (8) 1 (4) 32 : NS / SDR12 - * 1 4 (16) 1 (4) 64 - * 0 0 (1) 0 (2) 2 - * 0 1 (2) 0 (2) 4 : SDR104 / HS200 / HS400 (4 TAP) - * 1 2 (4) 0 (2) 8 - * 1 3 (8) 0 (2) 16 - * 1 4 (16) 0 (2) 32 - * - * NOTE: There is a quirk option to ignore the first row of the dividers - * table when searching for suitable settings. This is because HS400 on - * early ES versions of H3 and M3-W requires a specific setting to work. - */ -static const struct sd_div_table cpg_sd_div_table[] = { -/* CPG_SD_DIV_TABLE_DATA(stp_hck, sd_srcfc, sd_fc, sd_div) */ - CPG_SD_DIV_TABLE_DATA(0, 0, 1, 4), - CPG_SD_DIV_TABLE_DATA(0, 1, 1, 8), - CPG_SD_DIV_TABLE_DATA(1, 2, 1, 16), - CPG_SD_DIV_TABLE_DATA(1, 3, 1, 32), - CPG_SD_DIV_TABLE_DATA(1, 4, 1, 64), - CPG_SD_DIV_TABLE_DATA(0, 0, 0, 2), - CPG_SD_DIV_TABLE_DATA(0, 1, 0, 4), - CPG_SD_DIV_TABLE_DATA(1, 2, 0, 8), - CPG_SD_DIV_TABLE_DATA(1, 3, 0, 16), - CPG_SD_DIV_TABLE_DATA(1, 4, 0, 32), -}; - -#define to_sd_clock(_hw) container_of(_hw, struct sd_clock, hw) - -static int cpg_sd_clock_enable(struct clk_hw *hw) -{ - struct sd_clock *clock = to_sd_clock(hw); - - cpg_reg_modify(clock->csn.reg, CPG_SD_STP_MASK, - clock->div_table[clock->cur_div_idx].val & - CPG_SD_STP_MASK); - - return 0; -} - -static void cpg_sd_clock_disable(struct clk_hw *hw) -{ - struct sd_clock *clock = to_sd_clock(hw); - - cpg_reg_modify(clock->csn.reg, 0, CPG_SD_STP_MASK); -} - -static int cpg_sd_clock_is_enabled(struct clk_hw *hw) -{ - struct sd_clock *clock = to_sd_clock(hw); - - return !(readl(clock->csn.reg) & CPG_SD_STP_MASK); -} - -static unsigned long cpg_sd_clock_recalc_rate(struct clk_hw *hw, - unsigned long parent_rate) -{ - struct sd_clock *clock = to_sd_clock(hw); - - return DIV_ROUND_CLOSEST(parent_rate, - clock->div_table[clock->cur_div_idx].div); -} - -static int cpg_sd_clock_determine_rate(struct clk_hw *hw, - struct clk_rate_request *req) -{ - unsigned long best_rate = ULONG_MAX, diff_min = ULONG_MAX; - struct sd_clock *clock = to_sd_clock(hw); - unsigned long calc_rate, diff; - unsigned int i; - - for (i = 0; i < clock->div_num; i++) { - calc_rate = DIV_ROUND_CLOSEST(req->best_parent_rate, - clock->div_table[i].div); - if (calc_rate < req->min_rate || calc_rate > req->max_rate) - continue; - - diff = calc_rate > req->rate ? calc_rate - req->rate - : req->rate - calc_rate; - if (diff < diff_min) { - best_rate = calc_rate; - diff_min = diff; - } - } - - if (best_rate == ULONG_MAX) - return -EINVAL; - - req->rate = best_rate; - return 0; -} - -static int cpg_sd_clock_set_rate(struct clk_hw *hw, unsigned long rate, - unsigned long parent_rate) -{ - struct sd_clock *clock = to_sd_clock(hw); - unsigned int i; - - for (i = 0; i < clock->div_num; i++) - if (rate == DIV_ROUND_CLOSEST(parent_rate, - clock->div_table[i].div)) - break; - - if (i >= clock->div_num) - return -EINVAL; - - clock->cur_div_idx = i; - - cpg_reg_modify(clock->csn.reg, CPG_SD_STP_MASK | CPG_SD_FC_MASK, - clock->div_table[i].val & - (CPG_SD_STP_MASK | CPG_SD_FC_MASK)); - - return 0; -} - -static const struct clk_ops cpg_sd_clock_ops = { - .enable = cpg_sd_clock_enable, - .disable = cpg_sd_clock_disable, - .is_enabled = cpg_sd_clock_is_enabled, - .recalc_rate = cpg_sd_clock_recalc_rate, - .determine_rate = cpg_sd_clock_determine_rate, - .set_rate = cpg_sd_clock_set_rate, -}; - -static struct clk * __init cpg_sd_clk_register(const char *name, - void __iomem *base, unsigned int offset, const char *parent_name, - struct raw_notifier_head *notifiers, bool skip_first) -{ - struct clk_init_data init; - struct sd_clock *clock; - struct clk *clk; - u32 val; - - clock = kzalloc(sizeof(*clock), GFP_KERNEL); - if (!clock) - return ERR_PTR(-ENOMEM); - - init.name = name; - init.ops = &cpg_sd_clock_ops; - init.flags = CLK_SET_RATE_PARENT; - init.parent_names = &parent_name; - init.num_parents = 1; - - clock->csn.reg = base + offset; - clock->hw.init = &init; - clock->div_table = cpg_sd_div_table; - clock->div_num = ARRAY_SIZE(cpg_sd_div_table); - - if (skip_first) { - clock->div_table++; - clock->div_num--; - } - - val = readl(clock->csn.reg) & ~CPG_SD_FC_MASK; - val |= CPG_SD_STP_MASK | (clock->div_table[0].val & CPG_SD_FC_MASK); - writel(val, clock->csn.reg); - - clk = clk_register(NULL, &clock->hw); - if (IS_ERR(clk)) - goto free_clock; - - cpg_simple_notifier_register(notifiers, &clock->csn); - return clk; - -free_clock: - kfree(clock); - return clk; -} - struct rpc_clock { struct clk_divider div; struct clk_gate gate; -- cgit v1.2.3 From 792501727c2abf568f694c9c79b0da628c9dc4bb Mon Sep 17 00:00:00 2001 From: Wolfram Sang Date: Sun, 27 Dec 2020 18:41:58 +0100 Subject: clk: renesas: r8a779a0: Add SDHI support We use the shiny new CPG library for that. Signed-off-by: Wolfram Sang Link: https://lore.kernel.org/r/20201227174202.40834-5-wsa+renesas@sang-engineering.com Signed-off-by: Geert Uytterhoeven --- drivers/clk/renesas/Kconfig | 1 + drivers/clk/renesas/r8a779a0-cpg-mssr.c | 17 +++++++++++++++-- 2 files changed, 16 insertions(+), 2 deletions(-) (limited to 'drivers/clk') diff --git a/drivers/clk/renesas/Kconfig b/drivers/clk/renesas/Kconfig index 7e788fee6b9f..607e64a17d72 100644 --- a/drivers/clk/renesas/Kconfig +++ b/drivers/clk/renesas/Kconfig @@ -148,6 +148,7 @@ config CLK_R8A77995 config CLK_R8A779A0 bool "R-Car V3U clock support" if COMPILE_TEST + select CLK_RCAR_CPG_LIB select CLK_RENESAS_CPG_MSSR config CLK_R9A06G032 diff --git a/drivers/clk/renesas/r8a779a0-cpg-mssr.c b/drivers/clk/renesas/r8a779a0-cpg-mssr.c index 067c71067fd4..0f15590e1dba 100644 --- a/drivers/clk/renesas/r8a779a0-cpg-mssr.c +++ b/drivers/clk/renesas/r8a779a0-cpg-mssr.c @@ -25,6 +25,7 @@ #include +#include "rcar-cpg-lib.h" #include "renesas-cpg-mssr.h" enum rcar_r8a779a0_clk_types { @@ -32,6 +33,7 @@ enum rcar_r8a779a0_clk_types { CLK_TYPE_R8A779A0_PLL1, CLK_TYPE_R8A779A0_PLL2X_3X, /* PLL[23][01] */ CLK_TYPE_R8A779A0_PLL5, + CLK_TYPE_R8A779A0_SD, CLK_TYPE_R8A779A0_MDSEL, /* Select parent/divider using mode pin */ CLK_TYPE_R8A779A0_OSC, /* OSC EXTAL predivider and fixed divider */ }; @@ -82,6 +84,9 @@ enum clk_ids { DEF_BASE(_name, _id, CLK_TYPE_R8A779A0_PLL2X_3X, CLK_MAIN, \ .offset = _offset) +#define DEF_SD(_name, _id, _parent, _offset) \ + DEF_BASE(_name, _id, CLK_TYPE_R8A779A0_SD, _parent, .offset = _offset) + #define DEF_MDSEL(_name, _id, _md, _parent0, _div0, _parent1, _div1) \ DEF_BASE(_name, _id, CLK_TYPE_R8A779A0_MDSEL, \ (_parent0) << 16 | (_parent1), \ @@ -113,6 +118,7 @@ static const struct cpg_core_clk r8a779a0_core_clks[] __initconst = { DEF_FIXED(".pll5_div4", CLK_PLL5_DIV4, CLK_PLL5_DIV2, 2, 1), DEF_FIXED(".s1", CLK_S1, CLK_PLL1_DIV2, 2, 1), DEF_FIXED(".s3", CLK_S3, CLK_PLL1_DIV2, 4, 1), + DEF_FIXED(".sdsrc", CLK_SDSRC, CLK_PLL5_DIV4, 1, 1), DEF_RATE(".oco", CLK_OCO, 32768), /* Core Clock Outputs */ @@ -139,6 +145,8 @@ static const struct cpg_core_clk r8a779a0_core_clks[] __initconst = { DEF_FIXED("cbfusa", R8A779A0_CLK_CBFUSA, CLK_EXTAL, 2, 1), DEF_FIXED("cp", R8A779A0_CLK_CP, CLK_EXTAL, 2, 1), + DEF_SD("sd0", R8A779A0_CLK_SD0, CLK_SDSRC, 0x870), + DEF_DIV6P1("mso", R8A779A0_CLK_MSO, CLK_PLL5_DIV4, 0x87c), DEF_DIV6P1("canfd", R8A779A0_CLK_CANFD, CLK_PLL5_DIV4, 0x878), DEF_DIV6P1("csi0", R8A779A0_CLK_CSI0, CLK_PLL5_DIV4, 0x880), @@ -168,6 +176,7 @@ static const struct mssr_mod_clk r8a779a0_mod_clks[] __initconst = { DEF_MOD("scif1", 703, R8A779A0_CLK_S1D8), DEF_MOD("scif3", 704, R8A779A0_CLK_S1D8), DEF_MOD("scif4", 705, R8A779A0_CLK_S1D8), + DEF_MOD("sdhi0", 706, R8A779A0_CLK_SD0), DEF_MOD("vin00", 730, R8A779A0_CLK_S1D1), DEF_MOD("vin01", 731, R8A779A0_CLK_S1D1), DEF_MOD("vin02", 800, R8A779A0_CLK_S1D1), @@ -213,8 +222,6 @@ static const struct mssr_mod_clk r8a779a0_mod_clks[] __initconst = { DEF_MOD("vspx3", 1031, R8A779A0_CLK_S1D1), }; -static spinlock_t cpg_lock; - static const struct rcar_r8a779a0_cpg_pll_config *cpg_pll_config __initdata; static unsigned int cpg_clk_extalr __initdata; static u32 cpg_mode __initdata; @@ -253,6 +260,12 @@ static struct clk * __init rcar_r8a779a0_cpg_clk_register(struct device *dev, div = cpg_pll_config->pll5_div; break; + case CLK_TYPE_R8A779A0_SD: + return cpg_sd_clk_register(core->name, base, core->offset, + __clk_get_name(parent), notifiers, + false); + break; + case CLK_TYPE_R8A779A0_MDSEL: /* * Clock selectable between two parents and two fixed dividers -- cgit v1.2.3 From 2b6587288a5aacf05b1388ab0845afdb6fd0358c Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Thu, 7 Jan 2021 19:01:09 +0100 Subject: clk: renesas: r8a779a0: Add SYS-DMAC clocks Add the module clocks used by the Direct Memory Access Controller for System (SYS-DMAC) instances on the Renesas R-Car V3U (r8a779a0) SoC. Signed-off-by: Geert Uytterhoeven Link: https://lore.kernel.org/r/20210107180109.1946475-1-geert+renesas@glider.be --- drivers/clk/renesas/r8a779a0-cpg-mssr.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'drivers/clk') diff --git a/drivers/clk/renesas/r8a779a0-cpg-mssr.c b/drivers/clk/renesas/r8a779a0-cpg-mssr.c index 0f15590e1dba..ef45b7c10074 100644 --- a/drivers/clk/renesas/r8a779a0-cpg-mssr.c +++ b/drivers/clk/renesas/r8a779a0-cpg-mssr.c @@ -177,6 +177,8 @@ static const struct mssr_mod_clk r8a779a0_mod_clks[] __initconst = { DEF_MOD("scif3", 704, R8A779A0_CLK_S1D8), DEF_MOD("scif4", 705, R8A779A0_CLK_S1D8), DEF_MOD("sdhi0", 706, R8A779A0_CLK_SD0), + DEF_MOD("sydm1", 709, R8A779A0_CLK_S1D2), + DEF_MOD("sydm2", 710, R8A779A0_CLK_S1D2), DEF_MOD("vin00", 730, R8A779A0_CLK_S1D1), DEF_MOD("vin01", 731, R8A779A0_CLK_S1D1), DEF_MOD("vin02", 800, R8A779A0_CLK_S1D1), -- cgit v1.2.3 From 58fdf74d43f49da11073232d7408097b43c79a76 Mon Sep 17 00:00:00 2001 From: Lee Jones Date: Wed, 20 Jan 2021 09:30:34 +0000 Subject: clk: sunxi: clk-sunxi: Demote a bunch of non-conformant kernel-doc headers MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Fixes the following W=1 kernel build warning(s): drivers/clk/sunxi/clk-sunxi.c:34: warning: Function parameter or member 'req' not described in 'sun4i_get_pll1_factors' drivers/clk/sunxi/clk-sunxi.c:81: warning: Function parameter or member 'req' not described in 'sun6i_a31_get_pll1_factors' drivers/clk/sunxi/clk-sunxi.c:158: warning: Function parameter or member 'req' not described in 'sun8i_a23_get_pll1_factors' drivers/clk/sunxi/clk-sunxi.c:202: warning: Function parameter or member 'req' not described in 'sun4i_get_pll5_factors' drivers/clk/sunxi/clk-sunxi.c:229: warning: Function parameter or member 'req' not described in 'sun6i_a31_get_pll6_factors' drivers/clk/sunxi/clk-sunxi.c:250: warning: Function parameter or member 'req' not described in 'sun5i_a13_get_ahb_factors' drivers/clk/sunxi/clk-sunxi.c:289: warning: Function parameter or member 'req' not described in 'sun6i_get_ahb1_factors' drivers/clk/sunxi/clk-sunxi.c:328: warning: Function parameter or member 'req' not described in 'sun6i_ahb1_recalc' drivers/clk/sunxi/clk-sunxi.c:346: warning: Function parameter or member 'req' not described in 'sun4i_get_apb1_factors' drivers/clk/sunxi/clk-sunxi.c:385: warning: Function parameter or member 'req' not described in 'sun7i_a20_get_out_factors' drivers/clk/sunxi/clk-sunxi.c:415: warning: cannot understand function prototype: 'const struct clk_factors_config sun4i_pll1_config = ' drivers/clk/sunxi/clk-sunxi.c:724: warning: cannot understand function prototype: 'struct div_data ' drivers/clk/sunxi/clk-sunxi.c:945: warning: Function parameter or member 'node' not described in 'sunxi_divs_clk_setup' drivers/clk/sunxi/clk-sunxi.c:945: warning: Function parameter or member 'data' not described in 'sunxi_divs_clk_setup' Cc: "Emilio López" Cc: Michael Turquette Cc: Stephen Boyd Cc: Maxime Ripard Cc: Chen-Yu Tsai Cc: Jernej Skrabec Cc: linux-clk@vger.kernel.org Cc: linux-arm-kernel@lists.infradead.org Signed-off-by: Lee Jones Signed-off-by: Maxime Ripard Link: https://lore.kernel.org/r/20210120093040.1719407-15-lee.jones@linaro.org --- drivers/clk/sunxi/clk-sunxi.c | 32 ++++++++++++++++---------------- 1 file changed, 16 insertions(+), 16 deletions(-) (limited to 'drivers/clk') diff --git a/drivers/clk/sunxi/clk-sunxi.c b/drivers/clk/sunxi/clk-sunxi.c index e1aa1fbac48a..5fe7049ea693 100644 --- a/drivers/clk/sunxi/clk-sunxi.c +++ b/drivers/clk/sunxi/clk-sunxi.c @@ -23,7 +23,7 @@ static DEFINE_SPINLOCK(clk_lock); /* Maximum number of parents our clocks have */ #define SUNXI_MAX_PARENTS 5 -/** +/* * sun4i_get_pll1_factors() - calculates n, k, m, p factors for PLL1 * PLL1 rate is calculated as follows * rate = (parent_rate * n * (k + 1) >> p) / (m + 1); @@ -71,7 +71,7 @@ static void sun4i_get_pll1_factors(struct factors_request *req) req->n = div / 4; } -/** +/* * sun6i_a31_get_pll1_factors() - calculates n, k and m factors for PLL1 * PLL1 rate is calculated as follows * rate = parent_rate * (n + 1) * (k + 1) / (m + 1); @@ -147,7 +147,7 @@ static void sun6i_a31_get_pll1_factors(struct factors_request *req) } } -/** +/* * sun8i_a23_get_pll1_factors() - calculates n, k, m, p factors for PLL1 * PLL1 rate is calculated as follows * rate = (parent_rate * (n + 1) * (k + 1) >> p) / (m + 1); @@ -191,7 +191,7 @@ static void sun8i_a23_get_pll1_factors(struct factors_request *req) req->n = div / 4 - 1; } -/** +/* * sun4i_get_pll5_factors() - calculates n, k factors for PLL5 * PLL5 rate is calculated as follows * rate = parent_rate * n * (k + 1) @@ -218,7 +218,7 @@ static void sun4i_get_pll5_factors(struct factors_request *req) req->n = DIV_ROUND_UP(div, (req->k + 1)); } -/** +/* * sun6i_a31_get_pll6_factors() - calculates n, k factors for A31 PLL6x2 * PLL6x2 rate is calculated as follows * rate = parent_rate * (n + 1) * (k + 1) @@ -240,7 +240,7 @@ static void sun6i_a31_get_pll6_factors(struct factors_request *req) req->n = DIV_ROUND_UP(div, (req->k + 1)) - 1; } -/** +/* * sun5i_a13_get_ahb_factors() - calculates m, p factors for AHB * AHB rate is calculated as follows * rate = parent_rate >> p @@ -276,7 +276,7 @@ static void sun5i_a13_get_ahb_factors(struct factors_request *req) #define SUN6I_AHB1_PARENT_PLL6 3 -/** +/* * sun6i_a31_get_ahb_factors() - calculates m, p factors for AHB * AHB rate is calculated as follows * rate = parent_rate >> p @@ -320,7 +320,7 @@ static void sun6i_get_ahb1_factors(struct factors_request *req) req->m = calcm - 1; } -/** +/* * sun6i_ahb1_recalc() - calculates AHB clock rate from m, p factors and * parent index */ @@ -336,7 +336,7 @@ static void sun6i_ahb1_recalc(struct factors_request *req) req->rate >>= req->p; } -/** +/* * sun4i_get_apb1_factors() - calculates m, p factors for APB1 * APB1 rate is calculated as follows * rate = (parent_rate >> p) / (m + 1); @@ -375,7 +375,7 @@ static void sun4i_get_apb1_factors(struct factors_request *req) -/** +/* * sun7i_a20_get_out_factors() - calculates m, p factors for CLK_OUT_A/B * CLK_OUT rate is calculated as follows * rate = (parent_rate >> p) / (m + 1); @@ -408,7 +408,7 @@ static void sun7i_a20_get_out_factors(struct factors_request *req) req->p = calcp; } -/** +/* * sunxi_factors_clk_setup() - Setup function for factor clocks */ @@ -625,7 +625,7 @@ CLK_OF_DECLARE(sun7i_out, "allwinner,sun7i-a20-out-clk", sun7i_out_clk_setup); -/** +/* * sunxi_mux_clk_setup() - Setup function for muxes */ @@ -717,7 +717,7 @@ CLK_OF_DECLARE(sun8i_ahb2, "allwinner,sun8i-h3-ahb2-clk", sun8i_ahb2_clk_setup); -/** +/* * sunxi_divider_clk_setup() - Setup function for simple divider clocks */ @@ -853,7 +853,7 @@ CLK_OF_DECLARE(sun8i_axi, "allwinner,sun8i-a23-axi-clk", -/** +/* * sunxi_gates_clk_setup() - Setup function for leaf gates on clocks */ @@ -863,7 +863,7 @@ struct gates_data { DECLARE_BITMAP(mask, SUNXI_GATES_MAX_SIZE); }; -/** +/* * sunxi_divs_clk_setup() helper data */ @@ -929,7 +929,7 @@ static const struct divs_data sun6i_a31_pll6_divs_data __initconst = { } }; -/** +/* * sunxi_divs_clk_setup() - Setup function for leaf divisors on clocks * * These clocks look something like this -- cgit v1.2.3 From 29f476d443d6eb37568894ec0bea87d6080fc82f Mon Sep 17 00:00:00 2001 From: Lee Jones Date: Wed, 20 Jan 2021 09:30:37 +0000 Subject: clk: sunxi: clk-a10-ve: Demote obvious kernel-doc abuse MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Fixes the following W=1 kernel build warning(s): drivers/clk/sunxi/clk-a10-ve.c:27: warning: cannot understand function prototype: 'struct ve_reset_data ' Cc: "Emilio López" Cc: Michael Turquette Cc: Stephen Boyd Cc: Maxime Ripard Cc: Chen-Yu Tsai Cc: Jernej Skrabec Cc: Philipp Zabel Cc: linux-clk@vger.kernel.org Cc: linux-arm-kernel@lists.infradead.org Signed-off-by: Lee Jones Signed-off-by: Maxime Ripard Link: https://lore.kernel.org/r/20210120093040.1719407-18-lee.jones@linaro.org --- drivers/clk/sunxi/clk-a10-ve.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/clk') diff --git a/drivers/clk/sunxi/clk-a10-ve.c b/drivers/clk/sunxi/clk-a10-ve.c index cb5daa4b37db..65810937a13a 100644 --- a/drivers/clk/sunxi/clk-a10-ve.c +++ b/drivers/clk/sunxi/clk-a10-ve.c @@ -20,7 +20,7 @@ static DEFINE_SPINLOCK(ve_lock); #define SUN4I_VE_DIVIDER_WIDTH 3 #define SUN4I_VE_RESET 0 -/** +/* * sunxi_ve_reset... - reset bit in ve clk registers handling */ -- cgit v1.2.3 From eec9d9b7b09a9f14654341899195fb687c18eff7 Mon Sep 17 00:00:00 2001 From: Lee Jones Date: Wed, 20 Jan 2021 09:30:38 +0000 Subject: clk: sunxi: clk-mod0: Demote non-conformant kernel-doc header MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Fixes the following W=1 kernel build warning(s): drivers/clk/sunxi/clk-mod0.c:24: warning: Function parameter or member 'req' not described in 'sun4i_a10_get_mod0_factors' Cc: "Emilio López" Cc: Michael Turquette Cc: Stephen Boyd Cc: Maxime Ripard Cc: Chen-Yu Tsai Cc: Jernej Skrabec Cc: linux-clk@vger.kernel.org Cc: linux-arm-kernel@lists.infradead.org Signed-off-by: Lee Jones Signed-off-by: Maxime Ripard Link: https://lore.kernel.org/r/20210120093040.1719407-19-lee.jones@linaro.org --- drivers/clk/sunxi/clk-mod0.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/clk') diff --git a/drivers/clk/sunxi/clk-mod0.c b/drivers/clk/sunxi/clk-mod0.c index 0cca91e075a5..f9d715ec9908 100644 --- a/drivers/clk/sunxi/clk-mod0.c +++ b/drivers/clk/sunxi/clk-mod0.c @@ -14,7 +14,7 @@ #include "clk-factors.h" -/** +/* * sun4i_a10_get_mod0_factors() - calculates m, n factors for MOD0-style clocks * MOD0 rate is calculated as follows * rate = (parent_rate >> p) / (m + 1); -- cgit v1.2.3 From 04ef679591c76571a9e7d5ca48316cc86fa0ef12 Mon Sep 17 00:00:00 2001 From: Andre Przywara Date: Mon, 18 Jan 2021 00:09:12 +0000 Subject: clk: sunxi-ng: h6: Fix clock divider range on some clocks While comparing clocks between the H6 and H616, some of the M factor ranges were found to be wrong: the manual says they are only covering two bits [1:0], but our code had "5" in the number-of-bits field. By writing 0xff into that register in U-Boot and via FEL, it could be confirmed that bits [4:2] are indeed masked off, so the manual is right. Change to number of bits in the affected clock's description. Fixes: 524353ea480b ("clk: sunxi-ng: add support for the Allwinner H6 CCU") Signed-off-by: Andre Przywara Reviewed-by: Jernej Skrabec Signed-off-by: Maxime Ripard Link: https://lore.kernel.org/r/20210118000912.28116-1-andre.przywara@arm.com --- drivers/clk/sunxi-ng/ccu-sun50i-h6.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'drivers/clk') diff --git a/drivers/clk/sunxi-ng/ccu-sun50i-h6.c b/drivers/clk/sunxi-ng/ccu-sun50i-h6.c index a26dbbdff80d..bff446b78290 100644 --- a/drivers/clk/sunxi-ng/ccu-sun50i-h6.c +++ b/drivers/clk/sunxi-ng/ccu-sun50i-h6.c @@ -237,7 +237,7 @@ static const char * const psi_ahb1_ahb2_parents[] = { "osc24M", "osc32k", static SUNXI_CCU_MP_WITH_MUX(psi_ahb1_ahb2_clk, "psi-ahb1-ahb2", psi_ahb1_ahb2_parents, 0x510, - 0, 5, /* M */ + 0, 2, /* M */ 8, 2, /* P */ 24, 2, /* mux */ 0); @@ -246,19 +246,19 @@ static const char * const ahb3_apb1_apb2_parents[] = { "osc24M", "osc32k", "psi-ahb1-ahb2", "pll-periph0" }; static SUNXI_CCU_MP_WITH_MUX(ahb3_clk, "ahb3", ahb3_apb1_apb2_parents, 0x51c, - 0, 5, /* M */ + 0, 2, /* M */ 8, 2, /* P */ 24, 2, /* mux */ 0); static SUNXI_CCU_MP_WITH_MUX(apb1_clk, "apb1", ahb3_apb1_apb2_parents, 0x520, - 0, 5, /* M */ + 0, 2, /* M */ 8, 2, /* P */ 24, 2, /* mux */ 0); static SUNXI_CCU_MP_WITH_MUX(apb2_clk, "apb2", ahb3_apb1_apb2_parents, 0x524, - 0, 5, /* M */ + 0, 2, /* M */ 8, 2, /* P */ 24, 2, /* mux */ 0); -- cgit v1.2.3 From 6893a77279be77b8610f428985ba0f5fb7caebeb Mon Sep 17 00:00:00 2001 From: Wolfram Sang Date: Thu, 21 Jan 2021 10:54:17 +0100 Subject: clk: renesas: r8a779a0: Add I2C clocks Signed-off-by: Wolfram Sang Link: https://lore.kernel.org/r/20210121095420.5023-2-wsa+renesas@sang-engineering.com Signed-off-by: Geert Uytterhoeven --- drivers/clk/renesas/r8a779a0-cpg-mssr.c | 7 +++++++ 1 file changed, 7 insertions(+) (limited to 'drivers/clk') diff --git a/drivers/clk/renesas/r8a779a0-cpg-mssr.c b/drivers/clk/renesas/r8a779a0-cpg-mssr.c index ef45b7c10074..613f7b499cfc 100644 --- a/drivers/clk/renesas/r8a779a0-cpg-mssr.c +++ b/drivers/clk/renesas/r8a779a0-cpg-mssr.c @@ -166,6 +166,13 @@ static const struct mssr_mod_clk r8a779a0_mod_clks[] __initconst = { DEF_MOD("hscif1", 515, R8A779A0_CLK_S1D2), DEF_MOD("hscif2", 516, R8A779A0_CLK_S1D2), DEF_MOD("hscif3", 517, R8A779A0_CLK_S1D2), + DEF_MOD("i2c0", 518, R8A779A0_CLK_S1D4), + DEF_MOD("i2c1", 519, R8A779A0_CLK_S1D4), + DEF_MOD("i2c2", 520, R8A779A0_CLK_S1D4), + DEF_MOD("i2c3", 521, R8A779A0_CLK_S1D4), + DEF_MOD("i2c4", 522, R8A779A0_CLK_S1D4), + DEF_MOD("i2c5", 523, R8A779A0_CLK_S1D4), + DEF_MOD("i2c6", 524, R8A779A0_CLK_S1D4), DEF_MOD("msi0", 618, R8A779A0_CLK_MSO), DEF_MOD("msi1", 619, R8A779A0_CLK_MSO), DEF_MOD("msi2", 620, R8A779A0_CLK_MSO), -- cgit v1.2.3 From c5e91ba25a65378edb013fbfe418b65d74f9aae5 Mon Sep 17 00:00:00 2001 From: Wolfram Sang Date: Thu, 21 Jan 2021 11:06:16 +0100 Subject: clk: renesas: r8a779a0: Add RAVB clocks Signed-off-by: Wolfram Sang Link: https://lore.kernel.org/r/20210121100619.5653-3-wsa+renesas@sang-engineering.com Signed-off-by: Geert Uytterhoeven --- drivers/clk/renesas/r8a779a0-cpg-mssr.c | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'drivers/clk') diff --git a/drivers/clk/renesas/r8a779a0-cpg-mssr.c b/drivers/clk/renesas/r8a779a0-cpg-mssr.c index 613f7b499cfc..f23fe9d5e5e1 100644 --- a/drivers/clk/renesas/r8a779a0-cpg-mssr.c +++ b/drivers/clk/renesas/r8a779a0-cpg-mssr.c @@ -156,6 +156,12 @@ static const struct cpg_core_clk r8a779a0_core_clks[] __initconst = { }; static const struct mssr_mod_clk r8a779a0_mod_clks[] __initconst = { + DEF_MOD("avb0", 211, R8A779A0_CLK_S3D2), + DEF_MOD("avb1", 212, R8A779A0_CLK_S3D2), + DEF_MOD("avb2", 213, R8A779A0_CLK_S3D2), + DEF_MOD("avb3", 214, R8A779A0_CLK_S3D2), + DEF_MOD("avb4", 215, R8A779A0_CLK_S3D2), + DEF_MOD("avb5", 216, R8A779A0_CLK_S3D2), DEF_MOD("csi40", 331, R8A779A0_CLK_CSI0), DEF_MOD("csi41", 400, R8A779A0_CLK_CSI0), DEF_MOD("csi42", 401, R8A779A0_CLK_CSI0), -- cgit v1.2.3 From 415173712003ad7e54de7198979d68a428440ed6 Mon Sep 17 00:00:00 2001 From: Lee Jones Date: Wed, 20 Jan 2021 09:30:21 +0000 Subject: clk: rockchip: Demote non-conformant kernel-doc headers in main clock code Fixes the following W=1 kernel build warning(s): drivers/clk/rockchip/clk.c:45: warning: Function parameter or member 'name' not described in 'rockchip_clk_register_branch' drivers/clk/rockchip/clk.c:45: warning: Function parameter or member 'parent_names' not described in 'rockchip_clk_register_branch' drivers/clk/rockchip/clk.c:45: warning: Function parameter or member 'num_parents' not described in 'rockchip_clk_register_branch' drivers/clk/rockchip/clk.c:45: warning: Function parameter or member 'base' not described in 'rockchip_clk_register_branch' drivers/clk/rockchip/clk.c:45: warning: Function parameter or member 'muxdiv_offset' not described in 'rockchip_clk_register_branch' drivers/clk/rockchip/clk.c:45: warning: Function parameter or member 'mux_shift' not described in 'rockchip_clk_register_branch' drivers/clk/rockchip/clk.c:45: warning: Function parameter or member 'mux_width' not described in 'rockchip_clk_register_branch' drivers/clk/rockchip/clk.c:45: warning: Function parameter or member 'mux_flags' not described in 'rockchip_clk_register_branch' drivers/clk/rockchip/clk.c:45: warning: Function parameter or member 'div_offset' not described in 'rockchip_clk_register_branch' drivers/clk/rockchip/clk.c:45: warning: Function parameter or member 'div_shift' not described in 'rockchip_clk_register_branch' drivers/clk/rockchip/clk.c:45: warning: Function parameter or member 'div_width' not described in 'rockchip_clk_register_branch' drivers/clk/rockchip/clk.c:45: warning: Function parameter or member 'div_flags' not described in 'rockchip_clk_register_branch' drivers/clk/rockchip/clk.c:45: warning: Function parameter or member 'div_table' not described in 'rockchip_clk_register_branch' drivers/clk/rockchip/clk.c:45: warning: Function parameter or member 'gate_offset' not described in 'rockchip_clk_register_branch' drivers/clk/rockchip/clk.c:45: warning: Function parameter or member 'gate_shift' not described in 'rockchip_clk_register_branch' drivers/clk/rockchip/clk.c:45: warning: Function parameter or member 'gate_flags' not described in 'rockchip_clk_register_branch' drivers/clk/rockchip/clk.c:45: warning: Function parameter or member 'flags' not described in 'rockchip_clk_register_branch' drivers/clk/rockchip/clk.c:45: warning: Function parameter or member 'lock' not described in 'rockchip_clk_register_branch' drivers/clk/rockchip/clk.c:180: warning: Function parameter or member 'hw' not described in 'rockchip_fractional_approximation' drivers/clk/rockchip/clk.c:180: warning: Function parameter or member 'rate' not described in 'rockchip_fractional_approximation' drivers/clk/rockchip/clk.c:180: warning: Function parameter or member 'parent_rate' not described in 'rockchip_fractional_approximation' drivers/clk/rockchip/clk.c:180: warning: Function parameter or member 'm' not described in 'rockchip_fractional_approximation' drivers/clk/rockchip/clk.c:180: warning: Function parameter or member 'n' not described in 'rockchip_fractional_approximation' Cc: Michael Turquette Cc: Stephen Boyd Cc: Heiko Stuebner Cc: Xing Zheng Cc: Thomas Abraham Cc: linux-clk@vger.kernel.org Cc: linux-arm-kernel@lists.infradead.org Cc: linux-rockchip@lists.infradead.org Signed-off-by: Lee Jones Link: https://lore.kernel.org/r/20210120093040.1719407-2-lee.jones@linaro.org Signed-off-by: Heiko Stuebner --- drivers/clk/rockchip/clk.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers/clk') diff --git a/drivers/clk/rockchip/clk.c b/drivers/clk/rockchip/clk.c index 336481bc6cc7..049e5e0b64f6 100644 --- a/drivers/clk/rockchip/clk.c +++ b/drivers/clk/rockchip/clk.c @@ -24,7 +24,7 @@ #include #include "clk.h" -/** +/* * Register a clock branch. * Most clock branches have a form like * @@ -170,7 +170,7 @@ static int rockchip_clk_frac_notifier_cb(struct notifier_block *nb, return notifier_from_errno(ret); } -/** +/* * fractional divider must set that denominator is 20 times larger than * numerator to generate precise clock frequency. */ -- cgit v1.2.3 From 274ae6da4b3275fea32f0807e6e20715695dd210 Mon Sep 17 00:00:00 2001 From: Lee Jones Date: Wed, 20 Jan 2021 09:30:22 +0000 Subject: clk: rockchip: Remove unused/undocumented struct members from clk-cpu Fixes the following W=1 kernel build warning(s): drivers/clk/rockchip/clk-cpu.c:65: warning: Function parameter or member 'cpu_mux' not described in 'rockchip_cpuclk' drivers/clk/rockchip/clk-cpu.c:65: warning: Function parameter or member 'cpu_mux_ops' not described in 'rockchip_cpuclk' Cc: Michael Turquette Cc: Stephen Boyd Cc: Heiko Stuebner Cc: Thomas Abraham Cc: linux-clk@vger.kernel.org Cc: linux-arm-kernel@lists.infradead.org Cc: linux-rockchip@lists.infradead.org Signed-off-by: Lee Jones Link: https://lore.kernel.org/r/20210120093040.1719407-3-lee.jones@linaro.org Signed-off-by: Heiko Stuebner --- drivers/clk/rockchip/clk-cpu.c | 4 ---- 1 file changed, 4 deletions(-) (limited to 'drivers/clk') diff --git a/drivers/clk/rockchip/clk-cpu.c b/drivers/clk/rockchip/clk-cpu.c index 0dc478a19451..fa9027fb1920 100644 --- a/drivers/clk/rockchip/clk-cpu.c +++ b/drivers/clk/rockchip/clk-cpu.c @@ -51,10 +51,6 @@ */ struct rockchip_cpuclk { struct clk_hw hw; - - struct clk_mux cpu_mux; - const struct clk_ops *cpu_mux_ops; - struct clk *alt_parent; void __iomem *reg_base; struct notifier_block clk_nb; -- cgit v1.2.3 From eee7b95589e61bd7250cada52ddd8039c63535ef Mon Sep 17 00:00:00 2001 From: Lee Jones Date: Wed, 20 Jan 2021 09:30:23 +0000 Subject: clk: rockchip: Demote kernel-doc abuses to standard comment blocks in plls Fixes the following W=1 kernel build warning(s): drivers/clk/rockchip/clk-pll.c:104: warning: Function parameter or member 'i' not described in 'RK3036_PLLCON' drivers/clk/rockchip/clk-pll.c:365: warning: Function parameter or member 'nr' not described in 'RK3066_PLL_RESET_DELAY' drivers/clk/rockchip/clk-pll.c:584: warning: Function parameter or member 'i' not described in 'RK3399_PLLCON' Cc: Michael Turquette Cc: Stephen Boyd Cc: Heiko Stuebner Cc: Xing Zheng Cc: linux-clk@vger.kernel.org Cc: linux-arm-kernel@lists.infradead.org Cc: linux-rockchip@lists.infradead.org Signed-off-by: Lee Jones Link: https://lore.kernel.org/r/20210120093040.1719407-4-lee.jones@linaro.org Signed-off-by: Heiko Stuebner --- drivers/clk/rockchip/clk-pll.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'drivers/clk') diff --git a/drivers/clk/rockchip/clk-pll.c b/drivers/clk/rockchip/clk-pll.c index 4c6c9167ef50..fe937bcdb487 100644 --- a/drivers/clk/rockchip/clk-pll.c +++ b/drivers/clk/rockchip/clk-pll.c @@ -97,7 +97,7 @@ static int rockchip_pll_wait_lock(struct rockchip_clk_pll *pll) return ret; } -/** +/* * PLL used in RK3036 */ @@ -358,7 +358,7 @@ static const struct clk_ops rockchip_rk3036_pll_clk_ops = { .init = rockchip_rk3036_pll_init, }; -/** +/* * PLL used in RK3066, RK3188 and RK3288 */ @@ -577,7 +577,7 @@ static const struct clk_ops rockchip_rk3066_pll_clk_ops = { .init = rockchip_rk3066_pll_init, }; -/** +/* * PLL used in RK3399 */ -- cgit v1.2.3 From d48fbef962b095f7cc22017642fb9055d57fdb53 Mon Sep 17 00:00:00 2001 From: Lee Jones Date: Wed, 20 Jan 2021 09:30:24 +0000 Subject: clk: rockchip: Demote non-conformant kernel-doc header in half-divider Fixes the following W=1 kernel build warning(s): drivers/clk/rockchip/clk-half-divider.c:168: warning: Function parameter or member 'name' not described in 'rockchip_clk_register_halfdiv' drivers/clk/rockchip/clk-half-divider.c:168: warning: Function parameter or member 'parent_names' not described in 'rockchip_clk_register_halfdiv' drivers/clk/rockchip/clk-half-divider.c:168: warning: Function parameter or member 'num_parents' not described in 'rockchip_clk_register_halfdiv' drivers/clk/rockchip/clk-half-divider.c:168: warning: Function parameter or member 'base' not described in 'rockchip_clk_register_halfdiv' drivers/clk/rockchip/clk-half-divider.c:168: warning: Function parameter or member 'muxdiv_offset' not described in 'rockchip_clk_register_halfdiv' drivers/clk/rockchip/clk-half-divider.c:168: warning: Function parameter or member 'mux_shift' not described in 'rockchip_clk_register_halfdiv' drivers/clk/rockchip/clk-half-divider.c:168: warning: Function parameter or member 'mux_width' not described in 'rockchip_clk_register_halfdiv' drivers/clk/rockchip/clk-half-divider.c:168: warning: Function parameter or member 'mux_flags' not described in 'rockchip_clk_register_halfdiv' drivers/clk/rockchip/clk-half-divider.c:168: warning: Function parameter or member 'div_shift' not described in 'rockchip_clk_register_halfdiv' drivers/clk/rockchip/clk-half-divider.c:168: warning: Function parameter or member 'div_width' not described in 'rockchip_clk_register_halfdiv' drivers/clk/rockchip/clk-half-divider.c:168: warning: Function parameter or member 'div_flags' not described in 'rockchip_clk_register_halfdiv' drivers/clk/rockchip/clk-half-divider.c:168: warning: Function parameter or member 'gate_offset' not described in 'rockchip_clk_register_halfdiv' drivers/clk/rockchip/clk-half-divider.c:168: warning: Function parameter or member 'gate_shift' not described in 'rockchip_clk_register_halfdiv' drivers/clk/rockchip/clk-half-divider.c:168: warning: Function parameter or member 'gate_flags' not described in 'rockchip_clk_register_halfdiv' drivers/clk/rockchip/clk-half-divider.c:168: warning: Function parameter or member 'flags' not described in 'rockchip_clk_register_halfdiv' drivers/clk/rockchip/clk-half-divider.c:168: warning: Function parameter or member 'lock' not described in 'rockchip_clk_register_halfdiv' Cc: Michael Turquette Cc: Stephen Boyd Cc: Heiko Stuebner Cc: linux-clk@vger.kernel.org Cc: linux-arm-kernel@lists.infradead.org Cc: linux-rockchip@lists.infradead.org Signed-off-by: Lee Jones Link: https://lore.kernel.org/r/20210120093040.1719407-5-lee.jones@linaro.org Signed-off-by: Heiko Stuebner --- drivers/clk/rockchip/clk-half-divider.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/clk') diff --git a/drivers/clk/rockchip/clk-half-divider.c b/drivers/clk/rockchip/clk-half-divider.c index ccd5c270c213..64f7faad2148 100644 --- a/drivers/clk/rockchip/clk-half-divider.c +++ b/drivers/clk/rockchip/clk-half-divider.c @@ -145,7 +145,7 @@ static const struct clk_ops clk_half_divider_ops = { .set_rate = clk_half_divider_set_rate, }; -/** +/* * Register a clock branch. * Most clock branches have a form like * -- cgit v1.2.3 From 24ece96554a963d5eab597be7d65a1812d854d10 Mon Sep 17 00:00:00 2001 From: Lee Jones Date: Tue, 26 Jan 2021 12:45:30 +0000 Subject: clk: renesas: cpg-mssr: Fix formatting issues for 'smstpcr_saved's documentation Fixes the following W=1 kernel build warning(s): drivers/clk/renesas/renesas-cpg-mssr.c:168: warning: Function parameter or member 'smstpcr_saved' not described in 'cpg_mssr_priv' Signed-off-by: Lee Jones Link: https://lore.kernel.org/r/20210126124540.3320214-12-lee.jones@linaro.org Signed-off-by: Geert Uytterhoeven --- drivers/clk/renesas/renesas-cpg-mssr.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers/clk') diff --git a/drivers/clk/renesas/renesas-cpg-mssr.c b/drivers/clk/renesas/renesas-cpg-mssr.c index 1c3215dc4877..bffbc3d2faf5 100644 --- a/drivers/clk/renesas/renesas-cpg-mssr.c +++ b/drivers/clk/renesas/renesas-cpg-mssr.c @@ -136,8 +136,8 @@ static const u16 srstclr_for_v3u[] = { * @control_regs: Pointer to control registers array * @reset_regs: Pointer to reset registers array * @reset_clear_regs: Pointer to reset clearing registers array - * @smstpcr_saved[].mask: Mask of SMSTPCR[] bits under our control - * @smstpcr_saved[].val: Saved values of SMSTPCR[] + * @smstpcr_saved: [].mask: Mask of SMSTPCR[] bits under our control + * [].val: Saved values of SMSTPCR[] * @clks: Array containing all Core and Module Clocks */ struct cpg_mssr_priv { -- cgit v1.2.3 From 394a36dd9dec7fd48b75dab23432632a30f241ea Mon Sep 17 00:00:00 2001 From: Andre Przywara Date: Wed, 27 Jan 2021 17:24:42 +0000 Subject: clk: sunxi-ng: Add support for the Allwinner H616 R-CCU The clocks itself are identical to the H6 R-CCU, it's just that the H616 has not all of them implemented (or connected). Signed-off-by: Andre Przywara Acked-by: Maxime Ripard Signed-off-by: Maxime Ripard Link: https://lore.kernel.org/r/20210127172500.13356-3-andre.przywara@arm.com --- drivers/clk/sunxi-ng/Kconfig | 2 +- drivers/clk/sunxi-ng/ccu-sun50i-h6-r.c | 48 ++++++++++++++++++++++++++++++++++ 2 files changed, 49 insertions(+), 1 deletion(-) (limited to 'drivers/clk') diff --git a/drivers/clk/sunxi-ng/Kconfig b/drivers/clk/sunxi-ng/Kconfig index ce5f5847d5d3..feeb8d2074ee 100644 --- a/drivers/clk/sunxi-ng/Kconfig +++ b/drivers/clk/sunxi-ng/Kconfig @@ -33,7 +33,7 @@ config SUN50I_H6_CCU depends on (ARM64 && ARCH_SUNXI) || COMPILE_TEST config SUN50I_H6_R_CCU - bool "Support for the Allwinner H6 PRCM CCU" + bool "Support for the Allwinner H6 and H616 PRCM CCU" default ARM64 && ARCH_SUNXI depends on (ARM64 && ARCH_SUNXI) || COMPILE_TEST diff --git a/drivers/clk/sunxi-ng/ccu-sun50i-h6-r.c b/drivers/clk/sunxi-ng/ccu-sun50i-h6-r.c index 56e351b513f3..f8909a7ed553 100644 --- a/drivers/clk/sunxi-ng/ccu-sun50i-h6-r.c +++ b/drivers/clk/sunxi-ng/ccu-sun50i-h6-r.c @@ -139,6 +139,16 @@ static struct ccu_common *sun50i_h6_r_ccu_clks[] = { &w1_clk.common, }; +static struct ccu_common *sun50i_h616_r_ccu_clks[] = { + &r_apb1_clk.common, + &r_apb2_clk.common, + &r_apb1_twd_clk.common, + &r_apb2_i2c_clk.common, + &r_apb2_rsb_clk.common, + &r_apb1_ir_clk.common, + &ir_clk.common, +}; + static struct clk_hw_onecell_data sun50i_h6_r_hw_clks = { .hws = { [CLK_AR100] = &ar100_clk.common.hw, @@ -159,6 +169,20 @@ static struct clk_hw_onecell_data sun50i_h6_r_hw_clks = { .num = CLK_NUMBER, }; +static struct clk_hw_onecell_data sun50i_h616_r_hw_clks = { + .hws = { + [CLK_R_AHB] = &r_ahb_clk.hw, + [CLK_R_APB1] = &r_apb1_clk.common.hw, + [CLK_R_APB2] = &r_apb2_clk.common.hw, + [CLK_R_APB1_TWD] = &r_apb1_twd_clk.common.hw, + [CLK_R_APB2_I2C] = &r_apb2_i2c_clk.common.hw, + [CLK_R_APB2_RSB] = &r_apb2_rsb_clk.common.hw, + [CLK_R_APB1_IR] = &r_apb1_ir_clk.common.hw, + [CLK_IR] = &ir_clk.common.hw, + }, + .num = CLK_NUMBER, +}; + static struct ccu_reset_map sun50i_h6_r_ccu_resets[] = { [RST_R_APB1_TIMER] = { 0x11c, BIT(16) }, [RST_R_APB1_TWD] = { 0x12c, BIT(16) }, @@ -170,6 +194,13 @@ static struct ccu_reset_map sun50i_h6_r_ccu_resets[] = { [RST_R_APB1_W1] = { 0x1ec, BIT(16) }, }; +static struct ccu_reset_map sun50i_h616_r_ccu_resets[] = { + [RST_R_APB1_TWD] = { 0x12c, BIT(16) }, + [RST_R_APB2_I2C] = { 0x19c, BIT(16) }, + [RST_R_APB2_RSB] = { 0x1bc, BIT(16) }, + [RST_R_APB1_IR] = { 0x1cc, BIT(16) }, +}; + static const struct sunxi_ccu_desc sun50i_h6_r_ccu_desc = { .ccu_clks = sun50i_h6_r_ccu_clks, .num_ccu_clks = ARRAY_SIZE(sun50i_h6_r_ccu_clks), @@ -180,6 +211,16 @@ static const struct sunxi_ccu_desc sun50i_h6_r_ccu_desc = { .num_resets = ARRAY_SIZE(sun50i_h6_r_ccu_resets), }; +static const struct sunxi_ccu_desc sun50i_h616_r_ccu_desc = { + .ccu_clks = sun50i_h616_r_ccu_clks, + .num_ccu_clks = ARRAY_SIZE(sun50i_h616_r_ccu_clks), + + .hw_clks = &sun50i_h616_r_hw_clks, + + .resets = sun50i_h616_r_ccu_resets, + .num_resets = ARRAY_SIZE(sun50i_h616_r_ccu_resets), +}; + static void __init sunxi_r_ccu_init(struct device_node *node, const struct sunxi_ccu_desc *desc) { @@ -200,3 +241,10 @@ static void __init sun50i_h6_r_ccu_setup(struct device_node *node) } CLK_OF_DECLARE(sun50i_h6_r_ccu, "allwinner,sun50i-h6-r-ccu", sun50i_h6_r_ccu_setup); + +static void __init sun50i_h616_r_ccu_setup(struct device_node *node) +{ + sunxi_r_ccu_init(node, &sun50i_h616_r_ccu_desc); +} +CLK_OF_DECLARE(sun50i_h616_r_ccu, "allwinner,sun50i-h616-r-ccu", + sun50i_h616_r_ccu_setup); -- cgit v1.2.3 From 88dde5e23da1a16fe9a417171e6c941736b8d3a6 Mon Sep 17 00:00:00 2001 From: Andre Przywara Date: Wed, 27 Jan 2021 17:24:43 +0000 Subject: clk: sunxi-ng: Add support for the Allwinner H616 CCU While the clocks are fairly similar to the H6, many differ in tiny details, so a separate clock driver seems indicated. Derived from the H6 clock driver, and adjusted according to the manual. Signed-off-by: Andre Przywara Acked-by: Maxime Ripard Signed-off-by: Maxime Ripard Link: https://lore.kernel.org/r/20210127172500.13356-4-andre.przywara@arm.com --- drivers/clk/sunxi-ng/Kconfig | 5 + drivers/clk/sunxi-ng/Makefile | 1 + drivers/clk/sunxi-ng/ccu-sun50i-h616.c | 1150 +++++++++++++++++++++++++++ drivers/clk/sunxi-ng/ccu-sun50i-h616.h | 56 ++ include/dt-bindings/clock/sun50i-h616-ccu.h | 115 +++ include/dt-bindings/reset/sun50i-h616-ccu.h | 70 ++ 6 files changed, 1397 insertions(+) create mode 100644 drivers/clk/sunxi-ng/ccu-sun50i-h616.c create mode 100644 drivers/clk/sunxi-ng/ccu-sun50i-h616.h create mode 100644 include/dt-bindings/clock/sun50i-h616-ccu.h create mode 100644 include/dt-bindings/reset/sun50i-h616-ccu.h (limited to 'drivers/clk') diff --git a/drivers/clk/sunxi-ng/Kconfig b/drivers/clk/sunxi-ng/Kconfig index feeb8d2074ee..cd46d8853876 100644 --- a/drivers/clk/sunxi-ng/Kconfig +++ b/drivers/clk/sunxi-ng/Kconfig @@ -32,6 +32,11 @@ config SUN50I_H6_CCU default ARM64 && ARCH_SUNXI depends on (ARM64 && ARCH_SUNXI) || COMPILE_TEST +config SUN50I_H616_CCU + bool "Support for the Allwinner H616 CCU" + default ARM64 && ARCH_SUNXI + depends on (ARM64 && ARCH_SUNXI) || COMPILE_TEST + config SUN50I_H6_R_CCU bool "Support for the Allwinner H6 and H616 PRCM CCU" default ARM64 && ARCH_SUNXI diff --git a/drivers/clk/sunxi-ng/Makefile b/drivers/clk/sunxi-ng/Makefile index 3eb5cff40eac..96c324306d97 100644 --- a/drivers/clk/sunxi-ng/Makefile +++ b/drivers/clk/sunxi-ng/Makefile @@ -26,6 +26,7 @@ obj-$(CONFIG_SUN50I_A64_CCU) += ccu-sun50i-a64.o obj-$(CONFIG_SUN50I_A100_CCU) += ccu-sun50i-a100.o obj-$(CONFIG_SUN50I_A100_R_CCU) += ccu-sun50i-a100-r.o obj-$(CONFIG_SUN50I_H6_CCU) += ccu-sun50i-h6.o +obj-$(CONFIG_SUN50I_H616_CCU) += ccu-sun50i-h616.o obj-$(CONFIG_SUN50I_H6_R_CCU) += ccu-sun50i-h6-r.o obj-$(CONFIG_SUN4I_A10_CCU) += ccu-sun4i-a10.o obj-$(CONFIG_SUN5I_CCU) += ccu-sun5i.o diff --git a/drivers/clk/sunxi-ng/ccu-sun50i-h616.c b/drivers/clk/sunxi-ng/ccu-sun50i-h616.c new file mode 100644 index 000000000000..225307305880 --- /dev/null +++ b/drivers/clk/sunxi-ng/ccu-sun50i-h616.c @@ -0,0 +1,1150 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (c) 2020 Arm Ltd. + * Based on the H6 CCU driver, which is: + * Copyright (c) 2017 Icenowy Zheng + */ + +#include +#include +#include +#include + +#include "ccu_common.h" +#include "ccu_reset.h" + +#include "ccu_div.h" +#include "ccu_gate.h" +#include "ccu_mp.h" +#include "ccu_mult.h" +#include "ccu_nk.h" +#include "ccu_nkm.h" +#include "ccu_nkmp.h" +#include "ccu_nm.h" + +#include "ccu-sun50i-h616.h" + +/* + * The CPU PLL is actually NP clock, with P being /1, /2 or /4. However + * P should only be used for output frequencies lower than 288 MHz. + * + * For now we can just model it as a multiplier clock, and force P to /1. + * + * The M factor is present in the register's description, but not in the + * frequency formula, and it's documented as "M is only used for backdoor + * testing", so it's not modelled and then force to 0. + */ +#define SUN50I_H616_PLL_CPUX_REG 0x000 +static struct ccu_mult pll_cpux_clk = { + .enable = BIT(31), + .lock = BIT(28), + .mult = _SUNXI_CCU_MULT_MIN(8, 8, 12), + .common = { + .reg = 0x000, + .hw.init = CLK_HW_INIT("pll-cpux", "osc24M", + &ccu_mult_ops, + CLK_SET_RATE_UNGATE), + }, +}; + +/* Some PLLs are input * N / div1 / P. Model them as NKMP with no K */ +#define SUN50I_H616_PLL_DDR0_REG 0x010 +static struct ccu_nkmp pll_ddr0_clk = { + .enable = BIT(31), + .lock = BIT(28), + .n = _SUNXI_CCU_MULT_MIN(8, 8, 12), + .m = _SUNXI_CCU_DIV(1, 1), /* input divider */ + .p = _SUNXI_CCU_DIV(0, 1), /* output divider */ + .common = { + .reg = 0x010, + .hw.init = CLK_HW_INIT("pll-ddr0", "osc24M", + &ccu_nkmp_ops, + CLK_SET_RATE_UNGATE), + }, +}; + +#define SUN50I_H616_PLL_DDR1_REG 0x018 +static struct ccu_nkmp pll_ddr1_clk = { + .enable = BIT(31), + .lock = BIT(28), + .n = _SUNXI_CCU_MULT_MIN(8, 8, 12), + .m = _SUNXI_CCU_DIV(1, 1), /* input divider */ + .p = _SUNXI_CCU_DIV(0, 1), /* output divider */ + .common = { + .reg = 0x018, + .hw.init = CLK_HW_INIT("pll-ddr1", "osc24M", + &ccu_nkmp_ops, + CLK_SET_RATE_UNGATE), + }, +}; + +#define SUN50I_H616_PLL_PERIPH0_REG 0x020 +static struct ccu_nkmp pll_periph0_clk = { + .enable = BIT(31), + .lock = BIT(28), + .n = _SUNXI_CCU_MULT_MIN(8, 8, 12), + .m = _SUNXI_CCU_DIV(1, 1), /* input divider */ + .p = _SUNXI_CCU_DIV(0, 1), /* output divider */ + .fixed_post_div = 2, + .common = { + .reg = 0x020, + .features = CCU_FEATURE_FIXED_POSTDIV, + .hw.init = CLK_HW_INIT("pll-periph0", "osc24M", + &ccu_nkmp_ops, + CLK_SET_RATE_UNGATE), + }, +}; + +#define SUN50I_H616_PLL_PERIPH1_REG 0x028 +static struct ccu_nkmp pll_periph1_clk = { + .enable = BIT(31), + .lock = BIT(28), + .n = _SUNXI_CCU_MULT_MIN(8, 8, 12), + .m = _SUNXI_CCU_DIV(1, 1), /* input divider */ + .p = _SUNXI_CCU_DIV(0, 1), /* output divider */ + .fixed_post_div = 2, + .common = { + .reg = 0x028, + .features = CCU_FEATURE_FIXED_POSTDIV, + .hw.init = CLK_HW_INIT("pll-periph1", "osc24M", + &ccu_nkmp_ops, + CLK_SET_RATE_UNGATE), + }, +}; + +#define SUN50I_H616_PLL_GPU_REG 0x030 +static struct ccu_nkmp pll_gpu_clk = { + .enable = BIT(31), + .lock = BIT(28), + .n = _SUNXI_CCU_MULT_MIN(8, 8, 12), + .m = _SUNXI_CCU_DIV(1, 1), /* input divider */ + .p = _SUNXI_CCU_DIV(0, 1), /* output divider */ + .common = { + .reg = 0x030, + .hw.init = CLK_HW_INIT("pll-gpu", "osc24M", + &ccu_nkmp_ops, + CLK_SET_RATE_UNGATE), + }, +}; + +/* + * For Video PLLs, the output divider is described as "used for testing" + * in the user manual. So it's not modelled and forced to 0. + */ +#define SUN50I_H616_PLL_VIDEO0_REG 0x040 +static struct ccu_nm pll_video0_clk = { + .enable = BIT(31), + .lock = BIT(28), + .n = _SUNXI_CCU_MULT_MIN(8, 8, 12), + .m = _SUNXI_CCU_DIV(1, 1), /* input divider */ + .fixed_post_div = 4, + .min_rate = 288000000, + .max_rate = 2400000000UL, + .common = { + .reg = 0x040, + .features = CCU_FEATURE_FIXED_POSTDIV, + .hw.init = CLK_HW_INIT("pll-video0", "osc24M", + &ccu_nm_ops, + CLK_SET_RATE_UNGATE), + }, +}; + +#define SUN50I_H616_PLL_VIDEO1_REG 0x048 +static struct ccu_nm pll_video1_clk = { + .enable = BIT(31), + .lock = BIT(28), + .n = _SUNXI_CCU_MULT_MIN(8, 8, 12), + .m = _SUNXI_CCU_DIV(1, 1), /* input divider */ + .fixed_post_div = 4, + .min_rate = 288000000, + .max_rate = 2400000000UL, + .common = { + .reg = 0x048, + .features = CCU_FEATURE_FIXED_POSTDIV, + .hw.init = CLK_HW_INIT("pll-video1", "osc24M", + &ccu_nm_ops, + CLK_SET_RATE_UNGATE), + }, +}; + +#define SUN50I_H616_PLL_VIDEO2_REG 0x050 +static struct ccu_nm pll_video2_clk = { + .enable = BIT(31), + .lock = BIT(28), + .n = _SUNXI_CCU_MULT_MIN(8, 8, 12), + .m = _SUNXI_CCU_DIV(1, 1), /* input divider */ + .fixed_post_div = 4, + .min_rate = 288000000, + .max_rate = 2400000000UL, + .common = { + .reg = 0x050, + .features = CCU_FEATURE_FIXED_POSTDIV, + .hw.init = CLK_HW_INIT("pll-video2", "osc24M", + &ccu_nm_ops, + CLK_SET_RATE_UNGATE), + }, +}; + +#define SUN50I_H616_PLL_VE_REG 0x058 +static struct ccu_nkmp pll_ve_clk = { + .enable = BIT(31), + .lock = BIT(28), + .n = _SUNXI_CCU_MULT_MIN(8, 8, 12), + .m = _SUNXI_CCU_DIV(1, 1), /* input divider */ + .p = _SUNXI_CCU_DIV(0, 1), /* output divider */ + .common = { + .reg = 0x058, + .hw.init = CLK_HW_INIT("pll-ve", "osc24M", + &ccu_nkmp_ops, + CLK_SET_RATE_UNGATE), + }, +}; + +#define SUN50I_H616_PLL_DE_REG 0x060 +static struct ccu_nkmp pll_de_clk = { + .enable = BIT(31), + .lock = BIT(28), + .n = _SUNXI_CCU_MULT_MIN(8, 8, 12), + .m = _SUNXI_CCU_DIV(1, 1), /* input divider */ + .p = _SUNXI_CCU_DIV(0, 1), /* output divider */ + .common = { + .reg = 0x060, + .hw.init = CLK_HW_INIT("pll-de", "osc24M", + &ccu_nkmp_ops, + CLK_SET_RATE_UNGATE), + }, +}; + +/* + * TODO: Determine SDM settings for the audio PLL. The manual suggests + * PLL_FACTOR_N=16, PLL_POST_DIV_P=2, OUTPUT_DIV=2, pattern=0xe000c49b + * for 24.576 MHz, and PLL_FACTOR_N=22, PLL_POST_DIV_P=3, OUTPUT_DIV=2, + * pattern=0xe001288c for 22.5792 MHz. + * This clashes with our fixed PLL_POST_DIV_P. + */ +#define SUN50I_H616_PLL_AUDIO_REG 0x078 +static struct ccu_nm pll_audio_hs_clk = { + .enable = BIT(31), + .lock = BIT(28), + .n = _SUNXI_CCU_MULT_MIN(8, 8, 12), + .m = _SUNXI_CCU_DIV(1, 1), /* input divider */ + .common = { + .reg = 0x078, + .hw.init = CLK_HW_INIT("pll-audio-hs", "osc24M", + &ccu_nm_ops, + CLK_SET_RATE_UNGATE), + }, +}; + +static const char * const cpux_parents[] = { "osc24M", "osc32k", + "iosc", "pll-cpux", "pll-periph0" }; +static SUNXI_CCU_MUX(cpux_clk, "cpux", cpux_parents, + 0x500, 24, 3, CLK_SET_RATE_PARENT | CLK_IS_CRITICAL); +static SUNXI_CCU_M(axi_clk, "axi", "cpux", 0x500, 0, 2, 0); +static SUNXI_CCU_M(cpux_apb_clk, "cpux-apb", "cpux", 0x500, 8, 2, 0); + +static const char * const psi_ahb1_ahb2_parents[] = { "osc24M", "osc32k", + "iosc", "pll-periph0" }; +static SUNXI_CCU_MP_WITH_MUX(psi_ahb1_ahb2_clk, "psi-ahb1-ahb2", + psi_ahb1_ahb2_parents, + 0x510, + 0, 2, /* M */ + 8, 2, /* P */ + 24, 2, /* mux */ + 0); + +static const char * const ahb3_apb1_apb2_parents[] = { "osc24M", "osc32k", + "psi-ahb1-ahb2", + "pll-periph0" }; +static SUNXI_CCU_MP_WITH_MUX(ahb3_clk, "ahb3", ahb3_apb1_apb2_parents, 0x51c, + 0, 2, /* M */ + 8, 2, /* P */ + 24, 2, /* mux */ + 0); + +static SUNXI_CCU_MP_WITH_MUX(apb1_clk, "apb1", ahb3_apb1_apb2_parents, 0x520, + 0, 2, /* M */ + 8, 2, /* P */ + 24, 2, /* mux */ + 0); + +static SUNXI_CCU_MP_WITH_MUX(apb2_clk, "apb2", ahb3_apb1_apb2_parents, 0x524, + 0, 2, /* M */ + 8, 2, /* P */ + 24, 2, /* mux */ + 0); + +static const char * const mbus_parents[] = { "osc24M", "pll-periph0-2x", + "pll-ddr0", "pll-ddr1" }; +static SUNXI_CCU_M_WITH_MUX_GATE(mbus_clk, "mbus", mbus_parents, 0x540, + 0, 3, /* M */ + 24, 2, /* mux */ + BIT(31), /* gate */ + CLK_IS_CRITICAL); + +static const char * const de_parents[] = { "pll-de", "pll-periph0-2x" }; +static SUNXI_CCU_M_WITH_MUX_GATE(de_clk, "de", de_parents, 0x600, + 0, 4, /* M */ + 24, 1, /* mux */ + BIT(31), /* gate */ + CLK_SET_RATE_PARENT); + +static SUNXI_CCU_GATE(bus_de_clk, "bus-de", "psi-ahb1-ahb2", + 0x60c, BIT(0), 0); + +static SUNXI_CCU_M_WITH_MUX_GATE(deinterlace_clk, "deinterlace", + de_parents, + 0x620, + 0, 4, /* M */ + 24, 1, /* mux */ + BIT(31), /* gate */ + 0); + +static SUNXI_CCU_GATE(bus_deinterlace_clk, "bus-deinterlace", "psi-ahb1-ahb2", + 0x62c, BIT(0), 0); + +static SUNXI_CCU_M_WITH_MUX_GATE(g2d_clk, "g2d", de_parents, 0x630, + 0, 4, /* M */ + 24, 1, /* mux */ + BIT(31), /* gate */ + 0); + +static SUNXI_CCU_GATE(bus_g2d_clk, "bus-g2d", "psi-ahb1-ahb2", + 0x63c, BIT(0), 0); + +static const char * const gpu0_parents[] = { "pll-gpu", "gpu1" }; +static SUNXI_CCU_M_WITH_MUX_GATE(gpu0_clk, "gpu0", gpu0_parents, 0x670, + 0, 2, /* M */ + 24, 1, /* mux */ + BIT(31), /* gate */ + CLK_SET_RATE_PARENT); +static SUNXI_CCU_M_WITH_GATE(gpu1_clk, "gpu1", "pll-periph0-2x", 0x674, + 0, 2, /* M */ + BIT(31),/* gate */ + 0); + +static SUNXI_CCU_GATE(bus_gpu_clk, "bus-gpu", "psi-ahb1-ahb2", + 0x67c, BIT(0), 0); + +static const char * const ce_parents[] = { "osc24M", "pll-periph0-2x" }; +static SUNXI_CCU_MP_WITH_MUX_GATE(ce_clk, "ce", ce_parents, 0x680, + 0, 4, /* M */ + 8, 2, /* N */ + 24, 1, /* mux */ + BIT(31),/* gate */ + 0); + +static SUNXI_CCU_GATE(bus_ce_clk, "bus-ce", "psi-ahb1-ahb2", + 0x68c, BIT(0), 0); + +static const char * const ve_parents[] = { "pll-ve" }; +static SUNXI_CCU_M_WITH_MUX_GATE(ve_clk, "ve", ve_parents, 0x690, + 0, 3, /* M */ + 24, 1, /* mux */ + BIT(31), /* gate */ + CLK_SET_RATE_PARENT); + +static SUNXI_CCU_GATE(bus_ve_clk, "bus-ve", "psi-ahb1-ahb2", + 0x69c, BIT(0), 0); + +static SUNXI_CCU_GATE(bus_dma_clk, "bus-dma", "psi-ahb1-ahb2", + 0x70c, BIT(0), 0); + +static SUNXI_CCU_GATE(bus_hstimer_clk, "bus-hstimer", "psi-ahb1-ahb2", + 0x73c, BIT(0), 0); + +static SUNXI_CCU_GATE(avs_clk, "avs", "osc24M", 0x740, BIT(31), 0); + +static SUNXI_CCU_GATE(bus_dbg_clk, "bus-dbg", "psi-ahb1-ahb2", + 0x78c, BIT(0), 0); + +static SUNXI_CCU_GATE(bus_psi_clk, "bus-psi", "psi-ahb1-ahb2", + 0x79c, BIT(0), 0); + +static SUNXI_CCU_GATE(bus_pwm_clk, "bus-pwm", "apb1", 0x7ac, BIT(0), 0); + +static SUNXI_CCU_GATE(bus_iommu_clk, "bus-iommu", "apb1", 0x7bc, BIT(0), 0); + +static const char * const dram_parents[] = { "pll-ddr0", "pll-ddr1" }; +static struct ccu_div dram_clk = { + .div = _SUNXI_CCU_DIV(0, 2), + .mux = _SUNXI_CCU_MUX(24, 2), + .common = { + .reg = 0x800, + .hw.init = CLK_HW_INIT_PARENTS("dram", + dram_parents, + &ccu_div_ops, + CLK_IS_CRITICAL), + }, +}; + +static SUNXI_CCU_GATE(mbus_dma_clk, "mbus-dma", "mbus", + 0x804, BIT(0), 0); +static SUNXI_CCU_GATE(mbus_ve_clk, "mbus-ve", "mbus", + 0x804, BIT(1), 0); +static SUNXI_CCU_GATE(mbus_ce_clk, "mbus-ce", "mbus", + 0x804, BIT(2), 0); +static SUNXI_CCU_GATE(mbus_ts_clk, "mbus-ts", "mbus", + 0x804, BIT(3), 0); +static SUNXI_CCU_GATE(mbus_nand_clk, "mbus-nand", "mbus", + 0x804, BIT(5), 0); +static SUNXI_CCU_GATE(mbus_g2d_clk, "mbus-g2d", "mbus", + 0x804, BIT(10), 0); + +static SUNXI_CCU_GATE(bus_dram_clk, "bus-dram", "psi-ahb1-ahb2", + 0x80c, BIT(0), CLK_IS_CRITICAL); + +static const char * const nand_spi_parents[] = { "osc24M", "pll-periph0", + "pll-periph1", "pll-periph0-2x", + "pll-periph1-2x" }; +static SUNXI_CCU_MP_WITH_MUX_GATE(nand0_clk, "nand0", nand_spi_parents, 0x810, + 0, 4, /* M */ + 8, 2, /* N */ + 24, 3, /* mux */ + BIT(31),/* gate */ + 0); + +static SUNXI_CCU_MP_WITH_MUX_GATE(nand1_clk, "nand1", nand_spi_parents, 0x814, + 0, 4, /* M */ + 8, 2, /* N */ + 24, 3, /* mux */ + BIT(31),/* gate */ + 0); + +static SUNXI_CCU_GATE(bus_nand_clk, "bus-nand", "ahb3", 0x82c, BIT(0), 0); + +static const char * const mmc_parents[] = { "osc24M", "pll-periph0-2x", + "pll-periph1-2x" }; +static SUNXI_CCU_MP_WITH_MUX_GATE_POSTDIV(mmc0_clk, "mmc0", mmc_parents, 0x830, + 0, 4, /* M */ + 8, 2, /* N */ + 24, 2, /* mux */ + BIT(31), /* gate */ + 2, /* post-div */ + 0); + +static SUNXI_CCU_MP_WITH_MUX_GATE_POSTDIV(mmc1_clk, "mmc1", mmc_parents, 0x834, + 0, 4, /* M */ + 8, 2, /* N */ + 24, 2, /* mux */ + BIT(31), /* gate */ + 2, /* post-div */ + 0); + +static SUNXI_CCU_MP_WITH_MUX_GATE_POSTDIV(mmc2_clk, "mmc2", mmc_parents, 0x838, + 0, 4, /* M */ + 8, 2, /* N */ + 24, 2, /* mux */ + BIT(31), /* gate */ + 2, /* post-div */ + 0); + +static SUNXI_CCU_GATE(bus_mmc0_clk, "bus-mmc0", "ahb3", 0x84c, BIT(0), 0); +static SUNXI_CCU_GATE(bus_mmc1_clk, "bus-mmc1", "ahb3", 0x84c, BIT(1), 0); +static SUNXI_CCU_GATE(bus_mmc2_clk, "bus-mmc2", "ahb3", 0x84c, BIT(2), 0); + +static SUNXI_CCU_GATE(bus_uart0_clk, "bus-uart0", "apb2", 0x90c, BIT(0), 0); +static SUNXI_CCU_GATE(bus_uart1_clk, "bus-uart1", "apb2", 0x90c, BIT(1), 0); +static SUNXI_CCU_GATE(bus_uart2_clk, "bus-uart2", "apb2", 0x90c, BIT(2), 0); +static SUNXI_CCU_GATE(bus_uart3_clk, "bus-uart3", "apb2", 0x90c, BIT(3), 0); +static SUNXI_CCU_GATE(bus_uart4_clk, "bus-uart4", "apb2", 0x90c, BIT(4), 0); +static SUNXI_CCU_GATE(bus_uart5_clk, "bus-uart5", "apb2", 0x90c, BIT(5), 0); + +static SUNXI_CCU_GATE(bus_i2c0_clk, "bus-i2c0", "apb2", 0x91c, BIT(0), 0); +static SUNXI_CCU_GATE(bus_i2c1_clk, "bus-i2c1", "apb2", 0x91c, BIT(1), 0); +static SUNXI_CCU_GATE(bus_i2c2_clk, "bus-i2c2", "apb2", 0x91c, BIT(2), 0); +static SUNXI_CCU_GATE(bus_i2c3_clk, "bus-i2c3", "apb2", 0x91c, BIT(3), 0); +static SUNXI_CCU_GATE(bus_i2c4_clk, "bus-i2c4", "apb2", 0x91c, BIT(4), 0); + +static SUNXI_CCU_MP_WITH_MUX_GATE(spi0_clk, "spi0", nand_spi_parents, 0x940, + 0, 4, /* M */ + 8, 2, /* N */ + 24, 3, /* mux */ + BIT(31),/* gate */ + 0); + +static SUNXI_CCU_MP_WITH_MUX_GATE(spi1_clk, "spi1", nand_spi_parents, 0x944, + 0, 4, /* M */ + 8, 2, /* N */ + 24, 3, /* mux */ + BIT(31),/* gate */ + 0); + +static SUNXI_CCU_GATE(bus_spi0_clk, "bus-spi0", "ahb3", 0x96c, BIT(0), 0); +static SUNXI_CCU_GATE(bus_spi1_clk, "bus-spi1", "ahb3", 0x96c, BIT(1), 0); + +static SUNXI_CCU_GATE(emac_25m_clk, "emac-25m", "ahb3", 0x970, + BIT(31) | BIT(30), 0); + +static SUNXI_CCU_GATE(bus_emac0_clk, "bus-emac0", "ahb3", 0x97c, BIT(0), 0); +static SUNXI_CCU_GATE(bus_emac1_clk, "bus-emac1", "ahb3", 0x97c, BIT(1), 0); + +static const char * const ts_parents[] = { "osc24M", "pll-periph0" }; +static SUNXI_CCU_MP_WITH_MUX_GATE(ts_clk, "ts", ts_parents, 0x9b0, + 0, 4, /* M */ + 8, 2, /* N */ + 24, 1, /* mux */ + BIT(31),/* gate */ + 0); + +static SUNXI_CCU_GATE(bus_ts_clk, "bus-ts", "ahb3", 0x9bc, BIT(0), 0); + +static SUNXI_CCU_GATE(bus_ths_clk, "bus-ths", "apb1", 0x9fc, BIT(0), 0); + +static const char * const audio_parents[] = { "pll-audio-1x", "pll-audio-2x", + "pll-audio-4x", "pll-audio-hs" }; +static struct ccu_div spdif_clk = { + .enable = BIT(31), + .div = _SUNXI_CCU_DIV_FLAGS(8, 2, CLK_DIVIDER_POWER_OF_TWO), + .mux = _SUNXI_CCU_MUX(24, 2), + .common = { + .reg = 0xa20, + .hw.init = CLK_HW_INIT_PARENTS("spdif", + audio_parents, + &ccu_div_ops, + 0), + }, +}; + +static SUNXI_CCU_GATE(bus_spdif_clk, "bus-spdif", "apb1", 0xa2c, BIT(0), 0); + +static struct ccu_div dmic_clk = { + .enable = BIT(31), + .div = _SUNXI_CCU_DIV_FLAGS(8, 2, CLK_DIVIDER_POWER_OF_TWO), + .mux = _SUNXI_CCU_MUX(24, 2), + .common = { + .reg = 0xa40, + .hw.init = CLK_HW_INIT_PARENTS("dmic", + audio_parents, + &ccu_div_ops, + 0), + }, +}; + +static SUNXI_CCU_GATE(bus_dmic_clk, "bus-dmic", "apb1", 0xa4c, BIT(0), 0); + +static SUNXI_CCU_M_WITH_MUX_GATE(audio_codec_1x_clk, "audio-codec-1x", + audio_parents, 0xa50, + 0, 4, /* M */ + 24, 2, /* mux */ + BIT(31), /* gate */ + CLK_SET_RATE_PARENT); +static SUNXI_CCU_M_WITH_MUX_GATE(audio_codec_4x_clk, "audio-codec-4x", + audio_parents, 0xa54, + 0, 4, /* M */ + 24, 2, /* mux */ + BIT(31), /* gate */ + CLK_SET_RATE_PARENT); + +static SUNXI_CCU_GATE(bus_audio_codec_clk, "bus-audio-codec", "apb1", 0xa5c, + BIT(0), 0); + +static struct ccu_div audio_hub_clk = { + .enable = BIT(31), + .div = _SUNXI_CCU_DIV_FLAGS(8, 2, CLK_DIVIDER_POWER_OF_TWO), + .mux = _SUNXI_CCU_MUX(24, 2), + .common = { + .reg = 0xa60, + .hw.init = CLK_HW_INIT_PARENTS("audio-hub", + audio_parents, + &ccu_div_ops, + 0), + }, +}; + +static SUNXI_CCU_GATE(bus_audio_hub_clk, "bus-audio-hub", "apb1", 0xa6c, BIT(0), 0); + +/* + * There are OHCI 12M clock source selection bits for the four USB 2.0 ports. + * We will force them to 0 (12M divided from 48M). + */ +#define SUN50I_H616_USB0_CLK_REG 0xa70 +#define SUN50I_H616_USB1_CLK_REG 0xa74 +#define SUN50I_H616_USB2_CLK_REG 0xa78 +#define SUN50I_H616_USB3_CLK_REG 0xa7c + +static SUNXI_CCU_GATE(usb_ohci0_clk, "usb-ohci0", "osc12M", 0xa70, BIT(31), 0); +static SUNXI_CCU_GATE(usb_phy0_clk, "usb-phy0", "osc24M", 0xa70, BIT(29), 0); + +static SUNXI_CCU_GATE(usb_ohci1_clk, "usb-ohci1", "osc12M", 0xa74, BIT(31), 0); +static SUNXI_CCU_GATE(usb_phy1_clk, "usb-phy1", "osc24M", 0xa74, BIT(29), 0); + +static SUNXI_CCU_GATE(usb_ohci2_clk, "usb-ohci2", "osc12M", 0xa78, BIT(31), 0); +static SUNXI_CCU_GATE(usb_phy2_clk, "usb-phy2", "osc24M", 0xa78, BIT(29), 0); + +static SUNXI_CCU_GATE(usb_ohci3_clk, "usb-ohci3", "osc12M", 0xa7c, BIT(31), 0); +static SUNXI_CCU_GATE(usb_phy3_clk, "usb-phy3", "osc24M", 0xa7c, BIT(29), 0); + +static SUNXI_CCU_GATE(bus_ohci0_clk, "bus-ohci0", "ahb3", 0xa8c, BIT(0), 0); +static SUNXI_CCU_GATE(bus_ohci1_clk, "bus-ohci1", "ahb3", 0xa8c, BIT(1), 0); +static SUNXI_CCU_GATE(bus_ohci2_clk, "bus-ohci2", "ahb3", 0xa8c, BIT(2), 0); +static SUNXI_CCU_GATE(bus_ohci3_clk, "bus-ohci3", "ahb3", 0xa8c, BIT(3), 0); +static SUNXI_CCU_GATE(bus_ehci0_clk, "bus-ehci0", "ahb3", 0xa8c, BIT(4), 0); +static SUNXI_CCU_GATE(bus_ehci1_clk, "bus-ehci1", "ahb3", 0xa8c, BIT(5), 0); +static SUNXI_CCU_GATE(bus_ehci2_clk, "bus-ehci2", "ahb3", 0xa8c, BIT(6), 0); +static SUNXI_CCU_GATE(bus_ehci3_clk, "bus-ehci3", "ahb3", 0xa8c, BIT(7), 0); +static SUNXI_CCU_GATE(bus_otg_clk, "bus-otg", "ahb3", 0xa8c, BIT(8), 0); + +static SUNXI_CCU_GATE(bus_keyadc_clk, "bus-keyadc", "apb1", 0xa9c, BIT(0), 0); + +static const char * const hdmi_parents[] = { "pll-video0", "pll-video0-4x", + "pll-video2", "pll-video2-4x" }; +static SUNXI_CCU_M_WITH_MUX_GATE(hdmi_clk, "hdmi", hdmi_parents, 0xb00, + 0, 4, /* M */ + 24, 2, /* mux */ + BIT(31), /* gate */ + 0); + +static SUNXI_CCU_GATE(hdmi_slow_clk, "hdmi-slow", "osc24M", 0xb04, BIT(31), 0); + +static const char * const hdmi_cec_parents[] = { "osc32k", "pll-periph0-2x" }; +static const struct ccu_mux_fixed_prediv hdmi_cec_predivs[] = { + { .index = 1, .div = 36621 }, +}; + +#define SUN50I_H616_HDMI_CEC_CLK_REG 0xb10 +static struct ccu_mux hdmi_cec_clk = { + .enable = BIT(31) | BIT(30), + + .mux = { + .shift = 24, + .width = 2, + + .fixed_predivs = hdmi_cec_predivs, + .n_predivs = ARRAY_SIZE(hdmi_cec_predivs), + }, + + .common = { + .reg = 0xb10, + .features = CCU_FEATURE_FIXED_PREDIV, + .hw.init = CLK_HW_INIT_PARENTS("hdmi-cec", + hdmi_cec_parents, + &ccu_mux_ops, + 0), + }, +}; + +static SUNXI_CCU_GATE(bus_hdmi_clk, "bus-hdmi", "ahb3", 0xb1c, BIT(0), 0); + +static SUNXI_CCU_GATE(bus_tcon_top_clk, "bus-tcon-top", "ahb3", + 0xb5c, BIT(0), 0); + +static const char * const tcon_tv_parents[] = { "pll-video0", + "pll-video0-4x", + "pll-video1", + "pll-video1-4x" }; +static SUNXI_CCU_MP_WITH_MUX_GATE(tcon_tv0_clk, "tcon-tv0", + tcon_tv_parents, 0xb80, + 0, 4, /* M */ + 8, 2, /* P */ + 24, 3, /* mux */ + BIT(31), /* gate */ + CLK_SET_RATE_PARENT); +static SUNXI_CCU_MP_WITH_MUX_GATE(tcon_tv1_clk, "tcon-tv1", + tcon_tv_parents, 0xb84, + 0, 4, /* M */ + 8, 2, /* P */ + 24, 3, /* mux */ + BIT(31), /* gate */ + CLK_SET_RATE_PARENT); + +static SUNXI_CCU_GATE(bus_tcon_tv0_clk, "bus-tcon-tv0", "ahb3", + 0xb9c, BIT(0), 0); +static SUNXI_CCU_GATE(bus_tcon_tv1_clk, "bus-tcon-tv1", "ahb3", + 0xb9c, BIT(1), 0); + +static SUNXI_CCU_MP_WITH_MUX_GATE(tve0_clk, "tve0", + tcon_tv_parents, 0xbb0, + 0, 4, /* M */ + 8, 2, /* P */ + 24, 3, /* mux */ + BIT(31), /* gate */ + CLK_SET_RATE_PARENT); + +static SUNXI_CCU_GATE(bus_tve_top_clk, "bus-tve-top", "ahb3", + 0xbbc, BIT(0), 0); +static SUNXI_CCU_GATE(bus_tve0_clk, "bus-tve0", "ahb3", + 0xbbc, BIT(1), 0); + +static const char * const hdcp_parents[] = { "pll-periph0", "pll-periph1" }; +static SUNXI_CCU_M_WITH_MUX_GATE(hdcp_clk, "hdcp", hdcp_parents, 0xc40, + 0, 4, /* M */ + 24, 2, /* mux */ + BIT(31), /* gate */ + 0); + +static SUNXI_CCU_GATE(bus_hdcp_clk, "bus-hdcp", "ahb3", 0xc4c, BIT(0), 0); + +/* Fixed factor clocks */ +static CLK_FIXED_FACTOR_FW_NAME(osc12M_clk, "osc12M", "hosc", 2, 1, 0); + +static const struct clk_hw *clk_parent_pll_audio[] = { + &pll_audio_hs_clk.common.hw +}; + +/* + * The divider of pll-audio is fixed to 24 for now, so 24576000 and 22579200 + * rates can be set exactly in conjunction with sigma-delta modulation. + */ +static CLK_FIXED_FACTOR_HWS(pll_audio_1x_clk, "pll-audio-1x", + clk_parent_pll_audio, + 96, 1, CLK_SET_RATE_PARENT); +static CLK_FIXED_FACTOR_HWS(pll_audio_2x_clk, "pll-audio-2x", + clk_parent_pll_audio, + 48, 1, CLK_SET_RATE_PARENT); +static CLK_FIXED_FACTOR_HWS(pll_audio_4x_clk, "pll-audio-4x", + clk_parent_pll_audio, + 24, 1, CLK_SET_RATE_PARENT); + +static const struct clk_hw *pll_periph0_parents[] = { + &pll_periph0_clk.common.hw +}; + +static CLK_FIXED_FACTOR_HWS(pll_periph0_2x_clk, "pll-periph0-2x", + pll_periph0_parents, + 1, 2, 0); + +static const struct clk_hw *pll_periph1_parents[] = { + &pll_periph1_clk.common.hw +}; + +static CLK_FIXED_FACTOR_HWS(pll_periph1_2x_clk, "pll-periph1-2x", + pll_periph1_parents, + 1, 2, 0); + +static CLK_FIXED_FACTOR_HW(pll_video0_4x_clk, "pll-video0-4x", + &pll_video0_clk.common.hw, + 1, 4, CLK_SET_RATE_PARENT); +static CLK_FIXED_FACTOR_HW(pll_video1_4x_clk, "pll-video1-4x", + &pll_video1_clk.common.hw, + 1, 4, CLK_SET_RATE_PARENT); +static CLK_FIXED_FACTOR_HW(pll_video2_4x_clk, "pll-video2-4x", + &pll_video2_clk.common.hw, + 1, 4, CLK_SET_RATE_PARENT); + +static struct ccu_common *sun50i_h616_ccu_clks[] = { + &pll_cpux_clk.common, + &pll_ddr0_clk.common, + &pll_ddr1_clk.common, + &pll_periph0_clk.common, + &pll_periph1_clk.common, + &pll_gpu_clk.common, + &pll_video0_clk.common, + &pll_video1_clk.common, + &pll_video2_clk.common, + &pll_ve_clk.common, + &pll_de_clk.common, + &pll_audio_hs_clk.common, + &cpux_clk.common, + &axi_clk.common, + &cpux_apb_clk.common, + &psi_ahb1_ahb2_clk.common, + &ahb3_clk.common, + &apb1_clk.common, + &apb2_clk.common, + &mbus_clk.common, + &de_clk.common, + &bus_de_clk.common, + &deinterlace_clk.common, + &bus_deinterlace_clk.common, + &g2d_clk.common, + &bus_g2d_clk.common, + &gpu0_clk.common, + &bus_gpu_clk.common, + &gpu1_clk.common, + &ce_clk.common, + &bus_ce_clk.common, + &ve_clk.common, + &bus_ve_clk.common, + &bus_dma_clk.common, + &bus_hstimer_clk.common, + &avs_clk.common, + &bus_dbg_clk.common, + &bus_psi_clk.common, + &bus_pwm_clk.common, + &bus_iommu_clk.common, + &dram_clk.common, + &mbus_dma_clk.common, + &mbus_ve_clk.common, + &mbus_ce_clk.common, + &mbus_ts_clk.common, + &mbus_nand_clk.common, + &mbus_g2d_clk.common, + &bus_dram_clk.common, + &nand0_clk.common, + &nand1_clk.common, + &bus_nand_clk.common, + &mmc0_clk.common, + &mmc1_clk.common, + &mmc2_clk.common, + &bus_mmc0_clk.common, + &bus_mmc1_clk.common, + &bus_mmc2_clk.common, + &bus_uart0_clk.common, + &bus_uart1_clk.common, + &bus_uart2_clk.common, + &bus_uart3_clk.common, + &bus_uart4_clk.common, + &bus_uart5_clk.common, + &bus_i2c0_clk.common, + &bus_i2c1_clk.common, + &bus_i2c2_clk.common, + &bus_i2c3_clk.common, + &bus_i2c4_clk.common, + &spi0_clk.common, + &spi1_clk.common, + &bus_spi0_clk.common, + &bus_spi1_clk.common, + &emac_25m_clk.common, + &bus_emac0_clk.common, + &bus_emac1_clk.common, + &ts_clk.common, + &bus_ts_clk.common, + &bus_ths_clk.common, + &spdif_clk.common, + &bus_spdif_clk.common, + &dmic_clk.common, + &bus_dmic_clk.common, + &audio_codec_1x_clk.common, + &audio_codec_4x_clk.common, + &bus_audio_codec_clk.common, + &audio_hub_clk.common, + &bus_audio_hub_clk.common, + &usb_ohci0_clk.common, + &usb_phy0_clk.common, + &usb_ohci1_clk.common, + &usb_phy1_clk.common, + &usb_ohci2_clk.common, + &usb_phy2_clk.common, + &usb_ohci3_clk.common, + &usb_phy3_clk.common, + &bus_ohci0_clk.common, + &bus_ohci1_clk.common, + &bus_ohci2_clk.common, + &bus_ohci3_clk.common, + &bus_ehci0_clk.common, + &bus_ehci1_clk.common, + &bus_ehci2_clk.common, + &bus_ehci3_clk.common, + &bus_otg_clk.common, + &bus_keyadc_clk.common, + &hdmi_clk.common, + &hdmi_slow_clk.common, + &hdmi_cec_clk.common, + &bus_hdmi_clk.common, + &bus_tcon_top_clk.common, + &tcon_tv0_clk.common, + &tcon_tv1_clk.common, + &bus_tcon_tv0_clk.common, + &bus_tcon_tv1_clk.common, + &tve0_clk.common, + &bus_tve_top_clk.common, + &bus_tve0_clk.common, + &hdcp_clk.common, + &bus_hdcp_clk.common, +}; + +static struct clk_hw_onecell_data sun50i_h616_hw_clks = { + .hws = { + [CLK_OSC12M] = &osc12M_clk.hw, + [CLK_PLL_CPUX] = &pll_cpux_clk.common.hw, + [CLK_PLL_DDR0] = &pll_ddr0_clk.common.hw, + [CLK_PLL_DDR1] = &pll_ddr1_clk.common.hw, + [CLK_PLL_PERIPH0] = &pll_periph0_clk.common.hw, + [CLK_PLL_PERIPH0_2X] = &pll_periph0_2x_clk.hw, + [CLK_PLL_PERIPH1] = &pll_periph1_clk.common.hw, + [CLK_PLL_PERIPH1_2X] = &pll_periph1_2x_clk.hw, + [CLK_PLL_GPU] = &pll_gpu_clk.common.hw, + [CLK_PLL_VIDEO0] = &pll_video0_clk.common.hw, + [CLK_PLL_VIDEO0_4X] = &pll_video0_4x_clk.hw, + [CLK_PLL_VIDEO1] = &pll_video1_clk.common.hw, + [CLK_PLL_VIDEO1_4X] = &pll_video1_4x_clk.hw, + [CLK_PLL_VIDEO2] = &pll_video2_clk.common.hw, + [CLK_PLL_VIDEO2_4X] = &pll_video2_4x_clk.hw, + [CLK_PLL_VE] = &pll_ve_clk.common.hw, + [CLK_PLL_DE] = &pll_de_clk.common.hw, + [CLK_PLL_AUDIO_HS] = &pll_audio_hs_clk.common.hw, + [CLK_PLL_AUDIO_1X] = &pll_audio_1x_clk.hw, + [CLK_PLL_AUDIO_2X] = &pll_audio_2x_clk.hw, + [CLK_PLL_AUDIO_4X] = &pll_audio_4x_clk.hw, + [CLK_CPUX] = &cpux_clk.common.hw, + [CLK_AXI] = &axi_clk.common.hw, + [CLK_CPUX_APB] = &cpux_apb_clk.common.hw, + [CLK_PSI_AHB1_AHB2] = &psi_ahb1_ahb2_clk.common.hw, + [CLK_AHB3] = &ahb3_clk.common.hw, + [CLK_APB1] = &apb1_clk.common.hw, + [CLK_APB2] = &apb2_clk.common.hw, + [CLK_MBUS] = &mbus_clk.common.hw, + [CLK_DE] = &de_clk.common.hw, + [CLK_BUS_DE] = &bus_de_clk.common.hw, + [CLK_DEINTERLACE] = &deinterlace_clk.common.hw, + [CLK_BUS_DEINTERLACE] = &bus_deinterlace_clk.common.hw, + [CLK_G2D] = &g2d_clk.common.hw, + [CLK_BUS_G2D] = &bus_g2d_clk.common.hw, + [CLK_GPU0] = &gpu0_clk.common.hw, + [CLK_BUS_GPU] = &bus_gpu_clk.common.hw, + [CLK_GPU1] = &gpu1_clk.common.hw, + [CLK_CE] = &ce_clk.common.hw, + [CLK_BUS_CE] = &bus_ce_clk.common.hw, + [CLK_VE] = &ve_clk.common.hw, + [CLK_BUS_VE] = &bus_ve_clk.common.hw, + [CLK_BUS_DMA] = &bus_dma_clk.common.hw, + [CLK_BUS_HSTIMER] = &bus_hstimer_clk.common.hw, + [CLK_AVS] = &avs_clk.common.hw, + [CLK_BUS_DBG] = &bus_dbg_clk.common.hw, + [CLK_BUS_PSI] = &bus_psi_clk.common.hw, + [CLK_BUS_PWM] = &bus_pwm_clk.common.hw, + [CLK_BUS_IOMMU] = &bus_iommu_clk.common.hw, + [CLK_DRAM] = &dram_clk.common.hw, + [CLK_MBUS_DMA] = &mbus_dma_clk.common.hw, + [CLK_MBUS_VE] = &mbus_ve_clk.common.hw, + [CLK_MBUS_CE] = &mbus_ce_clk.common.hw, + [CLK_MBUS_TS] = &mbus_ts_clk.common.hw, + [CLK_MBUS_NAND] = &mbus_nand_clk.common.hw, + [CLK_MBUS_G2D] = &mbus_g2d_clk.common.hw, + [CLK_BUS_DRAM] = &bus_dram_clk.common.hw, + [CLK_NAND0] = &nand0_clk.common.hw, + [CLK_NAND1] = &nand1_clk.common.hw, + [CLK_BUS_NAND] = &bus_nand_clk.common.hw, + [CLK_MMC0] = &mmc0_clk.common.hw, + [CLK_MMC1] = &mmc1_clk.common.hw, + [CLK_MMC2] = &mmc2_clk.common.hw, + [CLK_BUS_MMC0] = &bus_mmc0_clk.common.hw, + [CLK_BUS_MMC1] = &bus_mmc1_clk.common.hw, + [CLK_BUS_MMC2] = &bus_mmc2_clk.common.hw, + [CLK_BUS_UART0] = &bus_uart0_clk.common.hw, + [CLK_BUS_UART1] = &bus_uart1_clk.common.hw, + [CLK_BUS_UART2] = &bus_uart2_clk.common.hw, + [CLK_BUS_UART3] = &bus_uart3_clk.common.hw, + [CLK_BUS_UART4] = &bus_uart4_clk.common.hw, + [CLK_BUS_UART5] = &bus_uart5_clk.common.hw, + [CLK_BUS_I2C0] = &bus_i2c0_clk.common.hw, + [CLK_BUS_I2C1] = &bus_i2c1_clk.common.hw, + [CLK_BUS_I2C2] = &bus_i2c2_clk.common.hw, + [CLK_BUS_I2C3] = &bus_i2c3_clk.common.hw, + [CLK_BUS_I2C4] = &bus_i2c4_clk.common.hw, + [CLK_SPI0] = &spi0_clk.common.hw, + [CLK_SPI1] = &spi1_clk.common.hw, + [CLK_BUS_SPI0] = &bus_spi0_clk.common.hw, + [CLK_BUS_SPI1] = &bus_spi1_clk.common.hw, + [CLK_EMAC_25M] = &emac_25m_clk.common.hw, + [CLK_BUS_EMAC0] = &bus_emac0_clk.common.hw, + [CLK_BUS_EMAC1] = &bus_emac1_clk.common.hw, + [CLK_TS] = &ts_clk.common.hw, + [CLK_BUS_TS] = &bus_ts_clk.common.hw, + [CLK_BUS_THS] = &bus_ths_clk.common.hw, + [CLK_SPDIF] = &spdif_clk.common.hw, + [CLK_BUS_SPDIF] = &bus_spdif_clk.common.hw, + [CLK_DMIC] = &dmic_clk.common.hw, + [CLK_BUS_DMIC] = &bus_dmic_clk.common.hw, + [CLK_AUDIO_CODEC_1X] = &audio_codec_1x_clk.common.hw, + [CLK_AUDIO_CODEC_4X] = &audio_codec_4x_clk.common.hw, + [CLK_BUS_AUDIO_CODEC] = &bus_audio_codec_clk.common.hw, + [CLK_AUDIO_HUB] = &audio_hub_clk.common.hw, + [CLK_BUS_AUDIO_HUB] = &bus_audio_hub_clk.common.hw, + [CLK_USB_OHCI0] = &usb_ohci0_clk.common.hw, + [CLK_USB_PHY0] = &usb_phy0_clk.common.hw, + [CLK_USB_OHCI1] = &usb_ohci1_clk.common.hw, + [CLK_USB_PHY1] = &usb_phy1_clk.common.hw, + [CLK_USB_OHCI2] = &usb_ohci2_clk.common.hw, + [CLK_USB_PHY2] = &usb_phy2_clk.common.hw, + [CLK_USB_OHCI3] = &usb_ohci3_clk.common.hw, + [CLK_USB_PHY3] = &usb_phy3_clk.common.hw, + [CLK_BUS_OHCI0] = &bus_ohci0_clk.common.hw, + [CLK_BUS_OHCI1] = &bus_ohci1_clk.common.hw, + [CLK_BUS_OHCI2] = &bus_ohci2_clk.common.hw, + [CLK_BUS_OHCI3] = &bus_ohci3_clk.common.hw, + [CLK_BUS_EHCI0] = &bus_ehci0_clk.common.hw, + [CLK_BUS_EHCI1] = &bus_ehci1_clk.common.hw, + [CLK_BUS_EHCI2] = &bus_ehci2_clk.common.hw, + [CLK_BUS_EHCI3] = &bus_ehci3_clk.common.hw, + [CLK_BUS_OTG] = &bus_otg_clk.common.hw, + [CLK_BUS_KEYADC] = &bus_keyadc_clk.common.hw, + [CLK_HDMI] = &hdmi_clk.common.hw, + [CLK_HDMI_SLOW] = &hdmi_slow_clk.common.hw, + [CLK_HDMI_CEC] = &hdmi_cec_clk.common.hw, + [CLK_BUS_HDMI] = &bus_hdmi_clk.common.hw, + [CLK_BUS_TCON_TOP] = &bus_tcon_top_clk.common.hw, + [CLK_TCON_TV0] = &tcon_tv0_clk.common.hw, + [CLK_TCON_TV1] = &tcon_tv1_clk.common.hw, + [CLK_BUS_TCON_TV0] = &bus_tcon_tv0_clk.common.hw, + [CLK_BUS_TCON_TV1] = &bus_tcon_tv1_clk.common.hw, + [CLK_TVE0] = &tve0_clk.common.hw, + [CLK_BUS_TVE_TOP] = &bus_tve_top_clk.common.hw, + [CLK_BUS_TVE0] = &bus_tve0_clk.common.hw, + [CLK_HDCP] = &hdcp_clk.common.hw, + [CLK_BUS_HDCP] = &bus_hdcp_clk.common.hw, + }, + .num = CLK_NUMBER, +}; + +static struct ccu_reset_map sun50i_h616_ccu_resets[] = { + [RST_MBUS] = { 0x540, BIT(30) }, + + [RST_BUS_DE] = { 0x60c, BIT(16) }, + [RST_BUS_DEINTERLACE] = { 0x62c, BIT(16) }, + [RST_BUS_GPU] = { 0x67c, BIT(16) }, + [RST_BUS_CE] = { 0x68c, BIT(16) }, + [RST_BUS_VE] = { 0x69c, BIT(16) }, + [RST_BUS_DMA] = { 0x70c, BIT(16) }, + [RST_BUS_HSTIMER] = { 0x73c, BIT(16) }, + [RST_BUS_DBG] = { 0x78c, BIT(16) }, + [RST_BUS_PSI] = { 0x79c, BIT(16) }, + [RST_BUS_PWM] = { 0x7ac, BIT(16) }, + [RST_BUS_IOMMU] = { 0x7bc, BIT(16) }, + [RST_BUS_DRAM] = { 0x80c, BIT(16) }, + [RST_BUS_NAND] = { 0x82c, BIT(16) }, + [RST_BUS_MMC0] = { 0x84c, BIT(16) }, + [RST_BUS_MMC1] = { 0x84c, BIT(17) }, + [RST_BUS_MMC2] = { 0x84c, BIT(18) }, + [RST_BUS_UART0] = { 0x90c, BIT(16) }, + [RST_BUS_UART1] = { 0x90c, BIT(17) }, + [RST_BUS_UART2] = { 0x90c, BIT(18) }, + [RST_BUS_UART3] = { 0x90c, BIT(19) }, + [RST_BUS_UART4] = { 0x90c, BIT(20) }, + [RST_BUS_UART5] = { 0x90c, BIT(21) }, + [RST_BUS_I2C0] = { 0x91c, BIT(16) }, + [RST_BUS_I2C1] = { 0x91c, BIT(17) }, + [RST_BUS_I2C2] = { 0x91c, BIT(18) }, + [RST_BUS_I2C3] = { 0x91c, BIT(19) }, + [RST_BUS_I2C4] = { 0x91c, BIT(20) }, + [RST_BUS_SPI0] = { 0x96c, BIT(16) }, + [RST_BUS_SPI1] = { 0x96c, BIT(17) }, + [RST_BUS_EMAC0] = { 0x97c, BIT(16) }, + [RST_BUS_EMAC1] = { 0x97c, BIT(17) }, + [RST_BUS_TS] = { 0x9bc, BIT(16) }, + [RST_BUS_THS] = { 0x9fc, BIT(16) }, + [RST_BUS_SPDIF] = { 0xa2c, BIT(16) }, + [RST_BUS_DMIC] = { 0xa4c, BIT(16) }, + [RST_BUS_AUDIO_CODEC] = { 0xa5c, BIT(16) }, + [RST_BUS_AUDIO_HUB] = { 0xa6c, BIT(16) }, + + [RST_USB_PHY0] = { 0xa70, BIT(30) }, + [RST_USB_PHY1] = { 0xa74, BIT(30) }, + [RST_USB_PHY2] = { 0xa78, BIT(30) }, + [RST_USB_PHY3] = { 0xa7c, BIT(30) }, + [RST_BUS_OHCI0] = { 0xa8c, BIT(16) }, + [RST_BUS_OHCI1] = { 0xa8c, BIT(17) }, + [RST_BUS_OHCI2] = { 0xa8c, BIT(18) }, + [RST_BUS_OHCI3] = { 0xa8c, BIT(19) }, + [RST_BUS_EHCI0] = { 0xa8c, BIT(20) }, + [RST_BUS_EHCI1] = { 0xa8c, BIT(21) }, + [RST_BUS_EHCI2] = { 0xa8c, BIT(22) }, + [RST_BUS_EHCI3] = { 0xa8c, BIT(23) }, + [RST_BUS_OTG] = { 0xa8c, BIT(24) }, + [RST_BUS_KEYADC] = { 0xa9c, BIT(16) }, + + [RST_BUS_HDMI] = { 0xb1c, BIT(16) }, + [RST_BUS_HDMI_SUB] = { 0xb1c, BIT(17) }, + [RST_BUS_TCON_TOP] = { 0xb5c, BIT(16) }, + [RST_BUS_TCON_TV0] = { 0xb9c, BIT(16) }, + [RST_BUS_TCON_TV1] = { 0xb9c, BIT(17) }, + [RST_BUS_TVE_TOP] = { 0xbbc, BIT(16) }, + [RST_BUS_TVE0] = { 0xbbc, BIT(17) }, + [RST_BUS_HDCP] = { 0xc4c, BIT(16) }, +}; + +static const struct sunxi_ccu_desc sun50i_h616_ccu_desc = { + .ccu_clks = sun50i_h616_ccu_clks, + .num_ccu_clks = ARRAY_SIZE(sun50i_h616_ccu_clks), + + .hw_clks = &sun50i_h616_hw_clks, + + .resets = sun50i_h616_ccu_resets, + .num_resets = ARRAY_SIZE(sun50i_h616_ccu_resets), +}; + +static const u32 pll_regs[] = { + SUN50I_H616_PLL_CPUX_REG, + SUN50I_H616_PLL_DDR0_REG, + SUN50I_H616_PLL_DDR1_REG, + SUN50I_H616_PLL_PERIPH0_REG, + SUN50I_H616_PLL_PERIPH1_REG, + SUN50I_H616_PLL_GPU_REG, + SUN50I_H616_PLL_VIDEO0_REG, + SUN50I_H616_PLL_VIDEO1_REG, + SUN50I_H616_PLL_VIDEO2_REG, + SUN50I_H616_PLL_VE_REG, + SUN50I_H616_PLL_DE_REG, + SUN50I_H616_PLL_AUDIO_REG, +}; + +static const u32 pll_video_regs[] = { + SUN50I_H616_PLL_VIDEO0_REG, + SUN50I_H616_PLL_VIDEO1_REG, + SUN50I_H616_PLL_VIDEO2_REG, +}; + +static const u32 usb2_clk_regs[] = { + SUN50I_H616_USB0_CLK_REG, + SUN50I_H616_USB1_CLK_REG, + SUN50I_H616_USB2_CLK_REG, + SUN50I_H616_USB3_CLK_REG, +}; + +static void __init sun50i_h616_ccu_setup(struct device_node *node) +{ + void __iomem *reg; + u32 val; + int i; + + reg = of_io_request_and_map(node, 0, of_node_full_name(node)); + if (IS_ERR(reg)) { + pr_err("%pOF: Could not map clock registers\n", node); + return; + } + + /* Enable the lock bits and the output enable bits on all PLLs */ + for (i = 0; i < ARRAY_SIZE(pll_regs); i++) { + val = readl(reg + pll_regs[i]); + val |= BIT(29) | BIT(27); + writel(val, reg + pll_regs[i]); + } + + /* + * Force the output divider of video PLLs to 0. + * + * See the comment before pll-video0 definition for the reason. + */ + for (i = 0; i < ARRAY_SIZE(pll_video_regs); i++) { + val = readl(reg + pll_video_regs[i]); + val &= ~BIT(0); + writel(val, reg + pll_video_regs[i]); + } + + /* + * Force OHCI 12M clock sources to 00 (12MHz divided from 48MHz) + * + * This clock mux is still mysterious, and the code just enforces + * it to have a valid clock parent. + */ + for (i = 0; i < ARRAY_SIZE(usb2_clk_regs); i++) { + val = readl(reg + usb2_clk_regs[i]); + val &= ~GENMASK(25, 24); + writel(val, reg + usb2_clk_regs[i]); + } + + /* + * Force the post-divider of pll-audio to 12 and the output divider + * of it to 2, so 24576000 and 22579200 rates can be set exactly. + */ + val = readl(reg + SUN50I_H616_PLL_AUDIO_REG); + val &= ~(GENMASK(21, 16) | BIT(0)); + writel(val | (11 << 16) | BIT(0), reg + SUN50I_H616_PLL_AUDIO_REG); + + /* + * First clock parent (osc32K) is unusable for CEC. But since there + * is no good way to force parent switch (both run with same frequency), + * just set second clock parent here. + */ + val = readl(reg + SUN50I_H616_HDMI_CEC_CLK_REG); + val |= BIT(24); + writel(val, reg + SUN50I_H616_HDMI_CEC_CLK_REG); + + i = sunxi_ccu_probe(node, reg, &sun50i_h616_ccu_desc); + if (i) + pr_err("%pOF: probing clocks fails: %d\n", node, i); +} + +CLK_OF_DECLARE(sun50i_h616_ccu, "allwinner,sun50i-h616-ccu", + sun50i_h616_ccu_setup); diff --git a/drivers/clk/sunxi-ng/ccu-sun50i-h616.h b/drivers/clk/sunxi-ng/ccu-sun50i-h616.h new file mode 100644 index 000000000000..dd671b413f22 --- /dev/null +++ b/drivers/clk/sunxi-ng/ccu-sun50i-h616.h @@ -0,0 +1,56 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Copyright 2020 Arm Ltd. + */ + +#ifndef _CCU_SUN50I_H616_H_ +#define _CCU_SUN50I_H616_H_ + +#include +#include + +#define CLK_OSC12M 0 +#define CLK_PLL_CPUX 1 +#define CLK_PLL_DDR0 2 +#define CLK_PLL_DDR1 3 + +/* PLL_PERIPH0 exported for PRCM */ + +#define CLK_PLL_PERIPH0_2X 5 +#define CLK_PLL_PERIPH1 6 +#define CLK_PLL_PERIPH1_2X 7 +#define CLK_PLL_GPU 8 +#define CLK_PLL_VIDEO0 9 +#define CLK_PLL_VIDEO0_4X 10 +#define CLK_PLL_VIDEO1 11 +#define CLK_PLL_VIDEO1_4X 12 +#define CLK_PLL_VIDEO2 13 +#define CLK_PLL_VIDEO2_4X 14 +#define CLK_PLL_VE 15 +#define CLK_PLL_DE 16 +#define CLK_PLL_AUDIO_HS 17 +#define CLK_PLL_AUDIO_1X 18 +#define CLK_PLL_AUDIO_2X 19 +#define CLK_PLL_AUDIO_4X 20 + +/* CPUX clock exported for DVFS */ + +#define CLK_AXI 22 +#define CLK_CPUX_APB 23 +#define CLK_PSI_AHB1_AHB2 24 +#define CLK_AHB3 25 + +/* APB1 clock exported for PIO */ + +#define CLK_APB2 27 +#define CLK_MBUS 28 + +/* All module clocks and bus gates are exported except DRAM */ + +#define CLK_DRAM 49 + +#define CLK_BUS_DRAM 56 + +#define CLK_NUMBER (CLK_BUS_HDCP + 1) + +#endif /* _CCU_SUN50I_H616_H_ */ diff --git a/include/dt-bindings/clock/sun50i-h616-ccu.h b/include/dt-bindings/clock/sun50i-h616-ccu.h new file mode 100644 index 000000000000..4fc08b0df2f3 --- /dev/null +++ b/include/dt-bindings/clock/sun50i-h616-ccu.h @@ -0,0 +1,115 @@ +/* SPDX-License-Identifier: (GPL-2.0+ or MIT) */ +/* + * Copyright (C) 2020 Arm Ltd. + */ + +#ifndef _DT_BINDINGS_CLK_SUN50I_H616_H_ +#define _DT_BINDINGS_CLK_SUN50I_H616_H_ + +#define CLK_PLL_PERIPH0 4 + +#define CLK_CPUX 21 + +#define CLK_APB1 26 + +#define CLK_DE 29 +#define CLK_BUS_DE 30 +#define CLK_DEINTERLACE 31 +#define CLK_BUS_DEINTERLACE 32 +#define CLK_G2D 33 +#define CLK_BUS_G2D 34 +#define CLK_GPU0 35 +#define CLK_BUS_GPU 36 +#define CLK_GPU1 37 +#define CLK_CE 38 +#define CLK_BUS_CE 39 +#define CLK_VE 40 +#define CLK_BUS_VE 41 +#define CLK_BUS_DMA 42 +#define CLK_BUS_HSTIMER 43 +#define CLK_AVS 44 +#define CLK_BUS_DBG 45 +#define CLK_BUS_PSI 46 +#define CLK_BUS_PWM 47 +#define CLK_BUS_IOMMU 48 + +#define CLK_MBUS_DMA 50 +#define CLK_MBUS_VE 51 +#define CLK_MBUS_CE 52 +#define CLK_MBUS_TS 53 +#define CLK_MBUS_NAND 54 +#define CLK_MBUS_G2D 55 + +#define CLK_NAND0 57 +#define CLK_NAND1 58 +#define CLK_BUS_NAND 59 +#define CLK_MMC0 60 +#define CLK_MMC1 61 +#define CLK_MMC2 62 +#define CLK_BUS_MMC0 63 +#define CLK_BUS_MMC1 64 +#define CLK_BUS_MMC2 65 +#define CLK_BUS_UART0 66 +#define CLK_BUS_UART1 67 +#define CLK_BUS_UART2 68 +#define CLK_BUS_UART3 69 +#define CLK_BUS_UART4 70 +#define CLK_BUS_UART5 71 +#define CLK_BUS_I2C0 72 +#define CLK_BUS_I2C1 73 +#define CLK_BUS_I2C2 74 +#define CLK_BUS_I2C3 75 +#define CLK_BUS_I2C4 76 +#define CLK_SPI0 77 +#define CLK_SPI1 78 +#define CLK_BUS_SPI0 79 +#define CLK_BUS_SPI1 80 +#define CLK_EMAC_25M 81 +#define CLK_BUS_EMAC0 82 +#define CLK_BUS_EMAC1 83 +#define CLK_TS 84 +#define CLK_BUS_TS 85 +#define CLK_BUS_THS 86 +#define CLK_SPDIF 87 +#define CLK_BUS_SPDIF 88 +#define CLK_DMIC 89 +#define CLK_BUS_DMIC 90 +#define CLK_AUDIO_CODEC_1X 91 +#define CLK_AUDIO_CODEC_4X 92 +#define CLK_BUS_AUDIO_CODEC 93 +#define CLK_AUDIO_HUB 94 +#define CLK_BUS_AUDIO_HUB 95 +#define CLK_USB_OHCI0 96 +#define CLK_USB_PHY0 97 +#define CLK_USB_OHCI1 98 +#define CLK_USB_PHY1 99 +#define CLK_USB_OHCI2 100 +#define CLK_USB_PHY2 101 +#define CLK_USB_OHCI3 102 +#define CLK_USB_PHY3 103 +#define CLK_BUS_OHCI0 104 +#define CLK_BUS_OHCI1 105 +#define CLK_BUS_OHCI2 106 +#define CLK_BUS_OHCI3 107 +#define CLK_BUS_EHCI0 108 +#define CLK_BUS_EHCI1 109 +#define CLK_BUS_EHCI2 110 +#define CLK_BUS_EHCI3 111 +#define CLK_BUS_OTG 112 +#define CLK_BUS_KEYADC 113 +#define CLK_HDMI 114 +#define CLK_HDMI_SLOW 115 +#define CLK_HDMI_CEC 116 +#define CLK_BUS_HDMI 117 +#define CLK_BUS_TCON_TOP 118 +#define CLK_TCON_TV0 119 +#define CLK_TCON_TV1 120 +#define CLK_BUS_TCON_TV0 121 +#define CLK_BUS_TCON_TV1 122 +#define CLK_TVE0 123 +#define CLK_BUS_TVE_TOP 124 +#define CLK_BUS_TVE0 125 +#define CLK_HDCP 126 +#define CLK_BUS_HDCP 127 + +#endif /* _DT_BINDINGS_CLK_SUN50I_H616_H_ */ diff --git a/include/dt-bindings/reset/sun50i-h616-ccu.h b/include/dt-bindings/reset/sun50i-h616-ccu.h new file mode 100644 index 000000000000..cb6285a8d128 --- /dev/null +++ b/include/dt-bindings/reset/sun50i-h616-ccu.h @@ -0,0 +1,70 @@ +/* SPDX-License-Identifier: (GPL-2.0+ or MIT) */ +/* + * Copyright (C) 2020 Arm Ltd. + */ + +#ifndef _DT_BINDINGS_RESET_SUN50I_H616_H_ +#define _DT_BINDINGS_RESET_SUN50I_H616_H_ + +#define RST_MBUS 0 +#define RST_BUS_DE 1 +#define RST_BUS_DEINTERLACE 2 +#define RST_BUS_GPU 3 +#define RST_BUS_CE 4 +#define RST_BUS_VE 5 +#define RST_BUS_DMA 6 +#define RST_BUS_HSTIMER 7 +#define RST_BUS_DBG 8 +#define RST_BUS_PSI 9 +#define RST_BUS_PWM 10 +#define RST_BUS_IOMMU 11 +#define RST_BUS_DRAM 12 +#define RST_BUS_NAND 13 +#define RST_BUS_MMC0 14 +#define RST_BUS_MMC1 15 +#define RST_BUS_MMC2 16 +#define RST_BUS_UART0 17 +#define RST_BUS_UART1 18 +#define RST_BUS_UART2 19 +#define RST_BUS_UART3 20 +#define RST_BUS_UART4 21 +#define RST_BUS_UART5 22 +#define RST_BUS_I2C0 23 +#define RST_BUS_I2C1 24 +#define RST_BUS_I2C2 25 +#define RST_BUS_I2C3 26 +#define RST_BUS_I2C4 27 +#define RST_BUS_SPI0 28 +#define RST_BUS_SPI1 29 +#define RST_BUS_EMAC0 30 +#define RST_BUS_EMAC1 31 +#define RST_BUS_TS 32 +#define RST_BUS_THS 33 +#define RST_BUS_SPDIF 34 +#define RST_BUS_DMIC 35 +#define RST_BUS_AUDIO_CODEC 36 +#define RST_BUS_AUDIO_HUB 37 +#define RST_USB_PHY0 38 +#define RST_USB_PHY1 39 +#define RST_USB_PHY2 40 +#define RST_USB_PHY3 41 +#define RST_BUS_OHCI0 42 +#define RST_BUS_OHCI1 43 +#define RST_BUS_OHCI2 44 +#define RST_BUS_OHCI3 45 +#define RST_BUS_EHCI0 46 +#define RST_BUS_EHCI1 47 +#define RST_BUS_EHCI2 48 +#define RST_BUS_EHCI3 49 +#define RST_BUS_OTG 50 +#define RST_BUS_HDMI 51 +#define RST_BUS_HDMI_SUB 52 +#define RST_BUS_TCON_TOP 53 +#define RST_BUS_TCON_TV0 54 +#define RST_BUS_TCON_TV1 55 +#define RST_BUS_TVE_TOP 56 +#define RST_BUS_TVE0 57 +#define RST_BUS_HDCP 58 +#define RST_BUS_KEYADC 59 + +#endif /* _DT_BINDINGS_RESET_SUN50I_H616_H_ */ -- cgit v1.2.3 From fabb841c5b16721298cfe649b569a4fa40af28a6 Mon Sep 17 00:00:00 2001 From: Heiko Stuebner Date: Fri, 5 Feb 2021 12:04:59 +0100 Subject: clk: rockchip: use clock ids for PCLK_DPHYRX and PCLK_DPHYTX0 on rk3368 Export the clocks via the newly added clock-ids. Signed-off-by: Heiko Stuebner Link: https://lore.kernel.org/r/20210205110502.1850669-2-heiko@sntech.de --- drivers/clk/rockchip/clk-rk3368.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers/clk') diff --git a/drivers/clk/rockchip/clk-rk3368.c b/drivers/clk/rockchip/clk-rk3368.c index 55443349439b..76fb04120089 100644 --- a/drivers/clk/rockchip/clk-rk3368.c +++ b/drivers/clk/rockchip/clk-rk3368.c @@ -818,8 +818,8 @@ static struct rockchip_clk_branch rk3368_clk_branches[] __initdata = { * pclk_vio gates * pclk_vio comes from the exactly same source as hclk_vio */ - GATE(0, "pclk_dphyrx", "hclk_vio", CLK_IGNORE_UNUSED, RK3368_CLKGATE_CON(14), 8, GFLAGS), - GATE(0, "pclk_dphytx", "hclk_vio", CLK_IGNORE_UNUSED, RK3368_CLKGATE_CON(14), 8, GFLAGS), + GATE(PCLK_DPHYRX, "pclk_dphyrx", "hclk_vio", CLK_IGNORE_UNUSED, RK3368_CLKGATE_CON(14), 8, GFLAGS), + GATE(PCLK_DPHYTX0, "pclk_dphytx0", "hclk_vio", CLK_IGNORE_UNUSED, RK3368_CLKGATE_CON(14), 8, GFLAGS), /* pclk_pd_pmu gates */ GATE(PCLK_PMUGRF, "pclk_pmugrf", "pclk_pd_pmu", CLK_IGNORE_UNUSED, RK3368_CLKGATE_CON(23), 5, GFLAGS), -- cgit v1.2.3 From ed2243e0038b8afdd7726d117da34ee4577e11ad Mon Sep 17 00:00:00 2001 From: Heiko Stuebner Date: Fri, 5 Feb 2021 12:05:01 +0100 Subject: clk: rockchip: use clock id for SCLK_VIP_OUT on rk3368 Export the vip-out clock via the newly added clock-id. Signed-off-by: Heiko Stuebner Link: https://lore.kernel.org/r/20210205110502.1850669-4-heiko@sntech.de --- drivers/clk/rockchip/clk-rk3368.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/clk') diff --git a/drivers/clk/rockchip/clk-rk3368.c b/drivers/clk/rockchip/clk-rk3368.c index 76fb04120089..61413be48d1a 100644 --- a/drivers/clk/rockchip/clk-rk3368.c +++ b/drivers/clk/rockchip/clk-rk3368.c @@ -474,7 +474,7 @@ static struct rockchip_clk_branch rk3368_clk_branches[] __initdata = { COMPOSITE_NODIV(0, "vip_src", mux_pll_src_cpll_gpll_p, 0, RK3368_CLKSEL_CON(21), 15, 1, MFLAGS, RK3368_CLKGATE_CON(4), 5, GFLAGS), - COMPOSITE_NOGATE(0, "sclk_vip_out", mux_vip_out_p, 0, + COMPOSITE_NOGATE(SCLK_VIP_OUT, "sclk_vip_out", mux_vip_out_p, 0, RK3368_CLKSEL_CON(21), 14, 1, MFLAGS, 8, 5, DFLAGS), COMPOSITE_NODIV(SCLK_EDP_24M, "sclk_edp_24m", mux_edp_24m_p, 0, -- cgit v1.2.3 From 4bc23b3c83c9a3fc0a7dd8f2f11f451aa92c85cd Mon Sep 17 00:00:00 2001 From: Heiko Stuebner Date: Fri, 5 Feb 2021 12:05:02 +0100 Subject: clk: rockchip: fix DPHY gate locations on rk3368 Fix the register and bits of the DPHY gate locations. Signed-off-by: Heiko Stuebner Link: https://lore.kernel.org/r/20210205110502.1850669-5-heiko@sntech.de --- drivers/clk/rockchip/clk-rk3368.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers/clk') diff --git a/drivers/clk/rockchip/clk-rk3368.c b/drivers/clk/rockchip/clk-rk3368.c index 61413be48d1a..9a0dab9448db 100644 --- a/drivers/clk/rockchip/clk-rk3368.c +++ b/drivers/clk/rockchip/clk-rk3368.c @@ -818,8 +818,8 @@ static struct rockchip_clk_branch rk3368_clk_branches[] __initdata = { * pclk_vio gates * pclk_vio comes from the exactly same source as hclk_vio */ - GATE(PCLK_DPHYRX, "pclk_dphyrx", "hclk_vio", CLK_IGNORE_UNUSED, RK3368_CLKGATE_CON(14), 8, GFLAGS), - GATE(PCLK_DPHYTX0, "pclk_dphytx0", "hclk_vio", CLK_IGNORE_UNUSED, RK3368_CLKGATE_CON(14), 8, GFLAGS), + GATE(PCLK_DPHYRX, "pclk_dphyrx", "hclk_vio", CLK_IGNORE_UNUSED, RK3368_CLKGATE_CON(22), 11, GFLAGS), + GATE(PCLK_DPHYTX0, "pclk_dphytx0", "hclk_vio", CLK_IGNORE_UNUSED, RK3368_CLKGATE_CON(22), 10, GFLAGS), /* pclk_pd_pmu gates */ GATE(PCLK_PMUGRF, "pclk_pmugrf", "pclk_pd_pmu", CLK_IGNORE_UNUSED, RK3368_CLKGATE_CON(23), 5, GFLAGS), -- cgit v1.2.3 From 324a810583ffec3e5c6e7e35bc202904d362e71b Mon Sep 17 00:00:00 2001 From: Alexandru Ardelean Date: Mon, 1 Feb 2021 17:12:42 +0200 Subject: clk: axi-clkgen: replace ARCH dependencies with driver deps The intent is to be able to run this driver to access the IP core in setups where FPGA board is also connected via a PCIe bus. In such cases the number of combinations explodes, where the host system can be an x86 with Xilinx Zynq/ZynqMP/Microblaze board connected via PCIe. Or even a ZynqMP board with a ZynqMP/Zynq/Microblaze connected via PCIe. To accommodate for these cases, this change removes the limitation for this driver to be compilable only on Zynq/Microblaze architectures. And adds dependencies on the mechanisms required by the driver to work (OF and HAS_IOMEM). Signed-off-by: Dragos Bogdan Signed-off-by: Alexandru Ardelean Link: https://lore.kernel.org/r/20210201151245.21845-2-alexandru.ardelean@analog.com Acked-by: Michal Simek Reviewed-by: Moritz Fischer Signed-off-by: Stephen Boyd --- drivers/clk/Kconfig | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'drivers/clk') diff --git a/drivers/clk/Kconfig b/drivers/clk/Kconfig index 85856cff506c..cee1d4e657bc 100644 --- a/drivers/clk/Kconfig +++ b/drivers/clk/Kconfig @@ -247,7 +247,8 @@ config CLK_TWL6040 config COMMON_CLK_AXI_CLKGEN tristate "AXI clkgen driver" - depends on ARCH_ZYNQ || MICROBLAZE || COMPILE_TEST + depends on HAS_IOMEM || COMPILE_TEST + depends on OF help Support for the Analog Devices axi-clkgen pcore clock generator for Xilinx FPGAs. It is commonly used in Analog Devices' reference designs. -- cgit v1.2.3 From da68c30963c04d7badbda53021418df1f043c985 Mon Sep 17 00:00:00 2001 From: Alexandru Ardelean Date: Mon, 1 Feb 2021 17:12:43 +0200 Subject: clk: clk-axiclkgen: add ZynqMP PFD and VCO limits For ZynqMP (Ultrascale) the PFD and VCO limits are different. In order to support these, this change adds a compatible string (i.e. 'adi,zynqmp-axi-clkgen-2.00.a') which will take into account for these limits and apply them. Signed-off-by: Dragos Bogdan Signed-off-by: Mathias Tausen Signed-off-by: Alexandru Ardelean Link: https://lore.kernel.org/r/20210201151245.21845-3-alexandru.ardelean@analog.com Acked-by: Moritz Fischer Signed-off-by: Stephen Boyd --- drivers/clk/clk-axi-clkgen.c | 11 +++++++++++ 1 file changed, 11 insertions(+) (limited to 'drivers/clk') diff --git a/drivers/clk/clk-axi-clkgen.c b/drivers/clk/clk-axi-clkgen.c index ad86e031ba3e..9d1b0fc56c73 100644 --- a/drivers/clk/clk-axi-clkgen.c +++ b/drivers/clk/clk-axi-clkgen.c @@ -108,6 +108,13 @@ static uint32_t axi_clkgen_lookup_lock(unsigned int m) return 0x1f1f00fa; } +static const struct axi_clkgen_limits axi_clkgen_zynqmp_default_limits = { + .fpfd_min = 10000, + .fpfd_max = 450000, + .fvco_min = 800000, + .fvco_max = 1600000, +}; + static const struct axi_clkgen_limits axi_clkgen_zynq_default_limits = { .fpfd_min = 10000, .fpfd_max = 300000, @@ -560,6 +567,10 @@ static int axi_clkgen_remove(struct platform_device *pdev) } static const struct of_device_id axi_clkgen_ids[] = { + { + .compatible = "adi,zynqmp-axi-clkgen-2.00.a", + .data = &axi_clkgen_zynqmp_default_limits, + }, { .compatible = "adi,axi-clkgen-2.00.a", .data = &axi_clkgen_zynq_default_limits, -- cgit v1.2.3 From 6ba7ea7630fb03c1ce01508bdf89f5bb39b38e54 Mon Sep 17 00:00:00 2001 From: Alexandru Ardelean Date: Mon, 1 Feb 2021 17:12:45 +0200 Subject: clk: axi-clkgen: use devm_platform_ioremap_resource() short-hand No major functional change. Noticed while checking the driver code that this could be used. Saves two lines. Signed-off-by: Alexandru Ardelean Link: https://lore.kernel.org/r/20210201151245.21845-5-alexandru.ardelean@analog.com Signed-off-by: Stephen Boyd --- drivers/clk/clk-axi-clkgen.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) (limited to 'drivers/clk') diff --git a/drivers/clk/clk-axi-clkgen.c b/drivers/clk/clk-axi-clkgen.c index 9d1b0fc56c73..ac6ff736ac8f 100644 --- a/drivers/clk/clk-axi-clkgen.c +++ b/drivers/clk/clk-axi-clkgen.c @@ -510,7 +510,6 @@ static int axi_clkgen_probe(struct platform_device *pdev) struct clk_init_data init; const char *parent_names[2]; const char *clk_name; - struct resource *mem; unsigned int i; int ret; @@ -522,8 +521,7 @@ static int axi_clkgen_probe(struct platform_device *pdev) if (!axi_clkgen) return -ENOMEM; - mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); - axi_clkgen->base = devm_ioremap_resource(&pdev->dev, mem); + axi_clkgen->base = devm_platform_ioremap_resource(pdev, 0); if (IS_ERR(axi_clkgen->base)) return PTR_ERR(axi_clkgen->base); -- cgit v1.2.3 From 0225daea08141b1dff681502d5af70b71e8b11ec Mon Sep 17 00:00:00 2001 From: Michael Tretter Date: Thu, 21 Jan 2021 08:16:46 +0100 Subject: clk: divider: fix initialization with parent_hw If a driver registers a divider clock with a parent_hw instead of the parent_name, the parent_hw is ignored and the clock does not have a parent. Fix this by initializing the parents the same way they are initialized for clock gates. Fixes: ff258817137a ("clk: divider: Add support for specifying parents via DT/pointers") Signed-off-by: Michael Tretter Reviewed-by: Stephen Boyd Acked-by: Michal Simek Link: https://lore.kernel.org/r/20210121071659.1226489-3-m.tretter@pengutronix.de Signed-off-by: Stephen Boyd --- drivers/clk/clk-divider.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) (limited to 'drivers/clk') diff --git a/drivers/clk/clk-divider.c b/drivers/clk/clk-divider.c index c499799693cc..344997203f0e 100644 --- a/drivers/clk/clk-divider.c +++ b/drivers/clk/clk-divider.c @@ -494,8 +494,13 @@ struct clk_hw *__clk_hw_register_divider(struct device *dev, else init.ops = &clk_divider_ops; init.flags = flags; - init.parent_names = (parent_name ? &parent_name: NULL); - init.num_parents = (parent_name ? 1 : 0); + init.parent_names = parent_name ? &parent_name : NULL; + init.parent_hws = parent_hw ? &parent_hw : NULL; + init.parent_data = parent_data; + if (parent_name || parent_hw || parent_data) + init.num_parents = 1; + else + init.num_parents = 0; /* struct clk_divider assignments */ div->reg = reg; -- cgit v1.2.3 From a2fe7baa27a46533005bdf3580ca04f0276c175f Mon Sep 17 00:00:00 2001 From: Michael Tretter Date: Thu, 21 Jan 2021 08:16:59 +0100 Subject: clk: xilinx: move xlnx_vcu clock driver from soc The xlnx_vcu driver is actually a clock controller driver which provides clocks that can be used by a driver for the encoder/decoder units. There is no reason to keep this driver in soc. Move the driver to clk. NOTE: The register mapping actually contains registers for AXI performance monitoring, but these are not used by the driver. Signed-off-by: Michael Tretter Acked-by: Michal Simek Link: https://lore.kernel.org/r/20210121071659.1226489-16-m.tretter@pengutronix.de Signed-off-by: Stephen Boyd --- drivers/clk/Kconfig | 1 + drivers/clk/Makefile | 1 + drivers/clk/xilinx/Kconfig | 19 ++ drivers/clk/xilinx/Makefile | 2 + drivers/clk/xilinx/xlnx_vcu.c | 743 ++++++++++++++++++++++++++++++++++++++++++ drivers/soc/xilinx/Kconfig | 17 - drivers/soc/xilinx/Makefile | 1 - drivers/soc/xilinx/xlnx_vcu.c | 743 ------------------------------------------ 8 files changed, 766 insertions(+), 761 deletions(-) create mode 100644 drivers/clk/xilinx/Kconfig create mode 100644 drivers/clk/xilinx/Makefile create mode 100644 drivers/clk/xilinx/xlnx_vcu.c delete mode 100644 drivers/soc/xilinx/xlnx_vcu.c (limited to 'drivers/clk') diff --git a/drivers/clk/Kconfig b/drivers/clk/Kconfig index cee1d4e657bc..7c5dc348c16f 100644 --- a/drivers/clk/Kconfig +++ b/drivers/clk/Kconfig @@ -393,6 +393,7 @@ source "drivers/clk/tegra/Kconfig" source "drivers/clk/ti/Kconfig" source "drivers/clk/uniphier/Kconfig" source "drivers/clk/x86/Kconfig" +source "drivers/clk/xilinx/Kconfig" source "drivers/clk/zynqmp/Kconfig" endif diff --git a/drivers/clk/Makefile b/drivers/clk/Makefile index dbdc590e7de3..074e2233f445 100644 --- a/drivers/clk/Makefile +++ b/drivers/clk/Makefile @@ -122,6 +122,7 @@ obj-y += versatile/ ifeq ($(CONFIG_COMMON_CLK), y) obj-$(CONFIG_X86) += x86/ endif +obj-y += xilinx/ obj-$(CONFIG_ARCH_ZX) += zte/ obj-$(CONFIG_ARCH_ZYNQ) += zynq/ obj-$(CONFIG_COMMON_CLK_ZYNQMP) += zynqmp/ diff --git a/drivers/clk/xilinx/Kconfig b/drivers/clk/xilinx/Kconfig new file mode 100644 index 000000000000..5224114176ed --- /dev/null +++ b/drivers/clk/xilinx/Kconfig @@ -0,0 +1,19 @@ +# SPDX-License-Identifier: GPL-2.0 + +config XILINX_VCU + tristate "Xilinx VCU logicoreIP Init" + depends on HAS_IOMEM && COMMON_CLK + select REGMAP_MMIO + help + Provides the driver to enable and disable the isolation between the + processing system and programmable logic part by using the logicoreIP + register set. This driver also configures the frequency based on the + clock information from the logicoreIP register set. + + If you say yes here you get support for the logicoreIP. + + If unsure, say N. + + To compile this driver as a module, choose M here: the + module will be called xlnx_vcu. + diff --git a/drivers/clk/xilinx/Makefile b/drivers/clk/xilinx/Makefile new file mode 100644 index 000000000000..dee8fd51e303 --- /dev/null +++ b/drivers/clk/xilinx/Makefile @@ -0,0 +1,2 @@ +# SPDX-License-Identifier: GPL-2.0 +obj-$(CONFIG_XILINX_VCU) += xlnx_vcu.o diff --git a/drivers/clk/xilinx/xlnx_vcu.c b/drivers/clk/xilinx/xlnx_vcu.c new file mode 100644 index 000000000000..d66b1315114e --- /dev/null +++ b/drivers/clk/xilinx/xlnx_vcu.c @@ -0,0 +1,743 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Xilinx VCU Init + * + * Copyright (C) 2016 - 2017 Xilinx, Inc. + * + * Contacts Dhaval Shah + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#define VCU_PLL_CTRL 0x24 +#define VCU_PLL_CTRL_RESET BIT(0) +#define VCU_PLL_CTRL_POR_IN BIT(1) +#define VCU_PLL_CTRL_PWR_POR BIT(2) +#define VCU_PLL_CTRL_BYPASS BIT(3) +#define VCU_PLL_CTRL_FBDIV GENMASK(14, 8) +#define VCU_PLL_CTRL_CLKOUTDIV GENMASK(18, 16) + +#define VCU_PLL_CFG 0x28 +#define VCU_PLL_CFG_RES GENMASK(3, 0) +#define VCU_PLL_CFG_CP GENMASK(8, 5) +#define VCU_PLL_CFG_LFHF GENMASK(12, 10) +#define VCU_PLL_CFG_LOCK_CNT GENMASK(22, 13) +#define VCU_PLL_CFG_LOCK_DLY GENMASK(31, 25) +#define VCU_ENC_CORE_CTRL 0x30 +#define VCU_ENC_MCU_CTRL 0x34 +#define VCU_DEC_CORE_CTRL 0x38 +#define VCU_DEC_MCU_CTRL 0x3c +#define VCU_PLL_STATUS 0x60 +#define VCU_PLL_STATUS_LOCK_STATUS BIT(0) + +#define MHZ 1000000 +#define FVCO_MIN (1500U * MHZ) +#define FVCO_MAX (3000U * MHZ) + +/** + * struct xvcu_device - Xilinx VCU init device structure + * @dev: Platform device + * @pll_ref: pll ref clock source + * @aclk: axi clock source + * @logicore_reg_ba: logicore reg base address + * @vcu_slcr_ba: vcu_slcr Register base address + * @pll: handle for the VCU PLL + * @pll_post: handle for the VCU PLL post divider + * @clk_data: clocks provided by the vcu clock provider + */ +struct xvcu_device { + struct device *dev; + struct clk *pll_ref; + struct clk *aclk; + struct regmap *logicore_reg_ba; + void __iomem *vcu_slcr_ba; + struct clk_hw *pll; + struct clk_hw *pll_post; + struct clk_hw_onecell_data *clk_data; +}; + +static struct regmap_config vcu_settings_regmap_config = { + .name = "regmap", + .reg_bits = 32, + .val_bits = 32, + .reg_stride = 4, + .max_register = 0xfff, + .cache_type = REGCACHE_NONE, +}; + +/** + * struct xvcu_pll_cfg - Helper data + * @fbdiv: The integer portion of the feedback divider to the PLL + * @cp: PLL charge pump control + * @res: PLL loop filter resistor control + * @lfhf: PLL loop filter high frequency capacitor control + * @lock_dly: Lock circuit configuration settings for lock windowsize + * @lock_cnt: Lock circuit counter setting + */ +struct xvcu_pll_cfg { + u32 fbdiv; + u32 cp; + u32 res; + u32 lfhf; + u32 lock_dly; + u32 lock_cnt; +}; + +static const struct xvcu_pll_cfg xvcu_pll_cfg[] = { + { 25, 3, 10, 3, 63, 1000 }, + { 26, 3, 10, 3, 63, 1000 }, + { 27, 4, 6, 3, 63, 1000 }, + { 28, 4, 6, 3, 63, 1000 }, + { 29, 4, 6, 3, 63, 1000 }, + { 30, 4, 6, 3, 63, 1000 }, + { 31, 6, 1, 3, 63, 1000 }, + { 32, 6, 1, 3, 63, 1000 }, + { 33, 4, 10, 3, 63, 1000 }, + { 34, 5, 6, 3, 63, 1000 }, + { 35, 5, 6, 3, 63, 1000 }, + { 36, 5, 6, 3, 63, 1000 }, + { 37, 5, 6, 3, 63, 1000 }, + { 38, 5, 6, 3, 63, 975 }, + { 39, 3, 12, 3, 63, 950 }, + { 40, 3, 12, 3, 63, 925 }, + { 41, 3, 12, 3, 63, 900 }, + { 42, 3, 12, 3, 63, 875 }, + { 43, 3, 12, 3, 63, 850 }, + { 44, 3, 12, 3, 63, 850 }, + { 45, 3, 12, 3, 63, 825 }, + { 46, 3, 12, 3, 63, 800 }, + { 47, 3, 12, 3, 63, 775 }, + { 48, 3, 12, 3, 63, 775 }, + { 49, 3, 12, 3, 63, 750 }, + { 50, 3, 12, 3, 63, 750 }, + { 51, 3, 2, 3, 63, 725 }, + { 52, 3, 2, 3, 63, 700 }, + { 53, 3, 2, 3, 63, 700 }, + { 54, 3, 2, 3, 63, 675 }, + { 55, 3, 2, 3, 63, 675 }, + { 56, 3, 2, 3, 63, 650 }, + { 57, 3, 2, 3, 63, 650 }, + { 58, 3, 2, 3, 63, 625 }, + { 59, 3, 2, 3, 63, 625 }, + { 60, 3, 2, 3, 63, 625 }, + { 61, 3, 2, 3, 63, 600 }, + { 62, 3, 2, 3, 63, 600 }, + { 63, 3, 2, 3, 63, 600 }, + { 64, 3, 2, 3, 63, 600 }, + { 65, 3, 2, 3, 63, 600 }, + { 66, 3, 2, 3, 63, 600 }, + { 67, 3, 2, 3, 63, 600 }, + { 68, 3, 2, 3, 63, 600 }, + { 69, 3, 2, 3, 63, 600 }, + { 70, 3, 2, 3, 63, 600 }, + { 71, 3, 2, 3, 63, 600 }, + { 72, 3, 2, 3, 63, 600 }, + { 73, 3, 2, 3, 63, 600 }, + { 74, 3, 2, 3, 63, 600 }, + { 75, 3, 2, 3, 63, 600 }, + { 76, 3, 2, 3, 63, 600 }, + { 77, 3, 2, 3, 63, 600 }, + { 78, 3, 2, 3, 63, 600 }, + { 79, 3, 2, 3, 63, 600 }, + { 80, 3, 2, 3, 63, 600 }, + { 81, 3, 2, 3, 63, 600 }, + { 82, 3, 2, 3, 63, 600 }, + { 83, 4, 2, 3, 63, 600 }, + { 84, 4, 2, 3, 63, 600 }, + { 85, 4, 2, 3, 63, 600 }, + { 86, 4, 2, 3, 63, 600 }, + { 87, 4, 2, 3, 63, 600 }, + { 88, 4, 2, 3, 63, 600 }, + { 89, 4, 2, 3, 63, 600 }, + { 90, 4, 2, 3, 63, 600 }, + { 91, 4, 2, 3, 63, 600 }, + { 92, 4, 2, 3, 63, 600 }, + { 93, 4, 2, 3, 63, 600 }, + { 94, 4, 2, 3, 63, 600 }, + { 95, 4, 2, 3, 63, 600 }, + { 96, 4, 2, 3, 63, 600 }, + { 97, 4, 2, 3, 63, 600 }, + { 98, 4, 2, 3, 63, 600 }, + { 99, 4, 2, 3, 63, 600 }, + { 100, 4, 2, 3, 63, 600 }, + { 101, 4, 2, 3, 63, 600 }, + { 102, 4, 2, 3, 63, 600 }, + { 103, 5, 2, 3, 63, 600 }, + { 104, 5, 2, 3, 63, 600 }, + { 105, 5, 2, 3, 63, 600 }, + { 106, 5, 2, 3, 63, 600 }, + { 107, 3, 4, 3, 63, 600 }, + { 108, 3, 4, 3, 63, 600 }, + { 109, 3, 4, 3, 63, 600 }, + { 110, 3, 4, 3, 63, 600 }, + { 111, 3, 4, 3, 63, 600 }, + { 112, 3, 4, 3, 63, 600 }, + { 113, 3, 4, 3, 63, 600 }, + { 114, 3, 4, 3, 63, 600 }, + { 115, 3, 4, 3, 63, 600 }, + { 116, 3, 4, 3, 63, 600 }, + { 117, 3, 4, 3, 63, 600 }, + { 118, 3, 4, 3, 63, 600 }, + { 119, 3, 4, 3, 63, 600 }, + { 120, 3, 4, 3, 63, 600 }, + { 121, 3, 4, 3, 63, 600 }, + { 122, 3, 4, 3, 63, 600 }, + { 123, 3, 4, 3, 63, 600 }, + { 124, 3, 4, 3, 63, 600 }, + { 125, 3, 4, 3, 63, 600 }, +}; + +/** + * xvcu_read - Read from the VCU register space + * @iomem: vcu reg space base address + * @offset: vcu reg offset from base + * + * Return: Returns 32bit value from VCU register specified + * + */ +static inline u32 xvcu_read(void __iomem *iomem, u32 offset) +{ + return ioread32(iomem + offset); +} + +/** + * xvcu_write - Write to the VCU register space + * @iomem: vcu reg space base address + * @offset: vcu reg offset from base + * @value: Value to write + */ +static inline void xvcu_write(void __iomem *iomem, u32 offset, u32 value) +{ + iowrite32(value, iomem + offset); +} + +#define to_vcu_pll(_hw) container_of(_hw, struct vcu_pll, hw) + +struct vcu_pll { + struct clk_hw hw; + void __iomem *reg_base; + unsigned long fvco_min; + unsigned long fvco_max; +}; + +static int xvcu_pll_wait_for_lock(struct vcu_pll *pll) +{ + void __iomem *base = pll->reg_base; + unsigned long timeout; + u32 lock_status; + + timeout = jiffies + msecs_to_jiffies(2000); + do { + lock_status = xvcu_read(base, VCU_PLL_STATUS); + if (lock_status & VCU_PLL_STATUS_LOCK_STATUS) + return 0; + } while (!time_after(jiffies, timeout)); + + return -ETIMEDOUT; +} + +static struct clk_hw *xvcu_register_pll_post(struct device *dev, + const char *name, + const struct clk_hw *parent_hw, + void __iomem *reg_base) +{ + u32 div; + u32 vcu_pll_ctrl; + + /* + * The output divider of the PLL must be set to 1/2 to meet the + * timing in the design. + */ + vcu_pll_ctrl = xvcu_read(reg_base, VCU_PLL_CTRL); + div = FIELD_GET(VCU_PLL_CTRL_CLKOUTDIV, vcu_pll_ctrl); + if (div != 1) + return ERR_PTR(-EINVAL); + + return clk_hw_register_fixed_factor(dev, "vcu_pll_post", + clk_hw_get_name(parent_hw), + CLK_SET_RATE_PARENT, 1, 2); +} + +static const struct xvcu_pll_cfg *xvcu_find_cfg(int div) +{ + const struct xvcu_pll_cfg *cfg = NULL; + unsigned int i; + + for (i = 0; i < ARRAY_SIZE(xvcu_pll_cfg) - 1; i++) + if (xvcu_pll_cfg[i].fbdiv == div) + cfg = &xvcu_pll_cfg[i]; + + return cfg; +} + +static int xvcu_pll_set_div(struct vcu_pll *pll, int div) +{ + void __iomem *base = pll->reg_base; + const struct xvcu_pll_cfg *cfg = NULL; + u32 vcu_pll_ctrl; + u32 cfg_val; + + cfg = xvcu_find_cfg(div); + if (!cfg) + return -EINVAL; + + vcu_pll_ctrl = xvcu_read(base, VCU_PLL_CTRL); + vcu_pll_ctrl &= ~VCU_PLL_CTRL_FBDIV; + vcu_pll_ctrl |= FIELD_PREP(VCU_PLL_CTRL_FBDIV, cfg->fbdiv); + xvcu_write(base, VCU_PLL_CTRL, vcu_pll_ctrl); + + cfg_val = FIELD_PREP(VCU_PLL_CFG_RES, cfg->res) | + FIELD_PREP(VCU_PLL_CFG_CP, cfg->cp) | + FIELD_PREP(VCU_PLL_CFG_LFHF, cfg->lfhf) | + FIELD_PREP(VCU_PLL_CFG_LOCK_CNT, cfg->lock_cnt) | + FIELD_PREP(VCU_PLL_CFG_LOCK_DLY, cfg->lock_dly); + xvcu_write(base, VCU_PLL_CFG, cfg_val); + + return 0; +} + +static long xvcu_pll_round_rate(struct clk_hw *hw, + unsigned long rate, unsigned long *parent_rate) +{ + struct vcu_pll *pll = to_vcu_pll(hw); + unsigned int feedback_div; + + rate = clamp_t(unsigned long, rate, pll->fvco_min, pll->fvco_max); + + feedback_div = DIV_ROUND_CLOSEST_ULL(rate, *parent_rate); + feedback_div = clamp_t(unsigned int, feedback_div, 25, 125); + + return *parent_rate * feedback_div; +} + +static unsigned long xvcu_pll_recalc_rate(struct clk_hw *hw, + unsigned long parent_rate) +{ + struct vcu_pll *pll = to_vcu_pll(hw); + void __iomem *base = pll->reg_base; + unsigned int div; + u32 vcu_pll_ctrl; + + vcu_pll_ctrl = xvcu_read(base, VCU_PLL_CTRL); + div = FIELD_GET(VCU_PLL_CTRL_FBDIV, vcu_pll_ctrl); + + return div * parent_rate; +} + +static int xvcu_pll_set_rate(struct clk_hw *hw, + unsigned long rate, unsigned long parent_rate) +{ + struct vcu_pll *pll = to_vcu_pll(hw); + + return xvcu_pll_set_div(pll, rate / parent_rate); +} + +static int xvcu_pll_enable(struct clk_hw *hw) +{ + struct vcu_pll *pll = to_vcu_pll(hw); + void __iomem *base = pll->reg_base; + u32 vcu_pll_ctrl; + int ret; + + vcu_pll_ctrl = xvcu_read(base, VCU_PLL_CTRL); + vcu_pll_ctrl |= VCU_PLL_CTRL_BYPASS; + xvcu_write(base, VCU_PLL_CTRL, vcu_pll_ctrl); + + vcu_pll_ctrl = xvcu_read(base, VCU_PLL_CTRL); + vcu_pll_ctrl &= ~VCU_PLL_CTRL_POR_IN; + vcu_pll_ctrl &= ~VCU_PLL_CTRL_PWR_POR; + vcu_pll_ctrl &= ~VCU_PLL_CTRL_RESET; + xvcu_write(base, VCU_PLL_CTRL, vcu_pll_ctrl); + + ret = xvcu_pll_wait_for_lock(pll); + if (ret) { + pr_err("VCU PLL is not locked\n"); + goto err; + } + + vcu_pll_ctrl = xvcu_read(base, VCU_PLL_CTRL); + vcu_pll_ctrl &= ~VCU_PLL_CTRL_BYPASS; + xvcu_write(base, VCU_PLL_CTRL, vcu_pll_ctrl); + +err: + return ret; +} + +static void xvcu_pll_disable(struct clk_hw *hw) +{ + struct vcu_pll *pll = to_vcu_pll(hw); + void __iomem *base = pll->reg_base; + u32 vcu_pll_ctrl; + + vcu_pll_ctrl = xvcu_read(base, VCU_PLL_CTRL); + vcu_pll_ctrl |= VCU_PLL_CTRL_POR_IN; + vcu_pll_ctrl |= VCU_PLL_CTRL_PWR_POR; + vcu_pll_ctrl |= VCU_PLL_CTRL_RESET; + xvcu_write(base, VCU_PLL_CTRL, vcu_pll_ctrl); +} + +static const struct clk_ops vcu_pll_ops = { + .enable = xvcu_pll_enable, + .disable = xvcu_pll_disable, + .round_rate = xvcu_pll_round_rate, + .recalc_rate = xvcu_pll_recalc_rate, + .set_rate = xvcu_pll_set_rate, +}; + +static struct clk_hw *xvcu_register_pll(struct device *dev, + void __iomem *reg_base, + const char *name, const char *parent, + unsigned long flags) +{ + struct vcu_pll *pll; + struct clk_hw *hw; + struct clk_init_data init; + int ret; + + init.name = name; + init.parent_names = &parent; + init.ops = &vcu_pll_ops; + init.num_parents = 1; + init.flags = flags; + + pll = devm_kmalloc(dev, sizeof(*pll), GFP_KERNEL); + if (!pll) + return ERR_PTR(-ENOMEM); + + pll->hw.init = &init; + pll->reg_base = reg_base; + pll->fvco_min = FVCO_MIN; + pll->fvco_max = FVCO_MAX; + + hw = &pll->hw; + ret = devm_clk_hw_register(dev, hw); + if (ret) + return ERR_PTR(ret); + + clk_hw_set_rate_range(hw, pll->fvco_min, pll->fvco_max); + + return hw; +} + +static struct clk_hw *xvcu_clk_hw_register_leaf(struct device *dev, + const char *name, + const struct clk_parent_data *parent_data, + u8 num_parents, + void __iomem *reg) +{ + u8 mux_flags = CLK_MUX_ROUND_CLOSEST; + u8 divider_flags = CLK_DIVIDER_ONE_BASED | CLK_DIVIDER_ALLOW_ZERO | + CLK_DIVIDER_ROUND_CLOSEST; + struct clk_hw *mux = NULL; + struct clk_hw *divider = NULL; + struct clk_hw *gate = NULL; + char *name_mux; + char *name_div; + int err; + /* Protect register shared by clocks */ + spinlock_t *lock; + + lock = devm_kzalloc(dev, sizeof(*lock), GFP_KERNEL); + if (!lock) + return ERR_PTR(-ENOMEM); + spin_lock_init(lock); + + name_mux = devm_kasprintf(dev, GFP_KERNEL, "%s%s", name, "_mux"); + if (!name_mux) + return ERR_PTR(-ENOMEM); + mux = clk_hw_register_mux_parent_data(dev, name_mux, + parent_data, num_parents, + CLK_SET_RATE_PARENT, + reg, 0, 1, mux_flags, lock); + if (IS_ERR(mux)) + return mux; + + name_div = devm_kasprintf(dev, GFP_KERNEL, "%s%s", name, "_div"); + if (!name_div) { + err = -ENOMEM; + goto unregister_mux; + } + divider = clk_hw_register_divider_parent_hw(dev, name_div, mux, + CLK_SET_RATE_PARENT, + reg, 4, 6, divider_flags, + lock); + if (IS_ERR(divider)) { + err = PTR_ERR(divider); + goto unregister_mux; + } + + gate = clk_hw_register_gate_parent_hw(dev, name, divider, + CLK_SET_RATE_PARENT, reg, 12, 0, + lock); + if (IS_ERR(gate)) { + err = PTR_ERR(gate); + goto unregister_divider; + } + + return gate; + +unregister_divider: + clk_hw_unregister_divider(divider); +unregister_mux: + clk_hw_unregister_mux(mux); + + return ERR_PTR(err); +} + +static void xvcu_clk_hw_unregister_leaf(struct clk_hw *hw) +{ + struct clk_hw *gate = hw; + struct clk_hw *divider; + struct clk_hw *mux; + + if (!gate) + return; + + divider = clk_hw_get_parent(gate); + clk_hw_unregister_gate(gate); + if (!divider) + return; + + mux = clk_hw_get_parent(divider); + clk_hw_unregister_mux(mux); + if (!divider) + return; + + clk_hw_unregister_divider(divider); +} + +static int xvcu_register_clock_provider(struct xvcu_device *xvcu) +{ + struct device *dev = xvcu->dev; + struct clk_parent_data parent_data[2] = { 0 }; + struct clk_hw_onecell_data *data; + struct clk_hw **hws; + struct clk_hw *hw; + void __iomem *reg_base = xvcu->vcu_slcr_ba; + + data = devm_kzalloc(dev, struct_size(data, hws, CLK_XVCU_NUM_CLOCKS), GFP_KERNEL); + if (!data) + return -ENOMEM; + data->num = CLK_XVCU_NUM_CLOCKS; + hws = data->hws; + + xvcu->clk_data = data; + + hw = xvcu_register_pll(dev, reg_base, + "vcu_pll", __clk_get_name(xvcu->pll_ref), + CLK_SET_RATE_NO_REPARENT | CLK_OPS_PARENT_ENABLE); + if (IS_ERR(hw)) + return PTR_ERR(hw); + xvcu->pll = hw; + + hw = xvcu_register_pll_post(dev, "vcu_pll_post", xvcu->pll, reg_base); + if (IS_ERR(hw)) + return PTR_ERR(hw); + xvcu->pll_post = hw; + + parent_data[0].fw_name = "pll_ref"; + parent_data[1].hw = xvcu->pll_post; + + hws[CLK_XVCU_ENC_CORE] = + xvcu_clk_hw_register_leaf(dev, "venc_core_clk", + parent_data, + ARRAY_SIZE(parent_data), + reg_base + VCU_ENC_CORE_CTRL); + hws[CLK_XVCU_ENC_MCU] = + xvcu_clk_hw_register_leaf(dev, "venc_mcu_clk", + parent_data, + ARRAY_SIZE(parent_data), + reg_base + VCU_ENC_MCU_CTRL); + hws[CLK_XVCU_DEC_CORE] = + xvcu_clk_hw_register_leaf(dev, "vdec_core_clk", + parent_data, + ARRAY_SIZE(parent_data), + reg_base + VCU_DEC_CORE_CTRL); + hws[CLK_XVCU_DEC_MCU] = + xvcu_clk_hw_register_leaf(dev, "vdec_mcu_clk", + parent_data, + ARRAY_SIZE(parent_data), + reg_base + VCU_DEC_MCU_CTRL); + + return devm_of_clk_add_hw_provider(dev, of_clk_hw_onecell_get, data); +} + +static void xvcu_unregister_clock_provider(struct xvcu_device *xvcu) +{ + struct clk_hw_onecell_data *data = xvcu->clk_data; + struct clk_hw **hws = data->hws; + + if (!IS_ERR_OR_NULL(hws[CLK_XVCU_DEC_MCU])) + xvcu_clk_hw_unregister_leaf(hws[CLK_XVCU_DEC_MCU]); + if (!IS_ERR_OR_NULL(hws[CLK_XVCU_DEC_CORE])) + xvcu_clk_hw_unregister_leaf(hws[CLK_XVCU_DEC_CORE]); + if (!IS_ERR_OR_NULL(hws[CLK_XVCU_ENC_MCU])) + xvcu_clk_hw_unregister_leaf(hws[CLK_XVCU_ENC_MCU]); + if (!IS_ERR_OR_NULL(hws[CLK_XVCU_ENC_CORE])) + xvcu_clk_hw_unregister_leaf(hws[CLK_XVCU_ENC_CORE]); + + clk_hw_unregister_fixed_factor(xvcu->pll_post); +} + +/** + * xvcu_probe - Probe existence of the logicoreIP + * and initialize PLL + * + * @pdev: Pointer to the platform_device structure + * + * Return: Returns 0 on success + * Negative error code otherwise + */ +static int xvcu_probe(struct platform_device *pdev) +{ + struct resource *res; + struct xvcu_device *xvcu; + void __iomem *regs; + int ret; + + xvcu = devm_kzalloc(&pdev->dev, sizeof(*xvcu), GFP_KERNEL); + if (!xvcu) + return -ENOMEM; + + xvcu->dev = &pdev->dev; + res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "vcu_slcr"); + if (!res) { + dev_err(&pdev->dev, "get vcu_slcr memory resource failed.\n"); + return -ENODEV; + } + + xvcu->vcu_slcr_ba = devm_ioremap(&pdev->dev, res->start, + resource_size(res)); + if (!xvcu->vcu_slcr_ba) { + dev_err(&pdev->dev, "vcu_slcr register mapping failed.\n"); + return -ENOMEM; + } + + xvcu->logicore_reg_ba = + syscon_regmap_lookup_by_compatible("xlnx,vcu-settings"); + if (IS_ERR(xvcu->logicore_reg_ba)) { + dev_info(&pdev->dev, + "could not find xlnx,vcu-settings: trying direct register access\n"); + + res = platform_get_resource_byname(pdev, + IORESOURCE_MEM, "logicore"); + if (!res) { + dev_err(&pdev->dev, "get logicore memory resource failed.\n"); + return -ENODEV; + } + + regs = devm_ioremap(&pdev->dev, res->start, resource_size(res)); + if (!regs) { + dev_err(&pdev->dev, "logicore register mapping failed.\n"); + return -ENOMEM; + } + + xvcu->logicore_reg_ba = + devm_regmap_init_mmio(&pdev->dev, regs, + &vcu_settings_regmap_config); + if (IS_ERR(xvcu->logicore_reg_ba)) { + dev_err(&pdev->dev, "failed to init regmap\n"); + return PTR_ERR(xvcu->logicore_reg_ba); + } + } + + xvcu->aclk = devm_clk_get(&pdev->dev, "aclk"); + if (IS_ERR(xvcu->aclk)) { + dev_err(&pdev->dev, "Could not get aclk clock\n"); + return PTR_ERR(xvcu->aclk); + } + + xvcu->pll_ref = devm_clk_get(&pdev->dev, "pll_ref"); + if (IS_ERR(xvcu->pll_ref)) { + dev_err(&pdev->dev, "Could not get pll_ref clock\n"); + return PTR_ERR(xvcu->pll_ref); + } + + ret = clk_prepare_enable(xvcu->aclk); + if (ret) { + dev_err(&pdev->dev, "aclk clock enable failed\n"); + return ret; + } + + /* + * Do the Gasket isolation and put the VCU out of reset + * Bit 0 : Gasket isolation + * Bit 1 : put VCU out of reset + */ + regmap_write(xvcu->logicore_reg_ba, VCU_GASKET_INIT, VCU_GASKET_VALUE); + + ret = xvcu_register_clock_provider(xvcu); + if (ret) { + dev_err(&pdev->dev, "failed to register clock provider\n"); + goto error_clk_provider; + } + + dev_set_drvdata(&pdev->dev, xvcu); + + return 0; + +error_clk_provider: + xvcu_unregister_clock_provider(xvcu); + clk_disable_unprepare(xvcu->aclk); + return ret; +} + +/** + * xvcu_remove - Insert gasket isolation + * and disable the clock + * @pdev: Pointer to the platform_device structure + * + * Return: Returns 0 on success + * Negative error code otherwise + */ +static int xvcu_remove(struct platform_device *pdev) +{ + struct xvcu_device *xvcu; + + xvcu = platform_get_drvdata(pdev); + if (!xvcu) + return -ENODEV; + + xvcu_unregister_clock_provider(xvcu); + + /* Add the Gasket isolation and put the VCU in reset. */ + regmap_write(xvcu->logicore_reg_ba, VCU_GASKET_INIT, 0); + + clk_disable_unprepare(xvcu->aclk); + + return 0; +} + +static const struct of_device_id xvcu_of_id_table[] = { + { .compatible = "xlnx,vcu" }, + { .compatible = "xlnx,vcu-logicoreip-1.0" }, + { } +}; +MODULE_DEVICE_TABLE(of, xvcu_of_id_table); + +static struct platform_driver xvcu_driver = { + .driver = { + .name = "xilinx-vcu", + .of_match_table = xvcu_of_id_table, + }, + .probe = xvcu_probe, + .remove = xvcu_remove, +}; + +module_platform_driver(xvcu_driver); + +MODULE_AUTHOR("Dhaval Shah "); +MODULE_DESCRIPTION("Xilinx VCU init Driver"); +MODULE_LICENSE("GPL v2"); diff --git a/drivers/soc/xilinx/Kconfig b/drivers/soc/xilinx/Kconfig index 9fe703772e5a..53af9115dc31 100644 --- a/drivers/soc/xilinx/Kconfig +++ b/drivers/soc/xilinx/Kconfig @@ -1,23 +1,6 @@ # SPDX-License-Identifier: GPL-2.0 menu "Xilinx SoC drivers" -config XILINX_VCU - tristate "Xilinx VCU logicoreIP Init" - depends on HAS_IOMEM && COMMON_CLK - select REGMAP_MMIO - help - Provides the driver to enable and disable the isolation between the - processing system and programmable logic part by using the logicoreIP - register set. This driver also configures the frequency based on the - clock information from the logicoreIP register set. - - If you say yes here you get support for the logicoreIP. - - If unsure, say N. - - To compile this driver as a module, choose M here: the - module will be called xlnx_vcu. - config ZYNQMP_POWER bool "Enable Xilinx Zynq MPSoC Power Management driver" depends on PM && ZYNQMP_FIRMWARE diff --git a/drivers/soc/xilinx/Makefile b/drivers/soc/xilinx/Makefile index f66bfea5de17..9854e6f6086b 100644 --- a/drivers/soc/xilinx/Makefile +++ b/drivers/soc/xilinx/Makefile @@ -1,4 +1,3 @@ # SPDX-License-Identifier: GPL-2.0 -obj-$(CONFIG_XILINX_VCU) += xlnx_vcu.o obj-$(CONFIG_ZYNQMP_POWER) += zynqmp_power.o obj-$(CONFIG_ZYNQMP_PM_DOMAINS) += zynqmp_pm_domains.o diff --git a/drivers/soc/xilinx/xlnx_vcu.c b/drivers/soc/xilinx/xlnx_vcu.c deleted file mode 100644 index d66b1315114e..000000000000 --- a/drivers/soc/xilinx/xlnx_vcu.c +++ /dev/null @@ -1,743 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 -/* - * Xilinx VCU Init - * - * Copyright (C) 2016 - 2017 Xilinx, Inc. - * - * Contacts Dhaval Shah - */ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include - -#define VCU_PLL_CTRL 0x24 -#define VCU_PLL_CTRL_RESET BIT(0) -#define VCU_PLL_CTRL_POR_IN BIT(1) -#define VCU_PLL_CTRL_PWR_POR BIT(2) -#define VCU_PLL_CTRL_BYPASS BIT(3) -#define VCU_PLL_CTRL_FBDIV GENMASK(14, 8) -#define VCU_PLL_CTRL_CLKOUTDIV GENMASK(18, 16) - -#define VCU_PLL_CFG 0x28 -#define VCU_PLL_CFG_RES GENMASK(3, 0) -#define VCU_PLL_CFG_CP GENMASK(8, 5) -#define VCU_PLL_CFG_LFHF GENMASK(12, 10) -#define VCU_PLL_CFG_LOCK_CNT GENMASK(22, 13) -#define VCU_PLL_CFG_LOCK_DLY GENMASK(31, 25) -#define VCU_ENC_CORE_CTRL 0x30 -#define VCU_ENC_MCU_CTRL 0x34 -#define VCU_DEC_CORE_CTRL 0x38 -#define VCU_DEC_MCU_CTRL 0x3c -#define VCU_PLL_STATUS 0x60 -#define VCU_PLL_STATUS_LOCK_STATUS BIT(0) - -#define MHZ 1000000 -#define FVCO_MIN (1500U * MHZ) -#define FVCO_MAX (3000U * MHZ) - -/** - * struct xvcu_device - Xilinx VCU init device structure - * @dev: Platform device - * @pll_ref: pll ref clock source - * @aclk: axi clock source - * @logicore_reg_ba: logicore reg base address - * @vcu_slcr_ba: vcu_slcr Register base address - * @pll: handle for the VCU PLL - * @pll_post: handle for the VCU PLL post divider - * @clk_data: clocks provided by the vcu clock provider - */ -struct xvcu_device { - struct device *dev; - struct clk *pll_ref; - struct clk *aclk; - struct regmap *logicore_reg_ba; - void __iomem *vcu_slcr_ba; - struct clk_hw *pll; - struct clk_hw *pll_post; - struct clk_hw_onecell_data *clk_data; -}; - -static struct regmap_config vcu_settings_regmap_config = { - .name = "regmap", - .reg_bits = 32, - .val_bits = 32, - .reg_stride = 4, - .max_register = 0xfff, - .cache_type = REGCACHE_NONE, -}; - -/** - * struct xvcu_pll_cfg - Helper data - * @fbdiv: The integer portion of the feedback divider to the PLL - * @cp: PLL charge pump control - * @res: PLL loop filter resistor control - * @lfhf: PLL loop filter high frequency capacitor control - * @lock_dly: Lock circuit configuration settings for lock windowsize - * @lock_cnt: Lock circuit counter setting - */ -struct xvcu_pll_cfg { - u32 fbdiv; - u32 cp; - u32 res; - u32 lfhf; - u32 lock_dly; - u32 lock_cnt; -}; - -static const struct xvcu_pll_cfg xvcu_pll_cfg[] = { - { 25, 3, 10, 3, 63, 1000 }, - { 26, 3, 10, 3, 63, 1000 }, - { 27, 4, 6, 3, 63, 1000 }, - { 28, 4, 6, 3, 63, 1000 }, - { 29, 4, 6, 3, 63, 1000 }, - { 30, 4, 6, 3, 63, 1000 }, - { 31, 6, 1, 3, 63, 1000 }, - { 32, 6, 1, 3, 63, 1000 }, - { 33, 4, 10, 3, 63, 1000 }, - { 34, 5, 6, 3, 63, 1000 }, - { 35, 5, 6, 3, 63, 1000 }, - { 36, 5, 6, 3, 63, 1000 }, - { 37, 5, 6, 3, 63, 1000 }, - { 38, 5, 6, 3, 63, 975 }, - { 39, 3, 12, 3, 63, 950 }, - { 40, 3, 12, 3, 63, 925 }, - { 41, 3, 12, 3, 63, 900 }, - { 42, 3, 12, 3, 63, 875 }, - { 43, 3, 12, 3, 63, 850 }, - { 44, 3, 12, 3, 63, 850 }, - { 45, 3, 12, 3, 63, 825 }, - { 46, 3, 12, 3, 63, 800 }, - { 47, 3, 12, 3, 63, 775 }, - { 48, 3, 12, 3, 63, 775 }, - { 49, 3, 12, 3, 63, 750 }, - { 50, 3, 12, 3, 63, 750 }, - { 51, 3, 2, 3, 63, 725 }, - { 52, 3, 2, 3, 63, 700 }, - { 53, 3, 2, 3, 63, 700 }, - { 54, 3, 2, 3, 63, 675 }, - { 55, 3, 2, 3, 63, 675 }, - { 56, 3, 2, 3, 63, 650 }, - { 57, 3, 2, 3, 63, 650 }, - { 58, 3, 2, 3, 63, 625 }, - { 59, 3, 2, 3, 63, 625 }, - { 60, 3, 2, 3, 63, 625 }, - { 61, 3, 2, 3, 63, 600 }, - { 62, 3, 2, 3, 63, 600 }, - { 63, 3, 2, 3, 63, 600 }, - { 64, 3, 2, 3, 63, 600 }, - { 65, 3, 2, 3, 63, 600 }, - { 66, 3, 2, 3, 63, 600 }, - { 67, 3, 2, 3, 63, 600 }, - { 68, 3, 2, 3, 63, 600 }, - { 69, 3, 2, 3, 63, 600 }, - { 70, 3, 2, 3, 63, 600 }, - { 71, 3, 2, 3, 63, 600 }, - { 72, 3, 2, 3, 63, 600 }, - { 73, 3, 2, 3, 63, 600 }, - { 74, 3, 2, 3, 63, 600 }, - { 75, 3, 2, 3, 63, 600 }, - { 76, 3, 2, 3, 63, 600 }, - { 77, 3, 2, 3, 63, 600 }, - { 78, 3, 2, 3, 63, 600 }, - { 79, 3, 2, 3, 63, 600 }, - { 80, 3, 2, 3, 63, 600 }, - { 81, 3, 2, 3, 63, 600 }, - { 82, 3, 2, 3, 63, 600 }, - { 83, 4, 2, 3, 63, 600 }, - { 84, 4, 2, 3, 63, 600 }, - { 85, 4, 2, 3, 63, 600 }, - { 86, 4, 2, 3, 63, 600 }, - { 87, 4, 2, 3, 63, 600 }, - { 88, 4, 2, 3, 63, 600 }, - { 89, 4, 2, 3, 63, 600 }, - { 90, 4, 2, 3, 63, 600 }, - { 91, 4, 2, 3, 63, 600 }, - { 92, 4, 2, 3, 63, 600 }, - { 93, 4, 2, 3, 63, 600 }, - { 94, 4, 2, 3, 63, 600 }, - { 95, 4, 2, 3, 63, 600 }, - { 96, 4, 2, 3, 63, 600 }, - { 97, 4, 2, 3, 63, 600 }, - { 98, 4, 2, 3, 63, 600 }, - { 99, 4, 2, 3, 63, 600 }, - { 100, 4, 2, 3, 63, 600 }, - { 101, 4, 2, 3, 63, 600 }, - { 102, 4, 2, 3, 63, 600 }, - { 103, 5, 2, 3, 63, 600 }, - { 104, 5, 2, 3, 63, 600 }, - { 105, 5, 2, 3, 63, 600 }, - { 106, 5, 2, 3, 63, 600 }, - { 107, 3, 4, 3, 63, 600 }, - { 108, 3, 4, 3, 63, 600 }, - { 109, 3, 4, 3, 63, 600 }, - { 110, 3, 4, 3, 63, 600 }, - { 111, 3, 4, 3, 63, 600 }, - { 112, 3, 4, 3, 63, 600 }, - { 113, 3, 4, 3, 63, 600 }, - { 114, 3, 4, 3, 63, 600 }, - { 115, 3, 4, 3, 63, 600 }, - { 116, 3, 4, 3, 63, 600 }, - { 117, 3, 4, 3, 63, 600 }, - { 118, 3, 4, 3, 63, 600 }, - { 119, 3, 4, 3, 63, 600 }, - { 120, 3, 4, 3, 63, 600 }, - { 121, 3, 4, 3, 63, 600 }, - { 122, 3, 4, 3, 63, 600 }, - { 123, 3, 4, 3, 63, 600 }, - { 124, 3, 4, 3, 63, 600 }, - { 125, 3, 4, 3, 63, 600 }, -}; - -/** - * xvcu_read - Read from the VCU register space - * @iomem: vcu reg space base address - * @offset: vcu reg offset from base - * - * Return: Returns 32bit value from VCU register specified - * - */ -static inline u32 xvcu_read(void __iomem *iomem, u32 offset) -{ - return ioread32(iomem + offset); -} - -/** - * xvcu_write - Write to the VCU register space - * @iomem: vcu reg space base address - * @offset: vcu reg offset from base - * @value: Value to write - */ -static inline void xvcu_write(void __iomem *iomem, u32 offset, u32 value) -{ - iowrite32(value, iomem + offset); -} - -#define to_vcu_pll(_hw) container_of(_hw, struct vcu_pll, hw) - -struct vcu_pll { - struct clk_hw hw; - void __iomem *reg_base; - unsigned long fvco_min; - unsigned long fvco_max; -}; - -static int xvcu_pll_wait_for_lock(struct vcu_pll *pll) -{ - void __iomem *base = pll->reg_base; - unsigned long timeout; - u32 lock_status; - - timeout = jiffies + msecs_to_jiffies(2000); - do { - lock_status = xvcu_read(base, VCU_PLL_STATUS); - if (lock_status & VCU_PLL_STATUS_LOCK_STATUS) - return 0; - } while (!time_after(jiffies, timeout)); - - return -ETIMEDOUT; -} - -static struct clk_hw *xvcu_register_pll_post(struct device *dev, - const char *name, - const struct clk_hw *parent_hw, - void __iomem *reg_base) -{ - u32 div; - u32 vcu_pll_ctrl; - - /* - * The output divider of the PLL must be set to 1/2 to meet the - * timing in the design. - */ - vcu_pll_ctrl = xvcu_read(reg_base, VCU_PLL_CTRL); - div = FIELD_GET(VCU_PLL_CTRL_CLKOUTDIV, vcu_pll_ctrl); - if (div != 1) - return ERR_PTR(-EINVAL); - - return clk_hw_register_fixed_factor(dev, "vcu_pll_post", - clk_hw_get_name(parent_hw), - CLK_SET_RATE_PARENT, 1, 2); -} - -static const struct xvcu_pll_cfg *xvcu_find_cfg(int div) -{ - const struct xvcu_pll_cfg *cfg = NULL; - unsigned int i; - - for (i = 0; i < ARRAY_SIZE(xvcu_pll_cfg) - 1; i++) - if (xvcu_pll_cfg[i].fbdiv == div) - cfg = &xvcu_pll_cfg[i]; - - return cfg; -} - -static int xvcu_pll_set_div(struct vcu_pll *pll, int div) -{ - void __iomem *base = pll->reg_base; - const struct xvcu_pll_cfg *cfg = NULL; - u32 vcu_pll_ctrl; - u32 cfg_val; - - cfg = xvcu_find_cfg(div); - if (!cfg) - return -EINVAL; - - vcu_pll_ctrl = xvcu_read(base, VCU_PLL_CTRL); - vcu_pll_ctrl &= ~VCU_PLL_CTRL_FBDIV; - vcu_pll_ctrl |= FIELD_PREP(VCU_PLL_CTRL_FBDIV, cfg->fbdiv); - xvcu_write(base, VCU_PLL_CTRL, vcu_pll_ctrl); - - cfg_val = FIELD_PREP(VCU_PLL_CFG_RES, cfg->res) | - FIELD_PREP(VCU_PLL_CFG_CP, cfg->cp) | - FIELD_PREP(VCU_PLL_CFG_LFHF, cfg->lfhf) | - FIELD_PREP(VCU_PLL_CFG_LOCK_CNT, cfg->lock_cnt) | - FIELD_PREP(VCU_PLL_CFG_LOCK_DLY, cfg->lock_dly); - xvcu_write(base, VCU_PLL_CFG, cfg_val); - - return 0; -} - -static long xvcu_pll_round_rate(struct clk_hw *hw, - unsigned long rate, unsigned long *parent_rate) -{ - struct vcu_pll *pll = to_vcu_pll(hw); - unsigned int feedback_div; - - rate = clamp_t(unsigned long, rate, pll->fvco_min, pll->fvco_max); - - feedback_div = DIV_ROUND_CLOSEST_ULL(rate, *parent_rate); - feedback_div = clamp_t(unsigned int, feedback_div, 25, 125); - - return *parent_rate * feedback_div; -} - -static unsigned long xvcu_pll_recalc_rate(struct clk_hw *hw, - unsigned long parent_rate) -{ - struct vcu_pll *pll = to_vcu_pll(hw); - void __iomem *base = pll->reg_base; - unsigned int div; - u32 vcu_pll_ctrl; - - vcu_pll_ctrl = xvcu_read(base, VCU_PLL_CTRL); - div = FIELD_GET(VCU_PLL_CTRL_FBDIV, vcu_pll_ctrl); - - return div * parent_rate; -} - -static int xvcu_pll_set_rate(struct clk_hw *hw, - unsigned long rate, unsigned long parent_rate) -{ - struct vcu_pll *pll = to_vcu_pll(hw); - - return xvcu_pll_set_div(pll, rate / parent_rate); -} - -static int xvcu_pll_enable(struct clk_hw *hw) -{ - struct vcu_pll *pll = to_vcu_pll(hw); - void __iomem *base = pll->reg_base; - u32 vcu_pll_ctrl; - int ret; - - vcu_pll_ctrl = xvcu_read(base, VCU_PLL_CTRL); - vcu_pll_ctrl |= VCU_PLL_CTRL_BYPASS; - xvcu_write(base, VCU_PLL_CTRL, vcu_pll_ctrl); - - vcu_pll_ctrl = xvcu_read(base, VCU_PLL_CTRL); - vcu_pll_ctrl &= ~VCU_PLL_CTRL_POR_IN; - vcu_pll_ctrl &= ~VCU_PLL_CTRL_PWR_POR; - vcu_pll_ctrl &= ~VCU_PLL_CTRL_RESET; - xvcu_write(base, VCU_PLL_CTRL, vcu_pll_ctrl); - - ret = xvcu_pll_wait_for_lock(pll); - if (ret) { - pr_err("VCU PLL is not locked\n"); - goto err; - } - - vcu_pll_ctrl = xvcu_read(base, VCU_PLL_CTRL); - vcu_pll_ctrl &= ~VCU_PLL_CTRL_BYPASS; - xvcu_write(base, VCU_PLL_CTRL, vcu_pll_ctrl); - -err: - return ret; -} - -static void xvcu_pll_disable(struct clk_hw *hw) -{ - struct vcu_pll *pll = to_vcu_pll(hw); - void __iomem *base = pll->reg_base; - u32 vcu_pll_ctrl; - - vcu_pll_ctrl = xvcu_read(base, VCU_PLL_CTRL); - vcu_pll_ctrl |= VCU_PLL_CTRL_POR_IN; - vcu_pll_ctrl |= VCU_PLL_CTRL_PWR_POR; - vcu_pll_ctrl |= VCU_PLL_CTRL_RESET; - xvcu_write(base, VCU_PLL_CTRL, vcu_pll_ctrl); -} - -static const struct clk_ops vcu_pll_ops = { - .enable = xvcu_pll_enable, - .disable = xvcu_pll_disable, - .round_rate = xvcu_pll_round_rate, - .recalc_rate = xvcu_pll_recalc_rate, - .set_rate = xvcu_pll_set_rate, -}; - -static struct clk_hw *xvcu_register_pll(struct device *dev, - void __iomem *reg_base, - const char *name, const char *parent, - unsigned long flags) -{ - struct vcu_pll *pll; - struct clk_hw *hw; - struct clk_init_data init; - int ret; - - init.name = name; - init.parent_names = &parent; - init.ops = &vcu_pll_ops; - init.num_parents = 1; - init.flags = flags; - - pll = devm_kmalloc(dev, sizeof(*pll), GFP_KERNEL); - if (!pll) - return ERR_PTR(-ENOMEM); - - pll->hw.init = &init; - pll->reg_base = reg_base; - pll->fvco_min = FVCO_MIN; - pll->fvco_max = FVCO_MAX; - - hw = &pll->hw; - ret = devm_clk_hw_register(dev, hw); - if (ret) - return ERR_PTR(ret); - - clk_hw_set_rate_range(hw, pll->fvco_min, pll->fvco_max); - - return hw; -} - -static struct clk_hw *xvcu_clk_hw_register_leaf(struct device *dev, - const char *name, - const struct clk_parent_data *parent_data, - u8 num_parents, - void __iomem *reg) -{ - u8 mux_flags = CLK_MUX_ROUND_CLOSEST; - u8 divider_flags = CLK_DIVIDER_ONE_BASED | CLK_DIVIDER_ALLOW_ZERO | - CLK_DIVIDER_ROUND_CLOSEST; - struct clk_hw *mux = NULL; - struct clk_hw *divider = NULL; - struct clk_hw *gate = NULL; - char *name_mux; - char *name_div; - int err; - /* Protect register shared by clocks */ - spinlock_t *lock; - - lock = devm_kzalloc(dev, sizeof(*lock), GFP_KERNEL); - if (!lock) - return ERR_PTR(-ENOMEM); - spin_lock_init(lock); - - name_mux = devm_kasprintf(dev, GFP_KERNEL, "%s%s", name, "_mux"); - if (!name_mux) - return ERR_PTR(-ENOMEM); - mux = clk_hw_register_mux_parent_data(dev, name_mux, - parent_data, num_parents, - CLK_SET_RATE_PARENT, - reg, 0, 1, mux_flags, lock); - if (IS_ERR(mux)) - return mux; - - name_div = devm_kasprintf(dev, GFP_KERNEL, "%s%s", name, "_div"); - if (!name_div) { - err = -ENOMEM; - goto unregister_mux; - } - divider = clk_hw_register_divider_parent_hw(dev, name_div, mux, - CLK_SET_RATE_PARENT, - reg, 4, 6, divider_flags, - lock); - if (IS_ERR(divider)) { - err = PTR_ERR(divider); - goto unregister_mux; - } - - gate = clk_hw_register_gate_parent_hw(dev, name, divider, - CLK_SET_RATE_PARENT, reg, 12, 0, - lock); - if (IS_ERR(gate)) { - err = PTR_ERR(gate); - goto unregister_divider; - } - - return gate; - -unregister_divider: - clk_hw_unregister_divider(divider); -unregister_mux: - clk_hw_unregister_mux(mux); - - return ERR_PTR(err); -} - -static void xvcu_clk_hw_unregister_leaf(struct clk_hw *hw) -{ - struct clk_hw *gate = hw; - struct clk_hw *divider; - struct clk_hw *mux; - - if (!gate) - return; - - divider = clk_hw_get_parent(gate); - clk_hw_unregister_gate(gate); - if (!divider) - return; - - mux = clk_hw_get_parent(divider); - clk_hw_unregister_mux(mux); - if (!divider) - return; - - clk_hw_unregister_divider(divider); -} - -static int xvcu_register_clock_provider(struct xvcu_device *xvcu) -{ - struct device *dev = xvcu->dev; - struct clk_parent_data parent_data[2] = { 0 }; - struct clk_hw_onecell_data *data; - struct clk_hw **hws; - struct clk_hw *hw; - void __iomem *reg_base = xvcu->vcu_slcr_ba; - - data = devm_kzalloc(dev, struct_size(data, hws, CLK_XVCU_NUM_CLOCKS), GFP_KERNEL); - if (!data) - return -ENOMEM; - data->num = CLK_XVCU_NUM_CLOCKS; - hws = data->hws; - - xvcu->clk_data = data; - - hw = xvcu_register_pll(dev, reg_base, - "vcu_pll", __clk_get_name(xvcu->pll_ref), - CLK_SET_RATE_NO_REPARENT | CLK_OPS_PARENT_ENABLE); - if (IS_ERR(hw)) - return PTR_ERR(hw); - xvcu->pll = hw; - - hw = xvcu_register_pll_post(dev, "vcu_pll_post", xvcu->pll, reg_base); - if (IS_ERR(hw)) - return PTR_ERR(hw); - xvcu->pll_post = hw; - - parent_data[0].fw_name = "pll_ref"; - parent_data[1].hw = xvcu->pll_post; - - hws[CLK_XVCU_ENC_CORE] = - xvcu_clk_hw_register_leaf(dev, "venc_core_clk", - parent_data, - ARRAY_SIZE(parent_data), - reg_base + VCU_ENC_CORE_CTRL); - hws[CLK_XVCU_ENC_MCU] = - xvcu_clk_hw_register_leaf(dev, "venc_mcu_clk", - parent_data, - ARRAY_SIZE(parent_data), - reg_base + VCU_ENC_MCU_CTRL); - hws[CLK_XVCU_DEC_CORE] = - xvcu_clk_hw_register_leaf(dev, "vdec_core_clk", - parent_data, - ARRAY_SIZE(parent_data), - reg_base + VCU_DEC_CORE_CTRL); - hws[CLK_XVCU_DEC_MCU] = - xvcu_clk_hw_register_leaf(dev, "vdec_mcu_clk", - parent_data, - ARRAY_SIZE(parent_data), - reg_base + VCU_DEC_MCU_CTRL); - - return devm_of_clk_add_hw_provider(dev, of_clk_hw_onecell_get, data); -} - -static void xvcu_unregister_clock_provider(struct xvcu_device *xvcu) -{ - struct clk_hw_onecell_data *data = xvcu->clk_data; - struct clk_hw **hws = data->hws; - - if (!IS_ERR_OR_NULL(hws[CLK_XVCU_DEC_MCU])) - xvcu_clk_hw_unregister_leaf(hws[CLK_XVCU_DEC_MCU]); - if (!IS_ERR_OR_NULL(hws[CLK_XVCU_DEC_CORE])) - xvcu_clk_hw_unregister_leaf(hws[CLK_XVCU_DEC_CORE]); - if (!IS_ERR_OR_NULL(hws[CLK_XVCU_ENC_MCU])) - xvcu_clk_hw_unregister_leaf(hws[CLK_XVCU_ENC_MCU]); - if (!IS_ERR_OR_NULL(hws[CLK_XVCU_ENC_CORE])) - xvcu_clk_hw_unregister_leaf(hws[CLK_XVCU_ENC_CORE]); - - clk_hw_unregister_fixed_factor(xvcu->pll_post); -} - -/** - * xvcu_probe - Probe existence of the logicoreIP - * and initialize PLL - * - * @pdev: Pointer to the platform_device structure - * - * Return: Returns 0 on success - * Negative error code otherwise - */ -static int xvcu_probe(struct platform_device *pdev) -{ - struct resource *res; - struct xvcu_device *xvcu; - void __iomem *regs; - int ret; - - xvcu = devm_kzalloc(&pdev->dev, sizeof(*xvcu), GFP_KERNEL); - if (!xvcu) - return -ENOMEM; - - xvcu->dev = &pdev->dev; - res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "vcu_slcr"); - if (!res) { - dev_err(&pdev->dev, "get vcu_slcr memory resource failed.\n"); - return -ENODEV; - } - - xvcu->vcu_slcr_ba = devm_ioremap(&pdev->dev, res->start, - resource_size(res)); - if (!xvcu->vcu_slcr_ba) { - dev_err(&pdev->dev, "vcu_slcr register mapping failed.\n"); - return -ENOMEM; - } - - xvcu->logicore_reg_ba = - syscon_regmap_lookup_by_compatible("xlnx,vcu-settings"); - if (IS_ERR(xvcu->logicore_reg_ba)) { - dev_info(&pdev->dev, - "could not find xlnx,vcu-settings: trying direct register access\n"); - - res = platform_get_resource_byname(pdev, - IORESOURCE_MEM, "logicore"); - if (!res) { - dev_err(&pdev->dev, "get logicore memory resource failed.\n"); - return -ENODEV; - } - - regs = devm_ioremap(&pdev->dev, res->start, resource_size(res)); - if (!regs) { - dev_err(&pdev->dev, "logicore register mapping failed.\n"); - return -ENOMEM; - } - - xvcu->logicore_reg_ba = - devm_regmap_init_mmio(&pdev->dev, regs, - &vcu_settings_regmap_config); - if (IS_ERR(xvcu->logicore_reg_ba)) { - dev_err(&pdev->dev, "failed to init regmap\n"); - return PTR_ERR(xvcu->logicore_reg_ba); - } - } - - xvcu->aclk = devm_clk_get(&pdev->dev, "aclk"); - if (IS_ERR(xvcu->aclk)) { - dev_err(&pdev->dev, "Could not get aclk clock\n"); - return PTR_ERR(xvcu->aclk); - } - - xvcu->pll_ref = devm_clk_get(&pdev->dev, "pll_ref"); - if (IS_ERR(xvcu->pll_ref)) { - dev_err(&pdev->dev, "Could not get pll_ref clock\n"); - return PTR_ERR(xvcu->pll_ref); - } - - ret = clk_prepare_enable(xvcu->aclk); - if (ret) { - dev_err(&pdev->dev, "aclk clock enable failed\n"); - return ret; - } - - /* - * Do the Gasket isolation and put the VCU out of reset - * Bit 0 : Gasket isolation - * Bit 1 : put VCU out of reset - */ - regmap_write(xvcu->logicore_reg_ba, VCU_GASKET_INIT, VCU_GASKET_VALUE); - - ret = xvcu_register_clock_provider(xvcu); - if (ret) { - dev_err(&pdev->dev, "failed to register clock provider\n"); - goto error_clk_provider; - } - - dev_set_drvdata(&pdev->dev, xvcu); - - return 0; - -error_clk_provider: - xvcu_unregister_clock_provider(xvcu); - clk_disable_unprepare(xvcu->aclk); - return ret; -} - -/** - * xvcu_remove - Insert gasket isolation - * and disable the clock - * @pdev: Pointer to the platform_device structure - * - * Return: Returns 0 on success - * Negative error code otherwise - */ -static int xvcu_remove(struct platform_device *pdev) -{ - struct xvcu_device *xvcu; - - xvcu = platform_get_drvdata(pdev); - if (!xvcu) - return -ENODEV; - - xvcu_unregister_clock_provider(xvcu); - - /* Add the Gasket isolation and put the VCU in reset. */ - regmap_write(xvcu->logicore_reg_ba, VCU_GASKET_INIT, 0); - - clk_disable_unprepare(xvcu->aclk); - - return 0; -} - -static const struct of_device_id xvcu_of_id_table[] = { - { .compatible = "xlnx,vcu" }, - { .compatible = "xlnx,vcu-logicoreip-1.0" }, - { } -}; -MODULE_DEVICE_TABLE(of, xvcu_of_id_table); - -static struct platform_driver xvcu_driver = { - .driver = { - .name = "xilinx-vcu", - .of_match_table = xvcu_of_id_table, - }, - .probe = xvcu_probe, - .remove = xvcu_remove, -}; - -module_platform_driver(xvcu_driver); - -MODULE_AUTHOR("Dhaval Shah "); -MODULE_DESCRIPTION("Xilinx VCU init Driver"); -MODULE_LICENSE("GPL v2"); -- cgit v1.2.3