From 49b2b0a2b6782609a9977095d9c80391de463044 Mon Sep 17 00:00:00 2001 From: Samuel Holland Date: Mon, 9 May 2022 00:29:31 -0500 Subject: clk: sunxi: Store the array sizes in the CCU descriptor The reset array size is currently used for bounds checking in the reset driver. The same bounds check should really be done in the clock driver. Currently, the array size is provided to the reset driver separately from the CCU descriptor, which is a bit strange. Let's do this the usual way, with the array sizes next to the arrays themselves. Signed-off-by: Samuel Holland Reviewed-by: Andre Przywara [Andre: add F1C100s support] Signed-off-by: Andre Przywara --- drivers/clk/sunxi/clk_a10.c | 2 ++ drivers/clk/sunxi/clk_a10s.c | 2 ++ drivers/clk/sunxi/clk_a23.c | 2 ++ drivers/clk/sunxi/clk_a31.c | 2 ++ drivers/clk/sunxi/clk_a31_r.c | 2 ++ drivers/clk/sunxi/clk_a64.c | 2 ++ drivers/clk/sunxi/clk_a80.c | 4 ++++ drivers/clk/sunxi/clk_a83t.c | 2 ++ drivers/clk/sunxi/clk_f1c100s.c | 2 ++ drivers/clk/sunxi/clk_h3.c | 2 ++ drivers/clk/sunxi/clk_h6.c | 2 ++ drivers/clk/sunxi/clk_h616.c | 2 ++ drivers/clk/sunxi/clk_h6_r.c | 2 ++ drivers/clk/sunxi/clk_r40.c | 2 ++ drivers/clk/sunxi/clk_v3s.c | 2 ++ 15 files changed, 32 insertions(+) (limited to 'drivers') diff --git a/drivers/clk/sunxi/clk_a10.c b/drivers/clk/sunxi/clk_a10.c index db92848..b3cca2a 100644 --- a/drivers/clk/sunxi/clk_a10.c +++ b/drivers/clk/sunxi/clk_a10.c @@ -67,6 +67,8 @@ static struct ccu_reset a10_resets[] = { static const struct ccu_desc a10_ccu_desc = { .gates = a10_gates, .resets = a10_resets, + .num_gates = ARRAY_SIZE(a10_gates), + .num_resets = ARRAY_SIZE(a10_resets), }; static int a10_clk_bind(struct udevice *dev) diff --git a/drivers/clk/sunxi/clk_a10s.c b/drivers/clk/sunxi/clk_a10s.c index 0c6564e..0e75c30 100644 --- a/drivers/clk/sunxi/clk_a10s.c +++ b/drivers/clk/sunxi/clk_a10s.c @@ -52,6 +52,8 @@ static struct ccu_reset a10s_resets[] = { static const struct ccu_desc a10s_ccu_desc = { .gates = a10s_gates, .resets = a10s_resets, + .num_gates = ARRAY_SIZE(a10s_gates), + .num_resets = ARRAY_SIZE(a10s_resets), }; static int a10s_clk_bind(struct udevice *dev) diff --git a/drivers/clk/sunxi/clk_a23.c b/drivers/clk/sunxi/clk_a23.c index 0280fb5..a9c77ba 100644 --- a/drivers/clk/sunxi/clk_a23.c +++ b/drivers/clk/sunxi/clk_a23.c @@ -71,6 +71,8 @@ static struct ccu_reset a23_resets[] = { static const struct ccu_desc a23_ccu_desc = { .gates = a23_gates, .resets = a23_resets, + .num_gates = ARRAY_SIZE(a23_gates), + .num_resets = ARRAY_SIZE(a23_resets), }; static int a23_clk_bind(struct udevice *dev) diff --git a/drivers/clk/sunxi/clk_a31.c b/drivers/clk/sunxi/clk_a31.c index 26d25f3..69df4e0 100644 --- a/drivers/clk/sunxi/clk_a31.c +++ b/drivers/clk/sunxi/clk_a31.c @@ -92,6 +92,8 @@ static struct ccu_reset a31_resets[] = { static const struct ccu_desc a31_ccu_desc = { .gates = a31_gates, .resets = a31_resets, + .num_gates = ARRAY_SIZE(a31_gates), + .num_resets = ARRAY_SIZE(a31_resets), }; static int a31_clk_bind(struct udevice *dev) diff --git a/drivers/clk/sunxi/clk_a31_r.c b/drivers/clk/sunxi/clk_a31_r.c index 1f08ea9..7bf1c45 100644 --- a/drivers/clk/sunxi/clk_a31_r.c +++ b/drivers/clk/sunxi/clk_a31_r.c @@ -31,6 +31,8 @@ static struct ccu_reset a31_r_resets[] = { static const struct ccu_desc a31_r_ccu_desc = { .gates = a31_r_gates, .resets = a31_r_resets, + .num_gates = ARRAY_SIZE(a31_r_gates), + .num_resets = ARRAY_SIZE(a31_r_resets), }; static int a31_r_clk_bind(struct udevice *dev) diff --git a/drivers/clk/sunxi/clk_a64.c b/drivers/clk/sunxi/clk_a64.c index cbb9168..e24d5c5 100644 --- a/drivers/clk/sunxi/clk_a64.c +++ b/drivers/clk/sunxi/clk_a64.c @@ -80,6 +80,8 @@ static const struct ccu_reset a64_resets[] = { static const struct ccu_desc a64_ccu_desc = { .gates = a64_gates, .resets = a64_resets, + .num_gates = ARRAY_SIZE(a64_gates), + .num_resets = ARRAY_SIZE(a64_resets), }; static int a64_clk_bind(struct udevice *dev) diff --git a/drivers/clk/sunxi/clk_a80.c b/drivers/clk/sunxi/clk_a80.c index 1ee1f99..adedcba 100644 --- a/drivers/clk/sunxi/clk_a80.c +++ b/drivers/clk/sunxi/clk_a80.c @@ -77,11 +77,15 @@ static const struct ccu_reset a80_mmc_resets[] = { static const struct ccu_desc a80_ccu_desc = { .gates = a80_gates, .resets = a80_resets, + .num_gates = ARRAY_SIZE(a80_gates), + .num_resets = ARRAY_SIZE(a80_resets), }; static const struct ccu_desc a80_mmc_clk_desc = { .gates = a80_mmc_gates, .resets = a80_mmc_resets, + .num_gates = ARRAY_SIZE(a80_mmc_gates), + .num_resets = ARRAY_SIZE(a80_mmc_resets), }; static int a80_clk_bind(struct udevice *dev) diff --git a/drivers/clk/sunxi/clk_a83t.c b/drivers/clk/sunxi/clk_a83t.c index 4b57434..4a0659a 100644 --- a/drivers/clk/sunxi/clk_a83t.c +++ b/drivers/clk/sunxi/clk_a83t.c @@ -75,6 +75,8 @@ static struct ccu_reset a83t_resets[] = { static const struct ccu_desc a83t_ccu_desc = { .gates = a83t_gates, .resets = a83t_resets, + .num_gates = ARRAY_SIZE(a83t_gates), + .num_resets = ARRAY_SIZE(a83t_resets), }; static int a83t_clk_bind(struct udevice *dev) diff --git a/drivers/clk/sunxi/clk_f1c100s.c b/drivers/clk/sunxi/clk_f1c100s.c index 72cf8a6..cb0159e 100644 --- a/drivers/clk/sunxi/clk_f1c100s.c +++ b/drivers/clk/sunxi/clk_f1c100s.c @@ -50,6 +50,8 @@ static struct ccu_reset f1c100s_resets[] = { static const struct ccu_desc f1c100s_ccu_desc = { .gates = f1c100s_gates, .resets = f1c100s_resets, + .num_gates = ARRAY_SIZE(f1c100s_gates), + .num_resets = ARRAY_SIZE(f1c100s_resets), }; static int f1c100s_clk_bind(struct udevice *dev) diff --git a/drivers/clk/sunxi/clk_h3.c b/drivers/clk/sunxi/clk_h3.c index 08a830b..d69cb04 100644 --- a/drivers/clk/sunxi/clk_h3.c +++ b/drivers/clk/sunxi/clk_h3.c @@ -93,6 +93,8 @@ static struct ccu_reset h3_resets[] = { static const struct ccu_desc h3_ccu_desc = { .gates = h3_gates, .resets = h3_resets, + .num_gates = ARRAY_SIZE(h3_gates), + .num_resets = ARRAY_SIZE(h3_resets), }; static int h3_clk_bind(struct udevice *dev) diff --git a/drivers/clk/sunxi/clk_h6.c b/drivers/clk/sunxi/clk_h6.c index b320234..f8d2379 100644 --- a/drivers/clk/sunxi/clk_h6.c +++ b/drivers/clk/sunxi/clk_h6.c @@ -94,6 +94,8 @@ static struct ccu_reset h6_resets[] = { static const struct ccu_desc h6_ccu_desc = { .gates = h6_gates, .resets = h6_resets, + .num_gates = ARRAY_SIZE(h6_gates), + .num_resets = ARRAY_SIZE(h6_resets), }; static int h6_clk_bind(struct udevice *dev) diff --git a/drivers/clk/sunxi/clk_h616.c b/drivers/clk/sunxi/clk_h616.c index 8009972..34cfcff 100644 --- a/drivers/clk/sunxi/clk_h616.c +++ b/drivers/clk/sunxi/clk_h616.c @@ -112,6 +112,8 @@ static struct ccu_reset h616_resets[] = { static const struct ccu_desc h616_ccu_desc = { .gates = h616_gates, .resets = h616_resets, + .num_gates = ARRAY_SIZE(h616_gates), + .num_resets = ARRAY_SIZE(h616_resets), }; static int h616_clk_bind(struct udevice *dev) diff --git a/drivers/clk/sunxi/clk_h6_r.c b/drivers/clk/sunxi/clk_h6_r.c index c592886..1891375 100644 --- a/drivers/clk/sunxi/clk_h6_r.c +++ b/drivers/clk/sunxi/clk_h6_r.c @@ -37,6 +37,8 @@ static struct ccu_reset h6_r_resets[] = { static const struct ccu_desc h6_r_ccu_desc = { .gates = h6_r_gates, .resets = h6_r_resets, + .num_gates = ARRAY_SIZE(h6_r_gates), + .num_resets = ARRAY_SIZE(h6_r_resets), }; static int h6_r_clk_bind(struct udevice *dev) diff --git a/drivers/clk/sunxi/clk_r40.c b/drivers/clk/sunxi/clk_r40.c index 45633a2..81e4a02 100644 --- a/drivers/clk/sunxi/clk_r40.c +++ b/drivers/clk/sunxi/clk_r40.c @@ -102,6 +102,8 @@ static struct ccu_reset r40_resets[] = { static const struct ccu_desc r40_ccu_desc = { .gates = r40_gates, .resets = r40_resets, + .num_gates = ARRAY_SIZE(r40_gates), + .num_resets = ARRAY_SIZE(r40_resets), }; static int r40_clk_bind(struct udevice *dev) diff --git a/drivers/clk/sunxi/clk_v3s.c b/drivers/clk/sunxi/clk_v3s.c index 67d215c..f45e940 100644 --- a/drivers/clk/sunxi/clk_v3s.c +++ b/drivers/clk/sunxi/clk_v3s.c @@ -52,6 +52,8 @@ static struct ccu_reset v3s_resets[] = { static const struct ccu_desc v3s_ccu_desc = { .gates = v3s_gates, .resets = v3s_resets, + .num_gates = ARRAY_SIZE(v3s_gates), + .num_resets = ARRAY_SIZE(v3s_resets), }; static int v3s_clk_bind(struct udevice *dev) -- cgit v1.1 From 6827aba3482d214afea3b3bc4cb2f5bddb606929 Mon Sep 17 00:00:00 2001 From: Samuel Holland Date: Mon, 9 May 2022 00:29:32 -0500 Subject: clk: sunxi: Prevent out-of-bounds gate array access Because the gate arrays are not given explicit sizes, the arrays are only as large as the highest-numbered gate described in the driver. However, only a subset of the CCU clocks are needed by U-Boot. So there are valid clock specifiers with indexes greater than the size of the arrays. Referencing any of these clocks causes out-of-bounds access. Fix this by checking the identifier against the size of the array. Fixes: 0d47bc705651 ("clk: Add Allwinner A64 CLK driver") Signed-off-by: Samuel Holland Reviewed-by: Andre Przywara Signed-off-by: Andre Przywara --- drivers/clk/sunxi/clk_sunxi.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/clk/sunxi/clk_sunxi.c b/drivers/clk/sunxi/clk_sunxi.c index 9a21367..62e7738 100644 --- a/drivers/clk/sunxi/clk_sunxi.c +++ b/drivers/clk/sunxi/clk_sunxi.c @@ -18,6 +18,9 @@ static const struct ccu_clk_gate *priv_to_gate(struct ccu_priv *priv, unsigned long id) { + if (id >= priv->desc->num_gates) + return NULL; + return &priv->desc->gates[id]; } @@ -27,10 +30,10 @@ static int sunxi_set_gate(struct clk *clk, bool on) const struct ccu_clk_gate *gate = priv_to_gate(priv, clk->id); u32 reg; - if ((gate->flags & CCU_CLK_F_DUMMY_GATE)) + if (gate && (gate->flags & CCU_CLK_F_DUMMY_GATE)) return 0; - if (!(gate->flags & CCU_CLK_F_IS_VALID)) { + if (!gate || !(gate->flags & CCU_CLK_F_IS_VALID)) { printf("%s: (CLK#%ld) unhandled\n", __func__, clk->id); return 0; } -- cgit v1.1 From d39088ad9c97fa612c480475b18759a3931c41fd Mon Sep 17 00:00:00 2001 From: Samuel Holland Date: Mon, 9 May 2022 00:29:33 -0500 Subject: reset: sunxi: Get the reset count from the CCU descriptor This allows all of the clock drivers to use a common bind function. Signed-off-by: Samuel Holland Reviewed-by: Andre Przywara [Andre: add F1C100s support] Signed-off-by: Andre Przywara --- drivers/clk/sunxi/clk_a10.c | 7 +------ drivers/clk/sunxi/clk_a10s.c | 7 +------ drivers/clk/sunxi/clk_a23.c | 7 +------ drivers/clk/sunxi/clk_a31.c | 7 +------ drivers/clk/sunxi/clk_a31_r.c | 7 +------ drivers/clk/sunxi/clk_a64.c | 7 +------ drivers/clk/sunxi/clk_a80.c | 12 +----------- drivers/clk/sunxi/clk_a83t.c | 7 +------ drivers/clk/sunxi/clk_f1c100s.c | 7 +------ drivers/clk/sunxi/clk_h3.c | 7 +------ drivers/clk/sunxi/clk_h6.c | 7 +------ drivers/clk/sunxi/clk_h616.c | 7 +------ drivers/clk/sunxi/clk_h6_r.c | 7 +------ drivers/clk/sunxi/clk_r40.c | 7 +------ drivers/clk/sunxi/clk_sunxi.c | 5 +++++ drivers/clk/sunxi/clk_v3s.c | 7 +------ drivers/reset/reset-sunxi.c | 6 ++---- 17 files changed, 22 insertions(+), 99 deletions(-) (limited to 'drivers') diff --git a/drivers/clk/sunxi/clk_a10.c b/drivers/clk/sunxi/clk_a10.c index b3cca2a..7bd9a37 100644 --- a/drivers/clk/sunxi/clk_a10.c +++ b/drivers/clk/sunxi/clk_a10.c @@ -71,11 +71,6 @@ static const struct ccu_desc a10_ccu_desc = { .num_resets = ARRAY_SIZE(a10_resets), }; -static int a10_clk_bind(struct udevice *dev) -{ - return sunxi_reset_bind(dev, ARRAY_SIZE(a10_resets)); -} - static const struct udevice_id a10_ccu_ids[] = { { .compatible = "allwinner,sun4i-a10-ccu", .data = (ulong)&a10_ccu_desc }, @@ -91,5 +86,5 @@ U_BOOT_DRIVER(clk_sun4i_a10) = { .priv_auto = sizeof(struct ccu_priv), .ops = &sunxi_clk_ops, .probe = sunxi_clk_probe, - .bind = a10_clk_bind, + .bind = sunxi_clk_bind, }; diff --git a/drivers/clk/sunxi/clk_a10s.c b/drivers/clk/sunxi/clk_a10s.c index 0e75c30..4a83d6b 100644 --- a/drivers/clk/sunxi/clk_a10s.c +++ b/drivers/clk/sunxi/clk_a10s.c @@ -56,11 +56,6 @@ static const struct ccu_desc a10s_ccu_desc = { .num_resets = ARRAY_SIZE(a10s_resets), }; -static int a10s_clk_bind(struct udevice *dev) -{ - return sunxi_reset_bind(dev, ARRAY_SIZE(a10s_resets)); -} - static const struct udevice_id a10s_ccu_ids[] = { { .compatible = "allwinner,sun5i-a10s-ccu", .data = (ulong)&a10s_ccu_desc }, @@ -76,5 +71,5 @@ U_BOOT_DRIVER(clk_sun5i_a10s) = { .priv_auto = sizeof(struct ccu_priv), .ops = &sunxi_clk_ops, .probe = sunxi_clk_probe, - .bind = a10s_clk_bind, + .bind = sunxi_clk_bind, }; diff --git a/drivers/clk/sunxi/clk_a23.c b/drivers/clk/sunxi/clk_a23.c index a9c77ba..c7f516d 100644 --- a/drivers/clk/sunxi/clk_a23.c +++ b/drivers/clk/sunxi/clk_a23.c @@ -75,11 +75,6 @@ static const struct ccu_desc a23_ccu_desc = { .num_resets = ARRAY_SIZE(a23_resets), }; -static int a23_clk_bind(struct udevice *dev) -{ - return sunxi_reset_bind(dev, ARRAY_SIZE(a23_resets)); -} - static const struct udevice_id a23_clk_ids[] = { { .compatible = "allwinner,sun8i-a23-ccu", .data = (ulong)&a23_ccu_desc }, @@ -95,5 +90,5 @@ U_BOOT_DRIVER(clk_sun8i_a23) = { .priv_auto = sizeof(struct ccu_priv), .ops = &sunxi_clk_ops, .probe = sunxi_clk_probe, - .bind = a23_clk_bind, + .bind = sunxi_clk_bind, }; diff --git a/drivers/clk/sunxi/clk_a31.c b/drivers/clk/sunxi/clk_a31.c index 69df4e0..aa113fa 100644 --- a/drivers/clk/sunxi/clk_a31.c +++ b/drivers/clk/sunxi/clk_a31.c @@ -96,11 +96,6 @@ static const struct ccu_desc a31_ccu_desc = { .num_resets = ARRAY_SIZE(a31_resets), }; -static int a31_clk_bind(struct udevice *dev) -{ - return sunxi_reset_bind(dev, ARRAY_SIZE(a31_resets)); -} - static const struct udevice_id a31_clk_ids[] = { { .compatible = "allwinner,sun6i-a31-ccu", .data = (ulong)&a31_ccu_desc }, @@ -114,5 +109,5 @@ U_BOOT_DRIVER(clk_sun6i_a31) = { .priv_auto = sizeof(struct ccu_priv), .ops = &sunxi_clk_ops, .probe = sunxi_clk_probe, - .bind = a31_clk_bind, + .bind = sunxi_clk_bind, }; diff --git a/drivers/clk/sunxi/clk_a31_r.c b/drivers/clk/sunxi/clk_a31_r.c index 7bf1c45..04c2382 100644 --- a/drivers/clk/sunxi/clk_a31_r.c +++ b/drivers/clk/sunxi/clk_a31_r.c @@ -35,11 +35,6 @@ static const struct ccu_desc a31_r_ccu_desc = { .num_resets = ARRAY_SIZE(a31_r_resets), }; -static int a31_r_clk_bind(struct udevice *dev) -{ - return sunxi_reset_bind(dev, ARRAY_SIZE(a31_r_resets)); -} - static const struct udevice_id a31_r_clk_ids[] = { { .compatible = "allwinner,sun8i-a83t-r-ccu", .data = (ulong)&a31_r_ccu_desc }, @@ -57,5 +52,5 @@ U_BOOT_DRIVER(clk_sun6i_a31_r) = { .priv_auto = sizeof(struct ccu_priv), .ops = &sunxi_clk_ops, .probe = sunxi_clk_probe, - .bind = a31_r_clk_bind, + .bind = sunxi_clk_bind, }; diff --git a/drivers/clk/sunxi/clk_a64.c b/drivers/clk/sunxi/clk_a64.c index e24d5c5..eac1151 100644 --- a/drivers/clk/sunxi/clk_a64.c +++ b/drivers/clk/sunxi/clk_a64.c @@ -84,11 +84,6 @@ static const struct ccu_desc a64_ccu_desc = { .num_resets = ARRAY_SIZE(a64_resets), }; -static int a64_clk_bind(struct udevice *dev) -{ - return sunxi_reset_bind(dev, ARRAY_SIZE(a64_resets)); -} - static const struct udevice_id a64_ccu_ids[] = { { .compatible = "allwinner,sun50i-a64-ccu", .data = (ulong)&a64_ccu_desc }, @@ -102,5 +97,5 @@ U_BOOT_DRIVER(clk_sun50i_a64) = { .priv_auto = sizeof(struct ccu_priv), .ops = &sunxi_clk_ops, .probe = sunxi_clk_probe, - .bind = a64_clk_bind, + .bind = sunxi_clk_bind, }; diff --git a/drivers/clk/sunxi/clk_a80.c b/drivers/clk/sunxi/clk_a80.c index adedcba..426205d 100644 --- a/drivers/clk/sunxi/clk_a80.c +++ b/drivers/clk/sunxi/clk_a80.c @@ -88,16 +88,6 @@ static const struct ccu_desc a80_mmc_clk_desc = { .num_resets = ARRAY_SIZE(a80_mmc_resets), }; -static int a80_clk_bind(struct udevice *dev) -{ - ulong count = ARRAY_SIZE(a80_resets); - - if (device_is_compatible(dev, "allwinner,sun9i-a80-mmc-config-clk")) - count = ARRAY_SIZE(a80_mmc_resets); - - return sunxi_reset_bind(dev, count); -} - static const struct udevice_id a80_ccu_ids[] = { { .compatible = "allwinner,sun9i-a80-ccu", .data = (ulong)&a80_ccu_desc }, @@ -113,5 +103,5 @@ U_BOOT_DRIVER(clk_sun9i_a80) = { .priv_auto = sizeof(struct ccu_priv), .ops = &sunxi_clk_ops, .probe = sunxi_clk_probe, - .bind = a80_clk_bind, + .bind = sunxi_clk_bind, }; diff --git a/drivers/clk/sunxi/clk_a83t.c b/drivers/clk/sunxi/clk_a83t.c index 4a0659a..464e95c 100644 --- a/drivers/clk/sunxi/clk_a83t.c +++ b/drivers/clk/sunxi/clk_a83t.c @@ -79,11 +79,6 @@ static const struct ccu_desc a83t_ccu_desc = { .num_resets = ARRAY_SIZE(a83t_resets), }; -static int a83t_clk_bind(struct udevice *dev) -{ - return sunxi_reset_bind(dev, ARRAY_SIZE(a83t_resets)); -} - static const struct udevice_id a83t_clk_ids[] = { { .compatible = "allwinner,sun8i-a83t-ccu", .data = (ulong)&a83t_ccu_desc }, @@ -97,5 +92,5 @@ U_BOOT_DRIVER(clk_sun8i_a83t) = { .priv_auto = sizeof(struct ccu_priv), .ops = &sunxi_clk_ops, .probe = sunxi_clk_probe, - .bind = a83t_clk_bind, + .bind = sunxi_clk_bind, }; diff --git a/drivers/clk/sunxi/clk_f1c100s.c b/drivers/clk/sunxi/clk_f1c100s.c index cb0159e..acba8f2 100644 --- a/drivers/clk/sunxi/clk_f1c100s.c +++ b/drivers/clk/sunxi/clk_f1c100s.c @@ -54,11 +54,6 @@ static const struct ccu_desc f1c100s_ccu_desc = { .num_resets = ARRAY_SIZE(f1c100s_resets), }; -static int f1c100s_clk_bind(struct udevice *dev) -{ - return sunxi_reset_bind(dev, ARRAY_SIZE(f1c100s_resets)); -} - static const struct udevice_id f1c100s_clk_ids[] = { { .compatible = "allwinner,suniv-f1c100s-ccu", .data = (ulong)&f1c100s_ccu_desc }, @@ -72,5 +67,5 @@ U_BOOT_DRIVER(clk_suniv_f1c100s) = { .priv_auto = sizeof(struct ccu_priv), .ops = &sunxi_clk_ops, .probe = sunxi_clk_probe, - .bind = f1c100s_clk_bind, + .bind = sunxi_clk_bind, }; diff --git a/drivers/clk/sunxi/clk_h3.c b/drivers/clk/sunxi/clk_h3.c index d69cb04..474cf98 100644 --- a/drivers/clk/sunxi/clk_h3.c +++ b/drivers/clk/sunxi/clk_h3.c @@ -97,11 +97,6 @@ static const struct ccu_desc h3_ccu_desc = { .num_resets = ARRAY_SIZE(h3_resets), }; -static int h3_clk_bind(struct udevice *dev) -{ - return sunxi_reset_bind(dev, ARRAY_SIZE(h3_resets)); -} - static const struct udevice_id h3_ccu_ids[] = { { .compatible = "allwinner,sun8i-h3-ccu", .data = (ulong)&h3_ccu_desc }, @@ -117,5 +112,5 @@ U_BOOT_DRIVER(clk_sun8i_h3) = { .priv_auto = sizeof(struct ccu_priv), .ops = &sunxi_clk_ops, .probe = sunxi_clk_probe, - .bind = h3_clk_bind, + .bind = sunxi_clk_bind, }; diff --git a/drivers/clk/sunxi/clk_h6.c b/drivers/clk/sunxi/clk_h6.c index f8d2379..4e717af 100644 --- a/drivers/clk/sunxi/clk_h6.c +++ b/drivers/clk/sunxi/clk_h6.c @@ -98,11 +98,6 @@ static const struct ccu_desc h6_ccu_desc = { .num_resets = ARRAY_SIZE(h6_resets), }; -static int h6_clk_bind(struct udevice *dev) -{ - return sunxi_reset_bind(dev, ARRAY_SIZE(h6_resets)); -} - static const struct udevice_id h6_ccu_ids[] = { { .compatible = "allwinner,sun50i-h6-ccu", .data = (ulong)&h6_ccu_desc }, @@ -116,5 +111,5 @@ U_BOOT_DRIVER(clk_sun50i_h6) = { .priv_auto = sizeof(struct ccu_priv), .ops = &sunxi_clk_ops, .probe = sunxi_clk_probe, - .bind = h6_clk_bind, + .bind = sunxi_clk_bind, }; diff --git a/drivers/clk/sunxi/clk_h616.c b/drivers/clk/sunxi/clk_h616.c index 34cfcff..1ecccd7 100644 --- a/drivers/clk/sunxi/clk_h616.c +++ b/drivers/clk/sunxi/clk_h616.c @@ -116,11 +116,6 @@ static const struct ccu_desc h616_ccu_desc = { .num_resets = ARRAY_SIZE(h616_resets), }; -static int h616_clk_bind(struct udevice *dev) -{ - return sunxi_reset_bind(dev, ARRAY_SIZE(h616_resets)); -} - static const struct udevice_id h616_ccu_ids[] = { { .compatible = "allwinner,sun50i-h616-ccu", .data = (ulong)&h616_ccu_desc }, @@ -134,5 +129,5 @@ U_BOOT_DRIVER(clk_sun50i_h616) = { .priv_auto = sizeof(struct ccu_priv), .ops = &sunxi_clk_ops, .probe = sunxi_clk_probe, - .bind = h616_clk_bind, + .bind = sunxi_clk_bind, }; diff --git a/drivers/clk/sunxi/clk_h6_r.c b/drivers/clk/sunxi/clk_h6_r.c index 1891375..bb67d58 100644 --- a/drivers/clk/sunxi/clk_h6_r.c +++ b/drivers/clk/sunxi/clk_h6_r.c @@ -41,11 +41,6 @@ static const struct ccu_desc h6_r_ccu_desc = { .num_resets = ARRAY_SIZE(h6_r_resets), }; -static int h6_r_clk_bind(struct udevice *dev) -{ - return sunxi_reset_bind(dev, ARRAY_SIZE(h6_r_resets)); -} - static const struct udevice_id h6_r_clk_ids[] = { { .compatible = "allwinner,sun50i-h6-r-ccu", .data = (ulong)&h6_r_ccu_desc }, @@ -61,5 +56,5 @@ U_BOOT_DRIVER(clk_sun50i_h6_r) = { .priv_auto = sizeof(struct ccu_priv), .ops = &sunxi_clk_ops, .probe = sunxi_clk_probe, - .bind = h6_r_clk_bind, + .bind = sunxi_clk_bind, }; diff --git a/drivers/clk/sunxi/clk_r40.c b/drivers/clk/sunxi/clk_r40.c index 81e4a02..daab6ad 100644 --- a/drivers/clk/sunxi/clk_r40.c +++ b/drivers/clk/sunxi/clk_r40.c @@ -106,11 +106,6 @@ static const struct ccu_desc r40_ccu_desc = { .num_resets = ARRAY_SIZE(r40_resets), }; -static int r40_clk_bind(struct udevice *dev) -{ - return sunxi_reset_bind(dev, ARRAY_SIZE(r40_resets)); -} - static const struct udevice_id r40_clk_ids[] = { { .compatible = "allwinner,sun8i-r40-ccu", .data = (ulong)&r40_ccu_desc }, @@ -124,5 +119,5 @@ U_BOOT_DRIVER(clk_sun8i_r40) = { .priv_auto = sizeof(struct ccu_priv), .ops = &sunxi_clk_ops, .probe = sunxi_clk_probe, - .bind = r40_clk_bind, + .bind = sunxi_clk_bind, }; diff --git a/drivers/clk/sunxi/clk_sunxi.c b/drivers/clk/sunxi/clk_sunxi.c index 62e7738..23d81f6 100644 --- a/drivers/clk/sunxi/clk_sunxi.c +++ b/drivers/clk/sunxi/clk_sunxi.c @@ -67,6 +67,11 @@ struct clk_ops sunxi_clk_ops = { .disable = sunxi_clk_disable, }; +int sunxi_clk_bind(struct udevice *dev) +{ + return sunxi_reset_bind(dev); +} + int sunxi_clk_probe(struct udevice *dev) { struct ccu_priv *priv = dev_get_priv(dev); diff --git a/drivers/clk/sunxi/clk_v3s.c b/drivers/clk/sunxi/clk_v3s.c index f45e940..5b5afa6 100644 --- a/drivers/clk/sunxi/clk_v3s.c +++ b/drivers/clk/sunxi/clk_v3s.c @@ -56,11 +56,6 @@ static const struct ccu_desc v3s_ccu_desc = { .num_resets = ARRAY_SIZE(v3s_resets), }; -static int v3s_clk_bind(struct udevice *dev) -{ - return sunxi_reset_bind(dev, ARRAY_SIZE(v3s_resets)); -} - static const struct udevice_id v3s_clk_ids[] = { { .compatible = "allwinner,sun8i-v3s-ccu", .data = (ulong)&v3s_ccu_desc }, @@ -76,5 +71,5 @@ U_BOOT_DRIVER(clk_sun8i_v3s) = { .priv_auto = sizeof(struct ccu_priv), .ops = &sunxi_clk_ops, .probe = sunxi_clk_probe, - .bind = v3s_clk_bind, + .bind = sunxi_clk_bind, }; diff --git a/drivers/reset/reset-sunxi.c b/drivers/reset/reset-sunxi.c index e2a9c2a..621912a 100644 --- a/drivers/reset/reset-sunxi.c +++ b/drivers/reset/reset-sunxi.c @@ -19,7 +19,6 @@ struct sunxi_reset_priv { void *base; - ulong count; const struct ccu_desc *desc; }; @@ -35,7 +34,7 @@ static int sunxi_reset_request(struct reset_ctl *reset_ctl) debug("%s: (RST#%ld)\n", __func__, reset_ctl->id); - if (reset_ctl->id >= priv->count) + if (reset_ctl->id >= priv->desc->num_resets) return -EINVAL; return 0; @@ -91,7 +90,7 @@ static int sunxi_reset_probe(struct udevice *dev) return 0; } -int sunxi_reset_bind(struct udevice *dev, ulong count) +int sunxi_reset_bind(struct udevice *dev) { struct udevice *rst_dev; struct sunxi_reset_priv *priv; @@ -104,7 +103,6 @@ int sunxi_reset_bind(struct udevice *dev, ulong count) return ret; } priv = malloc(sizeof(struct sunxi_reset_priv)); - priv->count = count; priv->desc = (const struct ccu_desc *)dev_get_driver_data(dev); dev_set_priv(rst_dev, priv); -- cgit v1.1 From 46fa23f9eecd0fc32215a194e7a7f5f5abe67cdc Mon Sep 17 00:00:00 2001 From: Samuel Holland Date: Mon, 9 May 2022 00:29:34 -0500 Subject: clk: sunxi: Use a single driver for all variants Now that all of the variants use the same bind/probe functions and ops, there is no need to have a separate driver for each variant. Since most SoCs contain two variants (the main CCU and PRCM CCU), this saves a bit of firmware size and RAM. Signed-off-by: Samuel Holland Reviewed-by: Andre Przywara [Andre: add F1C100s support] Signed-off-by: Andre Przywara --- drivers/clk/sunxi/clk_a10.c | 20 +------ drivers/clk/sunxi/clk_a10s.c | 20 +------ drivers/clk/sunxi/clk_a23.c | 20 +------ drivers/clk/sunxi/clk_a31.c | 18 +----- drivers/clk/sunxi/clk_a31_r.c | 22 +------ drivers/clk/sunxi/clk_a64.c | 18 +----- drivers/clk/sunxi/clk_a80.c | 22 +------ drivers/clk/sunxi/clk_a83t.c | 18 +----- drivers/clk/sunxi/clk_f1c100s.c | 18 +----- drivers/clk/sunxi/clk_h3.c | 20 +------ drivers/clk/sunxi/clk_h6.c | 18 +----- drivers/clk/sunxi/clk_h616.c | 18 +----- drivers/clk/sunxi/clk_h6_r.c | 20 +------ drivers/clk/sunxi/clk_r40.c | 18 +----- drivers/clk/sunxi/clk_sunxi.c | 123 +++++++++++++++++++++++++++++++++++++++- drivers/clk/sunxi/clk_v3s.c | 20 +------ 16 files changed, 137 insertions(+), 276 deletions(-) (limited to 'drivers') diff --git a/drivers/clk/sunxi/clk_a10.c b/drivers/clk/sunxi/clk_a10.c index 7bd9a37..abd4e8b 100644 --- a/drivers/clk/sunxi/clk_a10.c +++ b/drivers/clk/sunxi/clk_a10.c @@ -64,27 +64,9 @@ static struct ccu_reset a10_resets[] = { [RST_USB_PHY2] = RESET(0x0cc, BIT(2)), }; -static const struct ccu_desc a10_ccu_desc = { +const struct ccu_desc a10_ccu_desc = { .gates = a10_gates, .resets = a10_resets, .num_gates = ARRAY_SIZE(a10_gates), .num_resets = ARRAY_SIZE(a10_resets), }; - -static const struct udevice_id a10_ccu_ids[] = { - { .compatible = "allwinner,sun4i-a10-ccu", - .data = (ulong)&a10_ccu_desc }, - { .compatible = "allwinner,sun7i-a20-ccu", - .data = (ulong)&a10_ccu_desc }, - { } -}; - -U_BOOT_DRIVER(clk_sun4i_a10) = { - .name = "sun4i_a10_ccu", - .id = UCLASS_CLK, - .of_match = a10_ccu_ids, - .priv_auto = sizeof(struct ccu_priv), - .ops = &sunxi_clk_ops, - .probe = sunxi_clk_probe, - .bind = sunxi_clk_bind, -}; diff --git a/drivers/clk/sunxi/clk_a10s.c b/drivers/clk/sunxi/clk_a10s.c index 4a83d6b..e486ced 100644 --- a/drivers/clk/sunxi/clk_a10s.c +++ b/drivers/clk/sunxi/clk_a10s.c @@ -49,27 +49,9 @@ static struct ccu_reset a10s_resets[] = { [RST_USB_PHY1] = RESET(0x0cc, BIT(1)), }; -static const struct ccu_desc a10s_ccu_desc = { +const struct ccu_desc a10s_ccu_desc = { .gates = a10s_gates, .resets = a10s_resets, .num_gates = ARRAY_SIZE(a10s_gates), .num_resets = ARRAY_SIZE(a10s_resets), }; - -static const struct udevice_id a10s_ccu_ids[] = { - { .compatible = "allwinner,sun5i-a10s-ccu", - .data = (ulong)&a10s_ccu_desc }, - { .compatible = "allwinner,sun5i-a13-ccu", - .data = (ulong)&a10s_ccu_desc }, - { } -}; - -U_BOOT_DRIVER(clk_sun5i_a10s) = { - .name = "sun5i_a10s_ccu", - .id = UCLASS_CLK, - .of_match = a10s_ccu_ids, - .priv_auto = sizeof(struct ccu_priv), - .ops = &sunxi_clk_ops, - .probe = sunxi_clk_probe, - .bind = sunxi_clk_bind, -}; diff --git a/drivers/clk/sunxi/clk_a23.c b/drivers/clk/sunxi/clk_a23.c index c7f516d..d94feca 100644 --- a/drivers/clk/sunxi/clk_a23.c +++ b/drivers/clk/sunxi/clk_a23.c @@ -68,27 +68,9 @@ static struct ccu_reset a23_resets[] = { [RST_BUS_UART4] = RESET(0x2d8, BIT(20)), }; -static const struct ccu_desc a23_ccu_desc = { +const struct ccu_desc a23_ccu_desc = { .gates = a23_gates, .resets = a23_resets, .num_gates = ARRAY_SIZE(a23_gates), .num_resets = ARRAY_SIZE(a23_resets), }; - -static const struct udevice_id a23_clk_ids[] = { - { .compatible = "allwinner,sun8i-a23-ccu", - .data = (ulong)&a23_ccu_desc }, - { .compatible = "allwinner,sun8i-a33-ccu", - .data = (ulong)&a23_ccu_desc }, - { } -}; - -U_BOOT_DRIVER(clk_sun8i_a23) = { - .name = "sun8i_a23_ccu", - .id = UCLASS_CLK, - .of_match = a23_clk_ids, - .priv_auto = sizeof(struct ccu_priv), - .ops = &sunxi_clk_ops, - .probe = sunxi_clk_probe, - .bind = sunxi_clk_bind, -}; diff --git a/drivers/clk/sunxi/clk_a31.c b/drivers/clk/sunxi/clk_a31.c index aa113fa..3606589 100644 --- a/drivers/clk/sunxi/clk_a31.c +++ b/drivers/clk/sunxi/clk_a31.c @@ -89,25 +89,9 @@ static struct ccu_reset a31_resets[] = { [RST_APB2_UART5] = RESET(0x2d8, BIT(21)), }; -static const struct ccu_desc a31_ccu_desc = { +const struct ccu_desc a31_ccu_desc = { .gates = a31_gates, .resets = a31_resets, .num_gates = ARRAY_SIZE(a31_gates), .num_resets = ARRAY_SIZE(a31_resets), }; - -static const struct udevice_id a31_clk_ids[] = { - { .compatible = "allwinner,sun6i-a31-ccu", - .data = (ulong)&a31_ccu_desc }, - { } -}; - -U_BOOT_DRIVER(clk_sun6i_a31) = { - .name = "sun6i_a31_ccu", - .id = UCLASS_CLK, - .of_match = a31_clk_ids, - .priv_auto = sizeof(struct ccu_priv), - .ops = &sunxi_clk_ops, - .probe = sunxi_clk_probe, - .bind = sunxi_clk_bind, -}; diff --git a/drivers/clk/sunxi/clk_a31_r.c b/drivers/clk/sunxi/clk_a31_r.c index 04c2382..fa6887f 100644 --- a/drivers/clk/sunxi/clk_a31_r.c +++ b/drivers/clk/sunxi/clk_a31_r.c @@ -28,29 +28,9 @@ static struct ccu_reset a31_r_resets[] = { [RST_APB0_I2C] = RESET(0x0b0, BIT(6)), }; -static const struct ccu_desc a31_r_ccu_desc = { +const struct ccu_desc a31_r_ccu_desc = { .gates = a31_r_gates, .resets = a31_r_resets, .num_gates = ARRAY_SIZE(a31_r_gates), .num_resets = ARRAY_SIZE(a31_r_resets), }; - -static const struct udevice_id a31_r_clk_ids[] = { - { .compatible = "allwinner,sun8i-a83t-r-ccu", - .data = (ulong)&a31_r_ccu_desc }, - { .compatible = "allwinner,sun8i-h3-r-ccu", - .data = (ulong)&a31_r_ccu_desc }, - { .compatible = "allwinner,sun50i-a64-r-ccu", - .data = (ulong)&a31_r_ccu_desc }, - { } -}; - -U_BOOT_DRIVER(clk_sun6i_a31_r) = { - .name = "sun6i_a31_r_ccu", - .id = UCLASS_CLK, - .of_match = a31_r_clk_ids, - .priv_auto = sizeof(struct ccu_priv), - .ops = &sunxi_clk_ops, - .probe = sunxi_clk_probe, - .bind = sunxi_clk_bind, -}; diff --git a/drivers/clk/sunxi/clk_a64.c b/drivers/clk/sunxi/clk_a64.c index eac1151..8c81b1a 100644 --- a/drivers/clk/sunxi/clk_a64.c +++ b/drivers/clk/sunxi/clk_a64.c @@ -77,25 +77,9 @@ static const struct ccu_reset a64_resets[] = { [RST_BUS_UART4] = RESET(0x2d8, BIT(20)), }; -static const struct ccu_desc a64_ccu_desc = { +const struct ccu_desc a64_ccu_desc = { .gates = a64_gates, .resets = a64_resets, .num_gates = ARRAY_SIZE(a64_gates), .num_resets = ARRAY_SIZE(a64_resets), }; - -static const struct udevice_id a64_ccu_ids[] = { - { .compatible = "allwinner,sun50i-a64-ccu", - .data = (ulong)&a64_ccu_desc }, - { } -}; - -U_BOOT_DRIVER(clk_sun50i_a64) = { - .name = "sun50i_a64_ccu", - .id = UCLASS_CLK, - .of_match = a64_ccu_ids, - .priv_auto = sizeof(struct ccu_priv), - .ops = &sunxi_clk_ops, - .probe = sunxi_clk_probe, - .bind = sunxi_clk_bind, -}; diff --git a/drivers/clk/sunxi/clk_a80.c b/drivers/clk/sunxi/clk_a80.c index 426205d..3c9eb14 100644 --- a/drivers/clk/sunxi/clk_a80.c +++ b/drivers/clk/sunxi/clk_a80.c @@ -74,34 +74,16 @@ static const struct ccu_reset a80_mmc_resets[] = { [3] = GATE(0xc, BIT(18)), }; -static const struct ccu_desc a80_ccu_desc = { +const struct ccu_desc a80_ccu_desc = { .gates = a80_gates, .resets = a80_resets, .num_gates = ARRAY_SIZE(a80_gates), .num_resets = ARRAY_SIZE(a80_resets), }; -static const struct ccu_desc a80_mmc_clk_desc = { +const struct ccu_desc a80_mmc_clk_desc = { .gates = a80_mmc_gates, .resets = a80_mmc_resets, .num_gates = ARRAY_SIZE(a80_mmc_gates), .num_resets = ARRAY_SIZE(a80_mmc_resets), }; - -static const struct udevice_id a80_ccu_ids[] = { - { .compatible = "allwinner,sun9i-a80-ccu", - .data = (ulong)&a80_ccu_desc }, - { .compatible = "allwinner,sun9i-a80-mmc-config-clk", - .data = (ulong)&a80_mmc_clk_desc }, - { } -}; - -U_BOOT_DRIVER(clk_sun9i_a80) = { - .name = "sun9i_a80_ccu", - .id = UCLASS_CLK, - .of_match = a80_ccu_ids, - .priv_auto = sizeof(struct ccu_priv), - .ops = &sunxi_clk_ops, - .probe = sunxi_clk_probe, - .bind = sunxi_clk_bind, -}; diff --git a/drivers/clk/sunxi/clk_a83t.c b/drivers/clk/sunxi/clk_a83t.c index 464e95c..3562da6 100644 --- a/drivers/clk/sunxi/clk_a83t.c +++ b/drivers/clk/sunxi/clk_a83t.c @@ -72,25 +72,9 @@ static struct ccu_reset a83t_resets[] = { [RST_BUS_UART4] = RESET(0x2d8, BIT(20)), }; -static const struct ccu_desc a83t_ccu_desc = { +const struct ccu_desc a83t_ccu_desc = { .gates = a83t_gates, .resets = a83t_resets, .num_gates = ARRAY_SIZE(a83t_gates), .num_resets = ARRAY_SIZE(a83t_resets), }; - -static const struct udevice_id a83t_clk_ids[] = { - { .compatible = "allwinner,sun8i-a83t-ccu", - .data = (ulong)&a83t_ccu_desc }, - { } -}; - -U_BOOT_DRIVER(clk_sun8i_a83t) = { - .name = "sun8i_a83t_ccu", - .id = UCLASS_CLK, - .of_match = a83t_clk_ids, - .priv_auto = sizeof(struct ccu_priv), - .ops = &sunxi_clk_ops, - .probe = sunxi_clk_probe, - .bind = sunxi_clk_bind, -}; diff --git a/drivers/clk/sunxi/clk_f1c100s.c b/drivers/clk/sunxi/clk_f1c100s.c index acba8f2..7b4c3ce 100644 --- a/drivers/clk/sunxi/clk_f1c100s.c +++ b/drivers/clk/sunxi/clk_f1c100s.c @@ -47,25 +47,9 @@ static struct ccu_reset f1c100s_resets[] = { [RST_BUS_UART2] = RESET(0x2d0, BIT(22)), }; -static const struct ccu_desc f1c100s_ccu_desc = { +const struct ccu_desc f1c100s_ccu_desc = { .gates = f1c100s_gates, .resets = f1c100s_resets, .num_gates = ARRAY_SIZE(f1c100s_gates), .num_resets = ARRAY_SIZE(f1c100s_resets), }; - -static const struct udevice_id f1c100s_clk_ids[] = { - { .compatible = "allwinner,suniv-f1c100s-ccu", - .data = (ulong)&f1c100s_ccu_desc }, - { } -}; - -U_BOOT_DRIVER(clk_suniv_f1c100s) = { - .name = "suniv_f1c100s_ccu", - .id = UCLASS_CLK, - .of_match = f1c100s_clk_ids, - .priv_auto = sizeof(struct ccu_priv), - .ops = &sunxi_clk_ops, - .probe = sunxi_clk_probe, - .bind = sunxi_clk_bind, -}; diff --git a/drivers/clk/sunxi/clk_h3.c b/drivers/clk/sunxi/clk_h3.c index 474cf98..17ab3b5 100644 --- a/drivers/clk/sunxi/clk_h3.c +++ b/drivers/clk/sunxi/clk_h3.c @@ -90,27 +90,9 @@ static struct ccu_reset h3_resets[] = { [RST_BUS_UART3] = RESET(0x2d8, BIT(19)), }; -static const struct ccu_desc h3_ccu_desc = { +const struct ccu_desc h3_ccu_desc = { .gates = h3_gates, .resets = h3_resets, .num_gates = ARRAY_SIZE(h3_gates), .num_resets = ARRAY_SIZE(h3_resets), }; - -static const struct udevice_id h3_ccu_ids[] = { - { .compatible = "allwinner,sun8i-h3-ccu", - .data = (ulong)&h3_ccu_desc }, - { .compatible = "allwinner,sun50i-h5-ccu", - .data = (ulong)&h3_ccu_desc }, - { } -}; - -U_BOOT_DRIVER(clk_sun8i_h3) = { - .name = "sun8i_h3_ccu", - .id = UCLASS_CLK, - .of_match = h3_ccu_ids, - .priv_auto = sizeof(struct ccu_priv), - .ops = &sunxi_clk_ops, - .probe = sunxi_clk_probe, - .bind = sunxi_clk_bind, -}; diff --git a/drivers/clk/sunxi/clk_h6.c b/drivers/clk/sunxi/clk_h6.c index 4e717af..041bc5e 100644 --- a/drivers/clk/sunxi/clk_h6.c +++ b/drivers/clk/sunxi/clk_h6.c @@ -91,25 +91,9 @@ static struct ccu_reset h6_resets[] = { [RST_BUS_OTG] = RESET(0xa8c, BIT(24)), }; -static const struct ccu_desc h6_ccu_desc = { +const struct ccu_desc h6_ccu_desc = { .gates = h6_gates, .resets = h6_resets, .num_gates = ARRAY_SIZE(h6_gates), .num_resets = ARRAY_SIZE(h6_resets), }; - -static const struct udevice_id h6_ccu_ids[] = { - { .compatible = "allwinner,sun50i-h6-ccu", - .data = (ulong)&h6_ccu_desc }, - { } -}; - -U_BOOT_DRIVER(clk_sun50i_h6) = { - .name = "sun50i_h6_ccu", - .id = UCLASS_CLK, - .of_match = h6_ccu_ids, - .priv_auto = sizeof(struct ccu_priv), - .ops = &sunxi_clk_ops, - .probe = sunxi_clk_probe, - .bind = sunxi_clk_bind, -}; diff --git a/drivers/clk/sunxi/clk_h616.c b/drivers/clk/sunxi/clk_h616.c index 1ecccd7..964636d 100644 --- a/drivers/clk/sunxi/clk_h616.c +++ b/drivers/clk/sunxi/clk_h616.c @@ -109,25 +109,9 @@ static struct ccu_reset h616_resets[] = { [RST_BUS_OTG] = RESET(0xa8c, BIT(24)), }; -static const struct ccu_desc h616_ccu_desc = { +const struct ccu_desc h616_ccu_desc = { .gates = h616_gates, .resets = h616_resets, .num_gates = ARRAY_SIZE(h616_gates), .num_resets = ARRAY_SIZE(h616_resets), }; - -static const struct udevice_id h616_ccu_ids[] = { - { .compatible = "allwinner,sun50i-h616-ccu", - .data = (ulong)&h616_ccu_desc }, - { } -}; - -U_BOOT_DRIVER(clk_sun50i_h616) = { - .name = "sun50i_h616_ccu", - .id = UCLASS_CLK, - .of_match = h616_ccu_ids, - .priv_auto = sizeof(struct ccu_priv), - .ops = &sunxi_clk_ops, - .probe = sunxi_clk_probe, - .bind = sunxi_clk_bind, -}; diff --git a/drivers/clk/sunxi/clk_h6_r.c b/drivers/clk/sunxi/clk_h6_r.c index bb67d58..ddcb3da 100644 --- a/drivers/clk/sunxi/clk_h6_r.c +++ b/drivers/clk/sunxi/clk_h6_r.c @@ -34,27 +34,9 @@ static struct ccu_reset h6_r_resets[] = { [RST_R_APB1_W1] = RESET(0x1ec, BIT(16)), }; -static const struct ccu_desc h6_r_ccu_desc = { +const struct ccu_desc h6_r_ccu_desc = { .gates = h6_r_gates, .resets = h6_r_resets, .num_gates = ARRAY_SIZE(h6_r_gates), .num_resets = ARRAY_SIZE(h6_r_resets), }; - -static const struct udevice_id h6_r_clk_ids[] = { - { .compatible = "allwinner,sun50i-h6-r-ccu", - .data = (ulong)&h6_r_ccu_desc }, - { .compatible = "allwinner,sun50i-h616-r-ccu", - .data = (ulong)&h6_r_ccu_desc }, - { } -}; - -U_BOOT_DRIVER(clk_sun50i_h6_r) = { - .name = "sun50i_h6_r_ccu", - .id = UCLASS_CLK, - .of_match = h6_r_clk_ids, - .priv_auto = sizeof(struct ccu_priv), - .ops = &sunxi_clk_ops, - .probe = sunxi_clk_probe, - .bind = sunxi_clk_bind, -}; diff --git a/drivers/clk/sunxi/clk_r40.c b/drivers/clk/sunxi/clk_r40.c index daab6ad..ef743d6 100644 --- a/drivers/clk/sunxi/clk_r40.c +++ b/drivers/clk/sunxi/clk_r40.c @@ -99,25 +99,9 @@ static struct ccu_reset r40_resets[] = { [RST_BUS_UART7] = RESET(0x2d8, BIT(23)), }; -static const struct ccu_desc r40_ccu_desc = { +const struct ccu_desc r40_ccu_desc = { .gates = r40_gates, .resets = r40_resets, .num_gates = ARRAY_SIZE(r40_gates), .num_resets = ARRAY_SIZE(r40_resets), }; - -static const struct udevice_id r40_clk_ids[] = { - { .compatible = "allwinner,sun8i-r40-ccu", - .data = (ulong)&r40_ccu_desc }, - { } -}; - -U_BOOT_DRIVER(clk_sun8i_r40) = { - .name = "sun8i_r40_ccu", - .id = UCLASS_CLK, - .of_match = r40_clk_ids, - .priv_auto = sizeof(struct ccu_priv), - .ops = &sunxi_clk_ops, - .probe = sunxi_clk_probe, - .bind = sunxi_clk_bind, -}; diff --git a/drivers/clk/sunxi/clk_sunxi.c b/drivers/clk/sunxi/clk_sunxi.c index 23d81f6..8503c79 100644 --- a/drivers/clk/sunxi/clk_sunxi.c +++ b/drivers/clk/sunxi/clk_sunxi.c @@ -67,12 +67,12 @@ struct clk_ops sunxi_clk_ops = { .disable = sunxi_clk_disable, }; -int sunxi_clk_bind(struct udevice *dev) +static int sunxi_clk_bind(struct udevice *dev) { return sunxi_reset_bind(dev); } -int sunxi_clk_probe(struct udevice *dev) +static int sunxi_clk_probe(struct udevice *dev) { struct ccu_priv *priv = dev_get_priv(dev); struct clk_bulk clk_bulk; @@ -97,3 +97,122 @@ int sunxi_clk_probe(struct udevice *dev) return 0; } + +extern const struct ccu_desc a10_ccu_desc; +extern const struct ccu_desc a10s_ccu_desc; +extern const struct ccu_desc a23_ccu_desc; +extern const struct ccu_desc a31_ccu_desc; +extern const struct ccu_desc a31_r_ccu_desc; +extern const struct ccu_desc a64_ccu_desc; +extern const struct ccu_desc a80_ccu_desc; +extern const struct ccu_desc a80_mmc_clk_desc; +extern const struct ccu_desc a83t_ccu_desc; +extern const struct ccu_desc f1c100s_ccu_desc; +extern const struct ccu_desc h3_ccu_desc; +extern const struct ccu_desc h6_ccu_desc; +extern const struct ccu_desc h616_ccu_desc; +extern const struct ccu_desc h6_r_ccu_desc; +extern const struct ccu_desc r40_ccu_desc; +extern const struct ccu_desc v3s_ccu_desc; + +static const struct udevice_id sunxi_clk_ids[] = { +#ifdef CONFIG_CLK_SUN4I_A10 + { .compatible = "allwinner,sun4i-a10-ccu", + .data = (ulong)&a10_ccu_desc }, +#endif +#ifdef CONFIG_CLK_SUN5I_A10S + { .compatible = "allwinner,sun5i-a10s-ccu", + .data = (ulong)&a10s_ccu_desc }, + { .compatible = "allwinner,sun5i-a13-ccu", + .data = (ulong)&a10s_ccu_desc }, +#endif +#ifdef CONFIG_CLK_SUN6I_A31 + { .compatible = "allwinner,sun6i-a31-ccu", + .data = (ulong)&a31_ccu_desc }, +#endif +#ifdef CONFIG_CLK_SUN4I_A10 + { .compatible = "allwinner,sun7i-a20-ccu", + .data = (ulong)&a10_ccu_desc }, +#endif +#ifdef CONFIG_CLK_SUN8I_A23 + { .compatible = "allwinner,sun8i-a23-ccu", + .data = (ulong)&a23_ccu_desc }, + { .compatible = "allwinner,sun8i-a33-ccu", + .data = (ulong)&a23_ccu_desc }, +#endif +#ifdef CONFIG_CLK_SUN8I_A83T + { .compatible = "allwinner,sun8i-a83t-ccu", + .data = (ulong)&a83t_ccu_desc }, +#endif +#ifdef CONFIG_CLK_SUN6I_A31_R + { .compatible = "allwinner,sun8i-a83t-r-ccu", + .data = (ulong)&a31_r_ccu_desc }, +#endif +#ifdef CONFIG_CLK_SUN8I_H3 + { .compatible = "allwinner,sun8i-h3-ccu", + .data = (ulong)&h3_ccu_desc }, +#endif +#ifdef CONFIG_CLK_SUN6I_A31_R + { .compatible = "allwinner,sun8i-h3-r-ccu", + .data = (ulong)&a31_r_ccu_desc }, +#endif +#ifdef CONFIG_CLK_SUN8I_R40 + { .compatible = "allwinner,sun8i-r40-ccu", + .data = (ulong)&r40_ccu_desc }, +#endif +#ifdef CONFIG_CLK_SUN8I_V3S + { .compatible = "allwinner,sun8i-v3-ccu", + .data = (ulong)&v3s_ccu_desc }, + { .compatible = "allwinner,sun8i-v3s-ccu", + .data = (ulong)&v3s_ccu_desc }, +#endif +#ifdef CONFIG_CLK_SUN9I_A80 + { .compatible = "allwinner,sun9i-a80-ccu", + .data = (ulong)&a80_ccu_desc }, + { .compatible = "allwinner,sun9i-a80-mmc-config-clk", + .data = (ulong)&a80_mmc_clk_desc }, +#endif +#ifdef CONFIG_CLK_SUN50I_A64 + { .compatible = "allwinner,sun50i-a64-ccu", + .data = (ulong)&a64_ccu_desc }, +#endif +#ifdef CONFIG_CLK_SUN6I_A31_R + { .compatible = "allwinner,sun50i-a64-r-ccu", + .data = (ulong)&a31_r_ccu_desc }, +#endif +#ifdef CONFIG_CLK_SUN8I_H3 + { .compatible = "allwinner,sun50i-h5-ccu", + .data = (ulong)&h3_ccu_desc }, +#endif +#ifdef CONFIG_CLK_SUN50I_H6 + { .compatible = "allwinner,sun50i-h6-ccu", + .data = (ulong)&h6_ccu_desc }, +#endif +#ifdef CONFIG_CLK_SUN50I_H6_R + { .compatible = "allwinner,sun50i-h6-r-ccu", + .data = (ulong)&h6_r_ccu_desc }, +#endif +#ifdef CONFIG_CLK_SUN50I_H616 + { .compatible = "allwinner,sun50i-h616-ccu", + .data = (ulong)&h616_ccu_desc }, +#endif +#ifdef CONFIG_CLK_SUN50I_H6_R + { .compatible = "allwinner,sun50i-h616-r-ccu", + .data = (ulong)&h6_r_ccu_desc }, +#endif +#ifdef CONFIG_CLK_SUNIV_F1C100S + { .compatible = "allwinner,suniv-f1c100s-ccu", + .data = (ulong)&f1c100s_ccu_desc }, +#endif + { } +}; + +U_BOOT_DRIVER(sunxi_clk) = { + .name = "sunxi_clk", + .id = UCLASS_CLK, + .of_match = sunxi_clk_ids, + .bind = sunxi_clk_bind, + .probe = sunxi_clk_probe, + .priv_auto = sizeof(struct ccu_priv), + .ops = &sunxi_clk_ops, +}; diff --git a/drivers/clk/sunxi/clk_v3s.c b/drivers/clk/sunxi/clk_v3s.c index 5b5afa6..f2fd11e 100644 --- a/drivers/clk/sunxi/clk_v3s.c +++ b/drivers/clk/sunxi/clk_v3s.c @@ -49,27 +49,9 @@ static struct ccu_reset v3s_resets[] = { [RST_BUS_UART2] = RESET(0x2d8, BIT(18)), }; -static const struct ccu_desc v3s_ccu_desc = { +const struct ccu_desc v3s_ccu_desc = { .gates = v3s_gates, .resets = v3s_resets, .num_gates = ARRAY_SIZE(v3s_gates), .num_resets = ARRAY_SIZE(v3s_resets), }; - -static const struct udevice_id v3s_clk_ids[] = { - { .compatible = "allwinner,sun8i-v3s-ccu", - .data = (ulong)&v3s_ccu_desc }, - { .compatible = "allwinner,sun8i-v3-ccu", - .data = (ulong)&v3s_ccu_desc }, - { } -}; - -U_BOOT_DRIVER(clk_sun8i_v3s) = { - .name = "sun8i_v3s_ccu", - .id = UCLASS_CLK, - .of_match = v3s_clk_ids, - .priv_auto = sizeof(struct ccu_priv), - .ops = &sunxi_clk_ops, - .probe = sunxi_clk_probe, - .bind = sunxi_clk_bind, -}; -- cgit v1.1 From 5af97b6ff74e3ce7312b3ef533c55f73430fb7d5 Mon Sep 17 00:00:00 2001 From: Samuel Holland Date: Mon, 9 May 2022 00:29:35 -0500 Subject: clk: sunxi: Convert driver private data to platform data All of the driver private data should really be platform data since it is determined statically (selected by the compatible string or extracted from the devicetree). Move everything to platform data, so it can be provided when binding the driver. This is useful for SPL, or for instantiating the driver as part of an MFD. Signed-off-by: Samuel Holland Reviewed-by: Andre Przywara Signed-off-by: Andre Przywara --- drivers/clk/sunxi/clk_sunxi.c | 41 ++++++++++++++++++++++++----------------- 1 file changed, 24 insertions(+), 17 deletions(-) (limited to 'drivers') diff --git a/drivers/clk/sunxi/clk_sunxi.c b/drivers/clk/sunxi/clk_sunxi.c index 8503c79..5b208c9 100644 --- a/drivers/clk/sunxi/clk_sunxi.c +++ b/drivers/clk/sunxi/clk_sunxi.c @@ -15,19 +15,19 @@ #include #include -static const struct ccu_clk_gate *priv_to_gate(struct ccu_priv *priv, +static const struct ccu_clk_gate *plat_to_gate(struct ccu_plat *plat, unsigned long id) { - if (id >= priv->desc->num_gates) + if (id >= plat->desc->num_gates) return NULL; - return &priv->desc->gates[id]; + return &plat->desc->gates[id]; } static int sunxi_set_gate(struct clk *clk, bool on) { - struct ccu_priv *priv = dev_get_priv(clk->dev); - const struct ccu_clk_gate *gate = priv_to_gate(priv, clk->id); + struct ccu_plat *plat = dev_get_plat(clk->dev); + const struct ccu_clk_gate *gate = plat_to_gate(plat, clk->id); u32 reg; if (gate && (gate->flags & CCU_CLK_F_DUMMY_GATE)) @@ -41,13 +41,13 @@ static int sunxi_set_gate(struct clk *clk, bool on) debug("%s: (CLK#%ld) off#0x%x, BIT(%d)\n", __func__, clk->id, gate->off, ilog2(gate->bit)); - reg = readl(priv->base + gate->off); + reg = readl(plat->base + gate->off); if (on) reg |= gate->bit; else reg &= ~gate->bit; - writel(reg, priv->base + gate->off); + writel(reg, plat->base + gate->off); return 0; } @@ -74,19 +74,10 @@ static int sunxi_clk_bind(struct udevice *dev) static int sunxi_clk_probe(struct udevice *dev) { - struct ccu_priv *priv = dev_get_priv(dev); struct clk_bulk clk_bulk; struct reset_ctl_bulk rst_bulk; int ret; - priv->base = dev_read_addr_ptr(dev); - if (!priv->base) - return -ENOMEM; - - priv->desc = (const struct ccu_desc *)dev_get_driver_data(dev); - if (!priv->desc) - return -EINVAL; - ret = clk_get_bulk(dev, &clk_bulk); if (!ret) clk_enable_bulk(&clk_bulk); @@ -98,6 +89,21 @@ static int sunxi_clk_probe(struct udevice *dev) return 0; } +static int sunxi_clk_of_to_plat(struct udevice *dev) +{ + struct ccu_plat *plat = dev_get_plat(dev); + + plat->base = dev_read_addr_ptr(dev); + if (!plat->base) + return -ENOMEM; + + plat->desc = (const struct ccu_desc *)dev_get_driver_data(dev); + if (!plat->desc) + return -EINVAL; + + return 0; +} + extern const struct ccu_desc a10_ccu_desc; extern const struct ccu_desc a10s_ccu_desc; extern const struct ccu_desc a23_ccu_desc; @@ -213,6 +219,7 @@ U_BOOT_DRIVER(sunxi_clk) = { .of_match = sunxi_clk_ids, .bind = sunxi_clk_bind, .probe = sunxi_clk_probe, - .priv_auto = sizeof(struct ccu_priv), + .of_to_plat = sunxi_clk_of_to_plat, + .plat_auto = sizeof(struct ccu_plat), .ops = &sunxi_clk_ops, }; -- cgit v1.1 From 3fb1988aad29185409a9e05a1111b7e2b7e5f8fc Mon Sep 17 00:00:00 2001 From: Samuel Holland Date: Mon, 9 May 2022 00:29:36 -0500 Subject: reset: sunxi: Convert driver private data to platform data The reason here is the same as the reason for changing the clock driver: platform data can be provided when binding the driver. Signed-off-by: Samuel Holland Reviewed-by: Andre Przywara Signed-off-by: Andre Przywara --- drivers/reset/reset-sunxi.c | 36 ++++++++++++++++++------------------ 1 file changed, 18 insertions(+), 18 deletions(-) (limited to 'drivers') diff --git a/drivers/reset/reset-sunxi.c b/drivers/reset/reset-sunxi.c index 621912a..f5c66dd 100644 --- a/drivers/reset/reset-sunxi.c +++ b/drivers/reset/reset-sunxi.c @@ -17,24 +17,24 @@ #include #include -struct sunxi_reset_priv { +struct sunxi_reset_plat { void *base; const struct ccu_desc *desc; }; -static const struct ccu_reset *priv_to_reset(struct sunxi_reset_priv *priv, +static const struct ccu_reset *plat_to_reset(struct sunxi_reset_plat *plat, unsigned long id) { - return &priv->desc->resets[id]; + return &plat->desc->resets[id]; } static int sunxi_reset_request(struct reset_ctl *reset_ctl) { - struct sunxi_reset_priv *priv = dev_get_priv(reset_ctl->dev); + struct sunxi_reset_plat *plat = dev_get_plat(reset_ctl->dev); debug("%s: (RST#%ld)\n", __func__, reset_ctl->id); - if (reset_ctl->id >= priv->desc->num_resets) + if (reset_ctl->id >= plat->desc->num_resets) return -EINVAL; return 0; @@ -42,8 +42,8 @@ static int sunxi_reset_request(struct reset_ctl *reset_ctl) static int sunxi_set_reset(struct reset_ctl *reset_ctl, bool on) { - struct sunxi_reset_priv *priv = dev_get_priv(reset_ctl->dev); - const struct ccu_reset *reset = priv_to_reset(priv, reset_ctl->id); + struct sunxi_reset_plat *plat = dev_get_plat(reset_ctl->dev); + const struct ccu_reset *reset = plat_to_reset(plat, reset_ctl->id); u32 reg; if (!(reset->flags & CCU_RST_F_IS_VALID)) { @@ -54,13 +54,13 @@ static int sunxi_set_reset(struct reset_ctl *reset_ctl, bool on) debug("%s: (RST#%ld) off#0x%x, BIT(%d)\n", __func__, reset_ctl->id, reset->off, ilog2(reset->bit)); - reg = readl(priv->base + reset->off); + reg = readl(plat->base + reset->off); if (on) reg |= reset->bit; else reg &= ~reset->bit; - writel(reg, priv->base + reset->off); + writel(reg, plat->base + reset->off); return 0; } @@ -81,11 +81,11 @@ struct reset_ops sunxi_reset_ops = { .rst_deassert = sunxi_reset_deassert, }; -static int sunxi_reset_probe(struct udevice *dev) +static int sunxi_reset_of_to_plat(struct udevice *dev) { - struct sunxi_reset_priv *priv = dev_get_priv(dev); + struct sunxi_reset_plat *plat = dev_get_plat(dev); - priv->base = dev_read_addr_ptr(dev); + plat->base = dev_read_addr_ptr(dev); return 0; } @@ -93,7 +93,7 @@ static int sunxi_reset_probe(struct udevice *dev) int sunxi_reset_bind(struct udevice *dev) { struct udevice *rst_dev; - struct sunxi_reset_priv *priv; + struct sunxi_reset_plat *plat; int ret; ret = device_bind_driver_to_node(dev, "sunxi_reset", "reset", @@ -102,9 +102,9 @@ int sunxi_reset_bind(struct udevice *dev) debug("failed to bind sunxi_reset driver (ret=%d)\n", ret); return ret; } - priv = malloc(sizeof(struct sunxi_reset_priv)); - priv->desc = (const struct ccu_desc *)dev_get_driver_data(dev); - dev_set_priv(rst_dev, priv); + plat = malloc(sizeof(struct sunxi_reset_plat)); + plat->desc = (const struct ccu_desc *)dev_get_driver_data(dev); + dev_set_plat(rst_dev, plat); return 0; } @@ -113,6 +113,6 @@ U_BOOT_DRIVER(sunxi_reset) = { .name = "sunxi_reset", .id = UCLASS_RESET, .ops = &sunxi_reset_ops, - .probe = sunxi_reset_probe, - .priv_auto = sizeof(struct sunxi_reset_priv), + .of_to_plat = sunxi_reset_of_to_plat, + .plat_auto = sizeof(struct sunxi_reset_plat), }; -- cgit v1.1 From 66391263f8484aae41cae80753f31c0edc6138af Mon Sep 17 00:00:00 2001 From: Samuel Holland Date: Mon, 9 May 2022 00:29:37 -0500 Subject: reset: sunxi: Reuse the platform data from the clock driver The clock and reset drivers use the exact same platform data. Simplify them by sharing the object. This is safe because the parent device (the clock device) always gets its driver model callbacks run first. Signed-off-by: Samuel Holland Acked-by: Andre Przywara Signed-off-by: Andre Przywara --- drivers/clk/sunxi/clk_sunxi.c | 7 ++++++- drivers/reset/reset-sunxi.c | 43 +++---------------------------------------- 2 files changed, 9 insertions(+), 41 deletions(-) (limited to 'drivers') diff --git a/drivers/clk/sunxi/clk_sunxi.c b/drivers/clk/sunxi/clk_sunxi.c index 5b208c9..ec02a2d 100644 --- a/drivers/clk/sunxi/clk_sunxi.c +++ b/drivers/clk/sunxi/clk_sunxi.c @@ -12,9 +12,12 @@ #include #include #include +#include #include #include +extern U_BOOT_DRIVER(sunxi_reset); + static const struct ccu_clk_gate *plat_to_gate(struct ccu_plat *plat, unsigned long id) { @@ -69,7 +72,9 @@ struct clk_ops sunxi_clk_ops = { static int sunxi_clk_bind(struct udevice *dev) { - return sunxi_reset_bind(dev); + /* Reuse the platform data for the reset driver. */ + return device_bind(dev, DM_DRIVER_REF(sunxi_reset), "reset", + dev_get_plat(dev), dev_ofnode(dev), NULL); } static int sunxi_clk_probe(struct udevice *dev) diff --git a/drivers/reset/reset-sunxi.c b/drivers/reset/reset-sunxi.c index f5c66dd..e484d1f 100644 --- a/drivers/reset/reset-sunxi.c +++ b/drivers/reset/reset-sunxi.c @@ -12,17 +12,10 @@ #include #include #include -#include -#include #include #include -struct sunxi_reset_plat { - void *base; - const struct ccu_desc *desc; -}; - -static const struct ccu_reset *plat_to_reset(struct sunxi_reset_plat *plat, +static const struct ccu_reset *plat_to_reset(struct ccu_plat *plat, unsigned long id) { return &plat->desc->resets[id]; @@ -30,7 +23,7 @@ static const struct ccu_reset *plat_to_reset(struct sunxi_reset_plat *plat, static int sunxi_reset_request(struct reset_ctl *reset_ctl) { - struct sunxi_reset_plat *plat = dev_get_plat(reset_ctl->dev); + struct ccu_plat *plat = dev_get_plat(reset_ctl->dev); debug("%s: (RST#%ld)\n", __func__, reset_ctl->id); @@ -42,7 +35,7 @@ static int sunxi_reset_request(struct reset_ctl *reset_ctl) static int sunxi_set_reset(struct reset_ctl *reset_ctl, bool on) { - struct sunxi_reset_plat *plat = dev_get_plat(reset_ctl->dev); + struct ccu_plat *plat = dev_get_plat(reset_ctl->dev); const struct ccu_reset *reset = plat_to_reset(plat, reset_ctl->id); u32 reg; @@ -81,38 +74,8 @@ struct reset_ops sunxi_reset_ops = { .rst_deassert = sunxi_reset_deassert, }; -static int sunxi_reset_of_to_plat(struct udevice *dev) -{ - struct sunxi_reset_plat *plat = dev_get_plat(dev); - - plat->base = dev_read_addr_ptr(dev); - - return 0; -} - -int sunxi_reset_bind(struct udevice *dev) -{ - struct udevice *rst_dev; - struct sunxi_reset_plat *plat; - int ret; - - ret = device_bind_driver_to_node(dev, "sunxi_reset", "reset", - dev_ofnode(dev), &rst_dev); - if (ret) { - debug("failed to bind sunxi_reset driver (ret=%d)\n", ret); - return ret; - } - plat = malloc(sizeof(struct sunxi_reset_plat)); - plat->desc = (const struct ccu_desc *)dev_get_driver_data(dev); - dev_set_plat(rst_dev, plat); - - return 0; -} - U_BOOT_DRIVER(sunxi_reset) = { .name = "sunxi_reset", .id = UCLASS_RESET, .ops = &sunxi_reset_ops, - .of_to_plat = sunxi_reset_of_to_plat, - .plat_auto = sizeof(struct sunxi_reset_plat), }; -- cgit v1.1 From 62ee043325a3f282ddb4e4a15c555b810f094b76 Mon Sep 17 00:00:00 2001 From: Samuel Holland Date: Fri, 15 Jul 2022 00:20:56 -0500 Subject: net: sun8i-emac: Downgrade printf during probe to debug This just prints the PHY mode taken from the devicetree. It does not need to be printed during every boot, and also avoids an unwanted line break for the "net: " reporting line. Signed-off-by: Samuel Holland Reviewed-by: Andre Przywara Signed-off-by: Andre Przywara --- drivers/net/sun8i_emac.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/net/sun8i_emac.c b/drivers/net/sun8i_emac.c index 2220f84..a4b3492 100644 --- a/drivers/net/sun8i_emac.c +++ b/drivers/net/sun8i_emac.c @@ -857,7 +857,7 @@ static int sun8i_emac_eth_of_to_plat(struct udevice *dev) priv->phyaddr = fdtdec_get_int(gd->fdt_blob, offset, "reg", -1); pdata->phy_interface = dev_read_phy_mode(dev); - printf("phy interface%d\n", pdata->phy_interface); + debug("phy interface %d\n", pdata->phy_interface); if (pdata->phy_interface == PHY_INTERFACE_MODE_NA) return -EINVAL; -- cgit v1.1 From 68655e6ce14c5eff8d0aad84dc40d7ca1d40c2e9 Mon Sep 17 00:00:00 2001 From: Samuel Holland Date: Fri, 15 Jul 2022 00:20:57 -0500 Subject: net: sun8i-emac: Drop use of arch-specific header This header is not used since commit abdbefba2a4e ("net: sun8i_emac: Use consistent clock bitfield definitions"). Dropping it allows the driver to be architecture-independent. Signed-off-by: Samuel Holland Reviewed-by: Andre Przywara Signed-off-by: Andre Przywara --- drivers/net/sun8i_emac.c | 1 - 1 file changed, 1 deletion(-) (limited to 'drivers') diff --git a/drivers/net/sun8i_emac.c b/drivers/net/sun8i_emac.c index a4b3492..9cca8fa 100644 --- a/drivers/net/sun8i_emac.c +++ b/drivers/net/sun8i_emac.c @@ -16,7 +16,6 @@ #include #include #include -#include #include #include #include -- cgit v1.1 From 56e497eba1bd13f93c50183d5c1cefff77f0933b Mon Sep 17 00:00:00 2001 From: Icenowy Zheng Date: Tue, 28 Jun 2022 14:49:24 +0800 Subject: spi: sunxi: use XCH status to detect in-progress transfer The current detection of RX FIFO depth seems to be not reliable, and XCH will self-clear when a transfer is done. Check XCH bit when polling for transfer finish. Signed-off-by: Icenowy Zheng Reviewed-by: Andre Przywara Signed-off-by: Andre Przywara --- drivers/spi/spi-sunxi.c | 14 +++++--------- 1 file changed, 5 insertions(+), 9 deletions(-) (limited to 'drivers') diff --git a/drivers/spi/spi-sunxi.c b/drivers/spi/spi-sunxi.c index b6cd7dd..adec18d 100644 --- a/drivers/spi/spi-sunxi.c +++ b/drivers/spi/spi-sunxi.c @@ -75,7 +75,7 @@ DECLARE_GLOBAL_DATA_PTR; #define SUN4I_SPI_MAX_RATE 24000000 #define SUN4I_SPI_MIN_RATE 3000 #define SUN4I_SPI_DEFAULT_RATE 1000000 -#define SUN4I_SPI_TIMEOUT_US 1000000 +#define SUN4I_SPI_TIMEOUT_MS 1000 #define SPI_REG(priv, reg) ((priv)->base + \ (priv)->variant->regs[reg]) @@ -262,7 +262,6 @@ static int sun4i_spi_xfer(struct udevice *dev, unsigned int bitlen, struct dm_spi_slave_plat *slave_plat = dev_get_parent_plat(dev); u32 len = bitlen / 8; - u32 rx_fifocnt; u8 nbytes; int ret; @@ -300,13 +299,10 @@ static int sun4i_spi_xfer(struct udevice *dev, unsigned int bitlen, setbits_le32(SPI_REG(priv, SPI_TCR), SPI_BIT(priv, SPI_TCR_XCH)); - /* Wait till RX FIFO to be empty */ - ret = readl_poll_timeout(SPI_REG(priv, SPI_FSR), - rx_fifocnt, - (((rx_fifocnt & - SPI_BIT(priv, SPI_FSR_RF_CNT_MASK)) >> - SUN4I_FIFO_STA_RF_CNT_BITS) >= nbytes), - SUN4I_SPI_TIMEOUT_US); + /* Wait for the transfer to be done */ + ret = wait_for_bit_le32((const void *)SPI_REG(priv, SPI_TCR), + SPI_BIT(priv, SPI_TCR_XCH), + false, SUN4I_SPI_TIMEOUT_MS, false); if (ret < 0) { printf("ERROR: sun4i_spi: Timeout transferring data\n"); sun4i_spi_set_cs(bus, slave_plat->cs, false); -- cgit v1.1 From 239dfd11764ac59a3f413c7f5d7575bcebd34228 Mon Sep 17 00:00:00 2001 From: Andre Przywara Date: Tue, 3 May 2022 00:07:16 +0100 Subject: spi: sunxi: refactor SPI speed/mode programming As George rightfully pointed out [1], the spi-sunxi driver programs the speed and mode settings only when the respective functions are called, but this gets lost over a call to release_bus(). That asserts the reset line, thus forces each SPI register back to its default value. Adding to that, trying to program SPI_CCR and SPI_TCR might be pointless in the first place, when the reset line is still asserted (before claim_bus()), so those setting won't apply most of the time. In reality I see two nested claim_bus() calls for the first use, so settings between the two would work (for instance for the initial "sf probe"). However later on the speed setting is not programmed into the hardware anymore. So far we get away with that default frequency, because that is a rather tame 24 MHz, which most SPI flash chips can handle just fine. Move the actual register programming into a separate function, and use .set_speed and .set_mode just to set the variables in our priv structure. Then we only call this new function in claim_bus(), when we are sure that register accesses actually work and are preserved. [1] https://lore.kernel.org/u-boot/20210725231636.879913-17-me@yifangu.com/ Signed-off-by: Andre Przywara Reported-by: George Hilliard --- drivers/spi/spi-sunxi.c | 95 +++++++++++++++++++++++++++---------------------- 1 file changed, 52 insertions(+), 43 deletions(-) (limited to 'drivers') diff --git a/drivers/spi/spi-sunxi.c b/drivers/spi/spi-sunxi.c index adec18d..5d7ca5b 100644 --- a/drivers/spi/spi-sunxi.c +++ b/drivers/spi/spi-sunxi.c @@ -221,6 +221,56 @@ err_ahb: return ret; } +static void sun4i_spi_set_speed_mode(struct udevice *dev) +{ + struct sun4i_spi_priv *priv = dev_get_priv(dev); + unsigned int div; + u32 reg; + + /* + * Setup clock divider. + * + * We have two choices there. Either we can use the clock + * divide rate 1, which is calculated thanks to this formula: + * SPI_CLK = MOD_CLK / (2 ^ (cdr + 1)) + * Or we can use CDR2, which is calculated with the formula: + * SPI_CLK = MOD_CLK / (2 * (cdr + 1)) + * Whether we use the former or the latter is set through the + * DRS bit. + * + * First try CDR2, and if we can't reach the expected + * frequency, fall back to CDR1. + */ + + div = SUN4I_SPI_MAX_RATE / (2 * priv->freq); + reg = readl(SPI_REG(priv, SPI_CCR)); + + if (div <= (SUN4I_CLK_CTL_CDR2_MASK + 1)) { + if (div > 0) + div--; + + reg &= ~(SUN4I_CLK_CTL_CDR2_MASK | SUN4I_CLK_CTL_DRS); + reg |= SUN4I_CLK_CTL_CDR2(div) | SUN4I_CLK_CTL_DRS; + } else { + div = __ilog2(SUN4I_SPI_MAX_RATE) - __ilog2(priv->freq); + reg &= ~((SUN4I_CLK_CTL_CDR1_MASK << 8) | SUN4I_CLK_CTL_DRS); + reg |= SUN4I_CLK_CTL_CDR1(div); + } + + writel(reg, SPI_REG(priv, SPI_CCR)); + + reg = readl(SPI_REG(priv, SPI_TCR)); + reg &= ~(SPI_BIT(priv, SPI_TCR_CPOL) | SPI_BIT(priv, SPI_TCR_CPHA)); + + if (priv->mode & SPI_CPOL) + reg |= SPI_BIT(priv, SPI_TCR_CPOL); + + if (priv->mode & SPI_CPHA) + reg |= SPI_BIT(priv, SPI_TCR_CPHA); + + writel(reg, SPI_REG(priv, SPI_TCR)); +} + static int sun4i_spi_claim_bus(struct udevice *dev) { struct sun4i_spi_priv *priv = dev_get_priv(dev->parent); @@ -240,6 +290,8 @@ static int sun4i_spi_claim_bus(struct udevice *dev) setbits_le32(SPI_REG(priv, SPI_TCR), SPI_BIT(priv, SPI_TCR_CS_MANUAL) | SPI_BIT(priv, SPI_TCR_CS_ACTIVE_LOW)); + sun4i_spi_set_speed_mode(dev->parent); + return 0; } @@ -325,46 +377,14 @@ static int sun4i_spi_set_speed(struct udevice *dev, uint speed) { struct sun4i_spi_plat *plat = dev_get_plat(dev); struct sun4i_spi_priv *priv = dev_get_priv(dev); - unsigned int div; - u32 reg; if (speed > plat->max_hz) speed = plat->max_hz; if (speed < SUN4I_SPI_MIN_RATE) speed = SUN4I_SPI_MIN_RATE; - /* - * Setup clock divider. - * - * We have two choices there. Either we can use the clock - * divide rate 1, which is calculated thanks to this formula: - * SPI_CLK = MOD_CLK / (2 ^ (cdr + 1)) - * Or we can use CDR2, which is calculated with the formula: - * SPI_CLK = MOD_CLK / (2 * (cdr + 1)) - * Whether we use the former or the latter is set through the - * DRS bit. - * - * First try CDR2, and if we can't reach the expected - * frequency, fall back to CDR1. - */ - - div = SUN4I_SPI_MAX_RATE / (2 * speed); - reg = readl(SPI_REG(priv, SPI_CCR)); - - if (div <= (SUN4I_CLK_CTL_CDR2_MASK + 1)) { - if (div > 0) - div--; - - reg &= ~(SUN4I_CLK_CTL_CDR2_MASK | SUN4I_CLK_CTL_DRS); - reg |= SUN4I_CLK_CTL_CDR2(div) | SUN4I_CLK_CTL_DRS; - } else { - div = __ilog2(SUN4I_SPI_MAX_RATE) - __ilog2(speed); - reg &= ~((SUN4I_CLK_CTL_CDR1_MASK << 8) | SUN4I_CLK_CTL_DRS); - reg |= SUN4I_CLK_CTL_CDR1(div); - } priv->freq = speed; - writel(reg, SPI_REG(priv, SPI_CCR)); return 0; } @@ -372,19 +392,8 @@ static int sun4i_spi_set_speed(struct udevice *dev, uint speed) static int sun4i_spi_set_mode(struct udevice *dev, uint mode) { struct sun4i_spi_priv *priv = dev_get_priv(dev); - u32 reg; - - reg = readl(SPI_REG(priv, SPI_TCR)); - reg &= ~(SPI_BIT(priv, SPI_TCR_CPOL) | SPI_BIT(priv, SPI_TCR_CPHA)); - - if (mode & SPI_CPOL) - reg |= SPI_BIT(priv, SPI_TCR_CPOL); - - if (mode & SPI_CPHA) - reg |= SPI_BIT(priv, SPI_TCR_CPHA); priv->mode = mode; - writel(reg, SPI_REG(priv, SPI_TCR)); return 0; } -- cgit v1.1 From fcd6d936aac7bd934d125135a71192e3a3da9b48 Mon Sep 17 00:00:00 2001 From: Andre Przywara Date: Tue, 3 May 2022 02:06:37 +0100 Subject: spi: sunxi: improve SPI clock calculation The current SPI clock divider calculation has two problems: - We use a normal round-down division, which results in a divider typically being too small, resulting in a too high frequency on the bus. - The calculaction for the power-of-two divider is very inaccurate, and again rounds down, which might lead to wild bus frequencies. This wasn't a real problem so far, since most chips can handle slightly higher bus frequencies just fine. Also the actual speed was mostly lost anyway, due to release_bus() reseting the device. And the power-of-2 calculation was probably never used, because it only applies to frequencies below 47 KHz. However this will become a problem for the F1C100s support, due to its much higher base frequency. Calculate a safe divider correctly (using round-up), and re-use that value when calculating the power-of-2 value. We also separate the maximum frequency and the input clock on the way, since they will be different for the F1C100s. Signed-off-by: Andre Przywara --- drivers/spi/spi-sunxi.c | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/spi/spi-sunxi.c b/drivers/spi/spi-sunxi.c index 5d7ca5b..6282949 100644 --- a/drivers/spi/spi-sunxi.c +++ b/drivers/spi/spi-sunxi.c @@ -72,7 +72,9 @@ DECLARE_GLOBAL_DATA_PTR; #define SUN4I_XMIT_CNT(cnt) ((cnt) & SUN4I_MAX_XFER_SIZE) #define SUN4I_FIFO_STA_RF_CNT_BITS 0 -#define SUN4I_SPI_MAX_RATE 24000000 +/* the SPI mod clock, defaulting to be 1/1 of the HOSC@24MHz */ +#define SUNXI_INPUT_CLOCK 24000000 /* 24 MHz */ +#define SUN4I_SPI_MAX_RATE SUNXI_INPUT_CLOCK #define SUN4I_SPI_MIN_RATE 3000 #define SUN4I_SPI_DEFAULT_RATE 1000000 #define SUN4I_SPI_TIMEOUT_MS 1000 @@ -242,17 +244,18 @@ static void sun4i_spi_set_speed_mode(struct udevice *dev) * frequency, fall back to CDR1. */ - div = SUN4I_SPI_MAX_RATE / (2 * priv->freq); + div = DIV_ROUND_UP(SUNXI_INPUT_CLOCK, priv->freq); reg = readl(SPI_REG(priv, SPI_CCR)); - if (div <= (SUN4I_CLK_CTL_CDR2_MASK + 1)) { + if ((div / 2) <= (SUN4I_CLK_CTL_CDR2_MASK + 1)) { + div /= 2; if (div > 0) div--; reg &= ~(SUN4I_CLK_CTL_CDR2_MASK | SUN4I_CLK_CTL_DRS); reg |= SUN4I_CLK_CTL_CDR2(div) | SUN4I_CLK_CTL_DRS; } else { - div = __ilog2(SUN4I_SPI_MAX_RATE) - __ilog2(priv->freq); + div = fls(div - 1); reg &= ~((SUN4I_CLK_CTL_CDR1_MASK << 8) | SUN4I_CLK_CTL_DRS); reg |= SUN4I_CLK_CTL_CDR1(div); } -- cgit v1.1 From 8649995c76bb38b9cbfd94169e41ce80c0d5f6ac Mon Sep 17 00:00:00 2001 From: Andre Przywara Date: Tue, 26 Apr 2022 23:58:53 +0100 Subject: spi: sunxi: Add support for F1C100s SPI controller The SPI controllers in the Allwinner F1Cx00 series of SoCs are compatible to the H3 IP. The only difference in the integration is the missing mod clock in the F1C100, instead the SPI clock is directly derived from the AHB clock. We *should* be able to model this through the DT, but the addition of get_rate() requires quite some refactoring, so it's not really worth in this simple case: We programmed both the PLL_PERIPH to 600 MHz and the PLL/AHB divider to 3 in the SPL, so we know the SPI base clock is 200 MHz. Since we used a hard coded fixed clock rate of 24 MHz for all the other SoCs so far, we can as well do the same for the F1C100. Define the SPI input clock and maximum frequency differently when compiling for the F1C100 SoC. Also adjust the power-of-2 divider programming, because that uses a "minus one" encoding, compared to the other SoCs. This allows to enable SPI flash support for the F1C100 boards. Signed-off-by: Andre Przywara --- drivers/spi/spi-sunxi.c | 9 +++++++++ 1 file changed, 9 insertions(+) (limited to 'drivers') diff --git a/drivers/spi/spi-sunxi.c b/drivers/spi/spi-sunxi.c index 6282949..c56d82d 100644 --- a/drivers/spi/spi-sunxi.c +++ b/drivers/spi/spi-sunxi.c @@ -72,9 +72,15 @@ DECLARE_GLOBAL_DATA_PTR; #define SUN4I_XMIT_CNT(cnt) ((cnt) & SUN4I_MAX_XFER_SIZE) #define SUN4I_FIFO_STA_RF_CNT_BITS 0 +#ifdef CONFIG_MACH_SUNIV +/* the AHB clock, which we programmed to be 1/3 of PLL_PERIPH@600MHz */ +#define SUNXI_INPUT_CLOCK 200000000 /* 200 MHz */ +#define SUN4I_SPI_MAX_RATE (SUNXI_INPUT_CLOCK / 2) +#else /* the SPI mod clock, defaulting to be 1/1 of the HOSC@24MHz */ #define SUNXI_INPUT_CLOCK 24000000 /* 24 MHz */ #define SUN4I_SPI_MAX_RATE SUNXI_INPUT_CLOCK +#endif #define SUN4I_SPI_MIN_RATE 3000 #define SUN4I_SPI_DEFAULT_RATE 1000000 #define SUN4I_SPI_TIMEOUT_MS 1000 @@ -256,6 +262,9 @@ static void sun4i_spi_set_speed_mode(struct udevice *dev) reg |= SUN4I_CLK_CTL_CDR2(div) | SUN4I_CLK_CTL_DRS; } else { div = fls(div - 1); + /* The F1C100s encodes the divider as 2^(n+1) */ + if (IS_ENABLED(CONFIG_MACH_SUNIV)) + div--; reg &= ~((SUN4I_CLK_CTL_CDR1_MASK << 8) | SUN4I_CLK_CTL_DRS); reg |= SUN4I_CLK_CTL_CDR1(div); } -- cgit v1.1 From 5fd30ed78539e11c2c155001a88f483441a96ebd Mon Sep 17 00:00:00 2001 From: Markus Hoffrogge Date: Thu, 30 Jun 2022 01:26:39 +0200 Subject: sunxi-nand: fix the PIO instead of DMA implementation The sunxi nand SPL loader was broken at least for SUN4I, SUN5I and SUN7I SOCs since the implementation change from DMA to PIO usage - commit 6ddbb1e. Root cause for this issue is the NFC control flag NFC_CTL_RAM_METHOD being set by method nand_apply_config. This flag controls the bus being used for the NFCs internal RAM access. It must be set for the DMA use case only. See A33_Nand_Flash_Controller_Specification.pdf page 12. This fix is tested by myself on a Cubietruck A20 board. Others should test it on new generation SOCs as well. Signed-off-by: Markus Hoffrogge Reviewed-by: Andre Przywara Signed-off-by: Andre Przywara --- drivers/mtd/nand/raw/sunxi_nand_spl.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/mtd/nand/raw/sunxi_nand_spl.c b/drivers/mtd/nand/raw/sunxi_nand_spl.c index a29a76c..6de0b0a 100644 --- a/drivers/mtd/nand/raw/sunxi_nand_spl.c +++ b/drivers/mtd/nand/raw/sunxi_nand_spl.c @@ -208,7 +208,7 @@ static void nand_apply_config(const struct nfc_config *conf) val = readl(SUNXI_NFC_BASE + NFC_CTL); val &= ~NFC_CTL_PAGE_SIZE_MASK; - writel(val | NFC_CTL_RAM_METHOD | NFC_CTL_PAGE_SIZE(conf->page_size), + writel(val | NFC_CTL_PAGE_SIZE(conf->page_size), SUNXI_NFC_BASE + NFC_CTL); writel(conf->ecc_size, SUNXI_NFC_BASE + NFC_CNT); writel(conf->page_size, SUNXI_NFC_BASE + NFC_SPARE_AREA); -- cgit v1.1 From a35628ec33a12032b82cc7be58f8b41c7ab0a4b2 Mon Sep 17 00:00:00 2001 From: Samuel Holland Date: Thu, 14 Jul 2022 23:09:19 -0500 Subject: sunxi: Move INITIAL_USB_SCAN_DELAY to driver Kconfig This option is used only by the phy-sun4i-usb driver, which does not inherently depend on the ARM architecture. Signed-off-by: Samuel Holland Reviewed-by: Jagan Teki Signed-off-by: Andre Przywara --- drivers/phy/allwinner/Kconfig | 10 ++++++++++ 1 file changed, 10 insertions(+) (limited to 'drivers') diff --git a/drivers/phy/allwinner/Kconfig b/drivers/phy/allwinner/Kconfig index d3ff82f..f8f1e99 100644 --- a/drivers/phy/allwinner/Kconfig +++ b/drivers/phy/allwinner/Kconfig @@ -13,6 +13,16 @@ config PHY_SUN4I_USB This driver controls the entire USB PHY block, both the USB OTG parts, as well as the 2 regular USB 2 host PHYs. +config INITIAL_USB_SCAN_DELAY + int "Delay initial USB scan by x ms to allow builtin devices to init" + depends on PHY_SUN4I_USB + default 0 + help + Some boards have on board usb devices which need longer than + the USB spec's 1 second to connect from board powerup. Set + this option to a nonzero value to add an extra delay before + the first USB bus scan. + config PHY_SUN50I_USB3 bool "Allwinner sun50i USB3 PHY driver" depends on ARCH_SUNXI -- cgit v1.1 From 64331352cb75b722df848ff11449737fa78204b3 Mon Sep 17 00:00:00 2001 From: Samuel Holland Date: Thu, 14 Jul 2022 23:09:20 -0500 Subject: phy: sun4i-usb: Drop use of arch-specific headers Since commit 089ffd0aedb7 ("phy: sun4i-usb: Use CLK and RESET support") neither of these headers is used. Dropping them allows the driver to be architecture-independent. Signed-off-by: Samuel Holland Reviewed-by: Jagan Teki Signed-off-by: Andre Przywara --- drivers/phy/allwinner/phy-sun4i-usb.c | 2 -- 1 file changed, 2 deletions(-) (limited to 'drivers') diff --git a/drivers/phy/allwinner/phy-sun4i-usb.c b/drivers/phy/allwinner/phy-sun4i-usb.c index aef2cb8..6a965e7 100644 --- a/drivers/phy/allwinner/phy-sun4i-usb.c +++ b/drivers/phy/allwinner/phy-sun4i-usb.c @@ -20,8 +20,6 @@ #include #include #include -#include -#include #include #include #include -- cgit v1.1 From b33ee49ac10ce2e400d171c1018db2359b25fb96 Mon Sep 17 00:00:00 2001 From: Andre Przywara Date: Thu, 14 Jul 2022 23:09:21 -0500 Subject: phy: sun4i-usb: Rework HCI PHY (aka "pmu_unk1") handling As Icenowy pointed out, newer manuals (starting with H6) actually document the register block at offset 0x800 as "HCI controller and PHY interface", also describe the bits in our "PMU_UNK1" register. Let's put proper names to those "unknown" variables and symbols. While we are at it, generalise the existing code by allowing a bitmap of bits to clear and set, to cover newer SoCs: The A100 and H616 use a different bit for the SIDDQ control. Signed-off-by: Andre Przywara Signed-off-by: Samuel Holland Reviewed-by: Jagan Teki --- drivers/phy/allwinner/phy-sun4i-usb.c | 32 ++++++++++++++------------------ 1 file changed, 14 insertions(+), 18 deletions(-) (limited to 'drivers') diff --git a/drivers/phy/allwinner/phy-sun4i-usb.c b/drivers/phy/allwinner/phy-sun4i-usb.c index 6a965e7..73e660e 100644 --- a/drivers/phy/allwinner/phy-sun4i-usb.c +++ b/drivers/phy/allwinner/phy-sun4i-usb.c @@ -32,7 +32,8 @@ #define REG_PHYTUNE 0x0c #define REG_PHYCTL_A33 0x10 #define REG_PHY_OTGCTL 0x20 -#define REG_PMU_UNK1 0x10 + +#define REG_HCI_PHY_CTL 0x10 /* Common Control Bits for Both PHYs */ #define PHY_PLL_BW 0x03 @@ -63,6 +64,7 @@ /* A83T specific control bits for PHY0 */ #define PHY_CTL_VBUSVLDEXT BIT(5) #define PHY_CTL_SIDDQ BIT(3) +#define PHY_CTL_H3_SIDDQ BIT(1) /* A83T specific control bits for PHY2 HSIC */ #define SUNXI_EHCI_HS_FORCE BIT(20) @@ -87,9 +89,9 @@ struct sun4i_usb_phy_cfg { int num_phys; enum sun4i_usb_phy_type type; u32 disc_thresh; + u32 hci_phy_ctl_clear; u8 phyctl_offset; bool dedicated_clocks; - bool enable_pmu_unk1; bool phy0_dual_route; int missing_phys; }; @@ -275,6 +277,12 @@ static int sun4i_usb_phy_init(struct phy *phy) return ret; } + if (usb_phy->pmu && data->cfg->hci_phy_ctl_clear) { + val = readl(usb_phy->pmu + REG_HCI_PHY_CTL); + val &= ~data->cfg->hci_phy_ctl_clear; + writel(val, usb_phy->pmu + REG_HCI_PHY_CTL); + } + if (data->cfg->type == sun8i_a83t_phy || data->cfg->type == sun50i_h6_phy) { if (phy->id == 0) { @@ -284,11 +292,6 @@ static int sun4i_usb_phy_init(struct phy *phy) writel(val, data->base + data->cfg->phyctl_offset); } } else { - if (usb_phy->pmu && data->cfg->enable_pmu_unk1) { - val = readl(usb_phy->pmu + REG_PMU_UNK1); - writel(val & ~2, usb_phy->pmu + REG_PMU_UNK1); - } - if (usb_phy->id == 0) sun4i_usb_phy_write(phy, PHY_RES45_CAL_EN, PHY_RES45_CAL_DATA, @@ -528,7 +531,6 @@ static const struct sun4i_usb_phy_cfg sun4i_a10_cfg = { .disc_thresh = 3, .phyctl_offset = REG_PHYCTL_A10, .dedicated_clocks = false, - .enable_pmu_unk1 = false, }; static const struct sun4i_usb_phy_cfg sun5i_a13_cfg = { @@ -537,7 +539,6 @@ static const struct sun4i_usb_phy_cfg sun5i_a13_cfg = { .disc_thresh = 2, .phyctl_offset = REG_PHYCTL_A10, .dedicated_clocks = false, - .enable_pmu_unk1 = false, }; static const struct sun4i_usb_phy_cfg sun6i_a31_cfg = { @@ -546,7 +547,6 @@ static const struct sun4i_usb_phy_cfg sun6i_a31_cfg = { .disc_thresh = 3, .phyctl_offset = REG_PHYCTL_A10, .dedicated_clocks = true, - .enable_pmu_unk1 = false, }; static const struct sun4i_usb_phy_cfg sun7i_a20_cfg = { @@ -555,7 +555,6 @@ static const struct sun4i_usb_phy_cfg sun7i_a20_cfg = { .disc_thresh = 2, .phyctl_offset = REG_PHYCTL_A10, .dedicated_clocks = false, - .enable_pmu_unk1 = false, }; static const struct sun4i_usb_phy_cfg sun8i_a23_cfg = { @@ -564,7 +563,6 @@ static const struct sun4i_usb_phy_cfg sun8i_a23_cfg = { .disc_thresh = 3, .phyctl_offset = REG_PHYCTL_A10, .dedicated_clocks = true, - .enable_pmu_unk1 = false, }; static const struct sun4i_usb_phy_cfg sun8i_a33_cfg = { @@ -573,7 +571,6 @@ static const struct sun4i_usb_phy_cfg sun8i_a33_cfg = { .disc_thresh = 3, .phyctl_offset = REG_PHYCTL_A33, .dedicated_clocks = true, - .enable_pmu_unk1 = false, }; static const struct sun4i_usb_phy_cfg sun8i_a83t_cfg = { @@ -589,7 +586,7 @@ static const struct sun4i_usb_phy_cfg sun8i_h3_cfg = { .disc_thresh = 3, .phyctl_offset = REG_PHYCTL_A33, .dedicated_clocks = true, - .enable_pmu_unk1 = true, + .hci_phy_ctl_clear = PHY_CTL_H3_SIDDQ, .phy0_dual_route = true, }; @@ -599,7 +596,7 @@ static const struct sun4i_usb_phy_cfg sun8i_r40_cfg = { .disc_thresh = 3, .phyctl_offset = REG_PHYCTL_A33, .dedicated_clocks = true, - .enable_pmu_unk1 = true, + .hci_phy_ctl_clear = PHY_CTL_H3_SIDDQ, .phy0_dual_route = true, }; @@ -609,7 +606,7 @@ static const struct sun4i_usb_phy_cfg sun8i_v3s_cfg = { .disc_thresh = 3, .phyctl_offset = REG_PHYCTL_A33, .dedicated_clocks = true, - .enable_pmu_unk1 = true, + .hci_phy_ctl_clear = PHY_CTL_H3_SIDDQ, .phy0_dual_route = true, }; @@ -619,7 +616,7 @@ static const struct sun4i_usb_phy_cfg sun50i_a64_cfg = { .disc_thresh = 3, .phyctl_offset = REG_PHYCTL_A33, .dedicated_clocks = true, - .enable_pmu_unk1 = true, + .hci_phy_ctl_clear = PHY_CTL_H3_SIDDQ, .phy0_dual_route = true, }; @@ -629,7 +626,6 @@ static const struct sun4i_usb_phy_cfg sun50i_h6_cfg = { .disc_thresh = 3, .phyctl_offset = REG_PHYCTL_A33, .dedicated_clocks = true, - .enable_pmu_unk1 = true, .phy0_dual_route = true, .missing_phys = BIT(1) | BIT(2), }; -- cgit v1.1 From 25ba5be1c2b6324917254f0c22df1ad9d3d3c9e7 Mon Sep 17 00:00:00 2001 From: Samuel Holland Date: Thu, 14 Jul 2022 23:09:22 -0500 Subject: phy: sun4i-usb: Add D1 variant D1 has a register layout like A100 and H616, with the moved SIDDQ bit. Unlike H616 it does not have any dependencies between PHY instances. Signed-off-by: Samuel Holland Reviewed-by: Jagan Teki Signed-off-by: Andre Przywara --- drivers/phy/allwinner/phy-sun4i-usb.c | 10 ++++++++++ 1 file changed, 10 insertions(+) (limited to 'drivers') diff --git a/drivers/phy/allwinner/phy-sun4i-usb.c b/drivers/phy/allwinner/phy-sun4i-usb.c index 73e660e..2e969ab 100644 --- a/drivers/phy/allwinner/phy-sun4i-usb.c +++ b/drivers/phy/allwinner/phy-sun4i-usb.c @@ -610,6 +610,15 @@ static const struct sun4i_usb_phy_cfg sun8i_v3s_cfg = { .phy0_dual_route = true, }; +static const struct sun4i_usb_phy_cfg sun20i_d1_cfg = { + .num_phys = 2, + .type = sun50i_h6_phy, + .phyctl_offset = REG_PHYCTL_A33, + .dedicated_clocks = true, + .hci_phy_ctl_clear = PHY_CTL_SIDDQ, + .phy0_dual_route = true, +}; + static const struct sun4i_usb_phy_cfg sun50i_a64_cfg = { .num_phys = 2, .type = sun50i_a64_phy, @@ -641,6 +650,7 @@ static const struct udevice_id sun4i_usb_phy_ids[] = { { .compatible = "allwinner,sun8i-h3-usb-phy", .data = (ulong)&sun8i_h3_cfg }, { .compatible = "allwinner,sun8i-r40-usb-phy", .data = (ulong)&sun8i_r40_cfg }, { .compatible = "allwinner,sun8i-v3s-usb-phy", .data = (ulong)&sun8i_v3s_cfg }, + { .compatible = "allwinner,sun20i-d1-usb-phy", .data = (ulong)&sun20i_d1_cfg }, { .compatible = "allwinner,sun50i-a64-usb-phy", .data = (ulong)&sun50i_a64_cfg}, { .compatible = "allwinner,sun50i-h6-usb-phy", .data = (ulong)&sun50i_h6_cfg}, { } -- cgit v1.1