Hello Stephen, Sorry, do you have chance review my v4 modification? > Subject: [PATCH v4 3/3] clk: aspeed: add AST2700 clock driver. > > Add AST2700 clock controller driver and also use axiliary device framework > register the reset controller driver. > Due to clock and reset using the same register region. > > Signed-off-by: Ryan Chen <ryan_chen@xxxxxxxxxxxxxx> > --- > drivers/clk/Kconfig | 8 + > drivers/clk/Makefile | 1 + > drivers/clk/clk-ast2700.c | 1553 > +++++++++++++++++++++++++++++++++++++ > 3 files changed, 1562 insertions(+) > create mode 100644 drivers/clk/clk-ast2700.c > > diff --git a/drivers/clk/Kconfig b/drivers/clk/Kconfig index > 983ef4f36d8c..4cc35ecba1c0 100644 > --- a/drivers/clk/Kconfig > +++ b/drivers/clk/Kconfig > @@ -269,6 +269,14 @@ config COMMON_CLK_ASPEED > The G4 and G5 series, including the ast2400 and ast2500, are > supported > by this driver. > > +config COMMON_CLK_AST2700 > + bool "Clock driver for AST2700 SoC" > + depends on ARCH_ASPEED || COMPILE_TEST > + help > + This driver provides support for clock on AST2700 SoC. > + The driver is responsible for managing the various clocks required > + by the peripherals and cores within the AST2700. > + > config COMMON_CLK_S2MPS11 > tristate "Clock driver for S2MPS1X/S5M8767 MFD" > depends on MFD_SEC_CORE || COMPILE_TEST diff --git > a/drivers/clk/Makefile b/drivers/clk/Makefile index > f793a16cad40..fe95203c3138 100644 > --- a/drivers/clk/Makefile > +++ b/drivers/clk/Makefile > @@ -38,6 +38,7 @@ obj-$(CONFIG_COMMON_CLK_FSL_SAI) += clk-fsl-sai.o > obj-$(CONFIG_COMMON_CLK_GEMINI) += clk-gemini.o > obj-$(CONFIG_COMMON_CLK_ASPEED) += clk-aspeed.o > obj-$(CONFIG_MACH_ASPEED_G6) += clk-ast2600.o > +obj-$(CONFIG_COMMON_CLK_AST2700) += clk-ast2700.o > obj-$(CONFIG_ARCH_HIGHBANK) += clk-highbank.o > obj-$(CONFIG_CLK_HSDK) += clk-hsdk-pll.o > obj-$(CONFIG_COMMON_CLK_K210) += clk-k210.o > diff --git a/drivers/clk/clk-ast2700.c b/drivers/clk/clk-ast2700.c new file mode > 100644 index 000000000000..933b5232d7c1 > --- /dev/null > +++ b/drivers/clk/clk-ast2700.c > @@ -0,0 +1,1553 @@ > +// SPDX-License-Identifier: GPL-2.0 > +/* > + * Copyright (c) 2024 ASPEED Technology Inc. > + * Author: Ryan Chen <ryan_chen@xxxxxxxxxxxxxx> */ > + > +#include <linux/auxiliary_bus.h> > +#include <linux/clk-provider.h> > +#include <linux/of_address.h> > +#include <linux/of_device.h> > +#include <linux/of_platform.h> > +#include <linux/platform_device.h> > +#include <linux/slab.h> > + > +#include <dt-bindings/clock/aspeed,ast2700-scu.h> > + > +#define SCU_CLK_12MHZ 12000000 > +#define SCU_CLK_24MHZ 24000000 > +#define SCU_CLK_25MHZ 25000000 > +#define SCU_CLK_192MHZ 192000000 > + > +/* SOC0 */ > +#define SCU0_HWSTRAP1 0x010 > +#define SCU0_CLK_STOP 0x240 > +#define SCU0_CLK_SEL1 0x280 > +#define SCU0_CLK_SEL2 0x284 > +#define GET_USB_REFCLK_DIV(x) ((GENMASK(23, 20) & (x)) >> 20) #define > +UART_DIV13_EN BIT(30) #define SCU0_HPLL_PARAM 0x300 #define > +SCU0_DPLL_PARAM 0x308 #define SCU0_MPLL_PARAM 0x310 #define > +SCU0_D0CLK_PARAM 0x320 #define SCU0_D1CLK_PARAM 0x330 #define > +SCU0_CRT0CLK_PARAM 0x340 #define SCU0_CRT1CLK_PARAM 0x350 > #define > +SCU0_MPHYCLK_PARAM 0x360 > + > +/* SOC1 */ > +#define SCU1_REVISION_ID 0x0 > +#define REVISION_ID GENMASK(23, 16) > +#define SCU1_CLK_STOP 0x240 > +#define SCU1_CLK_STOP2 0x260 > +#define SCU1_CLK_SEL1 0x280 > +#define SCU1_CLK_SEL2 0x284 > +#define UXCLK_MASK GENMASK(1, 0) > +#define HUXCLK_MASK GENMASK(4, 3) > +#define SCU1_HPLL_PARAM 0x300 > +#define SCU1_APLL_PARAM 0x310 > +#define SCU1_DPLL_PARAM 0x320 > +#define SCU1_UXCLK_CTRL 0x330 > +#define SCU1_HUXCLK_CTRL 0x334 > +#define SCU1_MAC12_CLK_DLY 0x390 > +#define SCU1_MAC12_CLK_DLY_100M 0x394 > +#define SCU1_MAC12_CLK_DLY_10M 0x398 > + > +enum { > + CLK_MUX, > + CLK_PLL, > + CLK_GATE, > + CLK_MISC, > + CLK_FIXED, > + CLK_DIVIDER, > + CLK_UART_PLL, > + CLK_DIV_TABLE, > + CLK_FIXED_FACTOR, > +}; > + > +struct ast2700_clk_info { > + const char *name; > + const char * const *parent_names; > + const struct clk_div_table *div_table; > + unsigned long fixed_rate; > + unsigned int mult; > + unsigned int div; > + u32 reg; > + u32 flags; > + u32 type; > + u8 clk_idx; > + u8 bit_shift; > + u8 bit_width; > + u8 num_parents; > +}; > + > +struct ast2700_clk_data { > + struct ast2700_clk_info const *clk_info; > + unsigned int nr_clks; > + const int scu; > +}; > + > +struct ast2700_clk_ctrl { > + const struct ast2700_clk_data *clk_data; > + struct device *dev; > + void __iomem *base; > + spinlock_t lock; /* clk lock */ > +}; > + > +static const struct clk_div_table ast2700_rgmii_div_table[] = { > + { 0x0, 4 }, > + { 0x1, 4 }, > + { 0x2, 6 }, > + { 0x3, 8 }, > + { 0x4, 10 }, > + { 0x5, 12 }, > + { 0x6, 14 }, > + { 0x7, 16 }, > + { 0 } > +}; > + > +static const struct clk_div_table ast2700_rmii_div_table[] = { > + { 0x0, 8 }, > + { 0x1, 8 }, > + { 0x2, 12 }, > + { 0x3, 16 }, > + { 0x4, 20 }, > + { 0x5, 24 }, > + { 0x6, 28 }, > + { 0x7, 32 }, > + { 0 } > +}; > + > +static const struct clk_div_table ast2700_clk_div_table[] = { > + { 0x0, 2 }, > + { 0x1, 2 }, > + { 0x2, 3 }, > + { 0x3, 4 }, > + { 0x4, 5 }, > + { 0x5, 6 }, > + { 0x6, 7 }, > + { 0x7, 8 }, > + { 0 } > +}; > + > +static const struct clk_div_table ast2700_clk_div_table2[] = { > + { 0x0, 2 }, > + { 0x1, 4 }, > + { 0x2, 6 }, > + { 0x3, 8 }, > + { 0x4, 10 }, > + { 0x5, 12 }, > + { 0x6, 14 }, > + { 0x7, 16 }, > + { 0 } > +}; > + > +static const struct clk_div_table ast2700_clk_uart_div_table[] = { > + { 0x0, 1 }, > + { 0x1, 13 }, > + { 0 } > +}; > + > +static const struct ast2700_clk_info ast2700_scu0_clk_info[] __initconst = { > + [SCU0_CLKIN] = { > + .type = CLK_FIXED, > + .name = "soc0-clkin", > + .fixed_rate = SCU_CLK_25MHZ, > + }, > + [SCU0_CLK_24M] = { > + .type = CLK_FIXED, > + .name = "soc0-clk24Mhz", > + .fixed_rate = SCU_CLK_24MHZ, > + }, > + [SCU0_CLK_192M] = { > + .type = CLK_FIXED, > + .name = "soc0-clk192Mhz", > + .fixed_rate = SCU_CLK_192MHZ, > + }, > + [SCU0_CLK_HPLL] = { > + .type = CLK_PLL, > + .name = "soc0-hpll", > + .parent_names = (const char *[]){ "soc0-clkin", }, > + .reg = SCU0_HPLL_PARAM, > + }, > + [SCU0_CLK_HPLL_DIV2] = { > + .type = CLK_FIXED_FACTOR, > + .name = "soc0-hpll_div2", > + .parent_names = (const char *[]){ "soc0-hpll", }, > + .mult = 1, > + .div = 2, > + }, > + [SCU0_CLK_HPLL_DIV4] = { > + .type = CLK_FIXED_FACTOR, > + .name = "soc0-hpll_div4", > + .parent_names = (const char *[]){ "soc0-hpll", }, > + .mult = 1, > + .div = 4, > + }, > + [SCU0_CLK_HPLL_DIV_AHB] = { > + .type = CLK_DIV_TABLE, > + .name = "soc0-hpll_div_ahb", > + .parent_names = (const char *[]){ "soc0-hpll", }, > + .reg = SCU0_HWSTRAP1, > + .bit_shift = 5, > + .bit_width = 2, > + .div_table = ast2700_clk_div_table, > + }, > + [SCU0_CLK_DPLL] = { > + .type = CLK_PLL, > + .name = "dpll", > + .parent_names = (const char *[]){ "soc0-clkin", }, > + .reg = SCU0_DPLL_PARAM, > + }, > + [SCU0_CLK_MPLL] = { > + .type = CLK_PLL, > + .name = "soc0-mpll", > + .parent_names = (const char *[]){ "soc0-clkin", }, > + .reg = SCU0_MPLL_PARAM, > + }, > + [SCU0_CLK_MPLL_DIV2] = { > + .type = CLK_FIXED_FACTOR, > + .name = "soc0-mpll_div2", > + .parent_names = (const char *[]){ "soc0-mpll", }, > + .mult = 1, > + .div = 2, > + }, > + [SCU0_CLK_MPLL_DIV4] = { > + .type = CLK_FIXED_FACTOR, > + .name = "soc0-mpll_div4", > + .parent_names = (const char *[]){ "soc0-mpll", }, > + .mult = 1, > + .div = 4, > + }, > + [SCU0_CLK_MPLL_DIV8] = { > + .type = CLK_FIXED_FACTOR, > + .name = "soc0-mpll_div8", > + .parent_names = (const char *[]){ "soc0-mpll", }, > + .mult = 1, > + .div = 8, > + }, > + [SCU0_CLK_MPLL_DIV_AHB] = { > + .type = CLK_DIV_TABLE, > + .name = "soc0-mpll_div_ahb", > + .parent_names = (const char *[]){ "soc0-mpll", }, > + .reg = SCU0_HWSTRAP1, > + .bit_shift = 5, > + .bit_width = 2, > + .div_table = ast2700_clk_div_table, > + }, > + [SCU0_CLK_D0] = { > + .type = CLK_PLL, > + .name = "d0clk", > + .parent_names = (const char *[]){ "soc0-clkin", }, > + .reg = SCU0_D0CLK_PARAM, > + }, > + [SCU0_CLK_D1] = { > + .type = CLK_PLL, > + .name = "d1clk", > + .parent_names = (const char *[]){ "soc0-clkin", }, > + .reg = SCU0_D1CLK_PARAM, > + }, > + [SCU0_CLK_CRT0] = { > + .type = CLK_PLL, > + .name = "crt0clk", > + .parent_names = (const char *[]){ "soc0-clkin", }, > + .reg = SCU0_CRT0CLK_PARAM, > + }, > + [SCU0_CLK_CRT1] = { > + .type = CLK_PLL, > + .name = "crt1clk", > + .parent_names = (const char *[]){ "soc0-clkin", }, > + .reg = SCU0_CRT1CLK_PARAM, > + }, > + [SCU0_CLK_MPHY] = { > + .type = CLK_MISC, > + .name = "mphyclk", > + .parent_names = (const char *[]){ "soc0-hpll", }, > + .reg = SCU0_MPHYCLK_PARAM, > + }, > + [SCU0_CLK_PSP] = { > + .type = CLK_MUX, > + .name = "pspclk", > + .parent_names = (const char *[]){"soc0-mpll", "soc0-hpll", }, > + .num_parents = 2, > + .reg = SCU0_HWSTRAP1, > + .bit_shift = 4, > + .bit_width = 1, > + }, > + [SCU0_CLK_AXI0] = { > + .type = CLK_FIXED_FACTOR, > + .name = "axi0clk", > + .parent_names = (const char *[]){"pspclk", }, > + .mult = 1, > + .div = 2, > + }, > + [SCU0_CLK_AHB] = { > + .type = CLK_MUX, > + .name = "soc0-ahb", > + .parent_names = (const char *[]){"soc0-mpll_div_ahb", > "soc0-hspll_div_ahb", }, > + .num_parents = 2, > + .reg = SCU0_HWSTRAP1, > + .bit_shift = 7, > + .bit_width = 1, > + }, > + [SCU0_CLK_AXI1] = { > + .type = CLK_FIXED_FACTOR, > + .name = "axi1clk", > + .parent_names = (const char *[]){ "soc0-ahb", }, > + .mult = 1, > + .div = 2, > + }, > + [SCU0_CLK_APB] = { > + .type = CLK_DIV_TABLE, > + .name = "soc0-apb", > + .parent_names = (const char *[]){ "axi0clk", }, > + .reg = SCU0_CLK_SEL1, > + .bit_shift = 23, > + .bit_width = 3, > + .div_table = ast2700_clk_div_table2, > + }, > + [SCU0_CLK_GATE_MCLK] = { > + .type = CLK_GATE, > + .name = "mclk", > + .parent_names = (const char *[]){ "soc0-mpll", }, > + .reg = SCU0_CLK_STOP, > + .clk_idx = 0, > + .flags = CLK_IS_CRITICAL, > + }, > + [SCU0_CLK_GATE_ECLK] = { > + .type = CLK_GATE, > + .name = "eclk", > + .parent_names = (const char *[]){ }, > + .reg = SCU0_CLK_STOP, > + .clk_idx = 1, > + }, > + [SCU0_CLK_GATE_2DCLK] = { > + .type = CLK_GATE, > + .name = "gclk", > + .parent_names = (const char *[]){ }, > + .reg = SCU0_CLK_STOP, > + .clk_idx = 2, > + }, > + [SCU0_CLK_GATE_VCLK] = { > + .type = CLK_GATE, > + .name = "vclk", > + .parent_names = (const char *[]){ }, > + .reg = SCU0_CLK_STOP, > + .clk_idx = 3, > + }, > + [SCU0_CLK_GATE_BCLK] = { > + .type = CLK_GATE, > + .name = "bclk", > + .parent_names = (const char *[]){ }, > + .reg = SCU0_CLK_STOP, > + .clk_idx = 4, > + .flags = CLK_IS_CRITICAL, > + }, > + [SCU0_CLK_GATE_VGA0CLK] = { > + .type = CLK_GATE, > + .name = "d1clk-gate", > + .parent_names = (const char *[]){ }, > + .reg = SCU0_CLK_STOP, > + .clk_idx = 5, > + .flags = CLK_IS_CRITICAL, > + }, > + [SCU0_CLK_GATE_REFCLK] = { > + .type = CLK_GATE, > + .name = "soc0-refclk-gate", > + .parent_names = (const char *[]){ "soc0-clkin", }, > + .reg = SCU0_CLK_STOP, > + .clk_idx = 6, > + .flags = CLK_IS_CRITICAL, > + }, > + [SCU0_CLK_U2PHY_REFCLK] = { > + .type = CLK_MISC, > + .name = "xhci_ref_clk", > + .parent_names = (const char *[]){ "soc0-mpll_div8", }, > + .reg = SCU0_CLK_SEL2, > + }, > + [SCU0_CLK_U2PHY_CLK12M] = { > + .type = CLK_FIXED, > + .name = "xhci_suspend_clk", > + .parent_names = (const char *[]){ }, > + .fixed_rate = SCU_CLK_12MHZ, > + }, > + [SCU0_CLK_GATE_PORTBUSB2CLK] = { > + .type = CLK_GATE, > + .name = "portb-usb2clk", > + .parent_names = (const char *[]){ }, > + .reg = SCU0_CLK_STOP, > + .clk_idx = 7, > + }, > + [SCU0_CLK_GATE_UHCICLK] = { > + .type = CLK_GATE, > + .name = "uhciclk", > + .parent_names = (const char *[]){ }, > + .reg = SCU0_CLK_STOP, > + .clk_idx = 9, > + }, > + [SCU0_CLK_GATE_VGA1CLK] = { > + .type = CLK_GATE, > + .name = "d2clk-gate", > + .parent_names = (const char *[]){ }, > + .reg = SCU0_CLK_STOP, > + .clk_idx = 10, > + .flags = CLK_IS_CRITICAL, > + }, > + [SCU0_CLK_GATE_DDRPHYCLK] = { > + .type = CLK_GATE, > + .name = "ddrphy-gate", > + .parent_names = (const char *[]){ }, > + .reg = SCU0_CLK_STOP, > + .clk_idx = 11, > + .flags = CLK_IS_CRITICAL, > + }, > + [SCU0_CLK_GATE_E2M0CLK] = { > + .type = CLK_GATE, > + .name = "e2m0clk-gate", > + .parent_names = (const char *[]){ }, > + .reg = SCU0_CLK_STOP, > + .clk_idx = 12, > + .flags = CLK_IS_CRITICAL, > + }, > + [SCU0_CLK_GATE_HACCLK] = { > + .type = CLK_GATE, > + .name = "hac-clk", > + .parent_names = (const char *[]){ }, > + .reg = SCU0_CLK_STOP, > + .clk_idx = 13, > + }, > + [SCU0_CLK_GATE_PORTAUSB2CLK] = { > + .type = CLK_GATE, > + .name = "porta-usb2clk", > + .parent_names = (const char *[]){ }, > + .reg = SCU0_CLK_STOP, > + .clk_idx = 14, > + }, > + [SCU0_CLK_UART] = { > + .type = CLK_MUX, > + .name = "soc0-uartclk", > + .parent_names = (const char *[]){"soc0-clk24Mhz", > "soc0-clk192Mhz", }, > + .num_parents = 2, > + .reg = SCU0_CLK_SEL2, > + .bit_shift = 14, > + .bit_width = 1, > + }, > + [SCU0_CLK_UART4] = { > + .type = CLK_DIV_TABLE, > + .name = "uart4clk", > + .parent_names = (const char *[]){ "soc0-uartclk", }, > + .reg = SCU0_CLK_SEL2, > + .bit_shift = 30, > + .bit_width = 1, > + .div_table = ast2700_clk_uart_div_table, > + }, > + [SCU0_CLK_GATE_UART4CLK] = { > + .type = CLK_GATE, > + .name = "uart4clk-gate", > + .parent_names = (const char *[]){"uart4clk" }, > + .reg = SCU0_CLK_STOP, > + .clk_idx = 15, > + .flags = CLK_IS_CRITICAL, > + }, > + [SCU0_CLK_GATE_SLICLK] = { > + .type = CLK_GATE, > + .name = "soc0-sliclk-gate", > + .parent_names = (const char *[]){ }, > + .reg = SCU0_CLK_STOP, > + .clk_idx = 16, > + .flags = CLK_IS_CRITICAL, > + }, > + [SCU0_CLK_GATE_DACCLK] = { > + .type = CLK_GATE, > + .name = "dacclk-gate", > + .parent_names = (const char *[]){ }, > + .reg = SCU0_CLK_STOP, > + .clk_idx = 17, > + .flags = CLK_IS_CRITICAL, > + }, > + [SCU0_CLK_GATE_DP] = { > + .type = CLK_GATE, > + .name = "dpclk-gate", > + .parent_names = (const char *[]){ }, > + .reg = SCU0_CLK_STOP, > + .clk_idx = 18, > + .flags = CLK_IS_CRITICAL, > + }, > + [SCU0_CLK_GATE_E2M1CLK] = { > + .type = CLK_GATE, > + .name = "e2m1clk-gate", > + .parent_names = (const char *[]){ }, > + .reg = SCU0_CLK_STOP, > + .clk_idx = 19, > + .flags = CLK_IS_CRITICAL, > + }, > + [SCU0_CLK_GATE_CRT0CLK] = { > + .type = CLK_GATE, > + .name = "crt0clk-gate", > + .parent_names = (const char *[]){ }, > + .reg = SCU0_CLK_STOP, > + .clk_idx = 20, > + }, > + [SCU0_CLK_GATE_CRT1CLK] = { > + .type = CLK_GATE, > + .name = "crt1clk-gate", > + .parent_names = (const char *[]){ }, > + .reg = SCU0_CLK_STOP, > + .clk_idx = 21, > + }, > + [SCU0_CLK_GATE_ECDSACLK] = { > + .type = CLK_GATE, > + .name = "eccclk", > + .parent_names = (const char *[]){ }, > + .reg = SCU0_CLK_STOP, > + .clk_idx = 23, > + }, > + [SCU0_CLK_GATE_RSACLK] = { > + .type = CLK_GATE, > + .name = "rsaclk", > + .parent_names = (const char *[]){ }, > + .reg = SCU0_CLK_STOP, > + .clk_idx = 24, > + }, > + [SCU0_CLK_GATE_RVAS0CLK] = { > + .type = CLK_GATE, > + .name = "rvasclk", > + .parent_names = (const char *[]){ }, > + .reg = SCU0_CLK_STOP, > + .clk_idx = 25, > + }, > + [SCU0_CLK_GATE_UFSCLK] = { > + .type = CLK_GATE, > + .name = "ufsclk", > + .parent_names = (const char *[]){ }, > + .reg = SCU0_CLK_STOP, > + .clk_idx = 26, > + }, > + [SCU0_CLK_EMMCMUX] = { > + .type = CLK_MUX, > + .name = "emmcsrc-mux", > + .parent_names = (const char *[]){"soc0-mpll_div4", > "soc0-hpll_div4", }, > + .num_parents = 2, > + .reg = SCU0_CLK_SEL1, > + .bit_shift = 11, > + .bit_width = 1, > + }, > + [SCU0_CLK_EMMC] = { > + .type = CLK_DIV_TABLE, > + .name = "emmcclk", > + .parent_names = (const char *[]){ "emmcsrc-mux", }, > + .reg = SCU0_CLK_SEL1, > + .bit_shift = 12, > + .bit_width = 3, > + .div_table = ast2700_clk_div_table2, > + }, > + [SCU0_CLK_GATE_EMMCCLK] = { > + .type = CLK_GATE, > + .name = "emmcclk-gate", > + .parent_names = (const char *[]){ "emmcclk", }, > + .reg = SCU0_CLK_STOP, > + .clk_idx = 27, > + }, > + [SCU0_CLK_GATE_RVAS1CLK] = { > + .type = CLK_GATE, > + .name = "rvas2clk", > + .parent_names = (const char *[]){ "emmcclk", }, > + .reg = SCU0_CLK_STOP, > + .clk_idx = 28, > + }, > +}; > + > +static const struct ast2700_clk_info ast2700_scu1_clk_info[] __initconst = { > + [SCU1_CLKIN] = { > + .type = CLK_FIXED, > + .name = "soc1-clkin", > + .fixed_rate = SCU_CLK_25MHZ, > + }, > + [SCU1_CLK_HPLL] = { > + .type = CLK_PLL, > + .name = "soc1-hpll", > + .parent_names = (const char *[]){ "soc1-clkin", }, > + .reg = SCU1_HPLL_PARAM, > + }, > + [SCU1_CLK_APLL] = { > + .type = CLK_PLL, > + .name = "soc1-apll", > + .parent_names = (const char *[]){ "soc1-clkin", }, > + .reg = SCU1_APLL_PARAM, > + }, > + [SCU1_CLK_APLL_DIV2] = { > + .type = CLK_FIXED_FACTOR, > + .name = "soc1-apll_div2", > + .parent_names = (const char *[]){ "soc1-apll", }, > + .mult = 1, > + .div = 2, > + }, > + [SCU1_CLK_APLL_DIV4] = { > + .type = CLK_FIXED_FACTOR, > + .name = "soc1-apll_div4", > + .parent_names = (const char *[]){ "soc1-apll", }, > + .mult = 1, > + .div = 4, > + }, > + [SCU1_CLK_DPLL] = { > + .type = CLK_PLL, > + .name = "soc1-dpll", > + .parent_names = (const char *[]){ "soc1-clkin", }, > + .reg = SCU1_DPLL_PARAM, > + }, > + [SCU1_CLK_UXCLK] = { > + .type = CLK_MUX, > + .name = "uxclk", > + .parent_names = (const char *[]){ "soc1-apll_div4", "soc1-apll_div2", > + "soc1-apll", "soc1-hpll",}, > + .num_parents = 4, > + .reg = SCU1_CLK_SEL2, > + .bit_shift = 0, > + .bit_width = 2, > + }, > + [SCU1_CLK_UARTX] = { > + .type = CLK_UART_PLL, > + .name = "uartxclk", > + .parent_names = (const char *[]){ "uxclk", }, > + .reg = SCU1_UXCLK_CTRL, > + }, > + [SCU1_CLK_HUXCLK] = { > + .type = CLK_MUX, > + .name = "huxclk", > + .parent_names = (const char *[]){"soc1-apll_div4", "soc1-apll_div2", > + "soc1-apll", "soc1-hpll",}, > + .num_parents = 4, > + .reg = SCU1_CLK_SEL2, > + .bit_shift = 3, > + .bit_width = 2, > + }, > + [SCU1_CLK_HUARTX] = { > + .type = CLK_UART_PLL, > + .name = "huartxclk", > + .parent_names = (const char *[]){ "huxclk", }, > + .reg = SCU1_HUXCLK_CTRL, > + }, > + [SCU1_CLK_AHB] = { > + .type = CLK_DIV_TABLE, > + .name = "soc1-ahb", > + .parent_names = (const char *[]){"soc1-hpll", }, > + .reg = SCU1_CLK_SEL2, > + .bit_shift = 20, > + .bit_width = 3, > + .div_table = ast2700_clk_div_table, > + }, > + [SCU1_CLK_APB] = { > + .type = CLK_DIV_TABLE, > + .name = "soc1-apb", > + .parent_names = (const char *[]){"soc1-hpll", }, > + .reg = SCU1_CLK_SEL1, > + .bit_shift = 18, > + .bit_width = 3, > + .div_table = ast2700_clk_div_table2, > + }, > + [SCU1_CLK_RMII] = { > + .type = CLK_DIV_TABLE, > + .name = "rmii", > + .parent_names = (const char *[]){"soc1-hpll", }, > + .reg = SCU1_CLK_SEL1, > + .bit_shift = 21, > + .bit_width = 3, > + .div_table = ast2700_rmii_div_table, > + }, > + [SCU1_CLK_MAC0RCLK] = { > + .type = CLK_GATE, > + .name = "mac0rclk", > + .parent_names = (const char *[]){ "rmii", }, > + .reg = SCU1_MAC12_CLK_DLY, > + .clk_idx = 29, > + }, > + [SCU1_CLK_MAC1RCLK] = { > + .type = CLK_GATE, > + .name = "mac1rclk", > + .parent_names = (const char *[]){ "rmii", }, > + .reg = SCU1_MAC12_CLK_DLY, > + .clk_idx = 30, > + }, > + [SCU1_CLK_RGMII] = { > + .type = CLK_DIV_TABLE, > + .name = "rgmii", > + .parent_names = (const char *[]){"soc1-hpll", }, > + .reg = SCU1_CLK_SEL1, > + .bit_shift = 25, > + .bit_width = 3, > + .div_table = ast2700_rgmii_div_table, > + }, > + [SCU1_CLK_MACHCLK] = { > + .type = CLK_DIV_TABLE, > + .name = "machclk", > + .parent_names = (const char *[]){"soc1-hpll", }, > + .reg = SCU1_CLK_SEL1, > + .bit_shift = 29, > + .bit_width = 3, > + .div_table = ast2700_clk_div_table, > + }, > + [SCU1_CLK_GATE_LCLK0] = { > + .type = CLK_GATE, > + .name = "lclk0-gate", > + .parent_names = (const char *[]){ }, > + .reg = SCU1_CLK_STOP, > + .clk_idx = 0, > + .flags = CLK_IS_CRITICAL, > + }, > + [SCU1_CLK_GATE_LCLK1] = { > + .type = CLK_GATE, > + .name = "lclk1-gate", > + .parent_names = (const char *[]){ }, > + .reg = SCU1_CLK_STOP, > + .clk_idx = 1, > + .flags = CLK_IS_CRITICAL, > + }, > + [SCU1_CLK_GATE_ESPI0CLK] = { > + .type = CLK_GATE, > + .name = "espi0clk-gate", > + .parent_names = (const char *[]){ }, > + .reg = SCU1_CLK_STOP, > + .clk_idx = 2, > + .flags = CLK_IS_CRITICAL, > + }, > + [SCU1_CLK_GATE_ESPI1CLK] = { > + .type = CLK_GATE, > + .name = "espi1clk-gate", > + .parent_names = (const char *[]){ }, > + .reg = SCU1_CLK_STOP, > + .clk_idx = 3, > + .flags = CLK_IS_CRITICAL, > + }, > + [SCU1_CLK_APLL_DIVN] = { > + .type = CLK_DIV_TABLE, > + .name = "soc1-apll_divn", > + .parent_names = (const char *[]){"soc1-apll", }, > + .reg = SCU1_CLK_SEL2, > + .bit_shift = 8, > + .bit_width = 3, > + .div_table = ast2700_clk_div_table, > + }, > + [SCU1_CLK_SDMUX] = { > + .type = CLK_MUX, > + .name = "sdclk-mux", > + .parent_names = (const char *[]){ "soc1-hpll", "soc1-apll", }, > + .num_parents = 2, > + .reg = SCU1_CLK_SEL1, > + .bit_shift = 13, > + .bit_width = 1, > + }, > + [SCU1_CLK_SDCLK] = { > + .type = CLK_DIV_TABLE, > + .name = "sdclk", > + .parent_names = (const char *[]){"sdclk-mux", }, > + .reg = SCU1_CLK_SEL1, > + .bit_shift = 14, > + .bit_width = 3, > + .div_table = ast2700_clk_div_table, > + }, > + [SCU1_CLK_GATE_SDCLK] = { > + .type = CLK_GATE, > + .name = "sdclk-gate", > + .parent_names = (const char *[]){"sdclk", }, > + .reg = SCU1_CLK_STOP, > + .clk_idx = 4, > + }, > + [SCU1_CLK_GATE_IPEREFCLK] = { > + .type = CLK_GATE, > + .name = "soc1-iperefclk-gate", > + .parent_names = (const char *[]){ }, > + .reg = SCU1_CLK_STOP, > + .clk_idx = 5, > + .flags = CLK_IS_CRITICAL, > + }, > + [SCU1_CLK_GATE_REFCLK] = { > + .type = CLK_GATE, > + .name = "soc1-refclk-gate", > + .parent_names = (const char *[]){ }, > + .reg = SCU1_CLK_STOP, > + .clk_idx = 6, > + .flags = CLK_IS_CRITICAL, > + }, > + [SCU1_CLK_GATE_LPCHCLK] = { > + .type = CLK_GATE, > + .name = "lpchclk-gate", > + .parent_names = (const char *[]){ }, > + .reg = SCU1_CLK_STOP, > + .clk_idx = 7, > + .flags = CLK_IS_CRITICAL, > + }, > + [SCU1_CLK_GATE_MAC0CLK] = { > + .type = CLK_GATE, > + .name = "mac0clk-gate", > + .parent_names = (const char *[]){ }, > + .reg = SCU1_CLK_STOP, > + .clk_idx = 8, > + }, > + [SCU1_CLK_GATE_MAC1CLK] = { > + .type = CLK_GATE, > + .name = "mac1clk-gate", > + .parent_names = (const char *[]){ }, > + .reg = SCU1_CLK_STOP, > + .clk_idx = 9, > + }, > + [SCU1_CLK_GATE_MAC2CLK] = { > + .type = CLK_GATE, > + .name = "mac2clk-gate", > + .parent_names = (const char *[]){ }, > + .reg = SCU1_CLK_STOP, > + .clk_idx = 10, > + }, > + [SCU1_CLK_UART0] = { > + .type = CLK_MUX, > + .name = "uart0clk", > + .parent_names = (const char *[]){"uartxclk", "huartxclk", }, > + .num_parents = 2, > + .reg = SCU1_CLK_SEL1, > + .bit_shift = 0, > + .bit_width = 1, > + }, > + [SCU1_CLK_GATE_UART0CLK] = { > + .type = CLK_GATE, > + .name = "uart0clk-gate", > + .parent_names = (const char *[]){ "uart0clk", }, > + .reg = SCU1_CLK_STOP, > + .clk_idx = 11, > + }, > + [SCU1_CLK_UART1] = { > + .type = CLK_MUX, > + .name = "uart1clk", > + .parent_names = (const char *[]){"uartxclk", "huartxclk", }, > + .num_parents = 2, > + .reg = SCU1_CLK_SEL1, > + .bit_shift = 1, > + .bit_width = 1, > + }, > + [SCU1_CLK_GATE_UART1CLK] = { > + .type = CLK_GATE, > + .name = "uart1clk-gate", > + .parent_names = (const char *[]){ "uart1clk", }, > + .reg = SCU1_CLK_STOP, > + .clk_idx = 12, > + }, > + [SCU1_CLK_UART2] = { > + .type = CLK_MUX, > + .name = "uart2clk", > + .parent_names = (const char *[]){"uartxclk", "huartxclk", }, > + .num_parents = 2, > + .reg = SCU1_CLK_SEL1, > + .bit_shift = 2, > + .bit_width = 1, > + }, > + [SCU1_CLK_GATE_UART2CLK] = { > + .type = CLK_GATE, > + .name = "uart2clk-gate", > + .parent_names = (const char *[]){ "uart2clk", }, > + .reg = SCU1_CLK_STOP, > + .clk_idx = 13, > + }, > + [SCU1_CLK_UART3] = { > + .type = CLK_MUX, > + .name = "uart3clk", > + .parent_names = (const char *[]){"uartxclk", "huartxclk", }, > + .num_parents = 2, > + .reg = SCU1_CLK_SEL1, > + .bit_shift = 3, > + .bit_width = 1, > + }, > + [SCU1_CLK_GATE_UART3CLK] = { > + .type = CLK_GATE, > + .name = "uart3clk-gate", > + .parent_names = (const char *[]){ "uart3clk", }, > + .reg = SCU1_CLK_STOP, > + .clk_idx = 14, > + }, > + [SCU1_CLK_GATE_I2CCLK] = { > + .type = CLK_GATE, > + .name = "i2cclk-gate", > + .parent_names = (const char *[]){ }, > + .reg = SCU1_CLK_STOP, > + .clk_idx = 15, > + }, > + [SCU1_CLK_GATE_I3C0CLK] = { > + .type = CLK_GATE, > + .name = "i3c0clk-gate", > + .parent_names = (const char *[]){ "soc1-ahb", }, > + .reg = SCU1_CLK_STOP, > + .clk_idx = 16, > + }, > + [SCU1_CLK_GATE_I3C1CLK] = { > + .type = CLK_GATE, > + .name = "i3c1clk-gate", > + .parent_names = (const char *[]){ "soc1-ahb", }, > + .reg = SCU1_CLK_STOP, > + .clk_idx = 17, > + }, > + [SCU1_CLK_GATE_I3C2CLK] = { > + .type = CLK_GATE, > + .name = "i3c2clk-gate", > + .parent_names = (const char *[]){ "soc1-ahb", }, > + .reg = SCU1_CLK_STOP, > + .clk_idx = 18, > + }, > + [SCU1_CLK_GATE_I3C3CLK] = { > + .type = CLK_GATE, > + .name = "i3c3clk-gate", > + .parent_names = (const char *[]){ "soc1-ahb", }, > + .reg = SCU1_CLK_STOP, > + .clk_idx = 19, > + }, > + [SCU1_CLK_GATE_I3C4CLK] = { > + .type = CLK_GATE, > + .name = "i3c4clk-gate", > + .parent_names = (const char *[]){ "soc1-ahb", }, > + .reg = SCU1_CLK_STOP, > + .clk_idx = 20, > + }, > + [SCU1_CLK_GATE_I3C5CLK] = { > + .type = CLK_GATE, > + .name = "i3c5clk-gate", > + .parent_names = (const char *[]){ "soc1-ahb", }, > + .reg = SCU1_CLK_STOP, > + .clk_idx = 21, > + }, > + [SCU1_CLK_GATE_I3C6CLK] = { > + .type = CLK_GATE, > + .name = "i3c6clk-gate", > + .parent_names = (const char *[]){ "soc1-ahb", }, > + .reg = SCU1_CLK_STOP, > + .clk_idx = 22, > + }, > + [SCU1_CLK_GATE_I3C7CLK] = { > + .type = CLK_GATE, > + .name = "i3c7clk-gate", > + .parent_names = (const char *[]){ "soc1-ahb", }, > + .reg = SCU1_CLK_STOP, > + .clk_idx = 23, > + }, > + [SCU1_CLK_GATE_I3C8CLK] = { > + .type = CLK_GATE, > + .name = "i3c8clk-gate", > + .parent_names = (const char *[]){ "soc1-ahb", }, > + .reg = SCU1_CLK_STOP, > + .clk_idx = 24, > + }, > + [SCU1_CLK_GATE_I3C9CLK] = { > + .type = CLK_GATE, > + .name = "i3c9clk-gate", > + .parent_names = (const char *[]){ "soc1-ahb", }, > + .reg = SCU1_CLK_STOP, > + .clk_idx = 25, > + }, > + [SCU1_CLK_GATE_I3C10CLK] = { > + .type = CLK_GATE, > + .name = "i3c10clk-gate", > + .parent_names = (const char *[]){ "soc1-ahb", }, > + .reg = SCU1_CLK_STOP, > + .clk_idx = 26, > + }, > + [SCU1_CLK_GATE_I3C11CLK] = { > + .type = CLK_GATE, > + .name = "i3c11clk-gate", > + .parent_names = (const char *[]){ "soc1-ahb", }, > + .reg = SCU1_CLK_STOP, > + .clk_idx = 27, > + }, > + [SCU1_CLK_GATE_I3C12CLK] = { > + .type = CLK_GATE, > + .name = "i3c12clk-gate", > + .parent_names = (const char *[]){ "soc1-ahb", }, > + .reg = SCU1_CLK_STOP, > + .clk_idx = 28, > + }, > + [SCU1_CLK_GATE_I3C13CLK] = { > + .type = CLK_GATE, > + .name = "i3c13clk-gate", > + .parent_names = (const char *[]){ "soc1-ahb", }, > + .reg = SCU1_CLK_STOP, > + .clk_idx = 29, > + }, > + [SCU1_CLK_GATE_I3C14CLK] = { > + .type = CLK_GATE, > + .name = "i3c14clk-gate", > + .parent_names = (const char *[]){ "soc1-ahb", }, > + .reg = SCU1_CLK_STOP, > + .clk_idx = 30, > + }, > + [SCU1_CLK_GATE_I3C15CLK] = { > + .type = CLK_GATE, > + .name = "i3c15clk-gate", > + .parent_names = (const char *[]){ "soc1-ahb", }, > + .reg = SCU1_CLK_STOP, > + .clk_idx = 31, > + }, > + [SCU1_CLK_UART5] = { > + .type = CLK_MUX, > + .name = "uart5clk", > + .parent_names = (const char *[]){"uartxclk", "huartxclk", }, > + .num_parents = 2, > + .reg = SCU1_CLK_SEL1, > + .bit_shift = 5, > + .bit_width = 1, > + }, > + [SCU1_CLK_GATE_UART5CLK] = { > + .type = CLK_GATE, > + .name = "uart5clk-gate", > + .parent_names = (const char *[]){ "uart5clk", }, > + .reg = SCU1_CLK_STOP2, > + .clk_idx = 0, > + .flags = CLK_IS_CRITICAL, > + }, > + [SCU1_CLK_UART6] = { > + .type = CLK_MUX, > + .name = "uart6clk", > + .parent_names = (const char *[]){"uartxclk", "huartxclk", }, > + .num_parents = 2, > + .reg = SCU1_CLK_SEL1, > + .bit_shift = 6, > + .bit_width = 1, > + }, > + [SCU1_CLK_GATE_UART6CLK] = { > + .type = CLK_GATE, > + .name = "uart6clk-gate", > + .parent_names = (const char *[]){ "uart6clk", }, > + .reg = SCU1_CLK_STOP2, > + .clk_idx = 1, > + }, > + [SCU1_CLK_UART7] = { > + .type = CLK_MUX, > + .name = "uart7clk", > + .parent_names = (const char *[]){"uartxclk", "huartxclk", }, > + .num_parents = 2, > + .reg = SCU1_CLK_SEL1, > + .bit_shift = 7, > + .bit_width = 1, > + }, > + [SCU1_CLK_GATE_UART7CLK] = { > + .type = CLK_GATE, > + .name = "uart7clk-gate", > + .parent_names = (const char *[]){ "uart7clk", }, > + .reg = SCU1_CLK_STOP2, > + .clk_idx = 2, > + .flags = CLK_IS_CRITICAL, > + }, > + [SCU1_CLK_UART8] = { > + .type = CLK_MUX, > + .name = "uart8clk", > + .parent_names = (const char *[]){"uartxclk", "huartxclk", }, > + .num_parents = 2, > + .reg = SCU1_CLK_SEL1, > + .bit_shift = 8, > + .bit_width = 1, > + }, > + [SCU1_CLK_GATE_UART8CLK] = { > + .type = CLK_GATE, > + .name = "uart8clk-gate", > + .parent_names = (const char *[]){ "uart8clk", }, > + .reg = SCU1_CLK_STOP2, > + .clk_idx = 3, > + .flags = CLK_IS_CRITICAL, > + }, > + [SCU1_CLK_UART9] = { > + .type = CLK_MUX, > + .name = "uart9clk", > + .parent_names = (const char *[]){"uartxclk", "huartxclk", }, > + .num_parents = 2, > + .reg = SCU1_CLK_SEL1, > + .bit_shift = 9, > + .bit_width = 1, > + }, > + [SCU1_CLK_GATE_UART9CLK] = { > + .type = CLK_GATE, > + .name = "uart9clk-gate", > + .parent_names = (const char *[]){ "uart9clk", }, > + .reg = SCU1_CLK_STOP2, > + .clk_idx = 4, > + }, > + [SCU1_CLK_UART10] = { > + .type = CLK_MUX, > + .name = "uart10clk", > + .parent_names = (const char *[]){"uartxclk", "huartxclk", }, > + .num_parents = 2, > + .reg = SCU1_CLK_SEL1, > + .bit_shift = 10, > + .bit_width = 1, > + }, > + [SCU1_CLK_GATE_UART10CLK] = { > + .type = CLK_GATE, > + .name = "uart10clk-gate", > + .parent_names = (const char *[]){ "uart10clk", }, > + .reg = SCU1_CLK_STOP2, > + .clk_idx = 5, > + }, > + [SCU1_CLK_UART11] = { > + .type = CLK_MUX, > + .name = "uart11clk", > + .parent_names = (const char *[]){"uartxclk", "huartxclk", }, > + .num_parents = 2, > + .reg = SCU1_CLK_SEL1, > + .bit_shift = 11, > + .bit_width = 1, > + }, > + [SCU1_CLK_GATE_UART11CLK] = { > + .type = CLK_GATE, > + .name = "uart11clk-gate", > + .parent_names = (const char *[]){ "uart11clk", }, > + .reg = SCU1_CLK_STOP2, > + .clk_idx = 6, > + }, > + [SCU1_CLK_UART12] = { > + .type = CLK_MUX, > + .name = "uart12clk", > + .parent_names = (const char *[]){"uartxclk", "huartxclk", }, > + .num_parents = 2, > + .reg = SCU1_CLK_SEL1, > + .bit_shift = 12, > + .bit_width = 1, > + }, > + [SCU1_CLK_GATE_UART12CLK] = { > + .type = CLK_GATE, > + .name = "uart12clk-gate", > + .parent_names = (const char *[]){ "uart12clk", }, > + .reg = SCU1_CLK_STOP2, > + .clk_idx = 7, > + .flags = CLK_IS_CRITICAL, > + }, > + [SCU1_CLK_UART13] = { > + .type = CLK_FIXED_FACTOR, > + .name = "uart13clk", > + .parent_names = (const char *[]){ "huartxclk", }, > + .mult = 1, > + .div = 1, > + }, > + [SCU1_CLK_UART14] = { > + .type = CLK_FIXED_FACTOR, > + .name = "uart14clk", > + .parent_names = (const char *[]){ "huartxclk", }, > + .mult = 1, > + .div = 1, > + }, > + [SCU1_CLK_GATE_FSICLK] = { > + .type = CLK_GATE, > + .name = "fsiclk-gate", > + .parent_names = (const char *[]){ }, > + .reg = SCU1_CLK_STOP2, > + .clk_idx = 8, > + }, > + [SCU1_CLK_GATE_LTPIPHYCLK] = { > + .type = CLK_GATE, > + .name = "ltpiphyclk-gate", > + .parent_names = (const char *[]){ }, > + .reg = SCU1_CLK_STOP2, > + .clk_idx = 9, > + }, > + [SCU1_CLK_GATE_LTPICLK] = { > + .type = CLK_GATE, > + .name = "ltpiclk-gate", > + .parent_names = (const char *[]){ }, > + .reg = SCU1_CLK_STOP2, > + .clk_idx = 10, > + }, > + [SCU1_CLK_GATE_VGALCLK] = { > + .type = CLK_GATE, > + .name = "vgalclk-gate", > + .parent_names = (const char *[]){ }, > + .reg = SCU1_CLK_STOP2, > + .clk_idx = 11, > + .flags = CLK_IS_CRITICAL, > + }, > + [SCU1_CLK_GATE_UHCICLK] = { > + .type = CLK_GATE, > + .name = "usbuartclk-gate", > + .parent_names = (const char *[]){ }, > + .reg = SCU1_CLK_STOP2, > + .clk_idx = 12, > + }, > + [SCU1_CLK_CAN] = { > + .type = CLK_FIXED_FACTOR, > + .name = "canclk", > + .parent_names = (const char *[]){ "soc1-apll", }, > + .mult = 1, > + .div = 10, > + }, > + [SCU1_CLK_GATE_CANCLK] = { > + .type = CLK_GATE, > + .name = "canclk-gate", > + .parent_names = (const char *[]){ "canclk", }, > + .reg = SCU1_CLK_STOP2, > + .clk_idx = 13, > + }, > + [SCU1_CLK_GATE_PCICLK] = { > + .type = CLK_GATE, > + .name = "pciclk-gate", > + .parent_names = (const char *[]){ }, > + .reg = SCU1_CLK_STOP2, > + .clk_idx = 14, > + }, > + [SCU1_CLK_GATE_SLICLK] = { > + .type = CLK_GATE, > + .name = "soc1-sliclk-gate", > + .parent_names = (const char *[]){ }, > + .reg = SCU1_CLK_STOP2, > + .clk_idx = 15, > + .flags = CLK_IS_CRITICAL, > + }, > + [SCU1_CLK_GATE_E2MCLK] = { > + .type = CLK_GATE, > + .name = "soc1-e2m-gate", > + .parent_names = (const char *[]){ }, > + .reg = SCU1_CLK_STOP2, > + .clk_idx = 16, > + .flags = CLK_IS_CRITICAL, > + }, > + [SCU1_CLK_GATE_PORTCUSB2CLK] = { > + .type = CLK_GATE, > + .name = "portcusb2-gate", > + .parent_names = (const char *[]){ }, > + .reg = SCU1_CLK_STOP2, > + .clk_idx = 17, > + .flags = CLK_IS_CRITICAL, > + }, > + [SCU1_CLK_GATE_PORTDUSB2CLK] = { > + .type = CLK_GATE, > + .name = "portdusb2-gate", > + .parent_names = (const char *[]){ }, > + .reg = SCU1_CLK_STOP2, > + .clk_idx = 18, > + }, > + [SCU1_CLK_GATE_LTPI1TXCLK] = { > + .type = CLK_GATE, > + .name = "ltp1tx-gate", > + .parent_names = (const char *[]){ }, > + .reg = SCU1_CLK_STOP2, > + .clk_idx = 19, > + }, > +}; > + > +static struct clk_hw *ast2700_clk_hw_register_pll(int clk_idx, void __iomem > *reg, > + const struct ast2700_clk_info *clk, > + struct ast2700_clk_ctrl *clk_ctrl) { > + int scu = clk_ctrl->clk_data->scu; > + unsigned int mult, div; > + u32 val; > + > + if (!scu && clk_idx == SCU0_CLK_HPLL) { > + val = readl(clk_ctrl->base + SCU0_HWSTRAP1); > + if ((val & GENMASK(3, 2)) != 0) { > + switch ((val & GENMASK(3, 2)) >> 2) { > + case 1: > + return devm_clk_hw_register_fixed_rate(clk_ctrl->dev, > "soc0-hpll", > + NULL, 0, 1900000000); > + case 2: > + return devm_clk_hw_register_fixed_rate(clk_ctrl->dev, > "soc0-hpll", > + NULL, 0, 1800000000); > + case 3: > + return devm_clk_hw_register_fixed_rate(clk_ctrl->dev, > "soc0-hpll", > + NULL, 0, 1700000000); > + default: > + return ERR_PTR(-EINVAL); > + } > + } > + } > + > + val = readl(reg); > + > + if (val & BIT(24)) { > + /* Pass through mode */ > + mult = 1; > + div = 1; > + } else { > + u32 m = val & 0x1fff; > + u32 n = (val >> 13) & 0x3f; > + u32 p = (val >> 19) & 0xf; > + > + if (scu) { > + mult = (m + 1) / (n + 1); > + div = (p + 1); > + } else { > + if (clk_idx == SCU0_CLK_MPLL) { > + mult = m / (n + 1); > + div = (p + 1); > + } else { > + mult = (m + 1) / (2 * (n + 1)); > + div = (p + 1); > + } > + } > + } > + > + return devm_clk_hw_register_fixed_factor(clk_ctrl->dev, clk->name, > + clk->parent_names[0], 0, mult, div); } > + > +static struct clk_hw *ast2700_clk_hw_register_uartpll(int clk_idx, void > __iomem *reg, > + const struct ast2700_clk_info *clk, > + struct ast2700_clk_ctrl *clk_ctrl) { > + unsigned int mult, div; > + u32 val = readl(reg); > + u32 r = val & 0xff; > + u32 n = (val >> 8) & 0x3ff; > + > + mult = r; > + div = n * 2; > + > + return devm_clk_hw_register_fixed_factor(clk_ctrl->dev, clk->name, > + clk->parent_names[0], 0, mult, div); } > + > +static struct clk_hw *ast2700_clk_hw_register_misc(int clk_idx, void > __iomem *reg, > + const struct ast2700_clk_info *clk, > + struct ast2700_clk_ctrl *clk_ctrl) { > + u32 div = 0; > + > + if (clk_idx == SCU0_CLK_MPHY) > + div = readl(reg) + 1; > + else if (clk_idx == SCU0_CLK_U2PHY_REFCLK) > + div = (GET_USB_REFCLK_DIV(readl(reg)) + 1) << 1; > + else > + return ERR_PTR(-EINVAL); > + > + return devm_clk_hw_register_fixed_factor(clk_ctrl->dev, clk->name, > + clk->parent_names[0], clk->flags, > + 1, div); > +} > + > +static int ast2700_clk_is_enabled(struct clk_hw *hw) { > + struct clk_gate *gate = to_clk_gate(hw); > + u32 clk = BIT(gate->bit_idx); > + u32 reg; > + > + reg = readl(gate->reg); > + > + return !(reg & clk); > +} > + > +static int ast2700_clk_enable(struct clk_hw *hw) { > + struct clk_gate *gate = to_clk_gate(hw); > + u32 clk = BIT(gate->bit_idx); > + > + if (readl(gate->reg) & clk) > + writel(clk, gate->reg + 0x04); > + > + return 0; > +} > + > +static void ast2700_clk_disable(struct clk_hw *hw) { > + struct clk_gate *gate = to_clk_gate(hw); > + u32 clk = BIT(gate->bit_idx); > + > + /* Clock is set to enable, so use write to set register */ > + writel(clk, gate->reg); > +} > + > +static const struct clk_ops ast2700_clk_gate_ops = { > + .enable = ast2700_clk_enable, > + .disable = ast2700_clk_disable, > + .is_enabled = ast2700_clk_is_enabled, > +}; > + > +static struct clk_hw *ast2700_clk_hw_register_gate(struct device *dev, const > char *name, > + const char *parent_name, unsigned long > flags, > + void __iomem *reg, u8 clock_idx, > + u8 clk_gate_flags, spinlock_t *lock) { > + struct clk_gate *gate; > + struct clk_hw *hw; > + struct clk_init_data init; > + int ret = -EINVAL; > + > + gate = kzalloc(sizeof(*gate), GFP_KERNEL); > + if (!gate) > + return ERR_PTR(-ENOMEM); > + > + init.name = name; > + init.ops = &ast2700_clk_gate_ops; > + init.flags = flags; > + init.parent_names = parent_name ? &parent_name : NULL; > + init.num_parents = parent_name ? 1 : 0; > + > + gate->reg = reg; > + gate->bit_idx = clock_idx; > + gate->flags = clk_gate_flags; > + gate->lock = lock; > + gate->hw.init = &init; > + > + hw = &gate->hw; > + ret = clk_hw_register(dev, hw); > + if (ret) { > + kfree(gate); > + hw = ERR_PTR(ret); > + } > + > + return hw; > +} > + > +static void aspeed_reset_unregister_adev(void *_adev) { > + struct auxiliary_device *adev = _adev; > + > + auxiliary_device_delete(adev); > + auxiliary_device_uninit(adev); > +} > + > +static void aspeed_reset_adev_release(struct device *dev) { > + struct auxiliary_device *adev = to_auxiliary_dev(dev); > + > + kfree(adev); > +} > + > +static int aspeed_reset_controller_register(struct device *clk_dev, > + void __iomem *base, const char *adev_name) { > + struct auxiliary_device *adev; > + int ret; > + > + adev = kzalloc(sizeof(*adev), GFP_KERNEL); > + if (!adev) > + return -ENOMEM; > + > + adev->name = adev_name; > + adev->dev.parent = clk_dev; > + adev->dev.release = aspeed_reset_adev_release; > + adev->id = 666u; > + > + ret = auxiliary_device_init(adev); > + if (ret) { > + kfree(adev); > + return ret; > + } > + > + ret = auxiliary_device_add(adev); > + if (ret) { > + auxiliary_device_uninit(adev); > + return ret; > + } > + > + adev->dev.platform_data = (__force void *)base; > + > + return devm_add_action_or_reset(clk_dev, > aspeed_reset_unregister_adev, > +adev); } > + > +static int ast2700_soc_clk_probe(struct platform_device *pdev) { > + struct ast2700_clk_data *clk_data; > + struct ast2700_clk_ctrl *clk_ctrl; > + struct clk_hw_onecell_data *clk_hw_data; > + struct device *dev = &pdev->dev; > + void __iomem *clk_base; > + struct clk_hw **hws; > + char *reset_name; > + int ret; > + int i; > + > + clk_ctrl = devm_kzalloc(dev, sizeof(*clk_ctrl), GFP_KERNEL); > + if (!clk_ctrl) > + return -ENOMEM; > + clk_ctrl->dev = dev; > + dev_set_drvdata(&pdev->dev, clk_ctrl); > + > + spin_lock_init(&clk_ctrl->lock); > + > + clk_base = devm_platform_ioremap_resource(pdev, 0); > + if (IS_ERR(clk_base)) > + return PTR_ERR(clk_base); > + > + clk_ctrl->base = clk_base; > + > + clk_data = (struct ast2700_clk_data *)of_device_get_match_data(dev); > + if (!clk_data) > + return devm_of_platform_populate(dev); > + > + clk_ctrl->clk_data = clk_data; > + reset_name = devm_kasprintf(dev, GFP_KERNEL, "reset%d", > +clk_data->scu); > + > + clk_hw_data = devm_kzalloc(dev, struct_size(clk_hw_data, hws, > clk_data->nr_clks), > + GFP_KERNEL); > + if (!clk_hw_data) > + return -ENOMEM; > + > + clk_hw_data->num = clk_data->nr_clks; > + hws = clk_hw_data->hws; > + > + for (i = 0; i < clk_data->nr_clks; i++) { > + const struct ast2700_clk_info *clk = &clk_data->clk_info[i]; > + void __iomem *reg = clk_ctrl->base + clk->reg; > + > + if (clk->type == CLK_FIXED) { > + hws[i] = devm_clk_hw_register_fixed_rate(dev, clk->name, > NULL, > + clk->flags, clk->fixed_rate); > + } else if (clk->type == CLK_FIXED_FACTOR) { > + hws[i] = devm_clk_hw_register_fixed_factor(dev, clk->name, > + clk->parent_names[0], clk->flags, > + clk->mult, clk->div); > + } else if (clk->type == CLK_PLL) { > + hws[i] = ast2700_clk_hw_register_pll(i, reg, clk, clk_ctrl); > + } else if (clk->type == CLK_UART_PLL) { > + hws[i] = ast2700_clk_hw_register_uartpll(i, reg, clk, clk_ctrl); > + } else if (clk->type == CLK_MUX) { > + hws[i] = devm_clk_hw_register_mux(dev, clk->name, > clk->parent_names, > + clk->num_parents, clk->flags, reg, > + clk->bit_shift, clk->bit_width, > + 0, &clk_ctrl->lock); > + } else if (clk->type == CLK_MISC) { > + hws[i] = ast2700_clk_hw_register_misc(i, reg, clk, clk_ctrl); > + } else if (clk->type == CLK_DIVIDER) { > + hws[i] = devm_clk_hw_register_divider(dev, clk->name, > clk->parent_names[0], > + clk->flags, reg, clk->bit_shift, > + clk->bit_width, 0, > + &clk_ctrl->lock); > + } else if (clk->type == CLK_DIV_TABLE) { > + hws[i] = clk_hw_register_divider_table(dev, clk->name, > clk->parent_names[0], > + clk->flags, reg, clk->bit_shift, > + clk->bit_width, 0, > + clk->div_table, &clk_ctrl->lock); > + } else { > + hws[i] = ast2700_clk_hw_register_gate(dev, clk->name, > clk->parent_names[0], > + clk->flags, reg, clk->clk_idx, > + clk->flags, &clk_ctrl->lock); > + } > + > + if (IS_ERR(hws[i])) > + return PTR_ERR(hws[i]); > + } > + > + ret = devm_of_clk_add_hw_provider(dev, of_clk_hw_onecell_get, > clk_hw_data); > + if (ret) > + return ret; > + > + return aspeed_reset_controller_register(dev, clk_base, reset_name); } > + > +static const struct ast2700_clk_data ast2700_clk0_data = { > + .scu = 0, > + .nr_clks = ARRAY_SIZE(ast2700_scu0_clk_info), > + .clk_info = ast2700_scu0_clk_info, > +}; > + > +static const struct ast2700_clk_data ast2700_clk1_data = { > + .scu = 1, > + .nr_clks = ARRAY_SIZE(ast2700_scu1_clk_info), > + .clk_info = ast2700_scu1_clk_info, > +}; > + > +static const struct of_device_id ast2700_scu_match[] = { > + { .compatible = "aspeed,ast2700-scu0", .data = &ast2700_clk0_data }, > + { .compatible = "aspeed,ast2700-scu1", .data = &ast2700_clk1_data }, > + { /* sentinel */ } > +}; > + > +MODULE_DEVICE_TABLE(of, ast2700_scu_match); > + > +static struct platform_driver ast2700_scu_driver = { > + .driver = { > + .name = "clk-ast2700", > + .of_match_table = ast2700_scu_match, > + }, > +}; > + > +builtin_platform_driver_probe(ast2700_scu_driver, > +ast2700_soc_clk_probe); > -- > 2.34.1