Add C3 SoC PLLs and Peripheral clock controller dt-bindings.
Add PLLs and Peripheral clock controller driver for C3 SOC.
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 | 86 ++
.../bindings/clock/amlogic,c3-pll-clkc.yaml | 53 +
drivers/clk/meson/Kconfig | 25 +
drivers/clk/meson/Makefile | 2 +
drivers/clk/meson/c3-peripherals.c | 1372 +++++++++++++++++
drivers/clk/meson/c3-peripherals.h | 48 +
drivers/clk/meson/c3-pll.c | 510 ++++++
drivers/clk/meson/c3-pll.h | 35 +
.../clock/amlogic,c3-peripherals-clkc.h | 230 +++
.../dt-bindings/clock/amlogic,c3-pll-clkc.h | 42 +
10 files changed, 2403 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-peripherals.h
create mode 100644 drivers/clk/meson/c3-pll.c
create mode 100644 drivers/clk/meson/c3-pll.h
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.37.1
Add the peripherals clock controller dt-bindings for Amlogic C3 SoC family
Signed-off-by: Xianwei Zhao <[email protected]>
---
.../clock/amlogic,c3-peripherals-clkc.yaml | 86 +++++++
.../clock/amlogic,c3-peripherals-clkc.h | 230 ++++++++++++++++++
2 files changed, 316 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..ec4673714fa0
--- /dev/null
+++ b/Documentation/devicetree/bindings/clock/amlogic,c3-peripherals-clkc.yaml
@@ -0,0 +1,86 @@
+# 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 C serials Peripherals Clock Controller
+
+maintainers:
+ - Chuan Liu <[email protected]>
+
+properties:
+ compatible:
+ const: amlogic,c3-peripherals-clkc
+
+ reg:
+ maxItems: 1
+
+ clocks:
+ minItems: 10
+ items:
+ - description: input oscillator (usually at 24MHz)
+ - description: input fixed pll
+ - description: input fixed pll div2
+ - description: input fixed pll div2p5
+ - description: input fixed pll div3
+ - description: input fixed pll div4
+ - description: input fixed pll div5
+ - description: input fixed pll div7
+ - description: input gp0 pll
+ - description: input hifi pll
+
+ clock-names:
+ minItems: 10
+ items:
+ - const: xtal
+ - const: fixed_pll
+ - const: fclk_div2
+ - const: fclk_div2p5
+ - const: fclk_div3
+ - const: fclk_div4
+ - const: fclk_div5
+ - const: fclk_div7
+ - const: gp0_pll
+ - const: hifi_pll
+
+ "#clock-cells":
+ const: 1
+
+required:
+ - compatible
+ - reg
+ - clocks
+ - clock-names
+ - "#clock-cells"
+
+additionalProperties: false
+
+examples:
+ - |
+ clkc_periphs: clock-controller {
+ compatible = "amlogic,c3-peripherals-clkc";
+ #clock-cells = <1>;
+ reg = <0x0 0x0 0x0 0x49c>;
+ clocks = <&xtal>,
+ <&clkc_pll CLKID_FIXED_PLL>,
+ <&clkc_pll CLKID_FCLK_DIV2>,
+ <&clkc_pll CLKID_FCLK_DIV2P5>,
+ <&clkc_pll CLKID_FCLK_DIV3>,
+ <&clkc_pll CLKID_FCLK_DIV4>,
+ <&clkc_pll CLKID_FCLK_DIV5>,
+ <&clkc_pll CLKID_FCLK_DIV7>,
+ <&clkc_pll CLKID_GP0_PLL>,
+ <&clkc_pll CLKID_HIFI_PLL>;
+ clock-names = "xtal",
+ "fixed_pll",
+ "fclk_div2",
+ "fclk_div2p5",
+ "fclk_div3",
+ "fclk_div4",
+ "fclk_div5",
+ "fclk_div7",
+ "gp0_pll",
+ "hifi_pll";
+ };
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..82f9bf683ea0
--- /dev/null
+++ b/include/dt-bindings/clock/amlogic,c3-peripherals-clkc.h
@@ -0,0 +1,230 @@
+/* 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_IN 0
+#define CLKID_MCLK_PLL_IN 1
+#define CLKID_RTC_XTAL_CLKIN 2
+#define CLKID_RTC_32K_DIV 3
+#define CLKID_RTC_32K_MUX 4
+#define CLKID_RTC_32K 5
+#define CLKID_RTC_CLK 6
+#define CLKID_SYS_A_SEL 7
+#define CLKID_SYS_A_DIV 8
+#define CLKID_SYS_A 9
+#define CLKID_SYS_B_SEL 10
+#define CLKID_SYS_B_DIV 11
+#define CLKID_SYS_B 12
+#define CLKID_SYS_CLK 13
+#define CLKID_AXI_A_SEL 14
+#define CLKID_AXI_A_DIV 15
+#define CLKID_AXI_A 16
+#define CLKID_AXI_B_SEL 17
+#define CLKID_AXI_B_DIV 18
+#define CLKID_AXI_B 19
+#define CLKID_AXI_CLK 20
+#define CLKID_SYS_RESET_CTRL 21
+#define CLKID_SYS_PWR_CTRL 22
+#define CLKID_SYS_PAD_CTRL 23
+#define CLKID_SYS_CTRL 24
+#define CLKID_SYS_TS_PLL 25
+#define CLKID_SYS_DEV_ARB 26
+#define CLKID_SYS_MMC_PCLK 27
+#define CLKID_SYS_CAPU 28
+#define CLKID_SYS_CPU_CTRL 29
+#define CLKID_SYS_JTAG_CTRL 30
+#define CLKID_SYS_IR_CTRL 31
+#define CLKID_SYS_IRQ_CTRL 32
+#define CLKID_SYS_MSR_CLK 33
+#define CLKID_SYS_ROM 34
+#define CLKID_SYS_UART_F 35
+#define CLKID_SYS_CPU_ARB 36
+#define CLKID_SYS_RSA 37
+#define CLKID_SYS_SAR_ADC 38
+#define CLKID_SYS_STARTUP 39
+#define CLKID_SYS_SECURE 40
+#define CLKID_SYS_SPIFC 41
+#define CLKID_SYS_NNA 42
+#define CLKID_SYS_ETH_MAC 43
+#define CLKID_SYS_GIC 44
+#define CLKID_SYS_RAMA 45
+#define CLKID_SYS_BIG_NIC 46
+#define CLKID_SYS_RAMB 47
+#define CLKID_SYS_AUDIO_PCLK 48
+#define CLKID_SYS_PWM_KL 49
+#define CLKID_SYS_PWM_IJ 50
+#define CLKID_SYS_USB 51
+#define CLKID_SYS_SD_EMMC_A 52
+#define CLKID_SYS_SD_EMMC_C 53
+#define CLKID_SYS_PWM_AB 54
+#define CLKID_SYS_PWM_CD 55
+#define CLKID_SYS_PWM_EF 56
+#define CLKID_SYS_PWM_GH 57
+#define CLKID_SYS_SPICC_1 58
+#define CLKID_SYS_SPICC_0 59
+#define CLKID_SYS_UART_A 60
+#define CLKID_SYS_UART_B 61
+#define CLKID_SYS_UART_C 62
+#define CLKID_SYS_UART_D 63
+#define CLKID_SYS_UART_E 64
+#define CLKID_SYS_I2C_M_A 65
+#define CLKID_SYS_I2C_M_B 66
+#define CLKID_SYS_I2C_M_C 67
+#define CLKID_SYS_I2C_M_D 68
+#define CLKID_SYS_I2S_S_A 69
+#define CLKID_SYS_RTC 70
+#define CLKID_SYS_GE2D 71
+#define CLKID_SYS_ISP 72
+#define CLKID_SYS_GPV_ISP_NIC 73
+#define CLKID_SYS_GPV_CVE_NIC 74
+#define CLKID_SYS_MIPI_DSI_HOST 75
+#define CLKID_SYS_MIPI_DSI_PHY 76
+#define CLKID_SYS_ETH_PHY 77
+#define CLKID_SYS_ACODEC 78
+#define CLKID_SYS_DWAP 79
+#define CLKID_SYS_DOS 80
+#define CLKID_SYS_CVE 81
+#define CLKID_SYS_VOUT 82
+#define CLKID_SYS_VC9000E 83
+#define CLKID_SYS_PWM_MN 84
+#define CLKID_SYS_SD_EMMC_B 85
+#define CLKID_AXI_SYS_NIC 86
+#define CLKID_AXI_ISP_NIC 87
+#define CLKID_AXI_CVE_NIC 88
+#define CLKID_AXI_RAMB 89
+#define CLKID_AXI_RAMA 90
+#define CLKID_AXI_CPU_DMC 91
+#define CLKID_AXI_NIC 92
+#define CLKID_AXI_DMA 93
+#define CLKID_AXI_MUX_NIC 94
+#define CLKID_AXI_CAPU 95
+#define CLKID_AXI_CVE 96
+#define CLKID_AXI_DEV1_DMC 97
+#define CLKID_AXI_DEV0_DMC 98
+#define CLKID_AXI_DSP_DMC 99
+#define CLKID_12_24M_IN 100
+#define CLKID_12M_24M 101
+#define CLKID_FCLK_25M_DIV 102
+#define CLKID_FCLK_25M 103
+#define CLKID_GEN_SEL 104
+#define CLKID_GEN_DIV 105
+#define CLKID_GEN 106
+#define CLKID_SARADC_SEL 107
+#define CLKID_SARADC_DIV 108
+#define CLKID_SARADC 109
+#define CLKID_PWM_A_SEL 110
+#define CLKID_PWM_A_DIV 111
+#define CLKID_PWM_A 112
+#define CLKID_PWM_B_SEL 113
+#define CLKID_PWM_B_DIV 114
+#define CLKID_PWM_B 115
+#define CLKID_PWM_C_SEL 116
+#define CLKID_PWM_C_DIV 117
+#define CLKID_PWM_C 118
+#define CLKID_PWM_D_SEL 119
+#define CLKID_PWM_D_DIV 120
+#define CLKID_PWM_D 121
+#define CLKID_PWM_E_SEL 122
+#define CLKID_PWM_E_DIV 123
+#define CLKID_PWM_E 124
+#define CLKID_PWM_F_SEL 125
+#define CLKID_PWM_F_DIV 126
+#define CLKID_PWM_F 127
+#define CLKID_PWM_G_SEL 128
+#define CLKID_PWM_G_DIV 129
+#define CLKID_PWM_G 130
+#define CLKID_PWM_H_SEL 131
+#define CLKID_PWM_H_DIV 132
+#define CLKID_PWM_H 133
+#define CLKID_PWM_I_SEL 134
+#define CLKID_PWM_I_DIV 135
+#define CLKID_PWM_I 136
+#define CLKID_PWM_J_SEL 137
+#define CLKID_PWM_J_DIV 138
+#define CLKID_PWM_J 139
+#define CLKID_PWM_K_SEL 140
+#define CLKID_PWM_K_DIV 141
+#define CLKID_PWM_K 142
+#define CLKID_PWM_L_SEL 143
+#define CLKID_PWM_L_DIV 144
+#define CLKID_PWM_L 145
+#define CLKID_PWM_M_SEL 146
+#define CLKID_PWM_M_DIV 147
+#define CLKID_PWM_M 148
+#define CLKID_PWM_N_SEL 149
+#define CLKID_PWM_N_DIV 150
+#define CLKID_PWM_N 151
+#define CLKID_SPICC_A_SEL 152
+#define CLKID_SPICC_A_DIV 153
+#define CLKID_SPICC_A 154
+#define CLKID_SPICC_B_SEL 155
+#define CLKID_SPICC_B_DIV 156
+#define CLKID_SPICC_B 157
+#define CLKID_SPIFC_SEL 158
+#define CLKID_SPIFC_DIV 159
+#define CLKID_SPIFC 160
+#define CLKID_SD_EMMC_A_SEL 161
+#define CLKID_SD_EMMC_A_DIV 162
+#define CLKID_SD_EMMC_A 163
+#define CLKID_SD_EMMC_B_SEL 164
+#define CLKID_SD_EMMC_B_DIV 165
+#define CLKID_SD_EMMC_B 166
+#define CLKID_SD_EMMC_C_SEL 167
+#define CLKID_SD_EMMC_C_DIV 168
+#define CLKID_SD_EMMC_C 169
+#define CLKID_TS_DIV 170
+#define CLKID_TS 171
+#define CLKID_ETH_125M_DIV 172
+#define CLKID_ETH_125M 173
+#define CLKID_ETH_RMII_DIV 174
+#define CLKID_ETH_RMII 175
+#define CLKID_MIPI_DSI_MEAS_SEL 176
+#define CLKID_MIPI_DSI_MEAS_DIV 177
+#define CLKID_MIPI_DSI_MEAS 178
+#define CLKID_DSI_PHY_SEL 179
+#define CLKID_DSI_PHY_DIV 180
+#define CLKID_DSI_PHY 181
+#define CLKID_VOUT_MCLK_SEL 182
+#define CLKID_VOUT_MCLK_DIV 183
+#define CLKID_VOUT_MCLK 184
+#define CLKID_VOUT_ENC_SEL 185
+#define CLKID_VOUT_ENC_DIV 186
+#define CLKID_VOUT_ENC 187
+#define CLKID_HCODEC_0_SEL 188
+#define CLKID_HCODEC_0_DIV 189
+#define CLKID_HCODEC_0 190
+#define CLKID_HCODEC_1_SEL 191
+#define CLKID_HCODEC_1_DIV 192
+#define CLKID_HCODEC_1 193
+#define CLKID_HCODEC 194
+#define CLKID_VC9000E_ACLK_SEL 195
+#define CLKID_VC9000E_ACLK_DIV 196
+#define CLKID_VC9000E_ACLK 197
+#define CLKID_VC9000E_CORE_SEL 198
+#define CLKID_VC9000E_CORE_DIV 199
+#define CLKID_VC9000E_CORE 200
+#define CLKID_CSI_PHY0_SEL 201
+#define CLKID_CSI_PHY0_DIV 202
+#define CLKID_CSI_PHY0 203
+#define CLKID_DEWARPA_SEL 204
+#define CLKID_DEWARPA_DIV 205
+#define CLKID_DEWARPA 206
+#define CLKID_ISP0_SEL 207
+#define CLKID_ISP0_DIV 208
+#define CLKID_ISP0 209
+#define CLKID_NNA_CORE_SEL 210
+#define CLKID_NNA_CORE_DIV 211
+#define CLKID_NNA_CORE 212
+#define CLKID_GE2D_SEL 213
+#define CLKID_GE2D_DIV 214
+#define CLKID_GE2D 215
+#define CLKID_VAPB_SEL 216
+#define CLKID_VAPB_DIV 217
+#define CLKID_VAPB 218
+
+#endif /* _DT_BINDINGS_CLOCK_AMLOGIC_C3_PERIPHERALS_CLKC_H */
--
2.37.1
Add the C3 PLL clock controller driver for the Amlogic C3 SoC family.
Signed-off-by: Xianwei Zhao <[email protected]>
---
drivers/clk/meson/Kconfig | 12 +
drivers/clk/meson/Makefile | 1 +
drivers/clk/meson/c3-pll.c | 510 +++++++++++++++++++++++++++++++++++++
drivers/clk/meson/c3-pll.h | 35 +++
4 files changed, 558 insertions(+)
create mode 100644 drivers/clk/meson/c3-pll.c
create mode 100644 drivers/clk/meson/c3-pll.h
diff --git a/drivers/clk/meson/Kconfig b/drivers/clk/meson/Kconfig
index c5303e4c1604..76be4bbd2afb 100644
--- a/drivers/clk/meson/Kconfig
+++ b/drivers/clk/meson/Kconfig
@@ -128,6 +128,18 @@ 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"
+ 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, AW409 and AW419.
+ 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..5244dc19ab6e
--- /dev/null
+++ b/drivers/clk/meson/c3-pll.c
@@ -0,0 +1,510 @@
+// 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 "c3-pll.h"
+#include "meson-clkc-utils.h"
+#include <dt-bindings/clock/amlogic,c3-pll-clkc.h>
+
+#define MEMBER_REG_PARM(_member_name, _reg, _shift, _width) \
+ ._member_name = { \
+ .reg_off = _reg, \
+ .shift = _shift, \
+ .width = _width, \
+}
+
+#define __AML_CLK_PLL(_name, _en_reg, _en_shift, _en_width, \
+ _m_reg, _m_shift, _m_width, \
+ _f_reg, _f_shift, _f_width, \
+ _n_reg, _n_shift, _n_width, \
+ _l_reg, _l_shift, _l_width, \
+ _r_reg, _r_shift, _r_width, \
+ _init_reg, _init_reg_cnt, _range, _table, \
+ _dflags, _ops, _pname, _pdata, _phw, _iflags) \
+static struct clk_regmap _name = { \
+ .data = &(struct meson_clk_pll_data){ \
+ MEMBER_REG_PARM(en, \
+ _en_reg, _en_shift, _en_width), \
+ MEMBER_REG_PARM(m, \
+ _m_reg, _m_shift, _m_width), \
+ MEMBER_REG_PARM(frac, \
+ _f_reg, _f_shift, _f_width), \
+ MEMBER_REG_PARM(n, \
+ _n_reg, _n_shift, _n_width), \
+ MEMBER_REG_PARM(l, \
+ _l_reg, _l_shift, _l_width), \
+ MEMBER_REG_PARM(rst, \
+ _r_reg, _r_shift, _r_width), \
+ .range = _range, \
+ .table = _table, \
+ .init_regs = _init_reg, \
+ .init_count = _init_reg_cnt, \
+ .flags = _dflags, \
+ }, \
+ .hw.init = &(struct clk_init_data){ \
+ .name = #_name, \
+ .ops = _ops, \
+ .parent_names = _pname, \
+ .parent_data = _pdata, \
+ .parent_hws = (const struct clk_hw *[]) {_phw}, \
+ .num_parents = 1, \
+ .flags = _iflags, \
+ }, \
+}
+
+#define __AML_CLK_MUX(_name, _reg, _mask, _shift, _table, _dflags, \
+ _ops, _pname, _pdata, _phw, _pnub, _iflags) \
+static struct clk_regmap _name = { \
+ .data = &(struct clk_regmap_mux_data){ \
+ .offset = _reg, \
+ .mask = _mask, \
+ .shift = _shift, \
+ .table = _table, \
+ .flags = _dflags, \
+ }, \
+ .hw.init = &(struct clk_init_data){ \
+ .name = #_name, \
+ .ops = _ops, \
+ .parent_names = _pname, \
+ .parent_data = _pdata, \
+ .parent_hws = (const struct clk_hw *[]) { _phw }, \
+ .num_parents = _pnub, \
+ .flags = _iflags, \
+ }, \
+}
+
+#define __AML_CLK_DIV(_name, _reg, _shift, _width, _table, _dflags, \
+ _ops, _pname, _pdata, _phw, _iflags) \
+static struct clk_regmap _name = { \
+ .data = &(struct clk_regmap_div_data){ \
+ .offset = _reg, \
+ .shift = _shift, \
+ .width = _width, \
+ .table = _table, \
+ .flags = _dflags, \
+ }, \
+ .hw.init = &(struct clk_init_data){ \
+ .name = #_name, \
+ .ops = _ops, \
+ .parent_names = _pname, \
+ .parent_data = _pdata, \
+ .parent_hws = (const struct clk_hw *[]) { _phw }, \
+ .num_parents = 1, \
+ .flags = _iflags, \
+ }, \
+}
+
+#define __AML_CLK_GATE(_name, _reg, _bit, _gflags, \
+ _ops, _pname, _pdata, _phw, _iflags) \
+static struct clk_regmap _name = { \
+ .data = &(struct clk_regmap_gate_data){ \
+ .offset = _reg, \
+ .bit_idx = _bit, \
+ .flags = _gflags, \
+ }, \
+ .hw.init = &(struct clk_init_data) { \
+ .name = #_name, \
+ .ops = _ops, \
+ .parent_names = _pname, \
+ .parent_data = _pdata, \
+ .parent_hws = (const struct clk_hw *[]) { _phw }, \
+ .num_parents = 1, \
+ .flags = _iflags, \
+ }, \
+}
+
+#define __AML_CLK_FIXED_FACTOR(_name, _mult, _div, _ops, \
+ _pname, _pdata, _phw, _iflags) \
+ static struct clk_fixed_factor _name = { \
+ .mult = _mult, \
+ .div = _div, \
+ .hw.init = &(struct clk_init_data){ \
+ .name = #_name, \
+ .ops = _ops, \
+ .parent_names = _pname, \
+ .parent_data = _pdata, \
+ .parent_hws = (const struct clk_hw *[]) { _phw }, \
+ .num_parents = 1, \
+ .flags = _iflags, \
+ }, \
+}
+
+#define AML_CLK_PLL_RW(_name, _en_reg, _en_shift, _en_width, \
+ _m_reg, _m_shift, _m_width, \
+ _f_reg, _f_shift, _f_width, \
+ _n_reg, _n_shift, _n_width, \
+ _l_reg, _l_shift, _l_width, \
+ _r_reg, _r_shift, _r_width, \
+ _init_reg, _init_reg_cnt, _range, _table, _dflags,\
+ _pdata, _iflags) \
+ __AML_CLK_PLL(_name, _en_reg, _en_shift, _en_width, \
+ _m_reg, _m_shift, _m_width, \
+ _f_reg, _f_shift, _f_width, \
+ _n_reg, _n_shift, _n_width, \
+ _l_reg, _l_shift, _l_width, \
+ _r_reg, _r_shift, _r_width, \
+ _init_reg, _init_reg_cnt, _range, _table, \
+ _dflags, &meson_clk_pll_ops, \
+ NULL, _pdata, NULL, _iflags)
+
+#define AML_CLK_PLL_RO(_name, _en_reg, _en_shift, _en_width, \
+ _m_reg, _m_shift, _m_width, \
+ _f_reg, _f_shift, _f_width, \
+ _n_reg, _n_shift, _n_width, \
+ _l_reg, _l_shift, _l_width, \
+ _r_reg, _r_shift, _r_width, \
+ _init_reg, _init_reg_cnt, _range, _table, \
+ _dflags, _pdata, _iflags) \
+ __AML_CLK_PLL(_name, _en_reg, _en_shift, _en_width, \
+ _m_reg, _m_shift, _m_width, \
+ _f_reg, _f_shift, _f_width, \
+ _n_reg, _n_shift, _n_width, \
+ _l_reg, _l_shift, _l_width, \
+ _r_reg, _r_shift, _r_width, \
+ _init_reg, _init_reg_cnt, _range, _table, \
+ _dflags, &meson_clk_pll_ro_ops, \
+ NULL, _pdata, NULL, _iflags)
+
+#define AML_CLK_MUX_RW(_name, _reg, _mask, _shift, _table, _dflags, \
+ _pdata, _iflags) \
+ __AML_CLK_MUX(_name, _reg, _mask, _shift, _table, _dflags, \
+ &clk_regmap_mux_ops, NULL, _pdata, NULL, \
+ ARRAY_SIZE(_pdata), _iflags)
+
+#define AML_CLK_DIV_RW(_name, _reg, _shift, _width, _table, _dflags, \
+ _phw, _iflags) \
+ __AML_CLK_DIV(_name, _reg, _shift, _width, _table, _dflags, \
+ &clk_regmap_divider_ops, NULL, NULL, \
+ _phw, _iflags)
+
+#define AML_CLK_DIV_RO(_name, _reg, _shift, _width, _table, _dflags, \
+ _phw, _iflags) \
+ __AML_CLK_DIV(_name, _reg, _shift, _width, _table, _dflags, \
+ &clk_regmap_divider_ro_ops, NULL, NULL, \
+ _phw, _iflags)
+
+#define AML_CLK_GATE_RW(_name, _reg, _bit, _dflags, _phw, _iflags) \
+ __AML_CLK_GATE(_name, _reg, _bit, _dflags, \
+ &clk_regmap_gate_ops, NULL, NULL, _phw, \
+ _iflags)
+
+#define AML_CLK_GATE_RO(_name, _reg, _bit, _dflags, _phw, _iflags) \
+ __AML_CLK_GATE(_name, _reg, _bit, _dflags, \
+ &clk_regmap_gate_ro_ops, NULL, NULL, _phw, \
+ _iflags)
+
+#define AML_CLK_FIXED_FACTOR(_name, _mult, _div, _phw, _iflags) \
+ __AML_CLK_FIXED_FACTOR(_name, _mult, _div, \
+ &clk_fixed_factor_ops, NULL, NULL, \
+ _phw, _iflags)
+
+static const struct clk_parent_data pll_dco_parent = {
+ .fw_name = "pll_in",
+};
+
+static const struct clk_parent_data mclk_pll_dco_parent = {
+ .fw_name = "mclk_pll_in",
+};
+
+AML_CLK_PLL_RO(fixed_pll_dco, ANACTRL_FIXPLL_CTRL0, 28, 1, /* en */
+ ANACTRL_FIXPLL_CTRL0, 0, 8, /* m */
+ 0, 0, 0, /* frac */
+ ANACTRL_FIXPLL_CTRL0, 16, 5, /* n */
+ ANACTRL_FIXPLL_CTRL0, 31, 1, /* lock */
+ ANACTRL_FIXPLL_CTRL0, 29, 1, /* rst */
+ NULL, 0, NULL, NULL, 0, &pll_dco_parent, 0);
+AML_CLK_DIV_RO(fixed_pll, ANACTRL_FIXPLL_CTRL0, 12, 3, NULL,
+ CLK_DIVIDER_POWER_OF_TWO, &fixed_pll_dco.hw, 0);
+AML_CLK_FIXED_FACTOR(fclk_div40_div, 1, 40, &fixed_pll.hw, 0);
+AML_CLK_GATE_RO(fclk_div40, ANACTRL_FIXPLL_CTRL4, 0, 0, &fclk_div40_div.hw, 0);
+AML_CLK_FIXED_FACTOR(fclk_div2_div, 1, 2, &fixed_pll.hw, 0);
+AML_CLK_GATE_RO(fclk_div2, ANACTRL_FIXPLL_CTRL4, 24, 0, &fclk_div2_div.hw, 0);
+AML_CLK_FIXED_FACTOR(fclk_div2p5_div, 2, 5, &fixed_pll.hw, 0);
+AML_CLK_GATE_RO(fclk_div2p5, ANACTRL_FIXPLL_CTRL4, 4, 0, &fclk_div2p5_div.hw, 0);
+AML_CLK_FIXED_FACTOR(fclk_div3_div, 1, 3, &fixed_pll.hw, 0);
+AML_CLK_GATE_RO(fclk_div3, ANACTRL_FIXPLL_CTRL4, 20, 0, &fclk_div3_div.hw, 0);
+AML_CLK_FIXED_FACTOR(fclk_div4_div, 1, 4, &fixed_pll.hw, 0);
+AML_CLK_GATE_RO(fclk_div4, ANACTRL_FIXPLL_CTRL4, 21, 0, &fclk_div4_div.hw, 0);
+AML_CLK_FIXED_FACTOR(fclk_div5_div, 1, 5, &fixed_pll.hw, 0);
+AML_CLK_GATE_RO(fclk_div5, ANACTRL_FIXPLL_CTRL4, 22, 0, &fclk_div5_div.hw, 0);
+AML_CLK_FIXED_FACTOR(fclk_div7_div, 1, 7, &fixed_pll.hw, 0);
+AML_CLK_GATE_RO(fclk_div7, ANACTRL_FIXPLL_CTRL4, 23, 0, &fclk_div7_div.hw, 0);
+
+static const struct reg_sequence c3_gp0_init_regs[] = {
+ { .reg = ANACTRL_GP0PLL_CTRL1, .def = 0x0 },
+ { .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, .delay_us = 10 },
+ { .reg = ANACTRL_GP0PLL_CTRL0, .def = 0x080304fa },
+ { .reg = ANACTRL_GP0PLL_CTRL0, .def = 0x380304fa, .delay_us = 10 },
+ { .reg = ANACTRL_GP0PLL_CTRL0, .def = 0X180304fa }
+};
+
+static const struct pll_params_table c3_gp0_pll_params_table[] = {
+ PLL_PARAMS(150, 1), /* DCO = 3600M */
+ PLL_PARAMS(130, 1), /* DCO = 3120M */
+ PLL_PARAMS(192, 1), /* DCO = 4608M */
+ PLL_PARAMS(125, 1), /* DCO = 3000M */
+ { /* sentinel */ }
+};
+
+/* 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 */ }
+};
+
+AML_CLK_PLL_RW(gp0_pll_dco, ANACTRL_GP0PLL_CTRL0, 28, 1, /* en */
+ ANACTRL_GP0PLL_CTRL0, 0, 9, /* m */
+ ANACTRL_GP0PLL_CTRL1, 0, 19, /* frac */
+ ANACTRL_GP0PLL_CTRL0, 10, 5, /* n */
+ ANACTRL_GP0PLL_CTRL0, 31, 1, /* lock */
+ ANACTRL_GP0PLL_CTRL0, 29, 1, /* rst */
+ c3_gp0_init_regs, ARRAY_SIZE(c3_gp0_init_regs),
+ NULL, c3_gp0_pll_params_table, 0,
+ &pll_dco_parent, 0);
+AML_CLK_DIV_RW(gp0_pll, ANACTRL_GP0PLL_CTRL0, 16, 3,
+ c3_gp0_pll_od_table, 0,
+ &gp0_pll_dco.hw, CLK_SET_RATE_PARENT);
+
+static const struct reg_sequence c3_hifi_init_regs[] = {
+ { .reg = ANACTRL_HIFIPLL_CTRL0, .def = 0x08010496 },
+ { .reg = ANACTRL_HIFIPLL_CTRL0, .def = 0x38010496 },
+ { .reg = ANACTRL_HIFIPLL_CTRL1, .def = 0x0000ce40 },
+ { .reg = ANACTRL_HIFIPLL_CTRL2, .def = 0x00000000 },
+ { .reg = ANACTRL_HIFIPLL_CTRL3, .def = 0x6a285c00 },
+ { .reg = ANACTRL_HIFIPLL_CTRL4, .def = 0x65771290 },
+ { .reg = ANACTRL_HIFIPLL_CTRL5, .def = 0x3927200a },
+ { .reg = ANACTRL_HIFIPLL_CTRL6, .def = 0x56540000, .delay_us = 50 },
+ { .reg = ANACTRL_HIFIPLL_CTRL0, .def = 0x18010496, .delay_us = 20 },
+};
+
+static const struct pll_params_table c3_hifi_pll_params_table[] = {
+ PLL_PARAMS(150, 1), /* DCO = 3600M */
+ PLL_PARAMS(130, 1), /* DCO = 3120M */
+ PLL_PARAMS(192, 1), /* DCO = 4608M */
+ PLL_PARAMS(125, 1), /* DCO = 3000M */
+ { /* sentinel */ }
+};
+
+AML_CLK_PLL_RW(hifi_pll_dco, ANACTRL_HIFIPLL_CTRL0, 28, 1, /* en */
+ ANACTRL_HIFIPLL_CTRL0, 0, 8, /* m */
+ ANACTRL_HIFIPLL_CTRL1, 0, 19, /* frac */
+ ANACTRL_HIFIPLL_CTRL0, 10, 5, /* n */
+ ANACTRL_HIFIPLL_CTRL0, 31, 1, /* lock */
+ ANACTRL_HIFIPLL_CTRL0, 29, 1, /* rst */
+ c3_hifi_init_regs, ARRAY_SIZE(c3_hifi_init_regs),
+ NULL, c3_hifi_pll_params_table, 0,
+ &pll_dco_parent, 0);
+AML_CLK_DIV_RW(hifi_pll, ANACTRL_HIFIPLL_CTRL0, 16, 2,
+ NULL, CLK_DIVIDER_POWER_OF_TWO,
+ &hifi_pll_dco.hw, CLK_SET_RATE_PARENT);
+
+static const struct reg_sequence c3_mclk_init_regs[] = {
+ { .reg = ANACTRL_MPLL_CTRL0, .def = 0x20011063 },
+ { .reg = ANACTRL_MPLL_CTRL0, .def = 0x30011063 },
+ { .reg = ANACTRL_MPLL_CTRL1, .def = 0x1420500f },
+ { .reg = ANACTRL_MPLL_CTRL2, .def = 0x00023041 },
+ { .reg = ANACTRL_MPLL_CTRL3, .def = 0x18180000 },
+ { .reg = ANACTRL_MPLL_CTRL0, .def = 0x10011063 },
+ { .reg = ANACTRL_MPLL_CTRL2, .def = 0x00023001 }
+};
+
+static const struct pll_params_table c3_mclk_pll_params_table[] = {
+ PLL_PARAMS(99, 1), /* VCO = 2376M */
+ { /* sentinel */ }
+};
+
+static const struct clk_div_table c3_mpll_od_table[] = {
+ { 0, 1 },
+ { 1, 2 },
+ { 2, 4 },
+ { 3, 8 },
+ { 4, 16 },
+ { /* sentinel */ }
+};
+
+AML_CLK_PLL_RW(mclk_pll_dco, ANACTRL_MPLL_CTRL0, 28, 1, /* en */
+ ANACTRL_MPLL_CTRL0, 0, 8, /* m */
+ 0, 0, 0, /* frac */
+ ANACTRL_MPLL_CTRL0, 16, 5, /* n */
+ ANACTRL_MPLL_CTRL0, 31, 1, /* lock */
+ ANACTRL_MPLL_CTRL0, 29, 1, /* rst */
+ c3_mclk_init_regs, ARRAY_SIZE(c3_mclk_init_regs),
+ NULL, c3_mclk_pll_params_table, 0,
+ &mclk_pll_dco_parent, 0);
+AML_CLK_DIV_RW(mclk_pll, ANACTRL_MPLL_CTRL0, 12, 3,
+ c3_mpll_od_table, 0,
+ &mclk_pll_dco.hw, CLK_SET_RATE_PARENT);
+AML_CLK_DIV_RW(mclk_pll_clk, ANACTRL_MPLL_CTRL4, 16, 5, NULL,
+ CLK_DIVIDER_ONE_BASED | CLK_DIVIDER_ALLOW_ZERO,
+ &mclk_pll.hw, CLK_SET_RATE_PARENT);
+
+static const struct clk_parent_data mclk_parent[] = {
+ { .hw = &mclk_pll_clk.hw },
+ { .fw_name = "mclk_pll_in" },
+ { .hw = &fclk_div40.hw }
+};
+
+AML_CLK_MUX_RW(mclk0_sel, ANACTRL_MPLL_CTRL4, 0x3, 4, NULL, 0,
+ mclk_parent, 0);
+AML_CLK_GATE_RW(mclk0_sel_out, ANACTRL_MPLL_CTRL4, 1, 0,
+ &mclk0_sel.hw, CLK_SET_RATE_PARENT);
+AML_CLK_DIV_RW(mclk0_div, ANACTRL_MPLL_CTRL4, 2, 1, NULL, 0,
+ &mclk0_sel_out.hw, CLK_SET_RATE_PARENT);
+AML_CLK_GATE_RW(mclk0, ANACTRL_MPLL_CTRL4, 0, 0,
+ &mclk0_div.hw, CLK_SET_RATE_PARENT);
+
+AML_CLK_MUX_RW(mclk1_sel, ANACTRL_MPLL_CTRL4, 0x3, 12, NULL, 0,
+ mclk_parent, 0);
+AML_CLK_GATE_RW(mclk1_sel_out, ANACTRL_MPLL_CTRL4, 9, 0,
+ &mclk1_sel.hw, CLK_SET_RATE_PARENT);
+AML_CLK_DIV_RW(mclk1_div, ANACTRL_MPLL_CTRL4, 10, 1, NULL, 0,
+ &mclk1_sel_out.hw, CLK_SET_RATE_PARENT);
+AML_CLK_GATE_RW(mclk1, ANACTRL_MPLL_CTRL4, 8, 0,
+ &mclk1_div.hw, 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_DIV40_DIV] = &fclk_div40_div.hw,
+ [CLKID_FCLK_DIV40] = &fclk_div40.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_HIFI_PLL_DCO] = &hifi_pll_dco.hw,
+ [CLKID_HIFI_PLL] = &hifi_pll.hw,
+ [CLKID_MCLK_PLL_DCO] = &mclk_pll_dco.hw,
+ [CLKID_MCLK_PLL] = &mclk_pll.hw,
+ [CLKID_MCLK_PLL_CLK] = &mclk_pll_clk.hw,
+ [CLKID_MCLK0_SEL] = &mclk0_sel.hw,
+ [CLKID_MCLK0_SEL_OUT] = &mclk0_sel_out.hw,
+ [CLKID_MCLK0_DIV] = &mclk0_div.hw,
+ [CLKID_MCLK0] = &mclk0.hw,
+ [CLKID_MCLK1_SEL] = &mclk1_sel.hw,
+ [CLKID_MCLK1_SEL_OUT] = &mclk1_sel_out.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_div40,
+ &fclk_div2,
+ &fclk_div2p5,
+ &fclk_div3,
+ &fclk_div4,
+ &fclk_div5,
+ &fclk_div7,
+ &gp0_pll_dco,
+ &gp0_pll,
+ &hifi_pll_dco,
+ &hifi_pll,
+ &mclk_pll_dco,
+ &mclk_pll,
+ &mclk_pll_clk,
+ &mclk0_sel,
+ &mclk0_sel_out,
+ &mclk0_div,
+ &mclk0,
+ &mclk1_sel,
+ &mclk1_sel_out,
+ &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");
diff --git a/drivers/clk/meson/c3-pll.h b/drivers/clk/meson/c3-pll.h
new file mode 100644
index 000000000000..92a08196a46f
--- /dev/null
+++ b/drivers/clk/meson/c3-pll.h
@@ -0,0 +1,35 @@
+/* SPDX-License-Identifier: (GPL-2.0-only OR MIT) */
+/*
+ * Copyright (c) 2023 Amlogic, inc.
+ * Author: Chuan Liu <[email protected]>
+ */
+
+#ifndef __AML_C3_PLL_H__
+#define __AML_C3_PLL_H__
+
+#define ANACTRL_FIXPLL_CTRL0 0x0040
+#define ANACTRL_FIXPLL_CTRL4 0x0050
+#define ANACTRL_GP0PLL_CTRL0 0x0080
+#define ANACTRL_GP0PLL_CTRL1 0x0084
+#define ANACTRL_GP0PLL_CTRL2 0x0088
+#define ANACTRL_GP0PLL_CTRL3 0x008c
+#define ANACTRL_GP0PLL_CTRL4 0x0090
+#define ANACTRL_GP0PLL_CTRL5 0x0094
+#define ANACTRL_GP0PLL_CTRL6 0x0098
+#define ANACTRL_GP0PLL_STS 0x009c
+#define ANACTRL_HIFIPLL_CTRL0 0x0100
+#define ANACTRL_HIFIPLL_CTRL1 0x0104
+#define ANACTRL_HIFIPLL_CTRL2 0x0108
+#define ANACTRL_HIFIPLL_CTRL3 0x010c
+#define ANACTRL_HIFIPLL_CTRL4 0x0110
+#define ANACTRL_HIFIPLL_CTRL5 0x0114
+#define ANACTRL_HIFIPLL_CTRL6 0x0118
+#define ANACTRL_HIFIPLL_STS 0x011c
+#define ANACTRL_MPLL_CTRL0 0x0180
+#define ANACTRL_MPLL_CTRL1 0x0184
+#define ANACTRL_MPLL_CTRL2 0x0188
+#define ANACTRL_MPLL_CTRL3 0x018c
+#define ANACTRL_MPLL_CTRL4 0x0190
+#define ANACTRL_MPLL_STS 0x01a4
+
+#endif /* __AML_C3_PLL_H__ */
--
2.37.1
Add the C3 peripherals clock controller driver in the C3 SoC family.
Signed-off-by: Xianwei Zhao <[email protected]>
---
drivers/clk/meson/Kconfig | 13 +
drivers/clk/meson/Makefile | 1 +
drivers/clk/meson/c3-peripherals.c | 1372 ++++++++++++++++++++++++++++
drivers/clk/meson/c3-peripherals.h | 48 +
4 files changed, 1434 insertions(+)
create mode 100644 drivers/clk/meson/c3-peripherals.c
create mode 100644 drivers/clk/meson/c3-peripherals.h
diff --git a/drivers/clk/meson/Kconfig b/drivers/clk/meson/Kconfig
index 76be4bbd2afb..c8d59d28c8ff 100644
--- a/drivers/clk/meson/Kconfig
+++ b/drivers/clk/meson/Kconfig
@@ -140,6 +140,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"
+ default y
+ select COMMON_CLK_MESON_REGMAP
+ select COMMON_CLK_MESON_DUALDIV
+ select COMMON_CLK_MESON_CLKC_UTILS
+ select COMMON_CLK_C3_PLL
+ help
+ Support for the Peripherals clock controller on Amlogic C302X and
+ C308L devices, AKA c3. Amlogic C302X and C308L devices include
+ AW402, AW409 and AW419. 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..48827ecba28f
--- /dev/null
+++ b/drivers/clk/meson/c3-peripherals.c
@@ -0,0 +1,1372 @@
+// 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 "c3-peripherals.h"
+#include "meson-clkc-utils.h"
+#include <dt-bindings/clock/amlogic,c3-peripherals-clkc.h>
+
+#define __AML_CLK_MUX(_name, _reg, _mask, _shift, _table, _dflags, \
+ _ops, _pname, _pdata, _phw, _pnub, _iflags) \
+static struct clk_regmap _name = { \
+ .data = &(struct clk_regmap_mux_data){ \
+ .offset = _reg, \
+ .mask = _mask, \
+ .shift = _shift, \
+ .table = _table, \
+ .flags = _dflags, \
+ }, \
+ .hw.init = &(struct clk_init_data){ \
+ .name = #_name, \
+ .ops = _ops, \
+ .parent_names = _pname, \
+ .parent_data = _pdata, \
+ .parent_hws = _phw, \
+ .num_parents = _pnub, \
+ .flags = _iflags, \
+ }, \
+}
+
+#define __AML_CLK_DIV(_name, _reg, _shift, _width, _table, _dflags, \
+ _ops, _pname, _pdata, _phw, _iflags) \
+static struct clk_regmap _name = { \
+ .data = &(struct clk_regmap_div_data){ \
+ .offset = _reg, \
+ .shift = _shift, \
+ .width = _width, \
+ .table = _table, \
+ .flags = _dflags, \
+ }, \
+ .hw.init = &(struct clk_init_data){ \
+ .name = #_name, \
+ .ops = _ops, \
+ .parent_names = _pname, \
+ .parent_data = _pdata, \
+ .parent_hws = (const struct clk_hw *[]) { _phw }, \
+ .num_parents = 1, \
+ .flags = _iflags, \
+ }, \
+}
+
+#define __AML_CLK_GATE(_name, _reg, _bit, _dflags, \
+ _ops, _pname, _pdata, _phw, _iflags) \
+static struct clk_regmap _name = { \
+ .data = &(struct clk_regmap_gate_data){ \
+ .offset = _reg, \
+ .bit_idx = _bit, \
+ .flags = _dflags, \
+ }, \
+ .hw.init = &(struct clk_init_data) { \
+ .name = #_name, \
+ .ops = _ops, \
+ .parent_names = _pname, \
+ .parent_data = _pdata, \
+ .parent_hws = (const struct clk_hw *[]) { _phw }, \
+ .num_parents = 1, \
+ .flags = _iflags, \
+ }, \
+}
+
+#define AML_REG_PARM(_member_name, _reg, _shift, _width) \
+ ._member_name = { \
+ .reg_off = _reg, \
+ .shift = _shift, \
+ .width = _width, \
+ }
+
+#define __AML_CLK_DUALDIV(_name, _n1_reg, _n1_shift, _n1_width, \
+ _n2_reg, _n2_shift, _n2_width, \
+ _m1_reg, _m1_shift, _m1_width, \
+ _m2_reg, _m2_shift, _m2_width, \
+ _d_reg, _d_shift, _d_width, _dualdiv_table, \
+ _ops, _pname, _pdata, _phw, _iflags) \
+static struct clk_regmap _name = { \
+ .data = &(struct meson_clk_dualdiv_data){ \
+ AML_REG_PARM(n1, \
+ _n1_reg, _n1_shift, _n1_width), \
+ AML_REG_PARM(n2, \
+ _n2_reg, _n2_shift, _n2_width), \
+ AML_REG_PARM(m1, \
+ _m1_reg, _m1_shift, _m1_width), \
+ AML_REG_PARM(m2, \
+ _m2_reg, _m2_shift, _m2_width), \
+ AML_REG_PARM(dual, \
+ _d_reg, _d_shift, _d_width), \
+ .table = _dualdiv_table, \
+ }, \
+ .hw.init = &(struct clk_init_data) { \
+ .name = #_name, \
+ .ops = _ops, \
+ .parent_names = _pname, \
+ .parent_data = _pdata, \
+ .parent_hws = (const struct clk_hw *[]) { _phw }, \
+ .num_parents = 1, \
+ .flags = _iflags, \
+ }, \
+}
+
+#define __AML_CLK_FIXED_FACTOR(_name, _mult, _div, _ops, \
+ _pname, _pdata, _phw, _iflags) \
+static struct clk_fixed_factor _name = { \
+ .mult = _mult, \
+ .div = _div, \
+ .hw.init = &(struct clk_init_data){ \
+ .name = #_name, \
+ .ops = _ops, \
+ .parent_names = _pname, \
+ .parent_data = _pdata, \
+ .parent_hws = (const struct clk_hw *[]) { _phw }, \
+ .num_parents = 1, \
+ .flags = _iflags, \
+ }, \
+}
+
+#define AML_CLK_MUX_RW(_name, _reg, _mask, _shift, _table, _dflags, \
+ _pdata, _iflags) \
+ __AML_CLK_MUX(_name, _reg, _mask, _shift, _table, _dflags, \
+ &clk_regmap_mux_ops, NULL, _pdata, NULL, \
+ ARRAY_SIZE(_pdata), _iflags)
+
+#define AML_CLK_DIV_RW(_name, _reg, _shift, _width, _table, _dflags, \
+ _phw, _iflags) \
+ __AML_CLK_DIV(_name, _reg, _shift, _width, _table, _dflags, \
+ &clk_regmap_divider_ops, NULL, NULL, \
+ _phw, _iflags)
+
+#define AML_CLK_GATE_RW(_name, _reg, _bit, _dflags, _phw, _iflags) \
+ __AML_CLK_GATE(_name, _reg, _bit, _dflags, \
+ &clk_regmap_gate_ops, NULL, NULL, _phw, \
+ _iflags)
+
+#define AML_CLK_FIXED_FACTOR(_name, _mult, _div, _phw, _iflags) \
+ __AML_CLK_FIXED_FACTOR(_name, _mult, _div, \
+ &clk_fixed_factor_ops, NULL, NULL, \
+ _phw, _iflags)
+
+#define AML_CLK_DUALDIV_RW(_name, _n1_reg, _n1_shift, _n1_width, \
+ _n2_reg, _n2_shift, _n2_width, \
+ _m1_reg, _m1_shift, _m1_width, \
+ _m2_reg, _m2_shift, _m2_width, \
+ _d_reg, _d_shift, _d_width, _dualdiv_table,\
+ _phw, _iflags) \
+ __AML_CLK_DUALDIV(_name, _n1_reg, _n1_shift, _n1_width, \
+ _n2_reg, _n2_shift, _n2_width, \
+ _m1_reg, _m1_shift, _m1_width, \
+ _m2_reg, _m2_shift, _m2_width, \
+ _d_reg, _d_shift, _d_width, _dualdiv_table, \
+ &meson_clk_dualdiv_ops, \
+ NULL, NULL, _phw, _iflags)
+
+static struct clk_regmap pll_in = {
+ .data = &(struct clk_regmap_gate_data){
+ .offset = OSCIN_CTRL,
+ .bit_idx = 4,
+ },
+ .hw.init = &(struct clk_init_data) {
+ .name = "pll_in",
+ .ops = &clk_regmap_gate_ro_ops,
+ .parent_data = &(const struct clk_parent_data) {
+ .fw_name = "xtal",
+ },
+ .num_parents = 1,
+ },
+};
+
+static struct clk_regmap mclk_pll_in = {
+ .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",
+ },
+ .num_parents = 1,
+ },
+};
+
+static const struct clk_parent_data rtc_xtal_clkin_parent = {
+ .fw_name = "xtal",
+};
+
+__AML_CLK_GATE(rtc_xtal_clkin, RTC_BY_OSCIN_CTRL0, 31, 0,
+ &clk_regmap_gate_ops, NULL, &rtc_xtal_clkin_parent, NULL, 0);
+
+static const struct meson_clk_dualdiv_param rtc_32k_div_table[] = {
+ { 733, 732, 8, 11, 1 },
+ { /* sentinel */ }
+};
+
+AML_CLK_DUALDIV_RW(rtc_32k_div, RTC_BY_OSCIN_CTRL0, 0, 12,
+ RTC_BY_OSCIN_CTRL0, 12, 12,
+ RTC_BY_OSCIN_CTRL1, 0, 12,
+ RTC_BY_OSCIN_CTRL1, 12, 12,
+ RTC_BY_OSCIN_CTRL0, 28, 1, rtc_32k_div_table,
+ &rtc_xtal_clkin.hw, 0);
+
+static const struct clk_parent_data rtc_32k_mux_parent_data[] = {
+ { .hw = &rtc_32k_div.hw },
+ { .hw = &rtc_xtal_clkin.hw }
+};
+
+AML_CLK_MUX_RW(rtc_32k_mux, RTC_BY_OSCIN_CTRL1, 0x1, 24, NULL, 0,
+ rtc_32k_mux_parent_data, CLK_SET_RATE_PARENT);
+
+AML_CLK_GATE_RW(rtc_32k, RTC_BY_OSCIN_CTRL0, 30, 0,
+ &rtc_32k_mux.hw, CLK_SET_RATE_PARENT);
+
+static const struct clk_parent_data rtc_clk_mux_parent_data[] = {
+ { .fw_name = "xtal" },
+ { .hw = &rtc_32k.hw }
+};
+
+AML_CLK_MUX_RW(rtc_clk, RTC_CTRL, 0x3, 0, NULL, 0,
+ rtc_clk_mux_parent_data, CLK_SET_RATE_PARENT);
+
+/* sys_clk */
+#define AML_CLK_GATE_SYS_CLK(_name, _reg, _bit) \
+ AML_CLK_GATE_RW(_name, _reg, _bit, 0, &sys_clk.hw, CLK_IGNORE_UNUSED)
+
+/* axi_clk */
+#define AML_CLK_GATE_AXI_CLK(_name, _reg, _bit) \
+ AML_CLK_GATE_RW(_name, _reg, _bit, 0, &axi_clk.hw, CLK_IGNORE_UNUSED)
+
+/*
+ * Some clocks have multiple clock sources, and the parent clock and index are
+ * discontinuous, Some channels corresponding to the clock index are not
+ * actually connected inside the chip, or the clock source is invalid.
+ */
+static u32 sys_axi_parent_table[] = { 0, 2, 3, 4, 7 };
+static const struct clk_parent_data sys_axi_parent_data[] = {
+ { .fw_name = "xtal" },
+ { .fw_name = "fclk_div3" },
+ { .fw_name = "fclk_div4" },
+ { .fw_name = "fclk_div5" },
+ { .hw = &rtc_clk.hw }
+};
+
+AML_CLK_MUX_RW(sys_a_sel, SYS_CLK_CTRL0, 0x7, 10,
+ sys_axi_parent_table, 0, sys_axi_parent_data, 0);
+AML_CLK_DIV_RW(sys_a_div, SYS_CLK_CTRL0, 0, 10, NULL, 0,
+ &sys_a_sel.hw, 0);
+AML_CLK_GATE_RW(sys_a, SYS_CLK_CTRL0, 13, 0,
+ &sys_a_div.hw, CLK_IGNORE_UNUSED);
+
+AML_CLK_MUX_RW(sys_b_sel, SYS_CLK_CTRL0, 0x7, 26,
+ sys_axi_parent_table, 0, sys_axi_parent_data, 0);
+AML_CLK_DIV_RW(sys_b_div, SYS_CLK_CTRL0, 16, 10, NULL, 0,
+ &sys_b_sel.hw, 0);
+AML_CLK_GATE_RW(sys_b, SYS_CLK_CTRL0, 29, 0,
+ &sys_b_div.hw, CLK_IGNORE_UNUSED);
+
+static const struct clk_parent_data sys_clk_parent_data[] = {
+ { .hw = &sys_a.hw },
+ { .hw = &sys_b.hw }
+};
+
+AML_CLK_MUX_RW(sys_clk, SYS_CLK_CTRL0, 1, 15, NULL, 0,
+ sys_clk_parent_data, 0);
+
+AML_CLK_MUX_RW(axi_a_sel, AXI_CLK_CTRL0, 0x7, 10,
+ sys_axi_parent_table, 0, sys_axi_parent_data, 0);
+AML_CLK_DIV_RW(axi_a_div, AXI_CLK_CTRL0, 0, 10, NULL, 0,
+ &axi_a_sel.hw, 0);
+AML_CLK_GATE_RW(axi_a, AXI_CLK_CTRL0, 13, 0,
+ &axi_a_div.hw, CLK_IGNORE_UNUSED);
+
+AML_CLK_MUX_RW(axi_b_sel, AXI_CLK_CTRL0, 0x7, 26,
+ sys_axi_parent_table, 0, sys_axi_parent_data, 0);
+AML_CLK_DIV_RW(axi_b_div, AXI_CLK_CTRL0, 16, 10, NULL, 0,
+ &axi_b_sel.hw, 0);
+AML_CLK_GATE_RW(axi_b, AXI_CLK_CTRL0, 29, 0,
+ &axi_b_div.hw, CLK_IGNORE_UNUSED);
+
+static const struct clk_parent_data axi_clk_parent_data[] = {
+ { .hw = &axi_a.hw },
+ { .hw = &axi_b.hw }
+};
+
+AML_CLK_MUX_RW(axi_clk, AXI_CLK_CTRL0, 1, 15, NULL, 0,
+ axi_clk_parent_data, 0);
+
+AML_CLK_GATE_SYS_CLK(sys_reset_ctrl, SYS_CLK_EN0_REG0, 1);
+AML_CLK_GATE_SYS_CLK(sys_pwr_ctrl, SYS_CLK_EN0_REG0, 3);
+AML_CLK_GATE_SYS_CLK(sys_pad_ctrl, SYS_CLK_EN0_REG0, 4);
+AML_CLK_GATE_SYS_CLK(sys_ctrl, SYS_CLK_EN0_REG0, 5);
+AML_CLK_GATE_SYS_CLK(sys_ts_pll, SYS_CLK_EN0_REG0, 6);
+AML_CLK_GATE_SYS_CLK(sys_dev_arb, SYS_CLK_EN0_REG0, 7);
+AML_CLK_GATE_SYS_CLK(sys_mmc_pclk, SYS_CLK_EN0_REG0, 8);
+AML_CLK_GATE_SYS_CLK(sys_capu, SYS_CLK_EN0_REG0, 9);
+AML_CLK_GATE_SYS_CLK(sys_cpu_ctrl, SYS_CLK_EN0_REG0, 11);
+AML_CLK_GATE_SYS_CLK(sys_jtag_ctrl, SYS_CLK_EN0_REG0, 12);
+AML_CLK_GATE_SYS_CLK(sys_ir_ctrl, SYS_CLK_EN0_REG0, 13);
+AML_CLK_GATE_SYS_CLK(sys_irq_ctrl, SYS_CLK_EN0_REG0, 14);
+AML_CLK_GATE_SYS_CLK(sys_msr_clk, SYS_CLK_EN0_REG0, 15);
+AML_CLK_GATE_SYS_CLK(sys_rom, SYS_CLK_EN0_REG0, 16);
+AML_CLK_GATE_SYS_CLK(sys_uart_f, SYS_CLK_EN0_REG0, 17);
+AML_CLK_GATE_SYS_CLK(sys_cpu_apb, SYS_CLK_EN0_REG0, 18);
+AML_CLK_GATE_SYS_CLK(sys_rsa, SYS_CLK_EN0_REG0, 19);
+AML_CLK_GATE_SYS_CLK(sys_sar_adc, SYS_CLK_EN0_REG0, 20);
+AML_CLK_GATE_SYS_CLK(sys_startup, SYS_CLK_EN0_REG0, 21);
+AML_CLK_GATE_SYS_CLK(sys_secure, SYS_CLK_EN0_REG0, 22);
+AML_CLK_GATE_SYS_CLK(sys_spifc, SYS_CLK_EN0_REG0, 23);
+AML_CLK_GATE_SYS_CLK(sys_nna, SYS_CLK_EN0_REG0, 25);
+AML_CLK_GATE_SYS_CLK(sys_eth_mac, SYS_CLK_EN0_REG0, 26);
+AML_CLK_GATE_SYS_CLK(sys_gic, SYS_CLK_EN0_REG0, 27);
+AML_CLK_GATE_SYS_CLK(sys_rama, SYS_CLK_EN0_REG0, 28);
+AML_CLK_GATE_SYS_CLK(sys_big_nic, SYS_CLK_EN0_REG0, 29);
+AML_CLK_GATE_SYS_CLK(sys_ramb, SYS_CLK_EN0_REG0, 30);
+AML_CLK_GATE_SYS_CLK(sys_audio_pclk, SYS_CLK_EN0_REG0, 31);
+AML_CLK_GATE_SYS_CLK(sys_pwm_kl, SYS_CLK_EN0_REG1, 0);
+AML_CLK_GATE_SYS_CLK(sys_pwm_ij, SYS_CLK_EN0_REG1, 1);
+AML_CLK_GATE_SYS_CLK(sys_usb, SYS_CLK_EN0_REG1, 2);
+AML_CLK_GATE_SYS_CLK(sys_sd_emmc_a, SYS_CLK_EN0_REG1, 3);
+AML_CLK_GATE_SYS_CLK(sys_sd_emmc_c, SYS_CLK_EN0_REG1, 4);
+AML_CLK_GATE_SYS_CLK(sys_pwm_ab, SYS_CLK_EN0_REG1, 5);
+AML_CLK_GATE_SYS_CLK(sys_pwm_cd, SYS_CLK_EN0_REG1, 6);
+AML_CLK_GATE_SYS_CLK(sys_pwm_ef, SYS_CLK_EN0_REG1, 7);
+AML_CLK_GATE_SYS_CLK(sys_pwm_gh, SYS_CLK_EN0_REG1, 8);
+AML_CLK_GATE_SYS_CLK(sys_spicc_1, SYS_CLK_EN0_REG1, 9);
+AML_CLK_GATE_SYS_CLK(sys_spicc_0, SYS_CLK_EN0_REG1, 10);
+AML_CLK_GATE_SYS_CLK(sys_uart_a, SYS_CLK_EN0_REG1, 11);
+AML_CLK_GATE_SYS_CLK(sys_uart_b, SYS_CLK_EN0_REG1, 12);
+AML_CLK_GATE_SYS_CLK(sys_uart_c, SYS_CLK_EN0_REG1, 13);
+AML_CLK_GATE_SYS_CLK(sys_uart_d, SYS_CLK_EN0_REG1, 14);
+AML_CLK_GATE_SYS_CLK(sys_uart_e, SYS_CLK_EN0_REG1, 15);
+AML_CLK_GATE_SYS_CLK(sys_i2c_m_a, SYS_CLK_EN0_REG1, 16);
+AML_CLK_GATE_SYS_CLK(sys_i2c_m_b, SYS_CLK_EN0_REG1, 17);
+AML_CLK_GATE_SYS_CLK(sys_i2c_m_c, SYS_CLK_EN0_REG1, 18);
+AML_CLK_GATE_SYS_CLK(sys_i2c_m_d, SYS_CLK_EN0_REG1, 19);
+AML_CLK_GATE_SYS_CLK(sys_i2c_s_a, SYS_CLK_EN0_REG1, 20);
+AML_CLK_GATE_SYS_CLK(sys_rtc, SYS_CLK_EN0_REG1, 21);
+AML_CLK_GATE_SYS_CLK(sys_ge2d, SYS_CLK_EN0_REG1, 22);
+AML_CLK_GATE_SYS_CLK(sys_isp, SYS_CLK_EN0_REG1, 23);
+AML_CLK_GATE_SYS_CLK(sys_gpv_isp_nic, SYS_CLK_EN0_REG1, 24);
+AML_CLK_GATE_SYS_CLK(sys_gpv_cve_nic, SYS_CLK_EN0_REG1, 25);
+AML_CLK_GATE_SYS_CLK(sys_mipi_dsi_host, SYS_CLK_EN0_REG1, 26);
+AML_CLK_GATE_SYS_CLK(sys_mipi_dsi_phy, SYS_CLK_EN0_REG1, 27);
+AML_CLK_GATE_SYS_CLK(sys_eth_phy, SYS_CLK_EN0_REG1, 28);
+AML_CLK_GATE_SYS_CLK(sys_acodec, SYS_CLK_EN0_REG1, 29);
+AML_CLK_GATE_SYS_CLK(sys_dwap, SYS_CLK_EN0_REG1, 30);
+AML_CLK_GATE_SYS_CLK(sys_dos, SYS_CLK_EN0_REG1, 31);
+AML_CLK_GATE_SYS_CLK(sys_cve, SYS_CLK_EN0_REG2, 0);
+AML_CLK_GATE_SYS_CLK(sys_vout, SYS_CLK_EN0_REG2, 1);
+AML_CLK_GATE_SYS_CLK(sys_vc9000e, SYS_CLK_EN0_REG2, 2);
+AML_CLK_GATE_SYS_CLK(sys_pwm_mn, SYS_CLK_EN0_REG2, 3);
+AML_CLK_GATE_SYS_CLK(sys_sd_emmc_b, SYS_CLK_EN0_REG2, 4);
+AML_CLK_GATE_AXI_CLK(axi_sys_nic, AXI_CLK_EN0, 2);
+AML_CLK_GATE_AXI_CLK(axi_isp_nic, AXI_CLK_EN0, 3);
+AML_CLK_GATE_AXI_CLK(axi_cve_nic, AXI_CLK_EN0, 4);
+AML_CLK_GATE_AXI_CLK(axi_ramb, AXI_CLK_EN0, 5);
+AML_CLK_GATE_AXI_CLK(axi_rama, AXI_CLK_EN0, 6);
+AML_CLK_GATE_AXI_CLK(axi_cpu_dmc, AXI_CLK_EN0, 7);
+AML_CLK_GATE_AXI_CLK(axi_nic, AXI_CLK_EN0, 8);
+AML_CLK_GATE_AXI_CLK(axi_dma, AXI_CLK_EN0, 9);
+AML_CLK_GATE_AXI_CLK(axi_mux_nic, AXI_CLK_EN0, 10);
+AML_CLK_GATE_AXI_CLK(axi_capu, AXI_CLK_EN0, 11);
+AML_CLK_GATE_AXI_CLK(axi_cve, AXI_CLK_EN0, 12);
+AML_CLK_GATE_AXI_CLK(axi_dev1_dmc, AXI_CLK_EN0, 13);
+AML_CLK_GATE_AXI_CLK(axi_dev0_dmc, AXI_CLK_EN0, 14);
+AML_CLK_GATE_AXI_CLK(axi_dsp_dmc, AXI_CLK_EN0, 15);
+
+/*
+ * clk_12_24m model
+ *
+ * |------| |-----| clk_12m_24m |-----|
+ * xtal---->| gate |---->| div |------------>| pad |
+ * |------| |-----| |-----|
+ */
+static const struct clk_parent_data clk_12_24m_in_parent = {
+ .fw_name = "xtal",
+};
+
+__AML_CLK_GATE(clk_12_24m_in, CLK12_24_CTRL, 11, 0, &clk_regmap_gate_ops,
+ NULL, &clk_12_24m_in_parent, NULL, 0);
+AML_CLK_DIV_RW(clk_12_24m, CLK12_24_CTRL, 10, 1, NULL, 0, &clk_12_24m_in.hw, 0);
+
+static const struct clk_parent_data fclk_25m_div_parent = {
+ .fw_name = "fixed_pll",
+};
+
+__AML_CLK_DIV(fclk_25m_div, CLK12_24_CTRL, 0, 8, NULL, 0,
+ &clk_regmap_divider_ops, NULL, &fclk_25m_div_parent, NULL, 0);
+AML_CLK_GATE_RW(fclk_25m, CLK12_24_CTRL, 12, 0, &fclk_25m_div.hw,
+ CLK_SET_RATE_PARENT);
+
+/* generate clock output */
+static u32 gen_parent_table[] = { 0, 1, 5, 7 };
+static const struct clk_parent_data gen_parent_data[] = {
+ { .fw_name = "xtal" },
+ { .hw = &rtc_clk.hw },
+ { .fw_name = "gp0_pll" },
+ { .fw_name = "hifi_pll" }
+};
+
+AML_CLK_MUX_RW(gen_sel, GEN_CLK_CTRL, 0x1f, 12,
+ gen_parent_table, 0, gen_parent_data, 0);
+AML_CLK_DIV_RW(gen_div, GEN_CLK_CTRL, 0, 11, NULL, 0,
+ &gen_sel.hw, CLK_SET_RATE_PARENT);
+AML_CLK_GATE_RW(gen, GEN_CLK_CTRL, 11, 0,
+ &gen_div.hw, CLK_SET_RATE_PARENT);
+
+static const struct clk_parent_data saradc_parent_data[] = {
+ { .fw_name = "xtal" },
+ { .hw = &sys_clk.hw }
+};
+
+AML_CLK_MUX_RW(saradc_sel, SAR_CLK_CTRL0, 0x1, 9,
+ NULL, 0, saradc_parent_data, 0);
+AML_CLK_DIV_RW(saradc_div, SAR_CLK_CTRL0, 0, 8, NULL, 0,
+ &saradc_sel.hw, CLK_SET_RATE_PARENT);
+AML_CLK_GATE_RW(saradc, SAR_CLK_CTRL0, 8, 0,
+ &saradc_div.hw, CLK_SET_RATE_PARENT);
+
+static u32 pwm_parent_table[] = { 0, 2, 3 };
+static const struct clk_parent_data pwm_parent_data[] = {
+ { .fw_name = "xtal" },
+ { .fw_name = "fclk_div4" },
+ { .fw_name = "fclk_div3" }
+};
+
+AML_CLK_MUX_RW(pwm_a_sel, PWM_CLK_AB_CTRL, 0x3, 9,
+ pwm_parent_table, 0, pwm_parent_data, 0);
+AML_CLK_DIV_RW(pwm_a_div, PWM_CLK_AB_CTRL, 0, 8, NULL, 0,
+ &pwm_a_sel.hw, CLK_SET_RATE_PARENT);
+AML_CLK_GATE_RW(pwm_a, PWM_CLK_AB_CTRL, 8, 0,
+ &pwm_a_div.hw, CLK_SET_RATE_PARENT);
+
+AML_CLK_MUX_RW(pwm_b_sel, PWM_CLK_AB_CTRL, 0x3, 25,
+ pwm_parent_table, 0, pwm_parent_data, 0);
+AML_CLK_DIV_RW(pwm_b_div, PWM_CLK_AB_CTRL, 16, 8, NULL, 0,
+ &pwm_b_sel.hw, CLK_SET_RATE_PARENT);
+AML_CLK_GATE_RW(pwm_b, PWM_CLK_AB_CTRL, 24, 0,
+ &pwm_b_div.hw, CLK_SET_RATE_PARENT);
+
+AML_CLK_MUX_RW(pwm_c_sel, PWM_CLK_CD_CTRL, 0x3, 9,
+ pwm_parent_table, 0, pwm_parent_data, 0);
+AML_CLK_DIV_RW(pwm_c_div, PWM_CLK_CD_CTRL, 0, 8, NULL, 0,
+ &pwm_c_sel.hw, CLK_SET_RATE_PARENT);
+AML_CLK_GATE_RW(pwm_c, PWM_CLK_CD_CTRL, 8, 0,
+ &pwm_c_div.hw, CLK_SET_RATE_PARENT);
+
+AML_CLK_MUX_RW(pwm_d_sel, PWM_CLK_CD_CTRL, 0x3, 25,
+ pwm_parent_table, 0, pwm_parent_data, 0);
+AML_CLK_DIV_RW(pwm_d_div, PWM_CLK_CD_CTRL, 16, 8, NULL, 0,
+ &pwm_d_sel.hw, CLK_SET_RATE_PARENT);
+AML_CLK_GATE_RW(pwm_d, PWM_CLK_CD_CTRL, 24, 0,
+ &pwm_d_div.hw, CLK_SET_RATE_PARENT);
+
+AML_CLK_MUX_RW(pwm_e_sel, PWM_CLK_EF_CTRL, 0x3, 9,
+ pwm_parent_table, 0, pwm_parent_data, 0);
+AML_CLK_DIV_RW(pwm_e_div, PWM_CLK_EF_CTRL, 0, 8, NULL, 0,
+ &pwm_e_sel.hw, CLK_SET_RATE_PARENT);
+AML_CLK_GATE_RW(pwm_e, PWM_CLK_EF_CTRL, 8, 0,
+ &pwm_e_div.hw, CLK_SET_RATE_PARENT);
+
+AML_CLK_MUX_RW(pwm_f_sel, PWM_CLK_EF_CTRL, 0x3, 25,
+ pwm_parent_table, 0, pwm_parent_data, 0);
+AML_CLK_DIV_RW(pwm_f_div, PWM_CLK_EF_CTRL, 16, 8, NULL, 0,
+ &pwm_f_sel.hw, CLK_SET_RATE_PARENT);
+AML_CLK_GATE_RW(pwm_f, PWM_CLK_EF_CTRL, 24, 0,
+ &pwm_f_div.hw, CLK_SET_RATE_PARENT);
+
+AML_CLK_MUX_RW(pwm_g_sel, PWM_CLK_GH_CTRL, 0x3, 9,
+ pwm_parent_table, 0, pwm_parent_data, 0);
+AML_CLK_DIV_RW(pwm_g_div, PWM_CLK_GH_CTRL, 0, 8, NULL, 0,
+ &pwm_g_sel.hw, CLK_SET_RATE_PARENT);
+AML_CLK_GATE_RW(pwm_g, PWM_CLK_GH_CTRL, 8, 0,
+ &pwm_g_div.hw, CLK_SET_RATE_PARENT);
+
+AML_CLK_MUX_RW(pwm_h_sel, PWM_CLK_GH_CTRL, 0x3, 25,
+ pwm_parent_table, 0, pwm_parent_data, 0);
+AML_CLK_DIV_RW(pwm_h_div, PWM_CLK_GH_CTRL, 16, 8, NULL, 0,
+ &pwm_h_sel.hw, CLK_SET_RATE_PARENT);
+AML_CLK_GATE_RW(pwm_h, PWM_CLK_GH_CTRL, 24, 0,
+ &pwm_h_div.hw, CLK_SET_RATE_PARENT);
+
+AML_CLK_MUX_RW(pwm_i_sel, PWM_CLK_IJ_CTRL, 0x3, 9,
+ pwm_parent_table, 0, pwm_parent_data, 0);
+AML_CLK_DIV_RW(pwm_i_div, PWM_CLK_IJ_CTRL, 0, 8, NULL, 0,
+ &pwm_i_sel.hw, CLK_SET_RATE_PARENT);
+AML_CLK_GATE_RW(pwm_i, PWM_CLK_IJ_CTRL, 8, 0,
+ &pwm_i_div.hw, CLK_SET_RATE_PARENT);
+
+AML_CLK_MUX_RW(pwm_j_sel, PWM_CLK_IJ_CTRL, 0x3, 25,
+ pwm_parent_table, 0, pwm_parent_data, 0);
+AML_CLK_DIV_RW(pwm_j_div, PWM_CLK_IJ_CTRL, 16, 8, NULL, 0,
+ &pwm_j_sel.hw, CLK_SET_RATE_PARENT);
+AML_CLK_GATE_RW(pwm_j, PWM_CLK_IJ_CTRL, 24, 0,
+ &pwm_j_div.hw, CLK_SET_RATE_PARENT);
+
+AML_CLK_MUX_RW(pwm_k_sel, PWM_CLK_KL_CTRL, 0x3, 9,
+ pwm_parent_table, 0, pwm_parent_data, 0);
+AML_CLK_DIV_RW(pwm_k_div, PWM_CLK_KL_CTRL, 0, 8, NULL, 0,
+ &pwm_k_sel.hw, CLK_SET_RATE_PARENT);
+AML_CLK_GATE_RW(pwm_k, PWM_CLK_KL_CTRL, 8, 0,
+ &pwm_k_div.hw, CLK_SET_RATE_PARENT);
+
+AML_CLK_MUX_RW(pwm_l_sel, PWM_CLK_KL_CTRL, 0x3, 25,
+ pwm_parent_table, 0, pwm_parent_data, 0);
+AML_CLK_DIV_RW(pwm_l_div, PWM_CLK_KL_CTRL, 16, 8, NULL, 0,
+ &pwm_l_sel.hw, CLK_SET_RATE_PARENT);
+AML_CLK_GATE_RW(pwm_l, PWM_CLK_KL_CTRL, 24, 0,
+ &pwm_l_div.hw, CLK_SET_RATE_PARENT);
+
+AML_CLK_MUX_RW(pwm_m_sel, PWM_CLK_MN_CTRL, 0x3, 9,
+ pwm_parent_table, 0, pwm_parent_data, 0);
+AML_CLK_DIV_RW(pwm_m_div, PWM_CLK_MN_CTRL, 0, 8, NULL, 0,
+ &pwm_m_sel.hw, CLK_SET_RATE_PARENT);
+AML_CLK_GATE_RW(pwm_m, PWM_CLK_MN_CTRL, 8, 0,
+ &pwm_m_div.hw, CLK_SET_RATE_PARENT);
+
+AML_CLK_MUX_RW(pwm_n_sel, PWM_CLK_MN_CTRL, 0x3, 25,
+ pwm_parent_table, 0, pwm_parent_data, 0);
+AML_CLK_DIV_RW(pwm_n_div, PWM_CLK_MN_CTRL, 16, 8, NULL, 0,
+ &pwm_n_sel.hw, CLK_SET_RATE_PARENT);
+AML_CLK_GATE_RW(pwm_n, PWM_CLK_MN_CTRL, 24, 0,
+ &pwm_n_div.hw, CLK_SET_RATE_PARENT);
+
+static const struct clk_parent_data spicc_parent_data[] = {
+ { .fw_name = "xtal" },
+ { .hw = &sys_clk.hw },
+ { .fw_name = "fclk_div4" },
+ { .fw_name = "fclk_div3" },
+ { .fw_name = "fclk_div2" },
+ { .fw_name = "fclk_div5" },
+ { .fw_name = "fclk_div7" }
+};
+
+AML_CLK_MUX_RW(spicc_a_sel, SPICC_CLK_CTRL, 0x7, 7,
+ NULL, 0, spicc_parent_data, 0);
+AML_CLK_DIV_RW(spicc_a_div, SPICC_CLK_CTRL, 0, 6, NULL, 0,
+ &spicc_a_sel.hw, CLK_SET_RATE_PARENT);
+AML_CLK_GATE_RW(spicc_a, SPICC_CLK_CTRL, 6, 0,
+ &spicc_a_div.hw, CLK_SET_RATE_PARENT);
+
+AML_CLK_MUX_RW(spicc_b_sel, SPICC_CLK_CTRL, 0x7, 23,
+ NULL, 0, spicc_parent_data, 0);
+AML_CLK_DIV_RW(spicc_b_div, SPICC_CLK_CTRL, 16, 6, NULL, 0,
+ &spicc_b_sel.hw, CLK_SET_RATE_PARENT);
+AML_CLK_GATE_RW(spicc_b, SPICC_CLK_CTRL, 22, 0,
+ &spicc_b_div.hw, CLK_SET_RATE_PARENT);
+
+static const struct clk_parent_data spifc_parent_data[] = {
+ { .fw_name = "gp0_pll" },
+ { .fw_name = "fclk_div2" },
+ { .fw_name = "fclk_div3" },
+ { .fw_name = "fclk_div2p5" },
+ { .fw_name = "hifi_pll" },
+ { .fw_name = "fclk_div4" },
+ { .fw_name = "fclk_div5" },
+ { .fw_name = "fclk_div7" }
+};
+
+AML_CLK_MUX_RW(spifc_sel, SPIFC_CLK_CTRL, 0x7, 9,
+ NULL, 0, spifc_parent_data, 0);
+AML_CLK_DIV_RW(spifc_div, SPIFC_CLK_CTRL, 0, 7, NULL, 0,
+ &spifc_sel.hw, CLK_SET_RATE_PARENT);
+AML_CLK_GATE_RW(spifc, SPIFC_CLK_CTRL, 8, 0,
+ &spifc_div.hw, CLK_SET_RATE_PARENT);
+
+static u32 emmc_parent_table[] = { 0, 1, 2, 3, 4, 5, 7 };
+static const struct clk_parent_data emmc_parent_data[] = {
+ { .fw_name = "xtal" },
+ { .fw_name = "fclk_div2" },
+ { .fw_name = "fclk_div3" },
+ { .fw_name = "hifi_pll" },
+ { .fw_name = "fclk_div2p5" },
+ { .fw_name = "fclk_div4" },
+ { .fw_name = "gp0_pll" }
+};
+
+AML_CLK_MUX_RW(sd_emmc_a_sel, SD_EMMC_CLK_CTRL, 0x7, 9,
+ emmc_parent_table, 0, emmc_parent_data, 0);
+AML_CLK_DIV_RW(sd_emmc_a_div, SD_EMMC_CLK_CTRL, 0, 7, NULL, 0,
+ &sd_emmc_a_sel.hw, CLK_SET_RATE_PARENT);
+AML_CLK_GATE_RW(sd_emmc_a, SD_EMMC_CLK_CTRL, 7, 0,
+ &sd_emmc_a_div.hw, CLK_SET_RATE_PARENT);
+
+AML_CLK_MUX_RW(sd_emmc_b_sel, SD_EMMC_CLK_CTRL, 0x7, 25,
+ emmc_parent_table, 0, emmc_parent_data, 0);
+AML_CLK_DIV_RW(sd_emmc_b_div, SD_EMMC_CLK_CTRL, 16, 7, NULL, 0,
+ &sd_emmc_b_sel.hw, CLK_SET_RATE_PARENT);
+AML_CLK_GATE_RW(sd_emmc_b, SD_EMMC_CLK_CTRL, 23, 0,
+ &sd_emmc_b_div.hw, CLK_SET_RATE_PARENT);
+
+AML_CLK_MUX_RW(sd_emmc_c_sel, NAND_CLK_CTRL, 0x7, 9,
+ emmc_parent_table, 0, emmc_parent_data, 0);
+AML_CLK_DIV_RW(sd_emmc_c_div, NAND_CLK_CTRL, 0, 7, NULL, 0,
+ &sd_emmc_c_sel.hw, CLK_SET_RATE_PARENT);
+AML_CLK_GATE_RW(sd_emmc_c, NAND_CLK_CTRL, 7, 0,
+ &sd_emmc_c_div.hw, CLK_SET_RATE_PARENT);
+
+/* temperature sensor */
+static const struct clk_parent_data ts_parent = {
+ .fw_name = "xtal",
+};
+
+__AML_CLK_DIV(ts_div, TS_CLK_CTRL, 0, 8, NULL, 0,
+ &clk_regmap_divider_ops, NULL, &ts_parent, NULL, 0);
+AML_CLK_GATE_RW(ts, TS_CLK_CTRL, 8, 0, &ts_div.hw, CLK_SET_RATE_PARENT);
+
+static const struct clk_parent_data eth_parent = {
+ .fw_name = "fclk_div2",
+};
+
+__AML_CLK_FIXED_FACTOR(eth_125m_div, 1, 8, &clk_fixed_factor_ops,
+ NULL, ð_parent, NULL, 0);
+AML_CLK_GATE_RW(eth_125m, ETH_CLK_CTRL, 7, 0, ð_125m_div.hw,
+ CLK_SET_RATE_PARENT);
+__AML_CLK_DIV(eth_rmii_div, ETH_CLK_CTRL, 0, 7, NULL, 0,
+ &clk_regmap_divider_ops, NULL, ð_parent, NULL, 0);
+AML_CLK_GATE_RW(eth_rmii, ETH_CLK_CTRL, 8, 0, ð_rmii_div.hw,
+ CLK_SET_RATE_PARENT);
+
+static u32 mipi_dsi_meas_parent_table[] = { 0, 1, 2, 3, 5, 6, 7 };
+static const struct clk_parent_data mipi_dsi_meas_parent_data[] = {
+ { .fw_name = "xtal" },
+ { .fw_name = "fclk_div4" },
+ { .fw_name = "fclk_div3" },
+ { .fw_name = "fclk_div5" },
+ { .fw_name = "gp0_pll" },
+ { .fw_name = "fclk_div2" },
+ { .fw_name = "fclk_div7" }
+};
+
+AML_CLK_MUX_RW(mipi_dsi_meas_sel, VDIN_MEAS_CLK_CTRL, 0x7, 21,
+ mipi_dsi_meas_parent_table, 0, mipi_dsi_meas_parent_data, 0);
+AML_CLK_DIV_RW(mipi_dsi_meas_div, VDIN_MEAS_CLK_CTRL, 12, 7, NULL, 0,
+ &mipi_dsi_meas_sel.hw, CLK_SET_RATE_PARENT);
+AML_CLK_GATE_RW(mipi_dsi_meas, VDIN_MEAS_CLK_CTRL, 20, 0,
+ &mipi_dsi_meas_div.hw, CLK_SET_RATE_PARENT);
+
+static u32 dsi_phy_parent_table[] = { 1, 2, 3, 4, 5, 6, 7 };
+static const struct clk_parent_data dsi_phy_parent_data[] = {
+ { .fw_name = "gp0_pll" },
+ { .fw_name = "hifi_pll" },
+ { .fw_name = "fclk_div3" },
+ { .fw_name = "fclk_div2" },
+ { .fw_name = "fclk_div2p5" },
+ { .fw_name = "fclk_div4" },
+ { .fw_name = "fclk_div7" }
+};
+
+AML_CLK_MUX_RW(dsi_phy_sel, MIPIDSI_PHY_CLK_CTRL, 0x7, 12,
+ dsi_phy_parent_table, 0, dsi_phy_parent_data, 0);
+AML_CLK_DIV_RW(dsi_phy_div, MIPIDSI_PHY_CLK_CTRL, 0, 7, NULL, 0,
+ &dsi_phy_sel.hw, CLK_SET_RATE_PARENT);
+AML_CLK_GATE_RW(dsi_phy, MIPIDSI_PHY_CLK_CTRL, 8, 0,
+ &dsi_phy_div.hw, CLK_SET_RATE_PARENT);
+
+static u32 vout_parent_table[] = { 1, 2, 3, 4, 5, 6, 7 };
+static const struct clk_parent_data vout_parent_data[] = {
+ { .fw_name = "fclk_div3" },
+ { .fw_name = "fclk_div4" },
+ { .fw_name = "fclk_div5" },
+ { .fw_name = "gp0_pll" },
+ { .fw_name = "hifi_pll" },
+ { .fw_name = "fclk_div2p5" },
+ { .fw_name = "fclk_div7" }
+};
+
+AML_CLK_MUX_RW(vout_mclk_sel, VOUTENC_CLK_CTRL, 0x7, 9,
+ vout_parent_table, 0, vout_parent_data, 0);
+AML_CLK_DIV_RW(vout_mclk_div, VOUTENC_CLK_CTRL, 0, 7, NULL, 0,
+ &vout_mclk_sel.hw, CLK_SET_RATE_PARENT);
+AML_CLK_GATE_RW(vout_mclk, VOUTENC_CLK_CTRL, 8, 0,
+ &vout_mclk_div.hw, CLK_SET_RATE_PARENT);
+
+AML_CLK_MUX_RW(vout_enc_sel, VOUTENC_CLK_CTRL, 0x7, 25,
+ vout_parent_table, 0, vout_parent_data, 0);
+AML_CLK_DIV_RW(vout_enc_div, VOUTENC_CLK_CTRL, 16, 7, NULL, 0,
+ &vout_enc_sel.hw, CLK_SET_RATE_PARENT);
+AML_CLK_GATE_RW(vout_enc, VOUTENC_CLK_CTRL, 24, 0,
+ &vout_enc_div.hw, CLK_SET_RATE_PARENT);
+
+static const struct clk_parent_data hcodec_pre_parent_data[] = {
+ { .fw_name = "fclk_div2p5" },
+ { .fw_name = "fclk_div3" },
+ { .fw_name = "fclk_div4" },
+ { .fw_name = "fclk_div5" },
+ { .fw_name = "fclk_div7" },
+ { .fw_name = "hifi_pll" },
+ { .fw_name = "gp0_pll" },
+ { .fw_name = "xtal" }
+};
+
+AML_CLK_MUX_RW(hcodec_0_sel, VDEC_CLK_CTRL, 0x7, 9,
+ NULL, 0, hcodec_pre_parent_data, 0);
+AML_CLK_DIV_RW(hcodec_0_div, VDEC_CLK_CTRL, 0, 7, NULL, 0,
+ &hcodec_0_sel.hw, CLK_SET_RATE_PARENT);
+AML_CLK_GATE_RW(hcodec_0, VDEC_CLK_CTRL, 8, 0,
+ &hcodec_0_div.hw, CLK_SET_RATE_PARENT);
+
+AML_CLK_MUX_RW(hcodec_1_sel, VDEC3_CLK_CTRL, 0x7, 9,
+ NULL, 0, hcodec_pre_parent_data, 0);
+AML_CLK_DIV_RW(hcodec_1_div, VDEC3_CLK_CTRL, 0, 7, NULL, 0,
+ &hcodec_1_sel.hw, CLK_SET_RATE_PARENT);
+AML_CLK_GATE_RW(hcodec_1, VDEC3_CLK_CTRL, 8, 0,
+ &hcodec_1_div.hw, CLK_SET_RATE_PARENT);
+
+static const struct clk_parent_data hcodec_parent_data[] = {
+ { .hw = &hcodec_0.hw },
+ { .hw = &hcodec_1.hw }
+};
+
+AML_CLK_MUX_RW(hcodec, VDEC3_CLK_CTRL, 0x1, 15,
+ NULL, 0, hcodec_parent_data, 0);
+
+static const struct clk_parent_data vc9000e_parent_data[] = {
+ { .fw_name = "xtal" },
+ { .fw_name = "fclk_div4" },
+ { .fw_name = "fclk_div3" },
+ { .fw_name = "fclk_div5" },
+ { .fw_name = "fclk_div7" },
+ { .fw_name = "fclk_div2p5" },
+ { .fw_name = "hifi_pll" },
+ { .fw_name = "gp0_pll" }
+};
+
+AML_CLK_MUX_RW(vc9000e_aclk_sel, VC9000E_CLK_CTRL, 0x7, 9,
+ NULL, 0, vc9000e_parent_data, 0);
+AML_CLK_DIV_RW(vc9000e_aclk_div, VC9000E_CLK_CTRL, 0, 7, NULL, 0,
+ &vc9000e_aclk_sel.hw, CLK_SET_RATE_PARENT);
+AML_CLK_GATE_RW(vc9000e_aclk, VC9000E_CLK_CTRL, 8, 0,
+ &vc9000e_aclk_div.hw, CLK_SET_RATE_PARENT);
+
+AML_CLK_MUX_RW(vc9000e_core_sel, VC9000E_CLK_CTRL, 0x7, 25,
+ NULL, 0, vc9000e_parent_data, 0);
+AML_CLK_DIV_RW(vc9000e_core_div, VC9000E_CLK_CTRL, 16, 7, NULL, 0,
+ &vc9000e_core_sel.hw, CLK_SET_RATE_PARENT);
+AML_CLK_GATE_RW(vc9000e_core, VC9000E_CLK_CTRL, 24, 0,
+ &vc9000e_core_div.hw, CLK_SET_RATE_PARENT);
+
+static u32 csi_phy_parent_table[] = { 0, 1, 2, 3, 4, 5, 7 };
+static const struct clk_parent_data csi_phy_parent_data[] = {
+ { .fw_name = "fclk_div2p5" },
+ { .fw_name = "fclk_div3" },
+ { .fw_name = "fclk_div4" },
+ { .fw_name = "fclk_div5" },
+ { .fw_name = "gp0_pll" },
+ { .fw_name = "hifi_pll" },
+ { .fw_name = "xtal" }
+};
+
+AML_CLK_MUX_RW(csi_phy0_sel, ISP0_CLK_CTRL, 0x7, 25,
+ csi_phy_parent_table, 0, csi_phy_parent_data, 0);
+AML_CLK_DIV_RW(csi_phy0_div, ISP0_CLK_CTRL, 16, 7, NULL, 0,
+ &csi_phy0_sel.hw, CLK_SET_RATE_PARENT);
+AML_CLK_GATE_RW(csi_phy0, ISP0_CLK_CTRL, 24, 0,
+ &csi_phy0_div.hw, CLK_SET_RATE_PARENT);
+
+static u32 dewarpa_parent_table[] = { 0, 1, 2, 3, 4, 5, 7 };
+static const struct clk_parent_data dewarpa_parent_data[] = {
+ { .fw_name = "fclk_div2p5" },
+ { .fw_name = "fclk_div3" },
+ { .fw_name = "fclk_div4" },
+ { .fw_name = "fclk_div5" },
+ { .fw_name = "gp0_pll" },
+ { .fw_name = "hifi_pll" },
+ { .fw_name = "fclk_div7" }
+};
+
+AML_CLK_MUX_RW(dewarpa_sel, DEWARPA_CLK_CTRL, 0x7, 9,
+ dewarpa_parent_table, 0, dewarpa_parent_data, 0);
+AML_CLK_DIV_RW(dewarpa_div, DEWARPA_CLK_CTRL, 0, 7, NULL, 0,
+ &dewarpa_sel.hw, CLK_SET_RATE_PARENT);
+AML_CLK_GATE_RW(dewarpa, DEWARPA_CLK_CTRL, 8, 0,
+ &dewarpa_div.hw, CLK_SET_RATE_PARENT);
+
+static u32 isp_parent_table[] = { 0, 1, 2, 3, 4, 5, 7 };
+static const struct clk_parent_data isp_parent_data[] = {
+ { .fw_name = "fclk_div2p5" },
+ { .fw_name = "fclk_div3" },
+ { .fw_name = "fclk_div4" },
+ { .fw_name = "fclk_div5" },
+ { .fw_name = "gp0_pll" },
+ { .fw_name = "hifi_pll" },
+ { .fw_name = "xtal" }
+};
+
+AML_CLK_MUX_RW(isp0_sel, ISP0_CLK_CTRL, 0x7, 9,
+ isp_parent_table, 0, isp_parent_data, 0);
+AML_CLK_DIV_RW(isp0_div, ISP0_CLK_CTRL, 0, 7, NULL, 0,
+ &isp0_sel.hw, CLK_SET_RATE_PARENT);
+AML_CLK_GATE_RW(isp0, ISP0_CLK_CTRL, 8, 0,
+ &isp0_div.hw, CLK_SET_RATE_PARENT);
+
+static u32 nna_core_parent_table[] = { 0, 1, 2, 3, 4, 5, 7 };
+static const struct clk_parent_data nna_core_parent_data[] = {
+ { .fw_name = "xtal" },
+ { .fw_name = "fclk_div2p5" },
+ { .fw_name = "fclk_div4" },
+ { .fw_name = "fclk_div3" },
+ { .fw_name = "fclk_div5" },
+ { .fw_name = "fclk_div2" },
+ { .fw_name = "hifi_pll" }
+};
+
+AML_CLK_MUX_RW(nna_core_sel, NNA_CLK_CTRL, 0x7, 9,
+ nna_core_parent_table, 0, nna_core_parent_data, 0);
+AML_CLK_DIV_RW(nna_core_div, NNA_CLK_CTRL, 0, 7, NULL, 0,
+ &nna_core_sel.hw, CLK_SET_RATE_PARENT);
+AML_CLK_GATE_RW(nna_core, NNA_CLK_CTRL, 8, 0,
+ &nna_core_div.hw, CLK_SET_RATE_PARENT);
+
+static const struct clk_parent_data ge2d_parent_data[] = {
+ { .fw_name = "xtal" },
+ { .fw_name = "fclk_div2p5" },
+ { .fw_name = "fclk_div3" },
+ { .fw_name = "fclk_div4" },
+ { .fw_name = "hifi_pll" },
+ { .fw_name = "fclk_div5" },
+ { .fw_name = "gp0_pll" },
+ { .hw = &rtc_clk.hw }
+};
+
+AML_CLK_MUX_RW(ge2d_sel, GE2D_CLK_CTRL, 0x7, 9,
+ NULL, 0, ge2d_parent_data, 0);
+AML_CLK_DIV_RW(ge2d_div, GE2D_CLK_CTRL, 0, 7, NULL, 0,
+ &ge2d_sel.hw, CLK_SET_RATE_PARENT);
+AML_CLK_GATE_RW(ge2d, GE2D_CLK_CTRL, 8, 0,
+ &ge2d_div.hw, CLK_SET_RATE_PARENT);
+
+static u32 c3_vapb_parent_table[] = { 0, 1, 2, 3, 4, 5, 7 };
+static const struct clk_parent_data vapb_parent_data[] = {
+ { .fw_name = "fclk_div2p5" },
+ { .fw_name = "fclk_div3" },
+ { .fw_name = "fclk_div4" },
+ { .fw_name = "fclk_div5" },
+ { .fw_name = "gp0_pll" },
+ { .fw_name = "hifi_pll" },
+ { .fw_name = "xtal" }
+};
+
+AML_CLK_MUX_RW(vapb_sel, VAPB_CLK_CTRL, 0x7, 9,
+ c3_vapb_parent_table, 0, vapb_parent_data, 0);
+AML_CLK_DIV_RW(vapb_div, VAPB_CLK_CTRL, 0, 7, NULL, 0,
+ &vapb_sel.hw, CLK_SET_RATE_PARENT);
+AML_CLK_GATE_RW(vapb, VAPB_CLK_CTRL, 8, 0,
+ &vapb_div.hw, CLK_SET_RATE_PARENT);
+
+static struct clk_hw *c3_periphs_hw_clks[] = {
+ [CLKID_PLL_IN] = &pll_in.hw,
+ [CLKID_MCLK_PLL_IN] = &mclk_pll_in.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] = ð_125m_div.hw,
+ [CLKID_ETH_125M] = ð_125m.hw,
+ [CLKID_ETH_RMII_DIV] = ð_rmii_div.hw,
+ [CLKID_ETH_RMII] = ð_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_in,
+ &mclk_pll_in,
+ &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,
+ ð_125m,
+ ð_rmii_div,
+ ð_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",
+ },
+ {}
+};
+
+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");
diff --git a/drivers/clk/meson/c3-peripherals.h b/drivers/clk/meson/c3-peripherals.h
new file mode 100644
index 000000000000..ddcc23e25669
--- /dev/null
+++ b/drivers/clk/meson/c3-peripherals.h
@@ -0,0 +1,48 @@
+/* SPDX-License-Identifier: (GPL-2.0-only OR MIT) */
+/*
+ * Copyright (c) 2023 Amlogic, inc.
+ * Author: Chuan Liu <[email protected]>
+ */
+
+#ifndef __AML_C3_PERIPHERALS_H__
+#define __AML_C3_PERIPHERALS_H__
+
+#define OSCIN_CTRL 0x0004
+#define RTC_BY_OSCIN_CTRL0 0x0008
+#define RTC_BY_OSCIN_CTRL1 0x000c
+#define RTC_CTRL 0x0010
+#define SYS_CLK_CTRL0 0x0040
+#define SYS_CLK_EN0_REG0 0x0044
+#define SYS_CLK_EN0_REG1 0x0048
+#define SYS_CLK_EN0_REG2 0x004c
+#define AXI_CLK_CTRL0 0x006c
+#define CLK12_24_CTRL 0x00a8
+#define AXI_CLK_EN0 0x00ac
+#define VDIN_MEAS_CLK_CTRL 0x00f8
+#define VAPB_CLK_CTRL 0x00fc
+#define MIPIDSI_PHY_CLK_CTRL 0x0104
+#define GE2D_CLK_CTRL 0x010c
+#define ISP0_CLK_CTRL 0x0110
+#define DEWARPA_CLK_CTRL 0x0114
+#define VOUTENC_CLK_CTRL 0x0118
+#define VDEC_CLK_CTRL 0x0140
+#define VDEC3_CLK_CTRL 0x0148
+#define TS_CLK_CTRL 0x0158
+#define ETH_CLK_CTRL 0x0164
+#define NAND_CLK_CTRL 0x0168
+#define SD_EMMC_CLK_CTRL 0x016c
+#define SPICC_CLK_CTRL 0x0174
+#define GEN_CLK_CTRL 0x0178
+#define SAR_CLK_CTRL0 0x017c
+#define PWM_CLK_AB_CTRL 0x0180
+#define PWM_CLK_CD_CTRL 0x0184
+#define PWM_CLK_EF_CTRL 0x0188
+#define PWM_CLK_GH_CTRL 0x018c
+#define PWM_CLK_IJ_CTRL 0x0190
+#define PWM_CLK_KL_CTRL 0x0194
+#define PWM_CLK_MN_CTRL 0x0198
+#define VC9000E_CLK_CTRL 0x019c
+#define SPIFC_CLK_CTRL 0x01a0
+#define NNA_CLK_CTRL 0x0220
+
+#endif /* __AML_C3_PERIPHERALS_H__ */
--
2.37.1
On Thu, 28 Sep 2023 14:34:46 +0800, Xianwei Zhao wrote:
> Add the peripherals clock controller dt-bindings for Amlogic C3 SoC family
>
> Signed-off-by: Xianwei Zhao <[email protected]>
> ---
> .../clock/amlogic,c3-peripherals-clkc.yaml | 86 +++++++
> .../clock/amlogic,c3-peripherals-clkc.h | 230 ++++++++++++++++++
> 2 files changed, 316 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
>
My bot found errors running 'make DT_CHECKER_FLAGS=-m dt_binding_check'
on your patch (DT_CHECKER_FLAGS is new in v5.13):
yamllint warnings/errors:
dtschema/dtc warnings/errors:
/builds/robherring/dt-review-ci/linux/Documentation/devicetree/bindings/clock/amlogic,c3-peripherals-clkc.yaml: properties:clocks: 'oneOf' conditional failed, one must be fixed:
[{'description': 'input oscillator (usually at 24MHz)'}, {'description': 'input fixed pll'}, {'description': 'input fixed pll div2'}, {'description': 'input fixed pll div2p5'}, {'description': 'input fixed pll div3'}, {'description': 'input fixed pll div4'}, {'description': 'input fixed pll div5'}, {'description': 'input fixed pll div7'}, {'description': 'input gp0 pll'}, {'description': 'input hifi pll'}] is too long
[{'description': 'input oscillator (usually at 24MHz)'}, {'description': 'input fixed pll'}, {'description': 'input fixed pll div2'}, {'description': 'input fixed pll div2p5'}, {'description': 'input fixed pll div3'}, {'description': 'input fixed pll div4'}, {'description': 'input fixed pll div5'}, {'description': 'input fixed pll div7'}, {'description': 'input gp0 pll'}, {'description': 'input hifi pll'}] is too short
False schema does not allow 10
1 was expected
10 is greater than the maximum of 2
10 is greater than the maximum of 3
10 is greater than the maximum of 4
10 is greater than the maximum of 5
10 is greater than the maximum of 6
10 is greater than the maximum of 7
10 is greater than the maximum of 8
10 is greater than the maximum of 9
hint: "minItems" is only needed if less than the "items" list length
from schema $id: http://devicetree.org/meta-schemas/items.yaml#
/builds/robherring/dt-review-ci/linux/Documentation/devicetree/bindings/clock/amlogic,c3-peripherals-clkc.yaml: properties:clock-names: 'oneOf' conditional failed, one must be fixed:
[{'const': 'xtal'}, {'const': 'fixed_pll'}, {'const': 'fclk_div2'}, {'const': 'fclk_div2p5'}, {'const': 'fclk_div3'}, {'const': 'fclk_div4'}, {'const': 'fclk_div5'}, {'const': 'fclk_div7'}, {'const': 'gp0_pll'}, {'const': 'hifi_pll'}] is too long
[{'const': 'xtal'}, {'const': 'fixed_pll'}, {'const': 'fclk_div2'}, {'const': 'fclk_div2p5'}, {'const': 'fclk_div3'}, {'const': 'fclk_div4'}, {'const': 'fclk_div5'}, {'const': 'fclk_div7'}, {'const': 'gp0_pll'}, {'const': 'hifi_pll'}] is too short
False schema does not allow 10
1 was expected
10 is greater than the maximum of 2
10 is greater than the maximum of 3
10 is greater than the maximum of 4
10 is greater than the maximum of 5
10 is greater than the maximum of 6
10 is greater than the maximum of 7
10 is greater than the maximum of 8
10 is greater than the maximum of 9
hint: "minItems" is only needed if less than the "items" list length
from schema $id: http://devicetree.org/meta-schemas/items.yaml#
Error: Documentation/devicetree/bindings/clock/amlogic,c3-peripherals-clkc.example.dts:23.31-32 syntax error
FATAL ERROR: Unable to parse input tree
make[2]: *** [scripts/Makefile.lib:419: Documentation/devicetree/bindings/clock/amlogic,c3-peripherals-clkc.example.dtb] Error 1
make[2]: *** Waiting for unfinished jobs....
make[1]: *** [/builds/robherring/dt-review-ci/linux/Makefile:1427: dt_binding_check] Error 2
make: *** [Makefile:234: __sub-make] Error 2
doc reference errors (make refcheckdocs):
See https://patchwork.ozlabs.org/project/devicetree-bindings/patch/[email protected]
The base for the series is generally the latest rc1. A different dependency
should be noted in *this* patch.
If you already ran 'make dt_binding_check' and didn't see the above
error(s), then make sure 'yamllint' is installed and dt-schema is up to
date:
pip3 install dtschema --upgrade
Please check and re-submit after running the above command yourself. Note
that DT_SCHEMA_FILES can be set to your schema file to speed up checking
your schema. However, it must be unset to test all examples with your schema.
Hi Xianwei,
kernel test robot noticed the following build warnings:
[auto build test WARNING on 57b55c76aaf1ba50ecc6dcee5cd6843dc4d85239]
url: https://github.com/intel-lab-lkp/linux/commits/Xianwei-Zhao/dt-bindings-clock-add-Amlogic-C3-PLL-clock-controller-bindings/20230928-143707
base: 57b55c76aaf1ba50ecc6dcee5cd6843dc4d85239
patch link: https://lore.kernel.org/r/20230928063448.3544464-3-xianwei.zhao%40amlogic.com
patch subject: [PATCH 2/4] dt-bindings: clock: add Amlogic C3 peripherals clock controller bindings
compiler: loongarch64-linux-gcc (GCC) 13.2.0
reproduce: (https://download.01.org/0day-ci/archive/20230928/[email protected]/reproduce)
If you fix the issue in a separate patch/commit (i.e. not just a new version of
the same patch/commit), kindly add following tags
| Reported-by: kernel test robot <[email protected]>
| Closes: https://lore.kernel.org/oe-kbuild-all/[email protected]/
dtcheck warnings: (new ones prefixed by >>)
>> Documentation/devicetree/bindings/clock/amlogic,c3-pll-clkc.yaml:2:1: [error] missing document start "---" (document-start)
>> Documentation/devicetree/bindings/clock/amlogic,c3-pll-clkc.yaml:50:1: [error] syntax error: found character '\t' that cannot start any token (syntax)
--
>> Documentation/devicetree/bindings/clock/amlogic,c3-pll-clkc.yaml:4:1: but found another document
>> Documentation/devicetree/bindings/clock/amlogic,c3-peripherals-clkc.yaml: properties:clocks: 'oneOf' conditional failed, one must be fixed:
[{'description': 'input oscillator (usually at 24MHz)'}, {'description': 'input fixed pll'}, {'description': 'input fixed pll div2'}, {'description': 'input fixed pll div2p5'}, {'description': 'input fixed pll div3'}, {'description': 'input fixed pll div4'}, {'description': 'input fixed pll div5'}, {'description': 'input fixed pll div7'}, {'description': 'input gp0 pll'}, {'description': 'input hifi pll'}] is too long
[{'description': 'input oscillator (usually at 24MHz)'}, {'description': 'input fixed pll'}, {'description': 'input fixed pll div2'}, {'description': 'input fixed pll div2p5'}, {'description': 'input fixed pll div3'}, {'description': 'input fixed pll div4'}, {'description': 'input fixed pll div5'}, {'description': 'input fixed pll div7'}, {'description': 'input gp0 pll'}, {'description': 'input hifi pll'}] is too short
False schema does not allow 10
1 was expected
10 is greater than the maximum of 2
10 is greater than the maximum of 3
10 is greater than the maximum of 4
10 is greater than the maximum of 5
10 is greater than the maximum of 6
10 is greater than the maximum of 7
10 is greater than the maximum of 8
10 is greater than the maximum of 9
hint: "minItems" is only needed if less than the "items" list length
from schema $id: http://devicetree.org/meta-schemas/items.yaml#
>> Documentation/devicetree/bindings/clock/amlogic,c3-peripherals-clkc.yaml: properties:clock-names: 'oneOf' conditional failed, one must be fixed:
[{'const': 'xtal'}, {'const': 'fixed_pll'}, {'const': 'fclk_div2'}, {'const': 'fclk_div2p5'}, {'const': 'fclk_div3'}, {'const': 'fclk_div4'}, {'const': 'fclk_div5'}, {'const': 'fclk_div7'}, {'const': 'gp0_pll'}, {'const': 'hifi_pll'}] is too long
[{'const': 'xtal'}, {'const': 'fixed_pll'}, {'const': 'fclk_div2'}, {'const': 'fclk_div2p5'}, {'const': 'fclk_div3'}, {'const': 'fclk_div4'}, {'const': 'fclk_div5'}, {'const': 'fclk_div7'}, {'const': 'gp0_pll'}, {'const': 'hifi_pll'}] is too short
False schema does not allow 10
1 was expected
10 is greater than the maximum of 2
10 is greater than the maximum of 3
10 is greater than the maximum of 4
10 is greater than the maximum of 5
10 is greater than the maximum of 6
10 is greater than the maximum of 7
--
>> Documentation/devicetree/bindings/clock/amlogic,c3-pll-clkc.yaml: ignoring, error parsing file
--
0-DAY CI Kernel Test Service
https://github.com/intel/lkp-tests/wiki
On 28/09/2023 08:34, Xianwei Zhao wrote:
> Add C3 SoC PLLs and Peripheral clock controller dt-bindings.
> Add PLLs and Peripheral clock controller driver for C3 SOC.
>
> 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
>
This was absolutely never tested :(
It does not look like you tested the bindings, at least after quick
look. Please run `make dt_binding_check` (see
Documentation/devicetree/bindings/writing-schema.rst for instructions).
Maybe you need to update your dtschema and yamllint.
Best regards,
Krzysztof
On Thu 28 Sep 2023 at 14:34, Xianwei Zhao <[email protected]> wrote:
> Add the C3 PLL clock controller driver for the Amlogic C3 SoC family.
>
> Signed-off-by: Xianwei Zhao <[email protected]>
> ---
> drivers/clk/meson/Kconfig | 12 +
> drivers/clk/meson/Makefile | 1 +
> drivers/clk/meson/c3-pll.c | 510 +++++++++++++++++++++++++++++++++++++
> drivers/clk/meson/c3-pll.h | 35 +++
> 4 files changed, 558 insertions(+)
> create mode 100644 drivers/clk/meson/c3-pll.c
> create mode 100644 drivers/clk/meson/c3-pll.h
>
> diff --git a/drivers/clk/meson/Kconfig b/drivers/clk/meson/Kconfig
> index c5303e4c1604..76be4bbd2afb 100644
> --- a/drivers/clk/meson/Kconfig
> +++ b/drivers/clk/meson/Kconfig
> @@ -128,6 +128,18 @@ 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"
> + 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, AW409 and AW419.
> + 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..5244dc19ab6e
> --- /dev/null
> +++ b/drivers/clk/meson/c3-pll.c
> @@ -0,0 +1,510 @@
> +// SPDX-License-Identifier: GPL-2.0-only
> +/*
> + * Amlogic C3 PLL Controller Driver
> + *
> + * Copyright (c) 2023 Amlogic, inc.
> + * Author: Chuan Liu <[email protected]>
If Chuan is Author, shouldn't get his Signed-off-by ?
Maybe Co-developed-by as well ?
> + */
> +
> +#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 "c3-pll.h"
> +#include "meson-clkc-utils.h"
> +#include <dt-bindings/clock/amlogic,c3-pll-clkc.h>
> +
> +#define MEMBER_REG_PARM(_member_name, _reg, _shift, _width) \
> + ._member_name = { \
> + .reg_off = _reg, \
> + .shift = _shift, \
> + .width = _width, \
> +}
> +
> +#define __AML_CLK_PLL(_name, _en_reg, _en_shift, _en_width, \
> + _m_reg, _m_shift, _m_width, \
> + _f_reg, _f_shift, _f_width, \
> + _n_reg, _n_shift, _n_width, \
> + _l_reg, _l_shift, _l_width, \
> + _r_reg, _r_shift, _r_width, \
> + _init_reg, _init_reg_cnt, _range, _table, \
> + _dflags, _ops, _pname, _pdata, _phw, _iflags) \
> +static struct clk_regmap _name = { \
> + .data = &(struct meson_clk_pll_data){ \
> + MEMBER_REG_PARM(en, \
> + _en_reg, _en_shift, _en_width), \
> + MEMBER_REG_PARM(m, \
> + _m_reg, _m_shift, _m_width), \
> + MEMBER_REG_PARM(frac, \
> + _f_reg, _f_shift, _f_width), \
> + MEMBER_REG_PARM(n, \
> + _n_reg, _n_shift, _n_width), \
> + MEMBER_REG_PARM(l, \
> + _l_reg, _l_shift, _l_width), \
> + MEMBER_REG_PARM(rst, \
> + _r_reg, _r_shift, _r_width), \
> + .range = _range, \
> + .table = _table, \
> + .init_regs = _init_reg, \
> + .init_count = _init_reg_cnt, \
> + .flags = _dflags, \
> + }, \
> + .hw.init = &(struct clk_init_data){ \
> + .name = #_name, \
> + .ops = _ops, \
> + .parent_names = _pname, \
> + .parent_data = _pdata, \
> + .parent_hws = (const struct clk_hw *[]) {_phw}, \
> + .num_parents = 1, \
> + .flags = _iflags, \
> + }, \
> +}
> +
> +#define __AML_CLK_MUX(_name, _reg, _mask, _shift, _table, _dflags, \
> + _ops, _pname, _pdata, _phw, _pnub, _iflags) \
> +static struct clk_regmap _name = { \
> + .data = &(struct clk_regmap_mux_data){ \
> + .offset = _reg, \
> + .mask = _mask, \
> + .shift = _shift, \
> + .table = _table, \
> + .flags = _dflags, \
> + }, \
> + .hw.init = &(struct clk_init_data){ \
> + .name = #_name, \
> + .ops = _ops, \
> + .parent_names = _pname, \
> + .parent_data = _pdata, \
> + .parent_hws = (const struct clk_hw *[]) { _phw }, \
> + .num_parents = _pnub, \
> + .flags = _iflags, \
> + }, \
> +}
> +
> +#define __AML_CLK_DIV(_name, _reg, _shift, _width, _table, _dflags, \
> + _ops, _pname, _pdata, _phw, _iflags) \
> +static struct clk_regmap _name = { \
> + .data = &(struct clk_regmap_div_data){ \
> + .offset = _reg, \
> + .shift = _shift, \
> + .width = _width, \
> + .table = _table, \
> + .flags = _dflags, \
> + }, \
> + .hw.init = &(struct clk_init_data){ \
> + .name = #_name, \
> + .ops = _ops, \
> + .parent_names = _pname, \
> + .parent_data = _pdata, \
> + .parent_hws = (const struct clk_hw *[]) { _phw }, \
> + .num_parents = 1, \
> + .flags = _iflags, \
> + }, \
> +}
> +
> +#define __AML_CLK_GATE(_name, _reg, _bit, _gflags, \
> + _ops, _pname, _pdata, _phw, _iflags) \
> +static struct clk_regmap _name = { \
> + .data = &(struct clk_regmap_gate_data){ \
> + .offset = _reg, \
> + .bit_idx = _bit, \
> + .flags = _gflags, \
> + }, \
> + .hw.init = &(struct clk_init_data) { \
> + .name = #_name, \
> + .ops = _ops, \
> + .parent_names = _pname, \
> + .parent_data = _pdata, \
> + .parent_hws = (const struct clk_hw *[]) { _phw }, \
> + .num_parents = 1, \
> + .flags = _iflags, \
> + }, \
> +}
> +
> +#define __AML_CLK_FIXED_FACTOR(_name, _mult, _div, _ops, \
> + _pname, _pdata, _phw, _iflags) \
> + static struct clk_fixed_factor _name = { \
> + .mult = _mult, \
> + .div = _div, \
> + .hw.init = &(struct clk_init_data){ \
> + .name = #_name, \
> + .ops = _ops, \
> + .parent_names = _pname, \
> + .parent_data = _pdata, \
> + .parent_hws = (const struct clk_hw *[]) { _phw }, \
> + .num_parents = 1, \
> + .flags = _iflags, \
> + }, \
> +}
> +
> +#define AML_CLK_PLL_RW(_name, _en_reg, _en_shift, _en_width, \
> + _m_reg, _m_shift, _m_width, \
> + _f_reg, _f_shift, _f_width, \
> + _n_reg, _n_shift, _n_width, \
> + _l_reg, _l_shift, _l_width, \
> + _r_reg, _r_shift, _r_width, \
> + _init_reg, _init_reg_cnt, _range, _table, _dflags,\
> + _pdata, _iflags) \
> + __AML_CLK_PLL(_name, _en_reg, _en_shift, _en_width, \
> + _m_reg, _m_shift, _m_width, \
> + _f_reg, _f_shift, _f_width, \
> + _n_reg, _n_shift, _n_width, \
> + _l_reg, _l_shift, _l_width, \
> + _r_reg, _r_shift, _r_width, \
> + _init_reg, _init_reg_cnt, _range, _table, \
> + _dflags, &meson_clk_pll_ops, \
> + NULL, _pdata, NULL, _iflags)
> +
> +#define AML_CLK_PLL_RO(_name, _en_reg, _en_shift, _en_width, \
> + _m_reg, _m_shift, _m_width, \
> + _f_reg, _f_shift, _f_width, \
> + _n_reg, _n_shift, _n_width, \
> + _l_reg, _l_shift, _l_width, \
> + _r_reg, _r_shift, _r_width, \
> + _init_reg, _init_reg_cnt, _range, _table, \
> + _dflags, _pdata, _iflags) \
> + __AML_CLK_PLL(_name, _en_reg, _en_shift, _en_width, \
> + _m_reg, _m_shift, _m_width, \
> + _f_reg, _f_shift, _f_width, \
> + _n_reg, _n_shift, _n_width, \
> + _l_reg, _l_shift, _l_width, \
> + _r_reg, _r_shift, _r_width, \
> + _init_reg, _init_reg_cnt, _range, _table, \
> + _dflags, &meson_clk_pll_ro_ops, \
> + NULL, _pdata, NULL, _iflags)
> +
> +#define AML_CLK_MUX_RW(_name, _reg, _mask, _shift, _table, _dflags, \
> + _pdata, _iflags) \
> + __AML_CLK_MUX(_name, _reg, _mask, _shift, _table, _dflags, \
> + &clk_regmap_mux_ops, NULL, _pdata, NULL, \
> + ARRAY_SIZE(_pdata), _iflags)
> +
> +#define AML_CLK_DIV_RW(_name, _reg, _shift, _width, _table, _dflags, \
> + _phw, _iflags) \
> + __AML_CLK_DIV(_name, _reg, _shift, _width, _table, _dflags, \
> + &clk_regmap_divider_ops, NULL, NULL, \
> + _phw, _iflags)
> +
> +#define AML_CLK_DIV_RO(_name, _reg, _shift, _width, _table, _dflags, \
> + _phw, _iflags) \
> + __AML_CLK_DIV(_name, _reg, _shift, _width, _table, _dflags, \
> + &clk_regmap_divider_ro_ops, NULL, NULL, \
> + _phw, _iflags)
> +
> +#define AML_CLK_GATE_RW(_name, _reg, _bit, _dflags, _phw, _iflags) \
> + __AML_CLK_GATE(_name, _reg, _bit, _dflags, \
> + &clk_regmap_gate_ops, NULL, NULL, _phw, \
> + _iflags)
> +
> +#define AML_CLK_GATE_RO(_name, _reg, _bit, _dflags, _phw, _iflags) \
> + __AML_CLK_GATE(_name, _reg, _bit, _dflags, \
> + &clk_regmap_gate_ro_ops, NULL, NULL, _phw, \
> + _iflags)
> +
> +#define AML_CLK_FIXED_FACTOR(_name, _mult, _div, _phw, _iflags) \
> + __AML_CLK_FIXED_FACTOR(_name, _mult, _div, \
> + &clk_fixed_factor_ops, NULL, NULL, \
> + _phw, _iflags)
> +
I don't get why all these macro are needed ? I don't see a 10 instances
of the very same clock that would justify this.
It makes this driver borderline un-reviewable.
Unless you can provide a very reason why it is better like this, please
have a look a the a1 and s4 controllers and re-submit.
Same goes for patch #4
> +static const struct clk_parent_data pll_dco_parent = {
> + .fw_name = "pll_in",
> +};
> +
> +static const struct clk_parent_data mclk_pll_dco_parent = {
> + .fw_name = "mclk_pll_in",
> +};
> +
> +AML_CLK_PLL_RO(fixed_pll_dco, ANACTRL_FIXPLL_CTRL0, 28, 1, /* en */
> + ANACTRL_FIXPLL_CTRL0, 0, 8, /* m */
> + 0, 0, 0, /* frac */
> + ANACTRL_FIXPLL_CTRL0, 16, 5, /* n */
> + ANACTRL_FIXPLL_CTRL0, 31, 1, /* lock */
> + ANACTRL_FIXPLL_CTRL0, 29, 1, /* rst */
> + NULL, 0, NULL, NULL, 0, &pll_dco_parent, 0);
> +AML_CLK_DIV_RO(fixed_pll, ANACTRL_FIXPLL_CTRL0, 12, 3, NULL,
> + CLK_DIVIDER_POWER_OF_TWO, &fixed_pll_dco.hw, 0);
> +AML_CLK_FIXED_FACTOR(fclk_div40_div, 1, 40, &fixed_pll.hw, 0);
> +AML_CLK_GATE_RO(fclk_div40, ANACTRL_FIXPLL_CTRL4, 0, 0, &fclk_div40_div.hw, 0);
> +AML_CLK_FIXED_FACTOR(fclk_div2_div, 1, 2, &fixed_pll.hw, 0);
> +AML_CLK_GATE_RO(fclk_div2, ANACTRL_FIXPLL_CTRL4, 24, 0, &fclk_div2_div.hw, 0);
> +AML_CLK_FIXED_FACTOR(fclk_div2p5_div, 2, 5, &fixed_pll.hw, 0);
> +AML_CLK_GATE_RO(fclk_div2p5, ANACTRL_FIXPLL_CTRL4, 4, 0, &fclk_div2p5_div.hw, 0);
> +AML_CLK_FIXED_FACTOR(fclk_div3_div, 1, 3, &fixed_pll.hw, 0);
> +AML_CLK_GATE_RO(fclk_div3, ANACTRL_FIXPLL_CTRL4, 20, 0, &fclk_div3_div.hw, 0);
> +AML_CLK_FIXED_FACTOR(fclk_div4_div, 1, 4, &fixed_pll.hw, 0);
> +AML_CLK_GATE_RO(fclk_div4, ANACTRL_FIXPLL_CTRL4, 21, 0, &fclk_div4_div.hw, 0);
> +AML_CLK_FIXED_FACTOR(fclk_div5_div, 1, 5, &fixed_pll.hw, 0);
> +AML_CLK_GATE_RO(fclk_div5, ANACTRL_FIXPLL_CTRL4, 22, 0, &fclk_div5_div.hw, 0);
> +AML_CLK_FIXED_FACTOR(fclk_div7_div, 1, 7, &fixed_pll.hw, 0);
> +AML_CLK_GATE_RO(fclk_div7, ANACTRL_FIXPLL_CTRL4, 23, 0, &fclk_div7_div.hw, 0);
> +
> +static const struct reg_sequence c3_gp0_init_regs[] = {
> + { .reg = ANACTRL_GP0PLL_CTRL1, .def = 0x0 },
> + { .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, .delay_us = 10 },
> + { .reg = ANACTRL_GP0PLL_CTRL0, .def = 0x080304fa },
> + { .reg = ANACTRL_GP0PLL_CTRL0, .def = 0x380304fa, .delay_us = 10 },
> + { .reg = ANACTRL_GP0PLL_CTRL0, .def = 0X180304fa }
> +};
> +
> +static const struct pll_params_table c3_gp0_pll_params_table[] = {
> + PLL_PARAMS(150, 1), /* DCO = 3600M */
> + PLL_PARAMS(130, 1), /* DCO = 3120M */
> + PLL_PARAMS(192, 1), /* DCO = 4608M */
> + PLL_PARAMS(125, 1), /* DCO = 3000M */
> + { /* sentinel */ }
> +};
> +
> +/* 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 */ }
> +};
> +
> +AML_CLK_PLL_RW(gp0_pll_dco, ANACTRL_GP0PLL_CTRL0, 28, 1, /* en */
> + ANACTRL_GP0PLL_CTRL0, 0, 9, /* m */
> + ANACTRL_GP0PLL_CTRL1, 0, 19, /* frac */
> + ANACTRL_GP0PLL_CTRL0, 10, 5, /* n */
> + ANACTRL_GP0PLL_CTRL0, 31, 1, /* lock */
> + ANACTRL_GP0PLL_CTRL0, 29, 1, /* rst */
> + c3_gp0_init_regs, ARRAY_SIZE(c3_gp0_init_regs),
> + NULL, c3_gp0_pll_params_table, 0,
> + &pll_dco_parent, 0);
> +AML_CLK_DIV_RW(gp0_pll, ANACTRL_GP0PLL_CTRL0, 16, 3,
> + c3_gp0_pll_od_table, 0,
> + &gp0_pll_dco.hw, CLK_SET_RATE_PARENT);
> +
> +static const struct reg_sequence c3_hifi_init_regs[] = {
> + { .reg = ANACTRL_HIFIPLL_CTRL0, .def = 0x08010496 },
> + { .reg = ANACTRL_HIFIPLL_CTRL0, .def = 0x38010496 },
> + { .reg = ANACTRL_HIFIPLL_CTRL1, .def = 0x0000ce40 },
> + { .reg = ANACTRL_HIFIPLL_CTRL2, .def = 0x00000000 },
> + { .reg = ANACTRL_HIFIPLL_CTRL3, .def = 0x6a285c00 },
> + { .reg = ANACTRL_HIFIPLL_CTRL4, .def = 0x65771290 },
> + { .reg = ANACTRL_HIFIPLL_CTRL5, .def = 0x3927200a },
> + { .reg = ANACTRL_HIFIPLL_CTRL6, .def = 0x56540000, .delay_us = 50 },
> + { .reg = ANACTRL_HIFIPLL_CTRL0, .def = 0x18010496, .delay_us = 20 },
> +};
> +
> +static const struct pll_params_table c3_hifi_pll_params_table[] = {
> + PLL_PARAMS(150, 1), /* DCO = 3600M */
> + PLL_PARAMS(130, 1), /* DCO = 3120M */
> + PLL_PARAMS(192, 1), /* DCO = 4608M */
> + PLL_PARAMS(125, 1), /* DCO = 3000M */
> + { /* sentinel */ }
> +};
> +
> +AML_CLK_PLL_RW(hifi_pll_dco, ANACTRL_HIFIPLL_CTRL0, 28, 1, /* en */
> + ANACTRL_HIFIPLL_CTRL0, 0, 8, /* m */
> + ANACTRL_HIFIPLL_CTRL1, 0, 19, /* frac */
> + ANACTRL_HIFIPLL_CTRL0, 10, 5, /* n */
> + ANACTRL_HIFIPLL_CTRL0, 31, 1, /* lock */
> + ANACTRL_HIFIPLL_CTRL0, 29, 1, /* rst */
> + c3_hifi_init_regs, ARRAY_SIZE(c3_hifi_init_regs),
> + NULL, c3_hifi_pll_params_table, 0,
> + &pll_dco_parent, 0);
> +AML_CLK_DIV_RW(hifi_pll, ANACTRL_HIFIPLL_CTRL0, 16, 2,
> + NULL, CLK_DIVIDER_POWER_OF_TWO,
> + &hifi_pll_dco.hw, CLK_SET_RATE_PARENT);
> +
> +static const struct reg_sequence c3_mclk_init_regs[] = {
> + { .reg = ANACTRL_MPLL_CTRL0, .def = 0x20011063 },
> + { .reg = ANACTRL_MPLL_CTRL0, .def = 0x30011063 },
> + { .reg = ANACTRL_MPLL_CTRL1, .def = 0x1420500f },
> + { .reg = ANACTRL_MPLL_CTRL2, .def = 0x00023041 },
> + { .reg = ANACTRL_MPLL_CTRL3, .def = 0x18180000 },
> + { .reg = ANACTRL_MPLL_CTRL0, .def = 0x10011063 },
> + { .reg = ANACTRL_MPLL_CTRL2, .def = 0x00023001 }
> +};
> +
> +static const struct pll_params_table c3_mclk_pll_params_table[] = {
> + PLL_PARAMS(99, 1), /* VCO = 2376M */
> + { /* sentinel */ }
> +};
> +
> +static const struct clk_div_table c3_mpll_od_table[] = {
> + { 0, 1 },
> + { 1, 2 },
> + { 2, 4 },
> + { 3, 8 },
> + { 4, 16 },
> + { /* sentinel */ }
> +};
> +
> +AML_CLK_PLL_RW(mclk_pll_dco, ANACTRL_MPLL_CTRL0, 28, 1, /* en */
> + ANACTRL_MPLL_CTRL0, 0, 8, /* m */
> + 0, 0, 0, /* frac */
> + ANACTRL_MPLL_CTRL0, 16, 5, /* n */
> + ANACTRL_MPLL_CTRL0, 31, 1, /* lock */
> + ANACTRL_MPLL_CTRL0, 29, 1, /* rst */
> + c3_mclk_init_regs, ARRAY_SIZE(c3_mclk_init_regs),
> + NULL, c3_mclk_pll_params_table, 0,
> + &mclk_pll_dco_parent, 0);
> +AML_CLK_DIV_RW(mclk_pll, ANACTRL_MPLL_CTRL0, 12, 3,
> + c3_mpll_od_table, 0,
> + &mclk_pll_dco.hw, CLK_SET_RATE_PARENT);
> +AML_CLK_DIV_RW(mclk_pll_clk, ANACTRL_MPLL_CTRL4, 16, 5, NULL,
> + CLK_DIVIDER_ONE_BASED | CLK_DIVIDER_ALLOW_ZERO,
> + &mclk_pll.hw, CLK_SET_RATE_PARENT);
> +
> +static const struct clk_parent_data mclk_parent[] = {
> + { .hw = &mclk_pll_clk.hw },
> + { .fw_name = "mclk_pll_in" },
> + { .hw = &fclk_div40.hw }
> +};
> +
> +AML_CLK_MUX_RW(mclk0_sel, ANACTRL_MPLL_CTRL4, 0x3, 4, NULL, 0,
> + mclk_parent, 0);
> +AML_CLK_GATE_RW(mclk0_sel_out, ANACTRL_MPLL_CTRL4, 1, 0,
> + &mclk0_sel.hw, CLK_SET_RATE_PARENT);
> +AML_CLK_DIV_RW(mclk0_div, ANACTRL_MPLL_CTRL4, 2, 1, NULL, 0,
> + &mclk0_sel_out.hw, CLK_SET_RATE_PARENT);
> +AML_CLK_GATE_RW(mclk0, ANACTRL_MPLL_CTRL4, 0, 0,
> + &mclk0_div.hw, CLK_SET_RATE_PARENT);
> +
> +AML_CLK_MUX_RW(mclk1_sel, ANACTRL_MPLL_CTRL4, 0x3, 12, NULL, 0,
> + mclk_parent, 0);
> +AML_CLK_GATE_RW(mclk1_sel_out, ANACTRL_MPLL_CTRL4, 9, 0,
> + &mclk1_sel.hw, CLK_SET_RATE_PARENT);
> +AML_CLK_DIV_RW(mclk1_div, ANACTRL_MPLL_CTRL4, 10, 1, NULL, 0,
> + &mclk1_sel_out.hw, CLK_SET_RATE_PARENT);
> +AML_CLK_GATE_RW(mclk1, ANACTRL_MPLL_CTRL4, 8, 0,
> + &mclk1_div.hw, 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_DIV40_DIV] = &fclk_div40_div.hw,
> + [CLKID_FCLK_DIV40] = &fclk_div40.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_HIFI_PLL_DCO] = &hifi_pll_dco.hw,
> + [CLKID_HIFI_PLL] = &hifi_pll.hw,
> + [CLKID_MCLK_PLL_DCO] = &mclk_pll_dco.hw,
> + [CLKID_MCLK_PLL] = &mclk_pll.hw,
> + [CLKID_MCLK_PLL_CLK] = &mclk_pll_clk.hw,
> + [CLKID_MCLK0_SEL] = &mclk0_sel.hw,
> + [CLKID_MCLK0_SEL_OUT] = &mclk0_sel_out.hw,
> + [CLKID_MCLK0_DIV] = &mclk0_div.hw,
> + [CLKID_MCLK0] = &mclk0.hw,
> + [CLKID_MCLK1_SEL] = &mclk1_sel.hw,
> + [CLKID_MCLK1_SEL_OUT] = &mclk1_sel_out.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_div40,
> + &fclk_div2,
> + &fclk_div2p5,
> + &fclk_div3,
> + &fclk_div4,
> + &fclk_div5,
> + &fclk_div7,
> + &gp0_pll_dco,
> + &gp0_pll,
> + &hifi_pll_dco,
> + &hifi_pll,
> + &mclk_pll_dco,
> + &mclk_pll,
> + &mclk_pll_clk,
> + &mclk0_sel,
> + &mclk0_sel_out,
> + &mclk0_div,
> + &mclk0,
> + &mclk1_sel,
> + &mclk1_sel_out,
> + &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");
> diff --git a/drivers/clk/meson/c3-pll.h b/drivers/clk/meson/c3-pll.h
> new file mode 100644
> index 000000000000..92a08196a46f
> --- /dev/null
> +++ b/drivers/clk/meson/c3-pll.h
> @@ -0,0 +1,35 @@
> +/* SPDX-License-Identifier: (GPL-2.0-only OR MIT) */
> +/*
> + * Copyright (c) 2023 Amlogic, inc.
> + * Author: Chuan Liu <[email protected]>
> + */
> +
> +#ifndef __AML_C3_PLL_H__
> +#define __AML_C3_PLL_H__
> +
> +#define ANACTRL_FIXPLL_CTRL0 0x0040
> +#define ANACTRL_FIXPLL_CTRL4 0x0050
> +#define ANACTRL_GP0PLL_CTRL0 0x0080
> +#define ANACTRL_GP0PLL_CTRL1 0x0084
> +#define ANACTRL_GP0PLL_CTRL2 0x0088
> +#define ANACTRL_GP0PLL_CTRL3 0x008c
> +#define ANACTRL_GP0PLL_CTRL4 0x0090
> +#define ANACTRL_GP0PLL_CTRL5 0x0094
> +#define ANACTRL_GP0PLL_CTRL6 0x0098
> +#define ANACTRL_GP0PLL_STS 0x009c
> +#define ANACTRL_HIFIPLL_CTRL0 0x0100
> +#define ANACTRL_HIFIPLL_CTRL1 0x0104
> +#define ANACTRL_HIFIPLL_CTRL2 0x0108
> +#define ANACTRL_HIFIPLL_CTRL3 0x010c
> +#define ANACTRL_HIFIPLL_CTRL4 0x0110
> +#define ANACTRL_HIFIPLL_CTRL5 0x0114
> +#define ANACTRL_HIFIPLL_CTRL6 0x0118
> +#define ANACTRL_HIFIPLL_STS 0x011c
> +#define ANACTRL_MPLL_CTRL0 0x0180
> +#define ANACTRL_MPLL_CTRL1 0x0184
> +#define ANACTRL_MPLL_CTRL2 0x0188
> +#define ANACTRL_MPLL_CTRL3 0x018c
> +#define ANACTRL_MPLL_CTRL4 0x0190
> +#define ANACTRL_MPLL_STS 0x01a4
> +
> +#endif /* __AML_C3_PLL_H__ */
Hi Xianwei,
kernel test robot noticed the following build warnings:
[auto build test WARNING on 57b55c76aaf1ba50ecc6dcee5cd6843dc4d85239]
url: https://github.com/intel-lab-lkp/linux/commits/Xianwei-Zhao/dt-bindings-clock-add-Amlogic-C3-PLL-clock-controller-bindings/20230928-143707
base: 57b55c76aaf1ba50ecc6dcee5cd6843dc4d85239
patch link: https://lore.kernel.org/r/20230928063448.3544464-3-xianwei.zhao%40amlogic.com
patch subject: [PATCH 2/4] dt-bindings: clock: add Amlogic C3 peripherals clock controller bindings
compiler: loongarch64-linux-gcc (GCC) 13.2.0
reproduce: (https://download.01.org/0day-ci/archive/20231008/[email protected]/reproduce)
If you fix the issue in a separate patch/commit (i.e. not just a new version of
the same patch/commit), kindly add following tags
| Reported-by: kernel test robot <[email protected]>
| Closes: https://lore.kernel.org/oe-kbuild-all/[email protected]/
dtcheck warnings: (new ones prefixed by >>)
>> Documentation/devicetree/bindings/clock/amlogic,c3-pll-clkc.yaml:2:1: [error] missing document start "---" (document-start)
>> Documentation/devicetree/bindings/clock/amlogic,c3-pll-clkc.yaml:50:1: [error] syntax error: found character '\t' that cannot start any token (syntax)
--
>> Documentation/devicetree/bindings/clock/amlogic,c3-peripherals-clkc.yaml: properties:clocks: 'oneOf' conditional failed, one must be fixed:
[{'description': 'input oscillator (usually at 24MHz)'}, {'description': 'input fixed pll'}, {'description': 'input fixed pll div2'}, {'description': 'input fixed pll div2p5'}, {'description': 'input fixed pll div3'}, {'description': 'input fixed pll div4'}, {'description': 'input fixed pll div5'}, {'description': 'input fixed pll div7'}, {'description': 'input gp0 pll'}, {'description': 'input hifi pll'}] is too long
[{'description': 'input oscillator (usually at 24MHz)'}, {'description': 'input fixed pll'}, {'description': 'input fixed pll div2'}, {'description': 'input fixed pll div2p5'}, {'description': 'input fixed pll div3'}, {'description': 'input fixed pll div4'}, {'description': 'input fixed pll div5'}, {'description': 'input fixed pll div7'}, {'description': 'input gp0 pll'}, {'description': 'input hifi pll'}] is too short
False schema does not allow 10
1 was expected
10 is greater than the maximum of 2
10 is greater than the maximum of 3
10 is greater than the maximum of 4
10 is greater than the maximum of 5
10 is greater than the maximum of 6
10 is greater than the maximum of 7
10 is greater than the maximum of 8
10 is greater than the maximum of 9
hint: "minItems" is only needed if less than the "items" list length
from schema $id: http://devicetree.org/meta-schemas/items.yaml#
>> Documentation/devicetree/bindings/clock/amlogic,c3-peripherals-clkc.yaml: properties:clock-names: 'oneOf' conditional failed, one must be fixed:
[{'const': 'xtal'}, {'const': 'fixed_pll'}, {'const': 'fclk_div2'}, {'const': 'fclk_div2p5'}, {'const': 'fclk_div3'}, {'const': 'fclk_div4'}, {'const': 'fclk_div5'}, {'const': 'fclk_div7'}, {'const': 'gp0_pll'}, {'const': 'hifi_pll'}] is too long
[{'const': 'xtal'}, {'const': 'fixed_pll'}, {'const': 'fclk_div2'}, {'const': 'fclk_div2p5'}, {'const': 'fclk_div3'}, {'const': 'fclk_div4'}, {'const': 'fclk_div5'}, {'const': 'fclk_div7'}, {'const': 'gp0_pll'}, {'const': 'hifi_pll'}] is too short
False schema does not allow 10
1 was expected
10 is greater than the maximum of 2
10 is greater than the maximum of 3
10 is greater than the maximum of 4
10 is greater than the maximum of 5
10 is greater than the maximum of 6
10 is greater than the maximum of 7
10 is greater than the maximum of 8
10 is greater than the maximum of 9
hint: "minItems" is only needed if less than the "items" list length
from schema $id: http://devicetree.org/meta-schemas/items.yaml#
>> Documentation/devicetree/bindings/clock/amlogic,c3-pll-clkc.yaml:4:1: but found another document
--
>> Documentation/devicetree/bindings/clock/amlogic,c3-pll-clkc.yaml: ignoring, error parsing file
--
0-DAY CI Kernel Test Service
https://github.com/intel/lkp-tests/wiki
Hi Krzysztof,
Thanks, I will fix errors of bindings in next version.
On 2023/9/30 23:53, Krzysztof Kozlowski wrote:
> [ EXTERNAL EMAIL ]
>
> On 28/09/2023 08:34, Xianwei Zhao wrote:
>> Add C3 SoC PLLs and Peripheral clock controller dt-bindings.
>> Add PLLs and Peripheral clock controller driver for C3 SOC.
>>
>> 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
>>
>
> This was absolutely never tested :(
>
> It does not look like you tested the bindings, at least after quick
> look. Please run `make dt_binding_check` (see
> Documentation/devicetree/bindings/writing-schema.rst for instructions).
> Maybe you need to update your dtschema and yamllint.
>
> Best regards,
> Krzysztof
>
Hi Jerome,
Thanks for your advise, I will delete marco definition in next
version.
On 2023/10/3 20:55, Jerome Brunet wrote:
> [ EXTERNAL EMAIL ]
>
> On Thu 28 Sep 2023 at 14:34, Xianwei Zhao <[email protected]> wrote:
>
>> Add the C3 PLL clock controller driver for the Amlogic C3 SoC family.
>>
>> Signed-off-by: Xianwei Zhao <[email protected]>
>> ---
>> drivers/clk/meson/Kconfig | 12 +
>> drivers/clk/meson/Makefile | 1 +
>> drivers/clk/meson/c3-pll.c | 510 +++++++++++++++++++++++++++++++++++++
>> drivers/clk/meson/c3-pll.h | 35 +++
>> 4 files changed, 558 insertions(+)
>> create mode 100644 drivers/clk/meson/c3-pll.c
>> create mode 100644 drivers/clk/meson/c3-pll.h
>>
>> diff --git a/drivers/clk/meson/Kconfig b/drivers/clk/meson/Kconfig
>> index c5303e4c1604..76be4bbd2afb 100644
>> --- a/drivers/clk/meson/Kconfig
>> +++ b/drivers/clk/meson/Kconfig
>> @@ -128,6 +128,18 @@ 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"
>> + 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, AW409 and AW419.
>> + 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..5244dc19ab6e
>> --- /dev/null
>> +++ b/drivers/clk/meson/c3-pll.c
>> @@ -0,0 +1,510 @@
>> +// SPDX-License-Identifier: GPL-2.0-only
>> +/*
>> + * Amlogic C3 PLL Controller Driver
>> + *
>> + * Copyright (c) 2023 Amlogic, inc.
>> + * Author: Chuan Liu <[email protected]>
>
> If Chuan is Author, shouldn't get his Signed-off-by ?
> Maybe Co-developed-by as well ?
>
>> + */
>> +
>> +#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 "c3-pll.h"
>> +#include "meson-clkc-utils.h"
>> +#include <dt-bindings/clock/amlogic,c3-pll-clkc.h>
>> +
>> +#define MEMBER_REG_PARM(_member_name, _reg, _shift, _width) \
>> + ._member_name = { \
>> + .reg_off = _reg, \
>> + .shift = _shift, \
>> + .width = _width, \
>> +}
>> +
>> +#define __AML_CLK_PLL(_name, _en_reg, _en_shift, _en_width, \
>> + _m_reg, _m_shift, _m_width, \
>> + _f_reg, _f_shift, _f_width, \
>> + _n_reg, _n_shift, _n_width, \
>> + _l_reg, _l_shift, _l_width, \
>> + _r_reg, _r_shift, _r_width, \
>> + _init_reg, _init_reg_cnt, _range, _table, \
>> + _dflags, _ops, _pname, _pdata, _phw, _iflags) \
>> +static struct clk_regmap _name = { \
>> + .data = &(struct meson_clk_pll_data){ \
>> + MEMBER_REG_PARM(en, \
>> + _en_reg, _en_shift, _en_width), \
>> + MEMBER_REG_PARM(m, \
>> + _m_reg, _m_shift, _m_width), \
>> + MEMBER_REG_PARM(frac, \
>> + _f_reg, _f_shift, _f_width), \
>> + MEMBER_REG_PARM(n, \
>> + _n_reg, _n_shift, _n_width), \
>> + MEMBER_REG_PARM(l, \
>> + _l_reg, _l_shift, _l_width), \
>> + MEMBER_REG_PARM(rst, \
>> + _r_reg, _r_shift, _r_width), \
>> + .range = _range, \
>> + .table = _table, \
>> + .init_regs = _init_reg, \
>> + .init_count = _init_reg_cnt, \
>> + .flags = _dflags, \
>> + }, \
>> + .hw.init = &(struct clk_init_data){ \
>> + .name = #_name, \
>> + .ops = _ops, \
>> + .parent_names = _pname, \
>> + .parent_data = _pdata, \
>> + .parent_hws = (const struct clk_hw *[]) {_phw}, \
>> + .num_parents = 1, \
>> + .flags = _iflags, \
>> + }, \
>> +}
>> +
>> +#define __AML_CLK_MUX(_name, _reg, _mask, _shift, _table, _dflags, \
>> + _ops, _pname, _pdata, _phw, _pnub, _iflags) \
>> +static struct clk_regmap _name = { \
>> + .data = &(struct clk_regmap_mux_data){ \
>> + .offset = _reg, \
>> + .mask = _mask, \
>> + .shift = _shift, \
>> + .table = _table, \
>> + .flags = _dflags, \
>> + }, \
>> + .hw.init = &(struct clk_init_data){ \
>> + .name = #_name, \
>> + .ops = _ops, \
>> + .parent_names = _pname, \
>> + .parent_data = _pdata, \
>> + .parent_hws = (const struct clk_hw *[]) { _phw }, \
>> + .num_parents = _pnub, \
>> + .flags = _iflags, \
>> + }, \
>> +}
>> +
>> +#define __AML_CLK_DIV(_name, _reg, _shift, _width, _table, _dflags, \
>> + _ops, _pname, _pdata, _phw, _iflags) \
>> +static struct clk_regmap _name = { \
>> + .data = &(struct clk_regmap_div_data){ \
>> + .offset = _reg, \
>> + .shift = _shift, \
>> + .width = _width, \
>> + .table = _table, \
>> + .flags = _dflags, \
>> + }, \
>> + .hw.init = &(struct clk_init_data){ \
>> + .name = #_name, \
>> + .ops = _ops, \
>> + .parent_names = _pname, \
>> + .parent_data = _pdata, \
>> + .parent_hws = (const struct clk_hw *[]) { _phw }, \
>> + .num_parents = 1, \
>> + .flags = _iflags, \
>> + }, \
>> +}
>> +
>> +#define __AML_CLK_GATE(_name, _reg, _bit, _gflags, \
>> + _ops, _pname, _pdata, _phw, _iflags) \
>> +static struct clk_regmap _name = { \
>> + .data = &(struct clk_regmap_gate_data){ \
>> + .offset = _reg, \
>> + .bit_idx = _bit, \
>> + .flags = _gflags, \
>> + }, \
>> + .hw.init = &(struct clk_init_data) { \
>> + .name = #_name, \
>> + .ops = _ops, \
>> + .parent_names = _pname, \
>> + .parent_data = _pdata, \
>> + .parent_hws = (const struct clk_hw *[]) { _phw }, \
>> + .num_parents = 1, \
>> + .flags = _iflags, \
>> + }, \
>> +}
>> +
>> +#define __AML_CLK_FIXED_FACTOR(_name, _mult, _div, _ops, \
>> + _pname, _pdata, _phw, _iflags) \
>> + static struct clk_fixed_factor _name = { \
>> + .mult = _mult, \
>> + .div = _div, \
>> + .hw.init = &(struct clk_init_data){ \
>> + .name = #_name, \
>> + .ops = _ops, \
>> + .parent_names = _pname, \
>> + .parent_data = _pdata, \
>> + .parent_hws = (const struct clk_hw *[]) { _phw }, \
>> + .num_parents = 1, \
>> + .flags = _iflags, \
>> + }, \
>> +}
>> +
>> +#define AML_CLK_PLL_RW(_name, _en_reg, _en_shift, _en_width, \
>> + _m_reg, _m_shift, _m_width, \
>> + _f_reg, _f_shift, _f_width, \
>> + _n_reg, _n_shift, _n_width, \
>> + _l_reg, _l_shift, _l_width, \
>> + _r_reg, _r_shift, _r_width, \
>> + _init_reg, _init_reg_cnt, _range, _table, _dflags,\
>> + _pdata, _iflags) \
>> + __AML_CLK_PLL(_name, _en_reg, _en_shift, _en_width, \
>> + _m_reg, _m_shift, _m_width, \
>> + _f_reg, _f_shift, _f_width, \
>> + _n_reg, _n_shift, _n_width, \
>> + _l_reg, _l_shift, _l_width, \
>> + _r_reg, _r_shift, _r_width, \
>> + _init_reg, _init_reg_cnt, _range, _table, \
>> + _dflags, &meson_clk_pll_ops, \
>> + NULL, _pdata, NULL, _iflags)
>> +
>> +#define AML_CLK_PLL_RO(_name, _en_reg, _en_shift, _en_width, \
>> + _m_reg, _m_shift, _m_width, \
>> + _f_reg, _f_shift, _f_width, \
>> + _n_reg, _n_shift, _n_width, \
>> + _l_reg, _l_shift, _l_width, \
>> + _r_reg, _r_shift, _r_width, \
>> + _init_reg, _init_reg_cnt, _range, _table, \
>> + _dflags, _pdata, _iflags) \
>> + __AML_CLK_PLL(_name, _en_reg, _en_shift, _en_width, \
>> + _m_reg, _m_shift, _m_width, \
>> + _f_reg, _f_shift, _f_width, \
>> + _n_reg, _n_shift, _n_width, \
>> + _l_reg, _l_shift, _l_width, \
>> + _r_reg, _r_shift, _r_width, \
>> + _init_reg, _init_reg_cnt, _range, _table, \
>> + _dflags, &meson_clk_pll_ro_ops, \
>> + NULL, _pdata, NULL, _iflags)
>> +
>> +#define AML_CLK_MUX_RW(_name, _reg, _mask, _shift, _table, _dflags, \
>> + _pdata, _iflags) \
>> + __AML_CLK_MUX(_name, _reg, _mask, _shift, _table, _dflags, \
>> + &clk_regmap_mux_ops, NULL, _pdata, NULL, \
>> + ARRAY_SIZE(_pdata), _iflags)
>> +
>> +#define AML_CLK_DIV_RW(_name, _reg, _shift, _width, _table, _dflags, \
>> + _phw, _iflags) \
>> + __AML_CLK_DIV(_name, _reg, _shift, _width, _table, _dflags, \
>> + &clk_regmap_divider_ops, NULL, NULL, \
>> + _phw, _iflags)
>> +
>> +#define AML_CLK_DIV_RO(_name, _reg, _shift, _width, _table, _dflags, \
>> + _phw, _iflags) \
>> + __AML_CLK_DIV(_name, _reg, _shift, _width, _table, _dflags, \
>> + &clk_regmap_divider_ro_ops, NULL, NULL, \
>> + _phw, _iflags)
>> +
>> +#define AML_CLK_GATE_RW(_name, _reg, _bit, _dflags, _phw, _iflags) \
>> + __AML_CLK_GATE(_name, _reg, _bit, _dflags, \
>> + &clk_regmap_gate_ops, NULL, NULL, _phw, \
>> + _iflags)
>> +
>> +#define AML_CLK_GATE_RO(_name, _reg, _bit, _dflags, _phw, _iflags) \
>> + __AML_CLK_GATE(_name, _reg, _bit, _dflags, \
>> + &clk_regmap_gate_ro_ops, NULL, NULL, _phw, \
>> + _iflags)
>> +
>> +#define AML_CLK_FIXED_FACTOR(_name, _mult, _div, _phw, _iflags) \
>> + __AML_CLK_FIXED_FACTOR(_name, _mult, _div, \
>> + &clk_fixed_factor_ops, NULL, NULL, \
>> + _phw, _iflags)
>> +
>
> I don't get why all these macro are needed ? I don't see a 10 instances
> of the very same clock that would justify this.
>
> It makes this driver borderline un-reviewable.
>
> Unless you can provide a very reason why it is better like this, please
> have a look a the a1 and s4 controllers and re-submit.
>
> Same goes for patch #4
>
>
>> +static const struct clk_parent_data pll_dco_parent = {
>> + .fw_name = "pll_in",
>> +};
>> +
>> +static const struct clk_parent_data mclk_pll_dco_parent = {
>> + .fw_name = "mclk_pll_in",
>> +};
>> +
>> +AML_CLK_PLL_RO(fixed_pll_dco, ANACTRL_FIXPLL_CTRL0, 28, 1, /* en */
>> + ANACTRL_FIXPLL_CTRL0, 0, 8, /* m */
>> + 0, 0, 0, /* frac */
>> + ANACTRL_FIXPLL_CTRL0, 16, 5, /* n */
>> + ANACTRL_FIXPLL_CTRL0, 31, 1, /* lock */
>> + ANACTRL_FIXPLL_CTRL0, 29, 1, /* rst */
>> + NULL, 0, NULL, NULL, 0, &pll_dco_parent, 0);
>> +AML_CLK_DIV_RO(fixed_pll, ANACTRL_FIXPLL_CTRL0, 12, 3, NULL,
>> + CLK_DIVIDER_POWER_OF_TWO, &fixed_pll_dco.hw, 0);
>> +AML_CLK_FIXED_FACTOR(fclk_div40_div, 1, 40, &fixed_pll.hw, 0);
>> +AML_CLK_GATE_RO(fclk_div40, ANACTRL_FIXPLL_CTRL4, 0, 0, &fclk_div40_div.hw, 0);
>> +AML_CLK_FIXED_FACTOR(fclk_div2_div, 1, 2, &fixed_pll.hw, 0);
>> +AML_CLK_GATE_RO(fclk_div2, ANACTRL_FIXPLL_CTRL4, 24, 0, &fclk_div2_div.hw, 0);
>> +AML_CLK_FIXED_FACTOR(fclk_div2p5_div, 2, 5, &fixed_pll.hw, 0);
>> +AML_CLK_GATE_RO(fclk_div2p5, ANACTRL_FIXPLL_CTRL4, 4, 0, &fclk_div2p5_div.hw, 0);
>> +AML_CLK_FIXED_FACTOR(fclk_div3_div, 1, 3, &fixed_pll.hw, 0);
>> +AML_CLK_GATE_RO(fclk_div3, ANACTRL_FIXPLL_CTRL4, 20, 0, &fclk_div3_div.hw, 0);
>> +AML_CLK_FIXED_FACTOR(fclk_div4_div, 1, 4, &fixed_pll.hw, 0);
>> +AML_CLK_GATE_RO(fclk_div4, ANACTRL_FIXPLL_CTRL4, 21, 0, &fclk_div4_div.hw, 0);
>> +AML_CLK_FIXED_FACTOR(fclk_div5_div, 1, 5, &fixed_pll.hw, 0);
>> +AML_CLK_GATE_RO(fclk_div5, ANACTRL_FIXPLL_CTRL4, 22, 0, &fclk_div5_div.hw, 0);
>> +AML_CLK_FIXED_FACTOR(fclk_div7_div, 1, 7, &fixed_pll.hw, 0);
>> +AML_CLK_GATE_RO(fclk_div7, ANACTRL_FIXPLL_CTRL4, 23, 0, &fclk_div7_div.hw, 0);
>> +
>> +static const struct reg_sequence c3_gp0_init_regs[] = {
>> + { .reg = ANACTRL_GP0PLL_CTRL1, .def = 0x0 },
>> + { .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, .delay_us = 10 },
>> + { .reg = ANACTRL_GP0PLL_CTRL0, .def = 0x080304fa },
>> + { .reg = ANACTRL_GP0PLL_CTRL0, .def = 0x380304fa, .delay_us = 10 },
>> + { .reg = ANACTRL_GP0PLL_CTRL0, .def = 0X180304fa }
>> +};
>> +
>> +static const struct pll_params_table c3_gp0_pll_params_table[] = {
>> + PLL_PARAMS(150, 1), /* DCO = 3600M */
>> + PLL_PARAMS(130, 1), /* DCO = 3120M */
>> + PLL_PARAMS(192, 1), /* DCO = 4608M */
>> + PLL_PARAMS(125, 1), /* DCO = 3000M */
>> + { /* sentinel */ }
>> +};
>> +
>> +/* 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 */ }
>> +};
>> +
>> +AML_CLK_PLL_RW(gp0_pll_dco, ANACTRL_GP0PLL_CTRL0, 28, 1, /* en */
>> + ANACTRL_GP0PLL_CTRL0, 0, 9, /* m */
>> + ANACTRL_GP0PLL_CTRL1, 0, 19, /* frac */
>> + ANACTRL_GP0PLL_CTRL0, 10, 5, /* n */
>> + ANACTRL_GP0PLL_CTRL0, 31, 1, /* lock */
>> + ANACTRL_GP0PLL_CTRL0, 29, 1, /* rst */
>> + c3_gp0_init_regs, ARRAY_SIZE(c3_gp0_init_regs),
>> + NULL, c3_gp0_pll_params_table, 0,
>> + &pll_dco_parent, 0);
>> +AML_CLK_DIV_RW(gp0_pll, ANACTRL_GP0PLL_CTRL0, 16, 3,
>> + c3_gp0_pll_od_table, 0,
>> + &gp0_pll_dco.hw, CLK_SET_RATE_PARENT);
>> +
>> +static const struct reg_sequence c3_hifi_init_regs[] = {
>> + { .reg = ANACTRL_HIFIPLL_CTRL0, .def = 0x08010496 },
>> + { .reg = ANACTRL_HIFIPLL_CTRL0, .def = 0x38010496 },
>> + { .reg = ANACTRL_HIFIPLL_CTRL1, .def = 0x0000ce40 },
>> + { .reg = ANACTRL_HIFIPLL_CTRL2, .def = 0x00000000 },
>> + { .reg = ANACTRL_HIFIPLL_CTRL3, .def = 0x6a285c00 },
>> + { .reg = ANACTRL_HIFIPLL_CTRL4, .def = 0x65771290 },
>> + { .reg = ANACTRL_HIFIPLL_CTRL5, .def = 0x3927200a },
>> + { .reg = ANACTRL_HIFIPLL_CTRL6, .def = 0x56540000, .delay_us = 50 },
>> + { .reg = ANACTRL_HIFIPLL_CTRL0, .def = 0x18010496, .delay_us = 20 },
>> +};
>> +
>> +static const struct pll_params_table c3_hifi_pll_params_table[] = {
>> + PLL_PARAMS(150, 1), /* DCO = 3600M */
>> + PLL_PARAMS(130, 1), /* DCO = 3120M */
>> + PLL_PARAMS(192, 1), /* DCO = 4608M */
>> + PLL_PARAMS(125, 1), /* DCO = 3000M */
>> + { /* sentinel */ }
>> +};
>> +
>> +AML_CLK_PLL_RW(hifi_pll_dco, ANACTRL_HIFIPLL_CTRL0, 28, 1, /* en */
>> + ANACTRL_HIFIPLL_CTRL0, 0, 8, /* m */
>> + ANACTRL_HIFIPLL_CTRL1, 0, 19, /* frac */
>> + ANACTRL_HIFIPLL_CTRL0, 10, 5, /* n */
>> + ANACTRL_HIFIPLL_CTRL0, 31, 1, /* lock */
>> + ANACTRL_HIFIPLL_CTRL0, 29, 1, /* rst */
>> + c3_hifi_init_regs, ARRAY_SIZE(c3_hifi_init_regs),
>> + NULL, c3_hifi_pll_params_table, 0,
>> + &pll_dco_parent, 0);
>> +AML_CLK_DIV_RW(hifi_pll, ANACTRL_HIFIPLL_CTRL0, 16, 2,
>> + NULL, CLK_DIVIDER_POWER_OF_TWO,
>> + &hifi_pll_dco.hw, CLK_SET_RATE_PARENT);
>> +
>> +static const struct reg_sequence c3_mclk_init_regs[] = {
>> + { .reg = ANACTRL_MPLL_CTRL0, .def = 0x20011063 },
>> + { .reg = ANACTRL_MPLL_CTRL0, .def = 0x30011063 },
>> + { .reg = ANACTRL_MPLL_CTRL1, .def = 0x1420500f },
>> + { .reg = ANACTRL_MPLL_CTRL2, .def = 0x00023041 },
>> + { .reg = ANACTRL_MPLL_CTRL3, .def = 0x18180000 },
>> + { .reg = ANACTRL_MPLL_CTRL0, .def = 0x10011063 },
>> + { .reg = ANACTRL_MPLL_CTRL2, .def = 0x00023001 }
>> +};
>> +
>> +static const struct pll_params_table c3_mclk_pll_params_table[] = {
>> + PLL_PARAMS(99, 1), /* VCO = 2376M */
>> + { /* sentinel */ }
>> +};
>> +
>> +static const struct clk_div_table c3_mpll_od_table[] = {
>> + { 0, 1 },
>> + { 1, 2 },
>> + { 2, 4 },
>> + { 3, 8 },
>> + { 4, 16 },
>> + { /* sentinel */ }
>> +};
>> +
>> +AML_CLK_PLL_RW(mclk_pll_dco, ANACTRL_MPLL_CTRL0, 28, 1, /* en */
>> + ANACTRL_MPLL_CTRL0, 0, 8, /* m */
>> + 0, 0, 0, /* frac */
>> + ANACTRL_MPLL_CTRL0, 16, 5, /* n */
>> + ANACTRL_MPLL_CTRL0, 31, 1, /* lock */
>> + ANACTRL_MPLL_CTRL0, 29, 1, /* rst */
>> + c3_mclk_init_regs, ARRAY_SIZE(c3_mclk_init_regs),
>> + NULL, c3_mclk_pll_params_table, 0,
>> + &mclk_pll_dco_parent, 0);
>> +AML_CLK_DIV_RW(mclk_pll, ANACTRL_MPLL_CTRL0, 12, 3,
>> + c3_mpll_od_table, 0,
>> + &mclk_pll_dco.hw, CLK_SET_RATE_PARENT);
>> +AML_CLK_DIV_RW(mclk_pll_clk, ANACTRL_MPLL_CTRL4, 16, 5, NULL,
>> + CLK_DIVIDER_ONE_BASED | CLK_DIVIDER_ALLOW_ZERO,
>> + &mclk_pll.hw, CLK_SET_RATE_PARENT);
>> +
>> +static const struct clk_parent_data mclk_parent[] = {
>> + { .hw = &mclk_pll_clk.hw },
>> + { .fw_name = "mclk_pll_in" },
>> + { .hw = &fclk_div40.hw }
>> +};
>> +
>> +AML_CLK_MUX_RW(mclk0_sel, ANACTRL_MPLL_CTRL4, 0x3, 4, NULL, 0,
>> + mclk_parent, 0);
>> +AML_CLK_GATE_RW(mclk0_sel_out, ANACTRL_MPLL_CTRL4, 1, 0,
>> + &mclk0_sel.hw, CLK_SET_RATE_PARENT);
>> +AML_CLK_DIV_RW(mclk0_div, ANACTRL_MPLL_CTRL4, 2, 1, NULL, 0,
>> + &mclk0_sel_out.hw, CLK_SET_RATE_PARENT);
>> +AML_CLK_GATE_RW(mclk0, ANACTRL_MPLL_CTRL4, 0, 0,
>> + &mclk0_div.hw, CLK_SET_RATE_PARENT);
>> +
>> +AML_CLK_MUX_RW(mclk1_sel, ANACTRL_MPLL_CTRL4, 0x3, 12, NULL, 0,
>> + mclk_parent, 0);
>> +AML_CLK_GATE_RW(mclk1_sel_out, ANACTRL_MPLL_CTRL4, 9, 0,
>> + &mclk1_sel.hw, CLK_SET_RATE_PARENT);
>> +AML_CLK_DIV_RW(mclk1_div, ANACTRL_MPLL_CTRL4, 10, 1, NULL, 0,
>> + &mclk1_sel_out.hw, CLK_SET_RATE_PARENT);
>> +AML_CLK_GATE_RW(mclk1, ANACTRL_MPLL_CTRL4, 8, 0,
>> + &mclk1_div.hw, 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_DIV40_DIV] = &fclk_div40_div.hw,
>> + [CLKID_FCLK_DIV40] = &fclk_div40.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_HIFI_PLL_DCO] = &hifi_pll_dco.hw,
>> + [CLKID_HIFI_PLL] = &hifi_pll.hw,
>> + [CLKID_MCLK_PLL_DCO] = &mclk_pll_dco.hw,
>> + [CLKID_MCLK_PLL] = &mclk_pll.hw,
>> + [CLKID_MCLK_PLL_CLK] = &mclk_pll_clk.hw,
>> + [CLKID_MCLK0_SEL] = &mclk0_sel.hw,
>> + [CLKID_MCLK0_SEL_OUT] = &mclk0_sel_out.hw,
>> + [CLKID_MCLK0_DIV] = &mclk0_div.hw,
>> + [CLKID_MCLK0] = &mclk0.hw,
>> + [CLKID_MCLK1_SEL] = &mclk1_sel.hw,
>> + [CLKID_MCLK1_SEL_OUT] = &mclk1_sel_out.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_div40,
>> + &fclk_div2,
>> + &fclk_div2p5,
>> + &fclk_div3,
>> + &fclk_div4,
>> + &fclk_div5,
>> + &fclk_div7,
>> + &gp0_pll_dco,
>> + &gp0_pll,
>> + &hifi_pll_dco,
>> + &hifi_pll,
>> + &mclk_pll_dco,
>> + &mclk_pll,
>> + &mclk_pll_clk,
>> + &mclk0_sel,
>> + &mclk0_sel_out,
>> + &mclk0_div,
>> + &mclk0,
>> + &mclk1_sel,
>> + &mclk1_sel_out,
>> + &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");
>> diff --git a/drivers/clk/meson/c3-pll.h b/drivers/clk/meson/c3-pll.h
>> new file mode 100644
>> index 000000000000..92a08196a46f
>> --- /dev/null
>> +++ b/drivers/clk/meson/c3-pll.h
>> @@ -0,0 +1,35 @@
>> +/* SPDX-License-Identifier: (GPL-2.0-only OR MIT) */
>> +/*
>> + * Copyright (c) 2023 Amlogic, inc.
>> + * Author: Chuan Liu <[email protected]>
>> + */
>> +
>> +#ifndef __AML_C3_PLL_H__
>> +#define __AML_C3_PLL_H__
>> +
>> +#define ANACTRL_FIXPLL_CTRL0 0x0040
>> +#define ANACTRL_FIXPLL_CTRL4 0x0050
>> +#define ANACTRL_GP0PLL_CTRL0 0x0080
>> +#define ANACTRL_GP0PLL_CTRL1 0x0084
>> +#define ANACTRL_GP0PLL_CTRL2 0x0088
>> +#define ANACTRL_GP0PLL_CTRL3 0x008c
>> +#define ANACTRL_GP0PLL_CTRL4 0x0090
>> +#define ANACTRL_GP0PLL_CTRL5 0x0094
>> +#define ANACTRL_GP0PLL_CTRL6 0x0098
>> +#define ANACTRL_GP0PLL_STS 0x009c
>> +#define ANACTRL_HIFIPLL_CTRL0 0x0100
>> +#define ANACTRL_HIFIPLL_CTRL1 0x0104
>> +#define ANACTRL_HIFIPLL_CTRL2 0x0108
>> +#define ANACTRL_HIFIPLL_CTRL3 0x010c
>> +#define ANACTRL_HIFIPLL_CTRL4 0x0110
>> +#define ANACTRL_HIFIPLL_CTRL5 0x0114
>> +#define ANACTRL_HIFIPLL_CTRL6 0x0118
>> +#define ANACTRL_HIFIPLL_STS 0x011c
>> +#define ANACTRL_MPLL_CTRL0 0x0180
>> +#define ANACTRL_MPLL_CTRL1 0x0184
>> +#define ANACTRL_MPLL_CTRL2 0x0188
>> +#define ANACTRL_MPLL_CTRL3 0x018c
>> +#define ANACTRL_MPLL_CTRL4 0x0190
>> +#define ANACTRL_MPLL_STS 0x01a4
>> +
>> +#endif /* __AML_C3_PLL_H__ */
>