[PATCH v2 0/4] clk: sophgo: milkv_duo: Add and enable clock controller driver

This series of patches introduces the clock controller driver for the Sophgo CV1800B SoC, updates the device tree sources to use the new clock controller, and enables the clock controller in the configuration for the Milk-V Duo board.
Changes in v2: - Fix compilation error - Remove unused code
Kongyang Liu (4): dt-bindings: clk: import header for clock controller of sophgo CV1800B clk: sophgo: cv1800b: Add clock controller driver for cv1800b SoC configs: milkv_duo: Enable clock controller riscv: dts: sophgo: Replace device clocks with real clocks.
arch/riscv/dts/cv18xx.dtsi | 40 +- configs/milkv_duo_defconfig | 9 +- drivers/clk/Kconfig | 1 + drivers/clk/Makefile | 1 + drivers/clk/sophgo/Kconfig | 14 + drivers/clk/sophgo/Makefile | 6 + drivers/clk/sophgo/clk-common.h | 74 +++ drivers/clk/sophgo/clk-cv1800b.c | 754 ++++++++++++++++++++++ drivers/clk/sophgo/clk-cv1800b.h | 123 ++++ drivers/clk/sophgo/clk-ip.c | 594 +++++++++++++++++ drivers/clk/sophgo/clk-ip.h | 288 +++++++++ drivers/clk/sophgo/clk-pll.c | 275 ++++++++ drivers/clk/sophgo/clk-pll.h | 74 +++ include/dt-bindings/clock/sophgo,cv1800.h | 176 +++++ 14 files changed, 2401 insertions(+), 28 deletions(-) create mode 100644 drivers/clk/sophgo/Kconfig create mode 100644 drivers/clk/sophgo/Makefile create mode 100644 drivers/clk/sophgo/clk-common.h create mode 100644 drivers/clk/sophgo/clk-cv1800b.c create mode 100644 drivers/clk/sophgo/clk-cv1800b.h create mode 100644 drivers/clk/sophgo/clk-ip.c create mode 100644 drivers/clk/sophgo/clk-ip.h create mode 100644 drivers/clk/sophgo/clk-pll.c create mode 100644 drivers/clk/sophgo/clk-pll.h create mode 100644 include/dt-bindings/clock/sophgo,cv1800.h

Import header file of sophgo cv1800b clock controller from kernel
Signed-off-by: Kongyang Liu seashell11234455@gmail.com Link: https://lore.kernel.org/all/IA1PR20MB4953637E7A6C121D7A700F1CBB8BA@IA1PR20MB...
---
(no changes since v1)
include/dt-bindings/clock/sophgo,cv1800.h | 176 ++++++++++++++++++++++ 1 file changed, 176 insertions(+) create mode 100644 include/dt-bindings/clock/sophgo,cv1800.h
diff --git a/include/dt-bindings/clock/sophgo,cv1800.h b/include/dt-bindings/clock/sophgo,cv1800.h new file mode 100644 index 0000000000..cfbeca25a6 --- /dev/null +++ b/include/dt-bindings/clock/sophgo,cv1800.h @@ -0,0 +1,176 @@ +/* SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause */ +/* + * Copyright (C) 2023 Sophgo Ltd. + */ + +#ifndef __DT_BINDINGS_SOPHGO_CV1800_CLK_H__ +#define __DT_BINDINGS_SOPHGO_CV1800_CLK_H__ + +#define CLK_MPLL 0 +#define CLK_TPLL 1 +#define CLK_FPLL 2 +#define CLK_MIPIMPLL 3 +#define CLK_A0PLL 4 +#define CLK_DISPPLL 5 +#define CLK_CAM0PLL 6 +#define CLK_CAM1PLL 7 + +#define CLK_MIPIMPLL_D3 8 +#define CLK_CAM0PLL_D2 9 +#define CLK_CAM0PLL_D3 10 + +#define CLK_TPU 11 +#define CLK_TPU_FAB 12 +#define CLK_AHB_ROM 13 +#define CLK_DDR_AXI_REG 14 +#define CLK_RTC_25M 15 +#define CLK_SRC_RTC_SYS_0 16 +#define CLK_TEMPSEN 17 +#define CLK_SARADC 18 +#define CLK_EFUSE 19 +#define CLK_APB_EFUSE 20 +#define CLK_DEBUG 21 +#define CLK_AP_DEBUG 22 +#define CLK_XTAL_MISC 23 +#define CLK_AXI4_EMMC 24 +#define CLK_EMMC 25 +#define CLK_EMMC_100K 26 +#define CLK_AXI4_SD0 27 +#define CLK_SD0 28 +#define CLK_SD0_100K 29 +#define CLK_AXI4_SD1 30 +#define CLK_SD1 31 +#define CLK_SD1_100K 32 +#define CLK_SPI_NAND 33 +#define CLK_ETH0_500M 34 +#define CLK_AXI4_ETH0 35 +#define CLK_ETH1_500M 36 +#define CLK_AXI4_ETH1 37 +#define CLK_APB_GPIO 38 +#define CLK_APB_GPIO_INTR 39 +#define CLK_GPIO_DB 40 +#define CLK_AHB_SF 41 +#define CLK_AHB_SF1 42 +#define CLK_A24M 43 +#define CLK_AUDSRC 44 +#define CLK_APB_AUDSRC 45 +#define CLK_SDMA_AXI 46 +#define CLK_SDMA_AUD0 47 +#define CLK_SDMA_AUD1 48 +#define CLK_SDMA_AUD2 49 +#define CLK_SDMA_AUD3 50 +#define CLK_I2C 51 +#define CLK_APB_I2C 52 +#define CLK_APB_I2C0 53 +#define CLK_APB_I2C1 54 +#define CLK_APB_I2C2 55 +#define CLK_APB_I2C3 56 +#define CLK_APB_I2C4 57 +#define CLK_APB_WDT 58 +#define CLK_PWM_SRC 59 +#define CLK_PWM 60 +#define CLK_SPI 61 +#define CLK_APB_SPI0 62 +#define CLK_APB_SPI1 63 +#define CLK_APB_SPI2 64 +#define CLK_APB_SPI3 65 +#define CLK_1M 66 +#define CLK_CAM0_200 67 +#define CLK_PM 68 +#define CLK_TIMER0 69 +#define CLK_TIMER1 70 +#define CLK_TIMER2 71 +#define CLK_TIMER3 72 +#define CLK_TIMER4 73 +#define CLK_TIMER5 74 +#define CLK_TIMER6 75 +#define CLK_TIMER7 76 +#define CLK_UART0 77 +#define CLK_APB_UART0 78 +#define CLK_UART1 79 +#define CLK_APB_UART1 80 +#define CLK_UART2 81 +#define CLK_APB_UART2 82 +#define CLK_UART3 83 +#define CLK_APB_UART3 84 +#define CLK_UART4 85 +#define CLK_APB_UART4 86 +#define CLK_APB_I2S0 87 +#define CLK_APB_I2S1 88 +#define CLK_APB_I2S2 89 +#define CLK_APB_I2S3 90 +#define CLK_AXI4_USB 91 +#define CLK_APB_USB 92 +#define CLK_USB_125M 93 +#define CLK_USB_33K 94 +#define CLK_USB_12M 95 +#define CLK_AXI4 96 +#define CLK_AXI6 97 +#define CLK_DSI_ESC 98 +#define CLK_AXI_VIP 99 +#define CLK_SRC_VIP_SYS_0 100 +#define CLK_SRC_VIP_SYS_1 101 +#define CLK_SRC_VIP_SYS_2 102 +#define CLK_SRC_VIP_SYS_3 103 +#define CLK_SRC_VIP_SYS_4 104 +#define CLK_CSI_BE_VIP 105 +#define CLK_CSI_MAC0_VIP 106 +#define CLK_CSI_MAC1_VIP 107 +#define CLK_CSI_MAC2_VIP 108 +#define CLK_CSI0_RX_VIP 109 +#define CLK_CSI1_RX_VIP 110 +#define CLK_ISP_TOP_VIP 111 +#define CLK_IMG_D_VIP 112 +#define CLK_IMG_V_VIP 113 +#define CLK_SC_TOP_VIP 114 +#define CLK_SC_D_VIP 115 +#define CLK_SC_V1_VIP 116 +#define CLK_SC_V2_VIP 117 +#define CLK_SC_V3_VIP 118 +#define CLK_DWA_VIP 119 +#define CLK_BT_VIP 120 +#define CLK_DISP_VIP 121 +#define CLK_DSI_MAC_VIP 122 +#define CLK_LVDS0_VIP 123 +#define CLK_LVDS1_VIP 124 +#define CLK_PAD_VI_VIP 125 +#define CLK_PAD_VI1_VIP 126 +#define CLK_PAD_VI2_VIP 127 +#define CLK_CFG_REG_VIP 128 +#define CLK_VIP_IP0 129 +#define CLK_VIP_IP1 130 +#define CLK_VIP_IP2 131 +#define CLK_VIP_IP3 132 +#define CLK_IVE_VIP 133 +#define CLK_RAW_VIP 134 +#define CLK_OSDC_VIP 135 +#define CLK_CAM0_VIP 136 +#define CLK_AXI_VIDEO_CODEC 137 +#define CLK_VC_SRC0 138 +#define CLK_VC_SRC1 139 +#define CLK_VC_SRC2 140 +#define CLK_H264C 141 +#define CLK_APB_H264C 142 +#define CLK_H265C 143 +#define CLK_APB_H265C 144 +#define CLK_JPEG 145 +#define CLK_APB_JPEG 146 +#define CLK_CAM0 147 +#define CLK_CAM1 148 +#define CLK_WGN 149 +#define CLK_WGN0 150 +#define CLK_WGN1 151 +#define CLK_WGN2 152 +#define CLK_KEYSCAN 153 +#define CLK_CFG_REG_VC 154 +#define CLK_C906_0 155 +#define CLK_C906_1 156 +#define CLK_A53 157 +#define CLK_CPU_AXI0 158 +#define CLK_CPU_GIC 159 +#define CLK_XTAL_AP 160 + +// Only for CV181x +#define CLK_DISP_SRC_VIP 161 + +#endif /* __DT_BINDINGS_SOPHGO_CV1800_CLK_H__ */

On Tue, Jun 11, 2024 at 05:41:13PM +0800, Kongyang Liu wrote:
Import header file of sophgo cv1800b clock controller from kernel
Signed-off-by: Kongyang Liu seashell11234455@gmail.com Link: https://lore.kernel.org/all/IA1PR20MB4953637E7A6C121D7A700F1CBB8BA@IA1PR20MB...
(no changes since v1)
include/dt-bindings/clock/sophgo,cv1800.h | 176 ++++++++++++++++++++++ 1 file changed, 176 insertions(+) create mode 100644 include/dt-bindings/clock/sophgo,cv1800.h
Reviewed-by: Leo Yu-Chi Liang ycliang@andestech.com

