diff options
Diffstat (limited to 'drivers/clk')
95 files changed, 16314 insertions, 1191 deletions
diff --git a/drivers/clk/Kconfig b/drivers/clk/Kconfig index e80918be8e9c..e873f9ea2e65 100644 --- a/drivers/clk/Kconfig +++ b/drivers/clk/Kconfig @@ -6,10 +6,6 @@ config HAVE_CLK The <linux/clk.h> calls support software clock gating and thus are a key power management tool on many systems. -config CLKDEV_LOOKUP - bool - select HAVE_CLK - config HAVE_CLK_PREPARE bool @@ -26,7 +22,7 @@ menuconfig COMMON_CLK bool "Common Clock Framework" depends on !HAVE_LEGACY_CLK select HAVE_CLK_PREPARE - select CLKDEV_LOOKUP + select HAVE_CLK select SRCU select RATIONAL help @@ -55,6 +51,14 @@ config CLK_HSDK This driver supports the HSDK core, system, ddr, tunnel and hdmi PLLs control. +config LMK04832 + tristate "Ti LMK04832 JESD204B Compliant Clock Jitter Cleaner" + depends on SPI + select REGMAP_SPI + help + Say yes here to build support for Texas Instruments' LMK04832 Ultra + Low-Noise JESD204B Compliant Clock Jitter Cleaner With Dual Loop PLLs + config COMMON_CLK_MAX77686 tristate "Clock driver for Maxim 77620/77686/77802 MFD" depends on MFD_MAX77686 || MFD_MAX77620 || COMPILE_TEST @@ -335,6 +339,16 @@ config COMMON_CLK_STM32MP157 help Support for stm32mp157 SoC family clocks +config COMMON_CLK_STM32MP157_SCMI + bool "stm32mp157 Clock driver with Trusted Firmware" + depends on COMMON_CLK_STM32MP157 + select COMMON_CLK_SCMI + select ARM_SCMI_PROTOCOL + default y + help + Support for stm32mp157 SoC family clocks with Trusted Firmware using + SCMI protocol. + config COMMON_CLK_STM32F def_bool COMMON_CLK && (MACH_STM32F429 || MACH_STM32F469 || MACH_STM32F746) help @@ -358,10 +372,10 @@ config COMMON_CLK_MMP2_AUDIO config COMMON_CLK_BD718XX tristate "Clock driver for 32K clk gates on ROHM PMICs" - depends on MFD_ROHM_BD718XX || MFD_ROHM_BD70528 || MFD_ROHM_BD71828 + depends on MFD_ROHM_BD718XX || MFD_ROHM_BD71828 help - This driver supports ROHM BD71837, ROHM BD71847, ROHM BD71828 and - ROHM BD70528 PMICs clock gates. + This driver supports ROHM BD71837, BD71847, BD71850, BD71815 + and BD71828 PMICs clock gates. config COMMON_CLK_FIXED_MMIO bool "Clock driver for Memory Mapped Fixed values" diff --git a/drivers/clk/Makefile b/drivers/clk/Makefile index 5f06879d7fe9..2b91d34c582b 100644 --- a/drivers/clk/Makefile +++ b/drivers/clk/Makefile @@ -1,7 +1,6 @@ # SPDX-License-Identifier: GPL-2.0 # common clock types -obj-$(CONFIG_HAVE_CLK) += clk-devres.o clk-bulk.o -obj-$(CONFIG_CLKDEV_LOOKUP) += clkdev.o +obj-$(CONFIG_HAVE_CLK) += clk-devres.o clk-bulk.o clkdev.o obj-$(CONFIG_COMMON_CLK) += clk.o obj-$(CONFIG_COMMON_CLK) += clk-divider.o obj-$(CONFIG_COMMON_CLK) += clk-fixed-factor.o @@ -37,6 +36,7 @@ obj-$(CONFIG_MACH_ASPEED_G6) += clk-ast2600.o obj-$(CONFIG_ARCH_HIGHBANK) += clk-highbank.o obj-$(CONFIG_CLK_HSDK) += clk-hsdk-pll.o obj-$(CONFIG_COMMON_CLK_K210) += clk-k210.o +obj-$(CONFIG_LMK04832) += clk-lmk04832.o obj-$(CONFIG_COMMON_CLK_LOCHNAGAR) += clk-lochnagar.o obj-$(CONFIG_COMMON_CLK_MAX77686) += clk-max77686.o obj-$(CONFIG_COMMON_CLK_MAX9485) += clk-max9485.o diff --git a/drivers/clk/actions/owl-s500.c b/drivers/clk/actions/owl-s500.c index 61bb224f6330..57d06e183dff 100644 --- a/drivers/clk/actions/owl-s500.c +++ b/drivers/clk/actions/owl-s500.c @@ -113,6 +113,7 @@ static const char * const sensor_clk_mux_p[] = { "hosc", "bisp_clk" }; static const char * const sd_clk_mux_p[] = { "dev_clk", "nand_pll_clk" }; static const char * const pwm_clk_mux_p[] = { "losc", "hosc" }; static const char * const ahbprediv_clk_mux_p[] = { "dev_clk", "display_pll_clk", "nand_pll_clk", "ddr_pll_clk" }; +static const char * const nic_clk_mux_p[] = { "dev_clk", "display_pll_clk", "nand_pll_clk", "ddr_pll_clk" }; static const char * const uart_clk_mux_p[] = { "hosc", "dev_pll_clk" }; static const char * const de_clk_mux_p[] = { "display_pll_clk", "dev_clk" }; static const char * const i2s_clk_mux_p[] = { "audio_pll_clk" }; @@ -127,8 +128,7 @@ static struct clk_factor_table sd_factor_table[] = { { 12, 1, 13 }, { 13, 1, 14 }, { 14, 1, 15 }, { 15, 1, 16 }, { 16, 1, 17 }, { 17, 1, 18 }, { 18, 1, 19 }, { 19, 1, 20 }, { 20, 1, 21 }, { 21, 1, 22 }, { 22, 1, 23 }, { 23, 1, 24 }, - { 24, 1, 25 }, { 25, 1, 26 }, { 26, 1, 27 }, { 27, 1, 28 }, - { 28, 1, 29 }, { 29, 1, 30 }, { 30, 1, 31 }, { 31, 1, 32 }, + { 24, 1, 25 }, /* bit8: /128 */ { 256, 1, 1 * 128 }, { 257, 1, 2 * 128 }, { 258, 1, 3 * 128 }, { 259, 1, 4 * 128 }, @@ -137,19 +137,20 @@ static struct clk_factor_table sd_factor_table[] = { { 268, 1, 13 * 128 }, { 269, 1, 14 * 128 }, { 270, 1, 15 * 128 }, { 271, 1, 16 * 128 }, { 272, 1, 17 * 128 }, { 273, 1, 18 * 128 }, { 274, 1, 19 * 128 }, { 275, 1, 20 * 128 }, { 276, 1, 21 * 128 }, { 277, 1, 22 * 128 }, { 278, 1, 23 * 128 }, { 279, 1, 24 * 128 }, - { 280, 1, 25 * 128 }, { 281, 1, 26 * 128 }, { 282, 1, 27 * 128 }, { 283, 1, 28 * 128 }, - { 284, 1, 29 * 128 }, { 285, 1, 30 * 128 }, { 286, 1, 31 * 128 }, { 287, 1, 32 * 128 }, + { 280, 1, 25 * 128 }, { 0, 0, 0 }, }; -static struct clk_factor_table bisp_factor_table[] = { - { 0, 1, 1 }, { 1, 1, 2 }, { 2, 1, 3 }, { 3, 1, 4 }, - { 4, 1, 5 }, { 5, 1, 6 }, { 6, 1, 7 }, { 7, 1, 8 }, +static struct clk_factor_table de_factor_table[] = { + { 0, 1, 1 }, { 1, 2, 3 }, { 2, 1, 2 }, { 3, 2, 5 }, + { 4, 1, 3 }, { 5, 1, 4 }, { 6, 1, 6 }, { 7, 1, 8 }, + { 8, 1, 12 }, { 0, 0, 0 }, }; -static struct clk_factor_table ahb_factor_table[] = { - { 1, 1, 2 }, { 2, 1, 3 }, +static struct clk_factor_table hde_factor_table[] = { + { 0, 1, 1 }, { 1, 2, 3 }, { 2, 1, 2 }, { 3, 2, 5 }, + { 4, 1, 3 }, { 5, 1, 4 }, { 6, 1, 6 }, { 7, 1, 8 }, { 0, 0, 0 }, }; @@ -158,6 +159,13 @@ static struct clk_div_table rmii_ref_div_table[] = { { 0, 0 }, }; +static struct clk_div_table std12rate_div_table[] = { + { 0, 1 }, { 1, 2 }, { 2, 3 }, { 3, 4 }, + { 4, 5 }, { 5, 6 }, { 6, 7 }, { 7, 8 }, + { 8, 9 }, { 9, 10 }, { 10, 11 }, { 11, 12 }, + { 0, 0 }, +}; + static struct clk_div_table i2s_div_table[] = { { 0, 1 }, { 1, 2 }, { 2, 3 }, { 3, 4 }, { 4, 6 }, { 5, 8 }, { 6, 12 }, { 7, 16 }, @@ -174,7 +182,6 @@ static struct clk_div_table nand_div_table[] = { /* mux clock */ static OWL_MUX(dev_clk, "dev_clk", dev_clk_mux_p, CMU_DEVPLL, 12, 1, CLK_SET_RATE_PARENT); -static OWL_MUX(ahbprediv_clk, "ahbprediv_clk", ahbprediv_clk_mux_p, CMU_BUSCLK1, 8, 3, CLK_SET_RATE_PARENT); /* gate clocks */ static OWL_GATE(gpio_clk, "gpio_clk", "apb_clk", CMU_DEVCLKEN0, 18, 0, 0); @@ -187,45 +194,60 @@ static OWL_GATE(timer_clk, "timer_clk", "hosc", CMU_DEVCLKEN1, 27, 0, 0); static OWL_GATE(hdmi_clk, "hdmi_clk", "hosc", CMU_DEVCLKEN1, 3, 0, 0); /* divider clocks */ -static OWL_DIVIDER(h_clk, "h_clk", "ahbprediv_clk", CMU_BUSCLK1, 12, 2, NULL, 0, 0); -static OWL_DIVIDER(apb_clk, "apb_clk", "ahb_clk", CMU_BUSCLK1, 14, 2, NULL, 0, 0); +static OWL_DIVIDER(h_clk, "h_clk", "ahbprediv_clk", CMU_BUSCLK1, 2, 2, NULL, 0, 0); +static OWL_DIVIDER(apb_clk, "apb_clk", "nic_clk", CMU_BUSCLK1, 14, 2, NULL, 0, 0); static OWL_DIVIDER(rmii_ref_clk, "rmii_ref_clk", "ethernet_pll_clk", CMU_ETHERNETPLL, 1, 1, rmii_ref_div_table, 0, 0); /* factor clocks */ -static OWL_FACTOR(ahb_clk, "ahb_clk", "h_clk", CMU_BUSCLK1, 2, 2, ahb_factor_table, 0, 0); -static OWL_FACTOR(de1_clk, "de_clk1", "de_clk", CMU_DECLK, 0, 3, bisp_factor_table, 0, 0); -static OWL_FACTOR(de2_clk, "de_clk2", "de_clk", CMU_DECLK, 4, 3, bisp_factor_table, 0, 0); +static OWL_FACTOR(de1_clk, "de_clk1", "de_clk", CMU_DECLK, 0, 4, de_factor_table, 0, 0); +static OWL_FACTOR(de2_clk, "de_clk2", "de_clk", CMU_DECLK, 4, 4, de_factor_table, 0, 0); /* composite clocks */ +static OWL_COMP_DIV(nic_clk, "nic_clk", nic_clk_mux_p, + OWL_MUX_HW(CMU_BUSCLK1, 4, 3), + { 0 }, + OWL_DIVIDER_HW(CMU_BUSCLK1, 16, 2, 0, NULL), + 0); + +static OWL_COMP_DIV(ahbprediv_clk, "ahbprediv_clk", ahbprediv_clk_mux_p, + OWL_MUX_HW(CMU_BUSCLK1, 8, 3), + { 0 }, + OWL_DIVIDER_HW(CMU_BUSCLK1, 12, 2, 0, NULL), + CLK_SET_RATE_PARENT); + +static OWL_COMP_FIXED_FACTOR(ahb_clk, "ahb_clk", "h_clk", + { 0 }, + 1, 1, 0); + static OWL_COMP_FACTOR(vce_clk, "vce_clk", hde_clk_mux_p, OWL_MUX_HW(CMU_VCECLK, 4, 2), OWL_GATE_HW(CMU_DEVCLKEN0, 26, 0), - OWL_FACTOR_HW(CMU_VCECLK, 0, 3, 0, bisp_factor_table), + OWL_FACTOR_HW(CMU_VCECLK, 0, 3, 0, hde_factor_table), 0); static OWL_COMP_FACTOR(vde_clk, "vde_clk", hde_clk_mux_p, OWL_MUX_HW(CMU_VDECLK, 4, 2), OWL_GATE_HW(CMU_DEVCLKEN0, 25, 0), - OWL_FACTOR_HW(CMU_VDECLK, 0, 3, 0, bisp_factor_table), + OWL_FACTOR_HW(CMU_VDECLK, 0, 3, 0, hde_factor_table), 0); -static OWL_COMP_FACTOR(bisp_clk, "bisp_clk", bisp_clk_mux_p, +static OWL_COMP_DIV(bisp_clk, "bisp_clk", bisp_clk_mux_p, OWL_MUX_HW(CMU_BISPCLK, 4, 1), OWL_GATE_HW(CMU_DEVCLKEN0, 14, 0), - OWL_FACTOR_HW(CMU_BISPCLK, 0, 3, 0, bisp_factor_table), + OWL_DIVIDER_HW(CMU_BISPCLK, 0, 4, 0, std12rate_div_table), 0); -static OWL_COMP_FACTOR(sensor0_clk, "sensor0_clk", sensor_clk_mux_p, +static OWL_COMP_DIV(sensor0_clk, "sensor0_clk", sensor_clk_mux_p, OWL_MUX_HW(CMU_SENSORCLK, 4, 1), OWL_GATE_HW(CMU_DEVCLKEN0, 14, 0), - OWL_FACTOR_HW(CMU_SENSORCLK, 0, 3, 0, bisp_factor_table), - CLK_IGNORE_UNUSED); + OWL_DIVIDER_HW(CMU_SENSORCLK, 0, 4, 0, std12rate_div_table), + 0); -static OWL_COMP_FACTOR(sensor1_clk, "sensor1_clk", sensor_clk_mux_p, +static OWL_COMP_DIV(sensor1_clk, "sensor1_clk", sensor_clk_mux_p, OWL_MUX_HW(CMU_SENSORCLK, 4, 1), OWL_GATE_HW(CMU_DEVCLKEN0, 14, 0), - OWL_FACTOR_HW(CMU_SENSORCLK, 8, 3, 0, bisp_factor_table), - CLK_IGNORE_UNUSED); + OWL_DIVIDER_HW(CMU_SENSORCLK, 8, 4, 0, std12rate_div_table), + 0); static OWL_COMP_FACTOR(sd0_clk, "sd0_clk", sd_clk_mux_p, OWL_MUX_HW(CMU_SD0CLK, 9, 1), @@ -302,10 +324,14 @@ static OWL_COMP_FIXED_FACTOR(i2c3_clk, "i2c3_clk", "ethernet_pll_clk", OWL_GATE_HW(CMU_DEVCLKEN1, 31, 0), 1, 5, 0); +static OWL_COMP_FIXED_FACTOR(ethernet_clk, "ethernet_clk", "ethernet_pll_clk", + OWL_GATE_HW(CMU_DEVCLKEN1, 22, 0), + 1, 20, 0); + static OWL_COMP_DIV(uart0_clk, "uart0_clk", uart_clk_mux_p, OWL_MUX_HW(CMU_UART0CLK, 16, 1), OWL_GATE_HW(CMU_DEVCLKEN1, 6, 0), - OWL_DIVIDER_HW(CMU_UART1CLK, 0, 8, CLK_DIVIDER_ROUND_CLOSEST, NULL), + OWL_DIVIDER_HW(CMU_UART0CLK, 0, 8, CLK_DIVIDER_ROUND_CLOSEST, NULL), CLK_IGNORE_UNUSED); static OWL_COMP_DIV(uart1_clk, "uart1_clk", uart_clk_mux_p, @@ -317,31 +343,31 @@ static OWL_COMP_DIV(uart1_clk, "uart1_clk", uart_clk_mux_p, static OWL_COMP_DIV(uart2_clk, "uart2_clk", uart_clk_mux_p, OWL_MUX_HW(CMU_UART2CLK, 16, 1), OWL_GATE_HW(CMU_DEVCLKEN1, 8, 0), - OWL_DIVIDER_HW(CMU_UART1CLK, 0, 8, CLK_DIVIDER_ROUND_CLOSEST, NULL), + OWL_DIVIDER_HW(CMU_UART2CLK, 0, 8, CLK_DIVIDER_ROUND_CLOSEST, NULL), CLK_IGNORE_UNUSED); static OWL_COMP_DIV(uart3_clk, "uart3_clk", uart_clk_mux_p, OWL_MUX_HW(CMU_UART3CLK, 16, 1), OWL_GATE_HW(CMU_DEVCLKEN1, 19, 0), - OWL_DIVIDER_HW(CMU_UART1CLK, 0, 8, CLK_DIVIDER_ROUND_CLOSEST, NULL), + OWL_DIVIDER_HW(CMU_UART3CLK, 0, 8, CLK_DIVIDER_ROUND_CLOSEST, NULL), CLK_IGNORE_UNUSED); static OWL_COMP_DIV(uart4_clk, "uart4_clk", uart_clk_mux_p, OWL_MUX_HW(CMU_UART4CLK, 16, 1), OWL_GATE_HW(CMU_DEVCLKEN1, 20, 0), - OWL_DIVIDER_HW(CMU_UART1CLK, 0, 8, CLK_DIVIDER_ROUND_CLOSEST, NULL), + OWL_DIVIDER_HW(CMU_UART4CLK, 0, 8, CLK_DIVIDER_ROUND_CLOSEST, NULL), CLK_IGNORE_UNUSED); static OWL_COMP_DIV(uart5_clk, "uart5_clk", uart_clk_mux_p, OWL_MUX_HW(CMU_UART5CLK, 16, 1), OWL_GATE_HW(CMU_DEVCLKEN1, 21, 0), - OWL_DIVIDER_HW(CMU_UART1CLK, 0, 8, CLK_DIVIDER_ROUND_CLOSEST, NULL), + OWL_DIVIDER_HW(CMU_UART5CLK, 0, 8, CLK_DIVIDER_ROUND_CLOSEST, NULL), CLK_IGNORE_UNUSED); static OWL_COMP_DIV(uart6_clk, "uart6_clk", uart_clk_mux_p, OWL_MUX_HW(CMU_UART6CLK, 16, 1), OWL_GATE_HW(CMU_DEVCLKEN1, 18, 0), - OWL_DIVIDER_HW(CMU_UART1CLK, 0, 8, CLK_DIVIDER_ROUND_CLOSEST, NULL), + OWL_DIVIDER_HW(CMU_UART6CLK, 0, 8, CLK_DIVIDER_ROUND_CLOSEST, NULL), CLK_IGNORE_UNUSED); static OWL_COMP_DIV(i2srx_clk, "i2srx_clk", i2s_clk_mux_p, @@ -436,6 +462,8 @@ static struct owl_clk_common *s500_clks[] = { &apb_clk.common, &dmac_clk.common, &gpio_clk.common, + &nic_clk.common, + ðernet_clk.common, }; static struct clk_hw_onecell_data s500_hw_clks = { @@ -495,6 +523,8 @@ static struct clk_hw_onecell_data s500_hw_clks = { [CLK_APB] = &apb_clk.common.hw, [CLK_DMAC] = &dmac_clk.common.hw, [CLK_GPIO] = &gpio_clk.common.hw, + [CLK_NIC] = &nic_clk.common.hw, + [CLK_ETHERNET] = ðernet_clk.common.hw, }, .num = CLK_NR_CLKS, }; diff --git a/drivers/clk/analogbits/wrpll-cln28hpc.c b/drivers/clk/analogbits/wrpll-cln28hpc.c index 7c64ea52a8d5..09ca82356399 100644 --- a/drivers/clk/analogbits/wrpll-cln28hpc.c +++ b/drivers/clk/analogbits/wrpll-cln28hpc.c @@ -202,7 +202,7 @@ static int __wrpll_update_parent_rate(struct wrpll_cfg *c, } /** - * wrpll_configure() - compute PLL configuration for a target rate + * wrpll_configure_for_rate() - compute PLL configuration for a target rate * @c: ptr to a struct wrpll_cfg record to write into * @target_rate: target PLL output clock rate (post-Q-divider) * @parent_rate: PLL input refclk rate (pre-R-divider) diff --git a/drivers/clk/clk-bd718x7.c b/drivers/clk/clk-bd718x7.c index d9e70e506d18..ac40b669d60b 100644 --- a/drivers/clk/clk-bd718x7.c +++ b/drivers/clk/clk-bd718x7.c @@ -15,15 +15,13 @@ /* clk control registers */ /* BD71815 */ #define BD71815_REG_OUT32K 0x1d -/* BD70528 */ -#define BD70528_REG_OUT32K 0x2c /* BD71828 */ #define BD71828_REG_OUT32K 0x4B /* BD71837 and BD71847 */ #define BD718XX_REG_OUT32K 0x2E /* - * BD71837, BD71847, BD70528 and BD71828 all use bit [0] to clk output control + * BD71837, BD71847, and BD71828 all use bit [0] to clk output control */ #define CLK_OUT_EN_MASK BIT(0) @@ -116,10 +114,6 @@ static int bd71837_clk_probe(struct platform_device *pdev) c->reg = BD71828_REG_OUT32K; c->mask = CLK_OUT_EN_MASK; break; - case ROHM_CHIP_TYPE_BD70528: - c->reg = BD70528_REG_OUT32K; - c->mask = CLK_OUT_EN_MASK; - break; case ROHM_CHIP_TYPE_BD71815: c->reg = BD71815_REG_OUT32K; c->mask = CLK_OUT_EN_MASK; @@ -150,7 +144,6 @@ static int bd71837_clk_probe(struct platform_device *pdev) static const struct platform_device_id bd718x7_clk_id[] = { { "bd71837-clk", ROHM_CHIP_TYPE_BD71837 }, { "bd71847-clk", ROHM_CHIP_TYPE_BD71847 }, - { "bd70528-clk", ROHM_CHIP_TYPE_BD70528 }, { "bd71828-clk", ROHM_CHIP_TYPE_BD71828 }, { "bd71815-clk", ROHM_CHIP_TYPE_BD71815 }, { }, @@ -168,6 +161,6 @@ static struct platform_driver bd71837_clk = { module_platform_driver(bd71837_clk); MODULE_AUTHOR("Matti Vaittinen <matti.vaittinen@fi.rohmeurope.com>"); -MODULE_DESCRIPTION("BD718(15/18/28/37/47/50) and BD70528 chip clk driver"); +MODULE_DESCRIPTION("BD718(15/18/28/37/47/50) and chip clk driver"); MODULE_LICENSE("GPL"); MODULE_ALIAS("platform:bd718xx-clk"); diff --git a/drivers/clk/clk-lmk04832.c b/drivers/clk/clk-lmk04832.c new file mode 100644 index 000000000000..c1095e733220 --- /dev/null +++ b/drivers/clk/clk-lmk04832.c @@ -0,0 +1,1599 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * LMK04832 Ultra Low-Noise JESD204B Compliant Clock Jitter Cleaner + * Pin compatible with the LMK0482x family + * + * Datasheet: https://www.ti.com/lit/ds/symlink/lmk04832.pdf + * + * Copyright (c) 2020, Xiphos Systems Corp. + * + */ + +#include <linux/bitfield.h> +#include <linux/clk.h> +#include <linux/clk-provider.h> +#include <linux/debugfs.h> +#include <linux/device.h> +#include <linux/gcd.h> +#include <linux/gpio/consumer.h> +#include <linux/module.h> +#include <linux/uaccess.h> +#include <linux/regmap.h> +#include <linux/spi/spi.h> + +/* 0x000 - 0x00d System Functions */ +#define LMK04832_REG_RST3W 0x000 +#define LMK04832_BIT_RESET BIT(7) +#define LMK04832_BIT_SPI_3WIRE_DIS BIT(4) +#define LMK04832_REG_POWERDOWN 0x002 +#define LMK04832_REG_ID_DEV_TYPE 0x003 +#define LMK04832_REG_ID_PROD_MSB 0x004 +#define LMK04832_REG_ID_PROD_LSB 0x005 +#define LMK04832_REG_ID_MASKREV 0x006 +#define LMK04832_REG_ID_VNDR_MSB 0x00c +#define LMK04832_REG_ID_VNDR_LSB 0x00d + +/* 0x100 - 0x137 Device Clock and SYSREF Clock Output Control */ +#define LMK04832_REG_CLKOUT_CTRL0(ch) (0x100 + (ch >> 1) * 8) +#define LMK04832_BIT_DCLK_DIV_LSB GENMASK(7, 0) +#define LMK04832_REG_CLKOUT_CTRL1(ch) (0x101 + (ch >> 1) * 8) +#define LMK04832_BIT_DCLKX_Y_DDLY_LSB GENMASK(7, 0) +#define LMK04832_REG_CLKOUT_CTRL2(ch) (0x102 + (ch >> 1) * 8) +#define LMK04832_BIT_CLKOUTX_Y_PD BIT(7) +#define LMK04832_BIT_DCLKX_Y_DDLY_PD BIT(4) +#define LMK04832_BIT_DCLKX_Y_DDLY_MSB GENMASK(3, 2) +#define LMK04832_BIT_DCLK_DIV_MSB GENMASK(1, 0) +#define LMK04832_REG_CLKOUT_SRC_MUX(ch) (0x103 + (ch % 2) + (ch >> 1) * 8) +#define LMK04832_BIT_CLKOUT_SRC_MUX BIT(5) +#define LMK04832_REG_CLKOUT_CTRL3(ch) (0x103 + (ch >> 1) * 8) +#define LMK04832_BIT_DCLKX_Y_PD BIT(4) +#define LMK04832_BIT_DCLKX_Y_DCC BIT(2) +#define LMK04832_BIT_DCLKX_Y_HS BIT(0) +#define LMK04832_REG_CLKOUT_CTRL4(ch) (0x104 + (ch >> 1) * 8) +#define LMK04832_BIT_SCLK_PD BIT(4) +#define LMK04832_BIT_SCLKX_Y_DIS_MODE GENMASK(3, 2) +#define LMK04832_REG_SCLKX_Y_ADLY(ch) (0x105 + (ch >> 1) * 8) +#define LMK04832_REG_SCLKX_Y_DDLY(ch) (0x106 + (ch >> 1) * 8) +#define LMK04832_BIT_SCLKX_Y_DDLY GENMASK(3, 0) +#define LMK04832_REG_CLKOUT_FMT(ch) (0x107 + (ch >> 1) * 8) +#define LMK04832_BIT_CLKOUT_FMT(ch) (ch % 2 ? 0xf0 : 0x0f) +#define LMK04832_VAL_CLKOUT_FMT_POWERDOWN 0x00 +#define LMK04832_VAL_CLKOUT_FMT_LVDS 0x01 +#define LMK04832_VAL_CLKOUT_FMT_HSDS6 0x02 +#define LMK04832_VAL_CLKOUT_FMT_HSDS8 0x03 +#define LMK04832_VAL_CLKOUT_FMT_LVPECL1600 0x04 +#define LMK04832_VAL_CLKOUT_FMT_LVPECL2000 0x05 +#define LMK04832_VAL_CLKOUT_FMT_LCPECL 0x06 +#define LMK04832_VAL_CLKOUT_FMT_CML16 0x07 +#define LMK04832_VAL_CLKOUT_FMT_CML24 0x08 +#define LMK04832_VAL_CLKOUT_FMT_CML32 0x09 +#define LMK04832_VAL_CLKOUT_FMT_CMOS_OFF_INV 0x0a +#define LMK04832_VAL_CLKOUT_FMT_CMOS_NOR_OFF 0x0b +#define LMK04832_VAL_CLKOUT_FMT_CMOS_INV_INV 0x0c +#define LMK04832_VAL_CLKOUT_FMT_CMOS_INV_NOR 0x0d +#define LMK04832_VAL_CLKOUT_FMT_CMOS_NOR_INV 0x0e +#define LMK04832_VAL_CLKOUT_FMT_CMOS_NOR_NOR 0x0f + +/* 0x138 - 0x145 SYSREF, SYNC, and Device Config */ +#define LMK04832_REG_VCO_OSCOUT 0x138 +#define LMK04832_BIT_VCO_MUX GENMASK(6, 5) +#define LMK04832_VAL_VCO_MUX_VCO0 0x00 +#define LMK04832_VAL_VCO_MUX_VCO1 0x01 +#define LMK04832_VAL_VCO_MUX_EXT 0x02 +#define LMK04832_REG_SYSREF_OUT 0x139 +#define LMK04832_BIT_SYSREF_REQ_EN BIT(6) +#define LMK04832_BIT_SYSREF_MUX GENMASK(1, 0) +#define LMK04832_VAL_SYSREF_MUX_NORMAL_SYNC 0x00 +#define LMK04832_VAL_SYSREF_MUX_RECLK 0x01 +#define LMK04832_VAL_SYSREF_MUX_PULSER 0x02 +#define LMK04832_VAL_SYSREF_MUX_CONTINUOUS 0x03 +#define LMK04832_REG_SYSREF_DIV_MSB 0x13a +#define LMK04832_BIT_SYSREF_DIV_MSB GENMASK(4, 0) +#define LMK04832_REG_SYSREF_DIV_LSB 0x13b +#define LMK04832_REG_SYSREF_DDLY_MSB 0x13c +#define LMK04832_BIT_SYSREF_DDLY_MSB GENMASK(4, 0) +#define LMK04832_REG_SYSREF_DDLY_LSB 0x13d +#define LMK04832_REG_SYSREF_PULSE_CNT 0x13e +#define LMK04832_REG_FB_CTRL 0x13f +#define LMK04832_BIT_PLL2_RCLK_MUX BIT(7) +#define LMK04832_VAL_PLL2_RCLK_MUX_OSCIN 0x00 +#define LMK04832_VAL_PLL2_RCLK_MUX_CLKIN 0x01 +#define LMK04832_BIT_PLL2_NCLK_MUX BIT(5) +#define LMK04832_VAL_PLL2_NCLK_MUX_PLL2_P 0x00 +#define LMK04832_VAL_PLL2_NCLK_MUX_FB_MUX 0x01 +#define LMK04832_BIT_FB_MUX_EN BIT(0) +#define LMK04832_REG_MAIN_PD 0x140 +#define LMK04832_BIT_PLL1_PD BIT(7) +#define LMK04832_BIT_VCO_LDO_PD BIT(6) +#define LMK04832_BIT_VCO_PD BIT(5) +#define LMK04832_BIT_OSCIN_PD BIT(4) +#define LMK04832_BIT_SYSREF_GBL_PD BIT(3) +#define LMK04832_BIT_SYSREF_PD BIT(2) +#define LMK04832_BIT_SYSREF_DDLY_PD BIT(1) +#define LMK04832_BIT_SYSREF_PLSR_PD BIT(0) +#define LMK04832_REG_SYNC 0x143 +#define LMK04832_BIT_SYNC_CLR BIT(7) +#define LMK04832_BIT_SYNC_1SHOT_EN BIT(6) +#define LMK04832_BIT_SYNC_POL BIT(5) +#define LMK04832_BIT_SYNC_EN BIT(4) +#define LMK04832_BIT_SYNC_MODE GENMASK(1, 0) +#define LMK04832_VAL_SYNC_MODE_OFF 0x00 +#define LMK04832_VAL_SYNC_MODE_ON 0x01 +#define LMK04832_VAL_SYNC_MODE_PULSER_PIN 0x02 +#define LMK04832_VAL_SYNC_MODE_PULSER_SPI 0x03 +#define LMK04832_REG_SYNC_DIS 0x144 + +/* 0x146 - 0x14a CLKin Control */ +#define LMK04832_REG_CLKIN_SEL0 0x148 +#define LMK04832_REG_CLKIN_SEL1 0x149 +#define LMK04832_REG_CLKIN_RST 0x14a +#define LMK04832_BIT_SDIO_RDBK_TYPE BIT(6) +#define LMK04832_BIT_CLKIN_SEL_MUX GENMASK(5, 3) +#define LMK04832_VAL_CLKIN_SEL_MUX_SPI_RDBK 0x06 +#define LMK04832_BIT_CLKIN_SEL_TYPE GENMASK(2, 0) +#define LMK04832_VAL_CLKIN_SEL_TYPE_OUT 0x03 + +/* 0x14b - 0x152 Holdover */ + +/* 0x153 - 0x15f PLL1 Configuration */ + +/* 0x160 - 0x16e PLL2 Configuration */ +#define LMK04832_REG_PLL2_R_MSB 0x160 +#define LMK04832_BIT_PLL2_R_MSB GENMASK(3, 0) +#define LMK04832_REG_PLL2_R_LSB 0x161 +#define LMK04832_REG_PLL2_MISC 0x162 +#define LMK04832_BIT_PLL2_MISC_P GENMASK(7, 5) +#define LMK04832_BIT_PLL2_MISC_REF_2X_EN BIT(0) +#define LMK04832_REG_PLL2_N_CAL_0 0x163 +#define LMK04832_BIT_PLL2_N_CAL_0 GENMASK(1, 0) +#define LMK04832_REG_PLL2_N_CAL_1 0x164 +#define LMK04832_REG_PLL2_N_CAL_2 0x165 +#define LMK04832_REG_PLL2_N_0 0x166 +#define LMK04832_BIT_PLL2_N_0 GENMASK(1, 0) +#define LMK04832_REG_PLL2_N_1 0x167 +#define LMK04832_REG_PLL2_N_2 0x168 +#define LMK04832_REG_PLL2_DLD_CNT_MSB 0x16a +#define LMK04832_REG_PLL2_DLD_CNT_LSB 0x16b +#define LMK04832_REG_PLL2_LD 0x16e +#define LMK04832_BIT_PLL2_LD_MUX GENMASK(7, 3) +#define LMK04832_VAL_PLL2_LD_MUX_PLL2_DLD 0x02 +#define LMK04832_BIT_PLL2_LD_TYPE GENMASK(2, 0) +#define LMK04832_VAL_PLL2_LD_TYPE_OUT_PP 0x03 + +/* 0x16F - 0x555 Misc Registers */ +#define LMK04832_REG_PLL2_PD 0x173 +#define LMK04832_BIT_PLL2_PRE_PD BIT(6) +#define LMK04832_BIT_PLL2_PD BIT(5) +#define LMK04832_REG_PLL1R_RST 0x177 +#define LMK04832_REG_CLR_PLL_LOST 0x182 +#define LMK04832_REG_RB_PLL_LD 0x183 +#define LMK04832_REG_RB_CLK_DAC_VAL_MSB 0x184 +#define LMK04832_REG_RB_DAC_VAL_LSB 0x185 +#define LMK04832_REG_RB_HOLDOVER 0x188 +#define LMK04832_REG_SPI_LOCK 0x555 + +enum lmk04832_device_types { + LMK04832, +}; + +/** + * lmk04832_device_info - Holds static device information that is specific to + * the chip revision + * + * pid: Product Identifier + * maskrev: IC version identifier + * num_channels: Number of available output channels (clkout count) + * vco0_range: {min, max} of the VCO0 operating range (in MHz) + * vco1_range: {min, max} of the VCO1 operating range (in MHz) + */ +struct lmk04832_device_info { + u16 pid; + u8 maskrev; + size_t num_channels; + unsigned int vco0_range[2]; + unsigned int vco1_range[2]; +}; + +static const struct lmk04832_device_info lmk04832_device_info[] = { + [LMK04832] = { + .pid = 0x63d1, /* WARNING PROD_ID is inverted in the datasheet */ + .maskrev = 0x70, + .num_channels = 14, + .vco0_range = { 2440, 2580 }, + .vco1_range = { 2945, 3255 }, + }, +}; + +enum lmk04832_rdbk_type { + RDBK_CLKIN_SEL0, + RDBK_CLKIN_SEL1, + RDBK_RESET, +}; + +struct lmk_dclk { + struct lmk04832 *lmk; + struct clk_hw hw; + u8 id; +}; + +struct lmk_clkout { + struct lmk04832 *lmk; + struct clk_hw hw; + bool sysref; + u32 format; + u8 id; +}; + +/** + * struct lmk04832 - The LMK04832 device structure + * + * @dev: reference to a struct device, linked to the spi_device + * @regmap: struct regmap instance use to access the chip + * @sync_mode: operational mode for SYNC signal + * @sysref_mux: select SYSREF source + * @sysref_pulse_cnt: number of SYSREF pulses generated while not in continuous + * mode. + * @sysref_ddly: SYSREF digital delay value + * @oscin: PLL2 input clock + * @vco: reference to the internal VCO clock + * @sclk: reference to the internal sysref clock (SCLK) + * @vco_rate: user provided VCO rate + * @reset_gpio: reference to the reset GPIO + * @dclk: list of internal device clock references. + * Each pair of clkout clocks share a single device clock (DCLKX_Y) + * @clkout: list of output clock references + * @clk_data: holds clkout related data like clk_hw* and number of clocks + */ +struct lmk04832 { + struct device *dev; + struct regmap *regmap; + + unsigned int sync_mode; + unsigned int sysref_mux; + unsigned int sysref_pulse_cnt; + unsigned int sysref_ddly; + + struct clk *oscin; + struct clk_hw vco; + struct clk_hw sclk; + unsigned int vco_rate; + + struct gpio_desc *reset_gpio; + + struct lmk_dclk *dclk; + struct lmk_clkout *clkout; + struct clk_hw_onecell_data *clk_data; +}; + +static bool lmk04832_regmap_rd_regs(struct device *dev, unsigned int reg) +{ + switch (reg) { + case LMK04832_REG_RST3W ... LMK04832_REG_ID_MASKREV: + fallthrough; + case LMK04832_REG_ID_VNDR_MSB: + fallthrough; + case LMK04832_REG_ID_VNDR_LSB: + fallthrough; + case LMK04832_REG_CLKOUT_CTRL0(0) ... LMK04832_REG_PLL2_DLD_CNT_LSB: + fallthrough; + case LMK04832_REG_PLL2_LD: + fallthrough; + case LMK04832_REG_PLL2_PD: + fallthrough; + case LMK04832_REG_PLL1R_RST: + fallthrough; + case LMK04832_REG_CLR_PLL_LOST ... LMK04832_REG_RB_DAC_VAL_LSB: + fallthrough; + case LMK04832_REG_RB_HOLDOVER: + fallthrough; + case LMK04832_REG_SPI_LOCK: + return true; + default: + return false; + }; +}; + +static bool lmk04832_regmap_wr_regs(struct device *dev, unsigned int reg) +{ + switch (reg) { + case LMK04832_REG_RST3W: + fallthrough; + case LMK04832_REG_POWERDOWN: + return true; + case LMK04832_REG_ID_DEV_TYPE ... LMK04832_REG_ID_MASKREV: + fallthrough; + case LMK04832_REG_ID_VNDR_MSB: + fallthrough; + case LMK04832_REG_ID_VNDR_LSB: + return false; + case LMK04832_REG_CLKOUT_CTRL0(0) ... LMK04832_REG_PLL2_DLD_CNT_LSB: + fallthrough; + case LMK04832_REG_PLL2_LD: + fallthrough; + case LMK04832_REG_PLL2_PD: + fallthrough; + case LMK04832_REG_PLL1R_RST: + fallthrough; + case LMK04832_REG_CLR_PLL_LOST ... LMK04832_REG_RB_DAC_VAL_LSB: + fallthrough; + case LMK04832_REG_RB_HOLDOVER: + fallthrough; + case LMK04832_REG_SPI_LOCK: + return true; + default: + return false; + }; +}; + +static const struct regmap_config regmap_config = { + .name = "lmk04832", + .reg_bits = 16, + .val_bits = 8, + .use_single_read = 1, + .use_single_write = 1, + .read_flag_mask = 0x80, + .write_flag_mask = 0x00, + .readable_reg = lmk04832_regmap_rd_regs, + .writeable_reg = lmk04832_regmap_wr_regs, + .cache_type = REGCACHE_NONE, + .max_register = LMK04832_REG_SPI_LOCK, +}; + +static int lmk04832_vco_is_enabled(struct clk_hw *hw) +{ + struct lmk04832 *lmk = container_of(hw, struct lmk04832, vco); + unsigned int tmp; + int ret; + + ret = regmap_read(lmk->regmap, LMK04832_REG_MAIN_PD, &tmp); + if (ret) + return ret; + + return !(FIELD_GET(LMK04832_BIT_OSCIN_PD, tmp) | + FIELD_GET(LMK04832_BIT_VCO_PD, tmp) | + FIELD_GET(LMK04832_BIT_VCO_LDO_PD, tmp)); +} + +static int lmk04832_vco_prepare(struct clk_hw *hw) +{ + struct lmk04832 *lmk = container_of(hw, struct lmk04832, vco); + int ret; + + ret = regmap_update_bits(lmk->regmap, LMK04832_REG_PLL2_PD, + LMK04832_BIT_PLL2_PRE_PD | + LMK04832_BIT_PLL2_PD, + 0x00); + if (ret) + return ret; + + return regmap_update_bits(lmk->regmap, LMK04832_REG_MAIN_PD, + LMK04832_BIT_VCO_LDO_PD | + LMK04832_BIT_VCO_PD | + LMK04832_BIT_OSCIN_PD, 0x00); +} + +static void lmk04832_vco_unprepare(struct clk_hw *hw) +{ + struct lmk04832 *lmk = container_of(hw, struct lmk04832, vco); + + regmap_update_bits(lmk->regmap, LMK04832_REG_PLL2_PD, + LMK04832_BIT_PLL2_PRE_PD | LMK04832_BIT_PLL2_PD, + 0xff); + + /* Don't set LMK04832_BIT_OSCIN_PD since other clocks depend on it */ + regmap_update_bits(lmk->regmap, LMK04832_REG_MAIN_PD, + LMK04832_BIT_VCO_LDO_PD | LMK04832_BIT_VCO_PD, 0xff); +} + +static unsigned long lmk04832_vco_recalc_rate(struct clk_hw *hw, + unsigned long prate) +{ + struct lmk04832 *lmk = container_of(hw, struct lmk04832, vco); + unsigned int pll2_p[] = {8, 2, 2, 3, 4, 5, 6, 7}; + unsigned int pll2_n, p, pll2_r; + unsigned int pll2_misc; + unsigned long vco_rate; + u8 tmp[3]; + int ret; + + ret = regmap_read(lmk->regmap, LMK04832_REG_PLL2_MISC, &pll2_misc); + if (ret) + return ret; + + p = FIELD_GET(LMK04832_BIT_PLL2_MISC_P, pll2_misc); + + ret = regmap_bulk_read(lmk->regmap, LMK04832_REG_PLL2_N_0, &tmp, 3); + if (ret) + return ret; + + pll2_n = FIELD_PREP(0x030000, tmp[0]) | + FIELD_PREP(0x00ff00, tmp[1]) | + FIELD_PREP(0x0000ff, tmp[2]); + + ret = regmap_bulk_read(lmk->regmap, LMK04832_REG_PLL2_R_MSB, &tmp, 2); + if (ret) + return ret; + + pll2_r = FIELD_PREP(0x0f00, tmp[0]) | + FIELD_PREP(0x00ff, tmp[1]); + + vco_rate = (prate << FIELD_GET(LMK04832_BIT_PLL2_MISC_REF_2X_EN, + pll2_misc)) * pll2_n * pll2_p[p] / pll2_r; + + return vco_rate; +}; + +/** + * lmk04832_check_vco_ranges - Check requested VCO frequency against VCO ranges + * + * @lmk: Reference to the lmk device + * @rate: Desired output rate for the VCO + * + * The LMK04832 has 2 internal VCO, each with independent operating ranges. + * Use the device_info structure to determine which VCO to use based on rate. + * + * Returns VCO_MUX value or negative errno. + */ +static int lmk04832_check_vco_ranges(struct lmk04832 *lmk, unsigned long rate) +{ + struct spi_device *spi = to_spi_device(lmk->dev); + const struct lmk04832_device_info *info; + unsigned long mhz = rate / 1000000; + + info = &lmk04832_device_info[spi_get_device_id(spi)->driver_data]; + + if (mhz >= info->vco0_range[0] && mhz <= info->vco0_range[1]) + return LMK04832_VAL_VCO_MUX_VCO0; + + if (mhz >= info->vco1_range[0] && mhz <= info->vco1_range[1]) + return LMK04832_VAL_VCO_MUX_VCO1; + + dev_err(lmk->dev, "%lu Hz is out of VCO ranges\n", rate); + return -ERANGE; +} + +/** + * lmk04832_calc_pll2_params - Get PLL2 parameters used to set the VCO frequency + * + * @prate: parent rate to the PLL2, usually OSCin + * @rate: Desired output rate for the VCO + * @n: reference to PLL2_N + * @p: reference to PLL2_P + * @r: reference to PLL2_R + * + * This functions assumes LMK04832_BIT_PLL2_MISC_REF_2X_EN is set since it is + * recommended in the datasheet because a higher phase detector frequencies + * makes the design of wider loop bandwidth filters possible. + * + * the VCO rate can be calculated using the following expression: + * + * VCO = OSCin * 2 * PLL2_N * PLL2_P / PLL2_R + * + * Returns vco rate or negative errno. + */ +static long lmk04832_calc_pll2_params(unsigned long prate, unsigned long rate, + unsigned int *n, unsigned int *p, + unsigned int *r) +{ + unsigned int pll2_n, pll2_p, pll2_r; + unsigned long num, div; + + /* Set PLL2_P to a fixed value to simplify optimizations */ + pll2_p = 2; + + div = gcd(rate, prate); + + num = DIV_ROUND_CLOSEST(rate, div); + pll2_r = DIV_ROUND_CLOSEST(prate, div); + + if (num > 4) { + pll2_n = num >> 2; + } else { + pll2_r = pll2_r << 2; + pll2_n = num; + } + + if (pll2_n < 1 || pll2_n > 0x03ffff) + return -EINVAL; + if (pll2_r < 1 || pll2_r > 0xfff) + return -EINVAL; + + *n = pll2_n; + *p = pll2_p; + *r = pll2_r; + + return DIV_ROUND_CLOSEST(prate * 2 * pll2_p * pll2_n, pll2_r); +} + +static long lmk04832_vco_round_rate(struct clk_hw *hw, unsigned long rate, + unsigned long *prate) +{ + struct lmk04832 *lmk = container_of(hw, struct lmk04832, vco); + unsigned int n, p, r; + long vco_rate; + int ret; + + ret = lmk04832_check_vco_ranges(lmk, rate); + if (ret < 0) + return ret; + + vco_rate = lmk04832_calc_pll2_params(*prate, rate, &n, &p, &r); + if (vco_rate < 0) { + dev_err(lmk->dev, "PLL2 parmeters out of range\n"); + return vco_rate; + } + + if (rate != vco_rate) + return -EINVAL; + + return vco_rate; +}; + +static int lmk04832_vco_set_rate(struct clk_hw *hw, unsigned long rate, + unsigned long prate) +{ + struct lmk04832 *lmk = container_of(hw, struct lmk04832, vco); + unsigned int n, p, r; + long vco_rate; + int vco_mux; + int ret; + + vco_mux = lmk04832_check_vco_ranges(lmk, rate); + if (vco_mux < 0) + return vco_mux; + + ret = regmap_update_bits(lmk->regmap, LMK04832_REG_VCO_OSCOUT, + LMK04832_BIT_VCO_MUX, + FIELD_PREP(LMK04832_BIT_VCO_MUX, vco_mux)); + if (ret) + return ret; + + vco_rate = lmk04832_calc_pll2_params(prate, rate, &n, &p, &r); + if (vco_rate < 0) { + dev_err(lmk->dev, "failed to determine PLL2 parmeters\n"); + return vco_rate; + } + + ret = regmap_update_bits(lmk->regmap, LMK04832_REG_PLL2_R_MSB, + LMK04832_BIT_PLL2_R_MSB, + FIELD_GET(0x000700, r)); + if (ret) + return ret; + + ret = regmap_write(lmk->regmap, LMK04832_REG_PLL2_R_LSB, + FIELD_GET(0x0000ff, r)); + if (ret) + return ret; + + ret = regmap_update_bits(lmk->regmap, LMK04832_REG_PLL2_MISC, + LMK04832_BIT_PLL2_MISC_P, + FIELD_PREP(LMK04832_BIT_PLL2_MISC_P, p)); + if (ret) + return ret; + + /* + * PLL2_N registers must be programmed after other PLL2 dividers are + * programed to ensure proper VCO frequency calibration + */ + ret = regmap_write(lmk->regmap, LMK04832_REG_PLL2_N_0, + FIELD_GET(0x030000, n)); + if (ret) + return ret; + ret = regmap_write(lmk->regmap, LMK04832_REG_PLL2_N_1, + FIELD_GET(0x00ff00, n)); + if (ret) + return ret; + + return regmap_write(lmk->regmap, LMK04832_REG_PLL2_N_2, + FIELD_GET(0x0000ff, n)); +}; + +static const struct clk_ops lmk04832_vco_ops = { + .is_enabled = lmk04832_vco_is_enabled, + .prepare = lmk04832_vco_prepare, + .unprepare = lmk04832_vco_unprepare, + .recalc_rate = lmk04832_vco_recalc_rate, + .round_rate = lmk04832_vco_round_rate, + .set_rate = lmk04832_vco_set_rate, +}; + +/* + * lmk04832_register_vco - Initialize the internal VCO and clock distribution + * path in PLL2 single loop mode. + */ +static int lmk04832_register_vco(struct lmk04832 *lmk) +{ + const char *parent_names[1]; + struct clk_init_data init; + int ret; + + init.name = "lmk-vco"; + parent_names[0] = __clk_get_name(lmk->oscin); + init.parent_names = parent_names; + + init.ops = &lmk04832_vco_ops; + init.num_parents = 1; + + ret = regmap_update_bits(lmk->regmap, LMK04832_REG_VCO_OSCOUT, + LMK04832_BIT_VCO_MUX, + FIELD_PREP(LMK04832_BIT_VCO_MUX, + LMK04832_VAL_VCO_MUX_VCO1)); + if (ret) + return ret; + + ret = regmap_update_bits(lmk->regmap, LMK04832_REG_FB_CTRL, + LMK04832_BIT_PLL2_RCLK_MUX | + LMK04832_BIT_PLL2_NCLK_MUX, + FIELD_PREP(LMK04832_BIT_PLL2_RCLK_MUX, + LMK04832_VAL_PLL2_RCLK_MUX_OSCIN)| + FIELD_PREP(LMK04832_BIT_PLL2_NCLK_MUX, + LMK04832_VAL_PLL2_NCLK_MUX_PLL2_P)); + if (ret) + return ret; + + ret = regmap_update_bits(lmk->regmap, LMK04832_REG_PLL2_MISC, + LMK04832_BIT_PLL2_MISC_REF_2X_EN, + LMK04832_BIT_PLL2_MISC_REF_2X_EN); + if (ret) + return ret; + + ret = regmap_write(lmk->regmap, LMK04832_REG_PLL2_LD, + FIELD_PREP(LMK04832_BIT_PLL2_LD_MUX, + LMK04832_VAL_PLL2_LD_MUX_PLL2_DLD) | + FIELD_PREP(LMK04832_BIT_PLL2_LD_TYPE, + LMK04832_VAL_PLL2_LD_TYPE_OUT_PP)); + if (ret) + return ret; + + lmk->vco.init = &init; + return devm_clk_hw_register(lmk->dev, &lmk->vco); +} + +static int lmk04832_clkout_set_ddly(struct lmk04832 *lmk, int id) +{ + int dclk_div_adj[] = {0, 0, -2, -2, 0, 3, -1, 0}; + unsigned int sclkx_y_ddly = 10; + unsigned int dclkx_y_ddly; + unsigned int dclkx_y_div; + unsigned int sysref_ddly; + unsigned int dclkx_y_hs; + unsigned int lsb, msb; + int ret; + + ret = regmap_update_bits(lmk->regmap, + LMK04832_REG_CLKOUT_CTRL2(id), + LMK04832_BIT_DCLKX_Y_DDLY_PD, + FIELD_PREP(LMK04832_BIT_DCLKX_Y_DDLY_PD, 0)); + if (ret) + return ret; + + ret = regmap_read(lmk->regmap, LMK04832_REG_SYSREF_DDLY_LSB, &lsb); + if (ret) + return ret; + + ret = regmap_read(lmk->regmap, LMK04832_REG_SYSREF_DDLY_MSB, &msb); + if (ret) + return ret; + + sysref_ddly = FIELD_GET(LMK04832_BIT_SYSREF_DDLY_MSB, msb) << 8 | lsb; + + ret = regmap_read(lmk->regmap, LMK04832_REG_CLKOUT_CTRL0(id), &lsb); + if (ret) + return ret; + + ret = regmap_read(lmk->regmap, LMK04832_REG_CLKOUT_CTRL2(id), &msb); + if (ret) + return ret; + + dclkx_y_div = FIELD_GET(LMK04832_BIT_DCLK_DIV_MSB, msb) << 8 | lsb; + + ret = regmap_read(lmk->regmap, LMK04832_REG_CLKOUT_CTRL3(id), &lsb); + if (ret) + return ret; + + dclkx_y_hs = FIELD_GET(LMK04832_BIT_DCLKX_Y_HS, lsb); + + dclkx_y_ddly = sysref_ddly + 1 - + dclk_div_adj[dclkx_y_div < 6 ? dclkx_y_div : 7] - + dclkx_y_hs + sclkx_y_ddly; + + if (dclkx_y_ddly < 7 || dclkx_y_ddly > 0x3fff) { + dev_err(lmk->dev, "DCLKX_Y_DDLY out of range (%d)\n", + dclkx_y_ddly); + return -EINVAL; + } + + ret = regmap_write(lmk->regmap, + LMK04832_REG_SCLKX_Y_DDLY(id), + FIELD_GET(LMK04832_BIT_SCLKX_Y_DDLY, sclkx_y_ddly)); + if (ret) + return ret; + + ret = regmap_write(lmk->regmap, LMK04832_REG_CLKOUT_CTRL1(id), + FIELD_GET(0x00ff, dclkx_y_ddly)); + if (ret) + return ret; + + dev_dbg(lmk->dev, "clkout%02u: sysref_ddly=%u, dclkx_y_ddly=%u, " + "dclk_div_adj=%+d, dclkx_y_hs=%u, sclkx_y_ddly=%u\n", + id, sysref_ddly, dclkx_y_ddly, + dclk_div_adj[dclkx_y_div < 6 ? dclkx_y_div : 7], + dclkx_y_hs, sclkx_y_ddly); + + return regmap_update_bits(lmk->regmap, LMK04832_REG_CLKOUT_CTRL2(id), + LMK04832_BIT_DCLKX_Y_DDLY_MSB, + FIELD_GET(0x0300, dclkx_y_ddly)); +} + +/** lmk04832_sclk_sync - Establish deterministic phase relationship between sclk + * and dclk + * + * @lmk: Reference to the lmk device + * + * The synchronization sequence: + * - in the datasheet https://www.ti.com/lit/ds/symlink/lmk04832.pdf, p.31 + * (8.3.3.1 How to enable SYSREF) + * - Ti forum: https://e2e.ti.com/support/clock-and-timing/f/48/t/970972 + * + * Returns 0 or negative errno. + */ +static int lmk04832_sclk_sync_sequence(struct lmk04832 *lmk) +{ + int ret; + int i; + + /* 1. (optional) mute all sysref_outputs during synchronization */ + /* 2. Enable and write device clock digital delay to applicable clocks */ + ret = regmap_update_bits(lmk->regmap, LMK04832_REG_MAIN_PD, + LMK04832_BIT_SYSREF_DDLY_PD, + FIELD_PREP(LMK04832_BIT_SYSREF_DDLY_PD, 0)); + if (ret) + return ret; + + for (i = 0; i < lmk->clk_data->num; i += 2) { + ret = lmk04832_clkout_set_ddly(lmk, i); + if (ret) + return ret; + } + + /* + * 3. Configure SYNC_MODE to SYNC_PIN and SYSREF_MUX to Normal SYNC, + * and clear SYSREF_REQ_EN (see 6.) + */ + ret = regmap_update_bits(lmk->regmap, LMK04832_REG_SYSREF_OUT, + LMK04832_BIT_SYSREF_REQ_EN | + LMK04832_BIT_SYSREF_MUX, + FIELD_PREP(LMK04832_BIT_SYSREF_REQ_EN, 0) | + FIELD_PREP(LMK04832_BIT_SYSREF_MUX, + LMK04832_VAL_SYSREF_MUX_NORMAL_SYNC)); + if (ret) + return ret; + + ret = regmap_update_bits(lmk->regmap, LMK04832_REG_SYNC, + LMK04832_BIT_SYNC_MODE, + FIELD_PREP(LMK04832_BIT_SYNC_MODE, + LMK04832_VAL_SYNC_MODE_ON)); + if (ret) + return ret; + + /* 4. Clear SYNXC_DISx or applicable clocks and clear SYNC_DISSYSREF */ + ret = regmap_write(lmk->regmap, LMK04832_REG_SYNC_DIS, 0x00); + if (ret) + return ret; + + /* + * 5. If SCLKX_Y_DDLY != 0, Set SYSREF_CLR=1 for at least 15 clock + * distribution path cycles (VCO cycles), then back to 0. In + * PLL2-only use case, this will be complete in less than one SPI + * transaction. If SYSREF local digital delay is not used, this step + * can be skipped. + */ + ret = regmap_update_bits(lmk->regmap, LMK04832_REG_SYNC, + LMK04832_BIT_SYNC_CLR, + FIELD_PREP(LMK04832_BIT_SYNC_CLR, 0x01)); + if (ret) + return ret; + + ret = regmap_update_bits(lmk->regmap, LMK04832_REG_SYNC, + LMK04832_BIT_SYNC_CLR, + FIELD_PREP(LMK04832_BIT_SYNC_CLR, 0x00)); + if (ret) + return ret; + + /* + * 6. Toggle SYNC_POL state between inverted and not inverted. + * If you use an external signal on the SYNC pin instead of toggling + * SYNC_POL, make sure that SYSREF_REQ_EN=0 so that the SYSREF_MUX + * does not shift into continuous SYSREF mode. + */ + ret = regmap_update_bits(lmk->regmap, LMK04832_REG_SYNC, + LMK04832_BIT_SYNC_POL, + FIELD_PREP(LMK04832_BIT_SYNC_POL, 0x01)); + if (ret) + return ret; + + ret = regmap_update_bits(lmk->regmap, LMK04832_REG_SYNC, + LMK04832_BIT_SYNC_POL, + FIELD_PREP(LMK04832_BIT_SYNC_POL, 0x00)); + if (ret) + return ret; + + /* 7. Set all SYNC_DISx=1, including SYNC_DISSYSREF */ + ret = regmap_write(lmk->regmap, LMK04832_REG_SYNC_DIS, 0xff); + if (ret) + return ret; + + /* 8. Restore state of SYNC_MODE and SYSREF_MUX to desired values */ + ret = regmap_update_bits(lmk->regmap, LMK04832_REG_SYSREF_OUT, + LMK04832_BIT_SYSREF_MUX, + FIELD_PREP(LMK04832_BIT_SYSREF_MUX, + lmk->sysref_mux)); + if (ret) + return ret; + + ret = regmap_update_bits(lmk->regmap, LMK04832_REG_SYNC, + LMK04832_BIT_SYNC_MODE, + FIELD_PREP(LMK04832_BIT_SYNC_MODE, + lmk->sync_mode)); + if (ret) + return ret; + + /* + * 9. (optional) if SCLKx_y_DIS_MODE was used to mute SYSREF outputs + * during the SYNC event, restore SCLKx_y_DIS_MODE=0 for active state, + * or set SYSREF_GBL_PD=0 if SCLKx_y_DIS_MODE is set to a conditional + * option. + */ + + /* + * 10. (optional) To reduce power consumption, after the synchronization + * event is complete, DCLKx_y_DDLY_PD=1 and SYSREF_DDLY_PD=1 disable the + * digital delay counters (which are only used immediately after the + * SYNC pulse to delay the output by some number of VCO counts). + */ + + return ret; +} + +static int lmk04832_sclk_is_enabled(struct clk_hw *hw) +{ + struct lmk04832 *lmk = container_of(hw, struct lmk04832, sclk); + unsigned int tmp; + int ret; + + ret = regmap_read(lmk->regmap, LMK04832_REG_MAIN_PD, &tmp); + if (ret) + return ret; + + return FIELD_GET(LMK04832_BIT_SYSREF_PD, tmp); +} + +static int lmk04832_sclk_prepare(struct clk_hw *hw) +{ + struct lmk04832 *lmk = container_of(hw, struct lmk04832, sclk); + + return regmap_update_bits(lmk->regmap, LMK04832_REG_MAIN_PD, + LMK04832_BIT_SYSREF_PD, 0x00); +} + +static void lmk04832_sclk_unprepare(struct clk_hw *hw) +{ + struct lmk04832 *lmk = container_of(hw, struct lmk04832, sclk); + + regmap_update_bits(lmk->regmap, LMK04832_REG_MAIN_PD, + LMK04832_BIT_SYSREF_PD, LMK04832_BIT_SYSREF_PD); +} + +static unsigned long lmk04832_sclk_recalc_rate(struct clk_hw *hw, + unsigned long prate) +{ + struct lmk04832 *lmk = container_of(hw, struct lmk04832, sclk); + unsigned int sysref_div; + u8 tmp[2]; + int ret; + + ret = regmap_bulk_read(lmk->regmap, LMK04832_REG_SYSREF_DIV_MSB, &tmp, 2); + if (ret) + return ret; + + sysref_div = FIELD_GET(LMK04832_BIT_SYSREF_DIV_MSB, tmp[0]) << 8 | + tmp[1]; + + return DIV_ROUND_CLOSEST(prate, sysref_div); +} + +static long lmk04832_sclk_round_rate(struct clk_hw *hw, unsigned long rate, + unsigned long *prate) +{ + struct lmk04832 *lmk = container_of(hw, struct lmk04832, sclk); + unsigned long sclk_rate; + unsigned int sysref_div; + + sysref_div = DIV_ROUND_CLOSEST(*prate, rate); + sclk_rate = DIV_ROUND_CLOSEST(*prate, sysref_div); + + if (sysref_div < 0x07 || sysref_div > 0x1fff) { + dev_err(lmk->dev, "SYSREF divider out of range\n"); + return -EINVAL; + } + + if (rate != sclk_rate) + return -EINVAL; + + return sclk_rate; +} + +static int lmk04832_sclk_set_rate(struct clk_hw *hw, unsigned long rate, + unsigned long prate) +{ + struct lmk04832 *lmk = container_of(hw, struct lmk04832, sclk); + unsigned int sysref_div; + int ret; + + sysref_div = DIV_ROUND_CLOSEST(prate, rate); + + if (sysref_div < 0x07 || sysref_div > 0x1fff) { + dev_err(lmk->dev, "SYSREF divider out of range\n"); + return -EINVAL; + } + + ret = regmap_write(lmk->regmap, LMK04832_REG_SYSREF_DIV_MSB, + FIELD_GET(0x1f00, sysref_div)); + if (ret) + return ret; + + ret = regmap_write(lmk->regmap, LMK04832_REG_SYSREF_DIV_LSB, + FIELD_GET(0x00ff, sysref_div)); + if (ret) + return ret; + + ret = lmk04832_sclk_sync_sequence(lmk); + if (ret) + dev_err(lmk->dev, "SYNC sequence failed\n"); + + return ret; +} + +static const struct clk_ops lmk04832_sclk_ops = { + .is_enabled = lmk04832_sclk_is_enabled, + .prepare = lmk04832_sclk_prepare, + .unprepare = lmk04832_sclk_unprepare, + .recalc_rate = lmk04832_sclk_recalc_rate, + .round_rate = lmk04832_sclk_round_rate, + .set_rate = lmk04832_sclk_set_rate, +}; + +static int lmk04832_register_sclk(struct lmk04832 *lmk) +{ + const char *parent_names[1]; + struct clk_init_data init; + int ret; + + init.name = "lmk-sclk"; + parent_names[0] = clk_hw_get_name(&lmk->vco); + init.parent_names = parent_names; + + init.ops = &lmk04832_sclk_ops; + init.flags = CLK_SET_RATE_PARENT; + init.num_parents = 1; + + ret = regmap_update_bits(lmk->regmap, LMK04832_REG_SYSREF_OUT, + LMK04832_BIT_SYSREF_MUX, + FIELD_PREP(LMK04832_BIT_SYSREF_MUX, + lmk->sysref_mux)); + if (ret) + return ret; + + ret = regmap_write(lmk->regmap, LMK04832_REG_SYSREF_DDLY_LSB, + FIELD_GET(0x00ff, lmk->sysref_ddly)); + if (ret) + return ret; + + ret = regmap_write(lmk->regmap, LMK04832_REG_SYSREF_DDLY_MSB, + FIELD_GET(0x1f00, lmk->sysref_ddly)); + if (ret) + return ret; + + ret = regmap_write(lmk->regmap, LMK04832_REG_SYSREF_PULSE_CNT, + ilog2(lmk->sysref_pulse_cnt)); + if (ret) + return ret; + + ret = regmap_update_bits(lmk->regmap, LMK04832_REG_MAIN_PD, + LMK04832_BIT_SYSREF_DDLY_PD | + LMK04832_BIT_SYSREF_PLSR_PD, + FIELD_PREP(LMK04832_BIT_SYSREF_DDLY_PD, 0) | + FIELD_PREP(LMK04832_BIT_SYSREF_PLSR_PD, 0)); + if (ret) + return ret; + + ret = regmap_write(lmk->regmap, LMK04832_REG_SYNC, + FIELD_PREP(LMK04832_BIT_SYNC_POL, 0) | + FIELD_PREP(LMK04832_BIT_SYNC_EN, 1) | + FIELD_PREP(LMK04832_BIT_SYNC_MODE, lmk->sync_mode)); + if (ret) + return ret; + + ret = regmap_write(lmk->regmap, LMK04832_REG_SYNC_DIS, 0xff); + if (ret) + return ret; + + lmk->sclk.init = &init; + return devm_clk_hw_register(lmk->dev, &lmk->sclk); +} + +static int lmk04832_dclk_is_enabled(struct clk_hw *hw) +{ + struct lmk_dclk *dclk = container_of(hw, struct lmk_dclk, hw); + struct lmk04832 *lmk = dclk->lmk; + unsigned int tmp; + int ret; + + ret = regmap_read(lmk->regmap, LMK04832_REG_CLKOUT_CTRL3(dclk->id), + &tmp); + if (ret) + return ret; + + return !FIELD_GET(LMK04832_BIT_DCLKX_Y_PD, tmp); +} + +static int lmk04832_dclk_prepare(struct clk_hw *hw) +{ + struct lmk_dclk *dclk = container_of(hw, struct lmk_dclk, hw); + struct lmk04832 *lmk = dclk->lmk; + + return regmap_update_bits(lmk->regmap, + LMK04832_REG_CLKOUT_CTRL3(dclk->id), + LMK04832_BIT_DCLKX_Y_PD, 0x00); +} + +static void lmk04832_dclk_unprepare(struct clk_hw *hw) +{ + struct lmk_dclk *dclk = container_of(hw, struct lmk_dclk, hw); + struct lmk04832 *lmk = dclk->lmk; + + regmap_update_bits(lmk->regmap, + LMK04832_REG_CLKOUT_CTRL3(dclk->id), + LMK04832_BIT_DCLKX_Y_PD, 0xff); +} + +static unsigned long lmk04832_dclk_recalc_rate(struct clk_hw *hw, + unsigned long prate) +{ + struct lmk_dclk *dclk = container_of(hw, struct lmk_dclk, hw); + struct lmk04832 *lmk = dclk->lmk; + unsigned int dclk_div; + unsigned int lsb, msb; + unsigned long rate; + int ret; + + ret = regmap_read(lmk->regmap, LMK04832_REG_CLKOUT_CTRL0(dclk->id), + &lsb); + if (ret) + return ret; + + ret = regmap_read(lmk->regmap, LMK04832_REG_CLKOUT_CTRL2(dclk->id), + &msb); + if (ret) + return ret; + + dclk_div = FIELD_GET(LMK04832_BIT_DCLK_DIV_MSB, msb) << 8 | lsb; + rate = DIV_ROUND_CLOSEST(prate, dclk_div); + + return rate; +}; + +static long lmk04832_dclk_round_rate(struct clk_hw *hw, unsigned long rate, + unsigned long *prate) +{ + struct lmk_dclk *dclk = container_of(hw, struct lmk_dclk, hw); + struct lmk04832 *lmk = dclk->lmk; + unsigned long dclk_rate; + unsigned int dclk_div; + + dclk_div = DIV_ROUND_CLOSEST(*prate, rate); + dclk_rate = DIV_ROUND_CLOSEST(*prate, dclk_div); + + if (dclk_div < 1 || dclk_div > 0x3ff) { + dev_err(lmk->dev, "%s_div out of range\n", clk_hw_get_name(hw)); + return -EINVAL; + } + + if (rate != dclk_rate) + return -EINVAL; + + return dclk_rate; +}; + +static int lmk04832_dclk_set_rate(struct clk_hw *hw, unsigned long rate, + unsigned long prate) +{ + struct lmk_dclk *dclk = container_of(hw, struct lmk_dclk, hw); + struct lmk04832 *lmk = dclk->lmk; + unsigned int dclk_div; + int ret; + + dclk_div = DIV_ROUND_CLOSEST(prate, rate); + + if (dclk_div > 0x3ff) { + dev_err(lmk->dev, "%s_div out of range\n", clk_hw_get_name(hw)); + return -EINVAL; + } + + /* Enable Duty Cycle Corretion */ + if (dclk_div == 1) { + ret = regmap_update_bits(lmk->regmap, + LMK04832_REG_CLKOUT_CTRL3(dclk->id), + LMK04832_BIT_DCLKX_Y_DCC, + FIELD_PREP(LMK04832_BIT_DCLKX_Y_DCC, 1)); + if (ret) + return ret; + } + + /* + * While using Divide-by-2 or Divide-by-3 for DCLK_X_Y_DIV, SYNC + * procedure requires to first program Divide-by-4 and then back to + * Divide-by-2 or Divide-by-3 before doing SYNC. + */ + if (dclk_div == 2 || dclk_div == 3) { + ret = regmap_update_bits(lmk->regmap, + LMK04832_REG_CLKOUT_CTRL2(dclk->id), + LMK04832_BIT_DCLK_DIV_MSB, 0x00); + if (ret) + return ret; + + ret = regmap_write(lmk->regmap, + LMK04832_REG_CLKOUT_CTRL0(dclk->id), 0x04); + if (ret) + return ret; + } + + ret = regmap_write(lmk->regmap, LMK04832_REG_CLKOUT_CTRL0(dclk->id), + FIELD_GET(0x0ff, dclk_div)); + if (ret) + return ret; + + ret = regmap_update_bits(lmk->regmap, + LMK04832_REG_CLKOUT_CTRL2(dclk->id), + LMK04832_BIT_DCLK_DIV_MSB, + FIELD_GET(0x300, dclk_div)); + if (ret) + return ret; + + ret = lmk04832_sclk_sync_sequence(lmk); + if (ret) + dev_err(lmk->dev, "SYNC sequence failed\n"); + + return ret; +}; + +static const struct clk_ops lmk04832_dclk_ops = { + .is_enabled = lmk04832_dclk_is_enabled, + .prepare = lmk04832_dclk_prepare, + .unprepare = lmk04832_dclk_unprepare, + .recalc_rate = lmk04832_dclk_recalc_rate, + .round_rate = lmk04832_dclk_round_rate, + .set_rate = lmk04832_dclk_set_rate, +}; + +static int lmk04832_clkout_is_enabled(struct clk_hw *hw) +{ + struct lmk_clkout *clkout = container_of(hw, struct lmk_clkout, hw); + struct lmk04832 *lmk = clkout->lmk; + unsigned int clkoutx_y_pd; + unsigned int sclkx_y_pd; + unsigned int tmp; + u32 enabled; + int ret; + u8 fmt; + + ret = regmap_read(lmk->regmap, LMK04832_REG_CLKOUT_CTRL2(clkout->id), + &clkoutx_y_pd); + if (ret) + return ret; + + enabled = !FIELD_GET(LMK04832_BIT_CLKOUTX_Y_PD, clkoutx_y_pd); + + ret = regmap_read(lmk->regmap, LMK04832_REG_CLKOUT_SRC_MUX(clkout->id), + &tmp); + if (ret) + return ret; + + if (FIELD_GET(LMK04832_BIT_CLKOUT_SRC_MUX, tmp)) { + ret = regmap_read(lmk->regmap, + LMK04832_REG_CLKOUT_CTRL4(clkout->id), + &sclkx_y_pd); + if (ret) + return ret; + + enabled = enabled && !FIELD_GET(LMK04832_BIT_SCLK_PD, sclkx_y_pd); + } + + ret = regmap_read(lmk->regmap, LMK04832_REG_CLKOUT_FMT(clkout->id), + &tmp); + if (ret) + return ret; + + if (clkout->id % 2) + fmt = FIELD_GET(0xf0, tmp); + else + fmt = FIELD_GET(0x0f, tmp); + + return enabled && !fmt; +} + +static int lmk04832_clkout_prepare(struct clk_hw *hw) +{ + struct lmk_clkout *clkout = container_of(hw, struct lmk_clkout, hw); + struct lmk04832 *lmk = clkout->lmk; + unsigned int tmp; + int ret; + + if (clkout->format == LMK04832_VAL_CLKOUT_FMT_POWERDOWN) + dev_err(lmk->dev, "prepared %s but format is powerdown\n", + clk_hw_get_name(hw)); + + ret = regmap_update_bits(lmk->regmap, + LMK04832_REG_CLKOUT_CTRL2(clkout->id), + LMK04832_BIT_CLKOUTX_Y_PD, 0x00); + if (ret) + return ret; + + ret = regmap_read(lmk->regmap, LMK04832_REG_CLKOUT_SRC_MUX(clkout->id), + &tmp); + if (ret) + return ret; + + if (FIELD_GET(LMK04832_BIT_CLKOUT_SRC_MUX, tmp)) { + ret = regmap_update_bits(lmk->regmap, + LMK04832_REG_CLKOUT_CTRL4(clkout->id), + LMK04832_BIT_SCLK_PD, 0x00); + if (ret) + return ret; + } + + return regmap_update_bits(lmk->regmap, + LMK04832_REG_CLKOUT_FMT(clkout->id), + LMK04832_BIT_CLKOUT_FMT(clkout->id), + clkout->format << 4 * (clkout->id % 2)); +} + +static void lmk04832_clkout_unprepare(struct clk_hw *hw) +{ + struct lmk_clkout *clkout = container_of(hw, struct lmk_clkout, hw); + struct lmk04832 *lmk = clkout->lmk; + + regmap_update_bits(lmk->regmap, LMK04832_REG_CLKOUT_FMT(clkout->id), + LMK04832_BIT_CLKOUT_FMT(clkout->id), + 0x00); +} + +static int lmk04832_clkout_set_parent(struct clk_hw *hw, uint8_t index) +{ + struct lmk_clkout *clkout = container_of(hw, struct lmk_clkout, hw); + struct lmk04832 *lmk = clkout->lmk; + + return regmap_update_bits(lmk->regmap, + LMK04832_REG_CLKOUT_SRC_MUX(clkout->id), + LMK04832_BIT_CLKOUT_SRC_MUX, + FIELD_PREP(LMK04832_BIT_CLKOUT_SRC_MUX, + index)); +} + +static uint8_t lmk04832_clkout_get_parent(struct clk_hw *hw) +{ + struct lmk_clkout *clkout = container_of(hw, struct lmk_clkout, hw); + struct lmk04832 *lmk = clkout->lmk; + unsigned int tmp; + int ret; + + ret = regmap_read(lmk->regmap, LMK04832_REG_CLKOUT_SRC_MUX(clkout->id), + &tmp); + if (ret) + return ret; + + return FIELD_GET(LMK04832_BIT_CLKOUT_SRC_MUX, tmp); +} + +static const struct clk_ops lmk04832_clkout_ops = { + .is_enabled = lmk04832_clkout_is_enabled, + .prepare = lmk04832_clkout_prepare, + .unprepare = lmk04832_clkout_unprepare, + .set_parent = lmk04832_clkout_set_parent, + .get_parent = lmk04832_clkout_get_parent, +}; + +static int lmk04832_register_clkout(struct lmk04832 *lmk, const int num) +{ + char name[] = "lmk-clkoutXX"; + char dclk_name[] = "lmk-dclkXX_YY"; + const char *parent_names[2]; + struct clk_init_data init; + int dclk_num = num / 2; + int ret; + + if (num % 2 == 0) { + sprintf(dclk_name, "lmk-dclk%02d_%02d", num, num + 1); + init.name = dclk_name; + parent_names[0] = clk_hw_get_name(&lmk->vco); + init.ops = &lmk04832_dclk_ops; + init.flags = CLK_SET_RATE_PARENT; + init.num_parents = 1; + + lmk->dclk[dclk_num].id = num; + lmk->dclk[dclk_num].lmk = lmk; + lmk->dclk[dclk_num].hw.init = &init; + + ret = devm_clk_hw_register(lmk->dev, &lmk->dclk[dclk_num].hw); + if (ret) + return ret; + } else { + sprintf(dclk_name, "lmk-dclk%02d_%02d", num - 1, num); + } + + if (of_property_read_string_index(lmk->dev->of_node, + "clock-output-names", + num, &init.name)) { + sprintf(name, "lmk-clkout%02d", num); + init.name = name; + } + + parent_names[0] = dclk_name; + parent_names[1] = clk_hw_get_name(&lmk->sclk); + init.parent_names = parent_names; + init.ops = &lmk04832_clkout_ops; + init.flags = CLK_SET_RATE_PARENT | CLK_SET_RATE_NO_REPARENT; + init.num_parents = ARRAY_SIZE(parent_names); + + lmk->clkout[num].id = num; + lmk->clkout[num].lmk = lmk; + lmk->clkout[num].hw.init = &init; + lmk->clk_data->hws[num] = &lmk->clkout[num].hw; + + /* Set initial parent */ + regmap_update_bits(lmk->regmap, + LMK04832_REG_CLKOUT_SRC_MUX(num), + LMK04832_BIT_CLKOUT_SRC_MUX, + FIELD_PREP(LMK04832_BIT_CLKOUT_SRC_MUX, + lmk->clkout[num].sysref)); + + return devm_clk_hw_register(lmk->dev, &lmk->clkout[num].hw); +} + +static int lmk04832_set_spi_rdbk(const struct lmk04832 *lmk, const int rdbk_pin) +{ + int reg; + int ret; + + dev_info(lmk->dev, "setting up 4-wire mode\n"); + ret = regmap_write(lmk->regmap, LMK04832_REG_RST3W, + LMK04832_BIT_SPI_3WIRE_DIS); + if (ret) + return ret; + + switch (rdbk_pin) { + case RDBK_CLKIN_SEL0: + reg = LMK04832_REG_CLKIN_SEL0; + break; + case RDBK_CLKIN_SEL1: + reg = LMK04832_REG_CLKIN_SEL1; + break; + case RDBK_RESET: + reg = LMK04832_REG_CLKIN_RST; + break; + default: + return -EINVAL; + } + + return regmap_write(lmk->regmap, reg, + FIELD_PREP(LMK04832_BIT_CLKIN_SEL_MUX, + LMK04832_VAL_CLKIN_SEL_MUX_SPI_RDBK) | + FIELD_PREP(LMK04832_BIT_CLKIN_SEL_TYPE, + LMK04832_VAL_CLKIN_SEL_TYPE_OUT)); +} + +static int lmk04832_probe(struct spi_device *spi) +{ + const struct lmk04832_device_info *info; + int rdbk_pin = RDBK_CLKIN_SEL1; + struct device_node *child; + struct lmk04832 *lmk; + u8 tmp[3]; + int ret; + int i; + + info = &lmk04832_device_info[spi_get_device_id(spi)->driver_data]; + + lmk = devm_kzalloc(&spi->dev, sizeof(struct lmk04832), GFP_KERNEL); + if (!lmk) + return -ENOMEM; + + lmk->dev = &spi->dev; + + lmk->oscin = devm_clk_get(lmk->dev, "oscin"); + if (IS_ERR(lmk->oscin)) { + dev_err(lmk->dev, "failed to get oscin clock\n"); + return PTR_ERR(lmk->oscin); + } + + ret = clk_prepare_enable(lmk->oscin); + if (ret) + return ret; + + lmk->reset_gpio = devm_gpiod_get_optional(&spi->dev, "reset", + GPIOD_OUT_LOW); + + lmk->dclk = devm_kcalloc(lmk->dev, info->num_channels >> 1, + sizeof(struct lmk_dclk), GFP_KERNEL); + if (IS_ERR(lmk->dclk)) { + ret = PTR_ERR(lmk->dclk); + goto err_disable_oscin; + } + + lmk->clkout = devm_kcalloc(lmk->dev, info->num_channels, + sizeof(*lmk->clkout), GFP_KERNEL); + if (IS_ERR(lmk->clkout)) { + ret = PTR_ERR(lmk->clkout); + goto err_disable_oscin; + } + + lmk->clk_data = devm_kzalloc(lmk->dev, struct_size(lmk->clk_data, hws, + info->num_channels), + GFP_KERNEL); + if (IS_ERR(lmk->clk_data)) { + ret = PTR_ERR(lmk->clk_data); + goto err_disable_oscin; + } + + device_property_read_u32(lmk->dev, "ti,vco-hz", &lmk->vco_rate); + + lmk->sysref_ddly = 8; + device_property_read_u32(lmk->dev, "ti,sysref-ddly", &lmk->sysref_ddly); + + lmk->sysref_mux = LMK04832_VAL_SYSREF_MUX_CONTINUOUS; + device_property_read_u32(lmk->dev, "ti,sysref-mux", + &lmk->sysref_mux); + + lmk->sync_mode = LMK04832_VAL_SYNC_MODE_OFF; + device_property_read_u32(lmk->dev, "ti,sync-mode", + &lmk->sync_mode); + + lmk->sysref_pulse_cnt = 4; + device_property_read_u32(lmk->dev, "ti,sysref-pulse-count", + &lmk->sysref_pulse_cnt); + + for_each_child_of_node(lmk->dev->of_node, child) { + int reg; + + ret = of_property_read_u32(child, "reg", ®); + if (ret) { + dev_err(lmk->dev, "missing reg property in child: %s\n", + child->full_name); + of_node_put(child); + goto err_disable_oscin; + } + + of_property_read_u32(child, "ti,clkout-fmt", + &lmk->clkout[reg].format); + + if (lmk->clkout[reg].format >= 0x0a && reg % 2 == 0 + && reg != 8 && reg != 10) + dev_err(lmk->dev, "invalid format for clkout%02d\n", + reg); + + lmk->clkout[reg].sysref = + of_property_read_bool(child, "ti,clkout-sysref"); + } + + lmk->regmap = devm_regmap_init_spi(spi, ®map_config); + if (IS_ERR(lmk->regmap)) { + dev_err(lmk->dev, "%s: regmap allocation failed: %ld\n", + + __func__, PTR_ERR(lmk->regmap)); + ret = PTR_ERR(lmk->regmap); + goto err_disable_oscin; + } + + regmap_write(lmk->regmap, LMK04832_REG_RST3W, LMK04832_BIT_RESET); + + if (!(spi->mode & SPI_3WIRE)) { + device_property_read_u32(lmk->dev, "ti,spi-4wire-rdbk", + &rdbk_pin); + ret = lmk04832_set_spi_rdbk(lmk, rdbk_pin); + if (ret) + goto err_disable_oscin; + } + + regmap_bulk_read(lmk->regmap, LMK04832_REG_ID_PROD_MSB, &tmp, 3); + if ((tmp[0] << 8 | tmp[1]) != info->pid || tmp[2] != info->maskrev) { + dev_err(lmk->dev, "unsupported device type: pid 0x%04x, maskrev 0x%02x\n", + tmp[0] << 8 | tmp[1], tmp[2]); + ret = -EINVAL; + goto err_disable_oscin; + } + + ret = lmk04832_register_vco(lmk); + if (ret) { + dev_err(lmk->dev, "failed to init device clock path\n"); + goto err_disable_oscin; + } + + if (lmk->vco_rate) { + dev_info(lmk->dev, "setting VCO rate to %u Hz\n", lmk->vco_rate); + ret = clk_set_rate(lmk->vco.clk, lmk->vco_rate); + if (ret) { + dev_err(lmk->dev, "failed to set VCO rate\n"); + goto err_disable_vco; + } + } + + ret = lmk04832_register_sclk(lmk); + if (ret) { + dev_err(lmk->dev, "failed to init SYNC/SYSREF clock path\n"); + goto err_disable_vco; + } + + for (i = 0; i < info->num_channels; i++) { + ret = lmk04832_register_clkout(lmk, i); + if (ret) { + dev_err(lmk->dev, "failed to register clk %d\n", i); + goto err_disable_vco; + } + } + + lmk->clk_data->num = info->num_channels; + ret = of_clk_add_hw_provider(lmk->dev->of_node, of_clk_hw_onecell_get, + lmk->clk_data); + if (ret) { + dev_err(lmk->dev, "failed to add provider (%d)\n", ret); + goto err_disable_vco; + } + + spi_set_drvdata(spi, lmk); + + return 0; + +err_disable_vco: + clk_disable_unprepare(lmk->vco.clk); + +err_disable_oscin: + clk_disable_unprepare(lmk->oscin); + + return ret; +} + +static int lmk04832_remove(struct spi_device *spi) +{ + struct lmk04832 *lmk = spi_get_drvdata(spi); + + clk_disable_unprepare(lmk->oscin); + of_clk_del_provider(spi->dev.of_node); + + return 0; +} +static const struct spi_device_id lmk04832_id[] = { + { "lmk04832", LMK04832 }, + {} +}; +MODULE_DEVICE_TABLE(spi, lmk04832_id); + +static const struct of_device_id lmk04832_of_id[] = { + { .compatible = "ti,lmk04832" }, + {} +}; +MODULE_DEVICE_TABLE(of, lmk04832_of_id); + +static struct spi_driver lmk04832_driver = { + .driver = { + .name = "lmk04832", + .of_match_table = lmk04832_of_id, + }, + .probe = lmk04832_probe, + .remove = lmk04832_remove, + .id_table = lmk04832_id, +}; +module_spi_driver(lmk04832_driver); + +MODULE_AUTHOR("Liam Beguin <lvb@xiphos.com>"); +MODULE_DESCRIPTION("Texas Instruments LMK04832"); +MODULE_LICENSE("GPL v2"); diff --git a/drivers/clk/clk-si5341.c b/drivers/clk/clk-si5341.c index e0446e66fa64..57ae183982d8 100644 --- a/drivers/clk/clk-si5341.c +++ b/drivers/clk/clk-si5341.c @@ -19,6 +19,7 @@ #include <linux/i2c.h> #include <linux/module.h> #include <linux/regmap.h> +#include <linux/regulator/consumer.h> #include <linux/slab.h> #include <asm/unaligned.h> @@ -59,6 +60,7 @@ struct clk_si5341_synth { struct clk_si5341_output { struct clk_hw hw; struct clk_si5341 *data; + struct regulator *vddo_reg; u8 index; }; #define to_clk_si5341_output(_hw) \ @@ -78,12 +80,15 @@ struct clk_si5341 { u8 num_outputs; u8 num_synth; u16 chip_id; + bool xaxb_ext_clk; + bool iovdd_33; }; #define to_clk_si5341(_hw) container_of(_hw, struct clk_si5341, hw) struct clk_si5341_output_config { u8 out_format_drv_bits; u8 out_cm_ampl_bits; + u8 vdd_sel_bits; bool synth_master; bool always_on; }; @@ -92,12 +97,23 @@ struct clk_si5341_output_config { #define SI5341_PN_BASE 0x0002 #define SI5341_DEVICE_REV 0x0005 #define SI5341_STATUS 0x000C +#define SI5341_LOS 0x000D +#define SI5341_STATUS_STICKY 0x0011 +#define SI5341_LOS_STICKY 0x0012 #define SI5341_SOFT_RST 0x001C #define SI5341_IN_SEL 0x0021 +#define SI5341_DEVICE_READY 0x00FE #define SI5341_XAXB_CFG 0x090E +#define SI5341_IO_VDD_SEL 0x0943 #define SI5341_IN_EN 0x0949 #define SI5341_INX_TO_PFD_EN 0x094A +/* Status bits */ +#define SI5341_STATUS_SYSINCAL BIT(0) +#define SI5341_STATUS_LOSXAXB BIT(1) +#define SI5341_STATUS_LOSREF BIT(2) +#define SI5341_STATUS_LOL BIT(3) + /* Input selection */ #define SI5341_IN_SEL_MASK 0x06 #define SI5341_IN_SEL_SHIFT 1 @@ -126,6 +142,8 @@ struct clk_si5341_output_config { #define SI5341_OUT_R_REG(output) \ ((output)->data->reg_rdiv_offset[(output)->index]) +#define SI5341_OUT_MUX_VDD_SEL_MASK 0x38 + /* Synthesize N divider */ #define SI5341_SYNTH_N_NUM(x) (0x0302 + ((x) * 11)) #define SI5341_SYNTH_N_DEN(x) (0x0308 + ((x) * 11)) @@ -335,11 +353,12 @@ static const struct si5341_reg_default si5341_reg_defaults[] = { { 0x0804, 0x00 }, /* Not in datasheet */ { 0x090E, 0x02 }, /* XAXB_EXTCLK_EN=0 XAXB_PDNB=1 (use XTAL) */ { 0x091C, 0x04 }, /* ZDM_EN=4 (Normal mode) */ - { 0x0943, 0x00 }, /* IO_VDD_SEL=0 (0=1v8, use 1=3v3) */ { 0x0949, 0x00 }, /* IN_EN (disable input clocks) */ { 0x094A, 0x00 }, /* INx_TO_PFD_EN (disabled) */ { 0x0A02, 0x00 }, /* Not in datasheet */ { 0x0B44, 0x0F }, /* PDIV_ENB (datasheet does not mention what it is) */ + { 0x0B57, 0x10 }, /* VCO_RESET_CALCODE (not described in datasheet) */ + { 0x0B58, 0x05 }, /* VCO_RESET_CALCODE (not described in datasheet) */ }; /* Read and interpret a 44-bit followed by a 32-bit value in the regmap */ @@ -512,9 +531,11 @@ static int si5341_clk_reparent(struct clk_si5341 *data, u8 index) if (err < 0) return err; - /* Power up XTAL oscillator and buffer */ + /* Power up XTAL oscillator and buffer, select clock mode */ err = regmap_update_bits(data->regmap, SI5341_XAXB_CFG, - SI5341_XAXB_CFG_PDNB, SI5341_XAXB_CFG_PDNB); + SI5341_XAXB_CFG_PDNB | SI5341_XAXB_CFG_EXTCLK_EN, + SI5341_XAXB_CFG_PDNB | (data->xaxb_ext_clk ? + SI5341_XAXB_CFG_EXTCLK_EN : 0)); if (err < 0) return err; } @@ -623,6 +644,9 @@ static unsigned long si5341_synth_clk_recalc_rate(struct clk_hw *hw, SI5341_SYNTH_N_NUM(synth->index), &n_num, &n_den); if (err < 0) return err; + /* Check for bogus/uninitialized settings */ + if (!n_num || !n_den) + return 0; /* * n_num and n_den are shifted left as much as possible, so to prevent @@ -806,6 +830,9 @@ static long si5341_output_clk_round_rate(struct clk_hw *hw, unsigned long rate, { unsigned long r; + if (!rate) + return 0; + r = *parent_rate >> 1; /* If rate is an even divisor, no changes to parent required */ @@ -834,11 +861,16 @@ static int si5341_output_clk_set_rate(struct clk_hw *hw, unsigned long rate, unsigned long parent_rate) { struct clk_si5341_output *output = to_clk_si5341_output(hw); - /* Frequency divider is (r_div + 1) * 2 */ - u32 r_div = (parent_rate / rate) >> 1; + u32 r_div; int err; u8 r[3]; + if (!rate) + return -EINVAL; + + /* Frequency divider is (r_div + 1) * 2 */ + r_div = (parent_rate / rate) >> 1; + if (r_div <= 1) r_div = 0; else if (r_div >= BIT(24)) @@ -1083,7 +1115,7 @@ static const struct si5341_reg_default si5341_preamble[] = { { 0x0B25, 0x00 }, { 0x0502, 0x01 }, { 0x0505, 0x03 }, - { 0x0957, 0x1F }, + { 0x0957, 0x17 }, { 0x0B4E, 0x1A }, }; @@ -1129,6 +1161,11 @@ static int si5341_finalize_defaults(struct clk_si5341 *data) int res; u32 revision; + res = regmap_write(data->regmap, SI5341_IO_VDD_SEL, + data->iovdd_33 ? 1 : 0); + if (res < 0) + return res; + res = regmap_read(data->regmap, SI5341_DEVICE_REV, &revision); if (res < 0) return res; @@ -1189,6 +1226,32 @@ static const struct regmap_range_cfg si5341_regmap_ranges[] = { }, }; +static int si5341_wait_device_ready(struct i2c_client *client) +{ + int count; + + /* Datasheet warns: Any attempt to read or write any register other + * than DEVICE_READY before DEVICE_READY reads as 0x0F may corrupt the + * NVM programming and may corrupt the register contents, as they are + * read from NVM. Note that this includes accesses to the PAGE register. + * Also: DEVICE_READY is available on every register page, so no page + * change is needed to read it. + * Do this outside regmap to avoid automatic PAGE register access. + * May take up to 300ms to complete. + */ + for (count = 0; count < 15; ++count) { + s32 result = i2c_smbus_read_byte_data(client, + SI5341_DEVICE_READY); + if (result < 0) + return result; + if (result == 0x0F) + return 0; + msleep(20); + } + dev_err(&client->dev, "timeout waiting for DEVICE_READY\n"); + return -EIO; +} + static const struct regmap_config si5341_regmap_config = { .reg_bits = 8, .val_bits = 8, @@ -1199,11 +1262,11 @@ static const struct regmap_config si5341_regmap_config = { .volatile_table = &si5341_regmap_volatile, }; -static int si5341_dt_parse_dt(struct i2c_client *client, - struct clk_si5341_output_config *config) +static int si5341_dt_parse_dt(struct clk_si5341 *data, + struct clk_si5341_output_config *config) { struct device_node *child; - struct device_node *np = client->dev.of_node; + struct device_node *np = data->i2c_client->dev.of_node; u32 num; u32 val; @@ -1212,13 +1275,13 @@ static int si5341_dt_parse_dt(struct i2c_client *client, for_each_child_of_node(np, child) { if (of_property_read_u32(child, "reg", &num)) { - dev_err(&client->dev, "missing reg property of %s\n", + dev_err(&data->i2c_client->dev, "missing reg property of %s\n", child->name); goto put_child; } if (num >= SI5341_MAX_NUM_OUTPUTS) { - dev_err(&client->dev, "invalid clkout %d\n", num); + dev_err(&data->i2c_client->dev, "invalid clkout %d\n", num); goto put_child; } @@ -1237,7 +1300,7 @@ static int si5341_dt_parse_dt(struct i2c_client *client, config[num].out_format_drv_bits |= 0xc0; break; default: - dev_err(&client->dev, + dev_err(&data->i2c_client->dev, "invalid silabs,format %u for %u\n", val, num); goto put_child; @@ -1250,7 +1313,7 @@ static int si5341_dt_parse_dt(struct i2c_client *client, if (!of_property_read_u32(child, "silabs,common-mode", &val)) { if (val > 0xf) { - dev_err(&client->dev, + dev_err(&data->i2c_client->dev, "invalid silabs,common-mode %u\n", val); goto put_child; @@ -1261,7 +1324,7 @@ static int si5341_dt_parse_dt(struct i2c_client *client, if (!of_property_read_u32(child, "silabs,amplitude", &val)) { if (val > 0xf) { - dev_err(&client->dev, + dev_err(&data->i2c_client->dev, "invalid silabs,amplitude %u\n", val); goto put_child; @@ -1278,6 +1341,34 @@ static int si5341_dt_parse_dt(struct i2c_client *client, config[num].always_on = of_property_read_bool(child, "always-on"); + + config[num].vdd_sel_bits = 0x08; + if (data->clk[num].vddo_reg) { + int vdd = regulator_get_voltage(data->clk[num].vddo_reg); + + switch (vdd) { + case 3300000: + config[num].vdd_sel_bits |= 0 << 4; + break; + case 1800000: + config[num].vdd_sel_bits |= 1 << 4; + break; + case 2500000: + config[num].vdd_sel_bits |= 2 << 4; + break; + default: + dev_err(&data->i2c_client->dev, + "unsupported vddo voltage %d for %s\n", + vdd, child->name); + goto put_child; + } + } else { + /* chip seems to default to 2.5V when not set */ + dev_warn(&data->i2c_client->dev, + "no regulator set, defaulting vdd_sel to 2.5V for %s\n", + child->name); + config[num].vdd_sel_bits |= 2 << 4; + } } return 0; @@ -1366,6 +1457,94 @@ static int si5341_clk_select_active_input(struct clk_si5341 *data) return res; } +static ssize_t input_present_show(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + struct clk_si5341 *data = dev_get_drvdata(dev); + u32 status; + int res = regmap_read(data->regmap, SI5341_STATUS, &status); + + if (res < 0) + return res; + res = !(status & SI5341_STATUS_LOSREF); + return snprintf(buf, PAGE_SIZE, "%d\n", res); +} +static DEVICE_ATTR_RO(input_present); + +static ssize_t input_present_sticky_show(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + struct clk_si5341 *data = dev_get_drvdata(dev); + u32 status; + int res = regmap_read(data->regmap, SI5341_STATUS_STICKY, &status); + + if (res < 0) + return res; + res = !(status & SI5341_STATUS_LOSREF); + return snprintf(buf, PAGE_SIZE, "%d\n", res); +} +static DEVICE_ATTR_RO(input_present_sticky); + +static ssize_t pll_locked_show(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + struct clk_si5341 *data = dev_get_drvdata(dev); + u32 status; + int res = regmap_read(data->regmap, SI5341_STATUS, &status); + + if (res < 0) + return res; + res = !(status & SI5341_STATUS_LOL); + return snprintf(buf, PAGE_SIZE, "%d\n", res); +} +static DEVICE_ATTR_RO(pll_locked); + +static ssize_t pll_locked_sticky_show(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + struct clk_si5341 *data = dev_get_drvdata(dev); + u32 status; + int res = regmap_read(data->regmap, SI5341_STATUS_STICKY, &status); + + if (res < 0) + return res; + res = !(status & SI5341_STATUS_LOL); + return snprintf(buf, PAGE_SIZE, "%d\n", res); +} +static DEVICE_ATTR_RO(pll_locked_sticky); + +static ssize_t clear_sticky_store(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t count) +{ + struct clk_si5341 *data = dev_get_drvdata(dev); + long val; + + if (kstrtol(buf, 10, &val)) + return -EINVAL; + if (val) { + int res = regmap_write(data->regmap, SI5341_STATUS_STICKY, 0); + + if (res < 0) + return res; + } + return count; +} +static DEVICE_ATTR_WO(clear_sticky); + +static const struct attribute *si5341_attributes[] = { + &dev_attr_input_present.attr, + &dev_attr_input_present_sticky.attr, + &dev_attr_pll_locked.attr, + &dev_attr_pll_locked_sticky.attr, + &dev_attr_clear_sticky.attr, + NULL +}; + static int si5341_probe(struct i2c_client *client, const struct i2c_device_id *id) { @@ -1378,6 +1557,7 @@ static int si5341_probe(struct i2c_client *client, unsigned int i; struct clk_si5341_output_config config[SI5341_MAX_NUM_OUTPUTS]; bool initialization_required; + u32 status; data = devm_kzalloc(&client->dev, sizeof(*data), GFP_KERNEL); if (!data) @@ -1385,6 +1565,11 @@ static int si5341_probe(struct i2c_client *client, data->i2c_client = client; + /* Must be done before otherwise touching hardware */ + err = si5341_wait_device_ready(client); + if (err) + return err; + for (i = 0; i < SI5341_NUM_INPUTS; ++i) { input = devm_clk_get(&client->dev, si5341_input_clock_names[i]); if (IS_ERR(input)) { @@ -1397,9 +1582,33 @@ static int si5341_probe(struct i2c_client *client, } } - err = si5341_dt_parse_dt(client, config); + for (i = 0; i < SI5341_MAX_NUM_OUTPUTS; ++i) { + char reg_name[10]; + + snprintf(reg_name, sizeof(reg_name), "vddo%d", i); + data->clk[i].vddo_reg = devm_regulator_get_optional( + &client->dev, reg_name); + if (IS_ERR(data->clk[i].vddo_reg)) { + err = PTR_ERR(data->clk[i].vddo_reg); + data->clk[i].vddo_reg = NULL; + if (err == -ENODEV) + continue; + goto cleanup; + } else { + err = regulator_enable(data->clk[i].vddo_reg); + if (err) { + dev_err(&client->dev, + "failed to enable %s regulator: %d\n", + reg_name, err); + data->clk[i].vddo_reg = NULL; + goto cleanup; + } + } + } + + err = si5341_dt_parse_dt(data, config); if (err) - return err; + goto cleanup; if (of_property_read_string(client->dev.of_node, "clock-output-names", &init.name)) @@ -1407,34 +1616,40 @@ static int si5341_probe(struct i2c_client *client, root_clock_name = init.name; data->regmap = devm_regmap_init_i2c(client, &si5341_regmap_config); - if (IS_ERR(data->regmap)) - return PTR_ERR(data->regmap); + if (IS_ERR(data->regmap)) { + err = PTR_ERR(data->regmap); + goto cleanup; + } i2c_set_clientdata(client, data); err = si5341_probe_chip_id(data); if (err < 0) - return err; + goto cleanup; if (of_property_read_bool(client->dev.of_node, "silabs,reprogram")) { initialization_required = true; } else { err = si5341_is_programmed_already(data); if (err < 0) - return err; + goto cleanup; initialization_required = !err; } + data->xaxb_ext_clk = of_property_read_bool(client->dev.of_node, + "silabs,xaxb-ext-clk"); + data->iovdd_33 = of_property_read_bool(client->dev.of_node, + "silabs,iovdd-33"); if (initialization_required) { /* Populate the regmap cache in preparation for "cache only" */ err = si5341_read_settings(data); if (err < 0) - return err; + goto cleanup; err = si5341_send_preamble(data); if (err < 0) - return err; + goto cleanup; /* * We intend to send all 'final' register values in a single @@ -1447,19 +1662,19 @@ static int si5341_probe(struct i2c_client *client, err = si5341_write_multiple(data, si5341_reg_defaults, ARRAY_SIZE(si5341_reg_defaults)); if (err < 0) - return err; + goto cleanup; } /* Input must be up and running at this point */ err = si5341_clk_select_active_input(data); if (err < 0) - return err; + goto cleanup; if (initialization_required) { /* PLL configuration is required */ err = si5341_initialize_pll(data); if (err < 0) - return err; + goto cleanup; } /* Register the PLL */ @@ -1472,7 +1687,7 @@ static int si5341_probe(struct i2c_client *client, err = devm_clk_hw_register(&client->dev, &data->hw); if (err) { dev_err(&client->dev, "clock registration failed\n"); - return err; + goto cleanup; } init.num_parents = 1; @@ -1509,13 +1724,17 @@ static int si5341_probe(struct i2c_client *client, regmap_write(data->regmap, SI5341_OUT_CM(&data->clk[i]), config[i].out_cm_ampl_bits); + regmap_update_bits(data->regmap, + SI5341_OUT_MUX_SEL(&data->clk[i]), + SI5341_OUT_MUX_VDD_SEL_MASK, + config[i].vdd_sel_bits); } err = devm_clk_hw_register(&client->dev, &data->clk[i].hw); kfree(init.name); /* clock framework made a copy of the name */ if (err) { dev_err(&client->dev, "output %u registration failed\n", i); - return err; + goto cleanup; } if (config[i].always_on) clk_prepare(data->clk[i].hw.clk); @@ -1525,7 +1744,7 @@ static int si5341_probe(struct i2c_client *client, data); if (err) { dev_err(&client->dev, "unable to add clk provider\n"); - return err; + goto cleanup; } if (initialization_required) { @@ -1533,11 +1752,33 @@ static int si5341_probe(struct i2c_client *client, regcache_cache_only(data->regmap, false); err = regcache_sync(data->regmap); if (err < 0) - return err; + goto cleanup; err = si5341_finalize_defaults(data); if (err < 0) - return err; + goto cleanup; + } + + /* wait for device to report input clock present and PLL lock */ + err = regmap_read_poll_timeout(data->regmap, SI5341_STATUS, status, + !(status & (SI5341_STATUS_LOSREF | SI5341_STATUS_LOL)), + 10000, 250000); + if (err) { + dev_err(&client->dev, "Error waiting for input clock or PLL lock\n"); + goto cleanup; + } + + /* clear sticky alarm bits from initialization */ + err = regmap_write(data->regmap, SI5341_STATUS_STICKY, 0); + if (err) { + dev_err(&client->dev, "unable to clear sticky status\n"); + goto cleanup; + } + + err = sysfs_create_files(&client->dev.kobj, si5341_attributes); + if (err) { + dev_err(&client->dev, "unable to create sysfs files\n"); + goto cleanup; } /* Free the names, clk framework makes copies */ @@ -1545,6 +1786,28 @@ static int si5341_probe(struct i2c_client *client, devm_kfree(&client->dev, (void *)synth_clock_names[i]); return 0; + +cleanup: + for (i = 0; i < SI5341_MAX_NUM_OUTPUTS; ++i) { + if (data->clk[i].vddo_reg) + regulator_disable(data->clk[i].vddo_reg); + } + return err; +} + +static int si5341_remove(struct i2c_client *client) +{ + struct clk_si5341 *data = i2c_get_clientdata(client); + int i; + + sysfs_remove_files(&client->dev.kobj, si5341_attributes); + + for (i = 0; i < SI5341_MAX_NUM_OUTPUTS; ++i) { + if (data->clk[i].vddo_reg) + regulator_disable(data->clk[i].vddo_reg); + } + + return 0; } static const struct i2c_device_id si5341_id[] = { @@ -1573,6 +1836,7 @@ static struct i2c_driver si5341_driver = { .of_match_table = clk_si5341_of_match, }, .probe = si5341_probe, + .remove = si5341_remove, .id_table = si5341_id, }; module_i2c_driver(si5341_driver); diff --git a/drivers/clk/clk-stm32mp1.c b/drivers/clk/clk-stm32mp1.c index a875649df8b8..6adc625e79cb 100644 --- a/drivers/clk/clk-stm32mp1.c +++ b/drivers/clk/clk-stm32mp1.c @@ -10,8 +10,11 @@ #include <linux/delay.h> #include <linux/err.h> #include <linux/io.h> +#include <linux/module.h> #include <linux/of.h> #include <linux/of_address.h> +#include <linux/platform_device.h> +#include <linux/reset-controller.h> #include <linux/slab.h> #include <linux/spinlock.h> @@ -245,7 +248,7 @@ static const char * const dsi_src[] = { }; static const char * const rtc_src[] = { - "off", "ck_lse", "ck_lsi", "ck_hse_rtc" + "off", "ck_lse", "ck_lsi", "ck_hse" }; static const char * const mco1_src[] = { @@ -469,7 +472,7 @@ static const struct clk_ops mp1_gate_clk_ops = { .is_enabled = clk_gate_is_enabled, }; -static struct clk_hw *_get_stm32_mux(void __iomem *base, +static struct clk_hw *_get_stm32_mux(struct device *dev, void __iomem *base, const struct stm32_mux_cfg *cfg, spinlock_t *lock) { @@ -478,7 +481,7 @@ static struct clk_hw *_get_stm32_mux(void __iomem *base, struct clk_hw *mux_hw; if (cfg->mmux) { - mmux = kzalloc(sizeof(*mmux), GFP_KERNEL); + mmux = devm_kzalloc(dev, sizeof(*mmux), GFP_KERNEL); if (!mmux) return ERR_PTR(-ENOMEM); @@ -493,7 +496,7 @@ static struct clk_hw *_get_stm32_mux(void __iomem *base, cfg->mmux->hws[cfg->mmux->nbr_clk++] = mux_hw; } else { - mux = kzalloc(sizeof(*mux), GFP_KERNEL); + mux = devm_kzalloc(dev, sizeof(*mux), GFP_KERNEL); if (!mux) return ERR_PTR(-ENOMEM); @@ -509,13 +512,13 @@ static struct clk_hw *_get_stm32_mux(void __iomem *base, return mux_hw; } -static struct clk_hw *_get_stm32_div(void __iomem *base, +static struct clk_hw *_get_stm32_div(struct device *dev, void __iomem *base, const struct stm32_div_cfg *cfg, spinlock_t *lock) { struct clk_divider *div; - div = kzalloc(sizeof(*div), GFP_KERNEL); + div = devm_kzalloc(dev, sizeof(*div), GFP_KERNEL); if (!div) return ERR_PTR(-ENOMEM); @@ -530,16 +533,16 @@ static struct clk_hw *_get_stm32_div(void __iomem *base, return &div->hw; } -static struct clk_hw * -_get_stm32_gate(void __iomem *base, - const struct stm32_gate_cfg *cfg, spinlock_t *lock) +static struct clk_hw *_get_stm32_gate(struct device *dev, void __iomem *base, + const struct stm32_gate_cfg *cfg, + spinlock_t *lock) { struct stm32_clk_mgate *mgate; struct clk_gate *gate; struct clk_hw *gate_hw; if (cfg->mgate) { - mgate = kzalloc(sizeof(*mgate), GFP_KERNEL); + mgate = devm_kzalloc(dev, sizeof(*mgate), GFP_KERNEL); if (!mgate) return ERR_PTR(-ENOMEM); @@ -554,7 +557,7 @@ _get_stm32_gate(void __iomem *base, gate_hw = &mgate->gate.hw; } else { - gate = kzalloc(sizeof(*gate), GFP_KERNEL); + gate = devm_kzalloc(dev, sizeof(*gate), GFP_KERNEL); if (!gate) return ERR_PTR(-ENOMEM); @@ -592,7 +595,7 @@ clk_stm32_register_gate_ops(struct device *dev, if (cfg->ops) init.ops = cfg->ops; - hw = _get_stm32_gate(base, cfg, lock); + hw = _get_stm32_gate(dev, base, cfg, lock); if (IS_ERR(hw)) return ERR_PTR(-ENOMEM); @@ -623,7 +626,7 @@ clk_stm32_register_composite(struct device *dev, gate_ops = NULL; if (cfg->mux) { - mux_hw = _get_stm32_mux(base, cfg->mux, lock); + mux_hw = _get_stm32_mux(dev, base, cfg->mux, lock); if (!IS_ERR(mux_hw)) { mux_ops = &clk_mux_ops; @@ -634,7 +637,7 @@ clk_stm32_register_composite(struct device *dev, } if (cfg->div) { - div_hw = _get_stm32_div(base, cfg->div, lock); + div_hw = _get_stm32_div(dev, base, cfg->div, lock); if (!IS_ERR(div_hw)) { div_ops = &clk_divider_ops; @@ -645,7 +648,7 @@ clk_stm32_register_composite(struct device *dev, } if (cfg->gate) { - gate_hw = _get_stm32_gate(base, cfg->gate, lock); + gate_hw = _get_stm32_gate(dev, base, cfg->gate, lock); if (!IS_ERR(gate_hw)) { gate_ops = &clk_gate_ops; @@ -731,6 +734,7 @@ struct stm32_pll_obj { spinlock_t *lock; void __iomem *reg; struct clk_hw hw; + struct clk_mux mux; }; #define to_pll(_hw) container_of(_hw, struct stm32_pll_obj, hw) @@ -745,6 +749,8 @@ struct stm32_pll_obj { #define FRAC_MASK 0x1FFF #define FRAC_SHIFT 3 #define FRACLE BIT(16) +#define PLL_MUX_SHIFT 0 +#define PLL_MUX_MASK 3 static int __pll_is_enabled(struct clk_hw *hw) { @@ -856,16 +862,29 @@ static int pll_is_enabled(struct clk_hw *hw) return ret; } +static u8 pll_get_parent(struct clk_hw *hw) +{ + struct stm32_pll_obj *clk_elem = to_pll(hw); + struct clk_hw *mux_hw = &clk_elem->mux.hw; + + __clk_hw_set_clk(mux_hw, hw); + + return clk_mux_ops.get_parent(mux_hw); +} + static const struct clk_ops pll_ops = { .enable = pll_enable, .disable = pll_disable, .recalc_rate = pll_recalc_rate, .is_enabled = pll_is_enabled, + .get_parent = pll_get_parent, }; static struct clk_hw *clk_register_pll(struct device *dev, const char *name, - const char *parent_name, + const char * const *parent_names, + int num_parents, void __iomem *reg, + void __iomem *mux_reg, unsigned long flags, spinlock_t *lock) { @@ -874,15 +893,22 @@ static struct clk_hw *clk_register_pll(struct device *dev, const char *name, struct clk_hw *hw; int err; - element = kzalloc(sizeof(*element), GFP_KERNEL); + element = devm_kzalloc(dev, sizeof(*element), GFP_KERNEL); if (!element) return ERR_PTR(-ENOMEM); init.name = name; init.ops = &pll_ops; init.flags = flags; - init.parent_names = &parent_name; - init.num_parents = 1; + init.parent_names = parent_names; + init.num_parents = num_parents; + + element->mux.lock = lock; + element->mux.reg = mux_reg; + element->mux.shift = PLL_MUX_SHIFT; + element->mux.mask = PLL_MUX_MASK; + element->mux.flags = CLK_MUX_READ_ONLY; + element->mux.reg = mux_reg; element->hw.init = &init; element->reg = reg; @@ -891,10 +917,8 @@ static struct clk_hw *clk_register_pll(struct device *dev, const char *name, hw = &element->hw; err = clk_hw_register(dev, hw); - if (err) { - kfree(element); + if (err) return ERR_PTR(err); - } return hw; } @@ -1005,7 +1029,7 @@ static struct clk_hw *clk_register_cktim(struct device *dev, const char *name, struct clk_hw *hw; int err; - tim_ker = kzalloc(sizeof(*tim_ker), GFP_KERNEL); + tim_ker = devm_kzalloc(dev, sizeof(*tim_ker), GFP_KERNEL); if (!tim_ker) return ERR_PTR(-ENOMEM); @@ -1023,16 +1047,56 @@ static struct clk_hw *clk_register_cktim(struct device *dev, const char *name, hw = &tim_ker->hw; err = clk_hw_register(dev, hw); - if (err) { - kfree(tim_ker); + if (err) return ERR_PTR(err); - } return hw; } +/* The divider of RTC clock concerns only ck_hse clock */ +#define HSE_RTC 3 + +static unsigned long clk_divider_rtc_recalc_rate(struct clk_hw *hw, + unsigned long parent_rate) +{ + if (clk_hw_get_parent(hw) == clk_hw_get_parent_by_index(hw, HSE_RTC)) + return clk_divider_ops.recalc_rate(hw, parent_rate); + + return parent_rate; +} + +static int clk_divider_rtc_set_rate(struct clk_hw *hw, unsigned long rate, + unsigned long parent_rate) +{ + if (clk_hw_get_parent(hw) == clk_hw_get_parent_by_index(hw, HSE_RTC)) + return clk_divider_ops.set_rate(hw, rate, parent_rate); + + return parent_rate; +} + +static int clk_divider_rtc_determine_rate(struct clk_hw *hw, struct clk_rate_request *req) +{ + unsigned long best_parent_rate = req->best_parent_rate; + + if (req->best_parent_hw == clk_hw_get_parent_by_index(hw, HSE_RTC)) { + req->rate = clk_divider_ops.round_rate(hw, req->rate, &best_parent_rate); + req->best_parent_rate = best_parent_rate; + } else { + req->rate = best_parent_rate; + } + + return 0; +} + +static const struct clk_ops rtc_div_clk_ops = { + .recalc_rate = clk_divider_rtc_recalc_rate, + .set_rate = clk_divider_rtc_set_rate, + .determine_rate = clk_divider_rtc_determine_rate +}; + struct stm32_pll_cfg { u32 offset; + u32 muxoff; }; static struct clk_hw *_clk_register_pll(struct device *dev, @@ -1042,8 +1106,11 @@ static struct clk_hw *_clk_register_pll(struct device *dev, { struct stm32_pll_cfg *stm_pll_cfg = cfg->cfg; - return clk_register_pll(dev, cfg->name, cfg->parent_name, - base + stm_pll_cfg->offset, cfg->flags, lock); + return clk_register_pll(dev, cfg->name, cfg->parent_names, + cfg->num_parents, + base + stm_pll_cfg->offset, + base + stm_pll_cfg->muxoff, + cfg->flags, lock); } struct stm32_cktim_cfg { @@ -1153,14 +1220,16 @@ _clk_stm32_register_composite(struct device *dev, .func = _clk_hw_register_mux,\ } -#define PLL(_id, _name, _parent, _flags, _offset)\ +#define PLL(_id, _name, _parents, _flags, _offset_p, _offset_mux)\ {\ .id = _id,\ .name = _name,\ - .parent_name = _parent,\ - .flags = _flags,\ + .parent_names = _parents,\ + .num_parents = ARRAY_SIZE(_parents),\ + .flags = CLK_IGNORE_UNUSED | (_flags),\ .cfg = &(struct stm32_pll_cfg) {\ - .offset = _offset,\ + .offset = _offset_p,\ + .muxoff = _offset_mux,\ },\ .func = _clk_register_pll,\ } @@ -1243,6 +1312,10 @@ _clk_stm32_register_composite(struct device *dev, _STM32_DIV(_div_offset, _div_shift, _div_width,\ _div_flags, _div_table, NULL)\ +#define _DIV_RTC(_div_offset, _div_shift, _div_width, _div_flags, _div_table)\ + _STM32_DIV(_div_offset, _div_shift, _div_width,\ + _div_flags, _div_table, &rtc_div_clk_ops) + #define _STM32_MUX(_offset, _shift, _width, _mux_flags, _mmux, _ops)\ .mux = &(struct stm32_mux_cfg) {\ &(struct mux_cfg) {\ @@ -1657,36 +1730,26 @@ static const struct stm32_mux_cfg ker_mux_cfg[M_LAST] = { }; static const struct clock_config stm32mp1_clock_cfg[] = { - /* Oscillator divider */ - DIV(NO_ID, "clk-hsi-div", "clk-hsi", CLK_DIVIDER_POWER_OF_TWO, - RCC_HSICFGR, 0, 2, CLK_DIVIDER_READ_ONLY), - /* External / Internal Oscillators */ GATE_MP1(CK_HSE, "ck_hse", "clk-hse", 0, RCC_OCENSETR, 8, 0), /* ck_csi is used by IO compensation and should be critical */ GATE_MP1(CK_CSI, "ck_csi", "clk-csi", CLK_IS_CRITICAL, RCC_OCENSETR, 4, 0), - GATE_MP1(CK_HSI, "ck_hsi", "clk-hsi-div", 0, RCC_OCENSETR, 0, 0), + COMPOSITE(CK_HSI, "ck_hsi", PARENT("clk-hsi"), 0, + _GATE_MP1(RCC_OCENSETR, 0, 0), + _NO_MUX, + _DIV(RCC_HSICFGR, 0, 2, CLK_DIVIDER_POWER_OF_TWO | + CLK_DIVIDER_READ_ONLY, NULL)), GATE(CK_LSI, "ck_lsi", "clk-lsi", 0, RCC_RDLSICR, 0, 0), GATE(CK_LSE, "ck_lse", "clk-lse", 0, RCC_BDCR, 0, 0), FIXED_FACTOR(CK_HSE_DIV2, "clk-hse-div2", "ck_hse", 0, 1, 2), - /* ref clock pll */ - MUX(NO_ID, "ref1", ref12_parents, CLK_OPS_PARENT_ENABLE, RCC_RCK12SELR, - 0, 2, CLK_MUX_READ_ONLY), - - MUX(NO_ID, "ref3", ref3_parents, CLK_OPS_PARENT_ENABLE, RCC_RCK3SELR, - 0, 2, CLK_MUX_READ_ONLY), - - MUX(NO_ID, "ref4", ref4_parents, CLK_OPS_PARENT_ENABLE, RCC_RCK4SELR, - 0, 2, CLK_MUX_READ_ONLY), - /* PLLs */ - PLL(PLL1, "pll1", "ref1", CLK_IGNORE_UNUSED, RCC_PLL1CR), - PLL(PLL2, "pll2", "ref1", CLK_IGNORE_UNUSED, RCC_PLL2CR), - PLL(PLL3, "pll3", "ref3", CLK_IGNORE_UNUSED, RCC_PLL3CR), - PLL(PLL4, "pll4", "ref4", CLK_IGNORE_UNUSED, RCC_PLL4CR), + PLL(PLL1, "pll1", ref12_parents, 0, RCC_PLL1CR, RCC_RCK12SELR), + PLL(PLL2, "pll2", ref12_parents, 0, RCC_PLL2CR, RCC_RCK12SELR), + PLL(PLL3, "pll3", ref3_parents, 0, RCC_PLL3CR, RCC_RCK3SELR), + PLL(PLL4, "pll4", ref4_parents, 0, RCC_PLL4CR, RCC_RCK4SELR), /* ODF */ COMPOSITE(PLL1_P, "pll1_p", PARENT("pll1"), 0, @@ -1965,13 +2028,10 @@ static const struct clock_config stm32mp1_clock_cfg[] = { _DIV(RCC_ETHCKSELR, 4, 4, 0, NULL)), /* RTC clock */ - DIV(NO_ID, "ck_hse_rtc", "ck_hse", 0, RCC_RTCDIVR, 0, 6, 0), - - COMPOSITE(RTC, "ck_rtc", rtc_src, CLK_OPS_PARENT_ENABLE | - CLK_SET_RATE_PARENT, + COMPOSITE(RTC, "ck_rtc", rtc_src, CLK_OPS_PARENT_ENABLE, _GATE(RCC_BDCR, 20, 0), _MUX(RCC_BDCR, 16, 2, 0), - _NO_DIV), + _DIV_RTC(RCC_RTCDIVR, 0, 6, 0, NULL)), /* MCO clocks */ COMPOSITE(CK_MCO1, "ck_mco1", mco1_src, CLK_OPS_PARENT_ENABLE | @@ -1996,16 +2056,76 @@ static const struct clock_config stm32mp1_clock_cfg[] = { _DIV(RCC_DBGCFGR, 0, 3, 0, ck_trace_div_table)), }; -struct stm32_clock_match_data { +static const u32 stm32mp1_clock_secured[] = { + CK_HSE, + CK_HSI, + CK_CSI, + CK_LSI, + CK_LSE, + PLL1, + PLL2, + PLL1_P, + PLL2_P, + PLL2_Q, + PLL2_R, + CK_MPU, + CK_AXI, + SPI6, + I2C4, + I2C6, + USART1, + RTCAPB, + TZC1, + TZC2, + TZPC, + IWDG1, + BSEC, + STGEN, + GPIOZ, + CRYP1, + HASH1, + RNG1, + BKPSRAM, + RNG1_K, + STGEN_K, + SPI6_K, + I2C4_K, + I2C6_K, + USART1_K, + RTC, +}; + +static bool stm32_check_security(const struct clock_config *cfg) +{ + int i; + + for (i = 0; i < ARRAY_SIZE(stm32mp1_clock_secured); i++) + if (cfg->id == stm32mp1_clock_secured[i]) + return true; + return false; +} + +struct stm32_rcc_match_data { const struct clock_config *cfg; unsigned int num; unsigned int maxbinding; + u32 clear_offset; + bool (*check_security)(const struct clock_config *cfg); }; -static struct stm32_clock_match_data stm32mp1_data = { +static struct stm32_rcc_match_data stm32mp1_data = { .cfg = stm32mp1_clock_cfg, .num = ARRAY_SIZE(stm32mp1_clock_cfg), .maxbinding = STM32MP1_LAST_CLK, + .clear_offset = RCC_CLR, +}; + +static struct stm32_rcc_match_data stm32mp1_data_secure = { + .cfg = stm32mp1_clock_cfg, + .num = ARRAY_SIZE(stm32mp1_clock_cfg), + .maxbinding = STM32MP1_LAST_CLK, + .clear_offset = RCC_CLR, + .check_security = &stm32_check_security }; static const struct of_device_id stm32mp1_match_data[] = { @@ -2013,8 +2133,13 @@ static const struct of_device_id stm32mp1_match_data[] = { .compatible = "st,stm32mp1-rcc", .data = &stm32mp1_data, }, + { + .compatible = "st,stm32mp1-rcc-secure", + .data = &stm32mp1_data_secure, + }, { } }; +MODULE_DEVICE_TABLE(of, stm32mp1_match_data); static int stm32_register_hw_clk(struct device *dev, struct clk_hw_onecell_data *clk_data, @@ -2040,28 +2165,126 @@ static int stm32_register_hw_clk(struct device *dev, return 0; } -static int stm32_rcc_init(struct device_node *np, - void __iomem *base, - const struct of_device_id *match_data) +#define STM32_RESET_ID_MASK GENMASK(15, 0) + +struct stm32_reset_data { + /* reset lock */ + spinlock_t lock; + struct reset_controller_dev rcdev; + void __iomem *membase; + u32 clear_offset; +}; + +static inline struct stm32_reset_data * +to_stm32_reset_data(struct reset_controller_dev *rcdev) { - struct clk_hw_onecell_data *clk_data; - struct clk_hw **hws; - const struct of_device_id *match; - const struct stm32_clock_match_data *data; - int err, n, max_binding; + return container_of(rcdev, struct stm32_reset_data, rcdev); +} - match = of_match_node(match_data, np); - if (!match) { - pr_err("%s: match data not found\n", __func__); - return -ENODEV; +static int stm32_reset_update(struct reset_controller_dev *rcdev, + unsigned long id, bool assert) +{ + struct stm32_reset_data *data = to_stm32_reset_data(rcdev); + int reg_width = sizeof(u32); + int bank = id / (reg_width * BITS_PER_BYTE); + int offset = id % (reg_width * BITS_PER_BYTE); + + if (data->clear_offset) { + void __iomem *addr; + + addr = data->membase + (bank * reg_width); + if (!assert) + addr += data->clear_offset; + + writel(BIT(offset), addr); + + } else { + unsigned long flags; + u32 reg; + + spin_lock_irqsave(&data->lock, flags); + + reg = readl(data->membase + (bank * reg_width)); + + if (assert) + reg |= BIT(offset); + else + reg &= ~BIT(offset); + + writel(reg, data->membase + (bank * reg_width)); + + spin_unlock_irqrestore(&data->lock, flags); } + return 0; +} + +static int stm32_reset_assert(struct reset_controller_dev *rcdev, + unsigned long id) +{ + return stm32_reset_update(rcdev, id, true); +} + +static int stm32_reset_deassert(struct reset_controller_dev *rcdev, + unsigned long id) +{ + return stm32_reset_update(rcdev, id, false); +} + +static int stm32_reset_status(struct reset_controller_dev *rcdev, + unsigned long id) +{ + struct stm32_reset_data *data = to_stm32_reset_data(rcdev); + int reg_width = sizeof(u32); + int bank = id / (reg_width * BITS_PER_BYTE); + int offset = id % (reg_width * BITS_PER_BYTE); + u32 reg; + + reg = readl(data->membase + (bank * reg_width)); + + return !!(reg & BIT(offset)); +} + +static const struct reset_control_ops stm32_reset_ops = { + .assert = stm32_reset_assert, + .deassert = stm32_reset_deassert, + .status = stm32_reset_status, +}; + +static int stm32_rcc_reset_init(struct device *dev, void __iomem *base, + const struct of_device_id *match) +{ + const struct stm32_rcc_match_data *data = match->data; + struct stm32_reset_data *reset_data = NULL; + data = match->data; + reset_data = kzalloc(sizeof(*reset_data), GFP_KERNEL); + if (!reset_data) + return -ENOMEM; + + reset_data->membase = base; + reset_data->rcdev.owner = THIS_MODULE; + reset_data->rcdev.ops = &stm32_reset_ops; + reset_data->rcdev.of_node = dev_of_node(dev); + reset_data->rcdev.nr_resets = STM32_RESET_ID_MASK; + reset_data->clear_offset = data->clear_offset; + + return reset_controller_register(&reset_data->rcdev); +} + +static int stm32_rcc_clock_init(struct device *dev, void __iomem *base, + const struct of_device_id *match) +{ + const struct stm32_rcc_match_data *data = match->data; + struct clk_hw_onecell_data *clk_data; + struct clk_hw **hws; + int err, n, max_binding; + max_binding = data->maxbinding; - clk_data = kzalloc(struct_size(clk_data, hws, max_binding), - GFP_KERNEL); + clk_data = devm_kzalloc(dev, struct_size(clk_data, hws, max_binding), + GFP_KERNEL); if (!clk_data) return -ENOMEM; @@ -2073,36 +2296,139 @@ static int stm32_rcc_init(struct device_node *np, hws[n] = ERR_PTR(-ENOENT); for (n = 0; n < data->num; n++) { - err = stm32_register_hw_clk(NULL, clk_data, base, &rlock, + if (data->check_security && data->check_security(&data->cfg[n])) + continue; + + err = stm32_register_hw_clk(dev, clk_data, base, &rlock, &data->cfg[n]); if (err) { - pr_err("%s: can't register %s\n", __func__, - data->cfg[n].name); - - kfree(clk_data); + dev_err(dev, "Can't register clk %s: %d\n", + data->cfg[n].name, err); return err; } } - return of_clk_add_hw_provider(np, of_clk_hw_onecell_get, clk_data); + return of_clk_add_hw_provider(dev_of_node(dev), of_clk_hw_onecell_get, clk_data); } -static void stm32mp1_rcc_init(struct device_node *np) +static int stm32_rcc_init(struct device *dev, void __iomem *base, + const struct of_device_id *match_data) +{ + const struct of_device_id *match; + int err; + + match = of_match_node(match_data, dev_of_node(dev)); + if (!match) { + dev_err(dev, "match data not found\n"); + return -ENODEV; + } + + /* RCC Reset Configuration */ + err = stm32_rcc_reset_init(dev, base, match); + if (err) { + pr_err("stm32mp1 reset failed to initialize\n"); + return err; + } + + /* RCC Clock Configuration */ + err = stm32_rcc_clock_init(dev, base, match); + if (err) { + pr_err("stm32mp1 clock failed to initialize\n"); + return err; + } + + return 0; +} + +static int stm32mp1_rcc_init(struct device *dev) { void __iomem *base; + int ret; - base = of_iomap(np, 0); + base = of_iomap(dev_of_node(dev), 0); if (!base) { - pr_err("%pOFn: unable to map resource", np); - of_node_put(np); - return; + pr_err("%pOFn: unable to map resource", dev_of_node(dev)); + ret = -ENOMEM; + goto out; } - if (stm32_rcc_init(np, base, stm32mp1_match_data)) { - iounmap(base); - of_node_put(np); + ret = stm32_rcc_init(dev, base, stm32mp1_match_data); + +out: + if (ret) { + if (base) + iounmap(base); + + of_node_put(dev_of_node(dev)); } + + return ret; } -CLK_OF_DECLARE_DRIVER(stm32mp1_rcc, "st,stm32mp1-rcc", stm32mp1_rcc_init); +static int get_clock_deps(struct device *dev) +{ + static const char * const clock_deps_name[] = { + "hsi", "hse", "csi", "lsi", "lse", + }; + size_t deps_size = sizeof(struct clk *) * ARRAY_SIZE(clock_deps_name); + struct clk **clk_deps; + int i; + + clk_deps = devm_kzalloc(dev, deps_size, GFP_KERNEL); + if (!clk_deps) + return -ENOMEM; + + for (i = 0; i < ARRAY_SIZE(clock_deps_name); i++) { + struct clk *clk = of_clk_get_by_name(dev_of_node(dev), + clock_deps_name[i]); + + if (IS_ERR(clk)) { + if (PTR_ERR(clk) != -EINVAL && PTR_ERR(clk) != -ENOENT) + return PTR_ERR(clk); + } else { + /* Device gets a reference count on the clock */ + clk_deps[i] = devm_clk_get(dev, __clk_get_name(clk)); + clk_put(clk); + } + } + + return 0; +} + +static int stm32mp1_rcc_clocks_probe(struct platform_device *pdev) +{ + struct device *dev = &pdev->dev; + int ret = get_clock_deps(dev); + + if (!ret) + ret = stm32mp1_rcc_init(dev); + + return ret; +} + +static int stm32mp1_rcc_clocks_remove(struct platform_device *pdev) +{ + struct device *dev = &pdev->dev; + struct device_node *child, *np = dev_of_node(dev); + + for_each_available_child_of_node(np, child) + of_clk_del_provider(child); + + return 0; +} + +static struct platform_driver stm32mp1_rcc_clocks_driver = { + .driver = { + .name = "stm32mp1_rcc", + .of_match_table = stm32mp1_match_data, + }, + .probe = stm32mp1_rcc_clocks_probe, + .remove = stm32mp1_rcc_clocks_remove, +}; + +static int __init stm32mp1_clocks_init(void) +{ + return platform_driver_register(&stm32mp1_rcc_clocks_driver); +} +core_initcall(stm32mp1_clocks_init); diff --git a/drivers/clk/clk-versaclock5.c b/drivers/clk/clk-versaclock5.c index 344cd6c61188..3c737742c2a9 100644 --- a/drivers/clk/clk-versaclock5.c +++ b/drivers/clk/clk-versaclock5.c @@ -69,7 +69,10 @@ #define VC5_FEEDBACK_FRAC_DIV(n) (0x19 + (n)) #define VC5_RC_CONTROL0 0x1e #define VC5_RC_CONTROL1 0x1f -/* Register 0x20 is factory reserved */ + +/* These registers are named "Unused Factory Reserved Registers" */ +#define VC5_RESERVED_X0(idx) (0x20 + ((idx) * 0x10)) +#define VC5_RESERVED_X0_BYPASS_SYNC BIT(7) /* bypass_sync<idx> bit */ /* Output divider control for divider 1,2,3,4 */ #define VC5_OUT_DIV_CONTROL(idx) (0x21 + ((idx) * 0x10)) @@ -87,7 +90,6 @@ #define VC5_OUT_DIV_SKEW_INT(idx, n) (0x2b + ((idx) * 0x10) + (n)) #define VC5_OUT_DIV_INT(idx, n) (0x2d + ((idx) * 0x10) + (n)) #define VC5_OUT_DIV_SKEW_FRAC(idx) (0x2f + ((idx) * 0x10)) -/* Registers 0x30, 0x40, 0x50 are factory reserved */ /* Clock control register for clock 1,2 */ #define VC5_CLK_OUTPUT_CFG(idx, n) (0x60 + ((idx) * 0x2) + (n)) @@ -140,6 +142,8 @@ #define VC5_HAS_INTERNAL_XTAL BIT(0) /* chip has PFD requency doubler */ #define VC5_HAS_PFD_FREQ_DBL BIT(1) +/* chip has bits to disable FOD sync */ +#define VC5_HAS_BYPASS_SYNC_BIT BIT(2) /* Supported IDT VC5 models. */ enum vc5_model { @@ -582,6 +586,23 @@ static int vc5_clk_out_prepare(struct clk_hw *hw) int ret; /* + * When enabling a FOD, all currently enabled FODs are briefly + * stopped in order to synchronize all of them. This causes a clock + * disruption to any unrelated chips that might be already using + * other clock outputs. Bypass the sync feature to avoid the issue, + * which is possible on the VersaClock 6E family via reserved + * registers. + */ + if (vc5->chip_info->flags & VC5_HAS_BYPASS_SYNC_BIT) { + ret = regmap_update_bits(vc5->regmap, + VC5_RESERVED_X0(hwdata->num), + VC5_RESERVED_X0_BYPASS_SYNC, + VC5_RESERVED_X0_BYPASS_SYNC); + if (ret) + return ret; + } + + /* * If the input mux is disabled, enable it first and * select source from matching FOD. */ @@ -1166,7 +1187,7 @@ static const struct vc5_chip_info idt_5p49v6965_info = { .model = IDT_VC6_5P49V6965, .clk_fod_cnt = 4, .clk_out_cnt = 5, - .flags = 0, + .flags = VC5_HAS_BYPASS_SYNC_BIT, }; static const struct i2c_device_id vc5_id[] = { diff --git a/drivers/clk/clkdev.c b/drivers/clk/clkdev.c index 0f2e3fcf0f19..67f601a41023 100644 --- a/drivers/clk/clkdev.c +++ b/drivers/clk/clkdev.c @@ -190,34 +190,6 @@ vclkdev_create(struct clk_hw *hw, const char *con_id, const char *dev_fmt, return cl; } -struct clk_lookup * __ref -clkdev_alloc(struct clk *clk, const char *con_id, const char *dev_fmt, ...) -{ - struct clk_lookup *cl; - va_list ap; - - va_start(ap, dev_fmt); - cl = vclkdev_alloc(__clk_get_hw(clk), con_id, dev_fmt, ap); - va_end(ap); - - return cl; -} -EXPORT_SYMBOL(clkdev_alloc); - -struct clk_lookup * -clkdev_hw_alloc(struct clk_hw *hw, const char *con_id, const char *dev_fmt, ...) -{ - struct clk_lookup *cl; - va_list ap; - - va_start(ap, dev_fmt); - cl = vclkdev_alloc(hw, con_id, dev_fmt, ap); - va_end(ap); - - return cl; -} -EXPORT_SYMBOL(clkdev_hw_alloc); - /** * clkdev_create - allocate and add a clkdev lookup structure * @clk: struct clk to associate with all clk_lookups diff --git a/drivers/clk/hisilicon/Kconfig b/drivers/clk/hisilicon/Kconfig index 6a9e93a0bb95..5ecc37aaa118 100644 --- a/drivers/clk/hisilicon/Kconfig +++ b/drivers/clk/hisilicon/Kconfig @@ -15,6 +15,13 @@ config COMMON_CLK_HI3519 help Build the clock driver for hi3519. +config COMMON_CLK_HI3559A + bool "Hi3559A Clock Driver" + depends on ARCH_HISI || COMPILE_TEST + default ARCH_HISI + help + Build the clock driver for hi3559a. + config COMMON_CLK_HI3660 bool "Hi3660 Clock Driver" depends on ARCH_HISI || COMPILE_TEST diff --git a/drivers/clk/hisilicon/Makefile b/drivers/clk/hisilicon/Makefile index b2441b99f3d5..2978e56cb876 100644 --- a/drivers/clk/hisilicon/Makefile +++ b/drivers/clk/hisilicon/Makefile @@ -10,6 +10,7 @@ obj-$(CONFIG_ARCH_HIP04) += clk-hip04.o obj-$(CONFIG_ARCH_HIX5HD2) += clk-hix5hd2.o obj-$(CONFIG_COMMON_CLK_HI3516CV300) += crg-hi3516cv300.o obj-$(CONFIG_COMMON_CLK_HI3519) += clk-hi3519.o +obj-$(CONFIG_COMMON_CLK_HI3559A) += clk-hi3559a.o obj-$(CONFIG_COMMON_CLK_HI3660) += clk-hi3660.o obj-$(CONFIG_COMMON_CLK_HI3670) += clk-hi3670.o obj-$(CONFIG_COMMON_CLK_HI3798CV200) += crg-hi3798cv200.o diff --git a/drivers/clk/hisilicon/clk-hi3559a.c b/drivers/clk/hisilicon/clk-hi3559a.c new file mode 100644 index 000000000000..b1f19c43b558 --- /dev/null +++ b/drivers/clk/hisilicon/clk-hi3559a.c @@ -0,0 +1,846 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Hisilicon Hi3559A clock driver + * + * Copyright (c) 2019-2020, Huawei Tech. Co., Ltd. + * + * Author: Dongjiu Geng <gengdongjiu@huawei.com> + */ + +#include <linux/clk-provider.h> +#include <linux/module.h> +#include <linux/of_device.h> +#include <linux/platform_device.h> +#include <linux/slab.h> + +#include <dt-bindings/clock/hi3559av100-clock.h> + +#include "clk.h" +#include "crg.h" +#include "reset.h" + +#define CRG_BASE_ADDR 0x18020000 +#define PLL_MASK_WIDTH 24 + +struct hi3559av100_pll_clock { + u32 id; + const char *name; + const char *parent_name; + const u32 ctrl_reg1; + const u8 frac_shift; + const u8 frac_width; + const u8 postdiv1_shift; + const u8 postdiv1_width; + const u8 postdiv2_shift; + const u8 postdiv2_width; + const u32 ctrl_reg2; + const u8 fbdiv_shift; + const u8 fbdiv_width; + const u8 refdiv_shift; + const u8 refdiv_width; +}; + +struct hi3559av100_clk_pll { + struct clk_hw hw; + u32 id; + void __iomem *ctrl_reg1; + u8 frac_shift; + u8 frac_width; + u8 postdiv1_shift; + u8 postdiv1_width; + u8 postdiv2_shift; + u8 postdiv2_width; + void __iomem *ctrl_reg2; + u8 fbdiv_shift; + u8 fbdiv_width; + u8 refdiv_shift; + u8 refdiv_width; +}; + +/* soc clk config */ +static const struct hisi_fixed_rate_clock hi3559av100_fixed_rate_clks_crg[] = { + { HI3559AV100_FIXED_1188M, "1188m", NULL, 0, 1188000000, }, + { HI3559AV100_FIXED_1000M, "1000m", NULL, 0, 1000000000, }, + { HI3559AV100_FIXED_842M, "842m", NULL, 0, 842000000, }, + { HI3559AV100_FIXED_792M, "792m", NULL, 0, 792000000, }, + { HI3559AV100_FIXED_750M, "750m", NULL, 0, 750000000, }, + { HI3559AV100_FIXED_710M, "710m", NULL, 0, 710000000, }, + { HI3559AV100_FIXED_680M, "680m", NULL, 0, 680000000, }, + { HI3559AV100_FIXED_667M, "667m", NULL, 0, 667000000, }, + { HI3559AV100_FIXED_631M, "631m", NULL, 0, 631000000, }, + { HI3559AV100_FIXED_600M, "600m", NULL, 0, 600000000, }, + { HI3559AV100_FIXED_568M, "568m", NULL, 0, 568000000, }, + { HI3559AV100_FIXED_500M, "500m", NULL, 0, 500000000, }, + { HI3559AV100_FIXED_475M, "475m", NULL, 0, 475000000, }, + { HI3559AV100_FIXED_428M, "428m", NULL, 0, 428000000, }, + { HI3559AV100_FIXED_400M, "400m", NULL, 0, 400000000, }, + { HI3559AV100_FIXED_396M, "396m", NULL, 0, 396000000, }, + { HI3559AV100_FIXED_300M, "300m", NULL, 0, 300000000, }, + { HI3559AV100_FIXED_250M, "250m", NULL, 0, 250000000, }, + { HI3559AV100_FIXED_200M, "200m", NULL, 0, 200000000, }, + { HI3559AV100_FIXED_198M, "198m", NULL, 0, 198000000, }, + { HI3559AV100_FIXED_187p5M, "187p5m", NULL, 0, 187500000, }, + { HI3559AV100_FIXED_150M, "150m", NULL, 0, 150000000, }, + { HI3559AV100_FIXED_148p5M, "148p5m", NULL, 0, 1485000000, }, + { HI3559AV100_FIXED_125M, "125m", NULL, 0, 125000000, }, + { HI3559AV100_FIXED_107M, "107m", NULL, 0, 107000000, }, + { HI3559AV100_FIXED_100M, "100m", NULL, 0, 100000000, }, + { HI3559AV100_FIXED_99M, "99m", NULL, 0, 99000000, }, + { HI3559AV100_FIXED_75M, "75m", NULL, 0, 75000000, }, + { HI3559AV100_FIXED_74p25M, "74p25m", NULL, 0, 74250000, }, + { HI3559AV100_FIXED_72M, "72m", NULL, 0, 72000000, }, + { HI3559AV100_FIXED_60M, "60m", NULL, 0, 60000000, }, + { HI3559AV100_FIXED_54M, "54m", NULL, 0, 54000000, }, + { HI3559AV100_FIXED_50M, "50m", NULL, 0, 50000000, }, + { HI3559AV100_FIXED_49p5M, "49p5m", NULL, 0, 49500000, }, + { HI3559AV100_FIXED_37p125M, "37p125m", NULL, 0, 37125000, }, + { HI3559AV100_FIXED_36M, "36m", NULL, 0, 36000000, }, + { HI3559AV100_FIXED_32p4M, "32p4m", NULL, 0, 32400000, }, + { HI3559AV100_FIXED_27M, "27m", NULL, 0, 27000000, }, + { HI3559AV100_FIXED_25M, "25m", NULL, 0, 25000000, }, + { HI3559AV100_FIXED_24M, "24m", NULL, 0, 24000000, }, + { HI3559AV100_FIXED_12M, "12m", NULL, 0, 12000000, }, + { HI3559AV100_FIXED_3M, "3m", NULL, 0, 3000000, }, + { HI3559AV100_FIXED_1p6M, "1p6m", NULL, 0, 1600000, }, + { HI3559AV100_FIXED_400K, "400k", NULL, 0, 400000, }, + { HI3559AV100_FIXED_100K, "100k", NULL, 0, 100000, }, +}; + + +static const char *fmc_mux_p[] __initconst = { + "24m", "75m", "125m", "150m", "200m", "250m", "300m", "400m" +}; + +static const char *mmc_mux_p[] __initconst = { + "100k", "25m", "49p5m", "99m", "187p5m", "150m", "198m", "400k" +}; + +static const char *sysapb_mux_p[] __initconst = { + "24m", "50m", +}; + +static const char *sysbus_mux_p[] __initconst = { + "24m", "300m" +}; + +static const char *uart_mux_p[] __initconst = { "50m", "24m", "3m" }; + +static const char *a73_clksel_mux_p[] __initconst = { + "24m", "apll", "1000m" +}; + +static const u32 fmc_mux_table[] = { 0, 1, 2, 3, 4, 5, 6, 7 }; +static const u32 mmc_mux_table[] = { 0, 1, 2, 3, 4, 5, 6, 7 }; +static const u32 sysapb_mux_table[] = { 0, 1 }; +static const u32 sysbus_mux_table[] = { 0, 1 }; +static const u32 uart_mux_table[] = { 0, 1, 2 }; +static const u32 a73_clksel_mux_table[] = { 0, 1, 2 }; + +static struct hisi_mux_clock hi3559av100_mux_clks_crg[] __initdata = { + { + HI3559AV100_FMC_MUX, "fmc_mux", fmc_mux_p, ARRAY_SIZE(fmc_mux_p), + CLK_SET_RATE_PARENT, 0x170, 2, 3, 0, fmc_mux_table, + }, + { + HI3559AV100_MMC0_MUX, "mmc0_mux", mmc_mux_p, ARRAY_SIZE(mmc_mux_p), + CLK_SET_RATE_PARENT, 0x1a8, 24, 3, 0, mmc_mux_table, + }, + { + HI3559AV100_MMC1_MUX, "mmc1_mux", mmc_mux_p, ARRAY_SIZE(mmc_mux_p), + CLK_SET_RATE_PARENT, 0x1ec, 24, 3, 0, mmc_mux_table, + }, + + { + HI3559AV100_MMC2_MUX, "mmc2_mux", mmc_mux_p, ARRAY_SIZE(mmc_mux_p), + CLK_SET_RATE_PARENT, 0x214, 24, 3, 0, mmc_mux_table, + }, + + { + HI3559AV100_MMC3_MUX, "mmc3_mux", mmc_mux_p, ARRAY_SIZE(mmc_mux_p), + CLK_SET_RATE_PARENT, 0x23c, 24, 3, 0, mmc_mux_table, + }, + + { + HI3559AV100_SYSAPB_MUX, "sysapb_mux", sysapb_mux_p, ARRAY_SIZE(sysapb_mux_p), + CLK_SET_RATE_PARENT, 0xe8, 3, 1, 0, sysapb_mux_table + }, + + { + HI3559AV100_SYSBUS_MUX, "sysbus_mux", sysbus_mux_p, ARRAY_SIZE(sysbus_mux_p), + CLK_SET_RATE_PARENT, 0xe8, 0, 1, 0, sysbus_mux_table + }, + + { + HI3559AV100_UART_MUX, "uart_mux", uart_mux_p, ARRAY_SIZE(uart_mux_p), + CLK_SET_RATE_PARENT, 0x198, 28, 2, 0, uart_mux_table + }, + + { + HI3559AV100_A73_MUX, "a73_mux", a73_clksel_mux_p, ARRAY_SIZE(a73_clksel_mux_p), + CLK_SET_RATE_PARENT, 0xe4, 0, 2, 0, a73_clksel_mux_table + }, +}; + +static struct hisi_gate_clock hi3559av100_gate_clks[] __initdata = { + { + HI3559AV100_FMC_CLK, "clk_fmc", "fmc_mux", + CLK_SET_RATE_PARENT, 0x170, 1, 0, + }, + { + HI3559AV100_MMC0_CLK, "clk_mmc0", "mmc0_mux", + CLK_SET_RATE_PARENT, 0x1a8, 28, 0, + }, + { + HI3559AV100_MMC1_CLK, "clk_mmc1", "mmc1_mux", + CLK_SET_RATE_PARENT, 0x1ec, 28, 0, + }, + { + HI3559AV100_MMC2_CLK, "clk_mmc2", "mmc2_mux", + CLK_SET_RATE_PARENT, 0x214, 28, 0, + }, + { + HI3559AV100_MMC3_CLK, "clk_mmc3", "mmc3_mux", + CLK_SET_RATE_PARENT, 0x23c, 28, 0, + }, + { + HI3559AV100_UART0_CLK, "clk_uart0", "uart_mux", + CLK_SET_RATE_PARENT, 0x198, 23, 0, + }, + { + HI3559AV100_UART1_CLK, "clk_uart1", "uart_mux", + CLK_SET_RATE_PARENT, 0x198, 24, 0, + }, + { + HI3559AV100_UART2_CLK, "clk_uart2", "uart_mux", + CLK_SET_RATE_PARENT, 0x198, 25, 0, + }, + { + HI3559AV100_UART3_CLK, "clk_uart3", "uart_mux", + CLK_SET_RATE_PARENT, 0x198, 26, 0, + }, + { + HI3559AV100_UART4_CLK, "clk_uart4", "uart_mux", + CLK_SET_RATE_PARENT, 0x198, 27, 0, + }, + { + HI3559AV100_ETH_CLK, "clk_eth", NULL, + CLK_SET_RATE_PARENT, 0x0174, 1, 0, + }, + { + HI3559AV100_ETH_MACIF_CLK, "clk_eth_macif", NULL, + CLK_SET_RATE_PARENT, 0x0174, 5, 0, + }, + { + HI3559AV100_ETH1_CLK, "clk_eth1", NULL, + CLK_SET_RATE_PARENT, 0x0174, 3, 0, + }, + { + HI3559AV100_ETH1_MACIF_CLK, "clk_eth1_macif", NULL, + CLK_SET_RATE_PARENT, 0x0174, 7, 0, + }, + { + HI3559AV100_I2C0_CLK, "clk_i2c0", "50m", + CLK_SET_RATE_PARENT, 0x01a0, 16, 0, + }, + { + HI3559AV100_I2C1_CLK, "clk_i2c1", "50m", + CLK_SET_RATE_PARENT, 0x01a0, 17, 0, + }, + { + HI3559AV100_I2C2_CLK, "clk_i2c2", "50m", + CLK_SET_RATE_PARENT, 0x01a0, 18, 0, + }, + { + HI3559AV100_I2C3_CLK, "clk_i2c3", "50m", + CLK_SET_RATE_PARENT, 0x01a0, 19, 0, + }, + { + HI3559AV100_I2C4_CLK, "clk_i2c4", "50m", + CLK_SET_RATE_PARENT, 0x01a0, 20, 0, + }, + { + HI3559AV100_I2C5_CLK, "clk_i2c5", "50m", + CLK_SET_RATE_PARENT, 0x01a0, 21, 0, + }, + { + HI3559AV100_I2C6_CLK, "clk_i2c6", "50m", + CLK_SET_RATE_PARENT, 0x01a0, 22, 0, + }, + { + HI3559AV100_I2C7_CLK, "clk_i2c7", "50m", + CLK_SET_RATE_PARENT, 0x01a0, 23, 0, + }, + { + HI3559AV100_I2C8_CLK, "clk_i2c8", "50m", + CLK_SET_RATE_PARENT, 0x01a0, 24, 0, + }, + { + HI3559AV100_I2C9_CLK, "clk_i2c9", "50m", + CLK_SET_RATE_PARENT, 0x01a0, 25, 0, + }, + { + HI3559AV100_I2C10_CLK, "clk_i2c10", "50m", + CLK_SET_RATE_PARENT, 0x01a0, 26, 0, + }, + { + HI3559AV100_I2C11_CLK, "clk_i2c11", "50m", + CLK_SET_RATE_PARENT, 0x01a0, 27, 0, + }, + { + HI3559AV100_SPI0_CLK, "clk_spi0", "100m", + CLK_SET_RATE_PARENT, 0x0198, 16, 0, + }, + { + HI3559AV100_SPI1_CLK, "clk_spi1", "100m", + CLK_SET_RATE_PARENT, 0x0198, 17, 0, + }, + { + HI3559AV100_SPI2_CLK, "clk_spi2", "100m", + CLK_SET_RATE_PARENT, 0x0198, 18, 0, + }, + { + HI3559AV100_SPI3_CLK, "clk_spi3", "100m", + CLK_SET_RATE_PARENT, 0x0198, 19, 0, + }, + { + HI3559AV100_SPI4_CLK, "clk_spi4", "100m", + CLK_SET_RATE_PARENT, 0x0198, 20, 0, + }, + { + HI3559AV100_SPI5_CLK, "clk_spi5", "100m", + CLK_SET_RATE_PARENT, 0x0198, 21, 0, + }, + { + HI3559AV100_SPI6_CLK, "clk_spi6", "100m", + CLK_SET_RATE_PARENT, 0x0198, 22, 0, + }, + { + HI3559AV100_EDMAC_AXICLK, "axi_clk_edmac", NULL, + CLK_SET_RATE_PARENT, 0x16c, 6, 0, + }, + { + HI3559AV100_EDMAC_CLK, "clk_edmac", NULL, + CLK_SET_RATE_PARENT, 0x16c, 5, 0, + }, + { + HI3559AV100_EDMAC1_AXICLK, "axi_clk_edmac1", NULL, + CLK_SET_RATE_PARENT, 0x16c, 9, 0, + }, + { + HI3559AV100_EDMAC1_CLK, "clk_edmac1", NULL, + CLK_SET_RATE_PARENT, 0x16c, 8, 0, + }, + { + HI3559AV100_VDMAC_CLK, "clk_vdmac", NULL, + CLK_SET_RATE_PARENT, 0x14c, 5, 0, + }, +}; + +static struct hi3559av100_pll_clock hi3559av100_pll_clks[] __initdata = { + { + HI3559AV100_APLL_CLK, "apll", NULL, 0x0, 0, 24, 24, 3, 28, 3, + 0x4, 0, 12, 12, 6 + }, + { + HI3559AV100_GPLL_CLK, "gpll", NULL, 0x20, 0, 24, 24, 3, 28, 3, + 0x24, 0, 12, 12, 6 + }, +}; + +#define to_pll_clk(_hw) container_of(_hw, struct hi3559av100_clk_pll, hw) +static void hi3559av100_calc_pll(u32 *frac_val, u32 *postdiv1_val, + u32 *postdiv2_val, + u32 *fbdiv_val, u32 *refdiv_val, u64 rate) +{ + u64 rem; + + *postdiv1_val = 2; + *postdiv2_val = 1; + + rate = rate * ((*postdiv1_val) * (*postdiv2_val)); + + *frac_val = 0; + rem = do_div(rate, 1000000); + rem = do_div(rate, PLL_MASK_WIDTH); + *fbdiv_val = rate; + *refdiv_val = 1; + rem = rem * (1 << PLL_MASK_WIDTH); + do_div(rem, PLL_MASK_WIDTH); + *frac_val = rem; +} + +static int clk_pll_set_rate(struct clk_hw *hw, + unsigned long rate, + unsigned long parent_rate) +{ + struct hi3559av100_clk_pll *clk = to_pll_clk(hw); + u32 frac_val, postdiv1_val, postdiv2_val, fbdiv_val, refdiv_val; + u32 val; + + postdiv1_val = postdiv2_val = 0; + + hi3559av100_calc_pll(&frac_val, &postdiv1_val, &postdiv2_val, + &fbdiv_val, &refdiv_val, (u64)rate); + + val = readl_relaxed(clk->ctrl_reg1); + val &= ~(((1 << clk->frac_width) - 1) << clk->frac_shift); + val &= ~(((1 << clk->postdiv1_width) - 1) << clk->postdiv1_shift); + val &= ~(((1 << clk->postdiv2_width) - 1) << clk->postdiv2_shift); + + val |= frac_val << clk->frac_shift; + val |= postdiv1_val << clk->postdiv1_shift; + val |= postdiv2_val << clk->postdiv2_shift; + writel_relaxed(val, clk->ctrl_reg1); + + val = readl_relaxed(clk->ctrl_reg2); + val &= ~(((1 << clk->fbdiv_width) - 1) << clk->fbdiv_shift); + val &= ~(((1 << clk->refdiv_width) - 1) << clk->refdiv_shift); + + val |= fbdiv_val << clk->fbdiv_shift; + val |= refdiv_val << clk->refdiv_shift; + writel_relaxed(val, clk->ctrl_reg2); + + return 0; +} + +static unsigned long clk_pll_recalc_rate(struct clk_hw *hw, + unsigned long parent_rate) +{ + struct hi3559av100_clk_pll *clk = to_pll_clk(hw); + u64 frac_val, fbdiv_val, refdiv_val; + u32 postdiv1_val, postdiv2_val; + u32 val; + u64 tmp, rate; + + val = readl_relaxed(clk->ctrl_reg1); + val = val >> clk->frac_shift; + val &= ((1 << clk->frac_width) - 1); + frac_val = val; + + val = readl_relaxed(clk->ctrl_reg1); + val = val >> clk->postdiv1_shift; + val &= ((1 << clk->postdiv1_width) - 1); + postdiv1_val = val; + + val = readl_relaxed(clk->ctrl_reg1); + val = val >> clk->postdiv2_shift; + val &= ((1 << clk->postdiv2_width) - 1); + postdiv2_val = val; + + val = readl_relaxed(clk->ctrl_reg2); + val = val >> clk->fbdiv_shift; + val &= ((1 << clk->fbdiv_width) - 1); + fbdiv_val = val; + + val = readl_relaxed(clk->ctrl_reg2); + val = val >> clk->refdiv_shift; + val &= ((1 << clk->refdiv_width) - 1); + refdiv_val = val; + + /* rate = 24000000 * (fbdiv + frac / (1<<24) ) / refdiv */ + rate = 0; + tmp = 24000000 * fbdiv_val + (24000000 * frac_val) / (1 << 24); + rate += tmp; + do_div(rate, refdiv_val); + do_div(rate, postdiv1_val * postdiv2_val); + + return rate; +} + +static const struct clk_ops hisi_clk_pll_ops = { + .set_rate = clk_pll_set_rate, + .recalc_rate = clk_pll_recalc_rate, +}; + +static void hisi_clk_register_pll(struct hi3559av100_pll_clock *clks, + int nums, struct hisi_clock_data *data, struct device *dev) +{ + void __iomem *base = data->base; + struct hi3559av100_clk_pll *p_clk = NULL; + struct clk *clk = NULL; + struct clk_init_data init; + int i; + + p_clk = devm_kzalloc(dev, sizeof(*p_clk) * nums, GFP_KERNEL); + + if (!p_clk) + return; + + for (i = 0; i < nums; i++) { + init.name = clks[i].name; + init.flags = 0; + init.parent_names = + (clks[i].parent_name ? &clks[i].parent_name : NULL); + init.num_parents = (clks[i].parent_name ? 1 : 0); + init.ops = &hisi_clk_pll_ops; + + p_clk->ctrl_reg1 = base + clks[i].ctrl_reg1; + p_clk->frac_shift = clks[i].frac_shift; + p_clk->frac_width = clks[i].frac_width; + p_clk->postdiv1_shift = clks[i].postdiv1_shift; + p_clk->postdiv1_width = clks[i].postdiv1_width; + p_clk->postdiv2_shift = clks[i].postdiv2_shift; + p_clk->postdiv2_width = clks[i].postdiv2_width; + + p_clk->ctrl_reg2 = base + clks[i].ctrl_reg2; + p_clk->fbdiv_shift = clks[i].fbdiv_shift; + p_clk->fbdiv_width = clks[i].fbdiv_width; + p_clk->refdiv_shift = clks[i].refdiv_shift; + p_clk->refdiv_width = clks[i].refdiv_width; + p_clk->hw.init = &init; + + clk = clk_register(NULL, &p_clk->hw); + if (IS_ERR(clk)) { + devm_kfree(dev, p_clk); + dev_err(dev, "%s: failed to register clock %s\n", + __func__, clks[i].name); + continue; + } + + data->clk_data.clks[clks[i].id] = clk; + p_clk++; + } +} + +static __init struct hisi_clock_data *hi3559av100_clk_register( + struct platform_device *pdev) +{ + struct hisi_clock_data *clk_data; + int ret; + + clk_data = hisi_clk_alloc(pdev, HI3559AV100_CRG_NR_CLKS); + if (!clk_data) + return ERR_PTR(-ENOMEM); + + ret = hisi_clk_register_fixed_rate(hi3559av100_fixed_rate_clks_crg, + ARRAY_SIZE(hi3559av100_fixed_rate_clks_crg), clk_data); + if (ret) + return ERR_PTR(ret); + + hisi_clk_register_pll(hi3559av100_pll_clks, + ARRAY_SIZE(hi3559av100_pll_clks), clk_data, &pdev->dev); + + ret = hisi_clk_register_mux(hi3559av100_mux_clks_crg, + ARRAY_SIZE(hi3559av100_mux_clks_crg), clk_data); + if (ret) + goto unregister_fixed_rate; + + ret = hisi_clk_register_gate(hi3559av100_gate_clks, + ARRAY_SIZE(hi3559av100_gate_clks), clk_data); + if (ret) + goto unregister_mux; + + ret = of_clk_add_provider(pdev->dev.of_node, + of_clk_src_onecell_get, &clk_data->clk_data); + if (ret) + goto unregister_gate; + + return clk_data; + +unregister_gate: + hisi_clk_unregister_gate(hi3559av100_gate_clks, + ARRAY_SIZE(hi3559av100_gate_clks), clk_data); +unregister_mux: + hisi_clk_unregister_mux(hi3559av100_mux_clks_crg, + ARRAY_SIZE(hi3559av100_mux_clks_crg), clk_data); +unregister_fixed_rate: + hisi_clk_unregister_fixed_rate(hi3559av100_fixed_rate_clks_crg, + ARRAY_SIZE(hi3559av100_fixed_rate_clks_crg), clk_data); + return ERR_PTR(ret); +} + +static __init void hi3559av100_clk_unregister(struct platform_device *pdev) +{ + struct hisi_crg_dev *crg = platform_get_drvdata(pdev); + + of_clk_del_provider(pdev->dev.of_node); + + hisi_clk_unregister_gate(hi3559av100_gate_clks, + ARRAY_SIZE(hi3559av100_gate_clks), crg->clk_data); + hisi_clk_unregister_mux(hi3559av100_mux_clks_crg, + ARRAY_SIZE(hi3559av100_mux_clks_crg), crg->clk_data); + hisi_clk_unregister_fixed_rate(hi3559av100_fixed_rate_clks_crg, + ARRAY_SIZE(hi3559av100_fixed_rate_clks_crg), crg->clk_data); +} + +static const struct hisi_crg_funcs hi3559av100_crg_funcs = { + .register_clks = hi3559av100_clk_register, + .unregister_clks = hi3559av100_clk_unregister, +}; + +static struct hisi_fixed_rate_clock hi3559av100_shub_fixed_rate_clks[] + __initdata = { + { HI3559AV100_SHUB_SOURCE_SOC_24M, "clk_source_24M", NULL, 0, 24000000UL, }, + { HI3559AV100_SHUB_SOURCE_SOC_200M, "clk_source_200M", NULL, 0, 200000000UL, }, + { HI3559AV100_SHUB_SOURCE_SOC_300M, "clk_source_300M", NULL, 0, 300000000UL, }, + { HI3559AV100_SHUB_SOURCE_PLL, "clk_source_PLL", NULL, 0, 192000000UL, }, + { HI3559AV100_SHUB_I2C0_CLK, "clk_shub_i2c0", NULL, 0, 48000000UL, }, + { HI3559AV100_SHUB_I2C1_CLK, "clk_shub_i2c1", NULL, 0, 48000000UL, }, + { HI3559AV100_SHUB_I2C2_CLK, "clk_shub_i2c2", NULL, 0, 48000000UL, }, + { HI3559AV100_SHUB_I2C3_CLK, "clk_shub_i2c3", NULL, 0, 48000000UL, }, + { HI3559AV100_SHUB_I2C4_CLK, "clk_shub_i2c4", NULL, 0, 48000000UL, }, + { HI3559AV100_SHUB_I2C5_CLK, "clk_shub_i2c5", NULL, 0, 48000000UL, }, + { HI3559AV100_SHUB_I2C6_CLK, "clk_shub_i2c6", NULL, 0, 48000000UL, }, + { HI3559AV100_SHUB_I2C7_CLK, "clk_shub_i2c7", NULL, 0, 48000000UL, }, + { HI3559AV100_SHUB_UART_CLK_32K, "clk_uart_32K", NULL, 0, 32000UL, }, +}; + +/* shub mux clk */ +static u32 shub_source_clk_mux_table[] = {0, 1, 2, 3}; +static const char *shub_source_clk_mux_p[] __initconst = { + "clk_source_24M", "clk_source_200M", "clk_source_300M", "clk_source_PLL" +}; + +static u32 shub_uart_source_clk_mux_table[] = {0, 1, 2, 3}; +static const char *shub_uart_source_clk_mux_p[] __initconst = { + "clk_uart_32K", "clk_uart_div_clk", "clk_uart_div_clk", "clk_source_24M" +}; + +static struct hisi_mux_clock hi3559av100_shub_mux_clks[] __initdata = { + { + HI3559AV100_SHUB_SOURCE_CLK, "shub_clk", shub_source_clk_mux_p, + ARRAY_SIZE(shub_source_clk_mux_p), + 0, 0x0, 0, 2, 0, shub_source_clk_mux_table, + }, + + { + HI3559AV100_SHUB_UART_SOURCE_CLK, "shub_uart_source_clk", + shub_uart_source_clk_mux_p, ARRAY_SIZE(shub_uart_source_clk_mux_p), + 0, 0x1c, 28, 2, 0, shub_uart_source_clk_mux_table, + }, +}; + + +/* shub div clk */ +static struct clk_div_table shub_spi_clk_table[] = {{0, 8}, {1, 4}, {2, 2}}; +static struct clk_div_table shub_uart_div_clk_table[] = {{1, 8}, {2, 4}}; + +static struct hisi_divider_clock hi3559av100_shub_div_clks[] __initdata = { + { HI3559AV100_SHUB_SPI_SOURCE_CLK, "clk_spi_clk", "shub_clk", 0, 0x20, 24, 2, + CLK_DIVIDER_ALLOW_ZERO, shub_spi_clk_table, + }, + { HI3559AV100_SHUB_UART_DIV_CLK, "clk_uart_div_clk", "shub_clk", 0, 0x1c, 28, 2, + CLK_DIVIDER_ALLOW_ZERO, shub_uart_div_clk_table, + }, +}; + +/* shub gate clk */ +static struct hisi_gate_clock hi3559av100_shub_gate_clks[] __initdata = { + { + HI3559AV100_SHUB_SPI0_CLK, "clk_shub_spi0", "clk_spi_clk", + 0, 0x20, 1, 0, + }, + { + HI3559AV100_SHUB_SPI1_CLK, "clk_shub_spi1", "clk_spi_clk", + 0, 0x20, 5, 0, + }, + { + HI3559AV100_SHUB_SPI2_CLK, "clk_shub_spi2", "clk_spi_clk", + 0, 0x20, 9, 0, + }, + + { + HI3559AV100_SHUB_UART0_CLK, "clk_shub_uart0", "shub_uart_source_clk", + 0, 0x1c, 1, 0, + }, + { + HI3559AV100_SHUB_UART1_CLK, "clk_shub_uart1", "shub_uart_source_clk", + 0, 0x1c, 5, 0, + }, + { + HI3559AV100_SHUB_UART2_CLK, "clk_shub_uart2", "shub_uart_source_clk", + 0, 0x1c, 9, 0, + }, + { + HI3559AV100_SHUB_UART3_CLK, "clk_shub_uart3", "shub_uart_source_clk", + 0, 0x1c, 13, 0, + }, + { + HI3559AV100_SHUB_UART4_CLK, "clk_shub_uart4", "shub_uart_source_clk", + 0, 0x1c, 17, 0, + }, + { + HI3559AV100_SHUB_UART5_CLK, "clk_shub_uart5", "shub_uart_source_clk", + 0, 0x1c, 21, 0, + }, + { + HI3559AV100_SHUB_UART6_CLK, "clk_shub_uart6", "shub_uart_source_clk", + 0, 0x1c, 25, 0, + }, + + { + HI3559AV100_SHUB_EDMAC_CLK, "clk_shub_dmac", "shub_clk", + 0, 0x24, 4, 0, + }, +}; + +static int hi3559av100_shub_default_clk_set(void) +{ + void __iomem *crg_base; + unsigned int val; + + crg_base = ioremap(CRG_BASE_ADDR, SZ_4K); + + /* SSP: 192M/2 */ + val = readl_relaxed(crg_base + 0x20); + val |= (0x2 << 24); + writel_relaxed(val, crg_base + 0x20); + + /* UART: 192M/8 */ + val = readl_relaxed(crg_base + 0x1C); + val |= (0x1 << 28); + writel_relaxed(val, crg_base + 0x1C); + + iounmap(crg_base); + crg_base = NULL; + + return 0; +} + +static __init struct hisi_clock_data *hi3559av100_shub_clk_register( + struct platform_device *pdev) +{ + struct hisi_clock_data *clk_data = NULL; + int ret; + + hi3559av100_shub_default_clk_set(); + + clk_data = hisi_clk_alloc(pdev, HI3559AV100_SHUB_NR_CLKS); + if (!clk_data) + return ERR_PTR(-ENOMEM); + + ret = hisi_clk_register_fixed_rate(hi3559av100_shub_fixed_rate_clks, + ARRAY_SIZE(hi3559av100_shub_fixed_rate_clks), clk_data); + if (ret) + return ERR_PTR(ret); + + ret = hisi_clk_register_mux(hi3559av100_shub_mux_clks, + ARRAY_SIZE(hi3559av100_shub_mux_clks), clk_data); + if (ret) + goto unregister_fixed_rate; + + ret = hisi_clk_register_divider(hi3559av100_shub_div_clks, + ARRAY_SIZE(hi3559av100_shub_div_clks), clk_data); + if (ret) + goto unregister_mux; + + ret = hisi_clk_register_gate(hi3559av100_shub_gate_clks, + ARRAY_SIZE(hi3559av100_shub_gate_clks), clk_data); + if (ret) + goto unregister_factor; + + ret = of_clk_add_provider(pdev->dev.of_node, + of_clk_src_onecell_get, &clk_data->clk_data); + if (ret) + goto unregister_gate; + + return clk_data; + +unregister_gate: + hisi_clk_unregister_gate(hi3559av100_shub_gate_clks, + ARRAY_SIZE(hi3559av100_shub_gate_clks), clk_data); +unregister_factor: + hisi_clk_unregister_divider(hi3559av100_shub_div_clks, + ARRAY_SIZE(hi3559av100_shub_div_clks), clk_data); +unregister_mux: + hisi_clk_unregister_mux(hi3559av100_shub_mux_clks, + ARRAY_SIZE(hi3559av100_shub_mux_clks), clk_data); +unregister_fixed_rate: + hisi_clk_unregister_fixed_rate(hi3559av100_shub_fixed_rate_clks, + ARRAY_SIZE(hi3559av100_shub_fixed_rate_clks), clk_data); + return ERR_PTR(ret); +} + +static __init void hi3559av100_shub_clk_unregister(struct platform_device *pdev) +{ + struct hisi_crg_dev *crg = platform_get_drvdata(pdev); + + of_clk_del_provider(pdev->dev.of_node); + + hisi_clk_unregister_gate(hi3559av100_shub_gate_clks, + ARRAY_SIZE(hi3559av100_shub_gate_clks), crg->clk_data); + hisi_clk_unregister_divider(hi3559av100_shub_div_clks, + ARRAY_SIZE(hi3559av100_shub_div_clks), crg->clk_data); + hisi_clk_unregister_mux(hi3559av100_shub_mux_clks, + ARRAY_SIZE(hi3559av100_shub_mux_clks), crg->clk_data); + hisi_clk_unregister_fixed_rate(hi3559av100_shub_fixed_rate_clks, + ARRAY_SIZE(hi3559av100_shub_fixed_rate_clks), crg->clk_data); +} + +static const struct hisi_crg_funcs hi3559av100_shub_crg_funcs = { + .register_clks = hi3559av100_shub_clk_register, + .unregister_clks = hi3559av100_shub_clk_unregister, +}; + +static const struct of_device_id hi3559av100_crg_match_table[] = { + { + .compatible = "hisilicon,hi3559av100-clock", + .data = &hi3559av100_crg_funcs + }, + { + .compatible = "hisilicon,hi3559av100-shub-clock", + .data = &hi3559av100_shub_crg_funcs + }, + { } +}; +MODULE_DEVICE_TABLE(of, hi3559av100_crg_match_table); + +static int hi3559av100_crg_probe(struct platform_device *pdev) +{ + struct hisi_crg_dev *crg; + + crg = devm_kmalloc(&pdev->dev, sizeof(*crg), GFP_KERNEL); + if (!crg) + return -ENOMEM; + + crg->funcs = of_device_get_match_data(&pdev->dev); + if (!crg->funcs) + return -ENOENT; + + crg->rstc = hisi_reset_init(pdev); + if (!crg->rstc) + return -ENOMEM; + + crg->clk_data = crg->funcs->register_clks(pdev); + if (IS_ERR(crg->clk_data)) { + hisi_reset_exit(crg->rstc); + return PTR_ERR(crg->clk_data); + } + + platform_set_drvdata(pdev, crg); + return 0; +} + +static int hi3559av100_crg_remove(struct platform_device *pdev) +{ + struct hisi_crg_dev *crg = platform_get_drvdata(pdev); + + hisi_reset_exit(crg->rstc); + crg->funcs->unregister_clks(pdev); + return 0; +} + +static struct platform_driver hi3559av100_crg_driver = { + .probe = hi3559av100_crg_probe, + .remove = hi3559av100_crg_remove, + .driver = { + .name = "hi3559av100-clock", + .of_match_table = hi3559av100_crg_match_table, + }, +}; + +static int __init hi3559av100_crg_init(void) +{ + return platform_driver_register(&hi3559av100_crg_driver); +} +core_initcall(hi3559av100_crg_init); + +static void __exit hi3559av100_crg_exit(void) +{ + platform_driver_unregister(&hi3559av100_crg_driver); +} +module_exit(hi3559av100_crg_exit); + + +MODULE_LICENSE("GPL v2"); +MODULE_DESCRIPTION("HiSilicon Hi3559AV100 CRG Driver"); diff --git a/drivers/clk/hisilicon/clk.c b/drivers/clk/hisilicon/clk.c index 54d9fdc93599..9361fba7cd4c 100644 --- a/drivers/clk/hisilicon/clk.c +++ b/drivers/clk/hisilicon/clk.c @@ -162,7 +162,7 @@ int hisi_clk_register_mux(const struct hisi_mux_clock *clks, clks[i].num_parents, clks[i].flags, base + clks[i].offset, clks[i].shift, mask, clks[i].mux_flags, - clks[i].table, &hisi_clk_lock); + (u32 *)clks[i].table, &hisi_clk_lock); if (IS_ERR(clk)) { pr_err("%s: failed to register clock %s\n", __func__, clks[i].name); diff --git a/drivers/clk/hisilicon/clk.h b/drivers/clk/hisilicon/clk.h index 61cbd90d1213..7a9b42e1b027 100644 --- a/drivers/clk/hisilicon/clk.h +++ b/drivers/clk/hisilicon/clk.h @@ -50,7 +50,7 @@ struct hisi_mux_clock { u8 shift; u8 width; u8 mux_flags; - u32 *table; + const u32 *table; const char *alias; }; diff --git a/drivers/clk/imx/Makefile b/drivers/clk/imx/Makefile index dd6a737d060b..c24a2acbfa56 100644 --- a/drivers/clk/imx/Makefile +++ b/drivers/clk/imx/Makefile @@ -27,7 +27,8 @@ obj-$(CONFIG_CLK_IMX8MP) += clk-imx8mp.o obj-$(CONFIG_CLK_IMX8MQ) += clk-imx8mq.o obj-$(CONFIG_MXC_CLK_SCU) += clk-imx-scu.o clk-imx-lpcg-scu.o -clk-imx-scu-$(CONFIG_CLK_IMX8QXP) += clk-scu.o clk-imx8qxp.o +clk-imx-scu-$(CONFIG_CLK_IMX8QXP) += clk-scu.o clk-imx8qxp.o \ + clk-imx8qxp-rsrc.o clk-imx8qm-rsrc.o clk-imx-lpcg-scu-$(CONFIG_CLK_IMX8QXP) += clk-lpcg-scu.o clk-imx8qxp-lpcg.o obj-$(CONFIG_CLK_IMX1) += clk-imx1.o diff --git a/drivers/clk/imx/clk-imx8mp.c b/drivers/clk/imx/clk-imx8mp.c index e39c9c907c38..12837304545d 100644 --- a/drivers/clk/imx/clk-imx8mp.c +++ b/drivers/clk/imx/clk-imx8mp.c @@ -556,7 +556,6 @@ static int imx8mp_clocks_probe(struct platform_device *pdev) hws[IMX8MP_CLK_MIPI_DSI_ESC_RX] = imx8m_clk_hw_composite_bus("mipi_dsi_esc_rx", imx8mp_mipi_dsi_esc_rx_sels, ccm_base + 0x9200); hws[IMX8MP_CLK_IPG_ROOT] = imx_clk_hw_divider2("ipg_root", "ahb_root", ccm_base + 0x9080, 0, 1); - hws[IMX8MP_CLK_IPG_AUDIO_ROOT] = imx_clk_hw_divider2("ipg_audio_root", "audio_ahb", ccm_base + 0x9180, 0, 1); hws[IMX8MP_CLK_DRAM_ALT] = imx8m_clk_hw_composite("dram_alt", imx8mp_dram_alt_sels, ccm_base + 0xa000); hws[IMX8MP_CLK_DRAM_APB] = imx8m_clk_hw_composite_critical("dram_apb", imx8mp_dram_apb_sels, ccm_base + 0xa080); diff --git a/drivers/clk/imx/clk-imx8mq.c b/drivers/clk/imx/clk-imx8mq.c index b08019e1faf9..c491bc9c61ce 100644 --- a/drivers/clk/imx/clk-imx8mq.c +++ b/drivers/clk/imx/clk-imx8mq.c @@ -358,46 +358,26 @@ static int imx8mq_clocks_probe(struct platform_device *pdev) hws[IMX8MQ_VIDEO2_PLL_OUT] = imx_clk_hw_sscg_pll("video2_pll_out", video2_pll_out_sels, ARRAY_SIZE(video2_pll_out_sels), 0, 0, 0, base + 0x54, 0); /* SYS PLL1 fixed output */ - hws[IMX8MQ_SYS1_PLL_40M_CG] = imx_clk_hw_gate("sys1_pll_40m_cg", "sys1_pll_out", base + 0x30, 9); - hws[IMX8MQ_SYS1_PLL_80M_CG] = imx_clk_hw_gate("sys1_pll_80m_cg", "sys1_pll_out", base + 0x30, 11); - hws[IMX8MQ_SYS1_PLL_100M_CG] = imx_clk_hw_gate("sys1_pll_100m_cg", "sys1_pll_out", base + 0x30, 13); - hws[IMX8MQ_SYS1_PLL_133M_CG] = imx_clk_hw_gate("sys1_pll_133m_cg", "sys1_pll_out", base + 0x30, 15); - hws[IMX8MQ_SYS1_PLL_160M_CG] = imx_clk_hw_gate("sys1_pll_160m_cg", "sys1_pll_out", base + 0x30, 17); - hws[IMX8MQ_SYS1_PLL_200M_CG] = imx_clk_hw_gate("sys1_pll_200m_cg", "sys1_pll_out", base + 0x30, 19); - hws[IMX8MQ_SYS1_PLL_266M_CG] = imx_clk_hw_gate("sys1_pll_266m_cg", "sys1_pll_out", base + 0x30, 21); - hws[IMX8MQ_SYS1_PLL_400M_CG] = imx_clk_hw_gate("sys1_pll_400m_cg", "sys1_pll_out", base + 0x30, 23); - hws[IMX8MQ_SYS1_PLL_800M_CG] = imx_clk_hw_gate("sys1_pll_800m_cg", "sys1_pll_out", base + 0x30, 25); - - hws[IMX8MQ_SYS1_PLL_40M] = imx_clk_hw_fixed_factor("sys1_pll_40m", "sys1_pll_40m_cg", 1, 20); - hws[IMX8MQ_SYS1_PLL_80M] = imx_clk_hw_fixed_factor("sys1_pll_80m", "sys1_pll_80m_cg", 1, 10); - hws[IMX8MQ_SYS1_PLL_100M] = imx_clk_hw_fixed_factor("sys1_pll_100m", "sys1_pll_100m_cg", 1, 8); - hws[IMX8MQ_SYS1_PLL_133M] = imx_clk_hw_fixed_factor("sys1_pll_133m", "sys1_pll_133m_cg", 1, 6); - hws[IMX8MQ_SYS1_PLL_160M] = imx_clk_hw_fixed_factor("sys1_pll_160m", "sys1_pll_160m_cg", 1, 5); - hws[IMX8MQ_SYS1_PLL_200M] = imx_clk_hw_fixed_factor("sys1_pll_200m", "sys1_pll_200m_cg", 1, 4); - hws[IMX8MQ_SYS1_PLL_266M] = imx_clk_hw_fixed_factor("sys1_pll_266m", "sys1_pll_266m_cg", 1, 3); - hws[IMX8MQ_SYS1_PLL_400M] = imx_clk_hw_fixed_factor("sys1_pll_400m", "sys1_pll_400m_cg", 1, 2); - hws[IMX8MQ_SYS1_PLL_800M] = imx_clk_hw_fixed_factor("sys1_pll_800m", "sys1_pll_800m_cg", 1, 1); + hws[IMX8MQ_SYS1_PLL_40M] = imx_clk_hw_fixed_factor("sys1_pll_40m", "sys1_pll_out", 1, 20); + hws[IMX8MQ_SYS1_PLL_80M] = imx_clk_hw_fixed_factor("sys1_pll_80m", "sys1_pll_out", 1, 10); + hws[IMX8MQ_SYS1_PLL_100M] = imx_clk_hw_fixed_factor("sys1_pll_100m", "sys1_pll_out", 1, 8); + hws[IMX8MQ_SYS1_PLL_133M] = imx_clk_hw_fixed_factor("sys1_pll_133m", "sys1_pll_out", 1, 6); + hws[IMX8MQ_SYS1_PLL_160M] = imx_clk_hw_fixed_factor("sys1_pll_160m", "sys1_pll_out", 1, 5); + hws[IMX8MQ_SYS1_PLL_200M] = imx_clk_hw_fixed_factor("sys1_pll_200m", "sys1_pll_out", 1, 4); + hws[IMX8MQ_SYS1_PLL_266M] = imx_clk_hw_fixed_factor("sys1_pll_266m", "sys1_pll_out", 1, 3); + hws[IMX8MQ_SYS1_PLL_400M] = imx_clk_hw_fixed_factor("sys1_pll_400m", "sys1_pll_out", 1, 2); + hws[IMX8MQ_SYS1_PLL_800M] = imx_clk_hw_fixed_factor("sys1_pll_800m", "sys1_pll_out", 1, 1); /* SYS PLL2 fixed output */ - hws[IMX8MQ_SYS2_PLL_50M_CG] = imx_clk_hw_gate("sys2_pll_50m_cg", "sys2_pll_out", base + 0x3c, 9); - hws[IMX8MQ_SYS2_PLL_100M_CG] = imx_clk_hw_gate("sys2_pll_100m_cg", "sys2_pll_out", base + 0x3c, 11); - hws[IMX8MQ_SYS2_PLL_125M_CG] = imx_clk_hw_gate("sys2_pll_125m_cg", "sys2_pll_out", base + 0x3c, 13); - hws[IMX8MQ_SYS2_PLL_166M_CG] = imx_clk_hw_gate("sys2_pll_166m_cg", "sys2_pll_out", base + 0x3c, 15); - hws[IMX8MQ_SYS2_PLL_200M_CG] = imx_clk_hw_gate("sys2_pll_200m_cg", "sys2_pll_out", base + 0x3c, 17); - hws[IMX8MQ_SYS2_PLL_250M_CG] = imx_clk_hw_gate("sys2_pll_250m_cg", "sys2_pll_out", base + 0x3c, 19); - hws[IMX8MQ_SYS2_PLL_333M_CG] = imx_clk_hw_gate("sys2_pll_333m_cg", "sys2_pll_out", base + 0x3c, 21); - hws[IMX8MQ_SYS2_PLL_500M_CG] = imx_clk_hw_gate("sys2_pll_500m_cg", "sys2_pll_out", base + 0x3c, 23); - hws[IMX8MQ_SYS2_PLL_1000M_CG] = imx_clk_hw_gate("sys2_pll_1000m_cg", "sys2_pll_out", base + 0x3c, 25); - - hws[IMX8MQ_SYS2_PLL_50M] = imx_clk_hw_fixed_factor("sys2_pll_50m", "sys2_pll_50m_cg", 1, 20); - hws[IMX8MQ_SYS2_PLL_100M] = imx_clk_hw_fixed_factor("sys2_pll_100m", "sys2_pll_100m_cg", 1, 10); - hws[IMX8MQ_SYS2_PLL_125M] = imx_clk_hw_fixed_factor("sys2_pll_125m", "sys2_pll_125m_cg", 1, 8); - hws[IMX8MQ_SYS2_PLL_166M] = imx_clk_hw_fixed_factor("sys2_pll_166m", "sys2_pll_166m_cg", 1, 6); - hws[IMX8MQ_SYS2_PLL_200M] = imx_clk_hw_fixed_factor("sys2_pll_200m", "sys2_pll_200m_cg", 1, 5); - hws[IMX8MQ_SYS2_PLL_250M] = imx_clk_hw_fixed_factor("sys2_pll_250m", "sys2_pll_250m_cg", 1, 4); - hws[IMX8MQ_SYS2_PLL_333M] = imx_clk_hw_fixed_factor("sys2_pll_333m", "sys2_pll_333m_cg", 1, 3); - hws[IMX8MQ_SYS2_PLL_500M] = imx_clk_hw_fixed_factor("sys2_pll_500m", "sys2_pll_500m_cg", 1, 2); - hws[IMX8MQ_SYS2_PLL_1000M] = imx_clk_hw_fixed_factor("sys2_pll_1000m", "sys2_pll_1000m_cg", 1, 1); + hws[IMX8MQ_SYS2_PLL_50M] = imx_clk_hw_fixed_factor("sys2_pll_50m", "sys2_pll_out", 1, 20); + hws[IMX8MQ_SYS2_PLL_100M] = imx_clk_hw_fixed_factor("sys2_pll_100m", "sys2_pll_out", 1, 10); + hws[IMX8MQ_SYS2_PLL_125M] = imx_clk_hw_fixed_factor("sys2_pll_125m", "sys2_pll_out", 1, 8); + hws[IMX8MQ_SYS2_PLL_166M] = imx_clk_hw_fixed_factor("sys2_pll_166m", "sys2_pll_out", 1, 6); + hws[IMX8MQ_SYS2_PLL_200M] = imx_clk_hw_fixed_factor("sys2_pll_200m", "sys2_pll_out", 1, 5); + hws[IMX8MQ_SYS2_PLL_250M] = imx_clk_hw_fixed_factor("sys2_pll_250m", "sys2_pll_out", 1, 4); + hws[IMX8MQ_SYS2_PLL_333M] = imx_clk_hw_fixed_factor("sys2_pll_333m", "sys2_pll_out", 1, 3); + hws[IMX8MQ_SYS2_PLL_500M] = imx_clk_hw_fixed_factor("sys2_pll_500m", "sys2_pll_out", 1, 2); + hws[IMX8MQ_SYS2_PLL_1000M] = imx_clk_hw_fixed_factor("sys2_pll_1000m", "sys2_pll_out", 1, 1); hws[IMX8MQ_CLK_MON_AUDIO_PLL1_DIV] = imx_clk_hw_divider("audio_pll1_out_monitor", "audio_pll1_bypass", base + 0x78, 0, 3); hws[IMX8MQ_CLK_MON_AUDIO_PLL2_DIV] = imx_clk_hw_divider("audio_pll2_out_monitor", "audio_pll2_bypass", base + 0x78, 4, 3); diff --git a/drivers/clk/imx/clk-imx8qm-rsrc.c b/drivers/clk/imx/clk-imx8qm-rsrc.c new file mode 100644 index 000000000000..87e0b6ac027e --- /dev/null +++ b/drivers/clk/imx/clk-imx8qm-rsrc.c @@ -0,0 +1,116 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright 2019-2021 NXP + * Dong Aisheng <aisheng.dong@nxp.com> + */ + +#include <dt-bindings/firmware/imx/rsrc.h> + +#include "clk-scu.h" + +/* Keep sorted in the ascending order */ +static const u32 imx8qm_clk_scu_rsrc_table[] = { + IMX_SC_R_A53, + IMX_SC_R_A72, + IMX_SC_R_DC_0_VIDEO0, + IMX_SC_R_DC_0_VIDEO1, + IMX_SC_R_DC_0, + IMX_SC_R_DC_0_PLL_0, + IMX_SC_R_DC_0_PLL_1, + IMX_SC_R_DC_1_VIDEO0, + IMX_SC_R_DC_1_VIDEO1, + IMX_SC_R_DC_1, + IMX_SC_R_DC_1_PLL_0, + IMX_SC_R_DC_1_PLL_1, + IMX_SC_R_SPI_0, + IMX_SC_R_SPI_1, + IMX_SC_R_SPI_2, + IMX_SC_R_SPI_3, + IMX_SC_R_UART_0, + IMX_SC_R_UART_1, + IMX_SC_R_UART_2, + IMX_SC_R_UART_3, + IMX_SC_R_UART_4, + IMX_SC_R_EMVSIM_0, + IMX_SC_R_EMVSIM_1, + IMX_SC_R_I2C_0, + IMX_SC_R_I2C_1, + IMX_SC_R_I2C_2, + IMX_SC_R_I2C_3, + IMX_SC_R_I2C_4, + IMX_SC_R_ADC_0, + IMX_SC_R_ADC_1, + IMX_SC_R_FTM_0, + IMX_SC_R_FTM_1, + IMX_SC_R_CAN_0, + IMX_SC_R_GPU_0_PID0, + IMX_SC_R_GPU_1_PID0, + IMX_SC_R_PWM_0, + IMX_SC_R_PWM_1, + IMX_SC_R_PWM_2, + IMX_SC_R_PWM_3, + IMX_SC_R_PWM_4, + IMX_SC_R_PWM_5, + IMX_SC_R_PWM_6, + IMX_SC_R_PWM_7, + IMX_SC_R_GPT_0, + IMX_SC_R_GPT_1, + IMX_SC_R_GPT_2, + IMX_SC_R_GPT_3, + IMX_SC_R_GPT_4, + IMX_SC_R_FSPI_0, + IMX_SC_R_FSPI_1, + IMX_SC_R_SDHC_0, + IMX_SC_R_SDHC_1, + IMX_SC_R_SDHC_2, + IMX_SC_R_ENET_0, + IMX_SC_R_ENET_1, + IMX_SC_R_MLB_0, + IMX_SC_R_USB_2, + IMX_SC_R_NAND, + IMX_SC_R_LVDS_0, + IMX_SC_R_LVDS_0_PWM_0, + IMX_SC_R_LVDS_0_I2C_0, + IMX_SC_R_LVDS_0_I2C_1, + IMX_SC_R_LVDS_1, + IMX_SC_R_LVDS_1_PWM_0, + IMX_SC_R_LVDS_1_I2C_0, + IMX_SC_R_LVDS_1_I2C_1, + IMX_SC_R_M4_0_I2C, + IMX_SC_R_M4_1_I2C, + IMX_SC_R_AUDIO_PLL_0, + IMX_SC_R_VPU_UART, + IMX_SC_R_VPUCORE, + IMX_SC_R_MIPI_0, + IMX_SC_R_MIPI_0_PWM_0, + IMX_SC_R_MIPI_0_I2C_0, + IMX_SC_R_MIPI_0_I2C_1, + IMX_SC_R_MIPI_1, + IMX_SC_R_MIPI_1_PWM_0, + IMX_SC_R_MIPI_1_I2C_0, + IMX_SC_R_MIPI_1_I2C_1, + IMX_SC_R_CSI_0, + IMX_SC_R_CSI_0_PWM_0, + IMX_SC_R_CSI_0_I2C_0, + IMX_SC_R_CSI_1, + IMX_SC_R_CSI_1_PWM_0, + IMX_SC_R_CSI_1_I2C_0, + IMX_SC_R_HDMI, + IMX_SC_R_HDMI_I2S, + IMX_SC_R_HDMI_I2C_0, + IMX_SC_R_HDMI_PLL_0, + IMX_SC_R_HDMI_RX, + IMX_SC_R_HDMI_RX_BYPASS, + IMX_SC_R_HDMI_RX_I2C_0, + IMX_SC_R_AUDIO_PLL_1, + IMX_SC_R_AUDIO_CLK_0, + IMX_SC_R_AUDIO_CLK_1, + IMX_SC_R_HDMI_RX_PWM_0, + IMX_SC_R_HDMI_PLL_1, + IMX_SC_R_VPU, +}; + +const struct imx_clk_scu_rsrc_table imx_clk_scu_rsrc_imx8qm = { + .rsrc = imx8qm_clk_scu_rsrc_table, + .num = ARRAY_SIZE(imx8qm_clk_scu_rsrc_table), +}; diff --git a/drivers/clk/imx/clk-imx8qxp-rsrc.c b/drivers/clk/imx/clk-imx8qxp-rsrc.c new file mode 100644 index 000000000000..df09f2a7996d --- /dev/null +++ b/drivers/clk/imx/clk-imx8qxp-rsrc.c @@ -0,0 +1,89 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright 2019-2021 NXP + * Dong Aisheng <aisheng.dong@nxp.com> + */ + +#include <dt-bindings/firmware/imx/rsrc.h> + +#include "clk-scu.h" + +/* Keep sorted in the ascending order */ +static const u32 imx8qxp_clk_scu_rsrc_table[] = { + IMX_SC_R_DC_0_VIDEO0, + IMX_SC_R_DC_0_VIDEO1, + IMX_SC_R_DC_0, + IMX_SC_R_DC_0_PLL_0, + IMX_SC_R_DC_0_PLL_1, + IMX_SC_R_SPI_0, + IMX_SC_R_SPI_1, + IMX_SC_R_SPI_2, + IMX_SC_R_SPI_3, + IMX_SC_R_UART_0, + IMX_SC_R_UART_1, + IMX_SC_R_UART_2, + IMX_SC_R_UART_3, + IMX_SC_R_I2C_0, + IMX_SC_R_I2C_1, + IMX_SC_R_I2C_2, + IMX_SC_R_I2C_3, + IMX_SC_R_ADC_0, + IMX_SC_R_FTM_0, + IMX_SC_R_FTM_1, + IMX_SC_R_CAN_0, + IMX_SC_R_GPU_0_PID0, + IMX_SC_R_LCD_0, + IMX_SC_R_LCD_0_PWM_0, + IMX_SC_R_PWM_0, + IMX_SC_R_PWM_1, + IMX_SC_R_PWM_2, + IMX_SC_R_PWM_3, + IMX_SC_R_PWM_4, + IMX_SC_R_PWM_5, + IMX_SC_R_PWM_6, + IMX_SC_R_PWM_7, + IMX_SC_R_GPT_0, + IMX_SC_R_GPT_1, + IMX_SC_R_GPT_2, + IMX_SC_R_GPT_3, + IMX_SC_R_GPT_4, + IMX_SC_R_FSPI_0, + IMX_SC_R_FSPI_1, + IMX_SC_R_SDHC_0, + IMX_SC_R_SDHC_1, + IMX_SC_R_SDHC_2, + IMX_SC_R_ENET_0, + IMX_SC_R_ENET_1, + IMX_SC_R_MLB_0, + IMX_SC_R_USB_2, + IMX_SC_R_NAND, + IMX_SC_R_LVDS_0, + IMX_SC_R_LVDS_1, + IMX_SC_R_M4_0_I2C, + IMX_SC_R_ELCDIF_PLL, + IMX_SC_R_AUDIO_PLL_0, + IMX_SC_R_PI_0, + IMX_SC_R_PI_0_PLL, + IMX_SC_R_MIPI_0, + IMX_SC_R_MIPI_0_PWM_0, + IMX_SC_R_MIPI_0_I2C_0, + IMX_SC_R_MIPI_0_I2C_1, + IMX_SC_R_MIPI_1, + IMX_SC_R_MIPI_1_PWM_0, + IMX_SC_R_MIPI_1_I2C_0, + IMX_SC_R_MIPI_1_I2C_1, + IMX_SC_R_CSI_0, + IMX_SC_R_CSI_0_PWM_0, + IMX_SC_R_CSI_0_I2C_0, + IMX_SC_R_AUDIO_PLL_1, + IMX_SC_R_AUDIO_CLK_0, + IMX_SC_R_AUDIO_CLK_1, + IMX_SC_R_A35, + IMX_SC_R_VPU_DEC_0, + IMX_SC_R_VPU_ENC_0, +}; + +const struct imx_clk_scu_rsrc_table imx_clk_scu_rsrc_imx8qxp = { + .rsrc = imx8qxp_clk_scu_rsrc_table, + .num = ARRAY_SIZE(imx8qxp_clk_scu_rsrc_table), +}; diff --git a/drivers/clk/imx/clk-imx8qxp.c b/drivers/clk/imx/clk-imx8qxp.c index fbf1170c09ed..c53a688d8ccc 100644 --- a/drivers/clk/imx/clk-imx8qxp.c +++ b/drivers/clk/imx/clk-imx8qxp.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0+ /* - * Copyright 2018 NXP + * Copyright 2018-2021 NXP * Dong Aisheng <aisheng.dong@nxp.com> */ @@ -9,12 +9,12 @@ #include <linux/io.h> #include <linux/module.h> #include <linux/of.h> +#include <linux/of_device.h> #include <linux/platform_device.h> #include <linux/slab.h> #include "clk-scu.h" -#include <dt-bindings/clock/imx8-clock.h> #include <dt-bindings/firmware/imx/rsrc.h> static const char *dc0_sels[] = { @@ -25,159 +25,278 @@ static const char *dc0_sels[] = { "dc0_bypass0_clk", }; +static const char * const dc1_sels[] = { + "clk_dummy", + "clk_dummy", + "dc1_pll0_clk", + "dc1_pll1_clk", + "dc1_bypass0_clk", +}; + +static const char * const enet0_rgmii_txc_sels[] = { + "enet0_ref_div", + "clk_dummy", +}; + +static const char * const enet1_rgmii_txc_sels[] = { + "enet1_ref_div", + "clk_dummy", +}; + +static const char * const hdmi_sels[] = { + "clk_dummy", + "hdmi_dig_pll_clk", + "clk_dummy", + "clk_dummy", + "hdmi_av_pll_clk", +}; + +static const char * const hdmi_rx_sels[] = { + "clk_dummy", + "hdmi_rx_dig_pll_clk", + "clk_dummy", + "clk_dummy", + "hdmi_rx_bypass_clk", +}; + +static const char * const lcd_pxl_sels[] = { + "clk_dummy", + "clk_dummy", + "clk_dummy", + "clk_dummy", + "lcd_pxl_bypass_div_clk", +}; + +static const char * const mipi_sels[] = { + "clk_dummy", + "clk_dummy", + "mipi_pll_div2_clk", + "clk_dummy", + "clk_dummy", +}; + +static const char * const lcd_sels[] = { + "clk_dummy", + "clk_dummy", + "clk_dummy", + "clk_dummy", + "elcdif_pll", +}; + +static const char * const pi_pll0_sels[] = { + "clk_dummy", + "pi_dpll_clk", + "clk_dummy", + "clk_dummy", + "clk_dummy", +}; + static int imx8qxp_clk_probe(struct platform_device *pdev) { struct device_node *ccm_node = pdev->dev.of_node; - struct clk_hw_onecell_data *clk_data; - struct clk_hw **clks; - u32 clk_cells; - int ret, i; + const struct imx_clk_scu_rsrc_table *rsrc_table; + int ret; - ret = imx_clk_scu_init(ccm_node); + rsrc_table = of_device_get_match_data(&pdev->dev); + ret = imx_clk_scu_init(ccm_node, rsrc_table); if (ret) return ret; - clk_data = devm_kzalloc(&pdev->dev, struct_size(clk_data, hws, - IMX_SCU_CLK_END), GFP_KERNEL); - if (!clk_data) - return -ENOMEM; - - if (of_property_read_u32(ccm_node, "#clock-cells", &clk_cells)) - return -EINVAL; - - clk_data->num = IMX_SCU_CLK_END; - clks = clk_data->hws; - - /* Fixed clocks */ - clks[IMX_CLK_DUMMY] = clk_hw_register_fixed_rate(NULL, "dummy", NULL, 0, 0); - clks[IMX_ADMA_IPG_CLK_ROOT] = clk_hw_register_fixed_rate(NULL, "dma_ipg_clk_root", NULL, 0, 120000000); - clks[IMX_CONN_AXI_CLK_ROOT] = clk_hw_register_fixed_rate(NULL, "conn_axi_clk_root", NULL, 0, 333333333); - clks[IMX_CONN_AHB_CLK_ROOT] = clk_hw_register_fixed_rate(NULL, "conn_ahb_clk_root", NULL, 0, 166666666); - clks[IMX_CONN_IPG_CLK_ROOT] = clk_hw_register_fixed_rate(NULL, "conn_ipg_clk_root", NULL, 0, 83333333); - clks[IMX_DC_AXI_EXT_CLK] = clk_hw_register_fixed_rate(NULL, "dc_axi_ext_clk_root", NULL, 0, 800000000); - clks[IMX_DC_AXI_INT_CLK] = clk_hw_register_fixed_rate(NULL, "dc_axi_int_clk_root", NULL, 0, 400000000); - clks[IMX_DC_CFG_CLK] = clk_hw_register_fixed_rate(NULL, "dc_cfg_clk_root", NULL, 0, 100000000); - clks[IMX_MIPI_IPG_CLK] = clk_hw_register_fixed_rate(NULL, "mipi_ipg_clk_root", NULL, 0, 120000000); - clks[IMX_IMG_AXI_CLK] = clk_hw_register_fixed_rate(NULL, "img_axi_clk_root", NULL, 0, 400000000); - clks[IMX_IMG_IPG_CLK] = clk_hw_register_fixed_rate(NULL, "img_ipg_clk_root", NULL, 0, 200000000); - clks[IMX_IMG_PXL_CLK] = clk_hw_register_fixed_rate(NULL, "img_pxl_clk_root", NULL, 0, 600000000); - clks[IMX_HSIO_AXI_CLK] = clk_hw_register_fixed_rate(NULL, "hsio_axi_clk_root", NULL, 0, 400000000); - clks[IMX_HSIO_PER_CLK] = clk_hw_register_fixed_rate(NULL, "hsio_per_clk_root", NULL, 0, 133333333); - clks[IMX_LSIO_MEM_CLK] = clk_hw_register_fixed_rate(NULL, "lsio_mem_clk_root", NULL, 0, 200000000); - clks[IMX_LSIO_BUS_CLK] = clk_hw_register_fixed_rate(NULL, "lsio_bus_clk_root", NULL, 0, 100000000); - /* ARM core */ - clks[IMX_A35_CLK] = imx_clk_scu("a35_clk", IMX_SC_R_A35, IMX_SC_PM_CLK_CPU, clk_cells); + imx_clk_scu("a35_clk", IMX_SC_R_A35, IMX_SC_PM_CLK_CPU); + imx_clk_scu("a53_clk", IMX_SC_R_A53, IMX_SC_PM_CLK_CPU); + imx_clk_scu("a72_clk", IMX_SC_R_A72, IMX_SC_PM_CLK_CPU); /* LSIO SS */ - clks[IMX_LSIO_PWM0_CLK] = imx_clk_scu("pwm0_clk", IMX_SC_R_PWM_0, IMX_SC_PM_CLK_PER, clk_cells); - clks[IMX_LSIO_PWM1_CLK] = imx_clk_scu("pwm1_clk", IMX_SC_R_PWM_1, IMX_SC_PM_CLK_PER, clk_cells); - clks[IMX_LSIO_PWM2_CLK] = imx_clk_scu("pwm2_clk", IMX_SC_R_PWM_2, IMX_SC_PM_CLK_PER, clk_cells); - clks[IMX_LSIO_PWM3_CLK] = imx_clk_scu("pwm3_clk", IMX_SC_R_PWM_3, IMX_SC_PM_CLK_PER, clk_cells); - clks[IMX_LSIO_PWM4_CLK] = imx_clk_scu("pwm4_clk", IMX_SC_R_PWM_4, IMX_SC_PM_CLK_PER, clk_cells); - clks[IMX_LSIO_PWM5_CLK] = imx_clk_scu("pwm5_clk", IMX_SC_R_PWM_5, IMX_SC_PM_CLK_PER, clk_cells); - clks[IMX_LSIO_PWM6_CLK] = imx_clk_scu("pwm6_clk", IMX_SC_R_PWM_6, IMX_SC_PM_CLK_PER, clk_cells); - clks[IMX_LSIO_PWM7_CLK] = imx_clk_scu("pwm7_clk", IMX_SC_R_PWM_7, IMX_SC_PM_CLK_PER, clk_cells); - clks[IMX_LSIO_GPT0_CLK] = imx_clk_scu("gpt0_clk", IMX_SC_R_GPT_0, IMX_SC_PM_CLK_PER, clk_cells); - clks[IMX_LSIO_GPT1_CLK] = imx_clk_scu("gpt1_clk", IMX_SC_R_GPT_1, IMX_SC_PM_CLK_PER, clk_cells); - clks[IMX_LSIO_GPT2_CLK] = imx_clk_scu("gpt2_clk", IMX_SC_R_GPT_2, IMX_SC_PM_CLK_PER, clk_cells); - clks[IMX_LSIO_GPT3_CLK] = imx_clk_scu("gpt3_clk", IMX_SC_R_GPT_3, IMX_SC_PM_CLK_PER, clk_cells); - clks[IMX_LSIO_GPT4_CLK] = imx_clk_scu("gpt4_clk", IMX_SC_R_GPT_4, IMX_SC_PM_CLK_PER, clk_cells); - clks[IMX_LSIO_FSPI0_CLK] = imx_clk_scu("fspi0_clk", IMX_SC_R_FSPI_0, IMX_SC_PM_CLK_PER, clk_cells); - clks[IMX_LSIO_FSPI1_CLK] = imx_clk_scu("fspi1_clk", IMX_SC_R_FSPI_1, IMX_SC_PM_CLK_PER, clk_cells); - - /* ADMA SS */ - clks[IMX_ADMA_UART0_CLK] = imx_clk_scu("uart0_clk", IMX_SC_R_UART_0, IMX_SC_PM_CLK_PER, clk_cells); - clks[IMX_ADMA_UART1_CLK] = imx_clk_scu("uart1_clk", IMX_SC_R_UART_1, IMX_SC_PM_CLK_PER, clk_cells); - clks[IMX_ADMA_UART2_CLK] = imx_clk_scu("uart2_clk", IMX_SC_R_UART_2, IMX_SC_PM_CLK_PER, clk_cells); - clks[IMX_ADMA_UART3_CLK] = imx_clk_scu("uart3_clk", IMX_SC_R_UART_3, IMX_SC_PM_CLK_PER, clk_cells); - clks[IMX_ADMA_SPI0_CLK] = imx_clk_scu("spi0_clk", IMX_SC_R_SPI_0, IMX_SC_PM_CLK_PER, clk_cells); - clks[IMX_ADMA_SPI1_CLK] = imx_clk_scu("spi1_clk", IMX_SC_R_SPI_1, IMX_SC_PM_CLK_PER, clk_cells); - clks[IMX_ADMA_SPI2_CLK] = imx_clk_scu("spi2_clk", IMX_SC_R_SPI_2, IMX_SC_PM_CLK_PER, clk_cells); - clks[IMX_ADMA_SPI3_CLK] = imx_clk_scu("spi3_clk", IMX_SC_R_SPI_3, IMX_SC_PM_CLK_PER, clk_cells); - clks[IMX_ADMA_CAN0_CLK] = imx_clk_scu("can0_clk", IMX_SC_R_CAN_0, IMX_SC_PM_CLK_PER, clk_cells); - clks[IMX_ADMA_I2C0_CLK] = imx_clk_scu("i2c0_clk", IMX_SC_R_I2C_0, IMX_SC_PM_CLK_PER, clk_cells); - clks[IMX_ADMA_I2C1_CLK] = imx_clk_scu("i2c1_clk", IMX_SC_R_I2C_1, IMX_SC_PM_CLK_PER, clk_cells); - clks[IMX_ADMA_I2C2_CLK] = imx_clk_scu("i2c2_clk", IMX_SC_R_I2C_2, IMX_SC_PM_CLK_PER, clk_cells); - clks[IMX_ADMA_I2C3_CLK] = imx_clk_scu("i2c3_clk", IMX_SC_R_I2C_3, IMX_SC_PM_CLK_PER, clk_cells); - clks[IMX_ADMA_FTM0_CLK] = imx_clk_scu("ftm0_clk", IMX_SC_R_FTM_0, IMX_SC_PM_CLK_PER, clk_cells); - clks[IMX_ADMA_FTM1_CLK] = imx_clk_scu("ftm1_clk", IMX_SC_R_FTM_1, IMX_SC_PM_CLK_PER, clk_cells); - clks[IMX_ADMA_ADC0_CLK] = imx_clk_scu("adc0_clk", IMX_SC_R_ADC_0, IMX_SC_PM_CLK_PER, clk_cells); - clks[IMX_ADMA_PWM_CLK] = imx_clk_scu("pwm_clk", IMX_SC_R_LCD_0_PWM_0, IMX_SC_PM_CLK_PER, clk_cells); - clks[IMX_ADMA_LCD_CLK] = imx_clk_scu("lcd_clk", IMX_SC_R_LCD_0, IMX_SC_PM_CLK_PER, clk_cells); + imx_clk_scu("pwm0_clk", IMX_SC_R_PWM_0, IMX_SC_PM_CLK_PER); + imx_clk_scu("pwm1_clk", IMX_SC_R_PWM_1, IMX_SC_PM_CLK_PER); + imx_clk_scu("pwm2_clk", IMX_SC_R_PWM_2, IMX_SC_PM_CLK_PER); + imx_clk_scu("pwm3_clk", IMX_SC_R_PWM_3, IMX_SC_PM_CLK_PER); + imx_clk_scu("pwm4_clk", IMX_SC_R_PWM_4, IMX_SC_PM_CLK_PER); + imx_clk_scu("pwm5_clk", IMX_SC_R_PWM_5, IMX_SC_PM_CLK_PER); + imx_clk_scu("pwm6_clk", IMX_SC_R_PWM_6, IMX_SC_PM_CLK_PER); + imx_clk_scu("pwm7_clk", IMX_SC_R_PWM_7, IMX_SC_PM_CLK_PER); + imx_clk_scu("gpt0_clk", IMX_SC_R_GPT_0, IMX_SC_PM_CLK_PER); + imx_clk_scu("gpt1_clk", IMX_SC_R_GPT_1, IMX_SC_PM_CLK_PER); + imx_clk_scu("gpt2_clk", IMX_SC_R_GPT_2, IMX_SC_PM_CLK_PER); + imx_clk_scu("gpt3_clk", IMX_SC_R_GPT_3, IMX_SC_PM_CLK_PER); + imx_clk_scu("gpt4_clk", IMX_SC_R_GPT_4, IMX_SC_PM_CLK_PER); + imx_clk_scu("fspi0_clk", IMX_SC_R_FSPI_0, IMX_SC_PM_CLK_PER); + imx_clk_scu("fspi1_clk", IMX_SC_R_FSPI_1, IMX_SC_PM_CLK_PER); + + /* DMA SS */ + imx_clk_scu("uart0_clk", IMX_SC_R_UART_0, IMX_SC_PM_CLK_PER); + imx_clk_scu("uart1_clk", IMX_SC_R_UART_1, IMX_SC_PM_CLK_PER); + imx_clk_scu("uart2_clk", IMX_SC_R_UART_2, IMX_SC_PM_CLK_PER); + imx_clk_scu("uart3_clk", IMX_SC_R_UART_3, IMX_SC_PM_CLK_PER); + imx_clk_scu("uart4_clk", IMX_SC_R_UART_4, IMX_SC_PM_CLK_PER); + imx_clk_scu("sim0_clk", IMX_SC_R_EMVSIM_0, IMX_SC_PM_CLK_PER); + imx_clk_scu("spi0_clk", IMX_SC_R_SPI_0, IMX_SC_PM_CLK_PER); + imx_clk_scu("spi1_clk", IMX_SC_R_SPI_1, IMX_SC_PM_CLK_PER); + imx_clk_scu("spi2_clk", IMX_SC_R_SPI_2, IMX_SC_PM_CLK_PER); + imx_clk_scu("spi3_clk", IMX_SC_R_SPI_3, IMX_SC_PM_CLK_PER); + imx_clk_scu("can0_clk", IMX_SC_R_CAN_0, IMX_SC_PM_CLK_PER); + imx_clk_scu("can1_clk", IMX_SC_R_CAN_1, IMX_SC_PM_CLK_PER); + imx_clk_scu("can2_clk", IMX_SC_R_CAN_2, IMX_SC_PM_CLK_PER); + imx_clk_scu("i2c0_clk", IMX_SC_R_I2C_0, IMX_SC_PM_CLK_PER); + imx_clk_scu("i2c1_clk", IMX_SC_R_I2C_1, IMX_SC_PM_CLK_PER); + imx_clk_scu("i2c2_clk", IMX_SC_R_I2C_2, IMX_SC_PM_CLK_PER); + imx_clk_scu("i2c3_clk", IMX_SC_R_I2C_3, IMX_SC_PM_CLK_PER); + imx_clk_scu("i2c4_clk", IMX_SC_R_I2C_4, IMX_SC_PM_CLK_PER); + imx_clk_scu("ftm0_clk", IMX_SC_R_FTM_0, IMX_SC_PM_CLK_PER); + imx_clk_scu("ftm1_clk", IMX_SC_R_FTM_1, IMX_SC_PM_CLK_PER); + imx_clk_scu("adc0_clk", IMX_SC_R_ADC_0, IMX_SC_PM_CLK_PER); + imx_clk_scu("adc1_clk", IMX_SC_R_ADC_1, IMX_SC_PM_CLK_PER); + imx_clk_scu("pwm_clk", IMX_SC_R_LCD_0_PWM_0, IMX_SC_PM_CLK_PER); + imx_clk_scu2("lcd_clk", lcd_sels, ARRAY_SIZE(lcd_sels), IMX_SC_R_LCD_0, IMX_SC_PM_CLK_PER); + imx_clk_scu2("lcd_pxl_clk", lcd_pxl_sels, ARRAY_SIZE(lcd_pxl_sels), IMX_SC_R_LCD_0, IMX_SC_PM_CLK_MISC0); + imx_clk_scu("lcd_pxl_bypass_div_clk", IMX_SC_R_LCD_0, IMX_SC_PM_CLK_BYPASS); + imx_clk_scu("elcdif_pll", IMX_SC_R_ELCDIF_PLL, IMX_SC_PM_CLK_PLL); + + /* Audio SS */ + imx_clk_scu("audio_pll0_clk", IMX_SC_R_AUDIO_PLL_0, IMX_SC_PM_CLK_PLL); + imx_clk_scu("audio_pll1_clk", IMX_SC_R_AUDIO_PLL_1, IMX_SC_PM_CLK_PLL); + imx_clk_scu("audio_pll_div_clk0_clk", IMX_SC_R_AUDIO_PLL_0, IMX_SC_PM_CLK_MISC0); + imx_clk_scu("audio_pll_div_clk1_clk", IMX_SC_R_AUDIO_PLL_1, IMX_SC_PM_CLK_MISC0); + imx_clk_scu("audio_rec_clk0_clk", IMX_SC_R_AUDIO_PLL_0, IMX_SC_PM_CLK_MISC1); + imx_clk_scu("audio_rec_clk1_clk", IMX_SC_R_AUDIO_PLL_1, IMX_SC_PM_CLK_MISC1); /* Connectivity */ - clks[IMX_CONN_SDHC0_CLK] = imx_clk_scu("sdhc0_clk", IMX_SC_R_SDHC_0, IMX_SC_PM_CLK_PER, clk_cells); - clks[IMX_CONN_SDHC1_CLK] = imx_clk_scu("sdhc1_clk", IMX_SC_R_SDHC_1, IMX_SC_PM_CLK_PER, clk_cells); - clks[IMX_CONN_SDHC2_CLK] = imx_clk_scu("sdhc2_clk", IMX_SC_R_SDHC_2, IMX_SC_PM_CLK_PER, clk_cells); - clks[IMX_CONN_ENET0_ROOT_CLK] = imx_clk_scu("enet0_clk", IMX_SC_R_ENET_0, IMX_SC_PM_CLK_PER, clk_cells); - clks[IMX_CONN_ENET0_BYPASS_CLK] = imx_clk_scu("enet0_bypass_clk", IMX_SC_R_ENET_0, IMX_SC_PM_CLK_BYPASS, clk_cells); - clks[IMX_CONN_ENET0_RGMII_CLK] = imx_clk_scu("enet0_rgmii_clk", IMX_SC_R_ENET_0, IMX_SC_PM_CLK_MISC0, clk_cells); - clks[IMX_CONN_ENET1_ROOT_CLK] = imx_clk_scu("enet1_clk", IMX_SC_R_ENET_1, IMX_SC_PM_CLK_PER, clk_cells); - clks[IMX_CONN_ENET1_BYPASS_CLK] = imx_clk_scu("enet1_bypass_clk", IMX_SC_R_ENET_1, IMX_SC_PM_CLK_BYPASS, clk_cells); - clks[IMX_CONN_ENET1_RGMII_CLK] = imx_clk_scu("enet1_rgmii_clk", IMX_SC_R_ENET_1, IMX_SC_PM_CLK_MISC0, clk_cells); - clks[IMX_CONN_GPMI_BCH_IO_CLK] = imx_clk_scu("gpmi_io_clk", IMX_SC_R_NAND, IMX_SC_PM_CLK_MST_BUS, clk_cells); - clks[IMX_CONN_GPMI_BCH_CLK] = imx_clk_scu("gpmi_bch_clk", IMX_SC_R_NAND, IMX_SC_PM_CLK_PER, clk_cells); - clks[IMX_CONN_USB2_ACLK] = imx_clk_scu("usb3_aclk_div", IMX_SC_R_USB_2, IMX_SC_PM_CLK_PER, clk_cells); - clks[IMX_CONN_USB2_BUS_CLK] = imx_clk_scu("usb3_bus_div", IMX_SC_R_USB_2, IMX_SC_PM_CLK_MST_BUS, clk_cells); - clks[IMX_CONN_USB2_LPM_CLK] = imx_clk_scu("usb3_lpm_div", IMX_SC_R_USB_2, IMX_SC_PM_CLK_MISC, clk_cells); + imx_clk_scu("sdhc0_clk", IMX_SC_R_SDHC_0, IMX_SC_PM_CLK_PER); + imx_clk_scu("sdhc1_clk", IMX_SC_R_SDHC_1, IMX_SC_PM_CLK_PER); + imx_clk_scu("sdhc2_clk", IMX_SC_R_SDHC_2, IMX_SC_PM_CLK_PER); + imx_clk_scu("enet0_root_clk", IMX_SC_R_ENET_0, IMX_SC_PM_CLK_PER); + imx_clk_divider_gpr_scu("enet0_ref_div", "enet0_root_clk", IMX_SC_R_ENET_0, IMX_SC_C_CLKDIV); + imx_clk_mux_gpr_scu("enet0_rgmii_txc_sel", enet0_rgmii_txc_sels, ARRAY_SIZE(enet0_rgmii_txc_sels), IMX_SC_R_ENET_0, IMX_SC_C_TXCLK); + imx_clk_scu("enet0_bypass_clk", IMX_SC_R_ENET_0, IMX_SC_PM_CLK_BYPASS); + imx_clk_gate_gpr_scu("enet0_ref_50_clk", "clk_dummy", IMX_SC_R_ENET_0, IMX_SC_C_DISABLE_50, true); + imx_clk_scu("enet0_rgmii_rx_clk", IMX_SC_R_ENET_0, IMX_SC_PM_CLK_MISC0); + imx_clk_scu("enet1_root_clk", IMX_SC_R_ENET_1, IMX_SC_PM_CLK_PER); + imx_clk_divider_gpr_scu("enet1_ref_div", "enet1_root_clk", IMX_SC_R_ENET_1, IMX_SC_C_CLKDIV); + imx_clk_mux_gpr_scu("enet1_rgmii_txc_sel", enet1_rgmii_txc_sels, ARRAY_SIZE(enet1_rgmii_txc_sels), IMX_SC_R_ENET_1, IMX_SC_C_TXCLK); + imx_clk_scu("enet1_bypass_clk", IMX_SC_R_ENET_1, IMX_SC_PM_CLK_BYPASS); + imx_clk_gate_gpr_scu("enet1_ref_50_clk", "clk_dummy", IMX_SC_R_ENET_1, IMX_SC_C_DISABLE_50, true); + imx_clk_scu("enet1_rgmii_rx_clk", IMX_SC_R_ENET_1, IMX_SC_PM_CLK_MISC0); + imx_clk_scu("gpmi_io_clk", IMX_SC_R_NAND, IMX_SC_PM_CLK_MST_BUS); + imx_clk_scu("gpmi_bch_clk", IMX_SC_R_NAND, IMX_SC_PM_CLK_PER); + imx_clk_scu("usb3_aclk_div", IMX_SC_R_USB_2, IMX_SC_PM_CLK_PER); + imx_clk_scu("usb3_bus_div", IMX_SC_R_USB_2, IMX_SC_PM_CLK_MST_BUS); + imx_clk_scu("usb3_lpm_div", IMX_SC_R_USB_2, IMX_SC_PM_CLK_MISC); /* Display controller SS */ - clks[IMX_DC0_DISP0_CLK] = imx_clk_scu2("dc0_disp0_clk", dc0_sels, ARRAY_SIZE(dc0_sels), IMX_SC_R_DC_0, IMX_SC_PM_CLK_MISC0, clk_cells); - clks[IMX_DC0_DISP1_CLK] = imx_clk_scu2("dc0_disp1_clk", dc0_sels, ARRAY_SIZE(dc0_sels), IMX_SC_R_DC_0, IMX_SC_PM_CLK_MISC1, clk_cells); - clks[IMX_DC0_PLL0_CLK] = imx_clk_scu("dc0_pll0_clk", IMX_SC_R_DC_0_PLL_0, IMX_SC_PM_CLK_PLL, clk_cells); - clks[IMX_DC0_PLL1_CLK] = imx_clk_scu("dc0_pll1_clk", IMX_SC_R_DC_0_PLL_1, IMX_SC_PM_CLK_PLL, clk_cells); - clks[IMX_DC0_BYPASS0_CLK] = imx_clk_scu("dc0_bypass0_clk", IMX_SC_R_DC_0_VIDEO0, IMX_SC_PM_CLK_BYPASS, clk_cells); - clks[IMX_DC0_BYPASS1_CLK] = imx_clk_scu("dc0_bypass1_clk", IMX_SC_R_DC_0_VIDEO1, IMX_SC_PM_CLK_BYPASS, clk_cells); + imx_clk_scu2("dc0_disp0_clk", dc0_sels, ARRAY_SIZE(dc0_sels), IMX_SC_R_DC_0, IMX_SC_PM_CLK_MISC0); + imx_clk_scu2("dc0_disp1_clk", dc0_sels, ARRAY_SIZE(dc0_sels), IMX_SC_R_DC_0, IMX_SC_PM_CLK_MISC1); + imx_clk_scu("dc0_pll0_clk", IMX_SC_R_DC_0_PLL_0, IMX_SC_PM_CLK_PLL); + imx_clk_scu("dc0_pll1_clk", IMX_SC_R_DC_0_PLL_1, IMX_SC_PM_CLK_PLL); + imx_clk_scu("dc0_bypass0_clk", IMX_SC_R_DC_0_VIDEO0, IMX_SC_PM_CLK_BYPASS); + imx_clk_scu("dc0_bypass1_clk", IMX_SC_R_DC_0_VIDEO1, IMX_SC_PM_CLK_BYPASS); + + imx_clk_scu2("dc1_disp0_clk", dc1_sels, ARRAY_SIZE(dc1_sels), IMX_SC_R_DC_1, IMX_SC_PM_CLK_MISC0); + imx_clk_scu2("dc1_disp1_clk", dc1_sels, ARRAY_SIZE(dc1_sels), IMX_SC_R_DC_1, IMX_SC_PM_CLK_MISC1); + imx_clk_scu("dc1_pll0_clk", IMX_SC_R_DC_1_PLL_0, IMX_SC_PM_CLK_PLL); + imx_clk_scu("dc1_pll1_clk", IMX_SC_R_DC_1_PLL_1, IMX_SC_PM_CLK_PLL); + imx_clk_scu("dc1_bypass0_clk", IMX_SC_R_DC_1_VIDEO0, IMX_SC_PM_CLK_BYPASS); + imx_clk_scu("dc1_bypass1_clk", IMX_SC_R_DC_1_VIDEO1, IMX_SC_PM_CLK_BYPASS); /* MIPI-LVDS SS */ - clks[IMX_MIPI0_LVDS_PIXEL_CLK] = imx_clk_scu("mipi0_lvds_pixel_clk", IMX_SC_R_LVDS_0, IMX_SC_PM_CLK_MISC2, clk_cells); - clks[IMX_MIPI0_LVDS_BYPASS_CLK] = imx_clk_scu("mipi0_lvds_bypass_clk", IMX_SC_R_LVDS_0, IMX_SC_PM_CLK_BYPASS, clk_cells); - clks[IMX_MIPI0_LVDS_PHY_CLK] = imx_clk_scu("mipi0_lvds_phy_clk", IMX_SC_R_LVDS_0, IMX_SC_PM_CLK_MISC3, clk_cells); - clks[IMX_MIPI0_I2C0_CLK] = imx_clk_scu("mipi0_i2c0_clk", IMX_SC_R_MIPI_0_I2C_0, IMX_SC_PM_CLK_MISC2, clk_cells); - clks[IMX_MIPI0_I2C1_CLK] = imx_clk_scu("mipi0_i2c1_clk", IMX_SC_R_MIPI_0_I2C_1, IMX_SC_PM_CLK_MISC2, clk_cells); - clks[IMX_MIPI0_PWM0_CLK] = imx_clk_scu("mipi0_pwm0_clk", IMX_SC_R_MIPI_0_PWM_0, IMX_SC_PM_CLK_PER, clk_cells); - clks[IMX_MIPI1_LVDS_PIXEL_CLK] = imx_clk_scu("mipi1_lvds_pixel_clk", IMX_SC_R_LVDS_1, IMX_SC_PM_CLK_MISC2, clk_cells); - clks[IMX_MIPI1_LVDS_BYPASS_CLK] = imx_clk_scu("mipi1_lvds_bypass_clk", IMX_SC_R_LVDS_1, IMX_SC_PM_CLK_BYPASS, clk_cells); - clks[IMX_MIPI1_LVDS_PHY_CLK] = imx_clk_scu("mipi1_lvds_phy_clk", IMX_SC_R_LVDS_1, IMX_SC_PM_CLK_MISC3, clk_cells); - clks[IMX_MIPI1_I2C0_CLK] = imx_clk_scu("mipi1_i2c0_clk", IMX_SC_R_MIPI_1_I2C_0, IMX_SC_PM_CLK_MISC2, clk_cells); - clks[IMX_MIPI1_I2C1_CLK] = imx_clk_scu("mipi1_i2c1_clk", IMX_SC_R_MIPI_1_I2C_1, IMX_SC_PM_CLK_MISC2, clk_cells); - clks[IMX_MIPI1_PWM0_CLK] = imx_clk_scu("mipi1_pwm0_clk", IMX_SC_R_MIPI_1_PWM_0, IMX_SC_PM_CLK_PER, clk_cells); + imx_clk_scu("mipi0_bypass_clk", IMX_SC_R_MIPI_0, IMX_SC_PM_CLK_BYPASS); + imx_clk_scu("mipi0_pixel_clk", IMX_SC_R_MIPI_0, IMX_SC_PM_CLK_PER); + imx_clk_scu("mipi0_lvds_pixel_clk", IMX_SC_R_LVDS_0, IMX_SC_PM_CLK_MISC2); + imx_clk_scu("mipi0_lvds_bypass_clk", IMX_SC_R_LVDS_0, IMX_SC_PM_CLK_BYPASS); + imx_clk_scu("mipi0_lvds_phy_clk", IMX_SC_R_LVDS_0, IMX_SC_PM_CLK_MISC3); + imx_clk_scu2("mipi0_dsi_tx_esc_clk", mipi_sels, ARRAY_SIZE(mipi_sels), IMX_SC_R_MIPI_0, IMX_SC_PM_CLK_MST_BUS); + imx_clk_scu2("mipi0_dsi_rx_esc_clk", mipi_sels, ARRAY_SIZE(mipi_sels), IMX_SC_R_MIPI_0, IMX_SC_PM_CLK_SLV_BUS); + imx_clk_scu2("mipi0_dsi_phy_clk", mipi_sels, ARRAY_SIZE(mipi_sels), IMX_SC_R_MIPI_0, IMX_SC_PM_CLK_PHY); + imx_clk_scu("mipi0_i2c0_clk", IMX_SC_R_MIPI_0_I2C_0, IMX_SC_PM_CLK_MISC2); + imx_clk_scu("mipi0_i2c1_clk", IMX_SC_R_MIPI_0_I2C_1, IMX_SC_PM_CLK_MISC2); + imx_clk_scu("mipi0_pwm0_clk", IMX_SC_R_MIPI_0_PWM_0, IMX_SC_PM_CLK_PER); + + imx_clk_scu("mipi1_bypass_clk", IMX_SC_R_MIPI_1, IMX_SC_PM_CLK_BYPASS); + imx_clk_scu("mipi1_pixel_clk", IMX_SC_R_MIPI_1, IMX_SC_PM_CLK_PER); + imx_clk_scu("mipi1_lvds_pixel_clk", IMX_SC_R_LVDS_1, IMX_SC_PM_CLK_MISC2); + imx_clk_scu("mipi1_lvds_bypass_clk", IMX_SC_R_LVDS_1, IMX_SC_PM_CLK_BYPASS); + imx_clk_scu("mipi1_lvds_phy_clk", IMX_SC_R_LVDS_1, IMX_SC_PM_CLK_MISC3); + + imx_clk_scu2("mipi1_dsi_tx_esc_clk", mipi_sels, ARRAY_SIZE(mipi_sels), IMX_SC_R_MIPI_1, IMX_SC_PM_CLK_MST_BUS); + imx_clk_scu2("mipi1_dsi_rx_esc_clk", mipi_sels, ARRAY_SIZE(mipi_sels), IMX_SC_R_MIPI_1, IMX_SC_PM_CLK_SLV_BUS); + imx_clk_scu2("mipi1_dsi_phy_clk", mipi_sels, ARRAY_SIZE(mipi_sels), IMX_SC_R_MIPI_1, IMX_SC_PM_CLK_PHY); + imx_clk_scu("mipi1_i2c0_clk", IMX_SC_R_MIPI_1_I2C_0, IMX_SC_PM_CLK_MISC2); + imx_clk_scu("mipi1_i2c1_clk", IMX_SC_R_MIPI_1_I2C_1, IMX_SC_PM_CLK_MISC2); + imx_clk_scu("mipi1_pwm0_clk", IMX_SC_R_MIPI_1_PWM_0, IMX_SC_PM_CLK_PER); + + imx_clk_scu("lvds0_i2c0_clk", IMX_SC_R_LVDS_0_I2C_0, IMX_SC_PM_CLK_PER); + imx_clk_scu("lvds0_i2c1_clk", IMX_SC_R_LVDS_0_I2C_1, IMX_SC_PM_CLK_PER); + imx_clk_scu("lvds0_pwm0_clk", IMX_SC_R_LVDS_0_PWM_0, IMX_SC_PM_CLK_PER); + + imx_clk_scu("lvds1_i2c0_clk", IMX_SC_R_LVDS_1_I2C_0, IMX_SC_PM_CLK_PER); + imx_clk_scu("lvds1_i2c1_clk", IMX_SC_R_LVDS_1_I2C_1, IMX_SC_PM_CLK_PER); + imx_clk_scu("lvds1_pwm0_clk", IMX_SC_R_LVDS_1_PWM_0, IMX_SC_PM_CLK_PER); /* MIPI CSI SS */ - clks[IMX_CSI0_CORE_CLK] = imx_clk_scu("mipi_csi0_core_clk", IMX_SC_R_CSI_0, IMX_SC_PM_CLK_PER, clk_cells); - clks[IMX_CSI0_ESC_CLK] = imx_clk_scu("mipi_csi0_esc_clk", IMX_SC_R_CSI_0, IMX_SC_PM_CLK_MISC, clk_cells); - clks[IMX_CSI0_I2C0_CLK] = imx_clk_scu("mipi_csi0_i2c0_clk", IMX_SC_R_CSI_0_I2C_0, IMX_SC_PM_CLK_PER, clk_cells); - clks[IMX_CSI0_PWM0_CLK] = imx_clk_scu("mipi_csi0_pwm0_clk", IMX_SC_R_CSI_0_PWM_0, IMX_SC_PM_CLK_PER, clk_cells); + imx_clk_scu("mipi_csi0_core_clk", IMX_SC_R_CSI_0, IMX_SC_PM_CLK_PER); + imx_clk_scu("mipi_csi0_esc_clk", IMX_SC_R_CSI_0, IMX_SC_PM_CLK_MISC); + imx_clk_scu("mipi_csi0_i2c0_clk", IMX_SC_R_CSI_0_I2C_0, IMX_SC_PM_CLK_PER); + imx_clk_scu("mipi_csi0_pwm0_clk", IMX_SC_R_CSI_0_PWM_0, IMX_SC_PM_CLK_PER); + imx_clk_scu("mipi_csi1_core_clk", IMX_SC_R_CSI_1, IMX_SC_PM_CLK_PER); + imx_clk_scu("mipi_csi1_esc_clk", IMX_SC_R_CSI_1, IMX_SC_PM_CLK_MISC); + imx_clk_scu("mipi_csi1_i2c0_clk", IMX_SC_R_CSI_1_I2C_0, IMX_SC_PM_CLK_PER); + imx_clk_scu("mipi_csi1_pwm0_clk", IMX_SC_R_CSI_1_PWM_0, IMX_SC_PM_CLK_PER); + + /* Parallel Interface SS */ + imx_clk_scu("pi_dpll_clk", IMX_SC_R_PI_0_PLL, IMX_SC_PM_CLK_PLL); + imx_clk_scu2("pi_per_div_clk", pi_pll0_sels, ARRAY_SIZE(pi_pll0_sels), IMX_SC_R_PI_0, IMX_SC_PM_CLK_PER); + imx_clk_scu("pi_mclk_div_clk", IMX_SC_R_PI_0, IMX_SC_PM_CLK_MISC0); + imx_clk_scu("pi_i2c0_div_clk", IMX_SC_R_PI_0_I2C_0, IMX_SC_PM_CLK_PER); /* GPU SS */ - clks[IMX_GPU0_CORE_CLK] = imx_clk_scu("gpu_core0_clk", IMX_SC_R_GPU_0_PID0, IMX_SC_PM_CLK_PER, clk_cells); - clks[IMX_GPU0_SHADER_CLK] = imx_clk_scu("gpu_shader0_clk", IMX_SC_R_GPU_0_PID0, IMX_SC_PM_CLK_MISC, clk_cells); - - for (i = 0; i < clk_data->num; i++) { - if (IS_ERR(clks[i])) - pr_warn("i.MX clk %u: register failed with %ld\n", - i, PTR_ERR(clks[i])); - } - - if (clk_cells == 2) { - ret = of_clk_add_hw_provider(ccm_node, imx_scu_of_clk_src_get, imx_scu_clks); - if (ret) - imx_clk_scu_unregister(); - } else { - /* - * legacy binding code path doesn't unregister here because - * it will be removed later. - */ - ret = of_clk_add_hw_provider(ccm_node, of_clk_hw_onecell_get, clk_data); - } + imx_clk_scu("gpu_core0_clk", IMX_SC_R_GPU_0_PID0, IMX_SC_PM_CLK_PER); + imx_clk_scu("gpu_shader0_clk", IMX_SC_R_GPU_0_PID0, IMX_SC_PM_CLK_MISC); + + imx_clk_scu("gpu_core1_clk", IMX_SC_R_GPU_1_PID0, IMX_SC_PM_CLK_PER); + imx_clk_scu("gpu_shader1_clk", IMX_SC_R_GPU_1_PID0, IMX_SC_PM_CLK_MISC); + + /* CM40 SS */ + imx_clk_scu("cm40_i2c_div", IMX_SC_R_M4_0_I2C, IMX_SC_PM_CLK_PER); + imx_clk_scu("cm40_lpuart_div", IMX_SC_R_M4_0_UART, IMX_SC_PM_CLK_PER); + + /* CM41 SS */ + imx_clk_scu("cm41_i2c_div", IMX_SC_R_M4_1_I2C, IMX_SC_PM_CLK_PER); + + /* HDMI TX SS */ + imx_clk_scu("hdmi_dig_pll_clk", IMX_SC_R_HDMI_PLL_0, IMX_SC_PM_CLK_PLL); + imx_clk_scu("hdmi_av_pll_clk", IMX_SC_R_HDMI_PLL_1, IMX_SC_PM_CLK_PLL); + imx_clk_scu2("hdmi_pixel_mux_clk", hdmi_sels, ARRAY_SIZE(hdmi_sels), IMX_SC_R_HDMI, IMX_SC_PM_CLK_MISC0); + imx_clk_scu2("hdmi_pixel_link_clk", hdmi_sels, ARRAY_SIZE(hdmi_sels), IMX_SC_R_HDMI, IMX_SC_PM_CLK_MISC1); + imx_clk_scu("hdmi_ipg_clk", IMX_SC_R_HDMI, IMX_SC_PM_CLK_MISC4); + imx_clk_scu("hdmi_i2c0_clk", IMX_SC_R_HDMI_I2C_0, IMX_SC_PM_CLK_MISC2); + imx_clk_scu("hdmi_hdp_core_clk", IMX_SC_R_HDMI, IMX_SC_PM_CLK_MISC2); + imx_clk_scu2("hdmi_pxl_clk", hdmi_sels, ARRAY_SIZE(hdmi_sels), IMX_SC_R_HDMI, IMX_SC_PM_CLK_MISC3); + imx_clk_scu("hdmi_i2s_bypass_clk", IMX_SC_R_HDMI_I2S, IMX_SC_PM_CLK_BYPASS); + imx_clk_scu("hdmi_i2s_clk", IMX_SC_R_HDMI_I2S, IMX_SC_PM_CLK_MISC0); + + /* HDMI RX SS */ + imx_clk_scu("hdmi_rx_i2s_bypass_clk", IMX_SC_R_HDMI_RX_BYPASS, IMX_SC_PM_CLK_MISC0); + imx_clk_scu("hdmi_rx_spdif_bypass_clk", IMX_SC_R_HDMI_RX_BYPASS, IMX_SC_PM_CLK_MISC1); + imx_clk_scu("hdmi_rx_bypass_clk", IMX_SC_R_HDMI_RX_BYPASS, IMX_SC_PM_CLK_MISC2); + imx_clk_scu("hdmi_rx_i2c0_clk", IMX_SC_R_HDMI_RX_I2C_0, IMX_SC_PM_CLK_MISC2); + imx_clk_scu("hdmi_rx_pwm_clk", IMX_SC_R_HDMI_RX_PWM_0, IMX_SC_PM_CLK_MISC2); + imx_clk_scu("hdmi_rx_spdif_clk", IMX_SC_R_HDMI_RX, IMX_SC_PM_CLK_MISC0); + imx_clk_scu2("hdmi_rx_hd_ref_clk", hdmi_rx_sels, ARRAY_SIZE(hdmi_rx_sels), IMX_SC_R_HDMI_RX, IMX_SC_PM_CLK_MISC1); + imx_clk_scu2("hdmi_rx_hd_core_clk", hdmi_rx_sels, ARRAY_SIZE(hdmi_rx_sels), IMX_SC_R_HDMI_RX, IMX_SC_PM_CLK_MISC2); + imx_clk_scu2("hdmi_rx_pxl_clk", hdmi_rx_sels, ARRAY_SIZE(hdmi_rx_sels), IMX_SC_R_HDMI_RX, IMX_SC_PM_CLK_MISC3); + imx_clk_scu("hdmi_rx_i2s_clk", IMX_SC_R_HDMI_RX, IMX_SC_PM_CLK_MISC4); + + ret = of_clk_add_hw_provider(ccm_node, imx_scu_of_clk_src_get, imx_scu_clks); + if (ret) + imx_clk_scu_unregister(); return ret; } static const struct of_device_id imx8qxp_match[] = { { .compatible = "fsl,scu-clk", }, - { .compatible = "fsl,imx8qxp-clk", }, + { .compatible = "fsl,imx8qxp-clk", &imx_clk_scu_rsrc_imx8qxp, }, + { .compatible = "fsl,imx8qm-clk", &imx_clk_scu_rsrc_imx8qm, }, { /* sentinel */ } }; diff --git a/drivers/clk/imx/clk-scu.c b/drivers/clk/imx/clk-scu.c index f89b4da10e80..083da31dc3ea 100644 --- a/drivers/clk/imx/clk-scu.c +++ b/drivers/clk/imx/clk-scu.c @@ -1,11 +1,12 @@ // SPDX-License-Identifier: GPL-2.0+ /* - * Copyright 2018 NXP + * Copyright 2018-2021 NXP * Dong Aisheng <aisheng.dong@nxp.com> */ #include <dt-bindings/firmware/imx/rsrc.h> #include <linux/arm-smccc.h> +#include <linux/bsearch.h> #include <linux/clk-provider.h> #include <linux/err.h> #include <linux/of_platform.h> @@ -22,6 +23,7 @@ static struct imx_sc_ipc *ccm_ipc_handle; static struct device_node *pd_np; static struct platform_driver imx_clk_scu_driver; +static const struct imx_clk_scu_rsrc_table *rsrc_table; struct imx_scu_clk_node { const char *name; @@ -48,11 +50,29 @@ struct clk_scu { u8 clk_type; /* for state save&restore */ + struct clk_hw *parent; + u8 parent_index; bool is_enabled; u32 rate; }; /* + * struct clk_gpr_scu - Description of one SCU GPR clock + * @hw: the common clk_hw + * @rsrc_id: resource ID of this SCU clock + * @gpr_id: GPR ID index to control the divider + */ +struct clk_gpr_scu { + struct clk_hw hw; + u16 rsrc_id; + u8 gpr_id; + u8 flags; + bool gate_invert; +}; + +#define to_clk_gpr_scu(_hw) container_of(_hw, struct clk_gpr_scu, hw) + +/* * struct imx_sc_msg_req_set_clock_rate - clock set rate protocol * @hdr: SCU protocol header * @rate: rate to set @@ -151,7 +171,26 @@ static inline struct clk_scu *to_clk_scu(struct clk_hw *hw) return container_of(hw, struct clk_scu, hw); } -int imx_clk_scu_init(struct device_node *np) +static inline int imx_scu_clk_search_cmp(const void *rsrc, const void *rsrc_p) +{ + return *(u32 *)rsrc - *(u32 *)rsrc_p; +} + +static bool imx_scu_clk_is_valid(u32 rsrc_id) +{ + void *p; + + if (!rsrc_table) + return true; + + p = bsearch(&rsrc_id, rsrc_table->rsrc, rsrc_table->num, + sizeof(rsrc_table->rsrc[0]), imx_scu_clk_search_cmp); + + return p != NULL; +} + +int imx_clk_scu_init(struct device_node *np, + const struct imx_clk_scu_rsrc_table *data) { u32 clk_cells; int ret, i; @@ -170,6 +209,8 @@ int imx_clk_scu_init(struct device_node *np) pd_np = of_find_compatible_node(NULL, NULL, "fsl,scu-pd"); if (!pd_np) return -EINVAL; + + rsrc_table = data; } return platform_driver_register(&imx_clk_scu_driver); @@ -234,8 +275,10 @@ static int clk_scu_atf_set_cpu_rate(struct clk_hw *hw, unsigned long rate, struct arm_smccc_res res; unsigned long cluster_id; - if (clk->rsrc_id == IMX_SC_R_A35) + if (clk->rsrc_id == IMX_SC_R_A35 || clk->rsrc_id == IMX_SC_R_A53) cluster_id = 0; + else if (clk->rsrc_id == IMX_SC_R_A72) + cluster_id = 1; else return -EINVAL; @@ -296,6 +339,8 @@ static u8 clk_scu_get_parent(struct clk_hw *hw) return 0; } + clk->parent_index = msg.data.resp.parent; + return msg.data.resp.parent; } @@ -304,6 +349,7 @@ static int clk_scu_set_parent(struct clk_hw *hw, u8 index) struct clk_scu *clk = to_clk_scu(hw); struct imx_sc_msg_set_clock_parent msg; struct imx_sc_rpc_msg *hdr = &msg.hdr; + int ret; hdr->ver = IMX_SC_RPC_VERSION; hdr->svc = IMX_SC_RPC_SVC_PM; @@ -314,7 +360,16 @@ static int clk_scu_set_parent(struct clk_hw *hw, u8 index) msg.clk = clk->clk_type; msg.parent = index; - return imx_scu_call_rpc(ccm_ipc_handle, &msg, true); + ret = imx_scu_call_rpc(ccm_ipc_handle, &msg, true); + if (ret) { + pr_err("%s: failed to set clock parent %d\n", + clk_hw_get_name(hw), ret); + return ret; + } + + clk->parent_index = index; + + return 0; } static int sc_pm_clock_enable(struct imx_sc_ipc *ipc, u16 resource, @@ -386,6 +441,12 @@ static const struct clk_ops clk_scu_cpu_ops = { .unprepare = clk_scu_unprepare, }; +static const struct clk_ops clk_scu_pi_ops = { + .recalc_rate = clk_scu_recalc_rate, + .round_rate = clk_scu_round_rate, + .set_rate = clk_scu_set_rate, +}; + struct clk_hw *__imx_clk_scu(struct device *dev, const char *name, const char * const *parents, int num_parents, u32 rsrc_id, u8 clk_type) @@ -404,8 +465,10 @@ struct clk_hw *__imx_clk_scu(struct device *dev, const char *name, init.name = name; init.ops = &clk_scu_ops; - if (rsrc_id == IMX_SC_R_A35) + if (rsrc_id == IMX_SC_R_A35 || rsrc_id == IMX_SC_R_A53 || rsrc_id == IMX_SC_R_A72) init.ops = &clk_scu_cpu_ops; + else if (rsrc_id == IMX_SC_R_PI_0_PLL) + init.ops = &clk_scu_pi_ops; else init.ops = &clk_scu_ops; init.parent_names = parents; @@ -458,15 +521,19 @@ static int imx_clk_scu_probe(struct platform_device *pdev) struct clk_hw *hw; int ret; - pm_runtime_set_suspended(dev); - pm_runtime_set_autosuspend_delay(dev, 50); - pm_runtime_use_autosuspend(&pdev->dev); - pm_runtime_enable(dev); - - ret = pm_runtime_get_sync(dev); - if (ret) { - pm_runtime_disable(dev); - return ret; + if (!((clk->rsrc == IMX_SC_R_A35) || (clk->rsrc == IMX_SC_R_A53) || + (clk->rsrc == IMX_SC_R_A72))) { + pm_runtime_set_suspended(dev); + pm_runtime_set_autosuspend_delay(dev, 50); + pm_runtime_use_autosuspend(&pdev->dev); + pm_runtime_enable(dev); + + ret = pm_runtime_get_sync(dev); + if (ret) { + pm_genpd_remove_device(dev); + pm_runtime_disable(dev); + return ret; + } } hw = __imx_clk_scu(dev, clk->name, clk->parents, clk->num_parents, @@ -479,8 +546,11 @@ static int imx_clk_scu_probe(struct platform_device *pdev) clk->hw = hw; list_add_tail(&clk->node, &imx_scu_clks[clk->rsrc]); - pm_runtime_mark_last_busy(&pdev->dev); - pm_runtime_put_autosuspend(&pdev->dev); + if (!((clk->rsrc == IMX_SC_R_A35) || (clk->rsrc == IMX_SC_R_A53) || + (clk->rsrc == IMX_SC_R_A72))) { + pm_runtime_mark_last_busy(&pdev->dev); + pm_runtime_put_autosuspend(&pdev->dev); + } dev_dbg(dev, "register SCU clock rsrc:%d type:%d\n", clk->rsrc, clk->clk_type); @@ -491,10 +561,28 @@ static int imx_clk_scu_probe(struct platform_device *pdev) static int __maybe_unused imx_clk_scu_suspend(struct device *dev) { struct clk_scu *clk = dev_get_drvdata(dev); + u32 rsrc_id = clk->rsrc_id; + + if ((rsrc_id == IMX_SC_R_A35) || (rsrc_id == IMX_SC_R_A53) || + (rsrc_id == IMX_SC_R_A72)) + return 0; + + clk->parent = clk_hw_get_parent(&clk->hw); - clk->rate = clk_hw_get_rate(&clk->hw); + /* DC SS needs to handle bypass clock using non-cached clock rate */ + if (clk->rsrc_id == IMX_SC_R_DC_0_VIDEO0 || + clk->rsrc_id == IMX_SC_R_DC_0_VIDEO1 || + clk->rsrc_id == IMX_SC_R_DC_1_VIDEO0 || + clk->rsrc_id == IMX_SC_R_DC_1_VIDEO1) + clk->rate = clk_scu_recalc_rate(&clk->hw, 0); + else + clk->rate = clk_hw_get_rate(&clk->hw); clk->is_enabled = clk_hw_is_enabled(&clk->hw); + if (clk->parent) + dev_dbg(dev, "save parent %s idx %u\n", clk_hw_get_name(clk->parent), + clk->parent_index); + if (clk->rate) dev_dbg(dev, "save rate %d\n", clk->rate); @@ -507,15 +595,27 @@ static int __maybe_unused imx_clk_scu_suspend(struct device *dev) static int __maybe_unused imx_clk_scu_resume(struct device *dev) { struct clk_scu *clk = dev_get_drvdata(dev); + u32 rsrc_id = clk->rsrc_id; int ret = 0; + if ((rsrc_id == IMX_SC_R_A35) || (rsrc_id == IMX_SC_R_A53) || + (rsrc_id == IMX_SC_R_A72)) + return 0; + + if (clk->parent) { + ret = clk_scu_set_parent(&clk->hw, clk->parent_index); + dev_dbg(dev, "restore parent %s idx %u %s\n", + clk_hw_get_name(clk->parent), + clk->parent_index, !ret ? "success" : "failed"); + } + if (clk->rate) { ret = clk_scu_set_rate(&clk->hw, clk->rate, 0); dev_dbg(dev, "restore rate %d %s\n", clk->rate, !ret ? "success" : "failed"); } - if (clk->is_enabled) { + if (clk->is_enabled && rsrc_id != IMX_SC_R_PI_0_PLL) { ret = clk_scu_prepare(&clk->hw); dev_dbg(dev, "restore enabled state %s\n", !ret ? "success" : "failed"); @@ -567,6 +667,9 @@ struct clk_hw *imx_clk_scu_alloc_dev(const char *name, struct platform_device *pdev; int ret; + if (!imx_scu_clk_is_valid(rsrc_id)) + return ERR_PTR(-EINVAL); + pdev = platform_device_alloc(name, PLATFORM_DEVID_NONE); if (!pdev) { pr_err("%s: failed to allocate scu clk dev rsrc %d type %d\n", @@ -605,3 +708,176 @@ void imx_clk_scu_unregister(void) } } } + +static unsigned long clk_gpr_div_scu_recalc_rate(struct clk_hw *hw, + unsigned long parent_rate) +{ + struct clk_gpr_scu *clk = to_clk_gpr_scu(hw); + unsigned long rate = 0; + u32 val; + int err; + + err = imx_sc_misc_get_control(ccm_ipc_handle, clk->rsrc_id, + clk->gpr_id, &val); + + rate = val ? parent_rate / 2 : parent_rate; + + return err ? 0 : rate; +} + +static long clk_gpr_div_scu_round_rate(struct clk_hw *hw, unsigned long rate, + unsigned long *prate) +{ + if (rate < *prate) + rate = *prate / 2; + else + rate = *prate; + + return rate; +} + +static int clk_gpr_div_scu_set_rate(struct clk_hw *hw, unsigned long rate, + unsigned long parent_rate) +{ + struct clk_gpr_scu *clk = to_clk_gpr_scu(hw); + uint32_t val; + int err; + + val = (rate < parent_rate) ? 1 : 0; + err = imx_sc_misc_set_control(ccm_ipc_handle, clk->rsrc_id, + clk->gpr_id, val); + + return err ? -EINVAL : 0; +} + +static const struct clk_ops clk_gpr_div_scu_ops = { + .recalc_rate = clk_gpr_div_scu_recalc_rate, + .round_rate = clk_gpr_div_scu_round_rate, + .set_rate = clk_gpr_div_scu_set_rate, +}; + +static u8 clk_gpr_mux_scu_get_parent(struct clk_hw *hw) +{ + struct clk_gpr_scu *clk = to_clk_gpr_scu(hw); + u32 val = 0; + + imx_sc_misc_get_control(ccm_ipc_handle, clk->rsrc_id, + clk->gpr_id, &val); + + return (u8)val; +} + +static int clk_gpr_mux_scu_set_parent(struct clk_hw *hw, u8 index) +{ + struct clk_gpr_scu *clk = to_clk_gpr_scu(hw); + + return imx_sc_misc_set_control(ccm_ipc_handle, clk->rsrc_id, + clk->gpr_id, index); +} + +static const struct clk_ops clk_gpr_mux_scu_ops = { + .get_parent = clk_gpr_mux_scu_get_parent, + .set_parent = clk_gpr_mux_scu_set_parent, +}; + +static int clk_gpr_gate_scu_prepare(struct clk_hw *hw) +{ + struct clk_gpr_scu *clk = to_clk_gpr_scu(hw); + + return imx_sc_misc_set_control(ccm_ipc_handle, clk->rsrc_id, + clk->gpr_id, !clk->gate_invert); +} + +static void clk_gpr_gate_scu_unprepare(struct clk_hw *hw) +{ + struct clk_gpr_scu *clk = to_clk_gpr_scu(hw); + int ret; + + ret = imx_sc_misc_set_control(ccm_ipc_handle, clk->rsrc_id, + clk->gpr_id, clk->gate_invert); + if (ret) + pr_err("%s: clk unprepare failed %d\n", clk_hw_get_name(hw), + ret); +} + +static int clk_gpr_gate_scu_is_prepared(struct clk_hw *hw) +{ + struct clk_gpr_scu *clk = to_clk_gpr_scu(hw); + int ret; + u32 val; + + ret = imx_sc_misc_get_control(ccm_ipc_handle, clk->rsrc_id, + clk->gpr_id, &val); + if (ret) + return ret; + + return clk->gate_invert ? !val : val; +} + +static const struct clk_ops clk_gpr_gate_scu_ops = { + .prepare = clk_gpr_gate_scu_prepare, + .unprepare = clk_gpr_gate_scu_unprepare, + .is_prepared = clk_gpr_gate_scu_is_prepared, +}; + +struct clk_hw *__imx_clk_gpr_scu(const char *name, const char * const *parent_name, + int num_parents, u32 rsrc_id, u8 gpr_id, u8 flags, + bool invert) +{ + struct imx_scu_clk_node *clk_node; + struct clk_gpr_scu *clk; + struct clk_hw *hw; + struct clk_init_data init; + int ret; + + if (rsrc_id >= IMX_SC_R_LAST || gpr_id >= IMX_SC_C_LAST) + return ERR_PTR(-EINVAL); + + clk_node = kzalloc(sizeof(*clk_node), GFP_KERNEL); + if (!clk_node) + return ERR_PTR(-ENOMEM); + + if (!imx_scu_clk_is_valid(rsrc_id)) + return ERR_PTR(-EINVAL); + + clk = kzalloc(sizeof(*clk), GFP_KERNEL); + if (!clk) { + kfree(clk_node); + return ERR_PTR(-ENOMEM); + } + + clk->rsrc_id = rsrc_id; + clk->gpr_id = gpr_id; + clk->flags = flags; + clk->gate_invert = invert; + + if (flags & IMX_SCU_GPR_CLK_GATE) + init.ops = &clk_gpr_gate_scu_ops; + + if (flags & IMX_SCU_GPR_CLK_DIV) + init.ops = &clk_gpr_div_scu_ops; + + if (flags & IMX_SCU_GPR_CLK_MUX) + init.ops = &clk_gpr_mux_scu_ops; + + init.flags = 0; + init.name = name; + init.parent_names = parent_name; + init.num_parents = num_parents; + + clk->hw.init = &init; + + hw = &clk->hw; + ret = clk_hw_register(NULL, hw); + if (ret) { + kfree(clk); + kfree(clk_node); + hw = ERR_PTR(ret); + } else { + clk_node->hw = hw; + clk_node->clk_type = gpr_id; + list_add_tail(&clk_node->node, &imx_scu_clks[rsrc_id]); + } + + return hw; +} diff --git a/drivers/clk/imx/clk-scu.h b/drivers/clk/imx/clk-scu.h index e8352164923e..22156e93b85d 100644 --- a/drivers/clk/imx/clk-scu.h +++ b/drivers/clk/imx/clk-scu.h @@ -1,6 +1,6 @@ /* SPDX-License-Identifier: GPL-2.0+ */ /* - * Copyright 2018 NXP + * Copyright 2018-2021 NXP * Dong Aisheng <aisheng.dong@nxp.com> */ @@ -10,10 +10,22 @@ #include <linux/firmware/imx/sci.h> #include <linux/of.h> +#define IMX_SCU_GPR_CLK_GATE BIT(0) +#define IMX_SCU_GPR_CLK_DIV BIT(1) +#define IMX_SCU_GPR_CLK_MUX BIT(2) + +struct imx_clk_scu_rsrc_table { + const u32 *rsrc; + u8 num; +}; + extern struct list_head imx_scu_clks[]; extern const struct dev_pm_ops imx_clk_lpcg_scu_pm_ops; +extern const struct imx_clk_scu_rsrc_table imx_clk_scu_rsrc_imx8qxp; +extern const struct imx_clk_scu_rsrc_table imx_clk_scu_rsrc_imx8qm; -int imx_clk_scu_init(struct device_node *np); +int imx_clk_scu_init(struct device_node *np, + const struct imx_clk_scu_rsrc_table *data); struct clk_hw *imx_scu_of_clk_src_get(struct of_phandle_args *clkspec, void *data); struct clk_hw *imx_clk_scu_alloc_dev(const char *name, @@ -31,23 +43,20 @@ struct clk_hw *__imx_clk_lpcg_scu(struct device *dev, const char *name, void __iomem *reg, u8 bit_idx, bool hw_gate); void imx_clk_lpcg_scu_unregister(struct clk_hw *hw); +struct clk_hw *__imx_clk_gpr_scu(const char *name, const char * const *parent_name, + int num_parents, u32 rsrc_id, u8 gpr_id, u8 flags, + bool invert); + static inline struct clk_hw *imx_clk_scu(const char *name, u32 rsrc_id, - u8 clk_type, u8 clk_cells) + u8 clk_type) { - if (clk_cells == 2) - return imx_clk_scu_alloc_dev(name, NULL, 0, rsrc_id, clk_type); - else - return __imx_clk_scu(NULL, name, NULL, 0, rsrc_id, clk_type); + return imx_clk_scu_alloc_dev(name, NULL, 0, rsrc_id, clk_type); } static inline struct clk_hw *imx_clk_scu2(const char *name, const char * const *parents, - int num_parents, u32 rsrc_id, u8 clk_type, - u8 clk_cells) + int num_parents, u32 rsrc_id, u8 clk_type) { - if (clk_cells == 2) - return imx_clk_scu_alloc_dev(name, parents, num_parents, rsrc_id, clk_type); - else - return __imx_clk_scu(NULL, name, parents, num_parents, rsrc_id, clk_type); + return imx_clk_scu_alloc_dev(name, parents, num_parents, rsrc_id, clk_type); } static inline struct clk_hw *imx_clk_lpcg_scu_dev(struct device *dev, const char *name, @@ -65,4 +74,25 @@ static inline struct clk_hw *imx_clk_lpcg_scu(const char *name, const char *pare return __imx_clk_lpcg_scu(NULL, name, parent_name, flags, reg, bit_idx, hw_gate); } + +static inline struct clk_hw *imx_clk_gate_gpr_scu(const char *name, const char *parent_name, + u32 rsrc_id, u8 gpr_id, bool invert) +{ + return __imx_clk_gpr_scu(name, &parent_name, 1, rsrc_id, gpr_id, + IMX_SCU_GPR_CLK_GATE, invert); +} + +static inline struct clk_hw *imx_clk_divider_gpr_scu(const char *name, const char *parent_name, + u32 rsrc_id, u8 gpr_id) +{ + return __imx_clk_gpr_scu(name, &parent_name, 1, rsrc_id, gpr_id, + IMX_SCU_GPR_CLK_DIV, 0); +} + +static inline struct clk_hw *imx_clk_mux_gpr_scu(const char *name, const char * const *parent_names, + int num_parents, u32 rsrc_id, u8 gpr_id) +{ + return __imx_clk_gpr_scu(name, parent_names, num_parents, rsrc_id, + gpr_id, IMX_SCU_GPR_CLK_MUX, 0); +} #endif diff --git a/drivers/clk/ingenic/Kconfig b/drivers/clk/ingenic/Kconfig index 580b0cf69ed5..898f1bc478c9 100644 --- a/drivers/clk/ingenic/Kconfig +++ b/drivers/clk/ingenic/Kconfig @@ -25,6 +25,16 @@ config INGENIC_CGU_JZ4725B If building for a JZ4725B SoC, you want to say Y here. +config INGENIC_CGU_JZ4760 + bool "Ingenic JZ4760 CGU driver" + default MACH_JZ4760 + select INGENIC_CGU_COMMON + help + Support the clocks provided by the CGU hardware on Ingenic JZ4760 + and compatible SoCs. + + If building for a JZ4760 SoC, you want to say Y here. + config INGENIC_CGU_JZ4770 bool "Ingenic JZ4770 CGU driver" default MACH_JZ4770 diff --git a/drivers/clk/ingenic/Makefile b/drivers/clk/ingenic/Makefile index aaa4bffe03c6..9edfaf4610b9 100644 --- a/drivers/clk/ingenic/Makefile +++ b/drivers/clk/ingenic/Makefile @@ -2,6 +2,7 @@ obj-$(CONFIG_INGENIC_CGU_COMMON) += cgu.o pm.o obj-$(CONFIG_INGENIC_CGU_JZ4740) += jz4740-cgu.o obj-$(CONFIG_INGENIC_CGU_JZ4725B) += jz4725b-cgu.o +obj-$(CONFIG_INGENIC_CGU_JZ4760) += jz4760-cgu.o obj-$(CONFIG_INGENIC_CGU_JZ4770) += jz4770-cgu.o obj-$(CONFIG_INGENIC_CGU_JZ4780) += jz4780-cgu.o obj-$(CONFIG_INGENIC_CGU_X1000) += x1000-cgu.o diff --git a/drivers/clk/ingenic/cgu.c b/drivers/clk/ingenic/cgu.c index c8e9cb6c8e39..266c7595d330 100644 --- a/drivers/clk/ingenic/cgu.c +++ b/drivers/clk/ingenic/cgu.c @@ -99,13 +99,14 @@ ingenic_pll_recalc_rate(struct clk_hw *hw, unsigned long parent_rate) od_enc = ctl >> pll_info->od_shift; od_enc &= GENMASK(pll_info->od_bits - 1, 0); - ctl = readl(cgu->base + pll_info->bypass_reg); + if (pll_info->bypass_bit >= 0) { + ctl = readl(cgu->base + pll_info->bypass_reg); - bypass = !pll_info->no_bypass_bit && - !!(ctl & BIT(pll_info->bypass_bit)); + bypass = !!(ctl & BIT(pll_info->bypass_bit)); - if (bypass) - return parent_rate; + if (bypass) + return parent_rate; + } for (od = 0; od < pll_info->od_max; od++) { if (pll_info->od_encoding[od] == od_enc) @@ -118,28 +119,42 @@ ingenic_pll_recalc_rate(struct clk_hw *hw, unsigned long parent_rate) n * od); } -static unsigned long -ingenic_pll_calc(const struct ingenic_cgu_clk_info *clk_info, - unsigned long rate, unsigned long parent_rate, - unsigned *pm, unsigned *pn, unsigned *pod) +static void +ingenic_pll_calc_m_n_od(const struct ingenic_cgu_pll_info *pll_info, + unsigned long rate, unsigned long parent_rate, + unsigned int *pm, unsigned int *pn, unsigned int *pod) { - const struct ingenic_cgu_pll_info *pll_info; - unsigned m, n, od; - - pll_info = &clk_info->pll; - od = 1; + unsigned int m, n, od = 1; /* * The frequency after the input divider must be between 10 and 50 MHz. * The highest divider yields the best resolution. */ n = parent_rate / (10 * MHZ); - n = min_t(unsigned, n, 1 << clk_info->pll.n_bits); - n = max_t(unsigned, n, pll_info->n_offset); + n = min_t(unsigned int, n, 1 << pll_info->n_bits); + n = max_t(unsigned int, n, pll_info->n_offset); m = (rate / MHZ) * od * n / (parent_rate / MHZ); - m = min_t(unsigned, m, 1 << clk_info->pll.m_bits); - m = max_t(unsigned, m, pll_info->m_offset); + m = min_t(unsigned int, m, 1 << pll_info->m_bits); + m = max_t(unsigned int, m, pll_info->m_offset); + + *pm = m; + *pn = n; + *pod = od; +} + +static unsigned long +ingenic_pll_calc(const struct ingenic_cgu_clk_info *clk_info, + unsigned long rate, unsigned long parent_rate, + unsigned int *pm, unsigned int *pn, unsigned int *pod) +{ + const struct ingenic_cgu_pll_info *pll_info = &clk_info->pll; + unsigned int m, n, od; + + if (pll_info->calc_m_n_od) + (*pll_info->calc_m_n_od)(pll_info, rate, parent_rate, &m, &n, &od); + else + ingenic_pll_calc_m_n_od(pll_info, rate, parent_rate, &m, &n, &od); if (pm) *pm = m; @@ -225,11 +240,13 @@ static int ingenic_pll_enable(struct clk_hw *hw) u32 ctl; spin_lock_irqsave(&cgu->lock, flags); - ctl = readl(cgu->base + pll_info->bypass_reg); + if (pll_info->bypass_bit >= 0) { + ctl = readl(cgu->base + pll_info->bypass_reg); - ctl &= ~BIT(pll_info->bypass_bit); + ctl &= ~BIT(pll_info->bypass_bit); - writel(ctl, cgu->base + pll_info->bypass_reg); + writel(ctl, cgu->base + pll_info->bypass_reg); + } ctl = readl(cgu->base + pll_info->reg); @@ -369,18 +386,23 @@ ingenic_clk_recalc_rate(struct clk_hw *hw, unsigned long parent_rate) struct ingenic_cgu *cgu = ingenic_clk->cgu; unsigned long rate = parent_rate; u32 div_reg, div; + u8 parent; if (clk_info->type & CGU_CLK_DIV) { - div_reg = readl(cgu->base + clk_info->div.reg); - div = (div_reg >> clk_info->div.shift) & - GENMASK(clk_info->div.bits - 1, 0); + parent = ingenic_clk_get_parent(hw); - if (clk_info->div.div_table) - div = clk_info->div.div_table[div]; - else - div = (div + 1) * clk_info->div.div; + if (!(clk_info->div.bypass_mask & BIT(parent))) { + div_reg = readl(cgu->base + clk_info->div.reg); + div = (div_reg >> clk_info->div.shift) & + GENMASK(clk_info->div.bits - 1, 0); - rate /= div; + if (clk_info->div.div_table) + div = clk_info->div.div_table[div]; + else + div = (div + 1) * clk_info->div.div; + + rate /= div; + } } else if (clk_info->type & CGU_CLK_FIXDIV) { rate /= clk_info->fixdiv.div; } @@ -410,10 +432,16 @@ ingenic_clk_calc_hw_div(const struct ingenic_cgu_clk_info *clk_info, } static unsigned -ingenic_clk_calc_div(const struct ingenic_cgu_clk_info *clk_info, +ingenic_clk_calc_div(struct clk_hw *hw, + const struct ingenic_cgu_clk_info *clk_info, unsigned long parent_rate, unsigned long req_rate) { unsigned int div, hw_div; + u8 parent; + + parent = ingenic_clk_get_parent(hw); + if (clk_info->div.bypass_mask & BIT(parent)) + return 1; /* calculate the divide */ div = DIV_ROUND_UP(parent_rate, req_rate); @@ -448,7 +476,7 @@ ingenic_clk_round_rate(struct clk_hw *hw, unsigned long req_rate, unsigned int div = 1; if (clk_info->type & CGU_CLK_DIV) - div = ingenic_clk_calc_div(clk_info, *parent_rate, req_rate); + div = ingenic_clk_calc_div(hw, clk_info, *parent_rate, req_rate); else if (clk_info->type & CGU_CLK_FIXDIV) div = clk_info->fixdiv.div; else if (clk_hw_can_set_rate_parent(hw)) @@ -480,7 +508,7 @@ ingenic_clk_set_rate(struct clk_hw *hw, unsigned long req_rate, int ret = 0; if (clk_info->type & CGU_CLK_DIV) { - div = ingenic_clk_calc_div(clk_info, parent_rate, req_rate); + div = ingenic_clk_calc_div(hw, clk_info, parent_rate, req_rate); rate = DIV_ROUND_UP(parent_rate, div); if (rate != req_rate) diff --git a/drivers/clk/ingenic/cgu.h b/drivers/clk/ingenic/cgu.h index 2c75ef4a36f5..bfc2b9c38a41 100644 --- a/drivers/clk/ingenic/cgu.h +++ b/drivers/clk/ingenic/cgu.h @@ -39,10 +39,10 @@ * their encoded values in the PLL control register, or -1 for * unsupported values * @bypass_reg: the offset of the bypass control register within the CGU - * @bypass_bit: the index of the bypass bit in the PLL control register + * @bypass_bit: the index of the bypass bit in the PLL control register, or + * -1 if there is no bypass bit * @enable_bit: the index of the enable bit in the PLL control register * @stable_bit: the index of the stable bit in the PLL control register - * @no_bypass_bit: if set, the PLL has no bypass functionality */ struct ingenic_cgu_pll_info { unsigned reg; @@ -52,10 +52,12 @@ struct ingenic_cgu_pll_info { u8 n_shift, n_bits, n_offset; u8 od_shift, od_bits, od_max; unsigned bypass_reg; - u8 bypass_bit; + s8 bypass_bit; u8 enable_bit; u8 stable_bit; - bool no_bypass_bit; + void (*calc_m_n_od)(const struct ingenic_cgu_pll_info *pll_info, + unsigned long rate, unsigned long parent_rate, + unsigned int *m, unsigned int *n, unsigned int *od); }; /** @@ -84,6 +86,7 @@ struct ingenic_cgu_mux_info { * isn't one * @busy_bit: the index of the busy bit within reg, or -1 if there isn't one * @stop_bit: the index of the stop bit within reg, or -1 if there isn't one + * @bypass_mask: mask of parent clocks for which the divider does not apply * @div_table: optional table to map the value read from the register to the * actual divider value */ @@ -95,6 +98,7 @@ struct ingenic_cgu_div_info { s8 ce_bit; s8 busy_bit; s8 stop_bit; + u8 bypass_mask; const u8 *div_table; }; diff --git a/drivers/clk/ingenic/jz4725b-cgu.c b/drivers/clk/ingenic/jz4725b-cgu.c index 8c38e72d14a7..5154b0cf8ad6 100644 --- a/drivers/clk/ingenic/jz4725b-cgu.c +++ b/drivers/clk/ingenic/jz4725b-cgu.c @@ -80,7 +80,7 @@ static const struct ingenic_cgu_clk_info jz4725b_cgu_clocks[] = { "pll half", CGU_CLK_DIV, .parents = { JZ4725B_CLK_PLL, -1, -1, -1 }, .div = { - CGU_REG_CPCCR, 21, 1, 1, -1, -1, -1, + CGU_REG_CPCCR, 21, 1, 1, -1, -1, -1, 0, jz4725b_cgu_pll_half_div_table, }, }, @@ -89,7 +89,7 @@ static const struct ingenic_cgu_clk_info jz4725b_cgu_clocks[] = { "cclk", CGU_CLK_DIV, .parents = { JZ4725B_CLK_PLL, -1, -1, -1 }, .div = { - CGU_REG_CPCCR, 0, 1, 4, 22, -1, -1, + CGU_REG_CPCCR, 0, 1, 4, 22, -1, -1, 0, jz4725b_cgu_cpccr_div_table, }, }, @@ -98,7 +98,7 @@ static const struct ingenic_cgu_clk_info jz4725b_cgu_clocks[] = { "hclk", CGU_CLK_DIV, .parents = { JZ4725B_CLK_PLL, -1, -1, -1 }, .div = { - CGU_REG_CPCCR, 4, 1, 4, 22, -1, -1, + CGU_REG_CPCCR, 4, 1, 4, 22, -1, -1, 0, jz4725b_cgu_cpccr_div_table, }, }, @@ -107,7 +107,7 @@ static const struct ingenic_cgu_clk_info jz4725b_cgu_clocks[] = { "pclk", CGU_CLK_DIV, .parents = { JZ4725B_CLK_PLL, -1, -1, -1 }, .div = { - CGU_REG_CPCCR, 8, 1, 4, 22, -1, -1, + CGU_REG_CPCCR, 8, 1, 4, 22, -1, -1, 0, jz4725b_cgu_cpccr_div_table, }, }, @@ -116,7 +116,7 @@ static const struct ingenic_cgu_clk_info jz4725b_cgu_clocks[] = { "mclk", CGU_CLK_DIV, .parents = { JZ4725B_CLK_PLL, -1, -1, -1 }, .div = { - CGU_REG_CPCCR, 12, 1, 4, 22, -1, -1, + CGU_REG_CPCCR, 12, 1, 4, 22, -1, -1, 0, jz4725b_cgu_cpccr_div_table, }, }, @@ -125,7 +125,7 @@ static const struct ingenic_cgu_clk_info jz4725b_cgu_clocks[] = { "ipu", CGU_CLK_DIV | CGU_CLK_GATE, .parents = { JZ4725B_CLK_PLL, -1, -1, -1 }, .div = { - CGU_REG_CPCCR, 16, 1, 4, 22, -1, -1, + CGU_REG_CPCCR, 16, 1, 4, 22, -1, -1, 0, jz4725b_cgu_cpccr_div_table, }, .gate = { CGU_REG_CLKGR, 13 }, diff --git a/drivers/clk/ingenic/jz4740-cgu.c b/drivers/clk/ingenic/jz4740-cgu.c index c0ac9196a581..cd878f08aca3 100644 --- a/drivers/clk/ingenic/jz4740-cgu.c +++ b/drivers/clk/ingenic/jz4740-cgu.c @@ -95,7 +95,7 @@ static const struct ingenic_cgu_clk_info jz4740_cgu_clocks[] = { "pll half", CGU_CLK_DIV, .parents = { JZ4740_CLK_PLL, -1, -1, -1 }, .div = { - CGU_REG_CPCCR, 21, 1, 1, -1, -1, -1, + CGU_REG_CPCCR, 21, 1, 1, -1, -1, -1, 0, jz4740_cgu_pll_half_div_table, }, }, @@ -104,7 +104,7 @@ static const struct ingenic_cgu_clk_info jz4740_cgu_clocks[] = { "cclk", CGU_CLK_DIV, .parents = { JZ4740_CLK_PLL, -1, -1, -1 }, .div = { - CGU_REG_CPCCR, 0, 1, 4, 22, -1, -1, + CGU_REG_CPCCR, 0, 1, 4, 22, -1, -1, 0, jz4740_cgu_cpccr_div_table, }, }, @@ -113,7 +113,7 @@ static const struct ingenic_cgu_clk_info jz4740_cgu_clocks[] = { "hclk", CGU_CLK_DIV, .parents = { JZ4740_CLK_PLL, -1, -1, -1 }, .div = { - CGU_REG_CPCCR, 4, 1, 4, 22, -1, -1, + CGU_REG_CPCCR, 4, 1, 4, 22, -1, -1, 0, jz4740_cgu_cpccr_div_table, }, }, @@ -122,7 +122,7 @@ static const struct ingenic_cgu_clk_info jz4740_cgu_clocks[] = { "pclk", CGU_CLK_DIV, .parents = { JZ4740_CLK_PLL, -1, -1, -1 }, .div = { - CGU_REG_CPCCR, 8, 1, 4, 22, -1, -1, + CGU_REG_CPCCR, 8, 1, 4, 22, -1, -1, 0, jz4740_cgu_cpccr_div_table, }, }, @@ -131,7 +131,7 @@ static const struct ingenic_cgu_clk_info jz4740_cgu_clocks[] = { "mclk", CGU_CLK_DIV, .parents = { JZ4740_CLK_PLL, -1, -1, -1 }, .div = { - CGU_REG_CPCCR, 12, 1, 4, 22, -1, -1, + CGU_REG_CPCCR, 12, 1, 4, 22, -1, -1, 0, jz4740_cgu_cpccr_div_table, }, }, @@ -140,7 +140,7 @@ static const struct ingenic_cgu_clk_info jz4740_cgu_clocks[] = { "lcd", CGU_CLK_DIV | CGU_CLK_GATE, .parents = { JZ4740_CLK_PLL_HALF, -1, -1, -1 }, .div = { - CGU_REG_CPCCR, 16, 1, 5, 22, -1, -1, + CGU_REG_CPCCR, 16, 1, 5, 22, -1, -1, 0, jz4740_cgu_cpccr_div_table, }, .gate = { CGU_REG_CLKGR, 10 }, diff --git a/drivers/clk/ingenic/jz4760-cgu.c b/drivers/clk/ingenic/jz4760-cgu.c new file mode 100644 index 000000000000..14483797a4db --- /dev/null +++ b/drivers/clk/ingenic/jz4760-cgu.c @@ -0,0 +1,428 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * JZ4760 SoC CGU driver + * Copyright 2018, Paul Cercueil <paul@crapouillou.net> + */ + +#include <linux/bitops.h> +#include <linux/clk-provider.h> +#include <linux/delay.h> +#include <linux/io.h> +#include <linux/of.h> + +#include <linux/clk.h> + +#include <dt-bindings/clock/jz4760-cgu.h> + +#include "cgu.h" +#include "pm.h" + +#define MHZ (1000 * 1000) + +/* + * CPM registers offset address definition + */ +#define CGU_REG_CPCCR 0x00 +#define CGU_REG_LCR 0x04 +#define CGU_REG_CPPCR0 0x10 +#define CGU_REG_CLKGR0 0x20 +#define CGU_REG_OPCR 0x24 +#define CGU_REG_CLKGR1 0x28 +#define CGU_REG_CPPCR1 0x30 +#define CGU_REG_USBPCR 0x3c +#define CGU_REG_USBCDR 0x50 +#define CGU_REG_I2SCDR 0x60 +#define CGU_REG_LPCDR 0x64 +#define CGU_REG_MSCCDR 0x68 +#define CGU_REG_UHCCDR 0x6c +#define CGU_REG_SSICDR 0x74 +#define CGU_REG_CIMCDR 0x7c +#define CGU_REG_GPSCDR 0x80 +#define CGU_REG_PCMCDR 0x84 +#define CGU_REG_GPUCDR 0x88 + +static const s8 pll_od_encoding[8] = { + 0x0, 0x1, -1, 0x2, -1, -1, -1, 0x3, +}; + +static const u8 jz4760_cgu_cpccr_div_table[] = { + 1, 2, 3, 4, 6, 8, +}; + +static const u8 jz4760_cgu_pll_half_div_table[] = { + 2, 1, +}; + +static void +jz4760_cgu_calc_m_n_od(const struct ingenic_cgu_pll_info *pll_info, + unsigned long rate, unsigned long parent_rate, + unsigned int *pm, unsigned int *pn, unsigned int *pod) +{ + unsigned int m, n, od, m_max = (1 << pll_info->m_bits) - 2; + + /* The frequency after the N divider must be between 1 and 50 MHz. */ + n = parent_rate / (1 * MHZ); + + /* The N divider must be >= 2. */ + n = clamp_val(n, 2, 1 << pll_info->n_bits); + + for (;; n >>= 1) { + od = (unsigned int)-1; + + do { + m = (rate / MHZ) * (1 << ++od) * n / (parent_rate / MHZ); + } while ((m > m_max || m & 1) && (od < 4)); + + if (od < 4 && m >= 4 && m <= m_max) + break; + } + + *pm = m; + *pn = n; + *pod = 1 << od; +} + +static const struct ingenic_cgu_clk_info jz4760_cgu_clocks[] = { + + /* External clocks */ + + [JZ4760_CLK_EXT] = { "ext", CGU_CLK_EXT }, + [JZ4760_CLK_OSC32K] = { "osc32k", CGU_CLK_EXT }, + + /* PLLs */ + + [JZ4760_CLK_PLL0] = { + "pll0", CGU_CLK_PLL, + .parents = { JZ4760_CLK_EXT }, + .pll = { + .reg = CGU_REG_CPPCR0, + .rate_multiplier = 1, + .m_shift = 23, + .m_bits = 8, + .m_offset = 0, + .n_shift = 18, + .n_bits = 4, + .n_offset = 0, + .od_shift = 16, + .od_bits = 2, + .od_max = 8, + .od_encoding = pll_od_encoding, + .bypass_reg = CGU_REG_CPPCR0, + .bypass_bit = 9, + .enable_bit = 8, + .stable_bit = 10, + .calc_m_n_od = jz4760_cgu_calc_m_n_od, + }, + }, + + [JZ4760_CLK_PLL1] = { + /* TODO: PLL1 can depend on PLL0 */ + "pll1", CGU_CLK_PLL, + .parents = { JZ4760_CLK_EXT }, + .pll = { + .reg = CGU_REG_CPPCR1, + .rate_multiplier = 1, + .m_shift = 23, + .m_bits = 8, + .m_offset = 0, + .n_shift = 18, + .n_bits = 4, + .n_offset = 0, + .od_shift = 16, + .od_bits = 2, + .od_max = 8, + .od_encoding = pll_od_encoding, + .bypass_bit = -1, + .enable_bit = 7, + .stable_bit = 6, + .calc_m_n_od = jz4760_cgu_calc_m_n_od, + }, + }, + + /* Main clocks */ + + [JZ4760_CLK_CCLK] = { + "cclk", CGU_CLK_DIV, + .parents = { JZ4760_CLK_PLL0, }, + .div = { + CGU_REG_CPCCR, 0, 1, 4, 22, -1, -1, 0, + jz4760_cgu_cpccr_div_table, + }, + }, + [JZ4760_CLK_HCLK] = { + "hclk", CGU_CLK_DIV, + .parents = { JZ4760_CLK_PLL0, }, + .div = { + CGU_REG_CPCCR, 4, 1, 4, 22, -1, -1, 0, + jz4760_cgu_cpccr_div_table, + }, + }, + [JZ4760_CLK_SCLK] = { + "sclk", CGU_CLK_DIV, + .parents = { JZ4760_CLK_PLL0, }, + .div = { + CGU_REG_CPCCR, 24, 1, 4, 22, -1, -1, 0, + jz4760_cgu_cpccr_div_table, + }, + }, + [JZ4760_CLK_H2CLK] = { + "h2clk", CGU_CLK_DIV, + .parents = { JZ4760_CLK_PLL0, }, + .div = { + CGU_REG_CPCCR, 16, 1, 4, 22, -1, -1, 0, + jz4760_cgu_cpccr_div_table, + }, + }, + [JZ4760_CLK_MCLK] = { + "mclk", CGU_CLK_DIV, + .parents = { JZ4760_CLK_PLL0, }, + .div = { + CGU_REG_CPCCR, 12, 1, 4, 22, -1, -1, 0, + jz4760_cgu_cpccr_div_table, + }, + }, + [JZ4760_CLK_PCLK] = { + "pclk", CGU_CLK_DIV, + .parents = { JZ4760_CLK_PLL0, }, + .div = { + CGU_REG_CPCCR, 8, 1, 4, 22, -1, -1, 0, + jz4760_cgu_cpccr_div_table, + }, + }, + + /* Divided clocks */ + + [JZ4760_CLK_PLL0_HALF] = { + "pll0_half", CGU_CLK_DIV, + .parents = { JZ4760_CLK_PLL0 }, + .div = { + CGU_REG_CPCCR, 21, 1, 1, 22, -1, -1, 0, + jz4760_cgu_pll_half_div_table, + }, + }, + + /* Those divided clocks can connect to PLL0 or PLL1 */ + + [JZ4760_CLK_UHC] = { + "uhc", CGU_CLK_DIV | CGU_CLK_GATE | CGU_CLK_MUX, + .parents = { JZ4760_CLK_PLL0_HALF, JZ4760_CLK_PLL1, }, + .mux = { CGU_REG_UHCCDR, 31, 1 }, + .div = { CGU_REG_UHCCDR, 0, 1, 4, -1, -1, -1 }, + .gate = { CGU_REG_CLKGR0, 24 }, + }, + [JZ4760_CLK_GPU] = { + "gpu", CGU_CLK_DIV | CGU_CLK_GATE | CGU_CLK_MUX, + .parents = { JZ4760_CLK_PLL0_HALF, JZ4760_CLK_PLL1, }, + .mux = { CGU_REG_GPUCDR, 31, 1 }, + .div = { CGU_REG_GPUCDR, 0, 1, 3, -1, -1, -1 }, + .gate = { CGU_REG_CLKGR1, 9 }, + }, + [JZ4760_CLK_LPCLK_DIV] = { + "lpclk_div", CGU_CLK_DIV | CGU_CLK_MUX, + .parents = { JZ4760_CLK_PLL0_HALF, JZ4760_CLK_PLL1, }, + .mux = { CGU_REG_LPCDR, 29, 1 }, + .div = { CGU_REG_LPCDR, 0, 1, 11, -1, -1, -1 }, + }, + [JZ4760_CLK_TVE] = { + "tve", CGU_CLK_GATE | CGU_CLK_MUX, + .parents = { JZ4760_CLK_LPCLK_DIV, JZ4760_CLK_EXT, }, + .mux = { CGU_REG_LPCDR, 31, 1 }, + .gate = { CGU_REG_CLKGR0, 27 }, + }, + [JZ4760_CLK_LPCLK] = { + "lpclk", CGU_CLK_GATE | CGU_CLK_MUX, + .parents = { JZ4760_CLK_LPCLK_DIV, JZ4760_CLK_TVE, }, + .mux = { CGU_REG_LPCDR, 30, 1 }, + .gate = { CGU_REG_CLKGR0, 28 }, + }, + [JZ4760_CLK_GPS] = { + "gps", CGU_CLK_DIV | CGU_CLK_GATE | CGU_CLK_MUX, + .parents = { JZ4760_CLK_PLL0_HALF, JZ4760_CLK_PLL1, }, + .mux = { CGU_REG_GPSCDR, 31, 1 }, + .div = { CGU_REG_GPSCDR, 0, 1, 4, -1, -1, -1 }, + .gate = { CGU_REG_CLKGR0, 22 }, + }, + + /* Those divided clocks can connect to EXT, PLL0 or PLL1 */ + + [JZ4760_CLK_PCM] = { + "pcm", CGU_CLK_DIV | CGU_CLK_GATE | CGU_CLK_MUX, + .parents = { JZ4760_CLK_EXT, -1, + JZ4760_CLK_PLL0_HALF, JZ4760_CLK_PLL1 }, + .mux = { CGU_REG_PCMCDR, 30, 2 }, + .div = { CGU_REG_PCMCDR, 0, 1, 9, -1, -1, -1, BIT(0) }, + .gate = { CGU_REG_CLKGR1, 8 }, + }, + [JZ4760_CLK_I2S] = { + "i2s", CGU_CLK_DIV | CGU_CLK_MUX, + .parents = { JZ4760_CLK_EXT, -1, + JZ4760_CLK_PLL0_HALF, JZ4760_CLK_PLL1 }, + .mux = { CGU_REG_I2SCDR, 30, 2 }, + .div = { CGU_REG_I2SCDR, 0, 1, 9, -1, -1, -1, BIT(0) }, + }, + [JZ4760_CLK_OTG] = { + "usb", CGU_CLK_DIV | CGU_CLK_GATE | CGU_CLK_MUX, + .parents = { JZ4760_CLK_EXT, -1, + JZ4760_CLK_PLL0_HALF, JZ4760_CLK_PLL1 }, + .mux = { CGU_REG_USBCDR, 30, 2 }, + .div = { CGU_REG_USBCDR, 0, 1, 8, -1, -1, -1 }, + .gate = { CGU_REG_CLKGR0, 2 }, + }, + + /* Those divided clocks can connect to EXT or PLL0 */ + [JZ4760_CLK_MMC_MUX] = { + "mmc_mux", CGU_CLK_MUX | CGU_CLK_DIV, + .parents = { JZ4760_CLK_EXT, JZ4760_CLK_PLL0_HALF, }, + .mux = { CGU_REG_MSCCDR, 31, 1 }, + .div = { CGU_REG_MSCCDR, 0, 1, 6, -1, -1, -1, BIT(0) }, + }, + [JZ4760_CLK_SSI_MUX] = { + "ssi_mux", CGU_CLK_DIV | CGU_CLK_MUX, + .parents = { JZ4760_CLK_EXT, JZ4760_CLK_PLL0_HALF, }, + .mux = { CGU_REG_SSICDR, 31, 1 }, + .div = { CGU_REG_SSICDR, 0, 1, 6, -1, -1, -1, BIT(0) }, + }, + + /* These divided clock can connect to PLL0 only */ + [JZ4760_CLK_CIM] = { + "cim", CGU_CLK_DIV | CGU_CLK_GATE, + .parents = { JZ4760_CLK_PLL0_HALF }, + .div = { CGU_REG_CIMCDR, 0, 1, 8, -1, -1, -1 }, + .gate = { CGU_REG_CLKGR0, 26 }, + }, + + /* Gate-only clocks */ + + [JZ4760_CLK_SSI0] = { + "ssi0", CGU_CLK_GATE, + .parents = { JZ4760_CLK_SSI_MUX, }, + .gate = { CGU_REG_CLKGR0, 4 }, + }, + [JZ4760_CLK_SSI1] = { + "ssi1", CGU_CLK_GATE, + .parents = { JZ4760_CLK_SSI_MUX, }, + .gate = { CGU_REG_CLKGR0, 19 }, + }, + [JZ4760_CLK_SSI2] = { + "ssi2", CGU_CLK_GATE, + .parents = { JZ4760_CLK_SSI_MUX, }, + .gate = { CGU_REG_CLKGR0, 20 }, + }, + [JZ4760_CLK_DMA] = { + "dma", CGU_CLK_GATE, + .parents = { JZ4760_CLK_H2CLK, }, + .gate = { CGU_REG_CLKGR0, 21 }, + }, + [JZ4760_CLK_I2C0] = { + "i2c0", CGU_CLK_GATE, + .parents = { JZ4760_CLK_EXT, }, + .gate = { CGU_REG_CLKGR0, 5 }, + }, + [JZ4760_CLK_I2C1] = { + "i2c1", CGU_CLK_GATE, + .parents = { JZ4760_CLK_EXT, }, + .gate = { CGU_REG_CLKGR0, 6 }, + }, + [JZ4760_CLK_UART0] = { + "uart0", CGU_CLK_GATE, + .parents = { JZ4760_CLK_EXT, }, + .gate = { CGU_REG_CLKGR0, 15 }, + }, + [JZ4760_CLK_UART1] = { + "uart1", CGU_CLK_GATE, + .parents = { JZ4760_CLK_EXT, }, + .gate = { CGU_REG_CLKGR0, 16 }, + }, + [JZ4760_CLK_UART2] = { + "uart2", CGU_CLK_GATE, + .parents = { JZ4760_CLK_EXT, }, + .gate = { CGU_REG_CLKGR0, 17 }, + }, + [JZ4760_CLK_UART3] = { + "uart3", CGU_CLK_GATE, + .parents = { JZ4760_CLK_EXT, }, + .gate = { CGU_REG_CLKGR0, 18 }, + }, + [JZ4760_CLK_IPU] = { + "ipu", CGU_CLK_GATE, + .parents = { JZ4760_CLK_HCLK, }, + .gate = { CGU_REG_CLKGR0, 29 }, + }, + [JZ4760_CLK_ADC] = { + "adc", CGU_CLK_GATE, + .parents = { JZ4760_CLK_EXT, }, + .gate = { CGU_REG_CLKGR0, 14 }, + }, + [JZ4760_CLK_AIC] = { + "aic", CGU_CLK_GATE, + .parents = { JZ4760_CLK_EXT, }, + .gate = { CGU_REG_CLKGR0, 8 }, + }, + [JZ4760_CLK_VPU] = { + "vpu", CGU_CLK_GATE, + .parents = { JZ4760_CLK_HCLK, }, + .gate = { CGU_REG_LCR, 30, false, 150 }, + }, + [JZ4760_CLK_MMC0] = { + "mmc0", CGU_CLK_GATE, + .parents = { JZ4760_CLK_MMC_MUX, }, + .gate = { CGU_REG_CLKGR0, 3 }, + }, + [JZ4760_CLK_MMC1] = { + "mmc1", CGU_CLK_GATE, + .parents = { JZ4760_CLK_MMC_MUX, }, + .gate = { CGU_REG_CLKGR0, 11 }, + }, + [JZ4760_CLK_MMC2] = { + "mmc2", CGU_CLK_GATE, + .parents = { JZ4760_CLK_MMC_MUX, }, + .gate = { CGU_REG_CLKGR0, 12 }, + }, + [JZ4760_CLK_UHC_PHY] = { + "uhc_phy", CGU_CLK_GATE, + .parents = { JZ4760_CLK_UHC, }, + .gate = { CGU_REG_OPCR, 5 }, + }, + [JZ4760_CLK_OTG_PHY] = { + "usb_phy", CGU_CLK_GATE, + .parents = { JZ4760_CLK_OTG }, + .gate = { CGU_REG_OPCR, 7, true, 50 }, + }, + + /* Custom clocks */ + [JZ4760_CLK_EXT512] = { + "ext/512", CGU_CLK_FIXDIV, + .parents = { JZ4760_CLK_EXT }, + .fixdiv = { 512 }, + }, + [JZ4760_CLK_RTC] = { + "rtc", CGU_CLK_MUX, + .parents = { JZ4760_CLK_EXT512, JZ4760_CLK_OSC32K, }, + .mux = { CGU_REG_OPCR, 2, 1}, + }, +}; + +static void __init jz4760_cgu_init(struct device_node *np) +{ + struct ingenic_cgu *cgu; + int retval; + + cgu = ingenic_cgu_new(jz4760_cgu_clocks, + ARRAY_SIZE(jz4760_cgu_clocks), np); + if (!cgu) { + pr_err("%s: failed to initialise CGU\n", __func__); + return; + } + + retval = ingenic_cgu_register_clocks(cgu); + if (retval) + pr_err("%s: failed to register CGU Clocks\n", __func__); + + ingenic_cgu_register_syscore_ops(cgu); +} + +/* We only probe via devicetree, no need for a platform driver */ +CLK_OF_DECLARE_DRIVER(jz4760_cgu, "ingenic,jz4760-cgu", jz4760_cgu_init); + +/* JZ4760B has some small differences, but we don't implement them. */ +CLK_OF_DECLARE_DRIVER(jz4760b_cgu, "ingenic,jz4760b-cgu", jz4760_cgu_init); diff --git a/drivers/clk/ingenic/jz4770-cgu.c b/drivers/clk/ingenic/jz4770-cgu.c index 9ea4490ecb7f..2321742b3471 100644 --- a/drivers/clk/ingenic/jz4770-cgu.c +++ b/drivers/clk/ingenic/jz4770-cgu.c @@ -139,8 +139,7 @@ static const struct ingenic_cgu_clk_info jz4770_cgu_clocks[] = { .od_bits = 2, .od_max = 8, .od_encoding = pll_od_encoding, - .bypass_reg = CGU_REG_CPPCR1, - .no_bypass_bit = true, + .bypass_bit = -1, .enable_bit = 7, .stable_bit = 6, }, @@ -152,7 +151,7 @@ static const struct ingenic_cgu_clk_info jz4770_cgu_clocks[] = { "cclk", CGU_CLK_DIV, .parents = { JZ4770_CLK_PLL0, }, .div = { - CGU_REG_CPCCR, 0, 1, 4, 22, -1, -1, + CGU_REG_CPCCR, 0, 1, 4, 22, -1, -1, 0, jz4770_cgu_cpccr_div_table, }, }, @@ -160,7 +159,7 @@ static const struct ingenic_cgu_clk_info jz4770_cgu_clocks[] = { "h0clk", CGU_CLK_DIV, .parents = { JZ4770_CLK_PLL0, }, .div = { - CGU_REG_CPCCR, 4, 1, 4, 22, -1, -1, + CGU_REG_CPCCR, 4, 1, 4, 22, -1, -1, 0, jz4770_cgu_cpccr_div_table, }, }, @@ -168,7 +167,7 @@ static const struct ingenic_cgu_clk_info jz4770_cgu_clocks[] = { "h1clk", CGU_CLK_DIV | CGU_CLK_GATE, .parents = { JZ4770_CLK_PLL0, }, .div = { - CGU_REG_CPCCR, 24, 1, 4, 22, -1, -1, + CGU_REG_CPCCR, 24, 1, 4, 22, -1, -1, 0, jz4770_cgu_cpccr_div_table, }, .gate = { CGU_REG_CLKGR1, 7 }, @@ -177,7 +176,7 @@ static const struct ingenic_cgu_clk_info jz4770_cgu_clocks[] = { "h2clk", CGU_CLK_DIV, .parents = { JZ4770_CLK_PLL0, }, .div = { - CGU_REG_CPCCR, 16, 1, 4, 22, -1, -1, + CGU_REG_CPCCR, 16, 1, 4, 22, -1, -1, 0, jz4770_cgu_cpccr_div_table, }, }, @@ -185,7 +184,7 @@ static const struct ingenic_cgu_clk_info jz4770_cgu_clocks[] = { "c1clk", CGU_CLK_DIV | CGU_CLK_GATE, .parents = { JZ4770_CLK_PLL0, }, .div = { - CGU_REG_CPCCR, 12, 1, 4, 22, -1, -1, + CGU_REG_CPCCR, 12, 1, 4, 22, -1, -1, 0, jz4770_cgu_cpccr_div_table, }, .gate = { CGU_REG_OPCR, 31, true }, // disable CCLK stop on idle @@ -194,7 +193,7 @@ static const struct ingenic_cgu_clk_info jz4770_cgu_clocks[] = { "pclk", CGU_CLK_DIV, .parents = { JZ4770_CLK_PLL0, }, .div = { - CGU_REG_CPCCR, 8, 1, 4, 22, -1, -1, + CGU_REG_CPCCR, 8, 1, 4, 22, -1, -1, 0, jz4770_cgu_cpccr_div_table, }, }, diff --git a/drivers/clk/ingenic/tcu.c b/drivers/clk/ingenic/tcu.c index 9382dc3aa27e..77acfbeb4830 100644 --- a/drivers/clk/ingenic/tcu.c +++ b/drivers/clk/ingenic/tcu.c @@ -326,6 +326,7 @@ static const struct ingenic_soc_info x1000_soc_info = { static const struct of_device_id __maybe_unused ingenic_tcu_of_match[] __initconst = { { .compatible = "ingenic,jz4740-tcu", .data = &jz4740_soc_info, }, { .compatible = "ingenic,jz4725b-tcu", .data = &jz4725b_soc_info, }, + { .compatible = "ingenic,jz4760-tcu", .data = &jz4770_soc_info, }, { .compatible = "ingenic,jz4770-tcu", .data = &jz4770_soc_info, }, { .compatible = "ingenic,x1000-tcu", .data = &x1000_soc_info, }, { /* sentinel */ } @@ -477,5 +478,6 @@ static void __init ingenic_tcu_init(struct device_node *np) CLK_OF_DECLARE_DRIVER(jz4740_cgu, "ingenic,jz4740-tcu", ingenic_tcu_init); CLK_OF_DECLARE_DRIVER(jz4725b_cgu, "ingenic,jz4725b-tcu", ingenic_tcu_init); +CLK_OF_DECLARE_DRIVER(jz4760_cgu, "ingenic,jz4760-tcu", ingenic_tcu_init); CLK_OF_DECLARE_DRIVER(jz4770_cgu, "ingenic,jz4770-tcu", ingenic_tcu_init); CLK_OF_DECLARE_DRIVER(x1000_cgu, "ingenic,x1000-tcu", ingenic_tcu_init); diff --git a/drivers/clk/keystone/syscon-clk.c b/drivers/clk/keystone/syscon-clk.c index 5b3d36462174..aae1a4076281 100644 --- a/drivers/clk/keystone/syscon-clk.c +++ b/drivers/clk/keystone/syscon-clk.c @@ -149,11 +149,28 @@ static const struct ti_syscon_gate_clk_data am654_clk_data[] = { { /* Sentinel */ }, }; +static const struct ti_syscon_gate_clk_data am64_clk_data[] = { + TI_SYSCON_CLK_GATE("epwm_tbclk0", 0x0, 0), + TI_SYSCON_CLK_GATE("epwm_tbclk1", 0x0, 1), + TI_SYSCON_CLK_GATE("epwm_tbclk2", 0x0, 2), + TI_SYSCON_CLK_GATE("epwm_tbclk3", 0x0, 3), + TI_SYSCON_CLK_GATE("epwm_tbclk4", 0x0, 4), + TI_SYSCON_CLK_GATE("epwm_tbclk5", 0x0, 5), + TI_SYSCON_CLK_GATE("epwm_tbclk6", 0x0, 6), + TI_SYSCON_CLK_GATE("epwm_tbclk7", 0x0, 7), + TI_SYSCON_CLK_GATE("epwm_tbclk8", 0x0, 8), + { /* Sentinel */ }, +}; + static const struct of_device_id ti_syscon_gate_clk_ids[] = { { .compatible = "ti,am654-ehrpwm-tbclk", .data = &am654_clk_data, }, + { + .compatible = "ti,am64-epwm-tbclk", + .data = &am64_clk_data, + }, { } }; MODULE_DEVICE_TABLE(of, ti_syscon_gate_clk_ids); diff --git a/drivers/clk/meson/axg-audio.c b/drivers/clk/meson/axg-audio.c index 7c8d02164443..bfe36bd41339 100644 --- a/drivers/clk/meson/axg-audio.c +++ b/drivers/clk/meson/axg-audio.c @@ -1665,8 +1665,7 @@ static int devm_clk_get_enable(struct device *dev, char *id) clk = devm_clk_get(dev, id); if (IS_ERR(clk)) { ret = PTR_ERR(clk); - if (ret != -EPROBE_DEFER) - dev_err(dev, "failed to get %s", id); + dev_err_probe(dev, ret, "failed to get %s", id); return ret; } @@ -1811,7 +1810,7 @@ static int axg_audio_clkc_probe(struct platform_device *pdev) ret = device_reset(dev); if (ret) { - dev_err(dev, "failed to reset device\n"); + dev_err_probe(dev, ret, "failed to reset device\n"); return ret; } diff --git a/drivers/clk/meson/clk-pll.c b/drivers/clk/meson/clk-pll.c index 49f27fe53213..9e55617bc3b4 100644 --- a/drivers/clk/meson/clk-pll.c +++ b/drivers/clk/meson/clk-pll.c @@ -242,8 +242,8 @@ static int meson_clk_get_pll_settings(unsigned long rate, return best ? 0 : -EINVAL; } -static long meson_clk_pll_round_rate(struct clk_hw *hw, unsigned long rate, - unsigned long *parent_rate) +static int meson_clk_pll_determine_rate(struct clk_hw *hw, + struct clk_rate_request *req) { struct clk_regmap *clk = to_clk_regmap(hw); struct meson_clk_pll_data *pll = meson_clk_pll_data(clk); @@ -251,22 +251,26 @@ static long meson_clk_pll_round_rate(struct clk_hw *hw, unsigned long rate, unsigned long round; int ret; - ret = meson_clk_get_pll_settings(rate, *parent_rate, &m, &n, pll); + ret = meson_clk_get_pll_settings(req->rate, req->best_parent_rate, + &m, &n, pll); if (ret) - return meson_clk_pll_recalc_rate(hw, *parent_rate); + return ret; - round = __pll_params_to_rate(*parent_rate, m, n, 0, pll); + round = __pll_params_to_rate(req->best_parent_rate, m, n, 0, pll); - if (!MESON_PARM_APPLICABLE(&pll->frac) || rate == round) - return round; + if (!MESON_PARM_APPLICABLE(&pll->frac) || req->rate == round) { + req->rate = round; + return 0; + } /* * The rate provided by the setting is not an exact match, let's * try to improve the result using the fractional parameter */ - frac = __pll_params_with_frac(rate, *parent_rate, m, n, pll); + frac = __pll_params_with_frac(req->rate, req->best_parent_rate, m, n, pll); + req->rate = __pll_params_to_rate(req->best_parent_rate, m, n, frac, pll); - return __pll_params_to_rate(*parent_rate, m, n, frac, pll); + return 0; } static int meson_clk_pll_wait_lock(struct clk_hw *hw) @@ -419,7 +423,7 @@ static int meson_clk_pll_set_rate(struct clk_hw *hw, unsigned long rate, */ const struct clk_ops meson_clk_pcie_pll_ops = { .recalc_rate = meson_clk_pll_recalc_rate, - .round_rate = meson_clk_pll_round_rate, + .determine_rate = meson_clk_pll_determine_rate, .is_enabled = meson_clk_pll_is_enabled, .enable = meson_clk_pcie_pll_enable, .disable = meson_clk_pll_disable @@ -429,7 +433,7 @@ EXPORT_SYMBOL_GPL(meson_clk_pcie_pll_ops); const struct clk_ops meson_clk_pll_ops = { .init = meson_clk_pll_init, .recalc_rate = meson_clk_pll_recalc_rate, - .round_rate = meson_clk_pll_round_rate, + .determine_rate = meson_clk_pll_determine_rate, .set_rate = meson_clk_pll_set_rate, .is_enabled = meson_clk_pll_is_enabled, .enable = meson_clk_pll_enable, diff --git a/drivers/clk/meson/g12a.c b/drivers/clk/meson/g12a.c index b080359b4645..310accf94830 100644 --- a/drivers/clk/meson/g12a.c +++ b/drivers/clk/meson/g12a.c @@ -1603,7 +1603,7 @@ static struct clk_regmap g12b_cpub_clk_trace = { }; static const struct pll_mult_range g12a_gp0_pll_mult_range = { - .min = 55, + .min = 125, .max = 255, }; @@ -4723,6 +4723,12 @@ static struct clk_hw_onecell_data g12b_hw_onecell_data = { [CLKID_SPICC1_SCLK_SEL] = &g12a_spicc1_sclk_sel.hw, [CLKID_SPICC1_SCLK_DIV] = &g12a_spicc1_sclk_div.hw, [CLKID_SPICC1_SCLK] = &g12a_spicc1_sclk.hw, + [CLKID_NNA_AXI_CLK_SEL] = &sm1_nna_axi_clk_sel.hw, + [CLKID_NNA_AXI_CLK_DIV] = &sm1_nna_axi_clk_div.hw, + [CLKID_NNA_AXI_CLK] = &sm1_nna_axi_clk.hw, + [CLKID_NNA_CORE_CLK_SEL] = &sm1_nna_core_clk_sel.hw, + [CLKID_NNA_CORE_CLK_DIV] = &sm1_nna_core_clk_div.hw, + [CLKID_NNA_CORE_CLK] = &sm1_nna_core_clk.hw, [CLKID_MIPI_DSI_PXCLK_SEL] = &g12a_mipi_dsi_pxclk_sel.hw, [CLKID_MIPI_DSI_PXCLK_DIV] = &g12a_mipi_dsi_pxclk_div.hw, [CLKID_MIPI_DSI_PXCLK] = &g12a_mipi_dsi_pxclk.hw, diff --git a/drivers/clk/qcom/Kconfig b/drivers/clk/qcom/Kconfig index 45646b867cdb..62e00e15495c 100644 --- a/drivers/clk/qcom/Kconfig +++ b/drivers/clk/qcom/Kconfig @@ -210,6 +210,13 @@ config MSM_LCC_8960 Say Y if you want to use audio devices such as i2s, pcm, SLIMBus, etc. +config MDM_GCC_9607 + tristate "MDM9607 Global Clock Controller" + help + Support for the global clock controller on mdm9607 devices. + Say Y if you want to use peripheral devices such as UART, SPI, + I2C, USB, SD/eMMC, etc. + config MDM_GCC_9615 tristate "MDM9615 Global Clock Controller" help @@ -483,6 +490,13 @@ config SDX_GCC_55 Say Y if you want to use peripheral devices such as UART, SPI, I2C, USB, SD/UFS, PCIe etc. +config SM_CAMCC_8250 + tristate "SM8250 Camera Clock Controller" + select SM_GCC_8250 + help + Support for the camera clock controller on SM8250 devices. + Say Y if you want to support camera devices and camera functionality. + config SM_DISPCC_8250 tristate "SM8150 and SM8250 Display Clock Controller" depends on SM_GCC_8150 || SM_GCC_8250 @@ -492,6 +506,13 @@ config SM_DISPCC_8250 Say Y if you want to support display devices and functionality such as splash screen. +config SM_GCC_6125 + tristate "SM6125 Global Clock Controller" + help + Support for the global clock controller on SM6125 devices. + Say Y if you want to use peripheral devices such as UART, + SPI, I2C, USB, SD/UFS, PCIe etc. + config SM_GCC_8150 tristate "SM8150 Global Clock Controller" help diff --git a/drivers/clk/qcom/Makefile b/drivers/clk/qcom/Makefile index c8291312e723..c2a1cafb31bc 100644 --- a/drivers/clk/qcom/Makefile +++ b/drivers/clk/qcom/Makefile @@ -27,6 +27,7 @@ obj-$(CONFIG_IPQ_GCC_6018) += gcc-ipq6018.o obj-$(CONFIG_IPQ_GCC_806X) += gcc-ipq806x.o obj-$(CONFIG_IPQ_GCC_8074) += gcc-ipq8074.o obj-$(CONFIG_IPQ_LCC_806X) += lcc-ipq806x.o +obj-$(CONFIG_MDM_GCC_9607) += gcc-mdm9607.o obj-$(CONFIG_MDM_GCC_9615) += gcc-mdm9615.o obj-$(CONFIG_MDM_LCC_9615) += lcc-mdm9615.o obj-$(CONFIG_MSM_GCC_8660) += gcc-msm8660.o @@ -73,7 +74,9 @@ obj-$(CONFIG_SDM_GPUCC_845) += gpucc-sdm845.o obj-$(CONFIG_SDM_LPASSCC_845) += lpasscc-sdm845.o obj-$(CONFIG_SDM_VIDEOCC_845) += videocc-sdm845.o obj-$(CONFIG_SDX_GCC_55) += gcc-sdx55.o +obj-$(CONFIG_SM_CAMCC_8250) += camcc-sm8250.o obj-$(CONFIG_SM_DISPCC_8250) += dispcc-sm8250.o +obj-$(CONFIG_SM_GCC_6125) += gcc-sm6125.o obj-$(CONFIG_SM_GCC_8150) += gcc-sm8150.o obj-$(CONFIG_SM_GCC_8250) += gcc-sm8250.o obj-$(CONFIG_SM_GCC_8350) += gcc-sm8350.o diff --git a/drivers/clk/qcom/apcs-sdx55.c b/drivers/clk/qcom/apcs-sdx55.c index d0edabebf9c2..e599f862ec44 100644 --- a/drivers/clk/qcom/apcs-sdx55.c +++ b/drivers/clk/qcom/apcs-sdx55.c @@ -57,7 +57,7 @@ static int qcom_apcs_sdx55_clk_probe(struct platform_device *pdev) regmap = dev_get_regmap(parent, NULL); if (!regmap) { - dev_err_probe(dev, -ENODEV, "Failed to get parent regmap\n"); + dev_err(dev, "Failed to get parent regmap\n"); return -ENODEV; } @@ -80,19 +80,15 @@ static int qcom_apcs_sdx55_clk_probe(struct platform_device *pdev) a7cc->parent_map = apcs_mux_clk_parent_map; a7cc->pclk = devm_clk_get(parent, "pll"); - if (IS_ERR(a7cc->pclk)) { - ret = PTR_ERR(a7cc->pclk); - if (ret != -EPROBE_DEFER) - dev_err_probe(dev, ret, "Failed to get PLL clk\n"); - return ret; - } + if (IS_ERR(a7cc->pclk)) + return dev_err_probe(dev, PTR_ERR(a7cc->pclk), + "Failed to get PLL clk\n"); a7cc->clk_nb.notifier_call = a7cc_notifier_cb; ret = clk_notifier_register(a7cc->pclk, &a7cc->clk_nb); - if (ret) { - dev_err_probe(dev, ret, "Failed to register clock notifier\n"); - return ret; - } + if (ret) + return dev_err_probe(dev, ret, + "Failed to register clock notifier\n"); ret = devm_clk_register_regmap(dev, &a7cc->clkr); if (ret) { diff --git a/drivers/clk/qcom/camcc-sm8250.c b/drivers/clk/qcom/camcc-sm8250.c new file mode 100644 index 000000000000..439eaafdcc86 --- /dev/null +++ b/drivers/clk/qcom/camcc-sm8250.c @@ -0,0 +1,2456 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright (c) 2018-2021, The Linux Foundation. All rights reserved. + */ + +#include <linux/clk-provider.h> +#include <linux/module.h> +#include <linux/platform_device.h> +#include <linux/regmap.h> +#include <linux/reset-controller.h> + +#include <dt-bindings/clock/qcom,camcc-sm8250.h> + +#include "clk-alpha-pll.h" +#include "clk-branch.h" +#include "clk-rcg.h" +#include "clk-regmap-divider.h" +#include "common.h" +#include "gdsc.h" +#include "reset.h" + +enum { + P_BI_TCXO, + P_CAM_CC_PLL0_OUT_EVEN, + P_CAM_CC_PLL0_OUT_MAIN, + P_CAM_CC_PLL0_OUT_ODD, + P_CAM_CC_PLL1_OUT_EVEN, + P_CAM_CC_PLL2_OUT_EARLY, + P_CAM_CC_PLL2_OUT_MAIN, + P_CAM_CC_PLL3_OUT_EVEN, + P_CAM_CC_PLL4_OUT_EVEN, + P_SLEEP_CLK, +}; + +static struct pll_vco lucid_vco[] = { + { 249600000, 2000000000, 0 }, +}; + +static struct pll_vco zonda_vco[] = { + { 595200000UL, 3600000000UL, 0 }, +}; + +static const struct alpha_pll_config cam_cc_pll0_config = { + .l = 0x3e, + .alpha = 0x8000, + .config_ctl_val = 0x20485699, + .config_ctl_hi_val = 0x00002261, + .config_ctl_hi1_val = 0x329A699c, + .user_ctl_val = 0x00003100, + .user_ctl_hi_val = 0x00000805, + .user_ctl_hi1_val = 0x00000000, +}; + +static struct clk_alpha_pll cam_cc_pll0 = { + .offset = 0x0, + .vco_table = lucid_vco, + .num_vco = ARRAY_SIZE(lucid_vco), + .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_LUCID], + .clkr = { + .hw.init = &(struct clk_init_data){ + .name = "cam_cc_pll0", + .parent_data = &(const struct clk_parent_data){ + .fw_name = "bi_tcxo", + }, + .num_parents = 1, + .ops = &clk_alpha_pll_lucid_ops, + }, + }, +}; + +static const struct clk_div_table post_div_table_cam_cc_pll0_out_even[] = { + { 0x1, 2 }, + { } +}; + +static struct clk_alpha_pll_postdiv cam_cc_pll0_out_even = { + .offset = 0x0, + .post_div_shift = 8, + .post_div_table = post_div_table_cam_cc_pll0_out_even, + .num_post_div = ARRAY_SIZE(post_div_table_cam_cc_pll0_out_even), + .width = 4, + .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_LUCID], + .clkr.hw.init = &(struct clk_init_data){ + .name = "cam_cc_pll0_out_even", + .parent_hws = (const struct clk_hw*[]){ + &cam_cc_pll0.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_alpha_pll_postdiv_lucid_ops, + }, +}; + +static const struct clk_div_table post_div_table_cam_cc_pll0_out_odd[] = { + { 0x3, 3 }, + { } +}; + +static struct clk_alpha_pll_postdiv cam_cc_pll0_out_odd = { + .offset = 0x0, + .post_div_shift = 12, + .post_div_table = post_div_table_cam_cc_pll0_out_odd, + .num_post_div = ARRAY_SIZE(post_div_table_cam_cc_pll0_out_odd), + .width = 4, + .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_LUCID], + .clkr.hw.init = &(struct clk_init_data){ + .name = "cam_cc_pll0_out_odd", + .parent_hws = (const struct clk_hw*[]){ + &cam_cc_pll0.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_alpha_pll_postdiv_lucid_ops, + }, +}; + +static const struct alpha_pll_config cam_cc_pll1_config = { + .l = 0x1f, + .alpha = 0x4000, + .config_ctl_val = 0x20485699, + .config_ctl_hi_val = 0x00002261, + .config_ctl_hi1_val = 0x329A699c, + .user_ctl_val = 0x00000100, + .user_ctl_hi_val = 0x00000805, + .user_ctl_hi1_val = 0x00000000, +}; + +static struct clk_alpha_pll cam_cc_pll1 = { + .offset = 0x1000, + .vco_table = lucid_vco, + .num_vco = ARRAY_SIZE(lucid_vco), + .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_LUCID], + .clkr = { + .hw.init = &(struct clk_init_data){ + .name = "cam_cc_pll1", + .parent_data = &(const struct clk_parent_data){ + .fw_name = "bi_tcxo", + }, + .num_parents = 1, + .ops = &clk_alpha_pll_lucid_ops, + }, + }, +}; + +static const struct clk_div_table post_div_table_cam_cc_pll1_out_even[] = { + { 0x1, 2 }, + { } +}; + +static struct clk_alpha_pll_postdiv cam_cc_pll1_out_even = { + .offset = 0x1000, + .post_div_shift = 8, + .post_div_table = post_div_table_cam_cc_pll1_out_even, + .num_post_div = ARRAY_SIZE(post_div_table_cam_cc_pll1_out_even), + .width = 4, + .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_LUCID], + .clkr.hw.init = &(struct clk_init_data){ + .name = "cam_cc_pll1_out_even", + .parent_hws = (const struct clk_hw*[]){ + &cam_cc_pll1.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_alpha_pll_postdiv_lucid_ops, + }, +}; + +static const struct alpha_pll_config cam_cc_pll2_config = { + .l = 0x4b, + .alpha = 0x0, + .config_ctl_val = 0x08200920, + .config_ctl_hi_val = 0x05002015, + .config_ctl_hi1_val = 0x00000000, + .user_ctl_val = 0x00000100, + .user_ctl_hi_val = 0x00000000, + .user_ctl_hi1_val = 0x00000000, +}; + +static struct clk_alpha_pll cam_cc_pll2 = { + .offset = 0x2000, + .vco_table = zonda_vco, + .num_vco = ARRAY_SIZE(zonda_vco), + .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_ZONDA], + .clkr = { + .hw.init = &(struct clk_init_data){ + .name = "cam_cc_pll2", + .parent_data = &(const struct clk_parent_data){ + .fw_name = "bi_tcxo", + }, + .num_parents = 1, + .ops = &clk_alpha_pll_zonda_ops, + }, + }, +}; + +static const struct clk_div_table post_div_table_cam_cc_pll2_out_main[] = { + { 0x1, 2 }, + { } +}; + +static struct clk_alpha_pll_postdiv cam_cc_pll2_out_main = { + .offset = 0x2000, + .post_div_shift = 8, + .post_div_table = post_div_table_cam_cc_pll2_out_main, + .num_post_div = ARRAY_SIZE(post_div_table_cam_cc_pll2_out_main), + .width = 2, + .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_ZONDA], + .clkr.hw.init = &(struct clk_init_data){ + .name = "cam_cc_pll2_out_main", + .parent_hws = (const struct clk_hw*[]){ + &cam_cc_pll2.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_alpha_pll_postdiv_zonda_ops, + }, +}; + +static const struct alpha_pll_config cam_cc_pll3_config = { + .l = 0x24, + .alpha = 0x7555, + .config_ctl_val = 0x20485699, + .config_ctl_hi_val = 0x00002261, + .config_ctl_hi1_val = 0x329A699c, + .user_ctl_val = 0x00000100, + .user_ctl_hi_val = 0x00000805, + .user_ctl_hi1_val = 0x00000000, +}; + +static struct clk_alpha_pll cam_cc_pll3 = { + .offset = 0x3000, + .vco_table = lucid_vco, + .num_vco = ARRAY_SIZE(lucid_vco), + .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_LUCID], + .clkr = { + .hw.init = &(struct clk_init_data){ + .name = "cam_cc_pll3", + .parent_data = &(const struct clk_parent_data){ + .fw_name = "bi_tcxo", + }, + .num_parents = 1, + .ops = &clk_alpha_pll_lucid_ops, + }, + }, +}; + +static const struct clk_div_table post_div_table_cam_cc_pll3_out_even[] = { + { 0x1, 2 }, + { } +}; + +static struct clk_alpha_pll_postdiv cam_cc_pll3_out_even = { + .offset = 0x3000, + .post_div_shift = 8, + .post_div_table = post_div_table_cam_cc_pll3_out_even, + .num_post_div = ARRAY_SIZE(post_div_table_cam_cc_pll3_out_even), + .width = 4, + .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_LUCID], + .clkr.hw.init = &(struct clk_init_data){ + .name = "cam_cc_pll3_out_even", + .parent_hws = (const struct clk_hw*[]){ + &cam_cc_pll3.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_alpha_pll_postdiv_lucid_ops, + }, +}; + +static const struct alpha_pll_config cam_cc_pll4_config = { + .l = 0x24, + .alpha = 0x7555, + .config_ctl_val = 0x20485699, + .config_ctl_hi_val = 0x00002261, + .config_ctl_hi1_val = 0x329A699c, + .user_ctl_val = 0x00000100, + .user_ctl_hi_val = 0x00000805, + .user_ctl_hi1_val = 0x00000000, +}; + +static struct clk_alpha_pll cam_cc_pll4 = { + .offset = 0x4000, + .vco_table = lucid_vco, + .num_vco = ARRAY_SIZE(lucid_vco), + .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_LUCID], + .clkr = { + .hw.init = &(struct clk_init_data){ + .name = "cam_cc_pll4", + .parent_data = &(const struct clk_parent_data){ + .fw_name = "bi_tcxo", + }, + .num_parents = 1, + .ops = &clk_alpha_pll_lucid_ops, + }, + }, +}; + +static const struct clk_div_table post_div_table_cam_cc_pll4_out_even[] = { + { 0x1, 2 }, + { } +}; + +static struct clk_alpha_pll_postdiv cam_cc_pll4_out_even = { + .offset = 0x4000, + .post_div_shift = 8, + .post_div_table = post_div_table_cam_cc_pll4_out_even, + .num_post_div = ARRAY_SIZE(post_div_table_cam_cc_pll4_out_even), + .width = 4, + .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_LUCID], + .clkr.hw.init = &(struct clk_init_data){ + .name = "cam_cc_pll4_out_even", + .parent_hws = (const struct clk_hw*[]){ + &cam_cc_pll4.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_alpha_pll_postdiv_lucid_ops, + }, +}; + +static const struct parent_map cam_cc_parent_map_0[] = { + { P_BI_TCXO, 0 }, + { P_CAM_CC_PLL0_OUT_MAIN, 1 }, + { P_CAM_CC_PLL0_OUT_EVEN, 2 }, + { P_CAM_CC_PLL0_OUT_ODD, 3 }, + { P_CAM_CC_PLL2_OUT_MAIN, 5 }, +}; + +static const struct clk_parent_data cam_cc_parent_data_0[] = { + { .fw_name = "bi_tcxo" }, + { .hw = &cam_cc_pll0.clkr.hw }, + { .hw = &cam_cc_pll0_out_even.clkr.hw }, + { .hw = &cam_cc_pll0_out_odd.clkr.hw }, + { .hw = &cam_cc_pll2_out_main.clkr.hw }, +}; + +static const struct parent_map cam_cc_parent_map_1[] = { + { P_BI_TCXO, 0 }, + { P_CAM_CC_PLL2_OUT_EARLY, 5 }, +}; + +static const struct clk_parent_data cam_cc_parent_data_1[] = { + { .fw_name = "bi_tcxo" }, + { .hw = &cam_cc_pll2.clkr.hw }, +}; + +static const struct parent_map cam_cc_parent_map_2[] = { + { P_BI_TCXO, 0 }, + { P_CAM_CC_PLL3_OUT_EVEN, 6 }, +}; + +static const struct clk_parent_data cam_cc_parent_data_2[] = { + { .fw_name = "bi_tcxo" }, + { .hw = &cam_cc_pll3_out_even.clkr.hw }, +}; + +static const struct parent_map cam_cc_parent_map_3[] = { + { P_BI_TCXO, 0 }, + { P_CAM_CC_PLL4_OUT_EVEN, 6 }, +}; + +static const struct clk_parent_data cam_cc_parent_data_3[] = { + { .fw_name = "bi_tcxo" }, + { .hw = &cam_cc_pll4_out_even.clkr.hw }, +}; + +static const struct parent_map cam_cc_parent_map_4[] = { + { P_BI_TCXO, 0 }, + { P_CAM_CC_PLL1_OUT_EVEN, 4 }, +}; + +static const struct clk_parent_data cam_cc_parent_data_4[] = { + { .fw_name = "bi_tcxo" }, + { .hw = &cam_cc_pll1_out_even.clkr.hw }, +}; + +static const struct parent_map cam_cc_parent_map_5[] = { + { P_SLEEP_CLK, 0 }, +}; + +static const struct clk_parent_data cam_cc_parent_data_5[] = { + { .fw_name = "sleep_clk" }, +}; + +static const struct parent_map cam_cc_parent_map_6[] = { + { P_BI_TCXO, 0 }, +}; + +static const struct clk_parent_data cam_cc_parent_data_6[] = { + { .fw_name = "bi_tcxo" }, +}; + +static const struct freq_tbl ftbl_cam_cc_bps_clk_src[] = { + F(19200000, P_BI_TCXO, 1, 0, 0), + F(100000000, P_CAM_CC_PLL0_OUT_EVEN, 6, 0, 0), + F(200000000, P_CAM_CC_PLL0_OUT_ODD, 2, 0, 0), + F(400000000, P_CAM_CC_PLL0_OUT_ODD, 1, 0, 0), + F(480000000, P_CAM_CC_PLL2_OUT_MAIN, 1.5, 0, 0), + F(600000000, P_CAM_CC_PLL0_OUT_MAIN, 2, 0, 0), + { } +}; + +static struct clk_rcg2 cam_cc_bps_clk_src = { + .cmd_rcgr = 0x7010, + .mnd_width = 0, + .hid_width = 5, + .parent_map = cam_cc_parent_map_0, + .freq_tbl = ftbl_cam_cc_bps_clk_src, + .clkr.hw.init = &(struct clk_init_data){ + .name = "cam_cc_bps_clk_src", + .parent_data = cam_cc_parent_data_0, + .num_parents = ARRAY_SIZE(cam_cc_parent_data_0), + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_rcg2_ops, + }, +}; + +static const struct freq_tbl ftbl_cam_cc_camnoc_axi_clk_src[] = { + F(19200000, P_BI_TCXO, 1, 0, 0), + F(300000000, P_CAM_CC_PLL0_OUT_EVEN, 2, 0, 0), + F(400000000, P_CAM_CC_PLL0_OUT_ODD, 1, 0, 0), + { } +}; + +static struct clk_rcg2 cam_cc_camnoc_axi_clk_src = { + .cmd_rcgr = 0xc0f8, + .mnd_width = 0, + .hid_width = 5, + .parent_map = cam_cc_parent_map_0, + .freq_tbl = ftbl_cam_cc_camnoc_axi_clk_src, + .clkr.hw.init = &(struct clk_init_data){ + .name = "cam_cc_camnoc_axi_clk_src", + .parent_data = cam_cc_parent_data_0, + .num_parents = ARRAY_SIZE(cam_cc_parent_data_0), + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_rcg2_ops, + }, +}; + +static const struct freq_tbl ftbl_cam_cc_cci_0_clk_src[] = { + F(19200000, P_BI_TCXO, 1, 0, 0), + F(37500000, P_CAM_CC_PLL0_OUT_EVEN, 16, 0, 0), + { } +}; + +static struct clk_rcg2 cam_cc_cci_0_clk_src = { + .cmd_rcgr = 0xc0bc, + .mnd_width = 8, + .hid_width = 5, + .parent_map = cam_cc_parent_map_0, + .freq_tbl = ftbl_cam_cc_cci_0_clk_src, + .clkr.hw.init = &(struct clk_init_data){ + .name = "cam_cc_cci_0_clk_src", + .parent_data = cam_cc_parent_data_0, + .num_parents = ARRAY_SIZE(cam_cc_parent_data_0), + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_rcg2_ops, + }, +}; + +static struct clk_rcg2 cam_cc_cci_1_clk_src = { + .cmd_rcgr = 0xc0d8, + .mnd_width = 8, + .hid_width = 5, + .parent_map = cam_cc_parent_map_0, + .freq_tbl = ftbl_cam_cc_cci_0_clk_src, + .clkr.hw.init = &(struct clk_init_data){ + .name = "cam_cc_cci_1_clk_src", + .parent_data = cam_cc_parent_data_0, + .num_parents = ARRAY_SIZE(cam_cc_parent_data_0), + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_rcg2_ops, + }, +}; + +static const struct freq_tbl ftbl_cam_cc_cphy_rx_clk_src[] = { + F(19200000, P_BI_TCXO, 1, 0, 0), + F(400000000, P_CAM_CC_PLL0_OUT_ODD, 1, 0, 0), + { } +}; + +static struct clk_rcg2 cam_cc_cphy_rx_clk_src = { + .cmd_rcgr = 0xa068, + .mnd_width = 0, + .hid_width = 5, + .parent_map = cam_cc_parent_map_0, + .freq_tbl = ftbl_cam_cc_cphy_rx_clk_src, + .clkr.hw.init = &(struct clk_init_data){ + .name = "cam_cc_cphy_rx_clk_src", + .parent_data = cam_cc_parent_data_0, + .num_parents = ARRAY_SIZE(cam_cc_parent_data_0), + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_rcg2_ops, + }, +}; + +static const struct freq_tbl ftbl_cam_cc_csi0phytimer_clk_src[] = { + F(19200000, P_BI_TCXO, 1, 0, 0), + F(300000000, P_CAM_CC_PLL0_OUT_EVEN, 2, 0, 0), + { } +}; + +static struct clk_rcg2 cam_cc_csi0phytimer_clk_src = { + .cmd_rcgr = 0x6000, + .mnd_width = 0, + .hid_width = 5, + .parent_map = cam_cc_parent_map_0, + .freq_tbl = ftbl_cam_cc_csi0phytimer_clk_src, + .clkr.hw.init = &(struct clk_init_data){ + .name = "cam_cc_csi0phytimer_clk_src", + .parent_data = cam_cc_parent_data_0, + .num_parents = ARRAY_SIZE(cam_cc_parent_data_0), + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_rcg2_ops, + }, +}; + +static struct clk_rcg2 cam_cc_csi1phytimer_clk_src = { + .cmd_rcgr = 0x6020, + .mnd_width = 0, + .hid_width = 5, + .parent_map = cam_cc_parent_map_0, + .freq_tbl = ftbl_cam_cc_csi0phytimer_clk_src, + .clkr.hw.init = &(struct clk_init_data){ + .name = "cam_cc_csi1phytimer_clk_src", + .parent_data = cam_cc_parent_data_0, + .num_parents = ARRAY_SIZE(cam_cc_parent_data_0), + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_rcg2_ops, + }, +}; + +static struct clk_rcg2 cam_cc_csi2phytimer_clk_src = { + .cmd_rcgr = 0x6040, + .mnd_width = 0, + .hid_width = 5, + .parent_map = cam_cc_parent_map_0, + .freq_tbl = ftbl_cam_cc_csi0phytimer_clk_src, + .clkr.hw.init = &(struct clk_init_data){ + .name = "cam_cc_csi2phytimer_clk_src", + .parent_data = cam_cc_parent_data_0, + .num_parents = ARRAY_SIZE(cam_cc_parent_data_0), + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_rcg2_ops, + }, +}; + +static struct clk_rcg2 cam_cc_csi3phytimer_clk_src = { + .cmd_rcgr = 0x6060, + .mnd_width = 0, + .hid_width = 5, + .parent_map = cam_cc_parent_map_0, + .freq_tbl = ftbl_cam_cc_csi0phytimer_clk_src, + .clkr.hw.init = &(struct clk_init_data){ + .name = "cam_cc_csi3phytimer_clk_src", + .parent_data = cam_cc_parent_data_0, + .num_parents = ARRAY_SIZE(cam_cc_parent_data_0), + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_rcg2_ops, + }, +}; + +static struct clk_rcg2 cam_cc_csi4phytimer_clk_src = { + .cmd_rcgr = 0x6080, + .mnd_width = 0, + .hid_width = 5, + .parent_map = cam_cc_parent_map_0, + .freq_tbl = ftbl_cam_cc_csi0phytimer_clk_src, + .clkr.hw.init = &(struct clk_init_data){ + .name = "cam_cc_csi4phytimer_clk_src", + .parent_data = cam_cc_parent_data_0, + .num_parents = ARRAY_SIZE(cam_cc_parent_data_0), + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_rcg2_ops, + }, +}; + +static struct clk_rcg2 cam_cc_csi5phytimer_clk_src = { + .cmd_rcgr = 0x60a0, + .mnd_width = 0, + .hid_width = 5, + .parent_map = cam_cc_parent_map_0, + .freq_tbl = ftbl_cam_cc_csi0phytimer_clk_src, + .clkr.hw.init = &(struct clk_init_data){ + .name = "cam_cc_csi5phytimer_clk_src", + .parent_data = cam_cc_parent_data_0, + .num_parents = ARRAY_SIZE(cam_cc_parent_data_0), + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_rcg2_ops, + }, +}; + +static const struct freq_tbl ftbl_cam_cc_fast_ahb_clk_src[] = { + F(19200000, P_BI_TCXO, 1, 0, 0), + F(50000000, P_CAM_CC_PLL0_OUT_EVEN, 12, 0, 0), + F(100000000, P_CAM_CC_PLL0_OUT_EVEN, 6, 0, 0), + F(200000000, P_CAM_CC_PLL0_OUT_EVEN, 3, 0, 0), + F(300000000, P_CAM_CC_PLL0_OUT_MAIN, 4, 0, 0), + F(400000000, P_CAM_CC_PLL0_OUT_MAIN, 3, 0, 0), + { } +}; + +static struct clk_rcg2 cam_cc_fast_ahb_clk_src = { + .cmd_rcgr = 0x703c, + .mnd_width = 0, + .hid_width = 5, + .parent_map = cam_cc_parent_map_0, + .freq_tbl = ftbl_cam_cc_fast_ahb_clk_src, + .clkr.hw.init = &(struct clk_init_data){ + .name = "cam_cc_fast_ahb_clk_src", + .parent_data = cam_cc_parent_data_0, + .num_parents = ARRAY_SIZE(cam_cc_parent_data_0), + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_rcg2_ops, + }, +}; + +static const struct freq_tbl ftbl_cam_cc_fd_core_clk_src[] = { + F(19200000, P_BI_TCXO, 1, 0, 0), + F(400000000, P_CAM_CC_PLL0_OUT_ODD, 1, 0, 0), + F(480000000, P_CAM_CC_PLL2_OUT_MAIN, 1.5, 0, 0), + F(600000000, P_CAM_CC_PLL0_OUT_MAIN, 2, 0, 0), + { } +}; + +static struct clk_rcg2 cam_cc_fd_core_clk_src = { + .cmd_rcgr = 0xc098, + .mnd_width = 0, + .hid_width = 5, + .parent_map = cam_cc_parent_map_0, + .freq_tbl = ftbl_cam_cc_fd_core_clk_src, + .clkr.hw.init = &(struct clk_init_data){ + .name = "cam_cc_fd_core_clk_src", + .parent_data = cam_cc_parent_data_0, + .num_parents = ARRAY_SIZE(cam_cc_parent_data_0), + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_rcg2_ops, + }, +}; + +static struct clk_rcg2 cam_cc_icp_clk_src = { + .cmd_rcgr = 0xc074, + .mnd_width = 0, + .hid_width = 5, + .parent_map = cam_cc_parent_map_0, + .freq_tbl = ftbl_cam_cc_fd_core_clk_src, + .clkr.hw.init = &(struct clk_init_data){ + .name = "cam_cc_icp_clk_src", + .parent_data = cam_cc_parent_data_0, + .num_parents = ARRAY_SIZE(cam_cc_parent_data_0), + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_rcg2_ops, + }, +}; + +static const struct freq_tbl ftbl_cam_cc_ife_0_clk_src[] = { + F(19200000, P_BI_TCXO, 1, 0, 0), + F(350000000, P_CAM_CC_PLL3_OUT_EVEN, 1, 0, 0), + F(475000000, P_CAM_CC_PLL3_OUT_EVEN, 1, 0, 0), + F(576000000, P_CAM_CC_PLL3_OUT_EVEN, 1, 0, 0), + F(680000000, P_CAM_CC_PLL3_OUT_EVEN, 1, 0, 0), + { } +}; + +static struct clk_rcg2 cam_cc_ife_0_clk_src = { + .cmd_rcgr = 0xa010, + .mnd_width = 0, + .hid_width = 5, + .parent_map = cam_cc_parent_map_2, + .freq_tbl = ftbl_cam_cc_ife_0_clk_src, + .clkr.hw.init = &(struct clk_init_data){ + .name = "cam_cc_ife_0_clk_src", + .parent_data = cam_cc_parent_data_2, + .num_parents = ARRAY_SIZE(cam_cc_parent_data_2), + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_rcg2_ops, + }, +}; + +static struct clk_regmap_div cam_cc_sbi_div_clk_src = { + .reg = 0x9010, + .shift = 0, + .width = 3, + .clkr.hw.init = &(struct clk_init_data) { + .name = "cam_cc_sbi_div_clk_src", + .parent_hws = (const struct clk_hw*[]){ + &cam_cc_ife_0_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_regmap_div_ro_ops, + }, +}; + +static const struct freq_tbl ftbl_cam_cc_ife_0_csid_clk_src[] = { + F(19200000, P_BI_TCXO, 1, 0, 0), + F(75000000, P_CAM_CC_PLL0_OUT_EVEN, 8, 0, 0), + F(400000000, P_CAM_CC_PLL0_OUT_ODD, 1, 0, 0), + { } +}; + +static struct clk_rcg2 cam_cc_ife_0_csid_clk_src = { + .cmd_rcgr = 0xa040, + .mnd_width = 0, + .hid_width = 5, + .parent_map = cam_cc_parent_map_0, + .freq_tbl = ftbl_cam_cc_ife_0_csid_clk_src, + .clkr.hw.init = &(struct clk_init_data){ + .name = "cam_cc_ife_0_csid_clk_src", + .parent_data = cam_cc_parent_data_0, + .num_parents = ARRAY_SIZE(cam_cc_parent_data_0), + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_rcg2_ops, + }, +}; + +static const struct freq_tbl ftbl_cam_cc_ife_1_clk_src[] = { + F(19200000, P_BI_TCXO, 1, 0, 0), + F(350000000, P_CAM_CC_PLL4_OUT_EVEN, 1, 0, 0), + F(475000000, P_CAM_CC_PLL4_OUT_EVEN, 1, 0, 0), + F(576000000, P_CAM_CC_PLL4_OUT_EVEN, 1, 0, 0), + F(680000000, P_CAM_CC_PLL4_OUT_EVEN, 1, 0, 0), + { } +}; + +static struct clk_rcg2 cam_cc_ife_1_clk_src = { + .cmd_rcgr = 0xb010, + .mnd_width = 0, + .hid_width = 5, + .parent_map = cam_cc_parent_map_3, + .freq_tbl = ftbl_cam_cc_ife_1_clk_src, + .clkr.hw.init = &(struct clk_init_data){ + .name = "cam_cc_ife_1_clk_src", + .parent_data = cam_cc_parent_data_3, + .num_parents = ARRAY_SIZE(cam_cc_parent_data_3), + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_rcg2_ops, + }, +}; + +static struct clk_rcg2 cam_cc_ife_1_csid_clk_src = { + .cmd_rcgr = 0xb040, + .mnd_width = 0, + .hid_width = 5, + .parent_map = cam_cc_parent_map_0, + .freq_tbl = ftbl_cam_cc_ife_0_csid_clk_src, + .clkr.hw.init = &(struct clk_init_data){ + .name = "cam_cc_ife_1_csid_clk_src", + .parent_data = cam_cc_parent_data_0, + .num_parents = ARRAY_SIZE(cam_cc_parent_data_0), + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_rcg2_ops, + }, +}; + +static const struct freq_tbl ftbl_cam_cc_ife_lite_clk_src[] = { + F(19200000, P_BI_TCXO, 1, 0, 0), + F(400000000, P_CAM_CC_PLL0_OUT_ODD, 1, 0, 0), + F(480000000, P_CAM_CC_PLL2_OUT_MAIN, 1.5, 0, 0), + { } +}; + +static struct clk_rcg2 cam_cc_ife_lite_clk_src = { + .cmd_rcgr = 0xc000, + .mnd_width = 0, + .hid_width = 5, + .parent_map = cam_cc_parent_map_0, + .freq_tbl = ftbl_cam_cc_ife_lite_clk_src, + .clkr.hw.init = &(struct clk_init_data){ + .name = "cam_cc_ife_lite_clk_src", + .parent_data = cam_cc_parent_data_0, + .num_parents = ARRAY_SIZE(cam_cc_parent_data_0), + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_rcg2_ops, + }, +}; + +static struct clk_rcg2 cam_cc_ife_lite_csid_clk_src = { + .cmd_rcgr = 0xc01c, + .mnd_width = 0, + .hid_width = 5, + .parent_map = cam_cc_parent_map_0, + .freq_tbl = ftbl_cam_cc_cphy_rx_clk_src, + .clkr.hw.init = &(struct clk_init_data){ + .name = "cam_cc_ife_lite_csid_clk_src", + .parent_data = cam_cc_parent_data_0, + .num_parents = ARRAY_SIZE(cam_cc_parent_data_0), + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_rcg2_ops, + }, +}; + +static const struct freq_tbl ftbl_cam_cc_ipe_0_clk_src[] = { + F(19200000, P_BI_TCXO, 1, 0, 0), + F(300000000, P_CAM_CC_PLL1_OUT_EVEN, 1, 0, 0), + F(475000000, P_CAM_CC_PLL1_OUT_EVEN, 1, 0, 0), + F(525000000, P_CAM_CC_PLL1_OUT_EVEN, 1, 0, 0), + F(700000000, P_CAM_CC_PLL1_OUT_EVEN, 1, 0, 0), + { } +}; + +static struct clk_rcg2 cam_cc_ipe_0_clk_src = { + .cmd_rcgr = 0x8010, + .mnd_width = 0, + .hid_width = 5, + .parent_map = cam_cc_parent_map_4, + .freq_tbl = ftbl_cam_cc_ipe_0_clk_src, + .clkr.hw.init = &(struct clk_init_data){ + .name = "cam_cc_ipe_0_clk_src", + .parent_data = cam_cc_parent_data_4, + .num_parents = ARRAY_SIZE(cam_cc_parent_data_4), + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_rcg2_ops, + }, +}; + +static struct clk_rcg2 cam_cc_jpeg_clk_src = { + .cmd_rcgr = 0xc048, + .mnd_width = 0, + .hid_width = 5, + .parent_map = cam_cc_parent_map_0, + .freq_tbl = ftbl_cam_cc_bps_clk_src, + .clkr.hw.init = &(struct clk_init_data){ + .name = "cam_cc_jpeg_clk_src", + .parent_data = cam_cc_parent_data_0, + .num_parents = ARRAY_SIZE(cam_cc_parent_data_0), + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_rcg2_ops, + }, +}; + +static const struct freq_tbl ftbl_cam_cc_mclk0_clk_src[] = { + F(19200000, P_BI_TCXO, 1, 0, 0), + F(24000000, P_CAM_CC_PLL2_OUT_EARLY, 10, 1, 6), + F(68571429, P_CAM_CC_PLL2_OUT_EARLY, 1, 1, 21), + { } +}; + +static struct clk_rcg2 cam_cc_mclk0_clk_src = { + .cmd_rcgr = 0x5000, + .mnd_width = 8, + .hid_width = 5, + .parent_map = cam_cc_parent_map_1, + .freq_tbl = ftbl_cam_cc_mclk0_clk_src, + .clkr.hw.init = &(struct clk_init_data){ + .name = "cam_cc_mclk0_clk_src", + .parent_data = cam_cc_parent_data_1, + .num_parents = ARRAY_SIZE(cam_cc_parent_data_1), + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_rcg2_ops, + }, +}; + +static struct clk_rcg2 cam_cc_mclk1_clk_src = { + .cmd_rcgr = 0x501c, + .mnd_width = 8, + .hid_width = 5, + .parent_map = cam_cc_parent_map_1, + .freq_tbl = ftbl_cam_cc_mclk0_clk_src, + .clkr.hw.init = &(struct clk_init_data){ + .name = "cam_cc_mclk1_clk_src", + .parent_data = cam_cc_parent_data_1, + .num_parents = ARRAY_SIZE(cam_cc_parent_data_1), + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_rcg2_ops, + }, +}; + +static struct clk_rcg2 cam_cc_mclk2_clk_src = { + .cmd_rcgr = 0x5038, + .mnd_width = 8, + .hid_width = 5, + .parent_map = cam_cc_parent_map_1, + .freq_tbl = ftbl_cam_cc_mclk0_clk_src, + .clkr.hw.init = &(struct clk_init_data){ + .name = "cam_cc_mclk2_clk_src", + .parent_data = cam_cc_parent_data_1, + .num_parents = ARRAY_SIZE(cam_cc_parent_data_1), + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_rcg2_ops, + }, +}; + +static struct clk_rcg2 cam_cc_mclk3_clk_src = { + .cmd_rcgr = 0x5054, + .mnd_width = 8, + .hid_width = 5, + .parent_map = cam_cc_parent_map_1, + .freq_tbl = ftbl_cam_cc_mclk0_clk_src, + .clkr.hw.init = &(struct clk_init_data){ + .name = "cam_cc_mclk3_clk_src", + .parent_data = cam_cc_parent_data_1, + .num_parents = ARRAY_SIZE(cam_cc_parent_data_1), + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_rcg2_ops, + }, +}; + +static struct clk_rcg2 cam_cc_mclk4_clk_src = { + .cmd_rcgr = 0x5070, + .mnd_width = 8, + .hid_width = 5, + .parent_map = cam_cc_parent_map_1, + .freq_tbl = ftbl_cam_cc_mclk0_clk_src, + .clkr.hw.init = &(struct clk_init_data){ + .name = "cam_cc_mclk4_clk_src", + .parent_data = cam_cc_parent_data_1, + .num_parents = ARRAY_SIZE(cam_cc_parent_data_1), + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_rcg2_ops, + }, +}; + +static struct clk_rcg2 cam_cc_mclk5_clk_src = { + .cmd_rcgr = 0x508c, + .mnd_width = 8, + .hid_width = 5, + .parent_map = cam_cc_parent_map_1, + .freq_tbl = ftbl_cam_cc_mclk0_clk_src, + .clkr.hw.init = &(struct clk_init_data){ + .name = "cam_cc_mclk5_clk_src", + .parent_data = cam_cc_parent_data_1, + .num_parents = ARRAY_SIZE(cam_cc_parent_data_1), + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_rcg2_ops, + }, +}; + +static struct clk_rcg2 cam_cc_mclk6_clk_src = { + .cmd_rcgr = 0x50a8, + .mnd_width = 8, + .hid_width = 5, + .parent_map = cam_cc_parent_map_1, + .freq_tbl = ftbl_cam_cc_mclk0_clk_src, + .clkr.hw.init = &(struct clk_init_data){ + .name = "cam_cc_mclk6_clk_src", + .parent_data = cam_cc_parent_data_1, + .num_parents = ARRAY_SIZE(cam_cc_parent_data_1), + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_rcg2_ops, + }, +}; + +static struct clk_rcg2 cam_cc_sbi_csid_clk_src = { + .cmd_rcgr = 0x901c, + .mnd_width = 0, + .hid_width = 5, + .parent_map = cam_cc_parent_map_0, + .freq_tbl = ftbl_cam_cc_cphy_rx_clk_src, + .clkr.hw.init = &(struct clk_init_data){ + .name = "cam_cc_sbi_csid_clk_src", + .parent_data = cam_cc_parent_data_0, + .num_parents = ARRAY_SIZE(cam_cc_parent_data_0), + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_rcg2_ops, + }, +}; + +static const struct freq_tbl ftbl_cam_cc_sleep_clk_src[] = { + F(32768, P_SLEEP_CLK, 1, 0, 0), + { } +}; + +static struct clk_rcg2 cam_cc_sleep_clk_src = { + .cmd_rcgr = 0xc170, + .mnd_width = 0, + .hid_width = 5, + .parent_map = cam_cc_parent_map_5, + .freq_tbl = ftbl_cam_cc_sleep_clk_src, + .clkr.hw.init = &(struct clk_init_data){ + .name = "cam_cc_sleep_clk_src", + .parent_data = cam_cc_parent_data_5, + .num_parents = ARRAY_SIZE(cam_cc_parent_data_5), + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_rcg2_ops, + }, +}; + +static const struct freq_tbl ftbl_cam_cc_slow_ahb_clk_src[] = { + F(19200000, P_BI_TCXO, 1, 0, 0), + F(80000000, P_CAM_CC_PLL0_OUT_EVEN, 7.5, 0, 0), + { } +}; + +static struct clk_rcg2 cam_cc_slow_ahb_clk_src = { + .cmd_rcgr = 0x7058, + .mnd_width = 8, + .hid_width = 5, + .parent_map = cam_cc_parent_map_0, + .freq_tbl = ftbl_cam_cc_slow_ahb_clk_src, + .clkr.hw.init = &(struct clk_init_data){ + .name = "cam_cc_slow_ahb_clk_src", + .parent_data = cam_cc_parent_data_0, + .num_parents = ARRAY_SIZE(cam_cc_parent_data_0), + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_rcg2_ops, + }, +}; + +static const struct freq_tbl ftbl_cam_cc_xo_clk_src[] = { + F(19200000, P_BI_TCXO, 1, 0, 0), + { } +}; + +static struct clk_rcg2 cam_cc_xo_clk_src = { + .cmd_rcgr = 0xc154, + .mnd_width = 0, + .hid_width = 5, + .parent_map = cam_cc_parent_map_6, + .freq_tbl = ftbl_cam_cc_xo_clk_src, + .clkr.hw.init = &(struct clk_init_data){ + .name = "cam_cc_xo_clk_src", + .parent_data = cam_cc_parent_data_6, + .num_parents = ARRAY_SIZE(cam_cc_parent_data_6), + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_rcg2_ops, + }, +}; + +static struct clk_branch cam_cc_bps_ahb_clk = { + .halt_reg = 0x7070, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x7070, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "cam_cc_bps_ahb_clk", + .parent_hws = (const struct clk_hw*[]){ + &cam_cc_slow_ahb_clk_src.clkr.hw + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch cam_cc_bps_areg_clk = { + .halt_reg = 0x7054, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x7054, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "cam_cc_bps_areg_clk", + .parent_hws = (const struct clk_hw*[]){ + &cam_cc_fast_ahb_clk_src.clkr.hw + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch cam_cc_bps_axi_clk = { + .halt_reg = 0x7038, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x7038, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "cam_cc_bps_axi_clk", + .parent_hws = (const struct clk_hw*[]){ + &cam_cc_camnoc_axi_clk_src.clkr.hw + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch cam_cc_bps_clk = { + .halt_reg = 0x7028, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x7028, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "cam_cc_bps_clk", + .parent_hws = (const struct clk_hw*[]){ + &cam_cc_bps_clk_src.clkr.hw + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch cam_cc_camnoc_axi_clk = { + .halt_reg = 0xc114, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0xc114, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "cam_cc_camnoc_axi_clk", + .parent_hws = (const struct clk_hw*[]){ + &cam_cc_camnoc_axi_clk_src.clkr.hw + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch cam_cc_camnoc_dcd_xo_clk = { + .halt_reg = 0xc11c, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0xc11c, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "cam_cc_camnoc_dcd_xo_clk", + .parent_hws = (const struct clk_hw*[]){ + &cam_cc_xo_clk_src.clkr.hw + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch cam_cc_cci_0_clk = { + .halt_reg = 0xc0d4, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0xc0d4, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "cam_cc_cci_0_clk", + .parent_hws = (const struct clk_hw*[]){ + &cam_cc_cci_0_clk_src.clkr.hw + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch cam_cc_cci_1_clk = { + .halt_reg = 0xc0f0, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0xc0f0, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "cam_cc_cci_1_clk", + .parent_hws = (const struct clk_hw*[]){ + &cam_cc_cci_1_clk_src.clkr.hw + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch cam_cc_core_ahb_clk = { + .halt_reg = 0xc150, + .halt_check = BRANCH_HALT_DELAY, + .clkr = { + .enable_reg = 0xc150, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "cam_cc_core_ahb_clk", + .parent_hws = (const struct clk_hw*[]){ + &cam_cc_slow_ahb_clk_src.clkr.hw + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch cam_cc_cpas_ahb_clk = { + .halt_reg = 0xc0f4, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0xc0f4, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "cam_cc_cpas_ahb_clk", + .parent_hws = (const struct clk_hw*[]){ + &cam_cc_slow_ahb_clk_src.clkr.hw + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch cam_cc_csi0phytimer_clk = { + .halt_reg = 0x6018, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x6018, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "cam_cc_csi0phytimer_clk", + .parent_hws = (const struct clk_hw*[]){ + &cam_cc_csi0phytimer_clk_src.clkr.hw + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch cam_cc_csi1phytimer_clk = { + .halt_reg = 0x6038, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x6038, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "cam_cc_csi1phytimer_clk", + .parent_hws = (const struct clk_hw*[]){ + &cam_cc_csi1phytimer_clk_src.clkr.hw + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch cam_cc_csi2phytimer_clk = { + .halt_reg = 0x6058, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x6058, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "cam_cc_csi2phytimer_clk", + .parent_hws = (const struct clk_hw*[]){ + &cam_cc_csi2phytimer_clk_src.clkr.hw + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch cam_cc_csi3phytimer_clk = { + .halt_reg = 0x6078, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x6078, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "cam_cc_csi3phytimer_clk", + .parent_hws = (const struct clk_hw*[]){ + &cam_cc_csi3phytimer_clk_src.clkr.hw + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch cam_cc_csi4phytimer_clk = { + .halt_reg = 0x6098, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x6098, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "cam_cc_csi4phytimer_clk", + .parent_hws = (const struct clk_hw*[]){ + &cam_cc_csi4phytimer_clk_src.clkr.hw + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch cam_cc_csi5phytimer_clk = { + .halt_reg = 0x60b8, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x60b8, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "cam_cc_csi5phytimer_clk", + .parent_hws = (const struct clk_hw*[]){ + &cam_cc_csi5phytimer_clk_src.clkr.hw + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch cam_cc_csiphy0_clk = { + .halt_reg = 0x601c, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x601c, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "cam_cc_csiphy0_clk", + .parent_hws = (const struct clk_hw*[]){ + &cam_cc_cphy_rx_clk_src.clkr.hw + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch cam_cc_csiphy1_clk = { + .halt_reg = 0x603c, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x603c, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "cam_cc_csiphy1_clk", + .parent_hws = (const struct clk_hw*[]){ + &cam_cc_cphy_rx_clk_src.clkr.hw + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch cam_cc_csiphy2_clk = { + .halt_reg = 0x605c, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x605c, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "cam_cc_csiphy2_clk", + .parent_hws = (const struct clk_hw*[]){ + &cam_cc_cphy_rx_clk_src.clkr.hw + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch cam_cc_csiphy3_clk = { + .halt_reg = 0x607c, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x607c, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "cam_cc_csiphy3_clk", + .parent_hws = (const struct clk_hw*[]){ + &cam_cc_cphy_rx_clk_src.clkr.hw + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch cam_cc_csiphy4_clk = { + .halt_reg = 0x609c, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x609c, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "cam_cc_csiphy4_clk", + .parent_hws = (const struct clk_hw*[]){ + &cam_cc_cphy_rx_clk_src.clkr.hw + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch cam_cc_csiphy5_clk = { + .halt_reg = 0x60bc, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x60bc, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "cam_cc_csiphy5_clk", + .parent_hws = (const struct clk_hw*[]){ + &cam_cc_cphy_rx_clk_src.clkr.hw + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch cam_cc_fd_core_clk = { + .halt_reg = 0xc0b0, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0xc0b0, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "cam_cc_fd_core_clk", + .parent_hws = (const struct clk_hw*[]){ + &cam_cc_fd_core_clk_src.clkr.hw + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch cam_cc_fd_core_uar_clk = { + .halt_reg = 0xc0b8, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0xc0b8, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "cam_cc_fd_core_uar_clk", + .parent_hws = (const struct clk_hw*[]){ + &cam_cc_fd_core_clk_src.clkr.hw + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch cam_cc_gdsc_clk = { + .halt_reg = 0xc16c, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0xc16c, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "cam_cc_gdsc_clk", + .parent_hws = (const struct clk_hw*[]){ + &cam_cc_xo_clk_src.clkr.hw + }, + .num_parents = 1, + .flags = CLK_IS_CRITICAL | CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch cam_cc_icp_ahb_clk = { + .halt_reg = 0xc094, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0xc094, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "cam_cc_icp_ahb_clk", + .parent_hws = (const struct clk_hw*[]){ + &cam_cc_slow_ahb_clk_src.clkr.hw + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch cam_cc_icp_clk = { + .halt_reg = 0xc08c, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0xc08c, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "cam_cc_icp_clk", + .parent_hws = (const struct clk_hw*[]){ + &cam_cc_icp_clk_src.clkr.hw + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch cam_cc_ife_0_ahb_clk = { + .halt_reg = 0xa088, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0xa088, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "cam_cc_ife_0_ahb_clk", + .parent_hws = (const struct clk_hw*[]){ + &cam_cc_slow_ahb_clk_src.clkr.hw + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch cam_cc_ife_0_areg_clk = { + .halt_reg = 0xa030, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0xa030, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "cam_cc_ife_0_areg_clk", + .parent_hws = (const struct clk_hw*[]){ + &cam_cc_fast_ahb_clk_src.clkr.hw + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch cam_cc_ife_0_axi_clk = { + .halt_reg = 0xa084, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0xa084, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "cam_cc_ife_0_axi_clk", + .parent_hws = (const struct clk_hw*[]){ + &cam_cc_camnoc_axi_clk_src.clkr.hw + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch cam_cc_ife_0_clk = { + .halt_reg = 0xa028, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0xa028, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "cam_cc_ife_0_clk", + .parent_hws = (const struct clk_hw*[]){ + &cam_cc_ife_0_clk_src.clkr.hw + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch cam_cc_ife_0_cphy_rx_clk = { + .halt_reg = 0xa080, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0xa080, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "cam_cc_ife_0_cphy_rx_clk", + .parent_hws = (const struct clk_hw*[]){ + &cam_cc_cphy_rx_clk_src.clkr.hw + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch cam_cc_ife_0_csid_clk = { + .halt_reg = 0xa058, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0xa058, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "cam_cc_ife_0_csid_clk", + .parent_hws = (const struct clk_hw*[]){ + &cam_cc_ife_0_csid_clk_src.clkr.hw + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch cam_cc_ife_0_dsp_clk = { + .halt_reg = 0xa03c, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0xa03c, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "cam_cc_ife_0_dsp_clk", + .parent_hws = (const struct clk_hw*[]){ + &cam_cc_ife_0_clk_src.clkr.hw + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch cam_cc_ife_1_ahb_clk = { + .halt_reg = 0xb068, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0xb068, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "cam_cc_ife_1_ahb_clk", + .parent_hws = (const struct clk_hw*[]){ + &cam_cc_slow_ahb_clk_src.clkr.hw + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch cam_cc_ife_1_areg_clk = { + .halt_reg = 0xb030, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0xb030, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "cam_cc_ife_1_areg_clk", + .parent_hws = (const struct clk_hw*[]){ + &cam_cc_fast_ahb_clk_src.clkr.hw + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch cam_cc_ife_1_axi_clk = { + .halt_reg = 0xb064, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0xb064, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "cam_cc_ife_1_axi_clk", + .parent_hws = (const struct clk_hw*[]){ + &cam_cc_camnoc_axi_clk_src.clkr.hw + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch cam_cc_ife_1_clk = { + .halt_reg = 0xb028, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0xb028, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "cam_cc_ife_1_clk", + .parent_hws = (const struct clk_hw*[]){ + &cam_cc_ife_1_clk_src.clkr.hw + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch cam_cc_ife_1_cphy_rx_clk = { + .halt_reg = 0xb060, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0xb060, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "cam_cc_ife_1_cphy_rx_clk", + .parent_hws = (const struct clk_hw*[]){ + &cam_cc_cphy_rx_clk_src.clkr.hw + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch cam_cc_ife_1_csid_clk = { + .halt_reg = 0xb058, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0xb058, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "cam_cc_ife_1_csid_clk", + .parent_hws = (const struct clk_hw*[]){ + &cam_cc_ife_1_csid_clk_src.clkr.hw + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch cam_cc_ife_1_dsp_clk = { + .halt_reg = 0xb03c, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0xb03c, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "cam_cc_ife_1_dsp_clk", + .parent_hws = (const struct clk_hw*[]){ + &cam_cc_ife_1_clk_src.clkr.hw + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch cam_cc_ife_lite_ahb_clk = { + .halt_reg = 0xc040, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0xc040, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "cam_cc_ife_lite_ahb_clk", + .parent_hws = (const struct clk_hw*[]){ + &cam_cc_slow_ahb_clk_src.clkr.hw + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch cam_cc_ife_lite_axi_clk = { + .halt_reg = 0xc044, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0xc044, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "cam_cc_ife_lite_axi_clk", + .parent_hws = (const struct clk_hw*[]){ + &cam_cc_camnoc_axi_clk_src.clkr.hw + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch cam_cc_ife_lite_clk = { + .halt_reg = 0xc018, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0xc018, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "cam_cc_ife_lite_clk", + .parent_hws = (const struct clk_hw*[]){ + &cam_cc_ife_lite_clk_src.clkr.hw + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch cam_cc_ife_lite_cphy_rx_clk = { + .halt_reg = 0xc03c, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0xc03c, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "cam_cc_ife_lite_cphy_rx_clk", + .parent_hws = (const struct clk_hw*[]){ + &cam_cc_cphy_rx_clk_src.clkr.hw + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch cam_cc_ife_lite_csid_clk = { + .halt_reg = 0xc034, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0xc034, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "cam_cc_ife_lite_csid_clk", + .parent_hws = (const struct clk_hw*[]){ + &cam_cc_ife_lite_csid_clk_src.clkr.hw + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch cam_cc_ipe_0_ahb_clk = { + .halt_reg = 0x8040, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x8040, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "cam_cc_ipe_0_ahb_clk", + .parent_hws = (const struct clk_hw*[]){ + &cam_cc_slow_ahb_clk_src.clkr.hw + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch cam_cc_ipe_0_areg_clk = { + .halt_reg = 0x803c, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x803c, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "cam_cc_ipe_0_areg_clk", + .parent_hws = (const struct clk_hw*[]){ + &cam_cc_fast_ahb_clk_src.clkr.hw + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch cam_cc_ipe_0_axi_clk = { + .halt_reg = 0x8038, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x8038, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "cam_cc_ipe_0_axi_clk", + .parent_hws = (const struct clk_hw*[]){ + &cam_cc_camnoc_axi_clk_src.clkr.hw + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch cam_cc_ipe_0_clk = { + .halt_reg = 0x8028, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x8028, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "cam_cc_ipe_0_clk", + .parent_hws = (const struct clk_hw*[]){ + &cam_cc_ipe_0_clk_src.clkr.hw + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch cam_cc_jpeg_clk = { + .halt_reg = 0xc060, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0xc060, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "cam_cc_jpeg_clk", + .parent_hws = (const struct clk_hw*[]){ + &cam_cc_jpeg_clk_src.clkr.hw + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch cam_cc_mclk0_clk = { + .halt_reg = 0x5018, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x5018, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "cam_cc_mclk0_clk", + .parent_hws = (const struct clk_hw*[]){ + &cam_cc_mclk0_clk_src.clkr.hw + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch cam_cc_mclk1_clk = { + .halt_reg = 0x5034, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x5034, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "cam_cc_mclk1_clk", + .parent_hws = (const struct clk_hw*[]){ + &cam_cc_mclk1_clk_src.clkr.hw + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch cam_cc_mclk2_clk = { + .halt_reg = 0x5050, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x5050, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "cam_cc_mclk2_clk", + .parent_hws = (const struct clk_hw*[]){ + &cam_cc_mclk2_clk_src.clkr.hw + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch cam_cc_mclk3_clk = { + .halt_reg = 0x506c, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x506c, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "cam_cc_mclk3_clk", + .parent_hws = (const struct clk_hw*[]){ + &cam_cc_mclk3_clk_src.clkr.hw + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch cam_cc_mclk4_clk = { + .halt_reg = 0x5088, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x5088, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "cam_cc_mclk4_clk", + .parent_hws = (const struct clk_hw*[]){ + &cam_cc_mclk4_clk_src.clkr.hw + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch cam_cc_mclk5_clk = { + .halt_reg = 0x50a4, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x50a4, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "cam_cc_mclk5_clk", + .parent_hws = (const struct clk_hw*[]){ + &cam_cc_mclk5_clk_src.clkr.hw + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch cam_cc_mclk6_clk = { + .halt_reg = 0x50c0, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x50c0, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "cam_cc_mclk6_clk", + .parent_hws = (const struct clk_hw*[]){ + &cam_cc_mclk6_clk_src.clkr.hw + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch cam_cc_sbi_ahb_clk = { + .halt_reg = 0x9040, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x9040, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "cam_cc_sbi_ahb_clk", + .parent_hws = (const struct clk_hw*[]){ + &cam_cc_slow_ahb_clk_src.clkr.hw + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch cam_cc_sbi_axi_clk = { + .halt_reg = 0x903c, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x903c, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "cam_cc_sbi_axi_clk", + .parent_hws = (const struct clk_hw*[]){ + &cam_cc_camnoc_axi_clk_src.clkr.hw + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch cam_cc_sbi_clk = { + .halt_reg = 0x9014, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x9014, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "cam_cc_sbi_clk", + .parent_hws = (const struct clk_hw*[]){ + &cam_cc_sbi_div_clk_src.clkr.hw + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch cam_cc_sbi_cphy_rx_clk = { + .halt_reg = 0x9038, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x9038, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "cam_cc_sbi_cphy_rx_clk", + .parent_hws = (const struct clk_hw*[]){ + &cam_cc_cphy_rx_clk_src.clkr.hw + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch cam_cc_sbi_csid_clk = { + .halt_reg = 0x9034, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x9034, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "cam_cc_sbi_csid_clk", + .parent_hws = (const struct clk_hw*[]){ + &cam_cc_sbi_csid_clk_src.clkr.hw + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch cam_cc_sbi_ife_0_clk = { + .halt_reg = 0x9044, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x9044, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "cam_cc_sbi_ife_0_clk", + .parent_hws = (const struct clk_hw*[]){ + &cam_cc_ife_0_clk_src.clkr.hw + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch cam_cc_sbi_ife_1_clk = { + .halt_reg = 0x9048, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x9048, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "cam_cc_sbi_ife_1_clk", + .parent_hws = (const struct clk_hw*[]){ + &cam_cc_ife_1_clk_src.clkr.hw + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch cam_cc_sleep_clk = { + .halt_reg = 0xc188, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0xc188, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "cam_cc_sleep_clk", + .parent_hws = (const struct clk_hw*[]){ + &cam_cc_sleep_clk_src.clkr.hw + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct gdsc bps_gdsc = { + .gdscr = 0x7004, + .pd = { + .name = "bps_gdsc", + }, + .flags = HW_CTRL | POLL_CFG_GDSCR, + .pwrsts = PWRSTS_OFF_ON, +}; + +static struct gdsc ipe_0_gdsc = { + .gdscr = 0x8004, + .pd = { + .name = "ipe_0_gdsc", + }, + .flags = HW_CTRL | POLL_CFG_GDSCR, + .pwrsts = PWRSTS_OFF_ON, +}; + +static struct gdsc sbi_gdsc = { + .gdscr = 0x9004, + .pd = { + .name = "sbi_gdsc", + }, + .flags = HW_CTRL | POLL_CFG_GDSCR, + .pwrsts = PWRSTS_OFF_ON, +}; + +static struct gdsc ife_0_gdsc = { + .gdscr = 0xa004, + .pd = { + .name = "ife_0_gdsc", + }, + .flags = POLL_CFG_GDSCR, + .pwrsts = PWRSTS_OFF_ON, +}; + +static struct gdsc ife_1_gdsc = { + .gdscr = 0xb004, + .pd = { + .name = "ife_1_gdsc", + }, + .flags = POLL_CFG_GDSCR, + .pwrsts = PWRSTS_OFF_ON, +}; + +static struct gdsc titan_top_gdsc = { + .gdscr = 0xc144, + .pd = { + .name = "titan_top_gdsc", + }, + .flags = POLL_CFG_GDSCR, + .pwrsts = PWRSTS_OFF_ON, +}; + +static struct clk_regmap *cam_cc_sm8250_clocks[] = { + [CAM_CC_BPS_AHB_CLK] = &cam_cc_bps_ahb_clk.clkr, + [CAM_CC_BPS_AREG_CLK] = &cam_cc_bps_areg_clk.clkr, + [CAM_CC_BPS_AXI_CLK] = &cam_cc_bps_axi_clk.clkr, + [CAM_CC_BPS_CLK] = &cam_cc_bps_clk.clkr, + [CAM_CC_BPS_CLK_SRC] = &cam_cc_bps_clk_src.clkr, + [CAM_CC_CAMNOC_AXI_CLK] = &cam_cc_camnoc_axi_clk.clkr, + [CAM_CC_CAMNOC_AXI_CLK_SRC] = &cam_cc_camnoc_axi_clk_src.clkr, + [CAM_CC_CAMNOC_DCD_XO_CLK] = &cam_cc_camnoc_dcd_xo_clk.clkr, + [CAM_CC_CCI_0_CLK] = &cam_cc_cci_0_clk.clkr, + [CAM_CC_CCI_0_CLK_SRC] = &cam_cc_cci_0_clk_src.clkr, + [CAM_CC_CCI_1_CLK] = &cam_cc_cci_1_clk.clkr, + [CAM_CC_CCI_1_CLK_SRC] = &cam_cc_cci_1_clk_src.clkr, + [CAM_CC_CORE_AHB_CLK] = &cam_cc_core_ahb_clk.clkr, + [CAM_CC_CPAS_AHB_CLK] = &cam_cc_cpas_ahb_clk.clkr, + [CAM_CC_CPHY_RX_CLK_SRC] = &cam_cc_cphy_rx_clk_src.clkr, + [CAM_CC_CSI0PHYTIMER_CLK] = &cam_cc_csi0phytimer_clk.clkr, + [CAM_CC_CSI0PHYTIMER_CLK_SRC] = &cam_cc_csi0phytimer_clk_src.clkr, + [CAM_CC_CSI1PHYTIMER_CLK] = &cam_cc_csi1phytimer_clk.clkr, + [CAM_CC_CSI1PHYTIMER_CLK_SRC] = &cam_cc_csi1phytimer_clk_src.clkr, + [CAM_CC_CSI2PHYTIMER_CLK] = &cam_cc_csi2phytimer_clk.clkr, + [CAM_CC_CSI2PHYTIMER_CLK_SRC] = &cam_cc_csi2phytimer_clk_src.clkr, + [CAM_CC_CSI3PHYTIMER_CLK] = &cam_cc_csi3phytimer_clk.clkr, + [CAM_CC_CSI3PHYTIMER_CLK_SRC] = &cam_cc_csi3phytimer_clk_src.clkr, + [CAM_CC_CSI4PHYTIMER_CLK] = &cam_cc_csi4phytimer_clk.clkr, + [CAM_CC_CSI4PHYTIMER_CLK_SRC] = &cam_cc_csi4phytimer_clk_src.clkr, + [CAM_CC_CSI5PHYTIMER_CLK] = &cam_cc_csi5phytimer_clk.clkr, + [CAM_CC_CSI5PHYTIMER_CLK_SRC] = &cam_cc_csi5phytimer_clk_src.clkr, + [CAM_CC_CSIPHY0_CLK] = &cam_cc_csiphy0_clk.clkr, + [CAM_CC_CSIPHY1_CLK] = &cam_cc_csiphy1_clk.clkr, + [CAM_CC_CSIPHY2_CLK] = &cam_cc_csiphy2_clk.clkr, + [CAM_CC_CSIPHY3_CLK] = &cam_cc_csiphy3_clk.clkr, + [CAM_CC_CSIPHY4_CLK] = &cam_cc_csiphy4_clk.clkr, + [CAM_CC_CSIPHY5_CLK] = &cam_cc_csiphy5_clk.clkr, + [CAM_CC_FAST_AHB_CLK_SRC] = &cam_cc_fast_ahb_clk_src.clkr, + [CAM_CC_FD_CORE_CLK] = &cam_cc_fd_core_clk.clkr, + [CAM_CC_FD_CORE_CLK_SRC] = &cam_cc_fd_core_clk_src.clkr, + [CAM_CC_FD_CORE_UAR_CLK] = &cam_cc_fd_core_uar_clk.clkr, + [CAM_CC_GDSC_CLK] = &cam_cc_gdsc_clk.clkr, + [CAM_CC_ICP_AHB_CLK] = &cam_cc_icp_ahb_clk.clkr, + [CAM_CC_ICP_CLK] = &cam_cc_icp_clk.clkr, + [CAM_CC_ICP_CLK_SRC] = &cam_cc_icp_clk_src.clkr, + [CAM_CC_IFE_0_AHB_CLK] = &cam_cc_ife_0_ahb_clk.clkr, + [CAM_CC_IFE_0_AREG_CLK] = &cam_cc_ife_0_areg_clk.clkr, + [CAM_CC_IFE_0_AXI_CLK] = &cam_cc_ife_0_axi_clk.clkr, + [CAM_CC_IFE_0_CLK] = &cam_cc_ife_0_clk.clkr, + [CAM_CC_IFE_0_CLK_SRC] = &cam_cc_ife_0_clk_src.clkr, + [CAM_CC_IFE_0_CPHY_RX_CLK] = &cam_cc_ife_0_cphy_rx_clk.clkr, + [CAM_CC_IFE_0_CSID_CLK] = &cam_cc_ife_0_csid_clk.clkr, + [CAM_CC_IFE_0_CSID_CLK_SRC] = &cam_cc_ife_0_csid_clk_src.clkr, + [CAM_CC_IFE_0_DSP_CLK] = &cam_cc_ife_0_dsp_clk.clkr, + [CAM_CC_IFE_1_AHB_CLK] = &cam_cc_ife_1_ahb_clk.clkr, + [CAM_CC_IFE_1_AREG_CLK] = &cam_cc_ife_1_areg_clk.clkr, + [CAM_CC_IFE_1_AXI_CLK] = &cam_cc_ife_1_axi_clk.clkr, + [CAM_CC_IFE_1_CLK] = &cam_cc_ife_1_clk.clkr, + [CAM_CC_IFE_1_CLK_SRC] = &cam_cc_ife_1_clk_src.clkr, + [CAM_CC_IFE_1_CPHY_RX_CLK] = &cam_cc_ife_1_cphy_rx_clk.clkr, + [CAM_CC_IFE_1_CSID_CLK] = &cam_cc_ife_1_csid_clk.clkr, + [CAM_CC_IFE_1_CSID_CLK_SRC] = &cam_cc_ife_1_csid_clk_src.clkr, + [CAM_CC_IFE_1_DSP_CLK] = &cam_cc_ife_1_dsp_clk.clkr, + [CAM_CC_IFE_LITE_AHB_CLK] = &cam_cc_ife_lite_ahb_clk.clkr, + [CAM_CC_IFE_LITE_AXI_CLK] = &cam_cc_ife_lite_axi_clk.clkr, + [CAM_CC_IFE_LITE_CLK] = &cam_cc_ife_lite_clk.clkr, + [CAM_CC_IFE_LITE_CLK_SRC] = &cam_cc_ife_lite_clk_src.clkr, + [CAM_CC_IFE_LITE_CPHY_RX_CLK] = &cam_cc_ife_lite_cphy_rx_clk.clkr, + [CAM_CC_IFE_LITE_CSID_CLK] = &cam_cc_ife_lite_csid_clk.clkr, + [CAM_CC_IFE_LITE_CSID_CLK_SRC] = &cam_cc_ife_lite_csid_clk_src.clkr, + [CAM_CC_IPE_0_AHB_CLK] = &cam_cc_ipe_0_ahb_clk.clkr, + [CAM_CC_IPE_0_AREG_CLK] = &cam_cc_ipe_0_areg_clk.clkr, + [CAM_CC_IPE_0_AXI_CLK] = &cam_cc_ipe_0_axi_clk.clkr, + [CAM_CC_IPE_0_CLK] = &cam_cc_ipe_0_clk.clkr, + [CAM_CC_IPE_0_CLK_SRC] = &cam_cc_ipe_0_clk_src.clkr, + [CAM_CC_JPEG_CLK] = &cam_cc_jpeg_clk.clkr, + [CAM_CC_JPEG_CLK_SRC] = &cam_cc_jpeg_clk_src.clkr, + [CAM_CC_MCLK0_CLK] = &cam_cc_mclk0_clk.clkr, + [CAM_CC_MCLK0_CLK_SRC] = &cam_cc_mclk0_clk_src.clkr, + [CAM_CC_MCLK1_CLK] = &cam_cc_mclk1_clk.clkr, + [CAM_CC_MCLK1_CLK_SRC] = &cam_cc_mclk1_clk_src.clkr, + [CAM_CC_MCLK2_CLK] = &cam_cc_mclk2_clk.clkr, + [CAM_CC_MCLK2_CLK_SRC] = &cam_cc_mclk2_clk_src.clkr, + [CAM_CC_MCLK3_CLK] = &cam_cc_mclk3_clk.clkr, + [CAM_CC_MCLK3_CLK_SRC] = &cam_cc_mclk3_clk_src.clkr, + [CAM_CC_MCLK4_CLK] = &cam_cc_mclk4_clk.clkr, + [CAM_CC_MCLK4_CLK_SRC] = &cam_cc_mclk4_clk_src.clkr, + [CAM_CC_MCLK5_CLK] = &cam_cc_mclk5_clk.clkr, + [CAM_CC_MCLK5_CLK_SRC] = &cam_cc_mclk5_clk_src.clkr, + [CAM_CC_MCLK6_CLK] = &cam_cc_mclk6_clk.clkr, + [CAM_CC_MCLK6_CLK_SRC] = &cam_cc_mclk6_clk_src.clkr, + [CAM_CC_PLL0] = &cam_cc_pll0.clkr, + [CAM_CC_PLL0_OUT_EVEN] = &cam_cc_pll0_out_even.clkr, + [CAM_CC_PLL0_OUT_ODD] = &cam_cc_pll0_out_odd.clkr, + [CAM_CC_PLL1] = &cam_cc_pll1.clkr, + [CAM_CC_PLL1_OUT_EVEN] = &cam_cc_pll1_out_even.clkr, + [CAM_CC_PLL2] = &cam_cc_pll2.clkr, + [CAM_CC_PLL2_OUT_MAIN] = &cam_cc_pll2_out_main.clkr, + [CAM_CC_PLL3] = &cam_cc_pll3.clkr, + [CAM_CC_PLL3_OUT_EVEN] = &cam_cc_pll3_out_even.clkr, + [CAM_CC_PLL4] = &cam_cc_pll4.clkr, + [CAM_CC_PLL4_OUT_EVEN] = &cam_cc_pll4_out_even.clkr, + [CAM_CC_SBI_AHB_CLK] = &cam_cc_sbi_ahb_clk.clkr, + [CAM_CC_SBI_AXI_CLK] = &cam_cc_sbi_axi_clk.clkr, + [CAM_CC_SBI_CLK] = &cam_cc_sbi_clk.clkr, + [CAM_CC_SBI_CPHY_RX_CLK] = &cam_cc_sbi_cphy_rx_clk.clkr, + [CAM_CC_SBI_CSID_CLK] = &cam_cc_sbi_csid_clk.clkr, + [CAM_CC_SBI_CSID_CLK_SRC] = &cam_cc_sbi_csid_clk_src.clkr, + [CAM_CC_SBI_DIV_CLK_SRC] = &cam_cc_sbi_div_clk_src.clkr, + [CAM_CC_SBI_IFE_0_CLK] = &cam_cc_sbi_ife_0_clk.clkr, + [CAM_CC_SBI_IFE_1_CLK] = &cam_cc_sbi_ife_1_clk.clkr, + [CAM_CC_SLEEP_CLK] = &cam_cc_sleep_clk.clkr, + [CAM_CC_SLEEP_CLK_SRC] = &cam_cc_sleep_clk_src.clkr, + [CAM_CC_SLOW_AHB_CLK_SRC] = &cam_cc_slow_ahb_clk_src.clkr, + [CAM_CC_XO_CLK_SRC] = &cam_cc_xo_clk_src.clkr, +}; + +static struct gdsc *cam_cc_sm8250_gdscs[] = { + [BPS_GDSC] = &bps_gdsc, + [IPE_0_GDSC] = &ipe_0_gdsc, + [SBI_GDSC] = &sbi_gdsc, + [IFE_0_GDSC] = &ife_0_gdsc, + [IFE_1_GDSC] = &ife_1_gdsc, + [TITAN_TOP_GDSC] = &titan_top_gdsc, +}; + +static const struct qcom_reset_map cam_cc_sm8250_resets[] = { + [CAM_CC_BPS_BCR] = { 0x7000 }, + [CAM_CC_ICP_BCR] = { 0xc070 }, + [CAM_CC_IFE_0_BCR] = { 0xa000 }, + [CAM_CC_IFE_1_BCR] = { 0xb000 }, + [CAM_CC_IPE_0_BCR] = { 0x8000 }, + [CAM_CC_SBI_BCR] = { 0x9000 }, +}; + +static const struct regmap_config cam_cc_sm8250_regmap_config = { + .reg_bits = 32, + .reg_stride = 4, + .val_bits = 32, + .max_register = 0xe004, + .fast_io = true, +}; + +static const struct qcom_cc_desc cam_cc_sm8250_desc = { + .config = &cam_cc_sm8250_regmap_config, + .clks = cam_cc_sm8250_clocks, + .num_clks = ARRAY_SIZE(cam_cc_sm8250_clocks), + .resets = cam_cc_sm8250_resets, + .num_resets = ARRAY_SIZE(cam_cc_sm8250_resets), + .gdscs = cam_cc_sm8250_gdscs, + .num_gdscs = ARRAY_SIZE(cam_cc_sm8250_gdscs), +}; + +static const struct of_device_id cam_cc_sm8250_match_table[] = { + { .compatible = "qcom,sm8250-camcc" }, + { } +}; +MODULE_DEVICE_TABLE(of, cam_cc_sm8250_match_table); + +static int cam_cc_sm8250_probe(struct platform_device *pdev) +{ + struct regmap *regmap; + + regmap = qcom_cc_map(pdev, &cam_cc_sm8250_desc); + if (IS_ERR(regmap)) + return PTR_ERR(regmap); + + clk_lucid_pll_configure(&cam_cc_pll0, regmap, &cam_cc_pll0_config); + clk_lucid_pll_configure(&cam_cc_pll1, regmap, &cam_cc_pll1_config); + clk_zonda_pll_configure(&cam_cc_pll2, regmap, &cam_cc_pll2_config); + clk_lucid_pll_configure(&cam_cc_pll3, regmap, &cam_cc_pll3_config); + clk_lucid_pll_configure(&cam_cc_pll4, regmap, &cam_cc_pll4_config); + + return qcom_cc_really_probe(pdev, &cam_cc_sm8250_desc, regmap); +} + +static struct platform_driver cam_cc_sm8250_driver = { + .probe = cam_cc_sm8250_probe, + .driver = { + .name = "cam_cc-sm8250", + .of_match_table = cam_cc_sm8250_match_table, + }, +}; + +static int __init cam_cc_sm8250_init(void) +{ + return platform_driver_register(&cam_cc_sm8250_driver); +} +subsys_initcall(cam_cc_sm8250_init); + +static void __exit cam_cc_sm8250_exit(void) +{ + platform_driver_unregister(&cam_cc_sm8250_driver); +} +module_exit(cam_cc_sm8250_exit); + +MODULE_DESCRIPTION("QTI CAMCC SM8250 Driver"); +MODULE_LICENSE("GPL v2"); diff --git a/drivers/clk/qcom/clk-alpha-pll.c b/drivers/clk/qcom/clk-alpha-pll.c index c6eb99169ddc..eaedcceb766f 100644 --- a/drivers/clk/qcom/clk-alpha-pll.c +++ b/drivers/clk/qcom/clk-alpha-pll.c @@ -126,6 +126,19 @@ const u8 clk_alpha_pll_regs[][PLL_OFF_MAX_REGS] = { [PLL_OFF_TEST_CTL_U] = 0x1c, [PLL_OFF_STATUS] = 0x2c, }, + [CLK_ALPHA_PLL_TYPE_ZONDA] = { + [PLL_OFF_L_VAL] = 0x04, + [PLL_OFF_ALPHA_VAL] = 0x08, + [PLL_OFF_USER_CTL] = 0x0c, + [PLL_OFF_CONFIG_CTL] = 0x10, + [PLL_OFF_CONFIG_CTL_U] = 0x14, + [PLL_OFF_CONFIG_CTL_U1] = 0x18, + [PLL_OFF_TEST_CTL] = 0x1c, + [PLL_OFF_TEST_CTL_U] = 0x20, + [PLL_OFF_TEST_CTL_U1] = 0x24, + [PLL_OFF_OPMODE] = 0x28, + [PLL_OFF_STATUS] = 0x38, + }, }; EXPORT_SYMBOL_GPL(clk_alpha_pll_regs); @@ -162,6 +175,11 @@ EXPORT_SYMBOL_GPL(clk_alpha_pll_regs); #define LUCID_5LPE_PLL_LATCH_INPUT BIT(14) #define LUCID_5LPE_ENABLE_VOTE_RUN BIT(21) +/* ZONDA PLL specific */ +#define ZONDA_PLL_OUT_MASK 0xf +#define ZONDA_STAY_IN_CFA BIT(16) +#define ZONDA_PLL_FREQ_LOCK_DET BIT(29) + #define pll_alpha_width(p) \ ((PLL_ALPHA_VAL_U(p) - PLL_ALPHA_VAL(p) == 4) ? \ ALPHA_REG_BITWIDTH : ALPHA_REG_16BIT_WIDTH) @@ -208,6 +226,9 @@ static int wait_for_pll(struct clk_alpha_pll *pll, u32 mask, bool inverse, #define wait_for_pll_enable_lock(pll) \ wait_for_pll(pll, PLL_LOCK_DET, 0, "enable") +#define wait_for_zonda_pll_freq_lock(pll) \ + wait_for_pll(pll, ZONDA_PLL_FREQ_LOCK_DET, 0, "freq enable") + #define wait_for_pll_disable(pll) \ wait_for_pll(pll, PLL_ACTIVE_FLAG, 1, "disable") @@ -1234,7 +1255,7 @@ static int alpha_pll_fabia_prepare(struct clk_hw *hw) return ret; /* Setup PLL for calibration frequency */ - regmap_write(pll->clkr.regmap, PLL_ALPHA_VAL(pll), cal_l); + regmap_write(pll->clkr.regmap, PLL_CAL_L_VAL(pll), cal_l); /* Bringup the PLL at calibration frequency */ ret = clk_alpha_pll_enable(hw); @@ -1777,3 +1798,156 @@ const struct clk_ops clk_alpha_pll_postdiv_lucid_5lpe_ops = { .set_rate = clk_lucid_5lpe_pll_postdiv_set_rate, }; EXPORT_SYMBOL(clk_alpha_pll_postdiv_lucid_5lpe_ops); + +void clk_zonda_pll_configure(struct clk_alpha_pll *pll, struct regmap *regmap, + const struct alpha_pll_config *config) +{ + clk_alpha_pll_write_config(regmap, PLL_L_VAL(pll), config->l); + clk_alpha_pll_write_config(regmap, PLL_ALPHA_VAL(pll), config->alpha); + clk_alpha_pll_write_config(regmap, PLL_CONFIG_CTL(pll), config->config_ctl_val); + clk_alpha_pll_write_config(regmap, PLL_CONFIG_CTL_U(pll), config->config_ctl_hi_val); + clk_alpha_pll_write_config(regmap, PLL_CONFIG_CTL_U1(pll), config->config_ctl_hi1_val); + clk_alpha_pll_write_config(regmap, PLL_USER_CTL(pll), config->user_ctl_val); + clk_alpha_pll_write_config(regmap, PLL_USER_CTL_U(pll), config->user_ctl_hi_val); + clk_alpha_pll_write_config(regmap, PLL_USER_CTL_U1(pll), config->user_ctl_hi1_val); + clk_alpha_pll_write_config(regmap, PLL_TEST_CTL(pll), config->test_ctl_val); + clk_alpha_pll_write_config(regmap, PLL_TEST_CTL_U(pll), config->test_ctl_hi_val); + clk_alpha_pll_write_config(regmap, PLL_TEST_CTL_U1(pll), config->test_ctl_hi1_val); + + regmap_update_bits(regmap, PLL_MODE(pll), PLL_BYPASSNL, 0); + + /* Disable PLL output */ + regmap_update_bits(regmap, PLL_MODE(pll), PLL_OUTCTRL, 0); + + /* Set operation mode to OFF */ + regmap_write(regmap, PLL_OPMODE(pll), PLL_STANDBY); + + /* Place the PLL in STANDBY mode */ + regmap_update_bits(regmap, PLL_MODE(pll), PLL_RESET_N, PLL_RESET_N); +} +EXPORT_SYMBOL_GPL(clk_zonda_pll_configure); + +static int clk_zonda_pll_enable(struct clk_hw *hw) +{ + struct clk_alpha_pll *pll = to_clk_alpha_pll(hw); + struct regmap *regmap = pll->clkr.regmap; + u32 val; + int ret; + + regmap_read(regmap, PLL_MODE(pll), &val); + + /* If in FSM mode, just vote for it */ + if (val & PLL_VOTE_FSM_ENA) { + ret = clk_enable_regmap(hw); + if (ret) + return ret; + return wait_for_pll_enable_active(pll); + } + + /* Get the PLL out of bypass mode */ + regmap_update_bits(regmap, PLL_MODE(pll), PLL_BYPASSNL, PLL_BYPASSNL); + + /* + * H/W requires a 1us delay between disabling the bypass and + * de-asserting the reset. + */ + udelay(1); + + regmap_update_bits(regmap, PLL_MODE(pll), PLL_RESET_N, PLL_RESET_N); + + /* Set operation mode to RUN */ + regmap_write(regmap, PLL_OPMODE(pll), PLL_RUN); + + regmap_read(regmap, PLL_TEST_CTL(pll), &val); + + /* If cfa mode then poll for freq lock */ + if (val & ZONDA_STAY_IN_CFA) + ret = wait_for_zonda_pll_freq_lock(pll); + else + ret = wait_for_pll_enable_lock(pll); + if (ret) + return ret; + + /* Enable the PLL outputs */ + regmap_update_bits(regmap, PLL_USER_CTL(pll), ZONDA_PLL_OUT_MASK, ZONDA_PLL_OUT_MASK); + + /* Enable the global PLL outputs */ + regmap_update_bits(regmap, PLL_MODE(pll), PLL_OUTCTRL, PLL_OUTCTRL); + + return 0; +} + +static void clk_zonda_pll_disable(struct clk_hw *hw) +{ + struct clk_alpha_pll *pll = to_clk_alpha_pll(hw); + struct regmap *regmap = pll->clkr.regmap; + u32 val; + + regmap_read(regmap, PLL_MODE(pll), &val); + + /* If in FSM mode, just unvote it */ + if (val & PLL_VOTE_FSM_ENA) { + clk_disable_regmap(hw); + return; + } + + /* Disable the global PLL output */ + regmap_update_bits(regmap, PLL_MODE(pll), PLL_OUTCTRL, 0); + + /* Disable the PLL outputs */ + regmap_update_bits(regmap, PLL_USER_CTL(pll), ZONDA_PLL_OUT_MASK, 0); + + /* Put the PLL in bypass and reset */ + regmap_update_bits(regmap, PLL_MODE(pll), PLL_RESET_N | PLL_BYPASSNL, 0); + + /* Place the PLL mode in OFF state */ + regmap_write(regmap, PLL_OPMODE(pll), 0x0); +} + +static int clk_zonda_pll_set_rate(struct clk_hw *hw, unsigned long rate, + unsigned long prate) +{ + struct clk_alpha_pll *pll = to_clk_alpha_pll(hw); + unsigned long rrate; + u32 test_ctl_val; + u32 l, alpha_width = pll_alpha_width(pll); + u64 a; + int ret; + + rrate = alpha_pll_round_rate(rate, prate, &l, &a, alpha_width); + + ret = alpha_pll_check_rate_margin(hw, rrate, rate); + if (ret < 0) + return ret; + + regmap_write(pll->clkr.regmap, PLL_ALPHA_VAL(pll), a); + regmap_write(pll->clkr.regmap, PLL_L_VAL(pll), l); + + /* Wait before polling for the frequency latch */ + udelay(5); + + /* Read stay in cfa mode */ + regmap_read(pll->clkr.regmap, PLL_TEST_CTL(pll), &test_ctl_val); + + /* If cfa mode then poll for freq lock */ + if (test_ctl_val & ZONDA_STAY_IN_CFA) + ret = wait_for_zonda_pll_freq_lock(pll); + else + ret = wait_for_pll_enable_lock(pll); + if (ret) + return ret; + + /* Wait for PLL output to stabilize */ + udelay(100); + return 0; +} + +const struct clk_ops clk_alpha_pll_zonda_ops = { + .enable = clk_zonda_pll_enable, + .disable = clk_zonda_pll_disable, + .is_enabled = clk_trion_pll_is_enabled, + .recalc_rate = clk_trion_pll_recalc_rate, + .round_rate = clk_alpha_pll_round_rate, + .set_rate = clk_zonda_pll_set_rate, +}; +EXPORT_SYMBOL(clk_alpha_pll_zonda_ops); diff --git a/drivers/clk/qcom/clk-alpha-pll.h b/drivers/clk/qcom/clk-alpha-pll.h index 6943e933be0f..55e4fa47912f 100644 --- a/drivers/clk/qcom/clk-alpha-pll.h +++ b/drivers/clk/qcom/clk-alpha-pll.h @@ -16,6 +16,7 @@ enum { CLK_ALPHA_PLL_TYPE_TRION, CLK_ALPHA_PLL_TYPE_LUCID = CLK_ALPHA_PLL_TYPE_TRION, CLK_ALPHA_PLL_TYPE_AGERA, + CLK_ALPHA_PLL_TYPE_ZONDA, CLK_ALPHA_PLL_TYPE_MAX, }; @@ -148,6 +149,9 @@ extern const struct clk_ops clk_alpha_pll_lucid_5lpe_ops; extern const struct clk_ops clk_alpha_pll_fixed_lucid_5lpe_ops; extern const struct clk_ops clk_alpha_pll_postdiv_lucid_5lpe_ops; +extern const struct clk_ops clk_alpha_pll_zonda_ops; +#define clk_alpha_pll_postdiv_zonda_ops clk_alpha_pll_postdiv_fabia_ops + void clk_alpha_pll_configure(struct clk_alpha_pll *pll, struct regmap *regmap, const struct alpha_pll_config *config); void clk_fabia_pll_configure(struct clk_alpha_pll *pll, struct regmap *regmap, @@ -159,6 +163,8 @@ void clk_agera_pll_configure(struct clk_alpha_pll *pll, struct regmap *regmap, #define clk_lucid_pll_configure(pll, regmap, config) \ clk_trion_pll_configure(pll, regmap, config) +void clk_zonda_pll_configure(struct clk_alpha_pll *pll, struct regmap *regmap, + const struct alpha_pll_config *config); #endif diff --git a/drivers/clk/qcom/clk-rcg2.c b/drivers/clk/qcom/clk-rcg2.c index 05ff3b0d233e..e1b1b426fae4 100644 --- a/drivers/clk/qcom/clk-rcg2.c +++ b/drivers/clk/qcom/clk-rcg2.c @@ -357,6 +357,83 @@ static int clk_rcg2_set_floor_rate_and_parent(struct clk_hw *hw, return __clk_rcg2_set_rate(hw, rate, FLOOR); } +static int clk_rcg2_get_duty_cycle(struct clk_hw *hw, struct clk_duty *duty) +{ + struct clk_rcg2 *rcg = to_clk_rcg2(hw); + u32 notn_m, n, m, d, not2d, mask; + + if (!rcg->mnd_width) { + /* 50 % duty-cycle for Non-MND RCGs */ + duty->num = 1; + duty->den = 2; + return 0; + } + + regmap_read(rcg->clkr.regmap, RCG_D_OFFSET(rcg), ¬2d); + regmap_read(rcg->clkr.regmap, RCG_M_OFFSET(rcg), &m); + regmap_read(rcg->clkr.regmap, RCG_N_OFFSET(rcg), ¬n_m); + + if (!not2d && !m && !notn_m) { + /* 50 % duty-cycle always */ + duty->num = 1; + duty->den = 2; + return 0; + } + + mask = BIT(rcg->mnd_width) - 1; + + d = ~(not2d) & mask; + d = DIV_ROUND_CLOSEST(d, 2); + + n = (~(notn_m) + m) & mask; + + duty->num = d; + duty->den = n; + + return 0; +} + +static int clk_rcg2_set_duty_cycle(struct clk_hw *hw, struct clk_duty *duty) +{ + struct clk_rcg2 *rcg = to_clk_rcg2(hw); + u32 notn_m, n, m, d, not2d, mask, duty_per; + int ret; + + /* Duty-cycle cannot be modified for non-MND RCGs */ + if (!rcg->mnd_width) + return -EINVAL; + + mask = BIT(rcg->mnd_width) - 1; + + regmap_read(rcg->clkr.regmap, RCG_N_OFFSET(rcg), ¬n_m); + regmap_read(rcg->clkr.regmap, RCG_M_OFFSET(rcg), &m); + + n = (~(notn_m) + m) & mask; + + duty_per = (duty->num * 100) / duty->den; + + /* Calculate 2d value */ + d = DIV_ROUND_CLOSEST(n * duty_per * 2, 100); + + /* Check bit widths of 2d. If D is too big reduce duty cycle. */ + if (d > mask) + d = mask; + + if ((d / 2) > (n - m)) + d = (n - m) * 2; + else if ((d / 2) < (m / 2)) + d = m; + + not2d = ~d & mask; + + ret = regmap_update_bits(rcg->clkr.regmap, RCG_D_OFFSET(rcg), mask, + not2d); + if (ret) + return ret; + + return update_config(rcg); +} + const struct clk_ops clk_rcg2_ops = { .is_enabled = clk_rcg2_is_enabled, .get_parent = clk_rcg2_get_parent, @@ -365,6 +442,8 @@ const struct clk_ops clk_rcg2_ops = { .determine_rate = clk_rcg2_determine_rate, .set_rate = clk_rcg2_set_rate, .set_rate_and_parent = clk_rcg2_set_rate_and_parent, + .get_duty_cycle = clk_rcg2_get_duty_cycle, + .set_duty_cycle = clk_rcg2_set_duty_cycle, }; EXPORT_SYMBOL_GPL(clk_rcg2_ops); @@ -376,6 +455,8 @@ const struct clk_ops clk_rcg2_floor_ops = { .determine_rate = clk_rcg2_determine_floor_rate, .set_rate = clk_rcg2_set_floor_rate, .set_rate_and_parent = clk_rcg2_set_floor_rate_and_parent, + .get_duty_cycle = clk_rcg2_get_duty_cycle, + .set_duty_cycle = clk_rcg2_set_duty_cycle, }; EXPORT_SYMBOL_GPL(clk_rcg2_floor_ops); diff --git a/drivers/clk/qcom/clk-smd-rpm.c b/drivers/clk/qcom/clk-smd-rpm.c index 0e1dfa89489e..800b2fef1887 100644 --- a/drivers/clk/qcom/clk-smd-rpm.c +++ b/drivers/clk/qcom/clk-smd-rpm.c @@ -39,7 +39,10 @@ .hw.init = &(struct clk_init_data){ \ .ops = &clk_smd_rpm_ops, \ .name = #_name, \ - .parent_names = (const char *[]){ "xo_board" }, \ + .parent_data = &(const struct clk_parent_data){ \ + .fw_name = "xo", \ + .name = "xo_board", \ + }, \ .num_parents = 1, \ }, \ }; \ @@ -54,7 +57,10 @@ .hw.init = &(struct clk_init_data){ \ .ops = &clk_smd_rpm_ops, \ .name = #_active, \ - .parent_names = (const char *[]){ "xo_board" }, \ + .parent_data = &(const struct clk_parent_data){ \ + .fw_name = "xo", \ + .name = "xo_board", \ + }, \ .num_parents = 1, \ }, \ } @@ -73,7 +79,10 @@ .hw.init = &(struct clk_init_data){ \ .ops = &clk_smd_rpm_branch_ops, \ .name = #_name, \ - .parent_names = (const char *[]){ "xo_board" }, \ + .parent_data = &(const struct clk_parent_data){ \ + .fw_name = "xo", \ + .name = "xo_board", \ + }, \ .num_parents = 1, \ }, \ }; \ @@ -89,7 +98,10 @@ .hw.init = &(struct clk_init_data){ \ .ops = &clk_smd_rpm_branch_ops, \ .name = #_active, \ - .parent_names = (const char *[]){ "xo_board" }, \ + .parent_data = &(const struct clk_parent_data){ \ + .fw_name = "xo", \ + .name = "xo_board", \ + }, \ .num_parents = 1, \ }, \ } @@ -406,7 +418,6 @@ static const struct clk_ops clk_smd_rpm_branch_ops = { .unprepare = clk_smd_rpm_unprepare, }; -/* msm8916 */ DEFINE_CLK_SMD_RPM(msm8916, pcnoc_clk, pcnoc_a_clk, QCOM_SMD_RPM_BUS_CLK, 0); DEFINE_CLK_SMD_RPM(msm8916, snoc_clk, snoc_a_clk, QCOM_SMD_RPM_BUS_CLK, 1); DEFINE_CLK_SMD_RPM(msm8916, bimc_clk, bimc_a_clk, QCOM_SMD_RPM_MEM_CLK, 0); @@ -452,48 +463,35 @@ static const struct rpm_smd_clk_desc rpm_clk_msm8916 = { .num_clks = ARRAY_SIZE(msm8916_clks), }; -/* msm8936 */ -DEFINE_CLK_SMD_RPM(msm8936, pcnoc_clk, pcnoc_a_clk, QCOM_SMD_RPM_BUS_CLK, 0); -DEFINE_CLK_SMD_RPM(msm8936, snoc_clk, snoc_a_clk, QCOM_SMD_RPM_BUS_CLK, 1); -DEFINE_CLK_SMD_RPM(msm8936, bimc_clk, bimc_a_clk, QCOM_SMD_RPM_MEM_CLK, 0); DEFINE_CLK_SMD_RPM(msm8936, sysmmnoc_clk, sysmmnoc_a_clk, QCOM_SMD_RPM_BUS_CLK, 2); -DEFINE_CLK_SMD_RPM_QDSS(msm8936, qdss_clk, qdss_a_clk, QCOM_SMD_RPM_MISC_CLK, 1); -DEFINE_CLK_SMD_RPM_XO_BUFFER(msm8936, bb_clk1, bb_clk1_a, 1); -DEFINE_CLK_SMD_RPM_XO_BUFFER(msm8936, bb_clk2, bb_clk2_a, 2); -DEFINE_CLK_SMD_RPM_XO_BUFFER(msm8936, rf_clk1, rf_clk1_a, 4); -DEFINE_CLK_SMD_RPM_XO_BUFFER(msm8936, rf_clk2, rf_clk2_a, 5); -DEFINE_CLK_SMD_RPM_XO_BUFFER_PINCTRL(msm8936, bb_clk1_pin, bb_clk1_a_pin, 1); -DEFINE_CLK_SMD_RPM_XO_BUFFER_PINCTRL(msm8936, bb_clk2_pin, bb_clk2_a_pin, 2); -DEFINE_CLK_SMD_RPM_XO_BUFFER_PINCTRL(msm8936, rf_clk1_pin, rf_clk1_a_pin, 4); -DEFINE_CLK_SMD_RPM_XO_BUFFER_PINCTRL(msm8936, rf_clk2_pin, rf_clk2_a_pin, 5); static struct clk_smd_rpm *msm8936_clks[] = { - [RPM_SMD_PCNOC_CLK] = &msm8936_pcnoc_clk, - [RPM_SMD_PCNOC_A_CLK] = &msm8936_pcnoc_a_clk, - [RPM_SMD_SNOC_CLK] = &msm8936_snoc_clk, - [RPM_SMD_SNOC_A_CLK] = &msm8936_snoc_a_clk, - [RPM_SMD_BIMC_CLK] = &msm8936_bimc_clk, - [RPM_SMD_BIMC_A_CLK] = &msm8936_bimc_a_clk, + [RPM_SMD_PCNOC_CLK] = &msm8916_pcnoc_clk, + [RPM_SMD_PCNOC_A_CLK] = &msm8916_pcnoc_clk, + [RPM_SMD_SNOC_CLK] = &msm8916_snoc_clk, + [RPM_SMD_SNOC_A_CLK] = &msm8916_snoc_a_clk, + [RPM_SMD_BIMC_CLK] = &msm8916_bimc_clk, + [RPM_SMD_BIMC_A_CLK] = &msm8916_bimc_a_clk, [RPM_SMD_SYSMMNOC_CLK] = &msm8936_sysmmnoc_clk, [RPM_SMD_SYSMMNOC_A_CLK] = &msm8936_sysmmnoc_a_clk, - [RPM_SMD_QDSS_CLK] = &msm8936_qdss_clk, - [RPM_SMD_QDSS_A_CLK] = &msm8936_qdss_a_clk, - [RPM_SMD_BB_CLK1] = &msm8936_bb_clk1, - [RPM_SMD_BB_CLK1_A] = &msm8936_bb_clk1_a, - [RPM_SMD_BB_CLK2] = &msm8936_bb_clk2, - [RPM_SMD_BB_CLK2_A] = &msm8936_bb_clk2_a, - [RPM_SMD_RF_CLK1] = &msm8936_rf_clk1, - [RPM_SMD_RF_CLK1_A] = &msm8936_rf_clk1_a, - [RPM_SMD_RF_CLK2] = &msm8936_rf_clk2, - [RPM_SMD_RF_CLK2_A] = &msm8936_rf_clk2_a, - [RPM_SMD_BB_CLK1_PIN] = &msm8936_bb_clk1_pin, - [RPM_SMD_BB_CLK1_A_PIN] = &msm8936_bb_clk1_a_pin, - [RPM_SMD_BB_CLK2_PIN] = &msm8936_bb_clk2_pin, - [RPM_SMD_BB_CLK2_A_PIN] = &msm8936_bb_clk2_a_pin, - [RPM_SMD_RF_CLK1_PIN] = &msm8936_rf_clk1_pin, - [RPM_SMD_RF_CLK1_A_PIN] = &msm8936_rf_clk1_a_pin, - [RPM_SMD_RF_CLK2_PIN] = &msm8936_rf_clk2_pin, - [RPM_SMD_RF_CLK2_A_PIN] = &msm8936_rf_clk2_a_pin, + [RPM_SMD_QDSS_CLK] = &msm8916_qdss_clk, + [RPM_SMD_QDSS_A_CLK] = &msm8916_qdss_a_clk, + [RPM_SMD_BB_CLK1] = &msm8916_bb_clk1, + [RPM_SMD_BB_CLK1_A] = &msm8916_bb_clk1_a, + [RPM_SMD_BB_CLK2] = &msm8916_bb_clk2, + [RPM_SMD_BB_CLK2_A] = &msm8916_bb_clk2_a, + [RPM_SMD_RF_CLK1] = &msm8916_rf_clk1, + [RPM_SMD_RF_CLK1_A] = &msm8916_rf_clk1_a, + [RPM_SMD_RF_CLK2] = &msm8916_rf_clk2, + [RPM_SMD_RF_CLK2_A] = &msm8916_rf_clk2_a, + [RPM_SMD_BB_CLK1_PIN] = &msm8916_bb_clk1_pin, + [RPM_SMD_BB_CLK1_A_PIN] = &msm8916_bb_clk1_a_pin, + [RPM_SMD_BB_CLK2_PIN] = &msm8916_bb_clk2_pin, + [RPM_SMD_BB_CLK2_A_PIN] = &msm8916_bb_clk2_a_pin, + [RPM_SMD_RF_CLK1_PIN] = &msm8916_rf_clk1_pin, + [RPM_SMD_RF_CLK1_A_PIN] = &msm8916_rf_clk1_a_pin, + [RPM_SMD_RF_CLK2_PIN] = &msm8916_rf_clk2_pin, + [RPM_SMD_RF_CLK2_A_PIN] = &msm8916_rf_clk2_a_pin, }; static const struct rpm_smd_clk_desc rpm_clk_msm8936 = { @@ -501,15 +499,10 @@ static const struct rpm_smd_clk_desc rpm_clk_msm8936 = { .num_clks = ARRAY_SIZE(msm8936_clks), }; -/* msm8974 */ -DEFINE_CLK_SMD_RPM(msm8974, pnoc_clk, pnoc_a_clk, QCOM_SMD_RPM_BUS_CLK, 0); -DEFINE_CLK_SMD_RPM(msm8974, snoc_clk, snoc_a_clk, QCOM_SMD_RPM_BUS_CLK, 1); DEFINE_CLK_SMD_RPM(msm8974, cnoc_clk, cnoc_a_clk, QCOM_SMD_RPM_BUS_CLK, 2); DEFINE_CLK_SMD_RPM(msm8974, mmssnoc_ahb_clk, mmssnoc_ahb_a_clk, QCOM_SMD_RPM_BUS_CLK, 3); -DEFINE_CLK_SMD_RPM(msm8974, bimc_clk, bimc_a_clk, QCOM_SMD_RPM_MEM_CLK, 0); DEFINE_CLK_SMD_RPM(msm8974, gfx3d_clk_src, gfx3d_a_clk_src, QCOM_SMD_RPM_MEM_CLK, 1); DEFINE_CLK_SMD_RPM(msm8974, ocmemgx_clk, ocmemgx_a_clk, QCOM_SMD_RPM_MEM_CLK, 2); -DEFINE_CLK_SMD_RPM_QDSS(msm8974, qdss_clk, qdss_a_clk, QCOM_SMD_RPM_MISC_CLK, 1); DEFINE_CLK_SMD_RPM_XO_BUFFER(msm8974, cxo_d0, cxo_d0_a, 1); DEFINE_CLK_SMD_RPM_XO_BUFFER(msm8974, cxo_d1, cxo_d1_a, 2); DEFINE_CLK_SMD_RPM_XO_BUFFER(msm8974, cxo_a0, cxo_a0_a, 4); @@ -525,22 +518,22 @@ DEFINE_CLK_SMD_RPM_XO_BUFFER_PINCTRL(msm8974, cxo_a1_pin, cxo_a1_a_pin, 5); DEFINE_CLK_SMD_RPM_XO_BUFFER_PINCTRL(msm8974, cxo_a2_pin, cxo_a2_a_pin, 6); static struct clk_smd_rpm *msm8974_clks[] = { - [RPM_SMD_PNOC_CLK] = &msm8974_pnoc_clk, - [RPM_SMD_PNOC_A_CLK] = &msm8974_pnoc_a_clk, - [RPM_SMD_SNOC_CLK] = &msm8974_snoc_clk, - [RPM_SMD_SNOC_A_CLK] = &msm8974_snoc_a_clk, + [RPM_SMD_PNOC_CLK] = &msm8916_pcnoc_clk, + [RPM_SMD_PNOC_A_CLK] = &msm8916_pcnoc_a_clk, + [RPM_SMD_SNOC_CLK] = &msm8916_snoc_clk, + [RPM_SMD_SNOC_A_CLK] = &msm8916_snoc_a_clk, [RPM_SMD_CNOC_CLK] = &msm8974_cnoc_clk, [RPM_SMD_CNOC_A_CLK] = &msm8974_cnoc_a_clk, [RPM_SMD_MMSSNOC_AHB_CLK] = &msm8974_mmssnoc_ahb_clk, [RPM_SMD_MMSSNOC_AHB_A_CLK] = &msm8974_mmssnoc_ahb_a_clk, - [RPM_SMD_BIMC_CLK] = &msm8974_bimc_clk, + [RPM_SMD_BIMC_CLK] = &msm8916_bimc_clk, [RPM_SMD_GFX3D_CLK_SRC] = &msm8974_gfx3d_clk_src, [RPM_SMD_GFX3D_A_CLK_SRC] = &msm8974_gfx3d_a_clk_src, - [RPM_SMD_BIMC_A_CLK] = &msm8974_bimc_a_clk, + [RPM_SMD_BIMC_A_CLK] = &msm8916_bimc_a_clk, [RPM_SMD_OCMEMGX_CLK] = &msm8974_ocmemgx_clk, [RPM_SMD_OCMEMGX_A_CLK] = &msm8974_ocmemgx_a_clk, - [RPM_SMD_QDSS_CLK] = &msm8974_qdss_clk, - [RPM_SMD_QDSS_A_CLK] = &msm8974_qdss_a_clk, + [RPM_SMD_QDSS_CLK] = &msm8916_qdss_clk, + [RPM_SMD_QDSS_A_CLK] = &msm8916_qdss_a_clk, [RPM_SMD_CXO_D0] = &msm8974_cxo_d0, [RPM_SMD_CXO_D0_A] = &msm8974_cxo_d0_a, [RPM_SMD_CXO_D1] = &msm8974_cxo_d1, @@ -574,46 +567,33 @@ static const struct rpm_smd_clk_desc rpm_clk_msm8974 = { .num_clks = ARRAY_SIZE(msm8974_clks), }; - -/* msm8976 */ -DEFINE_CLK_SMD_RPM(msm8976, pcnoc_clk, pcnoc_a_clk, QCOM_SMD_RPM_BUS_CLK, 0); -DEFINE_CLK_SMD_RPM(msm8976, snoc_clk, snoc_a_clk, QCOM_SMD_RPM_BUS_CLK, 1); DEFINE_CLK_SMD_RPM(msm8976, mmssnoc_ahb_clk, mmssnoc_ahb_a_clk, QCOM_SMD_RPM_BUS_CLK, 2); -DEFINE_CLK_SMD_RPM(msm8976, bimc_clk, bimc_a_clk, QCOM_SMD_RPM_MEM_CLK, 0); DEFINE_CLK_SMD_RPM(msm8976, ipa_clk, ipa_a_clk, QCOM_SMD_RPM_IPA_CLK, 0); -DEFINE_CLK_SMD_RPM_QDSS(msm8976, qdss_clk, qdss_a_clk, - QCOM_SMD_RPM_MISC_CLK, 1); -DEFINE_CLK_SMD_RPM_XO_BUFFER(msm8976, bb_clk1, bb_clk1_a, 1); -DEFINE_CLK_SMD_RPM_XO_BUFFER(msm8976, bb_clk2, bb_clk2_a, 2); -DEFINE_CLK_SMD_RPM_XO_BUFFER(msm8976, rf_clk2, rf_clk2_a, 5); -DEFINE_CLK_SMD_RPM_XO_BUFFER(msm8976, div_clk2, div_clk2_a, 12); -DEFINE_CLK_SMD_RPM_XO_BUFFER_PINCTRL(msm8976, bb_clk1_pin, bb_clk1_a_pin, 1); -DEFINE_CLK_SMD_RPM_XO_BUFFER_PINCTRL(msm8976, bb_clk2_pin, bb_clk2_a_pin, 2); static struct clk_smd_rpm *msm8976_clks[] = { - [RPM_SMD_PCNOC_CLK] = &msm8976_pcnoc_clk, - [RPM_SMD_PCNOC_A_CLK] = &msm8976_pcnoc_a_clk, - [RPM_SMD_SNOC_CLK] = &msm8976_snoc_clk, - [RPM_SMD_SNOC_A_CLK] = &msm8976_snoc_a_clk, - [RPM_SMD_BIMC_CLK] = &msm8976_bimc_clk, - [RPM_SMD_BIMC_A_CLK] = &msm8976_bimc_a_clk, - [RPM_SMD_QDSS_CLK] = &msm8976_qdss_clk, - [RPM_SMD_QDSS_A_CLK] = &msm8976_qdss_a_clk, - [RPM_SMD_BB_CLK1] = &msm8976_bb_clk1, - [RPM_SMD_BB_CLK1_A] = &msm8976_bb_clk1_a, - [RPM_SMD_BB_CLK2] = &msm8976_bb_clk2, - [RPM_SMD_BB_CLK2_A] = &msm8976_bb_clk2_a, - [RPM_SMD_RF_CLK2] = &msm8976_rf_clk2, - [RPM_SMD_RF_CLK2_A] = &msm8976_rf_clk2_a, - [RPM_SMD_BB_CLK1_PIN] = &msm8976_bb_clk1_pin, - [RPM_SMD_BB_CLK1_A_PIN] = &msm8976_bb_clk1_a_pin, - [RPM_SMD_BB_CLK2_PIN] = &msm8976_bb_clk2_pin, - [RPM_SMD_BB_CLK2_A_PIN] = &msm8976_bb_clk2_a_pin, + [RPM_SMD_PCNOC_CLK] = &msm8916_pcnoc_clk, + [RPM_SMD_PCNOC_A_CLK] = &msm8916_pcnoc_a_clk, + [RPM_SMD_SNOC_CLK] = &msm8916_snoc_clk, + [RPM_SMD_SNOC_A_CLK] = &msm8916_snoc_a_clk, + [RPM_SMD_BIMC_CLK] = &msm8916_bimc_clk, + [RPM_SMD_BIMC_A_CLK] = &msm8916_bimc_a_clk, + [RPM_SMD_QDSS_CLK] = &msm8916_qdss_clk, + [RPM_SMD_QDSS_A_CLK] = &msm8916_qdss_a_clk, + [RPM_SMD_BB_CLK1] = &msm8916_bb_clk1, + [RPM_SMD_BB_CLK1_A] = &msm8916_bb_clk1_a, + [RPM_SMD_BB_CLK2] = &msm8916_bb_clk2, + [RPM_SMD_BB_CLK2_A] = &msm8916_bb_clk2_a, + [RPM_SMD_RF_CLK2] = &msm8916_rf_clk2, + [RPM_SMD_RF_CLK2_A] = &msm8916_rf_clk2_a, + [RPM_SMD_BB_CLK1_PIN] = &msm8916_bb_clk1_pin, + [RPM_SMD_BB_CLK1_A_PIN] = &msm8916_bb_clk1_a_pin, + [RPM_SMD_BB_CLK2_PIN] = &msm8916_bb_clk2_pin, + [RPM_SMD_BB_CLK2_A_PIN] = &msm8916_bb_clk2_a_pin, [RPM_SMD_MMSSNOC_AHB_CLK] = &msm8976_mmssnoc_ahb_clk, [RPM_SMD_MMSSNOC_AHB_A_CLK] = &msm8976_mmssnoc_ahb_a_clk, - [RPM_SMD_DIV_CLK2] = &msm8976_div_clk2, - [RPM_SMD_DIV_A_CLK2] = &msm8976_div_clk2_a, + [RPM_SMD_DIV_CLK2] = &msm8974_div_clk2, + [RPM_SMD_DIV_A_CLK2] = &msm8974_div_a_clk2, [RPM_SMD_IPA_CLK] = &msm8976_ipa_clk, [RPM_SMD_IPA_A_CLK] = &msm8976_ipa_a_clk, }; @@ -623,78 +603,55 @@ static const struct rpm_smd_clk_desc rpm_clk_msm8976 = { .num_clks = ARRAY_SIZE(msm8976_clks), }; -/* msm8992 */ -DEFINE_CLK_SMD_RPM(msm8992, pnoc_clk, pnoc_a_clk, QCOM_SMD_RPM_BUS_CLK, 0); -DEFINE_CLK_SMD_RPM(msm8992, ocmemgx_clk, ocmemgx_a_clk, QCOM_SMD_RPM_MEM_CLK, 2); -DEFINE_CLK_SMD_RPM(msm8992, bimc_clk, bimc_a_clk, QCOM_SMD_RPM_MEM_CLK, 0); -DEFINE_CLK_SMD_RPM(msm8992, cnoc_clk, cnoc_a_clk, QCOM_SMD_RPM_BUS_CLK, 2); -DEFINE_CLK_SMD_RPM(msm8992, gfx3d_clk_src, gfx3d_a_clk_src, QCOM_SMD_RPM_MEM_CLK, 1); -DEFINE_CLK_SMD_RPM(msm8992, snoc_clk, snoc_a_clk, QCOM_SMD_RPM_BUS_CLK, 1); -DEFINE_CLK_SMD_RPM_XO_BUFFER(msm8992, bb_clk1, bb_clk1_a, 1); -DEFINE_CLK_SMD_RPM_XO_BUFFER_PINCTRL(msm8992, bb_clk1_pin, bb_clk1_a_pin, 1); -DEFINE_CLK_SMD_RPM_XO_BUFFER(msm8992, bb_clk2, bb_clk2_a, 2); -DEFINE_CLK_SMD_RPM_XO_BUFFER_PINCTRL(msm8992, bb_clk2_pin, bb_clk2_a_pin, 2); - -DEFINE_CLK_SMD_RPM_XO_BUFFER(msm8992, div_clk1, div_clk1_a, 11); -DEFINE_CLK_SMD_RPM_XO_BUFFER(msm8992, div_clk2, div_clk2_a, 12); DEFINE_CLK_SMD_RPM_XO_BUFFER(msm8992, div_clk3, div_clk3_a, 13); -DEFINE_CLK_SMD_RPM(msm8992, ipa_clk, ipa_a_clk, QCOM_SMD_RPM_IPA_CLK, 0); DEFINE_CLK_SMD_RPM_XO_BUFFER(msm8992, ln_bb_clk, ln_bb_a_clk, 8); -DEFINE_CLK_SMD_RPM(msm8992, mmssnoc_ahb_clk, mmssnoc_ahb_a_clk, - QCOM_SMD_RPM_BUS_CLK, 3); -DEFINE_CLK_SMD_RPM_QDSS(msm8992, qdss_clk, qdss_a_clk, - QCOM_SMD_RPM_MISC_CLK, 1); -DEFINE_CLK_SMD_RPM_XO_BUFFER(msm8992, rf_clk1, rf_clk1_a, 4); -DEFINE_CLK_SMD_RPM_XO_BUFFER(msm8992, rf_clk2, rf_clk2_a, 5); -DEFINE_CLK_SMD_RPM_XO_BUFFER_PINCTRL(msm8992, rf_clk1_pin, rf_clk1_a_pin, 4); -DEFINE_CLK_SMD_RPM_XO_BUFFER_PINCTRL(msm8992, rf_clk2_pin, rf_clk2_a_pin, 5); DEFINE_CLK_SMD_RPM(msm8992, ce1_clk, ce1_a_clk, QCOM_SMD_RPM_CE_CLK, 0); DEFINE_CLK_SMD_RPM(msm8992, ce2_clk, ce2_a_clk, QCOM_SMD_RPM_CE_CLK, 1); static struct clk_smd_rpm *msm8992_clks[] = { - [RPM_SMD_PNOC_CLK] = &msm8992_pnoc_clk, - [RPM_SMD_PNOC_A_CLK] = &msm8992_pnoc_a_clk, - [RPM_SMD_OCMEMGX_CLK] = &msm8992_ocmemgx_clk, - [RPM_SMD_OCMEMGX_A_CLK] = &msm8992_ocmemgx_a_clk, - [RPM_SMD_BIMC_CLK] = &msm8992_bimc_clk, - [RPM_SMD_BIMC_A_CLK] = &msm8992_bimc_a_clk, - [RPM_SMD_CNOC_CLK] = &msm8992_cnoc_clk, - [RPM_SMD_CNOC_A_CLK] = &msm8992_cnoc_a_clk, - [RPM_SMD_GFX3D_CLK_SRC] = &msm8992_gfx3d_clk_src, - [RPM_SMD_GFX3D_A_CLK_SRC] = &msm8992_gfx3d_a_clk_src, - [RPM_SMD_SNOC_CLK] = &msm8992_snoc_clk, - [RPM_SMD_SNOC_A_CLK] = &msm8992_snoc_a_clk, - [RPM_SMD_BB_CLK1] = &msm8992_bb_clk1, - [RPM_SMD_BB_CLK1_A] = &msm8992_bb_clk1_a, - [RPM_SMD_BB_CLK1_PIN] = &msm8992_bb_clk1_pin, - [RPM_SMD_BB_CLK1_A_PIN] = &msm8992_bb_clk1_a_pin, - [RPM_SMD_BB_CLK2] = &msm8992_bb_clk2, - [RPM_SMD_BB_CLK2_A] = &msm8992_bb_clk2_a, - [RPM_SMD_BB_CLK2_PIN] = &msm8992_bb_clk2_pin, - [RPM_SMD_BB_CLK2_A_PIN] = &msm8992_bb_clk2_a_pin, - [RPM_SMD_DIV_CLK1] = &msm8992_div_clk1, - [RPM_SMD_DIV_A_CLK1] = &msm8992_div_clk1_a, - [RPM_SMD_DIV_CLK2] = &msm8992_div_clk2, - [RPM_SMD_DIV_A_CLK2] = &msm8992_div_clk2_a, + [RPM_SMD_PNOC_CLK] = &msm8916_pcnoc_clk, + [RPM_SMD_PNOC_A_CLK] = &msm8916_pcnoc_a_clk, + [RPM_SMD_OCMEMGX_CLK] = &msm8974_ocmemgx_clk, + [RPM_SMD_OCMEMGX_A_CLK] = &msm8974_ocmemgx_a_clk, + [RPM_SMD_BIMC_CLK] = &msm8916_bimc_clk, + [RPM_SMD_BIMC_A_CLK] = &msm8916_bimc_a_clk, + [RPM_SMD_CNOC_CLK] = &msm8974_cnoc_clk, + [RPM_SMD_CNOC_A_CLK] = &msm8974_cnoc_a_clk, + [RPM_SMD_GFX3D_CLK_SRC] = &msm8974_gfx3d_clk_src, + [RPM_SMD_GFX3D_A_CLK_SRC] = &msm8974_gfx3d_a_clk_src, + [RPM_SMD_SNOC_CLK] = &msm8916_snoc_clk, + [RPM_SMD_SNOC_A_CLK] = &msm8916_snoc_a_clk, + [RPM_SMD_BB_CLK1] = &msm8916_bb_clk1, + [RPM_SMD_BB_CLK1_A] = &msm8916_bb_clk1_a, + [RPM_SMD_BB_CLK1_PIN] = &msm8916_bb_clk1_pin, + [RPM_SMD_BB_CLK1_A_PIN] = &msm8916_bb_clk1_a_pin, + [RPM_SMD_BB_CLK2] = &msm8916_bb_clk2, + [RPM_SMD_BB_CLK2_A] = &msm8916_bb_clk2_a, + [RPM_SMD_BB_CLK2_PIN] = &msm8916_bb_clk2_pin, + [RPM_SMD_BB_CLK2_A_PIN] = &msm8916_bb_clk2_a_pin, + [RPM_SMD_DIV_CLK1] = &msm8974_div_clk1, + [RPM_SMD_DIV_A_CLK1] = &msm8974_div_a_clk1, + [RPM_SMD_DIV_CLK2] = &msm8974_div_clk2, + [RPM_SMD_DIV_A_CLK2] = &msm8974_div_a_clk2, [RPM_SMD_DIV_CLK3] = &msm8992_div_clk3, [RPM_SMD_DIV_A_CLK3] = &msm8992_div_clk3_a, - [RPM_SMD_IPA_CLK] = &msm8992_ipa_clk, - [RPM_SMD_IPA_A_CLK] = &msm8992_ipa_a_clk, + [RPM_SMD_IPA_CLK] = &msm8976_ipa_clk, + [RPM_SMD_IPA_A_CLK] = &msm8976_ipa_a_clk, [RPM_SMD_LN_BB_CLK] = &msm8992_ln_bb_clk, [RPM_SMD_LN_BB_A_CLK] = &msm8992_ln_bb_a_clk, - [RPM_SMD_MMSSNOC_AHB_CLK] = &msm8992_mmssnoc_ahb_clk, - [RPM_SMD_MMSSNOC_AHB_A_CLK] = &msm8992_mmssnoc_ahb_a_clk, - [RPM_SMD_QDSS_CLK] = &msm8992_qdss_clk, - [RPM_SMD_QDSS_A_CLK] = &msm8992_qdss_a_clk, - [RPM_SMD_RF_CLK1] = &msm8992_rf_clk1, - [RPM_SMD_RF_CLK1_A] = &msm8992_rf_clk1_a, - [RPM_SMD_RF_CLK2] = &msm8992_rf_clk2, - [RPM_SMD_RF_CLK2_A] = &msm8992_rf_clk2_a, - [RPM_SMD_RF_CLK1_PIN] = &msm8992_rf_clk1_pin, - [RPM_SMD_RF_CLK1_A_PIN] = &msm8992_rf_clk1_a_pin, - [RPM_SMD_RF_CLK2_PIN] = &msm8992_rf_clk2_pin, - [RPM_SMD_RF_CLK2_A_PIN] = &msm8992_rf_clk2_a_pin, + [RPM_SMD_MMSSNOC_AHB_CLK] = &msm8974_mmssnoc_ahb_clk, + [RPM_SMD_MMSSNOC_AHB_A_CLK] = &msm8974_mmssnoc_ahb_a_clk, + [RPM_SMD_QDSS_CLK] = &msm8916_qdss_clk, + [RPM_SMD_QDSS_A_CLK] = &msm8916_qdss_a_clk, + [RPM_SMD_RF_CLK1] = &msm8916_rf_clk1, + [RPM_SMD_RF_CLK1_A] = &msm8916_rf_clk1_a, + [RPM_SMD_RF_CLK2] = &msm8916_rf_clk2, + [RPM_SMD_RF_CLK2_A] = &msm8916_rf_clk2_a, + [RPM_SMD_RF_CLK1_PIN] = &msm8916_rf_clk1_pin, + [RPM_SMD_RF_CLK1_A_PIN] = &msm8916_rf_clk1_a_pin, + [RPM_SMD_RF_CLK2_PIN] = &msm8916_rf_clk2_pin, + [RPM_SMD_RF_CLK2_A_PIN] = &msm8916_rf_clk2_a_pin, [RPM_SMD_CE1_CLK] = &msm8992_ce1_clk, [RPM_SMD_CE1_A_CLK] = &msm8992_ce1_a_clk, [RPM_SMD_CE2_CLK] = &msm8992_ce2_clk, @@ -706,83 +663,55 @@ static const struct rpm_smd_clk_desc rpm_clk_msm8992 = { .num_clks = ARRAY_SIZE(msm8992_clks), }; -/* msm8994 */ -DEFINE_CLK_SMD_RPM(msm8994, pnoc_clk, pnoc_a_clk, QCOM_SMD_RPM_BUS_CLK, 0); -DEFINE_CLK_SMD_RPM(msm8994, ocmemgx_clk, ocmemgx_a_clk, QCOM_SMD_RPM_MEM_CLK, 2); -DEFINE_CLK_SMD_RPM(msm8994, bimc_clk, bimc_a_clk, QCOM_SMD_RPM_MEM_CLK, 0); -DEFINE_CLK_SMD_RPM(msm8994, cnoc_clk, cnoc_a_clk, QCOM_SMD_RPM_BUS_CLK, 2); -DEFINE_CLK_SMD_RPM(msm8994, gfx3d_clk_src, gfx3d_a_clk_src, QCOM_SMD_RPM_MEM_CLK, 1); -DEFINE_CLK_SMD_RPM(msm8994, snoc_clk, snoc_a_clk, QCOM_SMD_RPM_BUS_CLK, 1); -DEFINE_CLK_SMD_RPM_XO_BUFFER(msm8994, bb_clk1, bb_clk1_a, 1); -DEFINE_CLK_SMD_RPM_XO_BUFFER_PINCTRL(msm8994, bb_clk1_pin, bb_clk1_a_pin, 1); -DEFINE_CLK_SMD_RPM_XO_BUFFER(msm8994, bb_clk2, bb_clk2_a, 2); -DEFINE_CLK_SMD_RPM_XO_BUFFER_PINCTRL(msm8994, bb_clk2_pin, bb_clk2_a_pin, 2); - -DEFINE_CLK_SMD_RPM_XO_BUFFER(msm8994, div_clk1, div_clk1_a, 11); -DEFINE_CLK_SMD_RPM_XO_BUFFER(msm8994, div_clk2, div_clk2_a, 12); -DEFINE_CLK_SMD_RPM_XO_BUFFER(msm8994, div_clk3, div_clk3_a, 13); -DEFINE_CLK_SMD_RPM(msm8994, ipa_clk, ipa_a_clk, QCOM_SMD_RPM_IPA_CLK, 0); -DEFINE_CLK_SMD_RPM_XO_BUFFER(msm8994, ln_bb_clk, ln_bb_a_clk, 8); -DEFINE_CLK_SMD_RPM(msm8994, mmssnoc_ahb_clk, mmssnoc_ahb_a_clk, - QCOM_SMD_RPM_BUS_CLK, 3); -DEFINE_CLK_SMD_RPM_QDSS(msm8994, qdss_clk, qdss_a_clk, - QCOM_SMD_RPM_MISC_CLK, 1); -DEFINE_CLK_SMD_RPM_XO_BUFFER(msm8994, rf_clk1, rf_clk1_a, 4); -DEFINE_CLK_SMD_RPM_XO_BUFFER(msm8994, rf_clk2, rf_clk2_a, 5); -DEFINE_CLK_SMD_RPM_XO_BUFFER_PINCTRL(msm8994, rf_clk1_pin, rf_clk1_a_pin, 4); -DEFINE_CLK_SMD_RPM_XO_BUFFER_PINCTRL(msm8994, rf_clk2_pin, rf_clk2_a_pin, 5); - -DEFINE_CLK_SMD_RPM(msm8994, ce1_clk, ce1_a_clk, QCOM_SMD_RPM_CE_CLK, 0); -DEFINE_CLK_SMD_RPM(msm8994, ce2_clk, ce2_a_clk, QCOM_SMD_RPM_CE_CLK, 1); DEFINE_CLK_SMD_RPM(msm8994, ce3_clk, ce3_a_clk, QCOM_SMD_RPM_CE_CLK, 2); static struct clk_smd_rpm *msm8994_clks[] = { - [RPM_SMD_PNOC_CLK] = &msm8994_pnoc_clk, - [RPM_SMD_PNOC_A_CLK] = &msm8994_pnoc_a_clk, - [RPM_SMD_OCMEMGX_CLK] = &msm8994_ocmemgx_clk, - [RPM_SMD_OCMEMGX_A_CLK] = &msm8994_ocmemgx_a_clk, - [RPM_SMD_BIMC_CLK] = &msm8994_bimc_clk, - [RPM_SMD_BIMC_A_CLK] = &msm8994_bimc_a_clk, - [RPM_SMD_CNOC_CLK] = &msm8994_cnoc_clk, - [RPM_SMD_CNOC_A_CLK] = &msm8994_cnoc_a_clk, - [RPM_SMD_GFX3D_CLK_SRC] = &msm8994_gfx3d_clk_src, - [RPM_SMD_GFX3D_A_CLK_SRC] = &msm8994_gfx3d_a_clk_src, - [RPM_SMD_SNOC_CLK] = &msm8994_snoc_clk, - [RPM_SMD_SNOC_A_CLK] = &msm8994_snoc_a_clk, - [RPM_SMD_BB_CLK1] = &msm8994_bb_clk1, - [RPM_SMD_BB_CLK1_A] = &msm8994_bb_clk1_a, - [RPM_SMD_BB_CLK1_PIN] = &msm8994_bb_clk1_pin, - [RPM_SMD_BB_CLK1_A_PIN] = &msm8994_bb_clk1_a_pin, - [RPM_SMD_BB_CLK2] = &msm8994_bb_clk2, - [RPM_SMD_BB_CLK2_A] = &msm8994_bb_clk2_a, - [RPM_SMD_BB_CLK2_PIN] = &msm8994_bb_clk2_pin, - [RPM_SMD_BB_CLK2_A_PIN] = &msm8994_bb_clk2_a_pin, - [RPM_SMD_DIV_CLK1] = &msm8994_div_clk1, - [RPM_SMD_DIV_A_CLK1] = &msm8994_div_clk1_a, - [RPM_SMD_DIV_CLK2] = &msm8994_div_clk2, - [RPM_SMD_DIV_A_CLK2] = &msm8994_div_clk2_a, - [RPM_SMD_DIV_CLK3] = &msm8994_div_clk3, - [RPM_SMD_DIV_A_CLK3] = &msm8994_div_clk3_a, - [RPM_SMD_IPA_CLK] = &msm8994_ipa_clk, - [RPM_SMD_IPA_A_CLK] = &msm8994_ipa_a_clk, - [RPM_SMD_LN_BB_CLK] = &msm8994_ln_bb_clk, - [RPM_SMD_LN_BB_A_CLK] = &msm8994_ln_bb_a_clk, - [RPM_SMD_MMSSNOC_AHB_CLK] = &msm8994_mmssnoc_ahb_clk, - [RPM_SMD_MMSSNOC_AHB_A_CLK] = &msm8994_mmssnoc_ahb_a_clk, - [RPM_SMD_QDSS_CLK] = &msm8994_qdss_clk, - [RPM_SMD_QDSS_A_CLK] = &msm8994_qdss_a_clk, - [RPM_SMD_RF_CLK1] = &msm8994_rf_clk1, - [RPM_SMD_RF_CLK1_A] = &msm8994_rf_clk1_a, - [RPM_SMD_RF_CLK2] = &msm8994_rf_clk2, - [RPM_SMD_RF_CLK2_A] = &msm8994_rf_clk2_a, - [RPM_SMD_RF_CLK1_PIN] = &msm8994_rf_clk1_pin, - [RPM_SMD_RF_CLK1_A_PIN] = &msm8994_rf_clk1_a_pin, - [RPM_SMD_RF_CLK2_PIN] = &msm8994_rf_clk2_pin, - [RPM_SMD_RF_CLK2_A_PIN] = &msm8994_rf_clk2_a_pin, - [RPM_SMD_CE1_CLK] = &msm8994_ce1_clk, - [RPM_SMD_CE1_A_CLK] = &msm8994_ce1_a_clk, - [RPM_SMD_CE2_CLK] = &msm8994_ce2_clk, - [RPM_SMD_CE2_A_CLK] = &msm8994_ce2_a_clk, + [RPM_SMD_PNOC_CLK] = &msm8916_pcnoc_clk, + [RPM_SMD_PNOC_A_CLK] = &msm8916_pcnoc_a_clk, + [RPM_SMD_OCMEMGX_CLK] = &msm8974_ocmemgx_clk, + [RPM_SMD_OCMEMGX_A_CLK] = &msm8974_ocmemgx_a_clk, + [RPM_SMD_BIMC_CLK] = &msm8916_bimc_clk, + [RPM_SMD_BIMC_A_CLK] = &msm8916_bimc_a_clk, + [RPM_SMD_CNOC_CLK] = &msm8974_cnoc_clk, + [RPM_SMD_CNOC_A_CLK] = &msm8974_cnoc_a_clk, + [RPM_SMD_GFX3D_CLK_SRC] = &msm8974_gfx3d_clk_src, + [RPM_SMD_GFX3D_A_CLK_SRC] = &msm8974_gfx3d_a_clk_src, + [RPM_SMD_SNOC_CLK] = &msm8916_snoc_clk, + [RPM_SMD_SNOC_A_CLK] = &msm8916_snoc_a_clk, + [RPM_SMD_BB_CLK1] = &msm8916_bb_clk1, + [RPM_SMD_BB_CLK1_A] = &msm8916_bb_clk1_a, + [RPM_SMD_BB_CLK1_PIN] = &msm8916_bb_clk1_pin, + [RPM_SMD_BB_CLK1_A_PIN] = &msm8916_bb_clk1_a_pin, + [RPM_SMD_BB_CLK2] = &msm8916_bb_clk2, + [RPM_SMD_BB_CLK2_A] = &msm8916_bb_clk2_a, + [RPM_SMD_BB_CLK2_PIN] = &msm8916_bb_clk2_pin, + [RPM_SMD_BB_CLK2_A_PIN] = &msm8916_bb_clk2_a_pin, + [RPM_SMD_DIV_CLK1] = &msm8974_div_clk1, + [RPM_SMD_DIV_A_CLK1] = &msm8974_div_a_clk1, + [RPM_SMD_DIV_CLK2] = &msm8974_div_clk2, + [RPM_SMD_DIV_A_CLK2] = &msm8974_div_a_clk2, + [RPM_SMD_DIV_CLK3] = &msm8992_div_clk3, + [RPM_SMD_DIV_A_CLK3] = &msm8992_div_clk3_a, + [RPM_SMD_IPA_CLK] = &msm8976_ipa_clk, + [RPM_SMD_IPA_A_CLK] = &msm8976_ipa_a_clk, + [RPM_SMD_LN_BB_CLK] = &msm8992_ln_bb_clk, + [RPM_SMD_LN_BB_A_CLK] = &msm8992_ln_bb_a_clk, + [RPM_SMD_MMSSNOC_AHB_CLK] = &msm8974_mmssnoc_ahb_clk, + [RPM_SMD_MMSSNOC_AHB_A_CLK] = &msm8974_mmssnoc_ahb_a_clk, + [RPM_SMD_QDSS_CLK] = &msm8916_qdss_clk, + [RPM_SMD_QDSS_A_CLK] = &msm8916_qdss_a_clk, + [RPM_SMD_RF_CLK1] = &msm8916_rf_clk1, + [RPM_SMD_RF_CLK1_A] = &msm8916_rf_clk1_a, + [RPM_SMD_RF_CLK2] = &msm8916_rf_clk2, + [RPM_SMD_RF_CLK2_A] = &msm8916_rf_clk2_a, + [RPM_SMD_RF_CLK1_PIN] = &msm8916_rf_clk1_pin, + [RPM_SMD_RF_CLK1_A_PIN] = &msm8916_rf_clk1_a_pin, + [RPM_SMD_RF_CLK2_PIN] = &msm8916_rf_clk2_pin, + [RPM_SMD_RF_CLK2_A_PIN] = &msm8916_rf_clk2_a_pin, + [RPM_SMD_CE1_CLK] = &msm8992_ce1_clk, + [RPM_SMD_CE1_A_CLK] = &msm8992_ce1_a_clk, + [RPM_SMD_CE2_CLK] = &msm8992_ce2_clk, + [RPM_SMD_CE2_A_CLK] = &msm8992_ce2_a_clk, [RPM_SMD_CE3_CLK] = &msm8994_ce3_clk, [RPM_SMD_CE3_A_CLK] = &msm8994_ce3_a_clk, }; @@ -792,79 +721,58 @@ static const struct rpm_smd_clk_desc rpm_clk_msm8994 = { .num_clks = ARRAY_SIZE(msm8994_clks), }; -/* msm8996 */ -DEFINE_CLK_SMD_RPM(msm8996, pcnoc_clk, pcnoc_a_clk, QCOM_SMD_RPM_BUS_CLK, 0); -DEFINE_CLK_SMD_RPM(msm8996, snoc_clk, snoc_a_clk, QCOM_SMD_RPM_BUS_CLK, 1); -DEFINE_CLK_SMD_RPM(msm8996, cnoc_clk, cnoc_a_clk, QCOM_SMD_RPM_BUS_CLK, 2); -DEFINE_CLK_SMD_RPM(msm8996, bimc_clk, bimc_a_clk, QCOM_SMD_RPM_MEM_CLK, 0); DEFINE_CLK_SMD_RPM(msm8996, mmssnoc_axi_rpm_clk, mmssnoc_axi_rpm_a_clk, QCOM_SMD_RPM_MMAXI_CLK, 0); -DEFINE_CLK_SMD_RPM(msm8996, ipa_clk, ipa_a_clk, QCOM_SMD_RPM_IPA_CLK, 0); -DEFINE_CLK_SMD_RPM(msm8996, ce1_clk, ce1_a_clk, QCOM_SMD_RPM_CE_CLK, 0); DEFINE_CLK_SMD_RPM_BRANCH(msm8996, aggre1_noc_clk, aggre1_noc_a_clk, QCOM_SMD_RPM_AGGR_CLK, 1, 1000); DEFINE_CLK_SMD_RPM_BRANCH(msm8996, aggre2_noc_clk, aggre2_noc_a_clk, QCOM_SMD_RPM_AGGR_CLK, 2, 1000); -DEFINE_CLK_SMD_RPM_QDSS(msm8996, qdss_clk, qdss_a_clk, - QCOM_SMD_RPM_MISC_CLK, 1); -DEFINE_CLK_SMD_RPM_XO_BUFFER(msm8996, bb_clk1, bb_clk1_a, 1); -DEFINE_CLK_SMD_RPM_XO_BUFFER(msm8996, bb_clk2, bb_clk2_a, 2); -DEFINE_CLK_SMD_RPM_XO_BUFFER(msm8996, rf_clk1, rf_clk1_a, 4); -DEFINE_CLK_SMD_RPM_XO_BUFFER(msm8996, rf_clk2, rf_clk2_a, 5); -DEFINE_CLK_SMD_RPM_XO_BUFFER(msm8996, ln_bb_clk, ln_bb_a_clk, 8); -DEFINE_CLK_SMD_RPM_XO_BUFFER(msm8996, div_clk1, div_clk1_a, 0xb); -DEFINE_CLK_SMD_RPM_XO_BUFFER(msm8996, div_clk2, div_clk2_a, 0xc); -DEFINE_CLK_SMD_RPM_XO_BUFFER(msm8996, div_clk3, div_clk3_a, 0xd); -DEFINE_CLK_SMD_RPM_XO_BUFFER_PINCTRL(msm8996, bb_clk1_pin, bb_clk1_a_pin, 1); -DEFINE_CLK_SMD_RPM_XO_BUFFER_PINCTRL(msm8996, bb_clk2_pin, bb_clk2_a_pin, 2); -DEFINE_CLK_SMD_RPM_XO_BUFFER_PINCTRL(msm8996, rf_clk1_pin, rf_clk1_a_pin, 4); -DEFINE_CLK_SMD_RPM_XO_BUFFER_PINCTRL(msm8996, rf_clk2_pin, rf_clk2_a_pin, 5); static struct clk_smd_rpm *msm8996_clks[] = { - [RPM_SMD_PCNOC_CLK] = &msm8996_pcnoc_clk, - [RPM_SMD_PCNOC_A_CLK] = &msm8996_pcnoc_a_clk, - [RPM_SMD_SNOC_CLK] = &msm8996_snoc_clk, - [RPM_SMD_SNOC_A_CLK] = &msm8996_snoc_a_clk, - [RPM_SMD_CNOC_CLK] = &msm8996_cnoc_clk, - [RPM_SMD_CNOC_A_CLK] = &msm8996_cnoc_a_clk, - [RPM_SMD_BIMC_CLK] = &msm8996_bimc_clk, - [RPM_SMD_BIMC_A_CLK] = &msm8996_bimc_a_clk, + [RPM_SMD_PCNOC_CLK] = &msm8916_pcnoc_clk, + [RPM_SMD_PCNOC_A_CLK] = &msm8916_pcnoc_a_clk, + [RPM_SMD_SNOC_CLK] = &msm8916_snoc_clk, + [RPM_SMD_SNOC_A_CLK] = &msm8916_snoc_a_clk, + [RPM_SMD_CNOC_CLK] = &msm8974_cnoc_clk, + [RPM_SMD_CNOC_A_CLK] = &msm8974_cnoc_a_clk, + [RPM_SMD_BIMC_CLK] = &msm8916_bimc_clk, + [RPM_SMD_BIMC_A_CLK] = &msm8916_bimc_a_clk, [RPM_SMD_MMAXI_CLK] = &msm8996_mmssnoc_axi_rpm_clk, [RPM_SMD_MMAXI_A_CLK] = &msm8996_mmssnoc_axi_rpm_a_clk, - [RPM_SMD_IPA_CLK] = &msm8996_ipa_clk, - [RPM_SMD_IPA_A_CLK] = &msm8996_ipa_a_clk, - [RPM_SMD_CE1_CLK] = &msm8996_ce1_clk, - [RPM_SMD_CE1_A_CLK] = &msm8996_ce1_a_clk, + [RPM_SMD_IPA_CLK] = &msm8976_ipa_clk, + [RPM_SMD_IPA_A_CLK] = &msm8976_ipa_a_clk, + [RPM_SMD_CE1_CLK] = &msm8992_ce1_clk, + [RPM_SMD_CE1_A_CLK] = &msm8992_ce1_a_clk, [RPM_SMD_AGGR1_NOC_CLK] = &msm8996_aggre1_noc_clk, [RPM_SMD_AGGR1_NOC_A_CLK] = &msm8996_aggre1_noc_a_clk, [RPM_SMD_AGGR2_NOC_CLK] = &msm8996_aggre2_noc_clk, [RPM_SMD_AGGR2_NOC_A_CLK] = &msm8996_aggre2_noc_a_clk, - [RPM_SMD_QDSS_CLK] = &msm8996_qdss_clk, - [RPM_SMD_QDSS_A_CLK] = &msm8996_qdss_a_clk, - [RPM_SMD_BB_CLK1] = &msm8996_bb_clk1, - [RPM_SMD_BB_CLK1_A] = &msm8996_bb_clk1_a, - [RPM_SMD_BB_CLK2] = &msm8996_bb_clk2, - [RPM_SMD_BB_CLK2_A] = &msm8996_bb_clk2_a, - [RPM_SMD_RF_CLK1] = &msm8996_rf_clk1, - [RPM_SMD_RF_CLK1_A] = &msm8996_rf_clk1_a, - [RPM_SMD_RF_CLK2] = &msm8996_rf_clk2, - [RPM_SMD_RF_CLK2_A] = &msm8996_rf_clk2_a, - [RPM_SMD_LN_BB_CLK] = &msm8996_ln_bb_clk, - [RPM_SMD_LN_BB_A_CLK] = &msm8996_ln_bb_a_clk, - [RPM_SMD_DIV_CLK1] = &msm8996_div_clk1, - [RPM_SMD_DIV_A_CLK1] = &msm8996_div_clk1_a, - [RPM_SMD_DIV_CLK2] = &msm8996_div_clk2, - [RPM_SMD_DIV_A_CLK2] = &msm8996_div_clk2_a, - [RPM_SMD_DIV_CLK3] = &msm8996_div_clk3, - [RPM_SMD_DIV_A_CLK3] = &msm8996_div_clk3_a, - [RPM_SMD_BB_CLK1_PIN] = &msm8996_bb_clk1_pin, - [RPM_SMD_BB_CLK1_A_PIN] = &msm8996_bb_clk1_a_pin, - [RPM_SMD_BB_CLK2_PIN] = &msm8996_bb_clk2_pin, - [RPM_SMD_BB_CLK2_A_PIN] = &msm8996_bb_clk2_a_pin, - [RPM_SMD_RF_CLK1_PIN] = &msm8996_rf_clk1_pin, - [RPM_SMD_RF_CLK1_A_PIN] = &msm8996_rf_clk1_a_pin, - [RPM_SMD_RF_CLK2_PIN] = &msm8996_rf_clk2_pin, - [RPM_SMD_RF_CLK2_A_PIN] = &msm8996_rf_clk2_a_pin, + [RPM_SMD_QDSS_CLK] = &msm8916_qdss_clk, + [RPM_SMD_QDSS_A_CLK] = &msm8916_qdss_a_clk, + [RPM_SMD_BB_CLK1] = &msm8916_bb_clk1, + [RPM_SMD_BB_CLK1_A] = &msm8916_bb_clk1_a, + [RPM_SMD_BB_CLK2] = &msm8916_bb_clk2, + [RPM_SMD_BB_CLK2_A] = &msm8916_bb_clk2_a, + [RPM_SMD_RF_CLK1] = &msm8916_rf_clk1, + [RPM_SMD_RF_CLK1_A] = &msm8916_rf_clk1_a, + [RPM_SMD_RF_CLK2] = &msm8916_rf_clk2, + [RPM_SMD_RF_CLK2_A] = &msm8916_rf_clk2_a, + [RPM_SMD_LN_BB_CLK] = &msm8992_ln_bb_clk, + [RPM_SMD_LN_BB_A_CLK] = &msm8992_ln_bb_a_clk, + [RPM_SMD_DIV_CLK1] = &msm8974_div_clk1, + [RPM_SMD_DIV_A_CLK1] = &msm8974_div_a_clk1, + [RPM_SMD_DIV_CLK2] = &msm8974_div_clk2, + [RPM_SMD_DIV_A_CLK2] = &msm8974_div_a_clk2, + [RPM_SMD_DIV_CLK3] = &msm8992_div_clk3, + [RPM_SMD_DIV_A_CLK3] = &msm8992_div_clk3_a, + [RPM_SMD_BB_CLK1_PIN] = &msm8916_bb_clk1_pin, + [RPM_SMD_BB_CLK1_A_PIN] = &msm8916_bb_clk1_a_pin, + [RPM_SMD_BB_CLK2_PIN] = &msm8916_bb_clk2_pin, + [RPM_SMD_BB_CLK2_A_PIN] = &msm8916_bb_clk2_a_pin, + [RPM_SMD_RF_CLK1_PIN] = &msm8916_rf_clk1_pin, + [RPM_SMD_RF_CLK1_A_PIN] = &msm8916_rf_clk1_a_pin, + [RPM_SMD_RF_CLK2_PIN] = &msm8916_rf_clk2_pin, + [RPM_SMD_RF_CLK2_A_PIN] = &msm8916_rf_clk2_a_pin, }; static const struct rpm_smd_clk_desc rpm_clk_msm8996 = { @@ -872,43 +780,29 @@ static const struct rpm_smd_clk_desc rpm_clk_msm8996 = { .num_clks = ARRAY_SIZE(msm8996_clks), }; -/* QCS404 */ -DEFINE_CLK_SMD_RPM_QDSS(qcs404, qdss_clk, qdss_a_clk, QCOM_SMD_RPM_MISC_CLK, 1); - -DEFINE_CLK_SMD_RPM(qcs404, pnoc_clk, pnoc_a_clk, QCOM_SMD_RPM_BUS_CLK, 0); -DEFINE_CLK_SMD_RPM(qcs404, snoc_clk, snoc_a_clk, QCOM_SMD_RPM_BUS_CLK, 1); - -DEFINE_CLK_SMD_RPM(qcs404, bimc_clk, bimc_a_clk, QCOM_SMD_RPM_MEM_CLK, 0); DEFINE_CLK_SMD_RPM(qcs404, bimc_gpu_clk, bimc_gpu_a_clk, QCOM_SMD_RPM_MEM_CLK, 2); - DEFINE_CLK_SMD_RPM(qcs404, qpic_clk, qpic_a_clk, QCOM_SMD_RPM_QPIC_CLK, 0); -DEFINE_CLK_SMD_RPM(qcs404, ce1_clk, ce1_a_clk, QCOM_SMD_RPM_CE_CLK, 0); - -DEFINE_CLK_SMD_RPM_XO_BUFFER(qcs404, rf_clk1, rf_clk1_a, 4); -DEFINE_CLK_SMD_RPM_XO_BUFFER_PINCTRL(qcs404, rf_clk1_pin, rf_clk1_a_pin, 4); - -DEFINE_CLK_SMD_RPM_XO_BUFFER(qcs404, ln_bb_clk, ln_bb_a_clk, 8); DEFINE_CLK_SMD_RPM_XO_BUFFER_PINCTRL(qcs404, ln_bb_clk_pin, ln_bb_clk_a_pin, 8); static struct clk_smd_rpm *qcs404_clks[] = { - [RPM_SMD_QDSS_CLK] = &qcs404_qdss_clk, - [RPM_SMD_QDSS_A_CLK] = &qcs404_qdss_a_clk, - [RPM_SMD_PNOC_CLK] = &qcs404_pnoc_clk, - [RPM_SMD_PNOC_A_CLK] = &qcs404_pnoc_a_clk, - [RPM_SMD_SNOC_CLK] = &qcs404_snoc_clk, - [RPM_SMD_SNOC_A_CLK] = &qcs404_snoc_a_clk, - [RPM_SMD_BIMC_CLK] = &qcs404_bimc_clk, - [RPM_SMD_BIMC_A_CLK] = &qcs404_bimc_a_clk, + [RPM_SMD_QDSS_CLK] = &msm8916_qdss_clk, + [RPM_SMD_QDSS_A_CLK] = &msm8916_qdss_a_clk, + [RPM_SMD_PNOC_CLK] = &msm8916_pcnoc_clk, + [RPM_SMD_PNOC_A_CLK] = &msm8916_pcnoc_a_clk, + [RPM_SMD_SNOC_CLK] = &msm8916_snoc_clk, + [RPM_SMD_SNOC_A_CLK] = &msm8916_snoc_a_clk, + [RPM_SMD_BIMC_CLK] = &msm8916_bimc_clk, + [RPM_SMD_BIMC_A_CLK] = &msm8916_bimc_a_clk, [RPM_SMD_BIMC_GPU_CLK] = &qcs404_bimc_gpu_clk, [RPM_SMD_BIMC_GPU_A_CLK] = &qcs404_bimc_gpu_a_clk, [RPM_SMD_QPIC_CLK] = &qcs404_qpic_clk, [RPM_SMD_QPIC_CLK_A] = &qcs404_qpic_a_clk, - [RPM_SMD_CE1_CLK] = &qcs404_ce1_clk, - [RPM_SMD_CE1_A_CLK] = &qcs404_ce1_a_clk, - [RPM_SMD_RF_CLK1] = &qcs404_rf_clk1, - [RPM_SMD_RF_CLK1_A] = &qcs404_rf_clk1_a, - [RPM_SMD_LN_BB_CLK] = &qcs404_ln_bb_clk, - [RPM_SMD_LN_BB_A_CLK] = &qcs404_ln_bb_a_clk, + [RPM_SMD_CE1_CLK] = &msm8992_ce1_clk, + [RPM_SMD_CE1_A_CLK] = &msm8992_ce1_a_clk, + [RPM_SMD_RF_CLK1] = &msm8916_rf_clk1, + [RPM_SMD_RF_CLK1_A] = &msm8916_rf_clk1_a, + [RPM_SMD_LN_BB_CLK] = &msm8992_ln_bb_clk, + [RPM_SMD_LN_BB_A_CLK] = &msm8992_ln_bb_a_clk, }; static const struct rpm_smd_clk_desc rpm_clk_qcs404 = { @@ -916,63 +810,47 @@ static const struct rpm_smd_clk_desc rpm_clk_qcs404 = { .num_clks = ARRAY_SIZE(qcs404_clks), }; -/* msm8998 */ -DEFINE_CLK_SMD_RPM(msm8998, bimc_clk, bimc_a_clk, QCOM_SMD_RPM_MEM_CLK, 0); -DEFINE_CLK_SMD_RPM(msm8998, pcnoc_clk, pcnoc_a_clk, QCOM_SMD_RPM_BUS_CLK, 0); -DEFINE_CLK_SMD_RPM(msm8998, snoc_clk, snoc_a_clk, QCOM_SMD_RPM_BUS_CLK, 1); -DEFINE_CLK_SMD_RPM(msm8998, cnoc_clk, cnoc_a_clk, QCOM_SMD_RPM_BUS_CLK, 2); -DEFINE_CLK_SMD_RPM(msm8998, ce1_clk, ce1_a_clk, QCOM_SMD_RPM_CE_CLK, 0); -DEFINE_CLK_SMD_RPM_XO_BUFFER(msm8998, div_clk1, div_clk1_a, 0xb); -DEFINE_CLK_SMD_RPM(msm8998, ipa_clk, ipa_a_clk, QCOM_SMD_RPM_IPA_CLK, 0); -DEFINE_CLK_SMD_RPM_XO_BUFFER(msm8998, ln_bb_clk1, ln_bb_clk1_a, 1); -DEFINE_CLK_SMD_RPM_XO_BUFFER(msm8998, ln_bb_clk2, ln_bb_clk2_a, 2); DEFINE_CLK_SMD_RPM_XO_BUFFER_PINCTRL(msm8998, ln_bb_clk3_pin, ln_bb_clk3_a_pin, 3); -DEFINE_CLK_SMD_RPM(msm8998, mmssnoc_axi_rpm_clk, mmssnoc_axi_rpm_a_clk, - QCOM_SMD_RPM_MMAXI_CLK, 0); DEFINE_CLK_SMD_RPM(msm8998, aggre1_noc_clk, aggre1_noc_a_clk, QCOM_SMD_RPM_AGGR_CLK, 1); DEFINE_CLK_SMD_RPM(msm8998, aggre2_noc_clk, aggre2_noc_a_clk, QCOM_SMD_RPM_AGGR_CLK, 2); -DEFINE_CLK_SMD_RPM_QDSS(msm8998, qdss_clk, qdss_a_clk, - QCOM_SMD_RPM_MISC_CLK, 1); -DEFINE_CLK_SMD_RPM_XO_BUFFER(msm8998, rf_clk1, rf_clk1_a, 4); -DEFINE_CLK_SMD_RPM_XO_BUFFER_PINCTRL(msm8998, rf_clk2_pin, rf_clk2_a_pin, 5); DEFINE_CLK_SMD_RPM_XO_BUFFER(msm8998, rf_clk3, rf_clk3_a, 6); DEFINE_CLK_SMD_RPM_XO_BUFFER_PINCTRL(msm8998, rf_clk3_pin, rf_clk3_a_pin, 6); static struct clk_smd_rpm *msm8998_clks[] = { - [RPM_SMD_BIMC_CLK] = &msm8998_bimc_clk, - [RPM_SMD_BIMC_A_CLK] = &msm8998_bimc_a_clk, - [RPM_SMD_PCNOC_CLK] = &msm8998_pcnoc_clk, - [RPM_SMD_PCNOC_A_CLK] = &msm8998_pcnoc_a_clk, - [RPM_SMD_SNOC_CLK] = &msm8998_snoc_clk, - [RPM_SMD_SNOC_A_CLK] = &msm8998_snoc_a_clk, - [RPM_SMD_CNOC_CLK] = &msm8998_cnoc_clk, - [RPM_SMD_CNOC_A_CLK] = &msm8998_cnoc_a_clk, - [RPM_SMD_CE1_CLK] = &msm8998_ce1_clk, - [RPM_SMD_CE1_A_CLK] = &msm8998_ce1_a_clk, - [RPM_SMD_DIV_CLK1] = &msm8998_div_clk1, - [RPM_SMD_DIV_A_CLK1] = &msm8998_div_clk1_a, - [RPM_SMD_IPA_CLK] = &msm8998_ipa_clk, - [RPM_SMD_IPA_A_CLK] = &msm8998_ipa_a_clk, - [RPM_SMD_LN_BB_CLK1] = &msm8998_ln_bb_clk1, - [RPM_SMD_LN_BB_CLK1_A] = &msm8998_ln_bb_clk1_a, - [RPM_SMD_LN_BB_CLK2] = &msm8998_ln_bb_clk2, - [RPM_SMD_LN_BB_CLK2_A] = &msm8998_ln_bb_clk2_a, + [RPM_SMD_BIMC_CLK] = &msm8916_bimc_clk, + [RPM_SMD_BIMC_A_CLK] = &msm8916_bimc_a_clk, + [RPM_SMD_PCNOC_CLK] = &msm8916_pcnoc_clk, + [RPM_SMD_PCNOC_A_CLK] = &msm8916_pcnoc_a_clk, + [RPM_SMD_SNOC_CLK] = &msm8916_snoc_clk, + [RPM_SMD_SNOC_A_CLK] = &msm8916_snoc_a_clk, + [RPM_SMD_CNOC_CLK] = &msm8974_cnoc_clk, + [RPM_SMD_CNOC_A_CLK] = &msm8974_cnoc_a_clk, + [RPM_SMD_CE1_CLK] = &msm8992_ce1_clk, + [RPM_SMD_CE1_A_CLK] = &msm8992_ce1_a_clk, + [RPM_SMD_DIV_CLK1] = &msm8974_div_clk1, + [RPM_SMD_DIV_A_CLK1] = &msm8974_div_a_clk1, + [RPM_SMD_IPA_CLK] = &msm8976_ipa_clk, + [RPM_SMD_IPA_A_CLK] = &msm8976_ipa_a_clk, + [RPM_SMD_LN_BB_CLK1] = &msm8916_bb_clk1, + [RPM_SMD_LN_BB_CLK1_A] = &msm8916_bb_clk1_a, + [RPM_SMD_LN_BB_CLK2] = &msm8916_bb_clk2, + [RPM_SMD_LN_BB_CLK2_A] = &msm8916_bb_clk2_a, [RPM_SMD_LN_BB_CLK3_PIN] = &msm8998_ln_bb_clk3_pin, [RPM_SMD_LN_BB_CLK3_A_PIN] = &msm8998_ln_bb_clk3_a_pin, - [RPM_SMD_MMAXI_CLK] = &msm8998_mmssnoc_axi_rpm_clk, - [RPM_SMD_MMAXI_A_CLK] = &msm8998_mmssnoc_axi_rpm_a_clk, + [RPM_SMD_MMAXI_CLK] = &msm8996_mmssnoc_axi_rpm_clk, + [RPM_SMD_MMAXI_A_CLK] = &msm8996_mmssnoc_axi_rpm_a_clk, [RPM_SMD_AGGR1_NOC_CLK] = &msm8998_aggre1_noc_clk, [RPM_SMD_AGGR1_NOC_A_CLK] = &msm8998_aggre1_noc_a_clk, [RPM_SMD_AGGR2_NOC_CLK] = &msm8998_aggre2_noc_clk, [RPM_SMD_AGGR2_NOC_A_CLK] = &msm8998_aggre2_noc_a_clk, - [RPM_SMD_QDSS_CLK] = &msm8998_qdss_clk, - [RPM_SMD_QDSS_A_CLK] = &msm8998_qdss_a_clk, - [RPM_SMD_RF_CLK1] = &msm8998_rf_clk1, - [RPM_SMD_RF_CLK1_A] = &msm8998_rf_clk1_a, - [RPM_SMD_RF_CLK2_PIN] = &msm8998_rf_clk2_pin, - [RPM_SMD_RF_CLK2_A_PIN] = &msm8998_rf_clk2_a_pin, + [RPM_SMD_QDSS_CLK] = &msm8916_qdss_clk, + [RPM_SMD_QDSS_A_CLK] = &msm8916_qdss_a_clk, + [RPM_SMD_RF_CLK1] = &msm8916_rf_clk1, + [RPM_SMD_RF_CLK1_A] = &msm8916_rf_clk1_a, + [RPM_SMD_RF_CLK2_PIN] = &msm8916_rf_clk2_pin, + [RPM_SMD_RF_CLK2_A_PIN] = &msm8916_rf_clk2_a_pin, [RPM_SMD_RF_CLK3] = &msm8998_rf_clk3, [RPM_SMD_RF_CLK3_A] = &msm8998_rf_clk3_a, [RPM_SMD_RF_CLK3_PIN] = &msm8998_rf_clk3_pin, @@ -984,72 +862,48 @@ static const struct rpm_smd_clk_desc rpm_clk_msm8998 = { .num_clks = ARRAY_SIZE(msm8998_clks), }; -/* sdm660 */ DEFINE_CLK_SMD_RPM_BRANCH(sdm660, bi_tcxo, bi_tcxo_a, QCOM_SMD_RPM_MISC_CLK, 0, 19200000); -DEFINE_CLK_SMD_RPM(sdm660, snoc_clk, snoc_a_clk, QCOM_SMD_RPM_BUS_CLK, 1); -DEFINE_CLK_SMD_RPM(sdm660, cnoc_clk, cnoc_a_clk, QCOM_SMD_RPM_BUS_CLK, 2); -DEFINE_CLK_SMD_RPM(sdm660, cnoc_periph_clk, cnoc_periph_a_clk, - QCOM_SMD_RPM_BUS_CLK, 0); -DEFINE_CLK_SMD_RPM(sdm660, bimc_clk, bimc_a_clk, QCOM_SMD_RPM_MEM_CLK, 0); -DEFINE_CLK_SMD_RPM(sdm660, mmssnoc_axi_clk, mmssnoc_axi_a_clk, - QCOM_SMD_RPM_MMAXI_CLK, 0); -DEFINE_CLK_SMD_RPM(sdm660, ipa_clk, ipa_a_clk, QCOM_SMD_RPM_IPA_CLK, 0); -DEFINE_CLK_SMD_RPM(sdm660, ce1_clk, ce1_a_clk, QCOM_SMD_RPM_CE_CLK, 0); -DEFINE_CLK_SMD_RPM(sdm660, aggre2_noc_clk, aggre2_noc_a_clk, - QCOM_SMD_RPM_AGGR_CLK, 2); -DEFINE_CLK_SMD_RPM_QDSS(sdm660, qdss_clk, qdss_a_clk, - QCOM_SMD_RPM_MISC_CLK, 1); -DEFINE_CLK_SMD_RPM_XO_BUFFER(sdm660, rf_clk1, rf_clk1_a, 4); -DEFINE_CLK_SMD_RPM_XO_BUFFER(sdm660, div_clk1, div_clk1_a, 11); -DEFINE_CLK_SMD_RPM_XO_BUFFER(sdm660, ln_bb_clk1, ln_bb_clk1_a, 1); -DEFINE_CLK_SMD_RPM_XO_BUFFER(sdm660, ln_bb_clk2, ln_bb_clk2_a, 2); DEFINE_CLK_SMD_RPM_XO_BUFFER(sdm660, ln_bb_clk3, ln_bb_clk3_a, 3); +DEFINE_CLK_SMD_RPM_XO_BUFFER_PINCTRL(sdm660, ln_bb_clk3_pin, ln_bb_clk3_pin_a, 3); -DEFINE_CLK_SMD_RPM_XO_BUFFER_PINCTRL(sdm660, rf_clk1_pin, rf_clk1_a_pin, 4); -DEFINE_CLK_SMD_RPM_XO_BUFFER_PINCTRL(sdm660, ln_bb_clk1_pin, - ln_bb_clk1_pin_a, 1); -DEFINE_CLK_SMD_RPM_XO_BUFFER_PINCTRL(sdm660, ln_bb_clk2_pin, - ln_bb_clk2_pin_a, 2); -DEFINE_CLK_SMD_RPM_XO_BUFFER_PINCTRL(sdm660, ln_bb_clk3_pin, - ln_bb_clk3_pin_a, 3); static struct clk_smd_rpm *sdm660_clks[] = { [RPM_SMD_XO_CLK_SRC] = &sdm660_bi_tcxo, [RPM_SMD_XO_A_CLK_SRC] = &sdm660_bi_tcxo_a, - [RPM_SMD_SNOC_CLK] = &sdm660_snoc_clk, - [RPM_SMD_SNOC_A_CLK] = &sdm660_snoc_a_clk, - [RPM_SMD_CNOC_CLK] = &sdm660_cnoc_clk, - [RPM_SMD_CNOC_A_CLK] = &sdm660_cnoc_a_clk, - [RPM_SMD_CNOC_PERIPH_CLK] = &sdm660_cnoc_periph_clk, - [RPM_SMD_CNOC_PERIPH_A_CLK] = &sdm660_cnoc_periph_a_clk, - [RPM_SMD_BIMC_CLK] = &sdm660_bimc_clk, - [RPM_SMD_BIMC_A_CLK] = &sdm660_bimc_a_clk, - [RPM_SMD_MMSSNOC_AXI_CLK] = &sdm660_mmssnoc_axi_clk, - [RPM_SMD_MMSSNOC_AXI_CLK_A] = &sdm660_mmssnoc_axi_a_clk, - [RPM_SMD_IPA_CLK] = &sdm660_ipa_clk, - [RPM_SMD_IPA_A_CLK] = &sdm660_ipa_a_clk, - [RPM_SMD_CE1_CLK] = &sdm660_ce1_clk, - [RPM_SMD_CE1_A_CLK] = &sdm660_ce1_a_clk, - [RPM_SMD_AGGR2_NOC_CLK] = &sdm660_aggre2_noc_clk, - [RPM_SMD_AGGR2_NOC_A_CLK] = &sdm660_aggre2_noc_a_clk, - [RPM_SMD_QDSS_CLK] = &sdm660_qdss_clk, - [RPM_SMD_QDSS_A_CLK] = &sdm660_qdss_a_clk, - [RPM_SMD_RF_CLK1] = &sdm660_rf_clk1, - [RPM_SMD_RF_CLK1_A] = &sdm660_rf_clk1_a, - [RPM_SMD_DIV_CLK1] = &sdm660_div_clk1, - [RPM_SMD_DIV_A_CLK1] = &sdm660_div_clk1_a, - [RPM_SMD_LN_BB_CLK] = &sdm660_ln_bb_clk1, - [RPM_SMD_LN_BB_A_CLK] = &sdm660_ln_bb_clk1_a, - [RPM_SMD_LN_BB_CLK2] = &sdm660_ln_bb_clk2, - [RPM_SMD_LN_BB_CLK2_A] = &sdm660_ln_bb_clk2_a, + [RPM_SMD_SNOC_CLK] = &msm8916_snoc_clk, + [RPM_SMD_SNOC_A_CLK] = &msm8916_snoc_a_clk, + [RPM_SMD_CNOC_CLK] = &msm8974_cnoc_clk, + [RPM_SMD_CNOC_A_CLK] = &msm8974_cnoc_a_clk, + [RPM_SMD_CNOC_PERIPH_CLK] = &msm8916_pcnoc_clk, + [RPM_SMD_CNOC_PERIPH_A_CLK] = &msm8916_pcnoc_a_clk, + [RPM_SMD_BIMC_CLK] = &msm8916_bimc_clk, + [RPM_SMD_BIMC_A_CLK] = &msm8916_bimc_a_clk, + [RPM_SMD_MMSSNOC_AXI_CLK] = &msm8996_mmssnoc_axi_rpm_clk, + [RPM_SMD_MMSSNOC_AXI_CLK_A] = &msm8996_mmssnoc_axi_rpm_a_clk, + [RPM_SMD_IPA_CLK] = &msm8976_ipa_clk, + [RPM_SMD_IPA_A_CLK] = &msm8976_ipa_a_clk, + [RPM_SMD_CE1_CLK] = &msm8992_ce1_clk, + [RPM_SMD_CE1_A_CLK] = &msm8992_ce1_a_clk, + [RPM_SMD_AGGR2_NOC_CLK] = &msm8998_aggre2_noc_clk, + [RPM_SMD_AGGR2_NOC_A_CLK] = &msm8998_aggre2_noc_a_clk, + [RPM_SMD_QDSS_CLK] = &msm8916_qdss_clk, + [RPM_SMD_QDSS_A_CLK] = &msm8916_qdss_a_clk, + [RPM_SMD_RF_CLK1] = &msm8916_rf_clk1, + [RPM_SMD_RF_CLK1_A] = &msm8916_rf_clk1_a, + [RPM_SMD_DIV_CLK1] = &msm8974_div_clk1, + [RPM_SMD_DIV_A_CLK1] = &msm8974_div_a_clk1, + [RPM_SMD_LN_BB_CLK] = &msm8916_bb_clk1, + [RPM_SMD_LN_BB_A_CLK] = &msm8916_bb_clk1_a, + [RPM_SMD_LN_BB_CLK2] = &msm8916_bb_clk2, + [RPM_SMD_LN_BB_CLK2_A] = &msm8916_bb_clk2_a, [RPM_SMD_LN_BB_CLK3] = &sdm660_ln_bb_clk3, [RPM_SMD_LN_BB_CLK3_A] = &sdm660_ln_bb_clk3_a, - [RPM_SMD_RF_CLK1_PIN] = &sdm660_rf_clk1_pin, - [RPM_SMD_RF_CLK1_A_PIN] = &sdm660_rf_clk1_a_pin, - [RPM_SMD_LN_BB_CLK1_PIN] = &sdm660_ln_bb_clk1_pin, - [RPM_SMD_LN_BB_CLK1_A_PIN] = &sdm660_ln_bb_clk1_pin_a, - [RPM_SMD_LN_BB_CLK2_PIN] = &sdm660_ln_bb_clk2_pin, - [RPM_SMD_LN_BB_CLK2_A_PIN] = &sdm660_ln_bb_clk2_pin_a, + [RPM_SMD_RF_CLK1_PIN] = &msm8916_rf_clk1_pin, + [RPM_SMD_RF_CLK1_A_PIN] = &msm8916_rf_clk1_a_pin, + [RPM_SMD_LN_BB_CLK1_PIN] = &msm8916_bb_clk1_pin, + [RPM_SMD_LN_BB_CLK1_A_PIN] = &msm8916_bb_clk1_a_pin, + [RPM_SMD_LN_BB_CLK2_PIN] = &msm8916_bb_clk2_pin, + [RPM_SMD_LN_BB_CLK2_A_PIN] = &msm8916_bb_clk2_a_pin, [RPM_SMD_LN_BB_CLK3_PIN] = &sdm660_ln_bb_clk3_pin, [RPM_SMD_LN_BB_CLK3_A_PIN] = &sdm660_ln_bb_clk3_pin_a, }; @@ -1060,6 +914,7 @@ static const struct rpm_smd_clk_desc rpm_clk_sdm660 = { }; static const struct of_device_id rpm_smd_clk_match_table[] = { + { .compatible = "qcom,rpmcc-msm8226", .data = &rpm_clk_msm8974 }, { .compatible = "qcom,rpmcc-msm8916", .data = &rpm_clk_msm8916 }, { .compatible = "qcom,rpmcc-msm8936", .data = &rpm_clk_msm8936 }, { .compatible = "qcom,rpmcc-msm8974", .data = &rpm_clk_msm8974 }, diff --git a/drivers/clk/qcom/dispcc-sm8250.c b/drivers/clk/qcom/dispcc-sm8250.c index de09cd5c209f..601c7c0ba483 100644 --- a/drivers/clk/qcom/dispcc-sm8250.c +++ b/drivers/clk/qcom/dispcc-sm8250.c @@ -26,6 +26,8 @@ enum { P_DISP_CC_PLL1_OUT_MAIN, P_DP_PHY_PLL_LINK_CLK, P_DP_PHY_PLL_VCO_DIV_CLK, + P_EDP_PHY_PLL_LINK_CLK, + P_EDP_PHY_PLL_VCO_DIV_CLK, P_DSI0_PHY_PLL_OUT_BYTECLK, P_DSI0_PHY_PLL_OUT_DSICLK, P_DSI1_PHY_PLL_OUT_BYTECLK, @@ -134,6 +136,18 @@ static const struct clk_parent_data disp_cc_parent_data_3[] = { { .hw = &disp_cc_pll1.clkr.hw }, }; +static const struct parent_map disp_cc_parent_map_4[] = { + { P_BI_TCXO, 0 }, + { P_EDP_PHY_PLL_LINK_CLK, 1 }, + { P_EDP_PHY_PLL_VCO_DIV_CLK, 2}, +}; + +static const struct clk_parent_data disp_cc_parent_data_4[] = { + { .fw_name = "bi_tcxo" }, + { .fw_name = "edp_phy_pll_link_clk" }, + { .fw_name = "edp_phy_pll_vco_div_clk" }, +}; + static const struct parent_map disp_cc_parent_map_5[] = { { P_BI_TCXO, 0 }, { P_DISP_CC_PLL0_OUT_MAIN, 1 }, @@ -158,6 +172,18 @@ static const struct clk_parent_data disp_cc_parent_data_6[] = { { .fw_name = "dsi1_phy_pll_out_dsiclk" }, }; +static const struct parent_map disp_cc_parent_map_7[] = { + { P_BI_TCXO, 0 }, + { P_DISP_CC_PLL1_OUT_MAIN, 4 }, + /* { P_DISP_CC_PLL1_OUT_EVEN, 5 }, */ +}; + +static const struct clk_parent_data disp_cc_parent_data_7[] = { + { .fw_name = "bi_tcxo" }, + { .hw = &disp_cc_pll1.clkr.hw }, + /* { .hw = &disp_cc_pll1_out_even.clkr.hw }, */ +}; + static const struct freq_tbl ftbl_disp_cc_mdss_ahb_clk_src[] = { F(19200000, P_BI_TCXO, 1, 0, 0), F(37500000, P_DISP_CC_PLL1_OUT_MAIN, 16, 0, 0), @@ -261,7 +287,7 @@ static struct clk_rcg2 disp_cc_mdss_dp_link1_clk_src = { .name = "disp_cc_mdss_dp_link1_clk_src", .parent_data = disp_cc_parent_data_0, .num_parents = ARRAY_SIZE(disp_cc_parent_data_0), - .ops = &clk_rcg2_ops, + .ops = &clk_byte2_ops, }, }; @@ -275,7 +301,7 @@ static struct clk_rcg2 disp_cc_mdss_dp_link_clk_src = { .name = "disp_cc_mdss_dp_link_clk_src", .parent_data = disp_cc_parent_data_0, .num_parents = ARRAY_SIZE(disp_cc_parent_data_0), - .ops = &clk_rcg2_ops, + .ops = &clk_byte2_ops, }, }; @@ -318,6 +344,153 @@ static struct clk_rcg2 disp_cc_mdss_dp_pixel_clk_src = { }, }; +static struct clk_rcg2 disp_cc_mdss_edp_aux_clk_src = { + .cmd_rcgr = 0x228c, + .mnd_width = 0, + .hid_width = 5, + .parent_map = disp_cc_parent_map_1, + .freq_tbl = ftbl_disp_cc_mdss_byte0_clk_src, + .clkr.hw.init = &(struct clk_init_data){ + .name = "disp_cc_mdss_edp_aux_clk_src", + .parent_data = disp_cc_parent_data_1, + .num_parents = ARRAY_SIZE(disp_cc_parent_data_1), + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_rcg2_ops, + }, +}; + +static struct clk_rcg2 disp_cc_mdss_edp_gtc_clk_src = { + .cmd_rcgr = 0x22a4, + .mnd_width = 0, + .hid_width = 5, + .parent_map = disp_cc_parent_map_7, + .freq_tbl = ftbl_disp_cc_mdss_byte0_clk_src, + .clkr.hw.init = &(struct clk_init_data){ + .name = "disp_cc_mdss_edp_gtc_clk_src", + .parent_data = disp_cc_parent_data_7, + .num_parents = ARRAY_SIZE(disp_cc_parent_data_7), + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_rcg2_ops, + }, +}; + +static struct clk_rcg2 disp_cc_mdss_edp_link_clk_src = { + .cmd_rcgr = 0x2270, + .mnd_width = 0, + .hid_width = 5, + .parent_map = disp_cc_parent_map_4, + .clkr.hw.init = &(struct clk_init_data){ + .name = "disp_cc_mdss_edp_link_clk_src", + .parent_data = disp_cc_parent_data_4, + .num_parents = ARRAY_SIZE(disp_cc_parent_data_4), + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_byte2_ops, + }, +}; + +static struct clk_rcg2 disp_cc_mdss_edp_pixel_clk_src = { + .cmd_rcgr = 0x2258, + .mnd_width = 16, + .hid_width = 5, + .parent_map = disp_cc_parent_map_4, + .clkr.hw.init = &(struct clk_init_data){ + .name = "disp_cc_mdss_edp_pixel_clk_src", + .parent_data = disp_cc_parent_data_4, + .num_parents = ARRAY_SIZE(disp_cc_parent_data_4), + .ops = &clk_dp_ops, + }, +}; + +static struct clk_branch disp_cc_mdss_edp_aux_clk = { + .halt_reg = 0x2078, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x2078, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "disp_cc_mdss_edp_aux_clk", + .parent_hws = (const struct clk_hw*[]){ + &disp_cc_mdss_edp_aux_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch disp_cc_mdss_edp_gtc_clk = { + .halt_reg = 0x207c, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x207c, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "disp_cc_mdss_edp_gtc_clk", + .parent_hws = (const struct clk_hw*[]){ + &disp_cc_mdss_edp_gtc_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch disp_cc_mdss_edp_link_clk = { + .halt_reg = 0x2070, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x2070, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "disp_cc_mdss_edp_link_clk", + .parent_hws = (const struct clk_hw*[]){ + &disp_cc_mdss_edp_link_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch disp_cc_mdss_edp_link_intf_clk = { + .halt_reg = 0x2074, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x2074, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "disp_cc_mdss_edp_link_intf_clk", + .parent_hws = (const struct clk_hw*[]){ + &disp_cc_mdss_edp_link_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_GET_RATE_NOCACHE, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch disp_cc_mdss_edp_pixel_clk = { + .halt_reg = 0x206c, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x206c, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "disp_cc_mdss_edp_pixel_clk", + .parent_hws = (const struct clk_hw*[]){ + &disp_cc_mdss_edp_pixel_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + static struct clk_rcg2 disp_cc_mdss_esc0_clk_src = { .cmd_rcgr = 0x2148, .mnd_width = 0, @@ -987,6 +1160,15 @@ static struct clk_regmap *disp_cc_sm8250_clocks[] = { [DISP_CC_MDSS_DP_PIXEL2_CLK_SRC] = &disp_cc_mdss_dp_pixel2_clk_src.clkr, [DISP_CC_MDSS_DP_PIXEL_CLK] = &disp_cc_mdss_dp_pixel_clk.clkr, [DISP_CC_MDSS_DP_PIXEL_CLK_SRC] = &disp_cc_mdss_dp_pixel_clk_src.clkr, + [DISP_CC_MDSS_EDP_AUX_CLK] = &disp_cc_mdss_edp_aux_clk.clkr, + [DISP_CC_MDSS_EDP_AUX_CLK_SRC] = &disp_cc_mdss_edp_aux_clk_src.clkr, + [DISP_CC_MDSS_EDP_GTC_CLK] = &disp_cc_mdss_edp_gtc_clk.clkr, + [DISP_CC_MDSS_EDP_GTC_CLK_SRC] = &disp_cc_mdss_edp_gtc_clk_src.clkr, + [DISP_CC_MDSS_EDP_LINK_CLK] = &disp_cc_mdss_edp_link_clk.clkr, + [DISP_CC_MDSS_EDP_LINK_CLK_SRC] = &disp_cc_mdss_edp_link_clk_src.clkr, + [DISP_CC_MDSS_EDP_LINK_INTF_CLK] = &disp_cc_mdss_edp_link_intf_clk.clkr, + [DISP_CC_MDSS_EDP_PIXEL_CLK] = &disp_cc_mdss_edp_pixel_clk.clkr, + [DISP_CC_MDSS_EDP_PIXEL_CLK_SRC] = &disp_cc_mdss_edp_pixel_clk_src.clkr, [DISP_CC_MDSS_ESC0_CLK] = &disp_cc_mdss_esc0_clk.clkr, [DISP_CC_MDSS_ESC0_CLK_SRC] = &disp_cc_mdss_esc0_clk_src.clkr, [DISP_CC_MDSS_ESC1_CLK] = &disp_cc_mdss_esc1_clk.clkr, @@ -1037,6 +1219,7 @@ static const struct qcom_cc_desc disp_cc_sm8250_desc = { }; static const struct of_device_id disp_cc_sm8250_match_table[] = { + { .compatible = "qcom,sc8180x-dispcc" }, { .compatible = "qcom,sm8150-dispcc" }, { .compatible = "qcom,sm8250-dispcc" }, { } @@ -1053,7 +1236,8 @@ static int disp_cc_sm8250_probe(struct platform_device *pdev) /* note: trion == lucid, except for the prepare() op */ BUILD_BUG_ON(CLK_ALPHA_PLL_TYPE_TRION != CLK_ALPHA_PLL_TYPE_LUCID); - if (of_device_is_compatible(pdev->dev.of_node, "qcom,sm8150-dispcc")) { + if (of_device_is_compatible(pdev->dev.of_node, "qcom,sc8180x-dispcc") || + of_device_is_compatible(pdev->dev.of_node, "qcom,sm8150-dispcc")) { disp_cc_pll0_config.config_ctl_hi_val = 0x00002267; disp_cc_pll0_config.config_ctl_hi1_val = 0x00000024; disp_cc_pll0_config.user_ctl_hi1_val = 0x000000D0; diff --git a/drivers/clk/qcom/gcc-mdm9607.c b/drivers/clk/qcom/gcc-mdm9607.c new file mode 100644 index 000000000000..4c9078e99bb3 --- /dev/null +++ b/drivers/clk/qcom/gcc-mdm9607.c @@ -0,0 +1,1632 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright (c) 2021, Konrad Dybcio <konrad.dybcio@somainline.org> + */ + +#include <linux/kernel.h> +#include <linux/bitops.h> +#include <linux/err.h> +#include <linux/platform_device.h> +#include <linux/module.h> +#include <linux/of.h> +#include <linux/of_device.h> +#include <linux/clk-provider.h> +#include <linux/regmap.h> +#include <linux/reset-controller.h> + +#include <dt-bindings/clock/qcom,gcc-mdm9607.h> + +#include "common.h" +#include "clk-regmap.h" +#include "clk-alpha-pll.h" +#include "clk-pll.h" +#include "clk-rcg.h" +#include "clk-branch.h" +#include "reset.h" +#include "gdsc.h" + +enum { + P_XO, + P_BIMC, + P_GPLL0, + P_GPLL1, + P_GPLL2, + P_SLEEP_CLK, +}; + +static struct clk_alpha_pll gpll0_early = { + .offset = 0x21000, + .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_DEFAULT], + .clkr = { + .enable_reg = 0x45000, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data) + { + .name = "gpll0_early", + .parent_data = &(const struct clk_parent_data){ + .fw_name = "xo", + }, + .num_parents = 1, + .ops = &clk_alpha_pll_ops, + }, + }, +}; + +static struct clk_alpha_pll_postdiv gpll0 = { + .offset = 0x21000, + .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_DEFAULT], + .clkr.hw.init = &(struct clk_init_data) + { + .name = "gpll0", + .parent_hws = (const struct clk_hw *[]){ &gpll0_early.clkr.hw }, + .num_parents = 1, + .ops = &clk_alpha_pll_postdiv_ops, + }, +}; + +static const struct parent_map gcc_xo_gpll0_map[] = { + { P_XO, 0 }, + { P_GPLL0, 1 }, +}; + +static const struct clk_parent_data gcc_xo_gpll0[] = { + { .fw_name = "xo" }, + { .hw = &gpll0.clkr.hw }, +}; + +static struct clk_pll gpll1 = { + .l_reg = 0x20004, + .m_reg = 0x20008, + .n_reg = 0x2000c, + .config_reg = 0x20010, + .mode_reg = 0x20000, + .status_reg = 0x2001c, + .status_bit = 17, + .clkr.hw.init = &(struct clk_init_data){ + .name = "gpll1", + .parent_data = &(const struct clk_parent_data){ + .fw_name = "xo", + }, + .num_parents = 1, + .ops = &clk_pll_ops, + }, +}; + +static struct clk_regmap gpll1_vote = { + .enable_reg = 0x45000, + .enable_mask = BIT(1), + .hw.init = &(struct clk_init_data){ + .name = "gpll1_vote", + .parent_hws = (const struct clk_hw *[]){ &gpll1.clkr.hw }, + .num_parents = 1, + .ops = &clk_pll_vote_ops, + }, +}; + +static const struct parent_map gcc_xo_gpll0_gpll1_sleep_map[] = { + { P_XO, 0 }, + { P_GPLL0, 1 }, + { P_GPLL1, 2 }, + { P_SLEEP_CLK, 6 }, +}; + +static const struct clk_parent_data gcc_xo_gpll0_gpll1_sleep[] = { + { .fw_name = "xo" }, + { .hw = &gpll0.clkr.hw }, + { .hw = &gpll1_vote.hw }, + { .fw_name = "sleep_clk" }, +}; + +static struct clk_alpha_pll gpll2_early = { + .offset = 0x25000, + .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_DEFAULT], + .clkr = { + .enable_reg = 0x45000, + .enable_mask = BIT(3), /* Yeah, apparently it's not 2 */ + .hw.init = &(struct clk_init_data) + { + .name = "gpll2_early", + .parent_data = &(const struct clk_parent_data){ + .fw_name = "xo", + }, + .num_parents = 1, + .ops = &clk_alpha_pll_ops, + }, + }, +}; + +static struct clk_alpha_pll_postdiv gpll2 = { + .offset = 0x25000, + .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_DEFAULT], + .clkr.hw.init = &(struct clk_init_data) + { + .name = "gpll2", + .parent_hws = (const struct clk_hw *[]){ &gpll2_early.clkr.hw }, + .num_parents = 1, + .ops = &clk_alpha_pll_postdiv_ops, + }, +}; + +static const struct parent_map gcc_xo_gpll0_gpll2_map[] = { + { P_XO, 0 }, + { P_GPLL0, 1 }, + { P_GPLL2, 2 }, +}; + +static const struct clk_parent_data gcc_xo_gpll0_gpll2[] = { + { .fw_name = "xo" }, + { .hw = &gpll0.clkr.hw }, + { .hw = &gpll2.clkr.hw }, +}; + +static const struct parent_map gcc_xo_gpll0_gpll1_gpll2_map[] = { + { P_XO, 0 }, + { P_GPLL0, 1 }, + { P_GPLL1, 2 }, + { P_GPLL2, 3 }, +}; + +static const struct clk_parent_data gcc_xo_gpll0_gpll1_gpll2[] = { + { .fw_name = "xo" }, + { .hw = &gpll0.clkr.hw }, + { .hw = &gpll1_vote.hw }, + { .hw = &gpll2.clkr.hw }, +}; + +static const struct freq_tbl ftbl_apss_ahb_clk[] = { + F(19200000, P_XO, 1, 0, 0), + F(50000000, P_GPLL0, 16, 0, 0), + F(100000000, P_GPLL0, 8, 0, 0), + { } +}; + +static struct clk_rcg2 apss_ahb_clk_src = { + .cmd_rcgr = 0x46000, + .hid_width = 5, + .parent_map = gcc_xo_gpll0_map, + .freq_tbl = ftbl_apss_ahb_clk, + .clkr.hw.init = &(struct clk_init_data){ + .name = "apss_ahb_clk_src", + .parent_data = gcc_xo_gpll0, + .num_parents = 2, + .ops = &clk_rcg2_ops, + }, +}; + +static struct clk_pll bimc_pll = { + .l_reg = 0x23004, + .m_reg = 0x23008, + .n_reg = 0x2300c, + .config_reg = 0x23010, + .mode_reg = 0x23000, + .status_reg = 0x2301c, + .status_bit = 17, + .clkr.hw.init = &(struct clk_init_data){ + .name = "bimc_pll", + .parent_data = &(const struct clk_parent_data){ + .fw_name = "xo", + }, + .num_parents = 1, + .ops = &clk_pll_ops, + }, +}; + +static struct clk_regmap bimc_pll_vote = { + .enable_reg = 0x45000, + .enable_mask = BIT(3), + .hw.init = &(struct clk_init_data){ + .name = "bimc_pll_vote", + .parent_hws = (const struct clk_hw *[]){ &bimc_pll.clkr.hw }, + .num_parents = 1, + .ops = &clk_pll_vote_ops, + }, +}; + +static const struct parent_map gcc_xo_gpll0_bimc_map[] = { + { P_XO, 0 }, + { P_GPLL0, 1 }, + { P_BIMC, 2 }, +}; + +static const struct clk_parent_data gcc_xo_gpll0_bimc[] = { + { .fw_name = "xo" }, + { .hw = &gpll0.clkr.hw }, + { .hw = &bimc_pll_vote.hw }, +}; + +static const struct freq_tbl ftbl_pcnoc_bfdcd_clk_src[] = { + F(19200000, P_XO, 1, 0, 0), + F(50000000, P_GPLL0, 16, 0, 0), + F(100000000, P_GPLL0, 8, 0, 0), + { } +}; + +static struct clk_rcg2 pcnoc_bfdcd_clk_src = { + .cmd_rcgr = 0x27000, + .freq_tbl = ftbl_pcnoc_bfdcd_clk_src, + .hid_width = 5, + .parent_map = gcc_xo_gpll0_bimc_map, + .clkr.hw.init = &(struct clk_init_data){ + .name = "pcnoc_bfdcd_clk_src", + .parent_data = gcc_xo_gpll0_bimc, + .num_parents = ARRAY_SIZE(gcc_xo_gpll0_bimc), + .ops = &clk_rcg2_ops, + .flags = CLK_IS_CRITICAL, + }, +}; + +static struct clk_rcg2 system_noc_bfdcd_clk_src = { + .cmd_rcgr = 0x26004, + .hid_width = 5, + .parent_map = gcc_xo_gpll0_bimc_map, + .clkr.hw.init = &(struct clk_init_data){ + .name = "system_noc_bfdcd_clk_src", + .parent_data = gcc_xo_gpll0_bimc, + .num_parents = ARRAY_SIZE(gcc_xo_gpll0_bimc), + .ops = &clk_rcg2_ops, + }, +}; + +static const struct freq_tbl ftbl_gcc_blsp1_qup1_6_i2c_apps_clk[] = { + F(19200000, P_XO, 1, 0, 0), + F(50000000, P_GPLL0, 16, 0, 0), + { } +}; + +static struct clk_rcg2 blsp1_qup1_i2c_apps_clk_src = { + .cmd_rcgr = 0x200c, + .hid_width = 5, + .parent_map = gcc_xo_gpll0_map, + .freq_tbl = ftbl_gcc_blsp1_qup1_6_i2c_apps_clk, + .clkr.hw.init = &(struct clk_init_data){ + .name = "blsp1_qup1_i2c_apps_clk_src", + .parent_data = gcc_xo_gpll0, + .num_parents = 2, + .ops = &clk_rcg2_ops, + }, +}; + +static const struct freq_tbl ftbl_gcc_blsp1_qup1_6_spi_apps_clk[] = { + F(960000, P_XO, 10, 1, 2), + F(4800000, P_XO, 4, 0, 0), + F(9600000, P_XO, 2, 0, 0), + F(16000000, P_GPLL0, 10, 1, 5), + F(19200000, P_XO, 1, 0, 0), + F(25000000, P_GPLL0, 16, 1, 2), + F(50000000, P_GPLL0, 16, 0, 0), + { } +}; + +static struct clk_rcg2 blsp1_qup1_spi_apps_clk_src = { + .cmd_rcgr = 0x2024, + .mnd_width = 8, + .hid_width = 5, + .parent_map = gcc_xo_gpll0_map, + .freq_tbl = ftbl_gcc_blsp1_qup1_6_spi_apps_clk, + .clkr.hw.init = &(struct clk_init_data){ + .name = "blsp1_qup1_spi_apps_clk_src", + .parent_data = gcc_xo_gpll0, + .num_parents = 2, + .ops = &clk_rcg2_ops, + }, +}; + +static struct clk_rcg2 blsp1_qup2_i2c_apps_clk_src = { + .cmd_rcgr = 0x3000, + .hid_width = 5, + .parent_map = gcc_xo_gpll0_map, + .freq_tbl = ftbl_gcc_blsp1_qup1_6_i2c_apps_clk, + .clkr.hw.init = &(struct clk_init_data){ + .name = "blsp1_qup2_i2c_apps_clk_src", + .parent_data = gcc_xo_gpll0, + .num_parents = 2, + .ops = &clk_rcg2_ops, + }, +}; + +static struct clk_rcg2 blsp1_qup2_spi_apps_clk_src = { + .cmd_rcgr = 0x3014, + .mnd_width = 8, + .hid_width = 5, + .parent_map = gcc_xo_gpll0_map, + .freq_tbl = ftbl_gcc_blsp1_qup1_6_spi_apps_clk, + .clkr.hw.init = &(struct clk_init_data){ + .name = "blsp1_qup2_spi_apps_clk_src", + .parent_data = gcc_xo_gpll0, + .num_parents = 2, + .ops = &clk_rcg2_ops, + }, +}; + +static struct clk_rcg2 blsp1_qup3_i2c_apps_clk_src = { + .cmd_rcgr = 0x4000, + .hid_width = 5, + .parent_map = gcc_xo_gpll0_map, + .freq_tbl = ftbl_gcc_blsp1_qup1_6_i2c_apps_clk, + .clkr.hw.init = &(struct clk_init_data){ + .name = "blsp1_qup3_i2c_apps_clk_src", + .parent_data = gcc_xo_gpll0, + .num_parents = 2, + .ops = &clk_rcg2_ops, + }, +}; + +static struct clk_rcg2 blsp1_qup3_spi_apps_clk_src = { + .cmd_rcgr = 0x4024, + .mnd_width = 8, + .hid_width = 5, + .parent_map = gcc_xo_gpll0_map, + .freq_tbl = ftbl_gcc_blsp1_qup1_6_spi_apps_clk, + .clkr.hw.init = &(struct clk_init_data){ + .name = "blsp1_qup3_spi_apps_clk_src", + .parent_data = gcc_xo_gpll0, + .num_parents = 2, + .ops = &clk_rcg2_ops, + }, +}; + +static struct clk_rcg2 blsp1_qup4_i2c_apps_clk_src = { + .cmd_rcgr = 0x5000, + .hid_width = 5, + .parent_map = gcc_xo_gpll0_map, + .freq_tbl = ftbl_gcc_blsp1_qup1_6_i2c_apps_clk, + .clkr.hw.init = &(struct clk_init_data){ + .name = "blsp1_qup4_i2c_apps_clk_src", + .parent_data = gcc_xo_gpll0, + .num_parents = 2, + .ops = &clk_rcg2_ops, + }, +}; + +static struct clk_rcg2 blsp1_qup4_spi_apps_clk_src = { + .cmd_rcgr = 0x5024, + .mnd_width = 8, + .hid_width = 5, + .parent_map = gcc_xo_gpll0_map, + .freq_tbl = ftbl_gcc_blsp1_qup1_6_spi_apps_clk, + .clkr.hw.init = &(struct clk_init_data){ + .name = "blsp1_qup4_spi_apps_clk_src", + .parent_data = gcc_xo_gpll0, + .num_parents = 2, + .ops = &clk_rcg2_ops, + }, +}; + +static struct clk_rcg2 blsp1_qup5_i2c_apps_clk_src = { + .cmd_rcgr = 0x6000, + .hid_width = 5, + .parent_map = gcc_xo_gpll0_map, + .freq_tbl = ftbl_gcc_blsp1_qup1_6_i2c_apps_clk, + .clkr.hw.init = &(struct clk_init_data){ + .name = "blsp1_qup5_i2c_apps_clk_src", + .parent_data = gcc_xo_gpll0, + .num_parents = 2, + .ops = &clk_rcg2_ops, + }, +}; + +static struct clk_rcg2 blsp1_qup5_spi_apps_clk_src = { + .cmd_rcgr = 0x6024, + .mnd_width = 8, + .hid_width = 5, + .parent_map = gcc_xo_gpll0_map, + .freq_tbl = ftbl_gcc_blsp1_qup1_6_spi_apps_clk, + .clkr.hw.init = &(struct clk_init_data){ + .name = "blsp1_qup5_spi_apps_clk_src", + .parent_data = gcc_xo_gpll0, + .num_parents = 2, + .ops = &clk_rcg2_ops, + }, +}; + +static struct clk_rcg2 blsp1_qup6_i2c_apps_clk_src = { + .cmd_rcgr = 0x7000, + .hid_width = 5, + .parent_map = gcc_xo_gpll0_map, + .freq_tbl = ftbl_gcc_blsp1_qup1_6_i2c_apps_clk, + .clkr.hw.init = &(struct clk_init_data){ + .name = "blsp1_qup6_i2c_apps_clk_src", + .parent_data = gcc_xo_gpll0, + .num_parents = 2, + .ops = &clk_rcg2_ops, + }, +}; + +static struct clk_rcg2 blsp1_qup6_spi_apps_clk_src = { + .cmd_rcgr = 0x7024, + .mnd_width = 8, + .hid_width = 5, + .parent_map = gcc_xo_gpll0_map, + .freq_tbl = ftbl_gcc_blsp1_qup1_6_spi_apps_clk, + .clkr.hw.init = &(struct clk_init_data){ + .name = "blsp1_qup6_spi_apps_clk_src", + .parent_data = gcc_xo_gpll0, + .num_parents = 2, + .ops = &clk_rcg2_ops, + }, +}; + +static const struct freq_tbl ftbl_gcc_blsp1_uart1_6_apps_clk[] = { + F(3686400, P_GPLL0, 1, 72, 15625), + F(7372800, P_GPLL0, 1, 144, 15625), + F(14745600, P_GPLL0, 1, 288, 15625), + F(16000000, P_GPLL0, 10, 1, 5), + F(19200000, P_XO, 1, 0, 0), + F(24000000, P_GPLL0, 1, 3, 100), + F(25000000, P_GPLL0, 16, 1, 2), + F(32000000, P_GPLL0, 1, 1, 25), + F(40000000, P_GPLL0, 1, 1, 20), + F(46400000, P_GPLL0, 1, 29, 500), + F(48000000, P_GPLL0, 1, 3, 50), + F(51200000, P_GPLL0, 1, 8, 125), + F(56000000, P_GPLL0, 1, 7, 100), + F(58982400, P_GPLL0, 1, 1152, 15625), + F(60000000, P_GPLL0, 1, 3, 40), + { } +}; + +static struct clk_rcg2 blsp1_uart1_apps_clk_src = { + .cmd_rcgr = 0x2044, + .mnd_width = 16, + .hid_width = 5, + .parent_map = gcc_xo_gpll0_map, + .freq_tbl = ftbl_gcc_blsp1_uart1_6_apps_clk, + .clkr.hw.init = &(struct clk_init_data){ + .name = "blsp1_uart1_apps_clk_src", + .parent_data = gcc_xo_gpll0, + .num_parents = 2, + .ops = &clk_rcg2_ops, + }, +}; + +static struct clk_rcg2 blsp1_uart2_apps_clk_src = { + .cmd_rcgr = 0x3034, + .mnd_width = 16, + .hid_width = 5, + .parent_map = gcc_xo_gpll0_map, + .freq_tbl = ftbl_gcc_blsp1_uart1_6_apps_clk, + .clkr.hw.init = &(struct clk_init_data){ + .name = "blsp1_uart2_apps_clk_src", + .parent_data = gcc_xo_gpll0, + .num_parents = 2, + .ops = &clk_rcg2_ops, + }, +}; + +static struct clk_rcg2 blsp1_uart3_apps_clk_src = { + .cmd_rcgr = 0x4044, + .mnd_width = 16, + .hid_width = 5, + .parent_map = gcc_xo_gpll0_map, + .freq_tbl = ftbl_gcc_blsp1_uart1_6_apps_clk, + .clkr.hw.init = &(struct clk_init_data){ + .name = "blsp1_uart3_apps_clk_src", + .parent_data = gcc_xo_gpll0, + .num_parents = 2, + .ops = &clk_rcg2_ops, + }, +}; + +static struct clk_rcg2 blsp1_uart4_apps_clk_src = { + .cmd_rcgr = 0x5044, + .mnd_width = 16, + .hid_width = 5, + .parent_map = gcc_xo_gpll0_map, + .freq_tbl = ftbl_gcc_blsp1_uart1_6_apps_clk, + .clkr.hw.init = &(struct clk_init_data){ + .name = "blsp1_uart4_apps_clk_src", + .parent_data = gcc_xo_gpll0, + .num_parents = 2, + .ops = &clk_rcg2_ops, + }, +}; + +static struct clk_rcg2 blsp1_uart5_apps_clk_src = { + .cmd_rcgr = 0x6044, + .mnd_width = 16, + .hid_width = 5, + .parent_map = gcc_xo_gpll0_map, + .freq_tbl = ftbl_gcc_blsp1_uart1_6_apps_clk, + .clkr.hw.init = &(struct clk_init_data){ + .name = "blsp1_uart5_apps_clk_src", + .parent_data = gcc_xo_gpll0, + .num_parents = 2, + .ops = &clk_rcg2_ops, + }, +}; + +static struct clk_rcg2 blsp1_uart6_apps_clk_src = { + .cmd_rcgr = 0x6044, + .mnd_width = 16, + .hid_width = 5, + .parent_map = gcc_xo_gpll0_map, + .freq_tbl = ftbl_gcc_blsp1_uart1_6_apps_clk, + .clkr.hw.init = &(struct clk_init_data){ + .name = "blsp1_uart6_apps_clk_src", + .parent_data = gcc_xo_gpll0, + .num_parents = 2, + .ops = &clk_rcg2_ops, + }, +}; + +static const struct freq_tbl ftbl_gcc_crypto_clk[] = { + F(50000000, P_GPLL0, 16, 0, 0), + F(80000000, P_GPLL0, 10, 0, 0), + F(100000000, P_GPLL0, 8, 0, 0), + F(160000000, P_GPLL0, 5, 0, 0), + { } +}; + +static struct clk_rcg2 crypto_clk_src = { + .cmd_rcgr = 0x16004, + .hid_width = 5, + .parent_map = gcc_xo_gpll0_map, + .freq_tbl = ftbl_gcc_crypto_clk, + .clkr.hw.init = &(struct clk_init_data){ + .name = "crypto_clk_src", + .parent_data = gcc_xo_gpll0, + .num_parents = 2, + .ops = &clk_rcg2_ops, + }, +}; + +static const struct freq_tbl ftbl_gcc_gp1_3_clk[] = { + F(19200000, P_XO, 1, 0, 0), + { } +}; + +static struct clk_rcg2 gp1_clk_src = { + .cmd_rcgr = 0x8004, + .mnd_width = 8, + .hid_width = 5, + .parent_map = gcc_xo_gpll0_gpll1_sleep_map, + .freq_tbl = ftbl_gcc_gp1_3_clk, + .clkr.hw.init = &(struct clk_init_data){ + .name = "gp1_clk_src", + .parent_data = gcc_xo_gpll0_gpll1_sleep, + .num_parents = ARRAY_SIZE(gcc_xo_gpll0_gpll1_sleep), + .ops = &clk_rcg2_ops, + }, +}; + +static struct clk_rcg2 gp2_clk_src = { + .cmd_rcgr = 0x09004, + .mnd_width = 8, + .hid_width = 5, + .parent_map = gcc_xo_gpll0_gpll1_sleep_map, + .freq_tbl = ftbl_gcc_gp1_3_clk, + .clkr.hw.init = &(struct clk_init_data){ + .name = "gp2_clk_src", + .parent_data = gcc_xo_gpll0_gpll1_sleep, + .num_parents = ARRAY_SIZE(gcc_xo_gpll0_gpll1_sleep), + .ops = &clk_rcg2_ops, + }, +}; + +static struct clk_rcg2 gp3_clk_src = { + .cmd_rcgr = 0x0a004, + .mnd_width = 8, + .hid_width = 5, + .parent_map = gcc_xo_gpll0_gpll1_sleep_map, + .freq_tbl = ftbl_gcc_gp1_3_clk, + .clkr.hw.init = &(struct clk_init_data){ + .name = "gp3_clk_src", + .parent_data = gcc_xo_gpll0_gpll1_sleep, + .num_parents = ARRAY_SIZE(gcc_xo_gpll0_gpll1_sleep), + .ops = &clk_rcg2_ops, + }, +}; + +static const struct freq_tbl ftbl_gcc_pdm2_clk[] = { + F(64000000, P_GPLL0, 12.5, 0, 0), + { } +}; + +static struct clk_rcg2 pdm2_clk_src = { + .cmd_rcgr = 0x44010, + .hid_width = 5, + .parent_map = gcc_xo_gpll0_map, + .freq_tbl = ftbl_gcc_pdm2_clk, + .clkr.hw.init = &(struct clk_init_data){ + .name = "pdm2_clk_src", + .parent_data = gcc_xo_gpll0, + .num_parents = 2, + .ops = &clk_rcg2_ops, + }, +}; + +static const struct freq_tbl ftbl_gcc_sdcc_apps_clk[] = { + F(144000, P_XO, 16, 3, 25), + F(400000, P_XO, 12, 1, 4), + F(20000000, P_GPLL0, 10, 1, 4), + F(25000000, P_GPLL0, 16, 1, 2), + F(50000000, P_GPLL0, 16, 0, 0), + F(100000000, P_GPLL0, 8, 0, 0), + F(177770000, P_GPLL0, 4.5, 0, 0), + F(200000000, P_GPLL0, 4, 0, 0), + { } +}; + +static struct clk_rcg2 sdcc1_apps_clk_src = { + .cmd_rcgr = 0x42004, + .mnd_width = 8, + .hid_width = 5, + .parent_map = gcc_xo_gpll0_map, + .freq_tbl = ftbl_gcc_sdcc_apps_clk, + .clkr.hw.init = &(struct clk_init_data){ + .name = "sdcc1_apps_clk_src", + .parent_data = gcc_xo_gpll0, + .num_parents = 2, + .ops = &clk_rcg2_floor_ops, + }, +}; + +static struct clk_rcg2 sdcc2_apps_clk_src = { + .cmd_rcgr = 0x43004, + .mnd_width = 8, + .hid_width = 5, + .parent_map = gcc_xo_gpll0_map, + .freq_tbl = ftbl_gcc_sdcc_apps_clk, + .clkr.hw.init = &(struct clk_init_data){ + .name = "sdcc2_apps_clk_src", + .parent_data = gcc_xo_gpll0, + .num_parents = 2, + .ops = &clk_rcg2_floor_ops, + }, +}; + +static const struct freq_tbl ftbl_gcc_apss_tcu_clk[] = { + F(155000000, P_GPLL2, 6, 0, 0), + F(310000000, P_GPLL2, 3, 0, 0), + F(400000000, P_GPLL0, 2, 0, 0), + { } +}; + +static struct clk_rcg2 apss_tcu_clk_src = { + .cmd_rcgr = 0x1207c, + .hid_width = 5, + .parent_map = gcc_xo_gpll0_gpll1_gpll2_map, + .freq_tbl = ftbl_gcc_apss_tcu_clk, + .clkr.hw.init = &(struct clk_init_data){ + .name = "apss_tcu_clk_src", + .parent_data = gcc_xo_gpll0_gpll1_gpll2, + .num_parents = 4, + .ops = &clk_rcg2_ops, + }, +}; + +static const struct freq_tbl ftbl_gcc_usb_hs_system_clk[] = { + F(19200000, P_XO, 1, 0, 0), + F(57140000, P_GPLL0, 14, 0, 0), + F(69565000, P_GPLL0, 11.5, 0, 0), + F(133330000, P_GPLL0, 6, 0, 0), + F(177778000, P_GPLL0, 4.5, 0, 0), + { } +}; + +static struct clk_rcg2 usb_hs_system_clk_src = { + .cmd_rcgr = 0x41010, + .hid_width = 5, + .parent_map = gcc_xo_gpll0_map, + .freq_tbl = ftbl_gcc_usb_hs_system_clk, + .clkr.hw.init = &(struct clk_init_data){ + .name = "usb_hs_system_clk_src", + .parent_data = gcc_xo_gpll0, + .num_parents = 2, + .ops = &clk_rcg2_ops, + }, +}; + +static const struct freq_tbl ftbl_usb_hsic_clk_src[] = { + F(480000000, P_GPLL2, 1, 0, 0), + { } +}; + +static struct clk_rcg2 usb_hsic_clk_src = { + .cmd_rcgr = 0x3d018, + .hid_width = 5, + .parent_map = gcc_xo_gpll0_gpll2_map, + .freq_tbl = ftbl_usb_hsic_clk_src, + .clkr.hw.init = &(struct clk_init_data){ + .name = "usb_hsic_clk_src", + .parent_data = gcc_xo_gpll0_gpll2, + .num_parents = ARRAY_SIZE(gcc_xo_gpll0_gpll2), + .ops = &clk_rcg2_ops, + }, +}; + +static const struct freq_tbl ftbl_usb_hsic_io_cal_clk_src[] = { + F(9600000, P_XO, 2, 0, 0), + { } +}; + +static struct clk_rcg2 usb_hsic_io_cal_clk_src = { + .cmd_rcgr = 0x3d030, + .hid_width = 5, + .parent_map = gcc_xo_gpll0_map, + .freq_tbl = ftbl_usb_hsic_io_cal_clk_src, + .clkr.hw.init = &(struct clk_init_data){ + .name = "usb_hsic_io_cal_clk_src", + .parent_data = gcc_xo_gpll0, + .num_parents = ARRAY_SIZE(gcc_xo_gpll0), + .ops = &clk_rcg2_ops, + }, +}; + +static const struct freq_tbl ftbl_usb_hsic_system_clk_src[] = { + F(19200000, P_XO, 1, 0, 0), + F(57140000, P_GPLL0, 14, 0, 0), + F(133330000, P_GPLL0, 6, 0, 0), + F(177778000, P_GPLL0, 4.5, 0, 0), + { } +}; + +static struct clk_rcg2 usb_hsic_system_clk_src = { + .cmd_rcgr = 0x3d000, + .hid_width = 5, + .parent_map = gcc_xo_gpll0_map, + .freq_tbl = ftbl_usb_hsic_system_clk_src, + .clkr.hw.init = &(struct clk_init_data){ + .name = "usb_hsic_system_clk_src", + .parent_data = gcc_xo_gpll0, + .num_parents = ARRAY_SIZE(gcc_xo_gpll0), + .ops = &clk_rcg2_ops, + }, +}; + +static struct clk_branch gcc_blsp1_ahb_clk = { + .halt_reg = 0x1008, + .halt_check = BRANCH_HALT_VOTED, + .clkr = { + .enable_reg = 0x45004, + .enable_mask = BIT(10), + .hw.init = &(struct clk_init_data){ + .name = "gcc_blsp1_ahb_clk", + .parent_hws = (const struct clk_hw *[]){ &pcnoc_bfdcd_clk_src.clkr.hw }, + .num_parents = 1, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_blsp1_sleep_clk = { + .halt_reg = 0x1004, + .clkr = { + .enable_reg = 0x1004, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_blsp1_sleep_clk", + .parent_data = &(const struct clk_parent_data){ + .fw_name = "sleep_clk", + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_blsp1_qup1_i2c_apps_clk = { + .halt_reg = 0x2008, + .clkr = { + .enable_reg = 0x2008, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_blsp1_qup1_i2c_apps_clk", + .parent_hws = (const struct clk_hw *[]){ &blsp1_qup1_i2c_apps_clk_src.clkr.hw }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_blsp1_qup1_spi_apps_clk = { + .halt_reg = 0x2004, + .clkr = { + .enable_reg = 0x2004, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_blsp1_qup1_spi_apps_clk", + .parent_hws = (const struct clk_hw *[]){ &blsp1_qup1_spi_apps_clk_src.clkr.hw }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_blsp1_qup2_i2c_apps_clk = { + .halt_reg = 0x3010, + .clkr = { + .enable_reg = 0x3010, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_blsp1_qup2_i2c_apps_clk", + .parent_hws = (const struct clk_hw *[]){ &blsp1_qup2_i2c_apps_clk_src.clkr.hw }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_blsp1_qup2_spi_apps_clk = { + .halt_reg = 0x300c, + .clkr = { + .enable_reg = 0x300c, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_blsp1_qup2_spi_apps_clk", + .parent_hws = (const struct clk_hw *[]){ &blsp1_qup2_spi_apps_clk_src.clkr.hw }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_blsp1_qup3_i2c_apps_clk = { + .halt_reg = 0x4020, + .clkr = { + .enable_reg = 0x4020, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_blsp1_qup3_i2c_apps_clk", + .parent_hws = (const struct clk_hw *[]){ &blsp1_qup3_i2c_apps_clk_src.clkr.hw }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_blsp1_qup3_spi_apps_clk = { + .halt_reg = 0x401c, + .clkr = { + .enable_reg = 0x401c, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_blsp1_qup3_spi_apps_clk", + .parent_hws = (const struct clk_hw *[]){ &blsp1_qup3_spi_apps_clk_src.clkr.hw }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_blsp1_qup4_i2c_apps_clk = { + .halt_reg = 0x5020, + .clkr = { + .enable_reg = 0x5020, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_blsp1_qup4_i2c_apps_clk", + .parent_hws = (const struct clk_hw *[]){ &blsp1_qup4_i2c_apps_clk_src.clkr.hw }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_blsp1_qup4_spi_apps_clk = { + .halt_reg = 0x501c, + .clkr = { + .enable_reg = 0x501c, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_blsp1_qup4_spi_apps_clk", + .parent_hws = (const struct clk_hw *[]){ &blsp1_qup4_spi_apps_clk_src.clkr.hw }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_blsp1_qup5_i2c_apps_clk = { + .halt_reg = 0x6020, + .clkr = { + .enable_reg = 0x6020, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_blsp1_qup5_i2c_apps_clk", + .parent_hws = (const struct clk_hw *[]){ &blsp1_qup5_i2c_apps_clk_src.clkr.hw }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_blsp1_qup5_spi_apps_clk = { + .halt_reg = 0x601c, + .clkr = { + .enable_reg = 0x601c, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_blsp1_qup5_spi_apps_clk", + .parent_hws = (const struct clk_hw *[]){ &blsp1_qup5_spi_apps_clk_src.clkr.hw }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_blsp1_qup6_i2c_apps_clk = { + .halt_reg = 0x7020, + .clkr = { + .enable_reg = 0x7020, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_blsp1_qup6_i2c_apps_clk", + .parent_hws = (const struct clk_hw *[]){ &blsp1_qup6_i2c_apps_clk_src.clkr.hw }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_blsp1_qup6_spi_apps_clk = { + .halt_reg = 0x701c, + .clkr = { + .enable_reg = 0x701c, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_blsp1_qup6_spi_apps_clk", + .parent_hws = (const struct clk_hw *[]){ &blsp1_qup6_spi_apps_clk_src.clkr.hw }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_blsp1_uart1_apps_clk = { + .halt_reg = 0x203c, + .clkr = { + .enable_reg = 0x203c, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_blsp1_uart1_apps_clk", + .parent_hws = (const struct clk_hw *[]){ &blsp1_uart1_apps_clk_src.clkr.hw }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_blsp1_uart2_apps_clk = { + .halt_reg = 0x302c, + .clkr = { + .enable_reg = 0x302c, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_blsp1_uart2_apps_clk", + .parent_hws = (const struct clk_hw *[]){ &blsp1_uart2_apps_clk_src.clkr.hw }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_blsp1_uart3_apps_clk = { + .halt_reg = 0x403c, + .clkr = { + .enable_reg = 0x403c, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_blsp1_uart3_apps_clk", + .parent_hws = (const struct clk_hw *[]){ &blsp1_uart3_apps_clk_src.clkr.hw }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_blsp1_uart4_apps_clk = { + .halt_reg = 0x503c, + .clkr = { + .enable_reg = 0x503c, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_blsp1_uart4_apps_clk", + .parent_hws = (const struct clk_hw *[]){ &blsp1_uart4_apps_clk_src.clkr.hw }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_blsp1_uart5_apps_clk = { + .halt_reg = 0x603c, + .clkr = { + .enable_reg = 0x603c, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_blsp1_uart5_apps_clk", + .parent_hws = (const struct clk_hw *[]){ &blsp1_uart5_apps_clk_src.clkr.hw }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_blsp1_uart6_apps_clk = { + .halt_reg = 0x703c, + .clkr = { + .enable_reg = 0x703c, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_blsp1_uart6_apps_clk", + .parent_hws = (const struct clk_hw *[]){ &blsp1_uart6_apps_clk_src.clkr.hw }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_boot_rom_ahb_clk = { + .halt_reg = 0x1300c, + .halt_check = BRANCH_HALT_VOTED, + .clkr = { + .enable_reg = 0x45004, + .enable_mask = BIT(7), + .hw.init = &(struct clk_init_data){ + .name = "gcc_boot_rom_ahb_clk", + .parent_hws = (const struct clk_hw *[]){ &pcnoc_bfdcd_clk_src.clkr.hw }, + .num_parents = 1, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_crypto_ahb_clk = { + .halt_reg = 0x16024, + .halt_check = BRANCH_HALT_VOTED, + .clkr = { + .enable_reg = 0x45004, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_crypto_ahb_clk", + .parent_hws = (const struct clk_hw *[]){ &pcnoc_bfdcd_clk_src.clkr.hw }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_crypto_axi_clk = { + .halt_reg = 0x16020, + .halt_check = BRANCH_HALT_VOTED, + .clkr = { + .enable_reg = 0x45004, + .enable_mask = BIT(1), + .hw.init = &(struct clk_init_data){ + .name = "gcc_crypto_axi_clk", + .parent_hws = (const struct clk_hw *[]){ &pcnoc_bfdcd_clk_src.clkr.hw }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_crypto_clk = { + .halt_reg = 0x1601c, + .halt_check = BRANCH_HALT_VOTED, + .clkr = { + .enable_reg = 0x45004, + .enable_mask = BIT(2), + .hw.init = &(struct clk_init_data){ + .name = "gcc_crypto_clk", + .parent_hws = (const struct clk_hw *[]){ &crypto_clk_src.clkr.hw }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_gp1_clk = { + .halt_reg = 0x08000, + .clkr = { + .enable_reg = 0x08000, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_gp1_clk", + .parent_hws = (const struct clk_hw *[]){ &gp1_clk_src.clkr.hw }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_gp2_clk = { + .halt_reg = 0x09000, + .clkr = { + .enable_reg = 0x09000, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_gp2_clk", + .parent_hws = (const struct clk_hw *[]){ &gp2_clk_src.clkr.hw }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_gp3_clk = { + .halt_reg = 0x0a000, + .clkr = { + .enable_reg = 0x0a000, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_gp3_clk", + .parent_hws = (const struct clk_hw *[]){ &gp3_clk_src.clkr.hw }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_mss_cfg_ahb_clk = { + .halt_reg = 0x49000, + .clkr = { + .enable_reg = 0x49000, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_mss_cfg_ahb_clk", + .parent_hws = (const struct clk_hw *[]){ &pcnoc_bfdcd_clk_src.clkr.hw }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_pdm2_clk = { + .halt_reg = 0x4400c, + .clkr = { + .enable_reg = 0x4400c, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_pdm2_clk", + .parent_hws = (const struct clk_hw *[]){ &pdm2_clk_src.clkr.hw }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_pdm_ahb_clk = { + .halt_reg = 0x44004, + .clkr = { + .enable_reg = 0x44004, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_pdm_ahb_clk", + .parent_hws = (const struct clk_hw *[]){ &pcnoc_bfdcd_clk_src.clkr.hw }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_prng_ahb_clk = { + .halt_reg = 0x13004, + .halt_check = BRANCH_HALT_VOTED, + .clkr = { + .enable_reg = 0x45004, + .enable_mask = BIT(8), + .hw.init = &(struct clk_init_data){ + .name = "gcc_prng_ahb_clk", + .parent_hws = (const struct clk_hw *[]){ &pcnoc_bfdcd_clk_src.clkr.hw }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_sdcc1_ahb_clk = { + .halt_reg = 0x4201c, + .clkr = { + .enable_reg = 0x4201c, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_sdcc1_ahb_clk", + .parent_hws = (const struct clk_hw *[]){ &pcnoc_bfdcd_clk_src.clkr.hw }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_sdcc1_apps_clk = { + .halt_reg = 0x42018, + .clkr = { + .enable_reg = 0x42018, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_sdcc1_apps_clk", + .parent_hws = (const struct clk_hw *[]){ &sdcc1_apps_clk_src.clkr.hw }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_sdcc2_ahb_clk = { + .halt_reg = 0x4301c, + .clkr = { + .enable_reg = 0x4301c, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_sdcc2_ahb_clk", + .parent_hws = (const struct clk_hw *[]){ &pcnoc_bfdcd_clk_src.clkr.hw }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_sdcc2_apps_clk = { + .halt_reg = 0x43018, + .clkr = { + .enable_reg = 0x43018, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_sdcc2_apps_clk", + .parent_hws = (const struct clk_hw *[]){ &sdcc2_apps_clk_src.clkr.hw }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_rcg2 bimc_ddr_clk_src = { + .cmd_rcgr = 0x32004, + .hid_width = 5, + .parent_map = gcc_xo_gpll0_bimc_map, + .clkr.hw.init = &(struct clk_init_data){ + .name = "bimc_ddr_clk_src", + .parent_data = gcc_xo_gpll0_bimc, + .num_parents = 3, + .ops = &clk_rcg2_ops, + .flags = CLK_GET_RATE_NOCACHE, + }, +}; + +static struct clk_branch gcc_mss_q6_bimc_axi_clk = { + .halt_reg = 0x49004, + .clkr = { + .enable_reg = 0x49004, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_mss_q6_bimc_axi_clk", + .parent_hws = (const struct clk_hw *[]){ &bimc_ddr_clk_src.clkr.hw }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_apss_tcu_clk = { + .halt_reg = 0x12018, + .halt_check = BRANCH_HALT_VOTED, + .clkr = { + .enable_reg = 0x4500c, + .enable_mask = BIT(1), + .hw.init = &(struct clk_init_data){ + .name = "gcc_apss_tcu_clk", + .parent_hws = (const struct clk_hw *[]){ &bimc_ddr_clk_src.clkr.hw }, + .num_parents = 1, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_smmu_cfg_clk = { + .halt_reg = 0x12038, + .halt_check = BRANCH_HALT_VOTED, + .clkr = { + .enable_reg = 0x4500c, + .enable_mask = BIT(12), + .hw.init = &(struct clk_init_data){ + .name = "gcc_smmu_cfg_clk", + .parent_hws = (const struct clk_hw *[]){ &pcnoc_bfdcd_clk_src.clkr.hw }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_qdss_dap_clk = { + .halt_reg = 0x29084, + .halt_check = BRANCH_HALT_VOTED, + .clkr = { + .enable_reg = 0x45004, + .enable_mask = BIT(19), + .hw.init = &(struct clk_init_data){ + .name = "gcc_qdss_dap_clk", + .parent_data = &(const struct clk_parent_data){ + .fw_name = "xo", + }, + .num_parents = 1, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_usb2a_phy_sleep_clk = { + .halt_reg = 0x4102c, + .clkr = { + .enable_reg = 0x4102c, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_usb2a_phy_sleep_clk", + .parent_data = &(const struct clk_parent_data){ + .fw_name = "sleep_clk", + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_usb_hs_phy_cfg_ahb_clk = { + .halt_reg = 0x41030, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x41030, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_usb_hs_phy_cfg_ahb_clk", + .parent_hws = (const struct clk_hw *[]){ &pcnoc_bfdcd_clk_src.clkr.hw }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_usb_hs_ahb_clk = { + .halt_reg = 0x41008, + .clkr = { + .enable_reg = 0x41008, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_usb_hs_ahb_clk", + .parent_hws = (const struct clk_hw *[]){ &pcnoc_bfdcd_clk_src.clkr.hw }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_usb_hs_system_clk = { + .halt_reg = 0x41004, + .clkr = { + .enable_reg = 0x41004, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_usb_hs_system_clk", + .parent_hws = (const struct clk_hw *[]){ &usb_hs_system_clk_src.clkr.hw }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_apss_ahb_clk = { + .halt_reg = 0x4601c, + .halt_check = BRANCH_HALT_VOTED, + .clkr = { + .enable_reg = 0x45004, + .enable_mask = BIT(14), + .hw.init = &(struct clk_init_data){ + .name = "gcc_apss_ahb_clk", + .parent_hws = (const struct clk_hw *[]){ &pcnoc_bfdcd_clk_src.clkr.hw }, + .num_parents = 1, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_apss_axi_clk = { + .halt_reg = 0x4601c, + .halt_check = BRANCH_HALT_VOTED, + .clkr = { + .enable_reg = 0x45004, + .enable_mask = BIT(13), + .hw.init = &(struct clk_init_data){ + .name = "gcc_apss_axi_clk", + .parent_hws = (const struct clk_hw *[]){ &pcnoc_bfdcd_clk_src.clkr.hw }, + .num_parents = 1, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_regmap *gcc_mdm9607_clocks[] = { + [GPLL0] = &gpll0.clkr, + [GPLL0_EARLY] = &gpll0_early.clkr, + [GPLL1] = &gpll1.clkr, + [GPLL1_VOTE] = &gpll1_vote, + [GPLL2] = &gpll2.clkr, + [GPLL2_EARLY] = &gpll2_early.clkr, + [BIMC_PLL] = &bimc_pll.clkr, + [BIMC_PLL_VOTE] = &bimc_pll_vote, + [BIMC_DDR_CLK_SRC] = &bimc_ddr_clk_src.clkr, + [PCNOC_BFDCD_CLK_SRC] = &pcnoc_bfdcd_clk_src.clkr, + [SYSTEM_NOC_BFDCD_CLK_SRC] = &system_noc_bfdcd_clk_src.clkr, + [APSS_AHB_CLK_SRC] = &apss_ahb_clk_src.clkr, + [BLSP1_QUP1_I2C_APPS_CLK_SRC] = &blsp1_qup1_i2c_apps_clk_src.clkr, + [BLSP1_QUP1_SPI_APPS_CLK_SRC] = &blsp1_qup1_spi_apps_clk_src.clkr, + [BLSP1_QUP2_I2C_APPS_CLK_SRC] = &blsp1_qup2_i2c_apps_clk_src.clkr, + [BLSP1_QUP2_SPI_APPS_CLK_SRC] = &blsp1_qup2_spi_apps_clk_src.clkr, + [BLSP1_QUP3_I2C_APPS_CLK_SRC] = &blsp1_qup3_i2c_apps_clk_src.clkr, + [BLSP1_QUP3_SPI_APPS_CLK_SRC] = &blsp1_qup3_spi_apps_clk_src.clkr, + [BLSP1_QUP4_I2C_APPS_CLK_SRC] = &blsp1_qup4_i2c_apps_clk_src.clkr, + [BLSP1_QUP4_SPI_APPS_CLK_SRC] = &blsp1_qup4_spi_apps_clk_src.clkr, + [BLSP1_QUP5_I2C_APPS_CLK_SRC] = &blsp1_qup5_i2c_apps_clk_src.clkr, + [BLSP1_QUP5_SPI_APPS_CLK_SRC] = &blsp1_qup5_spi_apps_clk_src.clkr, + [BLSP1_QUP6_I2C_APPS_CLK_SRC] = &blsp1_qup6_i2c_apps_clk_src.clkr, + [BLSP1_QUP6_SPI_APPS_CLK_SRC] = &blsp1_qup6_spi_apps_clk_src.clkr, + [BLSP1_UART1_APPS_CLK_SRC] = &blsp1_uart1_apps_clk_src.clkr, + [BLSP1_UART2_APPS_CLK_SRC] = &blsp1_uart2_apps_clk_src.clkr, + [BLSP1_UART3_APPS_CLK_SRC] = &blsp1_uart3_apps_clk_src.clkr, + [BLSP1_UART4_APPS_CLK_SRC] = &blsp1_uart4_apps_clk_src.clkr, + [BLSP1_UART5_APPS_CLK_SRC] = &blsp1_uart5_apps_clk_src.clkr, + [BLSP1_UART6_APPS_CLK_SRC] = &blsp1_uart6_apps_clk_src.clkr, + [CRYPTO_CLK_SRC] = &crypto_clk_src.clkr, + [GP1_CLK_SRC] = &gp1_clk_src.clkr, + [GP2_CLK_SRC] = &gp2_clk_src.clkr, + [GP3_CLK_SRC] = &gp3_clk_src.clkr, + [PDM2_CLK_SRC] = &pdm2_clk_src.clkr, + [SDCC1_APPS_CLK_SRC] = &sdcc1_apps_clk_src.clkr, + [SDCC2_APPS_CLK_SRC] = &sdcc2_apps_clk_src.clkr, + [APSS_TCU_CLK_SRC] = &apss_tcu_clk_src.clkr, + [USB_HS_SYSTEM_CLK_SRC] = &usb_hs_system_clk_src.clkr, + [GCC_BLSP1_AHB_CLK] = &gcc_blsp1_ahb_clk.clkr, + [GCC_BLSP1_SLEEP_CLK] = &gcc_blsp1_sleep_clk.clkr, + [GCC_BLSP1_QUP1_I2C_APPS_CLK] = &gcc_blsp1_qup1_i2c_apps_clk.clkr, + [GCC_BLSP1_QUP1_SPI_APPS_CLK] = &gcc_blsp1_qup1_spi_apps_clk.clkr, + [GCC_BLSP1_QUP2_I2C_APPS_CLK] = &gcc_blsp1_qup2_i2c_apps_clk.clkr, + [GCC_BLSP1_QUP2_SPI_APPS_CLK] = &gcc_blsp1_qup2_spi_apps_clk.clkr, + [GCC_BLSP1_QUP3_I2C_APPS_CLK] = &gcc_blsp1_qup3_i2c_apps_clk.clkr, + [GCC_BLSP1_QUP3_SPI_APPS_CLK] = &gcc_blsp1_qup3_spi_apps_clk.clkr, + [GCC_BLSP1_QUP4_I2C_APPS_CLK] = &gcc_blsp1_qup4_i2c_apps_clk.clkr, + [GCC_BLSP1_QUP4_SPI_APPS_CLK] = &gcc_blsp1_qup4_spi_apps_clk.clkr, + [GCC_BLSP1_QUP5_I2C_APPS_CLK] = &gcc_blsp1_qup5_i2c_apps_clk.clkr, + [GCC_BLSP1_QUP5_SPI_APPS_CLK] = &gcc_blsp1_qup5_spi_apps_clk.clkr, + [GCC_BLSP1_QUP6_I2C_APPS_CLK] = &gcc_blsp1_qup6_i2c_apps_clk.clkr, + [GCC_BLSP1_QUP6_SPI_APPS_CLK] = &gcc_blsp1_qup6_spi_apps_clk.clkr, + [GCC_BLSP1_UART1_APPS_CLK] = &gcc_blsp1_uart1_apps_clk.clkr, + [GCC_BLSP1_UART2_APPS_CLK] = &gcc_blsp1_uart2_apps_clk.clkr, + [GCC_BLSP1_UART3_APPS_CLK] = &gcc_blsp1_uart3_apps_clk.clkr, + [GCC_BLSP1_UART4_APPS_CLK] = &gcc_blsp1_uart4_apps_clk.clkr, + [GCC_BLSP1_UART5_APPS_CLK] = &gcc_blsp1_uart5_apps_clk.clkr, + [GCC_BLSP1_UART6_APPS_CLK] = &gcc_blsp1_uart6_apps_clk.clkr, + [GCC_BOOT_ROM_AHB_CLK] = &gcc_boot_rom_ahb_clk.clkr, + [GCC_CRYPTO_AHB_CLK] = &gcc_crypto_ahb_clk.clkr, + [GCC_CRYPTO_AXI_CLK] = &gcc_crypto_axi_clk.clkr, + [GCC_CRYPTO_CLK] = &gcc_crypto_clk.clkr, + [GCC_GP1_CLK] = &gcc_gp1_clk.clkr, + [GCC_GP2_CLK] = &gcc_gp2_clk.clkr, + [GCC_GP3_CLK] = &gcc_gp3_clk.clkr, + [GCC_MSS_CFG_AHB_CLK] = &gcc_mss_cfg_ahb_clk.clkr, + [GCC_PDM2_CLK] = &gcc_pdm2_clk.clkr, + [GCC_PDM_AHB_CLK] = &gcc_pdm_ahb_clk.clkr, + [GCC_PRNG_AHB_CLK] = &gcc_prng_ahb_clk.clkr, + [GCC_SDCC1_AHB_CLK] = &gcc_sdcc1_ahb_clk.clkr, + [GCC_SDCC1_APPS_CLK] = &gcc_sdcc1_apps_clk.clkr, + [GCC_SDCC2_AHB_CLK] = &gcc_sdcc2_ahb_clk.clkr, + [GCC_SDCC2_APPS_CLK] = &gcc_sdcc2_apps_clk.clkr, + [GCC_SMMU_CFG_CLK] = &gcc_smmu_cfg_clk.clkr, + [GCC_USB2A_PHY_SLEEP_CLK] = &gcc_usb2a_phy_sleep_clk.clkr, + [GCC_USB_HS_PHY_CFG_AHB_CLK] = &gcc_usb_hs_phy_cfg_ahb_clk.clkr, + [GCC_USB_HS_AHB_CLK] = &gcc_usb_hs_ahb_clk.clkr, + [GCC_USB_HS_SYSTEM_CLK] = &gcc_usb_hs_system_clk.clkr, + [GCC_APSS_TCU_CLK] = &gcc_apss_tcu_clk.clkr, + [GCC_MSS_Q6_BIMC_AXI_CLK] = &gcc_mss_q6_bimc_axi_clk.clkr, + [GCC_QDSS_DAP_CLK] = &gcc_qdss_dap_clk.clkr, + [GCC_APSS_AHB_CLK] = &gcc_apss_ahb_clk.clkr, + [GCC_APSS_AXI_CLK] = &gcc_apss_axi_clk.clkr, + [GCC_USB_HSIC_CLK_SRC] = &usb_hsic_clk_src.clkr, + [GCC_USB_HSIC_IO_CAL_CLK_SRC] = &usb_hsic_io_cal_clk_src.clkr, + [GCC_USB_HSIC_SYSTEM_CLK_SRC] = &usb_hsic_system_clk_src.clkr, +}; + +static const struct qcom_reset_map gcc_mdm9607_resets[] = { + [USB_HS_HSIC_BCR] = { 0x3d05c }, + [GCC_MSS_RESTART] = { 0x3e000 }, + [USB_HS_BCR] = { 0x41000 }, + [USB2_HS_PHY_ONLY_BCR] = { 0x41034 }, + [QUSB2_PHY_BCR] = { 0x4103c }, +}; + +static const struct regmap_config gcc_mdm9607_regmap_config = { + .reg_bits = 32, + .reg_stride = 4, + .val_bits = 32, + .max_register = 0x80000, + .fast_io = true, +}; + +static const struct qcom_cc_desc gcc_mdm9607_desc = { + .config = &gcc_mdm9607_regmap_config, + .clks = gcc_mdm9607_clocks, + .num_clks = ARRAY_SIZE(gcc_mdm9607_clocks), + .resets = gcc_mdm9607_resets, + .num_resets = ARRAY_SIZE(gcc_mdm9607_resets), +}; + +static const struct of_device_id gcc_mdm9607_match_table[] = { + { .compatible = "qcom,gcc-mdm9607" }, + { } +}; +MODULE_DEVICE_TABLE(of, gcc_mdm9607_match_table); + +static int gcc_mdm9607_probe(struct platform_device *pdev) +{ + struct regmap *regmap; + + regmap = qcom_cc_map(pdev, &gcc_mdm9607_desc); + if (IS_ERR(regmap)) + return PTR_ERR(regmap); + + /* Vote for GPLL0 to turn on. Needed by acpuclock. */ + regmap_update_bits(regmap, 0x45000, BIT(0), BIT(0)); + + return qcom_cc_really_probe(pdev, &gcc_mdm9607_desc, regmap); +} + +static struct platform_driver gcc_mdm9607_driver = { + .probe = gcc_mdm9607_probe, + .driver = { + .name = "gcc-mdm9607", + .of_match_table = gcc_mdm9607_match_table, + }, +}; + +static int __init gcc_mdm9607_init(void) +{ + return platform_driver_register(&gcc_mdm9607_driver); +} +core_initcall(gcc_mdm9607_init); + +static void __exit gcc_mdm9607_exit(void) +{ + platform_driver_unregister(&gcc_mdm9607_driver); +} +module_exit(gcc_mdm9607_exit); + +MODULE_DESCRIPTION("Qualcomm GCC mdm9607 Driver"); +MODULE_LICENSE("GPL v2"); diff --git a/drivers/clk/qcom/gcc-msm8974.c b/drivers/clk/qcom/gcc-msm8974.c index 740d3c44c04b..bf305fa9e522 100644 --- a/drivers/clk/qcom/gcc-msm8974.c +++ b/drivers/clk/qcom/gcc-msm8974.c @@ -719,6 +719,12 @@ static struct clk_rcg2 blsp2_uart6_apps_clk_src = { }, }; +static const struct freq_tbl ftbl_gcc_ce1_clk_msm8226[] = { + F(50000000, P_GPLL0, 12, 0, 0), + F(100000000, P_GPLL0, 6, 0, 0), + { } +}; + static const struct freq_tbl ftbl_gcc_ce1_clk[] = { F(50000000, P_GPLL0, 12, 0, 0), F(75000000, P_GPLL0, 8, 0, 0), @@ -761,6 +767,11 @@ static struct clk_rcg2 ce2_clk_src = { }, }; +static const struct freq_tbl ftbl_gcc_gp_clk_msm8226[] = { + F(19200000, P_XO, 1, 0, 0), + { } +}; + static const struct freq_tbl ftbl_gcc_gp_clk[] = { F(4800000, P_XO, 4, 0, 0), F(6000000, P_GPLL0, 10, 1, 10), @@ -1955,6 +1966,10 @@ static struct clk_branch gcc_mss_q6_bimc_axi_clk = { .enable_mask = BIT(0), .hw.init = &(struct clk_init_data){ .name = "gcc_mss_q6_bimc_axi_clk", + .parent_names = (const char *[]){ + "system_noc_clk_src", + }, + .num_parents = 1, .ops = &clk_branch2_ops, }, }, @@ -1993,6 +2008,20 @@ static struct clk_branch gcc_pdm_ahb_clk = { }, }; +static struct clk_branch gcc_pdm_xo4_clk = { + .halt_reg = 0x0cc8, + .clkr = { + .enable_reg = 0x0cc8, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_pdm_xo4_clk", + .parent_names = (const char *[]){ "xo" }, + .num_parents = 1, + .ops = &clk_branch2_ops, + }, + }, +}; + static struct clk_branch gcc_prng_ahb_clk = { .halt_reg = 0x0d04, .halt_check = BRANCH_HALT_VOTED, @@ -2430,6 +2459,121 @@ static struct gdsc usb_hs_hsic_gdsc = { .pwrsts = PWRSTS_OFF_ON, }; +static struct clk_regmap *gcc_msm8226_clocks[] = { + [GPLL0] = &gpll0.clkr, + [GPLL0_VOTE] = &gpll0_vote, + [GPLL1] = &gpll1.clkr, + [GPLL1_VOTE] = &gpll1_vote, + [CONFIG_NOC_CLK_SRC] = &config_noc_clk_src.clkr, + [PERIPH_NOC_CLK_SRC] = &periph_noc_clk_src.clkr, + [SYSTEM_NOC_CLK_SRC] = &system_noc_clk_src.clkr, + [BLSP1_QUP1_I2C_APPS_CLK_SRC] = &blsp1_qup1_i2c_apps_clk_src.clkr, + [BLSP1_QUP1_SPI_APPS_CLK_SRC] = &blsp1_qup1_spi_apps_clk_src.clkr, + [BLSP1_QUP2_I2C_APPS_CLK_SRC] = &blsp1_qup2_i2c_apps_clk_src.clkr, + [BLSP1_QUP2_SPI_APPS_CLK_SRC] = &blsp1_qup2_spi_apps_clk_src.clkr, + [BLSP1_QUP3_I2C_APPS_CLK_SRC] = &blsp1_qup3_i2c_apps_clk_src.clkr, + [BLSP1_QUP3_SPI_APPS_CLK_SRC] = &blsp1_qup3_spi_apps_clk_src.clkr, + [BLSP1_QUP4_I2C_APPS_CLK_SRC] = &blsp1_qup4_i2c_apps_clk_src.clkr, + [BLSP1_QUP4_SPI_APPS_CLK_SRC] = &blsp1_qup4_spi_apps_clk_src.clkr, + [BLSP1_QUP5_I2C_APPS_CLK_SRC] = &blsp1_qup5_i2c_apps_clk_src.clkr, + [BLSP1_QUP5_SPI_APPS_CLK_SRC] = &blsp1_qup5_spi_apps_clk_src.clkr, + [BLSP1_QUP6_I2C_APPS_CLK_SRC] = &blsp1_qup6_i2c_apps_clk_src.clkr, + [BLSP1_QUP6_SPI_APPS_CLK_SRC] = &blsp1_qup6_spi_apps_clk_src.clkr, + [BLSP1_UART1_APPS_CLK_SRC] = &blsp1_uart1_apps_clk_src.clkr, + [BLSP1_UART2_APPS_CLK_SRC] = &blsp1_uart2_apps_clk_src.clkr, + [BLSP1_UART3_APPS_CLK_SRC] = &blsp1_uart3_apps_clk_src.clkr, + [BLSP1_UART4_APPS_CLK_SRC] = &blsp1_uart4_apps_clk_src.clkr, + [BLSP1_UART5_APPS_CLK_SRC] = &blsp1_uart5_apps_clk_src.clkr, + [BLSP1_UART6_APPS_CLK_SRC] = &blsp1_uart6_apps_clk_src.clkr, + [CE1_CLK_SRC] = &ce1_clk_src.clkr, + [GP1_CLK_SRC] = &gp1_clk_src.clkr, + [GP2_CLK_SRC] = &gp2_clk_src.clkr, + [GP3_CLK_SRC] = &gp3_clk_src.clkr, + [PDM2_CLK_SRC] = &pdm2_clk_src.clkr, + [SDCC1_APPS_CLK_SRC] = &sdcc1_apps_clk_src.clkr, + [SDCC2_APPS_CLK_SRC] = &sdcc2_apps_clk_src.clkr, + [SDCC3_APPS_CLK_SRC] = &sdcc3_apps_clk_src.clkr, + [USB_HS_SYSTEM_CLK_SRC] = &usb_hs_system_clk_src.clkr, + [USB_HSIC_CLK_SRC] = &usb_hsic_clk_src.clkr, + [USB_HSIC_IO_CAL_CLK_SRC] = &usb_hsic_io_cal_clk_src.clkr, + [USB_HSIC_SYSTEM_CLK_SRC] = &usb_hsic_system_clk_src.clkr, + [GCC_BAM_DMA_AHB_CLK] = &gcc_bam_dma_ahb_clk.clkr, + [GCC_BLSP1_AHB_CLK] = &gcc_blsp1_ahb_clk.clkr, + [GCC_BLSP1_QUP1_I2C_APPS_CLK] = &gcc_blsp1_qup1_i2c_apps_clk.clkr, + [GCC_BLSP1_QUP1_SPI_APPS_CLK] = &gcc_blsp1_qup1_spi_apps_clk.clkr, + [GCC_BLSP1_QUP2_I2C_APPS_CLK] = &gcc_blsp1_qup2_i2c_apps_clk.clkr, + [GCC_BLSP1_QUP2_SPI_APPS_CLK] = &gcc_blsp1_qup2_spi_apps_clk.clkr, + [GCC_BLSP1_QUP3_I2C_APPS_CLK] = &gcc_blsp1_qup3_i2c_apps_clk.clkr, + [GCC_BLSP1_QUP3_SPI_APPS_CLK] = &gcc_blsp1_qup3_spi_apps_clk.clkr, + [GCC_BLSP1_QUP4_I2C_APPS_CLK] = &gcc_blsp1_qup4_i2c_apps_clk.clkr, + [GCC_BLSP1_QUP4_SPI_APPS_CLK] = &gcc_blsp1_qup4_spi_apps_clk.clkr, + [GCC_BLSP1_QUP5_I2C_APPS_CLK] = &gcc_blsp1_qup5_i2c_apps_clk.clkr, + [GCC_BLSP1_QUP5_SPI_APPS_CLK] = &gcc_blsp1_qup5_spi_apps_clk.clkr, + [GCC_BLSP1_QUP6_I2C_APPS_CLK] = &gcc_blsp1_qup6_i2c_apps_clk.clkr, + [GCC_BLSP1_QUP6_SPI_APPS_CLK] = &gcc_blsp1_qup6_spi_apps_clk.clkr, + [GCC_BLSP1_UART1_APPS_CLK] = &gcc_blsp1_uart1_apps_clk.clkr, + [GCC_BLSP1_UART2_APPS_CLK] = &gcc_blsp1_uart2_apps_clk.clkr, + [GCC_BLSP1_UART3_APPS_CLK] = &gcc_blsp1_uart3_apps_clk.clkr, + [GCC_BLSP1_UART4_APPS_CLK] = &gcc_blsp1_uart4_apps_clk.clkr, + [GCC_BLSP1_UART5_APPS_CLK] = &gcc_blsp1_uart5_apps_clk.clkr, + [GCC_BLSP1_UART6_APPS_CLK] = &gcc_blsp1_uart6_apps_clk.clkr, + [GCC_BOOT_ROM_AHB_CLK] = &gcc_boot_rom_ahb_clk.clkr, + [GCC_CE1_AHB_CLK] = &gcc_ce1_ahb_clk.clkr, + [GCC_CE1_AXI_CLK] = &gcc_ce1_axi_clk.clkr, + [GCC_CE1_CLK] = &gcc_ce1_clk.clkr, + [GCC_GP1_CLK] = &gcc_gp1_clk.clkr, + [GCC_GP2_CLK] = &gcc_gp2_clk.clkr, + [GCC_GP3_CLK] = &gcc_gp3_clk.clkr, + [GCC_LPASS_Q6_AXI_CLK] = &gcc_lpass_q6_axi_clk.clkr, + [GCC_MSS_CFG_AHB_CLK] = &gcc_mss_cfg_ahb_clk.clkr, + [GCC_MSS_Q6_BIMC_AXI_CLK] = &gcc_mss_q6_bimc_axi_clk.clkr, + [GCC_PDM2_CLK] = &gcc_pdm2_clk.clkr, + [GCC_PDM_AHB_CLK] = &gcc_pdm_ahb_clk.clkr, + [GCC_PDM_XO4_CLK] = &gcc_pdm_xo4_clk.clkr, + [GCC_PRNG_AHB_CLK] = &gcc_prng_ahb_clk.clkr, + [GCC_SDCC1_AHB_CLK] = &gcc_sdcc1_ahb_clk.clkr, + [GCC_SDCC1_APPS_CLK] = &gcc_sdcc1_apps_clk.clkr, + [GCC_SDCC2_AHB_CLK] = &gcc_sdcc2_ahb_clk.clkr, + [GCC_SDCC2_APPS_CLK] = &gcc_sdcc2_apps_clk.clkr, + [GCC_SDCC3_AHB_CLK] = &gcc_sdcc3_ahb_clk.clkr, + [GCC_SDCC3_APPS_CLK] = &gcc_sdcc3_apps_clk.clkr, + [GCC_USB2A_PHY_SLEEP_CLK] = &gcc_usb2a_phy_sleep_clk.clkr, + [GCC_USB_HS_AHB_CLK] = &gcc_usb_hs_ahb_clk.clkr, + [GCC_USB_HS_SYSTEM_CLK] = &gcc_usb_hs_system_clk.clkr, + [GCC_USB_HSIC_AHB_CLK] = &gcc_usb_hsic_ahb_clk.clkr, + [GCC_USB_HSIC_CLK] = &gcc_usb_hsic_clk.clkr, + [GCC_USB_HSIC_IO_CAL_CLK] = &gcc_usb_hsic_io_cal_clk.clkr, + [GCC_USB_HSIC_SYSTEM_CLK] = &gcc_usb_hsic_system_clk.clkr, +}; + +static const struct qcom_reset_map gcc_msm8226_resets[] = { + [GCC_USB_HS_HSIC_BCR] = { 0x0400 }, + [GCC_USB_HS_BCR] = { 0x0480 }, + [GCC_USB2A_PHY_BCR] = { 0x04a8 }, +}; + +static struct gdsc *gcc_msm8226_gdscs[] = { + [USB_HS_HSIC_GDSC] = &usb_hs_hsic_gdsc, +}; + +static const struct regmap_config gcc_msm8226_regmap_config = { + .reg_bits = 32, + .reg_stride = 4, + .val_bits = 32, + .max_register = 0x1a80, + .fast_io = true, +}; + +static const struct qcom_cc_desc gcc_msm8226_desc = { + .config = &gcc_msm8226_regmap_config, + .clks = gcc_msm8226_clocks, + .num_clks = ARRAY_SIZE(gcc_msm8226_clocks), + .resets = gcc_msm8226_resets, + .num_resets = ARRAY_SIZE(gcc_msm8226_resets), + .gdscs = gcc_msm8226_gdscs, + .num_gdscs = ARRAY_SIZE(gcc_msm8226_gdscs), +}; + static struct clk_regmap *gcc_msm8974_clocks[] = { [GPLL0] = &gpll0.clkr, [GPLL0_VOTE] = &gpll0_vote, @@ -2682,13 +2826,22 @@ static const struct qcom_cc_desc gcc_msm8974_desc = { }; static const struct of_device_id gcc_msm8974_match_table[] = { - { .compatible = "qcom,gcc-msm8974" }, - { .compatible = "qcom,gcc-msm8974pro" , .data = (void *)1UL }, - { .compatible = "qcom,gcc-msm8974pro-ac", .data = (void *)1UL }, + { .compatible = "qcom,gcc-msm8226", .data = &gcc_msm8226_desc }, + { .compatible = "qcom,gcc-msm8974", .data = &gcc_msm8974_desc }, + { .compatible = "qcom,gcc-msm8974pro", .data = &gcc_msm8974_desc }, + { .compatible = "qcom,gcc-msm8974pro-ac", .data = &gcc_msm8974_desc }, { } }; MODULE_DEVICE_TABLE(of, gcc_msm8974_match_table); +static void msm8226_clock_override(void) +{ + ce1_clk_src.freq_tbl = ftbl_gcc_ce1_clk_msm8226; + gp1_clk_src.freq_tbl = ftbl_gcc_gp_clk_msm8226; + gp2_clk_src.freq_tbl = ftbl_gcc_gp_clk_msm8226; + gp3_clk_src.freq_tbl = ftbl_gcc_gp_clk_msm8226; +} + static void msm8974_pro_clock_override(void) { sdcc1_apps_clk_src_init.parent_names = gcc_xo_gpll0_gpll4; @@ -2708,16 +2861,18 @@ static int gcc_msm8974_probe(struct platform_device *pdev) { int ret; struct device *dev = &pdev->dev; - bool pro; const struct of_device_id *id; id = of_match_device(gcc_msm8974_match_table, dev); if (!id) return -ENODEV; - pro = !!(id->data); - if (pro) - msm8974_pro_clock_override(); + if (!of_device_is_compatible(dev->of_node, "qcom,gcc-msm8974")) { + if (id->data == &gcc_msm8226_desc) + msm8226_clock_override(); + else + msm8974_pro_clock_override(); + } ret = qcom_cc_register_board_clk(dev, "xo_board", "xo", 19200000); if (ret) diff --git a/drivers/clk/qcom/gcc-sc7280.c b/drivers/clk/qcom/gcc-sc7280.c index ef734db316df..6cefcdc86990 100644 --- a/drivers/clk/qcom/gcc-sc7280.c +++ b/drivers/clk/qcom/gcc-sc7280.c @@ -716,6 +716,7 @@ static const struct freq_tbl ftbl_gcc_qupv3_wrap0_s2_clk_src[] = { F(29491200, P_GCC_GPLL0_OUT_EVEN, 1, 1536, 15625), F(32000000, P_GCC_GPLL0_OUT_EVEN, 1, 8, 75), F(48000000, P_GCC_GPLL0_OUT_EVEN, 1, 4, 25), + F(52174000, P_GCC_GPLL0_OUT_MAIN, 1, 2, 23), F(64000000, P_GCC_GPLL0_OUT_EVEN, 1, 16, 75), F(75000000, P_GCC_GPLL0_OUT_EVEN, 4, 0, 0), F(80000000, P_GCC_GPLL0_OUT_EVEN, 1, 4, 15), diff --git a/drivers/clk/qcom/gcc-sm6125.c b/drivers/clk/qcom/gcc-sm6125.c new file mode 100644 index 000000000000..543cfab7561f --- /dev/null +++ b/drivers/clk/qcom/gcc-sm6125.c @@ -0,0 +1,4190 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright (c) 2021, Konrad Dybcio <konrad.dybcio@somainline.org> + */ + +#include <linux/kernel.h> +#include <linux/err.h> +#include <linux/module.h> +#include <linux/platform_device.h> +#include <linux/of.h> +#include <linux/of_device.h> +#include <linux/clk-provider.h> +#include <linux/regmap.h> +#include <linux/reset-controller.h> + +#include <dt-bindings/clock/qcom,gcc-sm6125.h> + +#include "clk-alpha-pll.h" +#include "clk-branch.h" +#include "clk-rcg.h" +#include "clk-regmap.h" +#include "common.h" +#include "gdsc.h" +#include "reset.h" + +enum { + P_BI_TCXO, + P_GPLL0_OUT_AUX2, + P_GPLL0_OUT_EARLY, + P_GPLL3_OUT_EARLY, + P_GPLL4_OUT_MAIN, + P_GPLL5_OUT_MAIN, + P_GPLL6_OUT_EARLY, + P_GPLL6_OUT_MAIN, + P_GPLL7_OUT_MAIN, + P_GPLL8_OUT_EARLY, + P_GPLL8_OUT_MAIN, + P_GPLL9_OUT_MAIN, + P_SLEEP_CLK, +}; + +static struct clk_alpha_pll gpll0_out_early = { + .offset = 0x0, + .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_DEFAULT], + .clkr = { + .enable_reg = 0x79000, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gpll0_out_early", + .parent_data = &(const struct clk_parent_data){ + .fw_name = "bi_tcxo", + }, + .num_parents = 1, + .ops = &clk_alpha_pll_ops, + }, + }, +}; + +static struct clk_fixed_factor gpll0_out_aux2 = { + .mult = 1, + .div = 2, + .hw.init = &(struct clk_init_data){ + .name = "gpll0_out_aux2", + .parent_hws = (const struct clk_hw*[]){ + &gpll0_out_early.clkr.hw, + }, + .num_parents = 1, + .ops = &clk_fixed_factor_ops, + }, +}; + +static struct clk_fixed_factor gpll0_out_main = { + .mult = 1, + .div = 2, + .hw.init = &(struct clk_init_data){ + .name = "gpll0_out_main", + .parent_hws = (const struct clk_hw*[]){ + &gpll0_out_early.clkr.hw, + }, + .num_parents = 1, + .ops = &clk_fixed_factor_ops, + }, +}; + +static struct clk_alpha_pll gpll3_out_early = { + .offset = 0x3000, + .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_DEFAULT], + .clkr = { + .enable_reg = 0x79000, + .enable_mask = BIT(3), + .hw.init = &(struct clk_init_data){ + .name = "gpll3_out_early", + .parent_data = &(const struct clk_parent_data){ + .fw_name = "bi_tcxo", + }, + .num_parents = 1, + .ops = &clk_alpha_pll_ops, + }, + }, +}; + +static struct clk_alpha_pll gpll4_out_main = { + .offset = 0x4000, + .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_DEFAULT], + .clkr = { + .enable_reg = 0x79000, + .enable_mask = BIT(4), + .hw.init = &(struct clk_init_data){ + .name = "gpll4_out_main", + .parent_data = &(const struct clk_parent_data){ + .fw_name = "bi_tcxo", + }, + .num_parents = 1, + .ops = &clk_alpha_pll_ops, + }, + }, +}; + +static struct clk_alpha_pll gpll5_out_main = { + .offset = 0x5000, + .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_DEFAULT], + .clkr = { + .enable_reg = 0x79000, + .enable_mask = BIT(5), + .hw.init = &(struct clk_init_data){ + .name = "gpll5_out_main", + .parent_data = &(const struct clk_parent_data){ + .fw_name = "bi_tcxo", + }, + .num_parents = 1, + .ops = &clk_alpha_pll_ops, + }, + }, +}; + +static struct clk_alpha_pll gpll6_out_early = { + .offset = 0x6000, + .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_DEFAULT], + .clkr = { + .enable_reg = 0x79000, + .enable_mask = BIT(6), + .hw.init = &(struct clk_init_data){ + .name = "gpll6_out_early", + .parent_data = &(const struct clk_parent_data){ + .fw_name = "bi_tcxo", + }, + .num_parents = 1, + .ops = &clk_alpha_pll_ops, + }, + }, +}; + +static struct clk_fixed_factor gpll6_out_main = { + .mult = 1, + .div = 2, + .hw.init = &(struct clk_init_data){ + .name = "gpll6_out_main", + .parent_hws = (const struct clk_hw*[]){ + &gpll6_out_early.clkr.hw, + }, + .num_parents = 1, + .ops = &clk_fixed_factor_ops, + }, +}; + +static struct clk_alpha_pll gpll7_out_early = { + .offset = 0x7000, + .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_DEFAULT], + .clkr = { + .enable_reg = 0x79000, + .enable_mask = BIT(7), + .hw.init = &(struct clk_init_data){ + .name = "gpll7_out_early", + .parent_data = &(const struct clk_parent_data){ + .fw_name = "bi_tcxo", + }, + .num_parents = 1, + .ops = &clk_alpha_pll_ops, + }, + }, +}; + +static struct clk_fixed_factor gpll7_out_main = { + .mult = 1, + .div = 2, + .hw.init = &(struct clk_init_data){ + .name = "gpll7_out_main", + .parent_hws = (const struct clk_hw*[]){ + &gpll7_out_early.clkr.hw, + }, + .num_parents = 1, + .ops = &clk_fixed_factor_ops, + }, +}; + +static struct clk_alpha_pll gpll8_out_early = { + .offset = 0x8000, + .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_DEFAULT], + .clkr = { + .enable_reg = 0x79000, + .enable_mask = BIT(8), + .hw.init = &(struct clk_init_data){ + .name = "gpll8_out_early", + .parent_data = &(const struct clk_parent_data){ + .fw_name = "bi_tcxo", + }, + .num_parents = 1, + .ops = &clk_alpha_pll_ops, + }, + }, +}; + +static struct clk_fixed_factor gpll8_out_main = { + .mult = 1, + .div = 2, + .hw.init = &(struct clk_init_data){ + .name = "gpll8_out_main", + .parent_hws = (const struct clk_hw*[]){ + &gpll8_out_early.clkr.hw, + }, + .num_parents = 1, + .ops = &clk_fixed_factor_ops, + }, +}; + +static struct clk_alpha_pll gpll9_out_early = { + .offset = 0x9000, + .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_DEFAULT], + .clkr = { + .enable_reg = 0x79000, + .enable_mask = BIT(9), + .hw.init = &(struct clk_init_data){ + .name = "gpll9_out_early", + .parent_data = &(const struct clk_parent_data){ + .fw_name = "bi_tcxo", + }, + .num_parents = 1, + .ops = &clk_alpha_pll_ops, + }, + }, +}; + +static struct clk_fixed_factor gpll9_out_main = { + .mult = 1, + .div = 2, + .hw.init = &(struct clk_init_data){ + .name = "gpll9_out_main", + .parent_hws = (const struct clk_hw*[]){ + &gpll9_out_early.clkr.hw, + }, + .num_parents = 1, + .ops = &clk_fixed_factor_ops, + }, +}; + +static const struct parent_map gcc_parent_map_0[] = { + { P_BI_TCXO, 0 }, + { P_GPLL0_OUT_EARLY, 1 }, + { P_GPLL0_OUT_AUX2, 2 }, +}; + +static const struct clk_parent_data gcc_parent_data_0[] = { + { .fw_name = "bi_tcxo" }, + { .hw = &gpll0_out_early.clkr.hw }, + { .hw = &gpll0_out_aux2.hw }, +}; + +static const struct parent_map gcc_parent_map_1[] = { + { P_BI_TCXO, 0 }, + { P_GPLL0_OUT_EARLY, 1 }, + { P_GPLL0_OUT_AUX2, 2 }, + { P_GPLL6_OUT_MAIN, 4 }, +}; + +static const struct clk_parent_data gcc_parent_data_1[] = { + { .fw_name = "bi_tcxo" }, + { .hw = &gpll0_out_early.clkr.hw }, + { .hw = &gpll0_out_aux2.hw }, + { .hw = &gpll6_out_main.hw }, +}; + +static const struct parent_map gcc_parent_map_2[] = { + { P_BI_TCXO, 0 }, + { P_GPLL0_OUT_EARLY, 1 }, + { P_GPLL0_OUT_AUX2, 2 }, + { P_SLEEP_CLK, 5 }, +}; + +static const struct clk_parent_data gcc_parent_data_2[] = { + { .fw_name = "bi_tcxo" }, + { .hw = &gpll0_out_early.clkr.hw }, + { .hw = &gpll0_out_aux2.hw }, + { .fw_name = "sleep_clk" }, +}; + +static const struct parent_map gcc_parent_map_3[] = { + { P_BI_TCXO, 0 }, + { P_GPLL0_OUT_EARLY, 1 }, + { P_GPLL5_OUT_MAIN, 3 }, + { P_GPLL4_OUT_MAIN, 5 }, +}; + +static const struct clk_parent_data gcc_parent_data_3[] = { + { .fw_name = "bi_tcxo" }, + { .hw = &gpll0_out_early.clkr.hw }, + { .hw = &gpll5_out_main.clkr.hw }, + { .hw = &gpll4_out_main.clkr.hw }, +}; + +static const struct parent_map gcc_parent_map_4[] = { + { P_BI_TCXO, 0 }, + { P_GPLL0_OUT_EARLY, 1 }, + { P_GPLL9_OUT_MAIN, 2 }, +}; + +static const struct clk_parent_data gcc_parent_data_4[] = { + { .fw_name = "bi_tcxo" }, + { .hw = &gpll0_out_early.clkr.hw }, + { .hw = &gpll9_out_main.hw }, +}; + +static const struct parent_map gcc_parent_map_5[] = { + { P_BI_TCXO, 0 }, + { P_GPLL0_OUT_EARLY, 1 }, +}; + +static const struct clk_parent_data gcc_parent_data_5[] = { + { .fw_name = "bi_tcxo" }, + { .hw = &gpll0_out_early.clkr.hw }, +}; + +static const struct parent_map gcc_parent_map_6[] = { + { P_BI_TCXO, 0 }, + { P_GPLL0_OUT_EARLY, 1 }, + { P_GPLL4_OUT_MAIN, 5 }, +}; + +static const struct clk_parent_data gcc_parent_data_6[] = { + { .fw_name = "bi_tcxo" }, + { .hw = &gpll0_out_early.clkr.hw }, + { .hw = &gpll4_out_main.clkr.hw }, +}; + +static const struct parent_map gcc_parent_map_7[] = { + { P_BI_TCXO, 0 }, + { P_GPLL0_OUT_EARLY, 1 }, + { P_SLEEP_CLK, 5 }, +}; + +static const struct clk_parent_data gcc_parent_data_7[] = { + { .fw_name = "bi_tcxo" }, + { .hw = &gpll0_out_early.clkr.hw }, + { .fw_name = "sleep_clk" }, +}; + +static const struct parent_map gcc_parent_map_8[] = { + { P_BI_TCXO, 0 }, + { P_GPLL0_OUT_EARLY, 1 }, + { P_GPLL9_OUT_MAIN, 2 }, + { P_GPLL6_OUT_EARLY, 3 }, + { P_GPLL8_OUT_MAIN, 4 }, + { P_GPLL4_OUT_MAIN, 5 }, + { P_GPLL3_OUT_EARLY, 6 }, +}; + +static const struct clk_parent_data gcc_parent_data_8[] = { + { .fw_name = "bi_tcxo" }, + { .hw = &gpll0_out_early.clkr.hw }, + { .hw = &gpll9_out_main.hw }, + { .hw = &gpll6_out_early.clkr.hw }, + { .hw = &gpll8_out_main.hw }, + { .hw = &gpll4_out_main.clkr.hw }, + { .hw = &gpll3_out_early.clkr.hw }, +}; + +static const struct parent_map gcc_parent_map_9[] = { + { P_BI_TCXO, 0 }, + { P_GPLL0_OUT_EARLY, 1 }, + { P_GPLL8_OUT_MAIN, 4 }, +}; + +static const struct clk_parent_data gcc_parent_data_9[] = { + { .fw_name = "bi_tcxo" }, + { .hw = &gpll0_out_early.clkr.hw }, + { .hw = &gpll8_out_main.hw }, +}; + +static const struct parent_map gcc_parent_map_10[] = { + { P_BI_TCXO, 0 }, + { P_GPLL0_OUT_EARLY, 1 }, + { P_GPLL9_OUT_MAIN, 2 }, + { P_GPLL6_OUT_EARLY, 3 }, + { P_GPLL8_OUT_MAIN, 4 }, + { P_GPLL3_OUT_EARLY, 6 }, +}; + +static const struct clk_parent_data gcc_parent_data_10[] = { + { .fw_name = "bi_tcxo" }, + { .hw = &gpll0_out_early.clkr.hw }, + { .hw = &gpll9_out_main.hw }, + { .hw = &gpll6_out_early.clkr.hw }, + { .hw = &gpll8_out_main.hw }, + { .hw = &gpll3_out_early.clkr.hw }, +}; + +static const struct parent_map gcc_parent_map_11[] = { + { P_BI_TCXO, 0 }, + { P_GPLL0_OUT_EARLY, 1 }, + { P_GPLL8_OUT_EARLY, 4 }, + { P_GPLL4_OUT_MAIN, 5 }, +}; + +static const struct clk_parent_data gcc_parent_data_11[] = { + { .fw_name = "bi_tcxo" }, + { .hw = &gpll0_out_early.clkr.hw }, + { .hw = &gpll8_out_early.clkr.hw }, + { .hw = &gpll4_out_main.clkr.hw }, +}; + +static const struct parent_map gcc_parent_map_12[] = { + { P_BI_TCXO, 0 }, + { P_GPLL0_OUT_EARLY, 1 }, + { P_GPLL6_OUT_EARLY, 3 }, + { P_GPLL8_OUT_EARLY, 4 }, +}; + +static const struct clk_parent_data gcc_parent_data_12[] = { + { .fw_name = "bi_tcxo" }, + { .hw = &gpll0_out_early.clkr.hw }, + { .hw = &gpll6_out_early.clkr.hw }, + { .hw = &gpll8_out_early.clkr.hw }, +}; + +static const struct parent_map gcc_parent_map_13[] = { + { P_BI_TCXO, 0 }, + { P_GPLL0_OUT_EARLY, 1 }, + { P_GPLL0_OUT_AUX2, 2 }, + { P_GPLL7_OUT_MAIN, 3 }, + { P_GPLL4_OUT_MAIN, 5 }, +}; + +static const struct clk_parent_data gcc_parent_data_13[] = { + { .fw_name = "bi_tcxo" }, + { .hw = &gpll0_out_early.clkr.hw }, + { .hw = &gpll0_out_aux2.hw }, + { .hw = &gpll7_out_main.hw }, + { .hw = &gpll4_out_main.clkr.hw }, +}; + +static const struct parent_map gcc_parent_map_14[] = { + { P_BI_TCXO, 0 }, + { P_SLEEP_CLK, 5 }, +}; + +static const struct clk_parent_data gcc_parent_data_14[] = { + { .fw_name = "bi_tcxo" }, + { .fw_name = "sleep_clk" }, +}; + +static const struct freq_tbl ftbl_gcc_camss_ahb_clk_src[] = { + F(19200000, P_BI_TCXO, 1, 0, 0), + F(40000000, P_GPLL8_OUT_MAIN, 12, 0, 0), + F(80000000, P_GPLL8_OUT_MAIN, 6, 0, 0), + { } +}; + +static struct clk_rcg2 gcc_camss_ahb_clk_src = { + .cmd_rcgr = 0x56088, + .mnd_width = 0, + .hid_width = 5, + .parent_map = gcc_parent_map_9, + .freq_tbl = ftbl_gcc_camss_ahb_clk_src, + .clkr.hw.init = &(struct clk_init_data){ + .name = "gcc_camss_ahb_clk_src", + .parent_data = gcc_parent_data_9, + .num_parents = ARRAY_SIZE(gcc_parent_data_9), + .ops = &clk_rcg2_ops, + }, +}; + +static const struct freq_tbl ftbl_gcc_camss_cci_clk_src[] = { + F(37500000, P_GPLL0_OUT_EARLY, 16, 0, 0), + F(50000000, P_GPLL0_OUT_EARLY, 12, 0, 0), + F(100000000, P_GPLL0_OUT_EARLY, 6, 0, 0), + { } +}; + +static struct clk_rcg2 gcc_camss_cci_clk_src = { + .cmd_rcgr = 0x52004, + .mnd_width = 8, + .hid_width = 5, + .parent_map = gcc_parent_map_5, + .freq_tbl = ftbl_gcc_camss_cci_clk_src, + .clkr.hw.init = &(struct clk_init_data){ + .name = "gcc_camss_cci_clk_src", + .parent_data = gcc_parent_data_5, + .num_parents = ARRAY_SIZE(gcc_parent_data_5), + .ops = &clk_rcg2_ops, + }, +}; + +static const struct freq_tbl ftbl_gcc_camss_cpp_clk_src[] = { + F(120000000, P_GPLL8_OUT_MAIN, 4, 0, 0), + F(240000000, P_GPLL8_OUT_MAIN, 2, 0, 0), + F(320000000, P_GPLL8_OUT_MAIN, 1.5, 0, 0), + F(480000000, P_GPLL8_OUT_MAIN, 1, 0, 0), + F(576000000, P_GPLL9_OUT_MAIN, 1, 0, 0), + { } +}; + +static struct clk_rcg2 gcc_camss_cpp_clk_src = { + .cmd_rcgr = 0x560c8, + .mnd_width = 0, + .hid_width = 5, + .parent_map = gcc_parent_map_10, + .freq_tbl = ftbl_gcc_camss_cpp_clk_src, + .clkr.hw.init = &(struct clk_init_data){ + .name = "gcc_camss_cpp_clk_src", + .parent_data = gcc_parent_data_10, + .num_parents = ARRAY_SIZE(gcc_parent_data_10), + .ops = &clk_rcg2_ops, + }, +}; + +static const struct freq_tbl ftbl_gcc_camss_csi0_clk_src[] = { + F(100000000, P_GPLL0_OUT_EARLY, 6, 0, 0), + F(200000000, P_GPLL0_OUT_EARLY, 3, 0, 0), + F(311000000, P_GPLL5_OUT_MAIN, 3, 0, 0), + F(403200000, P_GPLL4_OUT_MAIN, 2, 0, 0), + F(466500000, P_GPLL5_OUT_MAIN, 2, 0, 0), + { } +}; + +static struct clk_rcg2 gcc_camss_csi0_clk_src = { + .cmd_rcgr = 0x55030, + .mnd_width = 0, + .hid_width = 5, + .parent_map = gcc_parent_map_3, + .freq_tbl = ftbl_gcc_camss_csi0_clk_src, + .clkr.hw.init = &(struct clk_init_data){ + .name = "gcc_camss_csi0_clk_src", + .parent_data = gcc_parent_data_3, + .num_parents = ARRAY_SIZE(gcc_parent_data_3), + .ops = &clk_rcg2_ops, + }, +}; + +static const struct freq_tbl ftbl_gcc_camss_csi0phytimer_clk_src[] = { + F(100000000, P_GPLL0_OUT_EARLY, 6, 0, 0), + F(200000000, P_GPLL0_OUT_EARLY, 3, 0, 0), + F(268800000, P_GPLL4_OUT_MAIN, 3, 0, 0), + { } +}; + +static struct clk_rcg2 gcc_camss_csi0phytimer_clk_src = { + .cmd_rcgr = 0x53004, + .mnd_width = 0, + .hid_width = 5, + .parent_map = gcc_parent_map_6, + .freq_tbl = ftbl_gcc_camss_csi0phytimer_clk_src, + .clkr.hw.init = &(struct clk_init_data){ + .name = "gcc_camss_csi0phytimer_clk_src", + .parent_data = gcc_parent_data_6, + .num_parents = ARRAY_SIZE(gcc_parent_data_6), + .ops = &clk_rcg2_ops, + }, +}; + +static struct clk_rcg2 gcc_camss_csi1_clk_src = { + .cmd_rcgr = 0x5506c, + .mnd_width = 0, + .hid_width = 5, + .parent_map = gcc_parent_map_3, + .freq_tbl = ftbl_gcc_camss_csi0_clk_src, + .clkr.hw.init = &(struct clk_init_data){ + .name = "gcc_camss_csi1_clk_src", + .parent_data = gcc_parent_data_3, + .num_parents = ARRAY_SIZE(gcc_parent_data_3), + .ops = &clk_rcg2_ops, + }, +}; + +static struct clk_rcg2 gcc_camss_csi1phytimer_clk_src = { + .cmd_rcgr = 0x53024, + .mnd_width = 0, + .hid_width = 5, + .parent_map = gcc_parent_map_6, + .freq_tbl = ftbl_gcc_camss_csi0phytimer_clk_src, + .clkr.hw.init = &(struct clk_init_data){ + .name = "gcc_camss_csi1phytimer_clk_src", + .parent_data = gcc_parent_data_6, + .num_parents = ARRAY_SIZE(gcc_parent_data_6), + .ops = &clk_rcg2_ops, + }, +}; + +static struct clk_rcg2 gcc_camss_csi2_clk_src = { + .cmd_rcgr = 0x550a4, + .mnd_width = 0, + .hid_width = 5, + .parent_map = gcc_parent_map_3, + .freq_tbl = ftbl_gcc_camss_csi0_clk_src, + .clkr.hw.init = &(struct clk_init_data){ + .name = "gcc_camss_csi2_clk_src", + .parent_data = gcc_parent_data_3, + .num_parents = ARRAY_SIZE(gcc_parent_data_3), + .ops = &clk_rcg2_ops, + }, +}; + +static struct clk_rcg2 gcc_camss_csi2phytimer_clk_src = { + .cmd_rcgr = 0x53044, + .mnd_width = 0, + .hid_width = 5, + .parent_map = gcc_parent_map_6, + .freq_tbl = ftbl_gcc_camss_csi0phytimer_clk_src, + .clkr.hw.init = &(struct clk_init_data){ + .name = "gcc_camss_csi2phytimer_clk_src", + .parent_data = gcc_parent_data_6, + .num_parents = ARRAY_SIZE(gcc_parent_data_6), + .ops = &clk_rcg2_ops, + }, +}; + +static struct clk_rcg2 gcc_camss_csi3_clk_src = { + .cmd_rcgr = 0x550e0, + .mnd_width = 0, + .hid_width = 5, + .parent_map = gcc_parent_map_3, + .freq_tbl = ftbl_gcc_camss_csi0_clk_src, + .clkr.hw.init = &(struct clk_init_data){ + .name = "gcc_camss_csi3_clk_src", + .parent_data = gcc_parent_data_3, + .num_parents = ARRAY_SIZE(gcc_parent_data_3), + .ops = &clk_rcg2_ops, + }, +}; + +static const struct freq_tbl ftbl_gcc_camss_csiphy_clk_src[] = { + F(100000000, P_GPLL0_OUT_EARLY, 6, 0, 0), + F(200000000, P_GPLL0_OUT_EARLY, 3, 0, 0), + F(268800000, P_GPLL4_OUT_MAIN, 3, 0, 0), + F(320000000, P_GPLL8_OUT_EARLY, 3, 0, 0), + { } +}; + +static struct clk_rcg2 gcc_camss_csiphy_clk_src = { + .cmd_rcgr = 0x55000, + .mnd_width = 0, + .hid_width = 5, + .parent_map = gcc_parent_map_11, + .freq_tbl = ftbl_gcc_camss_csiphy_clk_src, + .clkr.hw.init = &(struct clk_init_data){ + .name = "gcc_camss_csiphy_clk_src", + .parent_data = gcc_parent_data_11, + .num_parents = ARRAY_SIZE(gcc_parent_data_11), + .ops = &clk_rcg2_ops, + }, +}; + +static const struct freq_tbl ftbl_gcc_camss_gp0_clk_src[] = { + F(50000000, P_GPLL0_OUT_EARLY, 12, 0, 0), + F(100000000, P_GPLL0_OUT_EARLY, 6, 0, 0), + F(200000000, P_GPLL0_OUT_EARLY, 3, 0, 0), + { } +}; + +static struct clk_rcg2 gcc_camss_gp0_clk_src = { + .cmd_rcgr = 0x50000, + .mnd_width = 8, + .hid_width = 5, + .parent_map = gcc_parent_map_7, + .freq_tbl = ftbl_gcc_camss_gp0_clk_src, + .clkr.hw.init = &(struct clk_init_data){ + .name = "gcc_camss_gp0_clk_src", + .parent_data = gcc_parent_data_7, + .num_parents = ARRAY_SIZE(gcc_parent_data_7), + .ops = &clk_rcg2_ops, + }, +}; + +static struct clk_rcg2 gcc_camss_gp1_clk_src = { + .cmd_rcgr = 0x5001c, + .mnd_width = 8, + .hid_width = 5, + .parent_map = gcc_parent_map_7, + .freq_tbl = ftbl_gcc_camss_gp0_clk_src, + .clkr.hw.init = &(struct clk_init_data){ + .name = "gcc_camss_gp1_clk_src", + .parent_data = gcc_parent_data_7, + .num_parents = ARRAY_SIZE(gcc_parent_data_7), + .ops = &clk_rcg2_ops, + }, +}; + +static const struct freq_tbl ftbl_gcc_camss_jpeg_clk_src[] = { + F(66666667, P_GPLL0_OUT_EARLY, 9, 0, 0), + F(133333333, P_GPLL0_OUT_EARLY, 4.5, 0, 0), + F(219428571, P_GPLL6_OUT_EARLY, 3.5, 0, 0), + F(320000000, P_GPLL8_OUT_EARLY, 3, 0, 0), + F(480000000, P_GPLL8_OUT_EARLY, 2, 0, 0), + { } +}; + +static struct clk_rcg2 gcc_camss_jpeg_clk_src = { + .cmd_rcgr = 0x52028, + .mnd_width = 0, + .hid_width = 5, + .parent_map = gcc_parent_map_12, + .freq_tbl = ftbl_gcc_camss_jpeg_clk_src, + .clkr.hw.init = &(struct clk_init_data){ + .name = "gcc_camss_jpeg_clk_src", + .parent_data = gcc_parent_data_12, + .num_parents = ARRAY_SIZE(gcc_parent_data_12), + .ops = &clk_rcg2_ops, + }, +}; + +static const struct freq_tbl ftbl_gcc_camss_mclk0_clk_src[] = { + F(19200000, P_BI_TCXO, 1, 0, 0), + F(24000000, P_GPLL9_OUT_MAIN, 1, 1, 24), + F(64000000, P_GPLL9_OUT_MAIN, 1, 1, 9), + { } +}; + +static struct clk_rcg2 gcc_camss_mclk0_clk_src = { + .cmd_rcgr = 0x51000, + .mnd_width = 8, + .hid_width = 5, + .parent_map = gcc_parent_map_4, + .freq_tbl = ftbl_gcc_camss_mclk0_clk_src, + .clkr.hw.init = &(struct clk_init_data){ + .name = "gcc_camss_mclk0_clk_src", + .parent_data = gcc_parent_data_4, + .num_parents = ARRAY_SIZE(gcc_parent_data_4), + .ops = &clk_rcg2_ops, + }, +}; + +static struct clk_rcg2 gcc_camss_mclk1_clk_src = { + .cmd_rcgr = 0x5101c, + .mnd_width = 8, + .hid_width = 5, + .parent_map = gcc_parent_map_4, + .freq_tbl = ftbl_gcc_camss_mclk0_clk_src, + .clkr.hw.init = &(struct clk_init_data){ + .name = "gcc_camss_mclk1_clk_src", + .parent_data = gcc_parent_data_4, + .num_parents = ARRAY_SIZE(gcc_parent_data_4), + .ops = &clk_rcg2_ops, + }, +}; + +static struct clk_rcg2 gcc_camss_mclk2_clk_src = { + .cmd_rcgr = 0x51038, + .mnd_width = 8, + .hid_width = 5, + .parent_map = gcc_parent_map_4, + .freq_tbl = ftbl_gcc_camss_mclk0_clk_src, + .clkr.hw.init = &(struct clk_init_data){ + .name = "gcc_camss_mclk2_clk_src", + .parent_data = gcc_parent_data_4, + .num_parents = ARRAY_SIZE(gcc_parent_data_4), + .ops = &clk_rcg2_ops, + }, +}; + +static struct clk_rcg2 gcc_camss_mclk3_clk_src = { + .cmd_rcgr = 0x51054, + .mnd_width = 8, + .hid_width = 5, + .parent_map = gcc_parent_map_4, + .freq_tbl = ftbl_gcc_camss_mclk0_clk_src, + .clkr.hw.init = &(struct clk_init_data){ + .name = "gcc_camss_mclk3_clk_src", + .parent_data = gcc_parent_data_4, + .num_parents = ARRAY_SIZE(gcc_parent_data_4), + .ops = &clk_rcg2_ops, + }, +}; + +static const struct freq_tbl ftbl_gcc_camss_vfe0_clk_src[] = { + F(120000000, P_GPLL8_OUT_MAIN, 4, 0, 0), + F(256000000, P_GPLL6_OUT_EARLY, 3, 0, 0), + F(403200000, P_GPLL4_OUT_MAIN, 2, 0, 0), + F(480000000, P_GPLL8_OUT_MAIN, 1, 0, 0), + F(533000000, P_GPLL3_OUT_EARLY, 2, 0, 0), + F(576000000, P_GPLL9_OUT_MAIN, 1, 0, 0), + { } +}; + +static struct clk_rcg2 gcc_camss_vfe0_clk_src = { + .cmd_rcgr = 0x54010, + .mnd_width = 0, + .hid_width = 5, + .parent_map = gcc_parent_map_8, + .freq_tbl = ftbl_gcc_camss_vfe0_clk_src, + .clkr.hw.init = &(struct clk_init_data){ + .name = "gcc_camss_vfe0_clk_src", + .parent_data = gcc_parent_data_8, + .num_parents = ARRAY_SIZE(gcc_parent_data_8), + .ops = &clk_rcg2_ops, + }, +}; + +static struct clk_rcg2 gcc_camss_vfe1_clk_src = { + .cmd_rcgr = 0x54048, + .mnd_width = 0, + .hid_width = 5, + .parent_map = gcc_parent_map_8, + .freq_tbl = ftbl_gcc_camss_vfe0_clk_src, + .clkr.hw.init = &(struct clk_init_data){ + .name = "gcc_camss_vfe1_clk_src", + .parent_data = gcc_parent_data_8, + .num_parents = ARRAY_SIZE(gcc_parent_data_8), + .ops = &clk_rcg2_ops, + }, +}; + +static const struct freq_tbl ftbl_gcc_gp1_clk_src[] = { + F(25000000, P_GPLL0_OUT_AUX2, 12, 0, 0), + F(50000000, P_GPLL0_OUT_AUX2, 6, 0, 0), + F(100000000, P_GPLL0_OUT_EARLY, 6, 0, 0), + F(200000000, P_GPLL0_OUT_EARLY, 3, 0, 0), + { } +}; + +static struct clk_rcg2 gcc_gp1_clk_src = { + .cmd_rcgr = 0x4d004, + .mnd_width = 8, + .hid_width = 5, + .parent_map = gcc_parent_map_2, + .freq_tbl = ftbl_gcc_gp1_clk_src, + .clkr.hw.init = &(struct clk_init_data){ + .name = "gcc_gp1_clk_src", + .parent_data = gcc_parent_data_2, + .num_parents = ARRAY_SIZE(gcc_parent_data_2), + .ops = &clk_rcg2_ops, + }, +}; + +static struct clk_rcg2 gcc_gp2_clk_src = { + .cmd_rcgr = 0x4e004, + .mnd_width = 8, + .hid_width = 5, + .parent_map = gcc_parent_map_2, + .freq_tbl = ftbl_gcc_gp1_clk_src, + .clkr.hw.init = &(struct clk_init_data){ + .name = "gcc_gp2_clk_src", + .parent_data = gcc_parent_data_2, + .num_parents = ARRAY_SIZE(gcc_parent_data_2), + .ops = &clk_rcg2_ops, + }, +}; + +static struct clk_rcg2 gcc_gp3_clk_src = { + .cmd_rcgr = 0x4f004, + .mnd_width = 8, + .hid_width = 5, + .parent_map = gcc_parent_map_2, + .freq_tbl = ftbl_gcc_gp1_clk_src, + .clkr.hw.init = &(struct clk_init_data){ + .name = "gcc_gp3_clk_src", + .parent_data = gcc_parent_data_2, + .num_parents = ARRAY_SIZE(gcc_parent_data_2), + .ops = &clk_rcg2_ops, + }, +}; + +static const struct freq_tbl ftbl_gcc_pdm2_clk_src[] = { + F(19200000, P_BI_TCXO, 1, 0, 0), + F(60000000, P_GPLL0_OUT_EARLY, 10, 0, 0), + { } +}; + +static struct clk_rcg2 gcc_pdm2_clk_src = { + .cmd_rcgr = 0x20010, + .mnd_width = 0, + .hid_width = 5, + .parent_map = gcc_parent_map_0, + .freq_tbl = ftbl_gcc_pdm2_clk_src, + .clkr.hw.init = &(struct clk_init_data){ + .name = "gcc_pdm2_clk_src", + .parent_data = gcc_parent_data_0, + .num_parents = ARRAY_SIZE(gcc_parent_data_0), + .ops = &clk_rcg2_ops, + }, +}; + +static const struct freq_tbl ftbl_gcc_qupv3_wrap0_s0_clk_src[] = { + F(7372800, P_GPLL0_OUT_AUX2, 1, 384, 15625), + F(14745600, P_GPLL0_OUT_AUX2, 1, 768, 15625), + F(19200000, P_BI_TCXO, 1, 0, 0), + F(29491200, P_GPLL0_OUT_AUX2, 1, 1536, 15625), + F(32000000, P_GPLL0_OUT_AUX2, 1, 8, 75), + F(48000000, P_GPLL0_OUT_AUX2, 1, 4, 25), + F(64000000, P_GPLL0_OUT_AUX2, 1, 16, 75), + F(75000000, P_GPLL0_OUT_AUX2, 4, 0, 0), + F(80000000, P_GPLL0_OUT_AUX2, 1, 4, 15), + F(96000000, P_GPLL0_OUT_AUX2, 1, 8, 25), + F(100000000, P_GPLL0_OUT_EARLY, 6, 0, 0), + F(102400000, P_GPLL0_OUT_AUX2, 1, 128, 375), + F(112000000, P_GPLL0_OUT_AUX2, 1, 28, 75), + F(117964800, P_GPLL0_OUT_AUX2, 1, 6144, 15625), + F(120000000, P_GPLL0_OUT_AUX2, 2.5, 0, 0), + F(128000000, P_GPLL6_OUT_MAIN, 3, 0, 0), + { } +}; + +static struct clk_init_data gcc_qupv3_wrap0_s0_clk_src_init = { + .name = "gcc_qupv3_wrap0_s0_clk_src", + .parent_data = gcc_parent_data_1, + .num_parents = ARRAY_SIZE(gcc_parent_data_1), + .ops = &clk_rcg2_ops, +}; + +static struct clk_rcg2 gcc_qupv3_wrap0_s0_clk_src = { + .cmd_rcgr = 0x1f148, + .mnd_width = 16, + .hid_width = 5, + .parent_map = gcc_parent_map_1, + .freq_tbl = ftbl_gcc_qupv3_wrap0_s0_clk_src, + .clkr.hw.init = &gcc_qupv3_wrap0_s0_clk_src_init, +}; + +static struct clk_init_data gcc_qupv3_wrap0_s1_clk_src_init = { + .name = "gcc_qupv3_wrap0_s1_clk_src", + .parent_data = gcc_parent_data_1, + .num_parents = ARRAY_SIZE(gcc_parent_data_1), + .ops = &clk_rcg2_ops, +}; + +static struct clk_rcg2 gcc_qupv3_wrap0_s1_clk_src = { + .cmd_rcgr = 0x1f278, + .mnd_width = 16, + .hid_width = 5, + .parent_map = gcc_parent_map_1, + .freq_tbl = ftbl_gcc_qupv3_wrap0_s0_clk_src, + .clkr.hw.init = &gcc_qupv3_wrap0_s1_clk_src_init, +}; + +static struct clk_init_data gcc_qupv3_wrap0_s2_clk_src_init = { + .name = "gcc_qupv3_wrap0_s2_clk_src", + .parent_data = gcc_parent_data_1, + .num_parents = ARRAY_SIZE(gcc_parent_data_1), + .ops = &clk_rcg2_ops, +}; + +static struct clk_rcg2 gcc_qupv3_wrap0_s2_clk_src = { + .cmd_rcgr = 0x1f3a8, + .mnd_width = 16, + .hid_width = 5, + .parent_map = gcc_parent_map_1, + .freq_tbl = ftbl_gcc_qupv3_wrap0_s0_clk_src, + .clkr.hw.init = &gcc_qupv3_wrap0_s2_clk_src_init, +}; + +static struct clk_init_data gcc_qupv3_wrap0_s3_clk_src_init = { + .name = "gcc_qupv3_wrap0_s3_clk_src", + .parent_data = gcc_parent_data_1, + .num_parents = ARRAY_SIZE(gcc_parent_data_1), + .ops = &clk_rcg2_ops, +}; + +static struct clk_rcg2 gcc_qupv3_wrap0_s3_clk_src = { + .cmd_rcgr = 0x1f4d8, + .mnd_width = 16, + .hid_width = 5, + .parent_map = gcc_parent_map_1, + .freq_tbl = ftbl_gcc_qupv3_wrap0_s0_clk_src, + .clkr.hw.init = &gcc_qupv3_wrap0_s3_clk_src_init, +}; + +static struct clk_init_data gcc_qupv3_wrap0_s4_clk_src_init = { + .name = "gcc_qupv3_wrap0_s4_clk_src", + .parent_data = gcc_parent_data_1, + .num_parents = ARRAY_SIZE(gcc_parent_data_1), + .ops = &clk_rcg2_ops, +}; + +static struct clk_rcg2 gcc_qupv3_wrap0_s4_clk_src = { + .cmd_rcgr = 0x1f608, + .mnd_width = 16, + .hid_width = 5, + .parent_map = gcc_parent_map_1, + .freq_tbl = ftbl_gcc_qupv3_wrap0_s0_clk_src, + .clkr.hw.init = &gcc_qupv3_wrap0_s4_clk_src_init, +}; + +static struct clk_init_data gcc_qupv3_wrap0_s5_clk_src_init = { + .name = "gcc_qupv3_wrap0_s5_clk_src", + .parent_data = gcc_parent_data_1, + .num_parents = ARRAY_SIZE(gcc_parent_data_1), + .ops = &clk_rcg2_ops, +}; + +static struct clk_rcg2 gcc_qupv3_wrap0_s5_clk_src = { + .cmd_rcgr = 0x1f738, + .mnd_width = 16, + .hid_width = 5, + .parent_map = gcc_parent_map_1, + .freq_tbl = ftbl_gcc_qupv3_wrap0_s0_clk_src, + .clkr.hw.init = &gcc_qupv3_wrap0_s5_clk_src_init, +}; + +static struct clk_init_data gcc_qupv3_wrap1_s0_clk_src_init = { + .name = "gcc_qupv3_wrap1_s0_clk_src", + .parent_data = gcc_parent_data_1, + .num_parents = ARRAY_SIZE(gcc_parent_data_1), + .ops = &clk_rcg2_ops, +}; + +static struct clk_rcg2 gcc_qupv3_wrap1_s0_clk_src = { + .cmd_rcgr = 0x39148, + .mnd_width = 16, + .hid_width = 5, + .parent_map = gcc_parent_map_1, + .freq_tbl = ftbl_gcc_qupv3_wrap0_s0_clk_src, + .clkr.hw.init = &gcc_qupv3_wrap1_s0_clk_src_init, +}; + +static struct clk_init_data gcc_qupv3_wrap1_s1_clk_src_init = { + .name = "gcc_qupv3_wrap1_s1_clk_src", + .parent_data = gcc_parent_data_1, + .num_parents = ARRAY_SIZE(gcc_parent_data_1), + .ops = &clk_rcg2_ops, +}; + +static struct clk_rcg2 gcc_qupv3_wrap1_s1_clk_src = { + .cmd_rcgr = 0x39278, + .mnd_width = 16, + .hid_width = 5, + .parent_map = gcc_parent_map_1, + .freq_tbl = ftbl_gcc_qupv3_wrap0_s0_clk_src, + .clkr.hw.init = &gcc_qupv3_wrap1_s1_clk_src_init, +}; + +static struct clk_init_data gcc_qupv3_wrap1_s2_clk_src_init = { + .name = "gcc_qupv3_wrap1_s2_clk_src", + .parent_data = gcc_parent_data_1, + .num_parents = ARRAY_SIZE(gcc_parent_data_1), + .ops = &clk_rcg2_ops, +}; + +static struct clk_rcg2 gcc_qupv3_wrap1_s2_clk_src = { + .cmd_rcgr = 0x393a8, + .mnd_width = 16, + .hid_width = 5, + .parent_map = gcc_parent_map_1, + .freq_tbl = ftbl_gcc_qupv3_wrap0_s0_clk_src, + .clkr.hw.init = &gcc_qupv3_wrap1_s2_clk_src_init, +}; + +static struct clk_init_data gcc_qupv3_wrap1_s3_clk_src_init = { + .name = "gcc_qupv3_wrap1_s3_clk_src", + .parent_data = gcc_parent_data_1, + .num_parents = ARRAY_SIZE(gcc_parent_data_1), + .ops = &clk_rcg2_ops, +}; + +static struct clk_rcg2 gcc_qupv3_wrap1_s3_clk_src = { + .cmd_rcgr = 0x394d8, + .mnd_width = 16, + .hid_width = 5, + .parent_map = gcc_parent_map_1, + .freq_tbl = ftbl_gcc_qupv3_wrap0_s0_clk_src, + .clkr.hw.init = &gcc_qupv3_wrap1_s3_clk_src_init, +}; + +static struct clk_init_data gcc_qupv3_wrap1_s4_clk_src_init = { + .name = "gcc_qupv3_wrap1_s4_clk_src", + .parent_data = gcc_parent_data_1, + .num_parents = ARRAY_SIZE(gcc_parent_data_1), + .ops = &clk_rcg2_ops, +}; + +static struct clk_rcg2 gcc_qupv3_wrap1_s4_clk_src = { + .cmd_rcgr = 0x39608, + .mnd_width = 16, + .hid_width = 5, + .parent_map = gcc_parent_map_1, + .freq_tbl = ftbl_gcc_qupv3_wrap0_s0_clk_src, + .clkr.hw.init = &gcc_qupv3_wrap1_s4_clk_src_init, +}; + +static struct clk_init_data gcc_qupv3_wrap1_s5_clk_src_init = { + .name = "gcc_qupv3_wrap1_s5_clk_src", + .parent_data = gcc_parent_data_1, + .num_parents = ARRAY_SIZE(gcc_parent_data_1), + .ops = &clk_rcg2_ops, +}; + +static struct clk_rcg2 gcc_qupv3_wrap1_s5_clk_src = { + .cmd_rcgr = 0x39738, + .mnd_width = 16, + .hid_width = 5, + .parent_map = gcc_parent_map_1, + .freq_tbl = ftbl_gcc_qupv3_wrap0_s0_clk_src, + .clkr.hw.init = &gcc_qupv3_wrap1_s5_clk_src_init, +}; + +static const struct freq_tbl ftbl_gcc_sdcc1_apps_clk_src[] = { + F(144000, P_BI_TCXO, 16, 3, 25), + F(400000, P_BI_TCXO, 12, 1, 4), + F(20000000, P_GPLL0_OUT_AUX2, 5, 1, 3), + F(25000000, P_GPLL0_OUT_AUX2, 6, 1, 2), + F(50000000, P_GPLL0_OUT_AUX2, 6, 0, 0), + F(100000000, P_GPLL0_OUT_AUX2, 3, 0, 0), + F(192000000, P_GPLL6_OUT_MAIN, 2, 0, 0), + F(384000000, P_GPLL6_OUT_MAIN, 1, 0, 0), + { } +}; + +static struct clk_rcg2 gcc_sdcc1_apps_clk_src = { + .cmd_rcgr = 0x38028, + .mnd_width = 8, + .hid_width = 5, + .parent_map = gcc_parent_map_1, + .freq_tbl = ftbl_gcc_sdcc1_apps_clk_src, + .clkr.hw.init = &(struct clk_init_data){ + .name = "gcc_sdcc1_apps_clk_src", + .parent_data = gcc_parent_data_1, + .num_parents = ARRAY_SIZE(gcc_parent_data_1), + .ops = &clk_rcg2_ops, + }, +}; + +static const struct freq_tbl ftbl_gcc_sdcc1_ice_core_clk_src[] = { + F(75000000, P_GPLL0_OUT_AUX2, 4, 0, 0), + F(150000000, P_GPLL0_OUT_EARLY, 4, 0, 0), + F(200000000, P_GPLL0_OUT_EARLY, 3, 0, 0), + F(300000000, P_GPLL0_OUT_EARLY, 2, 0, 0), + { } +}; + +static struct clk_rcg2 gcc_sdcc1_ice_core_clk_src = { + .cmd_rcgr = 0x38010, + .mnd_width = 0, + .hid_width = 5, + .parent_map = gcc_parent_map_0, + .freq_tbl = ftbl_gcc_sdcc1_ice_core_clk_src, + .clkr.hw.init = &(struct clk_init_data){ + .name = "gcc_sdcc1_ice_core_clk_src", + .parent_data = gcc_parent_data_0, + .num_parents = ARRAY_SIZE(gcc_parent_data_0), + .ops = &clk_rcg2_floor_ops, + }, +}; + +static const struct freq_tbl ftbl_gcc_sdcc2_apps_clk_src[] = { + F(400000, P_BI_TCXO, 12, 1, 4), + F(19200000, P_BI_TCXO, 1, 0, 0), + F(25000000, P_GPLL0_OUT_AUX2, 12, 0, 0), + F(50000000, P_GPLL0_OUT_AUX2, 6, 0, 0), + F(100000000, P_GPLL0_OUT_AUX2, 3, 0, 0), + F(202000000, P_GPLL7_OUT_MAIN, 2, 0, 0), + { } +}; + +static struct clk_rcg2 gcc_sdcc2_apps_clk_src = { + .cmd_rcgr = 0x1e00c, + .mnd_width = 8, + .hid_width = 5, + .parent_map = gcc_parent_map_13, + .freq_tbl = ftbl_gcc_sdcc2_apps_clk_src, + .clkr.hw.init = &(struct clk_init_data){ + .name = "gcc_sdcc2_apps_clk_src", + .parent_data = gcc_parent_data_13, + .num_parents = ARRAY_SIZE(gcc_parent_data_13), + .ops = &clk_rcg2_floor_ops, + }, +}; + +static const struct freq_tbl ftbl_gcc_ufs_phy_axi_clk_src[] = { + F(25000000, P_GPLL0_OUT_AUX2, 12, 0, 0), + F(50000000, P_GPLL0_OUT_AUX2, 6, 0, 0), + F(100000000, P_GPLL0_OUT_EARLY, 6, 0, 0), + F(200000000, P_GPLL0_OUT_EARLY, 3, 0, 0), + F(240000000, P_GPLL0_OUT_EARLY, 2.5, 0, 0), + { } +}; + +static struct clk_rcg2 gcc_ufs_phy_axi_clk_src = { + .cmd_rcgr = 0x45020, + .mnd_width = 8, + .hid_width = 5, + .parent_map = gcc_parent_map_0, + .freq_tbl = ftbl_gcc_ufs_phy_axi_clk_src, + .clkr.hw.init = &(struct clk_init_data){ + .name = "gcc_ufs_phy_axi_clk_src", + .parent_data = gcc_parent_data_0, + .num_parents = ARRAY_SIZE(gcc_parent_data_0), + .ops = &clk_rcg2_ops, + }, +}; + +static const struct freq_tbl ftbl_gcc_ufs_phy_ice_core_clk_src[] = { + F(37500000, P_GPLL0_OUT_AUX2, 8, 0, 0), + F(75000000, P_GPLL0_OUT_AUX2, 4, 0, 0), + F(150000000, P_GPLL0_OUT_EARLY, 4, 0, 0), + F(300000000, P_GPLL0_OUT_EARLY, 2, 0, 0), + { } +}; + +static struct clk_rcg2 gcc_ufs_phy_ice_core_clk_src = { + .cmd_rcgr = 0x45048, + .mnd_width = 0, + .hid_width = 5, + .parent_map = gcc_parent_map_0, + .freq_tbl = ftbl_gcc_ufs_phy_ice_core_clk_src, + .clkr.hw.init = &(struct clk_init_data){ + .name = "gcc_ufs_phy_ice_core_clk_src", + .parent_data = gcc_parent_data_0, + .num_parents = ARRAY_SIZE(gcc_parent_data_0), + .ops = &clk_rcg2_ops, + }, +}; + +static const struct freq_tbl ftbl_gcc_ufs_phy_phy_aux_clk_src[] = { + F(9600000, P_BI_TCXO, 2, 0, 0), + F(19200000, P_BI_TCXO, 1, 0, 0), + { } +}; + +static struct clk_rcg2 gcc_ufs_phy_phy_aux_clk_src = { + .cmd_rcgr = 0x4507c, + .mnd_width = 0, + .hid_width = 5, + .parent_map = gcc_parent_map_0, + .freq_tbl = ftbl_gcc_ufs_phy_phy_aux_clk_src, + .clkr.hw.init = &(struct clk_init_data){ + .name = "gcc_ufs_phy_phy_aux_clk_src", + .parent_data = gcc_parent_data_0, + .num_parents = ARRAY_SIZE(gcc_parent_data_0), + .ops = &clk_rcg2_ops, + }, +}; + +static const struct freq_tbl ftbl_gcc_ufs_phy_unipro_core_clk_src[] = { + F(37500000, P_GPLL0_OUT_AUX2, 8, 0, 0), + F(75000000, P_GPLL0_OUT_EARLY, 8, 0, 0), + F(150000000, P_GPLL0_OUT_EARLY, 4, 0, 0), + { } +}; + +static struct clk_rcg2 gcc_ufs_phy_unipro_core_clk_src = { + .cmd_rcgr = 0x45060, + .mnd_width = 0, + .hid_width = 5, + .parent_map = gcc_parent_map_0, + .freq_tbl = ftbl_gcc_ufs_phy_unipro_core_clk_src, + .clkr.hw.init = &(struct clk_init_data){ + .name = "gcc_ufs_phy_unipro_core_clk_src", + .parent_data = gcc_parent_data_0, + .num_parents = ARRAY_SIZE(gcc_parent_data_0), + .ops = &clk_rcg2_ops, + }, +}; + +static const struct freq_tbl ftbl_gcc_usb30_prim_master_clk_src[] = { + F(66666667, P_GPLL0_OUT_AUX2, 4.5, 0, 0), + F(133333333, P_GPLL0_OUT_EARLY, 4.5, 0, 0), + F(200000000, P_GPLL0_OUT_EARLY, 3, 0, 0), + F(240000000, P_GPLL0_OUT_EARLY, 2.5, 0, 0), + { } +}; + +static struct clk_rcg2 gcc_usb30_prim_master_clk_src = { + .cmd_rcgr = 0x1a01c, + .mnd_width = 8, + .hid_width = 5, + .parent_map = gcc_parent_map_0, + .freq_tbl = ftbl_gcc_usb30_prim_master_clk_src, + .clkr.hw.init = &(struct clk_init_data){ + .name = "gcc_usb30_prim_master_clk_src", + .parent_data = gcc_parent_data_0, + .num_parents = ARRAY_SIZE(gcc_parent_data_0), + .ops = &clk_rcg2_ops, + }, +}; + +static const struct freq_tbl ftbl_gcc_usb30_prim_mock_utmi_clk_src[] = { + F(19200000, P_BI_TCXO, 1, 0, 0), + F(20000000, P_GPLL0_OUT_AUX2, 15, 0, 0), + F(40000000, P_GPLL0_OUT_AUX2, 7.5, 0, 0), + F(60000000, P_GPLL0_OUT_EARLY, 10, 0, 0), + { } +}; + +static struct clk_rcg2 gcc_usb30_prim_mock_utmi_clk_src = { + .cmd_rcgr = 0x1a034, + .mnd_width = 0, + .hid_width = 5, + .parent_map = gcc_parent_map_0, + .freq_tbl = ftbl_gcc_usb30_prim_mock_utmi_clk_src, + .clkr.hw.init = &(struct clk_init_data){ + .name = "gcc_usb30_prim_mock_utmi_clk_src", + .parent_data = gcc_parent_data_0, + .num_parents = ARRAY_SIZE(gcc_parent_data_0), + .ops = &clk_rcg2_ops, + }, +}; + +static const struct freq_tbl ftbl_gcc_usb3_prim_phy_aux_clk_src[] = { + F(19200000, P_BI_TCXO, 1, 0, 0), + { } +}; + +static struct clk_rcg2 gcc_usb3_prim_phy_aux_clk_src = { + .cmd_rcgr = 0x1a060, + .mnd_width = 0, + .hid_width = 5, + .parent_map = gcc_parent_map_14, + .freq_tbl = ftbl_gcc_usb3_prim_phy_aux_clk_src, + .clkr.hw.init = &(struct clk_init_data){ + .name = "gcc_usb3_prim_phy_aux_clk_src", + .parent_data = gcc_parent_data_14, + .num_parents = ARRAY_SIZE(gcc_parent_data_14), + .ops = &clk_rcg2_ops, + }, +}; + +static struct clk_rcg2 gcc_vs_ctrl_clk_src = { + .cmd_rcgr = 0x42030, + .mnd_width = 0, + .hid_width = 5, + .parent_map = gcc_parent_map_5, + .freq_tbl = ftbl_gcc_usb3_prim_phy_aux_clk_src, + .clkr.hw.init = &(struct clk_init_data){ + .name = "gcc_vs_ctrl_clk_src", + .parent_data = gcc_parent_data_5, + .num_parents = ARRAY_SIZE(gcc_parent_data_5), + .ops = &clk_rcg2_ops, + }, +}; + +static const struct freq_tbl ftbl_gcc_vsensor_clk_src[] = { + F(19200000, P_BI_TCXO, 1, 0, 0), + F(400000000, P_GPLL0_OUT_EARLY, 1.5, 0, 0), + F(600000000, P_GPLL0_OUT_EARLY, 1, 0, 0), + { } +}; + +static struct clk_rcg2 gcc_vsensor_clk_src = { + .cmd_rcgr = 0x42018, + .mnd_width = 0, + .hid_width = 5, + .parent_map = gcc_parent_map_5, + .freq_tbl = ftbl_gcc_vsensor_clk_src, + .clkr.hw.init = &(struct clk_init_data){ + .name = "gcc_vsensor_clk_src", + .parent_data = gcc_parent_data_5, + .num_parents = ARRAY_SIZE(gcc_parent_data_5), + .ops = &clk_rcg2_ops, + }, +}; + +static struct clk_branch gcc_ahb2phy_csi_clk = { + .halt_reg = 0x1d004, + .halt_check = BRANCH_HALT, + .hwcg_reg = 0x1d004, + .hwcg_bit = 1, + .clkr = { + .enable_reg = 0x1d004, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_ahb2phy_csi_clk", + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_ahb2phy_usb_clk = { + .halt_reg = 0x1d008, + .halt_check = BRANCH_HALT, + .hwcg_reg = 0x1d008, + .hwcg_bit = 1, + .clkr = { + .enable_reg = 0x1d008, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_ahb2phy_usb_clk", + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_apc_vs_clk = { + .halt_reg = 0x4204c, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x4204c, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_apc_vs_clk", + .parent_hws = (const struct clk_hw*[]){ + &gcc_vsensor_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_bimc_gpu_axi_clk = { + .halt_reg = 0x71154, + .halt_check = BRANCH_HALT_DELAY, + .clkr = { + .enable_reg = 0x71154, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_bimc_gpu_axi_clk", + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_boot_rom_ahb_clk = { + .halt_reg = 0x23004, + .halt_check = BRANCH_HALT_VOTED, + .hwcg_reg = 0x23004, + .hwcg_bit = 1, + .clkr = { + .enable_reg = 0x79004, + .enable_mask = BIT(10), + .hw.init = &(struct clk_init_data){ + .name = "gcc_boot_rom_ahb_clk", + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_camera_ahb_clk = { + .halt_reg = 0x17008, + .halt_check = BRANCH_HALT_DELAY, + .hwcg_reg = 0x17008, + .hwcg_bit = 1, + .clkr = { + .enable_reg = 0x17008, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_camera_ahb_clk", + .flags = CLK_IS_CRITICAL, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_camera_xo_clk = { + .halt_reg = 0x17028, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x17028, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_camera_xo_clk", + .flags = CLK_IS_CRITICAL, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_camss_cci_ahb_clk = { + .halt_reg = 0x52020, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x52020, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_camss_cci_ahb_clk", + .parent_hws = (const struct clk_hw*[]){ + &gcc_camss_ahb_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_camss_cci_clk = { + .halt_reg = 0x5201c, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x5201c, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_camss_cci_clk", + .parent_hws = (const struct clk_hw*[]){ + &gcc_camss_cci_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_camss_cphy_csid0_clk = { + .halt_reg = 0x5504c, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x5504c, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_camss_cphy_csid0_clk", + .parent_hws = (const struct clk_hw*[]){ + &gcc_camss_csiphy_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_camss_cphy_csid1_clk = { + .halt_reg = 0x55088, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x55088, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_camss_cphy_csid1_clk", + .parent_hws = (const struct clk_hw*[]){ + &gcc_camss_csiphy_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_camss_cphy_csid2_clk = { + .halt_reg = 0x550c0, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x550c0, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_camss_cphy_csid2_clk", + .parent_hws = (const struct clk_hw*[]){ + &gcc_camss_csiphy_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_camss_cphy_csid3_clk = { + .halt_reg = 0x550fc, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x550fc, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_camss_cphy_csid3_clk", + .parent_hws = (const struct clk_hw*[]){ + &gcc_camss_csiphy_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_camss_cpp_ahb_clk = { + .halt_reg = 0x560e8, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x560e8, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_camss_cpp_ahb_clk", + .parent_hws = (const struct clk_hw*[]){ + &gcc_camss_ahb_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_camss_cpp_axi_clk = { + .halt_reg = 0x560f4, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x560f4, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_camss_cpp_axi_clk", + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_camss_cpp_clk = { + .halt_reg = 0x560e0, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x560e0, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_camss_cpp_clk", + .parent_hws = (const struct clk_hw*[]){ + &gcc_camss_cpp_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_camss_cpp_vbif_ahb_clk = { + .halt_reg = 0x560f0, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x560f0, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_camss_cpp_vbif_ahb_clk", + .parent_hws = (const struct clk_hw*[]){ + &gcc_camss_ahb_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_camss_csi0_ahb_clk = { + .halt_reg = 0x55050, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x55050, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_camss_csi0_ahb_clk", + .parent_hws = (const struct clk_hw*[]){ + &gcc_camss_ahb_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_camss_csi0_clk = { + .halt_reg = 0x55048, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x55048, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_camss_csi0_clk", + .parent_hws = (const struct clk_hw*[]){ + &gcc_camss_csi0_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_camss_csi0phytimer_clk = { + .halt_reg = 0x5301c, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x5301c, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_camss_csi0phytimer_clk", + .parent_hws = (const struct clk_hw*[]){ + &gcc_camss_csi0phytimer_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_camss_csi0pix_clk = { + .halt_reg = 0x55060, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x55060, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_camss_csi0pix_clk", + .parent_hws = (const struct clk_hw*[]){ + &gcc_camss_csi0_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_camss_csi0rdi_clk = { + .halt_reg = 0x55058, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x55058, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_camss_csi0rdi_clk", + .parent_hws = (const struct clk_hw*[]){ + &gcc_camss_csi0_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_camss_csi1_ahb_clk = { + .halt_reg = 0x5508c, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x5508c, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_camss_csi1_ahb_clk", + .parent_hws = (const struct clk_hw*[]){ + &gcc_camss_ahb_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_camss_csi1_clk = { + .halt_reg = 0x55084, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x55084, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_camss_csi1_clk", + .parent_hws = (const struct clk_hw*[]){ + &gcc_camss_csi1_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_camss_csi1phytimer_clk = { + .halt_reg = 0x5303c, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x5303c, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_camss_csi1phytimer_clk", + .parent_hws = (const struct clk_hw*[]){ + &gcc_camss_csi1phytimer_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_camss_csi1pix_clk = { + .halt_reg = 0x5509c, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x5509c, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_camss_csi1pix_clk", + .parent_hws = (const struct clk_hw*[]){ + &gcc_camss_csi1_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_camss_csi1rdi_clk = { + .halt_reg = 0x55094, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x55094, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_camss_csi1rdi_clk", + .parent_hws = (const struct clk_hw*[]){ + &gcc_camss_csi1_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_camss_csi2_ahb_clk = { + .halt_reg = 0x550c4, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x550c4, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_camss_csi2_ahb_clk", + .parent_hws = (const struct clk_hw*[]){ + &gcc_camss_ahb_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_camss_csi2_clk = { + .halt_reg = 0x550bc, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x550bc, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_camss_csi2_clk", + .parent_hws = (const struct clk_hw*[]){ + &gcc_camss_csi2_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_camss_csi2phytimer_clk = { + .halt_reg = 0x5305c, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x5305c, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_camss_csi2phytimer_clk", + .parent_hws = (const struct clk_hw*[]){ + &gcc_camss_csi2phytimer_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_camss_csi2pix_clk = { + .halt_reg = 0x550d4, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x550d4, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_camss_csi2pix_clk", + .parent_hws = (const struct clk_hw*[]){ + &gcc_camss_csi2_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_camss_csi2rdi_clk = { + .halt_reg = 0x550cc, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x550cc, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_camss_csi2rdi_clk", + .parent_hws = (const struct clk_hw*[]){ + &gcc_camss_csi2_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_camss_csi3_ahb_clk = { + .halt_reg = 0x55100, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x55100, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_camss_csi3_ahb_clk", + .parent_hws = (const struct clk_hw*[]){ + &gcc_camss_ahb_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_camss_csi3_clk = { + .halt_reg = 0x550f8, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x550f8, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_camss_csi3_clk", + .parent_hws = (const struct clk_hw*[]){ + &gcc_camss_csi3_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_camss_csi3pix_clk = { + .halt_reg = 0x55110, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x55110, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_camss_csi3pix_clk", + .parent_hws = (const struct clk_hw*[]){ + &gcc_camss_csi3_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_camss_csi3rdi_clk = { + .halt_reg = 0x55108, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x55108, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_camss_csi3rdi_clk", + .parent_hws = (const struct clk_hw*[]){ + &gcc_camss_csi3_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_camss_csi_vfe0_clk = { + .halt_reg = 0x54074, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x54074, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_camss_csi_vfe0_clk", + .parent_hws = (const struct clk_hw*[]){ + &gcc_camss_vfe0_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_camss_csi_vfe1_clk = { + .halt_reg = 0x54080, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x54080, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_camss_csi_vfe1_clk", + .parent_hws = (const struct clk_hw*[]){ + &gcc_camss_vfe1_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_camss_csiphy0_clk = { + .halt_reg = 0x55018, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x55018, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_camss_csiphy0_clk", + .parent_hws = (const struct clk_hw*[]){ + &gcc_camss_csiphy_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_camss_csiphy1_clk = { + .halt_reg = 0x5501c, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x5501c, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_camss_csiphy1_clk", + .parent_hws = (const struct clk_hw*[]){ + &gcc_camss_csiphy_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_camss_csiphy2_clk = { + .halt_reg = 0x55020, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x55020, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_camss_csiphy2_clk", + .parent_hws = (const struct clk_hw*[]){ + &gcc_camss_csiphy_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_camss_gp0_clk = { + .halt_reg = 0x50018, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x50018, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_camss_gp0_clk", + .parent_hws = (const struct clk_hw*[]){ + &gcc_camss_gp0_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_camss_gp1_clk = { + .halt_reg = 0x50034, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x50034, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_camss_gp1_clk", + .parent_hws = (const struct clk_hw*[]){ + &gcc_camss_gp1_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_camss_ispif_ahb_clk = { + .halt_reg = 0x540a4, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x540a4, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_camss_ispif_ahb_clk", + .parent_hws = (const struct clk_hw*[]){ + &gcc_camss_ahb_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_camss_jpeg_ahb_clk = { + .halt_reg = 0x52048, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x52048, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_camss_jpeg_ahb_clk", + .parent_hws = (const struct clk_hw*[]){ + &gcc_camss_ahb_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_camss_jpeg_axi_clk = { + .halt_reg = 0x5204c, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x5204c, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_camss_jpeg_axi_clk", + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_camss_jpeg_clk = { + .halt_reg = 0x52040, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x52040, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_camss_jpeg_clk", + .parent_hws = (const struct clk_hw*[]){ + &gcc_camss_jpeg_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_camss_mclk0_clk = { + .halt_reg = 0x51018, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x51018, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_camss_mclk0_clk", + .parent_hws = (const struct clk_hw*[]){ + &gcc_camss_mclk0_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_camss_mclk1_clk = { + .halt_reg = 0x51034, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x51034, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_camss_mclk1_clk", + .parent_hws = (const struct clk_hw*[]){ + &gcc_camss_mclk1_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_camss_mclk2_clk = { + .halt_reg = 0x51050, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x51050, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_camss_mclk2_clk", + .parent_hws = (const struct clk_hw*[]){ + &gcc_camss_mclk2_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_camss_mclk3_clk = { + .halt_reg = 0x5106c, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x5106c, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_camss_mclk3_clk", + .parent_hws = (const struct clk_hw*[]){ + &gcc_camss_mclk3_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_camss_micro_ahb_clk = { + .halt_reg = 0x560b0, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x560b0, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_camss_micro_ahb_clk", + .parent_hws = (const struct clk_hw*[]){ + &gcc_camss_ahb_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_camss_throttle_nrt_axi_clk = { + .halt_reg = 0x560a4, + .halt_check = BRANCH_HALT_VOTED, + .clkr = { + .enable_reg = 0x79004, + .enable_mask = BIT(27), + .hw.init = &(struct clk_init_data){ + .name = "gcc_camss_throttle_nrt_axi_clk", + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_camss_throttle_rt_axi_clk = { + .halt_reg = 0x560a8, + .halt_check = BRANCH_HALT_VOTED, + .clkr = { + .enable_reg = 0x79004, + .enable_mask = BIT(26), + .hw.init = &(struct clk_init_data){ + .name = "gcc_camss_throttle_rt_axi_clk", + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_camss_top_ahb_clk = { + .halt_reg = 0x560a0, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x560a0, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_camss_top_ahb_clk", + .parent_hws = (const struct clk_hw*[]){ + &gcc_camss_ahb_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_camss_vfe0_ahb_clk = { + .halt_reg = 0x54034, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x54034, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_camss_vfe0_ahb_clk", + .parent_hws = (const struct clk_hw*[]){ + &gcc_camss_ahb_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_camss_vfe0_clk = { + .halt_reg = 0x54028, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x54028, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_camss_vfe0_clk", + .parent_hws = (const struct clk_hw*[]){ + &gcc_camss_vfe0_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_camss_vfe0_stream_clk = { + .halt_reg = 0x54030, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x54030, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_camss_vfe0_stream_clk", + .parent_hws = (const struct clk_hw*[]){ + &gcc_camss_vfe0_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_camss_vfe1_ahb_clk = { + .halt_reg = 0x5406c, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x5406c, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_camss_vfe1_ahb_clk", + .parent_hws = (const struct clk_hw*[]){ + &gcc_camss_ahb_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_camss_vfe1_clk = { + .halt_reg = 0x54060, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x54060, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_camss_vfe1_clk", + .parent_hws = (const struct clk_hw*[]){ + &gcc_camss_vfe1_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_camss_vfe1_stream_clk = { + .halt_reg = 0x54068, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x54068, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_camss_vfe1_stream_clk", + .parent_hws = (const struct clk_hw*[]){ + &gcc_camss_vfe1_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_camss_vfe_tsctr_clk = { + .halt_reg = 0x5409c, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x5409c, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_camss_vfe_tsctr_clk", + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_camss_vfe_vbif_ahb_clk = { + .halt_reg = 0x5408c, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x5408c, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_camss_vfe_vbif_ahb_clk", + .parent_hws = (const struct clk_hw*[]){ + &gcc_camss_ahb_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_camss_vfe_vbif_axi_clk = { + .halt_reg = 0x54090, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x54090, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_camss_vfe_vbif_axi_clk", + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_ce1_ahb_clk = { + .halt_reg = 0x2700c, + .halt_check = BRANCH_HALT_VOTED, + .hwcg_reg = 0x2700c, + .hwcg_bit = 1, + .clkr = { + .enable_reg = 0x79004, + .enable_mask = BIT(3), + .hw.init = &(struct clk_init_data){ + .name = "gcc_ce1_ahb_clk", + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_ce1_axi_clk = { + .halt_reg = 0x27008, + .halt_check = BRANCH_HALT_VOTED, + .clkr = { + .enable_reg = 0x79004, + .enable_mask = BIT(4), + .hw.init = &(struct clk_init_data){ + .name = "gcc_ce1_axi_clk", + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_ce1_clk = { + .halt_reg = 0x27004, + .halt_check = BRANCH_HALT_VOTED, + .clkr = { + .enable_reg = 0x79004, + .enable_mask = BIT(5), + .hw.init = &(struct clk_init_data){ + .name = "gcc_ce1_clk", + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_cfg_noc_usb3_prim_axi_clk = { + .halt_reg = 0x1a084, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x1a084, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_cfg_noc_usb3_prim_axi_clk", + .parent_hws = (const struct clk_hw*[]){ + &gcc_usb30_prim_master_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_cpuss_gnoc_clk = { + .halt_reg = 0x2b004, + .halt_check = BRANCH_HALT_VOTED, + .hwcg_reg = 0x2b004, + .hwcg_bit = 1, + .clkr = { + .enable_reg = 0x79004, + .enable_mask = BIT(22), + .hw.init = &(struct clk_init_data){ + .name = "gcc_cpuss_gnoc_clk", + .flags = CLK_IS_CRITICAL, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_disp_ahb_clk = { + .halt_reg = 0x1700c, + .halt_check = BRANCH_HALT, + .hwcg_reg = 0x1700c, + .hwcg_bit = 1, + .clkr = { + .enable_reg = 0x1700c, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_disp_ahb_clk", + .flags = CLK_IS_CRITICAL, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_disp_gpll0_div_clk_src = { + .halt_check = BRANCH_HALT_DELAY, + .clkr = { + .enable_reg = 0x79004, + .enable_mask = BIT(20), + .hw.init = &(struct clk_init_data){ + .name = "gcc_disp_gpll0_div_clk_src", + .parent_hws = (const struct clk_hw*[]){ + &gpll0_out_early.clkr.hw, + }, + .num_parents = 1, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_disp_hf_axi_clk = { + .halt_reg = 0x17020, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x17020, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_disp_hf_axi_clk", + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_disp_throttle_core_clk = { + .halt_reg = 0x17064, + .halt_check = BRANCH_HALT_VOTED, + .clkr = { + .enable_reg = 0x7900c, + .enable_mask = BIT(5), + .hw.init = &(struct clk_init_data){ + .name = "gcc_disp_throttle_core_clk", + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_disp_xo_clk = { + .halt_reg = 0x1702c, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x1702c, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_disp_xo_clk", + .flags = CLK_IS_CRITICAL, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_gp1_clk = { + .halt_reg = 0x4d000, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x4d000, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_gp1_clk", + .parent_hws = (const struct clk_hw*[]){ + &gcc_gp1_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_gp2_clk = { + .halt_reg = 0x4e000, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x4e000, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_gp2_clk", + .parent_hws = (const struct clk_hw*[]){ + &gcc_gp2_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_gp3_clk = { + .halt_reg = 0x4f000, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x4f000, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_gp3_clk", + .parent_hws = (const struct clk_hw*[]){ + &gcc_gp3_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_gpu_cfg_ahb_clk = { + .halt_reg = 0x36004, + .halt_check = BRANCH_HALT, + .hwcg_reg = 0x36004, + .hwcg_bit = 1, + .clkr = { + .enable_reg = 0x36004, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_gpu_cfg_ahb_clk", + .flags = CLK_IS_CRITICAL, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_gpu_gpll0_clk_src = { + .halt_check = BRANCH_HALT_DELAY, + .clkr = { + .enable_reg = 0x79004, + .enable_mask = BIT(15), + .hw.init = &(struct clk_init_data){ + .name = "gcc_gpu_gpll0_clk_src", + .parent_hws = (const struct clk_hw*[]){ + &gpll0_out_early.clkr.hw, + }, + .num_parents = 1, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_gpu_gpll0_div_clk_src = { + .halt_check = BRANCH_HALT_DELAY, + .clkr = { + .enable_reg = 0x79004, + .enable_mask = BIT(16), + .hw.init = &(struct clk_init_data){ + .name = "gcc_gpu_gpll0_div_clk_src", + .parent_hws = (const struct clk_hw*[]){ + &gpll0_out_aux2.hw, + }, + .num_parents = 1, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_gpu_memnoc_gfx_clk = { + .halt_reg = 0x3600c, + .halt_check = BRANCH_VOTED, + .clkr = { + .enable_reg = 0x3600c, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_gpu_memnoc_gfx_clk", + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_gpu_snoc_dvm_gfx_clk = { + .halt_reg = 0x36018, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x36018, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_gpu_snoc_dvm_gfx_clk", + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_gpu_throttle_core_clk = { + .halt_reg = 0x36048, + .halt_check = BRANCH_HALT_VOTED, + .clkr = { + .enable_reg = 0x79004, + .enable_mask = BIT(31), + .hw.init = &(struct clk_init_data){ + .name = "gcc_gpu_throttle_core_clk", + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_gpu_throttle_xo_clk = { + .halt_reg = 0x36044, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x36044, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_gpu_throttle_xo_clk", + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_mss_vs_clk = { + .halt_reg = 0x42048, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x42048, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_mss_vs_clk", + .parent_hws = (const struct clk_hw*[]){ + &gcc_vsensor_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_pdm2_clk = { + .halt_reg = 0x2000c, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x2000c, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_pdm2_clk", + .parent_hws = (const struct clk_hw*[]){ + &gcc_pdm2_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_pdm_ahb_clk = { + .halt_reg = 0x20004, + .halt_check = BRANCH_HALT, + .hwcg_reg = 0x20004, + .hwcg_bit = 1, + .clkr = { + .enable_reg = 0x20004, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_pdm_ahb_clk", + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_pdm_xo4_clk = { + .halt_reg = 0x20008, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x20008, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_pdm_xo4_clk", + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_prng_ahb_clk = { + .halt_reg = 0x21004, + .halt_check = BRANCH_HALT_VOTED, + .hwcg_reg = 0x21004, + .hwcg_bit = 1, + .clkr = { + .enable_reg = 0x79004, + .enable_mask = BIT(13), + .hw.init = &(struct clk_init_data){ + .name = "gcc_prng_ahb_clk", + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_qmip_camera_nrt_ahb_clk = { + .halt_reg = 0x17014, + .halt_check = BRANCH_HALT, + .hwcg_reg = 0x17014, + .hwcg_bit = 1, + .clkr = { + .enable_reg = 0x7900c, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_qmip_camera_nrt_ahb_clk", + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_qmip_camera_rt_ahb_clk = { + .halt_reg = 0x17060, + .halt_check = BRANCH_HALT_VOTED, + .hwcg_reg = 0x17060, + .hwcg_bit = 1, + .clkr = { + .enable_reg = 0x7900c, + .enable_mask = BIT(2), + .hw.init = &(struct clk_init_data){ + .name = "gcc_qmip_camera_rt_ahb_clk", + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_qmip_disp_ahb_clk = { + .halt_reg = 0x17018, + .halt_check = BRANCH_HALT, + .hwcg_reg = 0x17018, + .hwcg_bit = 1, + .clkr = { + .enable_reg = 0x7900c, + .enable_mask = BIT(1), + .hw.init = &(struct clk_init_data){ + .name = "gcc_qmip_disp_ahb_clk", + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_qmip_gpu_cfg_ahb_clk = { + .halt_reg = 0x36040, + .halt_check = BRANCH_HALT_VOTED, + .hwcg_reg = 0x36040, + .hwcg_bit = 1, + .clkr = { + .enable_reg = 0x7900c, + .enable_mask = BIT(4), + .hw.init = &(struct clk_init_data){ + .name = "gcc_qmip_gpu_cfg_ahb_clk", + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_qmip_video_vcodec_ahb_clk = { + .halt_reg = 0x17010, + .halt_check = BRANCH_HALT, + .hwcg_reg = 0x17010, + .hwcg_bit = 1, + .clkr = { + .enable_reg = 0x79004, + .enable_mask = BIT(25), + .hw.init = &(struct clk_init_data){ + .name = "gcc_qmip_video_vcodec_ahb_clk", + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_qupv3_wrap0_core_2x_clk = { + .halt_reg = 0x1f014, + .halt_check = BRANCH_HALT_VOTED, + .clkr = { + .enable_reg = 0x7900c, + .enable_mask = BIT(9), + .hw.init = &(struct clk_init_data){ + .name = "gcc_qupv3_wrap0_core_2x_clk", + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_qupv3_wrap0_core_clk = { + .halt_reg = 0x1f00c, + .halt_check = BRANCH_HALT_VOTED, + .clkr = { + .enable_reg = 0x7900c, + .enable_mask = BIT(8), + .hw.init = &(struct clk_init_data){ + .name = "gcc_qupv3_wrap0_core_clk", + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_qupv3_wrap0_s0_clk = { + .halt_reg = 0x1f144, + .halt_check = BRANCH_HALT_VOTED, + .clkr = { + .enable_reg = 0x7900c, + .enable_mask = BIT(10), + .hw.init = &(struct clk_init_data){ + .name = "gcc_qupv3_wrap0_s0_clk", + .parent_hws = (const struct clk_hw*[]){ + &gcc_qupv3_wrap0_s0_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_qupv3_wrap0_s1_clk = { + .halt_reg = 0x1f274, + .halt_check = BRANCH_HALT_VOTED, + .clkr = { + .enable_reg = 0x7900c, + .enable_mask = BIT(11), + .hw.init = &(struct clk_init_data){ + .name = "gcc_qupv3_wrap0_s1_clk", + .parent_hws = (const struct clk_hw*[]){ + &gcc_qupv3_wrap0_s1_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_qupv3_wrap0_s2_clk = { + .halt_reg = 0x1f3a4, + .halt_check = BRANCH_HALT_VOTED, + .clkr = { + .enable_reg = 0x7900c, + .enable_mask = BIT(12), + .hw.init = &(struct clk_init_data){ + .name = "gcc_qupv3_wrap0_s2_clk", + .parent_hws = (const struct clk_hw*[]){ + &gcc_qupv3_wrap0_s2_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_qupv3_wrap0_s3_clk = { + .halt_reg = 0x1f4d4, + .halt_check = BRANCH_HALT_VOTED, + .clkr = { + .enable_reg = 0x7900c, + .enable_mask = BIT(13), + .hw.init = &(struct clk_init_data){ + .name = "gcc_qupv3_wrap0_s3_clk", + .parent_hws = (const struct clk_hw*[]){ + &gcc_qupv3_wrap0_s3_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_qupv3_wrap0_s4_clk = { + .halt_reg = 0x1f604, + .halt_check = BRANCH_HALT_VOTED, + .clkr = { + .enable_reg = 0x7900c, + .enable_mask = BIT(14), + .hw.init = &(struct clk_init_data){ + .name = "gcc_qupv3_wrap0_s4_clk", + .parent_hws = (const struct clk_hw*[]){ + &gcc_qupv3_wrap0_s4_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_qupv3_wrap0_s5_clk = { + .halt_reg = 0x1f734, + .halt_check = BRANCH_HALT_VOTED, + .clkr = { + .enable_reg = 0x7900c, + .enable_mask = BIT(15), + .hw.init = &(struct clk_init_data){ + .name = "gcc_qupv3_wrap0_s5_clk", + .parent_hws = (const struct clk_hw*[]){ + &gcc_qupv3_wrap0_s5_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_qupv3_wrap1_core_2x_clk = { + .halt_reg = 0x39014, + .halt_check = BRANCH_HALT_VOTED, + .clkr = { + .enable_reg = 0x7900c, + .enable_mask = BIT(18), + .hw.init = &(struct clk_init_data){ + .name = "gcc_qupv3_wrap1_core_2x_clk", + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_qupv3_wrap1_core_clk = { + .halt_reg = 0x3900c, + .halt_check = BRANCH_HALT_VOTED, + .clkr = { + .enable_reg = 0x7900c, + .enable_mask = BIT(19), + .hw.init = &(struct clk_init_data){ + .name = "gcc_qupv3_wrap1_core_clk", + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_qupv3_wrap1_s0_clk = { + .halt_reg = 0x39144, + .halt_check = BRANCH_HALT_VOTED, + .clkr = { + .enable_reg = 0x7900c, + .enable_mask = BIT(22), + .hw.init = &(struct clk_init_data){ + .name = "gcc_qupv3_wrap1_s0_clk", + .parent_hws = (const struct clk_hw*[]){ + &gcc_qupv3_wrap1_s0_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_qupv3_wrap1_s1_clk = { + .halt_reg = 0x39274, + .halt_check = BRANCH_HALT_VOTED, + .clkr = { + .enable_reg = 0x7900c, + .enable_mask = BIT(23), + .hw.init = &(struct clk_init_data){ + .name = "gcc_qupv3_wrap1_s1_clk", + .parent_hws = (const struct clk_hw*[]){ + &gcc_qupv3_wrap1_s1_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_qupv3_wrap1_s2_clk = { + .halt_reg = 0x393a4, + .halt_check = BRANCH_HALT_VOTED, + .clkr = { + .enable_reg = 0x7900c, + .enable_mask = BIT(24), + .hw.init = &(struct clk_init_data){ + .name = "gcc_qupv3_wrap1_s2_clk", + .parent_hws = (const struct clk_hw*[]){ + &gcc_qupv3_wrap1_s2_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_qupv3_wrap1_s3_clk = { + .halt_reg = 0x394d4, + .halt_check = BRANCH_HALT_VOTED, + .clkr = { + .enable_reg = 0x7900c, + .enable_mask = BIT(25), + .hw.init = &(struct clk_init_data){ + .name = "gcc_qupv3_wrap1_s3_clk", + .parent_hws = (const struct clk_hw*[]){ + &gcc_qupv3_wrap1_s3_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_qupv3_wrap1_s4_clk = { + .halt_reg = 0x39604, + .halt_check = BRANCH_HALT_VOTED, + .clkr = { + .enable_reg = 0x7900c, + .enable_mask = BIT(26), + .hw.init = &(struct clk_init_data){ + .name = "gcc_qupv3_wrap1_s4_clk", + .parent_hws = (const struct clk_hw*[]){ + &gcc_qupv3_wrap1_s4_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_qupv3_wrap1_s5_clk = { + .halt_reg = 0x39734, + .halt_check = BRANCH_HALT_VOTED, + .clkr = { + .enable_reg = 0x7900c, + .enable_mask = BIT(27), + .hw.init = &(struct clk_init_data){ + .name = "gcc_qupv3_wrap1_s5_clk", + .parent_hws = (const struct clk_hw*[]){ + &gcc_qupv3_wrap1_s5_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_qupv3_wrap_0_m_ahb_clk = { + .halt_reg = 0x1f004, + .halt_check = BRANCH_HALT_VOTED, + .clkr = { + .enable_reg = 0x7900c, + .enable_mask = BIT(6), + .hw.init = &(struct clk_init_data){ + .name = "gcc_qupv3_wrap_0_m_ahb_clk", + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_qupv3_wrap_0_s_ahb_clk = { + .halt_reg = 0x1f008, + .halt_check = BRANCH_HALT_VOTED, + .hwcg_reg = 0x1f008, + .hwcg_bit = 1, + .clkr = { + .enable_reg = 0x7900c, + .enable_mask = BIT(7), + .hw.init = &(struct clk_init_data){ + .name = "gcc_qupv3_wrap_0_s_ahb_clk", + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_qupv3_wrap_1_m_ahb_clk = { + .halt_reg = 0x39004, + .halt_check = BRANCH_HALT_VOTED, + .clkr = { + .enable_reg = 0x7900c, + .enable_mask = BIT(20), + .hw.init = &(struct clk_init_data){ + .name = "gcc_qupv3_wrap_1_m_ahb_clk", + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_qupv3_wrap_1_s_ahb_clk = { + .halt_reg = 0x39008, + .halt_check = BRANCH_HALT_VOTED, + .hwcg_reg = 0x39008, + .hwcg_bit = 1, + .clkr = { + .enable_reg = 0x7900c, + .enable_mask = BIT(21), + .hw.init = &(struct clk_init_data){ + .name = "gcc_qupv3_wrap_1_s_ahb_clk", + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_sdcc1_ahb_clk = { + .halt_reg = 0x38008, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x38008, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_sdcc1_ahb_clk", + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_sdcc1_apps_clk = { + .halt_reg = 0x38004, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x38004, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_sdcc1_apps_clk", + .parent_hws = (const struct clk_hw*[]){ + &gcc_sdcc1_apps_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_sdcc1_ice_core_clk = { + .halt_reg = 0x3800c, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x3800c, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_sdcc1_ice_core_clk", + .parent_hws = (const struct clk_hw*[]){ + &gcc_sdcc1_ice_core_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_sdcc2_ahb_clk = { + .halt_reg = 0x1e008, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x1e008, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_sdcc2_ahb_clk", + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_sdcc2_apps_clk = { + .halt_reg = 0x1e004, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x1e004, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_sdcc2_apps_clk", + .parent_hws = (const struct clk_hw*[]){ + &gcc_sdcc2_apps_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_sys_noc_compute_sf_axi_clk = { + .halt_reg = 0x1050c, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x1050c, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_sys_noc_compute_sf_axi_clk", + .flags = CLK_IS_CRITICAL, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_sys_noc_cpuss_ahb_clk = { + .halt_reg = 0x2b06c, + .halt_check = BRANCH_HALT_VOTED, + .clkr = { + .enable_reg = 0x79004, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_sys_noc_cpuss_ahb_clk", + .flags = CLK_IS_CRITICAL, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_sys_noc_ufs_phy_axi_clk = { + .halt_reg = 0x45098, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x45098, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_sys_noc_ufs_phy_axi_clk", + .parent_hws = (const struct clk_hw*[]){ + &gcc_ufs_phy_axi_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_sys_noc_usb3_prim_axi_clk = { + .halt_reg = 0x1a080, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x1a080, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_sys_noc_usb3_prim_axi_clk", + .parent_hws = (const struct clk_hw*[]){ + &gcc_usb30_prim_master_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_ufs_mem_clkref_clk = { + .halt_reg = 0x8c000, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x8c000, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_ufs_mem_clkref_clk", + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_ufs_phy_ahb_clk = { + .halt_reg = 0x45014, + .halt_check = BRANCH_HALT, + .hwcg_reg = 0x45014, + .hwcg_bit = 1, + .clkr = { + .enable_reg = 0x45014, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_ufs_phy_ahb_clk", + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_ufs_phy_axi_clk = { + .halt_reg = 0x45010, + .halt_check = BRANCH_HALT, + .hwcg_reg = 0x45010, + .hwcg_bit = 1, + .clkr = { + .enable_reg = 0x45010, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_ufs_phy_axi_clk", + .parent_hws = (const struct clk_hw*[]){ + &gcc_ufs_phy_axi_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_ufs_phy_ice_core_clk = { + .halt_reg = 0x45044, + .halt_check = BRANCH_HALT, + .hwcg_reg = 0x45044, + .hwcg_bit = 1, + .clkr = { + .enable_reg = 0x45044, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_ufs_phy_ice_core_clk", + .parent_hws = (const struct clk_hw*[]){ + &gcc_ufs_phy_ice_core_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_ufs_phy_phy_aux_clk = { + .halt_reg = 0x45078, + .halt_check = BRANCH_HALT, + .hwcg_reg = 0x45078, + .hwcg_bit = 1, + .clkr = { + .enable_reg = 0x45078, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_ufs_phy_phy_aux_clk", + .parent_hws = (const struct clk_hw*[]){ + &gcc_ufs_phy_phy_aux_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_ufs_phy_rx_symbol_0_clk = { + .halt_reg = 0x4501c, + .halt_check = BRANCH_HALT_SKIP, + .clkr = { + .enable_reg = 0x4501c, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_ufs_phy_rx_symbol_0_clk", + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_ufs_phy_tx_symbol_0_clk = { + .halt_reg = 0x45018, + .halt_check = BRANCH_HALT_SKIP, + .clkr = { + .enable_reg = 0x45018, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_ufs_phy_tx_symbol_0_clk", + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_ufs_phy_unipro_core_clk = { + .halt_reg = 0x45040, + .halt_check = BRANCH_HALT, + .hwcg_reg = 0x45040, + .hwcg_bit = 1, + .clkr = { + .enable_reg = 0x45040, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_ufs_phy_unipro_core_clk", + .parent_hws = (const struct clk_hw*[]){ + &gcc_ufs_phy_unipro_core_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_usb30_prim_master_clk = { + .halt_reg = 0x1a010, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x1a010, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_usb30_prim_master_clk", + .parent_hws = (const struct clk_hw*[]){ + &gcc_usb30_prim_master_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_usb30_prim_mock_utmi_clk = { + .halt_reg = 0x1a018, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x1a018, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_usb30_prim_mock_utmi_clk", + .parent_hws = (const struct clk_hw*[]){ + &gcc_usb30_prim_mock_utmi_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_usb30_prim_sleep_clk = { + .halt_reg = 0x1a014, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x1a014, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_usb30_prim_sleep_clk", + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_usb3_prim_clkref_clk = { + .halt_reg = 0x80278, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x80278, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_usb3_prim_clkref_clk", + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_usb3_prim_phy_com_aux_clk = { + .halt_reg = 0x1a054, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x1a054, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_usb3_prim_phy_com_aux_clk", + .parent_hws = (const struct clk_hw*[]){ + &gcc_usb3_prim_phy_aux_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_usb3_prim_phy_pipe_clk = { + .halt_check = BRANCH_HALT_SKIP, + .clkr = { + .enable_reg = 0x1a058, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_usb3_prim_phy_pipe_clk", + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_vdda_vs_clk = { + .halt_reg = 0x4200c, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x4200c, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_vdda_vs_clk", + .parent_hws = (const struct clk_hw*[]){ + &gcc_vsensor_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_vddcx_vs_clk = { + .halt_reg = 0x42004, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x42004, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_vddcx_vs_clk", + .parent_hws = (const struct clk_hw*[]){ + &gcc_vsensor_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_vddmx_vs_clk = { + .halt_reg = 0x42008, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x42008, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_vddmx_vs_clk", + .parent_hws = (const struct clk_hw*[]){ + &gcc_vsensor_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_video_ahb_clk = { + .halt_reg = 0x17004, + .halt_check = BRANCH_HALT, + .hwcg_reg = 0x17004, + .hwcg_bit = 1, + .clkr = { + .enable_reg = 0x17004, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_video_ahb_clk", + .flags = CLK_IS_CRITICAL, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_video_axi0_clk = { + .halt_reg = 0x1701c, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x1701c, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_video_axi0_clk", + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_video_throttle_core_clk = { + .halt_reg = 0x17068, + .halt_check = BRANCH_HALT_VOTED, + .clkr = { + .enable_reg = 0x79004, + .enable_mask = BIT(28), + .hw.init = &(struct clk_init_data){ + .name = "gcc_video_throttle_core_clk", + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_video_xo_clk = { + .halt_reg = 0x17024, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x17024, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_video_xo_clk", + .flags = CLK_IS_CRITICAL, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_vs_ctrl_ahb_clk = { + .halt_reg = 0x42014, + .halt_check = BRANCH_HALT, + .hwcg_reg = 0x42014, + .hwcg_bit = 1, + .clkr = { + .enable_reg = 0x42014, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_vs_ctrl_ahb_clk", + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_vs_ctrl_clk = { + .halt_reg = 0x42010, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x42010, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_vs_ctrl_clk", + .parent_hws = (const struct clk_hw*[]){ + &gcc_vs_ctrl_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_wcss_vs_clk = { + .halt_reg = 0x42050, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x42050, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_wcss_vs_clk", + .parent_hws = (const struct clk_hw*[]){ + &gcc_vsensor_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct gdsc usb30_prim_gdsc = { + .gdscr = 0x1a004, + .pd = { + .name = "usb30_prim_gdsc", + }, + .pwrsts = PWRSTS_OFF_ON, +}; + +static struct gdsc ufs_phy_gdsc = { + .gdscr = 0x45004, + .pd = { + .name = "ufs_phy_gdsc", + }, + .pwrsts = PWRSTS_OFF_ON, +}; + +static struct gdsc camss_vfe0_gdsc = { + .gdscr = 0x54004, + .pd = { + .name = "camss_vfe0_gdsc", + }, + .pwrsts = PWRSTS_OFF_ON, +}; + +static struct gdsc camss_vfe1_gdsc = { + .gdscr = 0x5403c, + .pd = { + .name = "camss_vfe1_gdsc", + }, + .pwrsts = PWRSTS_OFF_ON, +}; + +static struct gdsc camss_top_gdsc = { + .gdscr = 0x5607c, + .pd = { + .name = "camss_top_gdsc", + }, + .pwrsts = PWRSTS_OFF_ON, +}; + +static struct gdsc cam_cpp_gdsc = { + .gdscr = 0x560bc, + .pd = { + .name = "cam_cpp_gdsc", + }, + .pwrsts = PWRSTS_OFF_ON, +}; + +static struct gdsc hlos1_vote_turing_mmu_tbu1_gdsc = { + .gdscr = 0x7d060, + .pd = { + .name = "hlos1_vote_turing_mmu_tbu1_gdsc", + }, + .pwrsts = PWRSTS_OFF_ON, + .flags = VOTABLE, +}; + +static struct gdsc hlos1_vote_mm_snoc_mmu_tbu_rt_gdsc = { + .gdscr = 0x80074, + .pd = { + .name = "hlos1_vote_mm_snoc_mmu_tbu_rt_gdsc", + }, + .pwrsts = PWRSTS_OFF_ON, + .flags = VOTABLE, +}; + +static struct gdsc hlos1_vote_mm_snoc_mmu_tbu_nrt_gdsc = { + .gdscr = 0x80084, + .pd = { + .name = "hlos1_vote_mm_snoc_mmu_tbu_nrt_gdsc", + }, + .pwrsts = PWRSTS_OFF_ON, + .flags = VOTABLE, +}; + + +static struct gdsc hlos1_vote_turing_mmu_tbu0_gdsc = { + .gdscr = 0x80094, + .pd = { + .name = "hlos1_vote_turing_mmu_tbu0_gdsc", + }, + .pwrsts = PWRSTS_OFF_ON, + .flags = VOTABLE, +}; + +static struct gdsc *gcc_sm6125_gdscs[] = { + [USB30_PRIM_GDSC] = &usb30_prim_gdsc, + [UFS_PHY_GDSC] = &ufs_phy_gdsc, + [CAMSS_VFE0_GDSC] = &camss_vfe0_gdsc, + [CAMSS_VFE1_GDSC] = &camss_vfe1_gdsc, + [CAMSS_TOP_GDSC] = &camss_top_gdsc, + [CAM_CPP_GDSC] = &cam_cpp_gdsc, + [HLOS1_VOTE_TURING_MMU_TBU1_GDSC] = &hlos1_vote_turing_mmu_tbu1_gdsc, + [HLOS1_VOTE_MM_SNOC_MMU_TBU_RT_GDSC] = &hlos1_vote_mm_snoc_mmu_tbu_rt_gdsc, + [HLOS1_VOTE_MM_SNOC_MMU_TBU_NRT_GDSC] = &hlos1_vote_mm_snoc_mmu_tbu_nrt_gdsc, + [HLOS1_VOTE_TURING_MMU_TBU0_GDSC] = &hlos1_vote_turing_mmu_tbu0_gdsc, +}; + +static struct clk_hw *gcc_sm6125_hws[] = { + [GPLL0_OUT_AUX2] = &gpll0_out_aux2.hw, + [GPLL0_OUT_MAIN] = &gpll0_out_main.hw, + [GPLL6_OUT_MAIN] = &gpll6_out_main.hw, + [GPLL7_OUT_MAIN] = &gpll7_out_main.hw, + [GPLL8_OUT_MAIN] = &gpll8_out_main.hw, + [GPLL9_OUT_MAIN] = &gpll9_out_main.hw, +}; + +static struct clk_regmap *gcc_sm6125_clocks[] = { + [GCC_AHB2PHY_CSI_CLK] = &gcc_ahb2phy_csi_clk.clkr, + [GCC_AHB2PHY_USB_CLK] = &gcc_ahb2phy_usb_clk.clkr, + [GCC_APC_VS_CLK] = &gcc_apc_vs_clk.clkr, + [GCC_BIMC_GPU_AXI_CLK] = &gcc_bimc_gpu_axi_clk.clkr, + [GCC_BOOT_ROM_AHB_CLK] = &gcc_boot_rom_ahb_clk.clkr, + [GCC_CAMERA_AHB_CLK] = &gcc_camera_ahb_clk.clkr, + [GCC_CAMERA_XO_CLK] = &gcc_camera_xo_clk.clkr, + [GCC_CAMSS_AHB_CLK_SRC] = &gcc_camss_ahb_clk_src.clkr, + [GCC_CAMSS_CCI_AHB_CLK] = &gcc_camss_cci_ahb_clk.clkr, + [GCC_CAMSS_CCI_CLK] = &gcc_camss_cci_clk.clkr, + [GCC_CAMSS_CCI_CLK_SRC] = &gcc_camss_cci_clk_src.clkr, + [GCC_CAMSS_CPHY_CSID0_CLK] = &gcc_camss_cphy_csid0_clk.clkr, + [GCC_CAMSS_CPHY_CSID1_CLK] = &gcc_camss_cphy_csid1_clk.clkr, + [GCC_CAMSS_CPHY_CSID2_CLK] = &gcc_camss_cphy_csid2_clk.clkr, + [GCC_CAMSS_CPHY_CSID3_CLK] = &gcc_camss_cphy_csid3_clk.clkr, + [GCC_CAMSS_CPP_AHB_CLK] = &gcc_camss_cpp_ahb_clk.clkr, + [GCC_CAMSS_CPP_AXI_CLK] = &gcc_camss_cpp_axi_clk.clkr, + [GCC_CAMSS_CPP_CLK] = &gcc_camss_cpp_clk.clkr, + [GCC_CAMSS_CPP_CLK_SRC] = &gcc_camss_cpp_clk_src.clkr, + [GCC_CAMSS_CPP_VBIF_AHB_CLK] = &gcc_camss_cpp_vbif_ahb_clk.clkr, + [GCC_CAMSS_CSI0_AHB_CLK] = &gcc_camss_csi0_ahb_clk.clkr, + [GCC_CAMSS_CSI0_CLK] = &gcc_camss_csi0_clk.clkr, + [GCC_CAMSS_CSI0_CLK_SRC] = &gcc_camss_csi0_clk_src.clkr, + [GCC_CAMSS_CSI0PHYTIMER_CLK] = &gcc_camss_csi0phytimer_clk.clkr, + [GCC_CAMSS_CSI0PHYTIMER_CLK_SRC] = &gcc_camss_csi0phytimer_clk_src.clkr, + [GCC_CAMSS_CSI0PIX_CLK] = &gcc_camss_csi0pix_clk.clkr, + [GCC_CAMSS_CSI0RDI_CLK] = &gcc_camss_csi0rdi_clk.clkr, + [GCC_CAMSS_CSI1_AHB_CLK] = &gcc_camss_csi1_ahb_clk.clkr, + [GCC_CAMSS_CSI1_CLK] = &gcc_camss_csi1_clk.clkr, + [GCC_CAMSS_CSI1_CLK_SRC] = &gcc_camss_csi1_clk_src.clkr, + [GCC_CAMSS_CSI1PHYTIMER_CLK] = &gcc_camss_csi1phytimer_clk.clkr, + [GCC_CAMSS_CSI1PHYTIMER_CLK_SRC] = &gcc_camss_csi1phytimer_clk_src.clkr, + [GCC_CAMSS_CSI1PIX_CLK] = &gcc_camss_csi1pix_clk.clkr, + [GCC_CAMSS_CSI1RDI_CLK] = &gcc_camss_csi1rdi_clk.clkr, + [GCC_CAMSS_CSI2_AHB_CLK] = &gcc_camss_csi2_ahb_clk.clkr, + [GCC_CAMSS_CSI2_CLK] = &gcc_camss_csi2_clk.clkr, + [GCC_CAMSS_CSI2_CLK_SRC] = &gcc_camss_csi2_clk_src.clkr, + [GCC_CAMSS_CSI2PHYTIMER_CLK] = &gcc_camss_csi2phytimer_clk.clkr, + [GCC_CAMSS_CSI2PHYTIMER_CLK_SRC] = &gcc_camss_csi2phytimer_clk_src.clkr, + [GCC_CAMSS_CSI2PIX_CLK] = &gcc_camss_csi2pix_clk.clkr, + [GCC_CAMSS_CSI2RDI_CLK] = &gcc_camss_csi2rdi_clk.clkr, + [GCC_CAMSS_CSI3_AHB_CLK] = &gcc_camss_csi3_ahb_clk.clkr, + [GCC_CAMSS_CSI3_CLK] = &gcc_camss_csi3_clk.clkr, + [GCC_CAMSS_CSI3_CLK_SRC] = &gcc_camss_csi3_clk_src.clkr, + [GCC_CAMSS_CSI3PIX_CLK] = &gcc_camss_csi3pix_clk.clkr, + [GCC_CAMSS_CSI3RDI_CLK] = &gcc_camss_csi3rdi_clk.clkr, + [GCC_CAMSS_CSI_VFE0_CLK] = &gcc_camss_csi_vfe0_clk.clkr, + [GCC_CAMSS_CSI_VFE1_CLK] = &gcc_camss_csi_vfe1_clk.clkr, + [GCC_CAMSS_CSIPHY0_CLK] = &gcc_camss_csiphy0_clk.clkr, + [GCC_CAMSS_CSIPHY1_CLK] = &gcc_camss_csiphy1_clk.clkr, + [GCC_CAMSS_CSIPHY2_CLK] = &gcc_camss_csiphy2_clk.clkr, + [GCC_CAMSS_CSIPHY_CLK_SRC] = &gcc_camss_csiphy_clk_src.clkr, + [GCC_CAMSS_GP0_CLK] = &gcc_camss_gp0_clk.clkr, + [GCC_CAMSS_GP0_CLK_SRC] = &gcc_camss_gp0_clk_src.clkr, + [GCC_CAMSS_GP1_CLK] = &gcc_camss_gp1_clk.clkr, + [GCC_CAMSS_GP1_CLK_SRC] = &gcc_camss_gp1_clk_src.clkr, + [GCC_CAMSS_ISPIF_AHB_CLK] = &gcc_camss_ispif_ahb_clk.clkr, + [GCC_CAMSS_JPEG_AHB_CLK] = &gcc_camss_jpeg_ahb_clk.clkr, + [GCC_CAMSS_JPEG_AXI_CLK] = &gcc_camss_jpeg_axi_clk.clkr, + [GCC_CAMSS_JPEG_CLK] = &gcc_camss_jpeg_clk.clkr, + [GCC_CAMSS_JPEG_CLK_SRC] = &gcc_camss_jpeg_clk_src.clkr, + [GCC_CAMSS_MCLK0_CLK] = &gcc_camss_mclk0_clk.clkr, + [GCC_CAMSS_MCLK0_CLK_SRC] = &gcc_camss_mclk0_clk_src.clkr, + [GCC_CAMSS_MCLK1_CLK] = &gcc_camss_mclk1_clk.clkr, + [GCC_CAMSS_MCLK1_CLK_SRC] = &gcc_camss_mclk1_clk_src.clkr, + [GCC_CAMSS_MCLK2_CLK] = &gcc_camss_mclk2_clk.clkr, + [GCC_CAMSS_MCLK2_CLK_SRC] = &gcc_camss_mclk2_clk_src.clkr, + [GCC_CAMSS_MCLK3_CLK] = &gcc_camss_mclk3_clk.clkr, + [GCC_CAMSS_MCLK3_CLK_SRC] = &gcc_camss_mclk3_clk_src.clkr, + [GCC_CAMSS_MICRO_AHB_CLK] = &gcc_camss_micro_ahb_clk.clkr, + [GCC_CAMSS_THROTTLE_NRT_AXI_CLK] = &gcc_camss_throttle_nrt_axi_clk.clkr, + [GCC_CAMSS_THROTTLE_RT_AXI_CLK] = &gcc_camss_throttle_rt_axi_clk.clkr, + [GCC_CAMSS_TOP_AHB_CLK] = &gcc_camss_top_ahb_clk.clkr, + [GCC_CAMSS_VFE0_AHB_CLK] = &gcc_camss_vfe0_ahb_clk.clkr, + [GCC_CAMSS_VFE0_CLK] = &gcc_camss_vfe0_clk.clkr, + [GCC_CAMSS_VFE0_CLK_SRC] = &gcc_camss_vfe0_clk_src.clkr, + [GCC_CAMSS_VFE0_STREAM_CLK] = &gcc_camss_vfe0_stream_clk.clkr, + [GCC_CAMSS_VFE1_AHB_CLK] = &gcc_camss_vfe1_ahb_clk.clkr, + [GCC_CAMSS_VFE1_CLK] = &gcc_camss_vfe1_clk.clkr, + [GCC_CAMSS_VFE1_CLK_SRC] = &gcc_camss_vfe1_clk_src.clkr, + [GCC_CAMSS_VFE1_STREAM_CLK] = &gcc_camss_vfe1_stream_clk.clkr, + [GCC_CAMSS_VFE_TSCTR_CLK] = &gcc_camss_vfe_tsctr_clk.clkr, + [GCC_CAMSS_VFE_VBIF_AHB_CLK] = &gcc_camss_vfe_vbif_ahb_clk.clkr, + [GCC_CAMSS_VFE_VBIF_AXI_CLK] = &gcc_camss_vfe_vbif_axi_clk.clkr, + [GCC_CE1_AHB_CLK] = &gcc_ce1_ahb_clk.clkr, + [GCC_CE1_AXI_CLK] = &gcc_ce1_axi_clk.clkr, + [GCC_CE1_CLK] = &gcc_ce1_clk.clkr, + [GCC_CFG_NOC_USB3_PRIM_AXI_CLK] = &gcc_cfg_noc_usb3_prim_axi_clk.clkr, + [GCC_CPUSS_GNOC_CLK] = &gcc_cpuss_gnoc_clk.clkr, + [GCC_DISP_AHB_CLK] = &gcc_disp_ahb_clk.clkr, + [GCC_DISP_GPLL0_DIV_CLK_SRC] = &gcc_disp_gpll0_div_clk_src.clkr, + [GCC_DISP_HF_AXI_CLK] = &gcc_disp_hf_axi_clk.clkr, + [GCC_DISP_THROTTLE_CORE_CLK] = &gcc_disp_throttle_core_clk.clkr, + [GCC_DISP_XO_CLK] = &gcc_disp_xo_clk.clkr, + [GCC_GP1_CLK] = &gcc_gp1_clk.clkr, + [GCC_GP1_CLK_SRC] = &gcc_gp1_clk_src.clkr, + [GCC_GP2_CLK] = &gcc_gp2_clk.clkr, + [GCC_GP2_CLK_SRC] = &gcc_gp2_clk_src.clkr, + [GCC_GP3_CLK] = &gcc_gp3_clk.clkr, + [GCC_GP3_CLK_SRC] = &gcc_gp3_clk_src.clkr, + [GCC_GPU_CFG_AHB_CLK] = &gcc_gpu_cfg_ahb_clk.clkr, + [GCC_GPU_GPLL0_CLK_SRC] = &gcc_gpu_gpll0_clk_src.clkr, + [GCC_GPU_GPLL0_DIV_CLK_SRC] = &gcc_gpu_gpll0_div_clk_src.clkr, + [GCC_GPU_MEMNOC_GFX_CLK] = &gcc_gpu_memnoc_gfx_clk.clkr, + [GCC_GPU_SNOC_DVM_GFX_CLK] = &gcc_gpu_snoc_dvm_gfx_clk.clkr, + [GCC_GPU_THROTTLE_CORE_CLK] = &gcc_gpu_throttle_core_clk.clkr, + [GCC_GPU_THROTTLE_XO_CLK] = &gcc_gpu_throttle_xo_clk.clkr, + [GCC_MSS_VS_CLK] = &gcc_mss_vs_clk.clkr, + [GCC_PDM2_CLK] = &gcc_pdm2_clk.clkr, + [GCC_PDM2_CLK_SRC] = &gcc_pdm2_clk_src.clkr, + [GCC_PDM_AHB_CLK] = &gcc_pdm_ahb_clk.clkr, + [GCC_PDM_XO4_CLK] = &gcc_pdm_xo4_clk.clkr, + [GCC_PRNG_AHB_CLK] = &gcc_prng_ahb_clk.clkr, + [GCC_QMIP_CAMERA_NRT_AHB_CLK] = &gcc_qmip_camera_nrt_ahb_clk.clkr, + [GCC_QMIP_CAMERA_RT_AHB_CLK] = &gcc_qmip_camera_rt_ahb_clk.clkr, + [GCC_QMIP_DISP_AHB_CLK] = &gcc_qmip_disp_ahb_clk.clkr, + [GCC_QMIP_GPU_CFG_AHB_CLK] = &gcc_qmip_gpu_cfg_ahb_clk.clkr, + [GCC_QMIP_VIDEO_VCODEC_AHB_CLK] = &gcc_qmip_video_vcodec_ahb_clk.clkr, + [GCC_QUPV3_WRAP0_CORE_2X_CLK] = &gcc_qupv3_wrap0_core_2x_clk.clkr, + [GCC_QUPV3_WRAP0_CORE_CLK] = &gcc_qupv3_wrap0_core_clk.clkr, + [GCC_QUPV3_WRAP0_S0_CLK] = &gcc_qupv3_wrap0_s0_clk.clkr, + [GCC_QUPV3_WRAP0_S0_CLK_SRC] = &gcc_qupv3_wrap0_s0_clk_src.clkr, + [GCC_QUPV3_WRAP0_S1_CLK] = &gcc_qupv3_wrap0_s1_clk.clkr, + [GCC_QUPV3_WRAP0_S1_CLK_SRC] = &gcc_qupv3_wrap0_s1_clk_src.clkr, + [GCC_QUPV3_WRAP0_S2_CLK] = &gcc_qupv3_wrap0_s2_clk.clkr, + [GCC_QUPV3_WRAP0_S2_CLK_SRC] = &gcc_qupv3_wrap0_s2_clk_src.clkr, + [GCC_QUPV3_WRAP0_S3_CLK] = &gcc_qupv3_wrap0_s3_clk.clkr, + [GCC_QUPV3_WRAP0_S3_CLK_SRC] = &gcc_qupv3_wrap0_s3_clk_src.clkr, + [GCC_QUPV3_WRAP0_S4_CLK] = &gcc_qupv3_wrap0_s4_clk.clkr, + [GCC_QUPV3_WRAP0_S4_CLK_SRC] = &gcc_qupv3_wrap0_s4_clk_src.clkr, + [GCC_QUPV3_WRAP0_S5_CLK] = &gcc_qupv3_wrap0_s5_clk.clkr, + [GCC_QUPV3_WRAP0_S5_CLK_SRC] = &gcc_qupv3_wrap0_s5_clk_src.clkr, + [GCC_QUPV3_WRAP1_CORE_2X_CLK] = &gcc_qupv3_wrap1_core_2x_clk.clkr, + [GCC_QUPV3_WRAP1_CORE_CLK] = &gcc_qupv3_wrap1_core_clk.clkr, + [GCC_QUPV3_WRAP1_S0_CLK] = &gcc_qupv3_wrap1_s0_clk.clkr, + [GCC_QUPV3_WRAP1_S0_CLK_SRC] = &gcc_qupv3_wrap1_s0_clk_src.clkr, + [GCC_QUPV3_WRAP1_S1_CLK] = &gcc_qupv3_wrap1_s1_clk.clkr, + [GCC_QUPV3_WRAP1_S1_CLK_SRC] = &gcc_qupv3_wrap1_s1_clk_src.clkr, + [GCC_QUPV3_WRAP1_S2_CLK] = &gcc_qupv3_wrap1_s2_clk.clkr, + [GCC_QUPV3_WRAP1_S2_CLK_SRC] = &gcc_qupv3_wrap1_s2_clk_src.clkr, + [GCC_QUPV3_WRAP1_S3_CLK] = &gcc_qupv3_wrap1_s3_clk.clkr, + [GCC_QUPV3_WRAP1_S3_CLK_SRC] = &gcc_qupv3_wrap1_s3_clk_src.clkr, + [GCC_QUPV3_WRAP1_S4_CLK] = &gcc_qupv3_wrap1_s4_clk.clkr, + [GCC_QUPV3_WRAP1_S4_CLK_SRC] = &gcc_qupv3_wrap1_s4_clk_src.clkr, + [GCC_QUPV3_WRAP1_S5_CLK] = &gcc_qupv3_wrap1_s5_clk.clkr, + [GCC_QUPV3_WRAP1_S5_CLK_SRC] = &gcc_qupv3_wrap1_s5_clk_src.clkr, + [GCC_QUPV3_WRAP_0_M_AHB_CLK] = &gcc_qupv3_wrap_0_m_ahb_clk.clkr, + [GCC_QUPV3_WRAP_0_S_AHB_CLK] = &gcc_qupv3_wrap_0_s_ahb_clk.clkr, + [GCC_QUPV3_WRAP_1_M_AHB_CLK] = &gcc_qupv3_wrap_1_m_ahb_clk.clkr, + [GCC_QUPV3_WRAP_1_S_AHB_CLK] = &gcc_qupv3_wrap_1_s_ahb_clk.clkr, + [GCC_SDCC1_AHB_CLK] = &gcc_sdcc1_ahb_clk.clkr, + [GCC_SDCC1_APPS_CLK] = &gcc_sdcc1_apps_clk.clkr, + [GCC_SDCC1_APPS_CLK_SRC] = &gcc_sdcc1_apps_clk_src.clkr, + [GCC_SDCC1_ICE_CORE_CLK] = &gcc_sdcc1_ice_core_clk.clkr, + [GCC_SDCC1_ICE_CORE_CLK_SRC] = &gcc_sdcc1_ice_core_clk_src.clkr, + [GCC_SDCC2_AHB_CLK] = &gcc_sdcc2_ahb_clk.clkr, + [GCC_SDCC2_APPS_CLK] = &gcc_sdcc2_apps_clk.clkr, + [GCC_SDCC2_APPS_CLK_SRC] = &gcc_sdcc2_apps_clk_src.clkr, + [GCC_SYS_NOC_COMPUTE_SF_AXI_CLK] = &gcc_sys_noc_compute_sf_axi_clk.clkr, + [GCC_SYS_NOC_CPUSS_AHB_CLK] = &gcc_sys_noc_cpuss_ahb_clk.clkr, + [GCC_SYS_NOC_UFS_PHY_AXI_CLK] = &gcc_sys_noc_ufs_phy_axi_clk.clkr, + [GCC_SYS_NOC_USB3_PRIM_AXI_CLK] = &gcc_sys_noc_usb3_prim_axi_clk.clkr, + [GCC_UFS_MEM_CLKREF_CLK] = &gcc_ufs_mem_clkref_clk.clkr, + [GCC_UFS_PHY_AHB_CLK] = &gcc_ufs_phy_ahb_clk.clkr, + [GCC_UFS_PHY_AXI_CLK] = &gcc_ufs_phy_axi_clk.clkr, + [GCC_UFS_PHY_AXI_CLK_SRC] = &gcc_ufs_phy_axi_clk_src.clkr, + [GCC_UFS_PHY_ICE_CORE_CLK] = &gcc_ufs_phy_ice_core_clk.clkr, + [GCC_UFS_PHY_ICE_CORE_CLK_SRC] = &gcc_ufs_phy_ice_core_clk_src.clkr, + [GCC_UFS_PHY_PHY_AUX_CLK] = &gcc_ufs_phy_phy_aux_clk.clkr, + [GCC_UFS_PHY_PHY_AUX_CLK_SRC] = &gcc_ufs_phy_phy_aux_clk_src.clkr, + [GCC_UFS_PHY_RX_SYMBOL_0_CLK] = &gcc_ufs_phy_rx_symbol_0_clk.clkr, + [GCC_UFS_PHY_TX_SYMBOL_0_CLK] = &gcc_ufs_phy_tx_symbol_0_clk.clkr, + [GCC_UFS_PHY_UNIPRO_CORE_CLK] = &gcc_ufs_phy_unipro_core_clk.clkr, + [GCC_UFS_PHY_UNIPRO_CORE_CLK_SRC] = + &gcc_ufs_phy_unipro_core_clk_src.clkr, + [GCC_USB30_PRIM_MASTER_CLK] = &gcc_usb30_prim_master_clk.clkr, + [GCC_USB30_PRIM_MASTER_CLK_SRC] = &gcc_usb30_prim_master_clk_src.clkr, + [GCC_USB30_PRIM_MOCK_UTMI_CLK] = &gcc_usb30_prim_mock_utmi_clk.clkr, + [GCC_USB30_PRIM_MOCK_UTMI_CLK_SRC] = + &gcc_usb30_prim_mock_utmi_clk_src.clkr, + [GCC_USB30_PRIM_SLEEP_CLK] = &gcc_usb30_prim_sleep_clk.clkr, + [GCC_USB3_PRIM_PHY_AUX_CLK_SRC] = &gcc_usb3_prim_phy_aux_clk_src.clkr, + [GCC_USB3_PRIM_PHY_COM_AUX_CLK] = &gcc_usb3_prim_phy_com_aux_clk.clkr, + [GCC_USB3_PRIM_PHY_PIPE_CLK] = &gcc_usb3_prim_phy_pipe_clk.clkr, + [GCC_VDDA_VS_CLK] = &gcc_vdda_vs_clk.clkr, + [GCC_VDDCX_VS_CLK] = &gcc_vddcx_vs_clk.clkr, + [GCC_VDDMX_VS_CLK] = &gcc_vddmx_vs_clk.clkr, + [GCC_VIDEO_AHB_CLK] = &gcc_video_ahb_clk.clkr, + [GCC_VIDEO_AXI0_CLK] = &gcc_video_axi0_clk.clkr, + [GCC_VIDEO_THROTTLE_CORE_CLK] = &gcc_video_throttle_core_clk.clkr, + [GCC_VIDEO_XO_CLK] = &gcc_video_xo_clk.clkr, + [GCC_VS_CTRL_AHB_CLK] = &gcc_vs_ctrl_ahb_clk.clkr, + [GCC_VS_CTRL_CLK] = &gcc_vs_ctrl_clk.clkr, + [GCC_VS_CTRL_CLK_SRC] = &gcc_vs_ctrl_clk_src.clkr, + [GCC_VSENSOR_CLK_SRC] = &gcc_vsensor_clk_src.clkr, + [GCC_WCSS_VS_CLK] = &gcc_wcss_vs_clk.clkr, + [GPLL0_OUT_EARLY] = &gpll0_out_early.clkr, + [GPLL3_OUT_EARLY] = &gpll3_out_early.clkr, + [GPLL4_OUT_MAIN] = &gpll4_out_main.clkr, + [GPLL5_OUT_MAIN] = &gpll5_out_main.clkr, + [GPLL6_OUT_EARLY] = &gpll6_out_early.clkr, + [GPLL7_OUT_EARLY] = &gpll7_out_early.clkr, + [GPLL8_OUT_EARLY] = &gpll8_out_early.clkr, + [GPLL9_OUT_EARLY] = &gpll9_out_early.clkr, + [GCC_USB3_PRIM_CLKREF_CLK] = &gcc_usb3_prim_clkref_clk.clkr, +}; + +static const struct qcom_reset_map gcc_sm6125_resets[] = { + [GCC_QUSB2PHY_PRIM_BCR] = { 0x1c000 }, + [GCC_QUSB2PHY_SEC_BCR] = { 0x1c004 }, + [GCC_UFS_PHY_BCR] = { 0x45000 }, + [GCC_USB30_PRIM_BCR] = { 0x1a000 }, + [GCC_USB_PHY_CFG_AHB2PHY_BCR] = { 0x1d000 }, + [GCC_USB3PHY_PHY_PRIM_SP0_BCR] = { 0x1b008 }, + [GCC_USB3_PHY_PRIM_SP0_BCR] = { 0x1b000 }, + [GCC_CAMSS_MICRO_BCR] = { 0x560ac }, +}; + +static struct clk_rcg_dfs_data gcc_dfs_clocks[] = { + DEFINE_RCG_DFS(gcc_qupv3_wrap0_s0_clk_src), + DEFINE_RCG_DFS(gcc_qupv3_wrap0_s1_clk_src), + DEFINE_RCG_DFS(gcc_qupv3_wrap0_s2_clk_src), + DEFINE_RCG_DFS(gcc_qupv3_wrap0_s3_clk_src), + DEFINE_RCG_DFS(gcc_qupv3_wrap0_s4_clk_src), + DEFINE_RCG_DFS(gcc_qupv3_wrap0_s5_clk_src), + DEFINE_RCG_DFS(gcc_qupv3_wrap1_s0_clk_src), + DEFINE_RCG_DFS(gcc_qupv3_wrap1_s1_clk_src), + DEFINE_RCG_DFS(gcc_qupv3_wrap1_s2_clk_src), + DEFINE_RCG_DFS(gcc_qupv3_wrap1_s3_clk_src), + DEFINE_RCG_DFS(gcc_qupv3_wrap1_s4_clk_src), + DEFINE_RCG_DFS(gcc_qupv3_wrap1_s5_clk_src), +}; + +static const struct regmap_config gcc_sm6125_regmap_config = { + .reg_bits = 32, + .reg_stride = 4, + .val_bits = 32, + .max_register = 0xc7000, + .fast_io = true, +}; + +static const struct qcom_cc_desc gcc_sm6125_desc = { + .config = &gcc_sm6125_regmap_config, + .clks = gcc_sm6125_clocks, + .num_clks = ARRAY_SIZE(gcc_sm6125_clocks), + .clk_hws = gcc_sm6125_hws, + .num_clk_hws = ARRAY_SIZE(gcc_sm6125_hws), + .resets = gcc_sm6125_resets, + .num_resets = ARRAY_SIZE(gcc_sm6125_resets), + .gdscs = gcc_sm6125_gdscs, + .num_gdscs = ARRAY_SIZE(gcc_sm6125_gdscs), +}; + +static const struct of_device_id gcc_sm6125_match_table[] = { + { .compatible = "qcom,gcc-sm6125" }, + { } +}; +MODULE_DEVICE_TABLE(of, gcc_sm6125_match_table); + +static int gcc_sm6125_probe(struct platform_device *pdev) +{ + struct regmap *regmap; + int ret; + + regmap = qcom_cc_map(pdev, &gcc_sm6125_desc); + if (IS_ERR(regmap)) + return PTR_ERR(regmap); + + /* + * Disable the GPLL0 active input to video block via + * MISC registers. + */ + regmap_update_bits(regmap, 0x80258, 0x1, 0x1); + + /* + * Enable DUAL_EDGE mode for MCLK RCGs + * This is requierd to enable MND divider mode + */ + regmap_update_bits(regmap, 0x51004, 0x3000, 0x2000); + regmap_update_bits(regmap, 0x51020, 0x3000, 0x2000); + regmap_update_bits(regmap, 0x5103c, 0x3000, 0x2000); + regmap_update_bits(regmap, 0x51058, 0x3000, 0x2000); + + ret = qcom_cc_register_rcg_dfs(regmap, gcc_dfs_clocks, + ARRAY_SIZE(gcc_dfs_clocks)); + if (ret) + return ret; + + return qcom_cc_really_probe(pdev, &gcc_sm6125_desc, regmap); +} + +static struct platform_driver gcc_sm6125_driver = { + .probe = gcc_sm6125_probe, + .driver = { + .name = "gcc-sm6125", + .of_match_table = gcc_sm6125_match_table, + }, +}; + +static int __init gcc_sm6125_init(void) +{ + return platform_driver_register(&gcc_sm6125_driver); +} +subsys_initcall(gcc_sm6125_init); + +static void __exit gcc_sm6125_exit(void) +{ + platform_driver_unregister(&gcc_sm6125_driver); +} +module_exit(gcc_sm6125_exit); + +MODULE_DESCRIPTION("QTI GCC SM6125 Driver"); +MODULE_LICENSE("GPL v2"); diff --git a/drivers/clk/renesas/Kconfig b/drivers/clk/renesas/Kconfig index 607e64a17d72..7b450650bcae 100644 --- a/drivers/clk/renesas/Kconfig +++ b/drivers/clk/renesas/Kconfig @@ -32,6 +32,7 @@ config CLK_RENESAS select CLK_R8A77995 if ARCH_R8A77995 select CLK_R8A779A0 if ARCH_R8A779A0 select CLK_R9A06G032 if ARCH_R9A06G032 + select CLK_R9A07G044 if ARCH_R9A07G044 select CLK_SH73A0 if ARCH_SH73A0 if CLK_RENESAS @@ -156,6 +157,10 @@ config CLK_R9A06G032 help This is a driver for R9A06G032 clocks +config CLK_R9A07G044 + bool "RZ/G2L clock support" if COMPILE_TEST + select CLK_RZG2L + config CLK_SH73A0 bool "SH-Mobile AG5 clock support" if COMPILE_TEST select CLK_RENESAS_CPG_MSTP @@ -182,6 +187,10 @@ config CLK_RCAR_USB2_CLOCK_SEL help This is a driver for R-Car USB2 clock selector +config CLK_RZG2L + bool "Renesas RZ/G2L family clock support" if COMPILE_TEST + select RESET_CONTROLLER + # Generic config CLK_RENESAS_CPG_MSSR bool "CPG/MSSR clock support" if COMPILE_TEST diff --git a/drivers/clk/renesas/Makefile b/drivers/clk/renesas/Makefile index ef0d2bba92bf..5c6c5c721d98 100644 --- a/drivers/clk/renesas/Makefile +++ b/drivers/clk/renesas/Makefile @@ -29,6 +29,7 @@ obj-$(CONFIG_CLK_R8A77990) += r8a77990-cpg-mssr.o obj-$(CONFIG_CLK_R8A77995) += r8a77995-cpg-mssr.o obj-$(CONFIG_CLK_R8A779A0) += r8a779a0-cpg-mssr.o obj-$(CONFIG_CLK_R9A06G032) += r9a06g032-clocks.o +obj-$(CONFIG_CLK_R9A07G044) += r9a07g044-cpg.o obj-$(CONFIG_CLK_SH73A0) += clk-sh73a0.o # Family @@ -36,6 +37,7 @@ obj-$(CONFIG_CLK_RCAR_CPG_LIB) += rcar-cpg-lib.o obj-$(CONFIG_CLK_RCAR_GEN2_CPG) += rcar-gen2-cpg.o obj-$(CONFIG_CLK_RCAR_GEN3_CPG) += rcar-gen3-cpg.o obj-$(CONFIG_CLK_RCAR_USB2_CLOCK_SEL) += rcar-usb2-clock-sel.o +obj-$(CONFIG_CLK_RZG2L) += renesas-rzg2l-cpg.o # Generic obj-$(CONFIG_CLK_RENESAS_CPG_MSSR) += renesas-cpg-mssr.o diff --git a/drivers/clk/renesas/clk-div6.c b/drivers/clk/renesas/clk-div6.c index 8fb68e703a6b..3abd6e5400ad 100644 --- a/drivers/clk/renesas/clk-div6.c +++ b/drivers/clk/renesas/clk-div6.c @@ -28,8 +28,7 @@ * @hw: handle between common and hardware-specific interfaces * @reg: IO-remapped register * @div: divisor value (1-64) - * @src_shift: Shift to access the register bits to select the parent clock - * @src_width: Number of register bits to select the parent clock (may be 0) + * @src_mask: Bitmask covering the register bits to select the parent clock * @nb: Notifier block to save/restore clock state for system resume * @parents: Array to map from valid parent clocks indices to hardware indices */ @@ -37,8 +36,7 @@ struct div6_clock { struct clk_hw hw; void __iomem *reg; unsigned int div; - u32 src_shift; - u32 src_width; + u32 src_mask; struct notifier_block nb; u8 parents[]; }; @@ -99,15 +97,52 @@ static unsigned int cpg_div6_clock_calc_div(unsigned long rate, rate = 1; div = DIV_ROUND_CLOSEST(parent_rate, rate); - return clamp_t(unsigned int, div, 1, 64); + return clamp(div, 1U, 64U); } -static long cpg_div6_clock_round_rate(struct clk_hw *hw, unsigned long rate, - unsigned long *parent_rate) +static int cpg_div6_clock_determine_rate(struct clk_hw *hw, + struct clk_rate_request *req) { - unsigned int div = cpg_div6_clock_calc_div(rate, *parent_rate); + unsigned long prate, calc_rate, diff, best_rate, best_prate; + unsigned int num_parents = clk_hw_get_num_parents(hw); + struct clk_hw *parent, *best_parent = NULL; + unsigned int i, min_div, max_div, div; + unsigned long min_diff = ULONG_MAX; + + for (i = 0; i < num_parents; i++) { + parent = clk_hw_get_parent_by_index(hw, i); + if (!parent) + continue; + + prate = clk_hw_get_rate(parent); + if (!prate) + continue; + + min_div = max(DIV_ROUND_UP(prate, req->max_rate), 1UL); + max_div = req->min_rate ? min(prate / req->min_rate, 64UL) : 64; + if (max_div < min_div) + continue; + + div = cpg_div6_clock_calc_div(req->rate, prate); + div = clamp(div, min_div, max_div); + calc_rate = prate / div; + diff = calc_rate > req->rate ? calc_rate - req->rate + : req->rate - calc_rate; + if (diff < min_diff) { + best_rate = calc_rate; + best_parent = parent; + best_prate = prate; + min_diff = diff; + } + } + + if (!best_parent) + return -EINVAL; - return *parent_rate / div; + req->best_parent_rate = best_prate; + req->best_parent_hw = best_parent; + req->rate = best_rate; + return 0; } static int cpg_div6_clock_set_rate(struct clk_hw *hw, unsigned long rate, @@ -133,11 +168,11 @@ static u8 cpg_div6_clock_get_parent(struct clk_hw *hw) unsigned int i; u8 hw_index; - if (clock->src_width == 0) + if (clock->src_mask == 0) return 0; - hw_index = (readl(clock->reg) >> clock->src_shift) & - (BIT(clock->src_width) - 1); + hw_index = (readl(clock->reg) & clock->src_mask) >> + __ffs(clock->src_mask); for (i = 0; i < clk_hw_get_num_parents(hw); i++) { if (clock->parents[i] == hw_index) return i; @@ -151,18 +186,13 @@ static u8 cpg_div6_clock_get_parent(struct clk_hw *hw) static int cpg_div6_clock_set_parent(struct clk_hw *hw, u8 index) { struct div6_clock *clock = to_div6_clock(hw); - u8 hw_index; - u32 mask; + u32 src; if (index >= clk_hw_get_num_parents(hw)) return -EINVAL; - mask = ~((BIT(clock->src_width) - 1) << clock->src_shift); - hw_index = clock->parents[index]; - - writel((readl(clock->reg) & mask) | (hw_index << clock->src_shift), - clock->reg); - + src = clock->parents[index] << __ffs(clock->src_mask); + writel((readl(clock->reg) & ~clock->src_mask) | src, clock->reg); return 0; } @@ -173,7 +203,7 @@ static const struct clk_ops cpg_div6_clock_ops = { .get_parent = cpg_div6_clock_get_parent, .set_parent = cpg_div6_clock_set_parent, .recalc_rate = cpg_div6_clock_recalc_rate, - .round_rate = cpg_div6_clock_round_rate, + .determine_rate = cpg_div6_clock_determine_rate, .set_rate = cpg_div6_clock_set_rate, }; @@ -236,17 +266,15 @@ struct clk * __init cpg_div6_register(const char *name, switch (num_parents) { case 1: /* fixed parent clock */ - clock->src_shift = clock->src_width = 0; + clock->src_mask = 0; break; case 4: /* clock with EXSRC bits 6-7 */ - clock->src_shift = 6; - clock->src_width = 2; + clock->src_mask = GENMASK(7, 6); break; case 8: /* VCLK with EXSRC bits 12-14 */ - clock->src_shift = 12; - clock->src_width = 3; + clock->src_mask = GENMASK(14, 12); break; default: pr_err("%s: invalid number of parents for DIV6 clock %s\n", diff --git a/drivers/clk/renesas/r8a77995-cpg-mssr.c b/drivers/clk/renesas/r8a77995-cpg-mssr.c index 9cfd00cf4e69..81c0bc1e78af 100644 --- a/drivers/clk/renesas/r8a77995-cpg-mssr.c +++ b/drivers/clk/renesas/r8a77995-cpg-mssr.c @@ -75,6 +75,7 @@ static const struct cpg_core_clk r8a77995_core_clks[] __initconst = { DEF_RATE(".oco", CLK_OCO, 8 * 1000 * 1000), /* Core Clock Outputs */ + DEF_FIXED("za2", R8A77995_CLK_ZA2, CLK_PLL0D3, 2, 1), DEF_FIXED("z2", R8A77995_CLK_Z2, CLK_PLL0D3, 1, 1), DEF_FIXED("ztr", R8A77995_CLK_ZTR, CLK_PLL1, 6, 1), DEF_FIXED("zt", R8A77995_CLK_ZT, CLK_PLL1, 4, 1), diff --git a/drivers/clk/renesas/r8a779a0-cpg-mssr.c b/drivers/clk/renesas/r8a779a0-cpg-mssr.c index 867c565cb58f..acaf5a93f1d3 100644 --- a/drivers/clk/renesas/r8a779a0-cpg-mssr.c +++ b/drivers/clk/renesas/r8a779a0-cpg-mssr.c @@ -180,6 +180,10 @@ static const struct mssr_mod_clk r8a779a0_mod_clks[] __initconst = { DEF_MOD("i2c4", 522, R8A779A0_CLK_S1D4), DEF_MOD("i2c5", 523, R8A779A0_CLK_S1D4), DEF_MOD("i2c6", 524, R8A779A0_CLK_S1D4), + DEF_MOD("ispcs0", 612, R8A779A0_CLK_S1D1), + DEF_MOD("ispcs1", 613, R8A779A0_CLK_S1D1), + DEF_MOD("ispcs2", 614, R8A779A0_CLK_S1D1), + DEF_MOD("ispcs3", 615, R8A779A0_CLK_S1D1), DEF_MOD("msi0", 618, R8A779A0_CLK_MSO), DEF_MOD("msi1", 619, R8A779A0_CLK_MSO), DEF_MOD("msi2", 620, R8A779A0_CLK_MSO), diff --git a/drivers/clk/renesas/r9a06g032-clocks.c b/drivers/clk/renesas/r9a06g032-clocks.c index 71b11443f6fc..c99942f0e4d4 100644 --- a/drivers/clk/renesas/r9a06g032-clocks.c +++ b/drivers/clk/renesas/r9a06g032-clocks.c @@ -604,20 +604,19 @@ r9a06g032_div_clamp_div(struct r9a06g032_clk_div *clk, return div; } -static long -r9a06g032_div_round_rate(struct clk_hw *hw, - unsigned long rate, unsigned long *prate) +static int +r9a06g032_div_determine_rate(struct clk_hw *hw, struct clk_rate_request *req) { struct r9a06g032_clk_div *clk = to_r9a06g032_div(hw); - u32 div = DIV_ROUND_UP(*prate, rate); + u32 div = DIV_ROUND_UP(req->best_parent_rate, req->rate); pr_devel("%s %pC %ld (prate %ld) (wanted div %u)\n", __func__, - hw->clk, rate, *prate, div); + hw->clk, req->rate, req->best_parent_rate, div); pr_devel(" min %d (%ld) max %d (%ld)\n", - clk->min, DIV_ROUND_UP(*prate, clk->min), - clk->max, DIV_ROUND_UP(*prate, clk->max)); + clk->min, DIV_ROUND_UP(req->best_parent_rate, clk->min), + clk->max, DIV_ROUND_UP(req->best_parent_rate, clk->max)); - div = r9a06g032_div_clamp_div(clk, rate, *prate); + div = r9a06g032_div_clamp_div(clk, req->rate, req->best_parent_rate); /* * this is a hack. Currently the serial driver asks for a clock rate * that is 16 times the baud rate -- and that is wildly outside the @@ -630,11 +629,13 @@ r9a06g032_div_round_rate(struct clk_hw *hw, if (clk->index == R9A06G032_DIV_UART || clk->index == R9A06G032_DIV_P2_PG) { pr_devel("%s div uart hack!\n", __func__); - return clk_get_rate(hw->clk); + req->rate = clk_get_rate(hw->clk); + return 0; } + req->rate = DIV_ROUND_UP(req->best_parent_rate, div); pr_devel("%s %pC %ld / %u = %ld\n", __func__, hw->clk, - *prate, div, DIV_ROUND_UP(*prate, div)); - return DIV_ROUND_UP(*prate, div); + req->best_parent_rate, div, req->rate); + return 0; } static int @@ -663,7 +664,7 @@ r9a06g032_div_set_rate(struct clk_hw *hw, static const struct clk_ops r9a06g032_clk_div_ops = { .recalc_rate = r9a06g032_div_recalc_rate, - .round_rate = r9a06g032_div_round_rate, + .determine_rate = r9a06g032_div_determine_rate, .set_rate = r9a06g032_div_set_rate, }; diff --git a/drivers/clk/renesas/r9a07g044-cpg.c b/drivers/clk/renesas/r9a07g044-cpg.c new file mode 100644 index 000000000000..50b5269586a4 --- /dev/null +++ b/drivers/clk/renesas/r9a07g044-cpg.c @@ -0,0 +1,127 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * RZ/G2L CPG driver + * + * Copyright (C) 2021 Renesas Electronics Corp. + */ + +#include <linux/clk-provider.h> +#include <linux/device.h> +#include <linux/init.h> +#include <linux/kernel.h> + +#include <dt-bindings/clock/r9a07g044-cpg.h> + +#include "renesas-rzg2l-cpg.h" + +enum clk_ids { + /* Core Clock Outputs exported to DT */ + LAST_DT_CORE_CLK = R9A07G044_OSCCLK, + + /* External Input Clocks */ + CLK_EXTAL, + + /* Internal Core Clocks */ + CLK_OSC_DIV1000, + CLK_PLL1, + CLK_PLL2, + CLK_PLL2_DIV2, + CLK_PLL2_DIV16, + CLK_PLL2_DIV20, + CLK_PLL3, + CLK_PLL3_DIV2, + CLK_PLL3_DIV4, + CLK_PLL3_DIV8, + CLK_PLL4, + CLK_PLL5, + CLK_PLL5_DIV2, + CLK_PLL6, + + /* Module Clocks */ + MOD_CLK_BASE, +}; + +/* Divider tables */ +static const struct clk_div_table dtable_3b[] = { + {0, 1}, + {1, 2}, + {2, 4}, + {3, 8}, + {4, 32}, +}; + +static const struct cpg_core_clk r9a07g044_core_clks[] __initconst = { + /* External Clock Inputs */ + DEF_INPUT("extal", CLK_EXTAL), + + /* Internal Core Clocks */ + DEF_FIXED(".osc", R9A07G044_OSCCLK, CLK_EXTAL, 1, 1), + DEF_FIXED(".osc_div1000", CLK_OSC_DIV1000, CLK_EXTAL, 1, 1000), + DEF_SAMPLL(".pll1", CLK_PLL1, CLK_EXTAL, PLL146_CONF(0)), + DEF_FIXED(".pll2", CLK_PLL2, CLK_EXTAL, 133, 2), + DEF_FIXED(".pll3", CLK_PLL3, CLK_EXTAL, 133, 2), + + DEF_FIXED(".pll2_div2", CLK_PLL2_DIV2, CLK_PLL2, 1, 2), + DEF_FIXED(".pll2_div16", CLK_PLL2_DIV16, CLK_PLL2, 1, 16), + DEF_FIXED(".pll2_div20", CLK_PLL2_DIV20, CLK_PLL2, 1, 20), + + DEF_FIXED(".pll3_div2", CLK_PLL3_DIV2, CLK_PLL3, 1, 2), + DEF_FIXED(".pll3_div4", CLK_PLL3_DIV4, CLK_PLL3, 1, 4), + DEF_FIXED(".pll3_div8", CLK_PLL3_DIV8, CLK_PLL3, 1, 8), + + /* Core output clk */ + DEF_FIXED("I", R9A07G044_CLK_I, CLK_PLL1, 1, 1), + DEF_DIV("P0", R9A07G044_CLK_P0, CLK_PLL2_DIV16, DIVPL2A, + dtable_3b, CLK_DIVIDER_HIWORD_MASK), + DEF_FIXED("TSU", R9A07G044_CLK_TSU, CLK_PLL2_DIV20, 1, 1), + DEF_DIV("P1", R9A07G044_CLK_P1, CLK_PLL3_DIV8, + DIVPL3B, dtable_3b, CLK_DIVIDER_HIWORD_MASK), +}; + +static struct rzg2l_mod_clk r9a07g044_mod_clks[] = { + DEF_MOD("gic", R9A07G044_CLK_GIC600, + R9A07G044_CLK_P1, + 0x514, BIT(0), (BIT(0) | BIT(1))), + DEF_MOD("ia55", R9A07G044_CLK_IA55, + R9A07G044_CLK_P1, + 0x518, (BIT(0) | BIT(1)), BIT(0)), + DEF_MOD("scif0", R9A07G044_CLK_SCIF0, + R9A07G044_CLK_P0, + 0x584, BIT(0), BIT(0)), + DEF_MOD("scif1", R9A07G044_CLK_SCIF1, + R9A07G044_CLK_P0, + 0x584, BIT(1), BIT(1)), + DEF_MOD("scif2", R9A07G044_CLK_SCIF2, + R9A07G044_CLK_P0, + 0x584, BIT(2), BIT(2)), + DEF_MOD("scif3", R9A07G044_CLK_SCIF3, + R9A07G044_CLK_P0, + 0x584, BIT(3), BIT(3)), + DEF_MOD("scif4", R9A07G044_CLK_SCIF4, + R9A07G044_CLK_P0, + 0x584, BIT(4), BIT(4)), + DEF_MOD("sci0", R9A07G044_CLK_SCI0, + R9A07G044_CLK_P0, + 0x588, BIT(0), BIT(0)), +}; + +static const unsigned int r9a07g044_crit_mod_clks[] __initconst = { + MOD_CLK_BASE + R9A07G044_CLK_GIC600, +}; + +const struct rzg2l_cpg_info r9a07g044_cpg_info = { + /* Core Clocks */ + .core_clks = r9a07g044_core_clks, + .num_core_clks = ARRAY_SIZE(r9a07g044_core_clks), + .last_dt_core_clk = LAST_DT_CORE_CLK, + .num_total_core_clks = MOD_CLK_BASE, + + /* Critical Module Clocks */ + .crit_mod_clks = r9a07g044_crit_mod_clks, + .num_crit_mod_clks = ARRAY_SIZE(r9a07g044_crit_mod_clks), + + /* Module Clocks */ + .mod_clks = r9a07g044_mod_clks, + .num_mod_clks = ARRAY_SIZE(r9a07g044_mod_clks), + .num_hw_mod_clks = R9A07G044_CLK_MIPI_DSI_PIN + 1, +}; diff --git a/drivers/clk/renesas/rcar-gen3-cpg.c b/drivers/clk/renesas/rcar-gen3-cpg.c index caa0f9414e45..558191c99b48 100644 --- a/drivers/clk/renesas/rcar-gen3-cpg.c +++ b/drivers/clk/renesas/rcar-gen3-cpg.c @@ -26,19 +26,135 @@ #include "rcar-cpg-lib.h" #include "rcar-gen3-cpg.h" -#define CPG_PLL0CR 0x00d8 +#define CPG_PLLECR 0x00d0 /* PLL Enable Control Register */ + +#define CPG_PLLECR_PLLST(n) BIT(8 + (n)) /* PLLn Circuit Status */ + +#define CPG_PLL0CR 0x00d8 /* PLLn Control Registers */ #define CPG_PLL2CR 0x002c #define CPG_PLL4CR 0x01f4 +#define CPG_PLLnCR_STC_MASK GENMASK(30, 24) /* PLL Circuit Mult. Ratio */ + #define CPG_RCKCR_CKSEL BIT(15) /* RCLK Clock Source Select */ +/* PLL Clocks */ +struct cpg_pll_clk { + struct clk_hw hw; + void __iomem *pllcr_reg; + void __iomem *pllecr_reg; + unsigned int fixed_mult; + u32 pllecr_pllst_mask; +}; + +#define to_pll_clk(_hw) container_of(_hw, struct cpg_pll_clk, hw) + +static unsigned long cpg_pll_clk_recalc_rate(struct clk_hw *hw, + unsigned long parent_rate) +{ + struct cpg_pll_clk *pll_clk = to_pll_clk(hw); + unsigned int mult; + u32 val; + + val = readl(pll_clk->pllcr_reg) & CPG_PLLnCR_STC_MASK; + mult = (val >> __ffs(CPG_PLLnCR_STC_MASK)) + 1; + + return parent_rate * mult * pll_clk->fixed_mult; +} + +static int cpg_pll_clk_determine_rate(struct clk_hw *hw, + struct clk_rate_request *req) +{ + struct cpg_pll_clk *pll_clk = to_pll_clk(hw); + unsigned int min_mult, max_mult, mult; + unsigned long prate; + + prate = req->best_parent_rate * pll_clk->fixed_mult; + min_mult = max(div64_ul(req->min_rate, prate), 1ULL); + max_mult = min(div64_ul(req->max_rate, prate), 128ULL); + if (max_mult < min_mult) + return -EINVAL; + + mult = DIV_ROUND_CLOSEST_ULL(req->rate, prate); + mult = clamp(mult, min_mult, max_mult); + + req->rate = prate * mult; + return 0; +} + +static int cpg_pll_clk_set_rate(struct clk_hw *hw, unsigned long rate, + unsigned long parent_rate) +{ + struct cpg_pll_clk *pll_clk = to_pll_clk(hw); + unsigned int mult, i; + u32 val; + + mult = DIV_ROUND_CLOSEST_ULL(rate, parent_rate * pll_clk->fixed_mult); + mult = clamp(mult, 1U, 128U); + + val = readl(pll_clk->pllcr_reg); + val &= ~CPG_PLLnCR_STC_MASK; + val |= (mult - 1) << __ffs(CPG_PLLnCR_STC_MASK); + writel(val, pll_clk->pllcr_reg); + + for (i = 1000; i; i--) { + if (readl(pll_clk->pllecr_reg) & pll_clk->pllecr_pllst_mask) + return 0; + + cpu_relax(); + } + + return -ETIMEDOUT; +} + +static const struct clk_ops cpg_pll_clk_ops = { + .recalc_rate = cpg_pll_clk_recalc_rate, + .determine_rate = cpg_pll_clk_determine_rate, + .set_rate = cpg_pll_clk_set_rate, +}; + +static struct clk * __init cpg_pll_clk_register(const char *name, + const char *parent_name, + void __iomem *base, + unsigned int mult, + unsigned int offset, + unsigned int index) + +{ + struct cpg_pll_clk *pll_clk; + struct clk_init_data init = {}; + struct clk *clk; + + pll_clk = kzalloc(sizeof(*pll_clk), GFP_KERNEL); + if (!pll_clk) + return ERR_PTR(-ENOMEM); + + init.name = name; + init.ops = &cpg_pll_clk_ops; + init.parent_names = &parent_name; + init.num_parents = 1; + + pll_clk->hw.init = &init; + pll_clk->pllcr_reg = base + offset; + pll_clk->pllecr_reg = base + CPG_PLLECR; + pll_clk->fixed_mult = mult; /* PLL refclk x (setting + 1) x mult */ + pll_clk->pllecr_pllst_mask = CPG_PLLECR_PLLST(index); + + clk = clk_register(NULL, &pll_clk->hw); + if (IS_ERR(clk)) + kfree(pll_clk); + + return clk; +} + /* * Z Clock & Z2 Clock * * Traits of this clock: * prepare - clk_prepare only ensures that parents are prepared * enable - clk_enable only ensures that parents are enabled - * rate - rate is adjustable. clk->rate = (parent->rate * mult / 32 ) / 2 + * rate - rate is adjustable. + * clk->rate = (parent->rate * mult / 32 ) / fixed_div * parent - fixed parent. No clk_set_parent support */ #define CPG_FRQCRB 0x00000004 @@ -49,8 +165,9 @@ struct cpg_z_clk { struct clk_hw hw; void __iomem *reg; void __iomem *kick_reg; - unsigned long mask; + unsigned long max_rate; /* Maximum rate for normal mode */ unsigned int fixed_div; + u32 mask; }; #define to_z_clk(_hw) container_of(_hw, struct cpg_z_clk, hw) @@ -74,7 +191,18 @@ static int cpg_z_clk_determine_rate(struct clk_hw *hw, { struct cpg_z_clk *zclk = to_z_clk(hw); unsigned int min_mult, max_mult, mult; - unsigned long prate; + unsigned long rate, prate; + + rate = min(req->rate, req->max_rate); + if (rate <= zclk->max_rate) { + /* Set parent rate to initial value for normal modes */ + prate = zclk->max_rate; + } else { + /* Set increased parent rate for boost modes */ + prate = rate; + } + req->best_parent_rate = clk_hw_round_rate(clk_hw_get_parent(hw), + prate * zclk->fixed_div); prate = req->best_parent_rate / zclk->fixed_div; min_mult = max(div64_ul(req->min_rate * 32ULL, prate), 1ULL); @@ -82,10 +210,10 @@ static int cpg_z_clk_determine_rate(struct clk_hw *hw, if (max_mult < min_mult) return -EINVAL; - mult = div64_ul(req->rate * 32ULL, prate); + mult = DIV_ROUND_CLOSEST_ULL(rate * 32ULL, prate); mult = clamp(mult, min_mult, max_mult); - req->rate = div_u64((u64)prate * mult, 32); + req->rate = DIV_ROUND_CLOSEST_ULL((u64)prate * mult, 32); return 0; } @@ -103,8 +231,7 @@ static int cpg_z_clk_set_rate(struct clk_hw *hw, unsigned long rate, if (readl(zclk->kick_reg) & CPG_FRQCRB_KICK) return -EBUSY; - cpg_reg_modify(zclk->reg, zclk->mask, - ((32 - mult) << __ffs(zclk->mask)) & zclk->mask); + cpg_reg_modify(zclk->reg, zclk->mask, (32 - mult) << __ffs(zclk->mask)); /* * Set KICK bit in FRQCRB to update hardware setting and wait for @@ -117,7 +244,7 @@ static int cpg_z_clk_set_rate(struct clk_hw *hw, unsigned long rate, * * Using experimental measurements, it seems that no more than * ~10 iterations are needed, independently of the CPU rate. - * Since this value might be dependent of external xtal rate, pll1 + * Since this value might be dependent on external xtal rate, pll1 * rate or even the other emulation clocks rate, use 1000 as a * "super" safe value. */ @@ -153,7 +280,7 @@ static struct clk * __init cpg_z_clk_register(const char *name, init.name = name; init.ops = &cpg_z_clk_ops; - init.flags = 0; + init.flags = CLK_SET_RATE_PARENT; init.parent_names = &parent_name; init.num_parents = 1; @@ -164,9 +291,13 @@ static struct clk * __init cpg_z_clk_register(const char *name, zclk->fixed_div = div; /* PLLVCO x 1/div x SYS-CPU divider */ clk = clk_register(NULL, &zclk->hw); - if (IS_ERR(clk)) + if (IS_ERR(clk)) { kfree(zclk); + return clk; + } + zclk->max_rate = clk_hw_get_rate(clk_hw_get_parent(&zclk->hw)) / + zclk->fixed_div; return clk; } @@ -314,16 +445,13 @@ struct clk * __init rcar_gen3_cpg_clk_register(struct device *dev, case CLK_TYPE_GEN3_PLL0: /* - * PLL0 is a configurable multiplier clock. Register it as a - * fixed factor clock for now as there's no generic multiplier - * clock implementation and we currently have no need to change - * the multiplier value. + * PLL0 is implemented as a custom clock, to change the + * multiplier when cpufreq changes between normal and boost + * modes. */ - value = readl(base + CPG_PLL0CR); - mult = (((value >> 24) & 0x7f) + 1) * 2; - if (cpg_quirks & PLL_ERRATA) - mult *= 2; - break; + mult = (cpg_quirks & PLL_ERRATA) ? 4 : 2; + return cpg_pll_clk_register(core->name, __clk_get_name(parent), + base, mult, CPG_PLL0CR, 0); case CLK_TYPE_GEN3_PLL1: mult = cpg_pll_config->pll1_mult; @@ -332,16 +460,13 @@ struct clk * __init rcar_gen3_cpg_clk_register(struct device *dev, case CLK_TYPE_GEN3_PLL2: /* - * PLL2 is a configurable multiplier clock. Register it as a - * fixed factor clock for now as there's no generic multiplier - * clock implementation and we currently have no need to change - * the multiplier value. + * PLL2 is implemented as a custom clock, to change the + * multiplier when cpufreq changes between normal and boost + * modes. */ - value = readl(base + CPG_PLL2CR); - mult = (((value >> 24) & 0x7f) + 1) * 2; - if (cpg_quirks & PLL_ERRATA) - mult *= 2; - break; + mult = (cpg_quirks & PLL_ERRATA) ? 4 : 2; + return cpg_pll_clk_register(core->name, __clk_get_name(parent), + base, mult, CPG_PLL2CR, 2); case CLK_TYPE_GEN3_PLL3: mult = cpg_pll_config->pll3_mult; diff --git a/drivers/clk/renesas/rcar-usb2-clock-sel.c b/drivers/clk/renesas/rcar-usb2-clock-sel.c index 34a85dc95beb..9fb79bd79435 100644 --- a/drivers/clk/renesas/rcar-usb2-clock-sel.c +++ b/drivers/clk/renesas/rcar-usb2-clock-sel.c @@ -128,10 +128,8 @@ static int rcar_usb2_clock_sel_resume(struct device *dev) static int rcar_usb2_clock_sel_remove(struct platform_device *pdev) { struct device *dev = &pdev->dev; - struct usb2_clock_sel_priv *priv = platform_get_drvdata(pdev); of_clk_del_provider(dev->of_node); - clk_hw_unregister(&priv->hw); pm_runtime_put(dev); pm_runtime_disable(dev); @@ -164,9 +162,6 @@ static int rcar_usb2_clock_sel_probe(struct platform_device *pdev) if (IS_ERR(priv->rsts)) return PTR_ERR(priv->rsts); - pm_runtime_enable(dev); - pm_runtime_get_sync(dev); - clk = devm_clk_get(dev, "usb_extal"); if (!IS_ERR(clk) && !clk_prepare_enable(clk)) { priv->extal = !!clk_get_rate(clk); @@ -183,6 +178,8 @@ static int rcar_usb2_clock_sel_probe(struct platform_device *pdev) return -ENOENT; } + pm_runtime_enable(dev); + pm_runtime_get_sync(dev); platform_set_drvdata(pdev, priv); dev_set_drvdata(dev, priv); @@ -190,11 +187,20 @@ static int rcar_usb2_clock_sel_probe(struct platform_device *pdev) init.ops = &usb2_clock_sel_clock_ops; priv->hw.init = &init; - clk = clk_register(NULL, &priv->hw); - if (IS_ERR(clk)) - return PTR_ERR(clk); + ret = devm_clk_hw_register(NULL, &priv->hw); + if (ret) + goto pm_put; + + ret = of_clk_add_hw_provider(np, of_clk_hw_simple_get, &priv->hw); + if (ret) + goto pm_put; + + return 0; - return of_clk_add_hw_provider(np, of_clk_hw_simple_get, &priv->hw); +pm_put: + pm_runtime_put(dev); + pm_runtime_disable(dev); + return ret; } static const struct dev_pm_ops rcar_usb2_clock_sel_pm_ops = { diff --git a/drivers/clk/renesas/renesas-cpg-mssr.c b/drivers/clk/renesas/renesas-cpg-mssr.c index fc531d35b269..21f762aa2131 100644 --- a/drivers/clk/renesas/renesas-cpg-mssr.c +++ b/drivers/clk/renesas/renesas-cpg-mssr.c @@ -100,13 +100,9 @@ static const u16 srcr_for_v3u[] = { 0x2C20, 0x2C24, 0x2C28, 0x2C2C, 0x2C30, 0x2C34, 0x2C38, }; -/* Realtime Module Stop Control Register offsets */ -#define RMSTPCR(i) (smstpcr[i] - 0x20) - -/* Modem Module Stop Control Register offsets (r8a73a4) */ -#define MMSTPCR(i) (smstpcr[i] + 0x20) - -/* Software Reset Clearing Register offsets */ +/* + * Software Reset Clearing Register offsets + */ static const u16 srstclr[] = { 0x940, 0x944, 0x948, 0x94C, 0x950, 0x954, 0x958, 0x95C, diff --git a/drivers/clk/renesas/renesas-rzg2l-cpg.c b/drivers/clk/renesas/renesas-rzg2l-cpg.c new file mode 100644 index 000000000000..5009b9e48b13 --- /dev/null +++ b/drivers/clk/renesas/renesas-rzg2l-cpg.c @@ -0,0 +1,750 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * RZ/G2L Clock Pulse Generator + * + * Copyright (C) 2021 Renesas Electronics Corp. + * + * Based on renesas-cpg-mssr.c + * + * Copyright (C) 2015 Glider bvba + * Copyright (C) 2013 Ideas On Board SPRL + * Copyright (C) 2015 Renesas Electronics Corp. + */ + +#include <linux/clk.h> +#include <linux/clk-provider.h> +#include <linux/clk/renesas.h> +#include <linux/delay.h> +#include <linux/device.h> +#include <linux/init.h> +#include <linux/mod_devicetable.h> +#include <linux/module.h> +#include <linux/of_address.h> +#include <linux/of_device.h> +#include <linux/platform_device.h> +#include <linux/pm_clock.h> +#include <linux/pm_domain.h> +#include <linux/reset-controller.h> +#include <linux/slab.h> + +#include <dt-bindings/clock/renesas-cpg-mssr.h> + +#include "renesas-rzg2l-cpg.h" + +#ifdef DEBUG +#define WARN_DEBUG(x) WARN_ON(x) +#else +#define WARN_DEBUG(x) do { } while (0) +#endif + +#define DIV_RSMASK(v, s, m) ((v >> s) & m) +#define GET_SHIFT(val) ((val >> 12) & 0xff) +#define GET_WIDTH(val) ((val >> 8) & 0xf) + +#define KDIV(val) DIV_RSMASK(val, 16, 0xffff) +#define MDIV(val) DIV_RSMASK(val, 6, 0x3ff) +#define PDIV(val) DIV_RSMASK(val, 0, 0x3f) +#define SDIV(val) DIV_RSMASK(val, 0, 0x7) + +#define CLK_ON_R(reg) (reg) +#define CLK_MON_R(reg) (0x680 - 0x500 + (reg)) +#define CLK_RST_R(reg) (0x800 - 0x500 + (reg)) +#define CLK_MRST_R(reg) (0x980 - 0x500 + (reg)) + +#define GET_REG_OFFSET(val) ((val >> 20) & 0xfff) +#define GET_REG_SAMPLL_CLK1(val) ((val >> 22) & 0xfff) +#define GET_REG_SAMPLL_CLK2(val) ((val >> 12) & 0xfff) + +/** + * struct rzg2l_cpg_priv - Clock Pulse Generator Private Data + * + * @rcdev: Reset controller entity + * @dev: CPG device + * @base: CPG register block base address + * @rmw_lock: protects register accesses + * @clks: Array containing all Core and Module Clocks + * @num_core_clks: Number of Core Clocks in clks[] + * @num_mod_clks: Number of Module Clocks in clks[] + * @last_dt_core_clk: ID of the last Core Clock exported to DT + * @notifiers: Notifier chain to save/restore clock state for system resume + * @info: Pointer to platform data + */ +struct rzg2l_cpg_priv { + struct reset_controller_dev rcdev; + struct device *dev; + void __iomem *base; + spinlock_t rmw_lock; + + struct clk **clks; + unsigned int num_core_clks; + unsigned int num_mod_clks; + unsigned int last_dt_core_clk; + + struct raw_notifier_head notifiers; + const struct rzg2l_cpg_info *info; +}; + +static void rzg2l_cpg_del_clk_provider(void *data) +{ + of_clk_del_provider(data); +} + +static struct clk * __init +rzg2l_cpg_div_clk_register(const struct cpg_core_clk *core, + struct clk **clks, + void __iomem *base, + struct rzg2l_cpg_priv *priv) +{ + struct device *dev = priv->dev; + const struct clk *parent; + const char *parent_name; + struct clk_hw *clk_hw; + + parent = clks[core->parent & 0xffff]; + if (IS_ERR(parent)) + return ERR_CAST(parent); + + parent_name = __clk_get_name(parent); + + if (core->dtable) + clk_hw = clk_hw_register_divider_table(dev, core->name, + parent_name, 0, + base + GET_REG_OFFSET(core->conf), + GET_SHIFT(core->conf), + GET_WIDTH(core->conf), + core->flag, + core->dtable, + &priv->rmw_lock); + else + clk_hw = clk_hw_register_divider(dev, core->name, + parent_name, 0, + base + GET_REG_OFFSET(core->conf), + GET_SHIFT(core->conf), + GET_WIDTH(core->conf), + core->flag, &priv->rmw_lock); + + if (IS_ERR(clk_hw)) + return NULL; + + return clk_hw->clk; +} + +struct pll_clk { + struct clk_hw hw; + unsigned int conf; + unsigned int type; + void __iomem *base; + struct rzg2l_cpg_priv *priv; +}; + +#define to_pll(_hw) container_of(_hw, struct pll_clk, hw) + +static unsigned long rzg2l_cpg_pll_clk_recalc_rate(struct clk_hw *hw, + unsigned long parent_rate) +{ + struct pll_clk *pll_clk = to_pll(hw); + struct rzg2l_cpg_priv *priv = pll_clk->priv; + unsigned int val1, val2; + unsigned int mult = 1; + unsigned int div = 1; + + if (pll_clk->type != CLK_TYPE_SAM_PLL) + return parent_rate; + + val1 = readl(priv->base + GET_REG_SAMPLL_CLK1(pll_clk->conf)); + val2 = readl(priv->base + GET_REG_SAMPLL_CLK2(pll_clk->conf)); + mult = MDIV(val1) + KDIV(val1) / 65536; + div = PDIV(val1) * (1 << SDIV(val2)); + + return DIV_ROUND_CLOSEST_ULL((u64)parent_rate * mult, div); +} + +static const struct clk_ops rzg2l_cpg_pll_ops = { + .recalc_rate = rzg2l_cpg_pll_clk_recalc_rate, +}; + +static struct clk * __init +rzg2l_cpg_pll_clk_register(const struct cpg_core_clk *core, + struct clk **clks, + void __iomem *base, + struct rzg2l_cpg_priv *priv) +{ + struct device *dev = priv->dev; + const struct clk *parent; + struct clk_init_data init; + const char *parent_name; + struct pll_clk *pll_clk; + struct clk *clk; + + parent = clks[core->parent & 0xffff]; + if (IS_ERR(parent)) + return ERR_CAST(parent); + + pll_clk = devm_kzalloc(dev, sizeof(*pll_clk), GFP_KERNEL); + if (!pll_clk) { + clk = ERR_PTR(-ENOMEM); + return NULL; + } + + parent_name = __clk_get_name(parent); + init.name = core->name; + init.ops = &rzg2l_cpg_pll_ops; + init.flags = 0; + init.parent_names = &parent_name; + init.num_parents = 1; + + pll_clk->hw.init = &init; + pll_clk->conf = core->conf; + pll_clk->base = base; + pll_clk->priv = priv; + pll_clk->type = core->type; + + clk = clk_register(NULL, &pll_clk->hw); + if (IS_ERR(clk)) + kfree(pll_clk); + + return clk; +} + +static struct clk +*rzg2l_cpg_clk_src_twocell_get(struct of_phandle_args *clkspec, + void *data) +{ + unsigned int clkidx = clkspec->args[1]; + struct rzg2l_cpg_priv *priv = data; + struct device *dev = priv->dev; + const char *type; + struct clk *clk; + + switch (clkspec->args[0]) { + case CPG_CORE: + type = "core"; + if (clkidx > priv->last_dt_core_clk) { + dev_err(dev, "Invalid %s clock index %u\n", type, clkidx); + return ERR_PTR(-EINVAL); + } + clk = priv->clks[clkidx]; + break; + + case CPG_MOD: + type = "module"; + if (clkidx > priv->num_mod_clks) { + dev_err(dev, "Invalid %s clock index %u\n", type, + clkidx); + return ERR_PTR(-EINVAL); + } + clk = priv->clks[priv->num_core_clks + clkidx]; + break; + + default: + dev_err(dev, "Invalid CPG clock type %u\n", clkspec->args[0]); + return ERR_PTR(-EINVAL); + } + + if (IS_ERR(clk)) + dev_err(dev, "Cannot get %s clock %u: %ld", type, clkidx, + PTR_ERR(clk)); + else + dev_dbg(dev, "clock (%u, %u) is %pC at %lu Hz\n", + clkspec->args[0], clkspec->args[1], clk, + clk_get_rate(clk)); + return clk; +} + +static void __init +rzg2l_cpg_register_core_clk(const struct cpg_core_clk *core, + const struct rzg2l_cpg_info *info, + struct rzg2l_cpg_priv *priv) +{ + struct clk *clk = ERR_PTR(-EOPNOTSUPP), *parent; + struct device *dev = priv->dev; + unsigned int id = core->id, div = core->div; + const char *parent_name; + + WARN_DEBUG(id >= priv->num_core_clks); + WARN_DEBUG(PTR_ERR(priv->clks[id]) != -ENOENT); + + if (!core->name) { + /* Skip NULLified clock */ + return; + } + + switch (core->type) { + case CLK_TYPE_IN: + clk = of_clk_get_by_name(priv->dev->of_node, core->name); + break; + case CLK_TYPE_FF: + WARN_DEBUG(core->parent >= priv->num_core_clks); + parent = priv->clks[core->parent]; + if (IS_ERR(parent)) { + clk = parent; + goto fail; + } + + parent_name = __clk_get_name(parent); + clk = clk_register_fixed_factor(NULL, core->name, + parent_name, CLK_SET_RATE_PARENT, + core->mult, div); + break; + case CLK_TYPE_SAM_PLL: + clk = rzg2l_cpg_pll_clk_register(core, priv->clks, + priv->base, priv); + break; + case CLK_TYPE_DIV: + clk = rzg2l_cpg_div_clk_register(core, priv->clks, + priv->base, priv); + break; + default: + goto fail; + }; + + if (IS_ERR_OR_NULL(clk)) + goto fail; + + dev_dbg(dev, "Core clock %pC at %lu Hz\n", clk, clk_get_rate(clk)); + priv->clks[id] = clk; + return; + +fail: + dev_err(dev, "Failed to register %s clock %s: %ld\n", "core", + core->name, PTR_ERR(clk)); +} + +/** + * struct mstp_clock - MSTP gating clock + * + * @hw: handle between common and hardware-specific interfaces + * @off: register offset + * @onoff: ON/MON bits + * @reset: reset bits + * @priv: CPG/MSTP private data + */ +struct mstp_clock { + struct clk_hw hw; + u16 off; + u8 onoff; + u8 reset; + struct rzg2l_cpg_priv *priv; +}; + +#define to_mod_clock(_hw) container_of(_hw, struct mstp_clock, hw) + +static int rzg2l_mod_clock_endisable(struct clk_hw *hw, bool enable) +{ + struct mstp_clock *clock = to_mod_clock(hw); + struct rzg2l_cpg_priv *priv = clock->priv; + unsigned int reg = clock->off; + struct device *dev = priv->dev; + unsigned long flags; + unsigned int i; + u32 value; + + if (!clock->off) { + dev_dbg(dev, "%pC does not support ON/OFF\n", hw->clk); + return 0; + } + + dev_dbg(dev, "CLK_ON %u/%pC %s\n", CLK_ON_R(reg), hw->clk, + enable ? "ON" : "OFF"); + spin_lock_irqsave(&priv->rmw_lock, flags); + + if (enable) + value = (clock->onoff << 16) | clock->onoff; + else + value = clock->onoff << 16; + writel(value, priv->base + CLK_ON_R(reg)); + + spin_unlock_irqrestore(&priv->rmw_lock, flags); + + if (!enable) + return 0; + + for (i = 1000; i > 0; --i) { + if (((readl(priv->base + CLK_MON_R(reg))) & clock->onoff)) + break; + cpu_relax(); + } + + if (!i) { + dev_err(dev, "Failed to enable CLK_ON %p\n", + priv->base + CLK_ON_R(reg)); + return -ETIMEDOUT; + } + + return 0; +} + +static int rzg2l_mod_clock_enable(struct clk_hw *hw) +{ + return rzg2l_mod_clock_endisable(hw, true); +} + +static void rzg2l_mod_clock_disable(struct clk_hw *hw) +{ + rzg2l_mod_clock_endisable(hw, false); +} + +static int rzg2l_mod_clock_is_enabled(struct clk_hw *hw) +{ + struct mstp_clock *clock = to_mod_clock(hw); + struct rzg2l_cpg_priv *priv = clock->priv; + u32 value; + + if (!clock->off) { + dev_dbg(priv->dev, "%pC does not support ON/OFF\n", hw->clk); + return 1; + } + + value = readl(priv->base + CLK_MON_R(clock->off)); + + return !(value & clock->onoff); +} + +static const struct clk_ops rzg2l_mod_clock_ops = { + .enable = rzg2l_mod_clock_enable, + .disable = rzg2l_mod_clock_disable, + .is_enabled = rzg2l_mod_clock_is_enabled, +}; + +static void __init +rzg2l_cpg_register_mod_clk(const struct rzg2l_mod_clk *mod, + const struct rzg2l_cpg_info *info, + struct rzg2l_cpg_priv *priv) +{ + struct mstp_clock *clock = NULL; + struct device *dev = priv->dev; + unsigned int id = mod->id; + struct clk_init_data init; + struct clk *parent, *clk; + const char *parent_name; + unsigned int i; + + WARN_DEBUG(id < priv->num_core_clks); + WARN_DEBUG(id >= priv->num_core_clks + priv->num_mod_clks); + WARN_DEBUG(mod->parent >= priv->num_core_clks + priv->num_mod_clks); + WARN_DEBUG(PTR_ERR(priv->clks[id]) != -ENOENT); + + if (!mod->name) { + /* Skip NULLified clock */ + return; + } + + parent = priv->clks[mod->parent]; + if (IS_ERR(parent)) { + clk = parent; + goto fail; + } + + clock = devm_kzalloc(dev, sizeof(*clock), GFP_KERNEL); + if (!clock) { + clk = ERR_PTR(-ENOMEM); + goto fail; + } + + init.name = mod->name; + init.ops = &rzg2l_mod_clock_ops; + init.flags = CLK_SET_RATE_PARENT; + for (i = 0; i < info->num_crit_mod_clks; i++) + if (id == info->crit_mod_clks[i]) { + dev_dbg(dev, "CPG %s setting CLK_IS_CRITICAL\n", + mod->name); + init.flags |= CLK_IS_CRITICAL; + break; + } + + parent_name = __clk_get_name(parent); + init.parent_names = &parent_name; + init.num_parents = 1; + + clock->off = mod->off; + clock->onoff = mod->onoff; + clock->reset = mod->reset; + clock->priv = priv; + clock->hw.init = &init; + + clk = clk_register(NULL, &clock->hw); + if (IS_ERR(clk)) + goto fail; + + dev_dbg(dev, "Module clock %pC at %lu Hz\n", clk, clk_get_rate(clk)); + priv->clks[id] = clk; + return; + +fail: + dev_err(dev, "Failed to register %s clock %s: %ld\n", "module", + mod->name, PTR_ERR(clk)); + kfree(clock); +} + +#define rcdev_to_priv(x) container_of(x, struct rzg2l_cpg_priv, rcdev) + +static int rzg2l_cpg_reset(struct reset_controller_dev *rcdev, + unsigned long id) +{ + struct rzg2l_cpg_priv *priv = rcdev_to_priv(rcdev); + const struct rzg2l_cpg_info *info = priv->info; + unsigned int reg = info->mod_clks[id].off; + u32 dis = info->mod_clks[id].reset; + u32 we = dis << 16; + + dev_dbg(rcdev->dev, "reset name:%s id:%ld offset:0x%x\n", + info->mod_clks[id].name, id, CLK_RST_R(reg)); + + /* Reset module */ + writel(we, priv->base + CLK_RST_R(reg)); + + /* Wait for at least one cycle of the RCLK clock (@ ca. 32 kHz) */ + udelay(35); + + /* Release module from reset state */ + writel(we | dis, priv->base + CLK_RST_R(reg)); + + return 0; +} + +static int rzg2l_cpg_assert(struct reset_controller_dev *rcdev, + unsigned long id) +{ + struct rzg2l_cpg_priv *priv = rcdev_to_priv(rcdev); + const struct rzg2l_cpg_info *info = priv->info; + unsigned int reg = info->mod_clks[id].off; + u32 value = info->mod_clks[id].reset << 16; + + dev_dbg(rcdev->dev, "assert name:%s id:%ld offset:0x%x\n", + info->mod_clks[id].name, id, CLK_RST_R(reg)); + + writel(value, priv->base + CLK_RST_R(reg)); + return 0; +} + +static int rzg2l_cpg_deassert(struct reset_controller_dev *rcdev, + unsigned long id) +{ + struct rzg2l_cpg_priv *priv = rcdev_to_priv(rcdev); + const struct rzg2l_cpg_info *info = priv->info; + unsigned int reg = info->mod_clks[id].off; + u32 dis = info->mod_clks[id].reset; + u32 value = (dis << 16) | dis; + + dev_dbg(rcdev->dev, "deassert name:%s id:%ld offset:0x%x\n", + info->mod_clks[id].name, id, CLK_RST_R(reg)); + + writel(value, priv->base + CLK_RST_R(reg)); + return 0; +} + +static int rzg2l_cpg_status(struct reset_controller_dev *rcdev, + unsigned long id) +{ + struct rzg2l_cpg_priv *priv = rcdev_to_priv(rcdev); + const struct rzg2l_cpg_info *info = priv->info; + unsigned int reg = info->mod_clks[id].off; + u32 bitmask = info->mod_clks[id].reset; + + return !(readl(priv->base + CLK_MRST_R(reg)) & bitmask); +} + +static const struct reset_control_ops rzg2l_cpg_reset_ops = { + .reset = rzg2l_cpg_reset, + .assert = rzg2l_cpg_assert, + .deassert = rzg2l_cpg_deassert, + .status = rzg2l_cpg_status, +}; + +static int rzg2l_cpg_reset_xlate(struct reset_controller_dev *rcdev, + const struct of_phandle_args *reset_spec) +{ + unsigned int id = reset_spec->args[0]; + + if (id >= rcdev->nr_resets) { + dev_err(rcdev->dev, "Invalid reset index %u\n", id); + return -EINVAL; + } + + return id; +} + +static int rzg2l_cpg_reset_controller_register(struct rzg2l_cpg_priv *priv) +{ + priv->rcdev.ops = &rzg2l_cpg_reset_ops; + priv->rcdev.of_node = priv->dev->of_node; + priv->rcdev.dev = priv->dev; + priv->rcdev.of_reset_n_cells = 1; + priv->rcdev.of_xlate = rzg2l_cpg_reset_xlate; + priv->rcdev.nr_resets = priv->num_mod_clks; + + return devm_reset_controller_register(priv->dev, &priv->rcdev); +} + +static bool rzg2l_cpg_is_pm_clk(const struct of_phandle_args *clkspec) +{ + if (clkspec->args_count != 2) + return false; + + switch (clkspec->args[0]) { + case CPG_MOD: + return true; + + default: + return false; + } +} + +static int rzg2l_cpg_attach_dev(struct generic_pm_domain *unused, struct device *dev) +{ + struct device_node *np = dev->of_node; + struct of_phandle_args clkspec; + struct clk *clk; + int error; + int i = 0; + + while (!of_parse_phandle_with_args(np, "clocks", "#clock-cells", i, + &clkspec)) { + if (rzg2l_cpg_is_pm_clk(&clkspec)) + goto found; + + of_node_put(clkspec.np); + i++; + } + + return 0; + +found: + clk = of_clk_get_from_provider(&clkspec); + of_node_put(clkspec.np); + + if (IS_ERR(clk)) + return PTR_ERR(clk); + + error = pm_clk_create(dev); + if (error) + goto fail_put; + + error = pm_clk_add_clk(dev, clk); + if (error) + goto fail_destroy; + + return 0; + +fail_destroy: + pm_clk_destroy(dev); +fail_put: + clk_put(clk); + return error; +} + +static void rzg2l_cpg_detach_dev(struct generic_pm_domain *unused, struct device *dev) +{ + if (!pm_clk_no_clocks(dev)) + pm_clk_destroy(dev); +} + +static int __init rzg2l_cpg_add_clk_domain(struct device *dev) +{ + struct device_node *np = dev->of_node; + struct generic_pm_domain *genpd; + + genpd = devm_kzalloc(dev, sizeof(*genpd), GFP_KERNEL); + if (!genpd) + return -ENOMEM; + + genpd->name = np->name; + genpd->flags = GENPD_FLAG_PM_CLK | GENPD_FLAG_ALWAYS_ON | + GENPD_FLAG_ACTIVE_WAKEUP; + genpd->attach_dev = rzg2l_cpg_attach_dev; + genpd->detach_dev = rzg2l_cpg_detach_dev; + pm_genpd_init(genpd, &pm_domain_always_on_gov, false); + + of_genpd_add_provider_simple(np, genpd); + return 0; +} + +static int __init rzg2l_cpg_probe(struct platform_device *pdev) +{ + struct device *dev = &pdev->dev; + struct device_node *np = dev->of_node; + const struct rzg2l_cpg_info *info; + struct rzg2l_cpg_priv *priv; + unsigned int nclks, i; + struct clk **clks; + int error; + + info = of_device_get_match_data(dev); + + priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL); + if (!priv) + return -ENOMEM; + + priv->dev = dev; + priv->info = info; + spin_lock_init(&priv->rmw_lock); + + priv->base = devm_platform_ioremap_resource(pdev, 0); + if (IS_ERR(priv->base)) + return PTR_ERR(priv->base); + + nclks = info->num_total_core_clks + info->num_hw_mod_clks; + clks = devm_kmalloc_array(dev, nclks, sizeof(*clks), GFP_KERNEL); + if (!clks) + return -ENOMEM; + + dev_set_drvdata(dev, priv); + priv->clks = clks; + priv->num_core_clks = info->num_total_core_clks; + priv->num_mod_clks = info->num_hw_mod_clks; + priv->last_dt_core_clk = info->last_dt_core_clk; + + for (i = 0; i < nclks; i++) + clks[i] = ERR_PTR(-ENOENT); + + for (i = 0; i < info->num_core_clks; i++) + rzg2l_cpg_register_core_clk(&info->core_clks[i], info, priv); + + for (i = 0; i < info->num_mod_clks; i++) + rzg2l_cpg_register_mod_clk(&info->mod_clks[i], info, priv); + + error = of_clk_add_provider(np, rzg2l_cpg_clk_src_twocell_get, priv); + if (error) + return error; + + error = devm_add_action_or_reset(dev, rzg2l_cpg_del_clk_provider, np); + if (error) + return error; + + error = rzg2l_cpg_add_clk_domain(dev); + if (error) + return error; + + error = rzg2l_cpg_reset_controller_register(priv); + if (error) + return error; + + return 0; +} + +static const struct of_device_id rzg2l_cpg_match[] = { +#ifdef CONFIG_CLK_R9A07G044 + { + .compatible = "renesas,r9a07g044-cpg", + .data = &r9a07g044_cpg_info, + }, +#endif + { /* sentinel */ } +}; + +static struct platform_driver rzg2l_cpg_driver = { + .driver = { + .name = "rzg2l-cpg", + .of_match_table = rzg2l_cpg_match, + }, +}; + +static int __init rzg2l_cpg_init(void) +{ + return platform_driver_probe(&rzg2l_cpg_driver, rzg2l_cpg_probe); +} + +subsys_initcall(rzg2l_cpg_init); + +MODULE_DESCRIPTION("Renesas RZ/G2L CPG Driver"); +MODULE_LICENSE("GPL v2"); diff --git a/drivers/clk/renesas/renesas-rzg2l-cpg.h b/drivers/clk/renesas/renesas-rzg2l-cpg.h new file mode 100644 index 000000000000..3948bdd8afc9 --- /dev/null +++ b/drivers/clk/renesas/renesas-rzg2l-cpg.h @@ -0,0 +1,136 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * RZ/G2L Clock Pulse Generator + * + * Copyright (C) 2021 Renesas Electronics Corp. + * + */ + +#ifndef __RENESAS_RZG2L_CPG_H__ +#define __RENESAS_RZG2L_CPG_H__ + +#define CPG_PL2_DDIV (0x204) +#define CPG_PL3A_DDIV (0x208) + +/* n = 0/1/2 for PLL1/4/6 */ +#define CPG_SAMPLL_CLK1(n) (0x04 + (16 * n)) +#define CPG_SAMPLL_CLK2(n) (0x08 + (16 * n)) + +#define PLL146_CONF(n) (CPG_SAMPLL_CLK1(n) << 22 | CPG_SAMPLL_CLK2(n) << 12) + +#define DDIV_PACK(offset, bitpos, size) \ + (((offset) << 20) | ((bitpos) << 12) | ((size) << 8)) +#define DIVPL2A DDIV_PACK(CPG_PL2_DDIV, 0, 3) +#define DIVPL3B DDIV_PACK(CPG_PL3A_DDIV, 4, 3) + +/** + * Definitions of CPG Core Clocks + * + * These include: + * - Clock outputs exported to DT + * - External input clocks + * - Internal CPG clocks + */ +struct cpg_core_clk { + const char *name; + unsigned int id; + unsigned int parent; + unsigned int div; + unsigned int mult; + unsigned int type; + unsigned int conf; + const struct clk_div_table *dtable; + const char * const *parent_names; + int flag; + int num_parents; +}; + +enum clk_types { + /* Generic */ + CLK_TYPE_IN, /* External Clock Input */ + CLK_TYPE_FF, /* Fixed Factor Clock */ + CLK_TYPE_SAM_PLL, + + /* Clock with divider */ + CLK_TYPE_DIV, +}; + +#define DEF_TYPE(_name, _id, _type...) \ + { .name = _name, .id = _id, .type = _type } +#define DEF_BASE(_name, _id, _type, _parent...) \ + DEF_TYPE(_name, _id, _type, .parent = _parent) +#define DEF_SAMPLL(_name, _id, _parent, _conf) \ + DEF_TYPE(_name, _id, CLK_TYPE_SAM_PLL, .parent = _parent, .conf = _conf) +#define DEF_INPUT(_name, _id) \ + DEF_TYPE(_name, _id, CLK_TYPE_IN) +#define DEF_FIXED(_name, _id, _parent, _mult, _div) \ + DEF_BASE(_name, _id, CLK_TYPE_FF, _parent, .div = _div, .mult = _mult) +#define DEF_DIV(_name, _id, _parent, _conf, _dtable, _flag) \ + DEF_TYPE(_name, _id, CLK_TYPE_DIV, .conf = _conf, \ + .parent = _parent, .dtable = _dtable, .flag = _flag) + +/** + * struct rzg2l_mod_clk - Module Clocks definitions + * + * @name: handle between common and hardware-specific interfaces + * @id: clock index in array containing all Core and Module Clocks + * @parent: id of parent clock + * @off: register offset + * @onoff: ON/MON bits + * @reset: reset bits + */ +struct rzg2l_mod_clk { + const char *name; + unsigned int id; + unsigned int parent; + u16 off; + u8 onoff; + u8 reset; +}; + +#define DEF_MOD(_name, _id, _parent, _off, _onoff, _reset) \ + [_id] = { \ + .name = _name, \ + .id = MOD_CLK_BASE + _id, \ + .parent = (_parent), \ + .off = (_off), \ + .onoff = (_onoff), \ + .reset = (_reset) \ + } + +/** + * struct rzg2l_cpg_info - SoC-specific CPG Description + * + * @core_clks: Array of Core Clock definitions + * @num_core_clks: Number of entries in core_clks[] + * @last_dt_core_clk: ID of the last Core Clock exported to DT + * @num_total_core_clks: Total number of Core Clocks (exported + internal) + * + * @mod_clks: Array of Module Clock definitions + * @num_mod_clks: Number of entries in mod_clks[] + * @num_hw_mod_clks: Number of Module Clocks supported by the hardware + * + * @crit_mod_clks: Array with Module Clock IDs of critical clocks that + * should not be disabled without a knowledgeable driver + * @num_crit_mod_clks: Number of entries in crit_mod_clks[] + */ +struct rzg2l_cpg_info { + /* Core Clocks */ + const struct cpg_core_clk *core_clks; + unsigned int num_core_clks; + unsigned int last_dt_core_clk; + unsigned int num_total_core_clks; + + /* Module Clocks */ + const struct rzg2l_mod_clk *mod_clks; + unsigned int num_mod_clks; + unsigned int num_hw_mod_clks; + + /* Critical Module Clocks that should not be disabled */ + const unsigned int *crit_mod_clks; + unsigned int num_crit_mod_clks; +}; + +extern const struct rzg2l_cpg_info r9a07g044_cpg_info; + +#endif diff --git a/drivers/clk/rockchip/clk-rk3036.c b/drivers/clk/rockchip/clk-rk3036.c index 91d56ad45817..614845cc5b4a 100644 --- a/drivers/clk/rockchip/clk-rk3036.c +++ b/drivers/clk/rockchip/clk-rk3036.c @@ -259,7 +259,7 @@ static struct rockchip_clk_branch rk3036_clk_branches[] __initdata = { RK2928_CLKGATE_CON(1), 13, GFLAGS, &rk3036_uart2_fracmux), - COMPOSITE(0, "aclk_vcodec", mux_pll_src_3plls_p, 0, + COMPOSITE(ACLK_VCODEC, "aclk_vcodec", mux_pll_src_3plls_p, 0, RK2928_CLKSEL_CON(32), 14, 2, MFLAGS, 8, 5, DFLAGS, RK2928_CLKGATE_CON(3), 11, GFLAGS), FACTOR_GATE(HCLK_VCODEC, "hclk_vcodec", "aclk_vcodec", 0, 1, 4, diff --git a/drivers/clk/rockchip/clk-rk3568.c b/drivers/clk/rockchip/clk-rk3568.c index 946ea2f45bf3..75ca855e720d 100644 --- a/drivers/clk/rockchip/clk-rk3568.c +++ b/drivers/clk/rockchip/clk-rk3568.c @@ -454,17 +454,17 @@ static struct rockchip_clk_branch rk3568_clk_branches[] __initdata = { COMPOSITE_NOMUX(CPLL_125M, "cpll_125m", "cpll", CLK_IGNORE_UNUSED, RK3568_CLKSEL_CON(80), 0, 5, DFLAGS, RK3568_CLKGATE_CON(35), 10, GFLAGS), + COMPOSITE_NOMUX(CPLL_100M, "cpll_100m", "cpll", CLK_IGNORE_UNUSED, + RK3568_CLKSEL_CON(82), 0, 5, DFLAGS, + RK3568_CLKGATE_CON(35), 11, GFLAGS), COMPOSITE_NOMUX(CPLL_62P5M, "cpll_62p5", "cpll", CLK_IGNORE_UNUSED, RK3568_CLKSEL_CON(80), 8, 5, DFLAGS, - RK3568_CLKGATE_CON(35), 11, GFLAGS), + RK3568_CLKGATE_CON(35), 12, GFLAGS), COMPOSITE_NOMUX(CPLL_50M, "cpll_50m", "cpll", CLK_IGNORE_UNUSED, RK3568_CLKSEL_CON(81), 0, 5, DFLAGS, - RK3568_CLKGATE_CON(35), 12, GFLAGS), + RK3568_CLKGATE_CON(35), 13, GFLAGS), COMPOSITE_NOMUX(CPLL_25M, "cpll_25m", "cpll", CLK_IGNORE_UNUSED, RK3568_CLKSEL_CON(81), 8, 6, DFLAGS, - RK3568_CLKGATE_CON(35), 13, GFLAGS), - COMPOSITE_NOMUX(CPLL_100M, "cpll_100m", "cpll", CLK_IGNORE_UNUSED, - RK3568_CLKSEL_CON(82), 0, 5, DFLAGS, RK3568_CLKGATE_CON(35), 14, GFLAGS), COMPOSITE_NOMUX(0, "clk_osc0_div_750k", "xin24m", CLK_IGNORE_UNUSED, RK3568_CLKSEL_CON(82), 8, 6, DFLAGS, diff --git a/drivers/clk/rockchip/clk.h b/drivers/clk/rockchip/clk.h index 571cee7bbfdc..7aa45cc70287 100644 --- a/drivers/clk/rockchip/clk.h +++ b/drivers/clk/rockchip/clk.h @@ -271,17 +271,24 @@ struct rockchip_clk_provider { struct rockchip_pll_rate_table { unsigned long rate; - unsigned int nr; - unsigned int nf; - unsigned int no; - unsigned int nb; - /* for RK3036/RK3399 */ - unsigned int fbdiv; - unsigned int postdiv1; - unsigned int refdiv; - unsigned int postdiv2; - unsigned int dsmpd; - unsigned int frac; + union { + struct { + /* for RK3066 */ + unsigned int nr; + unsigned int nf; + unsigned int no; + unsigned int nb; + }; + struct { + /* for RK3036/RK3399 */ + unsigned int fbdiv; + unsigned int postdiv1; + unsigned int refdiv; + unsigned int postdiv2; + unsigned int dsmpd; + unsigned int frac; + }; + }; }; /** diff --git a/drivers/clk/sifive/sifive-prci.c b/drivers/clk/sifive/sifive-prci.c index 0d79ba31a793..80a288c59e56 100644 --- a/drivers/clk/sifive/sifive-prci.c +++ b/drivers/clk/sifive/sifive-prci.c @@ -564,7 +564,7 @@ static int __prci_register_clocks(struct device *dev, struct __prci_data *pd, } /** - * sifive_prci_init() - initialize prci data and check parent count + * sifive_prci_probe() - initialize prci data and check parent count * @pdev: platform device pointer for the prci * * Return: 0 upon success or a negative error code upon failure. diff --git a/drivers/clk/socfpga/clk-agilex.c b/drivers/clk/socfpga/clk-agilex.c index 92a6d740a799..1cb21ea79c64 100644 --- a/drivers/clk/socfpga/clk-agilex.c +++ b/drivers/clk/socfpga/clk-agilex.c @@ -177,6 +177,8 @@ static const struct clk_parent_data emac_mux[] = { .name = "emaca_free_clk", }, { .fw_name = "emacb_free_clk", .name = "emacb_free_clk", }, + { .fw_name = "boot_clk", + .name = "boot_clk", }, }; static const struct clk_parent_data noc_mux[] = { @@ -186,6 +188,41 @@ static const struct clk_parent_data noc_mux[] = { .name = "boot_clk", }, }; +static const struct clk_parent_data sdmmc_mux[] = { + { .fw_name = "sdmmc_free_clk", + .name = "sdmmc_free_clk", }, + { .fw_name = "boot_clk", + .name = "boot_clk", }, +}; + +static const struct clk_parent_data s2f_user1_mux[] = { + { .fw_name = "s2f_user1_free_clk", + .name = "s2f_user1_free_clk", }, + { .fw_name = "boot_clk", + .name = "boot_clk", }, +}; + +static const struct clk_parent_data psi_mux[] = { + { .fw_name = "psi_ref_free_clk", + .name = "psi_ref_free_clk", }, + { .fw_name = "boot_clk", + .name = "boot_clk", }, +}; + +static const struct clk_parent_data gpio_db_mux[] = { + { .fw_name = "gpio_db_free_clk", + .name = "gpio_db_free_clk", }, + { .fw_name = "boot_clk", + .name = "boot_clk", }, +}; + +static const struct clk_parent_data emac_ptp_mux[] = { + { .fw_name = "emac_ptp_free_clk", + .name = "emac_ptp_free_clk", }, + { .fw_name = "boot_clk", + .name = "boot_clk", }, +}; + /* clocks in AO (always on) controller */ static const struct stratix10_pll_clock agilex_pll_clks[] = { { AGILEX_BOOT_CLK, "boot_clk", boot_mux, ARRAY_SIZE(boot_mux), 0, @@ -222,11 +259,9 @@ static const struct stratix10_perip_cnt_clock agilex_main_perip_cnt_clks[] = { { AGILEX_MPU_FREE_CLK, "mpu_free_clk", NULL, mpu_free_mux, ARRAY_SIZE(mpu_free_mux), 0, 0x3C, 0, 0, 0}, { AGILEX_NOC_FREE_CLK, "noc_free_clk", NULL, noc_free_mux, ARRAY_SIZE(noc_free_mux), - 0, 0x40, 0, 0, 1}, - { AGILEX_L4_SYS_FREE_CLK, "l4_sys_free_clk", "noc_free_clk", NULL, 1, 0, - 0, 4, 0, 0}, - { AGILEX_NOC_CLK, "noc_clk", NULL, noc_mux, ARRAY_SIZE(noc_mux), - 0, 0, 0, 0x30, 1}, + 0, 0x40, 0, 0, 0}, + { AGILEX_L4_SYS_FREE_CLK, "l4_sys_free_clk", NULL, noc_mux, ARRAY_SIZE(noc_mux), 0, + 0, 4, 0x30, 1}, { AGILEX_EMAC_A_FREE_CLK, "emaca_free_clk", NULL, emaca_free_mux, ARRAY_SIZE(emaca_free_mux), 0, 0xD4, 0, 0x88, 0}, { AGILEX_EMAC_B_FREE_CLK, "emacb_free_clk", NULL, emacb_free_mux, ARRAY_SIZE(emacb_free_mux), @@ -236,7 +271,7 @@ static const struct stratix10_perip_cnt_clock agilex_main_perip_cnt_clks[] = { { AGILEX_GPIO_DB_FREE_CLK, "gpio_db_free_clk", NULL, gpio_db_free_mux, ARRAY_SIZE(gpio_db_free_mux), 0, 0xE0, 0, 0x88, 3}, { AGILEX_SDMMC_FREE_CLK, "sdmmc_free_clk", NULL, sdmmc_free_mux, - ARRAY_SIZE(sdmmc_free_mux), 0, 0xE4, 0, 0x88, 4}, + ARRAY_SIZE(sdmmc_free_mux), 0, 0xE4, 0, 0, 0}, { AGILEX_S2F_USER0_FREE_CLK, "s2f_user0_free_clk", NULL, s2f_usr0_free_mux, ARRAY_SIZE(s2f_usr0_free_mux), 0, 0xE8, 0, 0, 0}, { AGILEX_S2F_USER1_FREE_CLK, "s2f_user1_free_clk", NULL, s2f_usr1_free_mux, @@ -252,24 +287,24 @@ static const struct stratix10_gate_clock agilex_gate_clks[] = { 0, 0, 0, 0, 0, 0, 4}, { AGILEX_MPU_CCU_CLK, "mpu_ccu_clk", "mpu_clk", NULL, 1, 0, 0x24, 0, 0, 0, 0, 0, 0, 2}, - { AGILEX_L4_MAIN_CLK, "l4_main_clk", "noc_clk", NULL, 1, 0, 0x24, - 1, 0x44, 0, 2, 0, 0, 0}, - { AGILEX_L4_MP_CLK, "l4_mp_clk", "noc_clk", NULL, 1, 0, 0x24, - 2, 0x44, 8, 2, 0, 0, 0}, + { AGILEX_L4_MAIN_CLK, "l4_main_clk", NULL, noc_mux, ARRAY_SIZE(noc_mux), 0, 0x24, + 1, 0x44, 0, 2, 0x30, 1, 0}, + { AGILEX_L4_MP_CLK, "l4_mp_clk", NULL, noc_mux, ARRAY_SIZE(noc_mux), 0, 0x24, + 2, 0x44, 8, 2, 0x30, 1, 0}, /* * The l4_sp_clk feeds a 100 MHz clock to various peripherals, one of them * being the SP timers, thus cannot get gated. */ - { AGILEX_L4_SP_CLK, "l4_sp_clk", "noc_clk", NULL, 1, CLK_IS_CRITICAL, 0x24, - 3, 0x44, 16, 2, 0, 0, 0}, - { AGILEX_CS_AT_CLK, "cs_at_clk", "noc_clk", NULL, 1, 0, 0x24, - 4, 0x44, 24, 2, 0, 0, 0}, - { AGILEX_CS_TRACE_CLK, "cs_trace_clk", "noc_clk", NULL, 1, 0, 0x24, - 4, 0x44, 26, 2, 0, 0, 0}, + { AGILEX_L4_SP_CLK, "l4_sp_clk", NULL, noc_mux, ARRAY_SIZE(noc_mux), CLK_IS_CRITICAL, 0x24, + 3, 0x44, 16, 2, 0x30, 1, 0}, + { AGILEX_CS_AT_CLK, "cs_at_clk", NULL, noc_mux, ARRAY_SIZE(noc_mux), 0, 0x24, + 4, 0x44, 24, 2, 0x30, 1, 0}, + { AGILEX_CS_TRACE_CLK, "cs_trace_clk", NULL, noc_mux, ARRAY_SIZE(noc_mux), 0, 0x24, + 4, 0x44, 26, 2, 0x30, 1, 0}, { AGILEX_CS_PDBG_CLK, "cs_pdbg_clk", "cs_at_clk", NULL, 1, 0, 0x24, 4, 0x44, 28, 1, 0, 0, 0}, - { AGILEX_CS_TIMER_CLK, "cs_timer_clk", "noc_clk", NULL, 1, 0, 0x24, - 5, 0, 0, 0, 0, 0, 0}, + { AGILEX_CS_TIMER_CLK, "cs_timer_clk", NULL, noc_mux, ARRAY_SIZE(noc_mux), 0, 0x24, + 5, 0, 0, 0, 0x30, 1, 0}, { AGILEX_S2F_USER0_CLK, "s2f_user0_clk", NULL, s2f_usr0_mux, ARRAY_SIZE(s2f_usr0_mux), 0, 0x24, 6, 0, 0, 0, 0, 0, 0}, { AGILEX_EMAC0_CLK, "emac0_clk", NULL, emac_mux, ARRAY_SIZE(emac_mux), 0, 0x7C, @@ -278,16 +313,16 @@ static const struct stratix10_gate_clock agilex_gate_clks[] = { 1, 0, 0, 0, 0x94, 27, 0}, { AGILEX_EMAC2_CLK, "emac2_clk", NULL, emac_mux, ARRAY_SIZE(emac_mux), 0, 0x7C, 2, 0, 0, 0, 0x94, 28, 0}, - { AGILEX_EMAC_PTP_CLK, "emac_ptp_clk", "emac_ptp_free_clk", NULL, 1, 0, 0x7C, - 3, 0, 0, 0, 0, 0, 0}, - { AGILEX_GPIO_DB_CLK, "gpio_db_clk", "gpio_db_free_clk", NULL, 1, 0, 0x7C, - 4, 0x98, 0, 16, 0, 0, 0}, - { AGILEX_SDMMC_CLK, "sdmmc_clk", "sdmmc_free_clk", NULL, 1, 0, 0x7C, - 5, 0, 0, 0, 0, 0, 4}, - { AGILEX_S2F_USER1_CLK, "s2f_user1_clk", "s2f_user1_free_clk", NULL, 1, 0, 0x7C, - 6, 0, 0, 0, 0, 0, 0}, - { AGILEX_PSI_REF_CLK, "psi_ref_clk", "psi_ref_free_clk", NULL, 1, 0, 0x7C, - 7, 0, 0, 0, 0, 0, 0}, + { AGILEX_EMAC_PTP_CLK, "emac_ptp_clk", NULL, emac_ptp_mux, ARRAY_SIZE(emac_ptp_mux), 0, 0x7C, + 3, 0, 0, 0, 0x88, 2, 0}, + { AGILEX_GPIO_DB_CLK, "gpio_db_clk", NULL, gpio_db_mux, ARRAY_SIZE(gpio_db_mux), 0, 0x7C, + 4, 0x98, 0, 16, 0x88, 3, 0}, + { AGILEX_SDMMC_CLK, "sdmmc_clk", NULL, sdmmc_mux, ARRAY_SIZE(sdmmc_mux), 0, 0x7C, + 5, 0, 0, 0, 0x88, 4, 4}, + { AGILEX_S2F_USER1_CLK, "s2f_user1_clk", NULL, s2f_user1_mux, ARRAY_SIZE(s2f_user1_mux), 0, 0x7C, + 6, 0, 0, 0, 0x88, 5, 0}, + { AGILEX_PSI_REF_CLK, "psi_ref_clk", NULL, psi_mux, ARRAY_SIZE(psi_mux), 0, 0x7C, + 7, 0, 0, 0, 0x88, 6, 0}, { AGILEX_USB_CLK, "usb_clk", "l4_mp_clk", NULL, 1, 0, 0x7C, 8, 0, 0, 0, 0, 0, 0}, { AGILEX_SPI_M_CLK, "spi_m_clk", "l4_mp_clk", NULL, 1, 0, 0x7C, @@ -366,7 +401,7 @@ static int agilex_clk_register_gate(const struct stratix10_gate_clock *clks, int i; for (i = 0; i < nums; i++) { - hw_clk = s10_register_gate(&clks[i], base); + hw_clk = agilex_register_gate(&clks[i], base); if (IS_ERR(hw_clk)) { pr_err("%s: failed to register clock %s\n", __func__, clks[i].name); diff --git a/drivers/clk/socfpga/clk-gate-s10.c b/drivers/clk/socfpga/clk-gate-s10.c index b84f2627551e..32567795765f 100644 --- a/drivers/clk/socfpga/clk-gate-s10.c +++ b/drivers/clk/socfpga/clk-gate-s10.c @@ -11,6 +11,13 @@ #define SOCFPGA_CS_PDBG_CLK "cs_pdbg_clk" #define to_socfpga_gate_clk(p) container_of(p, struct socfpga_gate_clk, hw.hw) +#define SOCFPGA_EMAC0_CLK "emac0_clk" +#define SOCFPGA_EMAC1_CLK "emac1_clk" +#define SOCFPGA_EMAC2_CLK "emac2_clk" +#define AGILEX_BYPASS_OFFSET 0xC +#define STRATIX10_BYPASS_OFFSET 0x2C +#define BOOTCLK_BYPASS 2 + static unsigned long socfpga_gate_clk_recalc_rate(struct clk_hw *hwclk, unsigned long parent_rate) { @@ -44,14 +51,61 @@ static unsigned long socfpga_dbg_clk_recalc_rate(struct clk_hw *hwclk, static u8 socfpga_gate_get_parent(struct clk_hw *hwclk) { struct socfpga_gate_clk *socfpgaclk = to_socfpga_gate_clk(hwclk); - u32 mask; + u32 mask, second_bypass; + u8 parent = 0; + const char *name = clk_hw_get_name(hwclk); + + if (socfpgaclk->bypass_reg) { + mask = (0x1 << socfpgaclk->bypass_shift); + parent = ((readl(socfpgaclk->bypass_reg) & mask) >> + socfpgaclk->bypass_shift); + } + + if (streq(name, SOCFPGA_EMAC0_CLK) || + streq(name, SOCFPGA_EMAC1_CLK) || + streq(name, SOCFPGA_EMAC2_CLK)) { + second_bypass = readl(socfpgaclk->bypass_reg - + STRATIX10_BYPASS_OFFSET); + /* EMACA bypass to bootclk @0xB0 offset */ + if (second_bypass & 0x1) + if (parent == 0) /* only applicable if parent is maca */ + parent = BOOTCLK_BYPASS; + + if (second_bypass & 0x2) + if (parent == 1) /* only applicable if parent is macb */ + parent = BOOTCLK_BYPASS; + } + return parent; +} + +static u8 socfpga_agilex_gate_get_parent(struct clk_hw *hwclk) +{ + struct socfpga_gate_clk *socfpgaclk = to_socfpga_gate_clk(hwclk); + u32 mask, second_bypass; u8 parent = 0; + const char *name = clk_hw_get_name(hwclk); if (socfpgaclk->bypass_reg) { mask = (0x1 << socfpgaclk->bypass_shift); parent = ((readl(socfpgaclk->bypass_reg) & mask) >> socfpgaclk->bypass_shift); } + + if (streq(name, SOCFPGA_EMAC0_CLK) || + streq(name, SOCFPGA_EMAC1_CLK) || + streq(name, SOCFPGA_EMAC2_CLK)) { + second_bypass = readl(socfpgaclk->bypass_reg - + AGILEX_BYPASS_OFFSET); + /* EMACA bypass to bootclk @0x88 offset */ + if (second_bypass & 0x1) + if (parent == 0) /* only applicable if parent is maca */ + parent = BOOTCLK_BYPASS; + + if (second_bypass & 0x2) + if (parent == 1) /* only applicable if parent is macb */ + parent = BOOTCLK_BYPASS; + } + return parent; } @@ -60,6 +114,11 @@ static struct clk_ops gateclk_ops = { .get_parent = socfpga_gate_get_parent, }; +static const struct clk_ops agilex_gateclk_ops = { + .recalc_rate = socfpga_gate_clk_recalc_rate, + .get_parent = socfpga_agilex_gate_get_parent, +}; + static const struct clk_ops dbgclk_ops = { .recalc_rate = socfpga_dbg_clk_recalc_rate, .get_parent = socfpga_gate_get_parent, @@ -122,3 +181,61 @@ struct clk_hw *s10_register_gate(const struct stratix10_gate_clock *clks, void _ } return hw_clk; } + +struct clk_hw *agilex_register_gate(const struct stratix10_gate_clock *clks, void __iomem *regbase) +{ + struct clk_hw *hw_clk; + struct socfpga_gate_clk *socfpga_clk; + struct clk_init_data init; + const char *parent_name = clks->parent_name; + int ret; + + socfpga_clk = kzalloc(sizeof(*socfpga_clk), GFP_KERNEL); + if (!socfpga_clk) + return NULL; + + socfpga_clk->hw.reg = regbase + clks->gate_reg; + socfpga_clk->hw.bit_idx = clks->gate_idx; + + gateclk_ops.enable = clk_gate_ops.enable; + gateclk_ops.disable = clk_gate_ops.disable; + + socfpga_clk->fixed_div = clks->fixed_div; + + if (clks->div_reg) + socfpga_clk->div_reg = regbase + clks->div_reg; + else + socfpga_clk->div_reg = NULL; + + socfpga_clk->width = clks->div_width; + socfpga_clk->shift = clks->div_offset; + + if (clks->bypass_reg) + socfpga_clk->bypass_reg = regbase + clks->bypass_reg; + else + socfpga_clk->bypass_reg = NULL; + socfpga_clk->bypass_shift = clks->bypass_shift; + + if (streq(clks->name, "cs_pdbg_clk")) + init.ops = &dbgclk_ops; + else + init.ops = &agilex_gateclk_ops; + + init.name = clks->name; + init.flags = clks->flags; + + init.num_parents = clks->num_parents; + init.parent_names = parent_name ? &parent_name : NULL; + if (init.parent_names == NULL) + init.parent_data = clks->parent_data; + socfpga_clk->hw.hw.init = &init; + + hw_clk = &socfpga_clk->hw.hw; + + ret = clk_hw_register(NULL, &socfpga_clk->hw.hw); + if (ret) { + kfree(socfpga_clk); + return ERR_PTR(ret); + } + return hw_clk; +} diff --git a/drivers/clk/socfpga/clk-periph-s10.c b/drivers/clk/socfpga/clk-periph-s10.c index e5a5fef76df7..cbabde2b476b 100644 --- a/drivers/clk/socfpga/clk-periph-s10.c +++ b/drivers/clk/socfpga/clk-periph-s10.c @@ -64,16 +64,21 @@ static u8 clk_periclk_get_parent(struct clk_hw *hwclk) { struct socfpga_periph_clk *socfpgaclk = to_periph_clk(hwclk); u32 clk_src, mask; - u8 parent; + u8 parent = 0; + /* handle the bypass first */ if (socfpgaclk->bypass_reg) { mask = (0x1 << socfpgaclk->bypass_shift); parent = ((readl(socfpgaclk->bypass_reg) & mask) >> socfpgaclk->bypass_shift); - } else { + if (parent) + return parent; + } + + if (socfpgaclk->hw.reg) { clk_src = readl(socfpgaclk->hw.reg); parent = (clk_src >> CLK_MGR_FREE_SHIFT) & - CLK_MGR_FREE_MASK; + CLK_MGR_FREE_MASK; } return parent; } diff --git a/drivers/clk/socfpga/clk-pll.c b/drivers/clk/socfpga/clk-pll.c index dcb573d44034..127cc849c5ee 100644 --- a/drivers/clk/socfpga/clk-pll.c +++ b/drivers/clk/socfpga/clk-pll.c @@ -80,7 +80,6 @@ static __init struct clk_hw *__socfpga_pll_init(struct device_node *node, const char *parent_name[SOCFPGA_MAX_PARENTS]; struct clk_init_data init; struct device_node *clkmgr_np; - int rc; int err; of_property_read_u32(node, "reg", ®); @@ -114,7 +113,7 @@ static __init struct clk_hw *__socfpga_pll_init(struct device_node *node, kfree(pll_clk); return ERR_PTR(err); } - rc = of_clk_add_provider(node, of_clk_src_simple_get, hw_clk); + of_clk_add_provider(node, of_clk_src_simple_get, hw_clk); return hw_clk; } diff --git a/drivers/clk/socfpga/clk-s10.c b/drivers/clk/socfpga/clk-s10.c index f0bd77138ecb..b532d51faaee 100644 --- a/drivers/clk/socfpga/clk-s10.c +++ b/drivers/clk/socfpga/clk-s10.c @@ -144,6 +144,41 @@ static const struct clk_parent_data mpu_free_mux[] = { .name = "f2s-free-clk", }, }; +static const struct clk_parent_data sdmmc_mux[] = { + { .fw_name = "sdmmc_free_clk", + .name = "sdmmc_free_clk", }, + { .fw_name = "boot_clk", + .name = "boot_clk", }, +}; + +static const struct clk_parent_data s2f_user1_mux[] = { + { .fw_name = "s2f_user1_free_clk", + .name = "s2f_user1_free_clk", }, + { .fw_name = "boot_clk", + .name = "boot_clk", }, +}; + +static const struct clk_parent_data psi_mux[] = { + { .fw_name = "psi_ref_free_clk", + .name = "psi_ref_free_clk", }, + { .fw_name = "boot_clk", + .name = "boot_clk", }, +}; + +static const struct clk_parent_data gpio_db_mux[] = { + { .fw_name = "gpio_db_free_clk", + .name = "gpio_db_free_clk", }, + { .fw_name = "boot_clk", + .name = "boot_clk", }, +}; + +static const struct clk_parent_data emac_ptp_mux[] = { + { .fw_name = "emac_ptp_free_clk", + .name = "emac_ptp_free_clk", }, + { .fw_name = "boot_clk", + .name = "boot_clk", }, +}; + /* clocks in AO (always on) controller */ static const struct stratix10_pll_clock s10_pll_clks[] = { { STRATIX10_BOOT_CLK, "boot_clk", boot_mux, ARRAY_SIZE(boot_mux), 0, @@ -167,7 +202,7 @@ static const struct stratix10_perip_cnt_clock s10_main_perip_cnt_clks[] = { { STRATIX10_MPU_FREE_CLK, "mpu_free_clk", NULL, mpu_free_mux, ARRAY_SIZE(mpu_free_mux), 0, 0x48, 0, 0, 0}, { STRATIX10_NOC_FREE_CLK, "noc_free_clk", NULL, noc_free_mux, ARRAY_SIZE(noc_free_mux), - 0, 0x4C, 0, 0, 0}, + 0, 0x4C, 0, 0x3C, 1}, { STRATIX10_MAIN_EMACA_CLK, "main_emaca_clk", "main_noc_base_clk", NULL, 1, 0, 0x50, 0, 0, 0}, { STRATIX10_MAIN_EMACB_CLK, "main_emacb_clk", "main_noc_base_clk", NULL, 1, 0, @@ -200,10 +235,8 @@ static const struct stratix10_perip_cnt_clock s10_main_perip_cnt_clks[] = { 0, 0xD4, 0, 0, 0}, { STRATIX10_PERI_PSI_REF_CLK, "peri_psi_ref_clk", "peri_noc_base_clk", NULL, 1, 0, 0xD8, 0, 0, 0}, - { STRATIX10_L4_SYS_FREE_CLK, "l4_sys_free_clk", "noc_free_clk", NULL, 1, 0, - 0, 4, 0, 0}, - { STRATIX10_NOC_CLK, "noc_clk", NULL, noc_mux, ARRAY_SIZE(noc_mux), - 0, 0, 0, 0x3C, 1}, + { STRATIX10_L4_SYS_FREE_CLK, "l4_sys_free_clk", NULL, noc_mux, ARRAY_SIZE(noc_mux), 0, + 0, 4, 0x3C, 1}, { STRATIX10_EMAC_A_FREE_CLK, "emaca_free_clk", NULL, emaca_free_mux, ARRAY_SIZE(emaca_free_mux), 0, 0, 2, 0xB0, 0}, { STRATIX10_EMAC_B_FREE_CLK, "emacb_free_clk", NULL, emacb_free_mux, ARRAY_SIZE(emacb_free_mux), @@ -227,20 +260,20 @@ static const struct stratix10_gate_clock s10_gate_clks[] = { 0, 0, 0, 0, 0, 0, 4}, { STRATIX10_MPU_L2RAM_CLK, "mpu_l2ram_clk", "mpu_clk", NULL, 1, 0, 0x30, 0, 0, 0, 0, 0, 0, 2}, - { STRATIX10_L4_MAIN_CLK, "l4_main_clk", "noc_clk", NULL, 1, 0, 0x30, - 1, 0x70, 0, 2, 0, 0, 0}, - { STRATIX10_L4_MP_CLK, "l4_mp_clk", "noc_clk", NULL, 1, 0, 0x30, - 2, 0x70, 8, 2, 0, 0, 0}, - { STRATIX10_L4_SP_CLK, "l4_sp_clk", "noc_clk", NULL, 1, CLK_IS_CRITICAL, 0x30, - 3, 0x70, 16, 2, 0, 0, 0}, - { STRATIX10_CS_AT_CLK, "cs_at_clk", "noc_clk", NULL, 1, 0, 0x30, - 4, 0x70, 24, 2, 0, 0, 0}, - { STRATIX10_CS_TRACE_CLK, "cs_trace_clk", "noc_clk", NULL, 1, 0, 0x30, - 4, 0x70, 26, 2, 0, 0, 0}, + { STRATIX10_L4_MAIN_CLK, "l4_main_clk", NULL, noc_mux, ARRAY_SIZE(noc_mux), 0, 0x30, + 1, 0x70, 0, 2, 0x3C, 1, 0}, + { STRATIX10_L4_MP_CLK, "l4_mp_clk", NULL, noc_mux, ARRAY_SIZE(noc_mux), 0, 0x30, + 2, 0x70, 8, 2, 0x3C, 1, 0}, + { STRATIX10_L4_SP_CLK, "l4_sp_clk", NULL, noc_mux, ARRAY_SIZE(noc_mux), CLK_IS_CRITICAL, 0x30, + 3, 0x70, 16, 2, 0x3C, 1, 0}, + { STRATIX10_CS_AT_CLK, "cs_at_clk", NULL, noc_mux, ARRAY_SIZE(noc_mux), 0, 0x30, + 4, 0x70, 24, 2, 0x3C, 1, 0}, + { STRATIX10_CS_TRACE_CLK, "cs_trace_clk", NULL, noc_mux, ARRAY_SIZE(noc_mux), 0, 0x30, + 4, 0x70, 26, 2, 0x3C, 1, 0}, { STRATIX10_CS_PDBG_CLK, "cs_pdbg_clk", "cs_at_clk", NULL, 1, 0, 0x30, 4, 0x70, 28, 1, 0, 0, 0}, - { STRATIX10_CS_TIMER_CLK, "cs_timer_clk", "noc_clk", NULL, 1, 0, 0x30, - 5, 0, 0, 0, 0, 0, 0}, + { STRATIX10_CS_TIMER_CLK, "cs_timer_clk", NULL, noc_mux, ARRAY_SIZE(noc_mux), 0, 0x30, + 5, 0, 0, 0, 0x3C, 1, 0}, { STRATIX10_S2F_USER0_CLK, "s2f_user0_clk", NULL, s2f_usr0_mux, ARRAY_SIZE(s2f_usr0_mux), 0, 0x30, 6, 0, 0, 0, 0, 0, 0}, { STRATIX10_EMAC0_CLK, "emac0_clk", NULL, emac_mux, ARRAY_SIZE(emac_mux), 0, 0xA4, @@ -249,16 +282,16 @@ static const struct stratix10_gate_clock s10_gate_clks[] = { 1, 0, 0, 0, 0xDC, 27, 0}, { STRATIX10_EMAC2_CLK, "emac2_clk", NULL, emac_mux, ARRAY_SIZE(emac_mux), 0, 0xA4, 2, 0, 0, 0, 0xDC, 28, 0}, - { STRATIX10_EMAC_PTP_CLK, "emac_ptp_clk", "emac_ptp_free_clk", NULL, 1, 0, 0xA4, - 3, 0, 0, 0, 0, 0, 0}, - { STRATIX10_GPIO_DB_CLK, "gpio_db_clk", "gpio_db_free_clk", NULL, 1, 0, 0xA4, - 4, 0xE0, 0, 16, 0, 0, 0}, - { STRATIX10_SDMMC_CLK, "sdmmc_clk", "sdmmc_free_clk", NULL, 1, 0, 0xA4, - 5, 0, 0, 0, 0, 0, 4}, - { STRATIX10_S2F_USER1_CLK, "s2f_user1_clk", "s2f_user1_free_clk", NULL, 1, 0, 0xA4, - 6, 0, 0, 0, 0, 0, 0}, - { STRATIX10_PSI_REF_CLK, "psi_ref_clk", "psi_ref_free_clk", NULL, 1, 0, 0xA4, - 7, 0, 0, 0, 0, 0, 0}, + { STRATIX10_EMAC_PTP_CLK, "emac_ptp_clk", NULL, emac_ptp_mux, ARRAY_SIZE(emac_ptp_mux), 0, 0xA4, + 3, 0, 0, 0, 0xB0, 2, 0}, + { STRATIX10_GPIO_DB_CLK, "gpio_db_clk", NULL, gpio_db_mux, ARRAY_SIZE(gpio_db_mux), 0, 0xA4, + 4, 0xE0, 0, 16, 0xB0, 3, 0}, + { STRATIX10_SDMMC_CLK, "sdmmc_clk", NULL, sdmmc_mux, ARRAY_SIZE(sdmmc_mux), 0, 0xA4, + 5, 0, 0, 0, 0xB0, 4, 4}, + { STRATIX10_S2F_USER1_CLK, "s2f_user1_clk", NULL, s2f_user1_mux, ARRAY_SIZE(s2f_user1_mux), 0, 0xA4, + 6, 0, 0, 0, 0xB0, 5, 0}, + { STRATIX10_PSI_REF_CLK, "psi_ref_clk", NULL, psi_mux, ARRAY_SIZE(psi_mux), 0, 0xA4, + 7, 0, 0, 0, 0xB0, 6, 0}, { STRATIX10_USB_CLK, "usb_clk", "l4_mp_clk", NULL, 1, 0, 0xA4, 8, 0, 0, 0, 0, 0, 0}, { STRATIX10_SPI_M_CLK, "spi_m_clk", "l4_mp_clk", NULL, 1, 0, 0xA4, diff --git a/drivers/clk/socfpga/stratix10-clk.h b/drivers/clk/socfpga/stratix10-clk.h index 61eaf3a41fbb..75234e0783e1 100644 --- a/drivers/clk/socfpga/stratix10-clk.h +++ b/drivers/clk/socfpga/stratix10-clk.h @@ -85,4 +85,6 @@ struct clk_hw *s10_register_cnt_periph(const struct stratix10_perip_cnt_clock *c void __iomem *reg); struct clk_hw *s10_register_gate(const struct stratix10_gate_clock *clks, void __iomem *reg); +struct clk_hw *agilex_register_gate(const struct stratix10_gate_clock *clks, + void __iomem *reg); #endif /* __STRATIX10_CLK_H */ diff --git a/drivers/clk/st/clk-flexgen.c b/drivers/clk/st/clk-flexgen.c index 55873d4b7603..7ae4f656191e 100644 --- a/drivers/clk/st/clk-flexgen.c +++ b/drivers/clk/st/clk-flexgen.c @@ -16,9 +16,16 @@ #include <linux/of.h> #include <linux/of_address.h> +struct clkgen_clk_out { + const char *name; + unsigned long flags; +}; + struct clkgen_data { unsigned long flags; bool mode; + const struct clkgen_clk_out *outputs; + const unsigned int outputs_nb; }; struct flexgen { @@ -295,6 +302,290 @@ static const struct clkgen_data clkgen_video = { .mode = 1, }; +static const struct clkgen_clk_out clkgen_stih407_a0_clk_out[] = { + /* This clk needs to be on so that memory interface is accessible */ + { .name = "clk-ic-lmi0", .flags = CLK_IS_CRITICAL }, +}; + +static const struct clkgen_data clkgen_stih407_a0 = { + .outputs = clkgen_stih407_a0_clk_out, + .outputs_nb = ARRAY_SIZE(clkgen_stih407_a0_clk_out), +}; + +static const struct clkgen_clk_out clkgen_stih410_a0_clk_out[] = { + /* Those clks need to be on so that memory interface is accessible */ + { .name = "clk-ic-lmi0", .flags = CLK_IS_CRITICAL }, + { .name = "clk-ic-lmi1", .flags = CLK_IS_CRITICAL }, +}; + +static const struct clkgen_data clkgen_stih410_a0 = { + .outputs = clkgen_stih410_a0_clk_out, + .outputs_nb = ARRAY_SIZE(clkgen_stih410_a0_clk_out), +}; + +static const struct clkgen_clk_out clkgen_stih407_c0_clk_out[] = { + { .name = "clk-icn-gpu", }, + { .name = "clk-fdma", }, + { .name = "clk-nand", }, + { .name = "clk-hva", }, + { .name = "clk-proc-stfe", }, + { .name = "clk-proc-tp", }, + { .name = "clk-rx-icn-dmu", }, + { .name = "clk-rx-icn-hva", }, + /* This clk needs to be on to keep bus interconnect alive */ + { .name = "clk-icn-cpu", .flags = CLK_IS_CRITICAL }, + /* This clk needs to be on to keep bus interconnect alive */ + { .name = "clk-tx-icn-dmu", .flags = CLK_IS_CRITICAL }, + { .name = "clk-mmc-0", }, + { .name = "clk-mmc-1", }, + { .name = "clk-jpegdec", }, + /* This clk needs to be on to keep A9 running */ + { .name = "clk-ext2fa9", .flags = CLK_IS_CRITICAL }, + { .name = "clk-ic-bdisp-0", }, + { .name = "clk-ic-bdisp-1", }, + { .name = "clk-pp-dmu", }, + { .name = "clk-vid-dmu", }, + { .name = "clk-dss-lpc", }, + { .name = "clk-st231-aud-0", }, + { .name = "clk-st231-gp-1", }, + { .name = "clk-st231-dmu", }, + /* This clk needs to be on to keep bus interconnect alive */ + { .name = "clk-icn-lmi", .flags = CLK_IS_CRITICAL }, + { .name = "clk-tx-icn-disp-1", }, + /* This clk needs to be on to keep bus interconnect alive */ + { .name = "clk-icn-sbc", .flags = CLK_IS_CRITICAL }, + { .name = "clk-stfe-frc2", }, + { .name = "clk-eth-phy", }, + { .name = "clk-eth-ref-phyclk", }, + { .name = "clk-flash-promip", }, + { .name = "clk-main-disp", }, + { .name = "clk-aux-disp", }, + { .name = "clk-compo-dvp", }, +}; + +static const struct clkgen_data clkgen_stih407_c0 = { + .outputs = clkgen_stih407_c0_clk_out, + .outputs_nb = ARRAY_SIZE(clkgen_stih407_c0_clk_out), +}; + +static const struct clkgen_clk_out clkgen_stih410_c0_clk_out[] = { + { .name = "clk-icn-gpu", }, + { .name = "clk-fdma", }, + { .name = "clk-nand", }, + { .name = "clk-hva", }, + { .name = "clk-proc-stfe", }, + { .name = "clk-proc-tp", }, + { .name = "clk-rx-icn-dmu", }, + { .name = "clk-rx-icn-hva", }, + /* This clk needs to be on to keep bus interconnect alive */ + { .name = "clk-icn-cpu", .flags = CLK_IS_CRITICAL }, + /* This clk needs to be on to keep bus interconnect alive */ + { .name = "clk-tx-icn-dmu", .flags = CLK_IS_CRITICAL }, + { .name = "clk-mmc-0", }, + { .name = "clk-mmc-1", }, + { .name = "clk-jpegdec", }, + /* This clk needs to be on to keep A9 running */ + { .name = "clk-ext2fa9", .flags = CLK_IS_CRITICAL }, + { .name = "clk-ic-bdisp-0", }, + { .name = "clk-ic-bdisp-1", }, + { .name = "clk-pp-dmu", }, + { .name = "clk-vid-dmu", }, + { .name = "clk-dss-lpc", }, + { .name = "clk-st231-aud-0", }, + { .name = "clk-st231-gp-1", }, + { .name = "clk-st231-dmu", }, + /* This clk needs to be on to keep bus interconnect alive */ + { .name = "clk-icn-lmi", .flags = CLK_IS_CRITICAL }, + { .name = "clk-tx-icn-disp-1", }, + /* This clk needs to be on to keep bus interconnect alive */ + { .name = "clk-icn-sbc", .flags = CLK_IS_CRITICAL }, + { .name = "clk-stfe-frc2", }, + { .name = "clk-eth-phy", }, + { .name = "clk-eth-ref-phyclk", }, + { .name = "clk-flash-promip", }, + { .name = "clk-main-disp", }, + { .name = "clk-aux-disp", }, + { .name = "clk-compo-dvp", }, + { .name = "clk-tx-icn-hades", }, + { .name = "clk-rx-icn-hades", }, + /* This clk needs to be on to keep bus interconnect alive */ + { .name = "clk-icn-reg-16", .flags = CLK_IS_CRITICAL }, + { .name = "clk-pp-hades", }, + { .name = "clk-clust-hades", }, + { .name = "clk-hwpe-hades", }, + { .name = "clk-fc-hades", }, +}; + +static const struct clkgen_data clkgen_stih410_c0 = { + .outputs = clkgen_stih410_c0_clk_out, + .outputs_nb = ARRAY_SIZE(clkgen_stih410_c0_clk_out), +}; + +static const struct clkgen_clk_out clkgen_stih418_c0_clk_out[] = { + { .name = "clk-icn-gpu", }, + { .name = "clk-fdma", }, + { .name = "clk-nand", }, + { .name = "clk-hva", }, + { .name = "clk-proc-stfe", }, + { .name = "clk-tp", }, + /* This clk needs to be on to keep bus interconnect alive */ + { .name = "clk-rx-icn-dmu", .flags = CLK_IS_CRITICAL }, + /* This clk needs to be on to keep bus interconnect alive */ + { .name = "clk-rx-icn-hva", .flags = CLK_IS_CRITICAL }, + { .name = "clk-icn-cpu", .flags = CLK_IS_CRITICAL }, + /* This clk needs to be on to keep bus interconnect alive */ + { .name = "clk-tx-icn-dmu", .flags = CLK_IS_CRITICAL }, + { .name = "clk-mmc-0", }, + { .name = "clk-mmc-1", }, + { .name = "clk-jpegdec", }, + /* This clk needs to be on to keep bus interconnect alive */ + { .name = "clk-icn-reg", .flags = CLK_IS_CRITICAL }, + { .name = "clk-proc-bdisp-0", }, + { .name = "clk-proc-bdisp-1", }, + { .name = "clk-pp-dmu", }, + { .name = "clk-vid-dmu", }, + { .name = "clk-dss-lpc", }, + { .name = "clk-st231-aud-0", }, + { .name = "clk-st231-gp-1", }, + { .name = "clk-st231-dmu", }, + /* This clk needs to be on to keep bus interconnect alive */ + { .name = "clk-icn-lmi", .flags = CLK_IS_CRITICAL }, + /* This clk needs to be on to keep bus interconnect alive */ + { .name = "clk-tx-icn-1", .flags = CLK_IS_CRITICAL }, + /* This clk needs to be on to keep bus interconnect alive */ + { .name = "clk-icn-sbc", .flags = CLK_IS_CRITICAL }, + { .name = "clk-stfe-frc2", }, + { .name = "clk-eth-phyref", }, + { .name = "clk-eth-ref-phyclk", }, + { .name = "clk-flash-promip", }, + { .name = "clk-main-disp", }, + { .name = "clk-aux-disp", }, + { .name = "clk-compo-dvp", }, + /* This clk needs to be on to keep bus interconnect alive */ + { .name = "clk-tx-icn-hades", .flags = CLK_IS_CRITICAL }, + /* This clk needs to be on to keep bus interconnect alive */ + { .name = "clk-rx-icn-hades", .flags = CLK_IS_CRITICAL }, + /* This clk needs to be on to keep bus interconnect alive */ + { .name = "clk-icn-reg-16", .flags = CLK_IS_CRITICAL }, + { .name = "clk-pp-hevc", }, + { .name = "clk-clust-hevc", }, + { .name = "clk-hwpe-hevc", }, + { .name = "clk-fc-hevc", }, + { .name = "clk-proc-mixer", }, + { .name = "clk-proc-sc", }, + { .name = "clk-avsp-hevc", }, +}; + +static const struct clkgen_data clkgen_stih418_c0 = { + .outputs = clkgen_stih418_c0_clk_out, + .outputs_nb = ARRAY_SIZE(clkgen_stih418_c0_clk_out), +}; + +static const struct clkgen_clk_out clkgen_stih407_d0_clk_out[] = { + { .name = "clk-pcm-0", }, + { .name = "clk-pcm-1", }, + { .name = "clk-pcm-2", }, + { .name = "clk-spdiff", }, +}; + +static const struct clkgen_data clkgen_stih407_d0 = { + .flags = CLK_SET_RATE_PARENT, + .outputs = clkgen_stih407_d0_clk_out, + .outputs_nb = ARRAY_SIZE(clkgen_stih407_d0_clk_out), +}; + +static const struct clkgen_clk_out clkgen_stih410_d0_clk_out[] = { + { .name = "clk-pcm-0", }, + { .name = "clk-pcm-1", }, + { .name = "clk-pcm-2", }, + { .name = "clk-spdiff", }, + { .name = "clk-pcmr10-master", }, + { .name = "clk-usb2-phy", }, +}; + +static const struct clkgen_data clkgen_stih410_d0 = { + .flags = CLK_SET_RATE_PARENT, + .outputs = clkgen_stih410_d0_clk_out, + .outputs_nb = ARRAY_SIZE(clkgen_stih410_d0_clk_out), +}; + +static const struct clkgen_clk_out clkgen_stih407_d2_clk_out[] = { + { .name = "clk-pix-main-disp", }, + { .name = "clk-pix-pip", }, + { .name = "clk-pix-gdp1", }, + { .name = "clk-pix-gdp2", }, + { .name = "clk-pix-gdp3", }, + { .name = "clk-pix-gdp4", }, + { .name = "clk-pix-aux-disp", }, + { .name = "clk-denc", }, + { .name = "clk-pix-hddac", }, + { .name = "clk-hddac", }, + { .name = "clk-sddac", }, + { .name = "clk-pix-dvo", }, + { .name = "clk-dvo", }, + { .name = "clk-pix-hdmi", }, + { .name = "clk-tmds-hdmi", }, + { .name = "clk-ref-hdmiphy", }, +}; + +static const struct clkgen_data clkgen_stih407_d2 = { + .outputs = clkgen_stih407_d2_clk_out, + .outputs_nb = ARRAY_SIZE(clkgen_stih407_d2_clk_out), + .flags = CLK_SET_RATE_PARENT, + .mode = 1, +}; + +static const struct clkgen_clk_out clkgen_stih418_d2_clk_out[] = { + { .name = "clk-pix-main-disp", }, + { .name = "", }, + { .name = "", }, + { .name = "", }, + { .name = "", }, + { .name = "clk-tmds-hdmi-div2", }, + { .name = "clk-pix-aux-disp", }, + { .name = "clk-denc", }, + { .name = "clk-pix-hddac", }, + { .name = "clk-hddac", }, + { .name = "clk-sddac", }, + { .name = "clk-pix-dvo", }, + { .name = "clk-dvo", }, + { .name = "clk-pix-hdmi", }, + { .name = "clk-tmds-hdmi", }, + { .name = "clk-ref-hdmiphy", }, + { .name = "", }, { .name = "", }, { .name = "", }, { .name = "", }, + { .name = "", }, { .name = "", }, { .name = "", }, { .name = "", }, + { .name = "", }, { .name = "", }, { .name = "", }, { .name = "", }, + { .name = "", }, { .name = "", }, { .name = "", }, { .name = "", }, + { .name = "", }, { .name = "", }, { .name = "", }, { .name = "", }, + { .name = "", }, { .name = "", }, { .name = "", }, { .name = "", }, + { .name = "", }, { .name = "", }, { .name = "", }, { .name = "", }, + { .name = "", }, { .name = "", }, { .name = "", }, + { .name = "clk-vp9", }, +}; + +static const struct clkgen_data clkgen_stih418_d2 = { + .outputs = clkgen_stih418_d2_clk_out, + .outputs_nb = ARRAY_SIZE(clkgen_stih418_d2_clk_out), + .flags = CLK_SET_RATE_PARENT, + .mode = 1, +}; + +static const struct clkgen_clk_out clkgen_stih407_d3_clk_out[] = { + { .name = "clk-stfe-frc1", }, + { .name = "clk-tsout-0", }, + { .name = "clk-tsout-1", }, + { .name = "clk-mchi", }, + { .name = "clk-vsens-compo", }, + { .name = "clk-frc1-remote", }, + { .name = "clk-lpc-0", }, + { .name = "clk-lpc-1", }, +}; + +static const struct clkgen_data clkgen_stih407_d3 = { + .outputs = clkgen_stih407_d3_clk_out, + .outputs_nb = ARRAY_SIZE(clkgen_stih407_d3_clk_out), +}; + static const struct of_device_id flexgen_of_match[] = { { .compatible = "st,flexgen-audio", @@ -304,6 +595,46 @@ static const struct of_device_id flexgen_of_match[] = { .compatible = "st,flexgen-video", .data = &clkgen_video, }, + { + .compatible = "st,flexgen-stih407-a0", + .data = &clkgen_stih407_a0, + }, + { + .compatible = "st,flexgen-stih410-a0", + .data = &clkgen_stih410_a0, + }, + { + .compatible = "st,flexgen-stih407-c0", + .data = &clkgen_stih407_c0, + }, + { + .compatible = "st,flexgen-stih410-c0", + .data = &clkgen_stih410_c0, + }, + { + .compatible = "st,flexgen-stih418-c0", + .data = &clkgen_stih418_c0, + }, + { + .compatible = "st,flexgen-stih407-d0", + .data = &clkgen_stih407_d0, + }, + { + .compatible = "st,flexgen-stih410-d0", + .data = &clkgen_stih410_d0, + }, + { + .compatible = "st,flexgen-stih407-d2", + .data = &clkgen_stih407_d2, + }, + { + .compatible = "st,flexgen-stih418-d2", + .data = &clkgen_stih418_d2, + }, + { + .compatible = "st,flexgen-stih407-d3", + .data = &clkgen_stih407_d3, + }, {} }; @@ -320,6 +651,7 @@ static void __init st_of_flexgen_setup(struct device_node *np) unsigned long flex_flags = 0; int ret; bool clk_mode = 0; + const char *clk_name; pnode = of_get_parent(np); if (!pnode) @@ -347,13 +679,17 @@ static void __init st_of_flexgen_setup(struct device_node *np) if (!clk_data) goto err; - ret = of_property_count_strings(np, "clock-output-names"); - if (ret <= 0) { - pr_err("%s: Failed to get number of output clocks (%d)", - __func__, clk_data->clk_num); - goto err; - } - clk_data->clk_num = ret; + /* First try to get output information from the compatible data */ + if (!data || !data->outputs_nb || !data->outputs) { + ret = of_property_count_strings(np, "clock-output-names"); + if (ret <= 0) { + pr_err("%s: Failed to get number of output clocks (%d)", + __func__, clk_data->clk_num); + goto err; + } + clk_data->clk_num = ret; + } else + clk_data->clk_num = data->outputs_nb; clk_data->clks = kcalloc(clk_data->clk_num, sizeof(struct clk *), GFP_KERNEL); @@ -368,16 +704,19 @@ static void __init st_of_flexgen_setup(struct device_node *np) for (i = 0; i < clk_data->clk_num; i++) { struct clk *clk; - const char *clk_name; - if (of_property_read_string_index(np, "clock-output-names", - i, &clk_name)) { - break; + if (!data || !data->outputs_nb || !data->outputs) { + if (of_property_read_string_index(np, + "clock-output-names", + i, &clk_name)) + break; + flex_flags &= ~CLK_IS_CRITICAL; + of_clk_detect_critical(np, i, &flex_flags); + } else { + clk_name = data->outputs[i].name; + flex_flags = data->flags | data->outputs[i].flags; } - flex_flags &= ~CLK_IS_CRITICAL; - of_clk_detect_critical(np, i, &flex_flags); - /* * If we read an empty clock name then the output is unused */ diff --git a/drivers/clk/st/clkgen-fsyn.c b/drivers/clk/st/clkgen-fsyn.c index dd6062e043e0..164285d6be97 100644 --- a/drivers/clk/st/clkgen-fsyn.c +++ b/drivers/clk/st/clkgen-fsyn.c @@ -66,6 +66,16 @@ struct clkgen_quadfs_data { unsigned long *); }; +struct clkgen_clk_out { + const char *name; + unsigned long flags; +}; + +struct clkgen_quadfs_data_clks { + struct clkgen_quadfs_data *data; + const struct clkgen_clk_out *outputs; +}; + static const struct clk_ops st_quadfs_pll_c32_ops; static int clk_fs660c32_dig_get_params(unsigned long input, @@ -115,6 +125,18 @@ static const struct clkgen_quadfs_data st_fs660c32_C = { .get_rate = clk_fs660c32_dig_get_rate, }; +static const struct clkgen_clk_out st_fs660c32_C_clks[] = { + { .name = "clk-s-c0-fs0-ch0", }, + { .name = "clk-s-c0-fs0-ch1", }, + { .name = "clk-s-c0-fs0-ch2", }, + { .name = "clk-s-c0-fs0-ch3", }, +}; + +static const struct clkgen_quadfs_data_clks st_fs660c32_C_data = { + .data = (struct clkgen_quadfs_data *)&st_fs660c32_C, + .outputs = st_fs660c32_C_clks, +}; + static const struct clkgen_quadfs_data st_fs660c32_D = { .nrst_present = true, .nrst = { CLKGEN_FIELD(0x2a0, 0x1, 0), @@ -156,6 +178,46 @@ static const struct clkgen_quadfs_data st_fs660c32_D = { .get_params = clk_fs660c32_dig_get_params, .get_rate = clk_fs660c32_dig_get_rate,}; +static const struct clkgen_quadfs_data_clks st_fs660c32_D_data = { + .data = (struct clkgen_quadfs_data *)&st_fs660c32_D, +}; + +static const struct clkgen_clk_out st_fs660c32_D0_clks[] = { + { .name = "clk-s-d0-fs0-ch0", }, + { .name = "clk-s-d0-fs0-ch1", }, + { .name = "clk-s-d0-fs0-ch2", }, + { .name = "clk-s-d0-fs0-ch3", }, +}; + +static const struct clkgen_quadfs_data_clks st_fs660c32_D0_data = { + .data = (struct clkgen_quadfs_data *)&st_fs660c32_D, + .outputs = st_fs660c32_D0_clks, +}; + +static const struct clkgen_clk_out st_fs660c32_D2_clks[] = { + { .name = "clk-s-d2-fs0-ch0", }, + { .name = "clk-s-d2-fs0-ch1", }, + { .name = "clk-s-d2-fs0-ch2", }, + { .name = "clk-s-d2-fs0-ch3", }, +}; + +static const struct clkgen_quadfs_data_clks st_fs660c32_D2_data = { + .data = (struct clkgen_quadfs_data *)&st_fs660c32_D, + .outputs = st_fs660c32_D2_clks, +}; + +static const struct clkgen_clk_out st_fs660c32_D3_clks[] = { + { .name = "clk-s-d3-fs0-ch0", }, + { .name = "clk-s-d3-fs0-ch1", }, + { .name = "clk-s-d3-fs0-ch2", }, + { .name = "clk-s-d3-fs0-ch3", }, +}; + +static const struct clkgen_quadfs_data_clks st_fs660c32_D3_data = { + .data = (struct clkgen_quadfs_data *)&st_fs660c32_D, + .outputs = st_fs660c32_D3_clks, +}; + /** * DOC: A Frequency Synthesizer that multiples its input clock by a fixed factor * @@ -857,7 +919,7 @@ static struct clk * __init st_clk_register_quadfs_fsynth( static void __init st_of_create_quadfs_fsynths( struct device_node *np, const char *pll_name, - struct clkgen_quadfs_data *quadfs, void __iomem *reg, + struct clkgen_quadfs_data_clks *quadfs, void __iomem *reg, spinlock_t *lock) { struct clk_onecell_data *clk_data; @@ -881,9 +943,15 @@ static void __init st_of_create_quadfs_fsynths( const char *clk_name; unsigned long flags = 0; - if (of_property_read_string_index(np, "clock-output-names", - fschan, &clk_name)) { - break; + if (quadfs->outputs) { + clk_name = quadfs->outputs[fschan].name; + flags = quadfs->outputs[fschan].flags; + } else { + if (of_property_read_string_index(np, + "clock-output-names", + fschan, &clk_name)) + break; + of_clk_detect_critical(np, fschan, &flags); } /* @@ -892,10 +960,8 @@ static void __init st_of_create_quadfs_fsynths( if (*clk_name == '\0') continue; - of_clk_detect_critical(np, fschan, &flags); - clk = st_clk_register_quadfs_fsynth(clk_name, pll_name, - quadfs, reg, fschan, + quadfs->data, reg, fschan, flags, lock); /* @@ -915,7 +981,7 @@ static void __init st_of_create_quadfs_fsynths( } static void __init st_of_quadfs_setup(struct device_node *np, - struct clkgen_quadfs_data *data) + struct clkgen_quadfs_data_clks *datac) { struct clk *clk; const char *pll_name, *clk_parent_name; @@ -940,7 +1006,7 @@ static void __init st_of_quadfs_setup(struct device_node *np, spin_lock_init(lock); - clk = st_clk_register_quadfs_pll(pll_name, clk_parent_name, data, + clk = st_clk_register_quadfs_pll(pll_name, clk_parent_name, datac->data, reg, lock); if (IS_ERR(clk)) goto err_exit; @@ -950,7 +1016,7 @@ static void __init st_of_quadfs_setup(struct device_node *np, __clk_get_name(clk_get_parent(clk)), (unsigned int)clk_get_rate(clk)); - st_of_create_quadfs_fsynths(np, pll_name, data, reg, lock); + st_of_create_quadfs_fsynths(np, pll_name, datac, reg, lock); err_exit: kfree(pll_name); /* No longer need local copy of the PLL name */ @@ -958,12 +1024,35 @@ err_exit: static void __init st_of_quadfs660C_setup(struct device_node *np) { - st_of_quadfs_setup(np, (struct clkgen_quadfs_data *) &st_fs660c32_C); + st_of_quadfs_setup(np, + (struct clkgen_quadfs_data_clks *) &st_fs660c32_C_data); } CLK_OF_DECLARE(quadfs660C, "st,quadfs-pll", st_of_quadfs660C_setup); static void __init st_of_quadfs660D_setup(struct device_node *np) { - st_of_quadfs_setup(np, (struct clkgen_quadfs_data *) &st_fs660c32_D); + st_of_quadfs_setup(np, + (struct clkgen_quadfs_data_clks *) &st_fs660c32_D_data); } CLK_OF_DECLARE(quadfs660D, "st,quadfs", st_of_quadfs660D_setup); + +static void __init st_of_quadfs660D0_setup(struct device_node *np) +{ + st_of_quadfs_setup(np, + (struct clkgen_quadfs_data_clks *) &st_fs660c32_D0_data); +} +CLK_OF_DECLARE(quadfs660D0, "st,quadfs-d0", st_of_quadfs660D0_setup); + +static void __init st_of_quadfs660D2_setup(struct device_node *np) +{ + st_of_quadfs_setup(np, + (struct clkgen_quadfs_data_clks *) &st_fs660c32_D2_data); +} +CLK_OF_DECLARE(quadfs660D2, "st,quadfs-d2", st_of_quadfs660D2_setup); + +static void __init st_of_quadfs660D3_setup(struct device_node *np) +{ + st_of_quadfs_setup(np, + (struct clkgen_quadfs_data_clks *) &st_fs660c32_D3_data); +} +CLK_OF_DECLARE(quadfs660D3, "st,quadfs-d3", st_of_quadfs660D3_setup); diff --git a/drivers/clk/st/clkgen-pll.c b/drivers/clk/st/clkgen-pll.c index 119c5b33080c..b36e4d803636 100644 --- a/drivers/clk/st/clkgen-pll.c +++ b/drivers/clk/st/clkgen-pll.c @@ -57,6 +57,17 @@ struct clkgen_pll_data { const struct clk_ops *ops; }; +struct clkgen_clk_out { + const char *name; + unsigned long flags; +}; + +struct clkgen_pll_data_clks { + struct clkgen_pll_data *data; + const struct clkgen_clk_out *outputs; +}; + + static const struct clk_ops stm_pll3200c32_ops; static const struct clk_ops stm_pll3200c32_a9_ops; static const struct clk_ops stm_pll4600c28_ops; @@ -74,6 +85,28 @@ static const struct clkgen_pll_data st_pll3200c32_cx_0 = { .ops = &stm_pll3200c32_ops, }; +static const struct clkgen_pll_data_clks st_pll3200c32_cx_0_legacy_data = { + .data = (struct clkgen_pll_data *)&st_pll3200c32_cx_0, +}; + +static const struct clkgen_clk_out st_pll3200c32_ax_0_clks[] = { + { .name = "clk-s-a0-pll-odf-0", }, +}; + +static const struct clkgen_pll_data_clks st_pll3200c32_a0_data = { + .data = (struct clkgen_pll_data *)&st_pll3200c32_cx_0, + .outputs = st_pll3200c32_ax_0_clks, +}; + +static const struct clkgen_clk_out st_pll3200c32_cx_0_clks[] = { + { .name = "clk-s-c0-pll0-odf-0", }, +}; + +static const struct clkgen_pll_data_clks st_pll3200c32_c0_data = { + .data = (struct clkgen_pll_data *)&st_pll3200c32_cx_0, + .outputs = st_pll3200c32_cx_0_clks, +}; + static const struct clkgen_pll_data st_pll3200c32_cx_1 = { /* 407 C0 PLL1 */ .pdn_status = CLKGEN_FIELD(0x2c8, 0x1, 8), @@ -87,6 +120,19 @@ static const struct clkgen_pll_data st_pll3200c32_cx_1 = { .ops = &stm_pll3200c32_ops, }; +static const struct clkgen_pll_data_clks st_pll3200c32_cx_1_legacy_data = { + .data = (struct clkgen_pll_data *)&st_pll3200c32_cx_1, +}; + +static const struct clkgen_clk_out st_pll3200c32_cx_1_clks[] = { + { .name = "clk-s-c0-pll1-odf-0", }, +}; + +static const struct clkgen_pll_data_clks st_pll3200c32_c1_data = { + .data = (struct clkgen_pll_data *)&st_pll3200c32_cx_1, + .outputs = st_pll3200c32_cx_1_clks, +}; + static const struct clkgen_pll_data st_pll3200c32_407_a9 = { /* 407 A9 */ .pdn_status = CLKGEN_FIELD(0x1a8, 0x1, 0), @@ -104,6 +150,15 @@ static const struct clkgen_pll_data st_pll3200c32_407_a9 = { .ops = &stm_pll3200c32_a9_ops, }; +static const struct clkgen_clk_out st_pll3200c32_407_a9_clks[] = { + { .name = "clockgen-a9-pll-odf", }, +}; + +static const struct clkgen_pll_data_clks st_pll3200c32_407_a9_data = { + .data = (struct clkgen_pll_data *)&st_pll3200c32_407_a9, + .outputs = st_pll3200c32_407_a9_clks, +}; + static struct clkgen_pll_data st_pll4600c28_418_a9 = { /* 418 A9 */ .pdn_status = CLKGEN_FIELD(0x1a8, 0x1, 0), @@ -120,6 +175,15 @@ static struct clkgen_pll_data st_pll4600c28_418_a9 = { .ops = &stm_pll4600c28_ops, }; +static const struct clkgen_clk_out st_pll4600c28_418_a9_clks[] = { + { .name = "clockgen-a9-pll-odf", }, +}; + +static const struct clkgen_pll_data_clks st_pll4600c28_418_a9_data = { + .data = (struct clkgen_pll_data *)&st_pll4600c28_418_a9, + .outputs = st_pll4600c28_418_a9_clks, +}; + /** * DOC: Clock Generated by PLL, rate set and enabled by bootloader * @@ -146,7 +210,6 @@ struct clkgen_pll { u32 ndiv; u32 idf; - u32 odf; u32 cp; }; @@ -685,7 +748,7 @@ static struct clk * __init clkgen_odf_register(const char *parent_name, static void __init clkgen_c32_pll_setup(struct device_node *np, - struct clkgen_pll_data *data) + struct clkgen_pll_data_clks *datac) { struct clk *clk; const char *parent_name, *pll_name; @@ -705,14 +768,14 @@ static void __init clkgen_c32_pll_setup(struct device_node *np, of_clk_detect_critical(np, 0, &pll_flags); - clk = clkgen_pll_register(parent_name, data, pll_base, pll_flags, - np->name, data->lock); + clk = clkgen_pll_register(parent_name, datac->data, pll_base, pll_flags, + np->name, datac->data->lock); if (IS_ERR(clk)) return; pll_name = __clk_get_name(clk); - num_odfs = data->num_odfs; + num_odfs = datac->data->num_odfs; clk_data = kzalloc(sizeof(*clk_data), GFP_KERNEL); if (!clk_data) @@ -730,14 +793,21 @@ static void __init clkgen_c32_pll_setup(struct device_node *np, const char *clk_name; unsigned long odf_flags = 0; - if (of_property_read_string_index(np, "clock-output-names", - odf, &clk_name)) - return; + if (datac->outputs) { + clk_name = datac->outputs[odf].name; + odf_flags = datac->outputs[odf].flags; + } else { + if (of_property_read_string_index(np, + "clock-output-names", + odf, &clk_name)) + return; - of_clk_detect_critical(np, odf, &odf_flags); + of_clk_detect_critical(np, odf, &odf_flags); + } - clk = clkgen_odf_register(pll_name, pll_base, data, odf_flags, - odf, &clkgena_c32_odf_lock, clk_name); + clk = clkgen_odf_register(pll_name, pll_base, datac->data, + odf_flags, odf, &clkgena_c32_odf_lock, + clk_name); if (IS_ERR(clk)) goto err; @@ -755,27 +825,48 @@ err: static void __init clkgen_c32_pll0_setup(struct device_node *np) { clkgen_c32_pll_setup(np, - (struct clkgen_pll_data *) &st_pll3200c32_cx_0); + (struct clkgen_pll_data_clks *) &st_pll3200c32_cx_0_legacy_data); } CLK_OF_DECLARE(c32_pll0, "st,clkgen-pll0", clkgen_c32_pll0_setup); +static void __init clkgen_c32_pll0_a0_setup(struct device_node *np) +{ + clkgen_c32_pll_setup(np, + (struct clkgen_pll_data_clks *) &st_pll3200c32_a0_data); +} +CLK_OF_DECLARE(c32_pll0_a0, "st,clkgen-pll0-a0", clkgen_c32_pll0_a0_setup); + +static void __init clkgen_c32_pll0_c0_setup(struct device_node *np) +{ + clkgen_c32_pll_setup(np, + (struct clkgen_pll_data_clks *) &st_pll3200c32_c0_data); +} +CLK_OF_DECLARE(c32_pll0_c0, "st,clkgen-pll0-c0", clkgen_c32_pll0_c0_setup); + static void __init clkgen_c32_pll1_setup(struct device_node *np) { clkgen_c32_pll_setup(np, - (struct clkgen_pll_data *) &st_pll3200c32_cx_1); + (struct clkgen_pll_data_clks *) &st_pll3200c32_cx_1_legacy_data); } CLK_OF_DECLARE(c32_pll1, "st,clkgen-pll1", clkgen_c32_pll1_setup); +static void __init clkgen_c32_pll1_c0_setup(struct device_node *np) +{ + clkgen_c32_pll_setup(np, + (struct clkgen_pll_data_clks *) &st_pll3200c32_c1_data); +} +CLK_OF_DECLARE(c32_pll1_c0, "st,clkgen-pll1-c0", clkgen_c32_pll1_c0_setup); + static void __init clkgen_c32_plla9_setup(struct device_node *np) { clkgen_c32_pll_setup(np, - (struct clkgen_pll_data *) &st_pll3200c32_407_a9); + (struct clkgen_pll_data_clks *) &st_pll3200c32_407_a9_data); } CLK_OF_DECLARE(c32_plla9, "st,stih407-clkgen-plla9", clkgen_c32_plla9_setup); static void __init clkgen_c28_plla9_setup(struct device_node *np) { clkgen_c32_pll_setup(np, - (struct clkgen_pll_data *) &st_pll4600c28_418_a9); + (struct clkgen_pll_data_clks *) &st_pll4600c28_418_a9_data); } CLK_OF_DECLARE(c28_plla9, "st,stih418-clkgen-plla9", clkgen_c28_plla9_setup); diff --git a/drivers/clk/sunxi-ng/ccu-sun8i-v3s.c b/drivers/clk/sunxi-ng/ccu-sun8i-v3s.c index a774942cb153..f49724a22540 100644 --- a/drivers/clk/sunxi-ng/ccu-sun8i-v3s.c +++ b/drivers/clk/sunxi-ng/ccu-sun8i-v3s.c @@ -817,10 +817,10 @@ static void __init sun8i_v3_v3s_ccu_init(struct device_node *node, return; } - /* Force the PLL-Audio-1x divider to 4 */ + /* Force the PLL-Audio-1x divider to 1 */ val = readl(reg + SUN8I_V3S_PLL_AUDIO_REG); val &= ~GENMASK(19, 16); - writel(val | (3 << 16), reg + SUN8I_V3S_PLL_AUDIO_REG); + writel(val, reg + SUN8I_V3S_PLL_AUDIO_REG); sunxi_ccu_probe(node, reg, ccu_desc); } diff --git a/drivers/clk/tegra/clk-periph-gate.c b/drivers/clk/tegra/clk-periph-gate.c index 4b31beefc9fc..2091fc9b0ca9 100644 --- a/drivers/clk/tegra/clk-periph-gate.c +++ b/drivers/clk/tegra/clk-periph-gate.c @@ -48,36 +48,45 @@ static int clk_periph_is_enabled(struct clk_hw *hw) return state; } -static int clk_periph_enable(struct clk_hw *hw) +static void clk_periph_enable_locked(struct clk_hw *hw) { struct tegra_clk_periph_gate *gate = to_clk_periph_gate(hw); - unsigned long flags = 0; - - spin_lock_irqsave(&periph_ref_lock, flags); - - gate->enable_refcnt[gate->clk_num]++; - if (gate->enable_refcnt[gate->clk_num] > 1) { - spin_unlock_irqrestore(&periph_ref_lock, flags); - return 0; - } write_enb_set(periph_clk_to_bit(gate), gate); udelay(2); - if (!(gate->flags & TEGRA_PERIPH_NO_RESET) && - !(gate->flags & TEGRA_PERIPH_MANUAL_RESET)) { - if (read_rst(gate) & periph_clk_to_bit(gate)) { - udelay(5); /* reset propogation delay */ - write_rst_clr(periph_clk_to_bit(gate), gate); - } - } - if (gate->flags & TEGRA_PERIPH_WAR_1005168) { writel_relaxed(0, gate->clk_base + LVL2_CLK_GATE_OVRE); writel_relaxed(BIT(22), gate->clk_base + LVL2_CLK_GATE_OVRE); udelay(1); writel_relaxed(0, gate->clk_base + LVL2_CLK_GATE_OVRE); } +} + +static void clk_periph_disable_locked(struct clk_hw *hw) +{ + struct tegra_clk_periph_gate *gate = to_clk_periph_gate(hw); + + /* + * If peripheral is in the APB bus then read the APB bus to + * flush the write operation in apb bus. This will avoid the + * peripheral access after disabling clock + */ + if (gate->flags & TEGRA_PERIPH_ON_APB) + tegra_read_chipid(); + + write_enb_clr(periph_clk_to_bit(gate), gate); +} + +static int clk_periph_enable(struct clk_hw *hw) +{ + struct tegra_clk_periph_gate *gate = to_clk_periph_gate(hw); + unsigned long flags = 0; + + spin_lock_irqsave(&periph_ref_lock, flags); + + if (!gate->enable_refcnt[gate->clk_num]++) + clk_periph_enable_locked(hw); spin_unlock_irqrestore(&periph_ref_lock, flags); @@ -91,21 +100,28 @@ static void clk_periph_disable(struct clk_hw *hw) spin_lock_irqsave(&periph_ref_lock, flags); - gate->enable_refcnt[gate->clk_num]--; - if (gate->enable_refcnt[gate->clk_num] > 0) { - spin_unlock_irqrestore(&periph_ref_lock, flags); - return; - } + WARN_ON(!gate->enable_refcnt[gate->clk_num]); + + if (--gate->enable_refcnt[gate->clk_num] == 0) + clk_periph_disable_locked(hw); + + spin_unlock_irqrestore(&periph_ref_lock, flags); +} + +static void clk_periph_disable_unused(struct clk_hw *hw) +{ + struct tegra_clk_periph_gate *gate = to_clk_periph_gate(hw); + unsigned long flags = 0; + + spin_lock_irqsave(&periph_ref_lock, flags); /* - * If peripheral is in the APB bus then read the APB bus to - * flush the write operation in apb bus. This will avoid the - * peripheral access after disabling clock + * Some clocks are duplicated and some of them are marked as critical, + * like fuse and fuse_burn for example, thus the enable_refcnt will + * be non-zero here if the "unused" duplicate is disabled by CCF. */ - if (gate->flags & TEGRA_PERIPH_ON_APB) - tegra_read_chipid(); - - write_enb_clr(periph_clk_to_bit(gate), gate); + if (!gate->enable_refcnt[gate->clk_num]) + clk_periph_disable_locked(hw); spin_unlock_irqrestore(&periph_ref_lock, flags); } @@ -114,6 +130,7 @@ const struct clk_ops tegra_clk_periph_gate_ops = { .is_enabled = clk_periph_is_enabled, .enable = clk_periph_enable, .disable = clk_periph_disable, + .disable_unused = clk_periph_disable_unused, }; struct clk *tegra_clk_register_periph_gate(const char *name, @@ -148,9 +165,6 @@ struct clk *tegra_clk_register_periph_gate(const char *name, gate->enable_refcnt = enable_refcnt; gate->regs = pregs; - if (read_enb(gate) & periph_clk_to_bit(gate)) - enable_refcnt[clk_num]++; - /* Data in .init is copied by clk_register(), so stack variable OK */ gate->hw.init = &init; diff --git a/drivers/clk/tegra/clk-periph.c b/drivers/clk/tegra/clk-periph.c index 67620c7ecd9e..79ca3aa072b7 100644 --- a/drivers/clk/tegra/clk-periph.c +++ b/drivers/clk/tegra/clk-periph.c @@ -100,6 +100,15 @@ static void clk_periph_disable(struct clk_hw *hw) gate_ops->disable(gate_hw); } +static void clk_periph_disable_unused(struct clk_hw *hw) +{ + struct tegra_clk_periph *periph = to_clk_periph(hw); + const struct clk_ops *gate_ops = periph->gate_ops; + struct clk_hw *gate_hw = &periph->gate.hw; + + gate_ops->disable_unused(gate_hw); +} + static void clk_periph_restore_context(struct clk_hw *hw) { struct tegra_clk_periph *periph = to_clk_periph(hw); @@ -126,6 +135,7 @@ const struct clk_ops tegra_clk_periph_ops = { .is_enabled = clk_periph_is_enabled, .enable = clk_periph_enable, .disable = clk_periph_disable, + .disable_unused = clk_periph_disable_unused, .restore_context = clk_periph_restore_context, }; @@ -135,6 +145,7 @@ static const struct clk_ops tegra_clk_periph_nodiv_ops = { .is_enabled = clk_periph_is_enabled, .enable = clk_periph_enable, .disable = clk_periph_disable, + .disable_unused = clk_periph_disable_unused, .restore_context = clk_periph_restore_context, }; diff --git a/drivers/clk/tegra/clk-pll.c b/drivers/clk/tegra/clk-pll.c index 0193cebe8c5a..eaa079c177c3 100644 --- a/drivers/clk/tegra/clk-pll.c +++ b/drivers/clk/tegra/clk-pll.c @@ -558,6 +558,9 @@ static int _calc_rate(struct clk_hw *hw, struct tegra_clk_pll_freq_table *cfg, u32 p_div = 0; int ret; + if (!rate) + return -EINVAL; + switch (parent_rate) { case 12000000: case 26000000: @@ -1131,7 +1134,8 @@ static int clk_pllu_enable(struct clk_hw *hw) if (pll->lock) spin_lock_irqsave(pll->lock, flags); - _clk_pll_enable(hw); + if (!clk_pll_is_enabled(hw)) + _clk_pll_enable(hw); ret = clk_pll_wait_for_lock(pll); if (ret < 0) @@ -1748,15 +1752,13 @@ static int clk_pllu_tegra114_enable(struct clk_hw *hw) return -EINVAL; } - if (clk_pll_is_enabled(hw)) - return 0; - input_rate = clk_hw_get_rate(__clk_get_hw(osc)); if (pll->lock) spin_lock_irqsave(pll->lock, flags); - _clk_pll_enable(hw); + if (!clk_pll_is_enabled(hw)) + _clk_pll_enable(hw); ret = clk_pll_wait_for_lock(pll); if (ret < 0) diff --git a/drivers/clk/tegra/clk-tegra-periph.c b/drivers/clk/tegra/clk-tegra-periph.c index 60cc34f90cb9..292d6269daf1 100644 --- a/drivers/clk/tegra/clk-tegra-periph.c +++ b/drivers/clk/tegra/clk-tegra-periph.c @@ -712,9 +712,9 @@ static struct tegra_periph_init_data periph_clks[] = { MUX8("ndflash", mux_pllp_pllc2_c_c3_pllm_clkm, CLK_SOURCE_NDFLASH, 13, TEGRA_PERIPH_ON_APB, tegra_clk_ndflash_8), MUX8("ndspeed", mux_pllp_pllc2_c_c3_pllm_clkm, CLK_SOURCE_NDSPEED, 80, TEGRA_PERIPH_ON_APB, tegra_clk_ndspeed_8), MUX8("hdmi", mux_pllp_pllm_plld_plla_pllc_plld2_clkm, CLK_SOURCE_HDMI, 51, 0, tegra_clk_hdmi), - MUX8("extern1", mux_plla_clk32_pllp_clkm_plle, CLK_SOURCE_EXTERN1, 120, 0, tegra_clk_extern1), - MUX8("extern2", mux_plla_clk32_pllp_clkm_plle, CLK_SOURCE_EXTERN2, 121, 0, tegra_clk_extern2), - MUX8("extern3", mux_plla_clk32_pllp_clkm_plle, CLK_SOURCE_EXTERN3, 122, 0, tegra_clk_extern3), + MUX8("extern1", mux_plla_clk32_pllp_clkm_plle, CLK_SOURCE_EXTERN1, 120, TEGRA_PERIPH_NO_RESET, tegra_clk_extern1), + MUX8("extern2", mux_plla_clk32_pllp_clkm_plle, CLK_SOURCE_EXTERN2, 121, TEGRA_PERIPH_NO_RESET, tegra_clk_extern2), + MUX8("extern3", mux_plla_clk32_pllp_clkm_plle, CLK_SOURCE_EXTERN3, 122, TEGRA_PERIPH_NO_RESET, tegra_clk_extern3), MUX8("soc_therm", mux_pllm_pllc_pllp_plla, CLK_SOURCE_SOC_THERM, 78, TEGRA_PERIPH_ON_APB, tegra_clk_soc_therm), MUX8("soc_therm", mux_clkm_pllc_pllp_plla, CLK_SOURCE_SOC_THERM, 78, TEGRA_PERIPH_ON_APB, tegra_clk_soc_therm_8), MUX8("vi_sensor", mux_pllm_pllc2_c_c3_pllp_plla, CLK_SOURCE_VI_SENSOR, 164, TEGRA_PERIPH_NO_RESET, tegra_clk_vi_sensor_8), diff --git a/drivers/clk/tegra/clk-tegra-super-cclk.c b/drivers/clk/tegra/clk-tegra-super-cclk.c index a03119c30456..68d7bcd5fc8a 100644 --- a/drivers/clk/tegra/clk-tegra-super-cclk.c +++ b/drivers/clk/tegra/clk-tegra-super-cclk.c @@ -25,6 +25,8 @@ #define SUPER_CDIV_ENB BIT(31) +#define TSENSOR_SLOWDOWN BIT(23) + static struct tegra_clk_super_mux *cclk_super; static bool cclk_on_pllx; @@ -47,10 +49,20 @@ static int cclk_super_set_rate(struct clk_hw *hw, unsigned long rate, static unsigned long cclk_super_recalc_rate(struct clk_hw *hw, unsigned long parent_rate) { + struct tegra_clk_super_mux *super = to_clk_super_mux(hw); + u32 val = readl_relaxed(super->reg); + unsigned int div2; + + /* check whether thermal throttling is active */ + if (val & TSENSOR_SLOWDOWN) + div2 = 1; + else + div2 = 0; + if (cclk_super_get_parent(hw) == PLLX_INDEX) - return parent_rate; + return parent_rate >> div2; - return tegra_clk_super_ops.recalc_rate(hw, parent_rate); + return tegra_clk_super_ops.recalc_rate(hw, parent_rate) >> div2; } static int cclk_super_determine_rate(struct clk_hw *hw, diff --git a/drivers/clk/tegra/clk-tegra124-dfll-fcpu.c b/drivers/clk/tegra/clk-tegra124-dfll-fcpu.c index 2ac2679d696d..5e339ad0a97c 100644 --- a/drivers/clk/tegra/clk-tegra124-dfll-fcpu.c +++ b/drivers/clk/tegra/clk-tegra124-dfll-fcpu.c @@ -537,7 +537,7 @@ static void get_alignment_from_dt(struct device *dev, static int get_alignment_from_regulator(struct device *dev, struct rail_alignment *align) { - struct regulator *reg = devm_regulator_get(dev, "vdd-cpu"); + struct regulator *reg = regulator_get(dev, "vdd-cpu"); if (IS_ERR(reg)) return PTR_ERR(reg); @@ -545,7 +545,7 @@ static int get_alignment_from_regulator(struct device *dev, align->offset_uv = regulator_list_voltage(reg, 0); align->step_uv = regulator_get_linear_step(reg); - devm_regulator_put(reg); + regulator_put(reg); return 0; } diff --git a/drivers/clk/tegra/clk-tegra124-emc.c b/drivers/clk/tegra/clk-tegra124-emc.c index bdf6f4a51617..74c1d894cca8 100644 --- a/drivers/clk/tegra/clk-tegra124-emc.c +++ b/drivers/clk/tegra/clk-tegra124-emc.c @@ -249,8 +249,10 @@ static int emc_set_timing(struct tegra_clk_emc *tegra, div = timing->parent_rate / (timing->rate / 2) - 2; err = tegra->prepare_timing_change(emc, timing->rate); - if (err) + if (err) { + clk_disable_unprepare(timing->parent); return err; + } spin_lock_irqsave(tegra->lock, flags); diff --git a/drivers/clk/tegra/clk-tegra20.c b/drivers/clk/tegra/clk-tegra20.c index 3efc651b42e3..3664593a5ba4 100644 --- a/drivers/clk/tegra/clk-tegra20.c +++ b/drivers/clk/tegra/clk-tegra20.c @@ -1021,9 +1021,9 @@ static struct tegra_clk_init_table init_table[] __initdata = { { TEGRA20_CLK_PLL_P_OUT3, TEGRA20_CLK_CLK_MAX, 72000000, 1 }, { TEGRA20_CLK_PLL_P_OUT4, TEGRA20_CLK_CLK_MAX, 24000000, 1 }, { TEGRA20_CLK_PLL_C, TEGRA20_CLK_CLK_MAX, 600000000, 0 }, - { TEGRA20_CLK_PLL_C_OUT1, TEGRA20_CLK_CLK_MAX, 240000000, 0 }, - { TEGRA20_CLK_SCLK, TEGRA20_CLK_PLL_C_OUT1, 240000000, 0 }, - { TEGRA20_CLK_HCLK, TEGRA20_CLK_CLK_MAX, 240000000, 0 }, + { TEGRA20_CLK_PLL_C_OUT1, TEGRA20_CLK_CLK_MAX, 120000000, 0 }, + { TEGRA20_CLK_SCLK, TEGRA20_CLK_PLL_C_OUT1, 120000000, 0 }, + { TEGRA20_CLK_HCLK, TEGRA20_CLK_CLK_MAX, 120000000, 0 }, { TEGRA20_CLK_PCLK, TEGRA20_CLK_CLK_MAX, 60000000, 0 }, { TEGRA20_CLK_CSITE, TEGRA20_CLK_CLK_MAX, 0, 1 }, { TEGRA20_CLK_CCLK, TEGRA20_CLK_CLK_MAX, 0, 1 }, diff --git a/drivers/clk/tegra/clk-tegra30.c b/drivers/clk/tegra/clk-tegra30.c index 16dbf83d2f62..64121bc66d85 100644 --- a/drivers/clk/tegra/clk-tegra30.c +++ b/drivers/clk/tegra/clk-tegra30.c @@ -930,7 +930,7 @@ static void __init tegra30_super_clk_init(void) /* CCLKG */ clk = tegra_clk_register_super_cclk("cclk_g", cclk_g_parents, ARRAY_SIZE(cclk_g_parents), - CLK_SET_RATE_PARENT, + CLK_SET_RATE_PARENT | CLK_GET_RATE_NOCACHE, clk_base + CCLKG_BURST_POLICY, 0, NULL); clks[TEGRA30_CLK_CCLK_G] = clk; @@ -1006,7 +1006,7 @@ static struct tegra_periph_init_data tegra_periph_clk_list[] = { TEGRA_INIT_DATA_MUX("dam0", mux_pllacp_clkm, CLK_SOURCE_DAM0, 108, 0, TEGRA30_CLK_DAM0), TEGRA_INIT_DATA_MUX("dam1", mux_pllacp_clkm, CLK_SOURCE_DAM1, 109, 0, TEGRA30_CLK_DAM1), TEGRA_INIT_DATA_MUX("dam2", mux_pllacp_clkm, CLK_SOURCE_DAM2, 110, 0, TEGRA30_CLK_DAM2), - TEGRA_INIT_DATA_INT("3d2", mux_pllmcpa, CLK_SOURCE_3D2, 98, TEGRA_PERIPH_MANUAL_RESET, TEGRA30_CLK_GR3D2), + TEGRA_INIT_DATA_INT("3d2", mux_pllmcpa, CLK_SOURCE_3D2, 98, 0, TEGRA30_CLK_GR3D2), TEGRA_INIT_DATA_INT("se", mux_pllpcm_clkm, CLK_SOURCE_SE, 127, 0, TEGRA30_CLK_SE), TEGRA_INIT_DATA_MUX8("hdmi", mux_pllpmdacd2_clkm, CLK_SOURCE_HDMI, 51, 0, TEGRA30_CLK_HDMI), TEGRA_INIT_DATA("pwm", NULL, NULL, pwm_parents, CLK_SOURCE_PWM, 28, 2, 0, 0, 8, 1, 0, 17, TEGRA_PERIPH_ON_APB, TEGRA30_CLK_PWM), @@ -1245,7 +1245,7 @@ static struct tegra_clk_init_table init_table[] __initdata = { { TEGRA30_CLK_GR3D, TEGRA30_CLK_PLL_C, 300000000, 0 }, { TEGRA30_CLK_GR3D2, TEGRA30_CLK_PLL_C, 300000000, 0 }, { TEGRA30_CLK_PLL_U, TEGRA30_CLK_CLK_MAX, 480000000, 0 }, - { TEGRA30_CLK_VDE, TEGRA30_CLK_PLL_C, 600000000, 0 }, + { TEGRA30_CLK_VDE, TEGRA30_CLK_PLL_C, 300000000, 0 }, { TEGRA30_CLK_SPDIF_IN_SYNC, TEGRA30_CLK_CLK_MAX, 24000000, 0 }, { TEGRA30_CLK_I2S0_SYNC, TEGRA30_CLK_CLK_MAX, 24000000, 0 }, { TEGRA30_CLK_I2S1_SYNC, TEGRA30_CLK_CLK_MAX, 24000000, 0 }, diff --git a/drivers/clk/tegra/clk.h b/drivers/clk/tegra/clk.h index c3e36b5dcc75..0c3ba0ccce1a 100644 --- a/drivers/clk/tegra/clk.h +++ b/drivers/clk/tegra/clk.h @@ -553,9 +553,6 @@ struct tegra_clk_periph_regs { * Flags: * TEGRA_PERIPH_NO_RESET - This flag indicates that reset is not allowed * for this module. - * TEGRA_PERIPH_MANUAL_RESET - This flag indicates not to reset module - * after clock enable and driver for the module is responsible for - * doing reset. * TEGRA_PERIPH_ON_APB - If peripheral is in the APB bus then read the * bus to flush the write operation in apb bus. This flag indicates * that this peripheral is in apb bus. @@ -577,7 +574,6 @@ struct tegra_clk_periph_gate { #define TEGRA_CLK_PERIPH_GATE_MAGIC 0x17760309 #define TEGRA_PERIPH_NO_RESET BIT(0) -#define TEGRA_PERIPH_MANUAL_RESET BIT(1) #define TEGRA_PERIPH_ON_APB BIT(2) #define TEGRA_PERIPH_WAR_1005168 BIT(3) #define TEGRA_PERIPH_NO_DIV BIT(4) diff --git a/drivers/clk/ti/adpll.c b/drivers/clk/ti/adpll.c index bb2f2836dab2..b341cd990be7 100644 --- a/drivers/clk/ti/adpll.c +++ b/drivers/clk/ti/adpll.c @@ -896,11 +896,8 @@ static int ti_adpll_probe(struct platform_device *pdev) d->pa = res->start; d->iobase = devm_ioremap_resource(dev, res); - if (IS_ERR(d->iobase)) { - dev_err(dev, "could not get IO base: %li\n", - PTR_ERR(d->iobase)); + if (IS_ERR(d->iobase)) return PTR_ERR(d->iobase); - } err = ti_adpll_init_registers(d); if (err) diff --git a/drivers/clk/ti/dpll.c b/drivers/clk/ti/dpll.c index d6f1ac5b53e1..e9f9aee936ae 100644 --- a/drivers/clk/ti/dpll.c +++ b/drivers/clk/ti/dpll.c @@ -290,7 +290,9 @@ static void __init of_ti_dpll_setup(struct device_node *node, struct clk_init_data *init = NULL; const char **parent_names = NULL; struct dpll_data *dd = NULL; + int ssc_clk_index; u8 dpll_mode = 0; + u32 min_div; dd = kmemdup(ddt, sizeof(*dd), GFP_KERNEL); clk_hw = kzalloc(sizeof(*clk_hw), GFP_KERNEL); @@ -345,6 +347,27 @@ static void __init of_ti_dpll_setup(struct device_node *node, if (dd->autoidle_mask) { if (ti_clk_get_reg_addr(node, 3, &dd->autoidle_reg)) goto cleanup; + + ssc_clk_index = 4; + } else { + ssc_clk_index = 3; + } + + if (dd->ssc_deltam_int_mask && dd->ssc_deltam_frac_mask && + dd->ssc_modfreq_mant_mask && dd->ssc_modfreq_exp_mask) { + if (ti_clk_get_reg_addr(node, ssc_clk_index++, + &dd->ssc_deltam_reg)) + goto cleanup; + + if (ti_clk_get_reg_addr(node, ssc_clk_index++, + &dd->ssc_modfreq_reg)) + goto cleanup; + + of_property_read_u32(node, "ti,ssc-modfreq-hz", + &dd->ssc_modfreq); + of_property_read_u32(node, "ti,ssc-deltam", &dd->ssc_deltam); + dd->ssc_downspread = + of_property_read_bool(node, "ti,ssc-downspread"); } if (of_property_read_bool(node, "ti,low-power-stop")) @@ -356,6 +379,10 @@ static void __init of_ti_dpll_setup(struct device_node *node, if (of_property_read_bool(node, "ti,lock")) dpll_mode |= 1 << DPLL_LOCKED; + if (!of_property_read_u32(node, "ti,min-div", &min_div) && + min_div > dd->min_divider) + dd->min_divider = min_div; + if (dpll_mode) dd->modes = dpll_mode; @@ -585,8 +612,14 @@ static void __init of_ti_am3_no_gate_dpll_setup(struct device_node *node) const struct dpll_data dd = { .idlest_mask = 0x1, .enable_mask = 0x7, + .ssc_enable_mask = 0x1 << 12, + .ssc_downspread_mask = 0x1 << 14, .mult_mask = 0x7ff << 8, .div1_mask = 0x7f, + .ssc_deltam_int_mask = 0x3 << 18, + .ssc_deltam_frac_mask = 0x3ffff, + .ssc_modfreq_mant_mask = 0x7f, + .ssc_modfreq_exp_mask = 0x7 << 8, .max_multiplier = 2047, .max_divider = 128, .min_divider = 1, @@ -645,8 +678,14 @@ static void __init of_ti_am3_dpll_setup(struct device_node *node) const struct dpll_data dd = { .idlest_mask = 0x1, .enable_mask = 0x7, + .ssc_enable_mask = 0x1 << 12, + .ssc_downspread_mask = 0x1 << 14, .mult_mask = 0x7ff << 8, .div1_mask = 0x7f, + .ssc_deltam_int_mask = 0x3 << 18, + .ssc_deltam_frac_mask = 0x3ffff, + .ssc_modfreq_mant_mask = 0x7f, + .ssc_modfreq_exp_mask = 0x7 << 8, .max_multiplier = 2047, .max_divider = 128, .min_divider = 1, diff --git a/drivers/clk/ti/dpll3xxx.c b/drivers/clk/ti/dpll3xxx.c index 6097b099a5df..e32b3515f9e7 100644 --- a/drivers/clk/ti/dpll3xxx.c +++ b/drivers/clk/ti/dpll3xxx.c @@ -292,7 +292,89 @@ static void _lookup_sddiv(struct clk_hw_omap *clk, u8 *sd_div, u16 m, u8 n) } /** - * _omap3_noncore_dpll_program - set non-core DPLL M,N values directly + * omap3_noncore_dpll_ssc_program - set spread-spectrum clocking registers + * @clk: struct clk * of DPLL to set + * + * Enable the DPLL spread spectrum clocking if frequency modulation and + * frequency spreading have been set, otherwise disable it. + */ +static void omap3_noncore_dpll_ssc_program(struct clk_hw_omap *clk) +{ + struct dpll_data *dd = clk->dpll_data; + unsigned long ref_rate; + u32 v, ctrl, mod_freq_divider, exponent, mantissa; + u32 deltam_step, deltam_ceil; + + ctrl = ti_clk_ll_ops->clk_readl(&dd->control_reg); + + if (dd->ssc_modfreq && dd->ssc_deltam) { + ctrl |= dd->ssc_enable_mask; + + if (dd->ssc_downspread) + ctrl |= dd->ssc_downspread_mask; + else + ctrl &= ~dd->ssc_downspread_mask; + + ref_rate = clk_hw_get_rate(dd->clk_ref); + mod_freq_divider = + (ref_rate / dd->last_rounded_n) / (4 * dd->ssc_modfreq); + if (dd->ssc_modfreq > (ref_rate / 70)) + pr_warn("clock: SSC modulation frequency of DPLL %s greater than %ld\n", + __clk_get_name(clk->hw.clk), ref_rate / 70); + + exponent = 0; + mantissa = mod_freq_divider; + while ((mantissa > 127) && (exponent < 7)) { + exponent++; + mantissa /= 2; + } + if (mantissa > 127) + mantissa = 127; + + v = ti_clk_ll_ops->clk_readl(&dd->ssc_modfreq_reg); + v &= ~(dd->ssc_modfreq_mant_mask | dd->ssc_modfreq_exp_mask); + v |= mantissa << __ffs(dd->ssc_modfreq_mant_mask); + v |= exponent << __ffs(dd->ssc_modfreq_exp_mask); + ti_clk_ll_ops->clk_writel(v, &dd->ssc_modfreq_reg); + + deltam_step = dd->last_rounded_m * dd->ssc_deltam; + deltam_step /= 10; + if (dd->ssc_downspread) + deltam_step /= 2; + + deltam_step <<= __ffs(dd->ssc_deltam_int_mask); + deltam_step /= 100; + deltam_step /= mod_freq_divider; + if (deltam_step > 0xFFFFF) + deltam_step = 0xFFFFF; + + deltam_ceil = (deltam_step & dd->ssc_deltam_int_mask) >> + __ffs(dd->ssc_deltam_int_mask); + if (deltam_step & dd->ssc_deltam_frac_mask) + deltam_ceil++; + + if ((dd->ssc_downspread && + ((dd->last_rounded_m - (2 * deltam_ceil)) < 20 || + dd->last_rounded_m > 2045)) || + ((dd->last_rounded_m - deltam_ceil) < 20 || + (dd->last_rounded_m + deltam_ceil) > 2045)) + pr_warn("clock: SSC multiplier of DPLL %s is out of range\n", + __clk_get_name(clk->hw.clk)); + + v = ti_clk_ll_ops->clk_readl(&dd->ssc_deltam_reg); + v &= ~(dd->ssc_deltam_int_mask | dd->ssc_deltam_frac_mask); + v |= deltam_step << __ffs(dd->ssc_deltam_int_mask | + dd->ssc_deltam_frac_mask); + ti_clk_ll_ops->clk_writel(v, &dd->ssc_deltam_reg); + } else { + ctrl &= ~dd->ssc_enable_mask; + } + + ti_clk_ll_ops->clk_writel(ctrl, &dd->control_reg); +} + +/** + * omap3_noncore_dpll_program - set non-core DPLL M,N values directly * @clk: struct clk * of DPLL to set * @freqsel: FREQSEL value to set * @@ -390,6 +472,9 @@ static int omap3_noncore_dpll_program(struct clk_hw_omap *clk, u16 freqsel) ti_clk_ll_ops->clk_writel(v, &dd->control_reg); } + if (dd->ssc_enable_mask) + omap3_noncore_dpll_ssc_program(clk); + /* We let the clock framework set the other output dividers later */ /* REVISIT: Set ramp-up delay? */ diff --git a/drivers/clk/versatile/Kconfig b/drivers/clk/versatile/Kconfig index 91f0ff54237d..481de5657d85 100644 --- a/drivers/clk/versatile/Kconfig +++ b/drivers/clk/versatile/Kconfig @@ -1,8 +1,7 @@ # SPDX-License-Identifier: GPL-2.0-only menu "Clock driver for ARM Reference designs" - depends on ARCH_INTEGRATOR || ARCH_REALVIEW || \ - ARCH_VERSATILE || ARCH_VEXPRESS || COMPILE_TEST + depends on HAS_IOMEM config ICST bool "Clock driver for ARM Reference designs ICST" diff --git a/drivers/clk/zynqmp/clk-gate-zynqmp.c b/drivers/clk/zynqmp/clk-gate-zynqmp.c index 10c9b889324f..695feaa82da5 100644 --- a/drivers/clk/zynqmp/clk-gate-zynqmp.c +++ b/drivers/clk/zynqmp/clk-gate-zynqmp.c @@ -121,7 +121,9 @@ struct clk_hw *zynqmp_clk_register_gate(const char *name, u32 clk_id, init.name = name; init.ops = &zynqmp_clk_gate_ops; - init.flags = nodes->flag; + + init.flags = zynqmp_clk_map_common_ccf_flags(nodes->flag); + init.parent_names = parents; init.num_parents = 1; diff --git a/drivers/clk/zynqmp/clk-mux-zynqmp.c b/drivers/clk/zynqmp/clk-mux-zynqmp.c index 06194149be83..157d4a960bf4 100644 --- a/drivers/clk/zynqmp/clk-mux-zynqmp.c +++ b/drivers/clk/zynqmp/clk-mux-zynqmp.c @@ -38,7 +38,7 @@ struct zynqmp_clk_mux { * zynqmp_clk_mux_get_parent() - Get parent of clock * @hw: handle between common and hardware-specific interfaces * - * Return: Parent index + * Return: Parent index on success or number of parents in case of error */ static u8 zynqmp_clk_mux_get_parent(struct clk_hw *hw) { @@ -50,9 +50,15 @@ static u8 zynqmp_clk_mux_get_parent(struct clk_hw *hw) ret = zynqmp_pm_clock_getparent(clk_id, &val); - if (ret) + if (ret) { pr_warn_once("%s() getparent failed for clock: %s, ret = %d\n", __func__, clk_name, ret); + /* + * clk_core_get_parent_by_index() takes num_parents as incorrect + * index which is exactly what I want to return here + */ + return clk_hw_get_num_parents(hw); + } return val; } @@ -90,6 +96,27 @@ static const struct clk_ops zynqmp_clk_mux_ro_ops = { .get_parent = zynqmp_clk_mux_get_parent, }; +static inline unsigned long zynqmp_clk_map_mux_ccf_flags( + const u32 zynqmp_type_flag) +{ + unsigned long ccf_flag = 0; + + if (zynqmp_type_flag & ZYNQMP_CLK_MUX_INDEX_ONE) + ccf_flag |= CLK_MUX_INDEX_ONE; + if (zynqmp_type_flag & ZYNQMP_CLK_MUX_INDEX_BIT) + ccf_flag |= CLK_MUX_INDEX_BIT; + if (zynqmp_type_flag & ZYNQMP_CLK_MUX_HIWORD_MASK) + ccf_flag |= CLK_MUX_HIWORD_MASK; + if (zynqmp_type_flag & ZYNQMP_CLK_MUX_READ_ONLY) + ccf_flag |= CLK_MUX_READ_ONLY; + if (zynqmp_type_flag & ZYNQMP_CLK_MUX_ROUND_CLOSEST) + ccf_flag |= CLK_MUX_ROUND_CLOSEST; + if (zynqmp_type_flag & ZYNQMP_CLK_MUX_BIG_ENDIAN) + ccf_flag |= CLK_MUX_BIG_ENDIAN; + + return ccf_flag; +} + /** * zynqmp_clk_register_mux() - Register a mux table with the clock * framework @@ -120,10 +147,12 @@ struct clk_hw *zynqmp_clk_register_mux(const char *name, u32 clk_id, init.ops = &zynqmp_clk_mux_ro_ops; else init.ops = &zynqmp_clk_mux_ops; - init.flags = nodes->flag; + + init.flags = zynqmp_clk_map_common_ccf_flags(nodes->flag); + init.parent_names = parents; init.num_parents = num_parents; - mux->flags = nodes->type_flag; + mux->flags = zynqmp_clk_map_mux_ccf_flags(nodes->type_flag); mux->hw.init = &init; mux->clk_id = clk_id; diff --git a/drivers/clk/zynqmp/clk-zynqmp.h b/drivers/clk/zynqmp/clk-zynqmp.h index 5beeb41b29fa..84fa80a969a9 100644 --- a/drivers/clk/zynqmp/clk-zynqmp.h +++ b/drivers/clk/zynqmp/clk-zynqmp.h @@ -10,6 +10,37 @@ #include <linux/firmware/xlnx-zynqmp.h> +/* Common Flags */ +/* must be gated across rate change */ +#define ZYNQMP_CLK_SET_RATE_GATE BIT(0) +/* must be gated across re-parent */ +#define ZYNQMP_CLK_SET_PARENT_GATE BIT(1) +/* propagate rate change up one level */ +#define ZYNQMP_CLK_SET_RATE_PARENT BIT(2) +/* do not gate even if unused */ +#define ZYNQMP_CLK_IGNORE_UNUSED BIT(3) +/* don't re-parent on rate change */ +#define ZYNQMP_CLK_SET_RATE_NO_REPARENT BIT(7) +/* do not gate, ever */ +#define ZYNQMP_CLK_IS_CRITICAL BIT(11) + +/* Type Flags for divider clock */ +#define ZYNQMP_CLK_DIVIDER_ONE_BASED BIT(0) +#define ZYNQMP_CLK_DIVIDER_POWER_OF_TWO BIT(1) +#define ZYNQMP_CLK_DIVIDER_ALLOW_ZERO BIT(2) +#define ZYNQMP_CLK_DIVIDER_HIWORD_MASK BIT(3) +#define ZYNQMP_CLK_DIVIDER_ROUND_CLOSEST BIT(4) +#define ZYNQMP_CLK_DIVIDER_READ_ONLY BIT(5) +#define ZYNQMP_CLK_DIVIDER_MAX_AT_ZERO BIT(6) + +/* Type Flags for mux clock */ +#define ZYNQMP_CLK_MUX_INDEX_ONE BIT(0) +#define ZYNQMP_CLK_MUX_INDEX_BIT BIT(1) +#define ZYNQMP_CLK_MUX_HIWORD_MASK BIT(2) +#define ZYNQMP_CLK_MUX_READ_ONLY BIT(3) +#define ZYNQMP_CLK_MUX_ROUND_CLOSEST BIT(4) +#define ZYNQMP_CLK_MUX_BIG_ENDIAN BIT(5) + enum topology_type { TYPE_INVALID, TYPE_MUX, @@ -33,6 +64,8 @@ struct clock_topology { u8 custom_type_flag; }; +unsigned long zynqmp_clk_map_common_ccf_flags(const u32 zynqmp_flag); + struct clk_hw *zynqmp_clk_register_pll(const char *name, u32 clk_id, const char * const *parents, u8 num_parents, diff --git a/drivers/clk/zynqmp/clkc.c b/drivers/clk/zynqmp/clkc.c index db8d0d7161ce..871184e406e1 100644 --- a/drivers/clk/zynqmp/clkc.c +++ b/drivers/clk/zynqmp/clkc.c @@ -271,6 +271,26 @@ static int zynqmp_pm_clock_get_topology(u32 clock_id, u32 index, return ret; } +unsigned long zynqmp_clk_map_common_ccf_flags(const u32 zynqmp_flag) +{ + unsigned long ccf_flag = 0; + + if (zynqmp_flag & ZYNQMP_CLK_SET_RATE_GATE) + ccf_flag |= CLK_SET_RATE_GATE; + if (zynqmp_flag & ZYNQMP_CLK_SET_PARENT_GATE) + ccf_flag |= CLK_SET_PARENT_GATE; + if (zynqmp_flag & ZYNQMP_CLK_SET_RATE_PARENT) + ccf_flag |= CLK_SET_RATE_PARENT; + if (zynqmp_flag & ZYNQMP_CLK_IGNORE_UNUSED) + ccf_flag |= CLK_IGNORE_UNUSED; + if (zynqmp_flag & ZYNQMP_CLK_SET_RATE_NO_REPARENT) + ccf_flag |= CLK_SET_RATE_NO_REPARENT; + if (zynqmp_flag & ZYNQMP_CLK_IS_CRITICAL) + ccf_flag |= CLK_IS_CRITICAL; + + return ccf_flag; +} + /** * zynqmp_clk_register_fixed_factor() - Register fixed factor with the * clock framework @@ -292,6 +312,7 @@ struct clk_hw *zynqmp_clk_register_fixed_factor(const char *name, u32 clk_id, struct zynqmp_pm_query_data qdata = {0}; u32 ret_payload[PAYLOAD_ARG_CNT]; int ret; + unsigned long flag; qdata.qid = PM_QID_CLOCK_GET_FIXEDFACTOR_PARAMS; qdata.arg1 = clk_id; @@ -303,9 +324,11 @@ struct clk_hw *zynqmp_clk_register_fixed_factor(const char *name, u32 clk_id, mult = ret_payload[1]; div = ret_payload[2]; + flag = zynqmp_clk_map_common_ccf_flags(nodes->flag); + hw = clk_hw_register_fixed_factor(NULL, name, parents[0], - nodes->flag, mult, + flag, mult, div); return hw; diff --git a/drivers/clk/zynqmp/divider.c b/drivers/clk/zynqmp/divider.c index e9bf7958b821..cb49281f9cf9 100644 --- a/drivers/clk/zynqmp/divider.c +++ b/drivers/clk/zynqmp/divider.c @@ -256,6 +256,11 @@ static const struct clk_ops zynqmp_clk_divider_ops = { .set_rate = zynqmp_clk_divider_set_rate, }; +static const struct clk_ops zynqmp_clk_divider_ro_ops = { + .recalc_rate = zynqmp_clk_divider_recalc_rate, + .round_rate = zynqmp_clk_divider_round_rate, +}; + /** * zynqmp_clk_get_max_divisor() - Get maximum supported divisor from firmware. * @clk_id: Id of clock @@ -284,6 +289,29 @@ static u32 zynqmp_clk_get_max_divisor(u32 clk_id, u32 type) return ret_payload[1]; } +static inline unsigned long zynqmp_clk_map_divider_ccf_flags( + const u32 zynqmp_type_flag) +{ + unsigned long ccf_flag = 0; + + if (zynqmp_type_flag & ZYNQMP_CLK_DIVIDER_ONE_BASED) + ccf_flag |= CLK_DIVIDER_ONE_BASED; + if (zynqmp_type_flag & ZYNQMP_CLK_DIVIDER_POWER_OF_TWO) + ccf_flag |= CLK_DIVIDER_POWER_OF_TWO; + if (zynqmp_type_flag & ZYNQMP_CLK_DIVIDER_ALLOW_ZERO) + ccf_flag |= CLK_DIVIDER_ALLOW_ZERO; + if (zynqmp_type_flag & ZYNQMP_CLK_DIVIDER_POWER_OF_TWO) + ccf_flag |= CLK_DIVIDER_HIWORD_MASK; + if (zynqmp_type_flag & ZYNQMP_CLK_DIVIDER_ROUND_CLOSEST) + ccf_flag |= CLK_DIVIDER_ROUND_CLOSEST; + if (zynqmp_type_flag & ZYNQMP_CLK_DIVIDER_READ_ONLY) + ccf_flag |= CLK_DIVIDER_READ_ONLY; + if (zynqmp_type_flag & ZYNQMP_CLK_DIVIDER_MAX_AT_ZERO) + ccf_flag |= CLK_DIVIDER_MAX_AT_ZERO; + + return ccf_flag; +} + /** * zynqmp_clk_register_divider() - Register a divider clock * @name: Name of this clock @@ -311,16 +339,20 @@ struct clk_hw *zynqmp_clk_register_divider(const char *name, return ERR_PTR(-ENOMEM); init.name = name; - init.ops = &zynqmp_clk_divider_ops; - /* CLK_FRAC is not defined in the common clk framework */ - init.flags = nodes->flag & ~CLK_FRAC; + if (nodes->type_flag & CLK_DIVIDER_READ_ONLY) + init.ops = &zynqmp_clk_divider_ro_ops; + else + init.ops = &zynqmp_clk_divider_ops; + + init.flags = zynqmp_clk_map_common_ccf_flags(nodes->flag); + init.parent_names = parents; init.num_parents = 1; /* struct clk_divider assignments */ div->is_frac = !!((nodes->flag & CLK_FRAC) | (nodes->custom_type_flag & CUSTOM_FLAG_CLK_FRAC)); - div->flags = nodes->type_flag; + div->flags = zynqmp_clk_map_divider_ccf_flags(nodes->type_flag); div->hw.init = &init; div->clk_id = clk_id; div->div_type = nodes->type; diff --git a/drivers/clk/zynqmp/pll.c b/drivers/clk/zynqmp/pll.c index abe6afbf3407..036e4ff64a2f 100644 --- a/drivers/clk/zynqmp/pll.c +++ b/drivers/clk/zynqmp/pll.c @@ -31,8 +31,9 @@ struct zynqmp_pll { #define PS_PLL_VCO_MAX 3000000000UL enum pll_mode { - PLL_MODE_INT, - PLL_MODE_FRAC, + PLL_MODE_INT = 0, + PLL_MODE_FRAC = 1, + PLL_MODE_ERROR = 2, }; #define FRAC_OFFSET 0x8 @@ -54,9 +55,11 @@ static inline enum pll_mode zynqmp_pll_get_mode(struct clk_hw *hw) int ret; ret = zynqmp_pm_get_pll_frac_mode(clk_id, ret_payload); - if (ret) + if (ret) { pr_warn_once("%s() PLL get frac mode failed for %s, ret = %d\n", __func__, clk_name, ret); + return PLL_MODE_ERROR; + } return ret_payload[1]; } @@ -126,7 +129,7 @@ static long zynqmp_pll_round_rate(struct clk_hw *hw, unsigned long rate, * @hw: Handle between common and hardware-specific interfaces * @parent_rate: Clock frequency of parent clock * - * Return: Current clock frequency + * Return: Current clock frequency or 0 in case of error */ static unsigned long zynqmp_pll_recalc_rate(struct clk_hw *hw, unsigned long parent_rate) @@ -138,14 +141,21 @@ static unsigned long zynqmp_pll_recalc_rate(struct clk_hw *hw, unsigned long rate, frac; u32 ret_payload[PAYLOAD_ARG_CNT]; int ret; + enum pll_mode mode; ret = zynqmp_pm_clock_getdivider(clk_id, &fbdiv); - if (ret) + if (ret) { pr_warn_once("%s() get divider failed for %s, ret = %d\n", __func__, clk_name, ret); + return 0ul; + } + + mode = zynqmp_pll_get_mode(hw); + if (mode == PLL_MODE_ERROR) + return 0ul; rate = parent_rate * fbdiv; - if (zynqmp_pll_get_mode(hw) == PLL_MODE_FRAC) { + if (mode == PLL_MODE_FRAC) { zynqmp_pm_get_pll_frac_data(clk_id, ret_payload); data = ret_payload[1]; frac = (parent_rate * data) / FRAC_DIV; @@ -312,7 +322,9 @@ struct clk_hw *zynqmp_clk_register_pll(const char *name, u32 clk_id, init.name = name; init.ops = &zynqmp_pll_ops; - init.flags = nodes->flag; + + init.flags = zynqmp_clk_map_common_ccf_flags(nodes->flag); + init.parent_names = parents; init.num_parents = 1; @@ -331,8 +343,6 @@ struct clk_hw *zynqmp_clk_register_pll(const char *name, u32 clk_id, } clk_hw_set_rate_range(hw, PS_PLL_VCO_MIN, PS_PLL_VCO_MAX); - if (ret < 0) - pr_err("%s:ERROR clk_set_rate_range failed %d\n", name, ret); return hw; } |