2023-11-06 08:56:27

by Xianwei Zhao

[permalink] [raw]
Subject: [PATCH V6 0/4] Add C3 SoC PLLs and Peripheral clock

The patchset adds support for the peripheral and PLL clock controller
found on the Amlogic C3 SoC family, such as C302X or C308L.

Changes since V5 [3]:
- Fix some typo and modify formart for MARCO. Suggested by Jerome.
- Add pad clock for peripheral input clock in bindings.
- Add some description for explaining why ddr_dpll_pt_clk and cts_msr_clk are out of tree.
Changes since V4 [10]:
- Change some fw_name of clocks. Suggested by Jerome.
- Delete minItem of clocks.
- Add CLk_GET_RATE_NOCACHE flags for gp1_pll
- Fix some format. and fix width as 8 for mclk_pll_dco.
- exchange gate and divder for fclk_50m clock.
- add CLK_SET_RATE_PARENT for axi_a_divder & axi_b_divder.
- add CLK_IS_CRITICAL for axi_clk
- Optimized macro define for pwm clk.
- add cts_oscin_clk mux between 24M and 32k
- add some missing gate clock, such as ddr_pll.
Changes since V3 [7]:
- Modify Kconfig desc and PLL yaml clk desc.
- Fix some format.Suggested by Yixun and Jerome.
- Add flag CLK_GET_RATE_NOCACHE for sys_clk.
- Optimized macro define for pwm clk.
- Use flag CLK_IS_CRITICAL for axi_clk.
- Add some description for some clocks.
- Use FCLK_50M instead of FCLK_DIV40.
Changes since V2 [4]:
- Modify some format, include clk name & inline, and so on.
- Define marco for pwm clock.
- Add GP1_PLL clock.
- Modify yaml use raw instead of macro.
Changes since V1 [2]:
- Fix errors when check binding by using "make dt_binding_check".
- Delete macro definition.

Xianwei Zhao (4):
dt-bindings: clock: add Amlogic C3 PLL clock controller bindings
dt-bindings: clock: add Amlogic C3 peripherals clock controller
bindings
clk: meson: c3: add support for the C3 SoC PLL clock
clk: meson: c3: add c3 clock peripherals controller driver

.../clock/amlogic,c3-peripherals-clkc.yaml | 104 +
.../bindings/clock/amlogic,c3-pll-clkc.yaml | 59 +
drivers/clk/meson/Kconfig | 26 +
drivers/clk/meson/Makefile | 2 +
drivers/clk/meson/c3-peripherals.c | 2745 +++++++++++++++++
drivers/clk/meson/c3-pll.c | 895 ++++++
.../clock/amlogic,c3-peripherals-clkc.h | 237 ++
.../dt-bindings/clock/amlogic,c3-pll-clkc.h | 44 +
8 files changed, 4112 insertions(+)
create mode 100644 Documentation/devicetree/bindings/clock/amlogic,c3-peripherals-clkc.yaml
create mode 100644 Documentation/devicetree/bindings/clock/amlogic,c3-pll-clkc.yaml
create mode 100644 drivers/clk/meson/c3-peripherals.c
create mode 100644 drivers/clk/meson/c3-pll.c
create mode 100644 include/dt-bindings/clock/amlogic,c3-peripherals-clkc.h
create mode 100644 include/dt-bindings/clock/amlogic,c3-pll-clkc.h


base-commit: 57b55c76aaf1ba50ecc6dcee5cd6843dc4d85239
--
2.39.2


2023-11-06 08:57:12

by Xianwei Zhao

[permalink] [raw]
Subject: [PATCH V6 3/4] clk: meson: c3: add support for the C3 SoC PLL clock

Add the C3 PLL clock controller driver for the Amlogic C3 SoC family.

Co-developed-by: Chuan Liu <[email protected]>
Signed-off-by: Chuan Liu <[email protected]>
Signed-off-by: Xianwei Zhao <[email protected]>
---
drivers/clk/meson/Kconfig | 13 +
drivers/clk/meson/Makefile | 1 +
drivers/clk/meson/c3-pll.c | 895 +++++++++++++++++++++++++++++++++++++
3 files changed, 909 insertions(+)
create mode 100644 drivers/clk/meson/c3-pll.c

diff --git a/drivers/clk/meson/Kconfig b/drivers/clk/meson/Kconfig
index c5303e4c1604..eab796f3d25b 100644
--- a/drivers/clk/meson/Kconfig
+++ b/drivers/clk/meson/Kconfig
@@ -128,6 +128,19 @@ config COMMON_CLK_A1_PERIPHERALS
device, A1 SoC Family. Say Y if you want A1 Peripherals clock
controller to work.