Add clock controller driver for sophgo cv1800b SoC
Signed-off-by: Kongyang Liu seashell11234455@gmail.com
---
Changes in v2: - Fix compilation error - Remove unused code
drivers/clk/Kconfig | 1 + drivers/clk/Makefile | 1 + drivers/clk/sophgo/Kconfig | 14 + drivers/clk/sophgo/Makefile | 6 + drivers/clk/sophgo/clk-common.h | 74 +++ drivers/clk/sophgo/clk-cv1800b.c | 754 +++++++++++++++++++++++++++++++ drivers/clk/sophgo/clk-cv1800b.h | 123 +++++ drivers/clk/sophgo/clk-ip.c | 594 ++++++++++++++++++++++++ drivers/clk/sophgo/clk-ip.h | 288 ++++++++++++ drivers/clk/sophgo/clk-pll.c | 275 +++++++++++ drivers/clk/sophgo/clk-pll.h | 74 +++ 11 files changed, 2204 insertions(+) create mode 100644 drivers/clk/sophgo/Kconfig create mode 100644 drivers/clk/sophgo/Makefile create mode 100644 drivers/clk/sophgo/clk-common.h create mode 100644 drivers/clk/sophgo/clk-cv1800b.c create mode 100644 drivers/clk/sophgo/clk-cv1800b.h create mode 100644 drivers/clk/sophgo/clk-ip.c create mode 100644 drivers/clk/sophgo/clk-ip.h create mode 100644 drivers/clk/sophgo/clk-pll.c create mode 100644 drivers/clk/sophgo/clk-pll.h
diff --git a/drivers/clk/Kconfig b/drivers/clk/Kconfig index bda6873be3..0a16b88f78 100644 --- a/drivers/clk/Kconfig +++ b/drivers/clk/Kconfig @@ -256,6 +256,7 @@ source "drivers/clk/mvebu/Kconfig" source "drivers/clk/owl/Kconfig" source "drivers/clk/qcom/Kconfig" source "drivers/clk/renesas/Kconfig" +source "drivers/clk/sophgo/Kconfig" source "drivers/clk/sunxi/Kconfig" source "drivers/clk/sifive/Kconfig" source "drivers/clk/starfive/Kconfig" diff --git a/drivers/clk/Makefile b/drivers/clk/Makefile index 638ad04bae..d9b1e5a341 100644 --- a/drivers/clk/Makefile +++ b/drivers/clk/Makefile @@ -43,6 +43,7 @@ obj-$(CONFIG_CLK_QCOM) += qcom/ obj-$(CONFIG_CLK_RENESAS) += renesas/ obj-$(CONFIG_$(SPL_TPL_)CLK_SCMI) += clk_scmi.o obj-$(CONFIG_CLK_SIFIVE) += sifive/ +obj-$(CONFIG_CLK_SOPHGO) += sophgo/ obj-$(CONFIG_CLK_SUNXI) += sunxi/ obj-$(CONFIG_CLK_UNIPHIER) += uniphier/ obj-$(CONFIG_CLK_VERSACLOCK) += clk_versaclock.o diff --git a/drivers/clk/sophgo/Kconfig b/drivers/clk/sophgo/Kconfig new file mode 100644 index 0000000000..59b51608fe --- /dev/null +++ b/drivers/clk/sophgo/Kconfig @@ -0,0 +1,14 @@ +# SPDX-License-Identifier: GPL-2.0+ +# +# Copyright (c) 2024, Kongyang Liu seashell11234455@gmail.com + +config CLK_SOPHGO + bool + +config CLK_SOPHGO_CV1800B + bool "Sophgo CV1800B clock support" + depends on CLK + select CLK_CCF + select CLK_SOPHGO + help + This enables support clock driver for Sophgo CV1800B SoC. diff --git a/drivers/clk/sophgo/Makefile b/drivers/clk/sophgo/Makefile new file mode 100644 index 0000000000..caec76222b --- /dev/null +++ b/drivers/clk/sophgo/Makefile @@ -0,0 +1,6 @@ +# SPDX-License-Identifier: GPL-2.0+ +# +# Copyright (c) 2024, Kongyang Liu seashell11234455@gmail.com + +obj-y += clk-ip.o clk-pll.o +obj-$(CONFIG_CLK_SOPHGO_CV1800B) += clk-cv1800b.o diff --git a/drivers/clk/sophgo/clk-common.h b/drivers/clk/sophgo/clk-common.h new file mode 100644 index 0000000000..95b82e968d --- /dev/null +++ b/drivers/clk/sophgo/clk-common.h @@ -0,0 +1,74 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ +/* + * Copyright (c) 2024, Kongyang Liu seashell11234455@gmail.com + * + */ + +#ifndef __CLK_SOPHGO_COMMON_H__ +#define __CLK_SOPHGO_COMMON_H__ + +#include <linux/bitops.h> +#include <linux/io.h> + +#define CV1800B_CLK_OSC 1 +#define CV1800B_CLK_BYPASS 2 +#define CV1800B_CLK_ID_TRANSFORM(_id) ((_id) + 3) + +struct cv1800b_clk_regbit { + u32 offset; + u8 shift; +}; + +struct cv1800b_clk_regfield { + u32 offset; + u8 shift; + u8 width; +}; + +#define CV1800B_CLK_REGBIT(_offset, _shift) \ + { \ + .offset = _offset, \ + .shift = _shift, \ + } + +#define CV1800B_CLK_REGFIELD(_offset, _shift, _width) \ + { \ + .offset = _offset, \ + .shift = _shift, \ + .width = _width, \ + } + +static inline u32 cv1800b_clk_getbit(void *base, struct cv1800b_clk_regbit *bit) +{ + return readl(base + bit->offset) & (BIT(bit->shift)); +} + +static inline u32 cv1800b_clk_setbit(void *base, struct cv1800b_clk_regbit *bit) +{ + return setbits_le32(base + bit->offset, BIT(bit->shift)); +} + +static inline u32 cv1800b_clk_clrbit(void *base, struct cv1800b_clk_regbit *bit) +{ + return clrbits_le32(base + bit->offset, BIT(bit->shift)); +} + +static inline u32 cv1800b_clk_getfield(void *base, + struct cv1800b_clk_regfield *field) +{ + u32 mask = GENMASK(field->shift + field->width - 1, field->shift); + + return (readl(base + field->offset) & mask) >> field->shift; +} + +static inline void +cv1800b_clk_setfield(void *base, struct cv1800b_clk_regfield *field, u32 val) +{ + u32 mask = GENMASK(field->shift + field->width - 1, field->shift); + u32 new_val = (readl(base + field->offset) & ~mask) | + ((val << field->shift) & mask); + + return writel(new_val, base + field->offset); +} + +#endif /* __CLK_SOPHGO_COMMON_H__ */ diff --git a/drivers/clk/sophgo/clk-cv1800b.c b/drivers/clk/sophgo/clk-cv1800b.c new file mode 100644 index 0000000000..d946ea57a4 --- /dev/null +++ b/drivers/clk/sophgo/clk-cv1800b.c @@ -0,0 +1,754 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright (c) 2024, Kongyang Liu seashell11234455@gmail.com + */ + +#include <clk-uclass.h> +#include <dm.h> +#include <linux/clk-provider.h> + +#include "clk-common.h" +#include "clk-cv1800b.h" +#include "clk-ip.h" +#include "clk-pll.h" + +static const char *const clk_cam_parents[] = { + "clk_cam0pll", + "clk_cam0pll_d2", + "clk_cam0pll_d3", + "clk_mipimpll_d3" +}; + +static const char *const clk_tpu_parents[] = { + "clk_tpll", + "clk_a0pll", + "clk_mipimpll", + "clk_fpll" +}; + +static const char *const clk_axi4_parents[] = { "clk_fpll", "clk_disppll" }; +static const char *const clk_aud_parents[] = { "clk_a0pll", "clk_a24m" }; +static const char *const clk_cam0_200_parents[] = { "osc", "clk_disppll" }; + +static const char *const clk_vip_sys_parents[] = { + "clk_mipimpll", + "clk_cam0pll", + "clk_disppll", + "clk_fpll" +}; + +static const char *const clk_axi_video_codec_parents[] = { + "clk_a0pll", + "clk_mipimpll", + "clk_cam1pll", + "clk_fpll" +}; + +static const char *const clk_vc_src0_parents[] = { + "clk_disppll", + "clk_mipimpll", + "clk_cam1pll", + "clk_fpll" +}; + +static const struct cv1800b_mmux_parent_info clk_c906_0_parents[] = { + { "clk_tpll", 0, 0 }, + { "clk_a0pll", 0, 1 }, + { "clk_mipimpll", 0, 2 }, + { "clk_mpll", 0, 3 }, + { "clk_fpll", 1, 0 }, +}; + +static const struct cv1800b_mmux_parent_info clk_c906_1_parents[] = { + { "clk_tpll", 0, 0 }, + { "clk_a0pll", 0, 1 }, + { "clk_disppll", 0, 2 }, + { "clk_mpll", 0, 3 }, + { "clk_fpll", 1, 0 }, +}; + +static const struct cv1800b_mmux_parent_info clk_a53_parents[] = { + { "clk_tpll", 0, 0 }, + { "clk_a0pll", 0, 1 }, + { "clk_mipimpll", 0, 2 }, + { "clk_mpll", 0, 3 }, + { "clk_fpll", 1, 0 }, +}; + +static struct cv1800b_clk_gate cv1800b_gate_info[] = { + CV1800B_GATE(CLK_XTAL_AP, "clk_xtal_ap", "osc", REG_CLK_EN_0, 3, CLK_IS_CRITICAL), + CV1800B_GATE(CLK_RTC_25M, "clk_rtc_25m", "osc", REG_CLK_EN_0, 8, CLK_IS_CRITICAL), + CV1800B_GATE(CLK_TEMPSEN, "clk_tempsen", "osc", REG_CLK_EN_0, 9, 0), + CV1800B_GATE(CLK_SARADC, "clk_saradc", "osc", REG_CLK_EN_0, 10, 0), + CV1800B_GATE(CLK_EFUSE, "clk_efuse", "osc", REG_CLK_EN_0, 11, 0), + CV1800B_GATE(CLK_APB_EFUSE, "clk_apb_efuse", "osc", REG_CLK_EN_0, 12, 0), + CV1800B_GATE(CLK_DEBUG, "clk_debug", "osc", REG_CLK_EN_0, 13, CLK_IS_CRITICAL), + CV1800B_GATE(CLK_XTAL_MISC, "clk_xtal_misc", "osc", REG_CLK_EN_0, 14, CLK_IS_CRITICAL), + CV1800B_GATE(CLK_APB_WDT, "clk_apb_wdt", "osc", REG_CLK_EN_1, 7, CLK_IS_CRITICAL), + CV1800B_GATE(CLK_WGN, "clk_wgn", "osc", REG_CLK_EN_3, 22, 0), + CV1800B_GATE(CLK_WGN0, "clk_wgn0", "osc", REG_CLK_EN_3, 23, 0), + CV1800B_GATE(CLK_WGN1, "clk_wgn1", "osc", REG_CLK_EN_3, 24, 0), + CV1800B_GATE(CLK_WGN2, "clk_wgn2", "osc", REG_CLK_EN_3, 25, 0), + CV1800B_GATE(CLK_KEYSCAN, "clk_keyscan", "osc", REG_CLK_EN_3, 26, 0), + CV1800B_GATE(CLK_TPU_FAB, "clk_tpu_fab", "clk_mipimpll", REG_CLK_EN_0, 5, 0), + CV1800B_GATE(CLK_AHB_ROM, "clk_ahb_rom", "clk_axi4", REG_CLK_EN_0, 6, 0), + CV1800B_GATE(CLK_AXI4_EMMC, "clk_axi4_emmc", "clk_axi4", REG_CLK_EN_0, 15, 0), + CV1800B_GATE(CLK_AXI4_SD0, "clk_axi4_sd0", "clk_axi4", REG_CLK_EN_0, 18, 0), + CV1800B_GATE(CLK_AXI4_SD1, "clk_axi4_sd1", "clk_axi4", REG_CLK_EN_0, 21, 0), + CV1800B_GATE(CLK_AXI4_ETH0, "clk_axi4_eth0", "clk_axi4", REG_CLK_EN_0, 26, 0), + CV1800B_GATE(CLK_AXI4_ETH1, "clk_axi4_eth1", "clk_axi4", REG_CLK_EN_0, 28, 0), + CV1800B_GATE(CLK_AHB_SF, "clk_ahb_sf", "clk_axi4", REG_CLK_EN_1, 0, 0), + CV1800B_GATE(CLK_SDMA_AXI, "clk_sdma_axi", "clk_axi4", REG_CLK_EN_1, 1, 0), + CV1800B_GATE(CLK_APB_I2C, "clk_apb_i2c", "clk_axi4", REG_CLK_EN_1, 6, 0), + CV1800B_GATE(CLK_APB_SPI0, "clk_apb_spi0", "clk_axi4", REG_CLK_EN_1, 9, 0), + CV1800B_GATE(CLK_APB_SPI1, "clk_apb_spi1", "clk_axi4", REG_CLK_EN_1, 10, 0), + CV1800B_GATE(CLK_APB_SPI2, "clk_apb_spi2", "clk_axi4", REG_CLK_EN_1, 11, 0), + CV1800B_GATE(CLK_APB_SPI3, "clk_apb_spi3", "clk_axi4", REG_CLK_EN_1, 12, 0), + CV1800B_GATE(CLK_APB_UART0, "clk_apb_uart0", "clk_axi4", REG_CLK_EN_1, 15, CLK_IS_CRITICAL), + CV1800B_GATE(CLK_APB_UART1, "clk_apb_uart1", "clk_axi4", REG_CLK_EN_1, 17, 0), + CV1800B_GATE(CLK_APB_UART2, "clk_apb_uart2", "clk_axi4", REG_CLK_EN_1, 19, 0), + CV1800B_GATE(CLK_APB_UART3, "clk_apb_uart3", "clk_axi4", REG_CLK_EN_1, 21, 0), + CV1800B_GATE(CLK_APB_UART4, "clk_apb_uart4", "clk_axi4", REG_CLK_EN_1, 23, 0), + CV1800B_GATE(CLK_APB_I2S0, "clk_apb_i2s0", "clk_axi4", REG_CLK_EN_1, 24, 0), + CV1800B_GATE(CLK_APB_I2S1, "clk_apb_i2s1", "clk_axi4", REG_CLK_EN_1, 25, 0), + CV1800B_GATE(CLK_APB_I2S2, "clk_apb_i2s2", "clk_axi4", REG_CLK_EN_1, 26, 0), + CV1800B_GATE(CLK_APB_I2S3, "clk_apb_i2s3", "clk_axi4", REG_CLK_EN_1, 27, 0), + CV1800B_GATE(CLK_AXI4_USB, "clk_axi4_usb", "clk_axi4", REG_CLK_EN_1, 28, 0), + CV1800B_GATE(CLK_APB_USB, "clk_apb_usb", "clk_axi4", REG_CLK_EN_1, 29, 0), + CV1800B_GATE(CLK_APB_I2C0, "clk_apb_i2c0", "clk_axi4", REG_CLK_EN_3, 17, 0), + CV1800B_GATE(CLK_APB_I2C1, "clk_apb_i2c1", "clk_axi4", REG_CLK_EN_3, 18, 0), + CV1800B_GATE(CLK_APB_I2C2, "clk_apb_i2c2", "clk_axi4", REG_CLK_EN_3, 19, 0), + CV1800B_GATE(CLK_APB_I2C3, "clk_apb_i2c3", "clk_axi4", REG_CLK_EN_3, 20, 0), + CV1800B_GATE(CLK_APB_I2C4, "clk_apb_i2c4", "clk_axi4", REG_CLK_EN_3, 21, 0), + CV1800B_GATE(CLK_AHB_SF1, "clk_ahb_sf1", "clk_axi4", REG_CLK_EN_3, 27, 0), + CV1800B_GATE(CLK_APB_AUDSRC, "clk_apb_audsrc", "clk_axi4", REG_CLK_EN_4, 2, 0), + CV1800B_GATE(CLK_DDR_AXI_REG, "clk_ddr_axi_reg", "clk_axi6", REG_CLK_EN_0, 7, + CLK_IS_CRITICAL), + CV1800B_GATE(CLK_APB_GPIO, "clk_apb_gpio", "clk_axi6", REG_CLK_EN_0, 29, CLK_IS_CRITICAL), + CV1800B_GATE(CLK_APB_GPIO_INTR, "clk_apb_gpio_intr", "clk_axi6", REG_CLK_EN_0, 30, + CLK_IS_CRITICAL), + CV1800B_GATE(CLK_APB_JPEG, "clk_apb_jpeg", "clk_axi6", REG_CLK_EN_2, 13, CLK_IGNORE_UNUSED), + CV1800B_GATE(CLK_APB_H264C, "clk_apb_h264c", "clk_axi6", REG_CLK_EN_2, 14, 0), + CV1800B_GATE(CLK_APB_H265C, "clk_apb_h265c", "clk_axi6", REG_CLK_EN_2, 15, 0), + CV1800B_GATE(CLK_PM, "clk_pm", "clk_axi6", REG_CLK_EN_3, 8, CLK_IS_CRITICAL), + CV1800B_GATE(CLK_CFG_REG_VIP, "clk_cfg_reg_vip", "clk_axi6", REG_CLK_EN_3, 31, 0), + CV1800B_GATE(CLK_CFG_REG_VC, "clk_cfg_reg_vc", "clk_axi6", REG_CLK_EN_4, 0, + CLK_IGNORE_UNUSED), + CV1800B_GATE(CLK_PWM, "clk_pwm", "clk_pwm_src", REG_CLK_EN_1, 8, CLK_IS_CRITICAL), + CV1800B_GATE(CLK_UART0, "clk_uart0", "clk_cam0_200", REG_CLK_EN_1, 14, CLK_IS_CRITICAL), + CV1800B_GATE(CLK_UART1, "clk_uart1", "clk_cam0_200", REG_CLK_EN_1, 16, 0), + CV1800B_GATE(CLK_UART2, "clk_uart2", "clk_cam0_200", REG_CLK_EN_1, 18, 0), + CV1800B_GATE(CLK_UART3, "clk_uart3", "clk_cam0_200", REG_CLK_EN_1, 20, 0), + CV1800B_GATE(CLK_UART4, "clk_uart4", "clk_cam0_200", REG_CLK_EN_1, 22, 0), + CV1800B_GATE(CLK_H264C, "clk_h264c", "clk_axi_video_codec", REG_CLK_EN_2, 10, 0), + CV1800B_GATE(CLK_H265C, "clk_h265c", "clk_axi_video_codec", REG_CLK_EN_2, 11, 0), + CV1800B_GATE(CLK_JPEG, "clk_jpeg", "clk_axi_video_codec", REG_CLK_EN_2, 12, + CLK_IGNORE_UNUSED), + CV1800B_GATE(CLK_CSI_MAC0_VIP, "clk_csi_mac0_vip", "clk_axi_vip", REG_CLK_EN_2, 18, 0), + CV1800B_GATE(CLK_CSI_MAC1_VIP, "clk_csi_mac1_vip", "clk_axi_vip", REG_CLK_EN_2, 19, 0), + CV1800B_GATE(CLK_ISP_TOP_VIP, "clk_isp_top_vip", "clk_axi_vip", REG_CLK_EN_2, 20, 0), + CV1800B_GATE(CLK_IMG_D_VIP, "clk_img_d_vip", "clk_axi_vip", REG_CLK_EN_2, 21, 0), + CV1800B_GATE(CLK_IMG_V_VIP, "clk_img_v_vip", "clk_axi_vip", REG_CLK_EN_2, 22, 0), + CV1800B_GATE(CLK_SC_TOP_VIP, "clk_sc_top_vip", "clk_axi_vip", REG_CLK_EN_2, 23, 0), + CV1800B_GATE(CLK_SC_D_VIP, "clk_sc_d_vip", "clk_axi_vip", REG_CLK_EN_2, 24, 0), + CV1800B_GATE(CLK_SC_V1_VIP, "clk_sc_v1_vip", "clk_axi_vip", REG_CLK_EN_2, 25, 0), + CV1800B_GATE(CLK_SC_V2_VIP, "clk_sc_v2_vip", "clk_axi_vip", REG_CLK_EN_2, 26, 0), + CV1800B_GATE(CLK_SC_V3_VIP, "clk_sc_v3_vip", "clk_axi_vip", REG_CLK_EN_2, 27, 0), + CV1800B_GATE(CLK_DWA_VIP, "clk_dwa_vip", "clk_axi_vip", REG_CLK_EN_2, 28, 0), + CV1800B_GATE(CLK_BT_VIP, "clk_bt_vip", "clk_axi_vip", REG_CLK_EN_2, 29, 0), + CV1800B_GATE(CLK_DISP_VIP, "clk_disp_vip", "clk_axi_vip", REG_CLK_EN_2, 30, 0), + CV1800B_GATE(CLK_DSI_MAC_VIP, "clk_dsi_mac_vip", "clk_axi_vip", REG_CLK_EN_2, 31, 0), + CV1800B_GATE(CLK_LVDS0_VIP, "clk_lvds0_vip", "clk_axi_vip", REG_CLK_EN_3, 0, 0), + CV1800B_GATE(CLK_LVDS1_VIP, "clk_lvds1_vip", "clk_axi_vip", REG_CLK_EN_3, 1, 0), + CV1800B_GATE(CLK_CSI0_RX_VIP, "clk_csi0_rx_vip", "clk_axi_vip", REG_CLK_EN_3, 2, 0), + CV1800B_GATE(CLK_CSI1_RX_VIP, "clk_csi1_rx_vip", "clk_axi_vip", REG_CLK_EN_3, 3, 0), + CV1800B_GATE(CLK_PAD_VI_VIP, "clk_pad_vi_vip", "clk_axi_vip", REG_CLK_EN_3, 4, 0), + CV1800B_GATE(CLK_PAD_VI1_VIP, "clk_pad_vi1_vip", "clk_axi_vip", REG_CLK_EN_3, 30, 0), + CV1800B_GATE(CLK_PAD_VI2_VIP, "clk_pad_vi2_vip", "clk_axi_vip", REG_CLK_EN_4, 7, 0), + CV1800B_GATE(CLK_CSI_BE_VIP, "clk_csi_be_vip", "clk_axi_vip", REG_CLK_EN_4, 8, 0), + CV1800B_GATE(CLK_VIP_IP0, "clk_vip_ip0", "clk_axi_vip", REG_CLK_EN_4, 9, 0), + CV1800B_GATE(CLK_VIP_IP1, "clk_vip_ip1", "clk_axi_vip", REG_CLK_EN_4, 10, 0), + CV1800B_GATE(CLK_VIP_IP2, "clk_vip_ip2", "clk_axi_vip", REG_CLK_EN_4, 11, 0), + CV1800B_GATE(CLK_VIP_IP3, "clk_vip_ip3", "clk_axi_vip", REG_CLK_EN_4, 12, 0), + CV1800B_GATE(CLK_IVE_VIP, "clk_ive_vip", "clk_axi_vip", REG_CLK_EN_4, 17, 0), + CV1800B_GATE(CLK_RAW_VIP, "clk_raw_vip", "clk_axi_vip", REG_CLK_EN_4, 18, 0), + CV1800B_GATE(CLK_OSDC_VIP, "clk_osdc_vip", "clk_axi_vip", REG_CLK_EN_4, 19, 0), + CV1800B_GATE(CLK_CSI_MAC2_VIP, "clk_csi_mac2_vip", "clk_axi_vip", REG_CLK_EN_4, 20, 0), + CV1800B_GATE(CLK_CAM0_VIP, "clk_cam0_vip", "clk_axi_vip", REG_CLK_EN_4, 21, 0), + CV1800B_GATE(CLK_TIMER0, "clk_timer0", "clk_xtal_misc", REG_CLK_EN_3, 9, CLK_IS_CRITICAL), + CV1800B_GATE(CLK_TIMER1, "clk_timer1", "clk_xtal_misc", REG_CLK_EN_3, 10, CLK_IS_CRITICAL), + CV1800B_GATE(CLK_TIMER2, "clk_timer2", "clk_xtal_misc", REG_CLK_EN_3, 11, CLK_IS_CRITICAL), + CV1800B_GATE(CLK_TIMER3, "clk_timer3", "clk_xtal_misc", REG_CLK_EN_3, 12, CLK_IS_CRITICAL), + CV1800B_GATE(CLK_TIMER4, "clk_timer4", "clk_xtal_misc", REG_CLK_EN_3, 13, CLK_IS_CRITICAL), + CV1800B_GATE(CLK_TIMER5, "clk_timer5", "clk_xtal_misc", REG_CLK_EN_3, 14, CLK_IS_CRITICAL), + CV1800B_GATE(CLK_TIMER6, "clk_timer6", "clk_xtal_misc", REG_CLK_EN_3, 15, CLK_IS_CRITICAL), + CV1800B_GATE(CLK_TIMER7, "clk_timer7", "clk_xtal_misc", REG_CLK_EN_3, 16, CLK_IS_CRITICAL), +}; + +struct cv1800b_clk_div cv1800b_div_info[] = { + CV1800B_DIV(CLK_1M, "clk_1m", "osc", REG_CLK_EN_3, 5, + REG_DIV_CLK_1M, 16, 6, 25, CLK_IS_CRITICAL), + CV1800B_DIV(CLK_EMMC_100K, "clk_emmc_100k", "clk_1m", REG_CLK_EN_0, 17, + REG_DIV_CLK_EMMC_100K, 16, 8, 10, 0), + CV1800B_DIV(CLK_SD0_100K, "clk_sd0_100k", "clk_1m", REG_CLK_EN_0, 20, + REG_DIV_CLK_SD0_100K, 16, 8, 10, 0), + CV1800B_DIV(CLK_SD1_100K, "clk_sd1_100k", "clk_1m", REG_CLK_EN_0, 23, + REG_DIV_CLK_SD1_100K, 16, 8, 10, 0), + CV1800B_DIV(CLK_GPIO_DB, "clk_gpio_db", "clk_1m", REG_CLK_EN_0, 31, + REG_DIV_CLK_GPIO_DB, 16, 16, 10, CLK_IS_CRITICAL) +}; + +struct cv1800b_clk_bypass_div cv1800b_bypass_div_info[] = { + CV1800B_BYPASS_DIV(CLK_AP_DEBUG, "clk_ap_debug", "clk_fpll", REG_CLK_EN_4, 5, + REG_DIV_CLK_AP_DEBUG, 16, 4, 5, REG_CLK_BYP_1, 4, CLK_IS_CRITICAL), + CV1800B_BYPASS_DIV(CLK_SRC_RTC_SYS_0, "clk_src_rtc_sys_0", "clk_fpll", REG_CLK_EN_4, 6, + REG_DIV_CLK_RTCSYS_SRC_0, 16, 4, 5, REG_CLK_BYP_1, 5, CLK_IS_CRITICAL), + CV1800B_BYPASS_DIV(CLK_CPU_GIC, "clk_cpu_gic", "clk_fpll", REG_CLK_EN_0, 2, + REG_DIV_CLK_CPU_GIC, 16, 4, 5, REG_CLK_BYP_0, 2, CLK_IS_CRITICAL), + CV1800B_BYPASS_DIV(CLK_ETH0_500M, "clk_eth0_500m", "clk_fpll", REG_CLK_EN_0, 25, + REG_DIV_CLK_GPIO_DB, 16, 4, 3, REG_CLK_BYP_0, 9, 0), + CV1800B_BYPASS_DIV(CLK_ETH1_500M, "clk_eth1_500m", "clk_fpll", REG_CLK_EN_0, 27, + REG_DIV_CLK_GPIO_DB, 16, 4, 3, REG_CLK_BYP_0, 10, 0), + CV1800B_BYPASS_DIV(CLK_AXI6, "clk_axi6", "clk_fpll", REG_CLK_EN_2, 2, REG_DIV_CLK_AXI6, 16, + 4, 15, REG_CLK_BYP_0, 20, CLK_IS_CRITICAL), + CV1800B_BYPASS_DIV(CLK_SPI, "clk_spi", "clk_fpll", REG_CLK_EN_3, 6, REG_DIV_CLK_SPI, 16, 6, + 8, REG_CLK_BYP_0, 30, 0), + CV1800B_BYPASS_DIV(CLK_DISP_SRC_VIP, "clk_disp_src_vip", "clk_disppll", REG_CLK_EN_2, 7, + REG_DIV_CLK_DISP_SRC_VIP, 16, 4, 8, REG_CLK_BYP_0, 25, 0), + CV1800B_BYPASS_DIV(CLK_CPU_AXI0, "clk_cpu_axi0", "clk_axi4", REG_CLK_EN_0, 1, + REG_DIV_CLK_CPU_AXI0, 16, 4, 3, REG_CLK_BYP_0, 1, CLK_IS_CRITICAL), + CV1800B_BYPASS_DIV(CLK_DSI_ESC, "clk_dsi_esc", "clk_axi6", REG_CLK_EN_2, 3, + REG_DIV_CLK_DSI_ESC, 16, 4, 5, REG_CLK_BYP_0, 21, 0), + CV1800B_BYPASS_DIV(CLK_I2C, "clk_i2c", "clk_axi6", REG_CLK_EN_3, 7, REG_DIV_CLK_I2C, 16, 4, + 1, REG_CLK_BYP_0, 31, 0), +}; + +struct cv1800b_clk_fixed_div cv1800b_fixed_div_info[] = { + CV1800B_FIXED_DIV(CLK_CAM0PLL_D2, "clk_cam0pll_d2", "clk_cam0pll", + REG_CAM0PLL_CLK_CSR, 1, 2, + CLK_SET_RATE_PARENT | CLK_IGNORE_UNUSED), + CV1800B_FIXED_DIV(CLK_CAM0PLL_D3, "clk_cam0pll_d3", "clk_cam0pll", + REG_CAM0PLL_CLK_CSR, 2, 3, + CLK_SET_RATE_PARENT | CLK_IGNORE_UNUSED), + CV1800B_FIXED_DIV(CLK_MIPIMPLL_D3, "clk_mipimpll_d3", "clk_mipimpll", + REG_MIPIMPLL_CLK_CSR, 2, 3, + CLK_SET_RATE_PARENT | CLK_IGNORE_UNUSED), + CV1800B_FIXED_DIV(CLK_USB_33K, "clk_usb_33k", "clk_1m", + REG_CLK_EN_1, 31, 3, + 0), +}; + +struct cv1800b_clk_bypass_fixed_div cv1800b_bypass_fixed_div_info[] = { + CV1800B_BYPASS_FIXED_DIV(CLK_USB_125M, "clk_usb_125m", "clk_fpll", + REG_CLK_EN_1, 30, 12, + REG_CLK_BYP_0, 17, + CLK_SET_RATE_PARENT), + CV1800B_BYPASS_FIXED_DIV(CLK_USB_12M, "clk_usb_12m", "clk_fpll", + REG_CLK_EN_2, 0, 125, + REG_CLK_BYP_0, 18, + CLK_SET_RATE_PARENT), + CV1800B_BYPASS_FIXED_DIV(CLK_VC_SRC1, "clk_vc_src1", "clk_fpll", + REG_CLK_EN_3, 28, 2, + REG_CLK_BYP_1, 0, + CLK_SET_RATE_PARENT), + CV1800B_BYPASS_FIXED_DIV(CLK_VC_SRC2, "clk_vc_src2", "clk_fpll", + REG_CLK_EN_4, 3, 3, + REG_CLK_BYP_1, 3, + CLK_SET_RATE_PARENT), +}; + +struct cv1800b_clk_mux cv1800b_mux_info[] = { + CV1800B_MUX(CLK_CAM0, "clk_cam0", clk_cam_parents, + REG_CLK_EN_2, 16, + REG_CLK_CAM0_SRC_DIV, 16, 6, 0, + REG_CLK_CAM0_SRC_DIV, 8, 2, + CLK_IGNORE_UNUSED), + CV1800B_MUX(CLK_CAM1, "clk_cam1", clk_cam_parents, + REG_CLK_EN_2, 17, + REG_CLK_CAM1_SRC_DIV, 16, 6, 0, + REG_CLK_CAM1_SRC_DIV, 8, 2, + CLK_IGNORE_UNUSED), +}; + +struct cv1800b_clk_bypass_mux cv1800b_bypass_mux_info[] = { + CV1800B_BYPASS_MUX(CLK_TPU, "clk_tpu", clk_tpu_parents, + REG_CLK_EN_0, 4, + REG_DIV_CLK_TPU, 16, 4, 3, + REG_DIV_CLK_TPU, 8, 2, + REG_CLK_BYP_0, 3, + 0), + CV1800B_BYPASS_MUX(CLK_EMMC, "clk_emmc", clk_axi4_parents, + REG_CLK_EN_0, 16, + REG_DIV_CLK_EMMC, 16, 5, 15, + REG_DIV_CLK_EMMC, 8, 2, + REG_CLK_BYP_0, 5, + 0), + CV1800B_BYPASS_MUX(CLK_SD0, "clk_sd0", clk_axi4_parents, + REG_CLK_EN_0, 19, + REG_DIV_CLK_SD0, 16, 5, 15, + REG_DIV_CLK_SD0, 8, 2, + REG_CLK_BYP_0, 6, + 0), + CV1800B_BYPASS_MUX(CLK_SD1, "clk_sd1", clk_axi4_parents, + REG_CLK_EN_0, 22, + REG_DIV_CLK_SD1, 16, 5, 15, + REG_DIV_CLK_SD1, 8, 2, + REG_CLK_BYP_0, 7, + 0), + CV1800B_BYPASS_MUX(CLK_SPI_NAND, "clk_spi_nand", clk_axi4_parents, + REG_CLK_EN_0, 24, + REG_DIV_CLK_SPI_NAND, 16, 5, 8, + REG_DIV_CLK_SPI_NAND, 8, 2, + REG_CLK_BYP_0, 8, + 0), + CV1800B_BYPASS_MUX(CLK_AXI4, "clk_axi4", clk_axi4_parents, + REG_CLK_EN_2, 1, + REG_DIV_CLK_AXI4, 16, 4, 5, + REG_DIV_CLK_AXI4, 8, 2, + REG_CLK_BYP_0, 19, + CLK_IS_CRITICAL), + CV1800B_BYPASS_MUX(CLK_PWM_SRC, "clk_pwm_src", clk_axi4_parents, + REG_CLK_EN_4, 4, + REG_DIV_CLK_PWM_SRC_0, 16, 6, 10, + REG_DIV_CLK_PWM_SRC_0, 8, 2, + REG_CLK_BYP_0, 15, + CLK_IS_CRITICAL), + CV1800B_BYPASS_MUX(CLK_AUDSRC, "clk_audsrc", clk_aud_parents, + REG_CLK_EN_4, 1, + REG_DIV_CLK_AUDSRC, 16, 8, 18, + REG_DIV_CLK_AUDSRC, 8, 2, + REG_CLK_BYP_1, 2, + 0), + CV1800B_BYPASS_MUX(CLK_SDMA_AUD0, "clk_sdma_aud0", clk_aud_parents, + REG_CLK_EN_1, 2, + REG_DIV_CLK_SDMA_AUD0, 16, 8, 18, + REG_DIV_CLK_SDMA_AUD0, 8, 2, + REG_CLK_BYP_0, 11, + 0), + CV1800B_BYPASS_MUX(CLK_SDMA_AUD1, "clk_sdma_aud1", clk_aud_parents, + REG_CLK_EN_1, 3, + REG_DIV_CLK_SDMA_AUD1, 16, 8, 18, + REG_DIV_CLK_SDMA_AUD1, 8, 2, + REG_CLK_BYP_0, 12, + 0), + CV1800B_BYPASS_MUX(CLK_SDMA_AUD2, "clk_sdma_aud2", clk_aud_parents, + REG_CLK_EN_1, 3, + REG_DIV_CLK_SDMA_AUD2, 16, 8, 18, + REG_DIV_CLK_SDMA_AUD2, 8, 2, + REG_CLK_BYP_0, 13, + 0), + CV1800B_BYPASS_MUX(CLK_SDMA_AUD3, "clk_sdma_aud3", clk_aud_parents, + REG_CLK_EN_1, 3, + REG_DIV_CLK_SDMA_AUD3, 16, 8, 18, + REG_DIV_CLK_SDMA_AUD3, 8, 2, + REG_CLK_BYP_0, 14, + 0), + CV1800B_BYPASS_MUX(CLK_CAM0_200, "clk_cam0_200", clk_cam0_200_parents, + REG_CLK_EN_1, 13, + REG_DIV_CLK_CAM0_200, 16, 4, 1, + REG_DIV_CLK_CAM0_200, 8, 2, + REG_CLK_BYP_0, 16, + CLK_IS_CRITICAL), + CV1800B_BYPASS_MUX(CLK_AXI_VIP, "clk_axi_vip", clk_vip_sys_parents, + REG_CLK_EN_2, 4, + REG_DIV_CLK_AXI_VIP, 16, 4, 3, + REG_DIV_CLK_AXI_VIP, 8, 2, + REG_CLK_BYP_0, 22, + 0), + CV1800B_BYPASS_MUX(CLK_SRC_VIP_SYS_0, "clk_src_vip_sys_0", clk_vip_sys_parents, + REG_CLK_EN_2, 5, + REG_DIV_CLK_SRC_VIP_SYS_0, 16, 4, 6, + REG_DIV_CLK_SRC_VIP_SYS_0, 8, 2, + REG_CLK_BYP_0, 23, + 0), + CV1800B_BYPASS_MUX(CLK_SRC_VIP_SYS_1, "clk_src_vip_sys_1", clk_vip_sys_parents, + REG_CLK_EN_2, 6, + REG_DIV_CLK_SRC_VIP_SYS_1, 16, 4, 6, + REG_DIV_CLK_SRC_VIP_SYS_1, 8, 2, + REG_CLK_BYP_0, 24, + 0), + CV1800B_BYPASS_MUX(CLK_SRC_VIP_SYS_2, "clk_src_vip_sys_2", clk_vip_sys_parents, + REG_CLK_EN_3, 29, + REG_DIV_CLK_SRC_VIP_SYS_2, 16, 4, 2, + REG_DIV_CLK_SRC_VIP_SYS_2, 8, 2, + REG_CLK_BYP_1, 1, + 0), + CV1800B_BYPASS_MUX(CLK_SRC_VIP_SYS_3, "clk_src_vip_sys_3", clk_vip_sys_parents, + REG_CLK_EN_4, 15, + REG_DIV_CLK_SRC_VIP_SYS_3, 16, 4, 2, + REG_DIV_CLK_SRC_VIP_SYS_3, 8, 2, + REG_CLK_BYP_1, 8, + 0), + CV1800B_BYPASS_MUX(CLK_SRC_VIP_SYS_4, "clk_src_vip_sys_4", clk_vip_sys_parents, + REG_CLK_EN_4, 16, + REG_DIV_CLK_SRC_VIP_SYS_4, 16, 4, 3, + REG_DIV_CLK_SRC_VIP_SYS_4, 8, 2, + REG_CLK_BYP_1, 9, + 0), + CV1800B_BYPASS_MUX(CLK_AXI_VIDEO_CODEC, "clk_axi_video_codec", clk_axi_video_codec_parents, + REG_CLK_EN_2, 8, + REG_DIV_CLK_AXI_VIDEO_CODEC, 16, 4, 2, + REG_DIV_CLK_AXI_VIDEO_CODEC, 8, 2, + REG_CLK_BYP_0, 26, + 0), + CV1800B_BYPASS_MUX(CLK_VC_SRC0, "clk_vc_src0", clk_vc_src0_parents, + REG_CLK_EN_2, 9, + REG_DIV_CLK_VC_SRC0, 16, 4, 2, + REG_DIV_CLK_VC_SRC0, 8, 2, + REG_CLK_BYP_0, 27, + 0), +}; + +struct cv1800b_clk_mmux cv1800b_mmux_info[] = { + CV1800B_MMUX(CLK_C906_0, "clk_c906_0", clk_c906_0_parents, + REG_CLK_EN_4, 13, + REG_DIV_CLK_C906_0_0, 16, 4, 1, + REG_DIV_CLK_C906_0_1, 16, 4, 2, + REG_DIV_CLK_C906_0_0, 8, 2, + REG_DIV_CLK_C906_0_1, 8, 2, + REG_CLK_BYP_1, 6, + REG_CLK_SEL_0, 23, + CLK_IS_CRITICAL | CLK_GET_RATE_NOCACHE), + CV1800B_MMUX(CLK_C906_1, "clk_c906_1", clk_c906_1_parents, + REG_CLK_EN_4, 14, + REG_DIV_CLK_C906_1_0, 16, 4, 2, + REG_DIV_CLK_C906_1_1, 16, 4, 3, + REG_DIV_CLK_C906_1_0, 8, 2, + REG_DIV_CLK_C906_1_1, 8, 2, + REG_CLK_BYP_1, 7, + REG_CLK_SEL_0, 24, + CLK_IS_CRITICAL | CLK_GET_RATE_NOCACHE), + CV1800B_MMUX(CLK_A53, "clk_a53", clk_a53_parents, + REG_CLK_EN_0, 0, + REG_DIV_CLK_A53_0, 16, 4, 1, + REG_DIV_CLK_A53_1, 16, 4, 2, + REG_DIV_CLK_A53_0, 8, 2, + REG_DIV_CLK_A53_1, 8, 2, + REG_CLK_BYP_0, 0, + REG_CLK_SEL_0, 0, + CLK_IS_CRITICAL | CLK_GET_RATE_NOCACHE), +}; + +static struct cv1800b_clk_audio cv1800b_audio_info[] = { + CV1800B_AUDIO(CLK_A24M, "clk_a24m", "clk_mipimpll", + REG_APLL_FRAC_DIV_CTRL, 0, + REG_APLL_FRAC_DIV_CTRL, 3, + REG_APLL_FRAC_DIV_CTRL, 1, + REG_APLL_FRAC_DIV_CTRL, 2, + REG_APLL_FRAC_DIV_M, 0, 22, + REG_APLL_FRAC_DIV_N, 0, 22, + 0), +}; + +static struct cv1800b_clk_ipll cv1800b_ipll_info[] = { + CV1800B_IPLL(CLK_FPLL, "clk_fpll", "osc", REG_FPLL_CSR, + REG_PLL_G6_CTRL, 8, + REG_PLL_G6_STATUS, 2, + CLK_IS_CRITICAL), + CV1800B_IPLL(CLK_MIPIMPLL, "clk_mipimpll", "osc", REG_MIPIMPLL_CSR, + REG_PLL_G2_CTRL, 0, + REG_PLL_G2_STATUS, 0, + CLK_IS_CRITICAL), +}; + +static struct cv1800b_clk_fpll cv1800b_fpll_info[] = { + CV1800B_FPLL(CLK_MPLL, "clk_mpll", "osc", REG_MPLL_CSR, + REG_PLL_G6_CTRL, 0, + REG_PLL_G6_STATUS, 0, + REG_PLL_G6_SSC_SYN_CTRL, 2, + REG_PLL_G6_SSC_SYN_CTRL, 0, + REG_MPLL_SSC_SYN_CTRL, REG_MPLL_SSC_SYN_SET, + CLK_IS_CRITICAL), + CV1800B_FPLL(CLK_TPLL, "clk_tpll", "osc", REG_TPLL_CSR, + REG_PLL_G6_CTRL, 4, + REG_PLL_G6_STATUS, 1, + REG_PLL_G6_SSC_SYN_CTRL, 3, + REG_PLL_G6_SSC_SYN_CTRL, 0, + REG_TPLL_SSC_SYN_CTRL, REG_TPLL_SSC_SYN_SET, + CLK_IS_CRITICAL), + CV1800B_FPLL(CLK_A0PLL, "clk_a0pll", "clk_mipimpll", REG_A0PLL_CSR, + REG_PLL_G2_CTRL, 4, + REG_PLL_G2_STATUS, 1, + REG_PLL_G2_SSC_SYN_CTRL, 2, + REG_PLL_G2_SSC_SYN_CTRL, 0, + REG_A0PLL_SSC_SYN_CTRL, REG_A0PLL_SSC_SYN_SET, + CLK_IS_CRITICAL), + CV1800B_FPLL(CLK_DISPPLL, "clk_disppll", "clk_mipimpll", REG_DISPPLL_CSR, + REG_PLL_G2_CTRL, 8, + REG_PLL_G2_STATUS, 2, + REG_PLL_G2_SSC_SYN_CTRL, 3, + REG_PLL_G2_SSC_SYN_CTRL, 0, + REG_DISPPLL_SSC_SYN_CTRL, REG_DISPPLL_SSC_SYN_SET, + CLK_IS_CRITICAL), + CV1800B_FPLL(CLK_CAM0PLL, "clk_cam0pll", "clk_mipimpll", REG_CAM0PLL_CSR, + REG_PLL_G2_CTRL, 12, + REG_PLL_G2_STATUS, 3, + REG_PLL_G2_SSC_SYN_CTRL, 4, + REG_PLL_G2_SSC_SYN_CTRL, 0, + REG_CAM0PLL_SSC_SYN_CTRL, REG_CAM0PLL_SSC_SYN_SET, + CLK_IGNORE_UNUSED), + CV1800B_FPLL(CLK_CAM1PLL, "clk_cam1pll", "clk_mipimpll", REG_CAM1PLL_CSR, + REG_PLL_G2_CTRL, 16, + REG_PLL_G2_STATUS, 4, + REG_PLL_G2_SSC_SYN_CTRL, 5, + REG_PLL_G2_SSC_SYN_CTRL, 0, + REG_CAM1PLL_SSC_SYN_CTRL, REG_CAM1PLL_SSC_SYN_SET, + CLK_IS_CRITICAL), +}; + +static int cv1800b_register_clk(struct udevice *dev) +{ + struct clk osc; + ulong osc_rate; + void *base = devfdt_get_addr_ptr(dev); + int i, ret; + + ret = clk_get_by_index(dev, 0, &osc); + if (ret) { + pr_err("Failed to get clock\n"); + return ret; + } + + osc_rate = clk_get_rate(&osc); + clk_dm(CV1800B_CLK_OSC, clk_register_fixed_rate(NULL, "osc", osc_rate)); + clk_dm(CV1800B_CLK_BYPASS, clk_register_fixed_rate(NULL, "bypass", osc_rate)); + + for (i = 0; i < ARRAY_SIZE(cv1800b_ipll_info); i++) { + struct cv1800b_clk_ipll *ipll = &cv1800b_ipll_info[i]; + + ipll->base = base; + ret = clk_register(&ipll->clk, "cv1800b_clk_ipll", ipll->name, + ipll->parent_name); + if (ret) { + pr_err("Failed to register ipll %s\n", ipll->name); + return ret; + } + } + + for (i = 0; i < ARRAY_SIZE(cv1800b_fpll_info); i++) { + struct cv1800b_clk_fpll *fpll = &cv1800b_fpll_info[i]; + + fpll->ipll.base = base; + ret = clk_register(&fpll->ipll.clk, "cv1800b_clk_fpll", + fpll->ipll.name, fpll->ipll.parent_name); + if (ret) { + pr_err("Failed to register fpll %s\n", fpll->ipll.name); + return ret; + } + } + + for (i = 0; i < ARRAY_SIZE(cv1800b_div_info); i++) { + struct cv1800b_clk_div *div = &cv1800b_div_info[i]; + + div->base = base; + ret = clk_register(&div->clk, "cv1800b_clk_div", div->name, + div->parent_name); + if (ret) { + pr_err("Failed to register div %s\n", div->name); + return ret; + } + } + + for (i = 0; i < ARRAY_SIZE(cv1800b_fixed_div_info); i++) { + struct cv1800b_clk_fixed_div *fixed_div = + &cv1800b_fixed_div_info[i]; + + fixed_div->base = base; + ret = clk_register(&fixed_div->clk, "cv1800b_clk_fixed_div", + fixed_div->name, fixed_div->parent_name); + if (ret) { + pr_err("Failed to register fixed div %s\n", + fixed_div->name); + return ret; + } + } + + for (i = 0; i < ARRAY_SIZE(cv1800b_bypass_fixed_div_info); i++) { + struct cv1800b_clk_bypass_fixed_div *bypass_fixed_div = + &cv1800b_bypass_fixed_div_info[i]; + + bypass_fixed_div->div.base = base; + ret = clk_register(&bypass_fixed_div->div.clk, + "cv1800b_clk_bypass_fixed_div", + bypass_fixed_div->div.name, + bypass_fixed_div->div.parent_name); + if (ret) { + pr_err("Failed to register bypass fixed div %s\n", + bypass_fixed_div->div.name); + return ret; + } + } + + for (i = 0; i < ARRAY_SIZE(cv1800b_mux_info); i++) { + struct cv1800b_clk_mux *mux = &cv1800b_mux_info[i]; + int parent; + + mux->base = base; + parent = cv1800b_clk_getfield(base, &mux->mux); + ret = clk_register(&mux->clk, "cv1800b_clk_mux", mux->name, + mux->parent_names[parent]); + if (ret) { + pr_err("Failed to register mux %s\n", mux->name); + return ret; + } + } + + for (i = 0; i < ARRAY_SIZE(cv1800b_mmux_info); i++) { + struct cv1800b_clk_mmux *mmux = &cv1800b_mmux_info[i]; + int clk_sel, parent, idx; + + mmux->base = base; + clk_sel = cv1800b_clk_getbit(base, &mmux->clk_sel) ? 0 : 1; + parent = cv1800b_clk_getfield(base, &mmux->mux[clk_sel]); + for (idx = 0; idx < mmux->num_parents; idx++) { + if (clk_sel == mmux->parent_infos[idx].clk_sel && + parent == mmux->parent_infos[idx].index) + break; + } + ret = clk_register(&mmux->clk, "cv1800b_clk_mmux", mmux->name, + mmux->parent_infos[idx].name); + if (ret) { + pr_err("Failed to register mmux %s\n", mmux->name); + return ret; + } + } + + for (i = 0; i < ARRAY_SIZE(cv1800b_audio_info); i++) { + struct cv1800b_clk_audio *audio = &cv1800b_audio_info[i]; + + audio->base = base; + ret = clk_register(&audio->clk, "cv1800b_clk_audio", + audio->name, audio->parent_name); + if (ret) { + pr_err("Failed to register audio %s\n", audio->name); + return ret; + } + } + + for (i = 0; i < ARRAY_SIZE(cv1800b_bypass_mux_info); i++) { + struct cv1800b_clk_bypass_mux *bypass_mux = + &cv1800b_bypass_mux_info[i]; + int parent; + + bypass_mux->mux.base = base; + parent = cv1800b_clk_getfield(base, &bypass_mux->mux.mux); + ret = clk_register(&bypass_mux->mux.clk, + "cv1800b_clk_bypass_mux", + bypass_mux->mux.name, + bypass_mux->mux.parent_names[parent]); + if (ret) { + pr_err("Failed to register bypass mux %s\n", + bypass_mux->mux.name); + return ret; + } + } + + for (i = 0; i < ARRAY_SIZE(cv1800b_bypass_div_info); i++) { + struct cv1800b_clk_bypass_div *bypass_div = + &cv1800b_bypass_div_info[i]; + + bypass_div->div.base = base; + ret = clk_register(&bypass_div->div.clk, + "cv1800b_clk_bypass_div", + bypass_div->div.name, + bypass_div->div.parent_name); + if (ret) { + pr_err("Failed to register bypass div %s\n", + bypass_div->div.name); + return ret; + } + } + + for (i = 0; i < ARRAY_SIZE(cv1800b_gate_info); i++) { + struct cv1800b_clk_gate *gate = &cv1800b_gate_info[i]; + + gate->base = base; + ret = clk_register(&gate->clk, "cv1800b_clk_gate", gate->name, + gate->parent_name); + if (ret) { + pr_err("Failed to register gate %s\n", gate->name); + return ret; + } + } + return 0; +} + +static int cv1800b_clk_probe(struct udevice *dev) +{ + return cv1800b_register_clk(dev); +} + +static int cv1800b_clk_enable(struct clk *clk) +{ + struct clk *c; + int err = clk_get_by_id(CV1800B_CLK_ID_TRANSFORM(clk->id), &c); + + if (err) + return err; + return clk_enable(c); +} + +static int cv1800b_clk_disable(struct clk *clk) +{ + struct clk *c; + int err = clk_get_by_id(CV1800B_CLK_ID_TRANSFORM(clk->id), &c); + + if (err) + return err; + return clk_disable(c); +} + +static ulong cv1800b_clk_get_rate(struct clk *clk) +{ + struct clk *c; + int err = clk_get_by_id(CV1800B_CLK_ID_TRANSFORM(clk->id), &c); + + if (err) + return err; + return clk_get_rate(c); +} + +static ulong cv1800b_clk_set_rate(struct clk *clk, ulong rate) +{ + struct clk *c; + int err = clk_get_by_id(CV1800B_CLK_ID_TRANSFORM(clk->id), &c); + + if (err) + return err; + return clk_set_rate(c, rate); +} + +static int cv1800b_clk_set_parent(struct clk *clk, struct clk *parent) +{ + struct clk *c, *p; + int err = clk_get_by_id(CV1800B_CLK_ID_TRANSFORM(clk->id), &c); + + if (err) + return err; + err = clk_get_by_id(CV1800B_CLK_ID_TRANSFORM(parent->id), &p); + if (err) + return err; + return clk_set_parent(c, p); +} + +const struct clk_ops cv1800b_clk_ops = { + .enable = cv1800b_clk_enable, + .disable = cv1800b_clk_disable, + .get_rate = cv1800b_clk_get_rate, + .set_rate = cv1800b_clk_set_rate, + .set_parent = cv1800b_clk_set_parent, +}; + +static const struct udevice_id cv1800b_clk_of_match[] = { + { .compatible = "sophgo,cv1800-clk" }, + { }, +}; + +U_BOOT_DRIVER(sophgo_clk) = { + .name = "cv1800b_clk", + .id = UCLASS_CLK, + .of_match = cv1800b_clk_of_match, + .probe = cv1800b_clk_probe, + .ops = &cv1800b_clk_ops, + .flags = DM_FLAG_PRE_RELOC, +}; diff --git a/drivers/clk/sophgo/clk-cv1800b.h b/drivers/clk/sophgo/clk-cv1800b.h new file mode 100644 index 0000000000..1e7107b5d0 --- /dev/null +++ b/drivers/clk/sophgo/clk-cv1800b.h @@ -0,0 +1,123 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Copyright (C) 2023 Inochi Amaoto inochiama@outlook.com + */ + +#ifndef _CLK_SOPHGO_CV1800_H_ +#define _CLK_SOPHGO_CV1800_H_ + +#include <dt-bindings/clock/sophgo,cv1800.h> + +#define CV1800_CLK_MAX (CLK_XTAL_AP + 1) +#define CV1810_CLK_MAX (CLK_DISP_SRC_VIP + 1) + +#define REG_PLL_G2_CTRL 0x800 +#define REG_PLL_G2_STATUS 0x804 +#define REG_MIPIMPLL_CSR 0x808 +#define REG_A0PLL_CSR 0x80C +#define REG_DISPPLL_CSR 0x810 +#define REG_CAM0PLL_CSR 0x814 +#define REG_CAM1PLL_CSR 0x818 +#define REG_PLL_G2_SSC_SYN_CTRL 0x840 +#define REG_A0PLL_SSC_SYN_CTRL 0x850 +#define REG_A0PLL_SSC_SYN_SET 0x854 +#define REG_A0PLL_SSC_SYN_SPAN 0x858 +#define REG_A0PLL_SSC_SYN_STEP 0x85C +#define REG_DISPPLL_SSC_SYN_CTRL 0x860 +#define REG_DISPPLL_SSC_SYN_SET 0x864 +#define REG_DISPPLL_SSC_SYN_SPAN 0x868 +#define REG_DISPPLL_SSC_SYN_STEP 0x86C +#define REG_CAM0PLL_SSC_SYN_CTRL 0x870 +#define REG_CAM0PLL_SSC_SYN_SET 0x874 +#define REG_CAM0PLL_SSC_SYN_SPAN 0x878 +#define REG_CAM0PLL_SSC_SYN_STEP 0x87C +#define REG_CAM1PLL_SSC_SYN_CTRL 0x880 +#define REG_CAM1PLL_SSC_SYN_SET 0x884 +#define REG_CAM1PLL_SSC_SYN_SPAN 0x888 +#define REG_CAM1PLL_SSC_SYN_STEP 0x88C +#define REG_APLL_FRAC_DIV_CTRL 0x890 +#define REG_APLL_FRAC_DIV_M 0x894 +#define REG_APLL_FRAC_DIV_N 0x898 +#define REG_MIPIMPLL_CLK_CSR 0x8A0 +#define REG_A0PLL_CLK_CSR 0x8A4 +#define REG_DISPPLL_CLK_CSR 0x8A8 +#define REG_CAM0PLL_CLK_CSR 0x8AC +#define REG_CAM1PLL_CLK_CSR 0x8B0 +#define REG_CLK_CAM0_SRC_DIV 0x8C0 +#define REG_CLK_CAM1_SRC_DIV 0x8C4 + +/* top_pll_g6 */ +#define REG_PLL_G6_CTRL 0x900 +#define REG_PLL_G6_STATUS 0x904 +#define REG_MPLL_CSR 0x908 +#define REG_TPLL_CSR 0x90C +#define REG_FPLL_CSR 0x910 +#define REG_PLL_G6_SSC_SYN_CTRL 0x940 +#define REG_DPLL_SSC_SYN_CTRL 0x950 +#define REG_DPLL_SSC_SYN_SET 0x954 +#define REG_DPLL_SSC_SYN_SPAN 0x958 +#define REG_DPLL_SSC_SYN_STEP 0x95C +#define REG_MPLL_SSC_SYN_CTRL 0x960 +#define REG_MPLL_SSC_SYN_SET 0x964 +#define REG_MPLL_SSC_SYN_SPAN 0x968 +#define REG_MPLL_SSC_SYN_STEP 0x96C +#define REG_TPLL_SSC_SYN_CTRL 0x970 +#define REG_TPLL_SSC_SYN_SET 0x974 +#define REG_TPLL_SSC_SYN_SPAN 0x978 +#define REG_TPLL_SSC_SYN_STEP 0x97C + +/* clkgen */ +#define REG_CLK_EN_0 0x000 +#define REG_CLK_EN_1 0x004 +#define REG_CLK_EN_2 0x008 +#define REG_CLK_EN_3 0x00C +#define REG_CLK_EN_4 0x010 +#define REG_CLK_SEL_0 0x020 +#define REG_CLK_BYP_0 0x030 +#define REG_CLK_BYP_1 0x034 + +#define REG_DIV_CLK_A53_0 0x040 +#define REG_DIV_CLK_A53_1 0x044 +#define REG_DIV_CLK_CPU_AXI0 0x048 +#define REG_DIV_CLK_CPU_GIC 0x050 +#define REG_DIV_CLK_TPU 0x054 +#define REG_DIV_CLK_EMMC 0x064 +#define REG_DIV_CLK_EMMC_100K 0x06C +#define REG_DIV_CLK_SD0 0x070 +#define REG_DIV_CLK_SD0_100K 0x078 +#define REG_DIV_CLK_SD1 0x07C +#define REG_DIV_CLK_SD1_100K 0x084 +#define REG_DIV_CLK_SPI_NAND 0x088 +#define REG_DIV_CLK_ETH0_500M 0x08C +#define REG_DIV_CLK_ETH1_500M 0x090 +#define REG_DIV_CLK_GPIO_DB 0x094 +#define REG_DIV_CLK_SDMA_AUD0 0x098 +#define REG_DIV_CLK_SDMA_AUD1 0x09C +#define REG_DIV_CLK_SDMA_AUD2 0x0A0 +#define REG_DIV_CLK_SDMA_AUD3 0x0A4 +#define REG_DIV_CLK_CAM0_200 0x0A8 +#define REG_DIV_CLK_AXI4 0x0B8 +#define REG_DIV_CLK_AXI6 0x0BC +#define REG_DIV_CLK_DSI_ESC 0x0C4 +#define REG_DIV_CLK_AXI_VIP 0x0C8 +#define REG_DIV_CLK_SRC_VIP_SYS_0 0x0D0 +#define REG_DIV_CLK_SRC_VIP_SYS_1 0x0D8 +#define REG_DIV_CLK_DISP_SRC_VIP 0x0E0 +#define REG_DIV_CLK_AXI_VIDEO_CODEC 0x0E4 +#define REG_DIV_CLK_VC_SRC0 0x0EC +#define REG_DIV_CLK_1M 0x0FC +#define REG_DIV_CLK_SPI 0x100 +#define REG_DIV_CLK_I2C 0x104 +#define REG_DIV_CLK_SRC_VIP_SYS_2 0x110 +#define REG_DIV_CLK_AUDSRC 0x118 +#define REG_DIV_CLK_PWM_SRC_0 0x120 +#define REG_DIV_CLK_AP_DEBUG 0x128 +#define REG_DIV_CLK_RTCSYS_SRC_0 0x12C +#define REG_DIV_CLK_C906_0_0 0x130 +#define REG_DIV_CLK_C906_0_1 0x134 +#define REG_DIV_CLK_C906_1_0 0x138 +#define REG_DIV_CLK_C906_1_1 0x13C +#define REG_DIV_CLK_SRC_VIP_SYS_3 0x140 +#define REG_DIV_CLK_SRC_VIP_SYS_4 0x144 + +#endif /* _CLK_SOPHGO_CV1800_H_ */ diff --git a/drivers/clk/sophgo/clk-ip.c b/drivers/clk/sophgo/clk-ip.c new file mode 100644 index 0000000000..d571fa671b --- /dev/null +++ b/drivers/clk/sophgo/clk-ip.c @@ -0,0 +1,594 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (C) 2023 Inochi Amaoto inochiama@outlook.com + */ + +#include <dm.h> +#include <div64.h> +#include <linux/clk-provider.h> +#include <linux/io.h> + +#include "clk-common.h" +#include "clk-ip.h" + +static int get_parent_index(struct clk *clk, const char *const *parent_name, + u8 num_parents) +{ + const char *name = clk_hw_get_name(clk); + int i; + + for (i = 0; i < num_parents; i++) { + if (!strcmp(name, parent_name[i])) + return i; + } + + return -1; +} + +/* GATE */ +#define to_cv1800b_clk_gate(_clk) \ + container_of(_clk, struct cv1800b_clk_gate, clk) + +static int gate_enable(struct clk *clk) +{ + struct cv1800b_clk_gate *gate = to_cv1800b_clk_gate(clk); + + return cv1800b_clk_setbit(gate->base, &gate->gate); +} + +static int gate_disable(struct clk *clk) +{ + struct cv1800b_clk_gate *gate = to_cv1800b_clk_gate(clk); + + return cv1800b_clk_clrbit(gate->base, &gate->gate); +} + +static ulong gate_get_rate(struct clk *clk) +{ + return clk_get_parent_rate(clk); +} + +const struct clk_ops cv1800b_clk_gate_ops = { + .disable = gate_disable, + .enable = gate_enable, + .get_rate = gate_get_rate, +}; + +U_BOOT_DRIVER(cv1800b_clk_gate) = { + .name = "cv1800b_clk_gate", + .id = UCLASS_CLK, + .ops = &cv1800b_clk_gate_ops, + .flags = DM_FLAG_PRE_RELOC, +}; + +/* DIV */ +#define CLK_DIV_EN_FACTOR BIT(3) + +#define to_cv1800b_clk_div(_clk) container_of(_clk, struct cv1800b_clk_div, clk) + +static int div_enable(struct clk *clk) +{ + struct cv1800b_clk_div *div = to_cv1800b_clk_div(clk); + + return cv1800b_clk_setbit(div->base, &div->gate); +} + +static int div_disable(struct clk *clk) +{ + struct cv1800b_clk_div *div = to_cv1800b_clk_div(clk); + + return cv1800b_clk_clrbit(div->base, &div->gate); +} + +static ulong div_get_rate(struct clk *clk) +{ + struct cv1800b_clk_div *div = to_cv1800b_clk_div(clk); + ulong val; + + if (div->div_init == 0 || + readl(div->base + div->div.offset) & CLK_DIV_EN_FACTOR) + val = cv1800b_clk_getfield(div->base, &div->div); + else + val = div->div_init; + + return DIV_ROUND_UP_ULL(clk_get_parent_rate(clk), val); +} + +static ulong div_set_rate(struct clk *clk, ulong rate) +{ + struct cv1800b_clk_div *div = to_cv1800b_clk_div(clk); + ulong parent_rate = clk_get_parent_rate(clk); + u32 val; + + val = DIV_ROUND_UP_ULL(parent_rate, rate); + val = min_t(u32, val, clk_div_mask(div->div.width)); + + cv1800b_clk_setfield(div->base, &div->div, val); + if (div->div_init > 0) + setbits_le32(div->base + div->div.offset, CLK_DIV_EN_FACTOR); + + return DIV_ROUND_UP_ULL(parent_rate, val); +} + +const struct clk_ops cv1800b_clk_div_ops = { + .disable = div_disable, + .enable = div_enable, + .get_rate = div_get_rate, + .set_rate = div_set_rate, +}; + +U_BOOT_DRIVER(cv1800b_clk_div) = { + .name = "cv1800b_clk_div", + .id = UCLASS_CLK, + .ops = &cv1800b_clk_div_ops, + .flags = DM_FLAG_PRE_RELOC, +}; + +#define to_cv1800b_clk_bypass_div(_clk) \ + container_of(_clk, struct cv1800b_clk_bypass_div, div.clk) + +static ulong bypass_div_get_rate(struct clk *clk) +{ + struct cv1800b_clk_bypass_div *div = to_cv1800b_clk_bypass_div(clk); + + if (cv1800b_clk_getbit(div->div.base, &div->bypass)) + return 0; + + return div_get_rate(clk); +} + +static ulong bypass_div_set_rate(struct clk *clk, ulong rate) +{ + struct cv1800b_clk_bypass_div *div = to_cv1800b_clk_bypass_div(clk); + + if (cv1800b_clk_getbit(div->div.base, &div->bypass)) + return 0; + + return div_set_rate(clk, rate); +} + +static int bypass_div_set_parent(struct clk *clk, struct clk *pclk) +{ + struct cv1800b_clk_bypass_div *div = to_cv1800b_clk_bypass_div(clk); + + if (pclk->id == CV1800B_CLK_BYPASS) { + cv1800b_clk_setbit(div->div.base, &div->bypass); + return 0; + } + + if (strcmp(clk_hw_get_name(pclk), div->div.parent_name)) + return -EINVAL; + + cv1800b_clk_clrbit(div->div.base, &div->bypass); + return 0; +} + +const struct clk_ops cv1800b_clk_bypass_div_ops = { + .disable = div_disable, + .enable = div_enable, + .get_rate = bypass_div_get_rate, + .set_rate = bypass_div_set_rate, + .set_parent = bypass_div_set_parent, +}; + +U_BOOT_DRIVER(cv1800b_clk_bypass_div) = { + .name = "cv1800b_clk_bypass_div", + .id = UCLASS_CLK, + .ops = &cv1800b_clk_bypass_div_ops, + .flags = DM_FLAG_PRE_RELOC, +}; + +/* FIXED DIV */ +#define to_cv1800b_clk_fixed_div(_clk) \ + container_of(_clk, struct cv1800b_clk_fixed_div, clk) + +static int fixed_div_enable(struct clk *clk) +{ + struct cv1800b_clk_fixed_div *div = to_cv1800b_clk_fixed_div(clk); + + return cv1800b_clk_setbit(div->base, &div->gate); +} + +static int fixed_div_disable(struct clk *clk) +{ + struct cv1800b_clk_fixed_div *div = to_cv1800b_clk_fixed_div(clk); + + return cv1800b_clk_clrbit(div->base, &div->gate); +} + +static ulong fixed_div_get_rate(struct clk *clk) +{ + struct cv1800b_clk_fixed_div *div = to_cv1800b_clk_fixed_div(clk); + + return DIV_ROUND_UP_ULL(clk_get_parent_rate(clk), div->div); +} + +const struct clk_ops cv1800b_clk_fixed_div_ops = { + .disable = fixed_div_disable, + .enable = fixed_div_enable, + .get_rate = fixed_div_get_rate, +}; + +U_BOOT_DRIVER(cv1800b_clk_fixed_div) = { + .name = "cv1800b_clk_fixed_div", + .id = UCLASS_CLK, + .ops = &cv1800b_clk_fixed_div_ops, + .flags = DM_FLAG_PRE_RELOC, +}; + +#define to_cv1800b_clk_bypass_fixed_div(_clk) \ + container_of(_clk, struct cv1800b_clk_bypass_fixed_div, div.clk) + +static ulong bypass_fixed_div_get_rate(struct clk *clk) +{ + struct cv1800b_clk_bypass_fixed_div *div = + to_cv1800b_clk_bypass_fixed_div(clk); + + if (cv1800b_clk_getbit(div->div.base, &div->bypass)) + return 0; + + return fixed_div_get_rate(clk); +} + +static int bypass_fixed_div_set_parent(struct clk *clk, struct clk *pclk) +{ + struct cv1800b_clk_bypass_fixed_div *div = + to_cv1800b_clk_bypass_fixed_div(clk); + + if (pclk->id == CV1800B_CLK_BYPASS) { + cv1800b_clk_setbit(div->div.base, &div->bypass); + return 0; + } + + if (strcmp(clk_hw_get_name(pclk), div->div.parent_name)) + return -EINVAL; + + cv1800b_clk_clrbit(div->div.base, &div->bypass); + return 0; +} + +const struct clk_ops cv1800b_clk_bypass_fixed_div_ops = { + .disable = fixed_div_disable, + .enable = fixed_div_enable, + .get_rate = bypass_fixed_div_get_rate, + .set_parent = bypass_fixed_div_set_parent, +}; + +U_BOOT_DRIVER(cv1800b_clk_bypass_fixed_div) = { + .name = "cv1800b_clk_bypass_fixed_div", + .id = UCLASS_CLK, + .ops = &cv1800b_clk_bypass_fixed_div_ops, + .flags = DM_FLAG_PRE_RELOC, +}; + +/* MUX */ +#define to_cv1800b_clk_mux(_clk) container_of(_clk, struct cv1800b_clk_mux, clk) + +static int mux_enable(struct clk *clk) +{ + struct cv1800b_clk_mux *mux = to_cv1800b_clk_mux(clk); + + return cv1800b_clk_setbit(mux->base, &mux->gate); +} + +static int mux_disable(struct clk *clk) +{ + struct cv1800b_clk_mux *mux = to_cv1800b_clk_mux(clk); + + return cv1800b_clk_clrbit(mux->base, &mux->gate); +} + +static ulong mux_get_rate(struct clk *clk) +{ + struct cv1800b_clk_mux *mux = to_cv1800b_clk_mux(clk); + ulong val; + + if (mux->div_init == 0 || + readl(mux->base + mux->div.offset) & CLK_DIV_EN_FACTOR) + val = cv1800b_clk_getfield(mux->base, &mux->div); + else + val = mux->div_init; + + return DIV_ROUND_UP_ULL(clk_get_parent_rate(clk), val); +} + +static ulong mux_set_rate(struct clk *clk, ulong rate) +{ + struct cv1800b_clk_mux *mux = to_cv1800b_clk_mux(clk); + ulong parent_rate = clk_get_parent_rate(clk); + ulong val; + + val = DIV_ROUND_UP_ULL(parent_rate, rate); + val = min_t(u32, val, clk_div_mask(mux->div.width)); + + cv1800b_clk_setfield(mux->base, &mux->div, val); + if (mux->div_init > 0) + setbits_le32(mux->base + mux->div.offset, CLK_DIV_EN_FACTOR); + + return DIV_ROUND_UP_ULL(parent_rate, val); +} + +static int mux_set_parent(struct clk *clk, struct clk *pclk) +{ + struct cv1800b_clk_mux *mux = to_cv1800b_clk_mux(clk); + int index = get_parent_index(pclk, mux->parent_names, mux->num_parents); + + if (index < 0) + return -EINVAL; + + cv1800b_clk_setfield(mux->base, &mux->mux, index); + return 0; +} + +const struct clk_ops cv1800b_clk_mux_ops = { + .disable = mux_disable, + .enable = mux_enable, + .get_rate = mux_get_rate, + .set_rate = mux_set_rate, + .set_parent = mux_set_parent, +}; + +U_BOOT_DRIVER(cv1800b_clk_mux) = { + .name = "cv1800b_clk_mux", + .id = UCLASS_CLK, + .ops = &cv1800b_clk_mux_ops, + .flags = DM_FLAG_PRE_RELOC, +}; + +#define to_cv1800b_clk_bypass_mux(_clk) \ + container_of(_clk, struct cv1800b_clk_bypass_mux, mux.clk) + +static ulong bypass_mux_get_rate(struct clk *clk) +{ + struct cv1800b_clk_bypass_mux *mux = to_cv1800b_clk_bypass_mux(clk); + + if (cv1800b_clk_getbit(mux->mux.base, &mux->bypass)) + return 0; + + return mux_get_rate(clk); +} + +static ulong bypass_mux_set_rate(struct clk *clk, ulong rate) +{ + struct cv1800b_clk_bypass_mux *mux = to_cv1800b_clk_bypass_mux(clk); + + if (cv1800b_clk_getbit(mux->mux.base, &mux->bypass)) + return 0; + + return mux_set_rate(clk, rate); +} + +static int bypass_mux_set_parent(struct clk *clk, struct clk *pclk) +{ + struct cv1800b_clk_bypass_mux *mux = to_cv1800b_clk_bypass_mux(clk); + int index; + + if (pclk->id == CV1800B_CLK_BYPASS) { + cv1800b_clk_setbit(mux->mux.base, &mux->bypass); + return 0; + } + + index = get_parent_index(pclk, mux->mux.parent_names, + mux->mux.num_parents); + if (index < 0) + return -EINVAL; + + cv1800b_clk_clrbit(mux->mux.base, &mux->bypass); + cv1800b_clk_setfield(mux->mux.base, &mux->mux.mux, index); + return 0; +} + +const struct clk_ops cv1800b_clk_bypass_mux_ops = { + .disable = mux_disable, + .enable = mux_enable, + .get_rate = bypass_mux_get_rate, + .set_rate = bypass_mux_set_rate, + .set_parent = bypass_mux_set_parent, +}; + +U_BOOT_DRIVER(cv1800b_clk_bypass_mux) = { + .name = "cv1800b_clk_bypass_mux", + .id = UCLASS_CLK, + .ops = &cv1800b_clk_bypass_mux_ops, + .flags = DM_FLAG_PRE_RELOC, +}; + +/* MMUX */ +#define to_cv1800b_clk_mmux(_clk) \ + container_of(_clk, struct cv1800b_clk_mmux, clk) + +static int mmux_enable(struct clk *clk) +{ + struct cv1800b_clk_mmux *mmux = to_cv1800b_clk_mmux(clk); + + return cv1800b_clk_setbit(mmux->base, &mmux->gate); +} + +static int mmux_disable(struct clk *clk) +{ + struct cv1800b_clk_mmux *mmux = to_cv1800b_clk_mmux(clk); + + return cv1800b_clk_clrbit(mmux->base, &mmux->gate); +} + +static ulong mmux_get_rate(struct clk *clk) +{ + struct cv1800b_clk_mmux *mmux = to_cv1800b_clk_mmux(clk); + int clk_sel = 1; + ulong reg, val; + + if (cv1800b_clk_getbit(mmux->base, &mmux->bypass)) + return 0; + + if (cv1800b_clk_getbit(mmux->base, &mmux->clk_sel)) + clk_sel = 0; + + reg = readl(mmux->base + mmux->div[clk_sel].offset); + + if (mmux->div_init[clk_sel] == 0 || reg & CLK_DIV_EN_FACTOR) + val = cv1800b_clk_getfield(mmux->base, &mmux->div[clk_sel]); + else + val = mmux->div_init[clk_sel]; + + return DIV_ROUND_UP_ULL(clk_get_parent_rate(clk), val); +} + +static ulong mmux_set_rate(struct clk *clk, ulong rate) +{ + struct cv1800b_clk_mmux *mmux = to_cv1800b_clk_mmux(clk); + int clk_sel = 1; + ulong parent_rate = clk_get_parent_rate(clk); + ulong val; + + if (cv1800b_clk_getbit(mmux->base, &mmux->bypass)) + return 0; + + if (cv1800b_clk_getbit(mmux->base, &mmux->clk_sel)) + clk_sel = 0; + + val = DIV_ROUND_UP_ULL(parent_rate, rate); + val = min_t(u32, val, clk_div_mask(mmux->div[clk_sel].width)); + + cv1800b_clk_setfield(mmux->base, &mmux->div[clk_sel], val); + if (mmux->div_init[clk_sel] > 0) + setbits_le32(mmux->base + mmux->div[clk_sel].offset, + CLK_DIV_EN_FACTOR); + + return DIV_ROUND_UP_ULL(parent_rate, val); +} + +static int mmux_set_parent(struct clk *clk, struct clk *pclk) +{ + struct cv1800b_clk_mmux *mmux = to_cv1800b_clk_mmux(clk); + const char *pname = clk_hw_get_name(pclk); + int i; + u8 clk_sel, index; + + if (pclk->id == CV1800B_CLK_BYPASS) { + cv1800b_clk_setbit(mmux->base, &mmux->bypass); + return 0; + } + + for (i = 0; i < mmux->num_parents; i++) { + if (!strcmp(pname, mmux->parent_infos[i].name)) + break; + } + + if (i == mmux->num_parents) + return -EINVAL; + + clk_sel = mmux->parent_infos[i].clk_sel; + index = mmux->parent_infos[i].index; + cv1800b_clk_clrbit(mmux->base, &mmux->bypass); + if (clk_sel) + cv1800b_clk_clrbit(mmux->base, &mmux->clk_sel); + else + cv1800b_clk_setbit(mmux->base, &mmux->clk_sel); + + cv1800b_clk_setfield(mmux->base, &mmux->mux[clk_sel], index); + return 0; +} + +const struct clk_ops cv1800b_clk_mmux_ops = { + .disable = mmux_disable, + .enable = mmux_enable, + .get_rate = mmux_get_rate, + .set_rate = mmux_set_rate, + .set_parent = mmux_set_parent, +}; + +U_BOOT_DRIVER(cv1800b_clk_mmux) = { + .name = "cv1800b_clk_mmux", + .id = UCLASS_CLK, + .ops = &cv1800b_clk_mmux_ops, + .flags = DM_FLAG_PRE_RELOC, +}; + +/* AUDIO CLK */ +#define to_cv1800b_clk_audio(_clk) \ + container_of(_clk, struct cv1800b_clk_audio, clk) + +static int aclk_enable(struct clk *clk) +{ + struct cv1800b_clk_audio *aclk = to_cv1800b_clk_audio(clk); + + cv1800b_clk_setbit(aclk->base, &aclk->src_en); + cv1800b_clk_setbit(aclk->base, &aclk->output_en); + return 0; +} + +static int aclk_disable(struct clk *clk) +{ + struct cv1800b_clk_audio *aclk = to_cv1800b_clk_audio(clk); + + cv1800b_clk_clrbit(aclk->base, &aclk->src_en); + cv1800b_clk_clrbit(aclk->base, &aclk->output_en); + return 0; +} + +static ulong aclk_get_rate(struct clk *clk) +{ + struct cv1800b_clk_audio *aclk = to_cv1800b_clk_audio(clk); + u64 parent_rate = clk_get_parent_rate(clk); + u32 m, n; + + if (!cv1800b_clk_getbit(aclk->base, &aclk->div_en)) + return 0; + + m = cv1800b_clk_getfield(aclk->base, &aclk->m); + n = cv1800b_clk_getfield(aclk->base, &aclk->n); + + return DIV_ROUND_UP_ULL(n * parent_rate, m * 2); +} + +static u32 gcd(u32 a, u32 b) +{ + u32 t; + + while (b != 0) { + t = a % b; + a = b; + b = t; + } + return a; +} + +static void aclk_determine_mn(ulong parent_rate, ulong rate, u32 *m, u32 *n) +{ + u32 tm = parent_rate / 2; + u32 tn = rate; + u32 tcommon = gcd(tm, tn); + *m = tm / tcommon; + *n = tn / tcommon; +} + +static ulong aclk_set_rate(struct clk *clk, ulong rate) +{ + struct cv1800b_clk_audio *aclk = to_cv1800b_clk_audio(clk); + ulong parent_rate = clk_get_parent_rate(clk); + u32 m, n; + + aclk_determine_mn(parent_rate, rate, &m, &n); + + cv1800b_clk_setfield(aclk->base, &aclk->m, m); + cv1800b_clk_setfield(aclk->base, &aclk->n, n); + + cv1800b_clk_setbit(aclk->base, &aclk->div_en); + cv1800b_clk_setbit(aclk->base, &aclk->div_up); + + return DIV_ROUND_UP_ULL(parent_rate * n, m * 2); +} + +const struct clk_ops cv1800b_clk_audio_ops = { + .disable = aclk_disable, + .enable = aclk_enable, + .get_rate = aclk_get_rate, + .set_rate = aclk_set_rate, +}; + +U_BOOT_DRIVER(cv1800b_clk_audio) = { + .name = "cv1800b_clk_audio", + .id = UCLASS_CLK, + .ops = &cv1800b_clk_audio_ops, + .flags = DM_FLAG_PRE_RELOC, +}; diff --git a/drivers/clk/sophgo/clk-ip.h b/drivers/clk/sophgo/clk-ip.h new file mode 100644 index 0000000000..09d15d86dc --- /dev/null +++ b/drivers/clk/sophgo/clk-ip.h @@ -0,0 +1,288 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ +/* + * Copyright (c) 2024, Kongyang Liu seashell11234455@gmail.com + * + */ + +#ifndef __CLK_SOPHGO_IP_H__ +#define __CLK_SOPHGO_IP_H__ + +#include <clk.h> + +#include "clk-common.h" + +struct cv1800b_mmux_parent_info { + const char *name; + u8 clk_sel; + u8 index; +}; + +struct cv1800b_clk_gate { + struct clk clk; + const char *name; + const char *parent_name; + void __iomem *base; + struct cv1800b_clk_regbit gate; +}; + +struct cv1800b_clk_div { + struct clk clk; + const char *name; + const char *parent_name; + void __iomem *base; + struct cv1800b_clk_regbit gate; + struct cv1800b_clk_regfield div; + int div_init; +}; + +struct cv1800b_clk_bypass_div { + struct cv1800b_clk_div div; + struct cv1800b_clk_regbit bypass; +}; + +struct cv1800b_clk_fixed_div { + struct clk clk; + const char *name; + const char *parent_name; + void __iomem *base; + struct cv1800b_clk_regbit gate; + int div; +}; + +struct cv1800b_clk_bypass_fixed_div { + struct cv1800b_clk_fixed_div div; + struct cv1800b_clk_regbit bypass; +}; + +struct cv1800b_clk_mux { + struct clk clk; + const char *name; + const char * const *parent_names; + u8 num_parents; + void __iomem *base; + struct cv1800b_clk_regbit gate; + struct cv1800b_clk_regfield div; + int div_init; + struct cv1800b_clk_regfield mux; +}; + +struct cv1800b_clk_bypass_mux { + struct cv1800b_clk_mux mux; + struct cv1800b_clk_regbit bypass; +}; + +struct cv1800b_clk_mmux { + struct clk clk; + const char *name; + const struct cv1800b_mmux_parent_info *parent_infos; + u8 num_parents; + void __iomem *base; + struct cv1800b_clk_regbit gate; + struct cv1800b_clk_regfield div[2]; + int div_init[2]; + struct cv1800b_clk_regfield mux[2]; + struct cv1800b_clk_regbit bypass; + struct cv1800b_clk_regbit clk_sel; +}; + +struct cv1800b_clk_audio { + struct clk clk; + const char *name; + const char *parent_name; + void __iomem *base; + struct cv1800b_clk_regbit src_en; + struct cv1800b_clk_regbit output_en; + struct cv1800b_clk_regbit div_en; + struct cv1800b_clk_regbit div_up; + struct cv1800b_clk_regfield m; + struct cv1800b_clk_regfield n; +}; + +#define CV1800B_GATE(_id, _name, _parent, \ + _gate_offset, _gate_shift, \ + _flags) \ + { \ + .clk = { \ + .id = CV1800B_CLK_ID_TRANSFORM(_id), \ + .flags = _flags, \ + }, \ + .name = _name, \ + .parent_name = _parent, \ + .gate = CV1800B_CLK_REGBIT(_gate_offset, _gate_shift), \ + } + +#define CV1800B_DIV(_id, _name, _parent, \ + _gate_offset, _gate_shift, \ + _div_offset, _div_shift, _div_width, \ + _div_init, _flags) \ + { \ + .clk = { \ + .id = CV1800B_CLK_ID_TRANSFORM(_id), \ + .flags = _flags, \ + }, \ + .name = _name, \ + .parent_name = _parent, \ + .gate = CV1800B_CLK_REGBIT(_gate_offset, _gate_shift), \ + .div = CV1800B_CLK_REGFIELD(_div_offset, _div_shift, \ + _div_width), \ + .div_init = _div_init, \ + } + +#define CV1800B_BYPASS_DIV(_id, _name, _parent, \ + _gate_offset, _gate_shift, \ + _div_offset, _div_shift, \ + _div_width, _div_init, \ + _bypass_offset, _bypass_shift, \ + _flags) \ + { \ + .div = CV1800B_DIV(_id, _name, _parent, \ + _gate_offset, _gate_shift, \ + _div_offset, _div_shift, _div_width, \ + _div_init, _flags), \ + .bypass = CV1800B_CLK_REGBIT(_bypass_offset, \ + _bypass_shift), \ + } + +#define CV1800B_FIXED_DIV(_id, _name, _parent, \ + _gate_offset, _gate_shift, \ + _div, _flags) \ + { \ + .clk = { \ + .id = CV1800B_CLK_ID_TRANSFORM(_id), \ + .flags = _flags, \ + }, \ + .name = _name, \ + .parent_name = _parent, \ + .gate = CV1800B_CLK_REGBIT(_gate_offset, _gate_shift), \ + .div = _div, \ + } + +#define CV1800B_BYPASS_FIXED_DIV(_id, _name, _parent, \ + _gate_offset, _gate_shift, \ + _div, \ + _bypass_offset, _bypass_shift, \ + _flags) \ + { \ + .div = CV1800B_FIXED_DIV(_id, _name, _parent, \ + _gate_offset, _gate_shift, \ + _div, _flags), \ + .bypass = CV1800B_CLK_REGBIT(_bypass_offset, \ + _bypass_shift) \ + } + +#define CV1800B_MUX(_id, _name, _parents, \ + _gate_offset, _gate_shift, \ + _div_offset, _div_shift, _div_width, _div_init, \ + _mux_offset, _mux_shift, _mux_width, \ + _flags) \ + { \ + .clk = { \ + .id = CV1800B_CLK_ID_TRANSFORM(_id), \ + .flags = _flags, \ + }, \ + .name = _name, \ + .parent_names = _parents, \ + .num_parents = ARRAY_SIZE(_parents), \ + .gate = CV1800B_CLK_REGBIT(_gate_offset, _gate_shift), \ + .div = CV1800B_CLK_REGFIELD(_div_offset, _div_shift, \ + _div_width), \ + .div_init = _div_init, \ + .mux = CV1800B_CLK_REGFIELD(_mux_offset, _mux_shift, \ + _mux_width), \ + } + +#define CV1800B_BYPASS_MUX(_id, _name, _parents, \ + _gate_offset, _gate_shift, \ + _div_offset, _div_shift, \ + _div_width, _div_init, \ + _mux_offset, _mux_shift, _mux_width, \ + _bypass_offset, _bypass_shift, \ + _flags) \ + { \ + .mux = CV1800B_MUX(_id, _name, _parents, \ + _gate_offset, _gate_shift, \ + _div_offset, _div_shift, \ + _div_width, _div_init, \ + _mux_offset, _mux_shift, _mux_width, \ + _flags), \ + .bypass = CV1800B_CLK_REGBIT(_bypass_offset, \ + _bypass_shift), \ + } + +#define CV1800B_MMUX(_id, _name, _parents, \ + _gate_offset, _gate_shift, \ + _div0_offset, _div0_shift, _div0_width, _div0_init,\ + _div1_offset, _div1_shift, _div1_width, _div1_init,\ + _mux0_offset, _mux0_shift, _mux0_width, \ + _mux1_offset, _mux1_shift, _mux1_width, \ + _bypass_offset, _bypass_shift, \ + _clk_sel_offset, _clk_sel_shift, \ + _flags) \ + { \ + .clk = { \ + .id = CV1800B_CLK_ID_TRANSFORM(_id), \ + .flags = _flags, \ + }, \ + .name = _name, \ + .parent_infos = _parents, \ + .num_parents = ARRAY_SIZE(_parents), \ + .gate = CV1800B_CLK_REGBIT(_gate_offset, _gate_shift), \ + .div = { \ + CV1800B_CLK_REGFIELD(_div0_offset, _div0_shift, \ + _div0_width), \ + CV1800B_CLK_REGFIELD(_div1_offset, _div1_shift, \ + _div1_width), \ + }, \ + .div_init = { _div0_init, _div1_init }, \ + .mux = { \ + CV1800B_CLK_REGFIELD(_mux0_offset, _mux0_shift, \ + _mux0_width), \ + CV1800B_CLK_REGFIELD(_mux1_offset, _mux1_shift, \ + _mux1_width), \ + }, \ + .bypass = CV1800B_CLK_REGBIT(_bypass_offset, \ + _bypass_shift), \ + .clk_sel = CV1800B_CLK_REGBIT(_clk_sel_offset, \ + _clk_sel_shift), \ + } + +#define CV1800B_AUDIO(_id, _name, _parent, \ + _src_en_offset, _src_en_shift, \ + _output_en_offset, _output_en_shift, \ + _div_en_offset, _div_en_shift, \ + _div_up_offset, _div_up_shift, \ + _m_offset, _m_shift, _m_width, \ + _n_offset, _n_shift, _n_width, \ + _flags) \ + { \ + .clk = { \ + .id = CV1800B_CLK_ID_TRANSFORM(_id), \ + .flags = _flags, \ + }, \ + .name = _name, \ + .parent_name = _parent, \ + .src_en = CV1800B_CLK_REGBIT(_src_en_offset, \ + _src_en_shift), \ + .output_en = CV1800B_CLK_REGBIT(_output_en_offset, \ + _output_en_shift), \ + .div_en = CV1800B_CLK_REGBIT(_div_en_offset, \ + _div_en_shift), \ + .div_up = CV1800B_CLK_REGBIT(_div_up_offset, \ + _div_up_shift), \ + .m = CV1800B_CLK_REGFIELD(_m_offset, _m_shift, \ + _m_width), \ + .n = CV1800B_CLK_REGFIELD(_n_offset, _n_shift, \ + _n_width), \ + } + +extern const struct clk_ops cv1800b_clk_gate_ops; +extern const struct clk_ops cv1800b_clk_div_ops; +extern const struct clk_ops cv1800b_clk_bypass_div_ops; +extern const struct clk_ops cv1800b_clk_fixed_div_ops; +extern const struct clk_ops cv1800b_clk_bypass_fixed_div_ops; +extern const struct clk_ops cv1800b_clk_mux_ops; +extern const struct clk_ops cv1800b_clk_bypass_mux_ops; +extern const struct clk_ops cv1800b_clk_mmux_ops; +extern const struct clk_ops cv1800b_clk_audio_ops; + +#endif /* __CLK_SOPHGO_IP_H__ */ diff --git a/drivers/clk/sophgo/clk-pll.c b/drivers/clk/sophgo/clk-pll.c new file mode 100644 index 0000000000..c99aa0b4e4 --- /dev/null +++ b/drivers/clk/sophgo/clk-pll.c @@ -0,0 +1,275 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright (c) 2024, Kongyang Liu seashell11234455@gmail.com + */ + +#include <clk-uclass.h> +#include <dm.h> +#include <div64.h> +#include <linux/bitfield.h> +#include <linux/clk-provider.h> +#include <linux/kernel.h> + +#include "clk-common.h" +#include "clk-pll.h" + +#define PLL_PRE_DIV_MIN 1 +#define PLL_PRE_DIV_MAX 127 +#define PLL_POST_DIV_MIN 1 +#define PLL_POST_DIV_MAX 127 +#define PLL_DIV_MIN 6 +#define PLL_DIV_MAX 127 +#define PLL_ICTRL_MIN 0 +#define PLL_ICTRL_MAX 7 +#define PLL_MODE_MIN 0 +#define PLL_MODE_MAX 3 +#define FOR_RANGE(x, RANGE) for (x = RANGE##_MIN; x <= RANGE##_MAX; x++) + +#define PLL_ICTRL GENMASK(26, 24) +#define PLL_DIV_SEL GENMASK(23, 17) +#define PLL_SEL_MODE GENMASK(16, 15) +#define PLL_POST_DIV_SEL GENMASK(14, 8) +#define PLL_PRE_DIV_SEL GENMASK(6, 0) +#define PLL_MASK_ALL (PLL_ICTRL | PLL_DIV_SEL | PLL_SEL_MODE | PLL_POST_DIV_SEL | PLL_PRE_DIV_SEL) + +/* IPLL */ +#define to_clk_ipll(dev) container_of(dev, struct cv1800b_clk_ipll, clk) + +static int cv1800b_ipll_enable(struct clk *clk) +{ + struct cv1800b_clk_ipll *pll = to_clk_ipll(clk); + + cv1800b_clk_clrbit(pll->base, &pll->pll_pwd); + return 0; +} + +static int cv1800b_ipll_disable(struct clk *clk) +{ + struct cv1800b_clk_ipll *pll = to_clk_ipll(clk); + + cv1800b_clk_setbit(pll->base, &pll->pll_pwd); + return 0; +} + +static ulong cv1800b_ipll_get_rate(struct clk *clk) +{ + struct cv1800b_clk_ipll *pll = to_clk_ipll(clk); + + ulong parent_rate = clk_get_parent_rate(clk); + u32 reg = readl(pll->base + pll->pll_reg); + u32 pre_div = FIELD_GET(PLL_PRE_DIV_SEL, reg); + u32 post_div = FIELD_GET(PLL_POST_DIV_SEL, reg); + u32 div = FIELD_GET(PLL_DIV_SEL, reg); + + return DIV_ROUND_DOWN_ULL(parent_rate * div, pre_div * post_div); +} + +static ulong cv1800b_ipll_set_rate(struct clk *clk, ulong rate) +{ + struct cv1800b_clk_ipll *pll = to_clk_ipll(clk); + ulong parent_rate = clk_get_parent_rate(clk); + u32 pre_div, post_div, div; + u32 pre_div_sel, post_div_sel, div_sel; + ulong new_rate, best_rate = 0; + u32 mode, ictrl; + u32 test, val; + + FOR_RANGE(pre_div, PLL_PRE_DIV) + { + FOR_RANGE(post_div, PLL_POST_DIV) + { + FOR_RANGE(div, PLL_DIV) + { + new_rate = + DIV_ROUND_DOWN_ULL(parent_rate * div, pre_div * post_div); + if (rate - new_rate < rate - best_rate) { + best_rate = new_rate; + pre_div_sel = pre_div; + post_div_sel = post_div; + div_sel = div; + } + } + } + } + + FOR_RANGE(mode, PLL_MODE) + { + FOR_RANGE(ictrl, PLL_ICTRL) + { + test = 184 * (1 + mode) * (1 + ictrl) / 2; + if (test > 20 * div_sel && test < 35 * div_sel) { + val = FIELD_PREP(PLL_PRE_DIV_SEL, pre_div_sel) | + FIELD_PREP(PLL_POST_DIV_SEL, post_div_sel) | + FIELD_PREP(PLL_DIV_SEL, div_sel) | + FIELD_PREP(PLL_ICTRL, ictrl) | + FIELD_PREP(PLL_SEL_MODE, mode); + clrsetbits_le32(pll->base + pll->pll_reg, PLL_MASK_ALL, val); + return best_rate; + } + } + } + + return -EINVAL; +} + +const struct clk_ops cv1800b_ipll_ops = { + .enable = cv1800b_ipll_enable, + .disable = cv1800b_ipll_disable, + .get_rate = cv1800b_ipll_get_rate, + .set_rate = cv1800b_ipll_set_rate, +}; + +U_BOOT_DRIVER(cv1800b_clk_ipll) = { + .name = "cv1800b_clk_ipll", + .id = UCLASS_CLK, + .ops = &cv1800b_ipll_ops, + .flags = DM_FLAG_PRE_RELOC, +}; + +/* FPLL */ +#define to_clk_fpll(dev) container_of(dev, struct cv1800b_clk_fpll, ipll.clk) + +static ulong cv1800b_fpll_get_rate(struct clk *clk) +{ + struct cv1800b_clk_fpll *pll = to_clk_fpll(clk); + u32 val, syn_set; + u32 pre_div, post_div, div; + u8 mult = 1; + ulong divisor, remainder, rate; + + if (!cv1800b_clk_getbit(pll->ipll.base, &pll->syn.en)) + return cv1800b_ipll_get_rate(clk); + + syn_set = readl(pll->ipll.base + pll->syn.set); + if (syn_set == 0) + return 0; + + val = readl(pll->ipll.base + pll->ipll.pll_reg); + pre_div = FIELD_GET(PLL_PRE_DIV_SEL, val); + post_div = FIELD_GET(PLL_POST_DIV_SEL, val); + div = FIELD_GET(PLL_DIV_SEL, val); + + if (cv1800b_clk_getbit(pll->ipll.base, &pll->syn.clk_half)) + mult = 2; + + divisor = (ulong)pre_div * post_div * syn_set; + rate = (clk_get_parent_rate(clk) * div) << 25; + remainder = rate % divisor; + rate /= divisor; + return rate * mult + DIV_ROUND_CLOSEST_ULL(remainder * mult, divisor); +} + +static ulong cv1800b_find_syn(ulong rate, ulong parent_rate, ulong pre_div, ulong post_div, + ulong div, u32 *syn) +{ + u32 syn_min = (4 << 26) + 1; + u32 syn_max = U32_MAX; + u32 mid; + ulong new_rate; + u32 mult = 1; + ulong divisor, remainder; + + while (syn_min < syn_max) { + mid = ((ulong)syn_min + syn_max) / 2; + divisor = pre_div * post_div * mid; + new_rate = (parent_rate * div) << 25; + remainder = do_div(new_rate, divisor); + new_rate = new_rate * mult + DIV_ROUND_CLOSEST_ULL(remainder * mult, divisor); + if (new_rate > rate) { + syn_max = mid + 1; + } else if (new_rate < rate) { + syn_min = mid - 1; + } else { + syn_min = mid; + break; + } + } + *syn = syn_min; + return new_rate; +} + +static ulong cv1800b_fpll_set_rate(struct clk *clk, ulong rate) +{ + struct cv1800b_clk_fpll *pll = to_clk_fpll(clk); + ulong parent_rate = clk_get_parent_rate(clk); + u32 pre_div, post_div, div; + u32 pre_div_sel, post_div_sel, div_sel; + u32 syn, syn_sel; + ulong new_rate, best_rate = 0; + u32 mult = 1; + u32 mode, ictrl; + + if (!cv1800b_clk_getbit(pll->ipll.base, &pll->syn.en)) + return cv1800b_ipll_set_rate(clk, rate); + + if (cv1800b_clk_getbit(pll->ipll.base, &pll->syn.clk_half)) + mult = 2; + + FOR_RANGE(pre_div, PLL_PRE_DIV) + { + FOR_RANGE(post_div, PLL_POST_DIV) + { + FOR_RANGE(div, PLL_DIV) + { + new_rate = cv1800b_find_syn(rate, parent_rate, pre_div, post_div, + div, &syn); + if (rate - new_rate < rate - best_rate) { + best_rate = new_rate; + pre_div_sel = pre_div; + post_div_sel = post_div; + div_sel = div; + syn_sel = syn; + } + } + } + } + + FOR_RANGE(mode, PLL_MODE) + { + FOR_RANGE(ictrl, PLL_ICTRL) + { + u32 test = 184 * (1 + mode) * (1 + ictrl) / 2; + + if (test > 10 * div_sel && test <= 24 * div_sel) { + u32 val = FIELD_PREP(PLL_PRE_DIV_SEL, pre_div_sel) | + FIELD_PREP(PLL_POST_DIV_SEL, post_div_sel) | + FIELD_PREP(PLL_DIV_SEL, div_sel) | + FIELD_PREP(PLL_ICTRL, ictrl) | + FIELD_PREP(PLL_SEL_MODE, mode); + clrsetbits_le32(pll->ipll.base + pll->ipll.pll_reg, PLL_MASK_ALL, + val); + writel(syn_sel, pll->ipll.base + pll->syn.set); + return best_rate; + } + } + } + + return -EINVAL; +} + +static int cv1800b_fpll_set_parent(struct clk *clk, struct clk *parent) +{ + struct cv1800b_clk_fpll *pll = to_clk_fpll(clk); + + if (parent->id == CV1800B_CLK_BYPASS) + cv1800b_clk_setbit(pll->ipll.base, &pll->syn.en); + else + cv1800b_clk_clrbit(pll->ipll.base, &pll->syn.en); + + return 0; +} + +const struct clk_ops cv1800b_fpll_ops = { + .enable = cv1800b_ipll_enable, + .disable = cv1800b_ipll_disable, + .get_rate = cv1800b_fpll_get_rate, + .set_rate = cv1800b_fpll_set_rate, + .set_parent = cv1800b_fpll_set_parent, +}; + +U_BOOT_DRIVER(cv1800b_clk_fpll) = { + .name = "cv1800b_clk_fpll", + .id = UCLASS_CLK, + .ops = &cv1800b_fpll_ops, + .flags = DM_FLAG_PRE_RELOC, +}; diff --git a/drivers/clk/sophgo/clk-pll.h b/drivers/clk/sophgo/clk-pll.h new file mode 100644 index 0000000000..bea9bd8a43 --- /dev/null +++ b/drivers/clk/sophgo/clk-pll.h @@ -0,0 +1,74 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ +/* + * Copyright (c) 2024, Kongyang Liu seashell11234455@gmail.com + * + */ + +#ifndef __clk_SOPHGO_PLL_H__ +#define __clk_SOPHGO_PLL_H__ + +#include <clk.h> + +#include "clk-common.h" + +struct cv1800b_clk_synthesizer { + struct cv1800b_clk_regbit en; + struct cv1800b_clk_regbit clk_half; + u32 ctrl; + u32 set; +}; + +struct cv1800b_clk_ipll { + struct clk clk; + const char *name; + const char *parent_name; + void __iomem *base; + u32 pll_reg; + struct cv1800b_clk_regbit pll_pwd; + struct cv1800b_clk_regbit pll_status; +}; + +struct cv1800b_clk_fpll { + struct cv1800b_clk_ipll ipll; + struct cv1800b_clk_synthesizer syn; +}; + +#define CV1800B_IPLL(_id, _name, _parent_name, _pll_reg, _pll_pwd_offset, \ + _pll_pwd_shift, _pll_status_offset, _pll_status_shift, \ + _flags) \ + { \ + .clk = { \ + .id = CV1800B_CLK_ID_TRANSFORM(_id), \ + .flags = _flags, \ + }, \ + .name = _name, \ + .parent_name = _parent_name, \ + .pll_reg = _pll_reg, \ + .pll_pwd = CV1800B_CLK_REGBIT(_pll_pwd_offset, _pll_pwd_shift), \ + .pll_status = CV1800B_CLK_REGBIT(_pll_status_offset, \ + _pll_status_shift), \ + } + +#define CV1800B_FPLL(_id, _name, _parent_name, _pll_reg, _pll_pwd_offset, \ + _pll_pwd_shift, _pll_status_offset, _pll_status_shift, \ + _syn_en_offset, _syn_en_shift, _syn_clk_half_offset, \ + _syn_clk_half_shift, _syn_ctrl_offset, _syn_set_offset, \ + _flags) \ + { \ + .ipll = CV1800B_IPLL(_id, _name, _parent_name, _pll_reg, \ + _pll_pwd_offset, _pll_pwd_shift, \ + _pll_status_offset, _pll_status_shift, \ + _flags), \ + .syn = { \ + .en = CV1800B_CLK_REGBIT(_syn_en_offset, _syn_en_shift),\ + .clk_half = CV1800B_CLK_REGBIT(_syn_clk_half_offset, \ + _syn_clk_half_shift), \ + .ctrl = _syn_ctrl_offset, \ + .set = _syn_set_offset, \ + }, \ + } + +extern const struct clk_ops cv1800b_ipll_ops; +extern const struct clk_ops cv1800b_fpll_ops; + +#endif /* __clk_SOPHGO_PLL_H__ */

