cv18x0: add new target for Sophgo CV18x0 RISC-V SoCs cv18x0-202407
authorZoltan HERPAI <wigyori@uid0.hu>
Wed, 4 Oct 2023 15:28:54 +0000 (17:28 +0200)
committerZoltan HERPAI <wigyori@uid0.hu>
Fri, 28 Jun 2024 22:25:33 +0000 (00:25 +0200)
Initially targeting the Milk-V Duo+dock board.

Signed-off-by: Zoltan HERPAI <wigyori@uid0.hu>
37 files changed:
package/boot/opensbi/Makefile
package/boot/uboot-cv18x0/Makefile [new file with mode: 0644]
package/boot/uboot-cv18x0/patches/100-mkimage-check-environment-for-dtc-binary-location.patch [new file with mode: 0644]
package/boot/uboot-cv18x0/patches/130-fix-mkimage-host-build.patch [new file with mode: 0644]
package/boot/uboot-cv18x0/patches/200-add-BL33-on-milkvduo.patch [new file with mode: 0644]
package/boot/uboot-cv18x0/uEnv-default.txt [new file with mode: 0644]
target/linux/cv18x0/Makefile [new file with mode: 0644]
target/linux/cv18x0/base-files/etc/board.d/01_leds [new file with mode: 0644]
target/linux/cv18x0/base-files/etc/board.d/02_network [new file with mode: 0644]
target/linux/cv18x0/base-files/etc/inittab [new file with mode: 0644]
target/linux/cv18x0/base-files/lib/preinit/79_move_config [new file with mode: 0644]
target/linux/cv18x0/base-files/lib/upgrade/platform.sh [new file with mode: 0644]
target/linux/cv18x0/config-6.6 [new file with mode: 0644]
target/linux/cv18x0/generic/target.mk [new file with mode: 0644]
target/linux/cv18x0/image/Config.in [new file with mode: 0644]
target/linux/cv18x0/image/Makefile [new file with mode: 0644]
target/linux/cv18x0/image/gen_cv18x0_sdcard_img.sh [new file with mode: 0755]
target/linux/cv18x0/patches-6.6/0001-riscv-Add-Sophgo-SoC-platform-hardware-support.patch [new file with mode: 0644]
target/linux/cv18x0/patches-6.6/0002-riscv-dts-sophgo-add-initial-CV1800B-SoC-device-tree.patch [new file with mode: 0644]
target/linux/cv18x0/patches-6.6/0003-riscv-dts-add-initial-SOPHGO-SG2042-SoC-device-tree.patch [new file with mode: 0644]
target/linux/cv18x0/patches-6.6/0004-riscv-dts-sophgo-add-Milk-V-Pioneer-board-device-tre.patch [new file with mode: 0644]
target/linux/cv18x0/patches-6.6/0005-riscv-dts-sophgo-add-Milk-V-Duo-board-device-tree.patch [new file with mode: 0644]
target/linux/cv18x0/patches-6.6/0006-riscv-dts-sophgo-add-initial-CV1812H-SoC-device-tree.patch [new file with mode: 0644]
target/linux/cv18x0/patches-6.6/0007-riscv-dts-sophgo-Separate-compatible-specific-for-CV.patch [new file with mode: 0644]
target/linux/cv18x0/patches-6.6/0008-riscv-dts-sophgo-cv18xx-Add-gpio-devices.patch [new file with mode: 0644]
target/linux/cv18x0/patches-6.6/0009-drivers-mmc-sdhci-of-dwcmshc-include-bitfield.h-for-.patch [new file with mode: 0644]
target/linux/cv18x0/patches-6.6/0010-mmc-sdhci-of-dwcmshc-Add-support-for-Sophgo-CV1800B-.patch [new file with mode: 0644]
target/linux/cv18x0/patches-6.6/0011-dt-bindings-clock-sophgo-Add-clock-controller-of-CV1.patch [new file with mode: 0644]
target/linux/cv18x0/patches-6.6/0012-clk-sophgo-Add-CV1800-SG2000-series-clock-controller.patch [new file with mode: 0644]
target/linux/cv18x0/patches-6.6/0013-riscv-dts-sophgo-add-sdcard-support-for-milkv-duo.patch [new file with mode: 0644]
target/linux/cv18x0/patches-6.6/0014-sophgo-add-reboot-shutdown-driver.patch [new file with mode: 0644]
target/linux/cv18x0/patches-6.6/0015-dt-bindings-reset-Add-binding-for-Sophgo-CV1800B-res.patch [new file with mode: 0644]
target/linux/cv18x0/patches-6.6/0016-reset-Add-reset-controller-support-for-Sophgo-CV1800.patch [new file with mode: 0644]
target/linux/cv18x0/patches-6.6/0017-riscv-dts-sophgo-add-watchdog-dt-node-for-CV1800.patch [new file with mode: 0644]
target/linux/cv18x0/patches-6.6/0018-riscv-dts-sophgo-add-timer-dt-node-for-CV1800.patch [new file with mode: 0644]
target/linux/cv18x0/patches-6.6/0019-mmc-sdhci-of-dwcmshc-Add-tuning-support-for-Sophgo-C.patch [new file with mode: 0644]
target/linux/cv18x0/patches-6.6/0020-riscv-dts-sophgo-use-real-clock-for-sdhci.patch [new file with mode: 0644]

index d77c00c884506ec86d4f85a72dc62faead76f8bd..9d62ae750b9132ce5f0a0af50ce187d0c687f711 100644 (file)
@@ -41,7 +41,7 @@ define Package/opensbi_generic
   $(Package/opensbi)
   TITLE:=OpenSBI generic
   OPENSBI_IMAGE:=fw_dynamic.bin
-  DEPENDS:=@TARGET_cv18x0:u-boot-milkv_duo
+  DEPENDS:=+(TARGET_cv18x0):u-boot-milkv_duo
   PLAT:=generic
 endef
 
@@ -50,8 +50,8 @@ export GCC_HONOUR_COPTS=s
 MAKE_VARS = \
        CROSS_COMPILE="$(TARGET_CROSS)"
 
-ifdef CONFIG_TARGET_cv18x0
-FW_FDT_PATH=$(STAGING_DIR_IMAGE)/asdasd.dtb
+ifdef CONFIG_TARGET_DEVICE_cv18x0_generic_DEVICE_milkv_duo
+FW_FDT_PATH=$(STAGING_DIR_IMAGE)/cv1800b-milkv-duo.dtb
 endif
 
 define Build/Compile
diff --git a/package/boot/uboot-cv18x0/Makefile b/package/boot/uboot-cv18x0/Makefile
new file mode 100644 (file)
index 0000000..8aa33b7
--- /dev/null
@@ -0,0 +1,57 @@
+# SPDX-License-Identifier: GPL-2.0-only
+#
+# Copyright (C) 2024 OpenWrt.org
+#
+
+include $(TOPDIR)/rules.mk
+include $(INCLUDE_DIR)/kernel.mk
+
+PKG_RELEASE:=1
+PKG_VERSION:=2024.07-rc5
+PKG_SOURCE_PROTO:=git
+PKG_SOURCE_URL:=https://github.com/u-boot/u-boot
+PKG_SOURCE_VERSION:=9e9f78f7aa0124ef0e622532043acf87e84008dc
+
+UBOOT_USE_INTREE_DTC:=1
+
+include $(INCLUDE_DIR)/u-boot.mk
+include $(INCLUDE_DIR)/package.mk
+
+PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.zst
+PKG_MIRROR_HASH:=3d69884648f0412b500f5968c2d3014acb51b3a97bc256e306ff9cac99a5fec0
+
+define U-Boot/Default
+  BUILD_TARGET:=cv18x0
+  BUILD_DEVICES=$(1)
+  UBOOT_IMAGE:=u-boot.bin
+  DTS_DIR:=arch/riscv/dts
+  UENV:=default
+  DEFAULT:=y
+endef
+
+define U-Boot/milkv_duo
+  NAME:=MilkV Duo
+  OPENSBI:=generic
+  DEPENDS:=+cv18xxlibs
+  UBOOT_DTS:=cv1800b-milkv-duo.dtb
+  BUILD_DEVICES:=milkv_duo
+endef
+
+UBOOT_TARGETS := \
+       milkv_duo
+
+#UBOOT_MAKE_FLAGS += \
+#        OPENSBI=$(STAGING_DIR_IMAGE)/fw_dynamic-${OPENSBI}.bin
+
+define Build/Configure
+       $(call Build/Configure/U-Boot)
+       sed -i 's/CONFIG_TOOLS_LIBCRYPTO=y/# CONFIG_TOOLS_LIBCRYPTO is not set/' $(PKG_BUILD_DIR)/.config
+endef
+
+define Build/InstallDev
+       $(INSTALL_DIR) $(STAGING_DIR_IMAGE)
+       $(INSTALL_BIN) $(PKG_BUILD_DIR)/$(UBOOT_IMAGE) $(STAGING_DIR_IMAGE)/$(BUILD_VARIANT)-$(UBOOT_IMAGE)
+       $(INSTALL_BIN) $(PKG_BUILD_DIR)/$(DTS_DIR)/$(UBOOT_DTS) $(STAGING_DIR_IMAGE)/$(UBOOT_DTS)
+endef
+
+$(eval $(call BuildPackage/U-Boot))
diff --git a/package/boot/uboot-cv18x0/patches/100-mkimage-check-environment-for-dtc-binary-location.patch b/package/boot/uboot-cv18x0/patches/100-mkimage-check-environment-for-dtc-binary-location.patch
new file mode 100644 (file)
index 0000000..482aa1a
--- /dev/null
@@ -0,0 +1,35 @@
+From 637800493945ffed2f454756300437a4ec86e3b1 Mon Sep 17 00:00:00 2001
+From: Hauke Mehrtens <hauke@hauke-m.de>
+Date: Wed, 19 Jul 2017 22:23:15 +0200
+Subject: mkimage: check environment for dtc binary location
+
+Currently mkimage assumes the dtc binary is in the path and fails
+otherwise. This patch makes it check the DTC environment variable first
+for the dtc binary and then fall back to the default path. This makes
+it possible to call the u-boot build with make DTC=... and build a fit
+image with the dtc binary not being the the default path.
+
+Signed-off-by: Hauke Mehrtens <hauke@hauke-m.de>
+Cc: Simon Glass <sjg@chromium.org>
+---
+ tools/fit_image.c | 7 ++++++-
+ 1 file changed, 6 insertions(+), 1 deletion(-)
+
+--- a/tools/fit_image.c
++++ b/tools/fit_image.c
+@@ -726,9 +726,14 @@ static int fit_handle_file(struct image_
+               }
+               *cmd = '\0';
+       } else if (params->datafile) {
++              const char* dtc = getenv("DTC");
++
++              if (!dtc)
++                      dtc = MKIMAGE_DTC;
++
+               /* dtc -I dts -O dtb -p 500 -o tmpfile datafile */
+               snprintf(cmd, sizeof(cmd), "%s %s -o \"%s\" \"%s\"",
+-                       MKIMAGE_DTC, params->dtc, tmpfile, params->datafile);
++                       dtc, params->dtc, tmpfile, params->datafile);
+               debug("Trying to execute \"%s\"\n", cmd);
+       } else {
+               snprintf(cmd, sizeof(cmd), "cp \"%s\" \"%s\"",
diff --git a/package/boot/uboot-cv18x0/patches/130-fix-mkimage-host-build.patch b/package/boot/uboot-cv18x0/patches/130-fix-mkimage-host-build.patch
new file mode 100644 (file)
index 0000000..cd65c13
--- /dev/null
@@ -0,0 +1,24 @@
+--- a/tools/image-host.c
++++ b/tools/image-host.c
+@@ -1125,6 +1125,7 @@ static int fit_config_add_verification_d
+  * 2) get public key (X509_get_pubkey)
+  * 3) provide der format (d2i_RSAPublicKey)
+  */
++#ifdef CONFIG_TOOLS_LIBCRYPTO
+ static int read_pub_key(const char *keydir, const void *name,
+                       unsigned char **pubkey, int *pubkey_len)
+ {
+@@ -1178,6 +1179,13 @@ err_cert:
+       fclose(f);
+       return ret;
+ }
++#else
++static int read_pub_key(const char *keydir, const void *name,
++                      unsigned char **pubkey, int *pubkey_len)
++{
++      return -ENOSYS;
++}
++#endif
+ int fit_pre_load_data(const char *keydir, void *keydest, void *fit)
+ {
diff --git a/package/boot/uboot-cv18x0/patches/200-add-BL33-on-milkvduo.patch b/package/boot/uboot-cv18x0/patches/200-add-BL33-on-milkvduo.patch
new file mode 100644 (file)
index 0000000..ae08fc5
--- /dev/null
@@ -0,0 +1,53 @@
+diff -ruN u-boot-2024-05-13.old/arch/riscv/cpu/start.S u-boot-2024-05-13/arch/riscv/cpu/start.S
+--- u-boot-2024-05-13.old/arch/riscv/cpu/start.S       2024-05-13 17:15:46.000000000 +0200
++++ u-boot-2024-05-13/arch/riscv/cpu/start.S   2024-05-14 11:31:51.924686607 +0200
+@@ -39,6 +39,10 @@
+ .section .text
+ .globl _start
+ _start:
++#if CONFIG_IS_ENABLED(TARGET_MILKV_DUO)
++#include <asm/boot0.h>
++#endif
++_start_real:
+ #if CONFIG_IS_ENABLED(RISCV_MMODE)
+       csrr    a0, CSR_MHARTID
+ #endif
+diff -ruN u-boot-2024-05-13.old/arch/riscv/include/asm/boot0.h u-boot-2024-05-13/arch/riscv/include/asm/boot0.h
+--- u-boot-2024-05-13.old/arch/riscv/include/asm/boot0.h       1970-01-01 01:00:00.000000000 +0100
++++ u-boot-2024-05-13/arch/riscv/include/asm/boot0.h   2024-04-30 23:23:20.728599523 +0200
+@@ -0,0 +1,35 @@
++/* SPDX-License-Identifier: GPL-2.0 */
++/*
++ * CVITEK u-boot header
++ */
++
++#ifndef __BOOT0_H__
++#define __BOOT0_H__
++
++/* BOOT0 header information */
++      j boot0_time_recode
++      .balign 4
++      .word 0x33334c42  /* b'BL33' */
++      .word 0xdeadbeea  /* CKSUM */
++      .word 0xdeadbeeb  /* SIZE */
++#ifdef CONFIG_SPL_BUILD
++      .quad   CONFIG_TEXT_BASE
++#else
++      .quad   CONFIG_TEXT_BASE
++#endif
++      .word 0xdeadbeec
++      .balign 4
++      j boot0_time_recode
++      .balign 4
++/* BOOT0 header end */
++boot0_time_recode:
++      csrr x1, time
++      la x2, BOOT0_START_TIME
++      sw x1, 0(x2)
++      j _start_real
++
++      .global BOOT0_START_TIME
++BOOT0_START_TIME:
++      .word 0
++
++#endif /* __BOOT0_H__ */
diff --git a/package/boot/uboot-cv18x0/uEnv-default.txt b/package/boot/uboot-cv18x0/uEnv-default.txt
new file mode 100644 (file)
index 0000000..8468a3c
--- /dev/null
@@ -0,0 +1,5 @@
+setenv loadkernel fatload mmc 0:3 \$kernel_addr_r Image
+setenv loaddtb fatload mmc 0:3 \$fdt_addr_r dtb
+setenv bootargs console=ttySIF0,115200 earlycon=sbi root=/dev/mmcblk0p4 rootwait
+setenv uenvcmd run loadkernel \&\& run loaddtb \&\& booti \$kernel_addr_r - \$fdt_addr_r
+run uenvcmd
diff --git a/target/linux/cv18x0/Makefile b/target/linux/cv18x0/Makefile
new file mode 100644 (file)
index 0000000..9a75746
--- /dev/null
@@ -0,0 +1,22 @@
+# SPDX-License-Identifier: GPL-2.0-only
+#
+# Copyright (C) 2024 Toco Technologies <info@toco.ae>
+#
+include $(TOPDIR)/rules.mk
+
+ARCH:=riscv64
+BOARD:=cv18x0
+BOARDNAME:=Cvitek CV180x boards
+FEATURES:=ext4
+KERNELNAME:=Image dtbs
+SUBTARGETS:=generic
+
+KERNEL_PATCHVER:=6.6
+
+include $(INCLUDE_DIR)/target.mk
+
+define Target/Description
+       Build firmware images for the Cvitek CV1800/1810 boards
+endef
+
+$(eval $(call BuildTarget))
diff --git a/target/linux/cv18x0/base-files/etc/board.d/01_leds b/target/linux/cv18x0/base-files/etc/board.d/01_leds
new file mode 100644 (file)
index 0000000..5610a79
--- /dev/null
@@ -0,0 +1,21 @@
+# SPDX-License-Identifier: GPL-2.0-only
+#
+# Copyright (C) 2022 OpenWrt.org
+#
+
+. /lib/functions/uci-defaults.sh
+
+board_config_update
+
+case "$(board_name)" in
+sifive,hifive-unleashed-a00)
+       ucidef_set_led_netdev "lan" "LAN" "green:d3" "eth0"
+       ;;
+sifive,hifive-unmatched-a00)
+       ucidef_set_led_netdev "lan" "LAN" "green:d2" "eth0"
+       ;;
+esac
+
+board_config_flush
+
+exit 0
diff --git a/target/linux/cv18x0/base-files/etc/board.d/02_network b/target/linux/cv18x0/base-files/etc/board.d/02_network
new file mode 100644 (file)
index 0000000..ca9f7f2
--- /dev/null
@@ -0,0 +1,18 @@
+# SPDX-License-Identifier: GPL-2.0-only
+#
+# Copyright (C) 2022 OpenWrt.org
+#
+
+. /lib/functions/uci-defaults.sh
+
+board_config_update
+
+case "$(board_name)" in
+*)
+       ucidef_set_interface_lan 'eth0'
+       ;;
+esac
+
+board_config_flush
+
+exit 0
diff --git a/target/linux/cv18x0/base-files/etc/inittab b/target/linux/cv18x0/base-files/etc/inittab
new file mode 100644 (file)
index 0000000..d1b5a0f
--- /dev/null
@@ -0,0 +1,4 @@
+::sysinit:/etc/init.d/rcS S boot
+::shutdown:/etc/init.d/rcS K shutdown
+ttyS0::askfirst:/usr/libexec/login.sh
+tty1::askfirst:/usr/libexec/login.sh
diff --git a/target/linux/cv18x0/base-files/lib/preinit/79_move_config b/target/linux/cv18x0/base-files/lib/preinit/79_move_config
new file mode 100644 (file)
index 0000000..2796c4d
--- /dev/null
@@ -0,0 +1,19 @@
+# Copyright (C) 2012-2015 OpenWrt.org
+
+move_config() {
+       local partdev
+
+       . /lib/upgrade/common.sh
+
+       if export_bootdevice && export_partdevice partdev 3; then
+               if mount -t vfat -o rw,noatime "/dev/$partdev" /mnt; then
+                       if [ -f "/mnt/$BACKUP_FILE" ]; then
+                               mv -f "/mnt/$BACKUP_FILE" /
+                       fi
+                       umount /mnt
+               fi
+       fi
+}
+
+boot_hook_add preinit_mount_root move_config
+
diff --git a/target/linux/cv18x0/base-files/lib/upgrade/platform.sh b/target/linux/cv18x0/base-files/lib/upgrade/platform.sh
new file mode 100644 (file)
index 0000000..b5f6bad
--- /dev/null
@@ -0,0 +1,86 @@
+platform_check_image() {
+       local diskdev partdev diff
+
+       export_bootdevice && export_partdevice diskdev 0 || {
+               echo "Unable to determine upgrade device"
+               return 1
+       }
+
+       get_partitions "/dev/$diskdev" bootdisk
+
+       #extract the boot sector from the image
+       get_image "$@" | dd of=/tmp/image.bs count=1 bs=512b 2>/dev/null
+
+       get_partitions /tmp/image.bs image
+
+       #compare tables
+       diff="$(grep -F -x -v -f /tmp/partmap.bootdisk /tmp/partmap.image)"
+
+       rm -f /tmp/image.bs /tmp/partmap.bootdisk /tmp/partmap.image
+
+       if [ -n "$diff" ]; then
+               echo "Partition layout has changed. Full image will be written."
+               ask_bool 0 "Abort" && exit 1
+               return 0
+       fi
+}
+
+platform_copy_config() {
+       local partdev
+
+       if export_partdevice partdev 3; then
+               mount -t vfat -o rw,noatime "/dev/$partdev" /mnt
+               cp -af "$UPGRADE_BACKUP" "/mnt/$BACKUP_FILE"
+               umount /mnt
+       fi
+}
+
+platform_do_upgrade() {
+       local diskdev partdev diff
+
+       export_bootdevice && export_partdevice diskdev 0 || {
+               echo "Unable to determine upgrade device"
+               return 1
+       }
+
+       sync
+
+       if [ "$UPGRADE_OPT_SAVE_PARTITIONS" = "1" ]; then
+               get_partitions "/dev/$diskdev" bootdisk
+
+               #extract the boot sector from the image
+               get_image "$@" | dd of=/tmp/image.bs count=1 bs=512b
+
+               get_partitions /tmp/image.bs image
+
+               #compare tables
+               diff="$(grep -F -x -v -f /tmp/partmap.bootdisk /tmp/partmap.image)"
+       else
+               diff=1
+       fi
+
+       if [ -n "$diff" ]; then
+               get_image "$@" | dd of="/dev/$diskdev" bs=4096 conv=fsync
+
+               # Separate removal and addtion is necessary; otherwise, partition 1
+               # will be missing if it overlaps with the old partition 2
+               partx -d - "/dev/$diskdev"
+               partx -a - "/dev/$diskdev"
+
+               return 0
+       fi
+
+       #iterate over each partition from the image and write it to the boot disk
+       while read part start size; do
+               if export_partdevice partdev $part; then
+                       echo "Writing image to /dev/$partdev..."
+                       get_image "$@" | dd of="/dev/$partdev" ibs="512" obs=1M skip="$start" count="$size" conv=fsync
+               else
+                       echo "Unable to find partition $part device, skipped."
+               fi
+       done < /tmp/partmap.image
+
+       #copy partition uuid
+       echo "Writing new UUID to /dev/$diskdev..."
+       get_image "$@" | dd of="/dev/$diskdev" bs=1 skip=440 count=4 seek=440 conv=fsync
+}
diff --git a/target/linux/cv18x0/config-6.6 b/target/linux/cv18x0/config-6.6
new file mode 100644 (file)
index 0000000..2a28e4e
--- /dev/null
@@ -0,0 +1,392 @@
+CONFIG_64BIT=y
+# CONFIG_ACPI is not set
+CONFIG_ARCH_CLOCKSOURCE_INIT=y
+CONFIG_ARCH_DMA_ADDR_T_64BIT=y
+CONFIG_ARCH_MMAP_RND_BITS=18
+CONFIG_ARCH_MMAP_RND_BITS_MAX=24
+CONFIG_ARCH_MMAP_RND_BITS_MIN=18
+CONFIG_ARCH_MMAP_RND_COMPAT_BITS_MAX=17
+CONFIG_ARCH_OPTIONAL_KERNEL_RWX=y
+CONFIG_ARCH_OPTIONAL_KERNEL_RWX_DEFAULT=y
+CONFIG_ARCH_RV64I=y
+CONFIG_ARCH_SELECT_MEMORY_MODEL=y
+CONFIG_ARCH_SOPHGO=y
+CONFIG_ARCH_SPARSEMEM_ENABLE=y
+CONFIG_ARCH_STACKWALK=y
+CONFIG_ARCH_THEAD=y
+CONFIG_ARCH_WANTS_THP_SWAP=y
+CONFIG_ASN1=y
+CONFIG_ASSOCIATIVE_ARRAY=y
+CONFIG_ATA=y
+CONFIG_ATA_VERBOSE_ERROR=y
+# CONFIG_AX45MP_L2_CACHE is not set
+CONFIG_BLK_DEV_SD=y
+CONFIG_BLK_MQ_PCI=y
+CONFIG_CAVIUM_PTP=y
+CONFIG_CC_HAVE_STACKPROTECTOR_TLS=y
+CONFIG_CC_IMPLICIT_FALLTHROUGH="-Wimplicit-fallthrough=5"
+CONFIG_CC_NO_ARRAY_BOUNDS=y
+CONFIG_CLONE_BACKWARDS=y
+CONFIG_CLK_SOPHGO_CV1800=y
+CONFIG_CLZ_TAB=y
+CONFIG_CMODEL_MEDANY=y
+# CONFIG_CMODEL_MEDLOW is not set
+CONFIG_COMMON_CLK=y
+CONFIG_COMPACT_UNEVICTABLE_DEFAULT=1
+# CONFIG_COMPAT_32BIT_TIME is not set
+CONFIG_COMPAT_BRK=y
+CONFIG_CONSOLE_TRANSLATIONS=y
+CONFIG_CONTEXT_TRACKING=y
+CONFIG_CONTEXT_TRACKING_IDLE=y
+CONFIG_COREDUMP=y
+CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS=y
+CONFIG_CPU_ISOLATION=y
+CONFIG_CPU_RMAP=y
+CONFIG_CRC16=y
+# CONFIG_CRC32_SARWATE is not set
+CONFIG_CRC32_SLICEBY8=y
+CONFIG_CRC7=y
+CONFIG_CRC_ITU_T=y
+CONFIG_CRYPTO_CRC32C=y
+CONFIG_CRYPTO_DRBG=y
+CONFIG_CRYPTO_DRBG_HMAC=y
+CONFIG_CRYPTO_DRBG_MENU=y
+CONFIG_CRYPTO_ECHAINIV=y
+CONFIG_CRYPTO_HMAC=y
+CONFIG_CRYPTO_JITTERENTROPY=y
+CONFIG_CRYPTO_LIB_BLAKE2S_GENERIC=y
+CONFIG_CRYPTO_LIB_POLY1305_RSIZE=1
+CONFIG_CRYPTO_LIB_SHA1=y
+CONFIG_CRYPTO_LIB_SHA256=y
+CONFIG_CRYPTO_LIB_UTILS=y
+CONFIG_CRYPTO_RNG=y
+CONFIG_CRYPTO_RNG2=y
+CONFIG_CRYPTO_RNG_DEFAULT=y
+CONFIG_CRYPTO_RSA=y
+CONFIG_CRYPTO_SHA256=y
+CONFIG_CRYPTO_SHA512=y
+CONFIG_DEBUG_BUGVERBOSE=y
+CONFIG_DEBUG_INFO=y
+CONFIG_DECOMPRESS_GZIP=y
+CONFIG_DEVTMPFS=y
+CONFIG_DEVTMPFS_MOUNT=y
+# CONFIG_DEVTMPFS_SAFE is not set
+CONFIG_DMA_DIRECT_REMAP=y
+CONFIG_DNOTIFY=y
+CONFIG_DTC=y
+CONFIG_DUMMY_CONSOLE=y
+CONFIG_DW_APB_TIMER=y
+CONFIG_DW_APB_TIMER_OF=y
+CONFIG_DW_WATCHDOG=y
+CONFIG_EDAC=y
+# CONFIG_EDAC_DEBUG is not set
+CONFIG_EDAC_LEGACY_SYSFS=y
+CONFIG_EDAC_SUPPORT=y
+CONFIG_EFI=y
+CONFIG_EFIVAR_FS=m
+# CONFIG_EFI_BOOTLOADER_CONTROL is not set
+# CONFIG_EFI_CAPSULE_LOADER is not set
+# CONFIG_EFI_COCO_SECRET is not set
+# CONFIG_EFI_DISABLE_PCI_DMA is not set
+# CONFIG_EFI_DISABLE_RUNTIME is not set
+CONFIG_EFI_EARLYCON=y
+CONFIG_EFI_ESRT=y
+CONFIG_EFI_GENERIC_STUB=y
+CONFIG_EFI_PARAMS_FROM_FDT=y
+CONFIG_EFI_RUNTIME_WRAPPERS=y
+CONFIG_EFI_STUB=y
+# CONFIG_EFI_TEST is not set
+# CONFIG_EFI_ZBOOT is not set
+CONFIG_ELF_CORE=y
+# CONFIG_ERRATA_ANDES is not set
+CONFIG_ERRATA_SIFIVE=y
+CONFIG_ERRATA_SIFIVE_CIP_1200=y
+CONFIG_ERRATA_SIFIVE_CIP_453=y
+CONFIG_ERRATA_THEAD=y
+CONFIG_ERRATA_THEAD_PBMT=y
+CONFIG_ERRATA_THEAD_CMO=y
+CONFIG_EXCLUSIVE_SYSTEM_RAM=y
+CONFIG_EXT4_FS=y
+CONFIG_FAILOVER=y
+CONFIG_FAT_FS=y
+CONFIG_FHANDLE=y
+CONFIG_FIXED_PHY=y
+CONFIG_FIX_EARLYCON_MEM=y
+CONFIG_FONT_8x16=y
+CONFIG_FONT_AUTOSELECT=y
+CONFIG_FONT_SUPPORT=y
+CONFIG_FPU=y
+CONFIG_FRAME_POINTER=y
+CONFIG_FS_IOMAP=y
+CONFIG_FS_MBCACHE=y
+CONFIG_FWNODE_MDIO=y
+CONFIG_FW_LOADER_PAGED_BUF=y
+CONFIG_FW_LOADER_SYSFS=y
+CONFIG_GCC11_NO_ARRAY_BOUNDS=y
+CONFIG_GENERIC_ALLOCATOR=y
+CONFIG_GENERIC_ARCH_TOPOLOGY=y
+CONFIG_GENERIC_BUG=y
+CONFIG_GENERIC_BUG_RELATIVE_POINTERS=y
+CONFIG_GENERIC_CLOCKEVENTS=y
+CONFIG_GENERIC_CLOCKEVENTS_BROADCAST=y
+CONFIG_GENERIC_CSUM=y
+CONFIG_GENERIC_EARLY_IOREMAP=y
+CONFIG_GENERIC_GETTIMEOFDAY=y
+CONFIG_GENERIC_IDLE_POLL_SETUP=y
+CONFIG_GENERIC_IOREMAP=y
+CONFIG_GENERIC_IRQ_EFFECTIVE_AFF_MASK=y
+CONFIG_GENERIC_IRQ_INJECTION=y
+CONFIG_GENERIC_IRQ_MULTI_HANDLER=y
+CONFIG_GENERIC_IRQ_SHOW=y
+CONFIG_GENERIC_IRQ_SHOW_LEVEL=y
+CONFIG_GENERIC_LIB_DEVMEM_IS_ALLOWED=y
+CONFIG_GENERIC_MSI_IRQ=y
+CONFIG_GENERIC_MSI_IRQ_DOMAIN=y
+CONFIG_GENERIC_PCI_IOMAP=y
+CONFIG_GENERIC_SCHED_CLOCK=y
+CONFIG_GENERIC_SMP_IDLE_THREAD=y
+CONFIG_GENERIC_STRNCPY_FROM_USER=y
+CONFIG_GENERIC_STRNLEN_USER=y
+CONFIG_GENERIC_TIME_VSYSCALL=y
+CONFIG_GLOB=y
+CONFIG_GPIOLIB_IRQCHIP=y
+CONFIG_GPIO_CDEV=y
+CONFIG_GPIO_CDEV_V1=y
+CONFIG_GPIO_DWAPB=y
+CONFIG_GPIO_GENERIC=y
+CONFIG_GPIO_SIFIVE=y
+CONFIG_HARDIRQS_SW_RESEND=y
+CONFIG_HAS_DMA=y
+CONFIG_HAS_IOMEM=y
+CONFIG_HAS_IOPORT_MAP=y
+CONFIG_HID=y
+CONFIG_HID_GENERIC=y
+CONFIG_HOTPLUG_PCI=y
+# CONFIG_HOTPLUG_PCI_CPCI is not set
+CONFIG_HOTPLUG_PCI_PCIE=y
+CONFIG_HOTPLUG_PCI_SHPC=y
+CONFIG_HVC_DRIVER=y
+CONFIG_HVC_RISCV_SBI=y
+CONFIG_HW_CONSOLE=y
+CONFIG_HZ_PERIODIC=y
+CONFIG_I2C=y
+CONFIG_I2C_BOARDINFO=y
+CONFIG_I2C_COMPAT=y
+CONFIG_I2C_HELPER_AUTO=y
+CONFIG_I2C_OCORES=y
+CONFIG_INITRAMFS_SOURCE=""
+CONFIG_INPUT=y
+# CONFIG_IOMMU_DEBUGFS is not set
+# CONFIG_IOMMUFD is not set
+CONFIG_IOMMU_SUPPORT=y
+CONFIG_IO_URING=y
+CONFIG_IRQ_STACKS=y
+CONFIG_IRQCHIP=y
+CONFIG_IRQ_DOMAIN=y
+CONFIG_IRQ_DOMAIN_HIERARCHY=y
+CONFIG_IRQ_FORCED_THREADING=y
+CONFIG_IRQ_WORK=y
+CONFIG_JBD2=y
+CONFIG_KALLSYMS=y
+CONFIG_KEYS=y
+CONFIG_LEDS_PWM=y
+CONFIG_LEDS_TRIGGER_DISK=y
+CONFIG_LEGACY_PTYS=y
+CONFIG_LEGACY_PTY_COUNT=256
+CONFIG_LIBFDT=y
+CONFIG_LOCALVERSION_AUTO=y
+CONFIG_LOCK_DEBUGGING_SUPPORT=y
+CONFIG_LOCK_SPIN_ON_OWNER=y
+CONFIG_MACB=y
+# CONFIG_MACB_PCI is not set
+CONFIG_MACB_USE_HWSTAMP=y
+CONFIG_MDIO_BUS=y
+CONFIG_MDIO_DEVICE=y
+CONFIG_MDIO_DEVRES=y
+CONFIG_MEMFD_CREATE=y
+CONFIG_MFD_SYSCON=y
+CONFIG_MICROSEMI_PHY=y
+CONFIG_MIGRATION=y
+CONFIG_MMC=y
+CONFIG_MMC_BLOCK=y
+CONFIG_MMC_SDHCI=y
+CONFIG_MMC_SDHCI_CADENCE=y
+CONFIG_MMC_SDHCI_CV1800B=y
+CONFIG_MMC_SDHCI_OF_DWCMSHC=y
+# CONFIG_MMC_SDHCI_PCI is not set
+CONFIG_MMC_SDHCI_PLTFM=y
+CONFIG_MMC_SPI=y
+CONFIG_MMIOWB=y
+CONFIG_MODULES_USE_ELF_RELA=y
+CONFIG_MODULE_SECTIONS=y
+CONFIG_MPILIB=y
+CONFIG_MQ_IOSCHED_DEADLINE=y
+CONFIG_MQ_IOSCHED_KYBER=y
+CONFIG_MTD_SPI_NOR=y
+CONFIG_MTD_SPI_NOR_USE_4K_SECTORS=y
+CONFIG_MUTEX_SPIN_ON_OWNER=y
+CONFIG_NEED_DMA_MAP_STATE=y
+CONFIG_NET_FAILOVER=y
+CONFIG_NET_FLOW_LIMIT=y
+CONFIG_NET_PTP_CLASSIFY=y
+CONFIG_NET_SELFTESTS=y
+CONFIG_NLS=y
+CONFIG_NLS_CODEPAGE_437=y
+CONFIG_NLS_ISO8859_1=y
+# CONFIG_NONPORTABLE is not set
+CONFIG_NR_CPUS=8
+CONFIG_NVMEM=y
+CONFIG_NVMEM_SYSFS=y
+CONFIG_OF=y
+CONFIG_OF_ADDRESS=y
+CONFIG_OF_DMA_DEFAULT_COHERENT=y
+CONFIG_OF_EARLY_FLATTREE=y
+CONFIG_OF_FLATTREE=y
+CONFIG_OF_GPIO=y
+CONFIG_OF_IRQ=y
+CONFIG_OF_KOBJ=y
+CONFIG_OF_MDIO=y
+CONFIG_OID_REGISTRY=y
+CONFIG_PADATA=y
+CONFIG_PAGE_OFFSET=0xff60000000000000
+CONFIG_PAGE_POOL=y
+CONFIG_PAGE_REPORTING=y
+CONFIG_PAGE_SIZE_LESS_THAN_256KB=y
+CONFIG_PAGE_SIZE_LESS_THAN_64KB=y
+CONFIG_PGTABLE_LEVELS=5
+CONFIG_PHYLIB=y
+CONFIG_PHYLINK=y
+CONFIG_PHYS_ADDR_T_64BIT=y
+CONFIG_PORTABLE=y
+CONFIG_POSIX_CPU_TIMERS_TASK_WORK=y
+CONFIG_POWER_RESET=y
+CONFIG_POWER_RESET_GPIO=y
+CONFIG_POWER_RESET_GPIO_RESTART=y
+CONFIG_POWER_RESET_RESTART=y
+CONFIG_POWER_RESET_SOPHGO=y
+CONFIG_POWER_RESET_SYSCON=y
+CONFIG_POWER_RESET_SYSCON_POWEROFF=y
+CONFIG_PPS=y
+CONFIG_PREEMPT_NONE_BUILD=y
+CONFIG_PRINTK_TIME=y
+CONFIG_PTP_1588_CLOCK=y
+CONFIG_PTP_1588_CLOCK_OPTIONAL=y
+CONFIG_PWM=y
+CONFIG_PWM_SIFIVE=y
+CONFIG_PWM_SYSFS=y
+CONFIG_QUEUED_RWLOCKS=y
+CONFIG_RANDSTRUCT_NONE=y
+CONFIG_RAS=y
+CONFIG_RATIONAL=y
+CONFIG_RCU_TRACE=y
+CONFIG_RD_GZIP=y
+CONFIG_REALTEK_PHY=y
+CONFIG_REGMAP=y
+CONFIG_REGMAP_MMIO=y
+# CONFIG_RESET_ATTACK_MITIGATION is not set
+CONFIG_RESET_CONTROLLER=y
+CONFIG_RESET_SIMPLE=y
+CONFIG_RFS_ACCEL=y
+CONFIG_RISCV=y
+CONFIG_RISCV_ALTERNATIVE=y
+# CONFIG_RISCV_BOOT_SPINWAIT is not set
+CONFIG_RISCV_DMA_NONCOHERENT=y
+CONFIG_RISCV_INTC=y
+CONFIG_RISCV_ISA_C=y
+CONFIG_RISCV_ISA_FALLBACK=y
+CONFIG_RISCV_ISA_SVNAPOT=y
+CONFIG_RISCV_ISA_SVPBMT=y
+CONFIG_RISCV_ISA_V=y
+CONFIG_RISCV_ISA_V_DEFAULT_ENABLE=y
+CONFIG_RISCV_ISA_ZBB=y
+CONFIG_RISCV_ISA_ZICBOZ=y
+CONFIG_RISCV_ISA_ZICBOM=y
+CONFIG_RISCV_SBI=y
+CONFIG_RISCV_SBI_V01=y
+CONFIG_RISCV_TIMER=y
+CONFIG_RPS=y
+CONFIG_RTC_CLASS=y
+# CONFIG_RTC_DRV_EFI is not set
+CONFIG_RTC_I2C_AND_SPI=y
+CONFIG_RWSEM_SPIN_ON_OWNER=y
+CONFIG_SCHED_DEBUG=y
+CONFIG_SCSI=y
+CONFIG_SCSI_COMMON=y
+CONFIG_SERIAL_8250_DEPRECATED_OPTIONS=y
+CONFIG_SERIAL_8250_DW=y
+CONFIG_SERIAL_8250_DWLIB=y
+CONFIG_SERIAL_8250_EXAR=y
+CONFIG_SERIAL_8250_NR_UARTS=4
+CONFIG_SERIAL_8250_PCI=y
+CONFIG_SERIAL_8250_RUNTIME_UARTS=4
+CONFIG_SERIAL_EARLYCON_RISCV_SBI=y
+CONFIG_SERIAL_MCTRL_GPIO=y
+CONFIG_SERIAL_OF_PLATFORM=y
+CONFIG_SERIAL_SIFIVE=y
+CONFIG_SERIAL_SIFIVE_CONSOLE=y
+CONFIG_SERIO=y
+CONFIG_SERIO_SERPORT=y
+CONFIG_SG_POOL=y
+CONFIG_SIFIVE_PLIC=y
+CONFIG_SLUB_DEBUG=y
+CONFIG_SMP=y
+CONFIG_SOCK_RX_QUEUE_MAPPING=y
+# CONFIG_SOC_MICROCHIP_POLARFIRE is not set
+# CONFIG_SOC_SIFIVE is not set
+CONFIG_SOC_SOPHGO=y
+# CONFIG_SOC_STARFIVE is not set
+# CONFIG_SOC_VIRT is not set
+CONFIG_SPARSEMEM_VMEMMAP_ENABLE=y
+CONFIG_SPARSE_IRQ=y
+CONFIG_SPI=y
+CONFIG_SPI_BITBANG=y
+CONFIG_SPI_MASTER=y
+CONFIG_SPI_MEM=y
+CONFIG_SPI_SIFIVE=y
+CONFIG_SRCU=y
+CONFIG_STACKDEPOT=y
+CONFIG_STACKTRACE=y
+CONFIG_SWIOTLB=y
+CONFIG_SWPHY=y
+CONFIG_SYSCTL_EXCEPTION_TRACE=y
+# CONFIG_SYSFB_SIMPLEFB is not set
+CONFIG_THREAD_INFO_IN_TASK=y
+CONFIG_THREAD_SIZE_ORDER=2
+CONFIG_TICK_CPU_ACCOUNTING=y
+CONFIG_TIMER_OF=y
+CONFIG_TIMER_PROBE=y
+CONFIG_TOOLCHAIN_HAS_ZICBOM=y
+CONFIG_TOOLCHAIN_HAS_ZIHINTPAUSE=y
+CONFIG_TOOLCHAIN_NEEDS_EXPLICIT_ZICSR_ZIFENCEI=y
+CONFIG_TRACE_CLOCK=y
+CONFIG_TREE_RCU=y
+CONFIG_TREE_SRCU=y
+CONFIG_TUNE_GENERIC=y
+CONFIG_UCS2_STRING=y
+CONFIG_UEVENT_HELPER_PATH=""
+CONFIG_USB=y
+CONFIG_USB_COMMON=y
+CONFIG_USB_EHCI_HCD=y
+# CONFIG_USB_EHCI_HCD_PLATFORM is not set
+CONFIG_USB_EHCI_PCI=y
+CONFIG_USB_HID=y
+CONFIG_USB_NET_DRIVERS=y
+CONFIG_USB_PCI=y
+CONFIG_USB_STORAGE=y
+CONFIG_USB_SUPPORT=y
+# CONFIG_USB_UHCI_HCD is not set
+CONFIG_USB_XHCI_HCD=y
+CONFIG_USB_XHCI_PCI=y
+# CONFIG_USB_XHCI_PLATFORM is not set
+CONFIG_VFAT_FS=y
+CONFIG_VGA_ARB=y
+CONFIG_VGA_ARB_MAX_GPUS=16
+CONFIG_VMAP_STACK=y
+CONFIG_VM_EVENT_COUNTERS=y
+CONFIG_VT=y
+CONFIG_VT_CONSOLE=y
+# CONFIG_VT_HW_CONSOLE_BINDING is not set
+CONFIG_WATCHDOG_CORE=y
+CONFIG_XPS=y
+CONFIG_ZLIB_INFLATE=y
+CONFIG_ZONE_DMA32=y
diff --git a/target/linux/cv18x0/generic/target.mk b/target/linux/cv18x0/generic/target.mk
new file mode 100644 (file)
index 0000000..f5cb1fb
--- /dev/null
@@ -0,0 +1 @@
+BOARDNAME:=Generic
diff --git a/target/linux/cv18x0/image/Config.in b/target/linux/cv18x0/image/Config.in
new file mode 100644 (file)
index 0000000..1d88edc
--- /dev/null
@@ -0,0 +1,4 @@
+config CV18X0_SD_BOOT_PARTSIZE
+       int "Boot (SD Card) filesystem partition size (in MB)"
+       depends on TARGET_cv18x0
+       default 32
diff --git a/target/linux/cv18x0/image/Makefile b/target/linux/cv18x0/image/Makefile
new file mode 100644 (file)
index 0000000..d3ec852
--- /dev/null
@@ -0,0 +1,62 @@
+# SPDX-License-Identifier: GPL-2.0-only
+#
+# Copyright (C) 2024 Toco Technologies <info@toco.ae>
+#
+include $(TOPDIR)/rules.mk
+include $(INCLUDE_DIR)/image.mk
+
+FAT32_BLOCK_SIZE=1024
+FAT32_BLOCKS=$(shell echo $$(($(CONFIG_CV18X0_SD_BOOT_PARTSIZE)*1024*1024/$(FAT32_BLOCK_SIZE))))
+
+KERNEL_LOADADDR:=0x80200000
+
+define Build/riscv-sdcard
+       rm -f $@.boot #$(KDIR_TMP)/$(IMG_PREFIX)-$(PROFILE)-boot.img
+       mkfs.fat $@.boot  -C $(FAT32_BLOCKS)
+
+       $(STAGING_DIR_HOST)/bin/fiptool --fsbl $(STAGING_DIR_IMAGE)/bl2_cv1800b_milkv_duo_sd.bin \
+               --opensbi $(STAGING_DIR_IMAGE)/fw_dynamic-generic.bin \
+               --uboot $(STAGING_DIR_IMAGE)/$(UBOOT)-u-boot.bin \
+               --ddr_param $(STAGING_DIR_IMAGE)/$(DDRPARAM) \
+               --rtos /dev/null \
+               $(STAGING_DIR_IMAGE)/fip_milkv_duo.bin
+
+       mcopy -i $@.boot $(STAGING_DIR_IMAGE)/fip_milkv_duo.bin ::fip.bin
+       mcopy -i $@.boot $(IMAGE_KERNEL) ::sd.boot
+
+       ./gen_cv18x0_sdcard_img.sh \
+               $@ \
+               $@.boot \
+               $(IMAGE_ROOTFS) \
+               $(CONFIG_CV18X0_SD_BOOT_PARTSIZE) \
+               $(CONFIG_TARGET_ROOTFS_PARTSIZE)
+endef
+
+define Device/Default
+  PROFILES := Default
+  KERNEL_NAME := Image
+  DTS_DIR := $(DTS_DIR)/sophgo
+  DEVICE_DTS := $$(SOC)-$(subst _,-,$(1))
+  IMAGES := sdcard.img.gz
+  IMAGE/sdcard.img.gz := riscv-sdcard | append-metadata | gzip
+endef
+
+define Device/FitImageLzma
+       KERNEL_SUFFIX := -fit-uImage.itb
+       KERNEL = kernel-bin | lzma | fit lzma $$(DTS_DIR)/$$(DEVICE_DTS).dtb
+       KERNEL_NAME := Image
+endef
+
+define Device/milkv_duo
+  $(call Device/FitImageLzma)
+  DEVICE_VENDOR := MilkV
+  DEVICE_MODEL := Duo
+  SOC := cv1800b
+  DEVICE_DTS := $$(SOC)-milkv-duo
+  DEVICE_PACKAGES := opensbi_generic
+  UBOOT := milkv_duo
+  DDRPARAM := cv181x_ddr_param.bin
+endef
+TARGET_DEVICES += milkv_duo
+
+$(eval $(call BuildImage))
diff --git a/target/linux/cv18x0/image/gen_cv18x0_sdcard_img.sh b/target/linux/cv18x0/image/gen_cv18x0_sdcard_img.sh
new file mode 100755 (executable)
index 0000000..cc78043
--- /dev/null
@@ -0,0 +1,28 @@
+#!/usr/bin/env bash
+# SPDX-License-Identifier: GPL-2.0-only
+#
+# Copyright (C) 2022 OpenWrt.org
+#
+
+set -ex
+[ $# -eq 5 ] || {
+    echo "SYNTAX: $0 <file> <bootfs image> <rootfs image> <bootfs size> <rootfs size>"
+    exit 1
+}
+
+OUTPUT="$1"
+BOOTFS="$2"
+ROOTFS="$3"
+BOOTFSSIZE="$4"
+ROOTFSSIZE="$5"
+
+head=4
+sect=63
+
+set $(ptgen -o $OUTPUT -h $head -s $sect -l 1024 -t c -p ${BOOTFSSIZE}M -t 83 -p ${ROOTFSSIZE}M)
+
+BOOTOFFSET=$(($1 / 512 ))
+ROOTFSOFFSET=$(($3 / 512))
+
+dd bs=512 if="$BOOTFS" of="$OUTPUT" seek=${BOOTOFFSET} conv=notrunc
+dd bs=512 if="$ROOTFS" of="$OUTPUT" seek=${ROOTFSOFFSET} conv=notrunc
diff --git a/target/linux/cv18x0/patches-6.6/0001-riscv-Add-Sophgo-SoC-platform-hardware-support.patch b/target/linux/cv18x0/patches-6.6/0001-riscv-Add-Sophgo-SoC-platform-hardware-support.patch
new file mode 100644 (file)
index 0000000..355cd0a
--- /dev/null
@@ -0,0 +1,30 @@
+From 28ecd3215ebc6271584f3b7b186223cb30f6b05b Mon Sep 17 00:00:00 2001
+From: Xiaoguang Xing <xiaoguang.xing@sophgo.com>
+Date: Thu, 31 Aug 2023 10:21:03 +0800
+Subject: [PATCH 01/18] riscv: Add Sophgo SoC platform hardware support
+
+Signed-off-by: Xiaoguang Xing <xiaoguang.xing@sophgo.com>
+---
+ arch/riscv/Kconfig.socs | 8 ++++++++
+ 1 file changed, 8 insertions(+)
+
+diff --git a/arch/riscv/Kconfig.socs b/arch/riscv/Kconfig.socs
+index 30fd6a512828..ad7e01a959e5 100644
+--- a/arch/riscv/Kconfig.socs
++++ b/arch/riscv/Kconfig.socs
+@@ -111,4 +111,12 @@ config SOC_CANAAN_K210_DTB_SOURCE
+ endif # ARCH_CANAAN
++config ARCH_SOPHGO
++      def_bool SOC_SOPHGO
++
++config SOC_SOPHGO
++      bool "Sophgo SoCs"
++      help
++        This enables support for Sophgo SoC platform hardware.
++
+ endmenu # "SoC selection"
+-- 
+2.20.1
+
diff --git a/target/linux/cv18x0/patches-6.6/0002-riscv-dts-sophgo-add-initial-CV1800B-SoC-device-tree.patch b/target/linux/cv18x0/patches-6.6/0002-riscv-dts-sophgo-add-initial-CV1800B-SoC-device-tree.patch
new file mode 100644 (file)
index 0000000..658e0b8
--- /dev/null
@@ -0,0 +1,147 @@
+From 53b8b80fdc210e7722f8ffd41bdfbcc0f5aea574 Mon Sep 17 00:00:00 2001
+From: Jisheng Zhang <jszhang@kernel.org>
+Date: Fri, 6 Oct 2023 20:14:48 +0800
+Subject: [PATCH 02/18] riscv: dts: sophgo: add initial CV1800B SoC device tree
+
+Add initial device tree for the CV1800B RISC-V SoC by SOPHGO.
+
+Signed-off-by: Jisheng Zhang <jszhang@kernel.org>
+Acked-by: Chen Wang <unicorn_wang@outlook.com>
+Signed-off-by: Conor Dooley <conor.dooley@microchip.com>
+---
+ arch/riscv/boot/dts/sophgo/cv1800b.dtsi | 123 ++++++++++++++++++++++++
+ 1 file changed, 123 insertions(+)
+ create mode 100644 arch/riscv/boot/dts/sophgo/cv1800b.dtsi
+
+diff --git a/arch/riscv/boot/dts/sophgo/cv1800b.dtsi b/arch/riscv/boot/dts/sophgo/cv1800b.dtsi
+new file mode 100644
+index 000000000000..df40e87ee063
+--- /dev/null
++++ b/arch/riscv/boot/dts/sophgo/cv1800b.dtsi
+@@ -0,0 +1,123 @@
++// SPDX-License-Identifier: (GPL-2.0 OR MIT)
++/*
++ * Copyright (C) 2023 Jisheng Zhang <jszhang@kernel.org>
++ */
++
++#include <dt-bindings/interrupt-controller/irq.h>
++
++/ {
++      compatible = "sophgo,cv1800b";
++      #address-cells = <1>;
++      #size-cells = <1>;
++
++      cpus: cpus {
++              #address-cells = <1>;
++              #size-cells = <0>;
++              timebase-frequency = <25000000>;
++
++              cpu0: cpu@0 {
++                      compatible = "thead,c906", "riscv";
++                      device_type = "cpu";
++                      reg = <0>;
++                      d-cache-block-size = <64>;
++                      d-cache-sets = <512>;
++                      d-cache-size = <65536>;
++                      i-cache-block-size = <64>;
++                      i-cache-sets = <128>;
++                      i-cache-size = <32768>;
++                      mmu-type = "riscv,sv39";
++                      riscv,isa = "rv64imafdc";
++                      riscv,isa-base = "rv64i";
++                      riscv,isa-extensions = "i", "m", "a", "f", "d", "c", "zicntr", "zicsr",
++                                             "zifencei", "zihpm";
++
++                      cpu0_intc: interrupt-controller {
++                              compatible = "riscv,cpu-intc";
++                              interrupt-controller;
++                              #address-cells = <0>;
++                              #interrupt-cells = <1>;
++                      };
++              };
++      };
++
++      osc: oscillator {
++              compatible = "fixed-clock";
++              clock-output-names = "osc_25m";
++              #clock-cells = <0>;
++      };
++
++      soc {
++              compatible = "simple-bus";
++              interrupt-parent = <&plic>;
++              #address-cells = <1>;
++              #size-cells = <1>;
++              dma-noncoherent;
++              ranges;
++
++              uart0: serial@4140000 {
++                      compatible = "snps,dw-apb-uart";
++                      reg = <0x04140000 0x100>;
++                      interrupts = <44 IRQ_TYPE_LEVEL_HIGH>;
++                      clocks = <&osc>;
++                      reg-shift = <2>;
++                      reg-io-width = <4>;
++                      status = "disabled";
++              };
++
++              uart1: serial@4150000 {
++                      compatible = "snps,dw-apb-uart";
++                      reg = <0x04150000 0x100>;
++                      interrupts = <45 IRQ_TYPE_LEVEL_HIGH>;
++                      clocks = <&osc>;
++                      reg-shift = <2>;
++                      reg-io-width = <4>;
++                      status = "disabled";
++              };
++
++              uart2: serial@4160000 {
++                      compatible = "snps,dw-apb-uart";
++                      reg = <0x04160000 0x100>;
++                      interrupts = <46 IRQ_TYPE_LEVEL_HIGH>;
++                      clocks = <&osc>;
++                      reg-shift = <2>;
++                      reg-io-width = <4>;
++                      status = "disabled";
++              };
++
++              uart3: serial@4170000 {
++                      compatible = "snps,dw-apb-uart";
++                      reg = <0x04170000 0x100>;
++                      interrupts = <47 IRQ_TYPE_LEVEL_HIGH>;
++                      clocks = <&osc>;
++                      reg-shift = <2>;
++                      reg-io-width = <4>;
++                      status = "disabled";
++              };
++
++              uart4: serial@41c0000 {
++                      compatible = "snps,dw-apb-uart";
++                      reg = <0x041c0000 0x100>;
++                      interrupts = <48 IRQ_TYPE_LEVEL_HIGH>;
++                      clocks = <&osc>;
++                      reg-shift = <2>;
++                      reg-io-width = <4>;
++                      status = "disabled";
++              };
++
++              plic: interrupt-controller@70000000 {
++                      compatible = "sophgo,cv1800b-plic", "thead,c900-plic";
++                      reg = <0x70000000 0x4000000>;
++                      interrupts-extended = <&cpu0_intc 11>, <&cpu0_intc 9>;
++                      interrupt-controller;
++                      #address-cells = <0>;
++                      #interrupt-cells = <2>;
++                      riscv,ndev = <101>;
++              };
++
++              clint: timer@74000000 {
++                      compatible = "sophgo,cv1800b-clint", "thead,c900-clint";
++                      reg = <0x74000000 0x10000>;
++                      interrupts-extended = <&cpu0_intc 3>, <&cpu0_intc 7>;
++              };
++      };
++};
+-- 
+2.20.1
+
diff --git a/target/linux/cv18x0/patches-6.6/0003-riscv-dts-add-initial-SOPHGO-SG2042-SoC-device-tree.patch b/target/linux/cv18x0/patches-6.6/0003-riscv-dts-add-initial-SOPHGO-SG2042-SoC-device-tree.patch
new file mode 100644 (file)
index 0000000..4209da9
--- /dev/null
@@ -0,0 +1,2232 @@
+From ad6de25748213578dc88100b0a7bf7bec4f44dff Mon Sep 17 00:00:00 2001
+From: Chen Wang <unicornxw@gmail.com>
+Date: Wed, 20 Sep 2023 14:40:32 +0800
+Subject: [PATCH 03/18] riscv: dts: add initial SOPHGO SG2042 SoC device tree
+
+Milk-V Pioneer motherboard is powered by SOPHON's SG2042.
+
+SG2042 is server grade chip with high performance, low power
+consumption and high data throughput.
+Key features:
+- 64 RISC-V cpu cores which implements IMAFDC
+- 4 cores per cluster, 16 clusters on chip
+- ......
+
+More info is available at [1].
+
+[1]: https://en.sophgo.com/product/introduce/sg2042.html
+
+Currently only support booting into console with only uart,
+other features will be added soon later.
+
+Acked-by: Xiaoguang Xing <xiaoguang.xing@sophgo.com>
+Signed-off-by: Xiaoguang Xing <xiaoguang.xing@sophgo.com>
+Signed-off-by: Inochi Amaoto <inochiama@outlook.com>
+Signed-off-by: Emil Renner Berthing <emil.renner.berthing@canonical.com>
+Signed-off-by: Chen Wang <wangchen20@iscas.ac.cn>
+Reviewed-by: Guo Ren <guoren@kernel.org>
+---
+ arch/riscv/boot/dts/sophgo/sg2042-cpus.dtsi | 1744 +++++++++++++++++++
+ arch/riscv/boot/dts/sophgo/sg2042.dtsi      |  439 +++++
+ 2 files changed, 2183 insertions(+)
+ create mode 100644 arch/riscv/boot/dts/sophgo/sg2042-cpus.dtsi
+ create mode 100644 arch/riscv/boot/dts/sophgo/sg2042.dtsi
+
+diff --git a/arch/riscv/boot/dts/sophgo/sg2042-cpus.dtsi b/arch/riscv/boot/dts/sophgo/sg2042-cpus.dtsi
+new file mode 100644
+index 000000000000..9fc79b1cf3bf
+--- /dev/null
++++ b/arch/riscv/boot/dts/sophgo/sg2042-cpus.dtsi
+@@ -0,0 +1,1744 @@
++// SPDX-License-Identifier: GPL-2.0 OR MIT
++/*
++ * Copyright (C) 2022 Sophgo Technology Inc. All rights reserved.
++ */
++
++/ {
++      cpus {
++              #address-cells = <1>;
++              #size-cells = <0>;
++              timebase-frequency = <50000000>;
++
++              cpu-map {
++                      socket0 {
++                              cluster0 {
++                                       core0 {
++                                              cpu = <&cpu0>;
++                                       };
++                                       core1 {
++                                              cpu = <&cpu1>;
++                                       };
++                                       core2 {
++                                              cpu = <&cpu2>;
++                                       };
++                                       core3 {
++                                              cpu = <&cpu3>;
++                                       };
++                              };
++
++                              cluster1 {
++                                       core0 {
++                                              cpu = <&cpu4>;
++                                       };
++                                       core1 {
++                                              cpu = <&cpu5>;
++                                       };
++                                       core2 {
++                                              cpu = <&cpu6>;
++                                       };
++                                       core3 {
++                                              cpu = <&cpu7>;
++                                       };
++                              };
++
++                              cluster2 {
++                                       core0 {
++                                              cpu = <&cpu16>;
++                                       };
++                                       core1 {
++                                              cpu = <&cpu17>;
++                                       };
++                                       core2 {
++                                              cpu = <&cpu18>;
++                                       };
++                                       core3 {
++                                              cpu = <&cpu19>;
++                                       };
++                              };
++
++                              cluster3 {
++                                       core0 {
++                                              cpu = <&cpu20>;
++                                       };
++                                       core1 {
++                                              cpu = <&cpu21>;
++                                       };
++                                       core2 {
++                                              cpu = <&cpu22>;
++                                       };
++                                       core3 {
++                                              cpu = <&cpu23>;
++                                       };
++                              };
++
++                              cluster4 {
++                                       core0 {
++                                              cpu = <&cpu8>;
++                                       };
++                                       core1 {
++                                              cpu = <&cpu9>;
++                                       };
++                                       core2 {
++                                              cpu = <&cpu10>;
++                                       };
++                                       core3 {
++                                              cpu = <&cpu11>;
++                                       };
++                              };
++
++                              cluster5 {
++                                       core0 {
++                                              cpu = <&cpu12>;
++                                       };
++                                       core1 {
++                                              cpu = <&cpu13>;
++                                       };
++                                       core2 {
++                                              cpu = <&cpu14>;
++                                       };
++                                       core3 {
++                                              cpu = <&cpu15>;
++                                       };
++                              };
++
++                              cluster6 {
++                                       core0 {
++                                              cpu = <&cpu24>;
++                                       };
++                                       core1 {
++                                              cpu = <&cpu25>;
++                                       };
++                                       core2 {
++                                              cpu = <&cpu26>;
++                                       };
++                                       core3 {
++                                              cpu = <&cpu27>;
++                                       };
++                              };
++
++                              cluster7 {
++                                       core0 {
++                                              cpu = <&cpu28>;
++                                       };
++                                       core1 {
++                                              cpu = <&cpu29>;
++                                       };
++                                       core2 {
++                                              cpu = <&cpu30>;
++                                       };
++                                       core3 {
++                                              cpu = <&cpu31>;
++                                       };
++                              };
++
++                              cluster8 {
++                                       core0 {
++                                              cpu = <&cpu32>;
++                                       };
++                                       core1 {
++                                              cpu = <&cpu33>;
++                                       };
++                                       core2 {
++                                              cpu = <&cpu34>;
++                                       };
++                                       core3 {
++                                              cpu = <&cpu35>;
++                                       };
++                              };
++
++                              cluster9 {
++                                       core0 {
++                                              cpu = <&cpu36>;
++                                       };
++                                       core1 {
++                                              cpu = <&cpu37>;
++                                       };
++                                       core2 {
++                                              cpu = <&cpu38>;
++                                       };
++                                       core3 {
++                                              cpu = <&cpu39>;
++                                       };
++                              };
++
++                              cluster10 {
++                                       core0 {
++                                              cpu = <&cpu48>;
++                                       };
++                                       core1 {
++                                              cpu = <&cpu49>;
++                                       };
++                                       core2 {
++                                              cpu = <&cpu50>;
++                                       };
++                                       core3 {
++                                              cpu = <&cpu51>;
++                                       };
++                              };
++
++                              cluster11 {
++                                       core0 {
++                                              cpu = <&cpu52>;
++                                       };
++                                       core1 {
++                                              cpu = <&cpu53>;
++                                       };
++                                       core2 {
++                                              cpu = <&cpu54>;
++                                       };
++                                       core3 {
++                                              cpu = <&cpu55>;
++                                       };
++                              };
++
++                              cluster12 {
++                                       core0 {
++                                              cpu = <&cpu40>;
++                                       };
++                                       core1 {
++                                              cpu = <&cpu41>;
++                                       };
++                                       core2 {
++                                              cpu = <&cpu42>;
++                                       };
++                                       core3 {
++                                              cpu = <&cpu43>;
++                                       };
++                              };
++
++                              cluster13 {
++                                       core0 {
++                                              cpu = <&cpu44>;
++                                       };
++                                       core1 {
++                                              cpu = <&cpu45>;
++                                       };
++                                       core2 {
++                                              cpu = <&cpu46>;
++                                       };
++                                       core3 {
++                                              cpu = <&cpu47>;
++                                       };
++                              };
++
++                              cluster14 {
++                                       core0 {
++                                              cpu = <&cpu56>;
++                                       };
++                                       core1 {
++                                              cpu = <&cpu57>;
++                                       };
++                                       core2 {
++                                              cpu = <&cpu58>;
++                                       };
++                                       core3 {
++                                              cpu = <&cpu59>;
++                                       };
++                              };
++
++                              cluster15 {
++                                       core0 {
++                                              cpu = <&cpu60>;
++                                       };
++                                       core1 {
++                                              cpu = <&cpu61>;
++                                       };
++                                       core2 {
++                                              cpu = <&cpu62>;
++                                       };
++                                       core3 {
++                                              cpu = <&cpu63>;
++                                       };
++                              };
++                      };
++              };
++
++              cpu0: cpu@0 {
++                      compatible = "thead,c920", "riscv";
++                      device_type = "cpu";
++                      riscv,isa = "rv64imafdc";
++                      reg = <0>;
++                      i-cache-block-size = <64>;
++                      i-cache-size = <65536>;
++                      i-cache-sets = <512>;
++                      d-cache-block-size = <64>;
++                      d-cache-size = <65536>;
++                      d-cache-sets = <512>;
++                      next-level-cache = <&l2_cache0>;
++                      mmu-type = "riscv,sv39";
++
++                      cpu0_intc: interrupt-controller {
++                              compatible = "riscv,cpu-intc";
++                              interrupt-controller;
++                              #interrupt-cells = <1>;
++                      };
++              };
++
++              cpu1: cpu@1 {
++                      compatible = "thead,c920", "riscv";
++                      device_type = "cpu";
++                      riscv,isa = "rv64imafdc";
++                      reg = <1>;
++                      i-cache-block-size = <64>;
++                      i-cache-size = <65536>;
++                      i-cache-sets = <512>;
++                      d-cache-block-size = <64>;
++                      d-cache-size = <65536>;
++                      d-cache-sets = <512>;
++                      next-level-cache = <&l2_cache0>;
++                      mmu-type = "riscv,sv39";
++
++                      cpu1_intc: interrupt-controller {
++                              compatible = "riscv,cpu-intc";
++                              interrupt-controller;
++                              #interrupt-cells = <1>;
++                      };
++              };
++
++              cpu2: cpu@2 {
++                      compatible = "thead,c920", "riscv";
++                      device_type = "cpu";
++                      riscv,isa = "rv64imafdc";
++                      reg = <2>;
++                      i-cache-block-size = <64>;
++                      i-cache-size = <65536>;
++                      i-cache-sets = <512>;
++                      d-cache-block-size = <64>;
++                      d-cache-size = <65536>;
++                      d-cache-sets = <512>;
++                      next-level-cache = <&l2_cache0>;
++                      mmu-type = "riscv,sv39";
++
++                      cpu2_intc: interrupt-controller {
++                              compatible = "riscv,cpu-intc";
++                              interrupt-controller;
++                              #interrupt-cells = <1>;
++                      };
++              };
++
++              cpu3: cpu@3 {
++                      compatible = "thead,c920", "riscv";
++                      device_type = "cpu";
++                      riscv,isa = "rv64imafdc";
++                      reg = <3>;
++                      i-cache-block-size = <64>;
++                      i-cache-size = <65536>;
++                      i-cache-sets = <512>;
++                      d-cache-block-size = <64>;
++                      d-cache-size = <65536>;
++                      d-cache-sets = <512>;
++                      next-level-cache = <&l2_cache0>;
++                      mmu-type = "riscv,sv39";
++
++                      cpu3_intc: interrupt-controller {
++                              compatible = "riscv,cpu-intc";
++                              interrupt-controller;
++                              #interrupt-cells = <1>;
++                      };
++              };
++
++              cpu4: cpu@4 {
++                      compatible = "thead,c920", "riscv";
++                      device_type = "cpu";
++                      riscv,isa = "rv64imafdc";
++                      reg = <4>;
++                      i-cache-block-size = <64>;
++                      i-cache-size = <65536>;
++                      i-cache-sets = <512>;
++                      d-cache-block-size = <64>;
++                      d-cache-size = <65536>;
++                      d-cache-sets = <512>;
++                      next-level-cache = <&l2_cache1>;
++                      mmu-type = "riscv,sv39";
++
++                      cpu4_intc: interrupt-controller {
++                              compatible = "riscv,cpu-intc";
++                              interrupt-controller;
++                              #interrupt-cells = <1>;
++                      };
++              };
++
++              cpu5: cpu@5 {
++                      compatible = "thead,c920", "riscv";
++                      device_type = "cpu";
++                      riscv,isa = "rv64imafdc";
++                      reg = <5>;
++                      i-cache-block-size = <64>;
++                      i-cache-size = <65536>;
++                      i-cache-sets = <512>;
++                      d-cache-block-size = <64>;
++                      d-cache-size = <65536>;
++                      d-cache-sets = <512>;
++                      next-level-cache = <&l2_cache1>;
++                      mmu-type = "riscv,sv39";
++
++                      cpu5_intc: interrupt-controller {
++                              compatible = "riscv,cpu-intc";
++                              interrupt-controller;
++                              #interrupt-cells = <1>;
++                      };
++              };
++
++              cpu6: cpu@6 {
++                      compatible = "thead,c920", "riscv";
++                      device_type = "cpu";
++                      riscv,isa = "rv64imafdc";
++                      reg = <6>;
++                      i-cache-block-size = <64>;
++                      i-cache-size = <65536>;
++                      i-cache-sets = <512>;
++                      d-cache-block-size = <64>;
++                      d-cache-size = <65536>;
++                      d-cache-sets = <512>;
++                      next-level-cache = <&l2_cache1>;
++                      mmu-type = "riscv,sv39";
++
++                      cpu6_intc: interrupt-controller {
++                              compatible = "riscv,cpu-intc";
++                              interrupt-controller;
++                              #interrupt-cells = <1>;
++                      };
++              };
++
++              cpu7: cpu@7 {
++                      compatible = "thead,c920", "riscv";
++                      device_type = "cpu";
++                      riscv,isa = "rv64imafdc";
++                      reg = <7>;
++                      i-cache-block-size = <64>;
++                      i-cache-size = <65536>;
++                      i-cache-sets = <512>;
++                      d-cache-block-size = <64>;
++                      d-cache-size = <65536>;
++                      d-cache-sets = <512>;
++                      next-level-cache = <&l2_cache1>;
++                      mmu-type = "riscv,sv39";
++
++                      cpu7_intc: interrupt-controller {
++                              compatible = "riscv,cpu-intc";
++                              interrupt-controller;
++                              #interrupt-cells = <1>;
++                      };
++              };
++
++              cpu8: cpu@8 {
++                      compatible = "thead,c920", "riscv";
++                      device_type = "cpu";
++                      riscv,isa = "rv64imafdc";
++                      reg = <8>;
++                      i-cache-block-size = <64>;
++                      i-cache-size = <65536>;
++                      i-cache-sets = <512>;
++                      d-cache-block-size = <64>;
++                      d-cache-size = <65536>;
++                      d-cache-sets = <512>;
++                      next-level-cache = <&l2_cache4>;
++                      mmu-type = "riscv,sv39";
++
++                      cpu8_intc: interrupt-controller {
++                              compatible = "riscv,cpu-intc";
++                              interrupt-controller;
++                              #interrupt-cells = <1>;
++                      };
++              };
++
++              cpu9: cpu@9 {
++                      compatible = "thead,c920", "riscv";
++                      device_type = "cpu";
++                      riscv,isa = "rv64imafdc";
++                      reg = <9>;
++                      i-cache-block-size = <64>;
++                      i-cache-size = <65536>;
++                      i-cache-sets = <512>;
++                      d-cache-block-size = <64>;
++                      d-cache-size = <65536>;
++                      d-cache-sets = <512>;
++                      next-level-cache = <&l2_cache4>;
++                      mmu-type = "riscv,sv39";
++
++                      cpu9_intc: interrupt-controller {
++                              compatible = "riscv,cpu-intc";
++                              interrupt-controller;
++                              #interrupt-cells = <1>;
++                      };
++              };
++
++              cpu10: cpu@10 {
++                      compatible = "thead,c920", "riscv";
++                      device_type = "cpu";
++                      riscv,isa = "rv64imafdc";
++                      reg = <10>;
++                      i-cache-block-size = <64>;
++                      i-cache-size = <65536>;
++                      i-cache-sets = <512>;
++                      d-cache-block-size = <64>;
++                      d-cache-size = <65536>;
++                      d-cache-sets = <512>;
++                      next-level-cache = <&l2_cache4>;
++                      mmu-type = "riscv,sv39";
++
++                      cpu10_intc: interrupt-controller {
++                              compatible = "riscv,cpu-intc";
++                              interrupt-controller;
++                              #interrupt-cells = <1>;
++                      };
++              };
++
++              cpu11: cpu@11 {
++                      compatible = "thead,c920", "riscv";
++                      device_type = "cpu";
++                      riscv,isa = "rv64imafdc";
++                      reg = <11>;
++                      i-cache-block-size = <64>;
++                      i-cache-size = <65536>;
++                      i-cache-sets = <512>;
++                      d-cache-block-size = <64>;
++                      d-cache-size = <65536>;
++                      d-cache-sets = <512>;
++                      next-level-cache = <&l2_cache4>;
++                      mmu-type = "riscv,sv39";
++
++                      cpu11_intc: interrupt-controller {
++                              compatible = "riscv,cpu-intc";
++                              interrupt-controller;
++                              #interrupt-cells = <1>;
++                      };
++              };
++
++              cpu12: cpu@12 {
++                      compatible = "thead,c920", "riscv";
++                      device_type = "cpu";
++                      riscv,isa = "rv64imafdc";
++                      reg = <12>;
++                      i-cache-block-size = <64>;
++                      i-cache-size = <65536>;
++                      i-cache-sets = <512>;
++                      d-cache-block-size = <64>;
++                      d-cache-size = <65536>;
++                      d-cache-sets = <512>;
++                      next-level-cache = <&l2_cache5>;
++                      mmu-type = "riscv,sv39";
++
++                      cpu12_intc: interrupt-controller {
++                              compatible = "riscv,cpu-intc";
++                              interrupt-controller;
++                              #interrupt-cells = <1>;
++                      };
++              };
++
++              cpu13: cpu@13 {
++                      compatible = "thead,c920", "riscv";
++                      device_type = "cpu";
++                      riscv,isa = "rv64imafdc";
++                      reg = <13>;
++                      i-cache-block-size = <64>;
++                      i-cache-size = <65536>;
++                      i-cache-sets = <512>;
++                      d-cache-block-size = <64>;
++                      d-cache-size = <65536>;
++                      d-cache-sets = <512>;
++                      next-level-cache = <&l2_cache5>;
++                      mmu-type = "riscv,sv39";
++
++                      cpu13_intc: interrupt-controller {
++                              compatible = "riscv,cpu-intc";
++                              interrupt-controller;
++                              #interrupt-cells = <1>;
++                      };
++              };
++
++              cpu14: cpu@14 {
++                      compatible = "thead,c920", "riscv";
++                      device_type = "cpu";
++                      riscv,isa = "rv64imafdc";
++                      reg = <14>;
++                      i-cache-block-size = <64>;
++                      i-cache-size = <65536>;
++                      i-cache-sets = <512>;
++                      d-cache-block-size = <64>;
++                      d-cache-size = <65536>;
++                      d-cache-sets = <512>;
++                      next-level-cache = <&l2_cache5>;
++                      mmu-type = "riscv,sv39";
++
++                      cpu14_intc: interrupt-controller {
++                              compatible = "riscv,cpu-intc";
++                              interrupt-controller;
++                              #interrupt-cells = <1>;
++                      };
++              };
++
++              cpu15: cpu@15 {
++                      compatible = "thead,c920", "riscv";
++                      device_type = "cpu";
++                      riscv,isa = "rv64imafdc";
++                      reg = <15>;
++                      i-cache-block-size = <64>;
++                      i-cache-size = <65536>;
++                      i-cache-sets = <512>;
++                      d-cache-block-size = <64>;
++                      d-cache-size = <65536>;
++                      d-cache-sets = <512>;
++                      next-level-cache = <&l2_cache5>;
++                      mmu-type = "riscv,sv39";
++
++                      cpu15_intc: interrupt-controller {
++                              compatible = "riscv,cpu-intc";
++                              interrupt-controller;
++                              #interrupt-cells = <1>;
++                      };
++              };
++
++              cpu16: cpu@16 {
++                      compatible = "thead,c920", "riscv";
++                      device_type = "cpu";
++                      riscv,isa = "rv64imafdc";
++                      reg = <16>;
++                      i-cache-block-size = <64>;
++                      i-cache-size = <65536>;
++                      i-cache-sets = <512>;
++                      d-cache-block-size = <64>;
++                      d-cache-size = <65536>;
++                      d-cache-sets = <512>;
++                      next-level-cache = <&l2_cache2>;
++                      mmu-type = "riscv,sv39";
++
++                      cpu16_intc: interrupt-controller {
++                              compatible = "riscv,cpu-intc";
++                              interrupt-controller;
++                              #interrupt-cells = <1>;
++                      };
++              };
++
++              cpu17: cpu@17 {
++                      compatible = "thead,c920", "riscv";
++                      device_type = "cpu";
++                      riscv,isa = "rv64imafdc";
++                      reg = <17>;
++                      i-cache-block-size = <64>;
++                      i-cache-size = <65536>;
++                      i-cache-sets = <512>;
++                      d-cache-block-size = <64>;
++                      d-cache-size = <65536>;
++                      d-cache-sets = <512>;
++                      next-level-cache = <&l2_cache2>;
++                      mmu-type = "riscv,sv39";
++
++                      cpu17_intc: interrupt-controller {
++                              compatible = "riscv,cpu-intc";
++                              interrupt-controller;
++                              #interrupt-cells = <1>;
++                      };
++              };
++
++              cpu18: cpu@18 {
++                      compatible = "thead,c920", "riscv";
++                      device_type = "cpu";
++                      riscv,isa = "rv64imafdc";
++                      reg = <18>;
++                      i-cache-block-size = <64>;
++                      i-cache-size = <65536>;
++                      i-cache-sets = <512>;
++                      d-cache-block-size = <64>;
++                      d-cache-size = <65536>;
++                      d-cache-sets = <512>;
++                      next-level-cache = <&l2_cache2>;
++                      mmu-type = "riscv,sv39";
++
++                      cpu18_intc: interrupt-controller {
++                              compatible = "riscv,cpu-intc";
++                              interrupt-controller;
++                              #interrupt-cells = <1>;
++                      };
++              };
++
++              cpu19: cpu@19 {
++                      compatible = "thead,c920", "riscv";
++                      device_type = "cpu";
++                      riscv,isa = "rv64imafdc";
++                      reg = <19>;
++                      i-cache-block-size = <64>;
++                      i-cache-size = <65536>;
++                      i-cache-sets = <512>;
++                      d-cache-block-size = <64>;
++                      d-cache-size = <65536>;
++                      d-cache-sets = <512>;
++                      next-level-cache = <&l2_cache2>;
++                      mmu-type = "riscv,sv39";
++
++                      cpu19_intc: interrupt-controller {
++                              compatible = "riscv,cpu-intc";
++                              interrupt-controller;
++                              #interrupt-cells = <1>;
++                      };
++              };
++
++              cpu20: cpu@20 {
++                      compatible = "thead,c920", "riscv";
++                      device_type = "cpu";
++                      riscv,isa = "rv64imafdc";
++                      reg = <20>;
++                      i-cache-block-size = <64>;
++                      i-cache-size = <65536>;
++                      i-cache-sets = <512>;
++                      d-cache-block-size = <64>;
++                      d-cache-size = <65536>;
++                      d-cache-sets = <512>;
++                      next-level-cache = <&l2_cache3>;
++                      mmu-type = "riscv,sv39";
++
++                      cpu20_intc: interrupt-controller {
++                              compatible = "riscv,cpu-intc";
++                              interrupt-controller;
++                              #interrupt-cells = <1>;
++                      };
++              };
++
++              cpu21: cpu@21 {
++                      compatible = "thead,c920", "riscv";
++                      device_type = "cpu";
++                      riscv,isa = "rv64imafdc";
++                      reg = <21>;
++                      i-cache-block-size = <64>;
++                      i-cache-size = <65536>;
++                      i-cache-sets = <512>;
++                      d-cache-block-size = <64>;
++                      d-cache-size = <65536>;
++                      d-cache-sets = <512>;
++                      next-level-cache = <&l2_cache3>;
++                      mmu-type = "riscv,sv39";
++
++                      cpu21_intc: interrupt-controller {
++                              compatible = "riscv,cpu-intc";
++                              interrupt-controller;
++                              #interrupt-cells = <1>;
++                      };
++              };
++
++              cpu22: cpu@22 {
++                      compatible = "thead,c920", "riscv";
++                      device_type = "cpu";
++                      riscv,isa = "rv64imafdc";
++                      reg = <22>;
++                      i-cache-block-size = <64>;
++                      i-cache-size = <65536>;
++                      i-cache-sets = <512>;
++                      d-cache-block-size = <64>;
++                      d-cache-size = <65536>;
++                      d-cache-sets = <512>;
++                      next-level-cache = <&l2_cache3>;
++                      mmu-type = "riscv,sv39";
++
++                      cpu22_intc: interrupt-controller {
++                              compatible = "riscv,cpu-intc";
++                              interrupt-controller;
++                              #interrupt-cells = <1>;
++                      };
++              };
++
++              cpu23: cpu@23 {
++                      compatible = "thead,c920", "riscv";
++                      device_type = "cpu";
++                      riscv,isa = "rv64imafdc";
++                      reg = <23>;
++                      i-cache-block-size = <64>;
++                      i-cache-size = <65536>;
++                      i-cache-sets = <512>;
++                      d-cache-block-size = <64>;
++                      d-cache-size = <65536>;
++                      d-cache-sets = <512>;
++                      next-level-cache = <&l2_cache3>;
++                      mmu-type = "riscv,sv39";
++
++                      cpu23_intc: interrupt-controller {
++                              compatible = "riscv,cpu-intc";
++                              interrupt-controller;
++                              #interrupt-cells = <1>;
++                      };
++              };
++
++              cpu24: cpu@24 {
++                      compatible = "thead,c920", "riscv";
++                      device_type = "cpu";
++                      riscv,isa = "rv64imafdc";
++                      reg = <24>;
++                      i-cache-block-size = <64>;
++                      i-cache-size = <65536>;
++                      i-cache-sets = <512>;
++                      d-cache-block-size = <64>;
++                      d-cache-size = <65536>;
++                      d-cache-sets = <512>;
++                      next-level-cache = <&l2_cache6>;
++                      mmu-type = "riscv,sv39";
++
++                      cpu24_intc: interrupt-controller {
++                              compatible = "riscv,cpu-intc";
++                              interrupt-controller;
++                              #interrupt-cells = <1>;
++                      };
++              };
++
++              cpu25: cpu@25 {
++                      compatible = "thead,c920", "riscv";
++                      device_type = "cpu";
++                      riscv,isa = "rv64imafdc";
++                      reg = <25>;
++                      i-cache-block-size = <64>;
++                      i-cache-size = <65536>;
++                      i-cache-sets = <512>;
++                      d-cache-block-size = <64>;
++                      d-cache-size = <65536>;
++                      d-cache-sets = <512>;
++                      next-level-cache = <&l2_cache6>;
++                      mmu-type = "riscv,sv39";
++
++                      cpu25_intc: interrupt-controller {
++                              compatible = "riscv,cpu-intc";
++                              interrupt-controller;
++                              #interrupt-cells = <1>;
++                      };
++              };
++
++              cpu26: cpu@26 {
++                      compatible = "thead,c920", "riscv";
++                      device_type = "cpu";
++                      riscv,isa = "rv64imafdc";
++                      reg = <26>;
++                      i-cache-block-size = <64>;
++                      i-cache-size = <65536>;
++                      i-cache-sets = <512>;
++                      d-cache-block-size = <64>;
++                      d-cache-size = <65536>;
++                      d-cache-sets = <512>;
++                      next-level-cache = <&l2_cache6>;
++                      mmu-type = "riscv,sv39";
++
++                      cpu26_intc: interrupt-controller {
++                              compatible = "riscv,cpu-intc";
++                              interrupt-controller;
++                              #interrupt-cells = <1>;
++                      };
++              };
++
++              cpu27: cpu@27 {
++                      compatible = "thead,c920", "riscv";
++                      device_type = "cpu";
++                      riscv,isa = "rv64imafdc";
++                      reg = <27>;
++                      i-cache-block-size = <64>;
++                      i-cache-size = <65536>;
++                      i-cache-sets = <512>;
++                      d-cache-block-size = <64>;
++                      d-cache-size = <65536>;
++                      d-cache-sets = <512>;
++                      next-level-cache = <&l2_cache6>;
++                      mmu-type = "riscv,sv39";
++
++                      cpu27_intc: interrupt-controller {
++                              compatible = "riscv,cpu-intc";
++                              interrupt-controller;
++                              #interrupt-cells = <1>;
++                      };
++              };
++
++              cpu28: cpu@28 {
++                      compatible = "thead,c920", "riscv";
++                      device_type = "cpu";
++                      riscv,isa = "rv64imafdc";
++                      reg = <28>;
++                      i-cache-block-size = <64>;
++                      i-cache-size = <65536>;
++                      i-cache-sets = <512>;
++                      d-cache-block-size = <64>;
++                      d-cache-size = <65536>;
++                      d-cache-sets = <512>;
++                      next-level-cache = <&l2_cache7>;
++                      mmu-type = "riscv,sv39";
++
++                      cpu28_intc: interrupt-controller {
++                              compatible = "riscv,cpu-intc";
++                              interrupt-controller;
++                              #interrupt-cells = <1>;
++                      };
++              };
++
++              cpu29: cpu@29 {
++                      compatible = "thead,c920", "riscv";
++                      device_type = "cpu";
++                      riscv,isa = "rv64imafdc";
++                      reg = <29>;
++                      i-cache-block-size = <64>;
++                      i-cache-size = <65536>;
++                      i-cache-sets = <512>;
++                      d-cache-block-size = <64>;
++                      d-cache-size = <65536>;
++                      d-cache-sets = <512>;
++                      next-level-cache = <&l2_cache7>;
++                      mmu-type = "riscv,sv39";
++
++                      cpu29_intc: interrupt-controller {
++                              compatible = "riscv,cpu-intc";
++                              interrupt-controller;
++                              #interrupt-cells = <1>;
++                      };
++              };
++
++              cpu30: cpu@30 {
++                      compatible = "thead,c920", "riscv";
++                      device_type = "cpu";
++                      riscv,isa = "rv64imafdc";
++                      reg = <30>;
++                      i-cache-block-size = <64>;
++                      i-cache-size = <65536>;
++                      i-cache-sets = <512>;
++                      d-cache-block-size = <64>;
++                      d-cache-size = <65536>;
++                      d-cache-sets = <512>;
++                      next-level-cache = <&l2_cache7>;
++                      mmu-type = "riscv,sv39";
++
++                      cpu30_intc: interrupt-controller {
++                              compatible = "riscv,cpu-intc";
++                              interrupt-controller;
++                              #interrupt-cells = <1>;
++                      };
++              };
++
++              cpu31: cpu@31 {
++                      compatible = "thead,c920", "riscv";
++                      device_type = "cpu";
++                      riscv,isa = "rv64imafdc";
++                      reg = <31>;
++                      i-cache-block-size = <64>;
++                      i-cache-size = <65536>;
++                      i-cache-sets = <512>;
++                      d-cache-block-size = <64>;
++                      d-cache-size = <65536>;
++                      d-cache-sets = <512>;
++                      next-level-cache = <&l2_cache7>;
++                      mmu-type = "riscv,sv39";
++
++                      cpu31_intc: interrupt-controller {
++                              compatible = "riscv,cpu-intc";
++                              interrupt-controller;
++                              #interrupt-cells = <1>;
++                      };
++              };
++
++              cpu32: cpu@32 {
++                      compatible = "thead,c920", "riscv";
++                      device_type = "cpu";
++                      riscv,isa = "rv64imafdc";
++                      reg = <32>;
++                      i-cache-block-size = <64>;
++                      i-cache-size = <65536>;
++                      i-cache-sets = <512>;
++                      d-cache-block-size = <64>;
++                      d-cache-size = <65536>;
++                      d-cache-sets = <512>;
++                      next-level-cache = <&l2_cache8>;
++                      mmu-type = "riscv,sv39";
++
++                      cpu32_intc: interrupt-controller {
++                              compatible = "riscv,cpu-intc";
++                              interrupt-controller;
++                              #interrupt-cells = <1>;
++                      };
++              };
++
++              cpu33: cpu@33 {
++                      compatible = "thead,c920", "riscv";
++                      device_type = "cpu";
++                      riscv,isa = "rv64imafdc";
++                      reg = <33>;
++                      i-cache-block-size = <64>;
++                      i-cache-size = <65536>;
++                      i-cache-sets = <512>;
++                      d-cache-block-size = <64>;
++                      d-cache-size = <65536>;
++                      d-cache-sets = <512>;
++                      next-level-cache = <&l2_cache8>;
++                      mmu-type = "riscv,sv39";
++
++                      cpu33_intc: interrupt-controller {
++                              compatible = "riscv,cpu-intc";
++                              interrupt-controller;
++                              #interrupt-cells = <1>;
++                      };
++              };
++
++              cpu34: cpu@34 {
++                      compatible = "thead,c920", "riscv";
++                      device_type = "cpu";
++                      riscv,isa = "rv64imafdc";
++                      reg = <34>;
++                      i-cache-block-size = <64>;
++                      i-cache-size = <65536>;
++                      i-cache-sets = <512>;
++                      d-cache-block-size = <64>;
++                      d-cache-size = <65536>;
++                      d-cache-sets = <512>;
++                      next-level-cache = <&l2_cache8>;
++                      mmu-type = "riscv,sv39";
++
++                      cpu34_intc: interrupt-controller {
++                              compatible = "riscv,cpu-intc";
++                              interrupt-controller;
++                              #interrupt-cells = <1>;
++                      };
++              };
++
++              cpu35: cpu@35 {
++                      compatible = "thead,c920", "riscv";
++                      device_type = "cpu";
++                      riscv,isa = "rv64imafdc";
++                      reg = <35>;
++                      i-cache-block-size = <64>;
++                      i-cache-size = <65536>;
++                      i-cache-sets = <512>;
++                      d-cache-block-size = <64>;
++                      d-cache-size = <65536>;
++                      d-cache-sets = <512>;
++                      next-level-cache = <&l2_cache8>;
++                      mmu-type = "riscv,sv39";
++
++                      cpu35_intc: interrupt-controller {
++                              compatible = "riscv,cpu-intc";
++                              interrupt-controller;
++                              #interrupt-cells = <1>;
++                      };
++              };
++
++              cpu36: cpu@36 {
++                      compatible = "thead,c920", "riscv";
++                      device_type = "cpu";
++                      riscv,isa = "rv64imafdc";
++                      reg = <36>;
++                      i-cache-block-size = <64>;
++                      i-cache-size = <65536>;
++                      i-cache-sets = <512>;
++                      d-cache-block-size = <64>;
++                      d-cache-size = <65536>;
++                      d-cache-sets = <512>;
++                      next-level-cache = <&l2_cache9>;
++                      mmu-type = "riscv,sv39";
++
++                      cpu36_intc: interrupt-controller {
++                              compatible = "riscv,cpu-intc";
++                              interrupt-controller;
++                              #interrupt-cells = <1>;
++                      };
++              };
++
++              cpu37: cpu@37 {
++                      compatible = "thead,c920", "riscv";
++                      device_type = "cpu";
++                      riscv,isa = "rv64imafdc";
++                      reg = <37>;
++                      i-cache-block-size = <64>;
++                      i-cache-size = <65536>;
++                      i-cache-sets = <512>;
++                      d-cache-block-size = <64>;
++                      d-cache-size = <65536>;
++                      d-cache-sets = <512>;
++                      next-level-cache = <&l2_cache9>;
++                      mmu-type = "riscv,sv39";
++
++                      cpu37_intc: interrupt-controller {
++                              compatible = "riscv,cpu-intc";
++                              interrupt-controller;
++                              #interrupt-cells = <1>;
++                      };
++              };
++
++              cpu38: cpu@38 {
++                      compatible = "thead,c920", "riscv";
++                      device_type = "cpu";
++                      riscv,isa = "rv64imafdc";
++                      reg = <38>;
++                      i-cache-block-size = <64>;
++                      i-cache-size = <65536>;
++                      i-cache-sets = <512>;
++                      d-cache-block-size = <64>;
++                      d-cache-size = <65536>;
++                      d-cache-sets = <512>;
++                      next-level-cache = <&l2_cache9>;
++                      mmu-type = "riscv,sv39";
++
++                      cpu38_intc: interrupt-controller {
++                              compatible = "riscv,cpu-intc";
++                              interrupt-controller;
++                              #interrupt-cells = <1>;
++                      };
++              };
++
++              cpu39: cpu@39 {
++                      compatible = "thead,c920", "riscv";
++                      device_type = "cpu";
++                      riscv,isa = "rv64imafdc";
++                      reg = <39>;
++                      i-cache-block-size = <64>;
++                      i-cache-size = <65536>;
++                      i-cache-sets = <512>;
++                      d-cache-block-size = <64>;
++                      d-cache-size = <65536>;
++                      d-cache-sets = <512>;
++                      next-level-cache = <&l2_cache9>;
++                      mmu-type = "riscv,sv39";
++
++                      cpu39_intc: interrupt-controller {
++                              compatible = "riscv,cpu-intc";
++                              interrupt-controller;
++                              #interrupt-cells = <1>;
++                      };
++              };
++
++              cpu40: cpu@40 {
++                      compatible = "thead,c920", "riscv";
++                      device_type = "cpu";
++                      riscv,isa = "rv64imafdc";
++                      reg = <40>;
++                      i-cache-block-size = <64>;
++                      i-cache-size = <65536>;
++                      i-cache-sets = <512>;
++                      d-cache-block-size = <64>;
++                      d-cache-size = <65536>;
++                      d-cache-sets = <512>;
++                      next-level-cache = <&l2_cache12>;
++                      mmu-type = "riscv,sv39";
++
++                      cpu40_intc: interrupt-controller {
++                              compatible = "riscv,cpu-intc";
++                              interrupt-controller;
++                              #interrupt-cells = <1>;
++                      };
++              };
++
++              cpu41: cpu@41 {
++                      compatible = "thead,c920", "riscv";
++                      device_type = "cpu";
++                      riscv,isa = "rv64imafdc";
++                      reg = <41>;
++                      i-cache-block-size = <64>;
++                      i-cache-size = <65536>;
++                      i-cache-sets = <512>;
++                      d-cache-block-size = <64>;
++                      d-cache-size = <65536>;
++                      d-cache-sets = <512>;
++                      next-level-cache = <&l2_cache12>;
++                      mmu-type = "riscv,sv39";
++
++                      cpu41_intc: interrupt-controller {
++                              compatible = "riscv,cpu-intc";
++                              interrupt-controller;
++                              #interrupt-cells = <1>;
++                      };
++              };
++
++              cpu42: cpu@42 {
++                      compatible = "thead,c920", "riscv";
++                      device_type = "cpu";
++                      riscv,isa = "rv64imafdc";
++                      reg = <42>;
++                      i-cache-block-size = <64>;
++                      i-cache-size = <65536>;
++                      i-cache-sets = <512>;
++                      d-cache-block-size = <64>;
++                      d-cache-size = <65536>;
++                      d-cache-sets = <512>;
++                      next-level-cache = <&l2_cache12>;
++                      mmu-type = "riscv,sv39";
++
++                      cpu42_intc: interrupt-controller {
++                              compatible = "riscv,cpu-intc";
++                              interrupt-controller;
++                              #interrupt-cells = <1>;
++                      };
++              };
++
++              cpu43: cpu@43 {
++                      compatible = "thead,c920", "riscv";
++                      device_type = "cpu";
++                      riscv,isa = "rv64imafdc";
++                      reg = <43>;
++                      i-cache-block-size = <64>;
++                      i-cache-size = <65536>;
++                      i-cache-sets = <512>;
++                      d-cache-block-size = <64>;
++                      d-cache-size = <65536>;
++                      d-cache-sets = <512>;
++                      next-level-cache = <&l2_cache12>;
++                      mmu-type = "riscv,sv39";
++
++                      cpu43_intc: interrupt-controller {
++                              compatible = "riscv,cpu-intc";
++                              interrupt-controller;
++                              #interrupt-cells = <1>;
++                      };
++              };
++
++              cpu44: cpu@44 {
++                      compatible = "thead,c920", "riscv";
++                      device_type = "cpu";
++                      riscv,isa = "rv64imafdc";
++                      reg = <44>;
++                      i-cache-block-size = <64>;
++                      i-cache-size = <65536>;
++                      i-cache-sets = <512>;
++                      d-cache-block-size = <64>;
++                      d-cache-size = <65536>;
++                      d-cache-sets = <512>;
++                      next-level-cache = <&l2_cache13>;
++                      mmu-type = "riscv,sv39";
++
++                      cpu44_intc: interrupt-controller {
++                              compatible = "riscv,cpu-intc";
++                              interrupt-controller;
++                              #interrupt-cells = <1>;
++                      };
++              };
++
++              cpu45: cpu@45 {
++                      compatible = "thead,c920", "riscv";
++                      device_type = "cpu";
++                      riscv,isa = "rv64imafdc";
++                      reg = <45>;
++                      i-cache-block-size = <64>;
++                      i-cache-size = <65536>;
++                      i-cache-sets = <512>;
++                      d-cache-block-size = <64>;
++                      d-cache-size = <65536>;
++                      d-cache-sets = <512>;
++                      next-level-cache = <&l2_cache13>;
++                      mmu-type = "riscv,sv39";
++
++                      cpu45_intc: interrupt-controller {
++                              compatible = "riscv,cpu-intc";
++                              interrupt-controller;
++                              #interrupt-cells = <1>;
++                      };
++              };
++
++              cpu46: cpu@46 {
++                      compatible = "thead,c920", "riscv";
++                      device_type = "cpu";
++                      riscv,isa = "rv64imafdc";
++                      reg = <46>;
++                      i-cache-block-size = <64>;
++                      i-cache-size = <65536>;
++                      i-cache-sets = <512>;
++                      d-cache-block-size = <64>;
++                      d-cache-size = <65536>;
++                      d-cache-sets = <512>;
++                      next-level-cache = <&l2_cache13>;
++                      mmu-type = "riscv,sv39";
++
++                      cpu46_intc: interrupt-controller {
++                              compatible = "riscv,cpu-intc";
++                              interrupt-controller;
++                              #interrupt-cells = <1>;
++                      };
++              };
++
++              cpu47: cpu@47 {
++                      compatible = "thead,c920", "riscv";
++                      device_type = "cpu";
++                      riscv,isa = "rv64imafdc";
++                      reg = <47>;
++                      i-cache-block-size = <64>;
++                      i-cache-size = <65536>;
++                      i-cache-sets = <512>;
++                      d-cache-block-size = <64>;
++                      d-cache-size = <65536>;
++                      d-cache-sets = <512>;
++                      next-level-cache = <&l2_cache13>;
++                      mmu-type = "riscv,sv39";
++
++                      cpu47_intc: interrupt-controller {
++                              compatible = "riscv,cpu-intc";
++                              interrupt-controller;
++                              #interrupt-cells = <1>;
++                      };
++              };
++
++              cpu48: cpu@48 {
++                      compatible = "thead,c920", "riscv";
++                      device_type = "cpu";
++                      riscv,isa = "rv64imafdc";
++                      reg = <48>;
++                      i-cache-block-size = <64>;
++                      i-cache-size = <65536>;
++                      i-cache-sets = <512>;
++                      d-cache-block-size = <64>;
++                      d-cache-size = <65536>;
++                      d-cache-sets = <512>;
++                      next-level-cache = <&l2_cache10>;
++                      mmu-type = "riscv,sv39";
++
++                      cpu48_intc: interrupt-controller {
++                              compatible = "riscv,cpu-intc";
++                              interrupt-controller;
++                              #interrupt-cells = <1>;
++                      };
++              };
++
++              cpu49: cpu@49 {
++                      compatible = "thead,c920", "riscv";
++                      device_type = "cpu";
++                      riscv,isa = "rv64imafdc";
++                      reg = <49>;
++                      i-cache-block-size = <64>;
++                      i-cache-size = <65536>;
++                      i-cache-sets = <512>;
++                      d-cache-block-size = <64>;
++                      d-cache-size = <65536>;
++                      d-cache-sets = <512>;
++                      next-level-cache = <&l2_cache10>;
++                      mmu-type = "riscv,sv39";
++
++                      cpu49_intc: interrupt-controller {
++                              compatible = "riscv,cpu-intc";
++                              interrupt-controller;
++                              #interrupt-cells = <1>;
++                      };
++              };
++
++              cpu50: cpu@50 {
++                      compatible = "thead,c920", "riscv";
++                      device_type = "cpu";
++                      riscv,isa = "rv64imafdc";
++                      reg = <50>;
++                      i-cache-block-size = <64>;
++                      i-cache-size = <65536>;
++                      i-cache-sets = <512>;
++                      d-cache-block-size = <64>;
++                      d-cache-size = <65536>;
++                      d-cache-sets = <512>;
++                      next-level-cache = <&l2_cache10>;
++                      mmu-type = "riscv,sv39";
++
++                      cpu50_intc: interrupt-controller {
++                              compatible = "riscv,cpu-intc";
++                              interrupt-controller;
++                              #interrupt-cells = <1>;
++                      };
++              };
++
++              cpu51: cpu@51 {
++                      compatible = "thead,c920", "riscv";
++                      device_type = "cpu";
++                      riscv,isa = "rv64imafdc";
++                      reg = <51>;
++                      i-cache-block-size = <64>;
++                      i-cache-size = <65536>;
++                      i-cache-sets = <512>;
++                      d-cache-block-size = <64>;
++                      d-cache-size = <65536>;
++                      d-cache-sets = <512>;
++                      next-level-cache = <&l2_cache10>;
++                      mmu-type = "riscv,sv39";
++
++                      cpu51_intc: interrupt-controller {
++                              compatible = "riscv,cpu-intc";
++                              interrupt-controller;
++                              #interrupt-cells = <1>;
++                      };
++              };
++
++              cpu52: cpu@52 {
++                      compatible = "thead,c920", "riscv";
++                      device_type = "cpu";
++                      riscv,isa = "rv64imafdc";
++                      reg = <52>;
++                      i-cache-block-size = <64>;
++                      i-cache-size = <65536>;
++                      i-cache-sets = <512>;
++                      d-cache-block-size = <64>;
++                      d-cache-size = <65536>;
++                      d-cache-sets = <512>;
++                      next-level-cache = <&l2_cache11>;
++                      mmu-type = "riscv,sv39";
++
++                      cpu52_intc: interrupt-controller {
++                              compatible = "riscv,cpu-intc";
++                              interrupt-controller;
++                              #interrupt-cells = <1>;
++                      };
++              };
++
++              cpu53: cpu@53 {
++                      compatible = "thead,c920", "riscv";
++                      device_type = "cpu";
++                      riscv,isa = "rv64imafdc";
++                      reg = <53>;
++                      i-cache-block-size = <64>;
++                      i-cache-size = <65536>;
++                      i-cache-sets = <512>;
++                      d-cache-block-size = <64>;
++                      d-cache-size = <65536>;
++                      d-cache-sets = <512>;
++                      next-level-cache = <&l2_cache11>;
++                      mmu-type = "riscv,sv39";
++
++                      cpu53_intc: interrupt-controller {
++                              compatible = "riscv,cpu-intc";
++                              interrupt-controller;
++                              #interrupt-cells = <1>;
++                      };
++              };
++
++              cpu54: cpu@54 {
++                      compatible = "thead,c920", "riscv";
++                      device_type = "cpu";
++                      riscv,isa = "rv64imafdc";
++                      reg = <54>;
++                      i-cache-block-size = <64>;
++                      i-cache-size = <65536>;
++                      i-cache-sets = <512>;
++                      d-cache-block-size = <64>;
++                      d-cache-size = <65536>;
++                      d-cache-sets = <512>;
++                      next-level-cache = <&l2_cache11>;
++                      mmu-type = "riscv,sv39";
++
++                      cpu54_intc: interrupt-controller {
++                              compatible = "riscv,cpu-intc";
++                              interrupt-controller;
++                              #interrupt-cells = <1>;
++                      };
++              };
++
++              cpu55: cpu@55 {
++                      compatible = "thead,c920", "riscv";
++                      device_type = "cpu";
++                      riscv,isa = "rv64imafdc";
++                      reg = <55>;
++                      i-cache-block-size = <64>;
++                      i-cache-size = <65536>;
++                      i-cache-sets = <512>;
++                      d-cache-block-size = <64>;
++                      d-cache-size = <65536>;
++                      d-cache-sets = <512>;
++                      next-level-cache = <&l2_cache11>;
++                      mmu-type = "riscv,sv39";
++
++                      cpu55_intc: interrupt-controller {
++                              compatible = "riscv,cpu-intc";
++                              interrupt-controller;
++                              #interrupt-cells = <1>;
++                      };
++              };
++
++              cpu56: cpu@56 {
++                      compatible = "thead,c920", "riscv";
++                      device_type = "cpu";
++                      riscv,isa = "rv64imafdc";
++                      reg = <56>;
++                      i-cache-block-size = <64>;
++                      i-cache-size = <65536>;
++                      i-cache-sets = <512>;
++                      d-cache-block-size = <64>;
++                      d-cache-size = <65536>;
++                      d-cache-sets = <512>;
++                      next-level-cache = <&l2_cache14>;
++                      mmu-type = "riscv,sv39";
++
++                      cpu56_intc: interrupt-controller {
++                              compatible = "riscv,cpu-intc";
++                              interrupt-controller;
++                              #interrupt-cells = <1>;
++                      };
++              };
++
++              cpu57: cpu@57 {
++                      compatible = "thead,c920", "riscv";
++                      device_type = "cpu";
++                      riscv,isa = "rv64imafdc";
++                      reg = <57>;
++                      i-cache-block-size = <64>;
++                      i-cache-size = <65536>;
++                      i-cache-sets = <512>;
++                      d-cache-block-size = <64>;
++                      d-cache-size = <65536>;
++                      d-cache-sets = <512>;
++                      next-level-cache = <&l2_cache14>;
++                      mmu-type = "riscv,sv39";
++
++                      cpu57_intc: interrupt-controller {
++                              compatible = "riscv,cpu-intc";
++                              interrupt-controller;
++                              #interrupt-cells = <1>;
++                      };
++              };
++
++              cpu58: cpu@58 {
++                      compatible = "thead,c920", "riscv";
++                      device_type = "cpu";
++                      riscv,isa = "rv64imafdc";
++                      reg = <58>;
++                      i-cache-block-size = <64>;
++                      i-cache-size = <65536>;
++                      i-cache-sets = <512>;
++                      d-cache-block-size = <64>;
++                      d-cache-size = <65536>;
++                      d-cache-sets = <512>;
++                      next-level-cache = <&l2_cache14>;
++                      mmu-type = "riscv,sv39";
++
++                      cpu58_intc: interrupt-controller {
++                              compatible = "riscv,cpu-intc";
++                              interrupt-controller;
++                              #interrupt-cells = <1>;
++                      };
++              };
++
++              cpu59: cpu@59 {
++                      compatible = "thead,c920", "riscv";
++                      device_type = "cpu";
++                      riscv,isa = "rv64imafdc";
++                      reg = <59>;
++                      i-cache-block-size = <64>;
++                      i-cache-size = <65536>;
++                      i-cache-sets = <512>;
++                      d-cache-block-size = <64>;
++                      d-cache-size = <65536>;
++                      d-cache-sets = <512>;
++                      next-level-cache = <&l2_cache14>;
++                      mmu-type = "riscv,sv39";
++
++                      cpu59_intc: interrupt-controller {
++                              compatible = "riscv,cpu-intc";
++                              interrupt-controller;
++                              #interrupt-cells = <1>;
++                      };
++              };
++
++              cpu60: cpu@60 {
++                      compatible = "thead,c920", "riscv";
++                      device_type = "cpu";
++                      riscv,isa = "rv64imafdc";
++                      reg = <60>;
++                      i-cache-block-size = <64>;
++                      i-cache-size = <65536>;
++                      i-cache-sets = <512>;
++                      d-cache-block-size = <64>;
++                      d-cache-size = <65536>;
++                      d-cache-sets = <512>;
++                      next-level-cache = <&l2_cache15>;
++                      mmu-type = "riscv,sv39";
++
++                      cpu60_intc: interrupt-controller {
++                              compatible = "riscv,cpu-intc";
++                              interrupt-controller;
++                              #interrupt-cells = <1>;
++                      };
++              };
++
++              cpu61: cpu@61 {
++                      compatible = "thead,c920", "riscv";
++                      device_type = "cpu";
++                      riscv,isa = "rv64imafdc";
++                      reg = <61>;
++                      i-cache-block-size = <64>;
++                      i-cache-size = <65536>;
++                      i-cache-sets = <512>;
++                      d-cache-block-size = <64>;
++                      d-cache-size = <65536>;
++                      d-cache-sets = <512>;
++                      next-level-cache = <&l2_cache15>;
++                      mmu-type = "riscv,sv39";
++
++                      cpu61_intc: interrupt-controller {
++                              compatible = "riscv,cpu-intc";
++                              interrupt-controller;
++                              #interrupt-cells = <1>;
++                      };
++              };
++
++              cpu62: cpu@62 {
++                      compatible = "thead,c920", "riscv";
++                      device_type = "cpu";
++                      riscv,isa = "rv64imafdc";
++                      reg = <62>;
++                      i-cache-block-size = <64>;
++                      i-cache-size = <65536>;
++                      i-cache-sets = <512>;
++                      d-cache-block-size = <64>;
++                      d-cache-size = <65536>;
++                      d-cache-sets = <512>;
++                      next-level-cache = <&l2_cache15>;
++                      mmu-type = "riscv,sv39";
++
++                      cpu62_intc: interrupt-controller {
++                              compatible = "riscv,cpu-intc";
++                              interrupt-controller;
++                              #interrupt-cells = <1>;
++                      };
++              };
++
++              cpu63: cpu@63 {
++                      compatible = "thead,c920", "riscv";
++                      device_type = "cpu";
++                      riscv,isa = "rv64imafdc";
++                      reg = <63>;
++                      i-cache-block-size = <64>;
++                      i-cache-size = <65536>;
++                      i-cache-sets = <512>;
++                      d-cache-block-size = <64>;
++                      d-cache-size = <65536>;
++                      d-cache-sets = <512>;
++                      next-level-cache = <&l2_cache15>;
++                      mmu-type = "riscv,sv39";
++
++                      cpu63_intc: interrupt-controller {
++                              compatible = "riscv,cpu-intc";
++                              interrupt-controller;
++                              #interrupt-cells = <1>;
++                      };
++              };
++
++              l2_cache0: l2-cache@0 {
++                      compatible = "cache";
++                      cache-block-size = <64>;
++                      cache-level = <2>;
++                      cache-size = <1048576>;
++                      cache-sets = <1024>;
++                      cache-unified;
++              };
++
++              l2_cache1: l2-cache@1 {
++                      compatible = "cache";
++                      cache-block-size = <64>;
++                      cache-level = <2>;
++                      cache-size = <1048576>;
++                      cache-sets = <1024>;
++                      cache-unified;
++              };
++
++              l2_cache2: l2-cache@2 {
++                      compatible = "cache";
++                      cache-block-size = <64>;
++                      cache-level = <2>;
++                      cache-size = <1048576>;
++                      cache-sets = <1024>;
++                      cache-unified;
++              };
++
++              l2_cache3: l2-cache@3 {
++                      compatible = "cache";
++                      cache-block-size = <64>;
++                      cache-level = <2>;
++                      cache-size = <1048576>;
++                      cache-sets = <1024>;
++                      cache-unified;
++              };
++
++              l2_cache4: l2-cache@4 {
++                      compatible = "cache";
++                      cache-block-size = <64>;
++                      cache-level = <2>;
++                      cache-size = <1048576>;
++                      cache-sets = <1024>;
++                      cache-unified;
++              };
++
++              l2_cache5: l2-cache@5 {
++                      compatible = "cache";
++                      cache-block-size = <64>;
++                      cache-level = <2>;
++                      cache-size = <1048576>;
++                      cache-sets = <1024>;
++                      cache-unified;
++              };
++
++              l2_cache6: l2-cache@6 {
++                      compatible = "cache";
++                      cache-block-size = <64>;
++                      cache-level = <2>;
++                      cache-size = <1048576>;
++                      cache-sets = <1024>;
++                      cache-unified;
++              };
++
++              l2_cache7: l2-cache@7 {
++                      compatible = "cache";
++                      cache-block-size = <64>;
++                      cache-level = <2>;
++                      cache-size = <1048576>;
++                      cache-sets = <1024>;
++                      cache-unified;
++              };
++
++              l2_cache8: l2-cache@8 {
++                      compatible = "cache";
++                      cache-block-size = <64>;
++                      cache-level = <2>;
++                      cache-size = <1048576>;
++                      cache-sets = <1024>;
++                      cache-unified;
++              };
++
++              l2_cache9: l2-cache@9 {
++                      compatible = "cache";
++                      cache-block-size = <64>;
++                      cache-level = <2>;
++                      cache-size = <1048576>;
++                      cache-sets = <1024>;
++                      cache-unified;
++              };
++
++              l2_cache10: l2-cache@10 {
++                      compatible = "cache";
++                      cache-block-size = <64>;
++                      cache-level = <2>;
++                      cache-size = <1048576>;
++                      cache-sets = <1024>;
++                      cache-unified;
++              };
++
++              l2_cache11: l2-cache@11 {
++                      compatible = "cache";
++                      cache-block-size = <64>;
++                      cache-level = <2>;
++                      cache-size = <1048576>;
++                      cache-sets = <1024>;
++                      cache-unified;
++              };
++
++              l2_cache12: l2-cache@12 {
++                      compatible = "cache";
++                      cache-block-size = <64>;
++                      cache-level = <2>;
++                      cache-size = <1048576>;
++                      cache-sets = <1024>;
++                      cache-unified;
++              };
++
++              l2_cache13: l2-cache@13 {
++                      compatible = "cache";
++                      cache-block-size = <64>;
++                      cache-level = <2>;
++                      cache-size = <1048576>;
++                      cache-sets = <1024>;
++                      cache-unified;
++              };
++
++              l2_cache14: l2-cache@14 {
++                      compatible = "cache";
++                      cache-block-size = <64>;
++                      cache-level = <2>;
++                      cache-size = <1048576>;
++                      cache-sets = <1024>;
++                      cache-unified;
++              };
++
++              l2_cache15: l2-cache@15 {
++                      compatible = "cache";
++                      cache-block-size = <64>;
++                      cache-level = <2>;
++                      cache-size = <1048576>;
++                      cache-sets = <1024>;
++                      cache-unified;
++              };
++      };
++};
+diff --git a/arch/riscv/boot/dts/sophgo/sg2042.dtsi b/arch/riscv/boot/dts/sophgo/sg2042.dtsi
+new file mode 100644
+index 000000000000..747fd9764c95
+--- /dev/null
++++ b/arch/riscv/boot/dts/sophgo/sg2042.dtsi
+@@ -0,0 +1,439 @@
++// SPDX-License-Identifier: GPL-2.0 OR MIT
++/*
++ * Copyright (C) 2022 Sophgo Technology Inc. All rights reserved.
++ */
++
++/dts-v1/;
++#include <dt-bindings/interrupt-controller/irq.h>
++
++#include "sg2042-cpus.dtsi"
++
++#define SOC_PERIPHERAL_IRQ(nr) (nr)
++
++/ {
++      compatible = "sophgo,sg2042";
++      #address-cells = <2>;
++      #size-cells = <2>;
++      dma-noncoherent;
++
++      aliases {
++              serial0 = &uart0;
++      };
++
++      /* the mem node will be updated by ZSBL. */
++      memory@0 {
++              device_type = "memory";
++              reg = <0x00000000 0x00000000 0x00000000 0x00000000>;
++      };
++
++      memory@1 {
++              device_type = "memory";
++              reg = <0x00000000 0x00000001 0x00000000 0x00000000>;
++      };
++
++      memory@2 {
++              device_type = "memory";
++              reg = <0x00000000 0x00000002 0x00000000 0x00000000>;
++      };
++
++      memory@3 {
++              device_type = "memory";
++              reg = <0x00000000 0x00000003 0x00000000 0x00000000>;
++      };
++
++      pmu {
++              compatible = "riscv,pmu";
++              riscv,event-to-mhpmevent =
++                      <0x00003 0x00000000 0x00000010>,
++                      <0x00004 0x00000000 0x00000011>,
++                      <0x00005 0x00000000 0x00000007>,
++                      <0x00006 0x00000000 0x00000006>,
++                      <0x00008 0x00000000 0x00000027>,
++                      <0x00009 0x00000000 0x00000028>,
++                      <0x10000 0x00000000 0x0000000c>,
++                      <0x10001 0x00000000 0x0000000d>,
++                      <0x10002 0x00000000 0x0000000e>,
++                      <0x10003 0x00000000 0x0000000f>,
++                      <0x10008 0x00000000 0x00000001>,
++                      <0x10009 0x00000000 0x00000002>,
++                      <0x10010 0x00000000 0x00000010>,
++                      <0x10011 0x00000000 0x00000011>,
++                      <0x10012 0x00000000 0x00000012>,
++                      <0x10013 0x00000000 0x00000013>,
++                      <0x10019 0x00000000 0x00000004>,
++                      <0x10021 0x00000000 0x00000003>,
++                      <0x10030 0x00000000 0x0000001c>,
++                      <0x10031 0x00000000 0x0000001b>;
++              riscv,event-to-mhpmcounters =
++                      <0x00003 0x00003 0xfffffff8>,
++                      <0x00004 0x00004 0xfffffff8>,
++                      <0x00005 0x00005 0xfffffff8>,
++                      <0x00006 0x00006 0xfffffff8>,
++                      <0x00007 0x00007 0xfffffff8>,
++                      <0x00008 0x00008 0xfffffff8>,
++                      <0x00009 0x00009 0xfffffff8>,
++                      <0x0000a 0x0000a 0xfffffff8>,
++                      <0x10000 0x10000 0xfffffff8>,
++                      <0x10001 0x10001 0xfffffff8>,
++                      <0x10002 0x10002 0xfffffff8>,
++                      <0x10003 0x10003 0xfffffff8>,
++                      <0x10008 0x10008 0xfffffff8>,
++                      <0x10009 0x10009 0xfffffff8>,
++                      <0x10010 0x10010 0xfffffff8>,
++                      <0x10011 0x10011 0xfffffff8>,
++                      <0x10012 0x10012 0xfffffff8>,
++                      <0x10013 0x10013 0xfffffff8>,
++                      <0x10019 0x10019 0xfffffff8>,
++                      <0x10021 0x10021 0xfffffff8>,
++                      <0x10030 0x10030 0xfffffff8>,
++                      <0x10031 0x10031 0xfffffff8>;
++              riscv,raw-event-to-mhpmcounters =
++                      <0x00000000 0x00000001 0xffffffff 0xffffffff 0xfffffff8>,
++                      <0x00000000 0x00000002 0xffffffff 0xffffffff 0xfffffff8>,
++                      <0x00000000 0x00000003 0xffffffff 0xffffffff 0xfffffff8>,
++                      <0x00000000 0x00000004 0xffffffff 0xffffffff 0xfffffff8>,
++                      <0x00000000 0x00000005 0xffffffff 0xffffffff 0xfffffff8>,
++                      <0x00000000 0x00000006 0xffffffff 0xffffffff 0xfffffff8>,
++                      <0x00000000 0x00000007 0xffffffff 0xffffffff 0xfffffff8>,
++                      <0x00000000 0x00000008 0xffffffff 0xffffffff 0xfffffff8>,
++                      <0x00000000 0x00000009 0xffffffff 0xffffffff 0xfffffff8>,
++                      <0x00000000 0x0000000a 0xffffffff 0xffffffff 0xfffffff8>,
++                      <0x00000000 0x0000000b 0xffffffff 0xffffffff 0xfffffff8>,
++                      <0x00000000 0x0000000c 0xffffffff 0xffffffff 0xfffffff8>,
++                      <0x00000000 0x0000000d 0xffffffff 0xffffffff 0xfffffff8>,
++                      <0x00000000 0x0000000e 0xffffffff 0xffffffff 0xfffffff8>,
++                      <0x00000000 0x0000000f 0xffffffff 0xffffffff 0xfffffff8>,
++                      <0x00000000 0x00000010 0xffffffff 0xffffffff 0xfffffff8>,
++                      <0x00000000 0x00000011 0xffffffff 0xffffffff 0xfffffff8>,
++                      <0x00000000 0x00000012 0xffffffff 0xffffffff 0xfffffff8>,
++                      <0x00000000 0x00000013 0xffffffff 0xffffffff 0xfffffff8>,
++                      <0x00000000 0x00000014 0xffffffff 0xffffffff 0xfffffff8>,
++                      <0x00000000 0x00000015 0xffffffff 0xffffffff 0xfffffff8>,
++                      <0x00000000 0x00000016 0xffffffff 0xffffffff 0xfffffff8>,
++                      <0x00000000 0x00000017 0xffffffff 0xffffffff 0xfffffff8>,
++                      <0x00000000 0x00000018 0xffffffff 0xffffffff 0xfffffff8>,
++                      <0x00000000 0x00000019 0xffffffff 0xffffffff 0xfffffff8>,
++                      <0x00000000 0x0000001a 0xffffffff 0xffffffff 0xfffffff8>,
++                      <0x00000000 0x0000001b 0xffffffff 0xffffffff 0xfffffff8>,
++                      <0x00000000 0x0000001c 0xffffffff 0xffffffff 0xfffffff8>,
++                      <0x00000000 0x0000001d 0xffffffff 0xffffffff 0xfffffff8>,
++                      <0x00000000 0x0000001e 0xffffffff 0xffffffff 0xfffffff8>,
++                      <0x00000000 0x0000001f 0xffffffff 0xffffffff 0xfffffff8>,
++                      <0x00000000 0x00000020 0xffffffff 0xffffffff 0xfffffff8>,
++                      <0x00000000 0x00000021 0xffffffff 0xffffffff 0xfffffff8>,
++                      <0x00000000 0x00000022 0xffffffff 0xffffffff 0xfffffff8>,
++                      <0x00000000 0x00000023 0xffffffff 0xffffffff 0xfffffff8>,
++                      <0x00000000 0x00000024 0xffffffff 0xffffffff 0xfffffff8>,
++                      <0x00000000 0x00000025 0xffffffff 0xffffffff 0xfffffff8>,
++                      <0x00000000 0x00000026 0xffffffff 0xffffffff 0xfffffff8>,
++                      <0x00000000 0x00000027 0xffffffff 0xffffffff 0xfffffff8>,
++                      <0x00000000 0x00000028 0xffffffff 0xffffffff 0xfffffff8>,
++                      <0x00000000 0x00000029 0xffffffff 0xffffffff 0xfffffff8>,
++                      <0x00000000 0x0000002a 0xffffffff 0xffffffff 0xfffffff8>;
++      };
++
++      soc: soc {
++              compatible = "simple-bus";
++              #address-cells = <2>;
++              #size-cells = <2>;
++              ranges;
++
++              clint_mswi: interrupt-controller@7094000000 {
++                      compatible = "sophgo,sg2042-clint-mswi", "thead,c900-clint-mswi";
++                      reg = <0x00000070 0x94000000 0x00000000 0x00004000>;
++                      interrupts-extended = <&cpu0_intc 3>,
++                                            <&cpu1_intc 3>,
++                                            <&cpu2_intc 3>,
++                                            <&cpu3_intc 3>,
++                                            <&cpu4_intc 3>,
++                                            <&cpu5_intc 3>,
++                                            <&cpu6_intc 3>,
++                                            <&cpu7_intc 3>,
++                                            <&cpu8_intc 3>,
++                                            <&cpu9_intc 3>,
++                                            <&cpu10_intc 3>,
++                                            <&cpu11_intc 3>,
++                                            <&cpu12_intc 3>,
++                                            <&cpu13_intc 3>,
++                                            <&cpu14_intc 3>,
++                                            <&cpu15_intc 3>,
++                                            <&cpu16_intc 3>,
++                                            <&cpu17_intc 3>,
++                                            <&cpu18_intc 3>,
++                                            <&cpu19_intc 3>,
++                                            <&cpu20_intc 3>,
++                                            <&cpu21_intc 3>,
++                                            <&cpu22_intc 3>,
++                                            <&cpu23_intc 3>,
++                                            <&cpu24_intc 3>,
++                                            <&cpu25_intc 3>,
++                                            <&cpu26_intc 3>,
++                                            <&cpu27_intc 3>,
++                                            <&cpu28_intc 3>,
++                                            <&cpu29_intc 3>,
++                                            <&cpu30_intc 3>,
++                                            <&cpu31_intc 3>,
++                                            <&cpu32_intc 3>,
++                                            <&cpu33_intc 3>,
++                                            <&cpu34_intc 3>,
++                                            <&cpu35_intc 3>,
++                                            <&cpu36_intc 3>,
++                                            <&cpu37_intc 3>,
++                                            <&cpu38_intc 3>,
++                                            <&cpu39_intc 3>,
++                                            <&cpu40_intc 3>,
++                                            <&cpu41_intc 3>,
++                                            <&cpu42_intc 3>,
++                                            <&cpu43_intc 3>,
++                                            <&cpu44_intc 3>,
++                                            <&cpu45_intc 3>,
++                                            <&cpu46_intc 3>,
++                                            <&cpu47_intc 3>,
++                                            <&cpu48_intc 3>,
++                                            <&cpu49_intc 3>,
++                                            <&cpu50_intc 3>,
++                                            <&cpu51_intc 3>,
++                                            <&cpu52_intc 3>,
++                                            <&cpu53_intc 3>,
++                                            <&cpu54_intc 3>,
++                                            <&cpu55_intc 3>,
++                                            <&cpu56_intc 3>,
++                                            <&cpu57_intc 3>,
++                                            <&cpu58_intc 3>,
++                                            <&cpu59_intc 3>,
++                                            <&cpu60_intc 3>,
++                                            <&cpu61_intc 3>,
++                                            <&cpu62_intc 3>,
++                                            <&cpu63_intc 3>;
++              };
++
++              clint_mtimer0: timer@70ac000000 {
++                      compatible = "sophgo,sg2042-clint-mtimer", "thead,c900-clint-mtimer";
++                      reg = <0x00000070 0xac000000 0x00000000 0x00007ff8>;
++                      interrupts-extended = <&cpu0_intc 7>,
++                                            <&cpu1_intc 7>,
++                                            <&cpu2_intc 7>,
++                                            <&cpu3_intc 7>;
++              };
++
++              clint_mtimer1: timer@70ac010000 {
++                      compatible = "sophgo,sg2042-clint-mtimer", "thead,c900-clint-mtimer";
++                      reg = <0x00000070 0xac010000 0x00000000 0x00007ff8>;
++                      interrupts-extended = <&cpu4_intc 7>,
++                                            <&cpu5_intc 7>,
++                                            <&cpu6_intc 7>,
++                                            <&cpu7_intc 7>;
++              };
++
++              clint_mtimer2: timer@70ac020000 {
++                      compatible = "sophgo,sg2042-clint-mtimer", "thead,c900-clint-mtimer";
++                      reg = <0x00000070 0xac020000 0x00000000 0x00007ff8>;
++                      interrupts-extended = <&cpu8_intc 7>,
++                                            <&cpu9_intc 7>,
++                                            <&cpu10_intc 7>,
++                                            <&cpu11_intc 7>;
++              };
++
++              clint_mtimer3: timer@70ac030000 {
++                      compatible = "sophgo,sg2042-clint-mtimer", "thead,c900-clint-mtimer";
++                      reg = <0x00000070 0xac030000 0x00000000 0x00007ff8>;
++                      interrupts-extended = <&cpu12_intc 7>,
++                                            <&cpu13_intc 7>,
++                                            <&cpu14_intc 7>,
++                                            <&cpu15_intc 7>;
++              };
++
++              clint_mtimer4: timer@70ac040000 {
++                      compatible = "sophgo,sg2042-clint-mtimer", "thead,c900-clint-mtimer";
++                      reg = <0x00000070 0xac040000 0x00000000 0x00007ff8>;
++                      interrupts-extended = <&cpu16_intc 7>,
++                                            <&cpu17_intc 7>,
++                                            <&cpu18_intc 7>,
++                                            <&cpu19_intc 7>;
++              };
++
++              clint_mtimer5: timer@70ac050000 {
++                      compatible = "sophgo,sg2042-clint-mtimer", "thead,c900-clint-mtimer";
++                      reg = <0x00000070 0xac050000 0x00000000 0x00007ff8>;
++                      interrupts-extended = <&cpu20_intc 7>,
++                                            <&cpu21_intc 7>,
++                                            <&cpu22_intc 7>,
++                                            <&cpu23_intc 7>;
++              };
++
++              clint_mtimer6: timer@70ac060000 {
++                      compatible = "sophgo,sg2042-clint-mtimer", "thead,c900-clint-mtimer";
++                      reg = <0x00000070 0xac060000 0x00000000 0x00007ff8>;
++                      interrupts-extended = <&cpu24_intc 7>,
++                                            <&cpu25_intc 7>,
++                                            <&cpu26_intc 7>,
++                                            <&cpu27_intc 7>;
++              };
++
++              clint_mtimer7: timer@70ac070000 {
++                      compatible = "sophgo,sg2042-clint-mtimer", "thead,c900-clint-mtimer";
++                      reg = <0x00000070 0xac070000 0x00000000 0x00007ff8>;
++                      interrupts-extended = <&cpu28_intc 7>,
++                                            <&cpu29_intc 7>,
++                                            <&cpu30_intc 7>,
++                                            <&cpu31_intc 7>;
++              };
++
++              clint_mtimer8: timer@70ac080000 {
++                      compatible = "sophgo,sg2042-clint-mtimer", "thead,c900-clint-mtimer";
++                      reg = <0x00000070 0xac080000 0x00000000 0x00007ff8>;
++                      interrupts-extended = <&cpu32_intc 7>,
++                                            <&cpu33_intc 7>,
++                                            <&cpu34_intc 7>,
++                                            <&cpu35_intc 7>;
++              };
++
++              clint_mtimer9: timer@70ac090000 {
++                      compatible = "sophgo,sg2042-clint-mtimer", "thead,c900-clint-mtimer";
++                      reg = <0x00000070 0xac090000 0x00000000 0x00007ff8>;
++                      interrupts-extended = <&cpu36_intc 7>,
++                                            <&cpu37_intc 7>,
++                                            <&cpu38_intc 7>,
++                                            <&cpu39_intc 7>;
++              };
++
++              clint_mtimer10: timer@70ac0a0000 {
++                      compatible = "sophgo,sg2042-clint-mtimer", "thead,c900-clint-mtimer";
++                      reg = <0x00000070 0xac0a0000 0x00000000 0x00007ff8>;
++                      interrupts-extended = <&cpu40_intc 7>,
++                                            <&cpu41_intc 7>,
++                                            <&cpu42_intc 7>,
++                                            <&cpu43_intc 7>;
++              };
++
++              clint_mtimer11: timer@70ac0b0000 {
++                      compatible = "sophgo,sg2042-clint-mtimer", "thead,c900-clint-mtimer";
++                      reg = <0x00000070 0xac0b0000 0x00000000 0x00007ff8>;
++                      interrupts-extended = <&cpu44_intc 7>,
++                                            <&cpu45_intc 7>,
++                                            <&cpu46_intc 7>,
++                                            <&cpu47_intc 7>;
++              };
++
++              clint_mtimer12: timer@70ac0c0000 {
++                      compatible = "sophgo,sg2042-clint-mtimer", "thead,c900-clint-mtimer";
++                      reg = <0x00000070 0xac0c0000 0x00000000 0x00007ff8>;
++                      interrupts-extended = <&cpu48_intc 7>,
++                                            <&cpu49_intc 7>,
++                                            <&cpu50_intc 7>,
++                                            <&cpu51_intc 7>;
++              };
++
++              clint_mtimer13: timer@70ac0d0000 {
++                      compatible = "sophgo,sg2042-clint-mtimer", "thead,c900-clint-mtimer";
++                      reg = <0x00000070 0xac0d0000 0x00000000 0x00007ff8>;
++                      interrupts-extended = <&cpu52_intc 7>,
++                                            <&cpu53_intc 7>,
++                                            <&cpu54_intc 7>,
++                                            <&cpu55_intc 7>;
++              };
++
++              clint_mtimer14: timer@70ac0e0000 {
++                      compatible = "sophgo,sg2042-clint-mtimer", "thead,c900-clint-mtimer";
++                      reg = <0x00000070 0xac0e0000 0x00000000 0x00007ff8>;
++                      interrupts-extended = <&cpu56_intc 7>,
++                                            <&cpu57_intc 7>,
++                                            <&cpu58_intc 7>,
++                                            <&cpu59_intc 7>;
++              };
++
++              clint_mtimer15: timer@70ac0f0000 {
++                      compatible = "sophgo,sg2042-clint-mtimer", "thead,c900-clint-mtimer";
++                      reg = <0x00000070 0xac0f0000 0x00000000 0x00007ff8>;
++                      interrupts-extended = <&cpu60_intc 7>,
++                                            <&cpu61_intc 7>,
++                                            <&cpu62_intc 7>,
++                                            <&cpu63_intc 7>;
++              };
++
++              intc: interrupt-controller@7090000000 {
++                      compatible = "sophgo,sg2042-plic", "thead,c900-plic";
++                      #address-cells = <0>;
++                      #interrupt-cells = <2>;
++                      reg = <0x00000070 0x90000000 0x00000000 0x04000000>;
++                      interrupt-controller;
++                      interrupts-extended =
++                              <&cpu0_intc 0xffffffff>,  <&cpu0_intc 9>,
++                              <&cpu1_intc 0xffffffff>,  <&cpu1_intc 9>,
++                              <&cpu2_intc 0xffffffff>,  <&cpu2_intc 9>,
++                              <&cpu3_intc 0xffffffff>,  <&cpu3_intc 9>,
++                              <&cpu4_intc 0xffffffff>,  <&cpu4_intc 9>,
++                              <&cpu5_intc 0xffffffff>,  <&cpu5_intc 9>,
++                              <&cpu6_intc 0xffffffff>,  <&cpu6_intc 9>,
++                              <&cpu7_intc 0xffffffff>,  <&cpu7_intc 9>,
++                              <&cpu8_intc 0xffffffff>,  <&cpu8_intc 9>,
++                              <&cpu9_intc 0xffffffff>,  <&cpu9_intc 9>,
++                              <&cpu10_intc 0xffffffff>, <&cpu10_intc 9>,
++                              <&cpu11_intc 0xffffffff>, <&cpu11_intc 9>,
++                              <&cpu12_intc 0xffffffff>, <&cpu12_intc 9>,
++                              <&cpu13_intc 0xffffffff>, <&cpu13_intc 9>,
++                              <&cpu14_intc 0xffffffff>, <&cpu14_intc 9>,
++                              <&cpu15_intc 0xffffffff>, <&cpu15_intc 9>,
++                              <&cpu16_intc 0xffffffff>, <&cpu16_intc 9>,
++                              <&cpu17_intc 0xffffffff>, <&cpu17_intc 9>,
++                              <&cpu18_intc 0xffffffff>, <&cpu18_intc 9>,
++                              <&cpu19_intc 0xffffffff>, <&cpu19_intc 9>,
++                              <&cpu20_intc 0xffffffff>, <&cpu20_intc 9>,
++                              <&cpu21_intc 0xffffffff>, <&cpu21_intc 9>,
++                              <&cpu22_intc 0xffffffff>, <&cpu22_intc 9>,
++                              <&cpu23_intc 0xffffffff>, <&cpu23_intc 9>,
++                              <&cpu24_intc 0xffffffff>, <&cpu24_intc 9>,
++                              <&cpu25_intc 0xffffffff>, <&cpu25_intc 9>,
++                              <&cpu26_intc 0xffffffff>, <&cpu26_intc 9>,
++                              <&cpu27_intc 0xffffffff>, <&cpu27_intc 9>,
++                              <&cpu28_intc 0xffffffff>, <&cpu28_intc 9>,
++                              <&cpu29_intc 0xffffffff>, <&cpu29_intc 9>,
++                              <&cpu30_intc 0xffffffff>, <&cpu30_intc 9>,
++                              <&cpu31_intc 0xffffffff>, <&cpu31_intc 9>,
++                              <&cpu32_intc 0xffffffff>, <&cpu32_intc 9>,
++                              <&cpu33_intc 0xffffffff>, <&cpu33_intc 9>,
++                              <&cpu34_intc 0xffffffff>, <&cpu34_intc 9>,
++                              <&cpu35_intc 0xffffffff>, <&cpu35_intc 9>,
++                              <&cpu36_intc 0xffffffff>, <&cpu36_intc 9>,
++                              <&cpu37_intc 0xffffffff>, <&cpu37_intc 9>,
++                              <&cpu38_intc 0xffffffff>, <&cpu38_intc 9>,
++                              <&cpu39_intc 0xffffffff>, <&cpu39_intc 9>,
++                              <&cpu40_intc 0xffffffff>, <&cpu40_intc 9>,
++                              <&cpu41_intc 0xffffffff>, <&cpu41_intc 9>,
++                              <&cpu42_intc 0xffffffff>, <&cpu42_intc 9>,
++                              <&cpu43_intc 0xffffffff>, <&cpu43_intc 9>,
++                              <&cpu44_intc 0xffffffff>, <&cpu44_intc 9>,
++                              <&cpu45_intc 0xffffffff>, <&cpu45_intc 9>,
++                              <&cpu46_intc 0xffffffff>, <&cpu46_intc 9>,
++                              <&cpu47_intc 0xffffffff>, <&cpu47_intc 9>,
++                              <&cpu48_intc 0xffffffff>, <&cpu48_intc 9>,
++                              <&cpu49_intc 0xffffffff>, <&cpu49_intc 9>,
++                              <&cpu50_intc 0xffffffff>, <&cpu50_intc 9>,
++                              <&cpu51_intc 0xffffffff>, <&cpu51_intc 9>,
++                              <&cpu52_intc 0xffffffff>, <&cpu52_intc 9>,
++                              <&cpu53_intc 0xffffffff>, <&cpu53_intc 9>,
++                              <&cpu54_intc 0xffffffff>, <&cpu54_intc 9>,
++                              <&cpu55_intc 0xffffffff>, <&cpu55_intc 9>,
++                              <&cpu56_intc 0xffffffff>, <&cpu56_intc 9>,
++                              <&cpu57_intc 0xffffffff>, <&cpu57_intc 9>,
++                              <&cpu58_intc 0xffffffff>, <&cpu58_intc 9>,
++                              <&cpu59_intc 0xffffffff>, <&cpu59_intc 9>,
++                              <&cpu60_intc 0xffffffff>, <&cpu60_intc 9>,
++                              <&cpu61_intc 0xffffffff>, <&cpu61_intc 9>,
++                              <&cpu62_intc 0xffffffff>, <&cpu62_intc 9>,
++                              <&cpu63_intc 0xffffffff>, <&cpu63_intc 9>;
++                      riscv,ndev = <224>;
++              };
++
++              uart0: serial@7040000000 {
++                      compatible = "sophgo,sg2042-uart", "snps,dw-apb-uart";
++                      reg = <0x00000070 0x40000000 0x00000000 0x00001000>;
++                      interrupt-parent = <&intc>;
++                      interrupts = <SOC_PERIPHERAL_IRQ(112) IRQ_TYPE_LEVEL_HIGH>;
++                      clock-frequency = <500000000>;
++                      reg-shift = <2>;
++                      reg-io-width = <4>;
++                      status = "disabled";
++              };
++      };
++};
+-- 
+2.20.1
+
diff --git a/target/linux/cv18x0/patches-6.6/0004-riscv-dts-sophgo-add-Milk-V-Pioneer-board-device-tre.patch b/target/linux/cv18x0/patches-6.6/0004-riscv-dts-sophgo-add-Milk-V-Pioneer-board-device-tre.patch
new file mode 100644 (file)
index 0000000..83e3672
--- /dev/null
@@ -0,0 +1,76 @@
+From c43ee7ae03d60ca24e29ef1079be21dcd8023dfe Mon Sep 17 00:00:00 2001
+From: Chen Wang <unicornxw@gmail.com>
+Date: Wed, 20 Sep 2023 14:40:53 +0800
+Subject: [PATCH 04/18] riscv: dts: sophgo: add Milk-V Pioneer board device
+ tree
+
+Milk-V Pioneer [1] is a developer motherboard based on SOPHON
+SG2042 in a standard mATX form factor. It is a good
+choice for RISC-V developers and hardware pioneers to
+experience the cutting edge technology of RISC-V.
+
+Currently only support booting into console with only uart
+enabled, other features will be added soon later.
+
+[1]: https://milkv.io/pioneer
+
+Acked-by: Xiaoguang Xing <xiaoguang.xing@sophgo.com>
+Signed-off-by: Chen Wang <wangchen20@iscas.ac.cn>
+Reviewed-by: Guo Ren <guoren@kernel.org>
+---
+ arch/riscv/boot/dts/Makefile                  |  1 +
+ arch/riscv/boot/dts/sophgo/Makefile           |  3 +++
+ .../boot/dts/sophgo/sg2042-milkv-pioneer.dts  | 19 +++++++++++++++++++
+ 3 files changed, 23 insertions(+)
+ create mode 100644 arch/riscv/boot/dts/sophgo/Makefile
+ create mode 100644 arch/riscv/boot/dts/sophgo/sg2042-milkv-pioneer.dts
+
+diff --git a/arch/riscv/boot/dts/Makefile b/arch/riscv/boot/dts/Makefile
+index f60a280abb15..5da6736661da 100644
+--- a/arch/riscv/boot/dts/Makefile
++++ b/arch/riscv/boot/dts/Makefile
+@@ -3,6 +3,7 @@ subdir-y += allwinner
+ subdir-y += canaan
+ subdir-y += microchip
+ subdir-y += renesas
++subdir-y += sophgo
+ subdir-y += sifive
+ subdir-y += starfive
+ subdir-y += thead
+diff --git a/arch/riscv/boot/dts/sophgo/Makefile b/arch/riscv/boot/dts/sophgo/Makefile
+new file mode 100644
+index 000000000000..5a471b19df22
+--- /dev/null
++++ b/arch/riscv/boot/dts/sophgo/Makefile
+@@ -0,0 +1,3 @@
++# SPDX-License-Identifier: GPL-2.0
++dtb-$(CONFIG_ARCH_SOPHGO) += sg2042-milkv-pioneer.dtb
++
+diff --git a/arch/riscv/boot/dts/sophgo/sg2042-milkv-pioneer.dts b/arch/riscv/boot/dts/sophgo/sg2042-milkv-pioneer.dts
+new file mode 100644
+index 000000000000..d6e8c0285d1e
+--- /dev/null
++++ b/arch/riscv/boot/dts/sophgo/sg2042-milkv-pioneer.dts
+@@ -0,0 +1,19 @@
++// SPDX-License-Identifier: GPL-2.0 OR MIT
++/*
++ * Copyright (C) 2022 Sophgo Technology Inc. All rights reserved.
++ */
++
++#include "sg2042.dtsi"
++
++/ {
++      model = "Milk-V Pioneer";
++      compatible = "milkv,pioneer", "sophgo,sg2042";
++
++      chosen: chosen {
++              stdout-path = "serial0";
++      };
++};
++
++&uart0 {
++      status = "okay";
++};
+-- 
+2.20.1
+
diff --git a/target/linux/cv18x0/patches-6.6/0005-riscv-dts-sophgo-add-Milk-V-Duo-board-device-tree.patch b/target/linux/cv18x0/patches-6.6/0005-riscv-dts-sophgo-add-Milk-V-Duo-board-device-tree.patch
new file mode 100644 (file)
index 0000000..b015aee
--- /dev/null
@@ -0,0 +1,74 @@
+From c3be09615d98340463c8aade13064459b9267bc9 Mon Sep 17 00:00:00 2001
+From: Jisheng Zhang <jszhang@kernel.org>
+Date: Sat, 30 Sep 2023 20:39:37 +0800
+Subject: [PATCH 05/18] riscv: dts: sophgo: add Milk-V Duo board device tree
+
+Milk-V Duo[1] board is an embedded development platform based on the
+CV1800B chip. Add minimal device tree files for the development board.
+
+Support basic uart drivers, so supports booting to a basic shell.
+
+Link: https://milkv.io/duo [1]
+Signed-off-by: Jisheng Zhang <jszhang@kernel.org>
+---
+ arch/riscv/boot/dts/sophgo/Makefile           |  2 +-
+ .../boot/dts/sophgo/cv1800b-milkv-duo.dts     | 38 +++++++++++++++++++
+ 2 files changed, 39 insertions(+), 1 deletion(-)
+ create mode 100644 arch/riscv/boot/dts/sophgo/cv1800b-milkv-duo.dts
+
+diff --git a/arch/riscv/boot/dts/sophgo/Makefile b/arch/riscv/boot/dts/sophgo/Makefile
+index 5a471b19df22..5ea9ce398ff6 100644
+--- a/arch/riscv/boot/dts/sophgo/Makefile
++++ b/arch/riscv/boot/dts/sophgo/Makefile
+@@ -1,3 +1,3 @@
+ # SPDX-License-Identifier: GPL-2.0
+ dtb-$(CONFIG_ARCH_SOPHGO) += sg2042-milkv-pioneer.dtb
+-
++dtb-$(CONFIG_ARCH_SOPHGO) += cv1800b-milkv-duo.dtb
+diff --git a/arch/riscv/boot/dts/sophgo/cv1800b-milkv-duo.dts b/arch/riscv/boot/dts/sophgo/cv1800b-milkv-duo.dts
+new file mode 100644
+index 000000000000..3af9e34b3bc7
+--- /dev/null
++++ b/arch/riscv/boot/dts/sophgo/cv1800b-milkv-duo.dts
+@@ -0,0 +1,38 @@
++// SPDX-License-Identifier: (GPL-2.0 OR MIT)
++/*
++ * Copyright (C) 2023 Jisheng Zhang <jszhang@kernel.org>
++ */
++
++/dts-v1/;
++
++#include "cv1800b.dtsi"
++
++/ {
++      model = "Milk-V Duo";
++      compatible = "milkv,duo", "sophgo,cv1800b";
++
++      aliases {
++              serial0 = &uart0;
++              serial1 = &uart1;
++              serial2 = &uart2;
++              serial3 = &uart3;
++              serial4 = &uart4;
++      };
++
++      chosen {
++              stdout-path = "serial0:115200n8";
++      };
++
++      memory@80000000 {
++              device_type = "memory";
++              reg = <0x80000000 0x3f40000>;
++      };
++};
++
++&osc {
++      clock-frequency = <25000000>;
++};
++
++&uart0 {
++      status = "okay";
++};
+-- 
+2.20.1
+
diff --git a/target/linux/cv18x0/patches-6.6/0006-riscv-dts-sophgo-add-initial-CV1812H-SoC-device-tree.patch b/target/linux/cv18x0/patches-6.6/0006-riscv-dts-sophgo-add-initial-CV1812H-SoC-device-tree.patch
new file mode 100644 (file)
index 0000000..cdb08e8
--- /dev/null
@@ -0,0 +1,48 @@
+From 4f879141f6c39cada3681d5c86e335405f60f7d4 Mon Sep 17 00:00:00 2001
+From: Inochi Amaoto <inochiama@outlook.com>
+Date: Thu, 19 Oct 2023 07:18:53 +0800
+Subject: [PATCH 06/18] riscv: dts: sophgo: add initial CV1812H SoC device tree
+
+Add initial device tree for the CV1812H RISC-V SoC by SOPHGO.
+
+Signed-off-by: Inochi Amaoto <inochiama@outlook.com>
+Acked-by: Chen Wang <unicorn_wang@outlook.com>
+Signed-off-by: Conor Dooley <conor.dooley@microchip.com>
+---
+ arch/riscv/boot/dts/sophgo/cv1812h.dtsi | 24 ++++++++++++++++++++++++
+ 1 file changed, 24 insertions(+)
+ create mode 100644 arch/riscv/boot/dts/sophgo/cv1812h.dtsi
+
+diff --git a/arch/riscv/boot/dts/sophgo/cv1812h.dtsi b/arch/riscv/boot/dts/sophgo/cv1812h.dtsi
+new file mode 100644
+index 000000000000..3e7a942f5c1a
+--- /dev/null
++++ b/arch/riscv/boot/dts/sophgo/cv1812h.dtsi
+@@ -0,0 +1,24 @@
++// SPDX-License-Identifier: (GPL-2.0 OR MIT)
++/*
++ * Copyright (C) 2023 Inochi Amaoto <inochiama@outlook.com>
++ */
++
++#include <dt-bindings/interrupt-controller/irq.h>
++#include "cv18xx.dtsi"
++
++/ {
++      compatible = "sophgo,cv1812h";
++
++      memory@80000000 {
++              device_type = "memory";
++              reg = <0x80000000 0x10000000>;
++      };
++};
++
++&plic {
++      compatible = "sophgo,cv1812h-plic", "thead,c900-plic";
++};
++
++&clint {
++      compatible = "sophgo,cv1812h-clint", "thead,c900-clint";
++};
+-- 
+2.20.1
+
diff --git a/target/linux/cv18x0/patches-6.6/0007-riscv-dts-sophgo-Separate-compatible-specific-for-CV.patch b/target/linux/cv18x0/patches-6.6/0007-riscv-dts-sophgo-Separate-compatible-specific-for-CV.patch
new file mode 100644 (file)
index 0000000..540261e
--- /dev/null
@@ -0,0 +1,282 @@
+From 9acf530cd767b5f980647717776d2c4c260cf3b6 Mon Sep 17 00:00:00 2001
+From: Inochi Amaoto <inochiama@outlook.com>
+Date: Thu, 19 Oct 2023 07:18:51 +0800
+Subject: [PATCH 07/18] riscv: dts: sophgo: Separate compatible specific for
+ CV1800B soc
+
+As CV180x and CV181x have the identical layouts, it is OK to use the
+cv1800b basic device tree for the whole series.
+For CV1800B soc specific compatible, just move them out of the common
+file.
+
+Signed-off-by: Inochi Amaoto <inochiama@outlook.com>
+Acked-by: Chen Wang <unicorn_wang@outlook.com>
+Signed-off-by: Conor Dooley <conor.dooley@microchip.com>
+---
+ arch/riscv/boot/dts/sophgo/cv1800b.dtsi | 119 ++---------------------
+ arch/riscv/boot/dts/sophgo/cv18xx.dtsi  | 120 ++++++++++++++++++++++++
+ 2 files changed, 127 insertions(+), 112 deletions(-)
+ create mode 100644 arch/riscv/boot/dts/sophgo/cv18xx.dtsi
+
+diff --git a/arch/riscv/boot/dts/sophgo/cv1800b.dtsi b/arch/riscv/boot/dts/sophgo/cv1800b.dtsi
+index df40e87ee063..165e9e320a8c 100644
+--- a/arch/riscv/boot/dts/sophgo/cv1800b.dtsi
++++ b/arch/riscv/boot/dts/sophgo/cv1800b.dtsi
+@@ -3,121 +3,16 @@
+  * Copyright (C) 2023 Jisheng Zhang <jszhang@kernel.org>
+  */
+-#include <dt-bindings/interrupt-controller/irq.h>
++#include "cv18xx.dtsi"
+ / {
+       compatible = "sophgo,cv1800b";
+-      #address-cells = <1>;
+-      #size-cells = <1>;
+-
+-      cpus: cpus {
+-              #address-cells = <1>;
+-              #size-cells = <0>;
+-              timebase-frequency = <25000000>;
+-
+-              cpu0: cpu@0 {
+-                      compatible = "thead,c906", "riscv";
+-                      device_type = "cpu";
+-                      reg = <0>;
+-                      d-cache-block-size = <64>;
+-                      d-cache-sets = <512>;
+-                      d-cache-size = <65536>;
+-                      i-cache-block-size = <64>;
+-                      i-cache-sets = <128>;
+-                      i-cache-size = <32768>;
+-                      mmu-type = "riscv,sv39";
+-                      riscv,isa = "rv64imafdc";
+-                      riscv,isa-base = "rv64i";
+-                      riscv,isa-extensions = "i", "m", "a", "f", "d", "c", "zicntr", "zicsr",
+-                                             "zifencei", "zihpm";
+-
+-                      cpu0_intc: interrupt-controller {
+-                              compatible = "riscv,cpu-intc";
+-                              interrupt-controller;
+-                              #address-cells = <0>;
+-                              #interrupt-cells = <1>;
+-                      };
+-              };
+-      };
+-
+-      osc: oscillator {
+-              compatible = "fixed-clock";
+-              clock-output-names = "osc_25m";
+-              #clock-cells = <0>;
+-      };
+-
+-      soc {
+-              compatible = "simple-bus";
+-              interrupt-parent = <&plic>;
+-              #address-cells = <1>;
+-              #size-cells = <1>;
+-              dma-noncoherent;
+-              ranges;
+-
+-              uart0: serial@4140000 {
+-                      compatible = "snps,dw-apb-uart";
+-                      reg = <0x04140000 0x100>;
+-                      interrupts = <44 IRQ_TYPE_LEVEL_HIGH>;
+-                      clocks = <&osc>;
+-                      reg-shift = <2>;
+-                      reg-io-width = <4>;
+-                      status = "disabled";
+-              };
+-
+-              uart1: serial@4150000 {
+-                      compatible = "snps,dw-apb-uart";
+-                      reg = <0x04150000 0x100>;
+-                      interrupts = <45 IRQ_TYPE_LEVEL_HIGH>;
+-                      clocks = <&osc>;
+-                      reg-shift = <2>;
+-                      reg-io-width = <4>;
+-                      status = "disabled";
+-              };
+-
+-              uart2: serial@4160000 {
+-                      compatible = "snps,dw-apb-uart";
+-                      reg = <0x04160000 0x100>;
+-                      interrupts = <46 IRQ_TYPE_LEVEL_HIGH>;
+-                      clocks = <&osc>;
+-                      reg-shift = <2>;
+-                      reg-io-width = <4>;
+-                      status = "disabled";
+-              };
+-
+-              uart3: serial@4170000 {
+-                      compatible = "snps,dw-apb-uart";
+-                      reg = <0x04170000 0x100>;
+-                      interrupts = <47 IRQ_TYPE_LEVEL_HIGH>;
+-                      clocks = <&osc>;
+-                      reg-shift = <2>;
+-                      reg-io-width = <4>;
+-                      status = "disabled";
+-              };
+-
+-              uart4: serial@41c0000 {
+-                      compatible = "snps,dw-apb-uart";
+-                      reg = <0x041c0000 0x100>;
+-                      interrupts = <48 IRQ_TYPE_LEVEL_HIGH>;
+-                      clocks = <&osc>;
+-                      reg-shift = <2>;
+-                      reg-io-width = <4>;
+-                      status = "disabled";
+-              };
++};
+-              plic: interrupt-controller@70000000 {
+-                      compatible = "sophgo,cv1800b-plic", "thead,c900-plic";
+-                      reg = <0x70000000 0x4000000>;
+-                      interrupts-extended = <&cpu0_intc 11>, <&cpu0_intc 9>;
+-                      interrupt-controller;
+-                      #address-cells = <0>;
+-                      #interrupt-cells = <2>;
+-                      riscv,ndev = <101>;
+-              };
++&plic {
++      compatible = "sophgo,cv1800b-plic", "thead,c900-plic";
++};
+-              clint: timer@74000000 {
+-                      compatible = "sophgo,cv1800b-clint", "thead,c900-clint";
+-                      reg = <0x74000000 0x10000>;
+-                      interrupts-extended = <&cpu0_intc 3>, <&cpu0_intc 7>;
+-              };
+-      };
++&clint {
++      compatible = "sophgo,cv1800b-clint", "thead,c900-clint";
+ };
+diff --git a/arch/riscv/boot/dts/sophgo/cv18xx.dtsi b/arch/riscv/boot/dts/sophgo/cv18xx.dtsi
+new file mode 100644
+index 000000000000..55d4bc84faa0
+--- /dev/null
++++ b/arch/riscv/boot/dts/sophgo/cv18xx.dtsi
+@@ -0,0 +1,120 @@
++// SPDX-License-Identifier: (GPL-2.0 OR MIT)
++/*
++ * Copyright (C) 2023 Jisheng Zhang <jszhang@kernel.org>
++ */
++
++#include <dt-bindings/interrupt-controller/irq.h>
++
++/ {
++      #address-cells = <1>;
++      #size-cells = <1>;
++
++      cpus: cpus {
++              #address-cells = <1>;
++              #size-cells = <0>;
++              timebase-frequency = <25000000>;
++
++              cpu0: cpu@0 {
++                      compatible = "thead,c906", "riscv";
++                      device_type = "cpu";
++                      reg = <0>;
++                      d-cache-block-size = <64>;
++                      d-cache-sets = <512>;
++                      d-cache-size = <65536>;
++                      i-cache-block-size = <64>;
++                      i-cache-sets = <128>;
++                      i-cache-size = <32768>;
++                      mmu-type = "riscv,sv39";
++                      riscv,isa = "rv64imafdc";
++                      riscv,isa-base = "rv64i";
++                      riscv,isa-extensions = "i", "m", "a", "f", "d", "c", "zicntr", "zicsr",
++                                             "zifencei", "zihpm";
++
++                      cpu0_intc: interrupt-controller {
++                              compatible = "riscv,cpu-intc";
++                              interrupt-controller;
++                              #address-cells = <0>;
++                              #interrupt-cells = <1>;
++                      };
++              };
++      };
++
++      osc: oscillator {
++              compatible = "fixed-clock";
++              clock-output-names = "osc_25m";
++              #clock-cells = <0>;
++      };
++
++      soc {
++              compatible = "simple-bus";
++              interrupt-parent = <&plic>;
++              #address-cells = <1>;
++              #size-cells = <1>;
++              dma-noncoherent;
++              ranges;
++
++              uart0: serial@4140000 {
++                      compatible = "snps,dw-apb-uart";
++                      reg = <0x04140000 0x100>;
++                      interrupts = <44 IRQ_TYPE_LEVEL_HIGH>;
++                      clocks = <&osc>;
++                      reg-shift = <2>;
++                      reg-io-width = <4>;
++                      status = "disabled";
++              };
++
++              uart1: serial@4150000 {
++                      compatible = "snps,dw-apb-uart";
++                      reg = <0x04150000 0x100>;
++                      interrupts = <45 IRQ_TYPE_LEVEL_HIGH>;
++                      clocks = <&osc>;
++                      reg-shift = <2>;
++                      reg-io-width = <4>;
++                      status = "disabled";
++              };
++
++              uart2: serial@4160000 {
++                      compatible = "snps,dw-apb-uart";
++                      reg = <0x04160000 0x100>;
++                      interrupts = <46 IRQ_TYPE_LEVEL_HIGH>;
++                      clocks = <&osc>;
++                      reg-shift = <2>;
++                      reg-io-width = <4>;
++                      status = "disabled";
++              };
++
++              uart3: serial@4170000 {
++                      compatible = "snps,dw-apb-uart";
++                      reg = <0x04170000 0x100>;
++                      interrupts = <47 IRQ_TYPE_LEVEL_HIGH>;
++                      clocks = <&osc>;
++                      reg-shift = <2>;
++                      reg-io-width = <4>;
++                      status = "disabled";
++              };
++
++              uart4: serial@41c0000 {
++                      compatible = "snps,dw-apb-uart";
++                      reg = <0x041c0000 0x100>;
++                      interrupts = <48 IRQ_TYPE_LEVEL_HIGH>;
++                      clocks = <&osc>;
++                      reg-shift = <2>;
++                      reg-io-width = <4>;
++                      status = "disabled";
++              };
++
++              plic: interrupt-controller@70000000 {
++                      reg = <0x70000000 0x4000000>;
++                      interrupts-extended = <&cpu0_intc 11>, <&cpu0_intc 9>;
++                      interrupt-controller;
++                      #address-cells = <0>;
++                      #interrupt-cells = <2>;
++                      riscv,ndev = <101>;
++              };
++
++              clint: timer@74000000 {
++                      reg = <0x74000000 0x10000>;
++                      interrupts-extended = <&cpu0_intc 3>, <&cpu0_intc 7>;
++              };
++      };
++};
+-- 
+2.20.1
+
diff --git a/target/linux/cv18x0/patches-6.6/0008-riscv-dts-sophgo-cv18xx-Add-gpio-devices.patch b/target/linux/cv18x0/patches-6.6/0008-riscv-dts-sophgo-cv18xx-Add-gpio-devices.patch
new file mode 100644 (file)
index 0000000..bf24355
--- /dev/null
@@ -0,0 +1,109 @@
+From 53ebe26713247df9cec482075cbc27795d386d79 Mon Sep 17 00:00:00 2001
+From: Zoltan HERPAI <wigyori@uid0.hu>
+Date: Fri, 28 Jun 2024 15:10:43 +0000
+Subject: [PATCH 08/18] riscv: dts: sophgo: cv18xx: Add gpio devices
+
+Add common GPIO devices for the CV180x and CV181x soc.
+
+Signed-off-by: Inochi Amaoto <inochiama@outlook.com>
+Reviewed-by: Jisheng Zhang <jszhang@kernel.org>
+Acked-by: Chen Wang <unicorn_wang@outlook.com>
+Signed-off-by: Conor Dooley <conor.dooley@microchip.com>
+---
+ arch/riscv/boot/dts/sophgo/cv18xx.dtsi | 73 ++++++++++++++++++++++++++
+ 1 file changed, 73 insertions(+)
+
+diff --git a/arch/riscv/boot/dts/sophgo/cv18xx.dtsi b/arch/riscv/boot/dts/sophgo/cv18xx.dtsi
+index 55d4bc84faa0..d415cc758def 100644
+--- a/arch/riscv/boot/dts/sophgo/cv18xx.dtsi
++++ b/arch/riscv/boot/dts/sophgo/cv18xx.dtsi
+@@ -1,6 +1,7 @@
+ // SPDX-License-Identifier: (GPL-2.0 OR MIT)
+ /*
+  * Copyright (C) 2023 Jisheng Zhang <jszhang@kernel.org>
++ * Copyright (C) 2023 Inochi Amaoto <inochiama@outlook.com>
+  */
+ #include <dt-bindings/interrupt-controller/irq.h>
+@@ -53,6 +54,78 @@
+               dma-noncoherent;
+               ranges;
++              gpio0: gpio@3020000 {
++                      compatible = "snps,dw-apb-gpio";
++                      reg = <0x3020000 0x1000>;
++                      #address-cells = <1>;
++                      #size-cells = <0>;
++
++                      porta: gpio-controller@0 {
++                              compatible = "snps,dw-apb-gpio-port";
++                              gpio-controller;
++                              #gpio-cells = <2>;
++                              ngpios = <32>;
++                              reg = <0>;
++                              interrupt-controller;
++                              #interrupt-cells = <2>;
++                              interrupts = <60 IRQ_TYPE_LEVEL_HIGH>;
++                      };
++              };
++
++              gpio1: gpio@3021000 {
++                      compatible = "snps,dw-apb-gpio";
++                      reg = <0x3021000 0x1000>;
++                      #address-cells = <1>;
++                      #size-cells = <0>;
++
++                      portb: gpio-controller@0 {
++                              compatible = "snps,dw-apb-gpio-port";
++                              gpio-controller;
++                              #gpio-cells = <2>;
++                              ngpios = <32>;
++                              reg = <0>;
++                              interrupt-controller;
++                              #interrupt-cells = <2>;
++                              interrupts = <61 IRQ_TYPE_LEVEL_HIGH>;
++                      };
++              };
++
++              gpio2: gpio@3022000 {
++                      compatible = "snps,dw-apb-gpio";
++                      reg = <0x3022000 0x1000>;
++                      #address-cells = <1>;
++                      #size-cells = <0>;
++
++                      portc: gpio-controller@0 {
++                              compatible = "snps,dw-apb-gpio-port";
++                              gpio-controller;
++                              #gpio-cells = <2>;
++                              ngpios = <32>;
++                              reg = <0>;
++                              interrupt-controller;
++                              #interrupt-cells = <2>;
++                              interrupts = <62 IRQ_TYPE_LEVEL_HIGH>;
++                      };
++              };
++
++              gpio3: gpio@3023000 {
++                      compatible = "snps,dw-apb-gpio";
++                      reg = <0x3023000 0x1000>;
++                      #address-cells = <1>;
++                      #size-cells = <0>;
++
++                      portd: gpio-controller@0 {
++                              compatible = "snps,dw-apb-gpio-port";
++                              gpio-controller;
++                              #gpio-cells = <2>;
++                              ngpios = <32>;
++                              reg = <0>;
++                              interrupt-controller;
++                              #interrupt-cells = <2>;
++                              interrupts = <63 IRQ_TYPE_LEVEL_HIGH>;
++                      };
++              };
++
+               uart0: serial@4140000 {
+                       compatible = "snps,dw-apb-uart";
+                       reg = <0x04140000 0x100>;
+-- 
+2.20.1
+
diff --git a/target/linux/cv18x0/patches-6.6/0009-drivers-mmc-sdhci-of-dwcmshc-include-bitfield.h-for-.patch b/target/linux/cv18x0/patches-6.6/0009-drivers-mmc-sdhci-of-dwcmshc-include-bitfield.h-for-.patch
new file mode 100644 (file)
index 0000000..56619b9
--- /dev/null
@@ -0,0 +1,26 @@
+From 1fc5411e948548ed58a082530f25a24edf1b7672 Mon Sep 17 00:00:00 2001
+From: Zoltan HERPAI <wigyori@uid0.hu>
+Date: Fri, 28 Jun 2024 15:11:04 +0000
+Subject: [PATCH 09/18] drivers: mmc: sdhci-of-dwcmshc: include bitfield.h for
+ FIELD_PREP
+
+Signed-off-by: Zoltan HERPAI <wigyori@uid0.hu>
+---
+ drivers/mmc/host/sdhci-of-dwcmshc.c | 1 +
+ 1 file changed, 1 insertion(+)
+
+diff --git a/drivers/mmc/host/sdhci-of-dwcmshc.c b/drivers/mmc/host/sdhci-of-dwcmshc.c
+index a0524127ca07..2d19b1403879 100644
+--- a/drivers/mmc/host/sdhci-of-dwcmshc.c
++++ b/drivers/mmc/host/sdhci-of-dwcmshc.c
+@@ -18,6 +18,7 @@
+ #include <linux/pm_runtime.h>
+ #include <linux/reset.h>
+ #include <linux/sizes.h>
++#include <linux/bitfield.h>
+ #include "sdhci-pltfm.h"
+-- 
+2.20.1
+
diff --git a/target/linux/cv18x0/patches-6.6/0010-mmc-sdhci-of-dwcmshc-Add-support-for-Sophgo-CV1800B-.patch b/target/linux/cv18x0/patches-6.6/0010-mmc-sdhci-of-dwcmshc-Add-support-for-Sophgo-CV1800B-.patch
new file mode 100644 (file)
index 0000000..b4d425f
--- /dev/null
@@ -0,0 +1,122 @@
+From 9abc21706dbb37af1da7d4c95c21c131bbc2d512 Mon Sep 17 00:00:00 2001
+From: Jisheng Zhang <jszhang@kernel.org>
+Date: Sat, 17 Feb 2024 22:42:02 +0800
+Subject: [PATCH 10/18] mmc: sdhci-of-dwcmshc: Add support for Sophgo CV1800B
+ and SG2002
+
+Add support for the mmc controller in the Sophgo CV1800B and SG2002
+with corresponding new compatible strings. Implement custom sdhci_ops.
+
+Signed-off-by: Jisheng Zhang <jszhang@kernel.org>
+---
+ drivers/mmc/host/sdhci-of-dwcmshc.c | 66 +++++++++++++++++++++++++++++
+ 1 file changed, 66 insertions(+)
+
+diff --git a/drivers/mmc/host/sdhci-of-dwcmshc.c b/drivers/mmc/host/sdhci-of-dwcmshc.c
+index 2d19b1403879..e473af22e585 100644
+--- a/drivers/mmc/host/sdhci-of-dwcmshc.c
++++ b/drivers/mmc/host/sdhci-of-dwcmshc.c
+@@ -37,6 +37,20 @@
+ #define DWCMSHC_ENHANCED_STROBE               BIT(8)
+ #define DWCMSHC_EMMC_ATCTRL           0x40
++/* Sophgo CV18XX specific Registers */
++#define CV18XX_SDHCI_MSHC_CTRL                        0x00
++#define  CV18XX_EMMC_FUNC_EN                  BIT(0)
++#define  CV18XX_LATANCY_1T                    BIT(1)
++#define CV18XX_SDHCI_PHY_TX_RX_DLY            0x40
++#define  CV18XX_PHY_TX_DLY_MSK                        GENMASK(6, 0)
++#define  CV18XX_PHY_TX_SRC_MSK                        GENMASK(9, 8)
++#define  CV18XX_PHY_TX_SRC_INVERT_CLK_TX      0x1
++#define  CV18XX_PHY_RX_DLY_MSK                        GENMASK(22, 16)
++#define  CV18XX_PHY_RX_SRC_MSK                        GENMASK(25, 24)
++#define  CV18XX_PHY_RX_SRC_INVERT_RX_CLK      0x1
++#define CV18XX_SDHCI_PHY_CONFIG                       0x4c
++#define  CV18XX_PHY_TX_BPS                    BIT(0)
++
+ /* Rockchip specific Registers */
+ #define DWCMSHC_EMMC_DLL_CTRL         0x800
+ #define DWCMSHC_EMMC_DLL_RXCLK                0x804
+@@ -339,6 +353,35 @@ static void rk35xx_sdhci_reset(struct sdhci_host *host, u8 mask)
+       sdhci_reset(host, mask);
+ }
++static void cv18xx_sdhci_reset(struct sdhci_host *host, u8 mask)
++{
++      struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
++      struct dwcmshc_priv *priv = sdhci_pltfm_priv(pltfm_host);
++      u32 val, emmc_caps = MMC_CAP2_NO_SD | MMC_CAP2_NO_SDIO;
++
++      sdhci_reset(host, mask);
++
++      if ((host->mmc->caps2 & emmc_caps) == emmc_caps) {
++              val = sdhci_readl(host, priv->vendor_specific_area1 + CV18XX_SDHCI_MSHC_CTRL);
++              val |= CV18XX_EMMC_FUNC_EN;
++              sdhci_writel(host, val, priv->vendor_specific_area1 + CV18XX_SDHCI_MSHC_CTRL);
++      }
++
++      val = sdhci_readl(host, priv->vendor_specific_area1 + CV18XX_SDHCI_MSHC_CTRL);
++      val |= CV18XX_LATANCY_1T;
++      sdhci_writel(host, val, priv->vendor_specific_area1 + CV18XX_SDHCI_MSHC_CTRL);
++
++      val = sdhci_readl(host, priv->vendor_specific_area1 + CV18XX_SDHCI_PHY_CONFIG);
++      val |= CV18XX_PHY_TX_BPS;
++      sdhci_writel(host, val, priv->vendor_specific_area1 + CV18XX_SDHCI_PHY_CONFIG);
++
++      val =  (FIELD_PREP(CV18XX_PHY_TX_DLY_MSK, 0) |
++              FIELD_PREP(CV18XX_PHY_TX_SRC_MSK, CV18XX_PHY_TX_SRC_INVERT_CLK_TX) |
++              FIELD_PREP(CV18XX_PHY_RX_DLY_MSK, 0) |
++              FIELD_PREP(CV18XX_PHY_RX_SRC_MSK, CV18XX_PHY_RX_SRC_INVERT_RX_CLK));
++      sdhci_writel(host, val, priv->vendor_specific_area1 + CV18XX_SDHCI_PHY_TX_RX_DLY);
++}
++
+ static const struct sdhci_ops sdhci_dwcmshc_ops = {
+       .set_clock              = sdhci_set_clock,
+       .set_bus_width          = sdhci_set_bus_width,
+@@ -357,6 +400,15 @@ static const struct sdhci_ops sdhci_dwcmshc_rk35xx_ops = {
+       .adma_write_desc        = dwcmshc_adma_write_desc,
+ };
++static const struct sdhci_ops sdhci_dwcmshc_cv18xx_ops = {
++      .set_clock              = sdhci_set_clock,
++      .set_bus_width          = sdhci_set_bus_width,
++      .set_uhs_signaling      = dwcmshc_set_uhs_signaling,
++      .get_max_clock          = dwcmshc_get_max_clock,
++      .reset                  = cv18xx_sdhci_reset,
++      .adma_write_desc        = dwcmshc_adma_write_desc,
++};
++
+ static const struct sdhci_pltfm_data sdhci_dwcmshc_pdata = {
+       .ops = &sdhci_dwcmshc_ops,
+       .quirks = SDHCI_QUIRK_CAP_CLOCK_BASE_BROKEN,
+@@ -380,6 +432,12 @@ static const struct sdhci_pltfm_data sdhci_dwcmshc_rk35xx_pdata = {
+                  SDHCI_QUIRK2_CLOCK_DIV_ZERO_BROKEN,
+ };
++static const struct sdhci_pltfm_data sdhci_dwcmshc_cv18xx_pdata = {
++      .ops = &sdhci_dwcmshc_cv18xx_ops,
++      .quirks = SDHCI_QUIRK_CAP_CLOCK_BASE_BROKEN,
++      .quirks2 = SDHCI_QUIRK2_PRESET_VALUE_BROKEN,
++};
++
+ static int dwcmshc_rk35xx_init(struct sdhci_host *host, struct dwcmshc_priv *dwc_priv)
+ {
+       int err;
+@@ -444,6 +502,14 @@ static const struct of_device_id sdhci_dwcmshc_dt_ids[] = {
+               .compatible = "rockchip,rk3568-dwcmshc",
+               .data = &sdhci_dwcmshc_rk35xx_pdata,
+       },
++      {
++              .compatible = "sophgo,cv1800b-dwcmshc",
++              .data = &sdhci_dwcmshc_cv18xx_pdata,
++      },
++      {
++              .compatible = "sophgo,sg2002-dwcmshc",
++              .data = &sdhci_dwcmshc_cv18xx_pdata,
++      },
+       {
+               .compatible = "snps,dwcmshc-sdhci",
+               .data = &sdhci_dwcmshc_pdata,
+-- 
+2.20.1
+
diff --git a/target/linux/cv18x0/patches-6.6/0011-dt-bindings-clock-sophgo-Add-clock-controller-of-CV1.patch b/target/linux/cv18x0/patches-6.6/0011-dt-bindings-clock-sophgo-Add-clock-controller-of-CV1.patch
new file mode 100644 (file)
index 0000000..74d1a6a
--- /dev/null
@@ -0,0 +1,206 @@
+From 7304fd40e7822e1d51229c532ad9271577b212f0 Mon Sep 17 00:00:00 2001
+From: Inochi Amaoto <inochiama@outlook.com>
+Date: Mon, 18 Dec 2023 12:04:03 +0800
+Subject: [PATCH 11/18] dt-bindings: clock: sophgo: Add clock controller of
+ CV1800 series SoC
+
+Add definition for the clock controller of the CV1800 series SoC.
+
+For CV181X, it has a clock that CV180X does not have. To avoid misuse,
+also add a compatible string to identify CV181X series SoC.
+
+Signed-off-by: Inochi Amaoto <inochiama@outlook.com>
+Link: https://github.com/milkv-duo/duo-files/blob/main/hardware/CV1800B/CV1800B-CV1801B-Preliminary-Datasheet-full-en.pdf
+Reviewed-by: Krzysztof Kozlowski <krzysztof.kozlowski@linaro.org>
+Link: https://lore.kernel.org/r/IA1PR20MB49535E448097F6FFC1218C39BB90A@IA1PR20MB4953.namprd20.prod.outlook.com
+Signed-off-by: Stephen Boyd <sboyd@kernel.org>
+---
+ 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 000000000000..cfbeca25a650
+--- /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__ */
+-- 
+2.20.1
+
diff --git a/target/linux/cv18x0/patches-6.6/0012-clk-sophgo-Add-CV1800-SG2000-series-clock-controller.patch b/target/linux/cv18x0/patches-6.6/0012-clk-sophgo-Add-CV1800-SG2000-series-clock-controller.patch
new file mode 100644 (file)
index 0000000..dafe8b6
--- /dev/null
@@ -0,0 +1,3743 @@
+From ff1199b26c397a8dfd94a72565c515c20474f468 Mon Sep 17 00:00:00 2001
+From: Inochi Amaoto <inochiama@outlook.com>
+Date: Tue, 13 Feb 2024 16:22:34 +0800
+Subject: [PATCH 12/18] clk: sophgo: Add CV1800/SG2000 series clock controller
+ driver skeleton
+
+Add driver skeleton for CV1800/SG2000 series clock controller.
+The skeleton code includes:
+1. common utility code for clk_ops implementation
+2. basic probe code of the whole driver
+3. helper structure for clk definition
+
+Signed-off-by: Inochi Amaoto <inochiama@outlook.com>
+---
+ arch/riscv/boot/dts/sophgo/cv1800b.dtsi |    4 +
+ arch/riscv/boot/dts/sophgo/cv1812h.dtsi |    4 +
+ arch/riscv/boot/dts/sophgo/cv18xx.dtsi  |   22 +-
+ drivers/clk/Kconfig                     |    1 +
+ drivers/clk/Makefile                    |    1 +
+ drivers/clk/sophgo/Kconfig              |   12 +
+ drivers/clk/sophgo/Makefile             |    7 +
+ drivers/clk/sophgo/clk-cv1800.c         | 1541 +++++++++++++++++++++++
+ drivers/clk/sophgo/clk-cv1800.h         |  123 ++
+ drivers/clk/sophgo/clk-cv18xx-common.c  |   66 +
+ drivers/clk/sophgo/clk-cv18xx-common.h  |   81 ++
+ drivers/clk/sophgo/clk-cv18xx-ip.c      |  887 +++++++++++++
+ drivers/clk/sophgo/clk-cv18xx-ip.h      |  261 ++++
+ drivers/clk/sophgo/clk-cv18xx-pll.c     |  420 ++++++
+ drivers/clk/sophgo/clk-cv18xx-pll.h     |  118 ++
+ 15 files changed, 3543 insertions(+), 5 deletions(-)
+ create mode 100644 drivers/clk/sophgo/Kconfig
+ create mode 100644 drivers/clk/sophgo/Makefile
+ create mode 100644 drivers/clk/sophgo/clk-cv1800.c
+ create mode 100644 drivers/clk/sophgo/clk-cv1800.h
+ create mode 100644 drivers/clk/sophgo/clk-cv18xx-common.c
+ create mode 100644 drivers/clk/sophgo/clk-cv18xx-common.h
+ create mode 100644 drivers/clk/sophgo/clk-cv18xx-ip.c
+ create mode 100644 drivers/clk/sophgo/clk-cv18xx-ip.h
+ create mode 100644 drivers/clk/sophgo/clk-cv18xx-pll.c
+ create mode 100644 drivers/clk/sophgo/clk-cv18xx-pll.h
+
+diff --git a/arch/riscv/boot/dts/sophgo/cv1800b.dtsi b/arch/riscv/boot/dts/sophgo/cv1800b.dtsi
+index 165e9e320a8c..baf641829e72 100644
+--- a/arch/riscv/boot/dts/sophgo/cv1800b.dtsi
++++ b/arch/riscv/boot/dts/sophgo/cv1800b.dtsi
+@@ -16,3 +16,7 @@
+ &clint {
+       compatible = "sophgo,cv1800b-clint", "thead,c900-clint";
+ };
++
++&clk {
++      compatible = "sophgo,cv1800-clk";
++};
+diff --git a/arch/riscv/boot/dts/sophgo/cv1812h.dtsi b/arch/riscv/boot/dts/sophgo/cv1812h.dtsi
+index 3e7a942f5c1a..7fa4c1e2d1da 100644
+--- a/arch/riscv/boot/dts/sophgo/cv1812h.dtsi
++++ b/arch/riscv/boot/dts/sophgo/cv1812h.dtsi
+@@ -22,3 +22,7 @@
+ &clint {
+       compatible = "sophgo,cv1812h-clint", "thead,c900-clint";
+ };
++
++&clk {
++      compatible = "sophgo,cv1810-clk";
++};
+diff --git a/arch/riscv/boot/dts/sophgo/cv18xx.dtsi b/arch/riscv/boot/dts/sophgo/cv18xx.dtsi
+index d415cc758def..e375e9d9516e 100644
+--- a/arch/riscv/boot/dts/sophgo/cv18xx.dtsi
++++ b/arch/riscv/boot/dts/sophgo/cv18xx.dtsi
+@@ -5,6 +5,7 @@
+  */
+ #include <dt-bindings/interrupt-controller/irq.h>
++#include <dt-bindings/clock/sophgo,cv1800.h>
+ / {
+       #address-cells = <1>;
+@@ -54,6 +55,12 @@
+               dma-noncoherent;
+               ranges;
++              clk: clock-controller@3002000 {
++                      reg = <0x03002000 0x1000>;
++                      clocks = <&osc>;
++                      #clock-cells = <1>;
++              };
++
+               gpio0: gpio@3020000 {
+                       compatible = "snps,dw-apb-gpio";
+                       reg = <0x3020000 0x1000>;
+@@ -130,7 +137,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";
+@@ -140,7 +148,8 @@
+                       compatible = "snps,dw-apb-uart";
+                       reg = <0x04150000 0x100>;
+                       interrupts = <45 IRQ_TYPE_LEVEL_HIGH>;
+-                      clocks = <&osc>;
++                      clocks = <&clk CLK_UART1>, <&clk CLK_APB_UART1>;
++                      clock-names = "baudclk", "apb_pclk";
+                       reg-shift = <2>;
+                       reg-io-width = <4>;
+                       status = "disabled";
+@@ -150,7 +159,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";
+@@ -160,7 +170,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";
+@@ -170,7 +181,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";
+diff --git a/drivers/clk/Kconfig b/drivers/clk/Kconfig
+index c30099866174..f3ec23f22e3e 100644
+--- a/drivers/clk/Kconfig
++++ b/drivers/clk/Kconfig
+@@ -490,6 +490,7 @@ source "drivers/clk/rockchip/Kconfig"
+ source "drivers/clk/samsung/Kconfig"
+ source "drivers/clk/sifive/Kconfig"
+ source "drivers/clk/socfpga/Kconfig"
++source "drivers/clk/sophgo/Kconfig"
+ source "drivers/clk/sprd/Kconfig"
+ source "drivers/clk/starfive/Kconfig"
+ source "drivers/clk/sunxi/Kconfig"
+diff --git a/drivers/clk/Makefile b/drivers/clk/Makefile
+index 18969cbd4bb1..acac827d906a 100644
+--- a/drivers/clk/Makefile
++++ b/drivers/clk/Makefile
+@@ -117,6 +117,7 @@ obj-$(CONFIG_ARCH_ROCKCHIP)                += rockchip/
+ obj-$(CONFIG_COMMON_CLK_SAMSUNG)      += samsung/
+ obj-$(CONFIG_CLK_SIFIVE)              += sifive/
+ obj-y                                 += socfpga/
++obj-y                                 += sophgo/
+ obj-$(CONFIG_PLAT_SPEAR)              += spear/
+ obj-y                                 += sprd/
+ obj-$(CONFIG_ARCH_STI)                        += st/
+diff --git a/drivers/clk/sophgo/Kconfig b/drivers/clk/sophgo/Kconfig
+new file mode 100644
+index 000000000000..d67009fa749f
+--- /dev/null
++++ b/drivers/clk/sophgo/Kconfig
+@@ -0,0 +1,12 @@
++# SPDX-License-Identifier: GPL-2.0
++# common clock support for SOPHGO SoC family.
++
++config CLK_SOPHGO_CV1800
++      tristate "Support for the Sophgo CV1800 series SoCs clock controller"
++      default m
++      depends on ARCH_SOPHGO || COMPILE_TEST
++      help
++        This driver supports clock controller of Sophgo CV18XX series SoC.
++        The driver require a 25MHz Oscillator to function generate clock.
++        It includes PLLs, common clock function and some vendor clock for
++        IPs of CV18XX series SoC
+diff --git a/drivers/clk/sophgo/Makefile b/drivers/clk/sophgo/Makefile
+new file mode 100644
+index 000000000000..a50320764200
+--- /dev/null
++++ b/drivers/clk/sophgo/Makefile
+@@ -0,0 +1,7 @@
++# SPDX-License-Identifier: GPL-2.0
++obj-$(CONFIG_CLK_SOPHGO_CV1800)       += clk-sophgo-cv1800.o
++
++clk-sophgo-cv1800-y           += clk-cv1800.o
++clk-sophgo-cv1800-y           += clk-cv18xx-common.o
++clk-sophgo-cv1800-y           += clk-cv18xx-ip.o
++clk-sophgo-cv1800-y           += clk-cv18xx-pll.o
+diff --git a/drivers/clk/sophgo/clk-cv1800.c b/drivers/clk/sophgo/clk-cv1800.c
+new file mode 100644
+index 000000000000..1aedf2df242c
+--- /dev/null
++++ b/drivers/clk/sophgo/clk-cv1800.c
+@@ -0,0 +1,1541 @@
++// SPDX-License-Identifier: GPL-2.0
++/*
++ * Copyright (C) 2023 Inochi Amaoto <inochiama@outlook.com>
++ */
++
++#include <linux/module.h>
++#include <linux/clk-provider.h>
++#include <linux/platform_device.h>
++#include <linux/io.h>
++#include <linux/spinlock.h>
++
++#include "clk-cv1800.h"
++
++#include "clk-cv18xx-common.h"
++#include "clk-cv18xx-ip.h"
++#include "clk-cv18xx-pll.h"
++
++struct cv1800_clk_ctrl;
++
++struct cv1800_clk_desc {
++      struct clk_hw_onecell_data      *clks_data;
++
++      int (*pre_init)(struct device *dev, void __iomem *base,
++                      struct cv1800_clk_ctrl *ctrl,
++                      const struct cv1800_clk_desc *desc);
++};
++
++struct cv1800_clk_ctrl {
++      const struct cv1800_clk_desc    *desc;
++      spinlock_t                      lock;
++};
++
++#define CV1800_DIV_FLAG       \
++      (CLK_DIVIDER_ONE_BASED | CLK_DIVIDER_ROUND_CLOSEST)
++static const struct clk_parent_data osc_parents[] = {
++      { .index = 0 },
++};
++
++static const struct cv1800_clk_pll_limit pll_limits[] = {
++      {
++              .pre_div        = _CV1800_PLL_LIMIT(1, 127),
++              .div            = _CV1800_PLL_LIMIT(6, 127),
++              .post_div       = _CV1800_PLL_LIMIT(1, 127),
++              .ictrl          = _CV1800_PLL_LIMIT(0, 7),
++              .mode           = _CV1800_PLL_LIMIT(0, 3),
++      },
++      {
++              .pre_div        = _CV1800_PLL_LIMIT(1, 127),
++              .div            = _CV1800_PLL_LIMIT(6, 127),
++              .post_div       = _CV1800_PLL_LIMIT(1, 127),
++              .ictrl          = _CV1800_PLL_LIMIT(0, 7),
++              .mode           = _CV1800_PLL_LIMIT(0, 3),
++      },
++};
++
++static CV1800_INTEGRAL_PLL(clk_fpll, osc_parents,
++                         REG_FPLL_CSR,
++                         REG_PLL_G6_CTRL, 8,
++                         REG_PLL_G6_STATUS, 2,
++                         pll_limits,
++                         CLK_IS_CRITICAL);
++
++static CV1800_INTEGRAL_PLL(clk_mipimpll, osc_parents,
++                         REG_MIPIMPLL_CSR,
++                         REG_PLL_G2_CTRL, 0,
++                         REG_PLL_G2_STATUS, 0,
++                         pll_limits,
++                         CLK_IS_CRITICAL);
++
++static const struct clk_parent_data clk_mipimpll_parents[] = {
++      { .hw = &clk_mipimpll.common.hw },
++};
++static const struct clk_parent_data clk_bypass_mipimpll_parents[] = {
++      { .index = 0 },
++      { .hw = &clk_mipimpll.common.hw },
++};
++static const struct clk_parent_data clk_bypass_fpll_parents[] = {
++      { .index = 0 },
++      { .hw = &clk_fpll.common.hw },
++};
++
++struct cv1800_clk_pll_synthesizer clk_mpll_synthesizer = {
++      .en             = CV1800_CLK_BIT(REG_PLL_G6_SSC_SYN_CTRL, 2),
++      .clk_half       = CV1800_CLK_BIT(REG_PLL_G6_SSC_SYN_CTRL, 0),
++      .ctrl           = REG_MPLL_SSC_SYN_CTRL,
++      .set            = REG_MPLL_SSC_SYN_SET,
++};
++static CV1800_FACTIONAL_PLL(clk_mpll, clk_bypass_mipimpll_parents,
++                          REG_MPLL_CSR,
++                          REG_PLL_G6_CTRL, 0,
++                          REG_PLL_G6_STATUS, 0,
++                          pll_limits,
++                          &clk_mpll_synthesizer,
++                          CLK_IS_CRITICAL);
++
++struct cv1800_clk_pll_synthesizer clk_tpll_synthesizer = {
++      .en             = CV1800_CLK_BIT(REG_PLL_G6_SSC_SYN_CTRL, 3),
++      .clk_half       = CV1800_CLK_BIT(REG_PLL_G6_SSC_SYN_CTRL, 0),
++      .ctrl           = REG_TPLL_SSC_SYN_CTRL,
++      .set            = REG_TPLL_SSC_SYN_SET,
++};
++static CV1800_FACTIONAL_PLL(clk_tpll, clk_bypass_mipimpll_parents,
++                          REG_TPLL_CSR,
++                          REG_PLL_G6_CTRL, 4,
++                          REG_PLL_G6_STATUS, 1,
++                          pll_limits,
++                          &clk_tpll_synthesizer,
++                          CLK_IS_CRITICAL);
++
++struct cv1800_clk_pll_synthesizer clk_a0pll_synthesizer = {
++      .en             = CV1800_CLK_BIT(REG_PLL_G2_SSC_SYN_CTRL, 2),
++      .clk_half       = CV1800_CLK_BIT(REG_PLL_G2_SSC_SYN_CTRL, 0),
++      .ctrl           = REG_A0PLL_SSC_SYN_CTRL,
++      .set            = REG_A0PLL_SSC_SYN_SET,
++};
++static CV1800_FACTIONAL_PLL(clk_a0pll, clk_bypass_mipimpll_parents,
++                          REG_A0PLL_CSR,
++                          REG_PLL_G2_CTRL, 4,
++                          REG_PLL_G2_STATUS, 1,
++                          pll_limits,
++                          &clk_a0pll_synthesizer,
++                          CLK_IS_CRITICAL);
++
++struct cv1800_clk_pll_synthesizer clk_disppll_synthesizer = {
++      .en             = CV1800_CLK_BIT(REG_PLL_G2_SSC_SYN_CTRL, 3),
++      .clk_half       = CV1800_CLK_BIT(REG_PLL_G2_SSC_SYN_CTRL, 0),
++      .ctrl           = REG_DISPPLL_SSC_SYN_CTRL,
++      .set            = REG_DISPPLL_SSC_SYN_SET,
++};
++static CV1800_FACTIONAL_PLL(clk_disppll, clk_bypass_mipimpll_parents,
++                          REG_DISPPLL_CSR,
++                          REG_PLL_G2_CTRL, 8,
++                          REG_PLL_G2_STATUS, 2,
++                          pll_limits,
++                          &clk_disppll_synthesizer,
++                          CLK_IS_CRITICAL);
++
++struct cv1800_clk_pll_synthesizer clk_cam0pll_synthesizer = {
++      .en             = CV1800_CLK_BIT(REG_PLL_G2_SSC_SYN_CTRL, 4),
++      .clk_half       = CV1800_CLK_BIT(REG_PLL_G2_SSC_SYN_CTRL, 0),
++      .ctrl           = REG_CAM0PLL_SSC_SYN_CTRL,
++      .set            = REG_CAM0PLL_SSC_SYN_SET,
++};
++static CV1800_FACTIONAL_PLL(clk_cam0pll, clk_bypass_mipimpll_parents,
++                          REG_CAM0PLL_CSR,
++                          REG_PLL_G2_CTRL, 12,
++                          REG_PLL_G2_STATUS, 3,
++                          pll_limits,
++                          &clk_cam0pll_synthesizer,
++                          CLK_IGNORE_UNUSED);
++
++struct cv1800_clk_pll_synthesizer clk_cam1pll_synthesizer = {
++      .en             = CV1800_CLK_BIT(REG_PLL_G2_SSC_SYN_CTRL, 5),
++      .clk_half       = CV1800_CLK_BIT(REG_PLL_G2_SSC_SYN_CTRL, 0),
++      .ctrl           = REG_CAM1PLL_SSC_SYN_CTRL,
++      .set            = REG_CAM1PLL_SSC_SYN_SET,
++};
++static CV1800_FACTIONAL_PLL(clk_cam1pll, clk_bypass_mipimpll_parents,
++                          REG_CAM1PLL_CSR,
++                          REG_PLL_G2_CTRL, 16,
++                          REG_PLL_G2_STATUS, 4,
++                          pll_limits,
++                          &clk_cam1pll_synthesizer,
++                          CLK_IS_CRITICAL);
++
++static const struct clk_parent_data clk_cam0pll_parents[] = {
++      { .hw = &clk_cam0pll.common.hw },
++};
++
++/* G2D */
++static CV1800_FIXED_DIV(clk_cam0pll_d2, clk_cam0pll_parents,
++                      REG_CAM0PLL_CLK_CSR, 1,
++                      2,
++                      CLK_SET_RATE_PARENT | CLK_IGNORE_UNUSED);
++static CV1800_FIXED_DIV(clk_cam0pll_d3, clk_cam0pll_parents,
++                      REG_CAM0PLL_CLK_CSR, 2,
++                      3,
++                      CLK_SET_RATE_PARENT | CLK_IGNORE_UNUSED);
++static CV1800_FIXED_DIV(clk_mipimpll_d3, clk_mipimpll_parents,
++                      REG_MIPIMPLL_CLK_CSR, 2,
++                      3,
++                      CLK_SET_RATE_PARENT | CLK_IGNORE_UNUSED);
++
++/* TPU */
++static const struct clk_parent_data clk_tpu_parents[] = {
++      { .index = 0 },
++      { .hw = &clk_tpll.common.hw },
++      { .hw = &clk_a0pll.common.hw },
++      { .hw = &clk_mipimpll.common.hw },
++      { .hw = &clk_fpll.common.hw },
++};
++
++static CV1800_BYPASS_MUX(clk_tpu, clk_tpu_parents,
++                       REG_CLK_EN_0, 4,
++                       REG_DIV_CLK_TPU, 16, 4, 3, CV1800_DIV_FLAG,
++                       REG_DIV_CLK_TPU, 8, 2,
++                       REG_CLK_BYP_0, 3,
++                       0);
++static CV1800_GATE(clk_tpu_fab, clk_mipimpll_parents,
++                 REG_CLK_EN_0, 5,
++                 0);
++
++/* FABRIC_AXI6 */
++static CV1800_BYPASS_DIV(clk_axi6, clk_bypass_fpll_parents,
++                       REG_CLK_EN_2, 2,
++                       REG_DIV_CLK_AXI6, 16, 4, 15, CV1800_DIV_FLAG,
++                       REG_CLK_BYP_0, 20,
++                       CLK_IS_CRITICAL);
++
++static const struct clk_parent_data clk_axi6_bus_parents[] = {
++      { .hw = &clk_axi6.div.common.hw },
++};
++static const struct clk_parent_data clk_bypass_axi6_bus_parents[] = {
++      { .index = 0 },
++      { .hw = &clk_axi6.div.common.hw },
++};
++
++/* FABRIC_AXI4 */
++static const struct clk_parent_data clk_axi4_parents[] = {
++      { .index = 0 },
++      { .hw = &clk_fpll.common.hw },
++      { .hw = &clk_disppll.common.hw },
++};
++
++static CV1800_BYPASS_MUX(clk_axi4, clk_axi4_parents,
++                       REG_CLK_EN_2, 1,
++                       REG_DIV_CLK_AXI4, 16, 4, 5, CV1800_DIV_FLAG,
++                       REG_DIV_CLK_AXI4, 8, 2,
++                       REG_CLK_BYP_0, 19,
++                       CLK_IS_CRITICAL);
++
++static const struct clk_parent_data clk_axi4_bus_parents[] = {
++      { .hw = &clk_axi4.mux.common.hw },
++};
++
++/* XTAL_MISC */
++static CV1800_GATE(clk_xtal_misc, osc_parents,
++                 REG_CLK_EN_0, 14,
++                 CLK_IS_CRITICAL);
++
++static const struct clk_parent_data clk_timer_parents[] = {
++      { .hw = &clk_xtal_misc.common.hw },
++};
++
++/* TOP */
++static const struct clk_parent_data clk_cam0_200_parents[] = {
++      { .index = 0 },
++      { .index = 0 },
++      { .hw = &clk_disppll.common.hw },
++};
++
++static CV1800_BYPASS_MUX(clk_cam0_200, clk_cam0_200_parents,
++                       REG_CLK_EN_1, 13,
++                       REG_DIV_CLK_CAM0_200, 16, 4, 1, CV1800_DIV_FLAG,
++                       REG_DIV_CLK_CAM0_200, 8, 2,
++                       REG_CLK_BYP_0, 16,
++                       CLK_IS_CRITICAL);
++static CV1800_DIV(clk_1m, osc_parents,
++                REG_CLK_EN_3, 5,
++                REG_DIV_CLK_1M, 16, 6, 25, CV1800_DIV_FLAG,
++                CLK_IS_CRITICAL);
++static CV1800_GATE(clk_pm, clk_axi6_bus_parents,
++                 REG_CLK_EN_3, 8,
++                 CLK_IS_CRITICAL);
++static CV1800_GATE(clk_timer0, clk_timer_parents,
++                 REG_CLK_EN_3, 9,
++                 CLK_IS_CRITICAL);
++static CV1800_GATE(clk_timer1, clk_timer_parents,
++                 REG_CLK_EN_3, 10,
++                 CLK_IS_CRITICAL);
++static CV1800_GATE(clk_timer2, clk_timer_parents,
++                 REG_CLK_EN_3, 11,
++                 CLK_IS_CRITICAL);
++static CV1800_GATE(clk_timer3, clk_timer_parents,
++                 REG_CLK_EN_3, 12,
++                 CLK_IS_CRITICAL);
++static CV1800_GATE(clk_timer4, clk_timer_parents,
++                 REG_CLK_EN_3, 13,
++                 CLK_IS_CRITICAL);
++static CV1800_GATE(clk_timer5, clk_timer_parents,
++                 REG_CLK_EN_3, 14,
++                 CLK_IS_CRITICAL);
++static CV1800_GATE(clk_timer6, clk_timer_parents,
++                 REG_CLK_EN_3, 15,
++                 CLK_IS_CRITICAL);
++static CV1800_GATE(clk_timer7, clk_timer_parents,
++                 REG_CLK_EN_3, 16,
++                 CLK_IS_CRITICAL);
++
++static const struct clk_parent_data clk_parents_1m[] = {
++      { .hw = &clk_1m.common.hw },
++};
++static const struct clk_parent_data clk_uart_parents[] = {
++      { .hw = &clk_cam0_200.mux.common.hw },
++};
++
++/* AHB ROM */
++static CV1800_GATE(clk_ahb_rom, clk_axi4_bus_parents,
++                 REG_CLK_EN_0, 6,
++                 0);
++
++/* RTC */
++static CV1800_GATE(clk_rtc_25m, osc_parents,
++                 REG_CLK_EN_0, 8,
++                 CLK_IS_CRITICAL);
++static CV1800_BYPASS_DIV(clk_src_rtc_sys_0, clk_bypass_fpll_parents,
++                       REG_CLK_EN_4, 6,
++                       REG_DIV_CLK_RTCSYS_SRC_0, 16, 4, 5, CV1800_DIV_FLAG,
++                       REG_CLK_BYP_1, 5,
++                       CLK_IS_CRITICAL);
++
++/* TEMPSEN */
++static CV1800_GATE(clk_tempsen, osc_parents,
++                 REG_CLK_EN_0, 9,
++                 0);
++
++/* SARADC */
++static CV1800_GATE(clk_saradc, osc_parents,
++                 REG_CLK_EN_0, 10,
++                 0);
++
++/* EFUSE */
++static CV1800_GATE(clk_efuse, osc_parents,
++                 REG_CLK_EN_0, 11,
++                 0);
++static CV1800_GATE(clk_apb_efuse, osc_parents,
++                 REG_CLK_EN_0, 12,
++                 0);
++
++/* WDT */
++static CV1800_GATE(clk_apb_wdt, osc_parents,
++                 REG_CLK_EN_1, 7,
++                 CLK_IS_CRITICAL);
++
++/* WGN */
++static CV1800_GATE(clk_wgn, osc_parents,
++                 REG_CLK_EN_3, 22,
++                 0);
++static CV1800_GATE(clk_wgn0, osc_parents,
++                 REG_CLK_EN_3, 23,
++                 0);
++static CV1800_GATE(clk_wgn1, osc_parents,
++                 REG_CLK_EN_3, 24,
++                 0);
++static CV1800_GATE(clk_wgn2, osc_parents,
++                 REG_CLK_EN_3, 25,
++                 0);
++
++/* KEYSCAN */
++static CV1800_GATE(clk_keyscan, osc_parents,
++                 REG_CLK_EN_3, 26,
++                 0);
++
++/* EMMC */
++static CV1800_GATE(clk_axi4_emmc, clk_axi4_bus_parents,
++                 REG_CLK_EN_0, 15,
++                 0);
++static CV1800_BYPASS_MUX(clk_emmc, clk_axi4_parents,
++                       REG_CLK_EN_0, 16,
++                       REG_DIV_CLK_EMMC, 16, 5, 15, CV1800_DIV_FLAG,
++                       REG_DIV_CLK_EMMC, 8, 2,
++                       REG_CLK_BYP_0, 5,
++                       0);
++static CV1800_DIV(clk_emmc_100k, clk_parents_1m,
++                REG_CLK_EN_0, 17,
++                REG_DIV_CLK_EMMC_100K, 16, 8, 10, CV1800_DIV_FLAG,
++                0);
++
++/* SD */
++static CV1800_GATE(clk_axi4_sd0, clk_axi4_bus_parents,
++                 REG_CLK_EN_0, 18,
++                 0);
++static CV1800_BYPASS_MUX(clk_sd0, clk_axi4_parents,
++                       REG_CLK_EN_0, 19,
++                       REG_DIV_CLK_SD0, 16, 5, 15, CV1800_DIV_FLAG,
++                       REG_DIV_CLK_SD0, 8, 2,
++                       REG_CLK_BYP_0, 6,
++                       0);
++static CV1800_DIV(clk_sd0_100k, clk_parents_1m,
++                REG_CLK_EN_0, 20,
++                REG_DIV_CLK_SD0_100K, 16, 8, 10, CV1800_DIV_FLAG,
++                0);
++static CV1800_GATE(clk_axi4_sd1, clk_axi4_bus_parents,
++                 REG_CLK_EN_0, 21,
++                 0);
++static CV1800_BYPASS_MUX(clk_sd1, clk_axi4_parents,
++                       REG_CLK_EN_0, 22,
++                       REG_DIV_CLK_SD1, 16, 5, 15, CV1800_DIV_FLAG,
++                       REG_DIV_CLK_SD1, 8, 2,
++                       REG_CLK_BYP_0, 7,
++                       0);
++static CV1800_DIV(clk_sd1_100k, clk_parents_1m,
++                REG_CLK_EN_0, 23,
++                REG_DIV_CLK_SD1_100K, 16, 8, 10, CV1800_DIV_FLAG,
++                0);
++
++/* SPI NAND */
++static CV1800_BYPASS_MUX(clk_spi_nand, clk_axi4_parents,
++                       REG_CLK_EN_0, 24,
++                       REG_DIV_CLK_SPI_NAND, 16, 5, 8, CV1800_DIV_FLAG,
++                       REG_DIV_CLK_SPI_NAND, 8, 2,
++                       REG_CLK_BYP_0, 8,
++                       0);
++
++/* GPIO */
++static CV1800_DIV(clk_gpio_db, clk_parents_1m,
++                REG_CLK_EN_0, 31,
++                REG_DIV_CLK_GPIO_DB, 16, 16, 10, CV1800_DIV_FLAG,
++                CLK_IS_CRITICAL);
++static CV1800_GATE(clk_apb_gpio, clk_axi6_bus_parents,
++                 REG_CLK_EN_0, 29,
++                 CLK_IS_CRITICAL);
++static CV1800_GATE(clk_apb_gpio_intr, clk_axi6_bus_parents,
++                 REG_CLK_EN_0, 30,
++                 CLK_IS_CRITICAL);
++
++/* ETH */
++static CV1800_BYPASS_DIV(clk_eth0_500m, clk_bypass_fpll_parents,
++                       REG_CLK_EN_0, 25,
++                       REG_DIV_CLK_GPIO_DB, 16, 4, 3, CV1800_DIV_FLAG,
++                       REG_CLK_BYP_0, 9,
++                       0);
++static CV1800_GATE(clk_axi4_eth0, clk_axi4_bus_parents,
++                 REG_CLK_EN_0, 26,
++                 0);
++static CV1800_BYPASS_DIV(clk_eth1_500m, clk_bypass_fpll_parents,
++                       REG_CLK_EN_0, 27,
++                       REG_DIV_CLK_GPIO_DB, 16, 4, 3, CV1800_DIV_FLAG,
++                       REG_CLK_BYP_0, 10,
++                       0);
++static CV1800_GATE(clk_axi4_eth1, clk_axi4_bus_parents,
++                 REG_CLK_EN_0, 28,
++                 0);
++
++/* SF */
++static CV1800_GATE(clk_ahb_sf, clk_axi4_bus_parents,
++                 REG_CLK_EN_1, 0,
++                 0);
++static CV1800_GATE(clk_ahb_sf1, clk_axi4_bus_parents,
++                 REG_CLK_EN_3, 27,
++                 0);
++
++/* AUDSRC */
++static CV1800_ACLK(clk_a24m, clk_mipimpll_parents,
++                 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, CV1800_DIV_FLAG,
++                 REG_APLL_FRAC_DIV_N, 0, 22, CV1800_DIV_FLAG,
++                 24576000,
++                 0);
++
++static const struct clk_parent_data clk_aud_parents[] = {
++      { .index = 0 },
++      { .hw = &clk_a0pll.common.hw },
++      { .hw = &clk_a24m.common.hw },
++};
++
++static CV1800_BYPASS_MUX(clk_audsrc, clk_aud_parents,
++                       REG_CLK_EN_4, 1,
++                       REG_DIV_CLK_AUDSRC, 16, 8, 18, CV1800_DIV_FLAG,
++                       REG_DIV_CLK_AUDSRC, 8, 2,
++                       REG_CLK_BYP_1, 2,
++                       0);
++static CV1800_GATE(clk_apb_audsrc, clk_axi4_bus_parents,
++                 REG_CLK_EN_4, 2,
++                 0);
++
++/* SDMA */
++static CV1800_GATE(clk_sdma_axi, clk_axi4_bus_parents,
++                 REG_CLK_EN_1, 1,
++                 0);
++static CV1800_BYPASS_MUX(clk_sdma_aud0, clk_aud_parents,
++                       REG_CLK_EN_1, 2,
++                       REG_DIV_CLK_SDMA_AUD0, 16, 8, 18, CV1800_DIV_FLAG,
++                       REG_DIV_CLK_SDMA_AUD0, 8, 2,
++                       REG_CLK_BYP_0, 11,
++                       0);
++static CV1800_BYPASS_MUX(clk_sdma_aud1, clk_aud_parents,
++                       REG_CLK_EN_1, 3,
++                       REG_DIV_CLK_SDMA_AUD1, 16, 8, 18, CV1800_DIV_FLAG,
++                       REG_DIV_CLK_SDMA_AUD1, 8, 2,
++                       REG_CLK_BYP_0, 12,
++                       0);
++static CV1800_BYPASS_MUX(clk_sdma_aud2, clk_aud_parents,
++                       REG_CLK_EN_1, 3,
++                       REG_DIV_CLK_SDMA_AUD2, 16, 8, 18, CV1800_DIV_FLAG,
++                       REG_DIV_CLK_SDMA_AUD2, 8, 2,
++                       REG_CLK_BYP_0, 13,
++                       0);
++static CV1800_BYPASS_MUX(clk_sdma_aud3, clk_aud_parents,
++                       REG_CLK_EN_1, 3,
++                       REG_DIV_CLK_SDMA_AUD3, 16, 8, 18, CV1800_DIV_FLAG,
++                       REG_DIV_CLK_SDMA_AUD3, 8, 2,
++                       REG_CLK_BYP_0, 14,
++                       0);
++
++/* SPI */
++static CV1800_GATE(clk_apb_spi0, clk_axi4_bus_parents,
++                 REG_CLK_EN_1, 9,
++                 0);
++static CV1800_GATE(clk_apb_spi1, clk_axi4_bus_parents,
++                 REG_CLK_EN_1, 10,
++                 0);
++static CV1800_GATE(clk_apb_spi2, clk_axi4_bus_parents,
++                 REG_CLK_EN_1, 11,
++                 0);
++static CV1800_GATE(clk_apb_spi3, clk_axi4_bus_parents,
++                 REG_CLK_EN_1, 12,
++                 0);
++static CV1800_BYPASS_DIV(clk_spi, clk_bypass_fpll_parents,
++                       REG_CLK_EN_3, 6,
++                       REG_DIV_CLK_SPI, 16, 6, 8, CV1800_DIV_FLAG,
++                       REG_CLK_BYP_0, 30,
++                       0);
++
++/* UART */
++static CV1800_GATE(clk_uart0, clk_uart_parents,
++                 REG_CLK_EN_1, 14,
++                 CLK_IS_CRITICAL);
++static CV1800_GATE(clk_apb_uart0, clk_axi4_bus_parents,
++                 REG_CLK_EN_1, 15,
++                 CLK_IS_CRITICAL);
++static CV1800_GATE(clk_uart1, clk_uart_parents,
++                 REG_CLK_EN_1, 16,
++                 0);
++static CV1800_GATE(clk_apb_uart1, clk_axi4_bus_parents,
++                 REG_CLK_EN_1, 17,
++                 0);
++static CV1800_GATE(clk_uart2, clk_uart_parents,
++                 REG_CLK_EN_1, 18,
++                 0);
++static CV1800_GATE(clk_apb_uart2, clk_axi4_bus_parents,
++                 REG_CLK_EN_1, 19,
++                 0);
++static CV1800_GATE(clk_uart3, clk_uart_parents,
++                 REG_CLK_EN_1, 20,
++                 0);
++static CV1800_GATE(clk_apb_uart3, clk_axi4_bus_parents,
++                 REG_CLK_EN_1, 21,
++                 0);
++static CV1800_GATE(clk_uart4, clk_uart_parents,
++                 REG_CLK_EN_1, 22,
++                 0);
++static CV1800_GATE(clk_apb_uart4, clk_axi4_bus_parents,
++                 REG_CLK_EN_1, 23,
++                 0);
++
++/* I2S */
++static CV1800_GATE(clk_apb_i2s0, clk_axi4_bus_parents,
++                 REG_CLK_EN_1, 24,
++                 0);
++static CV1800_GATE(clk_apb_i2s1, clk_axi4_bus_parents,
++                 REG_CLK_EN_1, 25,
++                 0);
++static CV1800_GATE(clk_apb_i2s2, clk_axi4_bus_parents,
++                 REG_CLK_EN_1, 26,
++                 0);
++static CV1800_GATE(clk_apb_i2s3, clk_axi4_bus_parents,
++                 REG_CLK_EN_1, 27,
++                 0);
++
++/* DEBUG */
++static CV1800_GATE(clk_debug, osc_parents,
++                 REG_CLK_EN_0, 13,
++                 CLK_IS_CRITICAL);
++static CV1800_BYPASS_DIV(clk_ap_debug, clk_bypass_fpll_parents,
++                       REG_CLK_EN_4, 5,
++                       REG_DIV_CLK_AP_DEBUG, 16, 4, 5, CV1800_DIV_FLAG,
++                       REG_CLK_BYP_1, 4,
++                       CLK_IS_CRITICAL);
++
++/* DDR */
++static CV1800_GATE(clk_ddr_axi_reg, clk_axi6_bus_parents,
++                 REG_CLK_EN_0, 7,
++                 CLK_IS_CRITICAL);
++
++/* I2C */
++static CV1800_GATE(clk_apb_i2c, clk_axi4_bus_parents,
++                 REG_CLK_EN_1, 6,
++                 0);
++static CV1800_BYPASS_DIV(clk_i2c, clk_bypass_axi6_bus_parents,
++                       REG_CLK_EN_3, 7,
++                       REG_DIV_CLK_I2C, 16, 4, 1, CV1800_DIV_FLAG,
++                       REG_CLK_BYP_0, 31,
++                       0);
++static CV1800_GATE(clk_apb_i2c0, clk_axi4_bus_parents,
++                 REG_CLK_EN_3, 17,
++                 0);
++static CV1800_GATE(clk_apb_i2c1, clk_axi4_bus_parents,
++                 REG_CLK_EN_3, 18,
++                 0);
++static CV1800_GATE(clk_apb_i2c2, clk_axi4_bus_parents,
++                 REG_CLK_EN_3, 19,
++                 0);
++static CV1800_GATE(clk_apb_i2c3, clk_axi4_bus_parents,
++                 REG_CLK_EN_3, 20,
++                 0);
++static CV1800_GATE(clk_apb_i2c4, clk_axi4_bus_parents,
++                 REG_CLK_EN_3, 21,
++                 0);
++
++/* USB */
++static CV1800_GATE(clk_axi4_usb, clk_axi4_bus_parents,
++                 REG_CLK_EN_1, 28,
++                 0);
++static CV1800_GATE(clk_apb_usb, clk_axi4_bus_parents,
++                 REG_CLK_EN_1, 29,
++                 0);
++static CV1800_BYPASS_FIXED_DIV(clk_usb_125m, clk_bypass_fpll_parents,
++                             REG_CLK_EN_1, 30,
++                             12,
++                             REG_CLK_BYP_0, 17,
++                             CLK_SET_RATE_PARENT);
++static CV1800_FIXED_DIV(clk_usb_33k, clk_parents_1m,
++                      REG_CLK_EN_1, 31,
++                      3,
++                      0);
++static CV1800_BYPASS_FIXED_DIV(clk_usb_12m, clk_bypass_fpll_parents,
++                             REG_CLK_EN_2, 0,
++                             125,
++                             REG_CLK_BYP_0, 18,
++                             CLK_SET_RATE_PARENT);
++
++/* VIP SYS */
++static const struct clk_parent_data clk_vip_sys_parents[] = {
++      { .index = 0 },
++      { .hw = &clk_mipimpll.common.hw },
++      { .hw = &clk_cam0pll.common.hw },
++      { .hw = &clk_disppll.common.hw },
++      { .hw = &clk_fpll.common.hw },
++};
++static const struct clk_parent_data clk_disp_vip_parents[] = {
++      { .index = 0 },
++      { .hw = &clk_disppll.common.hw },
++};
++
++static CV1800_BYPASS_DIV(clk_dsi_esc, clk_bypass_axi6_bus_parents,
++                       REG_CLK_EN_2, 3,
++                       REG_DIV_CLK_DSI_ESC, 16, 4, 5, CV1800_DIV_FLAG,
++                       REG_CLK_BYP_0, 21,
++                       0);
++static CV1800_BYPASS_MUX(clk_axi_vip, clk_vip_sys_parents,
++                       REG_CLK_EN_2, 4,
++                       REG_DIV_CLK_AXI_VIP, 16, 4, 3, CV1800_DIV_FLAG,
++                       REG_DIV_CLK_AXI_VIP, 8, 2,
++                       REG_CLK_BYP_0, 22,
++                       0);
++
++static const struct clk_parent_data clk_axi_vip_bus_parents[] = {
++      { .hw = &clk_axi_vip.mux.common.hw },
++};
++
++static CV1800_BYPASS_MUX(clk_src_vip_sys_0, clk_vip_sys_parents,
++                       REG_CLK_EN_2, 5,
++                       REG_DIV_CLK_SRC_VIP_SYS_0, 16, 4, 6, CV1800_DIV_FLAG,
++                       REG_DIV_CLK_SRC_VIP_SYS_0, 8, 2,
++                       REG_CLK_BYP_0, 23,
++                       0);
++static CV1800_BYPASS_MUX(clk_src_vip_sys_1, clk_vip_sys_parents,
++                       REG_CLK_EN_2, 6,
++                       REG_DIV_CLK_SRC_VIP_SYS_1, 16, 4, 6, CV1800_DIV_FLAG,
++                       REG_DIV_CLK_SRC_VIP_SYS_1, 8, 2,
++                       REG_CLK_BYP_0, 24,
++                       0);
++static CV1800_BYPASS_DIV(clk_disp_src_vip, clk_disp_vip_parents,
++                       REG_CLK_EN_2, 7,
++                       REG_DIV_CLK_DISP_SRC_VIP, 16, 4, 8, CV1800_DIV_FLAG,
++                       REG_CLK_BYP_0, 25,
++                       0);
++static CV1800_BYPASS_MUX(clk_src_vip_sys_2, clk_vip_sys_parents,
++                       REG_CLK_EN_3, 29,
++                       REG_DIV_CLK_SRC_VIP_SYS_2, 16, 4, 2, CV1800_DIV_FLAG,
++                       REG_DIV_CLK_SRC_VIP_SYS_2, 8, 2,
++                       REG_CLK_BYP_1, 1,
++                       0);
++static CV1800_GATE(clk_csi_mac0_vip, clk_axi_vip_bus_parents,
++                 REG_CLK_EN_2, 18,
++                 0);
++static CV1800_GATE(clk_csi_mac1_vip, clk_axi_vip_bus_parents,
++                 REG_CLK_EN_2, 19,
++                 0);
++static CV1800_GATE(clk_isp_top_vip, clk_axi_vip_bus_parents,
++                 REG_CLK_EN_2, 20,
++                 0);
++static CV1800_GATE(clk_img_d_vip, clk_axi_vip_bus_parents,
++                 REG_CLK_EN_2, 21,
++                 0);
++static CV1800_GATE(clk_img_v_vip, clk_axi_vip_bus_parents,
++                 REG_CLK_EN_2, 22,
++                 0);
++static CV1800_GATE(clk_sc_top_vip, clk_axi_vip_bus_parents,
++                 REG_CLK_EN_2, 23,
++                 0);
++static CV1800_GATE(clk_sc_d_vip, clk_axi_vip_bus_parents,
++                 REG_CLK_EN_2, 24,
++                 0);
++static CV1800_GATE(clk_sc_v1_vip, clk_axi_vip_bus_parents,
++                 REG_CLK_EN_2, 25,
++                 0);
++static CV1800_GATE(clk_sc_v2_vip, clk_axi_vip_bus_parents,
++                 REG_CLK_EN_2, 26,
++                 0);
++static CV1800_GATE(clk_sc_v3_vip, clk_axi_vip_bus_parents,
++                 REG_CLK_EN_2, 27,
++                 0);
++static CV1800_GATE(clk_dwa_vip, clk_axi_vip_bus_parents,
++                 REG_CLK_EN_2, 28,
++                 0);
++static CV1800_GATE(clk_bt_vip, clk_axi_vip_bus_parents,
++                 REG_CLK_EN_2, 29,
++                 0);
++static CV1800_GATE(clk_disp_vip, clk_axi_vip_bus_parents,
++                 REG_CLK_EN_2, 30,
++                 0);
++static CV1800_GATE(clk_dsi_mac_vip, clk_axi_vip_bus_parents,
++                 REG_CLK_EN_2, 31,
++                 0);
++static CV1800_GATE(clk_lvds0_vip, clk_axi_vip_bus_parents,
++                 REG_CLK_EN_3, 0,
++                 0);
++static CV1800_GATE(clk_lvds1_vip, clk_axi_vip_bus_parents,
++                 REG_CLK_EN_3, 1,
++                 0);
++static CV1800_GATE(clk_csi0_rx_vip, clk_axi_vip_bus_parents,
++                 REG_CLK_EN_3, 2,
++                 0);
++static CV1800_GATE(clk_csi1_rx_vip, clk_axi_vip_bus_parents,
++                 REG_CLK_EN_3, 3,
++                 0);
++static CV1800_GATE(clk_pad_vi_vip, clk_axi_vip_bus_parents,
++                 REG_CLK_EN_3, 4,
++                 0);
++static CV1800_GATE(clk_pad_vi1_vip, clk_axi_vip_bus_parents,
++                 REG_CLK_EN_3, 30,
++                 0);
++static CV1800_GATE(clk_cfg_reg_vip, clk_axi6_bus_parents,
++                 REG_CLK_EN_3, 31,
++                 0);
++static CV1800_GATE(clk_pad_vi2_vip, clk_axi_vip_bus_parents,
++                 REG_CLK_EN_4, 7,
++                 0);
++static CV1800_GATE(clk_csi_be_vip, clk_axi_vip_bus_parents,
++                 REG_CLK_EN_4, 8,
++                 0);
++static CV1800_GATE(clk_vip_ip0, clk_axi_vip_bus_parents,
++                 REG_CLK_EN_4, 9,
++                 0);
++static CV1800_GATE(clk_vip_ip1, clk_axi_vip_bus_parents,
++                 REG_CLK_EN_4, 10,
++                 0);
++static CV1800_GATE(clk_vip_ip2, clk_axi_vip_bus_parents,
++                 REG_CLK_EN_4, 11,
++                 0);
++static CV1800_GATE(clk_vip_ip3, clk_axi_vip_bus_parents,
++                 REG_CLK_EN_4, 12,
++                 0);
++static CV1800_BYPASS_MUX(clk_src_vip_sys_3, clk_vip_sys_parents,
++                       REG_CLK_EN_4, 15,
++                       REG_DIV_CLK_SRC_VIP_SYS_3, 16, 4, 2, CV1800_DIV_FLAG,
++                       REG_DIV_CLK_SRC_VIP_SYS_3, 8, 2,
++                       REG_CLK_BYP_1, 8,
++                       0);
++static CV1800_BYPASS_MUX(clk_src_vip_sys_4, clk_vip_sys_parents,
++                       REG_CLK_EN_4, 16,
++                       REG_DIV_CLK_SRC_VIP_SYS_4, 16, 4, 3, CV1800_DIV_FLAG,
++                       REG_DIV_CLK_SRC_VIP_SYS_4, 8, 2,
++                       REG_CLK_BYP_1, 9,
++                       0);
++static CV1800_GATE(clk_ive_vip, clk_axi_vip_bus_parents,
++                 REG_CLK_EN_4, 17,
++                 0);
++static CV1800_GATE(clk_raw_vip, clk_axi_vip_bus_parents,
++                 REG_CLK_EN_4, 18,
++                 0);
++static CV1800_GATE(clk_osdc_vip, clk_axi_vip_bus_parents,
++                 REG_CLK_EN_4, 19,
++                 0);
++static CV1800_GATE(clk_csi_mac2_vip, clk_axi_vip_bus_parents,
++                 REG_CLK_EN_4, 20,
++                 0);
++static CV1800_GATE(clk_cam0_vip, clk_axi_vip_bus_parents,
++                 REG_CLK_EN_4, 21,
++                 0);
++
++/* CAM OUT */
++static const struct clk_parent_data clk_cam_parents[] = {
++      { .hw = &clk_cam0pll.common.hw },
++      { .hw = &clk_cam0pll_d2.common.hw },
++      { .hw = &clk_cam0pll_d3.common.hw },
++      { .hw = &clk_mipimpll_d3.common.hw },
++};
++
++static CV1800_MUX(clk_cam0, clk_cam_parents,
++                REG_CLK_EN_2, 16,
++                REG_CLK_CAM0_SRC_DIV, 16, 6, 0, CV1800_DIV_FLAG,
++                REG_CLK_CAM0_SRC_DIV, 8, 2,
++                CLK_IGNORE_UNUSED);
++static CV1800_MUX(clk_cam1, clk_cam_parents,
++                REG_CLK_EN_2, 17,
++                REG_CLK_CAM1_SRC_DIV, 16, 6, 0, CV1800_DIV_FLAG,
++                REG_CLK_CAM1_SRC_DIV, 8, 2,
++                CLK_IGNORE_UNUSED);
++
++/* VIDEO SUBSYS */
++static const struct clk_parent_data clk_axi_video_codec_parents[] = {
++      { .index = 0 },
++      { .hw = &clk_a0pll.common.hw },
++      { .hw = &clk_mipimpll.common.hw },
++      { .hw = &clk_cam1pll.common.hw },
++      { .hw = &clk_fpll.common.hw },
++};
++static const struct clk_parent_data clk_vc_src0_parents[] = {
++      { .index = 0 },
++      { .hw = &clk_disppll.common.hw },
++      { .hw = &clk_mipimpll.common.hw },
++      { .hw = &clk_cam1pll.common.hw },
++      { .hw = &clk_fpll.common.hw },
++};
++static const struct clk_parent_data clk_vc_src1_parents[] = {
++      { .index = 0 },
++      { .hw = &clk_cam1pll.common.hw },
++};
++
++static CV1800_BYPASS_MUX(clk_axi_video_codec, clk_axi_video_codec_parents,
++                       REG_CLK_EN_2, 8,
++                       REG_DIV_CLK_AXI_VIDEO_CODEC, 16, 4, 2, CV1800_DIV_FLAG,
++                       REG_DIV_CLK_AXI_VIDEO_CODEC, 8, 2,
++                       REG_CLK_BYP_0, 26,
++                       0);
++
++static const struct clk_parent_data clk_axi_video_codec_bus_parents[] = {
++      { .hw = &clk_axi_video_codec.mux.common.hw },
++};
++
++static CV1800_BYPASS_MUX(clk_vc_src0, clk_vc_src0_parents,
++                       REG_CLK_EN_2, 9,
++                       REG_DIV_CLK_VC_SRC0, 16, 4, 2, CV1800_DIV_FLAG,
++                       REG_DIV_CLK_VC_SRC0, 8, 2,
++                       REG_CLK_BYP_0, 27,
++                       0);
++
++static CV1800_GATE(clk_h264c, clk_axi_video_codec_bus_parents,
++                 REG_CLK_EN_2, 10,
++                 0);
++static CV1800_GATE(clk_h265c, clk_axi_video_codec_bus_parents,
++                 REG_CLK_EN_2, 11,
++                 0);
++static CV1800_GATE(clk_jpeg, clk_axi_video_codec_bus_parents,
++                 REG_CLK_EN_2, 12,
++                 CLK_IGNORE_UNUSED);
++static CV1800_GATE(clk_apb_jpeg, clk_axi6_bus_parents,
++                 REG_CLK_EN_2, 13,
++                 CLK_IGNORE_UNUSED);
++static CV1800_GATE(clk_apb_h264c, clk_axi6_bus_parents,
++                 REG_CLK_EN_2, 14,
++                 0);
++static CV1800_GATE(clk_apb_h265c, clk_axi6_bus_parents,
++                 REG_CLK_EN_2, 15,
++                 0);
++static CV1800_BYPASS_FIXED_DIV(clk_vc_src1, clk_vc_src1_parents,
++                             REG_CLK_EN_3, 28,
++                             2,
++                             REG_CLK_BYP_1, 0,
++                             CLK_SET_RATE_PARENT);
++static CV1800_BYPASS_FIXED_DIV(clk_vc_src2, clk_bypass_fpll_parents,
++                             REG_CLK_EN_4, 3,
++                             3,
++                             REG_CLK_BYP_1, 3,
++                             CLK_SET_RATE_PARENT);
++
++/* VC SYS */
++static CV1800_GATE(clk_cfg_reg_vc, clk_axi6_bus_parents,
++                 REG_CLK_EN_4, 0,
++                 CLK_IGNORE_UNUSED);
++
++/* PWM */
++static CV1800_BYPASS_MUX(clk_pwm_src, clk_axi4_parents,
++                       REG_CLK_EN_4, 4,
++                       REG_DIV_CLK_PWM_SRC_0, 16, 6, 10, CV1800_DIV_FLAG,
++                       REG_DIV_CLK_PWM_SRC_0, 8, 2,
++                       REG_CLK_BYP_0, 15,
++                       CLK_IS_CRITICAL);
++
++static const struct clk_parent_data clk_pwm_parents[] = {
++      { .hw = &clk_pwm_src.mux.common.hw },
++};
++
++static CV1800_GATE(clk_pwm, clk_pwm_parents,
++                 REG_CLK_EN_1, 8,
++                 CLK_IS_CRITICAL);
++
++/* C906 */
++static const struct clk_parent_data clk_c906_0_parents[] = {
++      { .index = 0 },
++      { .hw = &clk_tpll.common.hw },
++      { .hw = &clk_a0pll.common.hw },
++      { .hw = &clk_mipimpll.common.hw },
++      { .hw = &clk_mpll.common.hw },
++      { .hw = &clk_fpll.common.hw },
++};
++static const struct clk_parent_data clk_c906_1_parents[] = {
++      { .index = 0 },
++      { .hw = &clk_tpll.common.hw },
++      { .hw = &clk_a0pll.common.hw },
++      { .hw = &clk_disppll.common.hw },
++      { .hw = &clk_mpll.common.hw },
++      { .hw = &clk_fpll.common.hw },
++};
++
++static const s8 clk_c906_parent2sel[] = {
++      -1,     /* osc */
++      0,      /* mux 0: clk_tpll(c906_0), clk_tpll(c906_1) */
++      0,      /* mux 0: clk_a0pll(c906_0), clk_a0pll(c906_1) */
++      0,      /* mux 0: clk_mipimpll(c906_0), clk_disppll(c906_1) */
++      0,      /* mux 0: clk_mpll(c906_0), clk_mpll(c906_1) */
++      1       /* mux 1: clk_fpll(c906_0), clk_fpll(c906_1) */
++};
++
++static const u8 clk_c906_sel2parent[2][4] = {
++      [0] = {
++              1,
++              2,
++              3,
++              4
++      },
++      [1] = {
++              5,
++              5,
++              5,
++              5
++      },
++};
++
++static CV1800_MMUX(clk_c906_0, clk_c906_0_parents,
++                 REG_CLK_EN_4, 13,
++                 REG_DIV_CLK_C906_0_0, 16, 4, 1, CV1800_DIV_FLAG,
++                 REG_DIV_CLK_C906_0_1, 16, 4, 2, CV1800_DIV_FLAG,
++                 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_c906_parent2sel,
++                 clk_c906_sel2parent[0], clk_c906_sel2parent[1],
++                 CLK_IS_CRITICAL | CLK_GET_RATE_NOCACHE);
++static CV1800_MMUX(clk_c906_1, clk_c906_1_parents,
++                 REG_CLK_EN_4, 14,
++                 REG_DIV_CLK_C906_1_0, 16, 4, 2, CV1800_DIV_FLAG,
++                 REG_DIV_CLK_C906_1_1, 16, 4, 3, CV1800_DIV_FLAG,
++                 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_c906_parent2sel,
++                 clk_c906_sel2parent[0], clk_c906_sel2parent[1],
++                 CLK_IS_CRITICAL | CLK_GET_RATE_NOCACHE);
++
++/* A53 */
++static CV1800_BYPASS_DIV(clk_cpu_axi0, clk_axi4_parents,
++                       REG_CLK_EN_0, 1,
++                       REG_DIV_CLK_CPU_AXI0, 16, 4, 3, CV1800_DIV_FLAG,
++                       REG_CLK_BYP_0, 1,
++                       CLK_IS_CRITICAL);
++static CV1800_BYPASS_DIV(clk_cpu_gic, clk_bypass_fpll_parents,
++                       REG_CLK_EN_0, 2,
++                       REG_DIV_CLK_CPU_GIC, 16, 4, 5, CV1800_DIV_FLAG,
++                       REG_CLK_BYP_0, 2,
++                       CLK_IS_CRITICAL);
++static CV1800_GATE(clk_xtal_ap, osc_parents,
++                 REG_CLK_EN_0, 3,
++                 CLK_IS_CRITICAL);
++
++static const struct clk_parent_data clk_a53_parents[] = {
++      { .index = 0 },
++      { .hw = &clk_tpll.common.hw },
++      { .hw = &clk_a0pll.common.hw },
++      { .hw = &clk_mipimpll.common.hw },
++      { .hw = &clk_mpll.common.hw },
++      { .hw = &clk_fpll.common.hw },
++};
++
++static const s8 clk_a53_parent2sel[] = {
++      -1,     /* osc */
++      0,      /* mux 0: clk_tpll */
++      0,      /* mux 0: clk_a0pll */
++      0,      /* mux 0: clk_mipimpll */
++      0,      /* mux 0: clk_mpll */
++      1       /* mux 1: clk_fpll */
++};
++
++static const u8 clk_a53_sel2parent[2][4] = {
++      [0] = {
++              1,
++              2,
++              3,
++              4
++      },
++      [1] = {
++              5,
++              5,
++              5,
++              5
++      },
++};
++
++/*
++ * Clock for A53 cpu in the CV18XX/SG200X series.
++ * For CV180X and CV181X series, this clock is not used, but can not
++ * be set to bypass mode, or the SoC will hang.
++ */
++static CV1800_MMUX(clk_a53, clk_a53_parents,
++                 REG_CLK_EN_0, 0,
++                 REG_DIV_CLK_A53_0, 16, 4, 1, CV1800_DIV_FLAG,
++                 REG_DIV_CLK_A53_1, 16, 4, 2, CV1800_DIV_FLAG,
++                 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_a53_parent2sel,
++                 clk_a53_sel2parent[0], clk_a53_sel2parent[1],
++                 CLK_IS_CRITICAL | CLK_GET_RATE_NOCACHE);
++
++static struct clk_hw_onecell_data cv1800_hw_clks = {
++      .num    = CV1800_CLK_MAX,
++      .hws    = {
++              [CLK_MPLL]              = &clk_mpll.common.hw,
++              [CLK_TPLL]              = &clk_tpll.common.hw,
++              [CLK_FPLL]              = &clk_fpll.common.hw,
++              [CLK_MIPIMPLL]          = &clk_mipimpll.common.hw,
++              [CLK_A0PLL]             = &clk_a0pll.common.hw,
++              [CLK_DISPPLL]           = &clk_disppll.common.hw,
++              [CLK_CAM0PLL]           = &clk_cam0pll.common.hw,
++              [CLK_CAM1PLL]           = &clk_cam1pll.common.hw,
++
++              [CLK_MIPIMPLL_D3]       = &clk_mipimpll_d3.common.hw,
++              [CLK_CAM0PLL_D2]        = &clk_cam0pll_d2.common.hw,
++              [CLK_CAM0PLL_D3]        = &clk_cam0pll_d3.common.hw,
++
++              [CLK_TPU]               = &clk_tpu.mux.common.hw,
++              [CLK_TPU_FAB]           = &clk_tpu_fab.common.hw,
++              [CLK_AHB_ROM]           = &clk_ahb_rom.common.hw,
++              [CLK_DDR_AXI_REG]       = &clk_ddr_axi_reg.common.hw,
++              [CLK_RTC_25M]           = &clk_rtc_25m.common.hw,
++              [CLK_SRC_RTC_SYS_0]     = &clk_src_rtc_sys_0.div.common.hw,
++              [CLK_TEMPSEN]           = &clk_tempsen.common.hw,
++              [CLK_SARADC]            = &clk_saradc.common.hw,
++              [CLK_EFUSE]             = &clk_efuse.common.hw,
++              [CLK_APB_EFUSE]         = &clk_apb_efuse.common.hw,
++              [CLK_DEBUG]             = &clk_debug.common.hw,
++              [CLK_AP_DEBUG]          = &clk_ap_debug.div.common.hw,
++              [CLK_XTAL_MISC]         = &clk_xtal_misc.common.hw,
++              [CLK_AXI4_EMMC]         = &clk_axi4_emmc.common.hw,
++              [CLK_EMMC]              = &clk_emmc.mux.common.hw,
++              [CLK_EMMC_100K]         = &clk_emmc_100k.common.hw,
++              [CLK_AXI4_SD0]          = &clk_axi4_sd0.common.hw,
++              [CLK_SD0]               = &clk_sd0.mux.common.hw,
++              [CLK_SD0_100K]          = &clk_sd0_100k.common.hw,
++              [CLK_AXI4_SD1]          = &clk_axi4_sd1.common.hw,
++              [CLK_SD1]               = &clk_sd1.mux.common.hw,
++              [CLK_SD1_100K]          = &clk_sd1_100k.common.hw,
++              [CLK_SPI_NAND]          = &clk_spi_nand.mux.common.hw,
++              [CLK_ETH0_500M]         = &clk_eth0_500m.div.common.hw,
++              [CLK_AXI4_ETH0]         = &clk_axi4_eth0.common.hw,
++              [CLK_ETH1_500M]         = &clk_eth1_500m.div.common.hw,
++              [CLK_AXI4_ETH1]         = &clk_axi4_eth1.common.hw,
++              [CLK_APB_GPIO]          = &clk_apb_gpio.common.hw,
++              [CLK_APB_GPIO_INTR]     = &clk_apb_gpio_intr.common.hw,
++              [CLK_GPIO_DB]           = &clk_gpio_db.common.hw,
++              [CLK_AHB_SF]            = &clk_ahb_sf.common.hw,
++              [CLK_AHB_SF1]           = &clk_ahb_sf1.common.hw,
++              [CLK_A24M]              = &clk_a24m.common.hw,
++              [CLK_AUDSRC]            = &clk_audsrc.mux.common.hw,
++              [CLK_APB_AUDSRC]        = &clk_apb_audsrc.common.hw,
++              [CLK_SDMA_AXI]          = &clk_sdma_axi.common.hw,
++              [CLK_SDMA_AUD0]         = &clk_sdma_aud0.mux.common.hw,
++              [CLK_SDMA_AUD1]         = &clk_sdma_aud1.mux.common.hw,
++              [CLK_SDMA_AUD2]         = &clk_sdma_aud2.mux.common.hw,
++              [CLK_SDMA_AUD3]         = &clk_sdma_aud3.mux.common.hw,
++              [CLK_I2C]               = &clk_i2c.div.common.hw,
++              [CLK_APB_I2C]           = &clk_apb_i2c.common.hw,
++              [CLK_APB_I2C0]          = &clk_apb_i2c0.common.hw,
++              [CLK_APB_I2C1]          = &clk_apb_i2c1.common.hw,
++              [CLK_APB_I2C2]          = &clk_apb_i2c2.common.hw,
++              [CLK_APB_I2C3]          = &clk_apb_i2c3.common.hw,
++              [CLK_APB_I2C4]          = &clk_apb_i2c4.common.hw,
++              [CLK_APB_WDT]           = &clk_apb_wdt.common.hw,
++              [CLK_PWM_SRC]           = &clk_pwm_src.mux.common.hw,
++              [CLK_PWM]               = &clk_pwm.common.hw,
++              [CLK_SPI]               = &clk_spi.div.common.hw,
++              [CLK_APB_SPI0]          = &clk_apb_spi0.common.hw,
++              [CLK_APB_SPI1]          = &clk_apb_spi1.common.hw,
++              [CLK_APB_SPI2]          = &clk_apb_spi2.common.hw,
++              [CLK_APB_SPI3]          = &clk_apb_spi3.common.hw,
++              [CLK_1M]                = &clk_1m.common.hw,
++              [CLK_CAM0_200]          = &clk_cam0_200.mux.common.hw,
++              [CLK_PM]                = &clk_pm.common.hw,
++              [CLK_TIMER0]            = &clk_timer0.common.hw,
++              [CLK_TIMER1]            = &clk_timer1.common.hw,
++              [CLK_TIMER2]            = &clk_timer2.common.hw,
++              [CLK_TIMER3]            = &clk_timer3.common.hw,
++              [CLK_TIMER4]            = &clk_timer4.common.hw,
++              [CLK_TIMER5]            = &clk_timer5.common.hw,
++              [CLK_TIMER6]            = &clk_timer6.common.hw,
++              [CLK_TIMER7]            = &clk_timer7.common.hw,
++              [CLK_UART0]             = &clk_uart0.common.hw,
++              [CLK_APB_UART0]         = &clk_apb_uart0.common.hw,
++              [CLK_UART1]             = &clk_uart1.common.hw,
++              [CLK_APB_UART1]         = &clk_apb_uart1.common.hw,
++              [CLK_UART2]             = &clk_uart2.common.hw,
++              [CLK_APB_UART2]         = &clk_apb_uart2.common.hw,
++              [CLK_UART3]             = &clk_uart3.common.hw,
++              [CLK_APB_UART3]         = &clk_apb_uart3.common.hw,
++              [CLK_UART4]             = &clk_uart4.common.hw,
++              [CLK_APB_UART4]         = &clk_apb_uart4.common.hw,
++              [CLK_APB_I2S0]          = &clk_apb_i2s0.common.hw,
++              [CLK_APB_I2S1]          = &clk_apb_i2s1.common.hw,
++              [CLK_APB_I2S2]          = &clk_apb_i2s2.common.hw,
++              [CLK_APB_I2S3]          = &clk_apb_i2s3.common.hw,
++              [CLK_AXI4_USB]          = &clk_axi4_usb.common.hw,
++              [CLK_APB_USB]           = &clk_apb_usb.common.hw,
++              [CLK_USB_125M]          = &clk_usb_125m.div.common.hw,
++              [CLK_USB_33K]           = &clk_usb_33k.common.hw,
++              [CLK_USB_12M]           = &clk_usb_12m.div.common.hw,
++              [CLK_AXI4]              = &clk_axi4.mux.common.hw,
++              [CLK_AXI6]              = &clk_axi6.div.common.hw,
++              [CLK_DSI_ESC]           = &clk_dsi_esc.div.common.hw,
++              [CLK_AXI_VIP]           = &clk_axi_vip.mux.common.hw,
++              [CLK_SRC_VIP_SYS_0]     = &clk_src_vip_sys_0.mux.common.hw,
++              [CLK_SRC_VIP_SYS_1]     = &clk_src_vip_sys_1.mux.common.hw,
++              [CLK_SRC_VIP_SYS_2]     = &clk_src_vip_sys_2.mux.common.hw,
++              [CLK_SRC_VIP_SYS_3]     = &clk_src_vip_sys_3.mux.common.hw,
++              [CLK_SRC_VIP_SYS_4]     = &clk_src_vip_sys_4.mux.common.hw,
++              [CLK_CSI_BE_VIP]        = &clk_csi_be_vip.common.hw,
++              [CLK_CSI_MAC0_VIP]      = &clk_csi_mac0_vip.common.hw,
++              [CLK_CSI_MAC1_VIP]      = &clk_csi_mac1_vip.common.hw,
++              [CLK_CSI_MAC2_VIP]      = &clk_csi_mac2_vip.common.hw,
++              [CLK_CSI0_RX_VIP]       = &clk_csi0_rx_vip.common.hw,
++              [CLK_CSI1_RX_VIP]       = &clk_csi1_rx_vip.common.hw,
++              [CLK_ISP_TOP_VIP]       = &clk_isp_top_vip.common.hw,
++              [CLK_IMG_D_VIP]         = &clk_img_d_vip.common.hw,
++              [CLK_IMG_V_VIP]         = &clk_img_v_vip.common.hw,
++              [CLK_SC_TOP_VIP]        = &clk_sc_top_vip.common.hw,
++              [CLK_SC_D_VIP]          = &clk_sc_d_vip.common.hw,
++              [CLK_SC_V1_VIP]         = &clk_sc_v1_vip.common.hw,
++              [CLK_SC_V2_VIP]         = &clk_sc_v2_vip.common.hw,
++              [CLK_SC_V3_VIP]         = &clk_sc_v3_vip.common.hw,
++              [CLK_DWA_VIP]           = &clk_dwa_vip.common.hw,
++              [CLK_BT_VIP]            = &clk_bt_vip.common.hw,
++              [CLK_DISP_VIP]          = &clk_disp_vip.common.hw,
++              [CLK_DSI_MAC_VIP]       = &clk_dsi_mac_vip.common.hw,
++              [CLK_LVDS0_VIP]         = &clk_lvds0_vip.common.hw,
++              [CLK_LVDS1_VIP]         = &clk_lvds1_vip.common.hw,
++              [CLK_PAD_VI_VIP]        = &clk_pad_vi_vip.common.hw,
++              [CLK_PAD_VI1_VIP]       = &clk_pad_vi1_vip.common.hw,
++              [CLK_PAD_VI2_VIP]       = &clk_pad_vi2_vip.common.hw,
++              [CLK_CFG_REG_VIP]       = &clk_cfg_reg_vip.common.hw,
++              [CLK_VIP_IP0]           = &clk_vip_ip0.common.hw,
++              [CLK_VIP_IP1]           = &clk_vip_ip1.common.hw,
++              [CLK_VIP_IP2]           = &clk_vip_ip2.common.hw,
++              [CLK_VIP_IP3]           = &clk_vip_ip3.common.hw,
++              [CLK_IVE_VIP]           = &clk_ive_vip.common.hw,
++              [CLK_RAW_VIP]           = &clk_raw_vip.common.hw,
++              [CLK_OSDC_VIP]          = &clk_osdc_vip.common.hw,
++              [CLK_CAM0_VIP]          = &clk_cam0_vip.common.hw,
++              [CLK_AXI_VIDEO_CODEC]   = &clk_axi_video_codec.mux.common.hw,
++              [CLK_VC_SRC0]           = &clk_vc_src0.mux.common.hw,
++              [CLK_VC_SRC1]           = &clk_vc_src1.div.common.hw,
++              [CLK_VC_SRC2]           = &clk_vc_src2.div.common.hw,
++              [CLK_H264C]             = &clk_h264c.common.hw,
++              [CLK_APB_H264C]         = &clk_apb_h264c.common.hw,
++              [CLK_H265C]             = &clk_h265c.common.hw,
++              [CLK_APB_H265C]         = &clk_apb_h265c.common.hw,
++              [CLK_JPEG]              = &clk_jpeg.common.hw,
++              [CLK_APB_JPEG]          = &clk_apb_jpeg.common.hw,
++              [CLK_CAM0]              = &clk_cam0.common.hw,
++              [CLK_CAM1]              = &clk_cam1.common.hw,
++              [CLK_WGN]               = &clk_wgn.common.hw,
++              [CLK_WGN0]              = &clk_wgn0.common.hw,
++              [CLK_WGN1]              = &clk_wgn1.common.hw,
++              [CLK_WGN2]              = &clk_wgn2.common.hw,
++              [CLK_KEYSCAN]           = &clk_keyscan.common.hw,
++              [CLK_CFG_REG_VC]        = &clk_cfg_reg_vc.common.hw,
++              [CLK_C906_0]            = &clk_c906_0.common.hw,
++              [CLK_C906_1]            = &clk_c906_1.common.hw,
++              [CLK_A53]               = &clk_a53.common.hw,
++              [CLK_CPU_AXI0]          = &clk_cpu_axi0.div.common.hw,
++              [CLK_CPU_GIC]           = &clk_cpu_gic.div.common.hw,
++              [CLK_XTAL_AP]           = &clk_xtal_ap.common.hw,
++      },
++};
++
++static void cv18xx_clk_disable_auto_pd(void __iomem *base)
++{
++      static const u16 CV1800_PD_CLK[] = {
++              REG_MIPIMPLL_CLK_CSR,
++              REG_A0PLL_CLK_CSR,
++              REG_DISPPLL_CLK_CSR,
++              REG_CAM0PLL_CLK_CSR,
++              REG_CAM1PLL_CLK_CSR,
++      };
++
++      u32 val;
++      int i;
++
++      /* disable auto power down */
++      for (i = 0; i < ARRAY_SIZE(CV1800_PD_CLK); i++) {
++              u32 reg = CV1800_PD_CLK[i];
++
++              val = readl(base + reg);
++              val |= GENMASK(12, 9);
++              val &= ~BIT(8);
++              writel(val, base + reg);
++      }
++}
++
++static void cv18xx_clk_disable_a53(void __iomem *base)
++{
++      u32 val = readl(base + REG_CLK_BYP_0);
++
++      /* Set bypass clock for clk_a53 */
++      val |= BIT(0);
++
++      /* Set bypass clock for clk_cpu_axi0 */
++      val |= BIT(1);
++
++      /* Set bypass clock for clk_cpu_gic */
++      val |= BIT(2);
++
++      writel(val, base + REG_CLK_BYP_0);
++}
++
++static int cv1800_pre_init(struct device *dev, void __iomem *base,
++                         struct cv1800_clk_ctrl *ctrl,
++                         const struct cv1800_clk_desc *desc)
++{
++      u32 val = readl(base + REG_CLK_EN_2);
++
++      /* disable unsupported clk_disp_src_vip */
++      val &= ~BIT(7);
++
++      writel(val, base + REG_CLK_EN_2);
++
++      cv18xx_clk_disable_a53(base);
++      cv18xx_clk_disable_auto_pd(base);
++
++      return 0;
++}
++
++static const struct cv1800_clk_desc cv1800_desc = {
++      .clks_data      = &cv1800_hw_clks,
++      .pre_init       = cv1800_pre_init,
++};
++
++static struct clk_hw_onecell_data cv1810_hw_clks = {
++      .num    = CV1810_CLK_MAX,
++      .hws    = {
++              [CLK_MPLL]              = &clk_mpll.common.hw,
++              [CLK_TPLL]              = &clk_tpll.common.hw,
++              [CLK_FPLL]              = &clk_fpll.common.hw,
++              [CLK_MIPIMPLL]          = &clk_mipimpll.common.hw,
++              [CLK_A0PLL]             = &clk_a0pll.common.hw,
++              [CLK_DISPPLL]           = &clk_disppll.common.hw,
++              [CLK_CAM0PLL]           = &clk_cam0pll.common.hw,
++              [CLK_CAM1PLL]           = &clk_cam1pll.common.hw,
++
++              [CLK_MIPIMPLL_D3]       = &clk_mipimpll_d3.common.hw,
++              [CLK_CAM0PLL_D2]        = &clk_cam0pll_d2.common.hw,
++              [CLK_CAM0PLL_D3]        = &clk_cam0pll_d3.common.hw,
++
++              [CLK_TPU]               = &clk_tpu.mux.common.hw,
++              [CLK_TPU_FAB]           = &clk_tpu_fab.common.hw,
++              [CLK_AHB_ROM]           = &clk_ahb_rom.common.hw,
++              [CLK_DDR_AXI_REG]       = &clk_ddr_axi_reg.common.hw,
++              [CLK_RTC_25M]           = &clk_rtc_25m.common.hw,
++              [CLK_SRC_RTC_SYS_0]     = &clk_src_rtc_sys_0.div.common.hw,
++              [CLK_TEMPSEN]           = &clk_tempsen.common.hw,
++              [CLK_SARADC]            = &clk_saradc.common.hw,
++              [CLK_EFUSE]             = &clk_efuse.common.hw,
++              [CLK_APB_EFUSE]         = &clk_apb_efuse.common.hw,
++              [CLK_DEBUG]             = &clk_debug.common.hw,
++              [CLK_AP_DEBUG]          = &clk_ap_debug.div.common.hw,
++              [CLK_XTAL_MISC]         = &clk_xtal_misc.common.hw,
++              [CLK_AXI4_EMMC]         = &clk_axi4_emmc.common.hw,
++              [CLK_EMMC]              = &clk_emmc.mux.common.hw,
++              [CLK_EMMC_100K]         = &clk_emmc_100k.common.hw,
++              [CLK_AXI4_SD0]          = &clk_axi4_sd0.common.hw,
++              [CLK_SD0]               = &clk_sd0.mux.common.hw,
++              [CLK_SD0_100K]          = &clk_sd0_100k.common.hw,
++              [CLK_AXI4_SD1]          = &clk_axi4_sd1.common.hw,
++              [CLK_SD1]               = &clk_sd1.mux.common.hw,
++              [CLK_SD1_100K]          = &clk_sd1_100k.common.hw,
++              [CLK_SPI_NAND]          = &clk_spi_nand.mux.common.hw,
++              [CLK_ETH0_500M]         = &clk_eth0_500m.div.common.hw,
++              [CLK_AXI4_ETH0]         = &clk_axi4_eth0.common.hw,
++              [CLK_ETH1_500M]         = &clk_eth1_500m.div.common.hw,
++              [CLK_AXI4_ETH1]         = &clk_axi4_eth1.common.hw,
++              [CLK_APB_GPIO]          = &clk_apb_gpio.common.hw,
++              [CLK_APB_GPIO_INTR]     = &clk_apb_gpio_intr.common.hw,
++              [CLK_GPIO_DB]           = &clk_gpio_db.common.hw,
++              [CLK_AHB_SF]            = &clk_ahb_sf.common.hw,
++              [CLK_AHB_SF1]           = &clk_ahb_sf1.common.hw,
++              [CLK_A24M]              = &clk_a24m.common.hw,
++              [CLK_AUDSRC]            = &clk_audsrc.mux.common.hw,
++              [CLK_APB_AUDSRC]        = &clk_apb_audsrc.common.hw,
++              [CLK_SDMA_AXI]          = &clk_sdma_axi.common.hw,
++              [CLK_SDMA_AUD0]         = &clk_sdma_aud0.mux.common.hw,
++              [CLK_SDMA_AUD1]         = &clk_sdma_aud1.mux.common.hw,
++              [CLK_SDMA_AUD2]         = &clk_sdma_aud2.mux.common.hw,
++              [CLK_SDMA_AUD3]         = &clk_sdma_aud3.mux.common.hw,
++              [CLK_I2C]               = &clk_i2c.div.common.hw,
++              [CLK_APB_I2C]           = &clk_apb_i2c.common.hw,
++              [CLK_APB_I2C0]          = &clk_apb_i2c0.common.hw,
++              [CLK_APB_I2C1]          = &clk_apb_i2c1.common.hw,
++              [CLK_APB_I2C2]          = &clk_apb_i2c2.common.hw,
++              [CLK_APB_I2C3]          = &clk_apb_i2c3.common.hw,
++              [CLK_APB_I2C4]          = &clk_apb_i2c4.common.hw,
++              [CLK_APB_WDT]           = &clk_apb_wdt.common.hw,
++              [CLK_PWM_SRC]           = &clk_pwm_src.mux.common.hw,
++              [CLK_PWM]               = &clk_pwm.common.hw,
++              [CLK_SPI]               = &clk_spi.div.common.hw,
++              [CLK_APB_SPI0]          = &clk_apb_spi0.common.hw,
++              [CLK_APB_SPI1]          = &clk_apb_spi1.common.hw,
++              [CLK_APB_SPI2]          = &clk_apb_spi2.common.hw,
++              [CLK_APB_SPI3]          = &clk_apb_spi3.common.hw,
++              [CLK_1M]                = &clk_1m.common.hw,
++              [CLK_CAM0_200]          = &clk_cam0_200.mux.common.hw,
++              [CLK_PM]                = &clk_pm.common.hw,
++              [CLK_TIMER0]            = &clk_timer0.common.hw,
++              [CLK_TIMER1]            = &clk_timer1.common.hw,
++              [CLK_TIMER2]            = &clk_timer2.common.hw,
++              [CLK_TIMER3]            = &clk_timer3.common.hw,
++              [CLK_TIMER4]            = &clk_timer4.common.hw,
++              [CLK_TIMER5]            = &clk_timer5.common.hw,
++              [CLK_TIMER6]            = &clk_timer6.common.hw,
++              [CLK_TIMER7]            = &clk_timer7.common.hw,
++              [CLK_UART0]             = &clk_uart0.common.hw,
++              [CLK_APB_UART0]         = &clk_apb_uart0.common.hw,
++              [CLK_UART1]             = &clk_uart1.common.hw,
++              [CLK_APB_UART1]         = &clk_apb_uart1.common.hw,
++              [CLK_UART2]             = &clk_uart2.common.hw,
++              [CLK_APB_UART2]         = &clk_apb_uart2.common.hw,
++              [CLK_UART3]             = &clk_uart3.common.hw,
++              [CLK_APB_UART3]         = &clk_apb_uart3.common.hw,
++              [CLK_UART4]             = &clk_uart4.common.hw,
++              [CLK_APB_UART4]         = &clk_apb_uart4.common.hw,
++              [CLK_APB_I2S0]          = &clk_apb_i2s0.common.hw,
++              [CLK_APB_I2S1]          = &clk_apb_i2s1.common.hw,
++              [CLK_APB_I2S2]          = &clk_apb_i2s2.common.hw,
++              [CLK_APB_I2S3]          = &clk_apb_i2s3.common.hw,
++              [CLK_AXI4_USB]          = &clk_axi4_usb.common.hw,
++              [CLK_APB_USB]           = &clk_apb_usb.common.hw,
++              [CLK_USB_125M]          = &clk_usb_125m.div.common.hw,
++              [CLK_USB_33K]           = &clk_usb_33k.common.hw,
++              [CLK_USB_12M]           = &clk_usb_12m.div.common.hw,
++              [CLK_AXI4]              = &clk_axi4.mux.common.hw,
++              [CLK_AXI6]              = &clk_axi6.div.common.hw,
++              [CLK_DSI_ESC]           = &clk_dsi_esc.div.common.hw,
++              [CLK_AXI_VIP]           = &clk_axi_vip.mux.common.hw,
++              [CLK_SRC_VIP_SYS_0]     = &clk_src_vip_sys_0.mux.common.hw,
++              [CLK_SRC_VIP_SYS_1]     = &clk_src_vip_sys_1.mux.common.hw,
++              [CLK_SRC_VIP_SYS_2]     = &clk_src_vip_sys_2.mux.common.hw,
++              [CLK_SRC_VIP_SYS_3]     = &clk_src_vip_sys_3.mux.common.hw,
++              [CLK_SRC_VIP_SYS_4]     = &clk_src_vip_sys_4.mux.common.hw,
++              [CLK_CSI_BE_VIP]        = &clk_csi_be_vip.common.hw,
++              [CLK_CSI_MAC0_VIP]      = &clk_csi_mac0_vip.common.hw,
++              [CLK_CSI_MAC1_VIP]      = &clk_csi_mac1_vip.common.hw,
++              [CLK_CSI_MAC2_VIP]      = &clk_csi_mac2_vip.common.hw,
++              [CLK_CSI0_RX_VIP]       = &clk_csi0_rx_vip.common.hw,
++              [CLK_CSI1_RX_VIP]       = &clk_csi1_rx_vip.common.hw,
++              [CLK_ISP_TOP_VIP]       = &clk_isp_top_vip.common.hw,
++              [CLK_IMG_D_VIP]         = &clk_img_d_vip.common.hw,
++              [CLK_IMG_V_VIP]         = &clk_img_v_vip.common.hw,
++              [CLK_SC_TOP_VIP]        = &clk_sc_top_vip.common.hw,
++              [CLK_SC_D_VIP]          = &clk_sc_d_vip.common.hw,
++              [CLK_SC_V1_VIP]         = &clk_sc_v1_vip.common.hw,
++              [CLK_SC_V2_VIP]         = &clk_sc_v2_vip.common.hw,
++              [CLK_SC_V3_VIP]         = &clk_sc_v3_vip.common.hw,
++              [CLK_DWA_VIP]           = &clk_dwa_vip.common.hw,
++              [CLK_BT_VIP]            = &clk_bt_vip.common.hw,
++              [CLK_DISP_VIP]          = &clk_disp_vip.common.hw,
++              [CLK_DSI_MAC_VIP]       = &clk_dsi_mac_vip.common.hw,
++              [CLK_LVDS0_VIP]         = &clk_lvds0_vip.common.hw,
++              [CLK_LVDS1_VIP]         = &clk_lvds1_vip.common.hw,
++              [CLK_PAD_VI_VIP]        = &clk_pad_vi_vip.common.hw,
++              [CLK_PAD_VI1_VIP]       = &clk_pad_vi1_vip.common.hw,
++              [CLK_PAD_VI2_VIP]       = &clk_pad_vi2_vip.common.hw,
++              [CLK_CFG_REG_VIP]       = &clk_cfg_reg_vip.common.hw,
++              [CLK_VIP_IP0]           = &clk_vip_ip0.common.hw,
++              [CLK_VIP_IP1]           = &clk_vip_ip1.common.hw,
++              [CLK_VIP_IP2]           = &clk_vip_ip2.common.hw,
++              [CLK_VIP_IP3]           = &clk_vip_ip3.common.hw,
++              [CLK_IVE_VIP]           = &clk_ive_vip.common.hw,
++              [CLK_RAW_VIP]           = &clk_raw_vip.common.hw,
++              [CLK_OSDC_VIP]          = &clk_osdc_vip.common.hw,
++              [CLK_CAM0_VIP]          = &clk_cam0_vip.common.hw,
++              [CLK_AXI_VIDEO_CODEC]   = &clk_axi_video_codec.mux.common.hw,
++              [CLK_VC_SRC0]           = &clk_vc_src0.mux.common.hw,
++              [CLK_VC_SRC1]           = &clk_vc_src1.div.common.hw,
++              [CLK_VC_SRC2]           = &clk_vc_src2.div.common.hw,
++              [CLK_H264C]             = &clk_h264c.common.hw,
++              [CLK_APB_H264C]         = &clk_apb_h264c.common.hw,
++              [CLK_H265C]             = &clk_h265c.common.hw,
++              [CLK_APB_H265C]         = &clk_apb_h265c.common.hw,
++              [CLK_JPEG]              = &clk_jpeg.common.hw,
++              [CLK_APB_JPEG]          = &clk_apb_jpeg.common.hw,
++              [CLK_CAM0]              = &clk_cam0.common.hw,
++              [CLK_CAM1]              = &clk_cam1.common.hw,
++              [CLK_WGN]               = &clk_wgn.common.hw,
++              [CLK_WGN0]              = &clk_wgn0.common.hw,
++              [CLK_WGN1]              = &clk_wgn1.common.hw,
++              [CLK_WGN2]              = &clk_wgn2.common.hw,
++              [CLK_KEYSCAN]           = &clk_keyscan.common.hw,
++              [CLK_CFG_REG_VC]        = &clk_cfg_reg_vc.common.hw,
++              [CLK_C906_0]            = &clk_c906_0.common.hw,
++              [CLK_C906_1]            = &clk_c906_1.common.hw,
++              [CLK_A53]               = &clk_a53.common.hw,
++              [CLK_CPU_AXI0]          = &clk_cpu_axi0.div.common.hw,
++              [CLK_CPU_GIC]           = &clk_cpu_gic.div.common.hw,
++              [CLK_XTAL_AP]           = &clk_xtal_ap.common.hw,
++              [CLK_DISP_SRC_VIP]      = &clk_disp_src_vip.div.common.hw,
++      },
++};
++
++static int cv1810_pre_init(struct device *dev, void __iomem *base,
++                         struct cv1800_clk_ctrl *ctrl,
++                         const struct cv1800_clk_desc *desc)
++{
++      cv18xx_clk_disable_a53(base);
++      cv18xx_clk_disable_auto_pd(base);
++
++      return 0;
++}
++
++static const struct cv1800_clk_desc cv1810_desc = {
++      .clks_data      = &cv1810_hw_clks,
++      .pre_init       = cv1810_pre_init,
++};
++
++static int sg2000_pre_init(struct device *dev, void __iomem *base,
++                         struct cv1800_clk_ctrl *ctrl,
++                         const struct cv1800_clk_desc *desc)
++{
++      cv18xx_clk_disable_auto_pd(base);
++
++      return 0;
++}
++
++static const struct cv1800_clk_desc sg2000_desc = {
++      .clks_data      = &cv1810_hw_clks,
++      .pre_init       = sg2000_pre_init,
++};
++
++static int cv1800_clk_init_ctrl(struct device *dev, void __iomem *reg,
++                              struct cv1800_clk_ctrl *ctrl,
++                              const struct cv1800_clk_desc *desc)
++{
++      int i, ret;
++
++      ctrl->desc = desc;
++      spin_lock_init(&ctrl->lock);
++
++      for (i = 0; i < desc->clks_data->num; i++) {
++              struct clk_hw *hw = desc->clks_data->hws[i];
++              struct cv1800_clk_common *common;
++              const char *name;
++
++              if (!hw)
++                      continue;
++
++              name = hw->init->name;
++
++              common = hw_to_cv1800_clk_common(hw);
++              common->base = reg;
++              common->lock = &ctrl->lock;
++
++              ret = devm_clk_hw_register(dev, hw);
++              if (ret) {
++                      dev_err(dev, "Couldn't register clock %d - %s\n",
++                              i, name);
++                      return ret;
++              }
++      }
++
++      ret = devm_of_clk_add_hw_provider(dev, of_clk_hw_onecell_get,
++                                        desc->clks_data);
++
++      return ret;
++}
++
++static int cv1800_clk_probe(struct platform_device *pdev)
++{
++      struct device *dev = &pdev->dev;
++      void __iomem *reg;
++      int ret;
++      const struct cv1800_clk_desc *desc;
++      struct cv1800_clk_ctrl *ctrl;
++
++      reg = devm_platform_ioremap_resource(pdev, 0);
++      if (IS_ERR(reg))
++              return PTR_ERR(reg);
++
++      desc = device_get_match_data(dev);
++      if (!desc) {
++              dev_err(dev, "no match data for platform\n");
++              return -EINVAL;
++      }
++
++      ctrl = devm_kmalloc(dev, sizeof(*ctrl), GFP_KERNEL);
++      if (!ctrl)
++              return -ENOMEM;
++
++      if (desc->pre_init) {
++              ret = desc->pre_init(dev, reg, ctrl, desc);
++              if (ret)
++                      return ret;
++      }
++
++      ret = cv1800_clk_init_ctrl(dev, reg, ctrl, desc);
++
++      return ret;
++}
++
++static const struct of_device_id cv1800_clk_ids[] = {
++      { .compatible = "sophgo,cv1800-clk", .data = &cv1800_desc },
++      { .compatible = "sophgo,cv1810-clk", .data = &cv1810_desc },
++      { .compatible = "sophgo,sg2000-clk", .data = &sg2000_desc },
++      { }
++};
++MODULE_DEVICE_TABLE(of, cv1800_clk_ids);
++
++static struct platform_driver cv1800_clk_driver = {
++      .probe  = cv1800_clk_probe,
++      .driver = {
++              .name                   = "cv1800-clk",
++              .suppress_bind_attrs    = true,
++              .of_match_table         = cv1800_clk_ids,
++      },
++};
++module_platform_driver(cv1800_clk_driver);
++MODULE_LICENSE("GPL");
+diff --git a/drivers/clk/sophgo/clk-cv1800.h b/drivers/clk/sophgo/clk-cv1800.h
+new file mode 100644
+index 000000000000..1e7107b5d05e
+--- /dev/null
++++ b/drivers/clk/sophgo/clk-cv1800.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-cv18xx-common.c b/drivers/clk/sophgo/clk-cv18xx-common.c
+new file mode 100644
+index 000000000000..cbcdd88f0e23
+--- /dev/null
++++ b/drivers/clk/sophgo/clk-cv18xx-common.c
+@@ -0,0 +1,66 @@
++// SPDX-License-Identifier: GPL-2.0
++/*
++ * Copyright (C) 2023 Inochi Amaoto <inochiama@outlook.com>
++ */
++
++#include <linux/io.h>
++#include <linux/iopoll.h>
++#include <linux/spinlock.h>
++#include <linux/bug.h>
++
++#include "clk-cv18xx-common.h"
++
++int cv1800_clk_setbit(struct cv1800_clk_common *common,
++                    struct cv1800_clk_regbit *field)
++{
++      u32 mask = BIT(field->shift);
++      u32 value;
++      unsigned long flags;
++
++      spin_lock_irqsave(common->lock, flags);
++
++      value = readl(common->base + field->reg);
++      writel(value | mask, common->base + field->reg);
++
++      spin_unlock_irqrestore(common->lock, flags);
++
++      return 0;
++}
++
++int cv1800_clk_clearbit(struct cv1800_clk_common *common,
++                      struct cv1800_clk_regbit *field)
++{
++      u32 mask = BIT(field->shift);
++      u32 value;
++      unsigned long flags;
++
++      spin_lock_irqsave(common->lock, flags);
++
++      value = readl(common->base + field->reg);
++      writel(value & ~mask, common->base + field->reg);
++
++      spin_unlock_irqrestore(common->lock, flags);
++
++      return 0;
++}
++
++int cv1800_clk_checkbit(struct cv1800_clk_common *common,
++                      struct cv1800_clk_regbit *field)
++{
++      return readl(common->base + field->reg) & BIT(field->shift);
++}
++
++#define PLL_LOCK_TIMEOUT_US   (200 * 1000)
++
++void cv1800_clk_wait_for_lock(struct cv1800_clk_common *common,
++                            u32 reg, u32 lock)
++{
++      void __iomem *addr = common->base + reg;
++      u32 regval;
++
++      if (!lock)
++              return;
++
++      WARN_ON(readl_relaxed_poll_timeout(addr, regval, regval & lock,
++                                         100, PLL_LOCK_TIMEOUT_US));
++}
+diff --git a/drivers/clk/sophgo/clk-cv18xx-common.h b/drivers/clk/sophgo/clk-cv18xx-common.h
+new file mode 100644
+index 000000000000..2bfda02b2064
+--- /dev/null
++++ b/drivers/clk/sophgo/clk-cv18xx-common.h
+@@ -0,0 +1,81 @@
++/* SPDX-License-Identifier: GPL-2.0 */
++/*
++ * Copyright (C) 2023 Inochi Amaoto <inochiama@outlook.com>
++ */
++
++#ifndef _CLK_SOPHGO_CV18XX_IP_H_
++#define _CLK_SOPHGO_CV18XX_IP_H_
++
++#include <linux/compiler.h>
++#include <linux/clk-provider.h>
++#include <linux/bitfield.h>
++
++struct cv1800_clk_common {
++      void __iomem    *base;
++      spinlock_t      *lock;
++      struct clk_hw   hw;
++      unsigned long   features;
++};
++
++#define CV1800_CLK_COMMON(_name, _parents, _op, _flags)                       \
++      {                                                               \
++              .hw.init = CLK_HW_INIT_PARENTS_DATA(_name, _parents,    \
++                                                  _op, _flags),       \
++      }
++
++static inline struct cv1800_clk_common *
++hw_to_cv1800_clk_common(struct clk_hw *hw)
++{
++      return container_of(hw, struct cv1800_clk_common, hw);
++}
++
++struct cv1800_clk_regbit {
++      u16             reg;
++      s8              shift;
++};
++
++struct cv1800_clk_regfield {
++      u16             reg;
++      u8              shift;
++      u8              width;
++      s16             initval;
++      unsigned long   flags;
++};
++
++#define CV1800_CLK_BIT(_reg, _shift)  \
++      {                               \
++              .reg = _reg,            \
++              .shift = _shift,        \
++      }
++
++#define CV1800_CLK_REG(_reg, _shift, _width, _initval, _flags)        \
++      {                                                       \
++              .reg = _reg,                                    \
++              .shift = _shift,                                \
++              .width = _width,                                \
++              .initval = _initval,                            \
++              .flags = _flags,                                \
++      }
++
++#define cv1800_clk_regfield_genmask(_reg) \
++      GENMASK((_reg)->shift + (_reg)->width - 1, (_reg)->shift)
++#define cv1800_clk_regfield_get(_val, _reg) \
++      (((_val) >> (_reg)->shift) & GENMASK((_reg)->width - 1, 0))
++#define cv1800_clk_regfield_set(_val, _new, _reg)    \
++      (((_val) & ~cv1800_clk_regfield_genmask((_reg))) | \
++       (((_new) & GENMASK((_reg)->width - 1, 0)) << (_reg)->shift))
++
++#define _CV1800_SET_FIELD(_reg, _val, _field) \
++      (((_reg) & ~(_field)) | FIELD_PREP((_field), (_val)))
++
++int cv1800_clk_setbit(struct cv1800_clk_common *common,
++                    struct cv1800_clk_regbit *field);
++int cv1800_clk_clearbit(struct cv1800_clk_common *common,
++                      struct cv1800_clk_regbit *field);
++int cv1800_clk_checkbit(struct cv1800_clk_common *common,
++                      struct cv1800_clk_regbit *field);
++
++void cv1800_clk_wait_for_lock(struct cv1800_clk_common *common,
++                            u32 reg, u32 lock);
++
++#endif // _CLK_SOPHGO_CV18XX_IP_H_
+diff --git a/drivers/clk/sophgo/clk-cv18xx-ip.c b/drivers/clk/sophgo/clk-cv18xx-ip.c
+new file mode 100644
+index 000000000000..805f561725ae
+--- /dev/null
++++ b/drivers/clk/sophgo/clk-cv18xx-ip.c
+@@ -0,0 +1,887 @@
++// SPDX-License-Identifier: GPL-2.0
++/*
++ * Copyright (C) 2023 Inochi Amaoto <inochiama@outlook.com>
++ */
++
++#include <linux/clk-provider.h>
++#include <linux/io.h>
++#include <linux/gcd.h>
++#include <linux/spinlock.h>
++
++#include "clk-cv18xx-ip.h"
++
++/* GATE */
++static inline struct cv1800_clk_gate *hw_to_cv1800_clk_gate(struct clk_hw *hw)
++{
++      struct cv1800_clk_common *common = hw_to_cv1800_clk_common(hw);
++
++      return container_of(common, struct cv1800_clk_gate, common);
++}
++
++static int gate_enable(struct clk_hw *hw)
++{
++      struct cv1800_clk_gate *gate = hw_to_cv1800_clk_gate(hw);
++
++      return cv1800_clk_setbit(&gate->common, &gate->gate);
++}
++
++static void gate_disable(struct clk_hw *hw)
++{
++      struct cv1800_clk_gate *gate = hw_to_cv1800_clk_gate(hw);
++
++      cv1800_clk_clearbit(&gate->common, &gate->gate);
++}
++
++static int gate_is_enabled(struct clk_hw *hw)
++{
++      struct cv1800_clk_gate *gate = hw_to_cv1800_clk_gate(hw);
++
++      return cv1800_clk_checkbit(&gate->common, &gate->gate);
++}
++
++static unsigned long gate_recalc_rate(struct clk_hw *hw,
++                                    unsigned long parent_rate)
++{
++      return parent_rate;
++}
++
++static long gate_round_rate(struct clk_hw *hw, unsigned long rate,
++                          unsigned long *parent_rate)
++{
++      return *parent_rate;
++}
++
++static int gate_set_rate(struct clk_hw *hw, unsigned long rate,
++                       unsigned long parent_rate)
++{
++      return 0;
++}
++
++const struct clk_ops cv1800_clk_gate_ops = {
++      .disable = gate_disable,
++      .enable = gate_enable,
++      .is_enabled = gate_is_enabled,
++
++      .recalc_rate = gate_recalc_rate,
++      .round_rate = gate_round_rate,
++      .set_rate = gate_set_rate,
++};
++
++/* DIV */
++#define _DIV_EN_CLK_DIV_FACTOR_FIELD          BIT(3)
++
++#define DIV_GET_EN_CLK_DIV_FACTOR(_reg) \
++      FIELD_GET(_DIV_EN_CLK_DIV_FACTOR_FIELD, _reg)
++
++#define DIV_SET_EN_DIV_FACTOR(_reg) \
++      _CV1800_SET_FIELD(_reg, 1, _DIV_EN_CLK_DIV_FACTOR_FIELD)
++
++static inline struct cv1800_clk_div *hw_to_cv1800_clk_div(struct clk_hw *hw)
++{
++      struct cv1800_clk_common *common = hw_to_cv1800_clk_common(hw);
++
++      return container_of(common, struct cv1800_clk_div, common);
++}
++
++static int div_enable(struct clk_hw *hw)
++{
++      struct cv1800_clk_div *div = hw_to_cv1800_clk_div(hw);
++
++      return cv1800_clk_setbit(&div->common, &div->gate);
++}
++
++static void div_disable(struct clk_hw *hw)
++{
++      struct cv1800_clk_div *div = hw_to_cv1800_clk_div(hw);
++
++      cv1800_clk_clearbit(&div->common, &div->gate);
++}
++
++static int div_is_enabled(struct clk_hw *hw)
++{
++      struct cv1800_clk_div *div = hw_to_cv1800_clk_div(hw);
++
++      return cv1800_clk_checkbit(&div->common, &div->gate);
++}
++
++static int div_helper_set_rate(struct cv1800_clk_common *common,
++                             struct cv1800_clk_regfield *div,
++                             unsigned long val)
++{
++      unsigned long flags;
++      u32 reg;
++
++      if (div->width == 0)
++              return 0;
++
++      spin_lock_irqsave(common->lock, flags);
++
++      reg = readl(common->base + div->reg);
++      reg = cv1800_clk_regfield_set(reg, val, div);
++      if (div->initval > 0)
++              reg = DIV_SET_EN_DIV_FACTOR(reg);
++
++      writel(reg, common->base + div->reg);
++
++      spin_unlock_irqrestore(common->lock, flags);
++
++      return 0;
++}
++
++static u32 div_helper_get_clockdiv(struct cv1800_clk_common *common,
++                                 struct cv1800_clk_regfield *div)
++{
++      u32 clockdiv = 1;
++      u32 reg;
++
++      if (!div || div->initval < 0 || (div->width == 0 && div->initval <= 0))
++              return 1;
++
++      if (div->width == 0 && div->initval > 0)
++              return div->initval;
++
++      reg = readl(common->base + div->reg);
++
++      if (div->initval == 0 || DIV_GET_EN_CLK_DIV_FACTOR(reg))
++              clockdiv = cv1800_clk_regfield_get(reg, div);
++      else if (div->initval > 0)
++              clockdiv = div->initval;
++
++      return clockdiv;
++}
++
++static u32 div_helper_round_rate(struct cv1800_clk_regfield *div,
++                               struct clk_hw *hw, struct clk_hw *parent,
++                               unsigned long rate, unsigned long *prate)
++{
++      if (div->width == 0) {
++              if (div->initval <= 0)
++                      return DIV_ROUND_UP_ULL(*prate, 1);
++              else
++                      return DIV_ROUND_UP_ULL(*prate, div->initval);
++      }
++
++      return divider_round_rate_parent(hw, parent, rate, prate, NULL,
++                                       div->width, div->flags);
++}
++
++static long div_round_rate(struct clk_hw *parent, unsigned long *parent_rate,
++                         unsigned long rate, int id, void *data)
++{
++      struct cv1800_clk_div *div = data;
++
++      return div_helper_round_rate(&div->div, &div->common.hw, parent,
++                                   rate, parent_rate);
++}
++
++static bool div_is_better_rate(struct cv1800_clk_common *common,
++                             unsigned long target, unsigned long now,
++                             unsigned long best)
++{
++      if (common->features & CLK_DIVIDER_ROUND_CLOSEST)
++              return abs_diff(target, now) < abs_diff(target, best);
++
++      return now <= target && now > best;
++}
++
++static int mux_helper_determine_rate(struct cv1800_clk_common *common,
++                                   struct clk_rate_request *req,
++                                   long (*round)(struct clk_hw *,
++                                                 unsigned long *,
++                                                 unsigned long,
++                                                 int,
++                                                 void *),
++                                   void *data)
++{
++      unsigned long best_parent_rate = 0, best_rate = 0;
++      struct clk_hw *best_parent, *hw = &common->hw;
++      unsigned int i;
++
++      if (clk_hw_get_flags(hw) & CLK_SET_RATE_NO_REPARENT) {
++              unsigned long adj_parent_rate;
++
++              best_parent = clk_hw_get_parent(hw);
++              best_parent_rate = clk_hw_get_rate(best_parent);
++
++              best_rate = round(best_parent, &adj_parent_rate,
++                                req->rate, -1, data);
++
++              goto find;
++      }
++
++      for (i = 0; i < clk_hw_get_num_parents(hw); i++) {
++              unsigned long tmp_rate, parent_rate;
++              struct clk_hw *parent;
++
++              parent = clk_hw_get_parent_by_index(hw, i);
++              if (!parent)
++                      continue;
++
++              parent_rate = clk_hw_get_rate(parent);
++
++              tmp_rate = round(parent, &parent_rate, req->rate, i, data);
++
++              if (tmp_rate == req->rate) {
++                      best_parent = parent;
++                      best_parent_rate = parent_rate;
++                      best_rate = tmp_rate;
++                      goto find;
++              }
++
++              if (div_is_better_rate(common, req->rate,
++                                     tmp_rate, best_rate)) {
++                      best_parent = parent;
++                      best_parent_rate = parent_rate;
++                      best_rate = tmp_rate;
++              }
++      }
++
++      if (best_rate == 0)
++              return -EINVAL;
++
++find:
++      req->best_parent_hw = best_parent;
++      req->best_parent_rate = best_parent_rate;
++      req->rate = best_rate;
++      return 0;
++}
++
++static int div_determine_rate(struct clk_hw *hw,
++                            struct clk_rate_request *req)
++{
++      struct cv1800_clk_div *div = hw_to_cv1800_clk_div(hw);
++
++      return mux_helper_determine_rate(&div->common, req,
++                                       div_round_rate, div);
++}
++
++static unsigned long div_recalc_rate(struct clk_hw *hw,
++                                   unsigned long parent_rate)
++{
++      struct cv1800_clk_div *div = hw_to_cv1800_clk_div(hw);
++      unsigned long val;
++
++      val = div_helper_get_clockdiv(&div->common, &div->div);
++      if (val == 0)
++              return 0;
++
++      return divider_recalc_rate(hw, parent_rate, val, NULL,
++                                 div->div.flags, div->div.width);
++}
++
++static int div_set_rate(struct clk_hw *hw, unsigned long rate,
++                       unsigned long parent_rate)
++{
++      struct cv1800_clk_div *div = hw_to_cv1800_clk_div(hw);
++      unsigned long val;
++
++      val = divider_get_val(rate, parent_rate, NULL,
++                            div->div.width, div->div.flags);
++
++      return div_helper_set_rate(&div->common, &div->div, val);
++}
++
++const struct clk_ops cv1800_clk_div_ops = {
++      .disable = div_disable,
++      .enable = div_enable,
++      .is_enabled = div_is_enabled,
++
++      .determine_rate = div_determine_rate,
++      .recalc_rate    = div_recalc_rate,
++      .set_rate = div_set_rate,
++};
++
++static inline struct cv1800_clk_bypass_div *
++hw_to_cv1800_clk_bypass_div(struct clk_hw *hw)
++{
++      struct cv1800_clk_div *div = hw_to_cv1800_clk_div(hw);
++
++      return container_of(div, struct cv1800_clk_bypass_div, div);
++}
++
++static long bypass_div_round_rate(struct clk_hw *parent,
++                                unsigned long *parent_rate,
++                                unsigned long rate, int id, void *data)
++{
++      struct cv1800_clk_bypass_div *div = data;
++
++      if (id == -1) {
++              if (cv1800_clk_checkbit(&div->div.common, &div->bypass))
++                      return *parent_rate;
++              else
++                      return div_round_rate(parent, parent_rate, rate,
++                                            -1, &div->div);
++      }
++
++      if (id == 0)
++              return *parent_rate;
++
++      return div_round_rate(parent, parent_rate, rate, id - 1, &div->div);
++}
++
++static int bypass_div_determine_rate(struct clk_hw *hw,
++                                   struct clk_rate_request *req)
++{
++      struct cv1800_clk_bypass_div *div = hw_to_cv1800_clk_bypass_div(hw);
++
++      return mux_helper_determine_rate(&div->div.common, req,
++                                       bypass_div_round_rate, div);
++}
++
++static unsigned long bypass_div_recalc_rate(struct clk_hw *hw,
++                                          unsigned long parent_rate)
++{
++      struct cv1800_clk_bypass_div *div = hw_to_cv1800_clk_bypass_div(hw);
++
++      if (cv1800_clk_checkbit(&div->div.common, &div->bypass))
++              return parent_rate;
++
++      return div_recalc_rate(hw, parent_rate);
++}
++
++static int bypass_div_set_rate(struct clk_hw *hw, unsigned long rate,
++                             unsigned long parent_rate)
++{
++      struct cv1800_clk_bypass_div *div = hw_to_cv1800_clk_bypass_div(hw);
++
++      if (cv1800_clk_checkbit(&div->div.common, &div->bypass))
++              return 0;
++
++      return div_set_rate(hw, rate, parent_rate);
++}
++
++static u8 bypass_div_get_parent(struct clk_hw *hw)
++{
++      struct cv1800_clk_bypass_div *div = hw_to_cv1800_clk_bypass_div(hw);
++
++      if (cv1800_clk_checkbit(&div->div.common, &div->bypass))
++              return 0;
++
++      return 1;
++}
++
++static int bypass_div_set_parent(struct clk_hw *hw, u8 index)
++{
++      struct cv1800_clk_bypass_div *div = hw_to_cv1800_clk_bypass_div(hw);
++
++      if (index)
++              return cv1800_clk_clearbit(&div->div.common, &div->bypass);
++
++      return cv1800_clk_setbit(&div->div.common, &div->bypass);
++}
++
++const struct clk_ops cv1800_clk_bypass_div_ops = {
++      .disable = div_disable,
++      .enable = div_enable,
++      .is_enabled = div_is_enabled,
++
++      .determine_rate = bypass_div_determine_rate,
++      .recalc_rate = bypass_div_recalc_rate,
++      .set_rate = bypass_div_set_rate,
++
++      .set_parent = bypass_div_set_parent,
++      .get_parent = bypass_div_get_parent,
++};
++
++/* MUX */
++static inline struct cv1800_clk_mux *hw_to_cv1800_clk_mux(struct clk_hw *hw)
++{
++      struct cv1800_clk_common *common = hw_to_cv1800_clk_common(hw);
++
++      return container_of(common, struct cv1800_clk_mux, common);
++}
++
++static int mux_enable(struct clk_hw *hw)
++{
++      struct cv1800_clk_mux *mux = hw_to_cv1800_clk_mux(hw);
++
++      return cv1800_clk_setbit(&mux->common, &mux->gate);
++}
++
++static void mux_disable(struct clk_hw *hw)
++{
++      struct cv1800_clk_mux *mux = hw_to_cv1800_clk_mux(hw);
++
++      cv1800_clk_clearbit(&mux->common, &mux->gate);
++}
++
++static int mux_is_enabled(struct clk_hw *hw)
++{
++      struct cv1800_clk_mux *mux = hw_to_cv1800_clk_mux(hw);
++
++      return cv1800_clk_checkbit(&mux->common, &mux->gate);
++}
++
++static long mux_round_rate(struct clk_hw *parent, unsigned long *parent_rate,
++                         unsigned long rate, int id, void *data)
++{
++      struct cv1800_clk_mux *mux = data;
++
++      return div_helper_round_rate(&mux->div, &mux->common.hw, parent,
++                                   rate, parent_rate);
++}
++
++static int mux_determine_rate(struct clk_hw *hw,
++                            struct clk_rate_request *req)
++{
++      struct cv1800_clk_mux *mux = hw_to_cv1800_clk_mux(hw);
++
++      return mux_helper_determine_rate(&mux->common, req,
++                                       mux_round_rate, mux);
++}
++
++static unsigned long mux_recalc_rate(struct clk_hw *hw,
++                                   unsigned long parent_rate)
++{
++      struct cv1800_clk_mux *mux = hw_to_cv1800_clk_mux(hw);
++      unsigned long val;
++
++      val = div_helper_get_clockdiv(&mux->common, &mux->div);
++      if (val == 0)
++              return 0;
++
++      return divider_recalc_rate(hw, parent_rate, val, NULL,
++                                 mux->div.flags, mux->div.width);
++}
++
++static int mux_set_rate(struct clk_hw *hw, unsigned long rate,
++                      unsigned long parent_rate)
++{
++      struct cv1800_clk_mux *mux = hw_to_cv1800_clk_mux(hw);
++      unsigned long val;
++
++      val = divider_get_val(rate, parent_rate, NULL,
++                            mux->div.width, mux->div.flags);
++
++      return div_helper_set_rate(&mux->common, &mux->div, val);
++}
++
++static u8 mux_get_parent(struct clk_hw *hw)
++{
++      struct cv1800_clk_mux *mux = hw_to_cv1800_clk_mux(hw);
++      u32 reg = readl(mux->common.base + mux->mux.reg);
++
++      return cv1800_clk_regfield_get(reg, &mux->mux);
++}
++
++static int _mux_set_parent(struct cv1800_clk_mux *mux, u8 index)
++{
++      u32 reg;
++
++      reg = readl(mux->common.base + mux->mux.reg);
++      reg = cv1800_clk_regfield_set(reg, index, &mux->mux);
++      writel(reg, mux->common.base + mux->mux.reg);
++
++      return 0;
++}
++
++static int mux_set_parent(struct clk_hw *hw, u8 index)
++{
++      struct cv1800_clk_mux *mux = hw_to_cv1800_clk_mux(hw);
++      unsigned long flags;
++
++      spin_lock_irqsave(mux->common.lock, flags);
++
++      _mux_set_parent(mux, index);
++
++      spin_unlock_irqrestore(mux->common.lock, flags);
++
++      return 0;
++}
++
++const struct clk_ops cv1800_clk_mux_ops = {
++      .disable = mux_disable,
++      .enable = mux_enable,
++      .is_enabled = mux_is_enabled,
++
++      .determine_rate = mux_determine_rate,
++      .recalc_rate = mux_recalc_rate,
++      .set_rate = mux_set_rate,
++
++      .set_parent = mux_set_parent,
++      .get_parent = mux_get_parent,
++};
++
++static inline struct cv1800_clk_bypass_mux *
++hw_to_cv1800_clk_bypass_mux(struct clk_hw *hw)
++{
++      struct cv1800_clk_mux *mux = hw_to_cv1800_clk_mux(hw);
++
++      return container_of(mux, struct cv1800_clk_bypass_mux, mux);
++}
++
++static long bypass_mux_round_rate(struct clk_hw *parent,
++                                unsigned long *parent_rate,
++                                unsigned long rate, int id, void *data)
++{
++      struct cv1800_clk_bypass_mux *mux = data;
++
++      if (id == -1) {
++              if (cv1800_clk_checkbit(&mux->mux.common, &mux->bypass))
++                      return *parent_rate;
++              else
++                      return mux_round_rate(parent, parent_rate, rate,
++                                            -1, &mux->mux);
++      }
++
++      if (id == 0)
++              return *parent_rate;
++
++      return mux_round_rate(parent, parent_rate, rate, id - 1, &mux->mux);
++}
++
++static int bypass_mux_determine_rate(struct clk_hw *hw,
++                                   struct clk_rate_request *req)
++{
++      struct cv1800_clk_bypass_mux *mux = hw_to_cv1800_clk_bypass_mux(hw);
++
++      return mux_helper_determine_rate(&mux->mux.common, req,
++                                       bypass_mux_round_rate, mux);
++}
++
++static unsigned long bypass_mux_recalc_rate(struct clk_hw *hw,
++                                          unsigned long parent_rate)
++{
++      struct cv1800_clk_bypass_mux *mux = hw_to_cv1800_clk_bypass_mux(hw);
++
++      if (cv1800_clk_checkbit(&mux->mux.common, &mux->bypass))
++              return parent_rate;
++
++      return mux_recalc_rate(hw, parent_rate);
++}
++
++static int bypass_mux_set_rate(struct clk_hw *hw, unsigned long rate,
++                             unsigned long parent_rate)
++{
++      struct cv1800_clk_bypass_mux *mux = hw_to_cv1800_clk_bypass_mux(hw);
++
++      if (cv1800_clk_checkbit(&mux->mux.common, &mux->bypass))
++              return 0;
++
++      return mux_set_rate(hw, rate, parent_rate);
++}
++
++static u8 bypass_mux_get_parent(struct clk_hw *hw)
++{
++      struct cv1800_clk_bypass_mux *mux = hw_to_cv1800_clk_bypass_mux(hw);
++
++      if (cv1800_clk_checkbit(&mux->mux.common, &mux->bypass))
++              return 0;
++
++      return mux_get_parent(hw) + 1;
++}
++
++static int bypass_mux_set_parent(struct clk_hw *hw, u8 index)
++{
++      struct cv1800_clk_bypass_mux *mux = hw_to_cv1800_clk_bypass_mux(hw);
++
++      if (index == 0)
++              return cv1800_clk_setbit(&mux->mux.common, &mux->bypass);
++
++      return cv1800_clk_clearbit(&mux->mux.common, &mux->bypass);
++}
++
++const struct clk_ops cv1800_clk_bypass_mux_ops = {
++      .disable = mux_disable,
++      .enable = mux_enable,
++      .is_enabled = mux_is_enabled,
++
++      .determine_rate = bypass_mux_determine_rate,
++      .recalc_rate = bypass_mux_recalc_rate,
++      .set_rate = bypass_mux_set_rate,
++
++      .set_parent = bypass_mux_set_parent,
++      .get_parent = bypass_mux_get_parent,
++};
++
++/* MMUX */
++static inline struct cv1800_clk_mmux *hw_to_cv1800_clk_mmux(struct clk_hw *hw)
++{
++      struct cv1800_clk_common *common = hw_to_cv1800_clk_common(hw);
++
++      return container_of(common, struct cv1800_clk_mmux, common);
++}
++
++static u8 mmux_get_parent_id(struct cv1800_clk_mmux *mmux)
++{
++      struct clk_hw *hw = &mmux->common.hw;
++      struct clk_hw *parent = clk_hw_get_parent(hw);
++      unsigned int i;
++
++      for (i = 0; i < clk_hw_get_num_parents(hw); i++) {
++              if (parent == clk_hw_get_parent_by_index(hw, i))
++                      return i;
++      }
++
++      unreachable();
++}
++
++static int mmux_enable(struct clk_hw *hw)
++{
++      struct cv1800_clk_mmux *mmux = hw_to_cv1800_clk_mmux(hw);
++
++      return cv1800_clk_setbit(&mmux->common, &mmux->gate);
++}
++
++static void mmux_disable(struct clk_hw *hw)
++{
++      struct cv1800_clk_mmux *mmux = hw_to_cv1800_clk_mmux(hw);
++
++      cv1800_clk_clearbit(&mmux->common, &mmux->gate);
++}
++
++static int mmux_is_enabled(struct clk_hw *hw)
++{
++      struct cv1800_clk_mmux *mmux = hw_to_cv1800_clk_mmux(hw);
++
++      return cv1800_clk_checkbit(&mmux->common, &mmux->gate);
++}
++
++static long mmux_round_rate(struct clk_hw *parent, unsigned long *parent_rate,
++                          unsigned long rate, int id, void *data)
++{
++      struct cv1800_clk_mmux *mmux = data;
++      s8 div_id;
++
++      if (id == -1) {
++              if (cv1800_clk_checkbit(&mmux->common, &mmux->bypass))
++                      return *parent_rate;
++
++              id = mmux_get_parent_id(mmux);
++      }
++
++      div_id = mmux->parent2sel[id];
++
++      if (div_id < 0)
++              return *parent_rate;
++
++      return div_helper_round_rate(&mmux->div[div_id],
++                                   &mmux->common.hw, parent,
++                                   rate, parent_rate);
++}
++
++static int mmux_determine_rate(struct clk_hw *hw,
++                             struct clk_rate_request *req)
++{
++      struct cv1800_clk_mmux *mmux = hw_to_cv1800_clk_mmux(hw);
++
++      return mux_helper_determine_rate(&mmux->common, req,
++                                       mmux_round_rate, mmux);
++}
++
++static unsigned long mmux_recalc_rate(struct clk_hw *hw,
++                                    unsigned long parent_rate)
++{
++      struct cv1800_clk_mmux *mmux = hw_to_cv1800_clk_mmux(hw);
++      unsigned long val;
++      struct cv1800_clk_regfield *div;
++
++      if (cv1800_clk_checkbit(&mmux->common, &mmux->bypass))
++              return parent_rate;
++
++      if (cv1800_clk_checkbit(&mmux->common, &mmux->clk_sel))
++              div = &mmux->div[0];
++      else
++              div = &mmux->div[1];
++
++      val = div_helper_get_clockdiv(&mmux->common, div);
++      if (val == 0)
++              return 0;
++
++      return divider_recalc_rate(hw, parent_rate, val, NULL,
++                                 div->flags, div->width);
++}
++
++static int mmux_set_rate(struct clk_hw *hw, unsigned long rate,
++                       unsigned long parent_rate)
++{
++      struct cv1800_clk_mmux *mmux = hw_to_cv1800_clk_mmux(hw);
++      struct cv1800_clk_regfield *div;
++      unsigned long val;
++
++      if (cv1800_clk_checkbit(&mmux->common, &mmux->bypass))
++              return parent_rate;
++
++      if (cv1800_clk_checkbit(&mmux->common, &mmux->clk_sel))
++              div = &mmux->div[0];
++      else
++              div = &mmux->div[1];
++
++      val = divider_get_val(rate, parent_rate, NULL,
++                            div->width, div->flags);
++
++      return div_helper_set_rate(&mmux->common, div, val);
++}
++
++static u8 mmux_get_parent(struct clk_hw *hw)
++{
++      struct cv1800_clk_mmux *mmux = hw_to_cv1800_clk_mmux(hw);
++      struct cv1800_clk_regfield *mux;
++      u32 reg;
++      s8 clk_sel;
++
++      if (cv1800_clk_checkbit(&mmux->common, &mmux->bypass))
++              return 0;
++
++      if (cv1800_clk_checkbit(&mmux->common, &mmux->clk_sel))
++              clk_sel = 0;
++      else
++              clk_sel = 1;
++      mux = &mmux->mux[clk_sel];
++
++      reg = readl(mmux->common.base + mux->reg);
++
++      return mmux->sel2parent[clk_sel][cv1800_clk_regfield_get(reg, mux)];
++}
++
++static int mmux_set_parent(struct clk_hw *hw, u8 index)
++{
++      struct cv1800_clk_mmux *mmux = hw_to_cv1800_clk_mmux(hw);
++      struct cv1800_clk_regfield *mux;
++      unsigned long flags;
++      u32 reg;
++      s8 clk_sel = mmux->parent2sel[index];
++
++      if (index == 0 || clk_sel == -1) {
++              cv1800_clk_setbit(&mmux->common, &mmux->bypass);
++              goto release;
++      }
++
++      cv1800_clk_clearbit(&mmux->common, &mmux->bypass);
++
++      if (clk_sel)
++              cv1800_clk_clearbit(&mmux->common, &mmux->clk_sel);
++      else
++              cv1800_clk_setbit(&mmux->common, &mmux->clk_sel);
++
++      spin_lock_irqsave(mmux->common.lock, flags);
++
++      mux = &mmux->mux[clk_sel];
++      reg = readl(mmux->common.base + mux->reg);
++      reg = cv1800_clk_regfield_set(reg, index, mux);
++
++      writel(reg, mmux->common.base + mux->reg);
++
++      spin_unlock_irqrestore(mmux->common.lock, flags);
++
++release:
++      return 0;
++}
++
++const struct clk_ops cv1800_clk_mmux_ops = {
++      .disable = mmux_disable,
++      .enable = mmux_enable,
++      .is_enabled = mmux_is_enabled,
++
++      .determine_rate = mmux_determine_rate,
++      .recalc_rate = mmux_recalc_rate,
++      .set_rate = mmux_set_rate,
++
++      .set_parent = mmux_set_parent,
++      .get_parent = mmux_get_parent,
++};
++
++/* AUDIO CLK */
++static inline struct cv1800_clk_audio *
++hw_to_cv1800_clk_audio(struct clk_hw *hw)
++{
++      struct cv1800_clk_common *common = hw_to_cv1800_clk_common(hw);
++
++      return container_of(common, struct cv1800_clk_audio, common);
++}
++
++static int aclk_enable(struct clk_hw *hw)
++{
++      struct cv1800_clk_audio *aclk = hw_to_cv1800_clk_audio(hw);
++
++      cv1800_clk_setbit(&aclk->common, &aclk->src_en);
++      return cv1800_clk_setbit(&aclk->common, &aclk->output_en);
++}
++
++static void aclk_disable(struct clk_hw *hw)
++{
++      struct cv1800_clk_audio *aclk = hw_to_cv1800_clk_audio(hw);
++
++      cv1800_clk_clearbit(&aclk->common, &aclk->output_en);
++      cv1800_clk_clearbit(&aclk->common, &aclk->src_en);
++}
++
++static int aclk_is_enabled(struct clk_hw *hw)
++{
++      struct cv1800_clk_audio *aclk = hw_to_cv1800_clk_audio(hw);
++
++      return cv1800_clk_checkbit(&aclk->common, &aclk->output_en);
++}
++
++static int aclk_determine_rate(struct clk_hw *hw,
++                             struct clk_rate_request *req)
++{
++      struct cv1800_clk_audio *aclk = hw_to_cv1800_clk_audio(hw);
++
++      req->rate = aclk->target_rate;
++
++      return 0;
++}
++
++static unsigned long aclk_recalc_rate(struct clk_hw *hw,
++                                    unsigned long parent_rate)
++{
++      struct cv1800_clk_audio *aclk = hw_to_cv1800_clk_audio(hw);
++      u64 rate = parent_rate;
++      u64 factor = 2;
++      u32 regval;
++
++      if (!cv1800_clk_checkbit(&aclk->common, &aclk->div_en))
++              return 0;
++
++      regval = readl(aclk->common.base + aclk->m.reg);
++      factor *= cv1800_clk_regfield_get(regval, &aclk->m);
++
++      regval = readl(aclk->common.base + aclk->n.reg);
++      rate *= cv1800_clk_regfield_get(regval, &aclk->n);
++
++      return DIV64_U64_ROUND_UP(rate, factor);
++}
++
++static void aclk_determine_mn(unsigned long parent_rate, unsigned long 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 int aclk_set_rate(struct clk_hw *hw, unsigned long rate,
++                       unsigned long parent_rate)
++{
++      struct cv1800_clk_audio *aclk = hw_to_cv1800_clk_audio(hw);
++      unsigned long flags;
++      u32 m, n;
++
++      aclk_determine_mn(parent_rate, rate,
++                        &m, &n);
++
++      spin_lock_irqsave(aclk->common.lock, flags);
++
++      writel(m, aclk->common.base + aclk->m.reg);
++      writel(n, aclk->common.base + aclk->n.reg);
++
++      cv1800_clk_setbit(&aclk->common, &aclk->div_en);
++      cv1800_clk_setbit(&aclk->common, &aclk->div_up);
++
++      spin_unlock_irqrestore(aclk->common.lock, flags);
++
++      return 0;
++}
++
++const struct clk_ops cv1800_clk_audio_ops = {
++      .disable = aclk_disable,
++      .enable = aclk_enable,
++      .is_enabled = aclk_is_enabled,
++
++      .determine_rate = aclk_determine_rate,
++      .recalc_rate = aclk_recalc_rate,
++      .set_rate = aclk_set_rate,
++};
+diff --git a/drivers/clk/sophgo/clk-cv18xx-ip.h b/drivers/clk/sophgo/clk-cv18xx-ip.h
+new file mode 100644
+index 000000000000..b37ba42bfde3
+--- /dev/null
++++ b/drivers/clk/sophgo/clk-cv18xx-ip.h
+@@ -0,0 +1,261 @@
++/* SPDX-License-Identifier: GPL-2.0 */
++/*
++ * Copyright (C) 2023 Inochi Amaoto <inochiama@outlook.com>
++ */
++
++#ifndef _CLK_SOPHGO_CV1800_IP_H_
++#define _CLK_SOPHGO_CV1800_IP_H_
++
++#include "clk-cv18xx-common.h"
++
++struct cv1800_clk_gate {
++      struct cv1800_clk_common        common;
++      struct cv1800_clk_regbit        gate;
++};
++
++struct cv1800_clk_div_data {
++      u32             reg;
++      u32             mask;
++      u32             width;
++      u32             init;
++      u32             flags;
++};
++
++struct cv1800_clk_div {
++      struct cv1800_clk_common        common;
++      struct cv1800_clk_regbit        gate;
++      struct cv1800_clk_regfield      div;
++};
++
++struct cv1800_clk_bypass_div {
++      struct cv1800_clk_div           div;
++      struct cv1800_clk_regbit        bypass;
++};
++
++struct cv1800_clk_mux {
++      struct cv1800_clk_common        common;
++      struct cv1800_clk_regbit        gate;
++      struct cv1800_clk_regfield      div;
++      struct cv1800_clk_regfield      mux;
++};
++
++struct cv1800_clk_bypass_mux {
++      struct cv1800_clk_mux           mux;
++      struct cv1800_clk_regbit        bypass;
++};
++
++struct cv1800_clk_mmux {
++      struct cv1800_clk_common        common;
++      struct cv1800_clk_regbit        gate;
++      struct cv1800_clk_regfield      div[2];
++      struct cv1800_clk_regfield      mux[2];
++      struct cv1800_clk_regbit        bypass;
++      struct cv1800_clk_regbit        clk_sel;
++      const s8                        *parent2sel;
++      const u8                        *sel2parent[2];
++};
++
++struct cv1800_clk_audio {
++      struct cv1800_clk_common        common;
++      struct cv1800_clk_regbit        src_en;
++      struct cv1800_clk_regbit        output_en;
++      struct cv1800_clk_regbit        div_en;
++      struct cv1800_clk_regbit        div_up;
++      struct cv1800_clk_regfield      m;
++      struct cv1800_clk_regfield      n;
++      u32                             target_rate;
++};
++
++#define CV1800_GATE(_name, _parent, _gate_reg, _gate_shift, _flags)   \
++      struct cv1800_clk_gate _name = {                                \
++              .common = CV1800_CLK_COMMON(#_name, _parent,            \
++                                          &cv1800_clk_gate_ops,       \
++                                          _flags),                    \
++              .gate   = CV1800_CLK_BIT(_gate_reg, _gate_shift),       \
++      }
++
++#define _CV1800_DIV(_name, _parent, _gate_reg, _gate_shift,           \
++                  _div_reg, _div_shift, _div_width, _div_init,        \
++                  _div_flag, _ops, _flags)                            \
++      {                                                               \
++              .common         = CV1800_CLK_COMMON(#_name, _parent,    \
++                                                  _ops, _flags),      \
++              .gate           = CV1800_CLK_BIT(_gate_reg,             \
++                                               _gate_shift),          \
++              .div            = CV1800_CLK_REG(_div_reg, _div_shift,  \
++                                               _div_width, _div_init, \
++                                               _div_flag),            \
++      }
++
++#define _CV1800_FIXED_DIV_FLAG        \
++      (CLK_DIVIDER_ONE_BASED | CLK_DIVIDER_ROUND_CLOSEST)
++
++#define _CV1800_FIXED_DIV(_name, _parent, _gate_reg, _gate_shift,     \
++                        _fix_div, _ops, _flags)                       \
++      {                                                               \
++              .common         = CV1800_CLK_COMMON(#_name, _parent,    \
++                                                  _ops, _flags),      \
++              .gate           = CV1800_CLK_BIT(_gate_reg,             \
++                                               _gate_shift),          \
++              .div            = CV1800_CLK_REG(0, 0, 0,               \
++                                               _fix_div,              \
++                                               _CV1800_FIXED_DIV_FLAG),\
++      }
++
++#define CV1800_DIV(_name, _parent, _gate_reg, _gate_shift,            \
++                 _div_reg, _div_shift, _div_width, _div_init,         \
++                 _div_flag, _flags)                                   \
++      struct cv1800_clk_div _name =                                   \
++              _CV1800_DIV(_name, _parent, _gate_reg, _gate_shift,     \
++                          _div_reg, _div_shift, _div_width, _div_init,\
++                          _div_flag, &cv1800_clk_div_ops, _flags)
++
++#define CV1800_BYPASS_DIV(_name, _parent, _gate_reg, _gate_shift,     \
++                        _div_reg, _div_shift, _div_width, _div_init,  \
++                        _div_flag, _bypass_reg, _bypass_shift, _flags)\
++      struct cv1800_clk_bypass_div _name = {                          \
++              .div    = _CV1800_DIV(_name, _parent,                   \
++                                    _gate_reg, _gate_shift,           \
++                                    _div_reg, _div_shift,             \
++                                    _div_width, _div_init, _div_flag, \
++                                    &cv1800_clk_bypass_div_ops,       \
++                                    _flags),                          \
++              .bypass = CV1800_CLK_BIT(_bypass_reg, _bypass_shift),   \
++      }
++
++#define CV1800_FIXED_DIV(_name, _parent, _gate_reg, _gate_shift,      \
++                       _fix_div, _flags)                              \
++      struct cv1800_clk_div _name =                                   \
++              _CV1800_FIXED_DIV(_name, _parent,                       \
++                                _gate_reg, _gate_shift,               \
++                                _fix_div,                             \
++                                &cv1800_clk_div_ops, _flags)          \
++
++#define CV1800_BYPASS_FIXED_DIV(_name, _parent, _gate_reg, _gate_shift,       \
++                              _fix_div, _bypass_reg, _bypass_shift,   \
++                              _flags)                                 \
++      struct cv1800_clk_bypass_div _name = {                          \
++              .div    = _CV1800_FIXED_DIV(_name, _parent,             \
++                                          _gate_reg, _gate_shift,     \
++                                          _fix_div,                   \
++                                          &cv1800_clk_bypass_div_ops, \
++                                          _flags),                    \
++              .bypass = CV1800_CLK_BIT(_bypass_reg, _bypass_shift),   \
++      }
++
++#define _CV1800_MUX(_name, _parent, _gate_reg, _gate_shift,           \
++                  _div_reg, _div_shift, _div_width, _div_init,        \
++                  _div_flag,                                          \
++                  _mux_reg, _mux_shift, _mux_width,                   \
++                  _ops, _flags)                                       \
++      {                                                               \
++              .common         = CV1800_CLK_COMMON(#_name, _parent,    \
++                                                  _ops, _flags),      \
++              .gate           = CV1800_CLK_BIT(_gate_reg,             \
++                                               _gate_shift),          \
++              .div            = CV1800_CLK_REG(_div_reg, _div_shift,  \
++                                               _div_width, _div_init, \
++                                               _div_flag),            \
++              .mux            = CV1800_CLK_REG(_mux_reg, _mux_shift,  \
++                                               _mux_width, 0, 0),     \
++      }
++
++#define CV1800_MUX(_name, _parent, _gate_reg, _gate_shift,            \
++                 _div_reg, _div_shift, _div_width, _div_init,         \
++                 _div_flag,                                           \
++                 _mux_reg, _mux_shift, _mux_width, _flags)            \
++      struct cv1800_clk_mux _name =                                   \
++              _CV1800_MUX(_name, _parent, _gate_reg, _gate_shift,     \
++                          _div_reg, _div_shift, _div_width, _div_init,\
++                          _div_flag, _mux_reg, _mux_shift, _mux_width,\
++                          &cv1800_clk_mux_ops, _flags)
++
++#define CV1800_BYPASS_MUX(_name, _parent, _gate_reg, _gate_shift,     \
++                        _div_reg, _div_shift, _div_width, _div_init,  \
++                        _div_flag,                                    \
++                        _mux_reg, _mux_shift, _mux_width,             \
++                        _bypass_reg, _bypass_shift, _flags)           \
++      struct cv1800_clk_bypass_mux _name = {                          \
++              .mux    = _CV1800_MUX(_name, _parent,                   \
++                                    _gate_reg, _gate_shift,           \
++                                    _div_reg, _div_shift, _div_width, \
++                                    _div_init, _div_flag,             \
++                                    _mux_reg, _mux_shift, _mux_width, \
++                                    &cv1800_clk_bypass_mux_ops,       \
++                                    _flags),                          \
++              .bypass = CV1800_CLK_BIT(_bypass_reg, _bypass_shift),   \
++      }
++
++#define CV1800_MMUX(_name, _parent, _gate_reg, _gate_shift,           \
++                  _div0_reg, _div0_shift, _div0_width, _div0_init,    \
++                  _div0_flag,                                         \
++                  _div1_reg, _div1_shift, _div1_width, _div1_init,    \
++                  _div1_flag,                                         \
++                  _mux0_reg, _mux0_shift, _mux0_width,                \
++                  _mux1_reg, _mux1_shift, _mux1_width,                \
++                  _bypass_reg, _bypass_shift,                         \
++                  _clk_sel_reg, _clk_sel_shift,                       \
++                  _parent2sel, _sel2parent0, _sel2parent1, _flags)    \
++      struct cv1800_clk_mmux _name = {                                \
++              .common         = CV1800_CLK_COMMON(#_name, _parent,    \
++                                                  &cv1800_clk_mmux_ops,\
++                                                  _flags),            \
++              .gate           = CV1800_CLK_BIT(_gate_reg, _gate_shift),\
++              .div            = {                                     \
++                      CV1800_CLK_REG(_div0_reg, _div0_shift,          \
++                                     _div0_width, _div0_init,         \
++                                     _div0_flag),                     \
++                      CV1800_CLK_REG(_div1_reg, _div1_shift,          \
++                                     _div1_width, _div1_init,         \
++                                     _div1_flag),                     \
++              },                                                      \
++              .mux            = {                                     \
++                      CV1800_CLK_REG(_mux0_reg, _mux0_shift,          \
++                                     _mux0_width, 0, 0),              \
++                      CV1800_CLK_REG(_mux1_reg, _mux1_shift,          \
++                                     _mux1_width, 0, 0),              \
++              },                                                      \
++              .bypass         = CV1800_CLK_BIT(_bypass_reg,           \
++                                               _bypass_shift),        \
++              .clk_sel        = CV1800_CLK_BIT(_clk_sel_reg,          \
++                                               _clk_sel_shift),       \
++              .parent2sel     = _parent2sel,                          \
++              .sel2parent     = { _sel2parent0, _sel2parent1 },       \
++      }
++
++#define CV1800_ACLK(_name, _parent,                                   \
++                  _src_en_reg, _src_en_reg_shift,                     \
++                  _output_en_reg, _output_en_shift,                   \
++                  _div_en_reg, _div_en_reg_shift,                     \
++                  _div_up_reg, _div_up_reg_shift,                     \
++                  _m_reg, _m_shift, _m_width, _m_flag,                \
++                  _n_reg, _n_shift, _n_width, _n_flag,                \
++                  _target_rate, _flags)                               \
++      struct cv1800_clk_audio _name = {                               \
++              .common         = CV1800_CLK_COMMON(#_name, _parent,    \
++                                                  &cv1800_clk_audio_ops,\
++                                                  _flags),            \
++              .src_en         = CV1800_CLK_BIT(_src_en_reg,           \
++                                               _src_en_reg_shift),    \
++              .output_en      = CV1800_CLK_BIT(_output_en_reg,        \
++                                               _output_en_shift),     \
++              .div_en         = CV1800_CLK_BIT(_div_en_reg,           \
++                                               _div_en_reg_shift),    \
++              .div_up         = CV1800_CLK_BIT(_div_up_reg,           \
++                                               _div_up_reg_shift),    \
++              .m              = CV1800_CLK_REG(_m_reg, _m_shift,      \
++                                               _m_width, 0, _m_flag), \
++              .n              = CV1800_CLK_REG(_n_reg, _n_shift,      \
++                                               _n_width, 0, _n_flag), \
++              .target_rate    = _target_rate,                         \
++      }
++
++extern const struct clk_ops cv1800_clk_gate_ops;
++extern const struct clk_ops cv1800_clk_div_ops;
++extern const struct clk_ops cv1800_clk_bypass_div_ops;
++extern const struct clk_ops cv1800_clk_mux_ops;
++extern const struct clk_ops cv1800_clk_bypass_mux_ops;
++extern const struct clk_ops cv1800_clk_mmux_ops;
++extern const struct clk_ops cv1800_clk_audio_ops;
++
++#endif // _CLK_SOPHGO_CV1800_IP_H_
+diff --git a/drivers/clk/sophgo/clk-cv18xx-pll.c b/drivers/clk/sophgo/clk-cv18xx-pll.c
+new file mode 100644
+index 000000000000..c546dad1791c
+--- /dev/null
++++ b/drivers/clk/sophgo/clk-cv18xx-pll.c
+@@ -0,0 +1,420 @@
++// SPDX-License-Identifier: GPL-2.0
++/*
++ * Copyright (C) 2023 Inochi Amaoto <inochiama@outlook.com>
++ */
++
++#include <linux/clk-provider.h>
++#include <linux/io.h>
++#include <linux/limits.h>
++#include <linux/spinlock.h>
++
++#include "clk-cv18xx-pll.h"
++
++static inline struct cv1800_clk_pll *hw_to_cv1800_clk_pll(struct clk_hw *hw)
++{
++      struct cv1800_clk_common *common = hw_to_cv1800_clk_common(hw);
++
++      return container_of(common, struct cv1800_clk_pll, common);
++}
++
++static unsigned long ipll_calc_rate(unsigned long parent_rate,
++                                  unsigned long pre_div_sel,
++                                  unsigned long div_sel,
++                                  unsigned long post_div_sel)
++{
++      uint64_t rate = parent_rate;
++
++      rate *= div_sel;
++      do_div(rate, pre_div_sel * post_div_sel);
++
++      return rate;
++}
++
++static unsigned long ipll_recalc_rate(struct clk_hw *hw,
++                                    unsigned long parent_rate)
++{
++      struct cv1800_clk_pll *pll = hw_to_cv1800_clk_pll(hw);
++      u32 value;
++
++      value = readl(pll->common.base + pll->pll_reg);
++
++      return ipll_calc_rate(parent_rate,
++                            PLL_GET_PRE_DIV_SEL(value),
++                            PLL_GET_DIV_SEL(value),
++                            PLL_GET_POST_DIV_SEL(value));
++}
++
++static int ipll_find_rate(const struct cv1800_clk_pll_limit *limit,
++                        unsigned long prate, unsigned long *rate,
++                        u32 *value)
++{
++      unsigned long best_rate = 0;
++      unsigned long trate = *rate;
++      unsigned long pre_div_sel = 0, div_sel = 0, post_div_sel = 0;
++      unsigned long pre, div, post;
++      u32 detected = *value;
++      unsigned long tmp;
++
++      for_each_pll_limit_range(pre, &limit->pre_div) {
++              for_each_pll_limit_range(div, &limit->div) {
++                      for_each_pll_limit_range(post, &limit->post_div) {
++                              tmp = ipll_calc_rate(prate, pre, div, post);
++
++                              if (tmp > trate)
++                                      continue;
++
++                              if ((trate - tmp) < (trate - best_rate)) {
++                                      best_rate = tmp;
++                                      pre_div_sel = pre;
++                                      div_sel = div;
++                                      post_div_sel = post;
++                              }
++                      }
++              }
++      }
++
++      if (best_rate) {
++              detected = PLL_SET_PRE_DIV_SEL(detected, pre_div_sel);
++              detected = PLL_SET_POST_DIV_SEL(detected, post_div_sel);
++              detected = PLL_SET_DIV_SEL(detected, div_sel);
++              *value = detected;
++              *rate = best_rate;
++              return 0;
++      }
++
++      return -EINVAL;
++}
++
++static int ipll_determine_rate(struct clk_hw *hw, struct clk_rate_request *req)
++{
++      u32 val;
++      struct cv1800_clk_pll *pll = hw_to_cv1800_clk_pll(hw);
++
++      return ipll_find_rate(pll->pll_limit, req->best_parent_rate,
++                            &req->rate, &val);
++}
++
++static void pll_get_mode_ctrl(unsigned long div_sel,
++                            bool (*mode_ctrl_check)(unsigned long,
++                                                    unsigned long,
++                                                    unsigned long),
++                            const struct cv1800_clk_pll_limit *limit,
++                            u32 *value)
++{
++      unsigned long ictrl = 0, mode = 0;
++      u32 detected = *value;
++
++      for_each_pll_limit_range(mode, &limit->mode) {
++              for_each_pll_limit_range(ictrl, &limit->ictrl) {
++                      if (mode_ctrl_check(div_sel, ictrl, mode)) {
++                              detected = PLL_SET_SEL_MODE(detected, mode);
++                              detected = PLL_SET_ICTRL(detected, ictrl);
++                              *value = detected;
++                              return;
++                      }
++              }
++      }
++}
++
++static bool ipll_check_mode_ctrl_restrict(unsigned long div_sel,
++                                        unsigned long ictrl,
++                                        unsigned long mode)
++{
++      unsigned long left_rest = 20 * div_sel;
++      unsigned long right_rest = 35 * div_sel;
++      unsigned long test = 184 * (1 + mode) * (1 + ictrl) / 2;
++
++      return test > left_rest && test <= right_rest;
++}
++
++static int ipll_set_rate(struct clk_hw *hw, unsigned long rate,
++                       unsigned long parent_rate)
++{
++      u32 regval, detected = 0;
++      unsigned long flags;
++      struct cv1800_clk_pll *pll = hw_to_cv1800_clk_pll(hw);
++
++      ipll_find_rate(pll->pll_limit, parent_rate, &rate, &detected);
++      pll_get_mode_ctrl(PLL_GET_DIV_SEL(detected),
++                        ipll_check_mode_ctrl_restrict,
++                        pll->pll_limit, &detected);
++
++      spin_lock_irqsave(pll->common.lock, flags);
++
++      regval = readl(pll->common.base + pll->pll_reg);
++      regval = PLL_COPY_REG(regval, detected);
++
++      writel(regval, pll->common.base + pll->pll_reg);
++
++      spin_unlock_irqrestore(pll->common.lock, flags);
++
++      cv1800_clk_wait_for_lock(&pll->common, pll->pll_status.reg,
++                            BIT(pll->pll_status.shift));
++
++      return 0;
++}
++
++static int pll_enable(struct clk_hw *hw)
++{
++      struct cv1800_clk_pll *pll = hw_to_cv1800_clk_pll(hw);
++
++      return cv1800_clk_clearbit(&pll->common, &pll->pll_pwd);
++}
++
++static void pll_disable(struct clk_hw *hw)
++{
++      struct cv1800_clk_pll *pll = hw_to_cv1800_clk_pll(hw);
++
++      cv1800_clk_setbit(&pll->common, &pll->pll_pwd);
++}
++
++static int pll_is_enable(struct clk_hw *hw)
++{
++      struct cv1800_clk_pll *pll = hw_to_cv1800_clk_pll(hw);
++
++      return cv1800_clk_checkbit(&pll->common, &pll->pll_pwd) == 0;
++}
++
++const struct clk_ops cv1800_clk_ipll_ops = {
++      .disable = pll_disable,
++      .enable = pll_enable,
++      .is_enabled = pll_is_enable,
++
++      .recalc_rate = ipll_recalc_rate,
++      .determine_rate = ipll_determine_rate,
++      .set_rate = ipll_set_rate,
++};
++
++#define PLL_SYN_FACTOR_DOT_POS                26
++#define PLL_SYN_FACTOR_MINIMUM                ((4 << PLL_SYN_FACTOR_DOT_POS) + 1)
++
++static bool fpll_is_factional_mode(struct cv1800_clk_pll *pll)
++{
++      return cv1800_clk_checkbit(&pll->common, &pll->pll_syn->en);
++}
++
++static unsigned long fpll_calc_rate(unsigned long parent_rate,
++                                  unsigned long pre_div_sel,
++                                  unsigned long div_sel,
++                                  unsigned long post_div_sel,
++                                  unsigned long ssc_syn_set,
++                                  bool is_full_parent)
++{
++      u64 dividend = parent_rate * div_sel;
++      u64 factor = ssc_syn_set * pre_div_sel * post_div_sel;
++      unsigned long rate;
++
++      dividend <<= PLL_SYN_FACTOR_DOT_POS - 1;
++      rate = dividend / factor;
++      dividend %= factor;
++
++      if (is_full_parent) {
++              dividend <<= 1;
++              rate <<= 1;
++      }
++
++      rate += DIV64_U64_ROUND_CLOSEST(dividend, factor);
++
++      return rate;
++}
++
++static unsigned long fpll_recalc_rate(struct clk_hw *hw,
++                                        unsigned long parent_rate)
++{
++      struct cv1800_clk_pll *pll = hw_to_cv1800_clk_pll(hw);
++      u32 value;
++      bool clk_full;
++      u32 syn_set;
++
++      if (!fpll_is_factional_mode(pll))
++              return ipll_recalc_rate(hw, parent_rate);
++
++      syn_set = readl(pll->common.base + pll->pll_syn->set);
++
++      if (syn_set == 0)
++              return 0;
++
++      clk_full = cv1800_clk_checkbit(&pll->common,
++                                        &pll->pll_syn->clk_half);
++
++      value = readl(pll->common.base + pll->pll_reg);
++
++      return fpll_calc_rate(parent_rate,
++                            PLL_GET_PRE_DIV_SEL(value),
++                            PLL_GET_DIV_SEL(value),
++                            PLL_GET_POST_DIV_SEL(value),
++                            syn_set, clk_full);
++}
++
++static unsigned long fpll_find_synthesizer(unsigned long parent,
++                                         unsigned long rate,
++                                         unsigned long pre_div,
++                                         unsigned long div,
++                                         unsigned long post_div,
++                                         bool is_full_parent,
++                                         u32 *ssc_syn_set)
++{
++      u32 test_max = U32_MAX, test_min = PLL_SYN_FACTOR_MINIMUM;
++      unsigned long trate;
++
++      while (test_min < test_max) {
++              u32 tssc = (test_max + test_min) / 2;
++
++              trate = fpll_calc_rate(parent, pre_div, div, post_div,
++                                     tssc, is_full_parent);
++
++              if (trate == rate) {
++                      test_min = tssc;
++                      break;
++              }
++
++              if (trate > rate)
++                      test_min = tssc + 1;
++              else
++                      test_max = tssc - 1;
++      }
++
++      if (trate != 0)
++              *ssc_syn_set = test_min;
++
++      return trate;
++}
++
++static int fpll_find_rate(struct cv1800_clk_pll *pll,
++                        const struct cv1800_clk_pll_limit *limit,
++                        unsigned long prate,
++                        unsigned long *rate,
++                        u32 *value, u32 *ssc_syn_set)
++{
++      unsigned long best_rate = 0;
++      unsigned long pre_div_sel = 0, div_sel = 0, post_div_sel = 0;
++      unsigned long pre, div, post;
++      unsigned long trate = *rate;
++      u32 detected = *value;
++      unsigned long tmp;
++      bool clk_full = cv1800_clk_checkbit(&pll->common,
++                                             &pll->pll_syn->clk_half);
++
++      for_each_pll_limit_range(pre, &limit->pre_div) {
++              for_each_pll_limit_range(post, &limit->post_div) {
++                      for_each_pll_limit_range(div, &limit->div) {
++                              tmp = fpll_find_synthesizer(prate, trate,
++                                                          pre, div, post,
++                                                          clk_full,
++                                                          ssc_syn_set);
++
++                              if ((trate - tmp) < (trate - best_rate)) {
++                                      best_rate = tmp;
++                                      pre_div_sel = pre;
++                                      div_sel = div;
++                                      post_div_sel = post;
++                              }
++                      }
++              }
++      }
++
++      if (best_rate) {
++              detected = PLL_SET_PRE_DIV_SEL(detected, pre_div_sel);
++              detected = PLL_SET_POST_DIV_SEL(detected, post_div_sel);
++              detected = PLL_SET_DIV_SEL(detected, div_sel);
++              *value = detected;
++              *rate = best_rate;
++              return 0;
++      }
++
++      return -EINVAL;
++}
++
++static int fpll_determine_rate(struct clk_hw *hw, struct clk_rate_request *req)
++{
++      struct cv1800_clk_pll *pll = hw_to_cv1800_clk_pll(hw);
++      u32 val, ssc_syn_set;
++
++      if (!fpll_is_factional_mode(pll))
++              return ipll_determine_rate(hw, req);
++
++      fpll_find_rate(pll, &pll->pll_limit[2], req->best_parent_rate,
++                     &req->rate, &val, &ssc_syn_set);
++
++      return 0;
++}
++
++static bool fpll_check_mode_ctrl_restrict(unsigned long div_sel,
++                                        unsigned long ictrl,
++                                        unsigned long mode)
++{
++      unsigned long left_rest = 10 * div_sel;
++      unsigned long right_rest = 24 * div_sel;
++      unsigned long test = 184 * (1 + mode) * (1 + ictrl) / 2;
++
++      return test > left_rest && test <= right_rest;
++}
++
++static int fpll_set_rate(struct clk_hw *hw, unsigned long rate,
++                       unsigned long parent_rate)
++{
++      u32 regval;
++      u32 detected = 0, detected_ssc = 0;
++      unsigned long flags;
++      struct cv1800_clk_pll *pll = hw_to_cv1800_clk_pll(hw);
++
++      if (!fpll_is_factional_mode(pll))
++              return ipll_set_rate(hw, rate, parent_rate);
++
++      fpll_find_rate(pll, &pll->pll_limit[2], parent_rate,
++                     &rate, &detected, &detected_ssc);
++      pll_get_mode_ctrl(PLL_GET_DIV_SEL(detected),
++                        fpll_check_mode_ctrl_restrict,
++                        pll->pll_limit, &detected);
++
++      spin_lock_irqsave(pll->common.lock, flags);
++
++      writel(detected_ssc, pll->common.base + pll->pll_syn->set);
++
++      regval = readl(pll->common.base + pll->pll_reg);
++      regval = PLL_COPY_REG(regval, detected);
++
++      writel(regval, pll->common.base + pll->pll_reg);
++
++      spin_unlock_irqrestore(pll->common.lock, flags);
++
++      cv1800_clk_wait_for_lock(&pll->common, pll->pll_status.reg,
++                            BIT(pll->pll_status.shift));
++
++      return 0;
++}
++
++static u8 fpll_get_parent(struct clk_hw *hw)
++{
++      struct cv1800_clk_pll *pll = hw_to_cv1800_clk_pll(hw);
++
++      if (fpll_is_factional_mode(pll))
++              return 1;
++
++      return 0;
++}
++
++static int fpll_set_parent(struct clk_hw *hw, u8 index)
++{
++      struct cv1800_clk_pll *pll = hw_to_cv1800_clk_pll(hw);
++
++      if (index)
++              cv1800_clk_setbit(&pll->common, &pll->pll_syn->en);
++      else
++              cv1800_clk_clearbit(&pll->common, &pll->pll_syn->en);
++
++      return 0;
++}
++
++const struct clk_ops cv1800_clk_fpll_ops = {
++      .disable = pll_disable,
++      .enable = pll_enable,
++      .is_enabled = pll_is_enable,
++
++      .recalc_rate = fpll_recalc_rate,
++      .determine_rate = fpll_determine_rate,
++      .set_rate = fpll_set_rate,
++
++      .set_parent = fpll_set_parent,
++      .get_parent = fpll_get_parent,
++};
+diff --git a/drivers/clk/sophgo/clk-cv18xx-pll.h b/drivers/clk/sophgo/clk-cv18xx-pll.h
+new file mode 100644
+index 000000000000..7a33f3da2d64
+--- /dev/null
++++ b/drivers/clk/sophgo/clk-cv18xx-pll.h
+@@ -0,0 +1,118 @@
++/* SPDX-License-Identifier: GPL-2.0 */
++/*
++ * Copyright (C) 2023 Inochi Amaoto <inochiama@outlook.com>
++ */
++
++#ifndef _CLK_SOPHGO_CV1800_PLL_H_
++#define _CLK_SOPHGO_CV1800_PLL_H_
++
++#include "clk-cv18xx-common.h"
++
++struct cv1800_clk_pll_limit {
++      struct {
++              u8 min;
++              u8 max;
++      } pre_div, div, post_div, ictrl, mode;
++};
++
++#define _CV1800_PLL_LIMIT(_min, _max) \
++      {                               \
++              .min = _min,            \
++              .max = _max,            \
++      }                               \
++
++#define for_each_pll_limit_range(_var, _restrict) \
++      for (_var = (_restrict)->min; _var <= (_restrict)->max; _var++)
++
++struct cv1800_clk_pll_synthesizer {
++      struct cv1800_clk_regbit        en;
++      struct cv1800_clk_regbit        clk_half;
++      u32                             ctrl;
++      u32                             set;
++};
++
++#define _PLL_PRE_DIV_SEL_FIELD                GENMASK(6, 0)
++#define _PLL_POST_DIV_SEL_FIELD               GENMASK(14, 8)
++#define _PLL_SEL_MODE_FIELD           GENMASK(16, 15)
++#define _PLL_DIV_SEL_FIELD            GENMASK(23, 17)
++#define _PLL_ICTRL_FIELD              GENMASK(26, 24)
++
++#define _PLL_ALL_FIELD_MASK \
++      (_PLL_PRE_DIV_SEL_FIELD | \
++       _PLL_POST_DIV_SEL_FIELD | \
++       _PLL_SEL_MODE_FIELD | \
++       _PLL_DIV_SEL_FIELD | \
++       _PLL_ICTRL_FIELD)
++
++#define PLL_COPY_REG(_dest, _src) \
++      (((_dest) & (~_PLL_ALL_FIELD_MASK)) | ((_src) & _PLL_ALL_FIELD_MASK))
++
++#define PLL_GET_PRE_DIV_SEL(_reg) \
++      FIELD_GET(_PLL_PRE_DIV_SEL_FIELD, (_reg))
++#define PLL_GET_POST_DIV_SEL(_reg) \
++      FIELD_GET(_PLL_POST_DIV_SEL_FIELD, (_reg))
++#define PLL_GET_SEL_MODE(_reg) \
++      FIELD_GET(_PLL_SEL_MODE_FIELD, (_reg))
++#define PLL_GET_DIV_SEL(_reg) \
++      FIELD_GET(_PLL_DIV_SEL_FIELD, (_reg))
++#define PLL_GET_ICTRL(_reg) \
++      FIELD_GET(_PLL_ICTRL_FIELD, (_reg))
++
++#define PLL_SET_PRE_DIV_SEL(_reg, _val) \
++      _CV1800_SET_FIELD((_reg), (_val), _PLL_PRE_DIV_SEL_FIELD)
++#define PLL_SET_POST_DIV_SEL(_reg, _val) \
++      _CV1800_SET_FIELD((_reg), (_val), _PLL_POST_DIV_SEL_FIELD)
++#define PLL_SET_SEL_MODE(_reg, _val) \
++      _CV1800_SET_FIELD((_reg), (_val), _PLL_SEL_MODE_FIELD)
++#define PLL_SET_DIV_SEL(_reg, _val) \
++      _CV1800_SET_FIELD((_reg), (_val), _PLL_DIV_SEL_FIELD)
++#define PLL_SET_ICTRL(_reg, _val) \
++      _CV1800_SET_FIELD((_reg), (_val), _PLL_ICTRL_FIELD)
++
++struct cv1800_clk_pll {
++      struct cv1800_clk_common                common;
++      u32                                     pll_reg;
++      struct cv1800_clk_regbit                pll_pwd;
++      struct cv1800_clk_regbit                pll_status;
++      const struct cv1800_clk_pll_limit       *pll_limit;
++      struct cv1800_clk_pll_synthesizer       *pll_syn;
++};
++
++#define CV1800_INTEGRAL_PLL(_name, _parent, _pll_reg,                 \
++                           _pll_pwd_reg, _pll_pwd_shift,              \
++                           _pll_status_reg, _pll_status_shift,        \
++                           _pll_limit, _flags)                        \
++      struct cv1800_clk_pll _name = {                                 \
++              .common         = CV1800_CLK_COMMON(#_name, _parent,    \
++                                                  &cv1800_clk_ipll_ops,\
++                                                  _flags),            \
++              .pll_reg        = _pll_reg,                             \
++              .pll_pwd        = CV1800_CLK_BIT(_pll_pwd_reg,          \
++                                             _pll_pwd_shift),         \
++              .pll_status     = CV1800_CLK_BIT(_pll_status_reg,       \
++                                             _pll_status_shift),      \
++              .pll_limit      = _pll_limit,                           \
++              .pll_syn        = NULL,                                 \
++      }
++
++#define CV1800_FACTIONAL_PLL(_name, _parent, _pll_reg,                        \
++                           _pll_pwd_reg, _pll_pwd_shift,              \
++                           _pll_status_reg, _pll_status_shift,        \
++                           _pll_limit, _pll_syn, _flags)              \
++      struct cv1800_clk_pll _name = {                                 \
++              .common         = CV1800_CLK_COMMON(#_name, _parent,    \
++                                                  &cv1800_clk_fpll_ops,\
++                                                  _flags),            \
++              .pll_reg        = _pll_reg,                             \
++              .pll_pwd        = CV1800_CLK_BIT(_pll_pwd_reg,          \
++                                             _pll_pwd_shift),         \
++              .pll_status     = CV1800_CLK_BIT(_pll_status_reg,       \
++                                             _pll_status_shift),      \
++              .pll_limit      = _pll_limit,                           \
++              .pll_syn        = _pll_syn,                             \
++      }
++
++extern const struct clk_ops cv1800_clk_ipll_ops;
++extern const struct clk_ops cv1800_clk_fpll_ops;
++
++#endif // _CLK_SOPHGO_CV1800_PLL_H_
+-- 
+2.20.1
+
diff --git a/target/linux/cv18x0/patches-6.6/0013-riscv-dts-sophgo-add-sdcard-support-for-milkv-duo.patch b/target/linux/cv18x0/patches-6.6/0013-riscv-dts-sophgo-add-sdcard-support-for-milkv-duo.patch
new file mode 100644 (file)
index 0000000..ed63c4b
--- /dev/null
@@ -0,0 +1,80 @@
+From 5ae34f760404f060bf2b3e6593f50e0b1d0a4d6b Mon Sep 17 00:00:00 2001
+From: Jisheng Zhang <jszhang@kernel.org>
+Date: Sat, 17 Feb 2024 22:48:26 +0800
+Subject: [PATCH 13/18] riscv: dts: sophgo: add sdcard support for milkv duo
+
+Add sdhci dt node in SoC dtsi and enable it in milkv duo dts.
+
+Signed-off-by: Jisheng Zhang <jszhang@kernel.org>
+
+Upstream-Status: Submitted [https://lore.kernel.org/linux-riscv/20240217144826.3944-1-jszhang@kernel.org/]
+---
+ .../riscv/boot/dts/sophgo/cv1800b-milkv-duo.dts |  9 +++++++++
+ arch/riscv/boot/dts/sophgo/cv18xx.dtsi          | 17 +++++++++++++++++
+ 2 files changed, 26 insertions(+)
+
+diff --git a/arch/riscv/boot/dts/sophgo/cv1800b-milkv-duo.dts b/arch/riscv/boot/dts/sophgo/cv1800b-milkv-duo.dts
+index 3af9e34b3bc7..6944f3c1c6c6 100644
+--- a/arch/riscv/boot/dts/sophgo/cv1800b-milkv-duo.dts
++++ b/arch/riscv/boot/dts/sophgo/cv1800b-milkv-duo.dts
+@@ -33,6 +33,15 @@
+       clock-frequency = <25000000>;
+ };
++&sdhci0 {
++      status = "okay";
++      bus-width = <4>;
++      disable-wp;
++      no-1-8-v;
++      no-mmc;
++      no-sdio;
++};
++
+ &uart0 {
+       status = "okay";
+ };
+diff --git a/arch/riscv/boot/dts/sophgo/cv18xx.dtsi b/arch/riscv/boot/dts/sophgo/cv18xx.dtsi
+index e375e9d9516e..c0a0ca437fec 100644
+--- a/arch/riscv/boot/dts/sophgo/cv18xx.dtsi
++++ b/arch/riscv/boot/dts/sophgo/cv18xx.dtsi
+@@ -4,6 +4,7 @@
+  * Copyright (C) 2023 Inochi Amaoto <inochiama@outlook.com>
+  */
++#include <dt-bindings/gpio/gpio.h>
+ #include <dt-bindings/interrupt-controller/irq.h>
+ #include <dt-bindings/clock/sophgo,cv1800.h>
+@@ -47,6 +48,13 @@
+               #clock-cells = <0>;
+       };
++      sdhci_clk: sdhci-clock {
++              compatible = "fixed-clock";
++              clock-frequency = <375000000>;
++              clock-output-names = "sdhci_clk";
++              #clock-cells = <0>;
++      };
++
+       soc {
+               compatible = "simple-bus";
+               interrupt-parent = <&plic>;
+@@ -188,6 +196,15 @@
+                       status = "disabled";
+               };
++              sdhci0: mmc@4310000 {
++                      compatible = "sophgo,cv1800b-dwcmshc";
++                      reg = <0x4310000 0x1000>;
++                      interrupts = <36 IRQ_TYPE_LEVEL_HIGH>;
++                      clocks = <&sdhci_clk>;
++                      clock-names = "core";
++                      status = "disabled";
++              };
++
+               plic: interrupt-controller@70000000 {
+                       reg = <0x70000000 0x4000000>;
+                       interrupts-extended = <&cpu0_intc 11>, <&cpu0_intc 9>;
+-- 
+2.20.1
+
diff --git a/target/linux/cv18x0/patches-6.6/0014-sophgo-add-reboot-shutdown-driver.patch b/target/linux/cv18x0/patches-6.6/0014-sophgo-add-reboot-shutdown-driver.patch
new file mode 100644 (file)
index 0000000..de4fe89
--- /dev/null
@@ -0,0 +1,174 @@
+From 3759b7030c46bcb98ed0a114e3d5790eeb95d96a Mon Sep 17 00:00:00 2001
+From: GP Orcullo <kinsamanka@gmail.com>
+Date: Sat, 4 Nov 2023 13:09:27 +0000
+Subject: [PATCH 14/18] sophgo: add reboot/shutdown driver
+
+extracted from OEM supplied sources
+
+Upstream-Status: Pending
+---
+ arch/riscv/boot/dts/sophgo/cv18xx.dtsi |   5 ++
+ drivers/power/reset/Kconfig            |   6 ++
+ drivers/power/reset/Makefile           |   1 +
+ drivers/power/reset/sophgo-reboot.c    | 108 +++++++++++++++++++++++++
+ 4 files changed, 120 insertions(+)
+ create mode 100644 drivers/power/reset/sophgo-reboot.c
+
+diff --git a/arch/riscv/boot/dts/sophgo/cv18xx.dtsi b/arch/riscv/boot/dts/sophgo/cv18xx.dtsi
+index c0a0ca437fec..efd8bbdbf1ca 100644
+--- a/arch/riscv/boot/dts/sophgo/cv18xx.dtsi
++++ b/arch/riscv/boot/dts/sophgo/cv18xx.dtsi
+@@ -218,5 +218,10 @@
+                       reg = <0x74000000 0x10000>;
+                       interrupts-extended = <&cpu0_intc 3>, <&cpu0_intc 7>;
+               };
++
++              restart: restart-controller@5025000 {
++                      compatible = "sophgo,restart";
++                      reg = <0x05025000 0x2000>;
++              };
+       };
+ };
+diff --git a/drivers/power/reset/Kconfig b/drivers/power/reset/Kconfig
+index 411e00b255d6..f4ae605da7c7 100644
+--- a/drivers/power/reset/Kconfig
++++ b/drivers/power/reset/Kconfig
+@@ -199,6 +199,12 @@ config POWER_RESET_RESTART
+         Instead they restart, and u-boot holds the SoC until the
+         user presses a key. u-boot then boots into Linux.
++config POWER_RESET_SOPHGO
++      bool "SOPHGO power-off driver"
++      depends on ARCH_SOPHGO
++      help
++        Power off and restart support for SOPHGO boards.
++
+ config POWER_RESET_ST
+       bool "ST restart driver"
+       depends on ARCH_STI
+diff --git a/drivers/power/reset/Makefile b/drivers/power/reset/Makefile
+index a95d1bd275d1..a65266f2e3f6 100644
+--- a/drivers/power/reset/Makefile
++++ b/drivers/power/reset/Makefile
+@@ -36,3 +36,4 @@ obj-$(CONFIG_SYSCON_REBOOT_MODE) += syscon-reboot-mode.o
+ obj-$(CONFIG_POWER_RESET_SC27XX) += sc27xx-poweroff.o
+ obj-$(CONFIG_NVMEM_REBOOT_MODE) += nvmem-reboot-mode.o
+ obj-$(CONFIG_POWER_MLXBF) += pwr-mlxbf.o
++obj-$(CONFIG_POWER_RESET_SOPHGO) += sophgo-reboot.o
+diff --git a/drivers/power/reset/sophgo-reboot.c b/drivers/power/reset/sophgo-reboot.c
+new file mode 100644
+index 000000000000..17b828a15272
+--- /dev/null
++++ b/drivers/power/reset/sophgo-reboot.c
+@@ -0,0 +1,108 @@
++// SPDX-License-Identifier: GPL-2.0-only
++
++#include <linux/delay.h>
++#include <linux/io.h>
++#include <linux/module.h>
++#include <linux/notifier.h>
++#include <linux/of_address.h>
++#include <linux/platform_device.h>
++#include <linux/reboot.h>
++
++#define RTC_CTRL0_UNLOCKKEY           0x4
++#define RTC_CTRL0                     0x8
++#define RTC_EN_SHDN_REQ                       0xC0
++#define RTC_EN_WARM_RST_REQ           0xCC
++#define RTC_EN_SUSPEND_REQ            0xE4
++#define RSM_STATE                     0xD4
++#define ST_ON                         0x3
++
++static void __iomem *base;
++
++static int sophgo_restart_handler(struct notifier_block *this,
++                              unsigned long mode, void *cmd)
++{
++      void __iomem *REG_RTC_CTRL_BASE = base;
++      void __iomem *REG_RTC_BASE = base + 0x1000;
++
++      /* Enable power suspend wakeup source mask */
++      writel(0x1, REG_RTC_BASE + 0x3C); // 1 = select prdata from 32K domain
++
++      writel(0xAB18, REG_RTC_CTRL_BASE + RTC_CTRL0_UNLOCKKEY);
++
++      writel(0x1, REG_RTC_BASE + RTC_EN_WARM_RST_REQ);
++
++      while (readl(REG_RTC_BASE + RTC_EN_WARM_RST_REQ) != 0x01)
++              ;
++
++      while (readl(REG_RTC_BASE + RSM_STATE) != ST_ON)
++              ;
++
++      writel(0xFFFF0800 | (0x1 << 4), REG_RTC_CTRL_BASE + RTC_CTRL0);
++
++      return NOTIFY_DONE;
++}
++
++static void sophgo_do_pwroff(void)
++{
++      void __iomem *REG_RTC_CTRL_BASE = base;
++      void __iomem *REG_RTC_BASE = base + 0x1000;
++
++      /* Enable power suspend wakeup source mask */
++      writel(0x1, REG_RTC_BASE + 0x3C); // 1 = select prdata from 32K domain
++
++      writel(0xAB18, REG_RTC_CTRL_BASE + RTC_CTRL0_UNLOCKKEY);
++
++      writel(0x1, REG_RTC_BASE + RTC_EN_SHDN_REQ);
++
++      while (readl(REG_RTC_BASE + RTC_EN_SHDN_REQ) != 0x01)
++              ;
++
++      writel(0xFFFF0800 | (0x1 << 0), REG_RTC_CTRL_BASE + RTC_CTRL0);
++
++      /* Wait some time until system down, otherwise, notice with a warn */
++      mdelay(1000);
++
++      WARN_ONCE(1, "Unable to power off system\n");
++}
++
++static struct notifier_block sophgo_restart_nb = {
++      .notifier_call = sophgo_restart_handler,
++      .priority = 128,
++};
++
++static int sophgo_reboot_probe(struct platform_device *pdev)
++{
++      struct device_node *np = pdev->dev.of_node;
++      int err;
++
++      base = of_iomap(np, 0);
++      if (!base) {
++              WARN(1, "failed to map base address");
++              return -ENODEV;
++      }
++
++      err = register_restart_handler(&sophgo_restart_nb);
++      if (err) {
++              dev_err(&pdev->dev, "cannot register restart handler (err=%d)\n",
++                      err);
++              iounmap(base);
++      }
++
++      pm_power_off = &sophgo_do_pwroff;
++
++      return err;
++}
++
++static const struct of_device_id sophgo_reboot_of_match[] = {
++      { .compatible = "sophgo,restart" },
++      {}
++};
++
++static struct platform_driver sophgo_reboot_driver = {
++      .probe = sophgo_reboot_probe,
++      .driver = {
++              .name = "sophgo-reboot",
++              .of_match_table = sophgo_reboot_of_match,
++      },
++};
++module_platform_driver(sophgo_reboot_driver);
+-- 
+2.20.1
+
diff --git a/target/linux/cv18x0/patches-6.6/0015-dt-bindings-reset-Add-binding-for-Sophgo-CV1800B-res.patch b/target/linux/cv18x0/patches-6.6/0015-dt-bindings-reset-Add-binding-for-Sophgo-CV1800B-res.patch
new file mode 100644 (file)
index 0000000..ddc24df
--- /dev/null
@@ -0,0 +1,166 @@
+From 05bd968ce9f19c79ade3be9bc81991c3c40c70df Mon Sep 17 00:00:00 2001
+From: Jisheng Zhang <jszhang@kernel.org>
+Date: Mon, 13 Nov 2023 08:55:00 +0800
+Subject: [PATCH 15/18] dt-bindings: reset: Add binding for Sophgo CV1800B
+ reset controller
+
+Add devicetree binding for Sophgo CV1800B SoC reset controller.
+
+Signed-off-by: Jisheng Zhang <jszhang@kernel.org>
+Reviewed-by: Conor Dooley <conor.dooley@microchip.com>
+---
+ .../bindings/reset/sophgo,cv1800b-reset.yaml  | 38 ++++++++
+ .../dt-bindings/reset/sophgo,cv1800b-reset.h  | 96 +++++++++++++++++++
+ 2 files changed, 134 insertions(+)
+ create mode 100644 Documentation/devicetree/bindings/reset/sophgo,cv1800b-reset.yaml
+ create mode 100644 include/dt-bindings/reset/sophgo,cv1800b-reset.h
+
+diff --git a/Documentation/devicetree/bindings/reset/sophgo,cv1800b-reset.yaml b/Documentation/devicetree/bindings/reset/sophgo,cv1800b-reset.yaml
+new file mode 100644
+index 000000000000..20a525147490
+--- /dev/null
++++ b/Documentation/devicetree/bindings/reset/sophgo,cv1800b-reset.yaml
+@@ -0,0 +1,38 @@
++# SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause
++%YAML 1.2
++---
++$id: http://devicetree.org/schemas/reset/sophgo,cv1800b-reset.yaml#
++$schema: http://devicetree.org/meta-schemas/core.yaml#
++
++title: Sophgo CV1800B SoC Reset Controller
++
++maintainers:
++  - Jisheng Zhang <jszhang@kernel.org>
++
++properties:
++  compatible:
++    enum:
++      - sophgo,cv1800b-reset
++
++  reg:
++    maxItems: 1
++
++  "#reset-cells":
++    const: 1
++
++required:
++  - compatible
++  - reg
++  - "#reset-cells"
++
++additionalProperties: false
++
++examples:
++  - |
++    reset-controller@3003000 {
++        compatible = "sophgo,cv1800b-reset";
++        reg = <0x03003000 0x1000>;
++        #reset-cells = <1>;
++    };
++
++...
+diff --git a/include/dt-bindings/reset/sophgo,cv1800b-reset.h b/include/dt-bindings/reset/sophgo,cv1800b-reset.h
+new file mode 100644
+index 000000000000..4ab9ede74ba3
+--- /dev/null
++++ b/include/dt-bindings/reset/sophgo,cv1800b-reset.h
+@@ -0,0 +1,96 @@
++/* SPDX-License-Identifier: GPL-2.0 OR MIT */
++/*
++ * Copyright (C) 2023 Sophgo Technology Inc. All rights reserved.
++ * Copyright (C) 2023 Jisheng Zhang <jszhang@kernel.org>
++ */
++
++#ifndef _DT_BINDINGS_CV1800B_RESET_H
++#define _DT_BINDINGS_CV1800B_RESET_H
++
++/*                            0-1     */
++#define RST_DDR                       2
++#define RST_H264C             3
++#define RST_JPEG              4
++#define RST_H265C             5
++#define RST_VIPSYS            6
++#define RST_TDMA              7
++#define RST_TPU                       8
++#define RST_TPUSYS            9
++/*                            10      */
++#define RST_USB                       11
++#define RST_ETH0              12
++/*                            13      */
++#define RST_NAND              14
++/*                            15      */
++#define RST_SD0                       16
++/*                            17      */
++#define RST_SDMA              18
++#define RST_I2S0              19
++#define RST_I2S1              20
++#define RST_I2S2              21
++#define RST_I2S3              22
++#define RST_UART0             23
++#define RST_UART1             24
++#define RST_UART2             25
++#define RST_UART3             26
++#define RST_I2C0              27
++#define RST_I2C1              28
++#define RST_I2C2              29
++#define RST_I2C3              30
++#define RST_I2C4              31
++#define RST_PWM0              32
++#define RST_PWM1              33
++#define RST_PWM2              34
++#define RST_PWM3              35
++/*                            36-39   */
++#define RST_SPI0              40
++#define RST_SPI1              41
++#define RST_SPI2              42
++#define RST_SPI3              43
++#define RST_GPIO0             44
++#define RST_GPIO1             45
++#define RST_GPIO2             46
++#define RST_EFUSE             47
++#define RST_WDT                       48
++#define RST_AHBRST_ROM                49
++#define RST_SPIC              50
++#define RST_TEMPSEN           51
++#define RST_SARADC            52
++/*                            53-57   */
++#define RST_COMBORST_PHY0     58
++/*                            59-60   */
++#define RST_SPIRST_NAND               61
++#define RST_SE                        62
++/*                            63-73   */
++#define RST_UART4             74
++#define RST_GPIO3             75
++#define RST_SYSTEM            76
++#define RST_TIMER             77
++#define RST_TIMER0            78
++#define RST_TIMER1            79
++#define RST_TIMER2            80
++#define RST_TIMER3            81
++#define RST_TIMER4            82
++#define RST_TIMER5            83
++#define RST_TIMER6            84
++#define RST_TIMER7            85
++#define RST_WGN0              86
++#define RST_WGN1              87
++#define RST_WGN2              88
++#define RST_KEYSCAN           89
++/*                            90      */
++#define RST_AUDDAC            91
++#define RST_AUDDACRST_APB     92
++#define RST_AUDADC            93
++/*                            94      */
++#define RST_VCSYS             95
++#define RST_ETHPHY            96
++#define RST_ETHPHYRST_APB     97
++#define RST_AUDSRC            98
++#define RST_VIP_CAM0          99
++#define RST_WDT1              100
++#define RST_WDT2              101
++/*                            102-292 */
++#define RST_CPUSYS1           293
++#define RST_CPUSYS2           294
++#endif
+-- 
+2.20.1
+
diff --git a/target/linux/cv18x0/patches-6.6/0016-reset-Add-reset-controller-support-for-Sophgo-CV1800.patch b/target/linux/cv18x0/patches-6.6/0016-reset-Add-reset-controller-support-for-Sophgo-CV1800.patch
new file mode 100644 (file)
index 0000000..bc7cdfa
--- /dev/null
@@ -0,0 +1,117 @@
+From c251dd18b0a101c7ea551b9a1634b41f22796bb2 Mon Sep 17 00:00:00 2001
+From: Jisheng Zhang <jszhang@kernel.org>
+Date: Mon, 13 Nov 2023 08:55:01 +0800
+Subject: [PATCH 16/18] reset: Add reset controller support for Sophgo CV1800B
+ SoC
+
+Add reset controller support for Sophgo CV1800B SoC reusing the
+reset-simple driver.
+
+Signed-off-by: Jisheng Zhang <jszhang@kernel.org>
+---
+ arch/riscv/boot/dts/sophgo/cv18xx.dtsi | 12 ++++++++++++
+ drivers/reset/Kconfig                  |  3 ++-
+ drivers/reset/reset-simple.c           |  2 ++
+ 3 files changed, 16 insertions(+), 1 deletion(-)
+
+diff --git a/arch/riscv/boot/dts/sophgo/cv18xx.dtsi b/arch/riscv/boot/dts/sophgo/cv18xx.dtsi
+index efd8bbdbf1ca..37c71808b048 100644
+--- a/arch/riscv/boot/dts/sophgo/cv18xx.dtsi
++++ b/arch/riscv/boot/dts/sophgo/cv18xx.dtsi
+@@ -7,6 +7,7 @@
+ #include <dt-bindings/gpio/gpio.h>
+ #include <dt-bindings/interrupt-controller/irq.h>
+ #include <dt-bindings/clock/sophgo,cv1800.h>
++#include <dt-bindings/reset/sophgo,cv1800b-reset.h>
+ / {
+       #address-cells = <1>;
+@@ -141,12 +142,19 @@
+                       };
+               };
++              rst: reset-controller@3003000 {
++                      compatible = "sophgo,cv1800b-reset";
++                      reg = <0x03003000 0x1000>;
++                      #reset-cells = <1>;
++              };
++
+               uart0: serial@4140000 {
+                       compatible = "snps,dw-apb-uart";
+                       reg = <0x04140000 0x100>;
+                       interrupts = <44 IRQ_TYPE_LEVEL_HIGH>;
+                       clocks = <&clk CLK_UART0>, <&clk CLK_APB_UART0>;
+                       clock-names = "baudclk", "apb_pclk";
++                      resets = <&rst RST_UART0>;
+                       reg-shift = <2>;
+                       reg-io-width = <4>;
+                       status = "disabled";
+@@ -158,6 +166,7 @@
+                       interrupts = <45 IRQ_TYPE_LEVEL_HIGH>;
+                       clocks = <&clk CLK_UART1>, <&clk CLK_APB_UART1>;
+                       clock-names = "baudclk", "apb_pclk";
++                      resets = <&rst RST_UART1>;
+                       reg-shift = <2>;
+                       reg-io-width = <4>;
+                       status = "disabled";
+@@ -169,6 +178,7 @@
+                       interrupts = <46 IRQ_TYPE_LEVEL_HIGH>;
+                       clocks = <&clk CLK_UART2>, <&clk CLK_APB_UART2>;
+                       clock-names = "baudclk", "apb_pclk";
++                      resets = <&rst RST_UART2>;
+                       reg-shift = <2>;
+                       reg-io-width = <4>;
+                       status = "disabled";
+@@ -180,6 +190,7 @@
+                       interrupts = <47 IRQ_TYPE_LEVEL_HIGH>;
+                       clocks = <&clk CLK_UART3>, <&clk CLK_APB_UART3>;
+                       clock-names = "baudclk", "apb_pclk";
++                      resets = <&rst RST_UART3>;
+                       reg-shift = <2>;
+                       reg-io-width = <4>;
+                       status = "disabled";
+@@ -191,6 +202,7 @@
+                       interrupts = <48 IRQ_TYPE_LEVEL_HIGH>;
+                       clocks = <&clk CLK_UART4>, <&clk CLK_APB_UART4>;
+                       clock-names = "baudclk", "apb_pclk";
++                      resets = <&rst RST_UART4>;
+                       reg-shift = <2>;
+                       reg-io-width = <4>;
+                       status = "disabled";
+diff --git a/drivers/reset/Kconfig b/drivers/reset/Kconfig
+index ccd59ddd7610..2034f69d5953 100644
+--- a/drivers/reset/Kconfig
++++ b/drivers/reset/Kconfig
+@@ -213,7 +213,7 @@ config RESET_SCMI
+ config RESET_SIMPLE
+       bool "Simple Reset Controller Driver" if COMPILE_TEST || EXPERT
+-      default ARCH_ASPEED || ARCH_BCMBCA || ARCH_BITMAIN || ARCH_REALTEK || ARCH_STM32 || (ARCH_INTEL_SOCFPGA && ARM64) || ARCH_SUNXI || ARC
++      default ARCH_ASPEED || ARCH_BCMBCA || ARCH_BITMAIN || ARCH_REALTEK || ARCH_SOPHGO || ARCH_STM32 || (ARCH_INTEL_SOCFPGA && ARM64) || ARCH_SUNXI || ARC
+       depends on HAS_IOMEM
+       help
+         This enables a simple reset controller driver for reset lines that
+@@ -228,6 +228,7 @@ config RESET_SIMPLE
+          - RCC reset controller in STM32 MCUs
+          - Allwinner SoCs
+          - SiFive FU740 SoCs
++         - Sophgo SoCs
+ config RESET_SOCFPGA
+       bool "SoCFPGA Reset Driver" if COMPILE_TEST && (!ARM || !ARCH_INTEL_SOCFPGA)
+diff --git a/drivers/reset/reset-simple.c b/drivers/reset/reset-simple.c
+index 7ea5adbf2097..573753ae3e08 100644
+--- a/drivers/reset/reset-simple.c
++++ b/drivers/reset/reset-simple.c
+@@ -151,6 +151,8 @@ static const struct of_device_id reset_simple_dt_ids[] = {
+       { .compatible = "snps,dw-high-reset" },
+       { .compatible = "snps,dw-low-reset",
+               .data = &reset_simple_active_low },
++      { .compatible = "sophgo,cv1800b-reset",
++              .data = &reset_simple_active_low },
+       { /* sentinel */ },
+ };
+-- 
+2.20.1
+
diff --git a/target/linux/cv18x0/patches-6.6/0017-riscv-dts-sophgo-add-watchdog-dt-node-for-CV1800.patch b/target/linux/cv18x0/patches-6.6/0017-riscv-dts-sophgo-add-watchdog-dt-node-for-CV1800.patch
new file mode 100644 (file)
index 0000000..e7ace82
--- /dev/null
@@ -0,0 +1,58 @@
+From 945c22abfac4989df3e7d46f773a75518a61cdef Mon Sep 17 00:00:00 2001
+From: AnnanLiu <annan.liu.xdu@outlook.com>
+Date: Thu, 28 Dec 2023 21:08:17 +0800
+Subject: [PATCH 17/18] riscv: dts: sophgo: add watchdog dt node for CV1800
+
+Add the watchdog device tree node to cv1800 SoC.
+This patch depends on the clk driver and reset driver.
+Clk driver link:
+https://lore.kernel.org/all/IA1PR20MB49539CDAD9A268CBF6CA184BBB9FA@IA1PR20MB4953.namprd20.prod.outlook.com/
+Reset driver link:
+https://lore.kernel.org/all/20231113005503.2423-1-jszhang@kernel.org/
+
+Signed-off-by: AnnanLiu <annan.liu.xdu@outlook.com>
+---
+ arch/riscv/boot/dts/sophgo/cv1800b-milkv-duo.dts |  4 ++++
+ arch/riscv/boot/dts/sophgo/cv18xx.dtsi           | 14 ++++++++++++++
+ 2 files changed, 18 insertions(+)
+
+diff --git a/arch/riscv/boot/dts/sophgo/cv1800b-milkv-duo.dts b/arch/riscv/boot/dts/sophgo/cv1800b-milkv-duo.dts
+index 6944f3c1c6c6..22c3b5be0739 100644
+--- a/arch/riscv/boot/dts/sophgo/cv1800b-milkv-duo.dts
++++ b/arch/riscv/boot/dts/sophgo/cv1800b-milkv-duo.dts
+@@ -45,3 +45,7 @@
+ &uart0 {
+       status = "okay";
+ };
++
++&watchdog0 {
++      status = "okay";
++};
+diff --git a/arch/riscv/boot/dts/sophgo/cv18xx.dtsi b/arch/riscv/boot/dts/sophgo/cv18xx.dtsi
+index 37c71808b048..82e828721df7 100644
+--- a/arch/riscv/boot/dts/sophgo/cv18xx.dtsi
++++ b/arch/riscv/boot/dts/sophgo/cv18xx.dtsi
+@@ -226,6 +226,20 @@
+                       riscv,ndev = <101>;
+               };
++              watchdog0: watchdog@3010000{
++                      compatible = "snps,dw-wdt";
++                      reg = <0x3010000 0x100>;
++                      interrupts = <58 IRQ_TYPE_LEVEL_HIGH>;
++                      clocks = <&pclk>;
++                      resets = <&rst RST_WDT>;
++              };
++
++              pclk: pclk {
++                      #clock-cells = <0>;
++                      compatible = "fixed-clock";
++                      clock-frequency = <25000000>;
++              };
++
+               clint: timer@74000000 {
+                       reg = <0x74000000 0x10000>;
+                       interrupts-extended = <&cpu0_intc 3>, <&cpu0_intc 7>;
+-- 
+2.20.1
+
diff --git a/target/linux/cv18x0/patches-6.6/0018-riscv-dts-sophgo-add-timer-dt-node-for-CV1800.patch b/target/linux/cv18x0/patches-6.6/0018-riscv-dts-sophgo-add-timer-dt-node-for-CV1800.patch
new file mode 100644 (file)
index 0000000..d3ebeed
--- /dev/null
@@ -0,0 +1,103 @@
+From 6f1f2e3823dc0e4a9960c76792eea1d0a43c3f66 Mon Sep 17 00:00:00 2001
+From: AnnanLiu <annan.liu.xdu@outlook.com>
+Date: Thu, 28 Dec 2023 21:06:54 +0800
+Subject: [PATCH 18/18] riscv: dts: sophgo: add timer dt node for CV1800
+
+Add the timer device tree node to CV1800 SoC.
+This patch depends on the clk driver and reset driver.
+Clk driver link:
+https://lore.kernel.org/all/IA1PR20MB49539CDAD9A268CBF6CA184BBB9FA@IA1PR20MB4953.namprd20.prod.outlook.com/
+Reset driver link:
+https://lore.kernel.org/all/20231113005503.2423-1-jszhang@kernel.org/
+
+Signed-off-by: AnnanLiu <annan.liu.xdu@outlook.com>
+---
+ arch/riscv/boot/dts/sophgo/cv18xx.dtsi | 72 ++++++++++++++++++++++++++
+ 1 file changed, 72 insertions(+)
+
+diff --git a/arch/riscv/boot/dts/sophgo/cv18xx.dtsi b/arch/riscv/boot/dts/sophgo/cv18xx.dtsi
+index 82e828721df7..e87df337ec68 100644
+--- a/arch/riscv/boot/dts/sophgo/cv18xx.dtsi
++++ b/arch/riscv/boot/dts/sophgo/cv18xx.dtsi
+@@ -240,6 +240,78 @@
+                       clock-frequency = <25000000>;
+               };
++              timer0: timer@030a0000 {
++                      compatible = "snps,dw-apb-timer";
++                      reg = <0x030a0000 0x14>;
++                      interrupts = <79 IRQ_TYPE_LEVEL_HIGH>;
++                      clocks = <&osc>;
++                      resets = <&rst RST_TIMER0>;
++                      status = "okay";
++              };
++
++              timer1: timer@030a0014 {
++                      compatible = "snps,dw-apb-timer";
++                      reg = <0x030a0014 0x14>;
++                      interrupts = <80 IRQ_TYPE_LEVEL_HIGH>;
++                      clocks = <&osc>;
++                      resets = <&rst RST_TIMER1>;
++                      status = "okay";
++              };
++
++              timer2: timer@030a0028 {
++                      compatible = "snps,dw-apb-timer";
++                      reg = <0x030a0028 0x14>;
++                      interrupts = <81 IRQ_TYPE_LEVEL_HIGH>;
++                      clocks = <&osc>;
++                      resets = <&rst RST_TIMER2>;
++                      status = "okay";
++              };
++
++              timer3: timer@030a003c {
++                      compatible = "snps,dw-apb-timer";
++                      reg = <0x030a003c 0x14>;
++                      interrupts = <82 IRQ_TYPE_LEVEL_HIGH>;
++                      clocks = <&osc>;
++                      resets = <&rst RST_TIMER3>;
++                      status = "okay";
++              };
++
++              timer4: timer@030a0050 {
++                      compatible = "snps,dw-apb-timer";
++                      reg = <0x030a0050 0x14>;
++                      interrupts = <83 IRQ_TYPE_LEVEL_HIGH>;
++                      clocks = <&osc>;
++                      resets = <&rst RST_TIMER4>;
++                      status = "okay";
++              };
++
++              timer5: timer@30a0064 {
++                      compatible = "snps,dw-apb-timer";
++                      reg = <0x030a0064 0x14>;
++                      interrupts = <84 IRQ_TYPE_LEVEL_HIGH>;
++                      clocks = <&osc>;
++                      resets = <&rst RST_TIMER5>;
++                      status = "okay";
++              };
++
++              timer6: timer@030a0078 {
++                      compatible = "snps,dw-apb-timer";
++                      reg = <0x030a0078 0x14>;
++                      interrupts = <85 IRQ_TYPE_LEVEL_HIGH>;
++                      clocks = <&osc>;
++                      resets = <&rst RST_TIMER6>;
++                      status = "okay";
++              };
++
++              timer7: timer@030a008c {
++                      compatible = "snps,dw-apb-timer";
++                      reg = <0x030a008c 0x14>;
++                      interrupts = <86 IRQ_TYPE_LEVEL_HIGH>;
++                      clocks = <&osc>;
++                      resets = <&rst RST_TIMER7>;
++                      status = "okay";
++              };
++
+               clint: timer@74000000 {
+                       reg = <0x74000000 0x10000>;
+                       interrupts-extended = <&cpu0_intc 3>, <&cpu0_intc 7>;
+-- 
+2.20.1
+
diff --git a/target/linux/cv18x0/patches-6.6/0019-mmc-sdhci-of-dwcmshc-Add-tuning-support-for-Sophgo-C.patch b/target/linux/cv18x0/patches-6.6/0019-mmc-sdhci-of-dwcmshc-Add-tuning-support-for-Sophgo-C.patch
new file mode 100644 (file)
index 0000000..1fbb725
--- /dev/null
@@ -0,0 +1,158 @@
+From 295e4c305fb59d994970c94f11d7d8d524557693 Mon Sep 17 00:00:00 2001
+From: Jisheng Zhang <jszhang@kernel.org>
+Date: Sat, 20 Apr 2024 10:14:29 +0800
+Subject: [PATCH 19/19] mmc: sdhci-of-dwcmshc: Add tuning support for Sophgo
+ CV1800B and SG200X
+
+Implement the .platform_execute_tuning for Sophgo CV1800B and SG200X.
+Some code is borrowed from sdhci-esdhc-imx.c. The tuning result is
+similar as the one of SoC vendor's SDK.
+
+Signed-off-by: Jisheng Zhang <jszhang@kernel.org>
+Acked-by: Adrian Hunter <adrian.hunter@intel.com>
+Link: https://lore.kernel.org/r/20240420021429.454-1-jszhang@kernel.org
+Signed-off-by: Ulf Hansson <ulf.hansson@linaro.org>
+---
+ drivers/mmc/host/sdhci-of-dwcmshc.c | 112 ++++++++++++++++++++++++++++
+ 1 file changed, 112 insertions(+)
+
+diff --git a/drivers/mmc/host/sdhci-of-dwcmshc.c b/drivers/mmc/host/sdhci-of-dwcmshc.c
+index e473af22e585..54ebb59c3fab 100644
+--- a/drivers/mmc/host/sdhci-of-dwcmshc.c
++++ b/drivers/mmc/host/sdhci-of-dwcmshc.c
+@@ -51,6 +51,10 @@
+ #define CV18XX_SDHCI_PHY_CONFIG                       0x4c
+ #define  CV18XX_PHY_TX_BPS                    BIT(0)
++#define CV18XX_TUNE_MAX                               128
++#define CV18XX_TUNE_STEP                      1
++#define CV18XX_RETRY_TUNING_MAX                       50
++
+ /* Rockchip specific Registers */
+ #define DWCMSHC_EMMC_DLL_CTRL         0x800
+ #define DWCMSHC_EMMC_DLL_RXCLK                0x804
+@@ -382,6 +386,113 @@ static void cv18xx_sdhci_reset(struct sdhci_host *host, u8 mask)
+       sdhci_writel(host, val, priv->vendor_specific_area1 + CV18XX_SDHCI_PHY_TX_RX_DLY);
+ }
++static void cv18xx_sdhci_set_tap(struct sdhci_host *host, int tap)
++{
++      struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
++      struct dwcmshc_priv *priv = sdhci_pltfm_priv(pltfm_host);
++      u16 clk;
++      u32 val;
++
++      clk = sdhci_readw(host, SDHCI_CLOCK_CONTROL);
++      clk &= ~SDHCI_CLOCK_CARD_EN;
++      sdhci_writew(host, clk, SDHCI_CLOCK_CONTROL);
++
++      val = sdhci_readl(host, priv->vendor_specific_area1 + CV18XX_SDHCI_MSHC_CTRL);
++      val &= ~CV18XX_LATANCY_1T;
++      sdhci_writel(host, val, priv->vendor_specific_area1 + CV18XX_SDHCI_MSHC_CTRL);
++
++      val =  (FIELD_PREP(CV18XX_PHY_TX_DLY_MSK, 0) |
++              FIELD_PREP(CV18XX_PHY_TX_SRC_MSK, CV18XX_PHY_TX_SRC_INVERT_CLK_TX) |
++              FIELD_PREP(CV18XX_PHY_RX_DLY_MSK, tap));
++      sdhci_writel(host, val, priv->vendor_specific_area1 + CV18XX_SDHCI_PHY_TX_RX_DLY);
++
++      sdhci_writel(host, 0, priv->vendor_specific_area1 + CV18XX_SDHCI_PHY_CONFIG);
++
++      clk |= SDHCI_CLOCK_CARD_EN;
++      sdhci_writew(host, clk, SDHCI_CLOCK_CONTROL);
++      usleep_range(1000, 2000);
++}
++
++static int cv18xx_retry_tuning(struct mmc_host *mmc, u32 opcode, int *cmd_error)
++{
++      int ret, retry = 0;
++
++      while (retry < CV18XX_RETRY_TUNING_MAX) {
++              ret = mmc_send_tuning(mmc, opcode, NULL);
++              if (ret)
++                      return ret;
++              retry++;
++      }
++
++      return 0;
++}
++
++static void cv18xx_sdhci_post_tuning(struct sdhci_host *host)
++{
++      u32 val;
++
++      val = sdhci_readl(host, SDHCI_INT_STATUS);
++      val |= SDHCI_INT_DATA_AVAIL;
++      sdhci_writel(host, val, SDHCI_INT_STATUS);
++
++      sdhci_reset(host, SDHCI_RESET_CMD | SDHCI_RESET_DATA);
++}
++
++static int cv18xx_sdhci_execute_tuning(struct sdhci_host *host, u32 opcode)
++{
++      int min, max, avg, ret;
++      int win_length, target_min, target_max, target_win_length;
++
++      min = max = 0;
++      target_win_length = 0;
++
++      sdhci_reset_tuning(host);
++
++      while (max < CV18XX_TUNE_MAX) {
++              /* find the mininum delay first which can pass tuning */
++              while (min < CV18XX_TUNE_MAX) {
++                      cv18xx_sdhci_set_tap(host, min);
++                      if (!cv18xx_retry_tuning(host->mmc, opcode, NULL))
++                              break;
++                      min += CV18XX_TUNE_STEP;
++              }
++
++              /* find the maxinum delay which can not pass tuning */
++              max = min + CV18XX_TUNE_STEP;
++              while (max < CV18XX_TUNE_MAX) {
++                      cv18xx_sdhci_set_tap(host, max);
++                      if (cv18xx_retry_tuning(host->mmc, opcode, NULL)) {
++                              max -= CV18XX_TUNE_STEP;
++                              break;
++                      }
++                      max += CV18XX_TUNE_STEP;
++              }
++
++              win_length = max - min + 1;
++              /* get the largest pass window */
++              if (win_length > target_win_length) {
++                      target_win_length = win_length;
++                      target_min = min;
++                      target_max = max;
++              }
++
++              /* continue to find the next pass window */
++              min = max + CV18XX_TUNE_STEP;
++      }
++
++      cv18xx_sdhci_post_tuning(host);
++
++      /* use average delay to get the best timing */
++      avg = (target_min + target_max) / 2;
++      cv18xx_sdhci_set_tap(host, avg);
++      ret = mmc_send_tuning(host->mmc, opcode, NULL);
++
++      dev_dbg(mmc_dev(host->mmc), "tuning %s at 0x%x ret %d\n",
++              ret ? "failed" : "passed", avg, ret);
++
++      return ret;
++}
++
+ static const struct sdhci_ops sdhci_dwcmshc_ops = {
+       .set_clock              = sdhci_set_clock,
+       .set_bus_width          = sdhci_set_bus_width,
+@@ -407,6 +518,7 @@ static const struct sdhci_ops sdhci_dwcmshc_cv18xx_ops = {
+       .get_max_clock          = dwcmshc_get_max_clock,
+       .reset                  = cv18xx_sdhci_reset,
+       .adma_write_desc        = dwcmshc_adma_write_desc,
++      .platform_execute_tuning = cv18xx_sdhci_execute_tuning,
+ };
+ static const struct sdhci_pltfm_data sdhci_dwcmshc_pdata = {
+-- 
+2.20.1
+
diff --git a/target/linux/cv18x0/patches-6.6/0020-riscv-dts-sophgo-use-real-clock-for-sdhci.patch b/target/linux/cv18x0/patches-6.6/0020-riscv-dts-sophgo-use-real-clock-for-sdhci.patch
new file mode 100644 (file)
index 0000000..6f59e96
--- /dev/null
@@ -0,0 +1,48 @@
+From 72218d886b6719110e2b07be648ca702e696d1d6 Mon Sep 17 00:00:00 2001
+From: Inochi Amaoto <inochiama@outlook.com>
+Date: Thu, 11 Apr 2024 20:21:35 +0800
+Subject: [PATCH 20/20] riscv: dts: sophgo: use real clock for sdhci
+
+As the clk patch is merged, Use real clocks for sdhci0.
+
+Reviewed-by: Chen Wang <unicorn_wang@outlook.com>
+Link: https://lore.kernel.org/r/IA1PR20MB4953CA5D46EA8913B130D502BB052@IA1PR20MB4953.namprd20.prod.outlook.com
+Signed-off-by: Inochi Amaoto <inochiama@outlook.com>
+Signed-off-by: Chen Wang <unicorn_wang@outlook.com>
+---
+ arch/riscv/boot/dts/sophgo/cv18xx.dtsi | 12 +++---------
+ 1 file changed, 3 insertions(+), 9 deletions(-)
+
+diff --git a/arch/riscv/boot/dts/sophgo/cv18xx.dtsi b/arch/riscv/boot/dts/sophgo/cv18xx.dtsi
+index e87df337ec68..786a31617eca 100644
+--- a/arch/riscv/boot/dts/sophgo/cv18xx.dtsi
++++ b/arch/riscv/boot/dts/sophgo/cv18xx.dtsi
+@@ -49,13 +49,6 @@
+               #clock-cells = <0>;
+       };
+-      sdhci_clk: sdhci-clock {
+-              compatible = "fixed-clock";
+-              clock-frequency = <375000000>;
+-              clock-output-names = "sdhci_clk";
+-              #clock-cells = <0>;
+-      };
+-
+       soc {
+               compatible = "simple-bus";
+               interrupt-parent = <&plic>;
+@@ -212,8 +205,9 @@
+                       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";
+               };
+-- 
+2.20.1
+