+config COMMON_CLK_C3_PLL
+ tristate "Amlogic C3 PLL clock controller"
+ depends on ARM64
+ default y
+ select COMMON_CLK_MESON_REGMAP
+ select COMMON_CLK_MESON_PLL
+ select COMMON_CLK_MESON_CLKC_UTILS
+ help
+ Support for the PLL clock controller on Amlogic C302X and C308L devices,
+ AKA c3. Amlogic C302X and C308L devices include AW402 and the others.
+ Say Y if you want the board to work, because PLLs are the parent of most
+ peripherals.
+
config COMMON_CLK_G12A
tristate "G12 and SM1 SoC clock controllers support"
depends on ARM64
diff --git a/drivers/clk/meson/Makefile b/drivers/clk/meson/Makefile
index 9ee4b954c896..4420af628b31 100644
--- a/drivers/clk/meson/Makefile
+++ b/drivers/clk/meson/Makefile
@@ -19,6 +19,7 @@ obj-$(CONFIG_COMMON_CLK_AXG) += axg.o axg-aoclk.o
obj-$(CONFIG_COMMON_CLK_AXG_AUDIO) += axg-audio.o
obj-$(CONFIG_COMMON_CLK_A1_PLL) += a1-pll.o
obj-$(CONFIG_COMMON_CLK_A1_PERIPHERALS) += a1-peripherals.o
+obj-$(CONFIG_COMMON_CLK_C3_PLL) += c3-pll.o
obj-$(CONFIG_COMMON_CLK_GXBB) += gxbb.o gxbb-aoclk.o
obj-$(CONFIG_COMMON_CLK_G12A) += g12a.o g12a-aoclk.o
obj-$(CONFIG_COMMON_CLK_MESON8B) += meson8b.o meson8-ddr.o
diff --git a/drivers/clk/meson/c3-pll.c b/drivers/clk/meson/c3-pll.c
new file mode 100644
index 000000000000..b663666e3755
--- /dev/null
+++ b/drivers/clk/meson/c3-pll.c
@@ -0,0 +1,895 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Amlogic C3 PLL Controller Driver
+ *
+ * Copyright (c) 2023 Amlogic, inc.
+ * Author: Chuan Liu <[email protected]>
+ */
+
+#include <linux/clk-provider.h>
+#include <linux/of_device.h>
+#include <linux/platform_device.h>
+#include <linux/clk.h>
+#include "clk-regmap.h"
+#include "clk-pll.h"
+#include "meson-clkc-utils.h"
+#include <dt-bindings/clock/amlogic,c3-pll-clkc.h>
+
+#define ANACTRL_FIXPLL_CTRL0 0x40
+#define ANACTRL_FIXPLL_CTRL4 0x50
+#define ANACTRL_GP0PLL_CTRL0 0x80
+#define ANACTRL_GP0PLL_CTRL1 0x84
+#define ANACTRL_GP0PLL_CTRL2 0x88
+#define ANACTRL_GP0PLL_CTRL3 0x8c
+#define ANACTRL_GP0PLL_CTRL4 0x90
+#define ANACTRL_GP0PLL_CTRL5 0x94
+#define ANACTRL_GP0PLL_CTRL6 0x98
+#define ANACTRL_GP0PLL_STS 0x9c
+#define ANACTRL_GP1PLL_CTRL0 0xc0
+#define ANACTRL_GP1PLL_CTRL1 0xc4
+#define ANACTRL_GP1PLL_CTRL2 0xc8
+#define ANACTRL_GP1PLL_CTRL3 0xcc
+#define ANACTRL_GP1PLL_CTRL4 0xd0
+#define ANACTRL_GP1PLL_CTRL5 0xd4
+#define ANACTRL_GP1PLL_CTRL6 0xd8
+#define ANACTRL_GP1PLL_STS 0xdc
+#define ANACTRL_HIFIPLL_CTRL0 0x100
+#define ANACTRL_HIFIPLL_CTRL1 0x104
+#define ANACTRL_HIFIPLL_CTRL2 0x108
+#define ANACTRL_HIFIPLL_CTRL3 0x10c
+#define ANACTRL_HIFIPLL_CTRL4 0x110
+#define ANACTRL_HIFIPLL_CTRL5 0x114
+#define ANACTRL_HIFIPLL_CTRL6 0x118
+#define ANACTRL_HIFIPLL_STS 0x11c
+#define ANACTRL_MPLL_CTRL0 0x180
+#define ANACTRL_MPLL_CTRL1 0x184
+#define ANACTRL_MPLL_CTRL2 0x188
+#define ANACTRL_MPLL_CTRL3 0x18c
+#define ANACTRL_MPLL_CTRL4 0x190
+#define ANACTRL_MPLL_STS 0x1a4
+
+/*
+ * These clock are a fixed value (fixed_pll is 2GHz) that is initialized by ROMcode.
+ * The chip was changed fixed pll for security reasons. Fixed PLL registers are not writable
+ * in the kernel phase. Write of fixed PLL-related register will cause the system to crash.
+ * Meanwhile, these clock won't ever change at runtime.
+ * For the above reasons, we can only use ro_ops for fixed PLL related clocks.
+ */
+static struct clk_regmap fixed_pll_dco = {
+ .data = &(struct meson_clk_pll_data) {
+ .en = {
+ .reg_off = ANACTRL_FIXPLL_CTRL0,
+ .shift = 28,
+ .width = 1,
+ },
+ .m = {
+ .reg_off = ANACTRL_FIXPLL_CTRL0,
+ .shift = 0,
+ .width = 8,
+ },
+ .n = {
+ .reg_off = ANACTRL_FIXPLL_CTRL0,
+ .shift = 16,
+ .width = 5,
+ },
+ .l = {
+ .reg_off = ANACTRL_FIXPLL_CTRL0,
+ .shift = 31,
+ .width = 1,
+ },
+ .rst = {
+ .reg_off = ANACTRL_FIXPLL_CTRL0,
+ .shift = 29,
+ .width = 1,
+ },
+ },
+ .hw.init = &(struct clk_init_data) {
+ .name = "fixed_pll_dco",
+ .ops = &meson_clk_pll_ro_ops,
+ .parent_data = &(const struct clk_parent_data) {
+ .fw_name = "top",
+ },
+ .num_parents = 1,
+ },
+};
+
+static struct clk_regmap fixed_pll = {
+ .data = &(struct clk_regmap_div_data) {
+ .offset = ANACTRL_FIXPLL_CTRL0,
+ .shift = 12,
+ .width = 3,
+ .flags = CLK_DIVIDER_POWER_OF_TWO,
+ },
+ .hw.init = &(struct clk_init_data) {
+ .name = "fixed_pll",
+ .ops = &clk_regmap_divider_ro_ops,
+ .parent_hws = (const struct clk_hw *[]) {
+ &fixed_pll_dco.hw
+ },
+ .num_parents = 1,
+ },
+};
+
+static struct clk_regmap fclk_50m_en = {
+ .data = &(struct clk_regmap_gate_data) {
+ .offset = ANACTRL_FIXPLL_CTRL4,
+ .bit_idx = 0,
+ },
+ .hw.init = &(struct clk_init_data) {
+ .name = "fclk_50m_en",
+ .ops = &clk_regmap_gate_ro_ops,
+ .parent_hws = (const struct clk_hw *[]) {
+ &fixed_pll.hw
+ },
+ .num_parents = 1,
+ },
+};
+
+static struct clk_fixed_factor fclk_50m = {
+ .mult = 1,
+ .div = 40,
+ .hw.init = &(struct clk_init_data) {
+ .name = "fclk_50m",
+ .ops = &clk_fixed_factor_ops,
+ .parent_hws = (const struct clk_hw *[]) {
+ &fclk_50m_en.hw
+ },
+ .num_parents = 1,
+ },
+};
+
+static struct clk_fixed_factor fclk_div2_div = {
+ .mult = 1,
+ .div = 2,
+ .hw.init = &(struct clk_init_data) {
+ .name = "fclk_div2_div",
+ .ops = &clk_fixed_factor_ops,
+ .parent_hws = (const struct clk_hw *[]) {
+ &fixed_pll.hw
+ },
+ .num_parents = 1,
+ },
+};
+
+static struct clk_regmap fclk_div2 = {
+ .data = &(struct clk_regmap_gate_data) {
+ .offset = ANACTRL_FIXPLL_CTRL4,
+ .bit_idx = 24,
+ },
+ .hw.init = &(struct clk_init_data) {
+ .name = "fclk_div2",
+ .ops = &clk_regmap_gate_ro_ops,
+ .parent_hws = (const struct clk_hw *[]) {
+ &fclk_div2_div.hw
+ },
+ .num_parents = 1,
+ },
+};
+
+static struct clk_fixed_factor fclk_div2p5_div = {
+ .mult = 2,
+ .div = 5,
+ .hw.init = &(struct clk_init_data) {
+ .name = "fclk_div2p5_div",
+ .ops = &clk_fixed_factor_ops,
+ .parent_hws = (const struct clk_hw *[]) {
+ &fixed_pll.hw
+ },
+ .num_parents = 1,
+ },
+};
+
+static struct clk_regmap fclk_div2p5 = {
+ .data = &(struct clk_regmap_gate_data) {
+ .offset = ANACTRL_FIXPLL_CTRL4,
+ .bit_idx = 4,
+ },
+ .hw.init = &(struct clk_init_data) {
+ .name = "fclk_div2p5",
+ .ops = &clk_regmap_gate_ro_ops,
+ .parent_hws = (const struct clk_hw *[]) {
+ &fclk_div2p5_div.hw
+ },
+ .num_parents = 1,
+ },
+};
+
+static struct clk_fixed_factor fclk_div3_div = {
+ .mult = 1,
+ .div = 3,
+ .hw.init = &(struct clk_init_data) {
+ .name = "fclk_div3_div",
+ .ops = &clk_fixed_factor_ops,
+ .parent_hws = (const struct clk_hw *[]) {
+ &fixed_pll.hw
+ },
+ .num_parents = 1,
+ },
+};
+
+static struct clk_regmap fclk_div3 = {
+ .data = &(struct clk_regmap_gate_data) {
+ .offset = ANACTRL_FIXPLL_CTRL4,
+ .bit_idx = 20,
+ },
+ .hw.init = &(struct clk_init_data) {
+ .name = "fclk_div3",
+ .ops = &clk_regmap_gate_ro_ops,
+ .parent_hws = (const struct clk_hw *[]) {
+ &fclk_div3_div.hw
+ },
+ .num_parents = 1,
+ },
+};
+
+static struct clk_fixed_factor fclk_div4_div = {
+ .mult = 1,
+ .div = 4,
+ .hw.init = &(struct clk_init_data) {
+ .name = "fclk_div4_div",
+ .ops = &clk_fixed_factor_ops,
+ .parent_hws = (const struct clk_hw *[]) {
+ &fixed_pll.hw
+ },
+ .num_parents = 1,
+ },
+};
+
+static struct clk_regmap fclk_div4 = {
+ .data = &(struct clk_regmap_gate_data) {
+ .offset = ANACTRL_FIXPLL_CTRL4,
+ .bit_idx = 21,
+ },
+ .hw.init = &(struct clk_init_data) {
+ .name = "fclk_div4",
+ .ops = &clk_regmap_gate_ro_ops,
+ .parent_hws = (const struct clk_hw *[]) {
+ &fclk_div4_div.hw
+ },
+ .num_parents = 1,
+ },
+};
+
+static struct clk_fixed_factor fclk_div5_div = {
+ .mult = 1,
+ .div = 5,
+ .hw.init = &(struct clk_init_data) {
+ .name = "fclk_div5_div",
+ .ops = &clk_fixed_factor_ops,
+ .parent_hws = (const struct clk_hw *[]) {
+ &fixed_pll.hw
+ },
+ .num_parents = 1,
+ },
+};
+
+static struct clk_regmap fclk_div5 = {
+ .data = &(struct clk_regmap_gate_data) {
+ .offset = ANACTRL_FIXPLL_CTRL4,
+ .bit_idx = 22,
+ },
+ .hw.init = &(struct clk_init_data) {
+ .name = "fclk_div5",
+ .ops = &clk_regmap_gate_ro_ops,
+ .parent_hws = (const struct clk_hw *[]) {
+ &fclk_div5_div.hw
+ },
+ .num_parents = 1,
+ },
+};
+
+static struct clk_fixed_factor fclk_div7_div = {
+ .mult = 1,
+ .div = 7,
+ .hw.init = &(struct clk_init_data) {
+ .name = "fclk_div7_div",
+ .ops = &clk_fixed_factor_ops,
+ .parent_hws = (const struct clk_hw *[]) {
+ &fixed_pll.hw
+ },
+ .num_parents = 1,
+ },
+};
+
+static struct clk_regmap fclk_div7 = {
+ .data = &(struct clk_regmap_gate_data) {
+ .offset = ANACTRL_FIXPLL_CTRL4,
+ .bit_idx = 23,
+ },
+ .hw.init = &(struct clk_init_data) {
+ .name = "fclk_div7",
+ .ops = &clk_regmap_gate_ro_ops,
+ .parent_hws = (const struct clk_hw *[]) {
+ &fclk_div7_div.hw
+ },
+ .num_parents = 1,
+ },
+};
+
+static const struct reg_sequence c3_gp0_init_regs[] = {
+ { .reg = ANACTRL_GP0PLL_CTRL2, .def = 0x0 },
+ { .reg = ANACTRL_GP0PLL_CTRL3, .def = 0x48681c00 },
+ { .reg = ANACTRL_GP0PLL_CTRL4, .def = 0x88770290 },
+ { .reg = ANACTRL_GP0PLL_CTRL5, .def = 0x3927200a },
+ { .reg = ANACTRL_GP0PLL_CTRL6, .def = 0x56540000 },
+};
+
+static const struct pll_mult_range c3_gp0_pll_mult_range = {
+ .min = 125,
+ .max = 250,
+};
+
+static struct clk_regmap gp0_pll_dco = {
+ .data = &(struct meson_clk_pll_data) {
+ .en = {
+ .reg_off = ANACTRL_GP0PLL_CTRL0,
+ .shift = 28,
+ .width = 1,
+ },
+ .m = {
+ .reg_off = ANACTRL_GP0PLL_CTRL0,
+ .shift = 0,
+ .width = 9,
+ },
+ .frac = {
+ .reg_off = ANACTRL_GP0PLL_CTRL1,
+ .shift = 0,
+ .width = 19,
+ },
+ .n = {
+ .reg_off = ANACTRL_GP0PLL_CTRL0,
+ .shift = 10,
+ .width = 5,
+ },
+ .l = {
+ .reg_off = ANACTRL_GP0PLL_CTRL0,
+ .shift = 31,
+ .width = 1,
+ },
+ .rst = {
+ .reg_off = ANACTRL_GP0PLL_CTRL0,
+ .shift = 29,
+ .width = 1,
+ },
+ .range = &c3_gp0_pll_mult_range,
+ .init_regs = c3_gp0_init_regs,
+ .init_count = ARRAY_SIZE(c3_gp0_init_regs),
+ },
+ .hw.init = &(struct clk_init_data) {
+ .name = "gp0_pll_dco",
+ .ops = &meson_clk_pll_ops,
+ .parent_data = &(const struct clk_parent_data) {
+ .fw_name = "top",
+ },
+ .num_parents = 1,
+ },
+};
+
+/* The maximum frequency divider supports is 32, not 128(2^7) */
+static const struct clk_div_table c3_gp0_pll_od_table[] = {
+ { 0, 1 },
+ { 1, 2 },
+ { 2, 4 },
+ { 3, 8 },
+ { 4, 16 },
+ { 5, 32 },
+ { /* sentinel */ }
+};
+
+static struct clk_regmap gp0_pll = {
+ .data = &(struct clk_regmap_div_data) {
+ .offset = ANACTRL_GP0PLL_CTRL0,
+ .shift = 16,
+ .width = 3,
+ .table = c3_gp0_pll_od_table,
+ },
+ .hw.init = &(struct clk_init_data) {
+ .name = "gp0_pll",
+ .ops = &clk_regmap_divider_ops,
+ .parent_hws = (const struct clk_hw *[]) {
+ &gp0_pll_dco.hw
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ },
+};
+
+/*
+ * The register corresponding to gp1_pll has permission restrictions,
+ * The corresponding register is read-only in the kernel.
+ * For the above reasons, we can only use ro_ops for gp1_pll related clocks.
+ */
+static struct clk_regmap gp1_pll_dco = {
+ .data = &(struct meson_clk_pll_data) {
+ .en = {
+ .reg_off = ANACTRL_GP1PLL_CTRL0,
+ .shift = 28,
+ .width = 1,
+ },
+ .m = {
+ .reg_off = ANACTRL_GP1PLL_CTRL0,
+ .shift = 0,
+ .width = 9,
+ },
+ .frac = {
+ .reg_off = ANACTRL_GP1PLL_CTRL1,
+ .shift = 0,
+ .width = 19,
+ },
+ .n = {
+ .reg_off = ANACTRL_GP1PLL_CTRL0,
+ .shift = 10,
+ .width = 5,
+ },
+ .l = {
+ .reg_off = ANACTRL_GP1PLL_CTRL0,
+ .shift = 31,
+ .width = 1,
+ },
+ .rst = {
+ .reg_off = ANACTRL_GP1PLL_CTRL0,
+ .shift = 29,
+ .width = 1,
+ },
+ },
+ .hw.init = &(struct clk_init_data) {
+ .name = "gp1_pll_dco",
+ .ops = &meson_clk_pll_ro_ops,
+ .parent_data = &(const struct clk_parent_data) {
+ .fw_name = "top",
+ },
+ .num_parents = 1,
+ .flags = CLK_GET_RATE_NOCACHE,
+ },
+};
+
+static struct clk_regmap gp1_pll = {
+ .data = &(struct clk_regmap_div_data) {
+ .offset = ANACTRL_GP1PLL_CTRL0,
+ .shift = 16,
+ .width = 3,
+ },
+ .hw.init = &(struct clk_init_data) {
+ .name = "gp1_pll",
+ .ops = &clk_regmap_divider_ro_ops,
+ .parent_hws = (const struct clk_hw *[]) {
+ &gp1_pll_dco.hw
+ },
+ .num_parents = 1,
+ .flags = CLK_GET_RATE_NOCACHE,
+ },
+};
+
+static const struct reg_sequence c3_hifi_init_regs[] = {
+ { .reg = ANACTRL_HIFIPLL_CTRL2, .def = 0x0 },
+ { .reg = ANACTRL_HIFIPLL_CTRL3, .def = 0x6a285c00 },
+ { .reg = ANACTRL_HIFIPLL_CTRL4, .def = 0x65771290 },
+ { .reg = ANACTRL_HIFIPLL_CTRL5, .def = 0x3927200a },
+ { .reg = ANACTRL_HIFIPLL_CTRL6, .def = 0x56540000 },
+};
+
+static struct clk_regmap hifi_pll_dco = {
+ .data = &(struct meson_clk_pll_data) {
+ .en = {
+ .reg_off = ANACTRL_HIFIPLL_CTRL0,
+ .shift = 28,
+ .width = 1,
+ },
+ .m = {
+ .reg_off = ANACTRL_HIFIPLL_CTRL0,
+ .shift = 0,
+ .width = 8,
+ },
+ .frac = {
+ .reg_off = ANACTRL_HIFIPLL_CTRL1,
+ .shift = 0,
+ .width = 19,
+ },
+ .n = {
+ .reg_off = ANACTRL_HIFIPLL_CTRL0,
+ .shift = 10,
+ .width = 5,
+ },
+ .l = {
+ .reg_off = ANACTRL_HIFIPLL_CTRL0,
+ .shift = 31,
+ .width = 1,
+ },
+ .rst = {
+ .reg_off = ANACTRL_HIFIPLL_CTRL0,
+ .shift = 29,
+ .width = 1,
+ },
+ .range = &c3_gp0_pll_mult_range,
+ .init_regs = c3_hifi_init_regs,
+ .init_count = ARRAY_SIZE(c3_hifi_init_regs),
+ },
+ .hw.init = &(struct clk_init_data) {
+ .name = "hifi_pll_dco",
+ .ops = &meson_clk_pll_ops,
+ .parent_data = &(const struct clk_parent_data) {
+ .fw_name = "top",
+ },
+ .num_parents = 1,
+ },
+};
+
+static struct clk_regmap hifi_pll = {
+ .data = &(struct clk_regmap_div_data) {
+ .offset = ANACTRL_HIFIPLL_CTRL0,
+ .shift = 16,
+ .width = 2,
+ .flags = CLK_DIVIDER_POWER_OF_TWO,
+ },
+ .hw.init = &(struct clk_init_data) {
+ .name = "hifi_pll",
+ .ops = &clk_regmap_divider_ops,
+ .parent_hws = (const struct clk_hw *[]) {
+ &hifi_pll_dco.hw
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ },
+};
+
+static const struct reg_sequence c3_mclk_init_regs[] = {
+ { .reg = ANACTRL_MPLL_CTRL1, .def = 0x1420500f },
+ { .reg = ANACTRL_MPLL_CTRL2, .def = 0x00023041 },
+ { .reg = ANACTRL_MPLL_CTRL3, .def = 0x18180000 },
+ { .reg = ANACTRL_MPLL_CTRL2, .def = 0x00023001 }
+};
+
+static const struct pll_mult_range c3_mclk_pll_mult_range = {
+ .min = 67,
+ .max = 133,
+};
+
+static struct clk_regmap mclk_pll_dco = {
+ .data = &(struct meson_clk_pll_data) {
+ .en = {
+ .reg_off = ANACTRL_MPLL_CTRL0,
+ .shift = 28,
+ .width = 1,
+ },
+ .m = {
+ .reg_off = ANACTRL_MPLL_CTRL0,
+ .shift = 0,
+ .width = 8,
+ },
+ .n = {
+ .reg_off = ANACTRL_MPLL_CTRL0,
+ .shift = 10,
+ .width = 5,
+ },
+ .l = {
+ .reg_off = ANACTRL_MPLL_CTRL0,
+ .shift = 31,
+ .width = 1,
+ },
+ .rst = {
+ .reg_off = ANACTRL_MPLL_CTRL0,
+ .shift = 29,
+ .width = 1,
+ },
+ .range = &c3_mclk_pll_mult_range,
+ .init_regs = c3_mclk_init_regs,
+ .init_count = ARRAY_SIZE(c3_mclk_init_regs),
+ },
+ .hw.init = &(struct clk_init_data) {
+ .name = "mclk_pll_dco",
+ .ops = &meson_clk_pll_ops,
+ .parent_data = &(const struct clk_parent_data) {
+ .fw_name = "mpll",
+ },
+ .num_parents = 1,
+ },
+};
+
+static const struct clk_div_table c3_mpll_od_table[] = {
+ { 0, 1 },
+ { 1, 2 },
+ { 2, 4 },
+ { 3, 8 },
+ { 4, 16 },
+ { /* sentinel */ }
+};
+
+static struct clk_regmap mclk_pll_od = {
+ .data = &(struct clk_regmap_div_data) {
+ .offset = ANACTRL_MPLL_CTRL0,
+ .shift = 12,
+ .width = 3,
+ .table = c3_mpll_od_table,
+ },
+ .hw.init = &(struct clk_init_data) {
+ .name = "mclk_pll_od",
+ .ops = &clk_regmap_divider_ops,
+ .parent_hws = (const struct clk_hw *[]) {
+ &mclk_pll_dco.hw },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ },
+};
+
+/* both value 0 and 1 gives divide the input rate by one */
+static struct clk_regmap mclk_pll = {
+ .data = &(struct clk_regmap_div_data) {
+ .offset = ANACTRL_MPLL_CTRL4,
+ .shift = 16,
+ .width = 5,
+ .flags = CLK_DIVIDER_ONE_BASED | CLK_DIVIDER_ALLOW_ZERO,
+ },
+ .hw.init = &(struct clk_init_data) {
+ .name = "mclk_pll",
+ .ops = &clk_regmap_divider_ops,
+ .parent_hws = (const struct clk_hw *[]) {
+ &mclk_pll_od.hw
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ },
+};
+
+static const struct clk_parent_data mclk_parent[] = {
+ { .hw = &mclk_pll.hw },
+ { .fw_name = "mpll" },
+ { .hw = &fclk_50m.hw }
+};
+
+static struct clk_regmap mclk0_sel = {
+ .data = &(struct clk_regmap_mux_data) {
+ .offset = ANACTRL_MPLL_CTRL4,
+ .mask = 0x3,
+ .shift = 4,
+ },
+ .hw.init = &(struct clk_init_data) {
+ .name = "mclk0_sel",
+ .ops = &clk_regmap_mux_ops,
+ .parent_data = mclk_parent,
+ .num_parents = ARRAY_SIZE(mclk_parent),
+ },
+};
+
+static struct clk_regmap mclk0_div_en = {
+ .data = &(struct clk_regmap_gate_data) {
+ .offset = ANACTRL_MPLL_CTRL4,
+ .bit_idx = 1,
+ },
+ .hw.init = &(struct clk_init_data) {
+ .name = "mclk0_div_en",
+ .ops = &clk_regmap_gate_ops,
+ .parent_hws = (const struct clk_hw *[]) {
+ &mclk0_sel.hw
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ },
+};
+
+static struct clk_regmap mclk0_div = {
+ .data = &(struct clk_regmap_div_data) {
+ .offset = ANACTRL_MPLL_CTRL4,
+ .shift = 2,
+ .width = 1,
+ },
+ .hw.init = &(struct clk_init_data) {
+ .name = "mclk0_div",
+ .ops = &clk_regmap_divider_ops,
+ .parent_hws = (const struct clk_hw *[]) {
+ &mclk0_div_en.hw
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ },
+};
+
+static struct clk_regmap mclk0 = {
+ .data = &(struct clk_regmap_gate_data) {
+ .offset = ANACTRL_MPLL_CTRL4,
+ .bit_idx = 0,
+ },
+ .hw.init = &(struct clk_init_data) {
+ .name = "mclk0",
+ .ops = &clk_regmap_gate_ops,
+ .parent_hws = (const struct clk_hw *[]) {
+ &mclk0_div.hw
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ },
+};
+
+static struct clk_regmap mclk1_sel = {
+ .data = &(struct clk_regmap_mux_data) {
+ .offset = ANACTRL_MPLL_CTRL4,
+ .mask = 0x3,
+ .shift = 12,
+ },
+ .hw.init = &(struct clk_init_data) {
+ .name = "mclk1_sel",
+ .ops = &clk_regmap_mux_ops,
+ .parent_data = mclk_parent,
+ .num_parents = ARRAY_SIZE(mclk_parent),
+ },
+};
+
+static struct clk_regmap mclk1_div_en = {
+ .data = &(struct clk_regmap_gate_data) {
+ .offset = ANACTRL_MPLL_CTRL4,
+ .bit_idx = 9,
+ },
+ .hw.init = &(struct clk_init_data) {
+ .name = "mclk1_div_en",
+ .ops = &clk_regmap_gate_ops,
+ .parent_hws = (const struct clk_hw *[]) {
+ &mclk1_sel.hw
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ },
+};
+
+static struct clk_regmap mclk1_div = {
+ .data = &(struct clk_regmap_div_data) {
+ .offset = ANACTRL_MPLL_CTRL4,
+ .shift = 10,
+ .width = 1,
+ },
+ .hw.init = &(struct clk_init_data) {
+ .name = "mclk1_div",
+ .ops = &clk_regmap_divider_ops,
+ .parent_hws = (const struct clk_hw *[]) {
+ &mclk1_div_en.hw
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ },
+};
+
+static struct clk_regmap mclk1 = {
+ .data = &(struct clk_regmap_gate_data) {
+ .offset = ANACTRL_MPLL_CTRL4,
+ .bit_idx = 8,
+ },
+ .hw.init = &(struct clk_init_data) {
+ .name = "mclk1",
+ .ops = &clk_regmap_gate_ops,
+ .parent_hws = (const struct clk_hw *[]) {
+ &mclk1_div.hw
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ },
+};
+
+static struct clk_hw *c3_pll_hw_clks[] = {
+ [CLKID_FIXED_PLL_DCO] = &fixed_pll_dco.hw,
+ [CLKID_FIXED_PLL] = &fixed_pll.hw,
+ [CLKID_FCLK_50M_EN] = &fclk_50m_en.hw,
+ [CLKID_FCLK_50M] = &fclk_50m.hw,
+ [CLKID_FCLK_DIV2_DIV] = &fclk_div2_div.hw,
+ [CLKID_FCLK_DIV2] = &fclk_div2.hw,
+ [CLKID_FCLK_DIV2P5_DIV] = &fclk_div2p5_div.hw,
+ [CLKID_FCLK_DIV2P5] = &fclk_div2p5.hw,
+ [CLKID_FCLK_DIV3_DIV] = &fclk_div3_div.hw,
+ [CLKID_FCLK_DIV3] = &fclk_div3.hw,
+ [CLKID_FCLK_DIV4_DIV] = &fclk_div4_div.hw,
+ [CLKID_FCLK_DIV4] = &fclk_div4.hw,
+ [CLKID_FCLK_DIV5_DIV] = &fclk_div5_div.hw,
+ [CLKID_FCLK_DIV5] = &fclk_div5.hw,
+ [CLKID_FCLK_DIV7_DIV] = &fclk_div7_div.hw,
+ [CLKID_FCLK_DIV7] = &fclk_div7.hw,
+ [CLKID_GP0_PLL_DCO] = &gp0_pll_dco.hw,
+ [CLKID_GP0_PLL] = &gp0_pll.hw,
+ [CLKID_GP1_PLL_DCO] = &gp1_pll_dco.hw,
+ [CLKID_GP1_PLL] = &gp1_pll.hw,
+ [CLKID_HIFI_PLL_DCO] = &hifi_pll_dco.hw,
+ [CLKID_HIFI_PLL] = &hifi_pll.hw,
+ [CLKID_MCLK_PLL_DCO] = &mclk_pll_dco.hw,
+ [CLKID_MCLK_PLL_OD] = &mclk_pll_od.hw,
+ [CLKID_MCLK_PLL] = &mclk_pll.hw,
+ [CLKID_MCLK0_SEL] = &mclk0_sel.hw,
+ [CLKID_MCLK0_SEL_EN] = &mclk0_div_en.hw,
+ [CLKID_MCLK0_DIV] = &mclk0_div.hw,
+ [CLKID_MCLK0] = &mclk0.hw,
+ [CLKID_MCLK1_SEL] = &mclk1_sel.hw,
+ [CLKID_MCLK1_SEL_EN] = &mclk1_div_en.hw,
+ [CLKID_MCLK1_DIV] = &mclk1_div.hw,
+ [CLKID_MCLK1] = &mclk1.hw
+};
+
+/* Convenience table to populate regmap in .probe */
+static struct clk_regmap *const c3_pll_clk_regmaps[] = {
+ &fixed_pll_dco,
+ &fixed_pll,
+ &fclk_50m_en,
+ &fclk_div2,
+ &fclk_div2p5,
+ &fclk_div3,
+ &fclk_div4,
+ &fclk_div5,
+ &fclk_div7,
+ &gp0_pll_dco,
+ &gp0_pll,
+ &gp1_pll_dco,
+ &gp1_pll,
+ &hifi_pll_dco,
+ &hifi_pll,
+ &mclk_pll_dco,
+ &mclk_pll_od,
+ &mclk_pll,
+ &mclk0_sel,
+ &mclk0_div_en,
+ &mclk0_div,
+ &mclk0,
+ &mclk1_sel,
+ &mclk1_div_en,
+ &mclk1_div,
+ &mclk1,
+};
+
+static struct regmap_config clkc_regmap_config = {
+ .reg_bits = 32,
+ .val_bits = 32,
+ .reg_stride = 4,
+};
+
+static struct meson_clk_hw_data c3_pll_clks = {
+ .hws = c3_pll_hw_clks,
+ .num = ARRAY_SIZE(c3_pll_hw_clks),
+};
+
+static int aml_c3_pll_probe(struct platform_device *pdev)
+{
+ struct device *dev = &pdev->dev;
+ struct regmap *regmap;
+ void __iomem *base;
+ int clkid, ret, i;
+
+ base = devm_platform_ioremap_resource(pdev, 0);
+ if (IS_ERR(base))
+ return PTR_ERR(base);
+
+ regmap = devm_regmap_init_mmio(dev, base, &clkc_regmap_config);
+ if (IS_ERR(regmap))
+ return PTR_ERR(regmap);
+
+ /* Populate regmap for the regmap backed clocks */
+ for (i = 0; i < ARRAY_SIZE(c3_pll_clk_regmaps); i++)
+ c3_pll_clk_regmaps[i]->map = regmap;
+
+ for (clkid = 0; clkid < c3_pll_clks.num; clkid++) {
+ /* array might be sparse */
+ if (!c3_pll_clks.hws[clkid])
+ continue;
+
+ ret = devm_clk_hw_register(dev, c3_pll_clks.hws[clkid]);
+ if (ret) {
+ dev_err(dev, "Clock registration failed\n");
+ return ret;
+ }
+ }
+
+ return devm_of_clk_add_hw_provider(dev, meson_clk_hw_get,
+ &c3_pll_clks);
+}
+
+static const struct of_device_id c3_pll_clkc_match_table[] = {
+ {
+ .compatible = "amlogic,c3-pll-clkc",
+ },
+ {}
+};
+MODULE_DEVICE_TABLE(of, c3_pll_clkc_match_table);
+
+static struct platform_driver c3_pll_driver = {
+ .probe = aml_c3_pll_probe,
+ .driver = {
+ .name = "c3-pll-clkc",
+ .of_match_table = c3_pll_clkc_match_table,
+ },
+};
+
+module_platform_driver(c3_pll_driver);
+MODULE_AUTHOR("Chuan Liu <[email protected]>");
+MODULE_LICENSE("GPL");
--
2.39.2

2023-11-06 08:57:41

by Xianwei Zhao

[permalink] [raw]
Subject: [PATCH V6 1/4] dt-bindings: clock: add Amlogic C3 PLL clock controller bindings

Add the PLL clock controller dt-bindings for Amlogic C3 SoC family.

Co-developed-by: Chuan Liu <[email protected]>
Signed-off-by: Chuan Liu <[email protected]>
Signed-off-by: Xianwei Zhao <[email protected]>
---
.../bindings/clock/amlogic,c3-pll-clkc.yaml | 59 +++++++++++++++++++
.../dt-bindings/clock/amlogic,c3-pll-clkc.h | 44 ++++++++++++++
2 files changed, 103 insertions(+)
create mode 100644 Documentation/devicetree/bindings/clock/amlogic,c3-pll-clkc.yaml
create mode 100644 include/dt-bindings/clock/amlogic,c3-pll-clkc.h

diff --git a/Documentation/devicetree/bindings/clock/amlogic,c3-pll-clkc.yaml b/Documentation/devicetree/bindings/clock/amlogic,c3-pll-clkc.yaml
new file mode 100644
index 000000000000..9ca047698045
--- /dev/null
+++ b/Documentation/devicetree/bindings/clock/amlogic,c3-pll-clkc.yaml
@@ -0,0 +1,59 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+# Copyright (C) 2022-2023 Amlogic, Inc. All rights reserved
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/clock/amlogic,c3-pll-clkc.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Amlogic C3 Serials PLL Clock Controller
+
+maintainers:
+ - Neil Armstrong <[email protected]>
+ - Jerome Brunet <[email protected]>
+ - Chuan Liu <[email protected]>
+ - Xianwei Zhao <[email protected]>
+
+properties:
+ compatible:
+ const: amlogic,c3-pll-clkc
+
+ reg:
+ maxItems: 1
+
+ clocks:
+ items:
+ - description: input Top pll
+ - description: input MCLK pll
+
+ clock-names:
+ items:
+ - const: top
+ - const: mpll
+
+ "#clock-cells":
+ const: 1
+
+required:
+ - compatible
+ - reg
+ - clocks
+ - clock-names
+ - "#clock-cells"
+
+additionalProperties: false
+
+examples:
+ - |
+ apb {
+ #address-cells = <2>;
+ #size-cells = <2>;
+
+ clock-controller@8000 {
+ compatible = "amlogic,c3-pll-clkc";
+ reg = <0x0 0x8000 0x0 0x1a4>;
+ clocks = <&clkc_periphs 0>,
+ <&clkc_periphs 1>;
+ clock-names = "top", "mpll";
+ #clock-cells = <1>;
+ };
+ };
diff --git a/include/dt-bindings/clock/amlogic,c3-pll-clkc.h b/include/dt-bindings/clock/amlogic,c3-pll-clkc.h
new file mode 100644
index 000000000000..60df483629ed
--- /dev/null
+++ b/include/dt-bindings/clock/amlogic,c3-pll-clkc.h
@@ -0,0 +1,44 @@
+/* SPDX-License-Identifier: (GPL-2.0-only OR MIT) */
+/*
+ * Copyright (c) 2023 Amlogic, Inc. All rights reserved.
+ * Author: Chuan Liu <[email protected]>
+ */
+
+#ifndef _DT_BINDINGS_CLOCK_AMLOGIC_C3_PLL_CLKC_H
+#define _DT_BINDINGS_CLOCK_AMLOGIC_C3_PLL_CLKC_H
+
+#define CLKID_FIXED_PLL_DCO 0
+#define CLKID_FIXED_PLL 1
+#define CLKID_FCLK_50M_EN 2
+#define CLKID_FCLK_50M 3
+#define CLKID_FCLK_DIV2_DIV 4
+#define CLKID_FCLK_DIV2 5
+#define CLKID_FCLK_DIV2P5_DIV 6
+#define CLKID_FCLK_DIV2P5 7
+#define CLKID_FCLK_DIV3_DIV 8
+#define CLKID_FCLK_DIV3 9
+#define CLKID_FCLK_DIV4_DIV 10
+#define CLKID_FCLK_DIV4 11
+#define CLKID_FCLK_DIV5_DIV 12
+#define CLKID_FCLK_DIV5 13
+#define CLKID_FCLK_DIV7_DIV 14
+#define CLKID_FCLK_DIV7 15
+#define CLKID_GP0_PLL_DCO 16
+#define CLKID_GP0_PLL 17
+#define CLKID_GP1_PLL_DCO 18
+#define CLKID_GP1_PLL 19
+#define CLKID_HIFI_PLL_DCO 20
+#define CLKID_HIFI_PLL 21
+#define CLKID_MCLK_PLL_DCO 22
+#define CLKID_MCLK_PLL_OD 23
+#define CLKID_MCLK_PLL 24
+#define CLKID_MCLK0_SEL 25
+#define CLKID_MCLK0_SEL_EN 26
+#define CLKID_MCLK0_DIV 27
+#define CLKID_MCLK0 28
+#define CLKID_MCLK1_SEL 29
+#define CLKID_MCLK1_SEL_EN 30
+#define CLKID_MCLK1_DIV 31
+#define CLKID_MCLK1 32
+
+#endif /* _DT_BINDINGS_CLOCK_AMLOGIC_C3_PLL_CLKC_H */
--
2.39.2

2023-11-06 08:58:24

by Xianwei Zhao

[permalink] [raw]
Subject: [PATCH V6 4/4] clk: meson: c3: add c3 clock peripherals controller driver

Add the C3 peripherals clock controller driver in the C3 SoC family.

Co-developed-by: Chuan Liu <[email protected]>
Signed-off-by: Chuan Liu <[email protected]>
Signed-off-by: Xianwei Zhao <[email protected]>
---
drivers/clk/meson/Kconfig | 13 +
drivers/clk/meson/Makefile | 1 +
drivers/clk/meson/c3-peripherals.c | 2745 ++++++++++++++++++++++++++++
3 files changed, 2759 insertions(+)
create mode 100644 drivers/clk/meson/c3-peripherals.c

diff --git a/drivers/clk/meson/Kconfig b/drivers/clk/meson/Kconfig
index eab796f3d25b..f3ad3030a6b9 100644
--- a/drivers/clk/meson/Kconfig
+++ b/drivers/clk/meson/Kconfig
@@ -141,6 +141,19 @@ config COMMON_CLK_C3_PLL
Say Y if you want the board to work, because PLLs are the parent of most
peripherals.

+config COMMON_CLK_C3_PERIPHERALS
+ tristate "Amlogic C3 peripherals clock controller"
+ depends on ARM64
+ default y
+ select COMMON_CLK_MESON_REGMAP
+ select COMMON_CLK_MESON_DUALDIV
+ select COMMON_CLK_MESON_CLKC_UTILS
+ help
+ Support for the Peripherals clock controller on Amlogic C302X and
+ C308L devices, AKA c3. Amlogic C302X and C308L devices include
+ AW402 and others. Say Y if you want the peripherals clock to
+ work.
+
config COMMON_CLK_G12A
tristate "G12 and SM1 SoC clock controllers support"
depends on ARM64
diff --git a/drivers/clk/meson/Makefile b/drivers/clk/meson/Makefile
index 4420af628b31..20ad9482c892 100644
--- a/drivers/clk/meson/Makefile
+++ b/drivers/clk/meson/Makefile
@@ -20,6 +20,7 @@ obj-$(CONFIG_COMMON_CLK_AXG_AUDIO) += axg-audio.o
obj-$(CONFIG_COMMON_CLK_A1_PLL) += a1-pll.o
obj-$(CONFIG_COMMON_CLK_A1_PERIPHERALS) += a1-peripherals.o
obj-$(CONFIG_COMMON_CLK_C3_PLL) += c3-pll.o
+obj-$(CONFIG_COMMON_CLK_C3_PERIPHERALS) += c3-peripherals.o
obj-$(CONFIG_COMMON_CLK_GXBB) += gxbb.o gxbb-aoclk.o
obj-$(CONFIG_COMMON_CLK_G12A) += g12a.o g12a-aoclk.o
obj-$(CONFIG_COMMON_CLK_MESON8B) += meson8b.o meson8-ddr.o
diff --git a/drivers/clk/meson/c3-peripherals.c b/drivers/clk/meson/c3-peripherals.c
new file mode 100644
index 000000000000..ea0f71d4deb0
--- /dev/null
+++ b/drivers/clk/meson/c3-peripherals.c
@@ -0,0 +1,2745 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Amlogic C3 Peripherals Clock Controller Driver
+ *
+ * Copyright (c) 2023 Amlogic, inc.
+ * Author: Chuan Liu <[email protected]>
+ */
+
+#include <linux/clk-provider.h>
+#include <linux/of_device.h>
+#include <linux/platform_device.h>
+#include <linux/clk.h>
+#include "clk-regmap.h"
+#include "clk-dualdiv.h"
+#include "meson-clkc-utils.h"
+#include <dt-bindings/clock/amlogic,c3-peripherals-clkc.h>
+
+#define OSCIN_CTRL 0x4
+#define RTC_BY_OSCIN_CTRL0 0x8
+#define RTC_BY_OSCIN_CTRL1 0xc
+#define RTC_CTRL 0x10
+#define SYS_CLK_CTRL0 0x40
+#define SYS_CLK_EN0_REG0 0x44
+#define SYS_CLK_EN0_REG1 0x48
+#define SYS_CLK_EN0_REG2 0x4c
+#define AXI_CLK_CTRL0 0x6c
+#define CLK12_24_CTRL 0xa8
+#define AXI_CLK_EN0 0xac
+#define VDIN_MEAS_CLK_CTRL 0xf8
+#define VAPB_CLK_CTRL 0xfc
+#define MIPIDSI_PHY_CLK_CTRL 0x104
+#define GE2D_CLK_CTRL 0x10c
+#define ISP0_CLK_CTRL 0x110
+#define DEWARPA_CLK_CTRL 0x114
+#define VOUTENC_CLK_CTRL 0x118
+#define VDEC_CLK_CTRL 0x140
+#define VDEC3_CLK_CTRL 0x148
+#define TS_CLK_CTRL 0x158
+#define ETH_CLK_CTRL 0x164
+#define NAND_CLK_CTRL 0x168
+#define SD_EMMC_CLK_CTRL 0x16c
+#define SPICC_CLK_CTRL 0x174
+#define GEN_CLK_CTRL 0x178
+#define SAR_CLK_CTRL0 0x17c
+#define PWM_CLK_AB_CTRL 0x180
+#define PWM_CLK_CD_CTRL 0x184
+#define PWM_CLK_EF_CTRL 0x188
+#define PWM_CLK_GH_CTRL 0x18c
+#define PWM_CLK_IJ_CTRL 0x190
+#define PWM_CLK_KL_CTRL 0x194
+#define PWM_CLK_MN_CTRL 0x198
+#define VC9000E_CLK_CTRL 0x19c
+#define SPIFC_CLK_CTRL 0x1a0
+#define NNA_CLK_CTRL 0x220
+
+static struct clk_regmap pll_src = {
+ .data = &(struct clk_regmap_gate_data) {
+ .offset = OSCIN_CTRL,
+ .bit_idx = 4,
+ },
+ .hw.init = &(struct clk_init_data) {
+ .name = "pll_src",
+ .ops = &clk_regmap_gate_ro_ops,
+ .parent_data = &(const struct clk_parent_data) {
+ .fw_name = "xtal_24m",
+ },
+ .num_parents = 1,
+ },
+};
+
+static struct clk_regmap mclk_pll_src = {
+ .data = &(struct clk_regmap_gate_data) {
+ .offset = OSCIN_CTRL,
+ .bit_idx = 8,
+ },
+ .hw.init = &(struct clk_init_data) {
+ .name = "mclk_pll_in",
+ .ops = &clk_regmap_gate_ro_ops,
+ .parent_data = &(const struct clk_parent_data) {
+ .fw_name = "xtal_24m",
+ },
+ .num_parents = 1,
+ },
+};
+
+/*
+ * These clocks can't be closed, the system will crash or
+ * not work good for some peripherals if close,
+ * so use read-only ops.
+ */
+static struct clk_regmap ddr_pll_src = {
+ .data = &(struct clk_regmap_gate_data) {
+ .offset = OSCIN_CTRL,
+ .bit_idx = 1,
+ },
+ .hw.init = &(struct clk_init_data) {
+ .name = "ddr_pll_src",
+ .ops = &clk_regmap_gate_ro_ops,
+ .parent_data = &(const struct clk_parent_data) {
+ .fw_name = "xtal_24m",
+ },
+ .num_parents = 1,
+ },
+};
+
+static struct clk_regmap ddr_phy_src = {
+ .data = &(struct clk_regmap_gate_data) {
+ .offset = OSCIN_CTRL,
+ .bit_idx = 2,
+ },
+ .hw.init = &(struct clk_init_data) {
+ .name = "ddr_phy_src",
+ .ops = &clk_regmap_gate_ro_ops,
+ .parent_data = &(const struct clk_parent_data) {
+ .fw_name = "xtal_24m",
+ },
+ .num_parents = 1,
+ },
+};
+
+static struct clk_regmap usb_pll_src = {
+ .data = &(struct clk_regmap_gate_data) {
+ .offset = OSCIN_CTRL,
+ .bit_idx = 6,
+ },
+ .hw.init = &(struct clk_init_data) {
+ .name = "usb_pll_src",
+ .ops = &clk_regmap_gate_ro_ops,
+ .parent_data = &(const struct clk_parent_data) {
+ .fw_name = "xtal_24m",
+ },
+ .num_parents = 1,
+ },
+};
+
+static struct clk_regmap mipi_isp_vout_src = {
+ .data = &(struct clk_regmap_gate_data) {
+ .offset = OSCIN_CTRL,
+ .bit_idx = 7,
+ },
+ .hw.init = &(struct clk_init_data) {
+ .name = "mipi_isp_vout_src",
+ .ops = &clk_regmap_gate_ro_ops,
+ .parent_data = &(const struct clk_parent_data) {
+ .fw_name = "xtal_24m",
+ },
+ .num_parents = 1,
+ },
+};
+
+static struct clk_regmap usb_ctrl_src = {
+ .data = &(struct clk_regmap_gate_data) {
+ .offset = OSCIN_CTRL,
+ .bit_idx = 9,
+ },
+ .hw.init = &(struct clk_init_data) {
+ .name = "usb_ctrl_src",
+ .ops = &clk_regmap_gate_ro_ops,
+ .parent_data = &(const struct clk_parent_data) {
+ .fw_name = "xtal_24m",
+ },
+ .num_parents = 1,
+ },
+};
+
+static struct clk_regmap eth_pll_src = {
+ .data = &(struct clk_regmap_gate_data) {
+ .offset = OSCIN_CTRL,
+ .bit_idx = 10,
+ },
+ .hw.init = &(struct clk_init_data) {
+ .name = "eth_pll_src",
+ .ops = &clk_regmap_gate_ro_ops,
+ .parent_data = &(const struct clk_parent_data) {
+ .fw_name = "xtal_24m",
+ },
+ .num_parents = 1,
+ },
+};
+
+static const struct clk_parent_data cts_osc_src_parent_data[] = {
+ { .fw_name = "xtal_32k" },
+ { .fw_name = "xtal_24m" }
+};
+
+static struct clk_regmap cts_osc_src = {
+ .data = &(struct clk_regmap_mux_data) {
+ .offset = OSCIN_CTRL,
+ .mask = 0x1,
+ .shift = 31,
+ },
+ .hw.init = &(struct clk_init_data) {
+ .name = "cts_osc_src",
+ .ops = &clk_regmap_mux_ops,
+ .parent_data = cts_osc_src_parent_data,
+ .num_parents = ARRAY_SIZE(cts_osc_src_parent_data),
+ },
+};
+
+static struct clk_regmap rtc_xtal_clkin = {
+ .data = &(struct clk_regmap_gate_data) {
+ .offset = RTC_BY_OSCIN_CTRL0,
+ .bit_idx = 31,
+ },
+ .hw.init = &(struct clk_init_data) {
+ .name = "rtc_xtal_clkin",
+ .ops = &clk_regmap_gate_ops,
+ .parent_data = &(const struct clk_parent_data) {
+ .hw = &cts_osc_src.hw,
+ },
+ .num_parents = 1,
+ },
+};
+
+static const struct meson_clk_dualdiv_param rtc_32k_div_table[] = {
+ { 733, 732, 8, 11, 1 },
+ { /* sentinel */ }
+};
+
+static struct clk_regmap rtc_32k_div = {
+ .data = &(struct meson_clk_dualdiv_data) {
+ .n1 = {
+ .reg_off = RTC_BY_OSCIN_CTRL0,
+ .shift = 0,
+ .width = 12,
+ },
+ .n2 = {
+ .reg_off = RTC_BY_OSCIN_CTRL0,
+ .shift = 12,
+ .width = 12,
+ },
+ .m1 = {
+ .reg_off = RTC_BY_OSCIN_CTRL1,
+ .shift = 0,
+ .width = 12,
+ },
+ .m2 = {
+ .reg_off = RTC_BY_OSCIN_CTRL1,
+ .shift = 12,
+ .width = 12,
+ },
+ .dual = {
+ .reg_off = RTC_BY_OSCIN_CTRL0,
+ .shift = 28,
+ .width = 1,
+ },
+ .table = rtc_32k_div_table,
+ },
+ .hw.init = &(struct clk_init_data) {
+ .name = "rtc_32k_div",
+ .ops = &meson_clk_dualdiv_ops,
+ .parent_hws = (const struct clk_hw *[]) {
+ &rtc_xtal_clkin.hw
+ },
+ .num_parents = 1,
+ },
+};
+
+static const struct clk_parent_data rtc_32k_mux_parent_data[] = {
+ { .hw = &rtc_32k_div.hw },
+ { .hw = &rtc_xtal_clkin.hw }
+};
+
+static struct clk_regmap rtc_32k_mux = {
+ .data = &(struct clk_regmap_mux_data) {
+ .offset = RTC_BY_OSCIN_CTRL1,
+ .mask = 0x1,
+ .shift = 24,
+ },
+ .hw.init = &(struct clk_init_data) {
+ .name = "rtc_32k_mux",
+ .ops = &clk_regmap_mux_ops,
+ .parent_data = rtc_32k_mux_parent_data,
+ .num_parents = ARRAY_SIZE(rtc_32k_mux_parent_data),
+ .flags = CLK_SET_RATE_PARENT,
+ },
+};
+
+static struct clk_regmap rtc_32k = {
+ .data = &(struct clk_regmap_gate_data) {
+ .offset = RTC_BY_OSCIN_CTRL0,
+ .bit_idx = 30,
+ },
+ .hw.init = &(struct clk_init_data) {
+ .name = "rtc_32k",
+ .ops = &clk_regmap_gate_ops,
+ .parent_hws = (const struct clk_hw *[]) {
+ &rtc_32k_mux.hw
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ },
+};
+
+/*
+ * Index 2 clock is pad input clock, here we had not used.
+ * Index 3 is grounded.
+ */
+static const struct clk_parent_data rtc_clk_mux_parent_data[] = {
+ { .hw = &cts_osc_src.hw },
+ { .hw = &rtc_32k.hw }
+};
+
+static struct clk_regmap rtc_clk = {
+ .data = &(struct clk_regmap_mux_data) {
+ .offset = RTC_CTRL,
+ .mask = 0x3,
+ .shift = 0,
+ },
+ .hw.init = &(struct clk_init_data) {
+ .name = "rtc_clk",
+ .ops = &clk_regmap_mux_ops,
+ .parent_data = rtc_clk_mux_parent_data,
+ .num_parents = ARRAY_SIZE(rtc_clk_mux_parent_data),
+ .flags = CLK_SET_RATE_PARENT,
+ },
+};
+
+/*
+ * Channel 5(axi_clk_frcpu) is an external axi_cpu clock that is not handled
+ * right now. The corresponding registers are not placed in PLL or peripherals
+ * and are not readable or writable by the kernel, only accessed through
+ * SMC to SCP.
+ * Channel 6 is not connected.
+ */
+static u32 sys_axi_parent_table[] = { 0, 1, 2, 3, 4, 7 };
+
+static const struct clk_parent_data sys_axi_parent_data[] = {
+ { .hw = &cts_osc_src.hw },
+ { .fw_name = "gp1" },
+ { .fw_name = "fdiv3" },
+ { .fw_name = "fdiv4" },
+ { .fw_name = "fdiv5" },
+ { .hw = &rtc_clk.hw }
+};
+
+/*
+ * These clocks are initialized by ROM code.
+ * The chip was changed SYS_CLK for security reason. SYS_CLK registers are
+ * not writable in the kernel phase. Writing of SYS related register will cause
+ * the system to crash. Meanwhile, these clocks won't be changed at runtime.
+ * For the above reasons, we can only use ro_ops for SYS related clocks.
+ */
+static struct clk_regmap sys_a_sel = {
+ .data = &(struct clk_regmap_mux_data) {
+ .offset = SYS_CLK_CTRL0,
+ .mask = 0x7,
+ .shift = 10,
+ .table = sys_axi_parent_table,
+ },
+ .hw.init = &(struct clk_init_data) {
+ .name = "sys_a_sel",
+ .ops = &clk_regmap_mux_ro_ops,
+ .parent_data = sys_axi_parent_data,
+ .num_parents = ARRAY_SIZE(sys_axi_parent_data),
+ .flags = CLK_GET_RATE_NOCACHE,
+ },
+};
+
+static struct clk_regmap sys_a_div = {
+ .data = &(struct clk_regmap_div_data) {
+ .offset = SYS_CLK_CTRL0,
+ .shift = 0,
+ .width = 10,
+ },
+ .hw.init = &(struct clk_init_data) {
+ .name = "sys_a_div",
+ .ops = &clk_regmap_divider_ro_ops,
+ .parent_hws = (const struct clk_hw *[]) {
+ &sys_a_sel.hw
+ },
+ .num_parents = 1,
+ .flags = CLK_GET_RATE_NOCACHE,
+ },
+};
+
+static struct clk_regmap sys_a = {
+ .data = &(struct clk_regmap_gate_data) {
+ .offset = SYS_CLK_CTRL0,
+ .bit_idx = 13,
+ },
+ .hw.init = &(struct clk_init_data) {
+ .name = "sys_a",
+ .ops = &clk_regmap_gate_ro_ops,
+ .parent_hws = (const struct clk_hw *[]) {
+ &sys_a_div.hw
+ },
+ .num_parents = 1,
+ .flags = CLK_GET_RATE_NOCACHE,
+ },
+};
+
+static struct clk_regmap sys_b_sel = {
+ .data = &(struct clk_regmap_mux_data) {
+ .offset = SYS_CLK_CTRL0,
+ .mask = 0x7,
+ .shift = 26,
+ .table = sys_axi_parent_table,
+ },
+ .hw.init = &(struct clk_init_data) {
+ .name = "sys_b_sel",
+ .ops = &clk_regmap_mux_ro_ops,
+ .parent_data = sys_axi_parent_data,
+ .num_parents = ARRAY_SIZE(sys_axi_parent_data),
+ .flags = CLK_GET_RATE_NOCACHE,
+ },
+};
+
+static struct clk_regmap sys_b_div = {
+ .data = &(struct clk_regmap_div_data) {
+ .offset = SYS_CLK_CTRL0,
+ .shift = 16,
+ .width = 10,
+ },
+ .hw.init = &(struct clk_init_data) {
+ .name = "sys_b_div",
+ .ops = &clk_regmap_divider_ro_ops,
+ .parent_hws = (const struct clk_hw *[]) {
+ &sys_b_sel.hw
+ },
+ .num_parents = 1,
+ .flags = CLK_GET_RATE_NOCACHE,
+ },
+};
+
+static struct clk_regmap sys_b = {
+ .data = &(struct clk_regmap_gate_data) {
+ .offset = SYS_CLK_CTRL0,
+ .bit_idx = 29,
+ },
+ .hw.init = &(struct clk_init_data) {
+ .name = "sys_b",
+ .ops = &clk_regmap_gate_ro_ops,
+ .parent_hws = (const struct clk_hw *[]) {
+ &sys_b_div.hw
+ },
+ .num_parents = 1,
+ .flags = CLK_GET_RATE_NOCACHE,
+ },
+};
+
+static const struct clk_parent_data sys_clk_parent_data[] = {
+ { .hw = &sys_a.hw },
+ { .hw = &sys_b.hw }
+};
+
+static struct clk_regmap sys_clk = {
+ .data = &(struct clk_regmap_mux_data) {
+ .offset = SYS_CLK_CTRL0,
+ .mask = 0x1,
+ .shift = 15,
+ },
+ .hw.init = &(struct clk_init_data) {
+ .name = "sys_clk",
+ .ops = &clk_regmap_mux_ro_ops,
+ .parent_data = sys_clk_parent_data,
+ .num_parents = ARRAY_SIZE(sys_clk_parent_data),
+ .flags = CLK_GET_RATE_NOCACHE,
+ },
+};
+
+/*
+ * In the system, high-speed modules such as DDR, SRAM, ROM, CAPU and
+ * other key modules communicate through AXI_BUS and the clock is
+ * provided by the axi_clk. While the axi_clock is source of several
+ * peripheral gates, and that all should in theory be described and
+ * properly handled, it is not the case at the moment.
+ * The system will crash if the axi_clock is turned off, so the
+ * clock is critical, at least for now.
+ */
+static struct clk_regmap axi_a_sel = {
+ .data = &(struct clk_regmap_mux_data) {
+ .offset = AXI_CLK_CTRL0,
+ .mask = 0x7,
+ .shift = 10,
+ .table = sys_axi_parent_table,
+ },
+ .hw.init = &(struct clk_init_data) {
+ .name = "axi_a_sel",
+ .ops = &clk_regmap_mux_ops,
+ .parent_data = sys_axi_parent_data,
+ .num_parents = ARRAY_SIZE(sys_axi_parent_data),
+ },
+};
+
+static struct clk_regmap axi_a_div = {
+ .data = &(struct clk_regmap_div_data) {
+ .offset = AXI_CLK_CTRL0,
+ .shift = 0,
+ .width = 10,
+ },
+ .hw.init = &(struct clk_init_data) {
+ .name = "axi_a_div",
+ .ops = &clk_regmap_divider_ops,
+ .parent_hws = (const struct clk_hw *[]) {
+ &axi_a_sel.hw
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ },
+};
+
+static struct clk_regmap axi_a = {
+ .data = &(struct clk_regmap_gate_data) {
+ .offset = AXI_CLK_CTRL0,
+ .bit_idx = 13,
+ },
+ .hw.init = &(struct clk_init_data) {
+ .name = "axi_a",
+ .ops = &clk_regmap_gate_ops,
+ .parent_hws = (const struct clk_hw *[]) {
+ &axi_a_div.hw
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ },
+};
+
+static struct clk_regmap axi_b_sel = {
+ .data = &(struct clk_regmap_mux_data) {
+ .offset = AXI_CLK_CTRL0,
+ .mask = 0x7,
+ .shift = 26,
+ .table = sys_axi_parent_table,
+ },
+ .hw.init = &(struct clk_init_data) {
+ .name = "axi_b_sel",
+ .ops = &clk_regmap_mux_ops,
+ .parent_data = sys_axi_parent_data,
+ .num_parents = ARRAY_SIZE(sys_axi_parent_data),
+ },
+};
+
+static struct clk_regmap axi_b_div = {
+ .data = &(struct clk_regmap_div_data) {
+ .offset = AXI_CLK_CTRL0,
+ .shift = 16,
+ .width = 10,
+ },
+ .hw.init = &(struct clk_init_data) {
+ .name = "axi_b_div",
+ .ops = &clk_regmap_divider_ops,
+ .parent_hws = (const struct clk_hw *[]) {
+ &axi_b_sel.hw
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ },
+};
+
+static struct clk_regmap axi_b = {
+ .data = &(struct clk_regmap_gate_data) {
+ .offset = AXI_CLK_CTRL0,
+ .bit_idx = 29,
+ },
+ .hw.init = &(struct clk_init_data) {
+ .name = "axi_b",
+ .ops = &clk_regmap_gate_ops,
+ .parent_hws = (const struct clk_hw *[]) {
+ &axi_b_div.hw
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ },
+};
+
+static const struct clk_parent_data axi_clk_parent_data[] = {
+ { .hw = &axi_a.hw },
+ { .hw = &axi_b.hw }
+};
+
+static struct clk_regmap axi_clk = {
+ .data = &(struct clk_regmap_mux_data) {
+ .offset = AXI_CLK_CTRL0,
+ .mask = 0x1,
+ .shift = 15,
+ },
+ .hw.init = &(struct clk_init_data) {
+ .name = "axi_clk",
+ .ops = &clk_regmap_mux_ops,
+ .parent_data = axi_clk_parent_data,
+ .num_parents = ARRAY_SIZE(axi_clk_parent_data),
+ .flags = CLK_IS_CRITICAL,
+ },
+};
+
+#define AML_CLK_GATE_SYS_CLK(_name, _reg, _bit)\
+ MESON_PCLK(_name, _reg, _bit, &sys_clk.hw)
+#define AML_CLK_GATE_AXI_CLK(_name, _reg, _bit)\
+ MESON_PCLK(_name, _reg, _bit, &axi_clk.hw)
+
+static AML_CLK_GATE_SYS_CLK(sys_reset_ctrl, SYS_CLK_EN0_REG0, 1);
+static AML_CLK_GATE_SYS_CLK(sys_pwr_ctrl, SYS_CLK_EN0_REG0, 3);
+static AML_CLK_GATE_SYS_CLK(sys_pad_ctrl, SYS_CLK_EN0_REG0, 4);
+static AML_CLK_GATE_SYS_CLK(sys_ctrl, SYS_CLK_EN0_REG0, 5);
+static AML_CLK_GATE_SYS_CLK(sys_ts_pll, SYS_CLK_EN0_REG0, 6);
+static AML_CLK_GATE_SYS_CLK(sys_dev_arb, SYS_CLK_EN0_REG0, 7);
+static AML_CLK_GATE_SYS_CLK(sys_mmc_pclk, SYS_CLK_EN0_REG0, 8);
+static AML_CLK_GATE_SYS_CLK(sys_capu, SYS_CLK_EN0_REG0, 9);
+static AML_CLK_GATE_SYS_CLK(sys_cpu_ctrl, SYS_CLK_EN0_REG0, 11);
+static AML_CLK_GATE_SYS_CLK(sys_jtag_ctrl, SYS_CLK_EN0_REG0, 12);
+static AML_CLK_GATE_SYS_CLK(sys_ir_ctrl, SYS_CLK_EN0_REG0, 13);
+static AML_CLK_GATE_SYS_CLK(sys_irq_ctrl, SYS_CLK_EN0_REG0, 14);
+static AML_CLK_GATE_SYS_CLK(sys_msr_clk, SYS_CLK_EN0_REG0, 15);
+static AML_CLK_GATE_SYS_CLK(sys_rom, SYS_CLK_EN0_REG0, 16);
+static AML_CLK_GATE_SYS_CLK(sys_uart_f, SYS_CLK_EN0_REG0, 17);
+static AML_CLK_GATE_SYS_CLK(sys_cpu_apb, SYS_CLK_EN0_REG0, 18);
+static AML_CLK_GATE_SYS_CLK(sys_rsa, SYS_CLK_EN0_REG0, 19);
+static AML_CLK_GATE_SYS_CLK(sys_sar_adc, SYS_CLK_EN0_REG0, 20);
+static AML_CLK_GATE_SYS_CLK(sys_startup, SYS_CLK_EN0_REG0, 21);
+static AML_CLK_GATE_SYS_CLK(sys_secure, SYS_CLK_EN0_REG0, 22);
+static AML_CLK_GATE_SYS_CLK(sys_spifc, SYS_CLK_EN0_REG0, 23);
+static AML_CLK_GATE_SYS_CLK(sys_nna, SYS_CLK_EN0_REG0, 25);
+static AML_CLK_GATE_SYS_CLK(sys_eth_mac, SYS_CLK_EN0_REG0, 26);
+static AML_CLK_GATE_SYS_CLK(sys_gic, SYS_CLK_EN0_REG0, 27);
+static AML_CLK_GATE_SYS_CLK(sys_rama, SYS_CLK_EN0_REG0, 28);
+static AML_CLK_GATE_SYS_CLK(sys_big_nic, SYS_CLK_EN0_REG0, 29);
+static AML_CLK_GATE_SYS_CLK(sys_ramb, SYS_CLK_EN0_REG0, 30);
+static AML_CLK_GATE_SYS_CLK(sys_audio_pclk, SYS_CLK_EN0_REG0, 31);
+static AML_CLK_GATE_SYS_CLK(sys_pwm_kl, SYS_CLK_EN0_REG1, 0);
+static AML_CLK_GATE_SYS_CLK(sys_pwm_ij, SYS_CLK_EN0_REG1, 1);
+static AML_CLK_GATE_SYS_CLK(sys_usb, SYS_CLK_EN0_REG1, 2);
+static AML_CLK_GATE_SYS_CLK(sys_sd_emmc_a, SYS_CLK_EN0_REG1, 3);
+static AML_CLK_GATE_SYS_CLK(sys_sd_emmc_c, SYS_CLK_EN0_REG1, 4);
+static AML_CLK_GATE_SYS_CLK(sys_pwm_ab, SYS_CLK_EN0_REG1, 5);
+static AML_CLK_GATE_SYS_CLK(sys_pwm_cd, SYS_CLK_EN0_REG1, 6);
+static AML_CLK_GATE_SYS_CLK(sys_pwm_ef, SYS_CLK_EN0_REG1, 7);
+static AML_CLK_GATE_SYS_CLK(sys_pwm_gh, SYS_CLK_EN0_REG1, 8);
+static AML_CLK_GATE_SYS_CLK(sys_spicc_1, SYS_CLK_EN0_REG1, 9);
+static AML_CLK_GATE_SYS_CLK(sys_spicc_0, SYS_CLK_EN0_REG1, 10);
+static AML_CLK_GATE_SYS_CLK(sys_uart_a, SYS_CLK_EN0_REG1, 11);
+static AML_CLK_GATE_SYS_CLK(sys_uart_b, SYS_CLK_EN0_REG1, 12);
+static AML_CLK_GATE_SYS_CLK(sys_uart_c, SYS_CLK_EN0_REG1, 13);
+static AML_CLK_GATE_SYS_CLK(sys_uart_d, SYS_CLK_EN0_REG1, 14);
+static AML_CLK_GATE_SYS_CLK(sys_uart_e, SYS_CLK_EN0_REG1, 15);
+static AML_CLK_GATE_SYS_CLK(sys_i2c_m_a, SYS_CLK_EN0_REG1, 16);
+static AML_CLK_GATE_SYS_CLK(sys_i2c_m_b, SYS_CLK_EN0_REG1, 17);
+static AML_CLK_GATE_SYS_CLK(sys_i2c_m_c, SYS_CLK_EN0_REG1, 18);
+static AML_CLK_GATE_SYS_CLK(sys_i2c_m_d, SYS_CLK_EN0_REG1, 19);
+static AML_CLK_GATE_SYS_CLK(sys_i2c_s_a, SYS_CLK_EN0_REG1, 20);
+static AML_CLK_GATE_SYS_CLK(sys_rtc, SYS_CLK_EN0_REG1, 21);
+static AML_CLK_GATE_SYS_CLK(sys_ge2d, SYS_CLK_EN0_REG1, 22);
+static AML_CLK_GATE_SYS_CLK(sys_isp, SYS_CLK_EN0_REG1, 23);
+static AML_CLK_GATE_SYS_CLK(sys_gpv_isp_nic, SYS_CLK_EN0_REG1, 24);
+static AML_CLK_GATE_SYS_CLK(sys_gpv_cve_nic, SYS_CLK_EN0_REG1, 25);
+static AML_CLK_GATE_SYS_CLK(sys_mipi_dsi_host, SYS_CLK_EN0_REG1, 26);
+static AML_CLK_GATE_SYS_CLK(sys_mipi_dsi_phy, SYS_CLK_EN0_REG1, 27);
+static AML_CLK_GATE_SYS_CLK(sys_eth_phy, SYS_CLK_EN0_REG1, 28);
+static AML_CLK_GATE_SYS_CLK(sys_acodec, SYS_CLK_EN0_REG1, 29);
+static AML_CLK_GATE_SYS_CLK(sys_dwap, SYS_CLK_EN0_REG1, 30);
+static AML_CLK_GATE_SYS_CLK(sys_dos, SYS_CLK_EN0_REG1, 31);
+static AML_CLK_GATE_SYS_CLK(sys_cve, SYS_CLK_EN0_REG2, 0);
+static AML_CLK_GATE_SYS_CLK(sys_vout, SYS_CLK_EN0_REG2, 1);
+static AML_CLK_GATE_SYS_CLK(sys_vc9000e, SYS_CLK_EN0_REG2, 2);
+static AML_CLK_GATE_SYS_CLK(sys_pwm_mn, SYS_CLK_EN0_REG2, 3);
+static AML_CLK_GATE_SYS_CLK(sys_sd_emmc_b, SYS_CLK_EN0_REG2, 4);
+
+static AML_CLK_GATE_AXI_CLK(axi_sys_nic, AXI_CLK_EN0, 2);
+static AML_CLK_GATE_AXI_CLK(axi_isp_nic, AXI_CLK_EN0, 3);
+static AML_CLK_GATE_AXI_CLK(axi_cve_nic, AXI_CLK_EN0, 4);
+static AML_CLK_GATE_AXI_CLK(axi_ramb, AXI_CLK_EN0, 5);
+static AML_CLK_GATE_AXI_CLK(axi_rama, AXI_CLK_EN0, 6);
+static AML_CLK_GATE_AXI_CLK(axi_cpu_dmc, AXI_CLK_EN0, 7);
+static AML_CLK_GATE_AXI_CLK(axi_nic, AXI_CLK_EN0, 8);
+static AML_CLK_GATE_AXI_CLK(axi_dma, AXI_CLK_EN0, 9);
+static AML_CLK_GATE_AXI_CLK(axi_mux_nic, AXI_CLK_EN0, 10);
+static AML_CLK_GATE_AXI_CLK(axi_capu, AXI_CLK_EN0, 11);
+static AML_CLK_GATE_AXI_CLK(axi_cve, AXI_CLK_EN0, 12);
+static AML_CLK_GATE_AXI_CLK(axi_dev1_dmc, AXI_CLK_EN0, 13);
+static AML_CLK_GATE_AXI_CLK(axi_dev0_dmc, AXI_CLK_EN0, 14);
+static AML_CLK_GATE_AXI_CLK(axi_dsp_dmc, AXI_CLK_EN0, 15);
+
+/*
+ * clk_12_24m model
+ *
+ * |------| |-----| clk_12m_24m |-----|
+ * xtal---->| gate |---->| div |------------>| pad |
+ * |------| |-----| |-----|
+ */
+static struct clk_regmap clk_12_24m_in = {
+ .data = &(struct clk_regmap_gate_data) {
+ .offset = CLK12_24_CTRL,
+ .bit_idx = 11,
+ },
+ .hw.init = &(struct clk_init_data) {
+ .name = "clk_12_24m_in",
+ .ops = &clk_regmap_gate_ops,
+ .parent_data = &(const struct clk_parent_data) {
+ .fw_name = "xtal_24m",
+ },
+ .num_parents = 1,
+ },
+};
+
+static struct clk_regmap clk_12_24m = {
+ .data = &(struct clk_regmap_div_data) {
+ .offset = CLK12_24_CTRL,
+ .shift = 10,
+ .width = 1,
+ },
+ .hw.init = &(struct clk_init_data) {
+ .name = "clk_12_24m",
+ .ops = &clk_regmap_divider_ops,
+ .parent_hws = (const struct clk_hw *[]) {
+ &clk_12_24m_in.hw
+ },
+ .num_parents = 1,
+ },
+};
+
+/* Fix me: set value 0 will div by 2 like value 1 */
+static struct clk_regmap fclk_25m_div = {
+ .data = &(struct clk_regmap_div_data) {
+ .offset = CLK12_24_CTRL,
+ .shift = 0,
+ .width = 8,
+ },
+ .hw.init = &(struct clk_init_data) {
+ .name = "fclk_25m_div",
+ .ops = &clk_regmap_divider_ops,
+ .parent_data = &(const struct clk_parent_data) {
+ .fw_name = "fix",
+ },
+ .num_parents = 1,
+ },
+};
+
+static struct clk_regmap fclk_25m = {
+ .data = &(struct clk_regmap_gate_data) {
+ .offset = CLK12_24_CTRL,
+ .bit_idx = 12,
+ },
+ .hw.init = &(struct clk_init_data) {
+ .name = "fclk_25m",
+ .ops = &clk_regmap_gate_ops,
+ .parent_hws = (const struct clk_hw *[]) {
+ &fclk_25m_div.hw
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ },
+};
+
+/*
+ * Channel 2(sys_pll_div16), 17(sys_cpu_clk_div16) registers have
+ * permission restrictions. These registers are not readable or writable
+ * by the kernel, only accessed through SMC to SCP. This is not
+ * available at the moment.
+ * Channel 3(ddr_dpll_pt_clk) is manged by the DDR module; channel 12(cts_msr_clk)
+ * is manged by clock measures module. Their hardware are out of clock tree.
+ * Channel 4 8 9 10 11 13 14 15 16 18 are not connected.
+ */
+static u32 gen_parent_table[] = { 0, 1, 5, 6, 7, 19, 20, 21, 22, 23, 24};
+
+static const struct clk_parent_data gen_parent_data[] = {
+ { .hw = &cts_osc_src.hw },
+ { .hw = &rtc_clk.hw },
+ { .fw_name = "gp0" },
+ { .fw_name = "gp1" },
+ { .fw_name = "hifi" },
+ { .fw_name = "fdiv2" },
+ { .fw_name = "fdiv2p5" },
+ { .fw_name = "fdiv3" },
+ { .fw_name = "fdiv4" },
+ { .fw_name = "fdiv5" },
+ { .fw_name = "fdiv7" }
+};
+
+static struct clk_regmap gen_sel = {
+ .data = &(struct clk_regmap_mux_data) {
+ .offset = GEN_CLK_CTRL,
+ .mask = 0x1f,
+ .shift = 12,
+ .table = gen_parent_table,
+ },
+ .hw.init = &(struct clk_init_data) {
+ .name = "gen_sel",
+ .ops = &clk_regmap_mux_ops,
+ .parent_data = gen_parent_data,
+ .num_parents = ARRAY_SIZE(gen_parent_data),
+ },
+};
+
+static struct clk_regmap gen_div = {
+ .data = &(struct clk_regmap_div_data) {
+ .offset = GEN_CLK_CTRL,
+ .shift = 0,
+ .width = 11,
+ },
+ .hw.init = &(struct clk_init_data) {
+ .name = "gen_div",
+ .ops = &clk_regmap_divider_ops,
+ .parent_hws = (const struct clk_hw *[]) {
+ &gen_sel.hw
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ },
+};
+
+static struct clk_regmap gen = {
+ .data = &(struct clk_regmap_gate_data) {
+ .offset = GEN_CLK_CTRL,
+ .bit_idx = 11,
+ },
+ .hw.init = &(struct clk_init_data) {
+ .name = "gen",
+ .ops = &clk_regmap_gate_ops,
+ .parent_hws = (const struct clk_hw *[]) {
+ &gen_div.hw
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ },
+};
+
+static const struct clk_parent_data saradc_parent_data[] = {
+ { .hw = &cts_osc_src.hw },
+ { .hw = &sys_clk.hw }
+};
+
+static struct clk_regmap saradc_sel = {
+ .data = &(struct clk_regmap_mux_data) {
+ .offset = SAR_CLK_CTRL0,
+ .mask = 0x1,
+ .shift = 9,
+ },
+ .hw.init = &(struct clk_init_data) {
+ .name = "saradc_sel",
+ .ops = &clk_regmap_mux_ops,
+ .parent_data = saradc_parent_data,
+ .num_parents = ARRAY_SIZE(saradc_parent_data),
+ },
+};
+
+static struct clk_regmap saradc_div = {
+ .data = &(struct clk_regmap_div_data) {
+ .offset = SAR_CLK_CTRL0,
+ .shift = 0,
+ .width = 8,
+ },
+ .hw.init = &(struct clk_init_data) {
+ .name = "saradc_div",
+ .ops = &clk_regmap_divider_ops,
+ .parent_hws = (const struct clk_hw *[]) {
+ &saradc_sel.hw
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ },
+};
+
+static struct clk_regmap saradc = {
+ .data = &(struct clk_regmap_gate_data) {
+ .offset = SAR_CLK_CTRL0,
+ .bit_idx = 8,
+ },
+ .hw.init = &(struct clk_init_data) {
+ .name = "saradc",
+ .ops = &clk_regmap_gate_ops,
+ .parent_hws = (const struct clk_hw *[]) {
+ &saradc_div.hw
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ },
+};
+
+static const struct clk_parent_data pwm_parent_data[] = {
+ { .hw = &cts_osc_src.hw },
+ { .fw_name = "gp1" },
+ { .fw_name = "fdiv4" },
+ { .fw_name = "fdiv3" }
+};
+
+#define AML_PWM_CLK_MUX(_name, _reg, _shift) { \
+ .data = &(struct clk_regmap_mux_data) { \
+ .offset = _reg, \
+ .mask = 0x3, \
+ .shift = _shift, \
+ }, \
+ .hw.init = &(struct clk_init_data) { \
+ .name = #_name "_sel", \
+ .ops = &clk_regmap_mux_ops, \
+ .parent_data = pwm_parent_data, \
+ .num_parents = ARRAY_SIZE(pwm_parent_data), \
+ }, \
+}
+
+#define AML_PWM_CLK_DIV(_name, _reg, _shift) { \
+ .data = &(struct clk_regmap_div_data) { \
+ .offset = _reg, \
+ .shift = _shift, \
+ .width = 8, \
+ }, \
+ .hw.init = &(struct clk_init_data) { \
+ .name = #_name "_div", \
+ .ops = &clk_regmap_divider_ops, \
+ .parent_names = (const char *[]) { #_name "_sel" },\
+ .num_parents = 1, \
+ .flags = CLK_SET_RATE_PARENT, \
+ }, \
+}
+
+#define AML_PWM_CLK_GATE(_name, _reg, _bit) { \
+ .data = &(struct clk_regmap_gate_data) { \
+ .offset = _reg, \
+ .bit_idx = _bit, \
+ }, \
+ .hw.init = &(struct clk_init_data) { \
+ .name = #_name, \
+ .ops = &clk_regmap_gate_ops, \
+ .parent_names = (const char *[]) { #_name "_div" },\
+ .num_parents = 1, \
+ .flags = CLK_SET_RATE_PARENT, \
+ }, \
+}
+
+static struct clk_regmap pwm_a_sel =
+ AML_PWM_CLK_MUX(pwm_a, PWM_CLK_AB_CTRL, 9);
+static struct clk_regmap pwm_a_div =
+ AML_PWM_CLK_DIV(pwm_a, PWM_CLK_AB_CTRL, 0);
+static struct clk_regmap pwm_a =
+ AML_PWM_CLK_GATE(pwm_a, PWM_CLK_AB_CTRL, 8);
+
+static struct clk_regmap pwm_b_sel =
+ AML_PWM_CLK_MUX(pwm_b, PWM_CLK_AB_CTRL, 25);
+static struct clk_regmap pwm_b_div =
+ AML_PWM_CLK_DIV(pwm_b, PWM_CLK_AB_CTRL, 16);
+static struct clk_regmap pwm_b =
+ AML_PWM_CLK_GATE(pwm_b, PWM_CLK_AB_CTRL, 24);
+
+static struct clk_regmap pwm_c_sel =
+ AML_PWM_CLK_MUX(pwm_c, PWM_CLK_CD_CTRL, 9);
+static struct clk_regmap pwm_c_div =
+ AML_PWM_CLK_DIV(pwm_c, PWM_CLK_CD_CTRL, 0);
+static struct clk_regmap pwm_c =
+ AML_PWM_CLK_GATE(pwm_c, PWM_CLK_CD_CTRL, 8);
+
+static struct clk_regmap pwm_d_sel =
+ AML_PWM_CLK_MUX(pwm_d, PWM_CLK_CD_CTRL, 25);
+static struct clk_regmap pwm_d_div =
+ AML_PWM_CLK_DIV(pwm_d, PWM_CLK_CD_CTRL, 16);
+static struct clk_regmap pwm_d =
+ AML_PWM_CLK_GATE(pwm_d, PWM_CLK_CD_CTRL, 24);
+
+static struct clk_regmap pwm_e_sel =
+ AML_PWM_CLK_MUX(pwm_e, PWM_CLK_EF_CTRL, 9);
+static struct clk_regmap pwm_e_div =
+ AML_PWM_CLK_DIV(pwm_e, PWM_CLK_EF_CTRL, 0);
+static struct clk_regmap pwm_e =
+ AML_PWM_CLK_GATE(pwm_e, PWM_CLK_EF_CTRL, 8);
+
+static struct clk_regmap pwm_f_sel =
+ AML_PWM_CLK_MUX(pwm_f, PWM_CLK_EF_CTRL, 25);
+static struct clk_regmap pwm_f_div =
+ AML_PWM_CLK_DIV(pwm_f, PWM_CLK_EF_CTRL, 16);
+static struct clk_regmap pwm_f =
+ AML_PWM_CLK_GATE(pwm_f, PWM_CLK_EF_CTRL, 24);
+
+static struct clk_regmap pwm_g_sel =
+ AML_PWM_CLK_MUX(pwm_g, PWM_CLK_GH_CTRL, 9);
+static struct clk_regmap pwm_g_div =
+ AML_PWM_CLK_DIV(pwm_g, PWM_CLK_GH_CTRL, 0);
+static struct clk_regmap pwm_g =
+ AML_PWM_CLK_GATE(pwm_g, PWM_CLK_GH_CTRL, 8);
+
+static struct clk_regmap pwm_h_sel =
+ AML_PWM_CLK_MUX(pwm_h, PWM_CLK_GH_CTRL, 25);
+static struct clk_regmap pwm_h_div =
+ AML_PWM_CLK_DIV(pwm_h, PWM_CLK_GH_CTRL, 16);
+static struct clk_regmap pwm_h =
+ AML_PWM_CLK_GATE(pwm_h, PWM_CLK_GH_CTRL, 24);
+
+static struct clk_regmap pwm_i_sel =
+ AML_PWM_CLK_MUX(pwm_i, PWM_CLK_IJ_CTRL, 9);
+static struct clk_regmap pwm_i_div =
+ AML_PWM_CLK_DIV(pwm_i, PWM_CLK_IJ_CTRL, 0);
+static struct clk_regmap pwm_i =
+ AML_PWM_CLK_GATE(pwm_i, PWM_CLK_IJ_CTRL, 8);
+
+static struct clk_regmap pwm_j_sel =
+ AML_PWM_CLK_MUX(pwm_j, PWM_CLK_IJ_CTRL, 25);
+static struct clk_regmap pwm_j_div =
+ AML_PWM_CLK_DIV(pwm_j, PWM_CLK_IJ_CTRL, 16);
+static struct clk_regmap pwm_j =
+ AML_PWM_CLK_GATE(pwm_j, PWM_CLK_IJ_CTRL, 24);
+
+static struct clk_regmap pwm_k_sel =
+ AML_PWM_CLK_MUX(pwm_k, PWM_CLK_KL_CTRL, 9);
+static struct clk_regmap pwm_k_div =
+ AML_PWM_CLK_DIV(pwm_k, PWM_CLK_KL_CTRL, 0);
+static struct clk_regmap pwm_k =
+ AML_PWM_CLK_GATE(pwm_k, PWM_CLK_KL_CTRL, 8);
+
+static struct clk_regmap pwm_l_sel =
+ AML_PWM_CLK_MUX(pwm_l, PWM_CLK_KL_CTRL, 25);
+static struct clk_regmap pwm_l_div =
+ AML_PWM_CLK_DIV(pwm_l, PWM_CLK_KL_CTRL, 16);
+static struct clk_regmap pwm_l =
+ AML_PWM_CLK_GATE(pwm_l, PWM_CLK_KL_CTRL, 24);
+
+static struct clk_regmap pwm_m_sel =
+ AML_PWM_CLK_MUX(pwm_m, PWM_CLK_MN_CTRL, 9);
+static struct clk_regmap pwm_m_div =
+ AML_PWM_CLK_DIV(pwm_m, PWM_CLK_MN_CTRL, 0);
+static struct clk_regmap pwm_m =
+ AML_PWM_CLK_GATE(pwm_m, PWM_CLK_MN_CTRL, 8);
+
+static struct clk_regmap pwm_n_sel =
+ AML_PWM_CLK_MUX(pwm_n, PWM_CLK_MN_CTRL, 25);
+static struct clk_regmap pwm_n_div =
+ AML_PWM_CLK_DIV(pwm_n, PWM_CLK_MN_CTRL, 16);
+static struct clk_regmap pwm_n =
+ AML_PWM_CLK_GATE(pwm_n, PWM_CLK_MN_CTRL, 24);
+
+static const struct clk_parent_data spicc_parent_data[] = {
+ { .hw = &cts_osc_src.hw },
+ { .hw = &sys_clk.hw },
+ { .fw_name = "fdiv4" },
+ { .fw_name = "fdiv3" },
+ { .fw_name = "fdiv2" },
+ { .fw_name = "fdiv5" },
+ { .fw_name = "fdiv7" }
+};
+
+static struct clk_regmap spicc_a_sel = {
+ .data = &(struct clk_regmap_mux_data) {
+ .offset = SPICC_CLK_CTRL,
+ .mask = 0x7,
+ .shift = 7,
+ },
+ .hw.init = &(struct clk_init_data) {
+ .name = "spicc_a_sel",
+ .ops = &clk_regmap_mux_ops,
+ .parent_data = spicc_parent_data,
+ .num_parents = ARRAY_SIZE(spicc_parent_data),
+ },
+};
+
+static struct clk_regmap spicc_a_div = {
+ .data = &(struct clk_regmap_div_data) {
+ .offset = SPICC_CLK_CTRL,
+ .shift = 0,
+ .width = 6,
+ },
+ .hw.init = &(struct clk_init_data) {
+ .name = "spicc_a_div",
+ .ops = &clk_regmap_divider_ops,
+ .parent_hws = (const struct clk_hw *[]) {
+ &spicc_a_sel.hw
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ },
+};
+
+static struct clk_regmap spicc_a = {
+ .data = &(struct clk_regmap_gate_data) {
+ .offset = SPICC_CLK_CTRL,
+ .bit_idx = 6,
+ },
+ .hw.init = &(struct clk_init_data) {
+ .name = "spicc_a",
+ .ops = &clk_regmap_gate_ops,
+ .parent_hws = (const struct clk_hw *[]) {
+ &spicc_a_div.hw
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ },
+};
+
+static struct clk_regmap spicc_b_sel = {
+ .data = &(struct clk_regmap_mux_data) {
+ .offset = SPICC_CLK_CTRL,
+ .mask = 0x7,
+ .shift = 23,
+ },
+ .hw.init = &(struct clk_init_data) {
+ .name = "spicc_b_sel",
+ .ops = &clk_regmap_mux_ops,
+ .parent_data = spicc_parent_data,
+ .num_parents = ARRAY_SIZE(spicc_parent_data),
+ },
+};
+
+static struct clk_regmap spicc_b_div = {
+ .data = &(struct clk_regmap_div_data) {
+ .offset = SPICC_CLK_CTRL,
+ .shift = 16,
+ .width = 6,
+ },
+ .hw.init = &(struct clk_init_data) {
+ .name = "spicc_b_div",
+ .ops = &clk_regmap_divider_ops,
+ .parent_hws = (const struct clk_hw *[]) {
+ &spicc_b_sel.hw
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ },
+};
+
+static struct clk_regmap spicc_b = {
+ .data = &(struct clk_regmap_gate_data) {
+ .offset = SPICC_CLK_CTRL,
+ .bit_idx = 22,
+ },
+ .hw.init = &(struct clk_init_data) {
+ .name = "spicc_b",
+ .ops = &clk_regmap_gate_ops,
+ .parent_hws = (const struct clk_hw *[]) {
+ &spicc_b_div.hw
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ },
+};
+
+static const struct clk_parent_data spifc_parent_data[] = {
+ { .fw_name = "gp0" },
+ { .fw_name = "fdiv2" },
+ { .fw_name = "fdiv3" },
+ { .fw_name = "fdiv2p5" },
+ { .fw_name = "hifi" },
+ { .fw_name = "fdiv4" },
+ { .fw_name = "fdiv5" },
+ { .fw_name = "fdiv7" }
+};
+
+static struct clk_regmap spifc_sel = {
+ .data = &(struct clk_regmap_mux_data) {
+ .offset = SPIFC_CLK_CTRL,
+ .mask = 0x7,
+ .shift = 9,
+ },
+ .hw.init = &(struct clk_init_data) {
+ .name = "spifc_sel",
+ .ops = &clk_regmap_mux_ops,
+ .parent_data = spifc_parent_data,
+ .num_parents = ARRAY_SIZE(spifc_parent_data),
+ },
+};
+
+static struct clk_regmap spifc_div = {
+ .data = &(struct clk_regmap_div_data) {
+ .offset = SPIFC_CLK_CTRL,
+ .shift = 0,
+ .width = 7,
+ },
+ .hw.init = &(struct clk_init_data) {
+ .name = "spifc_div",
+ .ops = &clk_regmap_divider_ops,
+ .parent_hws = (const struct clk_hw *[]) {
+ &spifc_sel.hw
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ },
+};
+
+static struct clk_regmap spifc = {
+ .data = &(struct clk_regmap_gate_data) {
+ .offset = SPIFC_CLK_CTRL,
+ .bit_idx = 8,
+ },
+ .hw.init = &(struct clk_init_data) {
+ .name = "spifc",
+ .ops = &clk_regmap_gate_ops,
+ .parent_hws = (const struct clk_hw *[]) {
+ &spifc_div.hw
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ },
+};
+
+static const struct clk_parent_data emmc_parent_data[] = {
+ { .hw = &cts_osc_src.hw },
+ { .fw_name = "fdiv2" },
+ { .fw_name = "fdiv3" },
+ { .fw_name = "hifi" },
+ { .fw_name = "fdiv2p5" },
+ { .fw_name = "fdiv4" },
+ { .fw_name = "gp1" },
+ { .fw_name = "gp0" }
+};
+
+static struct clk_regmap sd_emmc_a_sel = {
+ .data = &(struct clk_regmap_mux_data) {
+ .offset = SD_EMMC_CLK_CTRL,
+ .mask = 0x7,
+ .shift = 9,
+ },
+ .hw.init = &(struct clk_init_data) {
+ .name = "sd_emmc_a_sel",
+ .ops = &clk_regmap_mux_ops,
+ .parent_data = emmc_parent_data,
+ .num_parents = ARRAY_SIZE(emmc_parent_data),
+ },
+};
+
+static struct clk_regmap sd_emmc_a_div = {
+ .data = &(struct clk_regmap_div_data) {
+ .offset = SD_EMMC_CLK_CTRL,
+ .shift = 0,
+ .width = 7,
+ },
+ .hw.init = &(struct clk_init_data) {
+ .name = "sd_emmc_a_div",
+ .ops = &clk_regmap_divider_ops,
+ .parent_hws = (const struct clk_hw *[]) {
+ &sd_emmc_a_sel.hw
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ },
+};
+
+static struct clk_regmap sd_emmc_a = {
+ .data = &(struct clk_regmap_gate_data) {
+ .offset = SD_EMMC_CLK_CTRL,
+ .bit_idx = 7,
+ },
+ .hw.init = &(struct clk_init_data) {
+ .name = "sd_emmc_a",
+ .ops = &clk_regmap_gate_ops,
+ .parent_hws = (const struct clk_hw *[]) {
+ &sd_emmc_a_div.hw
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ },
+};
+
+static struct clk_regmap sd_emmc_b_sel = {
+ .data = &(struct clk_regmap_mux_data) {
+ .offset = SD_EMMC_CLK_CTRL,
+ .mask = 0x7,
+ .shift = 25,
+ },
+ .hw.init = &(struct clk_init_data) {
+ .name = "sd_emmc_b_sel",
+ .ops = &clk_regmap_mux_ops,
+ .parent_data = emmc_parent_data,
+ .num_parents = ARRAY_SIZE(emmc_parent_data),
+ },
+};
+
+static struct clk_regmap sd_emmc_b_div = {
+ .data = &(struct clk_regmap_div_data) {
+ .offset = SD_EMMC_CLK_CTRL,
+ .shift = 16,
+ .width = 7,
+ },
+ .hw.init = &(struct clk_init_data) {
+ .name = "sd_emmc_b_div",
+ .ops = &clk_regmap_divider_ops,
+ .parent_hws = (const struct clk_hw *[]) {
+ &sd_emmc_b_sel.hw
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ },
+};
+
+static struct clk_regmap sd_emmc_b = {
+ .data = &(struct clk_regmap_gate_data) {
+ .offset = SD_EMMC_CLK_CTRL,
+ .bit_idx = 23,
+ },
+ .hw.init = &(struct clk_init_data) {
+ .name = "sd_emmc_b",
+ .ops = &clk_regmap_gate_ops,
+ .parent_hws = (const struct clk_hw *[]) {
+ &sd_emmc_b_div.hw
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ },
+};
+
+static struct clk_regmap sd_emmc_c_sel = {
+ .data = &(struct clk_regmap_mux_data) {
+ .offset = NAND_CLK_CTRL,
+ .mask = 0x7,
+ .shift = 9,
+ },
+ .hw.init = &(struct clk_init_data) {
+ .name = "sd_emmc_c_sel",
+ .ops = &clk_regmap_mux_ops,
+ .parent_data = emmc_parent_data,
+ .num_parents = ARRAY_SIZE(emmc_parent_data),
+ },
+};
+
+static struct clk_regmap sd_emmc_c_div = {
+ .data = &(struct clk_regmap_div_data) {
+ .offset = NAND_CLK_CTRL,
+ .shift = 0,
+ .width = 7,
+ },
+ .hw.init = &(struct clk_init_data) {
+ .name = "sd_emmc_c_div",
+ .ops = &clk_regmap_divider_ops,
+ .parent_hws = (const struct clk_hw *[]) {
+ &sd_emmc_c_sel.hw
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ },
+};
+
+static struct clk_regmap sd_emmc_c = {
+ .data = &(struct clk_regmap_gate_data) {
+ .offset = NAND_CLK_CTRL,
+ .bit_idx = 7,
+ },
+ .hw.init = &(struct clk_init_data) {
+ .name = "sd_emmc_c",
+ .ops = &clk_regmap_gate_ops,
+ .parent_hws = (const struct clk_hw *[]) {
+ &sd_emmc_c_div.hw
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ },
+};
+
+static struct clk_regmap ts_div = {
+ .data = &(struct clk_regmap_div_data) {
+ .offset = TS_CLK_CTRL,
+ .shift = 0,
+ .width = 8,
+ },
+ .hw.init = &(struct clk_init_data) {
+ .name = "ts_div",
+ .ops = &clk_regmap_divider_ops,
+ .parent_data = &(const struct clk_parent_data) {
+ .hw = &cts_osc_src.hw,
+ },
+ .num_parents = 1,
+ },
+};
+
+static struct clk_regmap ts = {
+ .data = &(struct clk_regmap_gate_data) {
+ .offset = TS_CLK_CTRL,
+ .bit_idx = 8,
+ },
+ .hw.init = &(struct clk_init_data) {
+ .name = "ts",
+ .ops = &clk_regmap_gate_ops,
+ .parent_hws = (const struct clk_hw *[]) {
+ &ts_div.hw
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ },
+};
+
+static const struct clk_parent_data eth_parent = {
+ .fw_name = "fdiv2",
+};
+
+static struct clk_fixed_factor eth_125m_div = {
+ .mult = 1,
+ .div = 8,
+ .hw.init = &(struct clk_init_data) {
+ .name = "eth_125m_div",
+ .ops = &clk_fixed_factor_ops,
+ .parent_data = &eth_parent,
+ .num_parents = 1,
+ },
+};
+
+static struct clk_regmap eth_125m = {
+ .data = &(struct clk_regmap_gate_data) {
+ .offset = ETH_CLK_CTRL,
+ .bit_idx = 7,
+ },
+ .hw.init = &(struct clk_init_data) {
+ .name = "eth_125m",
+ .ops = &clk_regmap_gate_ops,
+ .parent_hws = (const struct clk_hw *[]) {
+ &eth_125m_div.hw
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ },
+};
+
+static struct clk_regmap eth_rmii_div = {
+ .data = &(struct clk_regmap_div_data) {
+ .offset = ETH_CLK_CTRL,
+ .shift = 0,
+ .width = 7,
+ },
+ .hw.init = &(struct clk_init_data) {
+ .name = "eth_rmii_div",
+ .ops = &clk_regmap_divider_ops,
+ .parent_data = &eth_parent,
+ .num_parents = 1,
+ },
+};
+
+static struct clk_regmap eth_rmii = {
+ .data = &(struct clk_regmap_gate_data) {
+ .offset = ETH_CLK_CTRL,
+ .bit_idx = 8,
+ },
+ .hw.init = &(struct clk_init_data) {
+ .name = "eth_rmii",
+ .ops = &clk_regmap_gate_ops,
+ .parent_hws = (const struct clk_hw *[]) {
+ &eth_rmii_div.hw
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ },
+};
+
+static const struct clk_parent_data mipi_dsi_meas_parent_data[] = {
+ { .hw = &cts_osc_src.hw },
+ { .fw_name = "fdiv4" },
+ { .fw_name = "fdiv3" },
+ { .fw_name = "fdiv5" },
+ { .fw_name = "gp1" },
+ { .fw_name = "gp0" },
+ { .fw_name = "fdiv2" },
+ { .fw_name = "fdiv7" }
+};
+
+static struct clk_regmap mipi_dsi_meas_sel = {
+ .data = &(struct clk_regmap_mux_data) {
+ .offset = VDIN_MEAS_CLK_CTRL,
+ .mask = 0x7,
+ .shift = 21,
+ },
+ .hw.init = &(struct clk_init_data) {
+ .name = "mipi_dsi_meas_sel",
+ .ops = &clk_regmap_mux_ops,
+ .parent_data = mipi_dsi_meas_parent_data,
+ .num_parents = ARRAY_SIZE(mipi_dsi_meas_parent_data),
+ },
+};
+
+static struct clk_regmap mipi_dsi_meas_div = {
+ .data = &(struct clk_regmap_div_data) {
+ .offset = VDIN_MEAS_CLK_CTRL,
+ .shift = 12,
+ .width = 7,
+ },
+ .hw.init = &(struct clk_init_data) {
+ .name = "mipi_dsi_meas_div",
+ .ops = &clk_regmap_divider_ops,
+ .parent_hws = (const struct clk_hw *[]) {
+ &mipi_dsi_meas_sel.hw
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ },
+};
+
+static struct clk_regmap mipi_dsi_meas = {
+ .data = &(struct clk_regmap_gate_data) {
+ .offset = VDIN_MEAS_CLK_CTRL,
+ .bit_idx = 20,
+ },
+ .hw.init = &(struct clk_init_data) {
+ .name = "mipi_dsi_meas",
+ .ops = &clk_regmap_gate_ops,
+ .parent_hws = (const struct clk_hw *[]) {
+ &mipi_dsi_meas_div.hw
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ },
+};
+
+static const struct clk_parent_data dsi_phy_parent_data[] = {
+ { .fw_name = "gp1" },
+ { .fw_name = "gp0" },
+ { .fw_name = "hifi" },
+ { .fw_name = "fdiv3" },
+ { .fw_name = "fdiv2" },
+ { .fw_name = "fdiv2p5" },
+ { .fw_name = "fdiv4" },
+ { .fw_name = "fdiv7" }
+};
+
+static struct clk_regmap dsi_phy_sel = {
+ .data = &(struct clk_regmap_mux_data) {
+ .offset = MIPIDSI_PHY_CLK_CTRL,
+ .mask = 0x7,
+ .shift = 12,
+ },
+ .hw.init = &(struct clk_init_data) {
+ .name = "dsi_phy_sel",
+ .ops = &clk_regmap_mux_ops,
+ .parent_data = dsi_phy_parent_data,
+ .num_parents = ARRAY_SIZE(dsi_phy_parent_data),
+ },
+};
+
+static struct clk_regmap dsi_phy_div = {
+ .data = &(struct clk_regmap_div_data) {
+ .offset = MIPIDSI_PHY_CLK_CTRL,
+ .shift = 0,
+ .width = 7,
+ },
+ .hw.init = &(struct clk_init_data) {
+ .name = "dsi_phy_div",
+ .ops = &clk_regmap_divider_ops,
+ .parent_hws = (const struct clk_hw *[]) {
+ &dsi_phy_sel.hw
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ },
+};
+
+static struct clk_regmap dsi_phy = {
+ .data = &(struct clk_regmap_gate_data) {
+ .offset = MIPIDSI_PHY_CLK_CTRL,
+ .bit_idx = 8,
+ },
+ .hw.init = &(struct clk_init_data) {
+ .name = "dsi_phy",
+ .ops = &clk_regmap_gate_ops,
+ .parent_hws = (const struct clk_hw *[]) {
+ &dsi_phy_div.hw
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ },
+};
+
+static const struct clk_parent_data vout_parent_data[] = {
+ { .fw_name = "gp1" },
+ { .fw_name = "fdiv3" },
+ { .fw_name = "fdiv4" },
+ { .fw_name = "fdiv5" },
+ { .fw_name = "gp0" },
+ { .fw_name = "hifi" },
+ { .fw_name = "fdiv2p5" },
+ { .fw_name = "fdiv7" }
+};
+
+static struct clk_regmap vout_mclk_sel = {
+ .data = &(struct clk_regmap_mux_data) {
+ .offset = VOUTENC_CLK_CTRL,
+ .mask = 0x7,
+ .shift = 9,
+ },
+ .hw.init = &(struct clk_init_data) {
+ .name = "vout_mclk_sel",
+ .ops = &clk_regmap_mux_ops,
+ .parent_data = vout_parent_data,
+ .num_parents = ARRAY_SIZE(vout_parent_data),
+ },
+};
+
+static struct clk_regmap vout_mclk_div = {
+ .data = &(struct clk_regmap_div_data) {
+ .offset = VOUTENC_CLK_CTRL,
+ .shift = 0,
+ .width = 7,
+ },
+ .hw.init = &(struct clk_init_data) {
+ .name = "vout_mclk_div",
+ .ops = &clk_regmap_divider_ops,
+ .parent_hws = (const struct clk_hw *[]) {
+ &vout_mclk_sel.hw
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ },
+};
+
+static struct clk_regmap vout_mclk = {
+ .data = &(struct clk_regmap_gate_data) {
+ .offset = MIPIDSI_PHY_CLK_CTRL,
+ .bit_idx = 8,
+ },
+ .hw.init = &(struct clk_init_data) {
+ .name = "vout_mclk",
+ .ops = &clk_regmap_gate_ops,
+ .parent_hws = (const struct clk_hw *[]) {
+ &vout_mclk_div.hw
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ },
+};
+
+static struct clk_regmap vout_enc_sel = {
+ .data = &(struct clk_regmap_mux_data) {
+ .offset = VOUTENC_CLK_CTRL,
+ .mask = 0x7,
+ .shift = 25,
+ },
+ .hw.init = &(struct clk_init_data) {
+ .name = "vout_enc_sel",
+ .ops = &clk_regmap_mux_ops,
+ .parent_data = vout_parent_data,
+ .num_parents = ARRAY_SIZE(vout_parent_data),
+ },
+};
+
+static struct clk_regmap vout_enc_div = {
+ .data = &(struct clk_regmap_div_data) {
+ .offset = VOUTENC_CLK_CTRL,
+ .shift = 16,
+ .width = 7,
+ },
+ .hw.init = &(struct clk_init_data) {
+ .name = "vout_enc_div",
+ .ops = &clk_regmap_divider_ops,
+ .parent_hws = (const struct clk_hw *[]) {
+ &vout_enc_sel.hw
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ },
+};
+
+static struct clk_regmap vout_enc = {
+ .data = &(struct clk_regmap_gate_data) {
+ .offset = VOUTENC_CLK_CTRL,
+ .bit_idx = 24,
+ },
+ .hw.init = &(struct clk_init_data) {
+ .name = "vout_enc",
+ .ops = &clk_regmap_gate_ops,
+ .parent_hws = (const struct clk_hw *[]) {
+ &vout_enc_div.hw
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ },
+};
+
+static const struct clk_parent_data hcodec_pre_parent_data[] = {
+ { .fw_name = "fdiv2p5" },
+ { .fw_name = "fdiv3" },
+ { .fw_name = "fdiv4" },
+ { .fw_name = "fdiv5" },
+ { .fw_name = "fdiv7" },
+ { .fw_name = "hifi" },
+ { .fw_name = "gp0" },
+ { .hw = &cts_osc_src.hw }
+};
+
+static struct clk_regmap hcodec_0_sel = {
+ .data = &(struct clk_regmap_mux_data) {
+ .offset = VDEC_CLK_CTRL,
+ .mask = 0x7,
+ .shift = 9,
+ },
+ .hw.init = &(struct clk_init_data) {
+ .name = "hcodec_0_sel",
+ .ops = &clk_regmap_mux_ops,
+ .parent_data = hcodec_pre_parent_data,
+ .num_parents = ARRAY_SIZE(hcodec_pre_parent_data),
+ },
+};
+
+static struct clk_regmap hcodec_0_div = {
+ .data = &(struct clk_regmap_div_data) {
+ .offset = VDEC_CLK_CTRL,
+ .shift = 0,
+ .width = 7,
+ },
+ .hw.init = &(struct clk_init_data) {
+ .name = "hcodec_0_div",
+ .ops = &clk_regmap_divider_ops,
+ .parent_hws = (const struct clk_hw *[]) {
+ &hcodec_0_sel.hw
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ },
+};
+
+static struct clk_regmap hcodec_0 = {
+ .data = &(struct clk_regmap_gate_data) {
+ .offset = VDEC_CLK_CTRL,
+ .bit_idx = 8,
+ },
+ .hw.init = &(struct clk_init_data) {
+ .name = "hcodec_0",
+ .ops = &clk_regmap_gate_ops,
+ .parent_hws = (const struct clk_hw *[]) {
+ &hcodec_0_div.hw
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ },
+};
+
+static struct clk_regmap hcodec_1_sel = {
+ .data = &(struct clk_regmap_mux_data) {
+ .offset = VDEC3_CLK_CTRL,
+ .mask = 0x7,
+ .shift = 9,
+ },
+ .hw.init = &(struct clk_init_data) {
+ .name = "hcodec_1_sel",
+ .ops = &clk_regmap_mux_ops,
+ .parent_data = hcodec_pre_parent_data,
+ .num_parents = ARRAY_SIZE(hcodec_pre_parent_data),
+ },
+};
+
+static struct clk_regmap hcodec_1_div = {
+ .data = &(struct clk_regmap_div_data) {
+ .offset = VDEC3_CLK_CTRL,
+ .shift = 0,
+ .width = 7,
+ },
+ .hw.init = &(struct clk_init_data) {
+ .name = "hcodec_1_div",
+ .ops = &clk_regmap_divider_ops,
+ .parent_hws = (const struct clk_hw *[]) {
+ &hcodec_1_sel.hw
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ },
+};
+
+static struct clk_regmap hcodec_1 = {
+ .data = &(struct clk_regmap_gate_data) {
+ .offset = VDEC3_CLK_CTRL,
+ .bit_idx = 8,
+ },
+ .hw.init = &(struct clk_init_data) {
+ .name = "hcodec_1",
+ .ops = &clk_regmap_gate_ops,
+ .parent_hws = (const struct clk_hw *[]) {
+ &hcodec_1_div.hw
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ },
+};
+
+static const struct clk_parent_data hcodec_parent_data[] = {
+ { .hw = &hcodec_0.hw },
+ { .hw = &hcodec_1.hw }
+};
+
+static struct clk_regmap hcodec = {
+ .data = &(struct clk_regmap_mux_data) {
+ .offset = VDEC3_CLK_CTRL,
+ .mask = 0x1,
+ .shift = 15,
+ },
+ .hw.init = &(struct clk_init_data) {
+ .name = "hcodec",
+ .ops = &clk_regmap_mux_ops,
+ .parent_data = hcodec_parent_data,
+ .num_parents = ARRAY_SIZE(hcodec_parent_data),
+ .flags = CLK_SET_RATE_PARENT,
+ },
+};
+
+static const struct clk_parent_data vc9000e_parent_data[] = {
+ { .hw = &cts_osc_src.hw },
+ { .fw_name = "fdiv4" },
+ { .fw_name = "fdiv3" },
+ { .fw_name = "fdiv5" },
+ { .fw_name = "fdiv7" },
+ { .fw_name = "fdiv2p5" },
+ { .fw_name = "hifi" },
+ { .fw_name = "gp0" }
+};
+
+static struct clk_regmap vc9000e_aclk_sel = {
+ .data = &(struct clk_regmap_mux_data) {
+ .offset = VC9000E_CLK_CTRL,
+ .mask = 0x7,
+ .shift = 9,
+ },
+ .hw.init = &(struct clk_init_data) {
+ .name = "vc9000e_aclk_sel",
+ .ops = &clk_regmap_mux_ops,
+ .parent_data = vc9000e_parent_data,
+ .num_parents = ARRAY_SIZE(vc9000e_parent_data),
+ },
+};
+
+static struct clk_regmap vc9000e_aclk_div = {
+ .data = &(struct clk_regmap_div_data) {
+ .offset = VC9000E_CLK_CTRL,
+ .shift = 0,
+ .width = 7,
+ },
+ .hw.init = &(struct clk_init_data) {
+ .name = "vc9000e_aclk_div",
+ .ops = &clk_regmap_divider_ops,
+ .parent_hws = (const struct clk_hw *[]) {
+ &vc9000e_aclk_sel.hw
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ },
+};
+
+static struct clk_regmap vc9000e_aclk = {
+ .data = &(struct clk_regmap_gate_data) {
+ .offset = VC9000E_CLK_CTRL,
+ .bit_idx = 8,
+ },
+ .hw.init = &(struct clk_init_data) {
+ .name = "vc9000e_aclk",
+ .ops = &clk_regmap_gate_ops,
+ .parent_hws = (const struct clk_hw *[]) {
+ &vc9000e_aclk_div.hw
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ },
+};
+
+static struct clk_regmap vc9000e_core_sel = {
+ .data = &(struct clk_regmap_mux_data) {
+ .offset = VC9000E_CLK_CTRL,
+ .mask = 0x7,
+ .shift = 25,
+ },
+ .hw.init = &(struct clk_init_data) {
+ .name = "vc9000e_core_sel",
+ .ops = &clk_regmap_mux_ops,
+ .parent_data = vc9000e_parent_data,
+ .num_parents = ARRAY_SIZE(vc9000e_parent_data),
+ },
+};
+
+static struct clk_regmap vc9000e_core_div = {
+ .data = &(struct clk_regmap_div_data) {
+ .offset = VC9000E_CLK_CTRL,
+ .shift = 16,
+ .width = 7,
+ },
+ .hw.init = &(struct clk_init_data) {
+ .name = "vc9000e_core_div",
+ .ops = &clk_regmap_divider_ops,
+ .parent_hws = (const struct clk_hw *[]) {
+ &vc9000e_core_sel.hw
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ },
+};
+
+static struct clk_regmap vc9000e_core = {
+ .data = &(struct clk_regmap_gate_data) {
+ .offset = VC9000E_CLK_CTRL,
+ .bit_idx = 24,
+ },
+ .hw.init = &(struct clk_init_data) {
+ .name = "vc9000e_core",
+ .ops = &clk_regmap_gate_ops,
+ .parent_hws = (const struct clk_hw *[]) {
+ &vc9000e_core_div.hw
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ },
+};
+
+static const struct clk_parent_data csi_phy_parent_data[] = {
+ { .fw_name = "fdiv2p5" },
+ { .fw_name = "fdiv3" },
+ { .fw_name = "fdiv4" },
+ { .fw_name = "fdiv5" },
+ { .fw_name = "gp0" },
+ { .fw_name = "hifi" },
+ { .fw_name = "gp1" },
+ { .hw = &cts_osc_src.hw }
+};
+
+static struct clk_regmap csi_phy0_sel = {
+ .data = &(struct clk_regmap_mux_data) {
+ .offset = ISP0_CLK_CTRL,
+ .mask = 0x7,
+ .shift = 25,
+ },
+ .hw.init = &(struct clk_init_data) {
+ .name = "csi_phy0_sel",
+ .ops = &clk_regmap_mux_ops,
+ .parent_data = csi_phy_parent_data,
+ .num_parents = ARRAY_SIZE(csi_phy_parent_data),
+ },
+};
+
+static struct clk_regmap csi_phy0_div = {
+ .data = &(struct clk_regmap_div_data) {
+ .offset = ISP0_CLK_CTRL,
+ .shift = 16,
+ .width = 7,
+ },
+ .hw.init = &(struct clk_init_data) {
+ .name = "csi_phy0_div",
+ .ops = &clk_regmap_divider_ops,
+ .parent_hws = (const struct clk_hw *[]) {
+ &csi_phy0_sel.hw
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ },
+};
+
+static struct clk_regmap csi_phy0 = {
+ .data = &(struct clk_regmap_gate_data) {
+ .offset = ISP0_CLK_CTRL,
+ .bit_idx = 24,
+ },
+ .hw.init = &(struct clk_init_data) {
+ .name = "csi_phy0",
+ .ops = &clk_regmap_gate_ops,
+ .parent_hws = (const struct clk_hw *[]) {
+ &csi_phy0_div.hw
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ },
+};
+
+static const struct clk_parent_data dewarpa_parent_data[] = {
+ { .fw_name = "fdiv2p5" },
+ { .fw_name = "fdiv3" },
+ { .fw_name = "fdiv4" },
+ { .fw_name = "fdiv5" },
+ { .fw_name = "gp0" },
+ { .fw_name = "hifi" },
+ { .fw_name = "gp1" },
+ { .fw_name = "fdiv7" }
+};
+
+static struct clk_regmap dewarpa_sel = {
+ .data = &(struct clk_regmap_mux_data) {
+ .offset = DEWARPA_CLK_CTRL,
+ .mask = 0x7,
+ .shift = 9,
+ },
+ .hw.init = &(struct clk_init_data) {
+ .name = "dewarpa_sel",
+ .ops = &clk_regmap_mux_ops,
+ .parent_data = dewarpa_parent_data,
+ .num_parents = ARRAY_SIZE(dewarpa_parent_data),
+ },
+};
+
+static struct clk_regmap dewarpa_div = {
+ .data = &(struct clk_regmap_div_data) {
+ .offset = DEWARPA_CLK_CTRL,
+ .shift = 0,
+ .width = 7,
+ },
+ .hw.init = &(struct clk_init_data) {
+ .name = "dewarpa_div",
+ .ops = &clk_regmap_divider_ops,
+ .parent_hws = (const struct clk_hw *[]) {
+ &dewarpa_sel.hw
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ },
+};
+
+static struct clk_regmap dewarpa = {
+ .data = &(struct clk_regmap_gate_data) {
+ .offset = DEWARPA_CLK_CTRL,
+ .bit_idx = 8,
+ },
+ .hw.init = &(struct clk_init_data) {
+ .name = "dewarpa",
+ .ops = &clk_regmap_gate_ops,
+ .parent_hws = (const struct clk_hw *[]) {
+ &dewarpa_div.hw
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ },
+};
+
+static const struct clk_parent_data isp_parent_data[] = {
+ { .fw_name = "fdiv2p5" },
+ { .fw_name = "fdiv3" },
+ { .fw_name = "fdiv4" },
+ { .fw_name = "fdiv5" },
+ { .fw_name = "gp0" },
+ { .fw_name = "hifi" },
+ { .fw_name = "gp1" },
+ { .hw = &cts_osc_src.hw }
+};
+
+static struct clk_regmap isp0_sel = {
+ .data = &(struct clk_regmap_mux_data) {
+ .offset = ISP0_CLK_CTRL,
+ .mask = 0x7,
+ .shift = 9,
+ },
+ .hw.init = &(struct clk_init_data) {
+ .name = "isp0_sel",
+ .ops = &clk_regmap_mux_ops,
+ .parent_data = isp_parent_data,
+ .num_parents = ARRAY_SIZE(isp_parent_data),
+ },
+};
+
+static struct clk_regmap isp0_div = {
+ .data = &(struct clk_regmap_div_data) {
+ .offset = ISP0_CLK_CTRL,
+ .shift = 0,
+ .width = 7,
+ },
+ .hw.init = &(struct clk_init_data) {
+ .name = "isp0_div",
+ .ops = &clk_regmap_divider_ops,
+ .parent_hws = (const struct clk_hw *[]) {
+ &isp0_sel.hw
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ },
+};
+
+static struct clk_regmap isp0 = {
+ .data = &(struct clk_regmap_gate_data) {
+ .offset = ISP0_CLK_CTRL,
+ .bit_idx = 8,
+ },
+ .hw.init = &(struct clk_init_data) {
+ .name = "isp0",
+ .ops = &clk_regmap_gate_ops,
+ .parent_hws = (const struct clk_hw *[]) {
+ &isp0_div.hw
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ },
+};
+
+static const struct clk_parent_data nna_core_parent_data[] = {
+ { .hw = &cts_osc_src.hw },
+ { .fw_name = "fdiv2p5" },
+ { .fw_name = "fdiv4" },
+ { .fw_name = "fdiv3" },
+ { .fw_name = "fdiv5" },
+ { .fw_name = "fdiv2" },
+ { .fw_name = "gp1" },
+ { .fw_name = "hifi" }
+};
+
+static struct clk_regmap nna_core_sel = {
+ .data = &(struct clk_regmap_mux_data) {
+ .offset = NNA_CLK_CTRL,
+ .mask = 0x7,
+ .shift = 9,
+ },
+ .hw.init = &(struct clk_init_data) {
+ .name = "nna_core_sel",
+ .ops = &clk_regmap_mux_ops,
+ .parent_data = nna_core_parent_data,
+ .num_parents = ARRAY_SIZE(nna_core_parent_data),
+ },
+};
+
+static struct clk_regmap nna_core_div = {
+ .data = &(struct clk_regmap_div_data) {
+ .offset = NNA_CLK_CTRL,
+ .shift = 0,
+ .width = 7,
+ },
+ .hw.init = &(struct clk_init_data) {
+ .name = "nna_core_div",
+ .ops = &clk_regmap_divider_ops,
+ .parent_hws = (const struct clk_hw *[]) {
+ &nna_core_sel.hw
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ },
+};
+
+static struct clk_regmap nna_core = {
+ .data = &(struct clk_regmap_gate_data) {
+ .offset = NNA_CLK_CTRL,
+ .bit_idx = 8,
+ },
+ .hw.init = &(struct clk_init_data) {
+ .name = "nna_core",
+ .ops = &clk_regmap_gate_ops,
+ .parent_hws = (const struct clk_hw *[]) {
+ &nna_core_div.hw
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ },
+};
+
+static const struct clk_parent_data ge2d_parent_data[] = {
+ { .hw = &cts_osc_src.hw },
+ { .fw_name = "fdiv2p5" },
+ { .fw_name = "fdiv3" },
+ { .fw_name = "fdiv4" },
+ { .fw_name = "hifi" },
+ { .fw_name = "fdiv5" },
+ { .fw_name = "gp0" },
+ { .hw = &rtc_clk.hw }
+};
+
+static struct clk_regmap ge2d_sel = {
+ .data = &(struct clk_regmap_mux_data) {
+ .offset = GE2D_CLK_CTRL,
+ .mask = 0x7,
+ .shift = 9,
+ },
+ .hw.init = &(struct clk_init_data) {
+ .name = "ge2d_sel",
+ .ops = &clk_regmap_mux_ops,
+ .parent_data = ge2d_parent_data,
+ .num_parents = ARRAY_SIZE(ge2d_parent_data),
+ },
+};
+
+static struct clk_regmap ge2d_div = {
+ .data = &(struct clk_regmap_div_data) {
+ .offset = GE2D_CLK_CTRL,
+ .shift = 0,
+ .width = 7,
+ },
+ .hw.init = &(struct clk_init_data) {
+ .name = "ge2d_div",
+ .ops = &clk_regmap_divider_ops,
+ .parent_hws = (const struct clk_hw *[]) {
+ &ge2d_sel.hw
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ },
+};
+
+static struct clk_regmap ge2d = {
+ .data = &(struct clk_regmap_gate_data) {
+ .offset = GE2D_CLK_CTRL,
+ .bit_idx = 8,
+ },
+ .hw.init = &(struct clk_init_data) {
+ .name = "ge2d",
+ .ops = &clk_regmap_gate_ops,
+ .parent_hws = (const struct clk_hw *[]) {
+ &ge2d_div.hw
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ },
+};
+
+static const struct clk_parent_data vapb_parent_data[] = {
+ { .fw_name = "fdiv2p5" },
+ { .fw_name = "fdiv3" },
+ { .fw_name = "fdiv4" },
+ { .fw_name = "fdiv5" },
+ { .fw_name = "gp0" },
+ { .fw_name = "hifi" },
+ { .fw_name = "gp1" },
+ { .hw = &cts_osc_src.hw }
+};
+
+static struct clk_regmap vapb_sel = {
+ .data = &(struct clk_regmap_mux_data) {
+ .offset = VAPB_CLK_CTRL,
+ .mask = 0x7,
+ .shift = 9,
+ },
+ .hw.init = &(struct clk_init_data) {
+ .name = "vapb_sel",
+ .ops = &clk_regmap_mux_ops,
+ .parent_data = vapb_parent_data,
+ .num_parents = ARRAY_SIZE(vapb_parent_data),
+ },
+};
+
+static struct clk_regmap vapb_div = {
+ .data = &(struct clk_regmap_div_data) {
+ .offset = VAPB_CLK_CTRL,
+ .shift = 0,
+ .width = 7,
+ },
+ .hw.init = &(struct clk_init_data) {
+ .name = "vapb_div",
+ .ops = &clk_regmap_divider_ops,
+ .parent_hws = (const struct clk_hw *[]) {
+ &vapb_sel.hw
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ },
+};
+
+static struct clk_regmap vapb = {
+ .data = &(struct clk_regmap_gate_data) {
+ .offset = VAPB_CLK_CTRL,
+ .bit_idx = 8,
+ },
+ .hw.init = &(struct clk_init_data) {
+ .name = "vapb",
+ .ops = &clk_regmap_gate_ops,
+ .parent_hws = (const struct clk_hw *[]) {
+ &vapb_div.hw
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ },
+};
+
+static struct clk_hw *c3_periphs_hw_clks[] = {
+ [CLKID_PLL_SRC] = &pll_src.hw,
+ [CLKID_MCLK_PLL_SRC] = &mclk_pll_src.hw,
+ [CLKID_DDR_PLL_SRC] = &ddr_pll_src.hw,
+ [CLKID_DDR_PHY_SRC] = &ddr_phy_src.hw,
+ [CLKID_USB_PLL_SRC] = &usb_pll_src.hw,
+ [CLKID_MIPI_ISP_VOUT_SRC] = &mipi_isp_vout_src.hw,
+ [CLKID_USB_CTRL_SRC] = &usb_ctrl_src.hw,
+ [CLKID_ETH_PLL_SRC] = &eth_pll_src.hw,
+ [CLKID_CTS_OSC_SRC] = &cts_osc_src.hw,
+ [CLKID_RTC_XTAL_CLKIN] = &rtc_xtal_clkin.hw,
+ [CLKID_RTC_32K_DIV] = &rtc_32k_div.hw,
+ [CLKID_RTC_32K_MUX] = &rtc_32k_mux.hw,
+ [CLKID_RTC_32K] = &rtc_32k.hw,
+ [CLKID_RTC_CLK] = &rtc_clk.hw,
+ [CLKID_SYS_A_SEL] = &sys_a_sel.hw,
+ [CLKID_SYS_A_DIV] = &sys_a_div.hw,
+ [CLKID_SYS_A] = &sys_a.hw,
+ [CLKID_SYS_B_SEL] = &sys_b_sel.hw,
+ [CLKID_SYS_B_DIV] = &sys_b_div.hw,
+ [CLKID_SYS_B] = &sys_b.hw,
+ [CLKID_SYS_CLK] = &sys_clk.hw,
+ [CLKID_AXI_A_SEL] = &axi_a_sel.hw,
+ [CLKID_AXI_A_DIV] = &axi_a_div.hw,
+ [CLKID_AXI_A] = &axi_a.hw,
+ [CLKID_AXI_B_SEL] = &axi_b_sel.hw,
+ [CLKID_AXI_B_DIV] = &axi_b_div.hw,
+ [CLKID_AXI_B] = &axi_b.hw,
+ [CLKID_AXI_CLK] = &axi_clk.hw,
+ [CLKID_SYS_RESET_CTRL] = &sys_reset_ctrl.hw,
+ [CLKID_SYS_PAD_CTRL] = &sys_pwr_ctrl.hw,
+ [CLKID_SYS_CTRL] = &sys_ctrl.hw,
+ [CLKID_SYS_TS_PLL] = &sys_ts_pll.hw,
+ [CLKID_SYS_DEV_ARB] = &sys_dev_arb.hw,
+ [CLKID_SYS_MMC_PCLK] = &sys_mmc_pclk.hw,
+ [CLKID_SYS_CAPU] = &sys_capu.hw,
+ [CLKID_SYS_CPU_CTRL] = &sys_cpu_ctrl.hw,
+ [CLKID_SYS_JTAG_CTRL] = &sys_jtag_ctrl.hw,
+ [CLKID_SYS_IR_CTRL] = &sys_ir_ctrl.hw,
+ [CLKID_SYS_IRQ_CTRL] = &sys_irq_ctrl.hw,
+ [CLKID_SYS_MSR_CLK] = &sys_msr_clk.hw,
+ [CLKID_SYS_ROM] = &sys_rom.hw,
+ [CLKID_SYS_UART_F] = &sys_uart_f.hw,
+ [CLKID_SYS_CPU_ARB] = &sys_cpu_apb.hw,
+ [CLKID_SYS_RSA] = &sys_rsa.hw,
+ [CLKID_SYS_SAR_ADC] = &sys_sar_adc.hw,
+ [CLKID_SYS_STARTUP] = &sys_startup.hw,
+ [CLKID_SYS_SECURE] = &sys_secure.hw,
+ [CLKID_SYS_SPIFC] = &sys_spifc.hw,
+ [CLKID_SYS_NNA] = &sys_nna.hw,
+ [CLKID_SYS_ETH_MAC] = &sys_eth_mac.hw,
+ [CLKID_SYS_GIC] = &sys_gic.hw,
+ [CLKID_SYS_RAMA] = &sys_rama.hw,
+ [CLKID_SYS_BIG_NIC] = &sys_big_nic.hw,
+ [CLKID_SYS_RAMB] = &sys_ramb.hw,
+ [CLKID_SYS_AUDIO_PCLK] = &sys_audio_pclk.hw,
+ [CLKID_SYS_PWM_KL] = &sys_pwm_kl.hw,
+ [CLKID_SYS_PWM_IJ] = &sys_pwm_ij.hw,
+ [CLKID_SYS_USB] = &sys_usb.hw,
+ [CLKID_SYS_SD_EMMC_A] = &sys_sd_emmc_a.hw,
+ [CLKID_SYS_SD_EMMC_C] = &sys_sd_emmc_c.hw,
+ [CLKID_SYS_PWM_AB] = &sys_pwm_ab.hw,
+ [CLKID_SYS_PWM_CD] = &sys_pwm_cd.hw,
+ [CLKID_SYS_PWM_EF] = &sys_pwm_ef.hw,
+ [CLKID_SYS_PWM_GH] = &sys_pwm_gh.hw,
+ [CLKID_SYS_SPICC_1] = &sys_spicc_1.hw,
+ [CLKID_SYS_SPICC_0] = &sys_spicc_0.hw,
+ [CLKID_SYS_UART_A] = &sys_uart_a.hw,
+ [CLKID_SYS_UART_B] = &sys_uart_b.hw,
+ [CLKID_SYS_UART_C] = &sys_uart_c.hw,
+ [CLKID_SYS_UART_D] = &sys_uart_d.hw,
+ [CLKID_SYS_UART_E] = &sys_uart_e.hw,
+ [CLKID_SYS_I2C_M_A] = &sys_i2c_m_a.hw,
+ [CLKID_SYS_I2C_M_B] = &sys_i2c_m_b.hw,
+ [CLKID_SYS_I2C_M_C] = &sys_i2c_m_c.hw,
+ [CLKID_SYS_I2C_M_D] = &sys_i2c_m_d.hw,
+ [CLKID_SYS_I2S_S_A] = &sys_i2c_s_a.hw,
+ [CLKID_SYS_RTC] = &sys_rtc.hw,
+ [CLKID_SYS_GE2D] = &sys_ge2d.hw,
+ [CLKID_SYS_ISP] = &sys_isp.hw,
+ [CLKID_SYS_GPV_ISP_NIC] = &sys_gpv_isp_nic.hw,
+ [CLKID_SYS_GPV_CVE_NIC] = &sys_gpv_cve_nic.hw,
+ [CLKID_SYS_MIPI_DSI_HOST] = &sys_mipi_dsi_host.hw,
+ [CLKID_SYS_MIPI_DSI_PHY] = &sys_mipi_dsi_phy.hw,
+ [CLKID_SYS_ETH_PHY] = &sys_eth_phy.hw,
+ [CLKID_SYS_ACODEC] = &sys_acodec.hw,
+ [CLKID_SYS_DWAP] = &sys_dwap.hw,
+ [CLKID_SYS_DOS] = &sys_dos.hw,
+ [CLKID_SYS_CVE] = &sys_cve.hw,
+ [CLKID_SYS_VOUT] = &sys_vout.hw,
+ [CLKID_SYS_VC9000E] = &sys_vc9000e.hw,
+ [CLKID_SYS_PWM_MN] = &sys_pwm_mn.hw,
+ [CLKID_SYS_SD_EMMC_B] = &sys_sd_emmc_b.hw,
+ [CLKID_AXI_SYS_NIC] = &axi_sys_nic.hw,
+ [CLKID_AXI_ISP_NIC] = &axi_isp_nic.hw,
+ [CLKID_AXI_CVE_NIC] = &axi_cve_nic.hw,
+ [CLKID_AXI_RAMB] = &axi_ramb.hw,
+ [CLKID_AXI_RAMA] = &axi_rama.hw,
+ [CLKID_AXI_CPU_DMC] = &axi_cpu_dmc.hw,
+ [CLKID_AXI_NIC] = &axi_nic.hw,
+ [CLKID_AXI_DMA] = &axi_dma.hw,
+ [CLKID_AXI_MUX_NIC] = &axi_mux_nic.hw,
+ [CLKID_AXI_CAPU] = &axi_capu.hw,
+ [CLKID_AXI_CVE] = &axi_cve.hw,
+ [CLKID_AXI_DEV1_DMC] = &axi_dev1_dmc.hw,
+ [CLKID_AXI_DEV0_DMC] = &axi_dev0_dmc.hw,
+ [CLKID_AXI_DSP_DMC] = &axi_dsp_dmc.hw,
+ [CLKID_12_24M_IN] = &clk_12_24m_in.hw,
+ [CLKID_12M_24M] = &clk_12_24m.hw,
+ [CLKID_FCLK_25M_DIV] = &fclk_25m_div.hw,
+ [CLKID_FCLK_25M] = &fclk_25m.hw,
+ [CLKID_GEN_SEL] = &gen_sel.hw,
+ [CLKID_GEN_DIV] = &gen_div.hw,
+ [CLKID_GEN] = &gen.hw,
+ [CLKID_SARADC_SEL] = &saradc_sel.hw,
+ [CLKID_SARADC_DIV] = &saradc_div.hw,
+ [CLKID_SARADC] = &saradc.hw,
+ [CLKID_PWM_A_SEL] = &pwm_a_sel.hw,
+ [CLKID_PWM_A_DIV] = &pwm_a_div.hw,
+ [CLKID_PWM_A] = &pwm_a.hw,
+ [CLKID_PWM_B_SEL] = &pwm_b_sel.hw,
+ [CLKID_PWM_B_DIV] = &pwm_b_div.hw,
+ [CLKID_PWM_B] = &pwm_b.hw,
+ [CLKID_PWM_C_SEL] = &pwm_c_sel.hw,
+ [CLKID_PWM_C_DIV] = &pwm_c_div.hw,
+ [CLKID_PWM_C] = &pwm_c.hw,
+ [CLKID_PWM_D_SEL] = &pwm_d_sel.hw,
+ [CLKID_PWM_D_DIV] = &pwm_d_div.hw,
+ [CLKID_PWM_D] = &pwm_d.hw,
+ [CLKID_PWM_E_SEL] = &pwm_e_sel.hw,
+ [CLKID_PWM_E_DIV] = &pwm_e_div.hw,
+ [CLKID_PWM_E] = &pwm_e.hw,
+ [CLKID_PWM_F_SEL] = &pwm_f_sel.hw,
+ [CLKID_PWM_F_DIV] = &pwm_f_div.hw,
+ [CLKID_PWM_F] = &pwm_f.hw,
+ [CLKID_PWM_G_SEL] = &pwm_g_sel.hw,
+ [CLKID_PWM_G_DIV] = &pwm_g_div.hw,
+ [CLKID_PWM_G] = &pwm_g.hw,
+ [CLKID_PWM_H_SEL] = &pwm_h_sel.hw,
+ [CLKID_PWM_H_DIV] = &pwm_h_div.hw,
+ [CLKID_PWM_H] = &pwm_h.hw,
+ [CLKID_PWM_I_SEL] = &pwm_i_sel.hw,
+ [CLKID_PWM_I_DIV] = &pwm_i_div.hw,
+ [CLKID_PWM_I] = &pwm_i.hw,
+ [CLKID_PWM_J_SEL] = &pwm_j_sel.hw,
+ [CLKID_PWM_J_DIV] = &pwm_j_div.hw,
+ [CLKID_PWM_J] = &pwm_j.hw,
+ [CLKID_PWM_K_SEL] = &pwm_k_sel.hw,
+ [CLKID_PWM_K_DIV] = &pwm_k_div.hw,
+ [CLKID_PWM_K] = &pwm_k.hw,
+ [CLKID_PWM_L_SEL] = &pwm_l_sel.hw,
+ [CLKID_PWM_L_DIV] = &pwm_l_div.hw,
+ [CLKID_PWM_L] = &pwm_l.hw,
+ [CLKID_PWM_M_SEL] = &pwm_m_sel.hw,
+ [CLKID_PWM_M_DIV] = &pwm_m_div.hw,
+ [CLKID_PWM_M] = &pwm_m.hw,
+ [CLKID_PWM_N_SEL] = &pwm_n_sel.hw,
+ [CLKID_PWM_N_DIV] = &pwm_n_div.hw,
+ [CLKID_PWM_N] = &pwm_n.hw,
+ [CLKID_SPICC_A_SEL] = &spicc_a_sel.hw,
+ [CLKID_SPICC_A_DIV] = &spicc_a_div.hw,
+ [CLKID_SPICC_A] = &spicc_a.hw,
+ [CLKID_SPICC_B_SEL] = &spicc_b_sel.hw,
+ [CLKID_SPICC_B_DIV] = &spicc_b_div.hw,
+ [CLKID_SPICC_B] = &spicc_b.hw,
+ [CLKID_SPIFC_SEL] = &spifc_sel.hw,
+ [CLKID_SPIFC_DIV] = &spifc_div.hw,
+ [CLKID_SPIFC] = &spifc.hw,
+ [CLKID_SD_EMMC_A_SEL] = &sd_emmc_a_sel.hw,
+ [CLKID_SD_EMMC_A_DIV] = &sd_emmc_a_div.hw,
+ [CLKID_SD_EMMC_A] = &sd_emmc_a.hw,
+ [CLKID_SD_EMMC_B_SEL] = &sd_emmc_b_sel.hw,
+ [CLKID_SD_EMMC_B_DIV] = &sd_emmc_b_div.hw,
+ [CLKID_SD_EMMC_B] = &sd_emmc_b.hw,
+ [CLKID_SD_EMMC_C_SEL] = &sd_emmc_c_sel.hw,
+ [CLKID_SD_EMMC_C_DIV] = &sd_emmc_c_div.hw,
+ [CLKID_SD_EMMC_C] = &sd_emmc_c.hw,
+ [CLKID_TS_DIV] = &ts_div.hw,
+ [CLKID_TS] = &ts.hw,
+ [CLKID_ETH_125M_DIV] = &eth_125m_div.hw,
+ [CLKID_ETH_125M] = &eth_125m.hw,
+ [CLKID_ETH_RMII_DIV] = &eth_rmii_div.hw,
+ [CLKID_ETH_RMII] = &eth_rmii.hw,
+ [CLKID_MIPI_DSI_MEAS_SEL] = &mipi_dsi_meas_sel.hw,
+ [CLKID_MIPI_DSI_MEAS_DIV] = &mipi_dsi_meas_div.hw,
+ [CLKID_MIPI_DSI_MEAS] = &mipi_dsi_meas.hw,
+ [CLKID_DSI_PHY_SEL] = &dsi_phy_sel.hw,
+ [CLKID_DSI_PHY_DIV] = &dsi_phy_div.hw,
+ [CLKID_DSI_PHY] = &dsi_phy.hw,
+ [CLKID_VOUT_MCLK_SEL] = &vout_mclk_sel.hw,
+ [CLKID_VOUT_MCLK_DIV] = &vout_mclk_div.hw,
+ [CLKID_VOUT_MCLK] = &vout_mclk.hw,
+ [CLKID_VOUT_ENC_SEL] = &vout_enc_sel.hw,
+ [CLKID_VOUT_ENC_DIV] = &vout_enc_div.hw,
+ [CLKID_VOUT_ENC] = &vout_enc.hw,
+ [CLKID_HCODEC_0_SEL] = &hcodec_0_sel.hw,
+ [CLKID_HCODEC_0_DIV] = &hcodec_0_div.hw,
+ [CLKID_HCODEC_0] = &hcodec_0.hw,
+ [CLKID_HCODEC_1_SEL] = &hcodec_1_sel.hw,
+ [CLKID_HCODEC_1_DIV] = &hcodec_1_div.hw,
+ [CLKID_HCODEC_1] = &hcodec_1.hw,
+ [CLKID_HCODEC] = &hcodec.hw,
+ [CLKID_VC9000E_ACLK_SEL] = &vc9000e_aclk_sel.hw,
+ [CLKID_VC9000E_ACLK_DIV] = &vc9000e_aclk_div.hw,
+ [CLKID_VC9000E_ACLK] = &vc9000e_aclk.hw,
+ [CLKID_VC9000E_CORE_SEL] = &vc9000e_core_sel.hw,
+ [CLKID_VC9000E_CORE_DIV] = &vc9000e_core_div.hw,
+ [CLKID_VC9000E_CORE] = &vc9000e_core.hw,
+ [CLKID_CSI_PHY0_SEL] = &csi_phy0_sel.hw,
+ [CLKID_CSI_PHY0_DIV] = &csi_phy0_div.hw,
+ [CLKID_CSI_PHY0] = &csi_phy0.hw,
+ [CLKID_DEWARPA_SEL] = &dewarpa_sel.hw,
+ [CLKID_DEWARPA_DIV] = &dewarpa_div.hw,
+ [CLKID_DEWARPA] = &dewarpa.hw,
+ [CLKID_ISP0_SEL] = &isp0_sel.hw,
+ [CLKID_ISP0_DIV] = &isp0_div.hw,
+ [CLKID_ISP0] = &isp0.hw,
+ [CLKID_NNA_CORE_SEL] = &nna_core_sel.hw,
+ [CLKID_NNA_CORE_DIV] = &nna_core_div.hw,
+ [CLKID_NNA_CORE] = &nna_core.hw,
+ [CLKID_GE2D_SEL] = &ge2d_sel.hw,
+ [CLKID_GE2D_DIV] = &ge2d_div.hw,
+ [CLKID_GE2D] = &ge2d.hw,
+ [CLKID_VAPB_SEL] = &vapb_sel.hw,
+ [CLKID_VAPB_DIV] = &vapb_div.hw,
+ [CLKID_VAPB] = &vapb.hw,
+};
+
+/* Convenience table to populate regmap in .probe */
+static struct clk_regmap *const c3_periphs_clk_regmaps[] = {
+ &pll_src,
+ &mclk_pll_src,
+ &ddr_pll_src,
+ &ddr_phy_src,
+ &usb_pll_src,
+ &mipi_isp_vout_src,
+ &usb_ctrl_src,
+ &eth_pll_src,
+ &cts_osc_src,
+ &rtc_xtal_clkin,
+ &rtc_32k_div,
+ &rtc_32k_mux,
+ &rtc_32k,
+ &rtc_clk,
+ &sys_a_sel,
+ &sys_a_div,
+ &sys_a,
+ &sys_b_sel,
+ &sys_b_div,
+ &sys_b,
+ &sys_clk,
+ &axi_a_sel,
+ &axi_a_div,
+ &axi_a,
+ &axi_b_sel,
+ &axi_b_div,
+ &axi_b,
+ &axi_clk,
+ &sys_reset_ctrl,
+ &sys_pwr_ctrl,
+ &sys_pad_ctrl,
+ &sys_ctrl,
+ &sys_ts_pll,
+ &sys_dev_arb,
+ &sys_mmc_pclk,
+ &sys_capu,
+ &sys_cpu_ctrl,
+ &sys_jtag_ctrl,
+ &sys_ir_ctrl,
+ &sys_irq_ctrl,
+ &sys_msr_clk,
+ &sys_rom,
+ &sys_uart_f,
+ &sys_cpu_apb,
+ &sys_rsa,
+ &sys_sar_adc,
+ &sys_startup,
+ &sys_secure,
+ &sys_spifc,
+ &sys_nna,
+ &sys_eth_mac,
+ &sys_gic,
+ &sys_rama,
+ &sys_big_nic,
+ &sys_ramb,
+ &sys_audio_pclk,
+ &sys_pwm_kl,
+ &sys_pwm_ij,
+ &sys_usb,
+ &sys_sd_emmc_a,
+ &sys_sd_emmc_c,
+ &sys_pwm_ab,
+ &sys_pwm_cd,
+ &sys_pwm_ef,
+ &sys_pwm_gh,
+ &sys_spicc_1,
+ &sys_spicc_0,
+ &sys_uart_a,
+ &sys_uart_b,
+ &sys_uart_c,
+ &sys_uart_d,
+ &sys_uart_e,
+ &sys_i2c_m_a,
+ &sys_i2c_m_b,
+ &sys_i2c_m_c,
+ &sys_i2c_m_d,
+ &sys_i2c_s_a,
+ &sys_rtc,
+ &sys_ge2d,
+ &sys_isp,
+ &sys_gpv_isp_nic,
+ &sys_gpv_cve_nic,
+ &sys_mipi_dsi_host,
+ &sys_mipi_dsi_phy,
+ &sys_eth_phy,
+ &sys_acodec,
+ &sys_dwap,
+ &sys_dos,
+ &sys_cve,
+ &sys_vout,
+ &sys_vc9000e,
+ &sys_pwm_mn,
+ &sys_sd_emmc_b,
+ &axi_sys_nic,
+ &axi_isp_nic,
+ &axi_cve_nic,
+ &axi_ramb,
+ &axi_rama,
+ &axi_cpu_dmc,
+ &axi_nic,
+ &axi_dma,
+ &axi_mux_nic,
+ &axi_capu,
+ &axi_cve,
+ &axi_dev1_dmc,
+ &axi_dev0_dmc,
+ &axi_dsp_dmc,
+ &clk_12_24m_in,
+ &clk_12_24m,
+ &fclk_25m_div,
+ &fclk_25m,
+ &gen_sel,
+ &gen_div,
+ &gen,
+ &saradc_sel,
+ &saradc_div,
+ &saradc,
+ &pwm_a_sel,
+ &pwm_a_div,
+ &pwm_a,
+ &pwm_b_sel,
+ &pwm_b_div,
+ &pwm_b,
+ &pwm_c_sel,
+ &pwm_c_div,
+ &pwm_c,
+ &pwm_d_sel,
+ &pwm_d_div,
+ &pwm_d,
+ &pwm_e_sel,
+ &pwm_e_div,
+ &pwm_e,
+ &pwm_f_sel,
+ &pwm_f_div,
+ &pwm_f,
+ &pwm_g_sel,
+ &pwm_g_div,
+ &pwm_g,
+ &pwm_h_sel,
+ &pwm_h_div,
+ &pwm_h,
+ &pwm_i_sel,
+ &pwm_i_div,
+ &pwm_i,
+ &pwm_j_sel,
+ &pwm_j_div,
+ &pwm_j,
+ &pwm_k_sel,
+ &pwm_k_div,
+ &pwm_k,
+ &pwm_l_sel,
+ &pwm_l_div,
+ &pwm_l,
+ &pwm_m_sel,
+ &pwm_m_div,
+ &pwm_m,
+ &pwm_n_sel,
+ &pwm_n_div,
+ &pwm_n,
+ &spicc_a_sel,
+ &spicc_a_div,
+ &spicc_a,
+ &spicc_b_sel,
+ &spicc_b_div,
+ &spicc_b,
+ &spifc_sel,
+ &spifc_div,
+ &spifc,
+ &sd_emmc_a_sel,
+ &sd_emmc_a_div,
+ &sd_emmc_a,
+ &sd_emmc_b_sel,
+ &sd_emmc_b_div,
+ &sd_emmc_b,
+ &sd_emmc_c_sel,
+ &sd_emmc_c_div,
+ &sd_emmc_c,
+ &ts_div,
+ &ts,
+ &eth_125m,
+ &eth_rmii_div,
+ &eth_rmii,
+ &mipi_dsi_meas_sel,
+ &mipi_dsi_meas_div,
+ &mipi_dsi_meas,
+ &dsi_phy_sel,
+ &dsi_phy_div,
+ &dsi_phy,
+ &vout_mclk_sel,
+ &vout_mclk_div,
+ &vout_mclk,
+ &vout_enc_sel,
+ &vout_enc_div,
+ &vout_enc,
+ &hcodec_0_sel,
+ &hcodec_0_div,
+ &hcodec_0,
+ &hcodec_1_sel,
+ &hcodec_1_div,
+ &hcodec_1,
+ &hcodec,
+ &vc9000e_aclk_sel,
+ &vc9000e_aclk_div,
+ &vc9000e_aclk,
+ &vc9000e_core_sel,
+ &vc9000e_core_div,
+ &vc9000e_core,
+ &csi_phy0_sel,
+ &csi_phy0_div,
+ &csi_phy0,
+ &dewarpa_sel,
+ &dewarpa_div,
+ &dewarpa,
+ &isp0_sel,
+ &isp0_div,
+ &isp0,
+ &nna_core_sel,
+ &nna_core_div,
+ &nna_core,
+ &ge2d_sel,
+ &ge2d_div,
+ &ge2d,
+ &vapb_sel,
+ &vapb_div,
+ &vapb,
+};
+
+static struct regmap_config clkc_regmap_config = {
+ .reg_bits = 32,
+ .val_bits = 32,
+ .reg_stride = 4,
+};
+
+static struct meson_clk_hw_data c3_periphs_clks = {
+ .hws = c3_periphs_hw_clks,
+ .num = ARRAY_SIZE(c3_periphs_hw_clks),
+};
+
+static int aml_c3_peripherals_probe(struct platform_device *pdev)
+{
+ struct device *dev = &pdev->dev;
+ struct regmap *regmap;
+ void __iomem *base;
+ int clkid, ret, i;
+
+ base = devm_platform_ioremap_resource(pdev, 0);
+ if (IS_ERR(base))
+ return PTR_ERR(base);
+
+ regmap = devm_regmap_init_mmio(dev, base, &clkc_regmap_config);
+ if (IS_ERR(regmap))
+ return PTR_ERR(regmap);
+
+ /* Populate regmap for the regmap backed clocks */
+ for (i = 0; i < ARRAY_SIZE(c3_periphs_clk_regmaps); i++)
+ c3_periphs_clk_regmaps[i]->map = regmap;
+
+ for (clkid = 0; clkid < c3_periphs_clks.num; clkid++) {
+ /* array might be sparse */
+ if (!c3_periphs_clks.hws[clkid])
+ continue;
+
+ ret = devm_clk_hw_register(dev, c3_periphs_clks.hws[clkid]);
+ if (ret) {
+ dev_err(dev, "Clock registration failed\n");
+ return ret;
+ }
+ }
+
+ return devm_of_clk_add_hw_provider(dev, meson_clk_hw_get,
+ &c3_periphs_clks);
+}
+
+static const struct of_device_id c3_peripherals_clkc_match_table[] = {
+ {
+ .compatible = "amlogic,c3-peripherals-clkc",
+ },
+ { /* sentinel */ }
+};
+
+MODULE_DEVICE_TABLE(of, c3_peripherals_clkc_match_table);
+
+static struct platform_driver c3_peripherals_driver = {
+ .probe = aml_c3_peripherals_probe,
+ .driver = {
+ .name = "c3-peripherals-clkc",
+ .of_match_table = c3_peripherals_clkc_match_table,
+ },
+};
+
+module_platform_driver(c3_peripherals_driver);
+MODULE_AUTHOR("Chuan Liu <[email protected]>");
+MODULE_LICENSE("GPL");
--
2.39.2

2023-11-06 08:58:52

by Xianwei Zhao

[permalink] [raw]
Subject: [PATCH V6 2/4] dt-bindings: clock: add Amlogic C3 peripherals clock controller bindings

Add the peripherals clock controller dt-bindings for Amlogic C3 SoC family

Co-developed-by: Chuan Liu <[email protected]>
Signed-off-by: Chuan Liu <[email protected]>
Signed-off-by: Xianwei Zhao <[email protected]>
---
.../clock/amlogic,c3-peripherals-clkc.yaml | 104 ++++++++
.../clock/amlogic,c3-peripherals-clkc.h | 237 ++++++++++++++++++
2 files changed, 341 insertions(+)
create mode 100644 Documentation/devicetree/bindings/clock/amlogic,c3-peripherals-clkc.yaml
create mode 100644 include/dt-bindings/clock/amlogic,c3-peripherals-clkc.h

diff --git a/Documentation/devicetree/bindings/clock/amlogic,c3-peripherals-clkc.yaml b/Documentation/devicetree/bindings/clock/amlogic,c3-peripherals-clkc.yaml
new file mode 100644
index 000000000000..af1807dfa94a
--- /dev/null
+++ b/Documentation/devicetree/bindings/clock/amlogic,c3-peripherals-clkc.yaml
@@ -0,0 +1,104 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+# Copyright (C) 2022-2023 Amlogic, Inc. All rights reserved
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/clock/amlogic,c3-peripherals-clkc.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Amlogic C3 Serials Peripheral Clock Controller
+
+maintainers:
+ - Neil Armstrong <[email protected]>
+ - Jerome Brunet <[email protected]>
+ - Xianwei Zhao <[email protected]>
+ - Chuan Liu <[email protected]>
+
+properties:
+ compatible:
+ const: amlogic,c3-peripherals-clkc
+
+ reg:
+ maxItems: 1
+
+ clocks:
+ minItems: 12
+ items:
+ - description: input oscillator (usually at 24MHz)
+ - description: input oscillator (usually at 32KHz)
+ - description: input Fix PLL
+ - description: input Fclk div 2
+ - description: input Fclk div 2p5
+ - description: input Fclk div 3
+ - description: input Fclk div 4
+ - description: input Fclk div 5
+ - description: input Fclk div 7
+ - description: input gp0 pll
+ - description: input gp1 pll
+ - description: input hifi pll
+ - description: input pad clock for rtc_clk (optional)
+
+ clock-names:
+ minItems: 12
+ items:
+ - const: xtal_24m
+ - const: xtal_32k
+ - const: fix
+ - const: fdiv2
+ - const: fdiv2p5
+ - const: fdiv3
+ - const: fdiv4
+ - const: fdiv5
+ - const: fdiv7
+ - const: gp0
+ - const: gp1
+ - const: hifi
+ - const: pad
+
+ "#clock-cells":
+ const: 1
+
+required:
+ - compatible
+ - reg
+ - clocks
+ - clock-names
+ - "#clock-cells"
+
+additionalProperties: false
+
+examples:
+ - |
+ apb {
+ #address-cells = <2>;
+ #size-cells = <2>;
+
+ clock-controller@0 {
+ compatible = "amlogic,c3-peripherals-clkc";
+ reg = <0x0 0x0 0x0 0x49c>;
+ #clock-cells = <1>;
+ clocks = <&xtal_24m>,
+ <&xtal_32k>,
+ <&clkc_pll 1>,
+ <&clkc_pll 5>,
+ <&clkc_pll 7>,
+ <&clkc_pll 9>,
+ <&clkc_pll 11>,
+ <&clkc_pll 13>,
+ <&clkc_pll 15>,
+ <&clkc_pll 17>,
+ <&clkc_pll 19>,
+ <&clkc_pll 21>;
+ clock-names = "xtal_24m",
+ "xtal_32k",
+ "fix",
+ "fdiv2",
+ "fdiv2p5",
+ "fdiv3",
+ "fdiv4",
+ "fdiv5",
+ "fdiv7",
+ "gp0",
+ "gp1",
+ "hifi";
+ };
+ };
diff --git a/include/dt-bindings/clock/amlogic,c3-peripherals-clkc.h b/include/dt-bindings/clock/amlogic,c3-peripherals-clkc.h
new file mode 100644
index 000000000000..0175d8b9b32b
--- /dev/null
+++ b/include/dt-bindings/clock/amlogic,c3-peripherals-clkc.h
@@ -0,0 +1,237 @@
+/* SPDX-License-Identifier: (GPL-2.0-only OR MIT) */
+/*
+ * Copyright (c) 2023 Amlogic, Inc. All rights reserved.
+ * Author: Chuan Liu <[email protected]>
+ */
+
+#ifndef _DT_BINDINGS_CLOCK_AMLOGIC_C3_PERIPHERALS_CLKC_H
+#define _DT_BINDINGS_CLOCK_AMLOGIC_C3_PERIPHERALS_CLKC_H
+
+#define CLKID_PLL_SRC 0
+#define CLKID_MCLK_PLL_SRC 1
+#define CLKID_DDR_PLL_SRC 2
+#define CLKID_DDR_PHY_SRC 3
+#define CLKID_USB_PLL_SRC 4
+#define CLKID_MIPI_ISP_VOUT_SRC 5
+#define CLKID_USB_CTRL_SRC 6
+#define CLKID_ETH_PLL_SRC 7
+#define CLKID_CTS_OSC_SRC 8
+#define CLKID_RTC_XTAL_CLKIN 9
+#define CLKID_RTC_32K_DIV 10
+#define CLKID_RTC_32K_MUX 11
+#define CLKID_RTC_32K 12
+#define CLKID_RTC_CLK 13
+#define CLKID_SYS_A_SEL 14
+#define CLKID_SYS_A_DIV 15
+#define CLKID_SYS_A 16
+#define CLKID_SYS_B_SEL 17
+#define CLKID_SYS_B_DIV 18
+#define CLKID_SYS_B 19
+#define CLKID_SYS_CLK 20
+#define CLKID_AXI_A_SEL 21
+#define CLKID_AXI_A_DIV 22
+#define CLKID_AXI_A 23
+#define CLKID_AXI_B_SEL 24
+#define CLKID_AXI_B_DIV 25
+#define CLKID_AXI_B 26
+#define CLKID_AXI_CLK 27
+#define CLKID_SYS_RESET_CTRL 28
+#define CLKID_SYS_PWR_CTRL 29
+#define CLKID_SYS_PAD_CTRL 30
+#define CLKID_SYS_CTRL 31
+#define CLKID_SYS_TS_PLL 32
+#define CLKID_SYS_DEV_ARB 33
+#define CLKID_SYS_MMC_PCLK 34
+#define CLKID_SYS_CAPU 35
+#define CLKID_SYS_CPU_CTRL 36
+#define CLKID_SYS_JTAG_CTRL 37
+#define CLKID_SYS_IR_CTRL 38
+#define CLKID_SYS_IRQ_CTRL 39
+#define CLKID_SYS_MSR_CLK 40
+#define CLKID_SYS_ROM 41
+#define CLKID_SYS_UART_F 42
+#define CLKID_SYS_CPU_ARB 43
+#define CLKID_SYS_RSA 44
+#define CLKID_SYS_SAR_ADC 45
+#define CLKID_SYS_STARTUP 46
+#define CLKID_SYS_SECURE 47
+#define CLKID_SYS_SPIFC 48
+#define CLKID_SYS_NNA 49
+#define CLKID_SYS_ETH_MAC 50
+#define CLKID_SYS_GIC 51
+#define CLKID_SYS_RAMA 52
+#define CLKID_SYS_BIG_NIC 53
+#define CLKID_SYS_RAMB 54
+#define CLKID_SYS_AUDIO_PCLK 55
+#define CLKID_SYS_PWM_KL 56
+#define CLKID_SYS_PWM_IJ 57
+#define CLKID_SYS_USB 58
+#define CLKID_SYS_SD_EMMC_A 59
+#define CLKID_SYS_SD_EMMC_C 60
+#define CLKID_SYS_PWM_AB 61
+#define CLKID_SYS_PWM_CD 62
+#define CLKID_SYS_PWM_EF 63
+#define CLKID_SYS_PWM_GH 64
+#define CLKID_SYS_SPICC_1 65
+#define CLKID_SYS_SPICC_0 66
+#define CLKID_SYS_UART_A 67
+#define CLKID_SYS_UART_B 68
+#define CLKID_SYS_UART_C 69
+#define CLKID_SYS_UART_D 70
+#define CLKID_SYS_UART_E 71
+#define CLKID_SYS_I2C_M_A 72
+#define CLKID_SYS_I2C_M_B 73
+#define CLKID_SYS_I2C_M_C 74
+#define CLKID_SYS_I2C_M_D 75
+#define CLKID_SYS_I2S_S_A 76
+#define CLKID_SYS_RTC 77
+#define CLKID_SYS_GE2D 78
+#define CLKID_SYS_ISP 79
+#define CLKID_SYS_GPV_ISP_NIC 80
+#define CLKID_SYS_GPV_CVE_NIC 81
+#define CLKID_SYS_MIPI_DSI_HOST 82
+#define CLKID_SYS_MIPI_DSI_PHY 83
+#define CLKID_SYS_ETH_PHY 84
+#define CLKID_SYS_ACODEC 85
+#define CLKID_SYS_DWAP 86
+#define CLKID_SYS_DOS 87
+#define CLKID_SYS_CVE 88
+#define CLKID_SYS_VOUT 89
+#define CLKID_SYS_VC9000E 90
+#define CLKID_SYS_PWM_MN 91
+#define CLKID_SYS_SD_EMMC_B 92
+#define CLKID_AXI_SYS_NIC 93
+#define CLKID_AXI_ISP_NIC 94
+#define CLKID_AXI_CVE_NIC 95
+#define CLKID_AXI_RAMB 96
+#define CLKID_AXI_RAMA 97
+#define CLKID_AXI_CPU_DMC 98
+#define CLKID_AXI_NIC 99
+#define CLKID_AXI_DMA 100
+#define CLKID_AXI_MUX_NIC 101
+#define CLKID_AXI_CAPU 102
+#define CLKID_AXI_CVE 103
+#define CLKID_AXI_DEV1_DMC 104
+#define CLKID_AXI_DEV0_DMC 105
+#define CLKID_AXI_DSP_DMC 106
+#define CLKID_12_24M_IN 107
+#define CLKID_12M_24M 108
+#define CLKID_FCLK_25M_DIV 109
+#define CLKID_FCLK_25M 110
+#define CLKID_GEN_SEL 111
+#define CLKID_GEN_DIV 112
+#define CLKID_GEN 113
+#define CLKID_SARADC_SEL 114
+#define CLKID_SARADC_DIV 115
+#define CLKID_SARADC 116
+#define CLKID_PWM_A_SEL 117
+#define CLKID_PWM_A_DIV 118
+#define CLKID_PWM_A 119
+#define CLKID_PWM_B_SEL 120
+#define CLKID_PWM_B_DIV 121
+#define CLKID_PWM_B 122
+#define CLKID_PWM_C_SEL 123
+#define CLKID_PWM_C_DIV 124
+#define CLKID_PWM_C 125
+#define CLKID_PWM_D_SEL 126
+#define CLKID_PWM_D_DIV 127
+#define CLKID_PWM_D 128
+#define CLKID_PWM_E_SEL 129
+#define CLKID_PWM_E_DIV 130
+#define CLKID_PWM_E 131
+#define CLKID_PWM_F_SEL 132
+#define CLKID_PWM_F_DIV 133
+#define CLKID_PWM_F 134
+#define CLKID_PWM_G_SEL 135
+#define CLKID_PWM_G_DIV 136
+#define CLKID_PWM_G 137
+#define CLKID_PWM_H_SEL 138
+#define CLKID_PWM_H_DIV 139
+#define CLKID_PWM_H 140
+#define CLKID_PWM_I_SEL 141
+#define CLKID_PWM_I_DIV 142
+#define CLKID_PWM_I 143
+#define CLKID_PWM_J_SEL 144
+#define CLKID_PWM_J_DIV 145
+#define CLKID_PWM_J 146
+#define CLKID_PWM_K_SEL 147
+#define CLKID_PWM_K_DIV 148
+#define CLKID_PWM_K 149
+#define CLKID_PWM_L_SEL 150
+#define CLKID_PWM_L_DIV 151
+#define CLKID_PWM_L 152
+#define CLKID_PWM_M_SEL 153
+#define CLKID_PWM_M_DIV 154
+#define CLKID_PWM_M 155
+#define CLKID_PWM_N_SEL 156
+#define CLKID_PWM_N_DIV 157
+#define CLKID_PWM_N 158
+#define CLKID_SPICC_A_SEL 159
+#define CLKID_SPICC_A_DIV 160
+#define CLKID_SPICC_A 161
+#define CLKID_SPICC_B_SEL 162
+#define CLKID_SPICC_B_DIV 163
+#define CLKID_SPICC_B 164
+#define CLKID_SPIFC_SEL 165
+#define CLKID_SPIFC_DIV 166
+#define CLKID_SPIFC 167
+#define CLKID_SD_EMMC_A_SEL 168
+#define CLKID_SD_EMMC_A_DIV 169
+#define CLKID_SD_EMMC_A 170
+#define CLKID_SD_EMMC_B_SEL 171
+#define CLKID_SD_EMMC_B_DIV 172
+#define CLKID_SD_EMMC_B 173
+#define CLKID_SD_EMMC_C_SEL 174
+#define CLKID_SD_EMMC_C_DIV 175
+#define CLKID_SD_EMMC_C 176
+#define CLKID_TS_DIV 177
+#define CLKID_TS 178
+#define CLKID_ETH_125M_DIV 179
+#define CLKID_ETH_125M 180
+#define CLKID_ETH_RMII_DIV 181
+#define CLKID_ETH_RMII 182
+#define CLKID_MIPI_DSI_MEAS_SEL 183
+#define CLKID_MIPI_DSI_MEAS_DIV 184
+#define CLKID_MIPI_DSI_MEAS 185
+#define CLKID_DSI_PHY_SEL 186
+#define CLKID_DSI_PHY_DIV 187
+#define CLKID_DSI_PHY 188
+#define CLKID_VOUT_MCLK_SEL 189
+#define CLKID_VOUT_MCLK_DIV 190
+#define CLKID_VOUT_MCLK 191
+#define CLKID_VOUT_ENC_SEL 192
+#define CLKID_VOUT_ENC_DIV 193
+#define CLKID_VOUT_ENC 194
+#define CLKID_HCODEC_0_SEL 195
+#define CLKID_HCODEC_0_DIV 196
+#define CLKID_HCODEC_0 197
+#define CLKID_HCODEC_1_SEL 198
+#define CLKID_HCODEC_1_DIV 199
+#define CLKID_HCODEC_1 200
+#define CLKID_HCODEC 201
+#define CLKID_VC9000E_ACLK_SEL 202
+#define CLKID_VC9000E_ACLK_DIV 203
+#define CLKID_VC9000E_ACLK 204
+#define CLKID_VC9000E_CORE_SEL 205
+#define CLKID_VC9000E_CORE_DIV 206
+#define CLKID_VC9000E_CORE 207
+#define CLKID_CSI_PHY0_SEL 208
+#define CLKID_CSI_PHY0_DIV 209
+#define CLKID_CSI_PHY0 210
+#define CLKID_DEWARPA_SEL 211
+#define CLKID_DEWARPA_DIV 212
+#define CLKID_DEWARPA 213
+#define CLKID_ISP0_SEL 214
+#define CLKID_ISP0_DIV 215
+#define CLKID_ISP0 216
+#define CLKID_NNA_CORE_SEL 217
+#define CLKID_NNA_CORE_DIV 218
+#define CLKID_NNA_CORE 219
+#define CLKID_GE2D_SEL 220
+#define CLKID_GE2D_DIV 221
+#define CLKID_GE2D 222
+#define CLKID_VAPB_SEL 223
+#define CLKID_VAPB_DIV 224
+#define CLKID_VAPB 225
+
+#endif /* _DT_BINDINGS_CLOCK_AMLOGIC_C3_PERIPHERALS_CLKC_H */
--
2.39.2

2023-11-15 08:02:19

by Xianwei Zhao

[permalink] [raw]
Subject: Re: [PATCH V6 3/4] clk: meson: c3: add support for the C3 SoC PLL clock

Hi Jerome,
Thanks for your reply.

On 2023/11/14 18:25, Jerome Brunet wrote:
> [ EXTERNAL EMAIL ]
>
> On Mon 06 Nov 2023 at 16:55, Xianwei Zhao <[email protected]> wrote:
>
>> Add the C3 PLL clock controller driver for the Amlogic C3 SoC family.
>>
>> Co-developed-by: Chuan Liu <[email protected]>
>> Signed-off-by: Chuan Liu <[email protected]>
>> Signed-off-by: Xianwei Zhao <[email protected]>
>
> Just a few things to address
>
>> ---
>> drivers/clk/meson/Kconfig | 13 +
>> drivers/clk/meson/Makefile | 1 +
>> drivers/clk/meson/c3-pll.c | 895 +++++++++++++++++++++++++++++++++++++
>> 3 files changed, 909 insertions(+)
>> create mode 100644 drivers/clk/meson/c3-pll.c
>>
>> diff --git a/drivers/clk/meson/Kconfig b/drivers/clk/meson/Kconfig
>> index c5303e4c1604..eab796f3d25b 100644
>> --- a/drivers/clk/meson/Kconfig
>> +++ b/drivers/clk/meson/Kconfig
>> @@ -128,6 +128,19 @@ config COMMON_CLK_A1_PERIPHERALS
>> device, A1 SoC Family. Say Y if you want A1 Peripherals clock
>> controller to work.
>>
>> +config COMMON_CLK_C3_PLL
>> + tristate "Amlogic C3 PLL clock controller"
>> + depends on ARM64
>> + default y
>> + select COMMON_CLK_MESON_REGMAP
>> + select COMMON_CLK_MESON_PLL
>> + select COMMON_CLK_MESON_CLKC_UTILS
>> + help
>> + Support for the PLL clock controller on Amlogic C302X and C308L devices,
>> + AKA c3. Amlogic C302X and C308L devices include AW402 and the others.
>> + Say Y if you want the board to work, because PLLs are the parent of most
>> + peripherals.
>> +
>> config COMMON_CLK_G12A
>> tristate "G12 and SM1 SoC clock controllers support"
>> depends on ARM64
>> diff --git a/drivers/clk/meson/Makefile b/drivers/clk/meson/Makefile
>> index 9ee4b954c896..4420af628b31 100644
>> --- a/drivers/clk/meson/Makefile
>> +++ b/drivers/clk/meson/Makefile
>> @@ -19,6 +19,7 @@ obj-$(CONFIG_COMMON_CLK_AXG) += axg.o axg-aoclk.o
>> obj-$(CONFIG_COMMON_CLK_AXG_AUDIO) += axg-audio.o
>> obj-$(CONFIG_COMMON_CLK_A1_PLL) += a1-pll.o
>> obj-$(CONFIG_COMMON_CLK_A1_PERIPHERALS) += a1-peripherals.o
>> +obj-$(CONFIG_COMMON_CLK_C3_PLL) += c3-pll.o
>> obj-$(CONFIG_COMMON_CLK_GXBB) += gxbb.o gxbb-aoclk.o
>> obj-$(CONFIG_COMMON_CLK_G12A) += g12a.o g12a-aoclk.o
>> obj-$(CONFIG_COMMON_CLK_MESON8B) += meson8b.o meson8-ddr.o
>> diff --git a/drivers/clk/meson/c3-pll.c b/drivers/clk/meson/c3-pll.c
>> new file mode 100644
>> index 000000000000..b663666e3755
>> --- /dev/null
>> +++ b/drivers/clk/meson/c3-pll.c
>> @@ -0,0 +1,895 @@
>> +// SPDX-License-Identifier: GPL-2.0-only
>> +/*
>> + * Amlogic C3 PLL Controller Driver
>> + *
>> + * Copyright (c) 2023 Amlogic, inc.
>> + * Author: Chuan Liu <[email protected]>
>> + */
>> +
>> +#include <linux/clk-provider.h>
>> +#include <linux/of_device.h>
>> +#include <linux/platform_device.h>
>> +#include <linux/clk.h>
>
> What do you need that for ? you are not the using the clock consumer api.
Indeed not use, will delete it.
>
>> +#include "clk-regmap.h"
>> +#include "clk-pll.h"
>> +#include "meson-clkc-utils.h"
>> +#include <dt-bindings/clock/amlogic,c3-pll-clkc.h>
>> +
>> +#define ANACTRL_FIXPLL_CTRL0 0x40
>> +#define ANACTRL_FIXPLL_CTRL4 0x50
>> +#define ANACTRL_GP0PLL_CTRL0 0x80
>> +#define ANACTRL_GP0PLL_CTRL1 0x84
>> +#define ANACTRL_GP0PLL_CTRL2 0x88
>> +#define ANACTRL_GP0PLL_CTRL3 0x8c
>> +#define ANACTRL_GP0PLL_CTRL4 0x90
>> +#define ANACTRL_GP0PLL_CTRL5 0x94
>> +#define ANACTRL_GP0PLL_CTRL6 0x98
>> +#define ANACTRL_GP0PLL_STS 0x9c
>> +#define ANACTRL_GP1PLL_CTRL0 0xc0
>> +#define ANACTRL_GP1PLL_CTRL1 0xc4
>> +#define ANACTRL_GP1PLL_CTRL2 0xc8
>> +#define ANACTRL_GP1PLL_CTRL3 0xcc
>> +#define ANACTRL_GP1PLL_CTRL4 0xd0
>> +#define ANACTRL_GP1PLL_CTRL5 0xd4
>> +#define ANACTRL_GP1PLL_CTRL6 0xd8
>> +#define ANACTRL_GP1PLL_STS 0xdc
>> +#define ANACTRL_HIFIPLL_CTRL0 0x100
>> +#define ANACTRL_HIFIPLL_CTRL1 0x104
>> +#define ANACTRL_HIFIPLL_CTRL2 0x108
>> +#define ANACTRL_HIFIPLL_CTRL3 0x10c
>> +#define ANACTRL_HIFIPLL_CTRL4 0x110
>> +#define ANACTRL_HIFIPLL_CTRL5 0x114
>> +#define ANACTRL_HIFIPLL_CTRL6 0x118
>> +#define ANACTRL_HIFIPLL_STS 0x11c
>> +#define ANACTRL_MPLL_CTRL0 0x180
>> +#define ANACTRL_MPLL_CTRL1 0x184
>> +#define ANACTRL_MPLL_CTRL2 0x188
>> +#define ANACTRL_MPLL_CTRL3 0x18c
>> +#define ANACTRL_MPLL_CTRL4 0x190
>> +#define ANACTRL_MPLL_STS 0x1a4
>> +
>> +/*
>> + * These clock are a fixed value (fixed_pll is 2GHz) that is initialized by ROMcode.
>
> "This clock has a fixed rate" ?
>
> Just wondering, is it really the ROMcode doing this ?
>
> I'm sure the ROMcode must do some init but from the information
> that has surfaced recently on IRC for the GXBB and GXL, it
> looks like the final fixed PLL init is done by the bl2. Is it different
> on the C3 family ?
Look at Chuan Liu's descriptions.
>> + * The chip was changed fixed pll for security reasons. Fixed PLL registers are not writable
>> + * in the kernel phase. Write of fixed PLL-related register will cause the system to crash.
>> + * Meanwhile, these clock won't ever change at runtime.
>> + * For the above reasons, we can only use ro_ops for fixed PLL related clocks.
>> + */
>> +static struct clk_regmap fixed_pll_dco = {
>> + .data = &(struct meson_clk_pll_data) {
>> + .en = {
>> + .reg_off = ANACTRL_FIXPLL_CTRL0,
>> + .shift = 28,
>> + .width = 1,
>> + },
>> + .m = {
>> + .reg_off = ANACTRL_FIXPLL_CTRL0,
>> + .shift = 0,
>> + .width = 8,
>> + },
>> + .n = {
>> + .reg_off = ANACTRL_FIXPLL_CTRL0,
>> + .shift = 16,
>> + .width = 5,
>> + },
>> + .l = {
>> + .reg_off = ANACTRL_FIXPLL_CTRL0,
>> + .shift = 31,
>> + .width = 1,
>> + },
>> + .rst = {
>> + .reg_off = ANACTRL_FIXPLL_CTRL0,
>> + .shift = 29,
>> + .width = 1,
>> + },
>> + },
>> + .hw.init = &(struct clk_init_data) {
>> + .name = "fixed_pll_dco",
>> + .ops = &meson_clk_pll_ro_ops,
>> + .parent_data = &(const struct clk_parent_data) {
>> + .fw_name = "top",
>> + },
>> + .num_parents = 1,
>> + },
>> +};
>> +
>> +static struct clk_regmap fixed_pll = {
>> + .data = &(struct clk_regmap_div_data) {
>> + .offset = ANACTRL_FIXPLL_CTRL0,
>> + .shift = 12,
>> + .width = 3,
>> + .flags = CLK_DIVIDER_POWER_OF_TWO,
>> + },
>> + .hw.init = &(struct clk_init_data) {
>> + .name = "fixed_pll",
>> + .ops = &clk_regmap_divider_ro_ops,
>> + .parent_hws = (const struct clk_hw *[]) {
>> + &fixed_pll_dco.hw
>> + },
>> + .num_parents = 1,
>> + },
>> +};
>> +
>> +static struct clk_regmap fclk_50m_en = {
>> + .data = &(struct clk_regmap_gate_data) {
>> + .offset = ANACTRL_FIXPLL_CTRL4,
>> + .bit_idx = 0,
>> + },
>> + .hw.init = &(struct clk_init_data) {
>> + .name = "fclk_50m_en",
>> + .ops = &clk_regmap_gate_ro_ops,
>> + .parent_hws = (const struct clk_hw *[]) {
>> + &fixed_pll.hw
>> + },
>> + .num_parents = 1,
>> + },
>> +};
>> +
>> +static struct clk_fixed_factor fclk_50m = {
>> + .mult = 1,
>> + .div = 40,
>> + .hw.init = &(struct clk_init_data) {
>> + .name = "fclk_50m",
>> + .ops = &clk_fixed_factor_ops,
>> + .parent_hws = (const struct clk_hw *[]) {
>> + &fclk_50m_en.hw
>> + },
>> + .num_parents = 1,
>> + },
>> +};
>> +
>> +static struct clk_fixed_factor fclk_div2_div = {
>> + .mult = 1,
>> + .div = 2,
>> + .hw.init = &(struct clk_init_data) {
>> + .name = "fclk_div2_div",
>> + .ops = &clk_fixed_factor_ops,
>> + .parent_hws = (const struct clk_hw *[]) {
>> + &fixed_pll.hw
>> + },
>> + .num_parents = 1,
>> + },
>> +};
>> +
>> +static struct clk_regmap fclk_div2 = {
>> + .data = &(struct clk_regmap_gate_data) {
>> + .offset = ANACTRL_FIXPLL_CTRL4,
>> + .bit_idx = 24,
>> + },
>> + .hw.init = &(struct clk_init_data) {
>> + .name = "fclk_div2",
>> + .ops = &clk_regmap_gate_ro_ops,
>> + .parent_hws = (const struct clk_hw *[]) {
>> + &fclk_div2_div.hw
>> + },
>> + .num_parents = 1,
>> + },
>> +};
>> +
>> +static struct clk_fixed_factor fclk_div2p5_div = {
>> + .mult = 2,
>> + .div = 5,
>> + .hw.init = &(struct clk_init_data) {
>> + .name = "fclk_div2p5_div",
>> + .ops = &clk_fixed_factor_ops,
>> + .parent_hws = (const struct clk_hw *[]) {
>> + &fixed_pll.hw
>> + },
>> + .num_parents = 1,
>> + },
>> +};
>> +
>> +static struct clk_regmap fclk_div2p5 = {
>> + .data = &(struct clk_regmap_gate_data) {
>> + .offset = ANACTRL_FIXPLL_CTRL4,
>> + .bit_idx = 4,
>> + },
>> + .hw.init = &(struct clk_init_data) {
>> + .name = "fclk_div2p5",
>> + .ops = &clk_regmap_gate_ro_ops,
>> + .parent_hws = (const struct clk_hw *[]) {
>> + &fclk_div2p5_div.hw
>> + },
>> + .num_parents = 1,
>> + },
>> +};
>> +
>> +static struct clk_fixed_factor fclk_div3_div = {
>> + .mult = 1,
>> + .div = 3,
>> + .hw.init = &(struct clk_init_data) {
>> + .name = "fclk_div3_div",
>> + .ops = &clk_fixed_factor_ops,
>> + .parent_hws = (const struct clk_hw *[]) {
>> + &fixed_pll.hw
>> + },
>> + .num_parents = 1,
>> + },
>> +};
>> +
>> +static struct clk_regmap fclk_div3 = {
>> + .data = &(struct clk_regmap_gate_data) {
>> + .offset = ANACTRL_FIXPLL_CTRL4,
>> + .bit_idx = 20,
>> + },
>> + .hw.init = &(struct clk_init_data) {
>> + .name = "fclk_div3",
>> + .ops = &clk_regmap_gate_ro_ops,
>> + .parent_hws = (const struct clk_hw *[]) {
>> + &fclk_div3_div.hw
>> + },
>> + .num_parents = 1,
>> + },
>> +};
>> +
>> +static struct clk_fixed_factor fclk_div4_div = {
>> + .mult = 1,
>> + .div = 4,
>> + .hw.init = &(struct clk_init_data) {
>> + .name = "fclk_div4_div",
>> + .ops = &clk_fixed_factor_ops,
>> + .parent_hws = (const struct clk_hw *[]) {
>> + &fixed_pll.hw
>> + },
>> + .num_parents = 1,
>> + },
>> +};
>> +
>> +static struct clk_regmap fclk_div4 = {
>> + .data = &(struct clk_regmap_gate_data) {
>> + .offset = ANACTRL_FIXPLL_CTRL4,
>> + .bit_idx = 21,
>> + },
>> + .hw.init = &(struct clk_init_data) {
>> + .name = "fclk_div4",
>> + .ops = &clk_regmap_gate_ro_ops,
>> + .parent_hws = (const struct clk_hw *[]) {
>> + &fclk_div4_div.hw
>> + },
>> + .num_parents = 1,
>> + },
>> +};
>> +
>> +static struct clk_fixed_factor fclk_div5_div = {
>> + .mult = 1,
>> + .div = 5,
>> + .hw.init = &(struct clk_init_data) {
>> + .name = "fclk_div5_div",
>> + .ops = &clk_fixed_factor_ops,
>> + .parent_hws = (const struct clk_hw *[]) {
>> + &fixed_pll.hw
>> + },
>> + .num_parents = 1,
>> + },
>> +};
>> +
>> +static struct clk_regmap fclk_div5 = {
>> + .data = &(struct clk_regmap_gate_data) {
>> + .offset = ANACTRL_FIXPLL_CTRL4,
>> + .bit_idx = 22,
>> + },
>> + .hw.init = &(struct clk_init_data) {
>> + .name = "fclk_div5",
>> + .ops = &clk_regmap_gate_ro_ops,
>> + .parent_hws = (const struct clk_hw *[]) {
>> + &fclk_div5_div.hw
>> + },
>> + .num_parents = 1,
>> + },
>> +};
>> +
>> +static struct clk_fixed_factor fclk_div7_div = {
>> + .mult = 1,
>> + .div = 7,
>> + .hw.init = &(struct clk_init_data) {
>> + .name = "fclk_div7_div",
>> + .ops = &clk_fixed_factor_ops,
>> + .parent_hws = (const struct clk_hw *[]) {
>> + &fixed_pll.hw
>> + },
>> + .num_parents = 1,
>> + },
>> +};
>> +
>> +static struct clk_regmap fclk_div7 = {
>> + .data = &(struct clk_regmap_gate_data) {
>> + .offset = ANACTRL_FIXPLL_CTRL4,
>> + .bit_idx = 23,
>> + },
>> + .hw.init = &(struct clk_init_data) {
>> + .name = "fclk_div7",
>> + .ops = &clk_regmap_gate_ro_ops,
>> + .parent_hws = (const struct clk_hw *[]) {
>> + &fclk_div7_div.hw
>> + },
>> + .num_parents = 1,
>> + },
>> +};
>> +
>> +static const struct reg_sequence c3_gp0_init_regs[] = {
>> + { .reg = ANACTRL_GP0PLL_CTRL2, .def = 0x0 },
>> + { .reg = ANACTRL_GP0PLL_CTRL3, .def = 0x48681c00 },
>> + { .reg = ANACTRL_GP0PLL_CTRL4, .def = 0x88770290 },
>> + { .reg = ANACTRL_GP0PLL_CTRL5, .def = 0x3927200a },
>> + { .reg = ANACTRL_GP0PLL_CTRL6, .def = 0x56540000 },
>> +};
>> +
>> +static const struct pll_mult_range c3_gp0_pll_mult_range = {
>> + .min = 125,
>> + .max = 250,
>> +};
>> +
>> +static struct clk_regmap gp0_pll_dco = {
>> + .data = &(struct meson_clk_pll_data) {
>> + .en = {
>> + .reg_off = ANACTRL_GP0PLL_CTRL0,
>> + .shift = 28,
>> + .width = 1,
>> + },
>> + .m = {
>> + .reg_off = ANACTRL_GP0PLL_CTRL0,
>> + .shift = 0,
>> + .width = 9,
>> + },
>> + .frac = {
>> + .reg_off = ANACTRL_GP0PLL_CTRL1,
>> + .shift = 0,
>> + .width = 19,
>> + },
>> + .n = {
>> + .reg_off = ANACTRL_GP0PLL_CTRL0,
>> + .shift = 10,
>> + .width = 5,
>> + },
>> + .l = {
>> + .reg_off = ANACTRL_GP0PLL_CTRL0,
>> + .shift = 31,
>> + .width = 1,
>> + },
>> + .rst = {
>> + .reg_off = ANACTRL_GP0PLL_CTRL0,
>> + .shift = 29,
>> + .width = 1,
>> + },
>> + .range = &c3_gp0_pll_mult_range,
>> + .init_regs = c3_gp0_init_regs,
>> + .init_count = ARRAY_SIZE(c3_gp0_init_regs),
>> + },
>> + .hw.init = &(struct clk_init_data) {
>> + .name = "gp0_pll_dco",
>> + .ops = &meson_clk_pll_ops,
>> + .parent_data = &(const struct clk_parent_data) {
>> + .fw_name = "top",
>> + },
>> + .num_parents = 1,
>> + },
>> +};
>> +
>> +/* The maximum frequency divider supports is 32, not 128(2^7) */
>> +static const struct clk_div_table c3_gp0_pll_od_table[] = {
>> + { 0, 1 },
>> + { 1, 2 },
>> + { 2, 4 },
>> + { 3, 8 },
>> + { 4, 16 },
>> + { 5, 32 },
>> + { /* sentinel */ }
>> +};
>> +
>> +static struct clk_regmap gp0_pll = {
>> + .data = &(struct clk_regmap_div_data) {
>> + .offset = ANACTRL_GP0PLL_CTRL0,
>> + .shift = 16,
>> + .width = 3,
>> + .table = c3_gp0_pll_od_table,
>> + },
>> + .hw.init = &(struct clk_init_data) {
>> + .name = "gp0_pll",
>> + .ops = &clk_regmap_divider_ops,
>> + .parent_hws = (const struct clk_hw *[]) {
>> + &gp0_pll_dco.hw
>> + },
>> + .num_parents = 1,
>> + .flags = CLK_SET_RATE_PARENT,
>> + },
>> +};
>> +
>> +/*
>> + * The register corresponding to gp1_pll has permission restrictions,
>> + * The corresponding register is read-only in the kernel.
>> + * For the above reasons, we can only use ro_ops for gp1_pll related clocks.
>> + */
>> +static struct clk_regmap gp1_pll_dco = {
>> + .data = &(struct meson_clk_pll_data) {
>> + .en = {
>> + .reg_off = ANACTRL_GP1PLL_CTRL0,
>> + .shift = 28,
>> + .width = 1,
>> + },
>> + .m = {
>> + .reg_off = ANACTRL_GP1PLL_CTRL0,
>> + .shift = 0,
>> + .width = 9,
>> + },
>> + .frac = {
>> + .reg_off = ANACTRL_GP1PLL_CTRL1,
>> + .shift = 0,
>> + .width = 19,
>> + },
>> + .n = {
>> + .reg_off = ANACTRL_GP1PLL_CTRL0,
>> + .shift = 10,
>> + .width = 5,
>> + },
>> + .l = {
>> + .reg_off = ANACTRL_GP1PLL_CTRL0,
>> + .shift = 31,
>> + .width = 1,
>> + },
>> + .rst = {
>> + .reg_off = ANACTRL_GP1PLL_CTRL0,
>> + .shift = 29,
>> + .width = 1,
>> + },
>> + },
>> + .hw.init = &(struct clk_init_data) {
>> + .name = "gp1_pll_dco",
>> + .ops = &meson_clk_pll_ro_ops,
>> + .parent_data = &(const struct clk_parent_data) {
>> + .fw_name = "top",
>> + },
>> + .num_parents = 1,
>> + .flags = CLK_GET_RATE_NOCACHE,
>> + },
>> +};
>> +
>> +static struct clk_regmap gp1_pll = {
>> + .data = &(struct clk_regmap_div_data) {
>> + .offset = ANACTRL_GP1PLL_CTRL0,
>> + .shift = 16,
>> + .width = 3,
>> + },
>> + .hw.init = &(struct clk_init_data) {
>> + .name = "gp1_pll",
>> + .ops = &clk_regmap_divider_ro_ops,
>> + .parent_hws = (const struct clk_hw *[]) {
>> + &gp1_pll_dco.hw
>> + },
>> + .num_parents = 1,
>> + .flags = CLK_GET_RATE_NOCACHE,
>> + },
>> +};
>> +
>> +static const struct reg_sequence c3_hifi_init_regs[] = {
>> + { .reg = ANACTRL_HIFIPLL_CTRL2, .def = 0x0 },
>> + { .reg = ANACTRL_HIFIPLL_CTRL3, .def = 0x6a285c00 },
>> + { .reg = ANACTRL_HIFIPLL_CTRL4, .def = 0x65771290 },
>> + { .reg = ANACTRL_HIFIPLL_CTRL5, .def = 0x3927200a },
>> + { .reg = ANACTRL_HIFIPLL_CTRL6, .def = 0x56540000 },
>> +};
>> +
>> +static struct clk_regmap hifi_pll_dco = {
>> + .data = &(struct meson_clk_pll_data) {
>> + .en = {
>> + .reg_off = ANACTRL_HIFIPLL_CTRL0,
>> + .shift = 28,
>> + .width = 1,
>> + },
>> + .m = {
>> + .reg_off = ANACTRL_HIFIPLL_CTRL0,
>> + .shift = 0,
>> + .width = 8,
>> + },
>> + .frac = {
>> + .reg_off = ANACTRL_HIFIPLL_CTRL1,
>> + .shift = 0,
>> + .width = 19,
>> + },
>> + .n = {
>> + .reg_off = ANACTRL_HIFIPLL_CTRL0,
>> + .shift = 10,
>> + .width = 5,
>> + },
>> + .l = {
>> + .reg_off = ANACTRL_HIFIPLL_CTRL0,
>> + .shift = 31,
>> + .width = 1,
>> + },
>> + .rst = {
>> + .reg_off = ANACTRL_HIFIPLL_CTRL0,
>> + .shift = 29,
>> + .width = 1,
>> + },
>> + .range = &c3_gp0_pll_mult_range,
>> + .init_regs = c3_hifi_init_regs,
>> + .init_count = ARRAY_SIZE(c3_hifi_init_regs),
>> + },
>> + .hw.init = &(struct clk_init_data) {
>> + .name = "hifi_pll_dco",
>> + .ops = &meson_clk_pll_ops,
>> + .parent_data = &(const struct clk_parent_data) {
>> + .fw_name = "top",
>> + },
>> + .num_parents = 1,
>> + },
>> +};
>> +
>> +static struct clk_regmap hifi_pll = {
>> + .data = &(struct clk_regmap_div_data) {
>> + .offset = ANACTRL_HIFIPLL_CTRL0,
>> + .shift = 16,
>> + .width = 2,
>> + .flags = CLK_DIVIDER_POWER_OF_TWO,
>> + },
>> + .hw.init = &(struct clk_init_data) {
>> + .name = "hifi_pll",
>> + .ops = &clk_regmap_divider_ops,
>> + .parent_hws = (const struct clk_hw *[]) {
>> + &hifi_pll_dco.hw
>> + },
>> + .num_parents = 1,
>> + .flags = CLK_SET_RATE_PARENT,
>> + },
>> +};
>> +
>> +static const struct reg_sequence c3_mclk_init_regs[] = {
>> + { .reg = ANACTRL_MPLL_CTRL1, .def = 0x1420500f },
>> + { .reg = ANACTRL_MPLL_CTRL2, .def = 0x00023041 },
>> + { .reg = ANACTRL_MPLL_CTRL3, .def = 0x18180000 },
>> + { .reg = ANACTRL_MPLL_CTRL2, .def = 0x00023001 }
>> +};
>> +
>> +static const struct pll_mult_range c3_mclk_pll_mult_range = {
>> + .min = 67,
>> + .max = 133,
>> +};
>> +
>> +static struct clk_regmap mclk_pll_dco = {
>> + .data = &(struct meson_clk_pll_data) {
>> + .en = {
>> + .reg_off = ANACTRL_MPLL_CTRL0,
>> + .shift = 28,
>> + .width = 1,
>> + },
>> + .m = {
>> + .reg_off = ANACTRL_MPLL_CTRL0,
>> + .shift = 0,
>> + .width = 8,
>> + },
>> + .n = {
>> + .reg_off = ANACTRL_MPLL_CTRL0,
>> + .shift = 10,
>> + .width = 5,
>> + },
>> + .l = {
>> + .reg_off = ANACTRL_MPLL_CTRL0,
>> + .shift = 31,
>> + .width = 1,
>> + },
>> + .rst = {
>> + .reg_off = ANACTRL_MPLL_CTRL0,
>> + .shift = 29,
>> + .width = 1,
>> + },
>> + .range = &c3_mclk_pll_mult_range,
>> + .init_regs = c3_mclk_init_regs,
>> + .init_count = ARRAY_SIZE(c3_mclk_init_regs),
>> + },
>> + .hw.init = &(struct clk_init_data) {
>> + .name = "mclk_pll_dco",
>> + .ops = &meson_clk_pll_ops,
>> + .parent_data = &(const struct clk_parent_data) {
>> + .fw_name = "mpll",
>> + },
>> + .num_parents = 1,
>> + },
>> +};
>> +
>> +static const struct clk_div_table c3_mpll_od_table[] = {
>> + { 0, 1 },
>> + { 1, 2 },
>> + { 2, 4 },
>> + { 3, 8 },
>> + { 4, 16 },
>> + { /* sentinel */ }
>> +};
>> +
>> +static struct clk_regmap mclk_pll_od = {
>> + .data = &(struct clk_regmap_div_data) {
>> + .offset = ANACTRL_MPLL_CTRL0,
>> + .shift = 12,
>> + .width = 3,
>> + .table = c3_mpll_od_table,
>> + },
>> + .hw.init = &(struct clk_init_data) {
>> + .name = "mclk_pll_od",
>> + .ops = &clk_regmap_divider_ops,
>> + .parent_hws = (const struct clk_hw *[]) {
>> + &mclk_pll_dco.hw },
>> + .num_parents = 1,
>> + .flags = CLK_SET_RATE_PARENT,
>> + },
>> +};
>> +
>> +/* both value 0 and 1 gives divide the input rate by one */
>> +static struct clk_regmap mclk_pll = {
>> + .data = &(struct clk_regmap_div_data) {
>> + .offset = ANACTRL_MPLL_CTRL4,
>> + .shift = 16,
>> + .width = 5,
>> + .flags = CLK_DIVIDER_ONE_BASED | CLK_DIVIDER_ALLOW_ZERO,
>> + },
>> + .hw.init = &(struct clk_init_data) {
>> + .name = "mclk_pll",
>> + .ops = &clk_regmap_divider_ops,
>> + .parent_hws = (const struct clk_hw *[]) {
>> + &mclk_pll_od.hw
>> + },
>> + .num_parents = 1,
>> + .flags = CLK_SET_RATE_PARENT,
>> + },
>> +};
>> +
>> +static const struct clk_parent_data mclk_parent[] = {
>> + { .hw = &mclk_pll.hw },
>> + { .fw_name = "mpll" },
>> + { .hw = &fclk_50m.hw }
>> +};
>> +
>> +static struct clk_regmap mclk0_sel = {
>> + .data = &(struct clk_regmap_mux_data) {
>> + .offset = ANACTRL_MPLL_CTRL4,
>> + .mask = 0x3,
>> + .shift = 4,
>> + },
>> + .hw.init = &(struct clk_init_data) {
>> + .name = "mclk0_sel",
>> + .ops = &clk_regmap_mux_ops,
>> + .parent_data = mclk_parent,
>> + .num_parents = ARRAY_SIZE(mclk_parent),
>> + },
>> +};
>> +
>> +static struct clk_regmap mclk0_div_en = {
>> + .data = &(struct clk_regmap_gate_data) {
>> + .offset = ANACTRL_MPLL_CTRL4,
>> + .bit_idx = 1,
>> + },
>> + .hw.init = &(struct clk_init_data) {
>> + .name = "mclk0_div_en",
>> + .ops = &clk_regmap_gate_ops,
>> + .parent_hws = (const struct clk_hw *[]) {
>> + &mclk0_sel.hw
>> + },
>> + .num_parents = 1,
>> + .flags = CLK_SET_RATE_PARENT,
>> + },
>> +};
>> +
>> +static struct clk_regmap mclk0_div = {
>> + .data = &(struct clk_regmap_div_data) {
>> + .offset = ANACTRL_MPLL_CTRL4,
>> + .shift = 2,
>> + .width = 1,
>> + },
>> + .hw.init = &(struct clk_init_data) {
>> + .name = "mclk0_div",
>> + .ops = &clk_regmap_divider_ops,
>> + .parent_hws = (const struct clk_hw *[]) {
>> + &mclk0_div_en.hw
>> + },
>> + .num_parents = 1,
>> + .flags = CLK_SET_RATE_PARENT,
>> + },
>> +};
>> +
>> +static struct clk_regmap mclk0 = {
>> + .data = &(struct clk_regmap_gate_data) {
>> + .offset = ANACTRL_MPLL_CTRL4,
>> + .bit_idx = 0,
>> + },
>> + .hw.init = &(struct clk_init_data) {
>> + .name = "mclk0",
>> + .ops = &clk_regmap_gate_ops,
>> + .parent_hws = (const struct clk_hw *[]) {
>> + &mclk0_div.hw
>> + },
>> + .num_parents = 1,
>> + .flags = CLK_SET_RATE_PARENT,
>> + },
>> +};
>> +
>> +static struct clk_regmap mclk1_sel = {
>> + .data = &(struct clk_regmap_mux_data) {
>> + .offset = ANACTRL_MPLL_CTRL4,
>> + .mask = 0x3,
>> + .shift = 12,
>> + },
>> + .hw.init = &(struct clk_init_data) {
>> + .name = "mclk1_sel",
>> + .ops = &clk_regmap_mux_ops,
>> + .parent_data = mclk_parent,
>> + .num_parents = ARRAY_SIZE(mclk_parent),
>> + },
>> +};
>> +
>> +static struct clk_regmap mclk1_div_en = {
>> + .data = &(struct clk_regmap_gate_data) {
>> + .offset = ANACTRL_MPLL_CTRL4,
>> + .bit_idx = 9,
>> + },
>> + .hw.init = &(struct clk_init_data) {
>> + .name = "mclk1_div_en",
>> + .ops = &clk_regmap_gate_ops,
>> + .parent_hws = (const struct clk_hw *[]) {
>> + &mclk1_sel.hw
>> + },
>> + .num_parents = 1,
>> + .flags = CLK_SET_RATE_PARENT,
>> + },
>> +};
>> +
>> +static struct clk_regmap mclk1_div = {
>> + .data = &(struct clk_regmap_div_data) {
>> + .offset = ANACTRL_MPLL_CTRL4,
>> + .shift = 10,
>> + .width = 1,
>> + },
>> + .hw.init = &(struct clk_init_data) {
>> + .name = "mclk1_div",
>> + .ops = &clk_regmap_divider_ops,
>> + .parent_hws = (const struct clk_hw *[]) {
>> + &mclk1_div_en.hw
>> + },
>> + .num_parents = 1,
>> + .flags = CLK_SET_RATE_PARENT,
>> + },
>> +};
>> +
>> +static struct clk_regmap mclk1 = {
>> + .data = &(struct clk_regmap_gate_data) {
>> + .offset = ANACTRL_MPLL_CTRL4,
>> + .bit_idx = 8,
>> + },
>> + .hw.init = &(struct clk_init_data) {
>> + .name = "mclk1",
>> + .ops = &clk_regmap_gate_ops,
>> + .parent_hws = (const struct clk_hw *[]) {
>> + &mclk1_div.hw
>> + },
>> + .num_parents = 1,
>> + .flags = CLK_SET_RATE_PARENT,
>> + },
>> +};
>> +
>> +static struct clk_hw *c3_pll_hw_clks[] = {
>> + [CLKID_FIXED_PLL_DCO] = &fixed_pll_dco.hw,
>> + [CLKID_FIXED_PLL] = &fixed_pll.hw,
>> + [CLKID_FCLK_50M_EN] = &fclk_50m_en.hw,
>> + [CLKID_FCLK_50M] = &fclk_50m.hw,
>> + [CLKID_FCLK_DIV2_DIV] = &fclk_div2_div.hw,
>> + [CLKID_FCLK_DIV2] = &fclk_div2.hw,
>> + [CLKID_FCLK_DIV2P5_DIV] = &fclk_div2p5_div.hw,
>> + [CLKID_FCLK_DIV2P5] = &fclk_div2p5.hw,
>> + [CLKID_FCLK_DIV3_DIV] = &fclk_div3_div.hw,
>> + [CLKID_FCLK_DIV3] = &fclk_div3.hw,
>> + [CLKID_FCLK_DIV4_DIV] = &fclk_div4_div.hw,
>> + [CLKID_FCLK_DIV4] = &fclk_div4.hw,
>> + [CLKID_FCLK_DIV5_DIV] = &fclk_div5_div.hw,
>> + [CLKID_FCLK_DIV5] = &fclk_div5.hw,
>> + [CLKID_FCLK_DIV7_DIV] = &fclk_div7_div.hw,
>> + [CLKID_FCLK_DIV7] = &fclk_div7.hw,
>> + [CLKID_GP0_PLL_DCO] = &gp0_pll_dco.hw,
>> + [CLKID_GP0_PLL] = &gp0_pll.hw,
>> + [CLKID_GP1_PLL_DCO] = &gp1_pll_dco.hw,
>> + [CLKID_GP1_PLL] = &gp1_pll.hw,
>> + [CLKID_HIFI_PLL_DCO] = &hifi_pll_dco.hw,
>> + [CLKID_HIFI_PLL] = &hifi_pll.hw,
>> + [CLKID_MCLK_PLL_DCO] = &mclk_pll_dco.hw,
>> + [CLKID_MCLK_PLL_OD] = &mclk_pll_od.hw,
>> + [CLKID_MCLK_PLL] = &mclk_pll.hw,
>> + [CLKID_MCLK0_SEL] = &mclk0_sel.hw,
>> + [CLKID_MCLK0_SEL_EN] = &mclk0_div_en.hw,
>> + [CLKID_MCLK0_DIV] = &mclk0_div.hw,
>> + [CLKID_MCLK0] = &mclk0.hw,
>> + [CLKID_MCLK1_SEL] = &mclk1_sel.hw,
>> + [CLKID_MCLK1_SEL_EN] = &mclk1_div_en.hw,
>> + [CLKID_MCLK1_DIV] = &mclk1_div.hw,
>> + [CLKID_MCLK1] = &mclk1.hw
>> +};
>> +
>> +/* Convenience table to populate regmap in .probe */
>> +static struct clk_regmap *const c3_pll_clk_regmaps[] = {
>> + &fixed_pll_dco,
>> + &fixed_pll,
>> + &fclk_50m_en,
>> + &fclk_div2,
>> + &fclk_div2p5,
>> + &fclk_div3,
>> + &fclk_div4,
>> + &fclk_div5,
>> + &fclk_div7,
>> + &gp0_pll_dco,
>> + &gp0_pll,
>> + &gp1_pll_dco,
>> + &gp1_pll,
>> + &hifi_pll_dco,
>> + &hifi_pll,
>> + &mclk_pll_dco,
>> + &mclk_pll_od,
>> + &mclk_pll,
>> + &mclk0_sel,
>> + &mclk0_div_en,
>> + &mclk0_div,
>> + &mclk0,
>> + &mclk1_sel,
>> + &mclk1_div_en,
>> + &mclk1_div,
>> + &mclk1,
>> +};
>> +
>> +static struct regmap_config clkc_regmap_config = {
>> + .reg_bits = 32,
>> + .val_bits = 32,
>> + .reg_stride = 4,
>> +};
>> +
>> +static struct meson_clk_hw_data c3_pll_clks = {
>> + .hws = c3_pll_hw_clks,
>> + .num = ARRAY_SIZE(c3_pll_hw_clks),
>> +};
>> +
>> +static int aml_c3_pll_probe(struct platform_device *pdev)
>> +{
>> + struct device *dev = &pdev->dev;
>> + struct regmap *regmap;
>> + void __iomem *base;
>> + int clkid, ret, i;
>> +
>> + base = devm_platform_ioremap_resource(pdev, 0);
>> + if (IS_ERR(base))
>> + return PTR_ERR(base);
>> +
>> + regmap = devm_regmap_init_mmio(dev, base, &clkc_regmap_config);
>> + if (IS_ERR(regmap))
>> + return PTR_ERR(regmap);
>> +
>> + /* Populate regmap for the regmap backed clocks */
>> + for (i = 0; i < ARRAY_SIZE(c3_pll_clk_regmaps); i++)
>> + c3_pll_clk_regmaps[i]->map = regmap;
>> +
>> + for (clkid = 0; clkid < c3_pll_clks.num; clkid++) {
>> + /* array might be sparse */
>> + if (!c3_pll_clks.hws[clkid])
>> + continue;
>> +
>> + ret = devm_clk_hw_register(dev, c3_pll_clks.hws[clkid]);
>> + if (ret) {
>> + dev_err(dev, "Clock registration failed\n");
>> + return ret;
>> + }
>> + }
>> +
>> + return devm_of_clk_add_hw_provider(dev, meson_clk_hw_get,
>> + &c3_pll_clks);
>> +}
>> +
>> +static const struct of_device_id c3_pll_clkc_match_table[] = {
>> + {
>> + .compatible = "amlogic,c3-pll-clkc",
>> + },
>> + {}
>> +};
>> +MODULE_DEVICE_TABLE(of, c3_pll_clkc_match_table);
>> +
>> +static struct platform_driver c3_pll_driver = {
>> + .probe = aml_c3_pll_probe,
>> + .driver = {
>> + .name = "c3-pll-clkc",
>> + .of_match_table = c3_pll_clkc_match_table,
>> + },
>> +};
>> +
>> +module_platform_driver(c3_pll_driver);
>> +MODULE_AUTHOR("Chuan Liu <[email protected]>");
>> +MODULE_LICENSE("GPL");
>