On Tue, Jun 11, 2024 at 05:41:14PM +0800, Kongyang Liu wrote:
Add clock controller driver for sophgo cv1800b SoC
Signed-off-by: Kongyang Liu seashell11234455@gmail.com
Changes in v2:
- Fix compilation error
- Remove unused code
drivers/clk/Kconfig | 1 + drivers/clk/Makefile | 1 + drivers/clk/sophgo/Kconfig | 14 + drivers/clk/sophgo/Makefile | 6 + drivers/clk/sophgo/clk-common.h | 74 +++ drivers/clk/sophgo/clk-cv1800b.c | 754 +++++++++++++++++++++++++++++++ drivers/clk/sophgo/clk-cv1800b.h | 123 +++++ drivers/clk/sophgo/clk-ip.c | 594 ++++++++++++++++++++++++ drivers/clk/sophgo/clk-ip.h | 288 ++++++++++++ drivers/clk/sophgo/clk-pll.c | 275 +++++++++++ drivers/clk/sophgo/clk-pll.h | 74 +++ 11 files changed, 2204 insertions(+) create mode 100644 drivers/clk/sophgo/Kconfig create mode 100644 drivers/clk/sophgo/Makefile create mode 100644 drivers/clk/sophgo/clk-common.h create mode 100644 drivers/clk/sophgo/clk-cv1800b.c create mode 100644 drivers/clk/sophgo/clk-cv1800b.h create mode 100644 drivers/clk/sophgo/clk-ip.c create mode 100644 drivers/clk/sophgo/clk-ip.h create mode 100644 drivers/clk/sophgo/clk-pll.c create mode 100644 drivers/clk/sophgo/clk-pll.h
Reviewed-by: Leo Yu-Chi Liang ycliang@andestech.com

