Переглянути джерело

starfive: add new target for StarFive JH7100/7110 SoC

This target adds support for the StarFive JH7100 and JH7110 SoCs, based on
6.1, as well as a couple boards equipped with these.

Specifications:

SoCs:

JH7100:
 - StarFive JH7100 dual-core RISC-V (U74, RC64GC)
 - additional monitoring (S7) and control (E24) cores
 - 2Mb L2 cache

JH7110:
 - StarFive JH7110 quad-core RISC-V (U74, RV64GC)
 - additional monitoring (S7) and control (E24) cores
 - 2Mb L2 cache

Boards:

VisionFive1:
 - JH7100 @ 1GHz
 - Memory: 8Gb LPDDR4
 - 4x USB3.0
 - 1x GBit ethernet
 - AMPak 6236 wifi / bluetooth
 - audio
 - powered via USB-C

VisionFive2:
 - JH7110 @ 1.5GHz
 - Memory: 2/4/8Gb DDR4
 - 2x Gbit ethernet
 - 2x USB3.0 / 2x USB2.0
 - eMMC / SDIO
 - various multimedia input/outputs (MIPI CSI, HDMI, audio)
 - M.2 key M slot
 - PoE support
 - powered via USB-C

Installation:
Standard SD-card installation via dd-ing the generated image to
an SD-card of at least 256Mb.

Signed-off-by: Zoltan HERPAI <[email protected]>
Zoltan HERPAI 2 роки тому
батько
коміт
4070e2a64c
100 змінених файлів з 24612 додано та 0 видалено
  1. 21 0
      target/linux/starfive/Makefile
  2. 22 0
      target/linux/starfive/base-files/etc/board.d/02_network
  3. 4 0
      target/linux/starfive/base-files/etc/inittab
  4. 53 0
      target/linux/starfive/base-files/lib/firmware/brcm/brcmfmac43430-sdio.txt
  5. 1 0
      target/linux/starfive/base-files/lib/firmware/brcm/brcmfmac43430a0-sdio.txt
  6. 555 0
      target/linux/starfive/config-6.1
  7. 1 0
      target/linux/starfive/generic/target.mk
  8. 5 0
      target/linux/starfive/image/Config.in
  9. 85 0
      target/linux/starfive/image/Makefile
  10. 24 0
      target/linux/starfive/image/gen_starfive_sdcard_img.sh
  11. 4 0
      target/linux/starfive/image/mmc.bootscript.jh7100
  12. 5 0
      target/linux/starfive/image/mmc.bootscript.jh7110
  13. 31 0
      target/linux/starfive/modules.mk
  14. 482 0
      target/linux/starfive/patches-6.1/0001-dt-bindings-clock-Add-StarFive-JH7110-system-clock-a.patch
  15. 176 0
      target/linux/starfive/patches-6.1/0002-dt-bindings-clock-Add-StarFive-JH7110-always-on-cloc.patch
  16. 53 0
      target/linux/starfive/patches-6.1/0003-clk-starfive-Replace-SOC_STARFIVE-with-ARCH_STARFIVE.patch
  17. 749 0
      target/linux/starfive/patches-6.1/0004-clk-starfive-Factor-out-common-JH7100-and-JH7110-cod.patch
  18. 290 0
      target/linux/starfive/patches-6.1/0005-clk-starfive-Rename-clk-starfive-jh7100.h-to-clk-sta.patch
  19. 1249 0
      target/linux/starfive/patches-6.1/0006-clk-starfive-Rename-jh7100-to-jh71x0-for-the-common-.patch
  20. 30 0
      target/linux/starfive/patches-6.1/0007-reset-starfive-Replace-SOC_STARFIVE-with-ARCH_STARFI.patch
  21. 436 0
      target/linux/starfive/patches-6.1/0008-reset-Create-subdirectory-for-StarFive-drivers.patch
  22. 390 0
      target/linux/starfive/patches-6.1/0009-reset-starfive-Factor-out-common-JH71X0-reset-code.patch
  23. 215 0
      target/linux/starfive/patches-6.1/0010-reset-starfive-Extract-the-common-JH71X0-reset-code.patch
  24. 167 0
      target/linux/starfive/patches-6.1/0011-reset-starfive-Rename-jh7100-to-jh71x0-for-the-commo.patch
  25. 146 0
      target/linux/starfive/patches-6.1/0012-reset-starfive-jh71x0-Use-32bit-I-O-on-32bit-registe.patch
  26. 557 0
      target/linux/starfive/patches-6.1/0013-clk-starfive-Add-StarFive-JH7110-system-clock-driver.patch
  27. 206 0
      target/linux/starfive/patches-6.1/0014-clk-starfive-Add-StarFive-JH7110-always-on-clock-dri.patch
  28. 113 0
      target/linux/starfive/patches-6.1/0015-reset-starfive-Add-StarFive-JH7110-reset-driver.patch
  29. 50 0
      target/linux/starfive/patches-6.1/0016-MAINTAINERS-generalise-StarFive-clk-reset-entries.patch
  30. 128 0
      target/linux/starfive/patches-6.1/0017-clk-starfive-Avoid-casting-iomem-pointers.patch
  31. 27 0
      target/linux/starfive/patches-6.1/0018-dt-bindings-timer-Add-StarFive-JH7110-clint.patch
  32. 28 0
      target/linux/starfive/patches-6.1/0019-dt-bindings-interrupt-controller-Add-StarFive-JH7110.patch
  33. 27 0
      target/linux/starfive/patches-6.1/0020-dt-bindings-riscv-Add-SiFive-S7-compatible.patch
  34. 549 0
      target/linux/starfive/patches-6.1/0021-riscv-dts-starfive-Add-initial-StarFive-JH7110-devic.patch
  35. 331 0
      target/linux/starfive/patches-6.1/0022-riscv-dts-starfive-Add-StarFive-JH7110-pin-function-.patch
  36. 290 0
      target/linux/starfive/patches-6.1/0023-riscv-dts-starfive-Add-StarFive-JH7110-VisionFive-2-.patch
  37. 43 0
      target/linux/starfive/patches-6.1/0024-riscv-dts-starfive-Add-StarFive-VisionFive-V1-device.patch
  38. 349 0
      target/linux/starfive/patches-6.1/0025-riscv-dts-starfive-Add-common-DT-for-JH7100-based-bo.patch
  39. 303 0
      target/linux/starfive/patches-6.1/0026-dt-bindings-pinctrl-Add-StarFive-JH7110-sys-pinctrl.patch
  40. 176 0
      target/linux/starfive/patches-6.1/0027-dt-bindings-pinctrl-Add-StarFive-JH7110-aon-pinctrl.patch
  41. 1581 0
      target/linux/starfive/patches-6.1/0028-pinctrl-starfive-Add-StarFive-JH7110-sys-controller-.patch
  42. 224 0
      target/linux/starfive/patches-6.1/0029-pinctrl-starfive-Add-StarFive-JH7110-aon-controller-.patch
  43. 228 0
      target/linux/starfive/patches-6.1/0030-config-add-jh7110-defconfig-for-test-mini.patch
  44. 80 0
      target/linux/starfive/patches-6.1/0031-dt-bindings-clock-Add-StarFive-JH7110-PLL-clock-gene.patch
  45. 786 0
      target/linux/starfive/patches-6.1/0032-clk-starfive-Add-StarFive-JH7110-PLL-clock-driver.patch
  46. 75 0
      target/linux/starfive/patches-6.1/0033-dt-bindings-clock-jh7110-syscrg-Add-PLL-clock-inputs.patch
  47. 71 0
      target/linux/starfive/patches-6.1/0034-clk-starfive-jh7110-sys-Modify-PLL-clocks-source.patch
  48. 86 0
      target/linux/starfive/patches-6.1/0035-dt-bindings-power-Add-starfive-jh7110-pmu.patch
  49. 478 0
      target/linux/starfive/patches-6.1/0036-soc-starfive-Add-StarFive-JH71XX-pmu-driver.patch
  50. 98 0
      target/linux/starfive/patches-6.1/0037-dt-bindings-soc-starfive-Add-StarFive-syscon-module.patch
  51. 52 0
      target/linux/starfive/patches-6.1/0038-riscv-dts-starfive-jh7110-Add-syscon-nodes.patch
  52. 48 0
      target/linux/starfive/patches-6.1/0039-riscv-dts-starfive-jh7110-Add-PLL-clock-node-and-mod.patch
  53. 49 0
      target/linux/starfive/patches-6.1/0040-dt-bindings-net-snps-dwmac-Add-dwmac-5.20-version.patch
  54. 29 0
      target/linux/starfive/patches-6.1/0041-net-stmmac-platform-Add-snps-dwmac-5.20-IP-compatibl.patch
  55. 46 0
      target/linux/starfive/patches-6.1/0042-dt-bindings-net-snps-dwmac-Add-ahb-reset-reset-name.patch
  56. 190 0
      target/linux/starfive/patches-6.1/0043-dt-bindings-net-Add-support-StarFive-dwmac.patch
  57. 187 0
      target/linux/starfive/patches-6.1/0044-net-stmmac-Add-glue-layer-for-StarFive-JH7110-SoC.patch
  58. 93 0
      target/linux/starfive/patches-6.1/0045-net-stmmac-dwmac-starfive-Add-phy-interface-settings.patch
  59. 101 0
      target/linux/starfive/patches-6.1/0046-riscv-dts-starfive-jh7110-Add-ethernet-device-nodes.patch
  60. 128 0
      target/linux/starfive/patches-6.1/0047-riscv-dts-starfive-visionfive-2-Add-configuration-of.patch
  61. 147 0
      target/linux/starfive/patches-6.1/0048-dt-bindings-net-Add-Motorcomm-yt8xxx-ethernet-phy.patch
  62. 34 0
      target/linux/starfive/patches-6.1/0049-dt-bindings-net-motorcomm-Add-pad-driver-strength-cf.patch
  63. 34 0
      target/linux/starfive/patches-6.1/0050-riscv-dts-starfive-visionfive-2-v1.3B-Set-the-driver.patch
  64. 193 0
      target/linux/starfive/patches-6.1/0051-dt-bindings-clock-Add-StarFive-JH7110-System-Top-Gro.patch
  65. 218 0
      target/linux/starfive/patches-6.1/0052-clk-starfive-Add-StarFive-JH7110-System-Top-Group-cl.patch
  66. 156 0
      target/linux/starfive/patches-6.1/0053-dt-bindings-clock-Add-StarFive-JH7110-Image-Signal-P.patch
  67. 293 0
      target/linux/starfive/patches-6.1/0054-clk-starfive-Add-StarFive-JH7110-Image-Signal-Proces.patch
  68. 163 0
      target/linux/starfive/patches-6.1/0055-dt-bindings-clock-Add-StarFive-JH7110-Video-Output-c.patch
  69. 284 0
      target/linux/starfive/patches-6.1/0056-clk-starfive-Add-StarFive-JH7110-Video-Output-clock-.patch
  70. 61 0
      target/linux/starfive/patches-6.1/0057-reset-starfive-jh7110-Add-StarFive-STG-ISP-VOUT-rese.patch
  71. 819 0
      target/linux/starfive/patches-6.1/0058-clk-starfive-update-jh7110-PLL-clock-driver.patch
  72. 113 0
      target/linux/starfive/patches-6.1/0059-dt-bindings-timer-Add-timer-for-StarFive-JH7110-SoC.patch
  73. 540 0
      target/linux/starfive/patches-6.1/0060-clocksource-Add-StarFive-timer-driver.patch
  74. 36 0
      target/linux/starfive/patches-6.1/0061-dt-bindings-net-motorcomm-Add-pad-driver-strength-cf.patch
  75. 71 0
      target/linux/starfive/patches-6.1/0062-dt-bindings-PWM-Add-StarFive-PWM-module.patch
  76. 294 0
      target/linux/starfive/patches-6.1/0063-pwm-starfive-Add-PWM-driver-support.patch
  77. 90 0
      target/linux/starfive/patches-6.1/0064-dt-bindings-crypto-Add-StarFive-crypto-module.patch
  78. 337 0
      target/linux/starfive/patches-6.1/0065-crypto-starfive-Add-crypto-engine-support.patch
  79. 29 0
      target/linux/starfive/patches-6.1/0066-crypto-starfive-Fix-driver-dependencies.patch
  80. 23 0
      target/linux/starfive/patches-6.1/0067-riscv-Kconfig-Add-select-ARM_AMBA-to-SOC_STARFIVE.patch
  81. 117 0
      target/linux/starfive/patches-6.1/0068-ASoC-dt-bindings-Add-TDM-controller-bindings-for-Sta.patch
  82. 744 0
      target/linux/starfive/patches-6.1/0069-ASoC-starfive-Add-JH7110-TDM-driver.patch
  83. 32 0
      target/linux/starfive/patches-6.1/0070-dt-bindings-power-Add-power-domain-header-for-JH7110.patch
  84. 28 0
      target/linux/starfive/patches-6.1/0071-soc-starfive-Replace-SOC_STARFIVE-with-ARCH_STARFIVE.patch
  85. 175 0
      target/linux/starfive/patches-6.1/0072-soc-starfive-Extract-JH7110-pmu-private-operations.patch
  86. 119 0
      target/linux/starfive/patches-6.1/0073-soc-starfive-Add-JH7110-AON-PMU-support.patch
  87. 88 0
      target/linux/starfive/patches-6.1/0074-dt-bindings-phy-Add-starfive-jh7110-dphy-rx.patch
  88. 365 0
      target/linux/starfive/patches-6.1/0075-phy-starfive-Add-mipi-dphy-rx-support.patch
  89. 306 0
      target/linux/starfive/patches-6.1/0076-media-dt-bindings-cadence-csi2rx-Convert-to-DT-schem.patch
  90. 55 0
      target/linux/starfive/patches-6.1/0077-media-dt-bindings-cadence-csi2rx-Add-resets-property.patch
  91. 129 0
      target/linux/starfive/patches-6.1/0078-media-cadence-Add-operation-on-reset.patch
  92. 141 0
      target/linux/starfive/patches-6.1/0079-media-cadence-Add-support-for-external-dphy.patch
  93. 23 0
      target/linux/starfive/patches-6.1/0080-media-cadence-Add-support-for-JH7110-SoC.patch
  94. 197 0
      target/linux/starfive/patches-6.1/0081-media-dt-bindings-Add-JH7110-Camera-Subsystem.patch
  95. 106 0
      target/linux/starfive/patches-6.1/0082-media-admin-guide-Add-starfive_camss.rst-for-Starfiv.patch
  96. 630 0
      target/linux/starfive/patches-6.1/0083-media-starfive-Add-basic-driver.patch
  97. 992 0
      target/linux/starfive/patches-6.1/0084-media-starfive-Add-video-driver.patch
  98. 1667 0
      target/linux/starfive/patches-6.1/0085-media-starfive-Add-ISP-driver.patch
  99. 1694 0
      target/linux/starfive/patches-6.1/0086-media-starfive-Add-VIN-driver.patch
  100. 68 0
      target/linux/starfive/patches-6.1/0087-dt-bindings-phy-Add-StarFive-JH7110-USB-PHY.patch

+ 21 - 0
target/linux/starfive/Makefile

@@ -0,0 +1,21 @@
+# SPDX-License-Identifier: GPL-2.0-only
+#
+# Copyright (C) 2024 Toco Technologies <[email protected]>
+#
+include $(TOPDIR)/rules.mk
+
+ARCH:=riscv64
+BOARD:=starfive
+BOARDNAME:=StarFive JH71x0 (7100/7110)
+FEATURES:=ext4
+KERNELNAME:=Image dtbs
+
+KERNEL_PATCHVER:=6.1
+
+include $(INCLUDE_DIR)/target.mk
+
+define Target/Description
+	Build firmware images for the StarFive JH71x0-based boards
+endef
+
+$(eval $(call BuildTarget))

+ 22 - 0
target/linux/starfive/base-files/etc/board.d/02_network

@@ -0,0 +1,22 @@
+# SPDX-License-Identifier: GPL-2.0-only
+#
+# Copyright (C) 2022 OpenWrt.org
+#
+
+. /lib/functions/uci-defaults.sh
+
+board_config_update
+
+case "$(board_name)" in
+starfive,visionfive-2-v1.3b|\
+starfive,visionfive-2-v1.2a)
+	ucidef_set_interfaces_lan_wan "eth0" "eth1"
+	;;
+*)
+	ucidef_set_interface_lan 'eth0'
+	;;
+esac
+
+board_config_flush
+
+exit 0

+ 4 - 0
target/linux/starfive/base-files/etc/inittab

@@ -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

+ 53 - 0
target/linux/starfive/base-files/lib/firmware/brcm/brcmfmac43430-sdio.txt

@@ -0,0 +1,53 @@
+#AP6212_NVRAM_V1.0_20140603
+# 2.4 GHz, 20 MHz BW mode
+
+# The following parameter values are just placeholders, need to be updated.
+manfid=0x2d0
+prodid=0x0726
+vendid=0x14e4
+devid=0x43e2
+boardtype=0x0726
+boardrev=0x1101
+boardnum=22
+macaddr=00:90:4c:c5:12:38
+sromrev=11
+boardflags=0x00404201
+xtalfreq=26000
+nocrc=1
+ag0=255
+aa2g=1
+ccode=ALL
+
+pa0itssit=0x20
+extpagain2g=0
+
+#PA parameters for 2.4GHz, measured at CHIP OUTPUT
+pa2ga0=-168,7161,-820
+AvVmid_c0=0x0,0xc8
+cckpwroffset0=5
+
+# PPR params
+maxp2ga0=90
+txpwrbckof=6
+cckbw202gpo=0x5555
+legofdmbw202gpo=0x77777777
+mcsbw202gpo=0xaaaaaaaa
+
+# OFDM IIR :
+ofdmdigfilttype=7
+# PAPD mode:
+papdmode=2
+
+il0macaddr=00:90:4c:c5:12:38
+wl0id=0x431b
+
+#OOB parameters
+hostwake=0x40
+hostrdy=0x41
+usbrdy=0x03
+usbrdydelay=100
+deadman_to=0xffffffff
+# muxenab: 0x1 for UART enable, 0x10 for Host awake
+muxenab=0x10
+# CLDO PWM voltage settings - 0x4 - 1.1 volt
+#cldo_pwm=0x4

+ 1 - 0
target/linux/starfive/base-files/lib/firmware/brcm/brcmfmac43430a0-sdio.txt

@@ -0,0 +1 @@
+brcmfmac43430-sdio.txt

+ 555 - 0
target/linux/starfive/config-6.1

@@ -0,0 +1,555 @@
+CONFIG_64BIT=y
+CONFIG_AMBA_PL08X=y
+CONFIG_ARCH_CLOCKSOURCE_INIT=y
+CONFIG_ARCH_DMA_ADDR_T_64BIT=y
+CONFIG_ARCH_HIBERNATION_POSSIBLE=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_SIFIVE=y
+CONFIG_ARCH_SPARSEMEM_ENABLE=y
+CONFIG_ARCH_STACKWALK=y
+CONFIG_ARCH_STARFIVE=y
+CONFIG_ARCH_WANTS_THP_SWAP=y
+CONFIG_ARM_AMBA=y
+# CONFIG_ARM_MHU_V2 is not set
+CONFIG_ASN1=y
+CONFIG_ASSOCIATIVE_ARRAY=y
+CONFIG_AUXILIARY_BUS=y
+CONFIG_CC_HAVE_STACKPROTECTOR_TLS=y
+CONFIG_CC_IMPLICIT_FALLTHROUGH="-Wimplicit-fallthrough=5"
+CONFIG_CC_NO_ARRAY_BOUNDS=y
+CONFIG_CHECKPOINT_RESTORE=y
+CONFIG_CLKSRC_MMIO=y
+CONFIG_CLK_ANALOGBITS_WRPLL_CLN28HPC=y
+CONFIG_CLK_SIFIVE=y
+CONFIG_CLK_SIFIVE_PRCI=y
+CONFIG_CLK_STARFIVE_JH7100=y
+CONFIG_CLK_STARFIVE_JH7100_AUDIO=y
+CONFIG_CLK_STARFIVE_JH7110_AON=y
+CONFIG_CLK_STARFIVE_JH7110_ISP=y
+CONFIG_CLK_STARFIVE_JH7110_PLL=y
+CONFIG_CLK_STARFIVE_JH7110_STG=y
+CONFIG_CLK_STARFIVE_JH7110_SYS=y
+CONFIG_CLK_STARFIVE_JH7110_VOUT=y
+CONFIG_CLK_STARFIVE_JH71X0=y
+CONFIG_CLONE_BACKWARDS=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_CONFIGFS_FS=y
+CONFIG_CONTEXT_TRACKING=y
+CONFIG_CONTEXT_TRACKING_IDLE=y
+CONFIG_CONTIG_ALLOC=y
+CONFIG_CPUFREQ_DT=y
+CONFIG_CPUFREQ_DT_PLATDEV=y
+CONFIG_CPU_FREQ=y
+CONFIG_CPU_FREQ_DEFAULT_GOV_PERFORMANCE=y
+CONFIG_CPU_FREQ_GOV_ATTR_SET=y
+CONFIG_CPU_FREQ_GOV_COMMON=y
+CONFIG_CPU_FREQ_GOV_CONSERVATIVE=y
+CONFIG_CPU_FREQ_GOV_ONDEMAND=y
+CONFIG_CPU_FREQ_GOV_PERFORMANCE=y
+CONFIG_CPU_FREQ_GOV_POWERSAVE=y
+CONFIG_CPU_FREQ_GOV_USERSPACE=y
+CONFIG_CPU_FREQ_STAT=y
+CONFIG_CPU_IDLE=y
+CONFIG_CPU_IDLE_GOV_MENU=y
+CONFIG_CPU_IDLE_MULTIPLE_DRIVERS=y
+CONFIG_CPU_PM=y
+CONFIG_CPU_RMAP=y
+CONFIG_CRASH_CORE=y
+CONFIG_CRC16=y
+CONFIG_CRC7=y
+CONFIG_CRC_ITU_T=y
+CONFIG_CRYPTO_BLAKE2B=y
+CONFIG_CRYPTO_CMAC=y
+CONFIG_CRYPTO_CRC32C=y
+CONFIG_CRYPTO_DEV_JH7110=y
+CONFIG_CRYPTO_DRBG=y
+CONFIG_CRYPTO_DRBG_HMAC=y
+CONFIG_CRYPTO_DRBG_MENU=y
+CONFIG_CRYPTO_ECB=y
+CONFIG_CRYPTO_ECC=y
+CONFIG_CRYPTO_ECDH=y
+CONFIG_CRYPTO_ENGINE=y
+CONFIG_CRYPTO_HASH_INFO=y
+CONFIG_CRYPTO_HMAC=y
+CONFIG_CRYPTO_HW=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_CRYPTO_SM3=y
+CONFIG_CRYPTO_SM3_GENERIC=y
+CONFIG_CRYPTO_USER=y
+CONFIG_CRYPTO_USER_API=y
+CONFIG_CRYPTO_USER_API_AEAD=y
+CONFIG_CRYPTO_USER_API_HASH=y
+CONFIG_CRYPTO_USER_API_RNG=y
+CONFIG_CRYPTO_USER_API_SKCIPHER=y
+CONFIG_CRYPTO_XXHASH=y
+CONFIG_CRYPTO_ZSTD=y
+CONFIG_DEBUG_ATOMIC_SLEEP=y
+CONFIG_DEBUG_GPIO=y
+CONFIG_DEBUG_INFO=y
+CONFIG_DEBUG_PINCTRL=y
+CONFIG_DEBUG_RODATA_TEST=y
+CONFIG_DEBUG_RT_MUTEXES=y
+CONFIG_DEBUG_RWSEMS=y
+CONFIG_DEBUG_SECTION_MISMATCH=y
+CONFIG_DEBUG_SG=y
+CONFIG_DEBUG_SPINLOCK=y
+CONFIG_DEBUG_TIMEKEEPING=y
+CONFIG_DEBUG_WX=y
+CONFIG_DECOMPRESS_GZIP=y
+# CONFIG_DEVFREQ_GOV_PASSIVE is not set
+# CONFIG_DEVFREQ_GOV_PERFORMANCE is not set
+# CONFIG_DEVFREQ_GOV_POWERSAVE is not set
+# CONFIG_DEVFREQ_GOV_SIMPLE_ONDEMAND is not set
+# CONFIG_DEVFREQ_GOV_USERSPACE is not set
+# CONFIG_DEVFREQ_THERMAL is not set
+CONFIG_DEVTMPFS=y
+CONFIG_DEVTMPFS_MOUNT=y
+# CONFIG_DEVTMPFS_SAFE is not set
+CONFIG_DMADEVICES=y
+CONFIG_DMADEVICES_DEBUG=y
+CONFIG_DMADEVICES_VDEBUG=y
+CONFIG_DMA_ENGINE=y
+CONFIG_DMA_OF=y
+CONFIG_DMA_SHARED_BUFFER=y
+CONFIG_DMA_VIRTUAL_CHANNELS=y
+# CONFIG_DPM_WATCHDOG is not set
+CONFIG_DTC=y
+CONFIG_DT_IDLE_GENPD=y
+CONFIG_DT_IDLE_STATES=y
+CONFIG_DWMAC_DWC_QOS_ETH=y
+# CONFIG_DWMAC_GENERIC is not set
+CONFIG_DWMAC_STARFIVE=y
+CONFIG_DW_AXI_DMAC=y
+CONFIG_EDAC_SUPPORT=y
+CONFIG_EEPROM_AT24=y
+CONFIG_EFI=y
+CONFIG_EFIVAR_FS=y
+# 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=y
+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_ERRATA_SIFIVE=y
+CONFIG_ERRATA_SIFIVE_CIP_1200=y
+CONFIG_ERRATA_SIFIVE_CIP_453=y
+# CONFIG_ERRATA_THEAD is not set
+CONFIG_EXCLUSIVE_SYSTEM_RAM=y
+CONFIG_EXT4_FS=y
+CONFIG_EXT4_FS_POSIX_ACL=y
+CONFIG_EXTCON=y
+CONFIG_FAILOVER=y
+CONFIG_FANOTIFY=y
+CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-15"
+CONFIG_FAT_DEFAULT_UTF8=y
+CONFIG_FAT_FS=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_FS_IOMAP=y
+CONFIG_FS_MBCACHE=y
+CONFIG_FS_POSIX_ACL=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_MIGRATION=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_PHY=y
+CONFIG_GENERIC_PHY_MIPI_DPHY=y
+CONFIG_GENERIC_PINCONF=y
+CONFIG_GENERIC_PINCTRL_GROUPS=y
+CONFIG_GENERIC_PINMUX_FUNCTIONS=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_FASTPATH_LIMIT=128
+CONFIG_GPIOLIB_IRQCHIP=y
+CONFIG_GPIO_CDEV=y
+CONFIG_GPIO_TPS65086=y
+CONFIG_HARDIRQS_SW_RESEND=y
+CONFIG_HAS_DMA=y
+CONFIG_HAS_IOMEM=y
+CONFIG_HAS_IOPORT_MAP=y
+CONFIG_HOTPLUG_CPU=y
+CONFIG_HUGETLBFS=y
+CONFIG_HUGETLB_PAGE=y
+CONFIG_HVC_DRIVER=y
+CONFIG_HVC_RISCV_SBI=y
+CONFIG_HWMON=y
+CONFIG_HW_RANDOM=y
+CONFIG_HW_RANDOM_JH7110=y
+CONFIG_HW_RANDOM_STARFIVE_VIC=y
+CONFIG_I2C=y
+CONFIG_I2C_ALGOBIT=y
+CONFIG_I2C_BOARDINFO=y
+CONFIG_I2C_CHARDEV=y
+CONFIG_I2C_DESIGNWARE_CORE=y
+CONFIG_I2C_DESIGNWARE_PLATFORM=y
+CONFIG_IKCONFIG=y
+CONFIG_IKCONFIG_PROC=y
+CONFIG_INITRAMFS_SOURCE=""
+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_JH71XX_PMU=y
+CONFIG_JUMP_LABEL=y
+CONFIG_LIBFDT=y
+CONFIG_LOCKUP_DETECTOR=y
+CONFIG_LOCK_DEBUGGING_SUPPORT=y
+CONFIG_LOCK_SPIN_ON_OWNER=y
+CONFIG_LSM=""
+CONFIG_MARVELL_PHY=y
+CONFIG_MDIO_BUS=y
+CONFIG_MDIO_DEVICE=y
+CONFIG_MDIO_DEVRES=y
+CONFIG_MEMFD_CREATE=y
+CONFIG_MEMORY_ISOLATION=y
+CONFIG_MEMTEST=y
+CONFIG_MFD_AXP20X=y
+CONFIG_MFD_AXP20X_I2C=y
+CONFIG_MFD_CORE=y
+CONFIG_MFD_SYSCON=y
+CONFIG_MFD_TPS65086=y
+CONFIG_MICREL_PHY=y
+CONFIG_MICROCHIP_PHY=y
+CONFIG_MIGRATION=y
+CONFIG_MMC=y
+CONFIG_MMC_BLOCK=y
+CONFIG_MMC_DEBUG=y
+CONFIG_MMC_DW=y
+# CONFIG_MMC_DW_BLUEFIELD is not set
+# CONFIG_MMC_DW_EXYNOS is not set
+# CONFIG_MMC_DW_HI3798CV200 is not set
+# CONFIG_MMC_DW_K3 is not set
+# CONFIG_MMC_DW_PCI is not set
+CONFIG_MMC_DW_PLTFM=y
+CONFIG_MMC_DW_STARFIVE=y
+CONFIG_MMIOWB=y
+CONFIG_MODULES_TREE_LOOKUP=y
+CONFIG_MODULES_USE_ELF_RELA=y
+CONFIG_MODULE_SECTIONS=y
+CONFIG_MOTORCOMM_PHY=y
+CONFIG_MPILIB=y
+CONFIG_MTD_SPI_NOR=y
+CONFIG_MUTEX_SPIN_ON_OWNER=y
+CONFIG_NAMESPACES=y
+CONFIG_NEED_DMA_MAP_STATE=y
+CONFIG_NET_FAILOVER=y
+CONFIG_NET_FLOW_LIMIT=y
+CONFIG_NET_NS=y
+CONFIG_NET_SELFTESTS=y
+CONFIG_NLS=y
+CONFIG_NLS_CODEPAGE_437=y
+CONFIG_NLS_DEFAULT="iso8859-15"
+CONFIG_NLS_ISO8859_1=y
+CONFIG_NLS_ISO8859_15=y
+CONFIG_NO_HZ_COMMON=y
+CONFIG_NO_HZ_IDLE=y
+# CONFIG_NONPORTABLE is not set
+CONFIG_NR_CPUS=8
+CONFIG_NVMEM=y
+CONFIG_NVMEM_SYSFS=y
+CONFIG_NVME_CORE=y
+CONFIG_NVME_HWMON=y
+# CONFIG_NVME_MULTIPATH is not set
+CONFIG_OF=y
+CONFIG_OF_ADDRESS=y
+CONFIG_OF_DMA_DEFAULT_COHERENT=y
+CONFIG_OF_DYNAMIC=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_OF_OVERLAY=y
+CONFIG_OF_RESOLVE=y
+CONFIG_OID_REGISTRY=y
+CONFIG_OVERLAY_FS_INDEX=y
+CONFIG_OVERLAY_FS_METACOPY=y
+CONFIG_OVERLAY_FS_REDIRECT_DIR=y
+CONFIG_PADATA=y
+CONFIG_PAGE_EXTENSION=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_PCI=y
+CONFIG_PCIE_CADENCE=y
+CONFIG_PCIE_CADENCE_HOST=y
+CONFIG_PCIE_CADENCE_PLAT=y
+CONFIG_PCIE_CADENCE_PLAT_HOST=y
+# CONFIG_PCIE_FU740 is not set
+# CONFIG_PCIE_STARFIVE is not set
+CONFIG_PCI_DOMAINS=y
+CONFIG_PCI_DOMAINS_GENERIC=y
+CONFIG_PCI_MSI=y
+CONFIG_PCI_MSI_IRQ_DOMAIN=y
+CONFIG_PCS_XPCS=y
+CONFIG_PERF_EVENTS=y
+CONFIG_PGTABLE_LEVELS=5
+CONFIG_PHYLIB=y
+CONFIG_PHYLINK=y
+CONFIG_PHYS_ADDR_T_64BIT=y
+CONFIG_PHY_STARFIVE_DPHY_RX=y
+CONFIG_PHY_STARFIVE_JH7110_PCIE=y
+CONFIG_PHY_STARFIVE_JH7110_USB=y
+CONFIG_PINCTRL=y
+CONFIG_PINCTRL_STARFIVE_JH7100=y
+CONFIG_PINCTRL_STARFIVE_JH7110=y
+CONFIG_PINCTRL_STARFIVE_JH7110_AON=y
+CONFIG_PINCTRL_STARFIVE_JH7110_SYS=y
+CONFIG_PM=y
+CONFIG_PM_ADVANCED_DEBUG=y
+CONFIG_PM_CLK=y
+CONFIG_PM_DEBUG=y
+CONFIG_PM_DEVFREQ=y
+# CONFIG_PM_DEVFREQ_EVENT is not set
+CONFIG_PM_GENERIC_DOMAINS=y
+CONFIG_PM_GENERIC_DOMAINS_OF=y
+CONFIG_PM_OPP=y
+CONFIG_PORTABLE=y
+CONFIG_POSIX_CPU_TIMERS_TASK_WORK=y
+CONFIG_POSIX_MQUEUE=y
+CONFIG_POSIX_MQUEUE_SYSCTL=y
+CONFIG_POWER_RESET=y
+CONFIG_POWER_RESET_GPIO_RESTART=y
+CONFIG_POWER_RESET_SYSCON=y
+CONFIG_POWER_RESET_SYSCON_POWEROFF=y
+# CONFIG_POWER_RESET_TPS65086 is not set
+CONFIG_PPS=y
+CONFIG_PREEMPT_COUNT=y
+CONFIG_PREEMPT_NONE_BUILD=y
+CONFIG_PRINTK_TIME=y
+CONFIG_PROC_CHILDREN=y
+CONFIG_PROC_KCORE=y
+CONFIG_PTDUMP_CORE=y
+CONFIG_PTP_1588_CLOCK=y
+CONFIG_PTP_1588_CLOCK_OPTIONAL=y
+CONFIG_PWM=y
+# CONFIG_PWM_SIFIVE is not set
+CONFIG_PWM_SIFIVE_PTC=y
+CONFIG_PWM_STARFIVE_PTC=y
+CONFIG_PWM_SYSFS=y
+CONFIG_QUEUED_RWLOCKS=y
+CONFIG_RANDSTRUCT_NONE=y
+CONFIG_RATIONAL=y
+CONFIG_RCU_EQS_DEBUG=y
+CONFIG_RD_GZIP=y
+CONFIG_REALTEK_PHY=y
+CONFIG_REGMAP=y
+CONFIG_REGMAP_I2C=y
+CONFIG_REGMAP_IRQ=y
+CONFIG_REGMAP_MMIO=y
+CONFIG_REGULATOR=y
+CONFIG_REGULATOR_AXP20X=y
+CONFIG_REGULATOR_TPS65086=y
+# CONFIG_RESET_ATTACK_MITIGATION is not set
+CONFIG_RESET_CONTROLLER=y
+CONFIG_RESET_SIMPLE=y
+CONFIG_RESET_STARFIVE_JH7100=y
+CONFIG_RESET_STARFIVE_JH7100_AUDIO=y
+CONFIG_RESET_STARFIVE_JH7110=y
+CONFIG_RESET_STARFIVE_JH71X0=y
+CONFIG_RFS_ACCEL=y
+CONFIG_RISCV=y
+CONFIG_RISCV_ALTERNATIVE=y
+CONFIG_RISCV_BOOT_SPINWAIT=y
+CONFIG_RISCV_DMA_NONCOHERENT=y
+CONFIG_RISCV_INTC=y
+CONFIG_RISCV_ISA_C=y
+# CONFIG_RISCV_ISA_SVPBMT is not set
+CONFIG_RISCV_ISA_ZICBOM=y
+CONFIG_RISCV_PMU=y
+CONFIG_RISCV_PMU_LEGACY=y
+CONFIG_RISCV_PMU_SBI=y
+CONFIG_RISCV_SBI=y
+CONFIG_RISCV_SBI_CPUIDLE=y
+CONFIG_RISCV_SBI_V01=y
+CONFIG_RISCV_TIMER=y
+CONFIG_RPMSG=y
+CONFIG_RPMSG_CHAR=y
+# CONFIG_RPMSG_CTRL is not set
+CONFIG_RPMSG_NS=y
+# CONFIG_RPMSG_TTY is not set
+CONFIG_RPMSG_VIRTIO=y
+CONFIG_RPS=y
+CONFIG_RTC_CLASS=y
+# CONFIG_RTC_DRV_EFI is not set
+CONFIG_RTC_DRV_GOLDFISH=y
+CONFIG_RTC_DRV_HYM8563=y
+CONFIG_RTC_I2C_AND_SPI=y
+CONFIG_RWSEM_SPIN_ON_OWNER=y
+CONFIG_SCSI=y
+CONFIG_SCSI_COMMON=y
+CONFIG_SCSI_VIRTIO=y
+CONFIG_SENSORS_SFCTEMP=y
+# CONFIG_SERIAL_8250_16550A_VARIANTS is not set
+CONFIG_SERIAL_8250_DW=y
+CONFIG_SERIAL_8250_DWLIB=y
+CONFIG_SERIAL_8250_EXTENDED=y
+CONFIG_SERIAL_8250_MANY_PORTS=y
+CONFIG_SERIAL_8250_NR_UARTS=6
+CONFIG_SERIAL_8250_RUNTIME_UARTS=6
+# CONFIG_SERIAL_8250_SHARE_IRQ is not set
+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_SGL_ALLOC=y
+CONFIG_SG_POOL=y
+CONFIG_SIFIVE_CCACHE=y
+CONFIG_SIFIVE_PLIC=y
+CONFIG_SMP=y
+# CONFIG_SND_SOC_STARFIVE is not set
+CONFIG_SOCK_DIAG=y
+CONFIG_SOCK_RX_QUEUE_MAPPING=y
+# CONFIG_SOC_MICROCHIP_POLARFIRE is not set
+CONFIG_SOC_SIFIVE=y
+CONFIG_SOC_STARFIVE=y
+# CONFIG_SOC_VIRT is not set
+CONFIG_SOFTLOCKUP_DETECTOR=y
+CONFIG_SOUND=y
+CONFIG_SPARSEMEM_VMEMMAP_ENABLE=y
+CONFIG_SPARSE_IRQ=y
+CONFIG_SPI=y
+CONFIG_SPI_CADENCE_QUADSPI=y
+CONFIG_SPI_DYNAMIC=y
+CONFIG_SPI_MASTER=y
+CONFIG_SPI_MEM=y
+CONFIG_SPI_SPIDEV=y
+CONFIG_SRCU=y
+CONFIG_STARFIVE_TIMER=y
+CONFIG_STARFIVE_WATCHDOG=y
+CONFIG_STMMAC_ETH=y
+CONFIG_STMMAC_PLATFORM=y
+CONFIG_STMMAC_SELFTESTS=y
+CONFIG_SWIOTLB=y
+CONFIG_SWPHY=y
+CONFIG_SYNC_FILE=y
+CONFIG_SYSCTL_EXCEPTION_TRACE=y
+# CONFIG_SYSFB_SIMPLEFB is not set
+CONFIG_THERMAL=y
+CONFIG_THERMAL_DEFAULT_GOV_STEP_WISE=y
+CONFIG_THERMAL_EMERGENCY_POWEROFF_DELAY_MS=0
+CONFIG_THERMAL_GOV_STEP_WISE=y
+CONFIG_THERMAL_OF=y
+CONFIG_THREAD_INFO_IN_TASK=y
+CONFIG_TICK_CPU_ACCOUNTING=y
+CONFIG_TIMER_OF=y
+CONFIG_TIMER_PROBE=y
+CONFIG_TMPFS_POSIX_ACL=y
+CONFIG_TOOLCHAIN_HAS_ZICBOM=y
+CONFIG_TOOLCHAIN_HAS_ZIHINTPAUSE=y
+CONFIG_TOOLCHAIN_NEEDS_EXPLICIT_ZICSR_ZIFENCEI=y
+CONFIG_TREE_RCU=y
+CONFIG_TREE_SRCU=y
+CONFIG_TTY_PRINTK=y
+CONFIG_TTY_PRINTK_LEVEL=6
+CONFIG_TUNE_GENERIC=y
+CONFIG_UCS2_STRING=y
+CONFIG_UNINLINE_SPIN_UNLOCK=y
+CONFIG_USB=y
+CONFIG_USB_COMMON=y
+CONFIG_USB_CONFIGFS=y
+# CONFIG_USB_CONFIGFS_ACM is not set
+# CONFIG_USB_CONFIGFS_ECM is not set
+# CONFIG_USB_CONFIGFS_ECM_SUBSET is not set
+# CONFIG_USB_CONFIGFS_EEM is not set
+CONFIG_USB_CONFIGFS_F_FS=y
+# CONFIG_USB_CONFIGFS_F_HID is not set
+# CONFIG_USB_CONFIGFS_F_LB_SS is not set
+# CONFIG_USB_CONFIGFS_F_MIDI is not set
+# CONFIG_USB_CONFIGFS_F_PRINTER is not set
+# CONFIG_USB_CONFIGFS_F_UAC1 is not set
+# CONFIG_USB_CONFIGFS_F_UAC1_LEGACY is not set
+# CONFIG_USB_CONFIGFS_F_UAC2 is not set
+# CONFIG_USB_CONFIGFS_F_UVC is not set
+CONFIG_USB_CONFIGFS_MASS_STORAGE=y
+# CONFIG_USB_CONFIGFS_NCM is not set
+# CONFIG_USB_CONFIGFS_OBEX is not set
+# CONFIG_USB_CONFIGFS_RNDIS is not set
+# CONFIG_USB_CONFIGFS_SERIAL is not set
+CONFIG_USB_F_FS=y
+CONFIG_USB_F_MASS_STORAGE=y
+CONFIG_USB_GADGET=y
+CONFIG_USB_LIBCOMPOSITE=y
+CONFIG_USB_PCI=y
+CONFIG_USB_PHY=y
+CONFIG_USB_ROLE_SWITCH=y
+CONFIG_USB_SUPPORT=y
+# CONFIG_USB_UHCI_HCD is not set
+CONFIG_USELIB=y
+CONFIG_USER_NS=y
+CONFIG_VFAT_FS=y
+# CONFIG_VIRTIO_BLK is not set
+# CONFIG_VIRTIO_NET is not set
+CONFIG_VMAP_STACK=y
+CONFIG_WATCHDOG_CORE=y
+CONFIG_WATCHDOG_SYSFS=y
+CONFIG_WERROR=y
+CONFIG_WQ_WATCHDOG=y
+CONFIG_XPS=y
+CONFIG_XXHASH=y
+CONFIG_ZLIB_INFLATE=y
+CONFIG_ZONE_DMA32=y

+ 1 - 0
target/linux/starfive/generic/target.mk

@@ -0,0 +1 @@
+BOARDNAME:=Generic

+ 5 - 0
target/linux/starfive/image/Config.in

@@ -0,0 +1,5 @@
+config STARFIVE_SD_BOOT_PARTSIZE
+	int "Boot (SD Card) filesystem partition size (in MB)"
+	depends on TARGET_starfive
+	default 32
+

+ 85 - 0
target/linux/starfive/image/Makefile

@@ -0,0 +1,85 @@
+# SPDX-License-Identifier: GPL-2.0-only
+#
+# Copyright (C) 2023 Toco Technologies <[email protected]>
+#
+include $(TOPDIR)/rules.mk
+include $(INCLUDE_DIR)/image.mk
+
+FAT32_BLOCK_SIZE=1024
+FAT32_BLOCKS=$(shell echo $$(($(CONFIG_STARFIVE_SD_BOOT_PARTSIZE)*1024*1024/$(FAT32_BLOCK_SIZE))))
+
+define Build/boot-scr-jh7110
+	rm -f [email protected]
+	mkimage -A riscv -O linux -T script -C none -a 0 -e 0 -d mmc.bootscript.jh7110 [email protected]
+endef
+
+define Build/boot-scr-jh7100
+	rm -f [email protected]
+	mkimage -A riscv -O linux -T script -C none -a 0 -e 0 -d mmc.bootscript.jh7100 [email protected]
+endef
+
+define Build/riscv-sdcard
+	rm -f [email protected] #$(KDIR_TMP)/$(IMG_PREFIX)-$(PROFILE)-boot.img
+	mkfs.fat [email protected] -C $(FAT32_BLOCKS)
+	mcopy -i [email protected] $(LINUX_DIR)/arch/riscv/boot/dts/$(DEVICE_DTS).dtb ::dtb
+	mcopy -i [email protected] [email protected] ::boot.scr.uimg
+	mcopy -i [email protected] $(IMAGE_KERNEL) ::Image
+	./gen_starfive_sdcard_img.sh \
+		$@ \
+		[email protected] \
+		$(IMAGE_ROOTFS) \
+		$(CONFIG_STARFIVE_SD_BOOT_PARTSIZE) \
+		$(CONFIG_TARGET_ROOTFS_PARTSIZE)
+endef
+
+define Device/Default
+  PROFILES := Default
+  KERNEL_NAME := Image
+  KERNEL := kernel-bin
+  IMAGES := sdcard.img.gz
+  IMAGE/sdcard.img.gz := boot-scr-jh7110 | riscv-sdcard | append-metadata | gzip
+endef
+
+define Device/JH7100
+  PROFILES := Default
+  KERNEL_NAME := Image
+  KERNEL := kernel-bin
+  IMAGES := sdcard.img.gz
+  IMAGE/sdcard.img.gz := boot-scr-jh7100 | riscv-sdcard | append-metadata | gzip
+endef
+
+define Device/visionfive2-v1.2a
+  DEVICE_VENDOR := StarFive
+  DEVICE_MODEL := VisionFive2 v1.2a
+  DEVICE_DTS := starfive/jh7110-starfive-visionfive-2-v1.2a
+  DEVICE_PACKAGES := kmod-eeprom-at24 kmod-pcie-starfive kmod-usb3 kmod-usb-cdns3-starfive
+endef
+TARGET_DEVICES += visionfive2-v1.2a
+
+define Device/visionfive2-v1.3b
+  DEVICE_VENDOR := StarFive
+  DEVICE_MODEL := VisionFive2 v1.3b
+  DEVICE_DTS := starfive/jh7110-starfive-visionfive-2-v1.3b
+  DEVICE_PACKAGES := kmod-eeprom-at24 kmod-pcie-starfive kmod-usb3 kmod-usb-cdns3-starfive
+endef
+TARGET_DEVICES += visionfive2-v1.3b
+
+define Device/beaglev-starlight
+  $(call Device/JH7100)
+  DEVICE_VENDOR := BeagleV
+  DEVICE_MODEL := Starlight
+  DEVICE_DTS := starfive/jh7100-beaglev-starlight
+endef
+TARGET_DEVICES += beaglev-starlight
+
+define Device/visionfive-v1
+  $(call Device/JH7100)
+  DEVICE_VENDOR := StarFive
+  DEVICE_MODEL := VisionFive v1
+  DEVICE_DTS := starfive/jh7100-starfive-visionfive-v1
+  DEVICE_PACKAGES := kmod-eeprom-at24 kmod-brcmfmac cypress-firmware-43430-sdio wpad-basic-mbedtls \
+  			kmod-usb3 kmod-usb-cdns3-starfive
+endef
+TARGET_DEVICES += visionfive-v1
+
+$(eval $(call BuildImage))

+ 24 - 0
target/linux/starfive/image/gen_starfive_sdcard_img.sh

@@ -0,0 +1,24 @@
+#!/usr/bin/env bash
+# SPDX-License-Identifier: GPL-2.0-only
+#
+# Copyright (C) 2023 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"
+
+set $(ptgen -o $OUTPUT -v -g -T sifiveu_spl -N loader1 -p 1024 -T sifiveu_uboot -N loader2 -p 4096 -t ef -N boot -p ${BOOTFSSIZE}M -N rootfs -p ${ROOTFSSIZE}M)
+
+ROOTFSOFFSET=$(($7 / 512))
+
+dd bs=512 if="$BOOTFS" of="$OUTPUT" seek=10274 conv=notrunc
+dd bs=512 if="$ROOTFS" of="$OUTPUT" seek=${ROOTFSOFFSET} conv=notrunc

+ 4 - 0
target/linux/starfive/image/mmc.bootscript.jh7100

@@ -0,0 +1,4 @@
+fatload mmc 0:3 0x84000000 Image
+fatload mmc 0:3 0x88000000 dtb
+setenv bootargs "earlyprintk console=ttyS0,115200 debug rootwait earlycon=sbi root=/dev/mmcblk0p4"
+booti 0x84000000 - 0x88000000

+ 5 - 0
target/linux/starfive/image/mmc.bootscript.jh7110

@@ -0,0 +1,5 @@
+fatload mmc 1:3 0xa0000000 Image
+fatload mmc 1:3 0x46000000 dtb
+run chipa_set_linux
+setenv bootargs "earlyprintk console=ttyS0,115200 debug rootwait earlycon=sbi root=/dev/mmcblk1p4"
+booti 0xa0000000 - 0x46000000

+ 31 - 0
target/linux/starfive/modules.mk

@@ -0,0 +1,31 @@
+define KernelPackage/pcie-starfive
+  SUBMENU:=$(OTHER_MENU)
+  TITLE:=JH7110 PCIe controller support
+  DEPENDS:=@TARGET_starfive
+  KCONFIG:=CONFIG_PCIE_STARFIVE
+  FILES:=$(LINUX_DIR)/drivers/pci/controller/pcie-starfive.ko
+  AUTOLOAD:=$(call AutoLoad,41,pcie-starfive,1)
+endef
+
+define KernelPackage/pcie-starfive/description
+ PCIe support for JH7110
+endef
+
+$(eval $(call KernelPackage,pcie-starfive))
+
+
+define KernelPackage/usb-cdns3-starfive
+  TITLE:=Cadence USB3 StarFive USB driver
+  DEPENDS:=@TARGET_starfive +kmod-usb-cdns3
+  KCONFIG:= CONFIG_USB_CDNS3_STARFIVE
+  FILES:= $(LINUX_DIR)/drivers/usb/cdns3/cdns3-starfive.ko
+  AUTOLOAD:=$(call AutoLoad,53,cdns3-starfive,1)
+  $(call AddDepends/usb)
+endef
+
+define KernelPackage/usb-cdns3-starfive/description
+ Add support for the Cadence USB3 controller found in StarFive SoCs.
+endef
+
+
+$(eval $(call KernelPackage,usb-cdns3-starfive))

+ 482 - 0
target/linux/starfive/patches-6.1/0001-dt-bindings-clock-Add-StarFive-JH7110-system-clock-a.patch

@@ -0,0 +1,482 @@
+From c960c73ee9fdaae51fcd8a14d44d576b1cf522b7 Mon Sep 17 00:00:00 2001
+From: Emil Renner Berthing <[email protected]>
+Date: Sat, 1 Apr 2023 19:19:13 +0800
+Subject: [PATCH 001/122] dt-bindings: clock: Add StarFive JH7110 system clock
+ and reset generator
+
+Add bindings for the system clock and reset generator (SYSCRG) on the
+JH7110 RISC-V SoC by StarFive Ltd.
+
+Reviewed-by: Conor Dooley <[email protected]>
+Reviewed-by: Rob Herring <[email protected]>
+Reviewed-by: Emil Renner Berthing <[email protected]>
+Signed-off-by: Emil Renner Berthing <[email protected]>
+Signed-off-by: Hal Feng <[email protected]>
+Signed-off-by: Conor Dooley <[email protected]>
+---
+ .../clock/starfive,jh7110-syscrg.yaml         | 104 +++++++++
+ .../dt-bindings/clock/starfive,jh7110-crg.h   | 203 ++++++++++++++++++
+ .../dt-bindings/reset/starfive,jh7110-crg.h   | 142 ++++++++++++
+ 3 files changed, 449 insertions(+)
+ create mode 100644 Documentation/devicetree/bindings/clock/starfive,jh7110-syscrg.yaml
+ create mode 100644 include/dt-bindings/clock/starfive,jh7110-crg.h
+ create mode 100644 include/dt-bindings/reset/starfive,jh7110-crg.h
+
+--- /dev/null
++++ b/Documentation/devicetree/bindings/clock/starfive,jh7110-syscrg.yaml
+@@ -0,0 +1,104 @@
++# SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause
++%YAML 1.2
++---
++$id: http://devicetree.org/schemas/clock/starfive,jh7110-syscrg.yaml#
++$schema: http://devicetree.org/meta-schemas/core.yaml#
++
++title: StarFive JH7110 System Clock and Reset Generator
++
++maintainers:
++  - Emil Renner Berthing <[email protected]>
++
++properties:
++  compatible:
++    const: starfive,jh7110-syscrg
++
++  reg:
++    maxItems: 1
++
++  clocks:
++    oneOf:
++      - items:
++          - description: Main Oscillator (24 MHz)
++          - description: GMAC1 RMII reference or GMAC1 RGMII RX
++          - description: External I2S TX bit clock
++          - description: External I2S TX left/right channel clock
++          - description: External I2S RX bit clock
++          - description: External I2S RX left/right channel clock
++          - description: External TDM clock
++          - description: External audio master clock
++
++      - items:
++          - description: Main Oscillator (24 MHz)
++          - description: GMAC1 RMII reference
++          - description: GMAC1 RGMII RX
++          - description: External I2S TX bit clock
++          - description: External I2S TX left/right channel clock
++          - description: External I2S RX bit clock
++          - description: External I2S RX left/right channel clock
++          - description: External TDM clock
++          - description: External audio master clock
++
++  clock-names:
++    oneOf:
++      - items:
++          - const: osc
++          - enum:
++              - gmac1_rmii_refin
++              - gmac1_rgmii_rxin
++          - const: i2stx_bclk_ext
++          - const: i2stx_lrck_ext
++          - const: i2srx_bclk_ext
++          - const: i2srx_lrck_ext
++          - const: tdm_ext
++          - const: mclk_ext
++
++      - items:
++          - const: osc
++          - const: gmac1_rmii_refin
++          - const: gmac1_rgmii_rxin
++          - const: i2stx_bclk_ext
++          - const: i2stx_lrck_ext
++          - const: i2srx_bclk_ext
++          - const: i2srx_lrck_ext
++          - const: tdm_ext
++          - const: mclk_ext
++
++  '#clock-cells':
++    const: 1
++    description:
++      See <dt-bindings/clock/starfive,jh7110-crg.h> for valid indices.
++
++  '#reset-cells':
++    const: 1
++    description:
++      See <dt-bindings/reset/starfive,jh7110-crg.h> for valid indices.
++
++required:
++  - compatible
++  - reg
++  - clocks
++  - clock-names
++  - '#clock-cells'
++  - '#reset-cells'
++
++additionalProperties: false
++
++examples:
++  - |
++    clock-controller@13020000 {
++        compatible = "starfive,jh7110-syscrg";
++        reg = <0x13020000 0x10000>;
++        clocks = <&osc>, <&gmac1_rmii_refin>,
++                 <&gmac1_rgmii_rxin>,
++                 <&i2stx_bclk_ext>, <&i2stx_lrck_ext>,
++                 <&i2srx_bclk_ext>, <&i2srx_lrck_ext>,
++                 <&tdm_ext>, <&mclk_ext>;
++        clock-names = "osc", "gmac1_rmii_refin",
++                      "gmac1_rgmii_rxin",
++                      "i2stx_bclk_ext", "i2stx_lrck_ext",
++                      "i2srx_bclk_ext", "i2srx_lrck_ext",
++                      "tdm_ext", "mclk_ext";
++        #clock-cells = <1>;
++        #reset-cells = <1>;
++    };
+--- /dev/null
++++ b/include/dt-bindings/clock/starfive,jh7110-crg.h
+@@ -0,0 +1,203 @@
++/* SPDX-License-Identifier: GPL-2.0 OR MIT */
++/*
++ * Copyright 2022 Emil Renner Berthing <[email protected]>
++ */
++
++#ifndef __DT_BINDINGS_CLOCK_STARFIVE_JH7110_CRG_H__
++#define __DT_BINDINGS_CLOCK_STARFIVE_JH7110_CRG_H__
++
++/* SYSCRG clocks */
++#define JH7110_SYSCLK_CPU_ROOT			0
++#define JH7110_SYSCLK_CPU_CORE			1
++#define JH7110_SYSCLK_CPU_BUS			2
++#define JH7110_SYSCLK_GPU_ROOT			3
++#define JH7110_SYSCLK_PERH_ROOT			4
++#define JH7110_SYSCLK_BUS_ROOT			5
++#define JH7110_SYSCLK_NOCSTG_BUS		6
++#define JH7110_SYSCLK_AXI_CFG0			7
++#define JH7110_SYSCLK_STG_AXIAHB		8
++#define JH7110_SYSCLK_AHB0			9
++#define JH7110_SYSCLK_AHB1			10
++#define JH7110_SYSCLK_APB_BUS			11
++#define JH7110_SYSCLK_APB0			12
++#define JH7110_SYSCLK_PLL0_DIV2			13
++#define JH7110_SYSCLK_PLL1_DIV2			14
++#define JH7110_SYSCLK_PLL2_DIV2			15
++#define JH7110_SYSCLK_AUDIO_ROOT		16
++#define JH7110_SYSCLK_MCLK_INNER		17
++#define JH7110_SYSCLK_MCLK			18
++#define JH7110_SYSCLK_MCLK_OUT			19
++#define JH7110_SYSCLK_ISP_2X			20
++#define JH7110_SYSCLK_ISP_AXI			21
++#define JH7110_SYSCLK_GCLK0			22
++#define JH7110_SYSCLK_GCLK1			23
++#define JH7110_SYSCLK_GCLK2			24
++#define JH7110_SYSCLK_CORE			25
++#define JH7110_SYSCLK_CORE1			26
++#define JH7110_SYSCLK_CORE2			27
++#define JH7110_SYSCLK_CORE3			28
++#define JH7110_SYSCLK_CORE4			29
++#define JH7110_SYSCLK_DEBUG			30
++#define JH7110_SYSCLK_RTC_TOGGLE		31
++#define JH7110_SYSCLK_TRACE0			32
++#define JH7110_SYSCLK_TRACE1			33
++#define JH7110_SYSCLK_TRACE2			34
++#define JH7110_SYSCLK_TRACE3			35
++#define JH7110_SYSCLK_TRACE4			36
++#define JH7110_SYSCLK_TRACE_COM			37
++#define JH7110_SYSCLK_NOC_BUS_CPU_AXI		38
++#define JH7110_SYSCLK_NOC_BUS_AXICFG0_AXI	39
++#define JH7110_SYSCLK_OSC_DIV2			40
++#define JH7110_SYSCLK_PLL1_DIV4			41
++#define JH7110_SYSCLK_PLL1_DIV8			42
++#define JH7110_SYSCLK_DDR_BUS			43
++#define JH7110_SYSCLK_DDR_AXI			44
++#define JH7110_SYSCLK_GPU_CORE			45
++#define JH7110_SYSCLK_GPU_CORE_CLK		46
++#define JH7110_SYSCLK_GPU_SYS_CLK		47
++#define JH7110_SYSCLK_GPU_APB			48
++#define JH7110_SYSCLK_GPU_RTC_TOGGLE		49
++#define JH7110_SYSCLK_NOC_BUS_GPU_AXI		50
++#define JH7110_SYSCLK_ISP_TOP_CORE		51
++#define JH7110_SYSCLK_ISP_TOP_AXI		52
++#define JH7110_SYSCLK_NOC_BUS_ISP_AXI		53
++#define JH7110_SYSCLK_HIFI4_CORE		54
++#define JH7110_SYSCLK_HIFI4_AXI			55
++#define JH7110_SYSCLK_AXI_CFG1_MAIN		56
++#define JH7110_SYSCLK_AXI_CFG1_AHB		57
++#define JH7110_SYSCLK_VOUT_SRC			58
++#define JH7110_SYSCLK_VOUT_AXI			59
++#define JH7110_SYSCLK_NOC_BUS_DISP_AXI		60
++#define JH7110_SYSCLK_VOUT_TOP_AHB		61
++#define JH7110_SYSCLK_VOUT_TOP_AXI		62
++#define JH7110_SYSCLK_VOUT_TOP_HDMITX0_MCLK	63
++#define JH7110_SYSCLK_VOUT_TOP_MIPIPHY_REF	64
++#define JH7110_SYSCLK_JPEGC_AXI			65
++#define JH7110_SYSCLK_CODAJ12_AXI		66
++#define JH7110_SYSCLK_CODAJ12_CORE		67
++#define JH7110_SYSCLK_CODAJ12_APB		68
++#define JH7110_SYSCLK_VDEC_AXI			69
++#define JH7110_SYSCLK_WAVE511_AXI		70
++#define JH7110_SYSCLK_WAVE511_BPU		71
++#define JH7110_SYSCLK_WAVE511_VCE		72
++#define JH7110_SYSCLK_WAVE511_APB		73
++#define JH7110_SYSCLK_VDEC_JPG			74
++#define JH7110_SYSCLK_VDEC_MAIN			75
++#define JH7110_SYSCLK_NOC_BUS_VDEC_AXI		76
++#define JH7110_SYSCLK_VENC_AXI			77
++#define JH7110_SYSCLK_WAVE420L_AXI		78
++#define JH7110_SYSCLK_WAVE420L_BPU		79
++#define JH7110_SYSCLK_WAVE420L_VCE		80
++#define JH7110_SYSCLK_WAVE420L_APB		81
++#define JH7110_SYSCLK_NOC_BUS_VENC_AXI		82
++#define JH7110_SYSCLK_AXI_CFG0_MAIN_DIV		83
++#define JH7110_SYSCLK_AXI_CFG0_MAIN		84
++#define JH7110_SYSCLK_AXI_CFG0_HIFI4		85
++#define JH7110_SYSCLK_AXIMEM2_AXI		86
++#define JH7110_SYSCLK_QSPI_AHB			87
++#define JH7110_SYSCLK_QSPI_APB			88
++#define JH7110_SYSCLK_QSPI_REF_SRC		89
++#define JH7110_SYSCLK_QSPI_REF			90
++#define JH7110_SYSCLK_SDIO0_AHB			91
++#define JH7110_SYSCLK_SDIO1_AHB			92
++#define JH7110_SYSCLK_SDIO0_SDCARD		93
++#define JH7110_SYSCLK_SDIO1_SDCARD		94
++#define JH7110_SYSCLK_USB_125M			95
++#define JH7110_SYSCLK_NOC_BUS_STG_AXI		96
++#define JH7110_SYSCLK_GMAC1_AHB			97
++#define JH7110_SYSCLK_GMAC1_AXI			98
++#define JH7110_SYSCLK_GMAC_SRC			99
++#define JH7110_SYSCLK_GMAC1_GTXCLK		100
++#define JH7110_SYSCLK_GMAC1_RMII_RTX		101
++#define JH7110_SYSCLK_GMAC1_PTP			102
++#define JH7110_SYSCLK_GMAC1_RX			103
++#define JH7110_SYSCLK_GMAC1_RX_INV		104
++#define JH7110_SYSCLK_GMAC1_TX			105
++#define JH7110_SYSCLK_GMAC1_TX_INV		106
++#define JH7110_SYSCLK_GMAC1_GTXC		107
++#define JH7110_SYSCLK_GMAC0_GTXCLK		108
++#define JH7110_SYSCLK_GMAC0_PTP			109
++#define JH7110_SYSCLK_GMAC_PHY			110
++#define JH7110_SYSCLK_GMAC0_GTXC		111
++#define JH7110_SYSCLK_IOMUX_APB			112
++#define JH7110_SYSCLK_MAILBOX_APB		113
++#define JH7110_SYSCLK_INT_CTRL_APB		114
++#define JH7110_SYSCLK_CAN0_APB			115
++#define JH7110_SYSCLK_CAN0_TIMER		116
++#define JH7110_SYSCLK_CAN0_CAN			117
++#define JH7110_SYSCLK_CAN1_APB			118
++#define JH7110_SYSCLK_CAN1_TIMER		119
++#define JH7110_SYSCLK_CAN1_CAN			120
++#define JH7110_SYSCLK_PWM_APB			121
++#define JH7110_SYSCLK_WDT_APB			122
++#define JH7110_SYSCLK_WDT_CORE			123
++#define JH7110_SYSCLK_TIMER_APB			124
++#define JH7110_SYSCLK_TIMER0			125
++#define JH7110_SYSCLK_TIMER1			126
++#define JH7110_SYSCLK_TIMER2			127
++#define JH7110_SYSCLK_TIMER3			128
++#define JH7110_SYSCLK_TEMP_APB			129
++#define JH7110_SYSCLK_TEMP_CORE			130
++#define JH7110_SYSCLK_SPI0_APB			131
++#define JH7110_SYSCLK_SPI1_APB			132
++#define JH7110_SYSCLK_SPI2_APB			133
++#define JH7110_SYSCLK_SPI3_APB			134
++#define JH7110_SYSCLK_SPI4_APB			135
++#define JH7110_SYSCLK_SPI5_APB			136
++#define JH7110_SYSCLK_SPI6_APB			137
++#define JH7110_SYSCLK_I2C0_APB			138
++#define JH7110_SYSCLK_I2C1_APB			139
++#define JH7110_SYSCLK_I2C2_APB			140
++#define JH7110_SYSCLK_I2C3_APB			141
++#define JH7110_SYSCLK_I2C4_APB			142
++#define JH7110_SYSCLK_I2C5_APB			143
++#define JH7110_SYSCLK_I2C6_APB			144
++#define JH7110_SYSCLK_UART0_APB			145
++#define JH7110_SYSCLK_UART0_CORE		146
++#define JH7110_SYSCLK_UART1_APB			147
++#define JH7110_SYSCLK_UART1_CORE		148
++#define JH7110_SYSCLK_UART2_APB			149
++#define JH7110_SYSCLK_UART2_CORE		150
++#define JH7110_SYSCLK_UART3_APB			151
++#define JH7110_SYSCLK_UART3_CORE		152
++#define JH7110_SYSCLK_UART4_APB			153
++#define JH7110_SYSCLK_UART4_CORE		154
++#define JH7110_SYSCLK_UART5_APB			155
++#define JH7110_SYSCLK_UART5_CORE		156
++#define JH7110_SYSCLK_PWMDAC_APB		157
++#define JH7110_SYSCLK_PWMDAC_CORE		158
++#define JH7110_SYSCLK_SPDIF_APB			159
++#define JH7110_SYSCLK_SPDIF_CORE		160
++#define JH7110_SYSCLK_I2STX0_APB		161
++#define JH7110_SYSCLK_I2STX0_BCLK_MST		162
++#define JH7110_SYSCLK_I2STX0_BCLK_MST_INV	163
++#define JH7110_SYSCLK_I2STX0_LRCK_MST		164
++#define JH7110_SYSCLK_I2STX0_BCLK		165
++#define JH7110_SYSCLK_I2STX0_BCLK_INV		166
++#define JH7110_SYSCLK_I2STX0_LRCK		167
++#define JH7110_SYSCLK_I2STX1_APB		168
++#define JH7110_SYSCLK_I2STX1_BCLK_MST		169
++#define JH7110_SYSCLK_I2STX1_BCLK_MST_INV	170
++#define JH7110_SYSCLK_I2STX1_LRCK_MST		171
++#define JH7110_SYSCLK_I2STX1_BCLK		172
++#define JH7110_SYSCLK_I2STX1_BCLK_INV		173
++#define JH7110_SYSCLK_I2STX1_LRCK		174
++#define JH7110_SYSCLK_I2SRX_APB			175
++#define JH7110_SYSCLK_I2SRX_BCLK_MST		176
++#define JH7110_SYSCLK_I2SRX_BCLK_MST_INV	177
++#define JH7110_SYSCLK_I2SRX_LRCK_MST		178
++#define JH7110_SYSCLK_I2SRX_BCLK		179
++#define JH7110_SYSCLK_I2SRX_BCLK_INV		180
++#define JH7110_SYSCLK_I2SRX_LRCK		181
++#define JH7110_SYSCLK_PDM_DMIC			182
++#define JH7110_SYSCLK_PDM_APB			183
++#define JH7110_SYSCLK_TDM_AHB			184
++#define JH7110_SYSCLK_TDM_APB			185
++#define JH7110_SYSCLK_TDM_INTERNAL		186
++#define JH7110_SYSCLK_TDM_TDM			187
++#define JH7110_SYSCLK_TDM_TDM_INV		188
++#define JH7110_SYSCLK_JTAG_CERTIFICATION_TRNG	189
++
++#define JH7110_SYSCLK_END			190
++
++#endif /* __DT_BINDINGS_CLOCK_STARFIVE_JH7110_CRG_H__ */
+--- /dev/null
++++ b/include/dt-bindings/reset/starfive,jh7110-crg.h
+@@ -0,0 +1,142 @@
++/* SPDX-License-Identifier: GPL-2.0 OR MIT */
++/*
++ * Copyright (C) 2022 Emil Renner Berthing <[email protected]>
++ */
++
++#ifndef __DT_BINDINGS_RESET_STARFIVE_JH7110_CRG_H__
++#define __DT_BINDINGS_RESET_STARFIVE_JH7110_CRG_H__
++
++/* SYSCRG resets */
++#define JH7110_SYSRST_JTAG_APB			0
++#define JH7110_SYSRST_SYSCON_APB		1
++#define JH7110_SYSRST_IOMUX_APB			2
++#define JH7110_SYSRST_BUS			3
++#define JH7110_SYSRST_DEBUG			4
++#define JH7110_SYSRST_CORE0			5
++#define JH7110_SYSRST_CORE1			6
++#define JH7110_SYSRST_CORE2			7
++#define JH7110_SYSRST_CORE3			8
++#define JH7110_SYSRST_CORE4			9
++#define JH7110_SYSRST_CORE0_ST			10
++#define JH7110_SYSRST_CORE1_ST			11
++#define JH7110_SYSRST_CORE2_ST			12
++#define JH7110_SYSRST_CORE3_ST			13
++#define JH7110_SYSRST_CORE4_ST			14
++#define JH7110_SYSRST_TRACE0			15
++#define JH7110_SYSRST_TRACE1			16
++#define JH7110_SYSRST_TRACE2			17
++#define JH7110_SYSRST_TRACE3			18
++#define JH7110_SYSRST_TRACE4			19
++#define JH7110_SYSRST_TRACE_COM			20
++#define JH7110_SYSRST_GPU_APB			21
++#define JH7110_SYSRST_GPU_DOMA			22
++#define JH7110_SYSRST_NOC_BUS_APB		23
++#define JH7110_SYSRST_NOC_BUS_AXICFG0_AXI	24
++#define JH7110_SYSRST_NOC_BUS_CPU_AXI		25
++#define JH7110_SYSRST_NOC_BUS_DISP_AXI		26
++#define JH7110_SYSRST_NOC_BUS_GPU_AXI		27
++#define JH7110_SYSRST_NOC_BUS_ISP_AXI		28
++#define JH7110_SYSRST_NOC_BUS_DDRC		29
++#define JH7110_SYSRST_NOC_BUS_STG_AXI		30
++#define JH7110_SYSRST_NOC_BUS_VDEC_AXI		31
++
++#define JH7110_SYSRST_NOC_BUS_VENC_AXI		32
++#define JH7110_SYSRST_AXI_CFG1_AHB		33
++#define JH7110_SYSRST_AXI_CFG1_MAIN		34
++#define JH7110_SYSRST_AXI_CFG0_MAIN		35
++#define JH7110_SYSRST_AXI_CFG0_MAIN_DIV		36
++#define JH7110_SYSRST_AXI_CFG0_HIFI4		37
++#define JH7110_SYSRST_DDR_AXI			38
++#define JH7110_SYSRST_DDR_OSC			39
++#define JH7110_SYSRST_DDR_APB			40
++#define JH7110_SYSRST_ISP_TOP			41
++#define JH7110_SYSRST_ISP_TOP_AXI		42
++#define JH7110_SYSRST_VOUT_TOP_SRC		43
++#define JH7110_SYSRST_CODAJ12_AXI		44
++#define JH7110_SYSRST_CODAJ12_CORE		45
++#define JH7110_SYSRST_CODAJ12_APB		46
++#define JH7110_SYSRST_WAVE511_AXI		47
++#define JH7110_SYSRST_WAVE511_BPU		48
++#define JH7110_SYSRST_WAVE511_VCE		49
++#define JH7110_SYSRST_WAVE511_APB		50
++#define JH7110_SYSRST_VDEC_JPG			51
++#define JH7110_SYSRST_VDEC_MAIN			52
++#define JH7110_SYSRST_AXIMEM0_AXI		53
++#define JH7110_SYSRST_WAVE420L_AXI		54
++#define JH7110_SYSRST_WAVE420L_BPU		55
++#define JH7110_SYSRST_WAVE420L_VCE		56
++#define JH7110_SYSRST_WAVE420L_APB		57
++#define JH7110_SYSRST_AXIMEM1_AXI		58
++#define JH7110_SYSRST_AXIMEM2_AXI		59
++#define JH7110_SYSRST_INTMEM			60
++#define JH7110_SYSRST_QSPI_AHB			61
++#define JH7110_SYSRST_QSPI_APB			62
++#define JH7110_SYSRST_QSPI_REF			63
++
++#define JH7110_SYSRST_SDIO0_AHB			64
++#define JH7110_SYSRST_SDIO1_AHB			65
++#define JH7110_SYSRST_GMAC1_AXI			66
++#define JH7110_SYSRST_GMAC1_AHB			67
++#define JH7110_SYSRST_MAILBOX_APB		68
++#define JH7110_SYSRST_SPI0_APB			69
++#define JH7110_SYSRST_SPI1_APB			70
++#define JH7110_SYSRST_SPI2_APB			71
++#define JH7110_SYSRST_SPI3_APB			72
++#define JH7110_SYSRST_SPI4_APB			73
++#define JH7110_SYSRST_SPI5_APB			74
++#define JH7110_SYSRST_SPI6_APB			75
++#define JH7110_SYSRST_I2C0_APB			76
++#define JH7110_SYSRST_I2C1_APB			77
++#define JH7110_SYSRST_I2C2_APB			78
++#define JH7110_SYSRST_I2C3_APB			79
++#define JH7110_SYSRST_I2C4_APB			80
++#define JH7110_SYSRST_I2C5_APB			81
++#define JH7110_SYSRST_I2C6_APB			82
++#define JH7110_SYSRST_UART0_APB			83
++#define JH7110_SYSRST_UART0_CORE		84
++#define JH7110_SYSRST_UART1_APB			85
++#define JH7110_SYSRST_UART1_CORE		86
++#define JH7110_SYSRST_UART2_APB			87
++#define JH7110_SYSRST_UART2_CORE		88
++#define JH7110_SYSRST_UART3_APB			89
++#define JH7110_SYSRST_UART3_CORE		90
++#define JH7110_SYSRST_UART4_APB			91
++#define JH7110_SYSRST_UART4_CORE		92
++#define JH7110_SYSRST_UART5_APB			93
++#define JH7110_SYSRST_UART5_CORE		94
++#define JH7110_SYSRST_SPDIF_APB			95
++
++#define JH7110_SYSRST_PWMDAC_APB		96
++#define JH7110_SYSRST_PDM_DMIC			97
++#define JH7110_SYSRST_PDM_APB			98
++#define JH7110_SYSRST_I2SRX_APB			99
++#define JH7110_SYSRST_I2SRX_BCLK		100
++#define JH7110_SYSRST_I2STX0_APB		101
++#define JH7110_SYSRST_I2STX0_BCLK		102
++#define JH7110_SYSRST_I2STX1_APB		103
++#define JH7110_SYSRST_I2STX1_BCLK		104
++#define JH7110_SYSRST_TDM_AHB			105
++#define JH7110_SYSRST_TDM_CORE			106
++#define JH7110_SYSRST_TDM_APB			107
++#define JH7110_SYSRST_PWM_APB			108
++#define JH7110_SYSRST_WDT_APB			109
++#define JH7110_SYSRST_WDT_CORE			110
++#define JH7110_SYSRST_CAN0_APB			111
++#define JH7110_SYSRST_CAN0_CORE			112
++#define JH7110_SYSRST_CAN0_TIMER		113
++#define JH7110_SYSRST_CAN1_APB			114
++#define JH7110_SYSRST_CAN1_CORE			115
++#define JH7110_SYSRST_CAN1_TIMER		116
++#define JH7110_SYSRST_TIMER_APB			117
++#define JH7110_SYSRST_TIMER0			118
++#define JH7110_SYSRST_TIMER1			119
++#define JH7110_SYSRST_TIMER2			120
++#define JH7110_SYSRST_TIMER3			121
++#define JH7110_SYSRST_INT_CTRL_APB		122
++#define JH7110_SYSRST_TEMP_APB			123
++#define JH7110_SYSRST_TEMP_CORE			124
++#define JH7110_SYSRST_JTAG_CERTIFICATION	125
++
++#define JH7110_SYSRST_END			126
++
++#endif /* __DT_BINDINGS_RESET_STARFIVE_JH7110_CRG_H__ */

+ 176 - 0
target/linux/starfive/patches-6.1/0002-dt-bindings-clock-Add-StarFive-JH7110-always-on-cloc.patch

@@ -0,0 +1,176 @@
+From cd833f484009f37be57a2aa09257af6e8c1b25b6 Mon Sep 17 00:00:00 2001
+From: Emil Renner Berthing <[email protected]>
+Date: Sat, 1 Apr 2023 19:19:14 +0800
+Subject: [PATCH 002/122] dt-bindings: clock: Add StarFive JH7110 always-on
+ clock and reset generator
+
+Add bindings for the always-on clock and reset generator (AONCRG) on the
+JH7110 RISC-V SoC by StarFive Ltd.
+
+Reviewed-by: Conor Dooley <[email protected]>
+Reviewed-by: Rob Herring <[email protected]>
+Reviewed-by: Emil Renner Berthing <[email protected]>
+Signed-off-by: Emil Renner Berthing <[email protected]>
+Signed-off-by: Hal Feng <[email protected]>
+Signed-off-by: Conor Dooley <[email protected]>
+---
+ .../clock/starfive,jh7110-aoncrg.yaml         | 107 ++++++++++++++++++
+ .../dt-bindings/clock/starfive,jh7110-crg.h   |  18 +++
+ .../dt-bindings/reset/starfive,jh7110-crg.h   |  12 ++
+ 3 files changed, 137 insertions(+)
+ create mode 100644 Documentation/devicetree/bindings/clock/starfive,jh7110-aoncrg.yaml
+
+--- /dev/null
++++ b/Documentation/devicetree/bindings/clock/starfive,jh7110-aoncrg.yaml
+@@ -0,0 +1,107 @@
++# SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause
++%YAML 1.2
++---
++$id: http://devicetree.org/schemas/clock/starfive,jh7110-aoncrg.yaml#
++$schema: http://devicetree.org/meta-schemas/core.yaml#
++
++title: StarFive JH7110 Always-On Clock and Reset Generator
++
++maintainers:
++  - Emil Renner Berthing <[email protected]>
++
++properties:
++  compatible:
++    const: starfive,jh7110-aoncrg
++
++  reg:
++    maxItems: 1
++
++  clocks:
++    oneOf:
++      - items:
++          - description: Main Oscillator (24 MHz)
++          - description: GMAC0 RMII reference or GMAC0 RGMII RX
++          - description: STG AXI/AHB
++          - description: APB Bus
++          - description: GMAC0 GTX
++
++      - items:
++          - description: Main Oscillator (24 MHz)
++          - description: GMAC0 RMII reference or GMAC0 RGMII RX
++          - description: STG AXI/AHB or GMAC0 RGMII RX
++          - description: APB Bus or STG AXI/AHB
++          - description: GMAC0 GTX or APB Bus
++          - description: RTC Oscillator (32.768 kHz) or GMAC0 GTX
++
++      - items:
++          - description: Main Oscillator (24 MHz)
++          - description: GMAC0 RMII reference
++          - description: GMAC0 RGMII RX
++          - description: STG AXI/AHB
++          - description: APB Bus
++          - description: GMAC0 GTX
++          - description: RTC Oscillator (32.768 kHz)
++
++  clock-names:
++    oneOf:
++      - minItems: 5
++        items:
++          - const: osc
++          - enum:
++              - gmac0_rmii_refin
++              - gmac0_rgmii_rxin
++          - const: stg_axiahb
++          - const: apb_bus
++          - const: gmac0_gtxclk
++          - const: rtc_osc
++
++      - minItems: 6
++        items:
++          - const: osc
++          - const: gmac0_rmii_refin
++          - const: gmac0_rgmii_rxin
++          - const: stg_axiahb
++          - const: apb_bus
++          - const: gmac0_gtxclk
++          - const: rtc_osc
++
++  '#clock-cells':
++    const: 1
++    description:
++      See <dt-bindings/clock/starfive,jh7110-crg.h> for valid indices.
++
++  '#reset-cells':
++    const: 1
++    description:
++      See <dt-bindings/reset/starfive,jh7110-crg.h> for valid indices.
++
++required:
++  - compatible
++  - reg
++  - clocks
++  - clock-names
++  - '#clock-cells'
++  - '#reset-cells'
++
++additionalProperties: false
++
++examples:
++  - |
++    #include <dt-bindings/clock/starfive,jh7110-crg.h>
++
++    clock-controller@17000000 {
++        compatible = "starfive,jh7110-aoncrg";
++        reg = <0x17000000 0x10000>;
++        clocks = <&osc>, <&gmac0_rmii_refin>,
++                 <&gmac0_rgmii_rxin>,
++                 <&syscrg JH7110_SYSCLK_STG_AXIAHB>,
++                 <&syscrg JH7110_SYSCLK_APB_BUS>,
++                 <&syscrg JH7110_SYSCLK_GMAC0_GTXCLK>,
++                 <&rtc_osc>;
++        clock-names = "osc", "gmac0_rmii_refin",
++                      "gmac0_rgmii_rxin", "stg_axiahb",
++                      "apb_bus", "gmac0_gtxclk",
++                      "rtc_osc";
++        #clock-cells = <1>;
++        #reset-cells = <1>;
++    };
+--- a/include/dt-bindings/clock/starfive,jh7110-crg.h
++++ b/include/dt-bindings/clock/starfive,jh7110-crg.h
+@@ -200,4 +200,22 @@
+ 
+ #define JH7110_SYSCLK_END			190
+ 
++/* AONCRG clocks */
++#define JH7110_AONCLK_OSC_DIV4			0
++#define JH7110_AONCLK_APB_FUNC			1
++#define JH7110_AONCLK_GMAC0_AHB			2
++#define JH7110_AONCLK_GMAC0_AXI			3
++#define JH7110_AONCLK_GMAC0_RMII_RTX		4
++#define JH7110_AONCLK_GMAC0_TX			5
++#define JH7110_AONCLK_GMAC0_TX_INV		6
++#define JH7110_AONCLK_GMAC0_RX			7
++#define JH7110_AONCLK_GMAC0_RX_INV		8
++#define JH7110_AONCLK_OTPC_APB			9
++#define JH7110_AONCLK_RTC_APB			10
++#define JH7110_AONCLK_RTC_INTERNAL		11
++#define JH7110_AONCLK_RTC_32K			12
++#define JH7110_AONCLK_RTC_CAL			13
++
++#define JH7110_AONCLK_END			14
++
+ #endif /* __DT_BINDINGS_CLOCK_STARFIVE_JH7110_CRG_H__ */
+--- a/include/dt-bindings/reset/starfive,jh7110-crg.h
++++ b/include/dt-bindings/reset/starfive,jh7110-crg.h
+@@ -139,4 +139,16 @@
+ 
+ #define JH7110_SYSRST_END			126
+ 
++/* AONCRG resets */
++#define JH7110_AONRST_GMAC0_AXI			0
++#define JH7110_AONRST_GMAC0_AHB			1
++#define JH7110_AONRST_IOMUX			2
++#define JH7110_AONRST_PMU_APB			3
++#define JH7110_AONRST_PMU_WKUP			4
++#define JH7110_AONRST_RTC_APB			5
++#define JH7110_AONRST_RTC_CAL			6
++#define JH7110_AONRST_RTC_32K			7
++
++#define JH7110_AONRST_END			8
++
+ #endif /* __DT_BINDINGS_RESET_STARFIVE_JH7110_CRG_H__ */

+ 53 - 0
target/linux/starfive/patches-6.1/0003-clk-starfive-Replace-SOC_STARFIVE-with-ARCH_STARFIVE.patch

@@ -0,0 +1,53 @@
+From 124f322d1c42232e439ea9a356d68caf1d0656f3 Mon Sep 17 00:00:00 2001
+From: Hal Feng <[email protected]>
+Date: Sat, 1 Apr 2023 19:19:15 +0800
+Subject: [PATCH 003/122] clk: starfive: Replace SOC_STARFIVE with
+ ARCH_STARFIVE
+
+Using ARCH_FOO symbol is preferred than SOC_FOO.
+Set obj-y for starfive/ in Makefile, so the StarFive drivers
+can be compiled with COMPILE_TEST=y but ARCH_STARFIVE=n.
+
+Reviewed-by: Conor Dooley <[email protected]>
+Reviewed-by: Heiko Stuebner <[email protected]>
+Reviewed-by: Emil Renner Berthing <[email protected]>
+Signed-off-by: Hal Feng <[email protected]>
+Signed-off-by: Conor Dooley <[email protected]>
+---
+ drivers/clk/Makefile         | 2 +-
+ drivers/clk/starfive/Kconfig | 6 +++---
+ 2 files changed, 4 insertions(+), 4 deletions(-)
+
+--- a/drivers/clk/Makefile
++++ b/drivers/clk/Makefile
+@@ -117,7 +117,7 @@ obj-$(CONFIG_PLAT_SPEAR)		+= spear/
+ obj-y					+= sprd/
+ obj-$(CONFIG_ARCH_STI)			+= st/
+ obj-$(CONFIG_ARCH_STM32)		+= stm32/
+-obj-$(CONFIG_SOC_STARFIVE)		+= starfive/
++obj-y					+= starfive/
+ obj-$(CONFIG_ARCH_SUNXI)		+= sunxi/
+ obj-y					+= sunxi-ng/
+ obj-$(CONFIG_ARCH_TEGRA)		+= tegra/
+--- a/drivers/clk/starfive/Kconfig
++++ b/drivers/clk/starfive/Kconfig
+@@ -2,8 +2,8 @@
+ 
+ config CLK_STARFIVE_JH7100
+ 	bool "StarFive JH7100 clock support"
+-	depends on SOC_STARFIVE || COMPILE_TEST
+-	default SOC_STARFIVE
++	depends on ARCH_STARFIVE || COMPILE_TEST
++	default ARCH_STARFIVE
+ 	help
+ 	  Say yes here to support the clock controller on the StarFive JH7100
+ 	  SoC.
+@@ -11,7 +11,7 @@ config CLK_STARFIVE_JH7100
+ config CLK_STARFIVE_JH7100_AUDIO
+ 	tristate "StarFive JH7100 audio clock support"
+ 	depends on CLK_STARFIVE_JH7100
+-	default m if SOC_STARFIVE
++	default m if ARCH_STARFIVE
+ 	help
+ 	  Say Y or M here to support the audio clocks on the StarFive JH7100
+ 	  SoC.

+ 749 - 0
target/linux/starfive/patches-6.1/0004-clk-starfive-Factor-out-common-JH7100-and-JH7110-cod.patch

@@ -0,0 +1,749 @@
+From 6f14eb919e5b92076e17aec5388655348963eef7 Mon Sep 17 00:00:00 2001
+From: Emil Renner Berthing <[email protected]>
+Date: Sat, 1 Apr 2023 19:19:16 +0800
+Subject: [PATCH 004/122] clk: starfive: Factor out common JH7100 and JH7110
+ code
+
+The clock control registers on the StarFive JH7100 and JH7110 work
+identically, so factor out the code then drivers for the two SoCs
+can share it without depending on each other. No functional change.
+
+Tested-by: Tommaso Merciai <[email protected]>
+Reviewed-by: Conor Dooley <[email protected]>
+Reviewed-by: Emil Renner Berthing <[email protected]>
+Signed-off-by: Emil Renner Berthing <[email protected]>
+Signed-off-by: Hal Feng <[email protected]>
+Signed-off-by: Conor Dooley <[email protected]>
+---
+ drivers/clk/starfive/Kconfig               |   5 +
+ drivers/clk/starfive/Makefile              |   3 +-
+ drivers/clk/starfive/clk-starfive-jh7100.c | 325 --------------------
+ drivers/clk/starfive/clk-starfive-jh7100.h |   2 +
+ drivers/clk/starfive/clk-starfive-jh71x0.c | 333 +++++++++++++++++++++
+ 5 files changed, 342 insertions(+), 326 deletions(-)
+ create mode 100644 drivers/clk/starfive/clk-starfive-jh71x0.c
+
+--- a/drivers/clk/starfive/Kconfig
++++ b/drivers/clk/starfive/Kconfig
+@@ -1,8 +1,12 @@
+ # SPDX-License-Identifier: GPL-2.0
+ 
++config CLK_STARFIVE_JH71X0
++	bool
++
+ config CLK_STARFIVE_JH7100
+ 	bool "StarFive JH7100 clock support"
+ 	depends on ARCH_STARFIVE || COMPILE_TEST
++	select CLK_STARFIVE_JH71X0
+ 	default ARCH_STARFIVE
+ 	help
+ 	  Say yes here to support the clock controller on the StarFive JH7100
+@@ -11,6 +15,7 @@ config CLK_STARFIVE_JH7100
+ config CLK_STARFIVE_JH7100_AUDIO
+ 	tristate "StarFive JH7100 audio clock support"
+ 	depends on CLK_STARFIVE_JH7100
++	select CLK_STARFIVE_JH71X0
+ 	default m if ARCH_STARFIVE
+ 	help
+ 	  Say Y or M here to support the audio clocks on the StarFive JH7100
+--- a/drivers/clk/starfive/Makefile
++++ b/drivers/clk/starfive/Makefile
+@@ -1,4 +1,5 @@
+ # SPDX-License-Identifier: GPL-2.0
+-# StarFive Clock
++obj-$(CONFIG_CLK_STARFIVE_JH71X0)	+= clk-starfive-jh71x0.o
++
+ obj-$(CONFIG_CLK_STARFIVE_JH7100)	+= clk-starfive-jh7100.o
+ obj-$(CONFIG_CLK_STARFIVE_JH7100_AUDIO)	+= clk-starfive-jh7100-audio.o
+--- a/drivers/clk/starfive/clk-starfive-jh7100.c
++++ b/drivers/clk/starfive/clk-starfive-jh7100.c
+@@ -7,15 +7,10 @@
+  * Copyright (C) 2021 Emil Renner Berthing <[email protected]>
+  */
+ 
+-#include <linux/bits.h>
+ #include <linux/clk-provider.h>
+-#include <linux/debugfs.h>
+ #include <linux/device.h>
+ #include <linux/init.h>
+-#include <linux/io.h>
+-#include <linux/kernel.h>
+ #include <linux/mod_devicetable.h>
+-#include <linux/module.h>
+ #include <linux/platform_device.h>
+ 
+ #include <dt-bindings/clock/starfive-jh7100.h>
+@@ -269,326 +264,6 @@ static const struct jh7100_clk_data jh71
+ 	JH7100_GATE(JH7100_CLK_SYSERR_APB, "syserr_apb", 0, JH7100_CLK_APB2_BUS),
+ };
+ 
+-static struct jh7100_clk *jh7100_clk_from(struct clk_hw *hw)
+-{
+-	return container_of(hw, struct jh7100_clk, hw);
+-}
+-
+-static struct jh7100_clk_priv *jh7100_priv_from(struct jh7100_clk *clk)
+-{
+-	return container_of(clk, struct jh7100_clk_priv, reg[clk->idx]);
+-}
+-
+-static u32 jh7100_clk_reg_get(struct jh7100_clk *clk)
+-{
+-	struct jh7100_clk_priv *priv = jh7100_priv_from(clk);
+-	void __iomem *reg = priv->base + 4 * clk->idx;
+-
+-	return readl_relaxed(reg);
+-}
+-
+-static void jh7100_clk_reg_rmw(struct jh7100_clk *clk, u32 mask, u32 value)
+-{
+-	struct jh7100_clk_priv *priv = jh7100_priv_from(clk);
+-	void __iomem *reg = priv->base + 4 * clk->idx;
+-	unsigned long flags;
+-
+-	spin_lock_irqsave(&priv->rmw_lock, flags);
+-	value |= readl_relaxed(reg) & ~mask;
+-	writel_relaxed(value, reg);
+-	spin_unlock_irqrestore(&priv->rmw_lock, flags);
+-}
+-
+-static int jh7100_clk_enable(struct clk_hw *hw)
+-{
+-	struct jh7100_clk *clk = jh7100_clk_from(hw);
+-
+-	jh7100_clk_reg_rmw(clk, JH7100_CLK_ENABLE, JH7100_CLK_ENABLE);
+-	return 0;
+-}
+-
+-static void jh7100_clk_disable(struct clk_hw *hw)
+-{
+-	struct jh7100_clk *clk = jh7100_clk_from(hw);
+-
+-	jh7100_clk_reg_rmw(clk, JH7100_CLK_ENABLE, 0);
+-}
+-
+-static int jh7100_clk_is_enabled(struct clk_hw *hw)
+-{
+-	struct jh7100_clk *clk = jh7100_clk_from(hw);
+-
+-	return !!(jh7100_clk_reg_get(clk) & JH7100_CLK_ENABLE);
+-}
+-
+-static unsigned long jh7100_clk_recalc_rate(struct clk_hw *hw,
+-					    unsigned long parent_rate)
+-{
+-	struct jh7100_clk *clk = jh7100_clk_from(hw);
+-	u32 div = jh7100_clk_reg_get(clk) & JH7100_CLK_DIV_MASK;
+-
+-	return div ? parent_rate / div : 0;
+-}
+-
+-static int jh7100_clk_determine_rate(struct clk_hw *hw,
+-				     struct clk_rate_request *req)
+-{
+-	struct jh7100_clk *clk = jh7100_clk_from(hw);
+-	unsigned long parent = req->best_parent_rate;
+-	unsigned long rate = clamp(req->rate, req->min_rate, req->max_rate);
+-	unsigned long div = min_t(unsigned long, DIV_ROUND_UP(parent, rate), clk->max_div);
+-	unsigned long result = parent / div;
+-
+-	/*
+-	 * we want the result clamped by min_rate and max_rate if possible:
+-	 * case 1: div hits the max divider value, which means it's less than
+-	 * parent / rate, so the result is greater than rate and min_rate in
+-	 * particular. we can't do anything about result > max_rate because the
+-	 * divider doesn't go any further.
+-	 * case 2: div = DIV_ROUND_UP(parent, rate) which means the result is
+-	 * always lower or equal to rate and max_rate. however the result may
+-	 * turn out lower than min_rate, but then the next higher rate is fine:
+-	 *   div - 1 = ceil(parent / rate) - 1 < parent / rate
+-	 * and thus
+-	 *   min_rate <= rate < parent / (div - 1)
+-	 */
+-	if (result < req->min_rate && div > 1)
+-		result = parent / (div - 1);
+-
+-	req->rate = result;
+-	return 0;
+-}
+-
+-static int jh7100_clk_set_rate(struct clk_hw *hw,
+-			       unsigned long rate,
+-			       unsigned long parent_rate)
+-{
+-	struct jh7100_clk *clk = jh7100_clk_from(hw);
+-	unsigned long div = clamp(DIV_ROUND_CLOSEST(parent_rate, rate),
+-				  1UL, (unsigned long)clk->max_div);
+-
+-	jh7100_clk_reg_rmw(clk, JH7100_CLK_DIV_MASK, div);
+-	return 0;
+-}
+-
+-static unsigned long jh7100_clk_frac_recalc_rate(struct clk_hw *hw,
+-						 unsigned long parent_rate)
+-{
+-	struct jh7100_clk *clk = jh7100_clk_from(hw);
+-	u32 reg = jh7100_clk_reg_get(clk);
+-	unsigned long div100 = 100 * (reg & JH7100_CLK_INT_MASK) +
+-			       ((reg & JH7100_CLK_FRAC_MASK) >> JH7100_CLK_FRAC_SHIFT);
+-
+-	return (div100 >= JH7100_CLK_FRAC_MIN) ? 100 * parent_rate / div100 : 0;
+-}
+-
+-static int jh7100_clk_frac_determine_rate(struct clk_hw *hw,
+-					  struct clk_rate_request *req)
+-{
+-	unsigned long parent100 = 100 * req->best_parent_rate;
+-	unsigned long rate = clamp(req->rate, req->min_rate, req->max_rate);
+-	unsigned long div100 = clamp(DIV_ROUND_CLOSEST(parent100, rate),
+-				     JH7100_CLK_FRAC_MIN, JH7100_CLK_FRAC_MAX);
+-	unsigned long result = parent100 / div100;
+-
+-	/* clamp the result as in jh7100_clk_determine_rate() above */
+-	if (result > req->max_rate && div100 < JH7100_CLK_FRAC_MAX)
+-		result = parent100 / (div100 + 1);
+-	if (result < req->min_rate && div100 > JH7100_CLK_FRAC_MIN)
+-		result = parent100 / (div100 - 1);
+-
+-	req->rate = result;
+-	return 0;
+-}
+-
+-static int jh7100_clk_frac_set_rate(struct clk_hw *hw,
+-				    unsigned long rate,
+-				    unsigned long parent_rate)
+-{
+-	struct jh7100_clk *clk = jh7100_clk_from(hw);
+-	unsigned long div100 = clamp(DIV_ROUND_CLOSEST(100 * parent_rate, rate),
+-				     JH7100_CLK_FRAC_MIN, JH7100_CLK_FRAC_MAX);
+-	u32 value = ((div100 % 100) << JH7100_CLK_FRAC_SHIFT) | (div100 / 100);
+-
+-	jh7100_clk_reg_rmw(clk, JH7100_CLK_DIV_MASK, value);
+-	return 0;
+-}
+-
+-static u8 jh7100_clk_get_parent(struct clk_hw *hw)
+-{
+-	struct jh7100_clk *clk = jh7100_clk_from(hw);
+-	u32 value = jh7100_clk_reg_get(clk);
+-
+-	return (value & JH7100_CLK_MUX_MASK) >> JH7100_CLK_MUX_SHIFT;
+-}
+-
+-static int jh7100_clk_set_parent(struct clk_hw *hw, u8 index)
+-{
+-	struct jh7100_clk *clk = jh7100_clk_from(hw);
+-	u32 value = (u32)index << JH7100_CLK_MUX_SHIFT;
+-
+-	jh7100_clk_reg_rmw(clk, JH7100_CLK_MUX_MASK, value);
+-	return 0;
+-}
+-
+-static int jh7100_clk_mux_determine_rate(struct clk_hw *hw,
+-					 struct clk_rate_request *req)
+-{
+-	return clk_mux_determine_rate_flags(hw, req, 0);
+-}
+-
+-static int jh7100_clk_get_phase(struct clk_hw *hw)
+-{
+-	struct jh7100_clk *clk = jh7100_clk_from(hw);
+-	u32 value = jh7100_clk_reg_get(clk);
+-
+-	return (value & JH7100_CLK_INVERT) ? 180 : 0;
+-}
+-
+-static int jh7100_clk_set_phase(struct clk_hw *hw, int degrees)
+-{
+-	struct jh7100_clk *clk = jh7100_clk_from(hw);
+-	u32 value;
+-
+-	if (degrees == 0)
+-		value = 0;
+-	else if (degrees == 180)
+-		value = JH7100_CLK_INVERT;
+-	else
+-		return -EINVAL;
+-
+-	jh7100_clk_reg_rmw(clk, JH7100_CLK_INVERT, value);
+-	return 0;
+-}
+-
+-#ifdef CONFIG_DEBUG_FS
+-static void jh7100_clk_debug_init(struct clk_hw *hw, struct dentry *dentry)
+-{
+-	static const struct debugfs_reg32 jh7100_clk_reg = {
+-		.name = "CTRL",
+-		.offset = 0,
+-	};
+-	struct jh7100_clk *clk = jh7100_clk_from(hw);
+-	struct jh7100_clk_priv *priv = jh7100_priv_from(clk);
+-	struct debugfs_regset32 *regset;
+-
+-	regset = devm_kzalloc(priv->dev, sizeof(*regset), GFP_KERNEL);
+-	if (!regset)
+-		return;
+-
+-	regset->regs = &jh7100_clk_reg;
+-	regset->nregs = 1;
+-	regset->base = priv->base + 4 * clk->idx;
+-
+-	debugfs_create_regset32("registers", 0400, dentry, regset);
+-}
+-#else
+-#define jh7100_clk_debug_init NULL
+-#endif
+-
+-static const struct clk_ops jh7100_clk_gate_ops = {
+-	.enable = jh7100_clk_enable,
+-	.disable = jh7100_clk_disable,
+-	.is_enabled = jh7100_clk_is_enabled,
+-	.debug_init = jh7100_clk_debug_init,
+-};
+-
+-static const struct clk_ops jh7100_clk_div_ops = {
+-	.recalc_rate = jh7100_clk_recalc_rate,
+-	.determine_rate = jh7100_clk_determine_rate,
+-	.set_rate = jh7100_clk_set_rate,
+-	.debug_init = jh7100_clk_debug_init,
+-};
+-
+-static const struct clk_ops jh7100_clk_fdiv_ops = {
+-	.recalc_rate = jh7100_clk_frac_recalc_rate,
+-	.determine_rate = jh7100_clk_frac_determine_rate,
+-	.set_rate = jh7100_clk_frac_set_rate,
+-	.debug_init = jh7100_clk_debug_init,
+-};
+-
+-static const struct clk_ops jh7100_clk_gdiv_ops = {
+-	.enable = jh7100_clk_enable,
+-	.disable = jh7100_clk_disable,
+-	.is_enabled = jh7100_clk_is_enabled,
+-	.recalc_rate = jh7100_clk_recalc_rate,
+-	.determine_rate = jh7100_clk_determine_rate,
+-	.set_rate = jh7100_clk_set_rate,
+-	.debug_init = jh7100_clk_debug_init,
+-};
+-
+-static const struct clk_ops jh7100_clk_mux_ops = {
+-	.determine_rate = jh7100_clk_mux_determine_rate,
+-	.set_parent = jh7100_clk_set_parent,
+-	.get_parent = jh7100_clk_get_parent,
+-	.debug_init = jh7100_clk_debug_init,
+-};
+-
+-static const struct clk_ops jh7100_clk_gmux_ops = {
+-	.enable = jh7100_clk_enable,
+-	.disable = jh7100_clk_disable,
+-	.is_enabled = jh7100_clk_is_enabled,
+-	.determine_rate = jh7100_clk_mux_determine_rate,
+-	.set_parent = jh7100_clk_set_parent,
+-	.get_parent = jh7100_clk_get_parent,
+-	.debug_init = jh7100_clk_debug_init,
+-};
+-
+-static const struct clk_ops jh7100_clk_mdiv_ops = {
+-	.recalc_rate = jh7100_clk_recalc_rate,
+-	.determine_rate = jh7100_clk_determine_rate,
+-	.get_parent = jh7100_clk_get_parent,
+-	.set_parent = jh7100_clk_set_parent,
+-	.set_rate = jh7100_clk_set_rate,
+-	.debug_init = jh7100_clk_debug_init,
+-};
+-
+-static const struct clk_ops jh7100_clk_gmd_ops = {
+-	.enable = jh7100_clk_enable,
+-	.disable = jh7100_clk_disable,
+-	.is_enabled = jh7100_clk_is_enabled,
+-	.recalc_rate = jh7100_clk_recalc_rate,
+-	.determine_rate = jh7100_clk_determine_rate,
+-	.get_parent = jh7100_clk_get_parent,
+-	.set_parent = jh7100_clk_set_parent,
+-	.set_rate = jh7100_clk_set_rate,
+-	.debug_init = jh7100_clk_debug_init,
+-};
+-
+-static const struct clk_ops jh7100_clk_inv_ops = {
+-	.get_phase = jh7100_clk_get_phase,
+-	.set_phase = jh7100_clk_set_phase,
+-	.debug_init = jh7100_clk_debug_init,
+-};
+-
+-const struct clk_ops *starfive_jh7100_clk_ops(u32 max)
+-{
+-	if (max & JH7100_CLK_DIV_MASK) {
+-		if (max & JH7100_CLK_MUX_MASK) {
+-			if (max & JH7100_CLK_ENABLE)
+-				return &jh7100_clk_gmd_ops;
+-			return &jh7100_clk_mdiv_ops;
+-		}
+-		if (max & JH7100_CLK_ENABLE)
+-			return &jh7100_clk_gdiv_ops;
+-		if (max == JH7100_CLK_FRAC_MAX)
+-			return &jh7100_clk_fdiv_ops;
+-		return &jh7100_clk_div_ops;
+-	}
+-
+-	if (max & JH7100_CLK_MUX_MASK) {
+-		if (max & JH7100_CLK_ENABLE)
+-			return &jh7100_clk_gmux_ops;
+-		return &jh7100_clk_mux_ops;
+-	}
+-
+-	if (max & JH7100_CLK_ENABLE)
+-		return &jh7100_clk_gate_ops;
+-
+-	return &jh7100_clk_inv_ops;
+-}
+-EXPORT_SYMBOL_GPL(starfive_jh7100_clk_ops);
+-
+ static struct clk_hw *jh7100_clk_get(struct of_phandle_args *clkspec, void *data)
+ {
+ 	struct jh7100_clk_priv *priv = data;
+--- a/drivers/clk/starfive/clk-starfive-jh7100.h
++++ b/drivers/clk/starfive/clk-starfive-jh7100.h
+@@ -4,6 +4,8 @@
+ 
+ #include <linux/bits.h>
+ #include <linux/clk-provider.h>
++#include <linux/device.h>
++#include <linux/spinlock.h>
+ 
+ /* register fields */
+ #define JH7100_CLK_ENABLE	BIT(31)
+--- /dev/null
++++ b/drivers/clk/starfive/clk-starfive-jh71x0.c
+@@ -0,0 +1,333 @@
++// SPDX-License-Identifier: GPL-2.0
++/*
++ * StarFive JH7100 Clock Generator Driver
++ *
++ * Copyright (C) 2021-2022 Emil Renner Berthing <[email protected]>
++ */
++
++#include <linux/clk-provider.h>
++#include <linux/debugfs.h>
++#include <linux/device.h>
++#include <linux/io.h>
++
++#include "clk-starfive-jh7100.h"
++
++static struct jh7100_clk *jh7100_clk_from(struct clk_hw *hw)
++{
++	return container_of(hw, struct jh7100_clk, hw);
++}
++
++static struct jh7100_clk_priv *jh7100_priv_from(struct jh7100_clk *clk)
++{
++	return container_of(clk, struct jh7100_clk_priv, reg[clk->idx]);
++}
++
++static u32 jh7100_clk_reg_get(struct jh7100_clk *clk)
++{
++	struct jh7100_clk_priv *priv = jh7100_priv_from(clk);
++	void __iomem *reg = priv->base + 4 * clk->idx;
++
++	return readl_relaxed(reg);
++}
++
++static void jh7100_clk_reg_rmw(struct jh7100_clk *clk, u32 mask, u32 value)
++{
++	struct jh7100_clk_priv *priv = jh7100_priv_from(clk);
++	void __iomem *reg = priv->base + 4 * clk->idx;
++	unsigned long flags;
++
++	spin_lock_irqsave(&priv->rmw_lock, flags);
++	value |= readl_relaxed(reg) & ~mask;
++	writel_relaxed(value, reg);
++	spin_unlock_irqrestore(&priv->rmw_lock, flags);
++}
++
++static int jh7100_clk_enable(struct clk_hw *hw)
++{
++	struct jh7100_clk *clk = jh7100_clk_from(hw);
++
++	jh7100_clk_reg_rmw(clk, JH7100_CLK_ENABLE, JH7100_CLK_ENABLE);
++	return 0;
++}
++
++static void jh7100_clk_disable(struct clk_hw *hw)
++{
++	struct jh7100_clk *clk = jh7100_clk_from(hw);
++
++	jh7100_clk_reg_rmw(clk, JH7100_CLK_ENABLE, 0);
++}
++
++static int jh7100_clk_is_enabled(struct clk_hw *hw)
++{
++	struct jh7100_clk *clk = jh7100_clk_from(hw);
++
++	return !!(jh7100_clk_reg_get(clk) & JH7100_CLK_ENABLE);
++}
++
++static unsigned long jh7100_clk_recalc_rate(struct clk_hw *hw,
++					    unsigned long parent_rate)
++{
++	struct jh7100_clk *clk = jh7100_clk_from(hw);
++	u32 div = jh7100_clk_reg_get(clk) & JH7100_CLK_DIV_MASK;
++
++	return div ? parent_rate / div : 0;
++}
++
++static int jh7100_clk_determine_rate(struct clk_hw *hw,
++				     struct clk_rate_request *req)
++{
++	struct jh7100_clk *clk = jh7100_clk_from(hw);
++	unsigned long parent = req->best_parent_rate;
++	unsigned long rate = clamp(req->rate, req->min_rate, req->max_rate);
++	unsigned long div = min_t(unsigned long, DIV_ROUND_UP(parent, rate), clk->max_div);
++	unsigned long result = parent / div;
++
++	/*
++	 * we want the result clamped by min_rate and max_rate if possible:
++	 * case 1: div hits the max divider value, which means it's less than
++	 * parent / rate, so the result is greater than rate and min_rate in
++	 * particular. we can't do anything about result > max_rate because the
++	 * divider doesn't go any further.
++	 * case 2: div = DIV_ROUND_UP(parent, rate) which means the result is
++	 * always lower or equal to rate and max_rate. however the result may
++	 * turn out lower than min_rate, but then the next higher rate is fine:
++	 *   div - 1 = ceil(parent / rate) - 1 < parent / rate
++	 * and thus
++	 *   min_rate <= rate < parent / (div - 1)
++	 */
++	if (result < req->min_rate && div > 1)
++		result = parent / (div - 1);
++
++	req->rate = result;
++	return 0;
++}
++
++static int jh7100_clk_set_rate(struct clk_hw *hw,
++			       unsigned long rate,
++			       unsigned long parent_rate)
++{
++	struct jh7100_clk *clk = jh7100_clk_from(hw);
++	unsigned long div = clamp(DIV_ROUND_CLOSEST(parent_rate, rate),
++				  1UL, (unsigned long)clk->max_div);
++
++	jh7100_clk_reg_rmw(clk, JH7100_CLK_DIV_MASK, div);
++	return 0;
++}
++
++static unsigned long jh7100_clk_frac_recalc_rate(struct clk_hw *hw,
++						 unsigned long parent_rate)
++{
++	struct jh7100_clk *clk = jh7100_clk_from(hw);
++	u32 reg = jh7100_clk_reg_get(clk);
++	unsigned long div100 = 100 * (reg & JH7100_CLK_INT_MASK) +
++			       ((reg & JH7100_CLK_FRAC_MASK) >> JH7100_CLK_FRAC_SHIFT);
++
++	return (div100 >= JH7100_CLK_FRAC_MIN) ? 100 * parent_rate / div100 : 0;
++}
++
++static int jh7100_clk_frac_determine_rate(struct clk_hw *hw,
++					  struct clk_rate_request *req)
++{
++	unsigned long parent100 = 100 * req->best_parent_rate;
++	unsigned long rate = clamp(req->rate, req->min_rate, req->max_rate);
++	unsigned long div100 = clamp(DIV_ROUND_CLOSEST(parent100, rate),
++				     JH7100_CLK_FRAC_MIN, JH7100_CLK_FRAC_MAX);
++	unsigned long result = parent100 / div100;
++
++	/* clamp the result as in jh7100_clk_determine_rate() above */
++	if (result > req->max_rate && div100 < JH7100_CLK_FRAC_MAX)
++		result = parent100 / (div100 + 1);
++	if (result < req->min_rate && div100 > JH7100_CLK_FRAC_MIN)
++		result = parent100 / (div100 - 1);
++
++	req->rate = result;
++	return 0;
++}
++
++static int jh7100_clk_frac_set_rate(struct clk_hw *hw,
++				    unsigned long rate,
++				    unsigned long parent_rate)
++{
++	struct jh7100_clk *clk = jh7100_clk_from(hw);
++	unsigned long div100 = clamp(DIV_ROUND_CLOSEST(100 * parent_rate, rate),
++				     JH7100_CLK_FRAC_MIN, JH7100_CLK_FRAC_MAX);
++	u32 value = ((div100 % 100) << JH7100_CLK_FRAC_SHIFT) | (div100 / 100);
++
++	jh7100_clk_reg_rmw(clk, JH7100_CLK_DIV_MASK, value);
++	return 0;
++}
++
++static u8 jh7100_clk_get_parent(struct clk_hw *hw)
++{
++	struct jh7100_clk *clk = jh7100_clk_from(hw);
++	u32 value = jh7100_clk_reg_get(clk);
++
++	return (value & JH7100_CLK_MUX_MASK) >> JH7100_CLK_MUX_SHIFT;
++}
++
++static int jh7100_clk_set_parent(struct clk_hw *hw, u8 index)
++{
++	struct jh7100_clk *clk = jh7100_clk_from(hw);
++	u32 value = (u32)index << JH7100_CLK_MUX_SHIFT;
++
++	jh7100_clk_reg_rmw(clk, JH7100_CLK_MUX_MASK, value);
++	return 0;
++}
++
++static int jh7100_clk_mux_determine_rate(struct clk_hw *hw,
++					 struct clk_rate_request *req)
++{
++	return clk_mux_determine_rate_flags(hw, req, 0);
++}
++
++static int jh7100_clk_get_phase(struct clk_hw *hw)
++{
++	struct jh7100_clk *clk = jh7100_clk_from(hw);
++	u32 value = jh7100_clk_reg_get(clk);
++
++	return (value & JH7100_CLK_INVERT) ? 180 : 0;
++}
++
++static int jh7100_clk_set_phase(struct clk_hw *hw, int degrees)
++{
++	struct jh7100_clk *clk = jh7100_clk_from(hw);
++	u32 value;
++
++	if (degrees == 0)
++		value = 0;
++	else if (degrees == 180)
++		value = JH7100_CLK_INVERT;
++	else
++		return -EINVAL;
++
++	jh7100_clk_reg_rmw(clk, JH7100_CLK_INVERT, value);
++	return 0;
++}
++
++#ifdef CONFIG_DEBUG_FS
++static void jh7100_clk_debug_init(struct clk_hw *hw, struct dentry *dentry)
++{
++	static const struct debugfs_reg32 jh7100_clk_reg = {
++		.name = "CTRL",
++		.offset = 0,
++	};
++	struct jh7100_clk *clk = jh7100_clk_from(hw);
++	struct jh7100_clk_priv *priv = jh7100_priv_from(clk);
++	struct debugfs_regset32 *regset;
++
++	regset = devm_kzalloc(priv->dev, sizeof(*regset), GFP_KERNEL);
++	if (!regset)
++		return;
++
++	regset->regs = &jh7100_clk_reg;
++	regset->nregs = 1;
++	regset->base = priv->base + 4 * clk->idx;
++
++	debugfs_create_regset32("registers", 0400, dentry, regset);
++}
++#else
++#define jh7100_clk_debug_init NULL
++#endif
++
++static const struct clk_ops jh7100_clk_gate_ops = {
++	.enable = jh7100_clk_enable,
++	.disable = jh7100_clk_disable,
++	.is_enabled = jh7100_clk_is_enabled,
++	.debug_init = jh7100_clk_debug_init,
++};
++
++static const struct clk_ops jh7100_clk_div_ops = {
++	.recalc_rate = jh7100_clk_recalc_rate,
++	.determine_rate = jh7100_clk_determine_rate,
++	.set_rate = jh7100_clk_set_rate,
++	.debug_init = jh7100_clk_debug_init,
++};
++
++static const struct clk_ops jh7100_clk_fdiv_ops = {
++	.recalc_rate = jh7100_clk_frac_recalc_rate,
++	.determine_rate = jh7100_clk_frac_determine_rate,
++	.set_rate = jh7100_clk_frac_set_rate,
++	.debug_init = jh7100_clk_debug_init,
++};
++
++static const struct clk_ops jh7100_clk_gdiv_ops = {
++	.enable = jh7100_clk_enable,
++	.disable = jh7100_clk_disable,
++	.is_enabled = jh7100_clk_is_enabled,
++	.recalc_rate = jh7100_clk_recalc_rate,
++	.determine_rate = jh7100_clk_determine_rate,
++	.set_rate = jh7100_clk_set_rate,
++	.debug_init = jh7100_clk_debug_init,
++};
++
++static const struct clk_ops jh7100_clk_mux_ops = {
++	.determine_rate = jh7100_clk_mux_determine_rate,
++	.set_parent = jh7100_clk_set_parent,
++	.get_parent = jh7100_clk_get_parent,
++	.debug_init = jh7100_clk_debug_init,
++};
++
++static const struct clk_ops jh7100_clk_gmux_ops = {
++	.enable = jh7100_clk_enable,
++	.disable = jh7100_clk_disable,
++	.is_enabled = jh7100_clk_is_enabled,
++	.determine_rate = jh7100_clk_mux_determine_rate,
++	.set_parent = jh7100_clk_set_parent,
++	.get_parent = jh7100_clk_get_parent,
++	.debug_init = jh7100_clk_debug_init,
++};
++
++static const struct clk_ops jh7100_clk_mdiv_ops = {
++	.recalc_rate = jh7100_clk_recalc_rate,
++	.determine_rate = jh7100_clk_determine_rate,
++	.get_parent = jh7100_clk_get_parent,
++	.set_parent = jh7100_clk_set_parent,
++	.set_rate = jh7100_clk_set_rate,
++	.debug_init = jh7100_clk_debug_init,
++};
++
++static const struct clk_ops jh7100_clk_gmd_ops = {
++	.enable = jh7100_clk_enable,
++	.disable = jh7100_clk_disable,
++	.is_enabled = jh7100_clk_is_enabled,
++	.recalc_rate = jh7100_clk_recalc_rate,
++	.determine_rate = jh7100_clk_determine_rate,
++	.get_parent = jh7100_clk_get_parent,
++	.set_parent = jh7100_clk_set_parent,
++	.set_rate = jh7100_clk_set_rate,
++	.debug_init = jh7100_clk_debug_init,
++};
++
++static const struct clk_ops jh7100_clk_inv_ops = {
++	.get_phase = jh7100_clk_get_phase,
++	.set_phase = jh7100_clk_set_phase,
++	.debug_init = jh7100_clk_debug_init,
++};
++
++const struct clk_ops *starfive_jh7100_clk_ops(u32 max)
++{
++	if (max & JH7100_CLK_DIV_MASK) {
++		if (max & JH7100_CLK_MUX_MASK) {
++			if (max & JH7100_CLK_ENABLE)
++				return &jh7100_clk_gmd_ops;
++			return &jh7100_clk_mdiv_ops;
++		}
++		if (max & JH7100_CLK_ENABLE)
++			return &jh7100_clk_gdiv_ops;
++		if (max == JH7100_CLK_FRAC_MAX)
++			return &jh7100_clk_fdiv_ops;
++		return &jh7100_clk_div_ops;
++	}
++
++	if (max & JH7100_CLK_MUX_MASK) {
++		if (max & JH7100_CLK_ENABLE)
++			return &jh7100_clk_gmux_ops;
++		return &jh7100_clk_mux_ops;
++	}
++
++	if (max & JH7100_CLK_ENABLE)
++		return &jh7100_clk_gate_ops;
++
++	return &jh7100_clk_inv_ops;
++}
++EXPORT_SYMBOL_GPL(starfive_jh7100_clk_ops);

+ 290 - 0
target/linux/starfive/patches-6.1/0005-clk-starfive-Rename-clk-starfive-jh7100.h-to-clk-sta.patch

@@ -0,0 +1,290 @@
+From 8daa4c812f3b32a4d56ab48945e552a137fca9b7 Mon Sep 17 00:00:00 2001
+From: Emil Renner Berthing <[email protected]>
+Date: Sat, 1 Apr 2023 19:19:17 +0800
+Subject: [PATCH 005/122] clk: starfive: Rename clk-starfive-jh7100.h to
+ clk-starfive-jh71x0.h
+
+Rename clk-starfive-jh7100.h to clk-starfive-jh71x0.h for making
+the code to be common.
+
+Tested-by: Tommaso Merciai <[email protected]>
+Reviewed-by: Conor Dooley <[email protected]>
+Reviewed-by: Emil Renner Berthing <[email protected]>
+Signed-off-by: Emil Renner Berthing <[email protected]>
+Signed-off-by: Hal Feng <[email protected]>
+Signed-off-by: Conor Dooley <[email protected]>
+---
+ drivers/clk/starfive/clk-starfive-jh7100-audio.c                | 2 +-
+ drivers/clk/starfive/clk-starfive-jh7100.c                      | 2 +-
+ drivers/clk/starfive/clk-starfive-jh71x0.c                      | 2 +-
+ .../starfive/{clk-starfive-jh7100.h => clk-starfive-jh71x0.h}   | 0
+ 4 files changed, 3 insertions(+), 3 deletions(-)
+ rename drivers/clk/starfive/{clk-starfive-jh7100.h => clk-starfive-jh71x0.h} (100%)
+
+--- a/drivers/clk/starfive/clk-starfive-jh7100-audio.c
++++ b/drivers/clk/starfive/clk-starfive-jh7100-audio.c
+@@ -16,7 +16,7 @@
+ 
+ #include <dt-bindings/clock/starfive-jh7100-audio.h>
+ 
+-#include "clk-starfive-jh7100.h"
++#include "clk-starfive-jh71x0.h"
+ 
+ /* external clocks */
+ #define JH7100_AUDCLK_AUDIO_SRC			(JH7100_AUDCLK_END + 0)
+--- a/drivers/clk/starfive/clk-starfive-jh7100.c
++++ b/drivers/clk/starfive/clk-starfive-jh7100.c
+@@ -15,7 +15,7 @@
+ 
+ #include <dt-bindings/clock/starfive-jh7100.h>
+ 
+-#include "clk-starfive-jh7100.h"
++#include "clk-starfive-jh71x0.h"
+ 
+ /* external clocks */
+ #define JH7100_CLK_OSC_SYS		(JH7100_CLK_END + 0)
+--- a/drivers/clk/starfive/clk-starfive-jh71x0.c
++++ b/drivers/clk/starfive/clk-starfive-jh71x0.c
+@@ -10,7 +10,7 @@
+ #include <linux/device.h>
+ #include <linux/io.h>
+ 
+-#include "clk-starfive-jh7100.h"
++#include "clk-starfive-jh71x0.h"
+ 
+ static struct jh7100_clk *jh7100_clk_from(struct clk_hw *hw)
+ {
+--- a/drivers/clk/starfive/clk-starfive-jh7100.h
++++ /dev/null
+@@ -1,114 +0,0 @@
+-/* SPDX-License-Identifier: GPL-2.0 */
+-#ifndef __CLK_STARFIVE_JH7100_H
+-#define __CLK_STARFIVE_JH7100_H
+-
+-#include <linux/bits.h>
+-#include <linux/clk-provider.h>
+-#include <linux/device.h>
+-#include <linux/spinlock.h>
+-
+-/* register fields */
+-#define JH7100_CLK_ENABLE	BIT(31)
+-#define JH7100_CLK_INVERT	BIT(30)
+-#define JH7100_CLK_MUX_MASK	GENMASK(27, 24)
+-#define JH7100_CLK_MUX_SHIFT	24
+-#define JH7100_CLK_DIV_MASK	GENMASK(23, 0)
+-#define JH7100_CLK_FRAC_MASK	GENMASK(15, 8)
+-#define JH7100_CLK_FRAC_SHIFT	8
+-#define JH7100_CLK_INT_MASK	GENMASK(7, 0)
+-
+-/* fractional divider min/max */
+-#define JH7100_CLK_FRAC_MIN	100UL
+-#define JH7100_CLK_FRAC_MAX	25599UL
+-
+-/* clock data */
+-struct jh7100_clk_data {
+-	const char *name;
+-	unsigned long flags;
+-	u32 max;
+-	u8 parents[4];
+-};
+-
+-#define JH7100_GATE(_idx, _name, _flags, _parent) [_idx] = {			\
+-	.name = _name,								\
+-	.flags = CLK_SET_RATE_PARENT | (_flags),				\
+-	.max = JH7100_CLK_ENABLE,						\
+-	.parents = { [0] = _parent },						\
+-}
+-
+-#define JH7100__DIV(_idx, _name, _max, _parent) [_idx] = {			\
+-	.name = _name,								\
+-	.flags = 0,								\
+-	.max = _max,								\
+-	.parents = { [0] = _parent },						\
+-}
+-
+-#define JH7100_GDIV(_idx, _name, _flags, _max, _parent) [_idx] = {		\
+-	.name = _name,								\
+-	.flags = _flags,							\
+-	.max = JH7100_CLK_ENABLE | (_max),					\
+-	.parents = { [0] = _parent },						\
+-}
+-
+-#define JH7100_FDIV(_idx, _name, _parent) [_idx] = {				\
+-	.name = _name,								\
+-	.flags = 0,								\
+-	.max = JH7100_CLK_FRAC_MAX,						\
+-	.parents = { [0] = _parent },						\
+-}
+-
+-#define JH7100__MUX(_idx, _name, _nparents, ...) [_idx] = {			\
+-	.name = _name,								\
+-	.flags = 0,								\
+-	.max = ((_nparents) - 1) << JH7100_CLK_MUX_SHIFT,			\
+-	.parents = { __VA_ARGS__ },						\
+-}
+-
+-#define JH7100_GMUX(_idx, _name, _flags, _nparents, ...) [_idx] = {		\
+-	.name = _name,								\
+-	.flags = _flags,							\
+-	.max = JH7100_CLK_ENABLE |						\
+-		(((_nparents) - 1) << JH7100_CLK_MUX_SHIFT),			\
+-	.parents = { __VA_ARGS__ },						\
+-}
+-
+-#define JH7100_MDIV(_idx, _name, _max, _nparents, ...) [_idx] = {		\
+-	.name = _name,								\
+-	.flags = 0,								\
+-	.max = (((_nparents) - 1) << JH7100_CLK_MUX_SHIFT) | (_max),		\
+-	.parents = { __VA_ARGS__ },						\
+-}
+-
+-#define JH7100__GMD(_idx, _name, _flags, _max, _nparents, ...) [_idx] = {	\
+-	.name = _name,								\
+-	.flags = _flags,							\
+-	.max = JH7100_CLK_ENABLE |						\
+-		(((_nparents) - 1) << JH7100_CLK_MUX_SHIFT) | (_max),		\
+-	.parents = { __VA_ARGS__ },						\
+-}
+-
+-#define JH7100__INV(_idx, _name, _parent) [_idx] = {				\
+-	.name = _name,								\
+-	.flags = CLK_SET_RATE_PARENT,						\
+-	.max = JH7100_CLK_INVERT,						\
+-	.parents = { [0] = _parent },						\
+-}
+-
+-struct jh7100_clk {
+-	struct clk_hw hw;
+-	unsigned int idx;
+-	unsigned int max_div;
+-};
+-
+-struct jh7100_clk_priv {
+-	/* protect clk enable and set rate/parent from happening at the same time */
+-	spinlock_t rmw_lock;
+-	struct device *dev;
+-	void __iomem *base;
+-	struct clk_hw *pll[3];
+-	struct jh7100_clk reg[];
+-};
+-
+-const struct clk_ops *starfive_jh7100_clk_ops(u32 max);
+-
+-#endif
+--- /dev/null
++++ b/drivers/clk/starfive/clk-starfive-jh71x0.h
+@@ -0,0 +1,114 @@
++/* SPDX-License-Identifier: GPL-2.0 */
++#ifndef __CLK_STARFIVE_JH7100_H
++#define __CLK_STARFIVE_JH7100_H
++
++#include <linux/bits.h>
++#include <linux/clk-provider.h>
++#include <linux/device.h>
++#include <linux/spinlock.h>
++
++/* register fields */
++#define JH7100_CLK_ENABLE	BIT(31)
++#define JH7100_CLK_INVERT	BIT(30)
++#define JH7100_CLK_MUX_MASK	GENMASK(27, 24)
++#define JH7100_CLK_MUX_SHIFT	24
++#define JH7100_CLK_DIV_MASK	GENMASK(23, 0)
++#define JH7100_CLK_FRAC_MASK	GENMASK(15, 8)
++#define JH7100_CLK_FRAC_SHIFT	8
++#define JH7100_CLK_INT_MASK	GENMASK(7, 0)
++
++/* fractional divider min/max */
++#define JH7100_CLK_FRAC_MIN	100UL
++#define JH7100_CLK_FRAC_MAX	25599UL
++
++/* clock data */
++struct jh7100_clk_data {
++	const char *name;
++	unsigned long flags;
++	u32 max;
++	u8 parents[4];
++};
++
++#define JH7100_GATE(_idx, _name, _flags, _parent) [_idx] = {			\
++	.name = _name,								\
++	.flags = CLK_SET_RATE_PARENT | (_flags),				\
++	.max = JH7100_CLK_ENABLE,						\
++	.parents = { [0] = _parent },						\
++}
++
++#define JH7100__DIV(_idx, _name, _max, _parent) [_idx] = {			\
++	.name = _name,								\
++	.flags = 0,								\
++	.max = _max,								\
++	.parents = { [0] = _parent },						\
++}
++
++#define JH7100_GDIV(_idx, _name, _flags, _max, _parent) [_idx] = {		\
++	.name = _name,								\
++	.flags = _flags,							\
++	.max = JH7100_CLK_ENABLE | (_max),					\
++	.parents = { [0] = _parent },						\
++}
++
++#define JH7100_FDIV(_idx, _name, _parent) [_idx] = {				\
++	.name = _name,								\
++	.flags = 0,								\
++	.max = JH7100_CLK_FRAC_MAX,						\
++	.parents = { [0] = _parent },						\
++}
++
++#define JH7100__MUX(_idx, _name, _nparents, ...) [_idx] = {			\
++	.name = _name,								\
++	.flags = 0,								\
++	.max = ((_nparents) - 1) << JH7100_CLK_MUX_SHIFT,			\
++	.parents = { __VA_ARGS__ },						\
++}
++
++#define JH7100_GMUX(_idx, _name, _flags, _nparents, ...) [_idx] = {		\
++	.name = _name,								\
++	.flags = _flags,							\
++	.max = JH7100_CLK_ENABLE |						\
++		(((_nparents) - 1) << JH7100_CLK_MUX_SHIFT),			\
++	.parents = { __VA_ARGS__ },						\
++}
++
++#define JH7100_MDIV(_idx, _name, _max, _nparents, ...) [_idx] = {		\
++	.name = _name,								\
++	.flags = 0,								\
++	.max = (((_nparents) - 1) << JH7100_CLK_MUX_SHIFT) | (_max),		\
++	.parents = { __VA_ARGS__ },						\
++}
++
++#define JH7100__GMD(_idx, _name, _flags, _max, _nparents, ...) [_idx] = {	\
++	.name = _name,								\
++	.flags = _flags,							\
++	.max = JH7100_CLK_ENABLE |						\
++		(((_nparents) - 1) << JH7100_CLK_MUX_SHIFT) | (_max),		\
++	.parents = { __VA_ARGS__ },						\
++}
++
++#define JH7100__INV(_idx, _name, _parent) [_idx] = {				\
++	.name = _name,								\
++	.flags = CLK_SET_RATE_PARENT,						\
++	.max = JH7100_CLK_INVERT,						\
++	.parents = { [0] = _parent },						\
++}
++
++struct jh7100_clk {
++	struct clk_hw hw;
++	unsigned int idx;
++	unsigned int max_div;
++};
++
++struct jh7100_clk_priv {
++	/* protect clk enable and set rate/parent from happening at the same time */
++	spinlock_t rmw_lock;
++	struct device *dev;
++	void __iomem *base;
++	struct clk_hw *pll[3];
++	struct jh7100_clk reg[];
++};
++
++const struct clk_ops *starfive_jh7100_clk_ops(u32 max);
++
++#endif

+ 1249 - 0
target/linux/starfive/patches-6.1/0006-clk-starfive-Rename-jh7100-to-jh71x0-for-the-common-.patch

@@ -0,0 +1,1249 @@
+From 674fa25b207e4bef6c27af2acfbca3a0d765a45b Mon Sep 17 00:00:00 2001
+From: Emil Renner Berthing <[email protected]>
+Date: Sat, 1 Apr 2023 19:19:18 +0800
+Subject: [PATCH 006/122] clk: starfive: Rename "jh7100" to "jh71x0" for the
+ common code
+
+Rename some variables from "jh7100" or "JH7100" to "jh71x0"
+or "JH71X0".
+
+Tested-by: Tommaso Merciai <[email protected]>
+Reviewed-by: Conor Dooley <[email protected]>
+Reviewed-by: Emil Renner Berthing <[email protected]>
+Signed-off-by: Emil Renner Berthing <[email protected]>
+Signed-off-by: Hal Feng <[email protected]>
+Signed-off-by: Conor Dooley <[email protected]>
+---
+ .../clk/starfive/clk-starfive-jh7100-audio.c  |  72 ++--
+ drivers/clk/starfive/clk-starfive-jh7100.c    | 389 +++++++++---------
+ drivers/clk/starfive/clk-starfive-jh71x0.c    | 282 ++++++-------
+ drivers/clk/starfive/clk-starfive-jh71x0.h    |  81 ++--
+ 4 files changed, 418 insertions(+), 406 deletions(-)
+
+--- a/drivers/clk/starfive/clk-starfive-jh7100-audio.c
++++ b/drivers/clk/starfive/clk-starfive-jh7100-audio.c
+@@ -28,66 +28,66 @@
+ #define JH7100_AUDCLK_I2SDAC_LRCLK_IOPAD	(JH7100_AUDCLK_END + 6)
+ #define JH7100_AUDCLK_VAD_INTMEM                (JH7100_AUDCLK_END + 7)
+ 
+-static const struct jh7100_clk_data jh7100_audclk_data[] = {
+-	JH7100__GMD(JH7100_AUDCLK_ADC_MCLK, "adc_mclk", 0, 15, 2,
++static const struct jh71x0_clk_data jh7100_audclk_data[] = {
++	JH71X0__GMD(JH7100_AUDCLK_ADC_MCLK, "adc_mclk", 0, 15, 2,
+ 		    JH7100_AUDCLK_AUDIO_SRC,
+ 		    JH7100_AUDCLK_AUDIO_12288),
+-	JH7100__GMD(JH7100_AUDCLK_I2S1_MCLK, "i2s1_mclk", 0, 15, 2,
++	JH71X0__GMD(JH7100_AUDCLK_I2S1_MCLK, "i2s1_mclk", 0, 15, 2,
+ 		    JH7100_AUDCLK_AUDIO_SRC,
+ 		    JH7100_AUDCLK_AUDIO_12288),
+-	JH7100_GATE(JH7100_AUDCLK_I2SADC_APB, "i2sadc_apb", 0, JH7100_AUDCLK_APB0_BUS),
+-	JH7100_MDIV(JH7100_AUDCLK_I2SADC_BCLK, "i2sadc_bclk", 31, 2,
++	JH71X0_GATE(JH7100_AUDCLK_I2SADC_APB, "i2sadc_apb", 0, JH7100_AUDCLK_APB0_BUS),
++	JH71X0_MDIV(JH7100_AUDCLK_I2SADC_BCLK, "i2sadc_bclk", 31, 2,
+ 		    JH7100_AUDCLK_ADC_MCLK,
+ 		    JH7100_AUDCLK_I2SADC_BCLK_IOPAD),
+-	JH7100__INV(JH7100_AUDCLK_I2SADC_BCLK_N, "i2sadc_bclk_n", JH7100_AUDCLK_I2SADC_BCLK),
+-	JH7100_MDIV(JH7100_AUDCLK_I2SADC_LRCLK, "i2sadc_lrclk", 63, 3,
++	JH71X0__INV(JH7100_AUDCLK_I2SADC_BCLK_N, "i2sadc_bclk_n", JH7100_AUDCLK_I2SADC_BCLK),
++	JH71X0_MDIV(JH7100_AUDCLK_I2SADC_LRCLK, "i2sadc_lrclk", 63, 3,
+ 		    JH7100_AUDCLK_I2SADC_BCLK_N,
+ 		    JH7100_AUDCLK_I2SADC_LRCLK_IOPAD,
+ 		    JH7100_AUDCLK_I2SADC_BCLK),
+-	JH7100_GATE(JH7100_AUDCLK_PDM_APB, "pdm_apb", 0, JH7100_AUDCLK_APB0_BUS),
+-	JH7100__GMD(JH7100_AUDCLK_PDM_MCLK, "pdm_mclk", 0, 15, 2,
++	JH71X0_GATE(JH7100_AUDCLK_PDM_APB, "pdm_apb", 0, JH7100_AUDCLK_APB0_BUS),
++	JH71X0__GMD(JH7100_AUDCLK_PDM_MCLK, "pdm_mclk", 0, 15, 2,
+ 		    JH7100_AUDCLK_AUDIO_SRC,
+ 		    JH7100_AUDCLK_AUDIO_12288),
+-	JH7100_GATE(JH7100_AUDCLK_I2SVAD_APB, "i2svad_apb", 0, JH7100_AUDCLK_APB0_BUS),
+-	JH7100__GMD(JH7100_AUDCLK_SPDIF, "spdif", 0, 15, 2,
++	JH71X0_GATE(JH7100_AUDCLK_I2SVAD_APB, "i2svad_apb", 0, JH7100_AUDCLK_APB0_BUS),
++	JH71X0__GMD(JH7100_AUDCLK_SPDIF, "spdif", 0, 15, 2,
+ 		    JH7100_AUDCLK_AUDIO_SRC,
+ 		    JH7100_AUDCLK_AUDIO_12288),
+-	JH7100_GATE(JH7100_AUDCLK_SPDIF_APB, "spdif_apb", 0, JH7100_AUDCLK_APB0_BUS),
+-	JH7100_GATE(JH7100_AUDCLK_PWMDAC_APB, "pwmdac_apb", 0, JH7100_AUDCLK_APB0_BUS),
+-	JH7100__GMD(JH7100_AUDCLK_DAC_MCLK, "dac_mclk", 0, 15, 2,
++	JH71X0_GATE(JH7100_AUDCLK_SPDIF_APB, "spdif_apb", 0, JH7100_AUDCLK_APB0_BUS),
++	JH71X0_GATE(JH7100_AUDCLK_PWMDAC_APB, "pwmdac_apb", 0, JH7100_AUDCLK_APB0_BUS),
++	JH71X0__GMD(JH7100_AUDCLK_DAC_MCLK, "dac_mclk", 0, 15, 2,
+ 		    JH7100_AUDCLK_AUDIO_SRC,
+ 		    JH7100_AUDCLK_AUDIO_12288),
+-	JH7100_GATE(JH7100_AUDCLK_I2SDAC_APB, "i2sdac_apb", 0, JH7100_AUDCLK_APB0_BUS),
+-	JH7100_MDIV(JH7100_AUDCLK_I2SDAC_BCLK, "i2sdac_bclk", 31, 2,
++	JH71X0_GATE(JH7100_AUDCLK_I2SDAC_APB, "i2sdac_apb", 0, JH7100_AUDCLK_APB0_BUS),
++	JH71X0_MDIV(JH7100_AUDCLK_I2SDAC_BCLK, "i2sdac_bclk", 31, 2,
+ 		    JH7100_AUDCLK_DAC_MCLK,
+ 		    JH7100_AUDCLK_I2SDAC_BCLK_IOPAD),
+-	JH7100__INV(JH7100_AUDCLK_I2SDAC_BCLK_N, "i2sdac_bclk_n", JH7100_AUDCLK_I2SDAC_BCLK),
+-	JH7100_MDIV(JH7100_AUDCLK_I2SDAC_LRCLK, "i2sdac_lrclk", 31, 2,
++	JH71X0__INV(JH7100_AUDCLK_I2SDAC_BCLK_N, "i2sdac_bclk_n", JH7100_AUDCLK_I2SDAC_BCLK),
++	JH71X0_MDIV(JH7100_AUDCLK_I2SDAC_LRCLK, "i2sdac_lrclk", 31, 2,
+ 		    JH7100_AUDCLK_I2S1_MCLK,
+ 		    JH7100_AUDCLK_I2SDAC_BCLK_IOPAD),
+-	JH7100_GATE(JH7100_AUDCLK_I2S1_APB, "i2s1_apb", 0, JH7100_AUDCLK_APB0_BUS),
+-	JH7100_MDIV(JH7100_AUDCLK_I2S1_BCLK, "i2s1_bclk", 31, 2,
++	JH71X0_GATE(JH7100_AUDCLK_I2S1_APB, "i2s1_apb", 0, JH7100_AUDCLK_APB0_BUS),
++	JH71X0_MDIV(JH7100_AUDCLK_I2S1_BCLK, "i2s1_bclk", 31, 2,
+ 		    JH7100_AUDCLK_I2S1_MCLK,
+ 		    JH7100_AUDCLK_I2SDAC_BCLK_IOPAD),
+-	JH7100__INV(JH7100_AUDCLK_I2S1_BCLK_N, "i2s1_bclk_n", JH7100_AUDCLK_I2S1_BCLK),
+-	JH7100_MDIV(JH7100_AUDCLK_I2S1_LRCLK, "i2s1_lrclk", 63, 3,
++	JH71X0__INV(JH7100_AUDCLK_I2S1_BCLK_N, "i2s1_bclk_n", JH7100_AUDCLK_I2S1_BCLK),
++	JH71X0_MDIV(JH7100_AUDCLK_I2S1_LRCLK, "i2s1_lrclk", 63, 3,
+ 		    JH7100_AUDCLK_I2S1_BCLK_N,
+ 		    JH7100_AUDCLK_I2SDAC_LRCLK_IOPAD),
+-	JH7100_GATE(JH7100_AUDCLK_I2SDAC16K_APB, "i2s1dac16k_apb", 0, JH7100_AUDCLK_APB0_BUS),
+-	JH7100__DIV(JH7100_AUDCLK_APB0_BUS, "apb0_bus", 8, JH7100_AUDCLK_DOM7AHB_BUS),
+-	JH7100_GATE(JH7100_AUDCLK_DMA1P_AHB, "dma1p_ahb", 0, JH7100_AUDCLK_DOM7AHB_BUS),
+-	JH7100_GATE(JH7100_AUDCLK_USB_APB, "usb_apb", CLK_IGNORE_UNUSED, JH7100_AUDCLK_APB_EN),
+-	JH7100_GDIV(JH7100_AUDCLK_USB_LPM, "usb_lpm", CLK_IGNORE_UNUSED, 4, JH7100_AUDCLK_USB_APB),
+-	JH7100_GDIV(JH7100_AUDCLK_USB_STB, "usb_stb", CLK_IGNORE_UNUSED, 3, JH7100_AUDCLK_USB_APB),
+-	JH7100__DIV(JH7100_AUDCLK_APB_EN, "apb_en", 8, JH7100_AUDCLK_DOM7AHB_BUS),
+-	JH7100__MUX(JH7100_AUDCLK_VAD_MEM, "vad_mem", 2,
++	JH71X0_GATE(JH7100_AUDCLK_I2SDAC16K_APB, "i2s1dac16k_apb", 0, JH7100_AUDCLK_APB0_BUS),
++	JH71X0__DIV(JH7100_AUDCLK_APB0_BUS, "apb0_bus", 8, JH7100_AUDCLK_DOM7AHB_BUS),
++	JH71X0_GATE(JH7100_AUDCLK_DMA1P_AHB, "dma1p_ahb", 0, JH7100_AUDCLK_DOM7AHB_BUS),
++	JH71X0_GATE(JH7100_AUDCLK_USB_APB, "usb_apb", CLK_IGNORE_UNUSED, JH7100_AUDCLK_APB_EN),
++	JH71X0_GDIV(JH7100_AUDCLK_USB_LPM, "usb_lpm", CLK_IGNORE_UNUSED, 4, JH7100_AUDCLK_USB_APB),
++	JH71X0_GDIV(JH7100_AUDCLK_USB_STB, "usb_stb", CLK_IGNORE_UNUSED, 3, JH7100_AUDCLK_USB_APB),
++	JH71X0__DIV(JH7100_AUDCLK_APB_EN, "apb_en", 8, JH7100_AUDCLK_DOM7AHB_BUS),
++	JH71X0__MUX(JH7100_AUDCLK_VAD_MEM, "vad_mem", 2,
+ 		    JH7100_AUDCLK_VAD_INTMEM,
+ 		    JH7100_AUDCLK_AUDIO_12288),
+ };
+ 
+ static struct clk_hw *jh7100_audclk_get(struct of_phandle_args *clkspec, void *data)
+ {
+-	struct jh7100_clk_priv *priv = data;
++	struct jh71x0_clk_priv *priv = data;
+ 	unsigned int idx = clkspec->args[0];
+ 
+ 	if (idx < JH7100_AUDCLK_END)
+@@ -98,7 +98,7 @@ static struct clk_hw *jh7100_audclk_get(
+ 
+ static int jh7100_audclk_probe(struct platform_device *pdev)
+ {
+-	struct jh7100_clk_priv *priv;
++	struct jh71x0_clk_priv *priv;
+ 	unsigned int idx;
+ 	int ret;
+ 
+@@ -117,12 +117,12 @@ static int jh7100_audclk_probe(struct pl
+ 		struct clk_parent_data parents[4] = {};
+ 		struct clk_init_data init = {
+ 			.name = jh7100_audclk_data[idx].name,
+-			.ops = starfive_jh7100_clk_ops(max),
++			.ops = starfive_jh71x0_clk_ops(max),
+ 			.parent_data = parents,
+-			.num_parents = ((max & JH7100_CLK_MUX_MASK) >> JH7100_CLK_MUX_SHIFT) + 1,
++			.num_parents = ((max & JH71X0_CLK_MUX_MASK) >> JH71X0_CLK_MUX_SHIFT) + 1,
+ 			.flags = jh7100_audclk_data[idx].flags,
+ 		};
+-		struct jh7100_clk *clk = &priv->reg[idx];
++		struct jh71x0_clk *clk = &priv->reg[idx];
+ 		unsigned int i;
+ 
+ 		for (i = 0; i < init.num_parents; i++) {
+@@ -140,7 +140,7 @@ static int jh7100_audclk_probe(struct pl
+ 
+ 		clk->hw.init = &init;
+ 		clk->idx = idx;
+-		clk->max_div = max & JH7100_CLK_DIV_MASK;
++		clk->max_div = max & JH71X0_CLK_DIV_MASK;
+ 
+ 		ret = devm_clk_hw_register(priv->dev, &clk->hw);
+ 		if (ret)
+--- a/drivers/clk/starfive/clk-starfive-jh7100.c
++++ b/drivers/clk/starfive/clk-starfive-jh7100.c
+@@ -23,250 +23,253 @@
+ #define JH7100_CLK_GMAC_RMII_REF	(JH7100_CLK_END + 2)
+ #define JH7100_CLK_GMAC_GR_MII_RX	(JH7100_CLK_END + 3)
+ 
+-static const struct jh7100_clk_data jh7100_clk_data[] __initconst = {
+-	JH7100__MUX(JH7100_CLK_CPUNDBUS_ROOT, "cpundbus_root", 4,
++static const struct jh71x0_clk_data jh7100_clk_data[] __initconst = {
++	JH71X0__MUX(JH7100_CLK_CPUNDBUS_ROOT, "cpundbus_root", 4,
+ 		    JH7100_CLK_OSC_SYS,
+ 		    JH7100_CLK_PLL0_OUT,
+ 		    JH7100_CLK_PLL1_OUT,
+ 		    JH7100_CLK_PLL2_OUT),
+-	JH7100__MUX(JH7100_CLK_DLA_ROOT, "dla_root", 3,
++	JH71X0__MUX(JH7100_CLK_DLA_ROOT, "dla_root", 3,
+ 		    JH7100_CLK_OSC_SYS,
+ 		    JH7100_CLK_PLL1_OUT,
+ 		    JH7100_CLK_PLL2_OUT),
+-	JH7100__MUX(JH7100_CLK_DSP_ROOT, "dsp_root", 4,
++	JH71X0__MUX(JH7100_CLK_DSP_ROOT, "dsp_root", 4,
+ 		    JH7100_CLK_OSC_SYS,
+ 		    JH7100_CLK_PLL0_OUT,
+ 		    JH7100_CLK_PLL1_OUT,
+ 		    JH7100_CLK_PLL2_OUT),
+-	JH7100__MUX(JH7100_CLK_GMACUSB_ROOT, "gmacusb_root", 3,
++	JH71X0__MUX(JH7100_CLK_GMACUSB_ROOT, "gmacusb_root", 3,
+ 		    JH7100_CLK_OSC_SYS,
+ 		    JH7100_CLK_PLL0_OUT,
+ 		    JH7100_CLK_PLL2_OUT),
+-	JH7100__MUX(JH7100_CLK_PERH0_ROOT, "perh0_root", 2,
++	JH71X0__MUX(JH7100_CLK_PERH0_ROOT, "perh0_root", 2,
+ 		    JH7100_CLK_OSC_SYS,
+ 		    JH7100_CLK_PLL0_OUT),
+-	JH7100__MUX(JH7100_CLK_PERH1_ROOT, "perh1_root", 2,
++	JH71X0__MUX(JH7100_CLK_PERH1_ROOT, "perh1_root", 2,
+ 		    JH7100_CLK_OSC_SYS,
+ 		    JH7100_CLK_PLL2_OUT),
+-	JH7100__MUX(JH7100_CLK_VIN_ROOT, "vin_root", 3,
++	JH71X0__MUX(JH7100_CLK_VIN_ROOT, "vin_root", 3,
+ 		    JH7100_CLK_OSC_SYS,
+ 		    JH7100_CLK_PLL1_OUT,
+ 		    JH7100_CLK_PLL2_OUT),
+-	JH7100__MUX(JH7100_CLK_VOUT_ROOT, "vout_root", 3,
++	JH71X0__MUX(JH7100_CLK_VOUT_ROOT, "vout_root", 3,
+ 		    JH7100_CLK_OSC_AUD,
+ 		    JH7100_CLK_PLL0_OUT,
+ 		    JH7100_CLK_PLL2_OUT),
+-	JH7100_GDIV(JH7100_CLK_AUDIO_ROOT, "audio_root", 0, 8, JH7100_CLK_PLL0_OUT),
+-	JH7100__MUX(JH7100_CLK_CDECHIFI4_ROOT, "cdechifi4_root", 3,
++	JH71X0_GDIV(JH7100_CLK_AUDIO_ROOT, "audio_root", 0, 8, JH7100_CLK_PLL0_OUT),
++	JH71X0__MUX(JH7100_CLK_CDECHIFI4_ROOT, "cdechifi4_root", 3,
+ 		    JH7100_CLK_OSC_SYS,
+ 		    JH7100_CLK_PLL1_OUT,
+ 		    JH7100_CLK_PLL2_OUT),
+-	JH7100__MUX(JH7100_CLK_CDEC_ROOT, "cdec_root", 3,
++	JH71X0__MUX(JH7100_CLK_CDEC_ROOT, "cdec_root", 3,
+ 		    JH7100_CLK_OSC_SYS,
+ 		    JH7100_CLK_PLL0_OUT,
+ 		    JH7100_CLK_PLL1_OUT),
+-	JH7100__MUX(JH7100_CLK_VOUTBUS_ROOT, "voutbus_root", 3,
++	JH71X0__MUX(JH7100_CLK_VOUTBUS_ROOT, "voutbus_root", 3,
+ 		    JH7100_CLK_OSC_AUD,
+ 		    JH7100_CLK_PLL0_OUT,
+ 		    JH7100_CLK_PLL2_OUT),
+-	JH7100__DIV(JH7100_CLK_CPUNBUS_ROOT_DIV, "cpunbus_root_div", 2, JH7100_CLK_CPUNDBUS_ROOT),
+-	JH7100__DIV(JH7100_CLK_DSP_ROOT_DIV, "dsp_root_div", 4, JH7100_CLK_DSP_ROOT),
+-	JH7100__DIV(JH7100_CLK_PERH0_SRC, "perh0_src", 4, JH7100_CLK_PERH0_ROOT),
+-	JH7100__DIV(JH7100_CLK_PERH1_SRC, "perh1_src", 4, JH7100_CLK_PERH1_ROOT),
+-	JH7100_GDIV(JH7100_CLK_PLL0_TESTOUT, "pll0_testout", 0, 31, JH7100_CLK_PERH0_SRC),
+-	JH7100_GDIV(JH7100_CLK_PLL1_TESTOUT, "pll1_testout", 0, 31, JH7100_CLK_DLA_ROOT),
+-	JH7100_GDIV(JH7100_CLK_PLL2_TESTOUT, "pll2_testout", 0, 31, JH7100_CLK_PERH1_SRC),
+-	JH7100__MUX(JH7100_CLK_PLL2_REF, "pll2_refclk", 2,
++	JH71X0__DIV(JH7100_CLK_CPUNBUS_ROOT_DIV, "cpunbus_root_div", 2, JH7100_CLK_CPUNDBUS_ROOT),
++	JH71X0__DIV(JH7100_CLK_DSP_ROOT_DIV, "dsp_root_div", 4, JH7100_CLK_DSP_ROOT),
++	JH71X0__DIV(JH7100_CLK_PERH0_SRC, "perh0_src", 4, JH7100_CLK_PERH0_ROOT),
++	JH71X0__DIV(JH7100_CLK_PERH1_SRC, "perh1_src", 4, JH7100_CLK_PERH1_ROOT),
++	JH71X0_GDIV(JH7100_CLK_PLL0_TESTOUT, "pll0_testout", 0, 31, JH7100_CLK_PERH0_SRC),
++	JH71X0_GDIV(JH7100_CLK_PLL1_TESTOUT, "pll1_testout", 0, 31, JH7100_CLK_DLA_ROOT),
++	JH71X0_GDIV(JH7100_CLK_PLL2_TESTOUT, "pll2_testout", 0, 31, JH7100_CLK_PERH1_SRC),
++	JH71X0__MUX(JH7100_CLK_PLL2_REF, "pll2_refclk", 2,
+ 		    JH7100_CLK_OSC_SYS,
+ 		    JH7100_CLK_OSC_AUD),
+-	JH7100__DIV(JH7100_CLK_CPU_CORE, "cpu_core", 8, JH7100_CLK_CPUNBUS_ROOT_DIV),
+-	JH7100__DIV(JH7100_CLK_CPU_AXI, "cpu_axi", 8, JH7100_CLK_CPU_CORE),
+-	JH7100__DIV(JH7100_CLK_AHB_BUS, "ahb_bus", 8, JH7100_CLK_CPUNBUS_ROOT_DIV),
+-	JH7100__DIV(JH7100_CLK_APB1_BUS, "apb1_bus", 8, JH7100_CLK_AHB_BUS),
+-	JH7100__DIV(JH7100_CLK_APB2_BUS, "apb2_bus", 8, JH7100_CLK_AHB_BUS),
+-	JH7100_GATE(JH7100_CLK_DOM3AHB_BUS, "dom3ahb_bus", CLK_IS_CRITICAL, JH7100_CLK_AHB_BUS),
+-	JH7100_GATE(JH7100_CLK_DOM7AHB_BUS, "dom7ahb_bus", CLK_IS_CRITICAL, JH7100_CLK_AHB_BUS),
+-	JH7100_GATE(JH7100_CLK_U74_CORE0, "u74_core0", CLK_IS_CRITICAL, JH7100_CLK_CPU_CORE),
+-	JH7100_GDIV(JH7100_CLK_U74_CORE1, "u74_core1", CLK_IS_CRITICAL, 8, JH7100_CLK_CPU_CORE),
+-	JH7100_GATE(JH7100_CLK_U74_AXI, "u74_axi", CLK_IS_CRITICAL, JH7100_CLK_CPU_AXI),
+-	JH7100_GATE(JH7100_CLK_U74RTC_TOGGLE, "u74rtc_toggle", CLK_IS_CRITICAL, JH7100_CLK_OSC_SYS),
+-	JH7100_GATE(JH7100_CLK_SGDMA2P_AXI, "sgdma2p_axi", 0, JH7100_CLK_CPU_AXI),
+-	JH7100_GATE(JH7100_CLK_DMA2PNOC_AXI, "dma2pnoc_axi", 0, JH7100_CLK_CPU_AXI),
+-	JH7100_GATE(JH7100_CLK_SGDMA2P_AHB, "sgdma2p_ahb", 0, JH7100_CLK_AHB_BUS),
+-	JH7100__DIV(JH7100_CLK_DLA_BUS, "dla_bus", 4, JH7100_CLK_DLA_ROOT),
+-	JH7100_GATE(JH7100_CLK_DLA_AXI, "dla_axi", 0, JH7100_CLK_DLA_BUS),
+-	JH7100_GATE(JH7100_CLK_DLANOC_AXI, "dlanoc_axi", 0, JH7100_CLK_DLA_BUS),
+-	JH7100_GATE(JH7100_CLK_DLA_APB, "dla_apb", 0, JH7100_CLK_APB1_BUS),
+-	JH7100_GDIV(JH7100_CLK_VP6_CORE, "vp6_core", 0, 4, JH7100_CLK_DSP_ROOT_DIV),
+-	JH7100__DIV(JH7100_CLK_VP6BUS_SRC, "vp6bus_src", 4, JH7100_CLK_DSP_ROOT),
+-	JH7100_GDIV(JH7100_CLK_VP6_AXI, "vp6_axi", 0, 4, JH7100_CLK_VP6BUS_SRC),
+-	JH7100__DIV(JH7100_CLK_VCDECBUS_SRC, "vcdecbus_src", 4, JH7100_CLK_CDECHIFI4_ROOT),
+-	JH7100__DIV(JH7100_CLK_VDEC_BUS, "vdec_bus", 8, JH7100_CLK_VCDECBUS_SRC),
+-	JH7100_GATE(JH7100_CLK_VDEC_AXI, "vdec_axi", 0, JH7100_CLK_VDEC_BUS),
+-	JH7100_GATE(JH7100_CLK_VDECBRG_MAIN, "vdecbrg_mainclk", 0, JH7100_CLK_VDEC_BUS),
+-	JH7100_GDIV(JH7100_CLK_VDEC_BCLK, "vdec_bclk", 0, 8, JH7100_CLK_VCDECBUS_SRC),
+-	JH7100_GDIV(JH7100_CLK_VDEC_CCLK, "vdec_cclk", 0, 8, JH7100_CLK_CDEC_ROOT),
+-	JH7100_GATE(JH7100_CLK_VDEC_APB, "vdec_apb", 0, JH7100_CLK_APB1_BUS),
+-	JH7100_GDIV(JH7100_CLK_JPEG_AXI, "jpeg_axi", 0, 8, JH7100_CLK_CPUNBUS_ROOT_DIV),
+-	JH7100_GDIV(JH7100_CLK_JPEG_CCLK, "jpeg_cclk", 0, 8, JH7100_CLK_CPUNBUS_ROOT_DIV),
+-	JH7100_GATE(JH7100_CLK_JPEG_APB, "jpeg_apb", 0, JH7100_CLK_APB1_BUS),
+-	JH7100_GDIV(JH7100_CLK_GC300_2X, "gc300_2x", 0, 8, JH7100_CLK_CDECHIFI4_ROOT),
+-	JH7100_GATE(JH7100_CLK_GC300_AHB, "gc300_ahb", 0, JH7100_CLK_AHB_BUS),
+-	JH7100__DIV(JH7100_CLK_JPCGC300_AXIBUS, "jpcgc300_axibus", 8, JH7100_CLK_VCDECBUS_SRC),
+-	JH7100_GATE(JH7100_CLK_GC300_AXI, "gc300_axi", 0, JH7100_CLK_JPCGC300_AXIBUS),
+-	JH7100_GATE(JH7100_CLK_JPCGC300_MAIN, "jpcgc300_mainclk", 0, JH7100_CLK_JPCGC300_AXIBUS),
+-	JH7100__DIV(JH7100_CLK_VENC_BUS, "venc_bus", 8, JH7100_CLK_VCDECBUS_SRC),
+-	JH7100_GATE(JH7100_CLK_VENC_AXI, "venc_axi", 0, JH7100_CLK_VENC_BUS),
+-	JH7100_GATE(JH7100_CLK_VENCBRG_MAIN, "vencbrg_mainclk", 0, JH7100_CLK_VENC_BUS),
+-	JH7100_GDIV(JH7100_CLK_VENC_BCLK, "venc_bclk", 0, 8, JH7100_CLK_VCDECBUS_SRC),
+-	JH7100_GDIV(JH7100_CLK_VENC_CCLK, "venc_cclk", 0, 8, JH7100_CLK_CDEC_ROOT),
+-	JH7100_GATE(JH7100_CLK_VENC_APB, "venc_apb", 0, JH7100_CLK_APB1_BUS),
+-	JH7100_GDIV(JH7100_CLK_DDRPLL_DIV2, "ddrpll_div2", CLK_IS_CRITICAL, 2, JH7100_CLK_PLL1_OUT),
+-	JH7100_GDIV(JH7100_CLK_DDRPLL_DIV4, "ddrpll_div4", CLK_IS_CRITICAL, 2, JH7100_CLK_DDRPLL_DIV2),
+-	JH7100_GDIV(JH7100_CLK_DDRPLL_DIV8, "ddrpll_div8", CLK_IS_CRITICAL, 2, JH7100_CLK_DDRPLL_DIV4),
+-	JH7100_GDIV(JH7100_CLK_DDROSC_DIV2, "ddrosc_div2", CLK_IS_CRITICAL, 2, JH7100_CLK_OSC_SYS),
+-	JH7100_GMUX(JH7100_CLK_DDRC0, "ddrc0", CLK_IS_CRITICAL, 4,
++	JH71X0__DIV(JH7100_CLK_CPU_CORE, "cpu_core", 8, JH7100_CLK_CPUNBUS_ROOT_DIV),
++	JH71X0__DIV(JH7100_CLK_CPU_AXI, "cpu_axi", 8, JH7100_CLK_CPU_CORE),
++	JH71X0__DIV(JH7100_CLK_AHB_BUS, "ahb_bus", 8, JH7100_CLK_CPUNBUS_ROOT_DIV),
++	JH71X0__DIV(JH7100_CLK_APB1_BUS, "apb1_bus", 8, JH7100_CLK_AHB_BUS),
++	JH71X0__DIV(JH7100_CLK_APB2_BUS, "apb2_bus", 8, JH7100_CLK_AHB_BUS),
++	JH71X0_GATE(JH7100_CLK_DOM3AHB_BUS, "dom3ahb_bus", CLK_IS_CRITICAL, JH7100_CLK_AHB_BUS),
++	JH71X0_GATE(JH7100_CLK_DOM7AHB_BUS, "dom7ahb_bus", CLK_IS_CRITICAL, JH7100_CLK_AHB_BUS),
++	JH71X0_GATE(JH7100_CLK_U74_CORE0, "u74_core0", CLK_IS_CRITICAL, JH7100_CLK_CPU_CORE),
++	JH71X0_GDIV(JH7100_CLK_U74_CORE1, "u74_core1", CLK_IS_CRITICAL, 8, JH7100_CLK_CPU_CORE),
++	JH71X0_GATE(JH7100_CLK_U74_AXI, "u74_axi", CLK_IS_CRITICAL, JH7100_CLK_CPU_AXI),
++	JH71X0_GATE(JH7100_CLK_U74RTC_TOGGLE, "u74rtc_toggle", CLK_IS_CRITICAL, JH7100_CLK_OSC_SYS),
++	JH71X0_GATE(JH7100_CLK_SGDMA2P_AXI, "sgdma2p_axi", 0, JH7100_CLK_CPU_AXI),
++	JH71X0_GATE(JH7100_CLK_DMA2PNOC_AXI, "dma2pnoc_axi", 0, JH7100_CLK_CPU_AXI),
++	JH71X0_GATE(JH7100_CLK_SGDMA2P_AHB, "sgdma2p_ahb", 0, JH7100_CLK_AHB_BUS),
++	JH71X0__DIV(JH7100_CLK_DLA_BUS, "dla_bus", 4, JH7100_CLK_DLA_ROOT),
++	JH71X0_GATE(JH7100_CLK_DLA_AXI, "dla_axi", 0, JH7100_CLK_DLA_BUS),
++	JH71X0_GATE(JH7100_CLK_DLANOC_AXI, "dlanoc_axi", 0, JH7100_CLK_DLA_BUS),
++	JH71X0_GATE(JH7100_CLK_DLA_APB, "dla_apb", 0, JH7100_CLK_APB1_BUS),
++	JH71X0_GDIV(JH7100_CLK_VP6_CORE, "vp6_core", 0, 4, JH7100_CLK_DSP_ROOT_DIV),
++	JH71X0__DIV(JH7100_CLK_VP6BUS_SRC, "vp6bus_src", 4, JH7100_CLK_DSP_ROOT),
++	JH71X0_GDIV(JH7100_CLK_VP6_AXI, "vp6_axi", 0, 4, JH7100_CLK_VP6BUS_SRC),
++	JH71X0__DIV(JH7100_CLK_VCDECBUS_SRC, "vcdecbus_src", 4, JH7100_CLK_CDECHIFI4_ROOT),
++	JH71X0__DIV(JH7100_CLK_VDEC_BUS, "vdec_bus", 8, JH7100_CLK_VCDECBUS_SRC),
++	JH71X0_GATE(JH7100_CLK_VDEC_AXI, "vdec_axi", 0, JH7100_CLK_VDEC_BUS),
++	JH71X0_GATE(JH7100_CLK_VDECBRG_MAIN, "vdecbrg_mainclk", 0, JH7100_CLK_VDEC_BUS),
++	JH71X0_GDIV(JH7100_CLK_VDEC_BCLK, "vdec_bclk", 0, 8, JH7100_CLK_VCDECBUS_SRC),
++	JH71X0_GDIV(JH7100_CLK_VDEC_CCLK, "vdec_cclk", 0, 8, JH7100_CLK_CDEC_ROOT),
++	JH71X0_GATE(JH7100_CLK_VDEC_APB, "vdec_apb", 0, JH7100_CLK_APB1_BUS),
++	JH71X0_GDIV(JH7100_CLK_JPEG_AXI, "jpeg_axi", 0, 8, JH7100_CLK_CPUNBUS_ROOT_DIV),
++	JH71X0_GDIV(JH7100_CLK_JPEG_CCLK, "jpeg_cclk", 0, 8, JH7100_CLK_CPUNBUS_ROOT_DIV),
++	JH71X0_GATE(JH7100_CLK_JPEG_APB, "jpeg_apb", 0, JH7100_CLK_APB1_BUS),
++	JH71X0_GDIV(JH7100_CLK_GC300_2X, "gc300_2x", 0, 8, JH7100_CLK_CDECHIFI4_ROOT),
++	JH71X0_GATE(JH7100_CLK_GC300_AHB, "gc300_ahb", 0, JH7100_CLK_AHB_BUS),
++	JH71X0__DIV(JH7100_CLK_JPCGC300_AXIBUS, "jpcgc300_axibus", 8, JH7100_CLK_VCDECBUS_SRC),
++	JH71X0_GATE(JH7100_CLK_GC300_AXI, "gc300_axi", 0, JH7100_CLK_JPCGC300_AXIBUS),
++	JH71X0_GATE(JH7100_CLK_JPCGC300_MAIN, "jpcgc300_mainclk", 0, JH7100_CLK_JPCGC300_AXIBUS),
++	JH71X0__DIV(JH7100_CLK_VENC_BUS, "venc_bus", 8, JH7100_CLK_VCDECBUS_SRC),
++	JH71X0_GATE(JH7100_CLK_VENC_AXI, "venc_axi", 0, JH7100_CLK_VENC_BUS),
++	JH71X0_GATE(JH7100_CLK_VENCBRG_MAIN, "vencbrg_mainclk", 0, JH7100_CLK_VENC_BUS),
++	JH71X0_GDIV(JH7100_CLK_VENC_BCLK, "venc_bclk", 0, 8, JH7100_CLK_VCDECBUS_SRC),
++	JH71X0_GDIV(JH7100_CLK_VENC_CCLK, "venc_cclk", 0, 8, JH7100_CLK_CDEC_ROOT),
++	JH71X0_GATE(JH7100_CLK_VENC_APB, "venc_apb", 0, JH7100_CLK_APB1_BUS),
++	JH71X0_GDIV(JH7100_CLK_DDRPLL_DIV2, "ddrpll_div2", CLK_IS_CRITICAL, 2, JH7100_CLK_PLL1_OUT),
++	JH71X0_GDIV(JH7100_CLK_DDRPLL_DIV4, "ddrpll_div4", CLK_IS_CRITICAL, 2,
++		    JH7100_CLK_DDRPLL_DIV2),
++	JH71X0_GDIV(JH7100_CLK_DDRPLL_DIV8, "ddrpll_div8", CLK_IS_CRITICAL, 2,
++		    JH7100_CLK_DDRPLL_DIV4),
++	JH71X0_GDIV(JH7100_CLK_DDROSC_DIV2, "ddrosc_div2", CLK_IS_CRITICAL, 2, JH7100_CLK_OSC_SYS),
++	JH71X0_GMUX(JH7100_CLK_DDRC0, "ddrc0", CLK_IS_CRITICAL, 4,
+ 		    JH7100_CLK_DDROSC_DIV2,
+ 		    JH7100_CLK_DDRPLL_DIV2,
+ 		    JH7100_CLK_DDRPLL_DIV4,
+ 		    JH7100_CLK_DDRPLL_DIV8),
+-	JH7100_GMUX(JH7100_CLK_DDRC1, "ddrc1", CLK_IS_CRITICAL, 4,
++	JH71X0_GMUX(JH7100_CLK_DDRC1, "ddrc1", CLK_IS_CRITICAL, 4,
+ 		    JH7100_CLK_DDROSC_DIV2,
+ 		    JH7100_CLK_DDRPLL_DIV2,
+ 		    JH7100_CLK_DDRPLL_DIV4,
+ 		    JH7100_CLK_DDRPLL_DIV8),
+-	JH7100_GATE(JH7100_CLK_DDRPHY_APB, "ddrphy_apb", 0, JH7100_CLK_APB1_BUS),
+-	JH7100__DIV(JH7100_CLK_NOC_ROB, "noc_rob", 8, JH7100_CLK_CPUNBUS_ROOT_DIV),
+-	JH7100__DIV(JH7100_CLK_NOC_COG, "noc_cog", 8, JH7100_CLK_DLA_ROOT),
+-	JH7100_GATE(JH7100_CLK_NNE_AHB, "nne_ahb", 0, JH7100_CLK_AHB_BUS),
+-	JH7100__DIV(JH7100_CLK_NNEBUS_SRC1, "nnebus_src1", 4, JH7100_CLK_DSP_ROOT),
+-	JH7100__MUX(JH7100_CLK_NNE_BUS, "nne_bus", 2,
++	JH71X0_GATE(JH7100_CLK_DDRPHY_APB, "ddrphy_apb", 0, JH7100_CLK_APB1_BUS),
++	JH71X0__DIV(JH7100_CLK_NOC_ROB, "noc_rob", 8, JH7100_CLK_CPUNBUS_ROOT_DIV),
++	JH71X0__DIV(JH7100_CLK_NOC_COG, "noc_cog", 8, JH7100_CLK_DLA_ROOT),
++	JH71X0_GATE(JH7100_CLK_NNE_AHB, "nne_ahb", 0, JH7100_CLK_AHB_BUS),
++	JH71X0__DIV(JH7100_CLK_NNEBUS_SRC1, "nnebus_src1", 4, JH7100_CLK_DSP_ROOT),
++	JH71X0__MUX(JH7100_CLK_NNE_BUS, "nne_bus", 2,
+ 		    JH7100_CLK_CPU_AXI,
+ 		    JH7100_CLK_NNEBUS_SRC1),
+-	JH7100_GATE(JH7100_CLK_NNE_AXI, "nne_axi", 0, JH7100_CLK_NNE_BUS),
+-	JH7100_GATE(JH7100_CLK_NNENOC_AXI, "nnenoc_axi", 0, JH7100_CLK_NNE_BUS),
+-	JH7100_GATE(JH7100_CLK_DLASLV_AXI, "dlaslv_axi", 0, JH7100_CLK_NNE_BUS),
+-	JH7100_GATE(JH7100_CLK_DSPX2C_AXI, "dspx2c_axi", CLK_IS_CRITICAL, JH7100_CLK_NNE_BUS),
+-	JH7100__DIV(JH7100_CLK_HIFI4_SRC, "hifi4_src", 4, JH7100_CLK_CDECHIFI4_ROOT),
+-	JH7100__DIV(JH7100_CLK_HIFI4_COREFREE, "hifi4_corefree", 8, JH7100_CLK_HIFI4_SRC),
+-	JH7100_GATE(JH7100_CLK_HIFI4_CORE, "hifi4_core", 0, JH7100_CLK_HIFI4_COREFREE),
+-	JH7100__DIV(JH7100_CLK_HIFI4_BUS, "hifi4_bus", 8, JH7100_CLK_HIFI4_COREFREE),
+-	JH7100_GATE(JH7100_CLK_HIFI4_AXI, "hifi4_axi", 0, JH7100_CLK_HIFI4_BUS),
+-	JH7100_GATE(JH7100_CLK_HIFI4NOC_AXI, "hifi4noc_axi", 0, JH7100_CLK_HIFI4_BUS),
+-	JH7100__DIV(JH7100_CLK_SGDMA1P_BUS, "sgdma1p_bus", 8, JH7100_CLK_CPUNBUS_ROOT_DIV),
+-	JH7100_GATE(JH7100_CLK_SGDMA1P_AXI, "sgdma1p_axi", 0, JH7100_CLK_SGDMA1P_BUS),
+-	JH7100_GATE(JH7100_CLK_DMA1P_AXI, "dma1p_axi", 0, JH7100_CLK_SGDMA1P_BUS),
+-	JH7100_GDIV(JH7100_CLK_X2C_AXI, "x2c_axi", CLK_IS_CRITICAL, 8, JH7100_CLK_CPUNBUS_ROOT_DIV),
+-	JH7100__DIV(JH7100_CLK_USB_BUS, "usb_bus", 8, JH7100_CLK_CPUNBUS_ROOT_DIV),
+-	JH7100_GATE(JH7100_CLK_USB_AXI, "usb_axi", 0, JH7100_CLK_USB_BUS),
+-	JH7100_GATE(JH7100_CLK_USBNOC_AXI, "usbnoc_axi", 0, JH7100_CLK_USB_BUS),
+-	JH7100__DIV(JH7100_CLK_USBPHY_ROOTDIV, "usbphy_rootdiv", 4, JH7100_CLK_GMACUSB_ROOT),
+-	JH7100_GDIV(JH7100_CLK_USBPHY_125M, "usbphy_125m", 0, 8, JH7100_CLK_USBPHY_ROOTDIV),
+-	JH7100_GDIV(JH7100_CLK_USBPHY_PLLDIV25M, "usbphy_plldiv25m", 0, 32, JH7100_CLK_USBPHY_ROOTDIV),
+-	JH7100__MUX(JH7100_CLK_USBPHY_25M, "usbphy_25m", 2,
++	JH71X0_GATE(JH7100_CLK_NNE_AXI, "nne_axi", 0, JH7100_CLK_NNE_BUS),
++	JH71X0_GATE(JH7100_CLK_NNENOC_AXI, "nnenoc_axi", 0, JH7100_CLK_NNE_BUS),
++	JH71X0_GATE(JH7100_CLK_DLASLV_AXI, "dlaslv_axi", 0, JH7100_CLK_NNE_BUS),
++	JH71X0_GATE(JH7100_CLK_DSPX2C_AXI, "dspx2c_axi", CLK_IS_CRITICAL, JH7100_CLK_NNE_BUS),
++	JH71X0__DIV(JH7100_CLK_HIFI4_SRC, "hifi4_src", 4, JH7100_CLK_CDECHIFI4_ROOT),
++	JH71X0__DIV(JH7100_CLK_HIFI4_COREFREE, "hifi4_corefree", 8, JH7100_CLK_HIFI4_SRC),
++	JH71X0_GATE(JH7100_CLK_HIFI4_CORE, "hifi4_core", 0, JH7100_CLK_HIFI4_COREFREE),
++	JH71X0__DIV(JH7100_CLK_HIFI4_BUS, "hifi4_bus", 8, JH7100_CLK_HIFI4_COREFREE),
++	JH71X0_GATE(JH7100_CLK_HIFI4_AXI, "hifi4_axi", 0, JH7100_CLK_HIFI4_BUS),
++	JH71X0_GATE(JH7100_CLK_HIFI4NOC_AXI, "hifi4noc_axi", 0, JH7100_CLK_HIFI4_BUS),
++	JH71X0__DIV(JH7100_CLK_SGDMA1P_BUS, "sgdma1p_bus", 8, JH7100_CLK_CPUNBUS_ROOT_DIV),
++	JH71X0_GATE(JH7100_CLK_SGDMA1P_AXI, "sgdma1p_axi", 0, JH7100_CLK_SGDMA1P_BUS),
++	JH71X0_GATE(JH7100_CLK_DMA1P_AXI, "dma1p_axi", 0, JH7100_CLK_SGDMA1P_BUS),
++	JH71X0_GDIV(JH7100_CLK_X2C_AXI, "x2c_axi", CLK_IS_CRITICAL, 8, JH7100_CLK_CPUNBUS_ROOT_DIV),
++	JH71X0__DIV(JH7100_CLK_USB_BUS, "usb_bus", 8, JH7100_CLK_CPUNBUS_ROOT_DIV),
++	JH71X0_GATE(JH7100_CLK_USB_AXI, "usb_axi", 0, JH7100_CLK_USB_BUS),
++	JH71X0_GATE(JH7100_CLK_USBNOC_AXI, "usbnoc_axi", 0, JH7100_CLK_USB_BUS),
++	JH71X0__DIV(JH7100_CLK_USBPHY_ROOTDIV, "usbphy_rootdiv", 4, JH7100_CLK_GMACUSB_ROOT),
++	JH71X0_GDIV(JH7100_CLK_USBPHY_125M, "usbphy_125m", 0, 8, JH7100_CLK_USBPHY_ROOTDIV),
++	JH71X0_GDIV(JH7100_CLK_USBPHY_PLLDIV25M, "usbphy_plldiv25m", 0, 32,
++		    JH7100_CLK_USBPHY_ROOTDIV),
++	JH71X0__MUX(JH7100_CLK_USBPHY_25M, "usbphy_25m", 2,
+ 		    JH7100_CLK_OSC_SYS,
+ 		    JH7100_CLK_USBPHY_PLLDIV25M),
+-	JH7100_FDIV(JH7100_CLK_AUDIO_DIV, "audio_div", JH7100_CLK_AUDIO_ROOT),
+-	JH7100_GATE(JH7100_CLK_AUDIO_SRC, "audio_src", 0, JH7100_CLK_AUDIO_DIV),
+-	JH7100_GATE(JH7100_CLK_AUDIO_12288, "audio_12288", 0, JH7100_CLK_OSC_AUD),
+-	JH7100_GDIV(JH7100_CLK_VIN_SRC, "vin_src", 0, 4, JH7100_CLK_VIN_ROOT),
+-	JH7100__DIV(JH7100_CLK_ISP0_BUS, "isp0_bus", 8, JH7100_CLK_VIN_SRC),
+-	JH7100_GATE(JH7100_CLK_ISP0_AXI, "isp0_axi", 0, JH7100_CLK_ISP0_BUS),
+-	JH7100_GATE(JH7100_CLK_ISP0NOC_AXI, "isp0noc_axi", 0, JH7100_CLK_ISP0_BUS),
+-	JH7100_GATE(JH7100_CLK_ISPSLV_AXI, "ispslv_axi", 0, JH7100_CLK_ISP0_BUS),
+-	JH7100__DIV(JH7100_CLK_ISP1_BUS, "isp1_bus", 8, JH7100_CLK_VIN_SRC),
+-	JH7100_GATE(JH7100_CLK_ISP1_AXI, "isp1_axi", 0, JH7100_CLK_ISP1_BUS),
+-	JH7100_GATE(JH7100_CLK_ISP1NOC_AXI, "isp1noc_axi", 0, JH7100_CLK_ISP1_BUS),
+-	JH7100__DIV(JH7100_CLK_VIN_BUS, "vin_bus", 8, JH7100_CLK_VIN_SRC),
+-	JH7100_GATE(JH7100_CLK_VIN_AXI, "vin_axi", 0, JH7100_CLK_VIN_BUS),
+-	JH7100_GATE(JH7100_CLK_VINNOC_AXI, "vinnoc_axi", 0, JH7100_CLK_VIN_BUS),
+-	JH7100_GDIV(JH7100_CLK_VOUT_SRC, "vout_src", 0, 4, JH7100_CLK_VOUT_ROOT),
+-	JH7100__DIV(JH7100_CLK_DISPBUS_SRC, "dispbus_src", 4, JH7100_CLK_VOUTBUS_ROOT),
+-	JH7100__DIV(JH7100_CLK_DISP_BUS, "disp_bus", 4, JH7100_CLK_DISPBUS_SRC),
+-	JH7100_GATE(JH7100_CLK_DISP_AXI, "disp_axi", 0, JH7100_CLK_DISP_BUS),
+-	JH7100_GATE(JH7100_CLK_DISPNOC_AXI, "dispnoc_axi", 0, JH7100_CLK_DISP_BUS),
+-	JH7100_GATE(JH7100_CLK_SDIO0_AHB, "sdio0_ahb", 0, JH7100_CLK_AHB_BUS),
+-	JH7100_GDIV(JH7100_CLK_SDIO0_CCLKINT, "sdio0_cclkint", 0, 24, JH7100_CLK_PERH0_SRC),
+-	JH7100__INV(JH7100_CLK_SDIO0_CCLKINT_INV, "sdio0_cclkint_inv", JH7100_CLK_SDIO0_CCLKINT),
+-	JH7100_GATE(JH7100_CLK_SDIO1_AHB, "sdio1_ahb", 0, JH7100_CLK_AHB_BUS),
+-	JH7100_GDIV(JH7100_CLK_SDIO1_CCLKINT, "sdio1_cclkint", 0, 24, JH7100_CLK_PERH1_SRC),
+-	JH7100__INV(JH7100_CLK_SDIO1_CCLKINT_INV, "sdio1_cclkint_inv", JH7100_CLK_SDIO1_CCLKINT),
+-	JH7100_GATE(JH7100_CLK_GMAC_AHB, "gmac_ahb", 0, JH7100_CLK_AHB_BUS),
+-	JH7100__DIV(JH7100_CLK_GMAC_ROOT_DIV, "gmac_root_div", 8, JH7100_CLK_GMACUSB_ROOT),
+-	JH7100_GDIV(JH7100_CLK_GMAC_PTP_REF, "gmac_ptp_refclk", 0, 31, JH7100_CLK_GMAC_ROOT_DIV),
+-	JH7100_GDIV(JH7100_CLK_GMAC_GTX, "gmac_gtxclk", 0, 255, JH7100_CLK_GMAC_ROOT_DIV),
+-	JH7100_GDIV(JH7100_CLK_GMAC_RMII_TX, "gmac_rmii_txclk", 0, 8, JH7100_CLK_GMAC_RMII_REF),
+-	JH7100_GDIV(JH7100_CLK_GMAC_RMII_RX, "gmac_rmii_rxclk", 0, 8, JH7100_CLK_GMAC_RMII_REF),
+-	JH7100__MUX(JH7100_CLK_GMAC_TX, "gmac_tx", 3,
++	JH71X0_FDIV(JH7100_CLK_AUDIO_DIV, "audio_div", JH7100_CLK_AUDIO_ROOT),
++	JH71X0_GATE(JH7100_CLK_AUDIO_SRC, "audio_src", 0, JH7100_CLK_AUDIO_DIV),
++	JH71X0_GATE(JH7100_CLK_AUDIO_12288, "audio_12288", 0, JH7100_CLK_OSC_AUD),
++	JH71X0_GDIV(JH7100_CLK_VIN_SRC, "vin_src", 0, 4, JH7100_CLK_VIN_ROOT),
++	JH71X0__DIV(JH7100_CLK_ISP0_BUS, "isp0_bus", 8, JH7100_CLK_VIN_SRC),
++	JH71X0_GATE(JH7100_CLK_ISP0_AXI, "isp0_axi", 0, JH7100_CLK_ISP0_BUS),
++	JH71X0_GATE(JH7100_CLK_ISP0NOC_AXI, "isp0noc_axi", 0, JH7100_CLK_ISP0_BUS),
++	JH71X0_GATE(JH7100_CLK_ISPSLV_AXI, "ispslv_axi", 0, JH7100_CLK_ISP0_BUS),
++	JH71X0__DIV(JH7100_CLK_ISP1_BUS, "isp1_bus", 8, JH7100_CLK_VIN_SRC),
++	JH71X0_GATE(JH7100_CLK_ISP1_AXI, "isp1_axi", 0, JH7100_CLK_ISP1_BUS),
++	JH71X0_GATE(JH7100_CLK_ISP1NOC_AXI, "isp1noc_axi", 0, JH7100_CLK_ISP1_BUS),
++	JH71X0__DIV(JH7100_CLK_VIN_BUS, "vin_bus", 8, JH7100_CLK_VIN_SRC),
++	JH71X0_GATE(JH7100_CLK_VIN_AXI, "vin_axi", 0, JH7100_CLK_VIN_BUS),
++	JH71X0_GATE(JH7100_CLK_VINNOC_AXI, "vinnoc_axi", 0, JH7100_CLK_VIN_BUS),
++	JH71X0_GDIV(JH7100_CLK_VOUT_SRC, "vout_src", 0, 4, JH7100_CLK_VOUT_ROOT),
++	JH71X0__DIV(JH7100_CLK_DISPBUS_SRC, "dispbus_src", 4, JH7100_CLK_VOUTBUS_ROOT),
++	JH71X0__DIV(JH7100_CLK_DISP_BUS, "disp_bus", 4, JH7100_CLK_DISPBUS_SRC),
++	JH71X0_GATE(JH7100_CLK_DISP_AXI, "disp_axi", 0, JH7100_CLK_DISP_BUS),
++	JH71X0_GATE(JH7100_CLK_DISPNOC_AXI, "dispnoc_axi", 0, JH7100_CLK_DISP_BUS),
++	JH71X0_GATE(JH7100_CLK_SDIO0_AHB, "sdio0_ahb", 0, JH7100_CLK_AHB_BUS),
++	JH71X0_GDIV(JH7100_CLK_SDIO0_CCLKINT, "sdio0_cclkint", 0, 24, JH7100_CLK_PERH0_SRC),
++	JH71X0__INV(JH7100_CLK_SDIO0_CCLKINT_INV, "sdio0_cclkint_inv", JH7100_CLK_SDIO0_CCLKINT),
++	JH71X0_GATE(JH7100_CLK_SDIO1_AHB, "sdio1_ahb", 0, JH7100_CLK_AHB_BUS),
++	JH71X0_GDIV(JH7100_CLK_SDIO1_CCLKINT, "sdio1_cclkint", 0, 24, JH7100_CLK_PERH1_SRC),
++	JH71X0__INV(JH7100_CLK_SDIO1_CCLKINT_INV, "sdio1_cclkint_inv", JH7100_CLK_SDIO1_CCLKINT),
++	JH71X0_GATE(JH7100_CLK_GMAC_AHB, "gmac_ahb", 0, JH7100_CLK_AHB_BUS),
++	JH71X0__DIV(JH7100_CLK_GMAC_ROOT_DIV, "gmac_root_div", 8, JH7100_CLK_GMACUSB_ROOT),
++	JH71X0_GDIV(JH7100_CLK_GMAC_PTP_REF, "gmac_ptp_refclk", 0, 31, JH7100_CLK_GMAC_ROOT_DIV),
++	JH71X0_GDIV(JH7100_CLK_GMAC_GTX, "gmac_gtxclk", 0, 255, JH7100_CLK_GMAC_ROOT_DIV),
++	JH71X0_GDIV(JH7100_CLK_GMAC_RMII_TX, "gmac_rmii_txclk", 0, 8, JH7100_CLK_GMAC_RMII_REF),
++	JH71X0_GDIV(JH7100_CLK_GMAC_RMII_RX, "gmac_rmii_rxclk", 0, 8, JH7100_CLK_GMAC_RMII_REF),
++	JH71X0__MUX(JH7100_CLK_GMAC_TX, "gmac_tx", 3,
+ 		    JH7100_CLK_GMAC_GTX,
+ 		    JH7100_CLK_GMAC_TX_INV,
+ 		    JH7100_CLK_GMAC_RMII_TX),
+-	JH7100__INV(JH7100_CLK_GMAC_TX_INV, "gmac_tx_inv", JH7100_CLK_GMAC_TX),
+-	JH7100__MUX(JH7100_CLK_GMAC_RX_PRE, "gmac_rx_pre", 2,
++	JH71X0__INV(JH7100_CLK_GMAC_TX_INV, "gmac_tx_inv", JH7100_CLK_GMAC_TX),
++	JH71X0__MUX(JH7100_CLK_GMAC_RX_PRE, "gmac_rx_pre", 2,
+ 		    JH7100_CLK_GMAC_GR_MII_RX,
+ 		    JH7100_CLK_GMAC_RMII_RX),
+-	JH7100__INV(JH7100_CLK_GMAC_RX_INV, "gmac_rx_inv", JH7100_CLK_GMAC_RX_PRE),
+-	JH7100_GATE(JH7100_CLK_GMAC_RMII, "gmac_rmii", 0, JH7100_CLK_GMAC_RMII_REF),
+-	JH7100_GDIV(JH7100_CLK_GMAC_TOPHYREF, "gmac_tophyref", 0, 127, JH7100_CLK_GMAC_ROOT_DIV),
+-	JH7100_GATE(JH7100_CLK_SPI2AHB_AHB, "spi2ahb_ahb", 0, JH7100_CLK_AHB_BUS),
+-	JH7100_GDIV(JH7100_CLK_SPI2AHB_CORE, "spi2ahb_core", 0, 31, JH7100_CLK_PERH0_SRC),
+-	JH7100_GATE(JH7100_CLK_EZMASTER_AHB, "ezmaster_ahb", 0, JH7100_CLK_AHB_BUS),
+-	JH7100_GATE(JH7100_CLK_E24_AHB, "e24_ahb", 0, JH7100_CLK_AHB_BUS),
+-	JH7100_GATE(JH7100_CLK_E24RTC_TOGGLE, "e24rtc_toggle", 0, JH7100_CLK_OSC_SYS),
+-	JH7100_GATE(JH7100_CLK_QSPI_AHB, "qspi_ahb", 0, JH7100_CLK_AHB_BUS),
+-	JH7100_GATE(JH7100_CLK_QSPI_APB, "qspi_apb", 0, JH7100_CLK_APB1_BUS),
+-	JH7100_GDIV(JH7100_CLK_QSPI_REF, "qspi_refclk", 0, 31, JH7100_CLK_PERH0_SRC),
+-	JH7100_GATE(JH7100_CLK_SEC_AHB, "sec_ahb", 0, JH7100_CLK_AHB_BUS),
+-	JH7100_GATE(JH7100_CLK_AES, "aes_clk", 0, JH7100_CLK_SEC_AHB),
+-	JH7100_GATE(JH7100_CLK_SHA, "sha_clk", 0, JH7100_CLK_SEC_AHB),
+-	JH7100_GATE(JH7100_CLK_PKA, "pka_clk", 0, JH7100_CLK_SEC_AHB),
+-	JH7100_GATE(JH7100_CLK_TRNG_APB, "trng_apb", 0, JH7100_CLK_APB1_BUS),
+-	JH7100_GATE(JH7100_CLK_OTP_APB, "otp_apb", 0, JH7100_CLK_APB1_BUS),
+-	JH7100_GATE(JH7100_CLK_UART0_APB, "uart0_apb", 0, JH7100_CLK_APB1_BUS),
+-	JH7100_GDIV(JH7100_CLK_UART0_CORE, "uart0_core", 0, 63, JH7100_CLK_PERH1_SRC),
+-	JH7100_GATE(JH7100_CLK_UART1_APB, "uart1_apb", 0, JH7100_CLK_APB1_BUS),
+-	JH7100_GDIV(JH7100_CLK_UART1_CORE, "uart1_core", 0, 63, JH7100_CLK_PERH1_SRC),
+-	JH7100_GATE(JH7100_CLK_SPI0_APB, "spi0_apb", 0, JH7100_CLK_APB1_BUS),
+-	JH7100_GDIV(JH7100_CLK_SPI0_CORE, "spi0_core", 0, 63, JH7100_CLK_PERH1_SRC),
+-	JH7100_GATE(JH7100_CLK_SPI1_APB, "spi1_apb", 0, JH7100_CLK_APB1_BUS),
+-	JH7100_GDIV(JH7100_CLK_SPI1_CORE, "spi1_core", 0, 63, JH7100_CLK_PERH1_SRC),
+-	JH7100_GATE(JH7100_CLK_I2C0_APB, "i2c0_apb", 0, JH7100_CLK_APB1_BUS),
+-	JH7100_GDIV(JH7100_CLK_I2C0_CORE, "i2c0_core", 0, 63, JH7100_CLK_PERH1_SRC),
+-	JH7100_GATE(JH7100_CLK_I2C1_APB, "i2c1_apb", 0, JH7100_CLK_APB1_BUS),
+-	JH7100_GDIV(JH7100_CLK_I2C1_CORE, "i2c1_core", 0, 63, JH7100_CLK_PERH1_SRC),
+-	JH7100_GATE(JH7100_CLK_GPIO_APB, "gpio_apb", 0, JH7100_CLK_APB1_BUS),
+-	JH7100_GATE(JH7100_CLK_UART2_APB, "uart2_apb", 0, JH7100_CLK_APB2_BUS),
+-	JH7100_GDIV(JH7100_CLK_UART2_CORE, "uart2_core", 0, 63, JH7100_CLK_PERH0_SRC),
+-	JH7100_GATE(JH7100_CLK_UART3_APB, "uart3_apb", 0, JH7100_CLK_APB2_BUS),
+-	JH7100_GDIV(JH7100_CLK_UART3_CORE, "uart3_core", 0, 63, JH7100_CLK_PERH0_SRC),
+-	JH7100_GATE(JH7100_CLK_SPI2_APB, "spi2_apb", 0, JH7100_CLK_APB2_BUS),
+-	JH7100_GDIV(JH7100_CLK_SPI2_CORE, "spi2_core", 0, 63, JH7100_CLK_PERH0_SRC),
+-	JH7100_GATE(JH7100_CLK_SPI3_APB, "spi3_apb", 0, JH7100_CLK_APB2_BUS),
+-	JH7100_GDIV(JH7100_CLK_SPI3_CORE, "spi3_core", 0, 63, JH7100_CLK_PERH0_SRC),
+-	JH7100_GATE(JH7100_CLK_I2C2_APB, "i2c2_apb", 0, JH7100_CLK_APB2_BUS),
+-	JH7100_GDIV(JH7100_CLK_I2C2_CORE, "i2c2_core", 0, 63, JH7100_CLK_PERH0_SRC),
+-	JH7100_GATE(JH7100_CLK_I2C3_APB, "i2c3_apb", 0, JH7100_CLK_APB2_BUS),
+-	JH7100_GDIV(JH7100_CLK_I2C3_CORE, "i2c3_core", 0, 63, JH7100_CLK_PERH0_SRC),
+-	JH7100_GATE(JH7100_CLK_WDTIMER_APB, "wdtimer_apb", 0, JH7100_CLK_APB2_BUS),
+-	JH7100_GDIV(JH7100_CLK_WDT_CORE, "wdt_coreclk", 0, 63, JH7100_CLK_PERH0_SRC),
+-	JH7100_GDIV(JH7100_CLK_TIMER0_CORE, "timer0_coreclk", 0, 63, JH7100_CLK_PERH0_SRC),
+-	JH7100_GDIV(JH7100_CLK_TIMER1_CORE, "timer1_coreclk", 0, 63, JH7100_CLK_PERH0_SRC),
+-	JH7100_GDIV(JH7100_CLK_TIMER2_CORE, "timer2_coreclk", 0, 63, JH7100_CLK_PERH0_SRC),
+-	JH7100_GDIV(JH7100_CLK_TIMER3_CORE, "timer3_coreclk", 0, 63, JH7100_CLK_PERH0_SRC),
+-	JH7100_GDIV(JH7100_CLK_TIMER4_CORE, "timer4_coreclk", 0, 63, JH7100_CLK_PERH0_SRC),
+-	JH7100_GDIV(JH7100_CLK_TIMER5_CORE, "timer5_coreclk", 0, 63, JH7100_CLK_PERH0_SRC),
+-	JH7100_GDIV(JH7100_CLK_TIMER6_CORE, "timer6_coreclk", 0, 63, JH7100_CLK_PERH0_SRC),
+-	JH7100_GATE(JH7100_CLK_VP6INTC_APB, "vp6intc_apb", 0, JH7100_CLK_APB2_BUS),
+-	JH7100_GATE(JH7100_CLK_PWM_APB, "pwm_apb", 0, JH7100_CLK_APB2_BUS),
+-	JH7100_GATE(JH7100_CLK_MSI_APB, "msi_apb", 0, JH7100_CLK_APB2_BUS),
+-	JH7100_GATE(JH7100_CLK_TEMP_APB, "temp_apb", 0, JH7100_CLK_APB2_BUS),
+-	JH7100_GDIV(JH7100_CLK_TEMP_SENSE, "temp_sense", 0, 31, JH7100_CLK_OSC_SYS),
+-	JH7100_GATE(JH7100_CLK_SYSERR_APB, "syserr_apb", 0, JH7100_CLK_APB2_BUS),
++	JH71X0__INV(JH7100_CLK_GMAC_RX_INV, "gmac_rx_inv", JH7100_CLK_GMAC_RX_PRE),
++	JH71X0_GATE(JH7100_CLK_GMAC_RMII, "gmac_rmii", 0, JH7100_CLK_GMAC_RMII_REF),
++	JH71X0_GDIV(JH7100_CLK_GMAC_TOPHYREF, "gmac_tophyref", 0, 127, JH7100_CLK_GMAC_ROOT_DIV),
++	JH71X0_GATE(JH7100_CLK_SPI2AHB_AHB, "spi2ahb_ahb", 0, JH7100_CLK_AHB_BUS),
++	JH71X0_GDIV(JH7100_CLK_SPI2AHB_CORE, "spi2ahb_core", 0, 31, JH7100_CLK_PERH0_SRC),
++	JH71X0_GATE(JH7100_CLK_EZMASTER_AHB, "ezmaster_ahb", 0, JH7100_CLK_AHB_BUS),
++	JH71X0_GATE(JH7100_CLK_E24_AHB, "e24_ahb", 0, JH7100_CLK_AHB_BUS),
++	JH71X0_GATE(JH7100_CLK_E24RTC_TOGGLE, "e24rtc_toggle", 0, JH7100_CLK_OSC_SYS),
++	JH71X0_GATE(JH7100_CLK_QSPI_AHB, "qspi_ahb", 0, JH7100_CLK_AHB_BUS),
++	JH71X0_GATE(JH7100_CLK_QSPI_APB, "qspi_apb", 0, JH7100_CLK_APB1_BUS),
++	JH71X0_GDIV(JH7100_CLK_QSPI_REF, "qspi_refclk", 0, 31, JH7100_CLK_PERH0_SRC),
++	JH71X0_GATE(JH7100_CLK_SEC_AHB, "sec_ahb", 0, JH7100_CLK_AHB_BUS),
++	JH71X0_GATE(JH7100_CLK_AES, "aes_clk", 0, JH7100_CLK_SEC_AHB),
++	JH71X0_GATE(JH7100_CLK_SHA, "sha_clk", 0, JH7100_CLK_SEC_AHB),
++	JH71X0_GATE(JH7100_CLK_PKA, "pka_clk", 0, JH7100_CLK_SEC_AHB),
++	JH71X0_GATE(JH7100_CLK_TRNG_APB, "trng_apb", 0, JH7100_CLK_APB1_BUS),
++	JH71X0_GATE(JH7100_CLK_OTP_APB, "otp_apb", 0, JH7100_CLK_APB1_BUS),
++	JH71X0_GATE(JH7100_CLK_UART0_APB, "uart0_apb", 0, JH7100_CLK_APB1_BUS),
++	JH71X0_GDIV(JH7100_CLK_UART0_CORE, "uart0_core", 0, 63, JH7100_CLK_PERH1_SRC),
++	JH71X0_GATE(JH7100_CLK_UART1_APB, "uart1_apb", 0, JH7100_CLK_APB1_BUS),
++	JH71X0_GDIV(JH7100_CLK_UART1_CORE, "uart1_core", 0, 63, JH7100_CLK_PERH1_SRC),
++	JH71X0_GATE(JH7100_CLK_SPI0_APB, "spi0_apb", 0, JH7100_CLK_APB1_BUS),
++	JH71X0_GDIV(JH7100_CLK_SPI0_CORE, "spi0_core", 0, 63, JH7100_CLK_PERH1_SRC),
++	JH71X0_GATE(JH7100_CLK_SPI1_APB, "spi1_apb", 0, JH7100_CLK_APB1_BUS),
++	JH71X0_GDIV(JH7100_CLK_SPI1_CORE, "spi1_core", 0, 63, JH7100_CLK_PERH1_SRC),
++	JH71X0_GATE(JH7100_CLK_I2C0_APB, "i2c0_apb", 0, JH7100_CLK_APB1_BUS),
++	JH71X0_GDIV(JH7100_CLK_I2C0_CORE, "i2c0_core", 0, 63, JH7100_CLK_PERH1_SRC),
++	JH71X0_GATE(JH7100_CLK_I2C1_APB, "i2c1_apb", 0, JH7100_CLK_APB1_BUS),
++	JH71X0_GDIV(JH7100_CLK_I2C1_CORE, "i2c1_core", 0, 63, JH7100_CLK_PERH1_SRC),
++	JH71X0_GATE(JH7100_CLK_GPIO_APB, "gpio_apb", 0, JH7100_CLK_APB1_BUS),
++	JH71X0_GATE(JH7100_CLK_UART2_APB, "uart2_apb", 0, JH7100_CLK_APB2_BUS),
++	JH71X0_GDIV(JH7100_CLK_UART2_CORE, "uart2_core", 0, 63, JH7100_CLK_PERH0_SRC),
++	JH71X0_GATE(JH7100_CLK_UART3_APB, "uart3_apb", 0, JH7100_CLK_APB2_BUS),
++	JH71X0_GDIV(JH7100_CLK_UART3_CORE, "uart3_core", 0, 63, JH7100_CLK_PERH0_SRC),
++	JH71X0_GATE(JH7100_CLK_SPI2_APB, "spi2_apb", 0, JH7100_CLK_APB2_BUS),
++	JH71X0_GDIV(JH7100_CLK_SPI2_CORE, "spi2_core", 0, 63, JH7100_CLK_PERH0_SRC),
++	JH71X0_GATE(JH7100_CLK_SPI3_APB, "spi3_apb", 0, JH7100_CLK_APB2_BUS),
++	JH71X0_GDIV(JH7100_CLK_SPI3_CORE, "spi3_core", 0, 63, JH7100_CLK_PERH0_SRC),
++	JH71X0_GATE(JH7100_CLK_I2C2_APB, "i2c2_apb", 0, JH7100_CLK_APB2_BUS),
++	JH71X0_GDIV(JH7100_CLK_I2C2_CORE, "i2c2_core", 0, 63, JH7100_CLK_PERH0_SRC),
++	JH71X0_GATE(JH7100_CLK_I2C3_APB, "i2c3_apb", 0, JH7100_CLK_APB2_BUS),
++	JH71X0_GDIV(JH7100_CLK_I2C3_CORE, "i2c3_core", 0, 63, JH7100_CLK_PERH0_SRC),
++	JH71X0_GATE(JH7100_CLK_WDTIMER_APB, "wdtimer_apb", 0, JH7100_CLK_APB2_BUS),
++	JH71X0_GDIV(JH7100_CLK_WDT_CORE, "wdt_coreclk", 0, 63, JH7100_CLK_PERH0_SRC),
++	JH71X0_GDIV(JH7100_CLK_TIMER0_CORE, "timer0_coreclk", 0, 63, JH7100_CLK_PERH0_SRC),
++	JH71X0_GDIV(JH7100_CLK_TIMER1_CORE, "timer1_coreclk", 0, 63, JH7100_CLK_PERH0_SRC),
++	JH71X0_GDIV(JH7100_CLK_TIMER2_CORE, "timer2_coreclk", 0, 63, JH7100_CLK_PERH0_SRC),
++	JH71X0_GDIV(JH7100_CLK_TIMER3_CORE, "timer3_coreclk", 0, 63, JH7100_CLK_PERH0_SRC),
++	JH71X0_GDIV(JH7100_CLK_TIMER4_CORE, "timer4_coreclk", 0, 63, JH7100_CLK_PERH0_SRC),
++	JH71X0_GDIV(JH7100_CLK_TIMER5_CORE, "timer5_coreclk", 0, 63, JH7100_CLK_PERH0_SRC),
++	JH71X0_GDIV(JH7100_CLK_TIMER6_CORE, "timer6_coreclk", 0, 63, JH7100_CLK_PERH0_SRC),
++	JH71X0_GATE(JH7100_CLK_VP6INTC_APB, "vp6intc_apb", 0, JH7100_CLK_APB2_BUS),
++	JH71X0_GATE(JH7100_CLK_PWM_APB, "pwm_apb", 0, JH7100_CLK_APB2_BUS),
++	JH71X0_GATE(JH7100_CLK_MSI_APB, "msi_apb", 0, JH7100_CLK_APB2_BUS),
++	JH71X0_GATE(JH7100_CLK_TEMP_APB, "temp_apb", 0, JH7100_CLK_APB2_BUS),
++	JH71X0_GDIV(JH7100_CLK_TEMP_SENSE, "temp_sense", 0, 31, JH7100_CLK_OSC_SYS),
++	JH71X0_GATE(JH7100_CLK_SYSERR_APB, "syserr_apb", 0, JH7100_CLK_APB2_BUS),
+ };
+ 
+ static struct clk_hw *jh7100_clk_get(struct of_phandle_args *clkspec, void *data)
+ {
+-	struct jh7100_clk_priv *priv = data;
++	struct jh71x0_clk_priv *priv = data;
+ 	unsigned int idx = clkspec->args[0];
+ 
+ 	if (idx < JH7100_CLK_PLL0_OUT)
+@@ -280,7 +283,7 @@ static struct clk_hw *jh7100_clk_get(str
+ 
+ static int __init clk_starfive_jh7100_probe(struct platform_device *pdev)
+ {
+-	struct jh7100_clk_priv *priv;
++	struct jh71x0_clk_priv *priv;
+ 	unsigned int idx;
+ 	int ret;
+ 
+@@ -314,12 +317,12 @@ static int __init clk_starfive_jh7100_pr
+ 		struct clk_parent_data parents[4] = {};
+ 		struct clk_init_data init = {
+ 			.name = jh7100_clk_data[idx].name,
+-			.ops = starfive_jh7100_clk_ops(max),
++			.ops = starfive_jh71x0_clk_ops(max),
+ 			.parent_data = parents,
+-			.num_parents = ((max & JH7100_CLK_MUX_MASK) >> JH7100_CLK_MUX_SHIFT) + 1,
++			.num_parents = ((max & JH71X0_CLK_MUX_MASK) >> JH71X0_CLK_MUX_SHIFT) + 1,
+ 			.flags = jh7100_clk_data[idx].flags,
+ 		};
+-		struct jh7100_clk *clk = &priv->reg[idx];
++		struct jh71x0_clk *clk = &priv->reg[idx];
+ 		unsigned int i;
+ 
+ 		for (i = 0; i < init.num_parents; i++) {
+@@ -341,7 +344,7 @@ static int __init clk_starfive_jh7100_pr
+ 
+ 		clk->hw.init = &init;
+ 		clk->idx = idx;
+-		clk->max_div = max & JH7100_CLK_DIV_MASK;
++		clk->max_div = max & JH71X0_CLK_DIV_MASK;
+ 
+ 		ret = devm_clk_hw_register(priv->dev, &clk->hw);
+ 		if (ret)
+--- a/drivers/clk/starfive/clk-starfive-jh71x0.c
++++ b/drivers/clk/starfive/clk-starfive-jh71x0.c
+@@ -1,6 +1,6 @@
+ // SPDX-License-Identifier: GPL-2.0
+ /*
+- * StarFive JH7100 Clock Generator Driver
++ * StarFive JH71X0 Clock Generator Driver
+  *
+  * Copyright (C) 2021-2022 Emil Renner Berthing <[email protected]>
+  */
+@@ -12,27 +12,27 @@
+ 
+ #include "clk-starfive-jh71x0.h"
+ 
+-static struct jh7100_clk *jh7100_clk_from(struct clk_hw *hw)
++static struct jh71x0_clk *jh71x0_clk_from(struct clk_hw *hw)
+ {
+-	return container_of(hw, struct jh7100_clk, hw);
++	return container_of(hw, struct jh71x0_clk, hw);
+ }
+ 
+-static struct jh7100_clk_priv *jh7100_priv_from(struct jh7100_clk *clk)
++static struct jh71x0_clk_priv *jh71x0_priv_from(struct jh71x0_clk *clk)
+ {
+-	return container_of(clk, struct jh7100_clk_priv, reg[clk->idx]);
++	return container_of(clk, struct jh71x0_clk_priv, reg[clk->idx]);
+ }
+ 
+-static u32 jh7100_clk_reg_get(struct jh7100_clk *clk)
++static u32 jh71x0_clk_reg_get(struct jh71x0_clk *clk)
+ {
+-	struct jh7100_clk_priv *priv = jh7100_priv_from(clk);
++	struct jh71x0_clk_priv *priv = jh71x0_priv_from(clk);
+ 	void __iomem *reg = priv->base + 4 * clk->idx;
+ 
+ 	return readl_relaxed(reg);
+ }
+ 
+-static void jh7100_clk_reg_rmw(struct jh7100_clk *clk, u32 mask, u32 value)
++static void jh71x0_clk_reg_rmw(struct jh71x0_clk *clk, u32 mask, u32 value)
+ {
+-	struct jh7100_clk_priv *priv = jh7100_priv_from(clk);
++	struct jh71x0_clk_priv *priv = jh71x0_priv_from(clk);
+ 	void __iomem *reg = priv->base + 4 * clk->idx;
+ 	unsigned long flags;
+ 
+@@ -42,41 +42,41 @@ static void jh7100_clk_reg_rmw(struct jh
+ 	spin_unlock_irqrestore(&priv->rmw_lock, flags);
+ }
+ 
+-static int jh7100_clk_enable(struct clk_hw *hw)
++static int jh71x0_clk_enable(struct clk_hw *hw)
+ {
+-	struct jh7100_clk *clk = jh7100_clk_from(hw);
++	struct jh71x0_clk *clk = jh71x0_clk_from(hw);
+ 
+-	jh7100_clk_reg_rmw(clk, JH7100_CLK_ENABLE, JH7100_CLK_ENABLE);
++	jh71x0_clk_reg_rmw(clk, JH71X0_CLK_ENABLE, JH71X0_CLK_ENABLE);
+ 	return 0;
+ }
+ 
+-static void jh7100_clk_disable(struct clk_hw *hw)
++static void jh71x0_clk_disable(struct clk_hw *hw)
+ {
+-	struct jh7100_clk *clk = jh7100_clk_from(hw);
++	struct jh71x0_clk *clk = jh71x0_clk_from(hw);
+ 
+-	jh7100_clk_reg_rmw(clk, JH7100_CLK_ENABLE, 0);
++	jh71x0_clk_reg_rmw(clk, JH71X0_CLK_ENABLE, 0);
+ }
+ 
+-static int jh7100_clk_is_enabled(struct clk_hw *hw)
++static int jh71x0_clk_is_enabled(struct clk_hw *hw)
+ {
+-	struct jh7100_clk *clk = jh7100_clk_from(hw);
++	struct jh71x0_clk *clk = jh71x0_clk_from(hw);
+ 
+-	return !!(jh7100_clk_reg_get(clk) & JH7100_CLK_ENABLE);
++	return !!(jh71x0_clk_reg_get(clk) & JH71X0_CLK_ENABLE);
+ }
+ 
+-static unsigned long jh7100_clk_recalc_rate(struct clk_hw *hw,
++static unsigned long jh71x0_clk_recalc_rate(struct clk_hw *hw,
+ 					    unsigned long parent_rate)
+ {
+-	struct jh7100_clk *clk = jh7100_clk_from(hw);
+-	u32 div = jh7100_clk_reg_get(clk) & JH7100_CLK_DIV_MASK;
++	struct jh71x0_clk *clk = jh71x0_clk_from(hw);
++	u32 div = jh71x0_clk_reg_get(clk) & JH71X0_CLK_DIV_MASK;
+ 
+ 	return div ? parent_rate / div : 0;
+ }
+ 
+-static int jh7100_clk_determine_rate(struct clk_hw *hw,
++static int jh71x0_clk_determine_rate(struct clk_hw *hw,
+ 				     struct clk_rate_request *req)
+ {
+-	struct jh7100_clk *clk = jh7100_clk_from(hw);
++	struct jh71x0_clk *clk = jh71x0_clk_from(hw);
+ 	unsigned long parent = req->best_parent_rate;
+ 	unsigned long rate = clamp(req->rate, req->min_rate, req->max_rate);
+ 	unsigned long div = min_t(unsigned long, DIV_ROUND_UP(parent, rate), clk->max_div);
+@@ -102,232 +102,232 @@ static int jh7100_clk_determine_rate(str
+ 	return 0;
+ }
+ 
+-static int jh7100_clk_set_rate(struct clk_hw *hw,
++static int jh71x0_clk_set_rate(struct clk_hw *hw,
+ 			       unsigned long rate,
+ 			       unsigned long parent_rate)
+ {
+-	struct jh7100_clk *clk = jh7100_clk_from(hw);
++	struct jh71x0_clk *clk = jh71x0_clk_from(hw);
+ 	unsigned long div = clamp(DIV_ROUND_CLOSEST(parent_rate, rate),
+ 				  1UL, (unsigned long)clk->max_div);
+ 
+-	jh7100_clk_reg_rmw(clk, JH7100_CLK_DIV_MASK, div);
++	jh71x0_clk_reg_rmw(clk, JH71X0_CLK_DIV_MASK, div);
+ 	return 0;
+ }
+ 
+-static unsigned long jh7100_clk_frac_recalc_rate(struct clk_hw *hw,
++static unsigned long jh71x0_clk_frac_recalc_rate(struct clk_hw *hw,
+ 						 unsigned long parent_rate)
+ {
+-	struct jh7100_clk *clk = jh7100_clk_from(hw);
+-	u32 reg = jh7100_clk_reg_get(clk);
+-	unsigned long div100 = 100 * (reg & JH7100_CLK_INT_MASK) +
+-			       ((reg & JH7100_CLK_FRAC_MASK) >> JH7100_CLK_FRAC_SHIFT);
++	struct jh71x0_clk *clk = jh71x0_clk_from(hw);
++	u32 reg = jh71x0_clk_reg_get(clk);
++	unsigned long div100 = 100 * (reg & JH71X0_CLK_INT_MASK) +
++			       ((reg & JH71X0_CLK_FRAC_MASK) >> JH71X0_CLK_FRAC_SHIFT);
+ 
+-	return (div100 >= JH7100_CLK_FRAC_MIN) ? 100 * parent_rate / div100 : 0;
++	return (div100 >= JH71X0_CLK_FRAC_MIN) ? 100 * parent_rate / div100 : 0;
+ }
+ 
+-static int jh7100_clk_frac_determine_rate(struct clk_hw *hw,
++static int jh71x0_clk_frac_determine_rate(struct clk_hw *hw,
+ 					  struct clk_rate_request *req)
+ {
+ 	unsigned long parent100 = 100 * req->best_parent_rate;
+ 	unsigned long rate = clamp(req->rate, req->min_rate, req->max_rate);
+ 	unsigned long div100 = clamp(DIV_ROUND_CLOSEST(parent100, rate),
+-				     JH7100_CLK_FRAC_MIN, JH7100_CLK_FRAC_MAX);
++				     JH71X0_CLK_FRAC_MIN, JH71X0_CLK_FRAC_MAX);
+ 	unsigned long result = parent100 / div100;
+ 
+-	/* clamp the result as in jh7100_clk_determine_rate() above */
+-	if (result > req->max_rate && div100 < JH7100_CLK_FRAC_MAX)
++	/* clamp the result as in jh71x0_clk_determine_rate() above */
++	if (result > req->max_rate && div100 < JH71X0_CLK_FRAC_MAX)
+ 		result = parent100 / (div100 + 1);
+-	if (result < req->min_rate && div100 > JH7100_CLK_FRAC_MIN)
++	if (result < req->min_rate && div100 > JH71X0_CLK_FRAC_MIN)
+ 		result = parent100 / (div100 - 1);
+ 
+ 	req->rate = result;
+ 	return 0;
+ }
+ 
+-static int jh7100_clk_frac_set_rate(struct clk_hw *hw,
++static int jh71x0_clk_frac_set_rate(struct clk_hw *hw,
+ 				    unsigned long rate,
+ 				    unsigned long parent_rate)
+ {
+-	struct jh7100_clk *clk = jh7100_clk_from(hw);
++	struct jh71x0_clk *clk = jh71x0_clk_from(hw);
+ 	unsigned long div100 = clamp(DIV_ROUND_CLOSEST(100 * parent_rate, rate),
+-				     JH7100_CLK_FRAC_MIN, JH7100_CLK_FRAC_MAX);
+-	u32 value = ((div100 % 100) << JH7100_CLK_FRAC_SHIFT) | (div100 / 100);
++				     JH71X0_CLK_FRAC_MIN, JH71X0_CLK_FRAC_MAX);
++	u32 value = ((div100 % 100) << JH71X0_CLK_FRAC_SHIFT) | (div100 / 100);
+ 
+-	jh7100_clk_reg_rmw(clk, JH7100_CLK_DIV_MASK, value);
++	jh71x0_clk_reg_rmw(clk, JH71X0_CLK_DIV_MASK, value);
+ 	return 0;
+ }
+ 
+-static u8 jh7100_clk_get_parent(struct clk_hw *hw)
++static u8 jh71x0_clk_get_parent(struct clk_hw *hw)
+ {
+-	struct jh7100_clk *clk = jh7100_clk_from(hw);
+-	u32 value = jh7100_clk_reg_get(clk);
++	struct jh71x0_clk *clk = jh71x0_clk_from(hw);
++	u32 value = jh71x0_clk_reg_get(clk);
+ 
+-	return (value & JH7100_CLK_MUX_MASK) >> JH7100_CLK_MUX_SHIFT;
++	return (value & JH71X0_CLK_MUX_MASK) >> JH71X0_CLK_MUX_SHIFT;
+ }
+ 
+-static int jh7100_clk_set_parent(struct clk_hw *hw, u8 index)
++static int jh71x0_clk_set_parent(struct clk_hw *hw, u8 index)
+ {
+-	struct jh7100_clk *clk = jh7100_clk_from(hw);
+-	u32 value = (u32)index << JH7100_CLK_MUX_SHIFT;
++	struct jh71x0_clk *clk = jh71x0_clk_from(hw);
++	u32 value = (u32)index << JH71X0_CLK_MUX_SHIFT;
+ 
+-	jh7100_clk_reg_rmw(clk, JH7100_CLK_MUX_MASK, value);
++	jh71x0_clk_reg_rmw(clk, JH71X0_CLK_MUX_MASK, value);
+ 	return 0;
+ }
+ 
+-static int jh7100_clk_mux_determine_rate(struct clk_hw *hw,
++static int jh71x0_clk_mux_determine_rate(struct clk_hw *hw,
+ 					 struct clk_rate_request *req)
+ {
+ 	return clk_mux_determine_rate_flags(hw, req, 0);
+ }
+ 
+-static int jh7100_clk_get_phase(struct clk_hw *hw)
++static int jh71x0_clk_get_phase(struct clk_hw *hw)
+ {
+-	struct jh7100_clk *clk = jh7100_clk_from(hw);
+-	u32 value = jh7100_clk_reg_get(clk);
++	struct jh71x0_clk *clk = jh71x0_clk_from(hw);
++	u32 value = jh71x0_clk_reg_get(clk);
+ 
+-	return (value & JH7100_CLK_INVERT) ? 180 : 0;
++	return (value & JH71X0_CLK_INVERT) ? 180 : 0;
+ }
+ 
+-static int jh7100_clk_set_phase(struct clk_hw *hw, int degrees)
++static int jh71x0_clk_set_phase(struct clk_hw *hw, int degrees)
+ {
+-	struct jh7100_clk *clk = jh7100_clk_from(hw);
++	struct jh71x0_clk *clk = jh71x0_clk_from(hw);
+ 	u32 value;
+ 
+ 	if (degrees == 0)
+ 		value = 0;
+ 	else if (degrees == 180)
+-		value = JH7100_CLK_INVERT;
++		value = JH71X0_CLK_INVERT;
+ 	else
+ 		return -EINVAL;
+ 
+-	jh7100_clk_reg_rmw(clk, JH7100_CLK_INVERT, value);
++	jh71x0_clk_reg_rmw(clk, JH71X0_CLK_INVERT, value);
+ 	return 0;
+ }
+ 
+ #ifdef CONFIG_DEBUG_FS
+-static void jh7100_clk_debug_init(struct clk_hw *hw, struct dentry *dentry)
++static void jh71x0_clk_debug_init(struct clk_hw *hw, struct dentry *dentry)
+ {
+-	static const struct debugfs_reg32 jh7100_clk_reg = {
++	static const struct debugfs_reg32 jh71x0_clk_reg = {
+ 		.name = "CTRL",
+ 		.offset = 0,
+ 	};
+-	struct jh7100_clk *clk = jh7100_clk_from(hw);
+-	struct jh7100_clk_priv *priv = jh7100_priv_from(clk);
++	struct jh71x0_clk *clk = jh71x0_clk_from(hw);
++	struct jh71x0_clk_priv *priv = jh71x0_priv_from(clk);
+ 	struct debugfs_regset32 *regset;
+ 
+ 	regset = devm_kzalloc(priv->dev, sizeof(*regset), GFP_KERNEL);
+ 	if (!regset)
+ 		return;
+ 
+-	regset->regs = &jh7100_clk_reg;
++	regset->regs = &jh71x0_clk_reg;
+ 	regset->nregs = 1;
+ 	regset->base = priv->base + 4 * clk->idx;
+ 
+ 	debugfs_create_regset32("registers", 0400, dentry, regset);
+ }
+ #else
+-#define jh7100_clk_debug_init NULL
++#define jh71x0_clk_debug_init NULL
+ #endif
+ 
+-static const struct clk_ops jh7100_clk_gate_ops = {
+-	.enable = jh7100_clk_enable,
+-	.disable = jh7100_clk_disable,
+-	.is_enabled = jh7100_clk_is_enabled,
+-	.debug_init = jh7100_clk_debug_init,
++static const struct clk_ops jh71x0_clk_gate_ops = {
++	.enable = jh71x0_clk_enable,
++	.disable = jh71x0_clk_disable,
++	.is_enabled = jh71x0_clk_is_enabled,
++	.debug_init = jh71x0_clk_debug_init,
+ };
+ 
+-static const struct clk_ops jh7100_clk_div_ops = {
+-	.recalc_rate = jh7100_clk_recalc_rate,
+-	.determine_rate = jh7100_clk_determine_rate,
+-	.set_rate = jh7100_clk_set_rate,
+-	.debug_init = jh7100_clk_debug_init,
++static const struct clk_ops jh71x0_clk_div_ops = {
++	.recalc_rate = jh71x0_clk_recalc_rate,
++	.determine_rate = jh71x0_clk_determine_rate,
++	.set_rate = jh71x0_clk_set_rate,
++	.debug_init = jh71x0_clk_debug_init,
+ };
+ 
+-static const struct clk_ops jh7100_clk_fdiv_ops = {
+-	.recalc_rate = jh7100_clk_frac_recalc_rate,
+-	.determine_rate = jh7100_clk_frac_determine_rate,
+-	.set_rate = jh7100_clk_frac_set_rate,
+-	.debug_init = jh7100_clk_debug_init,
++static const struct clk_ops jh71x0_clk_fdiv_ops = {
++	.recalc_rate = jh71x0_clk_frac_recalc_rate,
++	.determine_rate = jh71x0_clk_frac_determine_rate,
++	.set_rate = jh71x0_clk_frac_set_rate,
++	.debug_init = jh71x0_clk_debug_init,
+ };
+ 
+-static const struct clk_ops jh7100_clk_gdiv_ops = {
+-	.enable = jh7100_clk_enable,
+-	.disable = jh7100_clk_disable,
+-	.is_enabled = jh7100_clk_is_enabled,
+-	.recalc_rate = jh7100_clk_recalc_rate,
+-	.determine_rate = jh7100_clk_determine_rate,
+-	.set_rate = jh7100_clk_set_rate,
+-	.debug_init = jh7100_clk_debug_init,
++static const struct clk_ops jh71x0_clk_gdiv_ops = {
++	.enable = jh71x0_clk_enable,
++	.disable = jh71x0_clk_disable,
++	.is_enabled = jh71x0_clk_is_enabled,
++	.recalc_rate = jh71x0_clk_recalc_rate,
++	.determine_rate = jh71x0_clk_determine_rate,
++	.set_rate = jh71x0_clk_set_rate,
++	.debug_init = jh71x0_clk_debug_init,
+ };
+ 
+-static const struct clk_ops jh7100_clk_mux_ops = {
+-	.determine_rate = jh7100_clk_mux_determine_rate,
+-	.set_parent = jh7100_clk_set_parent,
+-	.get_parent = jh7100_clk_get_parent,
+-	.debug_init = jh7100_clk_debug_init,
++static const struct clk_ops jh71x0_clk_mux_ops = {
++	.determine_rate = jh71x0_clk_mux_determine_rate,
++	.set_parent = jh71x0_clk_set_parent,
++	.get_parent = jh71x0_clk_get_parent,
++	.debug_init = jh71x0_clk_debug_init,
+ };
+ 
+-static const struct clk_ops jh7100_clk_gmux_ops = {
+-	.enable = jh7100_clk_enable,
+-	.disable = jh7100_clk_disable,
+-	.is_enabled = jh7100_clk_is_enabled,
+-	.determine_rate = jh7100_clk_mux_determine_rate,
+-	.set_parent = jh7100_clk_set_parent,
+-	.get_parent = jh7100_clk_get_parent,
+-	.debug_init = jh7100_clk_debug_init,
++static const struct clk_ops jh71x0_clk_gmux_ops = {
++	.enable = jh71x0_clk_enable,
++	.disable = jh71x0_clk_disable,
++	.is_enabled = jh71x0_clk_is_enabled,
++	.determine_rate = jh71x0_clk_mux_determine_rate,
++	.set_parent = jh71x0_clk_set_parent,
++	.get_parent = jh71x0_clk_get_parent,
++	.debug_init = jh71x0_clk_debug_init,
+ };
+ 
+-static const struct clk_ops jh7100_clk_mdiv_ops = {
+-	.recalc_rate = jh7100_clk_recalc_rate,
+-	.determine_rate = jh7100_clk_determine_rate,
+-	.get_parent = jh7100_clk_get_parent,
+-	.set_parent = jh7100_clk_set_parent,
+-	.set_rate = jh7100_clk_set_rate,
+-	.debug_init = jh7100_clk_debug_init,
++static const struct clk_ops jh71x0_clk_mdiv_ops = {
++	.recalc_rate = jh71x0_clk_recalc_rate,
++	.determine_rate = jh71x0_clk_determine_rate,
++	.get_parent = jh71x0_clk_get_parent,
++	.set_parent = jh71x0_clk_set_parent,
++	.set_rate = jh71x0_clk_set_rate,
++	.debug_init = jh71x0_clk_debug_init,
+ };
+ 
+-static const struct clk_ops jh7100_clk_gmd_ops = {
+-	.enable = jh7100_clk_enable,
+-	.disable = jh7100_clk_disable,
+-	.is_enabled = jh7100_clk_is_enabled,
+-	.recalc_rate = jh7100_clk_recalc_rate,
+-	.determine_rate = jh7100_clk_determine_rate,
+-	.get_parent = jh7100_clk_get_parent,
+-	.set_parent = jh7100_clk_set_parent,
+-	.set_rate = jh7100_clk_set_rate,
+-	.debug_init = jh7100_clk_debug_init,
++static const struct clk_ops jh71x0_clk_gmd_ops = {
++	.enable = jh71x0_clk_enable,
++	.disable = jh71x0_clk_disable,
++	.is_enabled = jh71x0_clk_is_enabled,
++	.recalc_rate = jh71x0_clk_recalc_rate,
++	.determine_rate = jh71x0_clk_determine_rate,
++	.get_parent = jh71x0_clk_get_parent,
++	.set_parent = jh71x0_clk_set_parent,
++	.set_rate = jh71x0_clk_set_rate,
++	.debug_init = jh71x0_clk_debug_init,
+ };
+ 
+-static const struct clk_ops jh7100_clk_inv_ops = {
+-	.get_phase = jh7100_clk_get_phase,
+-	.set_phase = jh7100_clk_set_phase,
+-	.debug_init = jh7100_clk_debug_init,
++static const struct clk_ops jh71x0_clk_inv_ops = {
++	.get_phase = jh71x0_clk_get_phase,
++	.set_phase = jh71x0_clk_set_phase,
++	.debug_init = jh71x0_clk_debug_init,
+ };
+ 
+-const struct clk_ops *starfive_jh7100_clk_ops(u32 max)
++const struct clk_ops *starfive_jh71x0_clk_ops(u32 max)
+ {
+-	if (max & JH7100_CLK_DIV_MASK) {
+-		if (max & JH7100_CLK_MUX_MASK) {
+-			if (max & JH7100_CLK_ENABLE)
+-				return &jh7100_clk_gmd_ops;
+-			return &jh7100_clk_mdiv_ops;
++	if (max & JH71X0_CLK_DIV_MASK) {
++		if (max & JH71X0_CLK_MUX_MASK) {
++			if (max & JH71X0_CLK_ENABLE)
++				return &jh71x0_clk_gmd_ops;
++			return &jh71x0_clk_mdiv_ops;
+ 		}
+-		if (max & JH7100_CLK_ENABLE)
+-			return &jh7100_clk_gdiv_ops;
+-		if (max == JH7100_CLK_FRAC_MAX)
+-			return &jh7100_clk_fdiv_ops;
+-		return &jh7100_clk_div_ops;
++		if (max & JH71X0_CLK_ENABLE)
++			return &jh71x0_clk_gdiv_ops;
++		if (max == JH71X0_CLK_FRAC_MAX)
++			return &jh71x0_clk_fdiv_ops;
++		return &jh71x0_clk_div_ops;
+ 	}
+ 
+-	if (max & JH7100_CLK_MUX_MASK) {
+-		if (max & JH7100_CLK_ENABLE)
+-			return &jh7100_clk_gmux_ops;
+-		return &jh7100_clk_mux_ops;
++	if (max & JH71X0_CLK_MUX_MASK) {
++		if (max & JH71X0_CLK_ENABLE)
++			return &jh71x0_clk_gmux_ops;
++		return &jh71x0_clk_mux_ops;
+ 	}
+ 
+-	if (max & JH7100_CLK_ENABLE)
+-		return &jh7100_clk_gate_ops;
++	if (max & JH71X0_CLK_ENABLE)
++		return &jh71x0_clk_gate_ops;
+ 
+-	return &jh7100_clk_inv_ops;
++	return &jh71x0_clk_inv_ops;
+ }
+-EXPORT_SYMBOL_GPL(starfive_jh7100_clk_ops);
++EXPORT_SYMBOL_GPL(starfive_jh71x0_clk_ops);
+--- a/drivers/clk/starfive/clk-starfive-jh71x0.h
++++ b/drivers/clk/starfive/clk-starfive-jh71x0.h
+@@ -1,6 +1,6 @@
+ /* SPDX-License-Identifier: GPL-2.0 */
+-#ifndef __CLK_STARFIVE_JH7100_H
+-#define __CLK_STARFIVE_JH7100_H
++#ifndef __CLK_STARFIVE_JH71X0_H
++#define __CLK_STARFIVE_JH71X0_H
+ 
+ #include <linux/bits.h>
+ #include <linux/clk-provider.h>
+@@ -8,107 +8,116 @@
+ #include <linux/spinlock.h>
+ 
+ /* register fields */
+-#define JH7100_CLK_ENABLE	BIT(31)
+-#define JH7100_CLK_INVERT	BIT(30)
+-#define JH7100_CLK_MUX_MASK	GENMASK(27, 24)
+-#define JH7100_CLK_MUX_SHIFT	24
+-#define JH7100_CLK_DIV_MASK	GENMASK(23, 0)
+-#define JH7100_CLK_FRAC_MASK	GENMASK(15, 8)
+-#define JH7100_CLK_FRAC_SHIFT	8
+-#define JH7100_CLK_INT_MASK	GENMASK(7, 0)
++#define JH71X0_CLK_ENABLE	BIT(31)
++#define JH71X0_CLK_INVERT	BIT(30)
++#define JH71X0_CLK_MUX_MASK	GENMASK(27, 24)
++#define JH71X0_CLK_MUX_SHIFT	24
++#define JH71X0_CLK_DIV_MASK	GENMASK(23, 0)
++#define JH71X0_CLK_FRAC_MASK	GENMASK(15, 8)
++#define JH71X0_CLK_FRAC_SHIFT	8
++#define JH71X0_CLK_INT_MASK	GENMASK(7, 0)
+ 
+ /* fractional divider min/max */
+-#define JH7100_CLK_FRAC_MIN	100UL
+-#define JH7100_CLK_FRAC_MAX	25599UL
++#define JH71X0_CLK_FRAC_MIN	100UL
++#define JH71X0_CLK_FRAC_MAX	25599UL
+ 
+ /* clock data */
+-struct jh7100_clk_data {
++struct jh71x0_clk_data {
+ 	const char *name;
+ 	unsigned long flags;
+ 	u32 max;
+ 	u8 parents[4];
+ };
+ 
+-#define JH7100_GATE(_idx, _name, _flags, _parent) [_idx] = {			\
++#define JH71X0_GATE(_idx, _name, _flags, _parent)				\
++[_idx] = {									\
+ 	.name = _name,								\
+ 	.flags = CLK_SET_RATE_PARENT | (_flags),				\
+-	.max = JH7100_CLK_ENABLE,						\
++	.max = JH71X0_CLK_ENABLE,						\
+ 	.parents = { [0] = _parent },						\
+ }
+ 
+-#define JH7100__DIV(_idx, _name, _max, _parent) [_idx] = {			\
++#define JH71X0__DIV(_idx, _name, _max, _parent)					\
++[_idx] = {									\
+ 	.name = _name,								\
+ 	.flags = 0,								\
+ 	.max = _max,								\
+ 	.parents = { [0] = _parent },						\
+ }
+ 
+-#define JH7100_GDIV(_idx, _name, _flags, _max, _parent) [_idx] = {		\
++#define JH71X0_GDIV(_idx, _name, _flags, _max, _parent)				\
++[_idx] = {									\
+ 	.name = _name,								\
+ 	.flags = _flags,							\
+-	.max = JH7100_CLK_ENABLE | (_max),					\
++	.max = JH71X0_CLK_ENABLE | (_max),					\
+ 	.parents = { [0] = _parent },						\
+ }
+ 
+-#define JH7100_FDIV(_idx, _name, _parent) [_idx] = {				\
++#define JH71X0_FDIV(_idx, _name, _parent)					\
++[_idx] = {									\
+ 	.name = _name,								\
+ 	.flags = 0,								\
+-	.max = JH7100_CLK_FRAC_MAX,						\
++	.max = JH71X0_CLK_FRAC_MAX,						\
+ 	.parents = { [0] = _parent },						\
+ }
+ 
+-#define JH7100__MUX(_idx, _name, _nparents, ...) [_idx] = {			\
++#define JH71X0__MUX(_idx, _name, _nparents, ...)				\
++[_idx] = {									\
+ 	.name = _name,								\
+ 	.flags = 0,								\
+-	.max = ((_nparents) - 1) << JH7100_CLK_MUX_SHIFT,			\
++	.max = ((_nparents) - 1) << JH71X0_CLK_MUX_SHIFT,			\
+ 	.parents = { __VA_ARGS__ },						\
+ }
+ 
+-#define JH7100_GMUX(_idx, _name, _flags, _nparents, ...) [_idx] = {		\
++#define JH71X0_GMUX(_idx, _name, _flags, _nparents, ...)			\
++[_idx] = {									\
+ 	.name = _name,								\
+ 	.flags = _flags,							\
+-	.max = JH7100_CLK_ENABLE |						\
+-		(((_nparents) - 1) << JH7100_CLK_MUX_SHIFT),			\
++	.max = JH71X0_CLK_ENABLE |						\
++		(((_nparents) - 1) << JH71X0_CLK_MUX_SHIFT),			\
+ 	.parents = { __VA_ARGS__ },						\
+ }
+ 
+-#define JH7100_MDIV(_idx, _name, _max, _nparents, ...) [_idx] = {		\
++#define JH71X0_MDIV(_idx, _name, _max, _nparents, ...)				\
++[_idx] = {									\
+ 	.name = _name,								\
+ 	.flags = 0,								\
+-	.max = (((_nparents) - 1) << JH7100_CLK_MUX_SHIFT) | (_max),		\
++	.max = (((_nparents) - 1) << JH71X0_CLK_MUX_SHIFT) | (_max),		\
+ 	.parents = { __VA_ARGS__ },						\
+ }
+ 
+-#define JH7100__GMD(_idx, _name, _flags, _max, _nparents, ...) [_idx] = {	\
++#define JH71X0__GMD(_idx, _name, _flags, _max, _nparents, ...)			\
++[_idx] = {									\
+ 	.name = _name,								\
+ 	.flags = _flags,							\
+-	.max = JH7100_CLK_ENABLE |						\
+-		(((_nparents) - 1) << JH7100_CLK_MUX_SHIFT) | (_max),		\
++	.max = JH71X0_CLK_ENABLE |						\
++		(((_nparents) - 1) << JH71X0_CLK_MUX_SHIFT) | (_max),		\
+ 	.parents = { __VA_ARGS__ },						\
+ }
+ 
+-#define JH7100__INV(_idx, _name, _parent) [_idx] = {				\
++#define JH71X0__INV(_idx, _name, _parent)					\
++[_idx] = {									\
+ 	.name = _name,								\
+ 	.flags = CLK_SET_RATE_PARENT,						\
+-	.max = JH7100_CLK_INVERT,						\
++	.max = JH71X0_CLK_INVERT,						\
+ 	.parents = { [0] = _parent },						\
+ }
+ 
+-struct jh7100_clk {
++struct jh71x0_clk {
+ 	struct clk_hw hw;
+ 	unsigned int idx;
+ 	unsigned int max_div;
+ };
+ 
+-struct jh7100_clk_priv {
++struct jh71x0_clk_priv {
+ 	/* protect clk enable and set rate/parent from happening at the same time */
+ 	spinlock_t rmw_lock;
+ 	struct device *dev;
+ 	void __iomem *base;
+ 	struct clk_hw *pll[3];
+-	struct jh7100_clk reg[];
++	struct jh71x0_clk reg[];
+ };
+ 
+-const struct clk_ops *starfive_jh7100_clk_ops(u32 max);
++const struct clk_ops *starfive_jh71x0_clk_ops(u32 max);
+ 
+ #endif

+ 30 - 0
target/linux/starfive/patches-6.1/0007-reset-starfive-Replace-SOC_STARFIVE-with-ARCH_STARFI.patch

@@ -0,0 +1,30 @@
+From 0ee5a7565601fa785d7e55c57f26ff5d79473eb2 Mon Sep 17 00:00:00 2001
+From: Hal Feng <[email protected]>
+Date: Sat, 1 Apr 2023 19:19:19 +0800
+Subject: [PATCH 007/122] reset: starfive: Replace SOC_STARFIVE with
+ ARCH_STARFIVE
+
+Using ARCH_FOO symbol is preferred than SOC_FOO.
+
+Reviewed-by: Philipp Zabel <[email protected]>
+Reviewed-by: Conor Dooley <[email protected]>
+Reviewed-by: Emil Renner Berthing <[email protected]>
+Signed-off-by: Hal Feng <[email protected]>
+Signed-off-by: Conor Dooley <[email protected]>
+---
+ drivers/reset/Kconfig | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+--- a/drivers/reset/Kconfig
++++ b/drivers/reset/Kconfig
+@@ -234,8 +234,8 @@ config RESET_SOCFPGA
+ 
+ config RESET_STARFIVE_JH7100
+ 	bool "StarFive JH7100 Reset Driver"
+-	depends on SOC_STARFIVE || COMPILE_TEST
+-	default SOC_STARFIVE
++	depends on ARCH_STARFIVE || COMPILE_TEST
++	default ARCH_STARFIVE
+ 	help
+ 	  This enables the reset controller driver for the StarFive JH7100 SoC.
+ 

+ 436 - 0
target/linux/starfive/patches-6.1/0008-reset-Create-subdirectory-for-StarFive-drivers.patch

@@ -0,0 +1,436 @@
+From ea9e5879793f9743fbfe613174900ab0c431ac0e Mon Sep 17 00:00:00 2001
+From: Emil Renner Berthing <[email protected]>
+Date: Sat, 1 Apr 2023 19:19:20 +0800
+Subject: [PATCH 008/122] reset: Create subdirectory for StarFive drivers
+
+This moves the StarFive JH7100 reset driver to a new subdirectory in
+preparation for adding more StarFive reset drivers.
+
+Reviewed-by: Philipp Zabel <[email protected]>
+Tested-by: Tommaso Merciai <[email protected]>
+Reviewed-by: Conor Dooley <[email protected]>
+Reviewed-by: Emil Renner Berthing <[email protected]>
+Signed-off-by: Emil Renner Berthing <[email protected]>
+Signed-off-by: Hal Feng <[email protected]>
+Signed-off-by: Conor Dooley <[email protected]>
+---
+ drivers/reset/Kconfig                                | 8 +-------
+ drivers/reset/Makefile                               | 2 +-
+ drivers/reset/starfive/Kconfig                       | 8 ++++++++
+ drivers/reset/starfive/Makefile                      | 2 ++
+ drivers/reset/{ => starfive}/reset-starfive-jh7100.c | 0
+ 5 files changed, 12 insertions(+), 8 deletions(-)
+ create mode 100644 drivers/reset/starfive/Kconfig
+ create mode 100644 drivers/reset/starfive/Makefile
+ rename drivers/reset/{ => starfive}/reset-starfive-jh7100.c (100%)
+
+--- a/drivers/reset/Kconfig
++++ b/drivers/reset/Kconfig
+@@ -232,13 +232,6 @@ config RESET_SOCFPGA
+ 	  This enables the reset driver for the SoCFPGA ARMv7 platforms. This
+ 	  driver gets initialized early during platform init calls.
+ 
+-config RESET_STARFIVE_JH7100
+-	bool "StarFive JH7100 Reset Driver"
+-	depends on ARCH_STARFIVE || COMPILE_TEST
+-	default ARCH_STARFIVE
+-	help
+-	  This enables the reset controller driver for the StarFive JH7100 SoC.
+-
+ config RESET_SUNPLUS
+ 	bool "Sunplus SoCs Reset Driver" if COMPILE_TEST
+ 	default ARCH_SUNPLUS
+@@ -320,6 +313,7 @@ config RESET_ZYNQ
+ 	help
+ 	  This enables the reset controller driver for Xilinx Zynq SoCs.
+ 
++source "drivers/reset/starfive/Kconfig"
+ source "drivers/reset/sti/Kconfig"
+ source "drivers/reset/hisilicon/Kconfig"
+ source "drivers/reset/tegra/Kconfig"
+--- a/drivers/reset/Makefile
++++ b/drivers/reset/Makefile
+@@ -1,6 +1,7 @@
+ # SPDX-License-Identifier: GPL-2.0
+ obj-y += core.o
+ obj-y += hisilicon/
++obj-y += starfive/
+ obj-$(CONFIG_ARCH_STI) += sti/
+ obj-$(CONFIG_ARCH_TEGRA) += tegra/
+ obj-$(CONFIG_RESET_A10SR) += reset-a10sr.o
+@@ -30,7 +31,6 @@ obj-$(CONFIG_RESET_RZG2L_USBPHY_CTRL) +=
+ obj-$(CONFIG_RESET_SCMI) += reset-scmi.o
+ obj-$(CONFIG_RESET_SIMPLE) += reset-simple.o
+ obj-$(CONFIG_RESET_SOCFPGA) += reset-socfpga.o
+-obj-$(CONFIG_RESET_STARFIVE_JH7100) += reset-starfive-jh7100.o
+ obj-$(CONFIG_RESET_SUNPLUS) += reset-sunplus.o
+ obj-$(CONFIG_RESET_SUNXI) += reset-sunxi.o
+ obj-$(CONFIG_RESET_TI_SCI) += reset-ti-sci.o
+--- /dev/null
++++ b/drivers/reset/starfive/Kconfig
+@@ -0,0 +1,8 @@
++# SPDX-License-Identifier: GPL-2.0-only
++
++config RESET_STARFIVE_JH7100
++	bool "StarFive JH7100 Reset Driver"
++	depends on ARCH_STARFIVE || COMPILE_TEST
++	default ARCH_STARFIVE
++	help
++	  This enables the reset controller driver for the StarFive JH7100 SoC.
+--- /dev/null
++++ b/drivers/reset/starfive/Makefile
+@@ -0,0 +1,2 @@
++# SPDX-License-Identifier: GPL-2.0
++obj-$(CONFIG_RESET_STARFIVE_JH7100)		+= reset-starfive-jh7100.o
+--- a/drivers/reset/reset-starfive-jh7100.c
++++ /dev/null
+@@ -1,173 +0,0 @@
+-// SPDX-License-Identifier: GPL-2.0-or-later
+-/*
+- * Reset driver for the StarFive JH7100 SoC
+- *
+- * Copyright (C) 2021 Emil Renner Berthing <[email protected]>
+- */
+-
+-#include <linux/bitmap.h>
+-#include <linux/io.h>
+-#include <linux/io-64-nonatomic-lo-hi.h>
+-#include <linux/iopoll.h>
+-#include <linux/mod_devicetable.h>
+-#include <linux/platform_device.h>
+-#include <linux/reset-controller.h>
+-#include <linux/spinlock.h>
+-
+-#include <dt-bindings/reset/starfive-jh7100.h>
+-
+-/* register offsets */
+-#define JH7100_RESET_ASSERT0	0x00
+-#define JH7100_RESET_ASSERT1	0x04
+-#define JH7100_RESET_ASSERT2	0x08
+-#define JH7100_RESET_ASSERT3	0x0c
+-#define JH7100_RESET_STATUS0	0x10
+-#define JH7100_RESET_STATUS1	0x14
+-#define JH7100_RESET_STATUS2	0x18
+-#define JH7100_RESET_STATUS3	0x1c
+-
+-/*
+- * Writing a 1 to the n'th bit of the m'th ASSERT register asserts
+- * line 32m + n, and writing a 0 deasserts the same line.
+- * Most reset lines have their status inverted so a 0 bit in the STATUS
+- * register means the line is asserted and a 1 means it's deasserted. A few
+- * lines don't though, so store the expected value of the status registers when
+- * all lines are asserted.
+- */
+-static const u64 jh7100_reset_asserted[2] = {
+-	/* STATUS0 */
+-	BIT_ULL_MASK(JH7100_RST_U74) |
+-	BIT_ULL_MASK(JH7100_RST_VP6_DRESET) |
+-	BIT_ULL_MASK(JH7100_RST_VP6_BRESET) |
+-	/* STATUS1 */
+-	BIT_ULL_MASK(JH7100_RST_HIFI4_DRESET) |
+-	BIT_ULL_MASK(JH7100_RST_HIFI4_BRESET),
+-	/* STATUS2 */
+-	BIT_ULL_MASK(JH7100_RST_E24) |
+-	/* STATUS3 */
+-	0,
+-};
+-
+-struct jh7100_reset {
+-	struct reset_controller_dev rcdev;
+-	/* protect registers against concurrent read-modify-write */
+-	spinlock_t lock;
+-	void __iomem *base;
+-};
+-
+-static inline struct jh7100_reset *
+-jh7100_reset_from(struct reset_controller_dev *rcdev)
+-{
+-	return container_of(rcdev, struct jh7100_reset, rcdev);
+-}
+-
+-static int jh7100_reset_update(struct reset_controller_dev *rcdev,
+-			       unsigned long id, bool assert)
+-{
+-	struct jh7100_reset *data = jh7100_reset_from(rcdev);
+-	unsigned long offset = BIT_ULL_WORD(id);
+-	u64 mask = BIT_ULL_MASK(id);
+-	void __iomem *reg_assert = data->base + JH7100_RESET_ASSERT0 + offset * sizeof(u64);
+-	void __iomem *reg_status = data->base + JH7100_RESET_STATUS0 + offset * sizeof(u64);
+-	u64 done = jh7100_reset_asserted[offset] & mask;
+-	u64 value;
+-	unsigned long flags;
+-	int ret;
+-
+-	if (!assert)
+-		done ^= mask;
+-
+-	spin_lock_irqsave(&data->lock, flags);
+-
+-	value = readq(reg_assert);
+-	if (assert)
+-		value |= mask;
+-	else
+-		value &= ~mask;
+-	writeq(value, reg_assert);
+-
+-	/* if the associated clock is gated, deasserting might otherwise hang forever */
+-	ret = readq_poll_timeout_atomic(reg_status, value, (value & mask) == done, 0, 1000);
+-
+-	spin_unlock_irqrestore(&data->lock, flags);
+-	return ret;
+-}
+-
+-static int jh7100_reset_assert(struct reset_controller_dev *rcdev,
+-			       unsigned long id)
+-{
+-	return jh7100_reset_update(rcdev, id, true);
+-}
+-
+-static int jh7100_reset_deassert(struct reset_controller_dev *rcdev,
+-				 unsigned long id)
+-{
+-	return jh7100_reset_update(rcdev, id, false);
+-}
+-
+-static int jh7100_reset_reset(struct reset_controller_dev *rcdev,
+-			      unsigned long id)
+-{
+-	int ret;
+-
+-	ret = jh7100_reset_assert(rcdev, id);
+-	if (ret)
+-		return ret;
+-
+-	return jh7100_reset_deassert(rcdev, id);
+-}
+-
+-static int jh7100_reset_status(struct reset_controller_dev *rcdev,
+-			       unsigned long id)
+-{
+-	struct jh7100_reset *data = jh7100_reset_from(rcdev);
+-	unsigned long offset = BIT_ULL_WORD(id);
+-	u64 mask = BIT_ULL_MASK(id);
+-	void __iomem *reg_status = data->base + JH7100_RESET_STATUS0 + offset * sizeof(u64);
+-	u64 value = readq(reg_status);
+-
+-	return !((value ^ jh7100_reset_asserted[offset]) & mask);
+-}
+-
+-static const struct reset_control_ops jh7100_reset_ops = {
+-	.assert		= jh7100_reset_assert,
+-	.deassert	= jh7100_reset_deassert,
+-	.reset		= jh7100_reset_reset,
+-	.status		= jh7100_reset_status,
+-};
+-
+-static int __init jh7100_reset_probe(struct platform_device *pdev)
+-{
+-	struct jh7100_reset *data;
+-
+-	data = devm_kzalloc(&pdev->dev, sizeof(*data), GFP_KERNEL);
+-	if (!data)
+-		return -ENOMEM;
+-
+-	data->base = devm_platform_ioremap_resource(pdev, 0);
+-	if (IS_ERR(data->base))
+-		return PTR_ERR(data->base);
+-
+-	data->rcdev.ops = &jh7100_reset_ops;
+-	data->rcdev.owner = THIS_MODULE;
+-	data->rcdev.nr_resets = JH7100_RSTN_END;
+-	data->rcdev.dev = &pdev->dev;
+-	data->rcdev.of_node = pdev->dev.of_node;
+-	spin_lock_init(&data->lock);
+-
+-	return devm_reset_controller_register(&pdev->dev, &data->rcdev);
+-}
+-
+-static const struct of_device_id jh7100_reset_dt_ids[] = {
+-	{ .compatible = "starfive,jh7100-reset" },
+-	{ /* sentinel */ }
+-};
+-
+-static struct platform_driver jh7100_reset_driver = {
+-	.driver = {
+-		.name = "jh7100-reset",
+-		.of_match_table = jh7100_reset_dt_ids,
+-		.suppress_bind_attrs = true,
+-	},
+-};
+-builtin_platform_driver_probe(jh7100_reset_driver, jh7100_reset_probe);
+--- /dev/null
++++ b/drivers/reset/starfive/reset-starfive-jh7100.c
+@@ -0,0 +1,173 @@
++// SPDX-License-Identifier: GPL-2.0-or-later
++/*
++ * Reset driver for the StarFive JH7100 SoC
++ *
++ * Copyright (C) 2021 Emil Renner Berthing <[email protected]>
++ */
++
++#include <linux/bitmap.h>
++#include <linux/io.h>
++#include <linux/io-64-nonatomic-lo-hi.h>
++#include <linux/iopoll.h>
++#include <linux/mod_devicetable.h>
++#include <linux/platform_device.h>
++#include <linux/reset-controller.h>
++#include <linux/spinlock.h>
++
++#include <dt-bindings/reset/starfive-jh7100.h>
++
++/* register offsets */
++#define JH7100_RESET_ASSERT0	0x00
++#define JH7100_RESET_ASSERT1	0x04
++#define JH7100_RESET_ASSERT2	0x08
++#define JH7100_RESET_ASSERT3	0x0c
++#define JH7100_RESET_STATUS0	0x10
++#define JH7100_RESET_STATUS1	0x14
++#define JH7100_RESET_STATUS2	0x18
++#define JH7100_RESET_STATUS3	0x1c
++
++/*
++ * Writing a 1 to the n'th bit of the m'th ASSERT register asserts
++ * line 32m + n, and writing a 0 deasserts the same line.
++ * Most reset lines have their status inverted so a 0 bit in the STATUS
++ * register means the line is asserted and a 1 means it's deasserted. A few
++ * lines don't though, so store the expected value of the status registers when
++ * all lines are asserted.
++ */
++static const u64 jh7100_reset_asserted[2] = {
++	/* STATUS0 */
++	BIT_ULL_MASK(JH7100_RST_U74) |
++	BIT_ULL_MASK(JH7100_RST_VP6_DRESET) |
++	BIT_ULL_MASK(JH7100_RST_VP6_BRESET) |
++	/* STATUS1 */
++	BIT_ULL_MASK(JH7100_RST_HIFI4_DRESET) |
++	BIT_ULL_MASK(JH7100_RST_HIFI4_BRESET),
++	/* STATUS2 */
++	BIT_ULL_MASK(JH7100_RST_E24) |
++	/* STATUS3 */
++	0,
++};
++
++struct jh7100_reset {
++	struct reset_controller_dev rcdev;
++	/* protect registers against concurrent read-modify-write */
++	spinlock_t lock;
++	void __iomem *base;
++};
++
++static inline struct jh7100_reset *
++jh7100_reset_from(struct reset_controller_dev *rcdev)
++{
++	return container_of(rcdev, struct jh7100_reset, rcdev);
++}
++
++static int jh7100_reset_update(struct reset_controller_dev *rcdev,
++			       unsigned long id, bool assert)
++{
++	struct jh7100_reset *data = jh7100_reset_from(rcdev);
++	unsigned long offset = BIT_ULL_WORD(id);
++	u64 mask = BIT_ULL_MASK(id);
++	void __iomem *reg_assert = data->base + JH7100_RESET_ASSERT0 + offset * sizeof(u64);
++	void __iomem *reg_status = data->base + JH7100_RESET_STATUS0 + offset * sizeof(u64);
++	u64 done = jh7100_reset_asserted[offset] & mask;
++	u64 value;
++	unsigned long flags;
++	int ret;
++
++	if (!assert)
++		done ^= mask;
++
++	spin_lock_irqsave(&data->lock, flags);
++
++	value = readq(reg_assert);
++	if (assert)
++		value |= mask;
++	else
++		value &= ~mask;
++	writeq(value, reg_assert);
++
++	/* if the associated clock is gated, deasserting might otherwise hang forever */
++	ret = readq_poll_timeout_atomic(reg_status, value, (value & mask) == done, 0, 1000);
++
++	spin_unlock_irqrestore(&data->lock, flags);
++	return ret;
++}
++
++static int jh7100_reset_assert(struct reset_controller_dev *rcdev,
++			       unsigned long id)
++{
++	return jh7100_reset_update(rcdev, id, true);
++}
++
++static int jh7100_reset_deassert(struct reset_controller_dev *rcdev,
++				 unsigned long id)
++{
++	return jh7100_reset_update(rcdev, id, false);
++}
++
++static int jh7100_reset_reset(struct reset_controller_dev *rcdev,
++			      unsigned long id)
++{
++	int ret;
++
++	ret = jh7100_reset_assert(rcdev, id);
++	if (ret)
++		return ret;
++
++	return jh7100_reset_deassert(rcdev, id);
++}
++
++static int jh7100_reset_status(struct reset_controller_dev *rcdev,
++			       unsigned long id)
++{
++	struct jh7100_reset *data = jh7100_reset_from(rcdev);
++	unsigned long offset = BIT_ULL_WORD(id);
++	u64 mask = BIT_ULL_MASK(id);
++	void __iomem *reg_status = data->base + JH7100_RESET_STATUS0 + offset * sizeof(u64);
++	u64 value = readq(reg_status);
++
++	return !((value ^ jh7100_reset_asserted[offset]) & mask);
++}
++
++static const struct reset_control_ops jh7100_reset_ops = {
++	.assert		= jh7100_reset_assert,
++	.deassert	= jh7100_reset_deassert,
++	.reset		= jh7100_reset_reset,
++	.status		= jh7100_reset_status,
++};
++
++static int __init jh7100_reset_probe(struct platform_device *pdev)
++{
++	struct jh7100_reset *data;
++
++	data = devm_kzalloc(&pdev->dev, sizeof(*data), GFP_KERNEL);
++	if (!data)
++		return -ENOMEM;
++
++	data->base = devm_platform_ioremap_resource(pdev, 0);
++	if (IS_ERR(data->base))
++		return PTR_ERR(data->base);
++
++	data->rcdev.ops = &jh7100_reset_ops;
++	data->rcdev.owner = THIS_MODULE;
++	data->rcdev.nr_resets = JH7100_RSTN_END;
++	data->rcdev.dev = &pdev->dev;
++	data->rcdev.of_node = pdev->dev.of_node;
++	spin_lock_init(&data->lock);
++
++	return devm_reset_controller_register(&pdev->dev, &data->rcdev);
++}
++
++static const struct of_device_id jh7100_reset_dt_ids[] = {
++	{ .compatible = "starfive,jh7100-reset" },
++	{ /* sentinel */ }
++};
++
++static struct platform_driver jh7100_reset_driver = {
++	.driver = {
++		.name = "jh7100-reset",
++		.of_match_table = jh7100_reset_dt_ids,
++		.suppress_bind_attrs = true,
++	},
++};
++builtin_platform_driver_probe(jh7100_reset_driver, jh7100_reset_probe);

+ 390 - 0
target/linux/starfive/patches-6.1/0009-reset-starfive-Factor-out-common-JH71X0-reset-code.patch

@@ -0,0 +1,390 @@
+From a8051a7daa45056f469686286886968bc62b94df Mon Sep 17 00:00:00 2001
+From: Emil Renner Berthing <[email protected]>
+Date: Sat, 1 Apr 2023 19:19:21 +0800
+Subject: [PATCH 009/122] reset: starfive: Factor out common JH71X0 reset code
+
+The StarFive JH7100 SoC has additional reset controllers for audio and
+video, but the registers follow the same structure. On the JH7110 the
+reset registers don't get their own memory range, but instead follow the
+clock control registers. The registers still follow the same structure
+though, so let's factor out the common code to handle all these cases.
+
+Tested-by: Tommaso Merciai <[email protected]>
+Reviewed-by: Conor Dooley <[email protected]>
+Reviewed-by: Emil Renner Berthing <[email protected]>
+Signed-off-by: Emil Renner Berthing <[email protected]>
+Signed-off-by: Hal Feng <[email protected]>
+Signed-off-by: Conor Dooley <[email protected]>
+---
+ drivers/reset/starfive/Kconfig                |   4 +
+ drivers/reset/starfive/Makefile               |   2 +
+ .../reset/starfive/reset-starfive-jh7100.c    | 150 +---------------
+ .../reset/starfive/reset-starfive-jh71x0.c    | 162 ++++++++++++++++++
+ .../reset/starfive/reset-starfive-jh71x0.h    |  11 ++
+ 5 files changed, 180 insertions(+), 149 deletions(-)
+ create mode 100644 drivers/reset/starfive/reset-starfive-jh71x0.c
+ create mode 100644 drivers/reset/starfive/reset-starfive-jh71x0.h
+
+--- a/drivers/reset/starfive/Kconfig
++++ b/drivers/reset/starfive/Kconfig
+@@ -1,8 +1,12 @@
+ # SPDX-License-Identifier: GPL-2.0-only
+ 
++config RESET_STARFIVE_JH71X0
++	bool
++
+ config RESET_STARFIVE_JH7100
+ 	bool "StarFive JH7100 Reset Driver"
+ 	depends on ARCH_STARFIVE || COMPILE_TEST
++	select RESET_STARFIVE_JH71X0
+ 	default ARCH_STARFIVE
+ 	help
+ 	  This enables the reset controller driver for the StarFive JH7100 SoC.
+--- a/drivers/reset/starfive/Makefile
++++ b/drivers/reset/starfive/Makefile
+@@ -1,2 +1,4 @@
+ # SPDX-License-Identifier: GPL-2.0
++obj-$(CONFIG_RESET_STARFIVE_JH71X0)		+= reset-starfive-jh71x0.o
++
+ obj-$(CONFIG_RESET_STARFIVE_JH7100)		+= reset-starfive-jh7100.o
+--- a/drivers/reset/starfive/reset-starfive-jh7100.c
++++ b/drivers/reset/starfive/reset-starfive-jh7100.c
+@@ -5,158 +5,10 @@
+  * Copyright (C) 2021 Emil Renner Berthing <[email protected]>
+  */
+ 
+-#include <linux/bitmap.h>
+-#include <linux/io.h>
+-#include <linux/io-64-nonatomic-lo-hi.h>
+-#include <linux/iopoll.h>
+ #include <linux/mod_devicetable.h>
+ #include <linux/platform_device.h>
+-#include <linux/reset-controller.h>
+-#include <linux/spinlock.h>
+ 
+-#include <dt-bindings/reset/starfive-jh7100.h>
+-
+-/* register offsets */
+-#define JH7100_RESET_ASSERT0	0x00
+-#define JH7100_RESET_ASSERT1	0x04
+-#define JH7100_RESET_ASSERT2	0x08
+-#define JH7100_RESET_ASSERT3	0x0c
+-#define JH7100_RESET_STATUS0	0x10
+-#define JH7100_RESET_STATUS1	0x14
+-#define JH7100_RESET_STATUS2	0x18
+-#define JH7100_RESET_STATUS3	0x1c
+-
+-/*
+- * Writing a 1 to the n'th bit of the m'th ASSERT register asserts
+- * line 32m + n, and writing a 0 deasserts the same line.
+- * Most reset lines have their status inverted so a 0 bit in the STATUS
+- * register means the line is asserted and a 1 means it's deasserted. A few
+- * lines don't though, so store the expected value of the status registers when
+- * all lines are asserted.
+- */
+-static const u64 jh7100_reset_asserted[2] = {
+-	/* STATUS0 */
+-	BIT_ULL_MASK(JH7100_RST_U74) |
+-	BIT_ULL_MASK(JH7100_RST_VP6_DRESET) |
+-	BIT_ULL_MASK(JH7100_RST_VP6_BRESET) |
+-	/* STATUS1 */
+-	BIT_ULL_MASK(JH7100_RST_HIFI4_DRESET) |
+-	BIT_ULL_MASK(JH7100_RST_HIFI4_BRESET),
+-	/* STATUS2 */
+-	BIT_ULL_MASK(JH7100_RST_E24) |
+-	/* STATUS3 */
+-	0,
+-};
+-
+-struct jh7100_reset {
+-	struct reset_controller_dev rcdev;
+-	/* protect registers against concurrent read-modify-write */
+-	spinlock_t lock;
+-	void __iomem *base;
+-};
+-
+-static inline struct jh7100_reset *
+-jh7100_reset_from(struct reset_controller_dev *rcdev)
+-{
+-	return container_of(rcdev, struct jh7100_reset, rcdev);
+-}
+-
+-static int jh7100_reset_update(struct reset_controller_dev *rcdev,
+-			       unsigned long id, bool assert)
+-{
+-	struct jh7100_reset *data = jh7100_reset_from(rcdev);
+-	unsigned long offset = BIT_ULL_WORD(id);
+-	u64 mask = BIT_ULL_MASK(id);
+-	void __iomem *reg_assert = data->base + JH7100_RESET_ASSERT0 + offset * sizeof(u64);
+-	void __iomem *reg_status = data->base + JH7100_RESET_STATUS0 + offset * sizeof(u64);
+-	u64 done = jh7100_reset_asserted[offset] & mask;
+-	u64 value;
+-	unsigned long flags;
+-	int ret;
+-
+-	if (!assert)
+-		done ^= mask;
+-
+-	spin_lock_irqsave(&data->lock, flags);
+-
+-	value = readq(reg_assert);
+-	if (assert)
+-		value |= mask;
+-	else
+-		value &= ~mask;
+-	writeq(value, reg_assert);
+-
+-	/* if the associated clock is gated, deasserting might otherwise hang forever */
+-	ret = readq_poll_timeout_atomic(reg_status, value, (value & mask) == done, 0, 1000);
+-
+-	spin_unlock_irqrestore(&data->lock, flags);
+-	return ret;
+-}
+-
+-static int jh7100_reset_assert(struct reset_controller_dev *rcdev,
+-			       unsigned long id)
+-{
+-	return jh7100_reset_update(rcdev, id, true);
+-}
+-
+-static int jh7100_reset_deassert(struct reset_controller_dev *rcdev,
+-				 unsigned long id)
+-{
+-	return jh7100_reset_update(rcdev, id, false);
+-}
+-
+-static int jh7100_reset_reset(struct reset_controller_dev *rcdev,
+-			      unsigned long id)
+-{
+-	int ret;
+-
+-	ret = jh7100_reset_assert(rcdev, id);
+-	if (ret)
+-		return ret;
+-
+-	return jh7100_reset_deassert(rcdev, id);
+-}
+-
+-static int jh7100_reset_status(struct reset_controller_dev *rcdev,
+-			       unsigned long id)
+-{
+-	struct jh7100_reset *data = jh7100_reset_from(rcdev);
+-	unsigned long offset = BIT_ULL_WORD(id);
+-	u64 mask = BIT_ULL_MASK(id);
+-	void __iomem *reg_status = data->base + JH7100_RESET_STATUS0 + offset * sizeof(u64);
+-	u64 value = readq(reg_status);
+-
+-	return !((value ^ jh7100_reset_asserted[offset]) & mask);
+-}
+-
+-static const struct reset_control_ops jh7100_reset_ops = {
+-	.assert		= jh7100_reset_assert,
+-	.deassert	= jh7100_reset_deassert,
+-	.reset		= jh7100_reset_reset,
+-	.status		= jh7100_reset_status,
+-};
+-
+-static int __init jh7100_reset_probe(struct platform_device *pdev)
+-{
+-	struct jh7100_reset *data;
+-
+-	data = devm_kzalloc(&pdev->dev, sizeof(*data), GFP_KERNEL);
+-	if (!data)
+-		return -ENOMEM;
+-
+-	data->base = devm_platform_ioremap_resource(pdev, 0);
+-	if (IS_ERR(data->base))
+-		return PTR_ERR(data->base);
+-
+-	data->rcdev.ops = &jh7100_reset_ops;
+-	data->rcdev.owner = THIS_MODULE;
+-	data->rcdev.nr_resets = JH7100_RSTN_END;
+-	data->rcdev.dev = &pdev->dev;
+-	data->rcdev.of_node = pdev->dev.of_node;
+-	spin_lock_init(&data->lock);
+-
+-	return devm_reset_controller_register(&pdev->dev, &data->rcdev);
+-}
++#include "reset-starfive-jh71x0.h"
+ 
+ static const struct of_device_id jh7100_reset_dt_ids[] = {
+ 	{ .compatible = "starfive,jh7100-reset" },
+--- /dev/null
++++ b/drivers/reset/starfive/reset-starfive-jh71x0.c
+@@ -0,0 +1,162 @@
++// SPDX-License-Identifier: GPL-2.0-or-later
++/*
++ * Reset driver for the StarFive JH7100 SoC
++ *
++ * Copyright (C) 2021 Emil Renner Berthing <[email protected]>
++ */
++
++#include <linux/bitmap.h>
++#include <linux/device.h>
++#include <linux/io.h>
++#include <linux/io-64-nonatomic-lo-hi.h>
++#include <linux/iopoll.h>
++#include <linux/platform_device.h>
++#include <linux/reset-controller.h>
++#include <linux/spinlock.h>
++
++#include "reset-starfive-jh71x0.h"
++
++#include <dt-bindings/reset/starfive-jh7100.h>
++
++/* register offsets */
++#define JH7100_RESET_ASSERT0	0x00
++#define JH7100_RESET_ASSERT1	0x04
++#define JH7100_RESET_ASSERT2	0x08
++#define JH7100_RESET_ASSERT3	0x0c
++#define JH7100_RESET_STATUS0	0x10
++#define JH7100_RESET_STATUS1	0x14
++#define JH7100_RESET_STATUS2	0x18
++#define JH7100_RESET_STATUS3	0x1c
++
++/*
++ * Writing a 1 to the n'th bit of the m'th ASSERT register asserts
++ * line 32m + n, and writing a 0 deasserts the same line.
++ * Most reset lines have their status inverted so a 0 bit in the STATUS
++ * register means the line is asserted and a 1 means it's deasserted. A few
++ * lines don't though, so store the expected value of the status registers when
++ * all lines are asserted.
++ */
++static const u64 jh7100_reset_asserted[2] = {
++	/* STATUS0 */
++	BIT_ULL_MASK(JH7100_RST_U74) |
++	BIT_ULL_MASK(JH7100_RST_VP6_DRESET) |
++	BIT_ULL_MASK(JH7100_RST_VP6_BRESET) |
++	/* STATUS1 */
++	BIT_ULL_MASK(JH7100_RST_HIFI4_DRESET) |
++	BIT_ULL_MASK(JH7100_RST_HIFI4_BRESET),
++	/* STATUS2 */
++	BIT_ULL_MASK(JH7100_RST_E24) |
++	/* STATUS3 */
++	0,
++};
++
++struct jh7100_reset {
++	struct reset_controller_dev rcdev;
++	/* protect registers against concurrent read-modify-write */
++	spinlock_t lock;
++	void __iomem *base;
++};
++
++static inline struct jh7100_reset *
++jh7100_reset_from(struct reset_controller_dev *rcdev)
++{
++	return container_of(rcdev, struct jh7100_reset, rcdev);
++}
++
++static int jh7100_reset_update(struct reset_controller_dev *rcdev,
++			       unsigned long id, bool assert)
++{
++	struct jh7100_reset *data = jh7100_reset_from(rcdev);
++	unsigned long offset = BIT_ULL_WORD(id);
++	u64 mask = BIT_ULL_MASK(id);
++	void __iomem *reg_assert = data->base + JH7100_RESET_ASSERT0 + offset * sizeof(u64);
++	void __iomem *reg_status = data->base + JH7100_RESET_STATUS0 + offset * sizeof(u64);
++	u64 done = jh7100_reset_asserted[offset] & mask;
++	u64 value;
++	unsigned long flags;
++	int ret;
++
++	if (!assert)
++		done ^= mask;
++
++	spin_lock_irqsave(&data->lock, flags);
++
++	value = readq(reg_assert);
++	if (assert)
++		value |= mask;
++	else
++		value &= ~mask;
++	writeq(value, reg_assert);
++
++	/* if the associated clock is gated, deasserting might otherwise hang forever */
++	ret = readq_poll_timeout_atomic(reg_status, value, (value & mask) == done, 0, 1000);
++
++	spin_unlock_irqrestore(&data->lock, flags);
++	return ret;
++}
++
++static int jh7100_reset_assert(struct reset_controller_dev *rcdev,
++			       unsigned long id)
++{
++	return jh7100_reset_update(rcdev, id, true);
++}
++
++static int jh7100_reset_deassert(struct reset_controller_dev *rcdev,
++				 unsigned long id)
++{
++	return jh7100_reset_update(rcdev, id, false);
++}
++
++static int jh7100_reset_reset(struct reset_controller_dev *rcdev,
++			      unsigned long id)
++{
++	int ret;
++
++	ret = jh7100_reset_assert(rcdev, id);
++	if (ret)
++		return ret;
++
++	return jh7100_reset_deassert(rcdev, id);
++}
++
++static int jh7100_reset_status(struct reset_controller_dev *rcdev,
++			       unsigned long id)
++{
++	struct jh7100_reset *data = jh7100_reset_from(rcdev);
++	unsigned long offset = BIT_ULL_WORD(id);
++	u64 mask = BIT_ULL_MASK(id);
++	void __iomem *reg_status = data->base + JH7100_RESET_STATUS0 + offset * sizeof(u64);
++	u64 value = readq(reg_status);
++
++	return !((value ^ jh7100_reset_asserted[offset]) & mask);
++}
++
++static const struct reset_control_ops jh7100_reset_ops = {
++	.assert		= jh7100_reset_assert,
++	.deassert	= jh7100_reset_deassert,
++	.reset		= jh7100_reset_reset,
++	.status		= jh7100_reset_status,
++};
++
++int jh7100_reset_probe(struct platform_device *pdev)
++{
++	struct jh7100_reset *data;
++
++	data = devm_kzalloc(&pdev->dev, sizeof(*data), GFP_KERNEL);
++	if (!data)
++		return -ENOMEM;
++
++	data->base = devm_platform_ioremap_resource(pdev, 0);
++	if (IS_ERR(data->base))
++		return PTR_ERR(data->base);
++
++	data->rcdev.ops = &jh7100_reset_ops;
++	data->rcdev.owner = THIS_MODULE;
++	data->rcdev.nr_resets = JH7100_RSTN_END;
++	data->rcdev.dev = &pdev->dev;
++	data->rcdev.of_node = pdev->dev.of_node;
++	spin_lock_init(&data->lock);
++
++	return devm_reset_controller_register(&pdev->dev, &data->rcdev);
++}
++EXPORT_SYMBOL_GPL(jh7100_reset_probe);
+--- /dev/null
++++ b/drivers/reset/starfive/reset-starfive-jh71x0.h
+@@ -0,0 +1,11 @@
++/* SPDX-License-Identifier: GPL-2.0-or-later */
++/*
++ * Copyright (C) 2021 Emil Renner Berthing <[email protected]>
++ */
++
++#ifndef __RESET_STARFIVE_JH71X0_H
++#define __RESET_STARFIVE_JH71X0_H
++
++int jh7100_reset_probe(struct platform_device *pdev);
++
++#endif /* __RESET_STARFIVE_JH71X0_H */

+ 215 - 0
target/linux/starfive/patches-6.1/0010-reset-starfive-Extract-the-common-JH71X0-reset-code.patch

@@ -0,0 +1,215 @@
+From dbee38aac9811a25e3e3204f813048bf64155248 Mon Sep 17 00:00:00 2001
+From: Emil Renner Berthing <[email protected]>
+Date: Sat, 1 Apr 2023 19:19:22 +0800
+Subject: [PATCH 010/122] reset: starfive: Extract the common JH71X0 reset code
+
+Extract the common JH71X0 reset code for reusing them to
+support JH7110 SoC.
+
+Tested-by: Tommaso Merciai <[email protected]>
+Reviewed-by: Conor Dooley <[email protected]>
+Reviewed-by: Emil Renner Berthing <[email protected]>
+Signed-off-by: Emil Renner Berthing <[email protected]>
+Signed-off-by: Hal Feng <[email protected]>
+Signed-off-by: Conor Dooley <[email protected]>
+---
+ .../reset/starfive/reset-starfive-jh7100.c    | 49 ++++++++++++
+ .../reset/starfive/reset-starfive-jh71x0.c    | 76 ++++++-------------
+ .../reset/starfive/reset-starfive-jh71x0.h    |  5 +-
+ 3 files changed, 76 insertions(+), 54 deletions(-)
+
+--- a/drivers/reset/starfive/reset-starfive-jh7100.c
++++ b/drivers/reset/starfive/reset-starfive-jh7100.c
+@@ -10,6 +10,55 @@
+ 
+ #include "reset-starfive-jh71x0.h"
+ 
++#include <dt-bindings/reset/starfive-jh7100.h>
++
++/* register offsets */
++#define JH7100_RESET_ASSERT0	0x00
++#define JH7100_RESET_ASSERT1	0x04
++#define JH7100_RESET_ASSERT2	0x08
++#define JH7100_RESET_ASSERT3	0x0c
++#define JH7100_RESET_STATUS0	0x10
++#define JH7100_RESET_STATUS1	0x14
++#define JH7100_RESET_STATUS2	0x18
++#define JH7100_RESET_STATUS3	0x1c
++
++/*
++ * Writing a 1 to the n'th bit of the m'th ASSERT register asserts
++ * line 32m + n, and writing a 0 deasserts the same line.
++ * Most reset lines have their status inverted so a 0 bit in the STATUS
++ * register means the line is asserted and a 1 means it's deasserted. A few
++ * lines don't though, so store the expected value of the status registers when
++ * all lines are asserted.
++ */
++static const u64 jh7100_reset_asserted[2] = {
++	/* STATUS0 */
++	BIT_ULL_MASK(JH7100_RST_U74) |
++	BIT_ULL_MASK(JH7100_RST_VP6_DRESET) |
++	BIT_ULL_MASK(JH7100_RST_VP6_BRESET) |
++	/* STATUS1 */
++	BIT_ULL_MASK(JH7100_RST_HIFI4_DRESET) |
++	BIT_ULL_MASK(JH7100_RST_HIFI4_BRESET),
++	/* STATUS2 */
++	BIT_ULL_MASK(JH7100_RST_E24) |
++	/* STATUS3 */
++	0,
++};
++
++static int __init jh7100_reset_probe(struct platform_device *pdev)
++{
++	void __iomem *base = devm_platform_ioremap_resource(pdev, 0);
++
++	if (IS_ERR(base))
++		return PTR_ERR(base);
++
++	return reset_starfive_jh7100_register(&pdev->dev, pdev->dev.of_node,
++					      base + JH7100_RESET_ASSERT0,
++					      base + JH7100_RESET_STATUS0,
++					      jh7100_reset_asserted,
++					      JH7100_RSTN_END,
++					      THIS_MODULE);
++}
++
+ static const struct of_device_id jh7100_reset_dt_ids[] = {
+ 	{ .compatible = "starfive,jh7100-reset" },
+ 	{ /* sentinel */ }
+--- a/drivers/reset/starfive/reset-starfive-jh71x0.c
++++ b/drivers/reset/starfive/reset-starfive-jh71x0.c
+@@ -10,51 +10,18 @@
+ #include <linux/io.h>
+ #include <linux/io-64-nonatomic-lo-hi.h>
+ #include <linux/iopoll.h>
+-#include <linux/platform_device.h>
+ #include <linux/reset-controller.h>
+ #include <linux/spinlock.h>
+ 
+ #include "reset-starfive-jh71x0.h"
+ 
+-#include <dt-bindings/reset/starfive-jh7100.h>
+-
+-/* register offsets */
+-#define JH7100_RESET_ASSERT0	0x00
+-#define JH7100_RESET_ASSERT1	0x04
+-#define JH7100_RESET_ASSERT2	0x08
+-#define JH7100_RESET_ASSERT3	0x0c
+-#define JH7100_RESET_STATUS0	0x10
+-#define JH7100_RESET_STATUS1	0x14
+-#define JH7100_RESET_STATUS2	0x18
+-#define JH7100_RESET_STATUS3	0x1c
+-
+-/*
+- * Writing a 1 to the n'th bit of the m'th ASSERT register asserts
+- * line 32m + n, and writing a 0 deasserts the same line.
+- * Most reset lines have their status inverted so a 0 bit in the STATUS
+- * register means the line is asserted and a 1 means it's deasserted. A few
+- * lines don't though, so store the expected value of the status registers when
+- * all lines are asserted.
+- */
+-static const u64 jh7100_reset_asserted[2] = {
+-	/* STATUS0 */
+-	BIT_ULL_MASK(JH7100_RST_U74) |
+-	BIT_ULL_MASK(JH7100_RST_VP6_DRESET) |
+-	BIT_ULL_MASK(JH7100_RST_VP6_BRESET) |
+-	/* STATUS1 */
+-	BIT_ULL_MASK(JH7100_RST_HIFI4_DRESET) |
+-	BIT_ULL_MASK(JH7100_RST_HIFI4_BRESET),
+-	/* STATUS2 */
+-	BIT_ULL_MASK(JH7100_RST_E24) |
+-	/* STATUS3 */
+-	0,
+-};
+-
+ struct jh7100_reset {
+ 	struct reset_controller_dev rcdev;
+ 	/* protect registers against concurrent read-modify-write */
+ 	spinlock_t lock;
+-	void __iomem *base;
++	void __iomem *assert;
++	void __iomem *status;
++	const u64 *asserted;
+ };
+ 
+ static inline struct jh7100_reset *
+@@ -69,9 +36,9 @@ static int jh7100_reset_update(struct re
+ 	struct jh7100_reset *data = jh7100_reset_from(rcdev);
+ 	unsigned long offset = BIT_ULL_WORD(id);
+ 	u64 mask = BIT_ULL_MASK(id);
+-	void __iomem *reg_assert = data->base + JH7100_RESET_ASSERT0 + offset * sizeof(u64);
+-	void __iomem *reg_status = data->base + JH7100_RESET_STATUS0 + offset * sizeof(u64);
+-	u64 done = jh7100_reset_asserted[offset] & mask;
++	void __iomem *reg_assert = data->assert + offset * sizeof(u64);
++	void __iomem *reg_status = data->status + offset * sizeof(u64);
++	u64 done = data->asserted ? data->asserted[offset] & mask : 0;
+ 	u64 value;
+ 	unsigned long flags;
+ 	int ret;
+@@ -125,10 +92,10 @@ static int jh7100_reset_status(struct re
+ 	struct jh7100_reset *data = jh7100_reset_from(rcdev);
+ 	unsigned long offset = BIT_ULL_WORD(id);
+ 	u64 mask = BIT_ULL_MASK(id);
+-	void __iomem *reg_status = data->base + JH7100_RESET_STATUS0 + offset * sizeof(u64);
++	void __iomem *reg_status = data->status + offset * sizeof(u64);
+ 	u64 value = readq(reg_status);
+ 
+-	return !((value ^ jh7100_reset_asserted[offset]) & mask);
++	return !((value ^ data->asserted[offset]) & mask);
+ }
+ 
+ static const struct reset_control_ops jh7100_reset_ops = {
+@@ -138,25 +105,28 @@ static const struct reset_control_ops jh
+ 	.status		= jh7100_reset_status,
+ };
+ 
+-int jh7100_reset_probe(struct platform_device *pdev)
++int reset_starfive_jh7100_register(struct device *dev, struct device_node *of_node,
++				   void __iomem *assert, void __iomem *status,
++				   const u64 *asserted, unsigned int nr_resets,
++				   struct module *owner)
+ {
+ 	struct jh7100_reset *data;
+ 
+-	data = devm_kzalloc(&pdev->dev, sizeof(*data), GFP_KERNEL);
++	data = devm_kzalloc(dev, sizeof(*data), GFP_KERNEL);
+ 	if (!data)
+ 		return -ENOMEM;
+ 
+-	data->base = devm_platform_ioremap_resource(pdev, 0);
+-	if (IS_ERR(data->base))
+-		return PTR_ERR(data->base);
+-
+ 	data->rcdev.ops = &jh7100_reset_ops;
+-	data->rcdev.owner = THIS_MODULE;
+-	data->rcdev.nr_resets = JH7100_RSTN_END;
+-	data->rcdev.dev = &pdev->dev;
+-	data->rcdev.of_node = pdev->dev.of_node;
++	data->rcdev.owner = owner;
++	data->rcdev.nr_resets = nr_resets;
++	data->rcdev.dev = dev;
++	data->rcdev.of_node = of_node;
++
+ 	spin_lock_init(&data->lock);
++	data->assert = assert;
++	data->status = status;
++	data->asserted = asserted;
+ 
+-	return devm_reset_controller_register(&pdev->dev, &data->rcdev);
++	return devm_reset_controller_register(dev, &data->rcdev);
+ }
+-EXPORT_SYMBOL_GPL(jh7100_reset_probe);
++EXPORT_SYMBOL_GPL(reset_starfive_jh7100_register);
+--- a/drivers/reset/starfive/reset-starfive-jh71x0.h
++++ b/drivers/reset/starfive/reset-starfive-jh71x0.h
+@@ -6,6 +6,9 @@
+ #ifndef __RESET_STARFIVE_JH71X0_H
+ #define __RESET_STARFIVE_JH71X0_H
+ 
+-int jh7100_reset_probe(struct platform_device *pdev);
++int reset_starfive_jh7100_register(struct device *dev, struct device_node *of_node,
++				   void __iomem *assert, void __iomem *status,
++				   const u64 *asserted, unsigned int nr_resets,
++				   struct module *owner);
+ 
+ #endif /* __RESET_STARFIVE_JH71X0_H */

+ 167 - 0
target/linux/starfive/patches-6.1/0011-reset-starfive-Rename-jh7100-to-jh71x0-for-the-commo.patch

@@ -0,0 +1,167 @@
+From 798b9b4681be53ddbf1d8db8a88ff19aaaca500f Mon Sep 17 00:00:00 2001
+From: Emil Renner Berthing <[email protected]>
+Date: Sat, 1 Apr 2023 19:19:23 +0800
+Subject: [PATCH 011/122] reset: starfive: Rename "jh7100" to "jh71x0" for the
+ common code
+
+For the common code will be shared with the StarFive JH7110 SoC.
+
+Tested-by: Tommaso Merciai <[email protected]>
+Reviewed-by: Conor Dooley <[email protected]>
+Reviewed-by: Emil Renner Berthing <[email protected]>
+Signed-off-by: Emil Renner Berthing <[email protected]>
+Signed-off-by: Hal Feng <[email protected]>
+Signed-off-by: Conor Dooley <[email protected]>
+---
+ .../reset/starfive/reset-starfive-jh7100.c    |  2 +-
+ .../reset/starfive/reset-starfive-jh71x0.c    | 50 +++++++++----------
+ .../reset/starfive/reset-starfive-jh71x0.h    |  2 +-
+ 3 files changed, 27 insertions(+), 27 deletions(-)
+
+--- a/drivers/reset/starfive/reset-starfive-jh7100.c
++++ b/drivers/reset/starfive/reset-starfive-jh7100.c
+@@ -51,7 +51,7 @@ static int __init jh7100_reset_probe(str
+ 	if (IS_ERR(base))
+ 		return PTR_ERR(base);
+ 
+-	return reset_starfive_jh7100_register(&pdev->dev, pdev->dev.of_node,
++	return reset_starfive_jh71x0_register(&pdev->dev, pdev->dev.of_node,
+ 					      base + JH7100_RESET_ASSERT0,
+ 					      base + JH7100_RESET_STATUS0,
+ 					      jh7100_reset_asserted,
+--- a/drivers/reset/starfive/reset-starfive-jh71x0.c
++++ b/drivers/reset/starfive/reset-starfive-jh71x0.c
+@@ -1,6 +1,6 @@
+ // SPDX-License-Identifier: GPL-2.0-or-later
+ /*
+- * Reset driver for the StarFive JH7100 SoC
++ * Reset driver for the StarFive JH71X0 SoCs
+  *
+  * Copyright (C) 2021 Emil Renner Berthing <[email protected]>
+  */
+@@ -15,7 +15,7 @@
+ 
+ #include "reset-starfive-jh71x0.h"
+ 
+-struct jh7100_reset {
++struct jh71x0_reset {
+ 	struct reset_controller_dev rcdev;
+ 	/* protect registers against concurrent read-modify-write */
+ 	spinlock_t lock;
+@@ -24,16 +24,16 @@ struct jh7100_reset {
+ 	const u64 *asserted;
+ };
+ 
+-static inline struct jh7100_reset *
+-jh7100_reset_from(struct reset_controller_dev *rcdev)
++static inline struct jh71x0_reset *
++jh71x0_reset_from(struct reset_controller_dev *rcdev)
+ {
+-	return container_of(rcdev, struct jh7100_reset, rcdev);
++	return container_of(rcdev, struct jh71x0_reset, rcdev);
+ }
+ 
+-static int jh7100_reset_update(struct reset_controller_dev *rcdev,
++static int jh71x0_reset_update(struct reset_controller_dev *rcdev,
+ 			       unsigned long id, bool assert)
+ {
+-	struct jh7100_reset *data = jh7100_reset_from(rcdev);
++	struct jh71x0_reset *data = jh71x0_reset_from(rcdev);
+ 	unsigned long offset = BIT_ULL_WORD(id);
+ 	u64 mask = BIT_ULL_MASK(id);
+ 	void __iomem *reg_assert = data->assert + offset * sizeof(u64);
+@@ -62,34 +62,34 @@ static int jh7100_reset_update(struct re
+ 	return ret;
+ }
+ 
+-static int jh7100_reset_assert(struct reset_controller_dev *rcdev,
++static int jh71x0_reset_assert(struct reset_controller_dev *rcdev,
+ 			       unsigned long id)
+ {
+-	return jh7100_reset_update(rcdev, id, true);
++	return jh71x0_reset_update(rcdev, id, true);
+ }
+ 
+-static int jh7100_reset_deassert(struct reset_controller_dev *rcdev,
++static int jh71x0_reset_deassert(struct reset_controller_dev *rcdev,
+ 				 unsigned long id)
+ {
+-	return jh7100_reset_update(rcdev, id, false);
++	return jh71x0_reset_update(rcdev, id, false);
+ }
+ 
+-static int jh7100_reset_reset(struct reset_controller_dev *rcdev,
++static int jh71x0_reset_reset(struct reset_controller_dev *rcdev,
+ 			      unsigned long id)
+ {
+ 	int ret;
+ 
+-	ret = jh7100_reset_assert(rcdev, id);
++	ret = jh71x0_reset_assert(rcdev, id);
+ 	if (ret)
+ 		return ret;
+ 
+-	return jh7100_reset_deassert(rcdev, id);
++	return jh71x0_reset_deassert(rcdev, id);
+ }
+ 
+-static int jh7100_reset_status(struct reset_controller_dev *rcdev,
++static int jh71x0_reset_status(struct reset_controller_dev *rcdev,
+ 			       unsigned long id)
+ {
+-	struct jh7100_reset *data = jh7100_reset_from(rcdev);
++	struct jh71x0_reset *data = jh71x0_reset_from(rcdev);
+ 	unsigned long offset = BIT_ULL_WORD(id);
+ 	u64 mask = BIT_ULL_MASK(id);
+ 	void __iomem *reg_status = data->status + offset * sizeof(u64);
+@@ -98,25 +98,25 @@ static int jh7100_reset_status(struct re
+ 	return !((value ^ data->asserted[offset]) & mask);
+ }
+ 
+-static const struct reset_control_ops jh7100_reset_ops = {
+-	.assert		= jh7100_reset_assert,
+-	.deassert	= jh7100_reset_deassert,
+-	.reset		= jh7100_reset_reset,
+-	.status		= jh7100_reset_status,
++static const struct reset_control_ops jh71x0_reset_ops = {
++	.assert		= jh71x0_reset_assert,
++	.deassert	= jh71x0_reset_deassert,
++	.reset		= jh71x0_reset_reset,
++	.status		= jh71x0_reset_status,
+ };
+ 
+-int reset_starfive_jh7100_register(struct device *dev, struct device_node *of_node,
++int reset_starfive_jh71x0_register(struct device *dev, struct device_node *of_node,
+ 				   void __iomem *assert, void __iomem *status,
+ 				   const u64 *asserted, unsigned int nr_resets,
+ 				   struct module *owner)
+ {
+-	struct jh7100_reset *data;
++	struct jh71x0_reset *data;
+ 
+ 	data = devm_kzalloc(dev, sizeof(*data), GFP_KERNEL);
+ 	if (!data)
+ 		return -ENOMEM;
+ 
+-	data->rcdev.ops = &jh7100_reset_ops;
++	data->rcdev.ops = &jh71x0_reset_ops;
+ 	data->rcdev.owner = owner;
+ 	data->rcdev.nr_resets = nr_resets;
+ 	data->rcdev.dev = dev;
+@@ -129,4 +129,4 @@ int reset_starfive_jh7100_register(struc
+ 
+ 	return devm_reset_controller_register(dev, &data->rcdev);
+ }
+-EXPORT_SYMBOL_GPL(reset_starfive_jh7100_register);
++EXPORT_SYMBOL_GPL(reset_starfive_jh71x0_register);
+--- a/drivers/reset/starfive/reset-starfive-jh71x0.h
++++ b/drivers/reset/starfive/reset-starfive-jh71x0.h
+@@ -6,7 +6,7 @@
+ #ifndef __RESET_STARFIVE_JH71X0_H
+ #define __RESET_STARFIVE_JH71X0_H
+ 
+-int reset_starfive_jh7100_register(struct device *dev, struct device_node *of_node,
++int reset_starfive_jh71x0_register(struct device *dev, struct device_node *of_node,
+ 				   void __iomem *assert, void __iomem *status,
+ 				   const u64 *asserted, unsigned int nr_resets,
+ 				   struct module *owner);

+ 146 - 0
target/linux/starfive/patches-6.1/0012-reset-starfive-jh71x0-Use-32bit-I-O-on-32bit-registe.patch

@@ -0,0 +1,146 @@
+From 365bb978e5e11a16c362d9c2c64d7bf8d04999df Mon Sep 17 00:00:00 2001
+From: Emil Renner Berthing <[email protected]>
+Date: Sat, 1 Apr 2023 19:19:24 +0800
+Subject: [PATCH 012/122] reset: starfive: jh71x0: Use 32bit I/O on 32bit
+ registers
+
+We currently use 64bit I/O on the 32bit registers. This works because
+there are an even number of assert and status registers, so they're only
+ever accessed in pairs on 64bit boundaries.
+
+There are however other reset controllers for audio and video on the
+JH7100 SoC with only one status register that isn't 64bit aligned so
+64bit I/O results in an unaligned access exception.
+
+Switch to 32bit I/O in preparation for supporting these resets too.
+
+Tested-by: Tommaso Merciai <[email protected]>
+Reviewed-by: Conor Dooley <[email protected]>
+Reviewed-by: Emil Renner Berthing <[email protected]>
+Signed-off-by: Emil Renner Berthing <[email protected]>
+Signed-off-by: Hal Feng <[email protected]>
+Signed-off-by: Conor Dooley <[email protected]>
+---
+ .../reset/starfive/reset-starfive-jh7100.c    | 14 ++++-----
+ .../reset/starfive/reset-starfive-jh71x0.c    | 31 +++++++++----------
+ .../reset/starfive/reset-starfive-jh71x0.h    |  2 +-
+ 3 files changed, 23 insertions(+), 24 deletions(-)
+
+--- a/drivers/reset/starfive/reset-starfive-jh7100.c
++++ b/drivers/reset/starfive/reset-starfive-jh7100.c
+@@ -30,16 +30,16 @@
+  * lines don't though, so store the expected value of the status registers when
+  * all lines are asserted.
+  */
+-static const u64 jh7100_reset_asserted[2] = {
++static const u32 jh7100_reset_asserted[4] = {
+ 	/* STATUS0 */
+-	BIT_ULL_MASK(JH7100_RST_U74) |
+-	BIT_ULL_MASK(JH7100_RST_VP6_DRESET) |
+-	BIT_ULL_MASK(JH7100_RST_VP6_BRESET) |
++	BIT(JH7100_RST_U74 % 32) |
++	BIT(JH7100_RST_VP6_DRESET % 32) |
++	BIT(JH7100_RST_VP6_BRESET % 32),
+ 	/* STATUS1 */
+-	BIT_ULL_MASK(JH7100_RST_HIFI4_DRESET) |
+-	BIT_ULL_MASK(JH7100_RST_HIFI4_BRESET),
++	BIT(JH7100_RST_HIFI4_DRESET % 32) |
++	BIT(JH7100_RST_HIFI4_BRESET % 32),
+ 	/* STATUS2 */
+-	BIT_ULL_MASK(JH7100_RST_E24) |
++	BIT(JH7100_RST_E24 % 32),
+ 	/* STATUS3 */
+ 	0,
+ };
+--- a/drivers/reset/starfive/reset-starfive-jh71x0.c
++++ b/drivers/reset/starfive/reset-starfive-jh71x0.c
+@@ -8,7 +8,6 @@
+ #include <linux/bitmap.h>
+ #include <linux/device.h>
+ #include <linux/io.h>
+-#include <linux/io-64-nonatomic-lo-hi.h>
+ #include <linux/iopoll.h>
+ #include <linux/reset-controller.h>
+ #include <linux/spinlock.h>
+@@ -21,7 +20,7 @@ struct jh71x0_reset {
+ 	spinlock_t lock;
+ 	void __iomem *assert;
+ 	void __iomem *status;
+-	const u64 *asserted;
++	const u32 *asserted;
+ };
+ 
+ static inline struct jh71x0_reset *
+@@ -34,12 +33,12 @@ static int jh71x0_reset_update(struct re
+ 			       unsigned long id, bool assert)
+ {
+ 	struct jh71x0_reset *data = jh71x0_reset_from(rcdev);
+-	unsigned long offset = BIT_ULL_WORD(id);
+-	u64 mask = BIT_ULL_MASK(id);
+-	void __iomem *reg_assert = data->assert + offset * sizeof(u64);
+-	void __iomem *reg_status = data->status + offset * sizeof(u64);
+-	u64 done = data->asserted ? data->asserted[offset] & mask : 0;
+-	u64 value;
++	unsigned long offset = id / 32;
++	u32 mask = BIT(id % 32);
++	void __iomem *reg_assert = data->assert + offset * sizeof(u32);
++	void __iomem *reg_status = data->status + offset * sizeof(u32);
++	u32 done = data->asserted ? data->asserted[offset] & mask : 0;
++	u32 value;
+ 	unsigned long flags;
+ 	int ret;
+ 
+@@ -48,15 +47,15 @@ static int jh71x0_reset_update(struct re
+ 
+ 	spin_lock_irqsave(&data->lock, flags);
+ 
+-	value = readq(reg_assert);
++	value = readl(reg_assert);
+ 	if (assert)
+ 		value |= mask;
+ 	else
+ 		value &= ~mask;
+-	writeq(value, reg_assert);
++	writel(value, reg_assert);
+ 
+ 	/* if the associated clock is gated, deasserting might otherwise hang forever */
+-	ret = readq_poll_timeout_atomic(reg_status, value, (value & mask) == done, 0, 1000);
++	ret = readl_poll_timeout_atomic(reg_status, value, (value & mask) == done, 0, 1000);
+ 
+ 	spin_unlock_irqrestore(&data->lock, flags);
+ 	return ret;
+@@ -90,10 +89,10 @@ static int jh71x0_reset_status(struct re
+ 			       unsigned long id)
+ {
+ 	struct jh71x0_reset *data = jh71x0_reset_from(rcdev);
+-	unsigned long offset = BIT_ULL_WORD(id);
+-	u64 mask = BIT_ULL_MASK(id);
+-	void __iomem *reg_status = data->status + offset * sizeof(u64);
+-	u64 value = readq(reg_status);
++	unsigned long offset = id / 32;
++	u32 mask = BIT(id % 32);
++	void __iomem *reg_status = data->status + offset * sizeof(u32);
++	u32 value = readl(reg_status);
+ 
+ 	return !((value ^ data->asserted[offset]) & mask);
+ }
+@@ -107,7 +106,7 @@ static const struct reset_control_ops jh
+ 
+ int reset_starfive_jh71x0_register(struct device *dev, struct device_node *of_node,
+ 				   void __iomem *assert, void __iomem *status,
+-				   const u64 *asserted, unsigned int nr_resets,
++				   const u32 *asserted, unsigned int nr_resets,
+ 				   struct module *owner)
+ {
+ 	struct jh71x0_reset *data;
+--- a/drivers/reset/starfive/reset-starfive-jh71x0.h
++++ b/drivers/reset/starfive/reset-starfive-jh71x0.h
+@@ -8,7 +8,7 @@
+ 
+ int reset_starfive_jh71x0_register(struct device *dev, struct device_node *of_node,
+ 				   void __iomem *assert, void __iomem *status,
+-				   const u64 *asserted, unsigned int nr_resets,
++				   const u32 *asserted, unsigned int nr_resets,
+ 				   struct module *owner);
+ 
+ #endif /* __RESET_STARFIVE_JH71X0_H */

+ 557 - 0
target/linux/starfive/patches-6.1/0013-clk-starfive-Add-StarFive-JH7110-system-clock-driver.patch

@@ -0,0 +1,557 @@
+From eea853275c704f6c24a418a50715bc5ad68a6283 Mon Sep 17 00:00:00 2001
+From: Emil Renner Berthing <[email protected]>
+Date: Sat, 1 Apr 2023 19:19:25 +0800
+Subject: [PATCH 013/122] clk: starfive: Add StarFive JH7110 system clock
+ driver
+
+Add driver for the StarFive JH7110 system clock controller and
+register an auxiliary device for system reset controller which
+is named as "rst-sys".
+
+Tested-by: Tommaso Merciai <[email protected]>
+Reviewed-by: Emil Renner Berthing <[email protected]>
+Signed-off-by: Emil Renner Berthing <[email protected]>
+Co-developed-by: Hal Feng <[email protected]>
+Signed-off-by: Hal Feng <[email protected]>
+Signed-off-by: Conor Dooley <[email protected]>
+---
+ drivers/clk/starfive/Kconfig                  |  11 +
+ drivers/clk/starfive/Makefile                 |   2 +
+ .../clk/starfive/clk-starfive-jh7110-sys.c    | 490 ++++++++++++++++++
+ drivers/clk/starfive/clk-starfive-jh7110.h    |  11 +
+ 4 files changed, 514 insertions(+)
+ create mode 100644 drivers/clk/starfive/clk-starfive-jh7110-sys.c
+ create mode 100644 drivers/clk/starfive/clk-starfive-jh7110.h
+
+--- a/drivers/clk/starfive/Kconfig
++++ b/drivers/clk/starfive/Kconfig
+@@ -20,3 +20,14 @@ config CLK_STARFIVE_JH7100_AUDIO
+ 	help
+ 	  Say Y or M here to support the audio clocks on the StarFive JH7100
+ 	  SoC.
++
++config CLK_STARFIVE_JH7110_SYS
++	bool "StarFive JH7110 system clock support"
++	depends on ARCH_STARFIVE || COMPILE_TEST
++	select AUXILIARY_BUS
++	select CLK_STARFIVE_JH71X0
++	select RESET_STARFIVE_JH7110
++	default ARCH_STARFIVE
++	help
++	  Say yes here to support the system clock controller on the
++	  StarFive JH7110 SoC.
+--- a/drivers/clk/starfive/Makefile
++++ b/drivers/clk/starfive/Makefile
+@@ -3,3 +3,5 @@ obj-$(CONFIG_CLK_STARFIVE_JH71X0)	+= clk
+ 
+ obj-$(CONFIG_CLK_STARFIVE_JH7100)	+= clk-starfive-jh7100.o
+ obj-$(CONFIG_CLK_STARFIVE_JH7100_AUDIO)	+= clk-starfive-jh7100-audio.o
++
++obj-$(CONFIG_CLK_STARFIVE_JH7110_SYS)	+= clk-starfive-jh7110-sys.o
+--- /dev/null
++++ b/drivers/clk/starfive/clk-starfive-jh7110-sys.c
+@@ -0,0 +1,490 @@
++// SPDX-License-Identifier: GPL-2.0
++/*
++ * StarFive JH7110 System Clock Driver
++ *
++ * Copyright (C) 2022 Emil Renner Berthing <[email protected]>
++ * Copyright (C) 2022 StarFive Technology Co., Ltd.
++ */
++
++#include <linux/auxiliary_bus.h>
++#include <linux/clk-provider.h>
++#include <linux/init.h>
++#include <linux/io.h>
++#include <linux/platform_device.h>
++
++#include <dt-bindings/clock/starfive,jh7110-crg.h>
++
++#include "clk-starfive-jh7110.h"
++
++/* external clocks */
++#define JH7110_SYSCLK_OSC			(JH7110_SYSCLK_END + 0)
++#define JH7110_SYSCLK_GMAC1_RMII_REFIN		(JH7110_SYSCLK_END + 1)
++#define JH7110_SYSCLK_GMAC1_RGMII_RXIN		(JH7110_SYSCLK_END + 2)
++#define JH7110_SYSCLK_I2STX_BCLK_EXT		(JH7110_SYSCLK_END + 3)
++#define JH7110_SYSCLK_I2STX_LRCK_EXT		(JH7110_SYSCLK_END + 4)
++#define JH7110_SYSCLK_I2SRX_BCLK_EXT		(JH7110_SYSCLK_END + 5)
++#define JH7110_SYSCLK_I2SRX_LRCK_EXT		(JH7110_SYSCLK_END + 6)
++#define JH7110_SYSCLK_TDM_EXT			(JH7110_SYSCLK_END + 7)
++#define JH7110_SYSCLK_MCLK_EXT			(JH7110_SYSCLK_END + 8)
++#define JH7110_SYSCLK_PLL0_OUT			(JH7110_SYSCLK_END + 9)
++#define JH7110_SYSCLK_PLL1_OUT			(JH7110_SYSCLK_END + 10)
++#define JH7110_SYSCLK_PLL2_OUT			(JH7110_SYSCLK_END + 11)
++
++static const struct jh71x0_clk_data jh7110_sysclk_data[] __initconst = {
++	/* root */
++	JH71X0__MUX(JH7110_SYSCLK_CPU_ROOT, "cpu_root", 2,
++		    JH7110_SYSCLK_OSC,
++		    JH7110_SYSCLK_PLL0_OUT),
++	JH71X0__DIV(JH7110_SYSCLK_CPU_CORE, "cpu_core", 7, JH7110_SYSCLK_CPU_ROOT),
++	JH71X0__DIV(JH7110_SYSCLK_CPU_BUS, "cpu_bus", 2, JH7110_SYSCLK_CPU_CORE),
++	JH71X0__MUX(JH7110_SYSCLK_GPU_ROOT, "gpu_root", 2,
++		    JH7110_SYSCLK_PLL2_OUT,
++		    JH7110_SYSCLK_PLL1_OUT),
++	JH71X0_MDIV(JH7110_SYSCLK_PERH_ROOT, "perh_root", 2, 2,
++		    JH7110_SYSCLK_PLL0_OUT,
++		    JH7110_SYSCLK_PLL2_OUT),
++	JH71X0__MUX(JH7110_SYSCLK_BUS_ROOT, "bus_root", 2,
++		    JH7110_SYSCLK_OSC,
++		    JH7110_SYSCLK_PLL2_OUT),
++	JH71X0__DIV(JH7110_SYSCLK_NOCSTG_BUS, "nocstg_bus", 3, JH7110_SYSCLK_BUS_ROOT),
++	JH71X0__DIV(JH7110_SYSCLK_AXI_CFG0, "axi_cfg0", 3, JH7110_SYSCLK_BUS_ROOT),
++	JH71X0__DIV(JH7110_SYSCLK_STG_AXIAHB, "stg_axiahb", 2, JH7110_SYSCLK_AXI_CFG0),
++	JH71X0_GATE(JH7110_SYSCLK_AHB0, "ahb0", CLK_IS_CRITICAL, JH7110_SYSCLK_STG_AXIAHB),
++	JH71X0_GATE(JH7110_SYSCLK_AHB1, "ahb1", CLK_IS_CRITICAL, JH7110_SYSCLK_STG_AXIAHB),
++	JH71X0__DIV(JH7110_SYSCLK_APB_BUS, "apb_bus", 8, JH7110_SYSCLK_STG_AXIAHB),
++	JH71X0_GATE(JH7110_SYSCLK_APB0, "apb0", CLK_IS_CRITICAL, JH7110_SYSCLK_APB_BUS),
++	JH71X0__DIV(JH7110_SYSCLK_PLL0_DIV2, "pll0_div2", 2, JH7110_SYSCLK_PLL0_OUT),
++	JH71X0__DIV(JH7110_SYSCLK_PLL1_DIV2, "pll1_div2", 2, JH7110_SYSCLK_PLL1_OUT),
++	JH71X0__DIV(JH7110_SYSCLK_PLL2_DIV2, "pll2_div2", 2, JH7110_SYSCLK_PLL2_OUT),
++	JH71X0__DIV(JH7110_SYSCLK_AUDIO_ROOT, "audio_root", 8, JH7110_SYSCLK_PLL2_OUT),
++	JH71X0__DIV(JH7110_SYSCLK_MCLK_INNER, "mclk_inner", 64, JH7110_SYSCLK_AUDIO_ROOT),
++	JH71X0__MUX(JH7110_SYSCLK_MCLK, "mclk", 2,
++		    JH7110_SYSCLK_MCLK_INNER,
++		    JH7110_SYSCLK_MCLK_EXT),
++	JH71X0_GATE(JH7110_SYSCLK_MCLK_OUT, "mclk_out", 0, JH7110_SYSCLK_MCLK_INNER),
++	JH71X0_MDIV(JH7110_SYSCLK_ISP_2X, "isp_2x", 8, 2,
++		    JH7110_SYSCLK_PLL2_OUT,
++		    JH7110_SYSCLK_PLL1_OUT),
++	JH71X0__DIV(JH7110_SYSCLK_ISP_AXI, "isp_axi", 4, JH7110_SYSCLK_ISP_2X),
++	JH71X0_GDIV(JH7110_SYSCLK_GCLK0, "gclk0", 0, 62, JH7110_SYSCLK_PLL0_DIV2),
++	JH71X0_GDIV(JH7110_SYSCLK_GCLK1, "gclk1", 0, 62, JH7110_SYSCLK_PLL1_DIV2),
++	JH71X0_GDIV(JH7110_SYSCLK_GCLK2, "gclk2", 0, 62, JH7110_SYSCLK_PLL2_DIV2),
++	/* cores */
++	JH71X0_GATE(JH7110_SYSCLK_CORE, "core", CLK_IS_CRITICAL, JH7110_SYSCLK_CPU_CORE),
++	JH71X0_GATE(JH7110_SYSCLK_CORE1, "core1", CLK_IS_CRITICAL, JH7110_SYSCLK_CPU_CORE),
++	JH71X0_GATE(JH7110_SYSCLK_CORE2, "core2", CLK_IS_CRITICAL, JH7110_SYSCLK_CPU_CORE),
++	JH71X0_GATE(JH7110_SYSCLK_CORE3, "core3", CLK_IS_CRITICAL, JH7110_SYSCLK_CPU_CORE),
++	JH71X0_GATE(JH7110_SYSCLK_CORE4, "core4", CLK_IS_CRITICAL, JH7110_SYSCLK_CPU_CORE),
++	JH71X0_GATE(JH7110_SYSCLK_DEBUG, "debug", 0, JH7110_SYSCLK_CPU_BUS),
++	JH71X0__DIV(JH7110_SYSCLK_RTC_TOGGLE, "rtc_toggle", 6, JH7110_SYSCLK_OSC),
++	JH71X0_GATE(JH7110_SYSCLK_TRACE0, "trace0", 0, JH7110_SYSCLK_CPU_CORE),
++	JH71X0_GATE(JH7110_SYSCLK_TRACE1, "trace1", 0, JH7110_SYSCLK_CPU_CORE),
++	JH71X0_GATE(JH7110_SYSCLK_TRACE2, "trace2", 0, JH7110_SYSCLK_CPU_CORE),
++	JH71X0_GATE(JH7110_SYSCLK_TRACE3, "trace3", 0, JH7110_SYSCLK_CPU_CORE),
++	JH71X0_GATE(JH7110_SYSCLK_TRACE4, "trace4", 0, JH7110_SYSCLK_CPU_CORE),
++	JH71X0_GATE(JH7110_SYSCLK_TRACE_COM, "trace_com", 0, JH7110_SYSCLK_CPU_BUS),
++	/* noc */
++	JH71X0_GATE(JH7110_SYSCLK_NOC_BUS_CPU_AXI, "noc_bus_cpu_axi", CLK_IS_CRITICAL,
++		    JH7110_SYSCLK_CPU_BUS),
++	JH71X0_GATE(JH7110_SYSCLK_NOC_BUS_AXICFG0_AXI, "noc_bus_axicfg0_axi", CLK_IS_CRITICAL,
++		    JH7110_SYSCLK_AXI_CFG0),
++	/* ddr */
++	JH71X0__DIV(JH7110_SYSCLK_OSC_DIV2, "osc_div2", 2, JH7110_SYSCLK_OSC),
++	JH71X0__DIV(JH7110_SYSCLK_PLL1_DIV4, "pll1_div4", 2, JH7110_SYSCLK_PLL1_DIV2),
++	JH71X0__DIV(JH7110_SYSCLK_PLL1_DIV8, "pll1_div8", 2, JH7110_SYSCLK_PLL1_DIV4),
++	JH71X0__MUX(JH7110_SYSCLK_DDR_BUS, "ddr_bus", 4,
++		    JH7110_SYSCLK_OSC_DIV2,
++		    JH7110_SYSCLK_PLL1_DIV2,
++		    JH7110_SYSCLK_PLL1_DIV4,
++		    JH7110_SYSCLK_PLL1_DIV8),
++	JH71X0_GATE(JH7110_SYSCLK_DDR_AXI, "ddr_axi", CLK_IS_CRITICAL, JH7110_SYSCLK_DDR_BUS),
++	/* gpu */
++	JH71X0__DIV(JH7110_SYSCLK_GPU_CORE, "gpu_core", 7, JH7110_SYSCLK_GPU_ROOT),
++	JH71X0_GATE(JH7110_SYSCLK_GPU_CORE_CLK, "gpu_core_clk", 0, JH7110_SYSCLK_GPU_CORE),
++	JH71X0_GATE(JH7110_SYSCLK_GPU_SYS_CLK, "gpu_sys_clk", 0, JH7110_SYSCLK_ISP_AXI),
++	JH71X0_GATE(JH7110_SYSCLK_GPU_APB, "gpu_apb", 0, JH7110_SYSCLK_APB_BUS),
++	JH71X0_GDIV(JH7110_SYSCLK_GPU_RTC_TOGGLE, "gpu_rtc_toggle", 0, 12, JH7110_SYSCLK_OSC),
++	JH71X0_GATE(JH7110_SYSCLK_NOC_BUS_GPU_AXI, "noc_bus_gpu_axi", 0, JH7110_SYSCLK_GPU_CORE),
++	/* isp */
++	JH71X0_GATE(JH7110_SYSCLK_ISP_TOP_CORE, "isp_top_core", 0, JH7110_SYSCLK_ISP_2X),
++	JH71X0_GATE(JH7110_SYSCLK_ISP_TOP_AXI, "isp_top_axi", 0, JH7110_SYSCLK_ISP_AXI),
++	JH71X0_GATE(JH7110_SYSCLK_NOC_BUS_ISP_AXI, "noc_bus_isp_axi", CLK_IS_CRITICAL,
++		    JH7110_SYSCLK_ISP_AXI),
++	/* hifi4 */
++	JH71X0__DIV(JH7110_SYSCLK_HIFI4_CORE, "hifi4_core", 15, JH7110_SYSCLK_BUS_ROOT),
++	JH71X0__DIV(JH7110_SYSCLK_HIFI4_AXI, "hifi4_axi", 2, JH7110_SYSCLK_HIFI4_CORE),
++	/* axi_cfg1 */
++	JH71X0_GATE(JH7110_SYSCLK_AXI_CFG1_MAIN, "axi_cfg1_main", CLK_IS_CRITICAL,
++		    JH7110_SYSCLK_ISP_AXI),
++	JH71X0_GATE(JH7110_SYSCLK_AXI_CFG1_AHB, "axi_cfg1_ahb", CLK_IS_CRITICAL,
++		    JH7110_SYSCLK_AHB0),
++	/* vout */
++	JH71X0_GATE(JH7110_SYSCLK_VOUT_SRC, "vout_src", 0, JH7110_SYSCLK_PLL2_OUT),
++	JH71X0__DIV(JH7110_SYSCLK_VOUT_AXI, "vout_axi", 7, JH7110_SYSCLK_PLL2_OUT),
++	JH71X0_GATE(JH7110_SYSCLK_NOC_BUS_DISP_AXI, "noc_bus_disp_axi", 0, JH7110_SYSCLK_VOUT_AXI),
++	JH71X0_GATE(JH7110_SYSCLK_VOUT_TOP_AHB, "vout_top_ahb", 0, JH7110_SYSCLK_AHB1),
++	JH71X0_GATE(JH7110_SYSCLK_VOUT_TOP_AXI, "vout_top_axi", 0, JH7110_SYSCLK_VOUT_AXI),
++	JH71X0_GATE(JH7110_SYSCLK_VOUT_TOP_HDMITX0_MCLK, "vout_top_hdmitx0_mclk", 0,
++		    JH7110_SYSCLK_MCLK),
++	JH71X0__DIV(JH7110_SYSCLK_VOUT_TOP_MIPIPHY_REF, "vout_top_mipiphy_ref", 2,
++		    JH7110_SYSCLK_OSC),
++	/* jpegc */
++	JH71X0__DIV(JH7110_SYSCLK_JPEGC_AXI, "jpegc_axi", 16, JH7110_SYSCLK_PLL2_OUT),
++	JH71X0_GATE(JH7110_SYSCLK_CODAJ12_AXI, "codaj12_axi", 0, JH7110_SYSCLK_JPEGC_AXI),
++	JH71X0_GDIV(JH7110_SYSCLK_CODAJ12_CORE, "codaj12_core", 0, 16, JH7110_SYSCLK_PLL2_OUT),
++	JH71X0_GATE(JH7110_SYSCLK_CODAJ12_APB, "codaj12_apb", 0, JH7110_SYSCLK_APB_BUS),
++	/* vdec */
++	JH71X0__DIV(JH7110_SYSCLK_VDEC_AXI, "vdec_axi", 7, JH7110_SYSCLK_BUS_ROOT),
++	JH71X0_GATE(JH7110_SYSCLK_WAVE511_AXI, "wave511_axi", 0, JH7110_SYSCLK_VDEC_AXI),
++	JH71X0_GDIV(JH7110_SYSCLK_WAVE511_BPU, "wave511_bpu", 0, 7, JH7110_SYSCLK_BUS_ROOT),
++	JH71X0_GDIV(JH7110_SYSCLK_WAVE511_VCE, "wave511_vce", 0, 7, JH7110_SYSCLK_PLL0_OUT),
++	JH71X0_GATE(JH7110_SYSCLK_WAVE511_APB, "wave511_apb", 0, JH7110_SYSCLK_APB_BUS),
++	JH71X0_GATE(JH7110_SYSCLK_VDEC_JPG, "vdec_jpg", 0, JH7110_SYSCLK_JPEGC_AXI),
++	JH71X0_GATE(JH7110_SYSCLK_VDEC_MAIN, "vdec_main", 0, JH7110_SYSCLK_VDEC_AXI),
++	JH71X0_GATE(JH7110_SYSCLK_NOC_BUS_VDEC_AXI, "noc_bus_vdec_axi", 0, JH7110_SYSCLK_VDEC_AXI),
++	/* venc */
++	JH71X0__DIV(JH7110_SYSCLK_VENC_AXI, "venc_axi", 15, JH7110_SYSCLK_PLL2_OUT),
++	JH71X0_GATE(JH7110_SYSCLK_WAVE420L_AXI, "wave420l_axi", 0, JH7110_SYSCLK_VENC_AXI),
++	JH71X0_GDIV(JH7110_SYSCLK_WAVE420L_BPU, "wave420l_bpu", 0, 15, JH7110_SYSCLK_PLL2_OUT),
++	JH71X0_GDIV(JH7110_SYSCLK_WAVE420L_VCE, "wave420l_vce", 0, 15, JH7110_SYSCLK_PLL2_OUT),
++	JH71X0_GATE(JH7110_SYSCLK_WAVE420L_APB, "wave420l_apb", 0, JH7110_SYSCLK_APB_BUS),
++	JH71X0_GATE(JH7110_SYSCLK_NOC_BUS_VENC_AXI, "noc_bus_venc_axi", 0, JH7110_SYSCLK_VENC_AXI),
++	/* axi_cfg0 */
++	JH71X0_GATE(JH7110_SYSCLK_AXI_CFG0_MAIN_DIV, "axi_cfg0_main_div", CLK_IS_CRITICAL,
++		    JH7110_SYSCLK_AHB1),
++	JH71X0_GATE(JH7110_SYSCLK_AXI_CFG0_MAIN, "axi_cfg0_main", CLK_IS_CRITICAL,
++		    JH7110_SYSCLK_AXI_CFG0),
++	JH71X0_GATE(JH7110_SYSCLK_AXI_CFG0_HIFI4, "axi_cfg0_hifi4", CLK_IS_CRITICAL,
++		    JH7110_SYSCLK_HIFI4_AXI),
++	/* intmem */
++	JH71X0_GATE(JH7110_SYSCLK_AXIMEM2_AXI, "aximem2_axi", 0, JH7110_SYSCLK_AXI_CFG0),
++	/* qspi */
++	JH71X0_GATE(JH7110_SYSCLK_QSPI_AHB, "qspi_ahb", 0, JH7110_SYSCLK_AHB1),
++	JH71X0_GATE(JH7110_SYSCLK_QSPI_APB, "qspi_apb", 0, JH7110_SYSCLK_APB_BUS),
++	JH71X0__DIV(JH7110_SYSCLK_QSPI_REF_SRC, "qspi_ref_src", 16, JH7110_SYSCLK_PLL0_OUT),
++	JH71X0_GMUX(JH7110_SYSCLK_QSPI_REF, "qspi_ref", 0, 2,
++		    JH7110_SYSCLK_OSC,
++		    JH7110_SYSCLK_QSPI_REF_SRC),
++	/* sdio */
++	JH71X0_GATE(JH7110_SYSCLK_SDIO0_AHB, "sdio0_ahb", 0, JH7110_SYSCLK_AHB0),
++	JH71X0_GATE(JH7110_SYSCLK_SDIO1_AHB, "sdio1_ahb", 0, JH7110_SYSCLK_AHB0),
++	JH71X0_GDIV(JH7110_SYSCLK_SDIO0_SDCARD, "sdio0_sdcard", 0, 15, JH7110_SYSCLK_AXI_CFG0),
++	JH71X0_GDIV(JH7110_SYSCLK_SDIO1_SDCARD, "sdio1_sdcard", 0, 15, JH7110_SYSCLK_AXI_CFG0),
++	/* stg */
++	JH71X0__DIV(JH7110_SYSCLK_USB_125M, "usb_125m", 15, JH7110_SYSCLK_PLL0_OUT),
++	JH71X0_GATE(JH7110_SYSCLK_NOC_BUS_STG_AXI, "noc_bus_stg_axi", CLK_IS_CRITICAL,
++		    JH7110_SYSCLK_NOCSTG_BUS),
++	/* gmac1 */
++	JH71X0_GATE(JH7110_SYSCLK_GMAC1_AHB, "gmac1_ahb", 0, JH7110_SYSCLK_AHB0),
++	JH71X0_GATE(JH7110_SYSCLK_GMAC1_AXI, "gmac1_axi", 0, JH7110_SYSCLK_STG_AXIAHB),
++	JH71X0__DIV(JH7110_SYSCLK_GMAC_SRC, "gmac_src", 7, JH7110_SYSCLK_PLL0_OUT),
++	JH71X0__DIV(JH7110_SYSCLK_GMAC1_GTXCLK, "gmac1_gtxclk", 15, JH7110_SYSCLK_PLL0_OUT),
++	JH71X0__DIV(JH7110_SYSCLK_GMAC1_RMII_RTX, "gmac1_rmii_rtx", 30,
++		    JH7110_SYSCLK_GMAC1_RMII_REFIN),
++	JH71X0_GDIV(JH7110_SYSCLK_GMAC1_PTP, "gmac1_ptp", 0, 31, JH7110_SYSCLK_GMAC_SRC),
++	JH71X0__MUX(JH7110_SYSCLK_GMAC1_RX, "gmac1_rx", 2,
++		    JH7110_SYSCLK_GMAC1_RGMII_RXIN,
++		    JH7110_SYSCLK_GMAC1_RMII_RTX),
++	JH71X0__INV(JH7110_SYSCLK_GMAC1_RX_INV, "gmac1_rx_inv", JH7110_SYSCLK_GMAC1_RX),
++	JH71X0_GMUX(JH7110_SYSCLK_GMAC1_TX, "gmac1_tx",
++		    CLK_SET_RATE_PARENT | CLK_SET_RATE_NO_REPARENT, 2,
++		    JH7110_SYSCLK_GMAC1_GTXCLK,
++		    JH7110_SYSCLK_GMAC1_RMII_RTX),
++	JH71X0__INV(JH7110_SYSCLK_GMAC1_TX_INV, "gmac1_tx_inv", JH7110_SYSCLK_GMAC1_TX),
++	JH71X0_GATE(JH7110_SYSCLK_GMAC1_GTXC, "gmac1_gtxc", 0, JH7110_SYSCLK_GMAC1_GTXCLK),
++	/* gmac0 */
++	JH71X0_GDIV(JH7110_SYSCLK_GMAC0_GTXCLK, "gmac0_gtxclk", 0, 15, JH7110_SYSCLK_PLL0_OUT),
++	JH71X0_GDIV(JH7110_SYSCLK_GMAC0_PTP, "gmac0_ptp", 0, 31, JH7110_SYSCLK_GMAC_SRC),
++	JH71X0_GDIV(JH7110_SYSCLK_GMAC_PHY, "gmac_phy", 0, 31, JH7110_SYSCLK_GMAC_SRC),
++	JH71X0_GATE(JH7110_SYSCLK_GMAC0_GTXC, "gmac0_gtxc", 0, JH7110_SYSCLK_GMAC0_GTXCLK),
++	/* apb misc */
++	JH71X0_GATE(JH7110_SYSCLK_IOMUX_APB, "iomux_apb", 0, JH7110_SYSCLK_APB_BUS),
++	JH71X0_GATE(JH7110_SYSCLK_MAILBOX_APB, "mailbox_apb", 0, JH7110_SYSCLK_APB_BUS),
++	JH71X0_GATE(JH7110_SYSCLK_INT_CTRL_APB, "int_ctrl_apb", 0, JH7110_SYSCLK_APB_BUS),
++	/* can0 */
++	JH71X0_GATE(JH7110_SYSCLK_CAN0_APB, "can0_apb", 0, JH7110_SYSCLK_APB_BUS),
++	JH71X0_GDIV(JH7110_SYSCLK_CAN0_TIMER, "can0_timer", 0, 24, JH7110_SYSCLK_OSC),
++	JH71X0_GDIV(JH7110_SYSCLK_CAN0_CAN, "can0_can", 0, 63, JH7110_SYSCLK_PERH_ROOT),
++	/* can1 */
++	JH71X0_GATE(JH7110_SYSCLK_CAN1_APB, "can1_apb", 0, JH7110_SYSCLK_APB_BUS),
++	JH71X0_GDIV(JH7110_SYSCLK_CAN1_TIMER, "can1_timer", 0, 24, JH7110_SYSCLK_OSC),
++	JH71X0_GDIV(JH7110_SYSCLK_CAN1_CAN, "can1_can", 0, 63, JH7110_SYSCLK_PERH_ROOT),
++	/* pwm */
++	JH71X0_GATE(JH7110_SYSCLK_PWM_APB, "pwm_apb", 0, JH7110_SYSCLK_APB_BUS),
++	/* wdt */
++	JH71X0_GATE(JH7110_SYSCLK_WDT_APB, "wdt_apb", 0, JH7110_SYSCLK_APB_BUS),
++	JH71X0_GATE(JH7110_SYSCLK_WDT_CORE, "wdt_core", 0, JH7110_SYSCLK_OSC),
++	/* timer */
++	JH71X0_GATE(JH7110_SYSCLK_TIMER_APB, "timer_apb", 0, JH7110_SYSCLK_APB_BUS),
++	JH71X0_GATE(JH7110_SYSCLK_TIMER0, "timer0", 0, JH7110_SYSCLK_OSC),
++	JH71X0_GATE(JH7110_SYSCLK_TIMER1, "timer1", 0, JH7110_SYSCLK_OSC),
++	JH71X0_GATE(JH7110_SYSCLK_TIMER2, "timer2", 0, JH7110_SYSCLK_OSC),
++	JH71X0_GATE(JH7110_SYSCLK_TIMER3, "timer3", 0, JH7110_SYSCLK_OSC),
++	/* temp sensor */
++	JH71X0_GATE(JH7110_SYSCLK_TEMP_APB, "temp_apb", 0, JH7110_SYSCLK_APB_BUS),
++	JH71X0_GDIV(JH7110_SYSCLK_TEMP_CORE, "temp_core", 0, 24, JH7110_SYSCLK_OSC),
++	/* spi */
++	JH71X0_GATE(JH7110_SYSCLK_SPI0_APB, "spi0_apb", 0, JH7110_SYSCLK_APB0),
++	JH71X0_GATE(JH7110_SYSCLK_SPI1_APB, "spi1_apb", 0, JH7110_SYSCLK_APB0),
++	JH71X0_GATE(JH7110_SYSCLK_SPI2_APB, "spi2_apb", 0, JH7110_SYSCLK_APB0),
++	JH71X0_GATE(JH7110_SYSCLK_SPI3_APB, "spi3_apb", 0, JH7110_SYSCLK_APB_BUS),
++	JH71X0_GATE(JH7110_SYSCLK_SPI4_APB, "spi4_apb", 0, JH7110_SYSCLK_APB_BUS),
++	JH71X0_GATE(JH7110_SYSCLK_SPI5_APB, "spi5_apb", 0, JH7110_SYSCLK_APB_BUS),
++	JH71X0_GATE(JH7110_SYSCLK_SPI6_APB, "spi6_apb", 0, JH7110_SYSCLK_APB_BUS),
++	/* i2c */
++	JH71X0_GATE(JH7110_SYSCLK_I2C0_APB, "i2c0_apb", 0, JH7110_SYSCLK_APB0),
++	JH71X0_GATE(JH7110_SYSCLK_I2C1_APB, "i2c1_apb", 0, JH7110_SYSCLK_APB0),
++	JH71X0_GATE(JH7110_SYSCLK_I2C2_APB, "i2c2_apb", 0, JH7110_SYSCLK_APB0),
++	JH71X0_GATE(JH7110_SYSCLK_I2C3_APB, "i2c3_apb", 0, JH7110_SYSCLK_APB_BUS),
++	JH71X0_GATE(JH7110_SYSCLK_I2C4_APB, "i2c4_apb", 0, JH7110_SYSCLK_APB_BUS),
++	JH71X0_GATE(JH7110_SYSCLK_I2C5_APB, "i2c5_apb", 0, JH7110_SYSCLK_APB_BUS),
++	JH71X0_GATE(JH7110_SYSCLK_I2C6_APB, "i2c6_apb", 0, JH7110_SYSCLK_APB_BUS),
++	/* uart */
++	JH71X0_GATE(JH7110_SYSCLK_UART0_APB, "uart0_apb", 0, JH7110_SYSCLK_APB0),
++	JH71X0_GATE(JH7110_SYSCLK_UART0_CORE, "uart0_core", 0, JH7110_SYSCLK_OSC),
++	JH71X0_GATE(JH7110_SYSCLK_UART1_APB, "uart1_apb", 0, JH7110_SYSCLK_APB0),
++	JH71X0_GATE(JH7110_SYSCLK_UART1_CORE, "uart1_core", 0, JH7110_SYSCLK_OSC),
++	JH71X0_GATE(JH7110_SYSCLK_UART2_APB, "uart2_apb", 0, JH7110_SYSCLK_APB0),
++	JH71X0_GATE(JH7110_SYSCLK_UART2_CORE, "uart2_core", 0, JH7110_SYSCLK_OSC),
++	JH71X0_GATE(JH7110_SYSCLK_UART3_APB, "uart3_apb", 0, JH7110_SYSCLK_APB0),
++	JH71X0_GDIV(JH7110_SYSCLK_UART3_CORE, "uart3_core", 0, 10, JH7110_SYSCLK_PERH_ROOT),
++	JH71X0_GATE(JH7110_SYSCLK_UART4_APB, "uart4_apb", 0, JH7110_SYSCLK_APB0),
++	JH71X0_GDIV(JH7110_SYSCLK_UART4_CORE, "uart4_core", 0, 10, JH7110_SYSCLK_PERH_ROOT),
++	JH71X0_GATE(JH7110_SYSCLK_UART5_APB, "uart5_apb", 0, JH7110_SYSCLK_APB0),
++	JH71X0_GDIV(JH7110_SYSCLK_UART5_CORE, "uart5_core", 0, 10, JH7110_SYSCLK_PERH_ROOT),
++	/* pwmdac */
++	JH71X0_GATE(JH7110_SYSCLK_PWMDAC_APB, "pwmdac_apb", 0, JH7110_SYSCLK_APB0),
++	JH71X0_GDIV(JH7110_SYSCLK_PWMDAC_CORE, "pwmdac_core", 0, 256, JH7110_SYSCLK_AUDIO_ROOT),
++	/* spdif */
++	JH71X0_GATE(JH7110_SYSCLK_SPDIF_APB, "spdif_apb", 0, JH7110_SYSCLK_APB0),
++	JH71X0_GATE(JH7110_SYSCLK_SPDIF_CORE, "spdif_core", 0, JH7110_SYSCLK_MCLK),
++	/* i2stx0 */
++	JH71X0_GATE(JH7110_SYSCLK_I2STX0_APB, "i2stx0_apb", 0, JH7110_SYSCLK_APB0),
++	JH71X0_GDIV(JH7110_SYSCLK_I2STX0_BCLK_MST, "i2stx0_bclk_mst", 0, 32, JH7110_SYSCLK_MCLK),
++	JH71X0__INV(JH7110_SYSCLK_I2STX0_BCLK_MST_INV, "i2stx0_bclk_mst_inv",
++		    JH7110_SYSCLK_I2STX0_BCLK_MST),
++	JH71X0_MDIV(JH7110_SYSCLK_I2STX0_LRCK_MST, "i2stx0_lrck_mst", 64, 2,
++		    JH7110_SYSCLK_I2STX0_BCLK_MST_INV,
++		    JH7110_SYSCLK_I2STX0_BCLK_MST),
++	JH71X0__MUX(JH7110_SYSCLK_I2STX0_BCLK, "i2stx0_bclk",	2,
++		    JH7110_SYSCLK_I2STX0_BCLK_MST,
++		    JH7110_SYSCLK_I2STX_BCLK_EXT),
++	JH71X0__INV(JH7110_SYSCLK_I2STX0_BCLK_INV, "i2stx0_bclk_inv", JH7110_SYSCLK_I2STX0_BCLK),
++	JH71X0__MUX(JH7110_SYSCLK_I2STX0_LRCK, "i2stx0_lrck", 2,
++		    JH7110_SYSCLK_I2STX0_LRCK_MST,
++		    JH7110_SYSCLK_I2STX_LRCK_EXT),
++	/* i2stx1 */
++	JH71X0_GATE(JH7110_SYSCLK_I2STX1_APB, "i2stx1_apb", 0, JH7110_SYSCLK_APB0),
++	JH71X0_GDIV(JH7110_SYSCLK_I2STX1_BCLK_MST, "i2stx1_bclk_mst", 0, 32, JH7110_SYSCLK_MCLK),
++	JH71X0__INV(JH7110_SYSCLK_I2STX1_BCLK_MST_INV, "i2stx1_bclk_mst_inv",
++		    JH7110_SYSCLK_I2STX1_BCLK_MST),
++	JH71X0_MDIV(JH7110_SYSCLK_I2STX1_LRCK_MST, "i2stx1_lrck_mst", 64, 2,
++		    JH7110_SYSCLK_I2STX1_BCLK_MST_INV,
++		    JH7110_SYSCLK_I2STX1_BCLK_MST),
++	JH71X0__MUX(JH7110_SYSCLK_I2STX1_BCLK, "i2stx1_bclk", 2,
++		    JH7110_SYSCLK_I2STX1_BCLK_MST,
++		    JH7110_SYSCLK_I2STX_BCLK_EXT),
++	JH71X0__INV(JH7110_SYSCLK_I2STX1_BCLK_INV, "i2stx1_bclk_inv", JH7110_SYSCLK_I2STX1_BCLK),
++	JH71X0__MUX(JH7110_SYSCLK_I2STX1_LRCK, "i2stx1_lrck", 2,
++		    JH7110_SYSCLK_I2STX1_LRCK_MST,
++		    JH7110_SYSCLK_I2STX_LRCK_EXT),
++	/* i2srx */
++	JH71X0_GATE(JH7110_SYSCLK_I2SRX_APB, "i2srx_apb", 0, JH7110_SYSCLK_APB0),
++	JH71X0_GDIV(JH7110_SYSCLK_I2SRX_BCLK_MST, "i2srx_bclk_mst", 0, 32, JH7110_SYSCLK_MCLK),
++	JH71X0__INV(JH7110_SYSCLK_I2SRX_BCLK_MST_INV, "i2srx_bclk_mst_inv",
++		    JH7110_SYSCLK_I2SRX_BCLK_MST),
++	JH71X0_MDIV(JH7110_SYSCLK_I2SRX_LRCK_MST, "i2srx_lrck_mst", 64, 2,
++		    JH7110_SYSCLK_I2SRX_BCLK_MST_INV,
++		    JH7110_SYSCLK_I2SRX_BCLK_MST),
++	JH71X0__MUX(JH7110_SYSCLK_I2SRX_BCLK, "i2srx_bclk", 2,
++		    JH7110_SYSCLK_I2SRX_BCLK_MST,
++		    JH7110_SYSCLK_I2SRX_BCLK_EXT),
++	JH71X0__INV(JH7110_SYSCLK_I2SRX_BCLK_INV, "i2srx_bclk_inv", JH7110_SYSCLK_I2SRX_BCLK),
++	JH71X0__MUX(JH7110_SYSCLK_I2SRX_LRCK, "i2srx_lrck", 2,
++		    JH7110_SYSCLK_I2SRX_LRCK_MST,
++		    JH7110_SYSCLK_I2SRX_LRCK_EXT),
++	/* pdm */
++	JH71X0_GDIV(JH7110_SYSCLK_PDM_DMIC, "pdm_dmic", 0, 64, JH7110_SYSCLK_MCLK),
++	JH71X0_GATE(JH7110_SYSCLK_PDM_APB, "pdm_apb", 0, JH7110_SYSCLK_APB0),
++	/* tdm */
++	JH71X0_GATE(JH7110_SYSCLK_TDM_AHB, "tdm_ahb", 0, JH7110_SYSCLK_AHB0),
++	JH71X0_GATE(JH7110_SYSCLK_TDM_APB, "tdm_apb", 0, JH7110_SYSCLK_APB0),
++	JH71X0_GDIV(JH7110_SYSCLK_TDM_INTERNAL, "tdm_internal", 0, 64, JH7110_SYSCLK_MCLK),
++	JH71X0__MUX(JH7110_SYSCLK_TDM_TDM, "tdm_tdm", 2,
++		    JH7110_SYSCLK_TDM_INTERNAL,
++		    JH7110_SYSCLK_TDM_EXT),
++	JH71X0__INV(JH7110_SYSCLK_TDM_TDM_INV, "tdm_tdm_inv", JH7110_SYSCLK_TDM_TDM),
++	/* jtag */
++	JH71X0__DIV(JH7110_SYSCLK_JTAG_CERTIFICATION_TRNG, "jtag_certification_trng", 4,
++		    JH7110_SYSCLK_OSC),
++};
++
++static struct clk_hw *jh7110_sysclk_get(struct of_phandle_args *clkspec, void *data)
++{
++	struct jh71x0_clk_priv *priv = data;
++	unsigned int idx = clkspec->args[0];
++
++	if (idx < JH7110_SYSCLK_END)
++		return &priv->reg[idx].hw;
++
++	return ERR_PTR(-EINVAL);
++}
++
++static void jh7110_reset_unregister_adev(void *_adev)
++{
++	struct auxiliary_device *adev = _adev;
++
++	auxiliary_device_delete(adev);
++}
++
++static void jh7110_reset_adev_release(struct device *dev)
++{
++	struct auxiliary_device *adev = to_auxiliary_dev(dev);
++
++	auxiliary_device_uninit(adev);
++}
++
++int jh7110_reset_controller_register(struct jh71x0_clk_priv *priv,
++				     const char *adev_name,
++				     u32 adev_id)
++{
++	struct auxiliary_device *adev;
++	int ret;
++
++	adev = devm_kzalloc(priv->dev, sizeof(*adev), GFP_KERNEL);
++	if (!adev)
++		return -ENOMEM;
++
++	adev->name = adev_name;
++	adev->dev.parent = priv->dev;
++	adev->dev.release = jh7110_reset_adev_release;
++	adev->id = adev_id;
++
++	ret = auxiliary_device_init(adev);
++	if (ret)
++		return ret;
++
++	ret = auxiliary_device_add(adev);
++	if (ret) {
++		auxiliary_device_uninit(adev);
++		return ret;
++	}
++
++	return devm_add_action_or_reset(priv->dev,
++					jh7110_reset_unregister_adev, adev);
++}
++EXPORT_SYMBOL_GPL(jh7110_reset_controller_register);
++
++static int __init jh7110_syscrg_probe(struct platform_device *pdev)
++{
++	struct jh71x0_clk_priv *priv;
++	unsigned int idx;
++	int ret;
++
++	priv = devm_kzalloc(&pdev->dev,
++			    struct_size(priv, reg, JH7110_SYSCLK_END),
++			    GFP_KERNEL);
++	if (!priv)
++		return -ENOMEM;
++
++	spin_lock_init(&priv->rmw_lock);
++	priv->dev = &pdev->dev;
++	priv->base = devm_platform_ioremap_resource(pdev, 0);
++	if (IS_ERR(priv->base))
++		return PTR_ERR(priv->base);
++
++	dev_set_drvdata(priv->dev, (void *)(&priv->base));
++
++	/*
++	 * These PLL clocks are not actually fixed factor clocks and can be
++	 * controlled by the syscon registers of JH7110. They will be dropped
++	 * and registered in the PLL clock driver instead.
++	 */
++	/* 24MHz -> 1000.0MHz */
++	priv->pll[0] = devm_clk_hw_register_fixed_factor(priv->dev, "pll0_out",
++							 "osc", 0, 125, 3);
++	if (IS_ERR(priv->pll[0]))
++		return PTR_ERR(priv->pll[0]);
++
++	/* 24MHz -> 1066.0MHz */
++	priv->pll[1] = devm_clk_hw_register_fixed_factor(priv->dev, "pll1_out",
++							 "osc", 0, 533, 12);
++	if (IS_ERR(priv->pll[1]))
++		return PTR_ERR(priv->pll[1]);
++
++	/* 24MHz -> 1188.0MHz */
++	priv->pll[2] = devm_clk_hw_register_fixed_factor(priv->dev, "pll2_out",
++							 "osc", 0, 99, 2);
++	if (IS_ERR(priv->pll[2]))
++		return PTR_ERR(priv->pll[2]);
++
++	for (idx = 0; idx < JH7110_SYSCLK_END; idx++) {
++		u32 max = jh7110_sysclk_data[idx].max;
++		struct clk_parent_data parents[4] = {};
++		struct clk_init_data init = {
++			.name = jh7110_sysclk_data[idx].name,
++			.ops = starfive_jh71x0_clk_ops(max),
++			.parent_data = parents,
++			.num_parents =
++				((max & JH71X0_CLK_MUX_MASK) >> JH71X0_CLK_MUX_SHIFT) + 1,
++			.flags = jh7110_sysclk_data[idx].flags,
++		};
++		struct jh71x0_clk *clk = &priv->reg[idx];
++		unsigned int i;
++
++		for (i = 0; i < init.num_parents; i++) {
++			unsigned int pidx = jh7110_sysclk_data[idx].parents[i];
++
++			if (pidx < JH7110_SYSCLK_END)
++				parents[i].hw = &priv->reg[pidx].hw;
++			else if (pidx == JH7110_SYSCLK_OSC)
++				parents[i].fw_name = "osc";
++			else if (pidx == JH7110_SYSCLK_GMAC1_RMII_REFIN)
++				parents[i].fw_name = "gmac1_rmii_refin";
++			else if (pidx == JH7110_SYSCLK_GMAC1_RGMII_RXIN)
++				parents[i].fw_name = "gmac1_rgmii_rxin";
++			else if (pidx == JH7110_SYSCLK_I2STX_BCLK_EXT)
++				parents[i].fw_name = "i2stx_bclk_ext";
++			else if (pidx == JH7110_SYSCLK_I2STX_LRCK_EXT)
++				parents[i].fw_name = "i2stx_lrck_ext";
++			else if (pidx == JH7110_SYSCLK_I2SRX_BCLK_EXT)
++				parents[i].fw_name = "i2srx_bclk_ext";
++			else if (pidx == JH7110_SYSCLK_I2SRX_LRCK_EXT)
++				parents[i].fw_name = "i2srx_lrck_ext";
++			else if (pidx == JH7110_SYSCLK_TDM_EXT)
++				parents[i].fw_name = "tdm_ext";
++			else if (pidx == JH7110_SYSCLK_MCLK_EXT)
++				parents[i].fw_name = "mclk_ext";
++			else
++				parents[i].hw = priv->pll[pidx - JH7110_SYSCLK_PLL0_OUT];
++		}
++
++		clk->hw.init = &init;
++		clk->idx = idx;
++		clk->max_div = max & JH71X0_CLK_DIV_MASK;
++
++		ret = devm_clk_hw_register(&pdev->dev, &clk->hw);
++		if (ret)
++			return ret;
++	}
++
++	ret = devm_of_clk_add_hw_provider(&pdev->dev, jh7110_sysclk_get, priv);
++	if (ret)
++		return ret;
++
++	return jh7110_reset_controller_register(priv, "rst-sys", 0);
++}
++
++static const struct of_device_id jh7110_syscrg_match[] = {
++	{ .compatible = "starfive,jh7110-syscrg" },
++	{ /* sentinel */ }
++};
++
++static struct platform_driver jh7110_syscrg_driver = {
++	.driver = {
++		.name = "clk-starfive-jh7110-sys",
++		.of_match_table = jh7110_syscrg_match,
++		.suppress_bind_attrs = true,
++	},
++};
++builtin_platform_driver_probe(jh7110_syscrg_driver, jh7110_syscrg_probe);
+--- /dev/null
++++ b/drivers/clk/starfive/clk-starfive-jh7110.h
+@@ -0,0 +1,11 @@
++/* SPDX-License-Identifier: GPL-2.0 */
++#ifndef __CLK_STARFIVE_JH7110_H
++#define __CLK_STARFIVE_JH7110_H
++
++#include "clk-starfive-jh71x0.h"
++
++int jh7110_reset_controller_register(struct jh71x0_clk_priv *priv,
++				     const char *adev_name,
++				     u32 adev_id);
++
++#endif

+ 206 - 0
target/linux/starfive/patches-6.1/0014-clk-starfive-Add-StarFive-JH7110-always-on-clock-dri.patch

@@ -0,0 +1,206 @@
+From 6b9f7a65cd2e9cc4bdc2ee3c3fb46bef4568af0a Mon Sep 17 00:00:00 2001
+From: Emil Renner Berthing <[email protected]>
+Date: Sat, 1 Apr 2023 19:19:26 +0800
+Subject: [PATCH 014/122] clk: starfive: Add StarFive JH7110 always-on clock
+ driver
+
+Add driver for the StarFive JH7110 always-on clock controller
+and register an auxiliary device for always-on reset controller
+which is named as "rst-aon".
+
+Tested-by: Tommaso Merciai <[email protected]>
+Reviewed-by: Emil Renner Berthing <[email protected]>
+Signed-off-by: Emil Renner Berthing <[email protected]>
+Co-developed-by: Hal Feng <[email protected]>
+Signed-off-by: Hal Feng <[email protected]>
+Signed-off-by: Conor Dooley <[email protected]>
+---
+ drivers/clk/starfive/Kconfig                  |  11 ++
+ drivers/clk/starfive/Makefile                 |   1 +
+ .../clk/starfive/clk-starfive-jh7110-aon.c    | 156 ++++++++++++++++++
+ 3 files changed, 168 insertions(+)
+ create mode 100644 drivers/clk/starfive/clk-starfive-jh7110-aon.c
+
+--- a/drivers/clk/starfive/Kconfig
++++ b/drivers/clk/starfive/Kconfig
+@@ -31,3 +31,14 @@ config CLK_STARFIVE_JH7110_SYS
+ 	help
+ 	  Say yes here to support the system clock controller on the
+ 	  StarFive JH7110 SoC.
++
++config CLK_STARFIVE_JH7110_AON
++	tristate "StarFive JH7110 always-on clock support"
++	depends on CLK_STARFIVE_JH7110_SYS
++	select AUXILIARY_BUS
++	select CLK_STARFIVE_JH71X0
++	select RESET_STARFIVE_JH7110
++	default m if ARCH_STARFIVE
++	help
++	  Say yes here to support the always-on clock controller on the
++	  StarFive JH7110 SoC.
+--- a/drivers/clk/starfive/Makefile
++++ b/drivers/clk/starfive/Makefile
+@@ -5,3 +5,4 @@ obj-$(CONFIG_CLK_STARFIVE_JH7100)	+= clk
+ obj-$(CONFIG_CLK_STARFIVE_JH7100_AUDIO)	+= clk-starfive-jh7100-audio.o
+ 
+ obj-$(CONFIG_CLK_STARFIVE_JH7110_SYS)	+= clk-starfive-jh7110-sys.o
++obj-$(CONFIG_CLK_STARFIVE_JH7110_AON)	+= clk-starfive-jh7110-aon.o
+--- /dev/null
++++ b/drivers/clk/starfive/clk-starfive-jh7110-aon.c
+@@ -0,0 +1,156 @@
++// SPDX-License-Identifier: GPL-2.0
++/*
++ * StarFive JH7110 Always-On Clock Driver
++ *
++ * Copyright (C) 2022 Emil Renner Berthing <[email protected]>
++ * Copyright (C) 2022 StarFive Technology Co., Ltd.
++ */
++
++#include <linux/clk-provider.h>
++#include <linux/io.h>
++#include <linux/platform_device.h>
++
++#include <dt-bindings/clock/starfive,jh7110-crg.h>
++
++#include "clk-starfive-jh7110.h"
++
++/* external clocks */
++#define JH7110_AONCLK_OSC		(JH7110_AONCLK_END + 0)
++#define JH7110_AONCLK_GMAC0_RMII_REFIN	(JH7110_AONCLK_END + 1)
++#define JH7110_AONCLK_GMAC0_RGMII_RXIN	(JH7110_AONCLK_END + 2)
++#define JH7110_AONCLK_STG_AXIAHB	(JH7110_AONCLK_END + 3)
++#define JH7110_AONCLK_APB_BUS		(JH7110_AONCLK_END + 4)
++#define JH7110_AONCLK_GMAC0_GTXCLK	(JH7110_AONCLK_END + 5)
++#define JH7110_AONCLK_RTC_OSC		(JH7110_AONCLK_END + 6)
++
++static const struct jh71x0_clk_data jh7110_aonclk_data[] = {
++	/* source */
++	JH71X0__DIV(JH7110_AONCLK_OSC_DIV4, "osc_div4", 4, JH7110_AONCLK_OSC),
++	JH71X0__MUX(JH7110_AONCLK_APB_FUNC, "apb_func", 2,
++		    JH7110_AONCLK_OSC_DIV4,
++		    JH7110_AONCLK_OSC),
++	/* gmac0 */
++	JH71X0_GATE(JH7110_AONCLK_GMAC0_AHB, "gmac0_ahb", 0, JH7110_AONCLK_STG_AXIAHB),
++	JH71X0_GATE(JH7110_AONCLK_GMAC0_AXI, "gmac0_axi", 0, JH7110_AONCLK_STG_AXIAHB),
++	JH71X0__DIV(JH7110_AONCLK_GMAC0_RMII_RTX, "gmac0_rmii_rtx", 30,
++		    JH7110_AONCLK_GMAC0_RMII_REFIN),
++	JH71X0_GMUX(JH7110_AONCLK_GMAC0_TX, "gmac0_tx",
++		    CLK_SET_RATE_PARENT | CLK_SET_RATE_NO_REPARENT, 2,
++		    JH7110_AONCLK_GMAC0_GTXCLK,
++		    JH7110_AONCLK_GMAC0_RMII_RTX),
++	JH71X0__INV(JH7110_AONCLK_GMAC0_TX_INV, "gmac0_tx_inv", JH7110_AONCLK_GMAC0_TX),
++	JH71X0__MUX(JH7110_AONCLK_GMAC0_RX, "gmac0_rx", 2,
++		    JH7110_AONCLK_GMAC0_RGMII_RXIN,
++		    JH7110_AONCLK_GMAC0_RMII_RTX),
++	JH71X0__INV(JH7110_AONCLK_GMAC0_RX_INV, "gmac0_rx_inv", JH7110_AONCLK_GMAC0_RX),
++	/* otpc */
++	JH71X0_GATE(JH7110_AONCLK_OTPC_APB, "otpc_apb", 0, JH7110_AONCLK_APB_BUS),
++	/* rtc */
++	JH71X0_GATE(JH7110_AONCLK_RTC_APB, "rtc_apb", 0, JH7110_AONCLK_APB_BUS),
++	JH71X0__DIV(JH7110_AONCLK_RTC_INTERNAL, "rtc_internal", 1022, JH7110_AONCLK_OSC),
++	JH71X0__MUX(JH7110_AONCLK_RTC_32K, "rtc_32k", 2,
++		    JH7110_AONCLK_RTC_OSC,
++		    JH7110_AONCLK_RTC_INTERNAL),
++	JH71X0_GATE(JH7110_AONCLK_RTC_CAL, "rtc_cal", 0, JH7110_AONCLK_OSC),
++};
++
++static struct clk_hw *jh7110_aonclk_get(struct of_phandle_args *clkspec, void *data)
++{
++	struct jh71x0_clk_priv *priv = data;
++	unsigned int idx = clkspec->args[0];
++
++	if (idx < JH7110_AONCLK_END)
++		return &priv->reg[idx].hw;
++
++	return ERR_PTR(-EINVAL);
++}
++
++static int jh7110_aoncrg_probe(struct platform_device *pdev)
++{
++	struct jh71x0_clk_priv *priv;
++	unsigned int idx;
++	int ret;
++
++	priv = devm_kzalloc(&pdev->dev,
++			    struct_size(priv, reg, JH7110_AONCLK_END),
++			    GFP_KERNEL);
++	if (!priv)
++		return -ENOMEM;
++
++	spin_lock_init(&priv->rmw_lock);
++	priv->dev = &pdev->dev;
++	priv->base = devm_platform_ioremap_resource(pdev, 0);
++	if (IS_ERR(priv->base))
++		return PTR_ERR(priv->base);
++
++	dev_set_drvdata(priv->dev, (void *)(&priv->base));
++
++	for (idx = 0; idx < JH7110_AONCLK_END; idx++) {
++		u32 max = jh7110_aonclk_data[idx].max;
++		struct clk_parent_data parents[4] = {};
++		struct clk_init_data init = {
++			.name = jh7110_aonclk_data[idx].name,
++			.ops = starfive_jh71x0_clk_ops(max),
++			.parent_data = parents,
++			.num_parents =
++				((max & JH71X0_CLK_MUX_MASK) >> JH71X0_CLK_MUX_SHIFT) + 1,
++			.flags = jh7110_aonclk_data[idx].flags,
++		};
++		struct jh71x0_clk *clk = &priv->reg[idx];
++		unsigned int i;
++
++		for (i = 0; i < init.num_parents; i++) {
++			unsigned int pidx = jh7110_aonclk_data[idx].parents[i];
++
++			if (pidx < JH7110_AONCLK_END)
++				parents[i].hw = &priv->reg[pidx].hw;
++			else if (pidx == JH7110_AONCLK_OSC)
++				parents[i].fw_name = "osc";
++			else if (pidx == JH7110_AONCLK_GMAC0_RMII_REFIN)
++				parents[i].fw_name = "gmac0_rmii_refin";
++			else if (pidx == JH7110_AONCLK_GMAC0_RGMII_RXIN)
++				parents[i].fw_name = "gmac0_rgmii_rxin";
++			else if (pidx == JH7110_AONCLK_STG_AXIAHB)
++				parents[i].fw_name = "stg_axiahb";
++			else if (pidx == JH7110_AONCLK_APB_BUS)
++				parents[i].fw_name = "apb_bus";
++			else if (pidx == JH7110_AONCLK_GMAC0_GTXCLK)
++				parents[i].fw_name = "gmac0_gtxclk";
++			else if (pidx == JH7110_AONCLK_RTC_OSC)
++				parents[i].fw_name = "rtc_osc";
++		}
++
++		clk->hw.init = &init;
++		clk->idx = idx;
++		clk->max_div = max & JH71X0_CLK_DIV_MASK;
++
++		ret = devm_clk_hw_register(&pdev->dev, &clk->hw);
++		if (ret)
++			return ret;
++	}
++
++	ret = devm_of_clk_add_hw_provider(&pdev->dev, jh7110_aonclk_get, priv);
++	if (ret)
++		return ret;
++
++	return jh7110_reset_controller_register(priv, "rst-aon", 1);
++}
++
++static const struct of_device_id jh7110_aoncrg_match[] = {
++	{ .compatible = "starfive,jh7110-aoncrg" },
++	{ /* sentinel */ }
++};
++MODULE_DEVICE_TABLE(of, jh7110_aoncrg_match);
++
++static struct platform_driver jh7110_aoncrg_driver = {
++	.probe = jh7110_aoncrg_probe,
++	.driver = {
++		.name = "clk-starfive-jh7110-aon",
++		.of_match_table = jh7110_aoncrg_match,
++	},
++};
++module_platform_driver(jh7110_aoncrg_driver);
++
++MODULE_AUTHOR("Emil Renner Berthing");
++MODULE_DESCRIPTION("StarFive JH7110 always-on clock driver");
++MODULE_LICENSE("GPL");

+ 113 - 0
target/linux/starfive/patches-6.1/0015-reset-starfive-Add-StarFive-JH7110-reset-driver.patch

@@ -0,0 +1,113 @@
+From ea2f40c943f4a6d39a2f3ea4660266250d37c95a Mon Sep 17 00:00:00 2001
+From: Hal Feng <[email protected]>
+Date: Sat, 1 Apr 2023 19:19:27 +0800
+Subject: [PATCH 015/122] reset: starfive: Add StarFive JH7110 reset driver
+
+Add auxiliary driver to support StarFive JH7110 system
+and always-on resets.
+
+Tested-by: Tommaso Merciai <[email protected]>
+Reviewed-by: Emil Renner Berthing <[email protected]>
+Signed-off-by: Hal Feng <[email protected]>
+Signed-off-by: Conor Dooley <[email protected]>
+---
+ drivers/reset/starfive/Kconfig                |  8 +++
+ drivers/reset/starfive/Makefile               |  1 +
+ .../reset/starfive/reset-starfive-jh7110.c    | 70 +++++++++++++++++++
+ 3 files changed, 79 insertions(+)
+ create mode 100644 drivers/reset/starfive/reset-starfive-jh7110.c
+
+--- a/drivers/reset/starfive/Kconfig
++++ b/drivers/reset/starfive/Kconfig
+@@ -10,3 +10,11 @@ config RESET_STARFIVE_JH7100
+ 	default ARCH_STARFIVE
+ 	help
+ 	  This enables the reset controller driver for the StarFive JH7100 SoC.
++
++config RESET_STARFIVE_JH7110
++	bool "StarFive JH7110 Reset Driver"
++	depends on AUXILIARY_BUS && CLK_STARFIVE_JH7110_SYS
++	select RESET_STARFIVE_JH71X0
++	default ARCH_STARFIVE
++	help
++	  This enables the reset controller driver for the StarFive JH7110 SoC.
+--- a/drivers/reset/starfive/Makefile
++++ b/drivers/reset/starfive/Makefile
+@@ -2,3 +2,4 @@
+ obj-$(CONFIG_RESET_STARFIVE_JH71X0)		+= reset-starfive-jh71x0.o
+ 
+ obj-$(CONFIG_RESET_STARFIVE_JH7100)		+= reset-starfive-jh7100.o
++obj-$(CONFIG_RESET_STARFIVE_JH7110)		+= reset-starfive-jh7110.o
+--- /dev/null
++++ b/drivers/reset/starfive/reset-starfive-jh7110.c
+@@ -0,0 +1,70 @@
++// SPDX-License-Identifier: GPL-2.0-or-later
++/*
++ * Reset driver for the StarFive JH7110 SoC
++ *
++ * Copyright (C) 2022 StarFive Technology Co., Ltd.
++ */
++
++#include <linux/auxiliary_bus.h>
++
++#include "reset-starfive-jh71x0.h"
++
++#include <dt-bindings/reset/starfive,jh7110-crg.h>
++
++struct jh7110_reset_info {
++	unsigned int nr_resets;
++	unsigned int assert_offset;
++	unsigned int status_offset;
++};
++
++static const struct jh7110_reset_info jh7110_sys_info = {
++	.nr_resets = JH7110_SYSRST_END,
++	.assert_offset = 0x2F8,
++	.status_offset = 0x308,
++};
++
++static const struct jh7110_reset_info jh7110_aon_info = {
++	.nr_resets = JH7110_AONRST_END,
++	.assert_offset = 0x38,
++	.status_offset = 0x3C,
++};
++
++static int jh7110_reset_probe(struct auxiliary_device *adev,
++			      const struct auxiliary_device_id *id)
++{
++	struct jh7110_reset_info *info = (struct jh7110_reset_info *)(id->driver_data);
++	void __iomem **base = (void __iomem **)dev_get_drvdata(adev->dev.parent);
++
++	if (!info || !base)
++		return -ENODEV;
++
++	return reset_starfive_jh71x0_register(&adev->dev, adev->dev.parent->of_node,
++					      *base + info->assert_offset,
++					      *base + info->status_offset,
++					      NULL,
++					      info->nr_resets,
++					      NULL);
++}
++
++static const struct auxiliary_device_id jh7110_reset_ids[] = {
++	{
++		.name = "clk_starfive_jh7110_sys.rst-sys",
++		.driver_data = (kernel_ulong_t)&jh7110_sys_info,
++	},
++	{
++		.name = "clk_starfive_jh7110_sys.rst-aon",
++		.driver_data = (kernel_ulong_t)&jh7110_aon_info,
++	},
++	{ /* sentinel */ }
++};
++MODULE_DEVICE_TABLE(auxiliary, jh7110_reset_ids);
++
++static struct auxiliary_driver jh7110_reset_driver = {
++	.probe		= jh7110_reset_probe,
++	.id_table	= jh7110_reset_ids,
++};
++module_auxiliary_driver(jh7110_reset_driver);
++
++MODULE_AUTHOR("Hal Feng <[email protected]>");
++MODULE_DESCRIPTION("StarFive JH7110 reset driver");
++MODULE_LICENSE("GPL");

+ 50 - 0
target/linux/starfive/patches-6.1/0016-MAINTAINERS-generalise-StarFive-clk-reset-entries.patch

@@ -0,0 +1,50 @@
+From 17fecb06e9de3ae5bbf7aecc4d91e14517982f5c Mon Sep 17 00:00:00 2001
+From: "shanlong.li" <[email protected]>
+Date: Wed, 17 May 2023 20:41:51 -0700
+Subject: [PATCH 016/122] MAINTAINERS: generalise StarFive clk/reset entries
+
+Update the MAINTAINERS entry for StarFive's clock and reset drivers to
+account for the addition of JH7110 support and Hal's role in that.
+
+Signed-off-by: shanlong.li <[email protected]>
+---
+ MAINTAINERS | 16 +++++++++-------
+ 1 file changed, 9 insertions(+), 7 deletions(-)
+
+--- a/MAINTAINERS
++++ b/MAINTAINERS
+@@ -19650,12 +19650,13 @@ M:	Emil Renner Berthing <[email protected]
+ S:	Maintained
+ F:	arch/riscv/boot/dts/starfive/
+ 
+-STARFIVE JH7100 CLOCK DRIVERS
++STARFIVE JH71X0 CLOCK DRIVERS
+ M:	Emil Renner Berthing <[email protected]>
++M:	Hal Feng <[email protected]>
+ S:	Maintained
+-F:	Documentation/devicetree/bindings/clock/starfive,jh7100-*.yaml
+-F:	drivers/clk/starfive/clk-starfive-jh7100*
+-F:	include/dt-bindings/clock/starfive-jh7100*.h
++F:	Documentation/devicetree/bindings/clock/starfive,jh71*.yaml
++F:	drivers/clk/starfive/clk-starfive-jh71*
++F:	include/dt-bindings/clock/starfive?jh71*.h
+ 
+ STARFIVE JH7100 PINCTRL DRIVER
+ M:	Emil Renner Berthing <[email protected]>
+@@ -19665,12 +19666,13 @@ F:	Documentation/devicetree/bindings/pin
+ F:	drivers/pinctrl/starfive/
+ F:	include/dt-bindings/pinctrl/pinctrl-starfive-jh7100.h
+ 
+-STARFIVE JH7100 RESET CONTROLLER DRIVER
++STARFIVE JH71X0 RESET CONTROLLER DRIVERS
+ M:	Emil Renner Berthing <[email protected]>
++M:	Hal Feng <[email protected]>
+ S:	Maintained
+ F:	Documentation/devicetree/bindings/reset/starfive,jh7100-reset.yaml
+-F:	drivers/reset/reset-starfive-jh7100.c
+-F:	include/dt-bindings/reset/starfive-jh7100.h
++F:	drivers/reset/starfive/reset-starfive-jh71*
++F:	include/dt-bindings/reset/starfive?jh71*.h
+ 
+ STATIC BRANCH/CALL
+ M:	Peter Zijlstra <[email protected]>

+ 128 - 0
target/linux/starfive/patches-6.1/0017-clk-starfive-Avoid-casting-iomem-pointers.patch

@@ -0,0 +1,128 @@
+From d9d4e0fb44a50cace195e1639cfb23e518e17e88 Mon Sep 17 00:00:00 2001
+From: Stephen Boyd <[email protected]>
+Date: Thu, 13 Apr 2023 13:55:28 -0700
+Subject: [PATCH 017/122] clk: starfive: Avoid casting iomem pointers
+
+Let's use a wrapper struct for the auxiliary_device made in
+jh7110_reset_controller_register() so that we can stop casting iomem
+pointers. The casts trip up tools like sparse, and make for some awkward
+casts that are largely unnecessary. While we're here, change the
+allocation from devm and actually free the auxiliary_device memory in
+the release function. This avoids any use after free problems where the
+parent device driver is unbound from the device but the
+auxiliuary_device is still in use accessing devm freed memory.
+
+Cc: Tommaso Merciai <[email protected]>
+Cc: Emil Renner Berthing <[email protected]>
+Cc: Hal Feng <[email protected]>
+Cc: Conor Dooley <[email protected]>
+Cc: Xingyu Wu <[email protected]>
+Reviewed-by: Conor Dooley <[email protected]>
+Fixes: edab7204afe5 ("clk: starfive: Add StarFive JH7110 system clock driver")
+Signed-off-by: Stephen Boyd <[email protected]>
+Link: https://lore.kernel.org/r/[email protected]
+---
+ drivers/clk/starfive/clk-starfive-jh7110-sys.c | 15 ++++++++++++---
+ drivers/reset/starfive/reset-starfive-jh7110.c |  9 ++++++---
+ include/soc/starfive/reset-starfive-jh71x0.h   | 17 +++++++++++++++++
+ 3 files changed, 35 insertions(+), 6 deletions(-)
+ create mode 100644 include/soc/starfive/reset-starfive-jh71x0.h
+
+--- a/drivers/clk/starfive/clk-starfive-jh7110-sys.c
++++ b/drivers/clk/starfive/clk-starfive-jh7110-sys.c
+@@ -11,6 +11,9 @@
+ #include <linux/init.h>
+ #include <linux/io.h>
+ #include <linux/platform_device.h>
++#include <linux/slab.h>
++
++#include <soc/starfive/reset-starfive-jh71x0.h>
+ 
+ #include <dt-bindings/clock/starfive,jh7110-crg.h>
+ 
+@@ -335,26 +338,32 @@ static void jh7110_reset_unregister_adev
+ 	struct auxiliary_device *adev = _adev;
+ 
+ 	auxiliary_device_delete(adev);
++	auxiliary_device_uninit(adev);
+ }
+ 
+ static void jh7110_reset_adev_release(struct device *dev)
+ {
+ 	struct auxiliary_device *adev = to_auxiliary_dev(dev);
++	struct jh71x0_reset_adev *rdev = to_jh71x0_reset_adev(adev);
+ 
+-	auxiliary_device_uninit(adev);
++	kfree(rdev);
+ }
+ 
+ int jh7110_reset_controller_register(struct jh71x0_clk_priv *priv,
+ 				     const char *adev_name,
+ 				     u32 adev_id)
+ {
++	struct jh71x0_reset_adev *rdev;
+ 	struct auxiliary_device *adev;
+ 	int ret;
+ 
+-	adev = devm_kzalloc(priv->dev, sizeof(*adev), GFP_KERNEL);
+-	if (!adev)
++	rdev = kzalloc(sizeof(*rdev), GFP_KERNEL);
++	if (!rdev)
+ 		return -ENOMEM;
+ 
++	rdev->base = priv->base;
++
++	adev = &rdev->adev;
+ 	adev->name = adev_name;
+ 	adev->dev.parent = priv->dev;
+ 	adev->dev.release = jh7110_reset_adev_release;
+--- a/drivers/reset/starfive/reset-starfive-jh7110.c
++++ b/drivers/reset/starfive/reset-starfive-jh7110.c
+@@ -7,6 +7,8 @@
+ 
+ #include <linux/auxiliary_bus.h>
+ 
++#include <soc/starfive/reset-starfive-jh71x0.h>
++
+ #include "reset-starfive-jh71x0.h"
+ 
+ #include <dt-bindings/reset/starfive,jh7110-crg.h>
+@@ -33,14 +35,15 @@ static int jh7110_reset_probe(struct aux
+ 			      const struct auxiliary_device_id *id)
+ {
+ 	struct jh7110_reset_info *info = (struct jh7110_reset_info *)(id->driver_data);
+-	void __iomem **base = (void __iomem **)dev_get_drvdata(adev->dev.parent);
++	struct jh71x0_reset_adev *rdev = to_jh71x0_reset_adev(adev);
++	void __iomem *base = rdev->base;
+ 
+ 	if (!info || !base)
+ 		return -ENODEV;
+ 
+ 	return reset_starfive_jh71x0_register(&adev->dev, adev->dev.parent->of_node,
+-					      *base + info->assert_offset,
+-					      *base + info->status_offset,
++					      base + info->assert_offset,
++					      base + info->status_offset,
+ 					      NULL,
+ 					      info->nr_resets,
+ 					      NULL);
+--- /dev/null
++++ b/include/soc/starfive/reset-starfive-jh71x0.h
+@@ -0,0 +1,17 @@
++/* SPDX-License-Identifier: GPL-2.0 */
++#ifndef __SOC_STARFIVE_RESET_JH71X0_H
++#define __SOC_STARFIVE_RESET_JH71X0_H
++
++#include <linux/auxiliary_bus.h>
++#include <linux/compiler_types.h>
++#include <linux/container_of.h>
++
++struct jh71x0_reset_adev {
++	void __iomem *base;
++	struct auxiliary_device adev;
++};
++
++#define to_jh71x0_reset_adev(_adev) \
++	container_of((_adev), struct jh71x0_reset_adev, adev)
++
++#endif

+ 27 - 0
target/linux/starfive/patches-6.1/0018-dt-bindings-timer-Add-StarFive-JH7110-clint.patch

@@ -0,0 +1,27 @@
+From f043ba93a8f22fda312574eb98217be15468b7ef Mon Sep 17 00:00:00 2001
+From: Emil Renner Berthing <[email protected]>
+Date: Sat, 1 Apr 2023 19:19:28 +0800
+Subject: [PATCH 018/122] dt-bindings: timer: Add StarFive JH7110 clint
+
+Add compatible string for the StarFive JH7110 clint.
+
+Reviewed-by: Conor Dooley <[email protected]>
+Acked-by: Krzysztof Kozlowski <[email protected]>
+Reviewed-by: Emil Renner Berthing <[email protected]>
+Signed-off-by: Emil Renner Berthing <[email protected]>
+Signed-off-by: Hal Feng <[email protected]>
+Signed-off-by: Conor Dooley <[email protected]>
+---
+ Documentation/devicetree/bindings/timer/sifive,clint.yaml | 1 +
+ 1 file changed, 1 insertion(+)
+
+--- a/Documentation/devicetree/bindings/timer/sifive,clint.yaml
++++ b/Documentation/devicetree/bindings/timer/sifive,clint.yaml
+@@ -27,6 +27,7 @@ properties:
+           - enum:
+               - sifive,fu540-c000-clint
+               - starfive,jh7100-clint
++              - starfive,jh7110-clint
+               - canaan,k210-clint
+           - const: sifive,clint0
+       - items:

+ 28 - 0
target/linux/starfive/patches-6.1/0019-dt-bindings-interrupt-controller-Add-StarFive-JH7110.patch

@@ -0,0 +1,28 @@
+From dba83b8b65b4ef47e8986739b6734894f3979c52 Mon Sep 17 00:00:00 2001
+From: Emil Renner Berthing <[email protected]>
+Date: Sat, 1 Apr 2023 19:19:29 +0800
+Subject: [PATCH 019/122] dt-bindings: interrupt-controller: Add StarFive
+ JH7110 plic
+
+Add compatible string for StarFive JH7110 plic.
+
+Reviewed-by: Conor Dooley <[email protected]>
+Acked-by: Krzysztof Kozlowski <[email protected]>
+Reviewed-by: Emil Renner Berthing <[email protected]>
+Signed-off-by: Emil Renner Berthing <[email protected]>
+Signed-off-by: Hal Feng <[email protected]>
+Signed-off-by: Conor Dooley <[email protected]>
+---
+ .../bindings/interrupt-controller/sifive,plic-1.0.0.yaml         | 1 +
+ 1 file changed, 1 insertion(+)
+
+--- a/Documentation/devicetree/bindings/interrupt-controller/sifive,plic-1.0.0.yaml
++++ b/Documentation/devicetree/bindings/interrupt-controller/sifive,plic-1.0.0.yaml
+@@ -60,6 +60,7 @@ properties:
+           - enum:
+               - sifive,fu540-c000-plic
+               - starfive,jh7100-plic
++              - starfive,jh7110-plic
+               - canaan,k210-plic
+           - const: sifive,plic-1.0.0
+       - items:

+ 27 - 0
target/linux/starfive/patches-6.1/0020-dt-bindings-riscv-Add-SiFive-S7-compatible.patch

@@ -0,0 +1,27 @@
+From fccbb0c52438762999ea16c85d4ebf4cc7e2deff Mon Sep 17 00:00:00 2001
+From: Hal Feng <[email protected]>
+Date: Sat, 1 Apr 2023 19:19:30 +0800
+Subject: [PATCH 020/122] dt-bindings: riscv: Add SiFive S7 compatible
+
+Add a new compatible string in cpu.yaml for SiFive S7 CPU
+core which is used on SiFive U74-MC core complex etc.
+
+Reviewed-by: Conor Dooley <[email protected]>
+Acked-by: Krzysztof Kozlowski <[email protected]>
+Reviewed-by: Emil Renner Berthing <[email protected]>
+Signed-off-by: Hal Feng <[email protected]>
+Signed-off-by: Conor Dooley <[email protected]>
+---
+ Documentation/devicetree/bindings/riscv/cpus.yaml | 1 +
+ 1 file changed, 1 insertion(+)
+
+--- a/Documentation/devicetree/bindings/riscv/cpus.yaml
++++ b/Documentation/devicetree/bindings/riscv/cpus.yaml
+@@ -33,6 +33,7 @@ properties:
+               - sifive,e5
+               - sifive,e7
+               - sifive,e71
++              - sifive,s7
+               - sifive,u74-mc
+               - sifive,u54
+               - sifive,u74

+ 549 - 0
target/linux/starfive/patches-6.1/0021-riscv-dts-starfive-Add-initial-StarFive-JH7110-devic.patch

@@ -0,0 +1,549 @@
+From ca57ce82224c21f93ad43754474fb8de1baf5caa Mon Sep 17 00:00:00 2001
+From: Emil Renner Berthing <[email protected]>
+Date: Sat, 1 Apr 2023 19:19:31 +0800
+Subject: [PATCH 021/122] riscv: dts: starfive: Add initial StarFive JH7110
+ device tree
+
+Add initial device tree for the JH7110 RISC-V SoC by StarFive
+Technology Ltd.
+
+Tested-by: Tommaso Merciai <[email protected]>
+Reviewed-by: Conor Dooley <[email protected]>
+Signed-off-by: Emil Renner Berthing <[email protected]>
+Co-developed-by: Jianlong Huang <[email protected]>
+Signed-off-by: Jianlong Huang <[email protected]>
+Co-developed-by: Hal Feng <[email protected]>
+Signed-off-by: Hal Feng <[email protected]>
+[conor: squashed in the removal of the S7's non-existent mmu]
+Reviewed-by: Emil Renner Berthing <[email protected]>
+Signed-off-by: Conor Dooley <[email protected]>
+---
+ arch/riscv/Kconfig.socs                  |   5 +
+ arch/riscv/boot/dts/starfive/jh7110.dtsi | 500 +++++++++++++++++++++++
+ 2 files changed, 505 insertions(+)
+ create mode 100644 arch/riscv/boot/dts/starfive/jh7110.dtsi
+
+--- a/arch/riscv/Kconfig.socs
++++ b/arch/riscv/Kconfig.socs
+@@ -7,6 +7,8 @@ config SOC_MICROCHIP_POLARFIRE
+ 	help
+ 	  This enables support for Microchip PolarFire SoC platforms.
+ 
++config ARCH_SIFIVE
++	def_bool SOC_SIFIVE
+ config SOC_SIFIVE
+ 	bool "SiFive SoCs"
+ 	select SERIAL_SIFIVE if TTY
+@@ -18,6 +20,9 @@ config SOC_SIFIVE
+ 	help
+ 	  This enables support for SiFive SoC platform hardware.
+ 
++config ARCH_STARFIVE
++	def_bool SOC_STARFIVE
++
+ config SOC_STARFIVE
+ 	bool "StarFive SoCs"
+ 	select PINCTRL
+--- /dev/null
++++ b/arch/riscv/boot/dts/starfive/jh7110.dtsi
+@@ -0,0 +1,500 @@
++// SPDX-License-Identifier: GPL-2.0 OR MIT
++/*
++ * Copyright (C) 2022 StarFive Technology Co., Ltd.
++ * Copyright (C) 2022 Emil Renner Berthing <[email protected]>
++ */
++
++/dts-v1/;
++#include <dt-bindings/clock/starfive,jh7110-crg.h>
++#include <dt-bindings/reset/starfive,jh7110-crg.h>
++
++/ {
++	compatible = "starfive,jh7110";
++	#address-cells = <2>;
++	#size-cells = <2>;
++
++	cpus {
++		#address-cells = <1>;
++		#size-cells = <0>;
++
++		S7_0: cpu@0 {
++			compatible = "sifive,s7", "riscv";
++			reg = <0>;
++			device_type = "cpu";
++			i-cache-block-size = <64>;
++			i-cache-sets = <64>;
++			i-cache-size = <16384>;
++			next-level-cache = <&ccache>;
++			riscv,isa = "rv64imac_zba_zbb";
++			status = "disabled";
++
++			cpu0_intc: interrupt-controller {
++				compatible = "riscv,cpu-intc";
++				interrupt-controller;
++				#interrupt-cells = <1>;
++			};
++		};
++
++		U74_1: cpu@1 {
++			compatible = "sifive,u74-mc", "riscv";
++			reg = <1>;
++			d-cache-block-size = <64>;
++			d-cache-sets = <64>;
++			d-cache-size = <32768>;
++			d-tlb-sets = <1>;
++			d-tlb-size = <40>;
++			device_type = "cpu";
++			i-cache-block-size = <64>;
++			i-cache-sets = <64>;
++			i-cache-size = <32768>;
++			i-tlb-sets = <1>;
++			i-tlb-size = <40>;
++			mmu-type = "riscv,sv39";
++			next-level-cache = <&ccache>;
++			riscv,isa = "rv64imafdc_zba_zbb";
++			tlb-split;
++
++			cpu1_intc: interrupt-controller {
++				compatible = "riscv,cpu-intc";
++				interrupt-controller;
++				#interrupt-cells = <1>;
++			};
++		};
++
++		U74_2: cpu@2 {
++			compatible = "sifive,u74-mc", "riscv";
++			reg = <2>;
++			d-cache-block-size = <64>;
++			d-cache-sets = <64>;
++			d-cache-size = <32768>;
++			d-tlb-sets = <1>;
++			d-tlb-size = <40>;
++			device_type = "cpu";
++			i-cache-block-size = <64>;
++			i-cache-sets = <64>;
++			i-cache-size = <32768>;
++			i-tlb-sets = <1>;
++			i-tlb-size = <40>;
++			mmu-type = "riscv,sv39";
++			next-level-cache = <&ccache>;
++			riscv,isa = "rv64imafdc_zba_zbb";
++			tlb-split;
++
++			cpu2_intc: interrupt-controller {
++				compatible = "riscv,cpu-intc";
++				interrupt-controller;
++				#interrupt-cells = <1>;
++			};
++		};
++
++		U74_3: cpu@3 {
++			compatible = "sifive,u74-mc", "riscv";
++			reg = <3>;
++			d-cache-block-size = <64>;
++			d-cache-sets = <64>;
++			d-cache-size = <32768>;
++			d-tlb-sets = <1>;
++			d-tlb-size = <40>;
++			device_type = "cpu";
++			i-cache-block-size = <64>;
++			i-cache-sets = <64>;
++			i-cache-size = <32768>;
++			i-tlb-sets = <1>;
++			i-tlb-size = <40>;
++			mmu-type = "riscv,sv39";
++			next-level-cache = <&ccache>;
++			riscv,isa = "rv64imafdc_zba_zbb";
++			tlb-split;
++
++			cpu3_intc: interrupt-controller {
++				compatible = "riscv,cpu-intc";
++				interrupt-controller;
++				#interrupt-cells = <1>;
++			};
++		};
++
++		U74_4: cpu@4 {
++			compatible = "sifive,u74-mc", "riscv";
++			reg = <4>;
++			d-cache-block-size = <64>;
++			d-cache-sets = <64>;
++			d-cache-size = <32768>;
++			d-tlb-sets = <1>;
++			d-tlb-size = <40>;
++			device_type = "cpu";
++			i-cache-block-size = <64>;
++			i-cache-sets = <64>;
++			i-cache-size = <32768>;
++			i-tlb-sets = <1>;
++			i-tlb-size = <40>;
++			mmu-type = "riscv,sv39";
++			next-level-cache = <&ccache>;
++			riscv,isa = "rv64imafdc_zba_zbb";
++			tlb-split;
++
++			cpu4_intc: interrupt-controller {
++				compatible = "riscv,cpu-intc";
++				interrupt-controller;
++				#interrupt-cells = <1>;
++			};
++		};
++
++		cpu-map {
++			cluster0 {
++				core0 {
++					cpu = <&S7_0>;
++				};
++
++				core1 {
++					cpu = <&U74_1>;
++				};
++
++				core2 {
++					cpu = <&U74_2>;
++				};
++
++				core3 {
++					cpu = <&U74_3>;
++				};
++
++				core4 {
++					cpu = <&U74_4>;
++				};
++			};
++		};
++	};
++
++	gmac0_rgmii_rxin: gmac0-rgmii-rxin-clock {
++		compatible = "fixed-clock";
++		clock-output-names = "gmac0_rgmii_rxin";
++		#clock-cells = <0>;
++	};
++
++	gmac0_rmii_refin: gmac0-rmii-refin-clock {
++		compatible = "fixed-clock";
++		clock-output-names = "gmac0_rmii_refin";
++		#clock-cells = <0>;
++	};
++
++	gmac1_rgmii_rxin: gmac1-rgmii-rxin-clock {
++		compatible = "fixed-clock";
++		clock-output-names = "gmac1_rgmii_rxin";
++		#clock-cells = <0>;
++	};
++
++	gmac1_rmii_refin: gmac1-rmii-refin-clock {
++		compatible = "fixed-clock";
++		clock-output-names = "gmac1_rmii_refin";
++		#clock-cells = <0>;
++	};
++
++	i2srx_bclk_ext: i2srx-bclk-ext-clock {
++		compatible = "fixed-clock";
++		clock-output-names = "i2srx_bclk_ext";
++		#clock-cells = <0>;
++	};
++
++	i2srx_lrck_ext: i2srx-lrck-ext-clock {
++		compatible = "fixed-clock";
++		clock-output-names = "i2srx_lrck_ext";
++		#clock-cells = <0>;
++	};
++
++	i2stx_bclk_ext: i2stx-bclk-ext-clock {
++		compatible = "fixed-clock";
++		clock-output-names = "i2stx_bclk_ext";
++		#clock-cells = <0>;
++	};
++
++	i2stx_lrck_ext: i2stx-lrck-ext-clock {
++		compatible = "fixed-clock";
++		clock-output-names = "i2stx_lrck_ext";
++		#clock-cells = <0>;
++	};
++
++	mclk_ext: mclk-ext-clock {
++		compatible = "fixed-clock";
++		clock-output-names = "mclk_ext";
++		#clock-cells = <0>;
++	};
++
++	osc: oscillator {
++		compatible = "fixed-clock";
++		clock-output-names = "osc";
++		#clock-cells = <0>;
++	};
++
++	rtc_osc: rtc-oscillator {
++		compatible = "fixed-clock";
++		clock-output-names = "rtc_osc";
++		#clock-cells = <0>;
++	};
++
++	tdm_ext: tdm-ext-clock {
++		compatible = "fixed-clock";
++		clock-output-names = "tdm_ext";
++		#clock-cells = <0>;
++	};
++
++	soc {
++		compatible = "simple-bus";
++		interrupt-parent = <&plic>;
++		#address-cells = <2>;
++		#size-cells = <2>;
++		ranges;
++
++		clint: timer@2000000 {
++			compatible = "starfive,jh7110-clint", "sifive,clint0";
++			reg = <0x0 0x2000000 0x0 0x10000>;
++			interrupts-extended = <&cpu0_intc 3>, <&cpu0_intc 7>,
++					      <&cpu1_intc 3>, <&cpu1_intc 7>,
++					      <&cpu2_intc 3>, <&cpu2_intc 7>,
++					      <&cpu3_intc 3>, <&cpu3_intc 7>,
++					      <&cpu4_intc 3>, <&cpu4_intc 7>;
++		};
++
++		ccache: cache-controller@2010000 {
++			compatible = "starfive,jh7110-ccache", "sifive,ccache0", "cache";
++			reg = <0x0 0x2010000 0x0 0x4000>;
++			interrupts = <1>, <3>, <4>, <2>;
++			cache-block-size = <64>;
++			cache-level = <2>;
++			cache-sets = <2048>;
++			cache-size = <2097152>;
++			cache-unified;
++		};
++
++		plic: interrupt-controller@c000000 {
++			compatible = "starfive,jh7110-plic", "sifive,plic-1.0.0";
++			reg = <0x0 0xc000000 0x0 0x4000000>;
++			interrupts-extended = <&cpu0_intc 11>,
++					      <&cpu1_intc 11>, <&cpu1_intc 9>,
++					      <&cpu2_intc 11>, <&cpu2_intc 9>,
++					      <&cpu3_intc 11>, <&cpu3_intc 9>,
++					      <&cpu4_intc 11>, <&cpu4_intc 9>;
++			interrupt-controller;
++			#interrupt-cells = <1>;
++			#address-cells = <0>;
++			riscv,ndev = <136>;
++		};
++
++		uart0: serial@10000000 {
++			compatible = "snps,dw-apb-uart";
++			reg = <0x0 0x10000000 0x0 0x10000>;
++			clocks = <&syscrg JH7110_SYSCLK_UART0_CORE>,
++				 <&syscrg JH7110_SYSCLK_UART0_APB>;
++			clock-names = "baudclk", "apb_pclk";
++			resets = <&syscrg JH7110_SYSRST_UART0_APB>;
++			interrupts = <32>;
++			reg-io-width = <4>;
++			reg-shift = <2>;
++			status = "disabled";
++		};
++
++		uart1: serial@10010000 {
++			compatible = "snps,dw-apb-uart";
++			reg = <0x0 0x10010000 0x0 0x10000>;
++			clocks = <&syscrg JH7110_SYSCLK_UART1_CORE>,
++				 <&syscrg JH7110_SYSCLK_UART1_APB>;
++			clock-names = "baudclk", "apb_pclk";
++			resets = <&syscrg JH7110_SYSRST_UART1_APB>;
++			interrupts = <33>;
++			reg-io-width = <4>;
++			reg-shift = <2>;
++			status = "disabled";
++		};
++
++		uart2: serial@10020000 {
++			compatible = "snps,dw-apb-uart";
++			reg = <0x0 0x10020000 0x0 0x10000>;
++			clocks = <&syscrg JH7110_SYSCLK_UART2_CORE>,
++				 <&syscrg JH7110_SYSCLK_UART2_APB>;
++			clock-names = "baudclk", "apb_pclk";
++			resets = <&syscrg JH7110_SYSRST_UART2_APB>;
++			interrupts = <34>;
++			reg-io-width = <4>;
++			reg-shift = <2>;
++			status = "disabled";
++		};
++
++		i2c0: i2c@10030000 {
++			compatible = "snps,designware-i2c";
++			reg = <0x0 0x10030000 0x0 0x10000>;
++			clocks = <&syscrg JH7110_SYSCLK_I2C0_APB>;
++			clock-names = "ref";
++			resets = <&syscrg JH7110_SYSRST_I2C0_APB>;
++			interrupts = <35>;
++			#address-cells = <1>;
++			#size-cells = <0>;
++			status = "disabled";
++		};
++
++		i2c1: i2c@10040000 {
++			compatible = "snps,designware-i2c";
++			reg = <0x0 0x10040000 0x0 0x10000>;
++			clocks = <&syscrg JH7110_SYSCLK_I2C1_APB>;
++			clock-names = "ref";
++			resets = <&syscrg JH7110_SYSRST_I2C1_APB>;
++			interrupts = <36>;
++			#address-cells = <1>;
++			#size-cells = <0>;
++			status = "disabled";
++		};
++
++		i2c2: i2c@10050000 {
++			compatible = "snps,designware-i2c";
++			reg = <0x0 0x10050000 0x0 0x10000>;
++			clocks = <&syscrg JH7110_SYSCLK_I2C2_APB>;
++			clock-names = "ref";
++			resets = <&syscrg JH7110_SYSRST_I2C2_APB>;
++			interrupts = <37>;
++			#address-cells = <1>;
++			#size-cells = <0>;
++			status = "disabled";
++		};
++
++		uart3: serial@12000000 {
++			compatible = "snps,dw-apb-uart";
++			reg = <0x0 0x12000000 0x0 0x10000>;
++			clocks = <&syscrg JH7110_SYSCLK_UART3_CORE>,
++				 <&syscrg JH7110_SYSCLK_UART3_APB>;
++			clock-names = "baudclk", "apb_pclk";
++			resets = <&syscrg JH7110_SYSRST_UART3_APB>;
++			interrupts = <45>;
++			reg-io-width = <4>;
++			reg-shift = <2>;
++			status = "disabled";
++		};
++
++		uart4: serial@12010000 {
++			compatible = "snps,dw-apb-uart";
++			reg = <0x0 0x12010000 0x0 0x10000>;
++			clocks = <&syscrg JH7110_SYSCLK_UART4_CORE>,
++				 <&syscrg JH7110_SYSCLK_UART4_APB>;
++			clock-names = "baudclk", "apb_pclk";
++			resets = <&syscrg JH7110_SYSRST_UART4_APB>;
++			interrupts = <46>;
++			reg-io-width = <4>;
++			reg-shift = <2>;
++			status = "disabled";
++		};
++
++		uart5: serial@12020000 {
++			compatible = "snps,dw-apb-uart";
++			reg = <0x0 0x12020000 0x0 0x10000>;
++			clocks = <&syscrg JH7110_SYSCLK_UART5_CORE>,
++				 <&syscrg JH7110_SYSCLK_UART5_APB>;
++			clock-names = "baudclk", "apb_pclk";
++			resets = <&syscrg JH7110_SYSRST_UART5_APB>;
++			interrupts = <47>;
++			reg-io-width = <4>;
++			reg-shift = <2>;
++			status = "disabled";
++		};
++
++		i2c3: i2c@12030000 {
++			compatible = "snps,designware-i2c";
++			reg = <0x0 0x12030000 0x0 0x10000>;
++			clocks = <&syscrg JH7110_SYSCLK_I2C3_APB>;
++			clock-names = "ref";
++			resets = <&syscrg JH7110_SYSRST_I2C3_APB>;
++			interrupts = <48>;
++			#address-cells = <1>;
++			#size-cells = <0>;
++			status = "disabled";
++		};
++
++		i2c4: i2c@12040000 {
++			compatible = "snps,designware-i2c";
++			reg = <0x0 0x12040000 0x0 0x10000>;
++			clocks = <&syscrg JH7110_SYSCLK_I2C4_APB>;
++			clock-names = "ref";
++			resets = <&syscrg JH7110_SYSRST_I2C4_APB>;
++			interrupts = <49>;
++			#address-cells = <1>;
++			#size-cells = <0>;
++			status = "disabled";
++		};
++
++		i2c5: i2c@12050000 {
++			compatible = "snps,designware-i2c";
++			reg = <0x0 0x12050000 0x0 0x10000>;
++			clocks = <&syscrg JH7110_SYSCLK_I2C5_APB>;
++			clock-names = "ref";
++			resets = <&syscrg JH7110_SYSRST_I2C5_APB>;
++			interrupts = <50>;
++			#address-cells = <1>;
++			#size-cells = <0>;
++			status = "disabled";
++		};
++
++		i2c6: i2c@12060000 {
++			compatible = "snps,designware-i2c";
++			reg = <0x0 0x12060000 0x0 0x10000>;
++			clocks = <&syscrg JH7110_SYSCLK_I2C6_APB>;
++			clock-names = "ref";
++			resets = <&syscrg JH7110_SYSRST_I2C6_APB>;
++			interrupts = <51>;
++			#address-cells = <1>;
++			#size-cells = <0>;
++			status = "disabled";
++		};
++
++		syscrg: clock-controller@13020000 {
++			compatible = "starfive,jh7110-syscrg";
++			reg = <0x0 0x13020000 0x0 0x10000>;
++			clocks = <&osc>, <&gmac1_rmii_refin>,
++				 <&gmac1_rgmii_rxin>,
++				 <&i2stx_bclk_ext>, <&i2stx_lrck_ext>,
++				 <&i2srx_bclk_ext>, <&i2srx_lrck_ext>,
++				 <&tdm_ext>, <&mclk_ext>;
++			clock-names = "osc", "gmac1_rmii_refin",
++				      "gmac1_rgmii_rxin",
++				      "i2stx_bclk_ext", "i2stx_lrck_ext",
++				      "i2srx_bclk_ext", "i2srx_lrck_ext",
++				      "tdm_ext", "mclk_ext";
++			#clock-cells = <1>;
++			#reset-cells = <1>;
++		};
++
++		sysgpio: pinctrl@13040000 {
++			compatible = "starfive,jh7110-sys-pinctrl";
++			reg = <0x0 0x13040000 0x0 0x10000>;
++			clocks = <&syscrg JH7110_SYSCLK_IOMUX_APB>;
++			resets = <&syscrg JH7110_SYSRST_IOMUX_APB>;
++			interrupts = <86>;
++			interrupt-controller;
++			#interrupt-cells = <2>;
++			gpio-controller;
++			#gpio-cells = <2>;
++		};
++
++		aoncrg: clock-controller@17000000 {
++			compatible = "starfive,jh7110-aoncrg";
++			reg = <0x0 0x17000000 0x0 0x10000>;
++			clocks = <&osc>, <&gmac0_rmii_refin>,
++				 <&gmac0_rgmii_rxin>,
++				 <&syscrg JH7110_SYSCLK_STG_AXIAHB>,
++				 <&syscrg JH7110_SYSCLK_APB_BUS>,
++				 <&syscrg JH7110_SYSCLK_GMAC0_GTXCLK>,
++				 <&rtc_osc>;
++			clock-names = "osc", "gmac0_rmii_refin",
++				      "gmac0_rgmii_rxin", "stg_axiahb",
++				      "apb_bus", "gmac0_gtxclk",
++				      "rtc_osc";
++			#clock-cells = <1>;
++			#reset-cells = <1>;
++		};
++
++		aongpio: pinctrl@17020000 {
++			compatible = "starfive,jh7110-aon-pinctrl";
++			reg = <0x0 0x17020000 0x0 0x10000>;
++			resets = <&aoncrg JH7110_AONRST_IOMUX>;
++			interrupts = <85>;
++			interrupt-controller;
++			#interrupt-cells = <2>;
++			gpio-controller;
++			#gpio-cells = <2>;
++		};
++	};
++};

+ 331 - 0
target/linux/starfive/patches-6.1/0022-riscv-dts-starfive-Add-StarFive-JH7110-pin-function-.patch

@@ -0,0 +1,331 @@
+From 878c16d22c0feb52c3af65139734b8bb45e349e1 Mon Sep 17 00:00:00 2001
+From: Jianlong Huang <[email protected]>
+Date: Sat, 1 Apr 2023 19:19:32 +0800
+Subject: [PATCH 022/122] riscv: dts: starfive: Add StarFive JH7110 pin
+ function definitions
+
+Add pin function definitions for StarFive JH7110 SoC.
+
+Tested-by: Tommaso Merciai <[email protected]>
+Co-developed-by: Emil Renner Berthing <[email protected]>
+Signed-off-by: Emil Renner Berthing <[email protected]>
+Signed-off-by: Jianlong Huang <[email protected]>
+Signed-off-by: Hal Feng <[email protected]>
+Reviewed-by: Emil Renner Berthing <[email protected]>
+Signed-off-by: Conor Dooley <[email protected]>
+---
+ arch/riscv/boot/dts/starfive/jh7110-pinfunc.h | 308 ++++++++++++++++++
+ 1 file changed, 308 insertions(+)
+ create mode 100644 arch/riscv/boot/dts/starfive/jh7110-pinfunc.h
+
+--- /dev/null
++++ b/arch/riscv/boot/dts/starfive/jh7110-pinfunc.h
+@@ -0,0 +1,308 @@
++/* SPDX-License-Identifier: GPL-2.0 OR MIT */
++/*
++ * Copyright (C) 2022 Emil Renner Berthing <[email protected]>
++ * Copyright (C) 2022 StarFive Technology Co., Ltd.
++ */
++
++#ifndef __JH7110_PINFUNC_H__
++#define __JH7110_PINFUNC_H__
++
++/*
++ * mux bits:
++ *  | 31 - 24 | 23 - 16 | 15 - 10 |  9 - 8   |  7 - 0  |
++ *  |  din    |  dout   |  doen   | function | gpio nr |
++ *
++ * dout:     output signal
++ * doen:     output enable signal
++ * din:      optional input signal, 0xff = none
++ * function: function selector
++ * gpio nr:  gpio number, 0 - 63
++ */
++#define GPIOMUX(n, dout, doen, din) ( \
++		(((din)  & 0xff) << 24) | \
++		(((dout) & 0xff) << 16) | \
++		(((doen) & 0x3f) << 10) | \
++		((n) & 0x3f))
++
++#define PINMUX(n, func) ((1 << 10) | (((func) & 0x3) << 8) | ((n) & 0xff))
++
++/* sys_iomux dout */
++#define GPOUT_LOW				0
++#define GPOUT_HIGH				1
++#define GPOUT_SYS_WAVE511_UART_TX		2
++#define GPOUT_SYS_CAN0_STBY			3
++#define GPOUT_SYS_CAN0_TST_NEXT_BIT		4
++#define GPOUT_SYS_CAN0_TST_SAMPLE_POINT		5
++#define GPOUT_SYS_CAN0_TXD			6
++#define GPOUT_SYS_USB_DRIVE_VBUS		7
++#define GPOUT_SYS_QSPI_CS1			8
++#define GPOUT_SYS_SPDIF				9
++#define GPOUT_SYS_HDMI_CEC_SDA			10
++#define GPOUT_SYS_HDMI_DDC_SCL			11
++#define GPOUT_SYS_HDMI_DDC_SDA			12
++#define GPOUT_SYS_WATCHDOG			13
++#define GPOUT_SYS_I2C0_CLK			14
++#define GPOUT_SYS_I2C0_DATA			15
++#define GPOUT_SYS_SDIO0_BACK_END_POWER		16
++#define GPOUT_SYS_SDIO0_CARD_POWER_EN		17
++#define GPOUT_SYS_SDIO0_CCMD_OD_PULLUP_EN	18
++#define GPOUT_SYS_SDIO0_RST			19
++#define GPOUT_SYS_UART0_TX			20
++#define GPOUT_SYS_HIFI4_JTAG_TDO		21
++#define GPOUT_SYS_JTAG_TDO			22
++#define GPOUT_SYS_PDM_MCLK			23
++#define GPOUT_SYS_PWM_CHANNEL0			24
++#define GPOUT_SYS_PWM_CHANNEL1			25
++#define GPOUT_SYS_PWM_CHANNEL2			26
++#define GPOUT_SYS_PWM_CHANNEL3			27
++#define GPOUT_SYS_PWMDAC_LEFT			28
++#define GPOUT_SYS_PWMDAC_RIGHT			29
++#define GPOUT_SYS_SPI0_CLK			30
++#define GPOUT_SYS_SPI0_FSS			31
++#define GPOUT_SYS_SPI0_TXD			32
++#define GPOUT_SYS_GMAC_PHYCLK			33
++#define GPOUT_SYS_I2SRX_BCLK			34
++#define GPOUT_SYS_I2SRX_LRCK			35
++#define GPOUT_SYS_I2STX0_BCLK			36
++#define GPOUT_SYS_I2STX0_LRCK			37
++#define GPOUT_SYS_MCLK				38
++#define GPOUT_SYS_TDM_CLK			39
++#define GPOUT_SYS_TDM_SYNC			40
++#define GPOUT_SYS_TDM_TXD			41
++#define GPOUT_SYS_TRACE_DATA0			42
++#define GPOUT_SYS_TRACE_DATA1			43
++#define GPOUT_SYS_TRACE_DATA2			44
++#define GPOUT_SYS_TRACE_DATA3			45
++#define GPOUT_SYS_TRACE_REF			46
++#define GPOUT_SYS_CAN1_STBY			47
++#define GPOUT_SYS_CAN1_TST_NEXT_BIT		48
++#define GPOUT_SYS_CAN1_TST_SAMPLE_POINT		49
++#define GPOUT_SYS_CAN1_TXD			50
++#define GPOUT_SYS_I2C1_CLK			51
++#define GPOUT_SYS_I2C1_DATA			52
++#define GPOUT_SYS_SDIO1_BACK_END_POWER		53
++#define GPOUT_SYS_SDIO1_CARD_POWER_EN		54
++#define GPOUT_SYS_SDIO1_CLK			55
++#define GPOUT_SYS_SDIO1_CMD_OD_PULLUP_EN	56
++#define GPOUT_SYS_SDIO1_CMD			57
++#define GPOUT_SYS_SDIO1_DATA0			58
++#define GPOUT_SYS_SDIO1_DATA1			59
++#define GPOUT_SYS_SDIO1_DATA2			60
++#define GPOUT_SYS_SDIO1_DATA3			61
++#define GPOUT_SYS_SDIO1_DATA4			63
++#define GPOUT_SYS_SDIO1_DATA5			63
++#define GPOUT_SYS_SDIO1_DATA6			64
++#define GPOUT_SYS_SDIO1_DATA7			65
++#define GPOUT_SYS_SDIO1_RST			66
++#define GPOUT_SYS_UART1_RTS			67
++#define GPOUT_SYS_UART1_TX			68
++#define GPOUT_SYS_I2STX1_SDO0			69
++#define GPOUT_SYS_I2STX1_SDO1			70
++#define GPOUT_SYS_I2STX1_SDO2			71
++#define GPOUT_SYS_I2STX1_SDO3			72
++#define GPOUT_SYS_SPI1_CLK			73
++#define GPOUT_SYS_SPI1_FSS			74
++#define GPOUT_SYS_SPI1_TXD			75
++#define GPOUT_SYS_I2C2_CLK			76
++#define GPOUT_SYS_I2C2_DATA			77
++#define GPOUT_SYS_UART2_RTS			78
++#define GPOUT_SYS_UART2_TX			79
++#define GPOUT_SYS_SPI2_CLK			80
++#define GPOUT_SYS_SPI2_FSS			81
++#define GPOUT_SYS_SPI2_TXD			82
++#define GPOUT_SYS_I2C3_CLK			83
++#define GPOUT_SYS_I2C3_DATA			84
++#define GPOUT_SYS_UART3_TX			85
++#define GPOUT_SYS_SPI3_CLK			86
++#define GPOUT_SYS_SPI3_FSS			87
++#define GPOUT_SYS_SPI3_TXD			88
++#define GPOUT_SYS_I2C4_CLK			89
++#define GPOUT_SYS_I2C4_DATA			90
++#define GPOUT_SYS_UART4_RTS			91
++#define GPOUT_SYS_UART4_TX			92
++#define GPOUT_SYS_SPI4_CLK			93
++#define GPOUT_SYS_SPI4_FSS			94
++#define GPOUT_SYS_SPI4_TXD			95
++#define GPOUT_SYS_I2C5_CLK			96
++#define GPOUT_SYS_I2C5_DATA			97
++#define GPOUT_SYS_UART5_RTS			98
++#define GPOUT_SYS_UART5_TX			99
++#define GPOUT_SYS_SPI5_CLK			100
++#define GPOUT_SYS_SPI5_FSS			101
++#define GPOUT_SYS_SPI5_TXD			102
++#define GPOUT_SYS_I2C6_CLK			103
++#define GPOUT_SYS_I2C6_DATA			104
++#define GPOUT_SYS_SPI6_CLK			105
++#define GPOUT_SYS_SPI6_FSS			106
++#define GPOUT_SYS_SPI6_TXD			107
++
++/* aon_iomux dout */
++#define GPOUT_AON_CLK_32K_OUT			2
++#define GPOUT_AON_PTC0_PWM4			3
++#define GPOUT_AON_PTC0_PWM5			4
++#define GPOUT_AON_PTC0_PWM6			5
++#define GPOUT_AON_PTC0_PWM7			6
++#define GPOUT_AON_CLK_GCLK0			7
++#define GPOUT_AON_CLK_GCLK1			8
++#define GPOUT_AON_CLK_GCLK2			9
++
++/* sys_iomux doen */
++#define GPOEN_ENABLE				0
++#define GPOEN_DISABLE				1
++#define GPOEN_SYS_HDMI_CEC_SDA			2
++#define GPOEN_SYS_HDMI_DDC_SCL			3
++#define GPOEN_SYS_HDMI_DDC_SDA			4
++#define GPOEN_SYS_I2C0_CLK			5
++#define GPOEN_SYS_I2C0_DATA			6
++#define GPOEN_SYS_HIFI4_JTAG_TDO		7
++#define GPOEN_SYS_JTAG_TDO			8
++#define GPOEN_SYS_PWM0_CHANNEL0			9
++#define GPOEN_SYS_PWM0_CHANNEL1			10
++#define GPOEN_SYS_PWM0_CHANNEL2			11
++#define GPOEN_SYS_PWM0_CHANNEL3			12
++#define GPOEN_SYS_SPI0_NSSPCTL			13
++#define GPOEN_SYS_SPI0_NSSP			14
++#define GPOEN_SYS_TDM_SYNC			15
++#define GPOEN_SYS_TDM_TXD			16
++#define GPOEN_SYS_I2C1_CLK			17
++#define GPOEN_SYS_I2C1_DATA			18
++#define GPOEN_SYS_SDIO1_CMD			19
++#define GPOEN_SYS_SDIO1_DATA0			20
++#define GPOEN_SYS_SDIO1_DATA1			21
++#define GPOEN_SYS_SDIO1_DATA2			22
++#define GPOEN_SYS_SDIO1_DATA3			23
++#define GPOEN_SYS_SDIO1_DATA4			24
++#define GPOEN_SYS_SDIO1_DATA5			25
++#define GPOEN_SYS_SDIO1_DATA6			26
++#define GPOEN_SYS_SDIO1_DATA7			27
++#define GPOEN_SYS_SPI1_NSSPCTL			28
++#define GPOEN_SYS_SPI1_NSSP			29
++#define GPOEN_SYS_I2C2_CLK			30
++#define GPOEN_SYS_I2C2_DATA			31
++#define GPOEN_SYS_SPI2_NSSPCTL			32
++#define GPOEN_SYS_SPI2_NSSP			33
++#define GPOEN_SYS_I2C3_CLK			34
++#define GPOEN_SYS_I2C3_DATA			35
++#define GPOEN_SYS_SPI3_NSSPCTL			36
++#define GPOEN_SYS_SPI3_NSSP			37
++#define GPOEN_SYS_I2C4_CLK			38
++#define GPOEN_SYS_I2C4_DATA			39
++#define GPOEN_SYS_SPI4_NSSPCTL			40
++#define GPOEN_SYS_SPI4_NSSP			41
++#define GPOEN_SYS_I2C5_CLK			42
++#define GPOEN_SYS_I2C5_DATA			43
++#define GPOEN_SYS_SPI5_NSSPCTL			44
++#define GPOEN_SYS_SPI5_NSSP			45
++#define GPOEN_SYS_I2C6_CLK			46
++#define GPOEN_SYS_I2C6_DATA			47
++#define GPOEN_SYS_SPI6_NSSPCTL			48
++#define GPOEN_SYS_SPI6_NSSP			49
++
++/* aon_iomux doen */
++#define GPOEN_AON_PTC0_OE_N_4			2
++#define GPOEN_AON_PTC0_OE_N_5			3
++#define GPOEN_AON_PTC0_OE_N_6			4
++#define GPOEN_AON_PTC0_OE_N_7			5
++
++/* sys_iomux gin */
++#define GPI_NONE				255
++
++#define GPI_SYS_WAVE511_UART_RX			0
++#define GPI_SYS_CAN0_RXD			1
++#define GPI_SYS_USB_OVERCURRENT			2
++#define GPI_SYS_SPDIF				3
++#define GPI_SYS_JTAG_RST			4
++#define GPI_SYS_HDMI_CEC_SDA			5
++#define GPI_SYS_HDMI_DDC_SCL			6
++#define GPI_SYS_HDMI_DDC_SDA			7
++#define GPI_SYS_HDMI_HPD			8
++#define GPI_SYS_I2C0_CLK			9
++#define GPI_SYS_I2C0_DATA			10
++#define GPI_SYS_SDIO0_CD			11
++#define GPI_SYS_SDIO0_INT			12
++#define GPI_SYS_SDIO0_WP			13
++#define GPI_SYS_UART0_RX			14
++#define GPI_SYS_HIFI4_JTAG_TCK			15
++#define GPI_SYS_HIFI4_JTAG_TDI			16
++#define GPI_SYS_HIFI4_JTAG_TMS			17
++#define GPI_SYS_HIFI4_JTAG_RST			18
++#define GPI_SYS_JTAG_TDI			19
++#define GPI_SYS_JTAG_TMS			20
++#define GPI_SYS_PDM_DMIC0			21
++#define GPI_SYS_PDM_DMIC1			22
++#define GPI_SYS_I2SRX_SDIN0			23
++#define GPI_SYS_I2SRX_SDIN1			24
++#define GPI_SYS_I2SRX_SDIN2			25
++#define GPI_SYS_SPI0_CLK			26
++#define GPI_SYS_SPI0_FSS			27
++#define GPI_SYS_SPI0_RXD			28
++#define GPI_SYS_JTAG_TCK			29
++#define GPI_SYS_MCLK_EXT			30
++#define GPI_SYS_I2SRX_BCLK			31
++#define GPI_SYS_I2SRX_LRCK			32
++#define GPI_SYS_I2STX0_BCLK			33
++#define GPI_SYS_I2STX0_LRCK			34
++#define GPI_SYS_TDM_CLK				35
++#define GPI_SYS_TDM_RXD				36
++#define GPI_SYS_TDM_SYNC			37
++#define GPI_SYS_CAN1_RXD			38
++#define GPI_SYS_I2C1_CLK			39
++#define GPI_SYS_I2C1_DATA			40
++#define GPI_SYS_SDIO1_CD			41
++#define GPI_SYS_SDIO1_INT			42
++#define GPI_SYS_SDIO1_WP			43
++#define GPI_SYS_SDIO1_CMD			44
++#define GPI_SYS_SDIO1_DATA0			45
++#define GPI_SYS_SDIO1_DATA1			46
++#define GPI_SYS_SDIO1_DATA2			47
++#define GPI_SYS_SDIO1_DATA3			48
++#define GPI_SYS_SDIO1_DATA4			49
++#define GPI_SYS_SDIO1_DATA5			50
++#define GPI_SYS_SDIO1_DATA6			51
++#define GPI_SYS_SDIO1_DATA7			52
++#define GPI_SYS_SDIO1_STRB			53
++#define GPI_SYS_UART1_CTS			54
++#define GPI_SYS_UART1_RX			55
++#define GPI_SYS_SPI1_CLK			56
++#define GPI_SYS_SPI1_FSS			57
++#define GPI_SYS_SPI1_RXD			58
++#define GPI_SYS_I2C2_CLK			59
++#define GPI_SYS_I2C2_DATA			60
++#define GPI_SYS_UART2_CTS			61
++#define GPI_SYS_UART2_RX			62
++#define GPI_SYS_SPI2_CLK			63
++#define GPI_SYS_SPI2_FSS			64
++#define GPI_SYS_SPI2_RXD			65
++#define GPI_SYS_I2C3_CLK			66
++#define GPI_SYS_I2C3_DATA			67
++#define GPI_SYS_UART3_RX			68
++#define GPI_SYS_SPI3_CLK			69
++#define GPI_SYS_SPI3_FSS			70
++#define GPI_SYS_SPI3_RXD			71
++#define GPI_SYS_I2C4_CLK			72
++#define GPI_SYS_I2C4_DATA			73
++#define GPI_SYS_UART4_CTS			74
++#define GPI_SYS_UART4_RX			75
++#define GPI_SYS_SPI4_CLK			76
++#define GPI_SYS_SPI4_FSS			77
++#define GPI_SYS_SPI4_RXD			78
++#define GPI_SYS_I2C5_CLK			79
++#define GPI_SYS_I2C5_DATA			80
++#define GPI_SYS_UART5_CTS			81
++#define GPI_SYS_UART5_RX			82
++#define GPI_SYS_SPI5_CLK			83
++#define GPI_SYS_SPI5_FSS			84
++#define GPI_SYS_SPI5_RXD			85
++#define GPI_SYS_I2C6_CLK			86
++#define GPI_SYS_I2C6_DATA			87
++#define GPI_SYS_SPI6_CLK			88
++#define GPI_SYS_SPI6_FSS			89
++#define GPI_SYS_SPI6_RXD			90
++
++/* aon_iomux gin */
++#define GPI_AON_PMU_GPIO_WAKEUP_0		0
++#define GPI_AON_PMU_GPIO_WAKEUP_1		1
++#define GPI_AON_PMU_GPIO_WAKEUP_2		2
++#define GPI_AON_PMU_GPIO_WAKEUP_3		3
++
++#endif

+ 290 - 0
target/linux/starfive/patches-6.1/0023-riscv-dts-starfive-Add-StarFive-JH7110-VisionFive-2-.patch

@@ -0,0 +1,290 @@
+From 76bc84c399f11c7d6a37fe68cbd5f182e4c18369 Mon Sep 17 00:00:00 2001
+From: Emil Renner Berthing <[email protected]>
+Date: Sat, 1 Apr 2023 19:19:33 +0800
+Subject: [PATCH 023/122] riscv: dts: starfive: Add StarFive JH7110 VisionFive
+ 2 board device tree
+
+Add a minimal device tree for StarFive JH7110 VisionFive 2 board
+which has version A and version B. Support booting and basic
+clock/reset/pinctrl/uart drivers.
+
+Tested-by: Tommaso Merciai <[email protected]>
+Reviewed-by: Conor Dooley <[email protected]>
+Acked-by: Conor Dooley <[email protected]>
+Signed-off-by: Emil Renner Berthing <[email protected]>
+Co-developed-by: Jianlong Huang <[email protected]>
+Signed-off-by: Jianlong Huang <[email protected]>
+Co-developed-by: Hal Feng <[email protected]>
+Signed-off-by: Hal Feng <[email protected]>
+Reviewed-by: Emil Renner Berthing <[email protected]>
+Signed-off-by: Conor Dooley <[email protected]>
+---
+ arch/riscv/boot/dts/starfive/Makefile         |   6 +-
+ .../jh7110-starfive-visionfive-2-v1.2a.dts    |  13 ++
+ .../jh7110-starfive-visionfive-2-v1.3b.dts    |  13 ++
+ .../jh7110-starfive-visionfive-2.dtsi         | 215 ++++++++++++++++++
+ 4 files changed, 246 insertions(+), 1 deletion(-)
+ create mode 100644 arch/riscv/boot/dts/starfive/jh7110-starfive-visionfive-2-v1.2a.dts
+ create mode 100644 arch/riscv/boot/dts/starfive/jh7110-starfive-visionfive-2-v1.3b.dts
+ create mode 100644 arch/riscv/boot/dts/starfive/jh7110-starfive-visionfive-2.dtsi
+
+--- a/arch/riscv/boot/dts/starfive/Makefile
++++ b/arch/riscv/boot/dts/starfive/Makefile
+@@ -1,2 +1,6 @@
+ # SPDX-License-Identifier: GPL-2.0
+-dtb-$(CONFIG_SOC_STARFIVE) += jh7100-beaglev-starlight.dtb
++dtb-$(CONFIG_ARCH_STARFIVE) += jh7100-beaglev-starlight.dtb
++dtb-$(CONFIG_ARCH_STARFIVE) += jh7100-starfive-visionfive-v1.dtb
++
++dtb-$(CONFIG_ARCH_STARFIVE) += jh7110-starfive-visionfive-2-v1.2a.dtb
++dtb-$(CONFIG_ARCH_STARFIVE) += jh7110-starfive-visionfive-2-v1.3b.dtb
+--- /dev/null
++++ b/arch/riscv/boot/dts/starfive/jh7110-starfive-visionfive-2-v1.2a.dts
+@@ -0,0 +1,13 @@
++// SPDX-License-Identifier: GPL-2.0 OR MIT
++/*
++ * Copyright (C) 2022 StarFive Technology Co., Ltd.
++ * Copyright (C) 2022 Emil Renner Berthing <[email protected]>
++ */
++
++/dts-v1/;
++#include "jh7110-starfive-visionfive-2.dtsi"
++
++/ {
++	model = "StarFive VisionFive 2 v1.2A";
++	compatible = "starfive,visionfive-2-v1.2a", "starfive,jh7110";
++};
+--- /dev/null
++++ b/arch/riscv/boot/dts/starfive/jh7110-starfive-visionfive-2-v1.3b.dts
+@@ -0,0 +1,13 @@
++// SPDX-License-Identifier: GPL-2.0 OR MIT
++/*
++ * Copyright (C) 2022 StarFive Technology Co., Ltd.
++ * Copyright (C) 2022 Emil Renner Berthing <[email protected]>
++ */
++
++/dts-v1/;
++#include "jh7110-starfive-visionfive-2.dtsi"
++
++/ {
++	model = "StarFive VisionFive 2 v1.3B";
++	compatible = "starfive,visionfive-2-v1.3b", "starfive,jh7110";
++};
+--- /dev/null
++++ b/arch/riscv/boot/dts/starfive/jh7110-starfive-visionfive-2.dtsi
+@@ -0,0 +1,215 @@
++// SPDX-License-Identifier: GPL-2.0 OR MIT
++/*
++ * Copyright (C) 2022 StarFive Technology Co., Ltd.
++ * Copyright (C) 2022 Emil Renner Berthing <[email protected]>
++ */
++
++/dts-v1/;
++#include "jh7110.dtsi"
++#include "jh7110-pinfunc.h"
++#include <dt-bindings/gpio/gpio.h>
++
++/ {
++	aliases {
++		i2c0 = &i2c0;
++		i2c2 = &i2c2;
++		i2c5 = &i2c5;
++		i2c6 = &i2c6;
++		serial0 = &uart0;
++	};
++
++	chosen {
++		stdout-path = "serial0:115200n8";
++	};
++
++	cpus {
++		timebase-frequency = <4000000>;
++	};
++
++	memory@40000000 {
++		device_type = "memory";
++		reg = <0x0 0x40000000 0x1 0x0>;
++	};
++
++	gpio-restart {
++		compatible = "gpio-restart";
++		gpios = <&sysgpio 35 GPIO_ACTIVE_HIGH>;
++		priority = <224>;
++	};
++};
++
++&gmac0_rgmii_rxin {
++	clock-frequency = <125000000>;
++};
++
++&gmac0_rmii_refin {
++	clock-frequency = <50000000>;
++};
++
++&gmac1_rgmii_rxin {
++	clock-frequency = <125000000>;
++};
++
++&gmac1_rmii_refin {
++	clock-frequency = <50000000>;
++};
++
++&i2srx_bclk_ext {
++	clock-frequency = <12288000>;
++};
++
++&i2srx_lrck_ext {
++	clock-frequency = <192000>;
++};
++
++&i2stx_bclk_ext {
++	clock-frequency = <12288000>;
++};
++
++&i2stx_lrck_ext {
++	clock-frequency = <192000>;
++};
++
++&mclk_ext {
++	clock-frequency = <12288000>;
++};
++
++&osc {
++	clock-frequency = <24000000>;
++};
++
++&rtc_osc {
++	clock-frequency = <32768>;
++};
++
++&tdm_ext {
++	clock-frequency = <49152000>;
++};
++
++&i2c0 {
++	clock-frequency = <100000>;
++	i2c-sda-hold-time-ns = <300>;
++	i2c-sda-falling-time-ns = <510>;
++	i2c-scl-falling-time-ns = <510>;
++	pinctrl-names = "default";
++	pinctrl-0 = <&i2c0_pins>;
++	status = "okay";
++};
++
++&i2c2 {
++	clock-frequency = <100000>;
++	i2c-sda-hold-time-ns = <300>;
++	i2c-sda-falling-time-ns = <510>;
++	i2c-scl-falling-time-ns = <510>;
++	pinctrl-names = "default";
++	pinctrl-0 = <&i2c2_pins>;
++	status = "okay";
++};
++
++&i2c5 {
++	clock-frequency = <100000>;
++	i2c-sda-hold-time-ns = <300>;
++	i2c-sda-falling-time-ns = <510>;
++	i2c-scl-falling-time-ns = <510>;
++	pinctrl-names = "default";
++	pinctrl-0 = <&i2c5_pins>;
++	status = "okay";
++};
++
++&i2c6 {
++	clock-frequency = <100000>;
++	i2c-sda-hold-time-ns = <300>;
++	i2c-sda-falling-time-ns = <510>;
++	i2c-scl-falling-time-ns = <510>;
++	pinctrl-names = "default";
++	pinctrl-0 = <&i2c6_pins>;
++	status = "okay";
++};
++
++&sysgpio {
++	i2c0_pins: i2c0-0 {
++		i2c-pins {
++			pinmux = <GPIOMUX(57, GPOUT_LOW,
++					      GPOEN_SYS_I2C0_CLK,
++					      GPI_SYS_I2C0_CLK)>,
++				 <GPIOMUX(58, GPOUT_LOW,
++					      GPOEN_SYS_I2C0_DATA,
++					      GPI_SYS_I2C0_DATA)>;
++			bias-disable; /* external pull-up */
++			input-enable;
++			input-schmitt-enable;
++		};
++	};
++
++	i2c2_pins: i2c2-0 {
++		i2c-pins {
++			pinmux = <GPIOMUX(3, GPOUT_LOW,
++					     GPOEN_SYS_I2C2_CLK,
++					     GPI_SYS_I2C2_CLK)>,
++				 <GPIOMUX(2, GPOUT_LOW,
++					     GPOEN_SYS_I2C2_DATA,
++					     GPI_SYS_I2C2_DATA)>;
++			bias-disable; /* external pull-up */
++			input-enable;
++			input-schmitt-enable;
++		};
++	};
++
++	i2c5_pins: i2c5-0 {
++		i2c-pins {
++			pinmux = <GPIOMUX(19, GPOUT_LOW,
++					      GPOEN_SYS_I2C5_CLK,
++					      GPI_SYS_I2C5_CLK)>,
++				 <GPIOMUX(20, GPOUT_LOW,
++					      GPOEN_SYS_I2C5_DATA,
++					      GPI_SYS_I2C5_DATA)>;
++			bias-disable; /* external pull-up */
++			input-enable;
++			input-schmitt-enable;
++		};
++	};
++
++	i2c6_pins: i2c6-0 {
++		i2c-pins {
++			pinmux = <GPIOMUX(16, GPOUT_LOW,
++					      GPOEN_SYS_I2C6_CLK,
++					      GPI_SYS_I2C6_CLK)>,
++				 <GPIOMUX(17, GPOUT_LOW,
++					      GPOEN_SYS_I2C6_DATA,
++					      GPI_SYS_I2C6_DATA)>;
++			bias-disable; /* external pull-up */
++			input-enable;
++			input-schmitt-enable;
++		};
++	};
++
++	uart0_pins: uart0-0 {
++		tx-pins {
++			pinmux = <GPIOMUX(5, GPOUT_SYS_UART0_TX,
++					     GPOEN_ENABLE,
++					     GPI_NONE)>;
++			bias-disable;
++			drive-strength = <12>;
++			input-disable;
++			input-schmitt-disable;
++			slew-rate = <0>;
++		};
++
++		rx-pins {
++			pinmux = <GPIOMUX(6, GPOUT_LOW,
++					     GPOEN_DISABLE,
++					     GPI_SYS_UART0_RX)>;
++			bias-disable; /* external pull-up */
++			drive-strength = <2>;
++			input-enable;
++			input-schmitt-enable;
++			slew-rate = <0>;
++		};
++	};
++};
++
++&uart0 {
++	pinctrl-names = "default";
++	pinctrl-0 = <&uart0_pins>;
++	status = "okay";
++};

+ 43 - 0
target/linux/starfive/patches-6.1/0024-riscv-dts-starfive-Add-StarFive-VisionFive-V1-device.patch

@@ -0,0 +1,43 @@
+From cbb348ddbc68fe4fc8ac80bed11c298149e7893f Mon Sep 17 00:00:00 2001
+From: Cristian Ciocaltea <[email protected]>
+Date: Tue, 18 Oct 2022 00:05:42 +0300
+Subject: [PATCH 024/122] riscv: dts: starfive: Add StarFive VisionFive V1
+ device tree
+
+Add initial device tree for the StarFive VisionFive V1 SBC, which
+is similar with the already supported BeagleV Starlight Beta board,
+both being based on the StarFive JH7100 SoC.
+
+Link: https://github.com/starfive-tech/VisionFive
+Signed-off-by: Cristian Ciocaltea <[email protected]>
+Reviewed-by: Conor Dooley <[email protected]>
+Reviewed-by: Matthias Brugger <[email protected]>
+Signed-off-by: Conor Dooley <[email protected]>
+---
+ .../jh7100-starfive-visionfive-v1.dts         | 20 +++++++++++++++++++
+ 1 file changed, 20 insertions(+)
+ create mode 100644 arch/riscv/boot/dts/starfive/jh7100-starfive-visionfive-v1.dts
+
+--- /dev/null
++++ b/arch/riscv/boot/dts/starfive/jh7100-starfive-visionfive-v1.dts
+@@ -0,0 +1,20 @@
++// SPDX-License-Identifier: GPL-2.0 OR MIT
++/*
++ * Copyright (C) 2021 StarFive Technology Co., Ltd.
++ * Copyright (C) 2021 Emil Renner Berthing <[email protected]>
++ */
++
++/dts-v1/;
++#include "jh7100-common.dtsi"
++#include <dt-bindings/gpio/gpio.h>
++
++/ {
++	model = "StarFive VisionFive V1";
++	compatible = "starfive,visionfive-v1", "starfive,jh7100";
++
++	gpio-restart {
++		compatible = "gpio-restart";
++		gpios = <&gpio 63 GPIO_ACTIVE_HIGH>;
++		priority = <224>;
++	};
++};

+ 349 - 0
target/linux/starfive/patches-6.1/0025-riscv-dts-starfive-Add-common-DT-for-JH7100-based-bo.patch

@@ -0,0 +1,349 @@
+From 2101233d71b74e33de33e4cc292c6a8cf5da9d42 Mon Sep 17 00:00:00 2001
+From: Cristian Ciocaltea <[email protected]>
+Date: Tue, 18 Oct 2022 00:05:41 +0300
+Subject: [PATCH 025/122] riscv: dts: starfive: Add common DT for JH7100 based
+ boards
+
+In preparation for adding initial device tree support for the StarFive
+VisionFive board, which is similar with BeagleV Starlight, move most
+of the content from jh7100-beaglev-starlight.dts to a new file, to be
+shared between the two boards.
+
+Signed-off-by: Cristian Ciocaltea <[email protected]>
+Reviewed-by: Conor Dooley <[email protected]>
+Reviewed-by: Matthias Brugger <[email protected]>
+Signed-off-by: Conor Dooley <[email protected]>
+---
+ .../dts/starfive/jh7100-beaglev-starlight.dts | 153 +----------------
+ .../boot/dts/starfive/jh7100-common.dtsi      | 161 ++++++++++++++++++
+ 2 files changed, 162 insertions(+), 152 deletions(-)
+ create mode 100644 arch/riscv/boot/dts/starfive/jh7100-common.dtsi
+
+--- a/arch/riscv/boot/dts/starfive/jh7100-beaglev-starlight.dts
++++ b/arch/riscv/boot/dts/starfive/jh7100-beaglev-starlight.dts
+@@ -5,160 +5,9 @@
+  */
+ 
+ /dts-v1/;
+-#include "jh7100.dtsi"
+-#include <dt-bindings/gpio/gpio.h>
+-#include <dt-bindings/leds/common.h>
+-#include <dt-bindings/pinctrl/pinctrl-starfive-jh7100.h>
++#include "jh7100-common.dtsi"
+ 
+ / {
+ 	model = "BeagleV Starlight Beta";
+ 	compatible = "beagle,beaglev-starlight-jh7100-r0", "starfive,jh7100";
+-
+-	aliases {
+-		serial0 = &uart3;
+-	};
+-
+-	chosen {
+-		stdout-path = "serial0:115200n8";
+-	};
+-
+-	cpus {
+-		timebase-frequency = <6250000>;
+-	};
+-
+-	memory@80000000 {
+-		device_type = "memory";
+-		reg = <0x0 0x80000000 0x2 0x0>;
+-	};
+-
+-	leds {
+-		compatible = "gpio-leds";
+-
+-		led-ack {
+-			gpios = <&gpio 43 GPIO_ACTIVE_HIGH>;
+-			color = <LED_COLOR_ID_GREEN>;
+-			function = LED_FUNCTION_HEARTBEAT;
+-			linux,default-trigger = "heartbeat";
+-			label = "ack";
+-		};
+-	};
+-};
+-
+-&gpio {
+-	i2c0_pins: i2c0-0 {
+-		i2c-pins {
+-			pinmux = <GPIOMUX(62, GPO_LOW,
+-				  GPO_I2C0_PAD_SCK_OEN,
+-				  GPI_I2C0_PAD_SCK_IN)>,
+-				 <GPIOMUX(61, GPO_LOW,
+-				  GPO_I2C0_PAD_SDA_OEN,
+-				  GPI_I2C0_PAD_SDA_IN)>;
+-			bias-disable; /* external pull-up */
+-			input-enable;
+-			input-schmitt-enable;
+-		};
+-	};
+-
+-	i2c1_pins: i2c1-0 {
+-		i2c-pins {
+-			pinmux = <GPIOMUX(47, GPO_LOW,
+-				  GPO_I2C1_PAD_SCK_OEN,
+-				  GPI_I2C1_PAD_SCK_IN)>,
+-				 <GPIOMUX(48, GPO_LOW,
+-				  GPO_I2C1_PAD_SDA_OEN,
+-				  GPI_I2C1_PAD_SDA_IN)>;
+-			bias-pull-up;
+-			input-enable;
+-			input-schmitt-enable;
+-		};
+-	};
+-
+-	i2c2_pins: i2c2-0 {
+-		i2c-pins {
+-			pinmux = <GPIOMUX(60, GPO_LOW,
+-				  GPO_I2C2_PAD_SCK_OEN,
+-				  GPI_I2C2_PAD_SCK_IN)>,
+-				 <GPIOMUX(59, GPO_LOW,
+-				  GPO_I2C2_PAD_SDA_OEN,
+-				  GPI_I2C2_PAD_SDA_IN)>;
+-			bias-disable; /* external pull-up */
+-			input-enable;
+-			input-schmitt-enable;
+-		};
+-	};
+-
+-	uart3_pins: uart3-0 {
+-		rx-pins {
+-			pinmux = <GPIOMUX(13, GPO_LOW, GPO_DISABLE,
+-				  GPI_UART3_PAD_SIN)>;
+-			bias-pull-up;
+-			drive-strength = <14>;
+-			input-enable;
+-			input-schmitt-enable;
+-			slew-rate = <0>;
+-		};
+-		tx-pins {
+-			pinmux = <GPIOMUX(14, GPO_UART3_PAD_SOUT,
+-				  GPO_ENABLE, GPI_NONE)>;
+-			bias-disable;
+-			drive-strength = <35>;
+-			input-disable;
+-			input-schmitt-disable;
+-			slew-rate = <0>;
+-		};
+-	};
+-};
+-
+-&i2c0 {
+-	clock-frequency = <100000>;
+-	i2c-sda-hold-time-ns = <300>;
+-	i2c-sda-falling-time-ns = <500>;
+-	i2c-scl-falling-time-ns = <500>;
+-	pinctrl-names = "default";
+-	pinctrl-0 = <&i2c0_pins>;
+-	status = "okay";
+-
+-	pmic@5e {
+-		compatible = "ti,tps65086";
+-		reg = <0x5e>;
+-		gpio-controller;
+-		#gpio-cells = <2>;
+-
+-		regulators {
+-		};
+-	};
+-};
+-
+-&i2c1 {
+-	clock-frequency = <400000>;
+-	i2c-sda-hold-time-ns = <300>;
+-	i2c-sda-falling-time-ns = <100>;
+-	i2c-scl-falling-time-ns = <100>;
+-	pinctrl-names = "default";
+-	pinctrl-0 = <&i2c1_pins>;
+-	status = "okay";
+-};
+-
+-&i2c2 {
+-	clock-frequency = <100000>;
+-	i2c-sda-hold-time-ns = <300>;
+-	i2c-sda-falling-time-ns = <500>;
+-	i2c-scl-falling-time-ns = <500>;
+-	pinctrl-names = "default";
+-	pinctrl-0 = <&i2c2_pins>;
+-	status = "okay";
+-};
+-
+-&osc_sys {
+-	clock-frequency = <25000000>;
+-};
+-
+-&osc_aud {
+-	clock-frequency = <27000000>;
+-};
+-
+-&uart3 {
+-	pinctrl-names = "default";
+-	pinctrl-0 = <&uart3_pins>;
+-	status = "okay";
+ };
+--- /dev/null
++++ b/arch/riscv/boot/dts/starfive/jh7100-common.dtsi
+@@ -0,0 +1,161 @@
++// SPDX-License-Identifier: GPL-2.0 OR MIT
++/*
++ * Copyright (C) 2021 StarFive Technology Co., Ltd.
++ * Copyright (C) 2021 Emil Renner Berthing <[email protected]>
++ */
++
++/dts-v1/;
++#include "jh7100.dtsi"
++#include <dt-bindings/gpio/gpio.h>
++#include <dt-bindings/leds/common.h>
++#include <dt-bindings/pinctrl/pinctrl-starfive-jh7100.h>
++
++/ {
++	aliases {
++		serial0 = &uart3;
++	};
++
++	chosen {
++		stdout-path = "serial0:115200n8";
++	};
++
++	cpus {
++		timebase-frequency = <6250000>;
++	};
++
++	memory@80000000 {
++		device_type = "memory";
++		reg = <0x0 0x80000000 0x2 0x0>;
++	};
++
++	leds {
++		compatible = "gpio-leds";
++
++		led-ack {
++			gpios = <&gpio 43 GPIO_ACTIVE_HIGH>;
++			color = <LED_COLOR_ID_GREEN>;
++			function = LED_FUNCTION_HEARTBEAT;
++			linux,default-trigger = "heartbeat";
++			label = "ack";
++		};
++	};
++};
++
++&gpio {
++	i2c0_pins: i2c0-0 {
++		i2c-pins {
++			pinmux = <GPIOMUX(62, GPO_LOW,
++				  GPO_I2C0_PAD_SCK_OEN,
++				  GPI_I2C0_PAD_SCK_IN)>,
++				 <GPIOMUX(61, GPO_LOW,
++				  GPO_I2C0_PAD_SDA_OEN,
++				  GPI_I2C0_PAD_SDA_IN)>;
++			bias-disable; /* external pull-up */
++			input-enable;
++			input-schmitt-enable;
++		};
++	};
++
++	i2c1_pins: i2c1-0 {
++		i2c-pins {
++			pinmux = <GPIOMUX(47, GPO_LOW,
++				  GPO_I2C1_PAD_SCK_OEN,
++				  GPI_I2C1_PAD_SCK_IN)>,
++				 <GPIOMUX(48, GPO_LOW,
++				  GPO_I2C1_PAD_SDA_OEN,
++				  GPI_I2C1_PAD_SDA_IN)>;
++			bias-pull-up;
++			input-enable;
++			input-schmitt-enable;
++		};
++	};
++
++	i2c2_pins: i2c2-0 {
++		i2c-pins {
++			pinmux = <GPIOMUX(60, GPO_LOW,
++				  GPO_I2C2_PAD_SCK_OEN,
++				  GPI_I2C2_PAD_SCK_IN)>,
++				 <GPIOMUX(59, GPO_LOW,
++				  GPO_I2C2_PAD_SDA_OEN,
++				  GPI_I2C2_PAD_SDA_IN)>;
++			bias-disable; /* external pull-up */
++			input-enable;
++			input-schmitt-enable;
++		};
++	};
++
++	uart3_pins: uart3-0 {
++		rx-pins {
++			pinmux = <GPIOMUX(13, GPO_LOW, GPO_DISABLE,
++				  GPI_UART3_PAD_SIN)>;
++			bias-pull-up;
++			drive-strength = <14>;
++			input-enable;
++			input-schmitt-enable;
++			slew-rate = <0>;
++		};
++		tx-pins {
++			pinmux = <GPIOMUX(14, GPO_UART3_PAD_SOUT,
++				  GPO_ENABLE, GPI_NONE)>;
++			bias-disable;
++			drive-strength = <35>;
++			input-disable;
++			input-schmitt-disable;
++			slew-rate = <0>;
++		};
++	};
++};
++
++&i2c0 {
++	clock-frequency = <100000>;
++	i2c-sda-hold-time-ns = <300>;
++	i2c-sda-falling-time-ns = <500>;
++	i2c-scl-falling-time-ns = <500>;
++	pinctrl-names = "default";
++	pinctrl-0 = <&i2c0_pins>;
++	status = "okay";
++
++	pmic@5e {
++		compatible = "ti,tps65086";
++		reg = <0x5e>;
++		gpio-controller;
++		#gpio-cells = <2>;
++
++		regulators {
++		};
++	};
++};
++
++&i2c1 {
++	clock-frequency = <400000>;
++	i2c-sda-hold-time-ns = <300>;
++	i2c-sda-falling-time-ns = <100>;
++	i2c-scl-falling-time-ns = <100>;
++	pinctrl-names = "default";
++	pinctrl-0 = <&i2c1_pins>;
++	status = "okay";
++};
++
++&i2c2 {
++	clock-frequency = <100000>;
++	i2c-sda-hold-time-ns = <300>;
++	i2c-sda-falling-time-ns = <500>;
++	i2c-scl-falling-time-ns = <500>;
++	pinctrl-names = "default";
++	pinctrl-0 = <&i2c2_pins>;
++	status = "okay";
++};
++
++&osc_sys {
++	clock-frequency = <25000000>;
++};
++
++&osc_aud {
++	clock-frequency = <27000000>;
++};
++
++&uart3 {
++	pinctrl-names = "default";
++	pinctrl-0 = <&uart3_pins>;
++	status = "okay";
++};

+ 303 - 0
target/linux/starfive/patches-6.1/0026-dt-bindings-pinctrl-Add-StarFive-JH7110-sys-pinctrl.patch

@@ -0,0 +1,303 @@
+From 28518a9637fee6b84464beff9d4308edc3efba72 Mon Sep 17 00:00:00 2001
+From: Jianlong Huang <[email protected]>
+Date: Thu, 9 Feb 2023 22:36:59 +0800
+Subject: [PATCH 026/122] dt-bindings: pinctrl: Add StarFive JH7110 sys pinctrl
+
+Add pinctrl bindings for StarFive JH7110 SoC sys pinctrl controller.
+
+Reviewed-by: Rob Herring <[email protected]>
+Signed-off-by: Jianlong Huang <[email protected]>
+Co-developed-by: Emil Renner Berthing <[email protected]>
+Signed-off-by: Emil Renner Berthing <[email protected]>
+Signed-off-by: Hal Feng <[email protected]>
+---
+ .../pinctrl/starfive,jh7110-sys-pinctrl.yaml  | 142 ++++++++++++++++++
+ MAINTAINERS                                   |   6 +-
+ .../pinctrl/starfive,jh7110-pinctrl.h         | 115 ++++++++++++++
+ 3 files changed, 261 insertions(+), 2 deletions(-)
+ create mode 100644 Documentation/devicetree/bindings/pinctrl/starfive,jh7110-sys-pinctrl.yaml
+ create mode 100644 include/dt-bindings/pinctrl/starfive,jh7110-pinctrl.h
+
+--- /dev/null
++++ b/Documentation/devicetree/bindings/pinctrl/starfive,jh7110-sys-pinctrl.yaml
+@@ -0,0 +1,142 @@
++# SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause
++%YAML 1.2
++---
++$id: http://devicetree.org/schemas/pinctrl/starfive,jh7110-sys-pinctrl.yaml#
++$schema: http://devicetree.org/meta-schemas/core.yaml#
++
++title: StarFive JH7110 SYS Pin Controller
++
++description: |
++  Bindings for the JH7110 RISC-V SoC from StarFive Technology Ltd.
++
++  Out of the SoC's many pins only the ones named PAD_GPIO0 to PAD_GPIO63
++  can be multiplexed and have configurable bias, drive strength,
++  schmitt trigger etc.
++  Some peripherals have their I/O go through the 64 "GPIOs". This also
++  includes a number of other UARTs, I2Cs, SPIs, PWMs etc.
++  All these peripherals are connected to all 64 GPIOs such that
++  any GPIO can be set up to be controlled by any of the peripherals.
++
++maintainers:
++  - Jianlong Huang <[email protected]>
++
++properties:
++  compatible:
++    const: starfive,jh7110-sys-pinctrl
++
++  reg:
++    maxItems: 1
++
++  clocks:
++    maxItems: 1
++
++  resets:
++    maxItems: 1
++
++  interrupts:
++    maxItems: 1
++
++  interrupt-controller: true
++
++  '#interrupt-cells':
++    const: 2
++
++  gpio-controller: true
++
++  '#gpio-cells':
++    const: 2
++
++patternProperties:
++  '-[0-9]+$':
++    type: object
++    additionalProperties: false
++    patternProperties:
++      '-pins$':
++        type: object
++        description: |
++          A pinctrl node should contain at least one subnode representing the
++          pinctrl groups available on the machine. Each subnode will list the
++          pins it needs, and how they should be configured, with regard to
++          muxer configuration, bias, input enable/disable, input schmitt
++          trigger enable/disable, slew-rate and drive strength.
++        allOf:
++          - $ref: /schemas/pinctrl/pincfg-node.yaml
++          - $ref: /schemas/pinctrl/pinmux-node.yaml
++        additionalProperties: false
++
++        properties:
++          pinmux:
++            description: |
++              The list of GPIOs and their mux settings that properties in the
++              node apply to. This should be set using the GPIOMUX or PINMUX
++              macros.
++
++          bias-disable: true
++
++          bias-pull-up:
++            type: boolean
++
++          bias-pull-down:
++            type: boolean
++
++          drive-strength:
++            enum: [ 2, 4, 8, 12 ]
++
++          input-enable: true
++
++          input-disable: true
++
++          input-schmitt-enable: true
++
++          input-schmitt-disable: true
++
++          slew-rate:
++            maximum: 1
++
++required:
++  - compatible
++  - reg
++  - clocks
++  - interrupts
++  - interrupt-controller
++  - '#interrupt-cells'
++  - gpio-controller
++  - '#gpio-cells'
++
++additionalProperties: false
++
++examples:
++  - |
++    pinctrl@13040000 {
++        compatible = "starfive,jh7110-sys-pinctrl";
++        reg = <0x13040000 0x10000>;
++        clocks = <&syscrg 112>;
++        resets = <&syscrg 2>;
++        interrupts = <86>;
++        interrupt-controller;
++        #interrupt-cells = <2>;
++        gpio-controller;
++        #gpio-cells = <2>;
++
++        uart0-0 {
++            tx-pins {
++                pinmux = <0xff140005>;
++                bias-disable;
++                drive-strength = <12>;
++                input-disable;
++                input-schmitt-disable;
++                slew-rate = <0>;
++            };
++
++            rx-pins {
++                pinmux = <0x0E000406>;
++                bias-pull-up;
++                drive-strength = <2>;
++                input-enable;
++                input-schmitt-enable;
++                slew-rate = <0>;
++            };
++        };
++    };
++
++...
+--- a/MAINTAINERS
++++ b/MAINTAINERS
+@@ -19658,13 +19658,15 @@ F:	Documentation/devicetree/bindings/clo
+ F:	drivers/clk/starfive/clk-starfive-jh71*
+ F:	include/dt-bindings/clock/starfive?jh71*.h
+ 
+-STARFIVE JH7100 PINCTRL DRIVER
++STARFIVE JH71X0 PINCTRL DRIVERS
+ M:	Emil Renner Berthing <[email protected]>
++M:	Jianlong Huang <[email protected]>
+ L:	[email protected]
+ S:	Maintained
+-F:	Documentation/devicetree/bindings/pinctrl/starfive,jh7100-pinctrl.yaml
++F:	Documentation/devicetree/bindings/pinctrl/starfive,jh71*.yaml
+ F:	drivers/pinctrl/starfive/
+ F:	include/dt-bindings/pinctrl/pinctrl-starfive-jh7100.h
++F:	include/dt-bindings/pinctrl/starfive,jh7110-pinctrl.h
+ 
+ STARFIVE JH71X0 RESET CONTROLLER DRIVERS
+ M:	Emil Renner Berthing <[email protected]>
+--- /dev/null
++++ b/include/dt-bindings/pinctrl/starfive,jh7110-pinctrl.h
+@@ -0,0 +1,115 @@
++/* SPDX-License-Identifier: GPL-2.0 OR MIT */
++/*
++ * Copyright (C) 2022 Emil Renner Berthing <[email protected]>
++ * Copyright (C) 2022 StarFive Technology Co., Ltd.
++ */
++
++#ifndef __DT_BINDINGS_PINCTRL_STARFIVE_JH7110_H__
++#define __DT_BINDINGS_PINCTRL_STARFIVE_JH7110_H__
++
++/* sys_iomux pins */
++#define	PAD_GPIO0		0
++#define	PAD_GPIO1		1
++#define	PAD_GPIO2		2
++#define	PAD_GPIO3		3
++#define	PAD_GPIO4		4
++#define	PAD_GPIO5		5
++#define	PAD_GPIO6		6
++#define	PAD_GPIO7		7
++#define	PAD_GPIO8		8
++#define	PAD_GPIO9		9
++#define	PAD_GPIO10		10
++#define	PAD_GPIO11		11
++#define	PAD_GPIO12		12
++#define	PAD_GPIO13		13
++#define	PAD_GPIO14		14
++#define	PAD_GPIO15		15
++#define	PAD_GPIO16		16
++#define	PAD_GPIO17		17
++#define	PAD_GPIO18		18
++#define	PAD_GPIO19		19
++#define	PAD_GPIO20		20
++#define	PAD_GPIO21		21
++#define	PAD_GPIO22		22
++#define	PAD_GPIO23		23
++#define	PAD_GPIO24		24
++#define	PAD_GPIO25		25
++#define	PAD_GPIO26		26
++#define	PAD_GPIO27		27
++#define	PAD_GPIO28		28
++#define	PAD_GPIO29		29
++#define	PAD_GPIO30		30
++#define	PAD_GPIO31		31
++#define	PAD_GPIO32		32
++#define	PAD_GPIO33		33
++#define	PAD_GPIO34		34
++#define	PAD_GPIO35		35
++#define	PAD_GPIO36		36
++#define	PAD_GPIO37		37
++#define	PAD_GPIO38		38
++#define	PAD_GPIO39		39
++#define	PAD_GPIO40		40
++#define	PAD_GPIO41		41
++#define	PAD_GPIO42		42
++#define	PAD_GPIO43		43
++#define	PAD_GPIO44		44
++#define	PAD_GPIO45		45
++#define	PAD_GPIO46		46
++#define	PAD_GPIO47		47
++#define	PAD_GPIO48		48
++#define	PAD_GPIO49		49
++#define	PAD_GPIO50		50
++#define	PAD_GPIO51		51
++#define	PAD_GPIO52		52
++#define	PAD_GPIO53		53
++#define	PAD_GPIO54		54
++#define	PAD_GPIO55		55
++#define	PAD_GPIO56		56
++#define	PAD_GPIO57		57
++#define	PAD_GPIO58		58
++#define	PAD_GPIO59		59
++#define	PAD_GPIO60		60
++#define	PAD_GPIO61		61
++#define	PAD_GPIO62		62
++#define	PAD_GPIO63		63
++#define	PAD_SD0_CLK		64
++#define	PAD_SD0_CMD		65
++#define	PAD_SD0_DATA0		66
++#define	PAD_SD0_DATA1		67
++#define	PAD_SD0_DATA2		68
++#define	PAD_SD0_DATA3		69
++#define	PAD_SD0_DATA4		70
++#define	PAD_SD0_DATA5		71
++#define	PAD_SD0_DATA6		72
++#define	PAD_SD0_DATA7		73
++#define	PAD_SD0_STRB		74
++#define	PAD_GMAC1_MDC		75
++#define	PAD_GMAC1_MDIO		76
++#define	PAD_GMAC1_RXD0		77
++#define	PAD_GMAC1_RXD1		78
++#define	PAD_GMAC1_RXD2		79
++#define	PAD_GMAC1_RXD3		80
++#define	PAD_GMAC1_RXDV		81
++#define	PAD_GMAC1_RXC		82
++#define	PAD_GMAC1_TXD0		83
++#define	PAD_GMAC1_TXD1		84
++#define	PAD_GMAC1_TXD2		85
++#define	PAD_GMAC1_TXD3		86
++#define	PAD_GMAC1_TXEN		87
++#define	PAD_GMAC1_TXC		88
++#define	PAD_QSPI_SCLK		89
++#define	PAD_QSPI_CS0		90
++#define	PAD_QSPI_DATA0		91
++#define	PAD_QSPI_DATA1		92
++#define	PAD_QSPI_DATA2		93
++#define	PAD_QSPI_DATA3		94
++
++#define GPOUT_LOW		0
++#define GPOUT_HIGH		1
++
++#define GPOEN_ENABLE		0
++#define GPOEN_DISABLE		1
++
++#define GPI_NONE		255
++
++#endif

+ 176 - 0
target/linux/starfive/patches-6.1/0027-dt-bindings-pinctrl-Add-StarFive-JH7110-aon-pinctrl.patch

@@ -0,0 +1,176 @@
+From 514cae455122c799638226f4358e8e6f5e155248 Mon Sep 17 00:00:00 2001
+From: Jianlong Huang <[email protected]>
+Date: Thu, 9 Feb 2023 22:37:00 +0800
+Subject: [PATCH 027/122] dt-bindings: pinctrl: Add StarFive JH7110 aon pinctrl
+
+Add pinctrl bindings for StarFive JH7110 SoC aon pinctrl controller.
+
+Reviewed-by: Rob Herring <[email protected]>
+Signed-off-by: Jianlong Huang <[email protected]>
+Co-developed-by: Emil Renner Berthing <[email protected]>
+Signed-off-by: Emil Renner Berthing <[email protected]>
+Signed-off-by: Hal Feng <[email protected]>
+---
+ .../pinctrl/starfive,jh7110-aon-pinctrl.yaml  | 124 ++++++++++++++++++
+ .../pinctrl/starfive,jh7110-pinctrl.h         |  22 ++++
+ 2 files changed, 146 insertions(+)
+ create mode 100644 Documentation/devicetree/bindings/pinctrl/starfive,jh7110-aon-pinctrl.yaml
+
+--- /dev/null
++++ b/Documentation/devicetree/bindings/pinctrl/starfive,jh7110-aon-pinctrl.yaml
+@@ -0,0 +1,124 @@
++# SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause
++%YAML 1.2
++---
++$id: http://devicetree.org/schemas/pinctrl/starfive,jh7110-aon-pinctrl.yaml#
++$schema: http://devicetree.org/meta-schemas/core.yaml#
++
++title: StarFive JH7110 AON Pin Controller
++
++description: |
++  Bindings for the JH7110 RISC-V SoC from StarFive Technology Ltd.
++
++  Out of the SoC's many pins only the ones named PAD_RGPIO0 to PAD_RGPIO3
++  can be multiplexed and have configurable bias, drive strength,
++  schmitt trigger etc.
++  Some peripherals such as PWM have their I/O go through the 4 "GPIOs".
++
++maintainers:
++  - Jianlong Huang <[email protected]>
++
++properties:
++  compatible:
++    const: starfive,jh7110-aon-pinctrl
++
++  reg:
++    maxItems: 1
++
++  resets:
++    maxItems: 1
++
++  interrupts:
++    maxItems: 1
++
++  interrupt-controller: true
++
++  '#interrupt-cells':
++    const: 2
++
++  gpio-controller: true
++
++  '#gpio-cells':
++    const: 2
++
++patternProperties:
++  '-[0-9]+$':
++    type: object
++    additionalProperties: false
++    patternProperties:
++      '-pins$':
++        type: object
++        description: |
++          A pinctrl node should contain at least one subnode representing the
++          pinctrl groups available on the machine. Each subnode will list the
++          pins it needs, and how they should be configured, with regard to
++          muxer configuration, bias, input enable/disable, input schmitt
++          trigger enable/disable, slew-rate and drive strength.
++        allOf:
++          - $ref: /schemas/pinctrl/pincfg-node.yaml
++          - $ref: /schemas/pinctrl/pinmux-node.yaml
++        additionalProperties: false
++
++        properties:
++          pinmux:
++            description: |
++              The list of GPIOs and their mux settings that properties in the
++              node apply to. This should be set using the GPIOMUX macro.
++
++          bias-disable: true
++
++          bias-pull-up:
++            type: boolean
++
++          bias-pull-down:
++            type: boolean
++
++          drive-strength:
++            enum: [ 2, 4, 8, 12 ]
++
++          input-enable: true
++
++          input-disable: true
++
++          input-schmitt-enable: true
++
++          input-schmitt-disable: true
++
++          slew-rate:
++            maximum: 1
++
++required:
++  - compatible
++  - reg
++  - interrupts
++  - interrupt-controller
++  - '#interrupt-cells'
++  - gpio-controller
++  - '#gpio-cells'
++
++additionalProperties: false
++
++examples:
++  - |
++    pinctrl@17020000 {
++        compatible = "starfive,jh7110-aon-pinctrl";
++        reg = <0x17020000 0x10000>;
++        resets = <&aoncrg 2>;
++        interrupts = <85>;
++        interrupt-controller;
++        #interrupt-cells = <2>;
++        gpio-controller;
++        #gpio-cells = <2>;
++
++        pwm-0 {
++            pwm-pins {
++                pinmux = <0xff030802>;
++                bias-disable;
++                drive-strength = <12>;
++                input-disable;
++                input-schmitt-disable;
++                slew-rate = <0>;
++            };
++        };
++    };
++
++...
+--- a/include/dt-bindings/pinctrl/starfive,jh7110-pinctrl.h
++++ b/include/dt-bindings/pinctrl/starfive,jh7110-pinctrl.h
+@@ -104,6 +104,28 @@
+ #define	PAD_QSPI_DATA2		93
+ #define	PAD_QSPI_DATA3		94
+ 
++/* aon_iomux pins */
++#define	PAD_TESTEN		0
++#define	PAD_RGPIO0		1
++#define	PAD_RGPIO1		2
++#define	PAD_RGPIO2		3
++#define	PAD_RGPIO3		4
++#define	PAD_RSTN		5
++#define	PAD_GMAC0_MDC		6
++#define	PAD_GMAC0_MDIO		7
++#define	PAD_GMAC0_RXD0		8
++#define	PAD_GMAC0_RXD1		9
++#define	PAD_GMAC0_RXD2		10
++#define	PAD_GMAC0_RXD3		11
++#define	PAD_GMAC0_RXDV		12
++#define	PAD_GMAC0_RXC		13
++#define	PAD_GMAC0_TXD0		14
++#define	PAD_GMAC0_TXD1		15
++#define	PAD_GMAC0_TXD2		16
++#define	PAD_GMAC0_TXD3		17
++#define	PAD_GMAC0_TXEN		18
++#define	PAD_GMAC0_TXC		19
++
+ #define GPOUT_LOW		0
+ #define GPOUT_HIGH		1
+ 

+ 1581 - 0
target/linux/starfive/patches-6.1/0028-pinctrl-starfive-Add-StarFive-JH7110-sys-controller-.patch

@@ -0,0 +1,1581 @@
+From 4dba3156173e59131d234d702388ee7283bac8a9 Mon Sep 17 00:00:00 2001
+From: Jianlong Huang <[email protected]>
+Date: Thu, 9 Feb 2023 22:37:01 +0800
+Subject: [PATCH 028/122] pinctrl: starfive: Add StarFive JH7110 sys controller
+ driver
+
+Add pinctrl driver for StarFive JH7110 SoC sys pinctrl controller.
+
+Co-developed-by: Emil Renner Berthing <[email protected]>
+Signed-off-by: Emil Renner Berthing <[email protected]>
+Signed-off-by: Jianlong Huang <[email protected]>
+Signed-off-by: Hal Feng <[email protected]>
+---
+ MAINTAINERS                                   |   2 +-
+ drivers/pinctrl/starfive/Kconfig              |  21 +
+ drivers/pinctrl/starfive/Makefile             |   3 +
+ .../starfive/pinctrl-starfive-jh7110-sys.c    | 449 ++++++++
+ .../starfive/pinctrl-starfive-jh7110.c        | 982 ++++++++++++++++++
+ .../starfive/pinctrl-starfive-jh7110.h        |  70 ++
+ 6 files changed, 1526 insertions(+), 1 deletion(-)
+ create mode 100644 drivers/pinctrl/starfive/pinctrl-starfive-jh7110-sys.c
+ create mode 100644 drivers/pinctrl/starfive/pinctrl-starfive-jh7110.c
+ create mode 100644 drivers/pinctrl/starfive/pinctrl-starfive-jh7110.h
+
+--- a/MAINTAINERS
++++ b/MAINTAINERS
+@@ -19664,7 +19664,7 @@ M:	Jianlong Huang <jianlong.huang@starfi
+ L:	[email protected]
+ S:	Maintained
+ F:	Documentation/devicetree/bindings/pinctrl/starfive,jh71*.yaml
+-F:	drivers/pinctrl/starfive/
++F:	drivers/pinctrl/starfive/pinctrl-starfive-jh71*
+ F:	include/dt-bindings/pinctrl/pinctrl-starfive-jh7100.h
+ F:	include/dt-bindings/pinctrl/starfive,jh7110-pinctrl.h
+ 
+--- a/drivers/pinctrl/starfive/Kconfig
++++ b/drivers/pinctrl/starfive/Kconfig
+@@ -16,3 +16,24 @@ config PINCTRL_STARFIVE_JH7100
+ 	  This also provides an interface to the GPIO pins not used by other
+ 	  peripherals supporting inputs, outputs, configuring pull-up/pull-down
+ 	  and interrupts on input changes.
++
++config PINCTRL_STARFIVE_JH7110
++	bool
++	select GENERIC_PINCTRL_GROUPS
++	select GENERIC_PINMUX_FUNCTIONS
++	select GENERIC_PINCONF
++	select GPIOLIB
++	select GPIOLIB_IRQCHIP
++	select OF_GPIO
++
++config PINCTRL_STARFIVE_JH7110_SYS
++	tristate "System pinctrl and GPIO driver for the StarFive JH7110 SoC"
++	depends on SOC_STARFIVE  || COMPILE_TEST
++	depends on OF
++	select PINCTRL_STARFIVE_JH7110
++	default SOC_STARFIVE
++	help
++	  Say yes here to support system pin control on the StarFive JH7110 SoC.
++	  This also provides an interface to the GPIO pins not used by other
++	  peripherals supporting inputs, outputs, configuring pull-up/pull-down
++	  and interrupts on input changes.
+--- a/drivers/pinctrl/starfive/Makefile
++++ b/drivers/pinctrl/starfive/Makefile
+@@ -1,3 +1,6 @@
+ # SPDX-License-Identifier: GPL-2.0
+ 
+ obj-$(CONFIG_PINCTRL_STARFIVE_JH7100)	+= pinctrl-starfive-jh7100.o
++
++obj-$(CONFIG_PINCTRL_STARFIVE_JH7110)		+= pinctrl-starfive-jh7110.o
++obj-$(CONFIG_PINCTRL_STARFIVE_JH7110_SYS)	+= pinctrl-starfive-jh7110-sys.o
+--- /dev/null
++++ b/drivers/pinctrl/starfive/pinctrl-starfive-jh7110-sys.c
+@@ -0,0 +1,449 @@
++// SPDX-License-Identifier: GPL-2.0
++/*
++ * Pinctrl / GPIO driver for StarFive JH7110 SoC sys controller
++ *
++ * Copyright (C) 2022 Emil Renner Berthing <[email protected]>
++ * Copyright (C) 2022 StarFive Technology Co., Ltd.
++ */
++
++#include <linux/bits.h>
++#include <linux/clk.h>
++#include <linux/gpio/driver.h>
++#include <linux/io.h>
++#include <linux/mod_devicetable.h>
++#include <linux/module.h>
++#include <linux/mutex.h>
++#include <linux/of.h>
++#include <linux/of_device.h>
++#include <linux/platform_device.h>
++#include <linux/reset.h>
++#include <linux/spinlock.h>
++
++#include <linux/pinctrl/pinctrl.h>
++#include <linux/pinctrl/pinmux.h>
++
++#include <dt-bindings/pinctrl/starfive,jh7110-pinctrl.h>
++
++#include "../core.h"
++#include "../pinctrl-utils.h"
++#include "../pinmux.h"
++#include "../pinconf.h"
++#include "pinctrl-starfive-jh7110.h"
++
++#define JH7110_SYS_NGPIO		64
++#define JH7110_SYS_GC_BASE		0
++
++/* registers */
++#define JH7110_SYS_DOEN			0x000
++#define JH7110_SYS_DOUT			0x040
++#define JH7110_SYS_GPI			0x080
++#define JH7110_SYS_GPIOIN		0x118
++
++#define JH7110_SYS_GPIOEN		0x0dc
++#define JH7110_SYS_GPIOIS0		0x0e0
++#define JH7110_SYS_GPIOIS1		0x0e4
++#define JH7110_SYS_GPIOIC0		0x0e8
++#define JH7110_SYS_GPIOIC1		0x0ec
++#define JH7110_SYS_GPIOIBE0		0x0f0
++#define JH7110_SYS_GPIOIBE1		0x0f4
++#define JH7110_SYS_GPIOIEV0		0x0f8
++#define JH7110_SYS_GPIOIEV1		0x0fc
++#define JH7110_SYS_GPIOIE0		0x100
++#define JH7110_SYS_GPIOIE1		0x104
++#define JH7110_SYS_GPIORIS0		0x108
++#define JH7110_SYS_GPIORIS1		0x10c
++#define JH7110_SYS_GPIOMIS0		0x110
++#define JH7110_SYS_GPIOMIS1		0x114
++
++#define JH7110_SYS_GPO_PDA_0_74_CFG	0x120
++#define JH7110_SYS_GPO_PDA_89_94_CFG	0x284
++
++static const struct pinctrl_pin_desc jh7110_sys_pins[] = {
++	PINCTRL_PIN(PAD_GPIO0,		"GPIO0"),
++	PINCTRL_PIN(PAD_GPIO1,		"GPIO1"),
++	PINCTRL_PIN(PAD_GPIO2,		"GPIO2"),
++	PINCTRL_PIN(PAD_GPIO3,		"GPIO3"),
++	PINCTRL_PIN(PAD_GPIO4,		"GPIO4"),
++	PINCTRL_PIN(PAD_GPIO5,		"GPIO5"),
++	PINCTRL_PIN(PAD_GPIO6,		"GPIO6"),
++	PINCTRL_PIN(PAD_GPIO7,		"GPIO7"),
++	PINCTRL_PIN(PAD_GPIO8,		"GPIO8"),
++	PINCTRL_PIN(PAD_GPIO9,		"GPIO9"),
++	PINCTRL_PIN(PAD_GPIO10,		"GPIO10"),
++	PINCTRL_PIN(PAD_GPIO11,		"GPIO11"),
++	PINCTRL_PIN(PAD_GPIO12,		"GPIO12"),
++	PINCTRL_PIN(PAD_GPIO13,		"GPIO13"),
++	PINCTRL_PIN(PAD_GPIO14,		"GPIO14"),
++	PINCTRL_PIN(PAD_GPIO15,		"GPIO15"),
++	PINCTRL_PIN(PAD_GPIO16,		"GPIO16"),
++	PINCTRL_PIN(PAD_GPIO17,		"GPIO17"),
++	PINCTRL_PIN(PAD_GPIO18,		"GPIO18"),
++	PINCTRL_PIN(PAD_GPIO19,		"GPIO19"),
++	PINCTRL_PIN(PAD_GPIO20,		"GPIO20"),
++	PINCTRL_PIN(PAD_GPIO21,		"GPIO21"),
++	PINCTRL_PIN(PAD_GPIO22,		"GPIO22"),
++	PINCTRL_PIN(PAD_GPIO23,		"GPIO23"),
++	PINCTRL_PIN(PAD_GPIO24,		"GPIO24"),
++	PINCTRL_PIN(PAD_GPIO25,		"GPIO25"),
++	PINCTRL_PIN(PAD_GPIO26,		"GPIO26"),
++	PINCTRL_PIN(PAD_GPIO27,		"GPIO27"),
++	PINCTRL_PIN(PAD_GPIO28,		"GPIO28"),
++	PINCTRL_PIN(PAD_GPIO29,		"GPIO29"),
++	PINCTRL_PIN(PAD_GPIO30,		"GPIO30"),
++	PINCTRL_PIN(PAD_GPIO31,		"GPIO31"),
++	PINCTRL_PIN(PAD_GPIO32,		"GPIO32"),
++	PINCTRL_PIN(PAD_GPIO33,		"GPIO33"),
++	PINCTRL_PIN(PAD_GPIO34,		"GPIO34"),
++	PINCTRL_PIN(PAD_GPIO35,		"GPIO35"),
++	PINCTRL_PIN(PAD_GPIO36,		"GPIO36"),
++	PINCTRL_PIN(PAD_GPIO37,		"GPIO37"),
++	PINCTRL_PIN(PAD_GPIO38,		"GPIO38"),
++	PINCTRL_PIN(PAD_GPIO39,		"GPIO39"),
++	PINCTRL_PIN(PAD_GPIO40,		"GPIO40"),
++	PINCTRL_PIN(PAD_GPIO41,		"GPIO41"),
++	PINCTRL_PIN(PAD_GPIO42,		"GPIO42"),
++	PINCTRL_PIN(PAD_GPIO43,		"GPIO43"),
++	PINCTRL_PIN(PAD_GPIO44,		"GPIO44"),
++	PINCTRL_PIN(PAD_GPIO45,		"GPIO45"),
++	PINCTRL_PIN(PAD_GPIO46,		"GPIO46"),
++	PINCTRL_PIN(PAD_GPIO47,		"GPIO47"),
++	PINCTRL_PIN(PAD_GPIO48,		"GPIO48"),
++	PINCTRL_PIN(PAD_GPIO49,		"GPIO49"),
++	PINCTRL_PIN(PAD_GPIO50,		"GPIO50"),
++	PINCTRL_PIN(PAD_GPIO51,		"GPIO51"),
++	PINCTRL_PIN(PAD_GPIO52,		"GPIO52"),
++	PINCTRL_PIN(PAD_GPIO53,		"GPIO53"),
++	PINCTRL_PIN(PAD_GPIO54,		"GPIO54"),
++	PINCTRL_PIN(PAD_GPIO55,		"GPIO55"),
++	PINCTRL_PIN(PAD_GPIO56,		"GPIO56"),
++	PINCTRL_PIN(PAD_GPIO57,		"GPIO57"),
++	PINCTRL_PIN(PAD_GPIO58,		"GPIO58"),
++	PINCTRL_PIN(PAD_GPIO59,		"GPIO59"),
++	PINCTRL_PIN(PAD_GPIO60,		"GPIO60"),
++	PINCTRL_PIN(PAD_GPIO61,		"GPIO61"),
++	PINCTRL_PIN(PAD_GPIO62,		"GPIO62"),
++	PINCTRL_PIN(PAD_GPIO63,		"GPIO63"),
++	PINCTRL_PIN(PAD_SD0_CLK,	"SD0_CLK"),
++	PINCTRL_PIN(PAD_SD0_CMD,	"SD0_CMD"),
++	PINCTRL_PIN(PAD_SD0_DATA0,	"SD0_DATA0"),
++	PINCTRL_PIN(PAD_SD0_DATA1,	"SD0_DATA1"),
++	PINCTRL_PIN(PAD_SD0_DATA2,	"SD0_DATA2"),
++	PINCTRL_PIN(PAD_SD0_DATA3,	"SD0_DATA3"),
++	PINCTRL_PIN(PAD_SD0_DATA4,	"SD0_DATA4"),
++	PINCTRL_PIN(PAD_SD0_DATA5,	"SD0_DATA5"),
++	PINCTRL_PIN(PAD_SD0_DATA6,	"SD0_DATA6"),
++	PINCTRL_PIN(PAD_SD0_DATA7,	"SD0_DATA7"),
++	PINCTRL_PIN(PAD_SD0_STRB,	"SD0_STRB"),
++	PINCTRL_PIN(PAD_GMAC1_MDC,	"GMAC1_MDC"),
++	PINCTRL_PIN(PAD_GMAC1_MDIO,	"GMAC1_MDIO"),
++	PINCTRL_PIN(PAD_GMAC1_RXD0,	"GMAC1_RXD0"),
++	PINCTRL_PIN(PAD_GMAC1_RXD1,	"GMAC1_RXD1"),
++	PINCTRL_PIN(PAD_GMAC1_RXD2,	"GMAC1_RXD2"),
++	PINCTRL_PIN(PAD_GMAC1_RXD3,	"GMAC1_RXD3"),
++	PINCTRL_PIN(PAD_GMAC1_RXDV,	"GMAC1_RXDV"),
++	PINCTRL_PIN(PAD_GMAC1_RXC,	"GMAC1_RXC"),
++	PINCTRL_PIN(PAD_GMAC1_TXD0,	"GMAC1_TXD0"),
++	PINCTRL_PIN(PAD_GMAC1_TXD1,	"GMAC1_TXD1"),
++	PINCTRL_PIN(PAD_GMAC1_TXD2,	"GMAC1_TXD2"),
++	PINCTRL_PIN(PAD_GMAC1_TXD3,	"GMAC1_TXD3"),
++	PINCTRL_PIN(PAD_GMAC1_TXEN,	"GMAC1_TXEN"),
++	PINCTRL_PIN(PAD_GMAC1_TXC,	"GMAC1_TXC"),
++	PINCTRL_PIN(PAD_QSPI_SCLK,	"QSPI_SCLK"),
++	PINCTRL_PIN(PAD_QSPI_CS0,	"QSPI_CS0"),
++	PINCTRL_PIN(PAD_QSPI_DATA0,	"QSPI_DATA0"),
++	PINCTRL_PIN(PAD_QSPI_DATA1,	"QSPI_DATA1"),
++	PINCTRL_PIN(PAD_QSPI_DATA2,	"QSPI_DATA2"),
++	PINCTRL_PIN(PAD_QSPI_DATA3,	"QSPI_DATA3"),
++};
++
++struct jh7110_func_sel {
++	u16 offset;
++	u8 shift;
++	u8 max;
++};
++
++static const struct jh7110_func_sel
++	jh7110_sys_func_sel[ARRAY_SIZE(jh7110_sys_pins)] = {
++	[PAD_GMAC1_RXC] = { 0x29c,  0, 1 },
++	[PAD_GPIO10]    = { 0x29c,  2, 3 },
++	[PAD_GPIO11]    = { 0x29c,  5, 3 },
++	[PAD_GPIO12]    = { 0x29c,  8, 3 },
++	[PAD_GPIO13]    = { 0x29c, 11, 3 },
++	[PAD_GPIO14]    = { 0x29c, 14, 3 },
++	[PAD_GPIO15]    = { 0x29c, 17, 3 },
++	[PAD_GPIO16]    = { 0x29c, 20, 3 },
++	[PAD_GPIO17]    = { 0x29c, 23, 3 },
++	[PAD_GPIO18]    = { 0x29c, 26, 3 },
++	[PAD_GPIO19]    = { 0x29c, 29, 3 },
++
++	[PAD_GPIO20]    = { 0x2a0,  0, 3 },
++	[PAD_GPIO21]    = { 0x2a0,  3, 3 },
++	[PAD_GPIO22]    = { 0x2a0,  6, 3 },
++	[PAD_GPIO23]    = { 0x2a0,  9, 3 },
++	[PAD_GPIO24]    = { 0x2a0, 12, 3 },
++	[PAD_GPIO25]    = { 0x2a0, 15, 3 },
++	[PAD_GPIO26]    = { 0x2a0, 18, 3 },
++	[PAD_GPIO27]    = { 0x2a0, 21, 3 },
++	[PAD_GPIO28]    = { 0x2a0, 24, 3 },
++	[PAD_GPIO29]    = { 0x2a0, 27, 3 },
++
++	[PAD_GPIO30]    = { 0x2a4,  0, 3 },
++	[PAD_GPIO31]    = { 0x2a4,  3, 3 },
++	[PAD_GPIO32]    = { 0x2a4,  6, 3 },
++	[PAD_GPIO33]    = { 0x2a4,  9, 3 },
++	[PAD_GPIO34]    = { 0x2a4, 12, 3 },
++	[PAD_GPIO35]    = { 0x2a4, 15, 3 },
++	[PAD_GPIO36]    = { 0x2a4, 17, 3 },
++	[PAD_GPIO37]    = { 0x2a4, 20, 3 },
++	[PAD_GPIO38]    = { 0x2a4, 23, 3 },
++	[PAD_GPIO39]    = { 0x2a4, 26, 3 },
++	[PAD_GPIO40]    = { 0x2a4, 29, 3 },
++
++	[PAD_GPIO41]    = { 0x2a8,  0, 3 },
++	[PAD_GPIO42]    = { 0x2a8,  3, 3 },
++	[PAD_GPIO43]    = { 0x2a8,  6, 3 },
++	[PAD_GPIO44]    = { 0x2a8,  9, 3 },
++	[PAD_GPIO45]    = { 0x2a8, 12, 3 },
++	[PAD_GPIO46]    = { 0x2a8, 15, 3 },
++	[PAD_GPIO47]    = { 0x2a8, 18, 3 },
++	[PAD_GPIO48]    = { 0x2a8, 21, 3 },
++	[PAD_GPIO49]    = { 0x2a8, 24, 3 },
++	[PAD_GPIO50]    = { 0x2a8, 27, 3 },
++	[PAD_GPIO51]    = { 0x2a8, 30, 3 },
++
++	[PAD_GPIO52]    = { 0x2ac,  0, 3 },
++	[PAD_GPIO53]    = { 0x2ac,  2, 3 },
++	[PAD_GPIO54]    = { 0x2ac,  4, 3 },
++	[PAD_GPIO55]    = { 0x2ac,  6, 3 },
++	[PAD_GPIO56]    = { 0x2ac,  9, 3 },
++	[PAD_GPIO57]    = { 0x2ac, 12, 3 },
++	[PAD_GPIO58]    = { 0x2ac, 15, 3 },
++	[PAD_GPIO59]    = { 0x2ac, 18, 3 },
++	[PAD_GPIO60]    = { 0x2ac, 21, 3 },
++	[PAD_GPIO61]    = { 0x2ac, 24, 3 },
++	[PAD_GPIO62]    = { 0x2ac, 27, 3 },
++	[PAD_GPIO63]    = { 0x2ac, 30, 3 },
++
++	[PAD_GPIO6]     = { 0x2b0,  0, 3 },
++	[PAD_GPIO7]     = { 0x2b0,  2, 3 },
++	[PAD_GPIO8]     = { 0x2b0,  5, 3 },
++	[PAD_GPIO9]     = { 0x2b0,  8, 3 },
++};
++
++struct jh7110_vin_group_sel {
++	u16 offset;
++	u8 shift;
++	u8 group;
++};
++
++static const struct jh7110_vin_group_sel
++	jh7110_sys_vin_group_sel[ARRAY_SIZE(jh7110_sys_pins)] = {
++	[PAD_GPIO6]     = { 0x2b4, 21, 0 },
++	[PAD_GPIO7]     = { 0x2b4, 18, 0 },
++	[PAD_GPIO8]     = { 0x2b4, 15, 0 },
++	[PAD_GPIO9]     = { 0x2b0, 11, 0 },
++	[PAD_GPIO10]    = { 0x2b0, 20, 0 },
++	[PAD_GPIO11]    = { 0x2b0, 23, 0 },
++	[PAD_GPIO12]    = { 0x2b0, 26, 0 },
++	[PAD_GPIO13]    = { 0x2b0, 29, 0 },
++	[PAD_GPIO14]    = { 0x2b4,  0, 0 },
++	[PAD_GPIO15]    = { 0x2b4,  3, 0 },
++	[PAD_GPIO16]    = { 0x2b4,  6, 0 },
++	[PAD_GPIO17]    = { 0x2b4,  9, 0 },
++	[PAD_GPIO18]    = { 0x2b4, 12, 0 },
++	[PAD_GPIO19]    = { 0x2b0, 14, 0 },
++	[PAD_GPIO20]    = { 0x2b0, 17, 0 },
++
++	[PAD_GPIO21]    = { 0x2b4, 21, 1 },
++	[PAD_GPIO22]    = { 0x2b4, 18, 1 },
++	[PAD_GPIO23]    = { 0x2b4, 15, 1 },
++	[PAD_GPIO24]    = { 0x2b0, 11, 1 },
++	[PAD_GPIO25]    = { 0x2b0, 20, 1 },
++	[PAD_GPIO26]    = { 0x2b0, 23, 1 },
++	[PAD_GPIO27]    = { 0x2b0, 26, 1 },
++	[PAD_GPIO28]    = { 0x2b0, 29, 1 },
++	[PAD_GPIO29]    = { 0x2b4,  0, 1 },
++	[PAD_GPIO30]    = { 0x2b4,  3, 1 },
++	[PAD_GPIO31]    = { 0x2b4,  6, 1 },
++	[PAD_GPIO32]    = { 0x2b4,  9, 1 },
++	[PAD_GPIO33]    = { 0x2b4, 12, 1 },
++	[PAD_GPIO34]    = { 0x2b0, 14, 1 },
++	[PAD_GPIO35]    = { 0x2b0, 17, 1 },
++
++	[PAD_GPIO36]    = { 0x2b4, 21, 2 },
++	[PAD_GPIO37]    = { 0x2b4, 18, 2 },
++	[PAD_GPIO38]    = { 0x2b4, 15, 2 },
++	[PAD_GPIO39]    = { 0x2b0, 11, 2 },
++	[PAD_GPIO40]    = { 0x2b0, 20, 2 },
++	[PAD_GPIO41]    = { 0x2b0, 23, 2 },
++	[PAD_GPIO42]    = { 0x2b0, 26, 2 },
++	[PAD_GPIO43]    = { 0x2b0, 29, 2 },
++	[PAD_GPIO44]    = { 0x2b4,  0, 2 },
++	[PAD_GPIO45]    = { 0x2b4,  3, 2 },
++	[PAD_GPIO46]    = { 0x2b4,  6, 2 },
++	[PAD_GPIO47]    = { 0x2b4,  9, 2 },
++	[PAD_GPIO48]    = { 0x2b4, 12, 2 },
++	[PAD_GPIO49]    = { 0x2b0, 14, 2 },
++	[PAD_GPIO50]    = { 0x2b0, 17, 2 },
++};
++
++static void jh7110_set_function(struct jh7110_pinctrl *sfp,
++				unsigned int pin, u32 func)
++{
++	const struct jh7110_func_sel *fs = &jh7110_sys_func_sel[pin];
++	unsigned long flags;
++	void __iomem *reg;
++	u32 mask;
++
++	if (!fs->offset)
++		return;
++
++	if (func > fs->max)
++		return;
++
++	reg = sfp->base + fs->offset;
++	func = func << fs->shift;
++	mask = 0x3U << fs->shift;
++
++	raw_spin_lock_irqsave(&sfp->lock, flags);
++	func |= readl_relaxed(reg) & ~mask;
++	writel_relaxed(func, reg);
++	raw_spin_unlock_irqrestore(&sfp->lock, flags);
++}
++
++static void jh7110_set_vin_group(struct jh7110_pinctrl *sfp,
++				 unsigned int pin)
++{
++	const struct jh7110_vin_group_sel *gs = &jh7110_sys_vin_group_sel[pin];
++	unsigned long flags;
++	void __iomem *reg;
++	u32 mask;
++	u32 grp;
++
++	if (!gs->offset)
++		return;
++
++	reg = sfp->base + gs->offset;
++	grp = gs->group << gs->shift;
++	mask = 0x3U << gs->shift;
++
++	raw_spin_lock_irqsave(&sfp->lock, flags);
++	grp |= readl_relaxed(reg) & ~mask;
++	writel_relaxed(grp, reg);
++	raw_spin_unlock_irqrestore(&sfp->lock, flags);
++}
++
++static int jh7110_sys_set_one_pin_mux(struct jh7110_pinctrl *sfp,
++				      unsigned int pin,
++				      unsigned int din, u32 dout,
++				      u32 doen, u32 func)
++{
++	if (pin < sfp->gc.ngpio && func == 0)
++		jh7110_set_gpiomux(sfp, pin, din, dout, doen);
++
++	jh7110_set_function(sfp, pin, func);
++
++	if (pin < sfp->gc.ngpio && func == 2)
++		jh7110_set_vin_group(sfp, pin);
++
++	return 0;
++}
++
++static int jh7110_sys_get_padcfg_base(struct jh7110_pinctrl *sfp,
++				      unsigned int pin)
++{
++	if (pin < PAD_GMAC1_MDC)
++		return JH7110_SYS_GPO_PDA_0_74_CFG;
++	else if (pin > PAD_GMAC1_TXC && pin <= PAD_QSPI_DATA3)
++		return JH7110_SYS_GPO_PDA_89_94_CFG;
++	else
++		return -1;
++}
++
++static void jh7110_sys_irq_handler(struct irq_desc *desc)
++{
++	struct jh7110_pinctrl *sfp = jh7110_from_irq_desc(desc);
++	struct irq_chip *chip = irq_desc_get_chip(desc);
++	unsigned long mis;
++	unsigned int pin;
++
++	chained_irq_enter(chip, desc);
++
++	mis = readl_relaxed(sfp->base + JH7110_SYS_GPIOMIS0);
++	for_each_set_bit(pin, &mis, 32)
++		generic_handle_domain_irq(sfp->gc.irq.domain, pin);
++
++	mis = readl_relaxed(sfp->base + JH7110_SYS_GPIOMIS1);
++	for_each_set_bit(pin, &mis, 32)
++		generic_handle_domain_irq(sfp->gc.irq.domain, pin + 32);
++
++	chained_irq_exit(chip, desc);
++}
++
++static int jh7110_sys_init_hw(struct gpio_chip *gc)
++{
++	struct jh7110_pinctrl *sfp = container_of(gc,
++			struct jh7110_pinctrl, gc);
++
++	/* mask all GPIO interrupts */
++	writel(0U, sfp->base + JH7110_SYS_GPIOIE0);
++	writel(0U, sfp->base + JH7110_SYS_GPIOIE1);
++	/* clear edge interrupt flags */
++	writel(~0U, sfp->base + JH7110_SYS_GPIOIC0);
++	writel(~0U, sfp->base + JH7110_SYS_GPIOIC1);
++	/* enable GPIO interrupts */
++	writel(1U, sfp->base + JH7110_SYS_GPIOEN);
++	return 0;
++}
++
++static const struct jh7110_gpio_irq_reg jh7110_sys_irq_reg = {
++	.is_reg_base	= JH7110_SYS_GPIOIS0,
++	.ic_reg_base	= JH7110_SYS_GPIOIC0,
++	.ibe_reg_base	= JH7110_SYS_GPIOIBE0,
++	.iev_reg_base	= JH7110_SYS_GPIOIEV0,
++	.ie_reg_base	= JH7110_SYS_GPIOIE0,
++	.ris_reg_base	= JH7110_SYS_GPIORIS0,
++	.mis_reg_base	= JH7110_SYS_GPIOMIS0,
++};
++
++static const struct jh7110_pinctrl_soc_info jh7110_sys_pinctrl_info = {
++	.pins		= jh7110_sys_pins,
++	.npins		= ARRAY_SIZE(jh7110_sys_pins),
++	.ngpios		= JH7110_SYS_NGPIO,
++	.gc_base	= JH7110_SYS_GC_BASE,
++	.dout_reg_base	= JH7110_SYS_DOUT,
++	.dout_mask	= GENMASK(6, 0),
++	.doen_reg_base	= JH7110_SYS_DOEN,
++	.doen_mask	= GENMASK(5, 0),
++	.gpi_reg_base	= JH7110_SYS_GPI,
++	.gpi_mask	= GENMASK(6, 0),
++	.gpioin_reg_base	   = JH7110_SYS_GPIOIN,
++	.irq_reg		   = &jh7110_sys_irq_reg,
++	.jh7110_set_one_pin_mux  = jh7110_sys_set_one_pin_mux,
++	.jh7110_get_padcfg_base  = jh7110_sys_get_padcfg_base,
++	.jh7110_gpio_irq_handler = jh7110_sys_irq_handler,
++	.jh7110_gpio_init_hw	 = jh7110_sys_init_hw,
++};
++
++static const struct of_device_id jh7110_sys_pinctrl_of_match[] = {
++	{
++		.compatible = "starfive,jh7110-sys-pinctrl",
++		.data = &jh7110_sys_pinctrl_info,
++	},
++	{ /* sentinel */ }
++};
++MODULE_DEVICE_TABLE(of, jh7110_sys_pinctrl_of_match);
++
++static struct platform_driver jh7110_sys_pinctrl_driver = {
++	.probe = jh7110_pinctrl_probe,
++	.driver = {
++		.name = "starfive-jh7110-sys-pinctrl",
++		.of_match_table = jh7110_sys_pinctrl_of_match,
++	},
++};
++module_platform_driver(jh7110_sys_pinctrl_driver);
++
++MODULE_DESCRIPTION("Pinctrl driver for the StarFive JH7110 SoC sys controller");
++MODULE_AUTHOR("Emil Renner Berthing <[email protected]>");
++MODULE_AUTHOR("Jianlong Huang <[email protected]>");
++MODULE_LICENSE("GPL");
+--- /dev/null
++++ b/drivers/pinctrl/starfive/pinctrl-starfive-jh7110.c
+@@ -0,0 +1,982 @@
++// SPDX-License-Identifier: GPL-2.0
++/*
++ * Pinctrl / GPIO driver for StarFive JH7110 SoC
++ *
++ * Copyright (C) 2022 Emil Renner Berthing <[email protected]>
++ * Copyright (C) 2022 StarFive Technology Co., Ltd.
++ */
++
++#include <linux/bits.h>
++#include <linux/clk.h>
++#include <linux/gpio/driver.h>
++#include <linux/io.h>
++#include <linux/mod_devicetable.h>
++#include <linux/module.h>
++#include <linux/mutex.h>
++#include <linux/of.h>
++#include <linux/of_device.h>
++#include <linux/platform_device.h>
++#include <linux/reset.h>
++#include <linux/seq_file.h>
++#include <linux/spinlock.h>
++
++#include <linux/pinctrl/consumer.h>
++#include <linux/pinctrl/pinconf.h>
++#include <linux/pinctrl/pinctrl.h>
++#include <linux/pinctrl/pinmux.h>
++
++#include <dt-bindings/pinctrl/starfive,jh7110-pinctrl.h>
++
++#include "../core.h"
++#include "../pinctrl-utils.h"
++#include "../pinmux.h"
++#include "../pinconf.h"
++#include "pinctrl-starfive-jh7110.h"
++
++/* pad control bits */
++#define JH7110_PADCFG_POS	BIT(7)
++#define JH7110_PADCFG_SMT	BIT(6)
++#define JH7110_PADCFG_SLEW	BIT(5)
++#define JH7110_PADCFG_PD	BIT(4)
++#define JH7110_PADCFG_PU	BIT(3)
++#define JH7110_PADCFG_BIAS	(JH7110_PADCFG_PD | JH7110_PADCFG_PU)
++#define JH7110_PADCFG_DS_MASK	GENMASK(2, 1)
++#define JH7110_PADCFG_DS_2MA	(0U << 1)
++#define JH7110_PADCFG_DS_4MA	BIT(1)
++#define JH7110_PADCFG_DS_8MA	(2U << 1)
++#define JH7110_PADCFG_DS_12MA	(3U << 1)
++#define JH7110_PADCFG_IE	BIT(0)
++
++/*
++ * The packed pinmux values from the device tree look like this:
++ *
++ *  | 31 - 24 | 23 - 16 | 15 - 10 |  9 - 8   | 7 - 0 |
++ *  |   din   |  dout   |  doen   | function |  pin  |
++ */
++static unsigned int jh7110_pinmux_din(u32 v)
++{
++	return (v & GENMASK(31, 24)) >> 24;
++}
++
++static u32 jh7110_pinmux_dout(u32 v)
++{
++	return (v & GENMASK(23, 16)) >> 16;
++}
++
++static u32 jh7110_pinmux_doen(u32 v)
++{
++	return (v & GENMASK(15, 10)) >> 10;
++}
++
++static u32 jh7110_pinmux_function(u32 v)
++{
++	return (v & GENMASK(9, 8)) >> 8;
++}
++
++static unsigned int jh7110_pinmux_pin(u32 v)
++{
++	return v & GENMASK(7, 0);
++}
++
++static struct jh7110_pinctrl *jh7110_from_irq_data(struct irq_data *d)
++{
++	struct gpio_chip *gc = irq_data_get_irq_chip_data(d);
++
++	return container_of(gc, struct jh7110_pinctrl, gc);
++}
++
++struct jh7110_pinctrl *jh7110_from_irq_desc(struct irq_desc *desc)
++{
++	struct gpio_chip *gc = irq_desc_get_handler_data(desc);
++
++	return container_of(gc, struct jh7110_pinctrl, gc);
++}
++EXPORT_SYMBOL_GPL(jh7110_from_irq_desc);
++
++#ifdef CONFIG_DEBUG_FS
++static void jh7110_pin_dbg_show(struct pinctrl_dev *pctldev,
++				struct seq_file *s, unsigned int pin)
++{
++	struct jh7110_pinctrl *sfp = pinctrl_dev_get_drvdata(pctldev);
++	const struct jh7110_pinctrl_soc_info *info = sfp->info;
++
++	seq_printf(s, "%s", dev_name(pctldev->dev));
++
++	if (pin < sfp->gc.ngpio) {
++		unsigned int offset = 4 * (pin / 4);
++		unsigned int shift  = 8 * (pin % 4);
++		u32 dout = readl_relaxed(sfp->base + info->dout_reg_base + offset);
++		u32 doen = readl_relaxed(sfp->base + info->doen_reg_base + offset);
++		u32 gpi = readl_relaxed(sfp->base + info->gpi_reg_base + offset);
++
++		dout = (dout >> shift) & info->dout_mask;
++		doen = (doen >> shift) & info->doen_mask;
++		gpi = ((gpi >> shift) - 2) & info->gpi_mask;
++
++		seq_printf(s, " dout=%u doen=%u din=%u", dout, doen, gpi);
++	}
++}
++#else
++#define jh7110_pin_dbg_show NULL
++#endif
++
++static int jh7110_dt_node_to_map(struct pinctrl_dev *pctldev,
++				 struct device_node *np,
++				 struct pinctrl_map **maps,
++				 unsigned int *num_maps)
++{
++	struct jh7110_pinctrl *sfp = pinctrl_dev_get_drvdata(pctldev);
++	struct device *dev = sfp->gc.parent;
++	struct device_node *child;
++	struct pinctrl_map *map;
++	const char **pgnames;
++	const char *grpname;
++	int ngroups;
++	int nmaps;
++	int ret;
++
++	ngroups = 0;
++	for_each_child_of_node(np, child)
++		ngroups += 1;
++	nmaps = 2 * ngroups;
++
++	pgnames = devm_kcalloc(dev, ngroups, sizeof(*pgnames), GFP_KERNEL);
++	if (!pgnames)
++		return -ENOMEM;
++
++	map = kcalloc(nmaps, sizeof(*map), GFP_KERNEL);
++	if (!map)
++		return -ENOMEM;
++
++	nmaps = 0;
++	ngroups = 0;
++	mutex_lock(&sfp->mutex);
++	for_each_child_of_node(np, child) {
++		int npins = of_property_count_u32_elems(child, "pinmux");
++		int *pins;
++		u32 *pinmux;
++		int i;
++
++		if (npins < 1) {
++			dev_err(dev,
++				"invalid pinctrl group %pOFn.%pOFn: pinmux not set\n",
++				np, child);
++			ret = -EINVAL;
++			goto put_child;
++		}
++
++		grpname = devm_kasprintf(dev, GFP_KERNEL, "%pOFn.%pOFn", np, child);
++		if (!grpname) {
++			ret = -ENOMEM;
++			goto put_child;
++		}
++
++		pgnames[ngroups++] = grpname;
++
++		pins = devm_kcalloc(dev, npins, sizeof(*pins), GFP_KERNEL);
++		if (!pins) {
++			ret = -ENOMEM;
++			goto put_child;
++		}
++
++		pinmux = devm_kcalloc(dev, npins, sizeof(*pinmux), GFP_KERNEL);
++		if (!pinmux) {
++			ret = -ENOMEM;
++			goto put_child;
++		}
++
++		ret = of_property_read_u32_array(child, "pinmux", pinmux, npins);
++		if (ret)
++			goto put_child;
++
++		for (i = 0; i < npins; i++)
++			pins[i] = jh7110_pinmux_pin(pinmux[i]);
++
++		map[nmaps].type = PIN_MAP_TYPE_MUX_GROUP;
++		map[nmaps].data.mux.function = np->name;
++		map[nmaps].data.mux.group = grpname;
++		nmaps += 1;
++
++		ret = pinctrl_generic_add_group(pctldev, grpname,
++						pins, npins, pinmux);
++		if (ret < 0) {
++			dev_err(dev, "error adding group %s: %d\n", grpname, ret);
++			goto put_child;
++		}
++
++		ret = pinconf_generic_parse_dt_config(child, pctldev,
++						      &map[nmaps].data.configs.configs,
++						      &map[nmaps].data.configs.num_configs);
++		if (ret) {
++			dev_err(dev, "error parsing pin config of group %s: %d\n",
++				grpname, ret);
++			goto put_child;
++		}
++
++		/* don't create a map if there are no pinconf settings */
++		if (map[nmaps].data.configs.num_configs == 0)
++			continue;
++
++		map[nmaps].type = PIN_MAP_TYPE_CONFIGS_GROUP;
++		map[nmaps].data.configs.group_or_pin = grpname;
++		nmaps += 1;
++	}
++
++	ret = pinmux_generic_add_function(pctldev, np->name,
++					  pgnames, ngroups, NULL);
++	if (ret < 0) {
++		dev_err(dev, "error adding function %s: %d\n", np->name, ret);
++		goto free_map;
++	}
++	mutex_unlock(&sfp->mutex);
++
++	*maps = map;
++	*num_maps = nmaps;
++	return 0;
++
++put_child:
++	of_node_put(child);
++free_map:
++	pinctrl_utils_free_map(pctldev, map, nmaps);
++	mutex_unlock(&sfp->mutex);
++	return ret;
++}
++
++static const struct pinctrl_ops jh7110_pinctrl_ops = {
++	.get_groups_count = pinctrl_generic_get_group_count,
++	.get_group_name	  = pinctrl_generic_get_group_name,
++	.get_group_pins   = pinctrl_generic_get_group_pins,
++	.pin_dbg_show	  = jh7110_pin_dbg_show,
++	.dt_node_to_map	  = jh7110_dt_node_to_map,
++	.dt_free_map	  = pinctrl_utils_free_map,
++};
++
++void jh7110_set_gpiomux(struct jh7110_pinctrl *sfp, unsigned int pin,
++			unsigned int din, u32 dout, u32 doen)
++{
++	const struct jh7110_pinctrl_soc_info *info = sfp->info;
++
++	unsigned int offset = 4 * (pin / 4);
++	unsigned int shift  = 8 * (pin % 4);
++	u32 dout_mask = info->dout_mask << shift;
++	u32 done_mask = info->doen_mask << shift;
++	u32 ival, imask;
++	void __iomem *reg_dout;
++	void __iomem *reg_doen;
++	void __iomem *reg_din;
++	unsigned long flags;
++
++	reg_dout = sfp->base + info->dout_reg_base + offset;
++	reg_doen = sfp->base + info->doen_reg_base + offset;
++	dout <<= shift;
++	doen <<= shift;
++	if (din != GPI_NONE) {
++		unsigned int ioffset = 4 * (din / 4);
++		unsigned int ishift  = 8 * (din % 4);
++
++		reg_din = sfp->base + info->gpi_reg_base + ioffset;
++		ival = (pin + 2) << ishift;
++		imask = info->gpi_mask << ishift;
++	} else {
++		reg_din = NULL;
++	}
++
++	raw_spin_lock_irqsave(&sfp->lock, flags);
++	dout |= readl_relaxed(reg_dout) & ~dout_mask;
++	writel_relaxed(dout, reg_dout);
++	doen |= readl_relaxed(reg_doen) & ~done_mask;
++	writel_relaxed(doen, reg_doen);
++	if (reg_din) {
++		ival |= readl_relaxed(reg_din) & ~imask;
++		writel_relaxed(ival, reg_din);
++	}
++	raw_spin_unlock_irqrestore(&sfp->lock, flags);
++}
++EXPORT_SYMBOL_GPL(jh7110_set_gpiomux);
++
++static int jh7110_set_mux(struct pinctrl_dev *pctldev,
++			  unsigned int fsel, unsigned int gsel)
++{
++	struct jh7110_pinctrl *sfp = pinctrl_dev_get_drvdata(pctldev);
++	const struct jh7110_pinctrl_soc_info *info = sfp->info;
++	const struct group_desc *group;
++	const u32 *pinmux;
++	unsigned int i;
++
++	group = pinctrl_generic_get_group(pctldev, gsel);
++	if (!group)
++		return -EINVAL;
++
++	pinmux = group->data;
++	for (i = 0; i < group->num_pins; i++) {
++		u32 v = pinmux[i];
++
++		if (info->jh7110_set_one_pin_mux)
++			info->jh7110_set_one_pin_mux(sfp,
++					jh7110_pinmux_pin(v),
++					jh7110_pinmux_din(v),
++					jh7110_pinmux_dout(v),
++					jh7110_pinmux_doen(v),
++					jh7110_pinmux_function(v));
++	}
++
++	return 0;
++}
++
++static const struct pinmux_ops jh7110_pinmux_ops = {
++	.get_functions_count = pinmux_generic_get_function_count,
++	.get_function_name   = pinmux_generic_get_function_name,
++	.get_function_groups = pinmux_generic_get_function_groups,
++	.set_mux	     = jh7110_set_mux,
++	.strict		     = true,
++};
++
++static const u8 jh7110_drive_strength_mA[4] = { 2, 4, 8, 12 };
++
++static u32 jh7110_padcfg_ds_to_mA(u32 padcfg)
++{
++	return jh7110_drive_strength_mA[(padcfg >> 1) & 3U];
++}
++
++static u32 jh7110_padcfg_ds_from_mA(u32 v)
++{
++	int i;
++
++	for (i = 0; i < 3; i++) {
++		if (v <= jh7110_drive_strength_mA[i])
++			break;
++	}
++	return i << 1;
++}
++
++static void jh7110_padcfg_rmw(struct jh7110_pinctrl *sfp,
++			      unsigned int pin, u32 mask, u32 value)
++{
++	const struct jh7110_pinctrl_soc_info *info = sfp->info;
++	void __iomem *reg;
++	unsigned long flags;
++	int padcfg_base;
++
++	if (!info->jh7110_get_padcfg_base)
++		return;
++
++	padcfg_base = info->jh7110_get_padcfg_base(sfp, pin);
++	if (padcfg_base < 0)
++		return;
++
++	reg = sfp->base + padcfg_base + 4 * pin;
++	value &= mask;
++
++	raw_spin_lock_irqsave(&sfp->lock, flags);
++	value |= readl_relaxed(reg) & ~mask;
++	writel_relaxed(value, reg);
++	raw_spin_unlock_irqrestore(&sfp->lock, flags);
++}
++
++static int jh7110_pinconf_get(struct pinctrl_dev *pctldev,
++			      unsigned int pin, unsigned long *config)
++{
++	struct jh7110_pinctrl *sfp = pinctrl_dev_get_drvdata(pctldev);
++	const struct jh7110_pinctrl_soc_info *info = sfp->info;
++	int param = pinconf_to_config_param(*config);
++	u32 padcfg, arg;
++	bool enabled;
++	int padcfg_base;
++
++	if (!info->jh7110_get_padcfg_base)
++		return 0;
++
++	padcfg_base = info->jh7110_get_padcfg_base(sfp, pin);
++	if (padcfg_base < 0)
++		return 0;
++
++	padcfg = readl_relaxed(sfp->base + padcfg_base + 4 * pin);
++	switch (param) {
++	case PIN_CONFIG_BIAS_DISABLE:
++		enabled = !(padcfg & JH7110_PADCFG_BIAS);
++		arg = 0;
++		break;
++	case PIN_CONFIG_BIAS_PULL_DOWN:
++		enabled = padcfg & JH7110_PADCFG_PD;
++		arg = 1;
++		break;
++	case PIN_CONFIG_BIAS_PULL_UP:
++		enabled = padcfg & JH7110_PADCFG_PU;
++		arg = 1;
++		break;
++	case PIN_CONFIG_DRIVE_STRENGTH:
++		enabled = true;
++		arg = jh7110_padcfg_ds_to_mA(padcfg);
++		break;
++	case PIN_CONFIG_INPUT_ENABLE:
++		enabled = padcfg & JH7110_PADCFG_IE;
++		arg = enabled;
++		break;
++	case PIN_CONFIG_INPUT_SCHMITT_ENABLE:
++		enabled = padcfg & JH7110_PADCFG_SMT;
++		arg = enabled;
++		break;
++	case PIN_CONFIG_SLEW_RATE:
++		enabled = true;
++		arg = !!(padcfg & JH7110_PADCFG_SLEW);
++		break;
++	default:
++		return -ENOTSUPP;
++	}
++
++	*config = pinconf_to_config_packed(param, arg);
++	return enabled ? 0 : -EINVAL;
++}
++
++static int jh7110_pinconf_group_get(struct pinctrl_dev *pctldev,
++				    unsigned int gsel,
++				    unsigned long *config)
++{
++	const struct group_desc *group;
++
++	group = pinctrl_generic_get_group(pctldev, gsel);
++	if (!group)
++		return -EINVAL;
++
++	return jh7110_pinconf_get(pctldev, group->pins[0], config);
++}
++
++static int jh7110_pinconf_group_set(struct pinctrl_dev *pctldev,
++				    unsigned int gsel,
++				    unsigned long *configs,
++				    unsigned int num_configs)
++{
++	struct jh7110_pinctrl *sfp = pinctrl_dev_get_drvdata(pctldev);
++	const struct group_desc *group;
++	u16 mask, value;
++	int i;
++
++	group = pinctrl_generic_get_group(pctldev, gsel);
++	if (!group)
++		return -EINVAL;
++
++	mask = 0;
++	value = 0;
++	for (i = 0; i < num_configs; i++) {
++		int param = pinconf_to_config_param(configs[i]);
++		u32 arg = pinconf_to_config_argument(configs[i]);
++
++		switch (param) {
++		case PIN_CONFIG_BIAS_DISABLE:
++			mask |= JH7110_PADCFG_BIAS;
++			value &= ~JH7110_PADCFG_BIAS;
++			break;
++		case PIN_CONFIG_BIAS_PULL_DOWN:
++			if (arg == 0)
++				return -ENOTSUPP;
++			mask |= JH7110_PADCFG_BIAS;
++			value = (value & ~JH7110_PADCFG_BIAS) | JH7110_PADCFG_PD;
++			break;
++		case PIN_CONFIG_BIAS_PULL_UP:
++			if (arg == 0)
++				return -ENOTSUPP;
++			mask |= JH7110_PADCFG_BIAS;
++			value = (value & ~JH7110_PADCFG_BIAS) | JH7110_PADCFG_PU;
++			break;
++		case PIN_CONFIG_DRIVE_STRENGTH:
++			mask |= JH7110_PADCFG_DS_MASK;
++			value = (value & ~JH7110_PADCFG_DS_MASK) |
++				jh7110_padcfg_ds_from_mA(arg);
++			break;
++		case PIN_CONFIG_INPUT_ENABLE:
++			mask |= JH7110_PADCFG_IE;
++			if (arg)
++				value |= JH7110_PADCFG_IE;
++			else
++				value &= ~JH7110_PADCFG_IE;
++			break;
++		case PIN_CONFIG_INPUT_SCHMITT_ENABLE:
++			mask |= JH7110_PADCFG_SMT;
++			if (arg)
++				value |= JH7110_PADCFG_SMT;
++			else
++				value &= ~JH7110_PADCFG_SMT;
++			break;
++		case PIN_CONFIG_SLEW_RATE:
++			mask |= JH7110_PADCFG_SLEW;
++			if (arg)
++				value |= JH7110_PADCFG_SLEW;
++			else
++				value &= ~JH7110_PADCFG_SLEW;
++			break;
++		default:
++			return -ENOTSUPP;
++		}
++	}
++
++	for (i = 0; i < group->num_pins; i++)
++		jh7110_padcfg_rmw(sfp, group->pins[i], mask, value);
++
++	return 0;
++}
++
++#ifdef CONFIG_DEBUG_FS
++static void jh7110_pinconf_dbg_show(struct pinctrl_dev *pctldev,
++				    struct seq_file *s, unsigned int pin)
++{
++	struct jh7110_pinctrl *sfp = pinctrl_dev_get_drvdata(pctldev);
++	const struct jh7110_pinctrl_soc_info *info = sfp->info;
++	u32 value;
++	int padcfg_base;
++
++	if (!info->jh7110_get_padcfg_base)
++		return;
++
++	padcfg_base = info->jh7110_get_padcfg_base(sfp, pin);
++	if (padcfg_base < 0)
++		return;
++
++	value = readl_relaxed(sfp->base + padcfg_base + 4 * pin);
++	seq_printf(s, " (0x%02x)", value);
++}
++#else
++#define jh7110_pinconf_dbg_show NULL
++#endif
++
++static const struct pinconf_ops jh7110_pinconf_ops = {
++	.pin_config_get		= jh7110_pinconf_get,
++	.pin_config_group_get	= jh7110_pinconf_group_get,
++	.pin_config_group_set	= jh7110_pinconf_group_set,
++	.pin_config_dbg_show	= jh7110_pinconf_dbg_show,
++	.is_generic		= true,
++};
++
++static int jh7110_gpio_request(struct gpio_chip *gc, unsigned int gpio)
++{
++	return pinctrl_gpio_request(gc->base + gpio);
++}
++
++static void jh7110_gpio_free(struct gpio_chip *gc, unsigned int gpio)
++{
++	pinctrl_gpio_free(gc->base + gpio);
++}
++
++static int jh7110_gpio_get_direction(struct gpio_chip *gc,
++				     unsigned int gpio)
++{
++	struct jh7110_pinctrl *sfp = container_of(gc,
++			struct jh7110_pinctrl, gc);
++	const struct jh7110_pinctrl_soc_info *info = sfp->info;
++	unsigned int offset = 4 * (gpio / 4);
++	unsigned int shift  = 8 * (gpio % 4);
++	u32 doen = readl_relaxed(sfp->base + info->doen_reg_base + offset);
++
++	doen = (doen >> shift) & info->doen_mask;
++
++	return doen == GPOEN_ENABLE ?
++		GPIO_LINE_DIRECTION_OUT : GPIO_LINE_DIRECTION_IN;
++}
++
++static int jh7110_gpio_direction_input(struct gpio_chip *gc,
++				       unsigned int gpio)
++{
++	struct jh7110_pinctrl *sfp = container_of(gc,
++			struct jh7110_pinctrl, gc);
++	const struct jh7110_pinctrl_soc_info *info = sfp->info;
++
++	/* enable input and schmitt trigger */
++	jh7110_padcfg_rmw(sfp, gpio,
++			  JH7110_PADCFG_IE | JH7110_PADCFG_SMT,
++			  JH7110_PADCFG_IE | JH7110_PADCFG_SMT);
++
++	if (info->jh7110_set_one_pin_mux)
++		info->jh7110_set_one_pin_mux(sfp, gpio,
++				GPI_NONE, GPOUT_LOW, GPOEN_DISABLE, 0);
++
++	return 0;
++}
++
++static int jh7110_gpio_direction_output(struct gpio_chip *gc,
++					unsigned int gpio, int value)
++{
++	struct jh7110_pinctrl *sfp = container_of(gc,
++			struct jh7110_pinctrl, gc);
++	const struct jh7110_pinctrl_soc_info *info = sfp->info;
++
++	if (info->jh7110_set_one_pin_mux)
++		info->jh7110_set_one_pin_mux(sfp, gpio,
++				GPI_NONE, value ? GPOUT_HIGH : GPOUT_LOW,
++				GPOEN_ENABLE, 0);
++
++	/* disable input, schmitt trigger and bias */
++	jh7110_padcfg_rmw(sfp, gpio,
++			  JH7110_PADCFG_IE | JH7110_PADCFG_SMT |
++			  JH7110_PADCFG_BIAS, 0);
++	return 0;
++}
++
++static int jh7110_gpio_get(struct gpio_chip *gc, unsigned int gpio)
++{
++	struct jh7110_pinctrl *sfp = container_of(gc,
++			struct jh7110_pinctrl, gc);
++	const struct jh7110_pinctrl_soc_info *info = sfp->info;
++	void __iomem *reg = sfp->base + info->gpioin_reg_base
++			+ 4 * (gpio / 32);
++
++	return !!(readl_relaxed(reg) & BIT(gpio % 32));
++}
++
++static void jh7110_gpio_set(struct gpio_chip *gc,
++			    unsigned int gpio, int value)
++{
++	struct jh7110_pinctrl *sfp = container_of(gc,
++			struct jh7110_pinctrl, gc);
++	const struct jh7110_pinctrl_soc_info *info = sfp->info;
++	unsigned int offset = 4 * (gpio / 4);
++	unsigned int shift  = 8 * (gpio % 4);
++	void __iomem *reg_dout = sfp->base + info->dout_reg_base + offset;
++	u32 dout = (value ? GPOUT_HIGH : GPOUT_LOW) << shift;
++	u32 mask = info->dout_mask << shift;
++	unsigned long flags;
++
++	raw_spin_lock_irqsave(&sfp->lock, flags);
++	dout |= readl_relaxed(reg_dout) & ~mask;
++	writel_relaxed(dout, reg_dout);
++	raw_spin_unlock_irqrestore(&sfp->lock, flags);
++}
++
++static int jh7110_gpio_set_config(struct gpio_chip *gc,
++				  unsigned int gpio, unsigned long config)
++{
++	struct jh7110_pinctrl *sfp = container_of(gc,
++			struct jh7110_pinctrl, gc);
++	u32 arg = pinconf_to_config_argument(config);
++	u32 value;
++	u32 mask;
++
++	switch (pinconf_to_config_param(config)) {
++	case PIN_CONFIG_BIAS_DISABLE:
++		mask  = JH7110_PADCFG_BIAS;
++		value = 0;
++		break;
++	case PIN_CONFIG_BIAS_PULL_DOWN:
++		if (arg == 0)
++			return -ENOTSUPP;
++		mask  = JH7110_PADCFG_BIAS;
++		value = JH7110_PADCFG_PD;
++		break;
++	case PIN_CONFIG_BIAS_PULL_UP:
++		if (arg == 0)
++			return -ENOTSUPP;
++		mask  = JH7110_PADCFG_BIAS;
++		value = JH7110_PADCFG_PU;
++		break;
++	case PIN_CONFIG_DRIVE_PUSH_PULL:
++		return 0;
++	case PIN_CONFIG_INPUT_ENABLE:
++		mask  = JH7110_PADCFG_IE;
++		value = arg ? JH7110_PADCFG_IE : 0;
++		break;
++	case PIN_CONFIG_INPUT_SCHMITT_ENABLE:
++		mask  = JH7110_PADCFG_SMT;
++		value = arg ? JH7110_PADCFG_SMT : 0;
++		break;
++	default:
++		return -ENOTSUPP;
++	}
++
++	jh7110_padcfg_rmw(sfp, gpio, mask, value);
++	return 0;
++}
++
++static int jh7110_gpio_add_pin_ranges(struct gpio_chip *gc)
++{
++	struct jh7110_pinctrl *sfp = container_of(gc,
++			struct jh7110_pinctrl, gc);
++
++	sfp->gpios.name = sfp->gc.label;
++	sfp->gpios.base = sfp->gc.base;
++	sfp->gpios.pin_base = 0;
++	sfp->gpios.npins = sfp->gc.ngpio;
++	sfp->gpios.gc = &sfp->gc;
++	pinctrl_add_gpio_range(sfp->pctl, &sfp->gpios);
++	return 0;
++}
++
++static void jh7110_irq_ack(struct irq_data *d)
++{
++	struct jh7110_pinctrl *sfp = jh7110_from_irq_data(d);
++	const struct jh7110_gpio_irq_reg *irq_reg = sfp->info->irq_reg;
++	irq_hw_number_t gpio = irqd_to_hwirq(d);
++	void __iomem *ic = sfp->base + irq_reg->ic_reg_base
++		+ 4 * (gpio / 32);
++	u32 mask = BIT(gpio % 32);
++	unsigned long flags;
++	u32 value;
++
++	raw_spin_lock_irqsave(&sfp->lock, flags);
++	value = readl_relaxed(ic) & ~mask;
++	writel_relaxed(value, ic);
++	writel_relaxed(value | mask, ic);
++	raw_spin_unlock_irqrestore(&sfp->lock, flags);
++}
++
++static void jh7110_irq_mask(struct irq_data *d)
++{
++	struct jh7110_pinctrl *sfp = jh7110_from_irq_data(d);
++	const struct jh7110_gpio_irq_reg *irq_reg = sfp->info->irq_reg;
++	irq_hw_number_t gpio = irqd_to_hwirq(d);
++	void __iomem *ie = sfp->base + irq_reg->ie_reg_base
++		+ 4 * (gpio / 32);
++	u32 mask = BIT(gpio % 32);
++	unsigned long flags;
++	u32 value;
++
++	raw_spin_lock_irqsave(&sfp->lock, flags);
++	value = readl_relaxed(ie) & ~mask;
++	writel_relaxed(value, ie);
++	raw_spin_unlock_irqrestore(&sfp->lock, flags);
++
++	gpiochip_disable_irq(&sfp->gc, d->hwirq);
++}
++
++static void jh7110_irq_mask_ack(struct irq_data *d)
++{
++	struct jh7110_pinctrl *sfp = jh7110_from_irq_data(d);
++	const struct jh7110_gpio_irq_reg *irq_reg = sfp->info->irq_reg;
++	irq_hw_number_t gpio = irqd_to_hwirq(d);
++	void __iomem *ie = sfp->base + irq_reg->ie_reg_base
++		+ 4 * (gpio / 32);
++	void __iomem *ic = sfp->base + irq_reg->ic_reg_base
++		+ 4 * (gpio / 32);
++	u32 mask = BIT(gpio % 32);
++	unsigned long flags;
++	u32 value;
++
++	raw_spin_lock_irqsave(&sfp->lock, flags);
++	value = readl_relaxed(ie) & ~mask;
++	writel_relaxed(value, ie);
++
++	value = readl_relaxed(ic) & ~mask;
++	writel_relaxed(value, ic);
++	writel_relaxed(value | mask, ic);
++	raw_spin_unlock_irqrestore(&sfp->lock, flags);
++}
++
++static void jh7110_irq_unmask(struct irq_data *d)
++{
++	struct jh7110_pinctrl *sfp = jh7110_from_irq_data(d);
++	const struct jh7110_gpio_irq_reg *irq_reg = sfp->info->irq_reg;
++	irq_hw_number_t gpio = irqd_to_hwirq(d);
++	void __iomem *ie = sfp->base + irq_reg->ie_reg_base
++		+ 4 * (gpio / 32);
++	u32 mask = BIT(gpio % 32);
++	unsigned long flags;
++	u32 value;
++
++	gpiochip_enable_irq(&sfp->gc, d->hwirq);
++
++	raw_spin_lock_irqsave(&sfp->lock, flags);
++	value = readl_relaxed(ie) | mask;
++	writel_relaxed(value, ie);
++	raw_spin_unlock_irqrestore(&sfp->lock, flags);
++}
++
++static int jh7110_irq_set_type(struct irq_data *d, unsigned int trigger)
++{
++	struct jh7110_pinctrl *sfp = jh7110_from_irq_data(d);
++	const struct jh7110_gpio_irq_reg *irq_reg = sfp->info->irq_reg;
++	irq_hw_number_t gpio = irqd_to_hwirq(d);
++	void __iomem *base = sfp->base + 4 * (gpio / 32);
++	u32 mask = BIT(gpio % 32);
++	u32 irq_type, edge_both, polarity;
++	unsigned long flags;
++
++	switch (trigger) {
++	case IRQ_TYPE_EDGE_RISING:
++		irq_type  = mask; /* 1: edge triggered */
++		edge_both = 0;    /* 0: single edge */
++		polarity  = mask; /* 1: rising edge */
++		break;
++	case IRQ_TYPE_EDGE_FALLING:
++		irq_type  = mask; /* 1: edge triggered */
++		edge_both = 0;    /* 0: single edge */
++		polarity  = 0;    /* 0: falling edge */
++		break;
++	case IRQ_TYPE_EDGE_BOTH:
++		irq_type  = mask; /* 1: edge triggered */
++		edge_both = mask; /* 1: both edges */
++		polarity  = 0;    /* 0: ignored */
++		break;
++	case IRQ_TYPE_LEVEL_HIGH:
++		irq_type  = 0;    /* 0: level triggered */
++		edge_both = 0;    /* 0: ignored */
++		polarity  = mask; /* 1: high level */
++		break;
++	case IRQ_TYPE_LEVEL_LOW:
++		irq_type  = 0;    /* 0: level triggered */
++		edge_both = 0;    /* 0: ignored */
++		polarity  = 0;    /* 0: low level */
++		break;
++	default:
++		return -EINVAL;
++	}
++
++	if (trigger & IRQ_TYPE_EDGE_BOTH)
++		irq_set_handler_locked(d, handle_edge_irq);
++	else
++		irq_set_handler_locked(d, handle_level_irq);
++
++	raw_spin_lock_irqsave(&sfp->lock, flags);
++	irq_type |= readl_relaxed(base + irq_reg->is_reg_base) & ~mask;
++	writel_relaxed(irq_type, base + irq_reg->is_reg_base);
++
++	edge_both |= readl_relaxed(base + irq_reg->ibe_reg_base) & ~mask;
++	writel_relaxed(edge_both, base + irq_reg->ibe_reg_base);
++
++	polarity |= readl_relaxed(base + irq_reg->iev_reg_base) & ~mask;
++	writel_relaxed(polarity, base + irq_reg->iev_reg_base);
++	raw_spin_unlock_irqrestore(&sfp->lock, flags);
++	return 0;
++}
++
++static struct irq_chip jh7110_irq_chip = {
++	.irq_ack      = jh7110_irq_ack,
++	.irq_mask     = jh7110_irq_mask,
++	.irq_mask_ack = jh7110_irq_mask_ack,
++	.irq_unmask   = jh7110_irq_unmask,
++	.irq_set_type = jh7110_irq_set_type,
++	.flags	      = IRQCHIP_IMMUTABLE | IRQCHIP_SET_TYPE_MASKED,
++	GPIOCHIP_IRQ_RESOURCE_HELPERS,
++};
++
++static void jh7110_disable_clock(void *data)
++{
++	clk_disable_unprepare(data);
++}
++
++int jh7110_pinctrl_probe(struct platform_device *pdev)
++{
++	struct device *dev = &pdev->dev;
++	const struct jh7110_pinctrl_soc_info *info;
++	struct jh7110_pinctrl *sfp;
++	struct pinctrl_desc *jh7110_pinctrl_desc;
++	struct reset_control *rst;
++	struct clk *clk;
++	int ret;
++
++	info = of_device_get_match_data(&pdev->dev);
++	if (!info)
++		return -ENODEV;
++
++	if (!info->pins || !info->npins) {
++		dev_err(dev, "wrong pinctrl info\n");
++		return -EINVAL;
++	}
++
++	sfp = devm_kzalloc(dev, sizeof(*sfp), GFP_KERNEL);
++	if (!sfp)
++		return -ENOMEM;
++
++	sfp->base = devm_platform_ioremap_resource(pdev, 0);
++	if (IS_ERR(sfp->base))
++		return PTR_ERR(sfp->base);
++
++	clk = devm_clk_get_optional(dev, NULL);
++	if (IS_ERR(clk))
++		return dev_err_probe(dev, PTR_ERR(clk), "could not get clock\n");
++
++	rst = devm_reset_control_get_exclusive(dev, NULL);
++	if (IS_ERR(rst))
++		return dev_err_probe(dev, PTR_ERR(rst), "could not get reset\n");
++
++	/*
++	 * we don't want to assert reset and risk undoing pin muxing for the
++	 * early boot serial console, but let's make sure the reset line is
++	 * deasserted in case someone runs a really minimal bootloader.
++	 */
++	ret = reset_control_deassert(rst);
++	if (ret)
++		return dev_err_probe(dev, ret, "could not deassert reset\n");
++
++	if (clk) {
++		ret = clk_prepare_enable(clk);
++		if (ret)
++			return dev_err_probe(dev, ret, "could not enable clock\n");
++
++		ret = devm_add_action_or_reset(dev, jh7110_disable_clock, clk);
++		if (ret)
++			return ret;
++	}
++
++	jh7110_pinctrl_desc = devm_kzalloc(&pdev->dev,
++					   sizeof(*jh7110_pinctrl_desc),
++					   GFP_KERNEL);
++	if (!jh7110_pinctrl_desc)
++		return -ENOMEM;
++
++	jh7110_pinctrl_desc->name = dev_name(dev);
++	jh7110_pinctrl_desc->pins = info->pins;
++	jh7110_pinctrl_desc->npins = info->npins;
++	jh7110_pinctrl_desc->pctlops = &jh7110_pinctrl_ops;
++	jh7110_pinctrl_desc->pmxops = &jh7110_pinmux_ops;
++	jh7110_pinctrl_desc->confops = &jh7110_pinconf_ops;
++	jh7110_pinctrl_desc->owner = THIS_MODULE;
++
++	sfp->info = info;
++	sfp->dev = dev;
++	platform_set_drvdata(pdev, sfp);
++	sfp->gc.parent = dev;
++	raw_spin_lock_init(&sfp->lock);
++	mutex_init(&sfp->mutex);
++
++	ret = devm_pinctrl_register_and_init(dev,
++					     jh7110_pinctrl_desc,
++					     sfp, &sfp->pctl);
++	if (ret)
++		return dev_err_probe(dev, ret,
++				"could not register pinctrl driver\n");
++
++	sfp->gc.label = dev_name(dev);
++	sfp->gc.owner = THIS_MODULE;
++	sfp->gc.request = jh7110_gpio_request;
++	sfp->gc.free = jh7110_gpio_free;
++	sfp->gc.get_direction = jh7110_gpio_get_direction;
++	sfp->gc.direction_input = jh7110_gpio_direction_input;
++	sfp->gc.direction_output = jh7110_gpio_direction_output;
++	sfp->gc.get = jh7110_gpio_get;
++	sfp->gc.set = jh7110_gpio_set;
++	sfp->gc.set_config = jh7110_gpio_set_config;
++	sfp->gc.add_pin_ranges = jh7110_gpio_add_pin_ranges;
++	sfp->gc.base = info->gc_base;
++	sfp->gc.ngpio = info->ngpios;
++
++	jh7110_irq_chip.name = sfp->gc.label;
++	gpio_irq_chip_set_chip(&sfp->gc.irq, &jh7110_irq_chip);
++	sfp->gc.irq.parent_handler = info->jh7110_gpio_irq_handler;
++	sfp->gc.irq.num_parents = 1;
++	sfp->gc.irq.parents = devm_kcalloc(dev, sfp->gc.irq.num_parents,
++					   sizeof(*sfp->gc.irq.parents),
++					   GFP_KERNEL);
++	if (!sfp->gc.irq.parents)
++		return -ENOMEM;
++	sfp->gc.irq.default_type = IRQ_TYPE_NONE;
++	sfp->gc.irq.handler = handle_bad_irq;
++	sfp->gc.irq.init_hw = info->jh7110_gpio_init_hw;
++
++	ret = platform_get_irq(pdev, 0);
++	if (ret < 0)
++		return ret;
++	sfp->gc.irq.parents[0] = ret;
++
++	ret = devm_gpiochip_add_data(dev, &sfp->gc, sfp);
++	if (ret)
++		return dev_err_probe(dev, ret, "could not register gpiochip\n");
++
++	irq_domain_set_pm_device(sfp->gc.irq.domain, dev);
++
++	dev_info(dev, "StarFive GPIO chip registered %d GPIOs\n", sfp->gc.ngpio);
++
++	return pinctrl_enable(sfp->pctl);
++}
++EXPORT_SYMBOL_GPL(jh7110_pinctrl_probe);
++
++MODULE_DESCRIPTION("Pinctrl driver for the StarFive JH7110 SoC");
++MODULE_AUTHOR("Emil Renner Berthing <[email protected]>");
++MODULE_AUTHOR("Jianlong Huang <[email protected]>");
++MODULE_LICENSE("GPL");
+--- /dev/null
++++ b/drivers/pinctrl/starfive/pinctrl-starfive-jh7110.h
+@@ -0,0 +1,70 @@
++/* SPDX-License-Identifier: GPL-2.0 */
++/*
++ * Pinctrl / GPIO driver for StarFive JH7110 SoC
++ *
++ * Copyright (C) 2022 StarFive Technology Co., Ltd.
++ */
++
++#ifndef __PINCTRL_STARFIVE_JH7110_H__
++#define __PINCTRL_STARFIVE_JH7110_H__
++
++#include <linux/pinctrl/pinconf-generic.h>
++#include <linux/pinctrl/pinmux.h>
++
++struct jh7110_pinctrl {
++	struct device *dev;
++	struct gpio_chip gc;
++	struct pinctrl_gpio_range gpios;
++	raw_spinlock_t lock;
++	void __iomem *base;
++	struct pinctrl_dev *pctl;
++	/* register read/write mutex */
++	struct mutex mutex;
++	const struct jh7110_pinctrl_soc_info *info;
++};
++
++struct jh7110_gpio_irq_reg {
++	unsigned int is_reg_base;
++	unsigned int ic_reg_base;
++	unsigned int ibe_reg_base;
++	unsigned int iev_reg_base;
++	unsigned int ie_reg_base;
++	unsigned int ris_reg_base;
++	unsigned int mis_reg_base;
++};
++
++struct jh7110_pinctrl_soc_info {
++	const struct pinctrl_pin_desc *pins;
++	unsigned int npins;
++	unsigned int ngpios;
++	unsigned int gc_base;
++
++	/* gpio dout/doen/din/gpioinput register */
++	unsigned int dout_reg_base;
++	unsigned int dout_mask;
++	unsigned int doen_reg_base;
++	unsigned int doen_mask;
++	unsigned int gpi_reg_base;
++	unsigned int gpi_mask;
++	unsigned int gpioin_reg_base;
++
++	const struct jh7110_gpio_irq_reg *irq_reg;
++
++	/* generic pinmux */
++	int (*jh7110_set_one_pin_mux)(struct jh7110_pinctrl *sfp,
++				      unsigned int pin,
++				      unsigned int din, u32 dout,
++				      u32 doen, u32 func);
++	/* gpio chip */
++	int (*jh7110_get_padcfg_base)(struct jh7110_pinctrl *sfp,
++				      unsigned int pin);
++	void (*jh7110_gpio_irq_handler)(struct irq_desc *desc);
++	int (*jh7110_gpio_init_hw)(struct gpio_chip *gc);
++};
++
++void jh7110_set_gpiomux(struct jh7110_pinctrl *sfp, unsigned int pin,
++			unsigned int din, u32 dout, u32 doen);
++int jh7110_pinctrl_probe(struct platform_device *pdev);
++struct jh7110_pinctrl *jh7110_from_irq_desc(struct irq_desc *desc);
++
++#endif /* __PINCTRL_STARFIVE_JH7110_H__ */

+ 224 - 0
target/linux/starfive/patches-6.1/0029-pinctrl-starfive-Add-StarFive-JH7110-aon-controller-.patch

@@ -0,0 +1,224 @@
+From 9c1a9d6dfd6a9c28794536c8af002746a20d840f Mon Sep 17 00:00:00 2001
+From: Jianlong Huang <[email protected]>
+Date: Thu, 9 Feb 2023 22:37:02 +0800
+Subject: [PATCH 029/122] pinctrl: starfive: Add StarFive JH7110 aon controller
+ driver
+
+Add pinctrl driver for StarFive JH7110 SoC aon pinctrl controller.
+
+Co-developed-by: Emil Renner Berthing <[email protected]>
+Signed-off-by: Emil Renner Berthing <[email protected]>
+Signed-off-by: Jianlong Huang <[email protected]>
+Signed-off-by: Hal Feng <[email protected]>
+---
+ drivers/pinctrl/starfive/Kconfig              |  12 ++
+ drivers/pinctrl/starfive/Makefile             |   1 +
+ .../starfive/pinctrl-starfive-jh7110-aon.c    | 177 ++++++++++++++++++
+ 3 files changed, 190 insertions(+)
+ create mode 100644 drivers/pinctrl/starfive/pinctrl-starfive-jh7110-aon.c
+
+--- a/drivers/pinctrl/starfive/Kconfig
++++ b/drivers/pinctrl/starfive/Kconfig
+@@ -37,3 +37,15 @@ config PINCTRL_STARFIVE_JH7110_SYS
+ 	  This also provides an interface to the GPIO pins not used by other
+ 	  peripherals supporting inputs, outputs, configuring pull-up/pull-down
+ 	  and interrupts on input changes.
++
++config PINCTRL_STARFIVE_JH7110_AON
++	tristate "Always-on pinctrl and GPIO driver for the StarFive JH7110 SoC"
++	depends on SOC_STARFIVE  || COMPILE_TEST
++	depends on OF
++	select PINCTRL_STARFIVE_JH7110
++	default SOC_STARFIVE
++	help
++	  Say yes here to support always-on pin control on the StarFive JH7110 SoC.
++	  This also provides an interface to the GPIO pins not used by other
++	  peripherals supporting inputs, outputs, configuring pull-up/pull-down
++	  and interrupts on input changes.
+--- a/drivers/pinctrl/starfive/Makefile
++++ b/drivers/pinctrl/starfive/Makefile
+@@ -4,3 +4,4 @@ obj-$(CONFIG_PINCTRL_STARFIVE_JH7100)	+=
+ 
+ obj-$(CONFIG_PINCTRL_STARFIVE_JH7110)		+= pinctrl-starfive-jh7110.o
+ obj-$(CONFIG_PINCTRL_STARFIVE_JH7110_SYS)	+= pinctrl-starfive-jh7110-sys.o
++obj-$(CONFIG_PINCTRL_STARFIVE_JH7110_AON)	+= pinctrl-starfive-jh7110-aon.o
+--- /dev/null
++++ b/drivers/pinctrl/starfive/pinctrl-starfive-jh7110-aon.c
+@@ -0,0 +1,177 @@
++// SPDX-License-Identifier: GPL-2.0
++/*
++ * Pinctrl / GPIO driver for StarFive JH7110 SoC aon controller
++ *
++ * Copyright (C) 2022 StarFive Technology Co., Ltd.
++ */
++
++#include <linux/err.h>
++#include <linux/gpio/driver.h>
++#include <linux/init.h>
++#include <linux/interrupt.h>
++#include <linux/io.h>
++#include <linux/module.h>
++#include <linux/of.h>
++#include <linux/of_device.h>
++#include <linux/of_irq.h>
++#include <linux/of_platform.h>
++#include <linux/pinctrl/pinconf.h>
++#include <linux/pinctrl/pinconf-generic.h>
++#include <linux/pinctrl/pinctrl.h>
++#include <linux/pinctrl/pinmux.h>
++#include <linux/platform_device.h>
++#include <linux/pm_runtime.h>
++#include <linux/regmap.h>
++#include <linux/slab.h>
++
++#include <dt-bindings/pinctrl/starfive,jh7110-pinctrl.h>
++
++#include "../core.h"
++#include "../pinconf.h"
++#include "../pinmux.h"
++#include "pinctrl-starfive-jh7110.h"
++
++#define JH7110_AON_NGPIO		4
++#define JH7110_AON_GC_BASE		64
++
++/* registers */
++#define JH7110_AON_DOEN			0x0
++#define JH7110_AON_DOUT			0x4
++#define JH7110_AON_GPI			0x8
++#define JH7110_AON_GPIOIN		0x2c
++
++#define JH7110_AON_GPIOEN		0xc
++#define JH7110_AON_GPIOIS		0x10
++#define JH7110_AON_GPIOIC		0x14
++#define JH7110_AON_GPIOIBE		0x18
++#define JH7110_AON_GPIOIEV		0x1c
++#define JH7110_AON_GPIOIE		0x20
++#define JH7110_AON_GPIORIS		0x28
++#define JH7110_AON_GPIOMIS		0x28
++
++#define JH7110_AON_GPO_PDA_0_5_CFG	0x30
++
++static const struct pinctrl_pin_desc jh7110_aon_pins[] = {
++	PINCTRL_PIN(PAD_TESTEN,		"TESTEN"),
++	PINCTRL_PIN(PAD_RGPIO0,		"RGPIO0"),
++	PINCTRL_PIN(PAD_RGPIO1,		"RGPIO1"),
++	PINCTRL_PIN(PAD_RGPIO2,		"RGPIO2"),
++	PINCTRL_PIN(PAD_RGPIO3,		"RGPIO3"),
++	PINCTRL_PIN(PAD_RSTN,		"RSTN"),
++	PINCTRL_PIN(PAD_GMAC0_MDC,	"GMAC0_MDC"),
++	PINCTRL_PIN(PAD_GMAC0_MDIO,	"GMAC0_MDIO"),
++	PINCTRL_PIN(PAD_GMAC0_RXD0,	"GMAC0_RXD0"),
++	PINCTRL_PIN(PAD_GMAC0_RXD1,	"GMAC0_RXD1"),
++	PINCTRL_PIN(PAD_GMAC0_RXD2,	"GMAC0_RXD2"),
++	PINCTRL_PIN(PAD_GMAC0_RXD3,	"GMAC0_RXD3"),
++	PINCTRL_PIN(PAD_GMAC0_RXDV,	"GMAC0_RXDV"),
++	PINCTRL_PIN(PAD_GMAC0_RXC,	"GMAC0_RXC"),
++	PINCTRL_PIN(PAD_GMAC0_TXD0,	"GMAC0_TXD0"),
++	PINCTRL_PIN(PAD_GMAC0_TXD1,	"GMAC0_TXD1"),
++	PINCTRL_PIN(PAD_GMAC0_TXD2,	"GMAC0_TXD2"),
++	PINCTRL_PIN(PAD_GMAC0_TXD3,	"GMAC0_TXD3"),
++	PINCTRL_PIN(PAD_GMAC0_TXEN,	"GMAC0_TXEN"),
++	PINCTRL_PIN(PAD_GMAC0_TXC,	"GMAC0_TXC"),
++};
++
++static int jh7110_aon_set_one_pin_mux(struct jh7110_pinctrl *sfp,
++				      unsigned int pin,
++				      unsigned int din, u32 dout,
++				      u32 doen, u32 func)
++{
++	if (pin < sfp->gc.ngpio && func == 0)
++		jh7110_set_gpiomux(sfp, pin, din, dout, doen);
++
++	return 0;
++}
++
++static int jh7110_aon_get_padcfg_base(struct jh7110_pinctrl *sfp,
++				      unsigned int pin)
++{
++	if (pin < PAD_GMAC0_MDC)
++		return JH7110_AON_GPO_PDA_0_5_CFG;
++
++	return -1;
++}
++
++static void jh7110_aon_irq_handler(struct irq_desc *desc)
++{
++	struct jh7110_pinctrl *sfp = jh7110_from_irq_desc(desc);
++	struct irq_chip *chip = irq_desc_get_chip(desc);
++	unsigned long mis;
++	unsigned int pin;
++
++	chained_irq_enter(chip, desc);
++
++	mis = readl_relaxed(sfp->base + JH7110_AON_GPIOMIS);
++	for_each_set_bit(pin, &mis, JH7110_AON_NGPIO)
++		generic_handle_domain_irq(sfp->gc.irq.domain, pin);
++
++	chained_irq_exit(chip, desc);
++}
++
++static int jh7110_aon_init_hw(struct gpio_chip *gc)
++{
++	struct jh7110_pinctrl *sfp = container_of(gc,
++			struct jh7110_pinctrl, gc);
++
++	/* mask all GPIO interrupts */
++	writel_relaxed(0, sfp->base + JH7110_AON_GPIOIE);
++	/* clear edge interrupt flags */
++	writel_relaxed(0, sfp->base + JH7110_AON_GPIOIC);
++	writel_relaxed(0x0f, sfp->base + JH7110_AON_GPIOIC);
++	/* enable GPIO interrupts */
++	writel_relaxed(1, sfp->base + JH7110_AON_GPIOEN);
++	return 0;
++}
++
++static const struct jh7110_gpio_irq_reg jh7110_aon_irq_reg = {
++	.is_reg_base	= JH7110_AON_GPIOIS,
++	.ic_reg_base	= JH7110_AON_GPIOIC,
++	.ibe_reg_base	= JH7110_AON_GPIOIBE,
++	.iev_reg_base	= JH7110_AON_GPIOIEV,
++	.ie_reg_base	= JH7110_AON_GPIOIE,
++	.ris_reg_base	= JH7110_AON_GPIORIS,
++	.mis_reg_base	= JH7110_AON_GPIOMIS,
++};
++
++static const struct jh7110_pinctrl_soc_info jh7110_aon_pinctrl_info = {
++	.pins		= jh7110_aon_pins,
++	.npins		= ARRAY_SIZE(jh7110_aon_pins),
++	.ngpios		= JH7110_AON_NGPIO,
++	.gc_base	= JH7110_AON_GC_BASE,
++	.dout_reg_base	= JH7110_AON_DOUT,
++	.dout_mask	= GENMASK(3, 0),
++	.doen_reg_base	= JH7110_AON_DOEN,
++	.doen_mask	= GENMASK(2, 0),
++	.gpi_reg_base	= JH7110_AON_GPI,
++	.gpi_mask	= GENMASK(3, 0),
++	.gpioin_reg_base	   = JH7110_AON_GPIOIN,
++	.irq_reg		   = &jh7110_aon_irq_reg,
++	.jh7110_set_one_pin_mux  = jh7110_aon_set_one_pin_mux,
++	.jh7110_get_padcfg_base  = jh7110_aon_get_padcfg_base,
++	.jh7110_gpio_irq_handler = jh7110_aon_irq_handler,
++	.jh7110_gpio_init_hw	 = jh7110_aon_init_hw,
++};
++
++static const struct of_device_id jh7110_aon_pinctrl_of_match[] = {
++	{
++		.compatible = "starfive,jh7110-aon-pinctrl",
++		.data = &jh7110_aon_pinctrl_info,
++	},
++	{ /* sentinel */ }
++};
++MODULE_DEVICE_TABLE(of, jh7110_aon_pinctrl_of_match);
++
++static struct platform_driver jh7110_aon_pinctrl_driver = {
++	.probe = jh7110_pinctrl_probe,
++	.driver = {
++		.name = "starfive-jh7110-aon-pinctrl",
++		.of_match_table = jh7110_aon_pinctrl_of_match,
++	},
++};
++module_platform_driver(jh7110_aon_pinctrl_driver);
++
++MODULE_DESCRIPTION("Pinctrl driver for the StarFive JH7110 SoC aon controller");
++MODULE_AUTHOR("Jianlong Huang <[email protected]>");
++MODULE_LICENSE("GPL");

+ 228 - 0
target/linux/starfive/patches-6.1/0030-config-add-jh7110-defconfig-for-test-mini.patch

@@ -0,0 +1,228 @@
+From 537ee9e5bb7b4ebee4ad5a607098c8200af6c261 Mon Sep 17 00:00:00 2001
+From: "shanlong.li" <[email protected]>
+Date: Thu, 18 May 2023 19:27:28 -0700
+Subject: [PATCH 030/122] config: add jh7110 defconfig for test mini
+
+add jh7110 defconfig for test mini
+
+Signed-off-by: shanlong.li <[email protected]>
+---
+ arch/riscv/configs/jh7110_defconfig | 212 ++++++++++++++++++++++++++++
+ 1 file changed, 212 insertions(+)
+ create mode 100755 arch/riscv/configs/jh7110_defconfig
+
+--- /dev/null
++++ b/arch/riscv/configs/jh7110_defconfig
+@@ -0,0 +1,212 @@
++CONFIG_WERROR=y
++CONFIG_SYSVIPC=y
++# CONFIG_CROSS_MEMORY_ATTACH is not set
++CONFIG_NO_HZ_IDLE=y
++CONFIG_HIGH_RES_TIMERS=y
++CONFIG_PSI=y
++# CONFIG_CPU_ISOLATION is not set
++CONFIG_IKCONFIG=y
++CONFIG_IKCONFIG_PROC=y
++CONFIG_CGROUPS=y
++CONFIG_CGROUP_SCHED=y
++CONFIG_CGROUP_PIDS=y
++CONFIG_CGROUP_CPUACCT=y
++CONFIG_NAMESPACES=y
++CONFIG_BLK_DEV_INITRD=y
++CONFIG_RD_GZIP=y
++# CONFIG_RD_BZIP2 is not set
++# CONFIG_RD_LZMA is not set
++# CONFIG_RD_XZ is not set
++# CONFIG_RD_LZO is not set
++# CONFIG_RD_LZ4 is not set
++CONFIG_EXPERT=y
++# CONFIG_SYSFS_SYSCALL is not set
++CONFIG_KCMP=y
++CONFIG_PERF_EVENTS=y
++CONFIG_ARCH_STARFIVE=y
++CONFIG_SOC_STARFIVE=y
++CONFIG_ERRATA_SIFIVE=y
++CONFIG_SMP=y
++# CONFIG_RISCV_ISA_SVPBMT is not set
++# CONFIG_COMPAT is not set
++CONFIG_CPU_IDLE=y
++CONFIG_RISCV_SBI_CPUIDLE=y
++CONFIG_JUMP_LABEL=y
++# CONFIG_STACKPROTECTOR is not set
++CONFIG_MODULES=y
++CONFIG_MODULE_UNLOAD=y
++CONFIG_MODULE_COMPRESS_ZSTD=y
++# CONFIG_BLOCK_LEGACY_AUTOLOAD is not set
++CONFIG_BLK_WBT=y
++# CONFIG_BLK_DEBUG_FS is not set
++CONFIG_PARTITION_ADVANCED=y
++# CONFIG_MQ_IOSCHED_DEADLINE is not set
++# CONFIG_MQ_IOSCHED_KYBER is not set
++CONFIG_IOSCHED_BFQ=y
++CONFIG_KSM=y
++# CONFIG_VM_EVENT_COUNTERS is not set
++CONFIG_NET=y
++CONFIG_PACKET=y
++CONFIG_UNIX=y
++CONFIG_INET=y
++CONFIG_IP_ADVANCED_ROUTER=y
++CONFIG_IP_MULTIPLE_TABLES=y
++CONFIG_INET_DIAG=m
++# CONFIG_IPV6_SIT is not set
++CONFIG_IPV6_MULTIPLE_TABLES=y
++# CONFIG_WIRELESS is not set
++# CONFIG_ETHTOOL_NETLINK is not set
++CONFIG_DEVTMPFS=y
++CONFIG_DEVTMPFS_MOUNT=y
++# CONFIG_STANDALONE is not set
++# CONFIG_PREVENT_FIRMWARE_BUILD is not set
++# CONFIG_FW_LOADER is not set
++CONFIG_EFI_DISABLE_RUNTIME=y
++CONFIG_ZRAM=y
++CONFIG_ZRAM_MEMORY_TRACKING=y
++CONFIG_BLK_DEV_LOOP=y
++CONFIG_BLK_DEV_LOOP_MIN_COUNT=1
++CONFIG_NETDEVICES=y
++CONFIG_STMMAC_ETH=y
++CONFIG_DWMAC_DWC_QOS_ETH=y
++# CONFIG_DWMAC_GENERIC is not set
++CONFIG_DWMAC_STARFIVE=y
++CONFIG_MICROCHIP_PHY=y
++CONFIG_MOTORCOMM_PHY=y
++# CONFIG_WLAN is not set
++# CONFIG_INPUT_KEYBOARD is not set
++# CONFIG_INPUT_MOUSE is not set
++# CONFIG_SERIO is not set
++# CONFIG_VT is not set
++# CONFIG_LEGACY_PTYS is not set
++# CONFIG_LDISC_AUTOLOAD is not set
++CONFIG_SERIAL_8250=y
++# CONFIG_SERIAL_8250_DEPRECATED_OPTIONS is not set
++# CONFIG_SERIAL_8250_16550A_VARIANTS is not set
++CONFIG_SERIAL_8250_CONSOLE=y
++CONFIG_SERIAL_8250_DW=y
++CONFIG_SERIAL_OF_PLATFORM=y
++# CONFIG_DEVMEM is not set
++# CONFIG_RANDOM_TRUST_BOOTLOADER is not set
++CONFIG_I2C=y
++# CONFIG_I2C_COMPAT is not set
++CONFIG_I2C_CHARDEV=y
++# CONFIG_I2C_HELPER_AUTO is not set
++CONFIG_I2C_DESIGNWARE_PLATFORM=y
++# CONFIG_PTP_1588_CLOCK is not set
++CONFIG_PINCTRL_STARFIVE_JH7110=y
++CONFIG_GPIOLIB_FASTPATH_LIMIT=128
++CONFIG_GPIO_SYSFS=y
++CONFIG_POWER_RESET=y
++CONFIG_POWER_RESET_GPIO_RESTART=y
++CONFIG_SENSORS_SFCTEMP=y
++# CONFIG_HID is not set
++CONFIG_MMC=y
++# CONFIG_PWRSEQ_EMMC is not set
++# CONFIG_PWRSEQ_SIMPLE is not set
++CONFIG_MMC_DW=y
++# CONFIG_VIRTIO_MENU is not set
++CONFIG_CLK_STARFIVE_JH7110_AON=y
++# CONFIG_VHOST_MENU is not set
++# CONFIG_IOMMU_SUPPORT is not set
++CONFIG_BTRFS_FS=y
++CONFIG_BTRFS_FS_POSIX_ACL=y
++# CONFIG_DNOTIFY is not set
++CONFIG_FANOTIFY=y
++CONFIG_AUTOFS_FS=y
++CONFIG_VFAT_FS=y
++CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-15"
++CONFIG_FAT_DEFAULT_UTF8=y
++CONFIG_PROC_KCORE=y
++CONFIG_PROC_CHILDREN=y
++CONFIG_TMPFS=y
++CONFIG_TMPFS_POSIX_ACL=y
++CONFIG_EFIVAR_FS=y
++# CONFIG_MISC_FILESYSTEMS is not set
++# CONFIG_NETWORK_FILESYSTEMS is not set
++CONFIG_NLS_DEFAULT="iso8859-15"
++CONFIG_NLS_CODEPAGE_437=y
++CONFIG_NLS_ISO8859_15=y
++CONFIG_LSM=""
++CONFIG_CRYPTO_ZSTD=y
++# CONFIG_RAID6_PQ_BENCHMARK is not set
++# CONFIG_DEBUG_MISC is not set
++CONFIG_STRIP_ASM_SYMS=y
++CONFIG_DEBUG_SECTION_MISMATCH=y
++# CONFIG_SECTION_MISMATCH_WARN_ONLY is not set
++CONFIG_DEBUG_FS=y
++# CONFIG_SLUB_DEBUG is not set
++CONFIG_PAGE_TABLE_CHECK=y
++CONFIG_DEBUG_RODATA_TEST=y
++CONFIG_DEBUG_WX=y
++CONFIG_SOFTLOCKUP_DETECTOR=y
++CONFIG_WQ_WATCHDOG=y
++# CONFIG_SCHED_DEBUG is not set
++CONFIG_STACKTRACE=y
++CONFIG_RCU_CPU_STALL_TIMEOUT=60
++# CONFIG_RCU_TRACE is not set
++# CONFIG_FTRACE is not set
++# CONFIG_RUNTIME_TESTING_MENU is not set
++CONFIG_EXT4_FS=y
++CONFIG_CPUFREQ_DT_PLATDEV=y
++CONFIG_CPUFREQ_DT=y
++CONFIG_CPU_FREQ=y
++CONFIG_HIBERNATION=y
++CONFIG_ARCH_HIBERNATION_POSSIBLE=y
++CONFIG_SWAP=y
++CONFIG_PCIE_STARFIVE=y
++CONFIG_PCI_MSI=y
++CONFIG_PCI=y
++CONFIG_USB_CDNS3_STARFIVE=y
++CONFIG_PHY_STARFIVE_JH7110_PCIE=y
++CONFIG_PHY_STARFIVE_JH7110_USB=y
++CONFIG_USB_CDNS_SUPPORT=y
++CONFIG_USB_CDNS3=y
++CONFIG_USB=y
++CONFIG_USB_SUPPORT=y
++CONFIG_VIDEO_STARFIVE_CAMSS=y
++CONFIG_VIDEO_CADENCE_CSI2RX=y
++CONFIG_VIDEO_DEV=y
++CONFIG_V4L_PLATFORM_DRIVERS=y
++CONFIG_MEDIA_PLATFORM_DRIVERS=y
++CONFIG_MEDIA_PLATFORM_SUPPORT=y
++CONFIG_MEDIA_SUPPORT=y
++CONFIG_PHY_STARFIVE_DPHY_RX=y
++CONFIG_CRYPTO_DEV_JH7110=y
++CONFIG_CRYPTO_HW=y
++CONFIG_CRYPTO=y
++CONFIG_SND_SOC_JH7110_TDM=y
++CONFIG_SND_SOC_STARFIVE=y
++CONFIG_SND_SOC=y
++CONFIG_SND=y
++CONFIG_SOUND=y
++CONFIG_DW_AXI_DMAC=y
++CONFIG_DMADEVICES=y
++CONFIG_HAS_IOMEM=y
++CONFIG_PWM_STARFIVE_PTC=y
++CONFIG_PWM=y
++CONFIG_STARFIVE_TIMER=y
++CONFIG_SECTION_MISMATCH_WARN_ONLY=y
++CONFIG_GENERIC_CLOCKEVENTS=y
++CONFIG_STARFIVE_WATCHDOG=y
++CONFIG_WATCHDOG=y
++CONFIG_HW_RANDOM_JH7110=y
++CONFIG_HW_RANDOM=y
++CONFIG_STMMAC_PLATFORM=y
++CONFIG_SPI_CADENCE_QUADSPI=y
++CONFIG_SPI_MASTER=y
++CONFIG_SPI=y
++CONFIG_MMC_DW_STARFIVE=y
++CONFIG_CLK_STARFIVE_JH7110_PLL=y
++CONFIG_CLK_STARFIVE_JH7110_VOUT=y
++CONFIG_CLK_STARFIVE_JH7110_ISP=y
++CONFIG_CLK_STARFIVE_JH7110_STG=y
++CONFIG_JH71XX_PMU=y
++CONFIG_PM=y
++CONFIG_PINCTRL_STARFIVE_JH7110_AON=y
++CONFIG_PINCTRL_STARFIVE_JH7110_SYS=y
++CONFIG_CLK_STARFIVE_JH7110_AON=y
++CONFIG_CLK_STARFIVE_JH7110_SYS=y
++CONFIG_SIFIVE_CCACHE=y
++CONFIG_CLINT_TIMER=y
++CONFIG_SIFIVE_PLIC=y

+ 80 - 0
target/linux/starfive/patches-6.1/0031-dt-bindings-clock-Add-StarFive-JH7110-PLL-clock-gene.patch

@@ -0,0 +1,80 @@
+From 07f62b08668c0295b1c6342f9708b7e36093ff59 Mon Sep 17 00:00:00 2001
+From: Xingyu Wu <[email protected]>
+Date: Tue, 21 Feb 2023 17:13:48 +0800
+Subject: [PATCH 031/122] dt-bindings: clock: Add StarFive JH7110 PLL clock
+ generator
+
+Add bindings for the PLL clock generator on the JH7110 RISC-V SoC.
+
+Reviewed-by: Krzysztof Kozlowski <[email protected]>
+Signed-off-by: Xingyu Wu <[email protected]>
+---
+ .../bindings/clock/starfive,jh7110-pll.yaml   | 46 +++++++++++++++++++
+ .../dt-bindings/clock/starfive,jh7110-crg.h   |  6 +++
+ 2 files changed, 52 insertions(+)
+ create mode 100644 Documentation/devicetree/bindings/clock/starfive,jh7110-pll.yaml
+
+--- /dev/null
++++ b/Documentation/devicetree/bindings/clock/starfive,jh7110-pll.yaml
+@@ -0,0 +1,46 @@
++# SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause
++%YAML 1.2
++---
++$id: http://devicetree.org/schemas/clock/starfive,jh7110-pll.yaml#
++$schema: http://devicetree.org/meta-schemas/core.yaml#
++
++title: StarFive JH7110 PLL Clock Generator
++
++description:
++  This PLL are high speed, low jitter frequency synthesizers in JH7110.
++  Each PLL clocks work in integer mode or fraction mode by some dividers,
++  and the configuration registers and dividers are set in several syscon
++  registers. So pll node should be a child of SYS-SYSCON node.
++  The formula for calculating frequency is that,
++  Fvco = Fref * (NI + NF) / M / Q1
++
++maintainers:
++  - Xingyu Wu <[email protected]>
++
++properties:
++  compatible:
++    const: starfive,jh7110-pll
++
++  clocks:
++    maxItems: 1
++    description: Main Oscillator (24 MHz)
++
++  '#clock-cells':
++    const: 1
++    description:
++      See <dt-bindings/clock/starfive,jh7110-crg.h> for valid indices.
++
++required:
++  - compatible
++  - clocks
++  - '#clock-cells'
++
++additionalProperties: false
++
++examples:
++  - |
++    pll-clock-controller {
++      compatible = "starfive,jh7110-pll";
++      clocks = <&osc>;
++      #clock-cells = <1>;
++    };
+--- a/include/dt-bindings/clock/starfive,jh7110-crg.h
++++ b/include/dt-bindings/clock/starfive,jh7110-crg.h
+@@ -6,6 +6,12 @@
+ #ifndef __DT_BINDINGS_CLOCK_STARFIVE_JH7110_CRG_H__
+ #define __DT_BINDINGS_CLOCK_STARFIVE_JH7110_CRG_H__
+ 
++/* PLL clocks */
++#define JH7110_CLK_PLL0_OUT			0
++#define JH7110_CLK_PLL1_OUT			1
++#define JH7110_CLK_PLL2_OUT			2
++#define JH7110_PLLCLK_END			3
++
+ /* SYSCRG clocks */
+ #define JH7110_SYSCLK_CPU_ROOT			0
+ #define JH7110_SYSCLK_CPU_CORE			1

+ 786 - 0
target/linux/starfive/patches-6.1/0032-clk-starfive-Add-StarFive-JH7110-PLL-clock-driver.patch

@@ -0,0 +1,786 @@
+From 0bc7aa28dcdee75a52b1874a02dfbf0107c2d448 Mon Sep 17 00:00:00 2001
+From: Xingyu Wu <[email protected]>
+Date: Fri, 17 Feb 2023 17:30:09 +0800
+Subject: [PATCH 032/122] clk: starfive: Add StarFive JH7110 PLL clock driver
+
+Add driver for the StarFive JH7110 PLL clock controller
+and they work by reading and setting syscon registers.
+
+Signed-off-by: Xingyu Wu <[email protected]>
+---
+ MAINTAINERS                                   |   6 +
+ drivers/clk/starfive/Kconfig                  |   8 +
+ drivers/clk/starfive/Makefile                 |   1 +
+ .../clk/starfive/clk-starfive-jh7110-pll.c    | 427 ++++++++++++++++++
+ .../clk/starfive/clk-starfive-jh7110-pll.h    | 293 ++++++++++++
+ 5 files changed, 735 insertions(+)
+ create mode 100644 drivers/clk/starfive/clk-starfive-jh7110-pll.c
+ create mode 100644 drivers/clk/starfive/clk-starfive-jh7110-pll.h
+
+--- a/MAINTAINERS
++++ b/MAINTAINERS
+@@ -19650,6 +19650,12 @@ M:	Emil Renner Berthing <[email protected]
+ S:	Maintained
+ F:	arch/riscv/boot/dts/starfive/
+ 
++STARFIVE JH7110 PLL CLOCK DRIVER
++M:	Xingyu Wu <[email protected]>
++S:	Supported
++F:	Documentation/devicetree/bindings/clock/starfive,jh7110-pll.yaml
++F:	drivers/clk/starfive/clk-starfive-jh7110-pll.*
++
+ STARFIVE JH71X0 CLOCK DRIVERS
+ M:	Emil Renner Berthing <[email protected]>
+ M:	Hal Feng <[email protected]>
+--- a/drivers/clk/starfive/Kconfig
++++ b/drivers/clk/starfive/Kconfig
+@@ -21,6 +21,14 @@ config CLK_STARFIVE_JH7100_AUDIO
+ 	  Say Y or M here to support the audio clocks on the StarFive JH7100
+ 	  SoC.
+ 
++config CLK_STARFIVE_JH7110_PLL
++	bool "StarFive JH7110 PLL clock support"
++	depends on ARCH_STARFIVE || COMPILE_TEST
++	default ARCH_STARFIVE
++	help
++	  Say yes here to support the PLL clock controller on the
++	  StarFive JH7110 SoC.
++
+ config CLK_STARFIVE_JH7110_SYS
+ 	bool "StarFive JH7110 system clock support"
+ 	depends on ARCH_STARFIVE || COMPILE_TEST
+--- a/drivers/clk/starfive/Makefile
++++ b/drivers/clk/starfive/Makefile
+@@ -4,5 +4,6 @@ obj-$(CONFIG_CLK_STARFIVE_JH71X0)	+= clk
+ obj-$(CONFIG_CLK_STARFIVE_JH7100)	+= clk-starfive-jh7100.o
+ obj-$(CONFIG_CLK_STARFIVE_JH7100_AUDIO)	+= clk-starfive-jh7100-audio.o
+ 
++obj-$(CONFIG_CLK_STARFIVE_JH7110_PLL)	+= clk-starfive-jh7110-pll.o
+ obj-$(CONFIG_CLK_STARFIVE_JH7110_SYS)	+= clk-starfive-jh7110-sys.o
+ obj-$(CONFIG_CLK_STARFIVE_JH7110_AON)	+= clk-starfive-jh7110-aon.o
+--- /dev/null
++++ b/drivers/clk/starfive/clk-starfive-jh7110-pll.c
+@@ -0,0 +1,427 @@
++// SPDX-License-Identifier: GPL-2.0
++/*
++ * StarFive JH7110 PLL Clock Generator Driver
++ *
++ * Copyright (C) 2023 StarFive Technology Co., Ltd.
++ *
++ * This driver is about to register JH7110 PLL clock generator and support ops.
++ * The JH7110 have three PLL clock, PLL0, PLL1 and PLL2.
++ * Each PLL clocks work in integer mode or fraction mode by some dividers,
++ * and the configuration registers and dividers are set in several syscon registers.
++ * The formula for calculating frequency is:
++ * Fvco = Fref * (NI + NF) / M / Q1
++ * Fref: OSC source clock rate
++ * NI: integer frequency dividing ratio of feedback divider, set by fbdiv[11:0].
++ * NF: fractional frequency dividing ratio, set by frac[23:0]. NF = frac[23:0] / 2^24 = 0 ~ 0.999.
++ * M: frequency dividing ratio of pre-divider, set by prediv[5:0].
++ * Q1: frequency dividing ratio of post divider, set by postdiv1[1:0], Q1= 1,2,4,8.
++ */
++
++#include <linux/clk-provider.h>
++#include <linux/debugfs.h>
++#include <linux/device.h>
++#include <linux/kernel.h>
++#include <linux/mfd/syscon.h>
++#include <linux/platform_device.h>
++#include <linux/regmap.h>
++
++#include <dt-bindings/clock/starfive,jh7110-crg.h>
++
++#include "clk-starfive-jh7110-pll.h"
++
++static struct jh7110_clk_pll_data *jh7110_pll_data_from(struct clk_hw *hw)
++{
++	return container_of(hw, struct jh7110_clk_pll_data, hw);
++}
++
++static struct jh7110_clk_pll_priv *jh7110_pll_priv_from(struct jh7110_clk_pll_data *data)
++{
++	return container_of(data, struct jh7110_clk_pll_priv, data[data->idx]);
++}
++
++/* Read register value from syscon and calculate PLL(x) frequency */
++static unsigned long jh7110_pll_get_freq(struct jh7110_clk_pll_data *data,
++					 unsigned long parent_rate)
++{
++	struct jh7110_clk_pll_priv *priv = jh7110_pll_priv_from(data);
++	struct jh7110_pll_syscon_offset *offset = &data->offset;
++	struct jh7110_pll_syscon_mask *mask = &data->mask;
++	struct jh7110_pll_syscon_shift *shift = &data->shift;
++	unsigned long freq = 0;
++	unsigned long frac_cal;
++	u32 dacpd;
++	u32 dsmpd;
++	u32 fbdiv;
++	u32 prediv;
++	u32 postdiv1;
++	u32 frac;
++	u32 reg_val;
++
++	if (regmap_read(priv->syscon_regmap, offset->dacpd, &reg_val))
++		goto read_error;
++	dacpd = (reg_val & mask->dacpd) >> shift->dacpd;
++
++	if (regmap_read(priv->syscon_regmap, offset->dsmpd, &reg_val))
++		goto read_error;
++	dsmpd = (reg_val & mask->dsmpd) >> shift->dsmpd;
++
++	if (regmap_read(priv->syscon_regmap, offset->fbdiv, &reg_val))
++		goto read_error;
++	fbdiv = (reg_val & mask->fbdiv) >> shift->fbdiv;
++	/* fbdiv value should be 8 to 4095 */
++	if (fbdiv < 8)
++		goto read_error;
++
++	if (regmap_read(priv->syscon_regmap, offset->prediv, &reg_val))
++		goto read_error;
++	prediv = (reg_val & mask->prediv) >> shift->prediv;
++
++	if (regmap_read(priv->syscon_regmap, offset->postdiv1, &reg_val))
++		goto read_error;
++	/* postdiv1 = 2 ^ reg_val */
++	postdiv1 = 1 << ((reg_val & mask->postdiv1) >> shift->postdiv1);
++
++	if (regmap_read(priv->syscon_regmap, offset->frac, &reg_val))
++		goto read_error;
++	frac = (reg_val & mask->frac) >> shift->frac;
++
++	/*
++	 * Integer Mode (Both 1) or Fraction Mode (Both 0).
++	 * And the decimal places are counted by expanding them by
++	 * a factor of STARFIVE_PLL_FRAC_PATR_SIZE.
++	 */
++	if (dacpd == 1 && dsmpd == 1)
++		frac_cal = 0;
++	else if (dacpd == 0 && dsmpd == 0)
++		frac_cal = (unsigned long)frac * STARFIVE_PLL_FRAC_PATR_SIZE / (1 << 24);
++	else
++		goto read_error;
++
++	/* Fvco = Fref * (NI + NF) / M / Q1 */
++	freq = parent_rate / STARFIVE_PLL_FRAC_PATR_SIZE *
++	       (fbdiv * STARFIVE_PLL_FRAC_PATR_SIZE + frac_cal) / prediv / postdiv1;
++
++read_error:
++	return freq;
++}
++
++static unsigned long jh7110_pll_rate_sub_fabs(unsigned long rate1, unsigned long rate2)
++{
++	return rate1 > rate2 ? (rate1 - rate2) : (rate2 - rate1);
++}
++
++/* Select the appropriate frequency from the already configured registers value */
++static void jh7110_pll_select_near_freq_id(struct jh7110_clk_pll_data *data,
++					   unsigned long rate)
++{
++	const struct starfive_pll_syscon_value *syscon_val;
++	unsigned int id;
++	unsigned int pll_arry_size;
++	unsigned long rate_diff;
++
++	if (data->idx == JH7110_CLK_PLL0_OUT)
++		pll_arry_size = ARRAY_SIZE(jh7110_pll0_syscon_freq);
++	else if (data->idx == JH7110_CLK_PLL1_OUT)
++		pll_arry_size = ARRAY_SIZE(jh7110_pll1_syscon_freq);
++	else
++		pll_arry_size = ARRAY_SIZE(jh7110_pll2_syscon_freq);
++
++	/* compare the frequency one by one from small to large in order */
++	for (id = 0; id < pll_arry_size; id++) {
++		if (data->idx == JH7110_CLK_PLL0_OUT)
++			syscon_val = &jh7110_pll0_syscon_freq[id];
++		else if (data->idx == JH7110_CLK_PLL1_OUT)
++			syscon_val = &jh7110_pll1_syscon_freq[id];
++		else
++			syscon_val = &jh7110_pll2_syscon_freq[id];
++
++		if (rate == syscon_val->freq)
++			goto match_end;
++
++		/* select near frequency */
++		if (rate < syscon_val->freq) {
++			/* The last frequency is closer to the target rate than this time. */
++			if (id > 0)
++				if (rate_diff < jh7110_pll_rate_sub_fabs(rate, syscon_val->freq))
++					id--;
++
++			goto match_end;
++		} else {
++			rate_diff = jh7110_pll_rate_sub_fabs(rate, syscon_val->freq);
++		}
++	}
++
++match_end:
++	data->freq_select_idx = id;
++}
++
++static int jh7110_pll_set_freq_syscon(struct jh7110_clk_pll_data *data)
++{
++	struct jh7110_clk_pll_priv *priv = jh7110_pll_priv_from(data);
++	struct jh7110_pll_syscon_offset *offset = &data->offset;
++	struct jh7110_pll_syscon_mask *mask = &data->mask;
++	struct jh7110_pll_syscon_shift *shift = &data->shift;
++	unsigned int freq_idx = data->freq_select_idx;
++	const struct starfive_pll_syscon_value *syscon_val;
++	int ret;
++
++	if (data->idx == JH7110_CLK_PLL0_OUT)
++		syscon_val = &jh7110_pll0_syscon_freq[freq_idx];
++	else if (data->idx == JH7110_CLK_PLL1_OUT)
++		syscon_val = &jh7110_pll1_syscon_freq[freq_idx];
++	else
++		syscon_val = &jh7110_pll2_syscon_freq[freq_idx];
++
++	ret = regmap_update_bits(priv->syscon_regmap, offset->dacpd, mask->dacpd,
++				 (syscon_val->dacpd << shift->dacpd));
++	if (ret)
++		goto set_failed;
++
++	ret = regmap_update_bits(priv->syscon_regmap, offset->dsmpd, mask->dsmpd,
++				 (syscon_val->dsmpd << shift->dsmpd));
++	if (ret)
++		goto set_failed;
++
++	ret = regmap_update_bits(priv->syscon_regmap, offset->prediv, mask->prediv,
++				 (syscon_val->prediv << shift->prediv));
++	if (ret)
++		goto set_failed;
++
++	ret = regmap_update_bits(priv->syscon_regmap, offset->fbdiv, mask->fbdiv,
++				 (syscon_val->fbdiv << shift->fbdiv));
++	if (ret)
++		goto set_failed;
++
++	ret = regmap_update_bits(priv->syscon_regmap, offset->postdiv1, mask->postdiv1,
++				 ((syscon_val->postdiv1 >> 1) << shift->postdiv1));
++	if (ret)
++		goto set_failed;
++
++	/* frac: Integer Mode (Both 1) or Fraction Mode (Both 0) */
++	if (syscon_val->dacpd == 0 && syscon_val->dsmpd == 0)
++		ret = regmap_update_bits(priv->syscon_regmap, offset->frac, mask->frac,
++					 (syscon_val->frac << shift->frac));
++	else if (syscon_val->dacpd != syscon_val->dsmpd)
++		ret = -EINVAL;
++
++set_failed:
++	return ret;
++}
++
++static unsigned long jh7110_pll_recalc_rate(struct clk_hw *hw, unsigned long parent_rate)
++{
++	struct jh7110_clk_pll_data *data = jh7110_pll_data_from(hw);
++
++	return jh7110_pll_get_freq(data, parent_rate);
++}
++
++static int jh7110_pll_determine_rate(struct clk_hw *hw, struct clk_rate_request *req)
++{
++	struct jh7110_clk_pll_data *data = jh7110_pll_data_from(hw);
++
++	jh7110_pll_select_near_freq_id(data, req->rate);
++
++	if (data->idx == JH7110_CLK_PLL0_OUT)
++		req->rate = jh7110_pll0_syscon_freq[data->freq_select_idx].freq;
++	else if (data->idx == JH7110_CLK_PLL1_OUT)
++		req->rate = jh7110_pll1_syscon_freq[data->freq_select_idx].freq;
++	else
++		req->rate = jh7110_pll2_syscon_freq[data->freq_select_idx].freq;
++
++	return 0;
++}
++
++static int jh7110_pll_set_rate(struct clk_hw *hw, unsigned long rate,
++			       unsigned long parent_rate)
++{
++	struct jh7110_clk_pll_data *data = jh7110_pll_data_from(hw);
++
++	return jh7110_pll_set_freq_syscon(data);
++}
++
++#ifdef CONFIG_DEBUG_FS
++static void jh7110_pll_debug_init(struct clk_hw *hw, struct dentry *dentry)
++{
++	static const struct debugfs_reg32 jh7110_clk_pll_reg = {
++		.name = "CTRL",
++		.offset = 0,
++	};
++	struct jh7110_clk_pll_data *data = jh7110_pll_data_from(hw);
++	struct jh7110_clk_pll_priv *priv = jh7110_pll_priv_from(data);
++	struct debugfs_regset32 *regset;
++
++	regset = devm_kzalloc(priv->dev, sizeof(*regset), GFP_KERNEL);
++	if (!regset)
++		return;
++
++	regset->regs = &jh7110_clk_pll_reg;
++	regset->nregs = 1;
++
++	debugfs_create_regset32("registers", 0400, dentry, regset);
++}
++#else
++#define jh7110_pll_debug_init NULL
++#endif
++
++static const struct clk_ops jh7110_pll_ops = {
++	.recalc_rate = jh7110_pll_recalc_rate,
++	.determine_rate = jh7110_pll_determine_rate,
++	.set_rate = jh7110_pll_set_rate,
++	.debug_init = jh7110_pll_debug_init,
++};
++
++/* get offset, mask and shift of PLL(x) syscon */
++static int jh7110_pll_data_get(struct jh7110_clk_pll_data *data, int index)
++{
++	struct jh7110_pll_syscon_offset *offset = &data->offset;
++	struct jh7110_pll_syscon_mask *mask = &data->mask;
++	struct jh7110_pll_syscon_shift *shift = &data->shift;
++
++	if (index == JH7110_CLK_PLL0_OUT) {
++		offset->dacpd = STARFIVE_JH7110_PLL0_DACPD_OFFSET;
++		offset->dsmpd = STARFIVE_JH7110_PLL0_DSMPD_OFFSET;
++		offset->fbdiv = STARFIVE_JH7110_PLL0_FBDIV_OFFSET;
++		offset->frac = STARFIVE_JH7110_PLL0_FRAC_OFFSET;
++		offset->prediv = STARFIVE_JH7110_PLL0_PREDIV_OFFSET;
++		offset->postdiv1 = STARFIVE_JH7110_PLL0_POSTDIV1_OFFSET;
++
++		mask->dacpd = STARFIVE_JH7110_PLL0_DACPD_MASK;
++		mask->dsmpd = STARFIVE_JH7110_PLL0_DSMPD_MASK;
++		mask->fbdiv = STARFIVE_JH7110_PLL0_FBDIV_MASK;
++		mask->frac = STARFIVE_JH7110_PLL0_FRAC_MASK;
++		mask->prediv = STARFIVE_JH7110_PLL0_PREDIV_MASK;
++		mask->postdiv1 = STARFIVE_JH7110_PLL0_POSTDIV1_MASK;
++
++		shift->dacpd = STARFIVE_JH7110_PLL0_DACPD_SHIFT;
++		shift->dsmpd = STARFIVE_JH7110_PLL0_DSMPD_SHIFT;
++		shift->fbdiv = STARFIVE_JH7110_PLL0_FBDIV_SHIFT;
++		shift->frac = STARFIVE_JH7110_PLL0_FRAC_SHIFT;
++		shift->prediv = STARFIVE_JH7110_PLL0_PREDIV_SHIFT;
++		shift->postdiv1 = STARFIVE_JH7110_PLL0_POSTDIV1_SHIFT;
++
++	} else if (index == JH7110_CLK_PLL1_OUT) {
++		offset->dacpd = STARFIVE_JH7110_PLL1_DACPD_OFFSET;
++		offset->dsmpd = STARFIVE_JH7110_PLL1_DSMPD_OFFSET;
++		offset->fbdiv = STARFIVE_JH7110_PLL1_FBDIV_OFFSET;
++		offset->frac = STARFIVE_JH7110_PLL1_FRAC_OFFSET;
++		offset->prediv = STARFIVE_JH7110_PLL1_PREDIV_OFFSET;
++		offset->postdiv1 = STARFIVE_JH7110_PLL1_POSTDIV1_OFFSET;
++
++		mask->dacpd = STARFIVE_JH7110_PLL1_DACPD_MASK;
++		mask->dsmpd = STARFIVE_JH7110_PLL1_DSMPD_MASK;
++		mask->fbdiv = STARFIVE_JH7110_PLL1_FBDIV_MASK;
++		mask->frac = STARFIVE_JH7110_PLL1_FRAC_MASK;
++		mask->prediv = STARFIVE_JH7110_PLL1_PREDIV_MASK;
++		mask->postdiv1 = STARFIVE_JH7110_PLL1_POSTDIV1_MASK;
++
++		shift->dacpd = STARFIVE_JH7110_PLL1_DACPD_SHIFT;
++		shift->dsmpd = STARFIVE_JH7110_PLL1_DSMPD_SHIFT;
++		shift->fbdiv = STARFIVE_JH7110_PLL1_FBDIV_SHIFT;
++		shift->frac = STARFIVE_JH7110_PLL1_FRAC_SHIFT;
++		shift->prediv = STARFIVE_JH7110_PLL1_PREDIV_SHIFT;
++		shift->postdiv1 = STARFIVE_JH7110_PLL1_POSTDIV1_SHIFT;
++
++	} else if (index == JH7110_CLK_PLL2_OUT) {
++		offset->dacpd = STARFIVE_JH7110_PLL2_DACPD_OFFSET;
++		offset->dsmpd = STARFIVE_JH7110_PLL2_DSMPD_OFFSET;
++		offset->fbdiv = STARFIVE_JH7110_PLL2_FBDIV_OFFSET;
++		offset->frac = STARFIVE_JH7110_PLL2_FRAC_OFFSET;
++		offset->prediv = STARFIVE_JH7110_PLL2_PREDIV_OFFSET;
++		offset->postdiv1 = STARFIVE_JH7110_PLL2_POSTDIV1_OFFSET;
++
++		mask->dacpd = STARFIVE_JH7110_PLL2_DACPD_MASK;
++		mask->dsmpd = STARFIVE_JH7110_PLL2_DSMPD_MASK;
++		mask->fbdiv = STARFIVE_JH7110_PLL2_FBDIV_MASK;
++		mask->frac = STARFIVE_JH7110_PLL2_FRAC_MASK;
++		mask->prediv = STARFIVE_JH7110_PLL2_PREDIV_MASK;
++		mask->postdiv1 = STARFIVE_JH7110_PLL2_POSTDIV1_MASK;
++
++		shift->dacpd = STARFIVE_JH7110_PLL2_DACPD_SHIFT;
++		shift->dsmpd = STARFIVE_JH7110_PLL2_DSMPD_SHIFT;
++		shift->fbdiv = STARFIVE_JH7110_PLL2_FBDIV_SHIFT;
++		shift->frac = STARFIVE_JH7110_PLL2_FRAC_SHIFT;
++		shift->prediv = STARFIVE_JH7110_PLL2_PREDIV_SHIFT;
++		shift->postdiv1 = STARFIVE_JH7110_PLL2_POSTDIV1_SHIFT;
++
++	} else {
++		return -ENOENT;
++	}
++
++	return 0;
++}
++
++static struct clk_hw *jh7110_pll_get(struct of_phandle_args *clkspec, void *data)
++{
++	struct jh7110_clk_pll_priv *priv = data;
++	unsigned int idx = clkspec->args[0];
++
++	if (idx < JH7110_PLLCLK_END)
++		return &priv->data[idx].hw;
++
++	return ERR_PTR(-EINVAL);
++}
++
++static int jh7110_pll_probe(struct platform_device *pdev)
++{
++	const char *pll_name[JH7110_PLLCLK_END] = {
++		"pll0_out",
++		"pll1_out",
++		"pll2_out"
++	};
++	struct jh7110_clk_pll_priv *priv;
++	struct jh7110_clk_pll_data *data;
++	int ret;
++	unsigned int idx;
++
++	priv = devm_kzalloc(&pdev->dev, struct_size(priv, data, JH7110_PLLCLK_END),
++			    GFP_KERNEL);
++	if (!priv)
++		return -ENOMEM;
++
++	priv->dev = &pdev->dev;
++	priv->syscon_regmap = syscon_node_to_regmap(priv->dev->of_node->parent);
++	if (IS_ERR(priv->syscon_regmap))
++		return PTR_ERR(priv->syscon_regmap);
++
++	for (idx = 0; idx < JH7110_PLLCLK_END; idx++) {
++		struct clk_parent_data parents = {
++			.index = 0,
++		};
++		struct clk_init_data init = {
++			.name = pll_name[idx],
++			.ops = &jh7110_pll_ops,
++			.parent_data = &parents,
++			.num_parents = 1,
++			.flags = 0,
++		};
++
++		data = &priv->data[idx];
++
++		ret = jh7110_pll_data_get(data, idx);
++		if (ret)
++			return ret;
++
++		data->hw.init = &init;
++		data->idx = idx;
++
++		ret = devm_clk_hw_register(&pdev->dev, &data->hw);
++		if (ret)
++			return ret;
++	}
++
++	return devm_of_clk_add_hw_provider(&pdev->dev, jh7110_pll_get, priv);
++}
++
++static const struct of_device_id jh7110_pll_match[] = {
++	{ .compatible = "starfive,jh7110-pll" },
++	{ /* sentinel */ }
++};
++MODULE_DEVICE_TABLE(of, jh7110_pll_match);
++
++static struct platform_driver jh7110_pll_driver = {
++	.driver = {
++		.name = "clk-starfive-jh7110-pll",
++		.of_match_table = jh7110_pll_match,
++	},
++};
++builtin_platform_driver_probe(jh7110_pll_driver, jh7110_pll_probe);
+--- /dev/null
++++ b/drivers/clk/starfive/clk-starfive-jh7110-pll.h
+@@ -0,0 +1,293 @@
++/* SPDX-License-Identifier: GPL-2.0 OR MIT */
++/*
++ * StarFive JH7110 PLL Clock Generator Driver
++ *
++ * Copyright (C) 2023 StarFive Technology Co., Ltd.
++ */
++
++#ifndef _CLK_STARFIVE_JH7110_PLL_H_
++#define _CLK_STARFIVE_JH7110_PLL_H_
++
++#include <linux/bits.h>
++
++/* The decimal places are counted by expanding them by a factor of STARFIVE_PLL_FRAC_PATR_SIZE */
++#define STARFIVE_PLL_FRAC_PATR_SIZE		1000
++
++#define STARFIVE_JH7110_PLL0_DACPD_OFFSET	0x18
++#define STARFIVE_JH7110_PLL0_DACPD_SHIFT	24
++#define STARFIVE_JH7110_PLL0_DACPD_MASK		BIT(24)
++#define STARFIVE_JH7110_PLL0_DSMPD_OFFSET	0x18
++#define STARFIVE_JH7110_PLL0_DSMPD_SHIFT	25
++#define STARFIVE_JH7110_PLL0_DSMPD_MASK		BIT(25)
++#define STARFIVE_JH7110_PLL0_FBDIV_OFFSET	0x1c
++#define STARFIVE_JH7110_PLL0_FBDIV_SHIFT	0
++#define STARFIVE_JH7110_PLL0_FBDIV_MASK		GENMASK(11, 0)
++#define STARFIVE_JH7110_PLL0_FRAC_OFFSET	0x20
++#define STARFIVE_JH7110_PLL0_FRAC_SHIFT		0
++#define STARFIVE_JH7110_PLL0_FRAC_MASK		GENMASK(23, 0)
++#define STARFIVE_JH7110_PLL0_POSTDIV1_OFFSET	0x20
++#define STARFIVE_JH7110_PLL0_POSTDIV1_SHIFT	28
++#define STARFIVE_JH7110_PLL0_POSTDIV1_MASK	GENMASK(29, 28)
++#define STARFIVE_JH7110_PLL0_PREDIV_OFFSET	0x24
++#define STARFIVE_JH7110_PLL0_PREDIV_SHIFT	0
++#define STARFIVE_JH7110_PLL0_PREDIV_MASK	GENMASK(5, 0)
++
++#define STARFIVE_JH7110_PLL1_DACPD_OFFSET	0x24
++#define STARFIVE_JH7110_PLL1_DACPD_SHIFT	15
++#define STARFIVE_JH7110_PLL1_DACPD_MASK		BIT(15)
++#define STARFIVE_JH7110_PLL1_DSMPD_OFFSET	0x24
++#define STARFIVE_JH7110_PLL1_DSMPD_SHIFT	16
++#define STARFIVE_JH7110_PLL1_DSMPD_MASK		BIT(16)
++#define STARFIVE_JH7110_PLL1_FBDIV_OFFSET	0x24
++#define STARFIVE_JH7110_PLL1_FBDIV_SHIFT	17
++#define STARFIVE_JH7110_PLL1_FBDIV_MASK		GENMASK(28, 17)
++#define STARFIVE_JH7110_PLL1_FRAC_OFFSET	0x28
++#define STARFIVE_JH7110_PLL1_FRAC_SHIFT		0
++#define STARFIVE_JH7110_PLL1_FRAC_MASK		GENMASK(23, 0)
++#define STARFIVE_JH7110_PLL1_POSTDIV1_OFFSET	0x28
++#define STARFIVE_JH7110_PLL1_POSTDIV1_SHIFT	28
++#define STARFIVE_JH7110_PLL1_POSTDIV1_MASK	GENMASK(29, 28)
++#define STARFIVE_JH7110_PLL1_PREDIV_OFFSET	0x2c
++#define STARFIVE_JH7110_PLL1_PREDIV_SHIFT	0
++#define STARFIVE_JH7110_PLL1_PREDIV_MASK	GENMASK(5, 0)
++
++#define STARFIVE_JH7110_PLL2_DACPD_OFFSET	0x2c
++#define STARFIVE_JH7110_PLL2_DACPD_SHIFT	15
++#define STARFIVE_JH7110_PLL2_DACPD_MASK		BIT(15)
++#define STARFIVE_JH7110_PLL2_DSMPD_OFFSET	0x2c
++#define STARFIVE_JH7110_PLL2_DSMPD_SHIFT	16
++#define STARFIVE_JH7110_PLL2_DSMPD_MASK		BIT(16)
++#define STARFIVE_JH7110_PLL2_FBDIV_OFFSET	0x2c
++#define STARFIVE_JH7110_PLL2_FBDIV_SHIFT	17
++#define STARFIVE_JH7110_PLL2_FBDIV_MASK		GENMASK(28, 17)
++#define STARFIVE_JH7110_PLL2_FRAC_OFFSET	0x30
++#define STARFIVE_JH7110_PLL2_FRAC_SHIFT		0
++#define STARFIVE_JH7110_PLL2_FRAC_MASK		GENMASK(23, 0)
++#define STARFIVE_JH7110_PLL2_POSTDIV1_OFFSET	0x30
++#define STARFIVE_JH7110_PLL2_POSTDIV1_SHIFT	28
++#define STARFIVE_JH7110_PLL2_POSTDIV1_MASK	GENMASK(29, 28)
++#define STARFIVE_JH7110_PLL2_PREDIV_OFFSET	0x34
++#define STARFIVE_JH7110_PLL2_PREDIV_SHIFT	0
++#define STARFIVE_JH7110_PLL2_PREDIV_MASK	GENMASK(5, 0)
++
++struct jh7110_pll_syscon_offset {
++	unsigned int dacpd;
++	unsigned int dsmpd;
++	unsigned int fbdiv;
++	unsigned int frac;
++	unsigned int prediv;
++	unsigned int postdiv1;
++};
++
++struct jh7110_pll_syscon_mask {
++	u32 dacpd;
++	u32 dsmpd;
++	u32 fbdiv;
++	u32 frac;
++	u32 prediv;
++	u32 postdiv1;
++};
++
++struct jh7110_pll_syscon_shift {
++	char dacpd;
++	char dsmpd;
++	char fbdiv;
++	char frac;
++	char prediv;
++	char postdiv1;
++};
++
++struct jh7110_clk_pll_data {
++	struct clk_hw hw;
++	unsigned int idx;
++	unsigned int freq_select_idx;
++
++	struct jh7110_pll_syscon_offset offset;
++	struct jh7110_pll_syscon_mask mask;
++	struct jh7110_pll_syscon_shift shift;
++};
++
++struct jh7110_clk_pll_priv {
++	struct device *dev;
++	struct regmap *syscon_regmap;
++	struct jh7110_clk_pll_data data[];
++};
++
++struct starfive_pll_syscon_value {
++	unsigned long freq;
++	u32 prediv;
++	u32 fbdiv;
++	u32 postdiv1;
++/* Both daxpd and dsmpd set 1 while integer mode */
++/* Both daxpd and dsmpd set 0 while fraction mode */
++	u32 dacpd;
++	u32 dsmpd;
++/* frac value should be decimals multiplied by 2^24 */
++	u32 frac;
++};
++
++enum starfive_pll0_freq_index {
++	PLL0_FREQ_375 = 0,
++	PLL0_FREQ_500,
++	PLL0_FREQ_625,
++	PLL0_FREQ_750,
++	PLL0_FREQ_875,
++	PLL0_FREQ_1000,
++	PLL0_FREQ_1250,
++	PLL0_FREQ_1375,
++	PLL0_FREQ_1500,
++	PLL0_FREQ_MAX
++};
++
++enum starfive_pll1_freq_index {
++	PLL1_FREQ_1066 = 0,
++	PLL1_FREQ_1200,
++	PLL1_FREQ_1400,
++	PLL1_FREQ_1600,
++	PLL1_FREQ_MAX
++};
++
++enum starfive_pll2_freq_index {
++	PLL2_FREQ_1188 = 0,
++	PLL2_FREQ_12288,
++	PLL2_FREQ_MAX
++};
++
++/*
++ * Because the pll frequency is relatively fixed,
++ * it cannot be set arbitrarily, so it needs a specific configuration.
++ * PLL0 frequency should be multiple of 125MHz (USB frequency).
++ */
++static const struct starfive_pll_syscon_value
++	jh7110_pll0_syscon_freq[PLL0_FREQ_MAX] = {
++	[PLL0_FREQ_375] = {
++		.freq = 375000000,
++		.prediv = 8,
++		.fbdiv = 125,
++		.postdiv1 = 1,
++		.dacpd = 1,
++		.dsmpd = 1,
++	},
++	[PLL0_FREQ_500] = {
++		.freq = 500000000,
++		.prediv = 6,
++		.fbdiv = 125,
++		.postdiv1 = 1,
++		.dacpd = 1,
++		.dsmpd = 1,
++	},
++	[PLL0_FREQ_625] = {
++		.freq = 625000000,
++		.prediv = 24,
++		.fbdiv = 625,
++		.postdiv1 = 1,
++		.dacpd = 1,
++		.dsmpd = 1,
++	},
++	[PLL0_FREQ_750] = {
++		.freq = 750000000,
++		.prediv = 4,
++		.fbdiv = 125,
++		.postdiv1 = 1,
++		.dacpd = 1,
++		.dsmpd = 1,
++	},
++	[PLL0_FREQ_875] = {
++		.freq = 875000000,
++		.prediv = 24,
++		.fbdiv = 875,
++		.postdiv1 = 1,
++		.dacpd = 1,
++		.dsmpd = 1,
++	},
++	[PLL0_FREQ_1000] = {
++		.freq = 1000000000,
++		.prediv = 3,
++		.fbdiv = 125,
++		.postdiv1 = 1,
++		.dacpd = 1,
++		.dsmpd = 1,
++	},
++	[PLL0_FREQ_1250] = {
++		.freq = 1250000000,
++		.prediv = 12,
++		.fbdiv = 625,
++		.postdiv1 = 1,
++		.dacpd = 1,
++		.dsmpd = 1,
++	},
++	[PLL0_FREQ_1375] = {
++		.freq = 1375000000,
++		.prediv = 24,
++		.fbdiv = 1375,
++		.postdiv1 = 1,
++		.dacpd = 1,
++		.dsmpd = 1,
++	},
++	[PLL0_FREQ_1500] = {
++		.freq = 1500000000,
++		.prediv = 2,
++		.fbdiv = 125,
++		.postdiv1 = 1,
++		.dacpd = 1,
++		.dsmpd = 1,
++	},
++};
++
++static const struct starfive_pll_syscon_value
++	jh7110_pll1_syscon_freq[PLL1_FREQ_MAX] = {
++	[PLL1_FREQ_1066] = {
++		.freq = 1066000000,
++		.prediv = 12,
++		.fbdiv = 533,
++		.postdiv1 = 1,
++		.dacpd = 1,
++		.dsmpd = 1,
++	},
++	[PLL1_FREQ_1200] = {
++		.freq = 1200000000,
++		.prediv = 1,
++		.fbdiv = 50,
++		.postdiv1 = 1,
++		.dacpd = 1,
++		.dsmpd = 1,
++	},
++	[PLL1_FREQ_1400] = {
++		.freq = 1400000000,
++		.prediv = 6,
++		.fbdiv = 350,
++		.postdiv1 = 1,
++		.dacpd = 1,
++		.dsmpd = 1,
++	},
++	[PLL1_FREQ_1600] = {
++		.freq = 1600000000,
++		.prediv = 3,
++		.fbdiv = 200,
++		.postdiv1 = 1,
++		.dacpd = 1,
++		.dsmpd = 1,
++	},
++};
++
++static const struct starfive_pll_syscon_value
++	jh7110_pll2_syscon_freq[PLL2_FREQ_MAX] = {
++	[PLL2_FREQ_1188] = {
++		.freq = 1188000000,
++		.prediv = 2,
++		.fbdiv = 99,
++		.postdiv1 = 1,
++		.dacpd = 1,
++		.dsmpd = 1,
++	},
++	[PLL2_FREQ_12288] = {
++		.freq = 1228800000,
++		.prediv = 5,
++		.fbdiv = 256,
++		.postdiv1 = 1,
++		.dacpd = 1,
++		.dsmpd = 1,
++	},
++};
++
++#endif

+ 75 - 0
target/linux/starfive/patches-6.1/0033-dt-bindings-clock-jh7110-syscrg-Add-PLL-clock-inputs.patch

@@ -0,0 +1,75 @@
+From 1f788a0a5092b1e1cfd02aa7f31ceb551befa7e6 Mon Sep 17 00:00:00 2001
+From: Xingyu Wu <[email protected]>
+Date: Tue, 14 Mar 2023 16:43:50 +0800
+Subject: [PATCH 033/122] dt-bindings: clock: jh7110-syscrg: Add PLL clock
+ inputs
+
+Add PLL clock inputs from PLL clock generator.
+
+Acked-by: Krzysztof Kozlowski <[email protected]>
+Signed-off-by: Xingyu Wu <[email protected]>
+---
+ .../clock/starfive,jh7110-syscrg.yaml         | 20 +++++++++++++++++--
+ 1 file changed, 18 insertions(+), 2 deletions(-)
+
+--- a/Documentation/devicetree/bindings/clock/starfive,jh7110-syscrg.yaml
++++ b/Documentation/devicetree/bindings/clock/starfive,jh7110-syscrg.yaml
+@@ -27,6 +27,9 @@ properties:
+           - description: External I2S RX left/right channel clock
+           - description: External TDM clock
+           - description: External audio master clock
++          - description: PLL0
++          - description: PLL1
++          - description: PLL2
+ 
+       - items:
+           - description: Main Oscillator (24 MHz)
+@@ -38,6 +41,9 @@ properties:
+           - description: External I2S RX left/right channel clock
+           - description: External TDM clock
+           - description: External audio master clock
++          - description: PLL0
++          - description: PLL1
++          - description: PLL2
+ 
+   clock-names:
+     oneOf:
+@@ -52,6 +58,9 @@ properties:
+           - const: i2srx_lrck_ext
+           - const: tdm_ext
+           - const: mclk_ext
++          - const: pll0_out
++          - const: pll1_out
++          - const: pll2_out
+ 
+       - items:
+           - const: osc
+@@ -63,6 +72,9 @@ properties:
+           - const: i2srx_lrck_ext
+           - const: tdm_ext
+           - const: mclk_ext
++          - const: pll0_out
++          - const: pll1_out
++          - const: pll2_out
+ 
+   '#clock-cells':
+     const: 1
+@@ -93,12 +105,16 @@ examples:
+                  <&gmac1_rgmii_rxin>,
+                  <&i2stx_bclk_ext>, <&i2stx_lrck_ext>,
+                  <&i2srx_bclk_ext>, <&i2srx_lrck_ext>,
+-                 <&tdm_ext>, <&mclk_ext>;
++                 <&tdm_ext>, <&mclk_ext>,
++                 <&pllclk JH7110_CLK_PLL0_OUT>,
++                 <&pllclk JH7110_CLK_PLL1_OUT>,
++                 <&pllclk JH7110_CLK_PLL2_OUT>;
+         clock-names = "osc", "gmac1_rmii_refin",
+                       "gmac1_rgmii_rxin",
+                       "i2stx_bclk_ext", "i2stx_lrck_ext",
+                       "i2srx_bclk_ext", "i2srx_lrck_ext",
+-                      "tdm_ext", "mclk_ext";
++                      "tdm_ext", "mclk_ext",
++                      "pll0_out", "pll1_out", "pll2_out";
+         #clock-cells = <1>;
+         #reset-cells = <1>;
+     };

+ 71 - 0
target/linux/starfive/patches-6.1/0034-clk-starfive-jh7110-sys-Modify-PLL-clocks-source.patch

@@ -0,0 +1,71 @@
+From ffd7ee4fbd69d477a2156d9cba6ae80434a4c894 Mon Sep 17 00:00:00 2001
+From: Xingyu Wu <[email protected]>
+Date: Tue, 14 Mar 2023 17:16:07 +0800
+Subject: [PATCH 034/122] clk: starfive: jh7110-sys: Modify PLL clocks source
+
+Modify PLL clocks source to be got from dts instead of
+the fixed factor clocks.
+
+Signed-off-by: Xingyu Wu <[email protected]>
+---
+ drivers/clk/starfive/Kconfig                  |  1 +
+ .../clk/starfive/clk-starfive-jh7110-sys.c    | 31 ++++---------------
+ 2 files changed, 7 insertions(+), 25 deletions(-)
+
+--- a/drivers/clk/starfive/Kconfig
++++ b/drivers/clk/starfive/Kconfig
+@@ -35,6 +35,7 @@ config CLK_STARFIVE_JH7110_SYS
+ 	select AUXILIARY_BUS
+ 	select CLK_STARFIVE_JH71X0
+ 	select RESET_STARFIVE_JH7110
++	select CLK_STARFIVE_JH7110_PLL
+ 	default ARCH_STARFIVE
+ 	help
+ 	  Say yes here to support the system clock controller on the
+--- a/drivers/clk/starfive/clk-starfive-jh7110-sys.c
++++ b/drivers/clk/starfive/clk-starfive-jh7110-sys.c
+@@ -404,29 +404,6 @@ static int __init jh7110_syscrg_probe(st
+ 
+ 	dev_set_drvdata(priv->dev, (void *)(&priv->base));
+ 
+-	/*
+-	 * These PLL clocks are not actually fixed factor clocks and can be
+-	 * controlled by the syscon registers of JH7110. They will be dropped
+-	 * and registered in the PLL clock driver instead.
+-	 */
+-	/* 24MHz -> 1000.0MHz */
+-	priv->pll[0] = devm_clk_hw_register_fixed_factor(priv->dev, "pll0_out",
+-							 "osc", 0, 125, 3);
+-	if (IS_ERR(priv->pll[0]))
+-		return PTR_ERR(priv->pll[0]);
+-
+-	/* 24MHz -> 1066.0MHz */
+-	priv->pll[1] = devm_clk_hw_register_fixed_factor(priv->dev, "pll1_out",
+-							 "osc", 0, 533, 12);
+-	if (IS_ERR(priv->pll[1]))
+-		return PTR_ERR(priv->pll[1]);
+-
+-	/* 24MHz -> 1188.0MHz */
+-	priv->pll[2] = devm_clk_hw_register_fixed_factor(priv->dev, "pll2_out",
+-							 "osc", 0, 99, 2);
+-	if (IS_ERR(priv->pll[2]))
+-		return PTR_ERR(priv->pll[2]);
+-
+ 	for (idx = 0; idx < JH7110_SYSCLK_END; idx++) {
+ 		u32 max = jh7110_sysclk_data[idx].max;
+ 		struct clk_parent_data parents[4] = {};
+@@ -464,8 +441,12 @@ static int __init jh7110_syscrg_probe(st
+ 				parents[i].fw_name = "tdm_ext";
+ 			else if (pidx == JH7110_SYSCLK_MCLK_EXT)
+ 				parents[i].fw_name = "mclk_ext";
+-			else
+-				parents[i].hw = priv->pll[pidx - JH7110_SYSCLK_PLL0_OUT];
++			else if (pidx == JH7110_SYSCLK_PLL0_OUT)
++				parents[i].fw_name = "pll0_out";
++			else if (pidx == JH7110_SYSCLK_PLL1_OUT)
++				parents[i].fw_name = "pll1_out";
++			else if (pidx == JH7110_SYSCLK_PLL2_OUT)
++				parents[i].fw_name = "pll2_out";
+ 		}
+ 
+ 		clk->hw.init = &init;

+ 86 - 0
target/linux/starfive/patches-6.1/0035-dt-bindings-power-Add-starfive-jh7110-pmu.patch

@@ -0,0 +1,86 @@
+From 35bc6491a7b24872155a616f7770d3a5d6e40344 Mon Sep 17 00:00:00 2001
+From: Walker Chen <[email protected]>
+Date: Thu, 19 Jan 2023 17:44:46 +0800
+Subject: [PATCH 035/122] dt-bindings: power: Add starfive,jh7110-pmu
+
+Add bindings for the Power Management Unit on the StarFive JH7110 SoC.
+
+Signed-off-by: Walker Chen <[email protected]>
+Reviewed-by: Krzysztof Kozlowski <[email protected]>
+Reviewed-by: Conor Dooley <[email protected]>
+Reviewed-by: Heiko Stuebner <[email protected]>
+---
+ .../bindings/power/starfive,jh7110-pmu.yaml   | 45 +++++++++++++++++++
+ .../dt-bindings/power/starfive,jh7110-pmu.h   | 17 +++++++
+ 2 files changed, 62 insertions(+)
+ create mode 100644 Documentation/devicetree/bindings/power/starfive,jh7110-pmu.yaml
+ create mode 100644 include/dt-bindings/power/starfive,jh7110-pmu.h
+
+--- /dev/null
++++ b/Documentation/devicetree/bindings/power/starfive,jh7110-pmu.yaml
+@@ -0,0 +1,45 @@
++# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
++%YAML 1.2
++---
++$id: http://devicetree.org/schemas/power/starfive,jh7110-pmu.yaml#
++$schema: http://devicetree.org/meta-schemas/core.yaml#
++
++title: StarFive JH7110 Power Management Unit
++
++maintainers:
++  - Walker Chen <[email protected]>
++
++description: |
++  StarFive JH7110 SoC includes support for multiple power domains which can be
++  powered on/off by software based on different application scenes to save power.
++
++properties:
++  compatible:
++    enum:
++      - starfive,jh7110-pmu
++
++  reg:
++    maxItems: 1
++
++  interrupts:
++    maxItems: 1
++
++  "#power-domain-cells":
++    const: 1
++
++required:
++  - compatible
++  - reg
++  - interrupts
++  - "#power-domain-cells"
++
++additionalProperties: false
++
++examples:
++  - |
++    pwrc: power-controller@17030000 {
++        compatible = "starfive,jh7110-pmu";
++        reg = <0x17030000 0x10000>;
++        interrupts = <111>;
++        #power-domain-cells = <1>;
++    };
+--- /dev/null
++++ b/include/dt-bindings/power/starfive,jh7110-pmu.h
+@@ -0,0 +1,17 @@
++/* SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) */
++/*
++ * Copyright (C) 2022 StarFive Technology Co., Ltd.
++ * Author: Walker Chen <[email protected]>
++ */
++#ifndef __DT_BINDINGS_POWER_JH7110_POWER_H__
++#define __DT_BINDINGS_POWER_JH7110_POWER_H__
++
++#define JH7110_PD_SYSTOP	0
++#define JH7110_PD_CPU		1
++#define JH7110_PD_GPUA		2
++#define JH7110_PD_VDEC		3
++#define JH7110_PD_VOUT		4
++#define JH7110_PD_ISP		5
++#define JH7110_PD_VENC		6
++
++#endif

+ 478 - 0
target/linux/starfive/patches-6.1/0036-soc-starfive-Add-StarFive-JH71XX-pmu-driver.patch

@@ -0,0 +1,478 @@
+From 3e3b85a1064b07a5107504af1e8f0a42ff9d1fc1 Mon Sep 17 00:00:00 2001
+From: Walker Chen <[email protected]>
+Date: Thu, 19 Jan 2023 17:44:47 +0800
+Subject: [PATCH 036/122] soc: starfive: Add StarFive JH71XX pmu driver
+
+Add pmu driver for the StarFive JH71XX SoC.
+
+As the power domains provider, the Power Management Unit (PMU) is
+designed for including multiple PM domains that can be used for power
+gating of selected IP blocks for power saving by reduced leakage
+current. It accepts software encourage command to switch the power mode
+of SoC.
+
+Signed-off-by: Walker Chen <[email protected]>
+Reviewed-by: Conor Dooley <[email protected]>
+Reviewed-by: Heiko Stuebner <[email protected]>
+---
+ MAINTAINERS                       |  14 ++
+ drivers/soc/Kconfig               |   1 +
+ drivers/soc/Makefile              |   1 +
+ drivers/soc/starfive/Kconfig      |  12 +
+ drivers/soc/starfive/Makefile     |   3 +
+ drivers/soc/starfive/jh71xx_pmu.c | 383 ++++++++++++++++++++++++++++++
+ 6 files changed, 414 insertions(+)
+ create mode 100644 drivers/soc/starfive/Kconfig
+ create mode 100644 drivers/soc/starfive/Makefile
+ create mode 100644 drivers/soc/starfive/jh71xx_pmu.c
+
+--- a/MAINTAINERS
++++ b/MAINTAINERS
+@@ -19682,6 +19682,20 @@ F:	Documentation/devicetree/bindings/res
+ F:	drivers/reset/starfive/reset-starfive-jh71*
+ F:	include/dt-bindings/reset/starfive?jh71*.h
+ 
++STARFIVE SOC DRIVER
++M:	Conor Dooley <[email protected]>
++S:	Maintained
++T:	git https://git.kernel.org/pub/scm/linux/kernel/git/conor/linux.git/
++F:	drivers/soc/starfive/
++F:	include/soc/starfive/
++
++STARFIVE JH71XX PMU CONTROLLER DRIVER
++M:	Walker Chen <[email protected]>
++S:	Supported
++F:	Documentation/devicetree/bindings/power/starfive*
++F:	drivers/soc/starfive/jh71xx_pmu.c
++F:	include/dt-bindings/power/starfive,jh7110-pmu.h
++
+ STATIC BRANCH/CALL
+ M:	Peter Zijlstra <[email protected]>
+ M:	Josh Poimboeuf <[email protected]>
+--- a/drivers/soc/Kconfig
++++ b/drivers/soc/Kconfig
+@@ -21,6 +21,7 @@ source "drivers/soc/renesas/Kconfig"
+ source "drivers/soc/rockchip/Kconfig"
+ source "drivers/soc/samsung/Kconfig"
+ source "drivers/soc/sifive/Kconfig"
++source "drivers/soc/starfive/Kconfig"
+ source "drivers/soc/sunxi/Kconfig"
+ source "drivers/soc/tegra/Kconfig"
+ source "drivers/soc/ti/Kconfig"
+--- a/drivers/soc/Makefile
++++ b/drivers/soc/Makefile
+@@ -27,6 +27,7 @@ obj-y				+= renesas/
+ obj-y				+= rockchip/
+ obj-$(CONFIG_SOC_SAMSUNG)	+= samsung/
+ obj-$(CONFIG_SOC_SIFIVE)	+= sifive/
++obj-$(CONFIG_SOC_STARFIVE)	+= starfive/
+ obj-y				+= sunxi/
+ obj-$(CONFIG_ARCH_TEGRA)	+= tegra/
+ obj-y				+= ti/
+--- /dev/null
++++ b/drivers/soc/starfive/Kconfig
+@@ -0,0 +1,12 @@
++# SPDX-License-Identifier: GPL-2.0
++
++config JH71XX_PMU
++	bool "Support PMU for StarFive JH71XX Soc"
++	depends on PM
++	depends on SOC_STARFIVE || COMPILE_TEST
++	default SOC_STARFIVE
++	select PM_GENERIC_DOMAINS
++	help
++	  Say 'y' here to enable support power domain support.
++	  In order to meet low power requirements, a Power Management Unit (PMU)
++	  is designed for controlling power resources in StarFive JH71XX SoCs.
+--- /dev/null
++++ b/drivers/soc/starfive/Makefile
+@@ -0,0 +1,3 @@
++# SPDX-License-Identifier: GPL-2.0
++
++obj-$(CONFIG_JH71XX_PMU)	+= jh71xx_pmu.o
+--- /dev/null
++++ b/drivers/soc/starfive/jh71xx_pmu.c
+@@ -0,0 +1,383 @@
++// SPDX-License-Identifier: GPL-2.0-or-later
++/*
++ * StarFive JH71XX PMU (Power Management Unit) Controller Driver
++ *
++ * Copyright (C) 2022 StarFive Technology Co., Ltd.
++ */
++
++#include <linux/interrupt.h>
++#include <linux/io.h>
++#include <linux/iopoll.h>
++#include <linux/module.h>
++#include <linux/of.h>
++#include <linux/of_device.h>
++#include <linux/platform_device.h>
++#include <linux/pm_domain.h>
++#include <dt-bindings/power/starfive,jh7110-pmu.h>
++
++/* register offset */
++#define JH71XX_PMU_SW_TURN_ON_POWER	0x0C
++#define JH71XX_PMU_SW_TURN_OFF_POWER	0x10
++#define JH71XX_PMU_SW_ENCOURAGE		0x44
++#define JH71XX_PMU_TIMER_INT_MASK	0x48
++#define JH71XX_PMU_CURR_POWER_MODE	0x80
++#define JH71XX_PMU_EVENT_STATUS		0x88
++#define JH71XX_PMU_INT_STATUS		0x8C
++
++/* sw encourage cfg */
++#define JH71XX_PMU_SW_ENCOURAGE_EN_LO	0x05
++#define JH71XX_PMU_SW_ENCOURAGE_EN_HI	0x50
++#define JH71XX_PMU_SW_ENCOURAGE_DIS_LO	0x0A
++#define JH71XX_PMU_SW_ENCOURAGE_DIS_HI	0xA0
++#define JH71XX_PMU_SW_ENCOURAGE_ON	0xFF
++
++/* pmu int status */
++#define JH71XX_PMU_INT_SEQ_DONE		BIT(0)
++#define JH71XX_PMU_INT_HW_REQ		BIT(1)
++#define JH71XX_PMU_INT_SW_FAIL		GENMASK(3, 2)
++#define JH71XX_PMU_INT_HW_FAIL		GENMASK(5, 4)
++#define JH71XX_PMU_INT_PCH_FAIL		GENMASK(8, 6)
++#define JH71XX_PMU_INT_ALL_MASK		GENMASK(8, 0)
++
++/*
++ * The time required for switching power status is based on the time
++ * to turn on the largest domain's power, which is at microsecond level
++ */
++#define JH71XX_PMU_TIMEOUT_US		100
++
++struct jh71xx_domain_info {
++	const char * const name;
++	unsigned int flags;
++	u8 bit;
++};
++
++struct jh71xx_pmu_match_data {
++	const struct jh71xx_domain_info *domain_info;
++	int num_domains;
++};
++
++struct jh71xx_pmu {
++	struct device *dev;
++	const struct jh71xx_pmu_match_data *match_data;
++	void __iomem *base;
++	struct generic_pm_domain **genpd;
++	struct genpd_onecell_data genpd_data;
++	int irq;
++	spinlock_t lock;	/* protects pmu reg */
++};
++
++struct jh71xx_pmu_dev {
++	const struct jh71xx_domain_info *domain_info;
++	struct jh71xx_pmu *pmu;
++	struct generic_pm_domain genpd;
++};
++
++static int jh71xx_pmu_get_state(struct jh71xx_pmu_dev *pmd, u32 mask, bool *is_on)
++{
++	struct jh71xx_pmu *pmu = pmd->pmu;
++
++	if (!mask)
++		return -EINVAL;
++
++	*is_on = readl(pmu->base + JH71XX_PMU_CURR_POWER_MODE) & mask;
++
++	return 0;
++}
++
++static int jh71xx_pmu_set_state(struct jh71xx_pmu_dev *pmd, u32 mask, bool on)
++{
++	struct jh71xx_pmu *pmu = pmd->pmu;
++	unsigned long flags;
++	u32 val;
++	u32 mode;
++	u32 encourage_lo;
++	u32 encourage_hi;
++	bool is_on;
++	int ret;
++
++	ret = jh71xx_pmu_get_state(pmd, mask, &is_on);
++	if (ret) {
++		dev_dbg(pmu->dev, "unable to get current state for %s\n",
++			pmd->genpd.name);
++		return ret;
++	}
++
++	if (is_on == on) {
++		dev_dbg(pmu->dev, "pm domain [%s] is already %sable status.\n",
++			pmd->genpd.name, on ? "en" : "dis");
++		return 0;
++	}
++
++	spin_lock_irqsave(&pmu->lock, flags);
++
++	/*
++	 * The PMU accepts software encourage to switch power mode in the following 2 steps:
++	 *
++	 * 1.Configure the register SW_TURN_ON_POWER (offset 0x0c) by writing 1 to
++	 *   the bit corresponding to the power domain that will be turned on
++	 *   and writing 0 to the others.
++	 *   Likewise, configure the register SW_TURN_OFF_POWER (offset 0x10) by
++	 *   writing 1 to the bit corresponding to the power domain that will be
++	 *   turned off and writing 0 to the others.
++	 */
++	if (on) {
++		mode = JH71XX_PMU_SW_TURN_ON_POWER;
++		encourage_lo = JH71XX_PMU_SW_ENCOURAGE_EN_LO;
++		encourage_hi = JH71XX_PMU_SW_ENCOURAGE_EN_HI;
++	} else {
++		mode = JH71XX_PMU_SW_TURN_OFF_POWER;
++		encourage_lo = JH71XX_PMU_SW_ENCOURAGE_DIS_LO;
++		encourage_hi = JH71XX_PMU_SW_ENCOURAGE_DIS_HI;
++	}
++
++	writel(mask, pmu->base + mode);
++
++	/*
++	 * 2.Write SW encourage command sequence to the Software Encourage Reg (offset 0x44)
++	 *   First write SW_MODE_ENCOURAGE_ON to JH71XX_PMU_SW_ENCOURAGE. This will reset
++	 *   the state machine which parses the command sequence. This register must be
++	 *   written every time software wants to power on/off a domain.
++	 *   Then write the lower bits of the command sequence, followed by the upper
++	 *   bits. The sequence differs between powering on & off a domain.
++	 */
++	writel(JH71XX_PMU_SW_ENCOURAGE_ON, pmu->base + JH71XX_PMU_SW_ENCOURAGE);
++	writel(encourage_lo, pmu->base + JH71XX_PMU_SW_ENCOURAGE);
++	writel(encourage_hi, pmu->base + JH71XX_PMU_SW_ENCOURAGE);
++
++	spin_unlock_irqrestore(&pmu->lock, flags);
++
++	/* Wait for the power domain bit to be enabled / disabled */
++	if (on) {
++		ret = readl_poll_timeout_atomic(pmu->base + JH71XX_PMU_CURR_POWER_MODE,
++						val, val & mask,
++						1, JH71XX_PMU_TIMEOUT_US);
++	} else {
++		ret = readl_poll_timeout_atomic(pmu->base + JH71XX_PMU_CURR_POWER_MODE,
++						val, !(val & mask),
++						1, JH71XX_PMU_TIMEOUT_US);
++	}
++
++	if (ret) {
++		dev_err(pmu->dev, "%s: failed to power %s\n",
++			pmd->genpd.name, on ? "on" : "off");
++		return -ETIMEDOUT;
++	}
++
++	return 0;
++}
++
++static int jh71xx_pmu_on(struct generic_pm_domain *genpd)
++{
++	struct jh71xx_pmu_dev *pmd = container_of(genpd,
++						  struct jh71xx_pmu_dev, genpd);
++	u32 pwr_mask = BIT(pmd->domain_info->bit);
++
++	return jh71xx_pmu_set_state(pmd, pwr_mask, true);
++}
++
++static int jh71xx_pmu_off(struct generic_pm_domain *genpd)
++{
++	struct jh71xx_pmu_dev *pmd = container_of(genpd,
++						  struct jh71xx_pmu_dev, genpd);
++	u32 pwr_mask = BIT(pmd->domain_info->bit);
++
++	return jh71xx_pmu_set_state(pmd, pwr_mask, false);
++}
++
++static void jh71xx_pmu_int_enable(struct jh71xx_pmu *pmu, u32 mask, bool enable)
++{
++	u32 val;
++	unsigned long flags;
++
++	spin_lock_irqsave(&pmu->lock, flags);
++	val = readl(pmu->base + JH71XX_PMU_TIMER_INT_MASK);
++
++	if (enable)
++		val &= ~mask;
++	else
++		val |= mask;
++
++	writel(val, pmu->base + JH71XX_PMU_TIMER_INT_MASK);
++	spin_unlock_irqrestore(&pmu->lock, flags);
++}
++
++static irqreturn_t jh71xx_pmu_interrupt(int irq, void *data)
++{
++	struct jh71xx_pmu *pmu = data;
++	u32 val;
++
++	val = readl(pmu->base + JH71XX_PMU_INT_STATUS);
++
++	if (val & JH71XX_PMU_INT_SEQ_DONE)
++		dev_dbg(pmu->dev, "sequence done.\n");
++	if (val & JH71XX_PMU_INT_HW_REQ)
++		dev_dbg(pmu->dev, "hardware encourage requestion.\n");
++	if (val & JH71XX_PMU_INT_SW_FAIL)
++		dev_err(pmu->dev, "software encourage fail.\n");
++	if (val & JH71XX_PMU_INT_HW_FAIL)
++		dev_err(pmu->dev, "hardware encourage fail.\n");
++	if (val & JH71XX_PMU_INT_PCH_FAIL)
++		dev_err(pmu->dev, "p-channel fail event.\n");
++
++	/* clear interrupts */
++	writel(val, pmu->base + JH71XX_PMU_INT_STATUS);
++	writel(val, pmu->base + JH71XX_PMU_EVENT_STATUS);
++
++	return IRQ_HANDLED;
++}
++
++static int jh71xx_pmu_init_domain(struct jh71xx_pmu *pmu, int index)
++{
++	struct jh71xx_pmu_dev *pmd;
++	u32 pwr_mask;
++	int ret;
++	bool is_on = false;
++
++	pmd = devm_kzalloc(pmu->dev, sizeof(*pmd), GFP_KERNEL);
++	if (!pmd)
++		return -ENOMEM;
++
++	pmd->domain_info = &pmu->match_data->domain_info[index];
++	pmd->pmu = pmu;
++	pwr_mask = BIT(pmd->domain_info->bit);
++
++	pmd->genpd.name = pmd->domain_info->name;
++	pmd->genpd.flags = pmd->domain_info->flags;
++
++	ret = jh71xx_pmu_get_state(pmd, pwr_mask, &is_on);
++	if (ret)
++		dev_warn(pmu->dev, "unable to get current state for %s\n",
++			 pmd->genpd.name);
++
++	pmd->genpd.power_on = jh71xx_pmu_on;
++	pmd->genpd.power_off = jh71xx_pmu_off;
++	pm_genpd_init(&pmd->genpd, NULL, !is_on);
++
++	pmu->genpd_data.domains[index] = &pmd->genpd;
++
++	return 0;
++}
++
++static int jh71xx_pmu_probe(struct platform_device *pdev)
++{
++	struct device *dev = &pdev->dev;
++	struct device_node *np = dev->of_node;
++	const struct jh71xx_pmu_match_data *match_data;
++	struct jh71xx_pmu *pmu;
++	unsigned int i;
++	int ret;
++
++	pmu = devm_kzalloc(dev, sizeof(*pmu), GFP_KERNEL);
++	if (!pmu)
++		return -ENOMEM;
++
++	pmu->base = devm_platform_ioremap_resource(pdev, 0);
++	if (IS_ERR(pmu->base))
++		return PTR_ERR(pmu->base);
++
++	pmu->irq = platform_get_irq(pdev, 0);
++	if (pmu->irq < 0)
++		return pmu->irq;
++
++	ret = devm_request_irq(dev, pmu->irq, jh71xx_pmu_interrupt,
++			       0, pdev->name, pmu);
++	if (ret)
++		dev_err(dev, "failed to request irq\n");
++
++	match_data = of_device_get_match_data(dev);
++	if (!match_data)
++		return -EINVAL;
++
++	pmu->genpd = devm_kcalloc(dev, match_data->num_domains,
++				  sizeof(struct generic_pm_domain *),
++				  GFP_KERNEL);
++	if (!pmu->genpd)
++		return -ENOMEM;
++
++	pmu->dev = dev;
++	pmu->match_data = match_data;
++	pmu->genpd_data.domains = pmu->genpd;
++	pmu->genpd_data.num_domains = match_data->num_domains;
++
++	for (i = 0; i < match_data->num_domains; i++) {
++		ret = jh71xx_pmu_init_domain(pmu, i);
++		if (ret) {
++			dev_err(dev, "failed to initialize power domain\n");
++			return ret;
++		}
++	}
++
++	spin_lock_init(&pmu->lock);
++	jh71xx_pmu_int_enable(pmu, JH71XX_PMU_INT_ALL_MASK & ~JH71XX_PMU_INT_PCH_FAIL, true);
++
++	ret = of_genpd_add_provider_onecell(np, &pmu->genpd_data);
++	if (ret) {
++		dev_err(dev, "failed to register genpd driver: %d\n", ret);
++		return ret;
++	}
++
++	dev_dbg(dev, "registered %u power domains\n", i);
++
++	return 0;
++}
++
++static const struct jh71xx_domain_info jh7110_power_domains[] = {
++	[JH7110_PD_SYSTOP] = {
++		.name = "SYSTOP",
++		.bit = 0,
++		.flags = GENPD_FLAG_ALWAYS_ON,
++	},
++	[JH7110_PD_CPU] = {
++		.name = "CPU",
++		.bit = 1,
++		.flags = GENPD_FLAG_ALWAYS_ON,
++	},
++	[JH7110_PD_GPUA] = {
++		.name = "GPUA",
++		.bit = 2,
++	},
++	[JH7110_PD_VDEC] = {
++		.name = "VDEC",
++		.bit = 3,
++	},
++	[JH7110_PD_VOUT] = {
++		.name = "VOUT",
++		.bit = 4,
++	},
++	[JH7110_PD_ISP] = {
++		.name = "ISP",
++		.bit = 5,
++	},
++	[JH7110_PD_VENC] = {
++		.name = "VENC",
++		.bit = 6,
++	},
++};
++
++static const struct jh71xx_pmu_match_data jh7110_pmu = {
++	.num_domains = ARRAY_SIZE(jh7110_power_domains),
++	.domain_info = jh7110_power_domains,
++};
++
++static const struct of_device_id jh71xx_pmu_of_match[] = {
++	{
++		.compatible = "starfive,jh7110-pmu",
++		.data = (void *)&jh7110_pmu,
++	}, {
++		/* sentinel */
++	}
++};
++
++static struct platform_driver jh71xx_pmu_driver = {
++	.probe = jh71xx_pmu_probe,
++	.driver = {
++		.name = "jh71xx-pmu",
++		.of_match_table = jh71xx_pmu_of_match,
++		.suppress_bind_attrs = true,
++	},
++};
++builtin_platform_driver(jh71xx_pmu_driver);
++
++MODULE_AUTHOR("Walker Chen <[email protected]>");
++MODULE_DESCRIPTION("StarFive JH71XX PMU Driver");
++MODULE_LICENSE("GPL");

+ 98 - 0
target/linux/starfive/patches-6.1/0037-dt-bindings-soc-starfive-Add-StarFive-syscon-module.patch

@@ -0,0 +1,98 @@
+From 27d38dda7527414eb84ef471425e96c9d2566b38 Mon Sep 17 00:00:00 2001
+From: William Qiu <[email protected]>
+Date: Thu, 6 Apr 2023 15:46:13 +0800
+Subject: [PATCH 037/122] dt-bindings: soc: starfive: Add StarFive syscon
+ module
+
+Add documentation to describe StarFive System Controller Registers.
+
+Signed-off-by: William Qiu <[email protected]>
+---
+ .../soc/starfive/starfive,jh7110-syscon.yaml  | 58 +++++++++++++++++++
+ MAINTAINERS                                   |  6 ++
+ 2 files changed, 64 insertions(+)
+ create mode 100644 Documentation/devicetree/bindings/soc/starfive/starfive,jh7110-syscon.yaml
+
+--- /dev/null
++++ b/Documentation/devicetree/bindings/soc/starfive/starfive,jh7110-syscon.yaml
+@@ -0,0 +1,58 @@
++# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause)
++%YAML 1.2
++---
++$id: http://devicetree.org/schemas/soc/starfive/starfive,jh7110-syscon.yaml#
++$schema: http://devicetree.org/meta-schemas/core.yaml#
++
++title: StarFive JH7110 SoC system controller
++
++maintainers:
++  - William Qiu <[email protected]>
++
++description: |
++  The StarFive JH7110 SoC system controller provides register information such
++  as offset, mask and shift to configure related modules such as MMC and PCIe.
++
++properties:
++  compatible:
++    oneOf:
++      - items:
++          - enum:
++              - starfive,jh7110-aon-syscon
++              - starfive,jh7110-sys-syscon
++          - const: syscon
++          - const: simple-mfd
++      - items:
++          - const: starfive,jh7110-stg-syscon
++          - const: syscon
++
++  reg:
++    maxItems: 1
++
++  clock-controller:
++    $ref: /schemas/clock/starfive,jh7110-pll.yaml#
++    type: object
++
++  power-controller:
++    $ref: /schemas/power/starfive,jh7110-pmu.yaml#
++    type: object
++
++required:
++  - compatible
++  - reg
++
++additionalProperties: false
++
++examples:
++  - |
++    syscon@10240000 {
++        compatible = "starfive,jh7110-stg-syscon", "syscon";
++        reg = <0x10240000 0x1000>;
++    };
++
++    syscon@13030000 {
++        compatible = "starfive,jh7110-sys-syscon", "syscon", "simple-mfd";
++        reg = <0x13030000 0x1000>;
++    };
++
++...
+--- a/MAINTAINERS
++++ b/MAINTAINERS
+@@ -19656,6 +19656,11 @@ S:	Supported
+ F:	Documentation/devicetree/bindings/clock/starfive,jh7110-pll.yaml
+ F:	drivers/clk/starfive/clk-starfive-jh7110-pll.*
+ 
++STARFIVE JH7110 SYSCON
++M:	William Qiu <[email protected]>
++S:	Supported
++F:	Documentation/devicetree/bindings/soc/starfive/starfive,jh7110-syscon.yaml
++
+ STARFIVE JH71X0 CLOCK DRIVERS
+ M:	Emil Renner Berthing <[email protected]>
+ M:	Hal Feng <[email protected]>
+@@ -19686,6 +19691,7 @@ STARFIVE SOC DRIVER
+ M:	Conor Dooley <[email protected]>
+ S:	Maintained
+ T:	git https://git.kernel.org/pub/scm/linux/kernel/git/conor/linux.git/
++F:	Documentation/devicetree/bindings/soc/starfive/
+ F:	drivers/soc/starfive/
+ F:	include/soc/starfive/
+ 

+ 52 - 0
target/linux/starfive/patches-6.1/0038-riscv-dts-starfive-jh7110-Add-syscon-nodes.patch

@@ -0,0 +1,52 @@
+From 40098f3d986dc90f6a7be0e5a35ddaccd1ded0b5 Mon Sep 17 00:00:00 2001
+From: William Qiu <[email protected]>
+Date: Thu, 6 Apr 2023 15:46:34 +0800
+Subject: [PATCH 038/122] riscv: dts: starfive: jh7110: Add syscon nodes
+
+Add stg_syscon/sys_syscon/aon_syscon nodes for JH7110 Soc.
+
+Signed-off-by: William Qiu <[email protected]>
+Reviewed-by: Conor Dooley <[email protected]>
+Reviewed-by: Emil Renner Berthing <[email protected]>
+---
+ arch/riscv/boot/dts/starfive/jh7110.dtsi | 15 +++++++++++++++
+ 1 file changed, 15 insertions(+)
+
+--- a/arch/riscv/boot/dts/starfive/jh7110.dtsi
++++ b/arch/riscv/boot/dts/starfive/jh7110.dtsi
+@@ -353,6 +353,11 @@
+ 			status = "disabled";
+ 		};
+ 
++		stg_syscon: syscon@10240000 {
++			compatible = "starfive,jh7110-stg-syscon", "syscon";
++			reg = <0x0 0x10240000 0x0 0x1000>;
++		};
++
+ 		uart3: serial@12000000 {
+ 			compatible = "snps,dw-apb-uart";
+ 			reg = <0x0 0x12000000 0x0 0x10000>;
+@@ -457,6 +462,11 @@
+ 			#reset-cells = <1>;
+ 		};
+ 
++		sys_syscon: syscon@13030000 {
++			compatible = "starfive,jh7110-sys-syscon", "syscon", "simple-mfd";
++			reg = <0x0 0x13030000 0x0 0x1000>;
++		};
++
+ 		sysgpio: pinctrl@13040000 {
+ 			compatible = "starfive,jh7110-sys-pinctrl";
+ 			reg = <0x0 0x13040000 0x0 0x10000>;
+@@ -486,6 +496,11 @@
+ 			#reset-cells = <1>;
+ 		};
+ 
++		aon_syscon: syscon@17010000 {
++			compatible = "starfive,jh7110-aon-syscon", "syscon", "simple-mfd";
++			reg = <0x0 0x17010000 0x0 0x1000>;
++		};
++
+ 		aongpio: pinctrl@17020000 {
+ 			compatible = "starfive,jh7110-aon-pinctrl";
+ 			reg = <0x0 0x17020000 0x0 0x10000>;

+ 48 - 0
target/linux/starfive/patches-6.1/0039-riscv-dts-starfive-jh7110-Add-PLL-clock-node-and-mod.patch

@@ -0,0 +1,48 @@
+From f0548ab9212ef35abe79f46e5f509f4fc9d78699 Mon Sep 17 00:00:00 2001
+From: Xingyu Wu <[email protected]>
+Date: Mon, 20 Feb 2023 14:33:33 +0800
+Subject: [PATCH 039/122] riscv: dts: starfive: jh7110: Add PLL clock node and
+ modify syscrg node
+
+Add the PLL clock node for the Starfive JH7110 SoC and
+modify the SYSCRG node to add PLL clocks input.
+
+Signed-off-by: Xingyu Wu <[email protected]>
+---
+ arch/riscv/boot/dts/starfive/jh7110.dtsi | 14 ++++++++++++--
+ 1 file changed, 12 insertions(+), 2 deletions(-)
+
+--- a/arch/riscv/boot/dts/starfive/jh7110.dtsi
++++ b/arch/riscv/boot/dts/starfive/jh7110.dtsi
+@@ -452,12 +452,16 @@
+ 				 <&gmac1_rgmii_rxin>,
+ 				 <&i2stx_bclk_ext>, <&i2stx_lrck_ext>,
+ 				 <&i2srx_bclk_ext>, <&i2srx_lrck_ext>,
+-				 <&tdm_ext>, <&mclk_ext>;
++				 <&tdm_ext>, <&mclk_ext>,
++				 <&pllclk JH7110_CLK_PLL0_OUT>,
++				 <&pllclk JH7110_CLK_PLL1_OUT>,
++				 <&pllclk JH7110_CLK_PLL2_OUT>;
+ 			clock-names = "osc", "gmac1_rmii_refin",
+ 				      "gmac1_rgmii_rxin",
+ 				      "i2stx_bclk_ext", "i2stx_lrck_ext",
+ 				      "i2srx_bclk_ext", "i2srx_lrck_ext",
+-				      "tdm_ext", "mclk_ext";
++				      "tdm_ext", "mclk_ext",
++				      "pll0_out", "pll1_out", "pll2_out";
+ 			#clock-cells = <1>;
+ 			#reset-cells = <1>;
+ 		};
+@@ -465,6 +469,12 @@
+ 		sys_syscon: syscon@13030000 {
+ 			compatible = "starfive,jh7110-sys-syscon", "syscon", "simple-mfd";
+ 			reg = <0x0 0x13030000 0x0 0x1000>;
++
++			pllclk: clock-controller {
++				compatible = "starfive,jh7110-pll";
++				clocks = <&osc>;
++				#clock-cells = <1>;
++			};
+ 		};
+ 
+ 		sysgpio: pinctrl@13040000 {

+ 49 - 0
target/linux/starfive/patches-6.1/0040-dt-bindings-net-snps-dwmac-Add-dwmac-5.20-version.patch

@@ -0,0 +1,49 @@
+From 5866a8486a261decacd19769556d1b79b5d1269d Mon Sep 17 00:00:00 2001
+From: Emil Renner Berthing <[email protected]>
+Date: Mon, 8 Aug 2022 17:13:34 +0200
+Subject: [PATCH 040/122] dt-bindings: net: snps,dwmac: Add dwmac-5.20 version
+
+Add dwmac-5.20 IP version to snps.dwmac.yaml
+
+Acked-by: Krzysztof Kozlowski <[email protected]>
+Signed-off-by: Emil Renner Berthing <[email protected]>
+Signed-off-by: Samin Guo <[email protected]>
+Signed-off-by: Paolo Abeni <[email protected]>
+---
+ Documentation/devicetree/bindings/net/snps,dwmac.yaml | 4 ++++
+ 1 file changed, 4 insertions(+)
+
+--- a/Documentation/devicetree/bindings/net/snps,dwmac.yaml
++++ b/Documentation/devicetree/bindings/net/snps,dwmac.yaml
+@@ -30,6 +30,7 @@ select:
+           - snps,dwmac-4.10a
+           - snps,dwmac-4.20a
+           - snps,dwmac-5.10a
++          - snps,dwmac-5.20
+           - snps,dwxgmac
+           - snps,dwxgmac-2.10
+ 
+@@ -87,6 +88,7 @@ properties:
+         - snps,dwmac-4.10a
+         - snps,dwmac-4.20a
+         - snps,dwmac-5.10a
++        - snps,dwmac-5.20
+         - snps,dwxgmac
+         - snps,dwxgmac-2.10
+ 
+@@ -393,6 +395,7 @@ allOf:
+               - snps,dwmac-3.50a
+               - snps,dwmac-4.10a
+               - snps,dwmac-4.20a
++              - snps,dwmac-5.20
+               - snps,dwxgmac
+               - snps,dwxgmac-2.10
+               - st,spear600-gmac
+@@ -447,6 +450,7 @@ allOf:
+               - snps,dwmac-4.10a
+               - snps,dwmac-4.20a
+               - snps,dwmac-5.10a
++              - snps,dwmac-5.20
+               - snps,dwxgmac
+               - snps,dwxgmac-2.10
+               - st,spear600-gmac

+ 29 - 0
target/linux/starfive/patches-6.1/0041-net-stmmac-platform-Add-snps-dwmac-5.20-IP-compatibl.patch

@@ -0,0 +1,29 @@
+From cb00f835fc9f3ece473e7081f17c8613bf08a8ef Mon Sep 17 00:00:00 2001
+From: Emil Renner Berthing <[email protected]>
+Date: Sun, 7 Aug 2022 22:26:00 +0200
+Subject: [PATCH 041/122] net: stmmac: platform: Add snps,dwmac-5.20 IP
+ compatible string
+
+Add "snps,dwmac-5.20" compatible string for 5.20 version that can avoid
+to define some platform data in the glue layer.
+
+Tested-by: Tommaso Merciai <[email protected]>
+Signed-off-by: Emil Renner Berthing <[email protected]>
+Signed-off-by: Paolo Abeni <[email protected]>
+Signed-off-by: Samin Guo <[email protected]>
+---
+ drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c | 3 ++-
+ 1 file changed, 2 insertions(+), 1 deletion(-)
+
+--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c
++++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c
+@@ -519,7 +519,8 @@ stmmac_probe_config_dt(struct platform_d
+ 	if (of_device_is_compatible(np, "snps,dwmac-4.00") ||
+ 	    of_device_is_compatible(np, "snps,dwmac-4.10a") ||
+ 	    of_device_is_compatible(np, "snps,dwmac-4.20a") ||
+-	    of_device_is_compatible(np, "snps,dwmac-5.10a")) {
++	    of_device_is_compatible(np, "snps,dwmac-5.10a") ||
++	    of_device_is_compatible(np, "snps,dwmac-5.20")) {
+ 		plat->has_gmac4 = 1;
+ 		plat->has_gmac = 0;
+ 		plat->pmt = 1;

+ 46 - 0
target/linux/starfive/patches-6.1/0042-dt-bindings-net-snps-dwmac-Add-ahb-reset-reset-name.patch

@@ -0,0 +1,46 @@
+From 3b0609e57e031a3b680131b3fc25bc1165e3360f Mon Sep 17 00:00:00 2001
+From: Samin Guo <[email protected]>
+Date: Mon, 27 Feb 2023 18:26:04 +0800
+Subject: [PATCH 042/122] dt-bindings: net: snps,dwmac: Add 'ahb'
+ reset/reset-name
+
+According to:
+stmmac_platform.c: stmmac_probe_config_dt
+stmmac_main.c: stmmac_dvr_probe
+
+dwmac controller may require one (stmmaceth) or two (stmmaceth+ahb)
+reset signals, and the maxItems of resets/reset-names is going to be 2.
+
+The gmac of Starfive Jh7110 SOC must have two resets.
+it uses snps,dwmac-5.20 IP.
+
+Reviewed-by: Krzysztof Kozlowski <[email protected]>
+Signed-off-by: Samin Guo <[email protected]>
+Signed-off-by: Paolo Abeni <[email protected]>
+---
+ .../devicetree/bindings/net/snps,dwmac.yaml          | 12 ++++++++----
+ 1 file changed, 8 insertions(+), 4 deletions(-)
+
+--- a/Documentation/devicetree/bindings/net/snps,dwmac.yaml
++++ b/Documentation/devicetree/bindings/net/snps,dwmac.yaml
+@@ -133,12 +133,16 @@ properties:
+         - ptp_ref
+ 
+   resets:
+-    maxItems: 1
+-    description:
+-      MAC Reset signal.
++    minItems: 1
++    items:
++      - description: GMAC stmmaceth reset
++      - description: AHB reset
+ 
+   reset-names:
+-    const: stmmaceth
++    minItems: 1
++    items:
++      - const: stmmaceth
++      - const: ahb
+ 
+   power-domains:
+     maxItems: 1

+ 190 - 0
target/linux/starfive/patches-6.1/0043-dt-bindings-net-Add-support-StarFive-dwmac.patch

@@ -0,0 +1,190 @@
+From 6bef17fa124f20723724e2a9a1d890fd1a9d5eaa Mon Sep 17 00:00:00 2001
+From: Yanhong Wang <[email protected]>
+Date: Mon, 31 Oct 2022 18:08:15 +0800
+Subject: [PATCH 043/122] dt-bindings: net: Add support StarFive dwmac
+
+Add documentation to describe StarFive dwmac driver(GMAC).
+
+Signed-off-by: Yanhong Wang <[email protected]>
+Reviewed-by: Krzysztof Kozlowski <[email protected]>
+Signed-off-by: Paolo Abeni <[email protected]>
+Signed-off-by: Samin Guo <[email protected]>
+---
+ .../devicetree/bindings/net/snps,dwmac.yaml   |   1 +
+ .../bindings/net/starfive,jh7110-dwmac.yaml   | 144 ++++++++++++++++++
+ MAINTAINERS                                   |   6 +
+ 3 files changed, 151 insertions(+)
+ create mode 100644 Documentation/devicetree/bindings/net/starfive,jh7110-dwmac.yaml
+
+--- a/Documentation/devicetree/bindings/net/snps,dwmac.yaml
++++ b/Documentation/devicetree/bindings/net/snps,dwmac.yaml
+@@ -91,6 +91,7 @@ properties:
+         - snps,dwmac-5.20
+         - snps,dwxgmac
+         - snps,dwxgmac-2.10
++        - starfive,jh7110-dwmac
+ 
+   reg:
+     minItems: 1
+--- /dev/null
++++ b/Documentation/devicetree/bindings/net/starfive,jh7110-dwmac.yaml
+@@ -0,0 +1,144 @@
++# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
++# Copyright (C) 2022 StarFive Technology Co., Ltd.
++%YAML 1.2
++---
++$id: http://devicetree.org/schemas/net/starfive,jh7110-dwmac.yaml#
++$schema: http://devicetree.org/meta-schemas/core.yaml#
++
++title: StarFive JH7110 DWMAC glue layer
++
++maintainers:
++  - Emil Renner Berthing <[email protected]>
++  - Samin Guo <[email protected]>
++
++select:
++  properties:
++    compatible:
++      contains:
++        enum:
++          - starfive,jh7110-dwmac
++  required:
++    - compatible
++
++properties:
++  compatible:
++    items:
++      - enum:
++          - starfive,jh7110-dwmac
++      - const: snps,dwmac-5.20
++
++  reg:
++    maxItems: 1
++
++  clocks:
++    items:
++      - description: GMAC main clock
++      - description: GMAC AHB clock
++      - description: PTP clock
++      - description: TX clock
++      - description: GTX clock
++
++  clock-names:
++    items:
++      - const: stmmaceth
++      - const: pclk
++      - const: ptp_ref
++      - const: tx
++      - const: gtx
++
++  interrupts:
++    minItems: 3
++    maxItems: 3
++
++  interrupt-names:
++    minItems: 3
++    maxItems: 3
++
++  resets:
++    items:
++      - description: MAC Reset signal.
++      - description: AHB Reset signal.
++
++  reset-names:
++    items:
++      - const: stmmaceth
++      - const: ahb
++
++  starfive,tx-use-rgmii-clk:
++    description:
++      Tx clock is provided by external rgmii clock.
++    type: boolean
++
++  starfive,syscon:
++    $ref: /schemas/types.yaml#/definitions/phandle-array
++    items:
++      - items:
++          - description: phandle to syscon that configures phy mode
++          - description: Offset of phy mode selection
++          - description: Shift of phy mode selection
++    description:
++      A phandle to syscon with two arguments that configure phy mode.
++      The argument one is the offset of phy mode selection, the
++      argument two is the shift of phy mode selection.
++
++required:
++  - compatible
++  - reg
++  - clocks
++  - clock-names
++  - interrupts
++  - interrupt-names
++  - resets
++  - reset-names
++
++allOf:
++  - $ref: snps,dwmac.yaml#
++
++unevaluatedProperties: false
++
++examples:
++  - |
++    ethernet@16030000 {
++        compatible = "starfive,jh7110-dwmac", "snps,dwmac-5.20";
++        reg = <0x16030000 0x10000>;
++        clocks = <&clk 3>, <&clk 2>, <&clk 109>,
++                 <&clk 6>, <&clk 111>;
++        clock-names = "stmmaceth", "pclk", "ptp_ref",
++                      "tx", "gtx";
++        resets = <&rst 1>, <&rst 2>;
++        reset-names = "stmmaceth", "ahb";
++        interrupts = <7>, <6>, <5>;
++        interrupt-names = "macirq", "eth_wake_irq", "eth_lpi";
++        phy-mode = "rgmii-id";
++        snps,multicast-filter-bins = <64>;
++        snps,perfect-filter-entries = <8>;
++        rx-fifo-depth = <2048>;
++        tx-fifo-depth = <2048>;
++        snps,fixed-burst;
++        snps,no-pbl-x8;
++        snps,tso;
++        snps,force_thresh_dma_mode;
++        snps,axi-config = <&stmmac_axi_setup>;
++        snps,en-tx-lpi-clockgating;
++        snps,txpbl = <16>;
++        snps,rxpbl = <16>;
++        starfive,syscon = <&aon_syscon 0xc 0x12>;
++        phy-handle = <&phy0>;
++
++        mdio {
++            #address-cells = <1>;
++            #size-cells = <0>;
++            compatible = "snps,dwmac-mdio";
++
++            phy0: ethernet-phy@0 {
++                reg = <0>;
++            };
++        };
++
++        stmmac_axi_setup: stmmac-axi-config {
++            snps,lpi_en;
++            snps,wr_osr_lmt = <4>;
++            snps,rd_osr_lmt = <4>;
++            snps,blen = <256 128 64 32 0 0 0>;
++        };
++    };
+--- a/MAINTAINERS
++++ b/MAINTAINERS
+@@ -19650,6 +19650,12 @@ M:	Emil Renner Berthing <[email protected]
+ S:	Maintained
+ F:	arch/riscv/boot/dts/starfive/
+ 
++STARFIVE DWMAC GLUE LAYER
++M:	Emil Renner Berthing <[email protected]>
++M:	Samin Guo <[email protected]>
++S:	Maintained
++F:	Documentation/devicetree/bindings/net/starfive,jh7110-dwmac.yaml
++
+ STARFIVE JH7110 PLL CLOCK DRIVER
+ M:	Xingyu Wu <[email protected]>
+ S:	Supported

+ 187 - 0
target/linux/starfive/patches-6.1/0044-net-stmmac-Add-glue-layer-for-StarFive-JH7110-SoC.patch

@@ -0,0 +1,187 @@
+From 7c82049adb0460985dd6a1e5c9b6954d901247d2 Mon Sep 17 00:00:00 2001
+From: Samin Guo <[email protected]>
+Date: Fri, 3 Mar 2023 16:50:58 +0800
+Subject: [PATCH 044/122] net: stmmac: Add glue layer for StarFive JH7110 SoC
+
+This adds StarFive dwmac driver support on the StarFive JH7110 SoC.
+
+Tested-by: Tommaso Merciai <[email protected]>
+Co-developed-by: Emil Renner Berthing <[email protected]>
+Signed-off-by: Emil Renner Berthing <[email protected]>
+Signed-off-by: Paolo Abeni <[email protected]>
+Signed-off-by: Samin Guo <[email protected]>
+---
+ MAINTAINERS                                   |   1 +
+ drivers/net/ethernet/stmicro/stmmac/Kconfig   |  12 ++
+ drivers/net/ethernet/stmicro/stmmac/Makefile  |   1 +
+ .../ethernet/stmicro/stmmac/dwmac-starfive.c  | 123 ++++++++++++++++++
+ 4 files changed, 137 insertions(+)
+ create mode 100644 drivers/net/ethernet/stmicro/stmmac/dwmac-starfive.c
+
+--- a/MAINTAINERS
++++ b/MAINTAINERS
+@@ -19655,6 +19655,7 @@ M:	Emil Renner Berthing <[email protected]
+ M:	Samin Guo <[email protected]>
+ S:	Maintained
+ F:	Documentation/devicetree/bindings/net/starfive,jh7110-dwmac.yaml
++F:	drivers/net/ethernet/stmicro/stmmac/dwmac-starfive.c
+ 
+ STARFIVE JH7110 PLL CLOCK DRIVER
+ M:	Xingyu Wu <[email protected]>
+--- a/drivers/net/ethernet/stmicro/stmmac/Kconfig
++++ b/drivers/net/ethernet/stmicro/stmmac/Kconfig
+@@ -165,6 +165,18 @@ config DWMAC_SOCFPGA
+ 	  for the stmmac device driver. This driver is used for
+ 	  arria5 and cyclone5 FPGA SoCs.
+ 
++config DWMAC_STARFIVE
++	tristate "StarFive dwmac support"
++	depends on OF && (ARCH_STARFIVE || COMPILE_TEST)
++	select MFD_SYSCON
++	default m if ARCH_STARFIVE
++	help
++	  Support for ethernet controllers on StarFive RISC-V SoCs
++
++	  This selects the StarFive platform specific glue layer support for
++	  the stmmac device driver. This driver is used for StarFive JH7110
++	  ethernet controller.
++
+ config DWMAC_STI
+ 	tristate "STi GMAC support"
+ 	default ARCH_STI
+--- a/drivers/net/ethernet/stmicro/stmmac/Makefile
++++ b/drivers/net/ethernet/stmicro/stmmac/Makefile
+@@ -23,6 +23,7 @@ obj-$(CONFIG_DWMAC_OXNAS)	+= dwmac-oxnas
+ obj-$(CONFIG_DWMAC_QCOM_ETHQOS)	+= dwmac-qcom-ethqos.o
+ obj-$(CONFIG_DWMAC_ROCKCHIP)	+= dwmac-rk.o
+ obj-$(CONFIG_DWMAC_SOCFPGA)	+= dwmac-altr-socfpga.o
++obj-$(CONFIG_DWMAC_STARFIVE)	+= dwmac-starfive.o
+ obj-$(CONFIG_DWMAC_STI)		+= dwmac-sti.o
+ obj-$(CONFIG_DWMAC_STM32)	+= dwmac-stm32.o
+ obj-$(CONFIG_DWMAC_SUNXI)	+= dwmac-sunxi.o
+--- /dev/null
++++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-starfive.c
+@@ -0,0 +1,123 @@
++// SPDX-License-Identifier: GPL-2.0+
++/*
++ * StarFive DWMAC platform driver
++ *
++ * Copyright (C) 2021 Emil Renner Berthing <[email protected]>
++ * Copyright (C) 2022 StarFive Technology Co., Ltd.
++ *
++ */
++
++#include <linux/mfd/syscon.h>
++#include <linux/of_device.h>
++#include <linux/regmap.h>
++
++#include "stmmac_platform.h"
++
++struct starfive_dwmac {
++	struct device *dev;
++	struct clk *clk_tx;
++};
++
++static void starfive_dwmac_fix_mac_speed(void *priv, unsigned int speed)
++{
++	struct starfive_dwmac *dwmac = priv;
++	unsigned long rate;
++	int err;
++
++	rate = clk_get_rate(dwmac->clk_tx);
++
++	switch (speed) {
++	case SPEED_1000:
++		rate = 125000000;
++		break;
++	case SPEED_100:
++		rate = 25000000;
++		break;
++	case SPEED_10:
++		rate = 2500000;
++		break;
++	default:
++		dev_err(dwmac->dev, "invalid speed %u\n", speed);
++		break;
++	}
++
++	err = clk_set_rate(dwmac->clk_tx, rate);
++	if (err)
++		dev_err(dwmac->dev, "failed to set tx rate %lu\n", rate);
++}
++
++static int starfive_dwmac_probe(struct platform_device *pdev)
++{
++	struct plat_stmmacenet_data *plat_dat;
++	struct stmmac_resources stmmac_res;
++	struct starfive_dwmac *dwmac;
++	struct clk *clk_gtx;
++	int err;
++
++	err = stmmac_get_platform_resources(pdev, &stmmac_res);
++	if (err)
++		return dev_err_probe(&pdev->dev, err,
++				     "failed to get resources\n");
++
++	plat_dat = stmmac_probe_config_dt(pdev, stmmac_res.mac);
++	if (IS_ERR(plat_dat))
++		return dev_err_probe(&pdev->dev, PTR_ERR(plat_dat),
++				     "dt configuration failed\n");
++
++	dwmac = devm_kzalloc(&pdev->dev, sizeof(*dwmac), GFP_KERNEL);
++	if (!dwmac)
++		return -ENOMEM;
++
++	dwmac->clk_tx = devm_clk_get_enabled(&pdev->dev, "tx");
++	if (IS_ERR(dwmac->clk_tx))
++		return dev_err_probe(&pdev->dev, PTR_ERR(dwmac->clk_tx),
++				     "error getting tx clock\n");
++
++	clk_gtx = devm_clk_get_enabled(&pdev->dev, "gtx");
++	if (IS_ERR(clk_gtx))
++		return dev_err_probe(&pdev->dev, PTR_ERR(clk_gtx),
++				     "error getting gtx clock\n");
++
++	/* Generally, the rgmii_tx clock is provided by the internal clock,
++	 * which needs to match the corresponding clock frequency according
++	 * to different speeds. If the rgmii_tx clock is provided by the
++	 * external rgmii_rxin, there is no need to configure the clock
++	 * internally, because rgmii_rxin will be adaptively adjusted.
++	 */
++	if (!device_property_read_bool(&pdev->dev, "starfive,tx-use-rgmii-clk"))
++		plat_dat->fix_mac_speed = starfive_dwmac_fix_mac_speed;
++
++	dwmac->dev = &pdev->dev;
++	plat_dat->bsp_priv = dwmac;
++	plat_dat->dma_cfg->dche = true;
++
++	err = stmmac_dvr_probe(&pdev->dev, plat_dat, &stmmac_res);
++	if (err) {
++		stmmac_remove_config_dt(pdev, plat_dat);
++		return err;
++	}
++
++	return 0;
++}
++
++static const struct of_device_id starfive_dwmac_match[] = {
++	{ .compatible = "starfive,jh7110-dwmac"	},
++	{ /* sentinel */ }
++};
++MODULE_DEVICE_TABLE(of, starfive_dwmac_match);
++
++static struct platform_driver starfive_dwmac_driver = {
++	.probe  = starfive_dwmac_probe,
++	.remove = stmmac_pltfr_remove,
++	.driver = {
++		.name = "starfive-dwmac",
++		.pm = &stmmac_pltfr_pm_ops,
++		.of_match_table = starfive_dwmac_match,
++	},
++};
++module_platform_driver(starfive_dwmac_driver);
++
++MODULE_LICENSE("GPL");
++MODULE_DESCRIPTION("StarFive DWMAC platform driver");
++MODULE_AUTHOR("Emil Renner Berthing <[email protected]>");
++MODULE_AUTHOR("Samin Guo <[email protected]>");

+ 93 - 0
target/linux/starfive/patches-6.1/0045-net-stmmac-dwmac-starfive-Add-phy-interface-settings.patch

@@ -0,0 +1,93 @@
+From 20886cd583e8d569d78ea0e723f98384a61ab54b Mon Sep 17 00:00:00 2001
+From: Samin Guo <[email protected]>
+Date: Thu, 2 Mar 2023 19:52:37 +0800
+Subject: [PATCH 045/122] net: stmmac: dwmac-starfive: Add phy interface
+ settings
+
+dwmac supports multiple modess. When working under rmii and rgmii,
+you need to set different phy interfaces.
+
+According to the dwmac document, when working in rmii, it needs to be
+set to 0x4, and rgmii needs to be set to 0x1.
+
+The phy interface needs to be set in syscon, the format is as follows:
+starfive,syscon: <&syscon, offset, shift>
+
+Tested-by: Tommaso Merciai <[email protected]>
+Signed-off-by: Paolo Abeni <[email protected]>
+Signed-off-by: Samin Guo <[email protected]>
+---
+ .../ethernet/stmicro/stmmac/dwmac-starfive.c  | 48 +++++++++++++++++++
+ 1 file changed, 48 insertions(+)
+
+--- a/drivers/net/ethernet/stmicro/stmmac/dwmac-starfive.c
++++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-starfive.c
+@@ -13,6 +13,10 @@
+ 
+ #include "stmmac_platform.h"
+ 
++#define STARFIVE_DWMAC_PHY_INFT_RGMII	0x1
++#define STARFIVE_DWMAC_PHY_INFT_RMII	0x4
++#define STARFIVE_DWMAC_PHY_INFT_FIELD	0x7U
++
+ struct starfive_dwmac {
+ 	struct device *dev;
+ 	struct clk *clk_tx;
+@@ -46,6 +50,46 @@ static void starfive_dwmac_fix_mac_speed
+ 		dev_err(dwmac->dev, "failed to set tx rate %lu\n", rate);
+ }
+ 
++static int starfive_dwmac_set_mode(struct plat_stmmacenet_data *plat_dat)
++{
++	struct starfive_dwmac *dwmac = plat_dat->bsp_priv;
++	struct regmap *regmap;
++	unsigned int args[2];
++	unsigned int mode;
++	int err;
++
++	switch (plat_dat->interface) {
++	case PHY_INTERFACE_MODE_RMII:
++		mode = STARFIVE_DWMAC_PHY_INFT_RMII;
++		break;
++
++	case PHY_INTERFACE_MODE_RGMII:
++	case PHY_INTERFACE_MODE_RGMII_ID:
++		mode = STARFIVE_DWMAC_PHY_INFT_RGMII;
++		break;
++
++	default:
++		dev_err(dwmac->dev, "unsupported interface %d\n",
++			plat_dat->interface);
++		return -EINVAL;
++	}
++
++	regmap = syscon_regmap_lookup_by_phandle_args(dwmac->dev->of_node,
++						      "starfive,syscon",
++						      2, args);
++	if (IS_ERR(regmap))
++		return dev_err_probe(dwmac->dev, PTR_ERR(regmap), "getting the regmap failed\n");
++
++	/* args[0]:offset  args[1]: shift */
++	err = regmap_update_bits(regmap, args[0],
++				 STARFIVE_DWMAC_PHY_INFT_FIELD << args[1],
++				 mode << args[1]);
++	if (err)
++		return dev_err_probe(dwmac->dev, err, "error setting phy mode\n");
++
++	return 0;
++}
++
+ static int starfive_dwmac_probe(struct platform_device *pdev)
+ {
+ 	struct plat_stmmacenet_data *plat_dat;
+@@ -91,6 +135,10 @@ static int starfive_dwmac_probe(struct p
+ 	plat_dat->bsp_priv = dwmac;
+ 	plat_dat->dma_cfg->dche = true;
+ 
++	err = starfive_dwmac_set_mode(plat_dat);
++	if (err)
++		return err;
++
+ 	err = stmmac_dvr_probe(&pdev->dev, plat_dat, &stmmac_res);
+ 	if (err) {
+ 		stmmac_remove_config_dt(pdev, plat_dat);

+ 101 - 0
target/linux/starfive/patches-6.1/0046-riscv-dts-starfive-jh7110-Add-ethernet-device-nodes.patch

@@ -0,0 +1,101 @@
+From cad740398f4cb6604abf1ddcc70121b2634ac233 Mon Sep 17 00:00:00 2001
+From: Samin Guo <[email protected]>
+Date: Fri, 3 Mar 2023 16:49:31 +0800
+Subject: [PATCH 046/122] riscv: dts: starfive: jh7110: Add ethernet device
+ nodes
+
+Add JH7110 ethernet device node to support gmac driver for the JH7110
+RISC-V SoC.
+
+Tested-by: Tommaso Merciai <[email protected]>
+Signed-off-by: Yanhong Wang <[email protected]>
+Signed-off-by: Samin Guo <[email protected]>
+---
+ arch/riscv/boot/dts/starfive/jh7110.dtsi | 69 ++++++++++++++++++++++++
+ 1 file changed, 69 insertions(+)
+
+--- a/arch/riscv/boot/dts/starfive/jh7110.dtsi
++++ b/arch/riscv/boot/dts/starfive/jh7110.dtsi
+@@ -230,6 +230,13 @@
+ 		#clock-cells = <0>;
+ 	};
+ 
++	stmmac_axi_setup: stmmac-axi-config {
++		snps,lpi_en;
++		snps,wr_osr_lmt = <4>;
++		snps,rd_osr_lmt = <4>;
++		snps,blen = <256 128 64 32 0 0 0>;
++	};
++
+ 	tdm_ext: tdm-ext-clock {
+ 		compatible = "fixed-clock";
+ 		clock-output-names = "tdm_ext";
+@@ -489,6 +496,68 @@
+ 			#gpio-cells = <2>;
+ 		};
+ 
++		gmac0: ethernet@16030000 {
++			compatible = "starfive,jh7110-dwmac", "snps,dwmac-5.20";
++			reg = <0x0 0x16030000 0x0 0x10000>;
++			clocks = <&aoncrg JH7110_AONCLK_GMAC0_AXI>,
++				 <&aoncrg JH7110_AONCLK_GMAC0_AHB>,
++				 <&syscrg JH7110_SYSCLK_GMAC0_PTP>,
++				 <&aoncrg JH7110_AONCLK_GMAC0_TX_INV>,
++				 <&syscrg JH7110_SYSCLK_GMAC0_GTXC>;
++			clock-names = "stmmaceth", "pclk", "ptp_ref",
++				      "tx", "gtx";
++			resets = <&aoncrg JH7110_AONRST_GMAC0_AXI>,
++				 <&aoncrg JH7110_AONRST_GMAC0_AHB>;
++			reset-names = "stmmaceth", "ahb";
++			interrupts = <7>, <6>, <5>;
++			interrupt-names = "macirq", "eth_wake_irq", "eth_lpi";
++			rx-fifo-depth = <2048>;
++			tx-fifo-depth = <2048>;
++			snps,multicast-filter-bins = <64>;
++			snps,perfect-filter-entries = <8>;
++			snps,fixed-burst;
++			snps,no-pbl-x8;
++			snps,force_thresh_dma_mode;
++			snps,axi-config = <&stmmac_axi_setup>;
++			snps,tso;
++			snps,en-tx-lpi-clockgating;
++			snps,txpbl = <16>;
++			snps,rxpbl = <16>;
++			starfive,syscon = <&aon_syscon 0xc 0x12>;
++			status = "disabled";
++		};
++
++		gmac1: ethernet@16040000 {
++			compatible = "starfive,jh7110-dwmac", "snps,dwmac-5.20";
++			reg = <0x0 0x16040000 0x0 0x10000>;
++			clocks = <&syscrg JH7110_SYSCLK_GMAC1_AXI>,
++				 <&syscrg JH7110_SYSCLK_GMAC1_AHB>,
++				 <&syscrg JH7110_SYSCLK_GMAC1_PTP>,
++				 <&syscrg JH7110_SYSCLK_GMAC1_TX_INV>,
++				 <&syscrg JH7110_SYSCLK_GMAC1_GTXC>;
++			clock-names = "stmmaceth", "pclk", "ptp_ref",
++				      "tx", "gtx";
++			resets = <&syscrg JH7110_SYSRST_GMAC1_AXI>,
++				 <&syscrg JH7110_SYSRST_GMAC1_AHB>;
++			reset-names = "stmmaceth", "ahb";
++			interrupts = <78>, <77>, <76>;
++			interrupt-names = "macirq", "eth_wake_irq", "eth_lpi";
++			rx-fifo-depth = <2048>;
++			tx-fifo-depth = <2048>;
++			snps,multicast-filter-bins = <64>;
++			snps,perfect-filter-entries = <8>;
++			snps,fixed-burst;
++			snps,no-pbl-x8;
++			snps,force_thresh_dma_mode;
++			snps,axi-config = <&stmmac_axi_setup>;
++			snps,tso;
++			snps,en-tx-lpi-clockgating;
++			snps,txpbl = <16>;
++			snps,rxpbl = <16>;
++			starfive,syscon = <&sys_syscon 0x90 0x2>;
++			status = "disabled";
++		};
++
+ 		aoncrg: clock-controller@17000000 {
+ 			compatible = "starfive,jh7110-aoncrg";
+ 			reg = <0x0 0x17000000 0x0 0x10000>;

+ 128 - 0
target/linux/starfive/patches-6.1/0047-riscv-dts-starfive-visionfive-2-Add-configuration-of.patch

@@ -0,0 +1,128 @@
+From 6fd84cb9cceaa711671500a92dcee5b1072ab95a Mon Sep 17 00:00:00 2001
+From: Samin Guo <[email protected]>
+Date: Tue, 1 Nov 2022 18:11:02 +0800
+Subject: [PATCH 047/122] riscv: dts: starfive: visionfive 2: Add configuration
+ of gmac and phy
+
+v1.3B:
+  v1.3B uses motorcomm YT8531(rgmii-id phy) x2, need delay and
+  inverse configurations.
+  The tx_clk of v1.3B uses an external clock and needs to be
+  switched to an external clock source.
+
+v1.2A:
+  v1.2A gmac0 uses motorcomm YT8531(rgmii-id) PHY, and needs delay
+  configurations.
+  v1.2A gmac1 uses motorcomm YT8512(rmii) PHY, and needs to
+  switch rx and rx to external clock sources.
+
+Tested-by: Tommaso Merciai <[email protected]>
+Signed-off-by: Samin Guo <[email protected]>
+---
+ .../jh7110-starfive-visionfive-2-v1.2a.dts    | 13 +++++++
+ .../jh7110-starfive-visionfive-2-v1.3b.dts    | 27 +++++++++++++++
+ .../jh7110-starfive-visionfive-2.dtsi         | 34 +++++++++++++++++++
+ 3 files changed, 74 insertions(+)
+
+--- a/arch/riscv/boot/dts/starfive/jh7110-starfive-visionfive-2-v1.2a.dts
++++ b/arch/riscv/boot/dts/starfive/jh7110-starfive-visionfive-2-v1.2a.dts
+@@ -11,3 +11,16 @@
+ 	model = "StarFive VisionFive 2 v1.2A";
+ 	compatible = "starfive,visionfive-2-v1.2a", "starfive,jh7110";
+ };
++
++&gmac1 {
++	phy-mode = "rmii";
++	assigned-clocks = <&syscrg JH7110_SYSCLK_GMAC1_TX>,
++			  <&syscrg JH7110_SYSCLK_GMAC1_RX>;
++	assigned-clock-parents = <&syscrg JH7110_SYSCLK_GMAC1_RMII_RTX>,
++				 <&syscrg JH7110_SYSCLK_GMAC1_RMII_RTX>;
++};
++
++&phy0 {
++	rx-internal-delay-ps = <1900>;
++	tx-internal-delay-ps = <1350>;
++};
+--- a/arch/riscv/boot/dts/starfive/jh7110-starfive-visionfive-2-v1.3b.dts
++++ b/arch/riscv/boot/dts/starfive/jh7110-starfive-visionfive-2-v1.3b.dts
+@@ -11,3 +11,30 @@
+ 	model = "StarFive VisionFive 2 v1.3B";
+ 	compatible = "starfive,visionfive-2-v1.3b", "starfive,jh7110";
+ };
++
++&gmac0 {
++	starfive,tx-use-rgmii-clk;
++	assigned-clocks = <&aoncrg JH7110_AONCLK_GMAC0_TX>;
++	assigned-clock-parents = <&aoncrg JH7110_AONCLK_GMAC0_RMII_RTX>;
++};
++
++&gmac1 {
++	starfive,tx-use-rgmii-clk;
++	assigned-clocks = <&syscrg JH7110_SYSCLK_GMAC1_TX>;
++	assigned-clock-parents = <&syscrg JH7110_SYSCLK_GMAC1_RMII_RTX>;
++};
++
++&phy0 {
++	motorcomm,tx-clk-adj-enabled;
++	motorcomm,tx-clk-100-inverted;
++	motorcomm,tx-clk-1000-inverted;
++	rx-internal-delay-ps = <1500>;
++	tx-internal-delay-ps = <1500>;
++};
++
++&phy1 {
++	motorcomm,tx-clk-adj-enabled;
++	motorcomm,tx-clk-100-inverted;
++	rx-internal-delay-ps = <300>;
++	tx-internal-delay-ps = <0>;
++};
+--- a/arch/riscv/boot/dts/starfive/jh7110-starfive-visionfive-2.dtsi
++++ b/arch/riscv/boot/dts/starfive/jh7110-starfive-visionfive-2.dtsi
+@@ -11,6 +11,8 @@
+ 
+ / {
+ 	aliases {
++		ethernet0 = &gmac0;
++		ethernet1 = &gmac1;
+ 		i2c0 = &i2c0;
+ 		i2c2 = &i2c2;
+ 		i2c5 = &i2c5;
+@@ -86,6 +88,38 @@
+ 	clock-frequency = <49152000>;
+ };
+ 
++&gmac0 {
++	phy-handle = <&phy0>;
++	phy-mode = "rgmii-id";
++	status = "okay";
++
++	mdio {
++		#address-cells = <1>;
++		#size-cells = <0>;
++		compatible = "snps,dwmac-mdio";
++
++		phy0: ethernet-phy@0 {
++			reg = <0>;
++		};
++	};
++};
++
++&gmac1 {
++	phy-handle = <&phy1>;
++	phy-mode = "rgmii-id";
++	status = "okay";
++
++	mdio {
++		#address-cells = <1>;
++		#size-cells = <0>;
++		compatible = "snps,dwmac-mdio";
++
++		phy1: ethernet-phy@1 {
++			reg = <0>;
++		};
++	};
++};
++
+ &i2c0 {
+ 	clock-frequency = <100000>;
+ 	i2c-sda-hold-time-ns = <300>;

+ 147 - 0
target/linux/starfive/patches-6.1/0048-dt-bindings-net-Add-Motorcomm-yt8xxx-ethernet-phy.patch

@@ -0,0 +1,147 @@
+From 96edc2f71ea7ac6683011609f6d1f51ae9ea0b7a Mon Sep 17 00:00:00 2001
+From: Frank Sae <[email protected]>
+Date: Thu, 2 Feb 2023 11:00:33 +0800
+Subject: [PATCH 048/122] dt-bindings: net: Add Motorcomm yt8xxx ethernet phy
+
+Add a YAML binding document for the Motorcomm yt8xxx Ethernet phy.
+
+Signed-off-by: Frank Sae <[email protected]>
+Reviewed-by: Rob Herring <[email protected]>
+Signed-off-by: David S. Miller <[email protected]>
+---
+ .../bindings/net/motorcomm,yt8xxx.yaml        | 117 ++++++++++++++++++
+ .../devicetree/bindings/vendor-prefixes.yaml  |   2 +
+ 2 files changed, 119 insertions(+)
+ create mode 100644 Documentation/devicetree/bindings/net/motorcomm,yt8xxx.yaml
+
+--- /dev/null
++++ b/Documentation/devicetree/bindings/net/motorcomm,yt8xxx.yaml
+@@ -0,0 +1,117 @@
++# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
++%YAML 1.2
++---
++$id: http://devicetree.org/schemas/net/motorcomm,yt8xxx.yaml#
++$schema: http://devicetree.org/meta-schemas/core.yaml#
++
++title: MotorComm yt8xxx Ethernet PHY
++
++maintainers:
++  - Frank Sae <[email protected]>
++
++allOf:
++  - $ref: ethernet-phy.yaml#
++
++properties:
++  compatible:
++    enum:
++      - ethernet-phy-id4f51.e91a
++      - ethernet-phy-id4f51.e91b
++
++  rx-internal-delay-ps:
++    description: |
++      RGMII RX Clock Delay used only when PHY operates in RGMII mode with
++      internal delay (phy-mode is 'rgmii-id' or 'rgmii-rxid') in pico-seconds.
++    enum: [ 0, 150, 300, 450, 600, 750, 900, 1050, 1200, 1350, 1500, 1650,
++            1800, 1900, 1950, 2050, 2100, 2200, 2250, 2350, 2500, 2650, 2800,
++            2950, 3100, 3250, 3400, 3550, 3700, 3850, 4000, 4150 ]
++    default: 1950
++
++  tx-internal-delay-ps:
++    description: |
++      RGMII TX Clock Delay used only when PHY operates in RGMII mode with
++      internal delay (phy-mode is 'rgmii-id' or 'rgmii-txid') in pico-seconds.
++    enum: [ 0, 150, 300, 450, 600, 750, 900, 1050, 1200, 1350, 1500, 1650, 1800,
++            1950, 2100, 2250 ]
++    default: 1950
++
++  motorcomm,clk-out-frequency-hz:
++    description: clock output on clock output pin.
++    enum: [0, 25000000, 125000000]
++    default: 0
++
++  motorcomm,keep-pll-enabled:
++    description: |
++      If set, keep the PLL enabled even if there is no link. Useful if you
++      want to use the clock output without an ethernet link.
++    type: boolean
++
++  motorcomm,auto-sleep-disabled:
++    description: |
++      If set, PHY will not enter sleep mode and close AFE after unplug cable
++      for a timer.
++    type: boolean
++
++  motorcomm,tx-clk-adj-enabled:
++    description: |
++      This configuration is mainly to adapt to VF2 with JH7110 SoC.
++      Useful if you want to use tx-clk-xxxx-inverted to adj the delay of tx clk.
++    type: boolean
++
++  motorcomm,tx-clk-10-inverted:
++    description: |
++      Use original or inverted RGMII Transmit PHY Clock to drive the RGMII
++      Transmit PHY Clock delay train configuration when speed is 10Mbps.
++    type: boolean
++
++  motorcomm,tx-clk-100-inverted:
++    description: |
++      Use original or inverted RGMII Transmit PHY Clock to drive the RGMII
++      Transmit PHY Clock delay train configuration when speed is 100Mbps.
++    type: boolean
++
++  motorcomm,tx-clk-1000-inverted:
++    description: |
++      Use original or inverted RGMII Transmit PHY Clock to drive the RGMII
++      Transmit PHY Clock delay train configuration when speed is 1000Mbps.
++    type: boolean
++
++unevaluatedProperties: false
++
++examples:
++  - |
++    mdio {
++        #address-cells = <1>;
++        #size-cells = <0>;
++        phy-mode = "rgmii-id";
++        ethernet-phy@4 {
++            /*  Only needed to make DT lint tools work. Do not copy/paste
++             *  into real DTS files.
++             */
++            compatible = "ethernet-phy-id4f51.e91a";
++
++            reg = <4>;
++            rx-internal-delay-ps = <2100>;
++            tx-internal-delay-ps = <150>;
++            motorcomm,clk-out-frequency-hz = <0>;
++            motorcomm,keep-pll-enabled;
++            motorcomm,auto-sleep-disabled;
++        };
++    };
++  - |
++    mdio {
++        #address-cells = <1>;
++        #size-cells = <0>;
++        phy-mode = "rgmii";
++        ethernet-phy@5 {
++            /*  Only needed to make DT lint tools work. Do not copy/paste
++             *  into real DTS files.
++             */
++            compatible = "ethernet-phy-id4f51.e91a";
++
++            reg = <5>;
++            motorcomm,clk-out-frequency-hz = <125000000>;
++            motorcomm,keep-pll-enabled;
++            motorcomm,auto-sleep-disabled;
++        };
++    };
+--- a/Documentation/devicetree/bindings/vendor-prefixes.yaml
++++ b/Documentation/devicetree/bindings/vendor-prefixes.yaml
+@@ -831,6 +831,8 @@ patternProperties:
+     description: Moortec Semiconductor Ltd.
+   "^mosaixtech,.*":
+     description: Mosaix Technologies, Inc.
++  "^motorcomm,.*":
++    description: MotorComm, Inc.
+   "^motorola,.*":
+     description: Motorola, Inc.
+   "^moxa,.*":

+ 34 - 0
target/linux/starfive/patches-6.1/0049-dt-bindings-net-motorcomm-Add-pad-driver-strength-cf.patch

@@ -0,0 +1,34 @@
+From 2d146c6e550a4fb7f24ca44739cf14594cc2f892 Mon Sep 17 00:00:00 2001
+From: Samin Guo <[email protected]>
+Date: Tue, 25 Apr 2023 18:51:15 +0800
+Subject: [PATCH 049/122] dt-bindings: net: motorcomm: Add pad driver strength
+ cfg
+
+The motorcomm phy (YT8531) supports the ability to adjust the drive
+strength of the rx_clk/rx_data, the value range of pad driver
+strength is 0 to 7.
+
+Signed-off-by: Samin Guo <[email protected]>
+---
+ .../devicetree/bindings/net/motorcomm,yt8xxx.yaml      | 10 ++++++++++
+ 1 file changed, 10 insertions(+)
+
+--- a/Documentation/devicetree/bindings/net/motorcomm,yt8xxx.yaml
++++ b/Documentation/devicetree/bindings/net/motorcomm,yt8xxx.yaml
+@@ -18,6 +18,16 @@ properties:
+       - ethernet-phy-id4f51.e91a
+       - ethernet-phy-id4f51.e91b
+ 
++  rx-clk-driver-strength:
++    description: drive strength of rx_clk pad.
++    enum: [ 0, 1, 2, 3, 4, 5, 6, 7 ]
++    default: 3
++
++  rx-data-driver-strength:
++    description: drive strength of rxd/rx_ctl rgmii pad.
++    enum: [ 0, 1, 2, 3, 4, 5, 6, 7 ]
++    default: 3
++
+   rx-internal-delay-ps:
+     description: |
+       RGMII RX Clock Delay used only when PHY operates in RGMII mode with

+ 34 - 0
target/linux/starfive/patches-6.1/0050-riscv-dts-starfive-visionfive-2-v1.3B-Set-the-driver.patch

@@ -0,0 +1,34 @@
+From c156cb9ec64669600c96dbb01bf38dd2370b1850 Mon Sep 17 00:00:00 2001
+From: Samin Guo <[email protected]>
+Date: Wed, 26 Apr 2023 14:41:12 +0800
+Subject: [PATCH 050/122] riscv: dts: starfive: visionfive-2-v1.3B: Set the
+ driver strength of RXC/RXD
+
+VisionFive 2 v1.3B needs to increase the driver strength of rxd/rxc
+to increase the stability of gmac's transmission.
+
+Signed-off-by: Samin Guo <[email protected]>
+---
+ .../boot/dts/starfive/jh7110-starfive-visionfive-2-v1.3b.dts  | 4 ++++
+ 1 file changed, 4 insertions(+)
+
+--- a/arch/riscv/boot/dts/starfive/jh7110-starfive-visionfive-2-v1.3b.dts
++++ b/arch/riscv/boot/dts/starfive/jh7110-starfive-visionfive-2-v1.3b.dts
+@@ -28,6 +28,8 @@
+ 	motorcomm,tx-clk-adj-enabled;
+ 	motorcomm,tx-clk-100-inverted;
+ 	motorcomm,tx-clk-1000-inverted;
++	rx-clk-driver-strength = <0x6>;
++	rx-data-driver-strength = <0x3>;
+ 	rx-internal-delay-ps = <1500>;
+ 	tx-internal-delay-ps = <1500>;
+ };
+@@ -35,6 +37,8 @@
+ &phy1 {
+ 	motorcomm,tx-clk-adj-enabled;
+ 	motorcomm,tx-clk-100-inverted;
++	rx-clk-driver-strength = <0x6>;
++	rx-data-driver-strength = <0x3>;
+ 	rx-internal-delay-ps = <300>;
+ 	tx-internal-delay-ps = <0>;
+ };

+ 193 - 0
target/linux/starfive/patches-6.1/0051-dt-bindings-clock-Add-StarFive-JH7110-System-Top-Gro.patch

@@ -0,0 +1,193 @@
+From 84575863e4cf1a5dd877a11d31115c19004ac36a Mon Sep 17 00:00:00 2001
+From: Xingyu Wu <[email protected]>
+Date: Thu, 18 May 2023 18:12:24 +0800
+Subject: [PATCH 051/122] dt-bindings: clock: Add StarFive JH7110
+ System-Top-Group clock and reset generator
+
+Add bindings for the System-Top-Group clock and reset generator (STGCRG)
+on the JH7110 RISC-V SoC by StarFive Ltd.
+
+Reviewed-by: Krzysztof Kozlowski <[email protected]>
+Signed-off-by: Xingyu Wu <[email protected]>
+---
+ .../clock/starfive,jh7110-stgcrg.yaml         | 82 +++++++++++++++++++
+ .../dt-bindings/clock/starfive,jh7110-crg.h   | 34 ++++++++
+ .../dt-bindings/reset/starfive,jh7110-crg.h   | 28 +++++++
+ 3 files changed, 144 insertions(+)
+ create mode 100644 Documentation/devicetree/bindings/clock/starfive,jh7110-stgcrg.yaml
+
+--- /dev/null
++++ b/Documentation/devicetree/bindings/clock/starfive,jh7110-stgcrg.yaml
+@@ -0,0 +1,82 @@
++# SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause
++%YAML 1.2
++---
++$id: http://devicetree.org/schemas/clock/starfive,jh7110-stgcrg.yaml#
++$schema: http://devicetree.org/meta-schemas/core.yaml#
++
++title: StarFive JH7110 System-Top-Group Clock and Reset Generator
++
++maintainers:
++  - Xingyu Wu <[email protected]>
++
++properties:
++  compatible:
++    const: starfive,jh7110-stgcrg
++
++  reg:
++    maxItems: 1
++
++  clocks:
++    items:
++      - description: Main Oscillator (24 MHz)
++      - description: HIFI4 core
++      - description: STG AXI/AHB
++      - description: USB (125 MHz)
++      - description: CPU Bus
++      - description: HIFI4 Axi
++      - description: NOC STG Bus
++      - description: APB Bus
++
++  clock-names:
++    items:
++      - const: osc
++      - const: hifi4_core
++      - const: stg_axiahb
++      - const: usb_125m
++      - const: cpu_bus
++      - const: hifi4_axi
++      - const: nocstg_bus
++      - const: apb_bus
++
++  '#clock-cells':
++    const: 1
++    description:
++      See <dt-bindings/clock/starfive,jh7110-crg.h> for valid indices.
++
++  '#reset-cells':
++    const: 1
++    description:
++      See <dt-bindings/reset/starfive,jh7110-crg.h> for valid indices.
++
++required:
++  - compatible
++  - reg
++  - clocks
++  - clock-names
++  - '#clock-cells'
++  - '#reset-cells'
++
++additionalProperties: false
++
++examples:
++  - |
++    #include <dt-bindings/clock/starfive,jh7110-crg.h>
++
++    stgcrg: clock-controller@10230000 {
++        compatible = "starfive,jh7110-stgcrg";
++        reg = <0x10230000 0x10000>;
++        clocks = <&osc>,
++                 <&syscrg JH7110_SYSCLK_HIFI4_CORE>,
++                 <&syscrg JH7110_SYSCLK_STG_AXIAHB>,
++                 <&syscrg JH7110_SYSCLK_USB_125M>,
++                 <&syscrg JH7110_SYSCLK_CPU_BUS>,
++                 <&syscrg JH7110_SYSCLK_HIFI4_AXI>,
++                 <&syscrg JH7110_SYSCLK_NOCSTG_BUS>,
++                 <&syscrg JH7110_SYSCLK_APB_BUS>;
++        clock-names = "osc", "hifi4_core",
++                      "stg_axiahb", "usb_125m",
++                      "cpu_bus", "hifi4_axi",
++                      "nocstg_bus", "apb_bus";
++        #clock-cells = <1>;
++        #reset-cells = <1>;
++    };
+--- a/include/dt-bindings/clock/starfive,jh7110-crg.h
++++ b/include/dt-bindings/clock/starfive,jh7110-crg.h
+@@ -1,6 +1,7 @@
+ /* SPDX-License-Identifier: GPL-2.0 OR MIT */
+ /*
+  * Copyright 2022 Emil Renner Berthing <[email protected]>
++ * Copyright 2022 StarFive Technology Co., Ltd.
+  */
+ 
+ #ifndef __DT_BINDINGS_CLOCK_STARFIVE_JH7110_CRG_H__
+@@ -224,4 +225,37 @@
+ 
+ #define JH7110_AONCLK_END			14
+ 
++/* STGCRG clocks */
++#define JH7110_STGCLK_HIFI4_CLK_CORE		0
++#define JH7110_STGCLK_USB0_APB			1
++#define JH7110_STGCLK_USB0_UTMI_APB		2
++#define JH7110_STGCLK_USB0_AXI			3
++#define JH7110_STGCLK_USB0_LPM			4
++#define JH7110_STGCLK_USB0_STB			5
++#define JH7110_STGCLK_USB0_APP_125		6
++#define JH7110_STGCLK_USB0_REFCLK		7
++#define JH7110_STGCLK_PCIE0_AXI_MST0		8
++#define JH7110_STGCLK_PCIE0_APB			9
++#define JH7110_STGCLK_PCIE0_TL			10
++#define JH7110_STGCLK_PCIE1_AXI_MST0		11
++#define JH7110_STGCLK_PCIE1_APB			12
++#define JH7110_STGCLK_PCIE1_TL			13
++#define JH7110_STGCLK_PCIE_SLV_MAIN		14
++#define JH7110_STGCLK_SEC_AHB			15
++#define JH7110_STGCLK_SEC_MISC_AHB		16
++#define JH7110_STGCLK_GRP0_MAIN			17
++#define JH7110_STGCLK_GRP0_BUS			18
++#define JH7110_STGCLK_GRP0_STG			19
++#define JH7110_STGCLK_GRP1_MAIN			20
++#define JH7110_STGCLK_GRP1_BUS			21
++#define JH7110_STGCLK_GRP1_STG			22
++#define JH7110_STGCLK_GRP1_HIFI			23
++#define JH7110_STGCLK_E2_RTC			24
++#define JH7110_STGCLK_E2_CORE			25
++#define JH7110_STGCLK_E2_DBG			26
++#define JH7110_STGCLK_DMA1P_AXI			27
++#define JH7110_STGCLK_DMA1P_AHB			28
++
++#define JH7110_STGCLK_END			29
++
+ #endif /* __DT_BINDINGS_CLOCK_STARFIVE_JH7110_CRG_H__ */
+--- a/include/dt-bindings/reset/starfive,jh7110-crg.h
++++ b/include/dt-bindings/reset/starfive,jh7110-crg.h
+@@ -1,6 +1,7 @@
+ /* SPDX-License-Identifier: GPL-2.0 OR MIT */
+ /*
+  * Copyright (C) 2022 Emil Renner Berthing <[email protected]>
++ * Copyright (C) 2022 StarFive Technology Co., Ltd.
+  */
+ 
+ #ifndef __DT_BINDINGS_RESET_STARFIVE_JH7110_CRG_H__
+@@ -151,4 +152,31 @@
+ 
+ #define JH7110_AONRST_END			8
+ 
++/* STGCRG resets */
++#define JH7110_STGRST_SYSCON			0
++#define JH7110_STGRST_HIFI4_CORE		1
++#define JH7110_STGRST_HIFI4_AXI			2
++#define JH7110_STGRST_SEC_AHB			3
++#define JH7110_STGRST_E24_CORE			4
++#define JH7110_STGRST_DMA1P_AXI			5
++#define JH7110_STGRST_DMA1P_AHB			6
++#define JH7110_STGRST_USB0_AXI			7
++#define JH7110_STGRST_USB0_APB			8
++#define JH7110_STGRST_USB0_UTMI_APB		9
++#define JH7110_STGRST_USB0_PWRUP		10
++#define JH7110_STGRST_PCIE0_AXI_MST0		11
++#define JH7110_STGRST_PCIE0_AXI_SLV0		12
++#define JH7110_STGRST_PCIE0_AXI_SLV		13
++#define JH7110_STGRST_PCIE0_BRG			14
++#define JH7110_STGRST_PCIE0_CORE		15
++#define JH7110_STGRST_PCIE0_APB			16
++#define JH7110_STGRST_PCIE1_AXI_MST0		17
++#define JH7110_STGRST_PCIE1_AXI_SLV0		18
++#define JH7110_STGRST_PCIE1_AXI_SLV		19
++#define JH7110_STGRST_PCIE1_BRG			20
++#define JH7110_STGRST_PCIE1_CORE		21
++#define JH7110_STGRST_PCIE1_APB			22
++
++#define JH7110_STGRST_END			23
++
+ #endif /* __DT_BINDINGS_RESET_STARFIVE_JH7110_CRG_H__ */

+ 218 - 0
target/linux/starfive/patches-6.1/0052-clk-starfive-Add-StarFive-JH7110-System-Top-Group-cl.patch

@@ -0,0 +1,218 @@
+From 9a02d66b0515d987037d0229b99367412b9eb38c Mon Sep 17 00:00:00 2001
+From: Emil Renner Berthing <[email protected]>
+Date: Thu, 18 May 2023 18:12:25 +0800
+Subject: [PATCH 052/122] clk: starfive: Add StarFive JH7110 System-Top-Group
+ clock driver
+
+Add driver for the StarFive JH7110 System-Top-Group clock controller.
+
+Co-developed-by: Xingyu Wu <[email protected]>
+Signed-off-by: Xingyu Wu <[email protected]>
+Signed-off-by: Emil Renner Berthing <[email protected]>
+---
+ drivers/clk/starfive/Kconfig                  |  11 ++
+ drivers/clk/starfive/Makefile                 |   1 +
+ .../clk/starfive/clk-starfive-jh7110-stg.c    | 173 ++++++++++++++++++
+ 3 files changed, 185 insertions(+)
+ create mode 100644 drivers/clk/starfive/clk-starfive-jh7110-stg.c
+
+--- a/drivers/clk/starfive/Kconfig
++++ b/drivers/clk/starfive/Kconfig
+@@ -51,3 +51,14 @@ config CLK_STARFIVE_JH7110_AON
+ 	help
+ 	  Say yes here to support the always-on clock controller on the
+ 	  StarFive JH7110 SoC.
++
++config CLK_STARFIVE_JH7110_STG
++	tristate "StarFive JH7110 System-Top-Group clock support"
++	depends on CLK_STARFIVE_JH7110_SYS
++	select AUXILIARY_BUS
++	select CLK_STARFIVE_JH71X0
++	select RESET_STARFIVE_JH7110
++	default m if ARCH_STARFIVE
++	help
++	  Say yes here to support the System-Top-Group clock controller
++	  on the StarFive JH7110 SoC.
+--- a/drivers/clk/starfive/Makefile
++++ b/drivers/clk/starfive/Makefile
+@@ -7,3 +7,4 @@ obj-$(CONFIG_CLK_STARFIVE_JH7100_AUDIO)
+ obj-$(CONFIG_CLK_STARFIVE_JH7110_PLL)	+= clk-starfive-jh7110-pll.o
+ obj-$(CONFIG_CLK_STARFIVE_JH7110_SYS)	+= clk-starfive-jh7110-sys.o
+ obj-$(CONFIG_CLK_STARFIVE_JH7110_AON)	+= clk-starfive-jh7110-aon.o
++obj-$(CONFIG_CLK_STARFIVE_JH7110_STG)	+= clk-starfive-jh7110-stg.o
+--- /dev/null
++++ b/drivers/clk/starfive/clk-starfive-jh7110-stg.c
+@@ -0,0 +1,173 @@
++// SPDX-License-Identifier: GPL-2.0
++/*
++ * StarFive JH7110 System-Top-Group Clock Driver
++ *
++ * Copyright (C) 2022 Emil Renner Berthing <[email protected]>
++ * Copyright (C) 2022 StarFive Technology Co., Ltd.
++ */
++
++#include <linux/clk-provider.h>
++#include <linux/io.h>
++#include <linux/platform_device.h>
++
++#include <dt-bindings/clock/starfive,jh7110-crg.h>
++
++#include "clk-starfive-jh7110.h"
++
++/* external clocks */
++#define JH7110_STGCLK_OSC			(JH7110_STGCLK_END + 0)
++#define JH7110_STGCLK_HIFI4_CORE		(JH7110_STGCLK_END + 1)
++#define JH7110_STGCLK_STG_AXIAHB		(JH7110_STGCLK_END + 2)
++#define JH7110_STGCLK_USB_125M			(JH7110_STGCLK_END + 3)
++#define JH7110_STGCLK_CPU_BUS			(JH7110_STGCLK_END + 4)
++#define JH7110_STGCLK_HIFI4_AXI			(JH7110_STGCLK_END + 5)
++#define JH7110_STGCLK_NOCSTG_BUS		(JH7110_STGCLK_END + 6)
++#define JH7110_STGCLK_APB_BUS			(JH7110_STGCLK_END + 7)
++#define JH7110_STGCLK_EXT_END			(JH7110_STGCLK_END + 8)
++
++static const struct jh71x0_clk_data jh7110_stgclk_data[] = {
++	/* hifi4 */
++	JH71X0_GATE(JH7110_STGCLK_HIFI4_CLK_CORE, "hifi4_clk_core", 0,
++		    JH7110_STGCLK_HIFI4_CORE),
++	/* usb */
++	JH71X0_GATE(JH7110_STGCLK_USB0_APB, "usb0_apb", 0, JH7110_STGCLK_APB_BUS),
++	JH71X0_GATE(JH7110_STGCLK_USB0_UTMI_APB, "usb0_utmi_apb", 0, JH7110_STGCLK_APB_BUS),
++	JH71X0_GATE(JH7110_STGCLK_USB0_AXI, "usb0_axi", 0, JH7110_STGCLK_STG_AXIAHB),
++	JH71X0_GDIV(JH7110_STGCLK_USB0_LPM, "usb0_lpm", 0, 2, JH7110_STGCLK_OSC),
++	JH71X0_GDIV(JH7110_STGCLK_USB0_STB, "usb0_stb", 0, 4, JH7110_STGCLK_OSC),
++	JH71X0_GATE(JH7110_STGCLK_USB0_APP_125, "usb0_app_125", 0, JH7110_STGCLK_USB_125M),
++	JH71X0__DIV(JH7110_STGCLK_USB0_REFCLK, "usb0_refclk", 2, JH7110_STGCLK_OSC),
++	/* pci-e */
++	JH71X0_GATE(JH7110_STGCLK_PCIE0_AXI_MST0, "pcie0_axi_mst0", 0,
++		    JH7110_STGCLK_STG_AXIAHB),
++	JH71X0_GATE(JH7110_STGCLK_PCIE0_APB, "pcie0_apb", 0, JH7110_STGCLK_APB_BUS),
++	JH71X0_GATE(JH7110_STGCLK_PCIE0_TL, "pcie0_tl", 0, JH7110_STGCLK_STG_AXIAHB),
++	JH71X0_GATE(JH7110_STGCLK_PCIE1_AXI_MST0, "pcie1_axi_mst0", 0,
++		    JH7110_STGCLK_STG_AXIAHB),
++	JH71X0_GATE(JH7110_STGCLK_PCIE1_APB, "pcie1_apb", 0, JH7110_STGCLK_APB_BUS),
++	JH71X0_GATE(JH7110_STGCLK_PCIE1_TL, "pcie1_tl", 0, JH7110_STGCLK_STG_AXIAHB),
++	JH71X0_GATE(JH7110_STGCLK_PCIE_SLV_MAIN, "pcie_slv_main", CLK_IS_CRITICAL,
++		    JH7110_STGCLK_STG_AXIAHB),
++	/* security */
++	JH71X0_GATE(JH7110_STGCLK_SEC_AHB, "sec_ahb", 0, JH7110_STGCLK_STG_AXIAHB),
++	JH71X0_GATE(JH7110_STGCLK_SEC_MISC_AHB, "sec_misc_ahb", 0, JH7110_STGCLK_STG_AXIAHB),
++	/* stg mtrx */
++	JH71X0_GATE(JH7110_STGCLK_GRP0_MAIN, "mtrx_grp0_main", CLK_IS_CRITICAL,
++		    JH7110_STGCLK_CPU_BUS),
++	JH71X0_GATE(JH7110_STGCLK_GRP0_BUS, "mtrx_grp0_bus", CLK_IS_CRITICAL,
++		    JH7110_STGCLK_NOCSTG_BUS),
++	JH71X0_GATE(JH7110_STGCLK_GRP0_STG, "mtrx_grp0_stg", CLK_IS_CRITICAL,
++		    JH7110_STGCLK_STG_AXIAHB),
++	JH71X0_GATE(JH7110_STGCLK_GRP1_MAIN, "mtrx_grp1_main", CLK_IS_CRITICAL,
++		    JH7110_STGCLK_CPU_BUS),
++	JH71X0_GATE(JH7110_STGCLK_GRP1_BUS, "mtrx_grp1_bus", CLK_IS_CRITICAL,
++		    JH7110_STGCLK_NOCSTG_BUS),
++	JH71X0_GATE(JH7110_STGCLK_GRP1_STG, "mtrx_grp1_stg", CLK_IS_CRITICAL,
++		    JH7110_STGCLK_STG_AXIAHB),
++	JH71X0_GATE(JH7110_STGCLK_GRP1_HIFI, "mtrx_grp1_hifi", CLK_IS_CRITICAL,
++		    JH7110_STGCLK_HIFI4_AXI),
++	/* e24_rvpi */
++	JH71X0_GDIV(JH7110_STGCLK_E2_RTC, "e2_rtc", 0, 24, JH7110_STGCLK_OSC),
++	JH71X0_GATE(JH7110_STGCLK_E2_CORE, "e2_core", 0, JH7110_STGCLK_STG_AXIAHB),
++	JH71X0_GATE(JH7110_STGCLK_E2_DBG, "e2_dbg", 0, JH7110_STGCLK_STG_AXIAHB),
++	/* dw_sgdma1p */
++	JH71X0_GATE(JH7110_STGCLK_DMA1P_AXI, "dma1p_axi", 0, JH7110_STGCLK_STG_AXIAHB),
++	JH71X0_GATE(JH7110_STGCLK_DMA1P_AHB, "dma1p_ahb", 0, JH7110_STGCLK_STG_AXIAHB),
++};
++
++static struct clk_hw *jh7110_stgclk_get(struct of_phandle_args *clkspec, void *data)
++{
++	struct jh71x0_clk_priv *priv = data;
++	unsigned int idx = clkspec->args[0];
++
++	if (idx < JH7110_STGCLK_END)
++		return &priv->reg[idx].hw;
++
++	return ERR_PTR(-EINVAL);
++}
++
++static int jh7110_stgcrg_probe(struct platform_device *pdev)
++{
++	struct jh71x0_clk_priv *priv;
++	unsigned int idx;
++	int ret;
++
++	priv = devm_kzalloc(&pdev->dev, struct_size(priv, reg, JH7110_STGCLK_END),
++			    GFP_KERNEL);
++	if (!priv)
++		return -ENOMEM;
++
++	spin_lock_init(&priv->rmw_lock);
++	priv->dev = &pdev->dev;
++	priv->base = devm_platform_ioremap_resource(pdev, 0);
++	if (IS_ERR(priv->base))
++		return PTR_ERR(priv->base);
++
++	for (idx = 0; idx < JH7110_STGCLK_END; idx++) {
++		u32 max = jh7110_stgclk_data[idx].max;
++		struct clk_parent_data parents[4] = {};
++		struct clk_init_data init = {
++			.name = jh7110_stgclk_data[idx].name,
++			.ops = starfive_jh71x0_clk_ops(max),
++			.parent_data = parents,
++			.num_parents =
++				((max & JH71X0_CLK_MUX_MASK) >> JH71X0_CLK_MUX_SHIFT) + 1,
++			.flags = jh7110_stgclk_data[idx].flags,
++		};
++		struct jh71x0_clk *clk = &priv->reg[idx];
++		const char *fw_name[JH7110_STGCLK_EXT_END - JH7110_STGCLK_END] = {
++			"osc",
++			"hifi4_core",
++			"stg_axiahb",
++			"usb_125m",
++			"cpu_bus",
++			"hifi4_axi",
++			"nocstg_bus",
++			"apb_bus"
++		};
++		unsigned int i;
++
++		for (i = 0; i < init.num_parents; i++) {
++			unsigned int pidx = jh7110_stgclk_data[idx].parents[i];
++
++			if (pidx < JH7110_STGCLK_END)
++				parents[i].hw = &priv->reg[pidx].hw;
++			else if (pidx < JH7110_STGCLK_EXT_END)
++				parents[i].fw_name = fw_name[pidx - JH7110_STGCLK_END];
++		}
++
++		clk->hw.init = &init;
++		clk->idx = idx;
++		clk->max_div = max & JH71X0_CLK_DIV_MASK;
++
++		ret = devm_clk_hw_register(&pdev->dev, &clk->hw);
++		if (ret)
++			return ret;
++	}
++
++	ret = devm_of_clk_add_hw_provider(&pdev->dev, jh7110_stgclk_get, priv);
++	if (ret)
++		return ret;
++
++	return jh7110_reset_controller_register(priv, "rst-stg", 2);
++}
++
++static const struct of_device_id jh7110_stgcrg_match[] = {
++	{ .compatible = "starfive,jh7110-stgcrg" },
++	{ /* sentinel */ }
++};
++MODULE_DEVICE_TABLE(of, jh7110_stgcrg_match);
++
++static struct platform_driver jh7110_stgcrg_driver = {
++	.probe = jh7110_stgcrg_probe,
++	.driver = {
++		.name = "clk-starfive-jh7110-stg",
++		.of_match_table = jh7110_stgcrg_match,
++	},
++};
++module_platform_driver(jh7110_stgcrg_driver);
++
++MODULE_AUTHOR("Xingyu Wu <[email protected]>");
++MODULE_AUTHOR("Emil Renner Berthing <[email protected]>");
++MODULE_DESCRIPTION("StarFive JH7110 System-Top-Group clock driver");
++MODULE_LICENSE("GPL");

+ 156 - 0
target/linux/starfive/patches-6.1/0053-dt-bindings-clock-Add-StarFive-JH7110-Image-Signal-P.patch

@@ -0,0 +1,156 @@
+From 70df2590923e262ce8bf2b4f497f3481511d4fd6 Mon Sep 17 00:00:00 2001
+From: Xingyu Wu <[email protected]>
+Date: Thu, 18 May 2023 18:12:26 +0800
+Subject: [PATCH 053/122] dt-bindings: clock: Add StarFive JH7110
+ Image-Signal-Process clock and reset generator
+
+Add bindings for the Image-Signal-Process clock and reset
+generator (ISPCRG) on the JH7110 RISC-V SoC by StarFive Ltd.
+
+Reviewed-by: Krzysztof Kozlowski <[email protected]>
+Signed-off-by: Xingyu Wu <[email protected]>
+---
+ .../clock/starfive,jh7110-ispcrg.yaml         | 87 +++++++++++++++++++
+ .../dt-bindings/clock/starfive,jh7110-crg.h   | 18 ++++
+ .../dt-bindings/reset/starfive,jh7110-crg.h   | 16 ++++
+ 3 files changed, 121 insertions(+)
+ create mode 100644 Documentation/devicetree/bindings/clock/starfive,jh7110-ispcrg.yaml
+
+--- /dev/null
++++ b/Documentation/devicetree/bindings/clock/starfive,jh7110-ispcrg.yaml
+@@ -0,0 +1,87 @@
++# SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause
++%YAML 1.2
++---
++$id: http://devicetree.org/schemas/clock/starfive,jh7110-ispcrg.yaml#
++$schema: http://devicetree.org/meta-schemas/core.yaml#
++
++title: StarFive JH7110 Image-Signal-Process Clock and Reset Generator
++
++maintainers:
++  - Xingyu Wu <[email protected]>
++
++properties:
++  compatible:
++    const: starfive,jh7110-ispcrg
++
++  reg:
++    maxItems: 1
++
++  clocks:
++    items:
++      - description: ISP Top core
++      - description: ISP Top Axi
++      - description: NOC ISP Bus
++      - description: external DVP
++
++  clock-names:
++    items:
++      - const: isp_top_core
++      - const: isp_top_axi
++      - const: noc_bus_isp_axi
++      - const: dvp_clk
++
++  resets:
++    items:
++      - description: ISP Top core
++      - description: ISP Top Axi
++      - description: NOC ISP Bus
++
++  '#clock-cells':
++    const: 1
++    description:
++      See <dt-bindings/clock/starfive,jh7110-crg.h> for valid indices.
++
++  '#reset-cells':
++    const: 1
++    description:
++      See <dt-bindings/reset/starfive,jh7110-crg.h> for valid indices.
++
++  power-domains:
++    maxItems: 1
++    description:
++      ISP domain power
++
++required:
++  - compatible
++  - reg
++  - clocks
++  - clock-names
++  - resets
++  - '#clock-cells'
++  - '#reset-cells'
++  - power-domains
++
++additionalProperties: false
++
++examples:
++  - |
++    #include <dt-bindings/clock/starfive,jh7110-crg.h>
++    #include <dt-bindings/power/starfive,jh7110-pmu.h>
++    #include <dt-bindings/reset/starfive,jh7110-crg.h>
++
++    ispcrg: clock-controller@19810000 {
++        compatible = "starfive,jh7110-ispcrg";
++        reg = <0x19810000 0x10000>;
++        clocks = <&syscrg JH7110_SYSCLK_ISP_TOP_CORE>,
++                 <&syscrg JH7110_SYSCLK_ISP_TOP_AXI>,
++                 <&syscrg JH7110_SYSCLK_NOC_BUS_ISP_AXI>,
++                 <&dvp_clk>;
++        clock-names = "isp_top_core", "isp_top_axi",
++                      "noc_bus_isp_axi", "dvp_clk";
++        resets = <&syscrg JH7110_SYSRST_ISP_TOP>,
++                 <&syscrg JH7110_SYSRST_ISP_TOP_AXI>,
++                 <&syscrg JH7110_SYSRST_NOC_BUS_ISP_AXI>;
++        #clock-cells = <1>;
++        #reset-cells = <1>;
++        power-domains = <&pwrc JH7110_PD_ISP>;
++    };
+--- a/include/dt-bindings/clock/starfive,jh7110-crg.h
++++ b/include/dt-bindings/clock/starfive,jh7110-crg.h
+@@ -258,4 +258,22 @@
+ 
+ #define JH7110_STGCLK_END			29
+ 
++/* ISPCRG clocks */
++#define JH7110_ISPCLK_DOM4_APB_FUNC		0
++#define JH7110_ISPCLK_MIPI_RX0_PXL		1
++#define JH7110_ISPCLK_DVP_INV			2
++#define JH7110_ISPCLK_M31DPHY_CFG_IN		3
++#define JH7110_ISPCLK_M31DPHY_REF_IN		4
++#define JH7110_ISPCLK_M31DPHY_TX_ESC_LAN0	5
++#define JH7110_ISPCLK_VIN_APB			6
++#define JH7110_ISPCLK_VIN_SYS			7
++#define JH7110_ISPCLK_VIN_PIXEL_IF0		8
++#define JH7110_ISPCLK_VIN_PIXEL_IF1		9
++#define JH7110_ISPCLK_VIN_PIXEL_IF2		10
++#define JH7110_ISPCLK_VIN_PIXEL_IF3		11
++#define JH7110_ISPCLK_VIN_P_AXI_WR		12
++#define JH7110_ISPCLK_ISPV2_TOP_WRAPPER_C	13
++
++#define JH7110_ISPCLK_END			14
++
+ #endif /* __DT_BINDINGS_CLOCK_STARFIVE_JH7110_CRG_H__ */
+--- a/include/dt-bindings/reset/starfive,jh7110-crg.h
++++ b/include/dt-bindings/reset/starfive,jh7110-crg.h
+@@ -179,4 +179,20 @@
+ 
+ #define JH7110_STGRST_END			23
+ 
++/* ISPCRG resets */
++#define JH7110_ISPRST_ISPV2_TOP_WRAPPER_P	0
++#define JH7110_ISPRST_ISPV2_TOP_WRAPPER_C	1
++#define JH7110_ISPRST_M31DPHY_HW		2
++#define JH7110_ISPRST_M31DPHY_B09_AON		3
++#define JH7110_ISPRST_VIN_APB			4
++#define JH7110_ISPRST_VIN_PIXEL_IF0		5
++#define JH7110_ISPRST_VIN_PIXEL_IF1		6
++#define JH7110_ISPRST_VIN_PIXEL_IF2		7
++#define JH7110_ISPRST_VIN_PIXEL_IF3		8
++#define JH7110_ISPRST_VIN_SYS			9
++#define JH7110_ISPRST_VIN_P_AXI_RD		10
++#define JH7110_ISPRST_VIN_P_AXI_WR		11
++
++#define JH7110_ISPRST_END			12
++
+ #endif /* __DT_BINDINGS_RESET_STARFIVE_JH7110_CRG_H__ */

+ 293 - 0
target/linux/starfive/patches-6.1/0054-clk-starfive-Add-StarFive-JH7110-Image-Signal-Proces.patch

@@ -0,0 +1,293 @@
+From 003c13d81b525a184c5ca551e536e6786e2d2f5c Mon Sep 17 00:00:00 2001
+From: Xingyu Wu <[email protected]>
+Date: Thu, 18 May 2023 18:12:27 +0800
+Subject: [PATCH 054/122] clk: starfive: Add StarFive JH7110
+ Image-Signal-Process clock driver
+
+Add driver for the StarFive JH7110 Image-Signal-Process clock controller.
+And these clock controllers should power on and enable the clocks from
+SYSCRG first before registering.
+
+Signed-off-by: Xingyu Wu <[email protected]>
+---
+ drivers/clk/starfive/Kconfig                  |  11 +
+ drivers/clk/starfive/Makefile                 |   1 +
+ .../clk/starfive/clk-starfive-jh7110-isp.c    | 232 ++++++++++++++++++
+ drivers/clk/starfive/clk-starfive-jh7110.h    |   6 +
+ 4 files changed, 250 insertions(+)
+ create mode 100644 drivers/clk/starfive/clk-starfive-jh7110-isp.c
+
+--- a/drivers/clk/starfive/Kconfig
++++ b/drivers/clk/starfive/Kconfig
+@@ -62,3 +62,14 @@ config CLK_STARFIVE_JH7110_STG
+ 	help
+ 	  Say yes here to support the System-Top-Group clock controller
+ 	  on the StarFive JH7110 SoC.
++
++config CLK_STARFIVE_JH7110_ISP
++	tristate "StarFive JH7110 Image-Signal-Process clock support"
++	depends on CLK_STARFIVE_JH7110_SYS && JH71XX_PMU
++	select AUXILIARY_BUS
++	select CLK_STARFIVE_JH71X0
++	select RESET_STARFIVE_JH7110
++	default m if ARCH_STARFIVE
++	help
++	  Say yes here to support the Image-Signal-Process clock controller
++	  on the StarFive JH7110 SoC.
+--- a/drivers/clk/starfive/Makefile
++++ b/drivers/clk/starfive/Makefile
+@@ -8,3 +8,4 @@ obj-$(CONFIG_CLK_STARFIVE_JH7110_PLL)	+=
+ obj-$(CONFIG_CLK_STARFIVE_JH7110_SYS)	+= clk-starfive-jh7110-sys.o
+ obj-$(CONFIG_CLK_STARFIVE_JH7110_AON)	+= clk-starfive-jh7110-aon.o
+ obj-$(CONFIG_CLK_STARFIVE_JH7110_STG)	+= clk-starfive-jh7110-stg.o
++obj-$(CONFIG_CLK_STARFIVE_JH7110_ISP)	+= clk-starfive-jh7110-isp.o
+--- /dev/null
++++ b/drivers/clk/starfive/clk-starfive-jh7110-isp.c
+@@ -0,0 +1,232 @@
++// SPDX-License-Identifier: GPL-2.0
++/*
++ * StarFive JH7110 Image-Signal-Process Clock Driver
++ *
++ * Copyright (C) 2022-2023 StarFive Technology Co., Ltd.
++ */
++
++#include <linux/clk.h>
++#include <linux/clk-provider.h>
++#include <linux/io.h>
++#include <linux/platform_device.h>
++#include <linux/pm_runtime.h>
++#include <linux/reset.h>
++
++#include <dt-bindings/clock/starfive,jh7110-crg.h>
++
++#include "clk-starfive-jh7110.h"
++
++/* external clocks */
++#define JH7110_ISPCLK_ISP_TOP_CORE		(JH7110_ISPCLK_END + 0)
++#define JH7110_ISPCLK_ISP_TOP_AXI		(JH7110_ISPCLK_END + 1)
++#define JH7110_ISPCLK_NOC_BUS_ISP_AXI		(JH7110_ISPCLK_END + 2)
++#define JH7110_ISPCLK_DVP_CLK			(JH7110_ISPCLK_END + 3)
++#define JH7110_ISPCLK_EXT_END			(JH7110_ISPCLK_END + 4)
++
++static struct clk_bulk_data jh7110_isp_top_clks[] = {
++	{ .id = "isp_top_core" },
++	{ .id = "isp_top_axi" }
++};
++
++static const struct jh71x0_clk_data jh7110_ispclk_data[] = {
++	/* syscon */
++	JH71X0__DIV(JH7110_ISPCLK_DOM4_APB_FUNC, "dom4_apb_func", 15,
++		    JH7110_ISPCLK_ISP_TOP_AXI),
++	JH71X0__DIV(JH7110_ISPCLK_MIPI_RX0_PXL, "mipi_rx0_pxl", 8,
++		    JH7110_ISPCLK_ISP_TOP_CORE),
++	JH71X0__INV(JH7110_ISPCLK_DVP_INV, "dvp_inv", JH7110_ISPCLK_DVP_CLK),
++	/* vin */
++	JH71X0__DIV(JH7110_ISPCLK_M31DPHY_CFG_IN, "m31dphy_cfg_in", 16,
++		    JH7110_ISPCLK_ISP_TOP_CORE),
++	JH71X0__DIV(JH7110_ISPCLK_M31DPHY_REF_IN, "m31dphy_ref_in", 16,
++		    JH7110_ISPCLK_ISP_TOP_CORE),
++	JH71X0__DIV(JH7110_ISPCLK_M31DPHY_TX_ESC_LAN0, "m31dphy_tx_esc_lan0", 60,
++		    JH7110_ISPCLK_ISP_TOP_CORE),
++	JH71X0_GATE(JH7110_ISPCLK_VIN_APB, "vin_apb", 0,
++		    JH7110_ISPCLK_DOM4_APB_FUNC),
++	JH71X0__DIV(JH7110_ISPCLK_VIN_SYS, "vin_sys", 8, JH7110_ISPCLK_ISP_TOP_CORE),
++	JH71X0_GATE(JH7110_ISPCLK_VIN_PIXEL_IF0, "vin_pixel_if0", 0,
++		    JH7110_ISPCLK_MIPI_RX0_PXL),
++	JH71X0_GATE(JH7110_ISPCLK_VIN_PIXEL_IF1, "vin_pixel_if1", 0,
++		    JH7110_ISPCLK_MIPI_RX0_PXL),
++	JH71X0_GATE(JH7110_ISPCLK_VIN_PIXEL_IF2, "vin_pixel_if2", 0,
++		    JH7110_ISPCLK_MIPI_RX0_PXL),
++	JH71X0_GATE(JH7110_ISPCLK_VIN_PIXEL_IF3, "vin_pixel_if3", 0,
++		    JH7110_ISPCLK_MIPI_RX0_PXL),
++	JH71X0__MUX(JH7110_ISPCLK_VIN_P_AXI_WR, "vin_p_axi_wr", 2,
++		    JH7110_ISPCLK_MIPI_RX0_PXL,
++		    JH7110_ISPCLK_DVP_INV),
++	/* ispv2_top_wrapper */
++	JH71X0_GMUX(JH7110_ISPCLK_ISPV2_TOP_WRAPPER_C, "ispv2_top_wrapper_c", 0, 2,
++		    JH7110_ISPCLK_MIPI_RX0_PXL,
++		    JH7110_ISPCLK_DVP_INV),
++};
++
++static inline int jh7110_isp_top_rst_init(struct jh71x0_clk_priv *priv)
++{
++	struct reset_control *top_rsts;
++
++	/* The resets should be shared and other ISP modules will use its. */
++	top_rsts = devm_reset_control_array_get_shared(priv->dev);
++	if (IS_ERR(top_rsts))
++		return dev_err_probe(priv->dev, PTR_ERR(top_rsts),
++				     "failed to get top resets\n");
++
++	return reset_control_deassert(top_rsts);
++}
++
++static struct clk_hw *jh7110_ispclk_get(struct of_phandle_args *clkspec, void *data)
++{
++	struct jh71x0_clk_priv *priv = data;
++	unsigned int idx = clkspec->args[0];
++
++	if (idx < JH7110_ISPCLK_END)
++		return &priv->reg[idx].hw;
++
++	return ERR_PTR(-EINVAL);
++}
++
++#ifdef CONFIG_PM
++static int jh7110_ispcrg_suspend(struct device *dev)
++{
++	struct top_sysclk *top = dev_get_drvdata(dev);
++
++	clk_bulk_disable_unprepare(top->top_clks_num, top->top_clks);
++
++	return 0;
++}
++
++static int jh7110_ispcrg_resume(struct device *dev)
++{
++	struct top_sysclk *top = dev_get_drvdata(dev);
++
++	return clk_bulk_prepare_enable(top->top_clks_num, top->top_clks);
++}
++#endif
++
++static const struct dev_pm_ops jh7110_ispcrg_pm_ops = {
++	SET_RUNTIME_PM_OPS(jh7110_ispcrg_suspend, jh7110_ispcrg_resume, NULL)
++};
++
++static int jh7110_ispcrg_probe(struct platform_device *pdev)
++{
++	struct jh71x0_clk_priv *priv;
++	struct top_sysclk *top;
++	unsigned int idx;
++	int ret;
++
++	priv = devm_kzalloc(&pdev->dev,
++			    struct_size(priv, reg, JH7110_ISPCLK_END),
++			    GFP_KERNEL);
++	if (!priv)
++		return -ENOMEM;
++
++	top = devm_kzalloc(&pdev->dev, sizeof(*top), GFP_KERNEL);
++	if (!top)
++		return -ENOMEM;
++
++	spin_lock_init(&priv->rmw_lock);
++	priv->dev = &pdev->dev;
++	priv->base = devm_platform_ioremap_resource(pdev, 0);
++	if (IS_ERR(priv->base))
++		return PTR_ERR(priv->base);
++
++	top->top_clks = jh7110_isp_top_clks;
++	top->top_clks_num = ARRAY_SIZE(jh7110_isp_top_clks);
++	ret = devm_clk_bulk_get(priv->dev, top->top_clks_num, top->top_clks);
++	if (ret)
++		return dev_err_probe(priv->dev, ret, "failed to get main clocks\n");
++	dev_set_drvdata(priv->dev, top);
++
++	/* enable power domain and clocks */
++	pm_runtime_enable(priv->dev);
++	ret = pm_runtime_get_sync(priv->dev);
++	if (ret < 0)
++		return dev_err_probe(priv->dev, ret, "failed to turn on power\n");
++
++	ret = jh7110_isp_top_rst_init(priv);
++	if (ret)
++		goto err_exit;
++
++	for (idx = 0; idx < JH7110_ISPCLK_END; idx++) {
++		u32 max = jh7110_ispclk_data[idx].max;
++		struct clk_parent_data parents[4] = {};
++		struct clk_init_data init = {
++			.name = jh7110_ispclk_data[idx].name,
++			.ops = starfive_jh71x0_clk_ops(max),
++			.parent_data = parents,
++			.num_parents =
++				((max & JH71X0_CLK_MUX_MASK) >> JH71X0_CLK_MUX_SHIFT) + 1,
++			.flags = jh7110_ispclk_data[idx].flags,
++		};
++		struct jh71x0_clk *clk = &priv->reg[idx];
++		unsigned int i;
++		const char *fw_name[JH7110_ISPCLK_EXT_END - JH7110_ISPCLK_END] = {
++			"isp_top_core",
++			"isp_top_axi",
++			"noc_bus_isp_axi",
++			"dvp_clk"
++		};
++
++		for (i = 0; i < init.num_parents; i++) {
++			unsigned int pidx = jh7110_ispclk_data[idx].parents[i];
++
++			if (pidx < JH7110_ISPCLK_END)
++				parents[i].hw = &priv->reg[pidx].hw;
++			else
++				parents[i].fw_name = fw_name[pidx - JH7110_ISPCLK_END];
++		}
++
++		clk->hw.init = &init;
++		clk->idx = idx;
++		clk->max_div = max & JH71X0_CLK_DIV_MASK;
++
++		ret = devm_clk_hw_register(&pdev->dev, &clk->hw);
++		if (ret)
++			goto err_exit;
++	}
++
++	ret = devm_of_clk_add_hw_provider(&pdev->dev, jh7110_ispclk_get, priv);
++	if (ret)
++		goto err_exit;
++
++	ret = jh7110_reset_controller_register(priv, "rst-isp", 3);
++	if (ret)
++		goto err_exit;
++
++	return 0;
++
++err_exit:
++	pm_runtime_put_sync(priv->dev);
++	pm_runtime_disable(priv->dev);
++	return ret;
++}
++
++static int jh7110_ispcrg_remove(struct platform_device *pdev)
++{
++	pm_runtime_put_sync(&pdev->dev);
++	pm_runtime_disable(&pdev->dev);
++
++	return 0;
++}
++
++static const struct of_device_id jh7110_ispcrg_match[] = {
++	{ .compatible = "starfive,jh7110-ispcrg" },
++	{ /* sentinel */ }
++};
++MODULE_DEVICE_TABLE(of, jh7110_ispcrg_match);
++
++static struct platform_driver jh7110_ispcrg_driver = {
++	.probe = jh7110_ispcrg_probe,
++	.remove = jh7110_ispcrg_remove,
++	.driver = {
++		.name = "clk-starfive-jh7110-isp",
++		.of_match_table = jh7110_ispcrg_match,
++		.pm = &jh7110_ispcrg_pm_ops,
++	},
++};
++module_platform_driver(jh7110_ispcrg_driver);
++
++MODULE_AUTHOR("Xingyu Wu <[email protected]>");
++MODULE_DESCRIPTION("StarFive JH7110 Image-Signal-Process clock driver");
++MODULE_LICENSE("GPL");
+--- a/drivers/clk/starfive/clk-starfive-jh7110.h
++++ b/drivers/clk/starfive/clk-starfive-jh7110.h
+@@ -4,6 +4,12 @@
+ 
+ #include "clk-starfive-jh71x0.h"
+ 
++/* top clocks of ISP/VOUT domain from SYSCRG */
++struct top_sysclk {
++	struct clk_bulk_data *top_clks;
++	int top_clks_num;
++};
++
+ int jh7110_reset_controller_register(struct jh71x0_clk_priv *priv,
+ 				     const char *adev_name,
+ 				     u32 adev_id);

+ 163 - 0
target/linux/starfive/patches-6.1/0055-dt-bindings-clock-Add-StarFive-JH7110-Video-Output-c.patch

@@ -0,0 +1,163 @@
+From 06fa910083f37ecbc9234c7230dcbbd4d83e2f02 Mon Sep 17 00:00:00 2001
+From: Xingyu Wu <[email protected]>
+Date: Thu, 18 May 2023 18:12:28 +0800
+Subject: [PATCH 055/122] dt-bindings: clock: Add StarFive JH7110 Video-Output
+ clock and reset generator
+
+Add bindings for the Video-Output clock and reset generator (VOUTCRG)
+on the JH7110 RISC-V SoC by StarFive Ltd.
+
+Reviewed-by: Krzysztof Kozlowski <[email protected]>
+Signed-off-by: Xingyu Wu <[email protected]>
+---
+ .../clock/starfive,jh7110-voutcrg.yaml        | 90 +++++++++++++++++++
+ .../dt-bindings/clock/starfive,jh7110-crg.h   | 22 +++++
+ .../dt-bindings/reset/starfive,jh7110-crg.h   | 16 ++++
+ 3 files changed, 128 insertions(+)
+ create mode 100644 Documentation/devicetree/bindings/clock/starfive,jh7110-voutcrg.yaml
+
+--- /dev/null
++++ b/Documentation/devicetree/bindings/clock/starfive,jh7110-voutcrg.yaml
+@@ -0,0 +1,90 @@
++# SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause
++%YAML 1.2
++---
++$id: http://devicetree.org/schemas/clock/starfive,jh7110-voutcrg.yaml#
++$schema: http://devicetree.org/meta-schemas/core.yaml#
++
++title: StarFive JH7110 Video-Output Clock and Reset Generator
++
++maintainers:
++  - Xingyu Wu <[email protected]>
++
++properties:
++  compatible:
++    const: starfive,jh7110-voutcrg
++
++  reg:
++    maxItems: 1
++
++  clocks:
++    items:
++      - description: Vout Top core
++      - description: Vout Top Ahb
++      - description: Vout Top Axi
++      - description: Vout Top HDMI MCLK
++      - description: I2STX0 BCLK
++      - description: external HDMI pixel
++
++  clock-names:
++    items:
++      - const: vout_src
++      - const: vout_top_ahb
++      - const: vout_top_axi
++      - const: vout_top_hdmitx0_mclk
++      - const: i2stx0_bclk
++      - const: hdmitx0_pixelclk
++
++  resets:
++    maxItems: 1
++    description: Vout Top core
++
++  '#clock-cells':
++    const: 1
++    description:
++      See <dt-bindings/clock/starfive,jh7110-crg.h> for valid indices.
++
++  '#reset-cells':
++    const: 1
++    description:
++      See <dt-bindings/reset/starfive,jh7110-crg.h> for valid indices.
++
++  power-domains:
++    maxItems: 1
++    description:
++      Vout domain power
++
++required:
++  - compatible
++  - reg
++  - clocks
++  - clock-names
++  - resets
++  - '#clock-cells'
++  - '#reset-cells'
++  - power-domains
++
++additionalProperties: false
++
++examples:
++  - |
++    #include <dt-bindings/clock/starfive,jh7110-crg.h>
++    #include <dt-bindings/power/starfive,jh7110-pmu.h>
++    #include <dt-bindings/reset/starfive,jh7110-crg.h>
++
++    voutcrg: clock-controller@295C0000 {
++        compatible = "starfive,jh7110-voutcrg";
++        reg = <0x295C0000 0x10000>;
++        clocks = <&syscrg JH7110_SYSCLK_VOUT_SRC>,
++                 <&syscrg JH7110_SYSCLK_VOUT_TOP_AHB>,
++                 <&syscrg JH7110_SYSCLK_VOUT_TOP_AXI>,
++                 <&syscrg JH7110_SYSCLK_VOUT_TOP_HDMITX0_MCLK>,
++                 <&syscrg JH7110_SYSCLK_I2STX0_BCLK>,
++                 <&hdmitx0_pixelclk>;
++        clock-names = "vout_src", "vout_top_ahb",
++                      "vout_top_axi", "vout_top_hdmitx0_mclk",
++                      "i2stx0_bclk", "hdmitx0_pixelclk";
++        resets = <&syscrg JH7110_SYSRST_VOUT_TOP_SRC>;
++        #clock-cells = <1>;
++        #reset-cells = <1>;
++        power-domains = <&pwrc JH7110_PD_VOUT>;
++    };
+--- a/include/dt-bindings/clock/starfive,jh7110-crg.h
++++ b/include/dt-bindings/clock/starfive,jh7110-crg.h
+@@ -276,4 +276,26 @@
+ 
+ #define JH7110_ISPCLK_END			14
+ 
++/* VOUTCRG clocks */
++#define JH7110_VOUTCLK_APB			0
++#define JH7110_VOUTCLK_DC8200_PIX		1
++#define JH7110_VOUTCLK_DSI_SYS			2
++#define JH7110_VOUTCLK_TX_ESC			3
++#define JH7110_VOUTCLK_DC8200_AXI		4
++#define JH7110_VOUTCLK_DC8200_CORE		5
++#define JH7110_VOUTCLK_DC8200_AHB		6
++#define JH7110_VOUTCLK_DC8200_PIX0		7
++#define JH7110_VOUTCLK_DC8200_PIX1		8
++#define JH7110_VOUTCLK_DOM_VOUT_TOP_LCD		9
++#define JH7110_VOUTCLK_DSITX_APB		10
++#define JH7110_VOUTCLK_DSITX_SYS		11
++#define JH7110_VOUTCLK_DSITX_DPI		12
++#define JH7110_VOUTCLK_DSITX_TXESC		13
++#define JH7110_VOUTCLK_MIPITX_DPHY_TXESC	14
++#define JH7110_VOUTCLK_HDMI_TX_MCLK		15
++#define JH7110_VOUTCLK_HDMI_TX_BCLK		16
++#define JH7110_VOUTCLK_HDMI_TX_SYS		17
++
++#define JH7110_VOUTCLK_END			18
++
+ #endif /* __DT_BINDINGS_CLOCK_STARFIVE_JH7110_CRG_H__ */
+--- a/include/dt-bindings/reset/starfive,jh7110-crg.h
++++ b/include/dt-bindings/reset/starfive,jh7110-crg.h
+@@ -195,4 +195,20 @@
+ 
+ #define JH7110_ISPRST_END			12
+ 
++/* VOUTCRG resets */
++#define JH7110_VOUTRST_DC8200_AXI		0
++#define JH7110_VOUTRST_DC8200_AHB		1
++#define JH7110_VOUTRST_DC8200_CORE		2
++#define JH7110_VOUTRST_DSITX_DPI		3
++#define JH7110_VOUTRST_DSITX_APB		4
++#define JH7110_VOUTRST_DSITX_RXESC		5
++#define JH7110_VOUTRST_DSITX_SYS		6
++#define JH7110_VOUTRST_DSITX_TXBYTEHS		7
++#define JH7110_VOUTRST_DSITX_TXESC		8
++#define JH7110_VOUTRST_HDMI_TX_HDMI		9
++#define JH7110_VOUTRST_MIPITX_DPHY_SYS		10
++#define JH7110_VOUTRST_MIPITX_DPHY_TXBYTEHS	11
++
++#define JH7110_VOUTRST_END			12
++
+ #endif /* __DT_BINDINGS_RESET_STARFIVE_JH7110_CRG_H__ */

+ 284 - 0
target/linux/starfive/patches-6.1/0056-clk-starfive-Add-StarFive-JH7110-Video-Output-clock-.patch

@@ -0,0 +1,284 @@
+From 2e632d5c5f8b4577ac823f6a9dcf3eacdb14a0ba Mon Sep 17 00:00:00 2001
+From: Xingyu Wu <[email protected]>
+Date: Thu, 18 May 2023 18:12:29 +0800
+Subject: [PATCH 056/122] clk: starfive: Add StarFive JH7110 Video-Output clock
+ driver
+
+Add driver for the StarFive JH7110 Video-Output clock controller.
+And these clock controllers should power on and enable the clocks from
+SYSCRG first before registering.
+
+Signed-off-by: Xingyu Wu <[email protected]>
+---
+ drivers/clk/starfive/Kconfig                  |  11 +
+ drivers/clk/starfive/Makefile                 |   1 +
+ .../clk/starfive/clk-starfive-jh7110-vout.c   | 239 ++++++++++++++++++
+ 3 files changed, 251 insertions(+)
+ create mode 100644 drivers/clk/starfive/clk-starfive-jh7110-vout.c
+
+--- a/drivers/clk/starfive/Kconfig
++++ b/drivers/clk/starfive/Kconfig
+@@ -73,3 +73,14 @@ config CLK_STARFIVE_JH7110_ISP
+ 	help
+ 	  Say yes here to support the Image-Signal-Process clock controller
+ 	  on the StarFive JH7110 SoC.
++
++config CLK_STARFIVE_JH7110_VOUT
++	tristate "StarFive JH7110 Video-Output clock support"
++	depends on CLK_STARFIVE_JH7110_SYS && JH71XX_PMU
++	select AUXILIARY_BUS
++	select CLK_STARFIVE_JH71X0
++	select RESET_STARFIVE_JH7110
++	default m if ARCH_STARFIVE
++	help
++	  Say yes here to support the Video-Output clock controller
++	  on the StarFive JH7110 SoC.
+--- a/drivers/clk/starfive/Makefile
++++ b/drivers/clk/starfive/Makefile
+@@ -9,3 +9,4 @@ obj-$(CONFIG_CLK_STARFIVE_JH7110_SYS)	+=
+ obj-$(CONFIG_CLK_STARFIVE_JH7110_AON)	+= clk-starfive-jh7110-aon.o
+ obj-$(CONFIG_CLK_STARFIVE_JH7110_STG)	+= clk-starfive-jh7110-stg.o
+ obj-$(CONFIG_CLK_STARFIVE_JH7110_ISP)	+= clk-starfive-jh7110-isp.o
++obj-$(CONFIG_CLK_STARFIVE_JH7110_VOUT)	+= clk-starfive-jh7110-vout.o
+--- /dev/null
++++ b/drivers/clk/starfive/clk-starfive-jh7110-vout.c
+@@ -0,0 +1,239 @@
++// SPDX-License-Identifier: GPL-2.0
++/*
++ * StarFive JH7110 Video-Output Clock Driver
++ *
++ * Copyright (C) 2022-2023 StarFive Technology Co., Ltd.
++ */
++
++#include <linux/clk.h>
++#include <linux/clk-provider.h>
++#include <linux/io.h>
++#include <linux/platform_device.h>
++#include <linux/pm_runtime.h>
++#include <linux/reset.h>
++
++#include <dt-bindings/clock/starfive,jh7110-crg.h>
++
++#include "clk-starfive-jh7110.h"
++
++/* external clocks */
++#define JH7110_VOUTCLK_VOUT_SRC			(JH7110_VOUTCLK_END + 0)
++#define JH7110_VOUTCLK_VOUT_TOP_AHB		(JH7110_VOUTCLK_END + 1)
++#define JH7110_VOUTCLK_VOUT_TOP_AXI		(JH7110_VOUTCLK_END + 2)
++#define JH7110_VOUTCLK_VOUT_TOP_HDMITX0_MCLK	(JH7110_VOUTCLK_END + 3)
++#define JH7110_VOUTCLK_I2STX0_BCLK		(JH7110_VOUTCLK_END + 4)
++#define JH7110_VOUTCLK_HDMITX0_PIXELCLK		(JH7110_VOUTCLK_END + 5)
++#define JH7110_VOUTCLK_EXT_END			(JH7110_VOUTCLK_END + 6)
++
++static struct clk_bulk_data jh7110_vout_top_clks[] = {
++	{ .id = "vout_src" },
++	{ .id = "vout_top_ahb" }
++};
++
++static const struct jh71x0_clk_data jh7110_voutclk_data[] = {
++	/* divider */
++	JH71X0__DIV(JH7110_VOUTCLK_APB, "apb", 8, JH7110_VOUTCLK_VOUT_TOP_AHB),
++	JH71X0__DIV(JH7110_VOUTCLK_DC8200_PIX, "dc8200_pix", 63, JH7110_VOUTCLK_VOUT_SRC),
++	JH71X0__DIV(JH7110_VOUTCLK_DSI_SYS, "dsi_sys", 31, JH7110_VOUTCLK_VOUT_SRC),
++	JH71X0__DIV(JH7110_VOUTCLK_TX_ESC, "tx_esc", 31, JH7110_VOUTCLK_VOUT_TOP_AHB),
++	/* dc8200 */
++	JH71X0_GATE(JH7110_VOUTCLK_DC8200_AXI, "dc8200_axi", 0, JH7110_VOUTCLK_VOUT_TOP_AXI),
++	JH71X0_GATE(JH7110_VOUTCLK_DC8200_CORE, "dc8200_core", 0, JH7110_VOUTCLK_VOUT_TOP_AXI),
++	JH71X0_GATE(JH7110_VOUTCLK_DC8200_AHB, "dc8200_ahb", 0, JH7110_VOUTCLK_VOUT_TOP_AHB),
++	JH71X0_GMUX(JH7110_VOUTCLK_DC8200_PIX0, "dc8200_pix0", 0, 2,
++		    JH7110_VOUTCLK_DC8200_PIX,
++		    JH7110_VOUTCLK_HDMITX0_PIXELCLK),
++	JH71X0_GMUX(JH7110_VOUTCLK_DC8200_PIX1, "dc8200_pix1", 0, 2,
++		    JH7110_VOUTCLK_DC8200_PIX,
++		    JH7110_VOUTCLK_HDMITX0_PIXELCLK),
++	/* LCD */
++	JH71X0_GMUX(JH7110_VOUTCLK_DOM_VOUT_TOP_LCD, "dom_vout_top_lcd", 0, 2,
++		    JH7110_VOUTCLK_DC8200_PIX0,
++		    JH7110_VOUTCLK_DC8200_PIX1),
++	/* dsiTx */
++	JH71X0_GATE(JH7110_VOUTCLK_DSITX_APB, "dsiTx_apb", 0, JH7110_VOUTCLK_DSI_SYS),
++	JH71X0_GATE(JH7110_VOUTCLK_DSITX_SYS, "dsiTx_sys", 0, JH7110_VOUTCLK_DSI_SYS),
++	JH71X0_GMUX(JH7110_VOUTCLK_DSITX_DPI, "dsiTx_dpi", 0, 2,
++		    JH7110_VOUTCLK_DC8200_PIX,
++		    JH7110_VOUTCLK_HDMITX0_PIXELCLK),
++	JH71X0_GATE(JH7110_VOUTCLK_DSITX_TXESC, "dsiTx_txesc", 0, JH7110_VOUTCLK_TX_ESC),
++	/* mipitx DPHY */
++	JH71X0_GATE(JH7110_VOUTCLK_MIPITX_DPHY_TXESC, "mipitx_dphy_txesc", 0,
++		    JH7110_VOUTCLK_TX_ESC),
++	/* hdmi */
++	JH71X0_GATE(JH7110_VOUTCLK_HDMI_TX_MCLK, "hdmi_tx_mclk", 0,
++		    JH7110_VOUTCLK_VOUT_TOP_HDMITX0_MCLK),
++	JH71X0_GATE(JH7110_VOUTCLK_HDMI_TX_BCLK, "hdmi_tx_bclk", 0,
++		    JH7110_VOUTCLK_I2STX0_BCLK),
++	JH71X0_GATE(JH7110_VOUTCLK_HDMI_TX_SYS, "hdmi_tx_sys", 0, JH7110_VOUTCLK_APB),
++};
++
++static int jh7110_vout_top_rst_init(struct jh71x0_clk_priv *priv)
++{
++	struct reset_control *top_rst;
++
++	/* The reset should be shared and other Vout modules will use its. */
++	top_rst = devm_reset_control_get_shared(priv->dev, NULL);
++	if (IS_ERR(top_rst))
++		return dev_err_probe(priv->dev, PTR_ERR(top_rst), "failed to get top reset\n");
++
++	return reset_control_deassert(top_rst);
++}
++
++static struct clk_hw *jh7110_voutclk_get(struct of_phandle_args *clkspec, void *data)
++{
++	struct jh71x0_clk_priv *priv = data;
++	unsigned int idx = clkspec->args[0];
++
++	if (idx < JH7110_VOUTCLK_END)
++		return &priv->reg[idx].hw;
++
++	return ERR_PTR(-EINVAL);
++}
++
++#ifdef CONFIG_PM
++static int jh7110_voutcrg_suspend(struct device *dev)
++{
++	struct top_sysclk *top = dev_get_drvdata(dev);
++
++	clk_bulk_disable_unprepare(top->top_clks_num, top->top_clks);
++
++	return 0;
++}
++
++static int jh7110_voutcrg_resume(struct device *dev)
++{
++	struct top_sysclk *top = dev_get_drvdata(dev);
++
++	return clk_bulk_prepare_enable(top->top_clks_num, top->top_clks);
++}
++#endif
++
++static const struct dev_pm_ops jh7110_voutcrg_pm_ops = {
++	SET_RUNTIME_PM_OPS(jh7110_voutcrg_suspend, jh7110_voutcrg_resume, NULL)
++};
++
++static int jh7110_voutcrg_probe(struct platform_device *pdev)
++{
++	struct jh71x0_clk_priv *priv;
++	struct top_sysclk *top;
++	unsigned int idx;
++	int ret;
++
++	priv = devm_kzalloc(&pdev->dev,
++			    struct_size(priv, reg, JH7110_VOUTCLK_END),
++			    GFP_KERNEL);
++	if (!priv)
++		return -ENOMEM;
++
++	top = devm_kzalloc(&pdev->dev, sizeof(*top), GFP_KERNEL);
++	if (!top)
++		return -ENOMEM;
++
++	spin_lock_init(&priv->rmw_lock);
++	priv->dev = &pdev->dev;
++	priv->base = devm_platform_ioremap_resource(pdev, 0);
++	if (IS_ERR(priv->base))
++		return PTR_ERR(priv->base);
++
++	top->top_clks = jh7110_vout_top_clks;
++	top->top_clks_num = ARRAY_SIZE(jh7110_vout_top_clks);
++	ret = devm_clk_bulk_get(priv->dev, top->top_clks_num, top->top_clks);
++	if (ret)
++		return dev_err_probe(priv->dev, ret, "failed to get top clocks\n");
++	dev_set_drvdata(priv->dev, top);
++
++	/* enable power domain and clocks */
++	pm_runtime_enable(priv->dev);
++	ret = pm_runtime_get_sync(priv->dev);
++	if (ret < 0)
++		return dev_err_probe(priv->dev, ret, "failed to turn on power\n");
++
++	ret = jh7110_vout_top_rst_init(priv);
++	if (ret)
++		goto err_exit;
++
++	for (idx = 0; idx < JH7110_VOUTCLK_END; idx++) {
++		u32 max = jh7110_voutclk_data[idx].max;
++		struct clk_parent_data parents[4] = {};
++		struct clk_init_data init = {
++			.name = jh7110_voutclk_data[idx].name,
++			.ops = starfive_jh71x0_clk_ops(max),
++			.parent_data = parents,
++			.num_parents =
++				((max & JH71X0_CLK_MUX_MASK) >> JH71X0_CLK_MUX_SHIFT) + 1,
++			.flags = jh7110_voutclk_data[idx].flags,
++		};
++		struct jh71x0_clk *clk = &priv->reg[idx];
++		unsigned int i;
++		const char *fw_name[JH7110_VOUTCLK_EXT_END - JH7110_VOUTCLK_END] = {
++			"vout_src",
++			"vout_top_ahb",
++			"vout_top_axi",
++			"vout_top_hdmitx0_mclk",
++			"i2stx0_bclk",
++			"hdmitx0_pixelclk"
++		};
++
++		for (i = 0; i < init.num_parents; i++) {
++			unsigned int pidx = jh7110_voutclk_data[idx].parents[i];
++
++			if (pidx < JH7110_VOUTCLK_END)
++				parents[i].hw = &priv->reg[pidx].hw;
++			else if (pidx < JH7110_VOUTCLK_EXT_END)
++				parents[i].fw_name = fw_name[pidx - JH7110_VOUTCLK_END];
++		}
++
++		clk->hw.init = &init;
++		clk->idx = idx;
++		clk->max_div = max & JH71X0_CLK_DIV_MASK;
++
++		ret = devm_clk_hw_register(&pdev->dev, &clk->hw);
++		if (ret)
++			goto err_exit;
++	}
++
++	ret = devm_of_clk_add_hw_provider(&pdev->dev, jh7110_voutclk_get, priv);
++	if (ret)
++		goto err_exit;
++
++	ret = jh7110_reset_controller_register(priv, "rst-vo", 4);
++	if (ret)
++		goto err_exit;
++
++	return 0;
++
++err_exit:
++	pm_runtime_put_sync(priv->dev);
++	pm_runtime_disable(priv->dev);
++	return ret;
++}
++
++static int jh7110_voutcrg_remove(struct platform_device *pdev)
++{
++	pm_runtime_put_sync(&pdev->dev);
++	pm_runtime_disable(&pdev->dev);
++
++	return 0;
++}
++
++static const struct of_device_id jh7110_voutcrg_match[] = {
++	{ .compatible = "starfive,jh7110-voutcrg" },
++	{ /* sentinel */ }
++};
++MODULE_DEVICE_TABLE(of, jh7110_voutcrg_match);
++
++static struct platform_driver jh7110_voutcrg_driver = {
++	.probe = jh7110_voutcrg_probe,
++	.remove = jh7110_voutcrg_remove,
++	.driver = {
++		.name = "clk-starfive-jh7110-vout",
++		.of_match_table = jh7110_voutcrg_match,
++		.pm = &jh7110_voutcrg_pm_ops,
++	},
++};
++module_platform_driver(jh7110_voutcrg_driver);
++
++MODULE_AUTHOR("Xingyu Wu <[email protected]>");
++MODULE_DESCRIPTION("StarFive JH7110 Video-Output clock driver");
++MODULE_LICENSE("GPL");

+ 61 - 0
target/linux/starfive/patches-6.1/0057-reset-starfive-jh7110-Add-StarFive-STG-ISP-VOUT-rese.patch

@@ -0,0 +1,61 @@
+From a04a6eb3b4d112f3600bbd783249f24a43797e7a Mon Sep 17 00:00:00 2001
+From: Xingyu Wu <[email protected]>
+Date: Thu, 18 May 2023 18:12:31 +0800
+Subject: [PATCH 057/122] reset: starfive: jh7110: Add StarFive STG/ISP/VOUT
+ resets support
+
+Add new struct members and auxiliary_device_id of resets to support
+System-Top-Group, Image-Signal-Process and Video-Output on the StarFive
+JH7110 SoC.
+
+Signed-off-by: Xingyu Wu <[email protected]>
+---
+ .../reset/starfive/reset-starfive-jh7110.c    | 30 +++++++++++++++++++
+ 1 file changed, 30 insertions(+)
+
+--- a/drivers/reset/starfive/reset-starfive-jh7110.c
++++ b/drivers/reset/starfive/reset-starfive-jh7110.c
+@@ -31,6 +31,24 @@ static const struct jh7110_reset_info jh
+ 	.status_offset = 0x3C,
+ };
+ 
++static const struct jh7110_reset_info jh7110_stg_info = {
++	.nr_resets = JH7110_STGRST_END,
++	.assert_offset = 0x74,
++	.status_offset = 0x78,
++};
++
++static const struct jh7110_reset_info jh7110_isp_info = {
++	.nr_resets = JH7110_ISPRST_END,
++	.assert_offset = 0x38,
++	.status_offset = 0x3C,
++};
++
++static const struct jh7110_reset_info jh7110_vout_info = {
++	.nr_resets = JH7110_VOUTRST_END,
++	.assert_offset = 0x48,
++	.status_offset = 0x4C,
++};
++
+ static int jh7110_reset_probe(struct auxiliary_device *adev,
+ 			      const struct auxiliary_device_id *id)
+ {
+@@ -58,6 +76,18 @@ static const struct auxiliary_device_id
+ 		.name = "clk_starfive_jh7110_sys.rst-aon",
+ 		.driver_data = (kernel_ulong_t)&jh7110_aon_info,
+ 	},
++	{
++		.name = "clk_starfive_jh7110_sys.rst-stg",
++		.driver_data = (kernel_ulong_t)&jh7110_stg_info,
++	},
++	{
++		.name = "clk_starfive_jh7110_sys.rst-isp",
++		.driver_data = (kernel_ulong_t)&jh7110_isp_info,
++	},
++	{
++		.name = "clk_starfive_jh7110_sys.rst-vo",
++		.driver_data = (kernel_ulong_t)&jh7110_vout_info,
++	},
+ 	{ /* sentinel */ }
+ };
+ MODULE_DEVICE_TABLE(auxiliary, jh7110_reset_ids);

+ 819 - 0
target/linux/starfive/patches-6.1/0058-clk-starfive-update-jh7110-PLL-clock-driver.patch

@@ -0,0 +1,819 @@
+From 758c8c4c30f495465f34735aef2458c0cc255a75 Mon Sep 17 00:00:00 2001
+From: "shanlong.li" <[email protected]>
+Date: Wed, 31 May 2023 01:03:02 -0700
+Subject: [PATCH 058/122] clk: starfive: update jh7110 PLL clock driver
+
+Update the StarFive JH7110 PLL clock controller
+and they work by reading and setting syscon registers.
+
+Signed-off-by: shanlong.li <[email protected]>
+---
+ .../clk/starfive/clk-starfive-jh7110-pll.c    | 269 +++++-------------
+ .../clk/starfive/clk-starfive-jh7110-pll.h    | 264 +++++++++--------
+ 2 files changed, 227 insertions(+), 306 deletions(-)
+
+--- a/drivers/clk/starfive/clk-starfive-jh7110-pll.c
++++ b/drivers/clk/starfive/clk-starfive-jh7110-pll.c
+@@ -24,11 +24,29 @@
+ #include <linux/mfd/syscon.h>
+ #include <linux/platform_device.h>
+ #include <linux/regmap.h>
++#include <linux/of_platform.h>
+ 
+ #include <dt-bindings/clock/starfive,jh7110-crg.h>
+ 
+ #include "clk-starfive-jh7110-pll.h"
+ 
++struct jh7110_pll_conf_variant {
++	unsigned int pll_nums;
++	struct jh7110_pll_syscon_conf conf[];
++};
++
++static const struct jh7110_pll_conf_variant jh7110_pll_variant = {
++	.pll_nums = JH7110_PLLCLK_END,
++	.conf = {
++		JH7110_PLL(JH7110_CLK_PLL0_OUT, "pll0_out",
++			   JH7110_PLL0_FREQ_MAX, jh7110_pll0_syscon_val_preset),
++		JH7110_PLL(JH7110_CLK_PLL1_OUT, "pll1_out",
++			   JH7110_PLL1_FREQ_MAX, jh7110_pll1_syscon_val_preset),
++		JH7110_PLL(JH7110_CLK_PLL2_OUT, "pll2_out",
++			   JH7110_PLL2_FREQ_MAX, jh7110_pll2_syscon_val_preset),
++	},
++};
++
+ static struct jh7110_clk_pll_data *jh7110_pll_data_from(struct clk_hw *hw)
+ {
+ 	return container_of(hw, struct jh7110_clk_pll_data, hw);
+@@ -44,10 +62,9 @@ static unsigned long jh7110_pll_get_freq
+ 					 unsigned long parent_rate)
+ {
+ 	struct jh7110_clk_pll_priv *priv = jh7110_pll_priv_from(data);
+-	struct jh7110_pll_syscon_offset *offset = &data->offset;
+-	struct jh7110_pll_syscon_mask *mask = &data->mask;
+-	struct jh7110_pll_syscon_shift *shift = &data->shift;
+-	unsigned long freq = 0;
++	struct jh7110_pll_syscon_offset *offset = &data->conf.offsets;
++	struct jh7110_pll_syscon_mask *mask = &data->conf.masks;
++	struct jh7110_pll_syscon_shift *shift = &data->conf.shifts;
+ 	unsigned long frac_cal;
+ 	u32 dacpd;
+ 	u32 dsmpd;
+@@ -57,32 +74,23 @@ static unsigned long jh7110_pll_get_freq
+ 	u32 frac;
+ 	u32 reg_val;
+ 
+-	if (regmap_read(priv->syscon_regmap, offset->dacpd, &reg_val))
+-		goto read_error;
++	regmap_read(priv->syscon_regmap, offset->dacpd, &reg_val);
+ 	dacpd = (reg_val & mask->dacpd) >> shift->dacpd;
+ 
+-	if (regmap_read(priv->syscon_regmap, offset->dsmpd, &reg_val))
+-		goto read_error;
++	regmap_read(priv->syscon_regmap, offset->dsmpd, &reg_val);
+ 	dsmpd = (reg_val & mask->dsmpd) >> shift->dsmpd;
+ 
+-	if (regmap_read(priv->syscon_regmap, offset->fbdiv, &reg_val))
+-		goto read_error;
++	regmap_read(priv->syscon_regmap, offset->fbdiv, &reg_val);
+ 	fbdiv = (reg_val & mask->fbdiv) >> shift->fbdiv;
+-	/* fbdiv value should be 8 to 4095 */
+-	if (fbdiv < 8)
+-		goto read_error;
+ 
+-	if (regmap_read(priv->syscon_regmap, offset->prediv, &reg_val))
+-		goto read_error;
++	regmap_read(priv->syscon_regmap, offset->prediv, &reg_val);
+ 	prediv = (reg_val & mask->prediv) >> shift->prediv;
+ 
+-	if (regmap_read(priv->syscon_regmap, offset->postdiv1, &reg_val))
+-		goto read_error;
++	regmap_read(priv->syscon_regmap, offset->postdiv1, &reg_val);
+ 	/* postdiv1 = 2 ^ reg_val */
+ 	postdiv1 = 1 << ((reg_val & mask->postdiv1) >> shift->postdiv1);
+ 
+-	if (regmap_read(priv->syscon_regmap, offset->frac, &reg_val))
+-		goto read_error;
++	regmap_read(priv->syscon_regmap, offset->frac, &reg_val);
+ 	frac = (reg_val & mask->frac) >> shift->frac;
+ 
+ 	/*
+@@ -95,14 +103,11 @@ static unsigned long jh7110_pll_get_freq
+ 	else if (dacpd == 0 && dsmpd == 0)
+ 		frac_cal = (unsigned long)frac * STARFIVE_PLL_FRAC_PATR_SIZE / (1 << 24);
+ 	else
+-		goto read_error;
++		return 0;
+ 
+ 	/* Fvco = Fref * (NI + NF) / M / Q1 */
+-	freq = parent_rate / STARFIVE_PLL_FRAC_PATR_SIZE *
+-	       (fbdiv * STARFIVE_PLL_FRAC_PATR_SIZE + frac_cal) / prediv / postdiv1;
+-
+-read_error:
+-	return freq;
++	return (parent_rate / STARFIVE_PLL_FRAC_PATR_SIZE *
++		(fbdiv * STARFIVE_PLL_FRAC_PATR_SIZE + frac_cal) / prediv / postdiv1);
+ }
+ 
+ static unsigned long jh7110_pll_rate_sub_fabs(unsigned long rate1, unsigned long rate2)
+@@ -114,40 +119,27 @@ static unsigned long jh7110_pll_rate_sub
+ static void jh7110_pll_select_near_freq_id(struct jh7110_clk_pll_data *data,
+ 					   unsigned long rate)
+ {
+-	const struct starfive_pll_syscon_value *syscon_val;
++	const struct jh7110_pll_syscon_val *val;
+ 	unsigned int id;
+-	unsigned int pll_arry_size;
+ 	unsigned long rate_diff;
+ 
+-	if (data->idx == JH7110_CLK_PLL0_OUT)
+-		pll_arry_size = ARRAY_SIZE(jh7110_pll0_syscon_freq);
+-	else if (data->idx == JH7110_CLK_PLL1_OUT)
+-		pll_arry_size = ARRAY_SIZE(jh7110_pll1_syscon_freq);
+-	else
+-		pll_arry_size = ARRAY_SIZE(jh7110_pll2_syscon_freq);
+-
+ 	/* compare the frequency one by one from small to large in order */
+-	for (id = 0; id < pll_arry_size; id++) {
+-		if (data->idx == JH7110_CLK_PLL0_OUT)
+-			syscon_val = &jh7110_pll0_syscon_freq[id];
+-		else if (data->idx == JH7110_CLK_PLL1_OUT)
+-			syscon_val = &jh7110_pll1_syscon_freq[id];
+-		else
+-			syscon_val = &jh7110_pll2_syscon_freq[id];
++	for (id = 0; id < data->conf.preset_val_nums; id++) {
++		val = &data->conf.preset_val[id];
+ 
+-		if (rate == syscon_val->freq)
++		if (rate == val->freq)
+ 			goto match_end;
+ 
+ 		/* select near frequency */
+-		if (rate < syscon_val->freq) {
++		if (rate < val->freq) {
+ 			/* The last frequency is closer to the target rate than this time. */
+ 			if (id > 0)
+-				if (rate_diff < jh7110_pll_rate_sub_fabs(rate, syscon_val->freq))
++				if (rate_diff < jh7110_pll_rate_sub_fabs(rate, val->freq))
+ 					id--;
+ 
+ 			goto match_end;
+ 		} else {
+-			rate_diff = jh7110_pll_rate_sub_fabs(rate, syscon_val->freq);
++			rate_diff = jh7110_pll_rate_sub_fabs(rate, val->freq);
+ 		}
+ 	}
+ 
+@@ -158,54 +150,34 @@ match_end:
+ static int jh7110_pll_set_freq_syscon(struct jh7110_clk_pll_data *data)
+ {
+ 	struct jh7110_clk_pll_priv *priv = jh7110_pll_priv_from(data);
+-	struct jh7110_pll_syscon_offset *offset = &data->offset;
+-	struct jh7110_pll_syscon_mask *mask = &data->mask;
+-	struct jh7110_pll_syscon_shift *shift = &data->shift;
+-	unsigned int freq_idx = data->freq_select_idx;
+-	const struct starfive_pll_syscon_value *syscon_val;
+-	int ret;
++	struct jh7110_pll_syscon_offset *offset = &data->conf.offsets;
++	struct jh7110_pll_syscon_mask *mask = &data->conf.masks;
++	struct jh7110_pll_syscon_shift *shift = &data->conf.shifts;
++	const struct jh7110_pll_syscon_val *val = &data->conf.preset_val[data->freq_select_idx];
+ 
+-	if (data->idx == JH7110_CLK_PLL0_OUT)
+-		syscon_val = &jh7110_pll0_syscon_freq[freq_idx];
+-	else if (data->idx == JH7110_CLK_PLL1_OUT)
+-		syscon_val = &jh7110_pll1_syscon_freq[freq_idx];
+-	else
+-		syscon_val = &jh7110_pll2_syscon_freq[freq_idx];
++	/* frac: Integer Mode (Both 1) or Fraction Mode (Both 0) */
++	if (val->dacpd == 0 && val->dsmpd == 0)
++		regmap_update_bits(priv->syscon_regmap, offset->frac, mask->frac,
++				   (val->frac << shift->frac));
++	else if (val->dacpd != val->dsmpd)
++		return -EINVAL;
+ 
+-	ret = regmap_update_bits(priv->syscon_regmap, offset->dacpd, mask->dacpd,
+-				 (syscon_val->dacpd << shift->dacpd));
+-	if (ret)
+-		goto set_failed;
+-
+-	ret = regmap_update_bits(priv->syscon_regmap, offset->dsmpd, mask->dsmpd,
+-				 (syscon_val->dsmpd << shift->dsmpd));
+-	if (ret)
+-		goto set_failed;
+-
+-	ret = regmap_update_bits(priv->syscon_regmap, offset->prediv, mask->prediv,
+-				 (syscon_val->prediv << shift->prediv));
+-	if (ret)
+-		goto set_failed;
+-
+-	ret = regmap_update_bits(priv->syscon_regmap, offset->fbdiv, mask->fbdiv,
+-				 (syscon_val->fbdiv << shift->fbdiv));
+-	if (ret)
+-		goto set_failed;
+-
+-	ret = regmap_update_bits(priv->syscon_regmap, offset->postdiv1, mask->postdiv1,
+-				 ((syscon_val->postdiv1 >> 1) << shift->postdiv1));
+-	if (ret)
+-		goto set_failed;
++	/* fbdiv value should be 8 to 4095 */
++	if (val->fbdiv < 8)
++		return -EINVAL;
+ 
+-	/* frac: Integer Mode (Both 1) or Fraction Mode (Both 0) */
+-	if (syscon_val->dacpd == 0 && syscon_val->dsmpd == 0)
+-		ret = regmap_update_bits(priv->syscon_regmap, offset->frac, mask->frac,
+-					 (syscon_val->frac << shift->frac));
+-	else if (syscon_val->dacpd != syscon_val->dsmpd)
+-		ret = -EINVAL;
++	regmap_update_bits(priv->syscon_regmap, offset->dacpd, mask->dacpd,
++			   (val->dacpd << shift->dacpd));
++	regmap_update_bits(priv->syscon_regmap, offset->dsmpd, mask->dsmpd,
++			   (val->dsmpd << shift->dsmpd));
++	regmap_update_bits(priv->syscon_regmap, offset->prediv, mask->prediv,
++			   (val->prediv << shift->prediv));
++	regmap_update_bits(priv->syscon_regmap, offset->fbdiv, mask->fbdiv,
++			   (val->fbdiv << shift->fbdiv));
++	regmap_update_bits(priv->syscon_regmap, offset->postdiv1, mask->postdiv1,
++			   ((val->postdiv1 >> 1) << shift->postdiv1));
+ 
+-set_failed:
+-	return ret;
++	return 0;
+ }
+ 
+ static unsigned long jh7110_pll_recalc_rate(struct clk_hw *hw, unsigned long parent_rate)
+@@ -220,13 +192,7 @@ static int jh7110_pll_determine_rate(str
+ 	struct jh7110_clk_pll_data *data = jh7110_pll_data_from(hw);
+ 
+ 	jh7110_pll_select_near_freq_id(data, req->rate);
+-
+-	if (data->idx == JH7110_CLK_PLL0_OUT)
+-		req->rate = jh7110_pll0_syscon_freq[data->freq_select_idx].freq;
+-	else if (data->idx == JH7110_CLK_PLL1_OUT)
+-		req->rate = jh7110_pll1_syscon_freq[data->freq_select_idx].freq;
+-	else
+-		req->rate = jh7110_pll2_syscon_freq[data->freq_select_idx].freq;
++	req->rate = data->conf.preset_val[data->freq_select_idx].freq;
+ 
+ 	return 0;
+ }
+@@ -270,92 +236,12 @@ static const struct clk_ops jh7110_pll_o
+ 	.debug_init = jh7110_pll_debug_init,
+ };
+ 
+-/* get offset, mask and shift of PLL(x) syscon */
+-static int jh7110_pll_data_get(struct jh7110_clk_pll_data *data, int index)
+-{
+-	struct jh7110_pll_syscon_offset *offset = &data->offset;
+-	struct jh7110_pll_syscon_mask *mask = &data->mask;
+-	struct jh7110_pll_syscon_shift *shift = &data->shift;
+-
+-	if (index == JH7110_CLK_PLL0_OUT) {
+-		offset->dacpd = STARFIVE_JH7110_PLL0_DACPD_OFFSET;
+-		offset->dsmpd = STARFIVE_JH7110_PLL0_DSMPD_OFFSET;
+-		offset->fbdiv = STARFIVE_JH7110_PLL0_FBDIV_OFFSET;
+-		offset->frac = STARFIVE_JH7110_PLL0_FRAC_OFFSET;
+-		offset->prediv = STARFIVE_JH7110_PLL0_PREDIV_OFFSET;
+-		offset->postdiv1 = STARFIVE_JH7110_PLL0_POSTDIV1_OFFSET;
+-
+-		mask->dacpd = STARFIVE_JH7110_PLL0_DACPD_MASK;
+-		mask->dsmpd = STARFIVE_JH7110_PLL0_DSMPD_MASK;
+-		mask->fbdiv = STARFIVE_JH7110_PLL0_FBDIV_MASK;
+-		mask->frac = STARFIVE_JH7110_PLL0_FRAC_MASK;
+-		mask->prediv = STARFIVE_JH7110_PLL0_PREDIV_MASK;
+-		mask->postdiv1 = STARFIVE_JH7110_PLL0_POSTDIV1_MASK;
+-
+-		shift->dacpd = STARFIVE_JH7110_PLL0_DACPD_SHIFT;
+-		shift->dsmpd = STARFIVE_JH7110_PLL0_DSMPD_SHIFT;
+-		shift->fbdiv = STARFIVE_JH7110_PLL0_FBDIV_SHIFT;
+-		shift->frac = STARFIVE_JH7110_PLL0_FRAC_SHIFT;
+-		shift->prediv = STARFIVE_JH7110_PLL0_PREDIV_SHIFT;
+-		shift->postdiv1 = STARFIVE_JH7110_PLL0_POSTDIV1_SHIFT;
+-
+-	} else if (index == JH7110_CLK_PLL1_OUT) {
+-		offset->dacpd = STARFIVE_JH7110_PLL1_DACPD_OFFSET;
+-		offset->dsmpd = STARFIVE_JH7110_PLL1_DSMPD_OFFSET;
+-		offset->fbdiv = STARFIVE_JH7110_PLL1_FBDIV_OFFSET;
+-		offset->frac = STARFIVE_JH7110_PLL1_FRAC_OFFSET;
+-		offset->prediv = STARFIVE_JH7110_PLL1_PREDIV_OFFSET;
+-		offset->postdiv1 = STARFIVE_JH7110_PLL1_POSTDIV1_OFFSET;
+-
+-		mask->dacpd = STARFIVE_JH7110_PLL1_DACPD_MASK;
+-		mask->dsmpd = STARFIVE_JH7110_PLL1_DSMPD_MASK;
+-		mask->fbdiv = STARFIVE_JH7110_PLL1_FBDIV_MASK;
+-		mask->frac = STARFIVE_JH7110_PLL1_FRAC_MASK;
+-		mask->prediv = STARFIVE_JH7110_PLL1_PREDIV_MASK;
+-		mask->postdiv1 = STARFIVE_JH7110_PLL1_POSTDIV1_MASK;
+-
+-		shift->dacpd = STARFIVE_JH7110_PLL1_DACPD_SHIFT;
+-		shift->dsmpd = STARFIVE_JH7110_PLL1_DSMPD_SHIFT;
+-		shift->fbdiv = STARFIVE_JH7110_PLL1_FBDIV_SHIFT;
+-		shift->frac = STARFIVE_JH7110_PLL1_FRAC_SHIFT;
+-		shift->prediv = STARFIVE_JH7110_PLL1_PREDIV_SHIFT;
+-		shift->postdiv1 = STARFIVE_JH7110_PLL1_POSTDIV1_SHIFT;
+-
+-	} else if (index == JH7110_CLK_PLL2_OUT) {
+-		offset->dacpd = STARFIVE_JH7110_PLL2_DACPD_OFFSET;
+-		offset->dsmpd = STARFIVE_JH7110_PLL2_DSMPD_OFFSET;
+-		offset->fbdiv = STARFIVE_JH7110_PLL2_FBDIV_OFFSET;
+-		offset->frac = STARFIVE_JH7110_PLL2_FRAC_OFFSET;
+-		offset->prediv = STARFIVE_JH7110_PLL2_PREDIV_OFFSET;
+-		offset->postdiv1 = STARFIVE_JH7110_PLL2_POSTDIV1_OFFSET;
+-
+-		mask->dacpd = STARFIVE_JH7110_PLL2_DACPD_MASK;
+-		mask->dsmpd = STARFIVE_JH7110_PLL2_DSMPD_MASK;
+-		mask->fbdiv = STARFIVE_JH7110_PLL2_FBDIV_MASK;
+-		mask->frac = STARFIVE_JH7110_PLL2_FRAC_MASK;
+-		mask->prediv = STARFIVE_JH7110_PLL2_PREDIV_MASK;
+-		mask->postdiv1 = STARFIVE_JH7110_PLL2_POSTDIV1_MASK;
+-
+-		shift->dacpd = STARFIVE_JH7110_PLL2_DACPD_SHIFT;
+-		shift->dsmpd = STARFIVE_JH7110_PLL2_DSMPD_SHIFT;
+-		shift->fbdiv = STARFIVE_JH7110_PLL2_FBDIV_SHIFT;
+-		shift->frac = STARFIVE_JH7110_PLL2_FRAC_SHIFT;
+-		shift->prediv = STARFIVE_JH7110_PLL2_PREDIV_SHIFT;
+-		shift->postdiv1 = STARFIVE_JH7110_PLL2_POSTDIV1_SHIFT;
+-
+-	} else {
+-		return -ENOENT;
+-	}
+-
+-	return 0;
+-}
+-
+ static struct clk_hw *jh7110_pll_get(struct of_phandle_args *clkspec, void *data)
+ {
+ 	struct jh7110_clk_pll_priv *priv = data;
+ 	unsigned int idx = clkspec->args[0];
+ 
+-	if (idx < JH7110_PLLCLK_END)
++	if (idx < priv->pll_nums)
+ 		return &priv->data[idx].hw;
+ 
+ 	return ERR_PTR(-EINVAL);
+@@ -363,17 +249,17 @@ static struct clk_hw *jh7110_pll_get(str
+ 
+ static int jh7110_pll_probe(struct platform_device *pdev)
+ {
+-	const char *pll_name[JH7110_PLLCLK_END] = {
+-		"pll0_out",
+-		"pll1_out",
+-		"pll2_out"
+-	};
++	const struct jh7110_pll_conf_variant *variant;
+ 	struct jh7110_clk_pll_priv *priv;
+ 	struct jh7110_clk_pll_data *data;
+ 	int ret;
+ 	unsigned int idx;
+ 
+-	priv = devm_kzalloc(&pdev->dev, struct_size(priv, data, JH7110_PLLCLK_END),
++	variant = of_device_get_match_data(&pdev->dev);
++	if (!variant)
++		return -ENOMEM;
++
++	priv = devm_kzalloc(&pdev->dev, struct_size(priv, data, variant->pll_nums),
+ 			    GFP_KERNEL);
+ 	if (!priv)
+ 		return -ENOMEM;
+@@ -383,12 +269,13 @@ static int jh7110_pll_probe(struct platf
+ 	if (IS_ERR(priv->syscon_regmap))
+ 		return PTR_ERR(priv->syscon_regmap);
+ 
+-	for (idx = 0; idx < JH7110_PLLCLK_END; idx++) {
++	priv->pll_nums = variant->pll_nums;
++	for (idx = 0; idx < priv->pll_nums; idx++) {
+ 		struct clk_parent_data parents = {
+ 			.index = 0,
+ 		};
+ 		struct clk_init_data init = {
+-			.name = pll_name[idx],
++			.name = variant->conf[idx].name,
+ 			.ops = &jh7110_pll_ops,
+ 			.parent_data = &parents,
+ 			.num_parents = 1,
+@@ -396,11 +283,7 @@ static int jh7110_pll_probe(struct platf
+ 		};
+ 
+ 		data = &priv->data[idx];
+-
+-		ret = jh7110_pll_data_get(data, idx);
+-		if (ret)
+-			return ret;
+-
++		data->conf = variant->conf[idx];
+ 		data->hw.init = &init;
+ 		data->idx = idx;
+ 
+@@ -413,7 +296,7 @@ static int jh7110_pll_probe(struct platf
+ }
+ 
+ static const struct of_device_id jh7110_pll_match[] = {
+-	{ .compatible = "starfive,jh7110-pll" },
++	{ .compatible = "starfive,jh7110-pll", .data = &jh7110_pll_variant },
+ 	{ /* sentinel */ }
+ };
+ MODULE_DEVICE_TABLE(of, jh7110_pll_match);
+--- a/drivers/clk/starfive/clk-starfive-jh7110-pll.h
++++ b/drivers/clk/starfive/clk-starfive-jh7110-pll.h
+@@ -13,62 +13,93 @@
+ /* The decimal places are counted by expanding them by a factor of STARFIVE_PLL_FRAC_PATR_SIZE */
+ #define STARFIVE_PLL_FRAC_PATR_SIZE		1000
+ 
+-#define STARFIVE_JH7110_PLL0_DACPD_OFFSET	0x18
+-#define STARFIVE_JH7110_PLL0_DACPD_SHIFT	24
+-#define STARFIVE_JH7110_PLL0_DACPD_MASK		BIT(24)
+-#define STARFIVE_JH7110_PLL0_DSMPD_OFFSET	0x18
+-#define STARFIVE_JH7110_PLL0_DSMPD_SHIFT	25
+-#define STARFIVE_JH7110_PLL0_DSMPD_MASK		BIT(25)
+-#define STARFIVE_JH7110_PLL0_FBDIV_OFFSET	0x1c
+-#define STARFIVE_JH7110_PLL0_FBDIV_SHIFT	0
+-#define STARFIVE_JH7110_PLL0_FBDIV_MASK		GENMASK(11, 0)
+-#define STARFIVE_JH7110_PLL0_FRAC_OFFSET	0x20
+-#define STARFIVE_JH7110_PLL0_FRAC_SHIFT		0
+-#define STARFIVE_JH7110_PLL0_FRAC_MASK		GENMASK(23, 0)
+-#define STARFIVE_JH7110_PLL0_POSTDIV1_OFFSET	0x20
+-#define STARFIVE_JH7110_PLL0_POSTDIV1_SHIFT	28
+-#define STARFIVE_JH7110_PLL0_POSTDIV1_MASK	GENMASK(29, 28)
+-#define STARFIVE_JH7110_PLL0_PREDIV_OFFSET	0x24
+-#define STARFIVE_JH7110_PLL0_PREDIV_SHIFT	0
+-#define STARFIVE_JH7110_PLL0_PREDIV_MASK	GENMASK(5, 0)
+-
+-#define STARFIVE_JH7110_PLL1_DACPD_OFFSET	0x24
+-#define STARFIVE_JH7110_PLL1_DACPD_SHIFT	15
+-#define STARFIVE_JH7110_PLL1_DACPD_MASK		BIT(15)
+-#define STARFIVE_JH7110_PLL1_DSMPD_OFFSET	0x24
+-#define STARFIVE_JH7110_PLL1_DSMPD_SHIFT	16
+-#define STARFIVE_JH7110_PLL1_DSMPD_MASK		BIT(16)
+-#define STARFIVE_JH7110_PLL1_FBDIV_OFFSET	0x24
+-#define STARFIVE_JH7110_PLL1_FBDIV_SHIFT	17
+-#define STARFIVE_JH7110_PLL1_FBDIV_MASK		GENMASK(28, 17)
+-#define STARFIVE_JH7110_PLL1_FRAC_OFFSET	0x28
+-#define STARFIVE_JH7110_PLL1_FRAC_SHIFT		0
+-#define STARFIVE_JH7110_PLL1_FRAC_MASK		GENMASK(23, 0)
+-#define STARFIVE_JH7110_PLL1_POSTDIV1_OFFSET	0x28
+-#define STARFIVE_JH7110_PLL1_POSTDIV1_SHIFT	28
+-#define STARFIVE_JH7110_PLL1_POSTDIV1_MASK	GENMASK(29, 28)
+-#define STARFIVE_JH7110_PLL1_PREDIV_OFFSET	0x2c
+-#define STARFIVE_JH7110_PLL1_PREDIV_SHIFT	0
+-#define STARFIVE_JH7110_PLL1_PREDIV_MASK	GENMASK(5, 0)
+-
+-#define STARFIVE_JH7110_PLL2_DACPD_OFFSET	0x2c
+-#define STARFIVE_JH7110_PLL2_DACPD_SHIFT	15
+-#define STARFIVE_JH7110_PLL2_DACPD_MASK		BIT(15)
+-#define STARFIVE_JH7110_PLL2_DSMPD_OFFSET	0x2c
+-#define STARFIVE_JH7110_PLL2_DSMPD_SHIFT	16
+-#define STARFIVE_JH7110_PLL2_DSMPD_MASK		BIT(16)
+-#define STARFIVE_JH7110_PLL2_FBDIV_OFFSET	0x2c
+-#define STARFIVE_JH7110_PLL2_FBDIV_SHIFT	17
+-#define STARFIVE_JH7110_PLL2_FBDIV_MASK		GENMASK(28, 17)
+-#define STARFIVE_JH7110_PLL2_FRAC_OFFSET	0x30
+-#define STARFIVE_JH7110_PLL2_FRAC_SHIFT		0
+-#define STARFIVE_JH7110_PLL2_FRAC_MASK		GENMASK(23, 0)
+-#define STARFIVE_JH7110_PLL2_POSTDIV1_OFFSET	0x30
+-#define STARFIVE_JH7110_PLL2_POSTDIV1_SHIFT	28
+-#define STARFIVE_JH7110_PLL2_POSTDIV1_MASK	GENMASK(29, 28)
+-#define STARFIVE_JH7110_PLL2_PREDIV_OFFSET	0x34
+-#define STARFIVE_JH7110_PLL2_PREDIV_SHIFT	0
+-#define STARFIVE_JH7110_PLL2_PREDIV_MASK	GENMASK(5, 0)
++#define STARFIVE_JH7110_CLK_PLL0_OUT_DACPD_OFFSET	0x18
++#define STARFIVE_JH7110_CLK_PLL0_OUT_DACPD_SHIFT	24
++#define STARFIVE_JH7110_CLK_PLL0_OUT_DACPD_MASK		BIT(24)
++#define STARFIVE_JH7110_CLK_PLL0_OUT_DSMPD_OFFSET	0x18
++#define STARFIVE_JH7110_CLK_PLL0_OUT_DSMPD_SHIFT	25
++#define STARFIVE_JH7110_CLK_PLL0_OUT_DSMPD_MASK		BIT(25)
++#define STARFIVE_JH7110_CLK_PLL0_OUT_FBDIV_OFFSET	0x1c
++#define STARFIVE_JH7110_CLK_PLL0_OUT_FBDIV_SHIFT	0
++#define STARFIVE_JH7110_CLK_PLL0_OUT_FBDIV_MASK		GENMASK(11, 0)
++#define STARFIVE_JH7110_CLK_PLL0_OUT_FRAC_OFFSET	0x20
++#define STARFIVE_JH7110_CLK_PLL0_OUT_FRAC_SHIFT		0
++#define STARFIVE_JH7110_CLK_PLL0_OUT_FRAC_MASK		GENMASK(23, 0)
++#define STARFIVE_JH7110_CLK_PLL0_OUT_POSTDIV1_OFFSET	0x20
++#define STARFIVE_JH7110_CLK_PLL0_OUT_POSTDIV1_SHIFT	28
++#define STARFIVE_JH7110_CLK_PLL0_OUT_POSTDIV1_MASK	GENMASK(29, 28)
++#define STARFIVE_JH7110_CLK_PLL0_OUT_PREDIV_OFFSET	0x24
++#define STARFIVE_JH7110_CLK_PLL0_OUT_PREDIV_SHIFT	0
++#define STARFIVE_JH7110_CLK_PLL0_OUT_PREDIV_MASK	GENMASK(5, 0)
++
++#define STARFIVE_JH7110_CLK_PLL1_OUT_DACPD_OFFSET	0x24
++#define STARFIVE_JH7110_CLK_PLL1_OUT_DACPD_SHIFT	15
++#define STARFIVE_JH7110_CLK_PLL1_OUT_DACPD_MASK		BIT(15)
++#define STARFIVE_JH7110_CLK_PLL1_OUT_DSMPD_OFFSET	0x24
++#define STARFIVE_JH7110_CLK_PLL1_OUT_DSMPD_SHIFT	16
++#define STARFIVE_JH7110_CLK_PLL1_OUT_DSMPD_MASK		BIT(16)
++#define STARFIVE_JH7110_CLK_PLL1_OUT_FBDIV_OFFSET	0x24
++#define STARFIVE_JH7110_CLK_PLL1_OUT_FBDIV_SHIFT	17
++#define STARFIVE_JH7110_CLK_PLL1_OUT_FBDIV_MASK		GENMASK(28, 17)
++#define STARFIVE_JH7110_CLK_PLL1_OUT_FRAC_OFFSET	0x28
++#define STARFIVE_JH7110_CLK_PLL1_OUT_FRAC_SHIFT		0
++#define STARFIVE_JH7110_CLK_PLL1_OUT_FRAC_MASK		GENMASK(23, 0)
++#define STARFIVE_JH7110_CLK_PLL1_OUT_POSTDIV1_OFFSET	0x28
++#define STARFIVE_JH7110_CLK_PLL1_OUT_POSTDIV1_SHIFT	28
++#define STARFIVE_JH7110_CLK_PLL1_OUT_POSTDIV1_MASK	GENMASK(29, 28)
++#define STARFIVE_JH7110_CLK_PLL1_OUT_PREDIV_OFFSET	0x2c
++#define STARFIVE_JH7110_CLK_PLL1_OUT_PREDIV_SHIFT	0
++#define STARFIVE_JH7110_CLK_PLL1_OUT_PREDIV_MASK	GENMASK(5, 0)
++
++#define STARFIVE_JH7110_CLK_PLL2_OUT_DACPD_OFFSET	0x2c
++#define STARFIVE_JH7110_CLK_PLL2_OUT_DACPD_SHIFT	15
++#define STARFIVE_JH7110_CLK_PLL2_OUT_DACPD_MASK		BIT(15)
++#define STARFIVE_JH7110_CLK_PLL2_OUT_DSMPD_OFFSET	0x2c
++#define STARFIVE_JH7110_CLK_PLL2_OUT_DSMPD_SHIFT	16
++#define STARFIVE_JH7110_CLK_PLL2_OUT_DSMPD_MASK		BIT(16)
++#define STARFIVE_JH7110_CLK_PLL2_OUT_FBDIV_OFFSET	0x2c
++#define STARFIVE_JH7110_CLK_PLL2_OUT_FBDIV_SHIFT	17
++#define STARFIVE_JH7110_CLK_PLL2_OUT_FBDIV_MASK		GENMASK(28, 17)
++#define STARFIVE_JH7110_CLK_PLL2_OUT_FRAC_OFFSET	0x30
++#define STARFIVE_JH7110_CLK_PLL2_OUT_FRAC_SHIFT		0
++#define STARFIVE_JH7110_CLK_PLL2_OUT_FRAC_MASK		GENMASK(23, 0)
++#define STARFIVE_JH7110_CLK_PLL2_OUT_POSTDIV1_OFFSET	0x30
++#define STARFIVE_JH7110_CLK_PLL2_OUT_POSTDIV1_SHIFT	28
++#define STARFIVE_JH7110_CLK_PLL2_OUT_POSTDIV1_MASK	GENMASK(29, 28)
++#define STARFIVE_JH7110_CLK_PLL2_OUT_PREDIV_OFFSET	0x34
++#define STARFIVE_JH7110_CLK_PLL2_OUT_PREDIV_SHIFT	0
++#define STARFIVE_JH7110_CLK_PLL2_OUT_PREDIV_MASK	GENMASK(5, 0)
++
++#define JH7110_PLL(_idx, _name, _nums, _val)			\
++[_idx] = {							\
++	.name = _name,						\
++	.offsets = {						\
++		.dacpd = STARFIVE_##_idx##_DACPD_OFFSET,	\
++		.dsmpd = STARFIVE_##_idx##_DSMPD_OFFSET,	\
++		.fbdiv = STARFIVE_##_idx##_FBDIV_OFFSET,	\
++		.frac = STARFIVE_##_idx##_FRAC_OFFSET,		\
++		.prediv = STARFIVE_##_idx##_PREDIV_OFFSET,	\
++		.postdiv1 = STARFIVE_##_idx##_POSTDIV1_OFFSET,	\
++	},							\
++	.masks = {						\
++		.dacpd = STARFIVE_##_idx##_DACPD_MASK,		\
++		.dsmpd = STARFIVE_##_idx##_DSMPD_MASK,		\
++		.fbdiv = STARFIVE_##_idx##_FBDIV_MASK,		\
++		.frac = STARFIVE_##_idx##_FRAC_MASK,		\
++		.prediv = STARFIVE_##_idx##_PREDIV_MASK,	\
++		.postdiv1 = STARFIVE_##_idx##_POSTDIV1_MASK,	\
++	},							\
++	.shifts = {						\
++		.dacpd = STARFIVE_##_idx##_DACPD_SHIFT,		\
++		.dsmpd = STARFIVE_##_idx##_DSMPD_SHIFT,		\
++		.fbdiv = STARFIVE_##_idx##_FBDIV_SHIFT,		\
++		.frac = STARFIVE_##_idx##_FRAC_SHIFT,		\
++		.prediv = STARFIVE_##_idx##_PREDIV_SHIFT,	\
++		.postdiv1 = STARFIVE_##_idx##_POSTDIV1_SHIFT,	\
++	},							\
++	.preset_val_nums = _nums,				\
++	.preset_val = _val,					\
++}
+ 
+ struct jh7110_pll_syscon_offset {
+ 	unsigned int dacpd;
+@@ -97,23 +128,7 @@ struct jh7110_pll_syscon_shift {
+ 	char postdiv1;
+ };
+ 
+-struct jh7110_clk_pll_data {
+-	struct clk_hw hw;
+-	unsigned int idx;
+-	unsigned int freq_select_idx;
+-
+-	struct jh7110_pll_syscon_offset offset;
+-	struct jh7110_pll_syscon_mask mask;
+-	struct jh7110_pll_syscon_shift shift;
+-};
+-
+-struct jh7110_clk_pll_priv {
+-	struct device *dev;
+-	struct regmap *syscon_regmap;
+-	struct jh7110_clk_pll_data data[];
+-};
+-
+-struct starfive_pll_syscon_value {
++struct jh7110_pll_syscon_val {
+ 	unsigned long freq;
+ 	u32 prediv;
+ 	u32 fbdiv;
+@@ -126,31 +141,54 @@ struct starfive_pll_syscon_value {
+ 	u32 frac;
+ };
+ 
+-enum starfive_pll0_freq_index {
+-	PLL0_FREQ_375 = 0,
+-	PLL0_FREQ_500,
+-	PLL0_FREQ_625,
+-	PLL0_FREQ_750,
+-	PLL0_FREQ_875,
+-	PLL0_FREQ_1000,
+-	PLL0_FREQ_1250,
+-	PLL0_FREQ_1375,
+-	PLL0_FREQ_1500,
+-	PLL0_FREQ_MAX
+-};
+-
+-enum starfive_pll1_freq_index {
+-	PLL1_FREQ_1066 = 0,
+-	PLL1_FREQ_1200,
+-	PLL1_FREQ_1400,
+-	PLL1_FREQ_1600,
+-	PLL1_FREQ_MAX
+-};
+-
+-enum starfive_pll2_freq_index {
+-	PLL2_FREQ_1188 = 0,
+-	PLL2_FREQ_12288,
+-	PLL2_FREQ_MAX
++struct jh7110_pll_syscon_conf {
++	char *name;
++	struct jh7110_pll_syscon_offset offsets;
++	struct jh7110_pll_syscon_mask masks;
++	struct jh7110_pll_syscon_shift shifts;
++	unsigned int preset_val_nums;
++	const struct jh7110_pll_syscon_val *preset_val;
++};
++
++struct jh7110_clk_pll_data {
++	struct clk_hw hw;
++	unsigned int idx;
++	unsigned int freq_select_idx;
++	struct jh7110_pll_syscon_conf conf;
++};
++
++struct jh7110_clk_pll_priv {
++	unsigned int pll_nums;
++	struct device *dev;
++	struct regmap *syscon_regmap;
++	struct jh7110_clk_pll_data data[];
++};
++
++enum jh7110_pll0_freq_index {
++	JH7110_PLL0_FREQ_375 = 0,
++	JH7110_PLL0_FREQ_500,
++	JH7110_PLL0_FREQ_625,
++	JH7110_PLL0_FREQ_750,
++	JH7110_PLL0_FREQ_875,
++	JH7110_PLL0_FREQ_1000,
++	JH7110_PLL0_FREQ_1250,
++	JH7110_PLL0_FREQ_1375,
++	JH7110_PLL0_FREQ_1500,
++	JH7110_PLL0_FREQ_MAX
++};
++
++enum jh7110_pll1_freq_index {
++	JH7110_PLL1_FREQ_1066 = 0,
++	JH7110_PLL1_FREQ_1200,
++	JH7110_PLL1_FREQ_1400,
++	JH7110_PLL1_FREQ_1600,
++	JH7110_PLL1_FREQ_MAX
++};
++
++enum jh7110_pll2_freq_index {
++	JH7110_PLL2_FREQ_1188 = 0,
++	JH7110_PLL2_FREQ_12288,
++	JH7110_PLL2_FREQ_MAX
+ };
+ 
+ /*
+@@ -158,9 +196,9 @@ enum starfive_pll2_freq_index {
+  * it cannot be set arbitrarily, so it needs a specific configuration.
+  * PLL0 frequency should be multiple of 125MHz (USB frequency).
+  */
+-static const struct starfive_pll_syscon_value
+-	jh7110_pll0_syscon_freq[PLL0_FREQ_MAX] = {
+-	[PLL0_FREQ_375] = {
++static const struct jh7110_pll_syscon_val
++	jh7110_pll0_syscon_val_preset[] = {
++	[JH7110_PLL0_FREQ_375] = {
+ 		.freq = 375000000,
+ 		.prediv = 8,
+ 		.fbdiv = 125,
+@@ -168,7 +206,7 @@ static const struct starfive_pll_syscon_
+ 		.dacpd = 1,
+ 		.dsmpd = 1,
+ 	},
+-	[PLL0_FREQ_500] = {
++	[JH7110_PLL0_FREQ_500] = {
+ 		.freq = 500000000,
+ 		.prediv = 6,
+ 		.fbdiv = 125,
+@@ -176,7 +214,7 @@ static const struct starfive_pll_syscon_
+ 		.dacpd = 1,
+ 		.dsmpd = 1,
+ 	},
+-	[PLL0_FREQ_625] = {
++	[JH7110_PLL0_FREQ_625] = {
+ 		.freq = 625000000,
+ 		.prediv = 24,
+ 		.fbdiv = 625,
+@@ -184,7 +222,7 @@ static const struct starfive_pll_syscon_
+ 		.dacpd = 1,
+ 		.dsmpd = 1,
+ 	},
+-	[PLL0_FREQ_750] = {
++	[JH7110_PLL0_FREQ_750] = {
+ 		.freq = 750000000,
+ 		.prediv = 4,
+ 		.fbdiv = 125,
+@@ -192,7 +230,7 @@ static const struct starfive_pll_syscon_
+ 		.dacpd = 1,
+ 		.dsmpd = 1,
+ 	},
+-	[PLL0_FREQ_875] = {
++	[JH7110_PLL0_FREQ_875] = {
+ 		.freq = 875000000,
+ 		.prediv = 24,
+ 		.fbdiv = 875,
+@@ -200,7 +238,7 @@ static const struct starfive_pll_syscon_
+ 		.dacpd = 1,
+ 		.dsmpd = 1,
+ 	},
+-	[PLL0_FREQ_1000] = {
++	[JH7110_PLL0_FREQ_1000] = {
+ 		.freq = 1000000000,
+ 		.prediv = 3,
+ 		.fbdiv = 125,
+@@ -208,7 +246,7 @@ static const struct starfive_pll_syscon_
+ 		.dacpd = 1,
+ 		.dsmpd = 1,
+ 	},
+-	[PLL0_FREQ_1250] = {
++	[JH7110_PLL0_FREQ_1250] = {
+ 		.freq = 1250000000,
+ 		.prediv = 12,
+ 		.fbdiv = 625,
+@@ -216,7 +254,7 @@ static const struct starfive_pll_syscon_
+ 		.dacpd = 1,
+ 		.dsmpd = 1,
+ 	},
+-	[PLL0_FREQ_1375] = {
++	[JH7110_PLL0_FREQ_1375] = {
+ 		.freq = 1375000000,
+ 		.prediv = 24,
+ 		.fbdiv = 1375,
+@@ -224,7 +262,7 @@ static const struct starfive_pll_syscon_
+ 		.dacpd = 1,
+ 		.dsmpd = 1,
+ 	},
+-	[PLL0_FREQ_1500] = {
++	[JH7110_PLL0_FREQ_1500] = {
+ 		.freq = 1500000000,
+ 		.prediv = 2,
+ 		.fbdiv = 125,
+@@ -234,9 +272,9 @@ static const struct starfive_pll_syscon_
+ 	},
+ };
+ 
+-static const struct starfive_pll_syscon_value
+-	jh7110_pll1_syscon_freq[PLL1_FREQ_MAX] = {
+-	[PLL1_FREQ_1066] = {
++static const struct jh7110_pll_syscon_val
++	jh7110_pll1_syscon_val_preset[] = {
++	[JH7110_PLL1_FREQ_1066] = {
+ 		.freq = 1066000000,
+ 		.prediv = 12,
+ 		.fbdiv = 533,
+@@ -244,7 +282,7 @@ static const struct starfive_pll_syscon_
+ 		.dacpd = 1,
+ 		.dsmpd = 1,
+ 	},
+-	[PLL1_FREQ_1200] = {
++	[JH7110_PLL1_FREQ_1200] = {
+ 		.freq = 1200000000,
+ 		.prediv = 1,
+ 		.fbdiv = 50,
+@@ -252,7 +290,7 @@ static const struct starfive_pll_syscon_
+ 		.dacpd = 1,
+ 		.dsmpd = 1,
+ 	},
+-	[PLL1_FREQ_1400] = {
++	[JH7110_PLL1_FREQ_1400] = {
+ 		.freq = 1400000000,
+ 		.prediv = 6,
+ 		.fbdiv = 350,
+@@ -260,7 +298,7 @@ static const struct starfive_pll_syscon_
+ 		.dacpd = 1,
+ 		.dsmpd = 1,
+ 	},
+-	[PLL1_FREQ_1600] = {
++	[JH7110_PLL1_FREQ_1600] = {
+ 		.freq = 1600000000,
+ 		.prediv = 3,
+ 		.fbdiv = 200,
+@@ -270,9 +308,9 @@ static const struct starfive_pll_syscon_
+ 	},
+ };
+ 
+-static const struct starfive_pll_syscon_value
+-	jh7110_pll2_syscon_freq[PLL2_FREQ_MAX] = {
+-	[PLL2_FREQ_1188] = {
++static const struct jh7110_pll_syscon_val
++	jh7110_pll2_syscon_val_preset[] = {
++	[JH7110_PLL2_FREQ_1188] = {
+ 		.freq = 1188000000,
+ 		.prediv = 2,
+ 		.fbdiv = 99,
+@@ -280,7 +318,7 @@ static const struct starfive_pll_syscon_
+ 		.dacpd = 1,
+ 		.dsmpd = 1,
+ 	},
+-	[PLL2_FREQ_12288] = {
++	[JH7110_PLL2_FREQ_12288] = {
+ 		.freq = 1228800000,
+ 		.prediv = 5,
+ 		.fbdiv = 256,

+ 113 - 0
target/linux/starfive/patches-6.1/0059-dt-bindings-timer-Add-timer-for-StarFive-JH7110-SoC.patch

@@ -0,0 +1,113 @@
+From 944b96d734199642e2ede978c48d754109ca334c Mon Sep 17 00:00:00 2001
+From: Xingyu Wu <[email protected]>
+Date: Mon, 20 Mar 2023 21:54:31 +0800
+Subject: [PATCH 059/122] dt-bindings: timer: Add timer for StarFive JH7110 SoC
+
+Add bindings for the timer on the JH7110 RISC-V SoC
+by StarFive Technology Ltd.
+
+Signed-off-by: Xingyu Wu <[email protected]>
+Reviewed-by: Krzysztof Kozlowski <[email protected]>
+---
+ .../bindings/timer/starfive,jh7110-timer.yaml | 95 +++++++++++++++++++
+ 1 file changed, 95 insertions(+)
+ create mode 100644 Documentation/devicetree/bindings/timer/starfive,jh7110-timer.yaml
+
+--- /dev/null
++++ b/Documentation/devicetree/bindings/timer/starfive,jh7110-timer.yaml
+@@ -0,0 +1,95 @@
++# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
++%YAML 1.2
++---
++$id: http://devicetree.org/schemas/timer/starfive,jh7110-timer.yaml#
++$schema: http://devicetree.org/meta-schemas/core.yaml#
++
++title: StarFive JH7110 Timer
++maintainers:
++  - Xingyu Wu <[email protected]>
++  - Samin Guo <[email protected]>
++
++description:
++  This timer has four free-running 32 bit counters in StarFive JH7110 SoC.
++  And each channel(counter) triggers an interrupt when timeout. They support
++  one-shot mode and continuous-run mode.
++
++properties:
++  compatible:
++    const: starfive,jh7110-timer
++
++  reg:
++    maxItems: 1
++
++  interrupts:
++    items:
++      - description: channel 0
++      - description: channel 1
++      - description: channel 2
++      - description: channel 3
++
++  clocks:
++    items:
++      - description: timer APB
++      - description: channel 0
++      - description: channel 1
++      - description: channel 2
++      - description: channel 3
++
++  clock-names:
++    items:
++      - const: apb
++      - const: ch0
++      - const: ch1
++      - const: ch2
++      - const: ch3
++
++  resets:
++    items:
++      - description: timer APB
++      - description: channel 0
++      - description: channel 1
++      - description: channel 2
++      - description: channel 3
++
++  reset-names:
++    items:
++      - const: apb
++      - const: ch0
++      - const: ch1
++      - const: ch2
++      - const: ch3
++
++required:
++  - compatible
++  - reg
++  - interrupts
++  - clocks
++  - clock-names
++  - resets
++  - reset-names
++
++additionalProperties: false
++
++examples:
++  - |
++    timer@13050000 {
++        compatible = "starfive,jh7110-timer";
++        reg = <0x13050000 0x10000>;
++        interrupts = <69>, <70>, <71> ,<72>;
++        clocks = <&clk 124>,
++                 <&clk 125>,
++                 <&clk 126>,
++                 <&clk 127>,
++                 <&clk 128>;
++        clock-names = "apb", "ch0", "ch1",
++                      "ch2", "ch3";
++        resets = <&rst 117>,
++                 <&rst 118>,
++                 <&rst 119>,
++                 <&rst 120>,
++                 <&rst 121>;
++        reset-names = "apb", "ch0", "ch1",
++                      "ch2", "ch3";
++    };
++

+ 540 - 0
target/linux/starfive/patches-6.1/0060-clocksource-Add-StarFive-timer-driver.patch

@@ -0,0 +1,540 @@
+From 3fbdabd59bac0978536fb11b1b9deb81559f1c54 Mon Sep 17 00:00:00 2001
+From: Xingyu Wu <[email protected]>
+Date: Mon, 20 Mar 2023 21:54:32 +0800
+Subject: [PATCH 060/122] clocksource: Add StarFive timer driver
+
+Add timer driver for the StarFive JH7110 SoC.
+
+Signed-off-by: Xingyu Wu <[email protected]>
+---
+ drivers/clocksource/Kconfig          |  12 +
+ drivers/clocksource/Makefile         |   1 +
+ drivers/clocksource/timer-starfive.c | 390 +++++++++++++++++++++++++++
+ drivers/clocksource/timer-starfive.h |  96 +++++++
+ 4 files changed, 499 insertions(+)
+ create mode 100644 drivers/clocksource/timer-starfive.c
+ create mode 100644 drivers/clocksource/timer-starfive.h
+
+--- a/drivers/clocksource/Kconfig
++++ b/drivers/clocksource/Kconfig
+@@ -630,6 +630,18 @@ config RISCV_TIMER
+ 	  is accessed via both the SBI and the rdcycle instruction.  This is
+ 	  required for all RISC-V systems.
+ 
++config STARFIVE_TIMER
++	bool "Timer for the STARFIVE SoCs"
++	depends on ARCH_STARFIVE || COMPILE_TEST
++	select TIMER_OF
++	select CLKSRC_MMIO
++	default ARCH_STARFIVE
++	help
++	  This enables the timer for StarFive SoCs. On RISC-V platform,
++	  the system has started RISCV_TIMER. But you can also use this timer
++	  to do a lot more on StarFive SoCs. This timer can provide high
++	  precision and four channels to use in JH7110 SoC.
++
+ config CLINT_TIMER
+ 	bool "CLINT Timer for the RISC-V platform" if COMPILE_TEST
+ 	depends on GENERIC_SCHED_CLOCK && RISCV
+--- a/drivers/clocksource/Makefile
++++ b/drivers/clocksource/Makefile
+@@ -80,6 +80,7 @@ obj-$(CONFIG_INGENIC_TIMER)		+= ingenic-
+ obj-$(CONFIG_CLKSRC_ST_LPC)		+= clksrc_st_lpc.o
+ obj-$(CONFIG_X86_NUMACHIP)		+= numachip.o
+ obj-$(CONFIG_RISCV_TIMER)		+= timer-riscv.o
++obj-$(CONFIG_STARFIVE_TIMER)		+= timer-starfive.o
+ obj-$(CONFIG_CLINT_TIMER)		+= timer-clint.o
+ obj-$(CONFIG_CSKY_MP_TIMER)		+= timer-mp-csky.o
+ obj-$(CONFIG_GX6605S_TIMER)		+= timer-gx6605s.o
+--- /dev/null
++++ b/drivers/clocksource/timer-starfive.c
+@@ -0,0 +1,390 @@
++// SPDX-License-Identifier: GPL-2.0
++/*
++ * Starfive Timer driver
++ *
++ * Copyright (C) 2022 StarFive Technology Co., Ltd.
++ *
++ * Author:
++ * Xingyu Wu <[email protected]>
++ * Samin Guo <[email protected]>
++ */
++
++#include <linux/clk.h>
++#include <linux/clockchips.h>
++#include <linux/clocksource.h>
++#include <linux/err.h>
++#include <linux/interrupt.h>
++#include <linux/io.h>
++#include <linux/iopoll.h>
++#include <linux/irq.h>
++#include <linux/kernel.h>
++#include <linux/module.h>
++#include <linux/of.h>
++#include <linux/of_device.h>
++#include <linux/platform_device.h>
++#include <linux/reset.h>
++#include <linux/sched_clock.h>
++
++#include "timer-starfive.h"
++
++static const struct starfive_timer_chan_base starfive_timer_jh7110_base = {
++	.ctrl		= STARFIVE_TIMER_JH7110_CTL,
++	.load		= STARFIVE_TIMER_JH7110_LOAD,
++	.enable		= STARFIVE_TIMER_JH7110_ENABLE,
++	.reload		= STARFIVE_TIMER_JH7110_RELOAD,
++	.value		= STARFIVE_TIMER_JH7110_VALUE,
++	.intclr		= STARFIVE_TIMER_JH7110_INT_CLR,
++	.intmask	= STARFIVE_TIMER_JH7110_INT_MASK,
++	.channel_num	= STARFIVE_TIMER_CH_4,
++	.channel_base	= {STARFIVE_TIMER_CH_BASE(0), STARFIVE_TIMER_CH_BASE(1),
++			   STARFIVE_TIMER_CH_BASE(2), STARFIVE_TIMER_CH_BASE(3)},
++};
++
++static inline struct starfive_clkevt *to_starfive_clkevt(struct clock_event_device *evt)
++{
++	return container_of(evt, struct starfive_clkevt, evt);
++}
++
++/* 0:continuous-run mode, 1:single-run mode */
++static inline void starfive_timer_set_mod(struct starfive_clkevt *clkevt, int mod)
++{
++	writel(mod, clkevt->ctrl);
++}
++
++/* Interrupt Mask Register, 0:Unmask, 1:Mask */
++static inline void starfive_timer_int_enable(struct starfive_clkevt *clkevt)
++{
++	writel(STARFIVE_TIMER_INTMASK_DIS, clkevt->intmask);
++}
++
++static inline void starfive_timer_int_disable(struct starfive_clkevt *clkevt)
++{
++	writel(STARFIVE_TIMER_INTMASK_ENA, clkevt->intmask);
++}
++
++/*
++ * BIT(0): Read value represent channel intr status.
++ * Write 1 to this bit to clear interrupt. Write 0 has no effects.
++ * BIT(1): "1" means that it is clearing interrupt. BIT(0) can not be written.
++ */
++static inline int starfive_timer_int_clear(struct starfive_clkevt *clkevt)
++{
++	u32 value;
++	int ret;
++
++	/* waiting interrupt can be to clearing */
++	ret = readl_poll_timeout_atomic(clkevt->intclr, value,
++					!(value & STARFIVE_TIMER_JH7110_INT_CLR_AVA_MASK),
++					STARFIVE_DELAY_US, STARFIVE_TIMEOUT_US);
++	if (!ret)
++		writel(0x1, clkevt->intclr);
++
++	return ret;
++}
++
++/*
++ * The initial value to be loaded into the
++ * counter and is also used as the reload value.
++ * val = clock rate --> 1s
++ */
++static inline void starfive_timer_set_load(struct starfive_clkevt *clkevt, u32 val)
++{
++	writel(val, clkevt->load);
++}
++
++static inline u32 starfive_timer_get_val(struct starfive_clkevt *clkevt)
++{
++	return readl(clkevt->value);
++}
++
++/*
++ * Write RELOAD register to reload preset value to counter.
++ * (Write 0 and write 1 are both ok)
++ */
++static inline void starfive_timer_set_reload(struct starfive_clkevt *clkevt)
++{
++	writel(0, clkevt->reload);
++}
++
++static inline void starfive_timer_enable(struct starfive_clkevt *clkevt)
++{
++	writel(STARFIVE_TIMER_ENA, clkevt->enable);
++}
++
++static inline void starfive_timer_disable(struct starfive_clkevt *clkevt)
++{
++	writel(STARFIVE_TIMER_DIS, clkevt->enable);
++}
++
++static int starfive_timer_int_init_enable(struct starfive_clkevt *clkevt)
++{
++	int ret;
++
++	starfive_timer_int_disable(clkevt);
++	ret = starfive_timer_int_clear(clkevt);
++	if (ret)
++		return ret;
++
++	starfive_timer_int_enable(clkevt);
++	starfive_timer_enable(clkevt);
++
++	return 0;
++}
++
++static int starfive_timer_shutdown(struct clock_event_device *evt)
++{
++	struct starfive_clkevt *clkevt = to_starfive_clkevt(evt);
++
++	starfive_timer_disable(clkevt);
++	return starfive_timer_int_clear(clkevt);
++}
++
++static void starfive_timer_suspend(struct clock_event_device *evt)
++{
++	struct starfive_clkevt *clkevt = to_starfive_clkevt(evt);
++
++	clkevt->reload_val = starfive_timer_get_val(clkevt);
++	starfive_timer_shutdown(evt);
++}
++
++static void starfive_timer_resume(struct clock_event_device *evt)
++{
++	struct starfive_clkevt *clkevt = to_starfive_clkevt(evt);
++
++	starfive_timer_set_load(clkevt, clkevt->reload_val);
++	starfive_timer_set_reload(clkevt);
++	starfive_timer_int_enable(clkevt);
++	starfive_timer_enable(clkevt);
++}
++
++static int starfive_timer_tick_resume(struct clock_event_device *evt)
++{
++	starfive_timer_resume(evt);
++
++	return 0;
++}
++
++static int starfive_clocksource_init(struct starfive_clkevt *clkevt)
++{
++	int ret;
++
++	starfive_timer_set_mod(clkevt, STARFIVE_TIMER_MOD_CONTIN);
++	starfive_timer_set_load(clkevt, STARFIVE_TIMER_MAX_TICKS);
++	ret = starfive_timer_int_init_enable(clkevt);
++	if (ret)
++		return ret;
++
++	return clocksource_mmio_init(clkevt->value, clkevt->name, clkevt->rate,
++				     STARFIVE_CLOCK_SOURCE_RATING, STARFIVE_VALID_BITS,
++				     clocksource_mmio_readl_down);
++}
++
++/* IRQ handler for the timer */
++static irqreturn_t starfive_timer_interrupt(int irq, void *priv)
++{
++	struct clock_event_device *evt = (struct clock_event_device *)priv;
++	struct starfive_clkevt *clkevt = to_starfive_clkevt(evt);
++
++	if (starfive_timer_int_clear(clkevt))
++		return IRQ_NONE;
++
++	if (evt->event_handler)
++		evt->event_handler(evt);
++
++	return IRQ_HANDLED;
++}
++
++static int starfive_timer_set_periodic(struct clock_event_device *evt)
++{
++	struct starfive_clkevt *clkevt = to_starfive_clkevt(evt);
++
++	starfive_timer_disable(clkevt);
++	starfive_timer_set_mod(clkevt, STARFIVE_TIMER_MOD_CONTIN);
++	starfive_timer_set_load(clkevt, clkevt->periodic);
++
++	return starfive_timer_int_init_enable(clkevt);
++}
++
++static int starfive_timer_set_oneshot(struct clock_event_device *evt)
++{
++	struct starfive_clkevt *clkevt = to_starfive_clkevt(evt);
++
++	starfive_timer_disable(clkevt);
++	starfive_timer_set_mod(clkevt, STARFIVE_TIMER_MOD_SINGLE);
++	starfive_timer_set_load(clkevt, STARFIVE_TIMER_MAX_TICKS);
++
++	return starfive_timer_int_init_enable(clkevt);
++}
++
++static int starfive_timer_set_next_event(unsigned long next,
++					 struct clock_event_device *evt)
++{
++	struct starfive_clkevt *clkevt = to_starfive_clkevt(evt);
++
++	starfive_timer_disable(clkevt);
++	starfive_timer_set_mod(clkevt, STARFIVE_TIMER_MOD_SINGLE);
++	starfive_timer_set_load(clkevt, next);
++	starfive_timer_enable(clkevt);
++
++	return 0;
++}
++
++static void starfive_set_clockevent(struct clock_event_device *evt)
++{
++	evt->features = CLOCK_EVT_FEAT_PERIODIC |
++			CLOCK_EVT_FEAT_ONESHOT |
++			CLOCK_EVT_FEAT_DYNIRQ;
++	evt->set_state_shutdown = starfive_timer_shutdown;
++	evt->set_state_periodic = starfive_timer_set_periodic;
++	evt->set_state_oneshot = starfive_timer_set_oneshot;
++	evt->set_state_oneshot_stopped = starfive_timer_shutdown;
++	evt->tick_resume = starfive_timer_tick_resume;
++	evt->set_next_event = starfive_timer_set_next_event;
++	evt->suspend = starfive_timer_suspend;
++	evt->resume = starfive_timer_resume;
++	evt->rating = STARFIVE_CLOCKEVENT_RATING;
++}
++
++static void starfive_clockevents_register(struct starfive_clkevt *clkevt)
++{
++	clkevt->rate = clk_get_rate(clkevt->clk);
++	clkevt->periodic = DIV_ROUND_CLOSEST(clkevt->rate, HZ);
++
++	starfive_set_clockevent(&clkevt->evt);
++	clkevt->evt.name = clkevt->name;
++	clkevt->evt.irq = clkevt->irq;
++	clkevt->evt.cpumask = cpu_possible_mask;
++
++	clockevents_config_and_register(&clkevt->evt, clkevt->rate,
++					STARFIVE_TIMER_MIN_TICKS, STARFIVE_TIMER_MAX_TICKS);
++}
++
++static void __init starfive_clkevt_base_init(const struct starfive_timer_chan_base *timer,
++					     struct starfive_clkevt *clkevt,
++					     void __iomem *base, int ch)
++{
++	void __iomem *channel_base;
++
++	channel_base = base + timer->channel_base[ch];
++	clkevt->base = channel_base;
++	clkevt->ctrl = channel_base + timer->ctrl;
++	clkevt->load = channel_base + timer->load;
++	clkevt->enable = channel_base + timer->enable;
++	clkevt->reload = channel_base + timer->reload;
++	clkevt->value = channel_base + timer->value;
++	clkevt->intclr = channel_base + timer->intclr;
++	clkevt->intmask = channel_base + timer->intmask;
++}
++
++static int __init starfive_timer_probe(struct platform_device *pdev)
++{
++	const struct starfive_timer_chan_base *timer_base = of_device_get_match_data(&pdev->dev);
++	char name[10];
++	struct starfive_timer_priv *priv;
++	struct starfive_clkevt *clkevt;
++	struct clk *pclk;
++	struct reset_control *rst;
++	int ch;
++	int ret;
++
++	priv = devm_kzalloc(&pdev->dev, struct_size(priv, clkevt, timer_base->channel_num),
++			    GFP_KERNEL);
++	if (!priv)
++		return -ENOMEM;
++
++	priv->base = devm_platform_ioremap_resource(pdev, 0);
++	if (IS_ERR(priv->base))
++		return dev_err_probe(&pdev->dev, PTR_ERR(priv->base),
++				     "failed to map registers\n");
++
++	rst = devm_reset_control_get_exclusive(&pdev->dev, "apb");
++	if (IS_ERR(rst))
++		return dev_err_probe(&pdev->dev, PTR_ERR(rst), "failed to get apb reset\n");
++
++	pclk = devm_clk_get_enabled(&pdev->dev, "apb");
++	if (IS_ERR(pclk))
++		return dev_err_probe(&pdev->dev, PTR_ERR(pclk),
++				     "failed to get & enable apb clock\n");
++
++	ret = reset_control_deassert(rst);
++	if (ret)
++		goto err;
++
++	priv->dev = &pdev->dev;
++	platform_set_drvdata(pdev, priv);
++
++	for (ch = 0; ch < timer_base->channel_num; ch++) {
++		clkevt = &priv->clkevt[ch];
++		snprintf(name, sizeof(name), "ch%d", ch);
++
++		starfive_clkevt_base_init(timer_base, clkevt, priv->base, ch);
++		/* Ensure timers are disabled */
++		starfive_timer_disable(clkevt);
++
++		rst = devm_reset_control_get_exclusive(&pdev->dev, name);
++		if (IS_ERR(rst)) {
++			ret = PTR_ERR(rst);
++			goto err;
++		}
++
++		clkevt->clk = devm_clk_get_enabled(&pdev->dev, name);
++		if (IS_ERR(clkevt->clk)) {
++			ret = PTR_ERR(clkevt->clk);
++			goto err;
++		}
++
++		ret = reset_control_deassert(rst);
++		if (ret)
++			goto ch_err;
++
++		clkevt->irq = platform_get_irq(pdev, ch);
++		if (clkevt->irq < 0) {
++			ret = clkevt->irq;
++			goto ch_err;
++		}
++
++		snprintf(clkevt->name, sizeof(clkevt->name), "%s.ch%d", pdev->name, ch);
++		starfive_clockevents_register(clkevt);
++
++		ret = devm_request_irq(&pdev->dev, clkevt->irq, starfive_timer_interrupt,
++				       IRQF_TIMER | IRQF_IRQPOLL,
++				       clkevt->name, &clkevt->evt);
++		if (ret)
++			goto ch_err;
++
++		ret = starfive_clocksource_init(clkevt);
++		if (ret)
++			goto ch_err;
++	}
++
++	return 0;
++
++ch_err:
++	/* Only unregister the failed channel and the rest timer channels continue to work. */
++	clk_disable_unprepare(clkevt->clk);
++err:
++	/* If no other channel successfully registers, pclk should be disabled. */
++	if (!ch)
++		clk_disable_unprepare(pclk);
++
++	return ret;
++}
++
++static const struct of_device_id starfive_timer_match[] = {
++	{ .compatible = "starfive,jh7110-timer", .data = &starfive_timer_jh7110_base },
++	{ /* sentinel */ }
++};
++MODULE_DEVICE_TABLE(of, starfive_timer_match);
++
++static struct platform_driver starfive_timer_driver = {
++	.probe = starfive_timer_probe,
++	.driver = {
++		.name = "starfive-timer",
++		.of_match_table = starfive_timer_match,
++	},
++};
++module_platform_driver(starfive_timer_driver);
++
++MODULE_AUTHOR("Xingyu Wu <[email protected]>");
++MODULE_DESCRIPTION("StarFive timer driver");
++MODULE_LICENSE("GPL");
+--- /dev/null
++++ b/drivers/clocksource/timer-starfive.h
+@@ -0,0 +1,96 @@
++/* SPDX-License-Identifier: GPL-2.0 */
++/*
++ * Copyright (C) 2022 StarFive Technology Co., Ltd.
++ */
++
++#ifndef __STARFIVE_TIMER_H__
++#define __STARFIVE_TIMER_H__
++
++/* Bias: Ch0-0x0, Ch1-0x40, Ch2-0x80, and so on. */
++#define STARFIVE_TIMER_CH_LEN			0x40
++#define STARFIVE_TIMER_CH_BASE(x)		((STARFIVE_TIMER_CH_##x) * STARFIVE_TIMER_CH_LEN)
++
++#define STARFIVE_CLOCK_SOURCE_RATING		200
++#define STARFIVE_VALID_BITS			32
++#define STARFIVE_DELAY_US			0
++#define STARFIVE_TIMEOUT_US			10000
++#define STARFIVE_CLOCKEVENT_RATING		300
++#define STARFIVE_TIMER_MAX_TICKS		0xffffffff
++#define STARFIVE_TIMER_MIN_TICKS		0xf
++
++#define STARFIVE_TIMER_JH7110_INT_STATUS	0x00 /* RO[0:4]: Interrupt Status for channel0~4 */
++#define STARFIVE_TIMER_JH7110_CTL		0x04 /* RW[0]: 0-continuous run, 1-single run */
++#define STARFIVE_TIMER_JH7110_LOAD		0x08 /* RW: load value to counter */
++#define STARFIVE_TIMER_JH7110_ENABLE		0x10 /* RW[0]: timer enable register */
++#define STARFIVE_TIMER_JH7110_RELOAD		0x14 /* RW: write 1 or 0 both reload counter */
++#define STARFIVE_TIMER_JH7110_VALUE		0x18 /* RO: timer value register */
++#define STARFIVE_TIMER_JH7110_INT_CLR		0x20 /* RW: timer interrupt clear register */
++#define STARFIVE_TIMER_JH7110_INT_MASK		0x24 /* RW[0]: timer interrupt mask register */
++#define STARFIVE_TIMER_JH7110_INT_CLR_AVA_MASK	BIT(1)
++
++enum STARFIVE_TIMER_CH {
++	STARFIVE_TIMER_CH_0 = 0,
++	STARFIVE_TIMER_CH_1,
++	STARFIVE_TIMER_CH_2,
++	STARFIVE_TIMER_CH_3,
++	STARFIVE_TIMER_CH_4,
++	STARFIVE_TIMER_CH_5,
++	STARFIVE_TIMER_CH_6,
++	STARFIVE_TIMER_CH_7,
++	STARFIVE_TIMER_CH_MAX
++};
++
++enum STARFIVE_TIMER_INTMASK {
++	STARFIVE_TIMER_INTMASK_DIS = 0,
++	STARFIVE_TIMER_INTMASK_ENA = 1
++};
++
++enum STARFIVE_TIMER_MOD {
++	STARFIVE_TIMER_MOD_CONTIN = 0,
++	STARFIVE_TIMER_MOD_SINGLE = 1
++};
++
++enum STARFIVE_TIMER_CTL_EN {
++	STARFIVE_TIMER_DIS = 0,
++	STARFIVE_TIMER_ENA = 1
++};
++
++struct starfive_timer_chan_base {
++	/* Resgister */
++	unsigned int ctrl;
++	unsigned int load;
++	unsigned int enable;
++	unsigned int reload;
++	unsigned int value;
++	unsigned int intclr;
++	unsigned int intmask;
++
++	unsigned int channel_num;	/* timer channel numbers */
++	unsigned int channel_base[];
++};
++
++struct starfive_clkevt {
++	struct clock_event_device evt;
++	struct clk *clk;
++	char name[20];
++	int irq;
++	u32 periodic;
++	u32 rate;
++	u32 reload_val;
++	void __iomem *base;
++	void __iomem *ctrl;
++	void __iomem *load;
++	void __iomem *enable;
++	void __iomem *reload;
++	void __iomem *value;
++	void __iomem *intclr;
++	void __iomem *intmask;
++};
++
++struct starfive_timer_priv {
++	struct device *dev;
++	void __iomem *base;
++	struct starfive_clkevt clkevt[];
++};
++
++#endif /* __STARFIVE_TIMER_H__ */

+ 36 - 0
target/linux/starfive/patches-6.1/0061-dt-bindings-net-motorcomm-Add-pad-driver-strength-cf.patch

@@ -0,0 +1,36 @@
+From 16214121afaadb8ae9aaf73351e874405eb47c15 Mon Sep 17 00:00:00 2001
+From: Samin Guo <[email protected]>
+Date: Tue, 25 Apr 2023 18:51:15 +0800
+Subject: [PATCH 061/122] dt-bindings: net: motorcomm: Add pad driver strength
+ cfg
+
+The motorcomm phy (YT8531) supports the ability to adjust the drive
+strength of the rx_clk/rx_data, the value range of pad driver
+strength is 0 to 7.
+
+Signed-off-by: Samin Guo <[email protected]>
+---
+ .../devicetree/bindings/net/motorcomm,yt8xxx.yaml    | 12 ++++++++++++
+ 1 file changed, 12 insertions(+)
+
+--- a/Documentation/devicetree/bindings/net/motorcomm,yt8xxx.yaml
++++ b/Documentation/devicetree/bindings/net/motorcomm,yt8xxx.yaml
+@@ -62,6 +62,18 @@ properties:
+       for a timer.
+     type: boolean
+ 
++  motorcomm,rx-clk-driver-strength:
++    description: drive strength of rx_clk pad.
++    $ref: /schemas/types.yaml#/definitions/uint32
++    enum: [ 0, 1, 2, 3, 4, 5, 6, 7 ]
++    default: 3
++
++  motorcomm,rx-data-driver-strength:
++    description: drive strength of rx_data/rx_ctl rgmii pad.
++    $ref: /schemas/types.yaml#/definitions/uint32
++    enum: [ 0, 1, 2, 3, 4, 5, 6, 7 ]
++    default: 3
++
+   motorcomm,tx-clk-adj-enabled:
+     description: |
+       This configuration is mainly to adapt to VF2 with JH7110 SoC.

+ 71 - 0
target/linux/starfive/patches-6.1/0062-dt-bindings-PWM-Add-StarFive-PWM-module.patch

@@ -0,0 +1,71 @@
+From 99f0bf43994dada29e33fd8718fd25484634da3a Mon Sep 17 00:00:00 2001
+From: William Qiu <[email protected]>
+Date: Tue, 21 Mar 2023 13:52:27 +0800
+Subject: [PATCH 062/122] dt-bindings: PWM: Add StarFive PWM module
+
+Add documentation to describe StarFive Pulse Width Modulation
+controller driver.
+
+Signed-off-by: William Qiu <[email protected]>
+Reviewed-by: Krzysztof Kozlowski <[email protected]>
+---
+ .../bindings/pwm/starfive,jh7110-pwm.yaml     | 53 +++++++++++++++++++
+ 1 file changed, 53 insertions(+)
+ create mode 100644 Documentation/devicetree/bindings/pwm/starfive,jh7110-pwm.yaml
+
+--- /dev/null
++++ b/Documentation/devicetree/bindings/pwm/starfive,jh7110-pwm.yaml
+@@ -0,0 +1,53 @@
++# SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause
++%YAML 1.2
++---
++$id: http://devicetree.org/schemas/pwm/starfive,jh7110-pwm.yaml#
++$schema: http://devicetree.org/meta-schemas/core.yaml#
++
++title: StarFive PWM controller
++
++maintainers:
++  - William Qiu <[email protected]>
++
++description:
++  StarFive SoCs contain PWM and when operating in PWM mode, the PTC core generates
++  binary signal with user-programmable low and high periods. Clock source for the
++  PWM can be either system clockor external clock. Each PWM timer block provides 8
++  PWM channels.
++
++allOf:
++  - $ref: pwm.yaml#
++
++properties:
++  compatible:
++    const: starfive,jh7110-pwm
++
++  reg:
++    maxItems: 1
++
++  clocks:
++    maxItems: 1
++
++  resets:
++    maxItems: 1
++
++  "#pwm-cells":
++    const: 3
++
++required:
++  - compatible
++  - reg
++  - clocks
++  - resets
++
++additionalProperties: false
++
++examples:
++  - |
++    pwm@120d0000 {
++        compatible = "starfive,jh7110-pwm";
++        reg = <0x120d0000 0x10000>;
++        clocks = <&syscrg 121>;
++        resets = <&syscrg 108>;
++        #pwm-cells = <3>;
++    };

+ 294 - 0
target/linux/starfive/patches-6.1/0063-pwm-starfive-Add-PWM-driver-support.patch

@@ -0,0 +1,294 @@
+From fddea961e7ce1f26dd549e3d92ede624246690c0 Mon Sep 17 00:00:00 2001
+From: William Qiu <[email protected]>
+Date: Tue, 21 Mar 2023 13:52:28 +0800
+Subject: [PATCH 063/122] pwm: starfive: Add PWM driver support
+
+Add Pulse Width Modulation driver support for StarFive
+JH7110 soc.
+
+Signed-off-by: Hal Feng <[email protected]>
+Signed-off-by: William Qiu <[email protected]>
+---
+ drivers/pwm/Kconfig            |  10 ++
+ drivers/pwm/Makefile           |   1 +
+ drivers/pwm/pwm-starfive-ptc.c | 245 +++++++++++++++++++++++++++++++++
+ 3 files changed, 256 insertions(+)
+ create mode 100644 drivers/pwm/pwm-starfive-ptc.c
+
+--- a/drivers/pwm/Kconfig
++++ b/drivers/pwm/Kconfig
+@@ -536,6 +536,16 @@ config PWM_SPRD
+ 	  To compile this driver as a module, choose M here: the module
+ 	  will be called pwm-sprd.
+ 
++config PWM_STARFIVE_PTC
++	tristate "StarFive PWM PTC support"
++	depends on OF
++	depends on COMMON_CLK
++	help
++	  Generic PWM framework driver for StarFive SoCs.
++
++	  To compile this driver as a module, choose M here: the module
++	  will be called pwm-starfive-ptc.
++
+ config PWM_STI
+ 	tristate "STiH4xx PWM support"
+ 	depends on ARCH_STI || COMPILE_TEST
+--- a/drivers/pwm/Makefile
++++ b/drivers/pwm/Makefile
+@@ -49,6 +49,7 @@ obj-$(CONFIG_PWM_SIFIVE)	+= pwm-sifive.o
+ obj-$(CONFIG_PWM_SL28CPLD)	+= pwm-sl28cpld.o
+ obj-$(CONFIG_PWM_SPEAR)		+= pwm-spear.o
+ obj-$(CONFIG_PWM_SPRD)		+= pwm-sprd.o
++obj-$(CONFIG_PWM_STARFIVE_PTC)	+= pwm-starfive-ptc.o
+ obj-$(CONFIG_PWM_STI)		+= pwm-sti.o
+ obj-$(CONFIG_PWM_STM32)		+= pwm-stm32.o
+ obj-$(CONFIG_PWM_STM32_LP)	+= pwm-stm32-lp.o
+--- /dev/null
++++ b/drivers/pwm/pwm-starfive-ptc.c
+@@ -0,0 +1,245 @@
++// SPDX-License-Identifier: GPL-2.0
++/*
++ * PWM driver for the StarFive JH7110 SoC
++ *
++ * Copyright (C) 2018 StarFive Technology Co., Ltd.
++ */
++
++#include <dt-bindings/pwm/pwm.h>
++#include <linux/module.h>
++#include <linux/platform_device.h>
++#include <linux/pwm.h>
++#include <linux/slab.h>
++#include <linux/clk.h>
++#include <linux/reset.h>
++#include <linux/io.h>
++
++/* how many parameters can be transferred to ptc */
++#define OF_PWM_N_CELLS			3
++
++/* PTC Register offsets */
++#define REG_RPTC_CNTR			0x0
++#define REG_RPTC_HRC			0x4
++#define REG_RPTC_LRC			0x8
++#define REG_RPTC_CTRL			0xC
++
++/* Bit for PWM clock */
++#define BIT_PWM_CLOCK_EN		31
++
++/* Bit for clock gen soft reset */
++#define BIT_CLK_GEN_SOFT_RESET		13
++
++#define NS_PER_SECOND			1000000000
++
++/*
++ * Access PTC register (cntr hrc lrc and ctrl),
++ * need to replace PWM_BASE_ADDR
++ */
++#define REG_PTC_BASE_ADDR_SUB(base, N)	\
++((base) + (((N) > 3) ? (((N) % 4) * 0x10 + (1 << 15)) : ((N) * 0x10)))
++#define REG_PTC_RPTC_CNTR(base, N)	(REG_PTC_BASE_ADDR_SUB(base, N))
++#define REG_PTC_RPTC_HRC(base, N)	(REG_PTC_BASE_ADDR_SUB(base, N) + 0x4)
++#define REG_PTC_RPTC_LRC(base, N)	(REG_PTC_BASE_ADDR_SUB(base, N) + 0x8)
++#define REG_PTC_RPTC_CTRL(base, N)	(REG_PTC_BASE_ADDR_SUB(base, N) + 0xC)
++
++/* PTC_RPTC_CTRL */
++#define PTC_EN      BIT(0)
++#define PTC_ECLK    BIT(1)
++#define PTC_NEC     BIT(2)
++#define PTC_OE      BIT(3)
++#define PTC_SIGNLE  BIT(4)
++#define PTC_INTE    BIT(5)
++#define PTC_INT     BIT(6)
++#define PTC_CNTRRST BIT(7)
++#define PTC_CAPTE   BIT(8)
++
++struct starfive_pwm_ptc_device {
++	struct pwm_chip		chip;
++	struct clk		*clk;
++	struct reset_control	*rst;
++	void __iomem		*regs;
++	int			irq;
++	unsigned int		approx_freq;/*pwm apb clock frequency*/
++};
++
++static inline
++struct starfive_pwm_ptc_device *chip_to_starfive_ptc(struct pwm_chip *c)
++{
++	return container_of(c, struct starfive_pwm_ptc_device, chip);
++}
++
++static int starfive_pwm_ptc_get_state(struct pwm_chip *chip,
++				       struct pwm_device *dev,
++				       struct pwm_state *state)
++{
++	struct starfive_pwm_ptc_device *pwm = chip_to_starfive_ptc(chip);
++	u32 data_lrc, data_hrc;
++	u32 pwm_clk_ns = 0;
++
++	data_lrc = ioread32(REG_PTC_RPTC_LRC(pwm->regs, dev->hwpwm));
++	data_hrc = ioread32(REG_PTC_RPTC_HRC(pwm->regs, dev->hwpwm));
++
++	pwm_clk_ns = NS_PER_SECOND / pwm->approx_freq;
++
++	state->period = data_lrc * pwm_clk_ns;
++	state->duty_cycle = data_hrc * pwm_clk_ns;
++	state->polarity = PWM_POLARITY_NORMAL;
++	state->enabled = 1;
++
++	return 0;
++}
++
++static int starfive_pwm_ptc_apply(struct pwm_chip *chip,
++				  struct pwm_device *dev,
++				  struct pwm_state *state)
++{
++	struct starfive_pwm_ptc_device *pwm = chip_to_starfive_ptc(chip);
++	u32 data_hrc = 0;
++	u32 data_lrc = 0;
++	u32 period_data = 0;
++	u32 duty_data = 0;
++	s64 multi = pwm->approx_freq;
++	s64 div = NS_PER_SECOND;
++	void __iomem *reg_addr;
++
++	if (state->duty_cycle > state->period)
++		state->duty_cycle = state->period;
++
++	while (multi % 10 == 0 && div % 10 == 0 && multi > 0 && div > 0) {
++		multi /= 10;
++		div /= 10;
++	}
++
++	period_data = (u32)(state->period * multi / div);
++	if (abs(period_data * div / multi - state->period)
++	    > abs((period_data + 1) * div / multi - state->period) ||
++	    (state->period > 0 && period_data == 0))
++		period_data += 1;
++
++	if (state->enabled) {
++		duty_data = (u32)(state->duty_cycle * multi / div);
++		if (abs(duty_data * div / multi - state->duty_cycle)
++			> abs((duty_data + 1) * div / multi - state->duty_cycle) ||
++			(state->duty_cycle > 0 && duty_data == 0))
++			duty_data += 1;
++	} else {
++		duty_data = 0;
++	}
++
++	if (state->polarity == PWM_POLARITY_NORMAL)
++		data_hrc = period_data - duty_data;
++	else
++		data_hrc = duty_data;
++
++	data_lrc = period_data;
++
++	reg_addr = REG_PTC_RPTC_HRC(pwm->regs, dev->hwpwm);
++	iowrite32(data_hrc, reg_addr);
++
++	reg_addr = REG_PTC_RPTC_LRC(pwm->regs, dev->hwpwm);
++	iowrite32(data_lrc, reg_addr);
++
++	reg_addr = REG_PTC_RPTC_CNTR(pwm->regs, dev->hwpwm);
++	iowrite32(0, reg_addr);
++
++	reg_addr = REG_PTC_RPTC_CTRL(pwm->regs, dev->hwpwm);
++	iowrite32(PTC_EN | PTC_OE, reg_addr);
++
++	return 0;
++}
++
++static const struct pwm_ops starfive_pwm_ptc_ops = {
++	.get_state	= starfive_pwm_ptc_get_state,
++	.apply		= (void *)starfive_pwm_ptc_apply,
++	.owner		= THIS_MODULE,
++};
++
++static int starfive_pwm_ptc_probe(struct platform_device *pdev)
++{
++	struct device *dev = &pdev->dev;
++	struct starfive_pwm_ptc_device *pwm;
++	struct pwm_chip *chip;
++	int ret;
++
++	pwm = devm_kzalloc(dev, sizeof(*pwm), GFP_KERNEL);
++	if (!pwm)
++		return -ENOMEM;
++
++	chip = &pwm->chip;
++	chip->dev = dev;
++	chip->ops = &starfive_pwm_ptc_ops;
++	chip->npwm = 8;
++
++	chip->of_pwm_n_cells = OF_PWM_N_CELLS;
++	chip->base = -1;
++
++	pwm->regs = devm_platform_ioremap_resource(pdev, 0);
++	if (IS_ERR(pwm->regs))
++		return dev_err_probe(dev, PTR_ERR(pwm->regs),
++					"Unable to map IO resources\n");
++
++	pwm->clk = devm_clk_get(dev, NULL);
++	if (IS_ERR(pwm->clk))
++		return dev_err_probe(dev, PTR_ERR(pwm->clk),
++					"Unable to get pwm clock\n");
++
++	pwm->rst = devm_reset_control_get_exclusive(dev, NULL);
++	if (IS_ERR(pwm->rst))
++		return dev_err_probe(dev, PTR_ERR(pwm->rst),
++					"Unable to get pwm reset\n");
++
++	ret = clk_prepare_enable(pwm->clk);
++	if (ret) {
++		dev_err(dev,
++			"Failed to enable pwm clock, %d\n", ret);
++		return ret;
++	}
++
++	reset_control_deassert(pwm->rst);
++
++	pwm->approx_freq = (unsigned int)clk_get_rate(pwm->clk);
++	if (!pwm->approx_freq)
++		dev_err(dev, "get pwm apb clock rate failed.\n");
++
++	ret = devm_pwmchip_add(dev, chip);
++	if (ret < 0) {
++		dev_err(dev, "cannot register PTC: %d\n", ret);
++		clk_disable_unprepare(pwm->clk);
++		return ret;
++	}
++
++	platform_set_drvdata(pdev, pwm);
++
++	return 0;
++}
++
++static int starfive_pwm_ptc_remove(struct platform_device *dev)
++{
++	struct starfive_pwm_ptc_device *pwm = platform_get_drvdata(dev);
++	struct pwm_chip *chip = &pwm->chip;
++
++	pwmchip_remove(chip);
++
++	return 0;
++}
++
++static const struct of_device_id starfive_pwm_ptc_of_match[] = {
++	{ .compatible = "starfive,jh7110-pwm" },
++	{},
++};
++MODULE_DEVICE_TABLE(of, starfive_pwm_ptc_of_match);
++
++static struct platform_driver starfive_pwm_ptc_driver = {
++	.probe = starfive_pwm_ptc_probe,
++	.remove = starfive_pwm_ptc_remove,
++	.driver = {
++		.name = "pwm-starfive-ptc",
++		.of_match_table = starfive_pwm_ptc_of_match,
++	},
++};
++module_platform_driver(starfive_pwm_ptc_driver);
++
++MODULE_AUTHOR("Jenny Zhang <[email protected]>");
++MODULE_AUTHOR("Hal Feng <[email protected]>");
++MODULE_DESCRIPTION("StarFive PWM PTC driver");
++MODULE_LICENSE("GPL");

+ 90 - 0
target/linux/starfive/patches-6.1/0064-dt-bindings-crypto-Add-StarFive-crypto-module.patch

@@ -0,0 +1,90 @@
+From 207dde3ed123613cd84c8f706a24d75cefece67c Mon Sep 17 00:00:00 2001
+From: Jia Jie Ho <[email protected]>
+Date: Mon, 15 May 2023 20:53:52 +0800
+Subject: [PATCH 064/122] dt-bindings: crypto: Add StarFive crypto module
+
+Add documentation to describe StarFive cryptographic engine.
+
+Co-developed-by: Huan Feng <[email protected]>
+Signed-off-by: Huan Feng <[email protected]>
+Signed-off-by: Jia Jie Ho <[email protected]>
+Reviewed-by: Rob Herring <[email protected]>
+Signed-off-by: Herbert Xu <[email protected]>
+---
+ .../crypto/starfive,jh7110-crypto.yaml        | 70 +++++++++++++++++++
+ 1 file changed, 70 insertions(+)
+ create mode 100644 Documentation/devicetree/bindings/crypto/starfive,jh7110-crypto.yaml
+
+--- /dev/null
++++ b/Documentation/devicetree/bindings/crypto/starfive,jh7110-crypto.yaml
+@@ -0,0 +1,70 @@
++# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
++%YAML 1.2
++---
++$id: http://devicetree.org/schemas/crypto/starfive,jh7110-crypto.yaml#
++$schema: http://devicetree.org/meta-schemas/core.yaml#
++
++title: StarFive Cryptographic Module
++
++maintainers:
++  - Jia Jie Ho <[email protected]>
++  - William Qiu <[email protected]>
++
++properties:
++  compatible:
++    const: starfive,jh7110-crypto
++
++  reg:
++    maxItems: 1
++
++  clocks:
++    items:
++      - description: Hardware reference clock
++      - description: AHB reference clock
++
++  clock-names:
++    items:
++      - const: hclk
++      - const: ahb
++
++  interrupts:
++    maxItems: 1
++
++  resets:
++    maxItems: 1
++
++  dmas:
++    items:
++      - description: TX DMA channel
++      - description: RX DMA channel
++
++  dma-names:
++    items:
++      - const: tx
++      - const: rx
++
++required:
++  - compatible
++  - reg
++  - clocks
++  - clock-names
++  - resets
++  - dmas
++  - dma-names
++
++additionalProperties: false
++
++examples:
++  - |
++    crypto: crypto@16000000 {
++        compatible = "starfive,jh7110-crypto";
++        reg = <0x16000000 0x4000>;
++        clocks = <&clk 15>, <&clk 16>;
++        clock-names = "hclk", "ahb";
++        interrupts = <28>;
++        resets = <&reset 3>;
++        dmas = <&dma 1 2>,
++               <&dma 0 2>;
++        dma-names = "tx", "rx";
++    };
++...

+ 337 - 0
target/linux/starfive/patches-6.1/0065-crypto-starfive-Add-crypto-engine-support.patch

@@ -0,0 +1,337 @@
+From 8b1069fcc1dbb524556d851f3dedf0629a71f17b Mon Sep 17 00:00:00 2001
+From: Jia Jie Ho <[email protected]>
+Date: Mon, 15 May 2023 20:53:53 +0800
+Subject: [PATCH 065/122] crypto: starfive - Add crypto engine support
+
+Adding device probe and DMA init for StarFive cryptographic module.
+
+Co-developed-by: Huan Feng <[email protected]>
+Signed-off-by: Huan Feng <[email protected]>
+Signed-off-by: Jia Jie Ho <[email protected]>
+Signed-off-by: Herbert Xu <[email protected]>
+---
+ drivers/crypto/Kconfig                |   1 +
+ drivers/crypto/Makefile               |   1 +
+ drivers/crypto/starfive/Kconfig       |  17 +++
+ drivers/crypto/starfive/Makefile      |   4 +
+ drivers/crypto/starfive/jh7110-cryp.c | 201 ++++++++++++++++++++++++++
+ drivers/crypto/starfive/jh7110-cryp.h |  63 ++++++++
+ 6 files changed, 287 insertions(+)
+ create mode 100644 drivers/crypto/starfive/Kconfig
+ create mode 100644 drivers/crypto/starfive/Makefile
+ create mode 100644 drivers/crypto/starfive/jh7110-cryp.c
+ create mode 100644 drivers/crypto/starfive/jh7110-cryp.h
+
+--- a/drivers/crypto/Kconfig
++++ b/drivers/crypto/Kconfig
+@@ -823,5 +823,6 @@ config CRYPTO_DEV_SA2UL
+ 
+ source "drivers/crypto/keembay/Kconfig"
+ source "drivers/crypto/aspeed/Kconfig"
++source "drivers/crypto/starfive/Kconfig"
+ 
+ endif # CRYPTO_HW
+--- a/drivers/crypto/Makefile
++++ b/drivers/crypto/Makefile
+@@ -53,3 +53,4 @@ obj-y += xilinx/
+ obj-y += hisilicon/
+ obj-$(CONFIG_CRYPTO_DEV_AMLOGIC_GXL) += amlogic/
+ obj-y += keembay/
++obj-y += starfive/
+--- /dev/null
++++ b/drivers/crypto/starfive/Kconfig
+@@ -0,0 +1,17 @@
++#
++# StarFive crypto drivers configuration
++#
++
++config CRYPTO_DEV_JH7110
++	tristate "StarFive JH7110 cryptographic engine driver"
++	depends on SOC_STARFIVE || COMPILE_TEST
++	select CRYPTO_ENGINE
++	select ARM_AMBA
++	select DMADEVICES
++	select AMBA_PL08X
++	help
++	  Support for StarFive JH7110 crypto hardware acceleration engine.
++	  This module provides acceleration for public key algo,
++	  skciphers, AEAD and hash functions.
++
++	  If you choose 'M' here, this module will be called jh7110-crypto.
+--- /dev/null
++++ b/drivers/crypto/starfive/Makefile
+@@ -0,0 +1,4 @@
++# SPDX-License-Identifier: GPL-2.0
++
++obj-$(CONFIG_CRYPTO_DEV_JH7110) += jh7110-crypto.o
++jh7110-crypto-objs := jh7110-cryp.o
+--- /dev/null
++++ b/drivers/crypto/starfive/jh7110-cryp.c
+@@ -0,0 +1,201 @@
++// SPDX-License-Identifier: GPL-2.0
++/*
++ * Cryptographic API.
++ *
++ * Support for StarFive hardware cryptographic engine.
++ * Copyright (c) 2022 StarFive Technology
++ *
++ */
++
++#include <linux/clk.h>
++#include <linux/delay.h>
++#include <linux/interrupt.h>
++#include <linux/iopoll.h>
++#include <linux/module.h>
++#include <linux/of_device.h>
++#include <linux/platform_device.h>
++#include <linux/pm_runtime.h>
++#include <linux/reset.h>
++
++#include "jh7110-cryp.h"
++
++#define DRIVER_NAME             "jh7110-crypto"
++
++struct starfive_dev_list {
++	struct list_head        dev_list;
++	spinlock_t              lock; /* protect dev_list */
++};
++
++static struct starfive_dev_list dev_list = {
++	.dev_list = LIST_HEAD_INIT(dev_list.dev_list),
++	.lock     = __SPIN_LOCK_UNLOCKED(dev_list.lock),
++};
++
++struct starfive_cryp_dev *starfive_cryp_find_dev(struct starfive_cryp_ctx *ctx)
++{
++	struct starfive_cryp_dev *cryp = NULL, *tmp;
++
++	spin_lock_bh(&dev_list.lock);
++	if (!ctx->cryp) {
++		list_for_each_entry(tmp, &dev_list.dev_list, list) {
++			cryp = tmp;
++			break;
++		}
++		ctx->cryp = cryp;
++	} else {
++		cryp = ctx->cryp;
++	}
++
++	spin_unlock_bh(&dev_list.lock);
++
++	return cryp;
++}
++
++static int starfive_dma_init(struct starfive_cryp_dev *cryp)
++{
++	dma_cap_mask_t mask;
++
++	dma_cap_zero(mask);
++	dma_cap_set(DMA_SLAVE, mask);
++
++	cryp->tx = dma_request_chan(cryp->dev, "tx");
++	if (IS_ERR(cryp->tx))
++		return dev_err_probe(cryp->dev, PTR_ERR(cryp->tx),
++				     "Error requesting tx dma channel.\n");
++
++	cryp->rx = dma_request_chan(cryp->dev, "rx");
++	if (IS_ERR(cryp->rx)) {
++		dma_release_channel(cryp->tx);
++		return dev_err_probe(cryp->dev, PTR_ERR(cryp->rx),
++				     "Error requesting rx dma channel.\n");
++	}
++
++	return 0;
++}
++
++static void starfive_dma_cleanup(struct starfive_cryp_dev *cryp)
++{
++	dma_release_channel(cryp->tx);
++	dma_release_channel(cryp->rx);
++}
++
++static int starfive_cryp_probe(struct platform_device *pdev)
++{
++	struct starfive_cryp_dev *cryp;
++	struct resource *res;
++	int ret;
++
++	cryp = devm_kzalloc(&pdev->dev, sizeof(*cryp), GFP_KERNEL);
++	if (!cryp)
++		return -ENOMEM;
++
++	platform_set_drvdata(pdev, cryp);
++	cryp->dev = &pdev->dev;
++
++	cryp->base = devm_platform_get_and_ioremap_resource(pdev, 0, &res);
++	if (IS_ERR(cryp->base))
++		return dev_err_probe(&pdev->dev, PTR_ERR(cryp->base),
++				     "Error remapping memory for platform device\n");
++
++	cryp->phys_base = res->start;
++	cryp->dma_maxburst = 32;
++
++	cryp->hclk = devm_clk_get(&pdev->dev, "hclk");
++	if (IS_ERR(cryp->hclk))
++		return dev_err_probe(&pdev->dev, PTR_ERR(cryp->hclk),
++				     "Error getting hardware reference clock\n");
++
++	cryp->ahb = devm_clk_get(&pdev->dev, "ahb");
++	if (IS_ERR(cryp->ahb))
++		return dev_err_probe(&pdev->dev, PTR_ERR(cryp->ahb),
++				     "Error getting ahb reference clock\n");
++
++	cryp->rst = devm_reset_control_get_shared(cryp->dev, NULL);
++	if (IS_ERR(cryp->rst))
++		return dev_err_probe(&pdev->dev, PTR_ERR(cryp->rst),
++				     "Error getting hardware reset line\n");
++
++	clk_prepare_enable(cryp->hclk);
++	clk_prepare_enable(cryp->ahb);
++	reset_control_deassert(cryp->rst);
++
++	spin_lock(&dev_list.lock);
++	list_add(&cryp->list, &dev_list.dev_list);
++	spin_unlock(&dev_list.lock);
++
++	ret = starfive_dma_init(cryp);
++	if (ret) {
++		if (ret == -EPROBE_DEFER)
++			goto err_probe_defer;
++		else
++			goto err_dma_init;
++	}
++
++	/* Initialize crypto engine */
++	cryp->engine = crypto_engine_alloc_init(&pdev->dev, 1);
++	if (!cryp->engine) {
++		ret = -ENOMEM;
++		goto err_engine;
++	}
++
++	ret = crypto_engine_start(cryp->engine);
++	if (ret)
++		goto err_engine_start;
++
++	return 0;
++
++err_engine_start:
++	crypto_engine_exit(cryp->engine);
++err_engine:
++	starfive_dma_cleanup(cryp);
++err_dma_init:
++	spin_lock(&dev_list.lock);
++	list_del(&cryp->list);
++	spin_unlock(&dev_list.lock);
++
++	clk_disable_unprepare(cryp->hclk);
++	clk_disable_unprepare(cryp->ahb);
++	reset_control_assert(cryp->rst);
++err_probe_defer:
++	return ret;
++}
++
++static int starfive_cryp_remove(struct platform_device *pdev)
++{
++	struct starfive_cryp_dev *cryp = platform_get_drvdata(pdev);
++
++	crypto_engine_stop(cryp->engine);
++	crypto_engine_exit(cryp->engine);
++
++	starfive_dma_cleanup(cryp);
++
++	spin_lock(&dev_list.lock);
++	list_del(&cryp->list);
++	spin_unlock(&dev_list.lock);
++
++	clk_disable_unprepare(cryp->hclk);
++	clk_disable_unprepare(cryp->ahb);
++	reset_control_assert(cryp->rst);
++
++	return 0;
++}
++
++static const struct of_device_id starfive_dt_ids[] __maybe_unused = {
++	{ .compatible = "starfive,jh7110-crypto", .data = NULL},
++	{},
++};
++MODULE_DEVICE_TABLE(of, starfive_dt_ids);
++
++static struct platform_driver starfive_cryp_driver = {
++	.probe  = starfive_cryp_probe,
++	.remove = starfive_cryp_remove,
++	.driver = {
++		.name           = DRIVER_NAME,
++		.of_match_table = starfive_dt_ids,
++	},
++};
++
++module_platform_driver(starfive_cryp_driver);
++
++MODULE_LICENSE("GPL");
++MODULE_DESCRIPTION("StarFive JH7110 Cryptographic Module");
+--- /dev/null
++++ b/drivers/crypto/starfive/jh7110-cryp.h
+@@ -0,0 +1,63 @@
++/* SPDX-License-Identifier: GPL-2.0 */
++#ifndef __STARFIVE_STR_H__
++#define __STARFIVE_STR_H__
++
++#include <linux/delay.h>
++#include <linux/dma-mapping.h>
++#include <linux/dmaengine.h>
++
++#include <crypto/engine.h>
++
++#define STARFIVE_ALG_CR_OFFSET			0x0
++#define STARFIVE_ALG_FIFO_OFFSET		0x4
++#define STARFIVE_IE_MASK_OFFSET			0x8
++#define STARFIVE_IE_FLAG_OFFSET			0xc
++#define STARFIVE_DMA_IN_LEN_OFFSET		0x10
++#define STARFIVE_DMA_OUT_LEN_OFFSET		0x14
++
++#define STARFIVE_MSG_BUFFER_SIZE		SZ_16K
++
++union starfive_alg_cr {
++	u32 v;
++	struct {
++		u32 start			:1;
++		u32 aes_dma_en			:1;
++		u32 rsvd_0			:1;
++		u32 hash_dma_en			:1;
++		u32 alg_done			:1;
++		u32 rsvd_1			:3;
++		u32 clear			:1;
++		u32 rsvd_2			:23;
++	};
++};
++
++struct starfive_cryp_ctx {
++	struct crypto_engine_ctx		enginectx;
++	struct starfive_cryp_dev		*cryp;
++};
++
++struct starfive_cryp_dev {
++	struct list_head			list;
++	struct device				*dev;
++
++	struct clk				*hclk;
++	struct clk				*ahb;
++	struct reset_control			*rst;
++
++	void __iomem				*base;
++	phys_addr_t				phys_base;
++
++	u32					dma_maxburst;
++	struct dma_chan				*tx;
++	struct dma_chan				*rx;
++	struct dma_slave_config			cfg_in;
++	struct dma_slave_config			cfg_out;
++
++	struct crypto_engine			*engine;
++
++	union starfive_alg_cr			alg_cr;
++};
++
++struct starfive_cryp_dev *starfive_cryp_find_dev(struct starfive_cryp_ctx *ctx);
++
++#endif

+ 29 - 0
target/linux/starfive/patches-6.1/0066-crypto-starfive-Fix-driver-dependencies.patch

@@ -0,0 +1,29 @@
+From 0d3ee821ed469a787e8007de2d87e98a2370e087 Mon Sep 17 00:00:00 2001
+From: Jia Jie Ho <[email protected]>
+Date: Fri, 19 May 2023 21:42:33 +0800
+Subject: [PATCH 066/122] crypto: starfive - Fix driver dependencies
+
+Kconfig updated to depend on DMADEVICES instead of selecting it.
+
+Reported-by: kernel test robot <[email protected]>
+Link: https://lore.kernel.org/oe-kbuild-all/[email protected]/
+Signed-off-by: Jia Jie Ho <[email protected]>
+Signed-off-by: Herbert Xu <[email protected]>
+---
+ drivers/crypto/starfive/Kconfig | 3 +--
+ 1 file changed, 1 insertion(+), 2 deletions(-)
+
+--- a/drivers/crypto/starfive/Kconfig
++++ b/drivers/crypto/starfive/Kconfig
+@@ -4,10 +4,9 @@
+ 
+ config CRYPTO_DEV_JH7110
+ 	tristate "StarFive JH7110 cryptographic engine driver"
+-	depends on SOC_STARFIVE || COMPILE_TEST
++	depends on (SOC_STARFIVE || COMPILE_TEST) && DMADEVICES
+ 	select CRYPTO_ENGINE
+ 	select ARM_AMBA
+-	select DMADEVICES
+ 	select AMBA_PL08X
+ 	help
+ 	  Support for StarFive JH7110 crypto hardware acceleration engine.

+ 23 - 0
target/linux/starfive/patches-6.1/0067-riscv-Kconfig-Add-select-ARM_AMBA-to-SOC_STARFIVE.patch

@@ -0,0 +1,23 @@
+From e8d070e2eb856856055566d3515072a8346446f3 Mon Sep 17 00:00:00 2001
+From: "shanlong.li" <[email protected]>
+Date: Wed, 31 May 2023 01:37:41 -0700
+Subject: [PATCH 067/122] riscv: Kconfig: Add select ARM_AMBA to SOC_STARFIVE
+
+Selects ARM_AMBA platform support for StarFive SoCs required by spi and
+crypto dma engine.
+
+Signed-off-by: shanlong.li <[email protected]>
+---
+ arch/riscv/Kconfig.socs | 1 +
+ 1 file changed, 1 insertion(+)
+
+--- a/arch/riscv/Kconfig.socs
++++ b/arch/riscv/Kconfig.socs
+@@ -4,6 +4,7 @@ config SOC_MICROCHIP_POLARFIRE
+ 	bool "Microchip PolarFire SoCs"
+ 	select MCHP_CLK_MPFS
+ 	select SIFIVE_PLIC
++	select ARM_AMBA
+ 	help
+ 	  This enables support for Microchip PolarFire SoC platforms.
+ 

+ 117 - 0
target/linux/starfive/patches-6.1/0068-ASoC-dt-bindings-Add-TDM-controller-bindings-for-Sta.patch

@@ -0,0 +1,117 @@
+From 3b90e0fb53c31c50e64d2039e30ec25c1d8a8d5c Mon Sep 17 00:00:00 2001
+From: Walker Chen <[email protected]>
+Date: Fri, 26 May 2023 22:54:00 +0800
+Subject: [PATCH 068/122] ASoC: dt-bindings: Add TDM controller bindings for
+ StarFive JH7110
+
+Add bindings for TDM driver which supports multi-channel audio playback
+and capture on JH7110 platform.
+
+Reviewed-by: Krzysztof Kozlowski <[email protected]>
+Signed-off-by: Walker Chen <[email protected]>
+---
+ .../bindings/sound/starfive,jh7110-tdm.yaml   | 98 +++++++++++++++++++
+ 1 file changed, 98 insertions(+)
+ create mode 100644 Documentation/devicetree/bindings/sound/starfive,jh7110-tdm.yaml
+
+--- /dev/null
++++ b/Documentation/devicetree/bindings/sound/starfive,jh7110-tdm.yaml
+@@ -0,0 +1,98 @@
++# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
++%YAML 1.2
++---
++$id: http://devicetree.org/schemas/sound/starfive,jh7110-tdm.yaml#
++$schema: http://devicetree.org/meta-schemas/core.yaml#
++
++title: StarFive JH7110 TDM Controller
++
++description: |
++  The TDM Controller is a Time Division Multiplexed audio interface
++  integrated in StarFive JH7110 SoC, allowing up to 8 channels of
++  audio over a serial interface. The TDM controller can operate both
++  in master and slave mode.
++
++maintainers:
++  - Walker Chen <[email protected]>
++
++allOf:
++  - $ref: dai-common.yaml#
++
++properties:
++  compatible:
++    enum:
++      - starfive,jh7110-tdm
++
++  reg:
++    maxItems: 1
++
++  clocks:
++    items:
++      - description: TDM AHB Clock
++      - description: TDM APB Clock
++      - description: TDM Internal Clock
++      - description: TDM Clock
++      - description: Inner MCLK
++      - description: TDM External Clock
++
++  clock-names:
++    items:
++      - const: tdm_ahb
++      - const: tdm_apb
++      - const: tdm_internal
++      - const: tdm
++      - const: mclk_inner
++      - const: tdm_ext
++
++  resets:
++    items:
++      - description: tdm ahb reset line
++      - description: tdm apb reset line
++      - description: tdm core reset line
++
++  dmas:
++    items:
++      - description: RX DMA Channel
++      - description: TX DMA Channel
++
++  dma-names:
++    items:
++      - const: rx
++      - const: tx
++
++  "#sound-dai-cells":
++    const: 0
++
++required:
++  - compatible
++  - reg
++  - clocks
++  - clock-names
++  - resets
++  - dmas
++  - dma-names
++  - "#sound-dai-cells"
++
++additionalProperties: false
++
++examples:
++  - |
++    tdm@10090000 {
++        compatible = "starfive,jh7110-tdm";
++        reg = <0x10090000 0x1000>;
++        clocks = <&syscrg 184>,
++                 <&syscrg 185>,
++                 <&syscrg 186>,
++                 <&syscrg 187>,
++                 <&syscrg 17>,
++                 <&tdm_ext>;
++        clock-names = "tdm_ahb", "tdm_apb",
++                      "tdm_internal", "tdm",
++                      "mclk_inner", "tdm_ext";
++        resets = <&syscrg 105>,
++                 <&syscrg 107>,
++                 <&syscrg 106>;
++        dmas = <&dma 20>, <&dma 21>;
++        dma-names = "rx","tx";
++        #sound-dai-cells = <0>;
++    };

+ 744 - 0
target/linux/starfive/patches-6.1/0069-ASoC-starfive-Add-JH7110-TDM-driver.patch

@@ -0,0 +1,744 @@
+From 9d90936b0f69d891001a11d3f6c0c3728d8b6d85 Mon Sep 17 00:00:00 2001
+From: Walker Chen <[email protected]>
+Date: Fri, 26 May 2023 22:54:01 +0800
+Subject: [PATCH 069/122] ASoC: starfive: Add JH7110 TDM driver
+
+Add tdm driver support for the StarFive JH7110 SoC.
+
+Signed-off-by: Walker Chen <[email protected]>
+---
+ sound/soc/Kconfig               |   1 +
+ sound/soc/Makefile              |   1 +
+ sound/soc/starfive/Kconfig      |  15 +
+ sound/soc/starfive/Makefile     |   2 +
+ sound/soc/starfive/jh7110_tdm.c | 679 ++++++++++++++++++++++++++++++++
+ 5 files changed, 698 insertions(+)
+ create mode 100644 sound/soc/starfive/Kconfig
+ create mode 100644 sound/soc/starfive/Makefile
+ create mode 100644 sound/soc/starfive/jh7110_tdm.c
+
+--- a/sound/soc/Kconfig
++++ b/sound/soc/Kconfig
+@@ -91,6 +91,7 @@ source "sound/soc/sh/Kconfig"
+ source "sound/soc/sof/Kconfig"
+ source "sound/soc/spear/Kconfig"
+ source "sound/soc/sprd/Kconfig"
++source "sound/soc/starfive/Kconfig"
+ source "sound/soc/sti/Kconfig"
+ source "sound/soc/stm/Kconfig"
+ source "sound/soc/sunxi/Kconfig"
+--- a/sound/soc/Makefile
++++ b/sound/soc/Makefile
+@@ -59,6 +59,7 @@ obj-$(CONFIG_SND_SOC)	+= sh/
+ obj-$(CONFIG_SND_SOC)	+= sof/
+ obj-$(CONFIG_SND_SOC)	+= spear/
+ obj-$(CONFIG_SND_SOC)	+= sprd/
++obj-$(CONFIG_SND_SOC)	+= starfive/
+ obj-$(CONFIG_SND_SOC)	+= sti/
+ obj-$(CONFIG_SND_SOC)	+= stm/
+ obj-$(CONFIG_SND_SOC)	+= sunxi/
+--- /dev/null
++++ b/sound/soc/starfive/Kconfig
+@@ -0,0 +1,15 @@
++# SPDX-License-Identifier: GPL-2.0-only
++config SND_SOC_STARFIVE
++	tristate "Audio support for StarFive SoC"
++	depends on COMPILE_TEST || ARCH_STARFIVE
++	help
++	  Say Y or M if you want to add support for codecs attached to
++	  the Starfive SoCs' Audio interfaces. You will also need to
++	  select the audio interfaces to support below.
++
++config SND_SOC_JH7110_TDM
++	tristate "JH7110 TDM device driver"
++	depends on HAVE_CLK && SND_SOC_STARFIVE
++	select SND_SOC_GENERIC_DMAENGINE_PCM
++	help
++	  Say Y or M if you want to add support for StarFive TDM driver.
+--- /dev/null
++++ b/sound/soc/starfive/Makefile
+@@ -0,0 +1,2 @@
++# StarFive Platform Support
++obj-$(CONFIG_SND_SOC_JH7110_TDM) += jh7110_tdm.o
+--- /dev/null
++++ b/sound/soc/starfive/jh7110_tdm.c
+@@ -0,0 +1,679 @@
++// SPDX-License-Identifier: GPL-2.0
++/*
++ * jh7110_tdm.c -- StarFive JH7110 TDM driver
++ *
++ * Copyright (C) 2023 StarFive Technology Co., Ltd.
++ *
++ * Author: Walker Chen <[email protected]>
++ */
++
++#include <linux/clk.h>
++#include <linux/device.h>
++#include <linux/dmaengine.h>
++#include <linux/module.h>
++#include <linux/of_irq.h>
++#include <linux/of_platform.h>
++#include <linux/pm_runtime.h>
++#include <linux/regmap.h>
++#include <linux/reset.h>
++#include <linux/types.h>
++#include <sound/dmaengine_pcm.h>
++#include <sound/initval.h>
++#include <sound/pcm.h>
++#include <sound/pcm_params.h>
++#include <sound/soc.h>
++#include <sound/soc-dai.h>
++
++#define TDM_PCMGBCR			0x00
++	#define PCMGBCR_MASK		0x1e
++	#define PCMGBCR_ENABLE		BIT(0)
++	#define PCMGBCR_TRITXEN		BIT(4)
++	#define CLKPOL_BIT		5
++	#define TRITXEN_BIT		4
++	#define ELM_BIT			3
++	#define SYNCM_BIT		2
++	#define MS_BIT			1
++#define TDM_PCMTXCR			0x04
++	#define PCMTXCR_TXEN		BIT(0)
++	#define IFL_BIT			11
++	#define WL_BIT			8
++	#define SSCALE_BIT		4
++	#define SL_BIT			2
++	#define LRJ_BIT			1
++#define TDM_PCMRXCR			0x08
++	#define PCMRXCR_RXEN		BIT(0)
++	#define PCMRXCR_RXSL_MASK	0xc
++	#define PCMRXCR_RXSL_16BIT	0x4
++	#define PCMRXCR_RXSL_32BIT	0x8
++	#define PCMRXCR_SCALE_MASK	0xf0
++	#define PCMRXCR_SCALE_1CH	0x10
++#define TDM_PCMDIV			0x0c
++
++#define JH7110_TDM_FIFO			0x170c0000
++#define JH7110_TDM_FIFO_DEPTH		32
++
++enum TDM_MASTER_SLAVE_MODE {
++	TDM_AS_MASTER = 0,
++	TDM_AS_SLAVE,
++};
++
++enum TDM_CLKPOL {
++	/* tx raising and rx falling */
++	TDM_TX_RASING_RX_FALLING = 0,
++	/* tx falling and rx raising */
++	TDM_TX_FALLING_RX_RASING,
++};
++
++enum TDM_ELM {
++	/* only work while SYNCM=0 */
++	TDM_ELM_LATE = 0,
++	TDM_ELM_EARLY,
++};
++
++enum TDM_SYNCM {
++	/* short frame sync */
++	TDM_SYNCM_SHORT = 0,
++	/* long frame sync */
++	TDM_SYNCM_LONG,
++};
++
++enum TDM_IFL {
++	/* FIFO to send or received : half-1/2, Quarter-1/4 */
++	TDM_FIFO_HALF = 0,
++	TDM_FIFO_QUARTER,
++};
++
++enum TDM_WL {
++	/* send or received word length */
++	TDM_8BIT_WORD_LEN = 0,
++	TDM_16BIT_WORD_LEN,
++	TDM_20BIT_WORD_LEN,
++	TDM_24BIT_WORD_LEN,
++	TDM_32BIT_WORD_LEN,
++};
++
++enum TDM_SL {
++	/* send or received slot length */
++	TDM_8BIT_SLOT_LEN = 0,
++	TDM_16BIT_SLOT_LEN,
++	TDM_32BIT_SLOT_LEN,
++};
++
++enum TDM_LRJ {
++	/* left-justify or right-justify */
++	TDM_RIGHT_JUSTIFY = 0,
++	TDM_LEFT_JUSTIFT,
++};
++
++struct tdm_chan_cfg {
++	enum TDM_IFL ifl;
++	enum TDM_WL  wl;
++	unsigned char sscale;
++	enum TDM_SL  sl;
++	enum TDM_LRJ lrj;
++	unsigned char enable;
++};
++
++struct jh7110_tdm_dev {
++	void __iomem *tdm_base;
++	struct device *dev;
++	struct clk_bulk_data clks[6];
++	struct reset_control *resets;
++
++	enum TDM_CLKPOL clkpolity;
++	enum TDM_ELM	elm;
++	enum TDM_SYNCM	syncm;
++	enum TDM_MASTER_SLAVE_MODE ms_mode;
++
++	struct tdm_chan_cfg tx;
++	struct tdm_chan_cfg rx;
++
++	u16 syncdiv;
++	u32 samplerate;
++	u32 pcmclk;
++
++	/* data related to DMA transfers b/w tdm and DMAC */
++	struct snd_dmaengine_dai_dma_data play_dma_data;
++	struct snd_dmaengine_dai_dma_data capture_dma_data;
++	u32 saved_pcmgbcr;
++	u32 saved_pcmtxcr;
++	u32 saved_pcmrxcr;
++	u32 saved_pcmdiv;
++};
++
++static inline u32 jh7110_tdm_readl(struct jh7110_tdm_dev *tdm, u16 reg)
++{
++	return readl_relaxed(tdm->tdm_base + reg);
++}
++
++static inline void jh7110_tdm_writel(struct jh7110_tdm_dev *tdm, u16 reg, u32 val)
++{
++	writel_relaxed(val, tdm->tdm_base + reg);
++}
++
++static void jh7110_tdm_save_context(struct jh7110_tdm_dev *tdm,
++				    struct snd_pcm_substream *substream)
++{
++	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
++		tdm->saved_pcmtxcr = jh7110_tdm_readl(tdm, TDM_PCMTXCR);
++	else
++		tdm->saved_pcmrxcr = jh7110_tdm_readl(tdm, TDM_PCMRXCR);
++}
++
++static void jh7110_tdm_start(struct jh7110_tdm_dev *tdm,
++			     struct snd_pcm_substream *substream)
++{
++	u32 data;
++
++	data = jh7110_tdm_readl(tdm, TDM_PCMGBCR);
++	jh7110_tdm_writel(tdm, TDM_PCMGBCR, data | PCMGBCR_ENABLE);
++
++	/* restore context */
++	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
++		jh7110_tdm_writel(tdm, TDM_PCMTXCR, tdm->saved_pcmtxcr | PCMTXCR_TXEN);
++	else
++		jh7110_tdm_writel(tdm, TDM_PCMRXCR, tdm->saved_pcmrxcr | PCMRXCR_RXEN);
++}
++
++static void jh7110_tdm_stop(struct jh7110_tdm_dev *tdm,
++			    struct snd_pcm_substream *substream)
++{
++	unsigned int val;
++
++	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
++		val = jh7110_tdm_readl(tdm, TDM_PCMTXCR);
++		val &= ~PCMTXCR_TXEN;
++		jh7110_tdm_writel(tdm, TDM_PCMTXCR, val);
++	} else {
++		val = jh7110_tdm_readl(tdm, TDM_PCMRXCR);
++		val &= ~PCMRXCR_RXEN;
++		jh7110_tdm_writel(tdm, TDM_PCMRXCR, val);
++	}
++}
++
++static int jh7110_tdm_syncdiv(struct jh7110_tdm_dev *tdm)
++{
++	u32 sl, sscale, syncdiv;
++
++	if (tdm->rx.sl >= tdm->tx.sl)
++		sl = tdm->rx.sl;
++	else
++		sl = tdm->tx.sl;
++
++	if (tdm->rx.sscale >= tdm->tx.sscale)
++		sscale = tdm->rx.sscale;
++	else
++		sscale = tdm->tx.sscale;
++
++	syncdiv = tdm->pcmclk / tdm->samplerate - 1;
++
++	if ((syncdiv + 1) < (sl * sscale)) {
++		dev_err(tdm->dev, "Failed to set syncdiv!\n");
++		return -EINVAL;
++	}
++
++	if (tdm->syncm == TDM_SYNCM_LONG &&
++	    (tdm->rx.sscale <= 1 || tdm->tx.sscale <= 1) &&
++	    ((syncdiv + 1) <= sl)) {
++		dev_err(tdm->dev, "Wrong syncdiv! It must be (syncdiv+1) > max[tx.sl, rx.sl]\n");
++		return -EINVAL;
++	}
++
++	jh7110_tdm_writel(tdm, TDM_PCMDIV, syncdiv);
++	return 0;
++}
++
++static int jh7110_tdm_config(struct jh7110_tdm_dev *tdm,
++			     struct snd_pcm_substream *substream)
++{
++	u32 datarx, datatx;
++	int ret;
++
++	ret = jh7110_tdm_syncdiv(tdm);
++	if (ret)
++		return ret;
++
++	datarx = (tdm->rx.ifl << IFL_BIT) |
++		  (tdm->rx.wl << WL_BIT) |
++		  (tdm->rx.sscale << SSCALE_BIT) |
++		  (tdm->rx.sl << SL_BIT) |
++		  (tdm->rx.lrj << LRJ_BIT);
++
++	datatx = (tdm->tx.ifl << IFL_BIT) |
++		  (tdm->tx.wl << WL_BIT) |
++		  (tdm->tx.sscale << SSCALE_BIT) |
++		  (tdm->tx.sl << SL_BIT) |
++		  (tdm->tx.lrj << LRJ_BIT);
++
++	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
++		jh7110_tdm_writel(tdm, TDM_PCMTXCR, datatx);
++	else
++		jh7110_tdm_writel(tdm, TDM_PCMRXCR, datarx);
++
++	return 0;
++}
++
++static void jh7110_tdm_clk_disable(struct jh7110_tdm_dev *tdm)
++{
++	clk_bulk_disable_unprepare(ARRAY_SIZE(tdm->clks), tdm->clks);
++}
++
++static int jh7110_tdm_clk_enable(struct jh7110_tdm_dev *tdm)
++{
++	int ret;
++
++	ret = clk_bulk_prepare_enable(ARRAY_SIZE(tdm->clks), tdm->clks);
++	if (ret) {
++		dev_err(tdm->dev, "Failed to enable tdm clocks\n");
++		return ret;
++	}
++
++	ret = reset_control_deassert(tdm->resets);
++	if (ret) {
++		dev_err(tdm->dev, "Failed to deassert tdm resets\n");
++		goto dis_tdm_clk;
++	}
++
++	/* select tdm_ext clock as the clock source for tdm */
++	ret = clk_set_parent(tdm->clks[5].clk, tdm->clks[4].clk);
++	if (ret) {
++		dev_err(tdm->dev, "Can't set extern clock source for clk_tdm\n");
++		goto dis_tdm_clk;
++	}
++
++	return 0;
++
++dis_tdm_clk:
++	clk_bulk_disable_unprepare(ARRAY_SIZE(tdm->clks), tdm->clks);
++
++	return ret;
++}
++
++static int jh7110_tdm_runtime_suspend(struct device *dev)
++{
++	struct jh7110_tdm_dev *tdm = dev_get_drvdata(dev);
++
++	jh7110_tdm_clk_disable(tdm);
++	return 0;
++}
++
++static int jh7110_tdm_runtime_resume(struct device *dev)
++{
++	struct jh7110_tdm_dev *tdm = dev_get_drvdata(dev);
++
++	return jh7110_tdm_clk_enable(tdm);
++}
++
++static int jh7110_tdm_system_suspend(struct device *dev)
++{
++	struct jh7110_tdm_dev *tdm = dev_get_drvdata(dev);
++
++	/* save context */
++	tdm->saved_pcmgbcr = jh7110_tdm_readl(tdm, TDM_PCMGBCR);
++	tdm->saved_pcmdiv = jh7110_tdm_readl(tdm, TDM_PCMDIV);
++
++	return pm_runtime_force_suspend(dev);
++}
++
++static int jh7110_tdm_system_resume(struct device *dev)
++{
++	struct jh7110_tdm_dev *tdm = dev_get_drvdata(dev);
++
++	/* restore context */
++	jh7110_tdm_writel(tdm, TDM_PCMGBCR, tdm->saved_pcmgbcr);
++	jh7110_tdm_writel(tdm, TDM_PCMDIV, tdm->saved_pcmdiv);
++
++	return pm_runtime_force_resume(dev);
++}
++
++static const struct snd_soc_component_driver jh7110_tdm_component = {
++	.name = "jh7110-tdm",
++};
++
++static int jh7110_tdm_startup(struct snd_pcm_substream *substream,
++			      struct snd_soc_dai *cpu_dai)
++{
++	struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream);
++	struct snd_soc_dai_link *dai_link = rtd->dai_link;
++
++	dai_link->stop_dma_first = 1;
++
++	return 0;
++}
++
++static int jh7110_tdm_hw_params(struct snd_pcm_substream *substream,
++				struct snd_pcm_hw_params *params,
++				struct snd_soc_dai *dai)
++{
++	struct jh7110_tdm_dev *tdm = snd_soc_dai_get_drvdata(dai);
++	int chan_wl, chan_sl, chan_nr;
++	unsigned int data_width;
++	unsigned int dma_bus_width;
++	struct snd_dmaengine_dai_dma_data *dma_data = NULL;
++	int ret;
++
++	data_width = params_width(params);
++
++	tdm->samplerate = params_rate(params);
++	tdm->pcmclk = params_channels(params) * tdm->samplerate * data_width;
++
++	switch (params_format(params)) {
++	case SNDRV_PCM_FORMAT_S16_LE:
++		chan_wl = TDM_16BIT_WORD_LEN;
++		chan_sl = TDM_16BIT_SLOT_LEN;
++		dma_bus_width = DMA_SLAVE_BUSWIDTH_2_BYTES;
++		break;
++
++	case SNDRV_PCM_FORMAT_S32_LE:
++		chan_wl = TDM_32BIT_WORD_LEN;
++		chan_sl = TDM_32BIT_SLOT_LEN;
++		dma_bus_width = DMA_SLAVE_BUSWIDTH_4_BYTES;
++		break;
++
++	default:
++		dev_err(tdm->dev, "tdm: unsupported PCM fmt");
++		return -EINVAL;
++	}
++
++	chan_nr = params_channels(params);
++	switch (chan_nr) {
++	case 1:
++	case 2:
++	case 4:
++	case 6:
++	case 8:
++		break;
++	default:
++		dev_err(tdm->dev, "channel not supported\n");
++		return -EINVAL;
++	}
++
++	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
++		tdm->tx.wl = chan_wl;
++		tdm->tx.sl = chan_sl;
++		tdm->tx.sscale = chan_nr;
++		tdm->play_dma_data.addr_width = dma_bus_width;
++		dma_data = &tdm->play_dma_data;
++	} else {
++		tdm->rx.wl = chan_wl;
++		tdm->rx.sl = chan_sl;
++		tdm->rx.sscale = chan_nr;
++		tdm->capture_dma_data.addr_width = dma_bus_width;
++		dma_data = &tdm->capture_dma_data;
++	}
++
++	snd_soc_dai_set_dma_data(dai, substream, dma_data);
++
++	ret = jh7110_tdm_config(tdm, substream);
++	if (ret)
++		return ret;
++
++	jh7110_tdm_save_context(tdm, substream);
++	return 0;
++}
++
++static int jh7110_tdm_trigger(struct snd_pcm_substream *substream,
++			      int cmd, struct snd_soc_dai *dai)
++{
++	struct jh7110_tdm_dev *tdm = snd_soc_dai_get_drvdata(dai);
++	int ret = 0;
++
++	switch (cmd) {
++	case SNDRV_PCM_TRIGGER_START:
++	case SNDRV_PCM_TRIGGER_RESUME:
++	case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
++		jh7110_tdm_start(tdm, substream);
++		break;
++
++	case SNDRV_PCM_TRIGGER_STOP:
++	case SNDRV_PCM_TRIGGER_SUSPEND:
++	case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
++		jh7110_tdm_stop(tdm, substream);
++		break;
++	default:
++		ret = -EINVAL;
++		break;
++	}
++
++	return ret;
++}
++
++static int jh7110_tdm_set_dai_fmt(struct snd_soc_dai *cpu_dai,
++				  unsigned int fmt)
++{
++	struct jh7110_tdm_dev *tdm = snd_soc_dai_get_drvdata(cpu_dai);
++	unsigned int gbcr;
++
++	/* set master/slave audio interface */
++	switch (fmt & SND_SOC_DAIFMT_CLOCK_PROVIDER_MASK) {
++	case SND_SOC_DAIFMT_BP_FP:
++		/* cpu is master */
++		tdm->ms_mode = TDM_AS_MASTER;
++		break;
++	case SND_SOC_DAIFMT_BC_FC:
++		/* codec is master */
++		tdm->ms_mode = TDM_AS_SLAVE;
++		break;
++	case SND_SOC_DAIFMT_BC_FP:
++	case SND_SOC_DAIFMT_BP_FC:
++		return -EINVAL;
++	default:
++		dev_dbg(tdm->dev, "dwc : Invalid clock provider format\n");
++		return -EINVAL;
++	}
++
++	gbcr = (tdm->clkpolity << CLKPOL_BIT) |
++		(tdm->elm << ELM_BIT) |
++		(tdm->syncm << SYNCM_BIT) |
++		(tdm->ms_mode << MS_BIT);
++	jh7110_tdm_writel(tdm, TDM_PCMGBCR, gbcr);
++
++	return 0;
++}
++
++static const struct snd_soc_dai_ops jh7110_tdm_dai_ops = {
++	.startup	= jh7110_tdm_startup,
++	.hw_params	= jh7110_tdm_hw_params,
++	.trigger	= jh7110_tdm_trigger,
++	.set_fmt	= jh7110_tdm_set_dai_fmt,
++};
++
++static int jh7110_tdm_dai_probe(struct snd_soc_dai *dai)
++{
++	struct jh7110_tdm_dev *tdm = snd_soc_dai_get_drvdata(dai);
++
++	snd_soc_dai_init_dma_data(dai, &tdm->play_dma_data, &tdm->capture_dma_data);
++	snd_soc_dai_set_drvdata(dai, tdm);
++	return 0;
++}
++
++#define JH7110_TDM_RATES	SNDRV_PCM_RATE_8000_48000
++
++#define JH7110_TDM_FORMATS	(SNDRV_PCM_FMTBIT_S16_LE | \
++				 SNDRV_PCM_FMTBIT_S32_LE)
++
++static struct snd_soc_dai_driver jh7110_tdm_dai = {
++	.name = "sf_tdm",
++	.id = 0,
++	.playback = {
++		.stream_name    = "Playback",
++		.channels_min   = 1,
++		.channels_max   = 8,
++		.rates          = JH7110_TDM_RATES,
++		.formats        = JH7110_TDM_FORMATS,
++	},
++	.capture = {
++		.stream_name    = "Capture",
++		.channels_min   = 1,
++		.channels_max   = 8,
++		.rates          = JH7110_TDM_RATES,
++		.formats        = JH7110_TDM_FORMATS,
++	},
++	.ops = &jh7110_tdm_dai_ops,
++	.probe = jh7110_tdm_dai_probe,
++	.symmetric_rate = 1,
++};
++
++static const struct snd_pcm_hardware jh7110_pcm_hardware = {
++	.info			= (SNDRV_PCM_INFO_MMAP		|
++				   SNDRV_PCM_INFO_MMAP_VALID	|
++				   SNDRV_PCM_INFO_PAUSE		|
++				   SNDRV_PCM_INFO_RESUME	|
++				   SNDRV_PCM_INFO_INTERLEAVED	|
++				   SNDRV_PCM_INFO_BLOCK_TRANSFER),
++	.buffer_bytes_max	= 192512,
++	.period_bytes_min	= 4096,
++	.period_bytes_max	= 32768,
++	.periods_min		= 1,
++	.periods_max		= 48,
++	.fifo_size		= 16,
++};
++
++static const struct snd_dmaengine_pcm_config jh7110_dmaengine_pcm_config = {
++	.pcm_hardware = &jh7110_pcm_hardware,
++	.prepare_slave_config = snd_dmaengine_pcm_prepare_slave_config,
++	.prealloc_buffer_size = 192512,
++};
++
++static void jh7110_tdm_init_params(struct jh7110_tdm_dev *tdm)
++{
++	tdm->clkpolity = TDM_TX_RASING_RX_FALLING;
++	tdm->elm = TDM_ELM_LATE;
++	tdm->syncm = TDM_SYNCM_SHORT;
++
++	tdm->rx.ifl = TDM_FIFO_HALF;
++	tdm->tx.ifl = TDM_FIFO_HALF;
++	tdm->rx.wl = TDM_16BIT_WORD_LEN;
++	tdm->tx.wl = TDM_16BIT_WORD_LEN;
++	tdm->rx.sscale = 2;
++	tdm->tx.sscale = 2;
++	tdm->rx.lrj = TDM_LEFT_JUSTIFT;
++	tdm->tx.lrj = TDM_LEFT_JUSTIFT;
++
++	tdm->play_dma_data.addr = JH7110_TDM_FIFO;
++	tdm->play_dma_data.addr_width = DMA_SLAVE_BUSWIDTH_2_BYTES;
++	tdm->play_dma_data.fifo_size = JH7110_TDM_FIFO_DEPTH / 2;
++	tdm->play_dma_data.maxburst = 16;
++
++	tdm->capture_dma_data.addr = JH7110_TDM_FIFO;
++	tdm->capture_dma_data.addr_width = DMA_SLAVE_BUSWIDTH_2_BYTES;
++	tdm->capture_dma_data.fifo_size = JH7110_TDM_FIFO_DEPTH / 2;
++	tdm->capture_dma_data.maxburst = 8;
++}
++
++static int jh7110_tdm_clk_reset_get(struct platform_device *pdev,
++				    struct jh7110_tdm_dev *tdm)
++{
++	int ret;
++
++	tdm->clks[0].id = "mclk_inner";
++	tdm->clks[1].id = "tdm_ahb";
++	tdm->clks[2].id = "tdm_apb";
++	tdm->clks[3].id = "tdm_internal";
++	tdm->clks[4].id = "tdm_ext";
++	tdm->clks[5].id = "tdm";
++
++	ret = devm_clk_bulk_get(&pdev->dev, ARRAY_SIZE(tdm->clks), tdm->clks);
++	if (ret) {
++		dev_err(&pdev->dev, "Failed to get tdm clocks\n");
++		return ret;
++	}
++
++	tdm->resets = devm_reset_control_array_get_exclusive(&pdev->dev);
++	if (IS_ERR_OR_NULL(tdm->resets)) {
++		ret = PTR_ERR(tdm->resets);
++		dev_err(&pdev->dev, "Failed to get tdm resets");
++		return ret;
++	}
++
++	return 0;
++}
++
++static int jh7110_tdm_probe(struct platform_device *pdev)
++{
++	struct jh7110_tdm_dev *tdm;
++	int ret;
++
++	tdm = devm_kzalloc(&pdev->dev, sizeof(*tdm), GFP_KERNEL);
++	if (!tdm)
++		return -ENOMEM;
++
++	tdm->tdm_base = devm_platform_ioremap_resource(pdev, 0);
++	if (IS_ERR(tdm->tdm_base))
++		return PTR_ERR(tdm->tdm_base);
++
++	tdm->dev = &pdev->dev;
++
++	ret = jh7110_tdm_clk_reset_get(pdev, tdm);
++	if (ret) {
++		dev_err(&pdev->dev, "Failed to enable audio-tdm clock\n");
++		return ret;
++	}
++
++	jh7110_tdm_init_params(tdm);
++
++	dev_set_drvdata(&pdev->dev, tdm);
++	ret = devm_snd_soc_register_component(&pdev->dev, &jh7110_tdm_component,
++					      &jh7110_tdm_dai, 1);
++	if (ret) {
++		dev_err(&pdev->dev, "Failed to register dai\n");
++		return ret;
++	}
++
++	ret = devm_snd_dmaengine_pcm_register(&pdev->dev,
++					      &jh7110_dmaengine_pcm_config,
++					      SND_DMAENGINE_PCM_FLAG_COMPAT);
++	if (ret) {
++		dev_err(&pdev->dev, "Could not register pcm: %d\n", ret);
++		return ret;
++	}
++
++	pm_runtime_enable(&pdev->dev);
++	if (!pm_runtime_enabled(&pdev->dev)) {
++		ret = jh7110_tdm_runtime_resume(&pdev->dev);
++		if (ret)
++			goto err_pm_disable;
++	}
++
++	return 0;
++
++err_pm_disable:
++	pm_runtime_disable(&pdev->dev);
++
++	return ret;
++}
++
++static int jh7110_tdm_dev_remove(struct platform_device *pdev)
++{
++	pm_runtime_disable(&pdev->dev);
++	return 0;
++}
++
++static const struct of_device_id jh7110_tdm_of_match[] = {
++	{ .compatible = "starfive,jh7110-tdm", },
++	{}
++};
++
++MODULE_DEVICE_TABLE(of, jh7110_tdm_of_match);
++
++static const struct dev_pm_ops jh7110_tdm_pm_ops = {
++	RUNTIME_PM_OPS(jh7110_tdm_runtime_suspend,
++		       jh7110_tdm_runtime_resume, NULL)
++	SYSTEM_SLEEP_PM_OPS(jh7110_tdm_system_suspend,
++			    jh7110_tdm_system_resume)
++};
++
++static struct platform_driver jh7110_tdm_driver = {
++	.driver = {
++		.name = "jh7110-tdm",
++		.of_match_table = jh7110_tdm_of_match,
++		.pm = pm_ptr(&jh7110_tdm_pm_ops),
++	},
++	.probe = jh7110_tdm_probe,
++	.remove = jh7110_tdm_dev_remove,
++};
++module_platform_driver(jh7110_tdm_driver);
++
++MODULE_DESCRIPTION("StarFive JH7110 TDM ASoC Driver");
++MODULE_AUTHOR("Walker Chen <[email protected]>");
++MODULE_LICENSE("GPL");

+ 32 - 0
target/linux/starfive/patches-6.1/0070-dt-bindings-power-Add-power-domain-header-for-JH7110.patch

@@ -0,0 +1,32 @@
+From 598083825494088f927fa42c5a7bb2872029a7bc Mon Sep 17 00:00:00 2001
+From: Changhuang Liang <[email protected]>
+Date: Thu, 18 May 2023 23:01:59 -0700
+Subject: [PATCH 070/122] dt-bindings: power: Add power-domain header for
+ JH7110
+
+Add power-domain header for JH7110 SoC, it can use to operate dphy
+power.
+
+Signed-off-by: Changhuang Liang <[email protected]>
+---
+ include/dt-bindings/power/starfive,jh7110-pmu.h | 5 ++++-
+ 1 file changed, 4 insertions(+), 1 deletion(-)
+
+--- a/include/dt-bindings/power/starfive,jh7110-pmu.h
++++ b/include/dt-bindings/power/starfive,jh7110-pmu.h
+@@ -1,6 +1,6 @@
+ /* SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) */
+ /*
+- * Copyright (C) 2022 StarFive Technology Co., Ltd.
++ * Copyright (C) 2022-2023 StarFive Technology Co., Ltd.
+  * Author: Walker Chen <[email protected]>
+  */
+ #ifndef __DT_BINDINGS_POWER_JH7110_POWER_H__
+@@ -14,4 +14,7 @@
+ #define JH7110_PD_ISP		5
+ #define JH7110_PD_VENC		6
+ 
++#define JH7110_PD_DPHY_TX	0
++#define JH7110_PD_DPHY_RX	1
++
+ #endif

+ 28 - 0
target/linux/starfive/patches-6.1/0071-soc-starfive-Replace-SOC_STARFIVE-with-ARCH_STARFIVE.patch

@@ -0,0 +1,28 @@
+From d83b51f60997365b80637f71924ab3dec91d5b77 Mon Sep 17 00:00:00 2001
+From: Changhuang Liang <[email protected]>
+Date: Thu, 18 May 2023 23:02:00 -0700
+Subject: [PATCH 071/122] soc: starfive: Replace SOC_STARFIVE with
+ ARCH_STARFIVE
+
+Using ARCH_FOO symbol is preferred than SOC_FOO.
+
+Reviewed-by: Conor Dooley <[email protected]>
+Reviewed-by: Walker Chen <[email protected]>
+Signed-off-by: Changhuang Liang <[email protected]>
+---
+ drivers/soc/starfive/Kconfig | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+--- a/drivers/soc/starfive/Kconfig
++++ b/drivers/soc/starfive/Kconfig
+@@ -3,8 +3,8 @@
+ config JH71XX_PMU
+ 	bool "Support PMU for StarFive JH71XX Soc"
+ 	depends on PM
+-	depends on SOC_STARFIVE || COMPILE_TEST
+-	default SOC_STARFIVE
++	depends on ARCH_STARFIVE || COMPILE_TEST
++	default ARCH_STARFIVE
+ 	select PM_GENERIC_DOMAINS
+ 	help
+ 	  Say 'y' here to enable support power domain support.

+ 175 - 0
target/linux/starfive/patches-6.1/0072-soc-starfive-Extract-JH7110-pmu-private-operations.patch

@@ -0,0 +1,175 @@
+From 52e2ade50f3ec212468e284b1236aaa521ba5913 Mon Sep 17 00:00:00 2001
+From: Changhuang Liang <[email protected]>
+Date: Thu, 18 May 2023 23:02:01 -0700
+Subject: [PATCH 072/122] soc: starfive: Extract JH7110 pmu private operations
+
+Move JH7110 private operation into private data of compatible. Convenient
+to add AON PMU which would not have interrupts property.
+
+Signed-off-by: Changhuang Liang <[email protected]>
+Reviewed-by: Walker Chen <[email protected]>
+---
+ drivers/soc/starfive/jh71xx_pmu.c | 89 +++++++++++++++++++++----------
+ 1 file changed, 62 insertions(+), 27 deletions(-)
+
+--- a/drivers/soc/starfive/jh71xx_pmu.c
++++ b/drivers/soc/starfive/jh71xx_pmu.c
+@@ -51,9 +51,17 @@ struct jh71xx_domain_info {
+ 	u8 bit;
+ };
+ 
++struct jh71xx_pmu;
++struct jh71xx_pmu_dev;
++
+ struct jh71xx_pmu_match_data {
+ 	const struct jh71xx_domain_info *domain_info;
+ 	int num_domains;
++	unsigned int pmu_status;
++	int (*pmu_parse_irq)(struct platform_device *pdev,
++			     struct jh71xx_pmu *pmu);
++	int (*pmu_set_state)(struct jh71xx_pmu_dev *pmd,
++			     u32 mask, bool on);
+ };
+ 
+ struct jh71xx_pmu {
+@@ -79,12 +87,12 @@ static int jh71xx_pmu_get_state(struct j
+ 	if (!mask)
+ 		return -EINVAL;
+ 
+-	*is_on = readl(pmu->base + JH71XX_PMU_CURR_POWER_MODE) & mask;
++	*is_on = readl(pmu->base + pmu->match_data->pmu_status) & mask;
+ 
+ 	return 0;
+ }
+ 
+-static int jh71xx_pmu_set_state(struct jh71xx_pmu_dev *pmd, u32 mask, bool on)
++static int jh7110_pmu_set_state(struct jh71xx_pmu_dev *pmd, u32 mask, bool on)
+ {
+ 	struct jh71xx_pmu *pmu = pmd->pmu;
+ 	unsigned long flags;
+@@ -92,22 +100,8 @@ static int jh71xx_pmu_set_state(struct j
+ 	u32 mode;
+ 	u32 encourage_lo;
+ 	u32 encourage_hi;
+-	bool is_on;
+ 	int ret;
+ 
+-	ret = jh71xx_pmu_get_state(pmd, mask, &is_on);
+-	if (ret) {
+-		dev_dbg(pmu->dev, "unable to get current state for %s\n",
+-			pmd->genpd.name);
+-		return ret;
+-	}
+-
+-	if (is_on == on) {
+-		dev_dbg(pmu->dev, "pm domain [%s] is already %sable status.\n",
+-			pmd->genpd.name, on ? "en" : "dis");
+-		return 0;
+-	}
+-
+ 	spin_lock_irqsave(&pmu->lock, flags);
+ 
+ 	/*
+@@ -166,6 +160,29 @@ static int jh71xx_pmu_set_state(struct j
+ 	return 0;
+ }
+ 
++static int jh71xx_pmu_set_state(struct jh71xx_pmu_dev *pmd, u32 mask, bool on)
++{
++	struct jh71xx_pmu *pmu = pmd->pmu;
++	const struct jh71xx_pmu_match_data *match_data = pmu->match_data;
++	bool is_on;
++	int ret;
++
++	ret = jh71xx_pmu_get_state(pmd, mask, &is_on);
++	if (ret) {
++		dev_dbg(pmu->dev, "unable to get current state for %s\n",
++			pmd->genpd.name);
++		return ret;
++	}
++
++	if (is_on == on) {
++		dev_dbg(pmu->dev, "pm domain [%s] is already %sable status.\n",
++			pmd->genpd.name, on ? "en" : "dis");
++		return 0;
++	}
++
++	return match_data->pmu_set_state(pmd, mask, on);
++}
++
+ static int jh71xx_pmu_on(struct generic_pm_domain *genpd)
+ {
+ 	struct jh71xx_pmu_dev *pmd = container_of(genpd,
+@@ -226,6 +243,25 @@ static irqreturn_t jh71xx_pmu_interrupt(
+ 	return IRQ_HANDLED;
+ }
+ 
++static int jh7110_pmu_parse_irq(struct platform_device *pdev, struct jh71xx_pmu *pmu)
++{
++	struct device *dev = &pdev->dev;
++	int ret;
++
++	pmu->irq = platform_get_irq(pdev, 0);
++	if (pmu->irq < 0)
++		return pmu->irq;
++
++	ret = devm_request_irq(dev, pmu->irq, jh71xx_pmu_interrupt,
++			       0, pdev->name, pmu);
++	if (ret)
++		dev_err(dev, "failed to request irq\n");
++
++	jh71xx_pmu_int_enable(pmu, JH71XX_PMU_INT_ALL_MASK & ~JH71XX_PMU_INT_PCH_FAIL, true);
++
++	return 0;
++}
++
+ static int jh71xx_pmu_init_domain(struct jh71xx_pmu *pmu, int index)
+ {
+ 	struct jh71xx_pmu_dev *pmd;
+@@ -275,19 +311,18 @@ static int jh71xx_pmu_probe(struct platf
+ 	if (IS_ERR(pmu->base))
+ 		return PTR_ERR(pmu->base);
+ 
+-	pmu->irq = platform_get_irq(pdev, 0);
+-	if (pmu->irq < 0)
+-		return pmu->irq;
+-
+-	ret = devm_request_irq(dev, pmu->irq, jh71xx_pmu_interrupt,
+-			       0, pdev->name, pmu);
+-	if (ret)
+-		dev_err(dev, "failed to request irq\n");
++	spin_lock_init(&pmu->lock);
+ 
+ 	match_data = of_device_get_match_data(dev);
+ 	if (!match_data)
+ 		return -EINVAL;
+ 
++	ret = match_data->pmu_parse_irq(pdev, pmu);
++	if (ret) {
++		dev_err(dev, "failed to parse irq\n");
++		return ret;
++	}
++
+ 	pmu->genpd = devm_kcalloc(dev, match_data->num_domains,
+ 				  sizeof(struct generic_pm_domain *),
+ 				  GFP_KERNEL);
+@@ -307,9 +342,6 @@ static int jh71xx_pmu_probe(struct platf
+ 		}
+ 	}
+ 
+-	spin_lock_init(&pmu->lock);
+-	jh71xx_pmu_int_enable(pmu, JH71XX_PMU_INT_ALL_MASK & ~JH71XX_PMU_INT_PCH_FAIL, true);
+-
+ 	ret = of_genpd_add_provider_onecell(np, &pmu->genpd_data);
+ 	if (ret) {
+ 		dev_err(dev, "failed to register genpd driver: %d\n", ret);
+@@ -357,6 +389,9 @@ static const struct jh71xx_domain_info j
+ static const struct jh71xx_pmu_match_data jh7110_pmu = {
+ 	.num_domains = ARRAY_SIZE(jh7110_power_domains),
+ 	.domain_info = jh7110_power_domains,
++	.pmu_status = JH71XX_PMU_CURR_POWER_MODE,
++	.pmu_parse_irq = jh7110_pmu_parse_irq,
++	.pmu_set_state = jh7110_pmu_set_state,
+ };
+ 
+ static const struct of_device_id jh71xx_pmu_of_match[] = {

+ 119 - 0
target/linux/starfive/patches-6.1/0073-soc-starfive-Add-JH7110-AON-PMU-support.patch

@@ -0,0 +1,119 @@
+From 3124d653318c50e20eadbb3998eafa5928ac9b63 Mon Sep 17 00:00:00 2001
+From: Changhuang Liang <[email protected]>
+Date: Thu, 18 May 2023 23:02:02 -0700
+Subject: [PATCH 073/122] soc: starfive: Add JH7110 AON PMU support
+
+Add AON PMU for StarFive JH7110 SoC. It can be used to turn on/off the
+dphy rx/tx power switch.
+
+Reviewed-by: Walker Chen <[email protected]>
+Signed-off-by: Changhuang Liang <[email protected]>
+---
+ drivers/soc/starfive/jh71xx_pmu.c | 57 ++++++++++++++++++++++++++++---
+ 1 file changed, 52 insertions(+), 5 deletions(-)
+
+--- a/drivers/soc/starfive/jh71xx_pmu.c
++++ b/drivers/soc/starfive/jh71xx_pmu.c
+@@ -2,7 +2,7 @@
+ /*
+  * StarFive JH71XX PMU (Power Management Unit) Controller Driver
+  *
+- * Copyright (C) 2022 StarFive Technology Co., Ltd.
++ * Copyright (C) 2022-2023 StarFive Technology Co., Ltd.
+  */
+ 
+ #include <linux/interrupt.h>
+@@ -24,6 +24,9 @@
+ #define JH71XX_PMU_EVENT_STATUS		0x88
+ #define JH71XX_PMU_INT_STATUS		0x8C
+ 
++/* aon pmu register offset */
++#define JH71XX_AON_PMU_SWITCH		0x00
++
+ /* sw encourage cfg */
+ #define JH71XX_PMU_SW_ENCOURAGE_EN_LO	0x05
+ #define JH71XX_PMU_SW_ENCOURAGE_EN_HI	0x50
+@@ -160,6 +163,26 @@ static int jh7110_pmu_set_state(struct j
+ 	return 0;
+ }
+ 
++static int jh7110_aon_pmu_set_state(struct jh71xx_pmu_dev *pmd, u32 mask, bool on)
++{
++	struct jh71xx_pmu *pmu = pmd->pmu;
++	unsigned long flags;
++	u32 val;
++
++	spin_lock_irqsave(&pmu->lock, flags);
++	val = readl(pmu->base + JH71XX_AON_PMU_SWITCH);
++
++	if (on)
++		val |= mask;
++	else
++		val &= ~mask;
++
++	writel(val, pmu->base + JH71XX_AON_PMU_SWITCH);
++	spin_unlock_irqrestore(&pmu->lock, flags);
++
++	return 0;
++}
++
+ static int jh71xx_pmu_set_state(struct jh71xx_pmu_dev *pmd, u32 mask, bool on)
+ {
+ 	struct jh71xx_pmu *pmu = pmd->pmu;
+@@ -317,10 +340,12 @@ static int jh71xx_pmu_probe(struct platf
+ 	if (!match_data)
+ 		return -EINVAL;
+ 
+-	ret = match_data->pmu_parse_irq(pdev, pmu);
+-	if (ret) {
+-		dev_err(dev, "failed to parse irq\n");
+-		return ret;
++	if (match_data->pmu_parse_irq) {
++		ret = match_data->pmu_parse_irq(pdev, pmu);
++		if (ret) {
++			dev_err(dev, "failed to parse irq\n");
++			return ret;
++		}
+ 	}
+ 
+ 	pmu->genpd = devm_kcalloc(dev, match_data->num_domains,
+@@ -394,11 +419,32 @@ static const struct jh71xx_pmu_match_dat
+ 	.pmu_set_state = jh7110_pmu_set_state,
+ };
+ 
++static const struct jh71xx_domain_info jh7110_aon_power_domains[] = {
++	[JH7110_PD_DPHY_TX] = {
++		.name = "DPHY-TX",
++		.bit = 30,
++	},
++	[JH7110_PD_DPHY_RX] = {
++		.name = "DPHY-RX",
++		.bit = 31,
++	},
++};
++
++static const struct jh71xx_pmu_match_data jh7110_aon_pmu = {
++	.num_domains = ARRAY_SIZE(jh7110_aon_power_domains),
++	.domain_info = jh7110_aon_power_domains,
++	.pmu_status = JH71XX_AON_PMU_SWITCH,
++	.pmu_set_state = jh7110_aon_pmu_set_state,
++};
++
+ static const struct of_device_id jh71xx_pmu_of_match[] = {
+ 	{
+ 		.compatible = "starfive,jh7110-pmu",
+ 		.data = (void *)&jh7110_pmu,
+ 	}, {
++		.compatible = "starfive,jh7110-aon-syscon",
++		.data = (void *)&jh7110_aon_pmu,
++	}, {
+ 		/* sentinel */
+ 	}
+ };
+@@ -414,5 +460,6 @@ static struct platform_driver jh71xx_pmu
+ builtin_platform_driver(jh71xx_pmu_driver);
+ 
+ MODULE_AUTHOR("Walker Chen <[email protected]>");
++MODULE_AUTHOR("Changhuang Liang <[email protected]>");
+ MODULE_DESCRIPTION("StarFive JH71XX PMU Driver");
+ MODULE_LICENSE("GPL");

+ 88 - 0
target/linux/starfive/patches-6.1/0074-dt-bindings-phy-Add-starfive-jh7110-dphy-rx.patch

@@ -0,0 +1,88 @@
+From 7492ebbdd926da258f9abea5c41a9f8c4ec48631 Mon Sep 17 00:00:00 2001
+From: Changhuang Liang <[email protected]>
+Date: Mon, 29 May 2023 05:15:01 -0700
+Subject: [PATCH 074/122] dt-bindings: phy: Add starfive,jh7110-dphy-rx
+
+StarFive SoCs like the jh7110 use a MIPI D-PHY RX controller based on
+a M31 IP. Add a binding for it.
+
+Signed-off-by: Changhuang Liang <[email protected]>
+---
+ .../bindings/phy/starfive,jh7110-dphy-rx.yaml | 71 +++++++++++++++++++
+ 1 file changed, 71 insertions(+)
+ create mode 100644 Documentation/devicetree/bindings/phy/starfive,jh7110-dphy-rx.yaml
+
+--- /dev/null
++++ b/Documentation/devicetree/bindings/phy/starfive,jh7110-dphy-rx.yaml
+@@ -0,0 +1,71 @@
++# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause)
++%YAML 1.2
++---
++$id: http://devicetree.org/schemas/phy/starfive,jh7110-dphy-rx.yaml#
++$schema: http://devicetree.org/meta-schemas/core.yaml#
++
++title: StarFive SoC MIPI D-PHY Rx Controller
++
++maintainers:
++  - Jack Zhu <[email protected]>
++  - Changhuang Liang <[email protected]>
++
++description:
++  The StarFive SoC uses the MIPI CSI D-PHY based on M31 IP to transfer
++  CSI camera data.
++
++properties:
++  compatible:
++    const: starfive,jh7110-dphy-rx
++
++  reg:
++    maxItems: 1
++
++  clocks:
++    items:
++      - description: config clock
++      - description: reference clock
++      - description: escape mode transmit clock
++
++  clock-names:
++    items:
++      - const: cfg
++      - const: ref
++      - const: tx
++
++  resets:
++    items:
++      - description: DPHY_HW reset
++      - description: DPHY_B09_ALWAYS_ON reset
++
++  power-domains:
++    maxItems: 1
++
++  "#phy-cells":
++    const: 0
++
++required:
++  - compatible
++  - reg
++  - clocks
++  - clock-names
++  - resets
++  - power-domains
++  - "#phy-cells"
++
++additionalProperties: false
++
++examples:
++  - |
++    phy@19820000 {
++      compatible = "starfive,jh7110-dphy-rx";
++      reg = <0x19820000 0x10000>;
++      clocks = <&ispcrg 3>,
++               <&ispcrg 4>,
++               <&ispcrg 5>;
++      clock-names = "cfg", "ref", "tx";
++      resets = <&ispcrg 2>,
++               <&ispcrg 3>;
++      power-domains = <&dphy_pwrc 1>;
++      #phy-cells = <0>;
++    };

+ 365 - 0
target/linux/starfive/patches-6.1/0075-phy-starfive-Add-mipi-dphy-rx-support.patch

@@ -0,0 +1,365 @@
+From f6fbb431f9e3ac5c9144edf05340db9a96dffa59 Mon Sep 17 00:00:00 2001
+From: Changhuang Liang <[email protected]>
+Date: Mon, 29 May 2023 05:15:02 -0700
+Subject: [PATCH 075/122] phy: starfive: Add mipi dphy rx support
+
+Add mipi dphy rx support for the StarFive JH7110 SoC. It is used to
+transfer CSI camera data.
+
+Signed-off-by: Changhuang Liang <[email protected]>
+---
+ drivers/phy/Kconfig                         |   1 +
+ drivers/phy/Makefile                        |   1 +
+ drivers/phy/starfive/Kconfig                |  13 +
+ drivers/phy/starfive/Makefile               |   2 +
+ drivers/phy/starfive/phy-starfive-dphy-rx.c | 301 ++++++++++++++++++++
+ 5 files changed, 318 insertions(+)
+ create mode 100644 drivers/phy/starfive/Kconfig
+ create mode 100644 drivers/phy/starfive/Makefile
+ create mode 100644 drivers/phy/starfive/phy-starfive-dphy-rx.c
+
+--- a/drivers/phy/Kconfig
++++ b/drivers/phy/Kconfig
+@@ -91,6 +91,7 @@ source "drivers/phy/rockchip/Kconfig"
+ source "drivers/phy/samsung/Kconfig"
+ source "drivers/phy/socionext/Kconfig"
+ source "drivers/phy/st/Kconfig"
++source "drivers/phy/starfive/Kconfig"
+ source "drivers/phy/sunplus/Kconfig"
+ source "drivers/phy/tegra/Kconfig"
+ source "drivers/phy/ti/Kconfig"
+--- a/drivers/phy/Makefile
++++ b/drivers/phy/Makefile
+@@ -31,6 +31,7 @@ obj-y					+= allwinner/	\
+ 					   samsung/	\
+ 					   socionext/	\
+ 					   st/		\
++					   starfive/	\
+ 					   sunplus/	\
+ 					   tegra/	\
+ 					   ti/		\
+--- /dev/null
++++ b/drivers/phy/starfive/Kconfig
+@@ -0,0 +1,13 @@
++# SPDX-License-Identifier: GPL-2.0-only
++#
++# Phy drivers for StarFive platforms
++#
++
++config PHY_STARFIVE_DPHY_RX
++	tristate "StarFive D-PHY RX Support"
++	select GENERIC_PHY
++	select GENERIC_PHY_MIPI_DPHY
++	help
++	  Choose this option if you have a StarFive D-PHY in your
++	  system. If M is selected, the module will be called
++	  phy-starfive-dphy-rx.
+--- /dev/null
++++ b/drivers/phy/starfive/Makefile
+@@ -0,0 +1,2 @@
++# SPDX-License-Identifier: GPL-2.0
++obj-$(CONFIG_PHY_STARFIVE_DPHY_RX)      += phy-starfive-dphy-rx.o
+--- /dev/null
++++ b/drivers/phy/starfive/phy-starfive-dphy-rx.c
+@@ -0,0 +1,301 @@
++// SPDX-License-Identifier: GPL-2.0+
++/*
++ * DPHY driver for the StarFive JH7110 SoC
++ *
++ * Copyright (C) 2023 StarFive Technology Co., Ltd.
++ */
++
++#include <linux/bitfield.h>
++#include <linux/bitops.h>
++#include <linux/clk.h>
++#include <linux/io.h>
++#include <linux/module.h>
++#include <linux/of.h>
++#include <linux/of_device.h>
++#include <linux/phy/phy.h>
++#include <linux/platform_device.h>
++#include <linux/pm_runtime.h>
++#include <linux/reset.h>
++
++#define STF_DPHY_APBCFGSAIF_SYSCFG(x)		(x)
++
++#define STF_DPHY_DA_CDPHY_R100_CTRL0_2D1C_EFUSE_EN BIT(6)
++#define STF_DPHY_DA_CDPHY_R100_CTRL0_2D1C_EFUSE_IN GENMASK(12, 7)
++#define STF_DPHY_DA_CDPHY_R100_CTRL1_2D1C_EFUSE_EN BIT(19)
++#define STF_DPHY_DA_CDPHY_R100_CTRL1_2D1C_EFUSE_IN GENMASK(25, 20)
++
++#define STF_DPHY_DATA_BUS16_8			BIT(8)
++#define STF_DPHY_DEBUG_MODE_SEL			GENMASK(15, 9)
++
++#define STF_DPHY_ENABLE_CLK			BIT(6)
++#define STF_DPHY_ENABLE_CLK1			BIT(7)
++#define STF_DPHY_ENABLE_LAN0			BIT(8)
++#define STF_DPHY_ENABLE_LAN1			BIT(9)
++#define STF_DPHY_ENABLE_LAN2			BIT(10)
++#define STF_DPHY_ENABLE_LAN3			BIT(11)
++#define STF_DPHY_GPI_EN				GENMASK(17, 12)
++#define STF_DPHY_HS_FREQ_CHANGE_CLK		BIT(18)
++#define STF_DPHY_HS_FREQ_CHANGE_CLK1		BIT(19)
++#define STF_DPHY_LANE_SWAP_CLK			GENMASK(22, 20)
++#define STF_DPHY_LANE_SWAP_CLK1			GENMASK(25, 23)
++#define STF_DPHY_LANE_SWAP_LAN0			GENMASK(28, 26)
++#define STF_DPHY_LANE_SWAP_LAN1			GENMASK(31, 29)
++
++#define STF_DPHY_LANE_SWAP_LAN2			GENMASK(2, 0)
++#define STF_DPHY_LANE_SWAP_LAN3			GENMASK(5, 3)
++#define STF_DPHY_MP_TEST_EN			BIT(6)
++#define STF_DPHY_MP_TEST_MODE_SEL		GENMASK(11, 7)
++#define STF_DPHY_PLL_CLK_SEL			GENMASK(21, 12)
++#define STF_DPHY_PRECOUNTER_IN_CLK		GENMASK(29, 22)
++
++#define STF_DPHY_PRECOUNTER_IN_CLK1		GENMASK(7, 0)
++#define STF_DPHY_PRECOUNTER_IN_LAN0		GENMASK(15, 8)
++#define STF_DPHY_PRECOUNTER_IN_LAN1		GENMASK(23, 16)
++#define STF_DPHY_PRECOUNTER_IN_LAN2		GENMASK(31, 24)
++
++#define STF_DPHY_PRECOUNTER_IN_LAN3		GENMASK(7, 0)
++#define STF_DPHY_RX_1C2C_SEL			BIT(8)
++
++#define STF_MAP_LANES_NUM			6
++
++struct regval {
++	u32 addr;
++	u32 val;
++};
++
++struct stf_dphy_info {
++	/**
++	 * @maps:
++	 *
++	 * Physical lanes and logic lanes mapping table.
++	 *
++	 * The default order is:
++	 * [clk lane0, data lane 0, data lane 1, data lane 2, date lane 3, clk lane 1]
++	 */
++	u8 maps[STF_MAP_LANES_NUM];
++};
++
++struct stf_dphy {
++	struct device *dev;
++	void __iomem *regs;
++	struct clk *cfg_clk;
++	struct clk *ref_clk;
++	struct clk *tx_clk;
++	struct reset_control *rstc;
++	struct regulator *mipi_0p9;
++	struct phy *phy;
++	const struct stf_dphy_info *info;
++};
++
++static const struct regval stf_dphy_init_list[] = {
++	{ STF_DPHY_APBCFGSAIF_SYSCFG(4), 0x00000000 },
++	{ STF_DPHY_APBCFGSAIF_SYSCFG(8), 0x00000000 },
++	{ STF_DPHY_APBCFGSAIF_SYSCFG(12), 0x0000fff0 },
++	{ STF_DPHY_APBCFGSAIF_SYSCFG(16), 0x00000000 },
++	{ STF_DPHY_APBCFGSAIF_SYSCFG(20), 0x00000000 },
++	{ STF_DPHY_APBCFGSAIF_SYSCFG(24), 0x00000000 },
++	{ STF_DPHY_APBCFGSAIF_SYSCFG(28), 0x00000000 },
++	{ STF_DPHY_APBCFGSAIF_SYSCFG(32), 0x00000000 },
++	{ STF_DPHY_APBCFGSAIF_SYSCFG(36), 0x00000000 },
++	{ STF_DPHY_APBCFGSAIF_SYSCFG(40), 0x00000000 },
++	{ STF_DPHY_APBCFGSAIF_SYSCFG(40), 0x00000000 },
++	{ STF_DPHY_APBCFGSAIF_SYSCFG(48), 0x24000000 },
++	{ STF_DPHY_APBCFGSAIF_SYSCFG(52), 0x00000000 },
++	{ STF_DPHY_APBCFGSAIF_SYSCFG(56), 0x00000000 },
++	{ STF_DPHY_APBCFGSAIF_SYSCFG(60), 0x00000000 },
++	{ STF_DPHY_APBCFGSAIF_SYSCFG(64), 0x00000000 },
++	{ STF_DPHY_APBCFGSAIF_SYSCFG(68), 0x00000000 },
++	{ STF_DPHY_APBCFGSAIF_SYSCFG(72), 0x00000000 },
++	{ STF_DPHY_APBCFGSAIF_SYSCFG(76), 0x00000000 },
++	{ STF_DPHY_APBCFGSAIF_SYSCFG(80), 0x00000000 },
++	{ STF_DPHY_APBCFGSAIF_SYSCFG(84), 0x00000000 },
++	{ STF_DPHY_APBCFGSAIF_SYSCFG(88), 0x00000000 },
++	{ STF_DPHY_APBCFGSAIF_SYSCFG(92), 0x00000000 },
++	{ STF_DPHY_APBCFGSAIF_SYSCFG(96), 0x00000000 },
++	{ STF_DPHY_APBCFGSAIF_SYSCFG(100), 0x02000000 },
++	{ STF_DPHY_APBCFGSAIF_SYSCFG(104), 0x00000000 },
++	{ STF_DPHY_APBCFGSAIF_SYSCFG(108), 0x00000000 },
++	{ STF_DPHY_APBCFGSAIF_SYSCFG(112), 0x00000000 },
++	{ STF_DPHY_APBCFGSAIF_SYSCFG(116), 0x00000000 },
++	{ STF_DPHY_APBCFGSAIF_SYSCFG(120), 0x00000000 },
++	{ STF_DPHY_APBCFGSAIF_SYSCFG(124), 0x0000000c },
++	{ STF_DPHY_APBCFGSAIF_SYSCFG(128), 0x00000000 },
++	{ STF_DPHY_APBCFGSAIF_SYSCFG(132), 0xcc500000 },
++	{ STF_DPHY_APBCFGSAIF_SYSCFG(136), 0x000000cc },
++	{ STF_DPHY_APBCFGSAIF_SYSCFG(140), 0x00000000 },
++	{ STF_DPHY_APBCFGSAIF_SYSCFG(144), 0x00000000 },
++};
++
++static int stf_dphy_configure(struct phy *phy, union phy_configure_opts *opts)
++{
++	struct stf_dphy *dphy = phy_get_drvdata(phy);
++	const struct stf_dphy_info *info = dphy->info;
++	int i;
++
++	for (i = 0; i < ARRAY_SIZE(stf_dphy_init_list); i++)
++		writel(stf_dphy_init_list[i].val,
++		       dphy->regs + stf_dphy_init_list[i].addr);
++
++	writel(FIELD_PREP(STF_DPHY_DA_CDPHY_R100_CTRL0_2D1C_EFUSE_EN, 1) |
++	       FIELD_PREP(STF_DPHY_DA_CDPHY_R100_CTRL0_2D1C_EFUSE_IN, 0x1b) |
++	       FIELD_PREP(STF_DPHY_DA_CDPHY_R100_CTRL1_2D1C_EFUSE_EN, 1) |
++	       FIELD_PREP(STF_DPHY_DA_CDPHY_R100_CTRL1_2D1C_EFUSE_IN, 0x1b),
++	       dphy->regs + STF_DPHY_APBCFGSAIF_SYSCFG(0));
++
++	writel(FIELD_PREP(STF_DPHY_DATA_BUS16_8, 0) |
++	       FIELD_PREP(STF_DPHY_DEBUG_MODE_SEL, 0x5a),
++	       dphy->regs + STF_DPHY_APBCFGSAIF_SYSCFG(184));
++
++	writel(FIELD_PREP(STF_DPHY_ENABLE_CLK, 1) |
++	       FIELD_PREP(STF_DPHY_ENABLE_CLK1, 1) |
++	       FIELD_PREP(STF_DPHY_ENABLE_LAN0, 1) |
++	       FIELD_PREP(STF_DPHY_ENABLE_LAN1, 1) |
++	       FIELD_PREP(STF_DPHY_ENABLE_LAN2, 1) |
++	       FIELD_PREP(STF_DPHY_ENABLE_LAN3, 1) |
++	       FIELD_PREP(STF_DPHY_GPI_EN, 0) |
++	       FIELD_PREP(STF_DPHY_HS_FREQ_CHANGE_CLK, 0) |
++	       FIELD_PREP(STF_DPHY_HS_FREQ_CHANGE_CLK1, 0) |
++	       FIELD_PREP(STF_DPHY_LANE_SWAP_CLK, info->maps[0]) |
++	       FIELD_PREP(STF_DPHY_LANE_SWAP_CLK1, info->maps[5]) |
++	       FIELD_PREP(STF_DPHY_LANE_SWAP_LAN0, info->maps[1]) |
++	       FIELD_PREP(STF_DPHY_LANE_SWAP_LAN1, info->maps[2]),
++	       dphy->regs + STF_DPHY_APBCFGSAIF_SYSCFG(188));
++
++	writel(FIELD_PREP(STF_DPHY_LANE_SWAP_LAN2, info->maps[3]) |
++	       FIELD_PREP(STF_DPHY_LANE_SWAP_LAN3, info->maps[4]) |
++	       FIELD_PREP(STF_DPHY_MP_TEST_EN, 0) |
++	       FIELD_PREP(STF_DPHY_MP_TEST_MODE_SEL, 0) |
++	       FIELD_PREP(STF_DPHY_PLL_CLK_SEL, 0x37c) |
++	       FIELD_PREP(STF_DPHY_PRECOUNTER_IN_CLK, 8),
++	       dphy->regs + STF_DPHY_APBCFGSAIF_SYSCFG(192));
++
++	writel(FIELD_PREP(STF_DPHY_PRECOUNTER_IN_CLK1, 8) |
++	       FIELD_PREP(STF_DPHY_PRECOUNTER_IN_LAN0, 7) |
++	       FIELD_PREP(STF_DPHY_PRECOUNTER_IN_LAN1, 7) |
++	       FIELD_PREP(STF_DPHY_PRECOUNTER_IN_LAN2, 7),
++	       dphy->regs + STF_DPHY_APBCFGSAIF_SYSCFG(196));
++
++	writel(FIELD_PREP(STF_DPHY_PRECOUNTER_IN_LAN3, 7) |
++	       FIELD_PREP(STF_DPHY_RX_1C2C_SEL, 0),
++	       dphy->regs + STF_DPHY_APBCFGSAIF_SYSCFG(200));
++
++	return 0;
++}
++
++static int stf_dphy_power_on(struct phy *phy)
++{
++	struct stf_dphy *dphy = phy_get_drvdata(phy);
++	int ret;
++
++	pm_runtime_get_sync(dphy->dev);
++
++	ret = regulator_enable(dphy->mipi_0p9);
++	if (ret)
++		return ret;
++
++	clk_set_rate(dphy->cfg_clk, 99000000);
++	clk_set_rate(dphy->ref_clk, 49500000);
++	clk_set_rate(dphy->tx_clk, 19800000);
++	reset_control_deassert(dphy->rstc);
++
++	return 0;
++}
++
++static int stf_dphy_power_off(struct phy *phy)
++{
++	struct stf_dphy *dphy = phy_get_drvdata(phy);
++
++	reset_control_assert(dphy->rstc);
++
++	regulator_disable(dphy->mipi_0p9);
++
++	pm_runtime_put_sync(dphy->dev);
++
++	return 0;
++}
++
++static const struct phy_ops stf_dphy_ops = {
++	.configure = stf_dphy_configure,
++	.power_on  = stf_dphy_power_on,
++	.power_off = stf_dphy_power_off,
++};
++
++static int stf_dphy_probe(struct platform_device *pdev)
++{
++	struct phy_provider *phy_provider;
++	struct stf_dphy *dphy;
++
++	dphy = devm_kzalloc(&pdev->dev, sizeof(*dphy), GFP_KERNEL);
++	if (!dphy)
++		return -ENOMEM;
++
++	dphy->info = of_device_get_match_data(&pdev->dev);
++
++	dev_set_drvdata(&pdev->dev, dphy);
++	dphy->dev = &pdev->dev;
++
++	dphy->regs = devm_platform_ioremap_resource(pdev, 0);
++	if (IS_ERR(dphy->regs))
++		return PTR_ERR(dphy->regs);
++
++	dphy->cfg_clk = devm_clk_get(&pdev->dev, "cfg");
++	if (IS_ERR(dphy->cfg_clk))
++		return PTR_ERR(dphy->cfg_clk);
++
++	dphy->ref_clk = devm_clk_get(&pdev->dev, "ref");
++	if (IS_ERR(dphy->ref_clk))
++		return PTR_ERR(dphy->ref_clk);
++
++	dphy->tx_clk = devm_clk_get(&pdev->dev, "tx");
++	if (IS_ERR(dphy->tx_clk))
++		return PTR_ERR(dphy->tx_clk);
++
++	dphy->rstc = devm_reset_control_array_get_exclusive(&pdev->dev);
++	if (IS_ERR(dphy->rstc))
++		return PTR_ERR(dphy->rstc);
++
++	dphy->mipi_0p9 = devm_regulator_get(&pdev->dev, "mipi_0p9");
++	if (IS_ERR(dphy->mipi_0p9))
++		return PTR_ERR(dphy->mipi_0p9);
++
++	dphy->phy = devm_phy_create(&pdev->dev, NULL, &stf_dphy_ops);
++	if (IS_ERR(dphy->phy)) {
++		dev_err(&pdev->dev, "Failed to create PHY\n");
++		return PTR_ERR(dphy->phy);
++	}
++
++	pm_runtime_enable(&pdev->dev);
++
++	phy_set_drvdata(dphy->phy, dphy);
++	phy_provider = devm_of_phy_provider_register(&pdev->dev,
++						     of_phy_simple_xlate);
++
++	return PTR_ERR_OR_ZERO(phy_provider);
++}
++
++static const struct stf_dphy_info starfive_dphy_info = {
++	.maps = {4, 0, 1, 2, 3, 5},
++};
++
++static const struct of_device_id stf_dphy_dt_ids[] = {
++	{
++		.compatible = "starfive,jh7110-dphy-rx",
++		.data = &starfive_dphy_info,
++	},
++	{ /* sentinel */ },
++};
++MODULE_DEVICE_TABLE(of, stf_dphy_dt_ids);
++
++static struct platform_driver stf_dphy_driver = {
++	.probe = stf_dphy_probe,
++	.driver = {
++		.name	= "starfive-dphy-rx",
++		.of_match_table = stf_dphy_dt_ids,
++	},
++};
++module_platform_driver(stf_dphy_driver);
++
++MODULE_AUTHOR("Jack Zhu <[email protected]>");
++MODULE_AUTHOR("Changhuang Liang <[email protected]>");
++MODULE_DESCRIPTION("StarFive DPHY RX driver");
++MODULE_LICENSE("GPL");

+ 306 - 0
target/linux/starfive/patches-6.1/0076-media-dt-bindings-cadence-csi2rx-Convert-to-DT-schem.patch

@@ -0,0 +1,306 @@
+From 243b040c3517093309a41877e3c1c6e8a7540071 Mon Sep 17 00:00:00 2001
+From: Jack Zhu <[email protected]>
+Date: Tue, 23 May 2023 16:56:22 +0800
+Subject: [PATCH 076/122] media: dt-bindings: cadence-csi2rx: Convert to DT
+ schema
+
+Convert DT bindings document for Cadence MIPI-CSI2 RX controller to
+DT schema format.
+
+For compatible, new compatibles should not be messed with conversion,
+but the original binding did not specify any SoC-specific compatible
+string, so add the StarFive compatible string.
+
+Reviewed-by: Krzysztof Kozlowski <[email protected]>
+Reviewed-by: Laurent Pinchart <[email protected]>
+Signed-off-by: Jack Zhu <[email protected]>
+---
+ .../devicetree/bindings/media/cdns,csi2rx.txt | 100 ----------
+ .../bindings/media/cdns,csi2rx.yaml           | 177 ++++++++++++++++++
+ 2 files changed, 177 insertions(+), 100 deletions(-)
+ delete mode 100644 Documentation/devicetree/bindings/media/cdns,csi2rx.txt
+ create mode 100644 Documentation/devicetree/bindings/media/cdns,csi2rx.yaml
+
+--- a/Documentation/devicetree/bindings/media/cdns,csi2rx.txt
++++ /dev/null
+@@ -1,100 +0,0 @@
+-Cadence MIPI-CSI2 RX controller
+-===============================
+-
+-The Cadence MIPI-CSI2 RX controller is a CSI-2 bridge supporting up to 4 CSI
+-lanes in input, and 4 different pixel streams in output.
+-
+-Required properties:
+-  - compatible: must be set to "cdns,csi2rx" and an SoC-specific compatible
+-  - reg: base address and size of the memory mapped region
+-  - clocks: phandles to the clocks driving the controller
+-  - clock-names: must contain:
+-    * sys_clk: main clock
+-    * p_clk: register bank clock
+-    * pixel_if[0-3]_clk: pixel stream output clock, one for each stream
+-                         implemented in hardware, between 0 and 3
+-
+-Optional properties:
+-  - phys: phandle to the external D-PHY, phy-names must be provided
+-  - phy-names: must contain "dphy", if the implementation uses an
+-               external D-PHY
+-
+-Required subnodes:
+-  - ports: A ports node with one port child node per device input and output
+-           port, in accordance with the video interface bindings defined in
+-           Documentation/devicetree/bindings/media/video-interfaces.txt. The
+-           port nodes are numbered as follows:
+-
+-           Port Description
+-           -----------------------------
+-           0    CSI-2 input
+-           1    Stream 0 output
+-           2    Stream 1 output
+-           3    Stream 2 output
+-           4    Stream 3 output
+-
+-           The stream output port nodes are optional if they are not
+-           connected to anything at the hardware level or implemented
+-           in the design.Since there is only one endpoint per port,
+-           the endpoints are not numbered.
+-
+-
+-Example:
+-
+-csi2rx: csi-bridge@0d060000 {
+-	compatible = "cdns,csi2rx";
+-	reg = <0x0d060000 0x1000>;
+-	clocks = <&byteclock>, <&byteclock>
+-		 <&coreclock>, <&coreclock>,
+-		 <&coreclock>, <&coreclock>;
+-	clock-names = "sys_clk", "p_clk",
+-		      "pixel_if0_clk", "pixel_if1_clk",
+-		      "pixel_if2_clk", "pixel_if3_clk";
+-
+-	ports {
+-		#address-cells = <1>;
+-		#size-cells = <0>;
+-
+-		port@0 {
+-			reg = <0>;
+-
+-			csi2rx_in_sensor: endpoint {
+-				remote-endpoint = <&sensor_out_csi2rx>;
+-				clock-lanes = <0>;
+-				data-lanes = <1 2>;
+-			};
+-		};
+-
+-		port@1 {
+-			reg = <1>;
+-
+-			csi2rx_out_grabber0: endpoint {
+-				remote-endpoint = <&grabber0_in_csi2rx>;
+-			};
+-		};
+-
+-		port@2 {
+-			reg = <2>;
+-
+-			csi2rx_out_grabber1: endpoint {
+-				remote-endpoint = <&grabber1_in_csi2rx>;
+-			};
+-		};
+-
+-		port@3 {
+-			reg = <3>;
+-
+-			csi2rx_out_grabber2: endpoint {
+-				remote-endpoint = <&grabber2_in_csi2rx>;
+-			};
+-		};
+-
+-		port@4 {
+-			reg = <4>;
+-
+-			csi2rx_out_grabber3: endpoint {
+-				remote-endpoint = <&grabber3_in_csi2rx>;
+-			};
+-		};
+-	};
+-};
+--- /dev/null
++++ b/Documentation/devicetree/bindings/media/cdns,csi2rx.yaml
+@@ -0,0 +1,177 @@
++# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause)
++%YAML 1.2
++---
++$id: http://devicetree.org/schemas/media/cdns,csi2rx.yaml#
++$schema: http://devicetree.org/meta-schemas/core.yaml#
++
++title: Cadence MIPI-CSI2 RX controller
++
++maintainers:
++  - Maxime Ripard <[email protected]>
++
++description:
++  The Cadence MIPI-CSI2 RX controller is a CSI-2 bridge supporting up to 4 CSI
++  lanes in input, and 4 different pixel streams in output.
++
++properties:
++  compatible:
++    items:
++      - enum:
++          - starfive,jh7110-csi2rx
++      - const: cdns,csi2rx
++
++  reg:
++    maxItems: 1
++
++  clocks:
++    items:
++      - description: CSI2Rx system clock
++      - description: Gated Register bank clock for APB interface
++      - description: pixel Clock for Stream interface 0
++      - description: pixel Clock for Stream interface 1
++      - description: pixel Clock for Stream interface 2
++      - description: pixel Clock for Stream interface 3
++
++  clock-names:
++    items:
++      - const: sys_clk
++      - const: p_clk
++      - const: pixel_if0_clk
++      - const: pixel_if1_clk
++      - const: pixel_if2_clk
++      - const: pixel_if3_clk
++
++  phys:
++    maxItems: 1
++    description: MIPI D-PHY
++
++  phy-names:
++    items:
++      - const: dphy
++
++  ports:
++    $ref: /schemas/graph.yaml#/properties/ports
++
++    properties:
++      port@0:
++        $ref: /schemas/graph.yaml#/$defs/port-base
++        unevaluatedProperties: false
++        description:
++          Input port node, single endpoint describing the CSI-2 transmitter.
++
++        properties:
++          endpoint:
++            $ref: video-interfaces.yaml#
++            unevaluatedProperties: false
++
++            properties:
++              bus-type:
++                const: 4
++
++              clock-lanes:
++                const: 0
++
++              data-lanes:
++                minItems: 1
++                maxItems: 4
++                items:
++                  maximum: 4
++
++            required:
++              - data-lanes
++
++      port@1:
++        $ref: /schemas/graph.yaml#/properties/port
++        description:
++          Stream 0 Output port node
++
++      port@2:
++        $ref: /schemas/graph.yaml#/properties/port
++        description:
++          Stream 1 Output port node
++
++      port@3:
++        $ref: /schemas/graph.yaml#/properties/port
++        description:
++          Stream 2 Output port node
++
++      port@4:
++        $ref: /schemas/graph.yaml#/properties/port
++        description:
++          Stream 3 Output port node
++
++    required:
++      - port@0
++
++required:
++  - compatible
++  - reg
++  - clocks
++  - clock-names
++  - ports
++
++additionalProperties: false
++
++examples:
++  - |
++    csi@d060000 {
++        compatible = "starfive,jh7110-csi2rx", "cdns,csi2rx";
++        reg = <0x0d060000 0x1000>;
++        clocks = <&byteclock 7>, <&byteclock 6>,
++                 <&coreclock 8>, <&coreclock 9>,
++                 <&coreclock 10>, <&coreclock 11>;
++        clock-names = "sys_clk", "p_clk",
++                      "pixel_if0_clk", "pixel_if1_clk",
++                      "pixel_if2_clk", "pixel_if3_clk";
++        phys = <&csi_phy>;
++        phy-names = "dphy";
++
++        ports {
++                #address-cells = <1>;
++                #size-cells = <0>;
++
++                port@0 {
++                    reg = <0>;
++
++                    csi2rx_in_sensor: endpoint {
++                        remote-endpoint = <&sensor_out_csi2rx>;
++                        clock-lanes = <0>;
++                        data-lanes = <1 2>;
++                    };
++                };
++
++                port@1 {
++                    reg = <1>;
++
++                    csi2rx_out_grabber0: endpoint {
++                        remote-endpoint = <&grabber0_in_csi2rx>;
++                    };
++                };
++
++                port@2 {
++                    reg = <2>;
++
++                    csi2rx_out_grabber1: endpoint {
++                        remote-endpoint = <&grabber1_in_csi2rx>;
++                    };
++                };
++
++                port@3 {
++                    reg = <3>;
++
++                    csi2rx_out_grabber2: endpoint {
++                        remote-endpoint = <&grabber2_in_csi2rx>;
++                    };
++                };
++
++                port@4 {
++                    reg = <4>;
++
++                    csi2rx_out_grabber3: endpoint {
++                        remote-endpoint = <&grabber3_in_csi2rx>;
++                    };
++                };
++        };
++    };
++
++...

+ 55 - 0
target/linux/starfive/patches-6.1/0077-media-dt-bindings-cadence-csi2rx-Add-resets-property.patch

@@ -0,0 +1,55 @@
+From 60817a4e755c6e98092fdceec35fcda94d35e4b1 Mon Sep 17 00:00:00 2001
+From: Jack Zhu <[email protected]>
+Date: Tue, 23 May 2023 16:56:23 +0800
+Subject: [PATCH 077/122] media: dt-bindings: cadence-csi2rx: Add resets
+ property
+
+Add resets property for Cadence MIPI-CSI2 RX controller
+
+Reviewed-by: Krzysztof Kozlowski <[email protected]>
+Reviewed-by: Laurent Pinchart <[email protected]>
+Signed-off-by: Jack Zhu <[email protected]>
+---
+ .../bindings/media/cdns,csi2rx.yaml           | 24 +++++++++++++++++++
+ 1 file changed, 24 insertions(+)
+
+--- a/Documentation/devicetree/bindings/media/cdns,csi2rx.yaml
++++ b/Documentation/devicetree/bindings/media/cdns,csi2rx.yaml
+@@ -41,6 +41,24 @@ properties:
+       - const: pixel_if2_clk
+       - const: pixel_if3_clk
+ 
++  resets:
++    items:
++      - description: CSI2Rx system reset
++      - description: Gated Register bank reset for APB interface
++      - description: pixel reset for Stream interface 0
++      - description: pixel reset for Stream interface 1
++      - description: pixel reset for Stream interface 2
++      - description: pixel reset for Stream interface 3
++
++  reset-names:
++    items:
++      - const: sys
++      - const: reg_bank
++      - const: pixel_if0
++      - const: pixel_if1
++      - const: pixel_if2
++      - const: pixel_if3
++
+   phys:
+     maxItems: 1
+     description: MIPI D-PHY
+@@ -123,6 +141,12 @@ examples:
+         clock-names = "sys_clk", "p_clk",
+                       "pixel_if0_clk", "pixel_if1_clk",
+                       "pixel_if2_clk", "pixel_if3_clk";
++        resets = <&bytereset 9>, <&bytereset 4>,
++                 <&corereset 5>, <&corereset 6>,
++                 <&corereset 7>, <&corereset 8>;
++        reset-names = "sys", "reg_bank",
++                      "pixel_if0", "pixel_if1",
++                      "pixel_if2", "pixel_if3";
+         phys = <&csi_phy>;
+         phy-names = "dphy";
+ 

+ 129 - 0
target/linux/starfive/patches-6.1/0078-media-cadence-Add-operation-on-reset.patch

@@ -0,0 +1,129 @@
+From 2fbf4d367b25de4fa2f2d9cec57c88766c37d9de Mon Sep 17 00:00:00 2001
+From: Jack Zhu <[email protected]>
+Date: Tue, 23 May 2023 16:56:24 +0800
+Subject: [PATCH 078/122] media: cadence: Add operation on reset
+
+Add operation on reset for Cadence MIPI-CSI2 RX Controller.
+
+Reviewed-by: Laurent Pinchart <[email protected]>
+Signed-off-by: Jack Zhu <[email protected]>
+---
+ drivers/media/platform/cadence/cdns-csi2rx.c | 40 +++++++++++++++++---
+ 1 file changed, 35 insertions(+), 5 deletions(-)
+
+--- a/drivers/media/platform/cadence/cdns-csi2rx.c
++++ b/drivers/media/platform/cadence/cdns-csi2rx.c
+@@ -13,6 +13,7 @@
+ #include <linux/of_graph.h>
+ #include <linux/phy/phy.h>
+ #include <linux/platform_device.h>
++#include <linux/reset.h>
+ #include <linux/slab.h>
+ 
+ #include <media/v4l2-ctrls.h>
+@@ -68,6 +69,9 @@ struct csi2rx_priv {
+ 	struct clk			*sys_clk;
+ 	struct clk			*p_clk;
+ 	struct clk			*pixel_clk[CSI2RX_STREAMS_MAX];
++	struct reset_control		*sys_rst;
++	struct reset_control		*p_rst;
++	struct reset_control		*pixel_rst[CSI2RX_STREAMS_MAX];
+ 	struct phy			*dphy;
+ 
+ 	u8				lanes[CSI2RX_LANES_MAX];
+@@ -112,6 +116,7 @@ static int csi2rx_start(struct csi2rx_pr
+ 	if (ret)
+ 		return ret;
+ 
++	reset_control_deassert(csi2rx->p_rst);
+ 	csi2rx_reset(csi2rx);
+ 
+ 	reg = csi2rx->num_lanes << 8;
+@@ -154,6 +159,8 @@ static int csi2rx_start(struct csi2rx_pr
+ 		if (ret)
+ 			goto err_disable_pixclk;
+ 
++		reset_control_deassert(csi2rx->pixel_rst[i]);
++
+ 		writel(CSI2RX_STREAM_CFG_FIFO_MODE_LARGE_BUF,
+ 		       csi2rx->base + CSI2RX_STREAM_CFG_REG(i));
+ 
+@@ -169,13 +176,16 @@ static int csi2rx_start(struct csi2rx_pr
+ 	if (ret)
+ 		goto err_disable_pixclk;
+ 
++	reset_control_deassert(csi2rx->sys_rst);
+ 	clk_disable_unprepare(csi2rx->p_clk);
+ 
+ 	return 0;
+ 
+ err_disable_pixclk:
+-	for (; i > 0; i--)
++	for (; i > 0; i--) {
++		reset_control_assert(csi2rx->pixel_rst[i - 1]);
+ 		clk_disable_unprepare(csi2rx->pixel_clk[i - 1]);
++	}
+ 
+ err_disable_pclk:
+ 	clk_disable_unprepare(csi2rx->p_clk);
+@@ -188,14 +198,17 @@ static void csi2rx_stop(struct csi2rx_pr
+ 	unsigned int i;
+ 
+ 	clk_prepare_enable(csi2rx->p_clk);
++	reset_control_assert(csi2rx->sys_rst);
+ 	clk_disable_unprepare(csi2rx->sys_clk);
+ 
+ 	for (i = 0; i < csi2rx->max_streams; i++) {
+ 		writel(0, csi2rx->base + CSI2RX_STREAM_CTRL_REG(i));
+ 
++		reset_control_assert(csi2rx->pixel_rst[i]);
+ 		clk_disable_unprepare(csi2rx->pixel_clk[i]);
+ 	}
+ 
++	reset_control_assert(csi2rx->p_rst);
+ 	clk_disable_unprepare(csi2rx->p_clk);
+ 
+ 	if (v4l2_subdev_call(csi2rx->source_subdev, video, s_stream, false))
+@@ -299,6 +312,16 @@ static int csi2rx_get_resources(struct c
+ 		return PTR_ERR(csi2rx->p_clk);
+ 	}
+ 
++	csi2rx->sys_rst = devm_reset_control_get_optional_exclusive(&pdev->dev,
++								    "sys");
++	if (IS_ERR(csi2rx->sys_rst))
++		return PTR_ERR(csi2rx->sys_rst);
++
++	csi2rx->p_rst = devm_reset_control_get_optional_exclusive(&pdev->dev,
++								  "reg_bank");
++	if (IS_ERR(csi2rx->p_rst))
++		return PTR_ERR(csi2rx->p_rst);
++
+ 	csi2rx->dphy = devm_phy_optional_get(&pdev->dev, "dphy");
+ 	if (IS_ERR(csi2rx->dphy)) {
+ 		dev_err(&pdev->dev, "Couldn't get external D-PHY\n");
+@@ -349,14 +372,21 @@ static int csi2rx_get_resources(struct c
+ 	}
+ 
+ 	for (i = 0; i < csi2rx->max_streams; i++) {
+-		char clk_name[16];
++		char name[16];
+ 
+-		snprintf(clk_name, sizeof(clk_name), "pixel_if%u_clk", i);
+-		csi2rx->pixel_clk[i] = devm_clk_get(&pdev->dev, clk_name);
++		snprintf(name, sizeof(name), "pixel_if%u_clk", i);
++		csi2rx->pixel_clk[i] = devm_clk_get(&pdev->dev, name);
+ 		if (IS_ERR(csi2rx->pixel_clk[i])) {
+-			dev_err(&pdev->dev, "Couldn't get clock %s\n", clk_name);
++			dev_err(&pdev->dev, "Couldn't get clock %s\n", name);
+ 			return PTR_ERR(csi2rx->pixel_clk[i]);
+ 		}
++
++		snprintf(name, sizeof(name), "pixel_if%u", i);
++		csi2rx->pixel_rst[i] =
++			devm_reset_control_get_optional_exclusive(&pdev->dev,
++								  name);
++		if (IS_ERR(csi2rx->pixel_rst[i]))
++			return PTR_ERR(csi2rx->pixel_rst[i]);
+ 	}
+ 
+ 	return 0;

+ 141 - 0
target/linux/starfive/patches-6.1/0079-media-cadence-Add-support-for-external-dphy.patch

@@ -0,0 +1,141 @@
+From e97eb58b321b5b25b7d5c40880e6eb133d381581 Mon Sep 17 00:00:00 2001
+From: Jack Zhu <[email protected]>
+Date: Tue, 23 May 2023 16:56:25 +0800
+Subject: [PATCH 079/122] media: cadence: Add support for external dphy
+
+Add support for external MIPI D-PHY.
+
+Reviewed-by: Laurent Pinchart <[email protected]>
+Signed-off-by: Jack Zhu <[email protected]>
+---
+ drivers/media/platform/cadence/cdns-csi2rx.c | 66 +++++++++++++++++---
+ 1 file changed, 56 insertions(+), 10 deletions(-)
+
+--- a/drivers/media/platform/cadence/cdns-csi2rx.c
++++ b/drivers/media/platform/cadence/cdns-csi2rx.c
+@@ -31,6 +31,12 @@
+ #define CSI2RX_STATIC_CFG_DLANE_MAP(llane, plane)	((plane) << (16 + (llane) * 4))
+ #define CSI2RX_STATIC_CFG_LANES_MASK			GENMASK(11, 8)
+ 
++#define CSI2RX_DPHY_LANE_CTRL_REG		0x40
++#define CSI2RX_DPHY_CL_RST			BIT(16)
++#define CSI2RX_DPHY_DL_RST(i)			BIT((i) + 12)
++#define CSI2RX_DPHY_CL_EN			BIT(4)
++#define CSI2RX_DPHY_DL_EN(i)			BIT(i)
++
+ #define CSI2RX_STREAM_BASE(n)		(((n) + 1) * 0x100)
+ 
+ #define CSI2RX_STREAM_CTRL_REG(n)		(CSI2RX_STREAM_BASE(n) + 0x000)
+@@ -105,6 +111,24 @@ static void csi2rx_reset(struct csi2rx_p
+ 	writel(0, csi2rx->base + CSI2RX_SOFT_RESET_REG);
+ }
+ 
++static int csi2rx_configure_ext_dphy(struct csi2rx_priv *csi2rx)
++{
++	union phy_configure_opts opts = { };
++	int ret;
++
++	ret = phy_power_on(csi2rx->dphy);
++	if (ret)
++		return ret;
++
++	ret = phy_configure(csi2rx->dphy, &opts);
++	if (ret) {
++		phy_power_off(csi2rx->dphy);
++		return ret;
++	}
++
++	return 0;
++}
++
+ static int csi2rx_start(struct csi2rx_priv *csi2rx)
+ {
+ 	unsigned int i;
+@@ -144,6 +168,17 @@ static int csi2rx_start(struct csi2rx_pr
+ 	if (ret)
+ 		goto err_disable_pclk;
+ 
++	/* Enable DPHY clk and data lanes. */
++	if (csi2rx->dphy) {
++		reg = CSI2RX_DPHY_CL_EN | CSI2RX_DPHY_CL_RST;
++		for (i = 0; i < csi2rx->num_lanes; i++) {
++			reg |= CSI2RX_DPHY_DL_EN(csi2rx->lanes[i] - 1);
++			reg |= CSI2RX_DPHY_DL_RST(csi2rx->lanes[i] - 1);
++		}
++
++		writel(reg, csi2rx->base + CSI2RX_DPHY_LANE_CTRL_REG);
++	}
++
+ 	/*
+ 	 * Create a static mapping between the CSI virtual channels
+ 	 * and the output stream.
+@@ -177,10 +212,22 @@ static int csi2rx_start(struct csi2rx_pr
+ 		goto err_disable_pixclk;
+ 
+ 	reset_control_deassert(csi2rx->sys_rst);
++
++	if (csi2rx->dphy) {
++		ret = csi2rx_configure_ext_dphy(csi2rx);
++		if (ret) {
++			dev_err(csi2rx->dev,
++				"Failed to configure external DPHY: %d\n", ret);
++			goto err_disable_sysclk;
++		}
++	}
++
+ 	clk_disable_unprepare(csi2rx->p_clk);
+ 
+ 	return 0;
+ 
++err_disable_sysclk:
++	clk_disable_unprepare(csi2rx->sys_clk);
+ err_disable_pixclk:
+ 	for (; i > 0; i--) {
+ 		reset_control_assert(csi2rx->pixel_rst[i - 1]);
+@@ -213,6 +260,13 @@ static void csi2rx_stop(struct csi2rx_pr
+ 
+ 	if (v4l2_subdev_call(csi2rx->source_subdev, video, s_stream, false))
+ 		dev_warn(csi2rx->dev, "Couldn't disable our subdev\n");
++
++	if (csi2rx->dphy) {
++		writel(0, csi2rx->base + CSI2RX_DPHY_LANE_CTRL_REG);
++
++		if (phy_power_off(csi2rx->dphy))
++			dev_warn(csi2rx->dev, "Couldn't power off DPHY\n");
++	}
+ }
+ 
+ static int csi2rx_s_stream(struct v4l2_subdev *subdev, int enable)
+@@ -328,15 +382,6 @@ static int csi2rx_get_resources(struct c
+ 		return PTR_ERR(csi2rx->dphy);
+ 	}
+ 
+-	/*
+-	 * FIXME: Once we'll have external D-PHY support, the check
+-	 * will need to be removed.
+-	 */
+-	if (csi2rx->dphy) {
+-		dev_err(&pdev->dev, "External D-PHY not supported yet\n");
+-		return -EINVAL;
+-	}
+-
+ 	ret = clk_prepare_enable(csi2rx->p_clk);
+ 	if (ret) {
+ 		dev_err(&pdev->dev, "Couldn't prepare and enable P clock\n");
+@@ -366,7 +411,7 @@ static int csi2rx_get_resources(struct c
+ 	 * FIXME: Once we'll have internal D-PHY support, the check
+ 	 * will need to be removed.
+ 	 */
+-	if (csi2rx->has_internal_dphy) {
++	if (!csi2rx->dphy && csi2rx->has_internal_dphy) {
+ 		dev_err(&pdev->dev, "Internal D-PHY not supported yet\n");
+ 		return -EINVAL;
+ 	}
+@@ -494,6 +539,7 @@ static int csi2rx_probe(struct platform_
+ 	dev_info(&pdev->dev,
+ 		 "Probed CSI2RX with %u/%u lanes, %u streams, %s D-PHY\n",
+ 		 csi2rx->num_lanes, csi2rx->max_lanes, csi2rx->max_streams,
++		 csi2rx->dphy ? "external" :
+ 		 csi2rx->has_internal_dphy ? "internal" : "no");
+ 
+ 	return 0;

+ 23 - 0
target/linux/starfive/patches-6.1/0080-media-cadence-Add-support-for-JH7110-SoC.patch

@@ -0,0 +1,23 @@
+From d541f0ab42983dbc856f2229ee471677e80945a3 Mon Sep 17 00:00:00 2001
+From: Jack Zhu <[email protected]>
+Date: Tue, 23 May 2023 16:56:26 +0800
+Subject: [PATCH 080/122] media: cadence: Add support for JH7110 SoC
+
+Add support for Starfive JH7110 SoC which has the cadence csi2 receiver.
+
+Reviewed-by: Laurent Pinchart <[email protected]>
+Signed-off-by: Jack Zhu <[email protected]>
+---
+ drivers/media/platform/cadence/cdns-csi2rx.c | 1 +
+ 1 file changed, 1 insertion(+)
+
+--- a/drivers/media/platform/cadence/cdns-csi2rx.c
++++ b/drivers/media/platform/cadence/cdns-csi2rx.c
+@@ -565,6 +565,7 @@ static int csi2rx_remove(struct platform
+ }
+ 
+ static const struct of_device_id csi2rx_of_table[] = {
++	{ .compatible = "starfive,jh7110-csi2rx" },
+ 	{ .compatible = "cdns,csi2rx" },
+ 	{ },
+ };

+ 197 - 0
target/linux/starfive/patches-6.1/0081-media-dt-bindings-Add-JH7110-Camera-Subsystem.patch

@@ -0,0 +1,197 @@
+From f3195b45a3845fd3892ca932a9cc8e352942dbcd Mon Sep 17 00:00:00 2001
+From: Jack Zhu <[email protected]>
+Date: Fri, 12 May 2023 18:28:39 +0800
+Subject: [PATCH 081/122] media: dt-bindings: Add JH7110 Camera Subsystem
+
+Add the bindings documentation for Starfive JH7110 Camera Subsystem
+which is used for handing image sensor data.
+
+Reviewed-by: Krzysztof Kozlowski <[email protected]>
+Signed-off-by: Jack Zhu <[email protected]>
+---
+ .../bindings/media/starfive,jh7110-camss.yaml | 179 ++++++++++++++++++
+ 1 file changed, 179 insertions(+)
+ create mode 100644 Documentation/devicetree/bindings/media/starfive,jh7110-camss.yaml
+
+--- /dev/null
++++ b/Documentation/devicetree/bindings/media/starfive,jh7110-camss.yaml
+@@ -0,0 +1,179 @@
++# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause)
++%YAML 1.2
++---
++$id: http://devicetree.org/schemas/media/starfive,jh7110-camss.yaml#
++$schema: http://devicetree.org/meta-schemas/core.yaml#
++
++title: Starfive SoC CAMSS ISP
++
++maintainers:
++  - Jack Zhu <[email protected]>
++  - Changhuang Liang <[email protected]>
++
++description:
++  The Starfive CAMSS ISP is a Camera interface for Starfive JH7110 SoC. It
++  consists of a VIN controller (Video In Controller, a top-level control until)
++  and an ISP.
++
++properties:
++  compatible:
++    const: starfive,jh7110-camss
++
++  reg:
++    maxItems: 2
++
++  reg-names:
++    items:
++      - const: syscon
++      - const: isp
++
++  clocks:
++    maxItems: 7
++
++  clock-names:
++    items:
++      - const: apb_func
++      - const: wrapper_clk_c
++      - const: dvp_inv
++      - const: axiwr
++      - const: mipi_rx0_pxl
++      - const: ispcore_2x
++      - const: isp_axi
++
++  resets:
++    maxItems: 6
++
++  reset-names:
++    items:
++      - const: wrapper_p
++      - const: wrapper_c
++      - const: axird
++      - const: axiwr
++      - const: isp_top_n
++      - const: isp_top_axi
++
++  power-domains:
++    items:
++      - description: JH7110 ISP Power Domain Switch Controller.
++
++  interrupts:
++    maxItems: 4
++
++  ports:
++    $ref: /schemas/graph.yaml#/properties/ports
++
++    properties:
++      port@0:
++        $ref: /schemas/graph.yaml#/$defs/port-base
++        unevaluatedProperties: false
++        description: Input port for receiving DVP data.
++
++        properties:
++          endpoint:
++            $ref: video-interfaces.yaml#
++            unevaluatedProperties: false
++
++            properties:
++              bus-type:
++                enum: [5, 6]
++
++              bus-width:
++                enum: [8, 10, 12]
++
++              data-shift:
++                enum: [0, 2]
++                default: 0
++
++              hsync-active:
++                enum: [0, 1]
++                default: 1
++
++              vsync-active:
++                enum: [0, 1]
++                default: 1
++
++            required:
++              - bus-type
++              - bus-width
++
++      port@1:
++        $ref: /schemas/graph.yaml#/properties/port
++        description: Input port for receiving CSI data.
++
++    required:
++      - port@0
++      - port@1
++
++required:
++  - compatible
++  - reg
++  - reg-names
++  - clocks
++  - clock-names
++  - resets
++  - reset-names
++  - power-domains
++  - interrupts
++  - ports
++
++additionalProperties: false
++
++examples:
++  - |
++    isp@19840000 {
++        compatible = "starfive,jh7110-camss";
++        reg = <0x19840000 0x10000>,
++              <0x19870000 0x30000>;
++        reg-names = "syscon", "isp";
++        clocks = <&ispcrg 0>,
++                 <&ispcrg 13>,
++                 <&ispcrg 2>,
++                 <&ispcrg 12>,
++                 <&ispcrg 1>,
++                 <&syscrg 51>,
++                 <&syscrg 52>;
++        clock-names = "apb_func",
++                      "wrapper_clk_c",
++                      "dvp_inv",
++                      "axiwr",
++                      "mipi_rx0_pxl",
++                      "ispcore_2x",
++                      "isp_axi";
++        resets = <&ispcrg 0>,
++                 <&ispcrg 1>,
++                 <&ispcrg 10>,
++                 <&ispcrg 11>,
++                 <&syscrg 41>,
++                 <&syscrg 42>;
++        reset-names = "wrapper_p",
++                      "wrapper_c",
++                      "axird",
++                      "axiwr",
++                      "isp_top_n",
++                      "isp_top_axi";
++        power-domains = <&pwrc 5>;
++        interrupts = <92>, <87>, <88>, <90>;
++
++        ports {
++            #address-cells = <1>;
++            #size-cells = <0>;
++            port@0 {
++                reg = <0>;
++                vin_from_sc2235: endpoint {
++                    remote-endpoint = <&sc2235_to_vin>;
++                    bus-width = <8>;
++                    data-shift = <2>;
++                    hsync-active = <1>;
++                    vsync-active = <0>;
++                    pclk-sample = <1>;
++                };
++            };
++
++            port@1 {
++                reg = <1>;
++                vin_from_csi2rx: endpoint {
++                    remote-endpoint = <&csi2rx_to_vin>;
++                };
++            };
++        };
++    };

+ 106 - 0
target/linux/starfive/patches-6.1/0082-media-admin-guide-Add-starfive_camss.rst-for-Starfiv.patch

@@ -0,0 +1,106 @@
+From 949807343300a75b6e7c3e47463f817a7b6bc790 Mon Sep 17 00:00:00 2001
+From: Jack Zhu <[email protected]>
+Date: Fri, 12 May 2023 18:28:40 +0800
+Subject: [PATCH 082/122] media: admin-guide: Add starfive_camss.rst for
+ Starfive Camera Subsystem
+
+Add starfive_camss.rst file that documents the Starfive Camera
+Subsystem driver which is used for handing image sensor data.
+
+Signed-off-by: Jack Zhu <[email protected]>
+---
+ .../admin-guide/media/starfive_camss.rst      | 57 +++++++++++++++++++
+ .../media/starfive_camss_graph.dot            | 16 ++++++
+ .../admin-guide/media/v4l-drivers.rst         |  1 +
+ 3 files changed, 74 insertions(+)
+ create mode 100644 Documentation/admin-guide/media/starfive_camss.rst
+ create mode 100644 Documentation/admin-guide/media/starfive_camss_graph.dot
+
+--- /dev/null
++++ b/Documentation/admin-guide/media/starfive_camss.rst
+@@ -0,0 +1,57 @@
++.. SPDX-License-Identifier: GPL-2.0
++
++.. include:: <isonum.txt>
++
++================================
++Starfive Camera Subsystem driver
++================================
++
++Introduction
++------------
++
++This file documents the driver for the Starfive Camera Subsystem found on
++Starfive JH7110 SoC. The driver is located under drivers/media/platform/
++starfive.
++
++The driver implements V4L2, Media controller and v4l2_subdev interfaces.
++Camera sensor using V4L2 subdev interface in the kernel is supported.
++
++The driver has been successfully used on the Gstreamer 1.18.5 with
++v4l2src plugin.
++
++
++Starfive Camera Subsystem hardware
++----------------------------------
++
++The Starfive Camera Subsystem hardware consists of:
++
++- MIPI DPHY Receiver: receives mipi data from a MIPI camera sensor.
++- MIPI CSIRx Controller: is responsible for handling and decoding CSI2 protocol
++  based camera sensor data stream.
++- ISP: handles the image data streams from the MIPI CSIRx Controller.
++- VIN(Video In): a top-level module, is responsible for controlling power
++  and clocks to other modules, dumps the input data to memory or transfers the
++  input data to ISP.
++
++
++Topology
++--------
++
++The media controller pipeline graph is as follows:
++
++.. _starfive_camss_graph:
++
++.. kernel-figure:: starfive_camss_graph.dot
++    :alt:   starfive_camss_graph.dot
++    :align: center
++
++The driver has 2 video devices:
++
++- stf_vin0_wr_video0: capture device for images directly from the VIN module.
++- stf_vin0_isp0_video1: capture device for images without scaling.
++
++The driver has 3 subdevices:
++
++- stf_isp0: is responsible for all the isp operations.
++- stf_vin0_wr: used to dump RAW images to memory.
++- stf_vin0_isp0: used to capture images for the stf_vin0_isp0_video1 device.
+--- /dev/null
++++ b/Documentation/admin-guide/media/starfive_camss_graph.dot
+@@ -0,0 +1,16 @@
++digraph board {
++	rankdir=TB
++	n00000001 [label="{{<port0> 0} | stf_isp0\n/dev/v4l-subdev0 | {<port1> 1}}", shape=Mrecord, style=filled, fillcolor=green]
++	n00000001:port1 -> n0000000d:port0
++	n00000004 [label="{{<port0> 0} | stf_vin0_wr\n/dev/v4l-subdev1 | {<port1> 1}}", shape=Mrecord, style=filled, fillcolor=green]
++	n00000004:port1 -> n00000007 [style=bold]
++	n00000007 [label="stf_vin0_wr_video0\n/dev/video0", shape=box, style=filled, fillcolor=yellow]
++	n0000000d [label="{{<port0> 0} | stf_vin0_isp0\n/dev/v4l-subdev2 | {<port1> 1}}", shape=Mrecord, style=filled, fillcolor=green]
++	n0000000d:port1 -> n00000010 [style=bold]
++	n00000010 [label="stf_vin0_isp0_video1\n/dev/video1", shape=box, style=filled, fillcolor=yellow]
++	n00000018 [label="{{<port0> 0} | cdns_csi2rx.19800000.csi-bridge\n | {<port1> 1 | <port2> 2 | <port3> 3 | <port4> 4}}", shape=Mrecord, style=filled, fillcolor=green]
++	n00000018:port1 -> n00000004:port0 [style=dashed]
++	n00000018:port1 -> n00000001:port0
++	n00000028 [label="{{} | imx219 6-0010\n | {<port0> 0}}", shape=Mrecord, style=filled, fillcolor=green]
++	n00000028:port0 -> n00000018:port0 [style=bold]
++}
+--- a/Documentation/admin-guide/media/v4l-drivers.rst
++++ b/Documentation/admin-guide/media/v4l-drivers.rst
+@@ -30,5 +30,6 @@ Video4Linux (V4L) driver-specific docume
+ 	si470x
+ 	si4713
+ 	si476x
++	starfive_camss
+ 	vimc
+ 	vivid

+ 630 - 0
target/linux/starfive/patches-6.1/0083-media-starfive-Add-basic-driver.patch

@@ -0,0 +1,630 @@
+From 0dc93c9321ba947ac429baeb58202496e4b0f219 Mon Sep 17 00:00:00 2001
+From: Jack Zhu <[email protected]>
+Date: Fri, 12 May 2023 18:28:41 +0800
+Subject: [PATCH 083/122] media: starfive: Add basic driver
+
+Add basic platform driver for StarFive Camera Subsystem.
+
+Signed-off-by: Jack Zhu <[email protected]>
+Reviewed-by: Bryan O'Donoghue <[email protected]>
+---
+ drivers/media/platform/Kconfig               |   1 +
+ drivers/media/platform/Makefile              |   1 +
+ drivers/media/platform/starfive/Kconfig      |  19 +
+ drivers/media/platform/starfive/Makefile     |   9 +
+ drivers/media/platform/starfive/stf_camss.c  | 372 +++++++++++++++++++
+ drivers/media/platform/starfive/stf_camss.h  | 153 ++++++++
+ drivers/media/platform/starfive/stf_common.h |  18 +
+ 7 files changed, 573 insertions(+)
+ create mode 100644 drivers/media/platform/starfive/Kconfig
+ create mode 100644 drivers/media/platform/starfive/Makefile
+ create mode 100644 drivers/media/platform/starfive/stf_camss.c
+ create mode 100644 drivers/media/platform/starfive/stf_camss.h
+ create mode 100644 drivers/media/platform/starfive/stf_common.h
+
+--- a/drivers/media/platform/Kconfig
++++ b/drivers/media/platform/Kconfig
+@@ -79,6 +79,7 @@ source "drivers/media/platform/renesas/K
+ source "drivers/media/platform/rockchip/Kconfig"
+ source "drivers/media/platform/samsung/Kconfig"
+ source "drivers/media/platform/st/Kconfig"
++source "drivers/media/platform/starfive/Kconfig"
+ source "drivers/media/platform/sunxi/Kconfig"
+ source "drivers/media/platform/ti/Kconfig"
+ source "drivers/media/platform/verisilicon/Kconfig"
+--- a/drivers/media/platform/Makefile
++++ b/drivers/media/platform/Makefile
+@@ -22,6 +22,7 @@ obj-y += renesas/
+ obj-y += rockchip/
+ obj-y += samsung/
+ obj-y += st/
++obj-y += starfive/
+ obj-y += sunxi/
+ obj-y += ti/
+ obj-y += verisilicon/
+--- /dev/null
++++ b/drivers/media/platform/starfive/Kconfig
+@@ -0,0 +1,19 @@
++# SPDX-License-Identifier: GPL-2.0-only
++
++comment "Starfive media platform drivers"
++
++config VIDEO_STARFIVE_CAMSS
++	tristate "Starfive Camera Subsystem driver"
++	depends on V4L_PLATFORM_DRIVERS
++	depends on VIDEO_DEV && OF
++	depends on DMA_CMA
++	select MEDIA_CONTROLLER
++	select VIDEO_V4L2_SUBDEV_API
++	select VIDEOBUF2_DMA_CONTIG
++	select V4L2_FWNODE
++	help
++	   Enable this to support for the Starfive Camera subsystem
++	   found on Starfive JH7110 SoC.
++
++	   To compile this driver as a module, choose M here: the
++	   module will be called stf-camss.
+--- /dev/null
++++ b/drivers/media/platform/starfive/Makefile
+@@ -0,0 +1,9 @@
++# SPDX-License-Identifier: GPL-2.0
++#
++# Makefile for StarFive camera subsystem driver.
++#
++
++starfive-camss-objs += \
++		stf_camss.o
++
++obj-$(CONFIG_VIDEO_STARFIVE_CAMSS) += starfive-camss.o \
+--- /dev/null
++++ b/drivers/media/platform/starfive/stf_camss.c
+@@ -0,0 +1,372 @@
++// SPDX-License-Identifier: GPL-2.0
++/*
++ * stf_camss.c
++ *
++ * Starfive Camera Subsystem driver
++ *
++ * Copyright (C) 2021-2023 StarFive Technology Co., Ltd.
++ */
++#include <linux/module.h>
++#include <linux/of.h>
++#include <linux/of_graph.h>
++#include <linux/platform_device.h>
++#include <linux/pm_runtime.h>
++#include <linux/videodev2.h>
++#include <media/media-device.h>
++#include <media/v4l2-async.h>
++#include <media/v4l2-fwnode.h>
++#include <media/v4l2-mc.h>
++
++#include "stf_camss.h"
++
++static const char * const stfcamss_clocks[] = {
++	"clk_apb_func",
++	"clk_wrapper_clk_c",
++	"clk_dvp_inv",
++	"clk_axiwr",
++	"clk_mipi_rx0_pxl",
++	"clk_ispcore_2x",
++	"clk_isp_axi",
++};
++
++static const char * const stfcamss_resets[] = {
++	"rst_wrapper_p",
++	"rst_wrapper_c",
++	"rst_axird",
++	"rst_axiwr",
++	"rst_isp_top_n",
++	"rst_isp_top_axi",
++};
++
++static int stfcamss_get_mem_res(struct platform_device *pdev,
++				struct stfcamss *stfcamss)
++{
++	stfcamss->syscon_base =
++		devm_platform_ioremap_resource_byname(pdev, "syscon");
++	if (IS_ERR(stfcamss->syscon_base))
++		return PTR_ERR(stfcamss->syscon_base);
++
++	stfcamss->isp_base =
++		devm_platform_ioremap_resource_byname(pdev, "isp");
++	if (IS_ERR(stfcamss->isp_base))
++		return PTR_ERR(stfcamss->isp_base);
++
++	return 0;
++}
++
++/*
++ * stfcamss_of_parse_endpoint_node - Parse port endpoint node
++ * @dev: Device
++ * @node: Device node to be parsed
++ * @csd: Parsed data from port endpoint node
++ *
++ * Return 0 on success or a negative error code on failure
++ */
++static int stfcamss_of_parse_endpoint_node(struct device *dev,
++					   struct device_node *node,
++					   struct stfcamss_async_subdev *csd)
++{
++	struct v4l2_fwnode_endpoint vep = { { 0 } };
++
++	v4l2_fwnode_endpoint_parse(of_fwnode_handle(node), &vep);
++	dev_dbg(dev, "vep.base.port = 0x%x, id = 0x%x\n",
++		vep.base.port, vep.base.id);
++
++	csd->port = vep.base.port;
++
++	return 0;
++}
++
++/*
++ * stfcamss_of_parse_ports - Parse ports node
++ * @stfcamss: STFCAMSS device
++ *
++ * Return number of "port" nodes found in "ports" node
++ */
++static int stfcamss_of_parse_ports(struct stfcamss *stfcamss)
++{
++	struct device *dev = stfcamss->dev;
++	struct device_node *node = NULL;
++	struct device_node *remote = NULL;
++	int ret, num_subdevs = 0;
++
++	for_each_endpoint_of_node(dev->of_node, node) {
++		struct stfcamss_async_subdev *csd;
++
++		if (!of_device_is_available(node))
++			continue;
++
++		remote = of_graph_get_remote_port_parent(node);
++		if (!remote) {
++			dev_err(dev, "Cannot get remote parent\n");
++			ret = -EINVAL;
++			goto err_cleanup;
++		}
++
++		csd = v4l2_async_nf_add_fwnode(&stfcamss->notifier,
++					       of_fwnode_handle(remote),
++					       struct stfcamss_async_subdev);
++		of_node_put(remote);
++		if (IS_ERR(csd)) {
++			ret = PTR_ERR(csd);
++			goto err_cleanup;
++		}
++
++		ret = stfcamss_of_parse_endpoint_node(dev, node, csd);
++		if (ret < 0)
++			goto err_cleanup;
++
++		num_subdevs++;
++	}
++
++	return num_subdevs;
++
++err_cleanup:
++	of_node_put(node);
++	return ret;
++}
++
++static int stfcamss_subdev_notifier_bound(struct v4l2_async_notifier *async,
++					  struct v4l2_subdev *subdev,
++					  struct v4l2_async_subdev *asd)
++{
++	struct stfcamss *stfcamss =
++		container_of(async, struct stfcamss, notifier);
++	struct host_data *host_data = &stfcamss->host_data;
++	struct media_entity *source;
++	int i, j;
++
++	source = &subdev->entity;
++
++	for (i = 0; i < source->num_pads; i++) {
++		if (source->pads[i].flags & MEDIA_PAD_FL_SOURCE)
++			break;
++	}
++
++	if (i == source->num_pads) {
++		dev_err(stfcamss->dev, "No source pad in external entity\n");
++		return -EINVAL;
++	}
++
++	for (j = 0; host_data->host_entity[j] && (j < HOST_ENTITY_MAX); j++) {
++		struct media_entity *input;
++		int ret;
++
++		input = host_data->host_entity[j];
++
++		ret = media_create_pad_link(
++			source,
++			i,
++			input,
++			STF_PAD_SINK,
++			source->function == MEDIA_ENT_F_CAM_SENSOR ?
++			MEDIA_LNK_FL_IMMUTABLE | MEDIA_LNK_FL_ENABLED :
++			0);
++		if (ret < 0) {
++			dev_err(stfcamss->dev,
++				"Failed to link %s->%s entities: %d\n",
++				source->name, input->name, ret);
++			return ret;
++		}
++	}
++
++	return 0;
++}
++
++static int stfcamss_subdev_notifier_complete(struct v4l2_async_notifier *ntf)
++{
++	struct stfcamss *stfcamss =
++		container_of(ntf, struct stfcamss, notifier);
++
++	return v4l2_device_register_subdev_nodes(&stfcamss->v4l2_dev);
++}
++
++static const struct v4l2_async_notifier_operations
++stfcamss_subdev_notifier_ops = {
++	.bound = stfcamss_subdev_notifier_bound,
++	.complete = stfcamss_subdev_notifier_complete,
++};
++
++static const struct media_device_ops stfcamss_media_ops = {
++	.link_notify = v4l2_pipeline_link_notify,
++};
++
++static void stfcamss_mc_init(struct platform_device *pdev,
++			     struct stfcamss *stfcamss)
++{
++	stfcamss->media_dev.dev = stfcamss->dev;
++	strscpy(stfcamss->media_dev.model, "Starfive Camera Subsystem",
++		sizeof(stfcamss->media_dev.model));
++	snprintf(stfcamss->media_dev.bus_info,
++		 sizeof(stfcamss->media_dev.bus_info),
++		 "%s:%s", dev_bus_name(&pdev->dev), pdev->name);
++	stfcamss->media_dev.hw_revision = 0x01;
++	stfcamss->media_dev.ops = &stfcamss_media_ops;
++	media_device_init(&stfcamss->media_dev);
++
++	stfcamss->v4l2_dev.mdev = &stfcamss->media_dev;
++}
++
++/*
++ * stfcamss_probe - Probe STFCAMSS platform device
++ * @pdev: Pointer to STFCAMSS platform device
++ *
++ * Return 0 on success or a negative error code on failure
++ */
++static int stfcamss_probe(struct platform_device *pdev)
++{
++	struct stfcamss *stfcamss;
++	struct device *dev = &pdev->dev;
++	int ret = 0, i, num_subdevs;
++
++	stfcamss = devm_kzalloc(dev, sizeof(*stfcamss), GFP_KERNEL);
++	if (!stfcamss)
++		return -ENOMEM;
++
++	for (i = 0; i < ARRAY_SIZE(stfcamss->irq); ++i) {
++		stfcamss->irq[i] = platform_get_irq(pdev, i);
++		if (stfcamss->irq[i] < 0)
++			return dev_err_probe(&pdev->dev, stfcamss->irq[i],
++					     "Failed to get clock%d", i);
++	}
++
++	stfcamss->nclks = ARRAY_SIZE(stfcamss->sys_clk);
++	for (i = 0; i < ARRAY_SIZE(stfcamss->sys_clk); ++i)
++		stfcamss->sys_clk[i].id = stfcamss_clocks[i];
++	ret = devm_clk_bulk_get(dev, stfcamss->nclks, stfcamss->sys_clk);
++	if (ret) {
++		dev_err(dev, "Failed to get clk controls\n");
++		return ret;
++	}
++
++	stfcamss->nrsts = ARRAY_SIZE(stfcamss->sys_rst);
++	for (i = 0; i < ARRAY_SIZE(stfcamss->sys_rst); ++i)
++		stfcamss->sys_rst[i].id = stfcamss_resets[i];
++	ret = devm_reset_control_bulk_get_shared(dev, stfcamss->nrsts,
++						 stfcamss->sys_rst);
++	if (ret) {
++		dev_err(dev, "Failed to get reset controls\n");
++		return ret;
++	}
++
++	ret = stfcamss_get_mem_res(pdev, stfcamss);
++	if (ret) {
++		dev_err(dev, "Could not map registers\n");
++		return ret;
++	}
++
++	stfcamss->dev = dev;
++	platform_set_drvdata(pdev, stfcamss);
++
++	v4l2_async_nf_init(&stfcamss->notifier);
++
++	num_subdevs = stfcamss_of_parse_ports(stfcamss);
++	if (num_subdevs < 0) {
++		dev_err(dev, "Failed to find subdevices\n");
++		return -ENODEV;
++	}
++
++	stfcamss_mc_init(pdev, stfcamss);
++
++	ret = v4l2_device_register(stfcamss->dev, &stfcamss->v4l2_dev);
++	if (ret < 0) {
++		dev_err(dev, "Failed to register V4L2 device: %d\n", ret);
++		goto err_cleanup_notifier;
++	}
++
++	ret = media_device_register(&stfcamss->media_dev);
++	if (ret) {
++		dev_err(dev, "Failed to register media device: %d\n", ret);
++		goto err_unregister_device;
++	}
++
++	stfcamss->notifier.ops = &stfcamss_subdev_notifier_ops;
++	ret = v4l2_async_nf_register(&stfcamss->v4l2_dev, &stfcamss->notifier);
++	if (ret) {
++		dev_err(dev, "Failed to register async subdev nodes: %d\n",
++			ret);
++		goto err_unregister_media_dev;
++	}
++
++	pm_runtime_enable(dev);
++
++	return 0;
++
++err_unregister_media_dev:
++	media_device_unregister(&stfcamss->media_dev);
++err_unregister_device:
++	v4l2_device_unregister(&stfcamss->v4l2_dev);
++err_cleanup_notifier:
++	v4l2_async_nf_cleanup(&stfcamss->notifier);
++	return ret;
++}
++
++/*
++ * stfcamss_remove - Remove STFCAMSS platform device
++ * @pdev: Pointer to STFCAMSS platform device
++ *
++ * Always returns 0.
++ */
++static int stfcamss_remove(struct platform_device *pdev)
++{
++	struct stfcamss *stfcamss = platform_get_drvdata(pdev);
++
++	v4l2_device_unregister(&stfcamss->v4l2_dev);
++	media_device_cleanup(&stfcamss->media_dev);
++	pm_runtime_disable(&pdev->dev);
++
++	return 0;
++}
++
++static const struct of_device_id stfcamss_of_match[] = {
++	{ .compatible = "starfive,jh7110-camss" },
++	{ /* sentinel */ },
++};
++
++MODULE_DEVICE_TABLE(of, stfcamss_of_match);
++
++static int __maybe_unused stfcamss_runtime_suspend(struct device *dev)
++{
++	struct stfcamss *stfcamss = dev_get_drvdata(dev);
++
++	reset_control_assert(stfcamss->sys_rst[STF_RST_ISP_TOP_AXI].rstc);
++	reset_control_assert(stfcamss->sys_rst[STF_RST_ISP_TOP_N].rstc);
++	clk_disable_unprepare(stfcamss->sys_clk[STF_CLK_ISP_AXI].clk);
++	clk_disable_unprepare(stfcamss->sys_clk[STF_CLK_ISPCORE_2X].clk);
++
++	return 0;
++}
++
++static int __maybe_unused stfcamss_runtime_resume(struct device *dev)
++{
++	struct stfcamss *stfcamss = dev_get_drvdata(dev);
++
++	clk_prepare_enable(stfcamss->sys_clk[STF_CLK_ISPCORE_2X].clk);
++	clk_prepare_enable(stfcamss->sys_clk[STF_CLK_ISP_AXI].clk);
++	reset_control_deassert(stfcamss->sys_rst[STF_RST_ISP_TOP_N].rstc);
++	reset_control_deassert(stfcamss->sys_rst[STF_RST_ISP_TOP_AXI].rstc);
++
++	return 0;
++}
++
++static const struct dev_pm_ops stfcamss_pm_ops = {
++	SET_RUNTIME_PM_OPS(stfcamss_runtime_suspend,
++			   stfcamss_runtime_resume,
++			   NULL)
++};
++
++static struct platform_driver stfcamss_driver = {
++	.probe = stfcamss_probe,
++	.remove = stfcamss_remove,
++	.driver = {
++		.name = DRV_NAME,
++		.pm = &stfcamss_pm_ops,
++		.of_match_table = of_match_ptr(stfcamss_of_match),
++	},
++};
++
++module_platform_driver(stfcamss_driver);
++
++MODULE_AUTHOR("StarFive Corporation");
++MODULE_DESCRIPTION("StarFive Camera Subsystem driver");
++MODULE_LICENSE("GPL");
+--- /dev/null
++++ b/drivers/media/platform/starfive/stf_camss.h
+@@ -0,0 +1,153 @@
++/* SPDX-License-Identifier: GPL-2.0 */
++/*
++ * stf_camss.h
++ *
++ * Starfive Camera Subsystem driver
++ *
++ * Copyright (C) 2021-2023 StarFive Technology Co., Ltd.
++ */
++
++#ifndef STF_CAMSS_H
++#define STF_CAMSS_H
++
++#include <linux/clk.h>
++#include <linux/delay.h>
++#include <linux/reset.h>
++#include <media/v4l2-device.h>
++
++#include "stf_common.h"
++
++#define DRV_NAME     "starfive-camss"
++#define STF_DVP_NAME "stf_dvp"
++#define STF_CSI_NAME "cdns_csi2rx"
++#define STF_ISP_NAME "stf_isp"
++#define STF_VIN_NAME "stf_vin"
++
++#define STF_PAD_SINK   0
++#define STF_PAD_SRC    1
++#define STF_PADS_NUM   2
++
++enum port_num {
++	PORT_NUMBER_DVP_SENSOR = 0,
++	PORT_NUMBER_CSI2RX
++};
++
++enum stf_clk {
++	STF_CLK_APB_FUNC = 0,
++	STF_CLK_WRAPPER_CLK_C,
++	STF_CLK_DVP_INV,
++	STF_CLK_AXIWR,
++	STF_CLK_MIPI_RX0_PXL,
++	STF_CLK_ISPCORE_2X,
++	STF_CLK_ISP_AXI,
++	STF_CLK_NUM
++};
++
++enum stf_rst {
++	STF_RST_WRAPPER_P = 0,
++	STF_RST_WRAPPER_C,
++	STF_RST_AXIRD,
++	STF_RST_AXIWR,
++	STF_RST_ISP_TOP_N,
++	STF_RST_ISP_TOP_AXI,
++	STF_RST_NUM
++};
++
++enum stf_irq {
++	STF_IRQ_VINWR = 0,
++	STF_IRQ_ISP,
++	STF_IRQ_ISPCSIL,
++	STF_IRQ_NUM
++};
++
++#define HOST_ENTITY_MAX		2
++
++struct host_data {
++	struct media_entity *host_entity[HOST_ENTITY_MAX];
++};
++
++struct stfcamss {
++	struct v4l2_device v4l2_dev;
++	struct media_device media_dev;
++	struct media_pipeline pipe;
++	struct device *dev;
++	struct v4l2_async_notifier notifier;
++	struct host_data host_data;
++	void __iomem *syscon_base;
++	void __iomem *isp_base;
++	int irq[STF_IRQ_NUM];
++	struct clk_bulk_data sys_clk[STF_CLK_NUM];
++	int nclks;
++	struct reset_control_bulk_data sys_rst[STF_RST_NUM];
++	int nrsts;
++};
++
++struct stfcamss_async_subdev {
++	struct v4l2_async_subdev asd;  /* must be first */
++	enum port_num port;
++};
++
++static inline u32 stf_isp_reg_read(struct stfcamss *stfcamss, u32 reg)
++{
++	return ioread32(stfcamss->isp_base + reg);
++}
++
++static inline void stf_isp_reg_write(struct stfcamss *stfcamss,
++				     u32 reg, u32 val)
++{
++	iowrite32(val, stfcamss->isp_base + reg);
++}
++
++static inline void stf_isp_reg_write_delay(struct stfcamss *stfcamss,
++					   u32 reg, u32 val, u32 delay)
++{
++	iowrite32(val, stfcamss->isp_base + reg);
++	usleep_range(1000 * delay, 1000 * delay + 100);
++}
++
++static inline void stf_isp_reg_set_bit(struct stfcamss *stfcamss,
++				       u32 reg, u32 mask, u32 val)
++{
++	u32 value;
++
++	value = ioread32(stfcamss->isp_base + reg) & ~mask;
++	val &= mask;
++	val |= value;
++	iowrite32(val, stfcamss->isp_base + reg);
++}
++
++static inline void stf_isp_reg_set(struct stfcamss *stfcamss, u32 reg, u32 mask)
++{
++	iowrite32(ioread32(stfcamss->isp_base + reg) | mask,
++		  stfcamss->isp_base + reg);
++}
++
++static inline u32 stf_syscon_reg_read(struct stfcamss *stfcamss, u32 reg)
++{
++	return ioread32(stfcamss->syscon_base + reg);
++}
++
++static inline void stf_syscon_reg_write(struct stfcamss *stfcamss,
++					u32 reg, u32 val)
++{
++	iowrite32(val, stfcamss->syscon_base + reg);
++}
++
++static inline void stf_syscon_reg_set_bit(struct stfcamss *stfcamss,
++					  u32 reg, u32 bit_mask)
++{
++	u32 value;
++
++	value = ioread32(stfcamss->syscon_base + reg);
++	iowrite32(value | bit_mask, stfcamss->syscon_base + reg);
++}
++
++static inline void stf_syscon_reg_clear_bit(struct stfcamss *stfcamss,
++					    u32 reg, u32 bit_mask)
++{
++	u32 value;
++
++	value = ioread32(stfcamss->syscon_base + reg);
++	iowrite32(value & ~bit_mask, stfcamss->syscon_base + reg);
++}
++#endif /* STF_CAMSS_H */
+--- /dev/null
++++ b/drivers/media/platform/starfive/stf_common.h
+@@ -0,0 +1,18 @@
++/* SPDX-License-Identifier: GPL-2.0 */
++/*
++ * stf_common.h
++ *
++ * StarFive Camera Subsystem - Common definitions
++ *
++ * Copyright (C) 2021-2023 StarFive Technology Co., Ltd.
++ */
++
++#ifndef STF_COMMON_H
++#define STF_COMMON_H
++
++enum stf_subdev_type {
++	STF_SUBDEV_TYPE_VIN,
++	STF_SUBDEV_TYPE_ISP,
++};
++
++#endif /* STF_COMMON_H */

+ 992 - 0
target/linux/starfive/patches-6.1/0084-media-starfive-Add-video-driver.patch

@@ -0,0 +1,992 @@
+From 70a588f7daefe34697ccd04fa6ac3a6d4b63be88 Mon Sep 17 00:00:00 2001
+From: Jack Zhu <[email protected]>
+Date: Fri, 12 May 2023 18:28:42 +0800
+Subject: [PATCH 084/122] media: starfive: Add video driver
+
+Add video driver for StarFive Camera Subsystem.
+
+Signed-off-by: Jack Zhu <[email protected]>
+---
+ drivers/media/platform/starfive/Makefile    |   3 +-
+ drivers/media/platform/starfive/stf_video.c | 864 ++++++++++++++++++++
+ drivers/media/platform/starfive/stf_video.h |  95 +++
+ 3 files changed, 961 insertions(+), 1 deletion(-)
+ create mode 100644 drivers/media/platform/starfive/stf_video.c
+ create mode 100644 drivers/media/platform/starfive/stf_video.h
+
+--- a/drivers/media/platform/starfive/Makefile
++++ b/drivers/media/platform/starfive/Makefile
+@@ -4,6 +4,7 @@
+ #
+ 
+ starfive-camss-objs += \
+-		stf_camss.o
++		stf_camss.o \
++		stf_video.o
+ 
+ obj-$(CONFIG_VIDEO_STARFIVE_CAMSS) += starfive-camss.o \
+--- /dev/null
++++ b/drivers/media/platform/starfive/stf_video.c
+@@ -0,0 +1,864 @@
++// SPDX-License-Identifier: GPL-2.0
++/*
++ * stf_video.c
++ *
++ * StarFive Camera Subsystem - V4L2 device node
++ *
++ * Copyright (C) 2021-2023 StarFive Technology Co., Ltd.
++ */
++
++#include <media/media-entity.h>
++#include <media/v4l2-ctrls.h>
++#include <media/v4l2-event.h>
++#include <media/v4l2-mc.h>
++#include <media/videobuf2-dma-contig.h>
++
++#include "stf_camss.h"
++#include "stf_video.h"
++
++static const struct stfcamss_format_info formats_pix_wr[] = {
++	{ MEDIA_BUS_FMT_SRGGB10_1X10, V4L2_PIX_FMT_SRGGB10, 1,
++	  { { 1, 1 } }, { { 1, 1 } }, { 10 } },
++	{ MEDIA_BUS_FMT_SGRBG10_1X10, V4L2_PIX_FMT_SGRBG10, 1,
++	  { { 1, 1 } }, { { 1, 1 } }, { 10 } },
++	{ MEDIA_BUS_FMT_SGBRG10_1X10, V4L2_PIX_FMT_SGBRG10, 1,
++	  { { 1, 1 } }, { { 1, 1 } }, { 10 } },
++	{ MEDIA_BUS_FMT_SBGGR10_1X10, V4L2_PIX_FMT_SBGGR10, 1,
++	  { { 1, 1 } }, { { 1, 1 } }, { 10 } },
++};
++
++static const struct stfcamss_format_info formats_pix_isp[] = {
++	{ MEDIA_BUS_FMT_Y12_1X12, V4L2_PIX_FMT_NV12, 1,
++	  { { 1, 1 } }, { { 2, 3 } }, { 8 } },
++};
++
++/* -----------------------------------------------------------------------------
++ * Helper functions
++ */
++
++static int video_find_format(u32 code, u32 pixelformat,
++			     const struct stfcamss_format_info *formats,
++			     unsigned int nformats)
++{
++	int i;
++
++	for (i = 0; i < nformats; i++) {
++		if (formats[i].code == code &&
++		    formats[i].pixelformat == pixelformat)
++			return i;
++	}
++
++	for (i = 0; i < nformats; i++)
++		if (formats[i].code == code)
++			return i;
++
++	for (i = 0; i < nformats; i++)
++		if (formats[i].pixelformat == pixelformat)
++			return i;
++
++	return -EINVAL;
++}
++
++static int __video_try_fmt(struct stfcamss_video *video, struct v4l2_format *f)
++{
++	struct v4l2_pix_format *pix;
++	const struct stfcamss_format_info *fi;
++	u32 width, height;
++	u32 bpl;
++	int i;
++
++	pix = &f->fmt.pix;
++
++	for (i = 0; i < video->nformats; i++)
++		if (pix->pixelformat == video->formats[i].pixelformat)
++			break;
++
++	if (i == video->nformats)
++		i = 0; /* default format */
++
++	fi = &video->formats[i];
++	width = pix->width;
++	height = pix->height;
++
++	memset(pix, 0, sizeof(*pix));
++
++	pix->pixelformat = fi->pixelformat;
++	pix->width = clamp_t(u32, width, STFCAMSS_FRAME_MIN_WIDTH,
++			     STFCAMSS_FRAME_MAX_WIDTH);
++	pix->height = clamp_t(u32, height, STFCAMSS_FRAME_MIN_HEIGHT,
++			      STFCAMSS_FRAME_MAX_HEIGHT);
++	bpl = pix->width / fi->hsub[0].numerator *
++	      fi->hsub[0].denominator * fi->bpp[0] / 8;
++	bpl = ALIGN(bpl, video->bpl_alignment);
++	pix->bytesperline = bpl;
++	pix->sizeimage = pix->height / fi->vsub[0].numerator *
++			 fi->vsub[0].denominator * bpl;
++
++	pix->field = V4L2_FIELD_NONE;
++	pix->colorspace = V4L2_COLORSPACE_SRGB;
++	pix->flags = 0;
++	pix->ycbcr_enc =
++		V4L2_MAP_YCBCR_ENC_DEFAULT(pix->colorspace);
++	pix->quantization = V4L2_MAP_QUANTIZATION_DEFAULT(true,
++							  pix->colorspace,
++							  pix->ycbcr_enc);
++	pix->xfer_func = V4L2_MAP_XFER_FUNC_DEFAULT(pix->colorspace);
++
++	return 0;
++}
++
++static int stf_video_init_format(struct stfcamss_video *video)
++{
++	int ret;
++	struct v4l2_format format = {
++		.type = video->type,
++		.fmt.pix = {
++			.width = 1920,
++			.height = 1080,
++			.pixelformat = V4L2_PIX_FMT_RGB565,
++		},
++	};
++
++	ret = __video_try_fmt(video, &format);
++
++	if (ret < 0)
++		return ret;
++
++	video->active_fmt = format;
++
++	return 0;
++}
++
++/* -----------------------------------------------------------------------------
++ * Video queue operations
++ */
++
++static int video_queue_setup(struct vb2_queue *q,
++			     unsigned int *num_buffers,
++			     unsigned int *num_planes,
++			     unsigned int sizes[],
++			     struct device *alloc_devs[])
++{
++	struct stfcamss_video *video = vb2_get_drv_priv(q);
++	const struct v4l2_pix_format *format = &video->active_fmt.fmt.pix;
++
++	if (*num_planes) {
++		if (*num_planes != 1)
++			return -EINVAL;
++
++		if (sizes[0] < format->sizeimage)
++			return -EINVAL;
++	}
++
++	*num_planes = 1;
++	sizes[0] = format->sizeimage;
++	if (!sizes[0])
++		dev_err(video->stfcamss->dev,
++			"%s: error size is zero!!!\n", __func__);
++
++	dev_dbg(video->stfcamss->dev, "planes = %d, size = %d\n",
++		*num_planes, sizes[0]);
++
++	return 0;
++}
++
++static int video_buf_init(struct vb2_buffer *vb)
++{
++	struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
++	struct stfcamss_video *video = vb2_get_drv_priv(vb->vb2_queue);
++	struct stfcamss_buffer *buffer =
++		container_of(vbuf, struct stfcamss_buffer, vb);
++	const struct v4l2_pix_format *fmt = &video->active_fmt.fmt.pix;
++	dma_addr_t *paddr;
++
++	buffer->sizeimage = 0;
++
++	paddr = vb2_plane_cookie(vb, 0);
++	buffer->sizeimage = vb2_plane_size(vb, 0);
++	buffer->addr[0] = *paddr;
++	if (fmt->pixelformat == V4L2_PIX_FMT_NV12 ||
++	    fmt->pixelformat == V4L2_PIX_FMT_NV21 ||
++	    fmt->pixelformat == V4L2_PIX_FMT_NV16 ||
++	    fmt->pixelformat == V4L2_PIX_FMT_NV61)
++		buffer->addr[1] =
++			buffer->addr[0] + fmt->bytesperline * fmt->height;
++
++	return 0;
++}
++
++static int video_buf_prepare(struct vb2_buffer *vb)
++{
++	struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
++	struct stfcamss_video *video = vb2_get_drv_priv(vb->vb2_queue);
++	const struct v4l2_pix_format *fmt = &video->active_fmt.fmt.pix;
++
++	if (fmt->sizeimage > vb2_plane_size(vb, 0)) {
++		dev_err(video->stfcamss->dev,
++			"sizeimage = %d, plane size = %d\n",
++			fmt->sizeimage, (unsigned int)vb2_plane_size(vb, 0));
++		return -EINVAL;
++	}
++	vb2_set_plane_payload(vb, 0, fmt->sizeimage);
++
++	vbuf->field = V4L2_FIELD_NONE;
++
++	return 0;
++}
++
++static void video_buf_queue(struct vb2_buffer *vb)
++{
++	struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
++	struct stfcamss_video *video = vb2_get_drv_priv(vb->vb2_queue);
++	struct stfcamss_buffer *buffer =
++		container_of(vbuf, struct stfcamss_buffer, vb);
++
++	video->ops->queue_buffer(video, buffer);
++}
++
++/*
++ * video_mbus_to_pix - Convert v4l2_mbus_framefmt to v4l2_pix_format
++ * @mbus: v4l2_mbus_framefmt format (input)
++ * @pix: v4l2_pix_format_mplane format (output)
++ * @f: a pointer to formats array element to be used for the conversion
++ * @alignment: bytesperline alignment value
++ *
++ * Fill the output pix structure with information from the input mbus format.
++ *
++ * Return 0 on success or a negative error code otherwise
++ */
++static int video_mbus_to_pix(const struct v4l2_mbus_framefmt *mbus,
++			     struct v4l2_pix_format *pix,
++			     const struct stfcamss_format_info *f,
++			     unsigned int alignment)
++{
++	u32 bytesperline;
++
++	memset(pix, 0, sizeof(*pix));
++	v4l2_fill_pix_format(pix, mbus);
++	pix->pixelformat = f->pixelformat;
++	bytesperline = pix->width / f->hsub[0].numerator *
++		       f->hsub[0].denominator * f->bpp[0] / 8;
++	bytesperline = ALIGN(bytesperline, alignment);
++	pix->bytesperline = bytesperline;
++	pix->sizeimage = pix->height / f->vsub[0].numerator *
++			 f->vsub[0].denominator * bytesperline;
++	return 0;
++}
++
++static struct v4l2_subdev *video_remote_subdev(struct stfcamss_video *video,
++					       u32 *pad)
++{
++	struct media_pad *remote;
++
++	remote = media_pad_remote_pad_first(&video->pad);
++
++	if (!remote || !is_media_entity_v4l2_subdev(remote->entity))
++		return NULL;
++
++	if (pad)
++		*pad = remote->index;
++
++	return media_entity_to_v4l2_subdev(remote->entity);
++}
++
++static int video_get_subdev_format(struct stfcamss_video *video,
++				   struct v4l2_format *format)
++{
++	struct v4l2_pix_format *pix = &video->active_fmt.fmt.pix;
++	struct v4l2_subdev_format fmt;
++	struct v4l2_subdev *subdev;
++	u32 pixelformat;
++	u32 pad;
++	int ret;
++
++	subdev = video_remote_subdev(video, &pad);
++	if (!subdev)
++		return -EPIPE;
++
++	fmt.pad = pad;
++	fmt.which = V4L2_SUBDEV_FORMAT_ACTIVE;
++
++	ret = v4l2_subdev_call(subdev, pad, get_fmt, NULL, &fmt);
++	if (ret)
++		return ret;
++
++	pixelformat = pix->pixelformat;
++	ret = video_find_format(fmt.format.code, pixelformat,
++				video->formats, video->nformats);
++	if (ret < 0)
++		return ret;
++
++	format->type = video->type;
++
++	return video_mbus_to_pix(&fmt.format, &format->fmt.pix,
++				 &video->formats[ret], video->bpl_alignment);
++}
++
++static int video_check_format(struct stfcamss_video *video)
++{
++	struct v4l2_pix_format *pix = &video->active_fmt.fmt.pix;
++	struct v4l2_format format;
++	struct v4l2_pix_format *sd_pix = &format.fmt.pix;
++	int ret;
++
++	sd_pix->pixelformat = pix->pixelformat;
++	ret = video_get_subdev_format(video, &format);
++	if (ret < 0)
++		return ret;
++
++	if (pix->pixelformat != sd_pix->pixelformat ||
++	    pix->height > sd_pix->height ||
++	    pix->width > sd_pix->width ||
++	    pix->field != format.fmt.pix.field) {
++		dev_err(video->stfcamss->dev,
++			"%s, not match:\n"
++			"0x%x 0x%x\n0x%x 0x%x\n0x%x 0x%x\n",
++			__func__,
++			pix->pixelformat, sd_pix->pixelformat,
++			pix->height, sd_pix->height,
++			pix->field, format.fmt.pix.field);
++		return -EPIPE;
++	}
++
++	return 0;
++}
++
++static int video_start_streaming(struct vb2_queue *q, unsigned int count)
++{
++	struct stfcamss_video *video = vb2_get_drv_priv(q);
++	struct video_device *vdev = &video->vdev;
++	struct media_entity *entity;
++	struct media_pad *pad;
++	struct v4l2_subdev *subdev;
++	int ret;
++
++	ret = video_device_pipeline_start(vdev, &video->stfcamss->pipe);
++	if (ret < 0) {
++		dev_err(video->stfcamss->dev,
++			"Failed to media_pipeline_start: %d\n", ret);
++		return ret;
++	}
++
++	ret = video_check_format(video);
++	if (ret < 0)
++		goto error;
++	entity = &vdev->entity;
++	while (1) {
++		pad = &entity->pads[0];
++		if (!(pad->flags & MEDIA_PAD_FL_SINK))
++			break;
++
++		pad = media_pad_remote_pad_first(pad);
++		if (!pad || !is_media_entity_v4l2_subdev(pad->entity))
++			break;
++
++		entity = pad->entity;
++		subdev = media_entity_to_v4l2_subdev(entity);
++
++		ret = v4l2_subdev_call(subdev, video, s_stream, 1);
++		if (ret < 0 && ret != -ENOIOCTLCMD)
++			goto error;
++	}
++	return 0;
++
++error:
++	video_device_pipeline_stop(vdev);
++	video->ops->flush_buffers(video, VB2_BUF_STATE_QUEUED);
++	return ret;
++}
++
++static void video_stop_streaming(struct vb2_queue *q)
++{
++	struct stfcamss_video *video = vb2_get_drv_priv(q);
++	struct video_device *vdev = &video->vdev;
++	struct media_entity *entity;
++	struct media_pad *pad;
++	struct v4l2_subdev *subdev;
++
++	entity = &vdev->entity;
++	while (1) {
++		pad = &entity->pads[0];
++		if (!(pad->flags & MEDIA_PAD_FL_SINK))
++			break;
++
++		pad = media_pad_remote_pad_first(pad);
++		if (!pad || !is_media_entity_v4l2_subdev(pad->entity))
++			break;
++
++		entity = pad->entity;
++		subdev = media_entity_to_v4l2_subdev(entity);
++
++		v4l2_subdev_call(subdev, video, s_stream, 0);
++	}
++
++	video_device_pipeline_stop(vdev);
++	video->ops->flush_buffers(video, VB2_BUF_STATE_ERROR);
++}
++
++static const struct vb2_ops stf_video_vb2_q_ops = {
++	.queue_setup     = video_queue_setup,
++	.wait_prepare    = vb2_ops_wait_prepare,
++	.wait_finish     = vb2_ops_wait_finish,
++	.buf_init        = video_buf_init,
++	.buf_prepare     = video_buf_prepare,
++	.buf_queue       = video_buf_queue,
++	.start_streaming = video_start_streaming,
++	.stop_streaming  = video_stop_streaming,
++};
++
++/* -----------------------------------------------------------------------------
++ * V4L2 ioctls
++ */
++
++static int video_querycap(struct file *file, void *fh,
++			  struct v4l2_capability *cap)
++{
++	struct stfcamss_video *video = video_drvdata(file);
++
++	strscpy(cap->driver, "stf camss", sizeof(cap->driver));
++	strscpy(cap->card, "Starfive Camera Subsystem", sizeof(cap->card));
++	snprintf(cap->bus_info, sizeof(cap->bus_info), "platform:%s",
++		 dev_name(video->stfcamss->dev));
++	return 0;
++}
++
++static int video_get_pfmt_by_index(struct stfcamss_video *video, int ndx)
++{
++	int i, j, k;
++
++	/* find index "i" of "k"th unique pixelformat in formats array */
++	k = -1;
++	for (i = 0; i < video->nformats; i++) {
++		for (j = 0; j < i; j++) {
++			if (video->formats[i].pixelformat ==
++			    video->formats[j].pixelformat)
++				break;
++		}
++
++		if (j == i)
++			k++;
++
++		if (k == ndx)
++			return i;
++	}
++
++	return -EINVAL;
++}
++
++static int video_get_pfmt_by_mcode(struct stfcamss_video *video, u32 mcode)
++{
++	int i;
++
++	for (i = 0; i < video->nformats; i++) {
++		if (video->formats[i].code == mcode)
++			return i;
++	}
++
++	return -EINVAL;
++}
++
++static int video_enum_fmt(struct file *file, void *fh, struct v4l2_fmtdesc *f)
++{
++	struct stfcamss_video *video = video_drvdata(file);
++	int i;
++
++	if (f->type != video->type)
++		return -EINVAL;
++	if (f->index >= video->nformats)
++		return -EINVAL;
++
++	if (f->mbus_code) {
++		/* Each entry in formats[] table has unique mbus_code */
++		if (f->index > 0)
++			return -EINVAL;
++
++		i = video_get_pfmt_by_mcode(video, f->mbus_code);
++	} else {
++		i = video_get_pfmt_by_index(video, f->index);
++	}
++
++	if (i < 0)
++		return -EINVAL;
++
++	f->pixelformat = video->formats[i].pixelformat;
++
++	return 0;
++}
++
++static int video_enum_framesizes(struct file *file, void *fh,
++				 struct v4l2_frmsizeenum *fsize)
++{
++	struct stfcamss_video *video = video_drvdata(file);
++	int i;
++
++	if (fsize->index)
++		return -EINVAL;
++
++	for (i = 0; i < video->nformats; i++) {
++		if (video->formats[i].pixelformat == fsize->pixel_format)
++			break;
++	}
++
++	if (i == video->nformats)
++		return -EINVAL;
++
++	fsize->type = V4L2_FRMSIZE_TYPE_CONTINUOUS;
++	fsize->stepwise.min_width = STFCAMSS_FRAME_MIN_WIDTH;
++	fsize->stepwise.max_width = STFCAMSS_FRAME_MAX_WIDTH;
++	fsize->stepwise.min_height = STFCAMSS_FRAME_MIN_HEIGHT;
++	fsize->stepwise.max_height = STFCAMSS_FRAME_MAX_HEIGHT;
++	fsize->stepwise.step_width = 1;
++	fsize->stepwise.step_height = 1;
++
++	return 0;
++}
++
++static int video_g_fmt(struct file *file, void *fh, struct v4l2_format *f)
++{
++	struct stfcamss_video *video = video_drvdata(file);
++
++	*f = video->active_fmt;
++
++	return 0;
++}
++
++static int video_s_fmt(struct file *file, void *fh, struct v4l2_format *f)
++{
++	struct stfcamss_video *video = video_drvdata(file);
++	int ret;
++
++	if (vb2_is_busy(&video->vb2_q))
++		return -EBUSY;
++
++	ret = __video_try_fmt(video, f);
++	if (ret < 0)
++		return ret;
++
++	video->active_fmt = *f;
++
++	return 0;
++}
++
++static int video_try_fmt(struct file *file, void *fh, struct v4l2_format *f)
++{
++	struct stfcamss_video *video = video_drvdata(file);
++
++	return __video_try_fmt(video, f);
++}
++
++static int video_enum_input(struct file *file, void *fh,
++			    struct v4l2_input *input)
++{
++	if (input->index > 0)
++		return -EINVAL;
++
++	strscpy(input->name, "camera", sizeof(input->name));
++	input->type = V4L2_INPUT_TYPE_CAMERA;
++
++	return 0;
++}
++
++static int video_g_input(struct file *file, void *fh, unsigned int *input)
++{
++	*input = 0;
++
++	return 0;
++}
++
++static int video_s_input(struct file *file, void *fh, unsigned int input)
++{
++	return input == 0 ? 0 : -EINVAL;
++}
++
++static int video_g_parm(struct file *file, void *priv,
++			struct v4l2_streamparm *p)
++{
++	struct stfcamss_video *video = video_drvdata(file);
++	struct video_device *vdev = &video->vdev;
++	struct media_entity *entity;
++	struct v4l2_subdev *subdev;
++	struct media_pad *pad;
++	int ret, is_support = 0;
++
++	entity = &vdev->entity;
++	while (1) {
++		pad = &entity->pads[0];
++		if (!(pad->flags & MEDIA_PAD_FL_SINK))
++			break;
++
++		pad = media_pad_remote_pad_first(pad);
++		if (!pad || !is_media_entity_v4l2_subdev(pad->entity))
++			break;
++
++		entity = pad->entity;
++		subdev = media_entity_to_v4l2_subdev(entity);
++
++		ret = v4l2_g_parm_cap(vdev, subdev, p);
++		if (ret < 0 && ret != -ENOIOCTLCMD)
++			break;
++		if (!ret)
++			is_support = 1;
++	}
++
++	return is_support ? 0 : ret;
++}
++
++static int video_s_parm(struct file *file, void *priv,
++			struct v4l2_streamparm *p)
++{
++	struct stfcamss_video *video = video_drvdata(file);
++	struct video_device *vdev = &video->vdev;
++	struct media_entity *entity;
++	struct v4l2_subdev *subdev;
++	struct media_pad *pad;
++	struct v4l2_streamparm tmp_p;
++	int ret, is_support = 0;
++
++	entity = &vdev->entity;
++	while (1) {
++		pad = &entity->pads[0];
++		if (!(pad->flags & MEDIA_PAD_FL_SINK))
++			break;
++
++		pad = media_pad_remote_pad_first(pad);
++		if (!pad || !is_media_entity_v4l2_subdev(pad->entity))
++			break;
++
++		entity = pad->entity;
++		subdev = media_entity_to_v4l2_subdev(entity);
++
++		tmp_p = *p;
++		ret = v4l2_s_parm_cap(vdev, subdev, &tmp_p);
++		if (ret < 0 && ret != -ENOIOCTLCMD)
++			break;
++		if (!ret) {
++			is_support = 1;
++			*p = tmp_p;
++		}
++	}
++
++	return is_support ? 0 : ret;
++}
++
++static const struct v4l2_ioctl_ops stf_vid_vin_ioctl_ops = {
++	.vidioc_querycap                = video_querycap,
++	.vidioc_enum_fmt_vid_cap        = video_enum_fmt,
++	.vidioc_enum_fmt_vid_out        = video_enum_fmt,
++	.vidioc_enum_framesizes         = video_enum_framesizes,
++	.vidioc_g_fmt_vid_cap           = video_g_fmt,
++	.vidioc_s_fmt_vid_cap           = video_s_fmt,
++	.vidioc_try_fmt_vid_cap         = video_try_fmt,
++	.vidioc_g_fmt_vid_out           = video_g_fmt,
++	.vidioc_s_fmt_vid_out           = video_s_fmt,
++	.vidioc_try_fmt_vid_out         = video_try_fmt,
++	.vidioc_reqbufs                 = vb2_ioctl_reqbufs,
++	.vidioc_querybuf                = vb2_ioctl_querybuf,
++	.vidioc_qbuf                    = vb2_ioctl_qbuf,
++	.vidioc_expbuf                  = vb2_ioctl_expbuf,
++	.vidioc_dqbuf                   = vb2_ioctl_dqbuf,
++	.vidioc_create_bufs             = vb2_ioctl_create_bufs,
++	.vidioc_prepare_buf             = vb2_ioctl_prepare_buf,
++	.vidioc_streamon                = vb2_ioctl_streamon,
++	.vidioc_streamoff               = vb2_ioctl_streamoff,
++	.vidioc_enum_input              = video_enum_input,
++	.vidioc_g_input                 = video_g_input,
++	.vidioc_s_input                 = video_s_input,
++	.vidioc_g_parm                  = video_g_parm,
++	.vidioc_s_parm                  = video_s_parm,
++};
++
++static const struct v4l2_ioctl_ops stf_vid_isp_ioctl_ops = {
++	.vidioc_querycap                = video_querycap,
++	.vidioc_enum_fmt_vid_cap        = video_enum_fmt,
++	.vidioc_enum_fmt_vid_out        = video_enum_fmt,
++	.vidioc_enum_framesizes         = video_enum_framesizes,
++	.vidioc_g_fmt_vid_cap           = video_g_fmt,
++	.vidioc_s_fmt_vid_cap           = video_s_fmt,
++	.vidioc_try_fmt_vid_cap         = video_try_fmt,
++	.vidioc_g_fmt_vid_out           = video_g_fmt,
++	.vidioc_s_fmt_vid_out           = video_s_fmt,
++	.vidioc_try_fmt_vid_out         = video_try_fmt,
++	.vidioc_reqbufs                 = vb2_ioctl_reqbufs,
++	.vidioc_querybuf                = vb2_ioctl_querybuf,
++	.vidioc_qbuf                    = vb2_ioctl_qbuf,
++	.vidioc_expbuf                  = vb2_ioctl_expbuf,
++	.vidioc_dqbuf                   = vb2_ioctl_dqbuf,
++	.vidioc_create_bufs             = vb2_ioctl_create_bufs,
++	.vidioc_prepare_buf             = vb2_ioctl_prepare_buf,
++	.vidioc_streamon                = vb2_ioctl_streamon,
++	.vidioc_streamoff               = vb2_ioctl_streamoff,
++	.vidioc_enum_input              = video_enum_input,
++	.vidioc_g_input                 = video_g_input,
++	.vidioc_s_input                 = video_s_input,
++	.vidioc_g_parm                  = video_g_parm,
++	.vidioc_s_parm                  = video_s_parm,
++};
++
++/* -----------------------------------------------------------------------------
++ * V4L2 file operations
++ */
++
++static int video_open(struct file *file)
++{
++	struct video_device *vdev = video_devdata(file);
++	struct stfcamss_video *video = video_drvdata(file);
++	struct v4l2_fh *vfh;
++	int ret;
++
++	mutex_lock(&video->lock);
++
++	vfh = kzalloc(sizeof(*vfh), GFP_KERNEL);
++	if (!vfh) {
++		ret = -ENOMEM;
++		goto error_alloc;
++	}
++
++	v4l2_fh_init(vfh, vdev);
++	v4l2_fh_add(vfh);
++
++	file->private_data = vfh;
++
++	ret = v4l2_pipeline_pm_get(&vdev->entity);
++	if (ret < 0) {
++		dev_err(video->stfcamss->dev,
++			"Failed to power up pipeline: %d\n", ret);
++		goto error_pm_use;
++	}
++	mutex_unlock(&video->lock);
++
++	return 0;
++
++error_pm_use:
++	v4l2_fh_release(file);
++error_alloc:
++	mutex_unlock(&video->lock);
++	return ret;
++}
++
++static int video_release(struct file *file)
++{
++	struct video_device *vdev = video_devdata(file);
++
++	vb2_fop_release(file);
++	v4l2_pipeline_pm_put(&vdev->entity);
++	file->private_data = NULL;
++
++	return 0;
++}
++
++static const struct v4l2_file_operations stf_vid_fops = {
++	.owner          = THIS_MODULE,
++	.unlocked_ioctl = video_ioctl2,
++	.open           = video_open,
++	.release        = video_release,
++	.poll           = vb2_fop_poll,
++	.mmap           = vb2_fop_mmap,
++	.read           = vb2_fop_read,
++};
++
++/* -----------------------------------------------------------------------------
++ * STFCAMSS video core
++ */
++
++static void stf_video_release(struct video_device *vdev)
++{
++	struct stfcamss_video *video = video_get_drvdata(vdev);
++
++	media_entity_cleanup(&vdev->entity);
++
++	mutex_destroy(&video->q_lock);
++	mutex_destroy(&video->lock);
++}
++
++int stf_video_register(struct stfcamss_video *video,
++		       struct v4l2_device *v4l2_dev, const char *name)
++{
++	struct video_device *vdev;
++	struct vb2_queue *q;
++	struct media_pad *pad = &video->pad;
++	int ret;
++
++	vdev = &video->vdev;
++
++	mutex_init(&video->q_lock);
++
++	q = &video->vb2_q;
++	q->drv_priv = video;
++	q->mem_ops = &vb2_dma_contig_memops;
++	q->ops = &stf_video_vb2_q_ops;
++	q->type = video->type;
++	q->io_modes = VB2_DMABUF | VB2_MMAP | VB2_READ;
++	q->timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_MONOTONIC;
++	q->buf_struct_size = sizeof(struct stfcamss_buffer);
++	q->dev = video->stfcamss->dev;
++	q->lock = &video->q_lock;
++	q->min_buffers_needed = STFCAMSS_MIN_BUFFERS;
++	ret = vb2_queue_init(q);
++	if (ret < 0) {
++		dev_err(video->stfcamss->dev,
++			"Failed to init vb2 queue: %d\n", ret);
++		goto err_vb2_init;
++	}
++
++	pad->flags = MEDIA_PAD_FL_SINK;
++	ret = media_entity_pads_init(&vdev->entity, 1, pad);
++	if (ret < 0) {
++		dev_err(video->stfcamss->dev,
++			"Failed to init video entity: %d\n", ret);
++		goto err_vb2_init;
++	}
++
++	mutex_init(&video->lock);
++
++	if (video->id == STF_V_LINE_WR) {
++		video->formats = formats_pix_wr;
++		video->nformats = ARRAY_SIZE(formats_pix_wr);
++		video->bpl_alignment = STFCAMSS_FRAME_WIDTH_ALIGN_8;
++		vdev->ioctl_ops = &stf_vid_vin_ioctl_ops;
++	} else {
++		video->formats = formats_pix_isp;
++		video->nformats = ARRAY_SIZE(formats_pix_isp);
++		video->bpl_alignment = STFCAMSS_FRAME_WIDTH_ALIGN_8;
++		vdev->ioctl_ops = &stf_vid_isp_ioctl_ops;
++	}
++
++	ret = stf_video_init_format(video);
++	if (ret < 0) {
++		dev_err(video->stfcamss->dev,
++			"Failed to init format: %d\n", ret);
++		goto err_vid_init_format;
++	}
++
++	vdev->fops = &stf_vid_fops;
++	vdev->device_caps = V4L2_CAP_VIDEO_CAPTURE;
++	vdev->vfl_dir = VFL_DIR_RX;
++	vdev->device_caps |= V4L2_CAP_STREAMING | V4L2_CAP_READWRITE;
++	vdev->release = stf_video_release;
++	vdev->v4l2_dev = v4l2_dev;
++	vdev->queue = &video->vb2_q;
++	vdev->lock = &video->lock;
++	strscpy(vdev->name, name, sizeof(vdev->name));
++
++	ret = video_register_device(vdev, VFL_TYPE_VIDEO, video->id);
++	if (ret < 0) {
++		dev_err(video->stfcamss->dev,
++			"Failed to register video device: %d\n", ret);
++		goto err_vid_reg;
++	}
++
++	video_set_drvdata(vdev, video);
++	return 0;
++
++err_vid_reg:
++err_vid_init_format:
++	media_entity_cleanup(&vdev->entity);
++	mutex_destroy(&video->lock);
++err_vb2_init:
++	mutex_destroy(&video->q_lock);
++	return ret;
++}
++
++void stf_video_unregister(struct stfcamss_video *video)
++{
++	vb2_video_unregister_device(&video->vdev);
++}
+--- /dev/null
++++ b/drivers/media/platform/starfive/stf_video.h
+@@ -0,0 +1,95 @@
++/* SPDX-License-Identifier: GPL-2.0 */
++/*
++ * stf_video.h
++ *
++ * StarFive Camera Subsystem - V4L2 device node
++ *
++ * Copyright (C) 2021-2023 StarFive Technology Co., Ltd.
++ */
++
++#ifndef STF_VIDEO_H
++#define STF_VIDEO_H
++
++#include <linux/mutex.h>
++#include <linux/videodev2.h>
++#include <media/v4l2-dev.h>
++#include <media/v4l2-fh.h>
++#include <media/v4l2-ioctl.h>
++#include <media/videobuf2-v4l2.h>
++
++#define STFCAMSS_FRAME_MIN_WIDTH		64
++#define STFCAMSS_FRAME_MAX_WIDTH		1920
++#define STFCAMSS_FRAME_MIN_HEIGHT		64
++#define STFCAMSS_FRAME_MAX_HEIGHT		1080
++#define STFCAMSS_FRAME_WIDTH_ALIGN_8		8
++#define STFCAMSS_FRAME_WIDTH_ALIGN_128		128
++#define STFCAMSS_MIN_BUFFERS			2
++
++#define STFCAMSS_MAX_ENTITY_NAME_LEN		27
++
++enum stf_v_line_id {
++	STF_V_LINE_WR = 0,
++	STF_V_LINE_ISP,
++	STF_V_LINE_MAX,
++};
++
++struct stfcamss_buffer {
++	struct vb2_v4l2_buffer vb;
++	dma_addr_t addr[3];
++	struct list_head queue;
++	int sizeimage;
++};
++
++struct fract {
++	u8 numerator;
++	u8 denominator;
++};
++
++/*
++ * struct stfcamss_format_info - ISP media bus format information
++ * @code: V4L2 media bus format code
++ * @pixelformat: V4L2 pixel format FCC identifier
++ * @planes: Number of planes
++ * @hsub: Horizontal subsampling (for each plane)
++ * @vsub: Vertical subsampling (for each plane)
++ * @bpp: Bits per pixel when stored in memory (for each plane)
++ */
++struct stfcamss_format_info {
++	u32 code;
++	u32 pixelformat;
++	u8 planes;
++	struct fract hsub[3];
++	struct fract vsub[3];
++	u8 bpp[3];
++};
++
++struct stfcamss_video {
++	struct stfcamss *stfcamss;
++	u8 id;
++	struct vb2_queue vb2_q;
++	struct video_device vdev;
++	struct media_pad pad;
++	struct media_pipeline pipe;
++	struct v4l2_format active_fmt;
++	enum v4l2_buf_type type;
++	const struct stfcamss_video_ops *ops;
++	struct mutex lock;	 /* serialize device access */
++	struct mutex q_lock;	 /* protects the queue */
++	unsigned int bpl_alignment;
++	const struct stfcamss_format_info *formats;
++	unsigned int nformats;
++};
++
++struct stfcamss_video_ops {
++	int (*queue_buffer)(struct stfcamss_video *vid,
++			    struct stfcamss_buffer *buf);
++	int (*flush_buffers)(struct stfcamss_video *vid,
++			     enum vb2_buffer_state state);
++};
++
++int stf_video_register(struct stfcamss_video *video,
++		       struct v4l2_device *v4l2_dev, const char *name);
++
++void stf_video_unregister(struct stfcamss_video *video);
++
++#endif /* STF_VIDEO_H */

+ 1667 - 0
target/linux/starfive/patches-6.1/0085-media-starfive-Add-ISP-driver.patch

@@ -0,0 +1,1667 @@
+From 3b814965133cd53b1f30a34e4425294726cb0087 Mon Sep 17 00:00:00 2001
+From: Jack Zhu <[email protected]>
+Date: Fri, 12 May 2023 18:28:43 +0800
+Subject: [PATCH 085/122] media: starfive: Add ISP driver
+
+Add ISP driver for StarFive Camera Subsystem.
+
+Signed-off-by: Jack Zhu <[email protected]>
+---
+ drivers/media/platform/starfive/Makefile      |   2 +
+ drivers/media/platform/starfive/stf_camss.c   |  71 ++-
+ drivers/media/platform/starfive/stf_camss.h   |   2 +
+ drivers/media/platform/starfive/stf_isp.c     | 550 ++++++++++++++++++
+ drivers/media/platform/starfive/stf_isp.h     | 476 +++++++++++++++
+ .../media/platform/starfive/stf_isp_hw_ops.c  | 452 ++++++++++++++
+ 6 files changed, 1551 insertions(+), 2 deletions(-)
+ create mode 100644 drivers/media/platform/starfive/stf_isp.c
+ create mode 100644 drivers/media/platform/starfive/stf_isp.h
+ create mode 100644 drivers/media/platform/starfive/stf_isp_hw_ops.c
+
+--- a/drivers/media/platform/starfive/Makefile
++++ b/drivers/media/platform/starfive/Makefile
+@@ -5,6 +5,8 @@
+ 
+ starfive-camss-objs += \
+ 		stf_camss.o \
++		stf_isp.o \
++		stf_isp_hw_ops.o \
+ 		stf_video.o
+ 
+ obj-$(CONFIG_VIDEO_STARFIVE_CAMSS) += starfive-camss.o \
+--- a/drivers/media/platform/starfive/stf_camss.c
++++ b/drivers/media/platform/starfive/stf_camss.c
+@@ -126,16 +126,66 @@ err_cleanup:
+ 	return ret;
+ }
+ 
++/*
++ * stfcamss_init_subdevices - Initialize subdev structures and resources
++ * @stfcamss: STFCAMSS device
++ *
++ * Return 0 on success or a negative error code on failure
++ */
++static int stfcamss_init_subdevices(struct stfcamss *stfcamss)
++{
++	int ret;
++
++	ret = stf_isp_subdev_init(stfcamss);
++	if (ret < 0) {
++		dev_err(stfcamss->dev, "Failed to init isp subdev: %d\n", ret);
++		return ret;
++	}
++
++	return ret;
++}
++
++static int stfcamss_register_subdevices(struct stfcamss *stfcamss)
++{
++	int ret;
++	struct stf_isp_dev *isp_dev = &stfcamss->isp_dev;
++
++	ret = stf_isp_register(isp_dev, &stfcamss->v4l2_dev);
++	if (ret < 0) {
++		dev_err(stfcamss->dev,
++			"Failed to register stf isp%d entity: %d\n", 0, ret);
++		return ret;
++	}
++
++	return ret;
++}
++
++static void stfcamss_unregister_subdevices(struct stfcamss *stfcamss)
++{
++	stf_isp_unregister(&stfcamss->isp_dev);
++}
++
+ static int stfcamss_subdev_notifier_bound(struct v4l2_async_notifier *async,
+ 					  struct v4l2_subdev *subdev,
+ 					  struct v4l2_async_subdev *asd)
+ {
+ 	struct stfcamss *stfcamss =
+ 		container_of(async, struct stfcamss, notifier);
++	struct stfcamss_async_subdev *csd =
++		container_of(asd, struct stfcamss_async_subdev, asd);
++	enum port_num port = csd->port;
++	struct stf_isp_dev *isp_dev = &stfcamss->isp_dev;
+ 	struct host_data *host_data = &stfcamss->host_data;
+ 	struct media_entity *source;
+ 	int i, j;
+ 
++	if (port == PORT_NUMBER_CSI2RX) {
++		host_data->host_entity[1] = &isp_dev->subdev.entity;
++	} else if (port == PORT_NUMBER_DVP_SENSOR) {
++		dev_err(stfcamss->dev, "Not support DVP sensor\n");
++		return -EPERM;
++	}
++
+ 	source = &subdev->entity;
+ 
+ 	for (i = 0; i < source->num_pads; i++) {
+@@ -266,12 +316,18 @@ static int stfcamss_probe(struct platfor
+ 		return -ENODEV;
+ 	}
+ 
++	ret = stfcamss_init_subdevices(stfcamss);
++	if (ret < 0) {
++		dev_err(dev, "Failed to init subdevice: %d\n", ret);
++		goto err_cleanup_notifier;
++	}
++
+ 	stfcamss_mc_init(pdev, stfcamss);
+ 
+ 	ret = v4l2_device_register(stfcamss->dev, &stfcamss->v4l2_dev);
+ 	if (ret < 0) {
+ 		dev_err(dev, "Failed to register V4L2 device: %d\n", ret);
+-		goto err_cleanup_notifier;
++		goto err_cleanup_media_device;
+ 	}
+ 
+ 	ret = media_device_register(&stfcamss->media_dev);
+@@ -280,22 +336,32 @@ static int stfcamss_probe(struct platfor
+ 		goto err_unregister_device;
+ 	}
+ 
++	ret = stfcamss_register_subdevices(stfcamss);
++	if (ret < 0) {
++		dev_err(dev, "Failed to register subdevice: %d\n", ret);
++		goto err_unregister_media_dev;
++	}
++
+ 	stfcamss->notifier.ops = &stfcamss_subdev_notifier_ops;
+ 	ret = v4l2_async_nf_register(&stfcamss->v4l2_dev, &stfcamss->notifier);
+ 	if (ret) {
+ 		dev_err(dev, "Failed to register async subdev nodes: %d\n",
+ 			ret);
+-		goto err_unregister_media_dev;
++		goto err_unregister_subdevs;
+ 	}
+ 
+ 	pm_runtime_enable(dev);
+ 
+ 	return 0;
+ 
++err_unregister_subdevs:
++	stfcamss_unregister_subdevices(stfcamss);
+ err_unregister_media_dev:
+ 	media_device_unregister(&stfcamss->media_dev);
+ err_unregister_device:
+ 	v4l2_device_unregister(&stfcamss->v4l2_dev);
++err_cleanup_media_device:
++	media_device_cleanup(&stfcamss->media_dev);
+ err_cleanup_notifier:
+ 	v4l2_async_nf_cleanup(&stfcamss->notifier);
+ 	return ret;
+@@ -311,6 +377,7 @@ static int stfcamss_remove(struct platfo
+ {
+ 	struct stfcamss *stfcamss = platform_get_drvdata(pdev);
+ 
++	stfcamss_unregister_subdevices(stfcamss);
+ 	v4l2_device_unregister(&stfcamss->v4l2_dev);
+ 	media_device_cleanup(&stfcamss->media_dev);
+ 	pm_runtime_disable(&pdev->dev);
+--- a/drivers/media/platform/starfive/stf_camss.h
++++ b/drivers/media/platform/starfive/stf_camss.h
+@@ -16,6 +16,7 @@
+ #include <media/v4l2-device.h>
+ 
+ #include "stf_common.h"
++#include "stf_isp.h"
+ 
+ #define DRV_NAME     "starfive-camss"
+ #define STF_DVP_NAME "stf_dvp"
+@@ -71,6 +72,7 @@ struct stfcamss {
+ 	struct media_device media_dev;
+ 	struct media_pipeline pipe;
+ 	struct device *dev;
++	struct stf_isp_dev isp_dev;
+ 	struct v4l2_async_notifier notifier;
+ 	struct host_data host_data;
+ 	void __iomem *syscon_base;
+--- /dev/null
++++ b/drivers/media/platform/starfive/stf_isp.c
+@@ -0,0 +1,550 @@
++// SPDX-License-Identifier: GPL-2.0
++/*
++ * stf_isp.c
++ *
++ * StarFive Camera Subsystem - ISP Module
++ *
++ * Copyright (C) 2021-2023 StarFive Technology Co., Ltd.
++ */
++#include <linux/firmware.h>
++#include <media/v4l2-event.h>
++
++#include "stf_camss.h"
++
++#define SINK_FORMATS_INDEX    0
++#define UO_FORMATS_INDEX      1
++
++static int isp_set_selection(struct v4l2_subdev *sd,
++			     struct v4l2_subdev_state *state,
++			     struct v4l2_subdev_selection *sel);
++
++static const struct isp_format isp_formats_sink[] = {
++	{ MEDIA_BUS_FMT_SRGGB10_1X10, 10 },
++	{ MEDIA_BUS_FMT_SGRBG10_1X10, 10 },
++	{ MEDIA_BUS_FMT_SGBRG10_1X10, 10 },
++	{ MEDIA_BUS_FMT_SBGGR10_1X10, 10 },
++};
++
++static const struct isp_format isp_formats_uo[] = {
++	{ MEDIA_BUS_FMT_Y12_1X12, 8 },
++};
++
++static const struct isp_format_table isp_formats_st7110[] = {
++	{ isp_formats_sink, ARRAY_SIZE(isp_formats_sink) },
++	{ isp_formats_uo, ARRAY_SIZE(isp_formats_uo) },
++};
++
++int stf_isp_subdev_init(struct stfcamss *stfcamss)
++{
++	struct stf_isp_dev *isp_dev = &stfcamss->isp_dev;
++
++	isp_dev->sdev_type = STF_SUBDEV_TYPE_ISP;
++	isp_dev->stfcamss = stfcamss;
++	isp_dev->formats = isp_formats_st7110;
++	isp_dev->nformats = ARRAY_SIZE(isp_formats_st7110);
++
++	mutex_init(&isp_dev->stream_lock);
++	mutex_init(&isp_dev->power_lock);
++	return 0;
++}
++
++static int isp_set_power(struct v4l2_subdev *sd, int on)
++{
++	struct stf_isp_dev *isp_dev = v4l2_get_subdevdata(sd);
++
++	mutex_lock(&isp_dev->power_lock);
++	if (on) {
++		if (isp_dev->power_count == 0)
++			dev_dbg(isp_dev->stfcamss->dev, "turn on isp\n");
++		isp_dev->power_count++;
++	} else {
++		if (isp_dev->power_count == 0)
++			goto exit;
++		isp_dev->power_count--;
++	}
++exit:
++	mutex_unlock(&isp_dev->power_lock);
++
++	return 0;
++}
++
++static struct v4l2_mbus_framefmt *
++__isp_get_format(struct stf_isp_dev *isp_dev,
++		 struct v4l2_subdev_state *state,
++		 unsigned int pad,
++		 enum v4l2_subdev_format_whence which)
++{
++	if (which == V4L2_SUBDEV_FORMAT_TRY)
++		return v4l2_subdev_get_try_format(&isp_dev->subdev, state, pad);
++
++	return &isp_dev->fmt[pad];
++}
++
++static int isp_set_stream(struct v4l2_subdev *sd, int enable)
++{
++	struct stf_isp_dev *isp_dev = v4l2_get_subdevdata(sd);
++	int ret = 0;
++	struct v4l2_mbus_framefmt *fmt;
++	struct v4l2_event src_ch = { 0 };
++
++	fmt = __isp_get_format(isp_dev, NULL, STF_ISP_PAD_SINK,
++			       V4L2_SUBDEV_FORMAT_ACTIVE);
++	mutex_lock(&isp_dev->stream_lock);
++	if (enable) {
++		if (isp_dev->stream_count == 0) {
++			stf_isp_clk_enable(isp_dev);
++			stf_isp_reset(isp_dev);
++			stf_isp_init_cfg(isp_dev);
++			stf_isp_settings(isp_dev, isp_dev->rect, fmt->code);
++			stf_isp_stream_set(isp_dev);
++		}
++		isp_dev->stream_count++;
++	} else {
++		if (isp_dev->stream_count == 0)
++			goto exit;
++
++		if (isp_dev->stream_count == 1)
++			stf_isp_clk_disable(isp_dev);
++
++		isp_dev->stream_count--;
++	}
++	src_ch.type = V4L2_EVENT_SOURCE_CHANGE,
++	src_ch.u.src_change.changes = isp_dev->stream_count,
++
++	v4l2_subdev_notify_event(sd, &src_ch);
++exit:
++	mutex_unlock(&isp_dev->stream_lock);
++
++	return ret;
++}
++
++static void isp_try_format(struct stf_isp_dev *isp_dev,
++			   struct v4l2_subdev_state *state,
++			   unsigned int pad,
++			   struct v4l2_mbus_framefmt *fmt,
++			   enum v4l2_subdev_format_whence which)
++{
++	const struct isp_format_table *formats;
++	struct stf_isp_crop *rect;
++	int i;
++
++	switch (pad) {
++	case STF_ISP_PAD_SINK:
++		/* Set format on sink pad */
++		formats = &isp_dev->formats[SINK_FORMATS_INDEX];
++		rect = &isp_dev->rect[SINK_FORMATS_INDEX];
++		fmt->width = clamp_t(u32,
++				     fmt->width, STFCAMSS_FRAME_MIN_WIDTH,
++				     STFCAMSS_FRAME_MAX_WIDTH);
++		fmt->height = clamp_t(u32,
++				      fmt->height, STFCAMSS_FRAME_MIN_HEIGHT,
++				      STFCAMSS_FRAME_MAX_HEIGHT);
++		fmt->height &= ~0x1;
++		fmt->field = V4L2_FIELD_NONE;
++		fmt->colorspace = V4L2_COLORSPACE_SRGB;
++		fmt->flags = 0;
++		break;
++
++	case STF_ISP_PAD_SRC:
++		formats = &isp_dev->formats[UO_FORMATS_INDEX];
++		rect = &isp_dev->rect[UO_FORMATS_INDEX];
++		*fmt = *__isp_get_format(isp_dev, state,
++					 STF_ISP_PAD_SINK, which);
++		break;
++	}
++
++	for (i = 0; i < formats->nfmts; i++) {
++		if (fmt->code == formats->fmts[i].code)
++			break;
++	}
++
++	if (i >= formats->nfmts) {
++		fmt->code = formats->fmts[0].code;
++		rect->bpp = formats->fmts[0].bpp;
++	} else {
++		rect->bpp = formats->fmts[i].bpp;
++	}
++}
++
++static int isp_enum_mbus_code(struct v4l2_subdev *sd,
++			      struct v4l2_subdev_state *state,
++			      struct v4l2_subdev_mbus_code_enum *code)
++{
++	struct stf_isp_dev *isp_dev = v4l2_get_subdevdata(sd);
++	const struct isp_format_table *formats;
++
++	if (code->index >= isp_dev->nformats)
++		return -EINVAL;
++	if (code->pad == STF_ISP_PAD_SINK) {
++		formats = &isp_dev->formats[SINK_FORMATS_INDEX];
++		code->code = formats->fmts[code->index].code;
++	} else {
++		struct v4l2_mbus_framefmt *sink_fmt;
++
++		sink_fmt = __isp_get_format(isp_dev, state, STF_ISP_PAD_SINK,
++					    code->which);
++
++		code->code = sink_fmt->code;
++		if (!code->code)
++			return -EINVAL;
++	}
++	code->flags = 0;
++
++	return 0;
++}
++
++static int isp_enum_frame_size(struct v4l2_subdev *sd,
++			       struct v4l2_subdev_state *state,
++			       struct v4l2_subdev_frame_size_enum *fse)
++{
++	struct stf_isp_dev *isp_dev = v4l2_get_subdevdata(sd);
++	struct v4l2_mbus_framefmt format;
++
++	if (fse->index != 0)
++		return -EINVAL;
++
++	format.code = fse->code;
++	format.width = 1;
++	format.height = 1;
++	isp_try_format(isp_dev, state, fse->pad, &format, fse->which);
++	fse->min_width = format.width;
++	fse->min_height = format.height;
++
++	if (format.code != fse->code)
++		return -EINVAL;
++
++	format.code = fse->code;
++	format.width = -1;
++	format.height = -1;
++	isp_try_format(isp_dev, state, fse->pad, &format, fse->which);
++	fse->max_width = format.width;
++	fse->max_height = format.height;
++
++	return 0;
++}
++
++static int isp_get_format(struct v4l2_subdev *sd,
++			  struct v4l2_subdev_state *state,
++			  struct v4l2_subdev_format *fmt)
++{
++	struct stf_isp_dev *isp_dev = v4l2_get_subdevdata(sd);
++	struct v4l2_mbus_framefmt *format;
++
++	format = __isp_get_format(isp_dev, state, fmt->pad, fmt->which);
++	if (!format)
++		return -EINVAL;
++
++	fmt->format = *format;
++
++	return 0;
++}
++
++static int isp_set_format(struct v4l2_subdev *sd,
++			  struct v4l2_subdev_state *state,
++			  struct v4l2_subdev_format *fmt)
++{
++	struct stf_isp_dev *isp_dev = v4l2_get_subdevdata(sd);
++	struct v4l2_mbus_framefmt *format;
++
++	format = __isp_get_format(isp_dev, state, fmt->pad, fmt->which);
++	if (!format)
++		return -EINVAL;
++
++	mutex_lock(&isp_dev->stream_lock);
++
++	isp_try_format(isp_dev, state, fmt->pad, &fmt->format, fmt->which);
++	*format = fmt->format;
++
++	mutex_unlock(&isp_dev->stream_lock);
++
++	/* Propagate to in crop */
++	if (fmt->pad == STF_ISP_PAD_SINK) {
++		struct v4l2_subdev_selection sel = { 0 };
++		int ret;
++
++		/* Reset sink pad compose selection */
++		sel.which = fmt->which;
++		sel.pad = STF_ISP_PAD_SINK;
++		sel.target = V4L2_SEL_TGT_CROP;
++		sel.r.width = fmt->format.width;
++		sel.r.height = fmt->format.height;
++		ret = isp_set_selection(sd, state, &sel);
++		if (ret < 0)
++			return ret;
++	}
++
++	return 0;
++}
++
++static struct v4l2_rect *
++__isp_get_crop(struct stf_isp_dev *isp_dev,
++	       struct v4l2_subdev_state *state,
++	       unsigned int pad,
++	       enum v4l2_subdev_format_whence which)
++{
++	if (which == V4L2_SUBDEV_FORMAT_TRY)
++		return v4l2_subdev_get_try_crop(&isp_dev->subdev, state,
++						STF_ISP_PAD_SINK);
++
++	return &isp_dev->rect[pad].rect;
++}
++
++static void isp_try_crop(struct stf_isp_dev *isp_dev,
++			 struct v4l2_subdev_state *state,
++			 struct v4l2_rect *rect,
++			 enum v4l2_subdev_format_whence which)
++{
++	struct v4l2_mbus_framefmt *fmt;
++
++	fmt = __isp_get_format(isp_dev, state, STF_ISP_PAD_SINK, which);
++
++	if (rect->width > fmt->width)
++		rect->width = fmt->width;
++
++	if (rect->width + rect->left > fmt->width)
++		rect->left = fmt->width - rect->width;
++
++	if (rect->height > fmt->height)
++		rect->height = fmt->height;
++
++	if (rect->height + rect->top > fmt->height)
++		rect->top = fmt->height - rect->height;
++
++	if (rect->width < STFCAMSS_FRAME_MIN_WIDTH) {
++		rect->left = 0;
++		rect->width = STFCAMSS_FRAME_MAX_WIDTH;
++	}
++
++	if (rect->height < STFCAMSS_FRAME_MIN_HEIGHT) {
++		rect->top = 0;
++		rect->height = STFCAMSS_FRAME_MAX_HEIGHT;
++	}
++	rect->height &= ~0x1;
++}
++
++static int isp_get_selection(struct v4l2_subdev *sd,
++			     struct v4l2_subdev_state *state,
++			     struct v4l2_subdev_selection *sel)
++{
++	struct stf_isp_dev *isp_dev = v4l2_get_subdevdata(sd);
++	struct v4l2_subdev_format fmt = { 0 };
++	struct v4l2_rect *rect;
++	int ret;
++
++	switch (sel->target) {
++	case V4L2_SEL_TGT_CROP_BOUNDS:
++		if (sel->pad == STF_ISP_PAD_SINK) {
++			fmt.pad = sel->pad;
++			fmt.which = sel->which;
++			ret = isp_get_format(sd, state, &fmt);
++			if (ret < 0)
++				return ret;
++
++			sel->r.left = 0;
++			sel->r.top = 0;
++			sel->r.width = fmt.format.width;
++			sel->r.height = fmt.format.height;
++		} else if (sel->pad == STF_ISP_PAD_SRC) {
++			rect = __isp_get_crop(isp_dev, state,
++					      sel->pad, sel->which);
++			sel->r = *rect;
++		}
++		break;
++
++	case V4L2_SEL_TGT_CROP:
++		rect = __isp_get_crop(isp_dev, state, sel->pad, sel->which);
++		if (!rect)
++			return -EINVAL;
++
++		sel->r = *rect;
++		break;
++
++	default:
++		return -EINVAL;
++	}
++
++	return 0;
++}
++
++static int isp_set_selection(struct v4l2_subdev *sd,
++			     struct v4l2_subdev_state *state,
++			     struct v4l2_subdev_selection *sel)
++{
++	struct stf_isp_dev *isp_dev = v4l2_get_subdevdata(sd);
++	struct v4l2_rect *rect;
++	int ret = 0;
++
++	if (sel->target == V4L2_SEL_TGT_CROP &&
++	    sel->pad == STF_ISP_PAD_SINK) {
++		struct v4l2_subdev_selection crop = { 0 };
++
++		rect = __isp_get_crop(isp_dev, state, sel->pad, sel->which);
++		if (!rect)
++			return -EINVAL;
++
++		mutex_lock(&isp_dev->stream_lock);
++		isp_try_crop(isp_dev, state, &sel->r, sel->which);
++		*rect = sel->r;
++		mutex_unlock(&isp_dev->stream_lock);
++
++		/* Reset source crop selection */
++		crop.which = sel->which;
++		crop.pad = STF_ISP_PAD_SRC;
++		crop.target = V4L2_SEL_TGT_CROP;
++		crop.r = *rect;
++		ret = isp_set_selection(sd, state, &crop);
++	} else if (sel->target == V4L2_SEL_TGT_CROP &&
++		   sel->pad == STF_ISP_PAD_SRC) {
++		struct v4l2_subdev_format fmt = { 0 };
++
++		rect = __isp_get_crop(isp_dev, state, sel->pad, sel->which);
++		if (!rect)
++			return -EINVAL;
++
++		mutex_lock(&isp_dev->stream_lock);
++		isp_try_crop(isp_dev, state, &sel->r, sel->which);
++		*rect = sel->r;
++		mutex_unlock(&isp_dev->stream_lock);
++
++		/* Reset source pad format width and height */
++		fmt.which = sel->which;
++		fmt.pad = STF_ISP_PAD_SRC;
++		fmt.format.width = rect->width;
++		fmt.format.height = rect->height;
++		ret = isp_set_format(sd, state, &fmt);
++		if (ret < 0)
++			return ret;
++	}
++
++	dev_dbg(isp_dev->stfcamss->dev, "pad: %d sel(%d,%d)/%dx%d\n",
++		sel->pad, sel->r.left, sel->r.top, sel->r.width, sel->r.height);
++
++	return 0;
++}
++
++static int isp_init_formats(struct v4l2_subdev *sd,
++			    struct v4l2_subdev_fh *fh)
++{
++	struct v4l2_subdev_format format = {
++		.pad = STF_ISP_PAD_SINK,
++		.which =
++			fh ? V4L2_SUBDEV_FORMAT_TRY : V4L2_SUBDEV_FORMAT_ACTIVE,
++		.format = {
++			.code = MEDIA_BUS_FMT_RGB565_2X8_LE,
++			.width = 1920,
++			.height = 1080
++		}
++	};
++
++	return isp_set_format(sd, fh ? fh->state : NULL, &format);
++}
++
++static int isp_link_setup(struct media_entity *entity,
++			  const struct media_pad *local,
++			  const struct media_pad *remote, u32 flags)
++{
++	if (flags & MEDIA_LNK_FL_ENABLED)
++		if (media_pad_remote_pad_first(local))
++			return -EBUSY;
++	return 0;
++}
++
++static int stf_isp_subscribe_event(struct v4l2_subdev *sd,
++				   struct v4l2_fh *fh,
++				   struct v4l2_event_subscription *sub)
++{
++	switch (sub->type) {
++	case V4L2_EVENT_SOURCE_CHANGE:
++		return v4l2_src_change_event_subdev_subscribe(sd, fh, sub);
++	default:
++		return -EINVAL;
++	}
++}
++
++static const struct v4l2_subdev_core_ops isp_core_ops = {
++	.s_power = isp_set_power,
++	.subscribe_event = stf_isp_subscribe_event,
++	.unsubscribe_event = v4l2_event_subdev_unsubscribe,
++};
++
++static const struct v4l2_subdev_video_ops isp_video_ops = {
++	.s_stream = isp_set_stream,
++};
++
++static const struct v4l2_subdev_pad_ops isp_pad_ops = {
++	.enum_mbus_code = isp_enum_mbus_code,
++	.enum_frame_size = isp_enum_frame_size,
++	.get_fmt = isp_get_format,
++	.set_fmt = isp_set_format,
++	.get_selection = isp_get_selection,
++	.set_selection = isp_set_selection,
++};
++
++static const struct v4l2_subdev_ops isp_v4l2_ops = {
++	.core = &isp_core_ops,
++	.video = &isp_video_ops,
++	.pad = &isp_pad_ops,
++};
++
++static const struct v4l2_subdev_internal_ops isp_v4l2_internal_ops = {
++	.open = isp_init_formats,
++};
++
++static const struct media_entity_operations isp_media_ops = {
++	.link_setup = isp_link_setup,
++	.link_validate = v4l2_subdev_link_validate,
++};
++
++int stf_isp_register(struct stf_isp_dev *isp_dev, struct v4l2_device *v4l2_dev)
++{
++	struct v4l2_subdev *sd = &isp_dev->subdev;
++	struct media_pad *pads = isp_dev->pads;
++	int ret;
++
++	v4l2_subdev_init(sd, &isp_v4l2_ops);
++	sd->internal_ops = &isp_v4l2_internal_ops;
++	sd->flags |= V4L2_SUBDEV_FL_HAS_DEVNODE | V4L2_SUBDEV_FL_HAS_EVENTS;
++	snprintf(sd->name, ARRAY_SIZE(sd->name), "%s%d", STF_ISP_NAME, 0);
++	v4l2_set_subdevdata(sd, isp_dev);
++
++	ret = isp_init_formats(sd, NULL);
++	if (ret < 0) {
++		dev_err(isp_dev->stfcamss->dev, "Failed to init format: %d\n",
++			ret);
++		return ret;
++	}
++
++	pads[STF_ISP_PAD_SINK].flags = MEDIA_PAD_FL_SINK;
++	pads[STF_ISP_PAD_SRC].flags = MEDIA_PAD_FL_SOURCE;
++
++	sd->entity.function = MEDIA_ENT_F_PROC_VIDEO_PIXEL_FORMATTER;
++	sd->entity.ops = &isp_media_ops;
++	ret = media_entity_pads_init(&sd->entity, STF_ISP_PAD_MAX, pads);
++	if (ret < 0) {
++		dev_err(isp_dev->stfcamss->dev,
++			"Failed to init media entity: %d\n", ret);
++		return ret;
++	}
++
++	ret = v4l2_device_register_subdev(v4l2_dev, sd);
++	if (ret < 0) {
++		dev_err(isp_dev->stfcamss->dev,
++			"Failed to register subdev: %d\n", ret);
++		goto err_sreg;
++	}
++
++	return 0;
++
++err_sreg:
++	media_entity_cleanup(&sd->entity);
++	return ret;
++}
++
++int stf_isp_unregister(struct stf_isp_dev *isp_dev)
++{
++	v4l2_device_unregister_subdev(&isp_dev->subdev);
++	media_entity_cleanup(&isp_dev->subdev.entity);
++	mutex_destroy(&isp_dev->stream_lock);
++	mutex_destroy(&isp_dev->power_lock);
++	return 0;
++}
+--- /dev/null
++++ b/drivers/media/platform/starfive/stf_isp.h
+@@ -0,0 +1,476 @@
++/* SPDX-License-Identifier: GPL-2.0 */
++/*
++ * stf_isp.h
++ *
++ * StarFive Camera Subsystem - ISP Module
++ *
++ * Copyright (C) 2021-2023 StarFive Technology Co., Ltd.
++ */
++
++#ifndef STF_ISP_H
++#define STF_ISP_H
++
++#include <media/media-entity.h>
++#include <media/v4l2-subdev.h>
++
++#include "stf_video.h"
++
++#define ISP_RAW_DATA_BITS       12
++#define SCALER_RATIO_MAX        1
++#define STF_ISP_REG_OFFSET_MAX  0x0fff
++#define STF_ISP_REG_DELAY_MAX   100
++
++/* isp registers */
++#define ISP_REG_CSI_INPUT_EN_AND_STATUS	0x000
++#define CSI_SCD_ERR	BIT(6)
++#define CSI_ITU656_ERR	BIT(4)
++#define CSI_ITU656_F	BIT(3)
++#define CSI_SCD_DONE	BIT(2)
++#define CSI_BUSY_S	BIT(1)
++#define CSI_EN_S	BIT(0)
++
++#define ISP_REG_CSIINTS	0x008
++#define CSI_INTS(n)	((n) << 16)
++#define CSI_SHA_M(n)	((n) << 0)
++#define CSI_INTS_MASK	GENMASK(17, 16)
++
++#define ISP_REG_CSI_MODULE_CFG	0x010
++#define CSI_DUMP_EN	BIT(19)
++#define CSI_VS_EN	BIT(18)
++#define CSI_SC_EN	BIT(17)
++#define CSI_OBA_EN	BIT(16)
++#define CSI_AWB_EN	BIT(7)
++#define CSI_LCCF_EN	BIT(6)
++#define CSI_OECFHM_EN	BIT(5)
++#define CSI_OECF_EN	BIT(4)
++#define CSI_LCBQ_EN	BIT(3)
++#define CSI_OBC_EN	BIT(2)
++#define CSI_DEC_EN	BIT(1)
++#define CSI_DC_EN	BIT(0)
++
++#define ISP_REG_SENSOR	0x014
++#define DVP_SYNC_POL(n)	((n) << 2)
++#define ITU656_EN(n)	((n) << 1)
++#define IMAGER_SEL(n)	((n) << 0)
++
++#define ISP_REG_RAW_FORMAT_CFG	0x018
++#define SMY13(n)	((n) << 14)
++#define SMY12(n)	((n) << 12)
++#define SMY11(n)	((n) << 10)
++#define SMY10(n)	((n) << 8)
++#define SMY3(n)	((n) << 6)
++#define SMY2(n)	((n) << 4)
++#define SMY1(n)	((n) << 2)
++#define SMY0(n)	((n) << 0)
++
++#define ISP_REG_PIC_CAPTURE_START_CFG	0x01c
++#define VSTART_CAP(n)	((n) << 16)
++#define HSTART_CAP(n)	((n) << 0)
++
++#define ISP_REG_PIC_CAPTURE_END_CFG	0x020
++#define VEND_CAP(n)	((n) << 16)
++#define HEND_CAP(n)	((n) << 0)
++
++#define ISP_REG_DUMP_CFG_0	0x024
++#define ISP_REG_DUMP_CFG_1	0x028
++#define DUMP_ID(n)	((n) << 24)
++#define DUMP_SHT(n)	((n) << 20)
++#define DUMP_BURST_LEN(n)	((n) << 16)
++#define DUMP_SD(n)	((n) << 0)
++#define DUMP_BURST_LEN_MASK	GENMASK(17, 16)
++#define DUMP_SD_MASK	GENMASK(15, 0)
++
++#define ISP_REG_DEC_CFG	0x030
++#define DEC_V_KEEP(n)	((n) << 24)
++#define DEC_V_PERIOD(n)	((n) << 16)
++#define DEC_H_KEEP(n)	((n) << 8)
++#define DEC_H_PERIOD(n)	((n) << 0)
++
++#define ISP_REG_OBC_CFG	0x034
++#define OBC_W_H(y)	((y) << 4)
++#define OBC_W_W(x)	((x) << 0)
++
++#define ISP_REG_DC_CFG_1	0x044
++#define DC_AXI_ID(n)	((n) << 0)
++
++#define ISP_REG_LCCF_CFG_0	0x050
++#define Y_DISTANCE(y)	((y) << 16)
++#define X_DISTANCE(x)	((x) << 16)
++
++#define ISP_REG_LCCF_CFG_1	0x058
++#define LCCF_MAX_DIS(n)	((n) << 0)
++
++#define ISP_REG_LCBQ_CFG_0	0x074
++#define H_LCBQ(y)	((y) << 12)
++#define W_LCBQ(x)	((x) << 8)
++
++#define ISP_REG_LCBQ_CFG_1	0x07c
++#define Y_COOR(y)	((y) << 16)
++#define X_COOR(x)	((x) << 0)
++
++#define ISP_REG_OECF_X0_CFG0	0x100
++#define ISP_REG_OECF_X0_CFG1	0x104
++#define ISP_REG_OECF_X0_CFG2	0x108
++#define ISP_REG_OECF_X0_CFG3	0x10c
++#define ISP_REG_OECF_X0_CFG4	0x110
++#define ISP_REG_OECF_X0_CFG5	0x114
++#define ISP_REG_OECF_X0_CFG6	0x118
++#define ISP_REG_OECF_X0_CFG7	0x11c
++
++#define ISP_REG_OECF_Y3_CFG0	0x1e0
++#define ISP_REG_OECF_Y3_CFG1	0x1e4
++#define ISP_REG_OECF_Y3_CFG2	0x1e8
++#define ISP_REG_OECF_Y3_CFG3	0x1ec
++#define ISP_REG_OECF_Y3_CFG4	0x1f0
++#define ISP_REG_OECF_Y3_CFG5	0x1f4
++#define ISP_REG_OECF_Y3_CFG6	0x1f8
++#define ISP_REG_OECF_Y3_CFG7	0x1fc
++
++#define ISP_REG_OECF_S0_CFG0	0x200
++#define ISP_REG_OECF_S3_CFG7	0x27c
++#define OCEF_PAR_H(n)	((n) << 16)
++#define OCEF_PAR_L(n)	((n) << 0)
++
++#define ISP_REG_AWB_X0_CFG_0	0x280
++#define ISP_REG_AWB_X0_CFG_1	0x284
++#define ISP_REG_AWB_X1_CFG_0	0x288
++#define ISP_REG_AWB_X1_CFG_1	0x28c
++#define ISP_REG_AWB_X2_CFG_0	0x290
++#define ISP_REG_AWB_X2_CFG_1	0x294
++#define ISP_REG_AWB_X3_CFG_0	0x298
++#define ISP_REG_AWB_X3_CFG_1	0x29c
++#define AWB_X_SYMBOL_H(n)	((n) << 16)
++#define AWB_X_SYMBOL_L(n)	((n) << 0)
++
++#define ISP_REG_AWB_Y0_CFG_0	0x2a0
++#define ISP_REG_AWB_Y0_CFG_1	0x2a4
++#define ISP_REG_AWB_Y1_CFG_0	0x2a8
++#define ISP_REG_AWB_Y1_CFG_1	0x2ac
++#define ISP_REG_AWB_Y2_CFG_0	0x2b0
++#define ISP_REG_AWB_Y2_CFG_1	0x2b4
++#define ISP_REG_AWB_Y3_CFG_0	0x2b8
++#define ISP_REG_AWB_Y3_CFG_1	0x2bc
++#define AWB_Y_SYMBOL_H(n)	((n) << 16)
++#define AWB_Y_SYMBOL_L(n)	((n) << 0)
++
++#define ISP_REG_AWB_S0_CFG_0	0x2c0
++#define ISP_REG_AWB_S0_CFG_1	0x2c4
++#define ISP_REG_AWB_S1_CFG_0	0x2c8
++#define ISP_REG_AWB_S1_CFG_1	0x2cc
++#define ISP_REG_AWB_S2_CFG_0	0x2d0
++#define ISP_REG_AWB_S2_CFG_1	0x2d4
++#define ISP_REG_AWB_S3_CFG_0	0x2d8
++#define ISP_REG_AWB_S3_CFG_1	0x2dc
++#define AWB_S_SYMBOL_H(n)	((n) << 16)
++#define AWB_S_SYMBOL_L(n)	((n) << 0)
++
++#define ISP_REG_OBCG_CFG_0	0x2e0
++#define ISP_REG_OBCG_CFG_1	0x2e4
++#define ISP_REG_OBCG_CFG_2	0x2e8
++#define ISP_REG_OBCG_CFG_3	0x2ec
++#define ISP_REG_OBCO_CFG_0	0x2f0
++#define ISP_REG_OBCO_CFG_1	0x2f4
++#define ISP_REG_OBCO_CFG_2	0x2f8
++#define ISP_REG_OBCO_CFG_3	0x2fc
++#define GAIN_D_POINT(x)	((x) << 24)
++#define GAIN_C_POINT(x)	((x) << 16)
++#define GAIN_B_POINT(x)	((x) << 8)
++#define GAIN_A_POINT(x)	((x) << 0)
++#define OFFSET_D_POINT(x)	((x) << 24)
++#define OFFSET_C_POINT(x)	((x) << 16)
++#define OFFSET_B_POINT(x)	((x) << 8)
++#define OFFSET_A_POINT(x)	((x) << 0)
++
++#define ISP_REG_ISP_CTRL_0	0xa00
++#define ISPC_SCFEINT	BIT(27)
++#define ISPC_VSFWINT	BIT(26)
++#define ISPC_VSINT	BIT(25)
++#define ISPC_INTS	BIT(24)
++#define ISPC_ENUO	BIT(20)
++#define ISPC_ENLS	BIT(17)
++#define ISPC_ENSS1	BIT(12)
++#define ISPC_ENSS0	BIT(11)
++#define ISPC_RST	BIT(1)
++#define ISPC_EN	BIT(0)
++#define ISPC_RST_MASK	BIT(1)
++
++#define ISP_REG_ISP_CTRL_1	0xa08
++#define CTRL_SAT(n)	((n) << 28)
++#define CTRL_DBC	BIT(22)
++#define CTRL_CTC	BIT(21)
++#define CTRL_YHIST	BIT(20)
++#define CTRL_YCURVE	BIT(19)
++#define CTRL_CTM	BIT(18)
++#define CTRL_BIYUV	BIT(17)
++#define CTRL_SCE	BIT(8)
++#define CTRL_EE	BIT(7)
++#define CTRL_CCE	BIT(5)
++#define CTRL_RGE	BIT(4)
++#define CTRL_CME	BIT(3)
++#define CTRL_AE	BIT(2)
++#define CTRL_CE	BIT(1)
++#define CTRL_SAT_MASK	GENMASK(31, 28)
++
++#define ISP_REG_PIPELINE_XY_SIZE	0xa0c
++#define H_ACT_CAP(n)	((n) << 16)
++#define W_ACT_CAP(n)	((n) << 0)
++
++#define ISP_REG_ICTC	0xa10
++#define GF_MODE(n)	((n) << 30)
++#define MAXGT(n)	((n) << 16)
++#define MINGT(n)	((n) << 0)
++
++#define ISP_REG_IDBC	0xa14
++#define BADGT(n)	((n) << 16)
++#define BADXT(n)	((n) << 0)
++
++#define ISP_REG_ICFAM	0xa1c
++#define CROSS_COV(n)	((n) << 4)
++#define HV_W(n)	((n) << 0)
++
++#define ISP_REG_CS_GAIN	0xa30
++#define CMAD(n)	((n) << 16)
++#define CMAB(n)	((n) << 0)
++
++#define ISP_REG_CS_THRESHOLD	0xa34
++#define CMD(n)	((n) << 16)
++#define CMB(n)	((n) << 0)
++
++#define ISP_REG_CS_OFFSET	0xa38
++#define VOFF(n)	((n) << 16)
++#define UOFF(n)	((n) << 0)
++
++#define ISP_REG_CS_HUE_F	0xa3c
++#define SIN(n)	((n) << 16)
++#define COS(n)	((n) << 0)
++
++#define ISP_REG_CS_SCALE	0xa40
++#define CMSF(n)	((n) << 0)
++
++#define ISP_REG_IESHD	0xa50
++#define SHAD_UP_M	BIT(1)
++#define SHAD_UP_EN	BIT(0)
++
++#define ISP_REG_YADJ0	0xa54
++#define YOIR(n)	((n) << 16)
++#define YIMIN(n)	((n) << 0)
++
++#define ISP_REG_YADJ1	0xa58
++#define YOMAX(n)	((n) << 16)
++#define YOMIN(n)	((n) << 0)
++
++#define ISP_REG_Y_PLANE_START_ADDR	0xa80
++#define ISP_REG_UV_PLANE_START_ADDR	0xa84
++
++#define ISP_REG_STRIDE	0xa88
++#define IMG_STR(n)	((n) << 0)
++
++#define ISP_REG_ITIIWSR	0xb20
++#define ITI_HSIZE(n)	((n) << 16)
++#define ITI_WSIZE(n)	((n) << 0)
++
++#define ISP_REG_ITIDWLSR	0xb24
++#define ITI_WSTRIDE(n)	((n) << 0)
++
++#define ISP_REG_ITIPDFR	0xb38
++#define ITI_PACKAGE_FMT(n)	((n) << 0)
++
++#define ISP_REG_ITIDRLSR	0xb3C
++#define ITI_STRIDE_L(n)	((n) << 0)
++
++#define ISP_REG_DNYUV_YSWR0	0xc00
++#define ISP_REG_DNYUV_YSWR1	0xc04
++#define ISP_REG_DNYUV_CSWR0	0xc08
++#define ISP_REG_DNYUV_CSWR1	0xc0c
++#define YUVSW5(n)	((n) << 20)
++#define YUVSW4(n)	((n) << 16)
++#define YUVSW3(n)	((n) << 12)
++#define YUVSW2(n)	((n) << 8)
++#define YUVSW1(n)	((n) << 4)
++#define YUVSW0(n)	((n) << 0)
++
++#define ISP_REG_DNYUV_YDR0	0xc10
++#define ISP_REG_DNYUV_YDR1	0xc14
++#define ISP_REG_DNYUV_YDR2	0xc18
++#define ISP_REG_DNYUV_CDR0	0xc1c
++#define ISP_REG_DNYUV_CDR1	0xc20
++#define ISP_REG_DNYUV_CDR2	0xc24
++#define CURVE_D_H(n)	((n) << 16)
++#define CURVE_D_L(n)	((n) << 0)
++
++#define ISP_REG_ICAMD_0	0xc40
++#define DNRM_F(n)	((n) << 16)
++#define ISP_REG_ICAMD_12	0xc70
++#define ISP_REG_ICAMD_20	0xc90
++#define ISP_REG_ICAMD_24	0xca0
++#define ISP_REG_ICAMD_25	0xca4
++#define CCM_M_DAT(n)	((n) << 0)
++
++#define ISP_REG_GAMMA_VAL0	0xe00
++#define ISP_REG_GAMMA_VAL1	0xe04
++#define ISP_REG_GAMMA_VAL2	0xe08
++#define ISP_REG_GAMMA_VAL3	0xe0c
++#define ISP_REG_GAMMA_VAL4	0xe10
++#define ISP_REG_GAMMA_VAL5	0xe14
++#define ISP_REG_GAMMA_VAL6	0xe18
++#define ISP_REG_GAMMA_VAL7	0xe1c
++#define ISP_REG_GAMMA_VAL8	0xe20
++#define ISP_REG_GAMMA_VAL9	0xe24
++#define ISP_REG_GAMMA_VAL10	0xe28
++#define ISP_REG_GAMMA_VAL11	0xe2c
++#define ISP_REG_GAMMA_VAL12	0xe30
++#define ISP_REG_GAMMA_VAL13	0xe34
++#define ISP_REG_GAMMA_VAL14	0xe38
++#define GAMMA_S_VAL(n)	((n) << 16)
++#define GAMMA_VAL(n)	((n) << 0)
++
++#define ISP_REG_R2Y_0	0xe40
++#define ISP_REG_R2Y_1	0xe44
++#define ISP_REG_R2Y_2	0xe48
++#define ISP_REG_R2Y_3	0xe4c
++#define ISP_REG_R2Y_4	0xe50
++#define ISP_REG_R2Y_5	0xe54
++#define ISP_REG_R2Y_6	0xe58
++#define ISP_REG_R2Y_7	0xe5c
++#define ISP_REG_R2Y_8	0xe60
++#define CSC_M(n)	((n) << 0)
++
++#define ISP_REG_SHARPEN0	0xe80
++#define ISP_REG_SHARPEN1	0xe84
++#define ISP_REG_SHARPEN2	0xe88
++#define ISP_REG_SHARPEN3	0xe8c
++#define ISP_REG_SHARPEN4	0xe90
++#define ISP_REG_SHARPEN5	0xe94
++#define ISP_REG_SHARPEN6	0xe98
++#define ISP_REG_SHARPEN7	0xe9c
++#define ISP_REG_SHARPEN8	0xea0
++#define ISP_REG_SHARPEN9	0xea4
++#define ISP_REG_SHARPEN10	0xea8
++#define ISP_REG_SHARPEN11	0xeac
++#define ISP_REG_SHARPEN12	0xeb0
++#define ISP_REG_SHARPEN13	0xeb4
++#define ISP_REG_SHARPEN14	0xeb8
++#define S_DELTA(n)	((n) << 16)
++#define S_WEIGHT(n)	((n) << 8)
++
++#define ISP_REG_SHARPEN_FS0	0xebc
++#define ISP_REG_SHARPEN_FS1	0xec0
++#define ISP_REG_SHARPEN_FS2	0xec4
++#define ISP_REG_SHARPEN_FS3	0xec8
++#define ISP_REG_SHARPEN_FS4	0xecc
++#define ISP_REG_SHARPEN_FS5	0xed0
++#define S_FACTOR(n)	((n) << 24)
++#define S_SLOPE(n)	((n) << 0)
++
++#define ISP_REG_SHARPEN_WN	0xed4
++#define PDIRF(n)	((n) << 28)
++#define NDIRF(n)	((n) << 24)
++#define WSUM(n)	((n) << 0)
++
++#define ISP_REG_IUVS1	0xed8
++#define UVDIFF2(n)	((n) << 16)
++#define UVDIFF1(n)	((n) << 0)
++
++#define ISP_REG_IUVS2	0xedc
++#define UVF(n)	((n) << 24)
++#define UVSLOPE(n)	((n) << 0)
++
++#define ISP_REG_IUVCKS1	0xee0
++#define UVCKDIFF2(n)	((n) << 16)
++#define UVCKDIFF1(n)	((n) << 0)
++
++#define ISP_REG_IUVCKS2	0xee4
++#define UVCKSLOPE(n)	((n) << 0)
++
++#define ISP_REG_ISHRPET	0xee8
++#define TH(n)	((n) << 8)
++#define EN(n)	((n) << 0)
++
++#define ISP_REG_YCURVE_0	0xf00
++#define ISP_REG_YCURVE_63	0xffc
++#define L_PARAM(n)	((n) << 0)
++
++#define IMAGE_MAX_WIDTH	1920
++#define IMAGE_MAX_HEIGH	1080
++
++/* The output line of ISP */
++enum isp_line_id {
++	STF_ISP_LINE_INVALID = -1,
++	STF_ISP_LINE_SRC = 1,
++	STF_ISP_LINE_MAX = STF_ISP_LINE_SRC
++};
++
++/* pad id for media framework */
++enum isp_pad_id {
++	STF_ISP_PAD_SINK = 0,
++	STF_ISP_PAD_SRC,
++	STF_ISP_PAD_MAX
++};
++
++enum {
++	EN_INT_NONE                 = 0,
++	EN_INT_ISP_DONE             = (0x1 << 24),
++	EN_INT_CSI_DONE             = (0x1 << 25),
++	EN_INT_SC_DONE              = (0x1 << 26),
++	EN_INT_LINE_INT             = (0x1 << 27),
++	EN_INT_ALL                  = (0xF << 24),
++};
++
++enum {
++	INTERFACE_DVP = 0,
++	INTERFACE_CSI,
++};
++
++struct isp_format {
++	u32 code;
++	u8 bpp;
++};
++
++struct isp_format_table {
++	const struct isp_format *fmts;
++	int nfmts;
++};
++
++struct regval_t {
++	u32 addr;
++	u32 val;
++	u32 delay_ms;
++};
++
++struct reg_table {
++	const struct regval_t *regval;
++	int regval_num;
++};
++
++struct stf_isp_crop {
++	struct v4l2_rect rect;
++	u32 bpp;
++};
++
++struct stf_isp_dev {
++	enum stf_subdev_type sdev_type;  /* This member must be first */
++	struct stfcamss *stfcamss;
++	struct v4l2_subdev subdev;
++	struct media_pad pads[STF_ISP_PAD_MAX];
++	struct v4l2_mbus_framefmt fmt[STF_ISP_PAD_MAX];
++	struct stf_isp_crop rect[STF_ISP_PAD_MAX];
++	const struct isp_format_table *formats;
++	unsigned int nformats;
++	struct mutex power_lock;	/* serialize power control*/
++	int power_count;
++	struct mutex stream_lock;	/* serialize stream control */
++	int stream_count;
++};
++
++int stf_isp_clk_enable(struct stf_isp_dev *isp_dev);
++int stf_isp_clk_disable(struct stf_isp_dev *isp_dev);
++int stf_isp_reset(struct stf_isp_dev *isp_dev);
++void stf_isp_init_cfg(struct stf_isp_dev *isp_dev);
++void stf_isp_settings(struct stf_isp_dev *isp_dev,
++		      struct stf_isp_crop *crop_array, u32 mcode);
++void stf_isp_stream_set(struct stf_isp_dev *isp_dev);
++int stf_isp_subdev_init(struct stfcamss *stfcamss);
++int stf_isp_register(struct stf_isp_dev *isp_dev, struct v4l2_device *v4l2_dev);
++int stf_isp_unregister(struct stf_isp_dev *isp_dev);
++
++#endif /* STF_ISP_H */
+--- /dev/null
++++ b/drivers/media/platform/starfive/stf_isp_hw_ops.c
+@@ -0,0 +1,452 @@
++// SPDX-License-Identifier: GPL-2.0
++/*
++ * stf_isp_hw_ops.c
++ *
++ * Register interface file for StarFive ISP driver
++ *
++ * Copyright (C) 2021-2023 StarFive Technology Co., Ltd.
++ *
++ */
++
++#include "stf_camss.h"
++
++static void stf_isp_config_obc(struct stfcamss *stfcamss)
++{
++	u32 reg_val, reg_add;
++
++	stf_isp_reg_write(stfcamss, ISP_REG_OBC_CFG, OBC_W_H(11) | OBC_W_W(11));
++
++	reg_val = GAIN_D_POINT(0x40) | GAIN_C_POINT(0x40) |
++		  GAIN_B_POINT(0x40) | GAIN_A_POINT(0x40);
++	for (reg_add = ISP_REG_OBCG_CFG_0; reg_add <= ISP_REG_OBCG_CFG_3;) {
++		stf_isp_reg_write(stfcamss, reg_add, reg_val);
++		reg_add += 4;
++	}
++
++	reg_val = OFFSET_D_POINT(0) | OFFSET_C_POINT(0) |
++		  OFFSET_B_POINT(0) | OFFSET_A_POINT(0);
++	for (reg_add = ISP_REG_OBCO_CFG_0; reg_add <= ISP_REG_OBCO_CFG_3;) {
++		stf_isp_reg_write(stfcamss, reg_add, reg_val);
++		reg_add += 4;
++	}
++}
++
++static void stf_isp_config_oecf(struct stfcamss *stfcamss)
++{
++	u32 reg_add, par_val;
++	u16 par_h, par_l;
++
++	par_h = 0x10; par_l = 0;
++	par_val = OCEF_PAR_H(par_h) | OCEF_PAR_L(par_l);
++	for (reg_add = ISP_REG_OECF_X0_CFG0; reg_add <= ISP_REG_OECF_Y3_CFG0;) {
++		stf_isp_reg_write(stfcamss, reg_add, par_val);
++		reg_add += 0x20;
++	}
++
++	par_h = 0x40; par_l = 0x20;
++	par_val = OCEF_PAR_H(par_h) | OCEF_PAR_L(par_l);
++	for (reg_add = ISP_REG_OECF_X0_CFG1; reg_add <= ISP_REG_OECF_Y3_CFG1;) {
++		stf_isp_reg_write(stfcamss, reg_add, par_val);
++		reg_add += 0x20;
++	}
++
++	par_h = 0x80; par_l = 0x60;
++	par_val = OCEF_PAR_H(par_h) | OCEF_PAR_L(par_l);
++	for (reg_add = ISP_REG_OECF_X0_CFG2; reg_add <= ISP_REG_OECF_Y3_CFG2;) {
++		stf_isp_reg_write(stfcamss, reg_add, par_val);
++		reg_add += 0x20;
++	}
++
++	par_h = 0xc0; par_l = 0xa0;
++	par_val = OCEF_PAR_H(par_h) | OCEF_PAR_L(par_l);
++	for (reg_add = ISP_REG_OECF_X0_CFG3; reg_add <= ISP_REG_OECF_Y3_CFG3;) {
++		stf_isp_reg_write(stfcamss, reg_add, par_val);
++		reg_add += 0x20;
++	}
++
++	par_h = 0x100; par_l = 0xe0;
++	par_val = OCEF_PAR_H(par_h) | OCEF_PAR_L(par_l);
++	for (reg_add = ISP_REG_OECF_X0_CFG4; reg_add <= ISP_REG_OECF_Y3_CFG4;) {
++		stf_isp_reg_write(stfcamss, reg_add, par_val);
++		reg_add += 0x20;
++	}
++
++	par_h = 0x200; par_l = 0x180;
++	par_val = OCEF_PAR_H(par_h) | OCEF_PAR_L(par_l);
++	for (reg_add = ISP_REG_OECF_X0_CFG5; reg_add <= ISP_REG_OECF_Y3_CFG5;) {
++		stf_isp_reg_write(stfcamss, reg_add, par_val);
++		reg_add += 0x20;
++	}
++
++	par_h = 0x300; par_l = 0x280;
++	par_val = OCEF_PAR_H(par_h) | OCEF_PAR_L(par_l);
++	for (reg_add = ISP_REG_OECF_X0_CFG6; reg_add <= ISP_REG_OECF_Y3_CFG6;) {
++		stf_isp_reg_write(stfcamss, reg_add, par_val);
++		reg_add += 0x20;
++	}
++
++	par_h = 0x3fe; par_l = 0x380;
++	par_val = OCEF_PAR_H(par_h) | OCEF_PAR_L(par_l);
++	for (reg_add = ISP_REG_OECF_X0_CFG7; reg_add <= ISP_REG_OECF_Y3_CFG7;) {
++		stf_isp_reg_write(stfcamss, reg_add, par_val);
++		reg_add += 0x20;
++	}
++
++	par_h = 0x80; par_l = 0x80;
++	par_val = OCEF_PAR_H(par_h) | OCEF_PAR_L(par_l);
++	for (reg_add = ISP_REG_OECF_S0_CFG0; reg_add <= ISP_REG_OECF_S3_CFG7;) {
++		stf_isp_reg_write(stfcamss, reg_add, par_val);
++		reg_add += 4;
++	}
++}
++
++static void stf_isp_config_awb(struct stfcamss *stfcamss)
++{
++	u32 reg_val, reg_add;
++	u16 symbol_h, symbol_l;
++
++	symbol_h = 0x0; symbol_l = 0x0;
++	reg_val = AWB_X_SYMBOL_H(symbol_h) | AWB_X_SYMBOL_L(symbol_l);
++
++	for (reg_add = ISP_REG_AWB_X0_CFG_0; reg_add <= ISP_REG_AWB_X3_CFG_1;) {
++		stf_isp_reg_write(stfcamss, reg_add, reg_val);
++		reg_add += 4;
++	}
++
++	symbol_h = 0x0, symbol_l = 0x0;
++	reg_val = AWB_Y_SYMBOL_H(symbol_h) | AWB_Y_SYMBOL_L(symbol_l);
++
++	for (reg_add = ISP_REG_AWB_Y0_CFG_0; reg_add <= ISP_REG_AWB_Y3_CFG_1;) {
++		stf_isp_reg_write(stfcamss, reg_add, reg_val);
++		reg_add += 4;
++	}
++
++	symbol_h = 0x80, symbol_l = 0x80;
++	reg_val = AWB_S_SYMBOL_H(symbol_h) | AWB_S_SYMBOL_L(symbol_l);
++
++	for (reg_add = ISP_REG_AWB_S0_CFG_0; reg_add <= ISP_REG_AWB_S3_CFG_1;) {
++		stf_isp_reg_write(stfcamss, reg_add, reg_val);
++		reg_add += 4;
++	}
++}
++
++static void stf_isp_config_grgb(struct stfcamss *stfcamss)
++{
++	stf_isp_reg_write(stfcamss, ISP_REG_ICTC,
++			  GF_MODE(1) | MAXGT(0x140) | MINGT(0x40));
++	stf_isp_reg_write(stfcamss, ISP_REG_IDBC, BADGT(0x200) | BADXT(0x200));
++}
++
++static void stf_isp_config_cfa(struct stfcamss *stfcamss)
++{
++	stf_isp_reg_write(stfcamss, ISP_REG_RAW_FORMAT_CFG,
++			  SMY13(0) | SMY12(1) | SMY11(0) | SMY10(1) | SMY3(2) |
++			  SMY2(3) | SMY1(2) | SMY0(3));
++	stf_isp_reg_write(stfcamss, ISP_REG_ICFAM, CROSS_COV(3) | HV_W(2));
++}
++
++static void stf_isp_config_ccm(struct stfcamss *stfcamss)
++{
++	u32 reg_add;
++
++	stf_isp_reg_write(stfcamss, ISP_REG_ICAMD_0, DNRM_F(6) | CCM_M_DAT(0));
++
++	for (reg_add = ISP_REG_ICAMD_12; reg_add <= ISP_REG_ICAMD_20;) {
++		stf_isp_reg_write(stfcamss, reg_add, CCM_M_DAT(0x80));
++		reg_add += 0x10;
++	}
++
++	stf_isp_reg_write(stfcamss, ISP_REG_ICAMD_24, CCM_M_DAT(0x700));
++	stf_isp_reg_write(stfcamss, ISP_REG_ICAMD_25, CCM_M_DAT(0x200));
++}
++
++static void stf_isp_config_gamma(struct stfcamss *stfcamss)
++{
++	u32 reg_val, reg_add;
++	u16 gamma_slope_v, gamma_v;
++
++	gamma_slope_v = 0x2400; gamma_v = 0x0;
++	reg_val = GAMMA_S_VAL(gamma_slope_v) | GAMMA_VAL(gamma_v);
++	stf_isp_reg_write(stfcamss, ISP_REG_GAMMA_VAL0, reg_val);
++
++	gamma_slope_v = 0x800; gamma_v = 0x20;
++	for (reg_add = ISP_REG_GAMMA_VAL1; reg_add <= ISP_REG_GAMMA_VAL7;) {
++		reg_val = GAMMA_S_VAL(gamma_slope_v) | GAMMA_VAL(gamma_v);
++		stf_isp_reg_write(stfcamss, reg_add, reg_val);
++		reg_add += 4;
++		gamma_v += 0x20;
++	}
++
++	gamma_v = 0x100;
++	for (reg_add = ISP_REG_GAMMA_VAL8; reg_add <= ISP_REG_GAMMA_VAL13;) {
++		reg_val = GAMMA_S_VAL(gamma_slope_v) | GAMMA_VAL(gamma_v);
++		stf_isp_reg_write(stfcamss, reg_add, reg_val);
++		reg_add += 4;
++		gamma_v += 0x80;
++	}
++
++	gamma_v = 0x3fe;
++	reg_val = GAMMA_S_VAL(gamma_slope_v) | GAMMA_VAL(gamma_v);
++	stf_isp_reg_write(stfcamss, ISP_REG_GAMMA_VAL14, reg_val);
++}
++
++static void stf_isp_config_r2y(struct stfcamss *stfcamss)
++{
++	stf_isp_reg_write(stfcamss, ISP_REG_R2Y_0, CSC_M(0x4C));
++	stf_isp_reg_write(stfcamss, ISP_REG_R2Y_1, CSC_M(0x97));
++	stf_isp_reg_write(stfcamss, ISP_REG_R2Y_2, CSC_M(0x1d));
++	stf_isp_reg_write(stfcamss, ISP_REG_R2Y_3, CSC_M(0x1d5));
++	stf_isp_reg_write(stfcamss, ISP_REG_R2Y_4, CSC_M(0x1ac));
++	stf_isp_reg_write(stfcamss, ISP_REG_R2Y_5, CSC_M(0x80));
++	stf_isp_reg_write(stfcamss, ISP_REG_R2Y_6, CSC_M(0x80));
++	stf_isp_reg_write(stfcamss, ISP_REG_R2Y_7, CSC_M(0x194));
++	stf_isp_reg_write(stfcamss, ISP_REG_R2Y_8, CSC_M(0x1ec));
++}
++
++static void stf_isp_config_y_curve(struct stfcamss *stfcamss)
++{
++	u32 reg_add;
++	u16 y_curve;
++
++	y_curve = 0x0;
++	for (reg_add = ISP_REG_YCURVE_0; reg_add <= ISP_REG_YCURVE_63;) {
++		stf_isp_reg_write(stfcamss, reg_add, y_curve);
++		reg_add += 4;
++		y_curve += 0x10;
++	}
++}
++
++static void stf_isp_config_sharpen(struct stfcamss *sc)
++{
++	u32 reg_add;
++
++	stf_isp_reg_write(sc, ISP_REG_SHARPEN0, S_DELTA(0x7) | S_WEIGHT(0xf));
++	stf_isp_reg_write(sc, ISP_REG_SHARPEN1, S_DELTA(0x18) | S_WEIGHT(0xf));
++	stf_isp_reg_write(sc, ISP_REG_SHARPEN2, S_DELTA(0x80) | S_WEIGHT(0xf));
++	stf_isp_reg_write(sc, ISP_REG_SHARPEN3, S_DELTA(0x100) | S_WEIGHT(0xf));
++	stf_isp_reg_write(sc, ISP_REG_SHARPEN4, S_DELTA(0x10) | S_WEIGHT(0xf));
++	stf_isp_reg_write(sc, ISP_REG_SHARPEN5, S_DELTA(0x60) | S_WEIGHT(0xf));
++	stf_isp_reg_write(sc, ISP_REG_SHARPEN6, S_DELTA(0x100) | S_WEIGHT(0xf));
++	stf_isp_reg_write(sc, ISP_REG_SHARPEN7, S_DELTA(0x190) | S_WEIGHT(0xf));
++	stf_isp_reg_write(sc, ISP_REG_SHARPEN8, S_DELTA(0x0) | S_WEIGHT(0xf));
++
++	for (reg_add = ISP_REG_SHARPEN9; reg_add <= ISP_REG_SHARPEN14;) {
++		stf_isp_reg_write(sc, reg_add, S_WEIGHT(0xf));
++		reg_add += 4;
++	}
++
++	for (reg_add = ISP_REG_SHARPEN_FS0; reg_add <= ISP_REG_SHARPEN_FS5;) {
++		stf_isp_reg_write(sc, reg_add, S_FACTOR(0x10) | S_SLOPE(0x0));
++		reg_add += 4;
++	}
++
++	stf_isp_reg_write(sc, ISP_REG_SHARPEN_WN,
++			  PDIRF(0x8) | NDIRF(0x8) | WSUM(0xd7c));
++	stf_isp_reg_write(sc, ISP_REG_IUVS1, UVDIFF2(0xC0) | UVDIFF1(0x40));
++	stf_isp_reg_write(sc, ISP_REG_IUVS2, UVF(0xff) | UVSLOPE(0x0));
++	stf_isp_reg_write(sc, ISP_REG_IUVCKS1,
++			  UVCKDIFF2(0xa0) | UVCKDIFF1(0x40));
++}
++
++static void stf_isp_config_dnyuv(struct stfcamss *stfcamss)
++{
++	u32 reg_val;
++
++	reg_val = YUVSW5(7) | YUVSW4(7) | YUVSW3(7) | YUVSW2(7) |
++		  YUVSW1(7) | YUVSW0(7);
++	stf_isp_reg_write(stfcamss, ISP_REG_DNYUV_YSWR0, reg_val);
++	stf_isp_reg_write(stfcamss, ISP_REG_DNYUV_CSWR0, reg_val);
++
++	reg_val = YUVSW3(7) | YUVSW2(7) | YUVSW1(7) | YUVSW0(7);
++	stf_isp_reg_write(stfcamss, ISP_REG_DNYUV_YSWR1, reg_val);
++	stf_isp_reg_write(stfcamss, ISP_REG_DNYUV_CSWR1, reg_val);
++
++	reg_val = CURVE_D_H(0x60) | CURVE_D_L(0x40);
++	stf_isp_reg_write(stfcamss, ISP_REG_DNYUV_YDR0, reg_val);
++	stf_isp_reg_write(stfcamss, ISP_REG_DNYUV_CDR0, reg_val);
++
++	reg_val = CURVE_D_H(0xd8) | CURVE_D_L(0x90);
++	stf_isp_reg_write(stfcamss, ISP_REG_DNYUV_YDR1, reg_val);
++	stf_isp_reg_write(stfcamss, ISP_REG_DNYUV_CDR1, reg_val);
++
++	reg_val = CURVE_D_H(0x1e6) | CURVE_D_L(0x144);
++	stf_isp_reg_write(stfcamss, ISP_REG_DNYUV_YDR2, reg_val);
++	stf_isp_reg_write(stfcamss, ISP_REG_DNYUV_CDR2, reg_val);
++}
++
++static void stf_isp_config_sat(struct stfcamss *stfcamss)
++{
++	stf_isp_reg_write(stfcamss, ISP_REG_CS_GAIN, CMAD(0x0) | CMAB(0x100));
++	stf_isp_reg_write(stfcamss, ISP_REG_CS_THRESHOLD, CMD(0x1f) | CMB(0x1));
++	stf_isp_reg_write(stfcamss, ISP_REG_CS_OFFSET, VOFF(0x0) | UOFF(0x0));
++	stf_isp_reg_write(stfcamss, ISP_REG_CS_HUE_F, SIN(0x0) | COS(0x100));
++	stf_isp_reg_write(stfcamss, ISP_REG_CS_SCALE, CMSF(0x8));
++	stf_isp_reg_write(stfcamss, ISP_REG_YADJ0, YOIR(0x401) | YIMIN(0x1));
++	stf_isp_reg_write(stfcamss, ISP_REG_YADJ1, YOMAX(0x3ff) | YOMIN(0x1));
++}
++
++int stf_isp_clk_enable(struct stf_isp_dev *isp_dev)
++{
++	struct stfcamss *stfcamss = isp_dev->stfcamss;
++
++	clk_prepare_enable(stfcamss->sys_clk[STF_CLK_WRAPPER_CLK_C].clk);
++	reset_control_deassert(stfcamss->sys_rst[STF_RST_WRAPPER_C].rstc);
++	reset_control_deassert(stfcamss->sys_rst[STF_RST_WRAPPER_P].rstc);
++
++	return 0;
++}
++
++int stf_isp_clk_disable(struct stf_isp_dev *isp_dev)
++{
++	struct stfcamss *stfcamss = isp_dev->stfcamss;
++
++	reset_control_assert(stfcamss->sys_rst[STF_RST_WRAPPER_C].rstc);
++	reset_control_assert(stfcamss->sys_rst[STF_RST_WRAPPER_P].rstc);
++	clk_disable_unprepare(stfcamss->sys_clk[STF_CLK_WRAPPER_CLK_C].clk);
++
++	return 0;
++}
++
++int stf_isp_reset(struct stf_isp_dev *isp_dev)
++{
++	stf_isp_reg_set_bit(isp_dev->stfcamss, ISP_REG_ISP_CTRL_0,
++			    ISPC_RST_MASK, ISPC_RST);
++	stf_isp_reg_set_bit(isp_dev->stfcamss, ISP_REG_ISP_CTRL_0,
++			    ISPC_RST_MASK, 0);
++
++	return 0;
++}
++
++void stf_isp_init_cfg(struct stf_isp_dev *isp_dev)
++{
++	stf_isp_reg_write(isp_dev->stfcamss, ISP_REG_DC_CFG_1, DC_AXI_ID(0x0));
++	stf_isp_reg_write(isp_dev->stfcamss, ISP_REG_DEC_CFG,
++			  DEC_V_KEEP(0x0) |
++			  DEC_V_PERIOD(0x0) |
++			  DEC_H_KEEP(0x0) |
++			  DEC_H_PERIOD(0x0));
++
++	stf_isp_config_obc(isp_dev->stfcamss);
++	stf_isp_config_oecf(isp_dev->stfcamss);
++	stf_isp_config_awb(isp_dev->stfcamss);
++	stf_isp_config_grgb(isp_dev->stfcamss);
++	stf_isp_config_cfa(isp_dev->stfcamss);
++	stf_isp_config_ccm(isp_dev->stfcamss);
++	stf_isp_config_gamma(isp_dev->stfcamss);
++	stf_isp_config_r2y(isp_dev->stfcamss);
++	stf_isp_config_y_curve(isp_dev->stfcamss);
++	stf_isp_config_sharpen(isp_dev->stfcamss);
++	stf_isp_config_dnyuv(isp_dev->stfcamss);
++	stf_isp_config_sat(isp_dev->stfcamss);
++
++	stf_isp_reg_write(isp_dev->stfcamss, ISP_REG_CSI_MODULE_CFG,
++			  CSI_DUMP_EN | CSI_SC_EN | CSI_AWB_EN |
++			  CSI_LCCF_EN | CSI_OECF_EN | CSI_OBC_EN | CSI_DEC_EN);
++	stf_isp_reg_write(isp_dev->stfcamss, ISP_REG_ISP_CTRL_1,
++			  CTRL_SAT(1) | CTRL_DBC | CTRL_CTC | CTRL_YHIST |
++			  CTRL_YCURVE | CTRL_BIYUV | CTRL_SCE | CTRL_EE |
++			  CTRL_CCE | CTRL_RGE | CTRL_CME | CTRL_AE | CTRL_CE);
++}
++
++static void stf_isp_config_crop(struct stfcamss *stfcamss,
++				struct stf_isp_crop *crop)
++{
++	struct v4l2_rect *rect = &crop[STF_ISP_PAD_SRC].rect;
++	u32 bpp = crop[STF_ISP_PAD_SRC].bpp;
++	u32 val;
++
++	val = VSTART_CAP(rect->top) | HSTART_CAP(rect->left);
++	stf_isp_reg_write(stfcamss, ISP_REG_PIC_CAPTURE_START_CFG, val);
++
++	val = VEND_CAP(rect->height + rect->top - 1) |
++	      HEND_CAP(rect->width + rect->left - 1);
++	stf_isp_reg_write(stfcamss, ISP_REG_PIC_CAPTURE_END_CFG, val);
++
++	val = H_ACT_CAP(rect->height) | W_ACT_CAP(rect->width);
++	stf_isp_reg_write(stfcamss, ISP_REG_PIPELINE_XY_SIZE, val);
++
++	val = ALIGN(rect->width * bpp / 8, STFCAMSS_FRAME_WIDTH_ALIGN_8);
++	stf_isp_reg_write(stfcamss, ISP_REG_STRIDE, val);
++}
++
++static void stf_isp_config_raw_fmt(struct stfcamss *stfcamss, u32 mcode)
++{
++	u32 val, val1;
++
++	switch (mcode) {
++	case MEDIA_BUS_FMT_SRGGB10_1X10:
++	case MEDIA_BUS_FMT_SRGGB8_1X8:
++		/* 3 2 3 2 1 0 1 0 B Gb B Gb Gr R Gr R */
++		val = SMY13(3) | SMY12(2) | SMY11(3) | SMY10(2) |
++		      SMY3(1) | SMY2(0) | SMY1(1) | SMY0(0);
++		val1 = CTRL_SAT(0x0);
++		break;
++	case MEDIA_BUS_FMT_SGRBG10_1X10:
++	case MEDIA_BUS_FMT_SGRBG8_1X8:
++		/* 2 3 2 3 0 1 0 1, Gb B Gb B R Gr R Gr */
++		val = SMY13(2) | SMY12(3) | SMY11(2) | SMY10(3) |
++		      SMY3(0) | SMY2(1) | SMY1(0) | SMY0(1);
++		val1 = CTRL_SAT(0x2);
++		break;
++	case MEDIA_BUS_FMT_SGBRG10_1X10:
++	case MEDIA_BUS_FMT_SGBRG8_1X8:
++		/* 1 0 1 0 3 2 3 2, Gr R Gr R B Gb B Gb */
++		val = SMY13(1) | SMY12(0) | SMY11(1) | SMY10(0) |
++		      SMY3(3) | SMY2(2) | SMY1(3) | SMY0(2);
++		val1 = CTRL_SAT(0x3);
++		break;
++	case MEDIA_BUS_FMT_SBGGR10_1X10:
++	case MEDIA_BUS_FMT_SBGGR8_1X8:
++		/* 0 1 0 1 2 3 2 3 R Gr R Gr Gb B Gb B */
++		val = SMY13(0) | SMY12(1) | SMY11(0) | SMY10(1) |
++		      SMY3(2) | SMY2(3) | SMY1(2) | SMY0(3);
++		val1 = CTRL_SAT(0x1);
++		break;
++	default:
++		val = SMY13(0) | SMY12(1) | SMY11(0) | SMY10(1) |
++		      SMY3(2) | SMY2(3) | SMY1(2) | SMY0(3);
++		val1 = CTRL_SAT(0x1);
++		break;
++	}
++	stf_isp_reg_write(stfcamss, ISP_REG_RAW_FORMAT_CFG, val);
++	stf_isp_reg_set_bit(stfcamss, ISP_REG_ISP_CTRL_1, CTRL_SAT_MASK, val1);
++}
++
++void stf_isp_settings(struct stf_isp_dev *isp_dev,
++		      struct stf_isp_crop *crop, u32 mcode)
++{
++	struct stfcamss *stfcamss = isp_dev->stfcamss;
++
++	stf_isp_config_crop(stfcamss, crop);
++	stf_isp_config_raw_fmt(stfcamss, mcode);
++
++	stf_isp_reg_set_bit(stfcamss, ISP_REG_DUMP_CFG_1,
++			    DUMP_BURST_LEN_MASK | DUMP_SD_MASK,
++			    DUMP_BURST_LEN(3));
++
++	stf_isp_reg_write(stfcamss, ISP_REG_ITIIWSR,
++			  ITI_HSIZE(IMAGE_MAX_HEIGH) |
++			  ITI_WSIZE(IMAGE_MAX_WIDTH));
++	stf_isp_reg_write(stfcamss, ISP_REG_ITIDWLSR, ITI_WSTRIDE(0x960));
++	stf_isp_reg_write(stfcamss, ISP_REG_ITIDRLSR, ITI_STRIDE_L(0x960));
++	stf_isp_reg_write(stfcamss, ISP_REG_SENSOR, 0x1);
++}
++
++void stf_isp_stream_set(struct stf_isp_dev *isp_dev)
++{
++	struct stfcamss *stfcamss = isp_dev->stfcamss;
++
++	stf_isp_reg_write_delay(stfcamss, ISP_REG_ISP_CTRL_0,
++				ISPC_ENUO | ISPC_ENLS | ISPC_RST, 10);
++	stf_isp_reg_write_delay(stfcamss, ISP_REG_ISP_CTRL_0,
++				ISPC_ENUO | ISPC_ENLS, 10);
++	stf_isp_reg_write(stfcamss, ISP_REG_IESHD, SHAD_UP_M);
++	stf_isp_reg_write_delay(stfcamss, ISP_REG_ISP_CTRL_0,
++				ISPC_ENUO | ISPC_ENLS | ISPC_EN, 10);
++	stf_isp_reg_write_delay(stfcamss, ISP_REG_CSIINTS,
++				CSI_INTS(1) | CSI_SHA_M(4), 10);
++	stf_isp_reg_write_delay(stfcamss, ISP_REG_CSIINTS,
++				CSI_INTS(2) | CSI_SHA_M(4), 10);
++	stf_isp_reg_write_delay(stfcamss, ISP_REG_CSI_INPUT_EN_AND_STATUS,
++				CSI_EN_S, 10);
++}

+ 1694 - 0
target/linux/starfive/patches-6.1/0086-media-starfive-Add-VIN-driver.patch

@@ -0,0 +1,1694 @@
+From 030f0312433a85899fab4dccada5b2cbceb3bad5 Mon Sep 17 00:00:00 2001
+From: Jack Zhu <[email protected]>
+Date: Fri, 12 May 2023 18:28:44 +0800
+Subject: [PATCH 086/122] media: starfive: Add VIN driver
+
+Add Video In Controller driver for StarFive Camera Subsystem.
+
+Signed-off-by: Jack Zhu <[email protected]>
+---
+ drivers/media/platform/starfive/Makefile      |    4 +-
+ drivers/media/platform/starfive/stf_camss.c   |   39 +-
+ drivers/media/platform/starfive/stf_camss.h   |    2 +
+ drivers/media/platform/starfive/stf_vin.c     | 1134 +++++++++++++++++
+ drivers/media/platform/starfive/stf_vin.h     |  180 +++
+ .../media/platform/starfive/stf_vin_hw_ops.c  |  241 ++++
+ 6 files changed, 1598 insertions(+), 2 deletions(-)
+ create mode 100644 drivers/media/platform/starfive/stf_vin.c
+ create mode 100644 drivers/media/platform/starfive/stf_vin.h
+ create mode 100644 drivers/media/platform/starfive/stf_vin_hw_ops.c
+
+--- a/drivers/media/platform/starfive/Makefile
++++ b/drivers/media/platform/starfive/Makefile
+@@ -7,6 +7,8 @@ starfive-camss-objs += \
+ 		stf_camss.o \
+ 		stf_isp.o \
+ 		stf_isp_hw_ops.o \
+-		stf_video.o
++		stf_video.o \
++		stf_vin.o \
++		stf_vin_hw_ops.o
+ 
+ obj-$(CONFIG_VIDEO_STARFIVE_CAMSS) += starfive-camss.o \
+--- a/drivers/media/platform/starfive/stf_camss.c
++++ b/drivers/media/platform/starfive/stf_camss.c
+@@ -142,27 +142,61 @@ static int stfcamss_init_subdevices(stru
+ 		return ret;
+ 	}
+ 
++	ret = stf_vin_subdev_init(stfcamss);
++	if (ret < 0) {
++		dev_err(stfcamss->dev, "Failed to init vin subdev: %d\n", ret);
++		return ret;
++	}
+ 	return ret;
+ }
+ 
+ static int stfcamss_register_subdevices(struct stfcamss *stfcamss)
+ {
+ 	int ret;
++	struct stf_vin_dev *vin_dev = &stfcamss->vin_dev;
+ 	struct stf_isp_dev *isp_dev = &stfcamss->isp_dev;
+ 
+ 	ret = stf_isp_register(isp_dev, &stfcamss->v4l2_dev);
+ 	if (ret < 0) {
+ 		dev_err(stfcamss->dev,
+ 			"Failed to register stf isp%d entity: %d\n", 0, ret);
+-		return ret;
++		goto err_reg_isp;
++	}
++
++	ret = stf_vin_register(vin_dev, &stfcamss->v4l2_dev);
++	if (ret < 0) {
++		dev_err(stfcamss->dev,
++			"Failed to register vin entity: %d\n", ret);
++		goto err_reg_vin;
+ 	}
+ 
++	ret = media_create_pad_link(&isp_dev->subdev.entity,
++				    STF_ISP_PAD_SRC,
++				    &vin_dev->line[VIN_LINE_ISP].subdev.entity,
++				    STF_VIN_PAD_SINK,
++				    0);
++	if (ret < 0) {
++		dev_err(stfcamss->dev,
++			"Failed to link %s->%s entities: %d\n",
++			isp_dev->subdev.entity.name,
++			vin_dev->line[VIN_LINE_ISP].subdev.entity.name, ret);
++		goto err_link;
++	}
++
++	return ret;
++
++err_link:
++	stf_vin_unregister(&stfcamss->vin_dev);
++err_reg_vin:
++	stf_isp_unregister(&stfcamss->isp_dev);
++err_reg_isp:
+ 	return ret;
+ }
+ 
+ static void stfcamss_unregister_subdevices(struct stfcamss *stfcamss)
+ {
+ 	stf_isp_unregister(&stfcamss->isp_dev);
++	stf_vin_unregister(&stfcamss->vin_dev);
+ }
+ 
+ static int stfcamss_subdev_notifier_bound(struct v4l2_async_notifier *async,
+@@ -175,11 +209,14 @@ static int stfcamss_subdev_notifier_boun
+ 		container_of(asd, struct stfcamss_async_subdev, asd);
+ 	enum port_num port = csd->port;
+ 	struct stf_isp_dev *isp_dev = &stfcamss->isp_dev;
++	struct stf_vin_dev *vin_dev = &stfcamss->vin_dev;
+ 	struct host_data *host_data = &stfcamss->host_data;
+ 	struct media_entity *source;
+ 	int i, j;
+ 
+ 	if (port == PORT_NUMBER_CSI2RX) {
++		host_data->host_entity[0] =
++			&vin_dev->line[VIN_LINE_WR].subdev.entity;
+ 		host_data->host_entity[1] = &isp_dev->subdev.entity;
+ 	} else if (port == PORT_NUMBER_DVP_SENSOR) {
+ 		dev_err(stfcamss->dev, "Not support DVP sensor\n");
+--- a/drivers/media/platform/starfive/stf_camss.h
++++ b/drivers/media/platform/starfive/stf_camss.h
+@@ -17,6 +17,7 @@
+ 
+ #include "stf_common.h"
+ #include "stf_isp.h"
++#include "stf_vin.h"
+ 
+ #define DRV_NAME     "starfive-camss"
+ #define STF_DVP_NAME "stf_dvp"
+@@ -72,6 +73,7 @@ struct stfcamss {
+ 	struct media_device media_dev;
+ 	struct media_pipeline pipe;
+ 	struct device *dev;
++	struct stf_vin_dev vin_dev;
+ 	struct stf_isp_dev isp_dev;
+ 	struct v4l2_async_notifier notifier;
+ 	struct host_data host_data;
+--- /dev/null
++++ b/drivers/media/platform/starfive/stf_vin.c
+@@ -0,0 +1,1134 @@
++// SPDX-License-Identifier: GPL-2.0
++/*
++ * stf_vin.c
++ *
++ * StarFive Camera Subsystem - VIN Module
++ *
++ * Copyright (C) 2021-2023 StarFive Technology Co., Ltd.
++ */
++#include <linux/pm_runtime.h>
++
++#include "stf_camss.h"
++
++#define vin_line_array(ptr_line) \
++	((const struct vin_line (*)[]) &(ptr_line)[-((ptr_line)->id)])
++
++#define line_to_vin_dev(ptr_line) \
++	container_of(vin_line_array(ptr_line), struct stf_vin_dev, line)
++
++#define VIN_FRAME_DROP_MAX_VAL 90
++#define VIN_FRAME_DROP_MIN_VAL 4
++#define VIN_FRAME_PER_SEC_MAX_VAL 90
++
++/* ISP ctrl need 1 sec to let frames become stable. */
++#define VIN_FRAME_DROP_SEC_FOR_ISP_CTRL 1
++
++static const struct vin_format vin_formats_wr[] = {
++	{ MEDIA_BUS_FMT_SRGGB10_1X10, 10},
++	{ MEDIA_BUS_FMT_SGRBG10_1X10, 10},
++	{ MEDIA_BUS_FMT_SGBRG10_1X10, 10},
++	{ MEDIA_BUS_FMT_SBGGR10_1X10, 10},
++};
++
++static const struct vin_format vin_formats_uo[] = {
++	{ MEDIA_BUS_FMT_Y12_1X12, 8},
++};
++
++static const struct vin_format_table vin_formats_table[] = {
++	/* VIN_LINE_WR */
++	{ vin_formats_wr, ARRAY_SIZE(vin_formats_wr) },
++	/* VIN_LINE_ISP */
++	{ vin_formats_uo, ARRAY_SIZE(vin_formats_uo) },
++};
++
++static void vin_buffer_done(struct vin_line *line);
++static void vin_change_buffer(struct vin_line *line);
++static struct stfcamss_buffer *vin_buf_get_pending(struct vin_output *output);
++static void vin_output_init_addrs(struct vin_line *line);
++static void vin_init_outputs(struct vin_line *line);
++static struct v4l2_mbus_framefmt *
++__vin_get_format(struct vin_line *line,
++		 struct v4l2_subdev_state *state,
++		 unsigned int pad,
++		 enum v4l2_subdev_format_whence which);
++
++static char *vin_get_line_subdevname(int line_id)
++{
++	char *name = NULL;
++
++	switch (line_id) {
++	case VIN_LINE_WR:
++		name = "wr";
++		break;
++	case VIN_LINE_ISP:
++		name = "isp0";
++		break;
++	default:
++		name = "unknown";
++		break;
++	}
++	return name;
++}
++
++static enum isp_line_id vin_map_isp_line(enum vin_line_id line)
++{
++	enum isp_line_id line_id;
++
++	if (line > VIN_LINE_WR && line < VIN_LINE_MAX)
++		line_id = STF_ISP_LINE_SRC;
++	else
++		line_id = STF_ISP_LINE_INVALID;
++
++	return line_id;
++}
++
++enum isp_pad_id stf_vin_map_isp_pad(enum vin_line_id line, enum isp_pad_id def)
++{
++	enum isp_pad_id pad_id;
++
++	if (line == VIN_LINE_WR)
++		pad_id = STF_ISP_PAD_SINK;
++	else if ((line > VIN_LINE_WR) && (line < VIN_LINE_MAX))
++		pad_id = (enum isp_pad_id)vin_map_isp_line(line);
++	else
++		pad_id = def;
++
++	return pad_id;
++}
++
++int stf_vin_subdev_init(struct stfcamss *stfcamss)
++{
++	struct device *dev = stfcamss->dev;
++	struct stf_vin_dev *vin_dev = &stfcamss->vin_dev;
++	int i, ret = 0;
++
++	vin_dev->stfcamss = stfcamss;
++
++	vin_dev->isr_ops = devm_kzalloc(dev, sizeof(*vin_dev->isr_ops),
++					GFP_KERNEL);
++	if (!vin_dev->isr_ops)
++		return -ENOMEM;
++	vin_dev->isr_ops->isr_buffer_done = vin_buffer_done;
++	vin_dev->isr_ops->isr_change_buffer = vin_change_buffer;
++
++	atomic_set(&vin_dev->ref_count, 0);
++
++	ret = devm_request_irq(dev,
++			       stfcamss->irq[STF_IRQ_VINWR],
++			       stf_vin_wr_irq_handler,
++			       0, "vin_axiwr_irq", vin_dev);
++	if (ret) {
++		dev_err(dev, "Failed to request irq\n");
++		goto out;
++	}
++
++	ret = devm_request_irq(dev,
++			       stfcamss->irq[STF_IRQ_ISP],
++			       stf_vin_isp_irq_handler,
++			       0, "vin_isp_irq", vin_dev);
++	if (ret) {
++		dev_err(dev, "Failed to request isp irq\n");
++		goto out;
++	}
++
++	ret = devm_request_irq(dev,
++			       stfcamss->irq[STF_IRQ_ISPCSIL],
++			       stf_vin_isp_irq_csiline_handler,
++			       0, "vin_isp_irq_csiline", vin_dev);
++	if (ret) {
++		dev_err(dev, "failed to request isp irq csiline\n");
++		goto out;
++	}
++
++	mutex_init(&vin_dev->power_lock);
++	vin_dev->power_count = 0;
++
++	for (i = 0; i < STF_DUMMY_MODULE_NUMS; i++) {
++		struct dummy_buffer *dummy_buffer = &vin_dev->dummy_buffer[i];
++
++		mutex_init(&dummy_buffer->stream_lock);
++		dummy_buffer->nums =
++			i == 0 ? VIN_DUMMY_BUFFER_NUMS : ISP_DUMMY_BUFFER_NUMS;
++		dummy_buffer->stream_count = 0;
++		dummy_buffer->buffer =
++			devm_kzalloc(dev,
++				     dummy_buffer->nums * sizeof(struct vin_dummy_buffer),
++				     GFP_KERNEL);
++		atomic_set(&dummy_buffer->frame_skip, 0);
++	}
++
++	for (i = VIN_LINE_WR; i < STF_ISP_LINE_MAX + 1; i++) {
++		struct vin_line *l = &vin_dev->line[i];
++
++		l->video_out.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
++		l->video_out.stfcamss = stfcamss;
++		l->id = i;
++		l->sdev_type = STF_SUBDEV_TYPE_VIN;
++		l->formats = vin_formats_table[i].fmts;
++		l->nformats = vin_formats_table[i].nfmts;
++		spin_lock_init(&l->output_lock);
++
++		mutex_init(&l->stream_lock);
++		l->stream_count = 0;
++		mutex_init(&l->power_lock);
++		l->power_count = 0;
++	}
++
++	return 0;
++out:
++	return ret;
++}
++
++static enum link vin_get_link(struct media_entity *entity)
++{
++	struct v4l2_subdev *subdev;
++	struct media_pad *pad;
++	bool isp = false;
++
++	while (1) {
++		pad = &entity->pads[0];
++		if (!(pad->flags & MEDIA_PAD_FL_SINK))
++			return LINK_ERROR;
++
++		pad = media_pad_remote_pad_first(pad);
++		if (!pad || !is_media_entity_v4l2_subdev(pad->entity))
++			return LINK_ERROR;
++
++		entity = pad->entity;
++		subdev = media_entity_to_v4l2_subdev(entity);
++
++		if (!strncmp(subdev->name, STF_CSI_NAME,
++			     strlen(STF_CSI_NAME))) {
++			if (isp)
++				return LINK_CSI_TO_ISP;
++			else
++				return LINK_CSI_TO_WR;
++		} else if (!strncmp(subdev->name, STF_DVP_NAME,
++				    strlen(STF_DVP_NAME))) {
++			if (isp)
++				return LINK_DVP_TO_ISP;
++			else
++				return LINK_DVP_TO_WR;
++		} else if (!strncmp(subdev->name, STF_ISP_NAME,
++				    strlen(STF_ISP_NAME))) {
++			isp = true;
++		} else {
++			return LINK_ERROR;
++		}
++	}
++}
++
++static int vin_set_power(struct v4l2_subdev *sd, int on)
++{
++	struct vin_line *line = v4l2_get_subdevdata(sd);
++	struct stf_vin_dev *vin_dev = line_to_vin_dev(line);
++	struct stfcamss *stfcamss = vin_dev->stfcamss;
++	enum link link;
++
++	mutex_lock(&line->power_lock);
++	if (on) {
++		if (line->power_count == 0)
++			vin_init_outputs(line);
++		line->power_count++;
++	} else {
++		if (line->power_count == 0) {
++			dev_err(stfcamss->dev,
++				"line power off on power_count = 0\n");
++			goto exit_line;
++		}
++		line->power_count--;
++	}
++exit_line:
++	mutex_unlock(&line->power_lock);
++
++	mutex_lock(&vin_dev->power_lock);
++	link = vin_get_link(&sd->entity);
++	if (link == LINK_ERROR)
++		goto exit;
++
++	if (on) {
++		if (vin_dev->power_count == 0) {
++			pm_runtime_get_sync(stfcamss->dev);
++			stf_vin_clk_enable(vin_dev, link);
++		}
++		vin_dev->power_count++;
++	} else {
++		if (vin_dev->power_count == 0) {
++			dev_err(stfcamss->dev,
++				"vin_dev power off on power_count=0\n");
++			goto exit;
++		}
++		if (vin_dev->power_count == 1) {
++			stf_vin_clk_disable(vin_dev, link);
++			pm_runtime_put_sync(stfcamss->dev);
++		}
++		vin_dev->power_count--;
++	}
++exit:
++
++	mutex_unlock(&vin_dev->power_lock);
++
++	return 0;
++}
++
++static int vin_enable_output(struct vin_line *line)
++{
++	struct vin_output *output = &line->output;
++	unsigned long flags;
++
++	spin_lock_irqsave(&line->output_lock, flags);
++
++	output->state = VIN_OUTPUT_IDLE;
++
++	output->buf[0] = vin_buf_get_pending(output);
++
++	if (!output->buf[0] && output->buf[1]) {
++		output->buf[0] = output->buf[1];
++		output->buf[1] = NULL;
++	}
++
++	if (output->buf[0])
++		output->state = VIN_OUTPUT_SINGLE;
++
++	output->sequence = 0;
++
++	vin_output_init_addrs(line);
++	spin_unlock_irqrestore(&line->output_lock, flags);
++	return 0;
++}
++
++static int vin_disable_output(struct vin_line *line)
++{
++	struct vin_output *output = &line->output;
++	unsigned long flags;
++
++	spin_lock_irqsave(&line->output_lock, flags);
++
++	output->state = VIN_OUTPUT_OFF;
++
++	spin_unlock_irqrestore(&line->output_lock, flags);
++	return 0;
++}
++
++static u32 vin_line_to_dummy_module(struct vin_line *line)
++{
++	u32 dummy_module = 0;
++
++	switch (line->id) {
++	case VIN_LINE_WR:
++		dummy_module = STF_DUMMY_VIN;
++		break;
++	case VIN_LINE_ISP:
++		dummy_module = STF_DUMMY_ISP;
++		break;
++	default:
++		dummy_module = STF_DUMMY_VIN;
++		break;
++	}
++
++	return dummy_module;
++}
++
++static int vin_alloc_dummy_buffer(struct stf_vin_dev *vin_dev,
++				  struct v4l2_mbus_framefmt *fmt,
++				  int dummy_module)
++{
++	struct device *dev = vin_dev->stfcamss->dev;
++	struct dummy_buffer *dummy_buffer =
++				&vin_dev->dummy_buffer[dummy_module];
++	struct vin_dummy_buffer *buffer = NULL;
++	int ret = 0, i;
++	u32 aligns;
++
++	for (i = 0; i < dummy_buffer->nums; i++) {
++		buffer = &vin_dev->dummy_buffer[dummy_module].buffer[i];
++		buffer->width = fmt->width;
++		buffer->height = fmt->height;
++		buffer->mcode = fmt->code;
++		if (i == STF_VIN_PAD_SINK) {
++			aligns = ALIGN(fmt->width * 4,
++				       STFCAMSS_FRAME_WIDTH_ALIGN_8);
++			buffer->buffer_size = PAGE_ALIGN(aligns * fmt->height);
++		} else if (i == STF_ISP_PAD_SRC) {
++			aligns = ALIGN(fmt->width,
++				       STFCAMSS_FRAME_WIDTH_ALIGN_8);
++			buffer->buffer_size =
++				PAGE_ALIGN(aligns * fmt->height * 3 / 2);
++		} else {
++			continue;
++		}
++
++		buffer->vaddr = dma_alloc_coherent(dev,
++						   buffer->buffer_size,
++						   &buffer->paddr[0],
++						   GFP_DMA | GFP_KERNEL);
++
++		if (buffer->vaddr) {
++			if (i == STF_ISP_PAD_SRC)
++				buffer->paddr[1] =
++					(dma_addr_t)(buffer->paddr[0] + aligns * fmt->height);
++			else
++				dev_dbg(dev, "signal plane\n");
++		}
++	}
++
++	return ret;
++}
++
++static void vin_free_dummy_buffer(struct stf_vin_dev *vin_dev, int dummy_module)
++{
++	struct device *dev = vin_dev->stfcamss->dev;
++	struct dummy_buffer *dummy_buffer =
++		&vin_dev->dummy_buffer[dummy_module];
++	struct vin_dummy_buffer *buffer = NULL;
++	int i;
++
++	for (i = 0; i < dummy_buffer->nums; i++) {
++		buffer = &dummy_buffer->buffer[i];
++		if (buffer->vaddr)
++			dma_free_coherent(dev, buffer->buffer_size,
++					  buffer->vaddr, buffer->paddr[0]);
++		memset(buffer, 0, sizeof(struct vin_dummy_buffer));
++	}
++}
++
++static void vin_set_dummy_buffer(struct vin_line *line, u32 pad)
++{
++	struct stf_vin_dev *vin_dev = line_to_vin_dev(line);
++	int dummy_module = vin_line_to_dummy_module(line);
++	struct dummy_buffer *dummy_buffer =
++		&vin_dev->dummy_buffer[dummy_module];
++	struct vin_dummy_buffer *buffer = NULL;
++
++	switch (pad) {
++	case STF_VIN_PAD_SINK:
++		if (line->id == VIN_LINE_WR) {
++			buffer = &dummy_buffer->buffer[STF_VIN_PAD_SINK];
++			stf_vin_wr_set_ping_addr(vin_dev, buffer->paddr[0]);
++			stf_vin_wr_set_pong_addr(vin_dev, buffer->paddr[0]);
++		} else {
++			buffer = &dummy_buffer->buffer[STF_ISP_PAD_SRC];
++			stf_vin_isp_set_yuv_addr(vin_dev,
++						 buffer->paddr[0],
++						 buffer->paddr[1]);
++		}
++		break;
++	case STF_ISP_PAD_SRC:
++		buffer = &dummy_buffer->buffer[STF_ISP_PAD_SRC];
++		stf_vin_isp_set_yuv_addr(vin_dev,
++					 buffer->paddr[0],
++					 buffer->paddr[1]);
++		break;
++	default:
++		break;
++	}
++}
++
++static int vin_set_stream(struct v4l2_subdev *sd, int enable)
++{
++	struct vin_line *line = v4l2_get_subdevdata(sd);
++	struct stf_vin_dev *vin_dev = line_to_vin_dev(line);
++	int dummy_module = vin_line_to_dummy_module(line);
++	struct dummy_buffer *dummy_buffer =
++		&vin_dev->dummy_buffer[dummy_module];
++	struct v4l2_mbus_framefmt *fmt;
++	enum link link;
++
++	fmt = __vin_get_format(line, NULL,
++			       STF_VIN_PAD_SINK, V4L2_SUBDEV_FORMAT_ACTIVE);
++	mutex_lock(&dummy_buffer->stream_lock);
++	if (enable) {
++		if (dummy_buffer->stream_count == 0) {
++			vin_alloc_dummy_buffer(vin_dev, fmt, dummy_module);
++			vin_set_dummy_buffer(line, STF_VIN_PAD_SINK);
++			atomic_set(&dummy_buffer->frame_skip,
++				   VIN_FRAME_DROP_MIN_VAL + 30);
++		}
++		dummy_buffer->stream_count++;
++	} else {
++		if (dummy_buffer->stream_count == 1) {
++			vin_free_dummy_buffer(vin_dev, dummy_module);
++			/* set buffer addr to zero */
++			vin_set_dummy_buffer(line, STF_VIN_PAD_SINK);
++		} else {
++			vin_set_dummy_buffer(line,
++				stf_vin_map_isp_pad(line->id, STF_ISP_PAD_SINK));
++		}
++
++		dummy_buffer->stream_count--;
++	}
++	mutex_unlock(&dummy_buffer->stream_lock);
++
++	mutex_lock(&line->stream_lock);
++	link = vin_get_link(&sd->entity);
++	if (link == LINK_ERROR)
++		goto exit;
++
++	if (enable) {
++		if (line->stream_count == 0) {
++			stf_vin_stream_set(vin_dev, link);
++			if (line->id == VIN_LINE_WR) {
++				stf_vin_wr_irq_enable(vin_dev, 1);
++				stf_vin_wr_stream_set(vin_dev);
++			}
++		}
++		line->stream_count++;
++	} else {
++		if (line->stream_count == 1 && line->id == VIN_LINE_WR)
++			stf_vin_wr_irq_enable(vin_dev, 0);
++		line->stream_count--;
++	}
++exit:
++	mutex_unlock(&line->stream_lock);
++
++	if (enable)
++		vin_enable_output(line);
++	else
++		vin_disable_output(line);
++
++	return 0;
++}
++
++static struct v4l2_mbus_framefmt *
++__vin_get_format(struct vin_line *line,
++		 struct v4l2_subdev_state *state,
++		 unsigned int pad,
++		 enum v4l2_subdev_format_whence which)
++{
++	if (which == V4L2_SUBDEV_FORMAT_TRY)
++		return v4l2_subdev_get_try_format(&line->subdev, state, pad);
++	return &line->fmt[pad];
++}
++
++static void vin_try_format(struct vin_line *line,
++			   struct v4l2_subdev_state *state,
++			   unsigned int pad,
++			   struct v4l2_mbus_framefmt *fmt,
++			   enum v4l2_subdev_format_whence which)
++{
++	unsigned int i;
++
++	switch (pad) {
++	case STF_VIN_PAD_SINK:
++		/* Set format on sink pad */
++		for (i = 0; i < line->nformats; i++)
++			if (fmt->code == line->formats[i].code)
++				break;
++
++		/* If not found, use UYVY as default */
++		if (i >= line->nformats)
++			fmt->code = line->formats[0].code;
++
++		fmt->width = clamp_t(u32, fmt->width,
++				     STFCAMSS_FRAME_MIN_WIDTH,
++				     STFCAMSS_FRAME_MAX_WIDTH);
++		fmt->height = clamp_t(u32, fmt->height,
++				      STFCAMSS_FRAME_MIN_HEIGHT,
++				      STFCAMSS_FRAME_MAX_HEIGHT);
++
++		fmt->field = V4L2_FIELD_NONE;
++		fmt->colorspace = V4L2_COLORSPACE_SRGB;
++		fmt->flags = 0;
++		break;
++
++	case STF_VIN_PAD_SRC:
++		/* Set and return a format same as sink pad */
++		*fmt = *__vin_get_format(line, state, STF_VIN_PAD_SINK, which);
++		break;
++	}
++
++	fmt->colorspace = V4L2_COLORSPACE_SRGB;
++}
++
++static int vin_enum_mbus_code(struct v4l2_subdev *sd,
++			      struct v4l2_subdev_state *state,
++			      struct v4l2_subdev_mbus_code_enum *code)
++{
++	struct vin_line *line = v4l2_get_subdevdata(sd);
++
++	if (code->index >= line->nformats)
++		return -EINVAL;
++	if (code->pad == STF_VIN_PAD_SINK) {
++		code->code = line->formats[code->index].code;
++	} else {
++		struct v4l2_mbus_framefmt *sink_fmt;
++
++		sink_fmt = __vin_get_format(line, state, STF_VIN_PAD_SINK,
++					    code->which);
++
++		code->code = sink_fmt->code;
++		if (!code->code)
++			return -EINVAL;
++	}
++	code->flags = 0;
++
++	return 0;
++}
++
++static int vin_enum_frame_size(struct v4l2_subdev *sd,
++			       struct v4l2_subdev_state *state,
++			       struct v4l2_subdev_frame_size_enum *fse)
++{
++	struct vin_line *line = v4l2_get_subdevdata(sd);
++	struct v4l2_mbus_framefmt format;
++
++	if (fse->index != 0)
++		return -EINVAL;
++
++	format.code = fse->code;
++	format.width = 1;
++	format.height = 1;
++	vin_try_format(line, state, fse->pad, &format, fse->which);
++	fse->min_width = format.width;
++	fse->min_height = format.height;
++
++	if (format.code != fse->code)
++		return -EINVAL;
++
++	format.code = fse->code;
++	format.width = -1;
++	format.height = -1;
++	vin_try_format(line, state, fse->pad, &format, fse->which);
++	fse->max_width = format.width;
++	fse->max_height = format.height;
++
++	return 0;
++}
++
++static int vin_get_format(struct v4l2_subdev *sd,
++			  struct v4l2_subdev_state *state,
++			  struct v4l2_subdev_format *fmt)
++{
++	struct vin_line *line = v4l2_get_subdevdata(sd);
++	struct v4l2_mbus_framefmt *format;
++
++	format = __vin_get_format(line, state, fmt->pad, fmt->which);
++	if (!format)
++		return -EINVAL;
++
++	fmt->format = *format;
++
++	return 0;
++}
++
++static int vin_set_format(struct v4l2_subdev *sd,
++			  struct v4l2_subdev_state *state,
++			  struct v4l2_subdev_format *fmt)
++{
++	struct vin_line *line = v4l2_get_subdevdata(sd);
++	struct v4l2_mbus_framefmt *format;
++
++	format = __vin_get_format(line, state, fmt->pad, fmt->which);
++	if (!format)
++		return -EINVAL;
++
++	mutex_lock(&line->stream_lock);
++	if (line->stream_count) {
++		fmt->format = *format;
++		mutex_unlock(&line->stream_lock);
++		goto out;
++	} else {
++		vin_try_format(line, state, fmt->pad, &fmt->format, fmt->which);
++		*format = fmt->format;
++	}
++	mutex_unlock(&line->stream_lock);
++
++	if (fmt->pad == STF_VIN_PAD_SINK) {
++		/* Propagate the format from sink to source */
++		format = __vin_get_format(line, state, STF_VIN_PAD_SRC,
++					  fmt->which);
++
++		*format = fmt->format;
++		vin_try_format(line, state, STF_VIN_PAD_SRC, format,
++			       fmt->which);
++	}
++
++out:
++	return 0;
++}
++
++static int vin_init_formats(struct v4l2_subdev *sd,
++			    struct v4l2_subdev_fh *fh)
++{
++	struct v4l2_subdev_format format = {
++		.pad = STF_VIN_PAD_SINK,
++		.which = fh ?
++			 V4L2_SUBDEV_FORMAT_TRY : V4L2_SUBDEV_FORMAT_ACTIVE,
++		.format = {
++			.code = MEDIA_BUS_FMT_RGB565_2X8_LE,
++			.width = 1920,
++			.height = 1080
++		}
++	};
++
++	return vin_set_format(sd, fh ? fh->state : NULL, &format);
++}
++
++static void vin_output_init_addrs(struct vin_line *line)
++{
++	struct vin_output *output = &line->output;
++	struct stf_vin_dev *vin_dev = line_to_vin_dev(line);
++	dma_addr_t ping_addr;
++	dma_addr_t y_addr, uv_addr;
++
++	output->active_buf = 0;
++
++	if (output->buf[0]) {
++		ping_addr = output->buf[0]->addr[0];
++		y_addr = output->buf[0]->addr[0];
++		uv_addr = output->buf[0]->addr[1];
++	} else {
++		return;
++	}
++
++	switch (vin_map_isp_line(line->id)) {
++	case STF_ISP_LINE_SRC:
++		stf_vin_isp_set_yuv_addr(vin_dev, y_addr, uv_addr);
++		break;
++	default:
++		if (line->id == VIN_LINE_WR) {
++			stf_vin_wr_set_ping_addr(vin_dev, ping_addr);
++			stf_vin_wr_set_pong_addr(vin_dev, ping_addr);
++		}
++		break;
++	}
++}
++
++static void vin_init_outputs(struct vin_line *line)
++{
++	struct vin_output *output = &line->output;
++
++	output->state = VIN_OUTPUT_OFF;
++	output->buf[0] = NULL;
++	output->buf[1] = NULL;
++	output->active_buf = 0;
++	INIT_LIST_HEAD(&output->pending_bufs);
++	INIT_LIST_HEAD(&output->ready_bufs);
++}
++
++static void vin_buf_add_ready(struct vin_output *output,
++			      struct stfcamss_buffer *buffer)
++{
++	INIT_LIST_HEAD(&buffer->queue);
++	list_add_tail(&buffer->queue, &output->ready_bufs);
++}
++
++static struct stfcamss_buffer *vin_buf_get_ready(struct vin_output *output)
++{
++	struct stfcamss_buffer *buffer = NULL;
++
++	if (!list_empty(&output->ready_bufs)) {
++		buffer = list_first_entry(&output->ready_bufs,
++					  struct stfcamss_buffer,
++					  queue);
++		list_del(&buffer->queue);
++	}
++
++	return buffer;
++}
++
++static void vin_buf_add_pending(struct vin_output *output,
++				struct stfcamss_buffer *buffer)
++{
++	INIT_LIST_HEAD(&buffer->queue);
++	list_add_tail(&buffer->queue, &output->pending_bufs);
++}
++
++static struct stfcamss_buffer *vin_buf_get_pending(struct vin_output *output)
++{
++	struct stfcamss_buffer *buffer = NULL;
++
++	if (!list_empty(&output->pending_bufs)) {
++		buffer = list_first_entry(&output->pending_bufs,
++					  struct stfcamss_buffer,
++					  queue);
++		list_del(&buffer->queue);
++	}
++
++	return buffer;
++}
++
++static void vin_buf_update_on_last(struct vin_line *line)
++{
++	struct vin_output *output = &line->output;
++
++	switch (output->state) {
++	case VIN_OUTPUT_CONTINUOUS:
++		output->state = VIN_OUTPUT_SINGLE;
++		output->active_buf = !output->active_buf;
++		break;
++	case VIN_OUTPUT_SINGLE:
++		output->state = VIN_OUTPUT_STOPPING;
++		break;
++	default:
++		break;
++	}
++}
++
++static void vin_buf_update_on_next(struct vin_line *line)
++{
++	struct vin_output *output = &line->output;
++
++	switch (output->state) {
++	case VIN_OUTPUT_CONTINUOUS:
++		output->active_buf = !output->active_buf;
++		break;
++	case VIN_OUTPUT_SINGLE:
++	default:
++		break;
++	}
++}
++
++static void vin_buf_update_on_new(struct vin_line *line,
++				  struct vin_output *output,
++				  struct stfcamss_buffer *new_buf)
++{
++	switch (output->state) {
++	case VIN_OUTPUT_SINGLE:
++		vin_buf_add_pending(output, new_buf);
++		break;
++	case VIN_OUTPUT_IDLE:
++		if (!output->buf[0]) {
++			output->buf[0] = new_buf;
++			vin_output_init_addrs(line);
++			output->state = VIN_OUTPUT_SINGLE;
++		} else {
++			vin_buf_add_pending(output, new_buf);
++		}
++		break;
++	case VIN_OUTPUT_STOPPING:
++		if (output->last_buffer) {
++			output->buf[output->active_buf] = output->last_buffer;
++			output->last_buffer = NULL;
++		}
++
++		output->state = VIN_OUTPUT_SINGLE;
++		vin_buf_add_pending(output, new_buf);
++		break;
++	case VIN_OUTPUT_CONTINUOUS:
++	default:
++		vin_buf_add_pending(output, new_buf);
++		break;
++	}
++}
++
++static void vin_buf_flush(struct vin_output *output,
++			  enum vb2_buffer_state state)
++{
++	struct stfcamss_buffer *buf;
++	struct stfcamss_buffer *t;
++
++	list_for_each_entry_safe(buf, t, &output->pending_bufs, queue) {
++		vb2_buffer_done(&buf->vb.vb2_buf, state);
++		list_del(&buf->queue);
++	}
++	list_for_each_entry_safe(buf, t, &output->ready_bufs, queue) {
++		vb2_buffer_done(&buf->vb.vb2_buf, state);
++		list_del(&buf->queue);
++	}
++}
++
++static void vin_buffer_done(struct vin_line *line)
++{
++	struct stfcamss_buffer *ready_buf;
++	struct vin_output *output = &line->output;
++	unsigned long flags;
++	u64 ts = ktime_get_ns();
++
++	if (output->state == VIN_OUTPUT_OFF ||
++	    output->state == VIN_OUTPUT_RESERVED)
++		return;
++
++	spin_lock_irqsave(&line->output_lock, flags);
++
++	while ((ready_buf = vin_buf_get_ready(output))) {
++		ready_buf->vb.vb2_buf.timestamp = ts;
++		ready_buf->vb.sequence = output->sequence++;
++
++		vb2_buffer_done(&ready_buf->vb.vb2_buf, VB2_BUF_STATE_DONE);
++	}
++
++	spin_unlock_irqrestore(&line->output_lock, flags);
++}
++
++static void vin_change_buffer(struct vin_line *line)
++{
++	struct stfcamss_buffer *ready_buf;
++	struct vin_output *output = &line->output;
++	struct stf_vin_dev *vin_dev = line_to_vin_dev(line);
++	dma_addr_t *new_addr;
++	unsigned long flags;
++	u32 active_index;
++
++	if (output->state == VIN_OUTPUT_OFF ||
++	    output->state == VIN_OUTPUT_STOPPING ||
++	    output->state == VIN_OUTPUT_RESERVED ||
++	    output->state == VIN_OUTPUT_IDLE)
++		return;
++
++	spin_lock_irqsave(&line->output_lock, flags);
++
++	active_index = output->active_buf;
++
++	ready_buf = output->buf[active_index];
++	if (!ready_buf) {
++		dev_warn(vin_dev->stfcamss->dev, "Missing ready buf %d %d!\n",
++			 active_index, output->state);
++		active_index = !active_index;
++		ready_buf = output->buf[active_index];
++		if (!ready_buf) {
++			dev_err(vin_dev->stfcamss->dev,
++				"Missing ready buf2 %d %d!\n",
++				active_index, output->state);
++			goto out_unlock;
++		}
++	}
++
++	/* Get next buffer */
++	output->buf[active_index] = vin_buf_get_pending(output);
++	if (!output->buf[active_index]) {
++		/* No next buffer - set same address */
++		new_addr = ready_buf->addr;
++		vin_buf_update_on_last(line);
++	} else {
++		new_addr = output->buf[active_index]->addr;
++		vin_buf_update_on_next(line);
++	}
++
++	if (output->state == VIN_OUTPUT_STOPPING) {
++		output->last_buffer = ready_buf;
++	} else {
++		switch (vin_map_isp_line(line->id)) {
++		case STF_ISP_LINE_SRC:
++			stf_vin_isp_set_yuv_addr(vin_dev,
++						 new_addr[0],
++						 new_addr[1]);
++			break;
++		default:
++			if (line->id == VIN_LINE_WR) {
++				stf_vin_wr_set_ping_addr(vin_dev, new_addr[0]);
++				stf_vin_wr_set_pong_addr(vin_dev, new_addr[0]);
++			}
++			break;
++		}
++
++		vin_buf_add_ready(output, ready_buf);
++	}
++
++	spin_unlock_irqrestore(&line->output_lock, flags);
++	return;
++
++out_unlock:
++	spin_unlock_irqrestore(&line->output_lock, flags);
++}
++
++static int vin_queue_buffer(struct stfcamss_video *vid,
++			    struct stfcamss_buffer *buf)
++{
++	struct vin_line *line = container_of(vid, struct vin_line, video_out);
++	struct vin_output *output;
++	unsigned long flags;
++
++	output = &line->output;
++
++	spin_lock_irqsave(&line->output_lock, flags);
++
++	vin_buf_update_on_new(line, output, buf);
++
++	spin_unlock_irqrestore(&line->output_lock, flags);
++
++	return 0;
++}
++
++static int vin_flush_buffers(struct stfcamss_video *vid,
++			     enum vb2_buffer_state state)
++{
++	struct vin_line *line = container_of(vid, struct vin_line, video_out);
++	struct vin_output *output = &line->output;
++	unsigned long flags;
++
++	spin_lock_irqsave(&line->output_lock, flags);
++
++	vin_buf_flush(output, state);
++	if (output->buf[0])
++		vb2_buffer_done(&output->buf[0]->vb.vb2_buf, state);
++
++	if (output->buf[1])
++		vb2_buffer_done(&output->buf[1]->vb.vb2_buf, state);
++
++	if (output->last_buffer) {
++		vb2_buffer_done(&output->last_buffer->vb.vb2_buf, state);
++		output->last_buffer = NULL;
++	}
++	output->buf[0] = NULL;
++	output->buf[1] = NULL;
++
++	spin_unlock_irqrestore(&line->output_lock, flags);
++	return 0;
++}
++
++static int vin_link_setup(struct media_entity *entity,
++			  const struct media_pad *local,
++			  const struct media_pad *remote, u32 flags)
++{
++	if (flags & MEDIA_LNK_FL_ENABLED)
++		if (media_pad_remote_pad_first(local))
++			return -EBUSY;
++	return 0;
++}
++
++static const struct v4l2_subdev_core_ops vin_core_ops = {
++	.s_power = vin_set_power,
++};
++
++static const struct v4l2_subdev_video_ops vin_video_ops = {
++	.s_stream = vin_set_stream,
++};
++
++static const struct v4l2_subdev_pad_ops vin_pad_ops = {
++	.enum_mbus_code   = vin_enum_mbus_code,
++	.enum_frame_size  = vin_enum_frame_size,
++	.get_fmt          = vin_get_format,
++	.set_fmt          = vin_set_format,
++};
++
++static const struct v4l2_subdev_ops vin_v4l2_ops = {
++	.core = &vin_core_ops,
++	.video = &vin_video_ops,
++	.pad = &vin_pad_ops,
++};
++
++static const struct v4l2_subdev_internal_ops vin_v4l2_internal_ops = {
++	.open = vin_init_formats,
++};
++
++static const struct stfcamss_video_ops stfcamss_vin_video_ops = {
++	.queue_buffer = vin_queue_buffer,
++	.flush_buffers = vin_flush_buffers,
++};
++
++static const struct media_entity_operations vin_media_ops = {
++	.link_setup = vin_link_setup,
++	.link_validate = v4l2_subdev_link_validate,
++};
++
++int stf_vin_register(struct stf_vin_dev *vin_dev, struct v4l2_device *v4l2_dev)
++{
++	struct v4l2_subdev *sd;
++	struct stfcamss_video *video_out;
++	struct media_pad *pads;
++	int ret;
++	int i;
++
++	for (i = 0; i < STF_ISP_LINE_MAX + 1; i++) {
++		char name[32];
++		char *sub_name = vin_get_line_subdevname(i);
++
++		sd = &vin_dev->line[i].subdev;
++		pads = vin_dev->line[i].pads;
++		video_out = &vin_dev->line[i].video_out;
++		video_out->id = i;
++
++		v4l2_subdev_init(sd, &vin_v4l2_ops);
++		sd->internal_ops = &vin_v4l2_internal_ops;
++		sd->flags |= V4L2_SUBDEV_FL_HAS_DEVNODE;
++		snprintf(sd->name, ARRAY_SIZE(sd->name), "%s%d_%s",
++			 STF_VIN_NAME, 0, sub_name);
++		v4l2_set_subdevdata(sd, &vin_dev->line[i]);
++
++		ret = vin_init_formats(sd, NULL);
++		if (ret < 0) {
++			dev_err(vin_dev->stfcamss->dev,
++				"Failed to init format: %d\n", ret);
++			goto err_init;
++		}
++
++		pads[STF_VIN_PAD_SINK].flags = MEDIA_PAD_FL_SINK;
++		pads[STF_VIN_PAD_SRC].flags = MEDIA_PAD_FL_SOURCE;
++
++		sd->entity.function =
++			MEDIA_ENT_F_PROC_VIDEO_PIXEL_FORMATTER;
++		sd->entity.ops = &vin_media_ops;
++		ret = media_entity_pads_init(&sd->entity,
++					     STF_VIN_PADS_NUM, pads);
++		if (ret < 0) {
++			dev_err(vin_dev->stfcamss->dev,
++				"Failed to init media entity: %d\n",
++				ret);
++			goto err_init;
++		}
++
++		ret = v4l2_device_register_subdev(v4l2_dev, sd);
++		if (ret < 0) {
++			dev_err(vin_dev->stfcamss->dev,
++				"Failed to register subdev: %d\n", ret);
++			goto err_reg_subdev;
++		}
++
++		video_out->ops = &stfcamss_vin_video_ops;
++		video_out->bpl_alignment = 16 * 8;
++
++		snprintf(name, ARRAY_SIZE(name), "%s_%s%d",
++			 sd->name, "video", i);
++		ret = stf_video_register(video_out, v4l2_dev, name);
++		if (ret < 0) {
++			dev_err(vin_dev->stfcamss->dev,
++				"Failed to register video node: %d\n", ret);
++			goto err_vid_reg;
++		}
++
++		ret = media_create_pad_link(
++			&sd->entity, STF_VIN_PAD_SRC,
++			&video_out->vdev.entity, 0,
++			MEDIA_LNK_FL_IMMUTABLE | MEDIA_LNK_FL_ENABLED);
++		if (ret < 0) {
++			dev_err(vin_dev->stfcamss->dev,
++				"Failed to link %s->%s entities: %d\n",
++				sd->entity.name, video_out->vdev.entity.name,
++				ret);
++			goto err_create_link;
++		}
++	}
++
++	return 0;
++
++err_create_link:
++	stf_video_unregister(video_out);
++err_vid_reg:
++	v4l2_device_unregister_subdev(sd);
++err_reg_subdev:
++	media_entity_cleanup(&sd->entity);
++err_init:
++	for (i--; i >= 0; i--) {
++		sd = &vin_dev->line[i].subdev;
++		video_out = &vin_dev->line[i].video_out;
++
++		stf_video_unregister(video_out);
++		v4l2_device_unregister_subdev(sd);
++		media_entity_cleanup(&sd->entity);
++	}
++	return ret;
++}
++
++int stf_vin_unregister(struct stf_vin_dev *vin_dev)
++{
++	struct v4l2_subdev *sd;
++	struct stfcamss_video *video_out;
++	int i;
++
++	mutex_destroy(&vin_dev->power_lock);
++	for (i = 0; i < STF_DUMMY_MODULE_NUMS; i++)
++		mutex_destroy(&vin_dev->dummy_buffer[i].stream_lock);
++
++	for (i = 0; i < STF_ISP_LINE_MAX + 1; i++) {
++		sd = &vin_dev->line[i].subdev;
++		video_out = &vin_dev->line[i].video_out;
++
++		stf_video_unregister(video_out);
++		v4l2_device_unregister_subdev(sd);
++		media_entity_cleanup(&sd->entity);
++		mutex_destroy(&vin_dev->line[i].stream_lock);
++		mutex_destroy(&vin_dev->line[i].power_lock);
++	}
++	return 0;
++}
+--- /dev/null
++++ b/drivers/media/platform/starfive/stf_vin.h
+@@ -0,0 +1,180 @@
++/* SPDX-License-Identifier: GPL-2.0 */
++/*
++ * stf_vin.h
++ *
++ * StarFive Camera Subsystem - VIN Module
++ *
++ * Copyright (C) 2021-2023 StarFive Technology Co., Ltd.
++ */
++
++#ifndef STF_VIN_H
++#define STF_VIN_H
++
++#include <linux/interrupt.h>
++#include <linux/spinlock_types.h>
++#include <media/v4l2-subdev.h>
++
++#include "stf_video.h"
++
++#define SYSCONSAIF_SYSCFG(x)	(x)
++
++/* syscon offset 0 */
++#define U0_VIN_CNFG_AXI_DVP_EN	BIT(2)
++
++/* syscon offset 20 */
++#define U0_VIN_CHANNEL_SEL_MASK	GENMASK(3, 0)
++#define U0_VIN_AXIWR0_EN	BIT(4)
++#define CHANNEL(x)	((x) << 0)
++
++/* syscon offset 32 */
++#define U0_VIN_INTR_CLEAN	BIT(0)
++#define U0_VIN_INTR_M	BIT(1)
++#define U0_VIN_PIX_CNT_END_MASK	GENMASK(12, 2)
++#define U0_VIN_PIX_CT_MASK	GENMASK(14, 13)
++#define U0_VIN_PIXEL_HEIGH_BIT_SEL_MAKS	GENMASK(16, 15)
++
++#define PIX_CNT_END(x)	((x) << 2)
++#define PIX_CT(x)	((x) << 13)
++#define PIXEL_HEIGH_BIT_SEL(x)	((x) << 15)
++
++/* syscon offset 36 */
++#define U0_VIN_CNFG_DVP_HS_POS	BIT(1)
++#define U0_VIN_CNFG_DVP_SWAP_EN	BIT(2)
++#define U0_VIN_CNFG_DVP_VS_POS	BIT(3)
++#define U0_VIN_CNFG_GEN_EN_AXIRD	BIT(4)
++#define U0_VIN_CNFG_ISP_DVP_EN0		BIT(5)
++#define U0_VIN_MIPI_BYTE_EN_ISP0(n)	((n) << 6)
++#define U0_VIN_MIPI_CHANNEL_SEL0(n)	((n) << 8)
++#define U0_VIN_P_I_MIPI_HAEDER_EN0(n)	((n) << 12)
++#define U0_VIN_PIX_NUM(n)	((n) << 13)
++#define U0_VIN_MIPI_BYTE_EN_ISP0_MASK	GENMASK(7, 6)
++#define U0_VIN_MIPI_CHANNEL_SEL0_MASK	GENMASK(11, 8)
++#define U0_VIN_P_I_MIPI_HAEDER_EN0_MASK	BIT(12)
++#define U0_VIN_PIX_NUM_MASK	GENMASK(16, 13)
++
++#define STF_VIN_PAD_SINK   0
++#define STF_VIN_PAD_SRC    1
++#define STF_VIN_PADS_NUM   2
++
++#define ISP_DUMMY_BUFFER_NUMS  STF_ISP_PAD_MAX
++#define VIN_DUMMY_BUFFER_NUMS  1
++
++enum {
++	STF_DUMMY_VIN,
++	STF_DUMMY_ISP,
++	STF_DUMMY_MODULE_NUMS,
++};
++
++enum link {
++	LINK_ERROR = -1,
++	LINK_DVP_TO_WR,
++	LINK_DVP_TO_ISP,
++	LINK_CSI_TO_WR,
++	LINK_CSI_TO_ISP,
++};
++
++struct vin_format {
++	u32 code;
++	u8 bpp;
++};
++
++struct vin_format_table {
++	const struct vin_format *fmts;
++	int nfmts;
++};
++
++enum vin_output_state {
++	VIN_OUTPUT_OFF,
++	VIN_OUTPUT_RESERVED,
++	VIN_OUTPUT_SINGLE,
++	VIN_OUTPUT_CONTINUOUS,
++	VIN_OUTPUT_IDLE,
++	VIN_OUTPUT_STOPPING
++};
++
++struct vin_output {
++	int active_buf;
++	struct stfcamss_buffer *buf[2];
++	struct stfcamss_buffer *last_buffer;
++	struct list_head pending_bufs;
++	struct list_head ready_bufs;
++	enum vin_output_state state;
++	unsigned int sequence;
++	unsigned int frame_skip;
++};
++
++/* The vin output lines */
++enum vin_line_id {
++	VIN_LINE_NONE = -1,
++	VIN_LINE_WR = 0,
++	VIN_LINE_ISP,
++	VIN_LINE_MAX,
++};
++
++struct vin_line {
++	enum stf_subdev_type sdev_type;  /* must be frist */
++	enum vin_line_id id;
++	struct v4l2_subdev subdev;
++	struct media_pad pads[STF_VIN_PADS_NUM];
++	struct v4l2_mbus_framefmt fmt[STF_VIN_PADS_NUM];
++	struct stfcamss_video video_out;
++	struct mutex stream_lock;	/* serialize stream control */
++	int stream_count;
++	struct mutex power_lock; /* serialize pipeline control in power process*/
++	int power_count;
++	struct vin_output output;	/* pipeline and stream states */
++	spinlock_t output_lock;
++	const struct vin_format *formats;
++	unsigned int nformats;
++};
++
++struct vin_dummy_buffer {
++	dma_addr_t paddr[3];
++	void *vaddr;
++	u32 buffer_size;
++	u32 width;
++	u32 height;
++	u32 mcode;
++};
++
++struct dummy_buffer {
++	struct vin_dummy_buffer *buffer;
++	u32 nums;
++	struct mutex stream_lock;	/* protects buffer data */
++	int stream_count;
++	atomic_t frame_skip;
++};
++
++struct vin_isr_ops {
++	void (*isr_buffer_done)(struct vin_line *line);
++	void (*isr_change_buffer)(struct vin_line *line);
++};
++
++struct stf_vin_dev {
++	struct stfcamss *stfcamss;
++	struct vin_line line[VIN_LINE_MAX];
++	struct dummy_buffer dummy_buffer[STF_DUMMY_MODULE_NUMS];
++	struct vin_isr_ops *isr_ops;
++	atomic_t ref_count;
++	struct mutex power_lock;	/* serialize power control*/
++	int power_count;
++};
++
++int stf_vin_clk_enable(struct stf_vin_dev *vin_dev, enum link link);
++int stf_vin_clk_disable(struct stf_vin_dev *vin_dev, enum link link);
++int stf_vin_wr_stream_set(struct stf_vin_dev *vin_dev);
++int stf_vin_stream_set(struct stf_vin_dev *vin_dev, enum link link);
++void stf_vin_wr_irq_enable(struct stf_vin_dev *vin_dev, int enable);
++void stf_vin_wr_set_ping_addr(struct stf_vin_dev *vin_dev, dma_addr_t addr);
++void stf_vin_wr_set_pong_addr(struct stf_vin_dev *vin_dev, dma_addr_t addr);
++void stf_vin_isp_set_yuv_addr(struct stf_vin_dev *vin_dev,
++			      dma_addr_t y_addr, dma_addr_t uv_addr);
++irqreturn_t stf_vin_wr_irq_handler(int irq, void *priv);
++irqreturn_t stf_vin_isp_irq_handler(int irq, void *priv);
++irqreturn_t stf_vin_isp_irq_csiline_handler(int irq, void *priv);
++int stf_vin_subdev_init(struct stfcamss *stfcamss);
++int stf_vin_register(struct stf_vin_dev *vin_dev, struct v4l2_device *v4l2_dev);
++int stf_vin_unregister(struct stf_vin_dev *vin_dev);
++enum isp_pad_id stf_vin_map_isp_pad(enum vin_line_id line, enum isp_pad_id def);
++
++#endif /* STF_VIN_H */
+--- /dev/null
++++ b/drivers/media/platform/starfive/stf_vin_hw_ops.c
+@@ -0,0 +1,241 @@
++// SPDX-License-Identifier: GPL-2.0
++/*
++ * stf_vin_hw_ops.c
++ *
++ * Register interface file for StarFive VIN module driver
++ *
++ * Copyright (C) 2021-2023 StarFive Technology Co., Ltd.
++ */
++#include "stf_camss.h"
++
++static void vin_intr_clear(struct stfcamss *stfcamss)
++{
++	stf_syscon_reg_set_bit(stfcamss, SYSCONSAIF_SYSCFG(28),
++			       U0_VIN_INTR_CLEAN);
++	stf_syscon_reg_clear_bit(stfcamss, SYSCONSAIF_SYSCFG(28),
++				 U0_VIN_INTR_CLEAN);
++}
++
++irqreturn_t stf_vin_wr_irq_handler(int irq, void *priv)
++{
++	struct stf_vin_dev *vin_dev = priv;
++	struct stfcamss *stfcamss = vin_dev->stfcamss;
++	struct dummy_buffer *dummy_buffer =
++			&vin_dev->dummy_buffer[STF_DUMMY_VIN];
++
++	if (atomic_dec_if_positive(&dummy_buffer->frame_skip) < 0) {
++		vin_dev->isr_ops->isr_change_buffer(&vin_dev->line[VIN_LINE_WR]);
++		vin_dev->isr_ops->isr_buffer_done(&vin_dev->line[VIN_LINE_WR]);
++	}
++
++	vin_intr_clear(stfcamss);
++
++	return IRQ_HANDLED;
++}
++
++irqreturn_t stf_vin_isp_irq_handler(int irq, void *priv)
++{
++	struct stf_vin_dev *vin_dev = priv;
++	u32 int_status;
++
++	int_status = stf_isp_reg_read(vin_dev->stfcamss, ISP_REG_ISP_CTRL_0);
++
++	if (int_status & ISPC_INTS) {
++		if ((int_status & ISPC_ENUO))
++			vin_dev->isr_ops->isr_buffer_done(
++				&vin_dev->line[VIN_LINE_ISP]);
++
++		/* clear interrupt */
++		stf_isp_reg_write(vin_dev->stfcamss,
++				  ISP_REG_ISP_CTRL_0,
++				  (int_status & ~EN_INT_ALL) |
++				  EN_INT_ISP_DONE |
++				  EN_INT_CSI_DONE |
++				  EN_INT_SC_DONE);
++	}
++
++	return IRQ_HANDLED;
++}
++
++irqreturn_t stf_vin_isp_irq_csiline_handler(int irq, void *priv)
++{
++	struct stf_vin_dev *vin_dev = priv;
++	struct stf_isp_dev *isp_dev;
++	u32 int_status;
++
++	isp_dev = &vin_dev->stfcamss->isp_dev;
++
++	int_status = stf_isp_reg_read(vin_dev->stfcamss, ISP_REG_ISP_CTRL_0);
++	if (int_status & ISPC_SCFEINT) {
++		struct dummy_buffer *dummy_buffer =
++			&vin_dev->dummy_buffer[STF_DUMMY_ISP];
++
++		if (atomic_dec_if_positive(&dummy_buffer->frame_skip) < 0) {
++			if ((int_status & ISPC_ENUO))
++				vin_dev->isr_ops->isr_change_buffer(
++					&vin_dev->line[VIN_LINE_ISP]);
++		}
++
++		stf_isp_reg_set_bit(isp_dev->stfcamss, ISP_REG_CSIINTS,
++				    CSI_INTS_MASK, CSI_INTS(0x3));
++		stf_isp_reg_set_bit(isp_dev->stfcamss, ISP_REG_IESHD,
++				    SHAD_UP_M | SHAD_UP_EN, 0x3);
++
++		/* clear interrupt */
++		stf_isp_reg_write(vin_dev->stfcamss, ISP_REG_ISP_CTRL_0,
++				  (int_status & ~EN_INT_ALL) | EN_INT_LINE_INT);
++	}
++
++	return IRQ_HANDLED;
++}
++
++int stf_vin_clk_enable(struct stf_vin_dev *vin_dev, enum link link)
++{
++	struct stfcamss *stfcamss = vin_dev->stfcamss;
++
++	clk_set_rate(stfcamss->sys_clk[STF_CLK_APB_FUNC].clk, 49500000);
++
++	switch (link) {
++	case LINK_CSI_TO_WR:
++		clk_set_rate(stfcamss->sys_clk[STF_CLK_MIPI_RX0_PXL].clk,
++			     198000000);
++		reset_control_deassert(stfcamss->sys_rst[STF_RST_AXIWR].rstc);
++		clk_set_parent(stfcamss->sys_clk[STF_CLK_AXIWR].clk,
++			       stfcamss->sys_clk[STF_CLK_MIPI_RX0_PXL].clk);
++		break;
++	case LINK_CSI_TO_ISP:
++		clk_set_rate(stfcamss->sys_clk[STF_CLK_MIPI_RX0_PXL].clk,
++			     198000000);
++		clk_set_parent(stfcamss->sys_clk[STF_CLK_WRAPPER_CLK_C].clk,
++			       stfcamss->sys_clk[STF_CLK_MIPI_RX0_PXL].clk);
++		break;
++	case LINK_DVP_TO_WR:
++	case LINK_DVP_TO_ISP:
++	default:
++		return -EINVAL;
++	}
++
++	return 0;
++}
++
++int stf_vin_clk_disable(struct stf_vin_dev *vin_dev, enum link link)
++{
++	struct stfcamss *stfcamss = vin_dev->stfcamss;
++
++	switch (link) {
++	case LINK_CSI_TO_WR:
++		reset_control_assert(stfcamss->sys_rst[STF_RST_AXIWR].rstc);
++		break;
++	case LINK_CSI_TO_ISP:
++		break;
++	case LINK_DVP_TO_WR:
++	case LINK_DVP_TO_ISP:
++	default:
++		return -EINVAL;
++	}
++
++	return 0;
++}
++
++int stf_vin_wr_stream_set(struct stf_vin_dev *vin_dev)
++{
++	struct stfcamss *stfcamss = vin_dev->stfcamss;
++
++	/* make the axiwr alway on */
++	stf_syscon_reg_set_bit(stfcamss, SYSCONSAIF_SYSCFG(20),
++			       U0_VIN_AXIWR0_EN);
++
++	return 0;
++}
++
++int stf_vin_stream_set(struct stf_vin_dev *vin_dev, enum link link)
++{
++	struct stfcamss *stfcamss = vin_dev->stfcamss;
++	u32 val;
++
++	switch (link) {
++	case LINK_CSI_TO_WR:
++		val = stf_syscon_reg_read(stfcamss, SYSCONSAIF_SYSCFG(20));
++		val &= ~U0_VIN_CHANNEL_SEL_MASK;
++		val |= CHANNEL(0);
++		stf_syscon_reg_write(stfcamss, SYSCONSAIF_SYSCFG(20), val);
++
++		val = stf_syscon_reg_read(stfcamss, SYSCONSAIF_SYSCFG(28));
++		val &= ~U0_VIN_PIX_CT_MASK;
++		val |= PIX_CT(1);
++
++		val &= ~U0_VIN_PIXEL_HEIGH_BIT_SEL_MAKS;
++		val |= PIXEL_HEIGH_BIT_SEL(0);
++
++		val &= ~U0_VIN_PIX_CNT_END_MASK;
++		val |= PIX_CNT_END(IMAGE_MAX_WIDTH / 4 - 1);
++
++		stf_syscon_reg_write(stfcamss, SYSCONSAIF_SYSCFG(28), val);
++		break;
++	case LINK_CSI_TO_ISP:
++		val = stf_syscon_reg_read(stfcamss, SYSCONSAIF_SYSCFG(36));
++		val &= ~U0_VIN_MIPI_BYTE_EN_ISP0_MASK;
++		val |= U0_VIN_MIPI_BYTE_EN_ISP0(0);
++
++		val &= ~U0_VIN_MIPI_CHANNEL_SEL0_MASK;
++		val |= U0_VIN_MIPI_CHANNEL_SEL0(0);
++
++		val &= ~U0_VIN_PIX_NUM_MASK;
++		val |= U0_VIN_PIX_NUM(0);
++
++		val &= ~U0_VIN_P_I_MIPI_HAEDER_EN0_MASK;
++		val |= U0_VIN_P_I_MIPI_HAEDER_EN0(1);
++
++		stf_syscon_reg_write(stfcamss, SYSCONSAIF_SYSCFG(36), val);
++		break;
++	case LINK_DVP_TO_WR:
++	case LINK_DVP_TO_ISP:
++	default:
++		return -EINVAL;
++	}
++
++	return 0;
++}
++
++void stf_vin_wr_irq_enable(struct stf_vin_dev *vin_dev, int enable)
++{
++	struct stfcamss *stfcamss = vin_dev->stfcamss;
++
++	if (enable) {
++		stf_syscon_reg_clear_bit(stfcamss, SYSCONSAIF_SYSCFG(28),
++					 U0_VIN_INTR_M);
++	} else {
++		/* clear vin interrupt */
++		stf_syscon_reg_set_bit(stfcamss, SYSCONSAIF_SYSCFG(28),
++				       U0_VIN_INTR_CLEAN);
++		stf_syscon_reg_clear_bit(stfcamss, SYSCONSAIF_SYSCFG(28),
++					 U0_VIN_INTR_CLEAN);
++		stf_syscon_reg_set_bit(stfcamss, SYSCONSAIF_SYSCFG(28),
++				       U0_VIN_INTR_M);
++	}
++}
++
++void stf_vin_wr_set_ping_addr(struct stf_vin_dev *vin_dev, dma_addr_t addr)
++{
++	struct stfcamss *stfcamss = vin_dev->stfcamss;
++
++	/* set the start address */
++	stf_syscon_reg_write(stfcamss, SYSCONSAIF_SYSCFG(32), (long)addr);
++}
++
++void stf_vin_wr_set_pong_addr(struct stf_vin_dev *vin_dev, dma_addr_t addr)
++{
++	struct stfcamss *stfcamss = vin_dev->stfcamss;
++
++	/* set the start address */
++	stf_syscon_reg_write(stfcamss, SYSCONSAIF_SYSCFG(24), (long)addr);
++}
++
++void stf_vin_isp_set_yuv_addr(struct stf_vin_dev *vin_dev,
++			      dma_addr_t y_addr, dma_addr_t uv_addr)
++{
++	stf_isp_reg_write(vin_dev->stfcamss,
++			  ISP_REG_Y_PLANE_START_ADDR, y_addr);
++	stf_isp_reg_write(vin_dev->stfcamss,
++			  ISP_REG_UV_PLANE_START_ADDR, uv_addr);
++}

+ 68 - 0
target/linux/starfive/patches-6.1/0087-dt-bindings-phy-Add-StarFive-JH7110-USB-PHY.patch

@@ -0,0 +1,68 @@
+From 2ebd77fa8fb95f60b275cefb98ea7d6f4df06e55 Mon Sep 17 00:00:00 2001
+From: Minda Chen <[email protected]>
+Date: Thu, 18 May 2023 19:27:44 +0800
+Subject: [PATCH 087/122] dt-bindings: phy: Add StarFive JH7110 USB PHY
+
+Add StarFive JH7110 SoC USB 2.0 PHY dt-binding.
+
+Signed-off-by: Minda Chen <[email protected]>
+Reviewed-by: Hal Feng <[email protected]>
+Reviewed-by: Rob Herring <[email protected]>
+---
+ .../bindings/phy/starfive,jh7110-usb-phy.yaml | 50 +++++++++++++++++++
+ 1 file changed, 50 insertions(+)
+ create mode 100644 Documentation/devicetree/bindings/phy/starfive,jh7110-usb-phy.yaml
+
+--- /dev/null
++++ b/Documentation/devicetree/bindings/phy/starfive,jh7110-usb-phy.yaml
+@@ -0,0 +1,50 @@
++# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
++%YAML 1.2
++---
++$id: http://devicetree.org/schemas/phy/starfive,jh7110-usb-phy.yaml#
++$schema: http://devicetree.org/meta-schemas/core.yaml#
++
++title: StarFive JH7110 USB 2.0 PHY
++
++maintainers:
++  - Minda Chen <[email protected]>
++
++properties:
++  compatible:
++    const: starfive,jh7110-usb-phy
++
++  reg:
++    maxItems: 1
++
++  "#phy-cells":
++    const: 0
++
++  clocks:
++    items:
++      - description: PHY 125m
++      - description: app 125m
++
++  clock-names:
++    items:
++      - const: 125m
++      - const: app_125m
++
++required:
++  - compatible
++  - reg
++  - clocks
++  - clock-names
++  - "#phy-cells"
++
++additionalProperties: false
++
++examples:
++  - |
++    phy@10200000 {
++        compatible = "starfive,jh7110-usb-phy";
++        reg = <0x10200000 0x10000>;
++        clocks = <&syscrg 95>,
++                 <&stgcrg 6>;
++        clock-names = "125m", "app_125m";
++        #phy-cells = <0>;
++    };

Деякі файли не було показано, через те що забагато файлів було змінено