[PATCH 8/9] clk: meson: Add s4 clock driver

Sean Anderson <[email protected]>
Newsgroups gmane.comp.boot-loaders.u-boot
Message-ID <20260817171623.1943847-9-sanderson__10129.1148270079$1786990694$gmane$org@brivo.com>
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
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.