* [PATCH 1/8] clk: sunxi-ng: h6: Fix clock divider range on some clocks
[not found] <20201202135409.13683-1-andre.przywara@arm.com>
@ 2020-12-02 13:54 ` Andre Przywara
2020-12-02 16:17 ` Jernej Škrabec
2020-12-02 13:54 ` [PATCH 4/8] clk: sunxi-ng: Add support for the Allwinner H616 R-CCU Andre Przywara
2020-12-02 13:54 ` [PATCH 5/8] clk: sunxi-ng: Add support for the Allwinner H616 CCU Andre Przywara
2 siblings, 1 reply; 20+ messages in thread
From: Andre Przywara @ 2020-12-02 13:54 UTC (permalink / raw)
To: Maxime Ripard, Chen-Yu Tsai, Jernej Skrabec
Cc: Icenowy Zheng, linux-arm-kernel, linux-sunxi, Linus Walleij,
Rob Herring, Yangtao Li, linux-kernel, Michael Turquette,
Stephen Boyd, linux-clk, Andre Przywara
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 <andre.przywara@arm.com>
---
drivers/clk/sunxi-ng/ccu-sun50i-h6.c | 8 ++++----
1 file changed, 4 insertions(+), 4 deletions(-)
diff --git a/drivers/clk/sunxi-ng/ccu-sun50i-h6.c b/drivers/clk/sunxi-ng/ccu-sun50i-h6.c
index f2497d0a4683..d0565d378ea2 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);
--
2.17.5
^ permalink raw reply related [flat|nested] 20+ messages in thread
* [PATCH 4/8] clk: sunxi-ng: Add support for the Allwinner H616 R-CCU
[not found] <20201202135409.13683-1-andre.przywara@arm.com>
2020-12-02 13:54 ` [PATCH 1/8] clk: sunxi-ng: h6: Fix clock divider range on some clocks Andre Przywara
@ 2020-12-02 13:54 ` Andre Przywara
2020-12-02 14:31 ` Icenowy Zheng
2020-12-02 18:20 ` Jernej Škrabec
2020-12-02 13:54 ` [PATCH 5/8] clk: sunxi-ng: Add support for the Allwinner H616 CCU Andre Przywara
2 siblings, 2 replies; 20+ messages in thread
From: Andre Przywara @ 2020-12-02 13:54 UTC (permalink / raw)
To: Maxime Ripard, Chen-Yu Tsai, Jernej Skrabec
Cc: Icenowy Zheng, linux-arm-kernel, linux-sunxi, Linus Walleij,
Rob Herring, Yangtao Li, linux-kernel, Michael Turquette,
Stephen Boyd, Philipp Zabel, linux-clk, Andre Przywara
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 <andre.przywara@arm.com>
---
drivers/clk/sunxi-ng/ccu-sun50i-h6-r.c | 47 +++++++++++++++++++++++++-
drivers/clk/sunxi-ng/ccu-sun50i-h6-r.h | 3 +-
2 files changed, 48 insertions(+), 2 deletions(-)
diff --git a/drivers/clk/sunxi-ng/ccu-sun50i-h6-r.c b/drivers/clk/sunxi-ng/ccu-sun50i-h6-r.c
index 50f8d1bc7046..119d1797f501 100644
--- a/drivers/clk/sunxi-ng/ccu-sun50i-h6-r.c
+++ b/drivers/clk/sunxi-ng/ccu-sun50i-h6-r.c
@@ -136,6 +136,15 @@ 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_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,
@@ -152,7 +161,20 @@ static struct clk_hw_onecell_data sun50i_h6_r_hw_clks = {
[CLK_IR] = &ir_clk.common.hw,
[CLK_W1] = &w1_clk.common.hw,
},
- .num = CLK_NUMBER,
+ .num = CLK_NUMBER_H616,
+};
+
+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_APB1_IR] = &r_apb1_ir_clk.common.hw,
+ [CLK_IR] = &ir_clk.common.hw,
+ },
+ .num = CLK_NUMBER_H616,
};
static struct ccu_reset_map sun50i_h6_r_ccu_resets[] = {
@@ -165,6 +187,12 @@ 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_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),
@@ -175,6 +203,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)
{
@@ -195,3 +233,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);
diff --git a/drivers/clk/sunxi-ng/ccu-sun50i-h6-r.h b/drivers/clk/sunxi-ng/ccu-sun50i-h6-r.h
index 782117dc0b28..128302696ca1 100644
--- a/drivers/clk/sunxi-ng/ccu-sun50i-h6-r.h
+++ b/drivers/clk/sunxi-ng/ccu-sun50i-h6-r.h
@@ -14,6 +14,7 @@
#define CLK_R_APB2 3
-#define CLK_NUMBER (CLK_W1 + 1)
+#define CLK_NUMBER_H6 (CLK_W1 + 1)
+#define CLK_NUMBER_H616 (CLK_IR + 1)
#endif /* _CCU_SUN50I_H6_R_H */
--
2.17.5
^ permalink raw reply related [flat|nested] 20+ messages in thread
* [PATCH 5/8] clk: sunxi-ng: Add support for the Allwinner H616 CCU
[not found] <20201202135409.13683-1-andre.przywara@arm.com>
2020-12-02 13:54 ` [PATCH 1/8] clk: sunxi-ng: h6: Fix clock divider range on some clocks Andre Przywara
2020-12-02 13:54 ` [PATCH 4/8] clk: sunxi-ng: Add support for the Allwinner H616 R-CCU Andre Przywara
@ 2020-12-02 13:54 ` Andre Przywara
2020-12-02 15:56 ` Maxime Ripard
` (3 more replies)
2 siblings, 4 replies; 20+ messages in thread
From: Andre Przywara @ 2020-12-02 13:54 UTC (permalink / raw)
To: Maxime Ripard, Chen-Yu Tsai, Jernej Skrabec
Cc: Icenowy Zheng, linux-arm-kernel, linux-sunxi, Linus Walleij,
Rob Herring, Yangtao Li, linux-kernel, Michael Turquette,
Stephen Boyd, Philipp Zabel, linux-clk, Andre Przywara
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 <andre.przywara@arm.com>
---
drivers/clk/sunxi-ng/Kconfig | 7 +-
drivers/clk/sunxi-ng/Makefile | 1 +
drivers/clk/sunxi-ng/ccu-sun50i-h616.c | 1134 +++++++++++++++++++
drivers/clk/sunxi-ng/ccu-sun50i-h616.h | 58 +
include/dt-bindings/clock/sun50i-h616-ccu.h | 110 ++
include/dt-bindings/reset/sun50i-h616-ccu.h | 67 ++
6 files changed, 1376 insertions(+), 1 deletion(-)
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
diff --git a/drivers/clk/sunxi-ng/Kconfig b/drivers/clk/sunxi-ng/Kconfig
index ce5f5847d5d3..cd46d8853876 100644
--- a/drivers/clk/sunxi-ng/Kconfig
+++ b/drivers/clk/sunxi-ng/Kconfig
@@ -32,8 +32,13 @@ 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 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/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..3fbb258f0354
--- /dev/null
+++ b/drivers/clk/sunxi-ng/ccu-sun50i-h616.c
@@ -0,0 +1,1134 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (c) 2020 Arm Ltd.
+ * Based on the H6 CCU driver, which is:
+ * Copyright (c) 2017 Icenowy Zheng <icenowy@aosc.io>
+ */
+
+#include <linux/clk-provider.h>
+#include <linux/io.h>
+#include <linux/of_address.h>
+#include <linux/platform_device.h>
+
+#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 = 4,
+ .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 = 4,
+ .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, 3, /* 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 2 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", "osc12M", 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 struct clk_fixed_factor pll_periph0_4x_clk;
+
+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),
+
+ .mux = {
+ .shift = 24,
+ .width = 2,
+
+ .fixed_predivs = hdmi_cec_predivs,
+ .n_predivs = ARRAY_SIZE(hdmi_cec_predivs),
+ },
+
+ .common = {
+ .reg = 0xb10,
+ .features = CCU_FEATURE_VARIABLE_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_tv0_parents[] = { "pll-video0",
+ "pll-video0-4x",
+ "pll-video1",
+ "pll-video1-4x" };
+static SUNXI_CCU_MP_WITH_MUX_GATE(tcon_tv0_clk, "tcon-tv0",
+ tcon_tv0_parents, 0xb80,
+ 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 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_4x_clk, "pll-periph0-4x",
+ pll_periph0_parents,
+ 1, 4, 0);
+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_4x_clk, "pll-periph1-4x",
+ pll_periph1_parents,
+ 1, 4, 0);
+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,
+ &bus_tcon_tv0_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_PERIPH0_4X] = &pll_periph0_4x_clk.hw,
+ [CLK_PLL_PERIPH1] = &pll_periph1_clk.common.hw,
+ [CLK_PLL_PERIPH1_2X] = &pll_periph1_2x_clk.hw,
+ [CLK_PLL_PERIPH1_4X] = &pll_periph1_4x_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_BUS_TCON_TV0] = &bus_tcon_tv0_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_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 int sun50i_h616_ccu_probe(struct platform_device *pdev)
+{
+ struct resource *res;
+ void __iomem *reg;
+ u32 val;
+ int i;
+
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ reg = devm_ioremap_resource(&pdev->dev, res);
+ if (IS_ERR(reg))
+ return PTR_ERR(reg);
+
+ /* Enable the lock bits on all PLLs */
+ for (i = 0; i < ARRAY_SIZE(pll_regs); i++) {
+ val = readl(reg + pll_regs[i]);
+ val |= BIT(29);
+ 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);
+
+ return sunxi_ccu_probe(pdev->dev.of_node, reg, &sun50i_h616_ccu_desc);
+}
+
+static const struct of_device_id sun50i_h616_ccu_ids[] = {
+ { .compatible = "allwinner,sun50i-h616-ccu",
+ .data = &sun50i_h616_ccu_desc },
+ { }
+};
+
+static struct platform_driver sun50i_h616_ccu_driver = {
+ .probe = sun50i_h616_ccu_probe,
+ .driver = {
+ .name = "sun50i-h616-ccu",
+ .of_match_table = sun50i_h616_ccu_ids,
+ },
+};
+builtin_platform_driver(sun50i_h616_ccu_driver);
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..da8f0b1206f9
--- /dev/null
+++ b/drivers/clk/sunxi-ng/ccu-sun50i-h616.h
@@ -0,0 +1,58 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright 2020 Arm Ltd.
+ */
+
+#ifndef _CCU_SUN50I_H616_H_
+#define _CCU_SUN50I_H616_H_
+
+#include <dt-bindings/clock/sun50i-h616-ccu.h>
+#include <dt-bindings/reset/sun50i-h616-ccu.h>
+
+#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_PERIPH0_4X 6
+#define CLK_PLL_PERIPH1 7
+#define CLK_PLL_PERIPH1_2X 8
+#define CLK_PLL_PERIPH1_4X 9
+#define CLK_PLL_GPU 10
+#define CLK_PLL_VIDEO0 11
+#define CLK_PLL_VIDEO0_4X 12
+#define CLK_PLL_VIDEO1 13
+#define CLK_PLL_VIDEO1_4X 14
+#define CLK_PLL_VIDEO2 15
+#define CLK_PLL_VIDEO2_4X 16
+#define CLK_PLL_VE 17
+#define CLK_PLL_DE 18
+#define CLK_PLL_AUDIO_HS 19
+#define CLK_PLL_AUDIO_1X 20
+#define CLK_PLL_AUDIO_2X 21
+#define CLK_PLL_AUDIO_4X 22
+
+/* CPUX clock exported for DVFS */
+
+#define CLK_AXI 24
+#define CLK_CPUX_APB 25
+#define CLK_PSI_AHB1_AHB2 26
+#define CLK_AHB3 27
+
+/* APB1 clock exported for PIO */
+
+#define CLK_APB2 29
+#define CLK_MBUS 30
+
+/* All module clocks and bus gates are exported except DRAM */
+
+#define CLK_DRAM 51
+
+#define CLK_BUS_DRAM 58
+
+#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..a9cc8844e3a9
--- /dev/null
+++ b/include/dt-bindings/clock/sun50i-h616-ccu.h
@@ -0,0 +1,110 @@
+// 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 23
+
+#define CLK_APB1 28
+
+#define CLK_DE 31
+#define CLK_BUS_DE 32
+#define CLK_DEINTERLACE 33
+#define CLK_BUS_DEINTERLACE 34
+#define CLK_G2D 35
+#define CLK_BUS_G2D 36
+#define CLK_GPU0 37
+#define CLK_BUS_GPU 38
+#define CLK_GPU1 39
+#define CLK_CE 40
+#define CLK_BUS_CE 41
+#define CLK_VE 42
+#define CLK_BUS_VE 43
+#define CLK_BUS_DMA 44
+#define CLK_BUS_HSTIMER 45
+#define CLK_AVS 46
+#define CLK_BUS_DBG 47
+#define CLK_BUS_PSI 48
+#define CLK_BUS_PWM 49
+#define CLK_BUS_IOMMU 50
+
+#define CLK_MBUS_DMA 52
+#define CLK_MBUS_VE 53
+#define CLK_MBUS_CE 54
+#define CLK_MBUS_TS 55
+#define CLK_MBUS_NAND 56
+#define CLK_MBUS_G2D 57
+
+#define CLK_NAND0 59
+#define CLK_NAND1 60
+#define CLK_BUS_NAND 61
+#define CLK_MMC0 62
+#define CLK_MMC1 63
+#define CLK_MMC2 64
+#define CLK_BUS_MMC0 65
+#define CLK_BUS_MMC1 66
+#define CLK_BUS_MMC2 67
+#define CLK_BUS_UART0 68
+#define CLK_BUS_UART1 69
+#define CLK_BUS_UART2 70
+#define CLK_BUS_UART3 71
+#define CLK_BUS_UART4 72
+#define CLK_BUS_UART5 73
+#define CLK_BUS_I2C0 74
+#define CLK_BUS_I2C1 75
+#define CLK_BUS_I2C2 76
+#define CLK_BUS_I2C3 77
+#define CLK_BUS_I2C4 78
+#define CLK_SPI0 79
+#define CLK_SPI1 80
+#define CLK_BUS_SPI0 81
+#define CLK_BUS_SPI1 82
+#define CLK_EMAC_25M 83
+#define CLK_BUS_EMAC0 84
+#define CLK_BUS_EMAC1 85
+#define CLK_TS 86
+#define CLK_BUS_TS 87
+#define CLK_BUS_THS 88
+#define CLK_SPDIF 89
+#define CLK_BUS_SPDIF 90
+#define CLK_DMIC 91
+#define CLK_BUS_DMIC 92
+#define CLK_AUDIO_CODEC_1X 93
+#define CLK_AUDIO_CODEC_4X 94
+#define CLK_BUS_AUDIO_CODEC 95
+#define CLK_AUDIO_HUB 96
+#define CLK_BUS_AUDIO_HUB 97
+#define CLK_USB_OHCI0 98
+#define CLK_USB_PHY0 99
+#define CLK_USB_OHCI1 100
+#define CLK_USB_PHY1 101
+#define CLK_USB_OHCI2 102
+#define CLK_USB_PHY2 103
+#define CLK_USB_OHCI3 104
+#define CLK_USB_PHY3 105
+#define CLK_BUS_OHCI0 106
+#define CLK_BUS_OHCI1 107
+#define CLK_BUS_OHCI2 108
+#define CLK_BUS_OHCI3 109
+#define CLK_BUS_EHCI0 110
+#define CLK_BUS_EHCI1 111
+#define CLK_BUS_EHCI2 112
+#define CLK_BUS_EHCI3 113
+#define CLK_BUS_OTG 114
+#define CLK_BUS_KEYADC 115
+#define CLK_HDMI 116
+#define CLK_HDMI_SLOW 117
+#define CLK_HDMI_CEC 118
+#define CLK_BUS_HDMI 119
+#define CLK_BUS_TCON_TOP 120
+#define CLK_TCON_TV0 121
+#define CLK_BUS_TCON_TV0 122
+#define CLK_HDCP 123
+#define CLK_BUS_HDCP 124
+
+#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..1c992cfbbbab
--- /dev/null
+++ b/include/dt-bindings/reset/sun50i-h616-ccu.h
@@ -0,0 +1,67 @@
+// SPDX-License-Identifier: (GPL-2.0+ or MIT)
+/*
+ * Copyright (C) 2017 Icenowy Zheng <icenowy@aosc.io>
+ */
+
+#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_HDCP 55
+#define RST_BUS_KEYADC 56
+
+#endif /* _DT_BINDINGS_RESET_SUN50I_H616_H_ */
--
2.17.5
^ permalink raw reply related [flat|nested] 20+ messages in thread
* Re: [PATCH 4/8] clk: sunxi-ng: Add support for the Allwinner H616 R-CCU
2020-12-02 13:54 ` [PATCH 4/8] clk: sunxi-ng: Add support for the Allwinner H616 R-CCU Andre Przywara
@ 2020-12-02 14:31 ` Icenowy Zheng
2020-12-03 11:07 ` André Przywara
2020-12-02 18:20 ` Jernej Škrabec
1 sibling, 1 reply; 20+ messages in thread
From: Icenowy Zheng @ 2020-12-02 14:31 UTC (permalink / raw)
To: Andre Przywara, Maxime Ripard, Chen-Yu Tsai, Jernej Skrabec
Cc: Icenowy Zheng, linux-arm-kernel, linux-sunxi, Linus Walleij,
Rob Herring, Yangtao Li, linux-kernel, Michael Turquette,
Stephen Boyd, Philipp Zabel, linux-clk
于 2020年12月2日 GMT+08:00 下午9:54:05, Andre Przywara <andre.przywara@arm.com> 写到:
>The clocks itself are identical to the H6 R-CCU, it's just that the
>H616
>has not all of them implemented (or connected).
For selective clocks, try to follow the practice of V3(s) driver?
>
>Signed-off-by: Andre Przywara <andre.przywara@arm.com>
>---
> drivers/clk/sunxi-ng/ccu-sun50i-h6-r.c | 47 +++++++++++++++++++++++++-
> drivers/clk/sunxi-ng/ccu-sun50i-h6-r.h | 3 +-
> 2 files changed, 48 insertions(+), 2 deletions(-)
>
>diff --git a/drivers/clk/sunxi-ng/ccu-sun50i-h6-r.c
>b/drivers/clk/sunxi-ng/ccu-sun50i-h6-r.c
>index 50f8d1bc7046..119d1797f501 100644
>--- a/drivers/clk/sunxi-ng/ccu-sun50i-h6-r.c
>+++ b/drivers/clk/sunxi-ng/ccu-sun50i-h6-r.c
>@@ -136,6 +136,15 @@ 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_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,
>@@ -152,7 +161,20 @@ static struct clk_hw_onecell_data
>sun50i_h6_r_hw_clks = {
> [CLK_IR] = &ir_clk.common.hw,
> [CLK_W1] = &w1_clk.common.hw,
> },
>- .num = CLK_NUMBER,
>+ .num = CLK_NUMBER_H616,
>+};
>+
>+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_APB1_IR] = &r_apb1_ir_clk.common.hw,
>+ [CLK_IR] = &ir_clk.common.hw,
>+ },
>+ .num = CLK_NUMBER_H616,
> };
>
> static struct ccu_reset_map sun50i_h6_r_ccu_resets[] = {
>@@ -165,6 +187,12 @@ 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_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),
>@@ -175,6 +203,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)
> {
>@@ -195,3 +233,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);
>diff --git a/drivers/clk/sunxi-ng/ccu-sun50i-h6-r.h
>b/drivers/clk/sunxi-ng/ccu-sun50i-h6-r.h
>index 782117dc0b28..128302696ca1 100644
>--- a/drivers/clk/sunxi-ng/ccu-sun50i-h6-r.h
>+++ b/drivers/clk/sunxi-ng/ccu-sun50i-h6-r.h
>@@ -14,6 +14,7 @@
>
> #define CLK_R_APB2 3
>
>-#define CLK_NUMBER (CLK_W1 + 1)
>+#define CLK_NUMBER_H6 (CLK_W1 + 1)
>+#define CLK_NUMBER_H616 (CLK_IR + 1)
>
> #endif /* _CCU_SUN50I_H6_R_H */
^ permalink raw reply [flat|nested] 20+ messages in thread
* Re: [PATCH 5/8] clk: sunxi-ng: Add support for the Allwinner H616 CCU
2020-12-02 13:54 ` [PATCH 5/8] clk: sunxi-ng: Add support for the Allwinner H616 CCU Andre Przywara
@ 2020-12-02 15:56 ` Maxime Ripard
2020-12-02 21:03 ` Jernej Škrabec
` (2 subsequent siblings)
3 siblings, 0 replies; 20+ messages in thread
From: Maxime Ripard @ 2020-12-02 15:56 UTC (permalink / raw)
To: Andre Przywara
Cc: Chen-Yu Tsai, Jernej Skrabec, Icenowy Zheng, linux-arm-kernel,
linux-sunxi, Linus Walleij, Rob Herring, Yangtao Li,
linux-kernel, Michael Turquette, Stephen Boyd, Philipp Zabel,
linux-clk
[-- Attachment #1: Type: text/plain, Size: 441 bytes --]
Hi
On Wed, Dec 02, 2020 at 01:54:06PM +0000, Andre Przywara wrote:
> 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 <andre.przywara@arm.com>
The patch itself looks ok, but there's a bunch of checkpatch warning
you'll want to fix.
Maxime
[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 228 bytes --]
^ permalink raw reply [flat|nested] 20+ messages in thread
* Re: [PATCH 1/8] clk: sunxi-ng: h6: Fix clock divider range on some clocks
2020-12-02 13:54 ` [PATCH 1/8] clk: sunxi-ng: h6: Fix clock divider range on some clocks Andre Przywara
@ 2020-12-02 16:17 ` Jernej Škrabec
0 siblings, 0 replies; 20+ messages in thread
From: Jernej Škrabec @ 2020-12-02 16:17 UTC (permalink / raw)
To: Maxime Ripard, Chen-Yu Tsai, Andre Przywara
Cc: Icenowy Zheng, linux-arm-kernel, linux-sunxi, Linus Walleij,
Rob Herring, Yangtao Li, linux-kernel, Michael Turquette,
Stephen Boyd, linux-clk, Andre Przywara
Dne sreda, 02. december 2020 ob 14:54:02 CET je Andre Przywara napisal(a):
> 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 <andre.przywara@arm.com>
Reviewed-by: Jernej Skrabec <jernej.skrabec@siol.net>
Best regards,
Jernej
^ permalink raw reply [flat|nested] 20+ messages in thread
* Re: [PATCH 4/8] clk: sunxi-ng: Add support for the Allwinner H616 R-CCU
2020-12-02 13:54 ` [PATCH 4/8] clk: sunxi-ng: Add support for the Allwinner H616 R-CCU Andre Przywara
2020-12-02 14:31 ` Icenowy Zheng
@ 2020-12-02 18:20 ` Jernej Škrabec
2020-12-03 2:44 ` Samuel Holland
2020-12-03 10:52 ` André Przywara
1 sibling, 2 replies; 20+ messages in thread
From: Jernej Škrabec @ 2020-12-02 18:20 UTC (permalink / raw)
To: Maxime Ripard, Chen-Yu Tsai, Andre Przywara
Cc: Icenowy Zheng, linux-arm-kernel, linux-sunxi, Linus Walleij,
Rob Herring, Yangtao Li, linux-kernel, Michael Turquette,
Stephen Boyd, Philipp Zabel, linux-clk, Andre Przywara
Dne sreda, 02. december 2020 ob 14:54:05 CET je Andre Przywara napisal(a):
> 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 <andre.przywara@arm.com>
> ---
> drivers/clk/sunxi-ng/ccu-sun50i-h6-r.c | 47 +++++++++++++++++++++++++-
> drivers/clk/sunxi-ng/ccu-sun50i-h6-r.h | 3 +-
> 2 files changed, 48 insertions(+), 2 deletions(-)
>
> diff --git a/drivers/clk/sunxi-ng/ccu-sun50i-h6-r.c b/drivers/clk/sunxi-ng/
ccu-sun50i-h6-r.c
> index 50f8d1bc7046..119d1797f501 100644
> --- a/drivers/clk/sunxi-ng/ccu-sun50i-h6-r.c
> +++ b/drivers/clk/sunxi-ng/ccu-sun50i-h6-r.c
> @@ -136,6 +136,15 @@ 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_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,
> @@ -152,7 +161,20 @@ static struct clk_hw_onecell_data sun50i_h6_r_hw_clks =
{
> [CLK_IR] = &ir_clk.common.hw,
> [CLK_W1] = &w1_clk.common.hw,
> },
> - .num = CLK_NUMBER,
> + .num = CLK_NUMBER_H616,
Above macro should be CLK_NUMBER_H6.
> +};
> +
> +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,
Do we know if TWD exists? I tested I2C and IR. What is your source for these
clocks?
Best regards,
Jernej
> + [CLK_R_APB2_I2C] = &r_apb2_i2c_clk.common.hw,
> + [CLK_R_APB1_IR] =
&r_apb1_ir_clk.common.hw,
> + [CLK_IR] = &ir_clk.common.hw,
> + },
> + .num = CLK_NUMBER_H616,
> };
>
> static struct ccu_reset_map sun50i_h6_r_ccu_resets[] = {
> @@ -165,6 +187,12 @@ 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_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),
> @@ -175,6 +203,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)
> {
> @@ -195,3 +233,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);
> diff --git a/drivers/clk/sunxi-ng/ccu-sun50i-h6-r.h b/drivers/clk/sunxi-ng/
ccu-sun50i-h6-r.h
> index 782117dc0b28..128302696ca1 100644
> --- a/drivers/clk/sunxi-ng/ccu-sun50i-h6-r.h
> +++ b/drivers/clk/sunxi-ng/ccu-sun50i-h6-r.h
> @@ -14,6 +14,7 @@
>
> #define CLK_R_APB2 3
>
> -#define CLK_NUMBER (CLK_W1 + 1)
> +#define CLK_NUMBER_H6 (CLK_W1 + 1)
> +#define CLK_NUMBER_H616 (CLK_IR + 1)
>
> #endif /* _CCU_SUN50I_H6_R_H */
> --
> 2.17.5
>
>
^ permalink raw reply [flat|nested] 20+ messages in thread
* Re: [PATCH 5/8] clk: sunxi-ng: Add support for the Allwinner H616 CCU
2020-12-02 13:54 ` [PATCH 5/8] clk: sunxi-ng: Add support for the Allwinner H616 CCU Andre Przywara
2020-12-02 15:56 ` Maxime Ripard
@ 2020-12-02 21:03 ` Jernej Škrabec
2020-12-02 23:06 ` André Przywara
2020-12-09 14:33 ` [linux-sunxi] " Clément Péron
2020-12-10 13:31 ` Icenowy Zheng
3 siblings, 1 reply; 20+ messages in thread
From: Jernej Škrabec @ 2020-12-02 21:03 UTC (permalink / raw)
To: Maxime Ripard, Chen-Yu Tsai, Andre Przywara
Cc: Icenowy Zheng, linux-arm-kernel, linux-sunxi, Linus Walleij,
Rob Herring, Yangtao Li, linux-kernel, Michael Turquette,
Stephen Boyd, Philipp Zabel, linux-clk, Andre Przywara
Dne sreda, 02. december 2020 ob 14:54:06 CET je Andre Przywara napisal(a):
> 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 <andre.przywara@arm.com>
> ---
> drivers/clk/sunxi-ng/Kconfig | 7 +-
> drivers/clk/sunxi-ng/Makefile | 1 +
> drivers/clk/sunxi-ng/ccu-sun50i-h616.c | 1134 +++++++++++++++++++
> drivers/clk/sunxi-ng/ccu-sun50i-h616.h | 58 +
> include/dt-bindings/clock/sun50i-h616-ccu.h | 110 ++
> include/dt-bindings/reset/sun50i-h616-ccu.h | 67 ++
> 6 files changed, 1376 insertions(+), 1 deletion(-)
> 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
>
> diff --git a/drivers/clk/sunxi-ng/Kconfig b/drivers/clk/sunxi-ng/Kconfig
> index ce5f5847d5d3..cd46d8853876 100644
> --- a/drivers/clk/sunxi-ng/Kconfig
> +++ b/drivers/clk/sunxi-ng/Kconfig
> @@ -32,8 +32,13 @@ 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 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/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..3fbb258f0354
> --- /dev/null
> +++ b/drivers/clk/sunxi-ng/ccu-sun50i-h616.c
> @@ -0,0 +1,1134 @@
> +// SPDX-License-Identifier: GPL-2.0
> +/*
> + * Copyright (c) 2020 Arm Ltd.
> + * Based on the H6 CCU driver, which is:
> + * Copyright (c) 2017 Icenowy Zheng <icenowy@aosc.io>
> + */
> +
> +#include <linux/clk-provider.h>
> +#include <linux/io.h>
> +#include <linux/of_address.h>
> +#include <linux/platform_device.h>
> +
> +#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 = 4,
> + .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 = 4,
> + .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, 3, /* 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 2 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", "osc12M", 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 struct clk_fixed_factor pll_periph0_4x_clk;
> +
> +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),
> +
> + .mux = {
> + .shift = 24,
> + .width = 2,
> +
> + .fixed_predivs = hdmi_cec_predivs,
> + .n_predivs = ARRAY_SIZE(hdmi_cec_predivs),
> + },
> +
> + .common = {
> + .reg = 0xb10,
> + .features = CCU_FEATURE_VARIABLE_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_tv0_parents[] = { "pll-video0",
> + "pll-
video0-4x",
> + "pll-
video1",
> + "pll-
video1-4x" };
> +static SUNXI_CCU_MP_WITH_MUX_GATE(tcon_tv0_clk, "tcon-tv0",
> + tcon_tv0_parents, 0xb80,
> + 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 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_4x_clk, "pll-periph0-4x",
> + pll_periph0_parents,
> + 1, 4, 0);
> +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_4x_clk, "pll-periph1-4x",
> + pll_periph1_parents,
> + 1, 4, 0);
> +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,
> + &bus_tcon_tv0_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_PERIPH0_4X] = &pll_periph0_4x_clk.hw,
> + [CLK_PLL_PERIPH1] = &pll_periph1_clk.common.hw,
> + [CLK_PLL_PERIPH1_2X] = &pll_periph1_2x_clk.hw,
> + [CLK_PLL_PERIPH1_4X] = &pll_periph1_4x_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_BUS_TCON_TV0] = &bus_tcon_tv0_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_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 int sun50i_h616_ccu_probe(struct platform_device *pdev)
> +{
> + struct resource *res;
> + void __iomem *reg;
> + u32 val;
> + int i;
> +
> + res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
> + reg = devm_ioremap_resource(&pdev->dev, res);
> + if (IS_ERR(reg))
> + return PTR_ERR(reg);
> +
> + /* Enable the lock bits on all PLLs */
> + for (i = 0; i < ARRAY_SIZE(pll_regs); i++) {
> + val = readl(reg + pll_regs[i]);
> + val |= BIT(29);
You should also add BIT(27) here. It enables PLL output (new functionality in
H616). Without this only clocks which are child of PLL_CPUX and PLL_PERIPH0
would work (set up by U-Boot). I'm pretty sure that's not intended usage but
until we know better, it's ok imo.
> + 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);
> +
> + return sunxi_ccu_probe(pdev->dev.of_node, reg,
&sun50i_h616_ccu_desc);
> +}
> +
> +static const struct of_device_id sun50i_h616_ccu_ids[] = {
> + { .compatible = "allwinner,sun50i-h616-ccu",
> + .data = &sun50i_h616_ccu_desc },
> + { }
> +};
> +
> +static struct platform_driver sun50i_h616_ccu_driver = {
> + .probe = sun50i_h616_ccu_probe,
> + .driver = {
> + .name = "sun50i-h616-ccu",
> + .of_match_table = sun50i_h616_ccu_ids,
> + },
> +};
> +builtin_platform_driver(sun50i_h616_ccu_driver);
Please use CLK_OF_DECLARE() instead. That way clocks will be initialized
earlier and it will be actually possible to register both timer peripherals
(once DT nodes are added). If pdev or dev is ever needed, two stage
initialization can be made later.
Best regards,
Jernej
> 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..da8f0b1206f9
> --- /dev/null
> +++ b/drivers/clk/sunxi-ng/ccu-sun50i-h616.h
> @@ -0,0 +1,58 @@
> +/* SPDX-License-Identifier: GPL-2.0 */
> +/*
> + * Copyright 2020 Arm Ltd.
> + */
> +
> +#ifndef _CCU_SUN50I_H616_H_
> +#define _CCU_SUN50I_H616_H_
> +
> +#include <dt-bindings/clock/sun50i-h616-ccu.h>
> +#include <dt-bindings/reset/sun50i-h616-ccu.h>
> +
> +#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_PERIPH0_4X 6
> +#define CLK_PLL_PERIPH1 7
> +#define CLK_PLL_PERIPH1_2X 8
> +#define CLK_PLL_PERIPH1_4X 9
> +#define CLK_PLL_GPU 10
> +#define CLK_PLL_VIDEO0 11
> +#define CLK_PLL_VIDEO0_4X 12
> +#define CLK_PLL_VIDEO1 13
> +#define CLK_PLL_VIDEO1_4X 14
> +#define CLK_PLL_VIDEO2 15
> +#define CLK_PLL_VIDEO2_4X 16
> +#define CLK_PLL_VE 17
> +#define CLK_PLL_DE 18
> +#define CLK_PLL_AUDIO_HS 19
> +#define CLK_PLL_AUDIO_1X 20
> +#define CLK_PLL_AUDIO_2X 21
> +#define CLK_PLL_AUDIO_4X 22
> +
> +/* CPUX clock exported for DVFS */
> +
> +#define CLK_AXI 24
> +#define CLK_CPUX_APB 25
> +#define CLK_PSI_AHB1_AHB2 26
> +#define CLK_AHB3 27
> +
> +/* APB1 clock exported for PIO */
> +
> +#define CLK_APB2 29
> +#define CLK_MBUS 30
> +
> +/* All module clocks and bus gates are exported except DRAM */
> +
> +#define CLK_DRAM 51
> +
> +#define CLK_BUS_DRAM 58
> +
> +#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..a9cc8844e3a9
> --- /dev/null
> +++ b/include/dt-bindings/clock/sun50i-h616-ccu.h
> @@ -0,0 +1,110 @@
> +// 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 23
> +
> +#define CLK_APB1 28
> +
> +#define CLK_DE 31
> +#define CLK_BUS_DE 32
> +#define CLK_DEINTERLACE 33
> +#define CLK_BUS_DEINTERLACE 34
> +#define CLK_G2D 35
> +#define CLK_BUS_G2D 36
> +#define CLK_GPU0 37
> +#define CLK_BUS_GPU 38
> +#define CLK_GPU1 39
> +#define CLK_CE 40
> +#define CLK_BUS_CE 41
> +#define CLK_VE 42
> +#define CLK_BUS_VE 43
> +#define CLK_BUS_DMA 44
> +#define CLK_BUS_HSTIMER 45
> +#define CLK_AVS 46
> +#define CLK_BUS_DBG 47
> +#define CLK_BUS_PSI 48
> +#define CLK_BUS_PWM 49
> +#define CLK_BUS_IOMMU 50
> +
> +#define CLK_MBUS_DMA 52
> +#define CLK_MBUS_VE 53
> +#define CLK_MBUS_CE 54
> +#define CLK_MBUS_TS 55
> +#define CLK_MBUS_NAND 56
> +#define CLK_MBUS_G2D 57
> +
> +#define CLK_NAND0 59
> +#define CLK_NAND1 60
> +#define CLK_BUS_NAND 61
> +#define CLK_MMC0 62
> +#define CLK_MMC1 63
> +#define CLK_MMC2 64
> +#define CLK_BUS_MMC0 65
> +#define CLK_BUS_MMC1 66
> +#define CLK_BUS_MMC2 67
> +#define CLK_BUS_UART0 68
> +#define CLK_BUS_UART1 69
> +#define CLK_BUS_UART2 70
> +#define CLK_BUS_UART3 71
> +#define CLK_BUS_UART4 72
> +#define CLK_BUS_UART5 73
> +#define CLK_BUS_I2C0 74
> +#define CLK_BUS_I2C1 75
> +#define CLK_BUS_I2C2 76
> +#define CLK_BUS_I2C3 77
> +#define CLK_BUS_I2C4 78
> +#define CLK_SPI0 79
> +#define CLK_SPI1 80
> +#define CLK_BUS_SPI0 81
> +#define CLK_BUS_SPI1 82
> +#define CLK_EMAC_25M 83
> +#define CLK_BUS_EMAC0 84
> +#define CLK_BUS_EMAC1 85
> +#define CLK_TS 86
> +#define CLK_BUS_TS 87
> +#define CLK_BUS_THS 88
> +#define CLK_SPDIF 89
> +#define CLK_BUS_SPDIF 90
> +#define CLK_DMIC 91
> +#define CLK_BUS_DMIC 92
> +#define CLK_AUDIO_CODEC_1X 93
> +#define CLK_AUDIO_CODEC_4X 94
> +#define CLK_BUS_AUDIO_CODEC 95
> +#define CLK_AUDIO_HUB 96
> +#define CLK_BUS_AUDIO_HUB 97
> +#define CLK_USB_OHCI0 98
> +#define CLK_USB_PHY0 99
> +#define CLK_USB_OHCI1 100
> +#define CLK_USB_PHY1 101
> +#define CLK_USB_OHCI2 102
> +#define CLK_USB_PHY2 103
> +#define CLK_USB_OHCI3 104
> +#define CLK_USB_PHY3 105
> +#define CLK_BUS_OHCI0 106
> +#define CLK_BUS_OHCI1 107
> +#define CLK_BUS_OHCI2 108
> +#define CLK_BUS_OHCI3 109
> +#define CLK_BUS_EHCI0 110
> +#define CLK_BUS_EHCI1 111
> +#define CLK_BUS_EHCI2 112
> +#define CLK_BUS_EHCI3 113
> +#define CLK_BUS_OTG 114
> +#define CLK_BUS_KEYADC 115
> +#define CLK_HDMI 116
> +#define CLK_HDMI_SLOW 117
> +#define CLK_HDMI_CEC 118
> +#define CLK_BUS_HDMI 119
> +#define CLK_BUS_TCON_TOP 120
> +#define CLK_TCON_TV0 121
> +#define CLK_BUS_TCON_TV0 122
> +#define CLK_HDCP 123
> +#define CLK_BUS_HDCP 124
> +
> +#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..1c992cfbbbab
> --- /dev/null
> +++ b/include/dt-bindings/reset/sun50i-h616-ccu.h
> @@ -0,0 +1,67 @@
> +// SPDX-License-Identifier: (GPL-2.0+ or MIT)
> +/*
> + * Copyright (C) 2017 Icenowy Zheng <icenowy@aosc.io>
> + */
> +
> +#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_HDCP 55
> +#define RST_BUS_KEYADC 56
> +
> +#endif /* _DT_BINDINGS_RESET_SUN50I_H616_H_ */
> --
> 2.17.5
>
>
>
^ permalink raw reply [flat|nested] 20+ messages in thread
* Re: [PATCH 5/8] clk: sunxi-ng: Add support for the Allwinner H616 CCU
2020-12-02 21:03 ` Jernej Škrabec
@ 2020-12-02 23:06 ` André Przywara
2020-12-05 16:36 ` [linux-sunxi] " Icenowy Zheng
0 siblings, 1 reply; 20+ messages in thread
From: André Przywara @ 2020-12-02 23:06 UTC (permalink / raw)
To: Jernej Škrabec, Maxime Ripard, Chen-Yu Tsai
Cc: linux-arm-kernel, linux-sunxi, Linus Walleij, Rob Herring,
Yangtao Li, linux-kernel, Michael Turquette, Stephen Boyd,
Philipp Zabel, linux-clk, Clément Péron
On 02/12/2020 21:03, Jernej Škrabec wrote:
> Dne sreda, 02. december 2020 ob 14:54:06 CET je Andre Przywara napisal(a):
>> 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 <andre.przywara@arm.com>
>> ---
>> drivers/clk/sunxi-ng/Kconfig | 7 +-
>> drivers/clk/sunxi-ng/Makefile | 1 +
>> drivers/clk/sunxi-ng/ccu-sun50i-h616.c | 1134 +++++++++++++++++++
>> drivers/clk/sunxi-ng/ccu-sun50i-h616.h | 58 +
>> include/dt-bindings/clock/sun50i-h616-ccu.h | 110 ++
>> include/dt-bindings/reset/sun50i-h616-ccu.h | 67 ++
>> 6 files changed, 1376 insertions(+), 1 deletion(-)
>> 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
>>
>> diff --git a/drivers/clk/sunxi-ng/Kconfig b/drivers/clk/sunxi-ng/Kconfig
>> index ce5f5847d5d3..cd46d8853876 100644
>> --- a/drivers/clk/sunxi-ng/Kconfig
>> +++ b/drivers/clk/sunxi-ng/Kconfig
....
>> +static int sun50i_h616_ccu_probe(struct platform_device *pdev)
>> +{
>> + struct resource *res;
>> + void __iomem *reg;
>> + u32 val;
>> + int i;
>> +
>> + res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
>> + reg = devm_ioremap_resource(&pdev->dev, res);
>> + if (IS_ERR(reg))
>> + return PTR_ERR(reg);
>> +
>> + /* Enable the lock bits on all PLLs */
>> + for (i = 0; i < ARRAY_SIZE(pll_regs); i++) {
>> + val = readl(reg + pll_regs[i]);
>> + val |= BIT(29);
>
> You should also add BIT(27) here. It enables PLL output (new functionality in
> H616). Without this only clocks which are child of PLL_CPUX and PLL_PERIPH0
> would work (set up by U-Boot). I'm pretty sure that's not intended usage but
> until we know better, it's ok imo.
Ah right, the output enable bit. I was wondering if the A100 solution
would better here: use bit 27 as the .enable value, and actually enable
(bit31) all PLLs here.
Or we add another field, maybe a flag, to allow the kernel to decide
which bit to use. Clement suggested something like that on IRC.
But for now I can surely just set bit 27 here as well.
>> + 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);
>> +
>> + return sunxi_ccu_probe(pdev->dev.of_node, reg, &sun50i_h616_ccu_desc);
>> +}
>> +
>> +static const struct of_device_id sun50i_h616_ccu_ids[] = {
>> + { .compatible = "allwinner,sun50i-h616-ccu",
>> + .data = &sun50i_h616_ccu_desc },
>> + { }
>> +};
>> +
>> +static struct platform_driver sun50i_h616_ccu_driver = {
>> + .probe = sun50i_h616_ccu_probe,
>> + .driver = {
>> + .name = "sun50i-h616-ccu",
>> + .of_match_table = sun50i_h616_ccu_ids,
>> + },
>> +};
>> +builtin_platform_driver(sun50i_h616_ccu_driver);
>
> Please use CLK_OF_DECLARE() instead. That way clocks will be initialized
> earlier and it will be actually possible to register both timer peripherals
> (once DT nodes are added). If pdev or dev is ever needed, two stage
> initialization can be made later.
Sure, will do.
Thanks for having a look!
Andre
>
> Best regards,
> Jernej
>
>> 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..da8f0b1206f9
>> --- /dev/null
>> +++ b/drivers/clk/sunxi-ng/ccu-sun50i-h616.h
>> @@ -0,0 +1,58 @@
>> +/* SPDX-License-Identifier: GPL-2.0 */
>> +/*
>> + * Copyright 2020 Arm Ltd.
>> + */
>> +
>> +#ifndef _CCU_SUN50I_H616_H_
>> +#define _CCU_SUN50I_H616_H_
>> +
>> +#include <dt-bindings/clock/sun50i-h616-ccu.h>
>> +#include <dt-bindings/reset/sun50i-h616-ccu.h>
>> +
>> +#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_PERIPH0_4X 6
>> +#define CLK_PLL_PERIPH1 7
>> +#define CLK_PLL_PERIPH1_2X 8
>> +#define CLK_PLL_PERIPH1_4X 9
>> +#define CLK_PLL_GPU 10
>> +#define CLK_PLL_VIDEO0 11
>> +#define CLK_PLL_VIDEO0_4X 12
>> +#define CLK_PLL_VIDEO1 13
>> +#define CLK_PLL_VIDEO1_4X 14
>> +#define CLK_PLL_VIDEO2 15
>> +#define CLK_PLL_VIDEO2_4X 16
>> +#define CLK_PLL_VE 17
>> +#define CLK_PLL_DE 18
>> +#define CLK_PLL_AUDIO_HS 19
>> +#define CLK_PLL_AUDIO_1X 20
>> +#define CLK_PLL_AUDIO_2X 21
>> +#define CLK_PLL_AUDIO_4X 22
>> +
>> +/* CPUX clock exported for DVFS */
>> +
>> +#define CLK_AXI 24
>> +#define CLK_CPUX_APB 25
>> +#define CLK_PSI_AHB1_AHB2 26
>> +#define CLK_AHB3 27
>> +
>> +/* APB1 clock exported for PIO */
>> +
>> +#define CLK_APB2 29
>> +#define CLK_MBUS 30
>> +
>> +/* All module clocks and bus gates are exported except DRAM */
>> +
>> +#define CLK_DRAM 51
>> +
>> +#define CLK_BUS_DRAM 58
>> +
>> +#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..a9cc8844e3a9
>> --- /dev/null
>> +++ b/include/dt-bindings/clock/sun50i-h616-ccu.h
>> @@ -0,0 +1,110 @@
>> +// 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 23
>> +
>> +#define CLK_APB1 28
>> +
>> +#define CLK_DE 31
>> +#define CLK_BUS_DE 32
>> +#define CLK_DEINTERLACE 33
>> +#define CLK_BUS_DEINTERLACE 34
>> +#define CLK_G2D 35
>> +#define CLK_BUS_G2D 36
>> +#define CLK_GPU0 37
>> +#define CLK_BUS_GPU 38
>> +#define CLK_GPU1 39
>> +#define CLK_CE 40
>> +#define CLK_BUS_CE 41
>> +#define CLK_VE 42
>> +#define CLK_BUS_VE 43
>> +#define CLK_BUS_DMA 44
>> +#define CLK_BUS_HSTIMER 45
>> +#define CLK_AVS 46
>> +#define CLK_BUS_DBG 47
>> +#define CLK_BUS_PSI 48
>> +#define CLK_BUS_PWM 49
>> +#define CLK_BUS_IOMMU 50
>> +
>> +#define CLK_MBUS_DMA 52
>> +#define CLK_MBUS_VE 53
>> +#define CLK_MBUS_CE 54
>> +#define CLK_MBUS_TS 55
>> +#define CLK_MBUS_NAND 56
>> +#define CLK_MBUS_G2D 57
>> +
>> +#define CLK_NAND0 59
>> +#define CLK_NAND1 60
>> +#define CLK_BUS_NAND 61
>> +#define CLK_MMC0 62
>> +#define CLK_MMC1 63
>> +#define CLK_MMC2 64
>> +#define CLK_BUS_MMC0 65
>> +#define CLK_BUS_MMC1 66
>> +#define CLK_BUS_MMC2 67
>> +#define CLK_BUS_UART0 68
>> +#define CLK_BUS_UART1 69
>> +#define CLK_BUS_UART2 70
>> +#define CLK_BUS_UART3 71
>> +#define CLK_BUS_UART4 72
>> +#define CLK_BUS_UART5 73
>> +#define CLK_BUS_I2C0 74
>> +#define CLK_BUS_I2C1 75
>> +#define CLK_BUS_I2C2 76
>> +#define CLK_BUS_I2C3 77
>> +#define CLK_BUS_I2C4 78
>> +#define CLK_SPI0 79
>> +#define CLK_SPI1 80
>> +#define CLK_BUS_SPI0 81
>> +#define CLK_BUS_SPI1 82
>> +#define CLK_EMAC_25M 83
>> +#define CLK_BUS_EMAC0 84
>> +#define CLK_BUS_EMAC1 85
>> +#define CLK_TS 86
>> +#define CLK_BUS_TS 87
>> +#define CLK_BUS_THS 88
>> +#define CLK_SPDIF 89
>> +#define CLK_BUS_SPDIF 90
>> +#define CLK_DMIC 91
>> +#define CLK_BUS_DMIC 92
>> +#define CLK_AUDIO_CODEC_1X 93
>> +#define CLK_AUDIO_CODEC_4X 94
>> +#define CLK_BUS_AUDIO_CODEC 95
>> +#define CLK_AUDIO_HUB 96
>> +#define CLK_BUS_AUDIO_HUB 97
>> +#define CLK_USB_OHCI0 98
>> +#define CLK_USB_PHY0 99
>> +#define CLK_USB_OHCI1 100
>> +#define CLK_USB_PHY1 101
>> +#define CLK_USB_OHCI2 102
>> +#define CLK_USB_PHY2 103
>> +#define CLK_USB_OHCI3 104
>> +#define CLK_USB_PHY3 105
>> +#define CLK_BUS_OHCI0 106
>> +#define CLK_BUS_OHCI1 107
>> +#define CLK_BUS_OHCI2 108
>> +#define CLK_BUS_OHCI3 109
>> +#define CLK_BUS_EHCI0 110
>> +#define CLK_BUS_EHCI1 111
>> +#define CLK_BUS_EHCI2 112
>> +#define CLK_BUS_EHCI3 113
>> +#define CLK_BUS_OTG 114
>> +#define CLK_BUS_KEYADC 115
>> +#define CLK_HDMI 116
>> +#define CLK_HDMI_SLOW 117
>> +#define CLK_HDMI_CEC 118
>> +#define CLK_BUS_HDMI 119
>> +#define CLK_BUS_TCON_TOP 120
>> +#define CLK_TCON_TV0 121
>> +#define CLK_BUS_TCON_TV0 122
>> +#define CLK_HDCP 123
>> +#define CLK_BUS_HDCP 124
>> +
>> +#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..1c992cfbbbab
>> --- /dev/null
>> +++ b/include/dt-bindings/reset/sun50i-h616-ccu.h
>> @@ -0,0 +1,67 @@
>> +// SPDX-License-Identifier: (GPL-2.0+ or MIT)
>> +/*
>> + * Copyright (C) 2017 Icenowy Zheng <icenowy@aosc.io>
>> + */
>> +
>> +#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_HDCP 55
>> +#define RST_BUS_KEYADC 56
>> +
>> +#endif /* _DT_BINDINGS_RESET_SUN50I_H616_H_ */
>> --
>> 2.17.5
>>
>>
>>
>
>
^ permalink raw reply [flat|nested] 20+ messages in thread
* Re: [PATCH 4/8] clk: sunxi-ng: Add support for the Allwinner H616 R-CCU
2020-12-02 18:20 ` Jernej Škrabec
@ 2020-12-03 2:44 ` Samuel Holland
2020-12-03 10:52 ` André Przywara
1 sibling, 0 replies; 20+ messages in thread
From: Samuel Holland @ 2020-12-03 2:44 UTC (permalink / raw)
To: Jernej Škrabec, Maxime Ripard, Chen-Yu Tsai, Andre Przywara
Cc: Philipp Zabel, Stephen Boyd, Linus Walleij, linux-kernel,
linux-clk, linux-sunxi, Rob Herring, Icenowy Zheng, Yangtao Li,
Michael Turquette, linux-arm-kernel
On 12/2/20 12:20 PM, Jernej Škrabec wrote:
>> +};
>> +
>> +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,
>
> Do we know if TWD exists? I tested I2C and IR. What is your source for these
> clocks?
Looking at https://github.com/orangepi-xunlong/linux-orangepi and comparing
drivers/clk/sunxi/clk-sun50iw[69].h, I see:
/* PRCM Register List */
#define CPUS_CFG 0x0000
#define CPUS_APBS1_CFG 0x000C
#define CPUS_APBS2_CFG 0x0010
-#define CPUS_TIMER_GATE 0x011C
#define CPUS_TWDOG_GATE 0x012C
-#define CPUS_PWM_GATE 0x013C
-#define CPUS_UART_GATE 0x018C
#define CPUS_TWI_GATE 0x019C
#define CPUS_RSB_GATE 0x01BC
#define CPUS_CIR_CFG 0x01C0
#define CPUS_CIR_GATE 0x01CC
#define CPUS_OWC_CFG 0x01E0
#define CPUS_OWC_GATE 0x01EC
#define CPUS_RTC_GATE 0x020C
#define CPUS_CLK_MAX_REG 0x020C
which suggests that TWD is still there, along with OWC/W1 and an undocumented
RSB controller like the one in H6. Jernej, can you check RSB? It should be
PL0/PL1 function 2 and MMIO base 0x7083000.
Cheers,
Samuel
^ permalink raw reply [flat|nested] 20+ messages in thread
* Re: [PATCH 4/8] clk: sunxi-ng: Add support for the Allwinner H616 R-CCU
2020-12-02 18:20 ` Jernej Škrabec
2020-12-03 2:44 ` Samuel Holland
@ 2020-12-03 10:52 ` André Przywara
1 sibling, 0 replies; 20+ messages in thread
From: André Przywara @ 2020-12-03 10:52 UTC (permalink / raw)
To: Jernej Škrabec, Maxime Ripard, Chen-Yu Tsai
Cc: Icenowy Zheng, linux-arm-kernel, linux-sunxi, Linus Walleij,
Rob Herring, Yangtao Li, linux-kernel, Michael Turquette,
Stephen Boyd, Philipp Zabel, linux-clk
On 02/12/2020 18:20, Jernej Škrabec wrote:
Hi,
> Dne sreda, 02. december 2020 ob 14:54:05 CET je Andre Przywara napisal(a):
>> 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 <andre.przywara@arm.com>
>> ---
>> drivers/clk/sunxi-ng/ccu-sun50i-h6-r.c | 47 +++++++++++++++++++++++++-
>> drivers/clk/sunxi-ng/ccu-sun50i-h6-r.h | 3 +-
>> 2 files changed, 48 insertions(+), 2 deletions(-)
>>
>> diff --git a/drivers/clk/sunxi-ng/ccu-sun50i-h6-r.c b/drivers/clk/sunxi-ng/ccu-sun50i-h6-r.c
>> index 50f8d1bc7046..119d1797f501 100644
>> --- a/drivers/clk/sunxi-ng/ccu-sun50i-h6-r.c
>> +++ b/drivers/clk/sunxi-ng/ccu-sun50i-h6-r.c
>> @@ -136,6 +136,15 @@ 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_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,
>> @@ -152,7 +161,20 @@ static struct clk_hw_onecell_data sun50i_h6_r_hw_clks = {
>> [CLK_IR] = &ir_clk.common.hw,
>> [CLK_W1] = &w1_clk.common.hw,
>> },
>> - .num = CLK_NUMBER,
>> + .num = CLK_NUMBER_H616,
>
> Above macro should be CLK_NUMBER_H6.
Ouch, well spotted!
>> +};
>> +
>> +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,
>
> Do we know if TWD exists? I tested I2C and IR. What is your source for these
> clocks?
I poked around in this area, writing all Fs into those clock registers
and checked which stuck. There are actually even more clocks still
around there, though not all of the H6 (no PWM, for instance).
For TWD: it's mentioned in the manual, the clock register is there and
can be written to. The normal watchdog registers do not appear to work
at 0x7020800 (they are RAZ/WI), but there is a counter at 0x7020820,
which increments as long as those TWD clock gates are open. It stops
when the clock bits are cleared.
So that tells me that this clock is there and is working.
I didn't have time yet to check the other (former) peripherals from that
area.
Cheers,
Andre
>
> Best regards,
> Jernej
>
>> + [CLK_R_APB2_I2C] = &r_apb2_i2c_clk.common.hw,
>> + [CLK_R_APB1_IR] = &r_apb1_ir_clk.common.hw,
>> + [CLK_IR] = &ir_clk.common.hw,
>> + },
>> + .num = CLK_NUMBER_H616,
>> };
>>
>> static struct ccu_reset_map sun50i_h6_r_ccu_resets[] = {
>> @@ -165,6 +187,12 @@ 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_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),
>> @@ -175,6 +203,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)
>> {
>> @@ -195,3 +233,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);
>> diff --git a/drivers/clk/sunxi-ng/ccu-sun50i-h6-r.h b/drivers/clk/sunxi-ng/ccu-sun50i-h6-r.h
>> index 782117dc0b28..128302696ca1 100644
>> --- a/drivers/clk/sunxi-ng/ccu-sun50i-h6-r.h
>> +++ b/drivers/clk/sunxi-ng/ccu-sun50i-h6-r.h
>> @@ -14,6 +14,7 @@
>>
>> #define CLK_R_APB2 3
>>
>> -#define CLK_NUMBER (CLK_W1 + 1)
>> +#define CLK_NUMBER_H6 (CLK_W1 + 1)
>> +#define CLK_NUMBER_H616 (CLK_IR + 1)
>>
>> #endif /* _CCU_SUN50I_H6_R_H */
>> --
>> 2.17.5
>>
>>
^ permalink raw reply [flat|nested] 20+ messages in thread
* Re: [PATCH 4/8] clk: sunxi-ng: Add support for the Allwinner H616 R-CCU
2020-12-02 14:31 ` Icenowy Zheng
@ 2020-12-03 11:07 ` André Przywara
2020-12-03 14:02 ` [linux-sunxi] " Icenowy Zheng
0 siblings, 1 reply; 20+ messages in thread
From: André Przywara @ 2020-12-03 11:07 UTC (permalink / raw)
To: Icenowy Zheng, Maxime Ripard, Chen-Yu Tsai, Jernej Skrabec
Cc: Icenowy Zheng, linux-arm-kernel, linux-sunxi, Linus Walleij,
Rob Herring, Yangtao Li, linux-kernel, Michael Turquette,
Stephen Boyd, Philipp Zabel, linux-clk
On 02/12/2020 14:31, Icenowy Zheng wrote:
Hi,
> 于 2020年12月2日 GMT+08:00 下午9:54:05, Andre Przywara <andre.przywara@arm.com> 写到:
>> The clocks itself are identical to the H6 R-CCU, it's just that the
>> H616
>> has not all of them implemented (or connected).
>
> For selective clocks, try to follow the practice of V3(s) driver?
Not sure what you mean, isn't that what I do? Having a separate
sunxi_ccu_desc for each SoC and referencing separate structs? At least
that's what I see in ccu-sun8i-v3s.c.
What am I missing?
Cheers,
Andre
>>
>> Signed-off-by: Andre Przywara <andre.przywara@arm.com>
>> ---
>> drivers/clk/sunxi-ng/ccu-sun50i-h6-r.c | 47 +++++++++++++++++++++++++-
>> drivers/clk/sunxi-ng/ccu-sun50i-h6-r.h | 3 +-
>> 2 files changed, 48 insertions(+), 2 deletions(-)
>>
>> diff --git a/drivers/clk/sunxi-ng/ccu-sun50i-h6-r.c
>> b/drivers/clk/sunxi-ng/ccu-sun50i-h6-r.c
>> index 50f8d1bc7046..119d1797f501 100644
>> --- a/drivers/clk/sunxi-ng/ccu-sun50i-h6-r.c
>> +++ b/drivers/clk/sunxi-ng/ccu-sun50i-h6-r.c
>> @@ -136,6 +136,15 @@ 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_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,
>> @@ -152,7 +161,20 @@ static struct clk_hw_onecell_data
>> sun50i_h6_r_hw_clks = {
>> [CLK_IR] = &ir_clk.common.hw,
>> [CLK_W1] = &w1_clk.common.hw,
>> },
>> - .num = CLK_NUMBER,
>> + .num = CLK_NUMBER_H616,
>> +};
>> +
>> +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_APB1_IR] = &r_apb1_ir_clk.common.hw,
>> + [CLK_IR] = &ir_clk.common.hw,
>> + },
>> + .num = CLK_NUMBER_H616,
>> };
>>
>> static struct ccu_reset_map sun50i_h6_r_ccu_resets[] = {
>> @@ -165,6 +187,12 @@ 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_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),
>> @@ -175,6 +203,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)
>> {
>> @@ -195,3 +233,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);
>> diff --git a/drivers/clk/sunxi-ng/ccu-sun50i-h6-r.h
>> b/drivers/clk/sunxi-ng/ccu-sun50i-h6-r.h
>> index 782117dc0b28..128302696ca1 100644
>> --- a/drivers/clk/sunxi-ng/ccu-sun50i-h6-r.h
>> +++ b/drivers/clk/sunxi-ng/ccu-sun50i-h6-r.h
>> @@ -14,6 +14,7 @@
>>
>> #define CLK_R_APB2 3
>>
>> -#define CLK_NUMBER (CLK_W1 + 1)
>> +#define CLK_NUMBER_H6 (CLK_W1 + 1)
>> +#define CLK_NUMBER_H616 (CLK_IR + 1)
>>
>> #endif /* _CCU_SUN50I_H6_R_H */
^ permalink raw reply [flat|nested] 20+ messages in thread
* Re: [linux-sunxi] Re: [PATCH 4/8] clk: sunxi-ng: Add support for the Allwinner H616 R-CCU
2020-12-03 11:07 ` André Przywara
@ 2020-12-03 14:02 ` Icenowy Zheng
0 siblings, 0 replies; 20+ messages in thread
From: Icenowy Zheng @ 2020-12-03 14:02 UTC (permalink / raw)
To: andre.przywara, André Przywara, Maxime Ripard, Chen-Yu Tsai,
Jernej Skrabec
Cc: Icenowy Zheng, linux-arm-kernel, linux-sunxi, Linus Walleij,
Rob Herring, Yangtao Li, linux-kernel, Michael Turquette,
Stephen Boyd, Philipp Zabel, linux-clk
于 2020年12月3日 GMT+08:00 下午7:07:02, "André Przywara" <andre.przywara@arm.com> 写到:
>On 02/12/2020 14:31, Icenowy Zheng wrote:
>
>Hi,
>
>> 于 2020年12月2日 GMT+08:00 下午9:54:05, Andre Przywara
><andre.przywara@arm.com> 写到:
>>> The clocks itself are identical to the H6 R-CCU, it's just that the
>>> H616
>>> has not all of them implemented (or connected).
>>
>> For selective clocks, try to follow the practice of V3(s) driver?
>
>Not sure what you mean, isn't that what I do? Having a separate
>sunxi_ccu_desc for each SoC and referencing separate structs? At least
>that's what I see in ccu-sun8i-v3s.c.
>
>What am I missing?
Sorry, I misred it.
Ignore my disturbance.
>
>Cheers,
>Andre
>
>>>
>>> Signed-off-by: Andre Przywara <andre.przywara@arm.com>
>>> ---
>>> drivers/clk/sunxi-ng/ccu-sun50i-h6-r.c | 47
>+++++++++++++++++++++++++-
>>> drivers/clk/sunxi-ng/ccu-sun50i-h6-r.h | 3 +-
>>> 2 files changed, 48 insertions(+), 2 deletions(-)
>>>
>>> diff --git a/drivers/clk/sunxi-ng/ccu-sun50i-h6-r.c
>>> b/drivers/clk/sunxi-ng/ccu-sun50i-h6-r.c
>>> index 50f8d1bc7046..119d1797f501 100644
>>> --- a/drivers/clk/sunxi-ng/ccu-sun50i-h6-r.c
>>> +++ b/drivers/clk/sunxi-ng/ccu-sun50i-h6-r.c
>>> @@ -136,6 +136,15 @@ 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_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,
>>> @@ -152,7 +161,20 @@ static struct clk_hw_onecell_data
>>> sun50i_h6_r_hw_clks = {
>>> [CLK_IR] = &ir_clk.common.hw,
>>> [CLK_W1] = &w1_clk.common.hw,
>>> },
>>> - .num = CLK_NUMBER,
>>> + .num = CLK_NUMBER_H616,
>>> +};
>>> +
>>> +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_APB1_IR] = &r_apb1_ir_clk.common.hw,
>>> + [CLK_IR] = &ir_clk.common.hw,
>>> + },
>>> + .num = CLK_NUMBER_H616,
>>> };
>>>
>>> static struct ccu_reset_map sun50i_h6_r_ccu_resets[] = {
>>> @@ -165,6 +187,12 @@ 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_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),
>>> @@ -175,6 +203,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)
>>> {
>>> @@ -195,3 +233,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);
>>> diff --git a/drivers/clk/sunxi-ng/ccu-sun50i-h6-r.h
>>> b/drivers/clk/sunxi-ng/ccu-sun50i-h6-r.h
>>> index 782117dc0b28..128302696ca1 100644
>>> --- a/drivers/clk/sunxi-ng/ccu-sun50i-h6-r.h
>>> +++ b/drivers/clk/sunxi-ng/ccu-sun50i-h6-r.h
>>> @@ -14,6 +14,7 @@
>>>
>>> #define CLK_R_APB2 3
>>>
>>> -#define CLK_NUMBER (CLK_W1 + 1)
>>> +#define CLK_NUMBER_H6 (CLK_W1 + 1)
>>> +#define CLK_NUMBER_H616 (CLK_IR + 1)
>>>
>>> #endif /* _CCU_SUN50I_H6_R_H */
^ permalink raw reply [flat|nested] 20+ messages in thread
* Re: [linux-sunxi] Re: [PATCH 5/8] clk: sunxi-ng: Add support for the Allwinner H616 CCU
2020-12-02 23:06 ` André Przywara
@ 2020-12-05 16:36 ` Icenowy Zheng
0 siblings, 0 replies; 20+ messages in thread
From: Icenowy Zheng @ 2020-12-05 16:36 UTC (permalink / raw)
To: andre.przywara, Jernej �0�7krabec, Maxime Ripard,
Chen-Yu Tsai
Cc: linux-arm-kernel, linux-sunxi, Linus Walleij, Rob Herring,
Yangtao Li, linux-kernel, Michael Turquette, Stephen Boyd,
Philipp Zabel, linux-clk, Clément Péron
在 2020-12-02星期三的 23:06 +0000,André Przywara写道:
> On 02/12/2020 21:03, Jernej Škrabec wrote:
> > Dne sreda, 02. december 2020 ob 14:54:06 CET je Andre Przywara
> > napisal(a):
> > > 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 <andre.przywara@arm.com>
> > > ---
> > > drivers/clk/sunxi-ng/Kconfig | 7 +-
> > > drivers/clk/sunxi-ng/Makefile | 1 +
> > > drivers/clk/sunxi-ng/ccu-sun50i-h616.c | 1134
> > > +++++++++++++++++++
> > > drivers/clk/sunxi-ng/ccu-sun50i-h616.h | 58 +
> > > include/dt-bindings/clock/sun50i-h616-ccu.h | 110 ++
> > > include/dt-bindings/reset/sun50i-h616-ccu.h | 67 ++
> > > 6 files changed, 1376 insertions(+), 1 deletion(-)
> > > 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
> > >
> > > diff --git a/drivers/clk/sunxi-ng/Kconfig b/drivers/clk/sunxi-
> > > ng/Kconfig
> > > index ce5f5847d5d3..cd46d8853876 100644
> > > --- a/drivers/clk/sunxi-ng/Kconfig
> > > +++ b/drivers/clk/sunxi-ng/Kconfig
>
> ....
>
> > > +static int sun50i_h616_ccu_probe(struct platform_device *pdev)
> > > +{
> > > + struct resource *res;
> > > + void __iomem *reg;
> > > + u32 val;
> > > + int i;
> > > +
> > > + res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
> > > + reg = devm_ioremap_resource(&pdev->dev, res);
> > > + if (IS_ERR(reg))
> > > + return PTR_ERR(reg);
> > > +
> > > + /* Enable the lock bits on all PLLs */
> > > + for (i = 0; i < ARRAY_SIZE(pll_regs); i++) {
> > > + val = readl(reg + pll_regs[i]);
> > > + val |= BIT(29);
> >
> > You should also add BIT(27) here. It enables PLL output (new
> > functionality in
> > H616). Without this only clocks which are child of PLL_CPUX and
> > PLL_PERIPH0
> > would work (set up by U-Boot). I'm pretty sure that's not intended
> > usage but
> > until we know better, it's ok imo.
>
> Ah right, the output enable bit. I was wondering if the A100 solution
> would better here: use bit 27 as the .enable value, and actually
> enable
Why not .enable = BIT(27) | BIT(31) ?
> (bit31) all PLLs here.
> Or we add another field, maybe a flag, to allow the kernel to decide
> which bit to use. Clement suggested something like that on IRC.
> But for now I can surely just set bit 27 here as well.
>
> > > + 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);
> > > +
> > > + return sunxi_ccu_probe(pdev->dev.of_node, reg,
> > > &sun50i_h616_ccu_desc);
> > > +}
> > > +
> > > +static const struct of_device_id sun50i_h616_ccu_ids[] = {
> > > + { .compatible = "allwinner,sun50i-h616-ccu",
> > > + .data = &sun50i_h616_ccu_desc },
> > > + { }
> > > +};
> > > +
> > > +static struct platform_driver sun50i_h616_ccu_driver = {
> > > + .probe = sun50i_h616_ccu_probe,
> > > + .driver = {
> > > + .name = "sun50i-h616-ccu",
> > > + .of_match_table = sun50i_h616_ccu_ids,
> > > + },
> > > +};
> > > +builtin_platform_driver(sun50i_h616_ccu_driver);
> >
> > Please use CLK_OF_DECLARE() instead. That way clocks will be
> > initialized
> > earlier and it will be actually possible to register both timer
> > peripherals
> > (once DT nodes are added). If pdev or dev is ever needed, two
> > stage
> > initialization can be made later.
>
> Sure, will do.
>
> Thanks for having a look!
>
> Andre
>
> > Best regards,
> > Jernej
> >
> > > 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..da8f0b1206f9
> > > --- /dev/null
> > > +++ b/drivers/clk/sunxi-ng/ccu-sun50i-h616.h
> > > @@ -0,0 +1,58 @@
> > > +/* SPDX-License-Identifier: GPL-2.0 */
> > > +/*
> > > + * Copyright 2020 Arm Ltd.
> > > + */
> > > +
> > > +#ifndef _CCU_SUN50I_H616_H_
> > > +#define _CCU_SUN50I_H616_H_
> > > +
> > > +#include <dt-bindings/clock/sun50i-h616-ccu.h>
> > > +#include <dt-bindings/reset/sun50i-h616-ccu.h>
> > > +
> > > +#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_PERIPH0_4X 6
> > > +#define CLK_PLL_PERIPH1 7
> > > +#define CLK_PLL_PERIPH1_2X 8
> > > +#define CLK_PLL_PERIPH1_4X 9
> > > +#define CLK_PLL_GPU 10
> > > +#define CLK_PLL_VIDEO0 11
> > > +#define CLK_PLL_VIDEO0_4X 12
> > > +#define CLK_PLL_VIDEO1 13
> > > +#define CLK_PLL_VIDEO1_4X 14
> > > +#define CLK_PLL_VIDEO2 15
> > > +#define CLK_PLL_VIDEO2_4X 16
> > > +#define CLK_PLL_VE 17
> > > +#define CLK_PLL_DE 18
> > > +#define CLK_PLL_AUDIO_HS 19
> > > +#define CLK_PLL_AUDIO_1X 20
> > > +#define CLK_PLL_AUDIO_2X 21
> > > +#define CLK_PLL_AUDIO_4X 22
> > > +
> > > +/* CPUX clock exported for DVFS */
> > > +
> > > +#define CLK_AXI 24
> > > +#define CLK_CPUX_APB 25
> > > +#define CLK_PSI_AHB1_AHB2 26
> > > +#define CLK_AHB3 27
> > > +
> > > +/* APB1 clock exported for PIO */
> > > +
> > > +#define CLK_APB2 29
> > > +#define CLK_MBUS 30
> > > +
> > > +/* All module clocks and bus gates are exported except DRAM */
> > > +
> > > +#define CLK_DRAM 51
> > > +
> > > +#define CLK_BUS_DRAM 58
> > > +
> > > +#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..a9cc8844e3a9
> > > --- /dev/null
> > > +++ b/include/dt-bindings/clock/sun50i-h616-ccu.h
> > > @@ -0,0 +1,110 @@
> > > +// 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 23
> > > +
> > > +#define CLK_APB1 28
> > > +
> > > +#define CLK_DE 31
> > > +#define CLK_BUS_DE 32
> > > +#define CLK_DEINTERLACE 33
> > > +#define CLK_BUS_DEINTERLACE 34
> > > +#define CLK_G2D 35
> > > +#define CLK_BUS_G2D 36
> > > +#define CLK_GPU0 37
> > > +#define CLK_BUS_GPU 38
> > > +#define CLK_GPU1 39
> > > +#define CLK_CE 40
> > > +#define CLK_BUS_CE 41
> > > +#define CLK_VE 42
> > > +#define CLK_BUS_VE 43
> > > +#define CLK_BUS_DMA 44
> > > +#define CLK_BUS_HSTIMER 45
> > > +#define CLK_AVS 46
> > > +#define CLK_BUS_DBG 47
> > > +#define CLK_BUS_PSI 48
> > > +#define CLK_BUS_PWM 49
> > > +#define CLK_BUS_IOMMU 50
> > > +
> > > +#define CLK_MBUS_DMA 52
> > > +#define CLK_MBUS_VE 53
> > > +#define CLK_MBUS_CE 54
> > > +#define CLK_MBUS_TS 55
> > > +#define CLK_MBUS_NAND 56
> > > +#define CLK_MBUS_G2D 57
> > > +
> > > +#define CLK_NAND0 59
> > > +#define CLK_NAND1 60
> > > +#define CLK_BUS_NAND 61
> > > +#define CLK_MMC0 62
> > > +#define CLK_MMC1 63
> > > +#define CLK_MMC2 64
> > > +#define CLK_BUS_MMC0 65
> > > +#define CLK_BUS_MMC1 66
> > > +#define CLK_BUS_MMC2 67
> > > +#define CLK_BUS_UART0 68
> > > +#define CLK_BUS_UART1 69
> > > +#define CLK_BUS_UART2 70
> > > +#define CLK_BUS_UART3 71
> > > +#define CLK_BUS_UART4 72
> > > +#define CLK_BUS_UART5 73
> > > +#define CLK_BUS_I2C0 74
> > > +#define CLK_BUS_I2C1 75
> > > +#define CLK_BUS_I2C2 76
> > > +#define CLK_BUS_I2C3 77
> > > +#define CLK_BUS_I2C4 78
> > > +#define CLK_SPI0 79
> > > +#define CLK_SPI1 80
> > > +#define CLK_BUS_SPI0 81
> > > +#define CLK_BUS_SPI1 82
> > > +#define CLK_EMAC_25M 83
> > > +#define CLK_BUS_EMAC0 84
> > > +#define CLK_BUS_EMAC1 85
> > > +#define CLK_TS 86
> > > +#define CLK_BUS_TS 87
> > > +#define CLK_BUS_THS 88
> > > +#define CLK_SPDIF 89
> > > +#define CLK_BUS_SPDIF 90
> > > +#define CLK_DMIC 91
> > > +#define CLK_BUS_DMIC 92
> > > +#define CLK_AUDIO_CODEC_1X 93
> > > +#define CLK_AUDIO_CODEC_4X 94
> > > +#define CLK_BUS_AUDIO_CODEC 95
> > > +#define CLK_AUDIO_HUB 96
> > > +#define CLK_BUS_AUDIO_HUB 97
> > > +#define CLK_USB_OHCI0 98
> > > +#define CLK_USB_PHY0 99
> > > +#define CLK_USB_OHCI1 100
> > > +#define CLK_USB_PHY1 101
> > > +#define CLK_USB_OHCI2 102
> > > +#define CLK_USB_PHY2 103
> > > +#define CLK_USB_OHCI3 104
> > > +#define CLK_USB_PHY3 105
> > > +#define CLK_BUS_OHCI0 106
> > > +#define CLK_BUS_OHCI1 107
> > > +#define CLK_BUS_OHCI2 108
> > > +#define CLK_BUS_OHCI3 109
> > > +#define CLK_BUS_EHCI0 110
> > > +#define CLK_BUS_EHCI1 111
> > > +#define CLK_BUS_EHCI2 112
> > > +#define CLK_BUS_EHCI3 113
> > > +#define CLK_BUS_OTG 114
> > > +#define CLK_BUS_KEYADC 115
> > > +#define CLK_HDMI 116
> > > +#define CLK_HDMI_SLOW 117
> > > +#define CLK_HDMI_CEC 118
> > > +#define CLK_BUS_HDMI 119
> > > +#define CLK_BUS_TCON_TOP 120
> > > +#define CLK_TCON_TV0 121
> > > +#define CLK_BUS_TCON_TV0 122
> > > +#define CLK_HDCP 123
> > > +#define CLK_BUS_HDCP 124
> > > +
> > > +#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..1c992cfbbbab
> > > --- /dev/null
> > > +++ b/include/dt-bindings/reset/sun50i-h616-ccu.h
> > > @@ -0,0 +1,67 @@
> > > +// SPDX-License-Identifier: (GPL-2.0+ or MIT)
> > > +/*
> > > + * Copyright (C) 2017 Icenowy Zheng <icenowy@aosc.io>
> > > + */
> > > +
> > > +#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_HDCP 55
> > > +#define RST_BUS_KEYADC 56
> > > +
> > > +#endif /* _DT_BINDINGS_RESET_SUN50I_H616_H_ */
> > > --
> > > 2.17.5
> > >
> > >
> > >
^ permalink raw reply [flat|nested] 20+ messages in thread
* Re: [linux-sunxi] [PATCH 5/8] clk: sunxi-ng: Add support for the Allwinner H616 CCU
2020-12-02 13:54 ` [PATCH 5/8] clk: sunxi-ng: Add support for the Allwinner H616 CCU Andre Przywara
2020-12-02 15:56 ` Maxime Ripard
2020-12-02 21:03 ` Jernej Škrabec
@ 2020-12-09 14:33 ` Clément Péron
2020-12-09 21:35 ` André Przywara
2020-12-10 13:31 ` Icenowy Zheng
3 siblings, 1 reply; 20+ messages in thread
From: Clément Péron @ 2020-12-09 14:33 UTC (permalink / raw)
To: Andre Przywara
Cc: Maxime Ripard, Chen-Yu Tsai, Jernej Skrabec, Icenowy Zheng,
linux-arm-kernel, linux-sunxi, Linus Walleij, Rob Herring,
Yangtao Li, linux-kernel, Michael Turquette, Stephen Boyd,
Philipp Zabel, open list:COMMON CLK FRAMEWORK
Hi Andre,
I try to review this, and compare against the vendor Kernel
On Wed, 2 Dec 2020 at 14:54, Andre Przywara <andre.przywara@arm.com> wrote:
>
> 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 <andre.przywara@arm.com>
> ---
> drivers/clk/sunxi-ng/Kconfig | 7 +-
> drivers/clk/sunxi-ng/Makefile | 1 +
> drivers/clk/sunxi-ng/ccu-sun50i-h616.c | 1134 +++++++++++++++++++
> drivers/clk/sunxi-ng/ccu-sun50i-h616.h | 58 +
> include/dt-bindings/clock/sun50i-h616-ccu.h | 110 ++
> include/dt-bindings/reset/sun50i-h616-ccu.h | 67 ++
> 6 files changed, 1376 insertions(+), 1 deletion(-)
> 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
>
> diff --git a/drivers/clk/sunxi-ng/Kconfig b/drivers/clk/sunxi-ng/Kconfig
> index ce5f5847d5d3..cd46d8853876 100644
> --- a/drivers/clk/sunxi-ng/Kconfig
> +++ b/drivers/clk/sunxi-ng/Kconfig
> @@ -32,8 +32,13 @@ 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 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/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..3fbb258f0354
> --- /dev/null
> +++ b/drivers/clk/sunxi-ng/ccu-sun50i-h616.c
> @@ -0,0 +1,1134 @@
> +// SPDX-License-Identifier: GPL-2.0
> +/*
> + * Copyright (c) 2020 Arm Ltd.
> + * Based on the H6 CCU driver, which is:
> + * Copyright (c) 2017 Icenowy Zheng <icenowy@aosc.io>
> + */
> +
> +#include <linux/clk-provider.h>
> +#include <linux/io.h>
> +#include <linux/of_address.h>
> +#include <linux/platform_device.h>
> +
> +#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 = 4,
> + .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 = 4,
> + .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),
> + },
> +};
FYI the PLL video0 in your code is similar between H6/H616 but it's not the
same in the vendor kernel.
Vendor says for H6:
pll_video0/pll_video1: 24*N/D1/4
for H616:
pll_video0x4 24*N/D1
pll_video1/pll_video2: 24*N/D1/4
I'm not sure if this comment is correct or not.
> +
> +#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),
> + },
> +};
There is also a PLL_CSI. And all the CSI / LCD clocks but they are no
output pins available in the H616.
Maybe we can introduced these clocks later.
> +
> +#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, 3, /* M */
M here should be 0,2
> + 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);
Compare to H6, you drop mbus-deinterlace but it is present in the vendor kernel.
> +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 2 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", "osc12M", 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 struct clk_fixed_factor pll_periph0_4x_clk;
> +
> +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),
> +
> + .mux = {
> + .shift = 24,
> + .width = 2,
> +
> + .fixed_predivs = hdmi_cec_predivs,
> + .n_predivs = ARRAY_SIZE(hdmi_cec_predivs),
> + },
> +
> + .common = {
> + .reg = 0xb10,
> + .features = CCU_FEATURE_VARIABLE_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_tv0_parents[] = { "pll-video0",
> + "pll-video0-4x",
> + "pll-video1",
> + "pll-video1-4x" };
> +static SUNXI_CCU_MP_WITH_MUX_GATE(tcon_tv0_clk, "tcon-tv0",
> + tcon_tv0_parents, 0xb80,
> + 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);
The TV1 clk is missing here
> +
> +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_4x_clk, "pll-periph0-4x",
> + pll_periph0_parents,
> + 1, 4, 0);
> +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_4x_clk, "pll-periph1-4x",
> + pll_periph1_parents,
> + 1, 4, 0);
> +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,
> + &bus_tcon_tv0_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_PERIPH0_4X] = &pll_periph0_4x_clk.hw,
> + [CLK_PLL_PERIPH1] = &pll_periph1_clk.common.hw,
> + [CLK_PLL_PERIPH1_2X] = &pll_periph1_2x_clk.hw,
> + [CLK_PLL_PERIPH1_4X] = &pll_periph1_4x_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_BUS_TCON_TV0] = &bus_tcon_tv0_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_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 int sun50i_h616_ccu_probe(struct platform_device *pdev)
> +{
> + struct resource *res;
> + void __iomem *reg;
> + u32 val;
> + int i;
> +
> + res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
> + reg = devm_ioremap_resource(&pdev->dev, res);
> + if (IS_ERR(reg))
> + return PTR_ERR(reg);
> +
> + /* Enable the lock bits on all PLLs */
> + for (i = 0; i < ARRAY_SIZE(pll_regs); i++) {
> + val = readl(reg + pll_regs[i]);
> + val |= BIT(29);
> + 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);
> +
> + return sunxi_ccu_probe(pdev->dev.of_node, reg, &sun50i_h616_ccu_desc);
> +}
> +
> +static const struct of_device_id sun50i_h616_ccu_ids[] = {
> + { .compatible = "allwinner,sun50i-h616-ccu",
> + .data = &sun50i_h616_ccu_desc },
> + { }
> +};
> +
> +static struct platform_driver sun50i_h616_ccu_driver = {
> + .probe = sun50i_h616_ccu_probe,
> + .driver = {
> + .name = "sun50i-h616-ccu",
> + .of_match_table = sun50i_h616_ccu_ids,
> + },
> +};
> +builtin_platform_driver(sun50i_h616_ccu_driver);
> 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..da8f0b1206f9
> --- /dev/null
> +++ b/drivers/clk/sunxi-ng/ccu-sun50i-h616.h
> @@ -0,0 +1,58 @@
> +/* SPDX-License-Identifier: GPL-2.0 */
> +/*
> + * Copyright 2020 Arm Ltd.
> + */
> +
> +#ifndef _CCU_SUN50I_H616_H_
> +#define _CCU_SUN50I_H616_H_
> +
> +#include <dt-bindings/clock/sun50i-h616-ccu.h>
> +#include <dt-bindings/reset/sun50i-h616-ccu.h>
> +
> +#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_PERIPH0_4X 6
> +#define CLK_PLL_PERIPH1 7
> +#define CLK_PLL_PERIPH1_2X 8
> +#define CLK_PLL_PERIPH1_4X 9
> +#define CLK_PLL_GPU 10
> +#define CLK_PLL_VIDEO0 11
> +#define CLK_PLL_VIDEO0_4X 12
> +#define CLK_PLL_VIDEO1 13
> +#define CLK_PLL_VIDEO1_4X 14
> +#define CLK_PLL_VIDEO2 15
> +#define CLK_PLL_VIDEO2_4X 16
> +#define CLK_PLL_VE 17
> +#define CLK_PLL_DE 18
> +#define CLK_PLL_AUDIO_HS 19
> +#define CLK_PLL_AUDIO_1X 20
> +#define CLK_PLL_AUDIO_2X 21
> +#define CLK_PLL_AUDIO_4X 22
> +
> +/* CPUX clock exported for DVFS */
> +
> +#define CLK_AXI 24
> +#define CLK_CPUX_APB 25
> +#define CLK_PSI_AHB1_AHB2 26
> +#define CLK_AHB3 27
> +
> +/* APB1 clock exported for PIO */
> +
> +#define CLK_APB2 29
> +#define CLK_MBUS 30
> +
> +/* All module clocks and bus gates are exported except DRAM */
> +
> +#define CLK_DRAM 51
> +
> +#define CLK_BUS_DRAM 58
> +
> +#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..a9cc8844e3a9
> --- /dev/null
> +++ b/include/dt-bindings/clock/sun50i-h616-ccu.h
> @@ -0,0 +1,110 @@
> +// 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 23
> +
> +#define CLK_APB1 28
> +
> +#define CLK_DE 31
> +#define CLK_BUS_DE 32
> +#define CLK_DEINTERLACE 33
> +#define CLK_BUS_DEINTERLACE 34
> +#define CLK_G2D 35
> +#define CLK_BUS_G2D 36
> +#define CLK_GPU0 37
> +#define CLK_BUS_GPU 38
> +#define CLK_GPU1 39
> +#define CLK_CE 40
> +#define CLK_BUS_CE 41
> +#define CLK_VE 42
> +#define CLK_BUS_VE 43
> +#define CLK_BUS_DMA 44
> +#define CLK_BUS_HSTIMER 45
> +#define CLK_AVS 46
> +#define CLK_BUS_DBG 47
> +#define CLK_BUS_PSI 48
> +#define CLK_BUS_PWM 49
> +#define CLK_BUS_IOMMU 50
> +
> +#define CLK_MBUS_DMA 52
> +#define CLK_MBUS_VE 53
> +#define CLK_MBUS_CE 54
> +#define CLK_MBUS_TS 55
> +#define CLK_MBUS_NAND 56
> +#define CLK_MBUS_G2D 57
> +
> +#define CLK_NAND0 59
> +#define CLK_NAND1 60
> +#define CLK_BUS_NAND 61
> +#define CLK_MMC0 62
> +#define CLK_MMC1 63
> +#define CLK_MMC2 64
> +#define CLK_BUS_MMC0 65
> +#define CLK_BUS_MMC1 66
> +#define CLK_BUS_MMC2 67
> +#define CLK_BUS_UART0 68
> +#define CLK_BUS_UART1 69
> +#define CLK_BUS_UART2 70
> +#define CLK_BUS_UART3 71
> +#define CLK_BUS_UART4 72
> +#define CLK_BUS_UART5 73
> +#define CLK_BUS_I2C0 74
> +#define CLK_BUS_I2C1 75
> +#define CLK_BUS_I2C2 76
> +#define CLK_BUS_I2C3 77
> +#define CLK_BUS_I2C4 78
> +#define CLK_SPI0 79
> +#define CLK_SPI1 80
> +#define CLK_BUS_SPI0 81
> +#define CLK_BUS_SPI1 82
> +#define CLK_EMAC_25M 83
> +#define CLK_BUS_EMAC0 84
> +#define CLK_BUS_EMAC1 85
> +#define CLK_TS 86
> +#define CLK_BUS_TS 87
> +#define CLK_BUS_THS 88
> +#define CLK_SPDIF 89
> +#define CLK_BUS_SPDIF 90
> +#define CLK_DMIC 91
> +#define CLK_BUS_DMIC 92
> +#define CLK_AUDIO_CODEC_1X 93
> +#define CLK_AUDIO_CODEC_4X 94
> +#define CLK_BUS_AUDIO_CODEC 95
> +#define CLK_AUDIO_HUB 96
> +#define CLK_BUS_AUDIO_HUB 97
> +#define CLK_USB_OHCI0 98
> +#define CLK_USB_PHY0 99
> +#define CLK_USB_OHCI1 100
> +#define CLK_USB_PHY1 101
> +#define CLK_USB_OHCI2 102
> +#define CLK_USB_PHY2 103
> +#define CLK_USB_OHCI3 104
> +#define CLK_USB_PHY3 105
> +#define CLK_BUS_OHCI0 106
> +#define CLK_BUS_OHCI1 107
> +#define CLK_BUS_OHCI2 108
> +#define CLK_BUS_OHCI3 109
> +#define CLK_BUS_EHCI0 110
> +#define CLK_BUS_EHCI1 111
> +#define CLK_BUS_EHCI2 112
> +#define CLK_BUS_EHCI3 113
> +#define CLK_BUS_OTG 114
> +#define CLK_BUS_KEYADC 115
> +#define CLK_HDMI 116
> +#define CLK_HDMI_SLOW 117
> +#define CLK_HDMI_CEC 118
> +#define CLK_BUS_HDMI 119
> +#define CLK_BUS_TCON_TOP 120
> +#define CLK_TCON_TV0 121
> +#define CLK_BUS_TCON_TV0 122
> +#define CLK_HDCP 123
> +#define CLK_BUS_HDCP 124
> +
> +#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..1c992cfbbbab
> --- /dev/null
> +++ b/include/dt-bindings/reset/sun50i-h616-ccu.h
> @@ -0,0 +1,67 @@
> +// SPDX-License-Identifier: (GPL-2.0+ or MIT)
> +/*
> + * Copyright (C) 2017 Icenowy Zheng <icenowy@aosc.io>
> + */
> +
> +#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_HDCP 55
> +#define RST_BUS_KEYADC 56
> +
> +#endif /* _DT_BINDINGS_RESET_SUN50I_H616_H_ */
> --
> 2.17.5
>
> --
> You received this message because you are subscribed to the Google Groups "linux-sunxi" group.
> To unsubscribe from this group and stop receiving emails from it, send an email to linux-sunxi+unsubscribe@googlegroups.com.
> To view this discussion on the web, visit https://groups.google.com/d/msgid/linux-sunxi/20201202135409.13683-6-andre.przywara%40arm.com.
^ permalink raw reply [flat|nested] 20+ messages in thread
* Re: [linux-sunxi] [PATCH 5/8] clk: sunxi-ng: Add support for the Allwinner H616 CCU
2020-12-09 14:33 ` [linux-sunxi] " Clément Péron
@ 2020-12-09 21:35 ` André Przywara
2020-12-09 22:20 ` Jernej Škrabec
0 siblings, 1 reply; 20+ messages in thread
From: André Przywara @ 2020-12-09 21:35 UTC (permalink / raw)
To: Clément Péron
Cc: Maxime Ripard, Chen-Yu Tsai, Jernej Skrabec, Icenowy Zheng,
linux-arm-kernel, linux-sunxi, Linus Walleij, Rob Herring,
Yangtao Li, linux-kernel, Michael Turquette, Stephen Boyd,
Philipp Zabel, open list:COMMON CLK FRAMEWORK
On 09/12/2020 14:33, Clément Péron wrote:
Hi,
> I try to review this, and compare against the vendor Kernel>
> On Wed, 2 Dec 2020 at 14:54, Andre Przywara <andre.przywara@arm.com> wrote:
>>
>> 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 <andre.przywara@arm.com>
>> ---
>> drivers/clk/sunxi-ng/Kconfig | 7 +-
>> drivers/clk/sunxi-ng/Makefile | 1 +
>> drivers/clk/sunxi-ng/ccu-sun50i-h616.c | 1134 +++++++++++++++++++
>> drivers/clk/sunxi-ng/ccu-sun50i-h616.h | 58 +
>> include/dt-bindings/clock/sun50i-h616-ccu.h | 110 ++
>> include/dt-bindings/reset/sun50i-h616-ccu.h | 67 ++
>> 6 files changed, 1376 insertions(+), 1 deletion(-)
>> 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
>>
>> diff --git a/drivers/clk/sunxi-ng/Kconfig b/drivers/clk/sunxi-ng/Kconfig
>> index ce5f5847d5d3..cd46d8853876 100644
>> --- a/drivers/clk/sunxi-ng/Kconfig
>> +++ b/drivers/clk/sunxi-ng/Kconfig
>> @@ -32,8 +32,13 @@ 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 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/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..3fbb258f0354
>> --- /dev/null
>> +++ b/drivers/clk/sunxi-ng/ccu-sun50i-h616.c
>> @@ -0,0 +1,1134 @@
>> +// SPDX-License-Identifier: GPL-2.0
>> +/*
>> + * Copyright (c) 2020 Arm Ltd.
>> + * Based on the H6 CCU driver, which is:
>> + * Copyright (c) 2017 Icenowy Zheng <icenowy@aosc.io>
>> + */
>> +
>> +#include <linux/clk-provider.h>
>> +#include <linux/io.h>
>> +#include <linux/of_address.h>
>> +#include <linux/platform_device.h>
>> +
>> +#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 = 4,
>> + .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 = 4,
>> + .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),
>> + },
>> +};
>
> FYI the PLL video0 in your code is similar between H6/H616 but it's not the
> same in the vendor kernel.
> Vendor says for H6:
> pll_video0/pll_video1: 24*N/D1/4
> for H616:
> pll_video0x4 24*N/D1
> pll_video1/pll_video2: 24*N/D1/4
I don't see any particular problem with this? I mean we pretty surely
have the x4 clock on the H6, and for the H616 the manual agrees to your
findings?
> I'm not sure if this comment is correct or not.
>
>> +
>> +#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),
>> + },
>> +};
>
> There is also a PLL_CSI. And all the CSI / LCD clocks but they are no
> output pins available in the H616.
> Maybe we can introduced these clocks later.
I don't see good reasons to introduce undocumented and useless clocks at
this point.
So I will leave this out unless someone protests.
>> +
>> +#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, 3, /* M */
>
> M here should be 0,2
Right, good catch.
>> + 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);
>
> Compare to H6, you drop mbus-deinterlace but it is present in the vendor kernel.
It's not in the manual (which is what I look at). Not sure I can trust
the vendor kernel more here.
>> +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 2 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", "osc12M", 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 struct clk_fixed_factor pll_periph0_4x_clk;
>> +
>> +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),
>> +
>> + .mux = {
>> + .shift = 24,
>> + .width = 2,
>> +
>> + .fixed_predivs = hdmi_cec_predivs,
>> + .n_predivs = ARRAY_SIZE(hdmi_cec_predivs),
>> + },
>> +
>> + .common = {
>> + .reg = 0xb10,
>> + .features = CCU_FEATURE_VARIABLE_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_tv0_parents[] = { "pll-video0",
>> + "pll-video0-4x",
>> + "pll-video1",
>> + "pll-video1-4x" };
>> +static SUNXI_CCU_MP_WITH_MUX_GATE(tcon_tv0_clk, "tcon-tv0",
>> + tcon_tv0_parents, 0xb80,
>> + 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);
>
> The TV1 clk is missing here
Right, and some more TV encoder related.
Cheers,
Andre
^ permalink raw reply [flat|nested] 20+ messages in thread
* Re: [linux-sunxi] [PATCH 5/8] clk: sunxi-ng: Add support for the Allwinner H616 CCU
2020-12-09 21:35 ` André Przywara
@ 2020-12-09 22:20 ` Jernej Škrabec
2020-12-09 22:45 ` André Przywara
0 siblings, 1 reply; 20+ messages in thread
From: Jernej Škrabec @ 2020-12-09 22:20 UTC (permalink / raw)
To: Clément Péron, André Przywara
Cc: Maxime Ripard, Chen-Yu Tsai, Icenowy Zheng, linux-arm-kernel,
linux-sunxi, Linus Walleij, Rob Herring, Yangtao Li,
linux-kernel, Michael Turquette, Stephen Boyd, Philipp Zabel,
open list:COMMON CLK FRAMEWORK
Dne sreda, 09. december 2020 ob 22:35:51 CET je André Przywara napisal(a):
> On 09/12/2020 14:33, Clément Péron wrote:
>
> Hi,
>
> > I try to review this, and compare against the vendor Kernel>
> >
> > On Wed, 2 Dec 2020 at 14:54, Andre Przywara <andre.przywara@arm.com>
wrote:
> >> 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 <andre.przywara@arm.com>
> >> ---
> >>
> >> drivers/clk/sunxi-ng/Kconfig | 7 +-
> >> drivers/clk/sunxi-ng/Makefile | 1 +
> >> drivers/clk/sunxi-ng/ccu-sun50i-h616.c | 1134 +++++++++++++++++++
> >> drivers/clk/sunxi-ng/ccu-sun50i-h616.h | 58 +
> >> include/dt-bindings/clock/sun50i-h616-ccu.h | 110 ++
> >> include/dt-bindings/reset/sun50i-h616-ccu.h | 67 ++
> >> 6 files changed, 1376 insertions(+), 1 deletion(-)
> >> 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
> >>
> >> diff --git a/drivers/clk/sunxi-ng/Kconfig b/drivers/clk/sunxi-ng/Kconfig
> >> index ce5f5847d5d3..cd46d8853876 100644
> >> --- a/drivers/clk/sunxi-ng/Kconfig
> >> +++ b/drivers/clk/sunxi-ng/Kconfig
> >> @@ -32,8 +32,13 @@ 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 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/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..3fbb258f0354
> >> --- /dev/null
> >> +++ b/drivers/clk/sunxi-ng/ccu-sun50i-h616.c
> >> @@ -0,0 +1,1134 @@
> >> +// SPDX-License-Identifier: GPL-2.0
> >> +/*
> >> + * Copyright (c) 2020 Arm Ltd.
> >> + * Based on the H6 CCU driver, which is:
> >> + * Copyright (c) 2017 Icenowy Zheng <icenowy@aosc.io>
> >> + */
> >> +
> >> +#include <linux/clk-provider.h>
> >> +#include <linux/io.h>
> >> +#include <linux/of_address.h>
> >> +#include <linux/platform_device.h>
> >> +
> >> +#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 = 4,
> >> + .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 = 4,
> >> + .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),
> >> + },
> >> +};
> >
> > FYI the PLL video0 in your code is similar between H6/H616 but it's not
> > the
> > same in the vendor kernel.
> > Vendor says for H6:
> > pll_video0/pll_video1: 24*N/D1/4
> > for H616:
> > pll_video0x4 24*N/D1
> > pll_video1/pll_video2: 24*N/D1/4
>
> I don't see any particular problem with this? I mean we pretty surely
> have the x4 clock on the H6, and for the H616 the manual agrees to your
> findings?
>
> > I'm not sure if this comment is correct or not.
> >
> >> +
> >> +#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),
> >> + },
> >> +};
> >
> > There is also a PLL_CSI. And all the CSI / LCD clocks but they are no
> > output pins available in the H616.
> > Maybe we can introduced these clocks later.
>
> I don't see good reasons to introduce undocumented and useless clocks at
> this point.
> So I will leave this out unless someone protests.
I'm pretty sure that H616 datasheet describes only subset of functionality
supported by die and BSP drivers cover full die functionality. Not only here,
but everywhere. We can leave them out for now.
>
> >> +
> >> +#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, 3, /* M */
> >
> > M here should be 0,2
>
> Right, good catch.
>
> >> + 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);
> >
> > Compare to H6, you drop mbus-deinterlace but it is present in the vendor
> > kernel.
> It's not in the manual (which is what I look at). Not sure I can trust
> the vendor kernel more here.
This would need some experimenting.
Best regards,
Jernej
>
> >> +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 2 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", "osc12M",
> >> 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 struct clk_fixed_factor pll_periph0_4x_clk;
> >> +
> >> +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),
> >> +
> >> + .mux = {
> >> + .shift = 24,
> >> + .width = 2,
> >> +
> >> + .fixed_predivs = hdmi_cec_predivs,
> >> + .n_predivs = ARRAY_SIZE(hdmi_cec_predivs),
> >> + },
> >> +
> >> + .common = {
> >> + .reg = 0xb10,
> >> + .features = CCU_FEATURE_VARIABLE_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_tv0_parents[] = { "pll-video0",
> >> + "pll-video0-4x",
> >> + "pll-video1",
> >> + "pll-video1-4x" };
> >> +static SUNXI_CCU_MP_WITH_MUX_GATE(tcon_tv0_clk, "tcon-tv0",
> >> + tcon_tv0_parents, 0xb80,
> >> + 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);
> >
> > The TV1 clk is missing here
>
> Right, and some more TV encoder related.
>
> Cheers,
> Andre
^ permalink raw reply [flat|nested] 20+ messages in thread
* Re: [linux-sunxi] [PATCH 5/8] clk: sunxi-ng: Add support for the Allwinner H616 CCU
2020-12-09 22:20 ` Jernej Škrabec
@ 2020-12-09 22:45 ` André Przywara
0 siblings, 0 replies; 20+ messages in thread
From: André Przywara @ 2020-12-09 22:45 UTC (permalink / raw)
To: Jernej Škrabec, Clément Péron
Cc: Maxime Ripard, Chen-Yu Tsai, Icenowy Zheng, linux-arm-kernel,
linux-sunxi, Linus Walleij, Rob Herring, Yangtao Li,
linux-kernel, Michael Turquette, Stephen Boyd, Philipp Zabel,
open list:COMMON CLK FRAMEWORK
On 09/12/2020 22:20, Jernej Škrabec wrote:
> Dne sreda, 09. december 2020 ob 22:35:51 CET je André Przywara napisal(a):
>> On 09/12/2020 14:33, Clément Péron wrote:
>>
>> Hi,
>>
>>> I try to review this, and compare against the vendor Kernel>
>>>
>>> On Wed, 2 Dec 2020 at 14:54, Andre Przywara <andre.przywara@arm.com>
> wrote:
>>>> 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 <andre.przywara@arm.com>
>>>> ---
>>>>
>>>> drivers/clk/sunxi-ng/Kconfig | 7 +-
>>>> drivers/clk/sunxi-ng/Makefile | 1 +
>>>> drivers/clk/sunxi-ng/ccu-sun50i-h616.c | 1134 +++++++++++++++++++
>>>> drivers/clk/sunxi-ng/ccu-sun50i-h616.h | 58 +
>>>> include/dt-bindings/clock/sun50i-h616-ccu.h | 110 ++
>>>> include/dt-bindings/reset/sun50i-h616-ccu.h | 67 ++
>>>> 6 files changed, 1376 insertions(+), 1 deletion(-)
>>>> 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
>>>>
>>>> diff --git a/drivers/clk/sunxi-ng/Kconfig b/drivers/clk/sunxi-ng/Kconfig
>>>> index ce5f5847d5d3..cd46d8853876 100644
>>>> --- a/drivers/clk/sunxi-ng/Kconfig
>>>> +++ b/drivers/clk/sunxi-ng/Kconfig
>>>> @@ -32,8 +32,13 @@ 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 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/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..3fbb258f0354
>>>> --- /dev/null
>>>> +++ b/drivers/clk/sunxi-ng/ccu-sun50i-h616.c
>>>> @@ -0,0 +1,1134 @@
>>>> +// SPDX-License-Identifier: GPL-2.0
>>>> +/*
>>>> + * Copyright (c) 2020 Arm Ltd.
>>>> + * Based on the H6 CCU driver, which is:
>>>> + * Copyright (c) 2017 Icenowy Zheng <icenowy@aosc.io>
>>>> + */
>>>> +
>>>> +#include <linux/clk-provider.h>
>>>> +#include <linux/io.h>
>>>> +#include <linux/of_address.h>
>>>> +#include <linux/platform_device.h>
>>>> +
>>>> +#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 = 4,
>>>> + .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 = 4,
>>>> + .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),
>>>> + },
>>>> +};
>>>
>>> FYI the PLL video0 in your code is similar between H6/H616 but it's not
>>> the
>>> same in the vendor kernel.
>>> Vendor says for H6:
>>> pll_video0/pll_video1: 24*N/D1/4
>>> for H616:
>>> pll_video0x4 24*N/D1
>>> pll_video1/pll_video2: 24*N/D1/4
>>
>> I don't see any particular problem with this? I mean we pretty surely
>> have the x4 clock on the H6, and for the H616 the manual agrees to your
>> findings?
>>
>>> I'm not sure if this comment is correct or not.
>>>
>>>> +
>>>> +#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),
>>>> + },
>>>> +};
>>>
>>> There is also a PLL_CSI. And all the CSI / LCD clocks but they are no
>>> output pins available in the H616.
>>> Maybe we can introduced these clocks later.
>>
>> I don't see good reasons to introduce undocumented and useless clocks at
>> this point.
>> So I will leave this out unless someone protests.
>
> I'm pretty sure that H616 datasheet describes only subset of functionality
> supported by die and BSP drivers cover full die functionality.
Yeah, Clément found a comment in the BSP U-Boot that suggests that the
same die is used with different packages. The H700 is mentioned as a
sun50iw9p1 there as well, and this one supports LCD, reportedly.
> Not only here,
> but everywhere. We can leave them out for now.
Right, we can add them later, maybe using a new clock compatible, like
we do for the H3/H5.
Cheers,
Andre
>>>> +
>>>> +#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, 3, /* M */
>>>
>>> M here should be 0,2
>>
>> Right, good catch.
>>
>>>> + 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);
>>>
>>> Compare to H6, you drop mbus-deinterlace but it is present in the vendor
>>> kernel.
>> It's not in the manual (which is what I look at). Not sure I can trust
>> the vendor kernel more here.
>
> This would need some experimenting.
>
> Best regards,
> Jernej
>
>>
>>>> +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 2 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", "osc12M",
>>>> 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 struct clk_fixed_factor pll_periph0_4x_clk;
>>>> +
>>>> +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),
>>>> +
>>>> + .mux = {
>>>> + .shift = 24,
>>>> + .width = 2,
>>>> +
>>>> + .fixed_predivs = hdmi_cec_predivs,
>>>> + .n_predivs = ARRAY_SIZE(hdmi_cec_predivs),
>>>> + },
>>>> +
>>>> + .common = {
>>>> + .reg = 0xb10,
>>>> + .features = CCU_FEATURE_VARIABLE_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_tv0_parents[] = { "pll-video0",
>>>> + "pll-video0-4x",
>>>> + "pll-video1",
>>>> + "pll-video1-4x" };
>>>> +static SUNXI_CCU_MP_WITH_MUX_GATE(tcon_tv0_clk, "tcon-tv0",
>>>> + tcon_tv0_parents, 0xb80,
>>>> + 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);
>>>
>>> The TV1 clk is missing here
>>
>> Right, and some more TV encoder related.
>>
>> Cheers,
>> Andre
>
>
>
>
>
^ permalink raw reply [flat|nested] 20+ messages in thread
* Re: [linux-sunxi] [PATCH 5/8] clk: sunxi-ng: Add support for the Allwinner H616 CCU
2020-12-02 13:54 ` [PATCH 5/8] clk: sunxi-ng: Add support for the Allwinner H616 CCU Andre Przywara
` (2 preceding siblings ...)
2020-12-09 14:33 ` [linux-sunxi] " Clément Péron
@ 2020-12-10 13:31 ` Icenowy Zheng
2020-12-10 14:34 ` André Przywara
3 siblings, 1 reply; 20+ messages in thread
From: Icenowy Zheng @ 2020-12-10 13:31 UTC (permalink / raw)
To: andre.przywara, Maxime Ripard, Chen-Yu Tsai, Jernej Skrabec
Cc: Icenowy Zheng, linux-arm-kernel, linux-sunxi, Linus Walleij,
Rob Herring, Yangtao Li, linux-kernel, Michael Turquette,
Stephen Boyd, Philipp Zabel, linux-clk
在 2020-12-02星期三的 13:54 +0000,Andre Przywara写道:
> 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 <andre.przywara@arm.com>
> ---
> drivers/clk/sunxi-ng/Kconfig | 7 +-
> drivers/clk/sunxi-ng/Makefile | 1 +
> drivers/clk/sunxi-ng/ccu-sun50i-h616.c | 1134
> +++++++++++++++++++
> drivers/clk/sunxi-ng/ccu-sun50i-h616.h | 58 +
> include/dt-bindings/clock/sun50i-h616-ccu.h | 110 ++
> include/dt-bindings/reset/sun50i-h616-ccu.h | 67 ++
> 6 files changed, 1376 insertions(+), 1 deletion(-)
> 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
>
> diff --git a/drivers/clk/sunxi-ng/Kconfig b/drivers/clk/sunxi-
> ng/Kconfig
> index ce5f5847d5d3..cd46d8853876 100644
> --- a/drivers/clk/sunxi-ng/Kconfig
> +++ b/drivers/clk/sunxi-ng/Kconfig
> @@ -32,8 +32,13 @@ 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 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/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..3fbb258f0354
> --- /dev/null
> +++ b/drivers/clk/sunxi-ng/ccu-sun50i-h616.c
> @@ -0,0 +1,1134 @@
> +// SPDX-License-Identifier: GPL-2.0
> +/*
> + * Copyright (c) 2020 Arm Ltd.
> + * Based on the H6 CCU driver, which is:
> + * Copyright (c) 2017 Icenowy Zheng <icenowy@aosc.io>
> + */
> +
> +#include <linux/clk-provider.h>
> +#include <linux/io.h>
> +#include <linux/of_address.h>
> +#include <linux/platform_device.h>
> +
> +#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 = 4,
Isn't it 2 here?
The user manual says:
```
PLL_PERI0(2X) = 24 MHz*N/M0/M1
PLL_PERI0(1X) = 24 MHz*N/M0/M1/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 = 4,
> + .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, 3, /* 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 2 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", "osc12M", 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 struct clk_fixed_factor pll_periph0_4x_clk;
> +
> +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),
> +
> + .mux = {
> + .shift = 24,
> + .width = 2,
> +
> + .fixed_predivs = hdmi_cec_predivs,
> + .n_predivs = ARRAY_SIZE(hdmi_cec_predivs),
> + },
> +
> + .common = {
> + .reg = 0xb10,
> + .features = CCU_FEATURE_VARIABLE_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_tv0_parents[] = { "pll-video0",
> + "pll-video0-4x",
> + "pll-video1",
> + "pll-video1-4x" };
> +static SUNXI_CCU_MP_WITH_MUX_GATE(tcon_tv0_clk, "tcon-tv0",
> + tcon_tv0_parents, 0xb80,
> + 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 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_4x_clk, "pll-periph0-4x",
> + pll_periph0_parents,
> + 1, 4, 0);
> +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_4x_clk, "pll-periph1-4x",
> + pll_periph1_parents,
> + 1, 4, 0);
> +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,
> + &bus_tcon_tv0_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_PERIPH0_4X] = &pll_periph0_4x_clk.hw,
> + [CLK_PLL_PERIPH1] = &pll_periph1_clk.common.hw,
> + [CLK_PLL_PERIPH1_2X] = &pll_periph1_2x_clk.hw,
> + [CLK_PLL_PERIPH1_4X] = &pll_periph1_4x_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_BUS_TCON_TV0] =
> &bus_tcon_tv0_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_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 int sun50i_h616_ccu_probe(struct platform_device *pdev)
> +{
> + struct resource *res;
> + void __iomem *reg;
> + u32 val;
> + int i;
> +
> + res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
> + reg = devm_ioremap_resource(&pdev->dev, res);
> + if (IS_ERR(reg))
> + return PTR_ERR(reg);
> +
> + /* Enable the lock bits on all PLLs */
> + for (i = 0; i < ARRAY_SIZE(pll_regs); i++) {
> + val = readl(reg + pll_regs[i]);
> + val |= BIT(29);
> + 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);
> +
> + return sunxi_ccu_probe(pdev->dev.of_node, reg,
> &sun50i_h616_ccu_desc);
> +}
> +
> +static const struct of_device_id sun50i_h616_ccu_ids[] = {
> + { .compatible = "allwinner,sun50i-h616-ccu",
> + .data = &sun50i_h616_ccu_desc },
> + { }
> +};
> +
> +static struct platform_driver sun50i_h616_ccu_driver = {
> + .probe = sun50i_h616_ccu_probe,
> + .driver = {
> + .name = "sun50i-h616-ccu",
> + .of_match_table = sun50i_h616_ccu_ids,
> + },
> +};
> +builtin_platform_driver(sun50i_h616_ccu_driver);
> 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..da8f0b1206f9
> --- /dev/null
> +++ b/drivers/clk/sunxi-ng/ccu-sun50i-h616.h
> @@ -0,0 +1,58 @@
> +/* SPDX-License-Identifier: GPL-2.0 */
> +/*
> + * Copyright 2020 Arm Ltd.
> + */
> +
> +#ifndef _CCU_SUN50I_H616_H_
> +#define _CCU_SUN50I_H616_H_
> +
> +#include <dt-bindings/clock/sun50i-h616-ccu.h>
> +#include <dt-bindings/reset/sun50i-h616-ccu.h>
> +
> +#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_PERIPH0_4X 6
> +#define CLK_PLL_PERIPH1 7
> +#define CLK_PLL_PERIPH1_2X 8
> +#define CLK_PLL_PERIPH1_4X 9
> +#define CLK_PLL_GPU 10
> +#define CLK_PLL_VIDEO0 11
> +#define CLK_PLL_VIDEO0_4X 12
> +#define CLK_PLL_VIDEO1 13
> +#define CLK_PLL_VIDEO1_4X 14
> +#define CLK_PLL_VIDEO2 15
> +#define CLK_PLL_VIDEO2_4X 16
> +#define CLK_PLL_VE 17
> +#define CLK_PLL_DE 18
> +#define CLK_PLL_AUDIO_HS 19
> +#define CLK_PLL_AUDIO_1X 20
> +#define CLK_PLL_AUDIO_2X 21
> +#define CLK_PLL_AUDIO_4X 22
> +
> +/* CPUX clock exported for DVFS */
> +
> +#define CLK_AXI 24
> +#define CLK_CPUX_APB 25
> +#define CLK_PSI_AHB1_AHB2 26
> +#define CLK_AHB3 27
> +
> +/* APB1 clock exported for PIO */
> +
> +#define CLK_APB2 29
> +#define CLK_MBUS 30
> +
> +/* All module clocks and bus gates are exported except DRAM */
> +
> +#define CLK_DRAM 51
> +
> +#define CLK_BUS_DRAM 58
> +
> +#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..a9cc8844e3a9
> --- /dev/null
> +++ b/include/dt-bindings/clock/sun50i-h616-ccu.h
> @@ -0,0 +1,110 @@
> +// 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 23
> +
> +#define CLK_APB1 28
> +
> +#define CLK_DE 31
> +#define CLK_BUS_DE 32
> +#define CLK_DEINTERLACE 33
> +#define CLK_BUS_DEINTERLACE 34
> +#define CLK_G2D 35
> +#define CLK_BUS_G2D 36
> +#define CLK_GPU0 37
> +#define CLK_BUS_GPU 38
> +#define CLK_GPU1 39
> +#define CLK_CE 40
> +#define CLK_BUS_CE 41
> +#define CLK_VE 42
> +#define CLK_BUS_VE 43
> +#define CLK_BUS_DMA 44
> +#define CLK_BUS_HSTIMER 45
> +#define CLK_AVS 46
> +#define CLK_BUS_DBG 47
> +#define CLK_BUS_PSI 48
> +#define CLK_BUS_PWM 49
> +#define CLK_BUS_IOMMU 50
> +
> +#define CLK_MBUS_DMA 52
> +#define CLK_MBUS_VE 53
> +#define CLK_MBUS_CE 54
> +#define CLK_MBUS_TS 55
> +#define CLK_MBUS_NAND 56
> +#define CLK_MBUS_G2D 57
> +
> +#define CLK_NAND0 59
> +#define CLK_NAND1 60
> +#define CLK_BUS_NAND 61
> +#define CLK_MMC0 62
> +#define CLK_MMC1 63
> +#define CLK_MMC2 64
> +#define CLK_BUS_MMC0 65
> +#define CLK_BUS_MMC1 66
> +#define CLK_BUS_MMC2 67
> +#define CLK_BUS_UART0 68
> +#define CLK_BUS_UART1 69
> +#define CLK_BUS_UART2 70
> +#define CLK_BUS_UART3 71
> +#define CLK_BUS_UART4 72
> +#define CLK_BUS_UART5 73
> +#define CLK_BUS_I2C0 74
> +#define CLK_BUS_I2C1 75
> +#define CLK_BUS_I2C2 76
> +#define CLK_BUS_I2C3 77
> +#define CLK_BUS_I2C4 78
> +#define CLK_SPI0 79
> +#define CLK_SPI1 80
> +#define CLK_BUS_SPI0 81
> +#define CLK_BUS_SPI1 82
> +#define CLK_EMAC_25M 83
> +#define CLK_BUS_EMAC0 84
> +#define CLK_BUS_EMAC1 85
> +#define CLK_TS 86
> +#define CLK_BUS_TS 87
> +#define CLK_BUS_THS 88
> +#define CLK_SPDIF 89
> +#define CLK_BUS_SPDIF 90
> +#define CLK_DMIC 91
> +#define CLK_BUS_DMIC 92
> +#define CLK_AUDIO_CODEC_1X 93
> +#define CLK_AUDIO_CODEC_4X 94
> +#define CLK_BUS_AUDIO_CODEC 95
> +#define CLK_AUDIO_HUB 96
> +#define CLK_BUS_AUDIO_HUB 97
> +#define CLK_USB_OHCI0 98
> +#define CLK_USB_PHY0 99
> +#define CLK_USB_OHCI1 100
> +#define CLK_USB_PHY1 101
> +#define CLK_USB_OHCI2 102
> +#define CLK_USB_PHY2 103
> +#define CLK_USB_OHCI3 104
> +#define CLK_USB_PHY3 105
> +#define CLK_BUS_OHCI0 106
> +#define CLK_BUS_OHCI1 107
> +#define CLK_BUS_OHCI2 108
> +#define CLK_BUS_OHCI3 109
> +#define CLK_BUS_EHCI0 110
> +#define CLK_BUS_EHCI1 111
> +#define CLK_BUS_EHCI2 112
> +#define CLK_BUS_EHCI3 113
> +#define CLK_BUS_OTG 114
> +#define CLK_BUS_KEYADC 115
> +#define CLK_HDMI 116
> +#define CLK_HDMI_SLOW 117
> +#define CLK_HDMI_CEC 118
> +#define CLK_BUS_HDMI 119
> +#define CLK_BUS_TCON_TOP 120
> +#define CLK_TCON_TV0 121
> +#define CLK_BUS_TCON_TV0 122
> +#define CLK_HDCP 123
> +#define CLK_BUS_HDCP 124
> +
> +#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..1c992cfbbbab
> --- /dev/null
> +++ b/include/dt-bindings/reset/sun50i-h616-ccu.h
> @@ -0,0 +1,67 @@
> +// SPDX-License-Identifier: (GPL-2.0+ or MIT)
> +/*
> + * Copyright (C) 2017 Icenowy Zheng <icenowy@aosc.io>
> + */
> +
> +#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_HDCP 55
> +#define RST_BUS_KEYADC 56
> +
> +#endif /* _DT_BINDINGS_RESET_SUN50I_H616_H_ */
> --
> 2.17.5
>
^ permalink raw reply [flat|nested] 20+ messages in thread
* Re: [linux-sunxi] [PATCH 5/8] clk: sunxi-ng: Add support for the Allwinner H616 CCU
2020-12-10 13:31 ` Icenowy Zheng
@ 2020-12-10 14:34 ` André Przywara
0 siblings, 0 replies; 20+ messages in thread
From: André Przywara @ 2020-12-10 14:34 UTC (permalink / raw)
To: Icenowy Zheng, Maxime Ripard, Chen-Yu Tsai, Jernej Skrabec
Cc: Icenowy Zheng, linux-arm-kernel, linux-sunxi, Linus Walleij,
Rob Herring, Yangtao Li, linux-kernel, Michael Turquette,
Stephen Boyd, Philipp Zabel, linux-clk
On 10/12/2020 13:31, Icenowy Zheng wrote:
> 在 2020-12-02星期三的 13:54 +0000,Andre Przywara写道:
>> 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 <andre.przywara@arm.com>
>> ---
>> drivers/clk/sunxi-ng/Kconfig | 7 +-
>> drivers/clk/sunxi-ng/Makefile | 1 +
>> drivers/clk/sunxi-ng/ccu-sun50i-h616.c | 1134
>> +++++++++++++++++++
>> drivers/clk/sunxi-ng/ccu-sun50i-h616.h | 58 +
>> include/dt-bindings/clock/sun50i-h616-ccu.h | 110 ++
>> include/dt-bindings/reset/sun50i-h616-ccu.h | 67 ++
>> 6 files changed, 1376 insertions(+), 1 deletion(-)
>> 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
>>
>> diff --git a/drivers/clk/sunxi-ng/Kconfig b/drivers/clk/sunxi-
>> ng/Kconfig
>> index ce5f5847d5d3..cd46d8853876 100644
>> --- a/drivers/clk/sunxi-ng/Kconfig
>> +++ b/drivers/clk/sunxi-ng/Kconfig
>> @@ -32,8 +32,13 @@ 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 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/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..3fbb258f0354
>> --- /dev/null
>> +++ b/drivers/clk/sunxi-ng/ccu-sun50i-h616.c
>> @@ -0,0 +1,1134 @@
>> +// SPDX-License-Identifier: GPL-2.0
>> +/*
>> + * Copyright (c) 2020 Arm Ltd.
>> + * Based on the H6 CCU driver, which is:
>> + * Copyright (c) 2017 Icenowy Zheng <icenowy@aosc.io>
>> + */
>> +
>> +#include <linux/clk-provider.h>
>> +#include <linux/io.h>
>> +#include <linux/of_address.h>
>> +#include <linux/platform_device.h>
>> +
>> +#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 = 4,
>
> Isn't it 2 here?
>
> The user manual says:
>
> ```
> PLL_PERI0(2X) = 24 MHz*N/M0/M1
> PLL_PERI0(1X) = 24 MHz*N/M0/M1/2
Ouch, you are right, good catch!
I ripped out PLL_PERI0(4X) last minute, but missed that divider.
Thanks!
Andre
> ```
>
> + .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 = 4,
>> + .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, 3, /* 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 2 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", "osc12M", 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 struct clk_fixed_factor pll_periph0_4x_clk;
>> +
>> +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),
>> +
>> + .mux = {
>> + .shift = 24,
>> + .width = 2,
>> +
>> + .fixed_predivs = hdmi_cec_predivs,
>> + .n_predivs = ARRAY_SIZE(hdmi_cec_predivs),
>> + },
>> +
>> + .common = {
>> + .reg = 0xb10,
>> + .features = CCU_FEATURE_VARIABLE_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_tv0_parents[] = { "pll-video0",
>> + "pll-video0-4x",
>> + "pll-video1",
>> + "pll-video1-4x" };
>> +static SUNXI_CCU_MP_WITH_MUX_GATE(tcon_tv0_clk, "tcon-tv0",
>> + tcon_tv0_parents, 0xb80,
>> + 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 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_4x_clk, "pll-periph0-4x",
>> + pll_periph0_parents,
>> + 1, 4, 0);
>> +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_4x_clk, "pll-periph1-4x",
>> + pll_periph1_parents,
>> + 1, 4, 0);
>> +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,
>> + &bus_tcon_tv0_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_PERIPH0_4X] = &pll_periph0_4x_clk.hw,
>> + [CLK_PLL_PERIPH1] = &pll_periph1_clk.common.hw,
>> + [CLK_PLL_PERIPH1_2X] = &pll_periph1_2x_clk.hw,
>> + [CLK_PLL_PERIPH1_4X] = &pll_periph1_4x_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_BUS_TCON_TV0] =
>> &bus_tcon_tv0_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_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 int sun50i_h616_ccu_probe(struct platform_device *pdev)
>> +{
>> + struct resource *res;
>> + void __iomem *reg;
>> + u32 val;
>> + int i;
>> +
>> + res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
>> + reg = devm_ioremap_resource(&pdev->dev, res);
>> + if (IS_ERR(reg))
>> + return PTR_ERR(reg);
>> +
>> + /* Enable the lock bits on all PLLs */
>> + for (i = 0; i < ARRAY_SIZE(pll_regs); i++) {
>> + val = readl(reg + pll_regs[i]);
>> + val |= BIT(29);
>> + 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);
>> +
>> + return sunxi_ccu_probe(pdev->dev.of_node, reg,
>> &sun50i_h616_ccu_desc);
>> +}
>> +
>> +static const struct of_device_id sun50i_h616_ccu_ids[] = {
>> + { .compatible = "allwinner,sun50i-h616-ccu",
>> + .data = &sun50i_h616_ccu_desc },
>> + { }
>> +};
>> +
>> +static struct platform_driver sun50i_h616_ccu_driver = {
>> + .probe = sun50i_h616_ccu_probe,
>> + .driver = {
>> + .name = "sun50i-h616-ccu",
>> + .of_match_table = sun50i_h616_ccu_ids,
>> + },
>> +};
>> +builtin_platform_driver(sun50i_h616_ccu_driver);
>> 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..da8f0b1206f9
>> --- /dev/null
>> +++ b/drivers/clk/sunxi-ng/ccu-sun50i-h616.h
>> @@ -0,0 +1,58 @@
>> +/* SPDX-License-Identifier: GPL-2.0 */
>> +/*
>> + * Copyright 2020 Arm Ltd.
>> + */
>> +
>> +#ifndef _CCU_SUN50I_H616_H_
>> +#define _CCU_SUN50I_H616_H_
>> +
>> +#include <dt-bindings/clock/sun50i-h616-ccu.h>
>> +#include <dt-bindings/reset/sun50i-h616-ccu.h>
>> +
>> +#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_PERIPH0_4X 6
>> +#define CLK_PLL_PERIPH1 7
>> +#define CLK_PLL_PERIPH1_2X 8
>> +#define CLK_PLL_PERIPH1_4X 9
>> +#define CLK_PLL_GPU 10
>> +#define CLK_PLL_VIDEO0 11
>> +#define CLK_PLL_VIDEO0_4X 12
>> +#define CLK_PLL_VIDEO1 13
>> +#define CLK_PLL_VIDEO1_4X 14
>> +#define CLK_PLL_VIDEO2 15
>> +#define CLK_PLL_VIDEO2_4X 16
>> +#define CLK_PLL_VE 17
>> +#define CLK_PLL_DE 18
>> +#define CLK_PLL_AUDIO_HS 19
>> +#define CLK_PLL_AUDIO_1X 20
>> +#define CLK_PLL_AUDIO_2X 21
>> +#define CLK_PLL_AUDIO_4X 22
>> +
>> +/* CPUX clock exported for DVFS */
>> +
>> +#define CLK_AXI 24
>> +#define CLK_CPUX_APB 25
>> +#define CLK_PSI_AHB1_AHB2 26
>> +#define CLK_AHB3 27
>> +
>> +/* APB1 clock exported for PIO */
>> +
>> +#define CLK_APB2 29
>> +#define CLK_MBUS 30
>> +
>> +/* All module clocks and bus gates are exported except DRAM */
>> +
>> +#define CLK_DRAM 51
>> +
>> +#define CLK_BUS_DRAM 58
>> +
>> +#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..a9cc8844e3a9
>> --- /dev/null
>> +++ b/include/dt-bindings/clock/sun50i-h616-ccu.h
>> @@ -0,0 +1,110 @@
>> +// 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 23
>> +
>> +#define CLK_APB1 28
>> +
>> +#define CLK_DE 31
>> +#define CLK_BUS_DE 32
>> +#define CLK_DEINTERLACE 33
>> +#define CLK_BUS_DEINTERLACE 34
>> +#define CLK_G2D 35
>> +#define CLK_BUS_G2D 36
>> +#define CLK_GPU0 37
>> +#define CLK_BUS_GPU 38
>> +#define CLK_GPU1 39
>> +#define CLK_CE 40
>> +#define CLK_BUS_CE 41
>> +#define CLK_VE 42
>> +#define CLK_BUS_VE 43
>> +#define CLK_BUS_DMA 44
>> +#define CLK_BUS_HSTIMER 45
>> +#define CLK_AVS 46
>> +#define CLK_BUS_DBG 47
>> +#define CLK_BUS_PSI 48
>> +#define CLK_BUS_PWM 49
>> +#define CLK_BUS_IOMMU 50
>> +
>> +#define CLK_MBUS_DMA 52
>> +#define CLK_MBUS_VE 53
>> +#define CLK_MBUS_CE 54
>> +#define CLK_MBUS_TS 55
>> +#define CLK_MBUS_NAND 56
>> +#define CLK_MBUS_G2D 57
>> +
>> +#define CLK_NAND0 59
>> +#define CLK_NAND1 60
>> +#define CLK_BUS_NAND 61
>> +#define CLK_MMC0 62
>> +#define CLK_MMC1 63
>> +#define CLK_MMC2 64
>> +#define CLK_BUS_MMC0 65
>> +#define CLK_BUS_MMC1 66
>> +#define CLK_BUS_MMC2 67
>> +#define CLK_BUS_UART0 68
>> +#define CLK_BUS_UART1 69
>> +#define CLK_BUS_UART2 70
>> +#define CLK_BUS_UART3 71
>> +#define CLK_BUS_UART4 72
>> +#define CLK_BUS_UART5 73
>> +#define CLK_BUS_I2C0 74
>> +#define CLK_BUS_I2C1 75
>> +#define CLK_BUS_I2C2 76
>> +#define CLK_BUS_I2C3 77
>> +#define CLK_BUS_I2C4 78
>> +#define CLK_SPI0 79
>> +#define CLK_SPI1 80
>> +#define CLK_BUS_SPI0 81
>> +#define CLK_BUS_SPI1 82
>> +#define CLK_EMAC_25M 83
>> +#define CLK_BUS_EMAC0 84
>> +#define CLK_BUS_EMAC1 85
>> +#define CLK_TS 86
>> +#define CLK_BUS_TS 87
>> +#define CLK_BUS_THS 88
>> +#define CLK_SPDIF 89
>> +#define CLK_BUS_SPDIF 90
>> +#define CLK_DMIC 91
>> +#define CLK_BUS_DMIC 92
>> +#define CLK_AUDIO_CODEC_1X 93
>> +#define CLK_AUDIO_CODEC_4X 94
>> +#define CLK_BUS_AUDIO_CODEC 95
>> +#define CLK_AUDIO_HUB 96
>> +#define CLK_BUS_AUDIO_HUB 97
>> +#define CLK_USB_OHCI0 98
>> +#define CLK_USB_PHY0 99
>> +#define CLK_USB_OHCI1 100
>> +#define CLK_USB_PHY1 101
>> +#define CLK_USB_OHCI2 102
>> +#define CLK_USB_PHY2 103
>> +#define CLK_USB_OHCI3 104
>> +#define CLK_USB_PHY3 105
>> +#define CLK_BUS_OHCI0 106
>> +#define CLK_BUS_OHCI1 107
>> +#define CLK_BUS_OHCI2 108
>> +#define CLK_BUS_OHCI3 109
>> +#define CLK_BUS_EHCI0 110
>> +#define CLK_BUS_EHCI1 111
>> +#define CLK_BUS_EHCI2 112
>> +#define CLK_BUS_EHCI3 113
>> +#define CLK_BUS_OTG 114
>> +#define CLK_BUS_KEYADC 115
>> +#define CLK_HDMI 116
>> +#define CLK_HDMI_SLOW 117
>> +#define CLK_HDMI_CEC 118
>> +#define CLK_BUS_HDMI 119
>> +#define CLK_BUS_TCON_TOP 120
>> +#define CLK_TCON_TV0 121
>> +#define CLK_BUS_TCON_TV0 122
>> +#define CLK_HDCP 123
>> +#define CLK_BUS_HDCP 124
>> +
>> +#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..1c992cfbbbab
>> --- /dev/null
>> +++ b/include/dt-bindings/reset/sun50i-h616-ccu.h
>> @@ -0,0 +1,67 @@
>> +// SPDX-License-Identifier: (GPL-2.0+ or MIT)
>> +/*
>> + * Copyright (C) 2017 Icenowy Zheng <icenowy@aosc.io>
>> + */
>> +
>> +#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_HDCP 55
>> +#define RST_BUS_KEYADC 56
>> +
>> +#endif /* _DT_BINDINGS_RESET_SUN50I_H616_H_ */
>> --
>> 2.17.5
>>
^ permalink raw reply [flat|nested] 20+ messages in thread
end of thread, other threads:[~2020-12-10 14:35 UTC | newest]
Thread overview: 20+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
[not found] <20201202135409.13683-1-andre.przywara@arm.com>
2020-12-02 13:54 ` [PATCH 1/8] clk: sunxi-ng: h6: Fix clock divider range on some clocks Andre Przywara
2020-12-02 16:17 ` Jernej Škrabec
2020-12-02 13:54 ` [PATCH 4/8] clk: sunxi-ng: Add support for the Allwinner H616 R-CCU Andre Przywara
2020-12-02 14:31 ` Icenowy Zheng
2020-12-03 11:07 ` André Przywara
2020-12-03 14:02 ` [linux-sunxi] " Icenowy Zheng
2020-12-02 18:20 ` Jernej Škrabec
2020-12-03 2:44 ` Samuel Holland
2020-12-03 10:52 ` André Przywara
2020-12-02 13:54 ` [PATCH 5/8] clk: sunxi-ng: Add support for the Allwinner H616 CCU Andre Przywara
2020-12-02 15:56 ` Maxime Ripard
2020-12-02 21:03 ` Jernej Škrabec
2020-12-02 23:06 ` André Przywara
2020-12-05 16:36 ` [linux-sunxi] " Icenowy Zheng
2020-12-09 14:33 ` [linux-sunxi] " Clément Péron
2020-12-09 21:35 ` André Przywara
2020-12-09 22:20 ` Jernej Škrabec
2020-12-09 22:45 ` André Przywara
2020-12-10 13:31 ` Icenowy Zheng
2020-12-10 14:34 ` André Przywara
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).