Add configs to enable clock controller for Sophgo Milk-V Duo board
Signed-off-by: Kongyang Liu seashell11234455@gmail.com ---
(no changes since v1)
configs/milkv_duo_defconfig | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-)
diff --git a/configs/milkv_duo_defconfig b/configs/milkv_duo_defconfig index 0cb2922de4..1186763a73 100644 --- a/configs/milkv_duo_defconfig +++ b/configs/milkv_duo_defconfig @@ -1,6 +1,6 @@ CONFIG_RISCV=y CONFIG_SYS_MALLOC_LEN=0x820000 -CONFIG_SYS_MALLOC_F_LEN=0x2000 +CONFIG_SYS_MALLOC_F_LEN=0x8000 CONFIG_NR_DRAM_BANKS=1 CONFIG_HAS_CUSTOM_SYS_INIT_SP_ADDR=y CONFIG_CUSTOM_SYS_INIT_SP_ADDR=0x82300000 @@ -26,17 +26,18 @@ CONFIG_CMD_FAT=y CONFIG_CMD_FS_GENERIC=y CONFIG_ENV_OVERWRITE=y CONFIG_NET_RANDOM_ETHADDR=y +CONFIG_CLK_SOPHGO_CV1800B=y CONFIG_MMC=y CONFIG_MMC_IO_VOLTAGE=y CONFIG_MMC_UHS_SUPPORT=y CONFIG_MMC_SDHCI=y CONFIG_MMC_SDHCI_ADMA=y CONFIG_MMC_SDHCI_CV1800B=y +CONFIG_SPI_FLASH_MACRONIX=y CONFIG_ETH_DESIGNWARE=y CONFIG_SYS_NS16550=y CONFIG_SYS_NS16550_MEM32=y -CONFIG_SYSRESET=y -CONFIG_SYSRESET_CV1800B=y -CONFIG_SPI_FLASH_MACRONIX=y CONFIG_SPI=y CONFIG_CV1800B_SPIF=y +CONFIG_SYSRESET=y +CONFIG_SYSRESET_CV1800B=y

