[PATCH 8/9] clk: meson: Add s4 clock driver
Sean Anderson <[email protected]>
| Newsgroups | org.u-boot-project.lists.u-boot |
|---|---|
| Message-ID | <[email protected]> |
Add a clock driver to support for the "s4" series of SoCs (S805X2 and
S905Y4). I've added most of the clocks necessary at boot, although a few
of the unused parents (VID_PLL, RTC) have been omitted. I also left out
the parents of the MPLL clocks, as they have a custom divider. MPLL2 is
enabled by the Ethernet driver but is never actually selected so it's OK
to stub out the parent.
=> clk dump
Rate Usecnt Name
------------------------------------------
24000000 0 |-- xtal-clk
34700000 0 |-- bt-txco
meson-clk-s4 clock-controller@0:
clock-controller@0:
----------------------------------------------------------------------
clk frequency parent state
----------------------------------------------------------------------
sysclk_b_sel 498000000 fclk_div4 N/A
sysclk_b_div 166000000 sysclk_b_sel N/A
sysclk_b 166000000 sysclk_b_div enabled
sysclk_a_sel 24000000 xtal N/A
sysclk_a_div 24000000 sysclk_a_sel N/A
sysclk_a 24000000 sysclk_a_div enabled
sys 166000000 sysclk_b N/A
sd_emmc_c_sel 24000000 xtal N/A
sd_emmc_c_div 24000000 sd_emmc_c_sel N/A
sd_emmc_c 24000000 sd_emmc_c_div enabled
sd_emmc_a_sel 24000000 xtal N/A
sd_emmc_a_div 24000000 sd_emmc_a_sel N/A
sd_emmc_a 24000000 sd_emmc_a_div enabled
sd_emmc_b_sel 24000000 xtal N/A
sd_emmc_b_div 24000000 sd_emmc_b_sel N/A
sd_emmc_b 24000000 sd_emmc_b_div enabled
pwm_a_sel 24000000 xtal N/A
pwm_a_div 24000000 pwm_a_sel N/A
pwm_a 24000000 pwm_a_div disabled
pwm_b_sel 24000000 xtal N/A
pwm_b_div 24000000 pwm_b_sel N/A
pwm_b 24000000 pwm_b_div disabled
pwm_c_sel 24000000 xtal N/A
pwm_c_div 24000000 pwm_c_sel N/A
pwm_c 24000000 pwm_c_div disabled
pwm_d_sel 24000000 xtal N/A
pwm_d_div 24000000 pwm_d_sel N/A
pwm_d 24000000 pwm_d_div disabled
pwm_e_sel 24000000 xtal N/A
pwm_e_div 24000000 pwm_e_sel N/A
pwm_e 24000000 pwm_e_div disabled
pwm_f_sel 24000000 xtal N/A
pwm_f_div 24000000 pwm_f_sel N/A
pwm_f 24000000 pwm_f_div disabled
pwm_g_sel 24000000 xtal N/A
pwm_g_div 24000000 pwm_g_sel N/A
pwm_g 24000000 pwm_g_div disabled
pwm_h_sel 24000000 xtal N/A
pwm_h_div 24000000 pwm_h_sel N/A
pwm_h 24000000 pwm_h_div enabled
pwm_i_sel 24000000 xtal N/A
pwm_i_div 24000000 pwm_i_sel N/A
pwm_i 24000000 pwm_i_div disabled
pwm_j_sel 24000000 xtal N/A
pwm_j_div 24000000 pwm_j_sel N/A
pwm_j 24000000 pwm_j_div enabled
ethphy 166000000 sys enabled
sdemmc_a 166000000 sys enabled
sdemmc_b 166000000 sys enabled
nand 166000000 sys enabled
eth 166000000 sys enabled
uart_a 166000000 sys enabled
uart_b 166000000 sys enabled
uart_c 166000000 sys enabled
uart_d 166000000 sys enabled
uart_e 166000000 sys enabled
usb 166000000 sys enabled
i2c_m_a 166000000 sys enabled
i2c_m_b 166000000 sys enabled
i2c_m_c 166000000 sys enabled
i2c_m_d 166000000 sys enabled
i2c_m_e 166000000 sys enabled
usb1_to_ddr 166000000 sys enabled
pwm_ab 166000000 sys enabled
pwm_cd 166000000 sys enabled
pwm_ef 166000000 sys enabled
pwm_gh 166000000 sys enabled
pwm_ij 166000000 sys enabled
xtal 24000000 unknown N/A
fclk_div2 996000000 unknown N/A
fclk_div2p5 796800000 unknown N/A
fclk_div3 664000000 unknown N/A
fclk_div4 498000000 unknown N/A
fclk_div5 398400000 unknown N/A
fclk_div7 284571428 unknown N/A
hifi_pll 1176000000 unknown N/A
gp0_pll unknown unknown N/A
mpll0 unknown unknown N/A
mpll1 unknown unknown N/A
mpll2 unknown unknown N/A
mpll3 unknown unknown N/A
hdmi_pll unknown unknown N/A
meson-clk-s4 clock-controller@8000:
clock-controller@8000:
----------------------------------------------------------------------
clk frequency parent state
----------------------------------------------------------------------
fixed_pll_dco 3984000000 xtal N/A
fixed_pll 1992000000 fixed_pll_dco N/A
fclk_div2_div 996000000 fixed_pll N/A
fclk_div2 996000000 fclk_div2_div enabled
fclk_div3_div 664000000 fixed_pll N/A
fclk_div3 664000000 fclk_div3_div enabled
fclk_div4_div 498000000 fixed_pll N/A
fclk_div4 498000000 fclk_div4_div enabled
fclk_div5_div 398400000 fixed_pll N/A
fclk_div5 398400000 fclk_div5_div enabled
fclk_div7_div 284571428 fixed_pll N/A
fclk_div7 284571428 fclk_div7_div enabled
fclk_div2p5_div 796800000 fixed_pll N/A
fclk_div2p5 796800000 fclk_div2p5_div enabled
gp0_pll_dco unknown xtal N/A
gp0_pll unknown gp0_pll_dco N/A
hifi_pll_dco 4704000000 xtal N/A
hifi_pll 1176000000 hifi_pll_dco N/A
hdmi_pll_dco unknown xtal N/A
hdmi_pll_od unknown hdmi_pll_dco N/A
hdmi_pll unknown hdmi_pll_od N/A
mpll_50m_div 49800000 fixed_pll_dco N/A
mpll_50m 49800000 mpll_50m_div N/A
mpll0 unknown unknown disabled
mpll1 unknown unknown disabled
mpll2 unknown unknown enabled
mpll3 unknown unknown disabled
xtal 24000000 unknown N/A
Signed-off-by: Sean Anderson <[email protected]>
---
drivers/clk/meson/Kconfig | 8 +
drivers/clk/meson/Makefile | 1 +
drivers/clk/meson/s4.c | 587 +++++++++++++++++++++++++++++++++++++
3 files changed, 596 insertions(+)
create mode 100644 drivers/clk/meson/s4.c
diff --git a/drivers/clk/meson/Kconfig b/drivers/clk/meson/Kconfig
index ee33c611400..abdc6a70e25 100644
--- a/drivers/clk/meson/Kconfig
+++ b/drivers/clk/meson/Kconfig
@@ -30,6 +30,14 @@ config CLK_MESON_A1
Enable clock support for the Amlogic A1 SoC family, such as
the A113L
+config CLK_MESON_S4
+ bool "Enable clock support for Amlogic S4"
+ depends on CLK && ARCH_MESON
+ default MESON_S4
+ help
+ Enable clock support for the Amlogic S4 SoC family, such as
+ the S905Y4/S905W2
+
config CLK_MESON_MSR
bool "Enable clock measure driver for Amlogic SoCs"
depends on CLK && ARCH_MESON
diff --git a/drivers/clk/meson/Makefile b/drivers/clk/meson/Makefile
index 3d1dfcdb640..705591ed4a9 100644
--- a/drivers/clk/meson/Makefile
+++ b/drivers/clk/meson/Makefile
@@ -10,4 +10,5 @@ obj-$(CONFIG_CLK_MESON_AXG) += axg-ao.o
obj-$(CONFIG_CLK_MESON_G12A) += g12a.o
obj-$(CONFIG_CLK_MESON_G12A) += g12a-ao.o
obj-$(CONFIG_CLK_MESON_A1) += a1.o
+obj-$(CONFIG_CLK_MESON_S4) += s4.o
obj-$(CONFIG_CLK_MESON_MSR) += clk-measure.o
diff --git a/drivers/clk/meson/s4.c b/drivers/clk/meson/s4.c
new file mode 100644
index 00000000000..5bb8e58f378
--- /dev/null
+++ b/drivers/clk/meson/s4.c
@@ -0,0 +1,587 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (C) Brivo Systems LLC 2026
+ */
+
+#include <clk-uclass.h>
+#include <dm.h>
+#include <regmap.h>
+#include <dt-bindings/clock/amlogic,s4-pll-clkc.h>
+#include <dt-bindings/clock/amlogic,s4-peripherals-clkc.h>
+#include "clk_meson.h"
+
+/*
+ * This driver supports both PLL and peripherals clock sources.
+ * Following operations are supported:
+ * - calculating clock frequency on a limited tree
+ * - reading muxes and dividers
+ * - enabling/disabling gates without propagation
+ * - reparenting without rate propagation, only on muxes
+ * - setting rates with limited reparenting, only on dividers with mux parent
+ */
+
+#define RTC_BY_OSCIN_CTRL0 0x008
+#define RTC_BY_OSCIN_CTRL1 0x00c
+#define RTC_CTRL 0x010
+#define SYS_CLK_CTRL0 0x040
+#define SYS_CLK_EN0_REG0 0x044
+#define SYS_CLK_EN0_REG1 0x048
+#define SYS_CLK_EN0_REG2 0x04c
+#define SYS_CLK_EN0_REG3 0x050
+#define CECA_CTRL0 0x088
+#define CECA_CTRL1 0x08c
+#define CECB_CTRL0 0x090
+#define CECB_CTRL1 0x094
+#define SC_CLK_CTRL 0x098
+#define CLK12_24_CTRL 0x0a8
+#define VID_CLK_CTRL 0x0c0
+#define VID_CLK_CTRL2 0x0c4
+#define VID_CLK_DIV 0x0c8
+#define VIID_CLK_DIV 0x0cc
+#define VIID_CLK_CTRL 0x0d0
+#define HDMI_CLK_CTRL 0x0e0
+#define VID_PLL_CLK_DIV 0x0e4
+#define VPU_CLK_CTRL 0x0e8
+#define VPU_CLKB_CTRL 0x0ec
+#define VPU_CLKC_CTRL 0x0f0
+#define VID_LOCK_CLK_CTRL 0x0f4
+#define VDIN_MEAS_CLK_CTRL 0x0f8
+#define VAPBCLK_CTRL 0x0fc
+#define HDCP22_CTRL 0x100
+#define CDAC_CLK_CTRL 0x108
+#define VDEC_CLK_CTRL 0x140
+#define VDEC2_CLK_CTRL 0x144
+#define VDEC3_CLK_CTRL 0x148
+#define VDEC4_CLK_CTRL 0x14c
+#define TS_CLK_CTRL 0x158
+#define MALI_CLK_CTRL 0x15c
+#define NAND_CLK_CTRL 0x168
+#define SD_EMMC_CLK_CTRL 0x16c
+#define SPICC_CLK_CTRL 0x174
+#define GEN_CLK_CTRL 0x178
+#define SAR_CLK_CTRL 0x17c
+#define PWM_CLK_AB_CTRL 0x180
+#define PWM_CLK_CD_CTRL 0x184
+#define PWM_CLK_EF_CTRL 0x188
+#define PWM_CLK_GH_CTRL 0x18c
+#define PWM_CLK_IJ_CTRL 0x190
+#define DEMOD_CLK_CTRL 0x200
+
+#define FIXPLL_CTRL0 0x040
+#define FIXPLL_CTRL1 0x044
+#define FIXPLL_CTRL3 0x04c
+#define GP0PLL_CTRL0 0x080
+#define GP0PLL_CTRL1 0x084
+#define GP0PLL_CTRL2 0x088
+#define GP0PLL_CTRL3 0x08c
+#define GP0PLL_CTRL4 0x090
+#define GP0PLL_CTRL5 0x094
+#define GP0PLL_CTRL6 0x098
+#define HIFIPLL_CTRL0 0x100
+#define HIFIPLL_CTRL1 0x104
+#define HIFIPLL_CTRL2 0x108
+#define HIFIPLL_CTRL3 0x10c
+#define HIFIPLL_CTRL4 0x110
+#define HIFIPLL_CTRL5 0x114
+#define HIFIPLL_CTRL6 0x118
+#define MPLL_CTRL0 0x180
+#define MPLL_CTRL1 0x184
+#define MPLL_CTRL2 0x188
+#define MPLL_CTRL3 0x18c
+#define MPLL_CTRL4 0x190
+#define MPLL_CTRL5 0x194
+#define MPLL_CTRL6 0x198
+#define MPLL_CTRL7 0x19c
+#define MPLL_CTRL8 0x1a0
+#define HDMIPLL_CTRL0 0x1c0
+
+/* External clock IDs. Those should not overlap with regular IDs */
+enum {
+ EXTERNAL_XTAL = CLKID_ADC_EXTCLK_IN + 1,
+ EXTERNAL_FCLK_DIV2,
+ EXTERNAL_FCLK_DIV2P5,
+ EXTERNAL_FCLK_DIV3,
+ EXTERNAL_FCLK_DIV4,
+ EXTERNAL_FCLK_DIV5,
+ EXTERNAL_FCLK_DIV7,
+ EXTERNAL_HIFI_PLL,
+ EXTERNAL_GP0_PLL,
+ EXTERNAL_MPLL0,
+ EXTERNAL_MPLL1,
+ EXTERNAL_MPLL2,
+ EXTERNAL_MPLL3,
+ EXTERNAL_HDMI_PLL,
+
+ EXTERNAL_PLL_XTAL = CLKID_MPLL3 + 1,
+};
+
+/* S4 peripherals clocks */
+static const struct meson_clk_info *meson_clocks[] = {
+ [CLKID_SYS_CLK_B_SEL] = CLK_MUX("sysclk_b_sel", SYS_CLK_CTRL0, 26, 3, {
+ EXTERNAL_XTAL,
+ EXTERNAL_FCLK_DIV2,
+ EXTERNAL_FCLK_DIV3,
+ EXTERNAL_FCLK_DIV4,
+ EXTERNAL_FCLK_DIV5,
+ -ENOENT,
+ EXTERNAL_FCLK_DIV7,
+ -ENOENT,
+ }),
+ [CLKID_SYS_CLK_B_DIV] = CLK_DIV("sysclk_b_div", SYS_CLK_CTRL0, 16, 10,
+ CLKID_SYS_CLK_B_SEL
+ ),
+ [CLKID_SYS_CLK_B] = CLK_GATE("sysclk_b", SYS_CLK_CTRL0, 29,
+ CLKID_SYS_CLK_B_DIV
+ ),
+ [CLKID_SYS_CLK_A_SEL] = CLK_MUX("sysclk_a_sel", SYS_CLK_CTRL0, 10, 3, {
+ EXTERNAL_XTAL,
+ EXTERNAL_FCLK_DIV2,
+ EXTERNAL_FCLK_DIV3,
+ EXTERNAL_FCLK_DIV4,
+ EXTERNAL_FCLK_DIV5,
+ -ENOENT,
+ EXTERNAL_FCLK_DIV7,
+ -ENOENT,
+ }),
+ [CLKID_SYS_CLK_A_DIV] = CLK_DIV("sysclk_a_div", SYS_CLK_CTRL0, 0, 10,
+ CLKID_SYS_CLK_A_SEL
+ ),
+ [CLKID_SYS_CLK_A] = CLK_GATE("sysclk_a", SYS_CLK_CTRL0, 13,
+ CLKID_SYS_CLK_A_DIV
+ ),
+ [CLKID_SYS] = CLK_MUX("sys", SYS_CLK_CTRL0, 31, 1, {
+ CLKID_SYS_CLK_A,
+ CLKID_SYS_CLK_B,
+ }),
+
+ [CLKID_SD_EMMC_C_CLK_SEL] = CLK_MUX("sd_emmc_c_sel", NAND_CLK_CTRL, 9, 3, {
+ EXTERNAL_XTAL,
+ EXTERNAL_FCLK_DIV2,
+ EXTERNAL_FCLK_DIV3,
+ EXTERNAL_HIFI_PLL,
+ EXTERNAL_FCLK_DIV2P5,
+ EXTERNAL_MPLL2,
+ EXTERNAL_MPLL3,
+ EXTERNAL_GP0_PLL,
+ }),
+ [CLKID_SD_EMMC_C_CLK_DIV] = CLK_DIV("sd_emmc_c_div", NAND_CLK_CTRL, 0, 7,
+ CLKID_SD_EMMC_C_CLK_SEL
+ ),
+ [CLKID_SD_EMMC_C] = CLK_GATE("sd_emmc_c", NAND_CLK_CTRL, 7,
+ CLKID_SD_EMMC_C_CLK_DIV
+ ),
+
+ [CLKID_SD_EMMC_A_CLK_SEL] = CLK_MUX("sd_emmc_a_sel", SD_EMMC_CLK_CTRL, 9, 3, {
+ EXTERNAL_XTAL,
+ EXTERNAL_FCLK_DIV2,
+ EXTERNAL_FCLK_DIV3,
+ EXTERNAL_HIFI_PLL,
+ EXTERNAL_FCLK_DIV2P5,
+ EXTERNAL_MPLL2,
+ EXTERNAL_MPLL3,
+ EXTERNAL_GP0_PLL,
+ }),
+ [CLKID_SD_EMMC_A_CLK_DIV] = CLK_DIV("sd_emmc_a_div", SD_EMMC_CLK_CTRL, 0, 7,
+ CLKID_SD_EMMC_A_CLK_SEL
+ ),
+ [CLKID_SD_EMMC_A] = CLK_GATE("sd_emmc_a", SD_EMMC_CLK_CTRL, 7,
+ CLKID_SD_EMMC_A_CLK_DIV
+ ),
+
+ [CLKID_SD_EMMC_B_CLK_SEL] = CLK_MUX("sd_emmc_b_sel", SD_EMMC_CLK_CTRL, 25, 3, {
+ EXTERNAL_XTAL,
+ EXTERNAL_FCLK_DIV2,
+ EXTERNAL_FCLK_DIV3,
+ EXTERNAL_HIFI_PLL,
+ EXTERNAL_FCLK_DIV2P5,
+ EXTERNAL_MPLL2,
+ EXTERNAL_MPLL3,
+ EXTERNAL_GP0_PLL,
+ }),
+ [CLKID_SD_EMMC_B_CLK_DIV] = CLK_DIV("sd_emmc_b_div", SD_EMMC_CLK_CTRL, 16, 7,
+ CLKID_SD_EMMC_B_CLK_SEL
+ ),
+ [CLKID_SD_EMMC_B] = CLK_GATE("sd_emmc_b", SD_EMMC_CLK_CTRL, 23,
+ CLKID_SD_EMMC_B_CLK_DIV
+ ),
+
+ [CLKID_PWM_A_SEL] = CLK_MUX("pwm_a_sel", PWM_CLK_AB_CTRL, 9, 2, {
+ EXTERNAL_XTAL,
+ -ENOENT,
+ EXTERNAL_FCLK_DIV4,
+ EXTERNAL_FCLK_DIV3,
+ }),
+ [CLKID_PWM_A_DIV] = CLK_DIV("pwm_a_div", PWM_CLK_AB_CTRL, 0, 8,
+ CLKID_PWM_A_SEL
+ ),
+ [CLKID_PWM_A] = CLK_GATE("pwm_a", PWM_CLK_AB_CTRL, 8,
+ CLKID_PWM_A_DIV
+ ),
+
+ [CLKID_PWM_B_SEL] = CLK_MUX("pwm_b_sel", PWM_CLK_AB_CTRL, 25, 2, {
+ EXTERNAL_XTAL,
+ -ENOENT,
+ EXTERNAL_FCLK_DIV4,
+ EXTERNAL_FCLK_DIV3,
+ }),
+ [CLKID_PWM_B_DIV] = CLK_DIV("pwm_b_div", PWM_CLK_AB_CTRL, 16, 8,
+ CLKID_PWM_B_SEL
+ ),
+ [CLKID_PWM_B] = CLK_GATE("pwm_b", PWM_CLK_AB_CTRL, 24,
+ CLKID_PWM_B_DIV
+ ),
+
+ [CLKID_PWM_C_SEL] = CLK_MUX("pwm_c_sel", PWM_CLK_CD_CTRL, 9, 2, {
+ EXTERNAL_XTAL,
+ -ENOENT,
+ EXTERNAL_FCLK_DIV4,
+ EXTERNAL_FCLK_DIV3,
+ }),
+ [CLKID_PWM_C_DIV] = CLK_DIV("pwm_c_div", PWM_CLK_CD_CTRL, 0, 8,
+ CLKID_PWM_C_SEL
+ ),
+ [CLKID_PWM_C] = CLK_GATE("pwm_c", PWM_CLK_CD_CTRL, 8,
+ CLKID_PWM_C_DIV
+ ),
+
+ [CLKID_PWM_D_SEL] = CLK_MUX("pwm_d_sel", PWM_CLK_CD_CTRL, 25, 2, {
+ EXTERNAL_XTAL,
+ -ENOENT,
+ EXTERNAL_FCLK_DIV4,
+ EXTERNAL_FCLK_DIV3,
+ }),
+ [CLKID_PWM_D_DIV] = CLK_DIV("pwm_d_div", PWM_CLK_CD_CTRL, 16, 8,
+ CLKID_PWM_D_SEL
+ ),
+ [CLKID_PWM_D] = CLK_GATE("pwm_d", PWM_CLK_CD_CTRL, 24,
+ CLKID_PWM_D_DIV
+ ),
+
+ [CLKID_PWM_E_SEL] = CLK_MUX("pwm_e_sel", PWM_CLK_EF_CTRL, 9, 2, {
+ EXTERNAL_XTAL,
+ -ENOENT,
+ EXTERNAL_FCLK_DIV4,
+ EXTERNAL_FCLK_DIV3,
+ }),
+ [CLKID_PWM_E_DIV] = CLK_DIV("pwm_e_div", PWM_CLK_EF_CTRL, 0, 8,
+ CLKID_PWM_E_SEL
+ ),
+ [CLKID_PWM_E] = CLK_GATE("pwm_e", PWM_CLK_EF_CTRL, 8,
+ CLKID_PWM_E_DIV
+ ),
+
+ [CLKID_PWM_F_SEL] = CLK_MUX("pwm_f_sel", PWM_CLK_EF_CTRL, 25, 2, {
+ EXTERNAL_XTAL,
+ -ENOENT,
+ EXTERNAL_FCLK_DIV4,
+ EXTERNAL_FCLK_DIV3,
+ }),
+ [CLKID_PWM_F_DIV] = CLK_DIV("pwm_f_div", PWM_CLK_EF_CTRL, 16, 8,
+ CLKID_PWM_F_SEL
+ ),
+ [CLKID_PWM_F] = CLK_GATE("pwm_f", PWM_CLK_EF_CTRL, 24,
+ CLKID_PWM_F_DIV
+ ),
+
+ [CLKID_PWM_G_SEL] = CLK_MUX("pwm_g_sel", PWM_CLK_GH_CTRL, 9, 2, {
+ EXTERNAL_XTAL,
+ -ENOENT,
+ EXTERNAL_FCLK_DIV4,
+ EXTERNAL_FCLK_DIV3,
+ }),
+ [CLKID_PWM_G_DIV] = CLK_DIV("pwm_g_div", PWM_CLK_GH_CTRL, 0, 8,
+ CLKID_PWM_G_SEL
+ ),
+ [CLKID_PWM_G] = CLK_GATE("pwm_g", PWM_CLK_GH_CTRL, 8,
+ CLKID_PWM_G_DIV
+ ),
+
+ [CLKID_PWM_H_SEL] = CLK_MUX("pwm_h_sel", PWM_CLK_GH_CTRL, 25, 2, {
+ EXTERNAL_XTAL,
+ -ENOENT,
+ EXTERNAL_FCLK_DIV4,
+ EXTERNAL_FCLK_DIV3,
+ }),
+ [CLKID_PWM_H_DIV] = CLK_DIV("pwm_h_div", PWM_CLK_GH_CTRL, 16, 8,
+ CLKID_PWM_H_SEL
+ ),
+ [CLKID_PWM_H] = CLK_GATE("pwm_h", PWM_CLK_GH_CTRL, 24,
+ CLKID_PWM_H_DIV
+ ),
+
+ [CLKID_PWM_I_SEL] = CLK_MUX("pwm_i_sel", PWM_CLK_IJ_CTRL, 9, 2, {
+ EXTERNAL_XTAL,
+ -ENOENT,
+ EXTERNAL_FCLK_DIV4,
+ EXTERNAL_FCLK_DIV3,
+ }),
+ [CLKID_PWM_I_DIV] = CLK_DIV("pwm_i_div", PWM_CLK_IJ_CTRL, 0, 8,
+ CLKID_PWM_I_SEL
+ ),
+ [CLKID_PWM_I] = CLK_GATE("pwm_i", PWM_CLK_IJ_CTRL, 8,
+ CLKID_PWM_I_DIV
+ ),
+
+ [CLKID_PWM_J_SEL] = CLK_MUX("pwm_j_sel", PWM_CLK_IJ_CTRL, 25, 2, {
+ EXTERNAL_XTAL,
+ -ENOENT,
+ EXTERNAL_FCLK_DIV4,
+ EXTERNAL_FCLK_DIV3,
+ }),
+ [CLKID_PWM_J_DIV] = CLK_DIV("pwm_j_div", PWM_CLK_IJ_CTRL, 16, 8,
+ CLKID_PWM_J_SEL
+ ),
+ [CLKID_PWM_J] = CLK_GATE("pwm_j", PWM_CLK_IJ_CTRL, 24,
+ CLKID_PWM_J_DIV
+ ),
+
+ [CLKID_ETHPHY] = CLK_GATE("ethphy", SYS_CLK_EN0_REG0, 4,
+ CLKID_SYS
+ ),
+ [CLKID_SDEMMC_A] = CLK_GATE("sdemmc_a", SYS_CLK_EN0_REG0, 24,
+ CLKID_SYS
+ ),
+ [CLKID_SDEMMC_B] = CLK_GATE("sdemmc_b", SYS_CLK_EN0_REG0, 25,
+ CLKID_SYS
+ ),
+ [CLKID_NAND] = CLK_GATE("nand", SYS_CLK_EN0_REG0, 26,
+ CLKID_SYS
+ ),
+
+ [CLKID_ETH] = CLK_GATE("eth", SYS_CLK_EN0_REG1, 3,
+ CLKID_SYS
+ ),
+ [CLKID_UART_A] = CLK_GATE("uart_a", SYS_CLK_EN0_REG1, 5,
+ CLKID_SYS
+ ),
+ [CLKID_UART_B] = CLK_GATE("uart_b", SYS_CLK_EN0_REG1, 6,
+ CLKID_SYS
+ ),
+ [CLKID_UART_C] = CLK_GATE("uart_c", SYS_CLK_EN0_REG1, 7,
+ CLKID_SYS
+ ),
+ [CLKID_UART_D] = CLK_GATE("uart_d", SYS_CLK_EN0_REG1, 8,
+ CLKID_SYS
+ ),
+ [CLKID_UART_E] = CLK_GATE("uart_e", SYS_CLK_EN0_REG1, 9,
+ CLKID_SYS
+ ),
+ [CLKID_USB] = CLK_GATE("usb", SYS_CLK_EN0_REG1, 26,
+ CLKID_SYS
+ ),
+ [CLKID_I2C_M_A] = CLK_GATE("i2c_m_a", SYS_CLK_EN0_REG1, 30,
+ CLKID_SYS
+ ),
+ [CLKID_I2C_M_B] = CLK_GATE("i2c_m_b", SYS_CLK_EN0_REG1, 31,
+ CLKID_SYS
+ ),
+
+ [CLKID_I2C_M_C] = CLK_GATE("i2c_m_c", SYS_CLK_EN0_REG2, 0,
+ CLKID_SYS
+ ),
+ [CLKID_I2C_M_D] = CLK_GATE("i2c_m_d", SYS_CLK_EN0_REG2, 1,
+ CLKID_SYS
+ ),
+ [CLKID_I2C_M_E] = CLK_GATE("i2c_m_e", SYS_CLK_EN0_REG2, 2,
+ CLKID_SYS
+ ),
+ [CLKID_USB1_TO_DDR] = CLK_GATE("usb1_to_ddr", SYS_CLK_EN0_REG2, 8,
+ CLKID_SYS
+ ),
+
+ [CLKID_PWM_AB] = CLK_GATE("pwm_ab", SYS_CLK_EN0_REG3, 7,
+ CLKID_SYS
+ ),
+ [CLKID_PWM_CD] = CLK_GATE("pwm_cd", SYS_CLK_EN0_REG3, 8,
+ CLKID_SYS
+ ),
+ [CLKID_PWM_EF] = CLK_GATE("pwm_ef", SYS_CLK_EN0_REG3, 9,
+ CLKID_SYS
+ ),
+ [CLKID_PWM_GH] = CLK_GATE("pwm_gh", SYS_CLK_EN0_REG3, 10,
+ CLKID_SYS
+ ),
+ [CLKID_PWM_IJ] = CLK_GATE("pwm_ij", SYS_CLK_EN0_REG3, 11,
+ CLKID_SYS
+ ),
+
+ [EXTERNAL_XTAL] = CLK_EXTERNAL("xtal"),
+ [EXTERNAL_FCLK_DIV2] = CLK_EXTERNAL("fclk_div2"),
+ [EXTERNAL_FCLK_DIV2P5] = CLK_EXTERNAL("fclk_div2p5"),
+ [EXTERNAL_FCLK_DIV3] = CLK_EXTERNAL("fclk_div3"),
+ [EXTERNAL_FCLK_DIV4] = CLK_EXTERNAL("fclk_div4"),
+ [EXTERNAL_FCLK_DIV5] = CLK_EXTERNAL("fclk_div5"),
+ [EXTERNAL_FCLK_DIV7] = CLK_EXTERNAL("fclk_div7"),
+ [EXTERNAL_HIFI_PLL] = CLK_EXTERNAL("hifi_pll"),
+ [EXTERNAL_GP0_PLL] = CLK_EXTERNAL("gp0_pll"),
+ [EXTERNAL_MPLL0] = CLK_EXTERNAL("mpll0"),
+ [EXTERNAL_MPLL1] = CLK_EXTERNAL("mpll1"),
+ [EXTERNAL_MPLL2] = CLK_EXTERNAL("mpll2"),
+ [EXTERNAL_MPLL3] = CLK_EXTERNAL("mpll3"),
+ [EXTERNAL_HDMI_PLL] = CLK_EXTERNAL("hdmi_pll"),
+};
+
+/* S4 PLL clocks */
+static const struct meson_clk_info *meson_pll_clocks[] = {
+ [CLKID_FIXED_PLL_DCO] = CLK_PLL("fixed_pll_dco", EXTERNAL_PLL_XTAL, {
+ {FIXPLL_CTRL0, 0, 8},
+ {FIXPLL_CTRL0, 10, 5},
+ }),
+ [CLKID_GP0_PLL_DCO] = CLK_PLL("gp0_pll_dco", EXTERNAL_PLL_XTAL, {
+ {GP0PLL_CTRL0, 0, 8},
+ {GP0PLL_CTRL0, 10, 5},
+ }),
+ [CLKID_HIFI_PLL_DCO] = CLK_PLL("hifi_pll_dco", EXTERNAL_PLL_XTAL, {
+ {HIFIPLL_CTRL0, 0, 8},
+ {HIFIPLL_CTRL0, 10, 5},
+ }),
+ [CLKID_HDMI_PLL_DCO] = CLK_PLL("hdmi_pll_dco", EXTERNAL_PLL_XTAL, {
+ {HDMIPLL_CTRL0, 0, 8},
+ {HDMIPLL_CTRL0, 10, 5},
+ }),
+
+ [CLKID_FIXED_PLL] = CLK_DIV2("fixed_pll", FIXPLL_CTRL0, 16, 2,
+ CLKID_FIXED_PLL_DCO
+ ),
+ [CLKID_FCLK_DIV2_DIV] = CLK_DIV_FIXED("fclk_div2_div", 2,
+ CLKID_FIXED_PLL
+ ),
+ [CLKID_FCLK_DIV2P5_DIV] = CLK_DIV_FIXED_FULL("fclk_div2p5_div", 2, 5,
+ CLKID_FIXED_PLL
+ ),
+ [CLKID_FCLK_DIV3_DIV] = CLK_DIV_FIXED("fclk_div3_div", 3,
+ CLKID_FIXED_PLL
+ ),
+ [CLKID_FCLK_DIV4_DIV] = CLK_DIV_FIXED("fclk_div4_div", 4,
+ CLKID_FIXED_PLL
+ ),
+ [CLKID_FCLK_DIV5_DIV] = CLK_DIV_FIXED("fclk_div5_div", 5,
+ CLKID_FIXED_PLL
+ ),
+ [CLKID_FCLK_DIV7_DIV] = CLK_DIV_FIXED("fclk_div7_div", 7,
+ CLKID_FIXED_PLL
+ ),
+ [CLKID_GP0_PLL] = CLK_DIV2("gp0_pll", GP0PLL_CTRL0, 16, 3,
+ CLKID_GP0_PLL_DCO
+ ),
+ [CLKID_HDMI_PLL_OD] = CLK_DIV2("hdmi_pll_od", HDMIPLL_CTRL0, 16, 4,
+ CLKID_HDMI_PLL_DCO
+ ),
+ [CLKID_MPLL_50M_DIV] = CLK_DIV_FIXED("mpll_50m_div", 80,
+ CLKID_FIXED_PLL_DCO
+ ),
+
+ [CLKID_FCLK_DIV2] = CLK_GATE("fclk_div2", FIXPLL_CTRL1, 24,
+ CLKID_FCLK_DIV2_DIV
+ ),
+ [CLKID_FCLK_DIV2P5] = CLK_GATE("fclk_div2p5", FIXPLL_CTRL1, 25,
+ CLKID_FCLK_DIV2P5_DIV
+ ),
+ [CLKID_FCLK_DIV3] = CLK_GATE("fclk_div3", FIXPLL_CTRL1, 20,
+ CLKID_FCLK_DIV3_DIV
+ ),
+ [CLKID_FCLK_DIV4] = CLK_GATE("fclk_div4", FIXPLL_CTRL1, 21,
+ CLKID_FCLK_DIV4_DIV
+ ),
+ [CLKID_FCLK_DIV5] = CLK_GATE("fclk_div5", FIXPLL_CTRL1, 22,
+ CLKID_FCLK_DIV5_DIV
+ ),
+ [CLKID_FCLK_DIV7] = CLK_GATE("fclk_div7", FIXPLL_CTRL1, 23,
+ CLKID_FCLK_DIV7_DIV
+ ),
+ [CLKID_HIFI_PLL] = CLK_DIV2("hifi_pll", HIFIPLL_CTRL0, 16, 2,
+ CLKID_HIFI_PLL_DCO
+ ),
+ [CLKID_HDMI_PLL] = CLK_DIV("hdmi_pll", HDMIPLL_CTRL0, 20, 2,
+ CLKID_HDMI_PLL_OD
+ ),
+ [CLKID_MPLL_50M] = CLK_MUX("mpll_50m", FIXPLL_CTRL3, 5, 1, {
+ EXTERNAL_PLL_XTAL,
+ CLKID_MPLL_50M_DIV,
+ }),
+ [CLKID_MPLL0] = CLK_GATE("mpll0", MPLL_CTRL1, 31,
+ -ENOENT
+ ),
+ [CLKID_MPLL1] = CLK_GATE("mpll1", MPLL_CTRL3, 31,
+ -ENOENT
+ ),
+ [CLKID_MPLL2] = CLK_GATE("mpll2", MPLL_CTRL5, 31,
+ -ENOENT
+ ),
+ [CLKID_MPLL3] = CLK_GATE("mpll3", MPLL_CTRL7, 31,
+ -ENOENT
+ ),
+
+ [EXTERNAL_PLL_XTAL] = CLK_EXTERNAL("xtal"),
+};
+
+static ulong meson_clk_set_rate(struct clk *clk, ulong rate)
+{
+ switch (clk->id) {
+ case CLKID_SD_EMMC_A_CLK_DIV:
+ case CLKID_SD_EMMC_B_CLK_DIV:
+ case CLKID_SD_EMMC_C_CLK_DIV:
+ return meson_composite_set_rate(clk, rate);
+ case CLKID_SD_EMMC_A:
+ case CLKID_SD_EMMC_B:
+ case CLKID_SD_EMMC_C: {
+ struct clk parent = {
+ .dev = clk->dev,
+ .id = meson_clk_get_parent(clk),
+ };
+
+ return meson_clk_set_rate(&parent, rate);
+ }
+ }
+
+ return -EINVAL;
+}
+
+static int meson_clk_probe(struct udevice *dev)
+{
+ struct meson_clk *priv = dev_get_priv(dev);
+
+ return regmap_init_mem(dev_ofnode(dev), &priv->map);
+}
+
+struct meson_clk_data meson_s4_peripherals_info = {
+ .clocks = meson_clocks,
+ .num_clocks = ARRAY_SIZE(meson_clocks),
+};
+
+struct meson_clk_data meson_s4_pll_info = {
+ .clocks = meson_pll_clocks,
+ .num_clocks = ARRAY_SIZE(meson_pll_clocks),
+};
+
+static const struct udevice_id meson_clk_ids[] = {
+ {
+ .compatible = "amlogic,s4-peripherals-clkc",
+ .data = (ulong)&meson_s4_peripherals_info,
+ },
+ {
+ .compatible = "amlogic,s4-pll-clkc",
+ .data = (ulong)&meson_s4_pll_info,
+ },
+ { }
+};
+
+static struct clk_ops meson_clk_ops = {
+ .disable = meson_clk_disable,
+ .enable = meson_clk_enable,
+ .get_rate = meson_clk_get_rate,
+ .set_rate = meson_clk_set_rate,
+ .set_parent = meson_clk_set_parent,
+#if IS_ENABLED(CONFIG_CMD_CLK)
+ .dump = meson_clk_dump,
+#endif
+};
+
+U_BOOT_DRIVER(meson_clk_s4) = {
+ .name = "meson-clk-s4",
+ .id = UCLASS_CLK,
+ .of_match = meson_clk_ids,
+ .priv_auto = sizeof(struct meson_clk),
+ .ops = &meson_clk_ops,
+ .probe = meson_clk_probe,
+};
--
2.53.0