On Tue, Jun 11, 2024 at 05:41:15PM +0800, Kongyang Liu wrote:
Add configs to enable clock controller for Sophgo Milk-V Duo board
Signed-off-by: Kongyang Liu seashell11234455@gmail.com
(no changes since v1)
configs/milkv_duo_defconfig | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-)
Reviewed-by: Leo Yu-Chi Liang ycliang@andestech.com

Replace device clocks with real clocks from the clock controller, and remove dummy clocks.
Signed-off-by: Kongyang Liu seashell11234455@gmail.com ---
(no changes since v1)
arch/riscv/dts/cv18xx.dtsi | 40 +++++++++++++++----------------------- 1 file changed, 16 insertions(+), 24 deletions(-)
diff --git a/arch/riscv/dts/cv18xx.dtsi b/arch/riscv/dts/cv18xx.dtsi index 4b0143450e..8a7386b76e 100644 --- a/arch/riscv/dts/cv18xx.dtsi +++ b/arch/riscv/dts/cv18xx.dtsi @@ -5,6 +5,7 @@ */
#include <dt-bindings/interrupt-controller/irq.h> +#include <dt-bindings/clock/sophgo,cv1800.h>
/ { #address-cells = <1>; @@ -45,13 +46,6 @@ #clock-cells = <0>; };
- sdhci_clk: sdhci-clock { - compatible = "fixed-clock"; - clock-frequency = <375000000>; - clock-output-names = "sdhci_clk"; - #clock-cells = <0>; - }; - eth_csrclk: eth-csrclk { compatible = "fixed-clock"; clock-frequency = <250000000>; @@ -66,13 +60,6 @@ #clock-cells = <0x0>; };
- spif_clk: spi-flash-clock { - compatible = "fixed-clock"; - clock-frequency = <300000000>; - clock-output-names = "spif_clk"; - #clock-cells = <0>; - }; - soc { compatible = "simple-bus"; interrupt-parent = <&plic>; @@ -163,8 +150,8 @@ compatible = "sophgo,cv1800b-dwmac"; reg = <0x04070000 0x10000>; interrupts = <31 IRQ_TYPE_LEVEL_HIGH>; - clocks = <ð_csrclk>, <ð_ptpclk>; - clock-names = "stmmaceth", "ptp_ref"; + clocks = <&clk CLK_ETH0_500M>, <&clk CLK_AXI4_ETH0>; + clock-names = "stmmaceth", "pclk"; status = "disabled"; };
@@ -172,7 +159,8 @@ compatible = "snps,dw-apb-uart"; reg = <0x04140000 0x100>; interrupts = <44 IRQ_TYPE_LEVEL_HIGH>; - clocks = <&osc>; + clocks = <&clk CLK_UART0>, <&clk CLK_APB_UART0>; + clock-names = "baudclk", "apb_pclk"; reg-shift = <2>; reg-io-width = <4>; status = "disabled"; @@ -182,7 +170,8 @@ compatible = "snps,dw-apb-uart"; reg = <0x04150000 0x100>; interrupts = <45 IRQ_TYPE_LEVEL_HIGH>; - clocks = <&osc>; + clocks = <&clk CLK_UART4>, <&clk CLK_APB_UART4>; + clock-names = "baudclk", "apb_pclk"; reg-shift = <2>; reg-io-width = <4>; status = "disabled"; @@ -192,7 +181,8 @@ compatible = "snps,dw-apb-uart"; reg = <0x04160000 0x100>; interrupts = <46 IRQ_TYPE_LEVEL_HIGH>; - clocks = <&osc>; + clocks = <&clk CLK_UART2>, <&clk CLK_APB_UART2>; + clock-names = "baudclk", "apb_pclk"; reg-shift = <2>; reg-io-width = <4>; status = "disabled"; @@ -202,7 +192,8 @@ compatible = "snps,dw-apb-uart"; reg = <0x04170000 0x100>; interrupts = <47 IRQ_TYPE_LEVEL_HIGH>; - clocks = <&osc>; + clocks = <&clk CLK_UART3>, <&clk CLK_APB_UART3>; + clock-names = "baudclk", "apb_pclk"; reg-shift = <2>; reg-io-width = <4>; status = "disabled"; @@ -212,7 +203,8 @@ compatible = "snps,dw-apb-uart"; reg = <0x041c0000 0x100>; interrupts = <48 IRQ_TYPE_LEVEL_HIGH>; - clocks = <&osc>; + clocks = <&clk CLK_UART4>, <&clk CLK_APB_UART4>; + clock-names = "baudclk", "apb_pclk"; reg-shift = <2>; reg-io-width = <4>; status = "disabled"; @@ -222,8 +214,8 @@ compatible = "sophgo,cv1800b-dwcmshc"; reg = <0x4310000 0x1000>; interrupts = <36 IRQ_TYPE_LEVEL_HIGH>; - clocks = <&sdhci_clk>; - clock-names = "core"; + clocks = <&clk CLK_AXI4_SD0>, <&clk CLK_SD0>; + clock-names = "core", "bus"; status = "disabled"; };
@@ -232,7 +224,7 @@ reg = <0x10000000 0x10000000>; #address-cells = <1>; #size-cells = <0>; - clocks = <&spif_clk>; + clocks = <&clk CLK_AHB_SF>; interrupts = <95 IRQ_TYPE_LEVEL_HIGH>; status = "disabled"; };

On Tue, Jun 11, 2024 at 05:41:16PM +0800, Kongyang Liu wrote:
Replace device clocks with real clocks from the clock controller, and remove dummy clocks.
Signed-off-by: Kongyang Liu seashell11234455@gmail.com
(no changes since v1)
arch/riscv/dts/cv18xx.dtsi | 40 +++++++++++++++----------------------- 1 file changed, 16 insertions(+), 24 deletions(-)
Reviewed-by: Leo Yu-Chi Liang ycliang@andestech.com
participants (2)
-
Kongyang Liu
-
Leo Liang