]> git.ipfire.org Git - thirdparty/openwrt.git/commitdiff
starfive: drop 6.6 support
authorZoltan HERPAI <wigyori@uid0.hu>
Thu, 12 Jun 2025 16:15:13 +0000 (16:15 +0000)
committerZoltan HERPAI <wigyori@uid0.hu>
Fri, 13 Jun 2025 22:53:19 +0000 (00:53 +0200)
Drop configs and patches for Linux 6.6.

Signed-off-by: Zoltan HERPAI <wigyori@uid0.hu>
140 files changed:
target/linux/starfive/config-6.6 [deleted file]
target/linux/starfive/patches-6.6/0001-clk-starfive-jh7110-sys-Fix-lower-rate-of-CPUfreq-by.patch [deleted file]
target/linux/starfive/patches-6.6/0002-dt-bindings-timer-Add-timer-for-StarFive-JH7110-SoC.patch [deleted file]
target/linux/starfive/patches-6.6/0003-clocksource-Add-JH7110-timer-driver.patch [deleted file]
target/linux/starfive/patches-6.6/0004-dt-bindings-mmc-starfive-Remove-properties-from-requ.patch [deleted file]
target/linux/starfive/patches-6.6/0005-mmc-starfive-Change-tuning-implementation.patch [deleted file]
target/linux/starfive/patches-6.6/0006-dt-bindings-pwm-Add-bindings-for-OpenCores-PWM-Contr.patch [deleted file]
target/linux/starfive/patches-6.6/0007-pwm-opencores-Add-PWM-driver-support.patch [deleted file]
target/linux/starfive/patches-6.6/0008-crypto-starfive-remove-unnecessary-alignmask-for-aha.patch [deleted file]
target/linux/starfive/patches-6.6/0009-crypto-starfive-Update-driver-dependencies.patch [deleted file]
target/linux/starfive/patches-6.6/0010-crypto-starfive-RSA-poll-csr-for-done-status.patch [deleted file]
target/linux/starfive/patches-6.6/0011-crypto-starfive-Pad-adata-with-zeroes.patch [deleted file]
target/linux/starfive/patches-6.6/0012-crypto-starfive-Remove-cfb-and-ofb.patch [deleted file]
target/linux/starfive/patches-6.6/0013-crypto-starfive-Remove-unneeded-NULL-checks.patch [deleted file]
target/linux/starfive/patches-6.6/0014-dt-bindings-PCI-Add-PLDA-XpressRICH-PCIe-host-common.patch [deleted file]
target/linux/starfive/patches-6.6/0015-PCI-microchip-Move-pcie-microchip-host.c-to-plda-dir.patch [deleted file]
target/linux/starfive/patches-6.6/0016-PCI-microchip-Move-PLDA-IP-register-macros-to-pcie-p.patch [deleted file]
target/linux/starfive/patches-6.6/0017-PCI-microchip-Add-bridge_addr-field-to-struct-mc_pci.patch [deleted file]
target/linux/starfive/patches-6.6/0018-PCI-microchip-Rename-two-PCIe-data-structures.patch [deleted file]
target/linux/starfive/patches-6.6/0019-PCI-microchip-Move-PCIe-host-data-structures-to-plda.patch [deleted file]
target/linux/starfive/patches-6.6/0020-PCI-microchip-Rename-two-setup-functions.patch [deleted file]
target/linux/starfive/patches-6.6/0021-PCI-microchip-Change-the-argument-of-plda_pcie_setup.patch [deleted file]
target/linux/starfive/patches-6.6/0022-PCI-microchip-Move-setup-functions-to-pcie-plda-host.patch [deleted file]
target/linux/starfive/patches-6.6/0023-PCI-microchip-Rename-interrupt-related-functions.patch [deleted file]
target/linux/starfive/patches-6.6/0024-PCI-microchip-Add-num_events-field-to-struct-plda_pc.patch [deleted file]
target/linux/starfive/patches-6.6/0025-PCI-microchip-Add-request_event_irq-callback-functio.patch [deleted file]
target/linux/starfive/patches-6.6/0026-PCI-microchip-Add-INTx-and-MSI-event-num-to-struct-p.patch [deleted file]
target/linux/starfive/patches-6.6/0027-PCI-microchip-Add-get_events-callback-and-add-PLDA-g.patch [deleted file]
target/linux/starfive/patches-6.6/0028-PCI-microchip-Add-event-irqchip-field-to-host-port-a.patch [deleted file]
target/linux/starfive/patches-6.6/0029-PCI-microchip-Move-IRQ-functions-to-pcie-plda-host.c.patch [deleted file]
target/linux/starfive/patches-6.6/0030-pci-plda-Add-event-bitmap-field-to-struct-plda_pcie_.patch [deleted file]
target/linux/starfive/patches-6.6/0031-PCI-plda-Add-host-init-deinit-and-map-bus-functions.patch [deleted file]
target/linux/starfive/patches-6.6/0032-dt-bindings-PCI-Add-StarFive-JH7110-PCIe-controller.patch [deleted file]
target/linux/starfive/patches-6.6/0033-PCI-Add-PCIE_RESET_CONFIG_DEVICE_WAIT_MS-waiting-tim.patch [deleted file]
target/linux/starfive/patches-6.6/0034-PCI-starfive-Add-JH7110-PCIe-controller.patch [deleted file]
target/linux/starfive/patches-6.6/0035-ASoC-dt-bindings-Add-StarFive-JH7110-PWM-DAC-control.patch [deleted file]
target/linux/starfive/patches-6.6/0036-ASoC-starfive-Add-JH7110-PWM-DAC-driver.patch [deleted file]
target/linux/starfive/patches-6.6/0037-ASoC-Update-jh7110-PWM-DAC-for-ops-move.patch [deleted file]
target/linux/starfive/patches-6.6/0038-ASoC-starfive-jh7110-pwmdac-Convert-to-platform-remo.patch [deleted file]
target/linux/starfive/patches-6.6/0039-dt-bindings-power-Add-power-domain-header-for-JH7110.patch [deleted file]
target/linux/starfive/patches-6.6/0040-pmdomain-starfive-Replace-SOC_STARFIVE-with-ARCH_STA.patch [deleted file]
target/linux/starfive/patches-6.6/0041-pmdomain-starfive-Extract-JH7110-pmu-private-operati.patch [deleted file]
target/linux/starfive/patches-6.6/0042-pmdomain-starfive-Add-JH7110-AON-PMU-support.patch [deleted file]
target/linux/starfive/patches-6.6/0043-pmdomain-Prepare-to-move-Kconfig-files-into-the-pmdo.patch [deleted file]
target/linux/starfive/patches-6.6/0044-pmdomain-starfive-Move-Kconfig-file-to-the-pmdomain-.patch [deleted file]
target/linux/starfive/patches-6.6/0045-dt-bindings-power-Update-prefixes-for-AON-power-doma.patch [deleted file]
target/linux/starfive/patches-6.6/0046-pmdomain-starfive-Update-prefixes-for-AON-power-doma.patch [deleted file]
target/linux/starfive/patches-6.6/0047-riscv-dts-starfive-pinfunc-Fix-the-pins-name-of-I2ST.patch [deleted file]
target/linux/starfive/patches-6.6/0048-riscv-dts-starfive-Add-full-support-except-VIN-and-V.patch [deleted file]
target/linux/starfive/patches-6.6/0049-MAINTAINERS-Update-all-StarFive-entries.patch [deleted file]
target/linux/starfive/patches-6.6/0050-mmc-starfive-Change-the-voltage-to-adapt-to-JH7110-E.patch [deleted file]
target/linux/starfive/patches-6.6/0051-spi-spl022-Get-and-deassert-reset-in-probe.patch [deleted file]
target/linux/starfive/patches-6.6/0052-ASoC-dwc-i2s-Fix-getting-platform-data-error-for-Sta.patch [deleted file]
target/linux/starfive/patches-6.6/0053-ASoC-dwc-i2s-Add-RX-master-support-for-StarFive-JH71.patch [deleted file]
target/linux/starfive/patches-6.6/0054-pinctrl-starfive-jh7110-Unset-.strict-in-pinmux_ops.patch [deleted file]
target/linux/starfive/patches-6.6/0055-mm-pgtable-generic.c-Export-symbol-__pte_offset_map.patch [deleted file]
target/linux/starfive/patches-6.6/0056-riscv-dts-starfive-Add-JH7110-EVB-device-tree.patch [deleted file]
target/linux/starfive/patches-6.6/0057-riscv-dts-starfive-Add-JH7110-EVB-expanded-device-tr.patch [deleted file]
target/linux/starfive/patches-6.6/0058-riscv-dts-starfive-Add-evb-overlay-dtso-subdir.patch [deleted file]
target/linux/starfive/patches-6.6/0059-riscv-configs-Add-starfive_jh7110_defconfig.patch [deleted file]
target/linux/starfive/patches-6.6/0060-of-configfs-Add-configfs-function.patch [deleted file]
target/linux/starfive/patches-6.6/0061-usr-Add-gen_initramfs_list.sh.patch [deleted file]
target/linux/starfive/patches-6.6/0062-i2c-designware-Delete-SMBus-functionalities.patch [deleted file]
target/linux/starfive/patches-6.6/0063-drivers-mtd-gigadevice-add-gd25lq256d-32M-flash-supp.patch [deleted file]
target/linux/starfive/patches-6.6/0064-driver-mailbox-Add-mailbox-driver.patch [deleted file]
target/linux/starfive/patches-6.6/0065-driver-rtc-Add-StarFive-JH7110-rtc-driver.patch [deleted file]
target/linux/starfive/patches-6.6/0066-uart-8250-Add-dw-auto-flow-ctrl-support.patch [deleted file]
target/linux/starfive/patches-6.6/0067-driver-uart-fix-up-uart-communicate-fail.patch [deleted file]
target/linux/starfive/patches-6.6/0068-uart-8250-add-reset-operation-in-runtime-PM.patch [deleted file]
target/linux/starfive/patches-6.6/0069-dt-bindings-CAN-Add-StarFive-CAN-module.patch [deleted file]
target/linux/starfive/patches-6.6/0070-CAN-starfive-Add-CAN-engine-support.patch [deleted file]
target/linux/starfive/patches-6.6/0071-regulator-starfive-jh7110-Add-regulator-support-for-.patch [deleted file]
target/linux/starfive/patches-6.6/0072-drivers-nvme-Add-precheck-and-delay-for-CQE-pending-.patch [deleted file]
target/linux/starfive/patches-6.6/0073-RISC-V-Create-unique-identification-for-SoC-PMU.patch [deleted file]
target/linux/starfive/patches-6.6/0074-RISC-V-Support-CPUID-for-risc-v-in-perf.patch [deleted file]
target/linux/starfive/patches-6.6/0075-RISC-V-Added-generic-pmu-events-mapfile.patch [deleted file]
target/linux/starfive/patches-6.6/0076-perf-sbi-disable-cpu-hotplug-callback.patch [deleted file]
target/linux/starfive/patches-6.6/0077-dmaengine-dw-axi-dmac-Drop-unused-print-message.patch [deleted file]
target/linux/starfive/patches-6.6/0079-ASoC-codecs-Add-AC108-Codec-driver.patch [deleted file]
target/linux/starfive/patches-6.6/0080-ASoC-starfive-Add-SPDIF-and-PCM-driver.patch [deleted file]
target/linux/starfive/patches-6.6/0081-ASoC-starfive-Add-JH7110-PDM-driver.patch [deleted file]
target/linux/starfive/patches-6.6/0082-dt-binding-input-Add-tink_ft5406.patch [deleted file]
target/linux/starfive/patches-6.6/0083-input-touchscreen-Add-tinker_ft5406-driver-support.patch [deleted file]
target/linux/starfive/patches-6.6/0084-dt-binding-media-Add-JH7110-Camera-Subsystem.patch [deleted file]
target/linux/starfive/patches-6.6/0085-media-starfive-Add-vin-driver-support.patch [deleted file]
target/linux/starfive/patches-6.6/0086-dt-bindings-media-i2c-Add-IMX708-CMOS-sensor-binding.patch [deleted file]
target/linux/starfive/patches-6.6/0087-media-i2c-Add-imx708-support.patch [deleted file]
target/linux/starfive/patches-6.6/0088-media-i2c-imx708-Delete-gain.patch [deleted file]
target/linux/starfive/patches-6.6/0089-dt-bindings-display-Add-yamls-for-JH7110-display-sys.patch [deleted file]
target/linux/starfive/patches-6.6/0090-soc-starfive-jh71xx_pmu-Add-EVENT_TURN_OFF-register-.patch [deleted file]
target/linux/starfive/patches-6.6/0091-workqueue-Enable-flush_scheduled_work.patch [deleted file]
target/linux/starfive/patches-6.6/0092-riscv-Optimize-memcpy-with-aligned-version.patch [deleted file]
target/linux/starfive/patches-6.6/0093-riscv-purgatory-Change-memcpy-to-the-aligned-version.patch [deleted file]
target/linux/starfive/patches-6.6/0094-Add-16-ISP-controls-remove-the-frame-SYNC-event-to-v.patch [deleted file]
target/linux/starfive/patches-6.6/0095-Expand-2-bytes-after-the-SC-buffer-for-the-AE-AWB-fl.patch [deleted file]
target/linux/starfive/patches-6.6/0096-Add-ISP-control-for-video2-and-video3.patch [deleted file]
target/linux/starfive/patches-6.6/0097-media-starfive-Update-ISP-initialzation.patch [deleted file]
target/linux/starfive/patches-6.6/0098-crypto-jh7110-Comment-RSA-algo-register.patch [deleted file]
target/linux/starfive/patches-6.6/0099-riscv-dts-starfive-jh7110-evb-Add-qspi-norflash-part.patch [deleted file]
target/linux/starfive/patches-6.6/0100-driver-regulator-pmic-driver-support-kernel-6.6.patch [deleted file]
target/linux/starfive/patches-6.6/0101-spi-pl022-starfive-Add-platform-bus-register-to-adap.patch [deleted file]
target/linux/starfive/patches-6.6/0102-spi-pl022-starfive-Avoid-power-device-error-when-CON.patch [deleted file]
target/linux/starfive/patches-6.6/0103-spi-pl022-starfive-fix-the-problem-of-spi-overlay-re.patch [deleted file]
target/linux/starfive/patches-6.6/0104-spi-pl022-starfive-Enable-spi-to-be-compiled-into-mo.patch [deleted file]
target/linux/starfive/patches-6.6/0105-riscv-configs-add-visionfive2-defconfig-to-kernel-6..patch [deleted file]
target/linux/starfive/patches-6.6/0106-riscv-dts-starfive-update-dts-to-kernel-6.6.patch [deleted file]
target/linux/starfive/patches-6.6/0107-riscv-dts-starfive-evb-overlay-Support-SPI-overlay.patch [deleted file]
target/linux/starfive/patches-6.6/0108-riscv-configs-visionfive2-Add-standard-partition-for.patch [deleted file]
target/linux/starfive/patches-6.6/0109-usb-xhci-To-improve-performance-usb-using-lowmem-for.patch [deleted file]
target/linux/starfive/patches-6.6/0110-usb-xhci-using-dma_alloc_noncoherent-to-alloc-low-me.patch [deleted file]
target/linux/starfive/patches-6.6/0111-riscv-dts-starfive-Add-vf2-overlay-dtso-subdir.patch [deleted file]
target/linux/starfive/patches-6.6/0112-riscv-dts-starfive-visionfive-2-Add-aliases-for-i2c-.patch [deleted file]
target/linux/starfive/patches-6.6/0114-riscv-dts-starfive-visionfive-2-Sync-the-sound-card-.patch [deleted file]
target/linux/starfive/patches-6.6/0115-clk-starfive-jh7110-Change-uart3-uart5-clk-register-.patch [deleted file]
target/linux/starfive/patches-6.6/0116-riscv-dts-starfive-visionfive-2-Quote-corresponding-.patch [deleted file]
target/linux/starfive/patches-6.6/1000-serial-8250_dw-Add-starfive-jh7100-hsuart-compatible.patch [deleted file]
target/linux/starfive/patches-6.6/1001-RISC-V-Add-StarFive-JH7100-audio-clock-node.patch [deleted file]
target/linux/starfive/patches-6.6/1002-drivers-tty-serial-8250-update-driver-for-JH7100.patch [deleted file]
target/linux/starfive/patches-6.6/1003-dmaengine-dw-axi-dmac-Handle-xfer-start-while-non-id.patch [deleted file]
target/linux/starfive/patches-6.6/1004-dmaengine-dw-axi-dmac-Add-StarFive-JH7100-support.patch [deleted file]
target/linux/starfive/patches-6.6/1005-pinctrl-starfive-Reset-pinmux-settings.patch [deleted file]
target/linux/starfive/patches-6.6/1006-clk-starfive-Add-flags-argument-to-JH71X0__MUX-macro.patch [deleted file]
target/linux/starfive/patches-6.6/1007-clk-starfive-jh7100-Add-CLK_SET_RATE_PARENT-to-gmac_.patch [deleted file]
target/linux/starfive/patches-6.6/1008-clk-starfive-jh7100-Keep-more-clocks-alive.patch [deleted file]
target/linux/starfive/patches-6.6/1009-net-stmmac-use-GFP_DMA32.patch [deleted file]
target/linux/starfive/patches-6.6/1010-hwrng-Add-StarFive-JH7100-Random-Number-Generator-dr.patch [deleted file]
target/linux/starfive/patches-6.6/1011-pwm-sifive-ptc-Add-SiFive-PWM-PTC-driver.patch [deleted file]
target/linux/starfive/patches-6.6/1012-dt-bindings-reset-Add-StarFive-JH7100-audio-reset-de.patch [deleted file]
target/linux/starfive/patches-6.6/1013-dt-bindings-reset-Add-starfive-jh7100-audrst-binding.patch [deleted file]
target/linux/starfive/patches-6.6/1014-reset-starfive-Add-JH7100-audio-reset-driver.patch [deleted file]
target/linux/starfive/patches-6.6/1015-RISC-V-Add-StarFive-JH7100-audio-reset-node.patch [deleted file]
target/linux/starfive/patches-6.6/1016-soc-sifive-ccache-Add-StarFive-JH7100-support.patch [deleted file]
target/linux/starfive/patches-6.6/1017-riscv-errata-Add-StarFive-JH7100-errata.patch [deleted file]
target/linux/starfive/patches-6.6/1018-riscv-dts-starfive-Mark-the-JH7100-as-having-non-coh.patch [deleted file]
target/linux/starfive/patches-6.6/1019-riscv-dts-starfive-Add-JH7100-cache-controller.patch [deleted file]
target/linux/starfive/patches-6.6/1020-riscv-dts-starfive-Add-pool-for-coherent-DMA-memory-.patch [deleted file]
target/linux/starfive/patches-6.6/1021-riscv-dts-starfive-Add-JH7100-MMC-nodes.patch [deleted file]
target/linux/starfive/patches-6.6/1022-riscv-dts-starfive-Enable-SD-card-on-JH7100-boards.patch [deleted file]
target/linux/starfive/patches-6.6/1023-riscv-errata-Make-ERRATA_STARFIVE_JH7100-depend-on-D.patch [deleted file]
target/linux/starfive/patches-6.6/1024-riscv-dts-Add-full-JH7100-Starlight-and-VisionFive-s.patch [deleted file]

diff --git a/target/linux/starfive/config-6.6 b/target/linux/starfive/config-6.6
deleted file mode 100644 (file)
index 61b2ce7..0000000
+++ /dev/null
@@ -1,575 +0,0 @@
-CONFIG_64BIT=y
-# CONFIG_ACPI is not set
-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_RV32I is not set
-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_THEAD is not set
-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_AX45MP_L2_CACHE is not set
-CONFIG_CC_HAVE_STACKPROTECTOR_TLS=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_ANDES is not set
-CONFIG_ERRATA_SIFIVE=y
-CONFIG_ERRATA_SIFIVE_CIP_1200=y
-CONFIG_ERRATA_SIFIVE_CIP_453=y
-CONFIG_ERRATA_STARFIVE_JH7100=y
-# CONFIG_ERRATA_THEAD is not set
-CONFIG_EXCLUSIVE_SYSTEM_RAM=y
-CONFIG_EXT4_FS=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_FWNODE_MDIO=y
-CONFIG_FW_LOADER_PAGED_BUF=y
-CONFIG_FW_LOADER_SYSFS=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_IPMS_CAN is not set
-CONFIG_IRQCHIP=y
-CONFIG_IRQ_DOMAIN=y
-CONFIG_IRQ_DOMAIN_HIERARCHY=y
-CONFIG_IRQ_FORCED_THREADING=y
-CONFIG_IRQ_STACKS=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_NONPORTABLE=y
-CONFIG_NO_HZ_COMMON=y
-CONFIG_NO_HZ_IDLE=y
-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_CONFIGFS is not set
-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_HOST=y
-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_PHYS_RAM_BASE_FIXED is not set
-CONFIG_PHY_STARFIVE_DPHY_RX=y
-CONFIG_PHY_STARFIVE_JH7110_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_OCORES=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_STARFIVE_JH7110=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_FALLBACK=y
-CONFIG_RISCV_ISA_SVNAPOT=y
-# CONFIG_RISCV_ISA_SVPBMT is not set
-CONFIG_RISCV_ISA_V=y
-CONFIG_RISCV_ISA_V_DEFAULT_ENABLE=y
-CONFIG_RISCV_ISA_ZBB=y
-# CONFIG_RISCV_ISA_ZICBOM is not set
-CONFIG_RISCV_ISA_ZICBOZ=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_DRV_STARFIVE=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_AC108 is not set
-# 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_JH7110_TIMER=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_THREAD_SIZE_ORDER=2
-CONFIG_TICK_CPU_ACCOUNTING=y
-CONFIG_TIMER_OF=y
-CONFIG_TIMER_PROBE=y
-CONFIG_TOOLCHAIN_HAS_ZICBOM=y
-CONFIG_TOOLCHAIN_HAS_ZIHINTPAUSE=y
-CONFIG_TOOLCHAIN_NEEDS_EXPLICIT_ZICSR_ZIFENCEI=y
-# CONFIG_TOUCHSCREEN_TINKER_FT5406 is not set
-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_MIDI2 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_VIDEO_STF_VIN is not set
-# 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
diff --git a/target/linux/starfive/patches-6.6/0001-clk-starfive-jh7110-sys-Fix-lower-rate-of-CPUfreq-by.patch b/target/linux/starfive/patches-6.6/0001-clk-starfive-jh7110-sys-Fix-lower-rate-of-CPUfreq-by.patch
deleted file mode 100644 (file)
index e98e6df..0000000
+++ /dev/null
@@ -1,76 +0,0 @@
-From 69275b667bd930cf5d5f577ba0ab1987c9d13987 Mon Sep 17 00:00:00 2001
-From: Xingyu Wu <xingyu.wu@starfivetech.com>
-Date: Mon, 21 Aug 2023 23:29:15 +0800
-Subject: [PATCH 001/116] clk: starfive: jh7110-sys: Fix lower rate of CPUfreq
- by setting PLL0 rate to 1.5GHz
-
-CPUfreq supports 4 cpu frequency loads on 375/500/750/1500MHz.
-But now PLL0 rate is 1GHz and the cpu frequency loads become
-333/500/500/1000MHz in fact.
-
-So PLL0 rate should be set to 1.5GHz. Change the parent of cpu_root clock
-and the divider of cpu_core before the setting.
-
-Reviewed-by: Hal Feng <hal.feng@starfivetech.com>
-Fixes: e2c510d6d630 ("riscv: dts: starfive: Add cpu scaling for JH7110 SoC")
-Signed-off-by: Xingyu Wu <xingyu.wu@starfivetech.com>
----
- .../clk/starfive/clk-starfive-jh7110-sys.c    | 47 ++++++++++++++++++-
- 1 file changed, 46 insertions(+), 1 deletion(-)
-
---- a/drivers/clk/starfive/clk-starfive-jh7110-sys.c
-+++ b/drivers/clk/starfive/clk-starfive-jh7110-sys.c
-@@ -530,7 +530,52 @@ static int __init jh7110_syscrg_probe(st
-       if (ret)
-               return ret;
--      return jh7110_reset_controller_register(priv, "rst-sys", 0);
-+      ret = jh7110_reset_controller_register(priv, "rst-sys", 0);
-+      if (ret)
-+              return ret;
-+
-+      /*
-+       * Set PLL0 rate to 1.5GHz
-+       * In order to not affect the cpu when the PLL0 rate is changing,
-+       * we need to switch the parent of cpu_root clock to osc clock first,
-+       * and then switch back after setting the PLL0 rate.
-+       */
-+      pllclk = clk_get(priv->dev, "pll0_out");
-+      if (!IS_ERR(pllclk)) {
-+              struct clk *osc = clk_get(&pdev->dev, "osc");
-+              struct clk *cpu_root = priv->reg[JH7110_SYSCLK_CPU_ROOT].hw.clk;
-+              struct clk *cpu_core = priv->reg[JH7110_SYSCLK_CPU_CORE].hw.clk;
-+
-+              if (IS_ERR(osc)) {
-+                      clk_put(pllclk);
-+                      return PTR_ERR(osc);
-+              }
-+
-+              /*
-+               * CPU need voltage regulation by CPUfreq if set 1.5GHz.
-+               * So in this driver, cpu_core need to be set the divider to be 2 first
-+               * and will be 750M after setting parent.
-+               */
-+              ret = clk_set_rate(cpu_core, clk_get_rate(cpu_core) / 2);
-+              if (ret)
-+                      goto failed_set;
-+
-+              ret = clk_set_parent(cpu_root, osc);
-+              if (ret)
-+                      goto failed_set;
-+
-+              ret = clk_set_rate(pllclk, 1500000000);
-+              if (ret)
-+                      goto failed_set;
-+
-+              ret = clk_set_parent(cpu_root, pllclk);
-+
-+failed_set:
-+              clk_put(pllclk);
-+              clk_put(osc);
-+      }
-+
-+      return ret;
- }
- static const struct of_device_id jh7110_syscrg_match[] = {
diff --git a/target/linux/starfive/patches-6.6/0002-dt-bindings-timer-Add-timer-for-StarFive-JH7110-SoC.patch b/target/linux/starfive/patches-6.6/0002-dt-bindings-timer-Add-timer-for-StarFive-JH7110-SoC.patch
deleted file mode 100644 (file)
index 2b5318b..0000000
+++ /dev/null
@@ -1,114 +0,0 @@
-From 7d0dbcbc079e4f72b69f53442b7759da6ebc4f87 Mon Sep 17 00:00:00 2001
-From: Xingyu Wu <xingyu.wu@starfivetech.com>
-Date: Thu, 19 Oct 2023 13:34:59 +0800
-Subject: [PATCH 002/116] dt-bindings: timer: Add timer for StarFive JH7110 SoC
-
-Add bindings for the timer on the JH7110 RISC-V SoC
-by StarFive Technology Ltd.
-
-Reviewed-by: Krzysztof Kozlowski <krzysztof.kozlowski@linaro.org>
-Signed-off-by: Xingyu Wu <xingyu.wu@starfivetech.com>
----
- .../bindings/timer/starfive,jh7110-timer.yaml | 96 +++++++++++++++++++
- 1 file changed, 96 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,96 @@
-+# 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 <xingyu.wu@starfivetech.com>
-+  - Samin Guo <samin.guo@starfivetech.com>
-+
-+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";
-+    };
-+
diff --git a/target/linux/starfive/patches-6.6/0003-clocksource-Add-JH7110-timer-driver.patch b/target/linux/starfive/patches-6.6/0003-clocksource-Add-JH7110-timer-driver.patch
deleted file mode 100644 (file)
index b4398ef..0000000
+++ /dev/null
@@ -1,428 +0,0 @@
-From 7cb47848f8a10aed6e050c0ea483b4bb5eaa62a4 Mon Sep 17 00:00:00 2001
-From: Xingyu Wu <xingyu.wu@starfivetech.com>
-Date: Thu, 19 Oct 2023 13:35:00 +0800
-Subject: [PATCH 003/116] clocksource: Add JH7110 timer driver
-
-Add timer driver for the StarFive JH7110 SoC.
-
-Signed-off-by: Xingyu Wu <xingyu.wu@starfivetech.com>
----
- drivers/clocksource/Kconfig        |  11 +
- drivers/clocksource/Makefile       |   1 +
- drivers/clocksource/timer-jh7110.c | 380 +++++++++++++++++++++++++++++
- 3 files changed, 392 insertions(+)
- create mode 100644 drivers/clocksource/timer-jh7110.c
-
---- a/drivers/clocksource/Kconfig
-+++ b/drivers/clocksource/Kconfig
-@@ -642,6 +642,17 @@ config RISCV_TIMER
-         is accessed via both the SBI and the rdcycle instruction.  This is
-         required for all RISC-V systems.
-+config STARFIVE_JH7110_TIMER
-+      bool "Timer for the STARFIVE JH7110 SoC"
-+      depends on ARCH_STARFIVE || COMPILE_TEST
-+      select TIMER_OF
-+      select CLKSRC_MMIO
-+      default ARCH_STARFIVE
-+      help
-+        This enables the timer for StarFive JH7110 SoC. On RISC-V platform,
-+        the system has started RISCV_TIMER, but you can also use this timer
-+        which can provide four channels to do a lot more things on 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_JH7110_TIMER)   += timer-jh7110.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-jh7110.c
-@@ -0,0 +1,380 @@
-+// SPDX-License-Identifier: GPL-2.0
-+/*
-+ * Starfive JH7110 Timer driver
-+ *
-+ * Copyright (C) 2022-2023 StarFive Technology Co., Ltd.
-+ *
-+ * Author:
-+ * Xingyu Wu <xingyu.wu@starfivetech.com>
-+ * Samin Guo <samin.guo@starfivetech.com>
-+ */
-+
-+#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>
-+
-+/* Bias: Ch0-0x0, Ch1-0x40, Ch2-0x80, and so on. */
-+#define JH7110_TIMER_CH_LEN           0x40
-+#define JH7110_TIMER_CH_BASE(x)               ((x) * JH7110_TIMER_CH_LEN)
-+#define JH7110_TIMER_CH_MAX           4
-+
-+#define JH7110_CLOCK_SOURCE_RATING    200
-+#define JH7110_VALID_BITS             32
-+#define JH7110_DELAY_US                       0
-+#define JH7110_TIMEOUT_US             10000
-+#define JH7110_CLOCKEVENT_RATING      300
-+#define JH7110_TIMER_MAX_TICKS                0xffffffff
-+#define JH7110_TIMER_MIN_TICKS                0xf
-+#define JH7110_TIMER_RELOAD_VALUE     0
-+
-+#define JH7110_TIMER_INT_STATUS               0x00 /* RO[0:4]: Interrupt Status for channel0~4 */
-+#define JH7110_TIMER_CTL              0x04 /* RW[0]: 0-continuous run, 1-single run */
-+#define JH7110_TIMER_LOAD             0x08 /* RW: load value to counter */
-+#define JH7110_TIMER_ENABLE           0x10 /* RW[0]: timer enable register */
-+#define JH7110_TIMER_RELOAD           0x14 /* RW: write 1 or 0 both reload counter */
-+#define JH7110_TIMER_VALUE            0x18 /* RO: timer value register */
-+#define JH7110_TIMER_INT_CLR          0x20 /* RW: timer interrupt clear register */
-+#define JH7110_TIMER_INT_MASK         0x24 /* RW[0]: timer interrupt mask register */
-+
-+#define JH7110_TIMER_INT_CLR_ENA      BIT(0)
-+#define JH7110_TIMER_INT_CLR_AVA_MASK BIT(1)
-+
-+struct jh7110_clkevt {
-+      struct clock_event_device evt;
-+      struct clocksource cs;
-+      bool cs_is_valid;
-+      struct clk *clk;
-+      struct reset_control *rst;
-+      u32 rate;
-+      u32 reload_val;
-+      void __iomem *base;
-+      char name[sizeof("jh7110-timer.chX")];
-+};
-+
-+struct jh7110_timer_priv {
-+      struct clk *pclk;
-+      struct reset_control *prst;
-+      struct jh7110_clkevt clkevt[JH7110_TIMER_CH_MAX];
-+};
-+
-+/* 0:continuous-run mode, 1:single-run mode */
-+enum jh7110_timer_mode {
-+      JH7110_TIMER_MODE_CONTIN,
-+      JH7110_TIMER_MODE_SINGLE,
-+};
-+
-+/* Interrupt Mask, 0:Unmask, 1:Mask */
-+enum jh7110_timer_int_mask {
-+      JH7110_TIMER_INT_ENA,
-+      JH7110_TIMER_INT_DIS,
-+};
-+
-+enum jh7110_timer_enable {
-+      JH7110_TIMER_DIS,
-+      JH7110_TIMER_ENA,
-+};
-+
-+static inline struct jh7110_clkevt *to_jh7110_clkevt(struct clock_event_device *evt)
-+{
-+      return container_of(evt, struct jh7110_clkevt, evt);
-+}
-+
-+/*
-+ * BIT(0): Read value represent channel int 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 jh7110_timer_int_clear(struct jh7110_clkevt *clkevt)
-+{
-+      u32 value;
-+      int ret;
-+
-+      /* Waiting interrupt can be cleared */
-+      ret = readl_poll_timeout_atomic(clkevt->base + JH7110_TIMER_INT_CLR, value,
-+                                      !(value & JH7110_TIMER_INT_CLR_AVA_MASK),
-+                                      JH7110_DELAY_US, JH7110_TIMEOUT_US);
-+      if (!ret)
-+              writel(JH7110_TIMER_INT_CLR_ENA, clkevt->base + JH7110_TIMER_INT_CLR);
-+
-+      return ret;
-+}
-+
-+static int jh7110_timer_start(struct jh7110_clkevt *clkevt)
-+{
-+      int ret;
-+
-+      /* Disable and clear interrupt first */
-+      writel(JH7110_TIMER_INT_DIS, clkevt->base + JH7110_TIMER_INT_MASK);
-+      ret = jh7110_timer_int_clear(clkevt);
-+      if (ret)
-+              return ret;
-+
-+      writel(JH7110_TIMER_INT_ENA, clkevt->base + JH7110_TIMER_INT_MASK);
-+      writel(JH7110_TIMER_ENA, clkevt->base + JH7110_TIMER_ENABLE);
-+
-+      return 0;
-+}
-+
-+static int jh7110_timer_shutdown(struct clock_event_device *evt)
-+{
-+      struct jh7110_clkevt *clkevt = to_jh7110_clkevt(evt);
-+
-+      writel(JH7110_TIMER_DIS, clkevt->base + JH7110_TIMER_ENABLE);
-+      return jh7110_timer_int_clear(clkevt);
-+}
-+
-+static void jh7110_timer_suspend(struct clock_event_device *evt)
-+{
-+      struct jh7110_clkevt *clkevt = to_jh7110_clkevt(evt);
-+
-+      clkevt->reload_val = readl(clkevt->base + JH7110_TIMER_LOAD);
-+      jh7110_timer_shutdown(evt);
-+}
-+
-+static void jh7110_timer_resume(struct clock_event_device *evt)
-+{
-+      struct jh7110_clkevt *clkevt = to_jh7110_clkevt(evt);
-+
-+      writel(clkevt->reload_val, clkevt->base + JH7110_TIMER_LOAD);
-+      writel(JH7110_TIMER_RELOAD_VALUE, clkevt->base + JH7110_TIMER_RELOAD);
-+      jh7110_timer_start(clkevt);
-+}
-+
-+static int jh7110_timer_tick_resume(struct clock_event_device *evt)
-+{
-+      jh7110_timer_resume(evt);
-+
-+      return 0;
-+}
-+
-+/* IRQ handler for the timer */
-+static irqreturn_t jh7110_timer_interrupt(int irq, void *priv)
-+{
-+      struct clock_event_device *evt = (struct clock_event_device *)priv;
-+      struct jh7110_clkevt *clkevt = to_jh7110_clkevt(evt);
-+
-+      if (jh7110_timer_int_clear(clkevt))
-+              return IRQ_NONE;
-+
-+      if (evt->event_handler)
-+              evt->event_handler(evt);
-+
-+      return IRQ_HANDLED;
-+}
-+
-+static int jh7110_timer_set_periodic(struct clock_event_device *evt)
-+{
-+      struct jh7110_clkevt *clkevt = to_jh7110_clkevt(evt);
-+      u32 periodic = DIV_ROUND_CLOSEST(clkevt->rate, HZ);
-+
-+      writel(JH7110_TIMER_MODE_CONTIN, clkevt->base + JH7110_TIMER_CTL);
-+      writel(periodic, clkevt->base + JH7110_TIMER_LOAD);
-+
-+      return jh7110_timer_start(clkevt);
-+}
-+
-+static int jh7110_timer_set_oneshot(struct clock_event_device *evt)
-+{
-+      struct jh7110_clkevt *clkevt = to_jh7110_clkevt(evt);
-+
-+      writel(JH7110_TIMER_MODE_SINGLE, clkevt->base + JH7110_TIMER_CTL);
-+      writel(JH7110_TIMER_MAX_TICKS, clkevt->base + JH7110_TIMER_LOAD);
-+
-+      return jh7110_timer_start(clkevt);
-+}
-+
-+static int jh7110_timer_set_next_event(unsigned long next,
-+                                     struct clock_event_device *evt)
-+{
-+      struct jh7110_clkevt *clkevt = to_jh7110_clkevt(evt);
-+
-+      writel(JH7110_TIMER_MODE_SINGLE, clkevt->base + JH7110_TIMER_CTL);
-+      writel(next, clkevt->base + JH7110_TIMER_LOAD);
-+
-+      return jh7110_timer_start(clkevt);
-+}
-+
-+static void jh7110_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 = jh7110_timer_shutdown;
-+      evt->set_state_periodic = jh7110_timer_set_periodic;
-+      evt->set_state_oneshot = jh7110_timer_set_oneshot;
-+      evt->set_state_oneshot_stopped = jh7110_timer_shutdown;
-+      evt->tick_resume = jh7110_timer_tick_resume;
-+      evt->set_next_event = jh7110_timer_set_next_event;
-+      evt->suspend = jh7110_timer_suspend;
-+      evt->resume = jh7110_timer_resume;
-+      evt->rating = JH7110_CLOCKEVENT_RATING;
-+}
-+
-+static u64 jh7110_timer_clocksource_read(struct clocksource *cs)
-+{
-+      struct jh7110_clkevt *clkevt = container_of(cs, struct jh7110_clkevt, cs);
-+
-+      return (u64)readl(clkevt->base + JH7110_TIMER_VALUE);
-+}
-+
-+static int jh7110_clocksource_init(struct jh7110_clkevt *clkevt)
-+{
-+      int ret;
-+
-+      clkevt->cs.name = clkevt->name;
-+      clkevt->cs.rating = JH7110_CLOCK_SOURCE_RATING;
-+      clkevt->cs.read = jh7110_timer_clocksource_read;
-+      clkevt->cs.mask = CLOCKSOURCE_MASK(JH7110_VALID_BITS);
-+      clkevt->cs.flags = CLOCK_SOURCE_IS_CONTINUOUS;
-+
-+      ret = clocksource_register_hz(&clkevt->cs, clkevt->rate);
-+      if (ret)
-+              return ret;
-+
-+      clkevt->cs_is_valid = true; /* clocksource register done */
-+      writel(JH7110_TIMER_MODE_CONTIN, clkevt->base + JH7110_TIMER_CTL);
-+      writel(JH7110_TIMER_MAX_TICKS, clkevt->base + JH7110_TIMER_LOAD);
-+
-+      return jh7110_timer_start(clkevt);
-+}
-+
-+static void jh7110_clockevents_register(struct jh7110_clkevt *clkevt)
-+{
-+      clkevt->rate = clk_get_rate(clkevt->clk);
-+
-+      jh7110_set_clockevent(&clkevt->evt);
-+      clkevt->evt.name = clkevt->name;
-+      clkevt->evt.cpumask = cpu_possible_mask;
-+
-+      clockevents_config_and_register(&clkevt->evt, clkevt->rate,
-+                                      JH7110_TIMER_MIN_TICKS, JH7110_TIMER_MAX_TICKS);
-+}
-+
-+static void jh7110_timer_release(void *data)
-+{
-+      struct jh7110_timer_priv *priv = data;
-+      int i;
-+
-+      for (i = 0; i < JH7110_TIMER_CH_MAX; i++) {
-+              /* Disable each channel of timer */
-+              if (priv->clkevt[i].base)
-+                      writel(JH7110_TIMER_DIS, priv->clkevt[i].base + JH7110_TIMER_ENABLE);
-+
-+              /* Avoid no initialization in the loop of the probe */
-+              if (!IS_ERR_OR_NULL(priv->clkevt[i].rst))
-+                      reset_control_assert(priv->clkevt[i].rst);
-+
-+              if (priv->clkevt[i].cs_is_valid)
-+                      clocksource_unregister(&priv->clkevt[i].cs);
-+      }
-+
-+      reset_control_assert(priv->prst);
-+}
-+
-+static int jh7110_timer_probe(struct platform_device *pdev)
-+{
-+      struct jh7110_timer_priv *priv;
-+      struct jh7110_clkevt *clkevt;
-+      char name[sizeof("chX")];
-+      int ch;
-+      int ret;
-+      void __iomem *base;
-+
-+      priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL);
-+      if (!priv)
-+              return -ENOMEM;
-+
-+      base = devm_platform_ioremap_resource(pdev, 0);
-+      if (IS_ERR(base))
-+              return dev_err_probe(&pdev->dev, PTR_ERR(base),
-+                                   "failed to map registers\n");
-+
-+      priv->prst = devm_reset_control_get_exclusive(&pdev->dev, "apb");
-+      if (IS_ERR(priv->prst))
-+              return dev_err_probe(&pdev->dev, PTR_ERR(priv->prst),
-+                                   "failed to get apb reset\n");
-+
-+      priv->pclk = devm_clk_get_enabled(&pdev->dev, "apb");
-+      if (IS_ERR(priv->pclk))
-+              return dev_err_probe(&pdev->dev, PTR_ERR(priv->pclk),
-+                                   "failed to get & enable apb clock\n");
-+
-+      ret = reset_control_deassert(priv->prst);
-+      if (ret)
-+              return dev_err_probe(&pdev->dev, ret, "failed to deassert apb reset\n");
-+
-+      ret = devm_add_action_or_reset(&pdev->dev, jh7110_timer_release, priv);
-+      if (ret)
-+              return ret;
-+
-+      for (ch = 0; ch < JH7110_TIMER_CH_MAX; ch++) {
-+              clkevt = &priv->clkevt[ch];
-+              snprintf(name, sizeof(name), "ch%d", ch);
-+
-+              clkevt->base = base + JH7110_TIMER_CH_BASE(ch);
-+              /* Ensure timer is disabled */
-+              writel(JH7110_TIMER_DIS, clkevt->base + JH7110_TIMER_ENABLE);
-+
-+              clkevt->rst = devm_reset_control_get_exclusive(&pdev->dev, name);
-+              if (IS_ERR(clkevt->rst))
-+                      return PTR_ERR(clkevt->rst);
-+
-+              clkevt->clk = devm_clk_get_enabled(&pdev->dev, name);
-+              if (IS_ERR(clkevt->clk))
-+                      return PTR_ERR(clkevt->clk);
-+
-+              ret = reset_control_deassert(clkevt->rst);
-+              if (ret)
-+                      return ret;
-+
-+              clkevt->evt.irq = platform_get_irq(pdev, ch);
-+              if (clkevt->evt.irq < 0)
-+                      return clkevt->evt.irq;
-+
-+              snprintf(clkevt->name, sizeof(clkevt->name), "jh7110-timer.ch%d", ch);
-+              jh7110_clockevents_register(clkevt);
-+
-+              ret = devm_request_irq(&pdev->dev, clkevt->evt.irq, jh7110_timer_interrupt,
-+                                     IRQF_TIMER | IRQF_IRQPOLL,
-+                                     clkevt->name, &clkevt->evt);
-+              if (ret)
-+                      return ret;
-+
-+              ret = jh7110_clocksource_init(clkevt);
-+              if (ret)
-+                      return ret;
-+      }
-+
-+      return 0;
-+}
-+
-+static const struct of_device_id jh7110_timer_match[] = {
-+      { .compatible = "starfive,jh7110-timer", },
-+      { /* sentinel */ }
-+};
-+MODULE_DEVICE_TABLE(of, jh7110_timer_match);
-+
-+static struct platform_driver jh7110_timer_driver = {
-+      .probe = jh7110_timer_probe,
-+      .driver = {
-+              .name = "jh7110-timer",
-+              .of_match_table = jh7110_timer_match,
-+      },
-+};
-+module_platform_driver(jh7110_timer_driver);
-+
-+MODULE_AUTHOR("Xingyu Wu <xingyu.wu@starfivetech.com>");
-+MODULE_DESCRIPTION("StarFive JH7110 timer driver");
-+MODULE_LICENSE("GPL");
diff --git a/target/linux/starfive/patches-6.6/0004-dt-bindings-mmc-starfive-Remove-properties-from-requ.patch b/target/linux/starfive/patches-6.6/0004-dt-bindings-mmc-starfive-Remove-properties-from-requ.patch
deleted file mode 100644 (file)
index 9c1e78b..0000000
+++ /dev/null
@@ -1,34 +0,0 @@
-From b513eb2cabee212ba1a23839f18c0026a21e653e Mon Sep 17 00:00:00 2001
-From: William Qiu <william.qiu@starfivetech.com>
-Date: Fri, 22 Sep 2023 14:28:32 +0800
-Subject: [PATCH 004/116] dt-bindings: mmc: starfive: Remove properties from
- required
-
-Due to the change of tuning implementation, it's no longer necessary to
-use the "starfive,sysreg" property in dts, so remove it from required.
-
-Signed-off-by: William Qiu <william.qiu@starfivetech.com>
-Acked-by: Conor Dooley <conor.dooley@microchip.com>
-Reviewed-by: Emil Renner Berthing <emil.renner.berthing@canonical.com>
-Link: https://lore.kernel.org/r/20230922062834.39212-2-william.qiu@starfivetech.com
-Signed-off-by: Ulf Hansson <ulf.hansson@linaro.org>
----
- Documentation/devicetree/bindings/mmc/starfive,jh7110-mmc.yaml | 2 --
- 1 file changed, 2 deletions(-)
-
---- a/Documentation/devicetree/bindings/mmc/starfive,jh7110-mmc.yaml
-+++ b/Documentation/devicetree/bindings/mmc/starfive,jh7110-mmc.yaml
-@@ -55,7 +55,6 @@ required:
-   - clocks
-   - clock-names
-   - interrupts
--  - starfive,sysreg
- unevaluatedProperties: false
-@@ -73,5 +72,4 @@ examples:
-         fifo-depth = <32>;
-         fifo-watermark-aligned;
-         data-addr = <0>;
--        starfive,sysreg = <&sys_syscon 0x14 0x1a 0x7c000000>;
-     };
diff --git a/target/linux/starfive/patches-6.6/0005-mmc-starfive-Change-tuning-implementation.patch b/target/linux/starfive/patches-6.6/0005-mmc-starfive-Change-tuning-implementation.patch
deleted file mode 100644 (file)
index b8ea96f..0000000
+++ /dev/null
@@ -1,199 +0,0 @@
-From 3ae8cec8fd28e18847edb67dfea04718c2f3369f Mon Sep 17 00:00:00 2001
-From: William Qiu <william.qiu@starfivetech.com>
-Date: Fri, 22 Sep 2023 14:28:33 +0800
-Subject: [PATCH 005/116] mmc: starfive: Change tuning implementation
-
-Before, we used syscon to achieve tuning, but the actual measurement
-showed little effect, so the tuning implementation was modified here,
-and it was realized by reading and writing the UHS_REG_EXT register.
-
-Signed-off-by: William Qiu <william.qiu@starfivetech.com>
-Reviewed-by: Emil Renner Berthing <emil.renner.berthing@canonical.com>
-Link: https://lore.kernel.org/r/20230922062834.39212-3-william.qiu@starfivetech.com
-Signed-off-by: Ulf Hansson <ulf.hansson@linaro.org>
----
- drivers/mmc/host/dw_mmc-starfive.c | 137 +++++++++--------------------
- 1 file changed, 40 insertions(+), 97 deletions(-)
-
---- a/drivers/mmc/host/dw_mmc-starfive.c
-+++ b/drivers/mmc/host/dw_mmc-starfive.c
-@@ -5,6 +5,7 @@
-  * Copyright (c) 2022 StarFive Technology Co., Ltd.
-  */
-+#include <linux/bitfield.h>
- #include <linux/clk.h>
- #include <linux/delay.h>
- #include <linux/mfd/syscon.h>
-@@ -20,13 +21,7 @@
- #define ALL_INT_CLR           0x1ffff
- #define MAX_DELAY_CHAIN               32
--struct starfive_priv {
--      struct device *dev;
--      struct regmap *reg_syscon;
--      u32 syscon_offset;
--      u32 syscon_shift;
--      u32 syscon_mask;
--};
-+#define STARFIVE_SMPL_PHASE     GENMASK(20, 16)
- static void dw_mci_starfive_set_ios(struct dw_mci *host, struct mmc_ios *ios)
- {
-@@ -44,117 +39,65 @@ static void dw_mci_starfive_set_ios(stru
-       }
- }
-+static void dw_mci_starfive_set_sample_phase(struct dw_mci *host, u32 smpl_phase)
-+{
-+      /* change driver phase and sample phase */
-+      u32 reg_value = mci_readl(host, UHS_REG_EXT);
-+
-+      /* In UHS_REG_EXT, only 5 bits valid in DRV_PHASE and SMPL_PHASE */
-+      reg_value &= ~STARFIVE_SMPL_PHASE;
-+      reg_value |= FIELD_PREP(STARFIVE_SMPL_PHASE, smpl_phase);
-+      mci_writel(host, UHS_REG_EXT, reg_value);
-+
-+      /* We should delay 1ms wait for timing setting finished. */
-+      mdelay(1);
-+}
-+
- static int dw_mci_starfive_execute_tuning(struct dw_mci_slot *slot,
-                                            u32 opcode)
- {
-       static const int grade  = MAX_DELAY_CHAIN;
-       struct dw_mci *host = slot->host;
--      struct starfive_priv *priv = host->priv;
--      int rise_point = -1, fall_point = -1;
--      int err, prev_err = 0;
--      int i;
--      bool found = 0;
--      u32 regval;
--
--      /*
--       * Use grade as the max delay chain, and use the rise_point and
--       * fall_point to ensure the best sampling point of a data input
--       * signals.
--       */
--      for (i = 0; i < grade; i++) {
--              regval = i << priv->syscon_shift;
--              err = regmap_update_bits(priv->reg_syscon, priv->syscon_offset,
--                                              priv->syscon_mask, regval);
--              if (err)
--                      return err;
--              mci_writel(host, RINTSTS, ALL_INT_CLR);
--
--              err = mmc_send_tuning(slot->mmc, opcode, NULL);
--              if (!err)
--                      found = 1;
--
--              if (i > 0) {
--                      if (err && !prev_err)
--                              fall_point = i - 1;
--                      if (!err && prev_err)
--                              rise_point = i;
--              }
-+      int smpl_phase, smpl_raise = -1, smpl_fall = -1;
-+      int ret;
--              if (rise_point != -1 && fall_point != -1)
--                      goto tuning_out;
-+      for (smpl_phase = 0; smpl_phase < grade; smpl_phase++) {
-+              dw_mci_starfive_set_sample_phase(host, smpl_phase);
-+              mci_writel(host, RINTSTS, ALL_INT_CLR);
--              prev_err = err;
--              err = 0;
--      }
-+              ret = mmc_send_tuning(slot->mmc, opcode, NULL);
--tuning_out:
--      if (found) {
--              if (rise_point == -1)
--                      rise_point = 0;
--              if (fall_point == -1)
--                      fall_point = grade - 1;
--              if (fall_point < rise_point) {
--                      if ((rise_point + fall_point) >
--                          (grade - 1))
--                              i = fall_point / 2;
--                      else
--                              i = (rise_point + grade - 1) / 2;
--              } else {
--                      i = (rise_point + fall_point) / 2;
-+              if (!ret && smpl_raise < 0) {
-+                      smpl_raise = smpl_phase;
-+              } else if (ret && smpl_raise >= 0) {
-+                      smpl_fall = smpl_phase - 1;
-+                      break;
-               }
--
--              regval = i << priv->syscon_shift;
--              err = regmap_update_bits(priv->reg_syscon, priv->syscon_offset,
--                                              priv->syscon_mask, regval);
--              if (err)
--                      return err;
--              mci_writel(host, RINTSTS, ALL_INT_CLR);
--
--              dev_info(host->dev, "Found valid delay chain! use it [delay=%d]\n", i);
--      } else {
--              dev_err(host->dev, "No valid delay chain! use default\n");
--              err = -EINVAL;
-       }
--      mci_writel(host, RINTSTS, ALL_INT_CLR);
--      return err;
--}
--
--static int dw_mci_starfive_parse_dt(struct dw_mci *host)
--{
--      struct of_phandle_args args;
--      struct starfive_priv *priv;
--      int ret;
-+      if (smpl_phase >= grade)
-+              smpl_fall = grade - 1;
--      priv = devm_kzalloc(host->dev, sizeof(*priv), GFP_KERNEL);
--      if (!priv)
--              return -ENOMEM;
--
--      ret = of_parse_phandle_with_fixed_args(host->dev->of_node,
--                                              "starfive,sysreg", 3, 0, &args);
--      if (ret) {
--              dev_err(host->dev, "Failed to parse starfive,sysreg\n");
--              return -EINVAL;
-+      if (smpl_raise < 0) {
-+              smpl_phase = 0;
-+              dev_err(host->dev, "No valid delay chain! use default\n");
-+              ret = -EINVAL;
-+              goto out;
-       }
--      priv->reg_syscon = syscon_node_to_regmap(args.np);
--      of_node_put(args.np);
--      if (IS_ERR(priv->reg_syscon))
--              return PTR_ERR(priv->reg_syscon);
--
--      priv->syscon_offset = args.args[0];
--      priv->syscon_shift  = args.args[1];
--      priv->syscon_mask   = args.args[2];
--
--      host->priv = priv;
-+      smpl_phase = (smpl_raise + smpl_fall) / 2;
-+      dev_dbg(host->dev, "Found valid delay chain! use it [delay=%d]\n", smpl_phase);
-+      ret = 0;
--      return 0;
-+out:
-+      dw_mci_starfive_set_sample_phase(host, smpl_phase);
-+      mci_writel(host, RINTSTS, ALL_INT_CLR);
-+      return ret;
- }
- static const struct dw_mci_drv_data starfive_data = {
-       .common_caps            = MMC_CAP_CMD23,
-       .set_ios                = dw_mci_starfive_set_ios,
--      .parse_dt               = dw_mci_starfive_parse_dt,
-       .execute_tuning         = dw_mci_starfive_execute_tuning,
- };
diff --git a/target/linux/starfive/patches-6.6/0006-dt-bindings-pwm-Add-bindings-for-OpenCores-PWM-Contr.patch b/target/linux/starfive/patches-6.6/0006-dt-bindings-pwm-Add-bindings-for-OpenCores-PWM-Contr.patch
deleted file mode 100644 (file)
index aafbee5..0000000
+++ /dev/null
@@ -1,79 +0,0 @@
-From e366df2ff64e9f93a5b35eea6a198b005d5a0911 Mon Sep 17 00:00:00 2001
-From: William Qiu <william.qiu@starfivetech.com>
-Date: Fri, 22 Dec 2023 17:45:45 +0800
-Subject: [PATCH 006/116] dt-bindings: pwm: Add bindings for OpenCores PWM
- Controller
-MIME-Version: 1.0
-Content-Type: text/plain; charset=UTF-8
-Content-Transfer-Encoding: 8bit
-
-Add bindings for OpenCores PWM Controller.
-
-Signed-off-by: William Qiu <william.qiu@starfivetech.com>
-Reviewed-by: Hal Feng <hal.feng@starfivetech.com>
-Reviewed-by: Conor Dooley <conor.dooley@microchip.com>
-Reviewed-by: Uwe Kleine-König <u.kleine-koenig@pengutronix.de>
-Acked-by: Uwe Kleine-König <u.kleine-koenig@pengutronix.de>
----
- .../bindings/pwm/opencores,pwm.yaml           | 55 +++++++++++++++++++
- 1 file changed, 55 insertions(+)
- create mode 100644 Documentation/devicetree/bindings/pwm/opencores,pwm.yaml
-
---- /dev/null
-+++ b/Documentation/devicetree/bindings/pwm/opencores,pwm.yaml
-@@ -0,0 +1,55 @@
-+# SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause
-+%YAML 1.2
-+---
-+$id: http://devicetree.org/schemas/pwm/opencores,pwm.yaml#
-+$schema: http://devicetree.org/meta-schemas/core.yaml#
-+
-+title: OpenCores PWM controller
-+
-+maintainers:
-+  - William Qiu <william.qiu@starfivetech.com>
-+
-+description:
-+  The OpenCores PTC ip core contains a PWM controller. When operating in PWM
-+  mode, the PTC core generates binary signal with user-programmable low and
-+  high periods. All PTC counters and registers are 32-bit.
-+
-+allOf:
-+  - $ref: pwm.yaml#
-+
-+properties:
-+  compatible:
-+    items:
-+      - enum:
-+          - starfive,jh7100-pwm
-+          - starfive,jh7110-pwm
-+      - const: opencores,pwm-v1
-+
-+  reg:
-+    maxItems: 1
-+
-+  clocks:
-+    maxItems: 1
-+
-+  resets:
-+    maxItems: 1
-+
-+  "#pwm-cells":
-+    const: 3
-+
-+required:
-+  - compatible
-+  - reg
-+  - clocks
-+
-+additionalProperties: false
-+
-+examples:
-+  - |
-+    pwm@12490000 {
-+        compatible = "starfive,jh7110-pwm", "opencores,pwm-v1";
-+        reg = <0x12490000 0x10000>;
-+        clocks = <&clkgen 181>;
-+        resets = <&rstgen 109>;
-+        #pwm-cells = <3>;
-+    };
diff --git a/target/linux/starfive/patches-6.6/0007-pwm-opencores-Add-PWM-driver-support.patch b/target/linux/starfive/patches-6.6/0007-pwm-opencores-Add-PWM-driver-support.patch
deleted file mode 100644 (file)
index 27e510d..0000000
+++ /dev/null
@@ -1,285 +0,0 @@
-From 644bfe581dde9b762460a4916da4d71c148be06e Mon Sep 17 00:00:00 2001
-From: William Qiu <william.qiu@starfivetech.com>
-Date: Fri, 22 Dec 2023 17:45:46 +0800
-Subject: [PATCH 007/116] pwm: opencores: Add PWM driver support
-
-Add driver for OpenCores PWM Controller. And add compatibility code
-which based on StarFive SoC.
-
-Co-developed-by: Hal Feng <hal.feng@starfivetech.com>
-Signed-off-by: Hal Feng <hal.feng@starfivetech.com>
-Signed-off-by: William Qiu <william.qiu@starfivetech.com>
----
- drivers/pwm/Kconfig      |  12 ++
- drivers/pwm/Makefile     |   1 +
- drivers/pwm/pwm-ocores.c | 233 +++++++++++++++++++++++++++++++++++++++
- 3 files changed, 246 insertions(+)
- create mode 100644 drivers/pwm/pwm-ocores.c
-
---- a/drivers/pwm/Kconfig
-+++ b/drivers/pwm/Kconfig
-@@ -434,6 +434,18 @@ config PWM_NTXEC
-         controller found in certain e-book readers designed by the original
-         design manufacturer Netronix.
-+config PWM_OCORES
-+      tristate "OpenCores PWM support"
-+      depends on HAS_IOMEM && OF
-+      depends on COMMON_CLK
-+      depends on ARCH_STARFIVE || COMPILE_TEST
-+      help
-+        If you say yes to this option, support will be included for the
-+        OpenCores PWM. For details see https://opencores.org/projects/ptc.
-+
-+        To compile this driver as a module, choose M here: the module
-+        will be called pwm-ocores.
-+
- config PWM_OMAP_DMTIMER
-       tristate "OMAP Dual-Mode Timer PWM support"
-       depends on OF
---- a/drivers/pwm/Makefile
-+++ b/drivers/pwm/Makefile
-@@ -39,6 +39,7 @@ obj-$(CONFIG_PWM_MICROCHIP_CORE)     += pwm-
- obj-$(CONFIG_PWM_MTK_DISP)    += pwm-mtk-disp.o
- obj-$(CONFIG_PWM_MXS)         += pwm-mxs.o
- obj-$(CONFIG_PWM_NTXEC)               += pwm-ntxec.o
-+obj-$(CONFIG_PWM_OCORES)      += pwm-ocores.o
- obj-$(CONFIG_PWM_OMAP_DMTIMER)        += pwm-omap-dmtimer.o
- obj-$(CONFIG_PWM_PCA9685)     += pwm-pca9685.o
- obj-$(CONFIG_PWM_PXA)         += pwm-pxa.o
---- /dev/null
-+++ b/drivers/pwm/pwm-ocores.c
-@@ -0,0 +1,233 @@
-+// SPDX-License-Identifier: GPL-2.0
-+/*
-+ * OpenCores PWM Driver
-+ *
-+ * https://opencores.org/projects/ptc
-+ *
-+ * Copyright (C) 2018-2023 StarFive Technology Co., Ltd.
-+ *
-+ * Limitations:
-+ * - The hardware only do inverted polarity.
-+ * - The hardware minimum period / duty_cycle is (1 / pwm_apb clock frequency) ns.
-+ * - The hardware maximum period / duty_cycle is (U32_MAX / pwm_apb clock frequency) ns.
-+ */
-+
-+#include <linux/clk.h>
-+#include <linux/io.h>
-+#include <linux/module.h>
-+#include <linux/of.h>
-+#include <linux/of_device.h>
-+#include <linux/platform_device.h>
-+#include <linux/pwm.h>
-+#include <linux/reset.h>
-+#include <linux/slab.h>
-+
-+/* OCPWM_CTRL register bits*/
-+#define REG_OCPWM_EN      BIT(0)
-+#define REG_OCPWM_ECLK    BIT(1)
-+#define REG_OCPWM_NEC     BIT(2)
-+#define REG_OCPWM_OE      BIT(3)
-+#define REG_OCPWM_SIGNLE  BIT(4)
-+#define REG_OCPWM_INTE    BIT(5)
-+#define REG_OCPWM_INT     BIT(6)
-+#define REG_OCPWM_CNTRRST BIT(7)
-+#define REG_OCPWM_CAPTE   BIT(8)
-+
-+struct ocores_pwm_device {
-+      struct pwm_chip chip;
-+      struct clk *clk;
-+      struct reset_control *rst;
-+      const struct ocores_pwm_data *data;
-+      void __iomem *regs;
-+      u32 clk_rate; /* PWM APB clock frequency */
-+};
-+
-+struct ocores_pwm_data {
-+      void __iomem *(*get_ch_base)(void __iomem *base, unsigned int channel);
-+};
-+
-+static inline u32 ocores_readl(struct ocores_pwm_device *ddata,
-+                             unsigned int channel,
-+                             unsigned int offset)
-+{
-+      void __iomem *base = ddata->data->get_ch_base ?
-+                           ddata->data->get_ch_base(ddata->regs, channel) : ddata->regs;
-+
-+      return readl(base + offset);
-+}
-+
-+static inline void ocores_writel(struct ocores_pwm_device *ddata,
-+                               unsigned int channel,
-+                               unsigned int offset, u32 val)
-+{
-+      void __iomem *base = ddata->data->get_ch_base ?
-+                           ddata->data->get_ch_base(ddata->regs, channel) : ddata->regs;
-+
-+      writel(val, base + offset);
-+}
-+
-+static inline struct ocores_pwm_device *chip_to_ocores(struct pwm_chip *chip)
-+{
-+      return container_of(chip, struct ocores_pwm_device, chip);
-+}
-+
-+static void __iomem *starfive_jh71x0_get_ch_base(void __iomem *base,
-+                                               unsigned int channel)
-+{
-+      unsigned int offset = (channel > 3 ? 1 << 15 : 0) + (channel & 3) * 0x10;
-+
-+      return base + offset;
-+}
-+
-+static int ocores_pwm_get_state(struct pwm_chip *chip,
-+                              struct pwm_device *pwm,
-+                              struct pwm_state *state)
-+{
-+      struct ocores_pwm_device *ddata = chip_to_ocores(chip);
-+      u32 period_data, duty_data, ctrl_data;
-+
-+      period_data = ocores_readl(ddata, pwm->hwpwm, 0x8);
-+      duty_data = ocores_readl(ddata, pwm->hwpwm, 0x4);
-+      ctrl_data = ocores_readl(ddata, pwm->hwpwm, 0xC);
-+
-+      state->period = DIV_ROUND_UP_ULL((u64)period_data * NSEC_PER_SEC, ddata->clk_rate);
-+      state->duty_cycle = DIV_ROUND_UP_ULL((u64)duty_data * NSEC_PER_SEC, ddata->clk_rate);
-+      state->polarity = PWM_POLARITY_INVERSED;
-+      state->enabled = (ctrl_data & REG_OCPWM_EN) ? true : false;
-+
-+      return 0;
-+}
-+
-+static int ocores_pwm_apply(struct pwm_chip *chip,
-+                          struct pwm_device *pwm,
-+                          const struct pwm_state *state)
-+{
-+      struct ocores_pwm_device *ddata = chip_to_ocores(chip);
-+      u32 ctrl_data = 0;
-+      u64 period_data, duty_data;
-+
-+      if (state->polarity != PWM_POLARITY_INVERSED)
-+              return -EINVAL;
-+
-+      ctrl_data = ocores_readl(ddata, pwm->hwpwm, 0xC);
-+      ocores_writel(ddata, pwm->hwpwm, 0xC, 0);
-+
-+      period_data = DIV_ROUND_DOWN_ULL(state->period * ddata->clk_rate, NSEC_PER_SEC);
-+      if (period_data <= U32_MAX)
-+              ocores_writel(ddata, pwm->hwpwm, 0x8, (u32)period_data);
-+      else
-+              return -EINVAL;
-+
-+      duty_data = DIV_ROUND_DOWN_ULL(state->duty_cycle * ddata->clk_rate, NSEC_PER_SEC);
-+      if (duty_data <= U32_MAX)
-+              ocores_writel(ddata, pwm->hwpwm, 0x4, (u32)duty_data);
-+      else
-+              return -EINVAL;
-+
-+      ocores_writel(ddata, pwm->hwpwm, 0xC, 0);
-+
-+      if (state->enabled) {
-+              ctrl_data = ocores_readl(ddata, pwm->hwpwm, 0xC);
-+              ocores_writel(ddata, pwm->hwpwm, 0xC, ctrl_data | REG_OCPWM_EN | REG_OCPWM_OE);
-+      }
-+
-+      return 0;
-+}
-+
-+static const struct pwm_ops ocores_pwm_ops = {
-+      .get_state      = ocores_pwm_get_state,
-+      .apply          = ocores_pwm_apply,
-+};
-+
-+static const struct ocores_pwm_data jh7100_pwm_data = {
-+      .get_ch_base = starfive_jh71x0_get_ch_base,
-+};
-+
-+static const struct ocores_pwm_data jh7110_pwm_data = {
-+      .get_ch_base = starfive_jh71x0_get_ch_base,
-+};
-+
-+static const struct of_device_id ocores_pwm_of_match[] = {
-+      { .compatible = "opencores,pwm-v1" },
-+      { .compatible = "starfive,jh7100-pwm", .data = &jh7100_pwm_data},
-+      { .compatible = "starfive,jh7110-pwm", .data = &jh7110_pwm_data},
-+      { /* sentinel */ }
-+};
-+MODULE_DEVICE_TABLE(of, ocores_pwm_of_match);
-+
-+static void ocores_reset_control_assert(void *data)
-+{
-+      reset_control_assert(data);
-+}
-+
-+static int ocores_pwm_probe(struct platform_device *pdev)
-+{
-+      const struct of_device_id *id;
-+      struct device *dev = &pdev->dev;
-+      struct ocores_pwm_device *ddata;
-+      struct pwm_chip *chip;
-+      int ret;
-+
-+      id = of_match_device(ocores_pwm_of_match, dev);
-+      if (!id)
-+              return -EINVAL;
-+
-+      ddata = devm_kzalloc(dev, sizeof(*ddata), GFP_KERNEL);
-+      if (!ddata)
-+              return -ENOMEM;
-+
-+      ddata->data = id->data;
-+      chip = &ddata->chip;
-+      chip->dev = dev;
-+      chip->ops = &ocores_pwm_ops;
-+      chip->npwm = 8;
-+      chip->of_pwm_n_cells = 3;
-+
-+      ddata->regs = devm_platform_ioremap_resource(pdev, 0);
-+      if (IS_ERR(ddata->regs))
-+              return dev_err_probe(dev, PTR_ERR(ddata->regs),
-+                                   "Unable to map IO resources\n");
-+
-+      ddata->clk = devm_clk_get_enabled(dev, NULL);
-+      if (IS_ERR(ddata->clk))
-+              return dev_err_probe(dev, PTR_ERR(ddata->clk),
-+                                   "Unable to get pwm's clock\n");
-+
-+      ddata->rst = devm_reset_control_get_optional_exclusive(dev, NULL);
-+      if (IS_ERR(ddata->rst))
-+              return dev_err_probe(dev, PTR_ERR(ddata->rst),
-+                                   "Unable to get pwm's reset\n");
-+
-+      reset_control_deassert(ddata->rst);
-+
-+      ret = devm_add_action_or_reset(dev, ocores_reset_control_assert, ddata->rst);
-+      if (ret)
-+              return ret;
-+
-+      ddata->clk_rate = clk_get_rate(ddata->clk);
-+      if (ddata->clk_rate <= 0)
-+              return dev_err_probe(dev, ddata->clk_rate,
-+                                   "Unable to get clock's rate\n");
-+
-+      ret = devm_pwmchip_add(dev, chip);
-+      if (ret < 0)
-+              return dev_err_probe(dev, ret, "Could not register PWM chip\n");
-+
-+      platform_set_drvdata(pdev, ddata);
-+
-+      return ret;
-+}
-+
-+static struct platform_driver ocores_pwm_driver = {
-+      .probe = ocores_pwm_probe,
-+      .driver = {
-+              .name = "ocores-pwm",
-+              .of_match_table = ocores_pwm_of_match,
-+      },
-+};
-+module_platform_driver(ocores_pwm_driver);
-+
-+MODULE_AUTHOR("Jieqin Chen");
-+MODULE_AUTHOR("Hal Feng <hal.feng@starfivetech.com>");
-+MODULE_DESCRIPTION("OpenCores PWM PTC driver");
-+MODULE_LICENSE("GPL");
diff --git a/target/linux/starfive/patches-6.6/0008-crypto-starfive-remove-unnecessary-alignmask-for-aha.patch b/target/linux/starfive/patches-6.6/0008-crypto-starfive-remove-unnecessary-alignmask-for-aha.patch
deleted file mode 100644 (file)
index a6ede31..0000000
+++ /dev/null
@@ -1,117 +0,0 @@
-From 7d9521cad6474d45e9056176982e6da54d40bc19 Mon Sep 17 00:00:00 2001
-From: Eric Biggers <ebiggers@google.com>
-Date: Sun, 22 Oct 2023 01:10:42 -0700
-Subject: [PATCH 008/116] crypto: starfive - remove unnecessary alignmask for
- ahashes
-
-The crypto API's support for alignmasks for ahash algorithms is nearly
-useless, as its only effect is to cause the API to align the key and
-result buffers.  The drivers that happen to be specifying an alignmask
-for ahash rarely actually need it.  When they do, it's easily fixable,
-especially considering that these buffers cannot be used for DMA.
-
-In preparation for removing alignmask support from ahash, this patch
-makes the starfive driver no longer use it.  This driver did actually
-rely on it, but only for storing to the result buffer using int stores
-in starfive_hash_copy_hash().  This patch makes
-starfive_hash_copy_hash() use put_unaligned() instead.  (It really
-should use a specific endianness, but that's an existing bug.)
-
-Signed-off-by: Eric Biggers <ebiggers@google.com>
-Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
----
- drivers/crypto/starfive/jh7110-hash.c | 13 ++-----------
- 1 file changed, 2 insertions(+), 11 deletions(-)
-
---- a/drivers/crypto/starfive/jh7110-hash.c
-+++ b/drivers/crypto/starfive/jh7110-hash.c
-@@ -209,7 +209,8 @@ static int starfive_hash_copy_hash(struc
-       data = (u32 *)req->result;
-       for (count = 0; count < mlen; count++)
--              data[count] = readl(ctx->cryp->base + STARFIVE_HASH_SHARDR);
-+              put_unaligned(readl(ctx->cryp->base + STARFIVE_HASH_SHARDR),
-+                            &data[count]);
-       return 0;
- }
-@@ -628,7 +629,6 @@ static struct ahash_engine_alg algs_sha2
-                                                 CRYPTO_ALG_NEED_FALLBACK,
-                       .cra_blocksize          = SHA224_BLOCK_SIZE,
-                       .cra_ctxsize            = sizeof(struct starfive_cryp_ctx),
--                      .cra_alignmask          = 3,
-                       .cra_module             = THIS_MODULE,
-               }
-       },
-@@ -658,7 +658,6 @@ static struct ahash_engine_alg algs_sha2
-                                                 CRYPTO_ALG_NEED_FALLBACK,
-                       .cra_blocksize          = SHA224_BLOCK_SIZE,
-                       .cra_ctxsize            = sizeof(struct starfive_cryp_ctx),
--                      .cra_alignmask          = 3,
-                       .cra_module             = THIS_MODULE,
-               }
-       },
-@@ -687,7 +686,6 @@ static struct ahash_engine_alg algs_sha2
-                                                 CRYPTO_ALG_NEED_FALLBACK,
-                       .cra_blocksize          = SHA256_BLOCK_SIZE,
-                       .cra_ctxsize            = sizeof(struct starfive_cryp_ctx),
--                      .cra_alignmask          = 3,
-                       .cra_module             = THIS_MODULE,
-               }
-       },
-@@ -717,7 +715,6 @@ static struct ahash_engine_alg algs_sha2
-                                                 CRYPTO_ALG_NEED_FALLBACK,
-                       .cra_blocksize          = SHA256_BLOCK_SIZE,
-                       .cra_ctxsize            = sizeof(struct starfive_cryp_ctx),
--                      .cra_alignmask          = 3,
-                       .cra_module             = THIS_MODULE,
-               }
-       },
-@@ -746,7 +743,6 @@ static struct ahash_engine_alg algs_sha2
-                                                 CRYPTO_ALG_NEED_FALLBACK,
-                       .cra_blocksize          = SHA384_BLOCK_SIZE,
-                       .cra_ctxsize            = sizeof(struct starfive_cryp_ctx),
--                      .cra_alignmask          = 3,
-                       .cra_module             = THIS_MODULE,
-               }
-       },
-@@ -776,7 +772,6 @@ static struct ahash_engine_alg algs_sha2
-                                                 CRYPTO_ALG_NEED_FALLBACK,
-                       .cra_blocksize          = SHA384_BLOCK_SIZE,
-                       .cra_ctxsize            = sizeof(struct starfive_cryp_ctx),
--                      .cra_alignmask          = 3,
-                       .cra_module             = THIS_MODULE,
-               }
-       },
-@@ -805,7 +800,6 @@ static struct ahash_engine_alg algs_sha2
-                                                 CRYPTO_ALG_NEED_FALLBACK,
-                       .cra_blocksize          = SHA512_BLOCK_SIZE,
-                       .cra_ctxsize            = sizeof(struct starfive_cryp_ctx),
--                      .cra_alignmask          = 3,
-                       .cra_module             = THIS_MODULE,
-               }
-       },
-@@ -835,7 +829,6 @@ static struct ahash_engine_alg algs_sha2
-                                                 CRYPTO_ALG_NEED_FALLBACK,
-                       .cra_blocksize          = SHA512_BLOCK_SIZE,
-                       .cra_ctxsize            = sizeof(struct starfive_cryp_ctx),
--                      .cra_alignmask          = 3,
-                       .cra_module             = THIS_MODULE,
-               }
-       },
-@@ -864,7 +857,6 @@ static struct ahash_engine_alg algs_sha2
-                                                 CRYPTO_ALG_NEED_FALLBACK,
-                       .cra_blocksize          = SM3_BLOCK_SIZE,
-                       .cra_ctxsize            = sizeof(struct starfive_cryp_ctx),
--                      .cra_alignmask          = 3,
-                       .cra_module             = THIS_MODULE,
-               }
-       },
-@@ -894,7 +886,6 @@ static struct ahash_engine_alg algs_sha2
-                                                 CRYPTO_ALG_NEED_FALLBACK,
-                       .cra_blocksize          = SM3_BLOCK_SIZE,
-                       .cra_ctxsize            = sizeof(struct starfive_cryp_ctx),
--                      .cra_alignmask          = 3,
-                       .cra_module             = THIS_MODULE,
-               }
-       },
diff --git a/target/linux/starfive/patches-6.6/0009-crypto-starfive-Update-driver-dependencies.patch b/target/linux/starfive/patches-6.6/0009-crypto-starfive-Update-driver-dependencies.patch
deleted file mode 100644 (file)
index 145c013..0000000
+++ /dev/null
@@ -1,25 +0,0 @@
-From 52de0270ed6453727936b5a793dc367d75280e84 Mon Sep 17 00:00:00 2001
-From: Jia Jie Ho <jiajie.ho@starfivetech.com>
-Date: Wed, 15 Nov 2023 01:12:13 +0800
-Subject: [PATCH 009/116] crypto: starfive - Update driver dependencies
-
-Change AMBA_PL08X to required dependency as the hash ops depends on it
-for data transfer.
-
-Signed-off-by: Jia Jie Ho <jiajie.ho@starfivetech.com>
-Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
----
- drivers/crypto/starfive/Kconfig | 2 +-
- 1 file changed, 1 insertion(+), 1 deletion(-)
-
---- a/drivers/crypto/starfive/Kconfig
-+++ b/drivers/crypto/starfive/Kconfig
-@@ -4,7 +4,7 @@
- config CRYPTO_DEV_JH7110
-       tristate "StarFive JH7110 cryptographic engine driver"
--      depends on SOC_STARFIVE || AMBA_PL08X || COMPILE_TEST
-+      depends on (SOC_STARFIVE && AMBA_PL08X) || COMPILE_TEST
-       depends on HAS_DMA
-       select CRYPTO_ENGINE
-       select CRYPTO_HMAC
diff --git a/target/linux/starfive/patches-6.6/0010-crypto-starfive-RSA-poll-csr-for-done-status.patch b/target/linux/starfive/patches-6.6/0010-crypto-starfive-RSA-poll-csr-for-done-status.patch
deleted file mode 100644 (file)
index 5e353e3..0000000
+++ /dev/null
@@ -1,200 +0,0 @@
-From 68a1bbb99455fd5ea80b7e21ec726f369abc9572 Mon Sep 17 00:00:00 2001
-From: Jia Jie Ho <jiajie.ho@starfivetech.com>
-Date: Wed, 15 Nov 2023 01:12:14 +0800
-Subject: [PATCH 010/116] crypto: starfive - RSA poll csr for done status
-
-Hardware could not clear irq status without resetting the entire module.
-Driver receives irq immediately when mask bit is cleared causing
-intermittent errors in RSA calculations. Switch to use csr polling for
-done status instead.
-
-Signed-off-by: Jia Jie Ho <jiajie.ho@starfivetech.com>
-Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
----
- drivers/crypto/starfive/jh7110-cryp.c |  8 -----
- drivers/crypto/starfive/jh7110-cryp.h | 10 +++++-
- drivers/crypto/starfive/jh7110-rsa.c  | 49 +++++++--------------------
- 3 files changed, 22 insertions(+), 45 deletions(-)
-
---- a/drivers/crypto/starfive/jh7110-cryp.c
-+++ b/drivers/crypto/starfive/jh7110-cryp.c
-@@ -109,12 +109,6 @@ static irqreturn_t starfive_cryp_irq(int
-               tasklet_schedule(&cryp->hash_done);
-       }
--      if (status & STARFIVE_IE_FLAG_PKA_DONE) {
--              mask |= STARFIVE_IE_MASK_PKA_DONE;
--              writel(mask, cryp->base + STARFIVE_IE_MASK_OFFSET);
--              complete(&cryp->pka_done);
--      }
--
-       return IRQ_HANDLED;
- }
-@@ -159,8 +153,6 @@ static int starfive_cryp_probe(struct pl
-               return dev_err_probe(&pdev->dev, PTR_ERR(cryp->rst),
-                                    "Error getting hardware reset line\n");
--      init_completion(&cryp->pka_done);
--
-       irq = platform_get_irq(pdev, 0);
-       if (irq < 0)
-               return irq;
---- a/drivers/crypto/starfive/jh7110-cryp.h
-+++ b/drivers/crypto/starfive/jh7110-cryp.h
-@@ -126,6 +126,15 @@ union starfive_pka_cacr {
-       };
- };
-+union starfive_pka_casr {
-+      u32 v;
-+      struct {
-+#define STARFIVE_PKA_DONE                     BIT(0)
-+              u32 done                        :1;
-+              u32 rsvd_0                      :31;
-+      };
-+};
-+
- struct starfive_rsa_key {
-       u8      *n;
-       u8      *e;
-@@ -184,7 +193,6 @@ struct starfive_cryp_dev {
-       struct crypto_engine                    *engine;
-       struct tasklet_struct                   aes_done;
-       struct tasklet_struct                   hash_done;
--      struct completion                       pka_done;
-       size_t                                  assoclen;
-       size_t                                  total_in;
-       size_t                                  total_out;
---- a/drivers/crypto/starfive/jh7110-rsa.c
-+++ b/drivers/crypto/starfive/jh7110-rsa.c
-@@ -6,13 +6,7 @@
-  */
- #include <linux/crypto.h>
--#include <linux/delay.h>
--#include <linux/device.h>
--#include <linux/dma-direct.h>
--#include <linux/interrupt.h>
- #include <linux/iopoll.h>
--#include <linux/io.h>
--#include <linux/mod_devicetable.h>
- #include <crypto/akcipher.h>
- #include <crypto/algapi.h>
- #include <crypto/internal/akcipher.h>
-@@ -28,13 +22,13 @@
- #define STARFIVE_PKA_CAER_OFFSET      (STARFIVE_PKA_REGS_OFFSET + 0x108)
- #define STARFIVE_PKA_CANR_OFFSET      (STARFIVE_PKA_REGS_OFFSET + 0x208)
--// R^2 mod N and N0'
-+/* R ^ 2 mod N and N0' */
- #define CRYPTO_CMD_PRE                        0x0
--// A * R mod N   ==> A
-+/* A * R mod N   ==> A */
- #define CRYPTO_CMD_ARN                        0x5
--// A * E * R mod N ==> A
-+/* A * E * R mod N ==> A */
- #define CRYPTO_CMD_AERN                       0x6
--// A * A * R mod N ==> A
-+/* A * A * R mod N ==> A */
- #define CRYPTO_CMD_AARN                       0x7
- #define STARFIVE_RSA_RESET            0x2
-@@ -42,21 +36,10 @@
- static inline int starfive_pka_wait_done(struct starfive_cryp_ctx *ctx)
- {
-       struct starfive_cryp_dev *cryp = ctx->cryp;
-+      u32 status;
--      return wait_for_completion_timeout(&cryp->pka_done,
--                                         usecs_to_jiffies(100000));
--}
--
--static inline void starfive_pka_irq_mask_clear(struct starfive_cryp_ctx *ctx)
--{
--      struct starfive_cryp_dev *cryp = ctx->cryp;
--      u32 stat;
--
--      stat = readl(cryp->base + STARFIVE_IE_MASK_OFFSET);
--      stat &= ~STARFIVE_IE_MASK_PKA_DONE;
--      writel(stat, cryp->base + STARFIVE_IE_MASK_OFFSET);
--
--      reinit_completion(&cryp->pka_done);
-+      return readl_relaxed_poll_timeout(cryp->base + STARFIVE_PKA_CASR_OFFSET, status,
-+                                        status & STARFIVE_PKA_DONE, 10, 100000);
- }
- static void starfive_rsa_free_key(struct starfive_rsa_key *key)
-@@ -113,10 +96,9 @@ static int starfive_rsa_montgomery_form(
-               rctx->csr.pka.not_r2 = 1;
-               rctx->csr.pka.ie = 1;
--              starfive_pka_irq_mask_clear(ctx);
-               writel(rctx->csr.pka.v, cryp->base + STARFIVE_PKA_CACR_OFFSET);
--              if (!starfive_pka_wait_done(ctx))
-+              if (starfive_pka_wait_done(ctx))
-                       return -ETIMEDOUT;
-               for (loop = 0; loop <= opsize; loop++)
-@@ -135,10 +117,9 @@ static int starfive_rsa_montgomery_form(
-               rctx->csr.pka.start = 1;
-               rctx->csr.pka.ie = 1;
--              starfive_pka_irq_mask_clear(ctx);
-               writel(rctx->csr.pka.v, cryp->base + STARFIVE_PKA_CACR_OFFSET);
--              if (!starfive_pka_wait_done(ctx))
-+              if (starfive_pka_wait_done(ctx))
-                       return -ETIMEDOUT;
-       } else {
-               rctx->csr.pka.v = 0;
-@@ -150,10 +131,9 @@ static int starfive_rsa_montgomery_form(
-               rctx->csr.pka.pre_expf = 1;
-               rctx->csr.pka.ie = 1;
--              starfive_pka_irq_mask_clear(ctx);
-               writel(rctx->csr.pka.v, cryp->base + STARFIVE_PKA_CACR_OFFSET);
--              if (!starfive_pka_wait_done(ctx))
-+              if (starfive_pka_wait_done(ctx))
-                       return -ETIMEDOUT;
-               for (loop = 0; loop <= count; loop++)
-@@ -171,10 +151,9 @@ static int starfive_rsa_montgomery_form(
-               rctx->csr.pka.start = 1;
-               rctx->csr.pka.ie = 1;
--              starfive_pka_irq_mask_clear(ctx);
-               writel(rctx->csr.pka.v, cryp->base + STARFIVE_PKA_CACR_OFFSET);
--              if (!starfive_pka_wait_done(ctx))
-+              if (starfive_pka_wait_done(ctx))
-                       return -ETIMEDOUT;
-       }
-@@ -225,11 +204,10 @@ static int starfive_rsa_cpu_start(struct
-               rctx->csr.pka.start = 1;
-               rctx->csr.pka.ie = 1;
--              starfive_pka_irq_mask_clear(ctx);
-               writel(rctx->csr.pka.v, cryp->base + STARFIVE_PKA_CACR_OFFSET);
-               ret = -ETIMEDOUT;
--              if (!starfive_pka_wait_done(ctx))
-+              if (starfive_pka_wait_done(ctx))
-                       goto rsa_err;
-               if (mlen) {
-@@ -241,10 +219,9 @@ static int starfive_rsa_cpu_start(struct
-                       rctx->csr.pka.start = 1;
-                       rctx->csr.pka.ie = 1;
--                      starfive_pka_irq_mask_clear(ctx);
-                       writel(rctx->csr.pka.v, cryp->base + STARFIVE_PKA_CACR_OFFSET);
--                      if (!starfive_pka_wait_done(ctx))
-+                      if (starfive_pka_wait_done(ctx))
-                               goto rsa_err;
-               }
-       }
diff --git a/target/linux/starfive/patches-6.6/0011-crypto-starfive-Pad-adata-with-zeroes.patch b/target/linux/starfive/patches-6.6/0011-crypto-starfive-Pad-adata-with-zeroes.patch
deleted file mode 100644 (file)
index 268e405..0000000
+++ /dev/null
@@ -1,46 +0,0 @@
-From eea9f2c55cf944bbd5cdd43eb655416a867846af Mon Sep 17 00:00:00 2001
-From: Jia Jie Ho <jiajie.ho@starfivetech.com>
-Date: Mon, 20 Nov 2023 11:12:42 +0800
-Subject: [PATCH 011/116] crypto: starfive - Pad adata with zeroes
-
-Aad requires padding with zeroes up to 15 bytes in some cases. This
-patch increases the allocated buffer size for aad and prevents the
-driver accessing uninitialized memory region.
-
-v1->v2: Specify reason for alloc size change in descriptions.
-
-Signed-off-by: Jia Jie Ho <jiajie.ho@starfivetech.com>
-Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
----
- drivers/crypto/starfive/jh7110-aes.c | 6 ++++--
- 1 file changed, 4 insertions(+), 2 deletions(-)
-
---- a/drivers/crypto/starfive/jh7110-aes.c
-+++ b/drivers/crypto/starfive/jh7110-aes.c
-@@ -500,7 +500,7 @@ static int starfive_aes_prepare_req(stru
-       scatterwalk_start(&cryp->out_walk, rctx->out_sg);
-       if (cryp->assoclen) {
--              rctx->adata = kzalloc(ALIGN(cryp->assoclen, AES_BLOCK_SIZE), GFP_KERNEL);
-+              rctx->adata = kzalloc(cryp->assoclen + AES_BLOCK_SIZE, GFP_KERNEL);
-               if (!rctx->adata)
-                       return dev_err_probe(cryp->dev, -ENOMEM,
-                                            "Failed to alloc memory for adata");
-@@ -569,7 +569,7 @@ static int starfive_aes_aead_do_one_req(
-       struct starfive_cryp_ctx *ctx =
-               crypto_aead_ctx(crypto_aead_reqtfm(req));
-       struct starfive_cryp_dev *cryp = ctx->cryp;
--      struct starfive_cryp_request_ctx *rctx = ctx->rctx;
-+      struct starfive_cryp_request_ctx *rctx;
-       u32 block[AES_BLOCK_32];
-       u32 stat;
-       int err;
-@@ -579,6 +579,8 @@ static int starfive_aes_aead_do_one_req(
-       if (err)
-               return err;
-+      rctx = ctx->rctx;
-+
-       if (!cryp->assoclen)
-               goto write_text;
diff --git a/target/linux/starfive/patches-6.6/0012-crypto-starfive-Remove-cfb-and-ofb.patch b/target/linux/starfive/patches-6.6/0012-crypto-starfive-Remove-cfb-and-ofb.patch
deleted file mode 100644 (file)
index 102fbab..0000000
+++ /dev/null
@@ -1,125 +0,0 @@
-From 922b213ad22f93fb2788ce119084622ab3d25bf8 Mon Sep 17 00:00:00 2001
-From: Herbert Xu <herbert@gondor.apana.org.au>
-Date: Thu, 30 Nov 2023 18:12:55 +0800
-Subject: [PATCH 012/116] crypto: starfive - Remove cfb and ofb
-
-Remove the unused CFB/OFB implementation.
-
-Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
----
- drivers/crypto/starfive/jh7110-aes.c  | 71 +--------------------------
- drivers/crypto/starfive/jh7110-cryp.h |  2 -
- 2 files changed, 1 insertion(+), 72 deletions(-)
-
---- a/drivers/crypto/starfive/jh7110-aes.c
-+++ b/drivers/crypto/starfive/jh7110-aes.c
-@@ -262,12 +262,7 @@ static int starfive_aes_hw_init(struct s
-       rctx->csr.aes.mode  = hw_mode;
-       rctx->csr.aes.cmode = !is_encrypt(cryp);
-       rctx->csr.aes.ie = 1;
--
--      if (hw_mode == STARFIVE_AES_MODE_CFB ||
--          hw_mode == STARFIVE_AES_MODE_OFB)
--              rctx->csr.aes.stmode = STARFIVE_AES_MODE_XFB_128;
--      else
--              rctx->csr.aes.stmode = STARFIVE_AES_MODE_XFB_1;
-+      rctx->csr.aes.stmode = STARFIVE_AES_MODE_XFB_1;
-       if (cryp->side_chan) {
-               rctx->csr.aes.delay_aes = 1;
-@@ -294,8 +289,6 @@ static int starfive_aes_hw_init(struct s
-               starfive_aes_ccm_init(ctx);
-               starfive_aes_aead_hw_start(ctx, hw_mode);
-               break;
--      case STARFIVE_AES_MODE_OFB:
--      case STARFIVE_AES_MODE_CFB:
-       case STARFIVE_AES_MODE_CBC:
-       case STARFIVE_AES_MODE_CTR:
-               starfive_aes_write_iv(ctx, (void *)cryp->req.sreq->iv);
-@@ -785,26 +778,6 @@ static int starfive_aes_cbc_decrypt(stru
-       return starfive_aes_crypt(req, STARFIVE_AES_MODE_CBC);
- }
--static int starfive_aes_cfb_encrypt(struct skcipher_request *req)
--{
--      return starfive_aes_crypt(req, STARFIVE_AES_MODE_CFB | FLG_ENCRYPT);
--}
--
--static int starfive_aes_cfb_decrypt(struct skcipher_request *req)
--{
--      return starfive_aes_crypt(req, STARFIVE_AES_MODE_CFB);
--}
--
--static int starfive_aes_ofb_encrypt(struct skcipher_request *req)
--{
--      return starfive_aes_crypt(req, STARFIVE_AES_MODE_OFB | FLG_ENCRYPT);
--}
--
--static int starfive_aes_ofb_decrypt(struct skcipher_request *req)
--{
--      return starfive_aes_crypt(req, STARFIVE_AES_MODE_OFB);
--}
--
- static int starfive_aes_ctr_encrypt(struct skcipher_request *req)
- {
-       return starfive_aes_crypt(req, STARFIVE_AES_MODE_CTR | FLG_ENCRYPT);
-@@ -903,48 +876,6 @@ static struct skcipher_engine_alg skciph
-               .cra_priority           = 200,
-               .cra_flags              = CRYPTO_ALG_ASYNC,
-               .cra_blocksize          = 1,
--              .cra_ctxsize            = sizeof(struct starfive_cryp_ctx),
--              .cra_alignmask          = 0xf,
--              .cra_module             = THIS_MODULE,
--      },
--      .op = {
--              .do_one_request = starfive_aes_do_one_req,
--      },
--}, {
--      .base.init                      = starfive_aes_init_tfm,
--      .base.setkey                    = starfive_aes_setkey,
--      .base.encrypt                   = starfive_aes_cfb_encrypt,
--      .base.decrypt                   = starfive_aes_cfb_decrypt,
--      .base.min_keysize               = AES_MIN_KEY_SIZE,
--      .base.max_keysize               = AES_MAX_KEY_SIZE,
--      .base.ivsize                    = AES_BLOCK_SIZE,
--      .base.base = {
--              .cra_name               = "cfb(aes)",
--              .cra_driver_name        = "starfive-cfb-aes",
--              .cra_priority           = 200,
--              .cra_flags              = CRYPTO_ALG_ASYNC,
--              .cra_blocksize          = 1,
--              .cra_ctxsize            = sizeof(struct starfive_cryp_ctx),
--              .cra_alignmask          = 0xf,
--              .cra_module             = THIS_MODULE,
--      },
--      .op = {
--              .do_one_request = starfive_aes_do_one_req,
--      },
--}, {
--      .base.init                      = starfive_aes_init_tfm,
--      .base.setkey                    = starfive_aes_setkey,
--      .base.encrypt                   = starfive_aes_ofb_encrypt,
--      .base.decrypt                   = starfive_aes_ofb_decrypt,
--      .base.min_keysize               = AES_MIN_KEY_SIZE,
--      .base.max_keysize               = AES_MAX_KEY_SIZE,
--      .base.ivsize                    = AES_BLOCK_SIZE,
--      .base.base = {
--              .cra_name               = "ofb(aes)",
--              .cra_driver_name        = "starfive-ofb-aes",
--              .cra_priority           = 200,
--              .cra_flags              = CRYPTO_ALG_ASYNC,
--              .cra_blocksize          = 1,
-               .cra_ctxsize            = sizeof(struct starfive_cryp_ctx),
-               .cra_alignmask          = 0xf,
-               .cra_module             = THIS_MODULE,
---- a/drivers/crypto/starfive/jh7110-cryp.h
-+++ b/drivers/crypto/starfive/jh7110-cryp.h
-@@ -51,8 +51,6 @@ union starfive_aes_csr {
-               u32 ccm_start                   :1;
- #define STARFIVE_AES_MODE_ECB                 0x0
- #define STARFIVE_AES_MODE_CBC                 0x1
--#define STARFIVE_AES_MODE_CFB                 0x2
--#define STARFIVE_AES_MODE_OFB                 0x3
- #define STARFIVE_AES_MODE_CTR                 0x4
- #define STARFIVE_AES_MODE_CCM                 0x5
- #define STARFIVE_AES_MODE_GCM                 0x6
diff --git a/target/linux/starfive/patches-6.6/0013-crypto-starfive-Remove-unneeded-NULL-checks.patch b/target/linux/starfive/patches-6.6/0013-crypto-starfive-Remove-unneeded-NULL-checks.patch
deleted file mode 100644 (file)
index 2e12cfa..0000000
+++ /dev/null
@@ -1,33 +0,0 @@
-From 0dbdc763f10c5cfa968dffc290a7c060ee740172 Mon Sep 17 00:00:00 2001
-From: Jia Jie Ho <jiajie.ho@starfivetech.com>
-Date: Mon, 4 Dec 2023 11:02:39 +0800
-Subject: [PATCH 013/116] crypto: starfive - Remove unneeded NULL checks
-
-NULL check before kfree_sensitive function is not needed.
-
-Signed-off-by: Jia Jie Ho <jiajie.ho@starfivetech.com>
-Reported-by: kernel test robot <lkp@intel.com>
-Closes: https://lore.kernel.org/oe-kbuild-all/202311301702.LxswfETY-lkp@intel.com/
-Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
----
- drivers/crypto/starfive/jh7110-rsa.c | 9 +++------
- 1 file changed, 3 insertions(+), 6 deletions(-)
-
---- a/drivers/crypto/starfive/jh7110-rsa.c
-+++ b/drivers/crypto/starfive/jh7110-rsa.c
-@@ -44,12 +44,9 @@ static inline int starfive_pka_wait_done
- static void starfive_rsa_free_key(struct starfive_rsa_key *key)
- {
--      if (key->d)
--              kfree_sensitive(key->d);
--      if (key->e)
--              kfree_sensitive(key->e);
--      if (key->n)
--              kfree_sensitive(key->n);
-+      kfree_sensitive(key->d);
-+      kfree_sensitive(key->e);
-+      kfree_sensitive(key->n);
-       memset(key, 0, sizeof(*key));
- }
diff --git a/target/linux/starfive/patches-6.6/0014-dt-bindings-PCI-Add-PLDA-XpressRICH-PCIe-host-common.patch b/target/linux/starfive/patches-6.6/0014-dt-bindings-PCI-Add-PLDA-XpressRICH-PCIe-host-common.patch
deleted file mode 100644 (file)
index 4305715..0000000
+++ /dev/null
@@ -1,183 +0,0 @@
-From 708695ebf1a779de9a1fd2f72f7938afa6c14ada Mon Sep 17 00:00:00 2001
-From: Minda Chen <minda.chen@starfivetech.com>
-Date: Mon, 8 Jan 2024 19:05:51 +0800
-Subject: [PATCH 014/116] dt-bindings: PCI: Add PLDA XpressRICH PCIe host
- common properties
-
-Add PLDA XpressRICH PCIe host common properties dt-binding doc.
-PolarFire PCIe host using PLDA IP. Move common properties from Microchip
-PolarFire PCIe host to PLDA files.
-
-Signed-off-by: Minda Chen <minda.chen@starfivetech.com>
-Reviewed-by: Hal Feng <hal.feng@starfivetech.com>
-Reviewed-by: Conor Dooley <conor.dooley@microchip.com>
-Reviewed-by: Rob Herring <robh@kernel.org>
-Tested-by: John Clark <inindev@gmail.com>
----
- .../bindings/pci/microchip,pcie-host.yaml     | 55 +-------------
- .../pci/plda,xpressrich3-axi-common.yaml      | 75 +++++++++++++++++++
- 2 files changed, 76 insertions(+), 54 deletions(-)
- create mode 100644 Documentation/devicetree/bindings/pci/plda,xpressrich3-axi-common.yaml
-
---- a/Documentation/devicetree/bindings/pci/microchip,pcie-host.yaml
-+++ b/Documentation/devicetree/bindings/pci/microchip,pcie-host.yaml
-@@ -10,21 +10,13 @@ maintainers:
-   - Daire McNamara <daire.mcnamara@microchip.com>
- allOf:
--  - $ref: /schemas/pci/pci-bus.yaml#
-+  - $ref: plda,xpressrich3-axi-common.yaml#
-   - $ref: /schemas/interrupt-controller/msi-controller.yaml#
- properties:
-   compatible:
-     const: microchip,pcie-host-1.0 # PolarFire
--  reg:
--    maxItems: 2
--
--  reg-names:
--    items:
--      - const: cfg
--      - const: apb
--
-   clocks:
-     description:
-       Fabric Interface Controllers, FICs, are the interface between the FPGA
-@@ -52,18 +44,6 @@ properties:
-     items:
-       pattern: '^fic[0-3]$'
--  interrupts:
--    minItems: 1
--    items:
--      - description: PCIe host controller
--      - description: builtin MSI controller
--
--  interrupt-names:
--    minItems: 1
--    items:
--      - const: pcie
--      - const: msi
--
-   ranges:
-     maxItems: 1
-@@ -71,39 +51,6 @@ properties:
-     minItems: 1
-     maxItems: 6
--  msi-controller:
--    description: Identifies the node as an MSI controller.
--
--  msi-parent:
--    description: MSI controller the device is capable of using.
--
--  interrupt-controller:
--    type: object
--    properties:
--      '#address-cells':
--        const: 0
--
--      '#interrupt-cells':
--        const: 1
--
--      interrupt-controller: true
--
--    required:
--      - '#address-cells'
--      - '#interrupt-cells'
--      - interrupt-controller
--
--    additionalProperties: false
--
--required:
--  - reg
--  - reg-names
--  - "#interrupt-cells"
--  - interrupts
--  - interrupt-map-mask
--  - interrupt-map
--  - msi-controller
--
- unevaluatedProperties: false
- examples:
---- /dev/null
-+++ b/Documentation/devicetree/bindings/pci/plda,xpressrich3-axi-common.yaml
-@@ -0,0 +1,75 @@
-+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
-+%YAML 1.2
-+---
-+$id: http://devicetree.org/schemas/pci/plda,xpressrich3-axi-common.yaml#
-+$schema: http://devicetree.org/meta-schemas/core.yaml#
-+
-+title: PLDA XpressRICH PCIe host common properties
-+
-+maintainers:
-+  - Daire McNamara <daire.mcnamara@microchip.com>
-+  - Kevin Xie <kevin.xie@starfivetech.com>
-+
-+description:
-+  Generic PLDA XpressRICH PCIe host common properties.
-+
-+allOf:
-+  - $ref: /schemas/pci/pci-bus.yaml#
-+
-+properties:
-+  reg:
-+    maxItems: 2
-+
-+  reg-names:
-+    items:
-+      - const: cfg
-+      - const: apb
-+
-+  interrupts:
-+    minItems: 1
-+    items:
-+      - description: PCIe host controller
-+      - description: builtin MSI controller
-+
-+  interrupt-names:
-+    minItems: 1
-+    items:
-+      - const: pcie
-+      - const: msi
-+
-+  msi-controller:
-+    description: Identifies the node as an MSI controller.
-+
-+  msi-parent:
-+    description: MSI controller the device is capable of using.
-+
-+  interrupt-controller:
-+    type: object
-+    properties:
-+      '#address-cells':
-+        const: 0
-+
-+      '#interrupt-cells':
-+        const: 1
-+
-+      interrupt-controller: true
-+
-+    required:
-+      - '#address-cells'
-+      - '#interrupt-cells'
-+      - interrupt-controller
-+
-+    additionalProperties: false
-+
-+required:
-+  - reg
-+  - reg-names
-+  - interrupts
-+  - msi-controller
-+  - "#interrupt-cells"
-+  - interrupt-map-mask
-+  - interrupt-map
-+
-+additionalProperties: true
-+
-+...
diff --git a/target/linux/starfive/patches-6.6/0015-PCI-microchip-Move-pcie-microchip-host.c-to-plda-dir.patch b/target/linux/starfive/patches-6.6/0015-PCI-microchip-Move-pcie-microchip-host.c-to-plda-dir.patch
deleted file mode 100644 (file)
index 9e7717f..0000000
+++ /dev/null
@@ -1,2523 +0,0 @@
-From df67154aa92efdc774a8536ece6f431e7850aca2 Mon Sep 17 00:00:00 2001
-From: Minda Chen <minda.chen@starfivetech.com>
-Date: Mon, 8 Jan 2024 19:05:52 +0800
-Subject: [PATCH 015/116] PCI: microchip: Move pcie-microchip-host.c to plda
- directory
-
-For Microchip Polarfire PCIe host is PLDA XpressRich IP, move to plda
-directory. Prepare for refactoring the codes.
-
-Signed-off-by: Minda Chen <minda.chen@starfivetech.com>
-Reviewed-by: Conor Dooley <conor.dooley@microchip.com>
----
- drivers/pci/controller/Kconfig                     |  9 +--------
- drivers/pci/controller/Makefile                    |  2 +-
- drivers/pci/controller/plda/Kconfig                | 14 ++++++++++++++
- drivers/pci/controller/plda/Makefile               |  2 ++
- .../controller/{ => plda}/pcie-microchip-host.c    |  2 +-
- 5 files changed, 19 insertions(+), 10 deletions(-)
- create mode 100644 drivers/pci/controller/plda/Kconfig
- create mode 100644 drivers/pci/controller/plda/Makefile
- rename drivers/pci/controller/{ => plda}/pcie-microchip-host.c (99%)
-
---- a/drivers/pci/controller/Kconfig
-+++ b/drivers/pci/controller/Kconfig
-@@ -215,14 +215,6 @@ config PCIE_MT7621
-       help
-         This selects a driver for the MediaTek MT7621 PCIe Controller.
--config PCIE_MICROCHIP_HOST
--      tristate "Microchip AXI PCIe controller"
--      depends on PCI_MSI && OF
--      select PCI_HOST_COMMON
--      help
--        Say Y here if you want kernel to support the Microchip AXI PCIe
--        Host Bridge driver.
--
- config PCI_HYPERV_INTERFACE
-       tristate "Microsoft Hyper-V PCI Interface"
-       depends on ((X86 && X86_64) || ARM64) && HYPERV && PCI_MSI
-@@ -345,4 +337,5 @@ config PCIE_XILINX_CPM
- source "drivers/pci/controller/cadence/Kconfig"
- source "drivers/pci/controller/dwc/Kconfig"
- source "drivers/pci/controller/mobiveil/Kconfig"
-+source "drivers/pci/controller/plda/Kconfig"
- endmenu
---- a/drivers/pci/controller/Makefile
-+++ b/drivers/pci/controller/Makefile
-@@ -32,7 +32,6 @@ obj-$(CONFIG_PCIE_ROCKCHIP_EP) += pcie-r
- obj-$(CONFIG_PCIE_ROCKCHIP_HOST) += pcie-rockchip-host.o
- obj-$(CONFIG_PCIE_MEDIATEK) += pcie-mediatek.o
- obj-$(CONFIG_PCIE_MEDIATEK_GEN3) += pcie-mediatek-gen3.o
--obj-$(CONFIG_PCIE_MICROCHIP_HOST) += pcie-microchip-host.o
- obj-$(CONFIG_VMD) += vmd.o
- obj-$(CONFIG_PCIE_BRCMSTB) += pcie-brcmstb.o
- obj-$(CONFIG_PCI_LOONGSON) += pci-loongson.o
-@@ -43,6 +42,7 @@ obj-$(CONFIG_PCIE_MT7621) += pcie-mt7621
- # pcie-hisi.o quirks are needed even without CONFIG_PCIE_DW
- obj-y                         += dwc/
- obj-y                         += mobiveil/
-+obj-y                         += plda/
- # The following drivers are for devices that use the generic ACPI
---- /dev/null
-+++ b/drivers/pci/controller/plda/Kconfig
-@@ -0,0 +1,14 @@
-+# SPDX-License-Identifier: GPL-2.0
-+
-+menu "PLDA-based PCIe controllers"
-+      depends on PCI
-+
-+config PCIE_MICROCHIP_HOST
-+      tristate "Microchip AXI PCIe controller"
-+      depends on PCI_MSI && OF
-+      select PCI_HOST_COMMON
-+      help
-+        Say Y here if you want kernel to support the Microchip AXI PCIe
-+        Host Bridge driver.
-+
-+endmenu
---- /dev/null
-+++ b/drivers/pci/controller/plda/Makefile
-@@ -0,0 +1,2 @@
-+# SPDX-License-Identifier: GPL-2.0
-+obj-$(CONFIG_PCIE_MICROCHIP_HOST) += pcie-microchip-host.o
---- a/drivers/pci/controller/pcie-microchip-host.c
-+++ /dev/null
-@@ -1,1216 +0,0 @@
--// SPDX-License-Identifier: GPL-2.0
--/*
-- * Microchip AXI PCIe Bridge host controller driver
-- *
-- * Copyright (c) 2018 - 2020 Microchip Corporation. All rights reserved.
-- *
-- * Author: Daire McNamara <daire.mcnamara@microchip.com>
-- */
--
--#include <linux/bitfield.h>
--#include <linux/clk.h>
--#include <linux/irqchip/chained_irq.h>
--#include <linux/irqdomain.h>
--#include <linux/module.h>
--#include <linux/msi.h>
--#include <linux/of_address.h>
--#include <linux/of_pci.h>
--#include <linux/pci-ecam.h>
--#include <linux/platform_device.h>
--
--#include "../pci.h"
--
--/* Number of MSI IRQs */
--#define MC_MAX_NUM_MSI_IRQS                   32
--
--/* PCIe Bridge Phy and Controller Phy offsets */
--#define MC_PCIE1_BRIDGE_ADDR                  0x00008000u
--#define MC_PCIE1_CTRL_ADDR                    0x0000a000u
--
--#define MC_PCIE_BRIDGE_ADDR                   (MC_PCIE1_BRIDGE_ADDR)
--#define MC_PCIE_CTRL_ADDR                     (MC_PCIE1_CTRL_ADDR)
--
--/* PCIe Bridge Phy Regs */
--#define PCIE_PCI_IRQ_DW0                      0xa8
--#define  MSIX_CAP_MASK                                BIT(31)
--#define  NUM_MSI_MSGS_MASK                    GENMASK(6, 4)
--#define  NUM_MSI_MSGS_SHIFT                   4
--
--#define IMASK_LOCAL                           0x180
--#define  DMA_END_ENGINE_0_MASK                        0x00000000u
--#define  DMA_END_ENGINE_0_SHIFT                       0
--#define  DMA_END_ENGINE_1_MASK                        0x00000000u
--#define  DMA_END_ENGINE_1_SHIFT                       1
--#define  DMA_ERROR_ENGINE_0_MASK              0x00000100u
--#define  DMA_ERROR_ENGINE_0_SHIFT             8
--#define  DMA_ERROR_ENGINE_1_MASK              0x00000200u
--#define  DMA_ERROR_ENGINE_1_SHIFT             9
--#define  A_ATR_EVT_POST_ERR_MASK              0x00010000u
--#define  A_ATR_EVT_POST_ERR_SHIFT             16
--#define  A_ATR_EVT_FETCH_ERR_MASK             0x00020000u
--#define  A_ATR_EVT_FETCH_ERR_SHIFT            17
--#define  A_ATR_EVT_DISCARD_ERR_MASK           0x00040000u
--#define  A_ATR_EVT_DISCARD_ERR_SHIFT          18
--#define  A_ATR_EVT_DOORBELL_MASK              0x00000000u
--#define  A_ATR_EVT_DOORBELL_SHIFT             19
--#define  P_ATR_EVT_POST_ERR_MASK              0x00100000u
--#define  P_ATR_EVT_POST_ERR_SHIFT             20
--#define  P_ATR_EVT_FETCH_ERR_MASK             0x00200000u
--#define  P_ATR_EVT_FETCH_ERR_SHIFT            21
--#define  P_ATR_EVT_DISCARD_ERR_MASK           0x00400000u
--#define  P_ATR_EVT_DISCARD_ERR_SHIFT          22
--#define  P_ATR_EVT_DOORBELL_MASK              0x00000000u
--#define  P_ATR_EVT_DOORBELL_SHIFT             23
--#define  PM_MSI_INT_INTA_MASK                 0x01000000u
--#define  PM_MSI_INT_INTA_SHIFT                        24
--#define  PM_MSI_INT_INTB_MASK                 0x02000000u
--#define  PM_MSI_INT_INTB_SHIFT                        25
--#define  PM_MSI_INT_INTC_MASK                 0x04000000u
--#define  PM_MSI_INT_INTC_SHIFT                        26
--#define  PM_MSI_INT_INTD_MASK                 0x08000000u
--#define  PM_MSI_INT_INTD_SHIFT                        27
--#define  PM_MSI_INT_INTX_MASK                 0x0f000000u
--#define  PM_MSI_INT_INTX_SHIFT                        24
--#define  PM_MSI_INT_MSI_MASK                  0x10000000u
--#define  PM_MSI_INT_MSI_SHIFT                 28
--#define  PM_MSI_INT_AER_EVT_MASK              0x20000000u
--#define  PM_MSI_INT_AER_EVT_SHIFT             29
--#define  PM_MSI_INT_EVENTS_MASK                       0x40000000u
--#define  PM_MSI_INT_EVENTS_SHIFT              30
--#define  PM_MSI_INT_SYS_ERR_MASK              0x80000000u
--#define  PM_MSI_INT_SYS_ERR_SHIFT             31
--#define  NUM_LOCAL_EVENTS                     15
--#define ISTATUS_LOCAL                         0x184
--#define IMASK_HOST                            0x188
--#define ISTATUS_HOST                          0x18c
--#define IMSI_ADDR                             0x190
--#define ISTATUS_MSI                           0x194
--
--/* PCIe Master table init defines */
--#define ATR0_PCIE_WIN0_SRCADDR_PARAM          0x600u
--#define  ATR0_PCIE_ATR_SIZE                   0x25
--#define  ATR0_PCIE_ATR_SIZE_SHIFT             1
--#define ATR0_PCIE_WIN0_SRC_ADDR                       0x604u
--#define ATR0_PCIE_WIN0_TRSL_ADDR_LSB          0x608u
--#define ATR0_PCIE_WIN0_TRSL_ADDR_UDW          0x60cu
--#define ATR0_PCIE_WIN0_TRSL_PARAM             0x610u
--
--/* PCIe AXI slave table init defines */
--#define ATR0_AXI4_SLV0_SRCADDR_PARAM          0x800u
--#define  ATR_SIZE_SHIFT                               1
--#define  ATR_IMPL_ENABLE                      1
--#define ATR0_AXI4_SLV0_SRC_ADDR                       0x804u
--#define ATR0_AXI4_SLV0_TRSL_ADDR_LSB          0x808u
--#define ATR0_AXI4_SLV0_TRSL_ADDR_UDW          0x80cu
--#define ATR0_AXI4_SLV0_TRSL_PARAM             0x810u
--#define  PCIE_TX_RX_INTERFACE                 0x00000000u
--#define  PCIE_CONFIG_INTERFACE                        0x00000001u
--
--#define ATR_ENTRY_SIZE                                32
--
--/* PCIe Controller Phy Regs */
--#define SEC_ERROR_EVENT_CNT                   0x20
--#define DED_ERROR_EVENT_CNT                   0x24
--#define SEC_ERROR_INT                         0x28
--#define  SEC_ERROR_INT_TX_RAM_SEC_ERR_INT     GENMASK(3, 0)
--#define  SEC_ERROR_INT_RX_RAM_SEC_ERR_INT     GENMASK(7, 4)
--#define  SEC_ERROR_INT_PCIE2AXI_RAM_SEC_ERR_INT       GENMASK(11, 8)
--#define  SEC_ERROR_INT_AXI2PCIE_RAM_SEC_ERR_INT       GENMASK(15, 12)
--#define  SEC_ERROR_INT_ALL_RAM_SEC_ERR_INT    GENMASK(15, 0)
--#define  NUM_SEC_ERROR_INTS                   (4)
--#define SEC_ERROR_INT_MASK                    0x2c
--#define DED_ERROR_INT                         0x30
--#define  DED_ERROR_INT_TX_RAM_DED_ERR_INT     GENMASK(3, 0)
--#define  DED_ERROR_INT_RX_RAM_DED_ERR_INT     GENMASK(7, 4)
--#define  DED_ERROR_INT_PCIE2AXI_RAM_DED_ERR_INT       GENMASK(11, 8)
--#define  DED_ERROR_INT_AXI2PCIE_RAM_DED_ERR_INT       GENMASK(15, 12)
--#define  DED_ERROR_INT_ALL_RAM_DED_ERR_INT    GENMASK(15, 0)
--#define  NUM_DED_ERROR_INTS                   (4)
--#define DED_ERROR_INT_MASK                    0x34
--#define ECC_CONTROL                           0x38
--#define  ECC_CONTROL_TX_RAM_INJ_ERROR_0               BIT(0)
--#define  ECC_CONTROL_TX_RAM_INJ_ERROR_1               BIT(1)
--#define  ECC_CONTROL_TX_RAM_INJ_ERROR_2               BIT(2)
--#define  ECC_CONTROL_TX_RAM_INJ_ERROR_3               BIT(3)
--#define  ECC_CONTROL_RX_RAM_INJ_ERROR_0               BIT(4)
--#define  ECC_CONTROL_RX_RAM_INJ_ERROR_1               BIT(5)
--#define  ECC_CONTROL_RX_RAM_INJ_ERROR_2               BIT(6)
--#define  ECC_CONTROL_RX_RAM_INJ_ERROR_3               BIT(7)
--#define  ECC_CONTROL_PCIE2AXI_RAM_INJ_ERROR_0 BIT(8)
--#define  ECC_CONTROL_PCIE2AXI_RAM_INJ_ERROR_1 BIT(9)
--#define  ECC_CONTROL_PCIE2AXI_RAM_INJ_ERROR_2 BIT(10)
--#define  ECC_CONTROL_PCIE2AXI_RAM_INJ_ERROR_3 BIT(11)
--#define  ECC_CONTROL_AXI2PCIE_RAM_INJ_ERROR_0 BIT(12)
--#define  ECC_CONTROL_AXI2PCIE_RAM_INJ_ERROR_1 BIT(13)
--#define  ECC_CONTROL_AXI2PCIE_RAM_INJ_ERROR_2 BIT(14)
--#define  ECC_CONTROL_AXI2PCIE_RAM_INJ_ERROR_3 BIT(15)
--#define  ECC_CONTROL_TX_RAM_ECC_BYPASS                BIT(24)
--#define  ECC_CONTROL_RX_RAM_ECC_BYPASS                BIT(25)
--#define  ECC_CONTROL_PCIE2AXI_RAM_ECC_BYPASS  BIT(26)
--#define  ECC_CONTROL_AXI2PCIE_RAM_ECC_BYPASS  BIT(27)
--#define PCIE_EVENT_INT                                0x14c
--#define  PCIE_EVENT_INT_L2_EXIT_INT           BIT(0)
--#define  PCIE_EVENT_INT_HOTRST_EXIT_INT               BIT(1)
--#define  PCIE_EVENT_INT_DLUP_EXIT_INT         BIT(2)
--#define  PCIE_EVENT_INT_MASK                  GENMASK(2, 0)
--#define  PCIE_EVENT_INT_L2_EXIT_INT_MASK      BIT(16)
--#define  PCIE_EVENT_INT_HOTRST_EXIT_INT_MASK  BIT(17)
--#define  PCIE_EVENT_INT_DLUP_EXIT_INT_MASK    BIT(18)
--#define  PCIE_EVENT_INT_ENB_MASK              GENMASK(18, 16)
--#define  PCIE_EVENT_INT_ENB_SHIFT             16
--#define  NUM_PCIE_EVENTS                      (3)
--
--/* PCIe Config space MSI capability structure */
--#define MC_MSI_CAP_CTRL_OFFSET                        0xe0u
--
--/* Events */
--#define EVENT_PCIE_L2_EXIT                    0
--#define EVENT_PCIE_HOTRST_EXIT                        1
--#define EVENT_PCIE_DLUP_EXIT                  2
--#define EVENT_SEC_TX_RAM_SEC_ERR              3
--#define EVENT_SEC_RX_RAM_SEC_ERR              4
--#define EVENT_SEC_PCIE2AXI_RAM_SEC_ERR                5
--#define EVENT_SEC_AXI2PCIE_RAM_SEC_ERR                6
--#define EVENT_DED_TX_RAM_DED_ERR              7
--#define EVENT_DED_RX_RAM_DED_ERR              8
--#define EVENT_DED_PCIE2AXI_RAM_DED_ERR                9
--#define EVENT_DED_AXI2PCIE_RAM_DED_ERR                10
--#define EVENT_LOCAL_DMA_END_ENGINE_0          11
--#define EVENT_LOCAL_DMA_END_ENGINE_1          12
--#define EVENT_LOCAL_DMA_ERROR_ENGINE_0                13
--#define EVENT_LOCAL_DMA_ERROR_ENGINE_1                14
--#define EVENT_LOCAL_A_ATR_EVT_POST_ERR                15
--#define EVENT_LOCAL_A_ATR_EVT_FETCH_ERR               16
--#define EVENT_LOCAL_A_ATR_EVT_DISCARD_ERR     17
--#define EVENT_LOCAL_A_ATR_EVT_DOORBELL                18
--#define EVENT_LOCAL_P_ATR_EVT_POST_ERR                19
--#define EVENT_LOCAL_P_ATR_EVT_FETCH_ERR               20
--#define EVENT_LOCAL_P_ATR_EVT_DISCARD_ERR     21
--#define EVENT_LOCAL_P_ATR_EVT_DOORBELL                22
--#define EVENT_LOCAL_PM_MSI_INT_INTX           23
--#define EVENT_LOCAL_PM_MSI_INT_MSI            24
--#define EVENT_LOCAL_PM_MSI_INT_AER_EVT                25
--#define EVENT_LOCAL_PM_MSI_INT_EVENTS         26
--#define EVENT_LOCAL_PM_MSI_INT_SYS_ERR                27
--#define NUM_EVENTS                            28
--
--#define PCIE_EVENT_CAUSE(x, s)        \
--      [EVENT_PCIE_ ## x] = { __stringify(x), s }
--
--#define SEC_ERROR_CAUSE(x, s) \
--      [EVENT_SEC_ ## x] = { __stringify(x), s }
--
--#define DED_ERROR_CAUSE(x, s) \
--      [EVENT_DED_ ## x] = { __stringify(x), s }
--
--#define LOCAL_EVENT_CAUSE(x, s) \
--      [EVENT_LOCAL_ ## x] = { __stringify(x), s }
--
--#define PCIE_EVENT(x) \
--      .base = MC_PCIE_CTRL_ADDR, \
--      .offset = PCIE_EVENT_INT, \
--      .mask_offset = PCIE_EVENT_INT, \
--      .mask_high = 1, \
--      .mask = PCIE_EVENT_INT_ ## x ## _INT, \
--      .enb_mask = PCIE_EVENT_INT_ENB_MASK
--
--#define SEC_EVENT(x) \
--      .base = MC_PCIE_CTRL_ADDR, \
--      .offset = SEC_ERROR_INT, \
--      .mask_offset = SEC_ERROR_INT_MASK, \
--      .mask = SEC_ERROR_INT_ ## x ## _INT, \
--      .mask_high = 1, \
--      .enb_mask = 0
--
--#define DED_EVENT(x) \
--      .base = MC_PCIE_CTRL_ADDR, \
--      .offset = DED_ERROR_INT, \
--      .mask_offset = DED_ERROR_INT_MASK, \
--      .mask_high = 1, \
--      .mask = DED_ERROR_INT_ ## x ## _INT, \
--      .enb_mask = 0
--
--#define LOCAL_EVENT(x) \
--      .base = MC_PCIE_BRIDGE_ADDR, \
--      .offset = ISTATUS_LOCAL, \
--      .mask_offset = IMASK_LOCAL, \
--      .mask_high = 0, \
--      .mask = x ## _MASK, \
--      .enb_mask = 0
--
--#define PCIE_EVENT_TO_EVENT_MAP(x) \
--      { PCIE_EVENT_INT_ ## x ## _INT, EVENT_PCIE_ ## x }
--
--#define SEC_ERROR_TO_EVENT_MAP(x) \
--      { SEC_ERROR_INT_ ## x ## _INT, EVENT_SEC_ ## x }
--
--#define DED_ERROR_TO_EVENT_MAP(x) \
--      { DED_ERROR_INT_ ## x ## _INT, EVENT_DED_ ## x }
--
--#define LOCAL_STATUS_TO_EVENT_MAP(x) \
--      { x ## _MASK, EVENT_LOCAL_ ## x }
--
--struct event_map {
--      u32 reg_mask;
--      u32 event_bit;
--};
--
--struct mc_msi {
--      struct mutex lock;              /* Protect used bitmap */
--      struct irq_domain *msi_domain;
--      struct irq_domain *dev_domain;
--      u32 num_vectors;
--      u64 vector_phy;
--      DECLARE_BITMAP(used, MC_MAX_NUM_MSI_IRQS);
--};
--
--struct mc_pcie {
--      void __iomem *axi_base_addr;
--      struct device *dev;
--      struct irq_domain *intx_domain;
--      struct irq_domain *event_domain;
--      raw_spinlock_t lock;
--      struct mc_msi msi;
--};
--
--struct cause {
--      const char *sym;
--      const char *str;
--};
--
--static const struct cause event_cause[NUM_EVENTS] = {
--      PCIE_EVENT_CAUSE(L2_EXIT, "L2 exit event"),
--      PCIE_EVENT_CAUSE(HOTRST_EXIT, "Hot reset exit event"),
--      PCIE_EVENT_CAUSE(DLUP_EXIT, "DLUP exit event"),
--      SEC_ERROR_CAUSE(TX_RAM_SEC_ERR,  "sec error in tx buffer"),
--      SEC_ERROR_CAUSE(RX_RAM_SEC_ERR,  "sec error in rx buffer"),
--      SEC_ERROR_CAUSE(PCIE2AXI_RAM_SEC_ERR,  "sec error in pcie2axi buffer"),
--      SEC_ERROR_CAUSE(AXI2PCIE_RAM_SEC_ERR,  "sec error in axi2pcie buffer"),
--      DED_ERROR_CAUSE(TX_RAM_DED_ERR,  "ded error in tx buffer"),
--      DED_ERROR_CAUSE(RX_RAM_DED_ERR,  "ded error in rx buffer"),
--      DED_ERROR_CAUSE(PCIE2AXI_RAM_DED_ERR,  "ded error in pcie2axi buffer"),
--      DED_ERROR_CAUSE(AXI2PCIE_RAM_DED_ERR,  "ded error in axi2pcie buffer"),
--      LOCAL_EVENT_CAUSE(DMA_ERROR_ENGINE_0, "dma engine 0 error"),
--      LOCAL_EVENT_CAUSE(DMA_ERROR_ENGINE_1, "dma engine 1 error"),
--      LOCAL_EVENT_CAUSE(A_ATR_EVT_POST_ERR, "axi write request error"),
--      LOCAL_EVENT_CAUSE(A_ATR_EVT_FETCH_ERR, "axi read request error"),
--      LOCAL_EVENT_CAUSE(A_ATR_EVT_DISCARD_ERR, "axi read timeout"),
--      LOCAL_EVENT_CAUSE(P_ATR_EVT_POST_ERR, "pcie write request error"),
--      LOCAL_EVENT_CAUSE(P_ATR_EVT_FETCH_ERR, "pcie read request error"),
--      LOCAL_EVENT_CAUSE(P_ATR_EVT_DISCARD_ERR, "pcie read timeout"),
--      LOCAL_EVENT_CAUSE(PM_MSI_INT_AER_EVT, "aer event"),
--      LOCAL_EVENT_CAUSE(PM_MSI_INT_EVENTS, "pm/ltr/hotplug event"),
--      LOCAL_EVENT_CAUSE(PM_MSI_INT_SYS_ERR, "system error"),
--};
--
--static struct event_map pcie_event_to_event[] = {
--      PCIE_EVENT_TO_EVENT_MAP(L2_EXIT),
--      PCIE_EVENT_TO_EVENT_MAP(HOTRST_EXIT),
--      PCIE_EVENT_TO_EVENT_MAP(DLUP_EXIT),
--};
--
--static struct event_map sec_error_to_event[] = {
--      SEC_ERROR_TO_EVENT_MAP(TX_RAM_SEC_ERR),
--      SEC_ERROR_TO_EVENT_MAP(RX_RAM_SEC_ERR),
--      SEC_ERROR_TO_EVENT_MAP(PCIE2AXI_RAM_SEC_ERR),
--      SEC_ERROR_TO_EVENT_MAP(AXI2PCIE_RAM_SEC_ERR),
--};
--
--static struct event_map ded_error_to_event[] = {
--      DED_ERROR_TO_EVENT_MAP(TX_RAM_DED_ERR),
--      DED_ERROR_TO_EVENT_MAP(RX_RAM_DED_ERR),
--      DED_ERROR_TO_EVENT_MAP(PCIE2AXI_RAM_DED_ERR),
--      DED_ERROR_TO_EVENT_MAP(AXI2PCIE_RAM_DED_ERR),
--};
--
--static struct event_map local_status_to_event[] = {
--      LOCAL_STATUS_TO_EVENT_MAP(DMA_END_ENGINE_0),
--      LOCAL_STATUS_TO_EVENT_MAP(DMA_END_ENGINE_1),
--      LOCAL_STATUS_TO_EVENT_MAP(DMA_ERROR_ENGINE_0),
--      LOCAL_STATUS_TO_EVENT_MAP(DMA_ERROR_ENGINE_1),
--      LOCAL_STATUS_TO_EVENT_MAP(A_ATR_EVT_POST_ERR),
--      LOCAL_STATUS_TO_EVENT_MAP(A_ATR_EVT_FETCH_ERR),
--      LOCAL_STATUS_TO_EVENT_MAP(A_ATR_EVT_DISCARD_ERR),
--      LOCAL_STATUS_TO_EVENT_MAP(A_ATR_EVT_DOORBELL),
--      LOCAL_STATUS_TO_EVENT_MAP(P_ATR_EVT_POST_ERR),
--      LOCAL_STATUS_TO_EVENT_MAP(P_ATR_EVT_FETCH_ERR),
--      LOCAL_STATUS_TO_EVENT_MAP(P_ATR_EVT_DISCARD_ERR),
--      LOCAL_STATUS_TO_EVENT_MAP(P_ATR_EVT_DOORBELL),
--      LOCAL_STATUS_TO_EVENT_MAP(PM_MSI_INT_INTX),
--      LOCAL_STATUS_TO_EVENT_MAP(PM_MSI_INT_MSI),
--      LOCAL_STATUS_TO_EVENT_MAP(PM_MSI_INT_AER_EVT),
--      LOCAL_STATUS_TO_EVENT_MAP(PM_MSI_INT_EVENTS),
--      LOCAL_STATUS_TO_EVENT_MAP(PM_MSI_INT_SYS_ERR),
--};
--
--static struct {
--      u32 base;
--      u32 offset;
--      u32 mask;
--      u32 shift;
--      u32 enb_mask;
--      u32 mask_high;
--      u32 mask_offset;
--} event_descs[] = {
--      { PCIE_EVENT(L2_EXIT) },
--      { PCIE_EVENT(HOTRST_EXIT) },
--      { PCIE_EVENT(DLUP_EXIT) },
--      { SEC_EVENT(TX_RAM_SEC_ERR) },
--      { SEC_EVENT(RX_RAM_SEC_ERR) },
--      { SEC_EVENT(PCIE2AXI_RAM_SEC_ERR) },
--      { SEC_EVENT(AXI2PCIE_RAM_SEC_ERR) },
--      { DED_EVENT(TX_RAM_DED_ERR) },
--      { DED_EVENT(RX_RAM_DED_ERR) },
--      { DED_EVENT(PCIE2AXI_RAM_DED_ERR) },
--      { DED_EVENT(AXI2PCIE_RAM_DED_ERR) },
--      { LOCAL_EVENT(DMA_END_ENGINE_0) },
--      { LOCAL_EVENT(DMA_END_ENGINE_1) },
--      { LOCAL_EVENT(DMA_ERROR_ENGINE_0) },
--      { LOCAL_EVENT(DMA_ERROR_ENGINE_1) },
--      { LOCAL_EVENT(A_ATR_EVT_POST_ERR) },
--      { LOCAL_EVENT(A_ATR_EVT_FETCH_ERR) },
--      { LOCAL_EVENT(A_ATR_EVT_DISCARD_ERR) },
--      { LOCAL_EVENT(A_ATR_EVT_DOORBELL) },
--      { LOCAL_EVENT(P_ATR_EVT_POST_ERR) },
--      { LOCAL_EVENT(P_ATR_EVT_FETCH_ERR) },
--      { LOCAL_EVENT(P_ATR_EVT_DISCARD_ERR) },
--      { LOCAL_EVENT(P_ATR_EVT_DOORBELL) },
--      { LOCAL_EVENT(PM_MSI_INT_INTX) },
--      { LOCAL_EVENT(PM_MSI_INT_MSI) },
--      { LOCAL_EVENT(PM_MSI_INT_AER_EVT) },
--      { LOCAL_EVENT(PM_MSI_INT_EVENTS) },
--      { LOCAL_EVENT(PM_MSI_INT_SYS_ERR) },
--};
--
--static char poss_clks[][5] = { "fic0", "fic1", "fic2", "fic3" };
--
--static struct mc_pcie *port;
--
--static void mc_pcie_enable_msi(struct mc_pcie *port, void __iomem *ecam)
--{
--      struct mc_msi *msi = &port->msi;
--      u16 reg;
--      u8 queue_size;
--
--      /* Fixup MSI enable flag */
--      reg = readw_relaxed(ecam + MC_MSI_CAP_CTRL_OFFSET + PCI_MSI_FLAGS);
--      reg |= PCI_MSI_FLAGS_ENABLE;
--      writew_relaxed(reg, ecam + MC_MSI_CAP_CTRL_OFFSET + PCI_MSI_FLAGS);
--
--      /* Fixup PCI MSI queue flags */
--      queue_size = FIELD_GET(PCI_MSI_FLAGS_QMASK, reg);
--      reg |= FIELD_PREP(PCI_MSI_FLAGS_QSIZE, queue_size);
--      writew_relaxed(reg, ecam + MC_MSI_CAP_CTRL_OFFSET + PCI_MSI_FLAGS);
--
--      /* Fixup MSI addr fields */
--      writel_relaxed(lower_32_bits(msi->vector_phy),
--                     ecam + MC_MSI_CAP_CTRL_OFFSET + PCI_MSI_ADDRESS_LO);
--      writel_relaxed(upper_32_bits(msi->vector_phy),
--                     ecam + MC_MSI_CAP_CTRL_OFFSET + PCI_MSI_ADDRESS_HI);
--}
--
--static void mc_handle_msi(struct irq_desc *desc)
--{
--      struct mc_pcie *port = irq_desc_get_handler_data(desc);
--      struct irq_chip *chip = irq_desc_get_chip(desc);
--      struct device *dev = port->dev;
--      struct mc_msi *msi = &port->msi;
--      void __iomem *bridge_base_addr =
--              port->axi_base_addr + MC_PCIE_BRIDGE_ADDR;
--      unsigned long status;
--      u32 bit;
--      int ret;
--
--      chained_irq_enter(chip, desc);
--
--      status = readl_relaxed(bridge_base_addr + ISTATUS_LOCAL);
--      if (status & PM_MSI_INT_MSI_MASK) {
--              writel_relaxed(status & PM_MSI_INT_MSI_MASK, bridge_base_addr + ISTATUS_LOCAL);
--              status = readl_relaxed(bridge_base_addr + ISTATUS_MSI);
--              for_each_set_bit(bit, &status, msi->num_vectors) {
--                      ret = generic_handle_domain_irq(msi->dev_domain, bit);
--                      if (ret)
--                              dev_err_ratelimited(dev, "bad MSI IRQ %d\n",
--                                                  bit);
--              }
--      }
--
--      chained_irq_exit(chip, desc);
--}
--
--static void mc_msi_bottom_irq_ack(struct irq_data *data)
--{
--      struct mc_pcie *port = irq_data_get_irq_chip_data(data);
--      void __iomem *bridge_base_addr =
--              port->axi_base_addr + MC_PCIE_BRIDGE_ADDR;
--      u32 bitpos = data->hwirq;
--
--      writel_relaxed(BIT(bitpos), bridge_base_addr + ISTATUS_MSI);
--}
--
--static void mc_compose_msi_msg(struct irq_data *data, struct msi_msg *msg)
--{
--      struct mc_pcie *port = irq_data_get_irq_chip_data(data);
--      phys_addr_t addr = port->msi.vector_phy;
--
--      msg->address_lo = lower_32_bits(addr);
--      msg->address_hi = upper_32_bits(addr);
--      msg->data = data->hwirq;
--
--      dev_dbg(port->dev, "msi#%x address_hi %#x address_lo %#x\n",
--              (int)data->hwirq, msg->address_hi, msg->address_lo);
--}
--
--static int mc_msi_set_affinity(struct irq_data *irq_data,
--                             const struct cpumask *mask, bool force)
--{
--      return -EINVAL;
--}
--
--static struct irq_chip mc_msi_bottom_irq_chip = {
--      .name = "Microchip MSI",
--      .irq_ack = mc_msi_bottom_irq_ack,
--      .irq_compose_msi_msg = mc_compose_msi_msg,
--      .irq_set_affinity = mc_msi_set_affinity,
--};
--
--static int mc_irq_msi_domain_alloc(struct irq_domain *domain, unsigned int virq,
--                                 unsigned int nr_irqs, void *args)
--{
--      struct mc_pcie *port = domain->host_data;
--      struct mc_msi *msi = &port->msi;
--      unsigned long bit;
--
--      mutex_lock(&msi->lock);
--      bit = find_first_zero_bit(msi->used, msi->num_vectors);
--      if (bit >= msi->num_vectors) {
--              mutex_unlock(&msi->lock);
--              return -ENOSPC;
--      }
--
--      set_bit(bit, msi->used);
--
--      irq_domain_set_info(domain, virq, bit, &mc_msi_bottom_irq_chip,
--                          domain->host_data, handle_edge_irq, NULL, NULL);
--
--      mutex_unlock(&msi->lock);
--
--      return 0;
--}
--
--static void mc_irq_msi_domain_free(struct irq_domain *domain, unsigned int virq,
--                                 unsigned int nr_irqs)
--{
--      struct irq_data *d = irq_domain_get_irq_data(domain, virq);
--      struct mc_pcie *port = irq_data_get_irq_chip_data(d);
--      struct mc_msi *msi = &port->msi;
--
--      mutex_lock(&msi->lock);
--
--      if (test_bit(d->hwirq, msi->used))
--              __clear_bit(d->hwirq, msi->used);
--      else
--              dev_err(port->dev, "trying to free unused MSI%lu\n", d->hwirq);
--
--      mutex_unlock(&msi->lock);
--}
--
--static const struct irq_domain_ops msi_domain_ops = {
--      .alloc  = mc_irq_msi_domain_alloc,
--      .free   = mc_irq_msi_domain_free,
--};
--
--static struct irq_chip mc_msi_irq_chip = {
--      .name = "Microchip PCIe MSI",
--      .irq_ack = irq_chip_ack_parent,
--      .irq_mask = pci_msi_mask_irq,
--      .irq_unmask = pci_msi_unmask_irq,
--};
--
--static struct msi_domain_info mc_msi_domain_info = {
--      .flags = (MSI_FLAG_USE_DEF_DOM_OPS | MSI_FLAG_USE_DEF_CHIP_OPS |
--                MSI_FLAG_PCI_MSIX),
--      .chip = &mc_msi_irq_chip,
--};
--
--static int mc_allocate_msi_domains(struct mc_pcie *port)
--{
--      struct device *dev = port->dev;
--      struct fwnode_handle *fwnode = of_node_to_fwnode(dev->of_node);
--      struct mc_msi *msi = &port->msi;
--
--      mutex_init(&port->msi.lock);
--
--      msi->dev_domain = irq_domain_add_linear(NULL, msi->num_vectors,
--                                              &msi_domain_ops, port);
--      if (!msi->dev_domain) {
--              dev_err(dev, "failed to create IRQ domain\n");
--              return -ENOMEM;
--      }
--
--      msi->msi_domain = pci_msi_create_irq_domain(fwnode, &mc_msi_domain_info,
--                                                  msi->dev_domain);
--      if (!msi->msi_domain) {
--              dev_err(dev, "failed to create MSI domain\n");
--              irq_domain_remove(msi->dev_domain);
--              return -ENOMEM;
--      }
--
--      return 0;
--}
--
--static void mc_handle_intx(struct irq_desc *desc)
--{
--      struct mc_pcie *port = irq_desc_get_handler_data(desc);
--      struct irq_chip *chip = irq_desc_get_chip(desc);
--      struct device *dev = port->dev;
--      void __iomem *bridge_base_addr =
--              port->axi_base_addr + MC_PCIE_BRIDGE_ADDR;
--      unsigned long status;
--      u32 bit;
--      int ret;
--
--      chained_irq_enter(chip, desc);
--
--      status = readl_relaxed(bridge_base_addr + ISTATUS_LOCAL);
--      if (status & PM_MSI_INT_INTX_MASK) {
--              status &= PM_MSI_INT_INTX_MASK;
--              status >>= PM_MSI_INT_INTX_SHIFT;
--              for_each_set_bit(bit, &status, PCI_NUM_INTX) {
--                      ret = generic_handle_domain_irq(port->intx_domain, bit);
--                      if (ret)
--                              dev_err_ratelimited(dev, "bad INTx IRQ %d\n",
--                                                  bit);
--              }
--      }
--
--      chained_irq_exit(chip, desc);
--}
--
--static void mc_ack_intx_irq(struct irq_data *data)
--{
--      struct mc_pcie *port = irq_data_get_irq_chip_data(data);
--      void __iomem *bridge_base_addr =
--              port->axi_base_addr + MC_PCIE_BRIDGE_ADDR;
--      u32 mask = BIT(data->hwirq + PM_MSI_INT_INTX_SHIFT);
--
--      writel_relaxed(mask, bridge_base_addr + ISTATUS_LOCAL);
--}
--
--static void mc_mask_intx_irq(struct irq_data *data)
--{
--      struct mc_pcie *port = irq_data_get_irq_chip_data(data);
--      void __iomem *bridge_base_addr =
--              port->axi_base_addr + MC_PCIE_BRIDGE_ADDR;
--      unsigned long flags;
--      u32 mask = BIT(data->hwirq + PM_MSI_INT_INTX_SHIFT);
--      u32 val;
--
--      raw_spin_lock_irqsave(&port->lock, flags);
--      val = readl_relaxed(bridge_base_addr + IMASK_LOCAL);
--      val &= ~mask;
--      writel_relaxed(val, bridge_base_addr + IMASK_LOCAL);
--      raw_spin_unlock_irqrestore(&port->lock, flags);
--}
--
--static void mc_unmask_intx_irq(struct irq_data *data)
--{
--      struct mc_pcie *port = irq_data_get_irq_chip_data(data);
--      void __iomem *bridge_base_addr =
--              port->axi_base_addr + MC_PCIE_BRIDGE_ADDR;
--      unsigned long flags;
--      u32 mask = BIT(data->hwirq + PM_MSI_INT_INTX_SHIFT);
--      u32 val;
--
--      raw_spin_lock_irqsave(&port->lock, flags);
--      val = readl_relaxed(bridge_base_addr + IMASK_LOCAL);
--      val |= mask;
--      writel_relaxed(val, bridge_base_addr + IMASK_LOCAL);
--      raw_spin_unlock_irqrestore(&port->lock, flags);
--}
--
--static struct irq_chip mc_intx_irq_chip = {
--      .name = "Microchip PCIe INTx",
--      .irq_ack = mc_ack_intx_irq,
--      .irq_mask = mc_mask_intx_irq,
--      .irq_unmask = mc_unmask_intx_irq,
--};
--
--static int mc_pcie_intx_map(struct irq_domain *domain, unsigned int irq,
--                          irq_hw_number_t hwirq)
--{
--      irq_set_chip_and_handler(irq, &mc_intx_irq_chip, handle_level_irq);
--      irq_set_chip_data(irq, domain->host_data);
--
--      return 0;
--}
--
--static const struct irq_domain_ops intx_domain_ops = {
--      .map = mc_pcie_intx_map,
--};
--
--static inline u32 reg_to_event(u32 reg, struct event_map field)
--{
--      return (reg & field.reg_mask) ? BIT(field.event_bit) : 0;
--}
--
--static u32 pcie_events(struct mc_pcie *port)
--{
--      void __iomem *ctrl_base_addr = port->axi_base_addr + MC_PCIE_CTRL_ADDR;
--      u32 reg = readl_relaxed(ctrl_base_addr + PCIE_EVENT_INT);
--      u32 val = 0;
--      int i;
--
--      for (i = 0; i < ARRAY_SIZE(pcie_event_to_event); i++)
--              val |= reg_to_event(reg, pcie_event_to_event[i]);
--
--      return val;
--}
--
--static u32 sec_errors(struct mc_pcie *port)
--{
--      void __iomem *ctrl_base_addr = port->axi_base_addr + MC_PCIE_CTRL_ADDR;
--      u32 reg = readl_relaxed(ctrl_base_addr + SEC_ERROR_INT);
--      u32 val = 0;
--      int i;
--
--      for (i = 0; i < ARRAY_SIZE(sec_error_to_event); i++)
--              val |= reg_to_event(reg, sec_error_to_event[i]);
--
--      return val;
--}
--
--static u32 ded_errors(struct mc_pcie *port)
--{
--      void __iomem *ctrl_base_addr = port->axi_base_addr + MC_PCIE_CTRL_ADDR;
--      u32 reg = readl_relaxed(ctrl_base_addr + DED_ERROR_INT);
--      u32 val = 0;
--      int i;
--
--      for (i = 0; i < ARRAY_SIZE(ded_error_to_event); i++)
--              val |= reg_to_event(reg, ded_error_to_event[i]);
--
--      return val;
--}
--
--static u32 local_events(struct mc_pcie *port)
--{
--      void __iomem *bridge_base_addr = port->axi_base_addr + MC_PCIE_BRIDGE_ADDR;
--      u32 reg = readl_relaxed(bridge_base_addr + ISTATUS_LOCAL);
--      u32 val = 0;
--      int i;
--
--      for (i = 0; i < ARRAY_SIZE(local_status_to_event); i++)
--              val |= reg_to_event(reg, local_status_to_event[i]);
--
--      return val;
--}
--
--static u32 get_events(struct mc_pcie *port)
--{
--      u32 events = 0;
--
--      events |= pcie_events(port);
--      events |= sec_errors(port);
--      events |= ded_errors(port);
--      events |= local_events(port);
--
--      return events;
--}
--
--static irqreturn_t mc_event_handler(int irq, void *dev_id)
--{
--      struct mc_pcie *port = dev_id;
--      struct device *dev = port->dev;
--      struct irq_data *data;
--
--      data = irq_domain_get_irq_data(port->event_domain, irq);
--
--      if (event_cause[data->hwirq].str)
--              dev_err_ratelimited(dev, "%s\n", event_cause[data->hwirq].str);
--      else
--              dev_err_ratelimited(dev, "bad event IRQ %ld\n", data->hwirq);
--
--      return IRQ_HANDLED;
--}
--
--static void mc_handle_event(struct irq_desc *desc)
--{
--      struct mc_pcie *port = irq_desc_get_handler_data(desc);
--      unsigned long events;
--      u32 bit;
--      struct irq_chip *chip = irq_desc_get_chip(desc);
--
--      chained_irq_enter(chip, desc);
--
--      events = get_events(port);
--
--      for_each_set_bit(bit, &events, NUM_EVENTS)
--              generic_handle_domain_irq(port->event_domain, bit);
--
--      chained_irq_exit(chip, desc);
--}
--
--static void mc_ack_event_irq(struct irq_data *data)
--{
--      struct mc_pcie *port = irq_data_get_irq_chip_data(data);
--      u32 event = data->hwirq;
--      void __iomem *addr;
--      u32 mask;
--
--      addr = port->axi_base_addr + event_descs[event].base +
--              event_descs[event].offset;
--      mask = event_descs[event].mask;
--      mask |= event_descs[event].enb_mask;
--
--      writel_relaxed(mask, addr);
--}
--
--static void mc_mask_event_irq(struct irq_data *data)
--{
--      struct mc_pcie *port = irq_data_get_irq_chip_data(data);
--      u32 event = data->hwirq;
--      void __iomem *addr;
--      u32 mask;
--      u32 val;
--
--      addr = port->axi_base_addr + event_descs[event].base +
--              event_descs[event].mask_offset;
--      mask = event_descs[event].mask;
--      if (event_descs[event].enb_mask) {
--              mask <<= PCIE_EVENT_INT_ENB_SHIFT;
--              mask &= PCIE_EVENT_INT_ENB_MASK;
--      }
--
--      if (!event_descs[event].mask_high)
--              mask = ~mask;
--
--      raw_spin_lock(&port->lock);
--      val = readl_relaxed(addr);
--      if (event_descs[event].mask_high)
--              val |= mask;
--      else
--              val &= mask;
--
--      writel_relaxed(val, addr);
--      raw_spin_unlock(&port->lock);
--}
--
--static void mc_unmask_event_irq(struct irq_data *data)
--{
--      struct mc_pcie *port = irq_data_get_irq_chip_data(data);
--      u32 event = data->hwirq;
--      void __iomem *addr;
--      u32 mask;
--      u32 val;
--
--      addr = port->axi_base_addr + event_descs[event].base +
--              event_descs[event].mask_offset;
--      mask = event_descs[event].mask;
--
--      if (event_descs[event].enb_mask)
--              mask <<= PCIE_EVENT_INT_ENB_SHIFT;
--
--      if (event_descs[event].mask_high)
--              mask = ~mask;
--
--      if (event_descs[event].enb_mask)
--              mask &= PCIE_EVENT_INT_ENB_MASK;
--
--      raw_spin_lock(&port->lock);
--      val = readl_relaxed(addr);
--      if (event_descs[event].mask_high)
--              val &= mask;
--      else
--              val |= mask;
--      writel_relaxed(val, addr);
--      raw_spin_unlock(&port->lock);
--}
--
--static struct irq_chip mc_event_irq_chip = {
--      .name = "Microchip PCIe EVENT",
--      .irq_ack = mc_ack_event_irq,
--      .irq_mask = mc_mask_event_irq,
--      .irq_unmask = mc_unmask_event_irq,
--};
--
--static int mc_pcie_event_map(struct irq_domain *domain, unsigned int irq,
--                           irq_hw_number_t hwirq)
--{
--      irq_set_chip_and_handler(irq, &mc_event_irq_chip, handle_level_irq);
--      irq_set_chip_data(irq, domain->host_data);
--
--      return 0;
--}
--
--static const struct irq_domain_ops event_domain_ops = {
--      .map = mc_pcie_event_map,
--};
--
--static inline void mc_pcie_deinit_clk(void *data)
--{
--      struct clk *clk = data;
--
--      clk_disable_unprepare(clk);
--}
--
--static inline struct clk *mc_pcie_init_clk(struct device *dev, const char *id)
--{
--      struct clk *clk;
--      int ret;
--
--      clk = devm_clk_get_optional(dev, id);
--      if (IS_ERR(clk))
--              return clk;
--      if (!clk)
--              return clk;
--
--      ret = clk_prepare_enable(clk);
--      if (ret)
--              return ERR_PTR(ret);
--
--      devm_add_action_or_reset(dev, mc_pcie_deinit_clk, clk);
--
--      return clk;
--}
--
--static int mc_pcie_init_clks(struct device *dev)
--{
--      int i;
--      struct clk *fic;
--
--      /*
--       * PCIe may be clocked via Fabric Interface using between 1 and 4
--       * clocks. Scan DT for clocks and enable them if present
--       */
--      for (i = 0; i < ARRAY_SIZE(poss_clks); i++) {
--              fic = mc_pcie_init_clk(dev, poss_clks[i]);
--              if (IS_ERR(fic))
--                      return PTR_ERR(fic);
--      }
--
--      return 0;
--}
--
--static int mc_pcie_init_irq_domains(struct mc_pcie *port)
--{
--      struct device *dev = port->dev;
--      struct device_node *node = dev->of_node;
--      struct device_node *pcie_intc_node;
--
--      /* Setup INTx */
--      pcie_intc_node = of_get_next_child(node, NULL);
--      if (!pcie_intc_node) {
--              dev_err(dev, "failed to find PCIe Intc node\n");
--              return -EINVAL;
--      }
--
--      port->event_domain = irq_domain_add_linear(pcie_intc_node, NUM_EVENTS,
--                                                 &event_domain_ops, port);
--      if (!port->event_domain) {
--              dev_err(dev, "failed to get event domain\n");
--              of_node_put(pcie_intc_node);
--              return -ENOMEM;
--      }
--
--      irq_domain_update_bus_token(port->event_domain, DOMAIN_BUS_NEXUS);
--
--      port->intx_domain = irq_domain_add_linear(pcie_intc_node, PCI_NUM_INTX,
--                                                &intx_domain_ops, port);
--      if (!port->intx_domain) {
--              dev_err(dev, "failed to get an INTx IRQ domain\n");
--              of_node_put(pcie_intc_node);
--              return -ENOMEM;
--      }
--
--      irq_domain_update_bus_token(port->intx_domain, DOMAIN_BUS_WIRED);
--
--      of_node_put(pcie_intc_node);
--      raw_spin_lock_init(&port->lock);
--
--      return mc_allocate_msi_domains(port);
--}
--
--static void mc_pcie_setup_window(void __iomem *bridge_base_addr, u32 index,
--                               phys_addr_t axi_addr, phys_addr_t pci_addr,
--                               size_t size)
--{
--      u32 atr_sz = ilog2(size) - 1;
--      u32 val;
--
--      if (index == 0)
--              val = PCIE_CONFIG_INTERFACE;
--      else
--              val = PCIE_TX_RX_INTERFACE;
--
--      writel(val, bridge_base_addr + (index * ATR_ENTRY_SIZE) +
--             ATR0_AXI4_SLV0_TRSL_PARAM);
--
--      val = lower_32_bits(axi_addr) | (atr_sz << ATR_SIZE_SHIFT) |
--                          ATR_IMPL_ENABLE;
--      writel(val, bridge_base_addr + (index * ATR_ENTRY_SIZE) +
--             ATR0_AXI4_SLV0_SRCADDR_PARAM);
--
--      val = upper_32_bits(axi_addr);
--      writel(val, bridge_base_addr + (index * ATR_ENTRY_SIZE) +
--             ATR0_AXI4_SLV0_SRC_ADDR);
--
--      val = lower_32_bits(pci_addr);
--      writel(val, bridge_base_addr + (index * ATR_ENTRY_SIZE) +
--             ATR0_AXI4_SLV0_TRSL_ADDR_LSB);
--
--      val = upper_32_bits(pci_addr);
--      writel(val, bridge_base_addr + (index * ATR_ENTRY_SIZE) +
--             ATR0_AXI4_SLV0_TRSL_ADDR_UDW);
--
--      val = readl(bridge_base_addr + ATR0_PCIE_WIN0_SRCADDR_PARAM);
--      val |= (ATR0_PCIE_ATR_SIZE << ATR0_PCIE_ATR_SIZE_SHIFT);
--      writel(val, bridge_base_addr + ATR0_PCIE_WIN0_SRCADDR_PARAM);
--      writel(0, bridge_base_addr + ATR0_PCIE_WIN0_SRC_ADDR);
--}
--
--static int mc_pcie_setup_windows(struct platform_device *pdev,
--                               struct mc_pcie *port)
--{
--      void __iomem *bridge_base_addr =
--              port->axi_base_addr + MC_PCIE_BRIDGE_ADDR;
--      struct pci_host_bridge *bridge = platform_get_drvdata(pdev);
--      struct resource_entry *entry;
--      u64 pci_addr;
--      u32 index = 1;
--
--      resource_list_for_each_entry(entry, &bridge->windows) {
--              if (resource_type(entry->res) == IORESOURCE_MEM) {
--                      pci_addr = entry->res->start - entry->offset;
--                      mc_pcie_setup_window(bridge_base_addr, index,
--                                           entry->res->start, pci_addr,
--                                           resource_size(entry->res));
--                      index++;
--              }
--      }
--
--      return 0;
--}
--
--static inline void mc_clear_secs(struct mc_pcie *port)
--{
--      void __iomem *ctrl_base_addr = port->axi_base_addr + MC_PCIE_CTRL_ADDR;
--
--      writel_relaxed(SEC_ERROR_INT_ALL_RAM_SEC_ERR_INT, ctrl_base_addr +
--                     SEC_ERROR_INT);
--      writel_relaxed(0, ctrl_base_addr + SEC_ERROR_EVENT_CNT);
--}
--
--static inline void mc_clear_deds(struct mc_pcie *port)
--{
--      void __iomem *ctrl_base_addr = port->axi_base_addr + MC_PCIE_CTRL_ADDR;
--
--      writel_relaxed(DED_ERROR_INT_ALL_RAM_DED_ERR_INT, ctrl_base_addr +
--                     DED_ERROR_INT);
--      writel_relaxed(0, ctrl_base_addr + DED_ERROR_EVENT_CNT);
--}
--
--static void mc_disable_interrupts(struct mc_pcie *port)
--{
--      void __iomem *bridge_base_addr = port->axi_base_addr + MC_PCIE_BRIDGE_ADDR;
--      void __iomem *ctrl_base_addr = port->axi_base_addr + MC_PCIE_CTRL_ADDR;
--      u32 val;
--
--      /* Ensure ECC bypass is enabled */
--      val = ECC_CONTROL_TX_RAM_ECC_BYPASS |
--            ECC_CONTROL_RX_RAM_ECC_BYPASS |
--            ECC_CONTROL_PCIE2AXI_RAM_ECC_BYPASS |
--            ECC_CONTROL_AXI2PCIE_RAM_ECC_BYPASS;
--      writel_relaxed(val, ctrl_base_addr + ECC_CONTROL);
--
--      /* Disable SEC errors and clear any outstanding */
--      writel_relaxed(SEC_ERROR_INT_ALL_RAM_SEC_ERR_INT, ctrl_base_addr +
--                     SEC_ERROR_INT_MASK);
--      mc_clear_secs(port);
--
--      /* Disable DED errors and clear any outstanding */
--      writel_relaxed(DED_ERROR_INT_ALL_RAM_DED_ERR_INT, ctrl_base_addr +
--                     DED_ERROR_INT_MASK);
--      mc_clear_deds(port);
--
--      /* Disable local interrupts and clear any outstanding */
--      writel_relaxed(0, bridge_base_addr + IMASK_LOCAL);
--      writel_relaxed(GENMASK(31, 0), bridge_base_addr + ISTATUS_LOCAL);
--      writel_relaxed(GENMASK(31, 0), bridge_base_addr + ISTATUS_MSI);
--
--      /* Disable PCIe events and clear any outstanding */
--      val = PCIE_EVENT_INT_L2_EXIT_INT |
--            PCIE_EVENT_INT_HOTRST_EXIT_INT |
--            PCIE_EVENT_INT_DLUP_EXIT_INT |
--            PCIE_EVENT_INT_L2_EXIT_INT_MASK |
--            PCIE_EVENT_INT_HOTRST_EXIT_INT_MASK |
--            PCIE_EVENT_INT_DLUP_EXIT_INT_MASK;
--      writel_relaxed(val, ctrl_base_addr + PCIE_EVENT_INT);
--
--      /* Disable host interrupts and clear any outstanding */
--      writel_relaxed(0, bridge_base_addr + IMASK_HOST);
--      writel_relaxed(GENMASK(31, 0), bridge_base_addr + ISTATUS_HOST);
--}
--
--static int mc_init_interrupts(struct platform_device *pdev, struct mc_pcie *port)
--{
--      struct device *dev = &pdev->dev;
--      int irq;
--      int i, intx_irq, msi_irq, event_irq;
--      int ret;
--
--      ret = mc_pcie_init_irq_domains(port);
--      if (ret) {
--              dev_err(dev, "failed creating IRQ domains\n");
--              return ret;
--      }
--
--      irq = platform_get_irq(pdev, 0);
--      if (irq < 0)
--              return -ENODEV;
--
--      for (i = 0; i < NUM_EVENTS; i++) {
--              event_irq = irq_create_mapping(port->event_domain, i);
--              if (!event_irq) {
--                      dev_err(dev, "failed to map hwirq %d\n", i);
--                      return -ENXIO;
--              }
--
--              ret = devm_request_irq(dev, event_irq, mc_event_handler,
--                                     0, event_cause[i].sym, port);
--              if (ret) {
--                      dev_err(dev, "failed to request IRQ %d\n", event_irq);
--                      return ret;
--              }
--      }
--
--      intx_irq = irq_create_mapping(port->event_domain,
--                                    EVENT_LOCAL_PM_MSI_INT_INTX);
--      if (!intx_irq) {
--              dev_err(dev, "failed to map INTx interrupt\n");
--              return -ENXIO;
--      }
--
--      /* Plug the INTx chained handler */
--      irq_set_chained_handler_and_data(intx_irq, mc_handle_intx, port);
--
--      msi_irq = irq_create_mapping(port->event_domain,
--                                   EVENT_LOCAL_PM_MSI_INT_MSI);
--      if (!msi_irq)
--              return -ENXIO;
--
--      /* Plug the MSI chained handler */
--      irq_set_chained_handler_and_data(msi_irq, mc_handle_msi, port);
--
--      /* Plug the main event chained handler */
--      irq_set_chained_handler_and_data(irq, mc_handle_event, port);
--
--      return 0;
--}
--
--static int mc_platform_init(struct pci_config_window *cfg)
--{
--      struct device *dev = cfg->parent;
--      struct platform_device *pdev = to_platform_device(dev);
--      void __iomem *bridge_base_addr =
--              port->axi_base_addr + MC_PCIE_BRIDGE_ADDR;
--      int ret;
--
--      /* Configure address translation table 0 for PCIe config space */
--      mc_pcie_setup_window(bridge_base_addr, 0, cfg->res.start,
--                           cfg->res.start,
--                           resource_size(&cfg->res));
--
--      /* Need some fixups in config space */
--      mc_pcie_enable_msi(port, cfg->win);
--
--      /* Configure non-config space outbound ranges */
--      ret = mc_pcie_setup_windows(pdev, port);
--      if (ret)
--              return ret;
--
--      /* Address translation is up; safe to enable interrupts */
--      ret = mc_init_interrupts(pdev, port);
--      if (ret)
--              return ret;
--
--      return 0;
--}
--
--static int mc_host_probe(struct platform_device *pdev)
--{
--      struct device *dev = &pdev->dev;
--      void __iomem *bridge_base_addr;
--      int ret;
--      u32 val;
--
--      port = devm_kzalloc(dev, sizeof(*port), GFP_KERNEL);
--      if (!port)
--              return -ENOMEM;
--
--      port->dev = dev;
--
--      port->axi_base_addr = devm_platform_ioremap_resource(pdev, 1);
--      if (IS_ERR(port->axi_base_addr))
--              return PTR_ERR(port->axi_base_addr);
--
--      mc_disable_interrupts(port);
--
--      bridge_base_addr = port->axi_base_addr + MC_PCIE_BRIDGE_ADDR;
--
--      /* Allow enabling MSI by disabling MSI-X */
--      val = readl(bridge_base_addr + PCIE_PCI_IRQ_DW0);
--      val &= ~MSIX_CAP_MASK;
--      writel(val, bridge_base_addr + PCIE_PCI_IRQ_DW0);
--
--      /* Pick num vectors from bitfile programmed onto FPGA fabric */
--      val = readl(bridge_base_addr + PCIE_PCI_IRQ_DW0);
--      val &= NUM_MSI_MSGS_MASK;
--      val >>= NUM_MSI_MSGS_SHIFT;
--
--      port->msi.num_vectors = 1 << val;
--
--      /* Pick vector address from design */
--      port->msi.vector_phy = readl_relaxed(bridge_base_addr + IMSI_ADDR);
--
--      ret = mc_pcie_init_clks(dev);
--      if (ret) {
--              dev_err(dev, "failed to get clock resources, error %d\n", ret);
--              return -ENODEV;
--      }
--
--      return pci_host_common_probe(pdev);
--}
--
--static const struct pci_ecam_ops mc_ecam_ops = {
--      .init = mc_platform_init,
--      .pci_ops = {
--              .map_bus = pci_ecam_map_bus,
--              .read = pci_generic_config_read,
--              .write = pci_generic_config_write,
--      }
--};
--
--static const struct of_device_id mc_pcie_of_match[] = {
--      {
--              .compatible = "microchip,pcie-host-1.0",
--              .data = &mc_ecam_ops,
--      },
--      {},
--};
--
--MODULE_DEVICE_TABLE(of, mc_pcie_of_match);
--
--static struct platform_driver mc_pcie_driver = {
--      .probe = mc_host_probe,
--      .driver = {
--              .name = "microchip-pcie",
--              .of_match_table = mc_pcie_of_match,
--              .suppress_bind_attrs = true,
--      },
--};
--
--builtin_platform_driver(mc_pcie_driver);
--MODULE_LICENSE("GPL");
--MODULE_DESCRIPTION("Microchip PCIe host controller driver");
--MODULE_AUTHOR("Daire McNamara <daire.mcnamara@microchip.com>");
---- /dev/null
-+++ b/drivers/pci/controller/plda/pcie-microchip-host.c
-@@ -0,0 +1,1216 @@
-+// SPDX-License-Identifier: GPL-2.0
-+/*
-+ * Microchip AXI PCIe Bridge host controller driver
-+ *
-+ * Copyright (c) 2018 - 2020 Microchip Corporation. All rights reserved.
-+ *
-+ * Author: Daire McNamara <daire.mcnamara@microchip.com>
-+ */
-+
-+#include <linux/bitfield.h>
-+#include <linux/clk.h>
-+#include <linux/irqchip/chained_irq.h>
-+#include <linux/irqdomain.h>
-+#include <linux/module.h>
-+#include <linux/msi.h>
-+#include <linux/of_address.h>
-+#include <linux/of_pci.h>
-+#include <linux/pci-ecam.h>
-+#include <linux/platform_device.h>
-+
-+#include "../../pci.h"
-+
-+/* Number of MSI IRQs */
-+#define MC_MAX_NUM_MSI_IRQS                   32
-+
-+/* PCIe Bridge Phy and Controller Phy offsets */
-+#define MC_PCIE1_BRIDGE_ADDR                  0x00008000u
-+#define MC_PCIE1_CTRL_ADDR                    0x0000a000u
-+
-+#define MC_PCIE_BRIDGE_ADDR                   (MC_PCIE1_BRIDGE_ADDR)
-+#define MC_PCIE_CTRL_ADDR                     (MC_PCIE1_CTRL_ADDR)
-+
-+/* PCIe Bridge Phy Regs */
-+#define PCIE_PCI_IRQ_DW0                      0xa8
-+#define  MSIX_CAP_MASK                                BIT(31)
-+#define  NUM_MSI_MSGS_MASK                    GENMASK(6, 4)
-+#define  NUM_MSI_MSGS_SHIFT                   4
-+
-+#define IMASK_LOCAL                           0x180
-+#define  DMA_END_ENGINE_0_MASK                        0x00000000u
-+#define  DMA_END_ENGINE_0_SHIFT                       0
-+#define  DMA_END_ENGINE_1_MASK                        0x00000000u
-+#define  DMA_END_ENGINE_1_SHIFT                       1
-+#define  DMA_ERROR_ENGINE_0_MASK              0x00000100u
-+#define  DMA_ERROR_ENGINE_0_SHIFT             8
-+#define  DMA_ERROR_ENGINE_1_MASK              0x00000200u
-+#define  DMA_ERROR_ENGINE_1_SHIFT             9
-+#define  A_ATR_EVT_POST_ERR_MASK              0x00010000u
-+#define  A_ATR_EVT_POST_ERR_SHIFT             16
-+#define  A_ATR_EVT_FETCH_ERR_MASK             0x00020000u
-+#define  A_ATR_EVT_FETCH_ERR_SHIFT            17
-+#define  A_ATR_EVT_DISCARD_ERR_MASK           0x00040000u
-+#define  A_ATR_EVT_DISCARD_ERR_SHIFT          18
-+#define  A_ATR_EVT_DOORBELL_MASK              0x00000000u
-+#define  A_ATR_EVT_DOORBELL_SHIFT             19
-+#define  P_ATR_EVT_POST_ERR_MASK              0x00100000u
-+#define  P_ATR_EVT_POST_ERR_SHIFT             20
-+#define  P_ATR_EVT_FETCH_ERR_MASK             0x00200000u
-+#define  P_ATR_EVT_FETCH_ERR_SHIFT            21
-+#define  P_ATR_EVT_DISCARD_ERR_MASK           0x00400000u
-+#define  P_ATR_EVT_DISCARD_ERR_SHIFT          22
-+#define  P_ATR_EVT_DOORBELL_MASK              0x00000000u
-+#define  P_ATR_EVT_DOORBELL_SHIFT             23
-+#define  PM_MSI_INT_INTA_MASK                 0x01000000u
-+#define  PM_MSI_INT_INTA_SHIFT                        24
-+#define  PM_MSI_INT_INTB_MASK                 0x02000000u
-+#define  PM_MSI_INT_INTB_SHIFT                        25
-+#define  PM_MSI_INT_INTC_MASK                 0x04000000u
-+#define  PM_MSI_INT_INTC_SHIFT                        26
-+#define  PM_MSI_INT_INTD_MASK                 0x08000000u
-+#define  PM_MSI_INT_INTD_SHIFT                        27
-+#define  PM_MSI_INT_INTX_MASK                 0x0f000000u
-+#define  PM_MSI_INT_INTX_SHIFT                        24
-+#define  PM_MSI_INT_MSI_MASK                  0x10000000u
-+#define  PM_MSI_INT_MSI_SHIFT                 28
-+#define  PM_MSI_INT_AER_EVT_MASK              0x20000000u
-+#define  PM_MSI_INT_AER_EVT_SHIFT             29
-+#define  PM_MSI_INT_EVENTS_MASK                       0x40000000u
-+#define  PM_MSI_INT_EVENTS_SHIFT              30
-+#define  PM_MSI_INT_SYS_ERR_MASK              0x80000000u
-+#define  PM_MSI_INT_SYS_ERR_SHIFT             31
-+#define  NUM_LOCAL_EVENTS                     15
-+#define ISTATUS_LOCAL                         0x184
-+#define IMASK_HOST                            0x188
-+#define ISTATUS_HOST                          0x18c
-+#define IMSI_ADDR                             0x190
-+#define ISTATUS_MSI                           0x194
-+
-+/* PCIe Master table init defines */
-+#define ATR0_PCIE_WIN0_SRCADDR_PARAM          0x600u
-+#define  ATR0_PCIE_ATR_SIZE                   0x25
-+#define  ATR0_PCIE_ATR_SIZE_SHIFT             1
-+#define ATR0_PCIE_WIN0_SRC_ADDR                       0x604u
-+#define ATR0_PCIE_WIN0_TRSL_ADDR_LSB          0x608u
-+#define ATR0_PCIE_WIN0_TRSL_ADDR_UDW          0x60cu
-+#define ATR0_PCIE_WIN0_TRSL_PARAM             0x610u
-+
-+/* PCIe AXI slave table init defines */
-+#define ATR0_AXI4_SLV0_SRCADDR_PARAM          0x800u
-+#define  ATR_SIZE_SHIFT                               1
-+#define  ATR_IMPL_ENABLE                      1
-+#define ATR0_AXI4_SLV0_SRC_ADDR                       0x804u
-+#define ATR0_AXI4_SLV0_TRSL_ADDR_LSB          0x808u
-+#define ATR0_AXI4_SLV0_TRSL_ADDR_UDW          0x80cu
-+#define ATR0_AXI4_SLV0_TRSL_PARAM             0x810u
-+#define  PCIE_TX_RX_INTERFACE                 0x00000000u
-+#define  PCIE_CONFIG_INTERFACE                        0x00000001u
-+
-+#define ATR_ENTRY_SIZE                                32
-+
-+/* PCIe Controller Phy Regs */
-+#define SEC_ERROR_EVENT_CNT                   0x20
-+#define DED_ERROR_EVENT_CNT                   0x24
-+#define SEC_ERROR_INT                         0x28
-+#define  SEC_ERROR_INT_TX_RAM_SEC_ERR_INT     GENMASK(3, 0)
-+#define  SEC_ERROR_INT_RX_RAM_SEC_ERR_INT     GENMASK(7, 4)
-+#define  SEC_ERROR_INT_PCIE2AXI_RAM_SEC_ERR_INT       GENMASK(11, 8)
-+#define  SEC_ERROR_INT_AXI2PCIE_RAM_SEC_ERR_INT       GENMASK(15, 12)
-+#define  SEC_ERROR_INT_ALL_RAM_SEC_ERR_INT    GENMASK(15, 0)
-+#define  NUM_SEC_ERROR_INTS                   (4)
-+#define SEC_ERROR_INT_MASK                    0x2c
-+#define DED_ERROR_INT                         0x30
-+#define  DED_ERROR_INT_TX_RAM_DED_ERR_INT     GENMASK(3, 0)
-+#define  DED_ERROR_INT_RX_RAM_DED_ERR_INT     GENMASK(7, 4)
-+#define  DED_ERROR_INT_PCIE2AXI_RAM_DED_ERR_INT       GENMASK(11, 8)
-+#define  DED_ERROR_INT_AXI2PCIE_RAM_DED_ERR_INT       GENMASK(15, 12)
-+#define  DED_ERROR_INT_ALL_RAM_DED_ERR_INT    GENMASK(15, 0)
-+#define  NUM_DED_ERROR_INTS                   (4)
-+#define DED_ERROR_INT_MASK                    0x34
-+#define ECC_CONTROL                           0x38
-+#define  ECC_CONTROL_TX_RAM_INJ_ERROR_0               BIT(0)
-+#define  ECC_CONTROL_TX_RAM_INJ_ERROR_1               BIT(1)
-+#define  ECC_CONTROL_TX_RAM_INJ_ERROR_2               BIT(2)
-+#define  ECC_CONTROL_TX_RAM_INJ_ERROR_3               BIT(3)
-+#define  ECC_CONTROL_RX_RAM_INJ_ERROR_0               BIT(4)
-+#define  ECC_CONTROL_RX_RAM_INJ_ERROR_1               BIT(5)
-+#define  ECC_CONTROL_RX_RAM_INJ_ERROR_2               BIT(6)
-+#define  ECC_CONTROL_RX_RAM_INJ_ERROR_3               BIT(7)
-+#define  ECC_CONTROL_PCIE2AXI_RAM_INJ_ERROR_0 BIT(8)
-+#define  ECC_CONTROL_PCIE2AXI_RAM_INJ_ERROR_1 BIT(9)
-+#define  ECC_CONTROL_PCIE2AXI_RAM_INJ_ERROR_2 BIT(10)
-+#define  ECC_CONTROL_PCIE2AXI_RAM_INJ_ERROR_3 BIT(11)
-+#define  ECC_CONTROL_AXI2PCIE_RAM_INJ_ERROR_0 BIT(12)
-+#define  ECC_CONTROL_AXI2PCIE_RAM_INJ_ERROR_1 BIT(13)
-+#define  ECC_CONTROL_AXI2PCIE_RAM_INJ_ERROR_2 BIT(14)
-+#define  ECC_CONTROL_AXI2PCIE_RAM_INJ_ERROR_3 BIT(15)
-+#define  ECC_CONTROL_TX_RAM_ECC_BYPASS                BIT(24)
-+#define  ECC_CONTROL_RX_RAM_ECC_BYPASS                BIT(25)
-+#define  ECC_CONTROL_PCIE2AXI_RAM_ECC_BYPASS  BIT(26)
-+#define  ECC_CONTROL_AXI2PCIE_RAM_ECC_BYPASS  BIT(27)
-+#define PCIE_EVENT_INT                                0x14c
-+#define  PCIE_EVENT_INT_L2_EXIT_INT           BIT(0)
-+#define  PCIE_EVENT_INT_HOTRST_EXIT_INT               BIT(1)
-+#define  PCIE_EVENT_INT_DLUP_EXIT_INT         BIT(2)
-+#define  PCIE_EVENT_INT_MASK                  GENMASK(2, 0)
-+#define  PCIE_EVENT_INT_L2_EXIT_INT_MASK      BIT(16)
-+#define  PCIE_EVENT_INT_HOTRST_EXIT_INT_MASK  BIT(17)
-+#define  PCIE_EVENT_INT_DLUP_EXIT_INT_MASK    BIT(18)
-+#define  PCIE_EVENT_INT_ENB_MASK              GENMASK(18, 16)
-+#define  PCIE_EVENT_INT_ENB_SHIFT             16
-+#define  NUM_PCIE_EVENTS                      (3)
-+
-+/* PCIe Config space MSI capability structure */
-+#define MC_MSI_CAP_CTRL_OFFSET                        0xe0u
-+
-+/* Events */
-+#define EVENT_PCIE_L2_EXIT                    0
-+#define EVENT_PCIE_HOTRST_EXIT                        1
-+#define EVENT_PCIE_DLUP_EXIT                  2
-+#define EVENT_SEC_TX_RAM_SEC_ERR              3
-+#define EVENT_SEC_RX_RAM_SEC_ERR              4
-+#define EVENT_SEC_PCIE2AXI_RAM_SEC_ERR                5
-+#define EVENT_SEC_AXI2PCIE_RAM_SEC_ERR                6
-+#define EVENT_DED_TX_RAM_DED_ERR              7
-+#define EVENT_DED_RX_RAM_DED_ERR              8
-+#define EVENT_DED_PCIE2AXI_RAM_DED_ERR                9
-+#define EVENT_DED_AXI2PCIE_RAM_DED_ERR                10
-+#define EVENT_LOCAL_DMA_END_ENGINE_0          11
-+#define EVENT_LOCAL_DMA_END_ENGINE_1          12
-+#define EVENT_LOCAL_DMA_ERROR_ENGINE_0                13
-+#define EVENT_LOCAL_DMA_ERROR_ENGINE_1                14
-+#define EVENT_LOCAL_A_ATR_EVT_POST_ERR                15
-+#define EVENT_LOCAL_A_ATR_EVT_FETCH_ERR               16
-+#define EVENT_LOCAL_A_ATR_EVT_DISCARD_ERR     17
-+#define EVENT_LOCAL_A_ATR_EVT_DOORBELL                18
-+#define EVENT_LOCAL_P_ATR_EVT_POST_ERR                19
-+#define EVENT_LOCAL_P_ATR_EVT_FETCH_ERR               20
-+#define EVENT_LOCAL_P_ATR_EVT_DISCARD_ERR     21
-+#define EVENT_LOCAL_P_ATR_EVT_DOORBELL                22
-+#define EVENT_LOCAL_PM_MSI_INT_INTX           23
-+#define EVENT_LOCAL_PM_MSI_INT_MSI            24
-+#define EVENT_LOCAL_PM_MSI_INT_AER_EVT                25
-+#define EVENT_LOCAL_PM_MSI_INT_EVENTS         26
-+#define EVENT_LOCAL_PM_MSI_INT_SYS_ERR                27
-+#define NUM_EVENTS                            28
-+
-+#define PCIE_EVENT_CAUSE(x, s)        \
-+      [EVENT_PCIE_ ## x] = { __stringify(x), s }
-+
-+#define SEC_ERROR_CAUSE(x, s) \
-+      [EVENT_SEC_ ## x] = { __stringify(x), s }
-+
-+#define DED_ERROR_CAUSE(x, s) \
-+      [EVENT_DED_ ## x] = { __stringify(x), s }
-+
-+#define LOCAL_EVENT_CAUSE(x, s) \
-+      [EVENT_LOCAL_ ## x] = { __stringify(x), s }
-+
-+#define PCIE_EVENT(x) \
-+      .base = MC_PCIE_CTRL_ADDR, \
-+      .offset = PCIE_EVENT_INT, \
-+      .mask_offset = PCIE_EVENT_INT, \
-+      .mask_high = 1, \
-+      .mask = PCIE_EVENT_INT_ ## x ## _INT, \
-+      .enb_mask = PCIE_EVENT_INT_ENB_MASK
-+
-+#define SEC_EVENT(x) \
-+      .base = MC_PCIE_CTRL_ADDR, \
-+      .offset = SEC_ERROR_INT, \
-+      .mask_offset = SEC_ERROR_INT_MASK, \
-+      .mask = SEC_ERROR_INT_ ## x ## _INT, \
-+      .mask_high = 1, \
-+      .enb_mask = 0
-+
-+#define DED_EVENT(x) \
-+      .base = MC_PCIE_CTRL_ADDR, \
-+      .offset = DED_ERROR_INT, \
-+      .mask_offset = DED_ERROR_INT_MASK, \
-+      .mask_high = 1, \
-+      .mask = DED_ERROR_INT_ ## x ## _INT, \
-+      .enb_mask = 0
-+
-+#define LOCAL_EVENT(x) \
-+      .base = MC_PCIE_BRIDGE_ADDR, \
-+      .offset = ISTATUS_LOCAL, \
-+      .mask_offset = IMASK_LOCAL, \
-+      .mask_high = 0, \
-+      .mask = x ## _MASK, \
-+      .enb_mask = 0
-+
-+#define PCIE_EVENT_TO_EVENT_MAP(x) \
-+      { PCIE_EVENT_INT_ ## x ## _INT, EVENT_PCIE_ ## x }
-+
-+#define SEC_ERROR_TO_EVENT_MAP(x) \
-+      { SEC_ERROR_INT_ ## x ## _INT, EVENT_SEC_ ## x }
-+
-+#define DED_ERROR_TO_EVENT_MAP(x) \
-+      { DED_ERROR_INT_ ## x ## _INT, EVENT_DED_ ## x }
-+
-+#define LOCAL_STATUS_TO_EVENT_MAP(x) \
-+      { x ## _MASK, EVENT_LOCAL_ ## x }
-+
-+struct event_map {
-+      u32 reg_mask;
-+      u32 event_bit;
-+};
-+
-+struct mc_msi {
-+      struct mutex lock;              /* Protect used bitmap */
-+      struct irq_domain *msi_domain;
-+      struct irq_domain *dev_domain;
-+      u32 num_vectors;
-+      u64 vector_phy;
-+      DECLARE_BITMAP(used, MC_MAX_NUM_MSI_IRQS);
-+};
-+
-+struct mc_pcie {
-+      void __iomem *axi_base_addr;
-+      struct device *dev;
-+      struct irq_domain *intx_domain;
-+      struct irq_domain *event_domain;
-+      raw_spinlock_t lock;
-+      struct mc_msi msi;
-+};
-+
-+struct cause {
-+      const char *sym;
-+      const char *str;
-+};
-+
-+static const struct cause event_cause[NUM_EVENTS] = {
-+      PCIE_EVENT_CAUSE(L2_EXIT, "L2 exit event"),
-+      PCIE_EVENT_CAUSE(HOTRST_EXIT, "Hot reset exit event"),
-+      PCIE_EVENT_CAUSE(DLUP_EXIT, "DLUP exit event"),
-+      SEC_ERROR_CAUSE(TX_RAM_SEC_ERR,  "sec error in tx buffer"),
-+      SEC_ERROR_CAUSE(RX_RAM_SEC_ERR,  "sec error in rx buffer"),
-+      SEC_ERROR_CAUSE(PCIE2AXI_RAM_SEC_ERR,  "sec error in pcie2axi buffer"),
-+      SEC_ERROR_CAUSE(AXI2PCIE_RAM_SEC_ERR,  "sec error in axi2pcie buffer"),
-+      DED_ERROR_CAUSE(TX_RAM_DED_ERR,  "ded error in tx buffer"),
-+      DED_ERROR_CAUSE(RX_RAM_DED_ERR,  "ded error in rx buffer"),
-+      DED_ERROR_CAUSE(PCIE2AXI_RAM_DED_ERR,  "ded error in pcie2axi buffer"),
-+      DED_ERROR_CAUSE(AXI2PCIE_RAM_DED_ERR,  "ded error in axi2pcie buffer"),
-+      LOCAL_EVENT_CAUSE(DMA_ERROR_ENGINE_0, "dma engine 0 error"),
-+      LOCAL_EVENT_CAUSE(DMA_ERROR_ENGINE_1, "dma engine 1 error"),
-+      LOCAL_EVENT_CAUSE(A_ATR_EVT_POST_ERR, "axi write request error"),
-+      LOCAL_EVENT_CAUSE(A_ATR_EVT_FETCH_ERR, "axi read request error"),
-+      LOCAL_EVENT_CAUSE(A_ATR_EVT_DISCARD_ERR, "axi read timeout"),
-+      LOCAL_EVENT_CAUSE(P_ATR_EVT_POST_ERR, "pcie write request error"),
-+      LOCAL_EVENT_CAUSE(P_ATR_EVT_FETCH_ERR, "pcie read request error"),
-+      LOCAL_EVENT_CAUSE(P_ATR_EVT_DISCARD_ERR, "pcie read timeout"),
-+      LOCAL_EVENT_CAUSE(PM_MSI_INT_AER_EVT, "aer event"),
-+      LOCAL_EVENT_CAUSE(PM_MSI_INT_EVENTS, "pm/ltr/hotplug event"),
-+      LOCAL_EVENT_CAUSE(PM_MSI_INT_SYS_ERR, "system error"),
-+};
-+
-+static struct event_map pcie_event_to_event[] = {
-+      PCIE_EVENT_TO_EVENT_MAP(L2_EXIT),
-+      PCIE_EVENT_TO_EVENT_MAP(HOTRST_EXIT),
-+      PCIE_EVENT_TO_EVENT_MAP(DLUP_EXIT),
-+};
-+
-+static struct event_map sec_error_to_event[] = {
-+      SEC_ERROR_TO_EVENT_MAP(TX_RAM_SEC_ERR),
-+      SEC_ERROR_TO_EVENT_MAP(RX_RAM_SEC_ERR),
-+      SEC_ERROR_TO_EVENT_MAP(PCIE2AXI_RAM_SEC_ERR),
-+      SEC_ERROR_TO_EVENT_MAP(AXI2PCIE_RAM_SEC_ERR),
-+};
-+
-+static struct event_map ded_error_to_event[] = {
-+      DED_ERROR_TO_EVENT_MAP(TX_RAM_DED_ERR),
-+      DED_ERROR_TO_EVENT_MAP(RX_RAM_DED_ERR),
-+      DED_ERROR_TO_EVENT_MAP(PCIE2AXI_RAM_DED_ERR),
-+      DED_ERROR_TO_EVENT_MAP(AXI2PCIE_RAM_DED_ERR),
-+};
-+
-+static struct event_map local_status_to_event[] = {
-+      LOCAL_STATUS_TO_EVENT_MAP(DMA_END_ENGINE_0),
-+      LOCAL_STATUS_TO_EVENT_MAP(DMA_END_ENGINE_1),
-+      LOCAL_STATUS_TO_EVENT_MAP(DMA_ERROR_ENGINE_0),
-+      LOCAL_STATUS_TO_EVENT_MAP(DMA_ERROR_ENGINE_1),
-+      LOCAL_STATUS_TO_EVENT_MAP(A_ATR_EVT_POST_ERR),
-+      LOCAL_STATUS_TO_EVENT_MAP(A_ATR_EVT_FETCH_ERR),
-+      LOCAL_STATUS_TO_EVENT_MAP(A_ATR_EVT_DISCARD_ERR),
-+      LOCAL_STATUS_TO_EVENT_MAP(A_ATR_EVT_DOORBELL),
-+      LOCAL_STATUS_TO_EVENT_MAP(P_ATR_EVT_POST_ERR),
-+      LOCAL_STATUS_TO_EVENT_MAP(P_ATR_EVT_FETCH_ERR),
-+      LOCAL_STATUS_TO_EVENT_MAP(P_ATR_EVT_DISCARD_ERR),
-+      LOCAL_STATUS_TO_EVENT_MAP(P_ATR_EVT_DOORBELL),
-+      LOCAL_STATUS_TO_EVENT_MAP(PM_MSI_INT_INTX),
-+      LOCAL_STATUS_TO_EVENT_MAP(PM_MSI_INT_MSI),
-+      LOCAL_STATUS_TO_EVENT_MAP(PM_MSI_INT_AER_EVT),
-+      LOCAL_STATUS_TO_EVENT_MAP(PM_MSI_INT_EVENTS),
-+      LOCAL_STATUS_TO_EVENT_MAP(PM_MSI_INT_SYS_ERR),
-+};
-+
-+static struct {
-+      u32 base;
-+      u32 offset;
-+      u32 mask;
-+      u32 shift;
-+      u32 enb_mask;
-+      u32 mask_high;
-+      u32 mask_offset;
-+} event_descs[] = {
-+      { PCIE_EVENT(L2_EXIT) },
-+      { PCIE_EVENT(HOTRST_EXIT) },
-+      { PCIE_EVENT(DLUP_EXIT) },
-+      { SEC_EVENT(TX_RAM_SEC_ERR) },
-+      { SEC_EVENT(RX_RAM_SEC_ERR) },
-+      { SEC_EVENT(PCIE2AXI_RAM_SEC_ERR) },
-+      { SEC_EVENT(AXI2PCIE_RAM_SEC_ERR) },
-+      { DED_EVENT(TX_RAM_DED_ERR) },
-+      { DED_EVENT(RX_RAM_DED_ERR) },
-+      { DED_EVENT(PCIE2AXI_RAM_DED_ERR) },
-+      { DED_EVENT(AXI2PCIE_RAM_DED_ERR) },
-+      { LOCAL_EVENT(DMA_END_ENGINE_0) },
-+      { LOCAL_EVENT(DMA_END_ENGINE_1) },
-+      { LOCAL_EVENT(DMA_ERROR_ENGINE_0) },
-+      { LOCAL_EVENT(DMA_ERROR_ENGINE_1) },
-+      { LOCAL_EVENT(A_ATR_EVT_POST_ERR) },
-+      { LOCAL_EVENT(A_ATR_EVT_FETCH_ERR) },
-+      { LOCAL_EVENT(A_ATR_EVT_DISCARD_ERR) },
-+      { LOCAL_EVENT(A_ATR_EVT_DOORBELL) },
-+      { LOCAL_EVENT(P_ATR_EVT_POST_ERR) },
-+      { LOCAL_EVENT(P_ATR_EVT_FETCH_ERR) },
-+      { LOCAL_EVENT(P_ATR_EVT_DISCARD_ERR) },
-+      { LOCAL_EVENT(P_ATR_EVT_DOORBELL) },
-+      { LOCAL_EVENT(PM_MSI_INT_INTX) },
-+      { LOCAL_EVENT(PM_MSI_INT_MSI) },
-+      { LOCAL_EVENT(PM_MSI_INT_AER_EVT) },
-+      { LOCAL_EVENT(PM_MSI_INT_EVENTS) },
-+      { LOCAL_EVENT(PM_MSI_INT_SYS_ERR) },
-+};
-+
-+static char poss_clks[][5] = { "fic0", "fic1", "fic2", "fic3" };
-+
-+static struct mc_pcie *port;
-+
-+static void mc_pcie_enable_msi(struct mc_pcie *port, void __iomem *ecam)
-+{
-+      struct mc_msi *msi = &port->msi;
-+      u16 reg;
-+      u8 queue_size;
-+
-+      /* Fixup MSI enable flag */
-+      reg = readw_relaxed(ecam + MC_MSI_CAP_CTRL_OFFSET + PCI_MSI_FLAGS);
-+      reg |= PCI_MSI_FLAGS_ENABLE;
-+      writew_relaxed(reg, ecam + MC_MSI_CAP_CTRL_OFFSET + PCI_MSI_FLAGS);
-+
-+      /* Fixup PCI MSI queue flags */
-+      queue_size = FIELD_GET(PCI_MSI_FLAGS_QMASK, reg);
-+      reg |= FIELD_PREP(PCI_MSI_FLAGS_QSIZE, queue_size);
-+      writew_relaxed(reg, ecam + MC_MSI_CAP_CTRL_OFFSET + PCI_MSI_FLAGS);
-+
-+      /* Fixup MSI addr fields */
-+      writel_relaxed(lower_32_bits(msi->vector_phy),
-+                     ecam + MC_MSI_CAP_CTRL_OFFSET + PCI_MSI_ADDRESS_LO);
-+      writel_relaxed(upper_32_bits(msi->vector_phy),
-+                     ecam + MC_MSI_CAP_CTRL_OFFSET + PCI_MSI_ADDRESS_HI);
-+}
-+
-+static void mc_handle_msi(struct irq_desc *desc)
-+{
-+      struct mc_pcie *port = irq_desc_get_handler_data(desc);
-+      struct irq_chip *chip = irq_desc_get_chip(desc);
-+      struct device *dev = port->dev;
-+      struct mc_msi *msi = &port->msi;
-+      void __iomem *bridge_base_addr =
-+              port->axi_base_addr + MC_PCIE_BRIDGE_ADDR;
-+      unsigned long status;
-+      u32 bit;
-+      int ret;
-+
-+      chained_irq_enter(chip, desc);
-+
-+      status = readl_relaxed(bridge_base_addr + ISTATUS_LOCAL);
-+      if (status & PM_MSI_INT_MSI_MASK) {
-+              writel_relaxed(status & PM_MSI_INT_MSI_MASK, bridge_base_addr + ISTATUS_LOCAL);
-+              status = readl_relaxed(bridge_base_addr + ISTATUS_MSI);
-+              for_each_set_bit(bit, &status, msi->num_vectors) {
-+                      ret = generic_handle_domain_irq(msi->dev_domain, bit);
-+                      if (ret)
-+                              dev_err_ratelimited(dev, "bad MSI IRQ %d\n",
-+                                                  bit);
-+              }
-+      }
-+
-+      chained_irq_exit(chip, desc);
-+}
-+
-+static void mc_msi_bottom_irq_ack(struct irq_data *data)
-+{
-+      struct mc_pcie *port = irq_data_get_irq_chip_data(data);
-+      void __iomem *bridge_base_addr =
-+              port->axi_base_addr + MC_PCIE_BRIDGE_ADDR;
-+      u32 bitpos = data->hwirq;
-+
-+      writel_relaxed(BIT(bitpos), bridge_base_addr + ISTATUS_MSI);
-+}
-+
-+static void mc_compose_msi_msg(struct irq_data *data, struct msi_msg *msg)
-+{
-+      struct mc_pcie *port = irq_data_get_irq_chip_data(data);
-+      phys_addr_t addr = port->msi.vector_phy;
-+
-+      msg->address_lo = lower_32_bits(addr);
-+      msg->address_hi = upper_32_bits(addr);
-+      msg->data = data->hwirq;
-+
-+      dev_dbg(port->dev, "msi#%x address_hi %#x address_lo %#x\n",
-+              (int)data->hwirq, msg->address_hi, msg->address_lo);
-+}
-+
-+static int mc_msi_set_affinity(struct irq_data *irq_data,
-+                             const struct cpumask *mask, bool force)
-+{
-+      return -EINVAL;
-+}
-+
-+static struct irq_chip mc_msi_bottom_irq_chip = {
-+      .name = "Microchip MSI",
-+      .irq_ack = mc_msi_bottom_irq_ack,
-+      .irq_compose_msi_msg = mc_compose_msi_msg,
-+      .irq_set_affinity = mc_msi_set_affinity,
-+};
-+
-+static int mc_irq_msi_domain_alloc(struct irq_domain *domain, unsigned int virq,
-+                                 unsigned int nr_irqs, void *args)
-+{
-+      struct mc_pcie *port = domain->host_data;
-+      struct mc_msi *msi = &port->msi;
-+      unsigned long bit;
-+
-+      mutex_lock(&msi->lock);
-+      bit = find_first_zero_bit(msi->used, msi->num_vectors);
-+      if (bit >= msi->num_vectors) {
-+              mutex_unlock(&msi->lock);
-+              return -ENOSPC;
-+      }
-+
-+      set_bit(bit, msi->used);
-+
-+      irq_domain_set_info(domain, virq, bit, &mc_msi_bottom_irq_chip,
-+                          domain->host_data, handle_edge_irq, NULL, NULL);
-+
-+      mutex_unlock(&msi->lock);
-+
-+      return 0;
-+}
-+
-+static void mc_irq_msi_domain_free(struct irq_domain *domain, unsigned int virq,
-+                                 unsigned int nr_irqs)
-+{
-+      struct irq_data *d = irq_domain_get_irq_data(domain, virq);
-+      struct mc_pcie *port = irq_data_get_irq_chip_data(d);
-+      struct mc_msi *msi = &port->msi;
-+
-+      mutex_lock(&msi->lock);
-+
-+      if (test_bit(d->hwirq, msi->used))
-+              __clear_bit(d->hwirq, msi->used);
-+      else
-+              dev_err(port->dev, "trying to free unused MSI%lu\n", d->hwirq);
-+
-+      mutex_unlock(&msi->lock);
-+}
-+
-+static const struct irq_domain_ops msi_domain_ops = {
-+      .alloc  = mc_irq_msi_domain_alloc,
-+      .free   = mc_irq_msi_domain_free,
-+};
-+
-+static struct irq_chip mc_msi_irq_chip = {
-+      .name = "Microchip PCIe MSI",
-+      .irq_ack = irq_chip_ack_parent,
-+      .irq_mask = pci_msi_mask_irq,
-+      .irq_unmask = pci_msi_unmask_irq,
-+};
-+
-+static struct msi_domain_info mc_msi_domain_info = {
-+      .flags = (MSI_FLAG_USE_DEF_DOM_OPS | MSI_FLAG_USE_DEF_CHIP_OPS |
-+                MSI_FLAG_PCI_MSIX),
-+      .chip = &mc_msi_irq_chip,
-+};
-+
-+static int mc_allocate_msi_domains(struct mc_pcie *port)
-+{
-+      struct device *dev = port->dev;
-+      struct fwnode_handle *fwnode = of_node_to_fwnode(dev->of_node);
-+      struct mc_msi *msi = &port->msi;
-+
-+      mutex_init(&port->msi.lock);
-+
-+      msi->dev_domain = irq_domain_add_linear(NULL, msi->num_vectors,
-+                                              &msi_domain_ops, port);
-+      if (!msi->dev_domain) {
-+              dev_err(dev, "failed to create IRQ domain\n");
-+              return -ENOMEM;
-+      }
-+
-+      msi->msi_domain = pci_msi_create_irq_domain(fwnode, &mc_msi_domain_info,
-+                                                  msi->dev_domain);
-+      if (!msi->msi_domain) {
-+              dev_err(dev, "failed to create MSI domain\n");
-+              irq_domain_remove(msi->dev_domain);
-+              return -ENOMEM;
-+      }
-+
-+      return 0;
-+}
-+
-+static void mc_handle_intx(struct irq_desc *desc)
-+{
-+      struct mc_pcie *port = irq_desc_get_handler_data(desc);
-+      struct irq_chip *chip = irq_desc_get_chip(desc);
-+      struct device *dev = port->dev;
-+      void __iomem *bridge_base_addr =
-+              port->axi_base_addr + MC_PCIE_BRIDGE_ADDR;
-+      unsigned long status;
-+      u32 bit;
-+      int ret;
-+
-+      chained_irq_enter(chip, desc);
-+
-+      status = readl_relaxed(bridge_base_addr + ISTATUS_LOCAL);
-+      if (status & PM_MSI_INT_INTX_MASK) {
-+              status &= PM_MSI_INT_INTX_MASK;
-+              status >>= PM_MSI_INT_INTX_SHIFT;
-+              for_each_set_bit(bit, &status, PCI_NUM_INTX) {
-+                      ret = generic_handle_domain_irq(port->intx_domain, bit);
-+                      if (ret)
-+                              dev_err_ratelimited(dev, "bad INTx IRQ %d\n",
-+                                                  bit);
-+              }
-+      }
-+
-+      chained_irq_exit(chip, desc);
-+}
-+
-+static void mc_ack_intx_irq(struct irq_data *data)
-+{
-+      struct mc_pcie *port = irq_data_get_irq_chip_data(data);
-+      void __iomem *bridge_base_addr =
-+              port->axi_base_addr + MC_PCIE_BRIDGE_ADDR;
-+      u32 mask = BIT(data->hwirq + PM_MSI_INT_INTX_SHIFT);
-+
-+      writel_relaxed(mask, bridge_base_addr + ISTATUS_LOCAL);
-+}
-+
-+static void mc_mask_intx_irq(struct irq_data *data)
-+{
-+      struct mc_pcie *port = irq_data_get_irq_chip_data(data);
-+      void __iomem *bridge_base_addr =
-+              port->axi_base_addr + MC_PCIE_BRIDGE_ADDR;
-+      unsigned long flags;
-+      u32 mask = BIT(data->hwirq + PM_MSI_INT_INTX_SHIFT);
-+      u32 val;
-+
-+      raw_spin_lock_irqsave(&port->lock, flags);
-+      val = readl_relaxed(bridge_base_addr + IMASK_LOCAL);
-+      val &= ~mask;
-+      writel_relaxed(val, bridge_base_addr + IMASK_LOCAL);
-+      raw_spin_unlock_irqrestore(&port->lock, flags);
-+}
-+
-+static void mc_unmask_intx_irq(struct irq_data *data)
-+{
-+      struct mc_pcie *port = irq_data_get_irq_chip_data(data);
-+      void __iomem *bridge_base_addr =
-+              port->axi_base_addr + MC_PCIE_BRIDGE_ADDR;
-+      unsigned long flags;
-+      u32 mask = BIT(data->hwirq + PM_MSI_INT_INTX_SHIFT);
-+      u32 val;
-+
-+      raw_spin_lock_irqsave(&port->lock, flags);
-+      val = readl_relaxed(bridge_base_addr + IMASK_LOCAL);
-+      val |= mask;
-+      writel_relaxed(val, bridge_base_addr + IMASK_LOCAL);
-+      raw_spin_unlock_irqrestore(&port->lock, flags);
-+}
-+
-+static struct irq_chip mc_intx_irq_chip = {
-+      .name = "Microchip PCIe INTx",
-+      .irq_ack = mc_ack_intx_irq,
-+      .irq_mask = mc_mask_intx_irq,
-+      .irq_unmask = mc_unmask_intx_irq,
-+};
-+
-+static int mc_pcie_intx_map(struct irq_domain *domain, unsigned int irq,
-+                          irq_hw_number_t hwirq)
-+{
-+      irq_set_chip_and_handler(irq, &mc_intx_irq_chip, handle_level_irq);
-+      irq_set_chip_data(irq, domain->host_data);
-+
-+      return 0;
-+}
-+
-+static const struct irq_domain_ops intx_domain_ops = {
-+      .map = mc_pcie_intx_map,
-+};
-+
-+static inline u32 reg_to_event(u32 reg, struct event_map field)
-+{
-+      return (reg & field.reg_mask) ? BIT(field.event_bit) : 0;
-+}
-+
-+static u32 pcie_events(struct mc_pcie *port)
-+{
-+      void __iomem *ctrl_base_addr = port->axi_base_addr + MC_PCIE_CTRL_ADDR;
-+      u32 reg = readl_relaxed(ctrl_base_addr + PCIE_EVENT_INT);
-+      u32 val = 0;
-+      int i;
-+
-+      for (i = 0; i < ARRAY_SIZE(pcie_event_to_event); i++)
-+              val |= reg_to_event(reg, pcie_event_to_event[i]);
-+
-+      return val;
-+}
-+
-+static u32 sec_errors(struct mc_pcie *port)
-+{
-+      void __iomem *ctrl_base_addr = port->axi_base_addr + MC_PCIE_CTRL_ADDR;
-+      u32 reg = readl_relaxed(ctrl_base_addr + SEC_ERROR_INT);
-+      u32 val = 0;
-+      int i;
-+
-+      for (i = 0; i < ARRAY_SIZE(sec_error_to_event); i++)
-+              val |= reg_to_event(reg, sec_error_to_event[i]);
-+
-+      return val;
-+}
-+
-+static u32 ded_errors(struct mc_pcie *port)
-+{
-+      void __iomem *ctrl_base_addr = port->axi_base_addr + MC_PCIE_CTRL_ADDR;
-+      u32 reg = readl_relaxed(ctrl_base_addr + DED_ERROR_INT);
-+      u32 val = 0;
-+      int i;
-+
-+      for (i = 0; i < ARRAY_SIZE(ded_error_to_event); i++)
-+              val |= reg_to_event(reg, ded_error_to_event[i]);
-+
-+      return val;
-+}
-+
-+static u32 local_events(struct mc_pcie *port)
-+{
-+      void __iomem *bridge_base_addr = port->axi_base_addr + MC_PCIE_BRIDGE_ADDR;
-+      u32 reg = readl_relaxed(bridge_base_addr + ISTATUS_LOCAL);
-+      u32 val = 0;
-+      int i;
-+
-+      for (i = 0; i < ARRAY_SIZE(local_status_to_event); i++)
-+              val |= reg_to_event(reg, local_status_to_event[i]);
-+
-+      return val;
-+}
-+
-+static u32 get_events(struct mc_pcie *port)
-+{
-+      u32 events = 0;
-+
-+      events |= pcie_events(port);
-+      events |= sec_errors(port);
-+      events |= ded_errors(port);
-+      events |= local_events(port);
-+
-+      return events;
-+}
-+
-+static irqreturn_t mc_event_handler(int irq, void *dev_id)
-+{
-+      struct mc_pcie *port = dev_id;
-+      struct device *dev = port->dev;
-+      struct irq_data *data;
-+
-+      data = irq_domain_get_irq_data(port->event_domain, irq);
-+
-+      if (event_cause[data->hwirq].str)
-+              dev_err_ratelimited(dev, "%s\n", event_cause[data->hwirq].str);
-+      else
-+              dev_err_ratelimited(dev, "bad event IRQ %ld\n", data->hwirq);
-+
-+      return IRQ_HANDLED;
-+}
-+
-+static void mc_handle_event(struct irq_desc *desc)
-+{
-+      struct mc_pcie *port = irq_desc_get_handler_data(desc);
-+      unsigned long events;
-+      u32 bit;
-+      struct irq_chip *chip = irq_desc_get_chip(desc);
-+
-+      chained_irq_enter(chip, desc);
-+
-+      events = get_events(port);
-+
-+      for_each_set_bit(bit, &events, NUM_EVENTS)
-+              generic_handle_domain_irq(port->event_domain, bit);
-+
-+      chained_irq_exit(chip, desc);
-+}
-+
-+static void mc_ack_event_irq(struct irq_data *data)
-+{
-+      struct mc_pcie *port = irq_data_get_irq_chip_data(data);
-+      u32 event = data->hwirq;
-+      void __iomem *addr;
-+      u32 mask;
-+
-+      addr = port->axi_base_addr + event_descs[event].base +
-+              event_descs[event].offset;
-+      mask = event_descs[event].mask;
-+      mask |= event_descs[event].enb_mask;
-+
-+      writel_relaxed(mask, addr);
-+}
-+
-+static void mc_mask_event_irq(struct irq_data *data)
-+{
-+      struct mc_pcie *port = irq_data_get_irq_chip_data(data);
-+      u32 event = data->hwirq;
-+      void __iomem *addr;
-+      u32 mask;
-+      u32 val;
-+
-+      addr = port->axi_base_addr + event_descs[event].base +
-+              event_descs[event].mask_offset;
-+      mask = event_descs[event].mask;
-+      if (event_descs[event].enb_mask) {
-+              mask <<= PCIE_EVENT_INT_ENB_SHIFT;
-+              mask &= PCIE_EVENT_INT_ENB_MASK;
-+      }
-+
-+      if (!event_descs[event].mask_high)
-+              mask = ~mask;
-+
-+      raw_spin_lock(&port->lock);
-+      val = readl_relaxed(addr);
-+      if (event_descs[event].mask_high)
-+              val |= mask;
-+      else
-+              val &= mask;
-+
-+      writel_relaxed(val, addr);
-+      raw_spin_unlock(&port->lock);
-+}
-+
-+static void mc_unmask_event_irq(struct irq_data *data)
-+{
-+      struct mc_pcie *port = irq_data_get_irq_chip_data(data);
-+      u32 event = data->hwirq;
-+      void __iomem *addr;
-+      u32 mask;
-+      u32 val;
-+
-+      addr = port->axi_base_addr + event_descs[event].base +
-+              event_descs[event].mask_offset;
-+      mask = event_descs[event].mask;
-+
-+      if (event_descs[event].enb_mask)
-+              mask <<= PCIE_EVENT_INT_ENB_SHIFT;
-+
-+      if (event_descs[event].mask_high)
-+              mask = ~mask;
-+
-+      if (event_descs[event].enb_mask)
-+              mask &= PCIE_EVENT_INT_ENB_MASK;
-+
-+      raw_spin_lock(&port->lock);
-+      val = readl_relaxed(addr);
-+      if (event_descs[event].mask_high)
-+              val &= mask;
-+      else
-+              val |= mask;
-+      writel_relaxed(val, addr);
-+      raw_spin_unlock(&port->lock);
-+}
-+
-+static struct irq_chip mc_event_irq_chip = {
-+      .name = "Microchip PCIe EVENT",
-+      .irq_ack = mc_ack_event_irq,
-+      .irq_mask = mc_mask_event_irq,
-+      .irq_unmask = mc_unmask_event_irq,
-+};
-+
-+static int mc_pcie_event_map(struct irq_domain *domain, unsigned int irq,
-+                           irq_hw_number_t hwirq)
-+{
-+      irq_set_chip_and_handler(irq, &mc_event_irq_chip, handle_level_irq);
-+      irq_set_chip_data(irq, domain->host_data);
-+
-+      return 0;
-+}
-+
-+static const struct irq_domain_ops event_domain_ops = {
-+      .map = mc_pcie_event_map,
-+};
-+
-+static inline void mc_pcie_deinit_clk(void *data)
-+{
-+      struct clk *clk = data;
-+
-+      clk_disable_unprepare(clk);
-+}
-+
-+static inline struct clk *mc_pcie_init_clk(struct device *dev, const char *id)
-+{
-+      struct clk *clk;
-+      int ret;
-+
-+      clk = devm_clk_get_optional(dev, id);
-+      if (IS_ERR(clk))
-+              return clk;
-+      if (!clk)
-+              return clk;
-+
-+      ret = clk_prepare_enable(clk);
-+      if (ret)
-+              return ERR_PTR(ret);
-+
-+      devm_add_action_or_reset(dev, mc_pcie_deinit_clk, clk);
-+
-+      return clk;
-+}
-+
-+static int mc_pcie_init_clks(struct device *dev)
-+{
-+      int i;
-+      struct clk *fic;
-+
-+      /*
-+       * PCIe may be clocked via Fabric Interface using between 1 and 4
-+       * clocks. Scan DT for clocks and enable them if present
-+       */
-+      for (i = 0; i < ARRAY_SIZE(poss_clks); i++) {
-+              fic = mc_pcie_init_clk(dev, poss_clks[i]);
-+              if (IS_ERR(fic))
-+                      return PTR_ERR(fic);
-+      }
-+
-+      return 0;
-+}
-+
-+static int mc_pcie_init_irq_domains(struct mc_pcie *port)
-+{
-+      struct device *dev = port->dev;
-+      struct device_node *node = dev->of_node;
-+      struct device_node *pcie_intc_node;
-+
-+      /* Setup INTx */
-+      pcie_intc_node = of_get_next_child(node, NULL);
-+      if (!pcie_intc_node) {
-+              dev_err(dev, "failed to find PCIe Intc node\n");
-+              return -EINVAL;
-+      }
-+
-+      port->event_domain = irq_domain_add_linear(pcie_intc_node, NUM_EVENTS,
-+                                                 &event_domain_ops, port);
-+      if (!port->event_domain) {
-+              dev_err(dev, "failed to get event domain\n");
-+              of_node_put(pcie_intc_node);
-+              return -ENOMEM;
-+      }
-+
-+      irq_domain_update_bus_token(port->event_domain, DOMAIN_BUS_NEXUS);
-+
-+      port->intx_domain = irq_domain_add_linear(pcie_intc_node, PCI_NUM_INTX,
-+                                                &intx_domain_ops, port);
-+      if (!port->intx_domain) {
-+              dev_err(dev, "failed to get an INTx IRQ domain\n");
-+              of_node_put(pcie_intc_node);
-+              return -ENOMEM;
-+      }
-+
-+      irq_domain_update_bus_token(port->intx_domain, DOMAIN_BUS_WIRED);
-+
-+      of_node_put(pcie_intc_node);
-+      raw_spin_lock_init(&port->lock);
-+
-+      return mc_allocate_msi_domains(port);
-+}
-+
-+static void mc_pcie_setup_window(void __iomem *bridge_base_addr, u32 index,
-+                               phys_addr_t axi_addr, phys_addr_t pci_addr,
-+                               size_t size)
-+{
-+      u32 atr_sz = ilog2(size) - 1;
-+      u32 val;
-+
-+      if (index == 0)
-+              val = PCIE_CONFIG_INTERFACE;
-+      else
-+              val = PCIE_TX_RX_INTERFACE;
-+
-+      writel(val, bridge_base_addr + (index * ATR_ENTRY_SIZE) +
-+             ATR0_AXI4_SLV0_TRSL_PARAM);
-+
-+      val = lower_32_bits(axi_addr) | (atr_sz << ATR_SIZE_SHIFT) |
-+                          ATR_IMPL_ENABLE;
-+      writel(val, bridge_base_addr + (index * ATR_ENTRY_SIZE) +
-+             ATR0_AXI4_SLV0_SRCADDR_PARAM);
-+
-+      val = upper_32_bits(axi_addr);
-+      writel(val, bridge_base_addr + (index * ATR_ENTRY_SIZE) +
-+             ATR0_AXI4_SLV0_SRC_ADDR);
-+
-+      val = lower_32_bits(pci_addr);
-+      writel(val, bridge_base_addr + (index * ATR_ENTRY_SIZE) +
-+             ATR0_AXI4_SLV0_TRSL_ADDR_LSB);
-+
-+      val = upper_32_bits(pci_addr);
-+      writel(val, bridge_base_addr + (index * ATR_ENTRY_SIZE) +
-+             ATR0_AXI4_SLV0_TRSL_ADDR_UDW);
-+
-+      val = readl(bridge_base_addr + ATR0_PCIE_WIN0_SRCADDR_PARAM);
-+      val |= (ATR0_PCIE_ATR_SIZE << ATR0_PCIE_ATR_SIZE_SHIFT);
-+      writel(val, bridge_base_addr + ATR0_PCIE_WIN0_SRCADDR_PARAM);
-+      writel(0, bridge_base_addr + ATR0_PCIE_WIN0_SRC_ADDR);
-+}
-+
-+static int mc_pcie_setup_windows(struct platform_device *pdev,
-+                               struct mc_pcie *port)
-+{
-+      void __iomem *bridge_base_addr =
-+              port->axi_base_addr + MC_PCIE_BRIDGE_ADDR;
-+      struct pci_host_bridge *bridge = platform_get_drvdata(pdev);
-+      struct resource_entry *entry;
-+      u64 pci_addr;
-+      u32 index = 1;
-+
-+      resource_list_for_each_entry(entry, &bridge->windows) {
-+              if (resource_type(entry->res) == IORESOURCE_MEM) {
-+                      pci_addr = entry->res->start - entry->offset;
-+                      mc_pcie_setup_window(bridge_base_addr, index,
-+                                           entry->res->start, pci_addr,
-+                                           resource_size(entry->res));
-+                      index++;
-+              }
-+      }
-+
-+      return 0;
-+}
-+
-+static inline void mc_clear_secs(struct mc_pcie *port)
-+{
-+      void __iomem *ctrl_base_addr = port->axi_base_addr + MC_PCIE_CTRL_ADDR;
-+
-+      writel_relaxed(SEC_ERROR_INT_ALL_RAM_SEC_ERR_INT, ctrl_base_addr +
-+                     SEC_ERROR_INT);
-+      writel_relaxed(0, ctrl_base_addr + SEC_ERROR_EVENT_CNT);
-+}
-+
-+static inline void mc_clear_deds(struct mc_pcie *port)
-+{
-+      void __iomem *ctrl_base_addr = port->axi_base_addr + MC_PCIE_CTRL_ADDR;
-+
-+      writel_relaxed(DED_ERROR_INT_ALL_RAM_DED_ERR_INT, ctrl_base_addr +
-+                     DED_ERROR_INT);
-+      writel_relaxed(0, ctrl_base_addr + DED_ERROR_EVENT_CNT);
-+}
-+
-+static void mc_disable_interrupts(struct mc_pcie *port)
-+{
-+      void __iomem *bridge_base_addr = port->axi_base_addr + MC_PCIE_BRIDGE_ADDR;
-+      void __iomem *ctrl_base_addr = port->axi_base_addr + MC_PCIE_CTRL_ADDR;
-+      u32 val;
-+
-+      /* Ensure ECC bypass is enabled */
-+      val = ECC_CONTROL_TX_RAM_ECC_BYPASS |
-+            ECC_CONTROL_RX_RAM_ECC_BYPASS |
-+            ECC_CONTROL_PCIE2AXI_RAM_ECC_BYPASS |
-+            ECC_CONTROL_AXI2PCIE_RAM_ECC_BYPASS;
-+      writel_relaxed(val, ctrl_base_addr + ECC_CONTROL);
-+
-+      /* Disable SEC errors and clear any outstanding */
-+      writel_relaxed(SEC_ERROR_INT_ALL_RAM_SEC_ERR_INT, ctrl_base_addr +
-+                     SEC_ERROR_INT_MASK);
-+      mc_clear_secs(port);
-+
-+      /* Disable DED errors and clear any outstanding */
-+      writel_relaxed(DED_ERROR_INT_ALL_RAM_DED_ERR_INT, ctrl_base_addr +
-+                     DED_ERROR_INT_MASK);
-+      mc_clear_deds(port);
-+
-+      /* Disable local interrupts and clear any outstanding */
-+      writel_relaxed(0, bridge_base_addr + IMASK_LOCAL);
-+      writel_relaxed(GENMASK(31, 0), bridge_base_addr + ISTATUS_LOCAL);
-+      writel_relaxed(GENMASK(31, 0), bridge_base_addr + ISTATUS_MSI);
-+
-+      /* Disable PCIe events and clear any outstanding */
-+      val = PCIE_EVENT_INT_L2_EXIT_INT |
-+            PCIE_EVENT_INT_HOTRST_EXIT_INT |
-+            PCIE_EVENT_INT_DLUP_EXIT_INT |
-+            PCIE_EVENT_INT_L2_EXIT_INT_MASK |
-+            PCIE_EVENT_INT_HOTRST_EXIT_INT_MASK |
-+            PCIE_EVENT_INT_DLUP_EXIT_INT_MASK;
-+      writel_relaxed(val, ctrl_base_addr + PCIE_EVENT_INT);
-+
-+      /* Disable host interrupts and clear any outstanding */
-+      writel_relaxed(0, bridge_base_addr + IMASK_HOST);
-+      writel_relaxed(GENMASK(31, 0), bridge_base_addr + ISTATUS_HOST);
-+}
-+
-+static int mc_init_interrupts(struct platform_device *pdev, struct mc_pcie *port)
-+{
-+      struct device *dev = &pdev->dev;
-+      int irq;
-+      int i, intx_irq, msi_irq, event_irq;
-+      int ret;
-+
-+      ret = mc_pcie_init_irq_domains(port);
-+      if (ret) {
-+              dev_err(dev, "failed creating IRQ domains\n");
-+              return ret;
-+      }
-+
-+      irq = platform_get_irq(pdev, 0);
-+      if (irq < 0)
-+              return -ENODEV;
-+
-+      for (i = 0; i < NUM_EVENTS; i++) {
-+              event_irq = irq_create_mapping(port->event_domain, i);
-+              if (!event_irq) {
-+                      dev_err(dev, "failed to map hwirq %d\n", i);
-+                      return -ENXIO;
-+              }
-+
-+              ret = devm_request_irq(dev, event_irq, mc_event_handler,
-+                                     0, event_cause[i].sym, port);
-+              if (ret) {
-+                      dev_err(dev, "failed to request IRQ %d\n", event_irq);
-+                      return ret;
-+              }
-+      }
-+
-+      intx_irq = irq_create_mapping(port->event_domain,
-+                                    EVENT_LOCAL_PM_MSI_INT_INTX);
-+      if (!intx_irq) {
-+              dev_err(dev, "failed to map INTx interrupt\n");
-+              return -ENXIO;
-+      }
-+
-+      /* Plug the INTx chained handler */
-+      irq_set_chained_handler_and_data(intx_irq, mc_handle_intx, port);
-+
-+      msi_irq = irq_create_mapping(port->event_domain,
-+                                   EVENT_LOCAL_PM_MSI_INT_MSI);
-+      if (!msi_irq)
-+              return -ENXIO;
-+
-+      /* Plug the MSI chained handler */
-+      irq_set_chained_handler_and_data(msi_irq, mc_handle_msi, port);
-+
-+      /* Plug the main event chained handler */
-+      irq_set_chained_handler_and_data(irq, mc_handle_event, port);
-+
-+      return 0;
-+}
-+
-+static int mc_platform_init(struct pci_config_window *cfg)
-+{
-+      struct device *dev = cfg->parent;
-+      struct platform_device *pdev = to_platform_device(dev);
-+      void __iomem *bridge_base_addr =
-+              port->axi_base_addr + MC_PCIE_BRIDGE_ADDR;
-+      int ret;
-+
-+      /* Configure address translation table 0 for PCIe config space */
-+      mc_pcie_setup_window(bridge_base_addr, 0, cfg->res.start,
-+                           cfg->res.start,
-+                           resource_size(&cfg->res));
-+
-+      /* Need some fixups in config space */
-+      mc_pcie_enable_msi(port, cfg->win);
-+
-+      /* Configure non-config space outbound ranges */
-+      ret = mc_pcie_setup_windows(pdev, port);
-+      if (ret)
-+              return ret;
-+
-+      /* Address translation is up; safe to enable interrupts */
-+      ret = mc_init_interrupts(pdev, port);
-+      if (ret)
-+              return ret;
-+
-+      return 0;
-+}
-+
-+static int mc_host_probe(struct platform_device *pdev)
-+{
-+      struct device *dev = &pdev->dev;
-+      void __iomem *bridge_base_addr;
-+      int ret;
-+      u32 val;
-+
-+      port = devm_kzalloc(dev, sizeof(*port), GFP_KERNEL);
-+      if (!port)
-+              return -ENOMEM;
-+
-+      port->dev = dev;
-+
-+      port->axi_base_addr = devm_platform_ioremap_resource(pdev, 1);
-+      if (IS_ERR(port->axi_base_addr))
-+              return PTR_ERR(port->axi_base_addr);
-+
-+      mc_disable_interrupts(port);
-+
-+      bridge_base_addr = port->axi_base_addr + MC_PCIE_BRIDGE_ADDR;
-+
-+      /* Allow enabling MSI by disabling MSI-X */
-+      val = readl(bridge_base_addr + PCIE_PCI_IRQ_DW0);
-+      val &= ~MSIX_CAP_MASK;
-+      writel(val, bridge_base_addr + PCIE_PCI_IRQ_DW0);
-+
-+      /* Pick num vectors from bitfile programmed onto FPGA fabric */
-+      val = readl(bridge_base_addr + PCIE_PCI_IRQ_DW0);
-+      val &= NUM_MSI_MSGS_MASK;
-+      val >>= NUM_MSI_MSGS_SHIFT;
-+
-+      port->msi.num_vectors = 1 << val;
-+
-+      /* Pick vector address from design */
-+      port->msi.vector_phy = readl_relaxed(bridge_base_addr + IMSI_ADDR);
-+
-+      ret = mc_pcie_init_clks(dev);
-+      if (ret) {
-+              dev_err(dev, "failed to get clock resources, error %d\n", ret);
-+              return -ENODEV;
-+      }
-+
-+      return pci_host_common_probe(pdev);
-+}
-+
-+static const struct pci_ecam_ops mc_ecam_ops = {
-+      .init = mc_platform_init,
-+      .pci_ops = {
-+              .map_bus = pci_ecam_map_bus,
-+              .read = pci_generic_config_read,
-+              .write = pci_generic_config_write,
-+      }
-+};
-+
-+static const struct of_device_id mc_pcie_of_match[] = {
-+      {
-+              .compatible = "microchip,pcie-host-1.0",
-+              .data = &mc_ecam_ops,
-+      },
-+      {},
-+};
-+
-+MODULE_DEVICE_TABLE(of, mc_pcie_of_match);
-+
-+static struct platform_driver mc_pcie_driver = {
-+      .probe = mc_host_probe,
-+      .driver = {
-+              .name = "microchip-pcie",
-+              .of_match_table = mc_pcie_of_match,
-+              .suppress_bind_attrs = true,
-+      },
-+};
-+
-+builtin_platform_driver(mc_pcie_driver);
-+MODULE_LICENSE("GPL");
-+MODULE_DESCRIPTION("Microchip PCIe host controller driver");
-+MODULE_AUTHOR("Daire McNamara <daire.mcnamara@microchip.com>");
diff --git a/target/linux/starfive/patches-6.6/0016-PCI-microchip-Move-PLDA-IP-register-macros-to-pcie-p.patch b/target/linux/starfive/patches-6.6/0016-PCI-microchip-Move-PLDA-IP-register-macros-to-pcie-p.patch
deleted file mode 100644 (file)
index 0aacec2..0000000
+++ /dev/null
@@ -1,259 +0,0 @@
-From eca1b864bb2d4e8d9811506979560a89351c2e37 Mon Sep 17 00:00:00 2001
-From: Minda Chen <minda.chen@starfivetech.com>
-Date: Mon, 8 Jan 2024 19:05:53 +0800
-Subject: [PATCH 016/116] PCI: microchip: Move PLDA IP register macros to
- pcie-plda.h
-
-Move PLDA PCIe host controller IP registers macros to pcie-plda.h,
-including bridge registers and local IRQ event number.
-
-Signed-off-by: Minda Chen <minda.chen@starfivetech.com>
-Reviewed-by: Conor Dooley <conor.dooley@microchip.com>
----
- .../pci/controller/plda/pcie-microchip-host.c | 108 +++---------------
- drivers/pci/controller/plda/pcie-plda.h       | 108 ++++++++++++++++++
- 2 files changed, 124 insertions(+), 92 deletions(-)
- create mode 100644 drivers/pci/controller/plda/pcie-plda.h
-
---- a/drivers/pci/controller/plda/pcie-microchip-host.c
-+++ b/drivers/pci/controller/plda/pcie-microchip-host.c
-@@ -19,6 +19,7 @@
- #include <linux/platform_device.h>
- #include "../../pci.h"
-+#include "pcie-plda.h"
- /* Number of MSI IRQs */
- #define MC_MAX_NUM_MSI_IRQS                   32
-@@ -30,84 +31,6 @@
- #define MC_PCIE_BRIDGE_ADDR                   (MC_PCIE1_BRIDGE_ADDR)
- #define MC_PCIE_CTRL_ADDR                     (MC_PCIE1_CTRL_ADDR)
--/* PCIe Bridge Phy Regs */
--#define PCIE_PCI_IRQ_DW0                      0xa8
--#define  MSIX_CAP_MASK                                BIT(31)
--#define  NUM_MSI_MSGS_MASK                    GENMASK(6, 4)
--#define  NUM_MSI_MSGS_SHIFT                   4
--
--#define IMASK_LOCAL                           0x180
--#define  DMA_END_ENGINE_0_MASK                        0x00000000u
--#define  DMA_END_ENGINE_0_SHIFT                       0
--#define  DMA_END_ENGINE_1_MASK                        0x00000000u
--#define  DMA_END_ENGINE_1_SHIFT                       1
--#define  DMA_ERROR_ENGINE_0_MASK              0x00000100u
--#define  DMA_ERROR_ENGINE_0_SHIFT             8
--#define  DMA_ERROR_ENGINE_1_MASK              0x00000200u
--#define  DMA_ERROR_ENGINE_1_SHIFT             9
--#define  A_ATR_EVT_POST_ERR_MASK              0x00010000u
--#define  A_ATR_EVT_POST_ERR_SHIFT             16
--#define  A_ATR_EVT_FETCH_ERR_MASK             0x00020000u
--#define  A_ATR_EVT_FETCH_ERR_SHIFT            17
--#define  A_ATR_EVT_DISCARD_ERR_MASK           0x00040000u
--#define  A_ATR_EVT_DISCARD_ERR_SHIFT          18
--#define  A_ATR_EVT_DOORBELL_MASK              0x00000000u
--#define  A_ATR_EVT_DOORBELL_SHIFT             19
--#define  P_ATR_EVT_POST_ERR_MASK              0x00100000u
--#define  P_ATR_EVT_POST_ERR_SHIFT             20
--#define  P_ATR_EVT_FETCH_ERR_MASK             0x00200000u
--#define  P_ATR_EVT_FETCH_ERR_SHIFT            21
--#define  P_ATR_EVT_DISCARD_ERR_MASK           0x00400000u
--#define  P_ATR_EVT_DISCARD_ERR_SHIFT          22
--#define  P_ATR_EVT_DOORBELL_MASK              0x00000000u
--#define  P_ATR_EVT_DOORBELL_SHIFT             23
--#define  PM_MSI_INT_INTA_MASK                 0x01000000u
--#define  PM_MSI_INT_INTA_SHIFT                        24
--#define  PM_MSI_INT_INTB_MASK                 0x02000000u
--#define  PM_MSI_INT_INTB_SHIFT                        25
--#define  PM_MSI_INT_INTC_MASK                 0x04000000u
--#define  PM_MSI_INT_INTC_SHIFT                        26
--#define  PM_MSI_INT_INTD_MASK                 0x08000000u
--#define  PM_MSI_INT_INTD_SHIFT                        27
--#define  PM_MSI_INT_INTX_MASK                 0x0f000000u
--#define  PM_MSI_INT_INTX_SHIFT                        24
--#define  PM_MSI_INT_MSI_MASK                  0x10000000u
--#define  PM_MSI_INT_MSI_SHIFT                 28
--#define  PM_MSI_INT_AER_EVT_MASK              0x20000000u
--#define  PM_MSI_INT_AER_EVT_SHIFT             29
--#define  PM_MSI_INT_EVENTS_MASK                       0x40000000u
--#define  PM_MSI_INT_EVENTS_SHIFT              30
--#define  PM_MSI_INT_SYS_ERR_MASK              0x80000000u
--#define  PM_MSI_INT_SYS_ERR_SHIFT             31
--#define  NUM_LOCAL_EVENTS                     15
--#define ISTATUS_LOCAL                         0x184
--#define IMASK_HOST                            0x188
--#define ISTATUS_HOST                          0x18c
--#define IMSI_ADDR                             0x190
--#define ISTATUS_MSI                           0x194
--
--/* PCIe Master table init defines */
--#define ATR0_PCIE_WIN0_SRCADDR_PARAM          0x600u
--#define  ATR0_PCIE_ATR_SIZE                   0x25
--#define  ATR0_PCIE_ATR_SIZE_SHIFT             1
--#define ATR0_PCIE_WIN0_SRC_ADDR                       0x604u
--#define ATR0_PCIE_WIN0_TRSL_ADDR_LSB          0x608u
--#define ATR0_PCIE_WIN0_TRSL_ADDR_UDW          0x60cu
--#define ATR0_PCIE_WIN0_TRSL_PARAM             0x610u
--
--/* PCIe AXI slave table init defines */
--#define ATR0_AXI4_SLV0_SRCADDR_PARAM          0x800u
--#define  ATR_SIZE_SHIFT                               1
--#define  ATR_IMPL_ENABLE                      1
--#define ATR0_AXI4_SLV0_SRC_ADDR                       0x804u
--#define ATR0_AXI4_SLV0_TRSL_ADDR_LSB          0x808u
--#define ATR0_AXI4_SLV0_TRSL_ADDR_UDW          0x80cu
--#define ATR0_AXI4_SLV0_TRSL_PARAM             0x810u
--#define  PCIE_TX_RX_INTERFACE                 0x00000000u
--#define  PCIE_CONFIG_INTERFACE                        0x00000001u
--
--#define ATR_ENTRY_SIZE                                32
--
- /* PCIe Controller Phy Regs */
- #define SEC_ERROR_EVENT_CNT                   0x20
- #define DED_ERROR_EVENT_CNT                   0x24
-@@ -179,20 +102,21 @@
- #define EVENT_LOCAL_DMA_END_ENGINE_1          12
- #define EVENT_LOCAL_DMA_ERROR_ENGINE_0                13
- #define EVENT_LOCAL_DMA_ERROR_ENGINE_1                14
--#define EVENT_LOCAL_A_ATR_EVT_POST_ERR                15
--#define EVENT_LOCAL_A_ATR_EVT_FETCH_ERR               16
--#define EVENT_LOCAL_A_ATR_EVT_DISCARD_ERR     17
--#define EVENT_LOCAL_A_ATR_EVT_DOORBELL                18
--#define EVENT_LOCAL_P_ATR_EVT_POST_ERR                19
--#define EVENT_LOCAL_P_ATR_EVT_FETCH_ERR               20
--#define EVENT_LOCAL_P_ATR_EVT_DISCARD_ERR     21
--#define EVENT_LOCAL_P_ATR_EVT_DOORBELL                22
--#define EVENT_LOCAL_PM_MSI_INT_INTX           23
--#define EVENT_LOCAL_PM_MSI_INT_MSI            24
--#define EVENT_LOCAL_PM_MSI_INT_AER_EVT                25
--#define EVENT_LOCAL_PM_MSI_INT_EVENTS         26
--#define EVENT_LOCAL_PM_MSI_INT_SYS_ERR                27
--#define NUM_EVENTS                            28
-+#define NUM_MC_EVENTS                         15
-+#define EVENT_LOCAL_A_ATR_EVT_POST_ERR                (NUM_MC_EVENTS + PLDA_AXI_POST_ERR)
-+#define EVENT_LOCAL_A_ATR_EVT_FETCH_ERR               (NUM_MC_EVENTS + PLDA_AXI_FETCH_ERR)
-+#define EVENT_LOCAL_A_ATR_EVT_DISCARD_ERR     (NUM_MC_EVENTS + PLDA_AXI_DISCARD_ERR)
-+#define EVENT_LOCAL_A_ATR_EVT_DOORBELL                (NUM_MC_EVENTS + PLDA_AXI_DOORBELL)
-+#define EVENT_LOCAL_P_ATR_EVT_POST_ERR                (NUM_MC_EVENTS + PLDA_PCIE_POST_ERR)
-+#define EVENT_LOCAL_P_ATR_EVT_FETCH_ERR               (NUM_MC_EVENTS + PLDA_PCIE_FETCH_ERR)
-+#define EVENT_LOCAL_P_ATR_EVT_DISCARD_ERR     (NUM_MC_EVENTS + PLDA_PCIE_DISCARD_ERR)
-+#define EVENT_LOCAL_P_ATR_EVT_DOORBELL                (NUM_MC_EVENTS + PLDA_PCIE_DOORBELL)
-+#define EVENT_LOCAL_PM_MSI_INT_INTX           (NUM_MC_EVENTS + PLDA_INTX)
-+#define EVENT_LOCAL_PM_MSI_INT_MSI            (NUM_MC_EVENTS + PLDA_MSI)
-+#define EVENT_LOCAL_PM_MSI_INT_AER_EVT                (NUM_MC_EVENTS + PLDA_AER_EVENT)
-+#define EVENT_LOCAL_PM_MSI_INT_EVENTS         (NUM_MC_EVENTS + PLDA_MISC_EVENTS)
-+#define EVENT_LOCAL_PM_MSI_INT_SYS_ERR                (NUM_MC_EVENTS + PLDA_SYS_ERR)
-+#define NUM_EVENTS                            (NUM_MC_EVENTS + PLDA_INT_EVENT_NUM)
- #define PCIE_EVENT_CAUSE(x, s)        \
-       [EVENT_PCIE_ ## x] = { __stringify(x), s }
---- /dev/null
-+++ b/drivers/pci/controller/plda/pcie-plda.h
-@@ -0,0 +1,108 @@
-+/* SPDX-License-Identifier: GPL-2.0 */
-+/*
-+ * PLDA PCIe host controller driver
-+ */
-+
-+#ifndef _PCIE_PLDA_H
-+#define _PCIE_PLDA_H
-+
-+/* PCIe Bridge Phy Regs */
-+#define PCIE_PCI_IRQ_DW0                      0xa8
-+#define  MSIX_CAP_MASK                                BIT(31)
-+#define  NUM_MSI_MSGS_MASK                    GENMASK(6, 4)
-+#define  NUM_MSI_MSGS_SHIFT                   4
-+
-+#define IMASK_LOCAL                           0x180
-+#define  DMA_END_ENGINE_0_MASK                        0x00000000u
-+#define  DMA_END_ENGINE_0_SHIFT                       0
-+#define  DMA_END_ENGINE_1_MASK                        0x00000000u
-+#define  DMA_END_ENGINE_1_SHIFT                       1
-+#define  DMA_ERROR_ENGINE_0_MASK              0x00000100u
-+#define  DMA_ERROR_ENGINE_0_SHIFT             8
-+#define  DMA_ERROR_ENGINE_1_MASK              0x00000200u
-+#define  DMA_ERROR_ENGINE_1_SHIFT             9
-+#define  A_ATR_EVT_POST_ERR_MASK              0x00010000u
-+#define  A_ATR_EVT_POST_ERR_SHIFT             16
-+#define  A_ATR_EVT_FETCH_ERR_MASK             0x00020000u
-+#define  A_ATR_EVT_FETCH_ERR_SHIFT            17
-+#define  A_ATR_EVT_DISCARD_ERR_MASK           0x00040000u
-+#define  A_ATR_EVT_DISCARD_ERR_SHIFT          18
-+#define  A_ATR_EVT_DOORBELL_MASK              0x00000000u
-+#define  A_ATR_EVT_DOORBELL_SHIFT             19
-+#define  P_ATR_EVT_POST_ERR_MASK              0x00100000u
-+#define  P_ATR_EVT_POST_ERR_SHIFT             20
-+#define  P_ATR_EVT_FETCH_ERR_MASK             0x00200000u
-+#define  P_ATR_EVT_FETCH_ERR_SHIFT            21
-+#define  P_ATR_EVT_DISCARD_ERR_MASK           0x00400000u
-+#define  P_ATR_EVT_DISCARD_ERR_SHIFT          22
-+#define  P_ATR_EVT_DOORBELL_MASK              0x00000000u
-+#define  P_ATR_EVT_DOORBELL_SHIFT             23
-+#define  PM_MSI_INT_INTA_MASK                 0x01000000u
-+#define  PM_MSI_INT_INTA_SHIFT                        24
-+#define  PM_MSI_INT_INTB_MASK                 0x02000000u
-+#define  PM_MSI_INT_INTB_SHIFT                        25
-+#define  PM_MSI_INT_INTC_MASK                 0x04000000u
-+#define  PM_MSI_INT_INTC_SHIFT                        26
-+#define  PM_MSI_INT_INTD_MASK                 0x08000000u
-+#define  PM_MSI_INT_INTD_SHIFT                        27
-+#define  PM_MSI_INT_INTX_MASK                 0x0f000000u
-+#define  PM_MSI_INT_INTX_SHIFT                        24
-+#define  PM_MSI_INT_MSI_MASK                  0x10000000u
-+#define  PM_MSI_INT_MSI_SHIFT                 28
-+#define  PM_MSI_INT_AER_EVT_MASK              0x20000000u
-+#define  PM_MSI_INT_AER_EVT_SHIFT             29
-+#define  PM_MSI_INT_EVENTS_MASK                       0x40000000u
-+#define  PM_MSI_INT_EVENTS_SHIFT              30
-+#define  PM_MSI_INT_SYS_ERR_MASK              0x80000000u
-+#define  PM_MSI_INT_SYS_ERR_SHIFT             31
-+#define  NUM_LOCAL_EVENTS                     15
-+#define ISTATUS_LOCAL                         0x184
-+#define IMASK_HOST                            0x188
-+#define ISTATUS_HOST                          0x18c
-+#define IMSI_ADDR                             0x190
-+#define ISTATUS_MSI                           0x194
-+
-+/* PCIe Master table init defines */
-+#define ATR0_PCIE_WIN0_SRCADDR_PARAM          0x600u
-+#define  ATR0_PCIE_ATR_SIZE                   0x25
-+#define  ATR0_PCIE_ATR_SIZE_SHIFT             1
-+#define ATR0_PCIE_WIN0_SRC_ADDR                       0x604u
-+#define ATR0_PCIE_WIN0_TRSL_ADDR_LSB          0x608u
-+#define ATR0_PCIE_WIN0_TRSL_ADDR_UDW          0x60cu
-+#define ATR0_PCIE_WIN0_TRSL_PARAM             0x610u
-+
-+/* PCIe AXI slave table init defines */
-+#define ATR0_AXI4_SLV0_SRCADDR_PARAM          0x800u
-+#define  ATR_SIZE_SHIFT                               1
-+#define  ATR_IMPL_ENABLE                      1
-+#define ATR0_AXI4_SLV0_SRC_ADDR                       0x804u
-+#define ATR0_AXI4_SLV0_TRSL_ADDR_LSB          0x808u
-+#define ATR0_AXI4_SLV0_TRSL_ADDR_UDW          0x80cu
-+#define ATR0_AXI4_SLV0_TRSL_PARAM             0x810u
-+#define  PCIE_TX_RX_INTERFACE                 0x00000000u
-+#define  PCIE_CONFIG_INTERFACE                        0x00000001u
-+
-+#define ATR_ENTRY_SIZE                                32
-+
-+enum plda_int_event {
-+      PLDA_AXI_POST_ERR,
-+      PLDA_AXI_FETCH_ERR,
-+      PLDA_AXI_DISCARD_ERR,
-+      PLDA_AXI_DOORBELL,
-+      PLDA_PCIE_POST_ERR,
-+      PLDA_PCIE_FETCH_ERR,
-+      PLDA_PCIE_DISCARD_ERR,
-+      PLDA_PCIE_DOORBELL,
-+      PLDA_INTX,
-+      PLDA_MSI,
-+      PLDA_AER_EVENT,
-+      PLDA_MISC_EVENTS,
-+      PLDA_SYS_ERR,
-+      PLDA_INT_EVENT_NUM
-+};
-+
-+#define PLDA_NUM_DMA_EVENTS                   16
-+
-+#define PLDA_MAX_INT_NUM                      (PLDA_NUM_DMA_EVENTS + PLDA_INT_EVENT_NUM)
-+
-+#endif
diff --git a/target/linux/starfive/patches-6.6/0017-PCI-microchip-Add-bridge_addr-field-to-struct-mc_pci.patch b/target/linux/starfive/patches-6.6/0017-PCI-microchip-Add-bridge_addr-field-to-struct-mc_pci.patch
deleted file mode 100644 (file)
index bc3f909..0000000
+++ /dev/null
@@ -1,107 +0,0 @@
-From 6ee4d4568314425079ae88229bb9abbff9b92b8b Mon Sep 17 00:00:00 2001
-From: Minda Chen <minda.chen@starfivetech.com>
-Date: Mon, 8 Jan 2024 19:05:54 +0800
-Subject: [PATCH 017/116] PCI: microchip: Add bridge_addr field to struct
- mc_pcie
-
-For bridge address base is common PLDA field, Add this to struct mc_pcie
-first.
-
-INTx and MSI codes interrupts codes will get the bridge base address from
-port->bridge_addr. These codes will be changed to common codes.
-axi_base_addr is Microchip its own data.
-
-Signed-off-by: Minda Chen <minda.chen@starfivetech.com>
-Reviewed-by: Conor Dooley <conor.dooley@microchip.com>
----
- .../pci/controller/plda/pcie-microchip-host.c | 23 ++++++++-----------
- 1 file changed, 9 insertions(+), 14 deletions(-)
-
---- a/drivers/pci/controller/plda/pcie-microchip-host.c
-+++ b/drivers/pci/controller/plda/pcie-microchip-host.c
-@@ -195,6 +195,7 @@ struct mc_pcie {
-       struct irq_domain *event_domain;
-       raw_spinlock_t lock;
-       struct mc_msi msi;
-+      void __iomem *bridge_addr;
- };
- struct cause {
-@@ -339,8 +340,7 @@ static void mc_handle_msi(struct irq_des
-       struct irq_chip *chip = irq_desc_get_chip(desc);
-       struct device *dev = port->dev;
-       struct mc_msi *msi = &port->msi;
--      void __iomem *bridge_base_addr =
--              port->axi_base_addr + MC_PCIE_BRIDGE_ADDR;
-+      void __iomem *bridge_base_addr = port->bridge_addr;
-       unsigned long status;
-       u32 bit;
-       int ret;
-@@ -365,8 +365,7 @@ static void mc_handle_msi(struct irq_des
- static void mc_msi_bottom_irq_ack(struct irq_data *data)
- {
-       struct mc_pcie *port = irq_data_get_irq_chip_data(data);
--      void __iomem *bridge_base_addr =
--              port->axi_base_addr + MC_PCIE_BRIDGE_ADDR;
-+      void __iomem *bridge_base_addr = port->bridge_addr;
-       u32 bitpos = data->hwirq;
-       writel_relaxed(BIT(bitpos), bridge_base_addr + ISTATUS_MSI);
-@@ -488,8 +487,7 @@ static void mc_handle_intx(struct irq_de
-       struct mc_pcie *port = irq_desc_get_handler_data(desc);
-       struct irq_chip *chip = irq_desc_get_chip(desc);
-       struct device *dev = port->dev;
--      void __iomem *bridge_base_addr =
--              port->axi_base_addr + MC_PCIE_BRIDGE_ADDR;
-+      void __iomem *bridge_base_addr = port->bridge_addr;
-       unsigned long status;
-       u32 bit;
-       int ret;
-@@ -514,8 +512,7 @@ static void mc_handle_intx(struct irq_de
- static void mc_ack_intx_irq(struct irq_data *data)
- {
-       struct mc_pcie *port = irq_data_get_irq_chip_data(data);
--      void __iomem *bridge_base_addr =
--              port->axi_base_addr + MC_PCIE_BRIDGE_ADDR;
-+      void __iomem *bridge_base_addr = port->bridge_addr;
-       u32 mask = BIT(data->hwirq + PM_MSI_INT_INTX_SHIFT);
-       writel_relaxed(mask, bridge_base_addr + ISTATUS_LOCAL);
-@@ -524,8 +521,7 @@ static void mc_ack_intx_irq(struct irq_d
- static void mc_mask_intx_irq(struct irq_data *data)
- {
-       struct mc_pcie *port = irq_data_get_irq_chip_data(data);
--      void __iomem *bridge_base_addr =
--              port->axi_base_addr + MC_PCIE_BRIDGE_ADDR;
-+      void __iomem *bridge_base_addr = port->bridge_addr;
-       unsigned long flags;
-       u32 mask = BIT(data->hwirq + PM_MSI_INT_INTX_SHIFT);
-       u32 val;
-@@ -540,8 +536,7 @@ static void mc_mask_intx_irq(struct irq_
- static void mc_unmask_intx_irq(struct irq_data *data)
- {
-       struct mc_pcie *port = irq_data_get_irq_chip_data(data);
--      void __iomem *bridge_base_addr =
--              port->axi_base_addr + MC_PCIE_BRIDGE_ADDR;
-+      void __iomem *bridge_base_addr = port->bridge_addr;
-       unsigned long flags;
-       u32 mask = BIT(data->hwirq + PM_MSI_INT_INTX_SHIFT);
-       u32 val;
-@@ -896,8 +891,7 @@ static void mc_pcie_setup_window(void __
- static int mc_pcie_setup_windows(struct platform_device *pdev,
-                                struct mc_pcie *port)
- {
--      void __iomem *bridge_base_addr =
--              port->axi_base_addr + MC_PCIE_BRIDGE_ADDR;
-+      void __iomem *bridge_base_addr = port->bridge_addr;
-       struct pci_host_bridge *bridge = platform_get_drvdata(pdev);
-       struct resource_entry *entry;
-       u64 pci_addr;
-@@ -1081,6 +1075,7 @@ static int mc_host_probe(struct platform
-       mc_disable_interrupts(port);
-       bridge_base_addr = port->axi_base_addr + MC_PCIE_BRIDGE_ADDR;
-+      port->bridge_addr = bridge_base_addr;
-       /* Allow enabling MSI by disabling MSI-X */
-       val = readl(bridge_base_addr + PCIE_PCI_IRQ_DW0);
diff --git a/target/linux/starfive/patches-6.6/0018-PCI-microchip-Rename-two-PCIe-data-structures.patch b/target/linux/starfive/patches-6.6/0018-PCI-microchip-Rename-two-PCIe-data-structures.patch
deleted file mode 100644 (file)
index a9e7b89..0000000
+++ /dev/null
@@ -1,347 +0,0 @@
-From 7c1c679bdd0b6b727248edbee77836024c935f91 Mon Sep 17 00:00:00 2001
-From: Minda Chen <minda.chen@starfivetech.com>
-Date: Mon, 8 Jan 2024 19:05:55 +0800
-Subject: [PATCH 018/116] PCI: microchip: Rename two PCIe data structures
-
-Add PLDA PCIe related data structures by rename data structure name from
-mc_* to plda_*.
-
-axi_base_addr is stayed in struct mc_pcie for it's microchip its own data.
-
-The event interrupt codes is still using struct mc_pcie because the event
-interrupt codes can not be re-used.
-
-Signed-off-by: Minda Chen <minda.chen@starfivetech.com>
-Reviewed-by: Conor Dooley <conor.dooley@microchip.com>
----
- .../pci/controller/plda/pcie-microchip-host.c | 96 ++++++++++---------
- 1 file changed, 53 insertions(+), 43 deletions(-)
-
---- a/drivers/pci/controller/plda/pcie-microchip-host.c
-+++ b/drivers/pci/controller/plda/pcie-microchip-host.c
-@@ -22,7 +22,7 @@
- #include "pcie-plda.h"
- /* Number of MSI IRQs */
--#define MC_MAX_NUM_MSI_IRQS                   32
-+#define PLDA_MAX_NUM_MSI_IRQS                 32
- /* PCIe Bridge Phy and Controller Phy offsets */
- #define MC_PCIE1_BRIDGE_ADDR                  0x00008000u
-@@ -179,25 +179,29 @@ struct event_map {
-       u32 event_bit;
- };
--struct mc_msi {
-+struct plda_msi {
-       struct mutex lock;              /* Protect used bitmap */
-       struct irq_domain *msi_domain;
-       struct irq_domain *dev_domain;
-       u32 num_vectors;
-       u64 vector_phy;
--      DECLARE_BITMAP(used, MC_MAX_NUM_MSI_IRQS);
-+      DECLARE_BITMAP(used, PLDA_MAX_NUM_MSI_IRQS);
- };
--struct mc_pcie {
--      void __iomem *axi_base_addr;
-+struct plda_pcie_rp {
-       struct device *dev;
-       struct irq_domain *intx_domain;
-       struct irq_domain *event_domain;
-       raw_spinlock_t lock;
--      struct mc_msi msi;
-+      struct plda_msi msi;
-       void __iomem *bridge_addr;
- };
-+struct mc_pcie {
-+      struct plda_pcie_rp plda;
-+      void __iomem *axi_base_addr;
-+};
-+
- struct cause {
-       const char *sym;
-       const char *str;
-@@ -313,7 +317,7 @@ static struct mc_pcie *port;
- static void mc_pcie_enable_msi(struct mc_pcie *port, void __iomem *ecam)
- {
--      struct mc_msi *msi = &port->msi;
-+      struct plda_msi *msi = &port->plda.msi;
-       u16 reg;
-       u8 queue_size;
-@@ -336,10 +340,10 @@ static void mc_pcie_enable_msi(struct mc
- static void mc_handle_msi(struct irq_desc *desc)
- {
--      struct mc_pcie *port = irq_desc_get_handler_data(desc);
-+      struct plda_pcie_rp *port = irq_desc_get_handler_data(desc);
-       struct irq_chip *chip = irq_desc_get_chip(desc);
-       struct device *dev = port->dev;
--      struct mc_msi *msi = &port->msi;
-+      struct plda_msi *msi = &port->msi;
-       void __iomem *bridge_base_addr = port->bridge_addr;
-       unsigned long status;
-       u32 bit;
-@@ -364,7 +368,7 @@ static void mc_handle_msi(struct irq_des
- static void mc_msi_bottom_irq_ack(struct irq_data *data)
- {
--      struct mc_pcie *port = irq_data_get_irq_chip_data(data);
-+      struct plda_pcie_rp *port = irq_data_get_irq_chip_data(data);
-       void __iomem *bridge_base_addr = port->bridge_addr;
-       u32 bitpos = data->hwirq;
-@@ -373,7 +377,7 @@ static void mc_msi_bottom_irq_ack(struct
- static void mc_compose_msi_msg(struct irq_data *data, struct msi_msg *msg)
- {
--      struct mc_pcie *port = irq_data_get_irq_chip_data(data);
-+      struct plda_pcie_rp *port = irq_data_get_irq_chip_data(data);
-       phys_addr_t addr = port->msi.vector_phy;
-       msg->address_lo = lower_32_bits(addr);
-@@ -400,8 +404,8 @@ static struct irq_chip mc_msi_bottom_irq
- static int mc_irq_msi_domain_alloc(struct irq_domain *domain, unsigned int virq,
-                                  unsigned int nr_irqs, void *args)
- {
--      struct mc_pcie *port = domain->host_data;
--      struct mc_msi *msi = &port->msi;
-+      struct plda_pcie_rp *port = domain->host_data;
-+      struct plda_msi *msi = &port->msi;
-       unsigned long bit;
-       mutex_lock(&msi->lock);
-@@ -425,8 +429,8 @@ static void mc_irq_msi_domain_free(struc
-                                  unsigned int nr_irqs)
- {
-       struct irq_data *d = irq_domain_get_irq_data(domain, virq);
--      struct mc_pcie *port = irq_data_get_irq_chip_data(d);
--      struct mc_msi *msi = &port->msi;
-+      struct plda_pcie_rp *port = irq_data_get_irq_chip_data(d);
-+      struct plda_msi *msi = &port->msi;
-       mutex_lock(&msi->lock);
-@@ -456,11 +460,11 @@ static struct msi_domain_info mc_msi_dom
-       .chip = &mc_msi_irq_chip,
- };
--static int mc_allocate_msi_domains(struct mc_pcie *port)
-+static int mc_allocate_msi_domains(struct plda_pcie_rp *port)
- {
-       struct device *dev = port->dev;
-       struct fwnode_handle *fwnode = of_node_to_fwnode(dev->of_node);
--      struct mc_msi *msi = &port->msi;
-+      struct plda_msi *msi = &port->msi;
-       mutex_init(&port->msi.lock);
-@@ -484,7 +488,7 @@ static int mc_allocate_msi_domains(struc
- static void mc_handle_intx(struct irq_desc *desc)
- {
--      struct mc_pcie *port = irq_desc_get_handler_data(desc);
-+      struct plda_pcie_rp *port = irq_desc_get_handler_data(desc);
-       struct irq_chip *chip = irq_desc_get_chip(desc);
-       struct device *dev = port->dev;
-       void __iomem *bridge_base_addr = port->bridge_addr;
-@@ -511,7 +515,7 @@ static void mc_handle_intx(struct irq_de
- static void mc_ack_intx_irq(struct irq_data *data)
- {
--      struct mc_pcie *port = irq_data_get_irq_chip_data(data);
-+      struct plda_pcie_rp *port = irq_data_get_irq_chip_data(data);
-       void __iomem *bridge_base_addr = port->bridge_addr;
-       u32 mask = BIT(data->hwirq + PM_MSI_INT_INTX_SHIFT);
-@@ -520,7 +524,7 @@ static void mc_ack_intx_irq(struct irq_d
- static void mc_mask_intx_irq(struct irq_data *data)
- {
--      struct mc_pcie *port = irq_data_get_irq_chip_data(data);
-+      struct plda_pcie_rp *port = irq_data_get_irq_chip_data(data);
-       void __iomem *bridge_base_addr = port->bridge_addr;
-       unsigned long flags;
-       u32 mask = BIT(data->hwirq + PM_MSI_INT_INTX_SHIFT);
-@@ -535,7 +539,7 @@ static void mc_mask_intx_irq(struct irq_
- static void mc_unmask_intx_irq(struct irq_data *data)
- {
--      struct mc_pcie *port = irq_data_get_irq_chip_data(data);
-+      struct plda_pcie_rp *port = irq_data_get_irq_chip_data(data);
-       void __iomem *bridge_base_addr = port->bridge_addr;
-       unsigned long flags;
-       u32 mask = BIT(data->hwirq + PM_MSI_INT_INTX_SHIFT);
-@@ -625,21 +629,22 @@ static u32 local_events(struct mc_pcie *
-       return val;
- }
--static u32 get_events(struct mc_pcie *port)
-+static u32 get_events(struct plda_pcie_rp *port)
- {
-+      struct mc_pcie *mc_port = container_of(port, struct mc_pcie, plda);
-       u32 events = 0;
--      events |= pcie_events(port);
--      events |= sec_errors(port);
--      events |= ded_errors(port);
--      events |= local_events(port);
-+      events |= pcie_events(mc_port);
-+      events |= sec_errors(mc_port);
-+      events |= ded_errors(mc_port);
-+      events |= local_events(mc_port);
-       return events;
- }
- static irqreturn_t mc_event_handler(int irq, void *dev_id)
- {
--      struct mc_pcie *port = dev_id;
-+      struct plda_pcie_rp *port = dev_id;
-       struct device *dev = port->dev;
-       struct irq_data *data;
-@@ -655,7 +660,7 @@ static irqreturn_t mc_event_handler(int
- static void mc_handle_event(struct irq_desc *desc)
- {
--      struct mc_pcie *port = irq_desc_get_handler_data(desc);
-+      struct plda_pcie_rp *port = irq_desc_get_handler_data(desc);
-       unsigned long events;
-       u32 bit;
-       struct irq_chip *chip = irq_desc_get_chip(desc);
-@@ -672,12 +677,13 @@ static void mc_handle_event(struct irq_d
- static void mc_ack_event_irq(struct irq_data *data)
- {
--      struct mc_pcie *port = irq_data_get_irq_chip_data(data);
-+      struct plda_pcie_rp *port = irq_data_get_irq_chip_data(data);
-+      struct mc_pcie *mc_port = container_of(port, struct mc_pcie, plda);
-       u32 event = data->hwirq;
-       void __iomem *addr;
-       u32 mask;
--      addr = port->axi_base_addr + event_descs[event].base +
-+      addr = mc_port->axi_base_addr + event_descs[event].base +
-               event_descs[event].offset;
-       mask = event_descs[event].mask;
-       mask |= event_descs[event].enb_mask;
-@@ -687,13 +693,14 @@ static void mc_ack_event_irq(struct irq_
- static void mc_mask_event_irq(struct irq_data *data)
- {
--      struct mc_pcie *port = irq_data_get_irq_chip_data(data);
-+      struct plda_pcie_rp *port = irq_data_get_irq_chip_data(data);
-+      struct mc_pcie *mc_port = container_of(port, struct mc_pcie, plda);
-       u32 event = data->hwirq;
-       void __iomem *addr;
-       u32 mask;
-       u32 val;
--      addr = port->axi_base_addr + event_descs[event].base +
-+      addr = mc_port->axi_base_addr + event_descs[event].base +
-               event_descs[event].mask_offset;
-       mask = event_descs[event].mask;
-       if (event_descs[event].enb_mask) {
-@@ -717,13 +724,14 @@ static void mc_mask_event_irq(struct irq
- static void mc_unmask_event_irq(struct irq_data *data)
- {
--      struct mc_pcie *port = irq_data_get_irq_chip_data(data);
-+      struct plda_pcie_rp *port = irq_data_get_irq_chip_data(data);
-+      struct mc_pcie *mc_port = container_of(port, struct mc_pcie, plda);
-       u32 event = data->hwirq;
-       void __iomem *addr;
-       u32 mask;
-       u32 val;
--      addr = port->axi_base_addr + event_descs[event].base +
-+      addr = mc_port->axi_base_addr + event_descs[event].base +
-               event_descs[event].mask_offset;
-       mask = event_descs[event].mask;
-@@ -811,7 +819,7 @@ static int mc_pcie_init_clks(struct devi
-       return 0;
- }
--static int mc_pcie_init_irq_domains(struct mc_pcie *port)
-+static int mc_pcie_init_irq_domains(struct plda_pcie_rp *port)
- {
-       struct device *dev = port->dev;
-       struct device_node *node = dev->of_node;
-@@ -889,7 +897,7 @@ static void mc_pcie_setup_window(void __
- }
- static int mc_pcie_setup_windows(struct platform_device *pdev,
--                               struct mc_pcie *port)
-+                               struct plda_pcie_rp *port)
- {
-       void __iomem *bridge_base_addr = port->bridge_addr;
-       struct pci_host_bridge *bridge = platform_get_drvdata(pdev);
-@@ -970,7 +978,7 @@ static void mc_disable_interrupts(struct
-       writel_relaxed(GENMASK(31, 0), bridge_base_addr + ISTATUS_HOST);
- }
--static int mc_init_interrupts(struct platform_device *pdev, struct mc_pcie *port)
-+static int mc_init_interrupts(struct platform_device *pdev, struct plda_pcie_rp *port)
- {
-       struct device *dev = &pdev->dev;
-       int irq;
-@@ -1043,12 +1051,12 @@ static int mc_platform_init(struct pci_c
-       mc_pcie_enable_msi(port, cfg->win);
-       /* Configure non-config space outbound ranges */
--      ret = mc_pcie_setup_windows(pdev, port);
-+      ret = mc_pcie_setup_windows(pdev, &port->plda);
-       if (ret)
-               return ret;
-       /* Address translation is up; safe to enable interrupts */
--      ret = mc_init_interrupts(pdev, port);
-+      ret = mc_init_interrupts(pdev, &port->plda);
-       if (ret)
-               return ret;
-@@ -1059,6 +1067,7 @@ static int mc_host_probe(struct platform
- {
-       struct device *dev = &pdev->dev;
-       void __iomem *bridge_base_addr;
-+      struct plda_pcie_rp *plda;
-       int ret;
-       u32 val;
-@@ -1066,7 +1075,8 @@ static int mc_host_probe(struct platform
-       if (!port)
-               return -ENOMEM;
--      port->dev = dev;
-+      plda = &port->plda;
-+      plda->dev = dev;
-       port->axi_base_addr = devm_platform_ioremap_resource(pdev, 1);
-       if (IS_ERR(port->axi_base_addr))
-@@ -1075,7 +1085,7 @@ static int mc_host_probe(struct platform
-       mc_disable_interrupts(port);
-       bridge_base_addr = port->axi_base_addr + MC_PCIE_BRIDGE_ADDR;
--      port->bridge_addr = bridge_base_addr;
-+      plda->bridge_addr = bridge_base_addr;
-       /* Allow enabling MSI by disabling MSI-X */
-       val = readl(bridge_base_addr + PCIE_PCI_IRQ_DW0);
-@@ -1087,10 +1097,10 @@ static int mc_host_probe(struct platform
-       val &= NUM_MSI_MSGS_MASK;
-       val >>= NUM_MSI_MSGS_SHIFT;
--      port->msi.num_vectors = 1 << val;
-+      plda->msi.num_vectors = 1 << val;
-       /* Pick vector address from design */
--      port->msi.vector_phy = readl_relaxed(bridge_base_addr + IMSI_ADDR);
-+      plda->msi.vector_phy = readl_relaxed(bridge_base_addr + IMSI_ADDR);
-       ret = mc_pcie_init_clks(dev);
-       if (ret) {
diff --git a/target/linux/starfive/patches-6.6/0019-PCI-microchip-Move-PCIe-host-data-structures-to-plda.patch b/target/linux/starfive/patches-6.6/0019-PCI-microchip-Move-PCIe-host-data-structures-to-plda.patch
deleted file mode 100644 (file)
index 0823502..0000000
+++ /dev/null
@@ -1,87 +0,0 @@
-From a53cf9b237dd53c9538b51a8df592888935c8411 Mon Sep 17 00:00:00 2001
-From: Minda Chen <minda.chen@starfivetech.com>
-Date: Mon, 8 Jan 2024 19:05:56 +0800
-Subject: [PATCH 019/116] PCI: microchip: Move PCIe host data structures to
- plda-pcie.h
-
-Move the common data structures definition to head file for these two data
-structures can be re-used.
-
-Signed-off-by: Minda Chen <minda.chen@starfivetech.com>
-Reviewed-by: Conor Dooley <conor.dooley@microchip.com>
----
- .../pci/controller/plda/pcie-microchip-host.c | 20 ------------------
- drivers/pci/controller/plda/pcie-plda.h       | 21 +++++++++++++++++++
- 2 files changed, 21 insertions(+), 20 deletions(-)
-
---- a/drivers/pci/controller/plda/pcie-microchip-host.c
-+++ b/drivers/pci/controller/plda/pcie-microchip-host.c
-@@ -21,9 +21,6 @@
- #include "../../pci.h"
- #include "pcie-plda.h"
--/* Number of MSI IRQs */
--#define PLDA_MAX_NUM_MSI_IRQS                 32
--
- /* PCIe Bridge Phy and Controller Phy offsets */
- #define MC_PCIE1_BRIDGE_ADDR                  0x00008000u
- #define MC_PCIE1_CTRL_ADDR                    0x0000a000u
-@@ -179,23 +176,6 @@ struct event_map {
-       u32 event_bit;
- };
--struct plda_msi {
--      struct mutex lock;              /* Protect used bitmap */
--      struct irq_domain *msi_domain;
--      struct irq_domain *dev_domain;
--      u32 num_vectors;
--      u64 vector_phy;
--      DECLARE_BITMAP(used, PLDA_MAX_NUM_MSI_IRQS);
--};
--
--struct plda_pcie_rp {
--      struct device *dev;
--      struct irq_domain *intx_domain;
--      struct irq_domain *event_domain;
--      raw_spinlock_t lock;
--      struct plda_msi msi;
--      void __iomem *bridge_addr;
--};
- struct mc_pcie {
-       struct plda_pcie_rp plda;
---- a/drivers/pci/controller/plda/pcie-plda.h
-+++ b/drivers/pci/controller/plda/pcie-plda.h
-@@ -6,6 +6,9 @@
- #ifndef _PCIE_PLDA_H
- #define _PCIE_PLDA_H
-+/* Number of MSI IRQs */
-+#define PLDA_MAX_NUM_MSI_IRQS                 32
-+
- /* PCIe Bridge Phy Regs */
- #define PCIE_PCI_IRQ_DW0                      0xa8
- #define  MSIX_CAP_MASK                                BIT(31)
-@@ -105,4 +108,22 @@ enum plda_int_event {
- #define PLDA_MAX_INT_NUM                      (PLDA_NUM_DMA_EVENTS + PLDA_INT_EVENT_NUM)
-+struct plda_msi {
-+      struct mutex lock;              /* Protect used bitmap */
-+      struct irq_domain *msi_domain;
-+      struct irq_domain *dev_domain;
-+      u32 num_vectors;
-+      u64 vector_phy;
-+      DECLARE_BITMAP(used, PLDA_MAX_NUM_MSI_IRQS);
-+};
-+
-+struct plda_pcie_rp {
-+      struct device *dev;
-+      struct irq_domain *intx_domain;
-+      struct irq_domain *event_domain;
-+      raw_spinlock_t lock;
-+      struct plda_msi msi;
-+      void __iomem *bridge_addr;
-+};
-+
- #endif
diff --git a/target/linux/starfive/patches-6.6/0020-PCI-microchip-Rename-two-setup-functions.patch b/target/linux/starfive/patches-6.6/0020-PCI-microchip-Rename-two-setup-functions.patch
deleted file mode 100644 (file)
index 2bed600..0000000
+++ /dev/null
@@ -1,76 +0,0 @@
-From d0e56d1ef7398bbf76be6e48d77943cbf644688e Mon Sep 17 00:00:00 2001
-From: Minda Chen <minda.chen@starfivetech.com>
-Date: Mon, 8 Jan 2024 19:05:57 +0800
-Subject: [PATCH 020/116] PCI: microchip: Rename two setup functions
-
-Rename two setup functions to plda prefix. Prepare to re-use these two
-setup function.
-
-For two setup functions names are similar, rename mc_pcie_setup_windows()
-to plda_pcie_setup_iomems().
-
-Signed-off-by: Minda Chen <minda.chen@starfivetech.com>
-Reviewed-by: Conor Dooley <conor.dooley@microchip.com>
----
- .../pci/controller/plda/pcie-microchip-host.c | 24 +++++++++----------
- 1 file changed, 12 insertions(+), 12 deletions(-)
-
---- a/drivers/pci/controller/plda/pcie-microchip-host.c
-+++ b/drivers/pci/controller/plda/pcie-microchip-host.c
-@@ -838,9 +838,9 @@ static int mc_pcie_init_irq_domains(stru
-       return mc_allocate_msi_domains(port);
- }
--static void mc_pcie_setup_window(void __iomem *bridge_base_addr, u32 index,
--                               phys_addr_t axi_addr, phys_addr_t pci_addr,
--                               size_t size)
-+static void plda_pcie_setup_window(void __iomem *bridge_base_addr, u32 index,
-+                                 phys_addr_t axi_addr, phys_addr_t pci_addr,
-+                                 size_t size)
- {
-       u32 atr_sz = ilog2(size) - 1;
-       u32 val;
-@@ -876,8 +876,8 @@ static void mc_pcie_setup_window(void __
-       writel(0, bridge_base_addr + ATR0_PCIE_WIN0_SRC_ADDR);
- }
--static int mc_pcie_setup_windows(struct platform_device *pdev,
--                               struct plda_pcie_rp *port)
-+static int plda_pcie_setup_iomems(struct platform_device *pdev,
-+                                struct plda_pcie_rp *port)
- {
-       void __iomem *bridge_base_addr = port->bridge_addr;
-       struct pci_host_bridge *bridge = platform_get_drvdata(pdev);
-@@ -888,9 +888,9 @@ static int mc_pcie_setup_windows(struct
-       resource_list_for_each_entry(entry, &bridge->windows) {
-               if (resource_type(entry->res) == IORESOURCE_MEM) {
-                       pci_addr = entry->res->start - entry->offset;
--                      mc_pcie_setup_window(bridge_base_addr, index,
--                                           entry->res->start, pci_addr,
--                                           resource_size(entry->res));
-+                      plda_pcie_setup_window(bridge_base_addr, index,
-+                                             entry->res->start, pci_addr,
-+                                             resource_size(entry->res));
-                       index++;
-               }
-       }
-@@ -1023,15 +1023,15 @@ static int mc_platform_init(struct pci_c
-       int ret;
-       /* Configure address translation table 0 for PCIe config space */
--      mc_pcie_setup_window(bridge_base_addr, 0, cfg->res.start,
--                           cfg->res.start,
--                           resource_size(&cfg->res));
-+      plda_pcie_setup_window(bridge_base_addr, 0, cfg->res.start,
-+                             cfg->res.start,
-+                             resource_size(&cfg->res));
-       /* Need some fixups in config space */
-       mc_pcie_enable_msi(port, cfg->win);
-       /* Configure non-config space outbound ranges */
--      ret = mc_pcie_setup_windows(pdev, &port->plda);
-+      ret = plda_pcie_setup_iomems(pdev, &port->plda);
-       if (ret)
-               return ret;
diff --git a/target/linux/starfive/patches-6.6/0021-PCI-microchip-Change-the-argument-of-plda_pcie_setup.patch b/target/linux/starfive/patches-6.6/0021-PCI-microchip-Change-the-argument-of-plda_pcie_setup.patch
deleted file mode 100644 (file)
index de6868b..0000000
+++ /dev/null
@@ -1,49 +0,0 @@
-From 2fd7c88ef318fd39023ce1eb73f37a29fbd25d74 Mon Sep 17 00:00:00 2001
-From: Minda Chen <minda.chen@starfivetech.com>
-Date: Mon, 8 Jan 2024 19:05:58 +0800
-Subject: [PATCH 021/116] PCI: microchip: Change the argument of
- plda_pcie_setup_iomems()
-
-If other vendor do not select PCI_HOST_COMMON, the driver data is not
-struct pci_host_bridge.
-
-Move calling platform_get_drvdata() to mc_platform_init().
-
-Signed-off-by: Minda Chen <minda.chen@starfivetech.com>
-Reviewed-by: Conor Dooley <conor.dooley@microchip.com>
----
- drivers/pci/controller/plda/pcie-microchip-host.c | 6 +++---
- 1 file changed, 3 insertions(+), 3 deletions(-)
-
---- a/drivers/pci/controller/plda/pcie-microchip-host.c
-+++ b/drivers/pci/controller/plda/pcie-microchip-host.c
-@@ -876,11 +876,10 @@ static void plda_pcie_setup_window(void
-       writel(0, bridge_base_addr + ATR0_PCIE_WIN0_SRC_ADDR);
- }
--static int plda_pcie_setup_iomems(struct platform_device *pdev,
-+static int plda_pcie_setup_iomems(struct pci_host_bridge *bridge,
-                                 struct plda_pcie_rp *port)
- {
-       void __iomem *bridge_base_addr = port->bridge_addr;
--      struct pci_host_bridge *bridge = platform_get_drvdata(pdev);
-       struct resource_entry *entry;
-       u64 pci_addr;
-       u32 index = 1;
-@@ -1018,6 +1017,7 @@ static int mc_platform_init(struct pci_c
- {
-       struct device *dev = cfg->parent;
-       struct platform_device *pdev = to_platform_device(dev);
-+      struct pci_host_bridge *bridge = platform_get_drvdata(pdev);
-       void __iomem *bridge_base_addr =
-               port->axi_base_addr + MC_PCIE_BRIDGE_ADDR;
-       int ret;
-@@ -1031,7 +1031,7 @@ static int mc_platform_init(struct pci_c
-       mc_pcie_enable_msi(port, cfg->win);
-       /* Configure non-config space outbound ranges */
--      ret = plda_pcie_setup_iomems(pdev, &port->plda);
-+      ret = plda_pcie_setup_iomems(bridge, &port->plda);
-       if (ret)
-               return ret;
diff --git a/target/linux/starfive/patches-6.6/0022-PCI-microchip-Move-setup-functions-to-pcie-plda-host.patch b/target/linux/starfive/patches-6.6/0022-PCI-microchip-Move-setup-functions-to-pcie-plda-host.patch
deleted file mode 100644 (file)
index 62f458b..0000000
+++ /dev/null
@@ -1,200 +0,0 @@
-From 201ce99897ff5fff2612cb633406e90c1b2acbcf Mon Sep 17 00:00:00 2001
-From: Minda Chen <minda.chen@starfivetech.com>
-Date: Mon, 8 Jan 2024 19:05:59 +0800
-Subject: [PATCH 022/116] PCI: microchip: Move setup functions to
- pcie-plda-host.c
-
-Move setup functions to common pcie-plda-host.c. So these two functions
-can be re-used.
-
-Signed-off-by: Minda Chen <minda.chen@starfivetech.com>
-Reviewed-by: Conor Dooley <conor.dooley@microchip.com>
----
- drivers/pci/controller/plda/Kconfig           |  4 +
- drivers/pci/controller/plda/Makefile          |  1 +
- .../pci/controller/plda/pcie-microchip-host.c | 59 ---------------
- drivers/pci/controller/plda/pcie-plda-host.c  | 74 +++++++++++++++++++
- drivers/pci/controller/plda/pcie-plda.h       |  5 ++
- 5 files changed, 84 insertions(+), 59 deletions(-)
- create mode 100644 drivers/pci/controller/plda/pcie-plda-host.c
-
---- a/drivers/pci/controller/plda/Kconfig
-+++ b/drivers/pci/controller/plda/Kconfig
-@@ -3,10 +3,14 @@
- menu "PLDA-based PCIe controllers"
-       depends on PCI
-+config PCIE_PLDA_HOST
-+      bool
-+
- config PCIE_MICROCHIP_HOST
-       tristate "Microchip AXI PCIe controller"
-       depends on PCI_MSI && OF
-       select PCI_HOST_COMMON
-+      select PCIE_PLDA_HOST
-       help
-         Say Y here if you want kernel to support the Microchip AXI PCIe
-         Host Bridge driver.
---- a/drivers/pci/controller/plda/Makefile
-+++ b/drivers/pci/controller/plda/Makefile
-@@ -1,2 +1,3 @@
- # SPDX-License-Identifier: GPL-2.0
-+obj-$(CONFIG_PCIE_PLDA_HOST) += pcie-plda-host.o
- obj-$(CONFIG_PCIE_MICROCHIP_HOST) += pcie-microchip-host.o
---- a/drivers/pci/controller/plda/pcie-microchip-host.c
-+++ b/drivers/pci/controller/plda/pcie-microchip-host.c
-@@ -838,65 +838,6 @@ static int mc_pcie_init_irq_domains(stru
-       return mc_allocate_msi_domains(port);
- }
--static void plda_pcie_setup_window(void __iomem *bridge_base_addr, u32 index,
--                                 phys_addr_t axi_addr, phys_addr_t pci_addr,
--                                 size_t size)
--{
--      u32 atr_sz = ilog2(size) - 1;
--      u32 val;
--
--      if (index == 0)
--              val = PCIE_CONFIG_INTERFACE;
--      else
--              val = PCIE_TX_RX_INTERFACE;
--
--      writel(val, bridge_base_addr + (index * ATR_ENTRY_SIZE) +
--             ATR0_AXI4_SLV0_TRSL_PARAM);
--
--      val = lower_32_bits(axi_addr) | (atr_sz << ATR_SIZE_SHIFT) |
--                          ATR_IMPL_ENABLE;
--      writel(val, bridge_base_addr + (index * ATR_ENTRY_SIZE) +
--             ATR0_AXI4_SLV0_SRCADDR_PARAM);
--
--      val = upper_32_bits(axi_addr);
--      writel(val, bridge_base_addr + (index * ATR_ENTRY_SIZE) +
--             ATR0_AXI4_SLV0_SRC_ADDR);
--
--      val = lower_32_bits(pci_addr);
--      writel(val, bridge_base_addr + (index * ATR_ENTRY_SIZE) +
--             ATR0_AXI4_SLV0_TRSL_ADDR_LSB);
--
--      val = upper_32_bits(pci_addr);
--      writel(val, bridge_base_addr + (index * ATR_ENTRY_SIZE) +
--             ATR0_AXI4_SLV0_TRSL_ADDR_UDW);
--
--      val = readl(bridge_base_addr + ATR0_PCIE_WIN0_SRCADDR_PARAM);
--      val |= (ATR0_PCIE_ATR_SIZE << ATR0_PCIE_ATR_SIZE_SHIFT);
--      writel(val, bridge_base_addr + ATR0_PCIE_WIN0_SRCADDR_PARAM);
--      writel(0, bridge_base_addr + ATR0_PCIE_WIN0_SRC_ADDR);
--}
--
--static int plda_pcie_setup_iomems(struct pci_host_bridge *bridge,
--                                struct plda_pcie_rp *port)
--{
--      void __iomem *bridge_base_addr = port->bridge_addr;
--      struct resource_entry *entry;
--      u64 pci_addr;
--      u32 index = 1;
--
--      resource_list_for_each_entry(entry, &bridge->windows) {
--              if (resource_type(entry->res) == IORESOURCE_MEM) {
--                      pci_addr = entry->res->start - entry->offset;
--                      plda_pcie_setup_window(bridge_base_addr, index,
--                                             entry->res->start, pci_addr,
--                                             resource_size(entry->res));
--                      index++;
--              }
--      }
--
--      return 0;
--}
--
- static inline void mc_clear_secs(struct mc_pcie *port)
- {
-       void __iomem *ctrl_base_addr = port->axi_base_addr + MC_PCIE_CTRL_ADDR;
---- /dev/null
-+++ b/drivers/pci/controller/plda/pcie-plda-host.c
-@@ -0,0 +1,74 @@
-+// SPDX-License-Identifier: GPL-2.0
-+/*
-+ * PLDA PCIe XpressRich host controller driver
-+ *
-+ * Copyright (C) 2023 Microchip Co. Ltd
-+ *
-+ * Author: Daire McNamara <daire.mcnamara@microchip.com>
-+ */
-+
-+#include <linux/pci_regs.h>
-+#include <linux/pci-ecam.h>
-+
-+#include "pcie-plda.h"
-+
-+void plda_pcie_setup_window(void __iomem *bridge_base_addr, u32 index,
-+                          phys_addr_t axi_addr, phys_addr_t pci_addr,
-+                          size_t size)
-+{
-+      u32 atr_sz = ilog2(size) - 1;
-+      u32 val;
-+
-+      if (index == 0)
-+              val = PCIE_CONFIG_INTERFACE;
-+      else
-+              val = PCIE_TX_RX_INTERFACE;
-+
-+      writel(val, bridge_base_addr + (index * ATR_ENTRY_SIZE) +
-+             ATR0_AXI4_SLV0_TRSL_PARAM);
-+
-+      val = lower_32_bits(axi_addr) | (atr_sz << ATR_SIZE_SHIFT) |
-+                          ATR_IMPL_ENABLE;
-+      writel(val, bridge_base_addr + (index * ATR_ENTRY_SIZE) +
-+             ATR0_AXI4_SLV0_SRCADDR_PARAM);
-+
-+      val = upper_32_bits(axi_addr);
-+      writel(val, bridge_base_addr + (index * ATR_ENTRY_SIZE) +
-+             ATR0_AXI4_SLV0_SRC_ADDR);
-+
-+      val = lower_32_bits(pci_addr);
-+      writel(val, bridge_base_addr + (index * ATR_ENTRY_SIZE) +
-+             ATR0_AXI4_SLV0_TRSL_ADDR_LSB);
-+
-+      val = upper_32_bits(pci_addr);
-+      writel(val, bridge_base_addr + (index * ATR_ENTRY_SIZE) +
-+             ATR0_AXI4_SLV0_TRSL_ADDR_UDW);
-+
-+      val = readl(bridge_base_addr + ATR0_PCIE_WIN0_SRCADDR_PARAM);
-+      val |= (ATR0_PCIE_ATR_SIZE << ATR0_PCIE_ATR_SIZE_SHIFT);
-+      writel(val, bridge_base_addr + ATR0_PCIE_WIN0_SRCADDR_PARAM);
-+      writel(0, bridge_base_addr + ATR0_PCIE_WIN0_SRC_ADDR);
-+}
-+EXPORT_SYMBOL_GPL(plda_pcie_setup_window);
-+
-+int plda_pcie_setup_iomems(struct pci_host_bridge *bridge,
-+                         struct plda_pcie_rp *port)
-+{
-+      void __iomem *bridge_base_addr = port->bridge_addr;
-+      struct resource_entry *entry;
-+      u64 pci_addr;
-+      u32 index = 1;
-+
-+      resource_list_for_each_entry(entry, &bridge->windows) {
-+              if (resource_type(entry->res) == IORESOURCE_MEM) {
-+                      pci_addr = entry->res->start - entry->offset;
-+                      plda_pcie_setup_window(bridge_base_addr, index,
-+                                             entry->res->start, pci_addr,
-+                                             resource_size(entry->res));
-+                      index++;
-+              }
-+      }
-+
-+      return 0;
-+}
-+EXPORT_SYMBOL_GPL(plda_pcie_setup_iomems);
---- a/drivers/pci/controller/plda/pcie-plda.h
-+++ b/drivers/pci/controller/plda/pcie-plda.h
-@@ -126,4 +126,9 @@ struct plda_pcie_rp {
-       void __iomem *bridge_addr;
- };
-+void plda_pcie_setup_window(void __iomem *bridge_base_addr, u32 index,
-+                          phys_addr_t axi_addr, phys_addr_t pci_addr,
-+                          size_t size);
-+int plda_pcie_setup_iomems(struct pci_host_bridge *bridge,
-+                         struct plda_pcie_rp *port);
- #endif
diff --git a/target/linux/starfive/patches-6.6/0023-PCI-microchip-Rename-interrupt-related-functions.patch b/target/linux/starfive/patches-6.6/0023-PCI-microchip-Rename-interrupt-related-functions.patch
deleted file mode 100644 (file)
index 09c1633..0000000
+++ /dev/null
@@ -1,336 +0,0 @@
-From 2a48bc45dcf8cbe736b594d013cfa9d682214c43 Mon Sep 17 00:00:00 2001
-From: Minda Chen <minda.chen@starfivetech.com>
-Date: Mon, 8 Jan 2024 19:06:00 +0800
-Subject: [PATCH 023/116] PCI: microchip: Rename interrupt related functions
-
-Rename mc_* to plda_* for IRQ functions and related IRQ domain ops data
-instances.
-
-MSI, INTx interrupt code and IRQ init code are all can be re-used.
-
-Signed-off-by: Minda Chen <minda.chen@starfivetech.com>
-Acked-by: Conor Dooley <conor.dooley@microchip.com>
----
- .../pci/controller/plda/pcie-microchip-host.c | 109 +++++++++---------
- 1 file changed, 57 insertions(+), 52 deletions(-)
-
---- a/drivers/pci/controller/plda/pcie-microchip-host.c
-+++ b/drivers/pci/controller/plda/pcie-microchip-host.c
-@@ -318,7 +318,7 @@ static void mc_pcie_enable_msi(struct mc
-                      ecam + MC_MSI_CAP_CTRL_OFFSET + PCI_MSI_ADDRESS_HI);
- }
--static void mc_handle_msi(struct irq_desc *desc)
-+static void plda_handle_msi(struct irq_desc *desc)
- {
-       struct plda_pcie_rp *port = irq_desc_get_handler_data(desc);
-       struct irq_chip *chip = irq_desc_get_chip(desc);
-@@ -346,7 +346,7 @@ static void mc_handle_msi(struct irq_des
-       chained_irq_exit(chip, desc);
- }
--static void mc_msi_bottom_irq_ack(struct irq_data *data)
-+static void plda_msi_bottom_irq_ack(struct irq_data *data)
- {
-       struct plda_pcie_rp *port = irq_data_get_irq_chip_data(data);
-       void __iomem *bridge_base_addr = port->bridge_addr;
-@@ -355,7 +355,7 @@ static void mc_msi_bottom_irq_ack(struct
-       writel_relaxed(BIT(bitpos), bridge_base_addr + ISTATUS_MSI);
- }
--static void mc_compose_msi_msg(struct irq_data *data, struct msi_msg *msg)
-+static void plda_compose_msi_msg(struct irq_data *data, struct msi_msg *msg)
- {
-       struct plda_pcie_rp *port = irq_data_get_irq_chip_data(data);
-       phys_addr_t addr = port->msi.vector_phy;
-@@ -368,21 +368,23 @@ static void mc_compose_msi_msg(struct ir
-               (int)data->hwirq, msg->address_hi, msg->address_lo);
- }
--static int mc_msi_set_affinity(struct irq_data *irq_data,
--                             const struct cpumask *mask, bool force)
-+static int plda_msi_set_affinity(struct irq_data *irq_data,
-+                               const struct cpumask *mask, bool force)
- {
-       return -EINVAL;
- }
--static struct irq_chip mc_msi_bottom_irq_chip = {
--      .name = "Microchip MSI",
--      .irq_ack = mc_msi_bottom_irq_ack,
--      .irq_compose_msi_msg = mc_compose_msi_msg,
--      .irq_set_affinity = mc_msi_set_affinity,
-+static struct irq_chip plda_msi_bottom_irq_chip = {
-+      .name = "PLDA MSI",
-+      .irq_ack = plda_msi_bottom_irq_ack,
-+      .irq_compose_msi_msg = plda_compose_msi_msg,
-+      .irq_set_affinity = plda_msi_set_affinity,
- };
--static int mc_irq_msi_domain_alloc(struct irq_domain *domain, unsigned int virq,
--                                 unsigned int nr_irqs, void *args)
-+static int plda_irq_msi_domain_alloc(struct irq_domain *domain,
-+                                   unsigned int virq,
-+                                   unsigned int nr_irqs,
-+                                   void *args)
- {
-       struct plda_pcie_rp *port = domain->host_data;
-       struct plda_msi *msi = &port->msi;
-@@ -397,7 +399,7 @@ static int mc_irq_msi_domain_alloc(struc
-       set_bit(bit, msi->used);
--      irq_domain_set_info(domain, virq, bit, &mc_msi_bottom_irq_chip,
-+      irq_domain_set_info(domain, virq, bit, &plda_msi_bottom_irq_chip,
-                           domain->host_data, handle_edge_irq, NULL, NULL);
-       mutex_unlock(&msi->lock);
-@@ -405,8 +407,9 @@ static int mc_irq_msi_domain_alloc(struc
-       return 0;
- }
--static void mc_irq_msi_domain_free(struct irq_domain *domain, unsigned int virq,
--                                 unsigned int nr_irqs)
-+static void plda_irq_msi_domain_free(struct irq_domain *domain,
-+                                   unsigned int virq,
-+                                   unsigned int nr_irqs)
- {
-       struct irq_data *d = irq_domain_get_irq_data(domain, virq);
-       struct plda_pcie_rp *port = irq_data_get_irq_chip_data(d);
-@@ -423,24 +426,24 @@ static void mc_irq_msi_domain_free(struc
- }
- static const struct irq_domain_ops msi_domain_ops = {
--      .alloc  = mc_irq_msi_domain_alloc,
--      .free   = mc_irq_msi_domain_free,
-+      .alloc  = plda_irq_msi_domain_alloc,
-+      .free   = plda_irq_msi_domain_free,
- };
--static struct irq_chip mc_msi_irq_chip = {
--      .name = "Microchip PCIe MSI",
-+static struct irq_chip plda_msi_irq_chip = {
-+      .name = "PLDA PCIe MSI",
-       .irq_ack = irq_chip_ack_parent,
-       .irq_mask = pci_msi_mask_irq,
-       .irq_unmask = pci_msi_unmask_irq,
- };
--static struct msi_domain_info mc_msi_domain_info = {
-+static struct msi_domain_info plda_msi_domain_info = {
-       .flags = (MSI_FLAG_USE_DEF_DOM_OPS | MSI_FLAG_USE_DEF_CHIP_OPS |
-                 MSI_FLAG_PCI_MSIX),
--      .chip = &mc_msi_irq_chip,
-+      .chip = &plda_msi_irq_chip,
- };
--static int mc_allocate_msi_domains(struct plda_pcie_rp *port)
-+static int plda_allocate_msi_domains(struct plda_pcie_rp *port)
- {
-       struct device *dev = port->dev;
-       struct fwnode_handle *fwnode = of_node_to_fwnode(dev->of_node);
-@@ -455,7 +458,8 @@ static int mc_allocate_msi_domains(struc
-               return -ENOMEM;
-       }
--      msi->msi_domain = pci_msi_create_irq_domain(fwnode, &mc_msi_domain_info,
-+      msi->msi_domain = pci_msi_create_irq_domain(fwnode,
-+                                                  &plda_msi_domain_info,
-                                                   msi->dev_domain);
-       if (!msi->msi_domain) {
-               dev_err(dev, "failed to create MSI domain\n");
-@@ -466,7 +470,7 @@ static int mc_allocate_msi_domains(struc
-       return 0;
- }
--static void mc_handle_intx(struct irq_desc *desc)
-+static void plda_handle_intx(struct irq_desc *desc)
- {
-       struct plda_pcie_rp *port = irq_desc_get_handler_data(desc);
-       struct irq_chip *chip = irq_desc_get_chip(desc);
-@@ -493,7 +497,7 @@ static void mc_handle_intx(struct irq_de
-       chained_irq_exit(chip, desc);
- }
--static void mc_ack_intx_irq(struct irq_data *data)
-+static void plda_ack_intx_irq(struct irq_data *data)
- {
-       struct plda_pcie_rp *port = irq_data_get_irq_chip_data(data);
-       void __iomem *bridge_base_addr = port->bridge_addr;
-@@ -502,7 +506,7 @@ static void mc_ack_intx_irq(struct irq_d
-       writel_relaxed(mask, bridge_base_addr + ISTATUS_LOCAL);
- }
--static void mc_mask_intx_irq(struct irq_data *data)
-+static void plda_mask_intx_irq(struct irq_data *data)
- {
-       struct plda_pcie_rp *port = irq_data_get_irq_chip_data(data);
-       void __iomem *bridge_base_addr = port->bridge_addr;
-@@ -517,7 +521,7 @@ static void mc_mask_intx_irq(struct irq_
-       raw_spin_unlock_irqrestore(&port->lock, flags);
- }
--static void mc_unmask_intx_irq(struct irq_data *data)
-+static void plda_unmask_intx_irq(struct irq_data *data)
- {
-       struct plda_pcie_rp *port = irq_data_get_irq_chip_data(data);
-       void __iomem *bridge_base_addr = port->bridge_addr;
-@@ -532,24 +536,24 @@ static void mc_unmask_intx_irq(struct ir
-       raw_spin_unlock_irqrestore(&port->lock, flags);
- }
--static struct irq_chip mc_intx_irq_chip = {
--      .name = "Microchip PCIe INTx",
--      .irq_ack = mc_ack_intx_irq,
--      .irq_mask = mc_mask_intx_irq,
--      .irq_unmask = mc_unmask_intx_irq,
-+static struct irq_chip plda_intx_irq_chip = {
-+      .name = "PLDA PCIe INTx",
-+      .irq_ack = plda_ack_intx_irq,
-+      .irq_mask = plda_mask_intx_irq,
-+      .irq_unmask = plda_unmask_intx_irq,
- };
--static int mc_pcie_intx_map(struct irq_domain *domain, unsigned int irq,
--                          irq_hw_number_t hwirq)
-+static int plda_pcie_intx_map(struct irq_domain *domain, unsigned int irq,
-+                            irq_hw_number_t hwirq)
- {
--      irq_set_chip_and_handler(irq, &mc_intx_irq_chip, handle_level_irq);
-+      irq_set_chip_and_handler(irq, &plda_intx_irq_chip, handle_level_irq);
-       irq_set_chip_data(irq, domain->host_data);
-       return 0;
- }
- static const struct irq_domain_ops intx_domain_ops = {
--      .map = mc_pcie_intx_map,
-+      .map = plda_pcie_intx_map,
- };
- static inline u32 reg_to_event(u32 reg, struct event_map field)
-@@ -609,7 +613,7 @@ static u32 local_events(struct mc_pcie *
-       return val;
- }
--static u32 get_events(struct plda_pcie_rp *port)
-+static u32 mc_get_events(struct plda_pcie_rp *port)
- {
-       struct mc_pcie *mc_port = container_of(port, struct mc_pcie, plda);
-       u32 events = 0;
-@@ -638,7 +642,7 @@ static irqreturn_t mc_event_handler(int
-       return IRQ_HANDLED;
- }
--static void mc_handle_event(struct irq_desc *desc)
-+static void plda_handle_event(struct irq_desc *desc)
- {
-       struct plda_pcie_rp *port = irq_desc_get_handler_data(desc);
-       unsigned long events;
-@@ -647,7 +651,7 @@ static void mc_handle_event(struct irq_d
-       chained_irq_enter(chip, desc);
--      events = get_events(port);
-+      events = mc_get_events(port);
-       for_each_set_bit(bit, &events, NUM_EVENTS)
-               generic_handle_domain_irq(port->event_domain, bit);
-@@ -741,8 +745,8 @@ static struct irq_chip mc_event_irq_chip
-       .irq_unmask = mc_unmask_event_irq,
- };
--static int mc_pcie_event_map(struct irq_domain *domain, unsigned int irq,
--                           irq_hw_number_t hwirq)
-+static int plda_pcie_event_map(struct irq_domain *domain, unsigned int irq,
-+                             irq_hw_number_t hwirq)
- {
-       irq_set_chip_and_handler(irq, &mc_event_irq_chip, handle_level_irq);
-       irq_set_chip_data(irq, domain->host_data);
-@@ -750,8 +754,8 @@ static int mc_pcie_event_map(struct irq_
-       return 0;
- }
--static const struct irq_domain_ops event_domain_ops = {
--      .map = mc_pcie_event_map,
-+static const struct irq_domain_ops plda_event_domain_ops = {
-+      .map = plda_pcie_event_map,
- };
- static inline void mc_pcie_deinit_clk(void *data)
-@@ -799,7 +803,7 @@ static int mc_pcie_init_clks(struct devi
-       return 0;
- }
--static int mc_pcie_init_irq_domains(struct plda_pcie_rp *port)
-+static int plda_pcie_init_irq_domains(struct plda_pcie_rp *port)
- {
-       struct device *dev = port->dev;
-       struct device_node *node = dev->of_node;
-@@ -813,7 +817,8 @@ static int mc_pcie_init_irq_domains(stru
-       }
-       port->event_domain = irq_domain_add_linear(pcie_intc_node, NUM_EVENTS,
--                                                 &event_domain_ops, port);
-+                                                 &plda_event_domain_ops,
-+                                                 port);
-       if (!port->event_domain) {
-               dev_err(dev, "failed to get event domain\n");
-               of_node_put(pcie_intc_node);
-@@ -835,7 +840,7 @@ static int mc_pcie_init_irq_domains(stru
-       of_node_put(pcie_intc_node);
-       raw_spin_lock_init(&port->lock);
--      return mc_allocate_msi_domains(port);
-+      return plda_allocate_msi_domains(port);
- }
- static inline void mc_clear_secs(struct mc_pcie *port)
-@@ -898,14 +903,14 @@ static void mc_disable_interrupts(struct
-       writel_relaxed(GENMASK(31, 0), bridge_base_addr + ISTATUS_HOST);
- }
--static int mc_init_interrupts(struct platform_device *pdev, struct plda_pcie_rp *port)
-+static int plda_init_interrupts(struct platform_device *pdev, struct plda_pcie_rp *port)
- {
-       struct device *dev = &pdev->dev;
-       int irq;
-       int i, intx_irq, msi_irq, event_irq;
-       int ret;
--      ret = mc_pcie_init_irq_domains(port);
-+      ret = plda_pcie_init_irq_domains(port);
-       if (ret) {
-               dev_err(dev, "failed creating IRQ domains\n");
-               return ret;
-@@ -938,7 +943,7 @@ static int mc_init_interrupts(struct pla
-       }
-       /* Plug the INTx chained handler */
--      irq_set_chained_handler_and_data(intx_irq, mc_handle_intx, port);
-+      irq_set_chained_handler_and_data(intx_irq, plda_handle_intx, port);
-       msi_irq = irq_create_mapping(port->event_domain,
-                                    EVENT_LOCAL_PM_MSI_INT_MSI);
-@@ -946,10 +951,10 @@ static int mc_init_interrupts(struct pla
-               return -ENXIO;
-       /* Plug the MSI chained handler */
--      irq_set_chained_handler_and_data(msi_irq, mc_handle_msi, port);
-+      irq_set_chained_handler_and_data(msi_irq, plda_handle_msi, port);
-       /* Plug the main event chained handler */
--      irq_set_chained_handler_and_data(irq, mc_handle_event, port);
-+      irq_set_chained_handler_and_data(irq, plda_handle_event, port);
-       return 0;
- }
-@@ -977,7 +982,7 @@ static int mc_platform_init(struct pci_c
-               return ret;
-       /* Address translation is up; safe to enable interrupts */
--      ret = mc_init_interrupts(pdev, &port->plda);
-+      ret = plda_init_interrupts(pdev, &port->plda);
-       if (ret)
-               return ret;
diff --git a/target/linux/starfive/patches-6.6/0024-PCI-microchip-Add-num_events-field-to-struct-plda_pc.patch b/target/linux/starfive/patches-6.6/0024-PCI-microchip-Add-num_events-field-to-struct-plda_pc.patch
deleted file mode 100644 (file)
index 4071feb..0000000
+++ /dev/null
@@ -1,65 +0,0 @@
-From ab04dadb45a4150c9fd55b97fdd7397f4739a629 Mon Sep 17 00:00:00 2001
-From: Minda Chen <minda.chen@starfivetech.com>
-Date: Mon, 8 Jan 2024 19:06:01 +0800
-Subject: [PATCH 024/116] PCI: microchip: Add num_events field to struct
- plda_pcie_rp
-
-The number of events is different across platforms. In order to share
-interrupt processing code, add a variable that defines the number of
-events so that it can be set per-platform instead of hardcoding it.
-
-Signed-off-by: Minda Chen <minda.chen@starfivetech.com>
-Reviewed-by: Conor Dooley <conor.dooley@microchip.com>
----
- drivers/pci/controller/plda/pcie-microchip-host.c | 8 +++++---
- drivers/pci/controller/plda/pcie-plda.h           | 1 +
- 2 files changed, 6 insertions(+), 3 deletions(-)
-
---- a/drivers/pci/controller/plda/pcie-microchip-host.c
-+++ b/drivers/pci/controller/plda/pcie-microchip-host.c
-@@ -653,7 +653,7 @@ static void plda_handle_event(struct irq
-       events = mc_get_events(port);
--      for_each_set_bit(bit, &events, NUM_EVENTS)
-+      for_each_set_bit(bit, &events, port->num_events)
-               generic_handle_domain_irq(port->event_domain, bit);
-       chained_irq_exit(chip, desc);
-@@ -816,7 +816,8 @@ static int plda_pcie_init_irq_domains(st
-               return -EINVAL;
-       }
--      port->event_domain = irq_domain_add_linear(pcie_intc_node, NUM_EVENTS,
-+      port->event_domain = irq_domain_add_linear(pcie_intc_node,
-+                                                 port->num_events,
-                                                  &plda_event_domain_ops,
-                                                  port);
-       if (!port->event_domain) {
-@@ -920,7 +921,7 @@ static int plda_init_interrupts(struct p
-       if (irq < 0)
-               return -ENODEV;
--      for (i = 0; i < NUM_EVENTS; i++) {
-+      for (i = 0; i < port->num_events; i++) {
-               event_irq = irq_create_mapping(port->event_domain, i);
-               if (!event_irq) {
-                       dev_err(dev, "failed to map hwirq %d\n", i);
-@@ -1012,6 +1013,7 @@ static int mc_host_probe(struct platform
-       bridge_base_addr = port->axi_base_addr + MC_PCIE_BRIDGE_ADDR;
-       plda->bridge_addr = bridge_base_addr;
-+      plda->num_events = NUM_EVENTS;
-       /* Allow enabling MSI by disabling MSI-X */
-       val = readl(bridge_base_addr + PCIE_PCI_IRQ_DW0);
---- a/drivers/pci/controller/plda/pcie-plda.h
-+++ b/drivers/pci/controller/plda/pcie-plda.h
-@@ -124,6 +124,7 @@ struct plda_pcie_rp {
-       raw_spinlock_t lock;
-       struct plda_msi msi;
-       void __iomem *bridge_addr;
-+      int num_events;
- };
- void plda_pcie_setup_window(void __iomem *bridge_base_addr, u32 index,
diff --git a/target/linux/starfive/patches-6.6/0025-PCI-microchip-Add-request_event_irq-callback-functio.patch b/target/linux/starfive/patches-6.6/0025-PCI-microchip-Add-request_event_irq-callback-functio.patch
deleted file mode 100644 (file)
index 2b299e0..0000000
+++ /dev/null
@@ -1,114 +0,0 @@
-From 9f202f211cc79eefecbb03715c884e54eb95a62c Mon Sep 17 00:00:00 2001
-From: Minda Chen <minda.chen@starfivetech.com>
-Date: Mon, 8 Jan 2024 19:06:02 +0800
-Subject: [PATCH 025/116] PCI: microchip: Add request_event_irq() callback
- function
-
-As PLDA dts binding doc(Documentation/devicetree/bindings/pci/
-plda,xpressrich3-axi-common.yaml) showes, PLDA PCIe contains an interrupt
-controller. Microchip Polarfire PCIe add some PCIe interrupts base on
-PLDA IP interrupt controller.
-
-Microchip Polarfire PCIe additional intrerrupts:
-EVENT_PCIE_L2_EXIT
-EVENT_PCIE_HOTRST_EXIT
-EVENT_PCIE_DLUP_EXIT
-EVENT_SEC_TX_RAM_SEC_ERR
-EVENT_SEC_RX_RAM_SEC_ERR
-....
-
-Both codes of register interrupts and mc_event_handler() contain
-additional interrupts symbol names, these can not be re-used. So add a
-new plda_event_handler() functions, which implements PLDA interrupt
-defalt handler. Add request_event_irq() callback function to
-compat Microchip Polorfire PCIe additional interrupts.
-
-Signed-off-by: Minda Chen <minda.chen@starfivetech.com>
-Acked-by: Conor Dooley <conor.dooley@microchip.com>
----
- .../pci/controller/plda/pcie-microchip-host.c | 31 ++++++++++++++++---
- drivers/pci/controller/plda/pcie-plda.h       |  5 +++
- 2 files changed, 32 insertions(+), 4 deletions(-)
-
---- a/drivers/pci/controller/plda/pcie-microchip-host.c
-+++ b/drivers/pci/controller/plda/pcie-microchip-host.c
-@@ -642,6 +642,11 @@ static irqreturn_t mc_event_handler(int
-       return IRQ_HANDLED;
- }
-+static irqreturn_t plda_event_handler(int irq, void *dev_id)
-+{
-+      return IRQ_HANDLED;
-+}
-+
- static void plda_handle_event(struct irq_desc *desc)
- {
-       struct plda_pcie_rp *port = irq_desc_get_handler_data(desc);
-@@ -803,6 +808,17 @@ static int mc_pcie_init_clks(struct devi
-       return 0;
- }
-+static int mc_request_event_irq(struct plda_pcie_rp *plda, int event_irq,
-+                              int event)
-+{
-+      return devm_request_irq(plda->dev, event_irq, mc_event_handler,
-+                              0, event_cause[event].sym, plda);
-+}
-+
-+static const struct plda_event mc_event = {
-+      .request_event_irq = mc_request_event_irq,
-+};
-+
- static int plda_pcie_init_irq_domains(struct plda_pcie_rp *port)
- {
-       struct device *dev = port->dev;
-@@ -904,7 +920,9 @@ static void mc_disable_interrupts(struct
-       writel_relaxed(GENMASK(31, 0), bridge_base_addr + ISTATUS_HOST);
- }
--static int plda_init_interrupts(struct platform_device *pdev, struct plda_pcie_rp *port)
-+static int plda_init_interrupts(struct platform_device *pdev,
-+                              struct plda_pcie_rp *port,
-+                              const struct plda_event *event)
- {
-       struct device *dev = &pdev->dev;
-       int irq;
-@@ -928,8 +946,13 @@ static int plda_init_interrupts(struct p
-                       return -ENXIO;
-               }
--              ret = devm_request_irq(dev, event_irq, mc_event_handler,
--                                     0, event_cause[i].sym, port);
-+              if (event->request_event_irq)
-+                      ret = event->request_event_irq(port, event_irq, i);
-+              else
-+                      ret = devm_request_irq(dev, event_irq,
-+                                             plda_event_handler,
-+                                             0, NULL, port);
-+
-               if (ret) {
-                       dev_err(dev, "failed to request IRQ %d\n", event_irq);
-                       return ret;
-@@ -983,7 +1006,7 @@ static int mc_platform_init(struct pci_c
-               return ret;
-       /* Address translation is up; safe to enable interrupts */
--      ret = plda_init_interrupts(pdev, &port->plda);
-+      ret = plda_init_interrupts(pdev, &port->plda, &mc_event);
-       if (ret)
-               return ret;
---- a/drivers/pci/controller/plda/pcie-plda.h
-+++ b/drivers/pci/controller/plda/pcie-plda.h
-@@ -127,6 +127,11 @@ struct plda_pcie_rp {
-       int num_events;
- };
-+struct plda_event {
-+      int (*request_event_irq)(struct plda_pcie_rp *pcie,
-+                               int event_irq, int event);
-+};
-+
- void plda_pcie_setup_window(void __iomem *bridge_base_addr, u32 index,
-                           phys_addr_t axi_addr, phys_addr_t pci_addr,
-                           size_t size);
diff --git a/target/linux/starfive/patches-6.6/0026-PCI-microchip-Add-INTx-and-MSI-event-num-to-struct-p.patch b/target/linux/starfive/patches-6.6/0026-PCI-microchip-Add-INTx-and-MSI-event-num-to-struct-p.patch
deleted file mode 100644 (file)
index 85b8143..0000000
+++ /dev/null
@@ -1,56 +0,0 @@
-From 3cdc20d9cc029ba9444be111bf4e55fd5331ccbe Mon Sep 17 00:00:00 2001
-From: Minda Chen <minda.chen@starfivetech.com>
-Date: Mon, 8 Jan 2024 19:06:03 +0800
-Subject: [PATCH 026/116] PCI: microchip: Add INTx and MSI event num to struct
- plda_event
-
-The INTx and MSI interrupt event num is different in Microchip and
-StarFive platform.
-
-Signed-off-by: Minda Chen <minda.chen@starfivetech.com>
-Acked-by: Conor Dooley <conor.dooley@microchip.com>
----
- drivers/pci/controller/plda/pcie-microchip-host.c | 6 ++++--
- drivers/pci/controller/plda/pcie-plda.h           | 2 ++
- 2 files changed, 6 insertions(+), 2 deletions(-)
-
---- a/drivers/pci/controller/plda/pcie-microchip-host.c
-+++ b/drivers/pci/controller/plda/pcie-microchip-host.c
-@@ -817,6 +817,8 @@ static int mc_request_event_irq(struct p
- static const struct plda_event mc_event = {
-       .request_event_irq = mc_request_event_irq,
-+      .intx_event        = EVENT_LOCAL_PM_MSI_INT_INTX,
-+      .msi_event         = EVENT_LOCAL_PM_MSI_INT_MSI,
- };
- static int plda_pcie_init_irq_domains(struct plda_pcie_rp *port)
-@@ -960,7 +962,7 @@ static int plda_init_interrupts(struct p
-       }
-       intx_irq = irq_create_mapping(port->event_domain,
--                                    EVENT_LOCAL_PM_MSI_INT_INTX);
-+                                    event->intx_event);
-       if (!intx_irq) {
-               dev_err(dev, "failed to map INTx interrupt\n");
-               return -ENXIO;
-@@ -970,7 +972,7 @@ static int plda_init_interrupts(struct p
-       irq_set_chained_handler_and_data(intx_irq, plda_handle_intx, port);
-       msi_irq = irq_create_mapping(port->event_domain,
--                                   EVENT_LOCAL_PM_MSI_INT_MSI);
-+                                   event->msi_event);
-       if (!msi_irq)
-               return -ENXIO;
---- a/drivers/pci/controller/plda/pcie-plda.h
-+++ b/drivers/pci/controller/plda/pcie-plda.h
-@@ -130,6 +130,8 @@ struct plda_pcie_rp {
- struct plda_event {
-       int (*request_event_irq)(struct plda_pcie_rp *pcie,
-                                int event_irq, int event);
-+      int intx_event;
-+      int msi_event;
- };
- void plda_pcie_setup_window(void __iomem *bridge_base_addr, u32 index,
diff --git a/target/linux/starfive/patches-6.6/0027-PCI-microchip-Add-get_events-callback-and-add-PLDA-g.patch b/target/linux/starfive/patches-6.6/0027-PCI-microchip-Add-get_events-callback-and-add-PLDA-g.patch
deleted file mode 100644 (file)
index a0cb478..0000000
+++ /dev/null
@@ -1,167 +0,0 @@
-From b4a38ef87661f21fe2fb3e085ae98f25f78aaf99 Mon Sep 17 00:00:00 2001
-From: Minda Chen <minda.chen@starfivetech.com>
-Date: Mon, 8 Jan 2024 19:06:04 +0800
-Subject: [PATCH 027/116] PCI: microchip: Add get_events() callback and add
- PLDA get_event()
-
-As PLDA dts binding doc(Documentation/devicetree/bindings/pci/
-plda,xpressrich3-axi-common.yaml) showes, PLDA PCIe contains an interrupt
-controller.
-
-PolarFire implements its own PCIe interrupts, additional to the regular
-PCIe interrupts, due to lack of an MSI controller, so the interrupt to
-event number mapping is different to the PLDA regular interrupts,
-necessitating a custom get_events() implementation.
-
-Microchip Polarfire PCIe additional intrerrupts:
-EVENT_PCIE_L2_EXIT
-EVENT_PCIE_HOTRST_EXIT
-EVENT_PCIE_DLUP_EXIT
-EVENT_SEC_TX_RAM_SEC_ERR
-EVENT_SEC_RX_RAM_SEC_ERR
-....
-
-plda_get_events() adds interrupt register to PLDA local event num mapping
-codes. All The PLDA interrupts can be seen in new added graph.
-
-Signed-off-by: Minda Chen <minda.chen@starfivetech.com>
-Acked-by: Conor Dooley <conor.dooley@microchip.com>
----
- .../pci/controller/plda/pcie-microchip-host.c | 35 ++++++++++++++++++-
- drivers/pci/controller/plda/pcie-plda.h       | 32 +++++++++++++++++
- 2 files changed, 66 insertions(+), 1 deletion(-)
-
---- a/drivers/pci/controller/plda/pcie-microchip-host.c
-+++ b/drivers/pci/controller/plda/pcie-microchip-host.c
-@@ -626,6 +626,26 @@ static u32 mc_get_events(struct plda_pci
-       return events;
- }
-+static u32 plda_get_events(struct plda_pcie_rp *port)
-+{
-+      u32 events, val, origin;
-+
-+      origin = readl_relaxed(port->bridge_addr + ISTATUS_LOCAL);
-+
-+      /* MSI event and sys events */
-+      val = (origin & SYS_AND_MSI_MASK) >> PM_MSI_INT_MSI_SHIFT;
-+      events = val << (PM_MSI_INT_MSI_SHIFT - PCI_NUM_INTX + 1);
-+
-+      /* INTx events */
-+      if (origin & PM_MSI_INT_INTX_MASK)
-+              events |= BIT(PM_MSI_INT_INTX_SHIFT);
-+
-+      /* remains are same with register */
-+      events |= origin & GENMASK(P_ATR_EVT_DOORBELL_SHIFT, 0);
-+
-+      return events;
-+}
-+
- static irqreturn_t mc_event_handler(int irq, void *dev_id)
- {
-       struct plda_pcie_rp *port = dev_id;
-@@ -656,7 +676,7 @@ static void plda_handle_event(struct irq
-       chained_irq_enter(chip, desc);
--      events = mc_get_events(port);
-+      events = port->event_ops->get_events(port);
-       for_each_set_bit(bit, &events, port->num_events)
-               generic_handle_domain_irq(port->event_domain, bit);
-@@ -750,6 +770,10 @@ static struct irq_chip mc_event_irq_chip
-       .irq_unmask = mc_unmask_event_irq,
- };
-+static const struct plda_event_ops plda_event_ops = {
-+      .get_events = plda_get_events,
-+};
-+
- static int plda_pcie_event_map(struct irq_domain *domain, unsigned int irq,
-                              irq_hw_number_t hwirq)
- {
-@@ -815,6 +839,10 @@ static int mc_request_event_irq(struct p
-                               0, event_cause[event].sym, plda);
- }
-+static const struct plda_event_ops mc_event_ops = {
-+      .get_events = mc_get_events,
-+};
-+
- static const struct plda_event mc_event = {
-       .request_event_irq = mc_request_event_irq,
-       .intx_event        = EVENT_LOCAL_PM_MSI_INT_INTX,
-@@ -931,6 +959,9 @@ static int plda_init_interrupts(struct p
-       int i, intx_irq, msi_irq, event_irq;
-       int ret;
-+      if (!port->event_ops)
-+              port->event_ops = &plda_event_ops;
-+
-       ret = plda_pcie_init_irq_domains(port);
-       if (ret) {
-               dev_err(dev, "failed creating IRQ domains\n");
-@@ -1007,6 +1038,8 @@ static int mc_platform_init(struct pci_c
-       if (ret)
-               return ret;
-+      port->plda.event_ops = &mc_event_ops;
-+
-       /* Address translation is up; safe to enable interrupts */
-       ret = plda_init_interrupts(pdev, &port->plda, &mc_event);
-       if (ret)
---- a/drivers/pci/controller/plda/pcie-plda.h
-+++ b/drivers/pci/controller/plda/pcie-plda.h
-@@ -58,6 +58,7 @@
- #define  PM_MSI_INT_EVENTS_SHIFT              30
- #define  PM_MSI_INT_SYS_ERR_MASK              0x80000000u
- #define  PM_MSI_INT_SYS_ERR_SHIFT             31
-+#define  SYS_AND_MSI_MASK                     GENMASK(31, 28)
- #define  NUM_LOCAL_EVENTS                     15
- #define ISTATUS_LOCAL                         0x184
- #define IMASK_HOST                            0x188
-@@ -108,6 +109,36 @@ enum plda_int_event {
- #define PLDA_MAX_INT_NUM                      (PLDA_NUM_DMA_EVENTS + PLDA_INT_EVENT_NUM)
-+/*
-+ * PLDA interrupt register
-+ *
-+ * 31         27     23              15           7          0
-+ * +--+--+--+-+------+-+-+-+-+-+-+-+-+-----------+-----------+
-+ * |12|11|10|9| intx |7|6|5|4|3|2|1|0| DMA error | DMA end   |
-+ * +--+--+--+-+------+-+-+-+-+-+-+-+-+-----------+-----------+
-+ * bit 0-7  DMA interrupt end : reserved for vendor implement
-+ * bit 8-15 DMA error : reserved for vendor implement
-+ * 0:  AXI post error (PLDA_AXI_POST_ERR)
-+ * 1:  AXI fetch error (PLDA_AXI_FETCH_ERR)
-+ * 2:  AXI discard error (PLDA_AXI_DISCARD_ERR)
-+ * 3:  AXI doorbell (PLDA_PCIE_DOORBELL)
-+ * 4:  PCIe post error (PLDA_PCIE_POST_ERR)
-+ * 5:  PCIe fetch error (PLDA_PCIE_FETCH_ERR)
-+ * 6:  PCIe discard error (PLDA_PCIE_DISCARD_ERR)
-+ * 7:  PCIe doorbell (PLDA_PCIE_DOORBELL)
-+ * 8:  4 INTx interruts (PLDA_INTX)
-+ * 9:  MSI interrupt (PLDA_MSI)
-+ * 10: AER event (PLDA_AER_EVENT)
-+ * 11: PM/LTR/Hotplug (PLDA_MISC_EVENTS)
-+ * 12: System error (PLDA_SYS_ERR)
-+ */
-+
-+struct plda_pcie_rp;
-+
-+struct plda_event_ops {
-+      u32 (*get_events)(struct plda_pcie_rp *pcie);
-+};
-+
- struct plda_msi {
-       struct mutex lock;              /* Protect used bitmap */
-       struct irq_domain *msi_domain;
-@@ -123,6 +154,7 @@ struct plda_pcie_rp {
-       struct irq_domain *event_domain;
-       raw_spinlock_t lock;
-       struct plda_msi msi;
-+      const struct plda_event_ops *event_ops;
-       void __iomem *bridge_addr;
-       int num_events;
- };
diff --git a/target/linux/starfive/patches-6.6/0028-PCI-microchip-Add-event-irqchip-field-to-host-port-a.patch b/target/linux/starfive/patches-6.6/0028-PCI-microchip-Add-event-irqchip-field-to-host-port-a.patch
deleted file mode 100644 (file)
index 9ed8119..0000000
+++ /dev/null
@@ -1,144 +0,0 @@
-From 229ea8e7b674eb5c9bc4f70d43df1bd02a79862a Mon Sep 17 00:00:00 2001
-From: Minda Chen <minda.chen@starfivetech.com>
-Date: Mon, 8 Jan 2024 19:06:05 +0800
-Subject: [PATCH 028/116] PCI: microchip: Add event irqchip field to host port
- and add PLDA irqchip
-
-As PLDA dts binding doc(Documentation/devicetree/bindings/pci/
-plda,xpressrich3-axi-common.yaml) showes, PLDA PCIe contains an interrupt
-controller.
-
-Microchip PolarFire PCIE event IRQs includes PLDA interrupts and
-Polarfire their own interrupts. The interrupt irqchip ops includes
-ack/mask/unmask interrupt ops, which will write correct registers.
-Microchip Polarfire PCIe additional interrupts require to write Polarfire
-SoC self-defined registers. So Microchip PCIe event irqchip ops can not
-be re-used.
-
-To support PLDA its own event IRQ process, implements PLDA irqchip ops and
-add event irqchip field to struct pcie_plda_rp.
-
-Signed-off-by: Minda Chen <minda.chen@starfivetech.com>
-Acked-by: Conor Dooley <conor.dooley@microchip.com>
----
- .../pci/controller/plda/pcie-microchip-host.c | 66 ++++++++++++++++++-
- drivers/pci/controller/plda/pcie-plda.h       |  5 +-
- 2 files changed, 69 insertions(+), 2 deletions(-)
-
---- a/drivers/pci/controller/plda/pcie-microchip-host.c
-+++ b/drivers/pci/controller/plda/pcie-microchip-host.c
-@@ -770,6 +770,64 @@ static struct irq_chip mc_event_irq_chip
-       .irq_unmask = mc_unmask_event_irq,
- };
-+static u32 plda_hwirq_to_mask(int hwirq)
-+{
-+      u32 mask;
-+
-+      /* hwirq 23 - 0 are the same with register */
-+      if (hwirq < EVENT_PM_MSI_INT_INTX)
-+              mask = BIT(hwirq);
-+      else if (hwirq == EVENT_PM_MSI_INT_INTX)
-+              mask = PM_MSI_INT_INTX_MASK;
-+      else
-+              mask = BIT(hwirq + PCI_NUM_INTX - 1);
-+
-+      return mask;
-+}
-+
-+static void plda_ack_event_irq(struct irq_data *data)
-+{
-+      struct plda_pcie_rp *port = irq_data_get_irq_chip_data(data);
-+
-+      writel_relaxed(plda_hwirq_to_mask(data->hwirq),
-+                     port->bridge_addr + ISTATUS_LOCAL);
-+}
-+
-+static void plda_mask_event_irq(struct irq_data *data)
-+{
-+      struct plda_pcie_rp *port = irq_data_get_irq_chip_data(data);
-+      u32 mask, val;
-+
-+      mask = plda_hwirq_to_mask(data->hwirq);
-+
-+      raw_spin_lock(&port->lock);
-+      val = readl_relaxed(port->bridge_addr + IMASK_LOCAL);
-+      val &= ~mask;
-+      writel_relaxed(val, port->bridge_addr + IMASK_LOCAL);
-+      raw_spin_unlock(&port->lock);
-+}
-+
-+static void plda_unmask_event_irq(struct irq_data *data)
-+{
-+      struct plda_pcie_rp *port = irq_data_get_irq_chip_data(data);
-+      u32 mask, val;
-+
-+      mask = plda_hwirq_to_mask(data->hwirq);
-+
-+      raw_spin_lock(&port->lock);
-+      val = readl_relaxed(port->bridge_addr + IMASK_LOCAL);
-+      val |= mask;
-+      writel_relaxed(val, port->bridge_addr + IMASK_LOCAL);
-+      raw_spin_unlock(&port->lock);
-+}
-+
-+static struct irq_chip plda_event_irq_chip = {
-+      .name = "PLDA PCIe EVENT",
-+      .irq_ack = plda_ack_event_irq,
-+      .irq_mask = plda_mask_event_irq,
-+      .irq_unmask = plda_unmask_event_irq,
-+};
-+
- static const struct plda_event_ops plda_event_ops = {
-       .get_events = plda_get_events,
- };
-@@ -777,7 +835,9 @@ static const struct plda_event_ops plda_
- static int plda_pcie_event_map(struct irq_domain *domain, unsigned int irq,
-                              irq_hw_number_t hwirq)
- {
--      irq_set_chip_and_handler(irq, &mc_event_irq_chip, handle_level_irq);
-+      struct plda_pcie_rp *port = (void *)domain->host_data;
-+
-+      irq_set_chip_and_handler(irq, port->event_irq_chip, handle_level_irq);
-       irq_set_chip_data(irq, domain->host_data);
-       return 0;
-@@ -962,6 +1022,9 @@ static int plda_init_interrupts(struct p
-       if (!port->event_ops)
-               port->event_ops = &plda_event_ops;
-+      if (!port->event_irq_chip)
-+              port->event_irq_chip = &plda_event_irq_chip;
-+
-       ret = plda_pcie_init_irq_domains(port);
-       if (ret) {
-               dev_err(dev, "failed creating IRQ domains\n");
-@@ -1039,6 +1102,7 @@ static int mc_platform_init(struct pci_c
-               return ret;
-       port->plda.event_ops = &mc_event_ops;
-+      port->plda.event_irq_chip = &mc_event_irq_chip;
-       /* Address translation is up; safe to enable interrupts */
-       ret = plda_init_interrupts(pdev, &port->plda, &mc_event);
---- a/drivers/pci/controller/plda/pcie-plda.h
-+++ b/drivers/pci/controller/plda/pcie-plda.h
-@@ -107,7 +107,9 @@ enum plda_int_event {
- #define PLDA_NUM_DMA_EVENTS                   16
--#define PLDA_MAX_INT_NUM                      (PLDA_NUM_DMA_EVENTS + PLDA_INT_EVENT_NUM)
-+#define EVENT_PM_MSI_INT_INTX                 (PLDA_NUM_DMA_EVENTS + PLDA_INTX)
-+#define EVENT_PM_MSI_INT_MSI                  (PLDA_NUM_DMA_EVENTS + PLDA_MSI)
-+#define PLDA_MAX_EVENT_NUM                    (PLDA_NUM_DMA_EVENTS + PLDA_INT_EVENT_NUM)
- /*
-  * PLDA interrupt register
-@@ -155,6 +157,7 @@ struct plda_pcie_rp {
-       raw_spinlock_t lock;
-       struct plda_msi msi;
-       const struct plda_event_ops *event_ops;
-+      const struct irq_chip *event_irq_chip;
-       void __iomem *bridge_addr;
-       int num_events;
- };
diff --git a/target/linux/starfive/patches-6.6/0029-PCI-microchip-Move-IRQ-functions-to-pcie-plda-host.c.patch b/target/linux/starfive/patches-6.6/0029-PCI-microchip-Move-IRQ-functions-to-pcie-plda-host.c.patch
deleted file mode 100644 (file)
index 840e334..0000000
+++ /dev/null
@@ -1,1028 +0,0 @@
-From 6be452d8e61594790ae57b282a612ec0df473e61 Mon Sep 17 00:00:00 2001
-From: Minda Chen <minda.chen@starfivetech.com>
-Date: Mon, 8 Jan 2024 19:06:06 +0800
-Subject: [PATCH 029/116] PCI: microchip: Move IRQ functions to
- pcie-plda-host.c
-
-Move IRQ related functions to pcie-plda-host.c for re-use these codes.
-Now Refactoring codes complete.
-
-Including MSI, INTx, event interrupts and IRQ init functions.
-
-Signed-off-by: Minda Chen <minda.chen@starfivetech.com>
-Acked-by: Conor Dooley <conor.dooley@microchip.com>
----
- .../pci/controller/plda/pcie-microchip-host.c | 467 -----------------
- drivers/pci/controller/plda/pcie-plda-host.c  | 472 ++++++++++++++++++
- drivers/pci/controller/plda/pcie-plda.h       |   3 +
- 3 files changed, 475 insertions(+), 467 deletions(-)
-
---- a/drivers/pci/controller/plda/pcie-microchip-host.c
-+++ b/drivers/pci/controller/plda/pcie-microchip-host.c
-@@ -318,244 +318,6 @@ static void mc_pcie_enable_msi(struct mc
-                      ecam + MC_MSI_CAP_CTRL_OFFSET + PCI_MSI_ADDRESS_HI);
- }
--static void plda_handle_msi(struct irq_desc *desc)
--{
--      struct plda_pcie_rp *port = irq_desc_get_handler_data(desc);
--      struct irq_chip *chip = irq_desc_get_chip(desc);
--      struct device *dev = port->dev;
--      struct plda_msi *msi = &port->msi;
--      void __iomem *bridge_base_addr = port->bridge_addr;
--      unsigned long status;
--      u32 bit;
--      int ret;
--
--      chained_irq_enter(chip, desc);
--
--      status = readl_relaxed(bridge_base_addr + ISTATUS_LOCAL);
--      if (status & PM_MSI_INT_MSI_MASK) {
--              writel_relaxed(status & PM_MSI_INT_MSI_MASK, bridge_base_addr + ISTATUS_LOCAL);
--              status = readl_relaxed(bridge_base_addr + ISTATUS_MSI);
--              for_each_set_bit(bit, &status, msi->num_vectors) {
--                      ret = generic_handle_domain_irq(msi->dev_domain, bit);
--                      if (ret)
--                              dev_err_ratelimited(dev, "bad MSI IRQ %d\n",
--                                                  bit);
--              }
--      }
--
--      chained_irq_exit(chip, desc);
--}
--
--static void plda_msi_bottom_irq_ack(struct irq_data *data)
--{
--      struct plda_pcie_rp *port = irq_data_get_irq_chip_data(data);
--      void __iomem *bridge_base_addr = port->bridge_addr;
--      u32 bitpos = data->hwirq;
--
--      writel_relaxed(BIT(bitpos), bridge_base_addr + ISTATUS_MSI);
--}
--
--static void plda_compose_msi_msg(struct irq_data *data, struct msi_msg *msg)
--{
--      struct plda_pcie_rp *port = irq_data_get_irq_chip_data(data);
--      phys_addr_t addr = port->msi.vector_phy;
--
--      msg->address_lo = lower_32_bits(addr);
--      msg->address_hi = upper_32_bits(addr);
--      msg->data = data->hwirq;
--
--      dev_dbg(port->dev, "msi#%x address_hi %#x address_lo %#x\n",
--              (int)data->hwirq, msg->address_hi, msg->address_lo);
--}
--
--static int plda_msi_set_affinity(struct irq_data *irq_data,
--                               const struct cpumask *mask, bool force)
--{
--      return -EINVAL;
--}
--
--static struct irq_chip plda_msi_bottom_irq_chip = {
--      .name = "PLDA MSI",
--      .irq_ack = plda_msi_bottom_irq_ack,
--      .irq_compose_msi_msg = plda_compose_msi_msg,
--      .irq_set_affinity = plda_msi_set_affinity,
--};
--
--static int plda_irq_msi_domain_alloc(struct irq_domain *domain,
--                                   unsigned int virq,
--                                   unsigned int nr_irqs,
--                                   void *args)
--{
--      struct plda_pcie_rp *port = domain->host_data;
--      struct plda_msi *msi = &port->msi;
--      unsigned long bit;
--
--      mutex_lock(&msi->lock);
--      bit = find_first_zero_bit(msi->used, msi->num_vectors);
--      if (bit >= msi->num_vectors) {
--              mutex_unlock(&msi->lock);
--              return -ENOSPC;
--      }
--
--      set_bit(bit, msi->used);
--
--      irq_domain_set_info(domain, virq, bit, &plda_msi_bottom_irq_chip,
--                          domain->host_data, handle_edge_irq, NULL, NULL);
--
--      mutex_unlock(&msi->lock);
--
--      return 0;
--}
--
--static void plda_irq_msi_domain_free(struct irq_domain *domain,
--                                   unsigned int virq,
--                                   unsigned int nr_irqs)
--{
--      struct irq_data *d = irq_domain_get_irq_data(domain, virq);
--      struct plda_pcie_rp *port = irq_data_get_irq_chip_data(d);
--      struct plda_msi *msi = &port->msi;
--
--      mutex_lock(&msi->lock);
--
--      if (test_bit(d->hwirq, msi->used))
--              __clear_bit(d->hwirq, msi->used);
--      else
--              dev_err(port->dev, "trying to free unused MSI%lu\n", d->hwirq);
--
--      mutex_unlock(&msi->lock);
--}
--
--static const struct irq_domain_ops msi_domain_ops = {
--      .alloc  = plda_irq_msi_domain_alloc,
--      .free   = plda_irq_msi_domain_free,
--};
--
--static struct irq_chip plda_msi_irq_chip = {
--      .name = "PLDA PCIe MSI",
--      .irq_ack = irq_chip_ack_parent,
--      .irq_mask = pci_msi_mask_irq,
--      .irq_unmask = pci_msi_unmask_irq,
--};
--
--static struct msi_domain_info plda_msi_domain_info = {
--      .flags = (MSI_FLAG_USE_DEF_DOM_OPS | MSI_FLAG_USE_DEF_CHIP_OPS |
--                MSI_FLAG_PCI_MSIX),
--      .chip = &plda_msi_irq_chip,
--};
--
--static int plda_allocate_msi_domains(struct plda_pcie_rp *port)
--{
--      struct device *dev = port->dev;
--      struct fwnode_handle *fwnode = of_node_to_fwnode(dev->of_node);
--      struct plda_msi *msi = &port->msi;
--
--      mutex_init(&port->msi.lock);
--
--      msi->dev_domain = irq_domain_add_linear(NULL, msi->num_vectors,
--                                              &msi_domain_ops, port);
--      if (!msi->dev_domain) {
--              dev_err(dev, "failed to create IRQ domain\n");
--              return -ENOMEM;
--      }
--
--      msi->msi_domain = pci_msi_create_irq_domain(fwnode,
--                                                  &plda_msi_domain_info,
--                                                  msi->dev_domain);
--      if (!msi->msi_domain) {
--              dev_err(dev, "failed to create MSI domain\n");
--              irq_domain_remove(msi->dev_domain);
--              return -ENOMEM;
--      }
--
--      return 0;
--}
--
--static void plda_handle_intx(struct irq_desc *desc)
--{
--      struct plda_pcie_rp *port = irq_desc_get_handler_data(desc);
--      struct irq_chip *chip = irq_desc_get_chip(desc);
--      struct device *dev = port->dev;
--      void __iomem *bridge_base_addr = port->bridge_addr;
--      unsigned long status;
--      u32 bit;
--      int ret;
--
--      chained_irq_enter(chip, desc);
--
--      status = readl_relaxed(bridge_base_addr + ISTATUS_LOCAL);
--      if (status & PM_MSI_INT_INTX_MASK) {
--              status &= PM_MSI_INT_INTX_MASK;
--              status >>= PM_MSI_INT_INTX_SHIFT;
--              for_each_set_bit(bit, &status, PCI_NUM_INTX) {
--                      ret = generic_handle_domain_irq(port->intx_domain, bit);
--                      if (ret)
--                              dev_err_ratelimited(dev, "bad INTx IRQ %d\n",
--                                                  bit);
--              }
--      }
--
--      chained_irq_exit(chip, desc);
--}
--
--static void plda_ack_intx_irq(struct irq_data *data)
--{
--      struct plda_pcie_rp *port = irq_data_get_irq_chip_data(data);
--      void __iomem *bridge_base_addr = port->bridge_addr;
--      u32 mask = BIT(data->hwirq + PM_MSI_INT_INTX_SHIFT);
--
--      writel_relaxed(mask, bridge_base_addr + ISTATUS_LOCAL);
--}
--
--static void plda_mask_intx_irq(struct irq_data *data)
--{
--      struct plda_pcie_rp *port = irq_data_get_irq_chip_data(data);
--      void __iomem *bridge_base_addr = port->bridge_addr;
--      unsigned long flags;
--      u32 mask = BIT(data->hwirq + PM_MSI_INT_INTX_SHIFT);
--      u32 val;
--
--      raw_spin_lock_irqsave(&port->lock, flags);
--      val = readl_relaxed(bridge_base_addr + IMASK_LOCAL);
--      val &= ~mask;
--      writel_relaxed(val, bridge_base_addr + IMASK_LOCAL);
--      raw_spin_unlock_irqrestore(&port->lock, flags);
--}
--
--static void plda_unmask_intx_irq(struct irq_data *data)
--{
--      struct plda_pcie_rp *port = irq_data_get_irq_chip_data(data);
--      void __iomem *bridge_base_addr = port->bridge_addr;
--      unsigned long flags;
--      u32 mask = BIT(data->hwirq + PM_MSI_INT_INTX_SHIFT);
--      u32 val;
--
--      raw_spin_lock_irqsave(&port->lock, flags);
--      val = readl_relaxed(bridge_base_addr + IMASK_LOCAL);
--      val |= mask;
--      writel_relaxed(val, bridge_base_addr + IMASK_LOCAL);
--      raw_spin_unlock_irqrestore(&port->lock, flags);
--}
--
--static struct irq_chip plda_intx_irq_chip = {
--      .name = "PLDA PCIe INTx",
--      .irq_ack = plda_ack_intx_irq,
--      .irq_mask = plda_mask_intx_irq,
--      .irq_unmask = plda_unmask_intx_irq,
--};
--
--static int plda_pcie_intx_map(struct irq_domain *domain, unsigned int irq,
--                            irq_hw_number_t hwirq)
--{
--      irq_set_chip_and_handler(irq, &plda_intx_irq_chip, handle_level_irq);
--      irq_set_chip_data(irq, domain->host_data);
--
--      return 0;
--}
--
--static const struct irq_domain_ops intx_domain_ops = {
--      .map = plda_pcie_intx_map,
--};
--
- static inline u32 reg_to_event(u32 reg, struct event_map field)
- {
-       return (reg & field.reg_mask) ? BIT(field.event_bit) : 0;
-@@ -626,26 +388,6 @@ static u32 mc_get_events(struct plda_pci
-       return events;
- }
--static u32 plda_get_events(struct plda_pcie_rp *port)
--{
--      u32 events, val, origin;
--
--      origin = readl_relaxed(port->bridge_addr + ISTATUS_LOCAL);
--
--      /* MSI event and sys events */
--      val = (origin & SYS_AND_MSI_MASK) >> PM_MSI_INT_MSI_SHIFT;
--      events = val << (PM_MSI_INT_MSI_SHIFT - PCI_NUM_INTX + 1);
--
--      /* INTx events */
--      if (origin & PM_MSI_INT_INTX_MASK)
--              events |= BIT(PM_MSI_INT_INTX_SHIFT);
--
--      /* remains are same with register */
--      events |= origin & GENMASK(P_ATR_EVT_DOORBELL_SHIFT, 0);
--
--      return events;
--}
--
- static irqreturn_t mc_event_handler(int irq, void *dev_id)
- {
-       struct plda_pcie_rp *port = dev_id;
-@@ -662,28 +404,6 @@ static irqreturn_t mc_event_handler(int
-       return IRQ_HANDLED;
- }
--static irqreturn_t plda_event_handler(int irq, void *dev_id)
--{
--      return IRQ_HANDLED;
--}
--
--static void plda_handle_event(struct irq_desc *desc)
--{
--      struct plda_pcie_rp *port = irq_desc_get_handler_data(desc);
--      unsigned long events;
--      u32 bit;
--      struct irq_chip *chip = irq_desc_get_chip(desc);
--
--      chained_irq_enter(chip, desc);
--
--      events = port->event_ops->get_events(port);
--
--      for_each_set_bit(bit, &events, port->num_events)
--              generic_handle_domain_irq(port->event_domain, bit);
--
--      chained_irq_exit(chip, desc);
--}
--
- static void mc_ack_event_irq(struct irq_data *data)
- {
-       struct plda_pcie_rp *port = irq_data_get_irq_chip_data(data);
-@@ -770,83 +490,6 @@ static struct irq_chip mc_event_irq_chip
-       .irq_unmask = mc_unmask_event_irq,
- };
--static u32 plda_hwirq_to_mask(int hwirq)
--{
--      u32 mask;
--
--      /* hwirq 23 - 0 are the same with register */
--      if (hwirq < EVENT_PM_MSI_INT_INTX)
--              mask = BIT(hwirq);
--      else if (hwirq == EVENT_PM_MSI_INT_INTX)
--              mask = PM_MSI_INT_INTX_MASK;
--      else
--              mask = BIT(hwirq + PCI_NUM_INTX - 1);
--
--      return mask;
--}
--
--static void plda_ack_event_irq(struct irq_data *data)
--{
--      struct plda_pcie_rp *port = irq_data_get_irq_chip_data(data);
--
--      writel_relaxed(plda_hwirq_to_mask(data->hwirq),
--                     port->bridge_addr + ISTATUS_LOCAL);
--}
--
--static void plda_mask_event_irq(struct irq_data *data)
--{
--      struct plda_pcie_rp *port = irq_data_get_irq_chip_data(data);
--      u32 mask, val;
--
--      mask = plda_hwirq_to_mask(data->hwirq);
--
--      raw_spin_lock(&port->lock);
--      val = readl_relaxed(port->bridge_addr + IMASK_LOCAL);
--      val &= ~mask;
--      writel_relaxed(val, port->bridge_addr + IMASK_LOCAL);
--      raw_spin_unlock(&port->lock);
--}
--
--static void plda_unmask_event_irq(struct irq_data *data)
--{
--      struct plda_pcie_rp *port = irq_data_get_irq_chip_data(data);
--      u32 mask, val;
--
--      mask = plda_hwirq_to_mask(data->hwirq);
--
--      raw_spin_lock(&port->lock);
--      val = readl_relaxed(port->bridge_addr + IMASK_LOCAL);
--      val |= mask;
--      writel_relaxed(val, port->bridge_addr + IMASK_LOCAL);
--      raw_spin_unlock(&port->lock);
--}
--
--static struct irq_chip plda_event_irq_chip = {
--      .name = "PLDA PCIe EVENT",
--      .irq_ack = plda_ack_event_irq,
--      .irq_mask = plda_mask_event_irq,
--      .irq_unmask = plda_unmask_event_irq,
--};
--
--static const struct plda_event_ops plda_event_ops = {
--      .get_events = plda_get_events,
--};
--
--static int plda_pcie_event_map(struct irq_domain *domain, unsigned int irq,
--                             irq_hw_number_t hwirq)
--{
--      struct plda_pcie_rp *port = (void *)domain->host_data;
--
--      irq_set_chip_and_handler(irq, port->event_irq_chip, handle_level_irq);
--      irq_set_chip_data(irq, domain->host_data);
--
--      return 0;
--}
--
--static const struct irq_domain_ops plda_event_domain_ops = {
--      .map = plda_pcie_event_map,
--};
--
- static inline void mc_pcie_deinit_clk(void *data)
- {
-       struct clk *clk = data;
-@@ -909,47 +552,6 @@ static const struct plda_event mc_event
-       .msi_event         = EVENT_LOCAL_PM_MSI_INT_MSI,
- };
--static int plda_pcie_init_irq_domains(struct plda_pcie_rp *port)
--{
--      struct device *dev = port->dev;
--      struct device_node *node = dev->of_node;
--      struct device_node *pcie_intc_node;
--
--      /* Setup INTx */
--      pcie_intc_node = of_get_next_child(node, NULL);
--      if (!pcie_intc_node) {
--              dev_err(dev, "failed to find PCIe Intc node\n");
--              return -EINVAL;
--      }
--
--      port->event_domain = irq_domain_add_linear(pcie_intc_node,
--                                                 port->num_events,
--                                                 &plda_event_domain_ops,
--                                                 port);
--      if (!port->event_domain) {
--              dev_err(dev, "failed to get event domain\n");
--              of_node_put(pcie_intc_node);
--              return -ENOMEM;
--      }
--
--      irq_domain_update_bus_token(port->event_domain, DOMAIN_BUS_NEXUS);
--
--      port->intx_domain = irq_domain_add_linear(pcie_intc_node, PCI_NUM_INTX,
--                                                &intx_domain_ops, port);
--      if (!port->intx_domain) {
--              dev_err(dev, "failed to get an INTx IRQ domain\n");
--              of_node_put(pcie_intc_node);
--              return -ENOMEM;
--      }
--
--      irq_domain_update_bus_token(port->intx_domain, DOMAIN_BUS_WIRED);
--
--      of_node_put(pcie_intc_node);
--      raw_spin_lock_init(&port->lock);
--
--      return plda_allocate_msi_domains(port);
--}
--
- static inline void mc_clear_secs(struct mc_pcie *port)
- {
-       void __iomem *ctrl_base_addr = port->axi_base_addr + MC_PCIE_CTRL_ADDR;
-@@ -1010,75 +612,6 @@ static void mc_disable_interrupts(struct
-       writel_relaxed(GENMASK(31, 0), bridge_base_addr + ISTATUS_HOST);
- }
--static int plda_init_interrupts(struct platform_device *pdev,
--                              struct plda_pcie_rp *port,
--                              const struct plda_event *event)
--{
--      struct device *dev = &pdev->dev;
--      int irq;
--      int i, intx_irq, msi_irq, event_irq;
--      int ret;
--
--      if (!port->event_ops)
--              port->event_ops = &plda_event_ops;
--
--      if (!port->event_irq_chip)
--              port->event_irq_chip = &plda_event_irq_chip;
--
--      ret = plda_pcie_init_irq_domains(port);
--      if (ret) {
--              dev_err(dev, "failed creating IRQ domains\n");
--              return ret;
--      }
--
--      irq = platform_get_irq(pdev, 0);
--      if (irq < 0)
--              return -ENODEV;
--
--      for (i = 0; i < port->num_events; i++) {
--              event_irq = irq_create_mapping(port->event_domain, i);
--              if (!event_irq) {
--                      dev_err(dev, "failed to map hwirq %d\n", i);
--                      return -ENXIO;
--              }
--
--              if (event->request_event_irq)
--                      ret = event->request_event_irq(port, event_irq, i);
--              else
--                      ret = devm_request_irq(dev, event_irq,
--                                             plda_event_handler,
--                                             0, NULL, port);
--
--              if (ret) {
--                      dev_err(dev, "failed to request IRQ %d\n", event_irq);
--                      return ret;
--              }
--      }
--
--      intx_irq = irq_create_mapping(port->event_domain,
--                                    event->intx_event);
--      if (!intx_irq) {
--              dev_err(dev, "failed to map INTx interrupt\n");
--              return -ENXIO;
--      }
--
--      /* Plug the INTx chained handler */
--      irq_set_chained_handler_and_data(intx_irq, plda_handle_intx, port);
--
--      msi_irq = irq_create_mapping(port->event_domain,
--                                   event->msi_event);
--      if (!msi_irq)
--              return -ENXIO;
--
--      /* Plug the MSI chained handler */
--      irq_set_chained_handler_and_data(msi_irq, plda_handle_msi, port);
--
--      /* Plug the main event chained handler */
--      irq_set_chained_handler_and_data(irq, plda_handle_event, port);
--
--      return 0;
--}
--
- static int mc_platform_init(struct pci_config_window *cfg)
- {
-       struct device *dev = cfg->parent;
---- a/drivers/pci/controller/plda/pcie-plda-host.c
-+++ b/drivers/pci/controller/plda/pcie-plda-host.c
-@@ -7,11 +7,483 @@
-  * Author: Daire McNamara <daire.mcnamara@microchip.com>
-  */
-+#include <linux/irqchip/chained_irq.h>
-+#include <linux/irqdomain.h>
-+#include <linux/msi.h>
- #include <linux/pci_regs.h>
- #include <linux/pci-ecam.h>
- #include "pcie-plda.h"
-+static void plda_handle_msi(struct irq_desc *desc)
-+{
-+      struct plda_pcie_rp *port = irq_desc_get_handler_data(desc);
-+      struct irq_chip *chip = irq_desc_get_chip(desc);
-+      struct device *dev = port->dev;
-+      struct plda_msi *msi = &port->msi;
-+      void __iomem *bridge_base_addr = port->bridge_addr;
-+      unsigned long status;
-+      u32 bit;
-+      int ret;
-+
-+      chained_irq_enter(chip, desc);
-+
-+      status = readl_relaxed(bridge_base_addr + ISTATUS_LOCAL);
-+      if (status & PM_MSI_INT_MSI_MASK) {
-+              writel_relaxed(status & PM_MSI_INT_MSI_MASK,
-+                             bridge_base_addr + ISTATUS_LOCAL);
-+              status = readl_relaxed(bridge_base_addr + ISTATUS_MSI);
-+              for_each_set_bit(bit, &status, msi->num_vectors) {
-+                      ret = generic_handle_domain_irq(msi->dev_domain, bit);
-+                      if (ret)
-+                              dev_err_ratelimited(dev, "bad MSI IRQ %d\n",
-+                                                  bit);
-+              }
-+      }
-+
-+      chained_irq_exit(chip, desc);
-+}
-+
-+static void plda_msi_bottom_irq_ack(struct irq_data *data)
-+{
-+      struct plda_pcie_rp *port = irq_data_get_irq_chip_data(data);
-+      void __iomem *bridge_base_addr = port->bridge_addr;
-+      u32 bitpos = data->hwirq;
-+
-+      writel_relaxed(BIT(bitpos), bridge_base_addr + ISTATUS_MSI);
-+}
-+
-+static void plda_compose_msi_msg(struct irq_data *data, struct msi_msg *msg)
-+{
-+      struct plda_pcie_rp *port = irq_data_get_irq_chip_data(data);
-+      phys_addr_t addr = port->msi.vector_phy;
-+
-+      msg->address_lo = lower_32_bits(addr);
-+      msg->address_hi = upper_32_bits(addr);
-+      msg->data = data->hwirq;
-+
-+      dev_dbg(port->dev, "msi#%x address_hi %#x address_lo %#x\n",
-+              (int)data->hwirq, msg->address_hi, msg->address_lo);
-+}
-+
-+static int plda_msi_set_affinity(struct irq_data *irq_data,
-+                               const struct cpumask *mask, bool force)
-+{
-+      return -EINVAL;
-+}
-+
-+static struct irq_chip plda_msi_bottom_irq_chip = {
-+      .name = "PLDA MSI",
-+      .irq_ack = plda_msi_bottom_irq_ack,
-+      .irq_compose_msi_msg = plda_compose_msi_msg,
-+      .irq_set_affinity = plda_msi_set_affinity,
-+};
-+
-+static int plda_irq_msi_domain_alloc(struct irq_domain *domain,
-+                                   unsigned int virq,
-+                                   unsigned int nr_irqs,
-+                                   void *args)
-+{
-+      struct plda_pcie_rp *port = domain->host_data;
-+      struct plda_msi *msi = &port->msi;
-+      unsigned long bit;
-+
-+      mutex_lock(&msi->lock);
-+      bit = find_first_zero_bit(msi->used, msi->num_vectors);
-+      if (bit >= msi->num_vectors) {
-+              mutex_unlock(&msi->lock);
-+              return -ENOSPC;
-+      }
-+
-+      set_bit(bit, msi->used);
-+
-+      irq_domain_set_info(domain, virq, bit, &plda_msi_bottom_irq_chip,
-+                          domain->host_data, handle_edge_irq, NULL, NULL);
-+
-+      mutex_unlock(&msi->lock);
-+
-+      return 0;
-+}
-+
-+static void plda_irq_msi_domain_free(struct irq_domain *domain,
-+                                   unsigned int virq,
-+                                   unsigned int nr_irqs)
-+{
-+      struct irq_data *d = irq_domain_get_irq_data(domain, virq);
-+      struct plda_pcie_rp *port = irq_data_get_irq_chip_data(d);
-+      struct plda_msi *msi = &port->msi;
-+
-+      mutex_lock(&msi->lock);
-+
-+      if (test_bit(d->hwirq, msi->used))
-+              __clear_bit(d->hwirq, msi->used);
-+      else
-+              dev_err(port->dev, "trying to free unused MSI%lu\n", d->hwirq);
-+
-+      mutex_unlock(&msi->lock);
-+}
-+
-+static const struct irq_domain_ops msi_domain_ops = {
-+      .alloc  = plda_irq_msi_domain_alloc,
-+      .free   = plda_irq_msi_domain_free,
-+};
-+
-+static struct irq_chip plda_msi_irq_chip = {
-+      .name = "PLDA PCIe MSI",
-+      .irq_ack = irq_chip_ack_parent,
-+      .irq_mask = pci_msi_mask_irq,
-+      .irq_unmask = pci_msi_unmask_irq,
-+};
-+
-+static struct msi_domain_info plda_msi_domain_info = {
-+      .flags = (MSI_FLAG_USE_DEF_DOM_OPS | MSI_FLAG_USE_DEF_CHIP_OPS |
-+                MSI_FLAG_PCI_MSIX),
-+      .chip = &plda_msi_irq_chip,
-+};
-+
-+static int plda_allocate_msi_domains(struct plda_pcie_rp *port)
-+{
-+      struct device *dev = port->dev;
-+      struct fwnode_handle *fwnode = of_node_to_fwnode(dev->of_node);
-+      struct plda_msi *msi = &port->msi;
-+
-+      mutex_init(&port->msi.lock);
-+
-+      msi->dev_domain = irq_domain_add_linear(NULL, msi->num_vectors,
-+                                              &msi_domain_ops, port);
-+      if (!msi->dev_domain) {
-+              dev_err(dev, "failed to create IRQ domain\n");
-+              return -ENOMEM;
-+      }
-+
-+      msi->msi_domain = pci_msi_create_irq_domain(fwnode,
-+                                                  &plda_msi_domain_info,
-+                                                  msi->dev_domain);
-+      if (!msi->msi_domain) {
-+              dev_err(dev, "failed to create MSI domain\n");
-+              irq_domain_remove(msi->dev_domain);
-+              return -ENOMEM;
-+      }
-+
-+      return 0;
-+}
-+
-+static void plda_handle_intx(struct irq_desc *desc)
-+{
-+      struct plda_pcie_rp *port = irq_desc_get_handler_data(desc);
-+      struct irq_chip *chip = irq_desc_get_chip(desc);
-+      struct device *dev = port->dev;
-+      void __iomem *bridge_base_addr = port->bridge_addr;
-+      unsigned long status;
-+      u32 bit;
-+      int ret;
-+
-+      chained_irq_enter(chip, desc);
-+
-+      status = readl_relaxed(bridge_base_addr + ISTATUS_LOCAL);
-+      if (status & PM_MSI_INT_INTX_MASK) {
-+              status &= PM_MSI_INT_INTX_MASK;
-+              status >>= PM_MSI_INT_INTX_SHIFT;
-+              for_each_set_bit(bit, &status, PCI_NUM_INTX) {
-+                      ret = generic_handle_domain_irq(port->intx_domain, bit);
-+                      if (ret)
-+                              dev_err_ratelimited(dev, "bad INTx IRQ %d\n",
-+                                                  bit);
-+              }
-+      }
-+
-+      chained_irq_exit(chip, desc);
-+}
-+
-+static void plda_ack_intx_irq(struct irq_data *data)
-+{
-+      struct plda_pcie_rp *port = irq_data_get_irq_chip_data(data);
-+      void __iomem *bridge_base_addr = port->bridge_addr;
-+      u32 mask = BIT(data->hwirq + PM_MSI_INT_INTX_SHIFT);
-+
-+      writel_relaxed(mask, bridge_base_addr + ISTATUS_LOCAL);
-+}
-+
-+static void plda_mask_intx_irq(struct irq_data *data)
-+{
-+      struct plda_pcie_rp *port = irq_data_get_irq_chip_data(data);
-+      void __iomem *bridge_base_addr = port->bridge_addr;
-+      unsigned long flags;
-+      u32 mask = BIT(data->hwirq + PM_MSI_INT_INTX_SHIFT);
-+      u32 val;
-+
-+      raw_spin_lock_irqsave(&port->lock, flags);
-+      val = readl_relaxed(bridge_base_addr + IMASK_LOCAL);
-+      val &= ~mask;
-+      writel_relaxed(val, bridge_base_addr + IMASK_LOCAL);
-+      raw_spin_unlock_irqrestore(&port->lock, flags);
-+}
-+
-+static void plda_unmask_intx_irq(struct irq_data *data)
-+{
-+      struct plda_pcie_rp *port = irq_data_get_irq_chip_data(data);
-+      void __iomem *bridge_base_addr = port->bridge_addr;
-+      unsigned long flags;
-+      u32 mask = BIT(data->hwirq + PM_MSI_INT_INTX_SHIFT);
-+      u32 val;
-+
-+      raw_spin_lock_irqsave(&port->lock, flags);
-+      val = readl_relaxed(bridge_base_addr + IMASK_LOCAL);
-+      val |= mask;
-+      writel_relaxed(val, bridge_base_addr + IMASK_LOCAL);
-+      raw_spin_unlock_irqrestore(&port->lock, flags);
-+}
-+
-+static struct irq_chip plda_intx_irq_chip = {
-+      .name = "PLDA PCIe INTx",
-+      .irq_ack = plda_ack_intx_irq,
-+      .irq_mask = plda_mask_intx_irq,
-+      .irq_unmask = plda_unmask_intx_irq,
-+};
-+
-+static int plda_pcie_intx_map(struct irq_domain *domain, unsigned int irq,
-+                            irq_hw_number_t hwirq)
-+{
-+      irq_set_chip_and_handler(irq, &plda_intx_irq_chip, handle_level_irq);
-+      irq_set_chip_data(irq, domain->host_data);
-+
-+      return 0;
-+}
-+
-+static const struct irq_domain_ops intx_domain_ops = {
-+      .map = plda_pcie_intx_map,
-+};
-+
-+static u32 plda_get_events(struct plda_pcie_rp *port)
-+{
-+      u32 events, val, origin;
-+
-+      origin = readl_relaxed(port->bridge_addr + ISTATUS_LOCAL);
-+
-+      /* MSI event and sys events */
-+      val = (origin & SYS_AND_MSI_MASK) >> PM_MSI_INT_MSI_SHIFT;
-+      events = val << (PM_MSI_INT_MSI_SHIFT - PCI_NUM_INTX + 1);
-+
-+      /* INTx events */
-+      if (origin & PM_MSI_INT_INTX_MASK)
-+              events |= BIT(PM_MSI_INT_INTX_SHIFT);
-+
-+      /* remains are same with register */
-+      events |= origin & GENMASK(P_ATR_EVT_DOORBELL_SHIFT, 0);
-+
-+      return events;
-+}
-+
-+static irqreturn_t plda_event_handler(int irq, void *dev_id)
-+{
-+      return IRQ_HANDLED;
-+}
-+
-+static void plda_handle_event(struct irq_desc *desc)
-+{
-+      struct plda_pcie_rp *port = irq_desc_get_handler_data(desc);
-+      unsigned long events;
-+      u32 bit;
-+      struct irq_chip *chip = irq_desc_get_chip(desc);
-+
-+      chained_irq_enter(chip, desc);
-+
-+      events = port->event_ops->get_events(port);
-+
-+      for_each_set_bit(bit, &events, port->num_events)
-+              generic_handle_domain_irq(port->event_domain, bit);
-+
-+      chained_irq_exit(chip, desc);
-+}
-+
-+static u32 plda_hwirq_to_mask(int hwirq)
-+{
-+      u32 mask;
-+
-+      /* hwirq 23 - 0 are the same with register */
-+      if (hwirq < EVENT_PM_MSI_INT_INTX)
-+              mask = BIT(hwirq);
-+      else if (hwirq == EVENT_PM_MSI_INT_INTX)
-+              mask = PM_MSI_INT_INTX_MASK;
-+      else
-+              mask = BIT(hwirq + PCI_NUM_INTX - 1);
-+
-+      return mask;
-+}
-+
-+static void plda_ack_event_irq(struct irq_data *data)
-+{
-+      struct plda_pcie_rp *port = irq_data_get_irq_chip_data(data);
-+
-+      writel_relaxed(plda_hwirq_to_mask(data->hwirq),
-+                     port->bridge_addr + ISTATUS_LOCAL);
-+}
-+
-+static void plda_mask_event_irq(struct irq_data *data)
-+{
-+      struct plda_pcie_rp *port = irq_data_get_irq_chip_data(data);
-+      u32 mask, val;
-+
-+      mask = plda_hwirq_to_mask(data->hwirq);
-+
-+      raw_spin_lock(&port->lock);
-+      val = readl_relaxed(port->bridge_addr + IMASK_LOCAL);
-+      val &= ~mask;
-+      writel_relaxed(val, port->bridge_addr + IMASK_LOCAL);
-+      raw_spin_unlock(&port->lock);
-+}
-+
-+static void plda_unmask_event_irq(struct irq_data *data)
-+{
-+      struct plda_pcie_rp *port = irq_data_get_irq_chip_data(data);
-+      u32 mask, val;
-+
-+      mask = plda_hwirq_to_mask(data->hwirq);
-+
-+      raw_spin_lock(&port->lock);
-+      val = readl_relaxed(port->bridge_addr + IMASK_LOCAL);
-+      val |= mask;
-+      writel_relaxed(val, port->bridge_addr + IMASK_LOCAL);
-+      raw_spin_unlock(&port->lock);
-+}
-+
-+static struct irq_chip plda_event_irq_chip = {
-+      .name = "PLDA PCIe EVENT",
-+      .irq_ack = plda_ack_event_irq,
-+      .irq_mask = plda_mask_event_irq,
-+      .irq_unmask = plda_unmask_event_irq,
-+};
-+
-+static const struct plda_event_ops plda_event_ops = {
-+      .get_events = plda_get_events,
-+};
-+
-+static int plda_pcie_event_map(struct irq_domain *domain, unsigned int irq,
-+                             irq_hw_number_t hwirq)
-+{
-+      struct plda_pcie_rp *port = (void *)domain->host_data;
-+
-+      irq_set_chip_and_handler(irq, port->event_irq_chip, handle_level_irq);
-+      irq_set_chip_data(irq, domain->host_data);
-+
-+      return 0;
-+}
-+
-+static const struct irq_domain_ops plda_event_domain_ops = {
-+      .map = plda_pcie_event_map,
-+};
-+
-+static int plda_pcie_init_irq_domains(struct plda_pcie_rp *port)
-+{
-+      struct device *dev = port->dev;
-+      struct device_node *node = dev->of_node;
-+      struct device_node *pcie_intc_node;
-+
-+      /* Setup INTx */
-+      pcie_intc_node = of_get_next_child(node, NULL);
-+      if (!pcie_intc_node) {
-+              dev_err(dev, "failed to find PCIe Intc node\n");
-+              return -EINVAL;
-+      }
-+
-+      port->event_domain = irq_domain_add_linear(pcie_intc_node,
-+                                                 port->num_events,
-+                                                 &plda_event_domain_ops,
-+                                                 port);
-+      if (!port->event_domain) {
-+              dev_err(dev, "failed to get event domain\n");
-+              of_node_put(pcie_intc_node);
-+              return -ENOMEM;
-+      }
-+
-+      irq_domain_update_bus_token(port->event_domain, DOMAIN_BUS_NEXUS);
-+
-+      port->intx_domain = irq_domain_add_linear(pcie_intc_node, PCI_NUM_INTX,
-+                                                &intx_domain_ops, port);
-+      if (!port->intx_domain) {
-+              dev_err(dev, "failed to get an INTx IRQ domain\n");
-+              of_node_put(pcie_intc_node);
-+              return -ENOMEM;
-+      }
-+
-+      irq_domain_update_bus_token(port->intx_domain, DOMAIN_BUS_WIRED);
-+
-+      of_node_put(pcie_intc_node);
-+      raw_spin_lock_init(&port->lock);
-+
-+      return plda_allocate_msi_domains(port);
-+}
-+
-+int plda_init_interrupts(struct platform_device *pdev,
-+                       struct plda_pcie_rp *port,
-+                       const struct plda_event *event)
-+{
-+      struct device *dev = &pdev->dev;
-+      int irq;
-+      int i, intx_irq, msi_irq, event_irq;
-+      int ret;
-+
-+      if (!port->event_ops)
-+              port->event_ops = &plda_event_ops;
-+
-+      if (!port->event_irq_chip)
-+              port->event_irq_chip = &plda_event_irq_chip;
-+
-+      ret = plda_pcie_init_irq_domains(port);
-+      if (ret) {
-+              dev_err(dev, "failed creating IRQ domains\n");
-+              return ret;
-+      }
-+
-+      irq = platform_get_irq(pdev, 0);
-+      if (irq < 0)
-+              return -ENODEV;
-+
-+      for (i = 0; i < port->num_events; i++) {
-+              event_irq = irq_create_mapping(port->event_domain, i);
-+              if (!event_irq) {
-+                      dev_err(dev, "failed to map hwirq %d\n", i);
-+                      return -ENXIO;
-+              }
-+
-+              if (event->request_event_irq)
-+                      ret = event->request_event_irq(port, event_irq, i);
-+              else
-+                      ret = devm_request_irq(dev, event_irq,
-+                                             plda_event_handler,
-+                                             0, NULL, port);
-+
-+              if (ret) {
-+                      dev_err(dev, "failed to request IRQ %d\n", event_irq);
-+                      return ret;
-+              }
-+      }
-+
-+      intx_irq = irq_create_mapping(port->event_domain,
-+                                    event->intx_event);
-+      if (!intx_irq) {
-+              dev_err(dev, "failed to map INTx interrupt\n");
-+              return -ENXIO;
-+      }
-+
-+      /* Plug the INTx chained handler */
-+      irq_set_chained_handler_and_data(intx_irq, plda_handle_intx, port);
-+
-+      msi_irq = irq_create_mapping(port->event_domain,
-+                                   event->msi_event);
-+      if (!msi_irq)
-+              return -ENXIO;
-+
-+      /* Plug the MSI chained handler */
-+      irq_set_chained_handler_and_data(msi_irq, plda_handle_msi, port);
-+
-+      /* Plug the main event chained handler */
-+      irq_set_chained_handler_and_data(irq, plda_handle_event, port);
-+
-+      return 0;
-+}
-+EXPORT_SYMBOL_GPL(plda_init_interrupts);
-+
- void plda_pcie_setup_window(void __iomem *bridge_base_addr, u32 index,
-                           phys_addr_t axi_addr, phys_addr_t pci_addr,
-                           size_t size)
---- a/drivers/pci/controller/plda/pcie-plda.h
-+++ b/drivers/pci/controller/plda/pcie-plda.h
-@@ -169,6 +169,9 @@ struct plda_event {
-       int msi_event;
- };
-+int plda_init_interrupts(struct platform_device *pdev,
-+                       struct plda_pcie_rp *port,
-+                       const struct plda_event *event);
- void plda_pcie_setup_window(void __iomem *bridge_base_addr, u32 index,
-                           phys_addr_t axi_addr, phys_addr_t pci_addr,
-                           size_t size);
diff --git a/target/linux/starfive/patches-6.6/0030-pci-plda-Add-event-bitmap-field-to-struct-plda_pcie_.patch b/target/linux/starfive/patches-6.6/0030-pci-plda-Add-event-bitmap-field-to-struct-plda_pcie_.patch
deleted file mode 100644 (file)
index dcd2310..0000000
+++ /dev/null
@@ -1,67 +0,0 @@
-From 142fc300fd7511a217783dcfa342031d8ad70188 Mon Sep 17 00:00:00 2001
-From: Minda Chen <minda.chen@starfivetech.com>
-Date: Mon, 8 Jan 2024 19:06:07 +0800
-Subject: [PATCH 030/116] pci: plda: Add event bitmap field to struct
- plda_pcie_rp
-
-For PLDA DMA interrupts are not all implemented. The non-implemented
-interrupts should be masked. So add a bitmap field to mask the non-
-implemented interrupts.
-
-Signed-off-by: Minda Chen <minda.chen@starfivetech.com>
----
- drivers/pci/controller/plda/pcie-microchip-host.c | 1 +
- drivers/pci/controller/plda/pcie-plda-host.c      | 6 ++++--
- drivers/pci/controller/plda/pcie-plda.h           | 1 +
- 3 files changed, 6 insertions(+), 2 deletions(-)
-
---- a/drivers/pci/controller/plda/pcie-microchip-host.c
-+++ b/drivers/pci/controller/plda/pcie-microchip-host.c
-@@ -636,6 +636,7 @@ static int mc_platform_init(struct pci_c
-       port->plda.event_ops = &mc_event_ops;
-       port->plda.event_irq_chip = &mc_event_irq_chip;
-+      port->plda.events_bitmap = GENMASK(NUM_EVENTS - 1, 0);
-       /* Address translation is up; safe to enable interrupts */
-       ret = plda_init_interrupts(pdev, &port->plda, &mc_event);
---- a/drivers/pci/controller/plda/pcie-plda-host.c
-+++ b/drivers/pci/controller/plda/pcie-plda-host.c
-@@ -290,6 +290,7 @@ static void plda_handle_event(struct irq
-       events = port->event_ops->get_events(port);
-+      events &= port->events_bitmap;
-       for_each_set_bit(bit, &events, port->num_events)
-               generic_handle_domain_irq(port->event_domain, bit);
-@@ -420,8 +421,9 @@ int plda_init_interrupts(struct platform
- {
-       struct device *dev = &pdev->dev;
-       int irq;
--      int i, intx_irq, msi_irq, event_irq;
-+      int intx_irq, msi_irq, event_irq;
-       int ret;
-+      u32 i;
-       if (!port->event_ops)
-               port->event_ops = &plda_event_ops;
-@@ -439,7 +441,7 @@ int plda_init_interrupts(struct platform
-       if (irq < 0)
-               return -ENODEV;
--      for (i = 0; i < port->num_events; i++) {
-+      for_each_set_bit(i, &port->events_bitmap, port->num_events) {
-               event_irq = irq_create_mapping(port->event_domain, i);
-               if (!event_irq) {
-                       dev_err(dev, "failed to map hwirq %d\n", i);
---- a/drivers/pci/controller/plda/pcie-plda.h
-+++ b/drivers/pci/controller/plda/pcie-plda.h
-@@ -159,6 +159,7 @@ struct plda_pcie_rp {
-       const struct plda_event_ops *event_ops;
-       const struct irq_chip *event_irq_chip;
-       void __iomem *bridge_addr;
-+      unsigned long events_bitmap;
-       int num_events;
- };
diff --git a/target/linux/starfive/patches-6.6/0031-PCI-plda-Add-host-init-deinit-and-map-bus-functions.patch b/target/linux/starfive/patches-6.6/0031-PCI-plda-Add-host-init-deinit-and-map-bus-functions.patch
deleted file mode 100644 (file)
index eb22849..0000000
+++ /dev/null
@@ -1,256 +0,0 @@
-From 3b9991438094dc472dacb4555603bdc379653411 Mon Sep 17 00:00:00 2001
-From: Minda Chen <minda.chen@starfivetech.com>
-Date: Mon, 8 Jan 2024 19:06:08 +0800
-Subject: [PATCH 031/116] PCI: plda: Add host init/deinit and map bus functions
-
-Add PLDA host plda_pcie_host_init()/plda_pcie_host_deinit() and map bus
-function. So vendor can use it to init PLDA PCIe host core.
-
-Signed-off-by: Minda Chen <minda.chen@starfivetech.com>
-Reviewed-by: Mason Huo <mason.huo@starfivetech.com>
----
- drivers/pci/controller/plda/pcie-plda-host.c | 131 +++++++++++++++++--
- drivers/pci/controller/plda/pcie-plda.h      |  22 ++++
- 2 files changed, 139 insertions(+), 14 deletions(-)
-
---- a/drivers/pci/controller/plda/pcie-plda-host.c
-+++ b/drivers/pci/controller/plda/pcie-plda-host.c
-@@ -3,6 +3,7 @@
-  * PLDA PCIe XpressRich host controller driver
-  *
-  * Copyright (C) 2023 Microchip Co. Ltd
-+ *                  StarFive Co. Ltd
-  *
-  * Author: Daire McNamara <daire.mcnamara@microchip.com>
-  */
-@@ -15,6 +16,15 @@
- #include "pcie-plda.h"
-+void __iomem *plda_pcie_map_bus(struct pci_bus *bus, unsigned int devfn,
-+                              int where)
-+{
-+      struct plda_pcie_rp *pcie = bus->sysdata;
-+
-+      return pcie->config_base + PCIE_ECAM_OFFSET(bus->number, devfn, where);
-+}
-+EXPORT_SYMBOL_GPL(plda_pcie_map_bus);
-+
- static void plda_handle_msi(struct irq_desc *desc)
- {
-       struct plda_pcie_rp *port = irq_desc_get_handler_data(desc);
-@@ -420,9 +430,7 @@ int plda_init_interrupts(struct platform
-                        const struct plda_event *event)
- {
-       struct device *dev = &pdev->dev;
--      int irq;
--      int intx_irq, msi_irq, event_irq;
--      int ret;
-+      int event_irq, ret;
-       u32 i;
-       if (!port->event_ops)
-@@ -437,8 +445,8 @@ int plda_init_interrupts(struct platform
-               return ret;
-       }
--      irq = platform_get_irq(pdev, 0);
--      if (irq < 0)
-+      port->irq = platform_get_irq(pdev, 0);
-+      if (port->irq < 0)
-               return -ENODEV;
-       for_each_set_bit(i, &port->events_bitmap, port->num_events) {
-@@ -461,26 +469,26 @@ int plda_init_interrupts(struct platform
-               }
-       }
--      intx_irq = irq_create_mapping(port->event_domain,
--                                    event->intx_event);
--      if (!intx_irq) {
-+      port->intx_irq = irq_create_mapping(port->event_domain,
-+                                          event->intx_event);
-+      if (!port->intx_irq) {
-               dev_err(dev, "failed to map INTx interrupt\n");
-               return -ENXIO;
-       }
-       /* Plug the INTx chained handler */
--      irq_set_chained_handler_and_data(intx_irq, plda_handle_intx, port);
-+      irq_set_chained_handler_and_data(port->intx_irq, plda_handle_intx, port);
--      msi_irq = irq_create_mapping(port->event_domain,
--                                   event->msi_event);
--      if (!msi_irq)
-+      port->msi_irq = irq_create_mapping(port->event_domain,
-+                                         event->msi_event);
-+      if (!port->msi_irq)
-               return -ENXIO;
-       /* Plug the MSI chained handler */
--      irq_set_chained_handler_and_data(msi_irq, plda_handle_msi, port);
-+      irq_set_chained_handler_and_data(port->msi_irq, plda_handle_msi, port);
-       /* Plug the main event chained handler */
--      irq_set_chained_handler_and_data(irq, plda_handle_event, port);
-+      irq_set_chained_handler_and_data(port->irq, plda_handle_event, port);
-       return 0;
- }
-@@ -546,3 +554,98 @@ int plda_pcie_setup_iomems(struct pci_ho
-       return 0;
- }
- EXPORT_SYMBOL_GPL(plda_pcie_setup_iomems);
-+
-+static void plda_pcie_irq_domain_deinit(struct plda_pcie_rp *pcie)
-+{
-+      irq_set_chained_handler_and_data(pcie->irq, NULL, NULL);
-+      irq_set_chained_handler_and_data(pcie->msi_irq, NULL, NULL);
-+      irq_set_chained_handler_and_data(pcie->intx_irq, NULL, NULL);
-+
-+      irq_domain_remove(pcie->msi.msi_domain);
-+      irq_domain_remove(pcie->msi.dev_domain);
-+
-+      irq_domain_remove(pcie->intx_domain);
-+      irq_domain_remove(pcie->event_domain);
-+}
-+
-+int plda_pcie_host_init(struct plda_pcie_rp *port, struct pci_ops *ops,
-+                      const struct plda_event *plda_event)
-+{
-+      struct device *dev = port->dev;
-+      struct pci_host_bridge *bridge;
-+      struct platform_device *pdev = to_platform_device(dev);
-+      struct resource *cfg_res;
-+      int ret;
-+
-+      pdev = to_platform_device(dev);
-+
-+      port->bridge_addr =
-+              devm_platform_ioremap_resource_byname(pdev, "apb");
-+
-+      if (IS_ERR(port->bridge_addr))
-+              return dev_err_probe(dev, PTR_ERR(port->bridge_addr),
-+                                   "failed to map reg memory\n");
-+
-+      cfg_res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "cfg");
-+      if (!cfg_res)
-+              return dev_err_probe(dev, -ENODEV,
-+                                   "failed to get config memory\n");
-+
-+      port->config_base = devm_ioremap_resource(dev, cfg_res);
-+      if (IS_ERR(port->config_base))
-+              return dev_err_probe(dev, PTR_ERR(port->config_base),
-+                                   "failed to map config memory\n");
-+
-+      bridge = devm_pci_alloc_host_bridge(dev, 0);
-+      if (!bridge)
-+              return dev_err_probe(dev, -ENOMEM,
-+                                   "failed to alloc bridge\n");
-+
-+      if (port->host_ops && port->host_ops->host_init) {
-+              ret = port->host_ops->host_init(port);
-+              if (ret)
-+                      return ret;
-+      }
-+
-+      port->bridge = bridge;
-+      plda_pcie_setup_window(port->bridge_addr, 0, cfg_res->start, 0,
-+                             resource_size(cfg_res));
-+      plda_pcie_setup_iomems(bridge, port);
-+      plda_set_default_msi(&port->msi);
-+      ret = plda_init_interrupts(pdev, port, plda_event);
-+      if (ret)
-+              goto err_host;
-+
-+      /* Set default bus ops */
-+      bridge->ops = ops;
-+      bridge->sysdata = port;
-+
-+      ret = pci_host_probe(bridge);
-+      if (ret < 0) {
-+              dev_err_probe(dev, ret, "failed to probe pci host\n");
-+              goto err_probe;
-+      }
-+
-+      return ret;
-+
-+err_probe:
-+      plda_pcie_irq_domain_deinit(port);
-+err_host:
-+      if (port->host_ops && port->host_ops->host_deinit)
-+              port->host_ops->host_deinit(port);
-+
-+      return ret;
-+}
-+EXPORT_SYMBOL_GPL(plda_pcie_host_init);
-+
-+void plda_pcie_host_deinit(struct plda_pcie_rp *port)
-+{
-+      pci_stop_root_bus(port->bridge->bus);
-+      pci_remove_root_bus(port->bridge->bus);
-+
-+      plda_pcie_irq_domain_deinit(port);
-+
-+      if (port->host_ops && port->host_ops->host_deinit)
-+              port->host_ops->host_deinit(port);
-+}
-+EXPORT_SYMBOL_GPL(plda_pcie_host_deinit);
---- a/drivers/pci/controller/plda/pcie-plda.h
-+++ b/drivers/pci/controller/plda/pcie-plda.h
-@@ -141,6 +141,11 @@ struct plda_event_ops {
-       u32 (*get_events)(struct plda_pcie_rp *pcie);
- };
-+struct plda_pcie_host_ops {
-+      int (*host_init)(struct plda_pcie_rp *pcie);
-+      void (*host_deinit)(struct plda_pcie_rp *pcie);
-+};
-+
- struct plda_msi {
-       struct mutex lock;              /* Protect used bitmap */
-       struct irq_domain *msi_domain;
-@@ -152,14 +157,20 @@ struct plda_msi {
- struct plda_pcie_rp {
-       struct device *dev;
-+      struct pci_host_bridge *bridge;
-       struct irq_domain *intx_domain;
-       struct irq_domain *event_domain;
-       raw_spinlock_t lock;
-       struct plda_msi msi;
-       const struct plda_event_ops *event_ops;
-       const struct irq_chip *event_irq_chip;
-+      const struct plda_pcie_host_ops *host_ops;
-       void __iomem *bridge_addr;
-+      void __iomem *config_base;
-       unsigned long events_bitmap;
-+      int irq;
-+      int msi_irq;
-+      int intx_irq;
-       int num_events;
- };
-@@ -170,6 +181,8 @@ struct plda_event {
-       int msi_event;
- };
-+void __iomem *plda_pcie_map_bus(struct pci_bus *bus, unsigned int devfn,
-+                              int where);
- int plda_init_interrupts(struct platform_device *pdev,
-                        struct plda_pcie_rp *port,
-                        const struct plda_event *event);
-@@ -178,4 +191,13 @@ void plda_pcie_setup_window(void __iomem
-                           size_t size);
- int plda_pcie_setup_iomems(struct pci_host_bridge *bridge,
-                          struct plda_pcie_rp *port);
-+int plda_pcie_host_init(struct plda_pcie_rp *port, struct pci_ops *ops,
-+                      const struct plda_event *plda_event);
-+void plda_pcie_host_deinit(struct plda_pcie_rp *pcie);
-+
-+static inline void plda_set_default_msi(struct plda_msi *msi)
-+{
-+      msi->vector_phy = IMSI_ADDR;
-+      msi->num_vectors = PLDA_MAX_NUM_MSI_IRQS;
-+}
- #endif
diff --git a/target/linux/starfive/patches-6.6/0032-dt-bindings-PCI-Add-StarFive-JH7110-PCIe-controller.patch b/target/linux/starfive/patches-6.6/0032-dt-bindings-PCI-Add-StarFive-JH7110-PCIe-controller.patch
deleted file mode 100644 (file)
index 9e33f7d..0000000
+++ /dev/null
@@ -1,140 +0,0 @@
-From bc3f8207d9f0af3cb96a7eae232074a644a175f6 Mon Sep 17 00:00:00 2001
-From: Minda Chen <minda.chen@starfivetech.com>
-Date: Mon, 8 Jan 2024 19:06:09 +0800
-Subject: [PATCH 032/116] dt-bindings: PCI: Add StarFive JH7110 PCIe controller
-
-Add StarFive JH7110 SoC PCIe controller dt-bindings. JH7110 using PLDA
-XpressRICH PCIe host controller IP.
-
-Signed-off-by: Minda Chen <minda.chen@starfivetech.com>
-Reviewed-by: Hal Feng <hal.feng@starfivetech.com>
-Reviewed-by: Conor Dooley <conor.dooley@microchip.com>
-Reviewed-by: Rob Herring <robh@kernel.org>
----
- .../bindings/pci/starfive,jh7110-pcie.yaml    | 120 ++++++++++++++++++
- 1 file changed, 120 insertions(+)
- create mode 100644 Documentation/devicetree/bindings/pci/starfive,jh7110-pcie.yaml
-
---- /dev/null
-+++ b/Documentation/devicetree/bindings/pci/starfive,jh7110-pcie.yaml
-@@ -0,0 +1,120 @@
-+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
-+%YAML 1.2
-+---
-+$id: http://devicetree.org/schemas/pci/starfive,jh7110-pcie.yaml#
-+$schema: http://devicetree.org/meta-schemas/core.yaml#
-+
-+title: StarFive JH7110 PCIe host controller
-+
-+maintainers:
-+  - Kevin Xie <kevin.xie@starfivetech.com>
-+
-+allOf:
-+  - $ref: plda,xpressrich3-axi-common.yaml#
-+
-+properties:
-+  compatible:
-+    const: starfive,jh7110-pcie
-+
-+  clocks:
-+    items:
-+      - description: NOC bus clock
-+      - description: Transport layer clock
-+      - description: AXI MST0 clock
-+      - description: APB clock
-+
-+  clock-names:
-+    items:
-+      - const: noc
-+      - const: tl
-+      - const: axi_mst0
-+      - const: apb
-+
-+  resets:
-+    items:
-+      - description: AXI MST0 reset
-+      - description: AXI SLAVE0 reset
-+      - description: AXI SLAVE reset
-+      - description: PCIE BRIDGE reset
-+      - description: PCIE CORE reset
-+      - description: PCIE APB reset
-+
-+  reset-names:
-+    items:
-+      - const: mst0
-+      - const: slv0
-+      - const: slv
-+      - const: brg
-+      - const: core
-+      - const: apb
-+
-+  starfive,stg-syscon:
-+    $ref: /schemas/types.yaml#/definitions/phandle-array
-+    description:
-+      The phandle to System Register Controller syscon node.
-+
-+  perst-gpios:
-+    description: GPIO controlled connection to PERST# signal
-+    maxItems: 1
-+
-+  phys:
-+    description:
-+      Specified PHY is attached to PCIe controller.
-+    maxItems: 1
-+
-+required:
-+  - clocks
-+  - resets
-+  - starfive,stg-syscon
-+
-+unevaluatedProperties: false
-+
-+examples:
-+  - |
-+    #include <dt-bindings/gpio/gpio.h>
-+    soc {
-+        #address-cells = <2>;
-+        #size-cells = <2>;
-+
-+        pcie@940000000 {
-+            compatible = "starfive,jh7110-pcie";
-+            reg = <0x9 0x40000000 0x0 0x10000000>,
-+                  <0x0 0x2b000000 0x0 0x1000000>;
-+            reg-names = "cfg", "apb";
-+            #address-cells = <3>;
-+            #size-cells = <2>;
-+            #interrupt-cells = <1>;
-+            device_type = "pci";
-+            ranges = <0x82000000  0x0 0x30000000  0x0 0x30000000 0x0 0x08000000>,
-+                     <0xc3000000  0x9 0x00000000  0x9 0x00000000 0x0 0x40000000>;
-+            starfive,stg-syscon = <&stg_syscon>;
-+            bus-range = <0x0 0xff>;
-+            interrupt-parent = <&plic>;
-+            interrupts = <56>;
-+            interrupt-map-mask = <0x0 0x0 0x0 0x7>;
-+            interrupt-map = <0x0 0x0 0x0 0x1 &pcie_intc0 0x1>,
-+                            <0x0 0x0 0x0 0x2 &pcie_intc0 0x2>,
-+                            <0x0 0x0 0x0 0x3 &pcie_intc0 0x3>,
-+                            <0x0 0x0 0x0 0x4 &pcie_intc0 0x4>;
-+            msi-controller;
-+            clocks = <&syscrg 86>,
-+                     <&stgcrg 10>,
-+                     <&stgcrg 8>,
-+                     <&stgcrg 9>;
-+            clock-names = "noc", "tl", "axi_mst0", "apb";
-+            resets = <&stgcrg 11>,
-+                     <&stgcrg 12>,
-+                     <&stgcrg 13>,
-+                     <&stgcrg 14>,
-+                     <&stgcrg 15>,
-+                     <&stgcrg 16>;
-+            perst-gpios = <&gpios 26 GPIO_ACTIVE_LOW>;
-+            phys = <&pciephy0>;
-+
-+            pcie_intc0: interrupt-controller {
-+                #address-cells = <0>;
-+                #interrupt-cells = <1>;
-+                interrupt-controller;
-+            };
-+        };
-+    };
diff --git a/target/linux/starfive/patches-6.6/0033-PCI-Add-PCIE_RESET_CONFIG_DEVICE_WAIT_MS-waiting-tim.patch b/target/linux/starfive/patches-6.6/0033-PCI-Add-PCIE_RESET_CONFIG_DEVICE_WAIT_MS-waiting-tim.patch
deleted file mode 100644 (file)
index ff08960..0000000
+++ /dev/null
@@ -1,55 +0,0 @@
-From abb20b7b8f5e3a7f36dbd6264e6d346275434154 Mon Sep 17 00:00:00 2001
-From: Kevin Xie <kevin.xie@starfivetech.com>
-Date: Mon, 8 Jan 2024 19:06:10 +0800
-Subject: [PATCH 033/116] PCI: Add PCIE_RESET_CONFIG_DEVICE_WAIT_MS waiting
- time value
-
-Add the PCIE_RESET_CONFIG_DEVICE_WAIT_MS macro to define the minimum
-waiting time between exit from a conventional reset and sending the
-first configuration request to the device.
-
-As described in PCI base specification r6.0, section 6.6.1 <Conventional
-Reset>, there are two different use cases of the value:
-
-   - "With a Downstream Port that does not support Link speeds greater
-     than 5.0 GT/s, software must wait a minimum of 100 ms following exit
-     from a Conventional Reset before sending a Configuration Request to
-     the device immediately below that Port."
-
-   - "With a Downstream Port that supports Link speeds greater than
-     5.0 GT/s, software must wait a minimum of 100 ms after Link training
-     completes before sending a Configuration Request to the device
-     immediately below that Port."
-
-Signed-off-by: Kevin Xie <kevin.xie@starfivetech.com>
-Reviewed-by: Mason Huo <mason.huo@starfivetech.com>
-Acked-by: Bjorn Helgaas <bhelgaas@google.com>
----
- drivers/pci/pci.h | 16 ++++++++++++++++
- 1 file changed, 16 insertions(+)
-
---- a/drivers/pci/pci.h
-+++ b/drivers/pci/pci.h
-@@ -22,6 +22,22 @@
-  */
- #define PCIE_PME_TO_L2_TIMEOUT_US     10000
-+/*
-+ * As described in PCI base specification r6.0, section 6.6.1 <Conventional
-+ * Reset>, there are two different use cases of the value:
-+ *
-+ * - "With a Downstream Port that does not support Link speeds greater
-+ *    than 5.0 GT/s, software must wait a minimum of 100 ms following exit
-+ *    from a Conventional Reset before sending a Configuration Request to
-+ *    the device immediately below that Port."
-+ *
-+ * - "With a Downstream Port that supports Link speeds greater than
-+ *    5.0 GT/s, software must wait a minimum of 100 ms after Link training
-+ *    completes before sending a Configuration Request to the device
-+ *    immediately below that Port."
-+ */
-+#define PCIE_RESET_CONFIG_DEVICE_WAIT_MS      100
-+
- extern const unsigned char pcie_link_speed[];
- extern bool pci_early_dump;
diff --git a/target/linux/starfive/patches-6.6/0034-PCI-starfive-Add-JH7110-PCIe-controller.patch b/target/linux/starfive/patches-6.6/0034-PCI-starfive-Add-JH7110-PCIe-controller.patch
deleted file mode 100644 (file)
index 45a549f..0000000
+++ /dev/null
@@ -1,623 +0,0 @@
-From 323aedef34315b758dc30ba23e2cabca259bb4b2 Mon Sep 17 00:00:00 2001
-From: Minda Chen <minda.chen@starfivetech.com>
-Date: Mon, 8 Jan 2024 19:06:11 +0800
-Subject: [PATCH 034/116] PCI: starfive: Add JH7110 PCIe controller
-
-Add StarFive JH7110 SoC PCIe controller platform driver codes, JH7110
-with PLDA host PCIe core.
-
-Signed-off-by: Minda Chen <minda.chen@starfivetech.com>
-Co-developed-by: Kevin Xie <kevin.xie@starfivetech.com>
-Reviewed-by: Mason Huo <mason.huo@starfivetech.com>
----
- drivers/pci/controller/plda/Kconfig         |  12 +
- drivers/pci/controller/plda/Makefile        |   1 +
- drivers/pci/controller/plda/pcie-plda.h     |  71 ++-
- drivers/pci/controller/plda/pcie-starfive.c | 473 ++++++++++++++++++++
- 4 files changed, 556 insertions(+), 1 deletion(-)
- create mode 100644 drivers/pci/controller/plda/pcie-starfive.c
-
---- a/drivers/pci/controller/plda/Kconfig
-+++ b/drivers/pci/controller/plda/Kconfig
-@@ -15,4 +15,16 @@ config PCIE_MICROCHIP_HOST
-         Say Y here if you want kernel to support the Microchip AXI PCIe
-         Host Bridge driver.
-+config PCIE_STARFIVE_HOST
-+      tristate "StarFive PCIe host controller"
-+      depends on PCI_MSI && OF
-+      depends on ARCH_STARFIVE || COMPILE_TEST
-+      select PCIE_PLDA_HOST
-+      help
-+        Say Y here if you want to support the StarFive PCIe controller in
-+        host mode. StarFive PCIe controller uses PLDA PCIe core.
-+
-+        If you choose to build this driver as module it will be dynamically
-+        linked and module will be called pcie-starfive.ko.
-+
- endmenu
---- a/drivers/pci/controller/plda/Makefile
-+++ b/drivers/pci/controller/plda/Makefile
-@@ -1,3 +1,4 @@
- # SPDX-License-Identifier: GPL-2.0
- obj-$(CONFIG_PCIE_PLDA_HOST) += pcie-plda-host.o
- obj-$(CONFIG_PCIE_MICROCHIP_HOST) += pcie-microchip-host.o
-+obj-$(CONFIG_PCIE_STARFIVE_HOST) += pcie-starfive.o
---- a/drivers/pci/controller/plda/pcie-plda.h
-+++ b/drivers/pci/controller/plda/pcie-plda.h
-@@ -10,10 +10,20 @@
- #define PLDA_MAX_NUM_MSI_IRQS                 32
- /* PCIe Bridge Phy Regs */
-+#define GEN_SETTINGS                          0x80
-+#define  RP_ENABLE                            1
-+#define PCIE_PCI_IDS_DW1                      0x9c
-+#define  IDS_CLASS_CODE_SHIFT                 16
-+#define  REVISION_ID_MASK                     GENMASK(7, 0)
-+#define  CLASS_CODE_ID_MASK                   GENMASK(31, 8)
- #define PCIE_PCI_IRQ_DW0                      0xa8
- #define  MSIX_CAP_MASK                                BIT(31)
- #define  NUM_MSI_MSGS_MASK                    GENMASK(6, 4)
- #define  NUM_MSI_MSGS_SHIFT                   4
-+#define PCI_MISC                              0xb4
-+#define  PHY_FUNCTION_DIS                     BIT(15)
-+#define PCIE_WINROM                           0xfc
-+#define  PREF_MEM_WIN_64_SUPPORT              BIT(3)
- #define IMASK_LOCAL                           0x180
- #define  DMA_END_ENGINE_0_MASK                        0x00000000u
-@@ -65,6 +75,8 @@
- #define ISTATUS_HOST                          0x18c
- #define IMSI_ADDR                             0x190
- #define ISTATUS_MSI                           0x194
-+#define PMSG_SUPPORT_RX                               0x3f0
-+#define  PMSG_LTR_SUPPORT                     BIT(2)
- /* PCIe Master table init defines */
- #define ATR0_PCIE_WIN0_SRCADDR_PARAM          0x600u
-@@ -86,6 +98,8 @@
- #define  PCIE_TX_RX_INTERFACE                 0x00000000u
- #define  PCIE_CONFIG_INTERFACE                        0x00000001u
-+#define CONFIG_SPACE_ADDR_OFFSET              0x1000u
-+
- #define ATR_ENTRY_SIZE                                32
- enum plda_int_event {
-@@ -200,4 +214,59 @@ static inline void plda_set_default_msi(
-       msi->vector_phy = IMSI_ADDR;
-       msi->num_vectors = PLDA_MAX_NUM_MSI_IRQS;
- }
--#endif
-+
-+static inline void plda_pcie_enable_root_port(struct plda_pcie_rp *plda)
-+{
-+      u32 value;
-+
-+      value = readl_relaxed(plda->bridge_addr + GEN_SETTINGS);
-+      value |= RP_ENABLE;
-+      writel_relaxed(value, plda->bridge_addr + GEN_SETTINGS);
-+}
-+
-+static inline void plda_pcie_set_standard_class(struct plda_pcie_rp *plda)
-+{
-+      u32 value;
-+
-+      /* set class code and reserve revision id */
-+      value = readl_relaxed(plda->bridge_addr + PCIE_PCI_IDS_DW1);
-+      value &= REVISION_ID_MASK;
-+      value |= (PCI_CLASS_BRIDGE_PCI << IDS_CLASS_CODE_SHIFT);
-+      writel_relaxed(value, plda->bridge_addr + PCIE_PCI_IDS_DW1);
-+}
-+
-+static inline void plda_pcie_set_pref_win_64bit(struct plda_pcie_rp *plda)
-+{
-+      u32 value;
-+
-+      value = readl_relaxed(plda->bridge_addr + PCIE_WINROM);
-+      value |= PREF_MEM_WIN_64_SUPPORT;
-+      writel_relaxed(value, plda->bridge_addr + PCIE_WINROM);
-+}
-+
-+static inline void plda_pcie_disable_ltr(struct plda_pcie_rp *plda)
-+{
-+      u32 value;
-+
-+      value = readl_relaxed(plda->bridge_addr + PMSG_SUPPORT_RX);
-+      value &= ~PMSG_LTR_SUPPORT;
-+      writel_relaxed(value, plda->bridge_addr + PMSG_SUPPORT_RX);
-+}
-+
-+static inline void plda_pcie_disable_func(struct plda_pcie_rp *plda)
-+{
-+      u32 value;
-+
-+      value = readl_relaxed(plda->bridge_addr + PCI_MISC);
-+      value |= PHY_FUNCTION_DIS;
-+      writel_relaxed(value, plda->bridge_addr + PCI_MISC);
-+}
-+
-+static inline void plda_pcie_write_rc_bar(struct plda_pcie_rp *plda, u64 val)
-+{
-+      void __iomem *addr = plda->bridge_addr + CONFIG_SPACE_ADDR_OFFSET;
-+
-+      writel_relaxed(lower_32_bits(val), addr + PCI_BASE_ADDRESS_0);
-+      writel_relaxed(upper_32_bits(val), addr + PCI_BASE_ADDRESS_1);
-+}
-+#endif /* _PCIE_PLDA_H */
---- /dev/null
-+++ b/drivers/pci/controller/plda/pcie-starfive.c
-@@ -0,0 +1,473 @@
-+// SPDX-License-Identifier: GPL-2.0+
-+/*
-+ * PCIe host controller driver for StarFive JH7110 Soc.
-+ *
-+ * Copyright (C) 2023 StarFive Technology Co., Ltd.
-+ */
-+
-+#include <linux/bitfield.h>
-+#include <linux/clk.h>
-+#include <linux/delay.h>
-+#include <linux/gpio/consumer.h>
-+#include <linux/interrupt.h>
-+#include <linux/kernel.h>
-+#include <linux/mfd/syscon.h>
-+#include <linux/module.h>
-+#include <linux/of_address.h>
-+#include <linux/of_irq.h>
-+#include <linux/of_pci.h>
-+#include <linux/pci.h>
-+#include <linux/phy/phy.h>
-+#include <linux/platform_device.h>
-+#include <linux/pm_runtime.h>
-+#include <linux/regmap.h>
-+#include <linux/reset.h>
-+#include "../../pci.h"
-+
-+#include "pcie-plda.h"
-+
-+#define PCIE_FUNC_NUM                 4
-+
-+/* system control */
-+#define STG_SYSCON_PCIE0_BASE                 0x48
-+#define STG_SYSCON_PCIE1_BASE                 0x1f8
-+
-+#define STG_SYSCON_AR_OFFSET                  0x78
-+#define STG_SYSCON_AXI4_SLVL_AR_MASK          GENMASK(22, 8)
-+#define STG_SYSCON_AXI4_SLVL_PHY_AR(x)                FIELD_PREP(GENMASK(20, 17), x)
-+#define STG_SYSCON_AW_OFFSET                  0x7c
-+#define STG_SYSCON_AXI4_SLVL_AW_MASK          GENMASK(14, 0)
-+#define STG_SYSCON_AXI4_SLVL_PHY_AW(x)                FIELD_PREP(GENMASK(12, 9), x)
-+#define STG_SYSCON_CLKREQ                     BIT(22)
-+#define STG_SYSCON_CKREF_SRC_MASK             GENMASK(19, 18)
-+#define STG_SYSCON_RP_NEP_OFFSET              0xe8
-+#define STG_SYSCON_K_RP_NEP                   BIT(8)
-+#define STG_SYSCON_LNKSTA_OFFSET              0x170
-+#define DATA_LINK_ACTIVE                      BIT(5)
-+
-+/* Parameters for the waiting for link up routine */
-+#define LINK_WAIT_MAX_RETRIES 10
-+#define LINK_WAIT_USLEEP_MIN  90000
-+#define LINK_WAIT_USLEEP_MAX  100000
-+
-+struct starfive_jh7110_pcie {
-+      struct plda_pcie_rp plda;
-+      struct reset_control *resets;
-+      struct clk_bulk_data *clks;
-+      struct regmap *reg_syscon;
-+      struct gpio_desc *power_gpio;
-+      struct gpio_desc *reset_gpio;
-+      struct phy *phy;
-+
-+      unsigned int stg_pcie_base;
-+      int num_clks;
-+};
-+
-+/*
-+ * The BAR0/1 of bridge should be hidden during enumeration to
-+ * avoid the sizing and resource allocation by PCIe core.
-+ */
-+static bool starfive_pcie_hide_rc_bar(struct pci_bus *bus, unsigned int devfn,
-+                                    int offset)
-+{
-+      if (pci_is_root_bus(bus) && !devfn &&
-+          (offset == PCI_BASE_ADDRESS_0 || offset == PCI_BASE_ADDRESS_1))
-+              return true;
-+
-+      return false;
-+}
-+
-+static int starfive_pcie_config_write(struct pci_bus *bus, unsigned int devfn,
-+                                    int where, int size, u32 value)
-+{
-+      if (starfive_pcie_hide_rc_bar(bus, devfn, where))
-+              return PCIBIOS_SUCCESSFUL;
-+
-+      return pci_generic_config_write(bus, devfn, where, size, value);
-+}
-+
-+static int starfive_pcie_config_read(struct pci_bus *bus, unsigned int devfn,
-+                                   int where, int size, u32 *value)
-+{
-+      if (starfive_pcie_hide_rc_bar(bus, devfn, where)) {
-+              *value = 0;
-+              return PCIBIOS_SUCCESSFUL;
-+      }
-+
-+      return pci_generic_config_read(bus, devfn, where, size, value);
-+}
-+
-+static int starfive_pcie_parse_dt(struct starfive_jh7110_pcie *pcie,
-+                                struct device *dev)
-+{
-+      int domain_nr;
-+
-+      pcie->num_clks = devm_clk_bulk_get_all(dev, &pcie->clks);
-+      if (pcie->num_clks < 0)
-+              return dev_err_probe(dev, pcie->num_clks,
-+                                   "failed to get pcie clocks\n");
-+
-+      pcie->resets = devm_reset_control_array_get_exclusive(dev);
-+      if (IS_ERR(pcie->resets))
-+              return dev_err_probe(dev, PTR_ERR(pcie->resets),
-+                                   "failed to get pcie resets");
-+
-+      pcie->reg_syscon =
-+              syscon_regmap_lookup_by_phandle(dev->of_node,
-+                                              "starfive,stg-syscon");
-+
-+      if (IS_ERR(pcie->reg_syscon))
-+              return dev_err_probe(dev, PTR_ERR(pcie->reg_syscon),
-+                                   "failed to parse starfive,stg-syscon\n");
-+
-+      pcie->phy = devm_phy_optional_get(dev, NULL);
-+      if (IS_ERR(pcie->phy))
-+              return dev_err_probe(dev, PTR_ERR(pcie->phy),
-+                                   "failed to get pcie phy\n");
-+
-+      domain_nr = of_get_pci_domain_nr(dev->of_node);
-+
-+      if (domain_nr < 0 || domain_nr > 1)
-+              return dev_err_probe(dev, -ENODEV,
-+                                   "failed to get valid pcie domain\n");
-+
-+      if (domain_nr == 0)
-+              pcie->stg_pcie_base = STG_SYSCON_PCIE0_BASE;
-+      else
-+              pcie->stg_pcie_base = STG_SYSCON_PCIE1_BASE;
-+
-+      pcie->reset_gpio = devm_gpiod_get_optional(dev, "perst",
-+                                                 GPIOD_OUT_HIGH);
-+      if (IS_ERR(pcie->reset_gpio))
-+              return dev_err_probe(dev, PTR_ERR(pcie->reset_gpio),
-+                                   "failed to get perst-gpio\n");
-+
-+      pcie->power_gpio = devm_gpiod_get_optional(dev, "enable",
-+                                                 GPIOD_OUT_LOW);
-+      if (IS_ERR(pcie->power_gpio))
-+              return dev_err_probe(dev, PTR_ERR(pcie->power_gpio),
-+                                   "failed to get power-gpio\n");
-+
-+      return 0;
-+}
-+
-+static struct pci_ops starfive_pcie_ops = {
-+      .map_bus        = plda_pcie_map_bus,
-+      .read           = starfive_pcie_config_read,
-+      .write          = starfive_pcie_config_write,
-+};
-+
-+static int starfive_pcie_clk_rst_init(struct starfive_jh7110_pcie *pcie)
-+{
-+      struct device *dev = pcie->plda.dev;
-+      int ret;
-+
-+      ret = clk_bulk_prepare_enable(pcie->num_clks, pcie->clks);
-+      if (ret)
-+              return dev_err_probe(dev, ret, "failed to enable clocks\n");
-+
-+      ret = reset_control_deassert(pcie->resets);
-+      if (ret) {
-+              clk_bulk_disable_unprepare(pcie->num_clks, pcie->clks);
-+              dev_err_probe(dev, ret, "failed to deassert resets\n");
-+      }
-+
-+      return ret;
-+}
-+
-+static void starfive_pcie_clk_rst_deinit(struct starfive_jh7110_pcie *pcie)
-+{
-+      reset_control_assert(pcie->resets);
-+      clk_bulk_disable_unprepare(pcie->num_clks, pcie->clks);
-+}
-+
-+static bool starfive_pcie_link_up(struct plda_pcie_rp *plda)
-+{
-+      struct starfive_jh7110_pcie *pcie =
-+              container_of(plda, struct starfive_jh7110_pcie, plda);
-+      int ret;
-+      u32 stg_reg_val;
-+
-+      ret = regmap_read(pcie->reg_syscon,
-+                        pcie->stg_pcie_base + STG_SYSCON_LNKSTA_OFFSET,
-+                        &stg_reg_val);
-+      if (ret) {
-+              dev_err(pcie->plda.dev, "failed to read link status\n");
-+              return false;
-+      }
-+
-+      return !!(stg_reg_val & DATA_LINK_ACTIVE);
-+}
-+
-+static int starfive_pcie_host_wait_for_link(struct starfive_jh7110_pcie *pcie)
-+{
-+      int retries;
-+
-+      /* Check if the link is up or not */
-+      for (retries = 0; retries < LINK_WAIT_MAX_RETRIES; retries++) {
-+              if (starfive_pcie_link_up(&pcie->plda)) {
-+                      dev_info(pcie->plda.dev, "port link up\n");
-+                      return 0;
-+              }
-+              usleep_range(LINK_WAIT_USLEEP_MIN, LINK_WAIT_USLEEP_MAX);
-+      }
-+
-+      return -ETIMEDOUT;
-+}
-+
-+static int starfive_pcie_enable_phy(struct device *dev,
-+                                  struct starfive_jh7110_pcie *pcie)
-+{
-+      int ret;
-+
-+      if (!pcie->phy)
-+              return 0;
-+
-+      ret = phy_init(pcie->phy);
-+      if (ret)
-+              return dev_err_probe(dev, ret,
-+                                   "failed to initialize pcie phy\n");
-+
-+      ret = phy_set_mode(pcie->phy, PHY_MODE_PCIE);
-+      if (ret) {
-+              dev_err_probe(dev, ret, "failed to set pcie mode\n");
-+              goto err_phy_on;
-+      }
-+
-+      ret = phy_power_on(pcie->phy);
-+      if (ret) {
-+              dev_err_probe(dev, ret, "failed to power on pcie phy\n");
-+              goto err_phy_on;
-+      }
-+
-+      return 0;
-+
-+err_phy_on:
-+      phy_exit(pcie->phy);
-+      return ret;
-+}
-+
-+static void starfive_pcie_disable_phy(struct starfive_jh7110_pcie *pcie)
-+{
-+      phy_power_off(pcie->phy);
-+      phy_exit(pcie->phy);
-+}
-+
-+static void starfive_pcie_host_deinit(struct plda_pcie_rp *plda)
-+{
-+      struct starfive_jh7110_pcie *pcie =
-+              container_of(plda, struct starfive_jh7110_pcie, plda);
-+
-+      starfive_pcie_clk_rst_deinit(pcie);
-+      if (pcie->power_gpio)
-+              gpiod_set_value_cansleep(pcie->power_gpio, 0);
-+      starfive_pcie_disable_phy(pcie);
-+}
-+
-+static int starfive_pcie_host_init(struct plda_pcie_rp *plda)
-+{
-+      struct starfive_jh7110_pcie *pcie =
-+              container_of(plda, struct starfive_jh7110_pcie, plda);
-+      struct device *dev = plda->dev;
-+      int ret;
-+      int i;
-+
-+      ret = starfive_pcie_enable_phy(dev, pcie);
-+      if (ret)
-+              return ret;
-+
-+      regmap_update_bits(pcie->reg_syscon,
-+                         pcie->stg_pcie_base + STG_SYSCON_RP_NEP_OFFSET,
-+                         STG_SYSCON_K_RP_NEP, STG_SYSCON_K_RP_NEP);
-+
-+      regmap_update_bits(pcie->reg_syscon,
-+                         pcie->stg_pcie_base + STG_SYSCON_AW_OFFSET,
-+                         STG_SYSCON_CKREF_SRC_MASK,
-+                         FIELD_PREP(STG_SYSCON_CKREF_SRC_MASK, 2));
-+
-+      regmap_update_bits(pcie->reg_syscon,
-+                         pcie->stg_pcie_base + STG_SYSCON_AW_OFFSET,
-+                         STG_SYSCON_CLKREQ, STG_SYSCON_CLKREQ);
-+
-+      ret = starfive_pcie_clk_rst_init(pcie);
-+      if (ret)
-+              return ret;
-+
-+      if (pcie->power_gpio)
-+              gpiod_set_value_cansleep(pcie->power_gpio, 1);
-+
-+      if (pcie->reset_gpio)
-+              gpiod_set_value_cansleep(pcie->reset_gpio, 1);
-+
-+      /* Disable physical functions except #0 */
-+      for (i = 1; i < PCIE_FUNC_NUM; i++) {
-+              regmap_update_bits(pcie->reg_syscon,
-+                                 pcie->stg_pcie_base + STG_SYSCON_AR_OFFSET,
-+                                 STG_SYSCON_AXI4_SLVL_AR_MASK,
-+                                 STG_SYSCON_AXI4_SLVL_PHY_AR(i));
-+
-+              regmap_update_bits(pcie->reg_syscon,
-+                                 pcie->stg_pcie_base + STG_SYSCON_AW_OFFSET,
-+                                 STG_SYSCON_AXI4_SLVL_AW_MASK,
-+                                 STG_SYSCON_AXI4_SLVL_PHY_AW(i));
-+
-+              plda_pcie_disable_func(plda);
-+      }
-+
-+      regmap_update_bits(pcie->reg_syscon,
-+                         pcie->stg_pcie_base + STG_SYSCON_AR_OFFSET,
-+                         STG_SYSCON_AXI4_SLVL_AR_MASK, 0);
-+      regmap_update_bits(pcie->reg_syscon,
-+                         pcie->stg_pcie_base + STG_SYSCON_AW_OFFSET,
-+                         STG_SYSCON_AXI4_SLVL_AW_MASK, 0);
-+
-+      plda_pcie_enable_root_port(plda);
-+      plda_pcie_write_rc_bar(plda, 0);
-+
-+      /* PCIe PCI Standard Configuration Identification Settings. */
-+      plda_pcie_set_standard_class(plda);
-+
-+      /*
-+       * The LTR message forwarding of PCIe Message Reception was set by core
-+       * as default, but the forward id & addr are also need to be reset.
-+       * If we do not disable LTR message forwarding here, or set a legal
-+       * forwarding address, the kernel will get stuck after the driver probe.
-+       * To workaround, disable the LTR message forwarding support on
-+       * PCIe Message Reception.
-+       */
-+      plda_pcie_disable_ltr(plda);
-+
-+      /* Prefetchable memory window 64-bit addressing support */
-+      plda_pcie_set_pref_win_64bit(plda);
-+
-+      /*
-+       * Ensure that PERST has been asserted for at least 100 ms,
-+       * the sleep value is T_PVPERL from PCIe CEM spec r2.0 (Table 2-4)
-+       */
-+      msleep(100);
-+      if (pcie->reset_gpio)
-+              gpiod_set_value_cansleep(pcie->reset_gpio, 0);
-+
-+      /*
-+       * With a Downstream Port (<=5GT/s), software must wait a minimum
-+       * of 100ms following exit from a conventional reset before
-+       * sending a configuration request to the device.
-+       */
-+      msleep(PCIE_RESET_CONFIG_DEVICE_WAIT_MS);
-+
-+      if (starfive_pcie_host_wait_for_link(pcie))
-+              dev_info(dev, "port link down\n");
-+
-+      return 0;
-+}
-+
-+static const struct plda_pcie_host_ops sf_host_ops = {
-+      .host_init = starfive_pcie_host_init,
-+      .host_deinit = starfive_pcie_host_deinit,
-+};
-+
-+static const struct plda_event stf_pcie_event = {
-+      .intx_event = EVENT_PM_MSI_INT_INTX,
-+      .msi_event  = EVENT_PM_MSI_INT_MSI
-+};
-+
-+static int starfive_pcie_probe(struct platform_device *pdev)
-+{
-+      struct starfive_jh7110_pcie *pcie;
-+      struct device *dev = &pdev->dev;
-+      struct plda_pcie_rp *plda;
-+      int ret;
-+
-+      pcie = devm_kzalloc(dev, sizeof(*pcie), GFP_KERNEL);
-+      if (!pcie)
-+              return -ENOMEM;
-+
-+      plda = &pcie->plda;
-+      plda->dev = dev;
-+
-+      ret = starfive_pcie_parse_dt(pcie, dev);
-+      if (ret)
-+              return ret;
-+
-+      plda->host_ops = &sf_host_ops;
-+      plda->num_events = PLDA_MAX_EVENT_NUM;
-+      /* mask doorbell event */
-+      plda->events_bitmap = GENMASK(PLDA_INT_EVENT_NUM - 1, 0)
-+                           & ~BIT(PLDA_AXI_DOORBELL)
-+                           & ~BIT(PLDA_PCIE_DOORBELL);
-+      plda->events_bitmap <<= PLDA_NUM_DMA_EVENTS;
-+      ret = plda_pcie_host_init(&pcie->plda, &starfive_pcie_ops,
-+                                &stf_pcie_event);
-+      if (ret)
-+              return ret;
-+
-+      pm_runtime_enable(&pdev->dev);
-+      pm_runtime_get_sync(&pdev->dev);
-+      platform_set_drvdata(pdev, pcie);
-+
-+      return 0;
-+}
-+
-+static void starfive_pcie_remove(struct platform_device *pdev)
-+{
-+      struct starfive_jh7110_pcie *pcie = platform_get_drvdata(pdev);
-+
-+      pm_runtime_put(&pdev->dev);
-+      pm_runtime_disable(&pdev->dev);
-+      plda_pcie_host_deinit(&pcie->plda);
-+      platform_set_drvdata(pdev, NULL);
-+}
-+
-+static int starfive_pcie_suspend_noirq(struct device *dev)
-+{
-+      struct starfive_jh7110_pcie *pcie = dev_get_drvdata(dev);
-+
-+      clk_bulk_disable_unprepare(pcie->num_clks, pcie->clks);
-+      starfive_pcie_disable_phy(pcie);
-+
-+      return 0;
-+}
-+
-+static int starfive_pcie_resume_noirq(struct device *dev)
-+{
-+      struct starfive_jh7110_pcie *pcie = dev_get_drvdata(dev);
-+      int ret;
-+
-+      ret = starfive_pcie_enable_phy(dev, pcie);
-+      if (ret)
-+              return ret;
-+
-+      ret = clk_bulk_prepare_enable(pcie->num_clks, pcie->clks);
-+      if (ret) {
-+              dev_err(dev, "failed to enable clocks\n");
-+              starfive_pcie_disable_phy(pcie);
-+              return ret;
-+      }
-+
-+      return 0;
-+}
-+
-+static const struct dev_pm_ops starfive_pcie_pm_ops = {
-+      NOIRQ_SYSTEM_SLEEP_PM_OPS(starfive_pcie_suspend_noirq,
-+                                starfive_pcie_resume_noirq)
-+};
-+
-+static const struct of_device_id starfive_pcie_of_match[] = {
-+      { .compatible = "starfive,jh7110-pcie", },
-+      { /* sentinel */ }
-+};
-+MODULE_DEVICE_TABLE(of, starfive_pcie_of_match);
-+
-+static struct platform_driver starfive_pcie_driver = {
-+      .driver = {
-+              .name = "pcie-starfive",
-+              .of_match_table = of_match_ptr(starfive_pcie_of_match),
-+              .pm = pm_sleep_ptr(&starfive_pcie_pm_ops),
-+      },
-+      .probe = starfive_pcie_probe,
-+      .remove_new = starfive_pcie_remove,
-+};
-+module_platform_driver(starfive_pcie_driver);
-+
-+MODULE_DESCRIPTION("StarFive JH7110 PCIe host driver");
-+MODULE_LICENSE("GPL v2");
diff --git a/target/linux/starfive/patches-6.6/0035-ASoC-dt-bindings-Add-StarFive-JH7110-PWM-DAC-control.patch b/target/linux/starfive/patches-6.6/0035-ASoC-dt-bindings-Add-StarFive-JH7110-PWM-DAC-control.patch
deleted file mode 100644 (file)
index cf14242..0000000
+++ /dev/null
@@ -1,97 +0,0 @@
-From a306724fd4f32808d1e27efbd87019d56f60db20 Mon Sep 17 00:00:00 2001
-From: Hal Feng <hal.feng@starfivetech.com>
-Date: Mon, 14 Aug 2023 16:06:16 +0800
-Subject: [PATCH 035/116] ASoC: dt-bindings: Add StarFive JH7110 PWM-DAC
- controller
-
-Add bindings for the PWM-DAC controller on the JH7110
-RISC-V SoC by StarFive Ltd.
-
-Reviewed-by: Krzysztof Kozlowski <krzysztof.kozlowski@linaro.org>
-Signed-off-by: Hal Feng <hal.feng@starfivetech.com>
-Link: https://lore.kernel.org/r/20230814080618.10036-2-hal.feng@starfivetech.com
-Signed-off-by: Mark Brown <broonie@kernel.org>
----
- .../sound/starfive,jh7110-pwmdac.yaml         | 76 +++++++++++++++++++
- 1 file changed, 76 insertions(+)
- create mode 100644 Documentation/devicetree/bindings/sound/starfive,jh7110-pwmdac.yaml
-
---- /dev/null
-+++ b/Documentation/devicetree/bindings/sound/starfive,jh7110-pwmdac.yaml
-@@ -0,0 +1,76 @@
-+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
-+%YAML 1.2
-+---
-+$id: http://devicetree.org/schemas/sound/starfive,jh7110-pwmdac.yaml#
-+$schema: http://devicetree.org/meta-schemas/core.yaml#
-+
-+title: StarFive JH7110 PWM-DAC Controller
-+
-+description:
-+  The PWM-DAC Controller uses PWM square wave generators plus RC filters to
-+  form a DAC for audio play in StarFive JH7110 SoC. This audio play controller
-+  supports 16 bit audio format, up to 48K sampling frequency, up to left and
-+  right dual channels.
-+
-+maintainers:
-+  - Hal Feng <hal.feng@starfivetech.com>
-+
-+allOf:
-+  - $ref: dai-common.yaml#
-+
-+properties:
-+  compatible:
-+    const: starfive,jh7110-pwmdac
-+
-+  reg:
-+    maxItems: 1
-+
-+  clocks:
-+    items:
-+      - description: PWMDAC APB
-+      - description: PWMDAC CORE
-+
-+  clock-names:
-+    items:
-+      - const: apb
-+      - const: core
-+
-+  resets:
-+    maxItems: 1
-+    description: PWMDAC APB
-+
-+  dmas:
-+    maxItems: 1
-+    description: TX DMA Channel
-+
-+  dma-names:
-+    const: tx
-+
-+  "#sound-dai-cells":
-+    const: 0
-+
-+required:
-+  - compatible
-+  - reg
-+  - clocks
-+  - clock-names
-+  - resets
-+  - dmas
-+  - dma-names
-+  - "#sound-dai-cells"
-+
-+additionalProperties: false
-+
-+examples:
-+  - |
-+    pwmdac@100b0000 {
-+        compatible = "starfive,jh7110-pwmdac";
-+        reg = <0x100b0000 0x1000>;
-+        clocks = <&syscrg 157>,
-+                 <&syscrg 158>;
-+        clock-names = "apb", "core";
-+        resets = <&syscrg 96>;
-+        dmas = <&dma 22>;
-+        dma-names = "tx";
-+        #sound-dai-cells = <0>;
-+    };
diff --git a/target/linux/starfive/patches-6.6/0036-ASoC-starfive-Add-JH7110-PWM-DAC-driver.patch b/target/linux/starfive/patches-6.6/0036-ASoC-starfive-Add-JH7110-PWM-DAC-driver.patch
deleted file mode 100644 (file)
index acc8593..0000000
+++ /dev/null
@@ -1,574 +0,0 @@
-From a79d2ec524012e35e32a2c4ae2401d0aa763697d Mon Sep 17 00:00:00 2001
-From: Hal Feng <hal.feng@starfivetech.com>
-Date: Mon, 14 Aug 2023 16:06:17 +0800
-Subject: [PATCH 036/116] ASoC: starfive: Add JH7110 PWM-DAC driver
-
-Add PWM-DAC driver support for the StarFive JH7110 SoC.
-
-Reviewed-by: Walker Chen <walker.chen@starfivetech.com>
-Signed-off-by: Hal Feng <hal.feng@starfivetech.com>
-Link: https://lore.kernel.org/r/20230814080618.10036-3-hal.feng@starfivetech.com
-Signed-off-by: Mark Brown <broonie@kernel.org>
----
- sound/soc/starfive/Kconfig         |   9 +
- sound/soc/starfive/Makefile        |   1 +
- sound/soc/starfive/jh7110_pwmdac.c | 529 +++++++++++++++++++++++++++++
- 3 files changed, 539 insertions(+)
- create mode 100644 sound/soc/starfive/jh7110_pwmdac.c
-
---- a/sound/soc/starfive/Kconfig
-+++ b/sound/soc/starfive/Kconfig
-@@ -7,6 +7,15 @@ config SND_SOC_STARFIVE
-         the Starfive SoCs' Audio interfaces. You will also need to
-         select the audio interfaces to support below.
-+config SND_SOC_JH7110_PWMDAC
-+      tristate "JH7110 PWM-DAC device driver"
-+      depends on HAVE_CLK && SND_SOC_STARFIVE
-+      select SND_SOC_GENERIC_DMAENGINE_PCM
-+      select SND_SOC_SPDIF
-+      help
-+       Say Y or M if you want to add support for StarFive JH7110
-+       PWM-DAC driver.
-+
- config SND_SOC_JH7110_TDM
-       tristate "JH7110 TDM device driver"
-       depends on HAVE_CLK && SND_SOC_STARFIVE
---- a/sound/soc/starfive/Makefile
-+++ b/sound/soc/starfive/Makefile
-@@ -1,2 +1,3 @@
- # StarFive Platform Support
-+obj-$(CONFIG_SND_SOC_JH7110_PWMDAC) += jh7110_pwmdac.o
- obj-$(CONFIG_SND_SOC_JH7110_TDM) += jh7110_tdm.o
---- /dev/null
-+++ b/sound/soc/starfive/jh7110_pwmdac.c
-@@ -0,0 +1,529 @@
-+// SPDX-License-Identifier: GPL-2.0
-+/*
-+ * jh7110_pwmdac.c -- StarFive JH7110 PWM-DAC driver
-+ *
-+ * Copyright (C) 2021-2023 StarFive Technology Co., Ltd.
-+ *
-+ * Authors: Jenny Zhang
-+ *        Curry Zhang
-+ *        Xingyu Wu <xingyu.wu@starfivetech.com>
-+ *        Hal Feng <hal.feng@starfivetech.com>
-+ */
-+
-+#include <linux/clk.h>
-+#include <linux/device.h>
-+#include <linux/init.h>
-+#include <linux/interrupt.h>
-+#include <linux/io.h>
-+#include <linux/module.h>
-+#include <linux/pm_runtime.h>
-+#include <linux/reset.h>
-+#include <linux/slab.h>
-+#include <linux/types.h>
-+#include <sound/dmaengine_pcm.h>
-+#include <sound/pcm.h>
-+#include <sound/pcm_params.h>
-+#include <sound/soc.h>
-+
-+#define JH7110_PWMDAC_WDATA                           0x00
-+#define JH7110_PWMDAC_CTRL                            0x04
-+      #define JH7110_PWMDAC_ENABLE                    BIT(0)
-+      #define JH7110_PWMDAC_SHIFT                     BIT(1)
-+      #define JH7110_PWMDAC_DUTY_CYCLE_SHIFT          2
-+      #define JH7110_PWMDAC_DUTY_CYCLE_MASK           GENMASK(3, 2)
-+      #define JH7110_PWMDAC_CNT_N_SHIFT               4
-+      #define JH7110_PWMDAC_CNT_N_MASK                GENMASK(12, 4)
-+      #define JH7110_PWMDAC_DATA_CHANGE               BIT(13)
-+      #define JH7110_PWMDAC_DATA_MODE                 BIT(14)
-+      #define JH7110_PWMDAC_DATA_SHIFT_SHIFT          15
-+      #define JH7110_PWMDAC_DATA_SHIFT_MASK           GENMASK(17, 15)
-+
-+enum JH7110_PWMDAC_SHIFT_VAL {
-+      PWMDAC_SHIFT_8 = 0,
-+      PWMDAC_SHIFT_10,
-+};
-+
-+enum JH7110_PWMDAC_DUTY_CYCLE_VAL {
-+      PWMDAC_CYCLE_LEFT = 0,
-+      PWMDAC_CYCLE_RIGHT,
-+      PWMDAC_CYCLE_CENTER,
-+};
-+
-+enum JH7110_PWMDAC_CNT_N_VAL {
-+      PWMDAC_SAMPLE_CNT_1 = 1,
-+      PWMDAC_SAMPLE_CNT_2,
-+      PWMDAC_SAMPLE_CNT_3,
-+      PWMDAC_SAMPLE_CNT_512 = 512, /* max */
-+};
-+
-+enum JH7110_PWMDAC_DATA_CHANGE_VAL {
-+      NO_CHANGE = 0,
-+      CHANGE,
-+};
-+
-+enum JH7110_PWMDAC_DATA_MODE_VAL {
-+      UNSIGNED_DATA = 0,
-+      INVERTER_DATA_MSB,
-+};
-+
-+enum JH7110_PWMDAC_DATA_SHIFT_VAL {
-+      PWMDAC_DATA_LEFT_SHIFT_BIT_0 = 0,
-+      PWMDAC_DATA_LEFT_SHIFT_BIT_1,
-+      PWMDAC_DATA_LEFT_SHIFT_BIT_2,
-+      PWMDAC_DATA_LEFT_SHIFT_BIT_3,
-+      PWMDAC_DATA_LEFT_SHIFT_BIT_4,
-+      PWMDAC_DATA_LEFT_SHIFT_BIT_5,
-+      PWMDAC_DATA_LEFT_SHIFT_BIT_6,
-+      PWMDAC_DATA_LEFT_SHIFT_BIT_7,
-+};
-+
-+struct jh7110_pwmdac_cfg {
-+      enum JH7110_PWMDAC_SHIFT_VAL shift;
-+      enum JH7110_PWMDAC_DUTY_CYCLE_VAL duty_cycle;
-+      u16 cnt_n;
-+      enum JH7110_PWMDAC_DATA_CHANGE_VAL data_change;
-+      enum JH7110_PWMDAC_DATA_MODE_VAL data_mode;
-+      enum JH7110_PWMDAC_DATA_SHIFT_VAL data_shift;
-+};
-+
-+struct jh7110_pwmdac_dev {
-+      void __iomem *base;
-+      resource_size_t mapbase;
-+      struct jh7110_pwmdac_cfg cfg;
-+
-+      struct clk_bulk_data clks[2];
-+      struct reset_control *rst_apb;
-+      struct device *dev;
-+      struct snd_dmaengine_dai_dma_data play_dma_data;
-+      u32 saved_ctrl;
-+};
-+
-+static inline void jh7110_pwmdac_write_reg(void __iomem *io_base, int reg, u32 val)
-+{
-+      writel(val, io_base + reg);
-+}
-+
-+static inline u32 jh7110_pwmdac_read_reg(void __iomem *io_base, int reg)
-+{
-+      return readl(io_base + reg);
-+}
-+
-+static void jh7110_pwmdac_set_enable(struct jh7110_pwmdac_dev *dev, bool enable)
-+{
-+      u32 value;
-+
-+      value = jh7110_pwmdac_read_reg(dev->base, JH7110_PWMDAC_CTRL);
-+      if (enable)
-+              value |= JH7110_PWMDAC_ENABLE;
-+      else
-+              value &= ~JH7110_PWMDAC_ENABLE;
-+
-+      jh7110_pwmdac_write_reg(dev->base, JH7110_PWMDAC_CTRL, value);
-+}
-+
-+static void jh7110_pwmdac_set_shift(struct jh7110_pwmdac_dev *dev)
-+{
-+      u32 value;
-+
-+      value = jh7110_pwmdac_read_reg(dev->base, JH7110_PWMDAC_CTRL);
-+      if (dev->cfg.shift == PWMDAC_SHIFT_8)
-+              value &= ~JH7110_PWMDAC_SHIFT;
-+      else if (dev->cfg.shift == PWMDAC_SHIFT_10)
-+              value |= JH7110_PWMDAC_SHIFT;
-+
-+      jh7110_pwmdac_write_reg(dev->base, JH7110_PWMDAC_CTRL, value);
-+}
-+
-+static void jh7110_pwmdac_set_duty_cycle(struct jh7110_pwmdac_dev *dev)
-+{
-+      u32 value;
-+
-+      value = jh7110_pwmdac_read_reg(dev->base, JH7110_PWMDAC_CTRL);
-+      value &= ~JH7110_PWMDAC_DUTY_CYCLE_MASK;
-+      value |= (dev->cfg.duty_cycle & 0x3) << JH7110_PWMDAC_DUTY_CYCLE_SHIFT;
-+
-+      jh7110_pwmdac_write_reg(dev->base, JH7110_PWMDAC_CTRL, value);
-+}
-+
-+static void jh7110_pwmdac_set_cnt_n(struct jh7110_pwmdac_dev *dev)
-+{
-+      u32 value;
-+
-+      value = jh7110_pwmdac_read_reg(dev->base, JH7110_PWMDAC_CTRL);
-+      value &= ~JH7110_PWMDAC_CNT_N_MASK;
-+      value |= ((dev->cfg.cnt_n - 1) & 0x1ff) << JH7110_PWMDAC_CNT_N_SHIFT;
-+
-+      jh7110_pwmdac_write_reg(dev->base, JH7110_PWMDAC_CTRL, value);
-+}
-+
-+static void jh7110_pwmdac_set_data_change(struct jh7110_pwmdac_dev *dev)
-+{
-+      u32 value;
-+
-+      value = jh7110_pwmdac_read_reg(dev->base, JH7110_PWMDAC_CTRL);
-+      if (dev->cfg.data_change == NO_CHANGE)
-+              value &= ~JH7110_PWMDAC_DATA_CHANGE;
-+      else if (dev->cfg.data_change == CHANGE)
-+              value |= JH7110_PWMDAC_DATA_CHANGE;
-+
-+      jh7110_pwmdac_write_reg(dev->base, JH7110_PWMDAC_CTRL, value);
-+}
-+
-+static void jh7110_pwmdac_set_data_mode(struct jh7110_pwmdac_dev *dev)
-+{
-+      u32 value;
-+
-+      value = jh7110_pwmdac_read_reg(dev->base, JH7110_PWMDAC_CTRL);
-+      if (dev->cfg.data_mode == UNSIGNED_DATA)
-+              value &= ~JH7110_PWMDAC_DATA_MODE;
-+      else if (dev->cfg.data_mode == INVERTER_DATA_MSB)
-+              value |= JH7110_PWMDAC_DATA_MODE;
-+
-+      jh7110_pwmdac_write_reg(dev->base, JH7110_PWMDAC_CTRL, value);
-+}
-+
-+static void jh7110_pwmdac_set_data_shift(struct jh7110_pwmdac_dev *dev)
-+{
-+      u32 value;
-+
-+      value = jh7110_pwmdac_read_reg(dev->base, JH7110_PWMDAC_CTRL);
-+      value &= ~JH7110_PWMDAC_DATA_SHIFT_MASK;
-+      value |= (dev->cfg.data_shift & 0x7) << JH7110_PWMDAC_DATA_SHIFT_SHIFT;
-+
-+      jh7110_pwmdac_write_reg(dev->base, JH7110_PWMDAC_CTRL, value);
-+}
-+
-+static void jh7110_pwmdac_set(struct jh7110_pwmdac_dev *dev)
-+{
-+      jh7110_pwmdac_set_shift(dev);
-+      jh7110_pwmdac_set_duty_cycle(dev);
-+      jh7110_pwmdac_set_cnt_n(dev);
-+      jh7110_pwmdac_set_enable(dev, true);
-+
-+      jh7110_pwmdac_set_data_change(dev);
-+      jh7110_pwmdac_set_data_mode(dev);
-+      jh7110_pwmdac_set_data_shift(dev);
-+}
-+
-+static void jh7110_pwmdac_stop(struct jh7110_pwmdac_dev *dev)
-+{
-+      jh7110_pwmdac_set_enable(dev, false);
-+}
-+
-+static int jh7110_pwmdac_startup(struct snd_pcm_substream *substream,
-+                               struct snd_soc_dai *dai)
-+{
-+      struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream);
-+      struct snd_soc_dai_link *dai_link = rtd->dai_link;
-+
-+      dai_link->trigger_stop = SND_SOC_TRIGGER_ORDER_LDC;
-+
-+      return 0;
-+}
-+
-+static int jh7110_pwmdac_hw_params(struct snd_pcm_substream *substream,
-+                                 struct snd_pcm_hw_params *params,
-+                                 struct snd_soc_dai *dai)
-+{
-+      struct jh7110_pwmdac_dev *dev = dev_get_drvdata(dai->dev);
-+      unsigned long core_clk_rate;
-+      int ret;
-+
-+      switch (params_rate(params)) {
-+      case 8000:
-+              dev->cfg.cnt_n = PWMDAC_SAMPLE_CNT_3;
-+              core_clk_rate = 6144000;
-+              break;
-+      case 11025:
-+              dev->cfg.cnt_n = PWMDAC_SAMPLE_CNT_2;
-+              core_clk_rate = 5644800;
-+              break;
-+      case 16000:
-+              dev->cfg.cnt_n = PWMDAC_SAMPLE_CNT_3;
-+              core_clk_rate = 12288000;
-+              break;
-+      case 22050:
-+              dev->cfg.cnt_n = PWMDAC_SAMPLE_CNT_1;
-+              core_clk_rate = 5644800;
-+              break;
-+      case 32000:
-+              dev->cfg.cnt_n = PWMDAC_SAMPLE_CNT_1;
-+              core_clk_rate = 8192000;
-+              break;
-+      case 44100:
-+              dev->cfg.cnt_n = PWMDAC_SAMPLE_CNT_1;
-+              core_clk_rate = 11289600;
-+              break;
-+      case 48000:
-+              dev->cfg.cnt_n = PWMDAC_SAMPLE_CNT_1;
-+              core_clk_rate = 12288000;
-+              break;
-+      default:
-+              dev_err(dai->dev, "%d rate not supported\n",
-+                      params_rate(params));
-+              return -EINVAL;
-+      }
-+
-+      switch (params_channels(params)) {
-+      case 1:
-+              dev->play_dma_data.addr_width = DMA_SLAVE_BUSWIDTH_2_BYTES;
-+              break;
-+      case 2:
-+              dev->play_dma_data.addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES;
-+              break;
-+      default:
-+              dev_err(dai->dev, "%d channels not supported\n",
-+                      params_channels(params));
-+              return -EINVAL;
-+      }
-+
-+      /*
-+       * The clock rate always rounds down when using clk_set_rate()
-+       * so increase the rate a bit
-+       */
-+      core_clk_rate += 64;
-+      jh7110_pwmdac_set(dev);
-+
-+      ret = clk_set_rate(dev->clks[1].clk, core_clk_rate);
-+      if (ret)
-+              return dev_err_probe(dai->dev, ret,
-+                                   "failed to set rate %lu for core clock\n",
-+                                   core_clk_rate);
-+
-+      return 0;
-+}
-+
-+static int jh7110_pwmdac_trigger(struct snd_pcm_substream *substream, int cmd,
-+                               struct snd_soc_dai *dai)
-+{
-+      struct jh7110_pwmdac_dev *dev = 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_pwmdac_set(dev);
-+              break;
-+
-+      case SNDRV_PCM_TRIGGER_STOP:
-+      case SNDRV_PCM_TRIGGER_SUSPEND:
-+      case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
-+              jh7110_pwmdac_stop(dev);
-+              break;
-+      default:
-+              ret = -EINVAL;
-+              break;
-+      }
-+
-+      return ret;
-+}
-+
-+static int jh7110_pwmdac_crg_enable(struct jh7110_pwmdac_dev *dev, bool enable)
-+{
-+      int ret;
-+
-+      if (enable) {
-+              ret = clk_bulk_prepare_enable(ARRAY_SIZE(dev->clks), dev->clks);
-+              if (ret)
-+                      return dev_err_probe(dev->dev, ret,
-+                                           "failed to enable pwmdac clocks\n");
-+
-+              ret = reset_control_deassert(dev->rst_apb);
-+              if (ret) {
-+                      dev_err(dev->dev, "failed to deassert pwmdac apb reset\n");
-+                      goto err_rst_apb;
-+              }
-+      } else {
-+              clk_bulk_disable_unprepare(ARRAY_SIZE(dev->clks), dev->clks);
-+      }
-+
-+      return 0;
-+
-+err_rst_apb:
-+      clk_bulk_disable_unprepare(ARRAY_SIZE(dev->clks), dev->clks);
-+
-+      return ret;
-+}
-+
-+static int jh7110_pwmdac_dai_probe(struct snd_soc_dai *dai)
-+{
-+      struct jh7110_pwmdac_dev *dev = dev_get_drvdata(dai->dev);
-+
-+      snd_soc_dai_init_dma_data(dai, &dev->play_dma_data, NULL);
-+      snd_soc_dai_set_drvdata(dai, dev);
-+
-+      return 0;
-+}
-+
-+static const struct snd_soc_dai_ops jh7110_pwmdac_dai_ops = {
-+      .startup        = jh7110_pwmdac_startup,
-+      .hw_params      = jh7110_pwmdac_hw_params,
-+      .trigger        = jh7110_pwmdac_trigger,
-+};
-+
-+static const struct snd_soc_component_driver jh7110_pwmdac_component = {
-+      .name           = "jh7110-pwmdac",
-+};
-+
-+static struct snd_soc_dai_driver jh7110_pwmdac_dai = {
-+      .name           = "jh7110-pwmdac",
-+      .id             = 0,
-+      .probe          = jh7110_pwmdac_dai_probe,
-+      .playback = {
-+              .channels_min = 1,
-+              .channels_max = 2,
-+              .rates = SNDRV_PCM_RATE_8000_48000,
-+              .formats = SNDRV_PCM_FMTBIT_S16_LE,
-+      },
-+      .ops = &jh7110_pwmdac_dai_ops,
-+};
-+
-+static int jh7110_pwmdac_runtime_suspend(struct device *dev)
-+{
-+      struct jh7110_pwmdac_dev *pwmdac = dev_get_drvdata(dev);
-+
-+      return jh7110_pwmdac_crg_enable(pwmdac, false);
-+}
-+
-+static int jh7110_pwmdac_runtime_resume(struct device *dev)
-+{
-+      struct jh7110_pwmdac_dev *pwmdac = dev_get_drvdata(dev);
-+
-+      return jh7110_pwmdac_crg_enable(pwmdac, true);
-+}
-+
-+static int jh7110_pwmdac_system_suspend(struct device *dev)
-+{
-+      struct jh7110_pwmdac_dev *pwmdac = dev_get_drvdata(dev);
-+
-+      /* save the CTRL register value */
-+      pwmdac->saved_ctrl = jh7110_pwmdac_read_reg(pwmdac->base,
-+                                                  JH7110_PWMDAC_CTRL);
-+      return pm_runtime_force_suspend(dev);
-+}
-+
-+static int jh7110_pwmdac_system_resume(struct device *dev)
-+{
-+      struct jh7110_pwmdac_dev *pwmdac = dev_get_drvdata(dev);
-+      int ret;
-+
-+      ret = pm_runtime_force_resume(dev);
-+      if (ret)
-+              return ret;
-+
-+      /* restore the CTRL register value */
-+      jh7110_pwmdac_write_reg(pwmdac->base, JH7110_PWMDAC_CTRL,
-+                              pwmdac->saved_ctrl);
-+      return 0;
-+}
-+
-+static const struct dev_pm_ops jh7110_pwmdac_pm_ops = {
-+      RUNTIME_PM_OPS(jh7110_pwmdac_runtime_suspend,
-+                     jh7110_pwmdac_runtime_resume, NULL)
-+      SYSTEM_SLEEP_PM_OPS(jh7110_pwmdac_system_suspend,
-+                          jh7110_pwmdac_system_resume)
-+};
-+
-+static void jh7110_pwmdac_init_params(struct jh7110_pwmdac_dev *dev)
-+{
-+      dev->cfg.shift = PWMDAC_SHIFT_8;
-+      dev->cfg.duty_cycle = PWMDAC_CYCLE_CENTER;
-+      dev->cfg.cnt_n = PWMDAC_SAMPLE_CNT_1;
-+      dev->cfg.data_change = NO_CHANGE;
-+      dev->cfg.data_mode = INVERTER_DATA_MSB;
-+      dev->cfg.data_shift = PWMDAC_DATA_LEFT_SHIFT_BIT_0;
-+
-+      dev->play_dma_data.addr = dev->mapbase + JH7110_PWMDAC_WDATA;
-+      dev->play_dma_data.addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES;
-+      dev->play_dma_data.fifo_size = 1;
-+      dev->play_dma_data.maxburst = 16;
-+}
-+
-+static int jh7110_pwmdac_probe(struct platform_device *pdev)
-+{
-+      struct jh7110_pwmdac_dev *dev;
-+      struct resource *res;
-+      int ret;
-+
-+      dev = devm_kzalloc(&pdev->dev, sizeof(*dev), GFP_KERNEL);
-+      if (!dev)
-+              return -ENOMEM;
-+
-+      dev->base = devm_platform_get_and_ioremap_resource(pdev, 0, &res);
-+      if (IS_ERR(dev->base))
-+              return PTR_ERR(dev->base);
-+
-+      dev->mapbase = res->start;
-+
-+      dev->clks[0].id = "apb";
-+      dev->clks[1].id = "core";
-+
-+      ret = devm_clk_bulk_get(&pdev->dev, ARRAY_SIZE(dev->clks), dev->clks);
-+      if (ret)
-+              return dev_err_probe(&pdev->dev, ret,
-+                                   "failed to get pwmdac clocks\n");
-+
-+      dev->rst_apb = devm_reset_control_get_exclusive(&pdev->dev, NULL);
-+      if (IS_ERR(dev->rst_apb))
-+              return dev_err_probe(&pdev->dev, PTR_ERR(dev->rst_apb),
-+                                   "failed to get pwmdac apb reset\n");
-+
-+      jh7110_pwmdac_init_params(dev);
-+
-+      dev->dev = &pdev->dev;
-+      dev_set_drvdata(&pdev->dev, dev);
-+      ret = devm_snd_soc_register_component(&pdev->dev,
-+                                            &jh7110_pwmdac_component,
-+                                            &jh7110_pwmdac_dai, 1);
-+      if (ret)
-+              return dev_err_probe(&pdev->dev, ret, "failed to register dai\n");
-+
-+      ret = devm_snd_dmaengine_pcm_register(&pdev->dev, NULL, 0);
-+      if (ret)
-+              return dev_err_probe(&pdev->dev, ret, "failed to register pcm\n");
-+
-+      pm_runtime_enable(dev->dev);
-+      if (!pm_runtime_enabled(&pdev->dev)) {
-+              ret = jh7110_pwmdac_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_pwmdac_remove(struct platform_device *pdev)
-+{
-+      pm_runtime_disable(&pdev->dev);
-+      return 0;
-+}
-+
-+static const struct of_device_id jh7110_pwmdac_of_match[] = {
-+      { .compatible = "starfive,jh7110-pwmdac" },
-+      { /* sentinel */ }
-+};
-+MODULE_DEVICE_TABLE(of, jh7110_pwmdac_of_match);
-+
-+static struct platform_driver jh7110_pwmdac_driver = {
-+      .driver         = {
-+              .name   = "jh7110-pwmdac",
-+              .of_match_table = jh7110_pwmdac_of_match,
-+              .pm = pm_ptr(&jh7110_pwmdac_pm_ops),
-+      },
-+      .probe          = jh7110_pwmdac_probe,
-+      .remove         = jh7110_pwmdac_remove,
-+};
-+module_platform_driver(jh7110_pwmdac_driver);
-+
-+MODULE_AUTHOR("Jenny Zhang");
-+MODULE_AUTHOR("Curry Zhang");
-+MODULE_AUTHOR("Xingyu Wu <xingyu.wu@starfivetech.com>");
-+MODULE_AUTHOR("Hal Feng <hal.feng@starfivetech.com>");
-+MODULE_DESCRIPTION("StarFive JH7110 PWM-DAC driver");
-+MODULE_LICENSE("GPL");
diff --git a/target/linux/starfive/patches-6.6/0037-ASoC-Update-jh7110-PWM-DAC-for-ops-move.patch b/target/linux/starfive/patches-6.6/0037-ASoC-Update-jh7110-PWM-DAC-for-ops-move.patch
deleted file mode 100644 (file)
index 4833067..0000000
+++ /dev/null
@@ -1,32 +0,0 @@
-From c6b693f990e1f89ab5af0a139da31401b8cda74f Mon Sep 17 00:00:00 2001
-From: Mark Brown <broonie@kernel.org>
-Date: Mon, 11 Sep 2023 23:48:39 +0100
-Subject: [PATCH 037/116] ASoC: Update jh7110 PWM DAC for ops move
-
-For some reason the JH7110 PWM DAC driver made it through build testing
-in spite of not being updated for the move of probe() to the ops struct.
-Make the required update.
-
-Signed-off-by: Mark Brown <broonie@kernel.org>
----
- sound/soc/starfive/jh7110_pwmdac.c | 2 +-
- 1 file changed, 1 insertion(+), 1 deletion(-)
-
---- a/sound/soc/starfive/jh7110_pwmdac.c
-+++ b/sound/soc/starfive/jh7110_pwmdac.c
-@@ -357,6 +357,7 @@ static int jh7110_pwmdac_dai_probe(struc
- }
- static const struct snd_soc_dai_ops jh7110_pwmdac_dai_ops = {
-+      .probe          = jh7110_pwmdac_dai_probe,
-       .startup        = jh7110_pwmdac_startup,
-       .hw_params      = jh7110_pwmdac_hw_params,
-       .trigger        = jh7110_pwmdac_trigger,
-@@ -369,7 +370,6 @@ static const struct snd_soc_component_dr
- static struct snd_soc_dai_driver jh7110_pwmdac_dai = {
-       .name           = "jh7110-pwmdac",
-       .id             = 0,
--      .probe          = jh7110_pwmdac_dai_probe,
-       .playback = {
-               .channels_min = 1,
-               .channels_max = 2,
diff --git a/target/linux/starfive/patches-6.6/0038-ASoC-starfive-jh7110-pwmdac-Convert-to-platform-remo.patch b/target/linux/starfive/patches-6.6/0038-ASoC-starfive-jh7110-pwmdac-Convert-to-platform-remo.patch
deleted file mode 100644 (file)
index 9b5f553..0000000
+++ /dev/null
@@ -1,52 +0,0 @@
-From 312c3c407c363f0ec7417d2d389cbe936c503729 Mon Sep 17 00:00:00 2001
-From: =?UTF-8?q?Uwe=20Kleine-K=C3=B6nig?= <u.kleine-koenig@pengutronix.de>
-Date: Sat, 14 Oct 2023 00:19:49 +0200
-Subject: [PATCH 038/116] ASoC: starfive/jh7110-pwmdac: Convert to platform
- remove callback returning void
-MIME-Version: 1.0
-Content-Type: text/plain; charset=UTF-8
-Content-Transfer-Encoding: 8bit
-
-The .remove() callback for a platform driver returns an int which makes
-many driver authors wrongly assume it's possible to do error handling by
-returning an error code. However the value returned is ignored (apart
-from emitting a warning) and this typically results in resource leaks.
-
-To improve here there is a quest to make the remove callback return
-void. In the first step of this quest all drivers are converted to
-.remove_new(), which already returns void. Eventually after all drivers
-are converted, .remove_new() will be renamed to .remove().
-
-Trivially convert this driver from always returning zero in the remove
-callback to the void returning variant.
-
-Signed-off-by: Uwe Kleine-König <u.kleine-koenig@pengutronix.de>
-Link: https://lore.kernel.org/r/20231013221945.1489203-12-u.kleine-koenig@pengutronix.de
-Signed-off-by: Mark Brown <broonie@kernel.org>
----
- sound/soc/starfive/jh7110_pwmdac.c | 5 ++---
- 1 file changed, 2 insertions(+), 3 deletions(-)
-
---- a/sound/soc/starfive/jh7110_pwmdac.c
-+++ b/sound/soc/starfive/jh7110_pwmdac.c
-@@ -498,10 +498,9 @@ err_pm_disable:
-       return ret;
- }
--static int jh7110_pwmdac_remove(struct platform_device *pdev)
-+static void jh7110_pwmdac_remove(struct platform_device *pdev)
- {
-       pm_runtime_disable(&pdev->dev);
--      return 0;
- }
- static const struct of_device_id jh7110_pwmdac_of_match[] = {
-@@ -517,7 +516,7 @@ static struct platform_driver jh7110_pwm
-               .pm = pm_ptr(&jh7110_pwmdac_pm_ops),
-       },
-       .probe          = jh7110_pwmdac_probe,
--      .remove         = jh7110_pwmdac_remove,
-+      .remove_new     = jh7110_pwmdac_remove,
- };
- module_platform_driver(jh7110_pwmdac_driver);
diff --git a/target/linux/starfive/patches-6.6/0039-dt-bindings-power-Add-power-domain-header-for-JH7110.patch b/target/linux/starfive/patches-6.6/0039-dt-bindings-power-Add-power-domain-header-for-JH7110.patch
deleted file mode 100644 (file)
index bcc9af2..0000000
+++ /dev/null
@@ -1,35 +0,0 @@
-From 8d84bac6d7471ba2e29b33d19a2ef887822e9cce Mon Sep 17 00:00:00 2001
-From: Changhuang Liang <changhuang.liang@starfivetech.com>
-Date: Wed, 13 Sep 2023 14:54:25 +0100
-Subject: [PATCH 039/116] 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 <changhuang.liang@starfivetech.com>
-Signed-off-by: Conor Dooley <conor.dooley@microchip.com>
-Link: https://lore.kernel.org/r/20230913-grumbly-rewrite-34c85539f2ed@spud
-Signed-off-by: Ulf Hansson <ulf.hansson@linaro.org>
----
- 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 <walker.chen@starfivetech.com>
-  */
- #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
diff --git a/target/linux/starfive/patches-6.6/0040-pmdomain-starfive-Replace-SOC_STARFIVE-with-ARCH_STA.patch b/target/linux/starfive/patches-6.6/0040-pmdomain-starfive-Replace-SOC_STARFIVE-with-ARCH_STA.patch
deleted file mode 100644 (file)
index 335193f..0000000
+++ /dev/null
@@ -1,31 +0,0 @@
-From 0ac8e8b0e65d242f455401df0cc6c6d4772216e6 Mon Sep 17 00:00:00 2001
-From: Changhuang Liang <changhuang.liang@starfivetech.com>
-Date: Wed, 13 Sep 2023 14:54:26 +0100
-Subject: [PATCH 040/116] pmdomain: starfive: Replace SOC_STARFIVE with
- ARCH_STARFIVE
-
-Using ARCH_FOO symbol is preferred than SOC_FOO.
-
-Reviewed-by: Conor Dooley <conor.dooley@microchip.com>
-Reviewed-by: Walker Chen <walker.chen@starfivetech.com>
-Signed-off-by: Changhuang Liang <changhuang.liang@starfivetech.com>
-Signed-off-by: Conor Dooley <conor.dooley@microchip.com>
-Link: https://lore.kernel.org/r/20230913-legibly-treachery-567cffcb5604@spud
-Signed-off-by: Ulf Hansson <ulf.hansson@linaro.org>
----
- 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.
diff --git a/target/linux/starfive/patches-6.6/0041-pmdomain-starfive-Extract-JH7110-pmu-private-operati.patch b/target/linux/starfive/patches-6.6/0041-pmdomain-starfive-Extract-JH7110-pmu-private-operati.patch
deleted file mode 100644 (file)
index 7425dd6..0000000
+++ /dev/null
@@ -1,179 +0,0 @@
-From a1ba60e35ca7f1b85243054556ecde2e259619e1 Mon Sep 17 00:00:00 2001
-From: Changhuang Liang <changhuang.liang@starfivetech.com>
-Date: Wed, 13 Sep 2023 14:54:27 +0100
-Subject: [PATCH 041/116] pmdomain: 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 <changhuang.liang@starfivetech.com>
-Reviewed-by: Walker Chen <walker.chen@starfivetech.com>
-Signed-off-by: Conor Dooley <conor.dooley@microchip.com>
-Link: https://lore.kernel.org/r/20230913-slideshow-luckiness-38ff17de84c6@spud
-Signed-off-by: Ulf Hansson <ulf.hansson@linaro.org>
----
- drivers/pmdomain/starfive/jh71xx-pmu.c | 89 ++++++++++++++++++--------
- 1 file changed, 62 insertions(+), 27 deletions(-)
-
---- a/drivers/pmdomain/starfive/jh71xx-pmu.c
-+++ b/drivers/pmdomain/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[] = {
diff --git a/target/linux/starfive/patches-6.6/0042-pmdomain-starfive-Add-JH7110-AON-PMU-support.patch b/target/linux/starfive/patches-6.6/0042-pmdomain-starfive-Add-JH7110-AON-PMU-support.patch
deleted file mode 100644 (file)
index 2563d54..0000000
+++ /dev/null
@@ -1,122 +0,0 @@
-From 1bf849b606d0b4cae643f96685d3d3981643683d Mon Sep 17 00:00:00 2001
-From: Changhuang Liang <changhuang.liang@starfivetech.com>
-Date: Wed, 13 Sep 2023 14:54:28 +0100
-Subject: [PATCH 042/116] pmdomain: 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 <walker.chen@starfivetech.com>
-Signed-off-by: Changhuang Liang <changhuang.liang@starfivetech.com>
-Signed-off-by: Conor Dooley <conor.dooley@microchip.com>
-Link: https://lore.kernel.org/r/20230913-dude-imprecise-fc32622bc947@spud
-Signed-off-by: Ulf Hansson <ulf.hansson@linaro.org>
----
- drivers/pmdomain/starfive/jh71xx-pmu.c | 57 +++++++++++++++++++++++---
- 1 file changed, 52 insertions(+), 5 deletions(-)
-
---- a/drivers/pmdomain/starfive/jh71xx-pmu.c
-+++ b/drivers/pmdomain/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 <walker.chen@starfivetech.com>");
-+MODULE_AUTHOR("Changhuang Liang <changhuang.liang@starfivetech.com>");
- MODULE_DESCRIPTION("StarFive JH71XX PMU Driver");
- MODULE_LICENSE("GPL");
diff --git a/target/linux/starfive/patches-6.6/0043-pmdomain-Prepare-to-move-Kconfig-files-into-the-pmdo.patch b/target/linux/starfive/patches-6.6/0043-pmdomain-Prepare-to-move-Kconfig-files-into-the-pmdo.patch
deleted file mode 100644 (file)
index 52be89f..0000000
+++ /dev/null
@@ -1,36 +0,0 @@
-From dff6605dcd1fc1e2af1437e59187a6f71ce389cd Mon Sep 17 00:00:00 2001
-From: Ulf Hansson <ulf.hansson@linaro.org>
-Date: Mon, 11 Sep 2023 17:22:15 +0200
-Subject: [PATCH 043/116] pmdomain: Prepare to move Kconfig files into the
- pmdomain subsystem
-
-Rather than having the various Kconfig files for the genpd providers
-sprinkled across subsystems, let's prepare to move them into the pmdomain
-subsystem along with the implementations.
-
-Reviewed-by: Geert Uytterhoeven <geert+renesas@glider.be>
-Signed-off-by: Ulf Hansson <ulf.hansson@linaro.org>
----
- drivers/Kconfig          | 2 ++
- drivers/pmdomain/Kconfig | 4 ++++
- 2 files changed, 6 insertions(+)
- create mode 100644 drivers/pmdomain/Kconfig
-
---- a/drivers/Kconfig
-+++ b/drivers/Kconfig
-@@ -175,6 +175,8 @@ source "drivers/soundwire/Kconfig"
- source "drivers/soc/Kconfig"
-+source "drivers/pmdomain/Kconfig"
-+
- source "drivers/devfreq/Kconfig"
- source "drivers/extcon/Kconfig"
---- /dev/null
-+++ b/drivers/pmdomain/Kconfig
-@@ -0,0 +1,4 @@
-+# SPDX-License-Identifier: GPL-2.0-only
-+menu "PM Domains"
-+
-+endmenu
diff --git a/target/linux/starfive/patches-6.6/0044-pmdomain-starfive-Move-Kconfig-file-to-the-pmdomain-.patch b/target/linux/starfive/patches-6.6/0044-pmdomain-starfive-Move-Kconfig-file-to-the-pmdomain-.patch
deleted file mode 100644 (file)
index 909f4cc..0000000
+++ /dev/null
@@ -1,69 +0,0 @@
-From de12fe43dbd0ea9fa980ffa05822bd7fd5eed330 Mon Sep 17 00:00:00 2001
-From: Ulf Hansson <ulf.hansson@linaro.org>
-Date: Tue, 12 Sep 2023 13:31:44 +0200
-Subject: [PATCH 044/116] pmdomain: starfive: Move Kconfig file to the pmdomain
- subsystem
-
-The Kconfig belongs closer to the corresponding implementation, hence let's
-move it from the soc subsystem to the pmdomain subsystem.
-
-Cc: Walker Chen <walker.chen@starfivetech.com>
-Cc: Conor Dooley <conor@kernel.org>
-Acked-by: Conor Dooley <conor.dooley@microchip.com>
-Signed-off-by: Ulf Hansson <ulf.hansson@linaro.org>
----
- drivers/pmdomain/Kconfig                   | 2 ++
- drivers/{soc => pmdomain}/starfive/Kconfig | 0
- drivers/soc/Kconfig                        | 1 -
- 3 files changed, 2 insertions(+), 1 deletion(-)
- rename drivers/{soc => pmdomain}/starfive/Kconfig (100%)
-
---- a/drivers/pmdomain/Kconfig
-+++ b/drivers/pmdomain/Kconfig
-@@ -1,4 +1,6 @@
- # SPDX-License-Identifier: GPL-2.0-only
- menu "PM Domains"
-+source "drivers/pmdomain/starfive/Kconfig"
-+
- endmenu
---- a/drivers/soc/Kconfig
-+++ b/drivers/soc/Kconfig
-@@ -24,7 +24,6 @@ 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"
---- /dev/null
-+++ b/drivers/pmdomain/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 ARCH_STARFIVE || COMPILE_TEST
-+      default ARCH_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.
---- a/drivers/soc/starfive/Kconfig
-+++ /dev/null
-@@ -1,12 +0,0 @@
--# SPDX-License-Identifier: GPL-2.0
--
--config JH71XX_PMU
--      bool "Support PMU for StarFive JH71XX Soc"
--      depends on PM
--      depends on ARCH_STARFIVE || COMPILE_TEST
--      default ARCH_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.
diff --git a/target/linux/starfive/patches-6.6/0045-dt-bindings-power-Update-prefixes-for-AON-power-doma.patch b/target/linux/starfive/patches-6.6/0045-dt-bindings-power-Update-prefixes-for-AON-power-doma.patch
deleted file mode 100644 (file)
index c6e0012..0000000
+++ /dev/null
@@ -1,31 +0,0 @@
-From cac9ce9c7f388a741389b1ec47af65420254db55 Mon Sep 17 00:00:00 2001
-From: Changhuang Liang <changhuang.liang@starfivetech.com>
-Date: Wed, 27 Sep 2023 06:07:33 -0700
-Subject: [PATCH 045/116] dt-bindings: power: Update prefixes for AON power
- domain
-
-Use "JH7110_AON_PD_" prefix for AON power domain for JH7110 SoC.
-
-Reviewed-by: Walker Chen <walker.chen@starfivetech.com>
-Signed-off-by: Changhuang Liang <changhuang.liang@starfivetech.com>
-Acked-by: Conor Dooley <conor.dooley@microchip.com>
-Reviewed-by: Geert Uytterhoeven <geert+renesas@glider.be>
-Link: https://lore.kernel.org/r/20230927130734.9921-2-changhuang.liang@starfivetech.com
-Signed-off-by: Ulf Hansson <ulf.hansson@linaro.org>
----
- include/dt-bindings/power/starfive,jh7110-pmu.h | 5 +++--
- 1 file changed, 3 insertions(+), 2 deletions(-)
-
---- a/include/dt-bindings/power/starfive,jh7110-pmu.h
-+++ b/include/dt-bindings/power/starfive,jh7110-pmu.h
-@@ -14,7 +14,8 @@
- #define JH7110_PD_ISP         5
- #define JH7110_PD_VENC                6
--#define JH7110_PD_DPHY_TX     0
--#define JH7110_PD_DPHY_RX     1
-+/* AON Power Domain */
-+#define JH7110_AON_PD_DPHY_TX 0
-+#define JH7110_AON_PD_DPHY_RX 1
- #endif
diff --git a/target/linux/starfive/patches-6.6/0046-pmdomain-starfive-Update-prefixes-for-AON-power-doma.patch b/target/linux/starfive/patches-6.6/0046-pmdomain-starfive-Update-prefixes-for-AON-power-doma.patch
deleted file mode 100644 (file)
index 5cb89ae..0000000
+++ /dev/null
@@ -1,32 +0,0 @@
-From 3ea89ffbd6cc5a15acca6bc2130572f8bd85b9d4 Mon Sep 17 00:00:00 2001
-From: Changhuang Liang <changhuang.liang@starfivetech.com>
-Date: Wed, 27 Sep 2023 06:07:34 -0700
-Subject: [PATCH 046/116] pmdomain: starfive: Update prefixes for AON power
- domain
-
-Use "JH7110_AON_PD_" prefix for AON power doamin for JH7110 SoC.
-
-Reviewed-by: Walker Chen <walker.chen@starfivetech.com>
-Signed-off-by: Changhuang Liang <changhuang.liang@starfivetech.com>
-Link: https://lore.kernel.org/r/20230927130734.9921-3-changhuang.liang@starfivetech.com
-Signed-off-by: Ulf Hansson <ulf.hansson@linaro.org>
----
- drivers/pmdomain/starfive/jh71xx-pmu.c | 4 ++--
- 1 file changed, 2 insertions(+), 2 deletions(-)
-
---- a/drivers/pmdomain/starfive/jh71xx-pmu.c
-+++ b/drivers/pmdomain/starfive/jh71xx-pmu.c
-@@ -420,11 +420,11 @@ static const struct jh71xx_pmu_match_dat
- };
- static const struct jh71xx_domain_info jh7110_aon_power_domains[] = {
--      [JH7110_PD_DPHY_TX] = {
-+      [JH7110_AON_PD_DPHY_TX] = {
-               .name = "DPHY-TX",
-               .bit = 30,
-       },
--      [JH7110_PD_DPHY_RX] = {
-+      [JH7110_AON_PD_DPHY_RX] = {
-               .name = "DPHY-RX",
-               .bit = 31,
-       },
diff --git a/target/linux/starfive/patches-6.6/0047-riscv-dts-starfive-pinfunc-Fix-the-pins-name-of-I2ST.patch b/target/linux/starfive/patches-6.6/0047-riscv-dts-starfive-pinfunc-Fix-the-pins-name-of-I2ST.patch
deleted file mode 100644 (file)
index 782e71a..0000000
+++ /dev/null
@@ -1,30 +0,0 @@
-From e7e3d62b7a470ddf15e30574232b52b2e23ba606 Mon Sep 17 00:00:00 2001
-From: Xingyu Wu <xingyu.wu@starfivetech.com>
-Date: Mon, 21 Aug 2023 22:41:50 +0800
-Subject: [PATCH 047/116] riscv: dts: starfive: pinfunc: Fix the pins name of
- I2STX1
-
-These pins are actually I2STX1 clock input, not I2STX0,
-so their names should be changed.
-
-Signed-off-by: Xingyu Wu <xingyu.wu@starfivetech.com>
-Reviewed-by: Walker Chen <walker.chen@starfivetech.com>
-Acked-by: Rob Herring <robh@kernel.org>
-Signed-off-by: Conor Dooley <conor.dooley@microchip.com>
----
- arch/riscv/boot/dts/starfive/jh7110-pinfunc.h | 4 ++--
- 1 file changed, 2 insertions(+), 2 deletions(-)
-
---- a/arch/riscv/boot/dts/starfive/jh7110-pinfunc.h
-+++ b/arch/riscv/boot/dts/starfive/jh7110-pinfunc.h
-@@ -240,8 +240,8 @@
- #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_I2STX1_BCLK                   33
-+#define GPI_SYS_I2STX1_LRCK                   34
- #define GPI_SYS_TDM_CLK                               35
- #define GPI_SYS_TDM_RXD                               36
- #define GPI_SYS_TDM_SYNC                      37
diff --git a/target/linux/starfive/patches-6.6/0048-riscv-dts-starfive-Add-full-support-except-VIN-and-V.patch b/target/linux/starfive/patches-6.6/0048-riscv-dts-starfive-Add-full-support-except-VIN-and-V.patch
deleted file mode 100644 (file)
index 75dd965..0000000
+++ /dev/null
@@ -1,536 +0,0 @@
-From a3d3f611f31fa2dca3deefa7cd443abca02e03fa Mon Sep 17 00:00:00 2001
-From: Hal Feng <hal.feng@starfivetech.com>
-Date: Tue, 11 Apr 2023 16:31:15 +0800
-Subject: [PATCH 048/116] riscv: dts: starfive: Add full support (except VIN
- and VOUT) for JH7110 and VisionFive 2 board
-
-Merge all StarFive dts patches together except VIN and VOUT.
-
-Signed-off-by: Hal Feng <hal.feng@starfivetech.com>
----
- .../jh7110-starfive-visionfive-2.dtsi         | 199 +++++++++++++++
- arch/riscv/boot/dts/starfive/jh7110.dtsi      | 233 ++++++++++++++++++
- 2 files changed, 432 insertions(+)
-
---- a/arch/riscv/boot/dts/starfive/jh7110-starfive-visionfive-2.dtsi
-+++ b/arch/riscv/boot/dts/starfive/jh7110-starfive-visionfive-2.dtsi
-@@ -19,6 +19,8 @@
-               i2c6 = &i2c6;
-               mmc0 = &mmc0;
-               mmc1 = &mmc1;
-+              pcie0 = &pcie0;
-+              pcie1 = &pcie1;
-               serial0 = &uart0;
-       };
-@@ -40,6 +42,33 @@
-               gpios = <&sysgpio 35 GPIO_ACTIVE_HIGH>;
-               priority = <224>;
-       };
-+
-+      pwmdac_codec: pwmdac-codec {
-+              compatible = "linux,spdif-dit";
-+              #sound-dai-cells = <0>;
-+      };
-+
-+      sound-pwmdac {
-+              compatible = "simple-audio-card";
-+              simple-audio-card,name = "StarFive-PWMDAC-Sound-Card";
-+              #address-cells = <1>;
-+              #size-cells = <0>;
-+
-+              simple-audio-card,dai-link@0 {
-+                      reg = <0>;
-+                      format = "left_j";
-+                      bitclock-master = <&sndcpu0>;
-+                      frame-master = <&sndcpu0>;
-+
-+                      sndcpu0: cpu {
-+                              sound-dai = <&pwmdac>;
-+                      };
-+
-+                      codec {
-+                              sound-dai = <&pwmdac_codec>;
-+                      };
-+              };
-+      };
- };
- &dvp_clk {
-@@ -202,6 +231,24 @@
-       status = "okay";
- };
-+&i2srx {
-+      pinctrl-names = "default";
-+      pinctrl-0 = <&i2srx_pins>;
-+      status = "okay";
-+};
-+
-+&i2stx0 {
-+      pinctrl-names = "default";
-+      pinctrl-0 = <&mclk_ext_pins>;
-+      status = "okay";
-+};
-+
-+&i2stx1 {
-+      pinctrl-names = "default";
-+      pinctrl-0 = <&i2stx1_pins>;
-+      status = "okay";
-+};
-+
- &mmc0 {
-       max-frequency = <100000000>;
-       assigned-clocks = <&syscrg JH7110_SYSCLK_SDIO0_SDCARD>;
-@@ -235,6 +282,34 @@
-       status = "okay";
- };
-+&pcie0 {
-+      perst-gpios = <&sysgpio 26 GPIO_ACTIVE_LOW>;
-+      phys = <&pciephy0>;
-+      pinctrl-names = "default";
-+      pinctrl-0 = <&pcie0_pins>;
-+      status = "okay";
-+};
-+
-+&pcie1 {
-+      perst-gpios = <&sysgpio 28 GPIO_ACTIVE_LOW>;
-+      phys = <&pciephy1>;
-+      pinctrl-names = "default";
-+      pinctrl-0 = <&pcie1_pins>;
-+      status = "okay";
-+};
-+
-+&pwm {
-+      pinctrl-names = "default";
-+      pinctrl-0 = <&pwm_pins>;
-+      status = "okay";
-+};
-+
-+&pwmdac {
-+      pinctrl-names = "default";
-+      pinctrl-0 = <&pwmdac_pins>;
-+      status = "okay";
-+};
-+
- &qspi {
-       #address-cells = <1>;
-       #size-cells = <0>;
-@@ -340,6 +415,46 @@
-               };
-       };
-+      i2srx_pins: i2srx-0 {
-+              clk-sd-pins {
-+                      pinmux = <GPIOMUX(38, GPOUT_LOW,
-+                                            GPOEN_DISABLE,
-+                                            GPI_SYS_I2SRX_BCLK)>,
-+                               <GPIOMUX(63, GPOUT_LOW,
-+                                            GPOEN_DISABLE,
-+                                            GPI_SYS_I2SRX_LRCK)>,
-+                               <GPIOMUX(38, GPOUT_LOW,
-+                                            GPOEN_DISABLE,
-+                                            GPI_SYS_I2STX1_BCLK)>,
-+                               <GPIOMUX(63, GPOUT_LOW,
-+                                            GPOEN_DISABLE,
-+                                            GPI_SYS_I2STX1_LRCK)>,
-+                               <GPIOMUX(61, GPOUT_LOW,
-+                                            GPOEN_DISABLE,
-+                                            GPI_SYS_I2SRX_SDIN0)>;
-+                      input-enable;
-+              };
-+      };
-+
-+      i2stx1_pins: i2stx1-0 {
-+              sd-pins {
-+                      pinmux = <GPIOMUX(44, GPOUT_SYS_I2STX1_SDO0,
-+                                            GPOEN_ENABLE,
-+                                            GPI_NONE)>;
-+                      bias-disable;
-+                      input-disable;
-+              };
-+      };
-+
-+      mclk_ext_pins: mclk-ext-0 {
-+              mclk-ext-pins {
-+                      pinmux = <GPIOMUX(4, GPOUT_LOW,
-+                                           GPOEN_DISABLE,
-+                                           GPI_SYS_MCLK_EXT)>;
-+                      input-enable;
-+              };
-+      };
-+
-       mmc0_pins: mmc0-0 {
-                rst-pins {
-                       pinmux = <GPIOMUX(62, GPOUT_SYS_SDIO0_RST,
-@@ -404,6 +519,86 @@
-                       slew-rate = <0>;
-               };
-       };
-+
-+      pcie0_pins: pcie0-0 {
-+              clkreq-pins {
-+                      pinmux = <GPIOMUX(27, GPOUT_LOW,
-+                                            GPOEN_DISABLE,
-+                                            GPI_NONE)>;
-+                      bias-pull-down;
-+                      drive-strength = <2>;
-+                      input-enable;
-+                      input-schmitt-disable;
-+                      slew-rate = <0>;
-+              };
-+
-+              wake-pins {
-+                      pinmux = <GPIOMUX(32, GPOUT_LOW,
-+                                            GPOEN_DISABLE,
-+                                            GPI_NONE)>;
-+                      bias-pull-up;
-+                      drive-strength = <2>;
-+                      input-enable;
-+                      input-schmitt-disable;
-+                      slew-rate = <0>;
-+              };
-+      };
-+
-+      pcie1_pins: pcie1-0 {
-+              clkreq-pins {
-+                      pinmux = <GPIOMUX(29, GPOUT_LOW,
-+                                            GPOEN_DISABLE,
-+                                            GPI_NONE)>;
-+                      bias-pull-down;
-+                      drive-strength = <2>;
-+                      input-enable;
-+                      input-schmitt-disable;
-+                      slew-rate = <0>;
-+              };
-+
-+              wake-pins {
-+                      pinmux = <GPIOMUX(21, GPOUT_LOW,
-+                                            GPOEN_DISABLE,
-+                                            GPI_NONE)>;
-+                      bias-pull-up;
-+                      drive-strength = <2>;
-+                      input-enable;
-+                      input-schmitt-disable;
-+                      slew-rate = <0>;
-+              };
-+      };
-+
-+      pwm_pins: pwm-0 {
-+              pwm-pins {
-+                      pinmux = <GPIOMUX(46, GPOUT_SYS_PWM_CHANNEL0,
-+                                            GPOEN_SYS_PWM0_CHANNEL0,
-+                                            GPI_NONE)>,
-+                               <GPIOMUX(59, GPOUT_SYS_PWM_CHANNEL1,
-+                                            GPOEN_SYS_PWM0_CHANNEL1,
-+                                            GPI_NONE)>;
-+                      bias-disable;
-+                      drive-strength = <12>;
-+                      input-disable;
-+                      input-schmitt-disable;
-+                      slew-rate = <0>;
-+              };
-+      };
-+
-+      pwmdac_pins: pwmdac-0 {
-+              pwmdac-pins {
-+                      pinmux = <GPIOMUX(33, GPOUT_SYS_PWMDAC_LEFT,
-+                                            GPOEN_ENABLE,
-+                                            GPI_NONE)>,
-+                               <GPIOMUX(34, GPOUT_SYS_PWMDAC_RIGHT,
-+                                            GPOEN_ENABLE,
-+                                            GPI_NONE)>;
-+                      bias-disable;
-+                      drive-strength = <2>;
-+                      input-disable;
-+                      input-schmitt-disable;
-+                      slew-rate = <0>;
-+              };
-+      };
-       spi0_pins: spi0-0 {
-               mosi-pins {
---- a/arch/riscv/boot/dts/starfive/jh7110.dtsi
-+++ b/arch/riscv/boot/dts/starfive/jh7110.dtsi
-@@ -244,6 +244,7 @@
-               clock-output-names = "dvp_clk";
-               #clock-cells = <0>;
-       };
-+
-       gmac0_rgmii_rxin: gmac0-rgmii-rxin-clock {
-               compatible = "fixed-clock";
-               clock-output-names = "gmac0_rgmii_rxin";
-@@ -512,6 +513,43 @@
-                       status = "disabled";
-               };
-+              pwmdac: pwmdac@100b0000 {
-+                      compatible = "starfive,jh7110-pwmdac";
-+                      reg = <0x0 0x100b0000 0x0 0x1000>;
-+                      clocks = <&syscrg JH7110_SYSCLK_PWMDAC_APB>,
-+                               <&syscrg JH7110_SYSCLK_PWMDAC_CORE>;
-+                      clock-names = "apb", "core";
-+                      resets = <&syscrg JH7110_SYSRST_PWMDAC_APB>;
-+                      dmas = <&dma 22>;
-+                      dma-names = "tx";
-+                      #sound-dai-cells = <0>;
-+                      status = "disabled";
-+              };
-+
-+              i2srx: i2s@100e0000 {
-+                      compatible = "starfive,jh7110-i2srx";
-+                      reg = <0x0 0x100e0000 0x0 0x1000>;
-+                      clocks = <&syscrg JH7110_SYSCLK_I2SRX_BCLK_MST>,
-+                               <&syscrg JH7110_SYSCLK_I2SRX_APB>,
-+                               <&syscrg JH7110_SYSCLK_MCLK>,
-+                               <&syscrg JH7110_SYSCLK_MCLK_INNER>,
-+                               <&mclk_ext>,
-+                               <&syscrg JH7110_SYSCLK_I2SRX_BCLK>,
-+                               <&syscrg JH7110_SYSCLK_I2SRX_LRCK>,
-+                               <&i2srx_bclk_ext>,
-+                               <&i2srx_lrck_ext>;
-+                      clock-names = "i2sclk", "apb", "mclk",
-+                                    "mclk_inner", "mclk_ext", "bclk",
-+                                    "lrck", "bclk_ext", "lrck_ext";
-+                      resets = <&syscrg JH7110_SYSRST_I2SRX_APB>,
-+                               <&syscrg JH7110_SYSRST_I2SRX_BCLK>;
-+                      dmas = <0>, <&dma 24>;
-+                      dma-names = "tx", "rx";
-+                      starfive,syscon = <&sys_syscon 0x18 0x2>;
-+                      #sound-dai-cells = <0>;
-+                      status = "disabled";
-+              };
-+
-               usb0: usb@10100000 {
-                       compatible = "starfive,jh7110-usb";
-                       ranges = <0x0 0x0 0x10100000 0x100000>;
-@@ -736,6 +774,56 @@
-                       status = "disabled";
-               };
-+              i2stx0: i2s@120b0000 {
-+                      compatible = "starfive,jh7110-i2stx0";
-+                      reg = <0x0 0x120b0000 0x0 0x1000>;
-+                      clocks = <&syscrg JH7110_SYSCLK_I2STX0_BCLK_MST>,
-+                               <&syscrg JH7110_SYSCLK_I2STX0_APB>,
-+                               <&syscrg JH7110_SYSCLK_MCLK>,
-+                               <&syscrg JH7110_SYSCLK_MCLK_INNER>,
-+                               <&mclk_ext>;
-+                      clock-names = "i2sclk", "apb", "mclk",
-+                                    "mclk_inner","mclk_ext";
-+                      resets = <&syscrg JH7110_SYSRST_I2STX0_APB>,
-+                               <&syscrg JH7110_SYSRST_I2STX0_BCLK>;
-+                      dmas = <&dma 47>;
-+                      dma-names = "tx";
-+                      #sound-dai-cells = <0>;
-+                      status = "disabled";
-+              };
-+
-+              i2stx1: i2s@120c0000 {
-+                      compatible = "starfive,jh7110-i2stx1";
-+                      reg = <0x0 0x120c0000 0x0 0x1000>;
-+                      clocks = <&syscrg JH7110_SYSCLK_I2STX1_BCLK_MST>,
-+                               <&syscrg JH7110_SYSCLK_I2STX1_APB>,
-+                               <&syscrg JH7110_SYSCLK_MCLK>,
-+                               <&syscrg JH7110_SYSCLK_MCLK_INNER>,
-+                               <&mclk_ext>,
-+                               <&syscrg JH7110_SYSCLK_I2STX1_BCLK>,
-+                               <&syscrg JH7110_SYSCLK_I2STX1_LRCK>,
-+                               <&i2stx_bclk_ext>,
-+                               <&i2stx_lrck_ext>;
-+                      clock-names = "i2sclk", "apb", "mclk",
-+                                    "mclk_inner", "mclk_ext", "bclk",
-+                                    "lrck", "bclk_ext", "lrck_ext";
-+                      resets = <&syscrg JH7110_SYSRST_I2STX1_APB>,
-+                               <&syscrg JH7110_SYSRST_I2STX1_BCLK>;
-+                      dmas = <&dma 48>;
-+                      dma-names = "tx";
-+                      #sound-dai-cells = <0>;
-+                      status = "disabled";
-+              };
-+
-+              pwm: pwm@120d0000 {
-+                      compatible = "starfive,jh7110-pwm", "opencores,pwm-v1";
-+                      reg = <0x0 0x120d0000 0x0 0x10000>;
-+                      clocks = <&syscrg JH7110_SYSCLK_PWM_APB>;
-+                      resets = <&syscrg JH7110_SYSRST_PWM_APB>;
-+                      #pwm-cells = <3>;
-+                      status = "disabled";
-+              };
-+
-               sfctemp: temperature-sensor@120e0000 {
-                       compatible = "starfive,jh7110-temp";
-                       reg = <0x0 0x120e0000 0x0 0x10000>;
-@@ -811,6 +899,26 @@
-                       #gpio-cells = <2>;
-               };
-+              timer@13050000 {
-+                      compatible = "starfive,jh7110-timer";
-+                      reg = <0x0 0x13050000 0x0 0x10000>;
-+                      interrupts = <69>, <70>, <71>, <72>;
-+                      clocks = <&syscrg JH7110_SYSCLK_TIMER_APB>,
-+                               <&syscrg JH7110_SYSCLK_TIMER0>,
-+                               <&syscrg JH7110_SYSCLK_TIMER1>,
-+                               <&syscrg JH7110_SYSCLK_TIMER2>,
-+                               <&syscrg JH7110_SYSCLK_TIMER3>;
-+                      clock-names = "apb", "ch0", "ch1",
-+                                    "ch2", "ch3";
-+                      resets = <&syscrg JH7110_SYSRST_TIMER_APB>,
-+                               <&syscrg JH7110_SYSRST_TIMER0>,
-+                               <&syscrg JH7110_SYSRST_TIMER1>,
-+                               <&syscrg JH7110_SYSRST_TIMER2>,
-+                               <&syscrg JH7110_SYSRST_TIMER3>;
-+                      reset-names = "apb", "ch0", "ch1",
-+                                    "ch2", "ch3";
-+              };
-+
-               watchdog@13070000 {
-                       compatible = "starfive,jh7110-wdt";
-                       reg = <0x0 0x13070000 0x0 0x10000>;
-@@ -1011,6 +1119,32 @@
-                       #power-domain-cells = <1>;
-               };
-+              csi2rx: csi-bridge@19800000 {
-+                      compatible = "starfive,jh7110-csi2rx";
-+                      reg = <0x0 0x19800000 0x0 0x10000>;
-+                      clocks = <&ispcrg JH7110_ISPCLK_VIN_SYS>,
-+                               <&ispcrg JH7110_ISPCLK_VIN_APB>,
-+                               <&ispcrg JH7110_ISPCLK_VIN_PIXEL_IF0>,
-+                               <&ispcrg JH7110_ISPCLK_VIN_PIXEL_IF1>,
-+                               <&ispcrg JH7110_ISPCLK_VIN_PIXEL_IF2>,
-+                               <&ispcrg JH7110_ISPCLK_VIN_PIXEL_IF3>;
-+                      clock-names = "sys_clk", "p_clk",
-+                               "pixel_if0_clk", "pixel_if1_clk",
-+                               "pixel_if2_clk", "pixel_if3_clk";
-+                      resets = <&ispcrg JH7110_ISPRST_VIN_SYS>,
-+                               <&ispcrg JH7110_ISPRST_VIN_APB>,
-+                               <&ispcrg JH7110_ISPRST_VIN_PIXEL_IF0>,
-+                               <&ispcrg JH7110_ISPRST_VIN_PIXEL_IF1>,
-+                               <&ispcrg JH7110_ISPRST_VIN_PIXEL_IF2>,
-+                               <&ispcrg JH7110_ISPRST_VIN_PIXEL_IF3>;
-+                      reset-names = "sys", "reg_bank",
-+                               "pixel_if0", "pixel_if1",
-+                               "pixel_if2", "pixel_if3";
-+                      phys = <&csi_phy>;
-+                      phy-names = "dphy";
-+                      status = "disabled";
-+              };
-+
-               ispcrg: clock-controller@19810000 {
-                       compatible = "starfive,jh7110-ispcrg";
-                       reg = <0x0 0x19810000 0x0 0x10000>;
-@@ -1028,6 +1162,19 @@
-                       power-domains = <&pwrc JH7110_PD_ISP>;
-               };
-+              csi_phy: phy@19820000 {
-+                      compatible = "starfive,jh7110-dphy-rx";
-+                      reg = <0x0 0x19820000 0x0 0x10000>;
-+                      clocks = <&ispcrg JH7110_ISPCLK_M31DPHY_CFG_IN>,
-+                               <&ispcrg JH7110_ISPCLK_M31DPHY_REF_IN>,
-+                               <&ispcrg JH7110_ISPCLK_M31DPHY_TX_ESC_LAN0>;
-+                      clock-names = "cfg", "ref", "tx";
-+                      resets = <&ispcrg JH7110_ISPRST_M31DPHY_HW>,
-+                               <&ispcrg JH7110_ISPRST_M31DPHY_B09_AON>;
-+                      power-domains = <&aon_syscon JH7110_AON_PD_DPHY_RX>;
-+                      #phy-cells = <0>;
-+              };
-+
-               voutcrg: clock-controller@295c0000 {
-                       compatible = "starfive,jh7110-voutcrg";
-                       reg = <0x0 0x295c0000 0x0 0x10000>;
-@@ -1045,5 +1192,91 @@
-                       #reset-cells = <1>;
-                       power-domains = <&pwrc JH7110_PD_VOUT>;
-               };
-+
-+              pcie0: pcie@940000000 {
-+                      compatible = "starfive,jh7110-pcie";
-+                      reg = <0x9 0x40000000 0x0 0x1000000>,
-+                            <0x0 0x2b000000 0x0 0x100000>;
-+                      reg-names = "cfg", "apb";
-+                      linux,pci-domain = <0>;
-+                      #address-cells = <3>;
-+                      #size-cells = <2>;
-+                      #interrupt-cells = <1>;
-+                      ranges = <0x82000000  0x0 0x30000000  0x0 0x30000000 0x0 0x08000000>,
-+                               <0xc3000000  0x9 0x00000000  0x9 0x00000000 0x0 0x40000000>;
-+                      interrupts = <56>;
-+                      interrupt-map-mask = <0x0 0x0 0x0 0x7>;
-+                      interrupt-map = <0x0 0x0 0x0 0x1 &pcie_intc0 0x1>,
-+                                      <0x0 0x0 0x0 0x2 &pcie_intc0 0x2>,
-+                                      <0x0 0x0 0x0 0x3 &pcie_intc0 0x3>,
-+                                      <0x0 0x0 0x0 0x4 &pcie_intc0 0x4>;
-+                      msi-controller;
-+                      device_type = "pci";
-+                      starfive,stg-syscon = <&stg_syscon>;
-+                      bus-range = <0x0 0xff>;
-+                      clocks = <&syscrg JH7110_SYSCLK_NOC_BUS_STG_AXI>,
-+                               <&stgcrg JH7110_STGCLK_PCIE0_TL>,
-+                               <&stgcrg JH7110_STGCLK_PCIE0_AXI_MST0>,
-+                               <&stgcrg JH7110_STGCLK_PCIE0_APB>;
-+                      clock-names = "noc", "tl", "axi_mst0", "apb";
-+                      resets = <&stgcrg JH7110_STGRST_PCIE0_AXI_MST0>,
-+                               <&stgcrg JH7110_STGRST_PCIE0_AXI_SLV0>,
-+                               <&stgcrg JH7110_STGRST_PCIE0_AXI_SLV>,
-+                               <&stgcrg JH7110_STGRST_PCIE0_BRG>,
-+                               <&stgcrg JH7110_STGRST_PCIE0_CORE>,
-+                               <&stgcrg JH7110_STGRST_PCIE0_APB>;
-+                      reset-names = "mst0", "slv0", "slv", "brg",
-+                                    "core", "apb";
-+                      status = "disabled";
-+
-+                      pcie_intc0: interrupt-controller {
-+                              #address-cells = <0>;
-+                              #interrupt-cells = <1>;
-+                              interrupt-controller;
-+                      };
-+              };
-+
-+              pcie1: pcie@9c0000000 {
-+                      compatible = "starfive,jh7110-pcie";
-+                      reg = <0x9 0xc0000000 0x0 0x1000000>,
-+                            <0x0 0x2c000000 0x0 0x100000>;
-+                      reg-names = "cfg", "apb";
-+                      linux,pci-domain = <1>;
-+                      #address-cells = <3>;
-+                      #size-cells = <2>;
-+                      #interrupt-cells = <1>;
-+                      ranges = <0x82000000  0x0 0x38000000  0x0 0x38000000 0x0 0x08000000>,
-+                               <0xc3000000  0x9 0x80000000  0x9 0x80000000 0x0 0x40000000>;
-+                      interrupts = <57>;
-+                      interrupt-map-mask = <0x0 0x0 0x0 0x7>;
-+                      interrupt-map = <0x0 0x0 0x0 0x1 &pcie_intc1 0x1>,
-+                                      <0x0 0x0 0x0 0x2 &pcie_intc1 0x2>,
-+                                      <0x0 0x0 0x0 0x3 &pcie_intc1 0x3>,
-+                                      <0x0 0x0 0x0 0x4 &pcie_intc1 0x4>;
-+                      msi-controller;
-+                      device_type = "pci";
-+                      starfive,stg-syscon = <&stg_syscon>;
-+                      bus-range = <0x0 0xff>;
-+                      clocks = <&syscrg JH7110_SYSCLK_NOC_BUS_STG_AXI>,
-+                               <&stgcrg JH7110_STGCLK_PCIE1_TL>,
-+                               <&stgcrg JH7110_STGCLK_PCIE1_AXI_MST0>,
-+                               <&stgcrg JH7110_STGCLK_PCIE1_APB>;
-+                      clock-names = "noc", "tl", "axi_mst0", "apb";
-+                      resets = <&stgcrg JH7110_STGRST_PCIE1_AXI_MST0>,
-+                               <&stgcrg JH7110_STGRST_PCIE1_AXI_SLV0>,
-+                               <&stgcrg JH7110_STGRST_PCIE1_AXI_SLV>,
-+                               <&stgcrg JH7110_STGRST_PCIE1_BRG>,
-+                               <&stgcrg JH7110_STGRST_PCIE1_CORE>,
-+                               <&stgcrg JH7110_STGRST_PCIE1_APB>;
-+                      reset-names = "mst0", "slv0", "slv", "brg",
-+                                    "core", "apb";
-+                      status = "disabled";
-+
-+                      pcie_intc1: interrupt-controller {
-+                              #address-cells = <0>;
-+                              #interrupt-cells = <1>;
-+                              interrupt-controller;
-+                      };
-+              };
-       };
- };
diff --git a/target/linux/starfive/patches-6.6/0049-MAINTAINERS-Update-all-StarFive-entries.patch b/target/linux/starfive/patches-6.6/0049-MAINTAINERS-Update-all-StarFive-entries.patch
deleted file mode 100644 (file)
index 5f2c949..0000000
+++ /dev/null
@@ -1,147 +0,0 @@
-From ae7b57a0c69953f5ec06a378aedeed4c86637998 Mon Sep 17 00:00:00 2001
-From: Hal Feng <hal.feng@starfivetech.com>
-Date: Tue, 11 Apr 2023 16:25:57 +0800
-Subject: [PATCH 049/116] MAINTAINERS: Update all StarFive entries
-
-Merge all StarFive maintainers changes together.
-
-Signed-off-by: Hal Feng <hal.feng@starfivetech.com>
----
- MAINTAINERS | 61 +++++++++++++++++++++++++++++++++++++++++++++++++----
- 1 file changed, 57 insertions(+), 4 deletions(-)
-
---- a/MAINTAINERS
-+++ b/MAINTAINERS
-@@ -7054,6 +7054,14 @@ T:      git git://anongit.freedesktop.org/drm
- F:    Documentation/devicetree/bindings/display/rockchip/
- F:    drivers/gpu/drm/rockchip/
-+DRM DRIVERS FOR STARFIVE
-+M:    Keith Zhao <keith.zhao@starfivetech.com>
-+L:    dri-devel@lists.freedesktop.org
-+S:    Maintained
-+T:    git git://anongit.freedesktop.org/drm/drm-misc
-+F:    Documentation/devicetree/bindings/display/starfive/
-+F:    drivers/gpu/drm/verisilicon/
-+
- DRM DRIVERS FOR STI
- M:    Alain Volmat <alain.volmat@foss.st.com>
- L:    dri-devel@lists.freedesktop.org
-@@ -16018,6 +16026,13 @@ F:    Documentation/i2c/busses/i2c-ocores.r
- F:    drivers/i2c/busses/i2c-ocores.c
- F:    include/linux/platform_data/i2c-ocores.h
-+OPENCORES PWM DRIVER
-+M:    William Qiu <william.qiu@starfivetech.com>
-+M:    Hal Feng <hal.feng@starfivetech.com>
-+S:    Supported
-+F:    Documentation/devicetree/bindings/pwm/opencores,pwm.yaml
-+F:    drivers/pwm/pwm-ocores.c
-+
- OPENRISC ARCHITECTURE
- M:    Jonas Bonn <jonas@southpole.se>
- M:    Stefan Kristiansson <stefan.kristiansson@saunalahti.fi>
-@@ -16429,6 +16444,14 @@ S:    Maintained
- F:    Documentation/devicetree/bindings/pci/layerscape-pcie-gen4.txt
- F:    drivers/pci/controller/mobiveil/pcie-layerscape-gen4.c
-+PCI DRIVER FOR PLDA PCIE IP
-+M:    Daire McNamara <daire.mcnamara@microchip.com>
-+M:    Kevin Xie <kevin.xie@starfivetech.com>
-+L:    linux-pci@vger.kernel.org
-+S:    Maintained
-+F:    Documentation/devicetree/bindings/pci/plda,*
-+F:    drivers/pci/controller/plda/*plda*
-+
- PCI DRIVER FOR RENESAS R-CAR
- M:    Marek Vasut <marek.vasut+renesas@gmail.com>
- M:    Yoshihiro Shimoda <yoshihiro.shimoda.uh@renesas.com>
-@@ -16660,7 +16683,7 @@ M:     Daire McNamara <daire.mcnamara@microc
- L:    linux-pci@vger.kernel.org
- S:    Supported
- F:    Documentation/devicetree/bindings/pci/microchip*
--F:    drivers/pci/controller/*microchip*
-+F:    drivers/pci/controller/plda/*microchip*
- PCIE DRIVER FOR QUALCOMM MSM
- M:    Manivannan Sadhasivam <manivannan.sadhasivam@linaro.org>
-@@ -16684,6 +16707,13 @@ S:    Maintained
- F:    Documentation/devicetree/bindings/pci/socionext,uniphier-pcie*
- F:    drivers/pci/controller/dwc/pcie-uniphier*
-+PCIE DRIVER FOR STARFIVE JH71x0
-+M:    Kevin Xie <kevin.xie@starfivetech.com>
-+L:    linux-pci@vger.kernel.org
-+S:    Maintained
-+F:    Documentation/devicetree/bindings/pci/starfive*
-+F:    drivers/pci/controller/plda/pcie-starfive.c
-+
- PCIE DRIVER FOR ST SPEAR13XX
- M:    Pratyush Anand <pratyush.anand@gmail.com>
- L:    linux-pci@vger.kernel.org
-@@ -18456,7 +18486,7 @@ F:     drivers/char/hw_random/mpfs-rng.c
- F:    drivers/clk/microchip/clk-mpfs*.c
- F:    drivers/i2c/busses/i2c-microchip-corei2c.c
- F:    drivers/mailbox/mailbox-mpfs.c
--F:    drivers/pci/controller/pcie-microchip-host.c
-+F:    drivers/pci/controller/plda/pcie-microchip-host.c
- F:    drivers/pwm/pwm-microchip-core.c
- F:    drivers/reset/reset-mpfs.c
- F:    drivers/rtc/rtc-mpfs.c
-@@ -20437,6 +20467,15 @@ M:    Ion Badulescu <ionut@badula.org>
- S:    Odd Fixes
- F:    drivers/net/ethernet/adaptec/starfire*
-+STARFIVE CAMERA SUBSYSTEM DRIVER
-+M:    Jack Zhu <jack.zhu@starfivetech.com>
-+M:    Changhuang Liang <changhuang.liang@starfivetech.com>
-+L:    linux-media@vger.kernel.org
-+S:    Maintained
-+F:    Documentation/admin-guide/media/starfive_camss.rst
-+F:    Documentation/devicetree/bindings/media/starfive,jh7110-camss.yaml
-+F:    drivers/staging/media/starfive/camss
-+
- STARFIVE CRYPTO DRIVER
- M:    Jia Jie Ho <jiajie.ho@starfivetech.com>
- M:    William Qiu <william.qiu@starfivetech.com>
-@@ -20475,6 +20514,13 @@ S:    Supported
- F:    Documentation/devicetree/bindings/clock/starfive,jh7110-pll.yaml
- F:    drivers/clk/starfive/clk-starfive-jh7110-pll.c
-+STARFIVE JH7110 PWMDAC DRIVER
-+M:    Hal Feng <hal.feng@starfivetech.com>
-+M:    Xingyu Wu <xingyu.wu@starfivetech.com>
-+S:    Supported
-+F:    Documentation/devicetree/bindings/sound/starfive,jh7110-pwmdac.yaml
-+F:    sound/soc/starfive/jh7110_pwmdac.c
-+
- STARFIVE JH7110 SYSCON
- M:    William Qiu <william.qiu@starfivetech.com>
- M:    Xingyu Wu <xingyu.wu@starfivetech.com>
-@@ -20522,9 +20568,10 @@ F:    drivers/usb/cdns3/cdns3-starfive.c
- STARFIVE JH71XX PMU CONTROLLER DRIVER
- M:    Walker Chen <walker.chen@starfivetech.com>
-+M:    Changhuang Liang <changhuang.liang@starfivetech.com>
- S:    Supported
- F:    Documentation/devicetree/bindings/power/starfive*
--F:    drivers/pmdomain/starfive/jh71xx-pmu.c
-+F:    drivers/pmdomain/starfive/
- F:    include/dt-bindings/power/starfive,jh7110-pmu.h
- STARFIVE SOC DRIVERS
-@@ -20532,7 +20579,13 @@ M:    Conor Dooley <conor@kernel.org>
- 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/
-+
-+STARFIVE JH7110 TIMER DRIVER
-+M:    Samin Guo <samin.guo@starfivetech.com>
-+M:    Xingyu Wu <xingyu.wu@starfivetech.com>
-+S:    Supported
-+F:    Documentation/devicetree/bindings/timer/starfive,jh7110-timer.yaml
-+F:    drivers/clocksource/timer-jh7110.c
- STARFIVE TRNG DRIVER
- M:    Jia Jie Ho <jiajie.ho@starfivetech.com>
diff --git a/target/linux/starfive/patches-6.6/0050-mmc-starfive-Change-the-voltage-to-adapt-to-JH7110-E.patch b/target/linux/starfive/patches-6.6/0050-mmc-starfive-Change-the-voltage-to-adapt-to-JH7110-E.patch
deleted file mode 100644 (file)
index a38a885..0000000
+++ /dev/null
@@ -1,64 +0,0 @@
-From e394195396995456ef98f52ac123c0cb64687748 Mon Sep 17 00:00:00 2001
-From: William Qiu <william.qiu@starfivetech.com>
-Date: Mon, 9 Oct 2023 10:59:03 +0800
-Subject: [PATCH 050/116] mmc: starfive: Change the voltage to adapt to JH7110
- EVB
-
-Change the voltage, so the driver can adapt to JH7110 EVB.
-
-Signed-off-by: William Qiu <william.qiu@starfivetech.com>
-Signed-off-by: Hal Feng <hal.feng@starfivetech.com>
----
- drivers/mmc/host/dw_mmc-starfive.c | 30 ++++++++++++++++++++++++++++++
- 1 file changed, 30 insertions(+)
-
---- a/drivers/mmc/host/dw_mmc-starfive.c
-+++ b/drivers/mmc/host/dw_mmc-starfive.c
-@@ -8,6 +8,7 @@
- #include <linux/bitfield.h>
- #include <linux/clk.h>
- #include <linux/delay.h>
-+#include <linux/gpio.h>
- #include <linux/mfd/syscon.h>
- #include <linux/mmc/host.h>
- #include <linux/module.h>
-@@ -95,10 +96,39 @@ out:
-       return ret;
- }
-+static int dw_mci_starfive_switch_voltage(struct mmc_host *mmc, struct mmc_ios *ios)
-+{
-+
-+      struct dw_mci_slot *slot = mmc_priv(mmc);
-+      struct dw_mci *host = slot->host;
-+      u32 ret;
-+
-+      if (ios->signal_voltage == MMC_SIGNAL_VOLTAGE_330)
-+              ret = gpio_direction_output(25, 0);
-+      else if (ios->signal_voltage == MMC_SIGNAL_VOLTAGE_180)
-+              ret = gpio_direction_output(25, 1);
-+      if (ret)
-+              return ret;
-+
-+      if (!IS_ERR(mmc->supply.vqmmc)) {
-+              ret = mmc_regulator_set_vqmmc(mmc, ios);
-+              if (ret < 0) {
-+                      dev_err(host->dev, "Regulator set error %d\n", ret);
-+                      return ret;
-+              }
-+      }
-+
-+      /* We should delay 20ms wait for timing setting finished. */
-+      mdelay(20);
-+
-+      return 0;
-+}
-+
- static const struct dw_mci_drv_data starfive_data = {
-       .common_caps            = MMC_CAP_CMD23,
-       .set_ios                = dw_mci_starfive_set_ios,
-       .execute_tuning         = dw_mci_starfive_execute_tuning,
-+      .switch_voltage         = dw_mci_starfive_switch_voltage,
- };
- static const struct of_device_id dw_mci_starfive_match[] = {
diff --git a/target/linux/starfive/patches-6.6/0051-spi-spl022-Get-and-deassert-reset-in-probe.patch b/target/linux/starfive/patches-6.6/0051-spi-spl022-Get-and-deassert-reset-in-probe.patch
deleted file mode 100644 (file)
index 485ab0d..0000000
+++ /dev/null
@@ -1,60 +0,0 @@
-From 2cd3e51cb76d49d8db6274ebdc1ba1eb5c872f10 Mon Sep 17 00:00:00 2001
-From: "ziv.xu" <ziv.xu@starfivetech.com>
-Date: Sun, 4 Feb 2024 10:35:24 +0800
-Subject: [PATCH 051/116] spi: spl022: Get and deassert reset in probe()
-
-This fix spi1~6 communication time out.
-
-Signed-off-by: ziv.xu <ziv.xu@starfivetech.com>
-Signed-off-by: Hal Feng <hal.feng@starfivetech.com>
----
- drivers/spi/spi-pl022.c | 17 +++++++++++++++++
- 1 file changed, 17 insertions(+)
-
---- a/drivers/spi/spi-pl022.c
-+++ b/drivers/spi/spi-pl022.c
-@@ -33,6 +33,7 @@
- #include <linux/pm_runtime.h>
- #include <linux/of.h>
- #include <linux/pinctrl/consumer.h>
-+#include <linux/reset.h>
- /*
-  * This macro is used to define some register default values.
-@@ -370,6 +371,7 @@ struct pl022 {
-       resource_size_t                 phybase;
-       void __iomem                    *virtbase;
-       struct clk                      *clk;
-+      struct reset_control            *rst;
-       struct spi_controller           *host;
-       struct pl022_ssp_controller     *host_info;
-       /* Message per-transfer pump */
-@@ -2181,6 +2183,19 @@ static int pl022_probe(struct amba_devic
-               goto err_no_clk_en;
-       }
-+      pl022->rst = devm_reset_control_get(&adev->dev, NULL);
-+      if (IS_ERR(pl022->rst)) {
-+              status = PTR_ERR(pl022->rst);
-+              dev_err(&adev->dev, "could not retrieve SSP/SPI bus reset\n");
-+              goto err_no_rst;
-+      }
-+
-+      status = reset_control_deassert(pl022->rst);
-+      if (status) {
-+              dev_err(&adev->dev, "could not deassert SSP/SPI bus reset\n");
-+              goto err_no_rst_de;
-+      }
-+
-       /* Initialize transfer pump */
-       tasklet_init(&pl022->pump_transfers, pump_transfers,
-                    (unsigned long)pl022);
-@@ -2240,6 +2255,8 @@ static int pl022_probe(struct amba_devic
-       if (platform_info->enable_dma)
-               pl022_dma_remove(pl022);
-  err_no_irq:
-+ err_no_rst_de:
-+ err_no_rst:
-       clk_disable_unprepare(pl022->clk);
-  err_no_clk_en:
-  err_no_clk:
diff --git a/target/linux/starfive/patches-6.6/0052-ASoC-dwc-i2s-Fix-getting-platform-data-error-for-Sta.patch b/target/linux/starfive/patches-6.6/0052-ASoC-dwc-i2s-Fix-getting-platform-data-error-for-Sta.patch
deleted file mode 100644 (file)
index 65ca992..0000000
+++ /dev/null
@@ -1,30 +0,0 @@
-From 9cc8de0cdc1600f460f618e342e1f524adad07c4 Mon Sep 17 00:00:00 2001
-From: Xingyu Wu <xingyu.wu@starfivetech.com>
-Date: Wed, 21 Feb 2024 10:23:48 +0800
-Subject: [PATCH 052/116] ASoC: dwc: i2s: Fix getting platform data error for
- StarFive JH7110
-
-JH7110 need to use a DT specific function to get the platform data,
-otherwise, it fails in probe().
-
-Fixes: 9c97790a07dc ("ASoC: dwc: Fix non-DT instantiation")
-Signed-off-by: Xingyu Wu <xingyu.wu@starfivetech.com>
-Signed-off-by: Hal Feng <hal.feng@starfivetech.com>
----
- sound/soc/dwc/dwc-i2s.c | 4 ++++
- 1 file changed, 4 insertions(+)
-
---- a/sound/soc/dwc/dwc-i2s.c
-+++ b/sound/soc/dwc/dwc-i2s.c
-@@ -916,7 +916,11 @@ static int jh7110_i2stx0_clk_cfg(struct
- static int dw_i2s_probe(struct platform_device *pdev)
- {
-+#ifdef CONFIG_OF
-+      const struct i2s_platform_data *pdata = of_device_get_match_data(&pdev->dev);
-+#else
-       const struct i2s_platform_data *pdata = pdev->dev.platform_data;
-+#endif
-       struct dw_i2s_dev *dev;
-       struct resource *res;
-       int ret, irq;
diff --git a/target/linux/starfive/patches-6.6/0053-ASoC-dwc-i2s-Add-RX-master-support-for-StarFive-JH71.patch b/target/linux/starfive/patches-6.6/0053-ASoC-dwc-i2s-Add-RX-master-support-for-StarFive-JH71.patch
deleted file mode 100644 (file)
index 48d47dc..0000000
+++ /dev/null
@@ -1,67 +0,0 @@
-From 1be9bd37fdb5f50162dba0158e1fee295ebca9aa Mon Sep 17 00:00:00 2001
-From: Xingyu Wu <xingyu.wu@starfivetech.com>
-Date: Tue, 17 Oct 2023 17:22:52 +0800
-Subject: [PATCH 053/116] ASoC: dwc: i2s: Add RX master support for StarFive
- JH7110 SoC
-
-Add JH7110 I2S RX master support, so the PDM can work on JH7110
-EVB board.
-
-Signed-off-by: Xingyu Wu <xingyu.wu@starfivetech.com>
-Signed-off-by: Hal Feng <hal.feng@starfivetech.com>
----
- sound/soc/dwc/dwc-i2s.c | 31 +++++++++++++++++++++++++++++++
- 1 file changed, 31 insertions(+)
-
---- a/sound/soc/dwc/dwc-i2s.c
-+++ b/sound/soc/dwc/dwc-i2s.c
-@@ -905,6 +905,27 @@ static int jh7110_i2srx_crg_init(struct
-       return jh7110_i2s_crg_slave_init(dev);
- }
-+/* Special syscon initialization about RX channel with master mode on JH7110 SoC */
-+static int jh7110_i2srx_mst_crg_init(struct dw_i2s_dev *dev)
-+{
-+      struct regmap *regmap;
-+      unsigned int args[5];
-+
-+      regmap = syscon_regmap_lookup_by_phandle_args(dev->dev->of_node,
-+                                                    "starfive,syscon",
-+                                                    5, args);
-+      if (IS_ERR(regmap))
-+              return dev_err_probe(dev->dev, PTR_ERR(regmap), "getting the regmap failed\n");
-+
-+      /* Enable I2Srx with syscon register, args[0]: offset, args[1]: mask */
-+      regmap_update_bits(regmap, args[0], args[1], args[1]);
-+
-+      /* Change I2Srx source (PDM) with syscon register, args[0]: offset, args[1]: mask */
-+      regmap_update_bits(regmap, args[2], args[3], args[4]);
-+
-+      return jh7110_i2s_crg_master_init(dev);
-+}
-+
- static int jh7110_i2stx0_clk_cfg(struct i2s_clk_config_data *config)
- {
-       struct dw_i2s_dev *dev = container_of(config, struct dw_i2s_dev, config);
-@@ -1085,11 +1106,21 @@ static const struct i2s_platform_data jh
-       .i2s_pd_init = jh7110_i2srx_crg_init,
- };
-+static const struct i2s_platform_data jh7110_i2srx_mst_data = {
-+      .cap = DWC_I2S_RECORD | DW_I2S_MASTER,
-+      .channel = TWO_CHANNEL_SUPPORT,
-+      .snd_fmts = SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S32_LE,
-+      .snd_rates = SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_11025 | SNDRV_PCM_RATE_16000,
-+      .i2s_clk_cfg = jh7110_i2stx0_clk_cfg,
-+      .i2s_pd_init = jh7110_i2srx_mst_crg_init,
-+};
-+
- static const struct of_device_id dw_i2s_of_match[] = {
-       { .compatible = "snps,designware-i2s",   },
-       { .compatible = "starfive,jh7110-i2stx0", .data = &jh7110_i2stx0_data, },
-       { .compatible = "starfive,jh7110-i2stx1", .data = &jh7110_i2stx1_data,},
-       { .compatible = "starfive,jh7110-i2srx", .data = &jh7110_i2srx_data,},
-+      { .compatible = "starfive,jh7110-i2srx-master", .data = &jh7110_i2srx_mst_data,},
-       {},
- };
diff --git a/target/linux/starfive/patches-6.6/0054-pinctrl-starfive-jh7110-Unset-.strict-in-pinmux_ops.patch b/target/linux/starfive/patches-6.6/0054-pinctrl-starfive-jh7110-Unset-.strict-in-pinmux_ops.patch
deleted file mode 100644 (file)
index 51976c6..0000000
+++ /dev/null
@@ -1,24 +0,0 @@
-From 1ec26ba377d8ae59cd09811ec78623a750a9c150 Mon Sep 17 00:00:00 2001
-From: Hal Feng <hal.feng@starfivetech.com>
-Date: Mon, 26 Feb 2024 11:35:44 +0800
-Subject: [PATCH 054/116] pinctrl: starfive: jh7110: Unset .strict in
- pinmux_ops
-
-Allow simultaneous use of the same pin for GPIO and another function.
-This feature is used in HDMI hot plug detect.
-
-Signed-off-by: Hal Feng <hal.feng@starfivetech.com>
----
- drivers/pinctrl/starfive/pinctrl-starfive-jh7110.c | 1 -
- 1 file changed, 1 deletion(-)
-
---- a/drivers/pinctrl/starfive/pinctrl-starfive-jh7110.c
-+++ b/drivers/pinctrl/starfive/pinctrl-starfive-jh7110.c
-@@ -327,7 +327,6 @@ static const struct pinmux_ops jh7110_pi
-       .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 };
diff --git a/target/linux/starfive/patches-6.6/0055-mm-pgtable-generic.c-Export-symbol-__pte_offset_map.patch b/target/linux/starfive/patches-6.6/0055-mm-pgtable-generic.c-Export-symbol-__pte_offset_map.patch
deleted file mode 100644 (file)
index 39699e8..0000000
+++ /dev/null
@@ -1,22 +0,0 @@
-From 005549a2bd839335b0e3dc4152f00f642b524f07 Mon Sep 17 00:00:00 2001
-From: Hal Feng <hal.feng@starfivetech.com>
-Date: Sat, 7 Oct 2023 18:10:20 +0800
-Subject: [PATCH 055/116] mm/pgtable-generic.c: Export symbol __pte_offset_map
-
-So JH7110 vdec can call pte_offset_map() when it is built as a module.
-
-Signed-off-by: Hal Feng <hal.feng@starfivetech.com>
----
- mm/pgtable-generic.c | 1 +
- 1 file changed, 1 insertion(+)
-
---- a/mm/pgtable-generic.c
-+++ b/mm/pgtable-generic.c
-@@ -304,6 +304,7 @@ nomap:
-       rcu_read_unlock();
-       return NULL;
- }
-+EXPORT_SYMBOL(__pte_offset_map);
- pte_t *pte_offset_map_nolock(struct mm_struct *mm, pmd_t *pmd,
-                            unsigned long addr, spinlock_t **ptlp)
diff --git a/target/linux/starfive/patches-6.6/0056-riscv-dts-starfive-Add-JH7110-EVB-device-tree.patch b/target/linux/starfive/patches-6.6/0056-riscv-dts-starfive-Add-JH7110-EVB-device-tree.patch
deleted file mode 100644 (file)
index 7b803d3..0000000
+++ /dev/null
@@ -1,2623 +0,0 @@
-From 9f46b0d43f8945ff3a8b81ddc6567df370b60911 Mon Sep 17 00:00:00 2001
-From: Hal Feng <hal.feng@starfivetech.com>
-Date: Fri, 28 Jul 2023 17:19:12 +0800
-Subject: [PATCH 056/116] riscv: dts: starfive: Add JH7110 EVB device tree
-
-Add JH7110 evaluation board device tree.
-The code is ported from tag JH7110_SDK_6.1_v5.11.3
-
-Signed-off-by: Hal Feng <hal.feng@starfivetech.com>
----
- arch/riscv/boot/dts/starfive/Makefile         |   3 +
- arch/riscv/boot/dts/starfive/jh7110-clk.dtsi  |  80 ++
- .../boot/dts/starfive/jh7110-evb-pinctrl.dtsi | 997 ++++++++++++++++++
- arch/riscv/boot/dts/starfive/jh7110-evb.dts   |  35 +
- arch/riscv/boot/dts/starfive/jh7110-evb.dtsi  | 854 +++++++++++++++
- arch/riscv/boot/dts/starfive/jh7110.dtsi      | 482 ++++++++-
- 6 files changed, 2444 insertions(+), 7 deletions(-)
- create mode 100644 arch/riscv/boot/dts/starfive/jh7110-clk.dtsi
- create mode 100644 arch/riscv/boot/dts/starfive/jh7110-evb-pinctrl.dtsi
- create mode 100644 arch/riscv/boot/dts/starfive/jh7110-evb.dts
- create mode 100644 arch/riscv/boot/dts/starfive/jh7110-evb.dtsi
-
---- a/arch/riscv/boot/dts/starfive/Makefile
-+++ b/arch/riscv/boot/dts/starfive/Makefile
-@@ -4,9 +4,12 @@ DTC_FLAGS_jh7100-beaglev-starlight := -@
- DTC_FLAGS_jh7100-starfive-visionfive-v1 := -@
- DTC_FLAGS_jh7110-starfive-visionfive-2-v1.2a := -@
- DTC_FLAGS_jh7110-starfive-visionfive-2-v1.3b := -@
-+DTC_FLAGS_jh7110-evb := -@
- 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
-+
-+dtb-$(CONFIG_ARCH_STARFIVE) += jh7110-evb.dtb
---- /dev/null
-+++ b/arch/riscv/boot/dts/starfive/jh7110-clk.dtsi
-@@ -0,0 +1,80 @@
-+// SPDX-License-Identifier: GPL-2.0 OR MIT
-+/*
-+ * Copyright (C) 2023 StarFive Technology Co., Ltd.
-+ */
-+
-+/ {
-+      ac108_mclk: ac108_mclk {
-+              compatible = "fixed-clock";
-+              #clock-cells = <0>;
-+              clock-frequency = <24000000>;
-+      };
-+
-+      clk_ext_camera: clk-ext-camera {
-+              compatible = "fixed-clock";
-+              #clock-cells = <0>;
-+              clock-frequency = <24000000>;
-+      };
-+
-+      wm8960_mclk: wm8960_mclk {
-+              compatible = "fixed-clock";
-+              #clock-cells = <0>;
-+              clock-frequency = <24576000>;
-+      };
-+};
-+
-+&dvp_clk {
-+      clock-frequency = <74250000>;
-+};
-+
-+&gmac0_rgmii_rxin {
-+      clock-frequency = <125000000>;
-+};
-+
-+&gmac0_rmii_refin {
-+      clock-frequency = <50000000>;
-+};
-+
-+&gmac1_rgmii_rxin {
-+      clock-frequency = <125000000>;
-+};
-+
-+&gmac1_rmii_refin {
-+      clock-frequency = <50000000>;
-+};
-+
-+&hdmitx0_pixelclk {
-+      clock-frequency = <297000000>;
-+};
-+
-+&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>;
-+};
---- /dev/null
-+++ b/arch/riscv/boot/dts/starfive/jh7110-evb-pinctrl.dtsi
-@@ -0,0 +1,997 @@
-+// SPDX-License-Identifier: GPL-2.0 OR MIT
-+/*
-+ * Copyright (C) 2023 StarFive Technology Co., Ltd.
-+ * Author: Hal Feng <hal.feng@starfivetech.com>
-+ */
-+
-+#include "jh7110-pinfunc.h"
-+
-+&sysgpio {
-+      can0_pins: can0-0 {
-+              can-pins {
-+                      pinmux = <GPIOMUX(30, GPOUT_SYS_CAN0_TXD,
-+                                            GPOEN_ENABLE,
-+                                            GPI_NONE)>,
-+                               <GPIOMUX(31, GPOUT_LOW,
-+                                            GPOEN_DISABLE,
-+                                            GPI_SYS_CAN0_RXD)>,
-+                               <GPIOMUX(32, GPOUT_SYS_CAN0_STBY,
-+                                            GPOEN_ENABLE,
-+                                            GPI_NONE)>;
-+                      input-enable;
-+              };
-+      };
-+
-+      can1_pins: can1-0 {
-+              can-pins {
-+                      pinmux = <GPIOMUX(29, GPOUT_SYS_CAN1_TXD,
-+                                            GPOEN_ENABLE,
-+                                            GPI_NONE)>,
-+                               <GPIOMUX(27, GPOUT_LOW,
-+                                            GPOEN_DISABLE,
-+                                            GPI_SYS_CAN1_RXD)>,
-+                               <GPIOMUX(45, GPOUT_SYS_CAN1_STBY,
-+                                            GPOEN_ENABLE,
-+                                            GPI_NONE)>;
-+                      drive-strength = <12>;
-+                      input-enable;
-+              };
-+      };
-+
-+      dvp_pins: dvp-0 {
-+              dvp-pins{
-+                      pinmux = <PINMUX(21, 2)>,
-+                               <PINMUX(22, 2)>,
-+                               <PINMUX(23, 2)>,
-+                               <PINMUX(24, 2)>,
-+                               <PINMUX(25, 2)>,
-+                               <PINMUX(26, 2)>,
-+                               <PINMUX(27, 2)>,
-+                               <PINMUX(28, 2)>,
-+                               <PINMUX(29, 2)>,
-+                               <PINMUX(30, 2)>,
-+                               <PINMUX(31, 2)>,
-+                               <PINMUX(32, 2)>,
-+                               <PINMUX(33, 2)>,
-+                               <PINMUX(34, 2)>,
-+                               <PINMUX(35, 2)>;
-+                      input-enable;
-+              };
-+      };
-+
-+      emmc0_pins: emmc0-0 {
-+              emmc-pins {
-+                      pinmux = <GPIOMUX(22, GPOUT_SYS_SDIO0_RST,
-+                                            GPOEN_ENABLE,
-+                                            GPI_NONE)>,
-+                               <PINMUX(64, 0)>,
-+                               <PINMUX(65, 0)>,
-+                               <PINMUX(66, 0)>,
-+                               <PINMUX(67, 0)>,
-+                               <PINMUX(68, 0)>,
-+                               <PINMUX(69, 0)>,
-+                               <PINMUX(70, 0)>,
-+                               <PINMUX(71, 0)>,
-+                               <PINMUX(72, 0)>,
-+                               <PINMUX(73, 0)>;
-+                      bias-pull-up;
-+                      drive-strength = <12>;
-+                      input-enable;
-+                      slew-rate = <1>;
-+              };
-+      };
-+
-+      emmc1_pins: emmc1-0 {
-+              emmc-pins {
-+                      pinmux = <GPIOMUX(51, GPOUT_SYS_SDIO1_RST,
-+                                            GPOEN_ENABLE,
-+                                            GPI_NONE)>,
-+                               <GPIOMUX(38, GPOUT_SYS_SDIO1_CLK,
-+                                            GPOEN_ENABLE,
-+                                            GPI_NONE)>,
-+                               <GPIOMUX(36, GPOUT_SYS_SDIO1_CMD,
-+                                            GPOEN_SYS_SDIO1_CMD,
-+                                            GPI_SYS_SDIO1_CMD)>,
-+                               <GPIOMUX(43, GPOUT_SYS_SDIO1_DATA0,
-+                                            GPOEN_SYS_SDIO1_DATA0,
-+                                            GPI_SYS_SDIO1_DATA0)>,
-+                               <GPIOMUX(48, GPOUT_SYS_SDIO1_DATA1,
-+                                            GPOEN_SYS_SDIO1_DATA1,
-+                                            GPI_SYS_SDIO1_DATA1)>,
-+                               <GPIOMUX(53, GPOUT_SYS_SDIO1_DATA2,
-+                                            GPOEN_SYS_SDIO1_DATA2,
-+                                            GPI_SYS_SDIO1_DATA2)>,
-+                               <GPIOMUX(63, GPOUT_SYS_SDIO1_DATA3,
-+                                            GPOEN_SYS_SDIO1_DATA3,
-+                                            GPI_SYS_SDIO1_DATA3)>,
-+                               <GPIOMUX(52, GPOUT_SYS_SDIO1_DATA4,
-+                                            GPOEN_SYS_SDIO1_DATA4,
-+                                            GPI_SYS_SDIO1_DATA4)>,
-+                               <GPIOMUX(39, GPOUT_SYS_SDIO1_DATA5,
-+                                            GPOEN_SYS_SDIO1_DATA5,
-+                                            GPI_SYS_SDIO1_DATA5)>,
-+                               <GPIOMUX(46, GPOUT_SYS_SDIO1_DATA6,
-+                                            GPOEN_SYS_SDIO1_DATA6,
-+                                            GPI_SYS_SDIO1_DATA6)>,
-+                               <GPIOMUX(47, GPOUT_SYS_SDIO1_DATA7,
-+                                            GPOEN_SYS_SDIO1_DATA7,
-+                                            GPI_SYS_SDIO1_DATA7)>;
-+                      bias-pull-up;
-+                      input-enable;
-+              };
-+      };
-+
-+      gmac0_pins: gmac0-0 {
-+              reset-pins {
-+                      pinmux = <GPIOMUX(13, GPOUT_HIGH,
-+                                            GPOEN_ENABLE,
-+                                            GPI_NONE)>;
-+                      bias-pull-up;
-+              };
-+      };
-+
-+      gmac1_pins: gmac1-0 {
-+              mdc-pins {
-+                      pinmux = <PINMUX(75, 0)>;
-+              };
-+      };
-+
-+      hdmi_pins: hdmi-0 {
-+              scl-pins {
-+                      pinmux = <GPIOMUX(7, GPOUT_SYS_HDMI_DDC_SCL,
-+                                           GPOEN_SYS_HDMI_DDC_SCL,
-+                                           GPI_SYS_HDMI_DDC_SCL)>;
-+                      bias-pull-up;
-+                      input-enable;
-+              };
-+
-+              sda-pins {
-+                      pinmux = <GPIOMUX(8, GPOUT_SYS_HDMI_DDC_SDA,
-+                                           GPOEN_SYS_HDMI_DDC_SDA,
-+                                           GPI_SYS_HDMI_DDC_SDA)>;
-+                      bias-pull-up;
-+                      input-enable;
-+              };
-+
-+              cec-pins {
-+                      pinmux = <GPIOMUX(14, GPOUT_SYS_HDMI_CEC_SDA,
-+                                            GPOEN_SYS_HDMI_CEC_SDA,
-+                                            GPI_SYS_HDMI_CEC_SDA)>;
-+                      bias-pull-up;
-+                      input-enable;
-+              };
-+
-+              hpd-pins {
-+                      pinmux = <GPIOMUX(15, GPOUT_LOW,
-+                                            GPOEN_DISABLE,
-+                                            GPI_SYS_HDMI_HPD)>;
-+                      bias-disable; /* external pull-up */
-+                      input-enable;
-+              };
-+      };
-+
-+      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-pull-up;
-+                      input-enable;
-+                      input-schmitt-enable;
-+              };
-+      };
-+
-+      i2c1_pins: i2c1-0 {
-+              i2c-pins {
-+                      pinmux = <GPIOMUX(49, GPOUT_LOW,
-+                                            GPOEN_SYS_I2C1_CLK,
-+                                            GPI_SYS_I2C1_CLK)>,
-+                               <GPIOMUX(50, GPOUT_LOW,
-+                                            GPOEN_SYS_I2C1_DATA,
-+                                            GPI_SYS_I2C1_DATA)>;
-+                      bias-pull-up;
-+                      input-enable;
-+                      input-schmitt-enable;
-+              };
-+      };
-+
-+      i2c2_pins: i2c2-0 {
-+              i2c-pins {
-+                      pinmux = <GPIOMUX(11, GPOUT_LOW,
-+                                            GPOEN_SYS_I2C2_CLK,
-+                                            GPI_SYS_I2C2_CLK)>,
-+                               <GPIOMUX(9, GPOUT_LOW,
-+                                           GPOEN_SYS_I2C2_DATA,
-+                                           GPI_SYS_I2C2_DATA)>;
-+                      bias-pull-up;
-+                      input-enable;
-+                      input-schmitt-enable;
-+              };
-+      };
-+
-+      i2c3_pins: i2c3-0 {
-+              i2c-pins {
-+                      pinmux = <GPIOMUX(51, GPOUT_LOW,
-+                                            GPOEN_SYS_I2C3_CLK,
-+                                            GPI_SYS_I2C3_CLK)>,
-+                               <GPIOMUX(52, GPOUT_LOW,
-+                                            GPOEN_SYS_I2C3_DATA,
-+                                            GPI_SYS_I2C3_DATA)>;
-+                      bias-pull-up;
-+                      input-enable;
-+                      input-schmitt-enable;
-+              };
-+      };
-+
-+      i2c4_pins: i2c4-0 {
-+              i2c-pins {
-+                      pinmux = <GPIOMUX(18, GPOUT_LOW,
-+                                            GPOEN_SYS_I2C4_CLK,
-+                                            GPI_SYS_I2C4_CLK)>,
-+                               <GPIOMUX(12, GPOUT_LOW,
-+                                            GPOEN_SYS_I2C4_DATA,
-+                                            GPI_SYS_I2C4_DATA)>;
-+                      bias-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-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-pull-up;
-+                      input-enable;
-+                      input-schmitt-enable;
-+              };
-+      };
-+
-+      i2s_clk_pins: i2s-clk-0 {
-+              bclk-lrck-pins {
-+                      pinmux = <GPIOMUX(38, GPOUT_LOW,
-+                                            GPOEN_DISABLE,
-+                                            GPI_SYS_I2STX1_BCLK)>,
-+                               <GPIOMUX(38, GPOUT_LOW,
-+                                            GPOEN_DISABLE,
-+                                            GPI_SYS_I2SRX_BCLK)>,
-+                               <GPIOMUX(63, GPOUT_LOW,
-+                                            GPOEN_DISABLE,
-+                                            GPI_SYS_I2STX1_LRCK)>,
-+                               <GPIOMUX(63, GPOUT_LOW,
-+                                            GPOEN_DISABLE,
-+                                            GPI_SYS_I2SRX_LRCK)>;
-+                      input-enable;
-+              };
-+      };
-+
-+      i2srx_clk_pins: i2srx-clk-0 {
-+              mclk-pins {
-+                      pinmux = <GPIOMUX(58, GPOUT_SYS_MCLK,
-+                                            GPOEN_ENABLE,
-+                                            GPI_NONE)>;
-+                      input-enable;
-+              };
-+      };
-+
-+      i2srx_pins: i2srx-0 {
-+              i2srx-pins {
-+                      pinmux = <GPIOMUX(61, GPOUT_LOW,
-+                                            GPOEN_DISABLE,
-+                                            GPI_SYS_I2SRX_SDIN0)>;
-+                      input-enable;
-+              };
-+      };
-+
-+      i2stx_pins: i2stx-0 {
-+              i2stx-pins {
-+                      pinmux = <GPIOMUX(44, GPOUT_SYS_I2STX1_SDO0,
-+                                            GPOEN_ENABLE,
-+                                            GPI_NONE)>;
-+                      input-enable;
-+              };
-+      };
-+
-+      mclk_ext_pins: mclk-ext-0 {
-+              mclk-ext-pins {
-+                      pinmux = <GPIOMUX(4, GPOUT_LOW,
-+                                           GPOEN_DISABLE,
-+                                           GPI_SYS_MCLK_EXT)>;
-+                      input-enable;
-+              };
-+      };
-+
-+      pdm_pins: pdm-0 {
-+              pdm-pins {
-+                      pinmux = <GPIOMUX(54, GPOUT_SYS_PDM_MCLK,
-+                                            GPOEN_ENABLE,
-+                                            GPI_NONE)>,
-+                               <GPIOMUX(60, GPOUT_LOW,
-+                                            GPOEN_DISABLE,
-+                                            GPI_SYS_PDM_DMIC0)>;
-+                      input-enable;
-+              };
-+      };
-+
-+      pwm_ch0to3_pins: pwm-ch0to3-0 {
-+              pwm-pins {
-+                      pinmux = <GPIOMUX(45, GPOUT_SYS_PWM_CHANNEL0,
-+                                            GPOEN_SYS_PWM0_CHANNEL0,
-+                                            GPI_NONE)>,
-+                               <GPIOMUX(46, GPOUT_SYS_PWM_CHANNEL1,
-+                                            GPOEN_SYS_PWM0_CHANNEL1,
-+                                            GPI_NONE)>,
-+                               <GPIOMUX(47, GPOUT_SYS_PWM_CHANNEL2,
-+                                            GPOEN_SYS_PWM0_CHANNEL2,
-+                                            GPI_NONE)>,
-+                               <GPIOMUX(48, GPOUT_SYS_PWM_CHANNEL3,
-+                                            GPOEN_SYS_PWM0_CHANNEL3,
-+                                            GPI_NONE)>;
-+                      drive-strength = <12>;
-+              };
-+      };
-+
-+      pwmdac_pins: pwmdac-0 {
-+              pwmdac-pins {
-+                      pinmux = <GPIOMUX(57, GPOUT_SYS_PWMDAC_LEFT,
-+                                            GPOEN_ENABLE,
-+                                            GPI_NONE)>,
-+                               <GPIOMUX(42, GPOUT_SYS_PWMDAC_RIGHT,
-+                                            GPOEN_ENABLE,
-+                                            GPI_NONE)>;
-+              };
-+      };
-+
-+      rgb_pad_pins: rgb-pad-pins {
-+              rgb-0-pins {
-+                      pinmux = <PINMUX(36, 1)>;
-+                      drive-strength = <12>;
-+                      input-disable;
-+                      slew-rate = <1>;
-+              };
-+
-+              rgb-pins {
-+                      pinmux = <PINMUX(37, 1)>,
-+                               <PINMUX(38, 1)>,
-+                               <PINMUX(39, 1)>,
-+                               <PINMUX(40, 1)>,
-+                               <PINMUX(41, 1)>,
-+                               <PINMUX(42, 1)>,
-+                               <PINMUX(43, 1)>,
-+                               <PINMUX(44, 1)>,
-+                               <PINMUX(45, 1)>,
-+                               <PINMUX(46, 1)>,
-+                               <PINMUX(47, 1)>,
-+                               <PINMUX(48, 1)>,
-+                               <PINMUX(49, 1)>,
-+                               <PINMUX(50, 1)>,
-+                               <PINMUX(51, 1)>,
-+                               <PINMUX(52, 1)>,
-+                               <PINMUX(53, 1)>,
-+                               <PINMUX(54, 1)>,
-+                               <PINMUX(55, 1)>,
-+                               <PINMUX(56, 1)>,
-+                               <PINMUX(57, 1)>,
-+                               <PINMUX(58, 1)>,
-+                               <PINMUX(59, 1)>,
-+                               <PINMUX(60, 1)>,
-+                               <PINMUX(61, 1)>,
-+                               <PINMUX(62, 1)>,
-+                               <PINMUX(63, 1)>;
-+                      drive-strength = <12>;
-+                      input-disable;
-+              };
-+      };
-+
-+      sdcard0_pins: sdcard0-0 {
-+              sdcard-pins {
-+                      pinmux = <GPIOMUX(24, GPOUT_SYS_SDIO0_RST,
-+                                            GPOEN_ENABLE,
-+                                            GPI_NONE)>,
-+                               <PINMUX(64, 0)>,
-+                               <PINMUX(65, 0)>,
-+                               <PINMUX(66, 0)>,
-+                               <PINMUX(67, 0)>,
-+                               <PINMUX(68, 0)>,
-+                               <PINMUX(69, 0)>;
-+                      bias-pull-up;
-+                      drive-strength = <12>;
-+                      input-enable;
-+                      slew-rate = <1>;
-+              };
-+      };
-+
-+      sdcard1_pins: sdcard1-0 {
-+              sdcard-pins {
-+                      pinmux = <GPIOMUX(56, GPOUT_SYS_SDIO1_CLK,
-+                                            GPOEN_ENABLE,
-+                                            GPI_NONE)>,
-+                               <GPIOMUX(50, GPOUT_SYS_SDIO1_CMD,
-+                                            GPOEN_SYS_SDIO1_CMD,
-+                                            GPI_SYS_SDIO1_CMD)>,
-+                               <GPIOMUX(49, GPOUT_SYS_SDIO1_DATA0,
-+                                            GPOEN_SYS_SDIO1_DATA0,
-+                                            GPI_SYS_SDIO1_DATA0)>,
-+                               <GPIOMUX(45, GPOUT_SYS_SDIO1_DATA1,
-+                                            GPOEN_SYS_SDIO1_DATA1,
-+                                            GPI_SYS_SDIO1_DATA1)>,
-+                               <GPIOMUX(62, GPOUT_SYS_SDIO1_DATA2,
-+                                            GPOEN_SYS_SDIO1_DATA2,
-+                                            GPI_SYS_SDIO1_DATA2)>,
-+                               <GPIOMUX(40, GPOUT_SYS_SDIO1_DATA3,
-+                                            GPOEN_SYS_SDIO1_DATA3,
-+                                            GPI_SYS_SDIO1_DATA3)>;
-+                      bias-pull-up;
-+                      input-enable;
-+              };
-+      };
-+
-+      spdif_pins: spdif-0 {
-+              spdif-pins {
-+                      pinmux = <GPIOMUX(57, GPOUT_SYS_SPDIF,
-+                                            GPOEN_ENABLE,
-+                                            GPI_NONE)>;
-+                      bias-pull-up;
-+                      input-enable;
-+              };
-+      };
-+
-+      spi0_pins: spi0-0 {
-+              mosi-pins {
-+                      pinmux = <GPIOMUX(38, GPOUT_SYS_SPI0_TXD,
-+                                            GPOEN_ENABLE,
-+                                            GPI_NONE)>;
-+                      bias-disable;
-+                      input-disable;
-+                      input-schmitt-disable;
-+              };
-+
-+              miso-pins {
-+                      pinmux = <GPIOMUX(39, GPOUT_LOW,
-+                                            GPOEN_DISABLE,
-+                                            GPI_SYS_SPI0_RXD)>;
-+                      bias-pull-up;
-+                      input-enable;
-+                      input-schmitt-enable;
-+              };
-+
-+              sck-pins {
-+                      pinmux = <GPIOMUX(36, GPOUT_SYS_SPI0_CLK,
-+                                            GPOEN_ENABLE,
-+                                            GPI_SYS_SPI0_CLK)>;
-+                      bias-disable;
-+                      input-disable;
-+                      input-schmitt-disable;
-+              };
-+
-+              ss-pins {
-+                      pinmux = <GPIOMUX(37, GPOUT_SYS_SPI0_FSS,
-+                                            GPOEN_ENABLE,
-+                                            GPI_SYS_SPI0_FSS)>;
-+                      bias-disable;
-+                      input-disable;
-+                      input-schmitt-disable;
-+              };
-+      };
-+
-+      spi1_pins: spi1-0 {
-+              mosi-pins {
-+                      pinmux = <GPIOMUX(42, GPOUT_SYS_SPI1_TXD,
-+                                            GPOEN_ENABLE,
-+                                            GPI_NONE)>;
-+                      bias-disable;
-+                      input-disable;
-+                      input-schmitt-disable;
-+              };
-+
-+              miso-pins {
-+                      pinmux = <GPIOMUX(43, GPOUT_LOW,
-+                                            GPOEN_DISABLE,
-+                                            GPI_SYS_SPI1_RXD)>;
-+                      bias-pull-up;
-+                      input-enable;
-+                      input-schmitt-enable;
-+              };
-+
-+              sck-pins {
-+                      pinmux = <GPIOMUX(40, GPOUT_SYS_SPI1_CLK,
-+                                            GPOEN_ENABLE,
-+                                            GPI_SYS_SPI1_CLK)>;
-+                      bias-disable;
-+                      input-disable;
-+                      input-schmitt-disable;
-+              };
-+
-+              ss-pins {
-+                      pinmux = <GPIOMUX(41, GPOUT_SYS_SPI1_FSS,
-+                                            GPOEN_ENABLE,
-+                                            GPI_SYS_SPI1_FSS)>;
-+                      bias-disable;
-+                      input-disable;
-+                      input-schmitt-disable;
-+              };
-+      };
-+
-+      spi2_pins: spi2-0 {
-+              mosi-pins {
-+                      pinmux = <GPIOMUX(46, GPOUT_SYS_SPI2_TXD,
-+                                            GPOEN_ENABLE,
-+                                            GPI_NONE)>;
-+                      bias-disable;
-+                      input-disable;
-+                      input-schmitt-disable;
-+              };
-+
-+              miso-pins {
-+                      pinmux = <GPIOMUX(47, GPOUT_LOW,
-+                                            GPOEN_DISABLE,
-+                                            GPI_SYS_SPI2_RXD)>;
-+                      bias-pull-up;
-+                      input-enable;
-+                      input-schmitt-enable;
-+              };
-+
-+              sck-pins {
-+                      pinmux = <GPIOMUX(44, GPOUT_SYS_SPI2_CLK,
-+                                            GPOEN_ENABLE,
-+                                            GPI_SYS_SPI2_CLK)>;
-+                      bias-disable;
-+                      input-disable;
-+                      input-schmitt-disable;
-+              };
-+
-+              ss-pins {
-+                      pinmux = <GPIOMUX(45, GPOUT_SYS_SPI2_FSS,
-+                                            GPOEN_ENABLE,
-+                                            GPI_SYS_SPI2_FSS)>;
-+                      bias-disable;
-+                      input-disable;
-+                      input-schmitt-disable;
-+              };
-+      };
-+
-+      spi3_pins: spi3-0 {
-+              mosi-pins {
-+                      pinmux = <GPIOMUX(50, GPOUT_SYS_SPI3_TXD,
-+                                            GPOEN_ENABLE,
-+                                            GPI_NONE)>;
-+                      bias-disable;
-+                      input-disable;
-+                      input-schmitt-disable;
-+              };
-+
-+              miso-pins {
-+                      pinmux = <GPIOMUX(51, GPOUT_LOW,
-+                                            GPOEN_DISABLE,
-+                                            GPI_SYS_SPI3_RXD)>;
-+                      bias-pull-up;
-+                      input-enable;
-+                      input-schmitt-enable;
-+              };
-+
-+              sck-pins {
-+                      pinmux = <GPIOMUX(48, GPOUT_SYS_SPI3_CLK,
-+                                            GPOEN_ENABLE,
-+                                            GPI_SYS_SPI3_CLK)>;
-+                      bias-disable;
-+                      input-disable;
-+                      input-schmitt-disable;
-+              };
-+
-+              ss-pins {
-+                      pinmux = <GPIOMUX(49, GPOUT_SYS_SPI3_FSS,
-+                                            GPOEN_ENABLE,
-+                                            GPI_SYS_SPI3_FSS)>;
-+                      bias-disable;
-+                      input-disable;
-+                      input-schmitt-disable;
-+              };
-+      };
-+
-+      spi4_pins: spi4-0 {
-+              mosi-pins {
-+                      pinmux = <GPIOMUX(54, GPOUT_SYS_SPI4_TXD,
-+                                            GPOEN_ENABLE,
-+                                            GPI_NONE)>;
-+                      bias-disable;
-+                      input-disable;
-+                      input-schmitt-disable;
-+              };
-+
-+              miso-pins {
-+                      pinmux = <GPIOMUX(55, GPOUT_LOW,
-+                                            GPOEN_DISABLE,
-+                                            GPI_SYS_SPI4_RXD)>;
-+                      bias-pull-up;
-+                      input-enable;
-+                      input-schmitt-enable;
-+              };
-+
-+              sck-pins {
-+                      pinmux = <GPIOMUX(52, GPOUT_SYS_SPI4_CLK,
-+                                            GPOEN_ENABLE,
-+                                            GPI_SYS_SPI4_CLK)>;
-+                      bias-disable;
-+                      input-disable;
-+                      input-schmitt-disable;
-+              };
-+
-+              ss-pins {
-+                      pinmux = <GPIOMUX(53, GPOUT_SYS_SPI4_FSS,
-+                                            GPOEN_ENABLE,
-+                                            GPI_SYS_SPI4_FSS)>;
-+                      bias-disable;
-+                      input-disable;
-+                      input-schmitt-disable;
-+              };
-+      };
-+
-+      spi5_pins: spi5-0 {
-+              mosi-pins {
-+                      pinmux = <GPIOMUX(58, GPOUT_SYS_SPI5_TXD,
-+                                            GPOEN_ENABLE,
-+                                            GPI_NONE)>;
-+                      bias-disable;
-+                      input-disable;
-+                      input-schmitt-disable;
-+              };
-+
-+              miso-pins {
-+                      pinmux = <GPIOMUX(59, GPOUT_LOW,
-+                                            GPOEN_DISABLE,
-+                                            GPI_SYS_SPI5_RXD)>;
-+                      bias-pull-up;
-+                      input-enable;
-+                      input-schmitt-enable;
-+              };
-+
-+              sck-pins {
-+                      pinmux = <GPIOMUX(56, GPOUT_SYS_SPI5_CLK,
-+                                            GPOEN_ENABLE,
-+                                            GPI_SYS_SPI5_CLK)>;
-+                      bias-disable;
-+                      input-disable;
-+                      input-schmitt-disable;
-+              };
-+
-+              ss-pins {
-+                      pinmux = <GPIOMUX(57, GPOUT_SYS_SPI5_FSS,
-+                                            GPOEN_ENABLE,
-+                                            GPI_SYS_SPI5_FSS)>;
-+                      bias-disable;
-+                      input-disable;
-+                      input-schmitt-disable;
-+              };
-+      };
-+
-+      spi6_pins: spi6-0 {
-+              mosi-pins {
-+                      pinmux = <GPIOMUX(62, GPOUT_SYS_SPI6_TXD,
-+                                            GPOEN_ENABLE,
-+                                            GPI_NONE)>;
-+                      bias-disable;
-+                      input-disable;
-+                      input-schmitt-disable;
-+              };
-+
-+              miso-pins {
-+                      pinmux = <GPIOMUX(63, GPOUT_LOW,
-+                                            GPOEN_DISABLE,
-+                                            GPI_SYS_SPI6_RXD)>;
-+                      bias-pull-up;
-+                      input-enable;
-+                      input-schmitt-enable;
-+              };
-+
-+              sck-pins {
-+                      pinmux = <GPIOMUX(60, GPOUT_SYS_SPI6_CLK,
-+                                            GPOEN_ENABLE,
-+                                            GPI_SYS_SPI6_CLK)>;
-+                      bias-disable;
-+                      input-disable;
-+                      input-schmitt-disable;
-+              };
-+
-+              ss-pins {
-+                      pinmux = <GPIOMUX(61, GPOUT_SYS_SPI6_FSS,
-+                                            GPOEN_ENABLE,
-+                                            GPI_SYS_SPI6_FSS)>;
-+                      bias-disable;
-+                      input-disable;
-+                      input-schmitt-disable;
-+              };
-+      };
-+
-+      tdm_pins: tdm-0 {
-+              tx-pins {
-+                      pinmux = <GPIOMUX(44, GPOUT_SYS_TDM_TXD,
-+                                            GPOEN_ENABLE,
-+                                            GPI_NONE)>;
-+                      bias-pull-up;
-+                      drive-strength = <2>;
-+                      input-disable;
-+                      input-schmitt-disable;
-+                      slew-rate = <0>;
-+              };
-+
-+              rx-pins {
-+                      pinmux = <GPIOMUX(61, GPOUT_HIGH,
-+                                            GPOEN_DISABLE,
-+                                            GPI_SYS_TDM_RXD)>;
-+                      input-enable;
-+              };
-+
-+              sync-pins {
-+                      pinmux = <GPIOMUX(63, GPOUT_HIGH,
-+                                            GPOEN_DISABLE,
-+                                            GPI_SYS_TDM_SYNC)>;
-+                      input-enable;
-+              };
-+
-+              pcmclk-pins {
-+                      pinmux = <GPIOMUX(38, GPOUT_HIGH,
-+                                            GPOEN_DISABLE,
-+                                            GPI_SYS_TDM_CLK)>;
-+                      input-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-pull-up;
-+                      drive-strength = <2>;
-+                      input-enable;
-+                      input-schmitt-enable;
-+                      slew-rate = <0>;
-+              };
-+      };
-+
-+      uart1_pins: uart1-0 {
-+              tx-pins {
-+                      pinmux = <GPIOMUX(30, GPOUT_SYS_UART1_TX,
-+                                            GPOEN_ENABLE,
-+                                            GPI_NONE)>;
-+                      bias-disable;
-+                      drive-strength = <12>;
-+                      input-disable;
-+                      input-schmitt-disable;
-+                      slew-rate = <0>;
-+              };
-+
-+              rx-pins {
-+                      pinmux = <GPIOMUX(31, GPOUT_LOW,
-+                                            GPOEN_DISABLE,
-+                                            GPI_SYS_UART1_RX)>;
-+                      bias-pull-up;
-+                      drive-strength = <2>;
-+                      input-enable;
-+                      input-schmitt-enable;
-+                      slew-rate = <0>;
-+              };
-+
-+              cts-pins {
-+                      pinmux = <GPIOMUX(29, GPOUT_LOW,
-+                                            GPOEN_DISABLE,
-+                                            GPI_SYS_UART1_CTS)>;
-+                      input-enable;
-+              };
-+
-+              rts-pins {
-+                      pinmux = <GPIOMUX(27, GPOUT_SYS_UART1_RTS,
-+                                            GPOEN_ENABLE,
-+                                            GPI_NONE)>;
-+                      input-enable;
-+              };
-+      };
-+
-+      uart2_pins: uart2-0 {
-+              tx-pins {
-+                      pinmux = <GPIOMUX(30, GPOUT_SYS_UART2_TX,
-+                                            GPOEN_ENABLE,
-+                                            GPI_NONE)>;
-+                      bias-disable;
-+                      drive-strength = <12>;
-+                      input-disable;
-+                      input-schmitt-disable;
-+                      slew-rate = <0>;
-+              };
-+
-+              rx-pins {
-+                      pinmux = <GPIOMUX(31, GPOUT_LOW,
-+                                            GPOEN_DISABLE,
-+                                            GPI_SYS_UART2_RX)>;
-+                      bias-pull-up;
-+                      drive-strength = <2>;
-+                      input-enable;
-+                      input-schmitt-enable;
-+                      slew-rate = <0>;
-+              };
-+
-+              cts-pins {
-+                      pinmux = <GPIOMUX(29, GPOUT_LOW,
-+                                            GPOEN_DISABLE,
-+                                            GPI_SYS_UART2_CTS)>;
-+                      input-enable;
-+              };
-+
-+              rts-pins {
-+                      pinmux = <GPIOMUX(27, GPOUT_SYS_UART2_RTS,
-+                                            GPOEN_ENABLE,
-+                                            GPI_NONE)>;
-+                      input-enable;
-+              };
-+      };
-+
-+      uart3_pins: uart3-0 {
-+              tx-pins {
-+                      pinmux = <GPIOMUX(30, GPOUT_SYS_UART3_TX,
-+                                            GPOEN_ENABLE,
-+                                            GPI_NONE)>;
-+                      bias-disable;
-+                      drive-strength = <12>;
-+                      input-disable;
-+                      input-schmitt-disable;
-+                      slew-rate = <0>;
-+              };
-+
-+              rx-pins {
-+                      pinmux = <GPIOMUX(31, GPOUT_LOW,
-+                                            GPOEN_DISABLE,
-+                                            GPI_SYS_UART3_RX)>;
-+                      bias-pull-up;
-+                      drive-strength = <2>;
-+                      input-enable;
-+                      input-schmitt-enable;
-+                      slew-rate = <0>;
-+              };
-+      };
-+
-+      uart4_pins: uart4-0 {
-+              tx-pins {
-+                      pinmux = <GPIOMUX(30, GPOUT_SYS_UART4_TX,
-+                                            GPOEN_ENABLE,
-+                                            GPI_NONE)>;
-+                      bias-disable;
-+                      drive-strength = <12>;
-+                      input-disable;
-+                      input-schmitt-disable;
-+                      slew-rate = <0>;
-+              };
-+
-+              rx-pins {
-+                      pinmux = <GPIOMUX(31, GPOUT_LOW,
-+                                            GPOEN_DISABLE,
-+                                            GPI_SYS_UART4_RX)>;
-+                      bias-pull-up;
-+                      drive-strength = <2>;
-+                      input-enable;
-+                      input-schmitt-enable;
-+                      slew-rate = <0>;
-+              };
-+
-+              cts-pins {
-+                      pinmux = <GPIOMUX(29, GPOUT_LOW,
-+                                            GPOEN_DISABLE,
-+                                            GPI_SYS_UART4_CTS)>;
-+                      input-enable;
-+              };
-+
-+              rts-pins {
-+                      pinmux = <GPIOMUX(27, GPOUT_SYS_UART4_RTS,
-+                                            GPOEN_ENABLE,
-+                                            GPI_NONE)>;
-+                      input-enable;
-+              };
-+      };
-+
-+      uart5_pins: uart5-0 {
-+              tx-pins {
-+                      pinmux = <GPIOMUX(30, GPOUT_SYS_UART5_TX,
-+                                            GPOEN_ENABLE,
-+                                            GPI_NONE)>;
-+                      bias-disable;
-+                      drive-strength = <12>;
-+                      input-disable;
-+                      input-schmitt-disable;
-+                      slew-rate = <0>;
-+              };
-+
-+              rx-pins {
-+                      pinmux = <GPIOMUX(31, GPOUT_LOW,
-+                                            GPOEN_DISABLE,
-+                                            GPI_SYS_UART5_RX)>;
-+                      bias-pull-up;
-+                      drive-strength = <2>;
-+                      input-enable;
-+                      input-schmitt-enable;
-+                      slew-rate = <0>;
-+              };
-+
-+              cts-pins {
-+                      pinmux = <GPIOMUX(29, GPOUT_LOW,
-+                                            GPOEN_DISABLE,
-+                                            GPI_SYS_UART5_CTS)>;
-+                      input-enable;
-+              };
-+
-+              rts-pins {
-+                      pinmux = <GPIOMUX(27, GPOUT_SYS_UART5_RTS,
-+                                            GPOEN_ENABLE,
-+                                            GPI_NONE)>;
-+                      input-enable;
-+              };
-+      };
-+
-+      usb_pins: usb-0 {
-+              usb-pins {
-+                      pinmux = <GPIOMUX(33, GPOUT_HIGH,
-+                                            GPOEN_ENABLE,
-+                                            GPI_NONE)>,
-+                               <GPIOMUX(34, GPOUT_LOW,
-+                                            GPOEN_DISABLE,
-+                                            GPI_SYS_USB_OVERCURRENT)>;
-+                      input-enable;
-+              };
-+      };
-+};
-+
-+&aongpio {
-+      pwm_ch4to5_pins: pwm-ch4to5-0 {
-+              pwm-pins {
-+                      pinmux = <GPIOMUX(1, GPOUT_AON_PTC0_PWM4, /* PAD_RGPIO0 */
-+                                           GPOEN_AON_PTC0_OE_N_4,
-+                                           GPI_NONE)>,
-+                               <GPIOMUX(2, GPOUT_AON_PTC0_PWM5, /* PAD_RGPIO1 */
-+                                           GPOEN_AON_PTC0_OE_N_5,
-+                                           GPI_NONE)>;
-+                      drive-strength = <12>;
-+              };
-+      };
-+
-+      pwm_ch6to7_pins: pwm-ch6to7-0 {
-+              pwm-pins {
-+                      pinmux = <GPIOMUX(1, GPOUT_AON_PTC0_PWM6, /* PAD_RGPIO0 */
-+                                           GPOEN_AON_PTC0_OE_N_6,
-+                                           GPI_NONE)>,
-+                               <GPIOMUX(2, GPOUT_AON_PTC0_PWM7, /* PAD_RGPIO1 */
-+                                           GPOEN_AON_PTC0_OE_N_7,
-+                                           GPI_NONE)>;
-+                      drive-strength = <12>;
-+              };
-+      };
-+};
---- /dev/null
-+++ b/arch/riscv/boot/dts/starfive/jh7110-evb.dts
-@@ -0,0 +1,35 @@
-+// SPDX-License-Identifier: GPL-2.0 OR MIT
-+/*
-+ * Copyright (C) 2023 StarFive Technology Co., Ltd.
-+ */
-+
-+/dts-v1/;
-+#include "jh7110-evb.dtsi"
-+
-+/ {
-+      model = "StarFive JH7110 EVB";
-+      compatible = "starfive,jh7110-evb", "starfive,jh7110";
-+};
-+
-+&mmc0 {
-+      assigned-clocks = <&syscrg JH7110_SYSCLK_SDIO0_SDCARD>;
-+      assigned-clock-rates = <50000000>;
-+      pinctrl-names = "default";
-+      pinctrl-0 = <&sdcard0_pins>;
-+      max-frequency = <100000000>;
-+      card-detect-delay = <300>;
-+      bus-width = <4>;
-+      no-sdio;
-+      no-mmc;
-+      broken-cd;
-+      post-power-on-delay-ms = <200>;
-+      status = "okay";
-+};
-+
-+&pcie1 {
-+      status = "okay";
-+};
-+
-+&usb0 {
-+      status = "okay";
-+};
---- /dev/null
-+++ b/arch/riscv/boot/dts/starfive/jh7110-evb.dtsi
-@@ -0,0 +1,854 @@
-+// SPDX-License-Identifier: GPL-2.0 OR MIT
-+/*
-+ * Copyright (C) 2023 StarFive Technology Co., Ltd.
-+ */
-+
-+/dts-v1/;
-+#include "jh7110.dtsi"
-+#include "jh7110-clk.dtsi"
-+#include "jh7110-evb-pinctrl.dtsi"
-+#include <dt-bindings/gpio/gpio.h>
-+
-+/ {
-+      aliases {
-+              ethernet0 = &gmac0;
-+              ethernet1 = &gmac1;
-+              i2c0 = &i2c0;
-+              i2c1 = &i2c1;
-+              i2c2 = &i2c2;
-+              i2c3 = &i2c3;
-+              i2c4 = &i2c4;
-+              i2c5 = &i2c5;
-+              i2c6 = &i2c6;
-+              pcie0 = &pcie0;
-+              pcie1 = &pcie1;
-+              serial0 = &uart0;
-+              serial3 = &uart3;
-+      };
-+
-+      chosen {
-+              stdout-path = "serial0:115200n8";
-+      };
-+
-+      cpus {
-+              timebase-frequency = <4000000>;
-+      };
-+
-+      memory@40000000 {
-+              device_type = "memory";
-+              reg = <0x0 0x40000000 0x1 0x0>;
-+      };
-+
-+      reserved-memory {
-+              #address-cells = <2>;
-+              #size-cells = <2>;
-+              ranges;
-+
-+              linux,cma {
-+                      compatible = "shared-dma-pool";
-+                      reusable;
-+                      size = <0x0 0x20000000>;
-+                      alignment = <0x0 0x1000>;
-+                      alloc-ranges = <0x0 0x70000000 0x0 0x20000000>;
-+                      linux,cma-default;
-+              };
-+
-+              e24_mem: e24@c0000000 {
-+                      reg = <0x0 0x6ce00000 0x0 0x1600000>;
-+              };
-+
-+              xrp_reserved: xrpbuffer@f0000000 {
-+                      reg = <0x0 0x69c00000 0x0 0x01ffffff
-+                             0x0 0x6bc00000 0x0 0x00001000
-+                             0x0 0x6bc01000 0x0 0x00fff000
-+                             0x0 0x6cc00000 0x0 0x00001000>;
-+              };
-+      };
-+
-+      /* i2s + hdmi */
-+      sound1: snd-card1 {
-+              compatible = "simple-audio-card";
-+              #address-cells = <1>;
-+              #size-cells = <0>;
-+
-+              simple-audio-card,name = "StarFive-HDMI-Sound-Card";
-+              simple-audio-card,dai-link@0 {
-+                      reg = <0>;
-+                      format = "i2s";
-+                      bitclock-master = <&sndi2s0>;
-+                      frame-master = <&sndi2s0>;
-+                      mclk-fs = <256>;
-+                      status = "okay";
-+
-+                      sndi2s0: cpu {
-+                              sound-dai = <&i2stx0>;
-+                      };
-+
-+                      codec {
-+                              sound-dai = <&hdmi>;
-+                      };
-+              };
-+      };
-+};
-+
-+&U74_1 {
-+      /delete-property/ clocks;
-+      /delete-property/ clock-names;
-+};
-+
-+&U74_2 {
-+      /delete-property/ clocks;
-+      /delete-property/ clock-names;
-+};
-+
-+&U74_3 {
-+      /delete-property/ clocks;
-+      /delete-property/ clock-names;
-+};
-+
-+&U74_4 {
-+      /delete-property/ clocks;
-+      /delete-property/ clock-names;
-+};
-+
-+&can0 {
-+      pinctrl-names = "default";
-+      pinctrl-0 = <&can0_pins>;
-+      status = "disabled";
-+};
-+
-+&can1 {
-+      pinctrl-names = "default";
-+      pinctrl-0 = <&can1_pins>;
-+      status = "disabled";
-+};
-+
-+&co_process {
-+      memory-region = <&e24_mem>;
-+      status = "okay";
-+};
-+
-+&dc8200 {
-+      status = "okay";
-+
-+      dc_out: port {
-+              #address-cells = <1>;
-+              #size-cells = <0>;
-+
-+              dc_out_dpi0: endpoint@0 {
-+                      reg = <0>;
-+                      remote-endpoint = <&hdmi_input0>;
-+              };
-+              dc_out_dpi1: endpoint@1 {
-+                      reg = <1>;
-+                      remote-endpoint = <&hdmi_in_lcdc>;
-+              };
-+              dc_out_dpi2: endpoint@2 {
-+                      reg = <2>;
-+                      remote-endpoint = <&mipi_in>;
-+              };
-+      };
-+};
-+
-+&display {
-+      ports = <&dc_out_dpi0>;
-+      status = "okay";
-+};
-+
-+&dsi_output {
-+      status = "okay";
-+
-+      ports {
-+              #address-cells = <1>;
-+              #size-cells = <0>;
-+
-+              port@0 {
-+                      reg = <0>;
-+                      mipi_in: endpoint {
-+                              remote-endpoint = <&dc_out_dpi2>;
-+                      };
-+              };
-+
-+              port@1 {
-+                      reg = <1>;
-+                      mipi_out: endpoint {
-+                              remote-endpoint = <&dsi_in_port>;
-+                      };
-+              };
-+      };
-+};
-+
-+&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>;
-+                      rx-internal-delay-ps = <1900>;
-+                      tx-internal-delay-ps = <1650>;
-+              };
-+      };
-+};
-+
-+&gmac1 {
-+      #address-cells = <1>;
-+      #size-cells = <0>;
-+      status = "okay";
-+
-+      phy1: ethernet-phy@1 {
-+              reg = <0>;
-+              rxc-skew-ps = <1060>;
-+              txc-skew-ps = <1800>;
-+      };
-+};
-+
-+&gpu {
-+      status = "okay";
-+};
-+
-+&hdmi {
-+      status = "okay";
-+      pinctrl-names = "default";
-+      pinctrl-0 = <&hdmi_pins>;
-+      hpd-gpio = <&sysgpio 15 GPIO_ACTIVE_HIGH>;
-+
-+      hdmi_in: port {
-+              #address-cells = <1>;
-+              #size-cells = <0>;
-+              hdmi_in_lcdc: endpoint@0 {
-+                      reg = <0>;
-+                      remote-endpoint = <&dc_out_dpi1>;
-+              };
-+      };
-+};
-+
-+&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 = "disabled";
-+
-+      wm8960: codec@1a {
-+              compatible = "wlf,wm8960";
-+              reg = <0x1a>;
-+              wlf,shared-lrclk;
-+              #sound-dai-cells = <0>;
-+      };
-+
-+      ac108: ac108@3b {
-+              compatible = "x-power,ac108_0";
-+              reg = <0x3b>;
-+              #sound-dai-cells = <0>;
-+              data-protocol = <0>;
-+      };
-+};
-+
-+&i2c1 {
-+      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 = <&i2c1_pins>;
-+      status = "disabled";
-+};
-+
-+&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";
-+
-+      tinker_ft5406: tinker_ft5406@38 {
-+              compatible = "tinker_ft5406";
-+              reg = <0x38>;
-+      };
-+
-+      seeed_plane_i2c@45 {
-+              compatible = "seeed_panel";
-+              reg = <0x45>;
-+
-+              port {
-+                      panel_dsi_port: endpoint {
-+                              remote-endpoint = <&dsi_out_port>;
-+                      };
-+              };
-+      };
-+};
-+
-+&i2c3 {
-+      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 = <&i2c3_pins>;
-+      status = "disabled";
-+};
-+
-+&i2c4 {
-+      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 = <&i2c4_pins>;
-+      status = "okay";
-+
-+      sc2235: sc2235@30 {
-+              compatible = "smartsens,sc2235";
-+              reg = <0x30>;
-+              clocks = <&clk_ext_camera>;
-+              clock-names = "xclk";
-+
-+              port {
-+                      /* Parallel bus endpoint */
-+                      sc2235_to_parallel: endpoint {
-+                              remote-endpoint = <&parallel_from_sc2235>;
-+                              bus-type = <5>;      /* Parallel */
-+                              bus-width = <8>;
-+                              data-shift = <2>; /* lines 13:6 are used */
-+                              hsync-active = <1>;
-+                              vsync-active = <1>;
-+                              pclk-sample = <1>;
-+                      };
-+              };
-+      };
-+
-+      tda998x@70 {
-+              compatible = "nxp,tda998x";
-+              reg = <0x70>;
-+
-+              port {
-+                      tda998x_0_input: endpoint {
-+                              remote-endpoint = <&hdmi_out>;
-+                      };
-+              };
-+      };
-+};
-+
-+&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";
-+
-+      pmic: jh7110_evb_reg@50 {
-+              compatible = "starfive,jh7110-evb-regulator";
-+              reg = <0x50>;
-+
-+              regulators {
-+                      hdmi_1p8: LDO_REG1 {
-+                              regulator-name = "hdmi_1p8";
-+                              regulator-min-microvolt = <1800000>;
-+                              regulator-max-microvolt = <1800000>;
-+                      };
-+                      mipitx_1p8: LDO_REG2 {
-+                              regulator-name = "mipitx_1p8";
-+                              regulator-min-microvolt = <1800000>;
-+                              regulator-max-microvolt = <1800000>;
-+                      };
-+                      mipirx_1p8: LDO_REG3 {
-+                              regulator-name = "mipirx_1p8";
-+                              regulator-min-microvolt = <1800000>;
-+                              regulator-max-microvolt = <1800000>;
-+                      };
-+                      hdmi_0p9: LDO_REG4 {
-+                              regulator-name = "hdmi_0p9";
-+                              regulator-min-microvolt = <900000>;
-+                              regulator-max-microvolt = <900000>;
-+                      };
-+                      mipitx_0p9: LDO_REG5 {
-+                              regulator-name = "mipitx_0p9";
-+                              regulator-min-microvolt = <900000>;
-+                              regulator-max-microvolt = <900000>;
-+                      };
-+                      mipirx_0p9: LDO_REG6 {
-+                              regulator-name = "mipirx_0p9";
-+                              regulator-min-microvolt = <900000>;
-+                              regulator-max-microvolt = <900000>;
-+                      };
-+                      sdio_vdd: LDO_REG7 {
-+                              regulator-name = "sdio_vdd";
-+                              regulator-min-microvolt = <1800000>;
-+                              regulator-max-microvolt = <3300000>;
-+                      };
-+              };
-+      };
-+};
-+
-+&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";
-+
-+      ov4689: ov4689@36 {
-+              compatible = "ovti,ov4689";
-+              reg = <0x36>;
-+              clocks = <&clk_ext_camera>;
-+              clock-names = "xclk";
-+              //reset-gpio = <&sysgpio 18 0>;
-+              rotation = <180>;
-+
-+              port {
-+                      /* Parallel bus endpoint */
-+                      ov4689_to_csi2rx0: endpoint {
-+                              remote-endpoint = <&csi2rx0_from_ov4689>;
-+                              bus-type = <4>;         /* MIPI CSI-2 D-PHY */
-+                              clock-lanes = <0>;
-+                              data-lanes = <1 2 3 4>;
-+                      };
-+              };
-+      };
-+
-+      imx219: imx219@10 {
-+              compatible = "sony,imx219";
-+              reg = <0x10>;
-+              clocks = <&clk_ext_camera>;
-+              clock-names = "xclk";
-+              reset-gpio = <&sysgpio 10 0>;
-+              //DOVDD-supply = <&v2v8>;
-+              rotation = <0>;
-+              orientation = <1>; //CAMERA_ORIENTATION_BACK
-+
-+              port {
-+                      /* CSI2 bus endpoint */
-+                      imx219_to_csi2rx0: endpoint {
-+                              remote-endpoint = <&csi2rx0_from_imx219>;
-+                              bus-type = <4>;      /* MIPI CSI-2 D-PHY */
-+                              clock-lanes = <0>;
-+                              data-lanes = <2 1>;
-+                              lane-polarities = <1 1 1>;
-+                              link-frequencies = /bits/ 64 <456000000>;
-+                      };
-+              };
-+      };
-+
-+      imx708: imx708@1a {
-+              compatible = "sony,imx708";
-+              reg = <0x1a>;
-+              clocks = <&clk_ext_camera>;
-+              reset-gpio = <&sysgpio 10 0>;
-+
-+              port {
-+                      imx708_to_csi2rx0: endpoint {
-+                              remote-endpoint = <&csi2rx0_from_imx708>;
-+                              data-lanes = <1 2>;
-+                              clock-noncontinuous;
-+                              link-frequencies = /bits/ 64 <450000000>;
-+                      };
-+              };
-+      };
-+};
-+
-+&i2srx {
-+      pinctrl-names = "default";
-+      pinctrl-0 = <&i2s_clk_pins &i2srx_pins>;
-+};
-+
-+&i2srx_mst {
-+      pinctrl-names = "default";
-+      pinctrl-0 = <&i2srx_clk_pins>;
-+};
-+
-+&i2stx0 {
-+      pinctrl-names = "default";
-+      pinctrl-0 = <&mclk_ext_pins>;
-+      status = "okay";
-+};
-+
-+&i2stx1 {
-+      pinctrl-names = "default";
-+      pinctrl-0 = <&i2stx_pins>;
-+};
-+
-+&jpu {
-+      status = "okay";
-+};
-+
-+&mailbox_contrl0 {
-+      status = "okay";
-+};
-+
-+&mailbox_client0 {
-+      status = "okay";
-+};
-+
-+&mipi_dphy {
-+      status = "okay";
-+};
-+
-+&mipi_dsi {
-+      status = "okay";
-+
-+      port {
-+              dsi_out_port: endpoint@0 {
-+                      remote-endpoint = <&panel_dsi_port>;
-+              };
-+              dsi_in_port: endpoint@1 {
-+                      remote-endpoint = <&mipi_out>;
-+              };
-+      };
-+
-+      mipi_panel: panel@0 {
-+              /*compatible = "";*/
-+              status = "okay";
-+      };
-+};
-+
-+&pcie0 {
-+      enable-gpios = <&sysgpio 32 GPIO_ACTIVE_HIGH>;
-+      perst-gpios = <&sysgpio 26 GPIO_ACTIVE_LOW>;
-+      phys = <&pciephy0>;
-+      status = "disabled";
-+};
-+
-+&pcie1 {
-+      enable-gpios = <&sysgpio 21 GPIO_ACTIVE_HIGH>;
-+      perst-gpios = <&sysgpio 28 GPIO_ACTIVE_LOW>;
-+      phys = <&pciephy1>;
-+      status = "disabled";
-+};
-+
-+&pciephy0 {
-+      starfive,sys-syscon = <&sys_syscon 0x18>;
-+      starfive,stg-syscon = <&stg_syscon 0x148 0x1f4>;
-+};
-+
-+&pdm {
-+      pinctrl-names = "default";
-+      pinctrl-0 = <&pdm_pins>;
-+      status = "disabled";
-+};
-+
-+&pwmdac {
-+      pinctrl-names = "default";
-+      pinctrl-0 = <&pwmdac_pins>;
-+};
-+
-+&qspi {
-+      #address-cells = <1>;
-+      #size-cells = <0>;
-+      status = "okay";
-+
-+      nor_flash: flash@0 {
-+              compatible = "jedec,spi-nor";
-+              reg=<0>;
-+              cdns,read-delay = <5>;
-+              spi-max-frequency = <4687500>;
-+              cdns,tshsl-ns = <1>;
-+              cdns,tsd2d-ns = <1>;
-+              cdns,tchsh-ns = <1>;
-+              cdns,tslch-ns = <1>;
-+
-+              partitions {
-+                      compatible = "fixed-partitions";
-+                      #address-cells = <1>;
-+                      #size-cells = <1>;
-+
-+                      spl@0 {
-+                              reg = <0x0 0x40000>;
-+                      };
-+                      uboot@100000 {
-+                              reg = <0x100000 0x300000>;
-+                      };
-+                      data@f00000 {
-+                              reg = <0xf00000 0x100000>;
-+                      };
-+              };
-+      };
-+};
-+
-+&rgb_output {
-+      status = "okay";
-+
-+      ports {
-+              #address-cells = <1>;
-+              #size-cells = <0>;
-+
-+              port@0 {
-+                      #address-cells = <1>;
-+                      #size-cells = <0>;
-+                      reg = <0>;
-+
-+                      hdmi_input0:endpoint@0 {
-+                              reg = <0>;
-+                              remote-endpoint = <&dc_out_dpi0>;
-+                      };
-+              };
-+
-+              port@1 {
-+                      reg = <1>;
-+
-+                      hdmi_out:endpoint {
-+                              remote-endpoint = <&tda998x_0_input>;
-+                      };
-+              };
-+      };
-+};
-+
-+&spdif {
-+      pinctrl-names = "default";
-+      pinctrl-0 = <&spdif_pins>;
-+};
-+
-+&spi0 {
-+      pinctrl-names = "default";
-+      pinctrl-0 = <&spi0_pins>;
-+      status = "disabled";
-+
-+      spi_dev0: spi_dev@0 {
-+              compatible = "rohm,dh2228fv";
-+              reg = <0>;
-+              pl022,com-mode = <1>;
-+              spi-max-frequency = <10000000>;
-+      };
-+};
-+
-+&spi1 {
-+      pinctrl-names = "default";
-+      pinctrl-0 = <&spi1_pins>;
-+      status = "disabled";
-+
-+      spi_dev1: spi_dev@0 {
-+              compatible = "rohm,dh2228fv";
-+              reg = <0>;
-+              pl022,com-mode = <1>;
-+              spi-max-frequency = <10000000>;
-+      };
-+};
-+
-+&spi2 {
-+      pinctrl-names = "default";
-+      pinctrl-0 = <&spi2_pins>;
-+      status = "disabled";
-+
-+      spi_dev2: spi_dev@0 {
-+              compatible = "rohm,dh2228fv";
-+              reg = <0>;
-+              pl022,com-mode = <1>;
-+              spi-max-frequency = <10000000>;
-+      };
-+};
-+
-+&spi3 {
-+      pinctrl-names = "default";
-+      pinctrl-0 = <&spi3_pins>;
-+      status = "disabled";
-+
-+      spi_dev3: spi_dev@0 {
-+              compatible = "rohm,dh2228fv";
-+              reg = <0>;
-+              pl022,com-mode = <1>;
-+              spi-max-frequency = <10000000>;
-+      };
-+};
-+
-+&spi4 {
-+      pinctrl-names = "default";
-+      pinctrl-0 = <&spi4_pins>;
-+      status = "disabled";
-+
-+      spi_dev4: spi_dev@0 {
-+              compatible = "rohm,dh2228fv";
-+              reg = <0>;
-+              pl022,com-mode = <1>;
-+              spi-max-frequency = <10000000>;
-+      };
-+};
-+
-+&spi5 {
-+      pinctrl-names = "default";
-+      pinctrl-0 = <&spi5_pins>;
-+      status = "disabled";
-+
-+      spi_dev5: spi_dev@0 {
-+              compatible = "rohm,dh2228fv";
-+              reg = <0>;
-+              pl022,com-mode = <1>;
-+              spi-max-frequency = <10000000>;
-+      };
-+};
-+
-+&spi6 {
-+      pinctrl-names = "default";
-+      pinctrl-0 = <&spi6_pins>;
-+      status = "disabled";
-+
-+      spi_dev6: spi_dev@0 {
-+              compatible = "rohm,dh2228fv";
-+              reg = <0>;
-+              pl022,com-mode = <1>;
-+              spi-max-frequency = <10000000>;
-+      };
-+};
-+
-+&tda988x_pin {
-+      pinctrl-names = "default";
-+      pinctrl-0 = <&rgb_pad_pins>;
-+      status = "disabled";
-+};
-+
-+&tdm {
-+      pinctrl-names = "default";
-+      pinctrl-0 = <&tdm_pins>;
-+      status = "disabled";
-+};
-+
-+&uart0 {
-+      pinctrl-names = "default";
-+      pinctrl-0 = <&uart0_pins>;
-+      status = "okay";
-+};
-+
-+&uart1 {
-+      pinctrl-names = "default";
-+      pinctrl-0 = <&uart1_pins>;
-+      status = "disabled";
-+};
-+
-+&uart2 {
-+      pinctrl-names = "default";
-+      pinctrl-0 = <&uart2_pins>;
-+      status = "disabled";
-+};
-+
-+&uart3 {
-+      pinctrl-names = "default";
-+      pinctrl-0 = <&uart3_pins>;
-+      status = "disabled";
-+};
-+
-+&uart4 {
-+      pinctrl-names = "default";
-+      pinctrl-0 = <&uart4_pins>;
-+      status = "disabled";
-+};
-+
-+&uart5 {
-+      pinctrl-names = "default";
-+      pinctrl-0 = <&uart5_pins>;
-+      status = "disabled";
-+};
-+
-+&usb0 {
-+      clocks = <&stgcrg JH7110_STGCLK_USB0_LPM>,
-+               <&stgcrg JH7110_STGCLK_USB0_STB>,
-+               <&stgcrg JH7110_STGCLK_USB0_APB>,
-+               <&stgcrg JH7110_STGCLK_USB0_AXI>,
-+               <&stgcrg JH7110_STGCLK_USB0_UTMI_APB>,
-+               <&stgcrg JH7110_STGCLK_PCIE0_APB>;
-+      clock-names = "lpm", "stb", "apb", "axi", "utmi_apb", "phy";
-+      resets = <&stgcrg JH7110_STGRST_USB0_PWRUP>,
-+               <&stgcrg JH7110_STGRST_USB0_APB>,
-+               <&stgcrg JH7110_STGRST_USB0_AXI>,
-+               <&stgcrg JH7110_STGRST_USB0_UTMI_APB>,
-+               <&stgcrg JH7110_STGRST_PCIE0_APB>;
-+      reset-names = "pwrup", "apb", "axi", "utmi_apb", "phy";
-+      pinctrl-names = "default";
-+      pinctrl-0 = <&usb_pins>;
-+      dr_mode = "host"; /* host or peripheral */
-+      status = "disabled";
-+};
-+
-+&usb_cdns3 {
-+      phys = <&usbphy0>, <&pciephy0>;
-+      phy-names = "cdns3,usb2-phy", "cdns3,usb3-phy";
-+};
-+
-+&vin_sysctl {
-+      status = "okay";
-+
-+      ports {
-+              #address-cells = <1>;
-+              #size-cells = <0>;
-+
-+              port@0 {
-+                      reg = <0>;
-+                      #address-cells = <1>;
-+                      #size-cells = <0>;
-+
-+                      /* Parallel bus endpoint */
-+                      parallel_from_sc2235: endpoint@0 {
-+                              reg = <0>;
-+                              remote-endpoint = <&sc2235_to_parallel>;
-+                              bus-type = <5>;         /* Parallel */
-+                              bus-width = <8>;
-+                              data-shift = <2>;       /* lines 9:2 are used */
-+                              hsync-active = <1>;
-+                              vsync-active = <0>;
-+                              pclk-sample = <1>;
-+                              status = "okay";
-+                      };
-+              };
-+
-+              port@1 {
-+                      reg = <1>;
-+                      #address-cells = <1>;
-+                      #size-cells = <0>;
-+
-+                      /* CSI2 bus endpoint */
-+                      csi2rx0_from_ov4689: endpoint@0 {
-+                              reg = <0>;
-+                              remote-endpoint = <&ov4689_to_csi2rx0>;
-+                              bus-type = <4>;      /* MIPI CSI-2 D-PHY */
-+                              clock-lanes = <0>;
-+                              data-lanes = <1 2 3 4>;
-+                              status = "okay";
-+                      };
-+
-+                      /* CSI2 bus endpoint */
-+                      csi2rx0_from_imx219: endpoint@1 {
-+                              reg = <1>;
-+                              remote-endpoint = <&imx219_to_csi2rx0>;
-+                              bus-type = <4>;      /* MIPI CSI-2 D-PHY */
-+                              clock-lanes = <0>;
-+                              data-lanes = <2 1>;
-+                              lane-polarities = <1 1 1>;
-+                              status = "okay";
-+                      };
-+
-+                      csi2rx0_from_imx708: endpoint@2 {
-+                              reg = <2>;
-+                              remote-endpoint = <&imx708_to_csi2rx0>;
-+                              bus-type = <4>;      /* MIPI CSI-2 D-PHY */
-+                              clock-lanes = <0>;
-+                              data-lanes = <2 1>;
-+                              lane-polarities = <1 1 1>;
-+                              status = "okay";
-+                      };
-+              };
-+      };
-+};
-+
-+&vpu_dec {
-+      status = "okay";
-+};
-+
-+&vpu_enc {
-+      status = "okay";
-+};
-+
-+&xrp {
-+      memory-region = <&xrp_reserved>;
-+      status = "okay";
-+};
---- a/arch/riscv/boot/dts/starfive/jh7110.dtsi
-+++ b/arch/riscv/boot/dts/starfive/jh7110.dtsi
-@@ -196,11 +196,60 @@
-                       opp-750000000 {
-                                       opp-hz = /bits/ 64 <750000000>;
-                                       opp-microvolt = <800000>;
-+                                      opp-suspend;
-                       };
-                       opp-1500000000 {
-                                       opp-hz = /bits/ 64 <1500000000>;
-                                       opp-microvolt = <1040000>;
-                       };
-+                      /* CPU opp table for 1.25GHz */
-+                      opp-312500000 {
-+                                      opp-hz = /bits/ 64 <312500000>;
-+                                      opp-microvolt = <800000>;
-+                      };
-+                      opp-417000000 {
-+                                      opp-hz = /bits/ 64 <417000000>;
-+                                      opp-microvolt = <800000>;
-+                      };
-+                      opp-625000000 {
-+                                      opp-hz = /bits/ 64 <625000000>;
-+                                      opp-microvolt = <800000>;
-+                                      opp-suspend;
-+                      };
-+                      opp-1250000000 {
-+                                      opp-hz = /bits/ 64 <1250000000>;
-+                                      opp-microvolt = <1000000>;
-+                      };
-+      };
-+
-+      display: display-subsystem {
-+              compatible = "starfive,jh7110-display","verisilicon,display-subsystem";
-+              status = "disabled";
-+      };
-+
-+      dsi_output: dsi-output {
-+              compatible = "starfive,jh7110-display-encoder","verisilicon,dsi-encoder";
-+              status = "disabled";
-+      };
-+
-+      mailbox_client0: mailbox_client {
-+              compatible = "starfive,mailbox-test";
-+              mbox-names = "rx", "tx";
-+              mboxes = <&mailbox_contrl0 0 1>,<&mailbox_contrl0 1 0>;
-+              status = "disabled";
-+      };
-+
-+      rgb_output: rgb-output {
-+              compatible = "starfive,jh7110-rgb_output","verisilicon,rgb-encoder";
-+              //verisilicon,dss-syscon = <&dssctrl>;
-+              //verisilicon,mux-mask = <0x70 0x380>;
-+              //verisilicon,mux-val = <0x40 0x280>;
-+              status = "disabled";
-+      };
-+
-+      tda988x_pin: tda988x_pin {
-+              compatible = "starfive,tda998x_rgb_pin";
-+              status = "disabled";
-       };
-       thermal-zones {
-@@ -349,7 +398,9 @@
-               ccache: cache-controller@2010000 {
-                       compatible = "starfive,jh7110-ccache", "sifive,ccache0", "cache";
--                      reg = <0x0 0x2010000 0x0 0x4000>;
-+                      reg = <0x0 0x2010000 0x0 0x4000>,
-+                            <0x0 0x8000000 0x0 0x2000000>,
-+                            <0x0 0xa000000 0x0 0x2000000>;
-                       interrupts = <1>, <3>, <4>, <2>;
-                       cache-block-size = <64>;
-                       cache-level = <2>;
-@@ -378,7 +429,8 @@
-                       clocks = <&syscrg JH7110_SYSCLK_UART0_CORE>,
-                                <&syscrg JH7110_SYSCLK_UART0_APB>;
-                       clock-names = "baudclk", "apb_pclk";
--                      resets = <&syscrg JH7110_SYSRST_UART0_APB>;
-+                      resets = <&syscrg JH7110_SYSRST_UART0_APB>,
-+                               <&syscrg JH7110_SYSRST_UART0_CORE>;
-                       interrupts = <32>;
-                       reg-io-width = <4>;
-                       reg-shift = <2>;
-@@ -391,7 +443,8 @@
-                       clocks = <&syscrg JH7110_SYSCLK_UART1_CORE>,
-                                <&syscrg JH7110_SYSCLK_UART1_APB>;
-                       clock-names = "baudclk", "apb_pclk";
--                      resets = <&syscrg JH7110_SYSRST_UART1_APB>;
-+                      resets = <&syscrg JH7110_SYSRST_UART1_APB>,
-+                               <&syscrg JH7110_SYSRST_UART1_CORE>;
-                       interrupts = <33>;
-                       reg-io-width = <4>;
-                       reg-shift = <2>;
-@@ -404,7 +457,8 @@
-                       clocks = <&syscrg JH7110_SYSCLK_UART2_CORE>,
-                                <&syscrg JH7110_SYSCLK_UART2_APB>;
-                       clock-names = "baudclk", "apb_pclk";
--                      resets = <&syscrg JH7110_SYSRST_UART2_APB>;
-+                      resets = <&syscrg JH7110_SYSRST_UART2_APB>,
-+                               <&syscrg JH7110_SYSRST_UART2_CORE>;
-                       interrupts = <34>;
-                       reg-io-width = <4>;
-                       reg-shift = <2>;
-@@ -513,6 +567,25 @@
-                       status = "disabled";
-               };
-+              spdif: spdif@100a0000 {
-+                      compatible = "starfive,jh7110-spdif";
-+                      reg = <0x0 0x100a0000 0x0 0x1000>;
-+                      clocks = <&syscrg JH7110_SYSCLK_SPDIF_APB>,
-+                               <&syscrg JH7110_SYSCLK_SPDIF_CORE>,
-+                               <&syscrg JH7110_SYSCLK_AUDIO_ROOT>,
-+                               <&syscrg JH7110_SYSCLK_MCLK_INNER>,
-+                               <&mclk_ext>, <&syscrg JH7110_SYSCLK_MCLK>;
-+                      clock-names = "apb", "core",
-+                                    "audroot", "mclk_inner",
-+                                    "mclk_ext", "mclk";
-+                      resets = <&syscrg JH7110_SYSRST_SPDIF_APB>;
-+                      reset-names = "apb";
-+                      interrupts = <84>;
-+                      interrupt-names = "tx";
-+                      #sound-dai-cells = <0>;
-+                      status = "disabled";
-+              };
-+
-               pwmdac: pwmdac@100b0000 {
-                       compatible = "starfive,jh7110-pwmdac";
-                       reg = <0x0 0x100b0000 0x0 0x1000>;
-@@ -526,6 +599,42 @@
-                       status = "disabled";
-               };
-+              pdm: pdm@100d0000 {
-+                      compatible = "starfive,jh7110-pdm";
-+                      reg = <0x0 0x100d0000 0x0 0x1000>;
-+                      reg-names = "pdm";
-+                      clocks = <&syscrg JH7110_SYSCLK_PDM_DMIC>,
-+                               <&syscrg JH7110_SYSCLK_PDM_APB>,
-+                               <&syscrg JH7110_SYSCLK_MCLK>,
-+                               <&mclk_ext>;
-+                      clock-names = "pdm_mclk", "pdm_apb",
-+                                    "clk_mclk", "mclk_ext";
-+                      resets = <&syscrg JH7110_SYSRST_PDM_DMIC>,
-+                               <&syscrg JH7110_SYSRST_PDM_APB>;
-+                      reset-names = "pdm_dmic", "pdm_apb";
-+                      #sound-dai-cells = <0>;
-+                      status = "disabled";
-+              };
-+
-+              i2srx_mst: i2srx_mst@100e0000 {
-+                      compatible = "starfive,jh7110-i2srx-master";
-+                      reg = <0x0 0x100e0000 0x0 0x1000>;
-+                      clocks = <&syscrg JH7110_SYSCLK_I2SRX_BCLK_MST>,
-+                               <&syscrg JH7110_SYSCLK_I2SRX_APB>,
-+                               <&syscrg JH7110_SYSCLK_MCLK>,
-+                               <&syscrg JH7110_SYSCLK_MCLK_INNER>,
-+                               <&mclk_ext>;
-+                      clock-names = "i2sclk", "apb", "mclk",
-+                                    "mclk_inner","mclk_ext";
-+                      resets = <&syscrg JH7110_SYSRST_I2SRX_APB>,
-+                               <&syscrg JH7110_SYSRST_I2SRX_BCLK>;
-+                      dmas = <&dma 24>;
-+                      dma-names = "rx";
-+                      starfive,syscon = <&sys_syscon 0x18 0x2 0x34 0x3FC00 0x24400>;
-+                      #sound-dai-cells = <0>;
-+                      status = "disabled";
-+              };
-+
-               i2srx: i2s@100e0000 {
-                       compatible = "starfive,jh7110-i2srx";
-                       reg = <0x0 0x100e0000 0x0 0x1000>;
-@@ -622,6 +731,26 @@
-                       #reset-cells = <1>;
-               };
-+              xrp: xrp@10230000 {
-+                      compatible = "cdns,xrp";
-+                      dma-coherent;
-+                      reg = <0x0 0x10230000 0x0 0x00010000
-+                             0x0 0x10240000 0x0 0x00010000>;
-+                      clocks = <&stgcrg JH7110_STGCLK_HIFI4_CLK_CORE>;
-+                      clock-names = "core_clk";
-+                      resets = <&stgcrg JH7110_STGRST_HIFI4_CORE>,
-+                               <&stgcrg JH7110_STGRST_HIFI4_AXI>;
-+                      reset-names = "rst_core","rst_axi";
-+                      starfive,stg-syscon = <&stg_syscon>;
-+                      firmware-name = "hifi4_elf";
-+                      #address-cells = <1>;
-+                      #size-cells = <1>;
-+                      ranges = <0x40000000 0x0 0x20000000 0x040000
-+                              0x69c00000 0x0 0x69c00000 0x03000000>;
-+                      status = "disabled";
-+                      dsp@0 {};
-+              };
-+
-               stg_syscon: syscon@10240000 {
-                       compatible = "starfive,jh7110-stg-syscon", "syscon";
-                       reg = <0x0 0x10240000 0x0 0x1000>;
-@@ -633,7 +762,8 @@
-                       clocks = <&syscrg JH7110_SYSCLK_UART3_CORE>,
-                                <&syscrg JH7110_SYSCLK_UART3_APB>;
-                       clock-names = "baudclk", "apb_pclk";
--                      resets = <&syscrg JH7110_SYSRST_UART3_APB>;
-+                      resets = <&syscrg JH7110_SYSRST_UART3_APB>,
-+                               <&syscrg JH7110_SYSRST_UART3_CORE>;
-                       interrupts = <45>;
-                       reg-io-width = <4>;
-                       reg-shift = <2>;
-@@ -646,7 +776,8 @@
-                       clocks = <&syscrg JH7110_SYSCLK_UART4_CORE>,
-                                <&syscrg JH7110_SYSCLK_UART4_APB>;
-                       clock-names = "baudclk", "apb_pclk";
--                      resets = <&syscrg JH7110_SYSRST_UART4_APB>;
-+                      resets = <&syscrg JH7110_SYSRST_UART4_APB>,
-+                               <&syscrg JH7110_SYSRST_UART4_CORE>;
-                       interrupts = <46>;
-                       reg-io-width = <4>;
-                       reg-shift = <2>;
-@@ -659,7 +790,8 @@
-                       clocks = <&syscrg JH7110_SYSCLK_UART5_CORE>,
-                                <&syscrg JH7110_SYSCLK_UART5_APB>;
-                       clock-names = "baudclk", "apb_pclk";
--                      resets = <&syscrg JH7110_SYSRST_UART5_APB>;
-+                      resets = <&syscrg JH7110_SYSRST_UART5_APB>,
-+                               <&syscrg JH7110_SYSRST_UART5_CORE>;
-                       interrupts = <47>;
-                       reg-io-width = <4>;
-                       reg-shift = <2>;
-@@ -919,6 +1051,18 @@
-                                     "ch2", "ch3";
-               };
-+              mailbox_contrl0: mailbox@13060000 {
-+                      compatible = "starfive,mail_box";
-+                      reg = <0x0 0x13060000 0x0 0x0001000>;
-+                      clocks = <&syscrg JH7110_SYSCLK_MAILBOX_APB>;
-+                      clock-names = "clk_apb";
-+                      resets = <&syscrg JH7110_SYSRST_MAILBOX_APB>;
-+                      reset-names = "mbx_rre";
-+                      interrupts = <26 27>;
-+                      #mbox-cells = <2>;
-+                      status = "disabled";
-+              };
-+
-               watchdog@13070000 {
-                       compatible = "starfive,jh7110-wdt";
-                       reg = <0x0 0x13070000 0x0 0x10000>;
-@@ -929,6 +1073,112 @@
-                                <&syscrg JH7110_SYSRST_WDT_CORE>;
-               };
-+              jpu: jpu@13090000 {
-+                      compatible = "starfive,jpu";
-+                      dma-coherent;
-+                      reg = <0x0 0x13090000 0x0 0x300>;
-+                      interrupts = <14>;
-+                      clocks = <&syscrg JH7110_SYSCLK_CODAJ12_AXI>,
-+                               <&syscrg JH7110_SYSCLK_CODAJ12_CORE>,
-+                               <&syscrg JH7110_SYSCLK_CODAJ12_APB>,
-+                               <&syscrg JH7110_SYSCLK_NOC_BUS_VDEC_AXI>,
-+                               <&syscrg JH7110_SYSCLK_VDEC_MAIN>,
-+                               <&syscrg JH7110_SYSCLK_VDEC_JPG>;
-+                      clock-names = "axi_clk", "core_clk", "apb_clk",
-+                                    "noc_bus", "main_clk", "dec_clk";
-+                      resets = <&syscrg JH7110_SYSRST_CODAJ12_AXI>,
-+                               <&syscrg JH7110_SYSRST_CODAJ12_CORE>,
-+                               <&syscrg JH7110_SYSRST_CODAJ12_APB>;
-+                      reset-names = "rst_axi", "rst_core", "rst_apb";
-+                      power-domains = <&pwrc JH7110_PD_VDEC>;
-+                      status = "disabled";
-+              };
-+
-+              vpu_dec: vpu_dec@130a0000 {
-+                      compatible = "starfive,vdec";
-+                      dma-coherent;
-+                      reg = <0x0 0x130a0000 0x0 0x10000>;
-+                      interrupts = <13>;
-+                      clocks = <&syscrg JH7110_SYSCLK_WAVE511_AXI>,
-+                               <&syscrg JH7110_SYSCLK_WAVE511_BPU>,
-+                               <&syscrg JH7110_SYSCLK_WAVE511_VCE>,
-+                               <&syscrg JH7110_SYSCLK_WAVE511_APB>,
-+                               <&syscrg JH7110_SYSCLK_NOC_BUS_VDEC_AXI>,
-+                               <&syscrg JH7110_SYSCLK_VDEC_MAIN>;
-+                      clock-names = "axi_clk", "bpu_clk", "vce_clk",
-+                                    "apb_clk", "noc_bus", "main_clk";
-+                      resets = <&syscrg JH7110_SYSRST_WAVE511_AXI>,
-+                               <&syscrg JH7110_SYSRST_WAVE511_BPU>,
-+                               <&syscrg JH7110_SYSRST_WAVE511_VCE>,
-+                               <&syscrg JH7110_SYSRST_WAVE511_APB>,
-+                               <&syscrg JH7110_SYSRST_AXIMEM0_AXI>;
-+                      reset-names = "rst_axi", "rst_bpu", "rst_vce",
-+                                    "rst_apb", "rst_sram";
-+                      starfive,vdec_noc_ctrl;
-+                      power-domains = <&pwrc JH7110_PD_VDEC>;
-+                      status = "disabled";
-+              };
-+
-+              vpu_enc: vpu_enc@130b0000 {
-+                      compatible = "starfive,venc";
-+                      dma-coherent;
-+                      reg = <0x0 0x130b0000 0x0 0x10000>;
-+                      interrupts = <15>;
-+                      clocks = <&syscrg JH7110_SYSCLK_WAVE420L_AXI>,
-+                               <&syscrg JH7110_SYSCLK_WAVE420L_BPU>,
-+                               <&syscrg JH7110_SYSCLK_WAVE420L_VCE>,
-+                               <&syscrg JH7110_SYSCLK_WAVE420L_APB>,
-+                               <&syscrg JH7110_SYSCLK_NOC_BUS_VENC_AXI>;
-+                      clock-names = "axi_clk", "bpu_clk", "vce_clk",
-+                                    "apb_clk", "noc_bus";
-+                      resets = <&syscrg JH7110_SYSRST_WAVE420L_AXI>,
-+                               <&syscrg JH7110_SYSRST_WAVE420L_BPU>,
-+                               <&syscrg JH7110_SYSRST_WAVE420L_VCE>,
-+                               <&syscrg JH7110_SYSRST_WAVE420L_APB>,
-+                               <&syscrg JH7110_SYSRST_AXIMEM1_AXI>;
-+                      reset-names = "rst_axi", "rst_bpu", "rst_vce",
-+                                    "rst_apb", "rst_sram";
-+                      starfive,venc_noc_ctrl;
-+                      power-domains = <&pwrc JH7110_PD_VENC>;
-+                      status = "disabled";
-+              };
-+
-+              can0: can@130d0000 {
-+                      compatible = "starfive,jh7110-can", "ipms,can";
-+                      reg = <0x0 0x130d0000 0x0 0x1000>;
-+                      interrupts = <112>;
-+                      clocks = <&syscrg JH7110_SYSCLK_CAN0_APB>,
-+                               <&syscrg JH7110_SYSCLK_CAN0_CAN>,
-+                               <&syscrg JH7110_SYSCLK_CAN0_TIMER>;
-+                      clock-names = "apb_clk", "core_clk", "timer_clk";
-+                      resets = <&syscrg JH7110_SYSRST_CAN0_APB>,
-+                               <&syscrg JH7110_SYSRST_CAN0_CORE>,
-+                               <&syscrg JH7110_SYSRST_CAN0_TIMER>;
-+                      reset-names = "rst_apb", "rst_core", "rst_timer";
-+                      frequency = <40000000>;
-+                      starfive,sys-syscon = <&sys_syscon 0x10 0x3 0x8>;
-+                      syscon,can_or_canfd = <0>;
-+                      status = "disabled";
-+              };
-+
-+              can1: can@130e0000 {
-+                      compatible = "starfive,jh7110-can", "ipms,can";
-+                      reg = <0x0 0x130e0000 0x0 0x1000>;
-+                      interrupts = <113>;
-+                      clocks = <&syscrg JH7110_SYSCLK_CAN1_APB>,
-+                               <&syscrg JH7110_SYSCLK_CAN1_CAN>,
-+                               <&syscrg JH7110_SYSCLK_CAN1_TIMER>;
-+                      clock-names = "apb_clk", "core_clk", "timer_clk";
-+                      resets = <&syscrg JH7110_SYSRST_CAN1_APB>,
-+                               <&syscrg JH7110_SYSRST_CAN1_CORE>,
-+                               <&syscrg JH7110_SYSRST_CAN1_TIMER>;
-+                      reset-names = "rst_apb", "rst_core", "rst_timer";
-+                      frequency = <40000000>;
-+                      starfive,sys-syscon = <&sys_syscon 0x88 0x12 0x40000>;
-+                      syscon,can_or_canfd = <0>;
-+                      status = "disabled";
-+              };
-+
-               crypto: crypto@16000000 {
-                       compatible = "starfive,jh7110-crypto";
-                       reg = <0x0 0x16000000 0x0 0x4000>;
-@@ -1119,6 +1369,42 @@
-                       #power-domain-cells = <1>;
-               };
-+              rtc: rtc@17040000 {
-+                      compatible = "starfive,jh7110-rtc";
-+                      reg = <0x0 0x17040000 0x0 0x10000>;
-+                      interrupts = <10>, <11>, <12>;
-+                      interrupt-names = "rtc_ms_pulse", "rtc_sec_pulse", "rtc";
-+                      clocks = <&aoncrg JH7110_AONCLK_RTC_APB>,
-+                               <&aoncrg JH7110_AONCLK_RTC_CAL>;
-+                      clock-names = "pclk", "cal_clk";
-+                      resets = <&aoncrg JH7110_AONRST_RTC_32K>,
-+                               <&aoncrg JH7110_AONRST_RTC_APB>,
-+                               <&aoncrg JH7110_AONRST_RTC_CAL>;
-+                      reset-names = "rst_osc", "rst_apb", "rst_cal";
-+                      rtc,cal-clock-freq = <1000000>;
-+              };
-+
-+              gpu: gpu@18000000 {
-+                      compatible = "img-gpu";
-+                      reg = <0x0 0x18000000 0x0 0x100000>,
-+                              <0x0 0x130C000 0x0 0x10000>;
-+                      clocks = <&syscrg JH7110_SYSCLK_GPU_CORE>,
-+                               <&syscrg JH7110_SYSCLK_GPU_APB>,
-+                               <&syscrg JH7110_SYSCLK_GPU_RTC_TOGGLE>,
-+                               <&syscrg JH7110_SYSCLK_GPU_CORE_CLK>,
-+                               <&syscrg JH7110_SYSCLK_GPU_SYS_CLK>,
-+                               <&syscrg JH7110_SYSCLK_NOC_BUS_GPU_AXI>;
-+                      clock-names = "clk_bv", "clk_apb", "clk_rtc",
-+                                      "clk_core", "clk_sys", "clk_axi";
-+                      resets = <&syscrg JH7110_SYSRST_GPU_APB>,
-+                               <&syscrg JH7110_SYSRST_GPU_DOMA>;
-+                      reset-names = "rst_apb", "rst_doma";
-+                      power-domains = <&pwrc JH7110_PD_GPUA>;
-+                      interrupts = <82>;
-+                      current-clock = <8000000>;
-+                      status = "disabled";
-+              };
-+
-               csi2rx: csi-bridge@19800000 {
-                       compatible = "starfive,jh7110-csi2rx";
-                       reg = <0x0 0x19800000 0x0 0x10000>;
-@@ -1145,6 +1431,67 @@
-                       status = "disabled";
-               };
-+              vin_sysctl: vin_sysctl@19800000 {
-+                      compatible = "starfive,jh7110-vin";
-+                      reg = <0x0 0x19800000 0x0 0x10000>,
-+                              <0x0 0x19810000 0x0 0x10000>,
-+                              <0x0 0x19820000 0x0 0x10000>,
-+                              <0x0 0x19840000 0x0 0x10000>,
-+                              <0x0 0x19870000 0x0 0x30000>,
-+                              <0x0 0x11840000 0x0 0x10000>,
-+                              <0x0 0x17030000 0x0 0x10000>,
-+                              <0x0 0x13020000 0x0 0x10000>;
-+                      reg-names = "csi2rx", "vclk", "vrst", "sctrl",
-+                              "isp", "trst", "pmu", "syscrg";
-+                      clocks = <&ispcrg JH7110_ISPCLK_DOM4_APB_FUNC>,
-+                               <&ispcrg JH7110_ISPCLK_VIN_APB>,
-+                               <&ispcrg JH7110_ISPCLK_VIN_SYS>,
-+                               <&ispcrg JH7110_ISPCLK_ISPV2_TOP_WRAPPER_C>,
-+                               <&ispcrg JH7110_ISPCLK_DVP_INV>,
-+                               <&ispcrg JH7110_ISPCLK_VIN_P_AXI_WR>,
-+                               <&ispcrg JH7110_ISPCLK_MIPI_RX0_PXL>,
-+                               <&ispcrg JH7110_ISPCLK_VIN_PIXEL_IF0>,
-+                               <&ispcrg JH7110_ISPCLK_VIN_PIXEL_IF1>,
-+                               <&ispcrg JH7110_ISPCLK_VIN_PIXEL_IF2>,
-+                               <&ispcrg JH7110_ISPCLK_VIN_PIXEL_IF3>,
-+                               <&ispcrg JH7110_ISPCLK_M31DPHY_CFG_IN>,
-+                               <&ispcrg JH7110_ISPCLK_M31DPHY_REF_IN>,
-+                               <&ispcrg JH7110_ISPCLK_M31DPHY_TX_ESC_LAN0>,
-+                               <&syscrg JH7110_SYSCLK_ISP_TOP_CORE>,
-+                               <&syscrg JH7110_SYSCLK_ISP_TOP_AXI>;
-+                      clock-names = "clk_apb_func", "clk_pclk", "clk_sys_clk",
-+                              "clk_wrapper_clk_c", "clk_dvp_inv", "clk_axiwr",
-+                              "clk_mipi_rx0_pxl", "clk_pixel_clk_if0",
-+                              "clk_pixel_clk_if1", "clk_pixel_clk_if2",
-+                              "clk_pixel_clk_if3", "clk_m31dphy_cfgclk_in",
-+                              "clk_m31dphy_refclk_in", "clk_m31dphy_txclkesc_lan0",
-+                              "clk_ispcore_2x", "clk_isp_axi";
-+                      resets = <&ispcrg JH7110_ISPRST_ISPV2_TOP_WRAPPER_P>,
-+                               <&ispcrg JH7110_ISPRST_ISPV2_TOP_WRAPPER_C>,
-+                               <&ispcrg JH7110_ISPRST_VIN_APB>,
-+                               <&ispcrg JH7110_ISPRST_VIN_SYS>,
-+                               <&ispcrg JH7110_ISPRST_VIN_P_AXI_RD>,
-+                               <&ispcrg JH7110_ISPRST_VIN_P_AXI_WR>,
-+                               <&ispcrg JH7110_ISPRST_VIN_PIXEL_IF0>,
-+                               <&ispcrg JH7110_ISPRST_VIN_PIXEL_IF1>,
-+                               <&ispcrg JH7110_ISPRST_VIN_PIXEL_IF2>,
-+                               <&ispcrg JH7110_ISPRST_VIN_PIXEL_IF3>,
-+                               <&ispcrg JH7110_ISPRST_M31DPHY_HW>,
-+                               <&ispcrg JH7110_ISPRST_M31DPHY_B09_AON>,
-+                               <&syscrg JH7110_SYSRST_ISP_TOP>,
-+                               <&syscrg JH7110_SYSRST_ISP_TOP_AXI>;
-+                      reset-names = "rst_wrapper_p", "rst_wrapper_c", "rst_pclk",
-+                              "rst_sys_clk", "rst_axird", "rst_axiwr", "rst_pixel_clk_if0",
-+                              "rst_pixel_clk_if1", "rst_pixel_clk_if2", "rst_pixel_clk_if3",
-+                              "rst_m31dphy_hw", "rst_m31dphy_b09_always_on",
-+                              "rst_isp_top_n", "rst_isp_top_axi";
-+                      starfive,aon-syscon = <&aon_syscon 0x00>;
-+                      power-domains = <&pwrc JH7110_PD_ISP>;
-+                      /* irq nr: vin, isp, isp_csi, isp_scd, isp_csiline */
-+                      interrupts = <92 87 88 89 90>;
-+                      status = "disabled";
-+              };
-+
-               ispcrg: clock-controller@19810000 {
-                       compatible = "starfive,jh7110-ispcrg";
-                       reg = <0x0 0x19810000 0x0 0x10000>;
-@@ -1175,6 +1522,66 @@
-                       #phy-cells = <0>;
-               };
-+              dc8200: dc8200@29400000 {
-+                      compatible = "starfive,jh7110-dc8200","verisilicon,dc8200";
-+                      verisilicon,dss-syscon = <&dssctrl>;//20220624 panel syscon
-+                      reg = <0x0 0x29400000 0x0 0x100>,
-+                            <0x0 0x29400800 0x0 0x2000>,
-+                            <0x0 0x17030000 0x0 0x1000>;
-+                      interrupts = <95>;
-+                      clocks = <&syscrg JH7110_SYSCLK_NOC_BUS_DISP_AXI>,
-+                               <&syscrg JH7110_SYSCLK_VOUT_SRC>,
-+                               <&syscrg JH7110_SYSCLK_VOUT_TOP_AXI>,
-+                               <&syscrg JH7110_SYSCLK_VOUT_TOP_AHB>,
-+                               <&voutcrg JH7110_VOUTCLK_DC8200_PIX0>,
-+                               <&voutcrg JH7110_VOUTCLK_DC8200_PIX1>,
-+                               <&voutcrg JH7110_VOUTCLK_DC8200_AXI>,
-+                               <&voutcrg JH7110_VOUTCLK_DC8200_CORE>,
-+                               <&voutcrg JH7110_VOUTCLK_DC8200_AHB>,
-+                               <&syscrg JH7110_SYSCLK_VOUT_TOP_AXI>,
-+                               <&voutcrg JH7110_VOUTCLK_DOM_VOUT_TOP_LCD>,
-+                               <&hdmitx0_pixelclk>,
-+                               <&voutcrg JH7110_VOUTCLK_DC8200_PIX>;
-+                      clock-names = "noc_disp","vout_src",
-+                         "top_vout_axi","top_vout_ahb",
-+                         "pix_clk","vout_pix1",
-+                         "axi_clk","core_clk","vout_ahb",
-+                         "vout_top_axi","vout_top_lcd","hdmitx0_pixelclk","dc8200_pix0";
-+                      resets = <&syscrg JH7110_SYSRST_VOUT_TOP_SRC>,
-+                               <&voutcrg JH7110_VOUTRST_DC8200_AXI>,
-+                               <&voutcrg JH7110_VOUTRST_DC8200_AHB>,
-+                               <&voutcrg JH7110_VOUTRST_DC8200_CORE>,
-+                               <&syscrg JH7110_SYSRST_NOC_BUS_DISP_AXI>;
-+                      reset-names = "rst_vout_src","rst_axi","rst_ahb","rst_core",
-+                                      "rst_noc_disp";
-+                      status = "disabled";
-+              };
-+
-+              hdmi: hdmi@29590000 {
-+                      compatible = "starfive,jh7110-hdmi","inno,hdmi";
-+                      reg = <0x0 0x29590000 0x0 0x4000>;
-+                      interrupts = <99>;
-+                      /*interrupts = <GIC_SPI 45 IRQ_TYPE_LEVEL_HIGH>;*/
-+                      /*clocks = <&cru  PCLK_HDMI>;*/
-+                      /*clock-names = "pclk";*/
-+                      /*pinctrl-names = "default";*/
-+                      /*pinctrl-0 = <&hdmi_ctl>;*/
-+                      clocks = <&voutcrg JH7110_VOUTCLK_HDMI_TX_SYS>,
-+                               <&voutcrg JH7110_VOUTCLK_HDMI_TX_MCLK>,
-+                               <&voutcrg JH7110_VOUTCLK_HDMI_TX_BCLK>,
-+                               <&hdmitx0_pixelclk>;
-+                      clock-names = "sysclk", "mclk","bclk","pclk";
-+                      resets = <&voutcrg JH7110_VOUTRST_HDMI_TX_HDMI>;
-+                      reset-names = "hdmi_tx";
-+                      #sound-dai-cells = <0>;
-+                      status = "disabled";
-+              };
-+
-+              dssctrl: dssctrl@295B0000 {
-+                      compatible = "starfive,jh7110-dssctrl","verisilicon,dss-ctrl", "syscon";
-+                      reg = <0 0x295B0000 0 0x90>;
-+              };
-+
-               voutcrg: clock-controller@295c0000 {
-                       compatible = "starfive,jh7110-voutcrg";
-                       reg = <0x0 0x295c0000 0x0 0x10000>;
-@@ -1193,6 +1600,67 @@
-                       power-domains = <&pwrc JH7110_PD_VOUT>;
-               };
-+              mipi_dsi: mipi@295d0000 {
-+                      compatible = "starfive,jh7110-mipi_dsi","cdns,dsi";
-+                      reg = <0x0 0x295d0000 0x0 0x10000>;
-+                      interrupts = <98>;
-+                      reg-names = "dsi";
-+                      clocks = <&voutcrg JH7110_VOUTCLK_DSITX_SYS>,
-+                               <&voutcrg JH7110_VOUTCLK_DSITX_APB>,
-+                               <&voutcrg JH7110_VOUTCLK_DSITX_TXESC>,
-+                               <&voutcrg JH7110_VOUTCLK_DSITX_DPI>;
-+                      clock-names = "dpi", "apb", "txesc", "sys";
-+                      resets = <&voutcrg JH7110_VOUTRST_DSITX_DPI>,
-+                               <&voutcrg JH7110_VOUTRST_DSITX_APB>,
-+                               <&voutcrg JH7110_VOUTRST_DSITX_RXESC>,
-+                               <&voutcrg JH7110_VOUTRST_DSITX_SYS>,
-+                               <&voutcrg JH7110_VOUTRST_DSITX_TXBYTEHS>,
-+                               <&voutcrg JH7110_VOUTRST_DSITX_TXESC>;
-+                      reset-names = "dsi_dpi", "dsi_apb", "dsi_rxesc",
-+                                      "dsi_sys", "dsi_txbytehs", "dsi_txesc";
-+                      phys = <&mipi_dphy>;
-+                      phy-names = "dphy";
-+                      status = "disabled";
-+              };
-+
-+              mipi_dphy: mipi-dphy@295e0000{
-+                      compatible = "starfive,jh7110-mipi-dphy-tx","m31,mipi-dphy-tx";
-+                      reg = <0x0 0x295e0000 0x0 0x10000>;
-+                      clocks = <&voutcrg JH7110_VOUTCLK_MIPITX_DPHY_TXESC>;
-+                      clock-names = "dphy_txesc";
-+                      resets = <&voutcrg JH7110_VOUTRST_MIPITX_DPHY_SYS>,
-+                               <&voutcrg JH7110_VOUTRST_MIPITX_DPHY_TXBYTEHS>;
-+                      reset-names = "dphy_sys", "dphy_txbytehs";
-+                      #phy-cells = <0>;
-+                      status = "disabled";
-+              };
-+
-+              co_process: e24@6e210000 {
-+                      compatible = "starfive,e24";
-+                      dma-coherent;
-+                      reg = <0x0 0x6e210000 0x0 0x00001000>,
-+                              <0x0 0x6e211000 0x0 0x0003f000>;
-+                      reg-names = "ecmd", "espace";
-+                      clocks = <&stgcrg JH7110_STGCLK_E2_RTC>,
-+                               <&stgcrg JH7110_STGCLK_E2_CORE>,
-+                               <&stgcrg JH7110_STGCLK_E2_DBG>;
-+                      clock-names = "clk_rtc", "clk_core", "clk_dbg";
-+                      resets = <&stgcrg JH7110_STGRST_E24_CORE>;
-+                      reset-names = "e24_core";
-+                      starfive,stg-syscon = <&stg_syscon>;
-+                      interrupt-parent = <&plic>;
-+                      firmware-name = "e24_elf";
-+                      irq-mode = <1>;
-+                      mbox-names = "tx", "rx";
-+                      mboxes = <&mailbox_contrl0 0 2>,
-+                               <&mailbox_contrl0 2 0>;
-+                      #address-cells = <1>;
-+                      #size-cells = <1>;
-+                      ranges = <0x6ce00000 0x0 0x6ce00000 0x1600000>;
-+                      status = "disabled";
-+                      dsp@0 {};
-+              };
-+
-               pcie0: pcie@940000000 {
-                       compatible = "starfive,jh7110-pcie";
-                       reg = <0x9 0x40000000 0x0 0x1000000>,
diff --git a/target/linux/starfive/patches-6.6/0057-riscv-dts-starfive-Add-JH7110-EVB-expanded-device-tr.patch b/target/linux/starfive/patches-6.6/0057-riscv-dts-starfive-Add-JH7110-EVB-expanded-device-tr.patch
deleted file mode 100644 (file)
index 7a23bf9..0000000
+++ /dev/null
@@ -1,728 +0,0 @@
-From cae7550054ca0cd940bbc1501ae5611f5d2957e6 Mon Sep 17 00:00:00 2001
-From: Hal Feng <hal.feng@starfivetech.com>
-Date: Wed, 20 Sep 2023 14:53:22 +0800
-Subject: [PATCH 057/116] riscv: dts: starfive: Add JH7110 EVB expanded device
- tree
-
-Add JH7110 EVB expanded device tree.
-The code is ported from tag JH7110_SDK_6.1_v5.11.3
-
-Signed-off-by: Hal Feng <hal.feng@starfivetech.com>
----
- arch/riscv/boot/dts/starfive/Makefile         |  11 +-
- .../starfive/jh7110-evb-can-pdm-pwmdac.dts    | 102 ++++++++++++++++
- .../dts/starfive/jh7110-evb-dvp-rgb2hdmi.dts  |  37 ++++++
- .../dts/starfive/jh7110-evb-i2s-ac108.dts     |  72 ++++++++++++
- .../dts/starfive/jh7110-evb-pcie-i2s-sd.dts   | 111 ++++++++++++++++++
- .../dts/starfive/jh7110-evb-spi-uart2.dts     |  65 ++++++++++
- .../starfive/jh7110-evb-uart1-rgb2hdmi.dts    |  57 +++++++++
- .../starfive/jh7110-evb-uart4-emmc-spdif.dts  |  78 ++++++++++++
- .../starfive/jh7110-evb-uart5-pwm-i2c-tdm.dts |  95 +++++++++++++++
- .../dts/starfive/jh7110-evb-usbdevice.dts     |  35 ++++++
- 10 files changed, 662 insertions(+), 1 deletion(-)
- create mode 100644 arch/riscv/boot/dts/starfive/jh7110-evb-can-pdm-pwmdac.dts
- create mode 100644 arch/riscv/boot/dts/starfive/jh7110-evb-dvp-rgb2hdmi.dts
- create mode 100644 arch/riscv/boot/dts/starfive/jh7110-evb-i2s-ac108.dts
- create mode 100644 arch/riscv/boot/dts/starfive/jh7110-evb-pcie-i2s-sd.dts
- create mode 100644 arch/riscv/boot/dts/starfive/jh7110-evb-spi-uart2.dts
- create mode 100644 arch/riscv/boot/dts/starfive/jh7110-evb-uart1-rgb2hdmi.dts
- create mode 100644 arch/riscv/boot/dts/starfive/jh7110-evb-uart4-emmc-spdif.dts
- create mode 100644 arch/riscv/boot/dts/starfive/jh7110-evb-uart5-pwm-i2c-tdm.dts
- create mode 100644 arch/riscv/boot/dts/starfive/jh7110-evb-usbdevice.dts
-
---- a/arch/riscv/boot/dts/starfive/Makefile
-+++ b/arch/riscv/boot/dts/starfive/Makefile
-@@ -12,4 +12,13 @@ dtb-$(CONFIG_ARCH_STARFIVE) += jh7100-st
- dtb-$(CONFIG_ARCH_STARFIVE) += jh7110-starfive-visionfive-2-v1.2a.dtb
- dtb-$(CONFIG_ARCH_STARFIVE) += jh7110-starfive-visionfive-2-v1.3b.dtb
--dtb-$(CONFIG_ARCH_STARFIVE) += jh7110-evb.dtb
-+dtb-$(CONFIG_ARCH_STARFIVE) += jh7110-evb.dtb                 \
-+                             jh7110-evb-pcie-i2s-sd.dtb       \
-+                             jh7110-evb-spi-uart2.dtb         \
-+                             jh7110-evb-uart4-emmc-spdif.dtb  \
-+                             jh7110-evb-uart5-pwm-i2c-tdm.dtb \
-+                             jh7110-evb-dvp-rgb2hdmi.dtb      \
-+                             jh7110-evb-can-pdm-pwmdac.dtb    \
-+                             jh7110-evb-i2s-ac108.dtb         \
-+                             jh7110-evb-usbdevice.dtb         \
-+                             jh7110-evb-uart1-rgb2hdmi.dtb
---- /dev/null
-+++ b/arch/riscv/boot/dts/starfive/jh7110-evb-can-pdm-pwmdac.dts
-@@ -0,0 +1,102 @@
-+// SPDX-License-Identifier: GPL-2.0 OR MIT
-+/*
-+ * Copyright (C) 2022 StarFive Technology Co., Ltd.
-+ */
-+
-+/dts-v1/;
-+#include "jh7110-evb.dtsi"
-+
-+/ {
-+      model = "StarFive JH7110 EVB";
-+      compatible = "starfive,jh7110-evb", "starfive,jh7110";
-+
-+      sound2: snd-card2 {
-+              compatible = "simple-audio-card";
-+              #address-cells = <1>;
-+              #size-cells = <0>;
-+
-+              simple-audio-card,name = "StarFive-PDM-Sound-Card";
-+              simple-audio-card,dai-link@0 {
-+                      reg = <0>;
-+                      format = "i2s";
-+                      bitclock-master = <&dailink_master>;
-+                      frame-master = <&dailink_master>;
-+
-+                      dailink_master:cpu {
-+                              sound-dai = <&i2srx_mst>;
-+                      };
-+
-+                      dailink_slave:codec {
-+                              sound-dai = <&pdm>;
-+                      };
-+              };
-+      };
-+
-+      pwmdac_codec: pwmdac-codec {
-+              compatible = "linux,spdif-dit";
-+              #sound-dai-cells = <0>;
-+      };
-+
-+      sound3: snd-card3 {
-+              compatible = "simple-audio-card";
-+              #address-cells = <1>;
-+              #size-cells = <0>;
-+
-+              simple-audio-card,name = "StarFive-PWMDAC-Sound-Card";
-+              simple-audio-card,dai-link@0 {
-+                      reg = <0>;
-+                      format = "left_j";
-+                      bitclock-master = <&sndcpu0>;
-+                      frame-master = <&sndcpu0>;
-+
-+                      sndcpu0: cpu {
-+                              sound-dai = <&pwmdac>;
-+                      };
-+
-+                      codec {
-+                              sound-dai = <&pwmdac_codec>;
-+                      };
-+              };
-+      };
-+};
-+
-+&mmc0 {
-+      assigned-clocks = <&syscrg JH7110_SYSCLK_SDIO0_SDCARD>;
-+      assigned-clock-rates = <50000000>;
-+      pinctrl-names = "default";
-+      pinctrl-0 = <&sdcard0_pins>;
-+      max-frequency = <100000000>;
-+      card-detect-delay = <300>;
-+      bus-width = <4>;
-+      broken-cd;
-+      post-power-on-delay-ms = <200>;
-+      status = "okay";
-+};
-+
-+&usb0 {
-+      status = "okay";
-+};
-+
-+&pcie1 {
-+      status = "okay";
-+};
-+
-+&can0 {
-+      status = "okay";
-+};
-+
-+&can1 {
-+      status = "okay";
-+};
-+
-+&i2srx_mst {
-+      status = "okay";
-+};
-+
-+&pwmdac {
-+      status = "okay";
-+};
-+
-+&pdm {
-+      status = "okay";
-+};
---- /dev/null
-+++ b/arch/riscv/boot/dts/starfive/jh7110-evb-dvp-rgb2hdmi.dts
-@@ -0,0 +1,37 @@
-+// SPDX-License-Identifier: GPL-2.0 OR MIT
-+/*
-+ * Copyright (C) 2022 StarFive Technology Co., Ltd.
-+ */
-+
-+/dts-v1/;
-+#include "jh7110-evb.dtsi"
-+
-+/ {
-+      model = "StarFive JH7110 EVB";
-+      compatible = "starfive,jh7110-evb", "starfive,jh7110";
-+};
-+
-+&vin_sysctl {
-+      pinctrl-names = "default";
-+      pinctrl-0 = <&dvp_pins>;
-+};
-+
-+&rgb_output {
-+      status = "okay";
-+};
-+
-+&tda988x_pin {
-+      status = "okay";
-+};
-+
-+&dsi_output {
-+      status = "disabled";
-+};
-+
-+&mipi_dsi {
-+      status = "disabled";
-+};
-+
-+&mipi_dphy {
-+      status = "disabled";
-+};
---- /dev/null
-+++ b/arch/riscv/boot/dts/starfive/jh7110-evb-i2s-ac108.dts
-@@ -0,0 +1,72 @@
-+// SPDX-License-Identifier: GPL-2.0 OR MIT
-+/*
-+ * Copyright (C) 2022 StarFive Technology Co., Ltd.
-+ */
-+
-+/dts-v1/;
-+#include "jh7110-evb.dtsi"
-+
-+/ {
-+      model = "StarFive JH7110 EVB";
-+      compatible = "starfive,jh7110-evb", "starfive,jh7110";
-+
-+      /* i2s + ac108 */
-+      sound0: snd-card0 {
-+              compatible = "simple-audio-card";
-+              #address-cells = <1>;
-+              #size-cells = <0>;
-+
-+              simple-audio-card,name = "StarFive-AC108-Sound-Card";
-+              simple-audio-card,dai-link@0 {
-+                      reg = <0>;
-+                      format = "i2s";
-+                      bitclock-master = <&sndcodec1>;
-+                      frame-master = <&sndcodec1>;
-+
-+                      widgets = "Microphone", "Mic Jack",
-+                                "Line", "Line In",
-+                                "Line", "Line Out",
-+                                "Speaker", "Speaker",
-+                                "Headphone", "Headphone Jack";
-+                      routing = "Headphone Jack", "HP_L",
-+                                "Headphone Jack", "HP_R",
-+                                "Speaker", "SPK_LP",
-+                                "Speaker", "SPK_LN",
-+                                "LINPUT1", "Mic Jack",
-+                                "LINPUT3", "Mic Jack",
-+                                "RINPUT1", "Mic Jack",
-+                                "RINPUT2", "Mic Jack";
-+
-+                      cpu {
-+                              sound-dai = <&i2srx>;
-+                      };
-+
-+                      sndcodec1: codec {
-+                              sound-dai = <&ac108>;
-+                              clocks = <&ac108_mclk>;
-+                              clock-names = "mclk";
-+                      };
-+              };
-+      };
-+};
-+
-+&mmc0 {
-+      assigned-clocks = <&syscrg JH7110_SYSCLK_SDIO0_SDCARD>;
-+      assigned-clock-rates = <50000000>;
-+      pinctrl-names = "default";
-+      pinctrl-0 = <&sdcard0_pins>;
-+      max-frequency = <100000000>;
-+      card-detect-delay = <300>;
-+      bus-width = <4>;
-+      broken-cd;
-+      post-power-on-delay-ms = <200>;
-+      status = "okay";
-+};
-+
-+&i2c0 {
-+      status = "okay";
-+};
-+
-+&i2srx {
-+      status = "okay";
-+};
---- /dev/null
-+++ b/arch/riscv/boot/dts/starfive/jh7110-evb-pcie-i2s-sd.dts
-@@ -0,0 +1,111 @@
-+// SPDX-License-Identifier: GPL-2.0 OR MIT
-+/*
-+ * Copyright (C) 2022 StarFive Technology Co., Ltd.
-+ */
-+
-+/dts-v1/;
-+#include "jh7110-evb.dtsi"
-+
-+/ {
-+      model = "StarFive JH7110 EVB";
-+      compatible = "starfive,jh7110-evb", "starfive,jh7110";
-+
-+      /* i2s + wm8960 */
-+      sound6: snd-card6 {
-+              compatible = "simple-audio-card";
-+              #address-cells = <1>;
-+              #size-cells = <0>;
-+
-+              simple-audio-card,name = "StarFive-WM8960-Sound-Card";
-+              simple-audio-card,dai-link@0 {
-+                      reg = <0>;
-+                      status = "okay";
-+                      format = "i2s";
-+                      bitclock-master = <&sndcodec1>;
-+                      frame-master = <&sndcodec1>;
-+
-+                      widgets = "Microphone", "Mic Jack",
-+                                "Line", "Line In",
-+                                "Line", "Line Out",
-+                                "Speaker", "Speaker",
-+                                "Headphone", "Headphone Jack";
-+                      routing = "Headphone Jack", "HP_L",
-+                                "Headphone Jack", "HP_R",
-+                                "Speaker", "SPK_LP",
-+                                "Speaker", "SPK_LN",
-+                                "LINPUT1", "Mic Jack",
-+                                "LINPUT3", "Mic Jack",
-+                                "RINPUT1", "Mic Jack",
-+                                "RINPUT2", "Mic Jack";
-+                      cpu0 {
-+                              sound-dai = <&i2srx>;
-+                      };
-+                      cpu1 {
-+                              sound-dai = <&i2stx1>;
-+                      };
-+
-+                      sndcodec1:codec {
-+                              sound-dai = <&wm8960>;
-+                              clocks = <&wm8960_mclk>;
-+                              clock-names = "mclk";
-+                      };
-+              };
-+      };
-+};
-+
-+&mmc0 {
-+      assigned-clocks = <&syscrg JH7110_SYSCLK_SDIO0_SDCARD>;
-+      assigned-clock-rates = <50000000>;
-+      pinctrl-names = "default";
-+      pinctrl-0 = <&sdcard0_pins>;
-+      max-frequency = <100000000>;
-+      card-detect-delay = <300>;
-+      bus-width = <4>;
-+      broken-cd;
-+      post-power-on-delay-ms = <200>;
-+      status = "okay";
-+};
-+
-+&pcie1 {
-+      status = "okay";
-+};
-+
-+&pcie0 {
-+      status = "okay";
-+};
-+
-+&uart3 {
-+      status = "okay";
-+};
-+
-+&i2c0 {
-+      status = "okay";
-+};
-+
-+&usb0 {
-+      clocks = <&stgcrg JH7110_STGCLK_USB0_LPM>,
-+               <&stgcrg JH7110_STGCLK_USB0_STB>,
-+               <&stgcrg JH7110_STGCLK_USB0_APB>,
-+               <&stgcrg JH7110_STGCLK_USB0_AXI>,
-+               <&stgcrg JH7110_STGCLK_USB0_UTMI_APB>;
-+      clock-names = "lpm", "stb", "apb", "axi", "utmi_apb";
-+      resets = <&stgcrg JH7110_STGRST_USB0_PWRUP>,
-+               <&stgcrg JH7110_STGRST_USB0_APB>,
-+               <&stgcrg JH7110_STGRST_USB0_AXI>,
-+               <&stgcrg JH7110_STGRST_USB0_UTMI_APB>;
-+      reset-names = "pwrup", "apb", "axi", "utmi_apb";
-+      dr_mode = "host"; /*host or peripheral*/
-+      starfive,usb2-only;
-+      pinctrl-names = "default";
-+      pinctrl-0 = <&usb_pins>;
-+      status = "okay";
-+};
-+
-+&i2srx {
-+      status = "okay";
-+};
-+
-+&i2stx1 {
-+      status = "okay";
-+};
-+
---- /dev/null
-+++ b/arch/riscv/boot/dts/starfive/jh7110-evb-spi-uart2.dts
-@@ -0,0 +1,65 @@
-+// SPDX-License-Identifier: GPL-2.0 OR MIT
-+/*
-+ * Copyright (C) 2022 StarFive Technology Co., Ltd.
-+ */
-+
-+/dts-v1/;
-+#include "jh7110-evb.dtsi"
-+
-+/ {
-+      model = "StarFive JH7110 EVB";
-+      compatible = "starfive,jh7110-evb", "starfive,jh7110";
-+};
-+
-+&mmc0 {
-+      assigned-clocks = <&syscrg JH7110_SYSCLK_SDIO0_SDCARD>;
-+      assigned-clock-rates = <50000000>;
-+      pinctrl-names = "default";
-+      pinctrl-0 = <&sdcard0_pins>;
-+      max-frequency = <100000000>;
-+      card-detect-delay = <300>;
-+      bus-width = <4>;
-+      broken-cd;
-+      post-power-on-delay-ms = <200>;
-+      status = "okay";
-+};
-+
-+&usb0 {
-+      status = "okay";
-+};
-+
-+&pcie1 {
-+      status = "okay";
-+};
-+
-+&uart2 {
-+      status = "okay";
-+};
-+
-+&spi0 {
-+      status = "okay";
-+};
-+
-+&spi1 {
-+      status = "okay";
-+};
-+
-+&spi2 {
-+      status = "okay";
-+};
-+
-+&spi3 {
-+      status = "okay";
-+};
-+
-+&spi4 {
-+      status = "okay";
-+};
-+
-+&spi5 {
-+      status = "okay";
-+};
-+
-+&spi6 {
-+      status = "okay";
-+};
---- /dev/null
-+++ b/arch/riscv/boot/dts/starfive/jh7110-evb-uart1-rgb2hdmi.dts
-@@ -0,0 +1,57 @@
-+// SPDX-License-Identifier: GPL-2.0 OR MIT
-+/*
-+ * Copyright (C) 2022 StarFive Technology Co., Ltd.
-+ */
-+
-+/dts-v1/;
-+#include "jh7110-evb.dtsi"
-+
-+/ {
-+      model = "StarFive JH7110 EVB";
-+      compatible = "starfive,jh7110-evb", "starfive,jh7110";
-+};
-+
-+&mmc0 {
-+      assigned-clocks = <&syscrg JH7110_SYSCLK_SDIO0_SDCARD>;
-+      assigned-clock-rates = <50000000>;
-+      pinctrl-names = "default";
-+      pinctrl-0 = <&sdcard0_pins>;
-+      max-frequency = <100000000>;
-+      card-detect-delay = <300>;
-+      bus-width = <4>;
-+      broken-cd;
-+      post-power-on-delay-ms = <200>;
-+      status = "okay";
-+};
-+
-+&usb0 {
-+      status = "okay";
-+};
-+
-+&pcie1 {
-+      status = "okay";
-+};
-+
-+&uart1 {
-+      status = "okay";
-+};
-+
-+&rgb_output {
-+      status = "okay";
-+};
-+
-+&tda988x_pin {
-+      status = "okay";
-+};
-+
-+&dsi_output {
-+      status = "disabled";
-+};
-+
-+&mipi_dsi {
-+      status = "disabled";
-+};
-+
-+&mipi_dphy {
-+      status = "disabled";
-+};
---- /dev/null
-+++ b/arch/riscv/boot/dts/starfive/jh7110-evb-uart4-emmc-spdif.dts
-@@ -0,0 +1,78 @@
-+// SPDX-License-Identifier: GPL-2.0 OR MIT
-+/*
-+ * Copyright (C) 2022 StarFive Technology Co., Ltd.
-+ */
-+
-+/dts-v1/;
-+#include "jh7110-evb.dtsi"
-+
-+/ {
-+      model = "StarFive JH7110 EVB";
-+      compatible = "starfive,jh7110-evb", "starfive,jh7110";
-+
-+      spdif_transmitter: spdif_transmitter {
-+              compatible = "linux,spdif-dit";
-+              #sound-dai-cells = <0>;
-+      };
-+
-+      sound4: snd-card4 {
-+              compatible = "simple-audio-card";
-+              #address-cells = <1>;
-+              #size-cells = <0>;
-+
-+              simple-audio-card,name = "StarFive-SPDIF-Sound-Card";
-+              simple-audio-card,dai-link@0 {
-+                      reg = <0>;
-+                      format = "left_j";
-+                      bitclock-master = <&sndcpu0>;
-+                      frame-master = <&sndcpu0>;
-+
-+                      sndcpu0: cpu {
-+                              sound-dai = <&spdif>;
-+                      };
-+
-+                      codec {
-+                              sound-dai = <&spdif_transmitter>;
-+                      };
-+              };
-+      };
-+};
-+
-+&usb0 {
-+      status = "okay";
-+};
-+
-+&pcie1 {
-+      status = "okay";
-+};
-+
-+&uart4 {
-+      status = "okay";
-+};
-+
-+&mmc0 {
-+      assigned-clocks = <&syscrg JH7110_SYSCLK_SDIO0_SDCARD>;
-+      assigned-clock-rates = <50000000>;
-+      pinctrl-names = "default";
-+      pinctrl-0 = <&emmc0_pins>;
-+      max-frequency = <100000000>;
-+      card-detect-delay = <300>;
-+      bus-width = <8>;
-+      cap-mmc-highspeed;
-+      mmc-hs200-1_8v;
-+      non-removable;
-+      cap-mmc-hw-reset;
-+      board-is-evb;
-+      post-power-on-delay-ms = <200>;
-+      status = "okay";
-+};
-+
-+&pwm {
-+      pinctrl-names = "default";
-+      pinctrl-0 = <&pwm_ch6to7_pins>;
-+      status = "okay";
-+};
-+
-+&spdif {
-+      status = "okay";
-+};
---- /dev/null
-+++ b/arch/riscv/boot/dts/starfive/jh7110-evb-uart5-pwm-i2c-tdm.dts
-@@ -0,0 +1,95 @@
-+// SPDX-License-Identifier: GPL-2.0 OR MIT
-+/*
-+ * Copyright (C) 2022 StarFive Technology Co., Ltd.
-+ */
-+
-+/dts-v1/;
-+#include "jh7110-evb.dtsi"
-+
-+/ {
-+      model = "StarFive JH7110 EVB";
-+      compatible = "starfive,jh7110-evb", "starfive,jh7110";
-+
-+      sound5: snd-card5 {
-+              compatible = "simple-audio-card";
-+              #address-cells = <1>;
-+              #size-cells = <0>;
-+
-+              simple-audio-card,name = "StarFive-TDM-Sound-Card";
-+              simple-audio-card,widgets = "Microphone", "Mic Jack",
-+                                          "Line", "Line In",
-+                                          "Line", "Line Out",
-+                                          "Speaker", "Speaker",
-+                                          "Headphone", "Headphone Jack";
-+              simple-audio-card,routing = "Headphone Jack", "HP_L",
-+                                          "Headphone Jack", "HP_R",
-+                                          "Speaker", "SPK_LP",
-+                                          "Speaker", "SPK_LN",
-+                                          "LINPUT1", "Mic Jack",
-+                                          "LINPUT3", "Mic Jack",
-+                                          "RINPUT1", "Mic Jack",
-+                                          "RINPUT2", "Mic Jack";
-+
-+              simple-audio-card,dai-link@0 {
-+                      reg = <0>;
-+                      format = "dsp_a";
-+                      bitclock-master = <&dailink_master>;
-+                      frame-master = <&dailink_master>;
-+
-+                      cpu {
-+                              sound-dai = <&tdm>;
-+                      };
-+                      dailink_master: codec {
-+                              sound-dai = <&wm8960>;
-+                              clocks = <&wm8960_mclk>;
-+                      };
-+              };
-+      };
-+};
-+
-+&mmc0 {
-+      assigned-clocks = <&syscrg JH7110_SYSCLK_SDIO0_SDCARD>;
-+      assigned-clock-rates = <50000000>;
-+      pinctrl-names = "default";
-+      pinctrl-0 = <&sdcard0_pins>;
-+      max-frequency = <100000000>;
-+      card-detect-delay = <300>;
-+      bus-width = <4>;
-+      broken-cd;
-+      post-power-on-delay-ms = <200>;
-+      status = "okay";
-+};
-+
-+&usb0 {
-+      status = "okay";
-+};
-+
-+&pcie1 {
-+      status = "okay";
-+};
-+
-+&uart5 {
-+      status = "okay";
-+};
-+
-+&pwm {
-+      pinctrl-names = "default";
-+      pinctrl-0 = <&pwm_ch0to3_pins &pwm_ch4to5_pins>;
-+      status = "okay";
-+};
-+
-+&tdm {
-+      status = "okay";
-+};
-+
-+&i2c0 {
-+      status = "okay";
-+};
-+
-+&i2c1 {
-+      status = "okay";
-+};
-+
-+&i2c3 {
-+      status = "okay";
-+};
---- /dev/null
-+++ b/arch/riscv/boot/dts/starfive/jh7110-evb-usbdevice.dts
-@@ -0,0 +1,35 @@
-+// SPDX-License-Identifier: GPL-2.0 OR MIT
-+/*
-+ * Copyright (C) 2022 StarFive Technology Co., Ltd.
-+ */
-+
-+/dts-v1/;
-+#include "jh7110-evb.dtsi"
-+
-+/ {
-+      model = "StarFive JH7110 EVB";
-+      compatible = "starfive,jh7110-evb", "starfive,jh7110";
-+};
-+
-+/* default sd card */
-+&mmc0 {
-+      assigned-clocks = <&syscrg JH7110_SYSCLK_SDIO0_SDCARD>;
-+      assigned-clock-rates = <50000000>;
-+      pinctrl-names = "default";
-+      pinctrl-0 = <&sdcard0_pins>;
-+      max-frequency = <100000000>;
-+      card-detect-delay = <300>;
-+      bus-width = <4>;
-+      broken-cd;
-+      post-power-on-delay-ms = <200>;
-+      status = "okay";
-+};
-+
-+&usb0 {
-+      dr_mode = "peripheral"; /*host or peripheral*/
-+      status = "okay";
-+};
-+
-+&pcie1 {
-+      status = "okay";
-+};
diff --git a/target/linux/starfive/patches-6.6/0058-riscv-dts-starfive-Add-evb-overlay-dtso-subdir.patch b/target/linux/starfive/patches-6.6/0058-riscv-dts-starfive-Add-evb-overlay-dtso-subdir.patch
deleted file mode 100644 (file)
index a75ffc2..0000000
+++ /dev/null
@@ -1,485 +0,0 @@
-From e9122ceaf2d8767753e2a126c14b29b78280446d Mon Sep 17 00:00:00 2001
-From: Hal Feng <hal.feng@starfivetech.com>
-Date: Tue, 19 Sep 2023 21:35:39 +0800
-Subject: [PATCH 058/116] riscv: dts: starfive: Add evb-overlay dtso subdir
-
-Create subdir evb-overlay/ and add overlay .dtso for JH7110 EVB.
-The code is ported from tag JH7110_SDK_6.1_v5.11.3
-
-Signed-off-by: Hal Feng <hal.feng@starfivetech.com>
----
- arch/riscv/boot/dts/starfive/Makefile         |   1 +
- .../boot/dts/starfive/evb-overlay/Makefile    |   7 +
- .../evb-overlay/jh7110-evb-overlay-can.dtso   |  24 ++++
- .../jh7110-evb-overlay-rgb2hdmi.dtso          |  24 ++++
- .../evb-overlay/jh7110-evb-overlay-sdio.dtso  |  78 +++++++++++
- .../evb-overlay/jh7110-evb-overlay-spi.dtso   |  72 ++++++++++
- .../jh7110-evb-overlay-uart4-emmc.dtso        | 130 ++++++++++++++++++
- .../jh7110-evb-overlay-uart5-pwm.dtso         |  92 +++++++++++++
- 8 files changed, 428 insertions(+)
- create mode 100644 arch/riscv/boot/dts/starfive/evb-overlay/Makefile
- create mode 100644 arch/riscv/boot/dts/starfive/evb-overlay/jh7110-evb-overlay-can.dtso
- create mode 100644 arch/riscv/boot/dts/starfive/evb-overlay/jh7110-evb-overlay-rgb2hdmi.dtso
- create mode 100644 arch/riscv/boot/dts/starfive/evb-overlay/jh7110-evb-overlay-sdio.dtso
- create mode 100644 arch/riscv/boot/dts/starfive/evb-overlay/jh7110-evb-overlay-spi.dtso
- create mode 100644 arch/riscv/boot/dts/starfive/evb-overlay/jh7110-evb-overlay-uart4-emmc.dtso
- create mode 100644 arch/riscv/boot/dts/starfive/evb-overlay/jh7110-evb-overlay-uart5-pwm.dtso
-
---- a/arch/riscv/boot/dts/starfive/Makefile
-+++ b/arch/riscv/boot/dts/starfive/Makefile
-@@ -12,6 +12,7 @@ dtb-$(CONFIG_ARCH_STARFIVE) += jh7100-st
- dtb-$(CONFIG_ARCH_STARFIVE) += jh7110-starfive-visionfive-2-v1.2a.dtb
- dtb-$(CONFIG_ARCH_STARFIVE) += jh7110-starfive-visionfive-2-v1.3b.dtb
-+subdir-y += evb-overlay
- dtb-$(CONFIG_ARCH_STARFIVE) += jh7110-evb.dtb                 \
-                              jh7110-evb-pcie-i2s-sd.dtb       \
-                              jh7110-evb-spi-uart2.dtb         \
---- /dev/null
-+++ b/arch/riscv/boot/dts/starfive/evb-overlay/Makefile
-@@ -0,0 +1,7 @@
-+# SPDX-License-Identifier: GPL-2.0
-+dtb-$(CONFIG_ARCH_STARFIVE) += jh7110-evb-overlay-can.dtbo            \
-+                              jh7110-evb-overlay-sdio.dtbo            \
-+                              jh7110-evb-overlay-spi.dtbo             \
-+                              jh7110-evb-overlay-uart4-emmc.dtbo      \
-+                              jh7110-evb-overlay-uart5-pwm.dtbo       \
-+                              jh7110-evb-overlay-rgb2hdmi.dtbo
---- /dev/null
-+++ b/arch/riscv/boot/dts/starfive/evb-overlay/jh7110-evb-overlay-can.dtso
-@@ -0,0 +1,24 @@
-+/dts-v1/;
-+/plugin/;
-+#include <dt-bindings/gpio/gpio.h>
-+#include "../jh7110-pinfunc.h"
-+/ {
-+      compatible = "starfive,jh7110";
-+
-+      //can0
-+      fragment@0 {
-+              target-path = "/soc/can@130d0000";
-+              __overlay__ {
-+                      status = "okay";
-+              };
-+      };
-+
-+      //can1
-+      fragment@1 {
-+              target-path = "/soc/can@130e0000";
-+              __overlay__ {
-+                      status = "okay";
-+              };
-+      };
-+};
-+
---- /dev/null
-+++ b/arch/riscv/boot/dts/starfive/evb-overlay/jh7110-evb-overlay-rgb2hdmi.dtso
-@@ -0,0 +1,24 @@
-+/dts-v1/;
-+/plugin/;
-+#include <dt-bindings/gpio/gpio.h>
-+#include "../jh7110-pinfunc.h"
-+/ {
-+      compatible = "starfive,jh7110";
-+
-+      //hdmi_output
-+      fragment@0 {
-+              target-path = "/tda988x_pin";
-+              __overlay__ {
-+                      status = "okay";
-+              };
-+      };
-+
-+      //uart1
-+      fragment@1 {
-+              target-path = "/soc/serial@10010000";
-+              __overlay__ {
-+                      status = "okay";
-+              };
-+      };
-+};
-+
---- /dev/null
-+++ b/arch/riscv/boot/dts/starfive/evb-overlay/jh7110-evb-overlay-sdio.dtso
-@@ -0,0 +1,78 @@
-+/dts-v1/;
-+/plugin/;
-+#include <dt-bindings/gpio/gpio.h>
-+#include "../jh7110-pinfunc.h"
-+/ {
-+      compatible = "starfive,jh7110";
-+
-+      //sysgpio
-+      fragment@0 {
-+              target-path = "/soc/pinctrl@13040000";
-+              __overlay__ {
-+                      dt_sdcard1_pins: dt-sdcard1-0 {
-+                              sdcard-pins {
-+                                      pinmux = <GPIOMUX(56, GPOUT_SYS_SDIO1_CLK,
-+                                                            GPOEN_ENABLE,
-+                                                            GPI_NONE)>,
-+                                               <GPIOMUX(50, GPOUT_SYS_SDIO1_CMD,
-+                                                            GPOEN_SYS_SDIO1_CMD,
-+                                                            GPI_SYS_SDIO1_CMD)>,
-+                                               <GPIOMUX(49, GPOUT_SYS_SDIO1_DATA0,
-+                                                            GPOEN_SYS_SDIO1_DATA0,
-+                                                            GPI_SYS_SDIO1_DATA0)>,
-+                                               <GPIOMUX(45, GPOUT_SYS_SDIO1_DATA1,
-+                                                            GPOEN_SYS_SDIO1_DATA1,
-+                                                            GPI_SYS_SDIO1_DATA1)>,
-+                                               <GPIOMUX(62, GPOUT_SYS_SDIO1_DATA2,
-+                                                            GPOEN_SYS_SDIO1_DATA2,
-+                                                            GPI_SYS_SDIO1_DATA2)>,
-+                                               <GPIOMUX(40, GPOUT_SYS_SDIO1_DATA3,
-+                                                            GPOEN_SYS_SDIO1_DATA3,
-+                                                            GPI_SYS_SDIO1_DATA3)>;
-+                                      bias-pull-up;
-+                                      input-enable;
-+                              };
-+                      };
-+              };
-+      };
-+
-+      //uart3
-+      fragment@1 {
-+              target-path = "/soc/serial@12000000";
-+              __overlay__ {
-+                      status = "okay";
-+              };
-+      };
-+
-+      //i2c0
-+      fragment@2 {
-+              target-path = "/soc/i2c@10030000";
-+              __overlay__ {
-+                      status = "okay";
-+              };
-+      };
-+
-+      //mmc1
-+      fragment@3 {
-+              target-path = "/soc/mmc@16020000";
-+              __overlay__ {
-+                      max-frequency = <100000000>;
-+                      card-detect-delay = <300>;
-+                      bus-width = <4>;
-+                      no-sdio;
-+                      no-mmc;
-+                      broken-cd;
-+                      sd-uhs-sdr12;
-+                      sd-uhs-sdr25;
-+                      sd-uhs-sdr50;
-+                      sd-uhs-sdr104;
-+                      sd-uhs-ddr50;
-+                      cap-sd-highspeed;
-+                      post-power-on-delay-ms = <200>;
-+                      pinctrl-names = "default";
-+                      pinctrl-0 = <&dt_sdcard1_pins>;
-+                      status = "okay";
-+              };
-+      };
-+};
-+
---- /dev/null
-+++ b/arch/riscv/boot/dts/starfive/evb-overlay/jh7110-evb-overlay-spi.dtso
-@@ -0,0 +1,72 @@
-+/dts-v1/;
-+/plugin/;
-+#include <dt-bindings/gpio/gpio.h>
-+#include "../jh7110-pinfunc.h"
-+/ {
-+      compatible = "starfive,jh7110";
-+
-+      //spi0
-+      fragment@0 {
-+              target-path = "/soc/spi@10060000";
-+              __overlay__ {
-+                      status = "okay";
-+              };
-+      };
-+
-+      //spi1
-+      fragment@1 {
-+              target-path = "/soc/spi@10070000";
-+              __overlay__ {
-+                      status = "okay";
-+              };
-+      };
-+
-+      //spi2
-+      fragment@2 {
-+              target-path = "/soc/spi@10080000";
-+              __overlay__ {
-+                      status = "okay";
-+              };
-+      };
-+
-+      //spi3
-+      fragment@3 {
-+              target-path = "/soc/spi@12070000";
-+              __overlay__ {
-+                      status = "okay";
-+              };
-+      };
-+
-+      //spi4
-+      fragment@4 {
-+              target-path = "/soc/spi@12080000";
-+              __overlay__ {
-+                      status = "okay";
-+              };
-+      };
-+
-+      //spi5
-+      fragment@5 {
-+              target-path = "/soc/spi@12090000";
-+              __overlay__ {
-+                      status = "okay";
-+              };
-+      };
-+
-+      //spi6
-+      fragment@6 {
-+              target-path = "/soc/spi@120a0000";
-+              __overlay__ {
-+                      status = "okay";
-+              };
-+      };
-+
-+      //uart2
-+      fragment@7 {
-+              target-path = "/soc/serial@10020000";
-+              __overlay__ {
-+                      status = "okay";
-+              };
-+      };
-+};
-+
---- /dev/null
-+++ b/arch/riscv/boot/dts/starfive/evb-overlay/jh7110-evb-overlay-uart4-emmc.dtso
-@@ -0,0 +1,130 @@
-+/dts-v1/;
-+/plugin/;
-+#include <dt-bindings/gpio/gpio.h>
-+#include "../jh7110-pinfunc.h"
-+/ {
-+      compatible = "starfive,jh7110";
-+
-+      //sysgpio
-+      fragment@0 {
-+              target-path = "/soc/pinctrl@13040000";
-+              __overlay__ {
-+                      dt_emmc0_pins: dt-emmc0-0 {
-+                              emmc-pins {
-+                                      pinmux = <GPIOMUX(22, GPOUT_SYS_SDIO0_RST,
-+                                                            GPOEN_ENABLE,
-+                                                            GPI_NONE)>,
-+                                               <PINMUX(64, 0)>,
-+                                               <PINMUX(65, 0)>,
-+                                               <PINMUX(66, 0)>,
-+                                               <PINMUX(67, 0)>,
-+                                               <PINMUX(68, 0)>,
-+                                               <PINMUX(69, 0)>,
-+                                               <PINMUX(70, 0)>,
-+                                               <PINMUX(71, 0)>,
-+                                               <PINMUX(72, 0)>,
-+                                               <PINMUX(73, 0)>;
-+                                      bias-pull-up;
-+                                      drive-strength = <12>;
-+                                      input-enable;
-+                                      slew-rate = <1>;
-+                              };
-+                      };
-+
-+                      dt_emmc1_pins: dt-emmc1-0 {
-+                              emmc-pins {
-+                                      pinmux = <GPIOMUX(51, GPOUT_SYS_SDIO1_RST,
-+                                                            GPOEN_ENABLE,
-+                                                            GPI_NONE)>,
-+                                               <GPIOMUX(38, GPOUT_SYS_SDIO1_CLK,
-+                                                            GPOEN_ENABLE,
-+                                                            GPI_NONE)>,
-+                                               <GPIOMUX(36, GPOUT_SYS_SDIO1_CMD,
-+                                                            GPOEN_SYS_SDIO1_CMD,
-+                                                            GPI_SYS_SDIO1_CMD)>,
-+                                               <GPIOMUX(43, GPOUT_SYS_SDIO1_DATA0,
-+                                                            GPOEN_SYS_SDIO1_DATA0,
-+                                                            GPI_SYS_SDIO1_DATA0)>,
-+                                               <GPIOMUX(48, GPOUT_SYS_SDIO1_DATA1,
-+                                                            GPOEN_SYS_SDIO1_DATA1,
-+                                                            GPI_SYS_SDIO1_DATA1)>,
-+                                               <GPIOMUX(53, GPOUT_SYS_SDIO1_DATA2,
-+                                                            GPOEN_SYS_SDIO1_DATA2,
-+                                                            GPI_SYS_SDIO1_DATA2)>,
-+                                               <GPIOMUX(63, GPOUT_SYS_SDIO1_DATA3,
-+                                                            GPOEN_SYS_SDIO1_DATA3,
-+                                                            GPI_SYS_SDIO1_DATA3)>,
-+                                               <GPIOMUX(52, GPOUT_SYS_SDIO1_DATA4,
-+                                                            GPOEN_SYS_SDIO1_DATA4,
-+                                                            GPI_SYS_SDIO1_DATA4)>,
-+                                               <GPIOMUX(39, GPOUT_SYS_SDIO1_DATA5,
-+                                                            GPOEN_SYS_SDIO1_DATA5,
-+                                                            GPI_SYS_SDIO1_DATA5)>,
-+                                               <GPIOMUX(46, GPOUT_SYS_SDIO1_DATA6,
-+                                                            GPOEN_SYS_SDIO1_DATA6,
-+                                                            GPI_SYS_SDIO1_DATA6)>,
-+                                               <GPIOMUX(47, GPOUT_SYS_SDIO1_DATA7,
-+                                                            GPOEN_SYS_SDIO1_DATA7,
-+                                                            GPI_SYS_SDIO1_DATA7)>;
-+                                      bias-pull-up;
-+                                      input-enable;
-+                              };
-+                      };
-+              };
-+      };
-+
-+      //aongpio
-+      fragment@1 {
-+              target-path = "/soc/pinctrl@17020000";
-+              __overlay__ {
-+                      dt_pwm_ch6to7_pins: dt-pwm-ch6to7-0 {
-+                              pwm-pins {
-+                                      pinmux = <GPIOMUX(1, GPOUT_AON_PTC0_PWM6, /* PAD_RGPIO0 */
-+                                                           GPOEN_AON_PTC0_OE_N_6,
-+                                                           GPI_NONE)>,
-+                                               <GPIOMUX(2, GPOUT_AON_PTC0_PWM7, /* PAD_RGPIO1 */
-+                                                           GPOEN_AON_PTC0_OE_N_7,
-+                                                           GPI_NONE)>;
-+                                      drive-strength = <12>;
-+                              };
-+                      };
-+              };
-+      };
-+
-+      //uart4
-+      fragment@2 {
-+              target-path = "/soc/serial@12010000";
-+              __overlay__ {
-+                      status = "okay";
-+              };
-+      };
-+
-+      //mmc1
-+      fragment@3 {
-+              target-path = "/soc/mmc@16020000";
-+              __overlay__ {
-+                      clock-frequency = <102400000>;
-+                      max-frequency = <100000000>;
-+                      card-detect-delay = <300>;
-+                      bus-width = <8>;
-+                      cap-mmc-hw-reset;
-+                      non-removable;
-+                      cap-mmc-highspeed;
-+                      post-power-on-delay-ms = <200>;
-+                      pinctrl-names = "default";
-+                      pinctrl-0 = <&dt_emmc1_pins>;
-+                      status = "okay";
-+              };
-+      };
-+
-+      //ptc
-+      fragment@4 {
-+              target-path = "/soc/pwm@120d0000";
-+              __overlay__ {
-+                      pinctrl-names = "default";
-+                      pinctrl-0 = <&dt_pwm_ch6to7_pins>;
-+                      status = "okay";
-+              };
-+      };
-+};
-+
---- /dev/null
-+++ b/arch/riscv/boot/dts/starfive/evb-overlay/jh7110-evb-overlay-uart5-pwm.dtso
-@@ -0,0 +1,92 @@
-+/dts-v1/;
-+/plugin/;
-+#include <dt-bindings/gpio/gpio.h>
-+#include "../jh7110-pinfunc.h"
-+/ {
-+      compatible = "starfive,jh7110";
-+
-+      //sysgpio
-+      fragment@0 {
-+              target-path = "/soc/pinctrl@13040000";
-+              __overlay__ {
-+                      dt_pwm_ch0to3_pins: dt-pwm-ch0to3-0 {
-+                              pwm-pins {
-+                                      pinmux = <GPIOMUX(45, GPOUT_SYS_PWM_CHANNEL0,
-+                                                            GPOEN_SYS_PWM0_CHANNEL0,
-+                                                            GPI_NONE)>,
-+                                               <GPIOMUX(46, GPOUT_SYS_PWM_CHANNEL1,
-+                                                            GPOEN_SYS_PWM0_CHANNEL1,
-+                                                            GPI_NONE)>,
-+                                               <GPIOMUX(47, GPOUT_SYS_PWM_CHANNEL2,
-+                                                            GPOEN_SYS_PWM0_CHANNEL2,
-+                                                            GPI_NONE)>,
-+                                               <GPIOMUX(48, GPOUT_SYS_PWM_CHANNEL3,
-+                                                            GPOEN_SYS_PWM0_CHANNEL3,
-+                                                            GPI_NONE)>;
-+                                      drive-strength = <12>;
-+                              };
-+                      };
-+              };
-+      };
-+
-+      //aongpio
-+      fragment@1 {
-+              target-path = "/soc/pinctrl@17020000";
-+              __overlay__ {
-+                      dt_pwm_ch4to5_pins: dt-pwm-ch4to5-0 {
-+                              pwm-pins {
-+                                      pinmux = <GPIOMUX(1, GPOUT_AON_PTC0_PWM4, /* PAD_RGPIO0 */
-+                                                           GPOEN_AON_PTC0_OE_N_4,
-+                                                           GPI_NONE)>,
-+                                               <GPIOMUX(2, GPOUT_AON_PTC0_PWM5, /* PAD_RGPIO1 */
-+                                                           GPOEN_AON_PTC0_OE_N_5,
-+                                                           GPI_NONE)>;
-+                                      drive-strength = <12>;
-+                              };
-+                      };
-+              };
-+      };
-+
-+      //uart5
-+      fragment@2 {
-+              target-path = "/soc/serial@12020000";
-+              __overlay__ {
-+                      status = "okay";
-+              };
-+      };
-+
-+      //ptc
-+      fragment@3 {
-+              target-path = "/soc/pwm@120d0000";
-+              __overlay__ {
-+                      pinctrl-names = "default";
-+                      pinctrl-0 = <&dt_pwm_ch0to3_pins &dt_pwm_ch4to5_pins>;
-+                      status = "okay";
-+              };
-+      };
-+
-+      //i2c0
-+      fragment@4 {
-+              target-path = "/soc/i2c@10030000";
-+              __overlay__ {
-+                      status = "okay";
-+              };
-+      };
-+
-+      //i2c1
-+      fragment@5 {
-+              target-path = "/soc/i2c@10040000";
-+              __overlay__ {
-+                      status = "okay";
-+              };
-+      };
-+
-+      //i2c3
-+      fragment@6 {
-+              target-path = "/soc/i2c@12030000";
-+              __overlay__ {
-+                      status = "okay";
-+              };
-+      };
-+};
-+
diff --git a/target/linux/starfive/patches-6.6/0059-riscv-configs-Add-starfive_jh7110_defconfig.patch b/target/linux/starfive/patches-6.6/0059-riscv-configs-Add-starfive_jh7110_defconfig.patch
deleted file mode 100644 (file)
index ddf7245..0000000
+++ /dev/null
@@ -1,385 +0,0 @@
-From 5c888fa081caf5d9473e733931d1c7b3d4b61e61 Mon Sep 17 00:00:00 2001
-From: Hal Feng <hal.feng@starfivetech.com>
-Date: Fri, 28 Jul 2023 18:42:55 +0800
-Subject: [PATCH 059/116] riscv: configs: Add starfive_jh7110_defconfig
-
-Add starfive_jh7110_defconfig for JH7110 EVB.
-The code is ported from tag JH7110_SDK_6.1_v5.11.3
-
-Signed-off-by: Hal Feng <hal.feng@starfivetech.com>
----
- arch/riscv/configs/starfive_jh7110_defconfig | 368 +++++++++++++++++++
- 1 file changed, 368 insertions(+)
- create mode 100644 arch/riscv/configs/starfive_jh7110_defconfig
-
---- /dev/null
-+++ b/arch/riscv/configs/starfive_jh7110_defconfig
-@@ -0,0 +1,368 @@
-+CONFIG_COMPILE_TEST=y
-+# CONFIG_WERROR is not set
-+CONFIG_DEFAULT_HOSTNAME="StarFive"
-+CONFIG_SYSVIPC=y
-+CONFIG_POSIX_MQUEUE=y
-+CONFIG_USELIB=y
-+CONFIG_NO_HZ_IDLE=y
-+CONFIG_HIGH_RES_TIMERS=y
-+CONFIG_BPF_SYSCALL=y
-+CONFIG_IKCONFIG=y
-+CONFIG_IKCONFIG_PROC=y
-+CONFIG_CGROUPS=y
-+CONFIG_MEMCG=y
-+CONFIG_CGROUP_SCHED=y
-+CONFIG_CFS_BANDWIDTH=y
-+CONFIG_RT_GROUP_SCHED=y
-+CONFIG_CGROUP_PIDS=y
-+CONFIG_CGROUP_FREEZER=y
-+CONFIG_CGROUP_HUGETLB=y
-+CONFIG_CPUSETS=y
-+CONFIG_CGROUP_DEVICE=y
-+CONFIG_CGROUP_CPUACCT=y
-+CONFIG_CGROUP_PERF=y
-+CONFIG_CGROUP_BPF=y
-+CONFIG_NAMESPACES=y
-+CONFIG_USER_NS=y
-+CONFIG_CHECKPOINT_RESTORE=y
-+CONFIG_BLK_DEV_INITRD=y
-+CONFIG_EXPERT=y
-+# CONFIG_SYSFS_SYSCALL is not set
-+CONFIG_PROFILING=y
-+CONFIG_SOC_MICROCHIP_POLARFIRE=y
-+CONFIG_SOC_STARFIVE=y
-+CONFIG_SOC_VIRT=y
-+CONFIG_ERRATA_SIFIVE=y
-+CONFIG_NONPORTABLE=y
-+CONFIG_SMP=y
-+CONFIG_RISCV_SBI_V01=y
-+# CONFIG_RISCV_BOOT_SPINWAIT is not set
-+CONFIG_HIBERNATION=y
-+CONFIG_PM_STD_PARTITION="PARTLABEL=hibernation"
-+CONFIG_PM_DEBUG=y
-+CONFIG_PM_ADVANCED_DEBUG=y
-+CONFIG_PM_TEST_SUSPEND=y
-+CONFIG_ENERGY_MODEL=y
-+CONFIG_CPU_IDLE=y
-+CONFIG_CPU_FREQ=y
-+CONFIG_CPU_FREQ_STAT=y
-+CONFIG_CPU_FREQ_DEFAULT_GOV_ONDEMAND=y
-+CONFIG_CPU_FREQ_GOV_POWERSAVE=y
-+CONFIG_CPU_FREQ_GOV_USERSPACE=y
-+CONFIG_CPU_FREQ_GOV_CONSERVATIVE=y
-+CONFIG_CPU_FREQ_GOV_SCHEDUTIL=y
-+CONFIG_CPUFREQ_DT=y
-+CONFIG_VIRTUALIZATION=y
-+CONFIG_KVM=m
-+CONFIG_JUMP_LABEL=y
-+CONFIG_MODULES=y
-+CONFIG_MODULE_UNLOAD=y
-+CONFIG_BINFMT_MISC=y
-+CONFIG_CMA=y
-+CONFIG_NET=y
-+CONFIG_PACKET=y
-+CONFIG_XFRM_USER=m
-+CONFIG_IP_MULTICAST=y
-+CONFIG_IP_ADVANCED_ROUTER=y
-+CONFIG_IP_MULTIPLE_TABLES=y
-+CONFIG_IP_PNP=y
-+CONFIG_IP_PNP_DHCP=y
-+CONFIG_IP_PNP_BOOTP=y
-+CONFIG_IP_PNP_RARP=y
-+CONFIG_INET_ESP=m
-+CONFIG_NETFILTER=y
-+CONFIG_BRIDGE_NETFILTER=m
-+CONFIG_NF_CONNTRACK=m
-+CONFIG_NF_CONNTRACK_FTP=m
-+CONFIG_NF_CONNTRACK_TFTP=m
-+CONFIG_NETFILTER_XT_MARK=m
-+CONFIG_NETFILTER_XT_MATCH_ADDRTYPE=m
-+CONFIG_NETFILTER_XT_MATCH_CONNTRACK=m
-+CONFIG_NETFILTER_XT_MATCH_IPVS=m
-+CONFIG_IP_VS=m
-+CONFIG_IP_VS_PROTO_TCP=y
-+CONFIG_IP_VS_PROTO_UDP=y
-+CONFIG_IP_VS_RR=m
-+CONFIG_IP_VS_NFCT=y
-+CONFIG_NF_LOG_ARP=m
-+CONFIG_NF_LOG_IPV4=m
-+CONFIG_IP_NF_IPTABLES=m
-+CONFIG_IP_NF_FILTER=m
-+CONFIG_IP_NF_TARGET_REJECT=m
-+CONFIG_IP_NF_NAT=m
-+CONFIG_IP_NF_TARGET_MASQUERADE=m
-+CONFIG_IP_NF_TARGET_REDIRECT=m
-+CONFIG_IP_NF_MANGLE=m
-+CONFIG_NF_LOG_IPV6=m
-+CONFIG_IP6_NF_IPTABLES=m
-+CONFIG_IP6_NF_MATCH_IPV6HEADER=m
-+CONFIG_IP6_NF_FILTER=m
-+CONFIG_IP6_NF_TARGET_REJECT=m
-+CONFIG_IP6_NF_MANGLE=m
-+CONFIG_BRIDGE=m
-+CONFIG_BRIDGE_VLAN_FILTERING=y
-+CONFIG_VLAN_8021Q=m
-+CONFIG_NET_SCHED=y
-+CONFIG_NET_CLS_CGROUP=m
-+CONFIG_NETLINK_DIAG=y
-+CONFIG_CGROUP_NET_PRIO=y
-+CONFIG_CAN=y
-+CONFIG_BT=y
-+CONFIG_BT_RFCOMM=y
-+CONFIG_BT_RFCOMM_TTY=y
-+CONFIG_BT_BNEP=y
-+CONFIG_BT_BNEP_MC_FILTER=y
-+CONFIG_BT_BNEP_PROTO_FILTER=y
-+CONFIG_BT_HCIUART=y
-+CONFIG_BT_HCIUART_H4=y
-+CONFIG_CFG80211=y
-+CONFIG_MAC80211=y
-+CONFIG_RFKILL=y
-+CONFIG_NET_9P=y
-+CONFIG_NET_9P_VIRTIO=y
-+CONFIG_PCI=y
-+CONFIG_PCIEPORTBUS=y
-+# CONFIG_PCIEASPM is not set
-+CONFIG_PCI_HOST_GENERIC=y
-+CONFIG_PCIE_FU740=y
-+CONFIG_PCIE_STARFIVE_HOST=y
-+CONFIG_DEVTMPFS=y
-+CONFIG_DEVTMPFS_MOUNT=y
-+CONFIG_MTD=y
-+CONFIG_MTD_BLOCK=y
-+CONFIG_MTD_SPI_NOR=y
-+CONFIG_OF_CONFIGFS=y
-+CONFIG_BLK_DEV_LOOP=y
-+CONFIG_VIRTIO_BLK=y
-+CONFIG_BLK_DEV_NVME=y
-+CONFIG_BLK_DEV_SD=y
-+CONFIG_BLK_DEV_SR=y
-+CONFIG_SCSI_VIRTIO=y
-+CONFIG_ATA=y
-+CONFIG_SATA_AHCI=y
-+CONFIG_SATA_AHCI_PLATFORM=y
-+CONFIG_MD=y
-+CONFIG_BLK_DEV_DM=m
-+CONFIG_DM_THIN_PROVISIONING=m
-+CONFIG_NETDEVICES=y
-+CONFIG_DUMMY=m
-+CONFIG_MACVLAN=m
-+CONFIG_IPVLAN=m
-+CONFIG_VXLAN=m
-+CONFIG_VETH=m
-+CONFIG_VIRTIO_NET=y
-+CONFIG_MACB=y
-+CONFIG_E1000E=y
-+CONFIG_R8169=y
-+CONFIG_STMMAC_ETH=y
-+CONFIG_DWMAC_DWC_QOS_ETH=y
-+# CONFIG_DWMAC_GENERIC is not set
-+CONFIG_DWMAC_STARFIVE=y
-+CONFIG_MARVELL_PHY=y
-+CONFIG_MICREL_PHY=y
-+CONFIG_MICROCHIP_PHY=y
-+CONFIG_MICROSEMI_PHY=y
-+CONFIG_MOTORCOMM_PHY=y
-+CONFIG_IPMS_CAN=y
-+CONFIG_IWLWIFI=y
-+CONFIG_IWLDVM=y
-+CONFIG_IWLMVM=y
-+CONFIG_INPUT_MOUSEDEV=y
-+CONFIG_INPUT_EVDEV=y
-+CONFIG_INPUT_TOUCHSCREEN=y
-+CONFIG_TOUCHSCREEN_TINKER_FT5406=y
-+CONFIG_SERIAL_8250=y
-+CONFIG_SERIAL_8250_CONSOLE=y
-+CONFIG_SERIAL_8250_NR_UARTS=6
-+CONFIG_SERIAL_8250_RUNTIME_UARTS=6
-+CONFIG_SERIAL_8250_EXTENDED=y
-+CONFIG_SERIAL_8250_MANY_PORTS=y
-+CONFIG_SERIAL_8250_DW=y
-+CONFIG_SERIAL_OF_PLATFORM=y
-+CONFIG_SERIAL_EARLYCON_RISCV_SBI=y
-+CONFIG_TTY_PRINTK=y
-+CONFIG_VIRTIO_CONSOLE=y
-+CONFIG_HW_RANDOM=y
-+CONFIG_HW_RANDOM_VIRTIO=y
-+CONFIG_HW_RANDOM_JH7110=y
-+CONFIG_I2C_CHARDEV=y
-+CONFIG_I2C_DESIGNWARE_PLATFORM=y
-+CONFIG_SPI=y
-+CONFIG_SPI_CADENCE_QUADSPI=y
-+CONFIG_SPI_PL022=y
-+CONFIG_SPI_SIFIVE=y
-+CONFIG_SPI_SPIDEV=y
-+# CONFIG_PTP_1588_CLOCK is not set
-+CONFIG_GPIO_SYSFS=y
-+CONFIG_GPIO_SIFIVE=y
-+CONFIG_SENSORS_SFCTEMP=y
-+CONFIG_THERMAL=y
-+CONFIG_THERMAL_WRITABLE_TRIPS=y
-+CONFIG_CPU_THERMAL=y
-+CONFIG_THERMAL_EMULATION=y
-+CONFIG_WATCHDOG=y
-+CONFIG_WATCHDOG_SYSFS=y
-+CONFIG_MFD_AXP20X_I2C=y
-+CONFIG_REGULATOR=y
-+CONFIG_REGULATOR_AXP20X=y
-+CONFIG_REGULATOR_STARFIVE_JH7110=y
-+# CONFIG_MEDIA_CEC_SUPPORT is not set
-+CONFIG_MEDIA_SUPPORT=y
-+CONFIG_MEDIA_USB_SUPPORT=y
-+CONFIG_USB_VIDEO_CLASS=y
-+CONFIG_V4L_PLATFORM_DRIVERS=y
-+CONFIG_V4L_MEM2MEM_DRIVERS=y
-+CONFIG_VIDEO_WAVE_VPU=m
-+CONFIG_VIN_SENSOR_SC2235=y
-+CONFIG_VIN_SENSOR_OV4689=y
-+CONFIG_VIN_SENSOR_IMX219=y
-+CONFIG_VIDEO_STF_VIN=y
-+CONFIG_VIDEO_IMX708=y
-+CONFIG_DRM_I2C_NXP_TDA998X=y
-+CONFIG_DRM_I2C_NXP_TDA9950=y
-+CONFIG_DRM_RADEON=m
-+CONFIG_DRM_VIRTIO_GPU=m
-+CONFIG_DRM_VERISILICON=y
-+CONFIG_STARFIVE_INNO_HDMI=y
-+CONFIG_STARFIVE_DSI=y
-+CONFIG_DRM_IMG_ROGUE=y
-+CONFIG_DRM_LEGACY=y
-+CONFIG_FB=y
-+CONFIG_SOUND=y
-+CONFIG_SND=y
-+CONFIG_SND_USB_AUDIO=y
-+CONFIG_SND_SOC=y
-+CONFIG_SND_DESIGNWARE_I2S=y
-+# CONFIG_SND_SOC_INTEL_SST_TOPLEVEL is not set
-+CONFIG_SND_SOC_STARFIVE=y
-+CONFIG_SND_SOC_JH7110_PDM=y
-+CONFIG_SND_SOC_JH7110_PWMDAC=y
-+CONFIG_SND_SOC_JH7110_SPDIF=y
-+CONFIG_SND_SOC_JH7110_TDM=y
-+CONFIG_SND_SOC_AC108=y
-+CONFIG_SND_SOC_WM8960=y
-+CONFIG_SND_SIMPLE_CARD=y
-+CONFIG_USB=y
-+CONFIG_USB_XHCI_HCD=y
-+CONFIG_USB_EHCI_HCD=y
-+CONFIG_USB_EHCI_HCD_PLATFORM=y
-+CONFIG_USB_OHCI_HCD=y
-+CONFIG_USB_OHCI_HCD_PLATFORM=y
-+CONFIG_USB_STORAGE=y
-+CONFIG_USB_UAS=y
-+CONFIG_USB_CDNS_SUPPORT=y
-+CONFIG_USB_CDNS3=y
-+CONFIG_USB_CDNS3_GADGET=y
-+CONFIG_USB_CDNS3_HOST=y
-+CONFIG_USB_CDNS3_STARFIVE=y
-+CONFIG_USB_GADGET=y
-+CONFIG_USB_CONFIGFS=y
-+CONFIG_USB_CONFIGFS_MASS_STORAGE=y
-+CONFIG_USB_CONFIGFS_F_FS=y
-+CONFIG_MMC=y
-+CONFIG_MMC_SDHCI=y
-+CONFIG_MMC_SDHCI_PLTFM=y
-+CONFIG_MMC_SDHCI_CADENCE=y
-+CONFIG_MMC_SPI=y
-+CONFIG_MMC_DW=y
-+CONFIG_MMC_DW_STARFIVE=y
-+CONFIG_RTC_CLASS=y
-+# CONFIG_RTC_DRV_SPEAR is not set
-+CONFIG_RTC_DRV_STARFIVE=y
-+CONFIG_DMADEVICES=y
-+CONFIG_AMBA_PL08X=y
-+CONFIG_DW_AXI_DMAC=y
-+# CONFIG_SH_DMAE_BASE is not set
-+# CONFIG_TI_EDMA is not set
-+# CONFIG_DMA_OMAP is not set
-+CONFIG_DMATEST=y
-+CONFIG_VIRTIO_PCI=y
-+CONFIG_VIRTIO_BALLOON=y
-+CONFIG_VIRTIO_INPUT=y
-+CONFIG_VIRTIO_MMIO=y
-+CONFIG_STAGING=y
-+CONFIG_STAGING_MEDIA=y
-+CONFIG_CLK_STARFIVE_JH7110_AON=y
-+CONFIG_CLK_STARFIVE_JH7110_STG=y
-+CONFIG_CLK_STARFIVE_JH7110_ISP=y
-+CONFIG_CLK_STARFIVE_JH7110_VOUT=y
-+CONFIG_MAILBOX=y
-+CONFIG_STARFIVE_MBOX=m
-+CONFIG_STARFIVE_MBOX_TEST=m
-+CONFIG_RPMSG_CHAR=y
-+CONFIG_RPMSG_CTRL=y
-+CONFIG_RPMSG_VIRTIO=y
-+CONFIG_SIFIVE_CCACHE=y
-+CONFIG_PWM=y
-+CONFIG_PWM_OCORES=y
-+CONFIG_PHY_STARFIVE_JH7110_PCIE=y
-+CONFIG_PHY_STARFIVE_JH7110_USB=y
-+CONFIG_PHY_M31_DPHY_RX0=y
-+CONFIG_EXT4_FS=y
-+CONFIG_EXT4_FS_POSIX_ACL=y
-+CONFIG_EXT4_FS_SECURITY=y
-+CONFIG_BTRFS_FS=m
-+CONFIG_BTRFS_FS_POSIX_ACL=y
-+CONFIG_AUTOFS_FS=y
-+CONFIG_FUSE_FS=y
-+CONFIG_OVERLAY_FS=y
-+CONFIG_OVERLAY_FS_INDEX=y
-+CONFIG_OVERLAY_FS_XINO_AUTO=y
-+CONFIG_OVERLAY_FS_METACOPY=y
-+CONFIG_ISO9660_FS=y
-+CONFIG_JOLIET=y
-+CONFIG_ZISOFS=y
-+CONFIG_MSDOS_FS=y
-+CONFIG_VFAT_FS=y
-+CONFIG_EXFAT_FS=y
-+CONFIG_TMPFS=y
-+CONFIG_TMPFS_POSIX_ACL=y
-+CONFIG_HUGETLBFS=y
-+CONFIG_JFFS2_FS=y
-+CONFIG_NFS_FS=y
-+CONFIG_NFS_V4=y
-+CONFIG_NFS_V4_1=y
-+CONFIG_NFS_V4_2=y
-+CONFIG_ROOT_NFS=y
-+CONFIG_9P_FS=y
-+CONFIG_NLS_CODEPAGE_437=y
-+CONFIG_NLS_ISO8859_1=m
-+CONFIG_SECURITY=y
-+CONFIG_SECURITY_SELINUX=y
-+CONFIG_SECURITY_APPARMOR=y
-+CONFIG_DEFAULT_SECURITY_DAC=y
-+CONFIG_LSM=""
-+CONFIG_INIT_STACK_NONE=y
-+CONFIG_CRYPTO_USER=y
-+CONFIG_CRYPTO_ZSTD=y
-+CONFIG_CRYPTO_USER_API_HASH=y
-+CONFIG_CRYPTO_USER_API_SKCIPHER=y
-+CONFIG_CRYPTO_USER_API_AEAD=y
-+CONFIG_CRYPTO_STATS=y
-+CONFIG_CRYPTO_DEV_VIRTIO=y
-+CONFIG_CRYPTO_DEV_JH7110=y
-+CONFIG_DMA_CMA=y
-+CONFIG_PRINTK_TIME=y
-+CONFIG_DEBUG_FS=y
-+CONFIG_DEBUG_PAGEALLOC=y
-+CONFIG_SCHED_STACK_END_CHECK=y
-+CONFIG_DEBUG_VM=y
-+CONFIG_DEBUG_VM_PGFLAGS=y
-+CONFIG_DEBUG_MEMORY_INIT=y
-+CONFIG_DEBUG_PER_CPU_MAPS=y
-+CONFIG_SOFTLOCKUP_DETECTOR=y
-+CONFIG_WQ_WATCHDOG=y
-+CONFIG_DEBUG_TIMEKEEPING=y
-+CONFIG_DEBUG_RT_MUTEXES=y
-+CONFIG_DEBUG_SPINLOCK=y
-+CONFIG_DEBUG_MUTEXES=y
-+CONFIG_DEBUG_RWSEMS=y
-+CONFIG_DEBUG_LIST=y
-+CONFIG_DEBUG_PLIST=y
-+CONFIG_DEBUG_SG=y
-+CONFIG_RCU_CPU_STALL_TIMEOUT=60
-+# CONFIG_RCU_TRACE is not set
-+CONFIG_RCU_EQS_DEBUG=y
-+# CONFIG_FTRACE is not set
-+# CONFIG_RUNTIME_TESTING_MENU is not set
-+CONFIG_MEMTEST=y
diff --git a/target/linux/starfive/patches-6.6/0060-of-configfs-Add-configfs-function.patch b/target/linux/starfive/patches-6.6/0060-of-configfs-Add-configfs-function.patch
deleted file mode 100644 (file)
index 68deb70..0000000
+++ /dev/null
@@ -1,318 +0,0 @@
-From 95c702022f5e4cb786719fcf90170334b1e562cc Mon Sep 17 00:00:00 2001
-From: Jianlong Huang <jianlong.huang@starfivetech.com>
-Date: Thu, 16 Jun 2022 17:13:57 +0800
-Subject: [PATCH 060/116] of: configfs: Add configfs function
-
-Signed-off-by: Jianlong Huang <jianlong.huang@starfivetech.com>
-Signed-off-by: Hal Feng <hal.feng@starfivetech.com>
----
- drivers/of/Kconfig    |   7 ++
- drivers/of/Makefile   |   1 +
- drivers/of/configfs.c | 277 ++++++++++++++++++++++++++++++++++++++++++
- 3 files changed, 285 insertions(+)
- create mode 100644 drivers/of/configfs.c
-
---- a/drivers/of/Kconfig
-+++ b/drivers/of/Kconfig
-@@ -102,4 +102,11 @@ config OF_OVERLAY
- config OF_NUMA
-       bool
-+config OF_CONFIGFS
-+        bool "Device Tree Overlay ConfigFS interface"
-+        select CONFIGFS_FS
-+        select OF_OVERLAY
-+        help
-+          Enable a simple user-space driven DT overlay interface.
-+
- endif # OF
---- a/drivers/of/Makefile
-+++ b/drivers/of/Makefile
-@@ -11,6 +11,7 @@ obj-$(CONFIG_OF_UNITTEST) += unittest.o
- obj-$(CONFIG_OF_RESERVED_MEM) += of_reserved_mem.o
- obj-$(CONFIG_OF_RESOLVE)  += resolver.o
- obj-$(CONFIG_OF_OVERLAY) += overlay.o
-+obj-$(CONFIG_OF_CONFIGFS) += configfs.o
- obj-$(CONFIG_OF_NUMA) += of_numa.o
- ifdef CONFIG_KEXEC_FILE
---- /dev/null
-+++ b/drivers/of/configfs.c
-@@ -0,0 +1,277 @@
-+/*
-+ * Configfs entries for device-tree
-+ *
-+ * Copyright (C) 2013 - Pantelis Antoniou <panto@antoniou-consulting.com>
-+ *
-+ * This program is free software; you can redistribute it and/or
-+ * modify it under the terms of the GNU General Public License
-+ * as published by the Free Software Foundation; either version
-+ * 2 of the License, or (at your option) any later version.
-+ */
-+#include <linux/ctype.h>
-+#include <linux/cpu.h>
-+#include <linux/module.h>
-+#include <linux/of.h>
-+#include <linux/of_fdt.h>
-+#include <linux/spinlock.h>
-+#include <linux/slab.h>
-+#include <linux/proc_fs.h>
-+#include <linux/configfs.h>
-+#include <linux/types.h>
-+#include <linux/stat.h>
-+#include <linux/limits.h>
-+#include <linux/file.h>
-+#include <linux/vmalloc.h>
-+#include <linux/firmware.h>
-+#include <linux/sizes.h>
-+
-+#include "of_private.h"
-+
-+struct cfs_overlay_item {
-+      struct config_item      item;
-+
-+      char                    path[PATH_MAX];
-+
-+      const struct firmware   *fw;
-+      struct device_node      *overlay;
-+      int                     ov_id;
-+
-+      void                    *dtbo;
-+      int                     dtbo_size;
-+};
-+
-+static inline struct cfs_overlay_item *to_cfs_overlay_item(
-+              struct config_item *item)
-+{
-+      return item ? container_of(item, struct cfs_overlay_item, item) : NULL;
-+}
-+
-+static ssize_t cfs_overlay_item_path_show(struct config_item *item,
-+              char *page)
-+{
-+      struct cfs_overlay_item *overlay = to_cfs_overlay_item(item);
-+      return sprintf(page, "%s\n", overlay->path);
-+}
-+
-+static ssize_t cfs_overlay_item_path_store(struct config_item *item,
-+              const char *page, size_t count)
-+{
-+      struct cfs_overlay_item *overlay = to_cfs_overlay_item(item);
-+      const char *p = page;
-+      char *s;
-+      int err;
-+
-+      /* if it's set do not allow changes */
-+      if (overlay->path[0] != '\0' || overlay->dtbo_size > 0)
-+              return -EPERM;
-+
-+      /* copy to path buffer (and make sure it's always zero terminated */
-+      count = snprintf(overlay->path, sizeof(overlay->path) - 1, "%s", p);
-+      overlay->path[sizeof(overlay->path) - 1] = '\0';
-+
-+      /* strip trailing newlines */
-+      s = overlay->path + strlen(overlay->path);
-+      while (s > overlay->path && *--s == '\n')
-+              *s = '\0';
-+
-+      pr_debug("%s: path is '%s'\n", __func__, overlay->path);
-+
-+      err = request_firmware(&overlay->fw, overlay->path, NULL);
-+      if (err != 0)
-+              return err;
-+
-+      err = of_overlay_fdt_apply((void *)overlay->fw->data,
-+                                 (u32)overlay->fw->size, &overlay->ov_id, NULL);
-+      if (err != 0)
-+              goto out_err;
-+
-+      return count;
-+
-+out_err:
-+
-+      release_firmware(overlay->fw);
-+      overlay->fw = NULL;
-+
-+      overlay->path[0] = '\0';
-+      return err;
-+}
-+
-+static ssize_t cfs_overlay_item_status_show(struct config_item *item,
-+              char *page)
-+{
-+      struct cfs_overlay_item *overlay = to_cfs_overlay_item(item);
-+
-+      return sprintf(page, "%s\n",
-+                      overlay->ov_id > 0 ? "applied" : "unapplied");
-+}
-+
-+CONFIGFS_ATTR(cfs_overlay_item_, path);
-+CONFIGFS_ATTR_RO(cfs_overlay_item_, status);
-+
-+static struct configfs_attribute *cfs_overlay_attrs[] = {
-+      &cfs_overlay_item_attr_path,
-+      &cfs_overlay_item_attr_status,
-+      NULL,
-+};
-+
-+ssize_t cfs_overlay_item_dtbo_read(struct config_item *item,
-+              void *buf, size_t max_count)
-+{
-+      struct cfs_overlay_item *overlay = to_cfs_overlay_item(item);
-+
-+      pr_debug("%s: buf=%p max_count=%zu\n", __func__,
-+                      buf, max_count);
-+
-+      if (overlay->dtbo == NULL)
-+              return 0;
-+
-+      /* copy if buffer provided */
-+      if (buf != NULL) {
-+              /* the buffer must be large enough */
-+              if (overlay->dtbo_size > max_count)
-+                      return -ENOSPC;
-+
-+              memcpy(buf, overlay->dtbo, overlay->dtbo_size);
-+      }
-+
-+      return overlay->dtbo_size;
-+}
-+
-+ssize_t cfs_overlay_item_dtbo_write(struct config_item *item,
-+              const void *buf, size_t count)
-+{
-+      struct cfs_overlay_item *overlay = to_cfs_overlay_item(item);
-+      int err;
-+
-+      /* if it's set do not allow changes */
-+      if (overlay->path[0] != '\0' || overlay->dtbo_size > 0)
-+              return -EPERM;
-+
-+      /* copy the contents */
-+      overlay->dtbo = kmemdup(buf, count, GFP_KERNEL);
-+      if (overlay->dtbo == NULL)
-+              return -ENOMEM;
-+
-+      overlay->dtbo_size = count;
-+
-+      err = of_overlay_fdt_apply(overlay->dtbo, overlay->dtbo_size,
-+                                 &overlay->ov_id, NULL);
-+      if (err != 0)
-+              goto out_err;
-+
-+      return count;
-+
-+out_err:
-+      kfree(overlay->dtbo);
-+      overlay->dtbo = NULL;
-+      overlay->dtbo_size = 0;
-+      overlay->ov_id = 0;
-+
-+      return err;
-+}
-+
-+CONFIGFS_BIN_ATTR(cfs_overlay_item_, dtbo, NULL, SZ_1M);
-+
-+static struct configfs_bin_attribute *cfs_overlay_bin_attrs[] = {
-+      &cfs_overlay_item_attr_dtbo,
-+      NULL,
-+};
-+
-+static void cfs_overlay_release(struct config_item *item)
-+{
-+      struct cfs_overlay_item *overlay = to_cfs_overlay_item(item);
-+
-+      if (overlay->ov_id > 0)
-+              of_overlay_remove(&overlay->ov_id);
-+      if (overlay->fw)
-+              release_firmware(overlay->fw);
-+      /* kfree with NULL is safe */
-+      kfree(overlay->dtbo);
-+      kfree(overlay);
-+}
-+
-+static struct configfs_item_operations cfs_overlay_item_ops = {
-+      .release        = cfs_overlay_release,
-+};
-+
-+static struct config_item_type cfs_overlay_type = {
-+      .ct_item_ops    = &cfs_overlay_item_ops,
-+      .ct_attrs       = cfs_overlay_attrs,
-+      .ct_bin_attrs   = cfs_overlay_bin_attrs,
-+      .ct_owner       = THIS_MODULE,
-+};
-+
-+static struct config_item *cfs_overlay_group_make_item(
-+              struct config_group *group, const char *name)
-+{
-+      struct cfs_overlay_item *overlay;
-+
-+      overlay = kzalloc(sizeof(*overlay), GFP_KERNEL);
-+      if (!overlay)
-+              return ERR_PTR(-ENOMEM);
-+
-+      config_item_init_type_name(&overlay->item, name, &cfs_overlay_type);
-+      return &overlay->item;
-+}
-+
-+static void cfs_overlay_group_drop_item(struct config_group *group,
-+              struct config_item *item)
-+{
-+      struct cfs_overlay_item *overlay = to_cfs_overlay_item(item);
-+
-+      config_item_put(&overlay->item);
-+}
-+
-+static struct configfs_group_operations overlays_ops = {
-+      .make_item      = cfs_overlay_group_make_item,
-+      .drop_item      = cfs_overlay_group_drop_item,
-+};
-+
-+static struct config_item_type overlays_type = {
-+      .ct_group_ops   = &overlays_ops,
-+      .ct_owner       = THIS_MODULE,
-+};
-+
-+static struct configfs_group_operations of_cfs_ops = {
-+      /* empty - we don't allow anything to be created */
-+};
-+
-+static struct config_item_type of_cfs_type = {
-+      .ct_group_ops   = &of_cfs_ops,
-+      .ct_owner       = THIS_MODULE,
-+};
-+
-+struct config_group of_cfs_overlay_group;
-+
-+static struct configfs_subsystem of_cfs_subsys = {
-+      .su_group = {
-+              .cg_item = {
-+                      .ci_namebuf = "device-tree",
-+                      .ci_type = &of_cfs_type,
-+              },
-+      },
-+      .su_mutex = __MUTEX_INITIALIZER(of_cfs_subsys.su_mutex),
-+};
-+
-+static int __init of_cfs_init(void)
-+{
-+      int ret;
-+
-+      pr_info("%s\n", __func__);
-+
-+      config_group_init(&of_cfs_subsys.su_group);
-+      config_group_init_type_name(&of_cfs_overlay_group, "overlays",
-+                      &overlays_type);
-+      configfs_add_default_group(&of_cfs_overlay_group,
-+                      &of_cfs_subsys.su_group);
-+
-+      ret = configfs_register_subsystem(&of_cfs_subsys);
-+      if (ret != 0) {
-+              pr_err("%s: failed to register subsys\n", __func__);
-+              goto out;
-+      }
-+      pr_info("%s: OK\n", __func__);
-+out:
-+      return ret;
-+}
-+late_initcall(of_cfs_init);
diff --git a/target/linux/starfive/patches-6.6/0061-usr-Add-gen_initramfs_list.sh.patch b/target/linux/starfive/patches-6.6/0061-usr-Add-gen_initramfs_list.sh.patch
deleted file mode 100644 (file)
index ade0f46..0000000
+++ /dev/null
@@ -1,344 +0,0 @@
-From 7891826f8c2de9ee0f6459cf969f7b082e29b154 Mon Sep 17 00:00:00 2001
-From: Hal Feng <hal.feng@starfivetech.com>
-Date: Thu, 1 Jun 2023 23:10:09 -0700
-Subject: [PATCH 061/116] usr: Add gen_initramfs_list.sh
-
-Add gen_initramfs_list.sh
-
-Signed-off-by: Hal Feng <hal.feng@starfivetech.com>
----
- usr/gen_initramfs_list.sh | 328 ++++++++++++++++++++++++++++++++++++++
- 1 file changed, 328 insertions(+)
- create mode 100644 usr/gen_initramfs_list.sh
-
---- /dev/null
-+++ b/usr/gen_initramfs_list.sh
-@@ -0,0 +1,328 @@
-+#!/bin/sh
-+# Copyright (C) Martin Schlemmer <azarah@nosferatu.za.org>
-+# Copyright (C) 2006 Sam Ravnborg <sam@ravnborg.org>
-+#
-+# Released under the terms of the GNU GPL
-+#
-+# Generate a cpio packed initramfs. It uses gen_init_cpio to generate
-+# the cpio archive, and then compresses it.
-+# The script may also be used to generate the inputfile used for gen_init_cpio
-+# This script assumes that gen_init_cpio is located in usr/ directory
-+
-+# error out on errors
-+set -e
-+
-+usage() {
-+cat << EOF
-+Usage:
-+$0 [-o <file>] [-u <uid>] [-g <gid>] {-d | <cpio_source>} ...
-+      -o <file>      Create compressed initramfs file named <file> using
-+                     gen_init_cpio and compressor depending on the extension
-+      -u <uid>       User ID to map to user ID 0 (root).
-+                     <uid> is only meaningful if <cpio_source> is a
-+                     directory.  "squash" forces all files to uid 0.
-+      -g <gid>       Group ID to map to group ID 0 (root).
-+                     <gid> is only meaningful if <cpio_source> is a
-+                     directory.  "squash" forces all files to gid 0.
-+      <cpio_source>  File list or directory for cpio archive.
-+                     If <cpio_source> is a .cpio file it will be used
-+                     as direct input to initramfs.
-+      -d             Output the default cpio list.
-+
-+All options except -o and -l may be repeated and are interpreted
-+sequentially and immediately.  -u and -g states are preserved across
-+<cpio_source> options so an explicit "-u 0 -g 0" is required
-+to reset the root/group mapping.
-+EOF
-+}
-+
-+# awk style field access
-+# $1 - field number; rest is argument string
-+field() {
-+      shift $1 ; echo $1
-+}
-+
-+list_default_initramfs() {
-+      # echo usr/kinit/kinit
-+      :
-+}
-+
-+default_initramfs() {
-+      cat <<-EOF >> ${output}
-+              # This is a very simple, default initramfs
-+
-+              dir /dev 0755 0 0
-+              nod /dev/console 0600 0 0 c 5 1
-+              dir /root 0700 0 0
-+              # file /kinit usr/kinit/kinit 0755 0 0
-+              # slink /init kinit 0755 0 0
-+      EOF
-+}
-+
-+filetype() {
-+      local argv1="$1"
-+
-+      # symlink test must come before file test
-+      if [ -L "${argv1}" ]; then
-+              echo "slink"
-+      elif [ -f "${argv1}" ]; then
-+              echo "file"
-+      elif [ -d "${argv1}" ]; then
-+              echo "dir"
-+      elif [ -b "${argv1}" -o -c "${argv1}" ]; then
-+              echo "nod"
-+      elif [ -p "${argv1}" ]; then
-+              echo "pipe"
-+      elif [ -S "${argv1}" ]; then
-+              echo "sock"
-+      else
-+              echo "invalid"
-+      fi
-+      return 0
-+}
-+
-+list_print_mtime() {
-+      :
-+}
-+
-+print_mtime() {
-+      local my_mtime="0"
-+
-+      if [ -e "$1" ]; then
-+              my_mtime=$(find "$1" -printf "%T@\n" | sort -r | head -n 1)
-+      fi
-+
-+      echo "# Last modified: ${my_mtime}" >> ${output}
-+      echo "" >> ${output}
-+}
-+
-+list_parse() {
-+      if [ -L "$1" ]; then
-+              return
-+      fi
-+      echo "$1" | sed 's/:/\\:/g; s/$/ \\/'
-+}
-+
-+# for each file print a line in following format
-+# <filetype> <name> <path to file> <octal mode> <uid> <gid>
-+# for links, devices etc the format differs. See gen_init_cpio for details
-+parse() {
-+      local location="$1"
-+      local name="/${location#${srcdir}}"
-+      # change '//' into '/'
-+      name=$(echo "$name" | sed -e 's://*:/:g')
-+      local mode="$2"
-+      local uid="$3"
-+      local gid="$4"
-+      local ftype=$(filetype "${location}")
-+      # remap uid/gid to 0 if necessary
-+      [ "$root_uid" = "squash" ] && uid=0 || [ "$uid" -eq "$root_uid" ] && uid=0
-+      [ "$root_gid" = "squash" ] && gid=0 || [ "$gid" -eq "$root_gid" ] && gid=0
-+      local str="${mode} ${uid} ${gid}"
-+
-+      [ "${ftype}" = "invalid" ] && return 0
-+      [ "${location}" = "${srcdir}" ] && return 0
-+
-+      case "${ftype}" in
-+              "file")
-+                      str="${ftype} ${name} ${location} ${str}"
-+                      ;;
-+              "nod")
-+                      local dev=`LC_ALL=C ls -l "${location}"`
-+                      local maj=`field 5 ${dev}`
-+                      local min=`field 6 ${dev}`
-+                      maj=${maj%,}
-+
-+                      [ -b "${location}" ] && dev="b" || dev="c"
-+
-+                      str="${ftype} ${name} ${str} ${dev} ${maj} ${min}"
-+                      ;;
-+              "slink")
-+                      local target=`readlink "${location}"`
-+                      str="${ftype} ${name} ${target} ${str}"
-+                      ;;
-+              *)
-+                      str="${ftype} ${name} ${str}"
-+                      ;;
-+      esac
-+
-+      echo "${str}" >> ${output}
-+
-+      return 0
-+}
-+
-+unknown_option() {
-+      printf "ERROR: unknown option \"$arg\"\n" >&2
-+      printf "If the filename validly begins with '-', " >&2
-+      printf "then it must be prefixed\n" >&2
-+      printf "by './' so that it won't be interpreted as an option." >&2
-+      printf "\n" >&2
-+      usage >&2
-+      exit 1
-+}
-+
-+list_header() {
-+      :
-+}
-+
-+header() {
-+      printf "\n#####################\n# $1\n" >> ${output}
-+}
-+
-+# process one directory (incl sub-directories)
-+dir_filelist() {
-+      ${dep_list}header "$1"
-+
-+      srcdir=$(echo "$1" | sed -e 's://*:/:g')
-+      dirlist=$(find "${srcdir}" -printf "%p %m %U %G\n" | LANG=C sort)
-+
-+      # If $dirlist is only one line, then the directory is empty
-+      if [  "$(echo "${dirlist}" | wc -l)" -gt 1 ]; then
-+              ${dep_list}print_mtime "$1"
-+
-+              echo "${dirlist}" | \
-+              while read x; do
-+                      ${dep_list}parse ${x}
-+              done
-+      fi
-+}
-+
-+# if only one file is specified and it is .cpio file then use it direct as fs
-+# if a directory is specified then add all files in given direcotry to fs
-+# if a regular file is specified assume it is in gen_initramfs format
-+input_file() {
-+      source="$1"
-+      if [ -f "$1" ]; then
-+              ${dep_list}header "$1"
-+              is_cpio="$(echo "$1" | sed 's/^.*\.cpio\(\..*\)\{0,1\}/cpio/')"
-+              if [ $2 -eq 0 -a ${is_cpio} = "cpio" ]; then
-+                      cpio_file=$1
-+                      echo "$1" | grep -q '^.*\.cpio\..*' && is_cpio_compressed="compressed"
-+                      [ ! -z ${dep_list} ] && echo "$1"
-+                      return 0
-+              fi
-+              if [ -z ${dep_list} ]; then
-+                      print_mtime "$1" >> ${output}
-+                      cat "$1"         >> ${output}
-+              else
-+                      echo "$1 \\"
-+                      cat "$1" | while read type dir file perm ; do
-+                              if [ "$type" = "file" ]; then
-+                                      echo "$file \\";
-+                              fi
-+                      done
-+              fi
-+      elif [ -d "$1" ]; then
-+              dir_filelist "$1"
-+      else
-+              echo "  ${prog}: Cannot open '$1'" >&2
-+              exit 1
-+      fi
-+}
-+
-+prog=$0
-+root_uid=0
-+root_gid=0
-+dep_list=
-+cpio_file=
-+cpio_list=
-+output="/dev/stdout"
-+output_file=""
-+is_cpio_compressed=
-+compr="gzip -n -9 -f"
-+
-+arg="$1"
-+case "$arg" in
-+      "-l")   # files included in initramfs - used by kbuild
-+              dep_list="list_"
-+              echo "deps_initramfs := $0 \\"
-+              shift
-+              ;;
-+      "-o")   # generate compressed cpio image named $1
-+              shift
-+              output_file="$1"
-+              cpio_list="$(mktemp ${TMPDIR:-/tmp}/cpiolist.XXXXXX)"
-+              output=${cpio_list}
-+              echo "$output_file" | grep -q "\.gz$" \
-+                && [ -x "`which gzip 2> /dev/null`" ] \
-+                && compr="gzip -n -9 -f"
-+              echo "$output_file" | grep -q "\.bz2$" \
-+                && [ -x "`which bzip2 2> /dev/null`" ] \
-+                && compr="bzip2 -9 -f"
-+              echo "$output_file" | grep -q "\.lzma$" \
-+                && [ -x "`which lzma 2> /dev/null`" ] \
-+                && compr="lzma -9 -f"
-+              echo "$output_file" | grep -q "\.xz$" \
-+                && [ -x "`which xz 2> /dev/null`" ] \
-+                && compr="xz --check=crc32 --lzma2=dict=1MiB"
-+              echo "$output_file" | grep -q "\.lzo$" \
-+                && [ -x "`which lzop 2> /dev/null`" ] \
-+                && compr="lzop -9 -f"
-+              echo "$output_file" | grep -q "\.lz4$" \
-+                && [ -x "`which lz4 2> /dev/null`" ] \
-+                && compr="lz4 -l -9 -f"
-+              echo "$output_file" | grep -q "\.cpio$" && compr="cat"
-+              shift
-+              ;;
-+esac
-+while [ $# -gt 0 ]; do
-+      arg="$1"
-+      shift
-+      case "$arg" in
-+              "-u")   # map $1 to uid=0 (root)
-+                      root_uid="$1"
-+                      [ "$root_uid" = "-1" ] && root_uid=$(id -u || echo 0)
-+                      shift
-+                      ;;
-+              "-g")   # map $1 to gid=0 (root)
-+                      root_gid="$1"
-+                      [ "$root_gid" = "-1" ] && root_gid=$(id -g || echo 0)
-+                      shift
-+                      ;;
-+              "-d")   # display default initramfs list
-+                      default_list="$arg"
-+                      ${dep_list}default_initramfs
-+                      ;;
-+              "-h")
-+                      usage
-+                      exit 0
-+                      ;;
-+              *)
-+                      case "$arg" in
-+                              "-"*)
-+                                      unknown_option
-+                                      ;;
-+                              *)      # input file/dir - process it
-+                                      input_file "$arg" "$#"
-+                                      ;;
-+                      esac
-+                      ;;
-+      esac
-+done
-+
-+# If output_file is set we will generate cpio archive and compress it
-+# we are careful to delete tmp files
-+if [ ! -z ${output_file} ]; then
-+      if [ -z ${cpio_file} ]; then
-+              timestamp=
-+              if test -n "$KBUILD_BUILD_TIMESTAMP"; then
-+                      timestamp="$(date -d"$KBUILD_BUILD_TIMESTAMP" +%s || :)"
-+                      if test -n "$timestamp"; then
-+                              timestamp="-t $timestamp"
-+                      fi
-+              fi
-+              cpio_tfile="$(mktemp ${TMPDIR:-/tmp}/cpiofile.XXXXXX)"
-+              usr/gen_init_cpio $timestamp ${cpio_list} > ${cpio_tfile}
-+      else
-+              cpio_tfile=${cpio_file}
-+      fi
-+      rm ${cpio_list}
-+      if [ "${is_cpio_compressed}" = "compressed" ]; then
-+              cat ${cpio_tfile} > ${output_file}
-+      else
-+              (cat ${cpio_tfile} | ${compr}  - > ${output_file}) \
-+              || (rm -f ${output_file} ; false)
-+      fi
-+      [ -z ${cpio_file} ] && rm ${cpio_tfile}
-+fi
-+exit 0
diff --git a/target/linux/starfive/patches-6.6/0062-i2c-designware-Delete-SMBus-functionalities.patch b/target/linux/starfive/patches-6.6/0062-i2c-designware-Delete-SMBus-functionalities.patch
deleted file mode 100644 (file)
index 05561f1..0000000
+++ /dev/null
@@ -1,33 +0,0 @@
-From dcc2827ed6e701a65731c05b0297745559837217 Mon Sep 17 00:00:00 2001
-From: Hal Feng <hal.feng@starfivetech.com>
-Date: Fri, 12 May 2023 17:33:20 +0800
-Subject: [PATCH 062/116] i2c: designware: Delete SMBus functionalities
-
-The driver didn't implement the smbus interface,
-so replace the SMBus functionalities with
-I2C_FUNC_SMBUS_EMUL.
-
-Signed-off-by: Hal Feng <hal.feng@starfivetech.com>
----
- drivers/i2c/busses/i2c-designware-core.h | 10 ++++------
- 1 file changed, 4 insertions(+), 6 deletions(-)
-
---- a/drivers/i2c/busses/i2c-designware-core.h
-+++ b/drivers/i2c/busses/i2c-designware-core.h
-@@ -18,12 +18,10 @@
- #include <linux/regmap.h>
- #include <linux/types.h>
--#define DW_IC_DEFAULT_FUNCTIONALITY           (I2C_FUNC_I2C | \
--                                               I2C_FUNC_SMBUS_BYTE | \
--                                               I2C_FUNC_SMBUS_BYTE_DATA | \
--                                               I2C_FUNC_SMBUS_WORD_DATA | \
--                                               I2C_FUNC_SMBUS_BLOCK_DATA | \
--                                               I2C_FUNC_SMBUS_I2C_BLOCK)
-+#define DW_IC_DEFAULT_FUNCTIONALITY   (I2C_FUNC_I2C | (I2C_FUNC_SMBUS_EMUL \
-+                                      & ~I2C_FUNC_SMBUS_QUICK \
-+                                      & ~I2C_FUNC_SMBUS_PROC_CALL \
-+                                      & ~I2C_FUNC_SMBUS_PEC))
- #define DW_IC_CON_MASTER                      BIT(0)
- #define DW_IC_CON_SPEED_STD                   (1 << 1)
diff --git a/target/linux/starfive/patches-6.6/0063-drivers-mtd-gigadevice-add-gd25lq256d-32M-flash-supp.patch b/target/linux/starfive/patches-6.6/0063-drivers-mtd-gigadevice-add-gd25lq256d-32M-flash-supp.patch
deleted file mode 100644 (file)
index 43a7e5b..0000000
+++ /dev/null
@@ -1,26 +0,0 @@
-From b61cefc6c785aa8a7177a0b535db746fd0047bd8 Mon Sep 17 00:00:00 2001
-From: Ziv Xu <ziv.xu@starfivetech.com>
-Date: Fri, 19 Jan 2024 15:22:55 +0800
-Subject: [PATCH 063/116] drivers: mtd: gigadevice: add gd25lq256d 32M flash
- support
-
-add gd25lq256d 32M flash support
-
-Signed-off-by: Ziv Xu <ziv.xu@starfivetech.com>
----
- drivers/mtd/spi-nor/gigadevice.c | 4 ++++
- 1 file changed, 4 insertions(+)
-
---- a/drivers/mtd/spi-nor/gigadevice.c
-+++ b/drivers/mtd/spi-nor/gigadevice.c
-@@ -66,6 +66,10 @@ static const struct flash_info gigadevic
-               FLAGS(SPI_NOR_HAS_LOCK | SPI_NOR_HAS_TB)
-               NO_SFDP_FLAGS(SECT_4K | SPI_NOR_DUAL_READ |
-                             SPI_NOR_QUAD_READ) },
-+      { "gd25lq256d", INFO(0xc86019, 0, 64 * 1024, 512)
-+              FLAGS( SPI_NOR_HAS_LOCK | SPI_NOR_HAS_TB | SPI_NOR_QUAD_PP)
-+              NO_SFDP_FLAGS(SECT_4K | SPI_NOR_DUAL_READ |
-+                              SPI_NOR_QUAD_READ) },
-       { "gd25q256", INFO(0xc84019, 0, 64 * 1024, 512)
-               PARSE_SFDP
-               FLAGS(SPI_NOR_HAS_LOCK | SPI_NOR_HAS_TB | SPI_NOR_TB_SR_BIT6)
diff --git a/target/linux/starfive/patches-6.6/0064-driver-mailbox-Add-mailbox-driver.patch b/target/linux/starfive/patches-6.6/0064-driver-mailbox-Add-mailbox-driver.patch
deleted file mode 100644 (file)
index b733110..0000000
+++ /dev/null
@@ -1,808 +0,0 @@
-From 76bc13aa12bd111f5da01e107f8d487b20b5a40c Mon Sep 17 00:00:00 2001
-From: "shanlong.li" <shanlong.li@starfivetech.com>
-Date: Thu, 8 Jun 2023 00:07:15 -0700
-Subject: [PATCH 064/116] driver: mailbox: Add mailbox driver
-
-Add mailbox driver.
-
-Signed-off-by: shanlong.li <shanlong.li@starfivetech.com>
-Signed-off-by: Hal Feng <hal.feng@starfivetech.com>
----
- drivers/mailbox/Kconfig                 |  13 +
- drivers/mailbox/Makefile                |   4 +
- drivers/mailbox/starfive_mailbox-test.c | 407 ++++++++++++++++++++++++
- drivers/mailbox/starfive_mailbox.c      | 347 ++++++++++++++++++++
- 4 files changed, 771 insertions(+)
- create mode 100644 drivers/mailbox/starfive_mailbox-test.c
- create mode 100644 drivers/mailbox/starfive_mailbox.c
-
---- a/drivers/mailbox/Kconfig
-+++ b/drivers/mailbox/Kconfig
-@@ -295,4 +295,17 @@ config QCOM_IPCC
-         acts as an interrupt controller for receiving interrupts from clients.
-         Say Y here if you want to build this driver.
-+config STARFIVE_MBOX
-+      tristate "Platform Starfive Mailbox"
-+      depends on OF
-+      help
-+        Say Y here if you want to build a platform specific variant RISCV
-+        controller driver.
-+
-+config STARFIVE_MBOX_TEST
-+      tristate "Starfive Mailbox Test Client"
-+      depends on OF
-+      depends on HAS_IOMEM
-+      help
-+        Test client to help with testing new Controller driver implementations.
- endif
---- a/drivers/mailbox/Makefile
-+++ b/drivers/mailbox/Makefile
-@@ -62,3 +62,7 @@ obj-$(CONFIG_SPRD_MBOX)              += sprd-mailbox
- obj-$(CONFIG_QCOM_IPCC)               += qcom-ipcc.o
- obj-$(CONFIG_APPLE_MAILBOX)   += apple-mailbox.o
-+
-+obj-$(CONFIG_STARFIVE_MBOX)    += starfive_mailbox.o
-+
-+obj-$(CONFIG_STARFIVE_MBOX_TEST)    += starfive_mailbox-test.o
---- /dev/null
-+++ b/drivers/mailbox/starfive_mailbox-test.c
-@@ -0,0 +1,407 @@
-+// SPDX-License-Identifier: GPL-2.0-or-later
-+/*
-+ * Copyright (C) 2015 ST Microelectronics
-+ *
-+ * Author: Lee Jones <lee.jones@linaro.org>
-+ */
-+
-+#include <linux/debugfs.h>
-+#include <linux/err.h>
-+#include <linux/fs.h>
-+#include <linux/io.h>
-+#include <linux/kernel.h>
-+#include <linux/mailbox_client.h>
-+#include <linux/module.h>
-+#include <linux/of.h>
-+#include <linux/platform_device.h>
-+#include <linux/poll.h>
-+#include <linux/slab.h>
-+#include <linux/uaccess.h>
-+#include <linux/sched/signal.h>
-+
-+#include <linux/mailbox_controller.h>
-+
-+#define MBOX_MAX_SIG_LEN      8
-+#define MBOX_MAX_MSG_LEN      16
-+#define MBOX_BYTES_PER_LINE   16
-+#define MBOX_HEXDUMP_LINE_LEN ((MBOX_BYTES_PER_LINE * 4) + 2)
-+#define MBOX_HEXDUMP_MAX_LEN  (MBOX_HEXDUMP_LINE_LEN * (MBOX_MAX_MSG_LEN / MBOX_BYTES_PER_LINE))
-+
-+static bool mbox_data_ready;
-+
-+struct mbox_test_device {
-+      struct device           *dev;
-+      void __iomem            *tx_mmio;
-+      void __iomem            *rx_mmio;
-+      struct mbox_chan        *tx_channel;
-+      struct mbox_chan        *rx_channel;
-+      char                    *rx_buffer;
-+      char                    *signal;
-+      char                    *message;
-+      spinlock_t              lock;
-+      wait_queue_head_t       waitq;
-+      struct fasync_struct    *async_queue;
-+      struct dentry           *root_debugfs_dir;
-+};
-+
-+static ssize_t mbox_test_signal_write(struct file *filp,
-+              const char __user *userbuf,
-+              size_t count, loff_t *ppos)
-+{
-+      struct mbox_test_device *tdev = filp->private_data;
-+
-+      if (!tdev->tx_channel) {
-+              dev_err(tdev->dev, "Channel cannot do Tx\n");
-+              return -EINVAL;
-+      }
-+
-+      if (count > MBOX_MAX_SIG_LEN) {
-+              dev_err(tdev->dev,
-+                      "Signal length %zd greater than max allowed %d\n",
-+                      count, MBOX_MAX_SIG_LEN);
-+              return -EINVAL;
-+      }
-+
-+      /* Only allocate memory if we need to */
-+      if (!tdev->signal) {
-+              tdev->signal = kzalloc(MBOX_MAX_SIG_LEN, GFP_KERNEL);
-+              if (!tdev->signal)
-+                      return -ENOMEM;
-+      }
-+
-+      if (copy_from_user(tdev->signal, userbuf, count)) {
-+              kfree(tdev->signal);
-+              tdev->signal = NULL;
-+              return -EFAULT;
-+      }
-+
-+      return count;
-+}
-+
-+static const struct file_operations mbox_test_signal_ops = {
-+      .write = mbox_test_signal_write,
-+      .open = simple_open,
-+      .llseek = generic_file_llseek,
-+};
-+
-+static int mbox_test_message_fasync(int fd, struct file *filp, int on)
-+{
-+      struct mbox_test_device *tdev = filp->private_data;
-+
-+      return fasync_helper(fd, filp, on, &tdev->async_queue);
-+}
-+
-+static ssize_t mbox_test_message_write(struct file *filp,
-+              const char __user *userbuf,
-+              size_t count, loff_t *ppos)
-+{
-+      struct mbox_test_device *tdev = filp->private_data;
-+      void *data;
-+      int ret;
-+
-+      if (!tdev->tx_channel) {
-+              dev_err(tdev->dev, "Channel cannot do Tx\n");
-+              return -EINVAL;
-+      }
-+
-+      if (count > MBOX_MAX_MSG_LEN) {
-+              dev_err(tdev->dev,
-+                      "Message length %zd greater than max allowed %d\n",
-+                      count, MBOX_MAX_MSG_LEN);
-+              return -EINVAL;
-+      }
-+
-+      tdev->message = kzalloc(MBOX_MAX_MSG_LEN, GFP_KERNEL);
-+      if (!tdev->message)
-+              return -ENOMEM;
-+
-+      ret = copy_from_user(tdev->message, userbuf, count);
-+      if (ret) {
-+              ret = -EFAULT;
-+              goto out;
-+      }
-+
-+      if (tdev->tx_mmio && tdev->signal) {
-+              print_hex_dump_bytes("Client: Sending: Signal: ", DUMP_PREFIX_ADDRESS,
-+                      tdev->signal, MBOX_MAX_SIG_LEN);
-+
-+              data = tdev->signal;
-+      } else
-+              data = tdev->message;
-+
-+      print_hex_dump_bytes("Client: Sending: Message: ", DUMP_PREFIX_ADDRESS,
-+              tdev->message, MBOX_MAX_MSG_LEN);
-+
-+      ret = mbox_send_message(tdev->tx_channel, data);
-+      mbox_chan_txdone(tdev->tx_channel, ret);
-+      if (ret < 0)
-+              dev_err(tdev->dev, "Failed to send message via mailbox\n");
-+
-+out:
-+      kfree(tdev->signal);
-+      kfree(tdev->message);
-+      tdev->signal = NULL;
-+
-+      return ret < 0 ? ret : count;
-+}
-+
-+static bool mbox_test_message_data_ready(struct mbox_test_device *tdev)
-+{
-+      bool data_ready;
-+      unsigned long flags;
-+
-+      spin_lock_irqsave(&tdev->lock, flags);
-+      data_ready = mbox_data_ready;
-+      spin_unlock_irqrestore(&tdev->lock, flags);
-+
-+      return data_ready;
-+}
-+
-+static ssize_t mbox_test_message_read(struct file *filp, char __user *userbuf,
-+              size_t count, loff_t *ppos)
-+{
-+      struct mbox_test_device *tdev = filp->private_data;
-+      unsigned long flags;
-+      char *touser, *ptr;
-+      int ret;
-+
-+      touser = kzalloc(MBOX_HEXDUMP_MAX_LEN + 1, GFP_KERNEL);
-+      if (!touser)
-+              return -ENOMEM;
-+
-+      if (!tdev->rx_channel) {
-+              ret = snprintf(touser, 20, "<NO RX CAPABILITY>\n");
-+              ret = simple_read_from_buffer(userbuf, count, ppos,
-+                      touser, ret);
-+              goto kfree_err;
-+      }
-+
-+      do {
-+              if (mbox_test_message_data_ready(tdev))
-+                      break;
-+
-+              if (filp->f_flags & O_NONBLOCK) {
-+                      ret = -EAGAIN;
-+                      goto waitq_err;
-+              }
-+
-+              if (signal_pending(current)) {
-+                      ret = -ERESTARTSYS;
-+                      goto waitq_err;
-+              }
-+              schedule();
-+
-+      } while (1);
-+
-+      spin_lock_irqsave(&tdev->lock, flags);
-+
-+      ptr = tdev->rx_buffer;
-+
-+      mbox_data_ready = false;
-+
-+      spin_unlock_irqrestore(&tdev->lock, flags);
-+      if (copy_to_user((void __user *)userbuf, ptr, 4))
-+              ret = -EFAULT;
-+
-+waitq_err:
-+      __set_current_state(TASK_RUNNING);
-+kfree_err:
-+      kfree(touser);
-+      return ret;
-+}
-+
-+static __poll_t
-+mbox_test_message_poll(struct file *filp, struct poll_table_struct *wait)
-+{
-+      struct mbox_test_device *tdev = filp->private_data;
-+
-+      poll_wait(filp, &tdev->waitq, wait);
-+
-+      if (mbox_test_message_data_ready(tdev))
-+              return EPOLLIN | EPOLLRDNORM;
-+      return 0;
-+}
-+
-+static const struct file_operations mbox_test_message_ops = {
-+      .write = mbox_test_message_write,
-+      .read = mbox_test_message_read,
-+      .fasync = mbox_test_message_fasync,
-+      .poll = mbox_test_message_poll,
-+      .open = simple_open,
-+      .llseek = generic_file_llseek,
-+};
-+
-+static int mbox_test_add_debugfs(struct platform_device *pdev,
-+              struct mbox_test_device *tdev)
-+{
-+      if (!debugfs_initialized())
-+              return 0;
-+
-+      tdev->root_debugfs_dir = debugfs_create_dir(dev_name(&pdev->dev), NULL);
-+      if (!tdev->root_debugfs_dir) {
-+              dev_err(&pdev->dev, "Failed to create Mailbox debugfs\n");
-+              return -EINVAL;
-+      }
-+
-+      debugfs_create_file("message", 0600, tdev->root_debugfs_dir,
-+              tdev, &mbox_test_message_ops);
-+
-+      debugfs_create_file("signal", 0200, tdev->root_debugfs_dir,
-+              tdev, &mbox_test_signal_ops);
-+
-+      return 0;
-+}
-+
-+static void mbox_test_receive_message(struct mbox_client *client, void *message)
-+{
-+      struct mbox_test_device *tdev = dev_get_drvdata(client->dev);
-+      unsigned long flags;
-+
-+      spin_lock_irqsave(&tdev->lock, flags);
-+      if (tdev->rx_mmio) {
-+              memcpy_fromio(tdev->rx_buffer, tdev->rx_mmio, MBOX_MAX_MSG_LEN);
-+              print_hex_dump_bytes("Client: Received [MMIO]: ", DUMP_PREFIX_ADDRESS,
-+                      tdev->rx_buffer, MBOX_MAX_MSG_LEN);
-+      } else if (message) {
-+              print_hex_dump_bytes("Client: Received [API]: ", DUMP_PREFIX_ADDRESS,
-+                      message, MBOX_MAX_MSG_LEN);
-+              memcpy(tdev->rx_buffer, message, MBOX_MAX_MSG_LEN);
-+      }
-+      mbox_data_ready = true;
-+      spin_unlock_irqrestore(&tdev->lock, flags);
-+}
-+
-+static void mbox_test_prepare_message(struct mbox_client *client, void *message)
-+{
-+      struct mbox_test_device *tdev = dev_get_drvdata(client->dev);
-+
-+      if (tdev->tx_mmio) {
-+              if (tdev->signal)
-+                      memcpy_toio(tdev->tx_mmio, tdev->message, MBOX_MAX_MSG_LEN);
-+              else
-+                      memcpy_toio(tdev->tx_mmio, message, MBOX_MAX_MSG_LEN);
-+      }
-+}
-+
-+static struct mbox_chan *
-+mbox_test_request_channel(struct platform_device *pdev, const char *name)
-+{
-+      struct mbox_client *client;
-+      struct mbox_chan *channel;
-+
-+      client = devm_kzalloc(&pdev->dev, sizeof(*client), GFP_KERNEL);
-+      if (!client)
-+              return ERR_PTR(-ENOMEM);
-+
-+      client->dev        = &pdev->dev;
-+      client->rx_callback    = mbox_test_receive_message;
-+      client->tx_prepare    = mbox_test_prepare_message;
-+      client->tx_block    = false;
-+      client->knows_txdone    = false;
-+      client->tx_tout        = 500;
-+
-+      channel = mbox_request_channel_byname(client, name);
-+      if (IS_ERR(channel)) {
-+              dev_warn(&pdev->dev, "Failed to request %s channel\n", name);
-+              return NULL;
-+      }
-+
-+      return channel;
-+}
-+
-+static int mbox_test_probe(struct platform_device *pdev)
-+{
-+      struct mbox_test_device *tdev;
-+      struct resource *res;
-+      resource_size_t size;
-+      int ret;
-+
-+      tdev = devm_kzalloc(&pdev->dev, sizeof(*tdev), GFP_KERNEL);
-+      if (!tdev)
-+              return -ENOMEM;
-+
-+      /* It's okay for MMIO to be NULL */
-+      res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-+      tdev->tx_mmio = devm_ioremap_resource(&pdev->dev, res);
-+      if (PTR_ERR(tdev->tx_mmio) == -EBUSY) {
-+              /* if reserved area in SRAM, try just ioremap */
-+              size = resource_size(res);
-+              tdev->tx_mmio = devm_ioremap(&pdev->dev, res->start, size);
-+      } else if (IS_ERR(tdev->tx_mmio)) {
-+              tdev->tx_mmio = NULL;
-+      }
-+
-+      /* If specified, second reg entry is Rx MMIO */
-+      res = platform_get_resource(pdev, IORESOURCE_MEM, 1);
-+      tdev->rx_mmio = devm_ioremap_resource(&pdev->dev, res);
-+      if (PTR_ERR(tdev->rx_mmio) == -EBUSY) {
-+              size = resource_size(res);
-+              tdev->rx_mmio = devm_ioremap(&pdev->dev, res->start, size);
-+      } else if (IS_ERR(tdev->rx_mmio)) {
-+              tdev->rx_mmio = tdev->tx_mmio;
-+      }
-+
-+      tdev->tx_channel = mbox_test_request_channel(pdev, "tx");
-+      tdev->rx_channel = mbox_test_request_channel(pdev, "rx");
-+
-+      if (!tdev->tx_channel && !tdev->rx_channel)
-+              return -EPROBE_DEFER;
-+
-+      /* If Rx is not specified but has Rx MMIO, then Rx = Tx */
-+      if (!tdev->rx_channel && (tdev->rx_mmio != tdev->tx_mmio))
-+              tdev->rx_channel = tdev->tx_channel;
-+
-+      tdev->dev = &pdev->dev;
-+      platform_set_drvdata(pdev, tdev);
-+
-+      spin_lock_init(&tdev->lock);
-+
-+      if (tdev->rx_channel) {
-+              tdev->rx_buffer = devm_kzalloc(&pdev->dev,
-+                      MBOX_MAX_MSG_LEN, GFP_KERNEL);
-+              if (!tdev->rx_buffer)
-+                      return -ENOMEM;
-+      }
-+
-+      ret = mbox_test_add_debugfs(pdev, tdev);
-+      if (ret)
-+              return ret;
-+
-+      dev_info(&pdev->dev, "Successfully registered\n");
-+
-+      return 0;
-+}
-+
-+static int mbox_test_remove(struct platform_device *pdev)
-+{
-+      struct mbox_test_device *tdev = platform_get_drvdata(pdev);
-+
-+      debugfs_remove_recursive(tdev->root_debugfs_dir);
-+
-+      if (tdev->tx_channel)
-+              mbox_free_channel(tdev->tx_channel);
-+      if (tdev->rx_channel)
-+              mbox_free_channel(tdev->rx_channel);
-+
-+      return 0;
-+}
-+
-+static const struct of_device_id mbox_test_match[] = {
-+      { .compatible = "starfive,mailbox-test" },
-+      {},
-+};
-+MODULE_DEVICE_TABLE(of, mbox_test_match);
-+
-+static struct platform_driver mbox_test_driver = {
-+      .driver = {
-+              .name = "mailbox_test",
-+              .of_match_table = mbox_test_match,
-+      },
-+      .probe  = mbox_test_probe,
-+      .remove = mbox_test_remove,
-+};
-+module_platform_driver(mbox_test_driver);
-+
-+MODULE_DESCRIPTION("Generic Mailbox Testing Facility");
-+MODULE_AUTHOR("Lee Jones <lee.jones@linaro.org");
-+MODULE_LICENSE("GPL v2");
---- /dev/null
-+++ b/drivers/mailbox/starfive_mailbox.c
-@@ -0,0 +1,347 @@
-+// SPDX-License-Identifier: GPL-2.0
-+/*
-+ * mailbox driver for StarFive JH7110 SoC
-+ *
-+ * Copyright (c) 2021 StarFive Technology Co., Ltd.
-+ * Author: Shanlong Li <shanlong.li@starfivetech.com>
-+ */
-+
-+#include <linux/bitops.h>
-+#include <linux/delay.h>
-+#include <linux/device.h>
-+#include <linux/err.h>
-+#include <linux/interrupt.h>
-+#include <linux/io.h>
-+#include <linux/iopoll.h>
-+#include <linux/mailbox_controller.h>
-+#include <linux/module.h>
-+#include <linux/platform_device.h>
-+#include <linux/slab.h>
-+#include <linux/clk.h>
-+#include <linux/reset.h>
-+#include <linux/pm_runtime.h>
-+
-+#include "mailbox.h"
-+
-+#define MBOX_CHAN_MAX         4
-+
-+#define MBOX_BASE(mbox, ch)   ((mbox)->base + ((ch) * 0x10))
-+#define MBOX_IRQ_REG          0x00
-+#define MBOX_SET_REG          0x04
-+#define MBOX_CLR_REG          0x08
-+#define MBOX_CMD_REG          0x0c
-+#define MBC_PEND_SMRY         0x100
-+
-+typedef enum {
-+      MAILBOX_CORE_U7 = 0,
-+      MAILBOX_CORE_HIFI4,
-+      MAILBOX_CORE_E2,
-+      MAILBOX_CORE_RSVD0,
-+      MAILBOX_CORE_NUM,
-+} mailbox_core_t;
-+
-+struct mailbox_irq_name_c{
-+      int id;
-+      char name[16];
-+};
-+
-+static const struct mailbox_irq_name_c irq_peer_name[MBOX_CHAN_MAX] = {
-+      {MAILBOX_CORE_U7,    "u74_core"},
-+      {MAILBOX_CORE_HIFI4, "hifi4_core"},
-+      {MAILBOX_CORE_E2,    "e24_core"},
-+      {MAILBOX_CORE_RSVD0, "" },
-+};
-+
-+/**
-+ * starfive mailbox channel information
-+ *
-+ * A channel can be used for TX or RX, it can trigger remote
-+ * processor interrupt to notify remote processor and can receive
-+ * interrupt if has incoming message.
-+ *
-+ * @dst_irq:    Interrupt vector for remote processor
-+ * @core_id:    id for remote processor
-+ */
-+struct starfive_chan_info {
-+      unsigned int dst_irq;
-+      mailbox_core_t core_id;
-+};
-+
-+/**
-+ * starfive mailbox controller data
-+ *
-+ * Mailbox controller includes 4 channels and can allocate
-+ * channel for message transferring.
-+ *
-+ * @dev:    Device to which it is attached
-+ * @base:    Base address of the register mapping region
-+ * @chan:    Representation of channels in mailbox controller
-+ * @mchan:    Representation of channel info
-+ * @controller:    Representation of a communication channel controller
-+ */
-+struct starfive_mbox {
-+      struct device *dev;
-+      void __iomem *base;
-+      struct mbox_chan chan[MBOX_CHAN_MAX];
-+      struct starfive_chan_info mchan[MBOX_CHAN_MAX];
-+      struct mbox_controller controller;
-+      struct clk *clk;
-+      struct reset_control *rst_rresetn;
-+};
-+
-+static struct starfive_mbox *to_starfive_mbox(struct mbox_controller *mbox)
-+{
-+      return container_of(mbox, struct starfive_mbox, controller);
-+}
-+
-+static struct mbox_chan *
-+starfive_of_mbox_index_xlate(struct mbox_controller *mbox,
-+                      const struct of_phandle_args *sp)
-+{
-+      struct starfive_mbox *sbox;
-+
-+      int ind = sp->args[0];
-+      int core_id = sp->args[1];
-+
-+      if (ind >= mbox->num_chans || core_id >= MAILBOX_CORE_NUM)
-+              return ERR_PTR(-EINVAL);
-+
-+      sbox = to_starfive_mbox(mbox);
-+
-+      sbox->mchan[ind].core_id = core_id;
-+
-+      return &mbox->chans[ind];
-+}
-+
-+static irqreturn_t starfive_rx_irq_handler(int irq, void *p)
-+{
-+      struct mbox_chan *chan = p;
-+      unsigned long ch = (unsigned long)chan->con_priv;
-+      struct starfive_mbox *mbox = to_starfive_mbox(chan->mbox);
-+      void __iomem *base = MBOX_BASE(mbox, ch);
-+      u32 val;
-+
-+      val = readl(base + MBOX_CMD_REG);
-+      if (!val)
-+              return IRQ_NONE;
-+
-+      mbox_chan_received_data(chan, (void *)&val);
-+      writel(val, base + MBOX_CLR_REG);
-+      return IRQ_HANDLED;
-+}
-+
-+static int starfive_mbox_check_state(struct mbox_chan *chan)
-+{
-+      unsigned long ch = (unsigned long)chan->con_priv;
-+      struct starfive_mbox *mbox = to_starfive_mbox(chan->mbox);
-+      unsigned long irq_flag = IRQF_SHARED;
-+      long ret = 0;
-+
-+      pm_runtime_get_sync(mbox->dev);
-+      /* MAILBOX should be with IRQF_NO_SUSPEND set */
-+      if (!mbox->dev->pm_domain)
-+              irq_flag |= IRQF_NO_SUSPEND;
-+
-+      /* Mailbox is idle so directly bail out */
-+      if (readl(mbox->base + MBC_PEND_SMRY) & BIT(ch))
-+              return -EBUSY;
-+
-+      if (mbox->mchan[ch].dst_irq > 0) {
-+              dev_dbg(mbox->dev, "%s: host IRQ = %d, ch:%ld", __func__, mbox->mchan[ch].dst_irq, ch);
-+              ret = devm_request_irq(mbox->dev, mbox->mchan[ch].dst_irq, starfive_rx_irq_handler,
-+                      irq_flag, irq_peer_name[ch].name, chan);
-+              if (ret < 0)
-+                      dev_err(mbox->dev, "request_irq %d failed\n", mbox->mchan[ch].dst_irq);
-+      }
-+
-+      return ret;
-+}
-+
-+static int starfive_mbox_startup(struct mbox_chan *chan)
-+{
-+      return starfive_mbox_check_state(chan);
-+}
-+
-+static void starfive_mbox_shutdown(struct mbox_chan *chan)
-+{
-+      struct starfive_mbox *mbox = to_starfive_mbox(chan->mbox);
-+      unsigned long ch = (unsigned long)chan->con_priv;
-+      void __iomem *base = MBOX_BASE(mbox, ch);
-+
-+      writel(0x0, base + MBOX_IRQ_REG);
-+      writel(0x0, base + MBOX_CLR_REG);
-+
-+      if (mbox->mchan[ch].dst_irq > 0)
-+              devm_free_irq(mbox->dev, mbox->mchan[ch].dst_irq, chan);
-+      pm_runtime_put_sync(mbox->dev);
-+}
-+
-+static int starfive_mbox_send_data(struct mbox_chan *chan, void *msg)
-+{
-+      unsigned long ch = (unsigned long)chan->con_priv;
-+      struct starfive_mbox *mbox = to_starfive_mbox(chan->mbox);
-+      struct starfive_chan_info *mchan = &mbox->mchan[ch];
-+      void __iomem *base = MBOX_BASE(mbox, ch);
-+      u32 *buf = msg;
-+
-+      /* Ensure channel is released */
-+      if (readl(mbox->base + MBC_PEND_SMRY) & BIT(ch)) {
-+              pr_debug("%s:%d. busy\n", __func__, __LINE__);
-+              return -EBUSY;
-+      }
-+
-+      /* Clear mask for destination interrupt */
-+      writel(BIT(mchan->core_id), base + MBOX_IRQ_REG);
-+
-+      /* Fill message data */
-+      writel(*buf, base + MBOX_SET_REG);
-+      return 0;
-+}
-+
-+static struct mbox_chan_ops starfive_mbox_ops = {
-+      .startup = starfive_mbox_startup,
-+      .send_data = starfive_mbox_send_data,
-+      .shutdown = starfive_mbox_shutdown,
-+};
-+
-+static const struct of_device_id starfive_mbox_of_match[] = {
-+      { .compatible = "starfive,mail_box",},
-+      {},
-+};
-+
-+MODULE_DEVICE_TABLE(of, starfive_mbox_of_match);
-+
-+void starfive_mailbox_init(struct starfive_mbox *mbox)
-+{
-+      mbox->clk = devm_clk_get_optional(mbox->dev, "clk_apb");
-+      if (IS_ERR(mbox->clk)) {
-+              dev_err(mbox->dev, "failed to get mailbox\n");
-+              return;
-+      }
-+
-+      mbox->rst_rresetn = devm_reset_control_get_exclusive(mbox->dev, "mbx_rre");
-+      if (IS_ERR(mbox->rst_rresetn)) {
-+              dev_err(mbox->dev, "failed to get mailbox reset\n");
-+              return;
-+      }
-+
-+      clk_prepare_enable(mbox->clk);
-+      reset_control_deassert(mbox->rst_rresetn);
-+}
-+
-+static int starfive_mbox_probe(struct platform_device *pdev)
-+{
-+      struct device *dev = &pdev->dev;
-+      struct starfive_mbox *mbox;
-+      struct mbox_chan *chan;
-+      struct resource *res;
-+      unsigned long ch;
-+      int err;
-+
-+      mbox = devm_kzalloc(dev, sizeof(*mbox), GFP_KERNEL);
-+      if (!mbox)
-+              return -ENOMEM;
-+
-+      res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-+      mbox->base = devm_ioremap_resource(dev, res);
-+      mbox->dev = dev;
-+
-+      if (IS_ERR(mbox->base))
-+              return PTR_ERR(mbox->base);
-+
-+      starfive_mailbox_init(mbox);
-+
-+      mbox->controller.dev = dev;
-+      mbox->controller.chans = mbox->chan;
-+      mbox->controller.num_chans = MBOX_CHAN_MAX;
-+      mbox->controller.ops = &starfive_mbox_ops;
-+      mbox->controller.of_xlate = starfive_of_mbox_index_xlate;
-+      mbox->controller.txdone_irq = true;
-+      mbox->controller.txdone_poll = false;
-+
-+      /* Initialize mailbox channel data */
-+      chan = mbox->chan;
-+      for (ch = 0; ch < MBOX_CHAN_MAX; ch++) {
-+              mbox->mchan[ch].dst_irq = 0;
-+              mbox->mchan[ch].core_id = (mailbox_core_t)ch;
-+              chan[ch].con_priv = (void *)ch;
-+      }
-+      mbox->mchan[MAILBOX_CORE_HIFI4].dst_irq = platform_get_irq(pdev, 0);
-+      mbox->mchan[MAILBOX_CORE_E2].dst_irq = platform_get_irq(pdev, 1);
-+
-+      err = mbox_controller_register(&mbox->controller);
-+      if (err) {
-+              dev_err(dev, "Failed to register mailbox %d\n", err);
-+              return err;
-+      }
-+
-+      platform_set_drvdata(pdev, mbox);
-+      dev_info(dev, "Mailbox enabled\n");
-+      pm_runtime_set_active(dev);
-+      pm_runtime_enable(dev);
-+
-+      return 0;
-+}
-+
-+static int starfive_mbox_remove(struct platform_device *pdev)
-+{
-+      struct starfive_mbox *mbox = platform_get_drvdata(pdev);
-+
-+      mbox_controller_unregister(&mbox->controller);
-+      devm_clk_put(mbox->dev, mbox->clk);
-+      pm_runtime_disable(mbox->dev);
-+
-+      return 0;
-+}
-+
-+static int __maybe_unused starfive_mbox_suspend(struct device *dev)
-+{
-+      struct starfive_mbox *mbox = dev_get_drvdata(dev);
-+
-+      clk_disable_unprepare(mbox->clk);
-+
-+      return 0;
-+}
-+
-+static int __maybe_unused starfive_mbox_resume(struct device *dev)
-+{
-+      struct starfive_mbox *mbox = dev_get_drvdata(dev);
-+      int ret;
-+
-+      ret = clk_prepare_enable(mbox->clk);
-+      if (ret)
-+              dev_err(dev, "failed to enable clock\n");
-+
-+      return ret;
-+}
-+
-+static const struct dev_pm_ops starfive_mbox_pm_ops = {
-+      .suspend = starfive_mbox_suspend,
-+      .resume = starfive_mbox_resume,
-+      SET_RUNTIME_PM_OPS(starfive_mbox_suspend, starfive_mbox_resume, NULL)
-+};
-+static struct platform_driver starfive_mbox_driver = {
-+      .probe  = starfive_mbox_probe,
-+      .remove = starfive_mbox_remove,
-+      .driver = {
-+      .name = "mailbox",
-+              .of_match_table = starfive_mbox_of_match,
-+              .pm = &starfive_mbox_pm_ops,
-+      },
-+};
-+
-+static int __init starfive_mbox_init(void)
-+{
-+      return platform_driver_register(&starfive_mbox_driver);
-+}
-+core_initcall(starfive_mbox_init);
-+
-+static void __exit starfive_mbox_exit(void)
-+{
-+      platform_driver_unregister(&starfive_mbox_driver);
-+}
-+module_exit(starfive_mbox_exit);
-+
-+MODULE_DESCRIPTION("StarFive Mailbox Controller driver");
-+MODULE_AUTHOR("Shanlong Li <shanlong.li@starfivetech.com>");
-+MODULE_LICENSE("GPL");
diff --git a/target/linux/starfive/patches-6.6/0065-driver-rtc-Add-StarFive-JH7110-rtc-driver.patch b/target/linux/starfive/patches-6.6/0065-driver-rtc-Add-StarFive-JH7110-rtc-driver.patch
deleted file mode 100644 (file)
index 0257cb0..0000000
+++ /dev/null
@@ -1,789 +0,0 @@
-From 0f44bd6bec708782f38bba4d03deecf927d1c83d Mon Sep 17 00:00:00 2001
-From: "ziv.xu" <ziv.xu@starfivetech.com>
-Date: Fri, 9 Jun 2023 15:31:53 +0800
-Subject: [PATCH 065/116] driver: rtc: Add StarFive JH7110 rtc driver
-
-Add RTC driver and support for StarFive JH7110 SoC.
-
-Signed-off-by: ziv.xu <ziv.xu@starfivetech.com>
-Signed-off-by: Hal Feng <hal.feng@starfivetech.com>
----
- drivers/rtc/Kconfig        |   8 +
- drivers/rtc/Makefile       |   1 +
- drivers/rtc/rtc-starfive.c | 743 +++++++++++++++++++++++++++++++++++++
- 3 files changed, 752 insertions(+)
- create mode 100644 drivers/rtc/rtc-starfive.c
-
---- a/drivers/rtc/Kconfig
-+++ b/drivers/rtc/Kconfig
-@@ -1327,6 +1327,14 @@ config RTC_DRV_NTXEC
-         embedded controller found in certain e-book readers designed by the
-         original design manufacturer Netronix.
-+config RTC_DRV_STARFIVE
-+      tristate "StarFive 32.768k-RTC"
-+      depends on ARCH_STARFIVE
-+      depends on OF
-+      help
-+        If you say Y here you will get support for the RTC found on
-+        StarFive SOCS.
-+
- comment "on-CPU RTC drivers"
- config RTC_DRV_ASM9260
---- a/drivers/rtc/Makefile
-+++ b/drivers/rtc/Makefile
-@@ -163,6 +163,7 @@ obj-$(CONFIG_RTC_DRV_SH)   += rtc-sh.o
- obj-$(CONFIG_RTC_DRV_SNVS)    += rtc-snvs.o
- obj-$(CONFIG_RTC_DRV_SPEAR)   += rtc-spear.o
- obj-$(CONFIG_RTC_DRV_STARFIRE)        += rtc-starfire.o
-+obj-$(CONFIG_RTC_DRV_STARFIVE)        += rtc-starfive.o
- obj-$(CONFIG_RTC_DRV_STK17TA8)        += rtc-stk17ta8.o
- obj-$(CONFIG_RTC_DRV_ST_LPC)  += rtc-st-lpc.o
- obj-$(CONFIG_RTC_DRV_STM32)   += rtc-stm32.o
---- /dev/null
-+++ b/drivers/rtc/rtc-starfive.c
-@@ -0,0 +1,743 @@
-+// SPDX-License-Identifier: GPL-2.0
-+/*
-+ * RTC driver for the StarFive JH7110 SoC
-+ *
-+ * Copyright (C) 2021 StarFive Technology Co., Ltd.
-+ */
-+
-+#include <asm/delay.h>
-+#include <linux/bcd.h>
-+#include <linux/bitfield.h>
-+#include <linux/clk.h>
-+#include <linux/reset.h>
-+#include <linux/completion.h>
-+#include <linux/interrupt.h>
-+#include <linux/io.h>
-+#include <linux/module.h>
-+#include <linux/of.h>
-+#include <linux/of_irq.h>
-+#include <linux/iopoll.h>
-+#include <linux/platform_device.h>
-+#include <linux/rtc.h>
-+
-+/* Registers */
-+#define SFT_RTC_CFG           0x00
-+#define SFT_RTC_SW_CAL_VALUE  0x04
-+#define SFT_RTC_HW_CAL_CFG    0x08
-+#define SFT_RTC_CMP_CFG               0x0C
-+#define SFT_RTC_IRQ_EN                0x10
-+#define SFT_RTC_IRQ_EVEVT     0x14
-+#define SFT_RTC_IRQ_STATUS    0x18
-+#define SFT_RTC_CAL_VALUE     0x24
-+#define SFT_RTC_CFG_TIME      0x28
-+#define SFT_RTC_CFG_DATE      0x2C
-+#define SFT_RTC_ACT_TIME      0x34
-+#define SFT_RTC_ACT_DATE      0x38
-+#define SFT_RTC_TIME          0x3C
-+#define SFT_RTC_DATE          0x40
-+#define SFT_RTC_TIME_LATCH    0x44
-+#define SFT_RTC_DATE_LATCH    0x48
-+
-+/* RTC_CFG */
-+#define RTC_CFG_ENABLE_SHIFT  0  /* RW: RTC Enable. */
-+#define RTC_CFG_CAL_EN_HW_SHIFT       1  /* RW: Enable of hardware calibretion. */
-+#define RTC_CFG_CAL_SEL_SHIFT 2  /* RW: select the hw/sw calibretion mode.*/
-+#define RTC_CFG_HOUR_MODE_SHIFT       3  /* RW: time hour mode. 24h|12h */
-+
-+/* RTC_SW_CAL_VALUE */
-+#define RTC_SW_CAL_VALUE_MASK GENMASK(15, 0)
-+#define RTC_SW_CAL_MAX                RTC_SW_CAL_VALUE_MASK
-+#define RTC_SW_CAL_MIN                0
-+#define RTC_TICKS_PER_SEC     32768           /* Number of ticks per second */
-+#define RTC_PPB_MULT          1000000000LL    /* Multiplier for ppb conversions */
-+
-+/* RTC_HW_CAL_CFG */
-+#define RTC_HW_CAL_REF_SEL_SHIFT      0
-+#define RTC_HW_CAL_FRQ_SEL_SHIFT      1
-+
-+/* IRQ_EN/IRQ_EVEVT/IRQ_STATUS */
-+#define RTC_IRQ_CAL_START     BIT(0)
-+#define RTC_IRQ_CAL_FINISH    BIT(1)
-+#define RTC_IRQ_CMP           BIT(2)
-+#define RTC_IRQ_1SEC          BIT(3)
-+#define RTC_IRQ_ALAEM         BIT(4)
-+#define RTC_IRQ_EVT_UPDATE_PSE        BIT(31) /* WO: Enable of update time&&date, IRQ_EVEVT only */
-+#define RTC_IRQ_ALL           (RTC_IRQ_CAL_START \
-+                              | RTC_IRQ_CAL_FINISH \
-+                              | RTC_IRQ_CMP \
-+                              | RTC_IRQ_1SEC \
-+                              | RTC_IRQ_ALAEM)
-+
-+/* CAL_VALUE */
-+#define RTC_CAL_VALUE_MASK    GENMASK(15, 0)
-+
-+/* CFG_TIME/ACT_TIME/RTC_TIME */
-+#define TIME_SEC_MASK         GENMASK(6, 0)
-+#define TIME_MIN_MASK         GENMASK(13, 7)
-+#define TIME_HOUR_MASK                GENMASK(20, 14)
-+
-+/* CFG_DATE/ACT_DATE/RTC_DATE */
-+#define DATE_DAY_MASK         GENMASK(5, 0)
-+#define DATE_MON_MASK         GENMASK(10, 6)
-+#define DATE_YEAR_MASK                GENMASK(18, 11)
-+
-+#define INT_TIMEOUT_US                180
-+
-+enum RTC_HOUR_MODE {
-+      RTC_HOUR_MODE_12H = 0,
-+      RTC_HOUR_MODE_24H = 1
-+};
-+
-+enum RTC_CAL_MODE {
-+      RTC_CAL_MODE_SW = 0,
-+      RTC_CAL_MODE_HW = 1
-+};
-+
-+enum RTC_HW_CAL_REF_MODE {
-+      RTC_CAL_CLK_REF = 0,
-+      RTC_CAL_CLK_MARK = 1
-+};
-+
-+static const unsigned long refclk_list[] = {
-+      1000000,
-+      2000000,
-+      4000000,
-+      5927000,
-+      6000000,
-+      7200000,
-+      8000000,
-+      10250000,
-+      11059200,
-+      12000000,
-+      12288000,
-+      13560000,
-+      16000000,
-+      19200000,
-+      20000000,
-+      22118000,
-+      24000000,
-+      24567000,
-+      25000000,
-+      26000000,
-+      27000000,
-+      30000000,
-+      32000000,
-+      33868800,
-+      36000000,
-+      36860000,
-+      40000000,
-+      44000000,
-+      50000000,
-+      54000000,
-+      28224000,
-+      28000000,
-+};
-+
-+struct sft_rtc {
-+      struct rtc_device *rtc_dev;
-+      struct completion cal_done;
-+      struct completion onesec_done;
-+      struct clk *pclk;
-+      struct clk *cal_clk;
-+      struct reset_control *rst_array;
-+      int hw_cal_map;
-+      void __iomem *regs;
-+      int rtc_irq;
-+      int ms_pulse_irq;
-+      int one_sec_pulse_irq;
-+};
-+
-+static inline void sft_rtc_set_enabled(struct sft_rtc *srtc, bool enabled)
-+{
-+      u32 val;
-+
-+      if (enabled) {
-+              val = readl(srtc->regs + SFT_RTC_CFG);
-+              val |= BIT(RTC_CFG_ENABLE_SHIFT);
-+              writel(val, srtc->regs + SFT_RTC_CFG);
-+      } else {
-+              val = readl(srtc->regs + SFT_RTC_CFG);
-+              val &= ~BIT(RTC_CFG_ENABLE_SHIFT);
-+              writel(val, srtc->regs + SFT_RTC_CFG);
-+      }
-+}
-+
-+static inline bool sft_rtc_get_enabled(struct sft_rtc *srtc)
-+{
-+      return !!(readl(srtc->regs + SFT_RTC_CFG) & BIT(RTC_CFG_ENABLE_SHIFT));
-+}
-+
-+static inline void sft_rtc_set_mode(struct sft_rtc *srtc, enum RTC_HOUR_MODE mode)
-+{
-+      u32 val;
-+
-+      val = readl(srtc->regs + SFT_RTC_CFG);
-+      val |= mode << RTC_CFG_HOUR_MODE_SHIFT;
-+      writel(val, srtc->regs + SFT_RTC_CFG);
-+}
-+
-+static inline int sft_rtc_irq_enable(struct sft_rtc *srtc, u32 irq, bool enable)
-+{
-+      u32 val;
-+
-+      if (!(irq & RTC_IRQ_ALL))
-+              return -EINVAL;
-+
-+      if (enable) {
-+              val = readl(srtc->regs + SFT_RTC_IRQ_EN);
-+              val |= irq;
-+              writel(val, srtc->regs + SFT_RTC_IRQ_EN);
-+      } else {
-+              val = readl(srtc->regs + SFT_RTC_IRQ_EN);
-+              val &= ~irq;
-+              writel(val, srtc->regs + SFT_RTC_IRQ_EN);
-+      }
-+      return 0;
-+}
-+
-+static inline void
-+sft_rtc_set_cal_hw_enable(struct sft_rtc *srtc, bool enable)
-+{
-+      u32 val;
-+
-+      if (enable) {
-+              val = readl(srtc->regs + SFT_RTC_CFG);
-+              val |= BIT(RTC_CFG_CAL_EN_HW_SHIFT);
-+              writel(val, srtc->regs + SFT_RTC_CFG);
-+      } else {
-+              val = readl(srtc->regs + SFT_RTC_CFG);
-+              val &= ~BIT(RTC_CFG_CAL_EN_HW_SHIFT);
-+              writel(val, srtc->regs + SFT_RTC_CFG);
-+      }
-+}
-+
-+static inline void
-+sft_rtc_set_cal_mode(struct sft_rtc *srtc, enum RTC_CAL_MODE mode)
-+{
-+      u32 val;
-+
-+      val = readl(srtc->regs + SFT_RTC_CFG);
-+      val |= mode << RTC_CFG_CAL_SEL_SHIFT;
-+      writel(val, srtc->regs + SFT_RTC_CFG);
-+}
-+
-+static int sft_rtc_get_hw_calclk(struct device *dev, unsigned long freq)
-+{
-+      int i;
-+
-+      for (i = 0; i < ARRAY_SIZE(refclk_list); i++)
-+              if (refclk_list[i] == freq)
-+                      return i;
-+
-+      dev_err(dev, "refclk: %ldHz do not support.\n", freq);
-+      return -EINVAL;
-+}
-+
-+static inline void sft_rtc_reg2time(struct rtc_time *tm, u32 reg)
-+{
-+      tm->tm_hour = bcd2bin(FIELD_GET(TIME_HOUR_MASK, reg));
-+      tm->tm_min = bcd2bin(FIELD_GET(TIME_MIN_MASK, reg));
-+      tm->tm_sec = bcd2bin(FIELD_GET(TIME_SEC_MASK, reg));
-+}
-+
-+static inline void sft_rtc_reg2date(struct rtc_time *tm, u32 reg)
-+{
-+      tm->tm_year = bcd2bin(FIELD_GET(DATE_YEAR_MASK, reg)) + 100;
-+      tm->tm_mon = bcd2bin(FIELD_GET(DATE_MON_MASK, reg)) - 1;
-+      tm->tm_mday = bcd2bin(FIELD_GET(DATE_DAY_MASK, reg));
-+}
-+
-+static inline u32 sft_rtc_time2reg(struct rtc_time *tm)
-+{
-+      return  FIELD_PREP(TIME_HOUR_MASK, bin2bcd(tm->tm_hour)) |
-+              FIELD_PREP(TIME_MIN_MASK, bin2bcd(tm->tm_min)) |
-+              FIELD_PREP(TIME_SEC_MASK, bin2bcd(tm->tm_sec));
-+}
-+
-+static inline u32 sft_rtc_date2reg(struct rtc_time *tm)
-+{
-+      return  FIELD_PREP(DATE_YEAR_MASK, bin2bcd(tm->tm_year - 100)) |
-+              FIELD_PREP(DATE_MON_MASK, bin2bcd(tm->tm_mon + 1)) |
-+              FIELD_PREP(DATE_DAY_MASK, bin2bcd(tm->tm_mday));
-+}
-+
-+static inline void sft_rtc_update_pulse(struct sft_rtc *srtc)
-+{
-+      u32 val;
-+
-+      val = readl(srtc->regs + SFT_RTC_IRQ_EVEVT);
-+      val |= RTC_IRQ_EVT_UPDATE_PSE;
-+      writel(val, srtc->regs + SFT_RTC_IRQ_EVEVT);
-+}
-+
-+static irqreturn_t sft_rtc_irq_handler(int irq, void *data)
-+{
-+      struct sft_rtc *srtc = data;
-+      struct timerqueue_node *next;
-+      u32 irq_flags = 0;
-+      u32 irq_mask = 0;
-+      u32 val;
-+      int ret = 0;
-+
-+      val = readl(srtc->regs + SFT_RTC_IRQ_EVEVT);
-+      if (val & RTC_IRQ_CAL_START)
-+              irq_mask |= RTC_IRQ_CAL_START;
-+
-+      if (val & RTC_IRQ_CAL_FINISH) {
-+              irq_mask |= RTC_IRQ_CAL_FINISH;
-+              complete(&srtc->cal_done);
-+      }
-+
-+      if (val & RTC_IRQ_CMP)
-+              irq_mask |= RTC_IRQ_CMP;
-+
-+      if (val & RTC_IRQ_1SEC) {
-+              irq_flags |= RTC_PF;
-+              irq_mask |= RTC_IRQ_1SEC;
-+              complete(&srtc->onesec_done);
-+      }
-+
-+      if (val & RTC_IRQ_ALAEM) {
-+              irq_flags |= RTC_AF;
-+              irq_mask |= RTC_IRQ_ALAEM;
-+
-+              next = timerqueue_getnext(&srtc->rtc_dev->timerqueue);
-+              if (next == &srtc->rtc_dev->aie_timer.node)
-+                      dev_info(&srtc->rtc_dev->dev, "alarm expires");
-+      }
-+
-+      writel(irq_mask, srtc->regs + SFT_RTC_IRQ_EVEVT);
-+
-+      /* Wait interrupt flag clear */
-+      ret = readl_poll_timeout_atomic(srtc->regs + SFT_RTC_IRQ_EVEVT, val,
-+                                      (val & irq_mask) == 0, 0, INT_TIMEOUT_US);
-+      if (ret)
-+              dev_warn(&srtc->rtc_dev->dev, "fail to clear rtc interrupt flag\n");
-+
-+      if (irq_flags)
-+              rtc_update_irq(srtc->rtc_dev, 1, irq_flags | RTC_IRQF);
-+
-+      return IRQ_HANDLED;
-+}
-+
-+static int sft_rtc_read_time(struct device *dev, struct rtc_time *tm)
-+{
-+      struct sft_rtc *srtc = dev_get_drvdata(dev);
-+      u32 val;
-+      int irq_1sec_state_start, irq_1sec_state_end;
-+
-+      /* If the RTC is disabled, assume the values are invalid */
-+      if (!sft_rtc_get_enabled(srtc))
-+              return -EINVAL;
-+
-+      irq_1sec_state_start =
-+              (readl(srtc->regs + SFT_RTC_IRQ_STATUS) & RTC_IRQ_1SEC) == 0 ? 0 : 1;
-+
-+read_again:
-+      val = readl(srtc->regs + SFT_RTC_TIME);
-+      sft_rtc_reg2time(tm, val);
-+
-+      val = readl(srtc->regs + SFT_RTC_DATE);
-+      sft_rtc_reg2date(tm, val);
-+
-+      if (irq_1sec_state_start == 0) {
-+              irq_1sec_state_end =
-+                      (readl(srtc->regs + SFT_RTC_IRQ_STATUS) & RTC_IRQ_1SEC) == 0 ? 0 : 1;
-+              if (irq_1sec_state_end == 1) {
-+                      irq_1sec_state_start = 1;
-+                      goto read_again;
-+              }
-+      }
-+
-+      return 0;
-+}
-+
-+static int sft_rtc_set_time(struct device *dev, struct rtc_time *tm)
-+{
-+      struct sft_rtc *srtc = dev_get_drvdata(dev);
-+      u32 val;
-+      int ret;
-+
-+      val = sft_rtc_time2reg(tm);
-+      writel(val, srtc->regs + SFT_RTC_CFG_TIME);
-+
-+      val = sft_rtc_date2reg(tm);
-+      writel(val, srtc->regs + SFT_RTC_CFG_DATE);
-+
-+      /* Update pulse */
-+      sft_rtc_update_pulse(srtc);
-+
-+      /* Ensure that data is fully written */
-+      ret = wait_for_completion_interruptible_timeout(&srtc->onesec_done,
-+                                                      usecs_to_jiffies(120));
-+      if (ret) {
-+              dev_warn(dev,
-+                       "rtc wait for completion interruptible timeout.\n");
-+      }
-+      return 0;
-+}
-+
-+static int sft_rtc_alarm_irq_enable(struct device *dev, unsigned int enabled)
-+{
-+      struct sft_rtc *srtc = dev_get_drvdata(dev);
-+
-+      return sft_rtc_irq_enable(srtc, RTC_IRQ_ALAEM, enabled);
-+}
-+
-+static int sft_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alarm)
-+{
-+      struct sft_rtc *srtc = dev_get_drvdata(dev);
-+      u32 val;
-+
-+      val = readl(srtc->regs + SFT_RTC_ACT_TIME);
-+      sft_rtc_reg2time(&alarm->time, val);
-+
-+      val = readl(srtc->regs + SFT_RTC_ACT_DATE);
-+      sft_rtc_reg2date(&alarm->time, val);
-+
-+      return 0;
-+}
-+
-+static int sft_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alarm)
-+{
-+      struct sft_rtc *srtc = dev_get_drvdata(dev);
-+      u32 val;
-+
-+      sft_rtc_alarm_irq_enable(dev, 0);
-+
-+      val = sft_rtc_time2reg(&alarm->time);
-+      writel(val, srtc->regs + SFT_RTC_ACT_TIME);
-+
-+      val = sft_rtc_date2reg(&alarm->time);
-+      writel(val, srtc->regs + SFT_RTC_ACT_DATE);
-+
-+      sft_rtc_alarm_irq_enable(dev, alarm->enabled);
-+
-+      return 0;
-+}
-+
-+static int sft_rtc_get_offset(struct device *dev, long *offset)
-+{
-+      struct sft_rtc *srtc = dev_get_drvdata(dev);
-+      s64 tmp;
-+      u32 val;
-+
-+      val = readl(srtc->regs + SFT_RTC_CAL_VALUE)
-+                      & RTC_SW_CAL_VALUE_MASK;
-+      val += 1;
-+      /*
-+       * the adjust val range is [0x0000-0xffff],
-+       * the default val is 0x7fff (32768-1),mapping offset=0 ;
-+       */
-+      tmp = (s64)val - RTC_TICKS_PER_SEC;
-+      tmp *= RTC_PPB_MULT;
-+      tmp = div_s64(tmp, RTC_TICKS_PER_SEC);
-+
-+      /* Offset value operates in negative way, so swap sign */
-+      *offset = -tmp;
-+
-+      return 0;
-+}
-+
-+static int sft_rtc_set_offset(struct device *dev, long offset)
-+{
-+      struct sft_rtc *srtc = dev_get_drvdata(dev);
-+      s64 tmp;
-+      u32 val;
-+
-+      tmp = offset * RTC_TICKS_PER_SEC;
-+      tmp = div_s64(tmp, RTC_PPB_MULT);
-+
-+      tmp = RTC_TICKS_PER_SEC - tmp;
-+      tmp -= 1;
-+      if (tmp > RTC_SW_CAL_MAX || tmp < RTC_SW_CAL_MIN) {
-+              dev_err(dev, "offset is out of range.\n");
-+              return -EINVAL;
-+      }
-+
-+      val = tmp & RTC_SW_CAL_VALUE_MASK;
-+      /* set software calibration value */
-+      writel(val, srtc->regs + SFT_RTC_SW_CAL_VALUE);
-+
-+      /* set CFG_RTC-cal_sel to select calibretion by software. */
-+      sft_rtc_set_cal_mode(srtc, RTC_CAL_MODE_SW);
-+
-+      return 0;
-+}
-+
-+static __maybe_unused int
-+sft_rtc_hw_adjustment(struct device *dev, unsigned int enable)
-+{
-+      struct sft_rtc *srtc = dev_get_drvdata(dev);
-+      u32 val;
-+
-+      if (srtc->hw_cal_map <= 0) {
-+              dev_err(dev, "fail to get cal-clock-freq.\n");
-+              return -EFAULT;
-+      }
-+
-+      if (enable) {
-+              sft_rtc_irq_enable(srtc, RTC_IRQ_CAL_FINISH, true);
-+
-+              /* Set reference clock frequency value */
-+              val = readl(srtc->regs + SFT_RTC_HW_CAL_CFG);
-+              val |= (srtc->hw_cal_map << RTC_HW_CAL_FRQ_SEL_SHIFT);
-+              writel(val, srtc->regs + SFT_RTC_HW_CAL_CFG);
-+
-+              /* Set CFG_RTC-cal_sel to select calibretion by hardware. */
-+              sft_rtc_set_cal_mode(srtc, RTC_CAL_MODE_HW);
-+
-+              /* Set CFG_RTC-cal_en_hw to launch hardware calibretion.*/
-+              sft_rtc_set_cal_hw_enable(srtc, true);
-+
-+              wait_for_completion_interruptible_timeout(&srtc->cal_done,
-+                                                        usecs_to_jiffies(100));
-+
-+              sft_rtc_irq_enable(srtc, RTC_IRQ_CAL_FINISH, false);
-+      } else {
-+              sft_rtc_set_cal_mode(srtc, RTC_CAL_MODE_SW);
-+              sft_rtc_set_cal_hw_enable(srtc, false);
-+      }
-+
-+      return 0;
-+}
-+
-+static int sft_rtc_get_cal_clk(struct device *dev, struct sft_rtc *srtc)
-+{
-+      struct device_node *np = dev->of_node;
-+      unsigned long cal_clk_freq;
-+      u32 freq;
-+      int ret;
-+
-+      srtc->cal_clk = devm_clk_get(dev, "cal_clk");
-+      if (IS_ERR(srtc->cal_clk))
-+              return PTR_ERR(srtc->cal_clk);
-+
-+      clk_prepare_enable(srtc->cal_clk);
-+
-+      cal_clk_freq = clk_get_rate(srtc->cal_clk);
-+      if (!cal_clk_freq) {
-+              dev_warn(dev,
-+                       "get rate failed, next try to get from dts.\n");
-+              ret = of_property_read_u32(np, "rtc,cal-clock-freq", &freq);
-+              if (!ret) {
-+                      cal_clk_freq = (u64)freq;
-+              } else {
-+                      dev_err(dev,
-+                              "Need rtc,cal-clock-freq define in dts.\n");
-+                      goto err_disable_cal_clk;
-+              }
-+      }
-+
-+      srtc->hw_cal_map = sft_rtc_get_hw_calclk(dev, cal_clk_freq);
-+      if (srtc->hw_cal_map < 0) {
-+              ret = srtc->hw_cal_map;
-+              goto err_disable_cal_clk;
-+      }
-+
-+      return 0;
-+
-+err_disable_cal_clk:
-+      clk_disable_unprepare(srtc->cal_clk);
-+
-+      return ret;
-+}
-+
-+static int sft_rtc_get_irq(struct platform_device *pdev, struct sft_rtc *srtc)
-+{
-+      int ret;
-+
-+      srtc->rtc_irq = platform_get_irq_byname(pdev, "rtc");
-+      if (srtc->rtc_irq < 0)
-+              return -EINVAL;
-+
-+      ret = devm_request_irq(&pdev->dev, srtc->rtc_irq,
-+                             sft_rtc_irq_handler, 0,
-+                              KBUILD_MODNAME, srtc);
-+      if (ret)
-+              dev_err(&pdev->dev, "Failed to request interrupt, %d\n", ret);
-+
-+      return ret;
-+}
-+
-+static const struct rtc_class_ops starfive_rtc_ops = {
-+      .read_time              = sft_rtc_read_time,
-+      .set_time               = sft_rtc_set_time,
-+      .read_alarm             = sft_rtc_read_alarm,
-+      .set_alarm              = sft_rtc_set_alarm,
-+      .alarm_irq_enable       = sft_rtc_alarm_irq_enable,
-+      .set_offset             = sft_rtc_set_offset,
-+      .read_offset            = sft_rtc_get_offset,
-+};
-+
-+static int sft_rtc_probe(struct platform_device *pdev)
-+{
-+      struct device *dev = &pdev->dev;
-+      struct sft_rtc *srtc;
-+      struct rtc_time tm;
-+      struct irq_desc *desc;
-+      int ret;
-+
-+      srtc = devm_kzalloc(dev, sizeof(*srtc), GFP_KERNEL);
-+      if (!srtc)
-+              return -ENOMEM;
-+
-+      srtc->regs = devm_platform_ioremap_resource(pdev, 0);
-+      if (IS_ERR(srtc->regs))
-+              return PTR_ERR(srtc->regs);
-+
-+      srtc->pclk = devm_clk_get(dev, "pclk");
-+      if (IS_ERR(srtc->pclk)) {
-+              ret = PTR_ERR(srtc->pclk);
-+              dev_err(dev,
-+                      "Failed to retrieve the peripheral clock, %d\n", ret);
-+              return ret;
-+      }
-+
-+      srtc->rst_array = devm_reset_control_array_get_exclusive(dev);
-+      if (IS_ERR(srtc->rst_array)) {
-+              ret = PTR_ERR(srtc->rst_array);
-+              dev_err(dev,
-+                      "Failed to retrieve the rtc reset, %d\n", ret);
-+              return ret;
-+      }
-+
-+      init_completion(&srtc->cal_done);
-+      init_completion(&srtc->onesec_done);
-+
-+      ret = clk_prepare_enable(srtc->pclk);
-+      if (ret) {
-+              dev_err(dev,
-+                      "Failed to enable the peripheral clock, %d\n", ret);
-+              return ret;
-+      }
-+
-+      ret = sft_rtc_get_cal_clk(dev, srtc);
-+      if (ret)
-+              goto err_disable_pclk;
-+
-+      ret = reset_control_deassert(srtc->rst_array);
-+      if (ret) {
-+              dev_err(dev,
-+                      "Failed to deassert rtc resets, %d\n", ret);
-+              goto err_disable_cal_clk;
-+      }
-+
-+      ret = sft_rtc_get_irq(pdev, srtc);
-+      if (ret)
-+              goto err_disable_cal_clk;
-+
-+      srtc->rtc_dev = devm_rtc_allocate_device(dev);
-+      if (IS_ERR(srtc->rtc_dev))
-+              return PTR_ERR(srtc->rtc_dev);
-+
-+      platform_set_drvdata(pdev, srtc);
-+
-+      /* The RTC supports 01.01.2001 - 31.12.2099 */
-+      srtc->rtc_dev->range_min = mktime64(2001,  1,  1,  0,  0,  0);
-+      srtc->rtc_dev->range_max = mktime64(2099, 12, 31, 23, 59, 59);
-+
-+      srtc->rtc_dev->ops = &starfive_rtc_ops;
-+      device_init_wakeup(dev, true);
-+
-+      desc = irq_to_desc(srtc->rtc_irq);
-+      irq_desc_get_chip(desc)->flags = IRQCHIP_SKIP_SET_WAKE;
-+
-+      /* Always use 24-hour mode and keep the RTC values */
-+      sft_rtc_set_mode(srtc, RTC_HOUR_MODE_24H);
-+
-+      sft_rtc_set_enabled(srtc, true);
-+
-+      if (device_property_read_bool(dev, "rtc,hw-adjustment"))
-+              sft_rtc_hw_adjustment(dev, true);
-+
-+      /*
-+       * If rtc time is out of supported range, reset it to the minimum time.
-+       * notice that, actual year = 1900 + tm.tm_year
-+       *              actual month = 1 + tm.tm_mon
-+       */
-+      sft_rtc_read_time(dev, &tm);
-+      if (tm.tm_year < 101 || tm.tm_year > 199 || tm.tm_mon < 0 || tm.tm_mon > 11 ||
-+          tm.tm_mday < 1 || tm.tm_mday > 31 || tm.tm_hour < 0 || tm.tm_hour > 23 ||
-+          tm.tm_min < 0 || tm.tm_min > 59 || tm.tm_sec < 0 || tm.tm_sec > 59) {
-+              rtc_time64_to_tm(srtc->rtc_dev->range_min, &tm);
-+              sft_rtc_set_time(dev, &tm);
-+      }
-+
-+      ret = devm_rtc_register_device(srtc->rtc_dev);
-+      if (ret)
-+              goto err_disable_wakeup;
-+
-+      return 0;
-+
-+err_disable_wakeup:
-+      device_init_wakeup(dev, false);
-+
-+err_disable_cal_clk:
-+      clk_disable_unprepare(srtc->cal_clk);
-+
-+err_disable_pclk:
-+      clk_disable_unprepare(srtc->pclk);
-+
-+      return ret;
-+}
-+
-+static int sft_rtc_remove(struct platform_device *pdev)
-+{
-+      struct sft_rtc *srtc = platform_get_drvdata(pdev);
-+
-+      sft_rtc_alarm_irq_enable(&pdev->dev, 0);
-+      device_init_wakeup(&pdev->dev, 0);
-+
-+      clk_disable_unprepare(srtc->pclk);
-+      clk_disable_unprepare(srtc->cal_clk);
-+
-+      return 0;
-+}
-+
-+#ifdef CONFIG_PM_SLEEP
-+static int sft_rtc_suspend(struct device *dev)
-+{
-+      struct sft_rtc *srtc = dev_get_drvdata(dev);
-+
-+      if (device_may_wakeup(dev))
-+              enable_irq_wake(srtc->rtc_irq);
-+
-+      return 0;
-+}
-+
-+static int sft_rtc_resume(struct device *dev)
-+{
-+      struct sft_rtc *srtc = dev_get_drvdata(dev);
-+
-+      if (device_may_wakeup(dev))
-+              disable_irq_wake(srtc->rtc_irq);
-+
-+      return 0;
-+}
-+#endif
-+
-+static SIMPLE_DEV_PM_OPS(sft_rtc_pm_ops, sft_rtc_suspend, sft_rtc_resume);
-+
-+static const struct of_device_id sft_rtc_of_match[] = {
-+      { .compatible = "starfive,jh7110-rtc" },
-+      { },
-+};
-+MODULE_DEVICE_TABLE(of, sft_rtc_of_match);
-+
-+static struct platform_driver starfive_rtc_driver = {
-+      .driver = {
-+              .name = "starfive-rtc",
-+              .of_match_table = sft_rtc_of_match,
-+              .pm   = &sft_rtc_pm_ops,
-+      },
-+      .probe = sft_rtc_probe,
-+      .remove = sft_rtc_remove,
-+};
-+module_platform_driver(starfive_rtc_driver);
-+
-+MODULE_AUTHOR("Samin Guo <samin.guo@starfivetech.com>");
-+MODULE_AUTHOR("Hal Feng <hal.feng@starfivetech.com>");
-+MODULE_DESCRIPTION("StarFive RTC driver");
-+MODULE_LICENSE("GPL v2");
-+MODULE_ALIAS("platform:starfive-rtc");
diff --git a/target/linux/starfive/patches-6.6/0066-uart-8250-Add-dw-auto-flow-ctrl-support.patch b/target/linux/starfive/patches-6.6/0066-uart-8250-Add-dw-auto-flow-ctrl-support.patch
deleted file mode 100644 (file)
index 4fd92a4..0000000
+++ /dev/null
@@ -1,96 +0,0 @@
-From 552114b8cbbd956ad8466261b5f11b059eba82ca Mon Sep 17 00:00:00 2001
-From: Minda Chen <minda.chen@starfivetech.com>
-Date: Sun, 25 Jun 2023 09:40:29 +0800
-Subject: [PATCH 066/116] uart: 8250: Add dw auto flow ctrl support
-
-Add designeware 8250 auto flow ctrl support. Enable
-it by add auto-flow-control in dts.
-
-Signed-off-by: Minda Chen <minda.chen@starfivetech.com>
----
- drivers/tty/serial/8250/8250_core.c |  2 ++
- drivers/tty/serial/8250/8250_dw.c   |  3 +++
- drivers/tty/serial/8250/8250_port.c | 14 +++++++++++++-
- include/linux/serial_8250.h         |  1 +
- include/uapi/linux/serial_core.h    |  2 ++
- 5 files changed, 21 insertions(+), 1 deletion(-)
-
---- a/drivers/tty/serial/8250/8250_core.c
-+++ b/drivers/tty/serial/8250/8250_core.c
-@@ -1129,6 +1129,8 @@ int serial8250_register_8250_port(const
-                       uart->dl_read = up->dl_read;
-               if (up->dl_write)
-                       uart->dl_write = up->dl_write;
-+              if (up->probe)
-+                      uart->probe = up->probe;
-               if (uart->port.type != PORT_8250_CIR) {
-                       if (uart_console_registered(&uart->port))
---- a/drivers/tty/serial/8250/8250_dw.c
-+++ b/drivers/tty/serial/8250/8250_dw.c
-@@ -612,6 +612,9 @@ static int dw8250_probe(struct platform_
-               data->msr_mask_off |= UART_MSR_TERI;
-       }
-+      if (device_property_read_bool(dev, "auto-flow-control"))
-+              up->probe |= UART_PROBE_AFE;
-+
-       /* If there is separate baudclk, get the rate from it. */
-       data->clk = devm_clk_get_optional(dev, "baudclk");
-       if (data->clk == NULL)
---- a/drivers/tty/serial/8250/8250_port.c
-+++ b/drivers/tty/serial/8250/8250_port.c
-@@ -330,6 +330,14 @@ static const struct serial8250_config ua
-               .rxtrig_bytes   = {1, 8, 16, 30},
-               .flags          = UART_CAP_FIFO | UART_CAP_AFE,
-       },
-+      [PORT_16550A_AFE] = {
-+              .name           = "16550A_AFE",
-+              .fifo_size      = 16,
-+              .tx_loadsz      = 16,
-+              .fcr            = UART_FCR_ENABLE_FIFO | UART_FCR_R_TRIG_10,
-+              .rxtrig_bytes   = {1, 4, 8, 14},
-+              .flags          = UART_CAP_FIFO | UART_CAP_AFE,
-+      },
- };
- /* Uart divisor latch read */
-@@ -1143,6 +1151,11 @@ static void autoconfig_16550a(struct uar
-               up->port.type = PORT_U6_16550A;
-               up->capabilities |= UART_CAP_AFE;
-       }
-+
-+      if ((up->port.type == PORT_16550A) && (up->probe & UART_PROBE_AFE)) {
-+              up->port.type = PORT_16550A_AFE;
-+              up->capabilities |= UART_CAP_AFE;
-+      }
- }
- /*
-@@ -2822,7 +2835,6 @@ serial8250_do_set_termios(struct uart_po
-               if (termios->c_cflag & CRTSCTS)
-                       up->mcr |= UART_MCR_AFE;
-       }
--
-       /*
-        * Update the per-port timeout.
-        */
---- a/include/linux/serial_8250.h
-+++ b/include/linux/serial_8250.h
-@@ -141,6 +141,7 @@ struct uart_8250_port {
-       unsigned char           probe;
-       struct mctrl_gpios      *gpios;
- #define UART_PROBE_RSA        (1 << 0)
-+#define UART_PROBE_AFE  (1 << 1)
-       /*
-        * Some bits in registers are cleared on a read, so they must
---- a/include/uapi/linux/serial_core.h
-+++ b/include/uapi/linux/serial_core.h
-@@ -245,4 +245,6 @@
- /* Sunplus UART */
- #define PORT_SUNPLUS  123
-+#define PORT_16550A_AFE       124
-+
- #endif /* _UAPILINUX_SERIAL_CORE_H */
diff --git a/target/linux/starfive/patches-6.6/0067-driver-uart-fix-up-uart-communicate-fail.patch b/target/linux/starfive/patches-6.6/0067-driver-uart-fix-up-uart-communicate-fail.patch
deleted file mode 100644 (file)
index 18d735b..0000000
+++ /dev/null
@@ -1,29 +0,0 @@
-From 6edee93a89254f30c3387c88231e7ecec06ba84a Mon Sep 17 00:00:00 2001
-From: "shanlong.li" <shanlong.li@starfivetech.com>
-Date: Mon, 10 Jul 2023 03:07:57 -0700
-Subject: [PATCH 067/116] driver:uart: fix up uart communicate fail
-
-fix up uart communicate fail
-
-Signed-off-by: shanlong.li <shanlong.li@starfivetech.com>
----
- drivers/tty/serial/8250/8250_dw.c | 8 ++++----
- 1 file changed, 4 insertions(+), 4 deletions(-)
-
---- a/drivers/tty/serial/8250/8250_dw.c
-+++ b/drivers/tty/serial/8250/8250_dw.c
-@@ -652,10 +652,10 @@ static int dw8250_probe(struct platform_
-       if (err)
-               return err;
--      data->rst = devm_reset_control_get_optional_exclusive(dev, NULL);
--      if (IS_ERR(data->rst))
--              return PTR_ERR(data->rst);
--
-+      data->rst = devm_reset_control_array_get_exclusive(dev);
-+      if (IS_ERR(data->rst)) {
-+              err = PTR_ERR(data->rst);
-+      }
-       reset_control_deassert(data->rst);
-       err = devm_add_action_or_reset(dev, dw8250_reset_control_assert, data->rst);
diff --git a/target/linux/starfive/patches-6.6/0068-uart-8250-add-reset-operation-in-runtime-PM.patch b/target/linux/starfive/patches-6.6/0068-uart-8250-add-reset-operation-in-runtime-PM.patch
deleted file mode 100644 (file)
index 56efebd..0000000
+++ /dev/null
@@ -1,32 +0,0 @@
-From 777d288f03a0b350f6c2d4367b01a80d9f25cd6e Mon Sep 17 00:00:00 2001
-From: William Qiu <william.qiu@starfivetech.com>
-Date: Wed, 20 Sep 2023 17:19:59 +0800
-Subject: [PATCH 068/116] uart: 8250: add reset operation in runtime PM
-
-add reset operation in runtime PM
-
-Signed-off-by: William Qiu <william.qiu@starfivetech.com>
----
- drivers/tty/serial/8250/8250_dw.c | 4 ++++
- 1 file changed, 4 insertions(+)
-
---- a/drivers/tty/serial/8250/8250_dw.c
-+++ b/drivers/tty/serial/8250/8250_dw.c
-@@ -745,6 +745,8 @@ static int dw8250_runtime_suspend(struct
- {
-       struct dw8250_data *data = dev_get_drvdata(dev);
-+      reset_control_assert(data->rst);
-+
-       clk_disable_unprepare(data->clk);
-       clk_disable_unprepare(data->pclk);
-@@ -760,6 +762,8 @@ static int dw8250_runtime_resume(struct
-       clk_prepare_enable(data->clk);
-+      reset_control_deassert(data->rst);
-+
-       return 0;
- }
diff --git a/target/linux/starfive/patches-6.6/0069-dt-bindings-CAN-Add-StarFive-CAN-module.patch b/target/linux/starfive/patches-6.6/0069-dt-bindings-CAN-Add-StarFive-CAN-module.patch
deleted file mode 100644 (file)
index eb46a96..0000000
+++ /dev/null
@@ -1,113 +0,0 @@
-From 5eda2331a252436756fb40861f01a7a38b1502c7 Mon Sep 17 00:00:00 2001
-From: William Qiu <william.qiu@starfivetech.com>
-Date: Thu, 15 Jun 2023 20:14:22 +0800
-Subject: [PATCH 069/116] dt-bindings: CAN: Add StarFive CAN module
-
-Add documentation to describe StarFive CAN engine.
-
-Signed-off-by: William Qiu <william.qiu@starfivetech.com>
----
- .../devicetree/bindings/net/can/ipms-can.yaml | 97 +++++++++++++++++++
- 1 file changed, 97 insertions(+)
- create mode 100644 Documentation/devicetree/bindings/net/can/ipms-can.yaml
-
---- /dev/null
-+++ b/Documentation/devicetree/bindings/net/can/ipms-can.yaml
-@@ -0,0 +1,97 @@
-+# SPDX-License-Identifier: GPL-2.0
-+%YAML 1.2
-+---
-+#$id: http://devicetree.org/schemas/net/can/ipms-can.yaml#
-+#$schema: http://devicetree.org/meta-schemas/core.yaml#
-+
-+title: IPMS CAN/CANFD controller Device Tree Bindings
-+
-+properties:
-+  compatible:
-+    const:ipms,can
-+
-+  reg:
-+    maxItems: 1
-+    items:
-+      - description:CAN controller registers
-+
-+  interrupts:
-+    maxItems: 1
-+
-+  clocks:
-+    minItems: 1
-+    items:
-+      - description:apb_clk clock
-+      - description:core_clk clock
-+      - description:timer_clk clock
-+
-+  clock-names:
-+    minItems: 1
-+    items:
-+      - const:apb_clk
-+      - const:core_clk
-+      - const:timer_clk
-+  resets:
-+   minItems: 1
-+    items:
-+      - description:apb_clk reset
-+      - description:core_clk reset
-+      - description:timer_clk reset
-+  reset-names:
-+    minItems: 1
-+    items:
-+      - const:rst_apb
-+      - const:rst_core
-+      - const:rst_timer
-+  starfive,sys-syscon:
-+    format:
-+    starfive,sys-syscon = <&arg0 arg1 arg2 arg3>
-+    description:
-+      arg0:arg0 is sys_syscon.
-+      arg1:arg1 is syscon register offset, used to enable can2.0/canfd function, can0 is 0x10, can1 is 0x88.
-+      arg2:arg2 is used to enable the register shift of the can2.0/canfd function, can0 is 0x3, can1 is 0x12.
-+      arg3:arg3 is used to enable the register mask of the can2.0/canfd function, can0 is 0x8, can1 is 0x40000
-+
-+  syscon,can_or_canfd:
-+    description:
-+    IPMS CAN-CTRL core is a serial communications controller that performs serial communication according to the CAN protocol.
-+    This CAN bus interface uses the basic CAN principle and meets all constraints of the CAN-specification 2.0B active.
-+    Furthermore this CAN core can be configured to meet the specification of CAN with flexible data rate CAN FD.
-+    When syscon,can_or_canfd is set to 0, use CAN2.0B.
-+    when syscon,can_or_canfd is set to 1, use CAN FD.
-+required:
-+  - compatible
-+  - reg
-+  - interrupts
-+  - clocks
-+  - clock-names
-+  - resets
-+  - reset-names
-+  - starfive,sys-syscon
-+  - syscon,can_or_canfd
-+additionalProperties:false
-+
-+examples:
-+  - |
-+    can0: can@130d0000{
-+    compatible = "ipms,can";
-+    reg = <0x0 0x130d0000 0x0 0x1000>;
-+    interrupts = <112>;
-+    interrupt-parent = <&plic>;
-+    clocks = <&clkgen JH7110_CAN0_CTRL_CLK_APB>,
-+             <&clkgen JH7110_CAN0_CTRL_CLK_CAN>,
-+             <&clkgen JH7110_CAN0_CTRL_CLK_TIMER>;
-+    clock-names = "apb_clk",
-+                  "core_clk",
-+                  "timer_clk";
-+    resets = <&rstgen RSTN_U0_CAN_CTRL_APB>,
-+             <&rstgen RSTN_U0_CAN_CTRL_CORE>,
-+             <&rstgen RSTN_U0_CAN_CTRL_TIMER>;
-+    reset-names = "rst_apb",
-+                  "rst_core",
-+                  "rst_timer";
-+    starfive,sys-syscon = <&sys_syscon, 0x10 0x3 0x8>;
-+    syscon,can_or_canfd = <0>;
-+    };
-+
-+...
diff --git a/target/linux/starfive/patches-6.6/0070-CAN-starfive-Add-CAN-engine-support.patch b/target/linux/starfive/patches-6.6/0070-CAN-starfive-Add-CAN-engine-support.patch
deleted file mode 100644 (file)
index 1bb41dd..0000000
+++ /dev/null
@@ -1,1317 +0,0 @@
-From b1fbe15b87be654b1b280a76ec1470917d79f720 Mon Sep 17 00:00:00 2001
-From: William Qiu <william.qiu@starfivetech.com>
-Date: Thu, 15 Jun 2023 20:15:25 +0800
-Subject: [PATCH 070/116] CAN: starfive - Add CAN engine support
-
-Adding device probe StarFive CAN module.
-
-Signed-off-by: William Qiu <william.qiu@starfivetech.com>
-Signed-off-by: Hal Feng <hal.feng@starfivetech.com>
----
- drivers/net/can/Kconfig      |    5 +
- drivers/net/can/Makefile     |    1 +
- drivers/net/can/ipms_canfd.c | 1275 ++++++++++++++++++++++++++++++++++
- 3 files changed, 1281 insertions(+)
- create mode 100644 drivers/net/can/ipms_canfd.c
-
---- a/drivers/net/can/Kconfig
-+++ b/drivers/net/can/Kconfig
-@@ -214,6 +214,11 @@ config CAN_XILINXCAN
-         Xilinx CAN driver. This driver supports both soft AXI CAN IP and
-         Zynq CANPS IP.
-+config IPMS_CAN
-+      tristate "IPMS CAN"
-+      help
-+        IPMS CANFD driver. This driver supports IPMS CANFD IP.
-+
- source "drivers/net/can/c_can/Kconfig"
- source "drivers/net/can/cc770/Kconfig"
- source "drivers/net/can/ctucanfd/Kconfig"
---- a/drivers/net/can/Makefile
-+++ b/drivers/net/can/Makefile
-@@ -31,5 +31,6 @@ obj-$(CONFIG_CAN_SJA1000)    += sja1000/
- obj-$(CONFIG_CAN_SUN4I)               += sun4i_can.o
- obj-$(CONFIG_CAN_TI_HECC)     += ti_hecc.o
- obj-$(CONFIG_CAN_XILINXCAN)   += xilinx_can.o
-+obj-$(CONFIG_IPMS_CAN)                += ipms_canfd.o
- subdir-ccflags-$(CONFIG_CAN_DEBUG_DEVICES) += -DDEBUG
---- /dev/null
-+++ b/drivers/net/can/ipms_canfd.c
-@@ -0,0 +1,1275 @@
-+// SPDX-License-Identifier: GPL-2.0
-+/*
-+ * StarFive Controller Area Network Host Controller Driver
-+ *
-+ * Copyright (c) 2022 StarFive Technology Co., Ltd.
-+ */
-+
-+#include <linux/clk.h>
-+#include <linux/reset.h>
-+#include <linux/errno.h>
-+#include <linux/init.h>
-+#include <linux/interrupt.h>
-+#include <linux/io.h>
-+#include <linux/kernel.h>
-+#include <linux/module.h>
-+#include <linux/netdevice.h>
-+#include <linux/of.h>
-+#include <linux/platform_device.h>
-+#include <linux/skbuff.h>
-+#include <linux/string.h>
-+#include <linux/types.h>
-+#include <linux/can/dev.h>
-+#include <linux/can/error.h>
-+#include <linux/pm_runtime.h>
-+#include <linux/of_device.h>
-+#include <linux/mfd/syscon.h>
-+#include <linux/regmap.h>
-+
-+#define DRIVER_NAME "ipms_canfd"
-+
-+/* CAN registers set */
-+enum canfd_device_reg {
-+      CANFD_RUBF_OFFSET           =   0x00,   /* Receive Buffer Registers 0x00-0x4f */
-+      CANFD_RUBF_ID_OFFSET        =   0x00,
-+      CANFD_RBUF_CTL_OFFSET       =   0x04,
-+      CANFD_RBUF_DATA_OFFSET      =   0x08,
-+      CANFD_TBUF_OFFSET           =   0x50,   /* Transmit Buffer Registers 0x50-0x97 */
-+      CANFD_TBUF_ID_OFFSET        =   0x50,
-+      CANFD_TBUF_CTL_OFFSET       =   0x54,
-+      CANFD_TBUF_DATA_OFFSET      =   0x58,
-+      CANFD_TTS_OFFSET            =   0x98,   /* Transmission Time Stamp 0x98-0x9f */
-+      CANFD_CFG_STAT_OFFSET       =   0xa0,
-+      CANFD_TCMD_OFFSET           =   0xa1,
-+      CANFD_TCTRL_OFFSET          =   0xa2,
-+      CANFD_RCTRL_OFFSET          =   0xa3,
-+      CANFD_RTIE_OFFSET           =   0xa4,
-+      CANFD_RTIF_OFFSET           =   0xa5,
-+      CANFD_ERRINT_OFFSET         =   0xa6,
-+      CANFD_LIMIT_OFFSET          =   0xa7,
-+      CANFD_S_SEG_1_OFFSET        =   0xa8,
-+      CANFD_S_SEG_2_OFFSET        =   0xa9,
-+      CANFD_S_SJW_OFFSET          =   0xaa,
-+      CANFD_S_PRESC_OFFSET        =   0xab,
-+      CANFD_F_SEG_1_OFFSET        =   0xac,
-+      CANFD_F_SEG_2_OFFSET        =   0xad,
-+      CANFD_F_SJW_OFFSET          =   0xae,
-+      CANFD_F_PRESC_OFFSET        =   0xaf,
-+      CANFD_EALCAP_OFFSET         =   0xb0,
-+      CANFD_RECNT_OFFSET          =   0xb2,
-+      CANFD_TECNT_OFFSET          =   0xb3,
-+};
-+
-+enum canfd_reg_bitchange {
-+      CAN_FD_SET_RST_MASK         =   0x80,   /* Set Reset Bit */
-+      CAN_FD_OFF_RST_MASK         =   0x7f,   /* Reset Off Bit */
-+      CAN_FD_SET_FULLCAN_MASK     =   0x10,   /* set TTTBM as 1->full TTCAN mode */
-+      CAN_FD_OFF_FULLCAN_MASK     =   0xef,   /* set TTTBM as 0->separate PTB and STB mode */
-+      CAN_FD_SET_FIFO_MASK        =   0x20,   /* set TSMODE as 1->FIFO mode */
-+      CAN_FD_OFF_FIFO_MASK        =   0xdf,   /* set TSMODE as 0->Priority mode */
-+      CAN_FD_SET_TSONE_MASK       =   0x04,
-+      CAN_FD_OFF_TSONE_MASK       =   0xfb,
-+      CAN_FD_SET_TSALL_MASK       =   0x02,
-+      CAN_FD_OFF_TSALL_MASK       =   0xfd,
-+      CAN_FD_LBMEMOD_MASK         =   0x40,   /* set loop back mode, external */
-+      CAN_FD_LBMIMOD_MASK         =   0x20,   /* set loopback internal mode */
-+      CAN_FD_SET_BUSOFF_MASK      =   0x01,
-+      CAN_FD_OFF_BUSOFF_MASK      =   0xfe,
-+      CAN_FD_SET_TTSEN_MASK       =   0x80,   /* set ttsen, tts update enable */
-+      CAN_FD_SET_BRS_MASK         =   0x10,   /* can fd Bit Rate Switch mask */
-+      CAN_FD_OFF_BRS_MASK         =   0xef,
-+      CAN_FD_SET_EDL_MASK         =   0x20,   /* Extended Data Length */
-+      CAN_FD_OFF_EDL_MASK         =   0xdf,
-+      CAN_FD_SET_DLC_MASK         =   0x0f,
-+      CAN_FD_SET_TENEXT_MASK      =   0x40,
-+      CAN_FD_SET_IDE_MASK         =   0x80,
-+      CAN_FD_OFF_IDE_MASK         =   0x7f,
-+      CAN_FD_SET_RTR_MASK         =   0x40,
-+      CAN_FD_OFF_RTR_MASK         =   0xbf,
-+      CAN_FD_INTR_ALL_MASK        =   0xff,   /* all interrupts enable mask */
-+      CAN_FD_SET_RIE_MASK         =   0x80,
-+      CAN_FD_OFF_RIE_MASK         =   0x7f,
-+      CAN_FD_SET_RFIE_MASK        =   0x20,
-+      CAN_FD_OFF_RFIE_MASK        =   0xdf,
-+      CAN_FD_SET_RAFIE_MASK       =   0x10,
-+      CAN_FD_OFF_RAFIE_MASK       =   0xef,
-+      CAN_FD_SET_EIE_MASK         =   0x02,
-+      CAN_FD_OFF_EIE_MASK         =   0xfd,
-+      CAN_FD_TASCTIVE_MASK        =   0x02,
-+      CAN_FD_RASCTIVE_MASK        =   0x04,
-+      CAN_FD_SET_TBSEL_MASK       =   0x80,   /* message writen in STB */
-+      CAN_FD_OFF_TBSEL_MASK       =   0x7f,   /* message writen in PTB */
-+      CAN_FD_SET_STBY_MASK        =   0x20,
-+      CAN_FD_OFF_STBY_MASK        =   0xdf,
-+      CAN_FD_SET_TPE_MASK         =   0x10,   /* Transmit primary enable */
-+      CAN_FD_SET_TPA_MASK         =   0x08,
-+      CAN_FD_SET_SACK_MASK        =   0x80,
-+      CAN_FD_SET_RREL_MASK        =   0x10,
-+      CAN_FD_RSTAT_NOT_EMPTY_MASK =   0x03,
-+      CAN_FD_SET_RIF_MASK         =   0x80,
-+      CAN_FD_OFF_RIF_MASK         =   0x7f,
-+      CAN_FD_SET_RAFIF_MASK       =   0x10,
-+      CAN_FD_SET_RFIF_MASK        =   0x20,
-+      CAN_FD_SET_TPIF_MASK        =   0x08,   /* Transmission Primary Interrupt Flag */
-+      CAN_FD_SET_TSIF_MASK        =   0x04,
-+      CAN_FD_SET_EIF_MASK         =   0x02,
-+      CAN_FD_SET_AIF_MASK         =   0x01,
-+      CAN_FD_SET_EWARN_MASK       =   0x80,
-+      CAN_FD_SET_EPASS_MASK       =   0x40,
-+      CAN_FD_SET_EPIE_MASK        =   0x20,
-+      CAN_FD_SET_EPIF_MASK        =   0x10,
-+      CAN_FD_SET_ALIE_MASK        =   0x08,
-+      CAN_FD_SET_ALIF_MASK        =   0x04,
-+      CAN_FD_SET_BEIE_MASK        =   0x02,
-+      CAN_FD_SET_BEIF_MASK        =   0x01,
-+      CAN_FD_OFF_EPIE_MASK        =   0xdf,
-+      CAN_FD_OFF_BEIE_MASK        =   0xfd,
-+      CAN_FD_SET_AFWL_MASK        =   0x40,
-+      CAN_FD_SET_EWL_MASK         =   0x0b,
-+      CAN_FD_SET_KOER_MASK        =   0xe0,
-+      CAN_FD_SET_BIT_ERROR_MASK   =   0x20,
-+      CAN_FD_SET_FORM_ERROR_MASK  =   0x40,
-+      CAN_FD_SET_STUFF_ERROR_MASK =   0x60,
-+      CAN_FD_SET_ACK_ERROR_MASK   =   0x80,
-+      CAN_FD_SET_CRC_ERROR_MASK   =   0xa0,
-+      CAN_FD_SET_OTH_ERROR_MASK   =   0xc0,
-+};
-+
-+/* seg1,seg2,sjw,prescaler all have 8 bits */
-+#define BITS_OF_BITTIMING_REG         8
-+
-+/* in can_bittiming strucure every field has 32 bits---->u32 */
-+#define FBITS_IN_BITTIMING_STR                32
-+#define SEG_1_SHIFT                   0
-+#define SEG_2_SHIFT                   8
-+#define SJW_SHIFT                     16
-+#define PRESC_SHIFT                   24
-+
-+/* TTSEN bit used for 32 bit register read or write */
-+#define TTSEN_8_32_SHIFT              24
-+#define RTR_32_8_SHIFT                        24
-+
-+/* transmit mode */
-+#define XMIT_FULL                     0
-+#define XMIT_SEP_FIFO                 1
-+#define XMIT_SEP_PRIO                 2
-+#define XMIT_PTB_MODE                 3
-+
-+enum  IPMS_CAN_TYPE {
-+      IPMS_CAN_TYPY_CAN       = 0,
-+      IPMS_CAN_TYPE_CANFD,
-+};
-+
-+struct ipms_canfd_priv {
-+      struct can_priv can;
-+      struct napi_struct napi;
-+      struct device *dev;
-+      struct regmap *reg_syscon;
-+      void __iomem *reg_base;
-+      u32 (*read_reg)(const struct ipms_canfd_priv *priv, enum canfd_device_reg reg);
-+      void (*write_reg)(const struct ipms_canfd_priv *priv, enum canfd_device_reg reg, u32 val);
-+      struct clk *can_clk;
-+      u32 tx_mode;
-+      struct reset_control *resets;
-+      struct clk_bulk_data *clks;
-+      int nr_clks;
-+      u32 can_or_canfd;
-+};
-+
-+static struct can_bittiming_const canfd_bittiming_const = {
-+      .name = DRIVER_NAME,
-+      .tseg1_min = 2,
-+      .tseg1_max = 16,
-+      .tseg2_min = 2,
-+      .tseg2_max = 8,
-+      .sjw_max = 4,
-+      .brp_min = 1,
-+      .brp_max = 512,
-+      .brp_inc = 1,
-+
-+};
-+
-+static struct can_bittiming_const canfd_data_bittiming_const = {
-+      .name = DRIVER_NAME,
-+      .tseg1_min = 1,
-+      .tseg1_max = 16,
-+      .tseg2_min = 2,
-+      .tseg2_max = 8,
-+      .sjw_max = 8,
-+      .brp_min = 1,
-+      .brp_max = 512,
-+      .brp_inc = 1,
-+};
-+
-+static void canfd_write_reg_le(const struct ipms_canfd_priv *priv,
-+                              enum canfd_device_reg reg, u32 val)
-+{
-+      iowrite32(val, priv->reg_base + reg);
-+}
-+
-+static u32 canfd_read_reg_le(const struct ipms_canfd_priv *priv,
-+                              enum canfd_device_reg reg)
-+{
-+      return ioread32(priv->reg_base + reg);
-+}
-+
-+static inline unsigned char can_ioread8(const void  *addr)
-+{
-+      void  *addr_down;
-+      union val {
-+              u8 val_8[4];
-+              u32 val_32;
-+      } val;
-+      u32 offset = 0;
-+
-+      addr_down = (void  *)ALIGN_DOWN((unsigned long)addr, 4);
-+      offset = addr - addr_down;
-+      val.val_32 = ioread32(addr_down);
-+      return val.val_8[offset];
-+}
-+
-+static inline void can_iowrite8(unsigned char value, void  *addr)
-+{
-+      void  *addr_down;
-+      union val {
-+              u8 val_8[4];
-+              u32 val_32;
-+      } val;
-+      u8 offset = 0;
-+
-+      addr_down = (void *)ALIGN_DOWN((unsigned long)addr, 4);
-+      offset = addr - addr_down;
-+      val.val_32 = ioread32(addr_down);
-+      val.val_8[offset] = value;
-+      iowrite32(val.val_32, addr_down);
-+}
-+
-+static void canfd_reigister_set_bit(const struct ipms_canfd_priv *priv,
-+                                      enum canfd_device_reg reg,
-+                                      enum canfd_reg_bitchange set_mask)
-+{
-+      void  *addr_down;
-+      union val {
-+              u8 val_8[4];
-+              u32 val_32;
-+      } val;
-+      u8 offset = 0;
-+
-+      addr_down = (void *)ALIGN_DOWN((unsigned long)(priv->reg_base + reg), 4);
-+      offset = (priv->reg_base + reg) - addr_down;
-+      val.val_32 = ioread32(addr_down);
-+      val.val_8[offset] |= set_mask;
-+      iowrite32(val.val_32, addr_down);
-+}
-+
-+static void canfd_reigister_off_bit(const struct ipms_canfd_priv *priv,
-+                                      enum canfd_device_reg reg,
-+                                      enum canfd_reg_bitchange set_mask)
-+{
-+      void  *addr_down;
-+      union val {
-+              u8 val_8[4];
-+              u32 val_32;
-+      } val;
-+      u8 offset = 0;
-+
-+      addr_down = (void *)ALIGN_DOWN((unsigned long)(priv->reg_base + reg), 4);
-+      offset = (priv->reg_base + reg) - addr_down;
-+      val.val_32 = ioread32(addr_down);
-+      val.val_8[offset] &= set_mask;
-+      iowrite32(val.val_32, addr_down);
-+}
-+
-+static int canfd_device_driver_bittime_configuration(struct net_device *ndev)
-+{
-+      struct ipms_canfd_priv *priv = netdev_priv(ndev);
-+      struct can_bittiming *bt = &priv->can.bittiming;
-+      struct can_bittiming *dbt = &priv->can.data_bittiming;
-+      u32 reset_test, bittiming_temp, dat_bittiming;
-+
-+      reset_test = can_ioread8(priv->reg_base + CANFD_CFG_STAT_OFFSET);
-+
-+      if (!(reset_test & CAN_FD_SET_RST_MASK)) {
-+              netdev_alert(ndev, "Not in reset mode, cannot set bit timing\n");
-+              return -EPERM;
-+      }
-+
-+      bittiming_temp = ((bt->phase_seg1 + bt->prop_seg + 1 - 2) << SEG_1_SHIFT) |
-+                       ((bt->phase_seg2 - 1) << SEG_2_SHIFT) |
-+                       ((bt->sjw - 1) << SJW_SHIFT) |
-+                       ((bt->brp - 1) << PRESC_SHIFT);
-+
-+      /* Check the bittime parameter */
-+      if ((((int)(bt->phase_seg1 + bt->prop_seg + 1) - 2) < 0) ||
-+              (((int)(bt->phase_seg2) - 1) < 0) ||
-+              (((int)(bt->sjw) - 1) < 0) ||
-+              (((int)(bt->brp) - 1) < 0))
-+              return -EINVAL;
-+
-+      priv->write_reg(priv, CANFD_S_SEG_1_OFFSET, bittiming_temp);
-+
-+      if (priv->can_or_canfd == IPMS_CAN_TYPE_CANFD) {
-+              dat_bittiming = ((dbt->phase_seg1 + dbt->prop_seg + 1 - 2) << SEG_1_SHIFT) |
-+                              ((dbt->phase_seg2 - 1) << SEG_2_SHIFT) |
-+                              ((dbt->sjw - 1) << SJW_SHIFT) |
-+                              ((dbt->brp - 1) << PRESC_SHIFT);
-+
-+              if ((((int)(dbt->phase_seg1 + dbt->prop_seg + 1) - 2) < 0) ||
-+                      (((int)(dbt->phase_seg2) - 1) < 0) ||
-+                      (((int)(dbt->sjw) - 1) < 0) ||
-+                      (((int)(dbt->brp) - 1) < 0))
-+                      return -EINVAL;
-+
-+              priv->write_reg(priv, CANFD_F_SEG_1_OFFSET, dat_bittiming);
-+      }
-+
-+      canfd_reigister_off_bit(priv, CANFD_CFG_STAT_OFFSET, CAN_FD_OFF_RST_MASK);
-+
-+      netdev_dbg(ndev, "Slow bit rate: %08x\n", priv->read_reg(priv, CANFD_S_SEG_1_OFFSET));
-+      netdev_dbg(ndev, "Fast bit rate: %08x\n", priv->read_reg(priv, CANFD_F_SEG_1_OFFSET));
-+
-+      return 0;
-+}
-+
-+int canfd_get_freebuffer(struct ipms_canfd_priv *priv)
-+{
-+      /* Get next transmit buffer */
-+      canfd_reigister_set_bit(priv, CANFD_TCTRL_OFFSET, CAN_FD_SET_TENEXT_MASK);
-+
-+      if (can_ioread8(priv->reg_base + CANFD_TCTRL_OFFSET) & CAN_FD_SET_TENEXT_MASK)
-+              return -1;
-+
-+      return 0;
-+}
-+
-+static void canfd_tx_interrupt(struct net_device *ndev, u8 isr)
-+{
-+      struct ipms_canfd_priv *priv = netdev_priv(ndev);
-+
-+      /* wait till transmission of the PTB or STB finished */
-+      while (isr & (CAN_FD_SET_TPIF_MASK | CAN_FD_SET_TSIF_MASK)) {
-+              if (isr & CAN_FD_SET_TPIF_MASK)
-+                      canfd_reigister_set_bit(priv, CANFD_RTIF_OFFSET, CAN_FD_SET_TPIF_MASK);
-+
-+              if (isr & CAN_FD_SET_TSIF_MASK)
-+                      canfd_reigister_set_bit(priv, CANFD_RTIF_OFFSET, CAN_FD_SET_TSIF_MASK);
-+
-+              isr = can_ioread8(priv->reg_base + CANFD_RTIF_OFFSET);
-+      }
-+      netif_wake_queue(ndev);
-+}
-+
-+static int can_rx(struct net_device *ndev)
-+{
-+      struct ipms_canfd_priv *priv = netdev_priv(ndev);
-+      struct net_device_stats *stats = &ndev->stats;
-+      struct can_frame *cf;
-+      struct sk_buff *skb;
-+      u32 can_id;
-+      u8  dlc, control, rx_status;
-+
-+      rx_status = can_ioread8(priv->reg_base + CANFD_RCTRL_OFFSET);
-+
-+      if (!(rx_status & CAN_FD_RSTAT_NOT_EMPTY_MASK))
-+              return 0;
-+      control = can_ioread8(priv->reg_base + CANFD_RBUF_CTL_OFFSET);
-+      can_id = priv->read_reg(priv, CANFD_RUBF_ID_OFFSET);
-+      dlc = can_ioread8(priv->reg_base + CANFD_RBUF_CTL_OFFSET) & CAN_FD_SET_DLC_MASK;
-+
-+      skb = alloc_can_skb(ndev, (struct can_frame **)&cf);
-+      if (!skb) {
-+              stats->rx_dropped++;
-+              return 0;
-+      }
-+      cf->can_dlc = can_cc_dlc2len(dlc);
-+
-+      /* change the CANFD id into socketcan id format */
-+      if (control & CAN_FD_SET_IDE_MASK) {
-+              cf->can_id = can_id;
-+              cf->can_id |= CAN_EFF_FLAG;
-+      } else {
-+              cf->can_id = can_id;
-+              cf->can_id &= (~CAN_EFF_FLAG);
-+      }
-+
-+      if (control & CAN_FD_SET_RTR_MASK)
-+              cf->can_id |= CAN_RTR_FLAG;
-+
-+      if (!(control & CAN_FD_SET_RTR_MASK)) {
-+              *((u32 *)(cf->data + 0)) = priv->read_reg(priv, CANFD_RBUF_DATA_OFFSET);
-+              *((u32 *)(cf->data + 4)) = priv->read_reg(priv, CANFD_RBUF_DATA_OFFSET + 4);
-+      }
-+
-+      canfd_reigister_set_bit(priv, CANFD_RCTRL_OFFSET, CAN_FD_SET_RREL_MASK);
-+      stats->rx_bytes += can_fd_dlc2len(cf->can_dlc);
-+      stats->rx_packets++;
-+      netif_receive_skb(skb);
-+
-+      return 1;
-+}
-+
-+static int canfd_rx(struct net_device *ndev)
-+{
-+      struct ipms_canfd_priv *priv = netdev_priv(ndev);
-+      struct net_device_stats *stats = &ndev->stats;
-+      struct canfd_frame *cf;
-+      struct sk_buff *skb;
-+      u32 can_id;
-+      u8  dlc, control, rx_status;
-+      int i;
-+
-+      rx_status = can_ioread8(priv->reg_base + CANFD_RCTRL_OFFSET);
-+
-+      if (!(rx_status & CAN_FD_RSTAT_NOT_EMPTY_MASK))
-+              return 0;
-+      control = can_ioread8(priv->reg_base + CANFD_RBUF_CTL_OFFSET);
-+      can_id = priv->read_reg(priv, CANFD_RUBF_ID_OFFSET);
-+      dlc = can_ioread8(priv->reg_base + CANFD_RBUF_CTL_OFFSET) & CAN_FD_SET_DLC_MASK;
-+
-+      if (control & CAN_FD_SET_EDL_MASK)
-+              /* allocate sk_buffer for canfd frame */
-+              skb = alloc_canfd_skb(ndev, &cf);
-+      else
-+              /* allocate sk_buffer for can frame */
-+              skb = alloc_can_skb(ndev, (struct can_frame **)&cf);
-+
-+      if (!skb) {
-+              stats->rx_dropped++;
-+              return 0;
-+      }
-+
-+      /* change the CANFD or CAN2.0 data into socketcan data format */
-+      if (control & CAN_FD_SET_EDL_MASK)
-+              cf->len = can_fd_dlc2len(dlc);
-+      else
-+              cf->len = can_cc_dlc2len(dlc);
-+
-+      /* change the CANFD id into socketcan id format */
-+      if (control & CAN_FD_SET_EDL_MASK) {
-+              cf->can_id = can_id;
-+              if (control & CAN_FD_SET_IDE_MASK)
-+                      cf->can_id |= CAN_EFF_FLAG;
-+              else
-+                      cf->can_id &= (~CAN_EFF_FLAG);
-+      } else {
-+              cf->can_id = can_id;
-+              if (control & CAN_FD_SET_IDE_MASK)
-+                      cf->can_id |= CAN_EFF_FLAG;
-+              else
-+                      cf->can_id &= (~CAN_EFF_FLAG);
-+
-+              if (control & CAN_FD_SET_RTR_MASK)
-+                      cf->can_id |= CAN_RTR_FLAG;
-+      }
-+
-+      /* CANFD frames handed over to SKB */
-+      if (control & CAN_FD_SET_EDL_MASK) {
-+              for (i = 0; i < cf->len; i += 4)
-+                      *((u32 *)(cf->data + i)) = priv->read_reg(priv, CANFD_RBUF_DATA_OFFSET + i);
-+      } else {
-+              /* skb reads the received datas, if the RTR bit not set */
-+              if (!(control & CAN_FD_SET_RTR_MASK)) {
-+                      *((u32 *)(cf->data + 0)) = priv->read_reg(priv, CANFD_RBUF_DATA_OFFSET);
-+                      *((u32 *)(cf->data + 4)) = priv->read_reg(priv, CANFD_RBUF_DATA_OFFSET + 4);
-+              }
-+      }
-+
-+      canfd_reigister_set_bit(priv, CANFD_RCTRL_OFFSET, CAN_FD_SET_RREL_MASK);
-+
-+      stats->rx_bytes += cf->len;
-+      stats->rx_packets++;
-+      netif_receive_skb(skb);
-+
-+      return 1;
-+}
-+
-+static int canfd_rx_poll(struct napi_struct *napi, int quota)
-+{
-+      struct net_device *ndev = napi->dev;
-+      struct ipms_canfd_priv *priv = netdev_priv(ndev);
-+      int work_done = 0;
-+      u8 rx_status = 0, control = 0;
-+
-+      control = can_ioread8(priv->reg_base + CANFD_RBUF_CTL_OFFSET);
-+      rx_status = can_ioread8(priv->reg_base + CANFD_RCTRL_OFFSET);
-+
-+      /* clear receive interrupt and deal with all the received frames */
-+      while ((rx_status & CAN_FD_RSTAT_NOT_EMPTY_MASK) && (work_done < quota)) {
-+              (control & CAN_FD_SET_EDL_MASK) ? (work_done += canfd_rx(ndev)) : (work_done += can_rx(ndev));
-+
-+              control = can_ioread8(priv->reg_base + CANFD_RBUF_CTL_OFFSET);
-+              rx_status = can_ioread8(priv->reg_base + CANFD_RCTRL_OFFSET);
-+      }
-+      napi_complete(napi);
-+      canfd_reigister_set_bit(priv, CANFD_RTIE_OFFSET, CAN_FD_SET_RIE_MASK);
-+      return work_done;
-+}
-+
-+static void canfd_rxfull_interrupt(struct net_device *ndev, u8 isr)
-+{
-+      struct ipms_canfd_priv *priv = netdev_priv(ndev);
-+
-+      if (isr & CAN_FD_SET_RAFIF_MASK)
-+              canfd_reigister_set_bit(priv, CANFD_RTIF_OFFSET, CAN_FD_SET_RAFIF_MASK);
-+
-+      if (isr & (CAN_FD_SET_RAFIF_MASK | CAN_FD_SET_RFIF_MASK))
-+              canfd_reigister_set_bit(priv, CANFD_RTIF_OFFSET,
-+                                      (CAN_FD_SET_RAFIF_MASK | CAN_FD_SET_RFIF_MASK));
-+}
-+
-+static int set_canfd_xmit_mode(struct net_device *ndev)
-+{
-+      struct ipms_canfd_priv *priv = netdev_priv(ndev);
-+
-+      switch (priv->tx_mode) {
-+      case XMIT_FULL:
-+              canfd_reigister_set_bit(priv, CANFD_TCTRL_OFFSET, CAN_FD_SET_FULLCAN_MASK);
-+              break;
-+      case XMIT_SEP_FIFO:
-+              canfd_reigister_off_bit(priv, CANFD_TCTRL_OFFSET, CAN_FD_OFF_FULLCAN_MASK);
-+              canfd_reigister_set_bit(priv, CANFD_TCTRL_OFFSET, CAN_FD_SET_FIFO_MASK);
-+              canfd_reigister_off_bit(priv, CANFD_TCMD_OFFSET, CAN_FD_SET_TBSEL_MASK);
-+              break;
-+      case XMIT_SEP_PRIO:
-+              canfd_reigister_off_bit(priv, CANFD_TCTRL_OFFSET, CAN_FD_OFF_FULLCAN_MASK);
-+              canfd_reigister_off_bit(priv, CANFD_TCTRL_OFFSET, CAN_FD_OFF_FIFO_MASK);
-+              canfd_reigister_off_bit(priv, CANFD_TCMD_OFFSET, CAN_FD_SET_TBSEL_MASK);
-+              break;
-+      case XMIT_PTB_MODE:
-+              canfd_reigister_off_bit(priv, CANFD_TCMD_OFFSET, CAN_FD_OFF_TBSEL_MASK);
-+              break;
-+      default:
-+              break;
-+      }
-+      return 0;
-+}
-+
-+static netdev_tx_t canfd_driver_start_xmit(struct sk_buff *skb, struct net_device *ndev)
-+{
-+      struct ipms_canfd_priv *priv = netdev_priv(ndev);
-+      struct canfd_frame *cf = (struct canfd_frame *)skb->data;
-+      struct net_device_stats *stats = &ndev->stats;
-+      u32 ttsen, id, ctl, addr_off;
-+      int i;
-+
-+      priv->tx_mode = XMIT_PTB_MODE;
-+
-+      if (can_dropped_invalid_skb(ndev, skb))
-+              return NETDEV_TX_OK;
-+
-+      switch (priv->tx_mode) {
-+      case XMIT_FULL:
-+              return NETDEV_TX_BUSY;
-+      case XMIT_PTB_MODE:
-+              set_canfd_xmit_mode(ndev);
-+              canfd_reigister_off_bit(priv, CANFD_TCMD_OFFSET, CAN_FD_OFF_STBY_MASK);
-+
-+              if (cf->can_id & CAN_EFF_FLAG) {
-+                      id = (cf->can_id & CAN_EFF_MASK);
-+                      ttsen = 0 << TTSEN_8_32_SHIFT;
-+                      id |= ttsen;
-+              } else {
-+                      id = (cf->can_id & CAN_SFF_MASK);
-+                      ttsen = 0 << TTSEN_8_32_SHIFT;
-+                      id |= ttsen;
-+              }
-+
-+              ctl = can_fd_len2dlc(cf->len);
-+
-+              /* transmit can fd frame */
-+              if (priv->can_or_canfd == IPMS_CAN_TYPE_CANFD) {
-+                      if (can_is_canfd_skb(skb)) {
-+                              if (cf->can_id & CAN_EFF_FLAG)
-+                                      ctl |= CAN_FD_SET_IDE_MASK;
-+                              else
-+                                      ctl &= CAN_FD_OFF_IDE_MASK;
-+
-+                              if (cf->flags & CANFD_BRS)
-+                                      ctl |= CAN_FD_SET_BRS_MASK;
-+
-+                              ctl |= CAN_FD_SET_EDL_MASK;
-+
-+                              addr_off = CANFD_TBUF_DATA_OFFSET;
-+
-+                              for (i = 0; i < cf->len; i += 4) {
-+                                      priv->write_reg(priv, addr_off,
-+                                                      *((u32 *)(cf->data + i)));
-+                                      addr_off += 4;
-+                              }
-+                      } else {
-+                              ctl &= CAN_FD_OFF_EDL_MASK;
-+                              ctl &= CAN_FD_OFF_BRS_MASK;
-+
-+                              if (cf->can_id & CAN_EFF_FLAG)
-+                                      ctl |= CAN_FD_SET_IDE_MASK;
-+                              else
-+                                      ctl &= CAN_FD_OFF_IDE_MASK;
-+
-+                              if (cf->can_id & CAN_RTR_FLAG) {
-+                                      ctl |= CAN_FD_SET_RTR_MASK;
-+                                      priv->write_reg(priv,
-+                                              CANFD_TBUF_ID_OFFSET, id);
-+                                      priv->write_reg(priv,
-+                                              CANFD_TBUF_CTL_OFFSET, ctl);
-+                              } else {
-+                                      ctl &= CAN_FD_OFF_RTR_MASK;
-+                                      addr_off = CANFD_TBUF_DATA_OFFSET;
-+                                      priv->write_reg(priv, addr_off,
-+                                                      *((u32 *)(cf->data + 0)));
-+                                      priv->write_reg(priv, addr_off + 4,
-+                                                      *((u32 *)(cf->data + 4)));
-+                              }
-+                      }
-+                      priv->write_reg(priv, CANFD_TBUF_ID_OFFSET, id);
-+                      priv->write_reg(priv, CANFD_TBUF_CTL_OFFSET, ctl);
-+                      addr_off = CANFD_TBUF_DATA_OFFSET;
-+              } else {
-+                      ctl &= CAN_FD_OFF_EDL_MASK;
-+                      ctl &= CAN_FD_OFF_BRS_MASK;
-+
-+                      if (cf->can_id & CAN_EFF_FLAG)
-+                              ctl |= CAN_FD_SET_IDE_MASK;
-+                      else
-+                              ctl &= CAN_FD_OFF_IDE_MASK;
-+
-+                      if (cf->can_id & CAN_RTR_FLAG) {
-+                              ctl |= CAN_FD_SET_RTR_MASK;
-+                              priv->write_reg(priv, CANFD_TBUF_ID_OFFSET, id);
-+                              priv->write_reg(priv, CANFD_TBUF_CTL_OFFSET, ctl);
-+                      } else {
-+                              ctl &= CAN_FD_OFF_RTR_MASK;
-+                              priv->write_reg(priv, CANFD_TBUF_ID_OFFSET, id);
-+                              priv->write_reg(priv, CANFD_TBUF_CTL_OFFSET, ctl);
-+                              addr_off = CANFD_TBUF_DATA_OFFSET;
-+                              priv->write_reg(priv, addr_off,
-+                                              *((u32 *)(cf->data + 0)));
-+                              priv->write_reg(priv, addr_off + 4,
-+                                              *((u32 *)(cf->data + 4)));
-+                      }
-+              }
-+              canfd_reigister_set_bit(priv, CANFD_TCMD_OFFSET, CAN_FD_SET_TPE_MASK);
-+              stats->tx_bytes += cf->len;
-+              break;
-+      default:
-+              break;
-+      }
-+
-+      /*Due to cache blocking, we need call dev_kfree_skb() here to free the socket
-+      buffer and return NETDEV_TX_OK */
-+      dev_kfree_skb(skb);
-+
-+      return NETDEV_TX_OK;
-+}
-+
-+static int set_reset_mode(struct net_device *ndev)
-+{
-+      struct ipms_canfd_priv *priv = netdev_priv(ndev);
-+      u8 ret;
-+
-+      ret = can_ioread8(priv->reg_base + CANFD_CFG_STAT_OFFSET);
-+      ret |= CAN_FD_SET_RST_MASK;
-+      can_iowrite8(ret, priv->reg_base + CANFD_CFG_STAT_OFFSET);
-+
-+      return 0;
-+}
-+
-+static void canfd_driver_stop(struct net_device *ndev)
-+{
-+      struct ipms_canfd_priv *priv = netdev_priv(ndev);
-+      int ret;
-+
-+      ret = set_reset_mode(ndev);
-+      if (ret)
-+              netdev_err(ndev, "Mode Resetting Failed!\n");
-+
-+      priv->can.state = CAN_STATE_STOPPED;
-+}
-+
-+static int canfd_driver_close(struct net_device *ndev)
-+{
-+      struct ipms_canfd_priv *priv = netdev_priv(ndev);
-+
-+      netif_stop_queue(ndev);
-+      napi_disable(&priv->napi);
-+      canfd_driver_stop(ndev);
-+
-+      free_irq(ndev->irq, ndev);
-+      close_candev(ndev);
-+
-+      pm_runtime_put(priv->dev);
-+
-+      return 0;
-+}
-+
-+static enum can_state get_of_chip_status(struct net_device *ndev)
-+{
-+      struct ipms_canfd_priv *priv = netdev_priv(ndev);
-+      u8 can_stat, eir;
-+
-+      can_stat = can_ioread8(priv->reg_base + CANFD_CFG_STAT_OFFSET);
-+      eir = can_ioread8(priv->reg_base + CANFD_ERRINT_OFFSET);
-+
-+      if (can_stat & CAN_FD_SET_BUSOFF_MASK)
-+              return CAN_STATE_BUS_OFF;
-+
-+      if ((eir & CAN_FD_SET_EPASS_MASK) && ~(can_stat & CAN_FD_SET_BUSOFF_MASK))
-+              return CAN_STATE_ERROR_PASSIVE;
-+
-+      if (eir & CAN_FD_SET_EWARN_MASK && ~(eir & CAN_FD_SET_EPASS_MASK))
-+              return CAN_STATE_ERROR_WARNING;
-+
-+      if (~(eir & CAN_FD_SET_EPASS_MASK))
-+              return CAN_STATE_ERROR_ACTIVE;
-+
-+      return CAN_STATE_ERROR_ACTIVE;
-+}
-+
-+static void canfd_error_interrupt(struct net_device *ndev, u8 isr, u8 eir)
-+{
-+      struct ipms_canfd_priv *priv = netdev_priv(ndev);
-+      struct net_device_stats *stats = &ndev->stats;
-+      struct can_frame *cf;
-+      struct sk_buff *skb;
-+      u8 koer, recnt = 0, tecnt = 0, can_stat = 0;
-+
-+      skb = alloc_can_err_skb(ndev, &cf);
-+
-+      koer = can_ioread8(priv->reg_base + CANFD_EALCAP_OFFSET) & CAN_FD_SET_KOER_MASK;
-+      recnt = can_ioread8(priv->reg_base + CANFD_RECNT_OFFSET);
-+      tecnt = can_ioread8(priv->reg_base + CANFD_TECNT_OFFSET);
-+
-+      /*Read can status*/
-+      can_stat = can_ioread8(priv->reg_base + CANFD_CFG_STAT_OFFSET);
-+
-+      /* Bus off --->active error mode */
-+      if ((isr & CAN_FD_SET_EIF_MASK) && priv->can.state == CAN_STATE_BUS_OFF)
-+              priv->can.state = get_of_chip_status(ndev);
-+
-+      /* State selection */
-+      if (can_stat & CAN_FD_SET_BUSOFF_MASK) {
-+              priv->can.state = get_of_chip_status(ndev);
-+              priv->can.can_stats.bus_off++;
-+              canfd_reigister_set_bit(priv, CANFD_CFG_STAT_OFFSET, CAN_FD_SET_BUSOFF_MASK);
-+              can_bus_off(ndev);
-+              if (skb)
-+                      cf->can_id |= CAN_ERR_BUSOFF;
-+
-+      } else if ((eir & CAN_FD_SET_EPASS_MASK) && ~(can_stat & CAN_FD_SET_BUSOFF_MASK)) {
-+              priv->can.state = get_of_chip_status(ndev);
-+              priv->can.can_stats.error_passive++;
-+              if (skb) {
-+                      cf->can_id |= CAN_ERR_CRTL;
-+                      cf->data[1] |= (recnt > 127) ? CAN_ERR_CRTL_RX_PASSIVE : 0;
-+                      cf->data[1] |= (tecnt > 127) ? CAN_ERR_CRTL_TX_PASSIVE : 0;
-+                      cf->data[6] = tecnt;
-+                      cf->data[7] = recnt;
-+              }
-+      } else if (eir & CAN_FD_SET_EWARN_MASK && ~(eir & CAN_FD_SET_EPASS_MASK)) {
-+              priv->can.state = get_of_chip_status(ndev);
-+              priv->can.can_stats.error_warning++;
-+              if (skb) {
-+                      cf->can_id |= CAN_ERR_CRTL;
-+                      cf->data[1] |= (recnt > 95) ? CAN_ERR_CRTL_RX_WARNING : 0;
-+                      cf->data[1] |= (tecnt > 95) ? CAN_ERR_CRTL_TX_WARNING : 0;
-+                      cf->data[6] = tecnt;
-+                      cf->data[7] = recnt;
-+              }
-+      }
-+
-+      /* Check for in protocol defined error interrupt */
-+      if (eir & CAN_FD_SET_BEIF_MASK) {
-+              if (skb)
-+                      cf->can_id |= CAN_ERR_BUSERROR | CAN_ERR_PROT;
-+
-+              /* bit error interrupt */
-+              if (koer == CAN_FD_SET_BIT_ERROR_MASK) {
-+                      stats->tx_errors++;
-+                      if (skb) {
-+                              cf->can_id |= CAN_ERR_PROT;
-+                              cf->data[2] = CAN_ERR_PROT_BIT;
-+                      }
-+              }
-+              /* format error interrupt */
-+              if (koer == CAN_FD_SET_FORM_ERROR_MASK) {
-+                      stats->rx_errors++;
-+                      if (skb) {
-+                              cf->can_id |= CAN_ERR_PROT;
-+                              cf->data[2] = CAN_ERR_PROT_FORM;
-+                      }
-+              }
-+              /* stuffing error interrupt */
-+              if (koer == CAN_FD_SET_STUFF_ERROR_MASK) {
-+                      stats->rx_errors++;
-+                      if (skb) {
-+                              cf->can_id |= CAN_ERR_PROT;
-+                              cf->data[3] = CAN_ERR_PROT_STUFF;
-+                      }
-+              }
-+              /* ack error interrupt */
-+              if (koer == CAN_FD_SET_ACK_ERROR_MASK) {
-+                      stats->tx_errors++;
-+                      if (skb) {
-+                              cf->can_id |= CAN_ERR_PROT;
-+                              cf->data[2] = CAN_ERR_PROT_LOC_ACK;
-+                      }
-+              }
-+              /* crc error interrupt */
-+              if (koer == CAN_FD_SET_CRC_ERROR_MASK) {
-+                      stats->rx_errors++;
-+                      if (skb) {
-+                              cf->can_id |= CAN_ERR_PROT;
-+                              cf->data[2] = CAN_ERR_PROT_LOC_CRC_SEQ;
-+                      }
-+              }
-+              priv->can.can_stats.bus_error++;
-+      }
-+      if (skb) {
-+              stats->rx_packets++;
-+              stats->rx_bytes += cf->can_dlc;
-+              netif_rx(skb);
-+      }
-+
-+      netdev_dbg(ndev, "Recnt is 0x%02x", can_ioread8(priv->reg_base + CANFD_RECNT_OFFSET));
-+      netdev_dbg(ndev, "Tecnt is 0x%02x", can_ioread8(priv->reg_base + CANFD_TECNT_OFFSET));
-+}
-+
-+static irqreturn_t canfd_interrupt(int irq, void *dev_id)
-+{
-+      struct net_device *ndev = (struct net_device *)dev_id;
-+      struct ipms_canfd_priv *priv = netdev_priv(ndev);
-+      u8 isr, eir;
-+      u8 isr_handled = 0, eir_handled = 0;
-+
-+      /* read the value of interrupt status register */
-+      isr = can_ioread8(priv->reg_base + CANFD_RTIF_OFFSET);
-+
-+      /* read the value of error interrupt register */
-+      eir = can_ioread8(priv->reg_base + CANFD_ERRINT_OFFSET);
-+
-+      /* Check for Tx interrupt and Processing it */
-+      if (isr & (CAN_FD_SET_TPIF_MASK | CAN_FD_SET_TSIF_MASK)) {
-+              canfd_tx_interrupt(ndev, isr);
-+              isr_handled |= (CAN_FD_SET_TPIF_MASK | CAN_FD_SET_TSIF_MASK);
-+      }
-+      if (isr & (CAN_FD_SET_RAFIF_MASK | CAN_FD_SET_RFIF_MASK)) {
-+              canfd_rxfull_interrupt(ndev, isr);
-+              isr_handled |= (CAN_FD_SET_RAFIF_MASK | CAN_FD_SET_RFIF_MASK);
-+      }
-+      /* Check Rx interrupt and Processing the receive interrupt routine */
-+      if (isr & CAN_FD_SET_RIF_MASK) {
-+              canfd_reigister_off_bit(priv, CANFD_RTIE_OFFSET, CAN_FD_OFF_RIE_MASK);
-+              canfd_reigister_set_bit(priv, CANFD_RTIF_OFFSET, CAN_FD_SET_RIF_MASK);
-+
-+              napi_schedule(&priv->napi);
-+              isr_handled |= CAN_FD_SET_RIF_MASK;
-+      }
-+      if ((isr & CAN_FD_SET_EIF_MASK) | (eir & (CAN_FD_SET_EPIF_MASK | CAN_FD_SET_BEIF_MASK))) {
-+              /* reset EPIF and BEIF. Reset EIF */
-+              canfd_reigister_set_bit(priv, CANFD_ERRINT_OFFSET,
-+                                      eir & (CAN_FD_SET_EPIF_MASK | CAN_FD_SET_BEIF_MASK));
-+              canfd_reigister_set_bit(priv, CANFD_RTIF_OFFSET,
-+                                      isr & CAN_FD_SET_EIF_MASK);
-+
-+              canfd_error_interrupt(ndev, isr, eir);
-+
-+              isr_handled |= CAN_FD_SET_EIF_MASK;
-+              eir_handled |= (CAN_FD_SET_EPIF_MASK | CAN_FD_SET_BEIF_MASK);
-+      }
-+      if ((isr_handled == 0) && (eir_handled == 0)) {
-+              netdev_err(ndev, "Unhandled interrupt!\n");
-+              return IRQ_NONE;
-+      }
-+
-+      return IRQ_HANDLED;
-+}
-+
-+static int canfd_chip_start(struct net_device *ndev)
-+{
-+      struct ipms_canfd_priv *priv = netdev_priv(ndev);
-+      int err;
-+      u8 ret;
-+
-+      err = set_reset_mode(ndev);
-+      if (err) {
-+              netdev_err(ndev, "Mode Resetting Failed!\n");
-+              return err;
-+      }
-+
-+      err = canfd_device_driver_bittime_configuration(ndev);
-+      if (err) {
-+              netdev_err(ndev, "Bittime Setting Failed!\n");
-+              return err;
-+      }
-+
-+      /* Set Almost Full Warning Limit */
-+      canfd_reigister_set_bit(priv, CANFD_LIMIT_OFFSET, CAN_FD_SET_AFWL_MASK);
-+
-+      /* Programmable Error Warning Limit = (EWL+1)*8. Set EWL=11->Error Warning=96 */
-+      canfd_reigister_set_bit(priv, CANFD_LIMIT_OFFSET, CAN_FD_SET_EWL_MASK);
-+
-+      /* Interrupts enable */
-+      can_iowrite8(CAN_FD_INTR_ALL_MASK, priv->reg_base + CANFD_RTIE_OFFSET);
-+
-+      /* Error Interrupts enable(Error Passive and Bus Error) */
-+      canfd_reigister_set_bit(priv, CANFD_ERRINT_OFFSET, CAN_FD_SET_EPIE_MASK);
-+
-+      ret = can_ioread8(priv->reg_base + CANFD_CFG_STAT_OFFSET);
-+
-+      /* Check whether it is loopback mode or normal mode */
-+      if (priv->can.ctrlmode & CAN_CTRLMODE_LOOPBACK) {
-+              ret |= CAN_FD_LBMIMOD_MASK;
-+      } else {
-+              ret &= ~CAN_FD_LBMEMOD_MASK;
-+              ret &= ~CAN_FD_LBMIMOD_MASK;
-+      }
-+
-+      can_iowrite8(ret, priv->reg_base + CANFD_CFG_STAT_OFFSET);
-+
-+      priv->can.state = CAN_STATE_ERROR_ACTIVE;
-+
-+      return 0;
-+}
-+
-+static int  canfd_do_set_mode(struct net_device *ndev, enum can_mode mode)
-+{
-+      int ret;
-+
-+      switch (mode) {
-+      case CAN_MODE_START:
-+              ret = canfd_chip_start(ndev);
-+              if (ret) {
-+                      netdev_err(ndev, "Could Not Start CAN device !!\n");
-+                      return ret;
-+              }
-+              netif_wake_queue(ndev);
-+              break;
-+      default:
-+              ret = -EOPNOTSUPP;
-+              break;
-+      }
-+
-+      return ret;
-+}
-+
-+static int canfd_driver_open(struct net_device *ndev)
-+{
-+      struct ipms_canfd_priv *priv = netdev_priv(ndev);
-+      int ret;
-+
-+      ret = pm_runtime_get_sync(priv->dev);
-+      if (ret < 0) {
-+              netdev_err(ndev, "%s: pm_runtime_get failed(%d)\n",
-+                         __func__, ret);
-+              goto err;
-+      }
-+
-+      /* Set chip into reset mode */
-+      ret = set_reset_mode(ndev);
-+      if (ret) {
-+              netdev_err(ndev, "Mode Resetting Failed!\n");
-+              return ret;
-+      }
-+
-+      /* Common open */
-+      ret = open_candev(ndev);
-+      if (ret)
-+              return ret;
-+
-+      /* Register interrupt handler */
-+      ret = request_irq(ndev->irq, canfd_interrupt, IRQF_SHARED, ndev->name, ndev);
-+      if (ret) {
-+              netdev_err(ndev, "Request_irq err: %d\n", ret);
-+              goto exit_irq;
-+      }
-+
-+      ret = canfd_chip_start(ndev);
-+      if (ret) {
-+              netdev_err(ndev, "Could Not Start CAN device !\n");
-+              goto exit_can_start;
-+      }
-+
-+      napi_enable(&priv->napi);
-+      netif_start_queue(ndev);
-+
-+      return 0;
-+
-+exit_can_start:
-+      free_irq(ndev->irq, ndev);
-+err:
-+      pm_runtime_put(priv->dev);
-+exit_irq:
-+      close_candev(ndev);
-+      return ret;
-+}
-+
-+static int canfd_control_parse_dt(struct ipms_canfd_priv *priv)
-+{
-+      struct of_phandle_args args;
-+      u32 syscon_mask, syscon_shift;
-+      u32 can_or_canfd;
-+      u32 syscon_offset, regval;
-+      int ret;
-+
-+      ret = of_parse_phandle_with_fixed_args(priv->dev->of_node,
-+                                              "starfive,sys-syscon", 3, 0, &args);
-+      if (ret) {
-+              dev_err(priv->dev, "Failed to parse starfive,sys-syscon\n");
-+              return -EINVAL;
-+      }
-+
-+      priv->reg_syscon = syscon_node_to_regmap(args.np);
-+      of_node_put(args.np);
-+      if (IS_ERR(priv->reg_syscon))
-+              return PTR_ERR(priv->reg_syscon);
-+
-+      syscon_offset = args.args[0];
-+      syscon_shift  = args.args[1];
-+      syscon_mask   = args.args[2];
-+
-+      ret = device_property_read_u32(priv->dev, "syscon,can_or_canfd", &can_or_canfd);
-+      if (ret)
-+              goto exit_parse;
-+
-+      priv->can_or_canfd = can_or_canfd;
-+
-+      /* enable can2.0/canfd function */
-+      regval = can_or_canfd << syscon_shift;
-+      ret = regmap_update_bits(priv->reg_syscon, syscon_offset, syscon_mask, regval);
-+      if (ret)
-+              return ret;
-+      return 0;
-+exit_parse:
-+      return ret;
-+}
-+
-+static const struct net_device_ops canfd_netdev_ops = {
-+      .ndo_open = canfd_driver_open,
-+      .ndo_stop = canfd_driver_close,
-+      .ndo_start_xmit = canfd_driver_start_xmit,
-+      .ndo_change_mtu = can_change_mtu,
-+};
-+
-+static int canfd_driver_probe(struct platform_device *pdev)
-+{
-+      struct net_device *ndev;
-+      struct ipms_canfd_priv *priv;
-+      void __iomem *addr;
-+      int ret;
-+      u32 frq;
-+
-+      addr = devm_platform_ioremap_resource(pdev, 0);
-+      if (IS_ERR(addr)) {
-+              ret = PTR_ERR(addr);
-+              goto exit;
-+      }
-+
-+      ndev = alloc_candev(sizeof(struct ipms_canfd_priv), 1);
-+      if (!ndev) {
-+              ret = -ENOMEM;
-+              goto exit;
-+      }
-+
-+      priv = netdev_priv(ndev);
-+      priv->dev = &pdev->dev;
-+
-+      ret = canfd_control_parse_dt(priv);
-+      if (ret)
-+              goto free_exit;
-+
-+      priv->nr_clks = devm_clk_bulk_get_all(priv->dev, &priv->clks);
-+      if (priv->nr_clks < 0) {
-+              dev_err(priv->dev, "Failed to get can clocks\n");
-+              ret = -ENODEV;
-+              goto free_exit;
-+      }
-+
-+      ret = clk_bulk_prepare_enable(priv->nr_clks, priv->clks);
-+      if (ret) {
-+              dev_err(priv->dev, "Failed to enable clocks\n");
-+              goto free_exit;
-+      }
-+
-+      priv->resets = devm_reset_control_array_get_exclusive(priv->dev);
-+      if (IS_ERR(priv->resets)) {
-+              ret = PTR_ERR(priv->resets);
-+              dev_err(priv->dev, "Failed to get can resets");
-+              goto clk_exit;
-+      }
-+
-+      ret = reset_control_deassert(priv->resets);
-+      if (ret)
-+              goto clk_exit;
-+      priv->can.bittiming_const = &canfd_bittiming_const;
-+      priv->can.data_bittiming_const = &canfd_data_bittiming_const;
-+      priv->can.do_set_mode = canfd_do_set_mode;
-+
-+      /* in user space the execution mode can be chosen */
-+      if (priv->can_or_canfd == IPMS_CAN_TYPE_CANFD)
-+              priv->can.ctrlmode_supported = CAN_CTRLMODE_LOOPBACK | CAN_CTRLMODE_FD;
-+      else
-+              priv->can.ctrlmode_supported = CAN_CTRLMODE_LOOPBACK;
-+      priv->reg_base = addr;
-+      priv->write_reg = canfd_write_reg_le;
-+      priv->read_reg = canfd_read_reg_le;
-+
-+      pm_runtime_enable(&pdev->dev);
-+
-+      priv->can_clk = devm_clk_get(&pdev->dev, "core_clk");
-+      if (IS_ERR(priv->can_clk)) {
-+              dev_err(&pdev->dev, "Device clock not found.\n");
-+              ret = PTR_ERR(priv->can_clk);
-+              goto reset_exit;
-+      }
-+
-+      device_property_read_u32(priv->dev, "frequency", &frq);
-+      clk_set_rate(priv->can_clk, frq);
-+
-+      priv->can.clock.freq = clk_get_rate(priv->can_clk);
-+      ndev->irq = platform_get_irq(pdev, 0);
-+
-+      /* we support local echo */
-+      ndev->flags |= IFF_ECHO;
-+      ndev->netdev_ops = &canfd_netdev_ops;
-+
-+      platform_set_drvdata(pdev, ndev);
-+      SET_NETDEV_DEV(ndev, &pdev->dev);
-+
-+      netif_napi_add(ndev, &priv->napi, canfd_rx_poll);
-+      ret = register_candev(ndev);
-+      if (ret) {
-+              dev_err(&pdev->dev, "Fail to register failed (err=%d)\n", ret);
-+              goto reset_exit;
-+      }
-+
-+      dev_dbg(&pdev->dev, "Driver registered: regs=%p, irp=%d, clock=%d\n",
-+              priv->reg_base, ndev->irq, priv->can.clock.freq);
-+
-+      return 0;
-+
-+reset_exit:
-+      reset_control_assert(priv->resets);
-+clk_exit:
-+      clk_bulk_disable_unprepare(priv->nr_clks, priv->clks);
-+free_exit:
-+      free_candev(ndev);
-+exit:
-+      return ret;
-+}
-+
-+static int canfd_driver_remove(struct platform_device *pdev)
-+{
-+      struct net_device *ndev = platform_get_drvdata(pdev);
-+      struct ipms_canfd_priv *priv = netdev_priv(ndev);
-+
-+      reset_control_assert(priv->resets);
-+      clk_bulk_disable_unprepare(priv->nr_clks, priv->clks);
-+      pm_runtime_disable(&pdev->dev);
-+
-+      unregister_candev(ndev);
-+      netif_napi_del(&priv->napi);
-+      free_candev(ndev);
-+
-+      return 0;
-+}
-+
-+#ifdef CONFIG_PM_SLEEP
-+static int __maybe_unused canfd_suspend(struct device *dev)
-+{
-+      struct net_device *ndev = dev_get_drvdata(dev);
-+
-+      if (netif_running(ndev)) {
-+              netif_stop_queue(ndev);
-+              netif_device_detach(ndev);
-+              canfd_driver_stop(ndev);
-+      }
-+
-+      return pm_runtime_force_suspend(dev);
-+}
-+
-+static int __maybe_unused canfd_resume(struct device *dev)
-+{
-+      struct net_device *ndev = dev_get_drvdata(dev);
-+      int ret;
-+
-+      ret = pm_runtime_force_resume(dev);
-+      if (ret) {
-+              dev_err(dev, "pm_runtime_force_resume failed on resume\n");
-+              return ret;
-+      }
-+
-+      if (netif_running(ndev)) {
-+              ret = canfd_chip_start(ndev);
-+              if (ret) {
-+                      dev_err(dev, "canfd_chip_start failed on resume\n");
-+                      return ret;
-+              }
-+
-+              netif_device_attach(ndev);
-+              netif_start_queue(ndev);
-+      }
-+
-+      return 0;
-+}
-+#endif
-+
-+#ifdef CONFIG_PM
-+static int canfd_runtime_suspend(struct device *dev)
-+{
-+      struct net_device *ndev = dev_get_drvdata(dev);
-+      struct ipms_canfd_priv *priv = netdev_priv(ndev);
-+
-+      reset_control_assert(priv->resets);
-+      clk_bulk_disable_unprepare(priv->nr_clks, priv->clks);
-+
-+      return 0;
-+}
-+
-+static int canfd_runtime_resume(struct device *dev)
-+{
-+      struct net_device *ndev = dev_get_drvdata(dev);
-+      struct ipms_canfd_priv *priv = netdev_priv(ndev);
-+      int ret;
-+
-+      ret = clk_bulk_prepare_enable(priv->nr_clks, priv->clks);
-+      if (ret) {
-+              dev_err(dev, "Failed to  prepare_enable clk\n");
-+              return ret;
-+      }
-+
-+      ret = reset_control_deassert(priv->resets);
-+      if (ret) {
-+              dev_err(dev, "Failed to deassert reset\n");
-+              return ret;
-+      }
-+
-+      return 0;
-+}
-+#endif
-+
-+static const struct dev_pm_ops canfd_pm_ops = {
-+      SET_SYSTEM_SLEEP_PM_OPS(canfd_suspend, canfd_resume)
-+      SET_RUNTIME_PM_OPS(canfd_runtime_suspend,
-+                         canfd_runtime_resume, NULL)
-+};
-+
-+static const struct of_device_id canfd_of_match[] = {
-+      { .compatible = "ipms,can" },
-+      { }
-+};
-+MODULE_DEVICE_TABLE(of, canfd_of_match);
-+
-+static struct platform_driver can_driver = {
-+      .probe          = canfd_driver_probe,
-+      .remove         = canfd_driver_remove,
-+      .driver = {
-+              .name  = DRIVER_NAME,
-+              .pm    = &canfd_pm_ops,
-+              .of_match_table = canfd_of_match,
-+      },
-+};
-+
-+module_platform_driver(can_driver);
-+
-+MODULE_DESCRIPTION("ipms can controller driver for StarFive jh7110 SoC");
-+MODULE_AUTHOR("William Qiu<william.qiu@starfivetech.com");
-+MODULE_LICENSE("GPL");
diff --git a/target/linux/starfive/patches-6.6/0071-regulator-starfive-jh7110-Add-regulator-support-for-.patch b/target/linux/starfive/patches-6.6/0071-regulator-starfive-jh7110-Add-regulator-support-for-.patch
deleted file mode 100644 (file)
index cf1e623..0000000
+++ /dev/null
@@ -1,204 +0,0 @@
-From b12213d474966fbf47e7afa36a6655b5b241cf36 Mon Sep 17 00:00:00 2001
-From: "Kevin.xie" <kevin.xie@starfivetech.com>
-Date: Fri, 9 Jun 2023 14:57:13 +0800
-Subject: [PATCH 071/116] regulator: starfive-jh7110: Add regulator support for
- JH7110 A type EVB.
-
-Add 7 regulators base on regulator framework for
-JH7110 evb HW design.
-
-Signed-off-by: Kevin.xie <kevin.xie@starfivetech.com>
----
- drivers/regulator/Kconfig                     |  10 ++
- drivers/regulator/Makefile                    |   1 +
- drivers/regulator/starfive-jh7110-regulator.c | 126 ++++++++++++++++++
- include/linux/regulator/jh7110.h              |  24 ++++
- 4 files changed, 161 insertions(+)
- create mode 100644 drivers/regulator/starfive-jh7110-regulator.c
- create mode 100644 include/linux/regulator/jh7110.h
-
---- a/drivers/regulator/Kconfig
-+++ b/drivers/regulator/Kconfig
-@@ -1335,6 +1335,16 @@ config REGULATOR_SM5703
-         This driver provides support for voltage regulators of SM5703
-         multi-function device.
-+config REGULATOR_STARFIVE_JH7110
-+      tristate "Starfive JH7110 PMIC"
-+      depends on I2C
-+      select REGMAP_I2C
-+      help
-+        Say y here to select this option to enable the power regulator of
-+        Starfive JH7110 PMIC.
-+        This driver supports the control of different power rails of device
-+        through regulator interface.
-+
- config REGULATOR_STM32_BOOSTER
-       tristate "STMicroelectronics STM32 BOOSTER"
-       depends on ARCH_STM32 || COMPILE_TEST
---- a/drivers/regulator/Makefile
-+++ b/drivers/regulator/Makefile
-@@ -156,6 +156,7 @@ obj-$(CONFIG_REGULATOR_SC2731) += sc2731
- obj-$(CONFIG_REGULATOR_SKY81452) += sky81452-regulator.o
- obj-$(CONFIG_REGULATOR_SLG51000) += slg51000-regulator.o
- obj-$(CONFIG_REGULATOR_SM5703) += sm5703-regulator.o
-+obj-$(CONFIG_REGULATOR_STARFIVE_JH7110) += starfive-jh7110-regulator.o
- obj-$(CONFIG_REGULATOR_STM32_BOOSTER) += stm32-booster.o
- obj-$(CONFIG_REGULATOR_STM32_VREFBUF) += stm32-vrefbuf.o
- obj-$(CONFIG_REGULATOR_STM32_PWR) += stm32-pwr.o
---- /dev/null
-+++ b/drivers/regulator/starfive-jh7110-regulator.c
-@@ -0,0 +1,126 @@
-+// SPDX-License-Identifier: GPL-2.0
-+/*
-+ * Copyright (c) 2022 Starfive Technology Co., Ltd.
-+ * Author: Mason Huo <mason.huo@starfivetech.com>
-+ */
-+
-+#include <linux/err.h>
-+#include <linux/gpio.h>
-+#include <linux/i2c.h>
-+#include <linux/init.h>
-+#include <linux/interrupt.h>
-+#include <linux/module.h>
-+#include <linux/regmap.h>
-+#include <linux/regulator/driver.h>
-+#include <linux/regulator/machine.h>
-+#include <linux/regulator/of_regulator.h>
-+#include <linux/regulator/jh7110.h>
-+#include <linux/slab.h>
-+
-+#define JH7110_PM_POWER_SW_0          0x80
-+#define JH7110_PM_POWER_SW_1          0x81
-+#define ENABLE_MASK(id)                       BIT(id)
-+
-+
-+static const struct regmap_config jh7110_regmap_config = {
-+      .reg_bits = 8,
-+      .val_bits = 8,
-+      .max_register = JH7110_PM_POWER_SW_1,
-+      .cache_type = REGCACHE_FLAT,
-+};
-+
-+static const struct regulator_ops jh7110_ldo_ops = {
-+      .enable = regulator_enable_regmap,
-+      .disable = regulator_disable_regmap,
-+      .is_enabled = regulator_is_enabled_regmap,
-+};
-+
-+#define JH7110_LDO(_id, _name, en_reg, en_mask) \
-+{\
-+      .name = (_name),\
-+      .ops = &jh7110_ldo_ops,\
-+      .of_match = of_match_ptr(_name),\
-+      .regulators_node = of_match_ptr("regulators"),\
-+      .type = REGULATOR_VOLTAGE,\
-+      .id = JH7110_ID_##_id,\
-+      .owner = THIS_MODULE,\
-+      .enable_reg = JH7110_PM_POWER_SW_##en_reg,\
-+      .enable_mask = ENABLE_MASK(en_mask),\
-+}
-+
-+static const struct regulator_desc jh7110_regulators[] = {
-+      JH7110_LDO(LDO_REG1, "hdmi_1p8", 0, 0),
-+      JH7110_LDO(LDO_REG2, "mipitx_1p8", 0, 1),
-+      JH7110_LDO(LDO_REG3, "mipirx_1p8", 0, 2),
-+      JH7110_LDO(LDO_REG4, "hdmi_0p9", 0, 3),
-+      JH7110_LDO(LDO_REG5, "mipitx_0p9", 0, 4),
-+      JH7110_LDO(LDO_REG6, "mipirx_0p9", 0, 5),
-+      JH7110_LDO(LDO_REG7, "sdio_vdd", 1, 0),
-+};
-+
-+static int jh7110_i2c_probe(struct i2c_client *i2c)
-+{
-+      struct regulator_config config = { };
-+      struct regulator_dev *rdev;
-+      struct regulator_init_data *init_data;
-+      struct regmap *regmap;
-+      int i, ret;
-+
-+      regmap = devm_regmap_init_i2c(i2c, &jh7110_regmap_config);
-+      if (IS_ERR(regmap)) {
-+              ret = PTR_ERR(regmap);
-+              dev_err(&i2c->dev, "Failed to allocate register map: %d\n",
-+                      ret);
-+              return ret;
-+      }
-+
-+      init_data = of_get_regulator_init_data(&i2c->dev, i2c->dev.of_node, NULL);
-+      if (!init_data)
-+              return -ENOMEM;
-+      config.init_data = init_data;
-+
-+      for (i = 0; i < JH7110_MAX_REGULATORS; i++) {
-+              config.dev = &i2c->dev;
-+              config.regmap = regmap;
-+
-+              rdev = devm_regulator_register(&i2c->dev,
-+                      &jh7110_regulators[i], &config);
-+              if (IS_ERR(rdev)) {
-+                      dev_err(&i2c->dev,
-+                              "Failed to register JH7110 regulator\n");
-+                      return PTR_ERR(rdev);
-+              }
-+      }
-+
-+      return 0;
-+}
-+
-+static const struct i2c_device_id jh7110_i2c_id[] = {
-+      {"jh7110_evb_reg", 0},
-+      {},
-+};
-+MODULE_DEVICE_TABLE(i2c, jh7110_i2c_id);
-+
-+#ifdef CONFIG_OF
-+static const struct of_device_id jh7110_dt_ids[] = {
-+      { .compatible = "starfive,jh7110-evb-regulator",
-+        .data = &jh7110_i2c_id[0] },
-+      {},
-+};
-+MODULE_DEVICE_TABLE(of, jh7110_dt_ids);
-+#endif
-+
-+static struct i2c_driver jh7110_regulator_driver = {
-+      .driver = {
-+              .name = "jh7110-evb-regulator",
-+              .of_match_table = of_match_ptr(jh7110_dt_ids),
-+      },
-+      .probe = jh7110_i2c_probe,
-+      .id_table = jh7110_i2c_id,
-+};
-+
-+module_i2c_driver(jh7110_regulator_driver);
-+
-+MODULE_AUTHOR("Mason Huo <mason.huo@starfivetech.com>");
-+MODULE_DESCRIPTION("Regulator device driver for Starfive JH7110");
-+MODULE_LICENSE("GPL v2");
---- /dev/null
-+++ b/include/linux/regulator/jh7110.h
-@@ -0,0 +1,24 @@
-+/* SPDX-License-Identifier: GPL-2.0-only */
-+/*
-+ * Copyright (c) 2022 Starfive Technology Co., Ltd.
-+ * Author: Mason Huo <mason.huo@starfivetech.com>
-+ */
-+
-+#ifndef __LINUX_REGULATOR_JH7110_H
-+#define __LINUX_REGULATOR_JH7110_H
-+
-+#define JH7110_MAX_REGULATORS 7
-+
-+
-+enum jh7110_reg_id {
-+      JH7110_ID_LDO_REG1 = 0,
-+      JH7110_ID_LDO_REG2,
-+      JH7110_ID_LDO_REG3,
-+      JH7110_ID_LDO_REG4,
-+      JH7110_ID_LDO_REG5,
-+      JH7110_ID_LDO_REG6,
-+      JH7110_ID_LDO_REG7,
-+};
-+
-+
-+#endif /* __LINUX_REGULATOR_JH7110_H */
diff --git a/target/linux/starfive/patches-6.6/0072-drivers-nvme-Add-precheck-and-delay-for-CQE-pending-.patch b/target/linux/starfive/patches-6.6/0072-drivers-nvme-Add-precheck-and-delay-for-CQE-pending-.patch
deleted file mode 100644 (file)
index 7b768a9..0000000
+++ /dev/null
@@ -1,40 +0,0 @@
-From f0b4cffe4d1813305f783d208f260747ecc56c50 Mon Sep 17 00:00:00 2001
-From: "Kevin.xie" <kevin.xie@starfivetech.com>
-Date: Thu, 24 Nov 2022 16:59:12 +0800
-Subject: [PATCH 072/116] drivers: nvme: Add precheck and delay for CQE pending
- status.
-
-To workaroud the NVMe I/O timeout problem in bootup S10udev case
-which caused by the CQE update lantancy.
-
-Signed-off-by: Kevin.xie <kevin.xie@starfivetech.com>
----
- drivers/nvme/host/pci.c | 10 ++++++++++
- 1 file changed, 10 insertions(+)
-
---- a/drivers/nvme/host/pci.c
-+++ b/drivers/nvme/host/pci.c
-@@ -28,6 +28,7 @@
- #include <linux/io-64-nonatomic-hi-lo.h>
- #include <linux/sed-opal.h>
- #include <linux/pci-p2pdma.h>
-+#include <linux/delay.h>
- #include "trace.h"
- #include "nvme.h"
-@@ -1058,6 +1059,15 @@ static inline int nvme_poll_cq(struct nv
- {
-       int found = 0;
-+      /*
-+       * In some cases, such as udev trigger, cqe status may update
-+       * a little bit later than MSI, which cause an irq handle missing.
-+       * To workaound, here we will prefetch the status first, and wait
-+       * 1us if we get nothing.
-+       */
-+      if (!nvme_cqe_pending(nvmeq))
-+              udelay(1);
-+
-       while (nvme_cqe_pending(nvmeq)) {
-               found++;
-               /*
diff --git a/target/linux/starfive/patches-6.6/0073-RISC-V-Create-unique-identification-for-SoC-PMU.patch b/target/linux/starfive/patches-6.6/0073-RISC-V-Create-unique-identification-for-SoC-PMU.patch
deleted file mode 100644 (file)
index fff01c4..0000000
+++ /dev/null
@@ -1,93 +0,0 @@
-From eb294df4b9fab46bc5dbf676edf51e28e06d1968 Mon Sep 17 00:00:00 2001
-From: =?UTF-8?q?Jo=C3=A3o=20M=C3=A1rio=20Domingos?=
- <joao.mario@tecnico.ulisboa.pt>
-Date: Tue, 16 Nov 2021 15:48:09 +0000
-Subject: [PATCH 073/116] RISC-V: Create unique identification for SoC PMU
-MIME-Version: 1.0
-Content-Type: text/plain; charset=UTF-8
-Content-Transfer-Encoding: 8bit
-
-The SBI PMU platform driver did not provide any identification for
-perf events matching. This patch introduces a new sysfs file inside the
-platform device (soc:pmu/id) for pmu identification.
-
-The identification is a 64-bit value generated as:
-[63-32]: mvendorid;
-[31]: marchid[MSB];
-[30-16]: marchid[15-0];
-[15-0]: mimpid[15MSBs];
-
-The CSRs are detailed in the RISC-V privileged spec [1].
-The marchid is split in MSB + 15LSBs, due to the MSB being used for
-open-source architecture identification.
-
-[1] https://github.com/riscv/riscv-isa-manual
-
-Signed-off-by: João Mário Domingos <joao.mario@tecnico.ulisboa.pt>
----
- drivers/perf/riscv_pmu_sbi.c | 47 ++++++++++++++++++++++++++++++++++++
- 1 file changed, 47 insertions(+)
-
---- a/drivers/perf/riscv_pmu_sbi.c
-+++ b/drivers/perf/riscv_pmu_sbi.c
-@@ -1019,6 +1019,46 @@ static struct ctl_table sbi_pmu_sysctl_t
-       { }
- };
-+static uint64_t pmu_sbi_get_pmu_id(void)
-+{
-+      union sbi_pmu_id {
-+              uint64_t value;
-+              struct {
-+                      uint16_t imp:16;
-+                      uint16_t arch:16;
-+                      uint32_t vendor:32;
-+              };
-+      } pmuid;
-+
-+      pmuid.value = 0;
-+      pmuid.vendor = (uint32_t) sbi_get_mvendorid();
-+      pmuid.arch = (sbi_get_marchid() >> (63 - 15) & (1 << 15)) | (sbi_get_marchid() & 0x7FFF);
-+      pmuid.imp = (sbi_get_mimpid() >> 16);
-+
-+      return pmuid.value;
-+}
-+
-+static ssize_t pmu_sbi_id_show(struct device *dev,
-+              struct device_attribute *attr, char *buf)
-+{
-+      int len;
-+
-+      len = sprintf(buf, "0x%llx\n", pmu_sbi_get_pmu_id());
-+      if (len <= 0)
-+              dev_err(dev, "mydrv: Invalid sprintf len: %dn", len);
-+
-+      return len;
-+}
-+
-+static DEVICE_ATTR(id, S_IRUGO | S_IWUSR, pmu_sbi_id_show, 0);
-+
-+static struct attribute *pmu_sbi_attrs[] = {
-+      &dev_attr_id.attr,
-+      NULL
-+};
-+
-+ATTRIBUTE_GROUPS(pmu_sbi);
-+
- static int pmu_sbi_device_probe(struct platform_device *pdev)
- {
-       struct riscv_pmu *pmu = NULL;
-@@ -1067,6 +1107,13 @@ static int pmu_sbi_device_probe(struct p
-       pmu->event_unmapped = pmu_sbi_event_unmapped;
-       pmu->csr_index = pmu_sbi_csr_index;
-+      ret = sysfs_create_group(&pdev->dev.kobj, &pmu_sbi_group);
-+      if (ret) {
-+              dev_err(&pdev->dev, "sysfs creation failed\n");
-+              return ret;
-+      }
-+      pdev->dev.groups = pmu_sbi_groups;
-+
-       ret = cpuhp_state_add_instance(CPUHP_AP_PERF_RISCV_STARTING, &pmu->node);
-       if (ret)
-               return ret;
diff --git a/target/linux/starfive/patches-6.6/0074-RISC-V-Support-CPUID-for-risc-v-in-perf.patch b/target/linux/starfive/patches-6.6/0074-RISC-V-Support-CPUID-for-risc-v-in-perf.patch
deleted file mode 100644 (file)
index 177b3b3..0000000
+++ /dev/null
@@ -1,55 +0,0 @@
-From 1dc069ffadf4ce7817a716f9df2f480254e9b01d Mon Sep 17 00:00:00 2001
-From: =?UTF-8?q?Jo=C3=A3o=20M=C3=A1rio=20Domingos?=
- <joao.mario@tecnico.ulisboa.pt>
-Date: Tue, 16 Nov 2021 15:48:10 +0000
-Subject: [PATCH 074/116] RISC-V: Support CPUID for risc-v in perf
-MIME-Version: 1.0
-Content-Type: text/plain; charset=UTF-8
-Content-Transfer-Encoding: 8bit
-
-This patch creates the header.c file for the risc-v architecture and introduces support for
-PMU identification through sysfs.
-It is now possible to configure pmu-events in risc-v.
-
-Depends on patch [1], that introduces the id sysfs file.
-
-Signed-off-by: João Mário Domingos <joao.mario@tecnico.ulisboa.pt>
-Signed-off-by: minda.chen <minda.chen@starfivetech.com>
----
- drivers/perf/riscv_pmu.c | 18 ++++++++++++++++++
- 1 file changed, 18 insertions(+)
-
---- a/drivers/perf/riscv_pmu.c
-+++ b/drivers/perf/riscv_pmu.c
-@@ -18,6 +18,23 @@
- #include <asm/sbi.h>
-+PMU_FORMAT_ATTR(event, "config:0-63");
-+
-+static struct attribute *riscv_arch_formats_attr[] = {
-+      &format_attr_event.attr,
-+      NULL,
-+};
-+
-+static struct attribute_group riscv_pmu_format_group = {
-+      .name = "format",
-+      .attrs = riscv_arch_formats_attr,
-+};
-+
-+static const struct attribute_group *riscv_pmu_attr_groups[] = {
-+      &riscv_pmu_format_group,
-+      NULL,
-+};
-+
- static bool riscv_perf_user_access(struct perf_event *event)
- {
-       return ((event->attr.type == PERF_TYPE_HARDWARE) ||
-@@ -410,6 +427,7 @@ struct riscv_pmu *riscv_pmu_alloc(void)
-                       cpuc->events[i] = NULL;
-       }
-       pmu->pmu = (struct pmu) {
-+              .attr_groups    = riscv_pmu_attr_groups,
-               .event_init     = riscv_pmu_event_init,
-               .event_mapped   = riscv_pmu_event_mapped,
-               .event_unmapped = riscv_pmu_event_unmapped,
diff --git a/target/linux/starfive/patches-6.6/0075-RISC-V-Added-generic-pmu-events-mapfile.patch b/target/linux/starfive/patches-6.6/0075-RISC-V-Added-generic-pmu-events-mapfile.patch
deleted file mode 100644 (file)
index 01bb4f1..0000000
+++ /dev/null
@@ -1,42 +0,0 @@
-From 3e6ea12dda276c01a756764fcafa315b19860c33 Mon Sep 17 00:00:00 2001
-From: =?UTF-8?q?Jo=C3=A3o=20M=C3=A1rio=20Domingos?=
- <joao.mario@tecnico.ulisboa.pt>
-Date: Tue, 16 Nov 2021 15:48:11 +0000
-Subject: [PATCH 075/116] RISC-V: Added generic pmu-events mapfile
-MIME-Version: 1.0
-Content-Type: text/plain; charset=UTF-8
-Content-Transfer-Encoding: 8bit
-
-The pmu-events now supports custom events for RISC-V, plus the cycle,
-time and instret events were defined.
-
-Signed-off-by: João Mário Domingos <joao.mario@tecnico.ulisboa.pt>
----
- .../pmu-events/arch/riscv/riscv-generic.json  | 20 +++++++++++++++++++
- 1 file changed, 20 insertions(+)
- create mode 100644 tools/perf/pmu-events/arch/riscv/riscv-generic.json
-
---- /dev/null
-+++ b/tools/perf/pmu-events/arch/riscv/riscv-generic.json
-@@ -0,0 +1,20 @@
-+[
-+  {
-+    "PublicDescription": "CPU Cycles",
-+    "EventCode": "0x00",
-+    "EventName": "riscv_cycles",
-+    "BriefDescription": "CPU cycles RISC-V generic counter"
-+  },
-+  {
-+    "PublicDescription": "CPU Time",
-+      "EventCode": "0x01",
-+      "EventName": "riscv_time",
-+      "BriefDescription": "CPU time RISC-V generic counter"
-+  },
-+  {
-+    "PublicDescription": "CPU Instructions",
-+      "EventCode": "0x02",
-+      "EventName": "riscv_instret",
-+      "BriefDescription": "CPU retired instructions RISC-V generic counter"
-+  }
-+]
-\ No newline at end of file
diff --git a/target/linux/starfive/patches-6.6/0076-perf-sbi-disable-cpu-hotplug-callback.patch b/target/linux/starfive/patches-6.6/0076-perf-sbi-disable-cpu-hotplug-callback.patch
deleted file mode 100644 (file)
index 152a60c..0000000
+++ /dev/null
@@ -1,30 +0,0 @@
-From 30e0cdcf9e05faa65ecde4ed8b70039568fdb660 Mon Sep 17 00:00:00 2001
-From: Minda Chen <minda.chen@starfivetech.com>
-Date: Thu, 2 Mar 2023 17:16:01 +0800
-Subject: [PATCH 076/116] perf: sbi: disable cpu hotplug callback.
-
-register cpu hotplug callback will cause dhrystone
-and coremark benchmark reduce the scores. this CPU
-hotplug ops will do in sbi cpu/on and off. So disable
-this no side effect.
-
-Signed-off-by: Minda Chen <minda.chen@starfivetech.com>
-Signed-off-by: Hal Feng <hal.feng@starfivetech.com>
----
- drivers/perf/riscv_pmu_sbi.c | 2 ++
- 1 file changed, 2 insertions(+)
-
---- a/drivers/perf/riscv_pmu_sbi.c
-+++ b/drivers/perf/riscv_pmu_sbi.c
-@@ -1114,9 +1114,11 @@ static int pmu_sbi_device_probe(struct p
-       }
-       pdev->dev.groups = pmu_sbi_groups;
-+#ifndef CONFIG_ARCH_STARFIVE
-       ret = cpuhp_state_add_instance(CPUHP_AP_PERF_RISCV_STARTING, &pmu->node);
-       if (ret)
-               return ret;
-+#endif
-       ret = riscv_pm_pmu_register(pmu);
-       if (ret)
diff --git a/target/linux/starfive/patches-6.6/0077-dmaengine-dw-axi-dmac-Drop-unused-print-message.patch b/target/linux/starfive/patches-6.6/0077-dmaengine-dw-axi-dmac-Drop-unused-print-message.patch
deleted file mode 100644 (file)
index cdc6e4e..0000000
+++ /dev/null
@@ -1,24 +0,0 @@
-From fc4b5c7c27e1b56b1f848e50511c4fd081b1b6c5 Mon Sep 17 00:00:00 2001
-From: Walker Chen <walker.chen@starfivetech.com>
-Date: Mon, 12 Jun 2023 21:21:45 +0800
-Subject: [PATCH 077/116] dmaengine: dw-axi-dmac: Drop unused print message
-
-Removed printing information which is not related to StarFive
-platform.
-
-Signed-off-by: Walker Chen <walker.chen@starfivetech.com>
----
- drivers/dma/dw-axi-dmac/dw-axi-dmac-platform.c | 2 +-
- 1 file changed, 1 insertion(+), 1 deletion(-)
-
---- a/drivers/dma/dw-axi-dmac/dw-axi-dmac-platform.c
-+++ b/drivers/dma/dw-axi-dmac/dw-axi-dmac-platform.c
-@@ -523,7 +523,7 @@ static void dw_axi_dma_set_hw_channel(st
-       unsigned long reg_value, val;
-       if (!chip->apb_regs) {
--              dev_err(chip->dev, "apb_regs not initialized\n");
-+              dev_dbg(chip->dev, "apb_regs not initialized\n");
-               return;
-       }
diff --git a/target/linux/starfive/patches-6.6/0079-ASoC-codecs-Add-AC108-Codec-driver.patch b/target/linux/starfive/patches-6.6/0079-ASoC-codecs-Add-AC108-Codec-driver.patch
deleted file mode 100644 (file)
index 2a82897..0000000
+++ /dev/null
@@ -1,4748 +0,0 @@
-From cd2254c6be9441ebacaa35693ecb5ce116b90622 Mon Sep 17 00:00:00 2001
-From: Xingyu Wu <xingyu.wu@starfivetech.com>
-Date: Fri, 16 Jun 2023 16:27:46 +0800
-Subject: [PATCH 079/116] ASoC: codecs: Add AC108 Codec driver
-
-Add AC108 Codec driver and AC101 driver for AC10x.
-
-Signed-off-by: Xingyu Wu <xingyu.wu@starfivetech.com>
-Signed-off-by: Hal Feng <hal.feng@starfivetech.com>
----
- sound/soc/codecs/Kconfig      |    5 +
- sound/soc/codecs/Makefile     |    2 +
- sound/soc/codecs/ac101.c      | 1716 +++++++++++++++++++++++++++++++++
- sound/soc/codecs/ac101_regs.h |  431 +++++++++
- sound/soc/codecs/ac108.c      | 1622 +++++++++++++++++++++++++++++++
- sound/soc/codecs/ac108.h      |  749 ++++++++++++++
- sound/soc/codecs/ac10x.h      |  152 +++
- 7 files changed, 4677 insertions(+)
- create mode 100644 sound/soc/codecs/ac101.c
- create mode 100644 sound/soc/codecs/ac101_regs.h
- create mode 100644 sound/soc/codecs/ac108.c
- create mode 100644 sound/soc/codecs/ac108.h
- create mode 100644 sound/soc/codecs/ac10x.h
-
---- a/sound/soc/codecs/Kconfig
-+++ b/sound/soc/codecs/Kconfig
-@@ -16,6 +16,7 @@ config SND_SOC_ALL_CODECS
-       depends on COMPILE_TEST
-       imply SND_SOC_88PM860X
-       imply SND_SOC_AB8500_CODEC
-+      imply SND_SOC_AC108
-       imply SND_SOC_AC97_CODEC
-       imply SND_SOC_AD1836
-       imply SND_SOC_AD193X_SPI
-@@ -397,6 +398,10 @@ config SND_SOC_AB8500_CODEC
-       tristate
-       depends on ABX500_CORE
-+config SND_SOC_AC108
-+      tristate "AC108"
-+      depends on I2C
-+
- config SND_SOC_AC97_CODEC
-       tristate "Build generic ASoC AC97 CODEC driver"
-       select SND_AC97_CODEC
---- a/sound/soc/codecs/Makefile
-+++ b/sound/soc/codecs/Makefile
-@@ -2,6 +2,7 @@
- snd-soc-88pm860x-objs := 88pm860x-codec.o
- snd-soc-ab8500-codec-objs := ab8500-codec.o
- snd-soc-ac97-objs := ac97.o
-+snd-soc-ac108-objs := ac108.o ac101.o
- snd-soc-ad1836-objs := ad1836.o
- snd-soc-ad193x-objs := ad193x.o
- snd-soc-ad193x-spi-objs := ad193x-spi.o
-@@ -386,6 +387,7 @@ snd-soc-simple-mux-objs := simple-mux.o
- obj-$(CONFIG_SND_SOC_88PM860X)        += snd-soc-88pm860x.o
- obj-$(CONFIG_SND_SOC_AB8500_CODEC)    += snd-soc-ab8500-codec.o
-+obj-$(CONFIG_SND_SOC_AC108)           += snd-soc-ac108.o
- obj-$(CONFIG_SND_SOC_AC97_CODEC)      += snd-soc-ac97.o
- obj-$(CONFIG_SND_SOC_AD1836)  += snd-soc-ad1836.o
- obj-$(CONFIG_SND_SOC_AD193X)  += snd-soc-ad193x.o
---- /dev/null
-+++ b/sound/soc/codecs/ac101.c
-@@ -0,0 +1,1716 @@
-+/*
-+ * ac101.c
-+ *
-+ * (C) Copyright 2017-2018
-+ * Seeed Technology Co., Ltd. <www.seeedstudio.com>
-+ *
-+ * PeterYang <linsheng.yang@seeed.cc>
-+ *
-+ * (C) Copyright 2014-2017
-+ * Reuuimlla Technology Co., Ltd. <www.reuuimllatech.com>
-+ *
-+ * huangxin <huangxin@Reuuimllatech.com>
-+ * liushaohua <liushaohua@allwinnertech.com>
-+ *
-+ * X-Powers AC101 codec driver
-+ *
-+ * This program is free software; you can redistribute it and/or
-+ * modify it under the terms of the GNU General Public License as
-+ * published by the Free Software Foundation; either version 2 of
-+ * the License, or (at your option) any later version.
-+ *
-+ */
-+
-+#include <linux/clk.h>
-+#include <linux/delay.h>
-+#include <linux/gpio/consumer.h>
-+#include <linux/i2c.h>
-+#include <linux/input.h>
-+#include <linux/irq.h>
-+#include <linux/module.h>
-+#include <linux/regmap.h>
-+#include <sound/tlv.h>
-+#include <linux/workqueue.h>
-+#include <sound/pcm.h>
-+#include <sound/pcm_params.h>
-+#include <sound/soc.h>
-+#include <sound/soc-dapm.h>
-+
-+#include "ac101_regs.h"
-+#include "ac10x.h"
-+
-+/* #undef AC101_DEBG
-+ * use 'make DEBUG=1' to enable debugging
-+ */
-+
-+/*
-+ * *** To sync channels ***
-+ *
-+ * 1. disable clock in codec   hw_params()
-+ * 2. clear   fifo  in bcm2835 hw_params()
-+ * 3. clear   fifo  in bcm2385 prepare()
-+ * 4. enable  RX    in bcm2835 trigger()
-+ * 5. enable  clock in machine trigger()
-+ */
-+
-+/*Default initialize configuration*/
-+static bool speaker_double_used = 1;
-+static int double_speaker_val = 0x1B;
-+static int single_speaker_val = 0x19;
-+static int headset_val                = 0x3B;
-+static int mainmic_val                = 0x4;
-+static int headsetmic_val     = 0x4;
-+static bool dmic_used         = 0;
-+static int adc_digital_val    = 0xb0b0;
-+static bool drc_used          = false;
-+
-+#define AC101_RATES  (SNDRV_PCM_RATE_8000_96000 &             \
-+              ~(SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_64000 | \
-+              SNDRV_PCM_RATE_88200))
-+#define AC101_FORMATS (/*SNDRV_PCM_FMTBIT_S16_LE | \
-+                      SNDRV_PCM_FMTBIT_S24_LE |*/     \
-+                      SNDRV_PCM_FMTBIT_S32_LE | \
-+                      0)
-+
-+static struct ac10x_priv* static_ac10x;
-+
-+
-+int ac101_read(struct snd_soc_codec *codec, unsigned reg) {
-+      struct ac10x_priv *ac10x = snd_soc_codec_get_drvdata(codec);
-+      int r, v = 0;
-+
-+      if ((r = regmap_read(ac10x->regmap101, reg, &v)) < 0) {
-+              dev_err(codec->dev, "read reg %02X fail\n",
-+                       reg);
-+              return r;
-+      }
-+      return v;
-+}
-+
-+int ac101_write(struct snd_soc_codec *codec, unsigned reg, unsigned val) {
-+      struct ac10x_priv *ac10x = snd_soc_codec_get_drvdata(codec);
-+      int v;
-+
-+      v = regmap_write(ac10x->regmap101, reg, val);
-+      return v;
-+}
-+
-+int ac101_update_bits(struct snd_soc_codec *codec, unsigned reg,
-+                      unsigned mask, unsigned value
-+) {
-+      struct ac10x_priv *ac10x = snd_soc_codec_get_drvdata(codec);
-+      int v;
-+
-+      v = regmap_update_bits(ac10x->regmap101, reg, mask, value);
-+      return v;
-+}
-+
-+
-+
-+#ifdef CONFIG_AC101_SWITCH_DETECT
-+/******************************************************************************/
-+/********************************switch****************************************/
-+/******************************************************************************/
-+#define KEY_HEADSETHOOK         226           /* key define */
-+#define HEADSET_FILTER_CNT    (10)
-+
-+/*
-+ * switch_hw_config:config the 53 codec register
-+ */
-+static void switch_hw_config(struct snd_soc_codec *codec)
-+{
-+      int r;
-+
-+      AC101_DBG();
-+
-+      /*HMIC/MMIC BIAS voltage level select:2.5v*/
-+      ac101_update_bits(codec, OMIXER_BST1_CTRL, (0xf<<BIASVOLTAGE), (0xf<<BIASVOLTAGE));
-+      /*debounce when Key down or keyup*/
-+      ac101_update_bits(codec, HMIC_CTRL1, (0xf<<HMIC_M), (0x0<<HMIC_M));
-+      /*debounce when earphone plugin or pullout*/
-+      ac101_update_bits(codec, HMIC_CTRL1, (0xf<<HMIC_N), (0x0<<HMIC_N));
-+      /*Down Sample Setting Select: Downby 4,32Hz*/
-+      ac101_update_bits(codec, HMIC_CTRL2, (0x3<<HMIC_SAMPLE_SELECT),
-+                        (0x02<<HMIC_SAMPLE_SELECT));
-+      /*Hmic_th2 for detecting Keydown or Keyup.*/
-+      ac101_update_bits(codec, HMIC_CTRL2, (0x1f<<HMIC_TH2), (0x8<<HMIC_TH2));
-+      /*Hmic_th1[4:0],detecting eraphone plugin or pullout*/
-+      ac101_update_bits(codec, HMIC_CTRL2, (0x1f<<HMIC_TH1), (0x1<<HMIC_TH1));
-+      /*Headset microphone BIAS working mode: when HBIASEN = 1 */
-+      ac101_update_bits(codec, ADC_APC_CTRL, (0x1<<HBIASMOD), (0x1<<HBIASMOD));
-+      /*Headset microphone BIAS Enable*/
-+      ac101_update_bits(codec, ADC_APC_CTRL, (0x1<<HBIASEN), (0x1<<HBIASEN));
-+      /*Headset microphone BIAS Current sensor & ADC Enable*/
-+      ac101_update_bits(codec, ADC_APC_CTRL, (0x1<<HBIASADCEN), (0x1<<HBIASADCEN));
-+      /*Earphone Plugin/out Irq Enable*/
-+      ac101_update_bits(codec, HMIC_CTRL1, (0x1<<HMIC_PULLOUT_IRQ), (0x1<<HMIC_PULLOUT_IRQ));
-+      ac101_update_bits(codec, HMIC_CTRL1, (0x1<<HMIC_PLUGIN_IRQ), (0x1<<HMIC_PLUGIN_IRQ));
-+
-+      /*Hmic KeyUp/key down Irq Enable*/
-+      ac101_update_bits(codec, HMIC_CTRL1, (0x1<<HMIC_KEYDOWN_IRQ), (0x1<<HMIC_KEYDOWN_IRQ));
-+      ac101_update_bits(codec, HMIC_CTRL1, (0x1<<HMIC_KEYUP_IRQ), (0x1<<HMIC_KEYUP_IRQ));
-+
-+      /*headphone calibration clock frequency select*/
-+      ac101_update_bits(codec, SPKOUT_CTRL, (0x7<<HPCALICKS), (0x7<<HPCALICKS));
-+
-+      /*clear hmic interrupt */
-+      r = HMIC_PEND_ALL;
-+      ac101_write(codec, HMIC_STS, r);
-+
-+      return;
-+}
-+
-+/*
-+ * switch_status_update: update the switch state.
-+ */
-+static void switch_status_update(struct ac10x_priv *ac10x)
-+{
-+      AC101_DBG("ac10x->state:%d\n", ac10x->state);
-+
-+    input_report_switch(ac10x->inpdev, SW_HEADPHONE_INSERT, ac10x->state);
-+    input_sync(ac10x->inpdev);
-+    return;
-+}
-+
-+/*
-+ * work_cb_clear_irq: clear audiocodec pending and Record the interrupt.
-+ */
-+static void work_cb_clear_irq(struct work_struct *work)
-+{
-+      int reg_val = 0;
-+      struct ac10x_priv *ac10x = container_of(work, struct ac10x_priv, work_clear_irq);
-+      struct snd_soc_codec *codec = ac10x->codec;
-+
-+      ac10x->irq_cntr++;
-+
-+      reg_val = ac101_read(codec, HMIC_STS);
-+      if (BIT(HMIC_PULLOUT_PEND) & reg_val) {
-+              ac10x->pullout_cntr++;
-+              AC101_DBG("ac10x->pullout_cntr: %d\n", ac10x->pullout_cntr);
-+      }
-+
-+      reg_val |= HMIC_PEND_ALL;
-+      ac101_write(codec, HMIC_STS, reg_val);
-+
-+      reg_val = ac101_read(codec, HMIC_STS);
-+      if ((reg_val & HMIC_PEND_ALL) != 0){
-+              reg_val |= HMIC_PEND_ALL;
-+              ac101_write(codec, HMIC_STS, reg_val);
-+      }
-+
-+      if (cancel_work_sync(&ac10x->work_switch) != 0) {
-+              ac10x->irq_cntr--;
-+      }
-+
-+      if (0 == schedule_work(&ac10x->work_switch)) {
-+              ac10x->irq_cntr--;
-+              AC101_DBG("[work_cb_clear_irq] add work struct failed!\n");
-+      }
-+}
-+
-+enum {
-+      HBIAS_LEVEL_1 = 0x02,
-+      HBIAS_LEVEL_2 = 0x0B,
-+      HBIAS_LEVEL_3 = 0x13,
-+      HBIAS_LEVEL_4 = 0x17,
-+      HBIAS_LEVEL_5 = 0x19,
-+};
-+
-+static int __ac101_get_hmic_data(struct snd_soc_codec *codec) {
-+      #ifdef AC101_DEBG
-+      static long counter;
-+      #endif
-+      int r, d;
-+
-+      d = GET_HMIC_DATA(ac101_read(codec, HMIC_STS));
-+
-+      r = 0x1 << HMIC_DATA_PEND;
-+      ac101_write(codec, HMIC_STS, r);
-+
-+      /* prevent i2c accessing too frequently */
-+      usleep_range(1500, 3000);
-+
-+      AC101_DBG("HMIC_DATA(%3ld): %02X\n", counter++, d);
-+      return d;
-+}
-+
-+/*
-+ * work_cb_earphone_switch: judge the status of the headphone
-+ */
-+static void work_cb_earphone_switch(struct work_struct *work)
-+{
-+      struct ac10x_priv *ac10x = container_of(work, struct ac10x_priv, work_switch);
-+      struct snd_soc_codec *codec = ac10x->codec;
-+
-+      static int hook_flag1 = 0, hook_flag2 = 0;
-+      static int KEY_VOLUME_FLAG = 0;
-+
-+      unsigned filter_buf = 0;
-+      int filt_index = 0;
-+      int t = 0;
-+
-+      ac10x->irq_cntr--;
-+
-+      /* read HMIC_DATA */
-+      t = __ac101_get_hmic_data(codec);
-+
-+      if ((t >= HBIAS_LEVEL_2) && (ac10x->mode == FOUR_HEADPHONE_PLUGIN)) {
-+              t = __ac101_get_hmic_data(codec);
-+
-+              if (t >= HBIAS_LEVEL_5){
-+                      msleep(150);
-+                      t = __ac101_get_hmic_data(codec);
-+                      if (((t < HBIAS_LEVEL_2 && t >= HBIAS_LEVEL_1 - 1) || t >= HBIAS_LEVEL_5)
-+                      && (ac10x->pullout_cntr == 0)) {
-+                              input_report_key(ac10x->inpdev, KEY_HEADSETHOOK, 1);
-+                              input_sync(ac10x->inpdev);
-+
-+                              AC101_DBG("KEY_HEADSETHOOK1\n");
-+
-+                              if (hook_flag1 != hook_flag2)
-+                                      hook_flag1 = hook_flag2 = 0;
-+                              hook_flag1++;
-+                      }
-+                      if (ac10x->pullout_cntr)
-+                              ac10x->pullout_cntr--;
-+              } else if (t >= HBIAS_LEVEL_4) {
-+                      msleep(80);
-+                      t = __ac101_get_hmic_data(codec);
-+                      if (t < HBIAS_LEVEL_5 && t >= HBIAS_LEVEL_4 && (ac10x->pullout_cntr == 0)) {
-+                              KEY_VOLUME_FLAG = 1;
-+                              input_report_key(ac10x->inpdev, KEY_VOLUMEUP, 1);
-+                              input_sync(ac10x->inpdev);
-+                              input_report_key(ac10x->inpdev, KEY_VOLUMEUP, 0);
-+                              input_sync(ac10x->inpdev);
-+
-+                              AC101_DBG("HMIC_DATA: %d KEY_VOLUMEUP\n", t);
-+                      }
-+                      if (ac10x->pullout_cntr)
-+                              ac10x->pullout_cntr--;
-+              } else if (t >= HBIAS_LEVEL_3){
-+                      msleep(80);
-+                      t = __ac101_get_hmic_data(codec);
-+                      if (t < HBIAS_LEVEL_4 && t >= HBIAS_LEVEL_3 && (ac10x->pullout_cntr == 0)) {
-+                              KEY_VOLUME_FLAG = 1;
-+                              input_report_key(ac10x->inpdev, KEY_VOLUMEDOWN, 1);
-+                              input_sync(ac10x->inpdev);
-+                              input_report_key(ac10x->inpdev, KEY_VOLUMEDOWN, 0);
-+                              input_sync(ac10x->inpdev);
-+                              AC101_DBG("KEY_VOLUMEDOWN\n");
-+                      }
-+                      if (ac10x->pullout_cntr)
-+                              ac10x->pullout_cntr--;
-+              }
-+      } else if ((t < HBIAS_LEVEL_2 && t >= HBIAS_LEVEL_1) &&
-+                 (ac10x->mode == FOUR_HEADPHONE_PLUGIN)) {
-+              t = __ac101_get_hmic_data(codec);
-+              if (t < HBIAS_LEVEL_2 && t >= HBIAS_LEVEL_1) {
-+                      if (KEY_VOLUME_FLAG) {
-+                              KEY_VOLUME_FLAG = 0;
-+                      }
-+                      if (hook_flag1 == (++hook_flag2)) {
-+                              hook_flag1 = hook_flag2 = 0;
-+                              input_report_key(ac10x->inpdev, KEY_HEADSETHOOK, 0);
-+                              input_sync(ac10x->inpdev);
-+
-+                              AC101_DBG("KEY_HEADSETHOOK0\n");
-+                      }
-+              }
-+      } else {
-+              while (ac10x->irq_cntr == 0 && ac10x->irq != 0) {
-+                      msleep(20);
-+
-+                      t = __ac101_get_hmic_data(codec);
-+
-+                      if (filt_index <= HEADSET_FILTER_CNT) {
-+                              if (filt_index++ == 0) {
-+                                      filter_buf = t;
-+                              } else if (filter_buf != t) {
-+                                      filt_index = 0;
-+                              }
-+                              continue;
-+                      }
-+
-+                      filt_index = 0;
-+                      if (filter_buf >= HBIAS_LEVEL_2) {
-+                              ac10x->mode = THREE_HEADPHONE_PLUGIN;
-+                              ac10x->state = 2;
-+                      } else if (filter_buf >= HBIAS_LEVEL_1 - 1) {
-+                              ac10x->mode = FOUR_HEADPHONE_PLUGIN;
-+                              ac10x->state = 1;
-+                      } else {
-+                              ac10x->mode = HEADPHONE_IDLE;
-+                              ac10x->state = 0;
-+                      }
-+                      switch_status_update(ac10x);
-+                      ac10x->pullout_cntr = 0;
-+                      break;
-+              }
-+      }
-+}
-+
-+/*
-+ * audio_hmic_irq:  the interrupt handlers
-+ */
-+static irqreturn_t audio_hmic_irq(int irq, void *para)
-+{
-+      struct ac10x_priv *ac10x = (struct ac10x_priv *)para;
-+      if (ac10x == NULL) {
-+              return -EINVAL;
-+      }
-+
-+      if (0 == schedule_work(&ac10x->work_clear_irq)){
-+              AC101_DBG("[audio_hmic_irq] work already in queue_codec_irq, adding failed!\n");
-+      }
-+      return IRQ_HANDLED;
-+}
-+
-+static int ac101_switch_probe(struct ac10x_priv *ac10x) {
-+      struct i2c_client *i2c = ac10x->i2c101;
-+      long ret;
-+
-+      ac10x->gpiod_irq = devm_gpiod_get_optional(&i2c->dev, "switch-irq", GPIOD_IN);
-+      if (IS_ERR(ac10x->gpiod_irq)) {
-+              ac10x->gpiod_irq = NULL;
-+              dev_err(&i2c->dev, "failed get switch-irq in device tree\n");
-+              goto _err_irq;
-+      }
-+
-+      gpiod_direction_input(ac10x->gpiod_irq);
-+
-+      ac10x->irq = gpiod_to_irq(ac10x->gpiod_irq);
-+      if (IS_ERR_VALUE(ac10x->irq)) {
-+              pr_info("[ac101] map gpio to irq failed, errno = %ld\n", ac10x->irq);
-+              ac10x->irq = 0;
-+              goto _err_irq;
-+      }
-+
-+      /* request irq, set irq type to falling edge trigger */
-+      ret = devm_request_irq(ac10x->codec->dev, ac10x->irq, audio_hmic_irq,
-+                             IRQF_TRIGGER_FALLING, "SWTICH_EINT", ac10x);
-+      if (IS_ERR_VALUE(ret)) {
-+              pr_info("[ac101] request virq %ld failed, errno = %ld\n", ac10x->irq, ret);
-+              goto _err_irq;
-+      }
-+
-+      ac10x->mode = HEADPHONE_IDLE;
-+      ac10x->state = -1;
-+
-+      /*use for judge the state of switch*/
-+      INIT_WORK(&ac10x->work_switch, work_cb_earphone_switch);
-+      INIT_WORK(&ac10x->work_clear_irq, work_cb_clear_irq);
-+
-+      /********************create input device************************/
-+      ac10x->inpdev = devm_input_allocate_device(ac10x->codec->dev);
-+      if (!ac10x->inpdev) {
-+              AC101_DBG("input_allocate_device: not enough memory for input device\n");
-+              ret = -ENOMEM;
-+              goto _err_input_allocate_device;
-+      }
-+
-+      ac10x->inpdev->name          = "seed-voicecard-headset";
-+      ac10x->inpdev->phys          = dev_name(ac10x->codec->dev);
-+      ac10x->inpdev->id.bustype    = BUS_I2C;
-+      ac10x->inpdev->dev.parent    = ac10x->codec->dev;
-+      input_set_drvdata(ac10x->inpdev, ac10x->codec);
-+
-+      ac10x->inpdev->evbit[0] = BIT_MASK(EV_KEY) | BIT(EV_SW);
-+
-+      set_bit(KEY_HEADSETHOOK, ac10x->inpdev->keybit);
-+      set_bit(KEY_VOLUMEUP,    ac10x->inpdev->keybit);
-+      set_bit(KEY_VOLUMEDOWN,  ac10x->inpdev->keybit);
-+      input_set_capability(ac10x->inpdev, EV_SW, SW_HEADPHONE_INSERT);
-+
-+      ret = input_register_device(ac10x->inpdev);
-+      if (ret) {
-+              AC101_DBG("input_register_device: input_register_device failed\n");
-+              goto _err_input_register_device;
-+      }
-+
-+      /* the first headset state checking */
-+      switch_hw_config(ac10x->codec);
-+      ac10x->irq_cntr = 1;
-+      schedule_work(&ac10x->work_switch);
-+
-+      return 0;
-+
-+_err_input_register_device:
-+_err_input_allocate_device:
-+
-+      if (ac10x->irq) {
-+              devm_free_irq(&i2c->dev, ac10x->irq, ac10x);
-+              ac10x->irq = 0;
-+      }
-+_err_irq:
-+      return ret;
-+}
-+/******************************************************************************/
-+/********************************switch****************************************/
-+/******************************************************************************/
-+#endif
-+
-+
-+
-+void drc_config(struct snd_soc_codec *codec)
-+{
-+      int reg_val;
-+      reg_val = ac101_read(codec, 0xa3);
-+      reg_val &= ~(0x7ff<<0);
-+      reg_val |= 1<<0;
-+      ac101_write(codec, 0xa3, reg_val);
-+      ac101_write(codec, 0xa4, 0x2baf);
-+
-+      reg_val = ac101_read(codec, 0xa5);
-+      reg_val &= ~(0x7ff<<0);
-+      reg_val |= 1<<0;
-+      ac101_write(codec, 0xa5, reg_val);
-+      ac101_write(codec, 0xa6, 0x2baf);
-+
-+      reg_val = ac101_read(codec, 0xa7);
-+      reg_val &= ~(0x7ff<<0);
-+      ac101_write(codec, 0xa7, reg_val);
-+      ac101_write(codec, 0xa8, 0x44a);
-+
-+      reg_val = ac101_read(codec, 0xa9);
-+      reg_val &= ~(0x7ff<<0);
-+      ac101_write(codec, 0xa9, reg_val);
-+      ac101_write(codec, 0xaa, 0x1e06);
-+
-+      reg_val = ac101_read(codec, 0xab);
-+      reg_val &= ~(0x7ff<<0);
-+      reg_val |= (0x352<<0);
-+      ac101_write(codec, 0xab, reg_val);
-+      ac101_write(codec, 0xac, 0x6910);
-+
-+      reg_val = ac101_read(codec, 0xad);
-+      reg_val &= ~(0x7ff<<0);
-+      reg_val |= (0x77a<<0);
-+      ac101_write(codec, 0xad, reg_val);
-+      ac101_write(codec, 0xae, 0xaaaa);
-+
-+      reg_val = ac101_read(codec, 0xaf);
-+      reg_val &= ~(0x7ff<<0);
-+      reg_val |= (0x2de<<0);
-+      ac101_write(codec, 0xaf, reg_val);
-+      ac101_write(codec, 0xb0, 0xc982);
-+
-+      ac101_write(codec, 0x16, 0x9f9f);
-+
-+}
-+
-+void drc_enable(struct snd_soc_codec *codec,bool on)
-+{
-+      int reg_val;
-+      if (on) {
-+              ac101_write(codec, 0xb5, 0xA080);
-+              reg_val = ac101_read(codec, MOD_CLK_ENA);
-+              reg_val |= (0x1<<6);
-+              ac101_write(codec, MOD_CLK_ENA, reg_val);
-+              reg_val = ac101_read(codec, MOD_RST_CTRL);
-+              reg_val |= (0x1<<6);
-+              ac101_write(codec, MOD_RST_CTRL, reg_val);
-+
-+              reg_val = ac101_read(codec, 0xa0);
-+              reg_val |= (0x7<<0);
-+              ac101_write(codec, 0xa0, reg_val);
-+      } else {
-+              ac101_write(codec, 0xb5, 0x0);
-+              reg_val = ac101_read(codec, MOD_CLK_ENA);
-+              reg_val &= ~(0x1<<6);
-+              ac101_write(codec, MOD_CLK_ENA, reg_val);
-+              reg_val = ac101_read(codec, MOD_RST_CTRL);
-+              reg_val &= ~(0x1<<6);
-+              ac101_write(codec, MOD_RST_CTRL, reg_val);
-+
-+              reg_val = ac101_read(codec, 0xa0);
-+              reg_val &= ~(0x7<<0);
-+              ac101_write(codec, 0xa0, reg_val);
-+      }
-+}
-+
-+void set_configuration(struct snd_soc_codec *codec)
-+{
-+      if (speaker_double_used) {
-+              ac101_update_bits(codec, SPKOUT_CTRL, (0x1f<<SPK_VOL),
-+                                (double_speaker_val<<SPK_VOL));
-+      } else {
-+              ac101_update_bits(codec, SPKOUT_CTRL, (0x1f<<SPK_VOL),
-+                                (single_speaker_val<<SPK_VOL));
-+      }
-+      ac101_update_bits(codec, HPOUT_CTRL, (0x3f<<HP_VOL), (headset_val<<HP_VOL));
-+      ac101_update_bits(codec, ADC_SRCBST_CTRL, (0x7<<ADC_MIC1G), (mainmic_val<<ADC_MIC1G));
-+      ac101_update_bits(codec, ADC_SRCBST_CTRL, (0x7<<ADC_MIC2G), (headsetmic_val<<ADC_MIC2G));
-+      if (dmic_used) {
-+              ac101_write(codec, ADC_VOL_CTRL, adc_digital_val);
-+      }
-+      if (drc_used) {
-+              drc_config(codec);
-+      }
-+      /*headphone calibration clock frequency select*/
-+      ac101_update_bits(codec, SPKOUT_CTRL, (0x7<<HPCALICKS), (0x7<<HPCALICKS));
-+
-+      /* I2S1 DAC Timeslot 0 data <- I2S1 DAC channel 0 */
-+      // "AIF1IN0L Mux" <= "AIF1DACL"
-+      // "AIF1IN0R Mux" <= "AIF1DACR"
-+      ac101_update_bits(codec, AIF1_DACDAT_CTRL, 0x3 << AIF1_DA0L_SRC, 0x0 << AIF1_DA0L_SRC);
-+      ac101_update_bits(codec, AIF1_DACDAT_CTRL, 0x3 << AIF1_DA0R_SRC, 0x0 << AIF1_DA0R_SRC);
-+      /* Timeslot 0 Left & Right Channel enable */
-+      ac101_update_bits(codec, AIF1_DACDAT_CTRL, 0x3 << AIF1_DA0R_ENA, 0x3 << AIF1_DA0R_ENA);
-+
-+      /* DAC Digital Mixer Source Select <- I2S1 DA0 */
-+      // "DACL Mixer" += "AIF1IN0L Mux"
-+      // "DACR Mixer" += "AIF1IN0R Mux"
-+      ac101_update_bits(codec, DAC_MXR_SRC, 0xF << DACL_MXR_ADCL, 0x8 << DACL_MXR_ADCL);
-+      ac101_update_bits(codec, DAC_MXR_SRC, 0xF << DACR_MXR_ADCR, 0x8 << DACR_MXR_ADCR);
-+      /* Internal DAC Analog Left & Right Channel enable */
-+      ac101_update_bits(codec, OMIXER_DACA_CTRL, 0x3 << DACALEN, 0x3 << DACALEN);
-+
-+      /* Output Mixer Source Select */
-+      // "Left Output Mixer"  += "DACL Mixer"
-+      // "Right Output Mixer" += "DACR Mixer"
-+      ac101_update_bits(codec, OMIXER_SR, 0x1 << LMIXMUTEDACL, 0x1 << LMIXMUTEDACL);
-+      ac101_update_bits(codec, OMIXER_SR, 0x1 << RMIXMUTEDACR, 0x1 << RMIXMUTEDACR);
-+      /* Left & Right Analog Output Mixer enable */
-+      ac101_update_bits(codec, OMIXER_DACA_CTRL, 0x3 << LMIXEN, 0x3 << LMIXEN);
-+
-+      /* Headphone Ouput Control */ 
-+      // "HP_R Mux" <= "DACR Mixer"
-+      // "HP_L Mux" <= "DACL Mixer"
-+      ac101_update_bits(codec, HPOUT_CTRL, 0x1 << LHPS, 0x0 << LHPS);
-+      ac101_update_bits(codec, HPOUT_CTRL, 0x1 << RHPS, 0x0 << RHPS);
-+
-+      /* Speaker Output Control */
-+      // "SPK_L Mux" <= "SPK_LR Adder"
-+      // "SPK_R Mux" <= "SPK_LR Adder"
-+      ac101_update_bits(codec, SPKOUT_CTRL, (0x1 << LSPKS) | (0x1 << RSPKS),
-+                        (0x1 << LSPKS) | (0x1 << RSPKS));
-+      /* Enable Left & Right Speaker */
-+      ac101_update_bits(codec, SPKOUT_CTRL, (0x1 << LSPK_EN) | (0x1 << RSPK_EN),
-+                        (0x1 << LSPK_EN) | (0x1 << RSPK_EN));
-+      return;
-+}
-+
-+static int late_enable_dac(struct snd_soc_codec* codec, int event) {
-+      struct ac10x_priv *ac10x = snd_soc_codec_get_drvdata(codec);
-+
-+      mutex_lock(&ac10x->dac_mutex);
-+      switch (event) {
-+      case SND_SOC_DAPM_PRE_PMU:
-+              AC101_DBG();
-+              if (ac10x->dac_enable == 0){
-+                      /*enable dac module clk*/
-+                      ac101_update_bits(codec, MOD_CLK_ENA, (0x1<<MOD_CLK_DAC_DIG),
-+                                        (0x1<<MOD_CLK_DAC_DIG));
-+                      ac101_update_bits(codec, MOD_RST_CTRL, (0x1<<MOD_RESET_DAC_DIG),
-+                                        (0x1<<MOD_RESET_DAC_DIG));
-+                      ac101_update_bits(codec, DAC_DIG_CTRL, (0x1<<ENDA), (0x1<<ENDA));
-+                      ac101_update_bits(codec, DAC_DIG_CTRL, (0x1<<ENHPF),(0x1<<ENHPF));
-+              }
-+              ac10x->dac_enable++;
-+              break;
-+      case SND_SOC_DAPM_POST_PMD:
-+              if (ac10x->dac_enable != 0){
-+                      ac10x->dac_enable = 0;
-+
-+                      ac101_update_bits(codec, DAC_DIG_CTRL, (0x1<<ENHPF),(0x0<<ENHPF));
-+                      ac101_update_bits(codec, DAC_DIG_CTRL, (0x1<<ENDA), (0x0<<ENDA));
-+                      /*disable dac module clk*/
-+                      ac101_update_bits(codec, MOD_CLK_ENA, (0x1<<MOD_CLK_DAC_DIG),
-+                                        (0x0<<MOD_CLK_DAC_DIG));
-+                      ac101_update_bits(codec, MOD_RST_CTRL, (0x1<<MOD_RESET_DAC_DIG),
-+                                        (0x0<<MOD_RESET_DAC_DIG));
-+              }
-+              break;
-+      }
-+      mutex_unlock(&ac10x->dac_mutex);
-+      return 0;
-+}
-+
-+static int ac101_headphone_event(struct snd_soc_codec* codec, int event) {
-+      switch (event) {
-+      case SND_SOC_DAPM_POST_PMU:
-+              /*open*/
-+              AC101_DBG("post:open\n");
-+              ac101_update_bits(codec, OMIXER_DACA_CTRL, (0xf<<HPOUTPUTENABLE),
-+                                (0xf<<HPOUTPUTENABLE));
-+              msleep(10);
-+              ac101_update_bits(codec, HPOUT_CTRL, (0x1<<HPPA_EN), (0x1<<HPPA_EN));
-+              ac101_update_bits(codec, HPOUT_CTRL, (0x3<<LHPPA_MUTE), (0x3<<LHPPA_MUTE));
-+              break;
-+      case SND_SOC_DAPM_PRE_PMD:
-+              /*close*/
-+              AC101_DBG("pre:close\n");
-+              ac101_update_bits(codec, HPOUT_CTRL, (0x3<<LHPPA_MUTE), (0x0<<LHPPA_MUTE));
-+              msleep(10);
-+              ac101_update_bits(codec, OMIXER_DACA_CTRL, (0xf<<HPOUTPUTENABLE),
-+                                (0x0<<HPOUTPUTENABLE));
-+              ac101_update_bits(codec, HPOUT_CTRL, (0x1<<HPPA_EN), (0x0<<HPPA_EN));
-+              break;
-+      }
-+      return 0;
-+}
-+
-+static int ac101_sysclk_started(void) {
-+      int reg_val;
-+
-+      reg_val = ac101_read(static_ac10x->codec, SYSCLK_CTRL);
-+      return (reg_val & (0x1<<SYSCLK_ENA));
-+}
-+
-+static int ac101_aif1clk(struct snd_soc_codec* codec, int event, int quick) {
-+      struct ac10x_priv *ac10x = snd_soc_codec_get_drvdata(codec);
-+      int ret = 0;
-+
-+      switch (event) {
-+      case SND_SOC_DAPM_PRE_PMU:
-+              if (ac10x->aif1_clken == 0){
-+                      ret = ac101_update_bits(codec, SYSCLK_CTRL, (0x1<<AIF1CLK_ENA),
-+                                              (0x1<<AIF1CLK_ENA));
-+                      if(!quick || _MASTER_MULTI_CODEC != _MASTER_AC101) {
-+                              /* enable aif1clk & sysclk */
-+                              ret = ret || ac101_update_bits(codec, MOD_CLK_ENA,
-+                                                             (0x1<<MOD_CLK_AIF1),
-+                                                             (0x1<<MOD_CLK_AIF1));
-+                              ret = ret || ac101_update_bits(codec, MOD_RST_CTRL,
-+                                                             (0x1<<MOD_RESET_AIF1),
-+                                                             (0x1<<MOD_RESET_AIF1));
-+                      }
-+                      ret = ret || ac101_update_bits(codec, SYSCLK_CTRL, (0x1<<SYSCLK_ENA),
-+                                                     (0x1<<SYSCLK_ENA));
-+
-+                      if (ret) {
-+                              AC101_DBG("start sysclk failed\n");
-+                      } else {
-+                              AC101_DBG("hw sysclk enable\n");
-+                              ac10x->aif1_clken++;
-+                      }
-+              }
-+              break;
-+      case SND_SOC_DAPM_POST_PMD:
-+              if (ac10x->aif1_clken != 0) {
-+                      /* disable aif1clk & sysclk */
-+                      ret = ac101_update_bits(codec, SYSCLK_CTRL, (0x1<<AIF1CLK_ENA),
-+                                              (0x0<<AIF1CLK_ENA));
-+                      ret = ret || ac101_update_bits(codec, MOD_CLK_ENA, (0x1<<MOD_CLK_AIF1),
-+                                                     (0x0<<MOD_CLK_AIF1));
-+                      ret = ret || ac101_update_bits(codec, MOD_RST_CTRL, (0x1<<MOD_RESET_AIF1),
-+                                                     (0x0<<MOD_RESET_AIF1));
-+                      ret = ret || ac101_update_bits(codec, SYSCLK_CTRL, (0x1<<SYSCLK_ENA),
-+                                                     (0x0<<SYSCLK_ENA));
-+
-+                      if (ret) {
-+                              AC101_DBG("stop sysclk failed\n");
-+                      } else {
-+                              AC101_DBG("hw sysclk disable\n");
-+                              ac10x->aif1_clken = 0;
-+                      }
-+                      break;
-+              }
-+      }
-+
-+      AC101_DBG("event=%d pre_up/%d post_down/%d\n", event, SND_SOC_DAPM_PRE_PMU,
-+                SND_SOC_DAPM_POST_PMD);
-+
-+      return ret;
-+}
-+
-+/**
-+ * snd_ac101_get_volsw - single mixer get callback
-+ * @kcontrol: mixer control
-+ * @ucontrol: control element information
-+ *
-+ * Callback to get the value of a single mixer control, or a double mixer
-+ * control that spans 2 registers.
-+ *
-+ * Returns 0 for success.
-+ */
-+static int snd_ac101_get_volsw(struct snd_kcontrol *kcontrol,
-+      struct snd_ctl_elem_value *ucontrol
-+){
-+      struct soc_mixer_control *mc =
-+              (struct soc_mixer_control *)kcontrol->private_value;
-+      unsigned int val, mask = (1 << fls(mc->max)) - 1;
-+      unsigned int invert = mc->invert;
-+      int ret;
-+
-+      if ((ret = ac101_read(static_ac10x->codec, mc->reg)) < 0)
-+              return ret;
-+
-+      val = (ret >> mc->shift) & mask;
-+      ucontrol->value.integer.value[0] = val - mc->min;
-+      if (invert) {
-+              ucontrol->value.integer.value[0] =
-+                      mc->max - ucontrol->value.integer.value[0];
-+      }
-+
-+      if (snd_soc_volsw_is_stereo(mc)) {
-+              val = (ret >> mc->rshift) & mask;
-+              ucontrol->value.integer.value[1] = val - mc->min;
-+              if (invert) {
-+                      ucontrol->value.integer.value[1] =
-+                              mc->max - ucontrol->value.integer.value[1];
-+              }
-+      }
-+      return 0;
-+}
-+
-+/**
-+ * snd_ac101_put_volsw - single mixer put callback
-+ * @kcontrol: mixer control
-+ * @ucontrol: control element information
-+ *
-+ * Callback to set the value of a single mixer control, or a double mixer
-+ * control that spans 2 registers.
-+ *
-+ * Returns 0 for success.
-+ */
-+static int snd_ac101_put_volsw(struct snd_kcontrol *kcontrol,
-+      struct snd_ctl_elem_value *ucontrol
-+){
-+      struct soc_mixer_control *mc =
-+              (struct soc_mixer_control *)kcontrol->private_value;
-+      unsigned int sign_bit = mc->sign_bit;
-+      unsigned int val, mask = (1 << fls(mc->max)) - 1;
-+      unsigned int invert = mc->invert;
-+      int ret;
-+
-+      if (sign_bit)
-+              mask = BIT(sign_bit + 1) - 1;
-+
-+      val = ((ucontrol->value.integer.value[0] + mc->min) & mask);
-+      if (invert) {
-+              val = mc->max - val;
-+      }
-+
-+      ret = ac101_update_bits(static_ac10x->codec, mc->reg, mask << mc->shift, val << mc->shift);
-+
-+      if (! snd_soc_volsw_is_stereo(mc)) {
-+              return ret;
-+      }
-+      val = ((ucontrol->value.integer.value[1] + mc->min) & mask);
-+      if (invert) {
-+              val = mc->max - val;
-+      }
-+
-+      ret = ac101_update_bits(static_ac10x->codec, mc->reg, mask << mc->rshift,
-+                              val << mc->rshift);
-+      return ret;
-+}
-+
-+
-+static const DECLARE_TLV_DB_SCALE(dac_vol_tlv, -11925, 75, 0);
-+static const DECLARE_TLV_DB_SCALE(dac_mix_vol_tlv, -600, 600, 0);
-+static const DECLARE_TLV_DB_SCALE(dig_vol_tlv, -7308, 116, 0);
-+static const DECLARE_TLV_DB_SCALE(speaker_vol_tlv, -4800, 150, 0);
-+static const DECLARE_TLV_DB_SCALE(headphone_vol_tlv, -6300, 100, 0);
-+
-+static struct snd_kcontrol_new ac101_controls[] = {
-+      /*DAC*/
-+      SOC_DOUBLE_TLV("DAC volume", DAC_VOL_CTRL, DAC_VOL_L, DAC_VOL_R, 0xff, 0, dac_vol_tlv),
-+      SOC_DOUBLE_TLV("DAC mixer gain", DAC_MXR_GAIN, DACL_MXR_GAIN, DACR_MXR_GAIN,
-+                     0xf, 0, dac_mix_vol_tlv),
-+      SOC_SINGLE_TLV("digital volume", DAC_DBG_CTRL, DVC, 0x3f, 1, dig_vol_tlv),
-+      SOC_SINGLE_TLV("speaker volume", SPKOUT_CTRL, SPK_VOL, 0x1f, 0, speaker_vol_tlv),
-+      SOC_SINGLE_TLV("headphone volume", HPOUT_CTRL, HP_VOL, 0x3f, 0, headphone_vol_tlv),
-+};
-+
-+/* PLL divisors */
-+struct pll_div {
-+      unsigned int pll_in;
-+      unsigned int pll_out;
-+      int m;
-+      int n_i;
-+      int n_f;
-+};
-+
-+struct aif1_fs {
-+      unsigned samp_rate;
-+      int bclk_div;
-+      int srbit;
-+      #define _SERIES_24_576K         0
-+      #define _SERIES_22_579K         1
-+      int series;
-+};
-+
-+struct kv_map {
-+      int val;
-+      int bit;
-+};
-+
-+/*
-+ * Note : pll code from original tdm/i2s driver.
-+ * freq_out = freq_in * N/(M*(2k+1)) , k=1,N=N_i+N_f,N_f=factor*0.2;
-+ *            N_i[0,1023], N_f_factor[0,7], m[1,64]=REG_VAL[1-63,0]
-+ */
-+static const struct pll_div codec_pll_div[] = {
-+      {128000,   _FREQ_22_579K,  1, 529, 1},
-+      {192000,   _FREQ_22_579K,  1, 352, 4},
-+      {256000,   _FREQ_22_579K,  1, 264, 3},
-+      {384000,   _FREQ_22_579K,  1, 176, 2}, /*((176+2*0.2)*6000000)/(38*(2*1+1))*/
-+      {1411200,  _FREQ_22_579K,  1,  48, 0},
-+      {2822400,  _FREQ_22_579K,  1,  24, 0}, /* accurate, 11025 * 256 */
-+      {5644800,  _FREQ_22_579K,  1,  12, 0}, /* accurate, 22050 * 256 */
-+      {6000000,  _FREQ_22_579K, 38, 429, 0}, /*((429+0*0.2)*6000000)/(38*(2*1+1))*/
-+      {11289600, _FREQ_22_579K,  1,   6, 0}, /* accurate, 44100 * 256 */
-+      {13000000, _FREQ_22_579K, 19,  99, 0},
-+      {19200000, _FREQ_22_579K, 25,  88, 1},
-+      {24000000, _FREQ_22_579K, 63, 177, 4}, /* 22577778 Hz */
-+
-+      {128000,   _FREQ_24_576K,  1, 576, 0},
-+      {192000,   _FREQ_24_576K,  1, 384, 0},
-+      {256000,   _FREQ_24_576K,  1, 288, 0},
-+      {384000,   _FREQ_24_576K,  1, 192, 0},
-+      {2048000,  _FREQ_24_576K,  1,  36, 0}, /* accurate,  8000 * 256 */
-+      {3072000,  _FREQ_24_576K,  1,  24, 0}, /* accurate, 12000 * 256 */
-+      {4096000,  _FREQ_24_576K,  1,  18, 0}, /* accurate, 16000 * 256 */
-+      {6000000,  _FREQ_24_576K, 25, 307, 1},
-+      {6144000,  _FREQ_24_576K,  4,  48, 0}, /* accurate, 24000 * 256 */
-+      {12288000, _FREQ_24_576K,  8,  48, 0}, /* accurate, 48000 * 256 */
-+      {13000000, _FREQ_24_576K, 42, 238, 1},
-+      {19200000, _FREQ_24_576K, 25,  96, 0},
-+      {24000000, _FREQ_24_576K, 25,  76, 4}, /* accurate */
-+
-+      {_FREQ_22_579K, _FREQ_22_579K,  8,  24, 0}, /* accurate, 88200 * 256 */
-+      {_FREQ_24_576K, _FREQ_24_576K,  8,  24, 0}, /* accurate, 96000 * 256 */
-+};
-+
-+static const struct aif1_fs codec_aif1_fs[] = {
-+      {8000, 12, 0},
-+      {11025, 8, 1, _SERIES_22_579K},
-+      {12000, 8, 2},
-+      {16000, 6, 3},
-+      {22050, 4, 4, _SERIES_22_579K},
-+      {24000, 4, 5},
-+      /* {32000, 3, 6}, dividing by 3 is not support */
-+      {44100, 2, 7, _SERIES_22_579K},
-+      {48000, 2, 8},
-+      {96000, 1, 9},
-+};
-+
-+static const struct kv_map codec_aif1_lrck[] = {
-+      {16, 0},
-+      {32, 1},
-+      {64, 2},
-+      {128, 3},
-+      {256, 4},
-+};
-+
-+static const struct kv_map codec_aif1_wsize[] = {
-+      {8, 0},
-+      {16, 1},
-+      {20, 2},
-+      {24, 3},
-+      {32, 3},
-+};
-+
-+static const unsigned ac101_bclkdivs[] = {
-+        1,   2,   4,   6,
-+        8,  12,  16,  24,
-+       32,  48,  64,  96,
-+      128, 192,   0,   0,
-+};
-+
-+static int ac101_aif_play(struct ac10x_priv* ac10x) {
-+      struct snd_soc_codec * codec = ac10x->codec;
-+
-+      late_enable_dac(codec, SND_SOC_DAPM_PRE_PMU);
-+      ac101_headphone_event(codec, SND_SOC_DAPM_POST_PMU);
-+      if (drc_used) {
-+              drc_enable(codec, 1);
-+      }
-+
-+      /* Enable Left & Right Speaker */
-+      ac101_update_bits(codec, SPKOUT_CTRL, (0x1 << LSPK_EN) | (0x1 << RSPK_EN),
-+                        (0x1 << LSPK_EN) | (0x1 << RSPK_EN));
-+      if (ac10x->gpiod_spk_amp_gate) {
-+              gpiod_set_value(ac10x->gpiod_spk_amp_gate, 1);
-+      }
-+      return 0;
-+}
-+
-+static void ac10x_work_aif_play(struct work_struct *work) {
-+      struct ac10x_priv *ac10x = container_of(work, struct ac10x_priv, dlywork.work);
-+
-+      ac101_aif_play(ac10x);
-+      return;
-+}
-+
-+int ac101_aif_mute(struct snd_soc_dai *codec_dai, int mute)
-+{
-+      struct snd_soc_codec *codec = codec_dai->codec;
-+      struct ac10x_priv *ac10x = snd_soc_codec_get_drvdata(codec);
-+
-+      AC101_DBG("mute=%d\n",  mute);
-+
-+      ac101_write(codec, DAC_VOL_CTRL, mute? 0: 0xA0A0);
-+
-+      if (!mute) {
-+              #if _MASTER_MULTI_CODEC != _MASTER_AC101
-+              /* enable global clock */
-+              ac10x->aif1_clken = 0;
-+              ac101_aif1clk(codec, SND_SOC_DAPM_PRE_PMU, 0);
-+              ac101_aif_play(ac10x);
-+              #else
-+              schedule_delayed_work(&ac10x->dlywork, msecs_to_jiffies(50));
-+              #endif
-+      } else {
-+              #if _MASTER_MULTI_CODEC == _MASTER_AC101
-+              cancel_delayed_work_sync(&ac10x->dlywork);
-+              #endif
-+
-+              if (ac10x->gpiod_spk_amp_gate) {
-+                      gpiod_set_value(ac10x->gpiod_spk_amp_gate, 0);
-+              }
-+              /* Disable Left & Right Speaker */
-+              ac101_update_bits(codec, SPKOUT_CTRL, (0x1 << LSPK_EN) | (0x1 << RSPK_EN),
-+                                (0x0 << LSPK_EN) | (0x0 << RSPK_EN));
-+              if (drc_used) {
-+                      drc_enable(codec, 0);
-+              }
-+              ac101_headphone_event(codec, SND_SOC_DAPM_PRE_PMD);
-+              late_enable_dac(codec, SND_SOC_DAPM_POST_PMD);
-+
-+              #if _MASTER_MULTI_CODEC != _MASTER_AC101
-+              ac10x->aif1_clken = 1;
-+              ac101_aif1clk(codec, SND_SOC_DAPM_POST_PMD, 0);
-+              #endif
-+      }
-+      return 0;
-+}
-+
-+void ac101_aif_shutdown(struct snd_pcm_substream *substream, struct snd_soc_dai *codec_dai)
-+{
-+      struct snd_soc_codec *codec = codec_dai->codec;
-+      struct ac10x_priv *ac10x = snd_soc_codec_get_drvdata(codec);
-+
-+      AC101_DBG("stream = %s, play: %d, capt: %d, active: %d\n", 
-+              snd_pcm_stream_str(substream),
-+              codec_dai->stream[SNDRV_PCM_STREAM_PLAYBACK].active,
-+              codec_dai->stream[SNDRV_PCM_STREAM_CAPTURE].active,
-+              snd_soc_dai_active(codec_dai));
-+
-+      if (!snd_soc_dai_active(codec_dai)) {
-+              ac10x->aif1_clken = 1;
-+              ac101_aif1clk(codec, SND_SOC_DAPM_POST_PMD, 0);
-+      } else {
-+              ac101_aif1clk(codec, SND_SOC_DAPM_PRE_PMU, 0);
-+      }
-+}
-+
-+static int ac101_set_pll(struct snd_soc_dai *codec_dai, int pll_id, int source,
-+                      unsigned int freq_in, unsigned int freq_out)
-+{
-+      struct snd_soc_codec *codec = codec_dai->codec;
-+      int i, m, n_i, n_f;
-+
-+      AC101_DBG("pll_id:%d\n",  pll_id);
-+
-+      /* clear volatile reserved bits*/
-+      ac101_update_bits(codec, SYSCLK_CTRL, 0xFF & ~(0x1 << SYSCLK_ENA), 0x0);
-+
-+      /* select aif1 clk srouce from mclk1 */
-+      ac101_update_bits(codec, SYSCLK_CTRL, (0x3<<AIF1CLK_SRC), (0x0<<AIF1CLK_SRC));
-+      /* disable pll */
-+      ac101_update_bits(codec, PLL_CTRL2, (0x1<<PLL_EN), (0<<PLL_EN));
-+
-+      if (!freq_out)
-+              return 0;
-+      if ((freq_in < 128000) || (freq_in > _FREQ_24_576K)) {
-+              return -EINVAL;
-+      } else if ((freq_in == _FREQ_24_576K) || (freq_in == _FREQ_22_579K)) {
-+              if (pll_id == AC101_MCLK1) {
-+                      /*select aif1 clk source from mclk1*/
-+                      ac101_update_bits(codec, SYSCLK_CTRL, (0x3<<AIF1CLK_SRC),
-+                                        (0x0<<AIF1CLK_SRC));
-+                      return 0;
-+              }
-+      }
-+
-+      switch (pll_id) {
-+      case AC101_MCLK1:
-+              /*pll source from MCLK1*/
-+              ac101_update_bits(codec, SYSCLK_CTRL, (0x3<<PLLCLK_SRC), (0x0<<PLLCLK_SRC));
-+              break;
-+      case AC101_BCLK1:
-+              /*pll source from BCLK1*/
-+              ac101_update_bits(codec, SYSCLK_CTRL, (0x3<<PLLCLK_SRC), (0x2<<PLLCLK_SRC));
-+              break;
-+      default:
-+              return -EINVAL;
-+      }
-+
-+      /* freq_out = freq_in * n/(m*(2k+1)) , k=1,N=N_i+N_f */
-+      for (i = m = n_i = n_f = 0; i < ARRAY_SIZE(codec_pll_div); i++) {
-+              if ((codec_pll_div[i].pll_in == freq_in) &&
-+                  (codec_pll_div[i].pll_out == freq_out)) {
-+                      m   = codec_pll_div[i].m;
-+                      n_i = codec_pll_div[i].n_i;
-+                      n_f = codec_pll_div[i].n_f;
-+                      break;
-+              }
-+      }
-+      /* config pll m */
-+      if (m  == 64) m = 0;
-+      ac101_update_bits(codec, PLL_CTRL1, (0x3f<<PLL_POSTDIV_M), (m<<PLL_POSTDIV_M));
-+      /* config pll n */
-+      ac101_update_bits(codec, PLL_CTRL2, (0x3ff<<PLL_PREDIV_NI), (n_i<<PLL_PREDIV_NI));
-+      ac101_update_bits(codec, PLL_CTRL2, (0x7<<PLL_POSTDIV_NF), (n_f<<PLL_POSTDIV_NF));
-+      /* enable pll */
-+      ac101_update_bits(codec, PLL_CTRL2, (0x1<<PLL_EN), (1<<PLL_EN));
-+      ac101_update_bits(codec, SYSCLK_CTRL, (0x1<<PLLCLK_ENA),  (0x1<<PLLCLK_ENA));
-+      ac101_update_bits(codec, SYSCLK_CTRL, (0x3<<AIF1CLK_SRC), (0x3<<AIF1CLK_SRC));
-+
-+      return 0;
-+}
-+
-+int ac101_hw_params(struct snd_pcm_substream *substream,
-+      struct snd_pcm_hw_params *params,
-+      struct snd_soc_dai *codec_dai)
-+{
-+      int i = 0;
-+      int AIF_CLK_CTRL = AIF1_CLK_CTRL;
-+      int aif1_word_size = 24;
-+      int aif1_slot_size = 32;
-+      int aif1_lrck_div;
-+      struct snd_soc_codec *codec = codec_dai->codec;
-+      struct ac10x_priv *ac10x = snd_soc_codec_get_drvdata(codec);
-+      int reg_val, freq_out;
-+      unsigned channels;
-+
-+      AC101_DBG("+++\n");
-+
-+      if (_MASTER_MULTI_CODEC == _MASTER_AC101 && ac101_sysclk_started()) {
-+              /* not configure hw_param twice if stream is playback, tell the caller it's started */
-+              if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
-+                      return 1;
-+              }
-+      }
-+
-+      /* get channels count & slot size */
-+      channels = params_channels(params);
-+
-+      switch (params_format(params)) {
-+      case SNDRV_PCM_FORMAT_S24_LE:
-+      case SNDRV_PCM_FORMAT_S32_LE:
-+              aif1_slot_size = 32;
-+              break;
-+      case SNDRV_PCM_FORMAT_S16_LE:
-+      default:
-+              aif1_slot_size = 16;
-+              break;
-+      }
-+
-+      /* set LRCK/BCLK ratio */
-+      aif1_lrck_div = aif1_slot_size * channels;
-+      for (i = 0; i < ARRAY_SIZE(codec_aif1_lrck); i++) {
-+              if (codec_aif1_lrck[i].val == aif1_lrck_div) {
-+                      break;
-+              }
-+      }
-+      ac101_update_bits(codec, AIF_CLK_CTRL, (0x7 << AIF1_LRCK_DIV),
-+                        codec_aif1_lrck[i].bit << AIF1_LRCK_DIV);
-+
-+      /* set PLL output freq */
-+      freq_out = _FREQ_24_576K;
-+      for (i = 0; i < ARRAY_SIZE(codec_aif1_fs); i++) {
-+              if (codec_aif1_fs[i].samp_rate == params_rate(params)) {
-+                      if (codec_dai->stream[SNDRV_PCM_STREAM_CAPTURE].active && dmic_used &&
-+                          codec_aif1_fs[i].samp_rate == 44100) {
-+                              ac101_update_bits(codec, AIF_SR_CTRL, (0xf<<AIF1_FS),
-+                                                (0x4<<AIF1_FS));
-+                      } else {
-+                              ac101_update_bits(codec, AIF_SR_CTRL, (0xf<<AIF1_FS),
-+                                                ((codec_aif1_fs[i].srbit)<<AIF1_FS));
-+                      }
-+                      if (codec_aif1_fs[i].series == _SERIES_22_579K)
-+                              freq_out = _FREQ_22_579K;
-+                      break;
-+              }
-+      }
-+
-+      /* set I2S word size */
-+      for (i = 0; i < ARRAY_SIZE(codec_aif1_wsize); i++) {
-+              if (codec_aif1_wsize[i].val == aif1_word_size) {
-+                      break;
-+              }
-+      }
-+      ac101_update_bits(codec, AIF_CLK_CTRL, (0x3<<AIF1_WORK_SIZ),
-+                        ((codec_aif1_wsize[i].bit)<<AIF1_WORK_SIZ));
-+
-+      /* set TDM slot size */
-+      if ((reg_val = codec_aif1_wsize[i].bit) > 2) reg_val = 2;
-+      ac101_update_bits(codec, AIF1_ADCDAT_CTRL, 0x3 << AIF1_SLOT_SIZ, reg_val << AIF1_SLOT_SIZ);
-+
-+      /* setting pll if it's master mode */
-+      reg_val = ac101_read(codec, AIF_CLK_CTRL);
-+      if ((reg_val & (0x1 << AIF1_MSTR_MOD)) == 0) {
-+              unsigned bclkdiv;
-+
-+              ac101_set_pll(codec_dai, AC101_MCLK1, 0, ac10x->sysclk, freq_out);
-+
-+              bclkdiv = freq_out / (aif1_lrck_div * params_rate(params));
-+              for (i = 0; i < ARRAY_SIZE(ac101_bclkdivs) - 1; i++) {
-+                      if (ac101_bclkdivs[i] >= bclkdiv) {
-+                              break;
-+                      }
-+              }
-+              ac101_update_bits(codec, AIF_CLK_CTRL, (0xf<<AIF1_BCLK_DIV), i<<AIF1_BCLK_DIV);
-+      } else {
-+              /* set pll clock source to BCLK if slave mode */
-+              ac101_set_pll(codec_dai, AC101_BCLK1, 0, aif1_lrck_div * params_rate(params),
-+                            freq_out);
-+      }
-+
-+      #if _MASTER_MULTI_CODEC == _MASTER_AC101
-+      /* Master mode, to clear cpu_dai fifos, disable output bclk & lrck */
-+      ac101_aif1clk(codec, SND_SOC_DAPM_POST_PMD, 0);
-+      #endif
-+
-+      AC101_DBG("rate: %d , channels: %d , samp_res: %d",
-+              params_rate(params), channels, aif1_slot_size);
-+
-+      AC101_DBG("---\n");
-+      return 0;
-+}
-+
-+int ac101_set_dai_fmt(struct snd_soc_dai *codec_dai, unsigned int fmt)
-+{
-+      int reg_val;
-+      int AIF_CLK_CTRL = AIF1_CLK_CTRL;
-+      struct snd_soc_codec *codec = codec_dai->codec;
-+
-+      AC101_DBG();
-+
-+      /*
-+       *      master or slave selection
-+       *      0 = Master mode
-+       *      1 = Slave mode
-+       */
-+      reg_val = ac101_read(codec, AIF_CLK_CTRL);
-+      reg_val &= ~(0x1<<AIF1_MSTR_MOD);
-+      switch(fmt & SND_SOC_DAIFMT_MASTER_MASK) {
-+      case SND_SOC_DAIFMT_CBM_CFM:   /* codec clk & frm master, ap is slave*/
-+              #if _MASTER_MULTI_CODEC == _MASTER_AC101
-+              pr_warn("AC101 as Master\n");
-+              reg_val |= (0x0<<AIF1_MSTR_MOD);
-+              break;
-+              #else
-+              pr_warn("AC108 as Master\n");
-+              #endif
-+      case SND_SOC_DAIFMT_CBS_CFS:   /* codec clk & frm slave, ap is master*/
-+              pr_warn("AC101 as Slave\n");
-+              reg_val |= (0x1<<AIF1_MSTR_MOD);
-+              break;
-+      default:
-+              pr_err("unknwon master/slave format\n");
-+              return -EINVAL;
-+      }
-+
-+      /*
-+       * Enable TDM mode
-+       */
-+      reg_val |=  (0x1 << AIF1_TDMM_ENA);
-+      ac101_write(codec, AIF_CLK_CTRL, reg_val);
-+
-+      /* i2s mode selection */
-+      reg_val = ac101_read(codec, AIF_CLK_CTRL);
-+      reg_val&=~(3<<AIF1_DATA_FMT);
-+      switch(fmt & SND_SOC_DAIFMT_FORMAT_MASK){
-+      case SND_SOC_DAIFMT_I2S:        /* I2S1 mode */
-+              reg_val |= (0x0<<AIF1_DATA_FMT);
-+              break;
-+      case SND_SOC_DAIFMT_RIGHT_J:    /* Right Justified mode */
-+              reg_val |= (0x2<<AIF1_DATA_FMT);
-+              break;
-+      case SND_SOC_DAIFMT_LEFT_J:     /* Left Justified mode */
-+              reg_val |= (0x1<<AIF1_DATA_FMT);
-+              break;
-+      case SND_SOC_DAIFMT_DSP_A:      /* L reg_val msb after FRM LRC */
-+              reg_val |= (0x3<<AIF1_DATA_FMT);
-+              break;
-+      case SND_SOC_DAIFMT_DSP_B:
-+              /* TODO: data offset set to 0 */
-+              reg_val |= (0x3<<AIF1_DATA_FMT);
-+              break;
-+      default:
-+              pr_err("%s, line:%d\n", __func__, __LINE__);
-+              return -EINVAL;
-+      }
-+      ac101_write(codec, AIF_CLK_CTRL, reg_val);
-+
-+      /* DAI signal inversions */
-+      reg_val = ac101_read(codec, AIF_CLK_CTRL);
-+      switch(fmt & SND_SOC_DAIFMT_INV_MASK){
-+      case SND_SOC_DAIFMT_NB_NF:     /* normal bit clock + nor frame */
-+              reg_val &= ~(0x1<<AIF1_LRCK_INV);
-+              reg_val &= ~(0x1<<AIF1_BCLK_INV);
-+              break;
-+      case SND_SOC_DAIFMT_NB_IF:     /* normal bclk + inv frm */
-+              reg_val |= (0x1<<AIF1_LRCK_INV);
-+              reg_val &= ~(0x1<<AIF1_BCLK_INV);
-+              break;
-+      case SND_SOC_DAIFMT_IB_NF:     /* invert bclk + nor frm */
-+              reg_val &= ~(0x1<<AIF1_LRCK_INV);
-+              reg_val |= (0x1<<AIF1_BCLK_INV);
-+              break;
-+      case SND_SOC_DAIFMT_IB_IF:     /* invert bclk + inv frm */
-+              reg_val |= (0x1<<AIF1_LRCK_INV);
-+              reg_val |= (0x1<<AIF1_BCLK_INV);
-+              break;
-+      }
-+      ac101_write(codec, AIF_CLK_CTRL, reg_val);
-+
-+      return 0;
-+}
-+
-+int ac101_audio_startup(struct snd_pcm_substream *substream,
-+      struct snd_soc_dai *codec_dai)
-+{
-+      // struct snd_soc_codec *codec = codec_dai->codec;
-+
-+      AC101_DBG("\n\n\n");
-+
-+      if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) {
-+      }
-+      return 0;
-+}
-+
-+int ac101_trigger(struct snd_pcm_substream *substream, int cmd,
-+                struct snd_soc_dai *dai)
-+{
-+      struct snd_soc_codec *codec = dai->codec;
-+      struct ac10x_priv *ac10x = snd_soc_codec_get_drvdata(codec);
-+      int ret = 0;
-+
-+      AC101_DBG("stream=%s  cmd=%d\n",
-+              snd_pcm_stream_str(substream),
-+              cmd);
-+
-+      switch (cmd) {
-+      case SNDRV_PCM_TRIGGER_START:
-+      case SNDRV_PCM_TRIGGER_RESUME:
-+      case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
-+              #if _MASTER_MULTI_CODEC == _MASTER_AC101
-+              if (ac10x->aif1_clken == 0){
-+                      /*
-+                       * enable aif1clk, it' here due to reduce time between 'AC108 Sysclk Enable' and 'AC101 Sysclk Enable'
-+                       * Or else the two AC108 chips lost the sync.
-+                       */
-+                      ret = 0;
-+                      ret = ret || ac101_update_bits(codec, MOD_CLK_ENA,
-+                                                     (0x1<<MOD_CLK_AIF1), (0x1<<MOD_CLK_AIF1));
-+                      ret = ret || ac101_update_bits(codec, MOD_RST_CTRL, (0x1<<MOD_RESET_AIF1),
-+                                                     (0x1<<MOD_RESET_AIF1));
-+              }
-+              #endif
-+              break;
-+      case SNDRV_PCM_TRIGGER_STOP:
-+      case SNDRV_PCM_TRIGGER_SUSPEND:
-+      case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
-+              break;
-+      default:
-+              ret = -EINVAL;
-+      }
-+      return ret;
-+}
-+
-+#if 0
-+static int ac101_set_dai_sysclk(struct snd_soc_dai *codec_dai,
-+                                int clk_id, unsigned int freq, int dir)
-+{
-+      struct snd_soc_codec *codec = codec_dai->codec;
-+      struct ac10x_priv *ac10x = snd_soc_codec_get_drvdata(codec);
-+
-+      AC101_DBG("id=%d freq=%d, dir=%d\n", 
-+              clk_id, freq, dir);
-+
-+      ac10x->sysclk = freq;
-+
-+      return 0;
-+}
-+
-+static const struct snd_soc_dai_ops ac101_aif1_dai_ops = {
-+      //.startup      = ac101_audio_startup,
-+      //.shutdown     = ac101_aif_shutdown,
-+      //.set_sysclk   = ac101_set_dai_sysclk,
-+      //.set_pll      = ac101_set_pll,
-+      //.set_fmt      = ac101_set_dai_fmt,
-+      //.hw_params    = ac101_hw_params,
-+      //.trigger      = ac101_trigger,
-+      //.digital_mute = ac101_aif_mute,
-+};
-+
-+static struct snd_soc_dai_driver ac101_dai[] = {
-+      {
-+              .name = "ac10x-aif1",
-+              .id = AIF1_CLK,
-+              .playback = {
-+                      .stream_name = "Playback",
-+                      .channels_min = 1,
-+                      .channels_max = 8,
-+                      .rates = AC101_RATES,
-+                      .formats = AC101_FORMATS,
-+              },
-+              #if 0
-+              .capture = {
-+                      .stream_name = "Capture",
-+                      .channels_min = 1,
-+                      .channels_max = 8,
-+                      .rates = AC101_RATES,
-+                      .formats = AC101_FORMATS,
-+              },
-+              #endif
-+              .ops = &ac101_aif1_dai_ops,
-+      }
-+};
-+#endif
-+
-+static void codec_resume_work(struct work_struct *work)
-+{
-+      struct ac10x_priv *ac10x = container_of(work, struct ac10x_priv, codec_resume);
-+      struct snd_soc_codec *codec = ac10x->codec;
-+
-+      AC101_DBG("+++\n");
-+
-+      set_configuration(codec);
-+      if (drc_used) {
-+              drc_config(codec);
-+      }
-+      /*enable this bit to prevent leakage from ldoin*/
-+      ac101_update_bits(codec, ADDA_TUNE3, (0x1<<OSCEN), (0x1<<OSCEN));
-+
-+      AC101_DBG("---\n");
-+      return;
-+}
-+
-+int ac101_set_bias_level(struct snd_soc_codec *codec, enum snd_soc_bias_level level)
-+{
-+      switch (level) {
-+      case SND_SOC_BIAS_ON:
-+              AC101_DBG("SND_SOC_BIAS_ON\n");
-+              break;
-+      case SND_SOC_BIAS_PREPARE:
-+              AC101_DBG("SND_SOC_BIAS_PREPARE\n");
-+              break;
-+      case SND_SOC_BIAS_STANDBY:
-+              AC101_DBG("SND_SOC_BIAS_STANDBY\n");
-+              #ifdef CONFIG_AC101_SWITCH_DETECT
-+              switch_hw_config(codec);
-+              #endif
-+              break;
-+      case SND_SOC_BIAS_OFF:
-+              #ifdef CONFIG_AC101_SWITCH_DETECT
-+              ac101_update_bits(codec, ADC_APC_CTRL, (0x1<<HBIASEN), (0<<HBIASEN));
-+              ac101_update_bits(codec, ADC_APC_CTRL, (0x1<<HBIASADCEN), (0<<HBIASADCEN));
-+              #endif
-+              ac101_update_bits(codec, OMIXER_DACA_CTRL, (0xf<<HPOUTPUTENABLE),
-+                                (0<<HPOUTPUTENABLE));
-+              ac101_update_bits(codec, ADDA_TUNE3, (0x1<<OSCEN), (0<<OSCEN));
-+              AC101_DBG("SND_SOC_BIAS_OFF\n");
-+              break;
-+      }
-+      snd_soc_codec_get_dapm(codec)->bias_level = level;
-+      return 0;
-+}
-+
-+int ac101_codec_probe(struct snd_soc_codec *codec)
-+{
-+      int ret = 0;
-+      struct ac10x_priv *ac10x;
-+
-+      ac10x = dev_get_drvdata(codec->dev);
-+      if (ac10x == NULL) {
-+              AC101_DBG("not set client data!\n");
-+              return -ENOMEM;
-+      }
-+      ac10x->codec = codec;
-+
-+      INIT_DELAYED_WORK(&ac10x->dlywork, ac10x_work_aif_play);
-+      INIT_WORK(&ac10x->codec_resume, codec_resume_work);
-+      ac10x->dac_enable = 0;
-+      ac10x->aif1_clken = 0;
-+      mutex_init(&ac10x->dac_mutex);
-+
-+      set_configuration(ac10x->codec);
-+
-+      /*enable this bit to prevent leakage from ldoin*/
-+      ac101_update_bits(codec, ADDA_TUNE3, (0x1<<OSCEN), (0x1<<OSCEN));
-+      ac101_write(codec, DAC_VOL_CTRL, 0);
-+
-+      /* customized get/put inteface */
-+      for (ret = 0; ret < ARRAY_SIZE(ac101_controls); ret++) {
-+              struct snd_kcontrol_new* skn = &ac101_controls[ret];
-+
-+              skn->get = snd_ac101_get_volsw;
-+              skn->put = snd_ac101_put_volsw;
-+      }
-+      ret = snd_soc_add_codec_controls(codec, ac101_controls, ARRAY_SIZE(ac101_controls));
-+      if (ret) {
-+              pr_err("[ac10x] Failed to register audio mode control, "
-+                              "will continue without it.\n");
-+      }
-+
-+      #ifdef CONFIG_AC101_SWITCH_DETECT
-+      ret = ac101_switch_probe(ac10x);
-+      if (ret) {
-+              // not care the switch return value
-+      }
-+      #endif
-+
-+      return 0;
-+}
-+
-+/* power down chip */
-+int ac101_codec_remove(struct snd_soc_codec *codec)
-+{
-+      #ifdef CONFIG_AC101_SWITCH_DETECT
-+      struct ac10x_priv *ac10x = snd_soc_codec_get_drvdata(codec);
-+
-+      if (ac10x->irq) {
-+              devm_free_irq(codec->dev, ac10x->irq, ac10x);
-+              ac10x->irq = 0;
-+      }
-+
-+      if (cancel_work_sync(&ac10x->work_switch) != 0) {
-+      }
-+
-+      if (cancel_work_sync(&ac10x->work_clear_irq) != 0) {
-+      }
-+
-+      if (ac10x->inpdev) {
-+              input_unregister_device(ac10x->inpdev);
-+              ac10x->inpdev = NULL;
-+      }
-+      #endif
-+
-+      return 0;
-+}
-+
-+int ac101_codec_suspend(struct snd_soc_codec *codec)
-+{
-+      struct ac10x_priv *ac10x = snd_soc_codec_get_drvdata(codec);
-+
-+      AC101_DBG("[codec]:suspend\n");
-+      regcache_cache_only(ac10x->regmap101, true);
-+      return 0;
-+}
-+
-+int ac101_codec_resume(struct snd_soc_codec *codec)
-+{
-+      struct ac10x_priv *ac10x = snd_soc_codec_get_drvdata(codec);
-+      int ret;
-+
-+      AC101_DBG("[codec]:resume");
-+
-+      /* Sync reg_cache with the hardware */
-+      regcache_cache_only(ac10x->regmap101, false);
-+      ret = regcache_sync(ac10x->regmap101);
-+      if (ret != 0) {
-+              dev_err(codec->dev, "Failed to sync register cache: %d\n", ret);
-+              regcache_cache_only(ac10x->regmap101, true);
-+              return ret;
-+      }
-+
-+      #ifdef CONFIG_AC101_SWITCH_DETECT
-+      ac10x->mode = HEADPHONE_IDLE;
-+      ac10x->state = -1;
-+      #endif
-+
-+      ac101_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
-+      schedule_work(&ac10x->codec_resume);
-+      return 0;
-+}
-+
-+/***************************************************************************/
-+static ssize_t ac101_debug_store(struct device *dev,
-+      struct device_attribute *attr, const char *buf, size_t count)
-+{
-+      struct ac10x_priv *ac10x = dev_get_drvdata(dev);
-+      int val = 0, flag = 0;
-+      u16 value_w, value_r;
-+      u8 reg, num, i=0;
-+
-+      val = simple_strtol(buf, NULL, 16);
-+      flag = (val >> 24) & 0xF;
-+      if (flag) {
-+              reg = (val >> 16) & 0xFF;
-+              value_w =  val & 0xFFFF;
-+              ac101_write(ac10x->codec, reg, value_w);
-+              printk("write 0x%x to reg:0x%x\n", value_w, reg);
-+      } else {
-+              reg = (val >> 8) & 0xFF;
-+              num = val & 0xff;
-+              printk("\n");
-+              printk("read:start add:0x%x,count:0x%x\n", reg, num);
-+
-+              regcache_cache_bypass(ac10x->regmap101, true);
-+              do {
-+                      value_r = ac101_read(ac10x->codec, reg);
-+                      printk("0x%x: 0x%04x ", reg++, value_r);
-+                      if (++i % 4 == 0 || i == num)
-+                              printk("\n");
-+              } while (i < num);
-+              regcache_cache_bypass(ac10x->regmap101, false);
-+      }
-+      return count;
-+}
-+static ssize_t ac101_debug_show(struct device *dev,
-+      struct device_attribute *attr, char *buf)
-+{
-+      printk("echo flag|reg|val > ac10x\n");
-+      printk("eg read star addres=0x06,count 0x10:echo 0610 >ac10x\n");
-+      printk("eg write value:0x13fe to address:0x06 :echo 10613fe > ac10x\n");
-+      return 0;
-+}
-+static DEVICE_ATTR(ac10x, 0644, ac101_debug_show, ac101_debug_store);
-+
-+static struct attribute *audio_debug_attrs[] = {
-+      &dev_attr_ac10x.attr,
-+      NULL,
-+};
-+
-+static struct attribute_group audio_debug_attr_group = {
-+      .name   = "ac101_debug",
-+      .attrs  = audio_debug_attrs,
-+};
-+/***************************************************************************/
-+
-+/************************************************************/
-+static bool ac101_volatile_reg(struct device *dev, unsigned int reg)
-+{
-+      switch (reg) {
-+      case PLL_CTRL2:
-+      case HMIC_STS:
-+              return true;
-+      }
-+      return false;
-+}
-+
-+static const struct regmap_config ac101_regmap = {
-+      .reg_bits = 8,
-+      .val_bits = 16,
-+      .reg_stride = 1,
-+      .max_register = 0xB5,
-+      .cache_type = REGCACHE_FLAT,
-+      .volatile_reg = ac101_volatile_reg,
-+};
-+
-+/* Sync reg_cache from the hardware */
-+int ac10x_fill_regcache(struct device* dev, struct regmap* map) {
-+      int r, i, n;
-+      int v;
-+
-+      n = regmap_get_max_register(map);
-+      for (i = 0; i < n; i++) {
-+              regcache_cache_bypass(map, true);
-+              r = regmap_read(map, i, &v);
-+              if (r) {
-+                      dev_dbg(dev, "failed to read register %d\n", i);
-+                      continue;
-+              }
-+              regcache_cache_bypass(map, false);
-+
-+              regcache_cache_only(map, true);
-+              r = regmap_write(map, i, v);
-+              regcache_cache_only(map, false);
-+      }
-+      regcache_cache_bypass(map, false);
-+      regcache_cache_only(map, false);
-+
-+      return 0;
-+}
-+
-+int ac101_probe(struct i2c_client *i2c, const struct i2c_device_id *id)
-+{
-+      struct ac10x_priv *ac10x = i2c_get_clientdata(i2c);
-+      int ret = 0;
-+      unsigned v = 0;
-+
-+      AC101_DBG();
-+
-+      static_ac10x = ac10x;
-+
-+      ac10x->regmap101 = devm_regmap_init_i2c(i2c, &ac101_regmap);
-+      if (IS_ERR(ac10x->regmap101)) {
-+              ret = PTR_ERR(ac10x->regmap101);
-+              dev_err(&i2c->dev, "Fail to initialize I/O: %d\n", ret);
-+              return ret;
-+      }
-+
-+      /* Chip reset */
-+      regcache_cache_only(ac10x->regmap101, false);
-+      ret = regmap_write(ac10x->regmap101, CHIP_AUDIO_RST, 0);
-+      msleep(50);
-+
-+      /* sync regcache for FLAT type */
-+      ac10x_fill_regcache(&i2c->dev, ac10x->regmap101);
-+
-+      ret = regmap_read(ac10x->regmap101, CHIP_AUDIO_RST, &v);
-+      if (ret < 0) {
-+              dev_err(&i2c->dev, "failed to read vendor ID: %d\n", ret);
-+              return ret;
-+      }
-+
-+      if (v != AC101_CHIP_ID) {
-+              dev_err(&i2c->dev, "chip is not AC101 (%X)\n", v);
-+              dev_err(&i2c->dev, "Expected %X\n", AC101_CHIP_ID);
-+              return -ENODEV;
-+      }
-+
-+      ret = sysfs_create_group(&i2c->dev.kobj, &audio_debug_attr_group);
-+      if (ret) {
-+              pr_err("failed to create attr group\n");
-+      }
-+
-+      ac10x->gpiod_spk_amp_gate = devm_gpiod_get_optional(&i2c->dev, "spk-amp-switch",
-+                                                          GPIOD_OUT_LOW);
-+      if (IS_ERR(ac10x->gpiod_spk_amp_gate)) {
-+              ac10x->gpiod_spk_amp_gate = NULL;
-+              dev_err(&i2c->dev, "failed get spk-amp-switch in device tree\n");
-+      }
-+
-+      return 0;
-+}
-+
-+void ac101_shutdown(struct i2c_client *i2c)
-+{
-+      struct ac10x_priv *ac10x = i2c_get_clientdata(i2c);
-+      struct snd_soc_codec *codec = ac10x->codec;
-+      int reg_val;
-+
-+      if (codec == NULL) {
-+              pr_err(": no sound card.\n");
-+              return;
-+      }
-+
-+      /*set headphone volume to 0*/
-+      reg_val = ac101_read(codec, HPOUT_CTRL);
-+      reg_val &= ~(0x3f<<HP_VOL);
-+      ac101_write(codec, HPOUT_CTRL, reg_val);
-+
-+      /*disable pa*/
-+      reg_val = ac101_read(codec, HPOUT_CTRL);
-+      reg_val &= ~(0x1<<HPPA_EN);
-+      ac101_write(codec, HPOUT_CTRL, reg_val);
-+
-+      /*hardware xzh support*/
-+      reg_val = ac101_read(codec, OMIXER_DACA_CTRL);
-+      reg_val &= ~(0xf<<HPOUTPUTENABLE);
-+      ac101_write(codec, OMIXER_DACA_CTRL, reg_val);
-+
-+      /*unmute l/r headphone pa*/
-+      reg_val = ac101_read(codec, HPOUT_CTRL);
-+      reg_val &= ~((0x1<<RHPPA_MUTE)|(0x1<<LHPPA_MUTE));
-+      ac101_write(codec, HPOUT_CTRL, reg_val);
-+      return;
-+}
-+
-+int ac101_remove(struct i2c_client *i2c)
-+{
-+      sysfs_remove_group(&i2c->dev.kobj, &audio_debug_attr_group);
-+      return 0;
-+}
-+
-+MODULE_DESCRIPTION("ASoC ac10x driver");
-+MODULE_AUTHOR("huangxin,liushaohua");
-+MODULE_AUTHOR("PeterYang<linsheng.yang@seeed.cc>");
---- /dev/null
-+++ b/sound/soc/codecs/ac101_regs.h
-@@ -0,0 +1,431 @@
-+/*
-+ * ac101_regs.h
-+ *
-+ * (C) Copyright 2017-2018
-+ * Seeed Technology Co., Ltd. <www.seeedstudio.com>
-+ *
-+ * PeterYang <linsheng.yang@seeed.cc>
-+ *
-+ * (C) Copyright 2010-2017
-+ * Reuuimlla Technology Co., Ltd. <www.reuuimllatech.com>
-+ * huangxin <huangxin@reuuimllatech.com>
-+ *
-+ * some simple description for this code
-+ *
-+ * This program is free software; you can redistribute it and/or
-+ * modify it under the terms of the GNU General Public License as
-+ * published by the Free Software Foundation; either version 2 of
-+ * the License, or (at your option) any later version.
-+ *
-+ */
-+#ifndef __AC101_REGS_H__
-+#define __AC101_REGS_H__
-+
-+/*pll source*/
-+#define AC101_MCLK1 1
-+#define AC101_MCLK2 2
-+#define AC101_BCLK1 3
-+#define AC101_BCLK2 4
-+
-+#define AIF1_CLK 1
-+#define AIF2_CLK 2
-+
-+#define       CHIP_AUDIO_RST          0x0
-+#define PLL_CTRL1             0x1
-+#define PLL_CTRL2             0x2
-+#define SYSCLK_CTRL           0x3
-+#define MOD_CLK_ENA           0x4
-+#define MOD_RST_CTRL          0x5
-+#define AIF_SR_CTRL           0x6
-+
-+#define AIF1_CLK_CTRL         0x10
-+#define AIF1_ADCDAT_CTRL      0x11
-+#define AIF1_DACDAT_CTRL      0x12
-+#define AIF1_MXR_SRC          0x13
-+#define AIF1_VOL_CTRL1                0x14
-+#define AIF1_VOL_CTRL2                0x15
-+#define AIF1_VOL_CTRL3                0x16
-+#define AIF1_VOL_CTRL4                0x17
-+#define AIF1_MXR_GAIN         0x18
-+#define AIF1_RXD_CTRL         0x19
-+#define ADC_DIG_CTRL          0x40
-+#define ADC_VOL_CTRL          0x41
-+#define ADC_DBG_CTRL          0x42
-+
-+#define HMIC_CTRL1                    0x44
-+#define HMIC_CTRL2                    0x45
-+#define HMIC_STS                      0x46
-+
-+#define DAC_DIG_CTRL          0x48
-+#define DAC_VOL_CTRL          0x49
-+#define DAC_DBG_CTRL          0x4a
-+#define DAC_MXR_SRC                   0x4c
-+#define DAC_MXR_GAIN          0x4d
-+
-+#define ADC_APC_CTRL          0x50
-+#define ADC_SRC                               0x51
-+#define ADC_SRCBST_CTRL               0x52
-+#define OMIXER_DACA_CTRL      0x53
-+#define OMIXER_SR                     0x54
-+#define OMIXER_BST1_CTRL      0x55
-+#define HPOUT_CTRL                    0x56
-+#define ESPKOUT_CTRL          0x57
-+#define SPKOUT_CTRL                   0x58
-+#define LOUT_CTRL                     0x59
-+#define ADDA_TUNE1                    0x5a
-+#define ADDA_TUNE2                    0x5b
-+#define ADDA_TUNE3                    0x5c
-+#define HPOUT_STR                     0x5d
-+
-+/*CHIP_AUDIO_RST*/
-+#define AC101_CHIP_ID                 0x0101
-+
-+/*PLL_CTRL1*/
-+#define DPLL_DAC_BIAS         14
-+#define PLL_POSTDIV_M         8
-+#define CLOSE_LOOP            6
-+#define INT                   0
-+
-+/*PLL_CTRL2*/
-+#define PLL_EN                        15
-+#define PLL_LOCK_STATUS               14
-+#define PLL_PREDIV_NI         4
-+#define PLL_POSTDIV_NF                0
-+
-+/*SYSCLK_CTRL*/
-+#define PLLCLK_ENA                    15
-+#define PLLCLK_SRC                    12
-+#define AIF1CLK_ENA                   11
-+#define AIF1CLK_SRC                   8
-+#define AIF2CLK_ENA                   7
-+#define AIF2CLK_SRC                   4
-+#define SYSCLK_ENA                    3
-+#define SYSCLK_SRC                    0
-+
-+/*MOD_CLK_ENA*/
-+#define MOD_CLK_AIF1          15
-+#define MOD_CLK_AIF2          14
-+#define MOD_CLK_AIF3          13
-+#define MOD_CLK_SRC1          11
-+#define MOD_CLK_SRC2          10
-+#define MOD_CLK_HPF_AGC               7
-+#define MOD_CLK_HPF_DRC               6
-+#define MOD_CLK_ADC_DIG               3
-+#define MOD_CLK_DAC_DIG               2
-+
-+/*MOD_RST_CTRL*/
-+#define MOD_RESET_CTL         0
-+#define MOD_RESET_AIF1                15
-+#define MOD_RESET_AIF2                14
-+#define MOD_RESET_AIF3                13
-+#define MOD_RESET_SRC1                11
-+#define MOD_RESET_SRC2                10
-+#define MOD_RESET_HPF_AGC     7
-+#define MOD_RESET_HPF_DRC     6
-+#define MOD_RESET_ADC_DIG     3
-+#define MOD_RESET_DAC_DIG     2
-+
-+/*AIF_SR_CTRL*/
-+#define AIF1_FS                               12      //AIF1 Sample Rate
-+#define AIF2_FS                               8       //AIF2 Sample Rate
-+#define SRC1_ENA                      3
-+#define SRC1_SRC                      2
-+#define SRC2_ENA                      1
-+#define SRC2_SRC                      0
-+
-+/*AIF1LCK_CTRL*/
-+#define AIF1_MSTR_MOD         15
-+#define AIF1_BCLK_INV         14
-+#define AIF1_LRCK_INV         13
-+#define AIF1_BCLK_DIV         9
-+#define AIF1_LRCK_DIV         6
-+#define AIF1_WORK_SIZ         4
-+#define AIF1_DATA_FMT         2
-+#define DSP_MONO_PCM          1
-+#define AIF1_TDMM_ENA         0
-+
-+/*AIF1_ADCDAT_CTRL*/
-+#define AIF1_AD0L_ENA         15
-+#define AIF1_AD0R_ENA         14
-+#define AIF1_AD1L_ENA         13
-+#define AIF1_AD1R_ENA         12
-+#define AIF1_AD0L_SRC         10
-+#define AIF1_AD0R_SRC         8
-+#define AIF1_AD1L_SRC         6
-+#define AIF1_AD1R_SRC         4
-+#define AIF1_ADCP_ENA         3
-+#define AIF1_ADUL_ENA         2
-+#define AIF1_SLOT_SIZ         0
-+
-+/*AIF1_DACDAT_CTRL*/
-+#define AIF1_DA0L_ENA         15
-+#define AIF1_DA0R_ENA         14
-+#define AIF1_DA1L_ENA         13
-+#define AIF1_DA1R_ENA         12
-+#define AIF1_DA0L_SRC         10
-+#define AIF1_DA0R_SRC         8
-+#define AIF1_DA1L_SRC         6
-+#define AIF1_DA1R_SRC         4
-+#define AIF1_DACP_ENA         3
-+#define AIF1_DAUL_ENA         2
-+#define AIF1_SLOT_SIZ         0
-+
-+/*AIF1_MXR_SRC*/
-+#define AIF1_AD0L_AIF1_DA0L_MXR               15
-+#define AIF1_AD0L_AIF2_DACL_MXR               14
-+#define AIF1_AD0L_ADCL_MXR            13
-+#define AIF1_AD0L_AIF2_DACR_MXR               12
-+#define AIF1_AD0R_AIF1_DA0R_MXR               11
-+#define AIF1_AD0R_AIF2_DACR_MXR               10
-+#define AIF1_AD0R_ADCR_MXR            9
-+#define AIF1_AD0R_AIF2_DACL_MXR               8
-+#define AIF1_AD1L_AIF2_DACL_MXR               7
-+#define AIF1_AD1L_ADCL_MXR            6
-+#define AIF1_AD1L_MXR_SRC     6
-+#define AIF1_AD1R_AIF2_DACR_MXR               3
-+#define AIF1_AD1R_ADCR_MXR            2
-+#define AIF1_AD1R_MXR_SRC     2
-+
-+/*AIF1_VOL_CTRL1*/
-+#define AIF1_AD0L_VOL         8
-+#define AIF1_AD0R_VOL         0
-+
-+/*AIF1_VOL_CTRL2*/
-+#define AIF1_AD1L_VOL         8
-+#define AIF1_AD1R_VOL         0
-+
-+/*AIF1_VOL_CTRL3*/
-+#define AIF1_DA0L_VOL         8
-+#define AIF1_DA0R_VOL         0
-+
-+/*AIF1_VOL_CTRL4*/
-+#define AIF1_DA1L_VOL         8
-+#define AIF1_DA1R_VOL                 0
-+
-+/*AIF1_MXR_GAIN*/
-+#define AIF1_AD0L_MXR_GAIN    12
-+#define AIF1_AD0R_MXR_GAIN    8
-+#define AIF1_AD1L_MXR_GAIN    6
-+#define AIF1_AD1R_MXR_GAIN    2
-+
-+/*AIF1_RXD_CTRL*/
-+#define AIF1_N_DATA_DISCARD   8
-+
-+/*ADC_DIG_CTRL*/
-+#define ENAD                          15
-+#define ENDM                          14
-+#define ADFIR32                               13
-+#define ADOUT_DTS                     2
-+#define ADOUT_DLY                     1
-+
-+/*ADC_VOL_CTRL*/
-+#define ADC_VOL_L                     8
-+#define ADC_VOL_R                     0
-+
-+/*ADC_DBG_CTRL*/
-+#define ADSW                          15
-+#define DMIC_CLK_PIN_CTRL     12
-+
-+/*HMIC_CTRL1*/
-+#define HMIC_M                                12
-+#define HMIC_N                                8
-+#define HMIC_DATA_IRQ_MODE    7
-+#define HMIC_TH1_HYSTERESIS   5
-+#define HMIC_PULLOUT_IRQ      4
-+#define HMIC_PLUGIN_IRQ               3
-+#define HMIC_KEYUP_IRQ                2
-+#define HMIC_KEYDOWN_IRQ      1
-+#define HMIC_DATA_IRQ_EN      0
-+
-+/*HMIC_CTRL2*/
-+#define HMIC_SAMPLE_SELECT    14
-+#define HMIC_TH2_HYSTERESIS   13
-+#define HMIC_TH2                      8
-+#define HMIC_SF                               6
-+#define KEYUP_CLEAR                   5
-+#define HMIC_TH1                      0
-+
-+/*HMIC_STS*/
-+#define HMIC_DATA                     8
-+#define GET_HMIC_DATA(r)              (((r) >> HMIC_DATA) & 0x1F)
-+#define HMIC_PULLOUT_PEND     4
-+#define HMIC_PLUGIN_PEND      3
-+#define HMIC_KEYUP_PEND               2
-+#define HMKC_KEYDOWN_PEND     1
-+#define HMIC_DATA_PEND                0
-+#define HMIC_PEND_ALL         (0x1F)
-+
-+/*DAC_DIG_CTRL*/
-+#define ENDA                          15
-+#define ENHPF                         14
-+#define DAFIR32                               13
-+#define MODQU                         8
-+
-+/*DAC_VOL_CTRL*/
-+#define DAC_VOL_L                     8
-+#define DAC_VOL_R                     0
-+
-+/*DAC_DBG_CTRL*/
-+#define DASW                          15
-+#define ENDWA_N                               14
-+#define DAC_MOD_DBG                   13
-+#define DAC_PTN_SEL                   6
-+#define DVC                           0
-+
-+/*DAC_MXR_SRC*/
-+#define DACL_MXR_AIF1_DA0L            15
-+#define DACL_MXR_AIF1_DA1L            14
-+#define DACL_MXR_AIF2_DACL            13
-+#define DACL_MXR_ADCL                 12
-+#define DACL_MXR_SRC                  12
-+#define DACR_MXR_AIF1_DA0R            11
-+#define DACR_MXR_AIF1_DA1R            10
-+#define DACR_MXR_AIF2_DACR            9
-+#define DACR_MXR_ADCR                 8
-+#define DACR_MXR_SRC          8
-+
-+/*DAC_MXR_GAIN*/
-+#define DACL_MXR_GAIN         12
-+#define DACR_MXR_GAIN         8
-+
-+/*ADC_APC_CTRL*/
-+#define ADCREN                                15
-+#define ADCRG                         12
-+#define ADCLEN                                11
-+#define ADCLG                         8
-+#define MBIASEN                               7
-+#define MMIC_BIAS_CHOP_EN             6
-+#define MMIC_BIAS_CHOP_CKS            4
-+#define HBIASMOD                      2
-+#define HBIASEN                               1
-+#define HBIASADCEN                    0
-+
-+/*ADC_SRC*/
-+#define RADCMIXMUTEMIC1BOOST    (13)
-+#define RADCMIXMUTEMIC2BOOST    (12)
-+#define RADCMIXMUTELINEINLR             (11)
-+#define RADCMIXMUTELINEINR              (10)
-+#define RADCMIXMUTEAUXINR               (9)
-+#define RADCMIXMUTEROUTPUT              (8)
-+#define RADCMIXMUTELOUTPUT              (7)
-+#define LADCMIXMUTEMIC1BOOST    (6)
-+#define LADCMIXMUTEMIC2BOOST    (5)
-+#define LADCMIXMUTELINEINLR             (4)
-+#define LADCMIXMUTELINEINL              (3)
-+#define LADCMIXMUTEAUXINL               (2)
-+#define LADCMIXMUTELOUTPUT              (1)
-+#define LADCMIXMUTEROUTPUT              (0)
-+
-+/*ADC_SRCBST_CTRL*/
-+#define MIC1AMPEN                     15
-+#define ADC_MIC1G                     12
-+#define MIC2AMPEN                     11
-+#define ADC_MIC2G                     8
-+#define MIC2SLT                               7
-+#define LINEIN_PREG                   4
-+#define AUXI_PREG                     0
-+
-+/*OMIXER_DACA_CTRL*/
-+#define DACAREN                               15
-+#define DACALEN                               14
-+#define RMIXEN                                13
-+#define LMIXEN                                12
-+#define HPOUTPUTENABLE                        8
-+
-+/*OMIXER_SR*/
-+#define RMIXMUTEMIC1BOOST               (13)
-+#define RMIXMUTEMIC2BOOST               (12)
-+#define RMIXMUTELINEINLR                (11)
-+#define RMIXMUTELINEINR                         (10)
-+#define RMIXMUTEAUXINR                          (9)
-+#define RMIXMUTEDACR                    (8)
-+#define RMIXMUTEDACL                    (7)
-+#define LMIXMUTEMIC1BOOST               (6)
-+#define LMIXMUTEMIC2BOOST               (5)
-+#define LMIXMUTELINEINLR                (4)
-+#define LMIXMUTELINEINL                         (3)
-+#define LMIXMUTEAUXINL                          (2)
-+#define LMIXMUTEDACL                    (1)
-+#define LMIXMUTEDACR                    (0)
-+
-+/*OMIXER_BST1_CTRL*/
-+#define BIASVOLTAGE                   12
-+#define AXG                           9
-+#define OMIXER_MIC1G                  6
-+#define OMIXER_MIC2G                  3
-+#define LINEING                               0
-+
-+/*HPOUT_CTRL*/
-+#define RHPS                          15
-+#define LHPS                          14
-+#define RHPPA_MUTE                    13
-+#define LHPPA_MUTE                    12
-+#define HPPA_EN                               11
-+#define HP_VOL                                4
-+#define HPPA_DEL                      2
-+#define HPPA_IS                               0
-+
-+/*ESPKOUT_CTRL*/
-+#define EAR_RAMP_TIME         11
-+#define       ESPA_OUT_CURRENT        9
-+#define ESPSR                         7
-+#define ESPPA_MUTE                    6
-+#define ESPPA_EN                      5
-+#define ESP_VOL                               0
-+
-+/*SPKOUT_CTRL*/
-+#define HPCALICKS                     13
-+#define RSPKS                         12
-+#define RSPKINVEN                     11
-+#define RSPK_EN                               9
-+#define LSPKS                         8
-+#define LSPKINVEN                     7
-+#define LSPK_EN                               5
-+#define SPK_VOL                               0
-+
-+/*LOUT_CTRL*/
-+#define LINEOUTG                      5
-+#define LINEOUTEN                     4
-+#define LINEOUTS0                     3
-+#define LINEOUTS1                     2
-+#define LINEOUTS2                     1
-+#define LINEOUTS3                     0
-+
-+/*ADDA_TUNE1*/
-+#define CURRENT_TEST_SELECT   14
-+#define BIHE_CTRL                     12
-+#define DITHER                                11
-+#define DITHER_CLK                    9
-+#define ZERO_CROSSOVER_EN     8
-+#define ZERO_CROSSOVER_TIME 7
-+#define EAR_SPEED_SELECT      6
-+#define REF_CHOPPEN_CKS               4
-+#define OPMIC_BIAS_CUR                0
-+
-+/*ADDA_TUNE2*/
-+#define OPDAC_BIAS_CUR                14
-+#define OPDRV_BIAS_CUR                12
-+#define OPMIX_BIAS_CUR                10
-+#define OPEAR_BIAS_CUR                8
-+#define OPVR_BIAS_CUR         6
-+#define OPAAF_BIAS_CUR                4
-+#define OPADC1_BIAS_CUR               2
-+#define OPADC2_BIAS_CUR               0
-+
-+/*ADDA_TUNE3*/
-+#define LDOEN                         15
-+#define LDO_SEL                               12
-+#define BIASCALIVERIFY                        11
-+#define BIASMODE                      10
-+#define BIASCALIDATA                  9
-+#define OSCS                          1
-+#define OSCEN                         0
-+
-+/*HPOUT_STR*/
-+#define HPVL_SOFT_MOD         14
-+#define       HPVL_STEP_CTRL          8
-+#define  DACA_CHND_ENA                7
-+#define HPPA_MXRD_ENA         6
-+#define HPVL_CTRL_OUT         0
-+
-+#endif//__AC101_REGS_H__
---- /dev/null
-+++ b/sound/soc/codecs/ac108.c
-@@ -0,0 +1,1622 @@
-+/*
-+ * ac10x.c  --  ac10x ALSA SoC Audio driver
-+ *
-+ *
-+ * Author: Baozhu Zuo<zuobaozhu@gmail.com>
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License version 2 as
-+ * published by the Free Software Foundation.
-+ */
-+#include <linux/clk.h>
-+#include <linux/delay.h>
-+#include <linux/gpio/consumer.h>
-+#include <linux/i2c.h>
-+#include <linux/init.h>
-+#include <linux/module.h>
-+#include <linux/moduleparam.h>
-+#include <linux/pm.h>
-+#include <linux/regmap.h>
-+#include <linux/slab.h>
-+#include <linux/workqueue.h>
-+#include <sound/core.h>
-+#include <sound/initval.h>
-+#include <sound/pcm.h>
-+#include <sound/pcm_params.h>
-+#include <sound/soc.h>
-+#include <sound/tlv.h>
-+
-+#include "ac108.h"
-+#include "ac10x.h"
-+
-+#define _USE_CAPTURE  1
-+#define _MASTER_INDEX 0
-+
-+/* #undef DEBUG
-+ * use 'make DEBUG=1' to enable debugging
-+ */
-+
-+/**
-+ * TODO:
-+ * 1, add PM API:  ac108_suspend,ac108_resume
-+ * 2,0x65-0x6a
-+ * 3,0x76-0x79 high 4bit
-+ */
-+struct pll_div {
-+      unsigned int freq_in;
-+      unsigned int freq_out;
-+      unsigned int m1;
-+      unsigned int m2;
-+      unsigned int n;
-+      unsigned int k1;
-+      unsigned int k2;
-+};
-+
-+static struct ac10x_priv *ac10x;
-+
-+struct real_val_to_reg_val {
-+      unsigned int real_val;
-+      unsigned int reg_val;
-+};
-+
-+static const struct real_val_to_reg_val ac108_sample_rate[] = {
-+      { 8000,  0 },
-+      { 11025, 1 },
-+      { 12000, 2 },
-+      { 16000, 3 },
-+      { 22050, 4 },
-+      { 24000, 5 },
-+      { 32000, 6 },
-+      { 44100, 7 },
-+      { 48000, 8 },
-+      { 96000, 9 },
-+};
-+
-+/* Sample resolution */
-+static const struct real_val_to_reg_val ac108_samp_res[] = {
-+      { 8,  1 },
-+      { 12, 2 },
-+      { 16, 3 },
-+      { 20, 4 },
-+      { 24, 5 },
-+      { 28, 6 },
-+      { 32, 7 },
-+};
-+
-+static const unsigned int ac108_bclkdivs[] = {
-+      0,   1,   2,   4,
-+      6,   8,  12,  16,
-+      24,  32,  48,  64,
-+      96, 128, 176, 192,
-+};
-+
-+/* FOUT =(FIN * N) / [(M1+1) * (M2+1)*(K1+1)*(K2+1)] ;        M1[0,31],  M2[0,1],  N[0,1023],  K1[0,31],  K2[0,1] */
-+static const struct pll_div ac108_pll_div_list[] = {
-+      { 400000,   _FREQ_24_576K, 0,  0, 614, 4, 1 },
-+      { 512000,   _FREQ_24_576K, 0,  0, 960, 9, 1 }, /* _FREQ_24_576K/48 */
-+      { 768000,   _FREQ_24_576K, 0,  0, 640, 9, 1 }, /* _FREQ_24_576K/32 */
-+      { 800000,   _FREQ_24_576K, 0,  0, 614, 9, 1 },
-+      { 1024000,  _FREQ_24_576K, 0,  0, 480, 9, 1 }, /* _FREQ_24_576K/24 */
-+      { 1600000,  _FREQ_24_576K, 0,  0, 307, 9, 1 },
-+      { 2048000,  _FREQ_24_576K, 0,  0, 240, 9, 1 }, /* accurate,  8000 * 256 */
-+      { 3072000,  _FREQ_24_576K, 0,  0, 160, 9, 1 }, /* accurate, 12000 * 256 */
-+      { 4096000,  _FREQ_24_576K, 2,  0, 360, 9, 1 }, /* accurate, 16000 * 256 */
-+      { 6000000,  _FREQ_24_576K, 4,  0, 410, 9, 1 },
-+      { 12000000, _FREQ_24_576K, 9,  0, 410, 9, 1 },
-+      { 13000000, _FREQ_24_576K, 8,  0, 340, 9, 1 },
-+      { 15360000, _FREQ_24_576K, 12, 0, 415, 9, 1 },
-+      { 16000000, _FREQ_24_576K, 12, 0, 400, 9, 1 },
-+      { 19200000, _FREQ_24_576K, 15, 0, 410, 9, 1 },
-+      { 19680000, _FREQ_24_576K, 15, 0, 400, 9, 1 },
-+      { 24000000, _FREQ_24_576K, 9,  0, 256,24, 0 }, /* accurate, 24M -> 24.576M */
-+
-+      { 400000,   _FREQ_22_579K, 0,  0, 566, 4, 1 },
-+      { 512000,   _FREQ_22_579K, 0,  0, 880, 9, 1 },
-+      { 768000,   _FREQ_22_579K, 0,  0, 587, 9, 1 },
-+      { 800000,   _FREQ_22_579K, 0,  0, 567, 9, 1 },
-+      { 1024000,  _FREQ_22_579K, 0,  0, 440, 9, 1 },
-+      { 1600000,  _FREQ_22_579K, 1,  0, 567, 9, 1 },
-+      { 2048000,  _FREQ_22_579K, 0,  0, 220, 9, 1 },
-+      { 3072000,  _FREQ_22_579K, 0,  0, 148, 9, 1 },
-+      { 4096000,  _FREQ_22_579K, 2,  0, 330, 9, 1 },
-+      { 6000000,  _FREQ_22_579K, 2,  0, 227, 9, 1 },
-+      { 12000000, _FREQ_22_579K, 8,  0, 340, 9, 1 },
-+      { 13000000, _FREQ_22_579K, 9,  0, 350, 9, 1 },
-+      { 15360000, _FREQ_22_579K, 10, 0, 325, 9, 1 },
-+      { 16000000, _FREQ_22_579K, 11, 0, 340, 9, 1 },
-+      { 19200000, _FREQ_22_579K, 13, 0, 330, 9, 1 },
-+      { 19680000, _FREQ_22_579K, 14, 0, 345, 9, 1 },
-+      { 24000000, _FREQ_22_579K, 24, 0, 588,24, 0 }, /* accurate, 24M -> 22.5792M */
-+
-+
-+      { _FREQ_24_576K / 1,   _FREQ_24_576K, 9,  0, 200, 9, 1 }, /* _FREQ_24_576K */
-+      { _FREQ_24_576K / 2,   _FREQ_24_576K, 9,  0, 400, 9, 1 }, /* 12288000,accurate, 48000 * 256 */
-+      { _FREQ_24_576K / 4,   _FREQ_24_576K, 4,  0, 400, 9, 1 }, /* 6144000, accurate, 24000 * 256 */
-+      { _FREQ_24_576K / 16,  _FREQ_24_576K, 0,  0, 320, 9, 1 }, /* 1536000 */
-+      { _FREQ_24_576K / 64,  _FREQ_24_576K, 0,  0, 640, 4, 1 }, /* 384000 */
-+      { _FREQ_24_576K / 96,  _FREQ_24_576K, 0,  0, 960, 4, 1 }, /* 256000 */
-+      { _FREQ_24_576K / 128, _FREQ_24_576K, 0,  0, 512, 1, 1 }, /* 192000 */
-+      { _FREQ_24_576K / 176, _FREQ_24_576K, 0,  0, 880, 4, 0 }, /* 140000 */
-+      { _FREQ_24_576K / 192, _FREQ_24_576K, 0,  0, 960, 4, 0 }, /* 128000 */
-+
-+      { _FREQ_22_579K / 1,   _FREQ_22_579K, 9,  0, 200, 9, 1 }, /* _FREQ_22_579K */
-+      { _FREQ_22_579K / 2,   _FREQ_22_579K, 9,  0, 400, 9, 1 }, /* 11289600,accurate, 44100 * 256 */
-+      { _FREQ_22_579K / 4,   _FREQ_22_579K, 4,  0, 400, 9, 1 }, /* 5644800, accurate, 22050 * 256 */
-+      { _FREQ_22_579K / 16,  _FREQ_22_579K, 0,  0, 320, 9, 1 }, /* 1411200 */
-+      { _FREQ_22_579K / 64,  _FREQ_22_579K, 0,  0, 640, 4, 1 }, /* 352800 */
-+      { _FREQ_22_579K / 96,  _FREQ_22_579K, 0,  0, 960, 4, 1 }, /* 235200 */
-+      { _FREQ_22_579K / 128, _FREQ_22_579K, 0,  0, 512, 1, 1 }, /* 176400 */
-+      { _FREQ_22_579K / 176, _FREQ_22_579K, 0,  0, 880, 4, 0 }, /* 128290 */
-+      { _FREQ_22_579K / 192, _FREQ_22_579K, 0,  0, 960, 4, 0 }, /* 117600 */
-+
-+      { _FREQ_22_579K / 6,   _FREQ_22_579K, 2,  0, 360, 9, 1 }, /* 3763200 */
-+      { _FREQ_22_579K / 8,   _FREQ_22_579K, 0,  0, 160, 9, 1 }, /* 2822400, accurate, 11025 * 256 */
-+      { _FREQ_22_579K / 12,  _FREQ_22_579K, 0,  0, 240, 9, 1 }, /* 1881600 */
-+      { _FREQ_22_579K / 24,  _FREQ_22_579K, 0,  0, 480, 9, 1 }, /* 940800 */
-+      { _FREQ_22_579K / 32,  _FREQ_22_579K, 0,  0, 640, 9, 1 }, /* 705600 */
-+      { _FREQ_22_579K / 48,  _FREQ_22_579K, 0,  0, 960, 9, 1 }, /* 470400 */
-+};
-+
-+
-+/* AC108 definition */
-+#define AC108_CHANNELS_MAX            8               /* range[1, 16] */
-+#define AC108_RATES                   (SNDRV_PCM_RATE_8000_96000 &            \
-+                                      ~(SNDRV_PCM_RATE_64000 | \
-+                                      SNDRV_PCM_RATE_88200 | SNDRV_PCM_RATE_96000))
-+#define AC108_FORMATS                 (SNDRV_PCM_FMTBIT_S16_LE | \
-+                                      /*SNDRV_PCM_FMTBIT_S20_3LE |   \
-+                                      SNDRV_PCM_FMTBIT_S24_LE |*/  \
-+                                      SNDRV_PCM_FMTBIT_S32_LE)
-+
-+static const DECLARE_TLV_DB_SCALE(tlv_adc_pga_gain, 0, 100, 0);
-+static const DECLARE_TLV_DB_SCALE(tlv_ch_digital_vol, -11925, 75, 0);
-+
-+int ac10x_read(u8 reg, u8* rt_val, struct regmap* i2cm)
-+{
-+      int r, v = 0;
-+
-+      if ((r = regmap_read(i2cm, reg, &v)) < 0)
-+              pr_info("ac10x_read info->[REG-0x%02x]\n", reg);
-+      else
-+              *rt_val = v;
-+      return r;
-+}
-+
-+int ac10x_write(u8 reg, u8 val, struct regmap* i2cm)
-+{
-+      int r;
-+
-+      if ((r = regmap_write(i2cm, reg, val)) < 0)
-+              pr_info("ac10x_write info->[REG-0x%02x,val-0x%02x]\n", reg, val);
-+      return r;
-+}
-+
-+int ac10x_update_bits(u8 reg, u8 mask, u8 val, struct regmap* i2cm)
-+{
-+      int r;
-+
-+      if ((r = regmap_update_bits(i2cm, reg, mask, val)) < 0)
-+              pr_info("%s() info->[REG-0x%02x,val-0x%02x]\n", __func__, reg, val);
-+      return r;
-+}
-+
-+/**
-+ * snd_ac108_get_volsw - single mixer get callback
-+ * @kcontrol: mixer control
-+ * @ucontrol: control element information
-+ *
-+ * Callback to get the value of a single mixer control, or a double mixer
-+ * control that spans 2 registers.
-+ *
-+ * Returns 0 for success.
-+ */
-+static int snd_ac108_get_volsw(struct snd_kcontrol *kcontrol,
-+      struct snd_ctl_elem_value *ucontrol)
-+{
-+      struct soc_mixer_control *mc =
-+              (struct soc_mixer_control *)kcontrol->private_value;
-+      unsigned int mask = (1 << fls(mc->max)) - 1;
-+      unsigned int invert = mc->invert;
-+      int ret, chip = mc->autodisable;
-+      u8 val;
-+
-+      if ((ret = ac10x_read(mc->reg, &val, ac10x->i2cmap[chip])) < 0)
-+              return ret;
-+
-+      val = ((val >> mc->shift) & mask) - mc->min;
-+      if (invert) {
-+              val = mc->max - val;
-+      }
-+      ucontrol->value.integer.value[0] = val;
-+      return 0;
-+}
-+
-+/**
-+ * snd_ac108_put_volsw - single mixer put callback
-+ * @kcontrol: mixer control
-+ * @ucontrol: control element information
-+ *
-+ * Callback to set the value of a single mixer control, or a double mixer
-+ * control that spans 2 registers.
-+ *
-+ * Returns 0 for success.
-+ */
-+static int snd_ac108_put_volsw(struct snd_kcontrol *kcontrol,
-+      struct snd_ctl_elem_value *ucontrol)
-+{
-+      struct soc_mixer_control *mc =
-+              (struct soc_mixer_control *)kcontrol->private_value;
-+      unsigned int sign_bit = mc->sign_bit;
-+      unsigned int val, mask = (1 << fls(mc->max)) - 1;
-+      unsigned int invert = mc->invert;
-+      int ret, chip = mc->autodisable;
-+
-+      if (sign_bit)
-+              mask = BIT(sign_bit + 1) - 1;
-+
-+      val = ((ucontrol->value.integer.value[0] + mc->min) & mask);
-+      if (invert) {
-+              val = mc->max - val;
-+      }
-+
-+      mask = mask << mc->shift;
-+      val = val << mc->shift;
-+
-+      ret = ac10x_update_bits(mc->reg, mask, val, ac10x->i2cmap[chip]);
-+      return ret;
-+}
-+
-+#define SOC_AC108_SINGLE_TLV(xname, reg, shift, max, invert, chip, tlv_array) \
-+{     .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \
-+      .access = SNDRV_CTL_ELEM_ACCESS_TLV_READ |\
-+               SNDRV_CTL_ELEM_ACCESS_READWRITE,\
-+      .tlv.p = (tlv_array), \
-+      .info = snd_soc_info_volsw, .get = snd_ac108_get_volsw,\
-+      .put = snd_ac108_put_volsw, \
-+      .private_value = SOC_SINGLE_VALUE(reg, shift, max, invert, chip) }
-+
-+/* single ac108 */
-+static const struct snd_kcontrol_new ac108_snd_controls[] = {
-+      /* ### chip 0 ### */
-+      /*0x70: ADC1 Digital Channel Volume Control Register*/
-+      SOC_AC108_SINGLE_TLV("CH1 digital volume", ADC1_DVOL_CTRL,
-+                           0, 0xff, 0, 0, tlv_ch_digital_vol),
-+      /*0x71: ADC2 Digital Channel Volume Control Register*/
-+      SOC_AC108_SINGLE_TLV("CH2 digital volume", ADC2_DVOL_CTRL,
-+                           0, 0xff, 0, 0, tlv_ch_digital_vol),
-+      /*0x72: ADC3 Digital Channel Volume Control Register*/
-+      SOC_AC108_SINGLE_TLV("CH3 digital volume", ADC3_DVOL_CTRL,
-+                           0, 0xff, 0, 0, tlv_ch_digital_vol),
-+      /*0x73: ADC4 Digital Channel Volume Control Register*/
-+      SOC_AC108_SINGLE_TLV("CH4 digital volume", ADC4_DVOL_CTRL,
-+                           0, 0xff, 0, 0, tlv_ch_digital_vol),
-+
-+      /*0x90: Analog PGA1 Control Register*/
-+      SOC_AC108_SINGLE_TLV("ADC1 PGA gain", ANA_PGA1_CTRL,
-+                           ADC1_ANALOG_PGA, 0x1f, 0, 0, tlv_adc_pga_gain),
-+      /*0x91: Analog PGA2 Control Register*/
-+      SOC_AC108_SINGLE_TLV("ADC2 PGA gain", ANA_PGA2_CTRL,
-+                           ADC2_ANALOG_PGA, 0x1f, 0, 0, tlv_adc_pga_gain),
-+      /*0x92: Analog PGA3 Control Register*/
-+      SOC_AC108_SINGLE_TLV("ADC3 PGA gain", ANA_PGA3_CTRL,
-+                           ADC3_ANALOG_PGA, 0x1f, 0, 0, tlv_adc_pga_gain),
-+      /*0x93: Analog PGA4 Control Register*/
-+      SOC_AC108_SINGLE_TLV("ADC4 PGA gain", ANA_PGA4_CTRL,
-+                           ADC4_ANALOG_PGA, 0x1f, 0, 0, tlv_adc_pga_gain),
-+};
-+/* multiple ac108s */
-+static const struct snd_kcontrol_new ac108tdm_snd_controls[] = {
-+      /* ### chip 1 ### */
-+      /*0x70: ADC1 Digital Channel Volume Control Register*/
-+      SOC_AC108_SINGLE_TLV("CH1 digital volume", ADC1_DVOL_CTRL,
-+                           0, 0xff, 0, 1, tlv_ch_digital_vol),
-+      /*0x71: ADC2 Digital Channel Volume Control Register*/
-+      SOC_AC108_SINGLE_TLV("CH2 digital volume", ADC2_DVOL_CTRL,
-+                           0, 0xff, 0, 1, tlv_ch_digital_vol),
-+      /*0x72: ADC3 Digital Channel Volume Control Register*/
-+      SOC_AC108_SINGLE_TLV("CH3 digital volume", ADC3_DVOL_CTRL,
-+                           0, 0xff, 0, 1, tlv_ch_digital_vol),
-+      /*0x73: ADC4 Digital Channel Volume Control Register*/
-+      SOC_AC108_SINGLE_TLV("CH4 digital volume", ADC4_DVOL_CTRL,
-+                           0, 0xff, 0, 1, tlv_ch_digital_vol),
-+
-+      /*0x90: Analog PGA1 Control Register*/
-+      SOC_AC108_SINGLE_TLV("ADC1 PGA gain", ANA_PGA1_CTRL,
-+                           ADC1_ANALOG_PGA, 0x1f, 0, 1, tlv_adc_pga_gain),
-+      /*0x91: Analog PGA2 Control Register*/
-+      SOC_AC108_SINGLE_TLV("ADC2 PGA gain", ANA_PGA2_CTRL,
-+                           ADC2_ANALOG_PGA, 0x1f, 0, 1, tlv_adc_pga_gain),
-+      /*0x92: Analog PGA3 Control Register*/
-+      SOC_AC108_SINGLE_TLV("ADC3 PGA gain", ANA_PGA3_CTRL,
-+                           ADC3_ANALOG_PGA, 0x1f, 0, 1, tlv_adc_pga_gain),
-+      /*0x93: Analog PGA4 Control Register*/
-+      SOC_AC108_SINGLE_TLV("ADC4 PGA gain", ANA_PGA4_CTRL,
-+                           ADC4_ANALOG_PGA, 0x1f, 0, 1, tlv_adc_pga_gain),
-+
-+      /* ### chip 0 ### */
-+      /*0x70: ADC1 Digital Channel Volume Control Register*/
-+      SOC_AC108_SINGLE_TLV("CH5 digital volume", ADC1_DVOL_CTRL,
-+                           0, 0xff, 0, 0, tlv_ch_digital_vol),
-+      /*0x71: ADC2 Digital Channel Volume Control Register*/
-+      SOC_AC108_SINGLE_TLV("CH6 digital volume", ADC2_DVOL_CTRL,
-+                           0, 0xff, 0, 0, tlv_ch_digital_vol),
-+      /*0x72: ADC3 Digital Channel Volume Control Register*/
-+      SOC_AC108_SINGLE_TLV("CH7 digital volume", ADC3_DVOL_CTRL,
-+                           0, 0xff, 0, 0, tlv_ch_digital_vol),
-+      /*0x73: ADC4 Digital Channel Volume Control Register*/
-+      SOC_AC108_SINGLE_TLV("CH8 digital volume", ADC4_DVOL_CTRL,
-+                           0, 0xff, 0, 0, tlv_ch_digital_vol),
-+
-+      /*0x90: Analog PGA1 Control Register*/
-+      SOC_AC108_SINGLE_TLV("ADC5 PGA gain", ANA_PGA1_CTRL,
-+                           ADC1_ANALOG_PGA, 0x1f, 0, 0, tlv_adc_pga_gain),
-+      /*0x91: Analog PGA2 Control Register*/
-+      SOC_AC108_SINGLE_TLV("ADC6 PGA gain", ANA_PGA2_CTRL,
-+                           ADC2_ANALOG_PGA, 0x1f, 0, 0, tlv_adc_pga_gain),
-+      /*0x92: Analog PGA3 Control Register*/
-+      SOC_AC108_SINGLE_TLV("ADC7 PGA gain", ANA_PGA3_CTRL,
-+                           ADC3_ANALOG_PGA, 0x1f, 0, 0, tlv_adc_pga_gain),
-+      /*0x93: Analog PGA4 Control Register*/
-+      SOC_AC108_SINGLE_TLV("ADC8 PGA gain", ANA_PGA4_CTRL,
-+                           ADC4_ANALOG_PGA, 0x1f, 0, 0, tlv_adc_pga_gain),
-+};
-+
-+
-+static const struct snd_soc_dapm_widget ac108_dapm_widgets[] = {
-+      /* input widgets */
-+      SND_SOC_DAPM_INPUT("MIC1P"),
-+      SND_SOC_DAPM_INPUT("MIC1N"),
-+
-+      SND_SOC_DAPM_INPUT("MIC2P"),
-+      SND_SOC_DAPM_INPUT("MIC2N"),
-+
-+      SND_SOC_DAPM_INPUT("MIC3P"),
-+      SND_SOC_DAPM_INPUT("MIC3N"),
-+
-+      SND_SOC_DAPM_INPUT("MIC4P"),
-+      SND_SOC_DAPM_INPUT("MIC4N"),
-+
-+      SND_SOC_DAPM_INPUT("DMIC1"),
-+      SND_SOC_DAPM_INPUT("DMIC2"),
-+
-+      /*0xa0: ADC1 Analog Control 1 Register*/
-+      /*0xa1-0xa6:use the defualt value*/
-+      SND_SOC_DAPM_AIF_IN("Channel 1 AAF", "Capture", 0, ANA_ADC1_CTRL1, ADC1_DSM_ENABLE, 1),
-+      SND_SOC_DAPM_SUPPLY("Channel 1 EN", ANA_ADC1_CTRL1, ADC1_PGA_ENABLE, 1, NULL, 0),
-+      SND_SOC_DAPM_MICBIAS("MIC1BIAS", ANA_ADC1_CTRL1, ADC1_MICBIAS_EN, 1),
-+
-+      /*0xa7: ADC2 Analog Control 1 Register*/
-+      /*0xa8-0xad:use the defualt value*/
-+      SND_SOC_DAPM_AIF_IN("Channel 2 AAF", "Capture", 0, ANA_ADC2_CTRL1, ADC2_DSM_ENABLE, 1),
-+      SND_SOC_DAPM_SUPPLY("Channel 2 EN", ANA_ADC2_CTRL1, ADC2_PGA_ENABLE, 1, NULL, 0),
-+      SND_SOC_DAPM_MICBIAS("MIC2BIAS", ANA_ADC2_CTRL1, ADC2_MICBIAS_EN, 1),
-+
-+      /*0xae: ADC3 Analog Control 1 Register*/
-+      /*0xaf-0xb4:use the defualt value*/
-+      SND_SOC_DAPM_AIF_IN("Channel 3 AAF", "Capture", 0, ANA_ADC3_CTRL1, ADC3_DSM_ENABLE, 1),
-+      SND_SOC_DAPM_SUPPLY("Channel 3 EN", ANA_ADC3_CTRL1, ADC3_PGA_ENABLE, 1, NULL, 0),
-+      SND_SOC_DAPM_MICBIAS("MIC3BIAS", ANA_ADC3_CTRL1, ADC3_MICBIAS_EN, 1),
-+
-+      /*0xb5: ADC4 Analog Control 1 Register*/
-+      /*0xb6-0xbb:use the defualt value*/
-+      SND_SOC_DAPM_AIF_IN("Channel 4 AAF", "Capture", 0, ANA_ADC4_CTRL1, ADC4_DSM_ENABLE, 1),
-+      SND_SOC_DAPM_SUPPLY("Channel 4 EN", ANA_ADC4_CTRL1, ADC4_PGA_ENABLE, 1, NULL, 0),
-+      SND_SOC_DAPM_MICBIAS("MIC4BIAS", ANA_ADC4_CTRL1, ADC4_MICBIAS_EN, 1),
-+
-+
-+      /*0x61: ADC Digital Part Enable Register*/
-+      SND_SOC_DAPM_SUPPLY("ADC EN", ADC_DIG_EN, 4,  1, NULL, 0),
-+      SND_SOC_DAPM_ADC("ADC1", "Capture", ADC_DIG_EN, 0,  1),
-+      SND_SOC_DAPM_ADC("ADC2", "Capture", ADC_DIG_EN, 1,  1),
-+      SND_SOC_DAPM_ADC("ADC3", "Capture", ADC_DIG_EN, 2,  1),
-+      SND_SOC_DAPM_ADC("ADC4", "Capture", ADC_DIG_EN, 3,  1),
-+
-+      SND_SOC_DAPM_SUPPLY("ADC1 CLK", ANA_ADC4_CTRL7, ADC1_CLK_GATING, 1, NULL, 0),
-+      SND_SOC_DAPM_SUPPLY("ADC2 CLK", ANA_ADC4_CTRL7, ADC2_CLK_GATING, 1, NULL, 0),
-+      SND_SOC_DAPM_SUPPLY("ADC3 CLK", ANA_ADC4_CTRL7, ADC3_CLK_GATING, 1, NULL, 0),
-+      SND_SOC_DAPM_SUPPLY("ADC4 CLK", ANA_ADC4_CTRL7, ADC4_CLK_GATING, 1, NULL, 0),
-+
-+      SND_SOC_DAPM_SUPPLY("DSM EN", ANA_ADC4_CTRL6, DSM_DEMOFF, 1, NULL, 0),
-+
-+      /*0x62:Digital MIC Enable Register*/
-+      SND_SOC_DAPM_MICBIAS("DMIC1 enable", DMIC_EN, 0, 0),
-+      SND_SOC_DAPM_MICBIAS("DMIC2 enable", DMIC_EN, 1, 0),
-+};
-+
-+static const struct snd_soc_dapm_route ac108_dapm_routes[] = {
-+
-+      { "ADC1", NULL, "Channel 1 AAF" },
-+      { "ADC2", NULL, "Channel 2 AAF" },
-+      { "ADC3", NULL, "Channel 3 AAF" },
-+      { "ADC4", NULL, "Channel 4 AAF" },
-+
-+      { "Channel 1 AAF", NULL, "MIC1BIAS" },
-+      { "Channel 2 AAF", NULL, "MIC2BIAS" },
-+      { "Channel 3 AAF", NULL, "MIC3BIAS" },
-+      { "Channel 4 AAF", NULL, "MIC4BIAS" },
-+
-+      { "MIC1BIAS", NULL, "ADC1 CLK" },
-+      { "MIC2BIAS", NULL, "ADC2 CLK" },
-+      { "MIC3BIAS", NULL, "ADC3 CLK" },
-+      { "MIC4BIAS", NULL, "ADC4 CLK" },
-+
-+
-+      { "ADC1 CLK", NULL, "DSM EN" },
-+      { "ADC2 CLK", NULL, "DSM EN" },
-+      { "ADC3 CLK", NULL, "DSM EN" },
-+      { "ADC4 CLK", NULL, "DSM EN" },
-+
-+
-+      { "DSM EN", NULL, "ADC EN" },
-+
-+      { "Channel 1 EN", NULL, "DSM EN" },
-+      { "Channel 2 EN", NULL, "DSM EN" },
-+      { "Channel 3 EN", NULL, "DSM EN" },
-+      { "Channel 4 EN", NULL, "DSM EN" },
-+
-+
-+      { "MIC1P", NULL, "Channel 1 EN" },
-+      { "MIC1N", NULL, "Channel 1 EN" },
-+
-+      { "MIC2P", NULL, "Channel 2 EN" },
-+      { "MIC2N", NULL, "Channel 2 EN" },
-+
-+      { "MIC3P", NULL, "Channel 3 EN" },
-+      { "MIC3N", NULL, "Channel 3 EN" },
-+
-+      { "MIC4P", NULL, "Channel 4 EN" },
-+      { "MIC4N", NULL, "Channel 4 EN" },
-+
-+};
-+
-+static int ac108_multi_write(u8 reg, u8 val, struct ac10x_priv *ac10x)
-+{
-+      u8 i;
-+      for (i = 0; i < ac10x->codec_cnt; i++)
-+              ac10x_write(reg, val, ac10x->i2cmap[i]);
-+      return 0;
-+}
-+
-+static int ac108_multi_update_bits(u8 reg, u8 mask, u8 val, struct ac10x_priv *ac10x)
-+{
-+      int r = 0;
-+      u8 i;
-+      for (i = 0; i < ac10x->codec_cnt; i++)
-+              r |= ac10x_update_bits(reg, mask, val, ac10x->i2cmap[i]);
-+      return r;
-+}
-+
-+static unsigned int ac108_codec_read(struct snd_soc_codec *codec, unsigned int reg)
-+{
-+      unsigned char val_r;
-+      struct ac10x_priv *ac10x = dev_get_drvdata(codec->dev);
-+      /*read one chip is fine*/
-+      ac10x_read(reg, &val_r, ac10x->i2cmap[_MASTER_INDEX]);
-+      return val_r;
-+}
-+
-+static int ac108_codec_write(struct snd_soc_codec *codec, unsigned int reg, unsigned int val)
-+{
-+      struct ac10x_priv *ac10x = dev_get_drvdata(codec->dev);
-+      ac108_multi_write(reg, val, ac10x);
-+      return 0;
-+}
-+
-+/**
-+ * The Power management related registers are Reg01h~Reg09h
-+ * 0x01-0x05,0x08,use the default value
-+ * @author baozhu (17-6-21)
-+ *
-+ * @param ac10x
-+ */
-+static void ac108_configure_power(struct ac10x_priv *ac10x)
-+{
-+      /**
-+       * 0x06:Enable Analog LDO
-+       */
-+      ac108_multi_update_bits(PWR_CTRL6, 0x01 << LDO33ANA_ENABLE, 0x01 << LDO33ANA_ENABLE, ac10x);
-+      /**
-+       * 0x07: 
-+       * Control VREF output and micbias voltage ?
-+       * REF faststart disable, enable Enable VREF (needed for Analog
-+       * LDO and MICBIAS)
-+       */
-+      ac108_multi_update_bits(PWR_CTRL7,
-+                              0x1f << VREF_SEL | 0x01 << VREF_FASTSTART_ENABLE |
-+                              0x01 << VREF_ENABLE,
-+                              0x13 << VREF_SEL | 0x00 << VREF_FASTSTART_ENABLE |
-+                              0x01 << VREF_ENABLE,
-+                              ac10x);
-+      /**
-+       * 0x09:
-+       * Disable fast-start circuit on VREFP
-+       * VREFP_RESCTRL=00=1 MOhm
-+       * IGEN_TRIM=100=+25%
-+       * Enable VREFP (needed by all audio input channels)
-+       */
-+      ac108_multi_update_bits(PWR_CTRL9,
-+                              0x01 << VREFP_FASTSTART_ENABLE | 0x03 << VREFP_RESCTRL |
-+                              0x07 << IGEN_TRIM | 0x01 << VREFP_ENABLE,
-+                              0x00 << VREFP_FASTSTART_ENABLE | 0x00 << VREFP_RESCTRL |
-+                              0x04 << IGEN_TRIM | 0x01 << VREFP_ENABLE,
-+                              ac10x);
-+}
-+
-+/**
-+ * The clock management related registers are Reg20h~Reg25h
-+ * The PLL management related registers are Reg10h~Reg18h.
-+ * @author baozhu (17-6-20)
-+ *
-+ * @param ac10x
-+ * @param rate : sample rate
-+ *
-+ * @return int : fail or success
-+ */
-+static int ac108_config_pll(struct ac10x_priv *ac10x, unsigned rate, unsigned lrck_ratio)
-+{
-+      unsigned int i = 0;
-+      struct pll_div ac108_pll_div = { 0 };
-+
-+      if (ac10x->clk_id == SYSCLK_SRC_PLL) {
-+              unsigned pll_src, pll_freq_in;
-+
-+              if (lrck_ratio == 0) {
-+                      /* PLL clock source from MCLK */
-+                      pll_freq_in = ac10x->sysclk;
-+                      pll_src = 0x0;
-+              } else {
-+                      /* PLL clock source from BCLK */
-+                      pll_freq_in = rate * lrck_ratio;
-+                      pll_src = 0x1;
-+              }
-+
-+              /* FOUT =(FIN * N) / [(M1+1) * (M2+1)*(K1+1)*(K2+1)] */
-+              for (i = 0; i < ARRAY_SIZE(ac108_pll_div_list); i++) {
-+                      if (ac108_pll_div_list[i].freq_in == pll_freq_in &&
-+                          ac108_pll_div_list[i].freq_out % rate == 0) {
-+                              ac108_pll_div = ac108_pll_div_list[i];
-+                              dev_info(&ac10x->i2c[_MASTER_INDEX]->dev,
-+                                       "AC108 PLL freq_in match:%u, freq_out:%u\n\n",
-+                                       ac108_pll_div.freq_in, ac108_pll_div.freq_out);
-+                              break;
-+                      }
-+              }
-+              /* 0x11,0x12,0x13,0x14: Config PLL DIV param M1/M2/N/K1/K2 */
-+              ac108_multi_update_bits(PLL_CTRL5,
-+                                      0x1f << PLL_POSTDIV1 | 0x01 << PLL_POSTDIV2,
-+                                      ac108_pll_div.k1 << PLL_POSTDIV1 |
-+                                      ac108_pll_div.k2 << PLL_POSTDIV2, ac10x);
-+              ac108_multi_update_bits(PLL_CTRL4, 0xff << PLL_LOOPDIV_LSB,
-+                                      (unsigned char)ac108_pll_div.n << PLL_LOOPDIV_LSB, ac10x);
-+              ac108_multi_update_bits(PLL_CTRL3, 0x03 << PLL_LOOPDIV_MSB,
-+                                      (ac108_pll_div.n >> 8) << PLL_LOOPDIV_MSB, ac10x);
-+              ac108_multi_update_bits(PLL_CTRL2, 0x1f << PLL_PREDIV1 | 0x01 << PLL_PREDIV2,
-+                                      ac108_pll_div.m1 << PLL_PREDIV1 |
-+                                      ac108_pll_div.m2 << PLL_PREDIV2, ac10x);
-+
-+              /*0x18: PLL clk lock enable*/
-+              ac108_multi_update_bits(PLL_LOCK_CTRL, 0x1 << PLL_LOCK_EN,
-+                                      0x1 << PLL_LOCK_EN, ac10x);
-+
-+              /**
-+               * 0x20: enable pll, pll source from mclk/bclk, sysclk source from pll, enable sysclk
-+               */
-+              ac108_multi_update_bits(SYSCLK_CTRL,
-+                                      0x01 << PLLCLK_EN | 0x03  << PLLCLK_SRC |
-+                                      0x01 << SYSCLK_SRC | 0x01 << SYSCLK_EN,
-+                                      0x01 << PLLCLK_EN | pll_src << PLLCLK_SRC |
-+                                      0x01 << SYSCLK_SRC | 0x01 << SYSCLK_EN, ac10x);
-+              ac10x->mclk = ac108_pll_div.freq_out;
-+      }
-+      if (ac10x->clk_id == SYSCLK_SRC_MCLK) {
-+              /**
-+               *0x20: sysclk source from mclk, enable sysclk
-+               */
-+              ac108_multi_update_bits(SYSCLK_CTRL,
-+                                      0x01 << PLLCLK_EN | 0x01 << SYSCLK_SRC | 0x01 << SYSCLK_EN,
-+                                      0x00 << PLLCLK_EN | 0x00 << SYSCLK_SRC | 0x01 << SYSCLK_EN,
-+                                      ac10x);
-+              ac10x->mclk = ac10x->sysclk;
-+      }
-+
-+      return 0;
-+}
-+
-+/*
-+ * support no more than 16 slots.
-+ */
-+static int ac108_multi_chips_slots(struct ac10x_priv *ac, int slots)
-+{
-+      int i;
-+
-+      /*
-+       * codec0 enable slots 2,3,0,1 when 1 codec
-+       *
-+       * codec0 enable slots 6,7,0,1 when 2 codec
-+       * codec1 enable slots 2,3,4,5
-+       *
-+       * ...
-+       */
-+      for (i = 0; i < ac->codec_cnt; i++) {
-+              /* rotate map, due to channels rotated by CPU_DAI */
-+              const unsigned vec_mask[] = {
-+                      0x3 << 6 | 0x3, // slots 6,7,0,1
-+                      0xF << 2,       // slots 2,3,4,5
-+                      0,
-+                      0,
-+              };
-+              const unsigned vec_maps[] = {
-+                      /*
-+                       * chip 0,
-+                       * mic 0 sample -> slot 6
-+                       * mic 1 sample -> slot 7
-+                       * mic 2 sample -> slot 0
-+                       * mic 3 sample -> slot 1
-+                       */
-+                      0x0 << 12 | 0x1 << 14 | 0x2 << 0 | 0x3 << 2,
-+                      /*
-+                       * chip 1,
-+                       * mic 0 sample -> slot 2
-+                       * mic 1 sample -> slot 3
-+                       * mic 2 sample -> slot 4
-+                       * mic 3 sample -> slot 5
-+                       */
-+                      0x0 << 4  | 0x1 << 6  | 0x2 << 8 | 0x3 << 10,
-+                      0,
-+                      0,
-+              };
-+              unsigned vec;
-+
-+              /* 0x38-0x3A I2S_TX1_CTRLx */
-+              if (ac->codec_cnt == 1) {
-+                      vec = 0xFUL;
-+              } else {
-+                      vec = vec_mask[i];
-+              }
-+              ac10x_write(I2S_TX1_CTRL1, slots - 1, ac->i2cmap[i]);
-+              ac10x_write(I2S_TX1_CTRL2, (vec >> 0) & 0xFF, ac->i2cmap[i]);
-+              ac10x_write(I2S_TX1_CTRL3, (vec >> 8) & 0xFF, ac->i2cmap[i]);
-+
-+              /* 0x3C-0x3F I2S_TX1_CHMP_CTRLx */
-+              if (ac->codec_cnt == 1) {
-+                      vec = (0x2 << 0 | 0x3 << 2 | 0x0 << 4 | 0x1 << 6);
-+              } else if (ac->codec_cnt == 2) {
-+                      vec = vec_maps[i];
-+              }
-+
-+              ac10x_write(I2S_TX1_CHMP_CTRL1, (vec >>  0) & 0xFF, ac->i2cmap[i]);
-+              ac10x_write(I2S_TX1_CHMP_CTRL2, (vec >>  8) & 0xFF, ac->i2cmap[i]);
-+              ac10x_write(I2S_TX1_CHMP_CTRL3, (vec >> 16) & 0xFF, ac->i2cmap[i]);
-+              ac10x_write(I2S_TX1_CHMP_CTRL4, (vec >> 24) & 0xFF, ac->i2cmap[i]);
-+      }
-+      return 0;
-+}
-+
-+static int ac108_hw_params(struct snd_pcm_substream *substream,
-+      struct snd_pcm_hw_params *params, struct snd_soc_dai *dai)
-+{
-+      unsigned int i, channels, samp_res, rate;
-+      struct snd_soc_codec *codec = dai->codec;
-+      struct ac10x_priv *ac10x = snd_soc_codec_get_drvdata(codec);
-+      unsigned bclkdiv;
-+      int ret = 0;
-+      u8 v;
-+
-+      dev_dbg(dai->dev, "%s() stream=%s play:%d capt:%d +++\n", __func__,
-+                      snd_pcm_stream_str(substream),
-+                      dai->stream[SNDRV_PCM_STREAM_PLAYBACK].active,
-+                      dai->stream[SNDRV_PCM_STREAM_CAPTURE].active);
-+
-+      if (ac10x->i2c101) {
-+              ret = ac101_hw_params(substream, params, dai);
-+              if (ret > 0) {
-+                      dev_dbg(dai->dev, "%s() L%d returned\n", __func__, __LINE__);
-+                      /* not configure hw_param twice */
-+                      return 0;
-+              }
-+      }
-+
-+      if ((substream->stream == SNDRV_PCM_STREAM_CAPTURE &&
-+           dai->stream[SNDRV_PCM_STREAM_PLAYBACK].active)
-+          || (substream->stream == SNDRV_PCM_STREAM_PLAYBACK &&
-+              dai->stream[SNDRV_PCM_STREAM_CAPTURE].active)) {
-+              /* not configure hw_param twice */
-+              /* return 0; */
-+      }
-+
-+      channels = params_channels(params);
-+
-+      /* Master mode, to clear cpu_dai fifos, output bclk without lrck */
-+      ac10x_read(I2S_CTRL, &v, ac10x->i2cmap[_MASTER_INDEX]);
-+      if (v & (0x01 << BCLK_IOEN)) {
-+              ac10x_update_bits(I2S_CTRL, 0x1 << LRCK_IOEN,
-+                                0x0 << LRCK_IOEN, ac10x->i2cmap[_MASTER_INDEX]);
-+      }
-+
-+      switch (params_format(params)) {
-+      case SNDRV_PCM_FORMAT_S8:
-+              samp_res = 0;
-+              break;
-+      case SNDRV_PCM_FORMAT_S16_LE:
-+              samp_res = 2;
-+              break;
-+      case SNDRV_PCM_FORMAT_S20_3LE:
-+              samp_res = 3;
-+              break;
-+      case SNDRV_PCM_FORMAT_S24_LE:
-+              samp_res = 4;
-+              break;
-+      case SNDRV_PCM_FORMAT_S32_LE:
-+              samp_res = 6;
-+              break;
-+      default:
-+              dev_err(dai->dev, "AC108 don't supported the sample resolution: %u\n",
-+                      params_format(params));
-+              return -EINVAL;
-+      }
-+
-+      for (i = 0; i < ARRAY_SIZE(ac108_sample_rate); i++) {
-+              if (ac108_sample_rate[i].real_val == params_rate(params) /
-+                  (ac10x->data_protocol + 1UL)) {
-+                      rate = i;
-+                      break;
-+              }
-+      }
-+      if (i >= ARRAY_SIZE(ac108_sample_rate)) {
-+              return -EINVAL;
-+      }
-+
-+      if (channels == 8 && ac108_sample_rate[rate].real_val == 96000) {
-+              /* 24.576M bit clock is not support by ac108 */
-+              return -EINVAL;
-+      }
-+
-+      dev_dbg(dai->dev, "rate: %d , channels: %d , samp_res: %d",
-+                      ac108_sample_rate[rate].real_val,
-+                      channels,
-+                      ac108_samp_res[samp_res].real_val);
-+
-+      /**
-+       * 0x33: 
-+       *  The 8-Low bit of LRCK period value. It is used to program
-+       *  the number of BCLKs per channel of sample frame. This value
-+       *  is interpreted as follow:
-+       *  The 8-Low bit of LRCK period value. It is used to program
-+       *  the number of BCLKs per channel of sample frame. This value
-+       *  is interpreted as follow: PCM mode: Number of BCLKs within
-+       *  (Left + Right) channel width I2S / Left-Justified /
-+       *  Right-Justified mode: Number of BCLKs within each individual
-+       *  channel width (Left or Right) N+1
-+       *  For example:
-+       *  n = 7: 8 BCLK width
-+       *  â€¦
-+       *  n = 1023: 1024 BCLKs width
-+       *  0X32[0:1]:
-+       *  The 2-High bit of LRCK period value. 
-+       */
-+      if (ac10x->i2s_mode != PCM_FORMAT) {
-+              if (ac10x->data_protocol) {
-+                      ac108_multi_write(I2S_LRCK_CTRL2, ac108_samp_res[samp_res].real_val - 1,
-+                                        ac10x);
-+                      /*encoding mode, the max LRCK period value < 32,so the 2-High bit is zero*/
-+                      ac108_multi_update_bits(I2S_LRCK_CTRL1, 0x03 << 0, 0x00, ac10x);
-+              } else {
-+                      /*TDM mode or normal mode*/
-+                      //ac108_multi_update_bits(I2S_LRCK_CTRL1, 0x03 << 0, 0x00, ac10x);
-+                      ac108_multi_write(I2S_LRCK_CTRL2, ac108_samp_res[samp_res].real_val - 1,
-+                                        ac10x);
-+                      ac108_multi_update_bits(I2S_LRCK_CTRL1, 0x03 << 0, 0x00, ac10x);
-+              }
-+      } else {
-+              unsigned div;
-+
-+              /*TDM mode or normal mode*/
-+              div = ac108_samp_res[samp_res].real_val * channels - 1;
-+              ac108_multi_write(I2S_LRCK_CTRL2, (div & 0xFF), ac10x);
-+              ac108_multi_update_bits(I2S_LRCK_CTRL1, 0x03 << 0, (div >> 8) << 0, ac10x);
-+      }
-+
-+      /**
-+       * 0x35: 
-+       * TX Encoding mode will add  4bits to mark channel number 
-+       * TODO: need a chat to explain this 
-+       */
-+      ac108_multi_update_bits(I2S_FMT_CTRL2, 0x07 << SAMPLE_RESOLUTION | 0x07 << SLOT_WIDTH_SEL,
-+                              ac108_samp_res[samp_res].reg_val << SAMPLE_RESOLUTION |
-+                              ac108_samp_res[samp_res].reg_val << SLOT_WIDTH_SEL, ac10x);
-+
-+      /**
-+       * 0x60: 
-+       * ADC Sample Rate synchronised with I2S1 clock zone 
-+       */
-+      ac108_multi_update_bits(ADC_SPRC, 0x0f << ADC_FS_I2S1,
-+                              ac108_sample_rate[rate].reg_val << ADC_FS_I2S1, ac10x);
-+      ac108_multi_write(HPF_EN, 0x0F, ac10x);
-+
-+      if (ac10x->i2c101 && _MASTER_MULTI_CODEC == _MASTER_AC101) {
-+              ac108_config_pll(ac10x, ac108_sample_rate[rate].real_val,
-+                               ac108_samp_res[samp_res].real_val * channels);
-+      } else {
-+              ac108_config_pll(ac10x, ac108_sample_rate[rate].real_val, 0);
-+      }
-+
-+      /*
-+       * master mode only
-+       */
-+      bclkdiv = ac10x->mclk / (ac108_sample_rate[rate].real_val * channels *
-+                               ac108_samp_res[samp_res].real_val);
-+      for (i = 0; i < ARRAY_SIZE(ac108_bclkdivs) - 1; i++) {
-+              if (ac108_bclkdivs[i] >= bclkdiv) {
-+                      break;
-+              }
-+      }
-+      ac108_multi_update_bits(I2S_BCLK_CTRL, 0x0F << BCLKDIV, i << BCLKDIV, ac10x);
-+
-+      /*
-+       * slots allocation for each chip
-+       */
-+      ac108_multi_chips_slots(ac10x, channels);
-+
-+      /*0x21: Module clock enable<I2S, ADC digital, MIC offset Calibration, ADC analog>*/
-+      ac108_multi_write(MOD_CLK_EN, 1 << I2S | 1 << ADC_DIGITAL |
-+                        1 << MIC_OFFSET_CALIBRATION | 1 << ADC_ANALOG, ac10x);
-+      /*0x22: Module reset de-asserted<I2S, ADC digital, MIC offset Calibration, ADC analog>*/
-+      ac108_multi_write(MOD_RST_CTRL, 1 << I2S | 1 << ADC_DIGITAL |
-+                        1 << MIC_OFFSET_CALIBRATION | 1 << ADC_ANALOG, ac10x);
-+      
-+      ac108_multi_write(I2S_TX1_CHMP_CTRL1, 0xE4, ac10x);
-+      ac108_multi_write(I2S_TX1_CHMP_CTRL2, 0xE4, ac10x);
-+      ac108_multi_write(I2S_TX1_CHMP_CTRL3, 0xE4, ac10x);
-+      ac108_multi_write(I2S_TX1_CHMP_CTRL4, 0xE4, ac10x);
-+      
-+      ac108_multi_write(I2S_TX2_CHMP_CTRL1, 0xE4, ac10x);
-+      ac108_multi_write(I2S_TX2_CHMP_CTRL2, 0xE4, ac10x);
-+      ac108_multi_write(I2S_TX2_CHMP_CTRL3, 0xE4, ac10x);
-+      ac108_multi_write(I2S_TX2_CHMP_CTRL4, 0xE4, ac10x);
-+
-+      dev_dbg(dai->dev, "%s() stream=%s ---\n", __func__,
-+                      snd_pcm_stream_str(substream));
-+
-+      return 0;
-+}
-+
-+static int ac108_set_sysclk(struct snd_soc_dai *dai, int clk_id, unsigned int freq, int dir)
-+{
-+
-+      struct ac10x_priv *ac10x = snd_soc_dai_get_drvdata(dai);
-+
-+      freq = 24000000;
-+      clk_id = SYSCLK_SRC_PLL;
-+
-+      switch (clk_id) {
-+      case SYSCLK_SRC_MCLK:
-+              ac108_multi_update_bits(SYSCLK_CTRL, 0x1 << SYSCLK_SRC,
-+                                      SYSCLK_SRC_MCLK << SYSCLK_SRC, ac10x);
-+              break;
-+      case SYSCLK_SRC_PLL:
-+              ac108_multi_update_bits(SYSCLK_CTRL, 0x1 << SYSCLK_SRC,
-+                                      SYSCLK_SRC_PLL << SYSCLK_SRC, ac10x);
-+              break;
-+      default:
-+              return -EINVAL;
-+      }
-+      ac10x->sysclk = freq;
-+      ac10x->clk_id = clk_id;
-+
-+      return 0;
-+}
-+
-+/**
-+ *  The i2s format management related registers are Reg
-+ *  30h~Reg36h
-+ *  33h,35h will be set in ac108_hw_params, It's BCLK width and
-+ *  Sample Resolution.
-+ * @author baozhu (17-6-20)
-+ * 
-+ * @param dai 
-+ * @param fmt 
-+ * 
-+ * @return int 
-+ */
-+static int ac108_set_fmt(struct snd_soc_dai *dai, unsigned int fmt)
-+{
-+      unsigned char tx_offset, lrck_polarity, brck_polarity;
-+      struct ac10x_priv *ac10x = dev_get_drvdata(dai->dev);
-+
-+      switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
-+      case SND_SOC_DAIFMT_CBM_CFM:    /* AC108 Master */
-+              if (! ac10x->i2c101 || _MASTER_MULTI_CODEC == _MASTER_AC108) {
-+                      /**
-+                       * 0x30:chip is master mode ,BCLK & LRCK output
-+                       */
-+                      ac108_multi_update_bits(I2S_CTRL,
-+                                              0x03 << LRCK_IOEN | 0x03 << SDO1_EN |
-+                                              0x1 << TXEN | 0x1 << GEN,
-+                                              0x03 << LRCK_IOEN | 0x01 << SDO1_EN |
-+                                              0x1 << TXEN | 0x1 << GEN, ac10x);
-+                      /* multi_chips: only one chip set as Master, and the others also need to set as Slave */
-+                      ac10x_update_bits(I2S_CTRL, 0x3 << LRCK_IOEN, 0x01 << BCLK_IOEN,
-+                                        ac10x->i2cmap[_MASTER_INDEX]);
-+              } else {
-+                      /* TODO: Both cpu_dai and codec_dai(AC108) be set as slave in DTS */
-+                      dev_err(dai->dev, "used as slave when AC101 is master\n");
-+              }
-+              break;
-+      case SND_SOC_DAIFMT_CBS_CFS:    /* AC108 Slave */
-+              /**
-+               * 0x30:chip is slave mode, BCLK & LRCK input,enable SDO1_EN and 
-+               *  SDO2_EN, Transmitter Block Enable, Globe Enable
-+               */
-+              ac108_multi_update_bits(I2S_CTRL,
-+                                      0x03 << LRCK_IOEN | 0x03 << SDO1_EN |
-+                                      0x1 << TXEN | 0x1 << GEN,
-+                                      0x00 << LRCK_IOEN | 0x03 << SDO1_EN |
-+                                      0x0 << TXEN | 0x0 << GEN, ac10x);
-+              break;
-+      default:
-+              dev_err(dai->dev, "AC108 Master/Slave mode config error:%u\n\n",
-+                      (fmt & SND_SOC_DAIFMT_MASTER_MASK) >> 12);
-+              return -EINVAL;
-+      }
-+
-+      /*AC108 config I2S/LJ/RJ/PCM format*/
-+      switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
-+      case SND_SOC_DAIFMT_I2S:
-+              ac10x->i2s_mode = LEFT_JUSTIFIED_FORMAT;
-+              tx_offset = 1;
-+              break;
-+      case SND_SOC_DAIFMT_RIGHT_J:
-+              ac10x->i2s_mode = RIGHT_JUSTIFIED_FORMAT;
-+              tx_offset = 0;
-+              break;
-+      case SND_SOC_DAIFMT_LEFT_J:
-+              ac10x->i2s_mode = LEFT_JUSTIFIED_FORMAT;
-+              tx_offset = 0;
-+              break;
-+      case SND_SOC_DAIFMT_DSP_A:
-+              ac10x->i2s_mode = PCM_FORMAT;
-+              tx_offset = 1;
-+              break;
-+      case SND_SOC_DAIFMT_DSP_B:
-+              ac10x->i2s_mode = PCM_FORMAT;
-+              tx_offset = 0;
-+              break;
-+      default:
-+              dev_err(dai->dev, "AC108 I2S format config error:%u\n\n",
-+                      fmt & SND_SOC_DAIFMT_FORMAT_MASK);
-+              return -EINVAL;
-+      }
-+
-+      /*AC108 config BCLK&LRCK polarity*/
-+      switch (fmt & SND_SOC_DAIFMT_INV_MASK) {
-+      case SND_SOC_DAIFMT_NB_NF:
-+              brck_polarity = BCLK_NORMAL_DRIVE_N_SAMPLE_P;
-+              lrck_polarity = LRCK_LEFT_HIGH_RIGHT_LOW;
-+              break;
-+      case SND_SOC_DAIFMT_NB_IF:
-+              brck_polarity = BCLK_NORMAL_DRIVE_N_SAMPLE_P;
-+              lrck_polarity = LRCK_LEFT_LOW_RIGHT_HIGH;
-+              break;
-+      case SND_SOC_DAIFMT_IB_NF:
-+              brck_polarity = BCLK_INVERT_DRIVE_P_SAMPLE_N;
-+              lrck_polarity = LRCK_LEFT_HIGH_RIGHT_LOW;
-+              break;
-+      case SND_SOC_DAIFMT_IB_IF:
-+              brck_polarity = BCLK_INVERT_DRIVE_P_SAMPLE_N;
-+              lrck_polarity = LRCK_LEFT_LOW_RIGHT_HIGH;
-+              break;
-+      default:
-+              dev_err(dai->dev, "AC108 config BCLK/LRCLK polarity error:%u\n\n",
-+                      (fmt & SND_SOC_DAIFMT_INV_MASK) >> 8);
-+              return -EINVAL;
-+      }
-+
-+      ac108_configure_power(ac10x);
-+
-+      /**
-+       *0x31: 0: normal mode, negative edge drive and positive edge sample
-+              1: invert mode, positive edge drive and negative edge sample
-+       */
-+      ac108_multi_update_bits(I2S_BCLK_CTRL,  0x01 << BCLK_POLARITY,
-+                              brck_polarity << BCLK_POLARITY, ac10x);
-+      /**
-+       * 0x32: same as 0x31
-+       */
-+      ac108_multi_update_bits(I2S_LRCK_CTRL1, 0x01 << LRCK_POLARITY,
-+                              lrck_polarity << LRCK_POLARITY, ac10x);
-+      /**
-+       * 0x34:Encoding Mode Selection,Mode 
-+       * Selection,data is offset by 1 BCLKs to LRCK 
-+       * normal mode for the last half cycle of BCLK in the slot ?
-+       * turn to hi-z state (TDM) when not transferring slot ?
-+       */
-+      ac108_multi_update_bits(I2S_FMT_CTRL1,
-+                              0x01 << ENCD_SEL | 0x03 << MODE_SEL | 0x01 << TX2_OFFSET |
-+                              0x01 << TX1_OFFSET | 0x01 << TX_SLOT_HIZ | 0x01 << TX_STATE,
-+                              ac10x->data_protocol << ENCD_SEL | ac10x->i2s_mode << MODE_SEL |
-+                              tx_offset << TX2_OFFSET | tx_offset << TX1_OFFSET |
-+                              0x00 << TX_SLOT_HIZ | 0x01 << TX_STATE, ac10x);
-+
-+      /**
-+       * 0x60: 
-+       * MSB / LSB First Select: This driver only support MSB First Select . 
-+       * OUT2_MUTE,OUT1_MUTE shoule be set in widget. 
-+       * LRCK = 1 BCLK width 
-+       * Linear PCM 
-+       *  
-+       * TODO:pcm mode, bit[0:1] and bit[2] is special
-+       */
-+      ac108_multi_update_bits(I2S_FMT_CTRL3,
-+                              0x01 << TX_MLS | 0x03 << SEXT |
-+                              0x01 << LRCK_WIDTH | 0x03 << TX_PDM,
-+                              0x00 << TX_MLS | 0x03 << SEXT |
-+                              0x00 << LRCK_WIDTH | 0x00 << TX_PDM, ac10x);
-+
-+      ac108_multi_write(HPF_EN, 0x00, ac10x);
-+
-+      if (ac10x->i2c101) {
-+              return ac101_set_dai_fmt(dai, fmt);
-+      }
-+      return 0;
-+}
-+
-+/*
-+ * due to miss channels order in cpu_dai, we meed defer the clock starting.
-+ */
-+static int ac108_set_clock(int y_start_n_stop)
-+{
-+      u8 reg;
-+      int ret = 0;
-+
-+      dev_dbg(ac10x->codec->dev, "%s() L%d cmd:%d\n", __func__, __LINE__, y_start_n_stop);
-+
-+      /* spin_lock move to machine trigger */
-+
-+      if (y_start_n_stop && ac10x->sysclk_en == 0) {
-+              /* enable lrck clock */
-+              ac10x_read(I2S_CTRL, &reg, ac10x->i2cmap[_MASTER_INDEX]);
-+              if (reg & (0x01 << BCLK_IOEN)) {
-+                      ret = ret || ac10x_update_bits(I2S_CTRL, 0x03 << LRCK_IOEN,
-+                                                     0x03 << LRCK_IOEN,
-+                                                     ac10x->i2cmap[_MASTER_INDEX]);
-+              }
-+
-+              /*0x10: PLL Common voltage enable, PLL enable */
-+              ret = ret || ac108_multi_update_bits(PLL_CTRL1,
-+                                                   0x01 << PLL_EN | 0x01 << PLL_COM_EN,
-+                                                   0x01 << PLL_EN | 0x01 << PLL_COM_EN, ac10x);
-+              /* enable global clock */
-+              ret = ret || ac108_multi_update_bits(I2S_CTRL, 0x1 << TXEN | 0x1 << GEN,
-+                                                   0x1 << TXEN | 0x1 << GEN, ac10x);
-+
-+              ac10x->sysclk_en = 1UL;
-+      } else if (!y_start_n_stop && ac10x->sysclk_en != 0) {
-+              /* disable global clock */
-+              ret = ret || ac108_multi_update_bits(I2S_CTRL, 0x1 << TXEN | 0x1 << GEN,
-+                                                   0x0 << TXEN | 0x0 << GEN, ac10x);
-+
-+              /*0x10: PLL Common voltage disable, PLL disable */
-+              ret = ret || ac108_multi_update_bits(PLL_CTRL1, 0x01 << PLL_EN | 0x01 << PLL_COM_EN,
-+                                                   0x00 << PLL_EN | 0x00 << PLL_COM_EN, ac10x);
-+
-+              /* disable lrck clock if it's enabled */
-+              ac10x_read(I2S_CTRL, &reg, ac10x->i2cmap[_MASTER_INDEX]);
-+              if (reg & (0x01 << LRCK_IOEN)) {
-+                      ret = ret || ac10x_update_bits(I2S_CTRL, 0x03 << LRCK_IOEN,
-+                                                     0x01 << BCLK_IOEN,
-+                                                     ac10x->i2cmap[_MASTER_INDEX]);
-+              }
-+              if (!ret) {
-+                      ac10x->sysclk_en = 0UL;
-+              }
-+      }
-+
-+      return ret;
-+}
-+
-+static int ac108_prepare(struct snd_pcm_substream *substream,
-+                       struct snd_soc_dai *dai)
-+{
-+      u8 r;
-+
-+      dev_dbg(dai->dev, "%s() stream=%s\n",
-+              __func__,
-+              snd_pcm_stream_str(substream));
-+      
-+      if (ac10x->i2c101 && _MASTER_MULTI_CODEC == _MASTER_AC101) {
-+              ac101_trigger(substream, SNDRV_PCM_TRIGGER_START, dai);
-+              if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
-+                     return 0;
-+              }
-+      }
-+
-+      ac10x_read(I2S_CTRL, &r, ac10x->i2cmap[_MASTER_INDEX]);
-+      if ((r & (0x01 << BCLK_IOEN)) && (r & (0x01 << LRCK_IOEN)) == 0) {
-+              /* disable global clock */
-+              ac108_multi_update_bits(I2S_CTRL, 0x1 << TXEN | 0x1 << GEN,
-+                                      0x0 << TXEN | 0x0 << GEN, ac10x);
-+      }
-+
-+      /* delayed clock starting, move to machine trigger() */
-+      ac108_set_clock(1);
-+
-+      return 0;
-+}
-+
-+int ac108_audio_startup(struct snd_pcm_substream *substream,
-+      struct snd_soc_dai *dai)
-+{
-+      struct snd_soc_codec *codec = dai->codec;
-+      struct ac10x_priv *ac10x = snd_soc_codec_get_drvdata(codec);
-+
-+      if (ac10x->i2c101) {
-+              return ac101_audio_startup(substream, dai);
-+      }
-+      return 0;
-+}
-+
-+void ac108_aif_shutdown(struct snd_pcm_substream *substream,
-+      struct snd_soc_dai *dai)
-+{
-+      struct snd_soc_codec *codec = dai->codec;
-+      struct ac10x_priv *ac10x = snd_soc_codec_get_drvdata(codec);
-+
-+      ac108_set_clock(0);
-+
-+      if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) {
-+              /*0x21: Module clock disable <I2S, ADC digital, MIC offset Calibration, ADC analog>*/
-+              ac108_multi_write(MOD_CLK_EN, 0x0, ac10x);
-+              /*0x22: Module reset asserted <I2S, ADC digital, MIC offset Calibration, ADC analog>*/
-+              ac108_multi_write(MOD_RST_CTRL, 0x0, ac10x);
-+      }
-+
-+      if (ac10x->i2c101) {
-+              ac101_aif_shutdown(substream, dai);
-+      }
-+}
-+
-+int ac108_aif_mute(struct snd_soc_dai *dai, int mute, int stream)
-+{
-+      struct snd_soc_codec *codec = dai->codec;
-+      struct ac10x_priv *ac10x = snd_soc_codec_get_drvdata(codec);
-+
-+      if (ac10x->i2c101) {
-+              return ac101_aif_mute(dai, mute);
-+      }
-+      return 0;       
-+}
-+
-+static const struct snd_soc_dai_ops ac108_dai_ops = {
-+      .startup        = ac108_audio_startup,
-+      .shutdown       = ac108_aif_shutdown,
-+
-+      /*DAI clocking configuration*/
-+      .set_sysclk     = ac108_set_sysclk,
-+
-+      /*ALSA PCM audio operations*/
-+      .hw_params      = ac108_hw_params,
-+      .prepare        = ac108_prepare,
-+      .mute_stream    = ac108_aif_mute,
-+
-+      /*DAI format configuration*/
-+      .set_fmt        = ac108_set_fmt,
-+};
-+
-+static  struct snd_soc_dai_driver ac108_dai0 = {
-+      .name = "ac10x-codec0",
-+      #if _USE_CAPTURE
-+      .playback = {
-+              .stream_name = "Playback",
-+              .channels_min = 1,
-+              .channels_max = AC108_CHANNELS_MAX,
-+              .rates = AC108_RATES,
-+              .formats = AC108_FORMATS,
-+      },
-+      #endif
-+      .capture = {
-+              .stream_name = "Capture",
-+              .channels_min = 1,
-+              .channels_max = AC108_CHANNELS_MAX,
-+              .rates = AC108_RATES,
-+              .formats = AC108_FORMATS,
-+      },
-+      .ops = &ac108_dai_ops,
-+};
-+
-+static  struct snd_soc_dai_driver ac108_dai1 = {
-+      .name = "ac10x-codec1",
-+      #if _USE_CAPTURE
-+      .playback = {
-+              .stream_name = "Playback",
-+              .channels_min = 1,
-+              .channels_max = AC108_CHANNELS_MAX,
-+              .rates = AC108_RATES,
-+              .formats = AC108_FORMATS,
-+      },
-+      #endif
-+      .capture = {
-+              .stream_name = "Capture",
-+              .channels_min = 1,
-+              .channels_max = AC108_CHANNELS_MAX,
-+              .rates = AC108_RATES,
-+              .formats = AC108_FORMATS,
-+      },
-+      .ops = &ac108_dai_ops,
-+};
-+
-+static  struct snd_soc_dai_driver *ac108_dai[] = {
-+      &ac108_dai0,
-+      &ac108_dai1,
-+};
-+
-+static int ac108_add_widgets(struct snd_soc_codec *codec)
-+{
-+      struct ac10x_priv *ac10x = snd_soc_codec_get_drvdata(codec);
-+      struct snd_soc_dapm_context *dapm = snd_soc_codec_get_dapm(codec);
-+      const struct snd_kcontrol_new* snd_kcntl = ac108_snd_controls;
-+      int ctrl_cnt = ARRAY_SIZE(ac108_snd_controls);
-+
-+      /* only register controls correspond to exist chips */
-+      if (ac10x->tdm_chips_cnt >= 2) {
-+              snd_kcntl = ac108tdm_snd_controls;
-+              ctrl_cnt = ARRAY_SIZE(ac108tdm_snd_controls);
-+      }
-+      snd_soc_add_codec_controls(codec, snd_kcntl, ctrl_cnt);
-+
-+      snd_soc_dapm_new_controls(dapm, ac108_dapm_widgets,ARRAY_SIZE(ac108_dapm_widgets));
-+      snd_soc_dapm_add_routes(dapm, ac108_dapm_routes, ARRAY_SIZE(ac108_dapm_routes));
-+
-+      return 0;
-+}
-+
-+static int ac108_codec_probe(struct snd_soc_codec *codec)
-+{
-+      spin_lock_init(&ac10x->lock);
-+
-+      ac10x->codec = codec;
-+      dev_set_drvdata(codec->dev, ac10x);
-+      ac108_add_widgets(codec);
-+
-+      if (ac10x->i2c101) {
-+              ac101_codec_probe(codec);
-+      }
-+
-+      /* change default volume */
-+      ac108_multi_update_bits(ADC1_DVOL_CTRL, 0xff, 0xc8, ac10x);
-+      ac108_multi_update_bits(ADC2_DVOL_CTRL, 0xff, 0xc8, ac10x);
-+      ac108_multi_update_bits(ADC3_DVOL_CTRL, 0xff, 0xc8, ac10x);
-+      ac108_multi_update_bits(ADC4_DVOL_CTRL, 0xff, 0xc8, ac10x);
-+
-+      return 0;
-+}
-+
-+static int ac108_set_bias_level(struct snd_soc_codec *codec, enum snd_soc_bias_level level)
-+{
-+      struct ac10x_priv *ac10x = snd_soc_codec_get_drvdata(codec);
-+
-+      dev_dbg(codec->dev, "AC108 level:%d\n", level);
-+
-+      switch (level) {
-+      case SND_SOC_BIAS_ON:
-+              ac108_multi_update_bits(ANA_ADC1_CTRL1, 0x01 << ADC1_MICBIAS_EN,
-+                                      0x01 << ADC1_MICBIAS_EN, ac10x);
-+              ac108_multi_update_bits(ANA_ADC2_CTRL1, 0x01 << ADC2_MICBIAS_EN,
-+                                      0x01 << ADC2_MICBIAS_EN, ac10x);
-+              ac108_multi_update_bits(ANA_ADC3_CTRL1, 0x01 << ADC3_MICBIAS_EN,
-+                                      0x01 << ADC3_MICBIAS_EN, ac10x);
-+              ac108_multi_update_bits(ANA_ADC4_CTRL1, 0x01 << ADC4_MICBIAS_EN,
-+                                      0x01 << ADC4_MICBIAS_EN, ac10x);
-+              break;
-+
-+      case SND_SOC_BIAS_PREPARE:
-+              /* Put the MICBIASes into regulating mode */
-+              break;
-+
-+      case SND_SOC_BIAS_STANDBY:
-+              break;
-+
-+      case SND_SOC_BIAS_OFF:
-+              ac108_multi_update_bits(ANA_ADC1_CTRL1, 0x01 << ADC1_MICBIAS_EN,
-+                                      0x00 << ADC1_MICBIAS_EN, ac10x);
-+              ac108_multi_update_bits(ANA_ADC2_CTRL1, 0x01 << ADC2_MICBIAS_EN,
-+                                      0x00 << ADC2_MICBIAS_EN, ac10x);
-+              ac108_multi_update_bits(ANA_ADC3_CTRL1, 0x01 << ADC3_MICBIAS_EN,
-+                                      0x00 << ADC3_MICBIAS_EN, ac10x);
-+              ac108_multi_update_bits(ANA_ADC4_CTRL1, 0x01 << ADC4_MICBIAS_EN,
-+                                      0x00 << ADC4_MICBIAS_EN, ac10x);
-+              break;
-+      }
-+
-+      if (ac10x->i2c101) {
-+              ac101_set_bias_level(codec, level);
-+      }
-+      return 0;
-+}
-+
-+int ac108_codec_remove(struct snd_soc_codec *codec) {
-+      struct ac10x_priv *ac10x = snd_soc_codec_get_drvdata(codec);
-+
-+      if (! ac10x->i2c101) {
-+              return 0;
-+      }
-+      return ac101_codec_remove(codec);
-+}
-+#if __NO_SND_SOC_CODEC_DRV
-+void ac108_codec_remove_void(struct snd_soc_codec *codec)
-+{
-+      ac108_codec_remove(codec);
-+}
-+#define ac108_codec_remove ac108_codec_remove_void
-+#endif
-+
-+int ac108_codec_suspend(struct snd_soc_codec *codec)
-+{
-+      struct ac10x_priv *ac10x = snd_soc_codec_get_drvdata(codec);
-+      int i;
-+
-+      for (i = 0; i < ac10x->codec_cnt; i++) {
-+              regcache_cache_only(ac10x->i2cmap[i], true);
-+      }
-+
-+      if (! ac10x->i2c101) {
-+              return 0;
-+      }
-+      return ac101_codec_suspend(codec);
-+}
-+
-+int ac108_codec_resume(struct snd_soc_codec *codec)
-+{
-+      struct ac10x_priv *ac10x = snd_soc_codec_get_drvdata(codec);
-+      int i, ret;
-+
-+      /* Sync reg_cache with the hardware */
-+      for (i = 0; i < ac10x->codec_cnt; i++) {
-+              regcache_cache_only(ac10x->i2cmap[i], false);
-+              ret = regcache_sync(ac10x->i2cmap[i]);
-+              if (ret != 0) {
-+                      dev_err(codec->dev, "Failed to sync i2cmap%d register cache: %d\n",
-+                              i, ret);
-+                      regcache_cache_only(ac10x->i2cmap[i], true);
-+              }
-+      }
-+
-+      if (! ac10x->i2c101) {
-+              return 0;
-+      }
-+      return ac101_codec_resume(codec);
-+}
-+
-+static struct snd_soc_codec_driver ac10x_soc_codec_driver = {
-+      .probe          = ac108_codec_probe,
-+      .remove         = ac108_codec_remove,
-+      .suspend        = ac108_codec_suspend,
-+      .resume         = ac108_codec_resume,
-+      .set_bias_level = ac108_set_bias_level,
-+      .read           = ac108_codec_read,
-+      .write          = ac108_codec_write,
-+};
-+
-+static ssize_t ac108_store(struct device *dev, struct device_attribute *attr,
-+                         const char *buf, size_t count)
-+{
-+      int val = 0, flag = 0;
-+      u8 i = 0, reg, num, value_w, value_r[4];
-+
-+      val = simple_strtol(buf, NULL, 16);
-+      flag = (val >> 16) & 0xF;
-+
-+      if (flag) {
-+              reg = (val >> 8) & 0xFF;
-+              value_w = val & 0xFF;
-+              ac108_multi_write(reg, value_w, ac10x);
-+              dev_info(dev, "Write 0x%02x to REG:0x%02x\n", value_w, reg);
-+      } else {
-+              int k;
-+
-+              reg = (val >> 8) & 0xFF;
-+              num = val & 0xff;
-+              dev_info(dev, "\nRead: start REG:0x%02x,count:0x%02x\n", reg, num);
-+
-+              for (k = 0; k < ac10x->codec_cnt; k++)
-+                      regcache_cache_bypass(ac10x->i2cmap[k], true);
-+
-+              do {
-+                      memset(value_r, 0, sizeof value_r);
-+
-+                      for (k = 0; k < ac10x->codec_cnt; k++)
-+                              ac10x_read(reg, &value_r[k], ac10x->i2cmap[k]);
-+
-+                      if (ac10x->codec_cnt >= 2)
-+                              dev_info(dev, "REG[0x%02x]: 0x%02x 0x%02x", reg,
-+                                       value_r[0], value_r[1]);
-+                      else
-+                              dev_info(dev, "REG[0x%02x]: 0x%02x", reg, value_r[0]);
-+                      reg++;
-+
-+                      if ((++i == num) || (i % 4 == 0))
-+                              dev_info(dev, "\n");
-+              } while (i < num);
-+
-+              for (k = 0; k < ac10x->codec_cnt; k++)
-+                      regcache_cache_bypass(ac10x->i2cmap[k], false);
-+      }
-+
-+      return count;
-+}
-+
-+static ssize_t ac108_show(struct device *dev, struct device_attribute *attr, char *buf)
-+{
-+      dev_info(dev, "echo flag|reg|val > ac108\n");
-+      dev_info(dev, "eg read star addres=0x06,count 0x10:echo 0610 >ac108\n");
-+      dev_info(dev, "eg write value:0xfe to address:0x06 :echo 106fe > ac108\n");
-+      return 0;
-+}
-+
-+static DEVICE_ATTR(ac108, 0644, ac108_show, ac108_store);
-+static struct attribute *ac108_debug_attrs[] = {
-+      &dev_attr_ac108.attr,
-+      NULL,
-+};
-+static struct attribute_group ac108_debug_attr_group = {
-+      .name   = "ac108_debug",
-+      .attrs  = ac108_debug_attrs,
-+};
-+
-+static const struct i2c_device_id ac108_i2c_id[] = {
-+      { "ac108_0", 0 },
-+      { "ac108_1", 1 },
-+      { "ac108_2", 2 },
-+      { "ac108_3", 3 },
-+      { "ac101", AC101_I2C_ID },
-+      { }
-+};
-+MODULE_DEVICE_TABLE(i2c, ac108_i2c_id);
-+
-+static const struct regmap_config ac108_regmap = {
-+      .reg_bits = 8,
-+      .val_bits = 8,
-+      .reg_stride = 1,
-+      .max_register = 0xDF,
-+      .cache_type = REGCACHE_FLAT,
-+};
-+static int ac108_i2c_probe(struct i2c_client *i2c)
-+{
-+      struct device_node *np = i2c->dev.of_node;
-+      const struct i2c_device_id *i2c_id;
-+      unsigned int val = 0;
-+      int ret = 0, index;
-+
-+      if (ac10x == NULL) {
-+              ac10x = kzalloc(sizeof(struct ac10x_priv), GFP_KERNEL);
-+              if (ac10x == NULL) {
-+                      dev_err(&i2c->dev, "Unable to allocate ac10x private data\n");
-+                      return -ENOMEM;
-+              }
-+      }
-+
-+      i2c_id = i2c_match_id(ac108_i2c_id, i2c);
-+      index = (int)i2c_id->driver_data;
-+      if (index == AC101_I2C_ID) {
-+              ac10x->i2c101 = i2c;
-+              i2c_set_clientdata(i2c, ac10x);
-+              ret = ac101_probe(i2c, i2c_id);
-+              if (ret) {
-+                      ac10x->i2c101 = NULL;
-+                      return ret;
-+              }
-+              goto __ret;
-+      }
-+
-+      ret = of_property_read_u32(np, "data-protocol", &val);
-+      if (ret) {
-+              dev_err(&i2c->dev, "Please set data-protocol.\n");
-+              return -EINVAL;
-+      }
-+      ac10x->data_protocol = val;
-+
-+      if (of_property_read_u32(np, "tdm-chips-count", &val)) val = 1;
-+      ac10x->tdm_chips_cnt = val;
-+
-+      dev_info(&i2c->dev, " ac10x i2c_id number: %d\n", index);
-+      dev_info(&i2c->dev, " ac10x data protocol: %d\n", ac10x->data_protocol);
-+
-+      ac10x->i2c[index] = i2c;
-+      ac10x->i2cmap[index] = devm_regmap_init_i2c(i2c, &ac108_regmap);
-+      if (IS_ERR(ac10x->i2cmap[index])) {
-+              ret = PTR_ERR(ac10x->i2cmap[index]);
-+              dev_err(&i2c->dev, "Fail to initialize i2cmap%d I/O: %d\n", index, ret);
-+              return ret;
-+      }
-+
-+      /*
-+       * Writing this register with 0x12
-+       * will resets all register to their default state.
-+       */
-+      regcache_cache_only(ac10x->i2cmap[index], false);
-+      
-+      ret = regmap_write(ac10x->i2cmap[index], CHIP_RST, CHIP_RST_VAL);
-+      msleep(1);
-+
-+      /* sync regcache for FLAT type */
-+      ac10x_fill_regcache(&i2c->dev, ac10x->i2cmap[index]);
-+
-+      ac10x->codec_cnt++;
-+      dev_info(&i2c->dev, " ac10x codec count  : %d\n", ac10x->codec_cnt);
-+
-+      ret = sysfs_create_group(&i2c->dev.kobj, &ac108_debug_attr_group);
-+      if (ret) {
-+              dev_err(&i2c->dev, "failed to create attr group\n");
-+      }
-+
-+__ret:
-+      /* It's time to bind codec to i2c[_MASTER_INDEX] when all i2c are ready */
-+      if ((ac10x->codec_cnt != 0 && ac10x->tdm_chips_cnt < 2)
-+      || (ac10x->i2c[0] && ac10x->i2c[1] && ac10x->i2c101)) {
-+              /* no playback stream */
-+              if (! ac10x->i2c101) {
-+                      memset(&ac108_dai[_MASTER_INDEX]->playback, '\0',
-+                             sizeof ac108_dai[_MASTER_INDEX]->playback);
-+              }
-+              ret = snd_soc_register_codec(&ac10x->i2c[_MASTER_INDEX]->dev,
-+                                           &ac10x_soc_codec_driver,
-+                                           ac108_dai[_MASTER_INDEX], 1);
-+              if (ret < 0) {
-+                      dev_err(&i2c->dev, "Failed to register ac10x codec: %d\n", ret);
-+              }
-+      }
-+      return ret;
-+}
-+
-+static void ac108_i2c_remove(struct i2c_client *i2c)
-+{
-+      if (ac10x->codec != NULL) {
-+              snd_soc_unregister_codec(&ac10x->i2c[_MASTER_INDEX]->dev);
-+              ac10x->codec = NULL;
-+      }
-+      if (i2c == ac10x->i2c101) {
-+              ac101_remove(ac10x->i2c101);
-+              ac10x->i2c101 = NULL;
-+              goto __ret;
-+      }
-+
-+      if (i2c == ac10x->i2c[0]) {
-+              ac10x->i2c[0] = NULL;
-+      }
-+      if (i2c == ac10x->i2c[1]) {
-+              ac10x->i2c[1] = NULL;
-+      }
-+
-+      sysfs_remove_group(&i2c->dev.kobj, &ac108_debug_attr_group);
-+
-+__ret:
-+      if (!ac10x->i2c[0] && !ac10x->i2c[1] && !ac10x->i2c101) {
-+              kfree(ac10x);
-+              ac10x = NULL;
-+      }
-+}
-+
-+static const struct of_device_id ac108_of_match[] = {
-+      { .compatible = "x-power,ac108_0", },
-+      { .compatible = "x-power,ac108_1", },
-+      { .compatible = "x-power,ac108_2", },
-+      { .compatible = "x-power,ac108_3", },
-+      { .compatible = "x-power,ac101",   },
-+      { }
-+};
-+MODULE_DEVICE_TABLE(of, ac108_of_match);
-+
-+static struct i2c_driver ac108_i2c_driver = {
-+      .driver = {
-+              .name = "ac10x-codec",
-+              .of_match_table = ac108_of_match,
-+      },
-+      .probe =    ac108_i2c_probe,
-+      .remove =   ac108_i2c_remove,
-+      .id_table = ac108_i2c_id,
-+};
-+
-+module_i2c_driver(ac108_i2c_driver);
-+
-+MODULE_DESCRIPTION("ASoC AC108 driver");
-+MODULE_AUTHOR("Baozhu Zuo<zuobaozhu@gmail.com>");
-+MODULE_LICENSE("GPL");
---- /dev/null
-+++ b/sound/soc/codecs/ac108.h
-@@ -0,0 +1,749 @@
-+/*
-+ * ac108.h --  ac108 ALSA Soc Audio driver
-+ *
-+ * Author: panjunwen
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License version 2 as
-+ * published by the Free Software Foundation.
-+ *
-+ */
-+
-+#ifndef _AC108_H
-+#define _AC108_H
-+
-+/*** AC108 Codec Register Define***/
-+
-+//Chip Reset
-+#define CHIP_RST                      0x00
-+#define CHIP_RST_VAL          0x12
-+
-+//Power Control
-+#define PWR_CTRL1                     0x01
-+#define PWR_CTRL2                     0x02
-+#define PWR_CTRL3                     0x03
-+#define PWR_CTRL4                     0x04
-+#define PWR_CTRL5                     0x05
-+#define PWR_CTRL6                     0x06
-+#define PWR_CTRL7                     0x07
-+#define PWR_CTRL8                     0x08
-+#define PWR_CTRL9                     0x09
-+
-+//PLL Configure Control
-+#define PLL_CTRL1                     0x10
-+#define PLL_CTRL2                     0x11
-+#define PLL_CTRL3                     0x12
-+#define PLL_CTRL4                     0x13
-+#define PLL_CTRL5                     0x14
-+#define PLL_CTRL6                     0x16
-+#define PLL_CTRL7                     0x17
-+#define PLL_LOCK_CTRL         0x18
-+
-+//System Clock Control
-+#define SYSCLK_CTRL                   0x20
-+#define MOD_CLK_EN                    0x21
-+#define MOD_RST_CTRL          0x22
-+#define DSM_CLK_CTRL          0x25
-+
-+//I2S Common Control
-+#define I2S_CTRL                      0x30
-+#define I2S_BCLK_CTRL         0x31
-+#define I2S_LRCK_CTRL1                0x32
-+#define I2S_LRCK_CTRL2                0x33
-+#define I2S_FMT_CTRL1         0x34
-+#define I2S_FMT_CTRL2         0x35
-+#define I2S_FMT_CTRL3         0x36
-+
-+//I2S TX1 Control
-+#define I2S_TX1_CTRL1         0x38
-+#define I2S_TX1_CTRL2         0x39
-+#define I2S_TX1_CTRL3         0x3A
-+#define I2S_TX1_CHMP_CTRL1    0x3C
-+#define I2S_TX1_CHMP_CTRL2    0x3D
-+#define I2S_TX1_CHMP_CTRL3    0x3E
-+#define I2S_TX1_CHMP_CTRL4    0x3F
-+
-+//I2S TX2 Control
-+#define I2S_TX2_CTRL1         0x40
-+#define I2S_TX2_CTRL2         0x41
-+#define I2S_TX2_CTRL3         0x42
-+#define I2S_TX2_CHMP_CTRL1    0x44
-+#define I2S_TX2_CHMP_CTRL2    0x45
-+#define I2S_TX2_CHMP_CTRL3    0x46
-+#define I2S_TX2_CHMP_CTRL4    0x47
-+
-+//I2S RX1 Control
-+#define I2S_RX1_CTRL1         0x50
-+#define I2S_RX1_CHMP_CTRL1    0x54
-+#define I2S_RX1_CHMP_CTRL2    0x55
-+#define I2S_RX1_CHMP_CTRL3    0x56
-+#define I2S_RX1_CHMP_CTRL4    0x57
-+
-+//I2S Loopback Debug
-+#define I2S_LPB_DEBUG         0x58
-+
-+//ADC Common Control
-+#define ADC_SPRC                      0x60
-+#define ADC_DIG_EN                    0x61
-+#define DMIC_EN                               0x62
-+#define ADC_DSR                               0x63
-+#define ADC_FIR                               0x64
-+#define ADC_DDT_CTRL          0x65
-+
-+//HPF Control
-+#define HPF_EN                                0x66
-+#define HPF_COEF_REGH1                0x67
-+#define HPF_COEF_REGH2                0x68
-+#define HPF_COEF_REGL1                0x69
-+#define HPF_COEF_REGL2                0x6A
-+#define HPF_GAIN_REGH1                0x6B
-+#define HPF_GAIN_REGH2                0x6C
-+#define HPF_GAIN_REGL1                0x6D
-+#define HPF_GAIN_REGL2                0x6E
-+
-+//ADC Digital Channel Volume Control
-+#define ADC1_DVOL_CTRL                0x70
-+#define ADC2_DVOL_CTRL                0x71
-+#define ADC3_DVOL_CTRL                0x72
-+#define ADC4_DVOL_CTRL                0x73
-+
-+//ADC Digital Mixer Source and Gain Control
-+#define ADC1_DMIX_SRC         0x76
-+#define ADC2_DMIX_SRC         0x77
-+#define ADC3_DMIX_SRC         0x78
-+#define ADC4_DMIX_SRC         0x79
-+
-+//ADC Digital Debug Control
-+#define ADC_DIG_DEBUG         0x7F
-+
-+//I2S Pad Drive Control
-+#define I2S_DAT_PADDRV_CTRL   0x80
-+#define I2S_CLK_PADDRV_CTRL   0x81
-+
-+//Analog PGA Control
-+#define ANA_PGA1_CTRL         0x90
-+#define ANA_PGA2_CTRL         0x91
-+#define ANA_PGA3_CTRL         0x92
-+#define ANA_PGA4_CTRL         0x93
-+
-+//MIC Offset Control
-+#define MIC_OFFSET_CTRL1      0x96
-+#define MIC_OFFSET_CTRL2      0x97
-+#define MIC1_OFFSET_STATU1    0x98
-+#define MIC1_OFFSET_STATU2    0x99
-+#define MIC2_OFFSET_STATU1    0x9A
-+#define MIC2_OFFSET_STATU2    0x9B
-+#define MIC3_OFFSET_STATU1    0x9C
-+#define MIC3_OFFSET_STATU2    0x9D
-+#define MIC4_OFFSET_STATU1    0x9E
-+#define MIC4_OFFSET_STATU2    0x9F
-+
-+//ADC1 Analog Control
-+#define ANA_ADC1_CTRL1                0xA0
-+#define ANA_ADC1_CTRL2                0xA1
-+#define ANA_ADC1_CTRL3                0xA2
-+#define ANA_ADC1_CTRL4                0xA3
-+#define ANA_ADC1_CTRL5                0xA4
-+#define ANA_ADC1_CTRL6                0xA5
-+#define ANA_ADC1_CTRL7                0xA6
-+
-+//ADC2 Analog Control
-+#define ANA_ADC2_CTRL1                0xA7
-+#define ANA_ADC2_CTRL2                0xA8
-+#define ANA_ADC2_CTRL3                0xA9
-+#define ANA_ADC2_CTRL4                0xAA
-+#define ANA_ADC2_CTRL5                0xAB
-+#define ANA_ADC2_CTRL6                0xAC
-+#define ANA_ADC2_CTRL7                0xAD
-+
-+//ADC3 Analog Control
-+#define ANA_ADC3_CTRL1                0xAE
-+#define ANA_ADC3_CTRL2                0xAF
-+#define ANA_ADC3_CTRL3                0xB0
-+#define ANA_ADC3_CTRL4                0xB1
-+#define ANA_ADC3_CTRL5                0xB2
-+#define ANA_ADC3_CTRL6                0xB3
-+#define ANA_ADC3_CTRL7                0xB4
-+
-+//ADC4 Analog Control
-+#define ANA_ADC4_CTRL1                0xB5
-+#define ANA_ADC4_CTRL2                0xB6
-+#define ANA_ADC4_CTRL3                0xB7
-+#define ANA_ADC4_CTRL4                0xB8
-+#define ANA_ADC4_CTRL5                0xB9
-+#define ANA_ADC4_CTRL6                0xBA
-+#define ANA_ADC4_CTRL7                0xBB
-+
-+//GPIO Configure
-+#define GPIO_CFG1                     0xC0
-+#define GPIO_CFG2                     0xC1
-+#define GPIO_DAT                      0xC2
-+#define GPIO_DRV                      0xC3
-+#define GPIO_PULL                     0xC4
-+#define GPIO_INT_CFG          0xC5
-+#define GPIO_INT_EN                   0xC6
-+#define GPIO_INT_STATUS               0xC7
-+
-+//Misc
-+#define BGTC_DAT                      0xD1
-+#define BGVC_DAT                      0xD2
-+#define PRNG_CLK_CTRL         0xDF
-+
-+/*** AC108 Codec Register Bit Define***/
-+
-+/*PWR_CTRL1*/
-+#define CP12_CTRL                             4
-+#define CP12_SENSE_SELECT             3
-+
-+/*PWR_CTRL2*/
-+#define CP12_SENSE_FILT                       6
-+#define CP12_COMP_FF_EN                       3
-+#define CP12_FORCE_ENABLE             2
-+#define CP12_FORCE_RSTB                       1
-+
-+/*PWR_CTRL3*/
-+#define LDO33DIG_CTRL                 0
-+
-+/*PWR_CTRL6*/
-+#define LDO33ANA_2XHDRM                       2
-+#define LDO33ANA_ENABLE                       0
-+
-+/*PWR_CTRL7*/
-+#define VREF_SEL                              3
-+#define VREF_FASTSTART_ENABLE 1
-+#define VREF_ENABLE                           0
-+
-+/*PWR_CTRL9*/
-+#define VREFP_FASTSTART_ENABLE        7
-+#define VREFP_RESCTRL                 5
-+#define VREFP_LPMODE                  4
-+#define IGEN_TRIM                             1
-+#define VREFP_ENABLE                  0
-+
-+/*PLL_CTRL1*/
-+#define PLL_IBIAS                             4
-+#define PLL_NDET                              3
-+#define PLL_LOCKED_STATUS             2
-+#define PLL_COM_EN                            1
-+#define PLL_EN                                        0
-+
-+/*PLL_CTRL2*/
-+#define PLL_PREDIV2                           5
-+#define PLL_PREDIV1                           0
-+
-+/*PLL_CTRL3*/
-+#define PLL_LOOPDIV_MSB                       0
-+
-+/*PLL_CTRL4*/
-+#define PLL_LOOPDIV_LSB                       0
-+
-+/*PLL_CTRL5*/
-+#define PLL_POSTDIV2                  5
-+#define PLL_POSTDIV1                  0
-+
-+/*PLL_CTRL6*/
-+#define PLL_LDO                                       6
-+#define PLL_CP                                        0
-+
-+/*PLL_CTRL7*/
-+#define PLL_CAP                                       6
-+#define PLL_RES                                       4
-+#define PLL_TEST_EN                           0
-+
-+/*PLL_LOCK_CTRL*/
-+#define LOCK_LEVEL1                           2
-+#define LOCK_LEVEL2                           1
-+#define PLL_LOCK_EN                           0
-+
-+/*SYSCLK_CTRL*/
-+#define PLLCLK_EN                             7
-+#define PLLCLK_SRC                            4
-+#define SYSCLK_SRC                            3
-+#define SYSCLK_EN                             0
-+
-+/*MOD_CLK_EN & MOD_RST_CTRL*/
-+#define I2S                                           7
-+#define ADC_DIGITAL                           4
-+#define MIC_OFFSET_CALIBRATION        1
-+#define ADC_ANALOG                            0
-+
-+/*DSM_CLK_CTRL*/
-+#define MIC_OFFSET_DIV                        4
-+#define DSM_CLK_SEL                           0
-+
-+/*I2S_CTRL*/
-+#define BCLK_IOEN                             7
-+#define LRCK_IOEN                             6
-+#define SDO2_EN                                       5
-+#define SDO1_EN                                       4
-+#define TXEN                                  2
-+#define RXEN                                  1
-+#define GEN                                           0
-+
-+/*I2S_BCLK_CTRL*/
-+#define EDGE_TRANSFER                 5
-+#define BCLK_POLARITY                 4
-+#define BCLKDIV                                       0
-+
-+/*I2S_LRCK_CTRL1*/
-+#define LRCK_POLARITY                 4
-+#define LRCK_PERIODH                  0
-+
-+/*I2S_LRCK_CTRL2*/
-+#define LRCK_PERIODL                  0
-+
-+/*I2S_FMT_CTRL1*/
-+#define ENCD_SEL                              6
-+#define MODE_SEL                              4
-+#define TX2_OFFSET                            3
-+#define TX1_OFFSET                            2
-+#define TX_SLOT_HIZ                           1
-+#define TX_STATE                              0
-+
-+/*I2S_FMT_CTRL2*/
-+#define SLOT_WIDTH_SEL                        4
-+#define SAMPLE_RESOLUTION             0
-+
-+/*I2S_FMT_CTRL3*/
-+#define TX_MLS                                        7
-+#define SEXT                                  5
-+#define OUT2_MUTE                             4
-+#define OUT1_MUTE                             3
-+#define LRCK_WIDTH                            2
-+#define TX_PDM                                        0
-+
-+/*I2S_TX1_CTRL1*/
-+#define TX1_CHSEL                             0
-+
-+/*I2S_TX1_CTRL2*/
-+#define TX1_CH8_EN                            7
-+#define TX1_CH7_EN                            6
-+#define TX1_CH6_EN                            5
-+#define TX1_CH5_EN                            4
-+#define TX1_CH4_EN                            3
-+#define TX1_CH3_EN                            2
-+#define TX1_CH2_EN                            1
-+#define TX1_CH1_EN                            0
-+
-+/*I2S_TX1_CTRL3*/
-+#define TX1_CH16_EN                           7
-+#define TX1_CH15_EN                           6
-+#define TX1_CH14_EN                           5
-+#define TX1_CH13_EN                           4
-+#define TX1_CH12_EN                           3
-+#define TX1_CH11_EN                           2
-+#define TX1_CH10_EN                           1
-+#define TX1_CH9_EN                            0
-+
-+/*I2S_TX1_CHMP_CTRL1*/
-+#define TX1_CH4_MAP                           6
-+#define TX1_CH3_MAP                           4
-+#define TX1_CH2_MAP                           2
-+#define TX1_CH1_MAP                           0
-+
-+/*I2S_TX1_CHMP_CTRL2*/
-+#define TX1_CH8_MAP                           6
-+#define TX1_CH7_MAP                           4
-+#define TX1_CH6_MAP                           2
-+#define TX1_CH5_MAP                           0
-+
-+/*I2S_TX1_CHMP_CTRL3*/
-+#define TX1_CH12_MAP                  6
-+#define TX1_CH11_MAP                  4
-+#define TX1_CH10_MAP                  2
-+#define TX1_CH9_MAP                           0
-+
-+/*I2S_TX1_CHMP_CTRL4*/
-+#define TX1_CH16_MAP                  6
-+#define TX1_CH15_MAP                  4
-+#define TX1_CH14_MAP                  2
-+#define TX1_CH13_MAP                  0
-+
-+/*I2S_TX2_CTRL1*/
-+#define TX2_CHSEL                             0
-+
-+/*I2S_TX2_CHMP_CTRL1*/
-+#define TX2_CH4_MAP                           6
-+#define TX2_CH3_MAP                           4
-+#define TX2_CH2_MAP                           2
-+#define TX2_CH1_MAP                           0
-+
-+/*I2S_TX2_CHMP_CTRL2*/
-+#define TX2_CH8_MAP                           6
-+#define TX2_CH7_MAP                           4
-+#define TX2_CH6_MAP                           2
-+#define TX2_CH5_MAP                           0
-+
-+/*I2S_TX2_CHMP_CTRL3*/
-+#define TX2_CH12_MAP                  6
-+#define TX2_CH11_MAP                  4
-+#define TX2_CH10_MAP                  2
-+#define TX2_CH9_MAP                           0
-+
-+/*I2S_TX2_CHMP_CTRL4*/
-+#define TX2_CH16_MAP                  6
-+#define TX2_CH15_MAP                  4
-+#define TX2_CH14_MAP                  2
-+#define TX2_CH13_MAP                  0
-+
-+/*I2S_RX1_CTRL1*/
-+#define RX1_CHSEL                             0
-+
-+/*I2S_RX1_CHMP_CTRL1*/
-+#define RX1_CH4_MAP                           6
-+#define RX1_CH3_MAP                           4
-+#define RX1_CH2_MAP                           2
-+#define RX1_CH1_MAP                           0
-+
-+/*I2S_RX1_CHMP_CTRL2*/
-+#define RX1_CH8_MAP                           6
-+#define RX1_CH7_MAP                           4
-+#define RX1_CH6_MAP                           2
-+#define RX1_CH5_MAP                           0
-+
-+/*I2S_RX1_CHMP_CTRL3*/
-+#define RX1_CH12_MAP                  6
-+#define RX1_CH11_MAP                  4
-+#define RX1_CH10_MAP                  2
-+#define RX1_CH9_MAP                           0
-+
-+/*I2S_RX1_CHMP_CTRL4*/
-+#define RX1_CH16_MAP                  6
-+#define RX1_CH15_MAP                  4
-+#define RX1_CH14_MAP                  2
-+#define RX1_CH13_MAP                  0
-+
-+/*I2S_LPB_DEBUG*/
-+#define I2S_LPB_DEBUG_EN              0
-+
-+/*ADC_SPRC*/
-+#define ADC_FS_I2S1                           0
-+
-+/*ADC_DIG_EN*/
-+#define DG_EN                                 4
-+#define ENAD4                                 3
-+#define ENAD3                                 2
-+#define ENAD2                                 1
-+#define ENAD1                                 0
-+
-+/*DMIC_EN*/
-+#define DMIC2_EN                              1
-+#define DMIC1_EN                              0
-+
-+/*ADC_DSR*/
-+#define DIG_ADC4_SRS                  6
-+#define DIG_ADC3_SRS                  4
-+#define DIG_ADC2_SRS                  2
-+#define DIG_ADC1_SRS                  0
-+
-+/*ADC_DDT_CTRL*/
-+#define ADOUT_DLY_EN                  2
-+#define ADOUT_DTS                             0
-+
-+/*HPF_EN*/
-+#define DIG_ADC4_HPF_EN                       3
-+#define DIG_ADC3_HPF_EN                       2
-+#define DIG_ADC2_HPF_EN                       1
-+#define DIG_ADC1_HPF_EN                       0
-+
-+/*ADC1_DMIX_SRC*/
-+#define ADC1_ADC4_DMXL_GC             7
-+#define ADC1_ADC3_DMXL_GC             6
-+#define ADC1_ADC2_DMXL_GC             5
-+#define ADC1_ADC1_DMXL_GC             4
-+#define ADC1_ADC4_DMXL_SRC            3
-+#define ADC1_ADC3_DMXL_SRC            2
-+#define ADC1_ADC2_DMXL_SRC            1
-+#define ADC1_ADC1_DMXL_SRC            0
-+
-+/*ADC2_DMIX_SRC*/
-+#define ADC2_ADC4_DMXL_GC             7
-+#define ADC2_ADC3_DMXL_GC             6
-+#define ADC2_ADC2_DMXL_GC             5
-+#define ADC2_ADC1_DMXL_GC             4
-+#define ADC2_ADC4_DMXL_SRC            3
-+#define ADC2_ADC3_DMXL_SRC            2
-+#define ADC2_ADC2_DMXL_SRC            1
-+#define ADC2_ADC1_DMXL_SRC            0
-+
-+/*ADC3_DMIX_SRC*/
-+#define ADC3_ADC4_DMXL_GC             7
-+#define ADC3_ADC3_DMXL_GC             6
-+#define ADC3_ADC2_DMXL_GC             5
-+#define ADC3_ADC1_DMXL_GC             4
-+#define ADC3_ADC4_DMXL_SRC            3
-+#define ADC3_ADC3_DMXL_SRC            2
-+#define ADC3_ADC2_DMXL_SRC            1
-+#define ADC3_ADC1_DMXL_SRC            0
-+
-+/*ADC4_DMIX_SRC*/
-+#define ADC4_ADC4_DMXL_GC             7
-+#define ADC4_ADC3_DMXL_GC             6
-+#define ADC4_ADC2_DMXL_GC             5
-+#define ADC4_ADC1_DMXL_GC             4
-+#define ADC4_ADC4_DMXL_SRC            3
-+#define ADC4_ADC3_DMXL_SRC            2
-+#define ADC4_ADC2_DMXL_SRC            1
-+#define ADC4_ADC1_DMXL_SRC            0
-+
-+/*ADC_DIG_DEBUG*/
-+#define ADC_PTN_SEL                           0
-+
-+/*I2S_DAT_PADDRV_CTRL*/
-+#define TX2_DAT_DRV                           4
-+#define TX1_DAT_DRV                           0
-+
-+/*I2S_CLK_PADDRV_CTRL*/
-+#define LRCK_DRV                              4
-+#define BCLK_DRV                              0
-+
-+/*ANA_PGA1_CTRL*/
-+#define ADC1_ANALOG_PGA                       1
-+#define ADC1_ANALOG_PGA_STEP  0
-+
-+/*ANA_PGA2_CTRL*/
-+#define ADC2_ANALOG_PGA                       1
-+#define ADC2_ANALOG_PGA_STEP  0
-+
-+/*ANA_PGA3_CTRL*/
-+#define ADC3_ANALOG_PGA                       1
-+#define ADC3_ANALOG_PGA_STEP  0
-+
-+/*ANA_PGA4_CTRL*/
-+#define ADC4_ANALOG_PGA                       1
-+#define ADC4_ANALOG_PGA_STEP  0
-+
-+
-+/*MIC_OFFSET_CTRL1*/
-+#define MIC_OFFSET_CAL_EN4            3
-+#define MIC_OFFSET_CAL_EN3            2
-+#define MIC_OFFSET_CAL_EN2            1
-+#define MIC_OFFSET_CAL_EN1            0
-+
-+/*MIC_OFFSET_CTRL2*/
-+#define MIC_OFFSET_CAL_GAIN           3
-+#define MIC_OFFSET_CAL_CHANNEL        1
-+#define MIC_OFFSET_CAL_EN_ONCE        0
-+
-+/*MIC1_OFFSET_STATU1*/
-+#define MIC1_OFFSET_CAL_DONE  7
-+#define MIC1_OFFSET_CAL_RUN_STA       6
-+#define MIC1_OFFSET_MSB                       0
-+
-+/*MIC1_OFFSET_STATU2*/
-+#define MIC1_OFFSET_LSB                       0
-+
-+/*MIC2_OFFSET_STATU1*/
-+#define MIC2_OFFSET_CAL_DONE  7
-+#define MIC2_OFFSET_CAL_RUN_STA       6
-+#define MIC2_OFFSET_MSB                       0
-+
-+/*MIC2_OFFSET_STATU2*/
-+#define MIC2_OFFSET_LSB                       0
-+
-+/*MIC3_OFFSET_STATU1*/
-+#define MIC3_OFFSET_CAL_DONE  7
-+#define MIC3_OFFSET_CAL_RUN_STA       6
-+#define MIC3_OFFSET_MSB                       0
-+
-+/*MIC3_OFFSET_STATU2*/
-+#define MIC3_OFFSET_LSB                       0
-+
-+/*MIC4_OFFSET_STATU1*/
-+#define MIC4_OFFSET_CAL_DONE  7
-+#define MIC4_OFFSET_CAL_RUN_STA       6
-+#define MIC4_OFFSET_MSB                       0
-+
-+/*MIC4_OFFSET_STATU2*/
-+#define MIC4_OFFSET_LSB                       0
-+
-+/*ANA_ADC1_CTRL1*/
-+#define ADC1_PGA_BYPASS                       7
-+#define ADC1_PGA_BYP_RCM              6
-+#define ADC1_PGA_CTRL_RCM             4
-+#define ADC1_PGA_MUTE                 3
-+#define ADC1_DSM_ENABLE                       2
-+#define ADC1_PGA_ENABLE                       1
-+#define ADC1_MICBIAS_EN                       0
-+
-+/*ANA_ADC1_CTRL3*/
-+#define ADC1_ANA_CAL_EN                       5
-+#define ADC1_SEL_OUT_EDGE             3
-+#define ADC1_DSM_DISABLE              2
-+#define ADC1_VREFP_DISABLE            1
-+#define ADC1_AAF_DISABLE              0
-+
-+/*ANA_ADC1_CTRL6*/
-+#define PGA_CTRL_TC                           6
-+#define PGA_CTRL_RC                           4
-+#define PGA_CTRL_I_LIN                        2
-+#define PGA_CTRL_I_IN                 0
-+
-+/*ANA_ADC1_CTRL7*/
-+#define PGA_CTRL_HI_Z                 7
-+#define PGA_CTRL_SHORT_RF             6
-+#define PGA_CTRL_VCM_VG                       4
-+#define PGA_CTRL_VCM_IN                       0
-+
-+/*ANA_ADC2_CTRL1*/
-+#define ADC2_PGA_BYPASS                       7
-+#define ADC2_PGA_BYP_RCM              6
-+#define ADC2_PGA_CTRL_RCM             4
-+#define ADC2_PGA_MUTE                 3
-+#define ADC2_DSM_ENABLE                       2
-+#define ADC2_PGA_ENABLE                       1
-+#define ADC2_MICBIAS_EN                       0
-+
-+/*ANA_ADC2_CTRL3*/
-+#define ADC2_ANA_CAL_EN                       5
-+#define ADC2_SEL_OUT_EDGE             3
-+#define ADC2_DSM_DISABLE              2
-+#define ADC2_VREFP_DISABLE            1
-+#define ADC2_AAF_DISABLE              0
-+
-+/*ANA_ADC2_CTRL6*/
-+#define PGA_CTRL_IBOOST                       7
-+#define PGA_CTRL_IQCTRL                       6
-+#define PGA_CTRL_OABIAS                       4
-+#define PGA_CTRL_CMLP_DIS             3
-+#define PGA_CTRL_PDB_RIN              2
-+#define PGA_CTRL_PEAKDET              0
-+
-+/*ANA_ADC2_CTRL7*/
-+#define AAF_LPMODE_EN                 7
-+#define AAF_STG2_IB_SEL                       4
-+#define AAFDSM_IB_DIV2                        3
-+#define AAF_STG1_IB_SEL                       0
-+
-+/*ANA_ADC3_CTRL1*/
-+#define ADC3_PGA_BYPASS                       7
-+#define ADC3_PGA_BYP_RCM              6
-+#define ADC3_PGA_CTRL_RCM             4
-+#define ADC3_PGA_MUTE                 3
-+#define ADC3_DSM_ENABLE                       2
-+#define ADC3_PGA_ENABLE                       1
-+#define ADC3_MICBIAS_EN                       0
-+
-+/*ANA_ADC3_CTRL3*/
-+#define ADC3_ANA_CAL_EN                       5
-+#define ADC3_INVERT_CLK                       4
-+#define ADC3_SEL_OUT_EDGE             3
-+#define ADC3_DSM_DISABLE              2
-+#define ADC3_VREFP_DISABLE            1
-+#define ADC3_AAF_DISABLE              0
-+
-+/*ANA_ADC3_CTRL7*/
-+#define DSM_COMP_IB_SEL                       6
-+#define DSM_OTA_CTRL                  4
-+#define DSM_LPMODE                            3
-+#define DSM_OTA_IB_SEL                        0
-+
-+/*ANA_ADC4_CTRL1*/
-+#define ADC4_PGA_BYPASS                       7
-+#define ADC4_PGA_BYP_RCM              6
-+#define ADC4_PGA_CTRL_RCM             4
-+#define ADC4_PGA_MUTE                 3
-+#define ADC4_DSM_ENABLE                       2
-+#define ADC4_PGA_ENABLE                       1
-+#define ADC4_MICBIAS_EN                       0
-+
-+/*ANA_ADC4_CTRL3*/
-+#define ADC4_ANA_CAL_EN                       5
-+#define ADC4_SEL_OUT_EDGE             3
-+#define ADC4_DSM_DISABLE              2
-+#define ADC4_VREFP_DISABLE            1
-+#define ADC4_AAF_DISABLE              0
-+
-+/*ANA_ADC4_CTRL6*/
-+#define DSM_DEMOFF                            5
-+#define DSM_EN_DITHER                 4
-+#define DSM_VREFP_LPMODE              2
-+#define DSM_VREFP_OUTCTRL             0
-+
-+/*ANA_ADC4_CTRL7*/
-+#define CK8M_EN                                       5
-+#define OSC_EN                                        4
-+#define ADC4_CLK_GATING                       3
-+#define ADC3_CLK_GATING                       2
-+#define ADC2_CLK_GATING                       1
-+#define ADC1_CLK_GATING                       0
-+
-+/*GPIO_CFG1*/
-+#define GPIO2_SELECT                  4
-+#define GPIO1_SELECT                  0
-+
-+/*GPIO_CFG2*/
-+#define GPIO4_SELECT                  4
-+#define GPIO3_SELECT                  0
-+
-+/*GPIO_DAT*///order???
-+#define GPIO4_DAT                             3
-+#define GPIO3_DAT                             2
-+#define GPIO2_DAT                             1
-+#define GPIO1_DAT                             0
-+
-+/*GPIO_DRV*/
-+#define GPIO4_DRV                             6
-+#define GPIO3_DRV                             4
-+#define GPIO2_DRV                             2
-+#define GPIO1_DRV                             0
-+
-+/*GPIO_PULL*/
-+#define GPIO4_PULL                            6
-+#define GPIO3_PULL                            4
-+#define GPIO2_PULL                            2
-+#define GPIO1_PULL                            0
-+
-+/*GPIO_INT_CFG*/
-+#define GPIO4_EINT_CFG                        6
-+#define GPIO3_EINT_CFG                        4
-+#define GPIO2_EINT_CFG                        2
-+#define GPIO1_EINT_CFG                        0
-+
-+/*GPIO_INT_EN*///order???
-+#define GPIO4_EINT_EN                 3
-+#define GPIO3_EINT_EN                 2
-+#define GPIO2_EINT_EN                 1
-+#define GPIO1_EINT_EN                 0
-+
-+/*GPIO_INT_STATUS*///order???
-+#define GPIO4_EINT_STA                        3
-+#define GPIO3_EINT_STA                        2
-+#define GPIO2_EINT_STA                        1
-+#define GPIO1_EINT_STA                        0
-+
-+/*PRNG_CLK_CTRL*/
-+#define PRNG_CLK_EN                           1
-+#define PRNG_CLK_POS                  0
-+
-+/*** Some Config Value ***/
-+
-+//[SYSCLK_CTRL]: PLLCLK_SRC
-+#define PLLCLK_SRC_MCLK                       0
-+#define PLLCLK_SRC_BCLK                       1
-+#define PLLCLK_SRC_GPIO2              2
-+#define PLLCLK_SRC_GPIO3              3
-+
-+//[SYSCLK_CTRL]: SYSCLK_SRC
-+#define SYSCLK_SRC_MCLK                       0
-+#define SYSCLK_SRC_PLL                        1
-+
-+//I2S BCLK POLARITY Control
-+#define BCLK_NORMAL_DRIVE_N_SAMPLE_P  0
-+#define BCLK_INVERT_DRIVE_P_SAMPLE_N  1
-+
-+//I2S LRCK POLARITY Control
-+#define       LRCK_LEFT_LOW_RIGHT_HIGH                0
-+#define LRCK_LEFT_HIGH_RIGHT_LOW              1
-+
-+//I2S Format Selection
-+#define PCM_FORMAT                                            0
-+#define LEFT_JUSTIFIED_FORMAT                 1
-+#define RIGHT_JUSTIFIED_FORMAT                        2
-+
-+//I2S data protocol types
-+
-+#define IS_ENCODING_MODE               0
-+
-+#endif
-+
---- /dev/null
-+++ b/sound/soc/codecs/ac10x.h
-@@ -0,0 +1,152 @@
-+/*
-+ * ac10x.h
-+ *
-+ * (C) Copyright 2017-2018
-+ * Seeed Technology Co., Ltd. <www.seeedstudio.com>
-+ *
-+ * PeterYang <linsheng.yang@seeed.cc>
-+ *
-+ * (C) Copyright 2010-2017
-+ * Reuuimlla Technology Co., Ltd. <www.reuuimllatech.com>
-+ * huangxin <huangxin@reuuimllatech.com>
-+ *
-+ * some simple description for this code
-+ *
-+ * This program is free software; you can redistribute it and/or
-+ * modify it under the terms of the GNU General Public License as
-+ * published by the Free Software Foundation; either version 2 of
-+ * the License, or (at your option) any later version.
-+ *
-+ */
-+#ifndef __AC10X_H__
-+#define __AC10X_H__
-+
-+#define AC101_I2C_ID          4
-+#define _MASTER_AC108         0
-+#define _MASTER_AC101         1
-+#define _MASTER_MULTI_CODEC   _MASTER_AC101
-+
-+/* enable headset detecting & headset button pressing */
-+#define CONFIG_AC101_SWITCH_DETECT
-+
-+/* obsolete */
-+#define CONFIG_AC10X_TRIG_LOCK        0
-+
-+#ifdef AC101_DEBG
-+    #define AC101_DBG(format,args...)  printk("[AC101] %s() L%d " format, __func__, __LINE__, ##args)
-+#else
-+    #define AC101_DBG(...)
-+#endif
-+
-+#include <linux/version.h>
-+
-+#if LINUX_VERSION_CODE >= KERNEL_VERSION(4,18,0)
-+#define __NO_SND_SOC_CODEC_DRV     1
-+#else
-+#define __NO_SND_SOC_CODEC_DRV     0
-+#endif
-+
-+#if LINUX_VERSION_CODE < KERNEL_VERSION(5,4,0)
-+#if __has_attribute(__fallthrough__)
-+# define fallthrough                    __attribute__((__fallthrough__))
-+#else
-+# define fallthrough                    do {} while (0)  /* fallthrough */
-+#endif
-+#endif
-+
-+#if __NO_SND_SOC_CODEC_DRV
-+#define codec                      component
-+#define snd_soc_codec              snd_soc_component
-+#define snd_soc_codec_driver       snd_soc_component_driver
-+#define snd_soc_codec_get_drvdata  snd_soc_component_get_drvdata
-+#define snd_soc_codec_get_dapm     snd_soc_component_get_dapm
-+#define snd_soc_codec_get_bias_level snd_soc_component_get_bias_level
-+#define snd_soc_kcontrol_codec     snd_soc_kcontrol_component
-+#define snd_soc_read               snd_soc_component_read32
-+#define snd_soc_register_codec     snd_soc_register_component
-+#define snd_soc_unregister_codec   snd_soc_unregister_component
-+#define snd_soc_update_bits        snd_soc_component_update_bits
-+#define snd_soc_write              snd_soc_component_write
-+#define snd_soc_add_codec_controls snd_soc_add_component_controls
-+#endif
-+
-+
-+#ifdef CONFIG_AC101_SWITCH_DETECT
-+enum headphone_mode_u {
-+      HEADPHONE_IDLE,
-+      FOUR_HEADPHONE_PLUGIN,
-+      THREE_HEADPHONE_PLUGIN,
-+};
-+#endif
-+
-+struct ac10x_priv {
-+      struct i2c_client *i2c[4];
-+      struct regmap* i2cmap[4];
-+      int codec_cnt;
-+      unsigned sysclk;
-+#define _FREQ_24_576K         24576000
-+#define _FREQ_22_579K         22579200
-+      unsigned mclk;  /* master clock or aif_clock/aclk */
-+      int clk_id;
-+      unsigned char i2s_mode;
-+      unsigned char data_protocol;
-+      struct delayed_work dlywork;
-+      int tdm_chips_cnt;
-+      int sysclk_en;
-+
-+      /* member for ac101 .begin */
-+      struct snd_soc_codec *codec;
-+      struct i2c_client *i2c101;
-+      struct regmap* regmap101;
-+
-+      struct mutex dac_mutex;
-+      u8 dac_enable;
-+      spinlock_t lock;
-+      u8 aif1_clken;
-+
-+      struct work_struct codec_resume;
-+      struct gpio_desc* gpiod_spk_amp_gate;
-+
-+      #ifdef CONFIG_AC101_SWITCH_DETECT
-+      struct gpio_desc* gpiod_irq;
-+      long irq;
-+      volatile int irq_cntr;
-+      volatile int pullout_cntr;
-+      volatile int state;
-+
-+      enum headphone_mode_u mode;
-+      struct work_struct work_switch;
-+      struct work_struct work_clear_irq;
-+
-+      struct input_dev* inpdev;
-+      #endif
-+      /* member for ac101 .end */
-+};
-+
-+
-+/* AC101 DAI operations */
-+int ac101_audio_startup(struct snd_pcm_substream *substream, struct snd_soc_dai *codec_dai);
-+void ac101_aif_shutdown(struct snd_pcm_substream *substream, struct snd_soc_dai *codec_dai);
-+int ac101_set_dai_fmt(struct snd_soc_dai *codec_dai, unsigned int fmt);
-+int ac101_hw_params(struct snd_pcm_substream *substream,
-+      struct snd_pcm_hw_params *params,
-+      struct snd_soc_dai *codec_dai);
-+int ac101_trigger(struct snd_pcm_substream *substream, int cmd,
-+                struct snd_soc_dai *dai);
-+int ac101_aif_mute(struct snd_soc_dai *codec_dai, int mute);
-+
-+/* codec driver specific */
-+int ac101_codec_probe(struct snd_soc_codec *codec);
-+int ac101_codec_remove(struct snd_soc_codec *codec);
-+int ac101_codec_suspend(struct snd_soc_codec *codec);
-+int ac101_codec_resume(struct snd_soc_codec *codec);
-+int ac101_set_bias_level(struct snd_soc_codec *codec, enum snd_soc_bias_level level);
-+
-+/* i2c device specific */
-+int ac101_probe(struct i2c_client *i2c, const struct i2c_device_id *id);
-+void ac101_shutdown(struct i2c_client *i2c);
-+int ac101_remove(struct i2c_client *i2c);
-+
-+int ac10x_fill_regcache(struct device* dev, struct regmap* map);
-+
-+#endif//__AC10X_H__
diff --git a/target/linux/starfive/patches-6.6/0080-ASoC-starfive-Add-SPDIF-and-PCM-driver.patch b/target/linux/starfive/patches-6.6/0080-ASoC-starfive-Add-SPDIF-and-PCM-driver.patch
deleted file mode 100644 (file)
index f2fb206..0000000
+++ /dev/null
@@ -1,1169 +0,0 @@
-From f03b7c834baef87e4f740e10a8bbcbfc57bd985a Mon Sep 17 00:00:00 2001
-From: Xingyu Wu <xingyu.wu@starfivetech.com>
-Date: Thu, 15 Jun 2023 11:32:50 +0800
-Subject: [PATCH 080/116] ASoC: starfive: Add SPDIF and PCM driver
-
-Add SPDIF and SPDIF-PCM driver for StarFive JH7110.
-
-Signed-off-by: Xingyu Wu <xingyu.wu@starfivetech.com>
-Signed-off-by: Hal Feng <hal.feng@starfivetech.com>
----
- sound/soc/starfive/Kconfig            |  17 +
- sound/soc/starfive/Makefile           |   5 +
- sound/soc/starfive/jh7110_spdif.c     | 568 ++++++++++++++++++++++++++
- sound/soc/starfive/jh7110_spdif.h     | 196 +++++++++
- sound/soc/starfive/jh7110_spdif_pcm.c | 339 +++++++++++++++
- 5 files changed, 1125 insertions(+)
- create mode 100644 sound/soc/starfive/jh7110_spdif.c
- create mode 100644 sound/soc/starfive/jh7110_spdif.h
- create mode 100644 sound/soc/starfive/jh7110_spdif_pcm.c
-
---- a/sound/soc/starfive/Kconfig
-+++ b/sound/soc/starfive/Kconfig
-@@ -16,6 +16,23 @@ config SND_SOC_JH7110_PWMDAC
-        Say Y or M if you want to add support for StarFive JH7110
-        PWM-DAC driver.
-+config SND_SOC_JH7110_SPDIF
-+      tristate "JH7110 SPDIF module"
-+      depends on HAVE_CLK && SND_SOC_STARFIVE
-+      select SND_SOC_GENERIC_DMAENGINE_PCM
-+      select REGMAP_MMIO
-+      help
-+        Say Y or M if you want to add support for SPDIF driver of StarFive
-+        JH7110 SoC.
-+
-+config SND_SOC_JH7110_SPDIF_PCM
-+      bool "PCM PIO extension for JH7110 SPDIF"
-+      depends on SND_SOC_JH7110_SPDIF
-+      default y if SND_SOC_JH7110_SPDIF
-+      help
-+        Say Y or N if you want to add a custom ALSA extension that registers
-+        a PCM and uses PIO to transfer data.
-+
- config SND_SOC_JH7110_TDM
-       tristate "JH7110 TDM device driver"
-       depends on HAVE_CLK && SND_SOC_STARFIVE
---- a/sound/soc/starfive/Makefile
-+++ b/sound/soc/starfive/Makefile
-@@ -1,3 +1,8 @@
- # StarFive Platform Support
- obj-$(CONFIG_SND_SOC_JH7110_PWMDAC) += jh7110_pwmdac.o
-+
-+obj-$(CONFIG_SND_SOC_JH7110_SPDIF) += spdif.o
-+spdif-y := jh7110_spdif.o
-+spdif-$(CONFIG_SND_SOC_JH7110_SPDIF_PCM) += jh7110_spdif_pcm.o
-+
- obj-$(CONFIG_SND_SOC_JH7110_TDM) += jh7110_tdm.o
---- /dev/null
-+++ b/sound/soc/starfive/jh7110_spdif.c
-@@ -0,0 +1,568 @@
-+// SPDX-License-Identifier: GPL-2.0
-+/*
-+ * SPDIF driver for the StarFive JH7110 SoC
-+ *
-+ * Copyright (C) 2022 StarFive Technology Co., Ltd.
-+ */
-+
-+#include <linux/clk.h>
-+#include <linux/init.h>
-+#include <linux/kernel.h>
-+#include <linux/module.h>
-+#include <linux/of.h>
-+#include <linux/platform_device.h>
-+#include <linux/pm_runtime.h>
-+#include <linux/regmap.h>
-+#include <linux/reset.h>
-+#include <linux/slab.h>
-+#include <sound/core.h>
-+#include <sound/dmaengine_pcm.h>
-+#include <sound/initval.h>
-+#include <sound/pcm.h>
-+#include <sound/pcm_params.h>
-+#include <sound/soc.h>
-+
-+#include "jh7110_spdif.h"
-+
-+static irqreturn_t spdif_irq_handler(int irq, void *dev_id)
-+{
-+      struct sf_spdif_dev *dev = dev_id;
-+      bool irq_valid = false;
-+      unsigned int intr;
-+      unsigned int stat;
-+
-+      regmap_read(dev->regmap, SPDIF_INT_REG, &intr);
-+      regmap_read(dev->regmap, SPDIF_STAT_REG, &stat);
-+      regmap_update_bits(dev->regmap, SPDIF_CTRL, SPDIF_MASK_ENABLE, 0);
-+      regmap_update_bits(dev->regmap, SPDIF_INT_REG, SPDIF_INT_REG_BIT, 0);
-+
-+      if ((stat & SPDIF_EMPTY_FLAG) || (stat & SPDIF_AEMPTY_FLAG)) {
-+              sf_spdif_pcm_push_tx(dev);
-+              irq_valid = true;
-+      }
-+
-+      if ((stat & SPDIF_FULL_FLAG) || (stat & SPDIF_AFULL_FLAG)) {
-+              sf_spdif_pcm_pop_rx(dev);
-+              irq_valid = true;
-+      }
-+
-+      if (stat & SPDIF_PARITY_FLAG)
-+              irq_valid = true;
-+
-+      if (stat & SPDIF_UNDERR_FLAG)
-+              irq_valid = true;
-+
-+      if (stat & SPDIF_OVRERR_FLAG)
-+              irq_valid = true;
-+
-+      if (stat & SPDIF_SYNCERR_FLAG)
-+              irq_valid = true;
-+
-+      if (stat & SPDIF_LOCK_FLAG)
-+              irq_valid = true;
-+
-+      if (stat & SPDIF_BEGIN_FLAG)
-+              irq_valid = true;
-+
-+      if (stat & SPDIF_RIGHT_LEFT)
-+              irq_valid = true;
-+
-+      regmap_update_bits(dev->regmap, SPDIF_CTRL,
-+              SPDIF_MASK_ENABLE, SPDIF_MASK_ENABLE);
-+
-+      if (irq_valid)
-+              return IRQ_HANDLED;
-+      else
-+              return IRQ_NONE;
-+}
-+
-+static int sf_spdif_trigger(struct snd_pcm_substream *substream, int cmd,
-+                          struct snd_soc_dai *dai)
-+{
-+      struct sf_spdif_dev *spdif = snd_soc_dai_get_drvdata(dai);
-+      bool tx = substream->stream == SNDRV_PCM_STREAM_PLAYBACK;
-+
-+      if (tx) {
-+              /* tx mode */
-+              regmap_update_bits(spdif->regmap, SPDIF_CTRL,
-+                                 SPDIF_TR_MODE, SPDIF_TR_MODE);
-+
-+              regmap_update_bits(spdif->regmap, SPDIF_CTRL,
-+                                 SPDIF_MASK_FIFO, SPDIF_EMPTY_MASK | SPDIF_AEMPTY_MASK);
-+      } else {
-+              /* rx mode */
-+              regmap_update_bits(spdif->regmap, SPDIF_CTRL,
-+                                 SPDIF_TR_MODE, 0);
-+
-+              regmap_update_bits(spdif->regmap, SPDIF_CTRL,
-+                                 SPDIF_MASK_FIFO, SPDIF_FULL_MASK | SPDIF_AFULL_MASK);
-+      }
-+
-+      switch (cmd) {
-+      case SNDRV_PCM_TRIGGER_START:
-+      case SNDRV_PCM_TRIGGER_RESUME:
-+      case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
-+              /* clock recovery form the SPDIF data stream  0:clk_enable */
-+              regmap_update_bits(spdif->regmap, SPDIF_CTRL,
-+                                 SPDIF_CLK_ENABLE, 0);
-+
-+              regmap_update_bits(spdif->regmap, SPDIF_CTRL,
-+                                 SPDIF_ENABLE, SPDIF_ENABLE);
-+              break;
-+      case SNDRV_PCM_TRIGGER_STOP:
-+      case SNDRV_PCM_TRIGGER_SUSPEND:
-+      case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
-+              /* clock recovery form the SPDIF data stream  1:power save mode */
-+              regmap_update_bits(spdif->regmap, SPDIF_CTRL,
-+                                 SPDIF_CLK_ENABLE, SPDIF_CLK_ENABLE);
-+              regmap_update_bits(spdif->regmap, SPDIF_CTRL,
-+                                 SPDIF_ENABLE, 0);
-+              break;
-+      default:
-+              dev_err(dai->dev, "%s L.%d cmd:%d\n", __func__, __LINE__, cmd);
-+              return -EINVAL;
-+      }
-+
-+      return 0;
-+}
-+
-+static int sf_spdif_hw_params(struct snd_pcm_substream *substream,
-+                            struct snd_pcm_hw_params *params, struct snd_soc_dai *dai)
-+{
-+      struct sf_spdif_dev *spdif = snd_soc_dai_get_drvdata(dai);
-+      unsigned int channels = params_channels(params);
-+      unsigned int rate = params_rate(params);
-+      unsigned int format = params_format(params);
-+      unsigned int tsamplerate;
-+      unsigned int mclk;
-+      unsigned int audio_root;
-+      int ret;
-+
-+      switch (channels) {
-+      case 1:
-+              regmap_update_bits(spdif->regmap, SPDIF_CTRL,
-+                                 SPDIF_CHANNEL_MODE, SPDIF_CHANNEL_MODE);
-+              regmap_update_bits(spdif->regmap, SPDIF_CTRL,
-+                                 SPDIF_DUPLICATE, SPDIF_DUPLICATE);
-+              spdif->channels = false;
-+              break;
-+      case 2:
-+              regmap_update_bits(spdif->regmap, SPDIF_CTRL,
-+                                 SPDIF_CHANNEL_MODE, 0);
-+              spdif->channels = true;
-+              break;
-+      default:
-+              dev_err(dai->dev, "invalid channels number\n");
-+              return -EINVAL;
-+      }
-+
-+      switch (format) {
-+      case SNDRV_PCM_FORMAT_S16_LE:
-+      case SNDRV_PCM_FORMAT_S24_LE:
-+      case SNDRV_PCM_FORMAT_S24_3LE:
-+      case SNDRV_PCM_FORMAT_S32_LE:
-+              break;
-+      default:
-+              dev_err(dai->dev, "invalid format\n");
-+              return -EINVAL;
-+      }
-+
-+      switch (rate) {
-+      case 8000:
-+              break;
-+      case 11025:
-+              audio_root = 148500000;
-+              /* 11025 * 512 = 5644800 */
-+              /* But now pll2 is 1188m and mclk should be 5711539 closely. */
-+              mclk = 5711539;
-+              break;
-+      case 16000:
-+              break;
-+      case 22050:
-+              audio_root = 148500000;
-+              mclk = 11423077;
-+              break;
-+      default:
-+              dev_err(dai->dev, "channel:%d sample rate:%d\n", channels, rate);
-+              return -EINVAL;
-+      }
-+
-+      /* use mclk_inner clock from 1188m PLL2 will be better about 11k and 22k*/
-+      if ((rate == 11025) || (rate == 22050)) {
-+              ret = clk_set_parent(spdif->mclk, spdif->mclk_inner);
-+              if (ret) {
-+                      dev_err(dai->dev,
-+                              "failed to set parent to mclk_inner ret=%d\n", ret);
-+                      goto fail_ext;
-+              }
-+
-+              ret = clk_set_rate(spdif->audio_root, audio_root);
-+              if (ret) {
-+                      dev_err(dai->dev, "failed to set audio_root rate :%d\n", ret);
-+                      goto fail_ext;
-+              }
-+
-+              ret = clk_set_rate(spdif->mclk_inner, mclk);
-+              if (ret) {
-+                      dev_err(dai->dev, "failed to set mclk_inner rate :%d\n", ret);
-+                      goto fail_ext;
-+              }
-+
-+              mclk = clk_get_rate(spdif->mclk_inner);
-+      } else {
-+              ret = clk_set_parent(spdif->mclk, spdif->mclk_ext);
-+              if (ret) {
-+                      dev_err(dai->dev,
-+                              "failed to set parent to mclk_ext ret=%d\n", ret);
-+                      goto fail_ext;
-+              }
-+
-+              mclk = clk_get_rate(spdif->mclk_ext);
-+      }
-+
-+      /* (FCLK)4096000/128=32000 */
-+      tsamplerate = (mclk / 128 + rate / 2) / rate - 1;
-+      if (tsamplerate < 3)
-+              tsamplerate = 3;
-+
-+      /* transmission sample rate */
-+      regmap_update_bits(spdif->regmap, SPDIF_CTRL, 0xFF, tsamplerate);
-+
-+      return 0;
-+
-+fail_ext:
-+      return ret;
-+}
-+
-+static int sf_spdif_clks_get(struct platform_device *pdev,
-+                           struct sf_spdif_dev *spdif)
-+{
-+      static struct clk_bulk_data clks[] = {
-+              { .id = "apb" },                /* clock-names in dts file */
-+              { .id = "core" },
-+              { .id = "audroot" },
-+              { .id = "mclk_inner"},
-+              { .id = "mclk_ext"},
-+              { .id = "mclk"},
-+      };
-+      int ret = devm_clk_bulk_get(&pdev->dev, ARRAY_SIZE(clks), clks);
-+
-+      spdif->spdif_apb = clks[0].clk;
-+      spdif->spdif_core = clks[1].clk;
-+      spdif->audio_root = clks[2].clk;
-+      spdif->mclk_inner = clks[3].clk;
-+      spdif->mclk_ext = clks[4].clk;
-+      spdif->mclk = clks[5].clk;
-+
-+      return ret;
-+}
-+
-+static int sf_spdif_resets_get(struct platform_device *pdev,
-+                             struct sf_spdif_dev *spdif)
-+{
-+      struct reset_control_bulk_data resets[] = {
-+                      { .id = "apb" },
-+      };
-+      int ret = devm_reset_control_bulk_get_exclusive(&pdev->dev, ARRAY_SIZE(resets), resets);
-+
-+      if (ret)
-+              return ret;
-+
-+      spdif->rst_apb = resets[0].rstc;
-+
-+      return 0;
-+}
-+
-+static int starfive_spdif_crg_enable(struct sf_spdif_dev *spdif, bool enable)
-+{
-+      int ret;
-+
-+      dev_dbg(spdif->dev, "starfive_spdif clk&rst %sable.\n", enable ? "en":"dis");
-+      if (enable) {
-+              ret = clk_prepare_enable(spdif->spdif_apb);
-+              if (ret) {
-+                      dev_err(spdif->dev, "failed to prepare enable spdif_apb\n");
-+                      goto failed_apb_clk;
-+              }
-+
-+              ret = clk_prepare_enable(spdif->spdif_core);
-+              if (ret) {
-+                      dev_err(spdif->dev, "failed to prepare enable spdif_core\n");
-+                      goto failed_core_clk;
-+              }
-+
-+              ret = reset_control_deassert(spdif->rst_apb);
-+              if (ret) {
-+                      dev_err(spdif->dev, "failed to deassert apb\n");
-+                      goto failed_rst;
-+              }
-+      } else {
-+              clk_disable_unprepare(spdif->spdif_core);
-+              clk_disable_unprepare(spdif->spdif_apb);
-+      }
-+
-+      return 0;
-+
-+failed_rst:
-+      clk_disable_unprepare(spdif->spdif_core);
-+failed_core_clk:
-+      clk_disable_unprepare(spdif->spdif_apb);
-+failed_apb_clk:
-+      return ret;
-+}
-+
-+static int sf_spdif_dai_probe(struct snd_soc_dai *dai)
-+{
-+      struct sf_spdif_dev *spdif = snd_soc_dai_get_drvdata(dai);
-+
-+      pm_runtime_get_sync(spdif->dev);
-+
-+      /* reset */
-+      regmap_update_bits(spdif->regmap, SPDIF_CTRL,
-+                         SPDIF_ENABLE | SPDIF_SFR_ENABLE | SPDIF_FIFO_ENABLE, 0);
-+
-+      /* clear irq */
-+      regmap_update_bits(spdif->regmap, SPDIF_INT_REG,
-+                         SPDIF_INT_REG_BIT, 0);
-+
-+      /* power save mode */
-+      regmap_update_bits(spdif->regmap, SPDIF_CTRL,
-+                         SPDIF_CLK_ENABLE, SPDIF_CLK_ENABLE);
-+
-+      /* power save mode */
-+      regmap_update_bits(spdif->regmap, SPDIF_CTRL,
-+                         SPDIF_CLK_ENABLE, SPDIF_CLK_ENABLE);
-+
-+      regmap_update_bits(spdif->regmap, SPDIF_CTRL,
-+                         SPDIF_PARITCHECK|SPDIF_VALIDITYCHECK|SPDIF_DUPLICATE,
-+                         SPDIF_PARITCHECK|SPDIF_VALIDITYCHECK|SPDIF_DUPLICATE);
-+
-+      regmap_update_bits(spdif->regmap, SPDIF_CTRL,
-+                         SPDIF_SETPREAMBB, SPDIF_SETPREAMBB);
-+
-+      regmap_update_bits(spdif->regmap, SPDIF_INT_REG,
-+                         BIT8TO20MASK<<SPDIF_PREAMBLEDEL, 0x3<<SPDIF_PREAMBLEDEL);
-+
-+      regmap_update_bits(spdif->regmap, SPDIF_FIFO_CTRL,
-+                         ALLBITMASK, 0x20|(0x20<<SPDIF_AFULL_THRESHOLD));
-+
-+      regmap_update_bits(spdif->regmap, SPDIF_CTRL,
-+                         SPDIF_PARITYGEN, SPDIF_PARITYGEN);
-+
-+      regmap_update_bits(spdif->regmap, SPDIF_CTRL,
-+                         SPDIF_MASK_ENABLE, SPDIF_MASK_ENABLE);
-+
-+      /* APB access to FIFO enable, disable if use DMA/FIFO */
-+      regmap_update_bits(spdif->regmap, SPDIF_CTRL,
-+                         SPDIF_USE_FIFO_IF, 0);
-+
-+      /* two channel */
-+      regmap_update_bits(spdif->regmap, SPDIF_CTRL,
-+                         SPDIF_CHANNEL_MODE, 0);
-+
-+      pm_runtime_put_sync(spdif->dev);
-+      return 0;
-+}
-+
-+static const struct snd_soc_dai_ops sf_spdif_dai_ops = {
-+      .probe = sf_spdif_dai_probe,
-+      .trigger = sf_spdif_trigger,
-+      .hw_params = sf_spdif_hw_params,
-+};
-+
-+#ifdef CONFIG_PM_SLEEP
-+static int spdif_system_suspend(struct device *dev)
-+{
-+      struct sf_spdif_dev *spdif = dev_get_drvdata(dev);
-+
-+      /* save the register value */
-+      regmap_read(spdif->regmap, SPDIF_CTRL, &spdif->reg_spdif_ctrl);
-+      regmap_read(spdif->regmap, SPDIF_INT_REG, &spdif->reg_spdif_int);
-+      regmap_read(spdif->regmap, SPDIF_FIFO_CTRL, &spdif->reg_spdif_fifo_ctrl);
-+
-+      return pm_runtime_force_suspend(dev);
-+}
-+
-+static int spdif_system_resume(struct device *dev)
-+{
-+      struct sf_spdif_dev *spdif = dev_get_drvdata(dev);
-+      int ret = pm_runtime_force_resume(dev);
-+
-+      if (ret)
-+              return ret;
-+
-+      /* restore the register value */
-+      regmap_update_bits(spdif->regmap, SPDIF_CTRL,
-+                         ALLBITMASK, spdif->reg_spdif_ctrl);
-+      regmap_update_bits(spdif->regmap, SPDIF_INT_REG,
-+                         ALLBITMASK, spdif->reg_spdif_int);
-+      regmap_update_bits(spdif->regmap, SPDIF_FIFO_CTRL,
-+                         ALLBITMASK, spdif->reg_spdif_fifo_ctrl);
-+
-+      return 0;
-+}
-+#endif
-+
-+#ifdef CONFIG_PM
-+static int spdif_runtime_suspend(struct device *dev)
-+{
-+      struct sf_spdif_dev *spdif = dev_get_drvdata(dev);
-+
-+      return starfive_spdif_crg_enable(spdif, false);
-+}
-+
-+static int spdif_runtime_resume(struct device *dev)
-+{
-+      struct sf_spdif_dev *spdif = dev_get_drvdata(dev);
-+
-+      return starfive_spdif_crg_enable(spdif, true);
-+}
-+#endif
-+
-+static const struct dev_pm_ops spdif_pm_ops = {
-+      SET_RUNTIME_PM_OPS(spdif_runtime_suspend, spdif_runtime_resume, NULL)
-+      SET_SYSTEM_SLEEP_PM_OPS(spdif_system_suspend, spdif_system_resume)
-+};
-+
-+#define SF_PCM_RATE_44100_192000 (SNDRV_PCM_RATE_44100 | \
-+                                SNDRV_PCM_RATE_48000 | \
-+                                SNDRV_PCM_RATE_96000 | \
-+                                SNDRV_PCM_RATE_192000)
-+
-+#define SF_PCM_RATE_8000_22050 (SNDRV_PCM_RATE_8000 | \
-+                              SNDRV_PCM_RATE_11025 | \
-+                              SNDRV_PCM_RATE_16000 | \
-+                              SNDRV_PCM_RATE_22050)
-+
-+static struct snd_soc_dai_driver sf_spdif_dai = {
-+      .name = "spdif",
-+      .id = 0,
-+      .playback = {
-+              .stream_name = "Playback",
-+              .channels_min = 1,
-+              .channels_max = 2,
-+              .rates = SF_PCM_RATE_8000_22050,
-+              .formats = SNDRV_PCM_FMTBIT_S16_LE |
-+                         SNDRV_PCM_FMTBIT_S24_LE |
-+                         SNDRV_PCM_FMTBIT_S24_3LE |
-+                         SNDRV_PCM_FMTBIT_S32_LE,
-+      },
-+      .ops = &sf_spdif_dai_ops,
-+      .symmetric_rate = 1,
-+};
-+
-+static const struct snd_soc_component_driver sf_spdif_component = {
-+      .name = "starfive-spdif",
-+};
-+
-+static const struct regmap_config sf_spdif_regmap_config = {
-+      .reg_bits = 32,
-+      .reg_stride = 4,
-+      .val_bits = 32,
-+      .max_register = 0x200,
-+};
-+
-+static int sf_spdif_probe(struct platform_device *pdev)
-+{
-+      struct sf_spdif_dev *spdif;
-+      struct resource *res;
-+      void __iomem *base;
-+      int ret;
-+      int irq;
-+
-+      spdif = devm_kzalloc(&pdev->dev, sizeof(*spdif), GFP_KERNEL);
-+      if (!spdif)
-+              return -ENOMEM;
-+
-+      platform_set_drvdata(pdev, spdif);
-+
-+      res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-+      base = devm_ioremap_resource(&pdev->dev, res);
-+      if (IS_ERR(base))
-+              return PTR_ERR(base);
-+
-+      spdif->spdif_base = base;
-+      spdif->regmap = devm_regmap_init_mmio(&pdev->dev, spdif->spdif_base,
-+                                            &sf_spdif_regmap_config);
-+      if (IS_ERR(spdif->regmap))
-+              return PTR_ERR(spdif->regmap);
-+
-+      spdif->dev = &pdev->dev;
-+
-+      ret = sf_spdif_clks_get(pdev, spdif);
-+      if (ret) {
-+              dev_err(&pdev->dev, "failed to get audio clock\n");
-+              return ret;
-+      }
-+
-+      ret = sf_spdif_resets_get(pdev, spdif);
-+      if (ret) {
-+              dev_err(&pdev->dev, "failed to get audio reset controls\n");
-+              return ret;
-+      }
-+
-+      ret = starfive_spdif_crg_enable(spdif, true);
-+      if (ret) {
-+              dev_err(&pdev->dev, "failed to enable audio clock\n");
-+              return ret;
-+      }
-+
-+      spdif->fifo_th = 16;
-+
-+      irq = platform_get_irq(pdev, 0);
-+      if (irq >= 0) {
-+              ret = devm_request_irq(&pdev->dev, irq, spdif_irq_handler, 0,
-+                              pdev->name, spdif);
-+              if (ret < 0) {
-+                      dev_err(&pdev->dev, "failed to request irq\n");
-+                      return ret;
-+              }
-+      }
-+
-+      ret = devm_snd_soc_register_component(&pdev->dev, &sf_spdif_component,
-+                                       &sf_spdif_dai, 1);
-+      if (ret)
-+              goto err_clk_disable;
-+
-+      if (irq >= 0) {
-+              ret = sf_spdif_pcm_register(pdev);
-+              spdif->use_pio = true;
-+      } else {
-+              ret = devm_snd_dmaengine_pcm_register(&pdev->dev, NULL,
-+                                      0);
-+              spdif->use_pio = false;
-+      }
-+
-+      if (ret)
-+              goto err_clk_disable;
-+
-+      starfive_spdif_crg_enable(spdif, false);
-+      pm_runtime_enable(&pdev->dev);
-+      dev_dbg(&pdev->dev, "spdif register done.\n");
-+
-+      return 0;
-+
-+err_clk_disable:
-+      return ret;
-+}
-+
-+static const struct of_device_id sf_spdif_of_match[] = {
-+      { .compatible = "starfive,jh7110-spdif", },
-+      {},
-+};
-+MODULE_DEVICE_TABLE(of, sf_spdif_of_match);
-+
-+static struct platform_driver sf_spdif_driver = {
-+      .driver = {
-+              .name = "starfive-spdif",
-+              .of_match_table = sf_spdif_of_match,
-+              .pm = &spdif_pm_ops,
-+      },
-+      .probe = sf_spdif_probe,
-+};
-+module_platform_driver(sf_spdif_driver);
-+
-+MODULE_AUTHOR("curry.zhang <curry.zhang@starfive.com>");
-+MODULE_AUTHOR("Xingyu Wu <xingyu.wu@starfivetech.com>");
-+MODULE_DESCRIPTION("starfive SPDIF driver");
-+MODULE_LICENSE("GPL v2");
---- /dev/null
-+++ b/sound/soc/starfive/jh7110_spdif.h
-@@ -0,0 +1,196 @@
-+/* SPDX-License-Identifier: GPL-2.0 */
-+/*
-+ * SPDIF driver for the StarFive JH7110 SoC
-+ *
-+ * Copyright (C) 2022 StarFive Technology Co., Ltd.
-+ */
-+
-+#ifndef __SND_SOC_JH7110_SPDIF_H
-+#define __SND_SOC_JH7110_SPDIF_H
-+
-+#include <linux/clk.h>
-+#include <linux/device.h>
-+#include <linux/dmaengine.h>
-+#include <linux/types.h>
-+#include <sound/dmaengine_pcm.h>
-+#include <sound/pcm.h>
-+
-+#define SPDIF_CTRL                    0x0
-+#define SPDIF_INT_REG                 0x4
-+#define SPDIF_FIFO_CTRL                       0x8
-+#define SPDIF_STAT_REG                        0xC
-+
-+#define SPDIF_FIFO_ADDR                       0x100
-+#define DMAC_SPDIF_POLLING_LEN                256
-+
-+/* ctrl: sampled on the rising clock edge */
-+#define       SPDIF_TSAMPLERATE       0       /* [SRATEW-1:0] */
-+/* 0:SFR reg reset to defualt value; auto set back to '1' after reset */
-+#define SPDIF_SFR_ENABLE      (1<<8)
-+/* 0:reset of SPDIF block, SRF bits are unchanged; 1:enables SPDIF module */
-+#define SPDIF_ENABLE          (1<<9)
-+/* 0:FIFO pointers are reset to zero,threshold levels for FIFO are unchaned; auto set back to 1 */
-+#define SPDIF_FIFO_ENABLE     (1<<10)
-+/* 1:blocked and the modules are in power save mode; 0:block feeds the modules */
-+#define SPDIF_CLK_ENABLE      (1<<11)
-+#define SPDIF_TR_MODE         (1<<12) /* 0:rx; 1:tx */
-+/* 0:party bit rx in a sub-frame is repeated on the parity; 1:check on a parity error */
-+#define SPDIF_PARITCHECK      (1<<13)
-+/*
-+ * 0:parity bit from FIFO is transmitted in sub-frame;
-+ * 1:parity bit generated inside the core and added to a transmitted sub-frame
-+ */
-+#define SPDIF_PARITYGEN               (1<<14)
-+/* 0:validity bit in frame isn't checked and all frame are written; 1:validity bit rx is checked */
-+#define SPDIF_VALIDITYCHECK   (1<<15)
-+#define SPDIF_CHANNEL_MODE    (1<<16) /* 0:two-channel; 1:single-channel */
-+/* only tx -single-channel mode; 0:secondary channel; 1: left(primary) channel */
-+#define SPDIF_DUPLICATE               (1<<17)
-+/*
-+ * only tx;
-+ * 0:first preamble B after reset tx valid sub-frame;
-+ * 1:first preamble B is tx after preambleddel(INT_REG)
-+ */
-+#define SPDIF_SETPREAMBB      (1<<18)
-+/* 0:FIFO disabled ,APB accese FIFO; 1:FIFO enable, APB access to FIFO disable; */
-+#define SPDIF_USE_FIFO_IF     (1<<19)
-+#define SPDIF_PARITY_MASK     (1<<21)
-+#define SPDIF_UNDERR_MASK     (1<<22)
-+#define SPDIF_OVRERR_MASK     (1<<23)
-+#define SPDIF_EMPTY_MASK      (1<<24)
-+#define       SPDIF_AEMPTY_MASK       (1<<25)
-+#define SPDIF_FULL_MASK               (1<<26)
-+#define SPDIF_AFULL_MASK      (1<<27)
-+#define SPDIF_SYNCERR_MASK    (1<<28)
-+#define SPDIF_LOCK_MASK               (1<<29)
-+#define SPDIF_BEGIN_MASK      (1<<30)
-+#define SPDIF_INTEREQ_MAKS    (1<<31)
-+
-+#define SPDIF_MASK_ENABLE     (SPDIF_PARITY_MASK | SPDIF_UNDERR_MASK | \
-+                               SPDIF_OVRERR_MASK | SPDIF_EMPTY_MASK | \
-+                               SPDIF_AEMPTY_MASK | SPDIF_FULL_MASK | \
-+                               SPDIF_AFULL_MASK | SPDIF_SYNCERR_MASK | \
-+                               SPDIF_LOCK_MASK | SPDIF_BEGIN_MASK | \
-+                               SPDIF_INTEREQ_MAKS)
-+
-+#define SPDIF_MASK_FIFO       (SPDIF_EMPTY_MASK | SPDIF_AEMPTY_MASK | \
-+                       SPDIF_FULL_MASK | SPDIF_AFULL_MASK)
-+
-+/* INT_REG */
-+#define SPDIF_RSAMPLERATE     0       /* [SRATEW-1:0] */
-+#define SPDIF_PREAMBLEDEL     8       /* [PDELAYW+7:8] first B delay */
-+#define SPDIF_PARITYO         (1<<21) /* 0:clear parity error */
-+#define SPDIF_TDATA_UNDERR    (1<<22) /* tx data underrun error;0:clear */
-+#define SPDIF_RDATA_OVRERR    (1<<23) /* rx data overrun error; 0:clear */
-+#define SPDIF_FIFO_EMPTY      (1<<24) /* empty; 0:clear */
-+#define SPDIF_FIOF_AEMPTY     (1<<25) /* almost empty; 0:clear */
-+#define SPDIF_FIFO_FULL               (1<<26) /* FIFO full; 0:clear */
-+#define SPDIF_FIFO_AFULL      (1<<27) /* FIFO almost full; 0:clear */
-+#define SPDIF_SYNCERR         (1<<28) /* sync error; 0:clear */
-+#define SPDIF_LOCK            (1<<29) /* sync; 0:clear */
-+#define SPDIF_BLOCK_BEGIN     (1<<30) /* new start block rx data */
-+
-+#define SPDIF_INT_REG_BIT     (SPDIF_PARITYO | SPDIF_TDATA_UNDERR | \
-+                               SPDIF_RDATA_OVRERR | SPDIF_FIFO_EMPTY | \
-+                               SPDIF_FIOF_AEMPTY | SPDIF_FIFO_FULL | \
-+                               SPDIF_FIFO_AFULL | SPDIF_SYNCERR | \
-+                               SPDIF_LOCK | SPDIF_BLOCK_BEGIN)
-+
-+#define SPDIF_ERROR_INT_STATUS        (SPDIF_PARITYO | \
-+                               SPDIF_TDATA_UNDERR | SPDIF_RDATA_OVRERR)
-+#define SPDIF_FIFO_INT_STATUS (SPDIF_FIFO_EMPTY | SPDIF_FIOF_AEMPTY | \
-+                               SPDIF_FIFO_FULL | SPDIF_FIFO_AFULL)
-+
-+#define SPDIF_INT_PARITY_ERROR        (-1)
-+#define SPDIF_INT_TDATA_UNDERR        (-2)
-+#define SPDIF_INT_RDATA_OVRERR        (-3)
-+#define SPDIF_INT_FIFO_EMPTY  1
-+#define SPDIF_INT_FIFO_AEMPTY 2
-+#define SPDIF_INT_FIFO_FULL   3
-+#define SPDIF_INT_FIFO_AFULL  4
-+#define SPDIF_INT_SYNCERR     (-4)
-+#define SPDIF_INT_LOCK                5 /* reciever has become synchronized with input data stream */
-+#define SPDIF_INT_BLOCK_BEGIN 6 /* start a new block in recieve data, written into FIFO */
-+
-+/* FIFO_CTRL */
-+#define SPDIF_AEMPTY_THRESHOLD        0       /* [depth-1:0] */
-+#define SPDIF_AFULL_THRESHOLD 16      /* [depth+15:16] */
-+
-+/* STAT_REG */
-+#define SPDIF_FIFO_LEVEL      (1<<0)
-+#define SPDIF_PARITY_FLAG     (1<<21) /* 1:error; 0:repeated */
-+#define SPDIF_UNDERR_FLAG     (1<<22) /* 1:error */
-+#define SPDIF_OVRERR_FLAG     (1<<23) /* 1:error */
-+#define SPDIF_EMPTY_FLAG      (1<<24) /* 1:fifo empty */
-+#define SPDIF_AEMPTY_FLAG     (1<<25) /* 1:fifo almost empty */
-+#define SPDIF_FULL_FLAG               (1<<26) /* 1:fifo full */
-+#define SPDIF_AFULL_FLAG      (1<<27) /* 1:fifo almost full */
-+#define SPDIF_SYNCERR_FLAG    (1<<28) /* 1:rx sync error */
-+#define SPDIF_LOCK_FLAG               (1<<29) /* 1:RX sync */
-+#define SPDIF_BEGIN_FLAG      (1<<30) /* 1:start a new block */
-+/* 1:left channel received and tx into FIFO; 0:right channel received and tx into FIFO */
-+#define SPDIF_RIGHT_LEFT      (1<<31)
-+
-+#define BIT8TO20MASK  0x1FFF
-+#define ALLBITMASK            0xFFFFFFFF
-+
-+#define SPDIF_STAT            (SPDIF_PARITY_FLAG | SPDIF_UNDERR_FLAG | \
-+                               SPDIF_OVRERR_FLAG | SPDIF_EMPTY_FLAG | \
-+                               SPDIF_AEMPTY_FLAG | SPDIF_FULL_FLAG | \
-+                               SPDIF_AFULL_FLAG | SPDIF_SYNCERR_FLAG | \
-+                               SPDIF_LOCK_FLAG | SPDIF_BEGIN_FLAG | \
-+                               SPDIF_RIGHT_LEFT)
-+struct sf_spdif_dev {
-+      void __iomem *spdif_base;
-+      struct regmap *regmap;
-+      struct device *dev;
-+      u32 fifo_th;
-+      int active;
-+
-+      /* data related to DMA transfers b/w i2s and DMAC */
-+      struct snd_dmaengine_dai_dma_data play_dma_data;
-+      struct snd_dmaengine_dai_dma_data capture_dma_data;
-+
-+      bool use_pio;
-+      struct snd_pcm_substream __rcu *tx_substream;
-+      struct snd_pcm_substream __rcu *rx_substream;
-+
-+      unsigned int (*tx_fn)(struct sf_spdif_dev *dev,
-+                            struct snd_pcm_runtime *runtime, unsigned int tx_ptr,
-+                            bool *period_elapsed, snd_pcm_format_t format);
-+      unsigned int (*rx_fn)(struct sf_spdif_dev *dev,
-+                            struct snd_pcm_runtime *runtime, unsigned int rx_ptr,
-+                            bool *period_elapsed, snd_pcm_format_t format);
-+
-+      snd_pcm_format_t format;
-+      bool channels;
-+      unsigned int tx_ptr;
-+      unsigned int rx_ptr;
-+      struct clk *spdif_apb;
-+      struct clk *spdif_core;
-+      struct clk *audio_root;
-+      struct clk *mclk_inner;
-+      struct clk *mclk;
-+      struct clk *mclk_ext;
-+      struct reset_control *rst_apb;
-+      unsigned int reg_spdif_ctrl;
-+      unsigned int reg_spdif_int;
-+      unsigned int reg_spdif_fifo_ctrl;
-+
-+      struct snd_dmaengine_dai_dma_data dma_data;
-+};
-+
-+#if IS_ENABLED(CONFIG_SND_SOC_JH7110_SPDIF_PCM)
-+void sf_spdif_pcm_push_tx(struct sf_spdif_dev *dev);
-+void sf_spdif_pcm_pop_rx(struct sf_spdif_dev *dev);
-+int sf_spdif_pcm_register(struct platform_device *pdev);
-+#else
-+void sf_spdif_pcm_push_tx(struct sf_spdif_dev *dev) { }
-+void sf_spdif_pcm_pop_rx(struct sf_spdif_dev *dev) { }
-+int sf_spdif_pcm_register(struct platform_device *pdev)
-+{
-+      return -EINVAL;
-+}
-+#endif
-+
-+#endif        /* __SND_SOC_JH7110_SPDIF_H */
---- /dev/null
-+++ b/sound/soc/starfive/jh7110_spdif_pcm.c
-@@ -0,0 +1,339 @@
-+// SPDX-License-Identifier: GPL-2.0
-+/*
-+ * SPDIF PCM driver for the StarFive JH7110 SoC
-+ *
-+ * Copyright (C) 2022 StarFive Technology Co., Ltd.
-+ */
-+
-+#include <linux/io.h>
-+#include <linux/rcupdate.h>
-+#include <sound/pcm.h>
-+#include <sound/pcm_params.h>
-+
-+#include "jh7110_spdif.h"
-+
-+#define BUFFER_BYTES_MAX      (3 * 2 * 8 * PERIOD_BYTES_MIN)
-+#define PERIOD_BYTES_MIN      4096
-+#define PERIODS_MIN           2
-+
-+static unsigned int sf_spdif_pcm_tx(struct sf_spdif_dev *dev,
-+                                  struct snd_pcm_runtime *runtime, unsigned int tx_ptr,
-+                                  bool *period_elapsed, snd_pcm_format_t format)
-+{
-+      unsigned int period_pos = tx_ptr % runtime->period_size;
-+      u32 data[2];
-+      int i;
-+
-+      /* two- channel and signal-channel mode */
-+      if (dev->channels) {
-+              const u16 (*p16)[2] = (void *)runtime->dma_area;
-+              const u32 (*p32)[2] = (void *)runtime->dma_area;
-+
-+              for (i = 0; i < dev->fifo_th; i++) {
-+                      if (format == SNDRV_PCM_FORMAT_S16_LE) {
-+                              data[0] = p16[tx_ptr][0];
-+                              data[0] = data[0]<<8;
-+                              data[0] &= 0x00ffff00;
-+                              data[1] = p16[tx_ptr][1];
-+                              data[1] = data[1]<<8;
-+                              data[1] &= 0x00ffff00;
-+                      } else if (format == SNDRV_PCM_FORMAT_S24_LE) {
-+                              data[0] = p32[tx_ptr][0];
-+                              data[1] = p32[tx_ptr][1];
-+
-+                              /*
-+                               * To adapt S24_3LE and ALSA pass parameter of S24_LE.
-+                               * operation of S24_LE should be same to S24_3LE.
-+                               * So it would wrong when playback S24_LE file.
-+                               * when want to playback S24_LE file, should add in there:
-+                               * data[0] = data[0]>>8;
-+                               * data[1] = data[1]>>8;
-+                               */
-+
-+                              data[0] &= 0x00ffffff;
-+                              data[1] &= 0x00ffffff;
-+                      } else if (format == SNDRV_PCM_FORMAT_S24_3LE) {
-+                              data[0] = p32[tx_ptr][0];
-+                              data[1] = p32[tx_ptr][1];
-+                              data[0] &= 0x00ffffff;
-+                              data[1] &= 0x00ffffff;
-+                      } else if (format == SNDRV_PCM_FORMAT_S32_LE) {
-+                              data[0] = p32[tx_ptr][0];
-+                              data[0] = data[0]>>8;
-+                              data[1] = p32[tx_ptr][1];
-+                              data[1] = data[1]>>8;
-+                      }
-+
-+                      iowrite32(data[0], dev->spdif_base + SPDIF_FIFO_ADDR);
-+                      iowrite32(data[1], dev->spdif_base + SPDIF_FIFO_ADDR);
-+                      period_pos++;
-+                      if (++tx_ptr >= runtime->buffer_size)
-+                              tx_ptr = 0;
-+              }
-+      } else {
-+              const u16 (*p16) = (void *)runtime->dma_area;
-+              const u32 (*p32) = (void *)runtime->dma_area;
-+
-+              for (i = 0; i < dev->fifo_th; i++) {
-+                      if (format == SNDRV_PCM_FORMAT_S16_LE) {
-+                              data[0] = p16[tx_ptr];
-+                              data[0] = data[0]<<8;
-+                              data[0] &= 0x00ffff00;
-+                      } else if (format == SNDRV_PCM_FORMAT_S24_LE ||
-+                              format == SNDRV_PCM_FORMAT_S24_3LE) {
-+                              data[0] = p32[tx_ptr];
-+                              data[0] &= 0x00ffffff;
-+                      } else if (format == SNDRV_PCM_FORMAT_S32_LE) {
-+                              data[0] = p32[tx_ptr];
-+                              data[0] = data[0]>>8;
-+                      }
-+
-+                      iowrite32(data[0], dev->spdif_base + SPDIF_FIFO_ADDR);
-+                      period_pos++;
-+                      if (++tx_ptr >= runtime->buffer_size)
-+                              tx_ptr = 0;
-+              }
-+      }
-+
-+      *period_elapsed = period_pos >= runtime->period_size;
-+      return tx_ptr;
-+}
-+
-+static unsigned int sf_spdif_pcm_rx(struct sf_spdif_dev *dev,
-+                                  struct snd_pcm_runtime *runtime, unsigned int rx_ptr,
-+                                  bool *period_elapsed, snd_pcm_format_t format)
-+{
-+      u16 (*p16)[2] = (void *)runtime->dma_area;
-+      u32 (*p32)[2] = (void *)runtime->dma_area;
-+      unsigned int period_pos = rx_ptr % runtime->period_size;
-+      u32 data[2];
-+      int i;
-+
-+      for (i = 0; i < dev->fifo_th; i++) {
-+              data[0] = ioread32(dev->spdif_base + SPDIF_FIFO_ADDR);
-+              data[1] = ioread32(dev->spdif_base + SPDIF_FIFO_ADDR);
-+              if (format == SNDRV_PCM_FORMAT_S16_LE) {
-+                      p16[rx_ptr][0] = data[0]>>8;
-+                      p16[rx_ptr][1] = data[1]>>8;
-+              } else if (format == SNDRV_PCM_FORMAT_S24_LE) {
-+                      p32[rx_ptr][0] = data[0];
-+                      p32[rx_ptr][1] = data[1];
-+              } else if (format == SNDRV_PCM_FORMAT_S32_LE) {
-+                      p32[rx_ptr][0] = data[0]<<8;
-+                      p32[rx_ptr][1] = data[1]<<8;
-+              }
-+
-+              period_pos++;
-+              if (++rx_ptr >= runtime->buffer_size)
-+                      rx_ptr = 0;
-+      }
-+
-+      *period_elapsed = period_pos >= runtime->period_size;
-+      return rx_ptr;
-+}
-+
-+static const struct snd_pcm_hardware sf_pcm_hardware = {
-+      .info = SNDRV_PCM_INFO_INTERLEAVED |
-+              SNDRV_PCM_INFO_MMAP |
-+              SNDRV_PCM_INFO_MMAP_VALID |
-+              SNDRV_PCM_INFO_BLOCK_TRANSFER |
-+              SNDRV_PCM_INFO_PAUSE |
-+              SNDRV_PCM_INFO_RESUME,
-+      .rates = SNDRV_PCM_RATE_8000 |
-+              SNDRV_PCM_RATE_11025 |
-+              SNDRV_PCM_RATE_16000 |
-+              SNDRV_PCM_RATE_22050 |
-+              SNDRV_PCM_RATE_32000 |
-+              SNDRV_PCM_RATE_44100 |
-+              SNDRV_PCM_RATE_48000,
-+      .rate_min = 8000,
-+      .rate_max = 48000,
-+      .formats = SNDRV_PCM_FMTBIT_S16_LE |
-+              SNDRV_PCM_FMTBIT_S24_LE |
-+              SNDRV_PCM_FMTBIT_S24_3LE |
-+              SNDRV_PCM_FMTBIT_S32_LE,
-+      .channels_min = 1,
-+      .channels_max = 2,
-+      .buffer_bytes_max = BUFFER_BYTES_MAX,
-+      .period_bytes_min = PERIOD_BYTES_MIN,
-+      .period_bytes_max = BUFFER_BYTES_MAX / PERIODS_MIN,
-+      .periods_min = PERIODS_MIN,
-+      .periods_max = BUFFER_BYTES_MAX / PERIOD_BYTES_MIN,
-+      .fifo_size = 16,
-+};
-+
-+static void sf_spdif_pcm_transfer(struct sf_spdif_dev *dev, bool push)
-+{
-+      struct snd_pcm_substream *substream;
-+      bool active, period_elapsed;
-+
-+      rcu_read_lock();
-+      if (push)
-+              substream = rcu_dereference(dev->tx_substream);
-+      else
-+              substream = rcu_dereference(dev->rx_substream);
-+
-+      active = substream && snd_pcm_running(substream);
-+      if (active) {
-+              unsigned int ptr;
-+              unsigned int new_ptr;
-+
-+              if (push) {
-+                      ptr = READ_ONCE(dev->tx_ptr);
-+                      new_ptr = dev->tx_fn(dev, substream->runtime, ptr,
-+                                      &period_elapsed, dev->format);
-+                      cmpxchg(&dev->tx_ptr, ptr, new_ptr);
-+              } else {
-+                      ptr = READ_ONCE(dev->rx_ptr);
-+                      new_ptr = dev->rx_fn(dev, substream->runtime, ptr,
-+                                      &period_elapsed, dev->format);
-+                      cmpxchg(&dev->rx_ptr, ptr, new_ptr);
-+              }
-+
-+              if (period_elapsed)
-+                      snd_pcm_period_elapsed(substream);
-+      }
-+      rcu_read_unlock();
-+}
-+
-+void sf_spdif_pcm_push_tx(struct sf_spdif_dev *dev)
-+{
-+      sf_spdif_pcm_transfer(dev, true);
-+}
-+
-+void sf_spdif_pcm_pop_rx(struct sf_spdif_dev *dev)
-+{
-+      sf_spdif_pcm_transfer(dev, false);
-+}
-+
-+static int sf_pcm_open(struct snd_soc_component *component,
-+                     struct snd_pcm_substream *substream)
-+{
-+      struct snd_pcm_runtime *runtime = substream->runtime;
-+      struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream);
-+      struct sf_spdif_dev *dev = snd_soc_dai_get_drvdata(asoc_rtd_to_cpu(rtd, 0));
-+
-+      snd_soc_set_runtime_hwparams(substream, &sf_pcm_hardware);
-+      snd_pcm_hw_constraint_integer(runtime, SNDRV_PCM_HW_PARAM_PERIODS);
-+      runtime->private_data = dev;
-+
-+      return 0;
-+}
-+
-+static int sf_pcm_close(struct snd_soc_component *component,
-+                      struct snd_pcm_substream *substream)
-+{
-+      synchronize_rcu();
-+      return 0;
-+}
-+
-+static int sf_pcm_hw_params(struct snd_soc_component *component,
-+                          struct snd_pcm_substream *substream,
-+                          struct snd_pcm_hw_params *hw_params)
-+{
-+      struct snd_pcm_runtime *runtime = substream->runtime;
-+      struct sf_spdif_dev *dev = runtime->private_data;
-+
-+      switch (params_channels(hw_params)) {
-+      case 1:
-+      case 2:
-+              break;
-+      default:
-+              dev_err(dev->dev, "invalid channels number\n");
-+              return -EINVAL;
-+      }
-+
-+      dev->format = params_format(hw_params);
-+      switch (dev->format) {
-+      case SNDRV_PCM_FORMAT_S16_LE:
-+      case SNDRV_PCM_FORMAT_S24_LE:
-+      case SNDRV_PCM_FORMAT_S24_3LE:
-+      case SNDRV_PCM_FORMAT_S32_LE:
-+              break;
-+      default:
-+              dev_err(dev->dev, "invalid format\n");
-+              return -EINVAL;
-+      }
-+
-+      dev->tx_fn = sf_spdif_pcm_tx;
-+      dev->rx_fn = sf_spdif_pcm_rx;
-+
-+      return 0;
-+}
-+
-+static int sf_pcm_trigger(struct snd_soc_component *component,
-+                        struct snd_pcm_substream *substream, int cmd)
-+{
-+      struct snd_pcm_runtime *runtime = substream->runtime;
-+      struct sf_spdif_dev *dev = runtime->private_data;
-+      int ret = 0;
-+
-+      switch (cmd) {
-+      case SNDRV_PCM_TRIGGER_START:
-+      case SNDRV_PCM_TRIGGER_RESUME:
-+      case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
-+              if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
-+                      WRITE_ONCE(dev->tx_ptr, 0);
-+                      rcu_assign_pointer(dev->tx_substream, substream);
-+              } else {
-+                      WRITE_ONCE(dev->rx_ptr, 0);
-+                      rcu_assign_pointer(dev->rx_substream, substream);
-+              }
-+              break;
-+      case SNDRV_PCM_TRIGGER_STOP:
-+      case SNDRV_PCM_TRIGGER_SUSPEND:
-+      case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
-+              if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
-+                      rcu_assign_pointer(dev->tx_substream, NULL);
-+              else
-+                      rcu_assign_pointer(dev->rx_substream, NULL);
-+              break;
-+      default:
-+              ret = -EINVAL;
-+              break;
-+      }
-+
-+      return ret;
-+}
-+
-+static snd_pcm_uframes_t sf_pcm_pointer(struct snd_soc_component *component,
-+                                      struct snd_pcm_substream *substream)
-+{
-+      struct snd_pcm_runtime *runtime = substream->runtime;
-+      struct sf_spdif_dev *dev = runtime->private_data;
-+      snd_pcm_uframes_t pos;
-+
-+      if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
-+              pos = READ_ONCE(dev->tx_ptr);
-+      else
-+              pos = READ_ONCE(dev->rx_ptr);
-+
-+      return pos < runtime->buffer_size ? pos : 0;
-+}
-+
-+static int sf_pcm_new(struct snd_soc_component *component,
-+                    struct snd_soc_pcm_runtime *rtd)
-+{
-+      size_t size = sf_pcm_hardware.buffer_bytes_max;
-+
-+      snd_pcm_set_managed_buffer_all(rtd->pcm,
-+                      SNDRV_DMA_TYPE_CONTINUOUS,
-+                      NULL, size, size);
-+
-+      return 0;
-+}
-+
-+static const struct snd_soc_component_driver sf_pcm_component = {
-+      .open           = sf_pcm_open,
-+      .close          = sf_pcm_close,
-+      .hw_params      = sf_pcm_hw_params,
-+      .trigger        = sf_pcm_trigger,
-+      .pointer        = sf_pcm_pointer,
-+      .pcm_construct  = sf_pcm_new,
-+};
-+
-+int sf_spdif_pcm_register(struct platform_device *pdev)
-+{
-+      return devm_snd_soc_register_component(&pdev->dev, &sf_pcm_component,
-+                                             NULL, 0);
-+}
diff --git a/target/linux/starfive/patches-6.6/0081-ASoC-starfive-Add-JH7110-PDM-driver.patch b/target/linux/starfive/patches-6.6/0081-ASoC-starfive-Add-JH7110-PDM-driver.patch
deleted file mode 100644 (file)
index 006760d..0000000
+++ /dev/null
@@ -1,537 +0,0 @@
-From 9c4858f9fe4d8f8fe5cf347b3ca727016b7ba492 Mon Sep 17 00:00:00 2001
-From: Walker Chen <walker.chen@starfivetech.com>
-Date: Tue, 20 Jun 2023 15:57:53 +0800
-Subject: [PATCH 081/116] ASoC: starfive: Add JH7110 PDM driver
-
-Add pdm driver support for the StarFive JH7110 SoC.
-
-Signed-off-by: Walker Chen <walker.chen@starfivetech.com>
----
- sound/soc/starfive/Kconfig      |   8 +
- sound/soc/starfive/Makefile     |   2 +
- sound/soc/starfive/jh7110_pdm.c | 493 ++++++++++++++++++++++++++++++++
- 3 files changed, 503 insertions(+)
- create mode 100644 sound/soc/starfive/jh7110_pdm.c
-
---- a/sound/soc/starfive/Kconfig
-+++ b/sound/soc/starfive/Kconfig
-@@ -7,6 +7,14 @@ config SND_SOC_STARFIVE
-         the Starfive SoCs' Audio interfaces. You will also need to
-         select the audio interfaces to support below.
-+config SND_SOC_JH7110_PDM
-+      tristate "JH7110 PDM device driver"
-+      depends on HAVE_CLK && SND_SOC_STARFIVE
-+      select SND_SOC_JH7110_I2S
-+      select REGMAP_MMIO
-+      help
-+        Say Y or M if you want to add support for StarFive pdm driver.
-+
- config SND_SOC_JH7110_PWMDAC
-       tristate "JH7110 PWM-DAC device driver"
-       depends on HAVE_CLK && SND_SOC_STARFIVE
---- a/sound/soc/starfive/Makefile
-+++ b/sound/soc/starfive/Makefile
-@@ -1,4 +1,6 @@
- # StarFive Platform Support
-+obj-$(CONFIG_SND_SOC_JH7110_PDM) += jh7110_pdm.o
-+
- obj-$(CONFIG_SND_SOC_JH7110_PWMDAC) += jh7110_pwmdac.o
- obj-$(CONFIG_SND_SOC_JH7110_SPDIF) += spdif.o
---- /dev/null
-+++ b/sound/soc/starfive/jh7110_pdm.c
-@@ -0,0 +1,493 @@
-+// SPDX-License-Identifier: GPL-2.0
-+/*
-+ * PDM driver for the StarFive JH7110 SoC
-+ *
-+ * Copyright (C) 2022 StarFive Technology Co., Ltd.
-+ */
-+#include <linux/clk.h>
-+#include <linux/device.h>
-+#include <linux/dmaengine.h>
-+#include <linux/reset.h>
-+#include <linux/module.h>
-+#include <linux/of_irq.h>
-+#include <linux/of_platform.h>
-+#include <linux/regmap.h>
-+#include <linux/pm_runtime.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>
-+#include <sound/tlv.h>
-+
-+#define PDM_DMIC_CTRL0                        0x00
-+#define PDM_DC_SCALE0                 0x04
-+#define PDM_DMIC_CTRL1                        0x10
-+#define PDM_DC_SCALE1                 0x14
-+
-+/* PDM CTRL OFFSET */
-+#define PDM_DMIC_MSB_SHIFT            1
-+#define PDM_DMIC_MSB_MASK             (0x7 << PDM_DMIC_MSB_SHIFT)
-+#define PDM_DMIC_VOL_SHIFT            16
-+#define PDM_DMIC_VOL_MASK             (0x3f << PDM_DMIC_VOL_SHIFT)
-+#define PDM_VOL_DB_MUTE                       (0x3f << PDM_DMIC_VOL_SHIFT)
-+#define PDM_VOL_DB_MAX                        0
-+
-+#define PDM_DMIC_RVOL_MASK            BIT(22)
-+#define PDM_DMIC_LVOL_MASK            BIT(23)
-+#define PDM_DMIC_I2S_SLAVE            BIT(24)
-+#define PDM_DMIC_HPF_EN                       BIT(28)
-+#define PDM_DMIC_FASTMODE_MASK                BIT(29)
-+#define PDM_DMIC_DC_BYPASS_MASK               BIT(30)
-+#define PDM_SW_RST_MASK                       BIT(31)
-+#define PDM_SW_RST_RELEASE            BIT(31)
-+
-+/* PDM SCALE OFFSET */
-+#define DMIC_DCOFF3_SHIFT             24
-+#define DMIC_DCOFF2_SHIFT             16
-+#define DMIC_DCOFF1_SHIFT             8
-+
-+#define DMIC_DCOFF3_MASK              (0xf << DMIC_DCOFF3_SHIFT)
-+#define DMIC_DCOFF3_VAL                       (0xc << DMIC_DCOFF3_SHIFT)
-+#define DMIC_DCOFF1_MASK              (0xff << DMIC_DCOFF1_SHIFT)
-+#define DMIC_DCOFF1_VAL                       (0x5 << DMIC_DCOFF1_SHIFT)
-+#define DMIC_SCALE_MASK                       0x3f
-+#define DMIC_SCALE_DEF_VAL            0x8
-+
-+enum PDM_MSB_SHIFT {
-+      PDM_MSB_SHIFT_NONE = 0,
-+      PDM_MSB_SHIFT_1,
-+      PDM_MSB_SHIFT_2,
-+      PDM_MSB_SHIFT_3,
-+      PDM_MSB_SHIFT_4,
-+      PDM_MSB_SHIFT_5,
-+      PDM_MSB_SHIFT_6,
-+      PDM_MSB_SHIFT_7,
-+};
-+
-+struct sf_pdm {
-+      struct regmap *pdm_map;
-+      struct device *dev;
-+      struct clk *clk_pdm_apb;
-+      struct clk *clk_pdm_mclk;
-+      struct clk *clk_mclk;
-+      struct clk *clk_mclk_ext;
-+      struct reset_control *rst_pdm_dmic;
-+      struct reset_control *rst_pdm_apb;
-+      unsigned char flag_first;
-+      unsigned int saved_ctrl0;
-+      unsigned int saved_scale0;
-+};
-+
-+static const DECLARE_TLV_DB_SCALE(volume_tlv, -9450, 150, 0);
-+
-+static const struct snd_kcontrol_new sf_pdm_snd_controls[] = {
-+      SOC_SINGLE("DC compensation Control", PDM_DMIC_CTRL0, 30, 1, 0),
-+      SOC_SINGLE("High Pass Filter Control", PDM_DMIC_CTRL0, 28, 1, 0),
-+      SOC_SINGLE("Left Channel Volume Control", PDM_DMIC_CTRL0, 23, 1, 0),
-+      SOC_SINGLE("Right Channel Volume Control", PDM_DMIC_CTRL0, 22, 1, 0),
-+      SOC_SINGLE_TLV("Volume", PDM_DMIC_CTRL0, 16, 0x3F, 1, volume_tlv),
-+      SOC_SINGLE("Data MSB Shift", PDM_DMIC_CTRL0, 1, 7, 0),
-+      SOC_SINGLE("SCALE", PDM_DC_SCALE0, 0, 0x3F, 0),
-+      SOC_SINGLE("DC offset", PDM_DC_SCALE0, 8, 0xFFFFF, 0),
-+};
-+
-+static void sf_pdm_enable(struct regmap *map)
-+{
-+      /* Left and Right Channel Volume Control Enable */
-+      regmap_update_bits(map, PDM_DMIC_CTRL0, PDM_DMIC_RVOL_MASK, 0);
-+      regmap_update_bits(map, PDM_DMIC_CTRL0, PDM_DMIC_LVOL_MASK, 0);
-+}
-+
-+static void sf_pdm_disable(struct regmap *map)
-+{
-+      /* Left and Right Channel Volume Control Disable */
-+      regmap_update_bits(map, PDM_DMIC_CTRL0,
-+                         PDM_DMIC_RVOL_MASK, PDM_DMIC_RVOL_MASK);
-+      regmap_update_bits(map, PDM_DMIC_CTRL0,
-+                         PDM_DMIC_LVOL_MASK, PDM_DMIC_LVOL_MASK);
-+}
-+
-+static int sf_pdm_trigger(struct snd_pcm_substream *substream, int cmd,
-+                         struct snd_soc_dai *dai)
-+{
-+      struct sf_pdm *priv = snd_soc_dai_get_drvdata(dai);
-+
-+      switch (cmd) {
-+      case SNDRV_PCM_TRIGGER_START:
-+      case SNDRV_PCM_TRIGGER_RESUME:
-+      case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
-+              if (priv->flag_first) {
-+                      priv->flag_first = 0;
-+                      mdelay(200);
-+              }
-+
-+              sf_pdm_enable(priv->pdm_map);
-+              return 0;
-+
-+      case SNDRV_PCM_TRIGGER_STOP:
-+      case SNDRV_PCM_TRIGGER_SUSPEND:
-+      case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
-+              sf_pdm_disable(priv->pdm_map);
-+              return 0;
-+
-+      default:
-+              return -EINVAL;
-+      }
-+}
-+
-+static int sf_pdm_hw_params(struct snd_pcm_substream *substream,
-+                           struct snd_pcm_hw_params *params,
-+                           struct snd_soc_dai *dai)
-+{
-+      struct sf_pdm *priv = snd_soc_dai_get_drvdata(dai);
-+      unsigned int sample_rate;
-+      unsigned int data_width;
-+      int ret;
-+      const int pdm_mul = 128;
-+
-+      sample_rate = params_rate(params);
-+      switch (sample_rate) {
-+      case 8000:
-+      case 11025:
-+      case 16000:
-+              break;
-+      default:
-+              dev_err(priv->dev, "can't support sample rate:%d\n", sample_rate);
-+              return -EINVAL;
-+      }
-+
-+      data_width = params_width(params);
-+      switch (data_width) {
-+      case 16:
-+      case 32:
-+              break;
-+      default:
-+              dev_err(priv->dev, "can't support bit width %d\n", data_width);
-+              return -EINVAL;
-+      }
-+
-+      /* set pdm_mclk,  PDM MCLK = 128 * LRCLK */
-+      ret = clk_set_rate(priv->clk_pdm_mclk, pdm_mul * sample_rate);
-+      if (ret) {
-+              dev_err(priv->dev, "Can't set pdm_mclk: %d\n", ret);
-+              return ret;
-+      }
-+
-+      return 0;
-+}
-+
-+static const struct snd_soc_dai_ops sf_pdm_dai_ops = {
-+      .trigger        = sf_pdm_trigger,
-+      .hw_params      = sf_pdm_hw_params,
-+};
-+
-+static void sf_pdm_module_init(struct sf_pdm *priv)
-+{
-+      /* Reset */
-+      regmap_update_bits(priv->pdm_map, PDM_DMIC_CTRL0,
-+                         PDM_SW_RST_MASK, 0x00);
-+      regmap_update_bits(priv->pdm_map, PDM_DMIC_CTRL0,
-+                         PDM_SW_RST_MASK, PDM_SW_RST_RELEASE);
-+
-+      /* Make sure the device is initially disabled */
-+      sf_pdm_disable(priv->pdm_map);
-+
-+      /* MUTE */
-+      regmap_update_bits(priv->pdm_map, PDM_DMIC_CTRL0,
-+                         PDM_DMIC_VOL_MASK, PDM_VOL_DB_MUTE);
-+
-+      /* UNMUTE */
-+      regmap_update_bits(priv->pdm_map, PDM_DMIC_CTRL0,
-+                         PDM_DMIC_VOL_MASK, PDM_VOL_DB_MAX);
-+
-+      /* enable high pass filter */
-+      regmap_update_bits(priv->pdm_map, PDM_DMIC_CTRL0,
-+                         PDM_DMIC_HPF_EN, PDM_DMIC_HPF_EN);
-+
-+      /* PDM work as slave mode */
-+      regmap_update_bits(priv->pdm_map, PDM_DMIC_CTRL0,
-+                         PDM_DMIC_I2S_SLAVE, PDM_DMIC_I2S_SLAVE);
-+
-+      /* disable fast mode */
-+      regmap_update_bits(priv->pdm_map, PDM_DMIC_CTRL0,
-+                         PDM_DMIC_FASTMODE_MASK, 0);
-+
-+      /* dmic msb shift 0 */
-+      regmap_update_bits(priv->pdm_map, PDM_DMIC_CTRL0,
-+                         PDM_DMIC_MSB_MASK, 0);
-+
-+      /* scale: 0x8 */
-+      regmap_update_bits(priv->pdm_map, PDM_DC_SCALE0,
-+                         DMIC_SCALE_MASK, DMIC_SCALE_DEF_VAL);
-+
-+      regmap_update_bits(priv->pdm_map, PDM_DC_SCALE0,
-+                         DMIC_DCOFF1_MASK, DMIC_DCOFF1_VAL);
-+
-+      regmap_update_bits(priv->pdm_map, PDM_DC_SCALE0,
-+                         DMIC_DCOFF3_MASK, DMIC_DCOFF3_VAL);
-+
-+      /* scale: 0x3f */
-+      regmap_update_bits(priv->pdm_map, PDM_DC_SCALE0,
-+                         DMIC_SCALE_MASK, DMIC_SCALE_MASK);
-+
-+      /* dmic msb shift 2 */
-+      regmap_update_bits(priv->pdm_map, PDM_DMIC_CTRL0,
-+                         PDM_DMIC_MSB_MASK, PDM_MSB_SHIFT_4);
-+}
-+
-+#define SF_PDM_RATES  (SNDRV_PCM_RATE_8000 | \
-+                      SNDRV_PCM_RATE_11025 | \
-+                      SNDRV_PCM_RATE_16000)
-+
-+#define SF_PDM_FORMATS        (SNDRV_PCM_FMTBIT_S16_LE | \
-+                      SNDRV_PCM_FMTBIT_S32_LE)
-+
-+static struct snd_soc_dai_driver sf_pdm_dai_drv = {
-+      .name = "PDM",
-+      .id = 0,
-+      .capture = {
-+              .stream_name    = "Capture",
-+              .channels_min   = 2,
-+              .channels_max   = 2,
-+              .rates          = SF_PDM_RATES,
-+              .formats        = SF_PDM_FORMATS,
-+      },
-+      .ops = &sf_pdm_dai_ops,
-+      .symmetric_rate = 1,
-+};
-+
-+static int sf_pdm_component_probe(struct snd_soc_component *component)
-+{
-+      struct sf_pdm *priv = snd_soc_component_get_drvdata(component);
-+
-+      snd_soc_component_init_regmap(component, priv->pdm_map);
-+      snd_soc_add_component_controls(component, sf_pdm_snd_controls,
-+                                     ARRAY_SIZE(sf_pdm_snd_controls));
-+
-+      return 0;
-+}
-+
-+static int sf_pdm_clock_enable(struct sf_pdm *priv)
-+{
-+      int ret;
-+
-+      ret = clk_prepare_enable(priv->clk_pdm_mclk);
-+      if (ret) {
-+              dev_err(priv->dev, "failed to prepare enable clk_pdm_mclk\n");
-+              return ret;
-+      }
-+
-+      ret = clk_prepare_enable(priv->clk_pdm_apb);
-+      if (ret) {
-+              dev_err(priv->dev, "failed to prepare enable clk_pdm_apb\n");
-+              goto disable_pdm_mclk;
-+      }
-+
-+      ret = reset_control_deassert(priv->rst_pdm_dmic);
-+      if (ret) {
-+              dev_err(priv->dev, "failed to deassert pdm_dmic\n");
-+              goto disable_pdm_apb;
-+      }
-+
-+      ret = reset_control_deassert(priv->rst_pdm_apb);
-+      if (ret) {
-+              dev_err(priv->dev, "failed to deassert pdm_apb\n");
-+              goto disable_pdm_apb;
-+      }
-+
-+      ret = clk_set_parent(priv->clk_mclk, priv->clk_mclk_ext);
-+      if (ret) {
-+              dev_err(priv->dev, "failed to set parent clk_mclk ret=%d\n", ret);
-+              goto disable_pdm_apb;
-+      }
-+
-+      return 0;
-+
-+disable_pdm_apb:
-+      clk_disable_unprepare(priv->clk_pdm_apb);
-+disable_pdm_mclk:
-+      clk_disable_unprepare(priv->clk_pdm_mclk);
-+
-+      return ret;
-+}
-+
-+#ifdef CONFIG_PM
-+static int sf_pdm_runtime_suspend(struct device *dev)
-+{
-+      struct sf_pdm *priv = dev_get_drvdata(dev);
-+
-+      clk_disable_unprepare(priv->clk_pdm_apb);
-+      clk_disable_unprepare(priv->clk_pdm_mclk);
-+
-+      return 0;
-+}
-+
-+static int sf_pdm_runtime_resume(struct device *dev)
-+{
-+      struct sf_pdm *priv = dev_get_drvdata(dev);
-+      int ret;
-+
-+      ret = sf_pdm_clock_enable(priv);
-+      if (!ret)
-+              sf_pdm_module_init(priv);
-+
-+      return ret;
-+}
-+#endif
-+
-+#ifdef CONFIG_PM_SLEEP
-+static int sf_pdm_suspend(struct snd_soc_component *component)
-+{
-+      return pm_runtime_force_suspend(component->dev);
-+}
-+
-+static int sf_pdm_resume(struct snd_soc_component *component)
-+{
-+      return pm_runtime_force_resume(component->dev);
-+}
-+
-+#else
-+#define sf_pdm_suspend        NULL
-+#define sf_pdm_resume NULL
-+#endif
-+
-+static const struct snd_soc_component_driver sf_pdm_component_drv = {
-+      .name = "jh7110-pdm",
-+      .probe = sf_pdm_component_probe,
-+      .suspend = sf_pdm_suspend,
-+      .resume = sf_pdm_resume,
-+};
-+
-+static const struct regmap_config sf_pdm_regmap_cfg = {
-+      .reg_bits       = 32,
-+      .val_bits       = 32,
-+      .reg_stride     = 4,
-+      .max_register   = 0x20,
-+};
-+
-+static int sf_pdm_clock_get(struct platform_device *pdev, struct sf_pdm *priv)
-+{
-+      int ret;
-+
-+      static struct clk_bulk_data clks[] = {
-+              { .id = "pdm_mclk" },
-+              { .id = "pdm_apb" },
-+              { .id = "clk_mclk" },
-+              { .id = "mclk_ext" },
-+      };
-+
-+      ret = devm_clk_bulk_get(&pdev->dev, ARRAY_SIZE(clks), clks);
-+      if (ret) {
-+              dev_err(&pdev->dev, "failed to get pdm clocks\n");
-+              goto exit;
-+      }
-+
-+      priv->clk_pdm_mclk = clks[0].clk;
-+      priv->clk_pdm_apb = clks[1].clk;
-+      priv->clk_mclk = clks[2].clk;
-+      priv->clk_mclk_ext = clks[3].clk;
-+
-+      priv->rst_pdm_dmic = devm_reset_control_get_exclusive(&pdev->dev, "pdm_dmic");
-+      if (IS_ERR(priv->rst_pdm_dmic)) {
-+              dev_err(&pdev->dev, "failed to get pdm_dmic reset control\n");
-+              ret = PTR_ERR(priv->rst_pdm_dmic);
-+              goto exit;
-+      }
-+
-+      priv->rst_pdm_apb = devm_reset_control_get_exclusive(&pdev->dev, "pdm_apb");
-+      if (IS_ERR(priv->rst_pdm_apb)) {
-+              dev_err(&pdev->dev, "failed to get pdm_apb reset control\n");
-+              ret = PTR_ERR(priv->rst_pdm_apb);
-+              goto exit;
-+      }
-+
-+      /*
-+       * pdm clock must always be enabled as hardware issue that
-+       * no data in the first 4 seconds of the first recording
-+       */
-+      ret = sf_pdm_clock_enable(priv);
-+
-+exit:
-+      return ret;
-+}
-+
-+static int sf_pdm_probe(struct platform_device *pdev)
-+{
-+      struct sf_pdm *priv;
-+      struct resource *res;
-+      void __iomem *regs;
-+      int ret;
-+
-+      priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL);
-+      if (!priv)
-+              return -ENOMEM;
-+      platform_set_drvdata(pdev, priv);
-+
-+      res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "pdm");
-+      regs = devm_ioremap_resource(&pdev->dev, res);
-+      if (IS_ERR(regs))
-+              return PTR_ERR(regs);
-+
-+      priv->pdm_map = devm_regmap_init_mmio(&pdev->dev, regs, &sf_pdm_regmap_cfg);
-+      if (IS_ERR(priv->pdm_map)) {
-+              dev_err(&pdev->dev, "failed to init regmap: %ld\n",
-+                      PTR_ERR(priv->pdm_map));
-+              return PTR_ERR(priv->pdm_map);
-+      }
-+
-+      priv->dev = &pdev->dev;
-+      priv->flag_first = 1;
-+
-+      ret = sf_pdm_clock_get(pdev, priv);
-+      if (ret) {
-+              dev_err(&pdev->dev, "failed to enable audio-pdm clock\n");
-+              return ret;
-+      }
-+
-+      dev_set_drvdata(&pdev->dev, priv);
-+
-+      ret = devm_snd_soc_register_component(&pdev->dev, &sf_pdm_component_drv,
-+                                            &sf_pdm_dai_drv, 1);
-+      if (ret) {
-+              dev_err(&pdev->dev, "failed to register pdm dai\n");
-+              return ret;
-+      }
-+      pm_runtime_enable(&pdev->dev);
-+
-+      return 0;
-+}
-+
-+static int sf_pdm_dev_remove(struct platform_device *pdev)
-+{
-+      pm_runtime_disable(&pdev->dev);
-+      return 0;
-+}
-+
-+static const struct of_device_id sf_pdm_of_match[] = {
-+      {.compatible = "starfive,jh7110-pdm",},
-+      {}
-+};
-+MODULE_DEVICE_TABLE(of, sf_pdm_of_match);
-+
-+static const struct dev_pm_ops sf_pdm_pm_ops = {
-+      SET_RUNTIME_PM_OPS(sf_pdm_runtime_suspend,
-+                         sf_pdm_runtime_resume, NULL)
-+};
-+
-+static struct platform_driver sf_pdm_driver = {
-+      .driver = {
-+              .name = "jh7110-pdm",
-+              .of_match_table = sf_pdm_of_match,
-+              .pm = &sf_pdm_pm_ops,
-+      },
-+      .probe = sf_pdm_probe,
-+      .remove = sf_pdm_dev_remove,
-+};
-+module_platform_driver(sf_pdm_driver);
-+
-+MODULE_AUTHOR("Walker Chen <walker.chen@starfivetech.com>");
-+MODULE_DESCRIPTION("Starfive PDM Controller Driver");
-+MODULE_LICENSE("GPL v2");
diff --git a/target/linux/starfive/patches-6.6/0082-dt-binding-input-Add-tink_ft5406.patch b/target/linux/starfive/patches-6.6/0082-dt-binding-input-Add-tink_ft5406.patch
deleted file mode 100644 (file)
index ed8a3af..0000000
+++ /dev/null
@@ -1,55 +0,0 @@
-From 59cbdfeee0fc1ad382a0bc8f7fa897a9f5d03df0 Mon Sep 17 00:00:00 2001
-From: Changhuang Liang <changhuang.liang@starfivetech.com>
-Date: Fri, 9 Jun 2023 16:54:36 +0800
-Subject: [PATCH 082/116] dt-binding: input: Add tink_ft5406
-
-Add tink_ft5406.
-
-Signed-off-by: Changhuang Liang <changhuang.liang@starfivetech.com>
----
- .../bindings/input/tinker_ft5406.yaml         | 39 +++++++++++++++++++
- 1 file changed, 39 insertions(+)
- create mode 100644 Documentation/devicetree/bindings/input/tinker_ft5406.yaml
-
---- /dev/null
-+++ b/Documentation/devicetree/bindings/input/tinker_ft5406.yaml
-@@ -0,0 +1,39 @@
-+# SPDX-License-Identifier: GPL-2.0
-+%YAML 1.2
-+---
-+$id: http://devicetree.org/schemas/input/touchscreen/goodix.yaml#
-+$schema: http://devicetree.org/meta-schemas/core.yaml#
-+
-+title: Tinker FT5406 touchscreen controller Bindings
-+
-+maintainers:
-+  - Changhuang Liang <changhuang.liang@starfivetech.com>
-+
-+allOf:
-+  - $ref: touchscreen.yaml#
-+
-+properties:
-+  compatible:
-+    const: tinker_ft5406
-+
-+  reg:
-+    const: 0x38
-+
-+additionalProperties: false
-+
-+required:
-+  - compatible
-+  - reg
-+
-+examples:
-+  - |
-+    i2c {
-+      #address-cells = <1>;
-+      #size-cells = <0>;
-+      tinker_ft5406@38 {
-+        compatible = "tinker_ft5406";
-+        reg = <0x38>;
-+      };
-+    };
-+
-+...
diff --git a/target/linux/starfive/patches-6.6/0083-input-touchscreen-Add-tinker_ft5406-driver-support.patch b/target/linux/starfive/patches-6.6/0083-input-touchscreen-Add-tinker_ft5406-driver-support.patch
deleted file mode 100644 (file)
index f45085f..0000000
+++ /dev/null
@@ -1,444 +0,0 @@
-From 4800b6e0f2190d991cd4e5352167a9422841f195 Mon Sep 17 00:00:00 2001
-From: Changhuang Liang <changhuang.liang@starfivetech.com>
-Date: Wed, 21 Dec 2022 16:20:04 +0800
-Subject: [PATCH 083/116] input: touchscreen: Add tinker_ft5406 driver support
-
-Add tinker_ft5406 driver support
-
-Signed-off-by: Changhuang Liang <changhuang.liang@starfivetech.com>
----
- drivers/input/touchscreen/Kconfig         |   6 +
- drivers/input/touchscreen/Makefile        |   1 +
- drivers/input/touchscreen/tinker_ft5406.c | 406 ++++++++++++++++++++++
- 3 files changed, 413 insertions(+)
- create mode 100644 drivers/input/touchscreen/tinker_ft5406.c
-
---- a/drivers/input/touchscreen/Kconfig
-+++ b/drivers/input/touchscreen/Kconfig
-@@ -1399,4 +1399,10 @@ config TOUCHSCREEN_HIMAX_HX83112B
-         To compile this driver as a module, choose M here: the
-         module will be called himax_hx83112b.
-+config TOUCHSCREEN_TINKER_FT5406
-+      tristate "tinker ft5406"
-+      depends on I2C
-+      help
-+        Control ft5406 touch ic.
-+
- endif
---- a/drivers/input/touchscreen/Makefile
-+++ b/drivers/input/touchscreen/Makefile
-@@ -118,3 +118,4 @@ obj-$(CONFIG_TOUCHSCREEN_IQS5XX)   += iqs5
- obj-$(CONFIG_TOUCHSCREEN_IQS7211)     += iqs7211.o
- obj-$(CONFIG_TOUCHSCREEN_ZINITIX)     += zinitix.o
- obj-$(CONFIG_TOUCHSCREEN_HIMAX_HX83112B)      += himax_hx83112b.o
-+obj-$(CONFIG_TOUCHSCREEN_TINKER_FT5406)       += tinker_ft5406.o
---- /dev/null
-+++ b/drivers/input/touchscreen/tinker_ft5406.c
-@@ -0,0 +1,406 @@
-+// SPDX-License-Identifier: GPL-2.0
-+/*
-+ *
-+ * TINKER BOARD FT5406 touch driver.
-+ *
-+ * Copyright (c) 2016 ASUSTek Computer Inc.
-+ * Copyright (c) 2012-2014, The Linux Foundation. All rights reserved.
-+ *
-+ * This software is licensed under the terms of the GNU General Public
-+ * License version 2, as published by the Free Software Foundation, and
-+ * may be copied, distributed, and modified under those terms.
-+ *
-+ * This program is distributed in the hope that it will be useful,
-+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
-+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-+ * GNU General Public License for more details.
-+ *
-+ */
-+
-+#include <linux/module.h>
-+#include <linux/slab.h>
-+#include <linux/delay.h>
-+#include <linux/i2c.h>
-+#include <linux/input.h>
-+#include <linux/input/mt.h>
-+#include <linux/module.h>
-+#include <linux/workqueue.h>
-+
-+#define RETRY_COUNT 10
-+#define FT_ONE_TCH_LEN        6
-+
-+#define FT_REG_FW_VER                 0xA6
-+#define FT_REG_FW_MIN_VER             0xB2
-+#define FT_REG_FW_SUB_MIN_VER 0xB3
-+
-+#define VALID_TD_STATUS_VAL           10
-+#define MAX_TOUCH_POINTS              5
-+
-+#define FT_PRESS                      0x7F
-+#define FT_MAX_ID                     0x0F
-+
-+#define FT_TOUCH_X_H  0
-+#define FT_TOUCH_X_L  1
-+#define FT_TOUCH_Y_H  2
-+#define FT_TOUCH_Y_L  3
-+#define FT_TOUCH_EVENT        0
-+#define FT_TOUCH_ID           2
-+
-+#define FT_TOUCH_X_H_REG      3
-+#define FT_TOUCH_X_L_REG      4
-+#define FT_TOUCH_Y_H_REG      5
-+#define FT_TOUCH_Y_L_REG      6
-+#define FT_TD_STATUS_REG      2
-+#define FT_TOUCH_EVENT_REG    3
-+#define FT_TOUCH_ID_REG               5
-+
-+#define FT_TOUCH_DOWN         0
-+#define FT_TOUCH_CONTACT      2
-+
-+struct ts_event {
-+      u16 au16_x[MAX_TOUCH_POINTS]; /*x coordinate */
-+      u16 au16_y[MAX_TOUCH_POINTS]; /*y coordinate */
-+      u8 au8_touch_event[MAX_TOUCH_POINTS]; /*touch event: 0:down; 1:up; 2:contact */
-+      u8 au8_finger_id[MAX_TOUCH_POINTS]; /*touch ID */
-+      u16 pressure;
-+      u8 touch_point;
-+      u8 point_num;
-+};
-+
-+struct tinker_ft5406_data {
-+      struct device *dev;
-+      struct i2c_client *client;
-+      struct input_dev *input_dev;
-+      struct ts_event event;
-+      struct work_struct ft5406_work;
-+
-+      int screen_width;
-+      int screen_height;
-+      int xy_reverse;
-+      int known_ids;
-+      int retry_count;
-+      bool finish_work;
-+};
-+
-+struct tinker_ft5406_data *g_ts_data;
-+
-+static int fts_i2c_read(struct i2c_client *client, char *writebuf,
-+                         int writelen, char *readbuf, int readlen)
-+{
-+      int ret;
-+
-+      if (writelen > 0) {
-+              struct i2c_msg msgs[] = {
-+                      {
-+                               .addr = client->addr,
-+                               .flags = 0,
-+                               .len = writelen,
-+                               .buf = writebuf,
-+                       },
-+                      {
-+                               .addr = client->addr,
-+                               .flags = I2C_M_RD,
-+                               .len = readlen,
-+                               .buf = readbuf,
-+                       },
-+              };
-+              ret = i2c_transfer(client->adapter, msgs, 2);
-+              if (ret < 0)
-+                      dev_err(&client->dev, "i2c read error, %d\n", ret);
-+      } else {
-+              struct i2c_msg msgs[] = {
-+                      {
-+                               .addr = client->addr,
-+                               .flags = I2C_M_RD,
-+                               .len = readlen,
-+                               .buf = readbuf,
-+                       },
-+              };
-+              ret = i2c_transfer(client->adapter, msgs, 1);
-+              if (ret < 0)
-+                      dev_err(&client->dev, "i2c read error, %d\n", ret);
-+      }
-+
-+      return ret;
-+}
-+
-+static int fts_read_reg(struct i2c_client *client, u8 addr, u8 *val)
-+{
-+      return fts_i2c_read(client, &addr, 1, val, 1);
-+}
-+
-+static int fts_check_fw_ver(struct i2c_client *client)
-+{
-+      u8 reg_addr, fw_ver[3];
-+      int ret;
-+
-+      reg_addr = FT_REG_FW_VER;
-+      ret = fts_i2c_read(client, &reg_addr, 1, &fw_ver[0], 1);
-+      if (ret < 0)
-+              goto error;
-+
-+      reg_addr = FT_REG_FW_MIN_VER;
-+      ret = fts_i2c_read(client, &reg_addr, 1, &fw_ver[1], 1);
-+      if (ret < 0)
-+              goto error;
-+
-+      reg_addr = FT_REG_FW_SUB_MIN_VER;
-+      ret = fts_i2c_read(client, &reg_addr, 1, &fw_ver[2], 1);
-+      if (ret < 0)
-+              goto error;
-+
-+      dev_info(&client->dev, "Firmware version = %d.%d.%d\n",
-+                      fw_ver[0], fw_ver[1], fw_ver[2]);
-+      return 0;
-+
-+error:
-+      return ret;
-+}
-+
-+static int fts_read_td_status(struct tinker_ft5406_data *ts_data)
-+{
-+      u8 td_status;
-+      int ret = -1;
-+
-+      ret = fts_read_reg(ts_data->client, FT_TD_STATUS_REG, &td_status);
-+      if (ret < 0) {
-+              dev_err(&ts_data->client->dev,
-+                              "Get reg td_status failed, %d\n", ret);
-+              return ret;
-+      }
-+      return (int)td_status;
-+}
-+
-+static int fts_read_touchdata(struct tinker_ft5406_data *ts_data)
-+{
-+      struct ts_event *event = &ts_data->event;
-+      int ret = -1, i;
-+      u8 buf[FT_ONE_TCH_LEN-2] = { 0 };
-+      u8 reg_addr, pointid = FT_MAX_ID;
-+
-+      for (i = 0; i < event->touch_point && i < MAX_TOUCH_POINTS; i++) {
-+              reg_addr = FT_TOUCH_X_H_REG + (i * FT_ONE_TCH_LEN);
-+              ret = fts_i2c_read(ts_data->client, &reg_addr, 1, buf, FT_ONE_TCH_LEN-2);
-+              if (ret < 0) {
-+                      dev_err(&ts_data->client->dev, "Read touchdata failed.\n");
-+                      return ret;
-+              }
-+
-+              pointid = (buf[FT_TOUCH_ID]) >> 4;
-+              if (pointid >= MAX_TOUCH_POINTS)
-+                      break;
-+              event->au8_finger_id[i] = pointid;
-+              event->au16_x[i] = (s16) (buf[FT_TOUCH_X_H] & 0x0F) << 8 | (s16) buf[FT_TOUCH_X_L];
-+              event->au16_y[i] = (s16) (buf[FT_TOUCH_Y_H] & 0x0F) << 8 | (s16) buf[FT_TOUCH_Y_L];
-+              event->au8_touch_event[i] = buf[FT_TOUCH_EVENT] >> 6;
-+
-+              if (ts_data->xy_reverse) {
-+                      event->au16_x[i] = ts_data->screen_width - event->au16_x[i] - 1;
-+                      event->au16_y[i] = ts_data->screen_height - event->au16_y[i] - 1;
-+              }
-+      }
-+      event->pressure = FT_PRESS;
-+
-+      return 0;
-+}
-+
-+static void fts_report_value(struct tinker_ft5406_data *ts_data)
-+{
-+      struct ts_event *event = &ts_data->event;
-+      int i, modified_ids = 0, released_ids;
-+
-+      for (i = 0; i < event->touch_point && i < MAX_TOUCH_POINTS; i++) {
-+              if (event->au8_touch_event[i] == FT_TOUCH_DOWN ||
-+                      event->au8_touch_event[i] == FT_TOUCH_CONTACT) {
-+                      modified_ids |= 1 << event->au8_finger_id[i];
-+                      input_mt_slot(ts_data->input_dev, event->au8_finger_id[i]);
-+                      input_mt_report_slot_state(ts_data->input_dev, MT_TOOL_FINGER,
-+                              true);
-+                      input_report_abs(ts_data->input_dev, ABS_MT_TOUCH_MAJOR,
-+                                      event->pressure);
-+                      input_report_abs(ts_data->input_dev, ABS_MT_POSITION_X,
-+                                      event->au16_x[i]);
-+                      input_report_abs(ts_data->input_dev, ABS_MT_POSITION_Y,
-+                                      event->au16_y[i]);
-+
-+                      if (!((1 << event->au8_finger_id[i]) & ts_data->known_ids))
-+                              dev_dbg(&ts_data->client->dev, "Touch id-%d: x = %d, y = %d\n",
-+                                      event->au8_finger_id[i],
-+                                      event->au16_x[i],
-+                                      event->au16_y[i]);
-+              }
-+      }
-+
-+      released_ids = ts_data->known_ids & ~modified_ids;
-+      for (i = 0; released_ids && i < MAX_TOUCH_POINTS; i++) {
-+              if (released_ids & (1<<i)) {
-+                      dev_dbg(&ts_data->client->dev, "Release id-%d, known = %x modified = %x\n",
-+                                      i, ts_data->known_ids, modified_ids);
-+                      input_mt_slot(ts_data->input_dev, i);
-+                      input_mt_report_slot_state(ts_data->input_dev, MT_TOOL_FINGER, false);
-+                      modified_ids &= ~(1 << i);
-+              }
-+      }
-+      ts_data->known_ids = modified_ids;
-+      input_mt_report_pointer_emulation(ts_data->input_dev, true);
-+      input_sync(ts_data->input_dev);
-+}
-+
-+static void fts_retry_clear(struct tinker_ft5406_data *ts_data)
-+{
-+      if (ts_data->retry_count != 0)
-+              ts_data->retry_count = 0;
-+}
-+
-+static int fts_retry_wait(struct tinker_ft5406_data *ts_data)
-+{
-+      if (ts_data->retry_count < RETRY_COUNT) {
-+              dev_info(&ts_data->client->dev,
-+                      "Wait and retry, count = %d\n", ts_data->retry_count);
-+              ts_data->retry_count++;
-+              msleep(1000);
-+              return 1;
-+      }
-+      dev_err(&ts_data->client->dev, "Attach retry count\n");
-+      return 0;
-+}
-+
-+static void tinker_ft5406_work(struct work_struct *work)
-+{
-+      struct ts_event *event = &g_ts_data->event;
-+      int ret = 0, td_status;
-+
-+      /* polling 60fps */
-+      while (!g_ts_data->finish_work) {
-+              td_status = fts_read_td_status(g_ts_data);
-+              if (td_status < 0) {
-+                      ret = fts_retry_wait(g_ts_data);
-+                      if (ret == 0) {
-+                              dev_err(&g_ts_data->client->dev, "Stop touch polling\n");
-+                              break;
-+                      }
-+              } else if (td_status < VALID_TD_STATUS_VAL + 1 &&
-+                      (td_status > 0 || g_ts_data->known_ids != 0)) {
-+                      fts_retry_clear(g_ts_data);
-+                      memset(event, -1, sizeof(struct ts_event));
-+                      event->touch_point = td_status;
-+                      ret = fts_read_touchdata(g_ts_data);
-+                      if (ret == 0)
-+                              fts_report_value(g_ts_data);
-+              }
-+              msleep_interruptible(17);
-+      }
-+}
-+
-+static int tinker_ft5406_open(struct input_dev *dev)
-+{
-+      schedule_work(&g_ts_data->ft5406_work);
-+      return 0;
-+}
-+
-+static void tinker_ft5406_close(struct input_dev *dev)
-+{
-+      g_ts_data->finish_work = true;
-+      cancel_work_sync(&g_ts_data->ft5406_work);
-+      g_ts_data->finish_work = false;
-+}
-+
-+static int tinker_ft5406_probe(struct i2c_client *client)
-+{
-+      struct input_dev *input_dev;
-+      int ret = 0;
-+
-+      dev_info(&client->dev, "Address = 0x%x\n", client->addr);
-+
-+      g_ts_data = kzalloc(sizeof(struct tinker_ft5406_data), GFP_KERNEL);
-+      if (g_ts_data == NULL) {
-+              dev_err(&client->dev, "No memory for device\n");
-+              return -ENOMEM;
-+      }
-+
-+      g_ts_data->client = client;
-+      i2c_set_clientdata(client, g_ts_data);
-+
-+      g_ts_data->screen_width = 800;
-+      g_ts_data->screen_height = 480;
-+      g_ts_data->xy_reverse = 1;
-+
-+      dev_info(&client->dev, "width = %d, height = %d, reverse = %d\n",
-+                      g_ts_data->screen_width, g_ts_data->screen_height, g_ts_data->xy_reverse);
-+
-+      ret = fts_check_fw_ver(g_ts_data->client);
-+      if (ret) {
-+              dev_err(&client->dev, "Checking touch ic failed\n");
-+              goto check_fw_err;
-+      }
-+
-+      input_dev = input_allocate_device();
-+      if (!input_dev) {
-+              dev_err(&client->dev, "Failed to allocate input device\n");
-+              goto input_allocate_failed;
-+      }
-+      input_dev->name = "fts_ts";
-+      input_dev->id.bustype = BUS_I2C;
-+      input_dev->dev.parent = &g_ts_data->client->dev;
-+      input_dev->open = tinker_ft5406_open;
-+      input_dev->close = tinker_ft5406_close;
-+
-+      g_ts_data->input_dev = input_dev;
-+      input_set_drvdata(input_dev, g_ts_data);
-+
-+      __set_bit(EV_SYN, input_dev->evbit);
-+      __set_bit(EV_KEY, input_dev->evbit);
-+      __set_bit(EV_ABS, input_dev->evbit);
-+      __set_bit(BTN_TOUCH, input_dev->keybit);
-+
-+      input_mt_init_slots(input_dev, MAX_TOUCH_POINTS, 0);
-+      input_set_abs_params(input_dev, ABS_MT_POSITION_X, 0, g_ts_data->screen_width, 0, 0);
-+      input_set_abs_params(input_dev, ABS_MT_POSITION_Y, 0, g_ts_data->screen_height, 0, 0);
-+
-+      ret = input_register_device(input_dev);
-+      if (ret) {
-+              dev_err(&client->dev, "Input device registration failed\n");
-+              goto input_register_failed;
-+      }
-+
-+      INIT_WORK(&g_ts_data->ft5406_work, tinker_ft5406_work);
-+
-+      return 0;
-+
-+input_register_failed:
-+      input_free_device(input_dev);
-+input_allocate_failed:
-+check_fw_err:
-+      kfree(g_ts_data);
-+      g_ts_data = NULL;
-+      return ret;
-+}
-+
-+static void tinker_ft5406_remove(struct i2c_client *client)
-+{
-+      cancel_work_sync(&g_ts_data->ft5406_work);
-+      if (g_ts_data->input_dev) {
-+              input_unregister_device(g_ts_data->input_dev);
-+              input_free_device(g_ts_data->input_dev);
-+      }
-+      kfree(g_ts_data);
-+      g_ts_data = NULL;
-+}
-+
-+static const struct i2c_device_id tinker_ft5406_id[] = {
-+      {"tinker_ft5406", 0},
-+      {},
-+};
-+
-+static struct i2c_driver tinker_ft5406_driver = {
-+      .driver = {
-+              .name = "tinker_ft5406",
-+      },
-+      .probe = tinker_ft5406_probe,
-+      .remove = tinker_ft5406_remove,
-+      .id_table = tinker_ft5406_id,
-+};
-+module_i2c_driver(tinker_ft5406_driver);
-+
-+MODULE_DESCRIPTION("TINKER BOARD FT5406 Touch driver");
-+MODULE_LICENSE("GPL v2");
diff --git a/target/linux/starfive/patches-6.6/0084-dt-binding-media-Add-JH7110-Camera-Subsystem.patch b/target/linux/starfive/patches-6.6/0084-dt-binding-media-Add-JH7110-Camera-Subsystem.patch
deleted file mode 100644 (file)
index 69d7c7f..0000000
+++ /dev/null
@@ -1,246 +0,0 @@
-From b477a1a53553336edcfeb83be1b35817928daed8 Mon Sep 17 00:00:00 2001
-From: Changhuang Liang <changhuang.liang@starfivetech.com>
-Date: Mon, 5 Jun 2023 14:46:16 +0800
-Subject: [PATCH 084/116] dt-binding: media: Add JH7110 Camera Subsystem.
-
-Add the bindings documentation for Starfive JH7110 Camera Subsystem
-which is used for handing image sensor data.
-
-Signed-off-by: Changhuang Liang <changhuang.liang@starfivetech.com>
-Signed-off-by: Jack Zhu <jack.zhu@starfivetech.com>
----
- .../bindings/media/starfive,jh7110-camss.yaml | 228 ++++++++++++++++++
- 1 file changed, 228 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,228 @@
-+# 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 <jack.zhu@starfivetech.com>
-+  - Changhuang Liang <changhuang.liang@starfivetech.com>
-+
-+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 unit)
-+  and an ISP.
-+
-+properties:
-+  compatible:
-+    const: starfive,jh7110-vin
-+
-+  reg:
-+    maxItems: 8
-+
-+  reg-names:
-+    items:
-+      - const: csi2rx
-+      - const: vclk
-+      - const: vrst
-+      - const: sctrl
-+      - const: isp
-+      - const: trst
-+      - const: pmu
-+      - const: syscrg
-+
-+  clocks:
-+    maxItems: 16
-+
-+  clock-names:
-+    items:
-+      - const: clk_apb_func
-+      - const: clk_pclk
-+      - const: clk_sys_clk
-+      - const: clk_wrapper_clk_c
-+      - const: clk_dvp_inv
-+      - const: clk_axiwr
-+      - const: clk_mipi_rx0_pxl
-+      - const: clk_pixel_clk_if0
-+      - const: clk_pixel_clk_if1
-+      - const: clk_pixel_clk_if2
-+      - const: clk_pixel_clk_if3
-+      - const: clk_m31dphy_cfgclk_in
-+      - const: clk_m31dphy_refclk_in
-+      - const: clk_m31dphy_txclkesc_lan0
-+      - const: clk_ispcore_2x
-+      - const: clk_isp_axi
-+
-+  resets:
-+    maxItems: 14
-+
-+  reset-names:
-+    items:
-+      - const: rst_wrapper_p
-+      - const: rst_wrapper_c
-+      - const: rst_pclk
-+      - const: rst_sys_clk
-+      - const: rst_axird
-+      - const: rst_axiwr
-+      - const: rst_pixel_clk_if0
-+      - const: rst_pixel_clk_if1
-+      - const: rst_pixel_clk_if2
-+      - const: rst_pixel_clk_if3
-+      - const: rst_m31dphy_hw
-+      - const: rst_m31dphy_b09_always_on
-+      - const: rst_isp_top_n
-+      - const: rst_isp_top_axi
-+
-+  power-domains:
-+    items:
-+      - description: JH7110 ISP Power Domain Switch Controller.
-+
-+  interrupts:
-+    maxItems: 5
-+
-+  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:
-+  - |
-+              vin_sysctl: vin_sysctl@19800000 {
-+                      compatible = "starfive,jh7110-vin";
-+                      reg = <0x0 0x19800000 0x0 0x10000>,
-+                                  <0x0 0x19810000 0x0 0x10000>,
-+                                  <0x0 0x19820000 0x0 0x10000>,
-+                                  <0x0 0x19840000 0x0 0x10000>,
-+                                  <0x0 0x19870000 0x0 0x30000>,
-+                                  <0x0 0x11840000 0x0 0x10000>,
-+                                  <0x0 0x17030000 0x0 0x10000>,
-+                                  <0x0 0x13020000 0x0 0x10000>;
-+                      reg-names = "csi2rx", "vclk", "vrst", "sctrl",
-+                                        "isp", "trst", "pmu", "syscrg";
-+                      clocks = <&clkisp JH7110_DOM4_APB_FUNC>,
-+                                     <&clkisp JH7110_U0_VIN_PCLK>,
-+                                     <&clkisp JH7110_U0_VIN_SYS_CLK>,
-+                                     <&clkisp JH7110_U0_ISPV2_TOP_WRAPPER_CLK_C>,
-+                                     <&clkisp JH7110_DVP_INV>,
-+                                     <&clkisp JH7110_U0_VIN_CLK_P_AXIWR>,
-+                                     <&clkisp JH7110_MIPI_RX0_PXL>,
-+                                     <&clkisp JH7110_U0_VIN_PIXEL_CLK_IF0>,
-+                                     <&clkisp JH7110_U0_VIN_PIXEL_CLK_IF1>,
-+                                     <&clkisp JH7110_U0_VIN_PIXEL_CLK_IF2>,
-+                                     <&clkisp JH7110_U0_VIN_PIXEL_CLK_IF3>,
-+                                     <&clkisp JH7110_U0_M31DPHY_CFGCLK_IN>,
-+                                     <&clkisp JH7110_U0_M31DPHY_REFCLK_IN>,
-+                                     <&clkisp JH7110_U0_M31DPHY_TXCLKESC_LAN0>,
-+                                     <&clkgen JH7110_ISP_TOP_CLK_ISPCORE_2X>,
-+                                     <&clkgen JH7110_ISP_TOP_CLK_ISP_AXI>;
-+                      clock-names = "clk_apb_func", "clk_pclk", "clk_sys_clk",
-+                                          "clk_wrapper_clk_c", "clk_dvp_inv", "clk_axiwr",
-+                                          "clk_mipi_rx0_pxl", "clk_pixel_clk_if0",
-+                                          "clk_pixel_clk_if1", "clk_pixel_clk_if2",
-+                                          "clk_pixel_clk_if3", "clk_m31dphy_cfgclk_in",
-+                                          "clk_m31dphy_refclk_in", "clk_m31dphy_txclkesc_lan0",
-+                                          "clk_ispcore_2x", "clk_isp_axi";
-+                      resets = <&rstgen RSTN_U0_ISPV2_TOP_WRAPPER_P>,
-+                                     <&rstgen RSTN_U0_ISPV2_TOP_WRAPPER_C>,
-+                                     <&rstgen RSTN_U0_VIN_N_PCLK>,
-+                                     <&rstgen RSTN_U0_VIN_N_SYS_CLK>,
-+                                     <&rstgen RSTN_U0_VIN_P_AXIRD>,
-+                                     <&rstgen RSTN_U0_VIN_P_AXIWR>,
-+                                     <&rstgen RSTN_U0_VIN_N_PIXEL_CLK_IF0>,
-+                                     <&rstgen RSTN_U0_VIN_N_PIXEL_CLK_IF1>,
-+                                     <&rstgen RSTN_U0_VIN_N_PIXEL_CLK_IF2>,
-+                                     <&rstgen RSTN_U0_VIN_N_PIXEL_CLK_IF3>,
-+                                     <&rstgen RSTN_U0_M31DPHY_HW>,
-+                                     <&rstgen RSTN_U0_M31DPHY_B09_ALWAYS_ON>,
-+                                     <&rstgen RSTN_U0_DOM_ISP_TOP_N>,
-+                                     <&rstgen RSTN_U0_DOM_ISP_TOP_AXI>;
-+                      reset-names = "rst_wrapper_p", "rst_wrapper_c", "rst_pclk",
-+                                      "rst_sys_clk", "rst_axird", "rst_axiwr", "rst_pixel_clk_if0",
-+                                      "rst_pixel_clk_if1", "rst_pixel_clk_if2", "rst_pixel_clk_if3",
-+                                      "rst_m31dphy_hw", "rst_m31dphy_b09_always_on",
-+                                      "rst_isp_top_n", "rst_isp_top_axi";
-+                      starfive,aon-syscon = <&aon_syscon 0x00>;
-+                      power-domains = <&pwrc JH7110_PD_ISP>;
-+                      /* irq nr: vin, isp, isp_csi, isp_scd, isp_csiline */
-+                      interrupts = <92>, <87>, <88>, <89>, <90>;
-+
-+      ports {
-+        #address-cells = <1>;
-+        #size-cells = <0>;
-+        port@0 {
-+          reg = <0>;
-+          vin_from_sc2235: endpoint {
-+            remote-endpoint = <&sc2235_to_vin>;
-+            bus-type = <5>;
-+            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>;
-+          };
-+        };
-+      };
-+    };
diff --git a/target/linux/starfive/patches-6.6/0085-media-starfive-Add-vin-driver-support.patch b/target/linux/starfive/patches-6.6/0085-media-starfive-Add-vin-driver-support.patch
deleted file mode 100644 (file)
index b5d5f73..0000000
+++ /dev/null
@@ -1,24014 +0,0 @@
-From 908b10ebc95eb29caae8c4737b23a29af5c6298f Mon Sep 17 00:00:00 2001
-From: Changhuang Liang <changhuang.liang@starfivetech.com>
-Date: Mon, 5 Jun 2023 13:54:16 +0800
-Subject: [PATCH 085/116] media: starfive: Add vin driver support
-
-Add vin driver support.
-
-Signed-off-by: Changhuang Liang <changhuang.liang@starfivetech.com>
----
- drivers/media/platform/Kconfig                |    1 +
- drivers/media/platform/Makefile               |    1 +
- drivers/media/platform/starfive/Kconfig       |   56 +
- drivers/media/platform/starfive/Makefile      |   24 +
- .../platform/starfive/v4l2_driver/Readme.txt  |   11 +
- .../starfive/v4l2_driver/imx219_mipi.c        | 1583 ++++++++
- .../starfive/v4l2_driver/ov13850_mipi.c       | 1921 ++++++++++
- .../starfive/v4l2_driver/ov4689_mipi.c        | 2975 +++++++++++++++
- .../platform/starfive/v4l2_driver/ov5640.c    | 3227 +++++++++++++++++
- .../platform/starfive/v4l2_driver/sc2235.c    | 1914 ++++++++++
- .../starfive/v4l2_driver/stf_common.h         |  185 +
- .../platform/starfive/v4l2_driver/stf_csi.c   |  465 +++
- .../platform/starfive/v4l2_driver/stf_csi.h   |   61 +
- .../starfive/v4l2_driver/stf_csi_hw_ops.c     |  310 ++
- .../starfive/v4l2_driver/stf_csiphy.c         |  357 ++
- .../starfive/v4l2_driver/stf_csiphy.h         |  188 +
- .../starfive/v4l2_driver/stf_csiphy_hw_ops.c  |  335 ++
- .../starfive/v4l2_driver/stf_dmabuf.c         |  123 +
- .../starfive/v4l2_driver/stf_dmabuf.h         |   12 +
- .../platform/starfive/v4l2_driver/stf_dvp.c   |  385 ++
- .../platform/starfive/v4l2_driver/stf_dvp.h   |   67 +
- .../starfive/v4l2_driver/stf_dvp_hw_ops.c     |  187 +
- .../platform/starfive/v4l2_driver/stf_event.c |   36 +
- .../platform/starfive/v4l2_driver/stf_isp.c   | 1521 ++++++++
- .../platform/starfive/v4l2_driver/stf_isp.h   |  222 ++
- .../starfive/v4l2_driver/stf_isp_hw_ops.c     | 1550 ++++++++
- .../starfive/v4l2_driver/stf_isp_ioctl.h      |  133 +
- .../platform/starfive/v4l2_driver/stf_video.c | 1552 ++++++++
- .../platform/starfive/v4l2_driver/stf_video.h |   83 +
- .../platform/starfive/v4l2_driver/stf_vin.c   | 1515 ++++++++
- .../platform/starfive/v4l2_driver/stf_vin.h   |  182 +
- .../starfive/v4l2_driver/stf_vin_hw_ops.c     |  433 +++
- .../platform/starfive/v4l2_driver/stfcamss.c  | 1369 +++++++
- .../platform/starfive/v4l2_driver/stfcamss.h  |  117 +
- include/uapi/linux/jh7110-isp.h               |  253 ++
- include/uapi/linux/v4l2-controls.h            |    6 +
- include/video/stf-vin.h                       |  443 +++
- 37 files changed, 23803 insertions(+)
- create mode 100644 drivers/media/platform/starfive/Kconfig
- create mode 100644 drivers/media/platform/starfive/Makefile
- create mode 100644 drivers/media/platform/starfive/v4l2_driver/Readme.txt
- create mode 100644 drivers/media/platform/starfive/v4l2_driver/imx219_mipi.c
- create mode 100644 drivers/media/platform/starfive/v4l2_driver/ov13850_mipi.c
- create mode 100644 drivers/media/platform/starfive/v4l2_driver/ov4689_mipi.c
- create mode 100644 drivers/media/platform/starfive/v4l2_driver/ov5640.c
- create mode 100644 drivers/media/platform/starfive/v4l2_driver/sc2235.c
- create mode 100644 drivers/media/platform/starfive/v4l2_driver/stf_common.h
- create mode 100644 drivers/media/platform/starfive/v4l2_driver/stf_csi.c
- create mode 100644 drivers/media/platform/starfive/v4l2_driver/stf_csi.h
- create mode 100644 drivers/media/platform/starfive/v4l2_driver/stf_csi_hw_ops.c
- create mode 100644 drivers/media/platform/starfive/v4l2_driver/stf_csiphy.c
- create mode 100644 drivers/media/platform/starfive/v4l2_driver/stf_csiphy.h
- create mode 100644 drivers/media/platform/starfive/v4l2_driver/stf_csiphy_hw_ops.c
- create mode 100644 drivers/media/platform/starfive/v4l2_driver/stf_dmabuf.c
- create mode 100644 drivers/media/platform/starfive/v4l2_driver/stf_dmabuf.h
- create mode 100644 drivers/media/platform/starfive/v4l2_driver/stf_dvp.c
- create mode 100644 drivers/media/platform/starfive/v4l2_driver/stf_dvp.h
- create mode 100644 drivers/media/platform/starfive/v4l2_driver/stf_dvp_hw_ops.c
- create mode 100644 drivers/media/platform/starfive/v4l2_driver/stf_event.c
- create mode 100644 drivers/media/platform/starfive/v4l2_driver/stf_isp.c
- create mode 100644 drivers/media/platform/starfive/v4l2_driver/stf_isp.h
- create mode 100644 drivers/media/platform/starfive/v4l2_driver/stf_isp_hw_ops.c
- create mode 100644 drivers/media/platform/starfive/v4l2_driver/stf_isp_ioctl.h
- create mode 100644 drivers/media/platform/starfive/v4l2_driver/stf_video.c
- create mode 100644 drivers/media/platform/starfive/v4l2_driver/stf_video.h
- create mode 100644 drivers/media/platform/starfive/v4l2_driver/stf_vin.c
- create mode 100644 drivers/media/platform/starfive/v4l2_driver/stf_vin.h
- create mode 100644 drivers/media/platform/starfive/v4l2_driver/stf_vin_hw_ops.c
- create mode 100644 drivers/media/platform/starfive/v4l2_driver/stfcamss.c
- create mode 100644 drivers/media/platform/starfive/v4l2_driver/stfcamss.h
- create mode 100644 include/uapi/linux/jh7110-isp.h
- create mode 100644 include/video/stf-vin.h
-
---- a/drivers/media/platform/Kconfig
-+++ b/drivers/media/platform/Kconfig
-@@ -80,6 +80,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
-@@ -23,6 +23,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,56 @@
-+# SPDX-License-Identifier: GPL-2.0-only
-+
-+comment "Starfive media platform drivers"
-+
-+config VIN_SENSOR_OV5640
-+      tristate "VIN SENSOR support OV5640"
-+      depends on VIDEO_STF_VIN
-+      select V4L2_FWNODE
-+      default n
-+      help
-+        Say Y here if you want to have support for VIN sensor OV5640
-+
-+config VIN_SENSOR_SC2235
-+      tristate "VIN SENSOR support SC2235"
-+      depends on VIDEO_STF_VIN
-+      select V4L2_FWNODE
-+      default n
-+      help
-+        Say Y here if you want to have support for VIN sensor SC2235
-+
-+config VIN_SENSOR_OV4689
-+      tristate "VIN SENSOR support OV4689"
-+      depends on VIDEO_STF_VIN
-+      select V4L2_FWNODE
-+      default n
-+
-+      help
-+        Say Y here if you want to have support for VIN sensor OV4689
-+
-+config VIN_SENSOR_OV13850
-+      bool "VIN SENSOR support OV13850"
-+      depends on VIDEO_STF_VIN
-+      select V4L2_FWNODE
-+      default n
-+      help
-+        Say Y here if you want to have support for VIN sensor OV13850
-+
-+config VIN_SENSOR_IMX219
-+      tristate "VIN SENSOR support IMX219"
-+      depends on VIDEO_STF_VIN
-+      select V4L2_FWNODE
-+      default n
-+      help
-+        Say Y here if you want to have support for VIN sensor IMX219
-+
-+config VIDEO_STF_VIN
-+      tristate "starfive VIC video in support"
-+      depends on V4L_PLATFORM_DRIVERS
-+      depends on VIDEO_DEV
-+      select MEDIA_CONTROLLER
-+      select VIDEOBUF2_DMA_CONTIG
-+      select VIDEO_V4L2_SUBDEV_API
-+      select V4L2_FWNODE
-+      help
-+        To compile this driver as a module, choose M here: the module
-+        will be called stf-vin.
---- /dev/null
-+++ b/drivers/media/platform/starfive/Makefile
-@@ -0,0 +1,24 @@
-+# SPDX-License-Identifier: GPL-2.0
-+
-+obj-$(CONFIG_VIN_SENSOR_OV5640) += v4l2_driver/ov5640.o
-+obj-$(CONFIG_VIN_SENSOR_SC2235) += v4l2_driver/sc2235.o
-+obj-$(CONFIG_VIN_SENSOR_OV4689) += v4l2_driver/ov4689_mipi.o
-+obj-$(CONFIG_VIN_SENSOR_OV13850) += v4l2_driver/ov13850_mipi.o
-+obj-$(CONFIG_VIN_SENSOR_IMX219) += v4l2_driver/imx219_mipi.o
-+
-+starfivecamss-objs +=         v4l2_driver/stfcamss.o \
-+                      v4l2_driver/stf_event.o \
-+                      v4l2_driver/stf_dvp.o   \
-+                      v4l2_driver/stf_csi.o   \
-+                      v4l2_driver/stf_csiphy.o   \
-+                      v4l2_driver/stf_isp.o   \
-+                      v4l2_driver/stf_video.o \
-+                      v4l2_driver/stf_vin.o \
-+                      v4l2_driver/stf_vin_hw_ops.o \
-+                      v4l2_driver/stf_csi_hw_ops.o \
-+                      v4l2_driver/stf_csiphy_hw_ops.o \
-+                      v4l2_driver/stf_isp_hw_ops.o \
-+                      v4l2_driver/stf_dvp_hw_ops.o \
-+                      v4l2_driver/stf_dmabuf.o
-+
-+obj-$(CONFIG_VIDEO_STF_VIN) += starfivecamss.o \
---- /dev/null
-+++ b/drivers/media/platform/starfive/v4l2_driver/Readme.txt
-@@ -0,0 +1,11 @@
-+
-+/dev/video0: Output the camera data directly.
-+/dev/video1: Output the data of the camera converted by isp.
-+
-+ensure linux/arch/riscv/configs/starfive_jh7110_defconfig:
-+CONFIG_VIDEO_STF_VIN=y
-+CONFIG_VIN_SENSOR_SC2235=y
-+CONFIG_VIN_SENSOR_OV4689=y
-+
-+Only support the lane0/lane5 of dphy as clock lane, lane1/lane2/lane3/lane4
-+as data lane.
---- /dev/null
-+++ b/drivers/media/platform/starfive/v4l2_driver/imx219_mipi.c
-@@ -0,0 +1,1583 @@
-+// SPDX-License-Identifier: GPL-2.0
-+/*
-+ * A V4L2 driver for Sony IMX219 cameras.
-+ * Copyright (C) 2019, Raspberry Pi (Trading) Ltd
-+ *
-+ * Based on Sony imx258 camera driver
-+ * Copyright (C) 2018 Intel Corporation
-+ *
-+ * DT / fwnode changes, and regulator / GPIO control taken from imx214 driver
-+ * Copyright 2018 Qtechnology A/S
-+ *
-+ * Flip handling taken from the Sony IMX319 driver.
-+ * Copyright (C) 2018 Intel Corporation
-+ *
-+ */
-+
-+#include <linux/clk.h>
-+#include <linux/delay.h>
-+#include <linux/gpio/consumer.h>
-+#include <linux/i2c.h>
-+#include <linux/module.h>
-+#include <linux/pm_runtime.h>
-+#include <linux/regulator/consumer.h>
-+#include <media/v4l2-ctrls.h>
-+#include <media/v4l2-device.h>
-+#include <media/v4l2-event.h>
-+#include <media/v4l2-fwnode.h>
-+#include <media/v4l2-mediabus.h>
-+#include <asm/unaligned.h>
-+
-+#define IMX219_REG_VALUE_08BIT                1
-+#define IMX219_REG_VALUE_16BIT                2
-+
-+#define IMX219_REG_MODE_SELECT                0x0100
-+#define IMX219_MODE_STANDBY           0x00
-+#define IMX219_MODE_STREAMING         0x01
-+
-+/* Chip ID */
-+#define IMX219_REG_CHIP_ID            0x0000
-+#define IMX219_CHIP_ID                        0x0219
-+
-+/* External clock frequency is 24.0M */
-+#define IMX219_XCLK_FREQ              24000000
-+
-+/* Pixel rate is fixed at 182.4M for all the modes */
-+#define IMX219_PIXEL_RATE             182400000
-+
-+#define IMX219_DEFAULT_LINK_FREQ      456000000
-+
-+/* V_TIMING internal */
-+#define IMX219_REG_VTS                        0x0160
-+#define IMX219_VTS_15FPS              0x0dc6
-+#define IMX219_VTS_30FPS_1080P                0x06e3
-+#define IMX219_VTS_30FPS_BINNED               0x06e3
-+#define IMX219_VTS_30FPS_1280x720     0x06e3
-+#define IMX219_VTS_30FPS_640x480      0x06e3
-+#define IMX219_VTS_MAX                        0xffff
-+
-+#define IMX219_VBLANK_MIN             4
-+
-+/*Frame Length Line*/
-+#define IMX219_FLL_MIN                        0x08a6
-+#define IMX219_FLL_MAX                        0xffff
-+#define IMX219_FLL_STEP                       1
-+#define IMX219_FLL_DEFAULT            0x0c98
-+
-+/* HBLANK control - read only */
-+#define IMX219_PPL_DEFAULT            3448
-+
-+/* Exposure control */
-+#define IMX219_REG_EXPOSURE           0x015a
-+#define IMX219_EXPOSURE_MIN           4
-+#define IMX219_EXPOSURE_STEP          1
-+#define IMX219_EXPOSURE_DEFAULT               0x640
-+#define IMX219_EXPOSURE_MAX           65535
-+
-+/* Analog gain control */
-+#define IMX219_REG_ANALOG_GAIN                0x0157
-+#define IMX219_ANA_GAIN_MIN           0
-+#define IMX219_ANA_GAIN_MAX           232
-+#define IMX219_ANA_GAIN_STEP          1
-+#define IMX219_ANA_GAIN_DEFAULT               0xd0
-+
-+/* Digital gain control */
-+#define IMX219_REG_DIGITAL_GAIN               0x0158
-+#define IMX219_DGTL_GAIN_MIN          0x0100
-+#define IMX219_DGTL_GAIN_MAX          0x0fff
-+#define IMX219_DGTL_GAIN_DEFAULT      0x0100
-+#define IMX219_DGTL_GAIN_STEP         1
-+
-+#define IMX219_REG_ORIENTATION                0x0172
-+
-+/* Test Pattern Control */
-+#define IMX219_REG_TEST_PATTERN               0x0600
-+#define IMX219_TEST_PATTERN_DISABLE   0
-+#define IMX219_TEST_PATTERN_SOLID_COLOR       1
-+#define IMX219_TEST_PATTERN_COLOR_BARS        2
-+#define IMX219_TEST_PATTERN_GREY_COLOR        3
-+#define IMX219_TEST_PATTERN_PN9               4
-+
-+/* Test pattern colour components */
-+#define IMX219_REG_TESTP_RED          0x0602
-+#define IMX219_REG_TESTP_GREENR               0x0604
-+#define IMX219_REG_TESTP_BLUE         0x0606
-+#define IMX219_REG_TESTP_GREENB               0x0608
-+#define IMX219_TESTP_COLOUR_MIN               0
-+#define IMX219_TESTP_COLOUR_MAX               0x03ff
-+#define IMX219_TESTP_COLOUR_STEP      1
-+#define IMX219_TESTP_RED_DEFAULT      IMX219_TESTP_COLOUR_MAX
-+#define IMX219_TESTP_GREENR_DEFAULT   0
-+#define IMX219_TESTP_BLUE_DEFAULT     0
-+#define IMX219_TESTP_GREENB_DEFAULT   0
-+
-+/* IMX219 native and active pixel array size. */
-+#define IMX219_NATIVE_WIDTH           3296U
-+#define IMX219_NATIVE_HEIGHT          2480U
-+#define IMX219_PIXEL_ARRAY_LEFT               8U
-+#define IMX219_PIXEL_ARRAY_TOP                8U
-+#define IMX219_PIXEL_ARRAY_WIDTH      3280U
-+#define IMX219_PIXEL_ARRAY_HEIGHT     2464U
-+
-+struct imx219_reg {
-+      u16 address;
-+      u8 val;
-+};
-+
-+struct imx219_reg_list {
-+      unsigned int num_of_regs;
-+      const struct imx219_reg *regs;
-+};
-+
-+/* Mode : resolution and related config&values */
-+struct imx219_mode {
-+      /* Frame width */
-+      unsigned int width;
-+      /* Frame height */
-+      unsigned int height;
-+
-+      unsigned int fps;
-+
-+      /* Analog crop rectangle. */
-+      struct v4l2_rect crop;
-+
-+      /* V-timing */
-+      unsigned int vts_def;
-+
-+      /* Default register values */
-+      struct imx219_reg_list reg_list;
-+};
-+
-+/*
-+ * Register sets lifted off the i2C interface from the Raspberry Pi firmware
-+ * driver.
-+ * 3280x2464 = mode 2, 1920x1080 = mode 1, 1640x1232 = mode 4, 640x480 = mode 7.
-+ */
-+
-+static const struct imx219_reg mode_1920_1080_regs[] = {
-+      {0x0100, 0x00},
-+      {0x30eb, 0x05},
-+      {0x30eb, 0x0c},
-+      {0x300a, 0xff},
-+      {0x300b, 0xff},
-+      {0x30eb, 0x05},
-+      {0x30eb, 0x09},
-+      {0x0114, 0x01},
-+      {0x0128, 0x00},
-+      {0x012a, 0x18},
-+      {0x012b, 0x00},
-+      {0x0162, 0x0d},
-+      {0x0163, 0x78},
-+      {0x0164, 0x02},
-+      {0x0165, 0xa8},
-+      {0x0166, 0x0a},
-+      {0x0167, 0x27},
-+      {0x0168, 0x02},
-+      {0x0169, 0xb4},
-+      {0x016a, 0x06},
-+      {0x016b, 0xeb},
-+      {0x016c, 0x07},
-+      {0x016d, 0x80},
-+      {0x016e, 0x04},
-+      {0x016f, 0x38},
-+      {0x0170, 0x01},
-+      {0x0171, 0x01},
-+      {0x0174, 0x00},
-+      {0x0175, 0x00},
-+      {0x0301, 0x05},
-+      {0x0303, 0x01},
-+      {0x0304, 0x03},
-+      {0x0305, 0x03},
-+      {0x0306, 0x00},
-+      {0x0307, 0x39},
-+      {0x030b, 0x01},
-+      {0x030c, 0x00},
-+      {0x030d, 0x72},
-+      {0x0624, 0x07},
-+      {0x0625, 0x80},
-+      {0x0626, 0x04},
-+      {0x0627, 0x38},
-+      {0x455e, 0x00},
-+      {0x471e, 0x4b},
-+      {0x4767, 0x0f},
-+      {0x4750, 0x14},
-+      {0x4540, 0x00},
-+      {0x47b4, 0x14},
-+      {0x4713, 0x30},
-+      {0x478b, 0x10},
-+      {0x478f, 0x10},
-+      {0x4793, 0x10},
-+      {0x4797, 0x0e},
-+      {0x479b, 0x0e},
-+};
-+
-+static const struct imx219_reg mode_1280_720_regs[] = {
-+      {0x0100, 0x00},
-+      {0x30eb, 0x05},
-+      {0x30eb, 0x0c},
-+      {0x300a, 0xff},
-+      {0x300b, 0xff},
-+      {0x30eb, 0x05},
-+      {0x30eb, 0x09},
-+      {0x0114, 0x01},
-+      {0x0128, 0x00},
-+      {0x012a, 0x18},
-+      {0x012b, 0x00},
-+      {0x0162, 0x0d},
-+      {0x0163, 0x78},
-+      {0x0164, 0x01},
-+      {0x0165, 0x68},
-+      {0x0166, 0x0b},
-+      {0x0167, 0x67},
-+      {0x0168, 0x02},
-+      {0x0169, 0x00},
-+      {0x016a, 0x07},
-+      {0x016b, 0x9f},
-+      {0x016c, 0x05},
-+      {0x016d, 0x00},
-+      {0x016e, 0x02},
-+      {0x016f, 0xd0},
-+      {0x0170, 0x01},
-+      {0x0171, 0x01},
-+      {0x0174, 0x01},
-+      {0x0175, 0x01},
-+      {0x0301, 0x05},
-+      {0x0303, 0x01},
-+      {0x0304, 0x03},
-+      {0x0305, 0x03},
-+      {0x0306, 0x00},
-+      {0x0307, 0x39},
-+      {0x030b, 0x01},
-+      {0x030c, 0x00},
-+      {0x030d, 0x72},
-+      {0x0624, 0x06},
-+      {0x0625, 0x68},
-+      {0x0626, 0x04},
-+      {0x0627, 0xd0},
-+      {0x455e, 0x00},
-+      {0x471e, 0x4b},
-+      {0x4767, 0x0f},
-+      {0x4750, 0x14},
-+      {0x4540, 0x00},
-+      {0x47b4, 0x14},
-+      {0x4713, 0x30},
-+      {0x478b, 0x10},
-+      {0x478f, 0x10},
-+      {0x4793, 0x10},
-+      {0x4797, 0x0e},
-+      {0x479b, 0x0e},
-+};
-+
-+static const struct imx219_reg mode_640_480_regs[] = {
-+      {0x0100, 0x00},
-+      {0x30eb, 0x05},
-+      {0x30eb, 0x0c},
-+      {0x300a, 0xff},
-+      {0x300b, 0xff},
-+      {0x30eb, 0x05},
-+      {0x30eb, 0x09},
-+      {0x0114, 0x01},
-+      {0x0128, 0x00},
-+      {0x012a, 0x18},
-+      {0x012b, 0x00},
-+      {0x0162, 0x0d},
-+      {0x0163, 0x78},
-+      {0x0164, 0x03},
-+      {0x0165, 0xe8},
-+      {0x0166, 0x08},
-+      {0x0167, 0xe7},
-+      {0x0168, 0x02},
-+      {0x0169, 0xf0},
-+      {0x016a, 0x06},
-+      {0x016b, 0xaf},
-+      {0x016c, 0x02},
-+      {0x016d, 0x80},
-+      {0x016e, 0x01},
-+      {0x016f, 0xe0},
-+      {0x0170, 0x01},
-+      {0x0171, 0x01},
-+      {0x0174, 0x03},
-+      {0x0175, 0x03},
-+      {0x0301, 0x05},
-+      {0x0303, 0x01},
-+      {0x0304, 0x03},
-+      {0x0305, 0x03},
-+      {0x0306, 0x00},
-+      {0x0307, 0x39},
-+      {0x030b, 0x01},
-+      {0x030c, 0x00},
-+      {0x030d, 0x72},
-+      {0x0624, 0x06},
-+      {0x0625, 0x68},
-+      {0x0626, 0x04},
-+      {0x0627, 0xd0},
-+      {0x455e, 0x00},
-+      {0x471e, 0x4b},
-+      {0x4767, 0x0f},
-+      {0x4750, 0x14},
-+      {0x4540, 0x00},
-+      {0x47b4, 0x14},
-+      {0x4713, 0x30},
-+      {0x478b, 0x10},
-+      {0x478f, 0x10},
-+      {0x4793, 0x10},
-+      {0x4797, 0x0e},
-+      {0x479b, 0x0e},
-+};
-+
-+static const struct imx219_reg raw8_framefmt_regs[] = {
-+      {0x018c, 0x08},
-+      {0x018d, 0x08},
-+      {0x0309, 0x08},
-+};
-+
-+static const struct imx219_reg raw10_framefmt_regs[] = {
-+      {0x018c, 0x0a},
-+      {0x018d, 0x0a},
-+      {0x0309, 0x0a},
-+};
-+
-+static const s64 imx219_link_freq_menu[] = {
-+      IMX219_DEFAULT_LINK_FREQ,
-+};
-+
-+static const char * const imx219_test_pattern_menu[] = {
-+      "Disabled",
-+      "Color Bars",
-+      "Solid Color",
-+      "Grey Color Bars",
-+      "PN9"
-+};
-+
-+static const int imx219_test_pattern_val[] = {
-+      IMX219_TEST_PATTERN_DISABLE,
-+      IMX219_TEST_PATTERN_COLOR_BARS,
-+      IMX219_TEST_PATTERN_SOLID_COLOR,
-+      IMX219_TEST_PATTERN_GREY_COLOR,
-+      IMX219_TEST_PATTERN_PN9,
-+};
-+
-+/* regulator supplies */
-+static const char * const imx219_supply_name[] = {
-+      /* Supplies can be enabled in any order */
-+      "VANA",  /* Analog (2.8V) supply */
-+      "VDIG",  /* Digital Core (1.8V) supply */
-+      "VDDL",  /* IF (1.2V) supply */
-+};
-+
-+#define IMX219_NUM_SUPPLIES ARRAY_SIZE(imx219_supply_name)
-+
-+/*
-+ * The supported formats.
-+ * This table MUST contain 4 entries per format, to cover the various flip
-+ * combinations in the order
-+ * - no flip
-+ * - h flip
-+ * - v flip
-+ * - h&v flips
-+ */
-+static const u32 codes[] = {
-+      MEDIA_BUS_FMT_SRGGB10_1X10,
-+      MEDIA_BUS_FMT_SGRBG10_1X10,
-+      MEDIA_BUS_FMT_SGBRG10_1X10,
-+      MEDIA_BUS_FMT_SBGGR10_1X10,
-+
-+      MEDIA_BUS_FMT_SRGGB8_1X8,
-+      MEDIA_BUS_FMT_SGRBG8_1X8,
-+      MEDIA_BUS_FMT_SGBRG8_1X8,
-+      MEDIA_BUS_FMT_SBGGR8_1X8,
-+};
-+
-+/*
-+ * Initialisation delay between XCLR low->high and the moment when the sensor
-+ * can start capture (i.e. can leave software stanby) must be not less than:
-+ *   t4 + max(t5, t6 + <time to initialize the sensor register over I2C>)
-+ * where
-+ *   t4 is fixed, and is max 200uS,
-+ *   t5 is fixed, and is 6000uS,
-+ *   t6 depends on the sensor external clock, and is max 32000 clock periods.
-+ * As per sensor datasheet, the external clock must be from 6MHz to 27MHz.
-+ * So for any acceptable external clock t6 is always within the range of
-+ * 1185 to 5333 uS, and is always less than t5.
-+ * For this reason this is always safe to wait (t4 + t5) = 6200 uS, then
-+ * initialize the sensor over I2C, and then exit the software standby.
-+ *
-+ * This start-up time can be optimized a bit more, if we start the writes
-+ * over I2C after (t4+t6), but before (t4+t5) expires. But then sensor
-+ * initialization over I2C may complete before (t4+t5) expires, and we must
-+ * ensure that capture is not started before (t4+t5).
-+ *
-+ * This delay doesn't account for the power supply startup time. If needed,
-+ * this should be taken care of via the regulator framework. E.g. in the
-+ * case of DT for regulator-fixed one should define the startup-delay-us
-+ * property.
-+ */
-+#define IMX219_XCLR_MIN_DELAY_US      6200
-+#define IMX219_XCLR_DELAY_RANGE_US    1000
-+
-+/* Mode configs */
-+static const struct imx219_mode supported_modes[] = {
-+      {
-+              /* 1080P 30fps cropped */
-+              .width = 1920,
-+              .height = 1080,
-+              .fps = 30,
-+              .crop = {
-+                      .left = 688,
-+                      .top = 700,
-+                      .width = 1920,
-+                      .height = 1080
-+              },
-+              .vts_def = IMX219_VTS_30FPS_1080P,
-+              .reg_list = {
-+                      .num_of_regs = ARRAY_SIZE(mode_1920_1080_regs),
-+                      .regs = mode_1920_1080_regs,
-+              },
-+      },
-+      {
-+              /* 1280x720 30fps mode */
-+              .width = 1280,
-+              .height = 720,
-+              .fps = 30,
-+              .crop = {
-+                      .left = 360,
-+                      .top = 512,
-+                      .width = 2560,
-+                      .height = 1440
-+              },
-+              .vts_def = IMX219_VTS_30FPS_1280x720,
-+              .reg_list = {
-+                      .num_of_regs = ARRAY_SIZE(mode_1280_720_regs),
-+                      .regs = mode_1280_720_regs,
-+              },
-+      },
-+      {
-+              /* 640x480 30fps mode */
-+              .width = 640,
-+              .height = 480,
-+              .fps = 30,
-+              .crop = {
-+                      .left = 1008,
-+                      .top = 760,
-+                      .width = 1280,
-+                      .height = 960
-+              },
-+              .vts_def = IMX219_VTS_30FPS_640x480,
-+              .reg_list = {
-+                      .num_of_regs = ARRAY_SIZE(mode_640_480_regs),
-+                      .regs = mode_640_480_regs,
-+              },
-+      },
-+};
-+
-+struct imx219 {
-+      struct v4l2_subdev sd;
-+      struct media_pad pad;
-+      //struct v4l2_fwnode_endpoint ep; /* the parsed DT endpoint info */
-+
-+      struct v4l2_mbus_framefmt fmt;
-+
-+      struct clk *xclk; /* system clock to IMX219 */
-+      u32 xclk_freq;
-+
-+      struct gpio_desc *reset_gpio;
-+      struct regulator_bulk_data supplies[IMX219_NUM_SUPPLIES];
-+
-+      struct v4l2_ctrl_handler ctrl_handler;
-+      /* V4L2 Controls */
-+      struct v4l2_ctrl *pixel_rate;
-+      struct v4l2_ctrl *link_freq;
-+      struct v4l2_ctrl *exposure;
-+      struct v4l2_ctrl *vflip;
-+      struct v4l2_ctrl *hflip;
-+      struct v4l2_ctrl *vblank;
-+      struct v4l2_ctrl *hblank;
-+
-+      /* Current mode */
-+      const struct imx219_mode *mode;
-+      struct v4l2_fract frame_interval;
-+
-+      /*
-+       * Mutex for serialized access:
-+       * Protect sensor module set pad format and start/stop streaming safely.
-+       */
-+      struct mutex mutex;
-+
-+      /* Streaming on/off */
-+      int streaming;
-+};
-+
-+static inline struct imx219 *to_imx219(struct v4l2_subdev *_sd)
-+{
-+      return container_of(_sd, struct imx219, sd);
-+}
-+
-+/* Read registers up to 2 at a time */
-+static int imx219_read_reg(struct imx219 *imx219, u16 reg, u32 len, u32 *val)
-+{
-+      struct i2c_client *client = v4l2_get_subdevdata(&imx219->sd);
-+      struct i2c_msg msgs[2];
-+      u8 addr_buf[2] = { reg >> 8, reg & 0xff };
-+      u8 data_buf[4] = { 0, };
-+      int ret;
-+
-+      if (len > 4)
-+              return -EINVAL;
-+
-+      /* Write register address */
-+      msgs[0].addr = client->addr;
-+      msgs[0].flags = 0;
-+      msgs[0].len = ARRAY_SIZE(addr_buf);
-+      msgs[0].buf = addr_buf;
-+
-+      /* Read data from register */
-+      msgs[1].addr = client->addr;
-+      msgs[1].flags = I2C_M_RD;
-+      msgs[1].len = len;
-+      msgs[1].buf = &data_buf[4 - len];
-+
-+      ret = i2c_transfer(client->adapter, msgs, ARRAY_SIZE(msgs));
-+      if (ret != ARRAY_SIZE(msgs))
-+              return -EIO;
-+
-+      *val = get_unaligned_be32(data_buf);
-+
-+      return 0;
-+}
-+
-+/* Write registers up to 2 at a time */
-+static int imx219_write_reg(struct imx219 *imx219, u16 reg, u32 len, u32 val)
-+{
-+      struct i2c_client *client = v4l2_get_subdevdata(&imx219->sd);
-+      u8 buf[6];
-+
-+      if (len > 4)
-+              return -EINVAL;
-+
-+      put_unaligned_be16(reg, buf);
-+      put_unaligned_be32(val << (8 * (4 - len)), buf + 2);
-+      if (i2c_master_send(client, buf, len + 2) != len + 2)
-+              return -EIO;
-+
-+      return 0;
-+}
-+
-+/* Write a list of registers */
-+static int imx219_write_regs(struct imx219 *imx219,
-+                           const struct imx219_reg *regs, u32 len)
-+{
-+      struct i2c_client *client = v4l2_get_subdevdata(&imx219->sd);
-+      unsigned int i;
-+      int ret;
-+
-+      for (i = 0; i < len; i++) {
-+              ret = imx219_write_reg(imx219, regs[i].address, 1, regs[i].val);
-+              if (ret) {
-+                      dev_err_ratelimited(&client->dev,
-+                                          "Failed to write reg 0x%4.4x. error = %d\n",
-+                                          regs[i].address, ret);
-+
-+                      return ret;
-+              }
-+      }
-+
-+      return 0;
-+}
-+
-+/* Get bayer order based on flip setting. */
-+static u32 imx219_get_format_code(struct imx219 *imx219, u32 code)
-+{
-+      unsigned int i;
-+
-+      lockdep_assert_held(&imx219->mutex);
-+
-+      for (i = 0; i < ARRAY_SIZE(codes); i++)
-+              if (codes[i] == code)
-+                      break;
-+
-+      if (i >= ARRAY_SIZE(codes))
-+              i = 0;
-+
-+      i = (i & ~3) | (imx219->vflip->val ? 2 : 0) |
-+          (imx219->hflip->val ? 1 : 0);
-+
-+      return codes[i];
-+}
-+
-+static void imx219_set_default_format(struct imx219 *imx219)
-+{
-+      struct v4l2_mbus_framefmt *fmt;
-+
-+      fmt = &imx219->fmt;
-+      fmt->code = MEDIA_BUS_FMT_SRGGB10_1X10;
-+      fmt->colorspace = V4L2_COLORSPACE_SRGB;
-+      fmt->ycbcr_enc = V4L2_MAP_YCBCR_ENC_DEFAULT(fmt->colorspace);
-+      fmt->quantization = V4L2_MAP_QUANTIZATION_DEFAULT(true,
-+              fmt->colorspace, fmt->ycbcr_enc);
-+      fmt->xfer_func = V4L2_MAP_XFER_FUNC_DEFAULT(fmt->colorspace);
-+      fmt->width = supported_modes[0].width;
-+      fmt->height = supported_modes[0].height;
-+      fmt->field = V4L2_FIELD_NONE;
-+}
-+
-+static int imx219_open(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh)
-+{
-+      struct imx219 *imx219 = to_imx219(sd);
-+      struct v4l2_mbus_framefmt *try_fmt =
-+              v4l2_subdev_get_try_format(sd, fh->state, 0);
-+      struct v4l2_rect *try_crop;
-+
-+      mutex_lock(&imx219->mutex);
-+
-+      /* Initialize try_fmt */
-+      try_fmt->width = supported_modes[0].width;
-+      try_fmt->height = supported_modes[0].height;
-+      try_fmt->code = imx219_get_format_code(imx219, MEDIA_BUS_FMT_SRGGB10_1X10);
-+      try_fmt->field = V4L2_FIELD_NONE;
-+
-+      /* Initialize try_crop rectangle. */
-+      try_crop = v4l2_subdev_get_try_crop(sd, fh->state, 0);
-+      try_crop->top = IMX219_PIXEL_ARRAY_TOP;
-+      try_crop->left = IMX219_PIXEL_ARRAY_LEFT;
-+      try_crop->width = IMX219_PIXEL_ARRAY_WIDTH;
-+      try_crop->height = IMX219_PIXEL_ARRAY_HEIGHT;
-+
-+      mutex_unlock(&imx219->mutex);
-+
-+      return 0;
-+}
-+
-+static int imx219_set_ctrl(struct v4l2_ctrl *ctrl)
-+{
-+      struct imx219 *imx219 =
-+              container_of(ctrl->handler, struct imx219, ctrl_handler);
-+      struct i2c_client *client = v4l2_get_subdevdata(&imx219->sd);
-+      int ret;
-+
-+      if (ctrl->id == V4L2_CID_VBLANK) {
-+              int exposure_max, exposure_def;
-+
-+              /* Update max exposure while meeting expected vblanking */
-+              exposure_max = imx219->mode->height + ctrl->val - 4;
-+              exposure_def = (exposure_max < IMX219_EXPOSURE_DEFAULT) ?
-+                      exposure_max : IMX219_EXPOSURE_DEFAULT;
-+              __v4l2_ctrl_modify_range(imx219->exposure, imx219->exposure->minimum,
-+                              exposure_max, imx219->exposure->step, exposure_def);
-+      }
-+
-+      /*
-+       * Applying V4L2 control value only happens
-+       * when power is up for streaming
-+       */
-+      if (pm_runtime_get_if_in_use(&client->dev) == 0)
-+              return 0;
-+
-+      switch (ctrl->id) {
-+      case V4L2_CID_ANALOGUE_GAIN:
-+              ret = imx219_write_reg(imx219, IMX219_REG_ANALOG_GAIN,
-+                              IMX219_REG_VALUE_08BIT, ctrl->val);
-+              break;
-+      case V4L2_CID_EXPOSURE:
-+              ret = imx219_write_reg(imx219, IMX219_REG_EXPOSURE,
-+                              IMX219_REG_VALUE_16BIT, ctrl->val);
-+              break;
-+      case V4L2_CID_DIGITAL_GAIN:
-+              ret = imx219_write_reg(imx219, IMX219_REG_DIGITAL_GAIN,
-+                              IMX219_REG_VALUE_16BIT, ctrl->val);
-+              break;
-+      case V4L2_CID_TEST_PATTERN:
-+              ret = imx219_write_reg(imx219, IMX219_REG_TEST_PATTERN,
-+                              IMX219_REG_VALUE_16BIT, imx219_test_pattern_val[ctrl->val]);
-+              break;
-+      case V4L2_CID_HFLIP:
-+      case V4L2_CID_VFLIP:
-+              ret = imx219_write_reg(imx219, IMX219_REG_ORIENTATION, 1,
-+                      imx219->hflip->val | imx219->vflip->val << 1);
-+              break;
-+      case V4L2_CID_VBLANK:
-+              ret = imx219_write_reg(imx219, IMX219_REG_VTS, IMX219_REG_VALUE_16BIT,
-+                              imx219->mode->height + ctrl->val);
-+              break;
-+      case V4L2_CID_TEST_PATTERN_RED:
-+              ret = imx219_write_reg(imx219, IMX219_REG_TESTP_RED,
-+                              IMX219_REG_VALUE_16BIT, ctrl->val);
-+              break;
-+      case V4L2_CID_TEST_PATTERN_GREENR:
-+              ret = imx219_write_reg(imx219, IMX219_REG_TESTP_GREENR,
-+                              IMX219_REG_VALUE_16BIT, ctrl->val);
-+              break;
-+      case V4L2_CID_TEST_PATTERN_BLUE:
-+              ret = imx219_write_reg(imx219, IMX219_REG_TESTP_BLUE,
-+                              IMX219_REG_VALUE_16BIT, ctrl->val);
-+              break;
-+      case V4L2_CID_TEST_PATTERN_GREENB:
-+              ret = imx219_write_reg(imx219, IMX219_REG_TESTP_GREENB,
-+                              IMX219_REG_VALUE_16BIT, ctrl->val);
-+              break;
-+      default:
-+              dev_info(&client->dev,
-+                       "ctrl(id:0x%x,val:0x%x) is not handled\n", ctrl->id, ctrl->val);
-+              ret = -EINVAL;
-+              break;
-+      }
-+
-+      pm_runtime_put(&client->dev);
-+
-+      return ret;
-+}
-+
-+static const struct v4l2_ctrl_ops imx219_ctrl_ops = {
-+      .s_ctrl = imx219_set_ctrl,
-+};
-+
-+static int imx219_enum_mbus_code(struct v4l2_subdev *sd,
-+                               struct v4l2_subdev_state *state,
-+                               struct v4l2_subdev_mbus_code_enum *code)
-+{
-+      struct imx219 *imx219 = to_imx219(sd);
-+
-+      if (code->index >= (ARRAY_SIZE(codes) / 4))
-+              return -EINVAL;
-+
-+      mutex_lock(&imx219->mutex);
-+      code->code = imx219_get_format_code(imx219, codes[code->index * 4]);
-+      mutex_unlock(&imx219->mutex);
-+
-+      return 0;
-+}
-+
-+static int imx219_enum_frame_size(struct v4l2_subdev *sd,
-+                                struct v4l2_subdev_state *state,
-+                                struct v4l2_subdev_frame_size_enum *fse)
-+{
-+      struct imx219 *imx219 = to_imx219(sd);
-+      u32 code;
-+
-+      if (fse->index >= ARRAY_SIZE(supported_modes))
-+              return -EINVAL;
-+
-+      mutex_lock(&imx219->mutex);
-+      code = imx219_get_format_code(imx219, fse->code);
-+      mutex_unlock(&imx219->mutex);
-+      if (fse->code != code)
-+              return -EINVAL;
-+
-+      fse->min_width = supported_modes[fse->index].width;
-+      fse->max_width = fse->min_width;
-+      fse->min_height = supported_modes[fse->index].height;
-+      fse->max_height = fse->min_height;
-+
-+      return 0;
-+}
-+
-+static int imx219_try_frame_interval(struct imx219 *imx219,
-+                                   struct v4l2_fract *fi,
-+                                   u32 w, u32 h)
-+{
-+      const struct imx219_mode *mode;
-+
-+      mode = v4l2_find_nearest_size(supported_modes, ARRAY_SIZE(supported_modes),
-+                      width, height, w, h);
-+      if (!mode || (mode->width != w || mode->height != h))
-+              return -EINVAL;
-+
-+      fi->numerator = 1;
-+      fi->denominator = mode->fps;
-+
-+      return mode->fps;
-+}
-+
-+static int imx219_enum_frame_interval(struct v4l2_subdev *sd,
-+                      struct v4l2_subdev_state *state,
-+                      struct v4l2_subdev_frame_interval_enum *fie)
-+{
-+      struct imx219 *imx219 = to_imx219(sd);
-+      struct v4l2_fract tpf;
-+      u32 code;
-+      int ret;
-+
-+      if (fie->index >= ARRAY_SIZE(supported_modes))
-+              return -EINVAL;
-+
-+      mutex_lock(&imx219->mutex);
-+      code = imx219_get_format_code(imx219, fie->code);
-+      if (fie->code != code) {
-+              ret = -EINVAL;
-+              goto out;
-+      }
-+
-+      ret = imx219_try_frame_interval(imx219, &tpf,
-+                              fie->width, fie->height);
-+      if (ret < 0) {
-+              ret = -EINVAL;
-+              goto out;
-+      }
-+
-+      mutex_unlock(&imx219->mutex);
-+      fie->interval = tpf;
-+
-+      return 0;
-+
-+out:
-+      mutex_unlock(&imx219->mutex);
-+      return ret;
-+}
-+
-+static int imx219_g_frame_interval(struct v4l2_subdev *sd,
-+                                 struct v4l2_subdev_frame_interval *fi)
-+{
-+      struct imx219 *imx219 = to_imx219(sd);
-+
-+      mutex_lock(&imx219->mutex);
-+      fi->interval = imx219->frame_interval;
-+      mutex_unlock(&imx219->mutex);
-+
-+      return 0;
-+}
-+
-+static int imx219_s_frame_interval(struct v4l2_subdev *sd,
-+                                 struct v4l2_subdev_frame_interval *fi)
-+{
-+      struct imx219 *imx219 = to_imx219(sd);
-+      const struct imx219_mode *mode = imx219->mode;
-+      int frame_rate, ret = 0;
-+
-+      if (fi->pad != 0)
-+              return -EINVAL;
-+
-+      mutex_lock(&imx219->mutex);
-+
-+      if (imx219->streaming) {
-+              ret = -EBUSY;
-+              goto out;
-+      }
-+
-+      frame_rate = imx219_try_frame_interval(imx219, &fi->interval,
-+                                             mode->width, mode->height);
-+      if (frame_rate < 0) {
-+              ret = -EINVAL;
-+              goto out;
-+      }
-+
-+      imx219->frame_interval = fi->interval;
-+
-+out:
-+      mutex_unlock(&imx219->mutex);
-+      return ret;
-+}
-+
-+static void imx219_reset_colorspace(struct v4l2_mbus_framefmt *fmt)
-+{
-+      fmt->colorspace = V4L2_COLORSPACE_SRGB;
-+      fmt->ycbcr_enc = V4L2_MAP_YCBCR_ENC_DEFAULT(fmt->colorspace);
-+      fmt->quantization = V4L2_MAP_QUANTIZATION_DEFAULT(true,
-+                      fmt->colorspace, fmt->ycbcr_enc);
-+      fmt->xfer_func = V4L2_MAP_XFER_FUNC_DEFAULT(fmt->colorspace);
-+}
-+
-+static void imx219_update_pad_format(struct imx219 *imx219,
-+                                   const struct imx219_mode *mode,
-+                                   struct v4l2_subdev_format *fmt)
-+{
-+      fmt->format.width = mode->width;
-+      fmt->format.height = mode->height;
-+      fmt->format.field = V4L2_FIELD_NONE;
-+      imx219_reset_colorspace(&fmt->format);
-+}
-+
-+static int __imx219_get_pad_format(struct imx219 *imx219,
-+                                 struct v4l2_subdev_state *state,
-+                                 struct v4l2_subdev_format *fmt)
-+{
-+      if (fmt->which == V4L2_SUBDEV_FORMAT_TRY) {
-+              struct v4l2_mbus_framefmt *try_fmt =
-+                      v4l2_subdev_get_try_format(&imx219->sd, state, fmt->pad);
-+              /* update the code which could change due to vflip or hflip: */
-+              try_fmt->code = imx219_get_format_code(imx219, try_fmt->code);
-+              fmt->format = *try_fmt;
-+      } else {
-+              imx219_update_pad_format(imx219, imx219->mode, fmt);
-+              fmt->format.code = imx219_get_format_code(imx219, imx219->fmt.code);
-+      }
-+
-+      return 0;
-+}
-+
-+static int imx219_get_pad_format(struct v4l2_subdev *sd,
-+                               struct v4l2_subdev_state *state,
-+                               struct v4l2_subdev_format *fmt)
-+{
-+      struct imx219 *imx219 = to_imx219(sd);
-+      int ret;
-+
-+      mutex_lock(&imx219->mutex);
-+      ret = __imx219_get_pad_format(imx219, state, fmt);
-+      mutex_unlock(&imx219->mutex);
-+
-+      return ret;
-+}
-+
-+static int imx219_set_pad_format(struct v4l2_subdev *sd,
-+                              struct v4l2_subdev_state *state,
-+                              struct v4l2_subdev_format *fmt)
-+{
-+      struct imx219 *imx219 = to_imx219(sd);
-+      const struct imx219_mode *mode;
-+      struct v4l2_mbus_framefmt *framefmt;
-+      int exposure_max, exposure_def, hblank;
-+      unsigned int i;
-+
-+      mutex_lock(&imx219->mutex);
-+
-+      for (i = 0; i < ARRAY_SIZE(codes); i++)
-+              if (codes[i] == fmt->format.code)
-+                      break;
-+      if (i >= ARRAY_SIZE(codes))
-+              i = 0;
-+
-+      /* Bayer order varies with flips */
-+      fmt->format.code = imx219_get_format_code(imx219, codes[i]);
-+
-+      mode = v4l2_find_nearest_size(supported_modes, ARRAY_SIZE(supported_modes),
-+                      width, height, fmt->format.width, fmt->format.height);
-+      imx219_update_pad_format(imx219, mode, fmt);
-+      if (fmt->which == V4L2_SUBDEV_FORMAT_TRY) {
-+              framefmt = v4l2_subdev_get_try_format(sd, state, fmt->pad);
-+              *framefmt = fmt->format;
-+      } else if (imx219->mode != mode ||
-+                 imx219->fmt.code != fmt->format.code) {
-+              imx219->fmt = fmt->format;
-+              imx219->mode = mode;
-+              /* Update limits and set FPS to default */
-+              __v4l2_ctrl_modify_range(imx219->vblank, IMX219_VBLANK_MIN,
-+                              IMX219_VTS_MAX - mode->height, 1,
-+                              mode->vts_def - mode->height);
-+              __v4l2_ctrl_s_ctrl(imx219->vblank, mode->vts_def - mode->height);
-+              /* Update max exposure while meeting expected vblanking */
-+              exposure_max = mode->vts_def - 4;
-+              exposure_def = (exposure_max < IMX219_EXPOSURE_DEFAULT) ?
-+                      exposure_max : IMX219_EXPOSURE_DEFAULT;
-+              __v4l2_ctrl_modify_range(imx219->exposure, imx219->exposure->minimum,
-+                              exposure_max, imx219->exposure->step, exposure_def);
-+              /*
-+               * Currently PPL is fixed to IMX219_PPL_DEFAULT, so hblank
-+               * depends on mode->width only, and is not changeble in any
-+               * way other than changing the mode.
-+               */
-+              hblank = IMX219_PPL_DEFAULT - mode->width;
-+              __v4l2_ctrl_modify_range(imx219->hblank, hblank, hblank, 1, hblank);
-+      }
-+
-+      mutex_unlock(&imx219->mutex);
-+
-+      return 0;
-+}
-+
-+static int imx219_set_framefmt(struct imx219 *imx219)
-+{
-+      switch (imx219->fmt.code) {
-+      case MEDIA_BUS_FMT_SRGGB8_1X8:
-+      case MEDIA_BUS_FMT_SGRBG8_1X8:
-+      case MEDIA_BUS_FMT_SGBRG8_1X8:
-+      case MEDIA_BUS_FMT_SBGGR8_1X8:
-+              return imx219_write_regs(imx219, raw8_framefmt_regs,
-+                              ARRAY_SIZE(raw8_framefmt_regs));
-+
-+      case MEDIA_BUS_FMT_SRGGB10_1X10:
-+      case MEDIA_BUS_FMT_SGRBG10_1X10:
-+      case MEDIA_BUS_FMT_SGBRG10_1X10:
-+      case MEDIA_BUS_FMT_SBGGR10_1X10:
-+              return imx219_write_regs(imx219, raw10_framefmt_regs,
-+                              ARRAY_SIZE(raw10_framefmt_regs));
-+      }
-+
-+      return -EINVAL;
-+}
-+
-+static const struct v4l2_rect *
-+__imx219_get_pad_crop(struct imx219 *imx219, struct v4l2_subdev_state *state,
-+                              unsigned int pad, enum v4l2_subdev_format_whence which)
-+{
-+      switch (which) {
-+      case V4L2_SUBDEV_FORMAT_TRY:
-+              return v4l2_subdev_get_try_crop(&imx219->sd, state, pad);
-+      case V4L2_SUBDEV_FORMAT_ACTIVE:
-+              return &imx219->mode->crop;
-+      }
-+
-+      return NULL;
-+}
-+
-+static int imx219_get_selection(struct v4l2_subdev *sd,
-+                                      struct v4l2_subdev_state *state,
-+                                      struct v4l2_subdev_selection *sel)
-+{
-+      switch (sel->target) {
-+      case V4L2_SEL_TGT_CROP: {
-+              struct imx219 *imx219 = to_imx219(sd);
-+
-+              mutex_lock(&imx219->mutex);
-+              sel->r = *__imx219_get_pad_crop(imx219, state, sel->pad, sel->which);
-+              mutex_unlock(&imx219->mutex);
-+              return 0;
-+      }
-+
-+      case V4L2_SEL_TGT_NATIVE_SIZE:
-+              sel->r.top = 0;
-+              sel->r.left = 0;
-+              sel->r.width = IMX219_NATIVE_WIDTH;
-+              sel->r.height = IMX219_NATIVE_HEIGHT;
-+              return 0;
-+
-+      case V4L2_SEL_TGT_CROP_DEFAULT:
-+      case V4L2_SEL_TGT_CROP_BOUNDS:
-+              sel->r.top = IMX219_PIXEL_ARRAY_TOP;
-+              sel->r.left = IMX219_PIXEL_ARRAY_LEFT;
-+              sel->r.width = IMX219_PIXEL_ARRAY_WIDTH;
-+              sel->r.height = IMX219_PIXEL_ARRAY_HEIGHT;
-+              return 0;
-+      }
-+
-+      return -EINVAL;
-+}
-+
-+static int imx219_start_streaming(struct imx219 *imx219)
-+{
-+      struct i2c_client *client = v4l2_get_subdevdata(&imx219->sd);
-+      const struct imx219_reg_list *reg_list;
-+      int ret;
-+
-+      /* Apply default values of current mode */
-+      reg_list = &imx219->mode->reg_list;
-+      ret = imx219_write_regs(imx219, reg_list->regs, reg_list->num_of_regs);
-+      if (ret) {
-+              dev_err(&client->dev, "%s failed to set mode\n", __func__);
-+              goto err;
-+      }
-+
-+      ret = imx219_set_framefmt(imx219);
-+      if (ret) {
-+              dev_err(&client->dev, "%s failed to set frame format: %d\n",
-+                      __func__, ret);
-+              goto err;
-+      }
-+
-+      /* Apply customized values from user */
-+      ret =  __v4l2_ctrl_handler_setup(imx219->sd.ctrl_handler);
-+      if (ret)
-+              goto err;
-+
-+      /* set stream on register */
-+      ret = imx219_write_reg(imx219, IMX219_REG_MODE_SELECT,
-+                             IMX219_REG_VALUE_08BIT, IMX219_MODE_STREAMING);
-+      if (ret)
-+              goto err;
-+
-+      /* vflip and hflip cannot change during streaming */
-+      __v4l2_ctrl_grab(imx219->vflip, true);
-+      __v4l2_ctrl_grab(imx219->hflip, true);
-+
-+      return 0;
-+
-+err:
-+      return ret;
-+}
-+
-+static void imx219_stop_streaming(struct imx219 *imx219)
-+{
-+      struct i2c_client *client = v4l2_get_subdevdata(&imx219->sd);
-+      int ret;
-+
-+      /* set stream off register */
-+      ret = imx219_write_reg(imx219, IMX219_REG_MODE_SELECT,
-+                      IMX219_REG_VALUE_08BIT, IMX219_MODE_STANDBY);
-+      if (ret)
-+              dev_err(&client->dev, "%s failed to set stream\n", __func__);
-+
-+      __v4l2_ctrl_grab(imx219->vflip, false);
-+      __v4l2_ctrl_grab(imx219->hflip, false);
-+}
-+
-+static int imx219_set_stream(struct v4l2_subdev *sd, int enable)
-+{
-+      struct imx219 *imx219 = to_imx219(sd);
-+      struct i2c_client *client = v4l2_get_subdevdata(sd);
-+      int ret = 0;
-+
-+      mutex_lock(&imx219->mutex);
-+
-+      if (enable) {
-+              ret = pm_runtime_get_sync(&client->dev);
-+              if (ret < 0) {
-+                      pm_runtime_put_noidle(&client->dev);
-+                      mutex_unlock(&imx219->mutex);
-+                      return ret;
-+              }
-+
-+              if (imx219->streaming)
-+                      goto unlock;
-+
-+              /*
-+               * Apply default & customized values
-+               * and then start streaming.
-+               */
-+              ret = imx219_start_streaming(imx219);
-+              if (ret)
-+                      goto err_unlock;
-+      } else {
-+              imx219_stop_streaming(imx219);
-+              pm_runtime_put(&client->dev);
-+      }
-+
-+unlock:
-+      imx219->streaming += enable ? 1 : -1;
-+      WARN_ON(imx219->streaming < 0);
-+
-+      mutex_unlock(&imx219->mutex);
-+
-+      return ret;
-+
-+err_unlock:
-+      pm_runtime_put(&client->dev);
-+      mutex_unlock(&imx219->mutex);
-+
-+      return ret;
-+}
-+
-+/* Power/clock management functions */
-+static int imx219_power_on(struct device *dev)
-+{
-+      struct v4l2_subdev *sd = dev_get_drvdata(dev);
-+      struct imx219 *imx219 = to_imx219(sd);
-+      int ret;
-+
-+      ret = regulator_bulk_enable(IMX219_NUM_SUPPLIES, imx219->supplies);
-+      if (ret) {
-+              dev_err(dev, "%s: failed to enable regulators\n",
-+                      __func__);
-+              return ret;
-+      }
-+
-+      ret = clk_prepare_enable(imx219->xclk);
-+      if (ret) {
-+              dev_err(dev, "%s: failed to enable clock\n", __func__);
-+              goto reg_off;
-+      }
-+
-+      gpiod_set_value_cansleep(imx219->reset_gpio, 1);
-+      usleep_range(IMX219_XCLR_MIN_DELAY_US,
-+                      IMX219_XCLR_MIN_DELAY_US + IMX219_XCLR_DELAY_RANGE_US);
-+
-+      return 0;
-+
-+reg_off:
-+      regulator_bulk_disable(IMX219_NUM_SUPPLIES, imx219->supplies);
-+
-+      return ret;
-+}
-+
-+static int imx219_power_off(struct device *dev)
-+{
-+      struct v4l2_subdev *sd = dev_get_drvdata(dev);
-+      struct imx219 *imx219 = to_imx219(sd);
-+
-+      gpiod_set_value_cansleep(imx219->reset_gpio, 0);
-+      regulator_bulk_disable(IMX219_NUM_SUPPLIES, imx219->supplies);
-+      clk_disable_unprepare(imx219->xclk);
-+
-+      return 0;
-+}
-+
-+static int imx219_get_regulators(struct imx219 *imx219)
-+{
-+      struct i2c_client *client = v4l2_get_subdevdata(&imx219->sd);
-+      unsigned int i;
-+
-+      for (i = 0; i < IMX219_NUM_SUPPLIES; i++)
-+              imx219->supplies[i].supply = imx219_supply_name[i];
-+
-+      return devm_regulator_bulk_get(&client->dev,
-+                      IMX219_NUM_SUPPLIES, imx219->supplies);
-+}
-+
-+/* Verify chip ID */
-+static int imx219_identify_module(struct imx219 *imx219)
-+{
-+      struct i2c_client *client = v4l2_get_subdevdata(&imx219->sd);
-+      int ret;
-+      u32 val;
-+
-+      ret = imx219_read_reg(imx219, IMX219_REG_CHIP_ID,
-+                            IMX219_REG_VALUE_16BIT, &val);
-+      if (ret) {
-+              dev_err(&client->dev, "failed to read chip id %x\n",
-+                      IMX219_CHIP_ID);
-+              return ret;
-+      }
-+
-+      if (val != IMX219_CHIP_ID) {
-+              dev_err(&client->dev, "chip id mismatch: %x!=%x\n",
-+                      IMX219_CHIP_ID, val);
-+              return -EIO;
-+      }
-+
-+      dev_err(&client->dev, "%s: chip identifier, got 0x%x\n",
-+              __func__, IMX219_CHIP_ID);
-+
-+      return 0;
-+}
-+
-+static const struct v4l2_subdev_core_ops imx219_core_ops = {
-+      .subscribe_event = v4l2_ctrl_subdev_subscribe_event,
-+      .unsubscribe_event = v4l2_event_subdev_unsubscribe,
-+};
-+
-+static const struct v4l2_subdev_video_ops imx219_video_ops = {
-+      .g_frame_interval = imx219_g_frame_interval,
-+      .s_frame_interval = imx219_s_frame_interval,
-+      .s_stream = imx219_set_stream,
-+};
-+
-+static const struct v4l2_subdev_pad_ops imx219_pad_ops = {
-+      .enum_mbus_code = imx219_enum_mbus_code,
-+      .get_fmt = imx219_get_pad_format,
-+      .set_fmt = imx219_set_pad_format,
-+      .get_selection = imx219_get_selection,
-+      .enum_frame_size = imx219_enum_frame_size,
-+      .enum_frame_interval = imx219_enum_frame_interval,
-+};
-+
-+static const struct v4l2_subdev_ops imx219_subdev_ops = {
-+      .core = &imx219_core_ops,
-+      .video = &imx219_video_ops,
-+      .pad = &imx219_pad_ops,
-+};
-+
-+static const struct v4l2_subdev_internal_ops imx219_internal_ops = {
-+      .open = imx219_open,
-+};
-+
-+/* Initialize control handlers */
-+static int imx219_init_controls(struct imx219 *imx219)
-+{
-+      struct i2c_client *client = v4l2_get_subdevdata(&imx219->sd);
-+      struct v4l2_ctrl_handler *ctrl_hdlr;
-+      unsigned int height = imx219->mode->height;
-+      struct v4l2_fwnode_device_properties props;
-+      int exposure_max, exposure_def, hblank;
-+      int i, ret;
-+
-+      ctrl_hdlr = &imx219->ctrl_handler;
-+      ret = v4l2_ctrl_handler_init(ctrl_hdlr, 12);
-+      if (ret)
-+              return ret;
-+
-+      mutex_init(&imx219->mutex);
-+      ctrl_hdlr->lock = &imx219->mutex;
-+
-+      /* By default, PIXEL_RATE is read only */
-+      imx219->pixel_rate = v4l2_ctrl_new_std(ctrl_hdlr, &imx219_ctrl_ops,
-+                      V4L2_CID_PIXEL_RATE, IMX219_PIXEL_RATE,
-+                      IMX219_PIXEL_RATE, 1, IMX219_PIXEL_RATE);
-+
-+      imx219->link_freq =
-+              v4l2_ctrl_new_int_menu(ctrl_hdlr, &imx219_ctrl_ops, V4L2_CID_LINK_FREQ,
-+                      ARRAY_SIZE(imx219_link_freq_menu) - 1, 0, imx219_link_freq_menu);
-+      if (imx219->link_freq)
-+              imx219->link_freq->flags |= V4L2_CTRL_FLAG_READ_ONLY;
-+
-+      /* Initial vblank/hblank/exposure parameters based on current mode */
-+      imx219->vblank = v4l2_ctrl_new_std(ctrl_hdlr, &imx219_ctrl_ops,
-+                                      V4L2_CID_VBLANK, IMX219_VBLANK_MIN,
-+                                      IMX219_VTS_MAX - height, 1,
-+                                      imx219->mode->vts_def - height);
-+      hblank = IMX219_PPL_DEFAULT - imx219->mode->width;
-+      imx219->hblank = v4l2_ctrl_new_std(ctrl_hdlr, &imx219_ctrl_ops,
-+                                      V4L2_CID_HBLANK, hblank, hblank, 1, hblank);
-+      if (imx219->hblank)
-+              imx219->hblank->flags |= V4L2_CTRL_FLAG_READ_ONLY;
-+      exposure_max = imx219->mode->vts_def - 4;
-+      exposure_def = (exposure_max < IMX219_EXPOSURE_DEFAULT) ?
-+              exposure_max : IMX219_EXPOSURE_DEFAULT;
-+      imx219->exposure = v4l2_ctrl_new_std(ctrl_hdlr, &imx219_ctrl_ops,
-+                              V4L2_CID_EXPOSURE, IMX219_EXPOSURE_MIN, exposure_max,
-+                              IMX219_EXPOSURE_STEP, exposure_def);
-+
-+      v4l2_ctrl_new_std(ctrl_hdlr, &imx219_ctrl_ops, V4L2_CID_ANALOGUE_GAIN,
-+                      IMX219_ANA_GAIN_MIN, IMX219_ANA_GAIN_MAX,
-+                      IMX219_ANA_GAIN_STEP, IMX219_ANA_GAIN_DEFAULT);
-+
-+      v4l2_ctrl_new_std(ctrl_hdlr, &imx219_ctrl_ops, V4L2_CID_DIGITAL_GAIN,
-+                      IMX219_DGTL_GAIN_MIN, IMX219_DGTL_GAIN_MAX,
-+                      IMX219_DGTL_GAIN_STEP, IMX219_DGTL_GAIN_DEFAULT);
-+
-+      imx219->hflip = v4l2_ctrl_new_std(ctrl_hdlr, &imx219_ctrl_ops,
-+                                        V4L2_CID_HFLIP, 0, 1, 1, 0);
-+      if (imx219->hflip)
-+              imx219->hflip->flags |= V4L2_CTRL_FLAG_MODIFY_LAYOUT;
-+
-+      imx219->vflip = v4l2_ctrl_new_std(ctrl_hdlr, &imx219_ctrl_ops,
-+                                        V4L2_CID_VFLIP, 0, 1, 1, 0);
-+      if (imx219->vflip)
-+              imx219->vflip->flags |= V4L2_CTRL_FLAG_MODIFY_LAYOUT;
-+
-+      v4l2_ctrl_new_std_menu_items(ctrl_hdlr, &imx219_ctrl_ops, V4L2_CID_TEST_PATTERN,
-+                      ARRAY_SIZE(imx219_test_pattern_menu) - 1,
-+                      0, 0, imx219_test_pattern_menu);
-+      for (i = 0; i < 4; i++) {
-+              /*
-+               * The assumption is that
-+               * V4L2_CID_TEST_PATTERN_GREENR == V4L2_CID_TEST_PATTERN_RED + 1
-+               * V4L2_CID_TEST_PATTERN_BLUE   == V4L2_CID_TEST_PATTERN_RED + 2
-+               * V4L2_CID_TEST_PATTERN_GREENB == V4L2_CID_TEST_PATTERN_RED + 3
-+               */
-+              v4l2_ctrl_new_std(ctrl_hdlr, &imx219_ctrl_ops,
-+                              V4L2_CID_TEST_PATTERN_RED + i,
-+                              IMX219_TESTP_COLOUR_MIN,
-+                              IMX219_TESTP_COLOUR_MAX,
-+                              IMX219_TESTP_COLOUR_STEP,
-+                              IMX219_TESTP_COLOUR_MAX);
-+              /* The "Solid color" pattern is white by default */
-+      }
-+
-+      if (ctrl_hdlr->error) {
-+              ret = ctrl_hdlr->error;
-+              dev_err(&client->dev, "%s control init failed (%d)\n",
-+                      __func__, ret);
-+              goto error;
-+      }
-+
-+      ret = v4l2_fwnode_device_parse(&client->dev, &props);
-+      if (ret)
-+              goto error;
-+
-+      ret = v4l2_ctrl_new_fwnode_properties(ctrl_hdlr, &imx219_ctrl_ops, &props);
-+      if (ret)
-+              goto error;
-+
-+      imx219->sd.ctrl_handler = ctrl_hdlr;
-+
-+      return 0;
-+
-+error:
-+      v4l2_ctrl_handler_free(ctrl_hdlr);
-+      mutex_destroy(&imx219->mutex);
-+
-+      return ret;
-+}
-+
-+static void imx219_free_controls(struct imx219 *imx219)
-+{
-+      v4l2_ctrl_handler_free(imx219->sd.ctrl_handler);
-+      mutex_destroy(&imx219->mutex);
-+}
-+
-+static int imx219_check_hwcfg(struct device *dev)
-+{
-+      struct fwnode_handle *endpoint;
-+      struct v4l2_fwnode_endpoint ep_cfg = {
-+              .bus_type = V4L2_MBUS_CSI2_DPHY
-+      };
-+      int ret = -EINVAL;
-+
-+      endpoint = fwnode_graph_get_next_endpoint(dev_fwnode(dev), NULL);
-+      if (!endpoint) {
-+              dev_err(dev, "endpoint node not found\n");
-+              return -EINVAL;
-+      }
-+
-+      if (v4l2_fwnode_endpoint_alloc_parse(endpoint, &ep_cfg)) {
-+              dev_err(dev, "could not parse endpoint\n");
-+              goto error_out;
-+      }
-+
-+      /* Check the number of MIPI CSI2 data lanes */
-+      if (ep_cfg.bus.mipi_csi2.num_data_lanes != 2) {
-+              dev_err(dev, "only 2 data lanes are currently supported\n");
-+              goto error_out;
-+      }
-+
-+      /* Check the link frequency set in device tree */
-+      if (!ep_cfg.nr_of_link_frequencies) {
-+              dev_err(dev, "link-frequency property not found in DT\n");
-+              goto error_out;
-+      }
-+
-+      if (ep_cfg.nr_of_link_frequencies != 1 ||
-+          ep_cfg.link_frequencies[0] != IMX219_DEFAULT_LINK_FREQ) {
-+              dev_err(dev, "Link frequency not supported: %lld\n",
-+                      ep_cfg.link_frequencies[0]);
-+              goto error_out;
-+      }
-+
-+      ret = 0;
-+
-+error_out:
-+      v4l2_fwnode_endpoint_free(&ep_cfg);
-+      fwnode_handle_put(endpoint);
-+
-+      return ret;
-+}
-+
-+static int imx219_probe(struct i2c_client *client)
-+{
-+      struct device *dev = &client->dev;
-+      struct imx219 *imx219;
-+      int ret;
-+
-+      imx219 = devm_kzalloc(&client->dev, sizeof(*imx219), GFP_KERNEL);
-+      if (!imx219)
-+              return -ENOMEM;
-+
-+      v4l2_i2c_subdev_init(&imx219->sd, client, &imx219_subdev_ops);
-+
-+      /* Check the hardware configuration in device tree */
-+      if (imx219_check_hwcfg(dev))
-+              return -EINVAL;
-+
-+      /* Get system clock (xclk) */
-+      imx219->xclk = devm_clk_get(dev, NULL);
-+      if (IS_ERR(imx219->xclk)) {
-+              dev_err(dev, "failed to get xclk\n");
-+              return PTR_ERR(imx219->xclk);
-+      }
-+
-+      imx219->xclk_freq = clk_get_rate(imx219->xclk);
-+      if (imx219->xclk_freq != IMX219_XCLK_FREQ) {
-+              dev_err(dev, "xclk frequency not supported: %d Hz\n",
-+                      imx219->xclk_freq);
-+              return -EINVAL;
-+      }
-+
-+      ret = imx219_get_regulators(imx219);
-+      if (ret) {
-+              dev_err(dev, "failed to get regulators\n");
-+              return ret;
-+      }
-+
-+      /* Request optional enable pin */
-+      imx219->reset_gpio = devm_gpiod_get_optional(dev, "reset", GPIOD_OUT_LOW);
-+      usleep_range(IMX219_XCLR_MIN_DELAY_US,
-+                      IMX219_XCLR_MIN_DELAY_US + IMX219_XCLR_DELAY_RANGE_US);
-+
-+      /*
-+       * The sensor must be powered for imx219_identify_module()
-+       * to be able to read the CHIP_ID register
-+       */
-+      ret = imx219_power_on(dev);
-+      if (ret)
-+              return ret;
-+
-+      ret = imx219_identify_module(imx219);
-+      if (ret)
-+              goto error_power_off;
-+
-+      /* Set default mode to max resolution */
-+      imx219->mode = &supported_modes[0];
-+      imx219->frame_interval.numerator = 1;
-+      imx219->frame_interval.denominator = supported_modes[0].fps;
-+
-+      /* sensor doesn't enter LP-11 state upon power up until and unless
-+       * streaming is started, so upon power up switch the modes to:
-+       * streaming -> standby
-+       */
-+      ret = imx219_write_reg(imx219, IMX219_REG_MODE_SELECT,
-+                      IMX219_REG_VALUE_08BIT, IMX219_MODE_STREAMING);
-+      if (ret < 0)
-+              goto error_power_off;
-+      usleep_range(100, 110);
-+
-+      /* put sensor back to standby mode */
-+      ret = imx219_write_reg(imx219, IMX219_REG_MODE_SELECT,
-+                      IMX219_REG_VALUE_08BIT, IMX219_MODE_STANDBY);
-+      if (ret < 0)
-+              goto error_power_off;
-+      usleep_range(100, 110);
-+
-+      ret = imx219_init_controls(imx219);
-+      if (ret)
-+              goto error_power_off;
-+
-+      /* Initialize subdev */
-+      imx219->sd.internal_ops = &imx219_internal_ops;
-+      imx219->sd.flags |= V4L2_SUBDEV_FL_HAS_DEVNODE | V4L2_SUBDEV_FL_HAS_EVENTS;
-+      imx219->sd.entity.function = MEDIA_ENT_F_CAM_SENSOR;
-+
-+      /* Initialize source pad */
-+      imx219->pad.flags = MEDIA_PAD_FL_SOURCE;
-+
-+      /* Initialize default format */
-+      imx219_set_default_format(imx219);
-+
-+      ret = media_entity_pads_init(&imx219->sd.entity, 1, &imx219->pad);
-+      if (ret) {
-+              dev_err(dev, "failed to init entity pads: %d\n", ret);
-+              goto error_handler_free;
-+      }
-+
-+      ret = v4l2_async_register_subdev_sensor(&imx219->sd);
-+      if (ret < 0) {
-+              dev_err(dev, "failed to register sensor sub-device: %d\n", ret);
-+              goto error_media_entity;
-+      }
-+
-+      /* Enable runtime PM and turn off the device */
-+      pm_runtime_set_active(dev);
-+      pm_runtime_enable(dev);
-+      pm_runtime_idle(dev);
-+
-+      return 0;
-+
-+error_media_entity:
-+      media_entity_cleanup(&imx219->sd.entity);
-+
-+error_handler_free:
-+      imx219_free_controls(imx219);
-+
-+error_power_off:
-+      imx219_power_off(dev);
-+
-+      return ret;
-+}
-+
-+static void imx219_remove(struct i2c_client *client)
-+{
-+      struct v4l2_subdev *sd = i2c_get_clientdata(client);
-+      struct imx219 *imx219 = to_imx219(sd);
-+
-+      v4l2_async_unregister_subdev(sd);
-+      media_entity_cleanup(&sd->entity);
-+      imx219_free_controls(imx219);
-+
-+      pm_runtime_disable(&client->dev);
-+      if (!pm_runtime_status_suspended(&client->dev))
-+              imx219_power_off(&client->dev);
-+      pm_runtime_set_suspended(&client->dev);
-+}
-+
-+static const struct of_device_id imx219_dt_ids[] = {
-+      { .compatible = "sony,imx219" },
-+      { /* sentinel */ }
-+};
-+MODULE_DEVICE_TABLE(of, imx219_dt_ids);
-+
-+static const struct dev_pm_ops imx219_pm_ops = {
-+      SET_SYSTEM_SLEEP_PM_OPS(pm_runtime_force_suspend, pm_runtime_force_resume)
-+      SET_RUNTIME_PM_OPS(imx219_power_off, imx219_power_on, NULL)
-+};
-+
-+static struct i2c_driver imx219_i2c_driver = {
-+      .driver = {
-+              .name = "imx219",
-+              .of_match_table = imx219_dt_ids,
-+              .pm = &imx219_pm_ops,
-+      },
-+      .probe = imx219_probe,
-+      .remove = imx219_remove,
-+};
-+
-+module_i2c_driver(imx219_i2c_driver);
-+
-+MODULE_AUTHOR("Dave Stevenson <dave.stevenson@raspberrypi.com");
-+MODULE_DESCRIPTION("Sony IMX219 sensor driver");
-+MODULE_LICENSE("GPL v2");
---- /dev/null
-+++ b/drivers/media/platform/starfive/v4l2_driver/ov13850_mipi.c
-@@ -0,0 +1,1921 @@
-+// SPDX-License-Identifier: GPL-2.0-or-later
-+/*
-+ * Copyright (C) 2021-2023 StarFive Technology Co., Ltd.
-+ *
-+ */
-+
-+#include <linux/clk.h>
-+#include <linux/clk-provider.h>
-+#include <linux/clkdev.h>
-+#include <linux/ctype.h>
-+#include <linux/delay.h>
-+#include <linux/device.h>
-+#include <linux/gpio/consumer.h>
-+#include <linux/i2c.h>
-+#include <linux/init.h>
-+#include <linux/module.h>
-+#include <linux/of_device.h>
-+#include <linux/regulator/consumer.h>
-+#include <linux/slab.h>
-+#include <linux/types.h>
-+#include <media/v4l2-async.h>
-+#include <media/v4l2-ctrls.h>
-+#include <media/v4l2-device.h>
-+#include <media/v4l2-event.h>
-+#include <media/v4l2-fwnode.h>
-+#include <media/v4l2-subdev.h>
-+#include "stfcamss.h"
-+
-+#define OV13850_XCLK_MIN  6000000
-+#define OV13850_XCLK_MAX 54000000
-+
-+#define OV13850_LINK_FREQ_500MHZ         500000000LL
-+
-+/**
-+ *OV13850 PLL
-+ *
-+ *PLL1:
-+ *
-+ *REF_CLK -> /PREDIVP[0] -> /PREDIV[2:0] -> *DIVP[9:8,7:0] -> /DIVM[3:0] -> /DIV_MIPI[1:0]  -> PCLK
-+ *(6-64M)     0x030A         0x0300          0x0301,0x302      0x0303        0x0304
-+ *                                                                      `-> MIPI_PHY_CLK
-+ *
-+ *
-+ *PLL2:
-+ *                           000: 1
-+ *                           001: 1.5
-+ *                           010: 2
-+ *                           011: 2.5
-+ *                           100: 3
-+ *                           101: 4
-+ *            0: /1          110: 6
-+ *            1: /2          111: 8
-+ *REF_CLK -> /PREDIVP[3] -> /PREDIV[2:0] -> /DIVP[9:0] -> /DIVDAC[3:0] -> DAC_CLK =
-+ *(6~64M)    0x3611
-+ *                                                     -> /DIVSP[3:0] -> /DIVS[2:0] -> SCLK
-+ *
-+ *                                                     -> /(1+DIVSRAM[3:0]) -> SRAM_CLK
-+ */
-+
-+// PREDIVP
-+#define OV13850_REG_PLL1_PREDIVP        0x030a
-+#define OV13850_PREDIVP_1   0
-+#define OV13850_PREDIVP_2   1
-+
-+// PREDIV
-+#define OV13850_REG_PLL1_PREDIV         0x0300
-+#define OV13850_PREDIV_1    0
-+#define OV13850_PREDIV_1_5  1
-+#define OV13850_PREDIV_2    2
-+#define OV13850_PREDIV_2_5  3
-+#define OV13850_PREDIV_3    4
-+#define OV13850_PREDIV_4    5
-+#define OV13850_PREDIV_6    6
-+#define OV13850_PREDIV_8    7
-+
-+// DIVP
-+#define OV13850_REG_PLL1_DIVP_H         0x0301
-+#define OV13850_REG_PLL1_DIVP_L         0x0302
-+#define OV13850_REG_PLL1_DIVP           OV13850_REG_PLL1_DIVP_H
-+
-+// DIVM
-+#define OV13850_REG_PLL1_DIVM           0x0303
-+#define OV13850_DIVM(n)     ((n)-1) // n=1~16
-+
-+// DIV_MIPI
-+#define OV13850_REG_PLL1_DIV_MIPI       0x0304
-+#define OV13850_DIV_MIPI_4  0
-+#define OV13850_DIV_MIPI_5  1
-+#define OV13850_DIV_MIPI_6  2
-+#define OV13850_DIV_MIPI_8  3
-+
-+// system control
-+#define OV13850_STREAM_CTRL             0x0100
-+#define OV13850_REG_MIPI_SC             0x300f
-+#define OV13850_MIPI_SC_8_BIT           0x0
-+#define OV13850_MIPI_SC_10_BIT          0x1
-+#define OV13850_MIPI_SC_12_BIT          0x2
-+#define OV13850_GET_MIPI_SC_MIPI_BIT(v)         ((v) & 0x3)
-+#define OV13850_REG_MIPI_SC_CTRL0       0x3012
-+#define OV13850_GET_MIPI_SC_CTRL0_LANE_NUM(v)   ((v)>>4 & 0xf)
-+
-+// timing
-+#define OV13850_REG_H_CROP_START_H      0x3800
-+#define OV13850_REG_H_CROP_START_L      0x3801
-+#define OV13850_REG_H_CROP_START        OV13850_REG_H_CROP_START_H
-+#define OV13850_REG_V_CROP_START_H      0x3802
-+#define OV13850_REG_V_CROP_START_L      0x3803
-+#define OV13850_REG_V_CROP_START        OV13850_REG_V_CROP_START_H
-+
-+#define OV13850_REG_H_CROP_END_H        0x3804
-+#define OV13850_REG_H_CROP_END_L        0x3805
-+#define OV13850_REG_H_CROP_END          OV13850_REG_H_CROP_END_H
-+#define OV13850_REG_V_CROP_END_H        0x3806
-+#define OV13850_REG_V_CROP_END_L        0x3807
-+#define OV13850_REG_V_CROP_END          OV13850_REG_V_CROP_END_H
-+
-+#define OV13850_REG_H_OUTPUT_SIZE_H     0x3808
-+#define OV13850_REG_H_OUTPUT_SIZE_L     0x3809
-+#define OV13850_REG_H_OUTPUT_SIZE       OV13850_REG_H_OUTPUT_SIZE_H
-+#define OV13850_REG_V_OUTPUT_SIZE_H     0x380a
-+#define OV13850_REG_V_OUTPUT_SIZE_L     0x380b
-+#define OV13850_REG_V_OUTPUT_SIZE       OV13850_REG_V_OUTPUT_SIZE_H
-+
-+#define OV13850_REG_TIMING_HTS_H        0x380c
-+#define OV13850_REG_TIMING_HTS_L        0x380d
-+#define OV13850_REG_TIMING_HTS          OV13850_REG_TIMING_HTS_H
-+#define OV13850_REG_TIMING_VTS_H        0x380e
-+#define OV13850_REG_TIMING_VTS_L        0x380f
-+#define OV13850_REG_TIMING_VTS          OV13850_REG_TIMING_VTS_H
-+
-+
-+#define OV13850_REG_H_WIN_OFF_H         0x3810
-+#define OV13850_REG_H_WIN_OFF_L         0x3811
-+#define OV13850_REG_V_WIN_OFF_H         0x3812
-+#define OV13850_REG_V_WIN_OFF_L         0x3813
-+
-+#define OV13850_REG_H_INC               0x3814
-+#define OV13850_REG_V_INC               0x3815
-+
-+enum ov13850_mode_id {
-+      OV13850_MODE_1080P_1920_1080 = 0,
-+      OV13850_NUM_MODES,
-+};
-+
-+enum ov13850_frame_rate {
-+      OV13850_15_FPS = 0,
-+      OV13850_30_FPS,
-+      OV13850_60_FPS,
-+      OV13850_NUM_FRAMERATES,
-+};
-+
-+static const int ov13850_framerates[] = {
-+      [OV13850_15_FPS] = 15,
-+      [OV13850_30_FPS] = 30,
-+      [OV13850_60_FPS] = 60,
-+};
-+
-+struct ov13850_pixfmt {
-+      u32 code;
-+      u32 colorspace;
-+};
-+
-+static const struct ov13850_pixfmt ov13850_formats[] = {
-+      { MEDIA_BUS_FMT_SBGGR10_1X10, V4L2_COLORSPACE_SRGB, },
-+      { MEDIA_BUS_FMT_SGBRG10_1X10, V4L2_COLORSPACE_SRGB, },
-+      { MEDIA_BUS_FMT_SGRBG10_1X10, V4L2_COLORSPACE_SRGB, },
-+      { MEDIA_BUS_FMT_SRGGB10_1X10, V4L2_COLORSPACE_SRGB, },
-+};
-+
-+/* regulator supplies */
-+static const char * const ov13850_supply_name[] = {
-+      "DOVDD", /* Digital I/O (1.8V) supply */
-+      "AVDD",  /* Analog (2.8V) supply */
-+      "DVDD",  /* Digital Core (1.5V) supply */
-+};
-+
-+#define OV13850_NUM_SUPPLIES ARRAY_SIZE(ov13850_supply_name)
-+
-+/*
-+ * Image size under 1280 * 960 are SUBSAMPLING
-+ * Image size upper 1280 * 960 are SCALING
-+ */
-+enum ov13850_downsize_mode {
-+      SUBSAMPLING,
-+      SCALING,
-+};
-+
-+struct reg_value {
-+      u16 reg_addr;
-+      u8 val;
-+      u8 mask;
-+      u32 delay_ms;
-+};
-+
-+struct ov13850_mode_info {
-+      enum ov13850_mode_id id;
-+      enum ov13850_downsize_mode dn_mode;
-+      u32 hact;
-+      u32 htot;
-+      u32 vact;
-+      u32 vtot;
-+      const struct reg_value *reg_data;
-+      u32 reg_data_size;
-+      u32 max_fps;
-+};
-+
-+struct ov13850_ctrls {
-+      struct v4l2_ctrl_handler handler;
-+      struct v4l2_ctrl *pixel_rate;
-+      struct {
-+              struct v4l2_ctrl *exposure;
-+      };
-+      struct {
-+              struct v4l2_ctrl *auto_wb;
-+              struct v4l2_ctrl *blue_balance;
-+              struct v4l2_ctrl *red_balance;
-+      };
-+      struct {
-+              struct v4l2_ctrl *anal_gain;
-+      };
-+      struct v4l2_ctrl *brightness;
-+      struct v4l2_ctrl *light_freq;
-+      struct v4l2_ctrl *link_freq;
-+      struct v4l2_ctrl *saturation;
-+      struct v4l2_ctrl *contrast;
-+      struct v4l2_ctrl *hue;
-+      struct v4l2_ctrl *test_pattern;
-+      struct v4l2_ctrl *hflip;
-+      struct v4l2_ctrl *vflip;
-+};
-+
-+struct ov13850_dev {
-+      struct i2c_client *i2c_client;
-+      struct v4l2_subdev sd;
-+      struct media_pad pad;
-+      struct v4l2_fwnode_endpoint ep; /* the parsed DT endpoint info */
-+      struct clk *xclk; /* system clock to OV13850 */
-+      u32 xclk_freq;
-+
-+      struct regulator_bulk_data supplies[OV13850_NUM_SUPPLIES];
-+      struct gpio_desc *reset_gpio;
-+      struct gpio_desc *pwdn_gpio;
-+      bool   upside_down;
-+
-+      /* lock to protect all members below */
-+      struct mutex lock;
-+
-+      int power_count;
-+
-+      struct v4l2_mbus_framefmt fmt;
-+      bool pending_fmt_change;
-+
-+      const struct ov13850_mode_info *current_mode;
-+      const struct ov13850_mode_info *last_mode;
-+      enum ov13850_frame_rate current_fr;
-+      struct v4l2_fract frame_interval;
-+
-+      struct ov13850_ctrls ctrls;
-+
-+      u32 prev_sysclk, prev_hts;
-+      u32 ae_low, ae_high, ae_target;
-+
-+      bool pending_mode_change;
-+      bool streaming;
-+};
-+
-+static inline struct ov13850_dev *to_ov13850_dev(struct v4l2_subdev *sd)
-+{
-+      return container_of(sd, struct ov13850_dev, sd);
-+}
-+
-+static inline struct v4l2_subdev *ctrl_to_sd(struct v4l2_ctrl *ctrl)
-+{
-+      return &container_of(ctrl->handler, struct ov13850_dev,
-+                      ctrls.handler)->sd;
-+}
-+
-+/* ov13850 initial register */
-+static const struct reg_value ov13850_init_setting_30fps_1080P[] = {
-+
-+};
-+
-+static const struct reg_value ov13850_setting_1080P_1920_1080[] = {
-+//;XVCLK=24Mhz, SCLK=4x120Mhz, MIPI 640Mbps, DACCLK=240Mhz
-+/*
-+ * using quarter size to scale down
-+ */
-+      {0x0103, 0x01, 0, 0}, // ; software reset
-+
-+      {0x0300, 0x01, 0, 0}, //; PLL
-+      {0x0301, 0x00, 0, 0}, //; PLL1_DIVP_hi
-+      {0x0302, 0x28, 0, 0}, //; PLL1_DIVP_lo
-+      {0x0303, 0x00, 0, 0}, // ; PLL
-+      {0x030a, 0x00, 0, 0}, // ; PLL
-+      //{0xffff, 20, 0, 0},
-+      {0x300f, 0x11, 0, 0}, // SFC modified, MIPI_SRC, [1:0] 00-8bit, 01-10bit, 10-12bit
-+      {0x3010, 0x01, 0, 0}, // ; MIPI PHY
-+      {0x3011, 0x76, 0, 0}, // ; MIPI PHY
-+      {0x3012, 0x41, 0, 0}, // ; MIPI 4 lane
-+      {0x3013, 0x12, 0, 0}, // ; MIPI control
-+      {0x3014, 0x11, 0, 0}, // ; MIPI control
-+      {0x301f, 0x03, 0, 0}, //
-+      {0x3106, 0x00, 0, 0}, //
-+      {0x3210, 0x47, 0, 0}, //
-+      {0x3500, 0x00, 0, 0}, // ; exposure HH
-+      {0x3501, 0x67, 0, 0}, // ; exposure H
-+      {0x3502, 0x80, 0, 0}, // ; exposure L
-+      {0x3506, 0x00, 0, 0}, // ; short exposure HH
-+      {0x3507, 0x02, 0, 0}, // ; short exposure H
-+      {0x3508, 0x00, 0, 0}, // ; shour exposure L
-+      {0x3509, 0x10, 0, 0},//00},//8},
-+      {0x350a, 0x00, 0, 0}, // ; gain H
-+      {0x350b, 0x10, 0, 0}, // ; gain L
-+      {0x350e, 0x00, 0, 0}, // ; short gain H
-+      {0x350f, 0x10, 0, 0}, // ; short gain L
-+      {0x3600, 0x40, 0, 0}, // ; analog control
-+      {0x3601, 0xfc, 0, 0}, // ; analog control
-+      {0x3602, 0x02, 0, 0}, // ; analog control
-+      {0x3603, 0x48, 0, 0}, // ; analog control
-+      {0x3604, 0xa5, 0, 0}, // ; analog control
-+      {0x3605, 0x9f, 0, 0}, // ; analog control
-+      {0x3607, 0x00, 0, 0}, // ; analog control
-+      {0x360a, 0x40, 0, 0}, // ; analog control
-+      {0x360b, 0x91, 0, 0}, // ; analog control
-+      {0x360c, 0x49, 0, 0}, // ; analog control
-+      {0x360f, 0x8a, 0, 0}, //
-+      {0x3611, 0x10, 0, 0}, // ; PLL2
-+      //{0x3612, 0x23, 0, 0}, // ; PLL2
-+      {0x3612, 0x13, 0, 0}, // ; PLL2
-+      //{0x3613, 0x33, 0, 0}, // ; PLL2
-+      {0x3613, 0x22, 0, 0}, // ; PLL2
-+      //{0xffff, 50, 0, 0},
-+      {0x3614, 0x28, 0, 0}, //[7:0] PLL2_DIVP lo
-+      {0x3615, 0x08, 0, 0}, //[7:6] Debug mode, [5:4] N_pump clock div, [3:2] P_pump clock div, [1:0] PLL2_DIVP hi
-+      {0x3641, 0x02, 0, 0},
-+      {0x3660, 0x82, 0, 0},
-+      {0x3668, 0x54, 0, 0},
-+      {0x3669, 0x40, 0, 0},
-+      {0x3667, 0xa0, 0, 0},
-+      {0x3702, 0x40, 0, 0},
-+      {0x3703, 0x44, 0, 0},
-+      {0x3704, 0x2c, 0, 0},
-+      {0x3705, 0x24, 0, 0},
-+      {0x3706, 0x50, 0, 0},
-+      {0x3707, 0x44, 0, 0},
-+      {0x3708, 0x3c, 0, 0},
-+      {0x3709, 0x1f, 0, 0},
-+      {0x370a, 0x26, 0, 0},
-+      {0x370b, 0x3c, 0, 0},
-+      {0x3720, 0x66, 0, 0},
-+      {0x3722, 0x84, 0, 0},
-+      {0x3728, 0x40, 0, 0},
-+      {0x372a, 0x00, 0, 0},
-+      {0x372f, 0x90, 0, 0},
-+      {0x3710, 0x28, 0, 0},
-+      {0x3716, 0x03, 0, 0},
-+      {0x3718, 0x10, 0, 0},
-+      {0x3719, 0x08, 0, 0},
-+      {0x371c, 0xfc, 0, 0},
-+      {0x3760, 0x13, 0, 0},
-+      {0x3761, 0x34, 0, 0},
-+      {0x3767, 0x24, 0, 0},
-+      {0x3768, 0x06, 0, 0},
-+      {0x3769, 0x45, 0, 0},
-+      {0x376c, 0x23, 0, 0},
-+      {0x3d84, 0x00, 0, 0}, // ; OTP program disable
-+      {0x3d85, 0x17, 0, 0}, // ; OTP power up load data enable, power load setting enable, software load setting
-+      {0x3d8c, 0x73, 0, 0}, // ; OTP start address H
-+      {0x3d8d, 0xbf, 0, 0}, // ; OTP start address L
-+      {0x3800, 0x00, 0, 0}, // ; H crop start H
-+      {0x3801, 0x08, 0, 0}, // ; H crop start L
-+      {0x3802, 0x00, 0, 0}, // ; V crop start H
-+      {0x3803, 0x04, 0, 0}, // ; V crop start L
-+      {0x3804, 0x10, 0, 0}, // ; H crop end H
-+      {0x3805, 0x97, 0, 0}, // ; H crop end L
-+      {0x3806, 0x0c, 0, 0}, // ; V crop end H
-+      {0x3807, 0x4b, 0, 0}, // ; V crop end L
-+      {0x3808, 0x08, 0, 0}, // ; H output size H
-+      {0x3809, 0x40, 0, 0}, // ; H output size L
-+      {0x380a, 0x06, 0, 0}, // ; V output size H
-+      {0x380b, 0x20, 0, 0}, // ; V output size L
-+      {0x380c, 0x25, 0, 0}, // ; HTS H
-+      {0x380d, 0x80, 0, 0}, // ; HTS L
-+      {0x380e, 0x06, 0, 0}, // ; VTS H
-+      {0x380f, 0x80, 0, 0}, // ; VTS L
-+      {0x3810, 0x00, 0, 0}, // ; H win off H
-+      {0x3811, 0x04, 0, 0}, // ; H win off L
-+      {0x3812, 0x00, 0, 0}, // ; V win off H
-+      {0x3813, 0x02, 0, 0}, // ; V win off L
-+      {0x3814, 0x31, 0, 0}, // ; H inc
-+      {0x3815, 0x31, 0, 0}, // ; V inc
-+      {0x3820, 0x02, 0, 0}, // ; V flip off, V bin on
-+      {0x3821, 0x05, 0, 0}, // ; H mirror on, H bin on
-+      {0x3834, 0x00, 0, 0}, //
-+      {0x3835, 0x1c, 0, 0}, // ; cut_en, vts_auto, blk_col_dis
-+      {0x3836, 0x08, 0, 0}, //
-+      {0x3837, 0x02, 0, 0}, //
-+      {0x4000, 0xf1, 0, 0},//c1}, // ; BLC offset trig en, format change trig en, gain trig en, exp trig en, median en
-+      {0x4001, 0x00, 0, 0}, // ; BLC
-+      {0x400b, 0x0c, 0, 0}, // ; BLC
-+      {0x4011, 0x00, 0, 0}, // ; BLC
-+      {0x401a, 0x00, 0, 0}, // ; BLC
-+      {0x401b, 0x00, 0, 0}, // ; BLC
-+      {0x401c, 0x00, 0, 0}, // ; BLC
-+      {0x401d, 0x00, 0, 0}, // ; BLC
-+      {0x4020, 0x00, 0, 0}, // ; BLC
-+      {0x4021, 0xe4, 0, 0}, // ; BLC
-+      {0x4022, 0x07, 0, 0}, // ; BLC
-+      {0x4023, 0x5f, 0, 0}, // ; BLC
-+      {0x4024, 0x08, 0, 0}, // ; BLC
-+      {0x4025, 0x44, 0, 0}, // ; BLC
-+      {0x4026, 0x08, 0, 0}, // ; BLC
-+      {0x4027, 0x47, 0, 0}, // ; BLC
-+      {0x4028, 0x00, 0, 0}, // ; BLC
-+      {0x4029, 0x02, 0, 0}, // ; BLC
-+      {0x402a, 0x04, 0, 0}, // ; BLC
-+      {0x402b, 0x08, 0, 0}, // ; BLC
-+      {0x402c, 0x02, 0, 0}, // ; BLC
-+      {0x402d, 0x02, 0, 0}, // ; BLC
-+      {0x402e, 0x0c, 0, 0}, // ; BLC
-+      {0x402f, 0x08, 0, 0}, // ; BLC
-+      {0x403d, 0x2c, 0, 0}, //
-+      {0x403f, 0x7f, 0, 0}, //
-+      {0x4500, 0x82, 0, 0}, // ; BLC
-+      {0x4501, 0x38, 0, 0}, // ; BLC
-+      {0x4601, 0x04, 0, 0}, //
-+      {0x4602, 0x22, 0, 0}, //
-+      {0x4603, 0x01, 0, 0}, //; VFIFO
-+      {0x4837, 0x19, 0, 0}, //; MIPI global timing
-+      {0x4d00, 0x04, 0, 0}, // ; temperature monitor
-+      {0x4d01, 0x42, 0, 0}, //  ; temperature monitor
-+      {0x4d02, 0xd1, 0, 0}, //  ; temperature monitor
-+      {0x4d03, 0x90, 0, 0}, //  ; temperature monitor
-+      {0x4d04, 0x66, 0, 0}, //  ; temperature monitor
-+      {0x4d05, 0x65, 0, 0}, // ; temperature monitor
-+      {0x5000, 0x0e, 0, 0}, // ; windowing enable, BPC on, WPC on, Lenc on
-+      {0x5001, 0x03, 0, 0}, // ; BLC enable, MWB on
-+      {0x5002, 0x07, 0, 0}, //
-+      {0x5013, 0x40, 0, 0},
-+      {0x501c, 0x00, 0, 0},
-+      {0x501d, 0x10, 0, 0},
-+      //{0x5057, 0x56, 0, 0},//add
-+      {0x5056, 0x08, 0, 0},
-+      {0x5058, 0x08, 0, 0},
-+      {0x505a, 0x08, 0, 0},
-+      {0x5242, 0x00, 0, 0},
-+      {0x5243, 0xb8, 0, 0},
-+      {0x5244, 0x00, 0, 0},
-+      {0x5245, 0xf9, 0, 0},
-+      {0x5246, 0x00, 0, 0},
-+      {0x5247, 0xf6, 0, 0},
-+      {0x5248, 0x00, 0, 0},
-+      {0x5249, 0xa6, 0, 0},
-+      {0x5300, 0xfc, 0, 0},
-+      {0x5301, 0xdf, 0, 0},
-+      {0x5302, 0x3f, 0, 0},
-+      {0x5303, 0x08, 0, 0},
-+      {0x5304, 0x0c, 0, 0},
-+      {0x5305, 0x10, 0, 0},
-+      {0x5306, 0x20, 0, 0},
-+      {0x5307, 0x40, 0, 0},
-+      {0x5308, 0x08, 0, 0},
-+      {0x5309, 0x08, 0, 0},
-+      {0x530a, 0x02, 0, 0},
-+      {0x530b, 0x01, 0, 0},
-+      {0x530c, 0x01, 0, 0},
-+      {0x530d, 0x0c, 0, 0},
-+      {0x530e, 0x02, 0, 0},
-+      {0x530f, 0x01, 0, 0},
-+      {0x5310, 0x01, 0, 0},
-+      {0x5400, 0x00, 0, 0},
-+      {0x5401, 0x61, 0, 0},
-+      {0x5402, 0x00, 0, 0},
-+      {0x5403, 0x00, 0, 0},
-+      {0x5404, 0x00, 0, 0},
-+      {0x5405, 0x40, 0, 0},
-+      {0x540c, 0x05, 0, 0},
-+      {0x5b00, 0x00, 0, 0},
-+      {0x5b01, 0x00, 0, 0},
-+      {0x5b02, 0x01, 0, 0},
-+      {0x5b03, 0xff, 0, 0},
-+      {0x5b04, 0x02, 0, 0},
-+      {0x5b05, 0x6c, 0, 0},
-+      {0x5b09, 0x02, 0, 0}, //
-+      //{0x5e00, 0x00, 0, 0}, // ; test pattern disable
-+      //{0x5e00, 0x80, 0, 0}, // ; test pattern enable
-+      {0x5e10, 0x1c, 0, 0}, // ; ISP test disable
-+
-+      //{0x0300, 0x01, 0, 0},// ; PLL
-+      //{0x0302, 0x28, 0, 0},// ; PLL
-+      //{0xffff,  50, 0, 0},
-+      {0x3501, 0x67, 0, 0},// ; Exposure H
-+      {0x370a, 0x26, 0, 0},//
-+      {0x372a, 0x00, 0, 0},
-+      {0x372f, 0x90, 0, 0},
-+      {0x3801, 0x08, 0, 0}, //; H crop start L
-+      {0x3803, 0x04, 0, 0}, //; V crop start L
-+      {0x3805, 0x97, 0, 0}, //; H crop end L
-+      {0x3807, 0x4b, 0, 0}, //; V crop end L
-+      {0x3808, 0x08, 0, 0}, //; H output size H
-+      {0x3809, 0x40, 0, 0}, //; H output size L
-+      {0x380a, 0x06, 0, 0}, //; V output size H
-+      {0x380b, 0x20, 0, 0}, //; V output size L
-+      {0x380c, 0x25, 0, 0}, //; HTS H
-+      {0x380d, 0x80, 0, 0}, //; HTS L
-+      {0x380e, 0x0a, 0, 0},//6}, //; VTS H
-+      {0x380f, 0x80, 0, 0}, //; VTS L
-+      {0x3813, 0x02, 0, 0}, //; V win off
-+      {0x3814, 0x31, 0, 0}, //; H inc
-+      {0x3815, 0x31, 0, 0}, //; V inc
-+      {0x3820, 0x02, 0, 0}, //; V flip off, V bin on
-+      {0x3821, 0x05, 0, 0}, //; H mirror on, H bin on
-+      {0x3836, 0x08, 0, 0}, //
-+      {0x3837, 0x02, 0, 0}, //
-+      {0x4020, 0x00, 0, 0}, //
-+      {0x4021, 0xe4, 0, 0}, //
-+      {0x4022, 0x07, 0, 0}, //
-+      {0x4023, 0x5f, 0, 0}, //
-+      {0x4024, 0x08, 0, 0}, //
-+      {0x4025, 0x44, 0, 0}, //
-+      {0x4026, 0x08, 0, 0}, //
-+      {0x4027, 0x47, 0, 0}, //
-+      {0x4603, 0x01, 0, 0}, //; VFIFO
-+      {0x4837, 0x19, 0, 0}, //; MIPI global timing
-+      {0x4802, 0x42, 0, 0},  //default 0x00
-+      {0x481a, 0x00, 0, 0},
-+      {0x481b, 0x1c, 0, 0},   //default 0x3c  prepare
-+      {0x4826, 0x12, 0, 0},   //default 0x32  trail
-+      {0x5401, 0x61, 0, 0}, //
-+      {0x5405, 0x40, 0, 0}, //
-+
-+      //{0xffff, 200, 0, 0},
-+      //{0xffff, 200, 0, 0},
-+      //{0xffff, 200, 0, 0},
-+
-+      //{0x0100, 0x01, 0, 0}, //; wake up, streaming
-+};
-+
-+/* power-on sensor init reg table */
-+static const struct ov13850_mode_info ov13850_mode_init_data = {
-+      OV13850_MODE_1080P_1920_1080, SCALING,
-+      1920, 0x6e0, 1080, 0x470,
-+      ov13850_init_setting_30fps_1080P,
-+      ARRAY_SIZE(ov13850_init_setting_30fps_1080P),
-+      OV13850_30_FPS,
-+};
-+
-+static const struct ov13850_mode_info
-+ov13850_mode_data[OV13850_NUM_MODES] = {
-+      {OV13850_MODE_1080P_1920_1080, SCALING,
-+      1920, 0x6e0, 1080, 0x470,
-+      ov13850_setting_1080P_1920_1080,
-+      ARRAY_SIZE(ov13850_setting_1080P_1920_1080),
-+      OV13850_30_FPS},
-+};
-+
-+static int ov13850_write_reg(struct ov13850_dev *sensor, u16 reg, u8 val)
-+{
-+      struct i2c_client *client = sensor->i2c_client;
-+      struct i2c_msg msg;
-+      u8 buf[3];
-+      int ret;
-+
-+      buf[0] = reg >> 8;
-+      buf[1] = reg & 0xff;
-+      buf[2] = val;
-+
-+      msg.addr = client->addr;
-+      msg.flags = client->flags;
-+      msg.buf = buf;
-+      msg.len = sizeof(buf);
-+
-+      ret = i2c_transfer(client->adapter, &msg, 1);
-+      if (ret < 0) {
-+              dev_err(&client->dev, "%s: error: reg=%x, val=%x\n",
-+                      __func__, reg, val);
-+              return ret;
-+      }
-+
-+      return 0;
-+}
-+
-+static int ov13850_read_reg(struct ov13850_dev *sensor, u16 reg, u8 *val)
-+{
-+      struct i2c_client *client = sensor->i2c_client;
-+      struct i2c_msg msg[2];
-+      u8 buf[2];
-+      int ret;
-+
-+      buf[0] = reg >> 8;
-+      buf[1] = reg & 0xff;
-+
-+      msg[0].addr = client->addr;
-+      msg[0].flags = client->flags;
-+      msg[0].buf = buf;
-+      msg[0].len = sizeof(buf);
-+
-+      msg[1].addr = client->addr;
-+      msg[1].flags = client->flags | I2C_M_RD;
-+      msg[1].buf = buf;
-+      msg[1].len = 1;
-+
-+      ret = i2c_transfer(client->adapter, msg, 2);
-+      if (ret < 0) {
-+              dev_err(&client->dev, "%s: error: reg=%x\n",
-+                      __func__, reg);
-+              return ret;
-+      }
-+
-+      *val = buf[0];
-+      return 0;
-+}
-+
-+static int ov13850_read_reg16(struct ov13850_dev *sensor, u16 reg, u16 *val)
-+{
-+      u8 hi, lo;
-+      int ret;
-+
-+      ret = ov13850_read_reg(sensor, reg, &hi);
-+      if (ret)
-+              return ret;
-+      ret = ov13850_read_reg(sensor, reg + 1, &lo);
-+      if (ret)
-+              return ret;
-+
-+      *val = ((u16)hi << 8) | (u16)lo;
-+      return 0;
-+}
-+
-+static int ov13850_write_reg16(struct ov13850_dev *sensor, u16 reg, u16 val)
-+{
-+      int ret;
-+
-+      ret = ov13850_write_reg(sensor, reg, val >> 8);
-+      if (ret)
-+              return ret;
-+
-+      return ov13850_write_reg(sensor, reg + 1, val & 0xff);
-+}
-+
-+static int ov13850_mod_reg(struct ov13850_dev *sensor, u16 reg,
-+                      u8 mask, u8 val)
-+{
-+      u8 readval;
-+      int ret;
-+
-+      ret = ov13850_read_reg(sensor, reg, &readval);
-+      if (ret)
-+              return ret;
-+
-+      readval &= ~mask;
-+      val &= mask;
-+      val |= readval;
-+
-+      return ov13850_write_reg(sensor, reg, val);
-+}
-+
-+static int ov13850_set_timings(struct ov13850_dev *sensor,
-+                      const struct ov13850_mode_info *mode)
-+{
-+      int ret;
-+
-+      ret = ov13850_write_reg16(sensor, OV13850_REG_H_OUTPUT_SIZE, mode->hact);
-+      if (ret < 0)
-+              return ret;
-+
-+      ret = ov13850_write_reg16(sensor, OV13850_REG_V_OUTPUT_SIZE, mode->vact);
-+      if (ret < 0)
-+              return ret;
-+
-+      return 0;
-+}
-+
-+static int ov13850_load_regs(struct ov13850_dev *sensor,
-+                      const struct ov13850_mode_info *mode)
-+{
-+      const struct reg_value *regs = mode->reg_data;
-+      unsigned int i;
-+      u32 delay_ms;
-+      u16 reg_addr;
-+      u8 mask, val;
-+      int ret = 0;
-+
-+      st_info(ST_SENSOR, "%s, mode = 0x%x\n", __func__, mode->id);
-+      for (i = 0; i < mode->reg_data_size; ++i, ++regs) {
-+              delay_ms = regs->delay_ms;
-+              reg_addr = regs->reg_addr;
-+              val = regs->val;
-+              mask = regs->mask;
-+
-+              if (mask)
-+                      ret = ov13850_mod_reg(sensor, reg_addr, mask, val);
-+              else
-+                      ret = ov13850_write_reg(sensor, reg_addr, val);
-+              if (ret)
-+                      break;
-+
-+              if (delay_ms)
-+                      usleep_range(1000 * delay_ms, 1000 * delay_ms + 100);
-+      }
-+
-+      return ov13850_set_timings(sensor, mode);
-+}
-+
-+
-+
-+static int ov13850_get_gain(struct ov13850_dev *sensor)
-+{
-+      u32 gain = 0;
-+      return gain;
-+}
-+
-+static int ov13850_set_gain(struct ov13850_dev *sensor, int gain)
-+{
-+      return 0;
-+}
-+
-+static int ov13850_set_stream_mipi(struct ov13850_dev *sensor, bool on)
-+{
-+      return 0;
-+}
-+
-+static int ov13850_get_sysclk(struct ov13850_dev *sensor)
-+{
-+      return 0;
-+}
-+
-+static int ov13850_set_night_mode(struct ov13850_dev *sensor)
-+{
-+      return 0;
-+}
-+
-+static int ov13850_get_hts(struct ov13850_dev *sensor)
-+{
-+      /* read HTS from register settings */
-+      u16 hts;
-+      int ret;
-+
-+      ret = ov13850_read_reg16(sensor, OV13850_REG_TIMING_HTS, &hts);
-+      if (ret)
-+              return ret;
-+      return hts;
-+}
-+
-+static int ov13850_set_hts(struct ov13850_dev *sensor, int hts)
-+{
-+      return ov13850_write_reg16(sensor, OV13850_REG_TIMING_HTS, hts);
-+}
-+
-+
-+static int ov13850_get_vts(struct ov13850_dev *sensor)
-+{
-+      u16 vts;
-+      int ret;
-+
-+      ret = ov13850_read_reg16(sensor, OV13850_REG_TIMING_VTS, &vts);
-+      if (ret)
-+              return ret;
-+      return vts;
-+}
-+
-+static int ov13850_set_vts(struct ov13850_dev *sensor, int vts)
-+{
-+      return ov13850_write_reg16(sensor, OV13850_REG_TIMING_VTS, vts);
-+}
-+
-+static int ov13850_get_light_freq(struct ov13850_dev *sensor)
-+{
-+      return 0;
-+}
-+
-+static int ov13850_set_bandingfilter(struct ov13850_dev *sensor)
-+{
-+      return 0;
-+}
-+
-+static int ov13850_set_ae_target(struct ov13850_dev *sensor, int target)
-+{
-+      return 0;
-+}
-+
-+static int ov13850_get_binning(struct ov13850_dev *sensor)
-+{
-+      return 0;
-+}
-+
-+static int ov13850_set_binning(struct ov13850_dev *sensor, bool enable)
-+{
-+      return 0;
-+}
-+
-+static const struct ov13850_mode_info *
-+ov13850_find_mode(struct ov13850_dev *sensor, enum ov13850_frame_rate fr,
-+              int width, int height, bool nearest)
-+{
-+      const struct ov13850_mode_info *mode;
-+
-+      mode = v4l2_find_nearest_size(ov13850_mode_data,
-+                              ARRAY_SIZE(ov13850_mode_data),
-+                              hact, vact,
-+                              width, height);
-+
-+      if (!mode ||
-+              (!nearest && (mode->hact != width || mode->vact != height)))
-+              return NULL;
-+
-+      /* Check to see if the current mode exceeds the max frame rate */
-+      if (ov13850_framerates[fr] > ov13850_framerates[mode->max_fps])
-+              return NULL;
-+
-+      return mode;
-+}
-+
-+static u64 ov13850_calc_pixel_rate(struct ov13850_dev *sensor)
-+{
-+      u64 rate;
-+
-+      rate = sensor->current_mode->vact * sensor->current_mode->hact;
-+      rate *= ov13850_framerates[sensor->current_fr];
-+
-+      return rate;
-+}
-+
-+/*
-+ * After trying the various combinations, reading various
-+ * documentations spread around the net, and from the various
-+ * feedback, the clock tree is probably as follows:
-+ *
-+ *   +--------------+
-+ *   |  Ext. Clock  |
-+ *   +-+------------+
-+ *     |  +----------+
-+ *     +->|   PLL1   | - reg 0x030a, bit0 for the pre-dividerp
-+ *        +-+--------+ - reg 0x0300, bits 0-2 for the pre-divider
-+ *        +-+--------+ - reg 0x0301~0x0302, for the multiplier
-+ *          |  +--------------+
-+ *          +->| MIPI Divider |  - reg 0x0303, bits 0-3 for the pre-divider
-+ *               | +---------> MIPI PHY CLK
-+ *               |    +-----+
-+ *               | +->| PLL1_DIV_MIPI | - reg 0x0304, bits 0-1 for the divider
-+ *                 |    +----------------> PCLK
-+ *               |    +-----+
-+ *
-+ *   +--------------+
-+ *   |  Ext. Clock  |
-+ *   +-+------------+
-+ *     |  +----------+
-+ *     +->|   PLL2  | - reg 0x0311, bit0 for the pre-dividerp
-+ *        +-+--------+ - reg 0x030b, bits 0-2 for the pre-divider
-+ *        +-+--------+ - reg 0x030c~0x030d, for the multiplier
-+ *          |  +--------------+
-+ *          +->| SCLK Divider |  - reg 0x030F, bits 0-3 for the pre-divider
-+ *               +-+--------+    - reg 0x030E, bits 0-2 for the divider
-+ *               |    +---------> SCLK
-+ *
-+ *          |       +-----+
-+ *          +->| DAC Divider | - reg 0x0312, bits 0-3 for the divider
-+ *                    |    +----------------> DACCLK
-+ **
-+ */
-+
-+/*
-+ * ov13850_set_mipi_pclk() - Calculate the clock tree configuration values
-+ *                    for the MIPI CSI-2 output.
-+ *
-+ * @rate: The requested bandwidth per lane in bytes per second.
-+ *    'Bandwidth Per Lane' is calculated as:
-+ *    bpl = HTOT * VTOT * FPS * bpp / num_lanes;
-+ *
-+ * This function use the requested bandwidth to calculate:
-+ *
-+ * - mipi_pclk   = bpl / 2; ( / 2 is for CSI-2 DDR)
-+ * - mipi_phy_clk   = mipi_pclk * PLL1_DIV_MIPI;
-+ *
-+ * with these fixed parameters:
-+ *    PLL1_PREDIVP    = 1;
-+ *    PLL1_PREDIV     = 1; (MIPI_BIT_MODE == 8 ? 2 : 2,5);
-+ *    PLL1_DIVM       = 1;
-+ *    PLL1_DIV_MIPI   = 4;
-+ *
-+ * FIXME: this have been tested with 10-bit raw and 2 lanes setup only.
-+ * MIPI_DIV is fixed to value 2, but it -might- be changed according to the
-+ * above formula for setups with 1 lane or image formats with different bpp.
-+ *
-+ * FIXME: this deviates from the sensor manual documentation which is quite
-+ * thin on the MIPI clock tree generation part.
-+ */
-+
-+
-+
-+static int ov13850_set_mipi_pclk(struct ov13850_dev *sensor,
-+                              unsigned long rate)
-+{
-+
-+      return 0;
-+}
-+
-+/*
-+ * if sensor changes inside scaling or subsampling
-+ * change mode directly
-+ */
-+static int ov13850_set_mode_direct(struct ov13850_dev *sensor,
-+                              const struct ov13850_mode_info *mode)
-+{
-+      if (!mode->reg_data)
-+              return -EINVAL;
-+
-+      /* Write capture setting */
-+      return ov13850_load_regs(sensor, mode);
-+}
-+
-+static int ov13850_set_mode(struct ov13850_dev *sensor)
-+{
-+      const struct ov13850_mode_info *mode = sensor->current_mode;
-+      const struct ov13850_mode_info *orig_mode = sensor->last_mode;
-+      int ret = 0;
-+
-+      ret = ov13850_set_mode_direct(sensor, mode);
-+      if (ret < 0)
-+              return ret;
-+
-+      /*
-+       * we support have 10 bits raw RGB(mipi)
-+       */
-+      if (sensor->ep.bus_type == V4L2_MBUS_CSI2_DPHY)
-+              ret = ov13850_set_mipi_pclk(sensor, 0);
-+
-+      if (ret < 0)
-+              return 0;
-+
-+      sensor->pending_mode_change = false;
-+      sensor->last_mode = mode;
-+      return 0;
-+}
-+
-+static int ov13850_set_framefmt(struct ov13850_dev *sensor,
-+                             struct v4l2_mbus_framefmt *format);
-+
-+/* restore the last set video mode after chip power-on */
-+static int ov13850_restore_mode(struct ov13850_dev *sensor)
-+{
-+      int ret;
-+
-+      /* first load the initial register values */
-+      ret = ov13850_load_regs(sensor, &ov13850_mode_init_data);
-+      if (ret < 0)
-+              return ret;
-+      sensor->last_mode = &ov13850_mode_init_data;
-+
-+      /* now restore the last capture mode */
-+      ret = ov13850_set_mode(sensor);
-+      if (ret < 0)
-+              return ret;
-+
-+      return ov13850_set_framefmt(sensor, &sensor->fmt);
-+}
-+
-+static void ov13850_power(struct ov13850_dev *sensor, bool enable)
-+{
-+      if (!sensor->pwdn_gpio)
-+              return;
-+      if (enable) {
-+              gpiod_set_value_cansleep(sensor->pwdn_gpio, 0);
-+              gpiod_set_value_cansleep(sensor->pwdn_gpio, 1);
-+      } else {
-+              gpiod_set_value_cansleep(sensor->pwdn_gpio, 0);
-+      }
-+
-+      mdelay(100);
-+}
-+
-+static void ov13850_reset(struct ov13850_dev *sensor)
-+{
-+      if (!sensor->reset_gpio)
-+              return;
-+
-+      gpiod_set_value_cansleep(sensor->reset_gpio, 0);
-+      gpiod_set_value_cansleep(sensor->reset_gpio, 1);
-+      mdelay(100);
-+}
-+
-+static int ov13850_set_power_on(struct ov13850_dev *sensor)
-+{
-+      struct i2c_client *client = sensor->i2c_client;
-+      int ret;
-+
-+      ret = clk_prepare_enable(sensor->xclk);
-+      if (ret) {
-+              dev_err(&client->dev, "%s: failed to enable clock\n",
-+                      __func__);
-+              return ret;
-+      }
-+
-+      ret = regulator_bulk_enable(OV13850_NUM_SUPPLIES,
-+                              sensor->supplies);
-+      if (ret) {
-+              dev_err(&client->dev, "%s: failed to enable regulators\n",
-+                      __func__);
-+              goto xclk_off;
-+      }
-+
-+      ov13850_reset(sensor);
-+      ov13850_power(sensor, true);
-+
-+      return 0;
-+
-+xclk_off:
-+      clk_disable_unprepare(sensor->xclk);
-+      return ret;
-+}
-+
-+static void ov13850_set_power_off(struct ov13850_dev *sensor)
-+{
-+      ov13850_power(sensor, false);
-+      regulator_bulk_disable(OV13850_NUM_SUPPLIES, sensor->supplies);
-+      clk_disable_unprepare(sensor->xclk);
-+}
-+
-+static int ov13850_set_power_mipi(struct ov13850_dev *sensor, bool on)
-+{
-+      return 0;
-+}
-+
-+static int ov13850_set_power(struct ov13850_dev *sensor, bool on)
-+{
-+      int ret = 0;
-+      u16 chip_id;
-+
-+      if (on) {
-+              ret = ov13850_set_power_on(sensor);
-+              if (ret)
-+                      return ret;
-+
-+#ifdef UNUSED_CODE
-+              ret = ov13850_read_reg16(sensor, OV13850_REG_CHIP_ID, &chip_id);
-+              if (ret) {
-+                      dev_err(&sensor->i2c_client->dev, "%s: failed to read chip identifier\n",
-+                              __func__);
-+                      ret = -ENODEV;
-+                      goto power_off;
-+              }
-+
-+              if (chip_id != OV13850_CHIP_ID) {
-+                      dev_err(&sensor->i2c_client->dev,
-+                                      "%s: wrong chip identifier, expected 0x%x, got 0x%x\n",
-+                                      __func__, OV13850_CHIP_ID, chip_id);
-+                      ret = -ENXIO;
-+                      goto power_off;
-+              }
-+              dev_err(&sensor->i2c_client->dev, "%s: chip identifier, got 0x%x\n",
-+                      __func__, chip_id);
-+#endif
-+
-+              ret = ov13850_restore_mode(sensor);
-+              if (ret)
-+                      goto power_off;
-+      }
-+
-+      if (sensor->ep.bus_type == V4L2_MBUS_CSI2_DPHY)
-+              ret = ov13850_set_power_mipi(sensor, on);
-+      if (ret)
-+              goto power_off;
-+
-+      if (!on)
-+              ov13850_set_power_off(sensor);
-+
-+      return 0;
-+
-+power_off:
-+      ov13850_set_power_off(sensor);
-+      return ret;
-+}
-+
-+static int ov13850_s_power(struct v4l2_subdev *sd, int on)
-+{
-+      struct ov13850_dev *sensor = to_ov13850_dev(sd);
-+      int ret = 0;
-+
-+      mutex_lock(&sensor->lock);
-+
-+      /*
-+       * If the power count is modified from 0 to != 0 or from != 0 to 0,
-+       * update the power state.
-+       */
-+      if (sensor->power_count == !on) {
-+              ret = ov13850_set_power(sensor, !!on);
-+              if (ret)
-+                      goto out;
-+      }
-+
-+      /* Update the power count. */
-+      sensor->power_count += on ? 1 : -1;
-+      WARN_ON(sensor->power_count < 0);
-+out:
-+      mutex_unlock(&sensor->lock);
-+
-+      if (on && !ret && sensor->power_count == 1) {
-+              /* restore controls */
-+              ret = v4l2_ctrl_handler_setup(&sensor->ctrls.handler);
-+      }
-+
-+      return ret;
-+}
-+
-+static int ov13850_try_frame_interval(struct ov13850_dev *sensor,
-+                              struct v4l2_fract *fi,
-+                              u32 width, u32 height)
-+{
-+      const struct ov13850_mode_info *mode;
-+      enum ov13850_frame_rate rate = OV13850_15_FPS;
-+      int minfps, maxfps, best_fps, fps;
-+      int i;
-+
-+      minfps = ov13850_framerates[OV13850_15_FPS];
-+      maxfps = ov13850_framerates[OV13850_NUM_FRAMERATES - 1];
-+
-+      if (fi->numerator == 0) {
-+              fi->denominator = maxfps;
-+              fi->numerator = 1;
-+              rate = OV13850_60_FPS;
-+              goto find_mode;
-+      }
-+
-+      fps = clamp_val(DIV_ROUND_CLOSEST(fi->denominator, fi->numerator),
-+                      minfps, maxfps);
-+
-+      best_fps = minfps;
-+      for (i = 0; i < ARRAY_SIZE(ov13850_framerates); i++) {
-+              int curr_fps = ov13850_framerates[i];
-+
-+              if (abs(curr_fps - fps) < abs(best_fps - fps)) {
-+                      best_fps = curr_fps;
-+                      rate = i;
-+              }
-+      }
-+      st_info(ST_SENSOR, "best_fps = %d, fps = %d\n", best_fps, fps);
-+
-+      fi->numerator = 1;
-+      fi->denominator = best_fps;
-+
-+find_mode:
-+      mode = ov13850_find_mode(sensor, rate, width, height, false);
-+      return mode ? rate : -EINVAL;
-+}
-+
-+static int ov13850_enum_mbus_code(struct v4l2_subdev *sd,
-+                              struct v4l2_subdev_state *state,
-+                              struct v4l2_subdev_mbus_code_enum *code)
-+{
-+      if (code->pad != 0)
-+              return -EINVAL;
-+
-+      if (code->index >= ARRAY_SIZE(ov13850_formats))
-+              return -EINVAL;
-+
-+      code->code = ov13850_formats[code->index].code;
-+      return 0;
-+}
-+
-+static int ov13850_get_fmt(struct v4l2_subdev *sd,
-+                      struct v4l2_subdev_state *state,
-+                      struct v4l2_subdev_format *format)
-+{
-+      struct ov13850_dev *sensor = to_ov13850_dev(sd);
-+      struct v4l2_mbus_framefmt *fmt;
-+
-+      if (format->pad != 0)
-+              return -EINVAL;
-+
-+      mutex_lock(&sensor->lock);
-+
-+      if (format->which == V4L2_SUBDEV_FORMAT_TRY)
-+              fmt = v4l2_subdev_get_try_format(&sensor->sd, state,
-+                                              format->pad);
-+      else
-+              fmt = &sensor->fmt;
-+
-+      format->format = *fmt;
-+
-+      mutex_unlock(&sensor->lock);
-+
-+      return 0;
-+}
-+
-+static int ov13850_try_fmt_internal(struct v4l2_subdev *sd,
-+                              struct v4l2_mbus_framefmt *fmt,
-+                              enum ov13850_frame_rate fr,
-+                              const struct ov13850_mode_info **new_mode)
-+{
-+      struct ov13850_dev *sensor = to_ov13850_dev(sd);
-+      const struct ov13850_mode_info *mode;
-+      int i;
-+
-+      mode = ov13850_find_mode(sensor, fr, fmt->width, fmt->height, true);
-+      if (!mode)
-+              return -EINVAL;
-+      fmt->width = mode->hact;
-+      fmt->height = mode->vact;
-+
-+      if (new_mode)
-+              *new_mode = mode;
-+
-+      for (i = 0; i < ARRAY_SIZE(ov13850_formats); i++)
-+              if (ov13850_formats[i].code == fmt->code)
-+                      break;
-+      if (i >= ARRAY_SIZE(ov13850_formats))
-+              i = 0;
-+
-+      fmt->code = ov13850_formats[i].code;
-+      fmt->colorspace = ov13850_formats[i].colorspace;
-+      fmt->ycbcr_enc = V4L2_MAP_YCBCR_ENC_DEFAULT(fmt->colorspace);
-+      fmt->quantization = V4L2_QUANTIZATION_FULL_RANGE;
-+      fmt->xfer_func = V4L2_MAP_XFER_FUNC_DEFAULT(fmt->colorspace);
-+
-+      return 0;
-+}
-+
-+static int ov13850_set_fmt(struct v4l2_subdev *sd,
-+                      struct v4l2_subdev_state *state,
-+                      struct v4l2_subdev_format *format)
-+{
-+      struct ov13850_dev *sensor = to_ov13850_dev(sd);
-+      const struct ov13850_mode_info *new_mode;
-+      struct v4l2_mbus_framefmt *mbus_fmt = &format->format;
-+      struct v4l2_mbus_framefmt *fmt;
-+      int ret;
-+
-+      if (format->pad != 0)
-+              return -EINVAL;
-+
-+      mutex_lock(&sensor->lock);
-+
-+      if (sensor->streaming) {
-+              ret = -EBUSY;
-+              goto out;
-+      }
-+
-+      ret = ov13850_try_fmt_internal(sd, mbus_fmt, 0, &new_mode);
-+      if (ret)
-+              goto out;
-+
-+      if (format->which == V4L2_SUBDEV_FORMAT_TRY)
-+              fmt = v4l2_subdev_get_try_format(sd, state, 0);
-+      else
-+              fmt = &sensor->fmt;
-+
-+      if (mbus_fmt->code != sensor->fmt.code)
-+              sensor->pending_fmt_change = true;
-+
-+      *fmt = *mbus_fmt;
-+
-+      if (new_mode != sensor->current_mode) {
-+              sensor->current_mode = new_mode;
-+              sensor->pending_mode_change = true;
-+      }
-+
-+      if (new_mode->max_fps < sensor->current_fr) {
-+              sensor->current_fr = new_mode->max_fps;
-+              sensor->frame_interval.numerator = 1;
-+              sensor->frame_interval.denominator =
-+                      ov13850_framerates[sensor->current_fr];
-+              sensor->current_mode = new_mode;
-+              sensor->pending_mode_change = true;
-+      }
-+
-+      __v4l2_ctrl_s_ctrl_int64(sensor->ctrls.pixel_rate,
-+                              ov13850_calc_pixel_rate(sensor));
-+out:
-+      mutex_unlock(&sensor->lock);
-+      return ret;
-+}
-+
-+static int ov13850_set_framefmt(struct ov13850_dev *sensor,
-+                             struct v4l2_mbus_framefmt *format)
-+{
-+      u8 fmt;
-+
-+      switch (format->code) {
-+      /* Raw, BGBG... / GRGR... */
-+      case MEDIA_BUS_FMT_SBGGR8_1X8:
-+      case MEDIA_BUS_FMT_SGBRG8_1X8:
-+      case MEDIA_BUS_FMT_SGRBG8_1X8:
-+      case MEDIA_BUS_FMT_SRGGB8_1X8:
-+              fmt = 0x0;
-+              break;
-+      case MEDIA_BUS_FMT_SBGGR10_1X10:
-+      case MEDIA_BUS_FMT_SGBRG10_1X10:
-+      case MEDIA_BUS_FMT_SGRBG10_1X10:
-+      case MEDIA_BUS_FMT_SRGGB10_1X10:
-+              fmt = 0x1;
-+      case MEDIA_BUS_FMT_SBGGR12_1X12:
-+      case MEDIA_BUS_FMT_SGBRG12_1X12:
-+      case MEDIA_BUS_FMT_SGRBG12_1X12:
-+      case MEDIA_BUS_FMT_SRGGB12_1X12:
-+              fmt = 0x2;
-+      default:
-+              return -EINVAL;
-+      }
-+
-+      return ov13850_mod_reg(sensor, OV13850_REG_MIPI_SC,
-+                      BIT(1) | BIT(0), fmt);
-+}
-+
-+/*
-+ * Sensor Controls.
-+ */
-+
-+static int ov13850_set_ctrl_hue(struct ov13850_dev *sensor, int value)
-+{
-+      int ret = 0;
-+
-+      return ret;
-+}
-+
-+static int ov13850_set_ctrl_contrast(struct ov13850_dev *sensor, int value)
-+{
-+      int ret = 0;
-+
-+      return ret;
-+}
-+
-+static int ov13850_set_ctrl_saturation(struct ov13850_dev *sensor, int value)
-+{
-+      int ret  = 0;
-+
-+      return ret;
-+}
-+
-+static int ov13850_set_ctrl_white_balance(struct ov13850_dev *sensor, int awb)
-+{
-+      struct ov13850_ctrls *ctrls = &sensor->ctrls;
-+      int ret = 0;
-+
-+      return ret;
-+}
-+
-+static int ov13850_set_ctrl_exposure(struct ov13850_dev *sensor,
-+                              enum v4l2_exposure_auto_type auto_exposure)
-+{
-+      struct ov13850_ctrls *ctrls = &sensor->ctrls;
-+      int ret = 0;
-+
-+      return ret;
-+}
-+
-+static const s64 link_freq_menu_items[] = {
-+      OV13850_LINK_FREQ_500MHZ
-+};
-+
-+static const char * const test_pattern_menu[] = {
-+      "Disabled",
-+      "Color bars",
-+      "Color bars w/ rolling bar",
-+      "Color squares",
-+      "Color squares w/ rolling bar",
-+};
-+
-+static int ov13850_set_ctrl_test_pattern(struct ov13850_dev *sensor, int value)
-+{
-+      return 0;
-+}
-+
-+static int ov13850_set_ctrl_light_freq(struct ov13850_dev *sensor, int value)
-+{
-+      return 0;
-+}
-+
-+static int ov13850_set_ctrl_hflip(struct ov13850_dev *sensor, int value)
-+{
-+      return 0;
-+}
-+
-+static int ov13850_set_ctrl_vflip(struct ov13850_dev *sensor, int value)
-+{
-+      return 0;
-+}
-+
-+static int ov13850_g_volatile_ctrl(struct v4l2_ctrl *ctrl)
-+{
-+      struct v4l2_subdev *sd = ctrl_to_sd(ctrl);
-+      struct ov13850_dev *sensor = to_ov13850_dev(sd);
-+      int val;
-+
-+      /* v4l2_ctrl_lock() locks our own mutex */
-+
-+      switch (ctrl->id) {
-+      case V4L2_CID_ANALOGUE_GAIN:
-+              val = ov13850_get_gain(sensor);
-+              break;
-+      }
-+
-+      return 0;
-+}
-+
-+static int ov13850_s_ctrl(struct v4l2_ctrl *ctrl)
-+{
-+      struct v4l2_subdev *sd = ctrl_to_sd(ctrl);
-+      struct ov13850_dev *sensor = to_ov13850_dev(sd);
-+      int ret;
-+
-+      /* v4l2_ctrl_lock() locks our own mutex */
-+
-+      /*
-+       * If the device is not powered up by the host driver do
-+       * not apply any controls to H/W at this time. Instead
-+       * the controls will be restored right after power-up.
-+       */
-+      if (sensor->power_count == 0)
-+              return 0;
-+
-+      switch (ctrl->id) {
-+      case V4L2_CID_ANALOGUE_GAIN:
-+              ret = ov13850_set_gain(sensor, ctrl->val);
-+              break;
-+      case V4L2_CID_EXPOSURE:
-+              ret = ov13850_set_ctrl_exposure(sensor, V4L2_EXPOSURE_MANUAL);
-+              break;
-+      case V4L2_CID_AUTO_WHITE_BALANCE:
-+              ret = ov13850_set_ctrl_white_balance(sensor, ctrl->val);
-+              break;
-+      case V4L2_CID_HUE:
-+              ret = ov13850_set_ctrl_hue(sensor, ctrl->val);
-+              break;
-+      case V4L2_CID_CONTRAST:
-+              ret = ov13850_set_ctrl_contrast(sensor, ctrl->val);
-+              break;
-+      case V4L2_CID_SATURATION:
-+              ret = ov13850_set_ctrl_saturation(sensor, ctrl->val);
-+              break;
-+      case V4L2_CID_TEST_PATTERN:
-+              ret = ov13850_set_ctrl_test_pattern(sensor, ctrl->val);
-+              break;
-+      case V4L2_CID_POWER_LINE_FREQUENCY:
-+              ret = ov13850_set_ctrl_light_freq(sensor, ctrl->val);
-+              break;
-+      case V4L2_CID_HFLIP:
-+              ret = ov13850_set_ctrl_hflip(sensor, ctrl->val);
-+              break;
-+      case V4L2_CID_VFLIP:
-+              ret = ov13850_set_ctrl_vflip(sensor, ctrl->val);
-+              break;
-+      default:
-+              ret = -EINVAL;
-+              break;
-+      }
-+
-+      return ret;
-+}
-+
-+static const struct v4l2_ctrl_ops ov13850_ctrl_ops = {
-+      .g_volatile_ctrl = ov13850_g_volatile_ctrl,
-+      .s_ctrl = ov13850_s_ctrl,
-+};
-+
-+static int ov13850_init_controls(struct ov13850_dev *sensor)
-+{
-+      const struct v4l2_ctrl_ops *ops = &ov13850_ctrl_ops;
-+      struct ov13850_ctrls *ctrls = &sensor->ctrls;
-+      struct v4l2_ctrl_handler *hdl = &ctrls->handler;
-+      int ret;
-+
-+      v4l2_ctrl_handler_init(hdl, 32);
-+
-+      /* we can use our own mutex for the ctrl lock */
-+      hdl->lock = &sensor->lock;
-+
-+      /* Clock related controls */
-+      ctrls->pixel_rate = v4l2_ctrl_new_std(hdl, ops, V4L2_CID_PIXEL_RATE,
-+                                      0, INT_MAX, 1,
-+                                      ov13850_calc_pixel_rate(sensor));
-+
-+      /* Auto/manual white balance */
-+      ctrls->auto_wb = v4l2_ctrl_new_std(hdl, ops,
-+                                      V4L2_CID_AUTO_WHITE_BALANCE,
-+                                      0, 1, 1, 0);
-+      ctrls->blue_balance = v4l2_ctrl_new_std(hdl, ops, V4L2_CID_BLUE_BALANCE,
-+                                              0, 4095, 1, 1024);
-+      ctrls->red_balance = v4l2_ctrl_new_std(hdl, ops, V4L2_CID_RED_BALANCE,
-+                                              0, 4095, 1, 1024);
-+
-+      ctrls->exposure = v4l2_ctrl_new_std(hdl, ops, V4L2_CID_EXPOSURE,
-+                                      4, 0xfff8, 1, 0x4c00);
-+      ctrls->anal_gain = v4l2_ctrl_new_std(hdl, ops, V4L2_CID_ANALOGUE_GAIN,
-+                                      0x10, 0xfff8, 1, 0x0080);
-+      ctrls->test_pattern =
-+              v4l2_ctrl_new_std_menu_items(hdl, ops, V4L2_CID_TEST_PATTERN,
-+                                      ARRAY_SIZE(test_pattern_menu) - 1,
-+                                      0, 0, test_pattern_menu);
-+      ctrls->hflip = v4l2_ctrl_new_std(hdl, ops, V4L2_CID_HFLIP,
-+                                      0, 1, 1, 0);
-+      ctrls->vflip = v4l2_ctrl_new_std(hdl, ops, V4L2_CID_VFLIP,
-+                                      0, 1, 1, 0);
-+      ctrls->light_freq =
-+              v4l2_ctrl_new_std_menu(hdl, ops,
-+                                      V4L2_CID_POWER_LINE_FREQUENCY,
-+                                      V4L2_CID_POWER_LINE_FREQUENCY_AUTO, 0,
-+                                      V4L2_CID_POWER_LINE_FREQUENCY_50HZ);
-+      ctrls->link_freq = v4l2_ctrl_new_int_menu(hdl, ops, V4L2_CID_LINK_FREQ,
-+                                      0, 0, link_freq_menu_items);
-+      if (hdl->error) {
-+              ret = hdl->error;
-+              goto free_ctrls;
-+      }
-+
-+      ctrls->pixel_rate->flags |= V4L2_CTRL_FLAG_READ_ONLY;
-+      ctrls->link_freq->flags |= V4L2_CTRL_FLAG_READ_ONLY;
-+      // ctrls->exposure->flags |= V4L2_CTRL_FLAG_VOLATILE;
-+      // ctrls->anal_gain->flags |= V4L2_CTRL_FLAG_VOLATILE;
-+
-+      v4l2_ctrl_auto_cluster(3, &ctrls->auto_wb, 0, false);
-+
-+      sensor->sd.ctrl_handler = hdl;
-+      return 0;
-+
-+free_ctrls:
-+      v4l2_ctrl_handler_free(hdl);
-+      return ret;
-+}
-+
-+static int ov13850_enum_frame_size(struct v4l2_subdev *sd,
-+                              struct v4l2_subdev_state *state,
-+                              struct v4l2_subdev_frame_size_enum *fse)
-+{
-+      if (fse->pad != 0)
-+              return -EINVAL;
-+      if (fse->index >= OV13850_NUM_MODES)
-+              return -EINVAL;
-+
-+      fse->min_width =
-+              ov13850_mode_data[fse->index].hact;
-+      fse->max_width = fse->min_width;
-+      fse->min_height =
-+              ov13850_mode_data[fse->index].vact;
-+      fse->max_height = fse->min_height;
-+
-+      return 0;
-+}
-+
-+static int ov13850_enum_frame_interval(
-+      struct v4l2_subdev *sd,
-+      struct v4l2_subdev_state *state,
-+      struct v4l2_subdev_frame_interval_enum *fie)
-+{
-+      struct ov13850_dev *sensor = to_ov13850_dev(sd);
-+      struct v4l2_fract tpf;
-+      int ret;
-+
-+      if (fie->pad != 0)
-+              return -EINVAL;
-+      if (fie->index >= OV13850_NUM_FRAMERATES)
-+              return -EINVAL;
-+
-+      tpf.numerator = 1;
-+      tpf.denominator = ov13850_framerates[fie->index];
-+
-+/*    ret = ov13850_try_frame_interval(sensor, &tpf,
-+ *                                    fie->width, fie->height);
-+ *    if (ret < 0)
-+ *            return -EINVAL;
-+ */
-+      fie->interval = tpf;
-+
-+      return 0;
-+}
-+
-+static int ov13850_g_frame_interval(struct v4l2_subdev *sd,
-+                              struct v4l2_subdev_frame_interval *fi)
-+{
-+      struct ov13850_dev *sensor = to_ov13850_dev(sd);
-+
-+      mutex_lock(&sensor->lock);
-+      fi->interval = sensor->frame_interval;
-+      mutex_unlock(&sensor->lock);
-+
-+      return 0;
-+}
-+
-+static int ov13850_s_frame_interval(struct v4l2_subdev *sd,
-+                              struct v4l2_subdev_frame_interval *fi)
-+{
-+      struct ov13850_dev *sensor = to_ov13850_dev(sd);
-+      const struct ov13850_mode_info *mode;
-+      int frame_rate, ret = 0;
-+
-+      if (fi->pad != 0)
-+              return -EINVAL;
-+
-+      mutex_lock(&sensor->lock);
-+
-+      if (sensor->streaming) {
-+              ret = -EBUSY;
-+              goto out;
-+      }
-+
-+      mode = sensor->current_mode;
-+
-+      frame_rate = ov13850_try_frame_interval(sensor, &fi->interval,
-+                                      mode->hact, mode->vact);
-+      if (frame_rate < 0) {
-+              /* Always return a valid frame interval value */
-+              fi->interval = sensor->frame_interval;
-+              goto out;
-+      }
-+
-+      mode = ov13850_find_mode(sensor, frame_rate, mode->hact,
-+                              mode->vact, true);
-+      if (!mode) {
-+              ret = -EINVAL;
-+              goto out;
-+      }
-+
-+      if (mode != sensor->current_mode ||
-+              frame_rate != sensor->current_fr) {
-+              sensor->current_fr = frame_rate;
-+              sensor->frame_interval = fi->interval;
-+              sensor->current_mode = mode;
-+              sensor->pending_mode_change = true;
-+
-+              __v4l2_ctrl_s_ctrl_int64(sensor->ctrls.pixel_rate,
-+                                      ov13850_calc_pixel_rate(sensor));
-+      }
-+out:
-+      mutex_unlock(&sensor->lock);
-+      return ret;
-+}
-+
-+static int ov13850_stream_start(struct ov13850_dev *sensor, int enable)
-+{
-+      int ret;
-+
-+      if (enable) {           //stream on
-+              mdelay(1000);
-+              ret = ov13850_write_reg(sensor, OV13850_STREAM_CTRL, enable);
-+      } else {                        //stream off
-+              ret = ov13850_write_reg(sensor, OV13850_STREAM_CTRL, enable);
-+              mdelay(100);
-+      }
-+
-+      return ret;
-+}
-+
-+static int ov13850_s_stream(struct v4l2_subdev *sd, int enable)
-+{
-+      struct ov13850_dev *sensor = to_ov13850_dev(sd);
-+      int ret = 0;
-+
-+      mutex_lock(&sensor->lock);
-+
-+      if (sensor->streaming == !enable) {
-+              if (enable && sensor->pending_mode_change) {
-+                      ret = ov13850_set_mode(sensor);
-+                      if (ret)
-+                              goto out;
-+              }
-+
-+              if (enable && sensor->pending_fmt_change) {
-+                      ret = ov13850_set_framefmt(sensor, &sensor->fmt);
-+                      if (ret)
-+                              goto out;
-+                      sensor->pending_fmt_change = false;
-+              }
-+
-+              if (sensor->ep.bus_type == V4L2_MBUS_CSI2_DPHY)
-+                      ret = ov13850_set_stream_mipi(sensor, enable);
-+
-+              ret = ov13850_stream_start(sensor, enable);
-+
-+              if (!ret)
-+                      sensor->streaming = enable;
-+      }
-+out:
-+      mutex_unlock(&sensor->lock);
-+      return ret;
-+}
-+
-+static const struct v4l2_subdev_core_ops ov13850_core_ops = {
-+      .s_power = ov13850_s_power,
-+      .log_status = v4l2_ctrl_subdev_log_status,
-+      .subscribe_event = v4l2_ctrl_subdev_subscribe_event,
-+      .unsubscribe_event = v4l2_event_subdev_unsubscribe,
-+};
-+
-+static const struct v4l2_subdev_video_ops ov13850_video_ops = {
-+      .g_frame_interval = ov13850_g_frame_interval,
-+      .s_frame_interval = ov13850_s_frame_interval,
-+      .s_stream = ov13850_s_stream,
-+};
-+
-+static const struct v4l2_subdev_pad_ops ov13850_pad_ops = {
-+      .enum_mbus_code = ov13850_enum_mbus_code,
-+      .get_fmt = ov13850_get_fmt,
-+      .set_fmt = ov13850_set_fmt,
-+      .enum_frame_size = ov13850_enum_frame_size,
-+      .enum_frame_interval = ov13850_enum_frame_interval,
-+};
-+
-+static const struct v4l2_subdev_ops ov13850_subdev_ops = {
-+      .core = &ov13850_core_ops,
-+      .video = &ov13850_video_ops,
-+      .pad = &ov13850_pad_ops,
-+};
-+
-+static int ov13850_get_regulators(struct ov13850_dev *sensor)
-+{
-+      int i;
-+
-+      for (i = 0; i < OV13850_NUM_SUPPLIES; i++)
-+              sensor->supplies[i].supply = ov13850_supply_name[i];
-+
-+      return devm_regulator_bulk_get(&sensor->i2c_client->dev,
-+                                      OV13850_NUM_SUPPLIES,
-+                                      sensor->supplies);
-+}
-+
-+static int ov13850_check_chip_id(struct ov13850_dev *sensor)
-+{
-+      struct i2c_client *client = sensor->i2c_client;
-+      int ret = 0;
-+      u16 chip_id;
-+
-+      ret = ov13850_set_power_on(sensor);
-+      if (ret)
-+              return ret;
-+
-+#ifdef UNUSED_CODE
-+      ret = ov13850_read_reg16(sensor, OV13850_REG_CHIP_ID, &chip_id);
-+      if (ret) {
-+              dev_err(&client->dev, "%s: failed to read chip identifier\n",
-+                      __func__);
-+              goto power_off;
-+      }
-+
-+      if (chip_id != OV13850_CHIP_ID) {
-+              dev_err(&client->dev, "%s: wrong chip identifier, expected 0x%x,  got 0x%x\n",
-+                      __func__, OV13850_CHIP_ID, chip_id);
-+              ret = -ENXIO;
-+      }
-+      dev_err(&client->dev, "%s: chip identifier, got 0x%x\n",
-+              __func__, chip_id);
-+#endif
-+
-+power_off:
-+      ov13850_set_power_off(sensor);
-+      return ret;
-+}
-+
-+static int ov13850_probe(struct i2c_client *client)
-+{
-+      struct device *dev = &client->dev;
-+      struct fwnode_handle *endpoint;
-+      struct ov13850_dev *sensor;
-+      struct v4l2_mbus_framefmt *fmt;
-+      u32 rotation;
-+      int ret;
-+      u8 chip_id_high, chip_id_low;
-+
-+      sensor = devm_kzalloc(dev, sizeof(*sensor), GFP_KERNEL);
-+      if (!sensor)
-+              return -ENOMEM;
-+
-+      sensor->i2c_client = client;
-+
-+      fmt = &sensor->fmt;
-+      fmt->code = MEDIA_BUS_FMT_SBGGR10_1X10;
-+      fmt->colorspace = V4L2_COLORSPACE_SRGB;
-+      fmt->ycbcr_enc = V4L2_MAP_YCBCR_ENC_DEFAULT(fmt->colorspace);
-+      fmt->quantization = V4L2_QUANTIZATION_FULL_RANGE;
-+      fmt->xfer_func = V4L2_MAP_XFER_FUNC_DEFAULT(fmt->colorspace);
-+      fmt->width = 1920;
-+      fmt->height = 1080;
-+      fmt->field = V4L2_FIELD_NONE;
-+      sensor->frame_interval.numerator = 1;
-+      sensor->frame_interval.denominator = ov13850_framerates[OV13850_30_FPS];
-+      sensor->current_fr = OV13850_30_FPS;
-+      sensor->current_mode =
-+              &ov13850_mode_data[OV13850_MODE_1080P_1920_1080];
-+      sensor->last_mode = sensor->current_mode;
-+
-+      sensor->ae_target = 52;
-+
-+      /* optional indication of physical rotation of sensor */
-+      ret = fwnode_property_read_u32(dev_fwnode(&client->dev), "rotation",
-+                                      &rotation);
-+      if (!ret) {
-+              switch (rotation) {
-+              case 180:
-+                      sensor->upside_down = true;
-+                      fallthrough;
-+              case 0:
-+                      break;
-+              default:
-+                      dev_warn(dev, "%u degrees rotation is not supported, ignoring...\n",
-+                              rotation);
-+              }
-+      }
-+
-+      endpoint = fwnode_graph_get_next_endpoint(dev_fwnode(&client->dev),
-+                                              NULL);
-+      if (!endpoint) {
-+              dev_err(dev, "endpoint node not found\n");
-+              return -EINVAL;
-+      }
-+
-+      ret = v4l2_fwnode_endpoint_parse(endpoint, &sensor->ep);
-+      fwnode_handle_put(endpoint);
-+      if (ret) {
-+              dev_err(dev, "Could not parse endpoint\n");
-+              return ret;
-+      }
-+
-+      if (sensor->ep.bus_type != V4L2_MBUS_PARALLEL &&
-+              sensor->ep.bus_type != V4L2_MBUS_CSI2_DPHY &&
-+              sensor->ep.bus_type != V4L2_MBUS_BT656) {
-+              dev_err(dev, "Unsupported bus type %d\n", sensor->ep.bus_type);
-+              return -EINVAL;
-+      }
-+
-+      /* get system clock (xclk) */
-+      sensor->xclk = devm_clk_get(dev, "xclk");
-+      if (IS_ERR(sensor->xclk)) {
-+              dev_err(dev, "failed to get xclk\n");
-+              return PTR_ERR(sensor->xclk);
-+      }
-+
-+      sensor->xclk_freq = clk_get_rate(sensor->xclk);
-+      if (sensor->xclk_freq < OV13850_XCLK_MIN ||
-+              sensor->xclk_freq > OV13850_XCLK_MAX) {
-+              dev_err(dev, "xclk frequency out of range: %d Hz\n",
-+                      sensor->xclk_freq);
-+              return -EINVAL;
-+      }
-+
-+      /* request optional power down pin */
-+      sensor->pwdn_gpio = devm_gpiod_get_optional(dev, "powerdown",
-+                                              GPIOD_OUT_HIGH);
-+      if (IS_ERR(sensor->pwdn_gpio))
-+              return PTR_ERR(sensor->pwdn_gpio);
-+
-+      /* request optional reset pin */
-+      sensor->reset_gpio = devm_gpiod_get_optional(dev, "reset",
-+                                              GPIOD_OUT_HIGH);
-+      if (IS_ERR(sensor->reset_gpio))
-+              return PTR_ERR(sensor->reset_gpio);
-+
-+      v4l2_i2c_subdev_init(&sensor->sd, client, &ov13850_subdev_ops);
-+
-+      sensor->sd.flags |= V4L2_SUBDEV_FL_HAS_DEVNODE |
-+                      V4L2_SUBDEV_FL_HAS_EVENTS;
-+      sensor->pad.flags = MEDIA_PAD_FL_SOURCE;
-+      sensor->sd.entity.function = MEDIA_ENT_F_CAM_SENSOR;
-+      ret = media_entity_pads_init(&sensor->sd.entity, 1, &sensor->pad);
-+      if (ret)
-+              return ret;
-+
-+      ret = ov13850_get_regulators(sensor);
-+      if (ret)
-+              return ret;
-+
-+      mutex_init(&sensor->lock);
-+
-+      ret = ov13850_check_chip_id(sensor);
-+      if (ret)
-+              goto entity_cleanup;
-+
-+      ret = ov13850_init_controls(sensor);
-+      if (ret)
-+              goto entity_cleanup;
-+
-+      ret = v4l2_async_register_subdev_sensor(&sensor->sd);
-+      if (ret)
-+              goto free_ctrls;
-+
-+      return 0;
-+
-+free_ctrls:
-+      v4l2_ctrl_handler_free(&sensor->ctrls.handler);
-+entity_cleanup:
-+      media_entity_cleanup(&sensor->sd.entity);
-+      mutex_destroy(&sensor->lock);
-+      return ret;
-+}
-+
-+static int ov13850_remove(struct i2c_client *client)
-+{
-+      struct v4l2_subdev *sd = i2c_get_clientdata(client);
-+      struct ov13850_dev *sensor = to_ov13850_dev(sd);
-+
-+      v4l2_async_unregister_subdev(&sensor->sd);
-+      media_entity_cleanup(&sensor->sd.entity);
-+      v4l2_ctrl_handler_free(&sensor->ctrls.handler);
-+      mutex_destroy(&sensor->lock);
-+
-+      return 0;
-+}
-+
-+static const struct i2c_device_id ov13850_id[] = {
-+      {"ov13850", 0},
-+      {},
-+};
-+MODULE_DEVICE_TABLE(i2c, ov13850_id);
-+
-+static const struct of_device_id ov13850_dt_ids[] = {
-+      { .compatible = "ovti,ov13850" },
-+      { /* sentinel */ }
-+};
-+MODULE_DEVICE_TABLE(of, ov13850_dt_ids);
-+
-+static struct i2c_driver ov13850_i2c_driver = {
-+      .driver = {
-+              .name  = "ov13850",
-+              .of_match_table = ov13850_dt_ids,
-+      },
-+      .id_table = ov13850_id,
-+      .probe_new = ov13850_probe,
-+      .remove   = ov13850_remove,
-+};
-+
-+module_i2c_driver(ov13850_i2c_driver);
-+
-+MODULE_DESCRIPTION("OV13850 MIPI Camera Subdev Driver");
-+MODULE_LICENSE("GPL");
---- /dev/null
-+++ b/drivers/media/platform/starfive/v4l2_driver/ov4689_mipi.c
-@@ -0,0 +1,2975 @@
-+// SPDX-License-Identifier: GPL-2.0-or-later
-+/*
-+ * Copyright (C) 2021-2023 StarFive Technology Co., Ltd.
-+ *
-+ */
-+
-+#include <linux/clk.h>
-+#include <linux/clk-provider.h>
-+#include <linux/clkdev.h>
-+#include <linux/ctype.h>
-+#include <linux/delay.h>
-+#include <linux/device.h>
-+#include <linux/gpio/consumer.h>
-+#include <linux/i2c.h>
-+#include <linux/init.h>
-+#include <linux/module.h>
-+#include <linux/pm_runtime.h>
-+#include <linux/of_device.h>
-+#include <linux/regulator/consumer.h>
-+#include <linux/slab.h>
-+#include <linux/types.h>
-+#include <media/v4l2-async.h>
-+#include <media/v4l2-ctrls.h>
-+#include <media/v4l2-device.h>
-+#include <media/v4l2-event.h>
-+#include <media/v4l2-fwnode.h>
-+#include <media/v4l2-subdev.h>
-+#include "stfcamss.h"
-+
-+
-+#define OV4689_LANES    4
-+
-+#define OV4689_LINK_FREQ_500MHZ         500000000LL
-+
-+/* min/typical/max system clock (xclk) frequencies */
-+#define OV4689_XCLK_MIN  6000000
-+#define OV4689_XCLK_MAX 64000000
-+
-+#define OV4689_CHIP_ID        (0x4688)
-+
-+#define OV4689_CHIP_ID_HIGH_BYTE        0x300a   // max should be 0x46
-+#define OV4689_CHIP_ID_LOW_BYTE         0x300b   // max should be 0x88
-+#define OV4689_REG_CHIP_ID              0x300a
-+
-+#define OV4689_REG_H_OUTPUT_SIZE      0x3808
-+#define OV4689_REG_V_OUTPUT_SIZE      0x380a
-+#define OV4689_REG_TIMING_HTS         0x380c
-+#define OV4689_REG_TIMING_VTS         0x380e
-+
-+#define OV4689_REG_EXPOSURE_HI          0x3500
-+#define OV4689_REG_EXPOSURE_MED         0x3501
-+#define OV4689_REG_EXPOSURE_LO          0x3502
-+#define OV4689_REG_GAIN_H               0x3507
-+#define OV4689_REG_GAIN_M               0x3508
-+#define OV4689_REG_GAIN_L               0x3509
-+#define OV4689_REG_TEST_PATTERN         0x5040
-+#define OV4689_REG_TIMING_TC_REG20      0x3820
-+#define OV4689_REG_TIMING_TC_REG21      0x3821
-+
-+#define OV4689_REG_AWB_R_GAIN           0x500C
-+#define OV4689_REG_AWB_B_GAIN           0x5010
-+#define OV4689_REG_STREAM_ON            0x0100
-+
-+#define OV4689_REG_MIPI_SC_CTRL_HI    0x3018
-+#define OV4689_REG_MIPI_SC_CTRL_LOW   0x3019
-+
-+enum ov4689_mode_id {
-+      //OV4689_MODE_720P_1280_720 = 0,
-+      OV4689_MODE_1080P_1920_1080 = 0,
-+      //OV4689_MODE_4M_2688_1520,
-+      OV4689_NUM_MODES,
-+};
-+
-+enum ov4689_frame_rate {
-+      OV4689_15_FPS = 0,
-+      OV4689_30_FPS,
-+      OV4689_45_FPS,
-+      OV4689_60_FPS,
-+      OV4689_90_FPS,
-+      OV4689_120_FPS,
-+      OV4689_150_FPS,
-+      OV4689_180_FPS,
-+      OV4689_330_FPS,
-+      OV4689_NUM_FRAMERATES,
-+};
-+
-+enum ov4689_format_mux {
-+      OV4689_FMT_MUX_RAW,
-+};
-+
-+static const int ov4689_framerates[] = {
-+      [OV4689_15_FPS] = 15,
-+      [OV4689_30_FPS] = 30,
-+      [OV4689_45_FPS] = 45,
-+      [OV4689_60_FPS] = 60,
-+      [OV4689_90_FPS] = 90,
-+      [OV4689_120_FPS] = 120,
-+      [OV4689_150_FPS] = 150,
-+      [OV4689_180_FPS] = 180,
-+      [OV4689_330_FPS] = 330,
-+};
-+
-+/* regulator supplies */
-+static const char * const ov4689_supply_name[] = {
-+      "DOVDD", /* Digital I/O (1.8V) supply */
-+      "AVDD",  /* Analog (2.8V) supply */
-+      "DVDD",  /* Digital Core (1.5V) supply */
-+};
-+
-+#define OV4689_NUM_SUPPLIES ARRAY_SIZE(ov4689_supply_name)
-+
-+/*
-+ * Image size under 1280 * 960 are SUBSAMPLING
-+ * Image size upper 1280 * 960 are SCALING
-+ */
-+enum ov4689_downsize_mode {
-+      SUBSAMPLING,
-+      SCALING,
-+};
-+
-+struct reg_value {
-+      u16 reg_addr;
-+      u8 val;
-+      u8 mask;
-+      u32 delay_ms;
-+};
-+
-+struct ov4689_mode_info {
-+      enum ov4689_mode_id id;
-+      enum ov4689_downsize_mode dn_mode;
-+      u32 hact;
-+      u32 htot;
-+      u32 vact;
-+      u32 vtot;
-+      const struct reg_value *reg_data;
-+      u32 reg_data_size;
-+      u32 max_fps;
-+};
-+
-+struct ov4689_ctrls {
-+      struct v4l2_ctrl_handler handler;
-+      struct v4l2_ctrl *pixel_rate;
-+      struct {
-+              struct v4l2_ctrl *exposure;
-+      };
-+      struct {
-+              struct v4l2_ctrl *auto_wb;
-+              struct v4l2_ctrl *blue_balance;
-+              struct v4l2_ctrl *red_balance;
-+      };
-+      struct {
-+              struct v4l2_ctrl *anal_gain;
-+      };
-+      struct v4l2_ctrl *brightness;
-+      struct v4l2_ctrl *light_freq;
-+      struct v4l2_ctrl *link_freq;
-+      struct v4l2_ctrl *saturation;
-+      struct v4l2_ctrl *contrast;
-+      struct v4l2_ctrl *hue;
-+      struct v4l2_ctrl *test_pattern;
-+      struct v4l2_ctrl *hflip;
-+      struct v4l2_ctrl *vflip;
-+};
-+
-+struct ov4689_dev {
-+      struct i2c_client *i2c_client;
-+      struct v4l2_subdev sd;
-+      struct media_pad pad;
-+      struct v4l2_fwnode_endpoint ep; /* the parsed DT endpoint info */
-+      struct clk *xclk; /* system clock to OV4689 */
-+      u32 xclk_freq;
-+
-+      struct regulator_bulk_data supplies[OV4689_NUM_SUPPLIES];
-+      struct gpio_desc *reset_gpio;
-+      struct gpio_desc *pwdn_gpio;
-+      bool   upside_down;
-+
-+      /* lock to protect all members below */
-+      struct mutex lock;
-+
-+      struct v4l2_mbus_framefmt fmt;
-+
-+      const struct ov4689_mode_info *current_mode;
-+      const struct ov4689_mode_info *last_mode;
-+      enum ov4689_frame_rate current_fr;
-+      struct v4l2_fract frame_interval;
-+
-+      struct ov4689_ctrls ctrls;
-+
-+      bool pending_mode_change;
-+      int streaming;
-+};
-+
-+static inline struct ov4689_dev *to_ov4689_dev(struct v4l2_subdev *sd)
-+{
-+      return container_of(sd, struct ov4689_dev, sd);
-+}
-+
-+static inline struct v4l2_subdev *ctrl_to_sd(struct v4l2_ctrl *ctrl)
-+{
-+      return &container_of(ctrl->handler, struct ov4689_dev,
-+                      ctrls.handler)->sd;
-+}
-+
-+/* ov4689 initial register */
-+static const struct reg_value ov4689_init_setting_30fps_1080P[] = {
-+/* ov4689_1080p_30fps_4d */
-+      {0x0103, 0x01, 0, 0},
-+      {0x3638, 0x00, 0, 0},
-+      {0x0300, 0x02, 0, 0},
-+      {0x0302, 0x32, 0, 0},
-+      {0x0303, 0x00, 0, 0},
-+      {0x0304, 0x03, 0, 0},
-+      {0x030b, 0x00, 0, 0},
-+      {0x030d, 0x1e, 0, 0},
-+      {0x030e, 0x04, 0, 0},
-+      {0x030f, 0x01, 0, 0},
-+      {0x0312, 0x01, 0, 0},
-+      {0x031e, 0x00, 0, 0},
-+      {0x3000, 0x20, 0, 0},
-+      {0x3002, 0x00, 0, 0},
-+      {0x3020, 0x93, 0, 0},
-+      {0x3021, 0x03, 0, 0},
-+      {0x3022, 0x01, 0, 0},
-+      {0x3031, 0x0a, 0, 0},
-+      {0x3305, 0xf1, 0, 0},
-+      {0x3307, 0x04, 0, 0},
-+      {0x3309, 0x29, 0, 0},
-+      {0x3500, 0x00, 0, 0},
-+      {0x3501, 0x4c, 0, 0},
-+      {0x3502, 0x00, 0, 0},
-+      {0x3503, 0x04, 0, 0},
-+      {0x3504, 0x00, 0, 0},
-+      {0x3505, 0x00, 0, 0},
-+      {0x3506, 0x00, 0, 0},
-+      {0x3507, 0x00, 0, 0},
-+      {0x3508, 0x00, 0, 0},
-+      {0x3509, 0x80, 0, 0},
-+      {0x350a, 0x00, 0, 0},
-+      {0x350b, 0x00, 0, 0},
-+      {0x350c, 0x00, 0, 0},
-+      {0x350d, 0x00, 0, 0},
-+      {0x350e, 0x00, 0, 0},
-+      {0x350f, 0x80, 0, 0},
-+      {0x3510, 0x00, 0, 0},
-+      {0x3511, 0x00, 0, 0},
-+      {0x3512, 0x00, 0, 0},
-+      {0x3513, 0x00, 0, 0},
-+      {0x3514, 0x00, 0, 0},
-+      {0x3515, 0x80, 0, 0},
-+      {0x3516, 0x00, 0, 0},
-+      {0x3517, 0x00, 0, 0},
-+      {0x3518, 0x00, 0, 0},
-+      {0x3519, 0x00, 0, 0},
-+      {0x351a, 0x00, 0, 0},
-+      {0x351b, 0x80, 0, 0},
-+      {0x351c, 0x00, 0, 0},
-+      {0x351d, 0x00, 0, 0},
-+      {0x351e, 0x00, 0, 0},
-+      {0x351f, 0x00, 0, 0},
-+      {0x3520, 0x00, 0, 0},
-+      {0x3521, 0x80, 0, 0},
-+      {0x3522, 0x08, 0, 0},
-+      {0x3524, 0x08, 0, 0},
-+      {0x3526, 0x08, 0, 0},
-+      {0x3528, 0x08, 0, 0},
-+      {0x352a, 0x08, 0, 0},
-+      {0x3602, 0x00, 0, 0},
-+      {0x3603, 0x40, 0, 0},
-+      {0x3604, 0x02, 0, 0},
-+      {0x3605, 0x00, 0, 0},
-+      {0x3606, 0x00, 0, 0},
-+      {0x3607, 0x00, 0, 0},
-+      {0x3609, 0x12, 0, 0},
-+      {0x360a, 0x40, 0, 0},
-+      {0x360c, 0x08, 0, 0},
-+      {0x360f, 0xe5, 0, 0},
-+      {0x3608, 0x8f, 0, 0},
-+      {0x3611, 0x00, 0, 0},
-+      {0x3613, 0xf7, 0, 0},
-+      {0x3616, 0x58, 0, 0},
-+      {0x3619, 0x99, 0, 0},
-+      {0x361b, 0x60, 0, 0},
-+      {0x361c, 0x7a, 0, 0},
-+      {0x361e, 0x79, 0, 0},
-+      {0x361f, 0x02, 0, 0},
-+      {0x3632, 0x00, 0, 0},
-+      {0x3633, 0x10, 0, 0},
-+      {0x3634, 0x10, 0, 0},
-+      {0x3635, 0x10, 0, 0},
-+      {0x3636, 0x15, 0, 0},
-+      {0x3646, 0x86, 0, 0},
-+      {0x364a, 0x0b, 0, 0},
-+      {0x3700, 0x17, 0, 0},
-+      {0x3701, 0x22, 0, 0},
-+      {0x3703, 0x10, 0, 0},
-+      {0x370a, 0x37, 0, 0},
-+      {0x3705, 0x00, 0, 0},
-+      {0x3706, 0x63, 0, 0},
-+      {0x3709, 0x3c, 0, 0},
-+      {0x370b, 0x01, 0, 0},
-+      {0x370c, 0x30, 0, 0},
-+      {0x3710, 0x24, 0, 0},
-+      {0x3711, 0x0c, 0, 0},
-+      {0x3716, 0x00, 0, 0},
-+      {0x3720, 0x28, 0, 0},
-+      {0x3729, 0x7b, 0, 0},
-+      {0x372a, 0x84, 0, 0},
-+      {0x372b, 0xbd, 0, 0},
-+      {0x372c, 0xbc, 0, 0},
-+      {0x372e, 0x52, 0, 0},
-+      {0x373c, 0x0e, 0, 0},
-+      {0x373e, 0x33, 0, 0},
-+      {0x3743, 0x10, 0, 0},
-+      {0x3744, 0x88, 0, 0},
-+      {0x3745, 0xc0, 0, 0},
-+      {0x374a, 0x43, 0, 0},
-+      {0x374c, 0x00, 0, 0},
-+      {0x374e, 0x23, 0, 0},
-+      {0x3751, 0x7b, 0, 0},
-+      {0x3752, 0x84, 0, 0},
-+      {0x3753, 0xbd, 0, 0},
-+      {0x3754, 0xbc, 0, 0},
-+      {0x3756, 0x52, 0, 0},
-+      {0x375c, 0x00, 0, 0},
-+      {0x3760, 0x00, 0, 0},
-+      {0x3761, 0x00, 0, 0},
-+      {0x3762, 0x00, 0, 0},
-+      {0x3763, 0x00, 0, 0},
-+      {0x3764, 0x00, 0, 0},
-+      {0x3767, 0x04, 0, 0},
-+      {0x3768, 0x04, 0, 0},
-+      {0x3769, 0x08, 0, 0},
-+      {0x376a, 0x08, 0, 0},
-+      {0x376b, 0x20, 0, 0},
-+      {0x376c, 0x00, 0, 0},
-+      {0x376d, 0x00, 0, 0},
-+      {0x376e, 0x00, 0, 0},
-+      {0x3773, 0x00, 0, 0},
-+      {0x3774, 0x51, 0, 0},
-+      {0x3776, 0xbd, 0, 0},
-+      {0x3777, 0xbd, 0, 0},
-+      {0x3781, 0x18, 0, 0},
-+      {0x3783, 0x25, 0, 0},
-+      {0x3798, 0x1b, 0, 0},
-+      {0x3800, 0x01, 0, 0},
-+      {0x3801, 0x88, 0, 0},
-+      {0x3802, 0x00, 0, 0},
-+      {0x3803, 0xe0, 0, 0},
-+      {0x3804, 0x09, 0, 0},
-+      {0x3805, 0x17, 0, 0},
-+      {0x3806, 0x05, 0, 0},
-+      {0x3807, 0x1f, 0, 0},
-+      {0x3808, 0x07, 0, 0},
-+      {0x3809, 0x80, 0, 0},
-+      {0x380a, 0x04, 0, 0},
-+      {0x380b, 0x38, 0, 0},
-+      {0x380c, 0x0d, 0, 0},
-+      {0x380d, 0x70, 0, 0},
-+      {0x380e, 0x04, 0, 0},
-+      {0x380f, 0x8A, 0, 0},
-+      {0x3810, 0x00, 0, 0},
-+      {0x3811, 0x08, 0, 0},
-+      {0x3812, 0x00, 0, 0},
-+      {0x3813, 0x04, 0, 0},
-+      {0x3814, 0x01, 0, 0},
-+      {0x3815, 0x01, 0, 0},
-+      {0x3819, 0x01, 0, 0},
-+      {0x3820, 0x06, 0, 0},
-+      {0x3821, 0x00, 0, 0},
-+      {0x3829, 0x00, 0, 0},
-+      {0x382a, 0x01, 0, 0},
-+      {0x382b, 0x01, 0, 0},
-+      {0x382d, 0x7f, 0, 0},
-+      {0x3830, 0x04, 0, 0},
-+      {0x3836, 0x01, 0, 0},
-+      {0x3837, 0x00, 0, 0},
-+      {0x3841, 0x02, 0, 0},
-+      {0x3846, 0x08, 0, 0},
-+      {0x3847, 0x07, 0, 0},
-+      {0x3d85, 0x36, 0, 0},
-+      {0x3d8c, 0x71, 0, 0},
-+      {0x3d8d, 0xcb, 0, 0},
-+      {0x3f0a, 0x00, 0, 0},
-+      {0x4000, 0xf1, 0, 0},
-+      {0x4001, 0x40, 0, 0},
-+      {0x4002, 0x04, 0, 0},
-+      {0x4003, 0x14, 0, 0},
-+      {0x400e, 0x00, 0, 0},
-+      {0x4011, 0x00, 0, 0},
-+      {0x401a, 0x00, 0, 0},
-+      {0x401b, 0x00, 0, 0},
-+      {0x401c, 0x00, 0, 0},
-+      {0x401d, 0x00, 0, 0},
-+      {0x401f, 0x00, 0, 0},
-+      {0x4020, 0x00, 0, 0},
-+      {0x4021, 0x10, 0, 0},
-+      {0x4022, 0x06, 0, 0},
-+      {0x4023, 0x13, 0, 0},
-+      {0x4024, 0x07, 0, 0},
-+      {0x4025, 0x40, 0, 0},
-+      {0x4026, 0x07, 0, 0},
-+      {0x4027, 0x50, 0, 0},
-+      {0x4028, 0x00, 0, 0},
-+      {0x4029, 0x02, 0, 0},
-+      {0x402a, 0x06, 0, 0},
-+      {0x402b, 0x04, 0, 0},
-+      {0x402c, 0x02, 0, 0},
-+      {0x402d, 0x02, 0, 0},
-+      {0x402e, 0x0e, 0, 0},
-+      {0x402f, 0x04, 0, 0},
-+      {0x4302, 0xff, 0, 0},
-+      {0x4303, 0xff, 0, 0},
-+      {0x4304, 0x00, 0, 0},
-+      {0x4305, 0x00, 0, 0},
-+      {0x4306, 0x00, 0, 0},
-+      {0x4308, 0x02, 0, 0},
-+      {0x4500, 0x6c, 0, 0},
-+      {0x4501, 0xc4, 0, 0},
-+      {0x4502, 0x40, 0, 0},
-+      {0x4503, 0x01, 0, 0},
-+      {0x4601, 0x77, 0, 0},
-+      {0x4800, 0x04, 0, 0},
-+      {0x4813, 0x08, 0, 0},
-+      {0x481f, 0x40, 0, 0},
-+      {0x4829, 0x78, 0, 0},
-+      {0x4837, 0x10, 0, 0},
-+      {0x4b00, 0x2a, 0, 0},
-+      {0x4b0d, 0x00, 0, 0},
-+      {0x4d00, 0x04, 0, 0},
-+      {0x4d01, 0x42, 0, 0},
-+      {0x4d02, 0xd1, 0, 0},
-+      {0x4d03, 0x93, 0, 0},
-+      {0x4d04, 0xf5, 0, 0},
-+      {0x4d05, 0xc1, 0, 0},
-+      {0x5000, 0xf3, 0, 0},
-+      {0x5001, 0x11, 0, 0},
-+      {0x5004, 0x00, 0, 0},
-+      {0x500a, 0x00, 0, 0},
-+      {0x500b, 0x00, 0, 0},
-+      {0x5032, 0x00, 0, 0},
-+      {0x5040, 0x00, 0, 0},
-+      {0x5050, 0x0c, 0, 0},
-+      {0x5500, 0x00, 0, 0},
-+      {0x5501, 0x10, 0, 0},
-+      {0x5502, 0x01, 0, 0},
-+      {0x5503, 0x0f, 0, 0},
-+      {0x8000, 0x00, 0, 0},
-+      {0x8001, 0x00, 0, 0},
-+      {0x8002, 0x00, 0, 0},
-+      {0x8003, 0x00, 0, 0},
-+      {0x8004, 0x00, 0, 0},
-+      {0x8005, 0x00, 0, 0},
-+      {0x8006, 0x00, 0, 0},
-+      {0x8007, 0x00, 0, 0},
-+      {0x8008, 0x00, 0, 0},
-+      {0x3638, 0x00, 0, 0},
-+};
-+
-+static const struct reg_value ov4689_setting_VGA_640_480[] = {
-+      //@@ RES_640x480_2x_Bin_330fps_816Mbps
-+      //OV4689_AM01B_640x480_24M_2lane_816Mbps_330fps_20140210.txt
-+      {0x0103, 0x01, 0, 0},
-+      {0x3638, 0x00, 0, 0},
-+      {0x0300, 0x00, 0, 0}, // 00
-+      {0x0302, 0x22, 0, 0}, // 816Mbps 5a ; 64 ; 5a ; 78  ; 78 ; 2a
-+      {0x0303, 0x00, 0, 0}, // 03 ; 01 ; 02 ;
-+      {0x0304, 0x03, 0, 0},
-+      {0x030b, 0x00, 0, 0},
-+      {0x030d, 0x1e, 0, 0},
-+      {0x030e, 0x04, 0, 0},
-+      {0x030f, 0x01, 0, 0},
-+      {0x0312, 0x01, 0, 0},
-+      {0x031e, 0x00, 0, 0},
-+      {0x3000, 0x20, 0, 0},
-+      {0x3002, 0x00, 0, 0},
-+      {0x3020, 0x93, 0, 0},
-+      {0x3021, 0x03, 0, 0},
-+      {0x3022, 0x01, 0, 0},
-+      {0x3031, 0x0a, 0, 0},
-+      {0x303f, 0x0c, 0, 0},
-+      {0x3305, 0xf1, 0, 0},
-+      {0x3307, 0x04, 0, 0},
-+      {0x3309, 0x29, 0, 0},
-+      {0x3500, 0x00, 0, 0},
-+      {0x3501, 0x4c, 0, 0},
-+      {0x3502, 0x00, 0, 0},
-+      {0x3503, 0x04, 0, 0},
-+      {0x3504, 0x00, 0, 0},
-+      {0x3505, 0x00, 0, 0},
-+      {0x3506, 0x00, 0, 0},
-+      {0x3507, 0x00, 0, 0},
-+      {0x3508, 0x00, 0, 0},
-+      {0x3509, 0x80, 0, 0}, // 8X
-+      {0x350a, 0x00, 0, 0},
-+      {0x350b, 0x00, 0, 0},
-+      {0x350c, 0x00, 0, 0},
-+      {0x350d, 0x00, 0, 0},
-+      {0x350e, 0x00, 0, 0},
-+      {0x350f, 0x80, 0, 0},
-+      {0x3510, 0x00, 0, 0},
-+      {0x3511, 0x00, 0, 0},
-+      {0x3512, 0x00, 0, 0},
-+      {0x3513, 0x00, 0, 0},
-+      {0x3514, 0x00, 0, 0},
-+      {0x3515, 0x80, 0, 0},
-+      {0x3516, 0x00, 0, 0},
-+      {0x3517, 0x00, 0, 0},
-+      {0x3518, 0x00, 0, 0},
-+      {0x3519, 0x00, 0, 0},
-+      {0x351a, 0x00, 0, 0},
-+      {0x351b, 0x80, 0, 0},
-+      {0x351c, 0x00, 0, 0},
-+      {0x351d, 0x00, 0, 0},
-+      {0x351e, 0x00, 0, 0},
-+      {0x351f, 0x00, 0, 0},
-+      {0x3520, 0x00, 0, 0},
-+      {0x3521, 0x80, 0, 0},
-+      {0x3522, 0x08, 0, 0},
-+      {0x3524, 0x08, 0, 0},
-+      {0x3526, 0x08, 0, 0},
-+      {0x3528, 0x08, 0, 0},
-+      {0x352a, 0x08, 0, 0},
-+      {0x3602, 0x00, 0, 0},
-+      {0x3603, 0x40, 0, 0},
-+      {0x3604, 0x02, 0, 0},
-+      {0x3605, 0x00, 0, 0},
-+      {0x3606, 0x00, 0, 0},
-+      {0x3607, 0x00, 0, 0},
-+      {0x3609, 0x12, 0, 0},
-+      {0x360a, 0x40, 0, 0},
-+      {0x360c, 0x08, 0, 0},
-+      {0x360f, 0xe5, 0, 0},
-+      {0x3608, 0x8f, 0, 0},
-+      {0x3611, 0x00, 0, 0},
-+      {0x3613, 0xf7, 0, 0},
-+      {0x3616, 0x58, 0, 0},
-+      {0x3619, 0x99, 0, 0},
-+      {0x361b, 0x60, 0, 0},
-+      {0x361c, 0x7a, 0, 0},
-+      {0x361e, 0x79, 0, 0},
-+      {0x361f, 0x02, 0, 0},
-+      {0x3632, 0x05, 0, 0},
-+      {0x3633, 0x10, 0, 0},
-+      {0x3634, 0x10, 0, 0},
-+      {0x3635, 0x10, 0, 0},
-+      {0x3636, 0x15, 0, 0},
-+      {0x3646, 0x86, 0, 0},
-+      {0x364a, 0x0b, 0, 0},
-+      {0x3700, 0x17, 0, 0},
-+      {0x3701, 0x22, 0, 0},
-+      {0x3703, 0x10, 0, 0},
-+      {0x370a, 0x37, 0, 0},
-+      {0x3705, 0x00, 0, 0},
-+      {0x3706, 0x63, 0, 0},
-+      {0x3709, 0x3c, 0, 0},
-+      {0x370b, 0x01, 0, 0},
-+      {0x370c, 0x30, 0, 0},
-+      {0x3710, 0x24, 0, 0},
-+      {0x3711, 0x0c, 0, 0},
-+      {0x3716, 0x00, 0, 0},
-+      {0x3720, 0x28, 0, 0},
-+      {0x3729, 0x7b, 0, 0},
-+      {0x372a, 0x84, 0, 0},
-+      {0x372b, 0xbd, 0, 0},
-+      {0x372c, 0xbc, 0, 0},
-+      {0x372e, 0x52, 0, 0},
-+      {0x373c, 0x0e, 0, 0},
-+      {0x373e, 0x33, 0, 0},
-+      {0x3743, 0x10, 0, 0},
-+      {0x3744, 0x88, 0, 0},
-+      {0x3745, 0xc0, 0, 0},
-+      {0x374a, 0x43, 0, 0},
-+      {0x374c, 0x00, 0, 0},
-+      {0x374e, 0x23, 0, 0},
-+      {0x3751, 0x7b, 0, 0},
-+      {0x3752, 0x84, 0, 0},
-+      {0x3753, 0xbd, 0, 0},
-+      {0x3754, 0xbc, 0, 0},
-+      {0x3756, 0x52, 0, 0},
-+      {0x375c, 0x00, 0, 0},
-+      {0x3760, 0x00, 0, 0},
-+      {0x3761, 0x00, 0, 0},
-+      {0x3762, 0x00, 0, 0},
-+      {0x3763, 0x00, 0, 0},
-+      {0x3764, 0x00, 0, 0},
-+      {0x3767, 0x04, 0, 0},
-+      {0x3768, 0x04, 0, 0},
-+      {0x3769, 0x08, 0, 0},
-+      {0x376a, 0x08, 0, 0},
-+      {0x376b, 0x40, 0, 0},
-+      {0x376c, 0x00, 0, 0},
-+      {0x376d, 0x00, 0, 0},
-+      {0x376e, 0x00, 0, 0},
-+      {0x3773, 0x00, 0, 0},
-+      {0x3774, 0x51, 0, 0},
-+      {0x3776, 0xbd, 0, 0},
-+      {0x3777, 0xbd, 0, 0},
-+      {0x3781, 0x18, 0, 0},
-+      {0x3783, 0x25, 0, 0},
-+      {0x3798, 0x1b, 0, 0},
-+      {0x3800, 0x00, 0, 0},
-+      {0x3801, 0x48, 0, 0},
-+      {0x3802, 0x00, 0, 0},
-+      {0x3803, 0x2C, 0, 0},
-+      {0x3804, 0x0a, 0, 0},
-+      {0x3805, 0x57, 0, 0},
-+      {0x3806, 0x05, 0, 0},
-+      {0x3807, 0xD3, 0, 0},
-+      {0x3808, 0x02, 0, 0},
-+      {0x3809, 0x80, 0, 0},
-+      {0x380a, 0x01, 0, 0},
-+      {0x380b, 0xe0, 0, 0},
-+
-+      {0x380c, 0x02, 0, 0}, // 0a ; 03
-+      {0x380d, 0x04, 0, 0}, // 1c ; 5C
-+
-+      {0x380e, 0x03, 0, 0},
-+      {0x380f, 0x05, 0, 0},
-+      {0x3810, 0x00, 0, 0},
-+      {0x3811, 0x04, 0, 0},
-+      {0x3812, 0x00, 0, 0},
-+      {0x3813, 0x02, 0, 0},
-+      {0x3814, 0x03, 0, 0},
-+      {0x3815, 0x01, 0, 0},
-+      {0x3819, 0x01, 0, 0},
-+      {0x3820, 0x06, 0, 0},
-+      {0x3821, 0x00, 0, 0},
-+      {0x3829, 0x00, 0, 0},
-+      {0x382a, 0x03, 0, 0},
-+      {0x382b, 0x01, 0, 0},
-+      {0x382d, 0x7f, 0, 0},
-+      {0x3830, 0x08, 0, 0},
-+      {0x3836, 0x02, 0, 0},
-+      {0x3837, 0x00, 0, 0},
-+      {0x3841, 0x02, 0, 0},
-+      {0x3846, 0x08, 0, 0},
-+      {0x3847, 0x07, 0, 0},
-+      {0x3d85, 0x36, 0, 0},
-+      {0x3d8c, 0x71, 0, 0},
-+      {0x3d8d, 0xcb, 0, 0},
-+      {0x3f0a, 0x00, 0, 0},
-+      {0x4000, 0x71, 0, 0},
-+      {0x4001, 0x50, 0, 0},
-+      {0x4002, 0x04, 0, 0},
-+      {0x4003, 0x14, 0, 0},
-+      {0x400e, 0x00, 0, 0},
-+      {0x4011, 0x00, 0, 0},
-+      {0x401a, 0x00, 0, 0},
-+      {0x401b, 0x00, 0, 0},
-+      {0x401c, 0x00, 0, 0},
-+      {0x401d, 0x00, 0, 0},
-+      {0x401f, 0x00, 0, 0},
-+      {0x4020, 0x00, 0, 0},
-+      {0x4021, 0x10, 0, 0},
-+      {0x4022, 0x03, 0, 0},
-+      {0x4023, 0x93, 0, 0},
-+      {0x4024, 0x04, 0, 0},
-+      {0x4025, 0xC0, 0, 0},
-+      {0x4026, 0x04, 0, 0},
-+      {0x4027, 0xD0, 0, 0},
-+      {0x4028, 0x00, 0, 0},
-+      {0x4029, 0x02, 0, 0},
-+      {0x402a, 0x06, 0, 0},
-+      {0x402b, 0x04, 0, 0},
-+      {0x402c, 0x02, 0, 0},
-+      {0x402d, 0x02, 0, 0},
-+      {0x402e, 0x0e, 0, 0},
-+      {0x402f, 0x04, 0, 0},
-+      {0x4302, 0xff, 0, 0},
-+      {0x4303, 0xff, 0, 0},
-+      {0x4304, 0x00, 0, 0},
-+      {0x4305, 0x00, 0, 0},
-+      {0x4306, 0x00, 0, 0},
-+      {0x4308, 0x02, 0, 0},
-+      {0x4500, 0x6c, 0, 0},
-+      {0x4501, 0xc4, 0, 0},
-+      {0x4502, 0x44, 0, 0},
-+      {0x4503, 0x01, 0, 0},
-+      {0x4600, 0x00, 0, 0},
-+      {0x4601, 0x4F, 0, 0},
-+      {0x4800, 0x04, 0, 0},
-+      {0x4813, 0x08, 0, 0},
-+      {0x481f, 0x40, 0, 0},
-+      {0x4829, 0x78, 0, 0},
-+      {0x4837, 0x10, 0, 0}, // 20 ; 10
-+      {0x4b00, 0x2a, 0, 0},
-+      {0x4b0d, 0x00, 0, 0},
-+      {0x4d00, 0x04, 0, 0},
-+      {0x4d01, 0x42, 0, 0},
-+      {0x4d02, 0xd1, 0, 0},
-+      {0x4d03, 0x93, 0, 0},
-+      {0x4d04, 0xf5, 0, 0},
-+      {0x4d05, 0xc1, 0, 0},
-+      {0x5000, 0xf3, 0, 0},
-+      {0x5001, 0x11, 0, 0},
-+      {0x5004, 0x00, 0, 0},
-+      {0x500a, 0x00, 0, 0},
-+      {0x500b, 0x00, 0, 0},
-+      {0x5032, 0x00, 0, 0},
-+      {0x5040, 0x00, 0, 0},
-+      {0x5050, 0x3c, 0, 0},
-+      {0x5500, 0x00, 0, 0},
-+      {0x5501, 0x10, 0, 0},
-+      {0x5502, 0x01, 0, 0},
-+      {0x5503, 0x0f, 0, 0},
-+      {0x8000, 0x00, 0, 0},
-+      {0x8001, 0x00, 0, 0},
-+      {0x8002, 0x00, 0, 0},
-+      {0x8003, 0x00, 0, 0},
-+      {0x8004, 0x00, 0, 0},
-+      {0x8005, 0x00, 0, 0},
-+      {0x8006, 0x00, 0, 0},
-+      {0x8007, 0x00, 0, 0},
-+      {0x8008, 0x00, 0, 0},
-+      {0x3638, 0x00, 0, 0},
-+};
-+
-+static const struct reg_value ov4689_setting_720P_1280_720[] = {
-+      //@@ RES_1280x720_2x_Bin_150fps_816Mbps
-+      //OV4689_AM01B_1280x720_24M_2lane_816Mbps_150fps_20140210.txt
-+      {0x0103, 0x01, 0, 0},
-+      {0x3638, 0x00, 0, 0},
-+      {0x0300, 0x00, 0, 0}, // 00
-+      {0x0302, 0x22, 0, 0}, // 816Mbps 5a ; 64 ; 5a ; 78  ; 78 ; 2a
-+      {0x0303, 0x00, 0, 0}, // 03 ; 01 ; 02 ;
-+      {0x0304, 0x03, 0, 0},
-+      {0x030b, 0x00, 0, 0},
-+      {0x030d, 0x1e, 0, 0},
-+      {0x030e, 0x04, 0, 0},
-+      {0x030f, 0x01, 0, 0},
-+      {0x0312, 0x01, 0, 0},
-+      {0x031e, 0x00, 0, 0},
-+      {0x3000, 0x20, 0, 0},
-+      {0x3002, 0x00, 0, 0},
-+      {0x3020, 0x93, 0, 0},
-+      {0x3021, 0x03, 0, 0},
-+      {0x3022, 0x01, 0, 0},
-+      {0x3031, 0x0a, 0, 0},
-+      {0x303f, 0x0c, 0, 0},
-+      {0x3305, 0xf1, 0, 0},
-+      {0x3307, 0x04, 0, 0},
-+      {0x3309, 0x29, 0, 0},
-+      {0x3500, 0x00, 0, 0},
-+      {0x3501, 0x30, 0, 0},
-+      {0x3502, 0x00, 0, 0},
-+      {0x3503, 0x04, 0, 0},
-+      {0x3504, 0x00, 0, 0},
-+      {0x3505, 0x00, 0, 0},
-+      {0x3506, 0x00, 0, 0},
-+      {0x3507, 0x00, 0, 0},
-+      {0x3508, 0x07, 0, 0},
-+      {0x3509, 0x78, 0, 0}, // 8X
-+      {0x350a, 0x00, 0, 0},
-+      {0x350b, 0x00, 0, 0},
-+      {0x350c, 0x00, 0, 0},
-+      {0x350d, 0x00, 0, 0},
-+      {0x350e, 0x00, 0, 0},
-+      {0x350f, 0x80, 0, 0},
-+      {0x3510, 0x00, 0, 0},
-+      {0x3511, 0x00, 0, 0},
-+      {0x3512, 0x00, 0, 0},
-+      {0x3513, 0x00, 0, 0},
-+      {0x3514, 0x00, 0, 0},
-+      {0x3515, 0x80, 0, 0},
-+      {0x3516, 0x00, 0, 0},
-+      {0x3517, 0x00, 0, 0},
-+      {0x3518, 0x00, 0, 0},
-+      {0x3519, 0x00, 0, 0},
-+      {0x351a, 0x00, 0, 0},
-+      {0x351b, 0x80, 0, 0},
-+      {0x351c, 0x00, 0, 0},
-+      {0x351d, 0x00, 0, 0},
-+      {0x351e, 0x00, 0, 0},
-+      {0x351f, 0x00, 0, 0},
-+      {0x3520, 0x00, 0, 0},
-+      {0x3521, 0x80, 0, 0},
-+      {0x3522, 0x08, 0, 0},
-+      {0x3524, 0x08, 0, 0},
-+      {0x3526, 0x08, 0, 0},
-+      {0x3528, 0x08, 0, 0},
-+      {0x352a, 0x08, 0, 0},
-+      {0x3602, 0x00, 0, 0},
-+      {0x3603, 0x40, 0, 0},
-+      {0x3604, 0x02, 0, 0},
-+      {0x3605, 0x00, 0, 0},
-+      {0x3606, 0x00, 0, 0},
-+      {0x3607, 0x00, 0, 0},
-+      {0x3609, 0x12, 0, 0},
-+      {0x360a, 0x40, 0, 0},
-+      {0x360c, 0x08, 0, 0},
-+      {0x360f, 0xe5, 0, 0},
-+      {0x3608, 0x8f, 0, 0},
-+      {0x3611, 0x00, 0, 0},
-+      {0x3613, 0xf7, 0, 0},
-+      {0x3616, 0x58, 0, 0},
-+      {0x3619, 0x99, 0, 0},
-+      {0x361b, 0x60, 0, 0},
-+      {0x361c, 0x7a, 0, 0},
-+      {0x361e, 0x79, 0, 0},
-+      {0x361f, 0x02, 0, 0},
-+      {0x3632, 0x05, 0, 0},
-+      {0x3633, 0x10, 0, 0},
-+      {0x3634, 0x10, 0, 0},
-+      {0x3635, 0x10, 0, 0},
-+      {0x3636, 0x15, 0, 0},
-+      {0x3646, 0x86, 0, 0},
-+      {0x364a, 0x0b, 0, 0},
-+      {0x3700, 0x17, 0, 0},
-+      {0x3701, 0x22, 0, 0},
-+      {0x3703, 0x10, 0, 0},
-+      {0x370a, 0x37, 0, 0},
-+      {0x3705, 0x00, 0, 0},
-+      {0x3706, 0x63, 0, 0},
-+      {0x3709, 0x3c, 0, 0},
-+      {0x370b, 0x01, 0, 0},
-+      {0x370c, 0x30, 0, 0},
-+      {0x3710, 0x24, 0, 0},
-+      {0x3711, 0x0c, 0, 0},
-+      {0x3716, 0x00, 0, 0},
-+      {0x3720, 0x28, 0, 0},
-+      {0x3729, 0x7b, 0, 0},
-+      {0x372a, 0x84, 0, 0},
-+      {0x372b, 0xbd, 0, 0},
-+      {0x372c, 0xbc, 0, 0},
-+      {0x372e, 0x52, 0, 0},
-+      {0x373c, 0x0e, 0, 0},
-+      {0x373e, 0x33, 0, 0},
-+      {0x3743, 0x10, 0, 0},
-+      {0x3744, 0x88, 0, 0},
-+      {0x3745, 0xc0, 0, 0},
-+      {0x374a, 0x43, 0, 0},
-+      {0x374c, 0x00, 0, 0},
-+      {0x374e, 0x23, 0, 0},
-+      {0x3751, 0x7b, 0, 0},
-+      {0x3752, 0x84, 0, 0},
-+      {0x3753, 0xbd, 0, 0},
-+      {0x3754, 0xbc, 0, 0},
-+      {0x3756, 0x52, 0, 0},
-+      {0x375c, 0x00, 0, 0},
-+      {0x3760, 0x00, 0, 0},
-+      {0x3761, 0x00, 0, 0},
-+      {0x3762, 0x00, 0, 0},
-+      {0x3763, 0x00, 0, 0},
-+      {0x3764, 0x00, 0, 0},
-+      {0x3767, 0x04, 0, 0},
-+      {0x3768, 0x04, 0, 0},
-+      {0x3769, 0x08, 0, 0},
-+      {0x376a, 0x08, 0, 0},
-+      {0x376b, 0x40, 0, 0},
-+      {0x376c, 0x00, 0, 0},
-+      {0x376d, 0x00, 0, 0},
-+      {0x376e, 0x00, 0, 0},
-+      {0x3773, 0x00, 0, 0},
-+      {0x3774, 0x51, 0, 0},
-+      {0x3776, 0xbd, 0, 0},
-+      {0x3777, 0xbd, 0, 0},
-+      {0x3781, 0x18, 0, 0},
-+      {0x3783, 0x25, 0, 0},
-+      {0x3798, 0x1b, 0, 0},
-+      {0x3800, 0x00, 0, 0},
-+      {0x3801, 0x48, 0, 0},
-+      {0x3802, 0x00, 0, 0},
-+      {0x3803, 0x2C, 0, 0},
-+      {0x3804, 0x0a, 0, 0},
-+      {0x3805, 0x57, 0, 0},
-+      {0x3806, 0x05, 0, 0},
-+      {0x3807, 0xD3, 0, 0},
-+      {0x3808, 0x05, 0, 0},
-+      {0x3809, 0x00, 0, 0},
-+      {0x380a, 0x02, 0, 0},
-+      {0x380b, 0xD0, 0, 0},
-+#ifndef UNUSED_CODE
-+      {0x380c, 0x04, 0, 0}, // 0a ; 03
-+      {0x380d, 0x08, 0, 0}, // 1c ; 5C
-+#else
-+      {0x380c, 0x05, 0, 0}, // 120fps
-+      {0x380d, 0x0A, 0, 0},
-+#endif
-+      {0x380e, 0x03, 0, 0},
-+      {0x380f, 0x05, 0, 0},
-+      {0x3810, 0x00, 0, 0},
-+      {0x3811, 0x04, 0, 0},
-+      {0x3812, 0x00, 0, 0},
-+      {0x3813, 0x02, 0, 0},
-+      {0x3814, 0x03, 0, 0},
-+      {0x3815, 0x01, 0, 0},
-+      {0x3819, 0x01, 0, 0},
-+      {0x3820, 0x06, 0, 0},
-+      {0x3821, 0x00, 0, 0},
-+      {0x3829, 0x00, 0, 0},
-+      {0x382a, 0x03, 0, 0},
-+      {0x382b, 0x01, 0, 0},
-+      {0x382d, 0x7f, 0, 0},
-+      {0x3830, 0x08, 0, 0},
-+      {0x3836, 0x02, 0, 0},
-+      {0x3837, 0x00, 0, 0},
-+      {0x3841, 0x02, 0, 0},
-+      {0x3846, 0x08, 0, 0},
-+      {0x3847, 0x07, 0, 0},
-+      {0x3d85, 0x36, 0, 0},
-+      {0x3d8c, 0x71, 0, 0},
-+      {0x3d8d, 0xcb, 0, 0},
-+      {0x3f0a, 0x00, 0, 0},
-+      {0x4000, 0x71, 0, 0},
-+      {0x4001, 0x50, 0, 0},
-+      {0x4002, 0x04, 0, 0},
-+      {0x4003, 0x14, 0, 0},
-+      {0x400e, 0x00, 0, 0},
-+      {0x4011, 0x00, 0, 0},
-+      {0x401a, 0x00, 0, 0},
-+      {0x401b, 0x00, 0, 0},
-+      {0x401c, 0x00, 0, 0},
-+      {0x401d, 0x00, 0, 0},
-+      {0x401f, 0x00, 0, 0},
-+      {0x4020, 0x00, 0, 0},
-+      {0x4021, 0x10, 0, 0},
-+      {0x4022, 0x03, 0, 0},
-+      {0x4023, 0x93, 0, 0},
-+      {0x4024, 0x04, 0, 0},
-+      {0x4025, 0xC0, 0, 0},
-+      {0x4026, 0x04, 0, 0},
-+      {0x4027, 0xD0, 0, 0},
-+      {0x4028, 0x00, 0, 0},
-+      {0x4029, 0x02, 0, 0},
-+      {0x402a, 0x06, 0, 0},
-+      {0x402b, 0x04, 0, 0},
-+      {0x402c, 0x02, 0, 0},
-+      {0x402d, 0x02, 0, 0},
-+      {0x402e, 0x0e, 0, 0},
-+      {0x402f, 0x04, 0, 0},
-+      {0x4302, 0xff, 0, 0},
-+      {0x4303, 0xff, 0, 0},
-+      {0x4304, 0x00, 0, 0},
-+      {0x4305, 0x00, 0, 0},
-+      {0x4306, 0x00, 0, 0},
-+      {0x4308, 0x02, 0, 0},
-+      {0x4500, 0x6c, 0, 0},
-+      {0x4501, 0xc4, 0, 0},
-+      {0x4502, 0x44, 0, 0},
-+      {0x4503, 0x01, 0, 0},
-+      {0x4600, 0x00, 0, 0},
-+      {0x4601, 0x4F, 0, 0},
-+      {0x4800, 0x04, 0, 0},
-+      {0x4813, 0x08, 0, 0},
-+      {0x481f, 0x40, 0, 0},
-+      {0x4829, 0x78, 0, 0},
-+      {0x4837, 0x10, 0, 0}, // 20 ; 10
-+      {0x4b00, 0x2a, 0, 0},
-+      {0x4b0d, 0x00, 0, 0},
-+      {0x4d00, 0x04, 0, 0},
-+      {0x4d01, 0x42, 0, 0},
-+      {0x4d02, 0xd1, 0, 0},
-+      {0x4d03, 0x93, 0, 0},
-+      {0x4d04, 0xf5, 0, 0},
-+      {0x4d05, 0xc1, 0, 0},
-+      {0x5000, 0xf3, 0, 0},
-+      {0x5001, 0x11, 0, 0},
-+      {0x5004, 0x00, 0, 0},
-+      {0x500a, 0x00, 0, 0},
-+      {0x500b, 0x00, 0, 0},
-+      {0x5032, 0x00, 0, 0},
-+      {0x5040, 0x00, 0, 0},
-+      {0x5050, 0x3c, 0, 0},
-+      {0x5500, 0x00, 0, 0},
-+      {0x5501, 0x10, 0, 0},
-+      {0x5502, 0x01, 0, 0},
-+      {0x5503, 0x0f, 0, 0},
-+      {0x8000, 0x00, 0, 0},
-+      {0x8001, 0x00, 0, 0},
-+      {0x8002, 0x00, 0, 0},
-+      {0x8003, 0x00, 0, 0},
-+      {0x8004, 0x00, 0, 0},
-+      {0x8005, 0x00, 0, 0},
-+      {0x8006, 0x00, 0, 0},
-+      {0x8007, 0x00, 0, 0},
-+      {0x8008, 0x00, 0, 0},
-+      {0x3638, 0x00, 0, 0},
-+};
-+
-+static const struct reg_value ov4689_setting_1080P_1920_1080[] = {
-+      //@@ RES_1920x1080_60fps_816Mbps 2lanes
-+      {0x0103, 0x01, 0, 0},
-+      {0x3638, 0x00, 0, 0},
-+      {0x0300, 0x00, 0, 0},  // clk
-+      {0x0302, 0x22, 0, 0},
-+      {0x0303, 0x00, 0, 0},
-+      {0x0304, 0x03, 0, 0},
-+      {0x030b, 0x00, 0, 0},
-+      {0x030d, 0x1e, 0, 0},
-+      {0x030e, 0x04, 0, 0},
-+      {0x030f, 0x01, 0, 0},
-+      {0x0312, 0x01, 0, 0},
-+      {0x031e, 0x00, 0, 0},
-+      {0x3000, 0x20, 0, 0},
-+      {0x3002, 0x00, 0, 0},
-+      {0x3020, 0x93, 0, 0},
-+      {0x3021, 0x03, 0, 0},
-+      {0x3022, 0x01, 0, 0},
-+      {0x3031, 0x0a, 0, 0},
-+      {0x303f, 0x0c, 0, 0},
-+      {0x3305, 0xf1, 0, 0},
-+      {0x3307, 0x04, 0, 0},
-+      {0x3309, 0x29, 0, 0},
-+      {0x3500, 0x00, 0, 0},  // AEC
-+      {0x3501, 0x4c, 0, 0},
-+      {0x3502, 0x00, 0, 0},
-+      {0x3503, 0x04, 0, 0},
-+      {0x3504, 0x00, 0, 0},
-+      {0x3505, 0x00, 0, 0},
-+      {0x3506, 0x00, 0, 0},
-+      {0x3507, 0x00, 0, 0},
-+      {0x3508, 0x00, 0, 0},
-+      {0x3509, 0x80, 0, 0},
-+      {0x350a, 0x00, 0, 0},
-+      {0x350b, 0x00, 0, 0},
-+      {0x350c, 0x00, 0, 0},
-+      {0x350d, 0x00, 0, 0},
-+      {0x350e, 0x00, 0, 0},
-+      {0x350f, 0x80, 0, 0},
-+      {0x3510, 0x00, 0, 0},
-+      {0x3511, 0x00, 0, 0},
-+      {0x3512, 0x00, 0, 0},
-+      {0x3513, 0x00, 0, 0},
-+      {0x3514, 0x00, 0, 0},
-+      {0x3515, 0x80, 0, 0},
-+      {0x3516, 0x00, 0, 0},
-+      {0x3517, 0x00, 0, 0},
-+      {0x3518, 0x00, 0, 0},
-+      {0x3519, 0x00, 0, 0},
-+      {0x351a, 0x00, 0, 0},
-+      {0x351b, 0x80, 0, 0},
-+      {0x351c, 0x00, 0, 0},
-+      {0x351d, 0x00, 0, 0},
-+      {0x351e, 0x00, 0, 0},
-+      {0x351f, 0x00, 0, 0},
-+      {0x3520, 0x00, 0, 0},
-+      {0x3521, 0x80, 0, 0},
-+      {0x3522, 0x08, 0, 0},
-+      {0x3524, 0x08, 0, 0},
-+      {0x3526, 0x08, 0, 0},
-+      {0x3528, 0x08, 0, 0},
-+      {0x352a, 0x08, 0, 0},
-+      {0x3602, 0x00, 0, 0},
-+      {0x3603, 0x40, 0, 0},
-+      {0x3604, 0x02, 0, 0},
-+      {0x3605, 0x00, 0, 0},
-+      {0x3606, 0x00, 0, 0},
-+      {0x3607, 0x00, 0, 0},
-+      {0x3609, 0x12, 0, 0},
-+      {0x360a, 0x40, 0, 0},
-+      {0x360c, 0x08, 0, 0},
-+      {0x360f, 0xe5, 0, 0},
-+      {0x3608, 0x8f, 0, 0},
-+      {0x3611, 0x00, 0, 0},
-+      {0x3613, 0xf7, 0, 0},
-+      {0x3616, 0x58, 0, 0},
-+      {0x3619, 0x99, 0, 0},
-+      {0x361b, 0x60, 0, 0},
-+      {0x361c, 0x7a, 0, 0},
-+      {0x361e, 0x79, 0, 0},
-+      {0x361f, 0x02, 0, 0},
-+      {0x3632, 0x00, 0, 0},
-+      {0x3633, 0x10, 0, 0},
-+      {0x3634, 0x10, 0, 0},
-+      {0x3635, 0x10, 0, 0},
-+      {0x3636, 0x15, 0, 0},
-+      {0x3646, 0x86, 0, 0},
-+      {0x364a, 0x0b, 0, 0},
-+      {0x3700, 0x17, 0, 0},
-+      {0x3701, 0x22, 0, 0},
-+      {0x3703, 0x10, 0, 0},
-+      {0x370a, 0x37, 0, 0},
-+      {0x3705, 0x00, 0, 0},
-+      {0x3706, 0x63, 0, 0},
-+      {0x3709, 0x3c, 0, 0},
-+      {0x370b, 0x01, 0, 0},
-+      {0x370c, 0x30, 0, 0},
-+      {0x3710, 0x24, 0, 0},
-+      {0x3711, 0x0c, 0, 0},
-+      {0x3716, 0x00, 0, 0},
-+      {0x3720, 0x28, 0, 0},
-+      {0x3729, 0x7b, 0, 0},
-+      {0x372a, 0x84, 0, 0},
-+      {0x372b, 0xbd, 0, 0},
-+      {0x372c, 0xbc, 0, 0},
-+      {0x372e, 0x52, 0, 0},
-+      {0x373c, 0x0e, 0, 0},
-+      {0x373e, 0x33, 0, 0},
-+      {0x3743, 0x10, 0, 0},
-+      {0x3744, 0x88, 0, 0},
-+      {0x3745, 0xc0, 0, 0},
-+      {0x374a, 0x43, 0, 0},
-+      {0x374c, 0x00, 0, 0},
-+      {0x374e, 0x23, 0, 0},
-+      {0x3751, 0x7b, 0, 0},
-+      {0x3752, 0x84, 0, 0},
-+      {0x3753, 0xbd, 0, 0},
-+      {0x3754, 0xbc, 0, 0},
-+      {0x3756, 0x52, 0, 0},
-+      {0x375c, 0x00, 0, 0},
-+      {0x3760, 0x00, 0, 0},
-+      {0x3761, 0x00, 0, 0},
-+      {0x3762, 0x00, 0, 0},
-+      {0x3763, 0x00, 0, 0},
-+      {0x3764, 0x00, 0, 0},
-+      {0x3767, 0x04, 0, 0},
-+      {0x3768, 0x04, 0, 0},
-+      {0x3769, 0x08, 0, 0},
-+      {0x376a, 0x08, 0, 0},
-+      {0x376b, 0x20, 0, 0},
-+      {0x376c, 0x00, 0, 0},
-+      {0x376d, 0x00, 0, 0},
-+      {0x376e, 0x00, 0, 0},
-+      {0x3773, 0x00, 0, 0},
-+      {0x3774, 0x51, 0, 0},
-+      {0x3776, 0xbd, 0, 0},
-+      {0x3777, 0xbd, 0, 0},
-+      {0x3781, 0x18, 0, 0},
-+      {0x3783, 0x25, 0, 0},
-+      {0x3798, 0x1b, 0, 0},
-+      {0x3800, 0x01, 0, 0},   // timings
-+      {0x3801, 0x88, 0, 0},
-+      {0x3802, 0x00, 0, 0},
-+      {0x3803, 0xe0, 0, 0},
-+      {0x3804, 0x09, 0, 0},
-+      {0x3805, 0x17, 0, 0},
-+      {0x3806, 0x05, 0, 0},
-+      {0x3807, 0x1f, 0, 0},
-+      {0x3808, 0x07, 0, 0},
-+      {0x3809, 0x80, 0, 0},
-+      {0x380a, 0x04, 0, 0},
-+      {0x380b, 0x38, 0, 0},
-+      {0x380c, 0x06, 0, 0},
-+      {0x380d, 0xe0, 0, 0},
-+      {0x380e, 0x04, 0, 0},
-+      {0x380f, 0x70, 0, 0},
-+      {0x3810, 0x00, 0, 0},
-+      {0x3811, 0x08, 0, 0},
-+      {0x3812, 0x00, 0, 0},
-+      {0x3813, 0x04, 0, 0},
-+      {0x3814, 0x01, 0, 0},
-+      {0x3815, 0x01, 0, 0},
-+      {0x3819, 0x01, 0, 0},
-+      {0x3820, 0x06, 0, 0},
-+      {0x3821, 0x00, 0, 0},
-+      {0x3829, 0x00, 0, 0},
-+      {0x382a, 0x01, 0, 0},
-+      {0x382b, 0x01, 0, 0},
-+      {0x382d, 0x7f, 0, 0},
-+      {0x3830, 0x04, 0, 0},
-+      {0x3836, 0x01, 0, 0},
-+      {0x3837, 0x00, 0, 0},
-+      {0x3841, 0x02, 0, 0},
-+      {0x3846, 0x08, 0, 0},
-+      {0x3847, 0x07, 0, 0},
-+      {0x3d85, 0x36, 0, 0},
-+      {0x3d8c, 0x71, 0, 0},
-+      {0x3d8d, 0xcb, 0, 0},
-+      {0x3f0a, 0x00, 0, 0},
-+      {0x4000, 0xf1, 0, 0},
-+      {0x4001, 0x40, 0, 0},
-+      {0x4002, 0x04, 0, 0},
-+      {0x4003, 0x14, 0, 0},
-+      {0x400e, 0x00, 0, 0},
-+      {0x4011, 0x00, 0, 0},
-+      {0x401a, 0x00, 0, 0},
-+      {0x401b, 0x00, 0, 0},
-+      {0x401c, 0x00, 0, 0},
-+      {0x401d, 0x00, 0, 0},
-+      {0x401f, 0x00, 0, 0},
-+      {0x4020, 0x00, 0, 0},
-+      {0x4021, 0x10, 0, 0},
-+      {0x4022, 0x06, 0, 0},
-+      {0x4023, 0x13, 0, 0},
-+      {0x4024, 0x07, 0, 0},
-+      {0x4025, 0x40, 0, 0},
-+      {0x4026, 0x07, 0, 0},
-+      {0x4027, 0x50, 0, 0},
-+      {0x4028, 0x00, 0, 0},
-+      {0x4029, 0x02, 0, 0},
-+      {0x402a, 0x06, 0, 0},
-+      {0x402b, 0x04, 0, 0},
-+      {0x402c, 0x02, 0, 0},
-+      {0x402d, 0x02, 0, 0},
-+      {0x402e, 0x0e, 0, 0},
-+      {0x402f, 0x04, 0, 0},
-+      {0x4302, 0xff, 0, 0},
-+      {0x4303, 0xff, 0, 0},
-+      {0x4304, 0x00, 0, 0},
-+      {0x4305, 0x00, 0, 0},
-+      {0x4306, 0x00, 0, 0},
-+      {0x4308, 0x02, 0, 0},
-+      {0x4500, 0x6c, 0, 0},
-+      {0x4501, 0xc4, 0, 0},
-+      {0x4502, 0x40, 0, 0},
-+      {0x4503, 0x01, 0, 0},
-+      {0x4601, 0x77, 0, 0},
-+      {0x4800, 0x04, 0, 0},
-+      {0x4813, 0x08, 0, 0},
-+      {0x481f, 0x40, 0, 0},
-+      {0x4829, 0x78, 0, 0},
-+      {0x4837, 0x10, 0, 0},
-+      {0x4b00, 0x2a, 0, 0},
-+      {0x4b0d, 0x00, 0, 0},
-+      {0x4d00, 0x04, 0, 0},
-+      {0x4d01, 0x42, 0, 0},
-+      {0x4d02, 0xd1, 0, 0},
-+      {0x4d03, 0x93, 0, 0},
-+      {0x4d04, 0xf5, 0, 0},
-+      {0x4d05, 0xc1, 0, 0},
-+      {0x5000, 0xf3, 0, 0},
-+      {0x5001, 0x11, 0, 0},
-+      {0x5004, 0x00, 0, 0},
-+      {0x500a, 0x00, 0, 0},
-+      {0x500b, 0x00, 0, 0},
-+      {0x5032, 0x00, 0, 0},
-+      {0x5040, 0x00, 0, 0},
-+      {0x5050, 0x0c, 0, 0},
-+      {0x5500, 0x00, 0, 0},
-+      {0x5501, 0x10, 0, 0},
-+      {0x5502, 0x01, 0, 0},
-+      {0x5503, 0x0f, 0, 0},
-+      {0x8000, 0x00, 0, 0},
-+      {0x8001, 0x00, 0, 0},
-+      {0x8002, 0x00, 0, 0},
-+      {0x8003, 0x00, 0, 0},
-+      {0x8004, 0x00, 0, 0},
-+      {0x8005, 0x00, 0, 0},
-+      {0x8006, 0x00, 0, 0},
-+      {0x8007, 0x00, 0, 0},
-+      {0x8008, 0x00, 0, 0},
-+      {0x3638, 0x00, 0, 0},
-+};
-+
-+static const struct reg_value ov4689_setting_4M_2688_1520[] = {
-+      //@@ 0 10 RES_2688x1520_default(60fps)
-+      //102 2630 960
-+      {0x0103, 0x01, 0, 0},
-+      {0x3638, 0x00, 0, 0},
-+      {0x0300, 0x00, 0, 0},
-+      {0x0302, 0x22, 0, 0}, // 2a ;1008Mbps,23 ;; 840Mbps
-+      {0x0304, 0x03, 0, 0},
-+      {0x030b, 0x00, 0, 0},
-+      {0x030d, 0x1e, 0, 0},
-+      {0x030e, 0x04, 0, 0},
-+      {0x030f, 0x01, 0, 0},
-+      {0x0312, 0x01, 0, 0},
-+      {0x031e, 0x00, 0, 0},
-+      {0x3000, 0x20, 0, 0},
-+      {0x3002, 0x00, 0, 0},
-+      {0x3020, 0x93, 0, 0},
-+      {0x3021, 0x03, 0, 0},
-+      {0x3022, 0x01, 0, 0},
-+      {0x3031, 0x0a, 0, 0},
-+      {0x303f, 0x0c, 0, 0},
-+      {0x3305, 0xf1, 0, 0},
-+      {0x3307, 0x04, 0, 0},
-+      {0x3309, 0x29, 0, 0},
-+      {0x3500, 0x00, 0, 0},
-+      {0x3501, 0x60, 0, 0},
-+      {0x3502, 0x00, 0, 0},
-+      {0x3503, 0x04, 0, 0},
-+      {0x3504, 0x00, 0, 0},
-+      {0x3505, 0x00, 0, 0},
-+      {0x3506, 0x00, 0, 0},
-+      {0x3507, 0x00, 0, 0},
-+      {0x3508, 0x00, 0, 0},
-+      {0x3509, 0x80, 0, 0},
-+      {0x350a, 0x00, 0, 0},
-+      {0x350b, 0x00, 0, 0},
-+      {0x350c, 0x00, 0, 0},
-+      {0x350d, 0x00, 0, 0},
-+      {0x350e, 0x00, 0, 0},
-+      {0x350f, 0x80, 0, 0},
-+      {0x3510, 0x00, 0, 0},
-+      {0x3511, 0x00, 0, 0},
-+      {0x3512, 0x00, 0, 0},
-+      {0x3513, 0x00, 0, 0},
-+      {0x3514, 0x00, 0, 0},
-+      {0x3515, 0x80, 0, 0},
-+      {0x3516, 0x00, 0, 0},
-+      {0x3517, 0x00, 0, 0},
-+      {0x3518, 0x00, 0, 0},
-+      {0x3519, 0x00, 0, 0},
-+      {0x351a, 0x00, 0, 0},
-+      {0x351b, 0x80, 0, 0},
-+      {0x351c, 0x00, 0, 0},
-+      {0x351d, 0x00, 0, 0},
-+      {0x351e, 0x00, 0, 0},
-+      {0x351f, 0x00, 0, 0},
-+      {0x3520, 0x00, 0, 0},
-+      {0x3521, 0x80, 0, 0},
-+      {0x3522, 0x08, 0, 0},
-+      {0x3524, 0x08, 0, 0},
-+      {0x3526, 0x08, 0, 0},
-+      {0x3528, 0x08, 0, 0},
-+      {0x352a, 0x08, 0, 0},
-+      {0x3602, 0x00, 0, 0},
-+      {0x3603, 0x40, 0, 0},
-+      {0x3604, 0x02, 0, 0},
-+      {0x3605, 0x00, 0, 0},
-+      {0x3606, 0x00, 0, 0},
-+      {0x3607, 0x00, 0, 0},
-+      {0x3609, 0x12, 0, 0},
-+      {0x360a, 0x40, 0, 0},
-+      {0x360c, 0x08, 0, 0},
-+      {0x360f, 0xe5, 0, 0},
-+      {0x3608, 0x8f, 0, 0},
-+      {0x3611, 0x00, 0, 0},
-+      {0x3613, 0xf7, 0, 0},
-+      {0x3616, 0x58, 0, 0},
-+      {0x3619, 0x99, 0, 0},
-+      {0x361b, 0x60, 0, 0},
-+      {0x361c, 0x7a, 0, 0},
-+      {0x361e, 0x79, 0, 0},
-+      {0x361f, 0x02, 0, 0},
-+      {0x3632, 0x00, 0, 0},
-+      {0x3633, 0x10, 0, 0},
-+      {0x3634, 0x10, 0, 0},
-+      {0x3635, 0x10, 0, 0},
-+      {0x3636, 0x15, 0, 0},
-+      {0x3646, 0x86, 0, 0},
-+      {0x364a, 0x0b, 0, 0},
-+      {0x3700, 0x17, 0, 0},
-+      {0x3701, 0x22, 0, 0},
-+      {0x3703, 0x10, 0, 0},
-+      {0x370a, 0x37, 0, 0},
-+      {0x3705, 0x00, 0, 0},
-+      {0x3706, 0x63, 0, 0},
-+      {0x3709, 0x3c, 0, 0},
-+      {0x370b, 0x01, 0, 0},
-+      {0x370c, 0x30, 0, 0},
-+      {0x3710, 0x24, 0, 0},
-+      {0x3711, 0x0c, 0, 0},
-+      {0x3716, 0x00, 0, 0},
-+      {0x3720, 0x28, 0, 0},
-+      {0x3729, 0x7b, 0, 0},
-+      {0x372a, 0x84, 0, 0},
-+      {0x372b, 0xbd, 0, 0},
-+      {0x372c, 0xbc, 0, 0},
-+      {0x372e, 0x52, 0, 0},
-+      {0x373c, 0x0e, 0, 0},
-+      {0x373e, 0x33, 0, 0},
-+      {0x3743, 0x10, 0, 0},
-+      {0x3744, 0x88, 0, 0},
-+      {0x3745, 0xc0, 0, 0},
-+      {0x374a, 0x43, 0, 0},
-+      {0x374c, 0x00, 0, 0},
-+      {0x374e, 0x23, 0, 0},
-+      {0x3751, 0x7b, 0, 0},
-+      {0x3752, 0x84, 0, 0},
-+      {0x3753, 0xbd, 0, 0},
-+      {0x3754, 0xbc, 0, 0},
-+      {0x3756, 0x52, 0, 0},
-+      {0x375c, 0x00, 0, 0},
-+      {0x3760, 0x00, 0, 0},
-+      {0x3761, 0x00, 0, 0},
-+      {0x3762, 0x00, 0, 0},
-+      {0x3763, 0x00, 0, 0},
-+      {0x3764, 0x00, 0, 0},
-+      {0x3767, 0x04, 0, 0},
-+      {0x3768, 0x04, 0, 0},
-+      {0x3769, 0x08, 0, 0},
-+      {0x376a, 0x08, 0, 0},
-+      {0x376b, 0x20, 0, 0},
-+      {0x376c, 0x00, 0, 0},
-+      {0x376d, 0x00, 0, 0},
-+      {0x376e, 0x00, 0, 0},
-+      {0x3773, 0x00, 0, 0},
-+      {0x3774, 0x51, 0, 0},
-+      {0x3776, 0xbd, 0, 0},
-+      {0x3777, 0xbd, 0, 0},
-+      {0x3781, 0x18, 0, 0},
-+      {0x3783, 0x25, 0, 0},
-+      {0x3798, 0x1b, 0, 0},
-+      {0x3800, 0x00, 0, 0},
-+      {0x3801, 0x08, 0, 0},
-+      {0x3802, 0x00, 0, 0},
-+      {0x3803, 0x04, 0, 0},
-+      {0x3804, 0x0a, 0, 0},
-+      {0x3805, 0x97, 0, 0},
-+      {0x3806, 0x05, 0, 0},
-+      {0x3807, 0xfb, 0, 0},
-+      {0x3808, 0x0a, 0, 0},
-+      {0x3809, 0x80, 0, 0},
-+      {0x380a, 0x05, 0, 0},
-+      {0x380b, 0xf0, 0, 0},
-+      {0x380c, 0x03, 0, 0},
-+      {0x380d, 0x5c, 0, 0},
-+      {0x380e, 0x06, 0, 0},
-+      {0x380f, 0x12, 0, 0},
-+      {0x3810, 0x00, 0, 0},
-+      {0x3811, 0x08, 0, 0},
-+      {0x3812, 0x00, 0, 0},
-+      {0x3813, 0x04, 0, 0},
-+      {0x3814, 0x01, 0, 0},
-+      {0x3815, 0x01, 0, 0},
-+      {0x3819, 0x01, 0, 0},
-+      {0x3820, 0x00, 0, 0},
-+      {0x3821, 0x06, 0, 0},
-+      {0x3829, 0x00, 0, 0},
-+      {0x382a, 0x01, 0, 0},
-+      {0x382b, 0x01, 0, 0},
-+      {0x382d, 0x7f, 0, 0},
-+      {0x3830, 0x04, 0, 0},
-+      {0x3836, 0x01, 0, 0},
-+      {0x3837, 0x00, 0, 0},
-+      {0x3841, 0x02, 0, 0},
-+      {0x3846, 0x08, 0, 0},
-+      {0x3847, 0x07, 0, 0},
-+      {0x3d85, 0x36, 0, 0},
-+      {0x3d8c, 0x71, 0, 0},
-+      {0x3d8d, 0xcb, 0, 0},
-+      {0x3f0a, 0x00, 0, 0},
-+      {0x4000, 0x71, 0, 0},
-+      {0x4001, 0x40, 0, 0},
-+      {0x4002, 0x04, 0, 0},
-+      {0x4003, 0x14, 0, 0},
-+      {0x400e, 0x00, 0, 0},
-+      {0x4011, 0x00, 0, 0},
-+      {0x401a, 0x00, 0, 0},
-+      {0x401b, 0x00, 0, 0},
-+      {0x401c, 0x00, 0, 0},
-+      {0x401d, 0x00, 0, 0},
-+      {0x401f, 0x00, 0, 0},
-+      {0x4020, 0x00, 0, 0},
-+      {0x4021, 0x10, 0, 0},
-+      {0x4022, 0x07, 0, 0},
-+      {0x4023, 0xcf, 0, 0},
-+      {0x4024, 0x09, 0, 0},
-+      {0x4025, 0x60, 0, 0},
-+      {0x4026, 0x09, 0, 0},
-+      {0x4027, 0x6f, 0, 0},
-+      {0x4028, 0x00, 0, 0},
-+      {0x4029, 0x02, 0, 0},
-+      {0x402a, 0x06, 0, 0},
-+      {0x402b, 0x04, 0, 0},
-+      {0x402c, 0x02, 0, 0},
-+      {0x402d, 0x02, 0, 0},
-+      {0x402e, 0x0e, 0, 0},
-+      {0x402f, 0x04, 0, 0},
-+      {0x4302, 0xff, 0, 0},
-+      {0x4303, 0xff, 0, 0},
-+      {0x4304, 0x00, 0, 0},
-+      {0x4305, 0x00, 0, 0},
-+      {0x4306, 0x00, 0, 0},
-+      {0x4308, 0x02, 0, 0},
-+      {0x4500, 0x6c, 0, 0},
-+      {0x4501, 0xc4, 0, 0},
-+      {0x4502, 0x40, 0, 0},
-+      {0x4503, 0x01, 0, 0},
-+      {0x4601, 0x04, 0, 0},
-+      {0x4800, 0x04, 0, 0},
-+      {0x4813, 0x08, 0, 0},
-+      {0x481f, 0x40, 0, 0},
-+      {0x4829, 0x78, 0, 0},
-+      {0x4837, 0x14, 0, 0}, // 10
-+      {0x4b00, 0x2a, 0, 0},
-+      {0x4b0d, 0x00, 0, 0},
-+      {0x4d00, 0x04, 0, 0},
-+      {0x4d01, 0x42, 0, 0},
-+      {0x4d02, 0xd1, 0, 0},
-+      {0x4d03, 0x93, 0, 0},
-+      {0x4d04, 0xf5, 0, 0},
-+      {0x4d05, 0xc1, 0, 0},
-+      {0x5000, 0xf3, 0, 0},
-+      {0x5001, 0x11, 0, 0},
-+      {0x5004, 0x00, 0, 0},
-+      {0x500a, 0x00, 0, 0},
-+      {0x500b, 0x00, 0, 0},
-+      {0x5032, 0x00, 0, 0},
-+      {0x5040, 0x00, 0, 0},
-+      {0x5050, 0x0c, 0, 0},
-+      {0x5500, 0x00, 0, 0},
-+      {0x5501, 0x10, 0, 0},
-+      {0x5502, 0x01, 0, 0},
-+      {0x5503, 0x0f, 0, 0},
-+      {0x8000, 0x00, 0, 0},
-+      {0x8001, 0x00, 0, 0},
-+      {0x8002, 0x00, 0, 0},
-+      {0x8003, 0x00, 0, 0},
-+      {0x8004, 0x00, 0, 0},
-+      {0x8005, 0x00, 0, 0},
-+      {0x8006, 0x00, 0, 0},
-+      {0x8007, 0x00, 0, 0},
-+      {0x8008, 0x00, 0, 0},
-+      {0x3638, 0x00, 0, 0},
-+//    {0x0100, 0x01, 0, 0},
-+
-+//    {0x0100, 0x00, 0, 0},
-+      {0x380c, 0x0A, 0, 0}, // 05
-+      {0x380d, 0x0A, 0, 0}, // 10
-+      {0x380e, 0x06, 0, 0},
-+      {0x380f, 0x12, 0, 0},
-+//    {0x0100, 0x01, 0, 0},
-+      {0x3105, 0x31, 0, 0},
-+      {0x301a, 0xf9, 0, 0},
-+      {0x3508, 0x07, 0, 0},
-+      {0x484b, 0x05, 0, 0},
-+      {0x4805, 0x03, 0, 0},
-+      {0x3601, 0x01, 0, 0},
-+      {0x3745, 0xc0, 0, 0},
-+      {0x3798, 0x1b, 0, 0},
-+//    {0x0100, 0x01, 0, 0},
-+      {0xffff, 0x0a, 0, 0},
-+      {0x3105, 0x11, 0, 0},
-+      {0x301a, 0xf1, 0, 0},
-+      {0x4805, 0x00, 0, 0},
-+      {0x301a, 0xf0, 0, 0},
-+      {0x3208, 0x00, 0, 0},
-+      {0x302a, 0x00, 0, 0},
-+      {0x302a, 0x00, 0, 0},
-+      {0x302a, 0x00, 0, 0},
-+      {0x302a, 0x00, 0, 0},
-+      {0x302a, 0x00, 0, 0},
-+      {0x3601, 0x00, 0, 0},
-+      {0x3638, 0x00, 0, 0},
-+      {0x3208, 0x10, 0, 0},
-+      {0x3208, 0xa0, 0, 0},
-+};
-+
-+/* power-on sensor init reg table */
-+static const struct ov4689_mode_info ov4689_mode_init_data = {
-+
-+};
-+
-+static const struct ov4689_mode_info
-+ov4689_mode_data[OV4689_NUM_MODES] = {
-+      // {OV4689_MODE_720P_1280_720, SUBSAMPLING,
-+      //  1280, 0x408, 720, 0x305,
-+      //  ov4689_setting_720P_1280_720,
-+      //  ARRAY_SIZE(ov4689_setting_720P_1280_720),
-+      //  OV4689_150_FPS},
-+      // {OV4689_MODE_1080P_1920_1080, SCALING,
-+      //  1920, 0x6e0, 1080, 0x470,
-+      //  ov4689_setting_1080P_1920_1080,
-+      //  ARRAY_SIZE(ov4689_setting_1080P_1920_1080),
-+      //  OV4689_60_FPS},
-+      // {OV4689_MODE_4M_2688_1520, SCALING,
-+      //  2688, 0xa0a, 1520, 0x612,
-+      //  ov4689_setting_4M_2688_1520,
-+      //  ARRAY_SIZE(ov4689_setting_4M_2688_1520),
-+      //  OV4689_60_FPS},
-+
-+      {OV4689_MODE_1080P_1920_1080, SCALING,
-+       1920, 0x6e0, 1080, 0x470,
-+       ov4689_init_setting_30fps_1080P,
-+       ARRAY_SIZE(ov4689_init_setting_30fps_1080P),
-+       OV4689_60_FPS},
-+};
-+
-+static int ov4689_write_reg(struct ov4689_dev *sensor, u16 reg, u8 val)
-+{
-+      struct i2c_client *client = sensor->i2c_client;
-+      struct i2c_msg msg;
-+      u8 buf[3];
-+      int ret;
-+
-+      buf[0] = reg >> 8;
-+      buf[1] = reg & 0xff;
-+      buf[2] = val;
-+
-+      msg.addr = client->addr;
-+      msg.flags = client->flags;
-+      msg.buf = buf;
-+      msg.len = sizeof(buf);
-+
-+      ret = i2c_transfer(client->adapter, &msg, 1);
-+      if (ret < 0) {
-+              dev_err(&client->dev, "%s: error: reg=%x, val=%x\n",
-+                      __func__, reg, val);
-+              return ret;
-+      }
-+
-+      return 0;
-+}
-+
-+static int ov4689_read_reg(struct ov4689_dev *sensor, u16 reg, u8 *val)
-+{
-+      struct i2c_client *client = sensor->i2c_client;
-+      struct i2c_msg msg[2];
-+      u8 buf[2];
-+      int ret;
-+
-+      buf[0] = reg >> 8;
-+      buf[1] = reg & 0xff;
-+
-+      msg[0].addr = client->addr;
-+      msg[0].flags = client->flags;
-+      msg[0].buf = buf;
-+      msg[0].len = sizeof(buf);
-+
-+      msg[1].addr = client->addr;
-+      msg[1].flags = client->flags | I2C_M_RD;
-+      msg[1].buf = buf;
-+      msg[1].len = 1;
-+
-+      ret = i2c_transfer(client->adapter, msg, 2);
-+      if (ret < 0) {
-+              dev_err(&client->dev, "%s: error: reg=%x\n",
-+                      __func__, reg);
-+              return ret;
-+      }
-+
-+      *val = buf[0];
-+      return 0;
-+}
-+
-+static int ov4689_read_reg16(struct ov4689_dev *sensor, u16 reg, u16 *val)
-+{
-+      u8 hi, lo;
-+      int ret;
-+
-+      ret = ov4689_read_reg(sensor, reg, &hi);
-+      if (ret)
-+              return ret;
-+      ret = ov4689_read_reg(sensor, reg + 1, &lo);
-+      if (ret)
-+              return ret;
-+
-+      *val = ((u16)hi << 8) | (u16)lo;
-+      return 0;
-+}
-+
-+static int ov4689_write_reg16(struct ov4689_dev *sensor, u16 reg, u16 val)
-+{
-+      int ret;
-+
-+      ret = ov4689_write_reg(sensor, reg, val >> 8);
-+      if (ret)
-+              return ret;
-+
-+      return ov4689_write_reg(sensor, reg + 1, val & 0xff);
-+}
-+
-+static int ov4689_mod_reg(struct ov4689_dev *sensor, u16 reg,
-+                      u8 mask, u8 val)
-+{
-+      u8 readval;
-+      int ret;
-+
-+      ret = ov4689_read_reg(sensor, reg, &readval);
-+      if (ret)
-+              return ret;
-+
-+      readval &= ~mask;
-+      val &= mask;
-+      val |= readval;
-+
-+      return ov4689_write_reg(sensor, reg, val);
-+}
-+
-+static int ov4689_set_timings(struct ov4689_dev *sensor,
-+                      const struct ov4689_mode_info *mode)
-+{
-+      return 0;
-+}
-+
-+static int ov4689_load_regs(struct ov4689_dev *sensor,
-+                      const struct ov4689_mode_info *mode)
-+{
-+      const struct reg_value *regs = mode->reg_data;
-+      unsigned int i;
-+      u32 delay_ms;
-+      u16 reg_addr;
-+      u8 mask, val;
-+      int ret = 0;
-+
-+      st_info(ST_SENSOR, "%s, mode = 0x%x\n", __func__, mode->id);
-+      for (i = 0; i < mode->reg_data_size; ++i, ++regs) {
-+              delay_ms = regs->delay_ms;
-+              reg_addr = regs->reg_addr;
-+              val = regs->val;
-+              mask = regs->mask;
-+
-+              if (mask)
-+                      ret = ov4689_mod_reg(sensor, reg_addr, mask, val);
-+              else
-+                      ret = ov4689_write_reg(sensor, reg_addr, val);
-+              if (ret)
-+                      break;
-+
-+              if (delay_ms)
-+                      usleep_range(1000 * delay_ms, 1000 * delay_ms + 100);
-+      }
-+
-+      return ov4689_set_timings(sensor, mode);
-+}
-+
-+#ifdef UNUSED_CODE
-+static int ov4689_get_exposure(struct ov4689_dev *sensor)
-+{
-+      int exp, ret;
-+      u8 temp;
-+
-+      ret = ov4689_read_reg(sensor, OV4689_REG_EXPOSURE_HI, &temp);
-+      if (ret)
-+              return ret;
-+      exp = ((int)temp & 0x0f) << 16;
-+      ret = ov4689_read_reg(sensor, OV4689_REG_EXPOSURE_MED, &temp);
-+      if (ret)
-+              return ret;
-+      exp |= ((int)temp << 8);
-+      ret = ov4689_read_reg(sensor, OV4689_REG_EXPOSURE_LO, &temp);
-+      if (ret)
-+              return ret;
-+      exp |= (int)temp;
-+
-+      return exp >> 4;
-+}
-+#endif
-+
-+static int ov4689_set_exposure(struct ov4689_dev *sensor, u32 exposure)
-+{
-+      int ret;
-+
-+      st_info(ST_SENSOR, "%s, exposure = 0x%x\n", __func__, exposure);
-+      exposure <<= 4;
-+
-+      ret = ov4689_write_reg(sensor,
-+                      OV4689_REG_EXPOSURE_LO,
-+                      exposure & 0xff);
-+      if (ret)
-+              return ret;
-+      ret = ov4689_write_reg(sensor,
-+                      OV4689_REG_EXPOSURE_MED,
-+                      (exposure >> 8) & 0xff);
-+      if (ret)
-+              return ret;
-+      return ov4689_write_reg(sensor,
-+                              OV4689_REG_EXPOSURE_HI,
-+                              (exposure >> 16) & 0x0f);
-+}
-+
-+static int ov4689_get_gain(struct ov4689_dev *sensor)
-+{
-+      u32 gain = 0;
-+      u8 val;
-+
-+      ov4689_read_reg(sensor, OV4689_REG_GAIN_H, &val);
-+      gain = (val & 0x3) << 16;
-+      ov4689_read_reg(sensor, OV4689_REG_GAIN_M, &val);
-+      gain |= val << 8;
-+      ov4689_read_reg(sensor, OV4689_REG_GAIN_L, &val);
-+      gain |= val;
-+
-+      return gain;
-+}
-+
-+static int ov4689_set_gain(struct ov4689_dev *sensor, int gain)
-+{
-+      ov4689_write_reg(sensor, OV4689_REG_GAIN_H,
-+                              (gain >> 16) & 0x3);
-+      ov4689_write_reg(sensor, OV4689_REG_GAIN_M,
-+                              (gain >> 8) & 0xff);
-+      ov4689_write_reg(sensor, OV4689_REG_GAIN_L,
-+                              gain & 0xff);
-+      return 0;
-+}
-+
-+#ifdef UNUSED_CODE
-+static int ov4689_get_sysclk(struct ov4689_dev *sensor)
-+{
-+      return 0;
-+}
-+
-+static int ov4689_set_night_mode(struct ov4689_dev *sensor)
-+{
-+      return 0;
-+}
-+
-+static int ov4689_get_hts(struct ov4689_dev *sensor)
-+{
-+      /* read HTS from register settings */
-+      u16 hts;
-+      int ret;
-+
-+      ret = ov4689_read_reg16(sensor, OV4689_REG_TIMING_HTS, &hts);
-+      if (ret)
-+              return ret;
-+      return hts;
-+}
-+#endif
-+
-+static int ov4689_get_vts(struct ov4689_dev *sensor)
-+{
-+      u16 vts;
-+      int ret;
-+
-+      ret = ov4689_read_reg16(sensor, OV4689_REG_TIMING_VTS, &vts);
-+      if (ret)
-+              return ret;
-+      return vts;
-+}
-+
-+#ifdef UNUSED_CODE
-+static int ov4689_set_vts(struct ov4689_dev *sensor, int vts)
-+{
-+      return ov4689_write_reg16(sensor, OV4689_REG_TIMING_VTS, vts);
-+}
-+
-+static int ov4689_get_light_freq(struct ov4689_dev *sensor)
-+{
-+      return 0;
-+}
-+
-+static int ov4689_set_bandingfilter(struct ov4689_dev *sensor)
-+{
-+      return 0;
-+}
-+
-+static int ov4689_set_ae_target(struct ov4689_dev *sensor, int target)
-+{
-+      return 0;
-+}
-+
-+static int ov4689_get_binning(struct ov4689_dev *sensor)
-+{
-+      return 0;
-+}
-+
-+static int ov4689_set_binning(struct ov4689_dev *sensor, bool enable)
-+{
-+      return 0;
-+}
-+#endif
-+
-+static const struct ov4689_mode_info *
-+ov4689_find_mode(struct ov4689_dev *sensor, enum ov4689_frame_rate fr,
-+              int width, int height, bool nearest)
-+{
-+      const struct ov4689_mode_info *mode;
-+
-+      mode = v4l2_find_nearest_size(ov4689_mode_data,
-+                              ARRAY_SIZE(ov4689_mode_data),
-+                              hact, vact,
-+                              width, height);
-+
-+      if (!mode ||
-+              (!nearest && (mode->hact != width || mode->vact != height)))
-+              return NULL;
-+
-+      /* Check to see if the current mode exceeds the max frame rate */
-+      if (ov4689_framerates[fr] > ov4689_framerates[mode->max_fps])
-+              return NULL;
-+
-+      return mode;
-+}
-+
-+static u64 ov4689_calc_pixel_rate(struct ov4689_dev *sensor)
-+{
-+      u64 rate;
-+
-+      rate = sensor->current_mode->vact * sensor->current_mode->hact;
-+      rate *= ov4689_framerates[sensor->current_fr];
-+
-+      return rate;
-+}
-+
-+/*
-+ * After trying the various combinations, reading various
-+ * documentations spread around the net, and from the various
-+ * feedback, the clock tree is probably as follows:
-+ *
-+ *   +--------------+
-+ *   |  Ext. Clock  |
-+ *   +-+------------+
-+ *     |  +----------+
-+ *     +->|   PLL1   | - reg 0x030a, bit0 for the pre-dividerp
-+ *        +-+--------+ - reg 0x0300, bits 0-2 for the pre-divider
-+ *        +-+--------+ - reg 0x0301~0x0302, for the multiplier
-+ *          |  +--------------+
-+ *          +->| MIPI Divider |  - reg 0x0303, bits 0-3 for the pre-divider
-+ *               | +---------> MIPI PHY CLK
-+ *               |    +-----+
-+ *               | +->| PLL1_DIV_MIPI | - reg 0x0304, bits 0-1 for the divider
-+ *                 |    +----------------> PCLK
-+ *               |    +-----+
-+ *
-+ *   +--------------+
-+ *   |  Ext. Clock  |
-+ *   +-+------------+
-+ *     |  +----------+
-+ *     +->|   PLL2  | - reg 0x0311, bit0 for the pre-dividerp
-+ *        +-+--------+ - reg 0x030b, bits 0-2 for the pre-divider
-+ *        +-+--------+ - reg 0x030c~0x030d, for the multiplier
-+ *          |  +--------------+
-+ *          +->| SCLK Divider |  - reg 0x030F, bits 0-3 for the pre-divider
-+ *               +-+--------+    - reg 0x030E, bits 0-2 for the divider
-+ *               |    +---------> SCLK
-+ *
-+ *          |       +-----+
-+ *          +->| DAC Divider | - reg 0x0312, bits 0-3 for the divider
-+ *                    |    +----------------> DACCLK
-+ **
-+ */
-+
-+/*
-+ * ov4689_set_mipi_pclk() - Calculate the clock tree configuration values
-+ *                    for the MIPI CSI-2 output.
-+ *
-+ * @rate: The requested bandwidth per lane in bytes per second.
-+ *    'Bandwidth Per Lane' is calculated as:
-+ *    bpl = HTOT * VTOT * FPS * bpp / num_lanes;
-+ *
-+ * This function use the requested bandwidth to calculate:
-+ *
-+ * - mipi_pclk   = bpl / 2; ( / 2 is for CSI-2 DDR)
-+ * - mipi_phy_clk   = mipi_pclk * PLL1_DIV_MIPI;
-+ *
-+ * with these fixed parameters:
-+ *    PLL1_PREDIVP    = 1;
-+ *    PLL1_PREDIV     = 1; (MIPI_BIT_MODE == 8 ? 2 : 2,5);
-+ *    PLL1_DIVM       = 1;
-+ *    PLL1_DIV_MIPI   = 4;
-+ *
-+ * FIXME: this have been tested with 10-bit raw and 2 lanes setup only.
-+ * MIPI_DIV is fixed to value 2, but it -might- be changed according to the
-+ * above formula for setups with 1 lane or image formats with different bpp.
-+ *
-+ * FIXME: this deviates from the sensor manual documentation which is quite
-+ * thin on the MIPI clock tree generation part.
-+ */
-+
-+#define PLL1_PREDIVP         1     // bypass
-+#define PLL1_PREDIV          1     // bypass
-+#define PLL1_DIVM            1  // bypass
-+#define PLL1_DIV_MIPI        3  // div
-+#define PLL1_DIV_MIPI_BASE   1  // div
-+
-+#define PLL1_DIVSP    1   // no use
-+#define PLL1_DIVS     1   // no use
-+
-+#define PLL2_PREDIVP       0
-+#define PLL2_PREDIV        0
-+#define PLL2_DIVSP       1
-+#define PLL2_DIVS        4
-+#define PLL2_DIVDAC      1
-+
-+#define OV4689_PLL1_PREDIVP         0x030a   // bits[0]
-+#define OV4689_PLL1_PREDIV          0x0300   // bits[2:0]
-+#define OV4689_PLL1_MULTIPLIER      0x0301   // bits[9:8]  0x0302 bits[7:0]
-+#define OV4689_PLL1_DIVM            0x0303   // bits[3:0]
-+#define OV4689_PLL1_DIV_MIPI        0x0304   // bits[1:0]
-+
-+#define OV4689_PLL1_DIVSP           0x0305   //bits[1:0]
-+#define OV4689_PLL1_DIVS            0x0306   // bits[0]
-+
-+#define OV4689_PLL2_PREDIVP         0x0311   // bits[0]
-+#define OV4689_PLL2_PREDIV          0x030b   // bits[2:0]
-+#define OV4689_PLL2_MULTIPLIER      0x030c   // bits[9:8]   0x030d bits[7:0]
-+#define OV4689_PLL2_DIVSP           0x030f  // bits[3:0]
-+#define OV4689_PLL2_DIVS            0x030e  // bits[2:0]
-+#define OV4689_PLL2_DIVDAC          0x0312  // bits[3:0]
-+
-+static int ov4689_set_mipi_pclk(struct ov4689_dev *sensor,
-+                              unsigned long rate)
-+{
-+      const struct ov4689_mode_info *mode = sensor->current_mode;
-+      //const struct ov4689_mode_info *orig_mode = sensor->last_mode;
-+      u8 val;
-+      int ret = 0;
-+      int fps = ov4689_framerates[sensor->current_fr];
-+      u16 htot, val16;
-+
-+      htot = mode->htot * ov4689_framerates[mode->max_fps] / fps;
-+
-+      ret = ov4689_write_reg16(sensor, OV4689_REG_TIMING_HTS, htot);
-+
-+      ret = ov4689_read_reg(sensor, OV4689_REG_TIMING_HTS, &val);
-+      val16 = val << 8;
-+      ret = ov4689_read_reg(sensor, OV4689_REG_TIMING_HTS + 1, &val);
-+      val16 |= val;
-+
-+      st_info(ST_SENSOR, "fps = %d, max_fps = %d\n", fps, mode->max_fps);
-+      st_info(ST_SENSOR, "mode->htot = 0x%x, htot = 0x%x\n", mode->htot,
-+                      htot);
-+      st_info(ST_SENSOR, "reg: 0x%x = 0x%x\n", OV4689_REG_TIMING_HTS, val16);
-+
-+      return 0;
-+}
-+
-+/*
-+ * if sensor changes inside scaling or subsampling
-+ * change mode directly
-+ */
-+static int ov4689_set_mode_direct(struct ov4689_dev *sensor,
-+                              const struct ov4689_mode_info *mode)
-+{
-+      if (!mode->reg_data)
-+              return -EINVAL;
-+
-+      /* Write capture setting */
-+      return ov4689_load_regs(sensor, mode);
-+}
-+
-+static int ov4689_set_mode(struct ov4689_dev *sensor)
-+{
-+      const struct ov4689_mode_info *mode = sensor->current_mode;
-+
-+      int ret = 0;
-+
-+      ret = ov4689_set_mode_direct(sensor, mode);
-+      if (ret < 0)
-+              return ret;
-+
-+      ret = ov4689_set_mipi_pclk(sensor, 0);
-+      if (ret < 0)
-+              return 0;
-+
-+      sensor->pending_mode_change = false;
-+      sensor->last_mode = mode;
-+      return 0;
-+}
-+
-+/* restore the last set video mode after chip power-on */
-+static int ov4689_restore_mode(struct ov4689_dev *sensor)
-+{
-+      int ret;
-+
-+      /* first load the initial register values */
-+      ret = ov4689_load_regs(sensor, &ov4689_mode_init_data);
-+      if (ret < 0)
-+              return ret;
-+      sensor->last_mode = &ov4689_mode_init_data;
-+
-+      /* now restore the last capture mode */
-+      ret = ov4689_set_mode(sensor);
-+      if (ret < 0)
-+              return ret;
-+
-+      return ret;
-+}
-+
-+static void ov4689_power(struct ov4689_dev *sensor, bool enable)
-+{
-+      if (!sensor->pwdn_gpio)
-+              return;
-+      gpiod_set_value_cansleep(sensor->pwdn_gpio, enable ? 0 : 1);
-+}
-+
-+static void ov4689_reset(struct ov4689_dev *sensor)
-+{
-+      if (!sensor->reset_gpio)
-+              return;
-+
-+      gpiod_set_value_cansleep(sensor->reset_gpio, 0);
-+
-+      usleep_range(5000, 25000);
-+
-+      gpiod_set_value_cansleep(sensor->reset_gpio, 1);
-+      usleep_range(1000, 2000);
-+}
-+
-+static int ov4689_set_power_on(struct device *dev)
-+{
-+      struct i2c_client *client = to_i2c_client(dev);
-+      struct v4l2_subdev *sd = i2c_get_clientdata(client);
-+      struct ov4689_dev *sensor = to_ov4689_dev(sd);
-+      int ret;
-+
-+      ret = clk_prepare_enable(sensor->xclk);
-+      if (ret) {
-+              dev_err(&client->dev, "%s: failed to enable clock\n",
-+                      __func__);
-+              return ret;
-+      }
-+
-+      ret = regulator_bulk_enable(OV4689_NUM_SUPPLIES,
-+                              sensor->supplies);
-+      if (ret) {
-+              dev_err(&client->dev, "%s: failed to enable regulators\n",
-+                      __func__);
-+              goto xclk_off;
-+      }
-+
-+      ov4689_reset(sensor);
-+      ov4689_power(sensor, true);
-+
-+      return 0;
-+
-+xclk_off:
-+      clk_disable_unprepare(sensor->xclk);
-+      return ret;
-+}
-+
-+static int ov4689_set_power_off(struct device *dev)
-+{
-+      struct i2c_client *client = to_i2c_client(dev);
-+      struct v4l2_subdev *sd = i2c_get_clientdata(client);
-+      struct ov4689_dev *sensor = to_ov4689_dev(sd);
-+
-+      ov4689_power(sensor, false);
-+      regulator_bulk_disable(OV4689_NUM_SUPPLIES, sensor->supplies);
-+      clk_disable_unprepare(sensor->xclk);
-+
-+      return 0;
-+}
-+
-+static int ov4689_try_frame_interval(struct ov4689_dev *sensor,
-+                              struct v4l2_fract *fi,
-+                              u32 width, u32 height)
-+{
-+      const struct ov4689_mode_info *mode;
-+      enum ov4689_frame_rate rate = OV4689_15_FPS;
-+      int minfps, maxfps, best_fps, fps;
-+      int i;
-+
-+      minfps = ov4689_framerates[OV4689_15_FPS];
-+      maxfps = ov4689_framerates[OV4689_NUM_FRAMERATES - 1];
-+
-+      if (fi->numerator == 0) {
-+              fi->denominator = maxfps;
-+              fi->numerator = 1;
-+              rate = OV4689_60_FPS;
-+              goto find_mode;
-+      }
-+
-+      fps = clamp_val(DIV_ROUND_CLOSEST(fi->denominator, fi->numerator),
-+                      minfps, maxfps);
-+
-+      best_fps = minfps;
-+      for (i = 0; i < ARRAY_SIZE(ov4689_framerates); i++) {
-+              int curr_fps = ov4689_framerates[i];
-+
-+              if (abs(curr_fps - fps) < abs(best_fps - fps)) {
-+                      best_fps = curr_fps;
-+                      rate = i;
-+              }
-+      }
-+      st_info(ST_SENSOR, "best_fps = %d, fps = %d\n", best_fps, fps);
-+
-+      fi->numerator = 1;
-+      fi->denominator = best_fps;
-+
-+find_mode:
-+      mode = ov4689_find_mode(sensor, rate, width, height, false);
-+      return mode ? rate : -EINVAL;
-+}
-+
-+static int ov4689_enum_mbus_code(struct v4l2_subdev *sd,
-+                              struct v4l2_subdev_state *state,
-+                              struct v4l2_subdev_mbus_code_enum *code)
-+{
-+      if (code->pad != 0)
-+              return -EINVAL;
-+
-+      if (code->index)
-+              return -EINVAL;
-+
-+      code->code = MEDIA_BUS_FMT_SBGGR10_1X10;
-+      return 0;
-+}
-+
-+static int ov4689_get_fmt(struct v4l2_subdev *sd,
-+                      struct v4l2_subdev_state *state,
-+                      struct v4l2_subdev_format *format)
-+{
-+      struct ov4689_dev *sensor = to_ov4689_dev(sd);
-+      struct v4l2_mbus_framefmt *fmt;
-+
-+      if (format->pad != 0)
-+              return -EINVAL;
-+
-+      mutex_lock(&sensor->lock);
-+
-+      if (format->which == V4L2_SUBDEV_FORMAT_TRY)
-+              fmt = v4l2_subdev_get_try_format(&sensor->sd, state,
-+                                              format->pad);
-+      else
-+              fmt = &sensor->fmt;
-+
-+      format->format = *fmt;
-+
-+      mutex_unlock(&sensor->lock);
-+
-+      return 0;
-+}
-+
-+static int ov4689_try_fmt_internal(struct v4l2_subdev *sd,
-+                              struct v4l2_mbus_framefmt *fmt,
-+                              enum ov4689_frame_rate fr,
-+                              const struct ov4689_mode_info **new_mode)
-+{
-+      struct ov4689_dev *sensor = to_ov4689_dev(sd);
-+      const struct ov4689_mode_info *mode;
-+
-+      mode = ov4689_find_mode(sensor, fr, fmt->width, fmt->height, true);
-+      if (!mode)
-+              return -EINVAL;
-+      fmt->width = mode->hact;
-+      fmt->height = mode->vact;
-+
-+      if (new_mode)
-+              *new_mode = mode;
-+
-+      fmt->code = MEDIA_BUS_FMT_SBGGR10_1X10;
-+
-+      return 0;
-+}
-+
-+static int ov4689_set_fmt(struct v4l2_subdev *sd,
-+                      struct v4l2_subdev_state *state,
-+                      struct v4l2_subdev_format *format)
-+{
-+      struct ov4689_dev *sensor = to_ov4689_dev(sd);
-+      const struct ov4689_mode_info *new_mode;
-+      struct v4l2_mbus_framefmt *mbus_fmt = &format->format;
-+      struct v4l2_mbus_framefmt *fmt;
-+      int ret;
-+
-+      if (format->pad != 0)
-+              return -EINVAL;
-+
-+      mutex_lock(&sensor->lock);
-+
-+      if (sensor->streaming) {
-+              ret = -EBUSY;
-+              goto out;
-+      }
-+
-+      ret = ov4689_try_fmt_internal(sd, mbus_fmt, 0, &new_mode);
-+      if (ret)
-+              goto out;
-+
-+      if (format->which == V4L2_SUBDEV_FORMAT_TRY)
-+              fmt = v4l2_subdev_get_try_format(sd, state, 0);
-+      else
-+              fmt = &sensor->fmt;
-+
-+      *fmt = *mbus_fmt;
-+
-+      if (new_mode != sensor->current_mode) {
-+              sensor->current_mode = new_mode;
-+              sensor->pending_mode_change = true;
-+      }
-+      if (new_mode->max_fps < sensor->current_fr) {
-+              sensor->current_fr = new_mode->max_fps;
-+              sensor->frame_interval.numerator = 1;
-+              sensor->frame_interval.denominator =
-+                      ov4689_framerates[sensor->current_fr];
-+              sensor->current_mode = new_mode;
-+              sensor->pending_mode_change = true;
-+      }
-+
-+      __v4l2_ctrl_s_ctrl_int64(sensor->ctrls.pixel_rate,
-+                              ov4689_calc_pixel_rate(sensor));
-+out:
-+      mutex_unlock(&sensor->lock);
-+      return ret;
-+}
-+
-+/*
-+ * Sensor Controls.
-+ */
-+
-+static int ov4689_set_ctrl_hue(struct ov4689_dev *sensor, int value)
-+{
-+      int ret = 0;
-+
-+      return ret;
-+}
-+
-+static int ov4689_set_ctrl_contrast(struct ov4689_dev *sensor, int value)
-+{
-+      int ret = 0;
-+
-+      return ret;
-+}
-+
-+static int ov4689_set_ctrl_saturation(struct ov4689_dev *sensor, int value)
-+{
-+      int ret  = 0;
-+
-+      return ret;
-+}
-+
-+static int ov4689_set_ctrl_white_balance(struct ov4689_dev *sensor, int awb)
-+{
-+      struct ov4689_ctrls *ctrls = &sensor->ctrls;
-+      int ret = 0;
-+
-+      if (!awb && (ctrls->red_balance->is_new
-+                      || ctrls->blue_balance->is_new)) {
-+              u16 red = (u16)ctrls->red_balance->val;
-+              u16 blue = (u16)ctrls->blue_balance->val;
-+
-+              st_info(ST_SENSOR, "red = 0x%x, blue = 0x%x\n", red, blue);
-+              ret = ov4689_write_reg16(sensor, OV4689_REG_AWB_R_GAIN, red);
-+              if (ret)
-+                      return ret;
-+              ret = ov4689_write_reg16(sensor, OV4689_REG_AWB_B_GAIN, blue);
-+      }
-+      return ret;
-+}
-+
-+static int ov4689_set_ctrl_exposure(struct ov4689_dev *sensor,
-+                              enum v4l2_exposure_auto_type auto_exposure)
-+{
-+      struct ov4689_ctrls *ctrls = &sensor->ctrls;
-+      bool auto_exp = (auto_exposure == V4L2_EXPOSURE_AUTO);
-+      int ret = 0;
-+
-+      if (!auto_exp && ctrls->exposure->is_new) {
-+              u16 max_exp = 0;
-+
-+              ret = ov4689_read_reg16(sensor, OV4689_REG_V_OUTPUT_SIZE,
-+                                      &max_exp);
-+
-+              ret = ov4689_get_vts(sensor);
-+              if (ret < 0)
-+                      return ret;
-+              max_exp += ret;
-+              ret = 0;
-+
-+              st_info(ST_SENSOR, "%s, max_exp = 0x%x\n", __func__, max_exp);
-+              if (ctrls->exposure->val < max_exp)
-+                      ret = ov4689_set_exposure(sensor, ctrls->exposure->val);
-+      }
-+
-+      return ret;
-+}
-+
-+static const s64 link_freq_menu_items[] = {
-+      OV4689_LINK_FREQ_500MHZ
-+};
-+
-+static const char * const test_pattern_menu[] = {
-+      "Disabled",
-+      "Color bars",
-+      "Color bars w/ rolling bar",
-+      "Color squares",
-+      "Color squares w/ rolling bar",
-+};
-+
-+#define OV4689_TEST_ENABLE            BIT(7)
-+#define OV4689_TEST_ROLLING           BIT(6)  /* rolling horizontal bar */
-+#define OV4689_TEST_TRANSPARENT               BIT(5)
-+#define OV4689_TEST_SQUARE_BW         BIT(4)  /* black & white squares */
-+#define OV4689_TEST_BAR_STANDARD      (0 << 2)
-+#define OV4689_TEST_BAR_DARKER_1      (1 << 2)
-+#define OV4689_TEST_BAR_DARKER_2      (2 << 2)
-+#define OV4689_TEST_BAR_DARKER_3      (3 << 2)
-+#define OV4689_TEST_BAR                       (0 << 0)
-+#define OV4689_TEST_RANDOM            (1 << 0)
-+#define OV4689_TEST_SQUARE            (2 << 0)
-+#define OV4689_TEST_BLACK             (3 << 0)
-+
-+static const u8 test_pattern_val[] = {
-+      0,
-+      OV4689_TEST_ENABLE | OV4689_TEST_BAR_STANDARD |
-+              OV4689_TEST_BAR,
-+      OV4689_TEST_ENABLE | OV4689_TEST_ROLLING |
-+              OV4689_TEST_BAR_DARKER_1 | OV4689_TEST_BAR,
-+      OV4689_TEST_ENABLE | OV4689_TEST_SQUARE,
-+      OV4689_TEST_ENABLE | OV4689_TEST_ROLLING | OV4689_TEST_SQUARE,
-+};
-+
-+static int ov4689_set_ctrl_test_pattern(struct ov4689_dev *sensor, int value)
-+{
-+      return ov4689_write_reg(sensor, OV4689_REG_TEST_PATTERN,
-+                      test_pattern_val[value]);
-+}
-+
-+static int ov4689_set_ctrl_light_freq(struct ov4689_dev *sensor, int value)
-+{
-+      return 0;
-+}
-+
-+static int ov4689_set_ctrl_hflip(struct ov4689_dev *sensor, int value)
-+{
-+      /*
-+       * TIMING TC REG21:
-+       * - [2]:       Digital mirror
-+       * - [1]:       Array mirror
-+       */
-+      return ov4689_mod_reg(sensor, OV4689_REG_TIMING_TC_REG21,
-+                      BIT(2) | BIT(1),
-+                      (!(value ^ sensor->upside_down)) ?
-+                      (BIT(2) | BIT(1)) : 0);
-+}
-+
-+static int ov4689_set_ctrl_vflip(struct ov4689_dev *sensor, int value)
-+{
-+      /*
-+       * TIMING TC REG20:
-+       * - [2]:       Digital vflip
-+       * - [1]:       Array vflip
-+       */
-+      return ov4689_mod_reg(sensor, OV4689_REG_TIMING_TC_REG20,
-+                              BIT(2) | BIT(1),
-+                              (value ^ sensor->upside_down) ?
-+                              (BIT(2) | BIT(1)) : 0);
-+}
-+
-+static int ov4689_g_volatile_ctrl(struct v4l2_ctrl *ctrl)
-+{
-+      struct v4l2_subdev *sd = ctrl_to_sd(ctrl);
-+      struct ov4689_dev *sensor = to_ov4689_dev(sd);
-+      int val;
-+
-+      /* v4l2_ctrl_lock() locks our own mutex */
-+
-+      if (!pm_runtime_get_if_in_use(&sensor->i2c_client->dev))
-+              return 0;
-+
-+      switch (ctrl->id) {
-+      case V4L2_CID_ANALOGUE_GAIN:
-+              val = ov4689_get_gain(sensor);
-+              break;
-+      }
-+
-+      pm_runtime_put(&sensor->i2c_client->dev);
-+
-+      return 0;
-+}
-+
-+static int ov4689_s_ctrl(struct v4l2_ctrl *ctrl)
-+{
-+      struct v4l2_subdev *sd = ctrl_to_sd(ctrl);
-+      struct ov4689_dev *sensor = to_ov4689_dev(sd);
-+      int ret;
-+
-+      /* v4l2_ctrl_lock() locks our own mutex */
-+
-+      /*
-+       * If the device is not powered up by the host driver do
-+       * not apply any controls to H/W at this time. Instead
-+       * the controls will be restored at start streaming time.
-+       */
-+      if (!pm_runtime_get_if_in_use(&sensor->i2c_client->dev))
-+              return 0;
-+
-+      switch (ctrl->id) {
-+      case V4L2_CID_ANALOGUE_GAIN:
-+              ret = ov4689_set_gain(sensor, ctrl->val);
-+              break;
-+      case V4L2_CID_EXPOSURE:
-+              ret = ov4689_set_ctrl_exposure(sensor, V4L2_EXPOSURE_MANUAL);
-+              break;
-+      case V4L2_CID_AUTO_WHITE_BALANCE:
-+              ret = ov4689_set_ctrl_white_balance(sensor, ctrl->val);
-+              break;
-+      case V4L2_CID_HUE:
-+              ret = ov4689_set_ctrl_hue(sensor, ctrl->val);
-+              break;
-+      case V4L2_CID_CONTRAST:
-+              ret = ov4689_set_ctrl_contrast(sensor, ctrl->val);
-+              break;
-+      case V4L2_CID_SATURATION:
-+              ret = ov4689_set_ctrl_saturation(sensor, ctrl->val);
-+              break;
-+      case V4L2_CID_TEST_PATTERN:
-+              ret = ov4689_set_ctrl_test_pattern(sensor, ctrl->val);
-+              break;
-+      case V4L2_CID_POWER_LINE_FREQUENCY:
-+              ret = ov4689_set_ctrl_light_freq(sensor, ctrl->val);
-+              break;
-+      case V4L2_CID_HFLIP:
-+              ret = ov4689_set_ctrl_hflip(sensor, ctrl->val);
-+              break;
-+      case V4L2_CID_VFLIP:
-+              ret = ov4689_set_ctrl_vflip(sensor, ctrl->val);
-+              break;
-+      default:
-+              ret = -EINVAL;
-+              break;
-+      }
-+
-+      pm_runtime_put(&sensor->i2c_client->dev);
-+
-+      return ret;
-+}
-+
-+static const struct v4l2_ctrl_ops ov4689_ctrl_ops = {
-+      .g_volatile_ctrl = ov4689_g_volatile_ctrl,
-+      .s_ctrl = ov4689_s_ctrl,
-+};
-+
-+static int ov4689_init_controls(struct ov4689_dev *sensor)
-+{
-+      const struct v4l2_ctrl_ops *ops = &ov4689_ctrl_ops;
-+      struct ov4689_ctrls *ctrls = &sensor->ctrls;
-+      struct v4l2_ctrl_handler *hdl = &ctrls->handler;
-+      int ret;
-+
-+      v4l2_ctrl_handler_init(hdl, 32);
-+
-+      /* we can use our own mutex for the ctrl lock */
-+      hdl->lock = &sensor->lock;
-+
-+      /* Clock related controls */
-+      ctrls->pixel_rate = v4l2_ctrl_new_std(hdl, ops, V4L2_CID_PIXEL_RATE,
-+                                      0, INT_MAX, 1,
-+                                      ov4689_calc_pixel_rate(sensor));
-+
-+      /* Auto/manual white balance */
-+      ctrls->auto_wb = v4l2_ctrl_new_std(hdl, ops,
-+                                      V4L2_CID_AUTO_WHITE_BALANCE,
-+                                      0, 1, 1, 0);
-+      ctrls->blue_balance = v4l2_ctrl_new_std(hdl, ops, V4L2_CID_BLUE_BALANCE,
-+                                              0, 4095, 1, 1024);
-+      ctrls->red_balance = v4l2_ctrl_new_std(hdl, ops, V4L2_CID_RED_BALANCE,
-+                                              0, 4095, 1, 1024);
-+
-+      ctrls->exposure = v4l2_ctrl_new_std(hdl, ops, V4L2_CID_EXPOSURE,
-+                                      4, 0xfff8, 1, 0x4c00);
-+      ctrls->anal_gain = v4l2_ctrl_new_std(hdl, ops, V4L2_CID_ANALOGUE_GAIN,
-+                                      0x10, 0xfff8, 1, 0x0080);
-+      ctrls->test_pattern =
-+              v4l2_ctrl_new_std_menu_items(hdl, ops, V4L2_CID_TEST_PATTERN,
-+                                      ARRAY_SIZE(test_pattern_menu) - 1,
-+                                      0, 0, test_pattern_menu);
-+      ctrls->hflip = v4l2_ctrl_new_std(hdl, ops, V4L2_CID_HFLIP,
-+                                      0, 1, 1, 0);
-+      ctrls->vflip = v4l2_ctrl_new_std(hdl, ops, V4L2_CID_VFLIP,
-+                                      0, 1, 1, 0);
-+      ctrls->light_freq =
-+              v4l2_ctrl_new_std_menu(hdl, ops,
-+                                      V4L2_CID_POWER_LINE_FREQUENCY,
-+                                      V4L2_CID_POWER_LINE_FREQUENCY_AUTO, 0,
-+                                      V4L2_CID_POWER_LINE_FREQUENCY_50HZ);
-+      ctrls->link_freq = v4l2_ctrl_new_int_menu(hdl, ops, V4L2_CID_LINK_FREQ,
-+                                      0, 0, link_freq_menu_items);
-+      if (hdl->error) {
-+              ret = hdl->error;
-+              goto free_ctrls;
-+      }
-+
-+      ctrls->pixel_rate->flags |= V4L2_CTRL_FLAG_READ_ONLY;
-+      ctrls->link_freq->flags |= V4L2_CTRL_FLAG_READ_ONLY;
-+      // ctrls->exposure->flags |= V4L2_CTRL_FLAG_VOLATILE;
-+      // ctrls->anal_gain->flags |= V4L2_CTRL_FLAG_VOLATILE;
-+
-+      v4l2_ctrl_auto_cluster(3, &ctrls->auto_wb, 0, false);
-+
-+      sensor->sd.ctrl_handler = hdl;
-+      return 0;
-+
-+free_ctrls:
-+      v4l2_ctrl_handler_free(hdl);
-+      return ret;
-+}
-+
-+static int ov4689_enum_frame_size(struct v4l2_subdev *sd,
-+                              struct v4l2_subdev_state *state,
-+                              struct v4l2_subdev_frame_size_enum *fse)
-+{
-+      if (fse->pad != 0)
-+              return -EINVAL;
-+      if (fse->index >= OV4689_NUM_MODES)
-+              return -EINVAL;
-+
-+      fse->min_width =
-+              ov4689_mode_data[fse->index].hact;
-+      fse->max_width = fse->min_width;
-+      fse->min_height =
-+              ov4689_mode_data[fse->index].vact;
-+      fse->max_height = fse->min_height;
-+
-+      return 0;
-+}
-+
-+static int ov4689_enum_frame_interval(
-+      struct v4l2_subdev *sd,
-+      struct v4l2_subdev_state *state,
-+      struct v4l2_subdev_frame_interval_enum *fie)
-+{
-+      //struct ov4689_dev *sensor = to_ov4689_dev(sd);
-+      struct v4l2_fract tpf;
-+      int i = 0;
-+
-+      if (fie->pad != 0)
-+              return -EINVAL;
-+      if (fie->index >= OV4689_NUM_FRAMERATES)
-+              return -EINVAL;
-+
-+      tpf.numerator = 1;
-+      tpf.denominator = ov4689_framerates[fie->index];
-+
-+      // ret = ov4689_try_frame_interval(sensor, &tpf,
-+      //              fie->width, fie->height);
-+      // if (ret < 0)
-+      //      return -EINVAL;
-+
-+      pr_debug("fie->width = %d, fie->height = %d\n", fie->width, fie->height);
-+      for (i = 0; i < OV4689_NUM_MODES; i++) {
-+              if (fie->width == ov4689_mode_data[i].hact &&
-+                      fie->height == ov4689_mode_data[i].vact)
-+                      break;
-+      }
-+      if (i == OV4689_NUM_MODES)
-+              return -ENOTTY;
-+
-+      fie->interval = tpf;
-+      fie->width = ov4689_mode_data[i].hact;
-+      fie->height = ov4689_mode_data[i].vact;
-+
-+      return 0;
-+}
-+
-+static int ov4689_g_frame_interval(struct v4l2_subdev *sd,
-+                              struct v4l2_subdev_frame_interval *fi)
-+{
-+      struct ov4689_dev *sensor = to_ov4689_dev(sd);
-+
-+      mutex_lock(&sensor->lock);
-+      fi->interval = sensor->frame_interval;
-+      mutex_unlock(&sensor->lock);
-+
-+      return 0;
-+}
-+
-+static int ov4689_s_frame_interval(struct v4l2_subdev *sd,
-+                              struct v4l2_subdev_frame_interval *fi)
-+{
-+      struct ov4689_dev *sensor = to_ov4689_dev(sd);
-+      const struct ov4689_mode_info *mode;
-+      int frame_rate, ret = 0;
-+
-+      if (fi->pad != 0)
-+              return -EINVAL;
-+
-+      mutex_lock(&sensor->lock);
-+
-+      if (sensor->streaming) {
-+              ret = -EBUSY;
-+              goto out;
-+      }
-+
-+      mode = sensor->current_mode;
-+
-+      frame_rate = ov4689_try_frame_interval(sensor, &fi->interval,
-+                                      mode->hact, mode->vact);
-+      if (frame_rate < 0) {
-+              /* Always return a valid frame interval value */
-+              fi->interval = sensor->frame_interval;
-+              goto out;
-+      }
-+
-+      mode = ov4689_find_mode(sensor, frame_rate, mode->hact,
-+                              mode->vact, true);
-+      if (!mode) {
-+              ret = -EINVAL;
-+              goto out;
-+      }
-+
-+      if (mode != sensor->current_mode ||
-+              frame_rate != sensor->current_fr) {
-+              sensor->current_fr = frame_rate;
-+              sensor->frame_interval = fi->interval;
-+              sensor->current_mode = mode;
-+              sensor->pending_mode_change = true;
-+
-+              __v4l2_ctrl_s_ctrl_int64(sensor->ctrls.pixel_rate,
-+                                      ov4689_calc_pixel_rate(sensor));
-+      }
-+out:
-+      mutex_unlock(&sensor->lock);
-+      return ret;
-+}
-+
-+static int ov4689_stream_start(struct ov4689_dev *sensor, int enable)
-+{
-+      return ov4689_write_reg(sensor, OV4689_REG_STREAM_ON, enable);
-+}
-+
-+static int ov4689_s_stream(struct v4l2_subdev *sd, int enable)
-+{
-+      struct ov4689_dev *sensor = to_ov4689_dev(sd);
-+      int ret = 0;
-+
-+      if (enable) {
-+              pm_runtime_get_sync(&sensor->i2c_client->dev);
-+
-+              ret = v4l2_ctrl_handler_setup(&sensor->ctrls.handler);
-+              if (ret) {
-+                      pm_runtime_put_sync(&sensor->i2c_client->dev);
-+                      return ret;
-+              }
-+      }
-+
-+      mutex_lock(&sensor->lock);
-+
-+      if (sensor->streaming == !enable) {
-+              if (enable) {
-+                      ret = ov4689_restore_mode(sensor);
-+                      if (ret)
-+                              goto out;
-+              }
-+
-+              if (enable && sensor->pending_mode_change) {
-+                      ret = ov4689_set_mode(sensor);
-+                      if (ret)
-+                              goto out;
-+              }
-+
-+              if (sensor->ep.bus.mipi_csi2.num_data_lanes == 2) {
-+                      ov4689_write_reg(sensor, OV4689_REG_MIPI_SC_CTRL_HI, 0x32);
-+                      ov4689_write_reg(sensor, OV4689_REG_MIPI_SC_CTRL_LOW, 0x0c);
-+              } else if (sensor->ep.bus.mipi_csi2.num_data_lanes == 4) {
-+                      ov4689_write_reg(sensor, OV4689_REG_MIPI_SC_CTRL_HI, 0x72);
-+                      ov4689_write_reg(sensor, OV4689_REG_MIPI_SC_CTRL_LOW, 0x00);
-+              } else {
-+                      dev_err(&sensor->i2c_client->dev, "Unsupport lane num\n");
-+              }
-+
-+              ret = ov4689_stream_start(sensor, enable);
-+              if (ret)
-+                      goto out;
-+      }
-+      sensor->streaming += enable ? 1 : -1;
-+      WARN_ON(sensor->streaming < 0);
-+out:
-+      mutex_unlock(&sensor->lock);
-+
-+      if (!enable || ret)
-+              pm_runtime_put_sync(&sensor->i2c_client->dev);
-+
-+      return ret;
-+}
-+
-+static const struct v4l2_subdev_core_ops ov4689_core_ops = {
-+      .log_status = v4l2_ctrl_subdev_log_status,
-+      .subscribe_event = v4l2_ctrl_subdev_subscribe_event,
-+      .unsubscribe_event = v4l2_event_subdev_unsubscribe,
-+};
-+
-+static const struct v4l2_subdev_video_ops ov4689_video_ops = {
-+      .g_frame_interval = ov4689_g_frame_interval,
-+      .s_frame_interval = ov4689_s_frame_interval,
-+      .s_stream = ov4689_s_stream,
-+};
-+
-+static const struct v4l2_subdev_pad_ops ov4689_pad_ops = {
-+      .enum_mbus_code = ov4689_enum_mbus_code,
-+      .get_fmt = ov4689_get_fmt,
-+      .set_fmt = ov4689_set_fmt,
-+      .enum_frame_size = ov4689_enum_frame_size,
-+      .enum_frame_interval = ov4689_enum_frame_interval,
-+};
-+
-+static const struct v4l2_subdev_ops ov4689_subdev_ops = {
-+      .core = &ov4689_core_ops,
-+      .video = &ov4689_video_ops,
-+      .pad = &ov4689_pad_ops,
-+};
-+
-+static int ov4689_get_regulators(struct ov4689_dev *sensor)
-+{
-+      int i;
-+
-+      for (i = 0; i < OV4689_NUM_SUPPLIES; i++)
-+              sensor->supplies[i].supply = ov4689_supply_name[i];
-+
-+      return devm_regulator_bulk_get(&sensor->i2c_client->dev,
-+                                      OV4689_NUM_SUPPLIES,
-+                                      sensor->supplies);
-+}
-+
-+static int ov4689_check_chip_id(struct ov4689_dev *sensor)
-+{
-+      struct i2c_client *client = sensor->i2c_client;
-+      int ret = 0;
-+      u16 chip_id;
-+
-+      ret = ov4689_read_reg16(sensor, OV4689_REG_CHIP_ID, &chip_id);
-+      if (ret) {
-+              dev_err(&client->dev, "%s: failed to read chip identifier\n",
-+                      __func__);
-+              return ret;
-+      }
-+
-+      if (chip_id != OV4689_CHIP_ID) {
-+              dev_err(&client->dev, "%s: wrong chip identifier, expected 0x%x,  got 0x%x\n",
-+                      __func__, OV4689_CHIP_ID, chip_id);
-+              return -ENXIO;
-+      }
-+      dev_err(&client->dev, "%s: chip identifier, got 0x%x\n",
-+              __func__, chip_id);
-+
-+      return 0;
-+}
-+
-+static int ov4689_probe(struct i2c_client *client)
-+{
-+      struct device *dev = &client->dev;
-+      struct fwnode_handle *endpoint;
-+      struct ov4689_dev *sensor;
-+      struct v4l2_mbus_framefmt *fmt;
-+      u32 rotation;
-+      int ret;
-+
-+      sensor = devm_kzalloc(dev, sizeof(*sensor), GFP_KERNEL);
-+      if (!sensor)
-+              return -ENOMEM;
-+
-+      sensor->i2c_client = client;
-+
-+      fmt = &sensor->fmt;
-+      fmt->code = MEDIA_BUS_FMT_SBGGR10_1X10;
-+      fmt->colorspace = V4L2_COLORSPACE_SRGB;
-+      fmt->ycbcr_enc = V4L2_MAP_YCBCR_ENC_DEFAULT(fmt->colorspace);
-+      fmt->quantization = V4L2_QUANTIZATION_FULL_RANGE;
-+      fmt->xfer_func = V4L2_MAP_XFER_FUNC_DEFAULT(fmt->colorspace);
-+      fmt->width = 1920;
-+      fmt->height = 1080;
-+      fmt->field = V4L2_FIELD_NONE;
-+      sensor->frame_interval.numerator = 1;
-+      sensor->frame_interval.denominator = ov4689_framerates[OV4689_30_FPS];
-+      sensor->current_fr = OV4689_30_FPS;
-+      sensor->current_mode =
-+              &ov4689_mode_data[OV4689_MODE_1080P_1920_1080];
-+      sensor->last_mode = sensor->current_mode;
-+
-+
-+      /* optional indication of physical rotation of sensor */
-+      ret = fwnode_property_read_u32(dev_fwnode(&client->dev), "rotation",
-+                                      &rotation);
-+      if (!ret) {
-+              switch (rotation) {
-+              case 180:
-+                      sensor->upside_down = true;
-+                      fallthrough;
-+              case 0:
-+                      break;
-+              default:
-+                      dev_warn(dev, "%u degrees rotation is not supported, ignoring...\n",
-+                              rotation);
-+              }
-+      }
-+
-+      endpoint = fwnode_graph_get_next_endpoint(dev_fwnode(&client->dev),
-+                                              NULL);
-+      if (!endpoint) {
-+              dev_err(dev, "endpoint node not found\n");
-+              return -EINVAL;
-+      }
-+
-+      ret = v4l2_fwnode_endpoint_parse(endpoint, &sensor->ep);
-+      fwnode_handle_put(endpoint);
-+      if (ret) {
-+              dev_err(dev, "Could not parse endpoint\n");
-+              return ret;
-+      }
-+
-+      if (sensor->ep.bus_type != V4L2_MBUS_CSI2_DPHY) {
-+              dev_err(dev, "Unsupported bus type %d\n", sensor->ep.bus_type);
-+              return -EINVAL;
-+      }
-+
-+      /* get system clock (xclk) */
-+      sensor->xclk = devm_clk_get(dev, "xclk");
-+      if (IS_ERR(sensor->xclk)) {
-+              dev_err(dev, "failed to get xclk\n");
-+              return PTR_ERR(sensor->xclk);
-+      }
-+
-+      sensor->xclk_freq = clk_get_rate(sensor->xclk);
-+      if (sensor->xclk_freq < OV4689_XCLK_MIN ||
-+              sensor->xclk_freq > OV4689_XCLK_MAX) {
-+              dev_err(dev, "xclk frequency out of range: %d Hz\n",
-+                      sensor->xclk_freq);
-+              return -EINVAL;
-+      }
-+
-+      /* request optional power down pin */
-+      sensor->pwdn_gpio = devm_gpiod_get_optional(dev, "powerdown",
-+                                              GPIOD_OUT_HIGH);
-+      if (IS_ERR(sensor->pwdn_gpio))
-+              return PTR_ERR(sensor->pwdn_gpio);
-+
-+      /* request optional reset pin */
-+      sensor->reset_gpio = devm_gpiod_get_optional(dev, "reset",
-+                                              GPIOD_OUT_HIGH);
-+      if (IS_ERR(sensor->reset_gpio))
-+              return PTR_ERR(sensor->reset_gpio);
-+
-+      v4l2_i2c_subdev_init(&sensor->sd, client, &ov4689_subdev_ops);
-+
-+      sensor->sd.flags |= V4L2_SUBDEV_FL_HAS_DEVNODE |
-+                      V4L2_SUBDEV_FL_HAS_EVENTS;
-+      sensor->pad.flags = MEDIA_PAD_FL_SOURCE;
-+      sensor->sd.entity.function = MEDIA_ENT_F_CAM_SENSOR;
-+      ret = media_entity_pads_init(&sensor->sd.entity, 1, &sensor->pad);
-+      if (ret)
-+              return ret;
-+
-+      ret = ov4689_get_regulators(sensor);
-+      if (ret)
-+              return ret;
-+
-+      mutex_init(&sensor->lock);
-+
-+      ret = ov4689_set_power_on(dev);
-+      if (ret) {
-+              dev_err(dev, "failed to power on\n");
-+              goto entity_cleanup;
-+      }
-+
-+      ret = ov4689_check_chip_id(sensor);
-+      if (ret)
-+              goto error_power_off;
-+
-+      ret = ov4689_init_controls(sensor);
-+      if (ret)
-+              goto error_power_off;
-+
-+      ret = v4l2_async_register_subdev_sensor(&sensor->sd);
-+      if (ret)
-+              goto free_ctrls;
-+
-+      pm_runtime_set_active(dev);
-+      pm_runtime_enable(dev);
-+
-+      return 0;
-+
-+free_ctrls:
-+      v4l2_ctrl_handler_free(&sensor->ctrls.handler);
-+error_power_off:
-+      ov4689_set_power_off(dev);
-+entity_cleanup:
-+      media_entity_cleanup(&sensor->sd.entity);
-+      mutex_destroy(&sensor->lock);
-+      return ret;
-+}
-+
-+static void ov4689_remove(struct i2c_client *client)
-+{
-+      struct v4l2_subdev *sd = i2c_get_clientdata(client);
-+      struct ov4689_dev *sensor = to_ov4689_dev(sd);
-+
-+      v4l2_async_unregister_subdev(&sensor->sd);
-+      media_entity_cleanup(&sensor->sd.entity);
-+      v4l2_ctrl_handler_free(&sensor->ctrls.handler);
-+      mutex_destroy(&sensor->lock);
-+
-+      pm_runtime_disable(&client->dev);
-+      if (!pm_runtime_status_suspended(&client->dev))
-+              ov4689_set_power_off(&client->dev);
-+      pm_runtime_set_suspended(&client->dev);
-+}
-+
-+static const struct i2c_device_id ov4689_id[] = {
-+      { "ov4689", 0 },
-+      {},
-+};
-+MODULE_DEVICE_TABLE(i2c, ov4689_id);
-+
-+static const struct of_device_id ov4689_dt_ids[] = {
-+      { .compatible = "ovti,ov4689" },
-+      { /* sentinel */ }
-+};
-+MODULE_DEVICE_TABLE(of, ov4689_dt_ids);
-+
-+static const struct dev_pm_ops ov4689_pm_ops = {
-+      SET_RUNTIME_PM_OPS(ov4689_set_power_off, ov4689_set_power_on, NULL)
-+};
-+
-+static struct i2c_driver ov4689_i2c_driver = {
-+      .driver = {
-+              .name  = "ov4689",
-+              .of_match_table = ov4689_dt_ids,
-+              .pm = &ov4689_pm_ops,
-+      },
-+      .id_table = ov4689_id,
-+      .probe = ov4689_probe,
-+      .remove   = ov4689_remove,
-+};
-+
-+module_i2c_driver(ov4689_i2c_driver);
-+
-+MODULE_DESCRIPTION("OV4689 MIPI Camera Subdev Driver");
-+MODULE_LICENSE("GPL");
---- /dev/null
-+++ b/drivers/media/platform/starfive/v4l2_driver/ov5640.c
-@@ -0,0 +1,3227 @@
-+// SPDX-License-Identifier: GPL-2.0-or-later
-+/*
-+ * Copyright (C) 2011-2013 Freescale Semiconductor, Inc. All Rights Reserved.
-+ * Copyright (C) 2014-2017 Mentor Graphics Inc.
-+ *
-+ */
-+
-+#include <linux/clk.h>
-+#include <linux/clk-provider.h>
-+#include <linux/clkdev.h>
-+#include <linux/ctype.h>
-+#include <linux/delay.h>
-+#include <linux/device.h>
-+#include <linux/gpio/consumer.h>
-+#include <linux/i2c.h>
-+#include <linux/init.h>
-+#include <linux/module.h>
-+#include <linux/of_device.h>
-+#include <linux/regulator/consumer.h>
-+#include <linux/slab.h>
-+#include <linux/types.h>
-+#include <media/v4l2-async.h>
-+#include <media/v4l2-ctrls.h>
-+#include <media/v4l2-device.h>
-+#include <media/v4l2-event.h>
-+#include <media/v4l2-fwnode.h>
-+#include <media/v4l2-subdev.h>
-+#include "stfcamss.h"
-+
-+/* min/typical/max system clock (xclk) frequencies */
-+#define OV5640_XCLK_MIN  6000000
-+#define OV5640_XCLK_MAX 54000000
-+
-+#define OV5640_SKIP_FRAMES      4
-+
-+#define OV5640_CHIP_ID                0x5640
-+#define OV5640_DEFAULT_SLAVE_ID 0x3c
-+
-+#define OV5640_REG_SYS_RESET02                0x3002
-+#define OV5640_REG_SYS_CLOCK_ENABLE02 0x3006
-+#define OV5640_REG_SYS_CTRL0          0x3008
-+#define OV5640_REG_SYS_CTRL0_SW_PWDN  0x42
-+#define OV5640_REG_SYS_CTRL0_SW_PWUP  0x02
-+#define OV5640_REG_CHIP_ID            0x300a
-+#define OV5640_REG_IO_MIPI_CTRL00     0x300e
-+#define OV5640_REG_PAD_OUTPUT_ENABLE01        0x3017
-+#define OV5640_REG_PAD_OUTPUT_ENABLE02        0x3018
-+#define OV5640_REG_PAD_OUTPUT00               0x3019
-+#define OV5640_REG_SYSTEM_CONTROL1    0x302e
-+#define OV5640_REG_SC_PLL_CTRL0               0x3034
-+#define OV5640_REG_SC_PLL_CTRL1               0x3035
-+#define OV5640_REG_SC_PLL_CTRL2               0x3036
-+#define OV5640_REG_SC_PLL_CTRL3               0x3037
-+#define OV5640_REG_SLAVE_ID           0x3100
-+#define OV5640_REG_SCCB_SYS_CTRL1     0x3103
-+#define OV5640_REG_SYS_ROOT_DIVIDER   0x3108
-+#define OV5640_REG_AWB_R_GAIN         0x3400
-+#define OV5640_REG_AWB_G_GAIN         0x3402
-+#define OV5640_REG_AWB_B_GAIN         0x3404
-+#define OV5640_REG_AWB_MANUAL_CTRL    0x3406
-+#define OV5640_REG_AEC_PK_EXPOSURE_HI 0x3500
-+#define OV5640_REG_AEC_PK_EXPOSURE_MED        0x3501
-+#define OV5640_REG_AEC_PK_EXPOSURE_LO 0x3502
-+#define OV5640_REG_AEC_PK_MANUAL      0x3503
-+#define OV5640_REG_AEC_PK_REAL_GAIN   0x350a
-+#define OV5640_REG_AEC_PK_VTS         0x350c
-+#define OV5640_REG_TIMING_DVPHO               0x3808
-+#define OV5640_REG_TIMING_DVPVO               0x380a
-+#define OV5640_REG_TIMING_HTS         0x380c
-+#define OV5640_REG_TIMING_VTS         0x380e
-+#define OV5640_REG_TIMING_TC_REG20    0x3820
-+#define OV5640_REG_TIMING_TC_REG21    0x3821
-+#define OV5640_REG_AEC_CTRL00         0x3a00
-+#define OV5640_REG_AEC_B50_STEP               0x3a08
-+#define OV5640_REG_AEC_B60_STEP               0x3a0a
-+#define OV5640_REG_AEC_CTRL0D         0x3a0d
-+#define OV5640_REG_AEC_CTRL0E         0x3a0e
-+#define OV5640_REG_AEC_CTRL0F         0x3a0f
-+#define OV5640_REG_AEC_CTRL10         0x3a10
-+#define OV5640_REG_AEC_CTRL11         0x3a11
-+#define OV5640_REG_AEC_CTRL1B         0x3a1b
-+#define OV5640_REG_AEC_CTRL1E         0x3a1e
-+#define OV5640_REG_AEC_CTRL1F         0x3a1f
-+#define OV5640_REG_HZ5060_CTRL00      0x3c00
-+#define OV5640_REG_HZ5060_CTRL01      0x3c01
-+#define OV5640_REG_SIGMADELTA_CTRL0C  0x3c0c
-+#define OV5640_REG_FRAME_CTRL01               0x4202
-+#define OV5640_REG_FORMAT_CONTROL00   0x4300
-+#define OV5640_REG_VFIFO_HSIZE                0x4602
-+#define OV5640_REG_VFIFO_VSIZE                0x4604
-+#define OV5640_REG_JPG_MODE_SELECT    0x4713
-+#define OV5640_REG_CCIR656_CTRL00     0x4730
-+#define OV5640_REG_POLARITY_CTRL00    0x4740
-+#define OV5640_REG_MIPI_CTRL00                0x4800
-+#define OV5640_REG_DEBUG_MODE         0x4814
-+#define OV5640_REG_ISP_FORMAT_MUX_CTRL        0x501f
-+#define OV5640_REG_PRE_ISP_TEST_SET1  0x503d
-+#define OV5640_REG_SDE_CTRL0          0x5580
-+#define OV5640_REG_SDE_CTRL1          0x5581
-+#define OV5640_REG_SDE_CTRL3          0x5583
-+#define OV5640_REG_SDE_CTRL4          0x5584
-+#define OV5640_REG_SDE_CTRL5          0x5585
-+#define OV5640_REG_AVG_READOUT                0x56a1
-+
-+enum ov5640_mode_id {
-+      OV5640_MODE_QCIF_176_144 = 0,
-+      OV5640_MODE_QVGA_320_240,
-+      OV5640_MODE_VGA_640_480,
-+      OV5640_MODE_NTSC_720_480,
-+      OV5640_MODE_PAL_720_576,
-+      OV5640_MODE_XGA_1024_768,
-+      OV5640_MODE_720P_1280_720,
-+      OV5640_MODE_1080P_1920_1080,
-+      OV5640_MODE_QSXGA_2592_1944,
-+      OV5640_NUM_MODES,
-+};
-+
-+enum ov5640_frame_rate {
-+      OV5640_15_FPS = 0,
-+      OV5640_30_FPS,
-+      OV5640_60_FPS,
-+      OV5640_NUM_FRAMERATES,
-+};
-+
-+enum ov5640_format_mux {
-+      OV5640_FMT_MUX_YUV422 = 0,
-+      OV5640_FMT_MUX_RGB,
-+      OV5640_FMT_MUX_DITHER,
-+      OV5640_FMT_MUX_RAW_DPC,
-+      OV5640_FMT_MUX_SNR_RAW,
-+      OV5640_FMT_MUX_RAW_CIP,
-+};
-+
-+struct ov5640_pixfmt {
-+      u32 code;
-+      u32 colorspace;
-+};
-+
-+static const struct ov5640_pixfmt ov5640_formats[] = {
-+      { MEDIA_BUS_FMT_JPEG_1X8, V4L2_COLORSPACE_JPEG, },
-+      { MEDIA_BUS_FMT_UYVY8_2X8, V4L2_COLORSPACE_SRGB, },
-+      { MEDIA_BUS_FMT_YUYV8_2X8, V4L2_COLORSPACE_SRGB, },
-+      { MEDIA_BUS_FMT_RGB565_2X8_LE, V4L2_COLORSPACE_SRGB, },
-+      { MEDIA_BUS_FMT_RGB565_2X8_BE, V4L2_COLORSPACE_SRGB, },
-+      { MEDIA_BUS_FMT_SBGGR8_1X8, V4L2_COLORSPACE_SRGB, },
-+      { MEDIA_BUS_FMT_SGBRG8_1X8, V4L2_COLORSPACE_SRGB, },
-+      { MEDIA_BUS_FMT_SGRBG8_1X8, V4L2_COLORSPACE_SRGB, },
-+      { MEDIA_BUS_FMT_SRGGB8_1X8, V4L2_COLORSPACE_SRGB, },
-+};
-+
-+/*
-+ * FIXME: remove this when a subdev API becomes available
-+ * to set the MIPI CSI-2 virtual channel.
-+ */
-+static unsigned int virtual_channel;
-+module_param(virtual_channel, uint, 0444);
-+MODULE_PARM_DESC(virtual_channel,
-+               "MIPI CSI-2 virtual channel (0..3), default 0");
-+
-+static const int ov5640_framerates[] = {
-+      [OV5640_15_FPS] = 15,
-+      [OV5640_30_FPS] = 30,
-+      [OV5640_60_FPS] = 60,
-+};
-+
-+/* regulator supplies */
-+static const char * const ov5640_supply_name[] = {
-+      "DOVDD", /* Digital I/O (1.8V) supply */
-+      "AVDD",  /* Analog (2.8V) supply */
-+      "DVDD",  /* Digital Core (1.5V) supply */
-+};
-+
-+#define OV5640_NUM_SUPPLIES ARRAY_SIZE(ov5640_supply_name)
-+
-+/*
-+ * Image size under 1280 * 960 are SUBSAMPLING
-+ * Image size upper 1280 * 960 are SCALING
-+ */
-+enum ov5640_downsize_mode {
-+      SUBSAMPLING,
-+      SCALING,
-+};
-+
-+struct reg_value {
-+      u16 reg_addr;
-+      u8 val;
-+      u8 mask;
-+      u32 delay_ms;
-+};
-+
-+struct ov5640_mode_info {
-+      enum ov5640_mode_id id;
-+      enum ov5640_downsize_mode dn_mode;
-+      u32 hact;
-+      u32 htot;
-+      u32 vact;
-+      u32 vtot;
-+      const struct reg_value *reg_data;
-+      u32 reg_data_size;
-+      u32 max_fps;
-+};
-+
-+struct ov5640_ctrls {
-+      struct v4l2_ctrl_handler handler;
-+      struct v4l2_ctrl *pixel_rate;
-+      struct {
-+              struct v4l2_ctrl *auto_exp;
-+              struct v4l2_ctrl *exposure;
-+      };
-+      struct {
-+              struct v4l2_ctrl *auto_wb;
-+              struct v4l2_ctrl *blue_balance;
-+              struct v4l2_ctrl *red_balance;
-+      };
-+      struct {
-+              struct v4l2_ctrl *auto_gain;
-+              struct v4l2_ctrl *gain;
-+      };
-+      struct v4l2_ctrl *brightness;
-+      struct v4l2_ctrl *light_freq;
-+      struct v4l2_ctrl *saturation;
-+      struct v4l2_ctrl *contrast;
-+      struct v4l2_ctrl *hue;
-+      struct v4l2_ctrl *test_pattern;
-+      struct v4l2_ctrl *hflip;
-+      struct v4l2_ctrl *vflip;
-+};
-+
-+struct ov5640_dev {
-+      struct i2c_client *i2c_client;
-+      struct v4l2_subdev sd;
-+      struct media_pad pad;
-+      struct v4l2_fwnode_endpoint ep; /* the parsed DT endpoint info */
-+      struct clk *xclk; /* system clock to OV5640 */
-+      u32 xclk_freq;
-+
-+      struct regulator_bulk_data supplies[OV5640_NUM_SUPPLIES];
-+      struct gpio_desc *reset_gpio;
-+      struct gpio_desc *pwdn_gpio;
-+      bool   upside_down;
-+
-+      /* lock to protect all members below */
-+      struct mutex lock;
-+
-+      int power_count;
-+
-+      struct v4l2_mbus_framefmt fmt;
-+      bool pending_fmt_change;
-+
-+      const struct ov5640_mode_info *current_mode;
-+      const struct ov5640_mode_info *last_mode;
-+      enum ov5640_frame_rate current_fr;
-+      struct v4l2_fract frame_interval;
-+
-+      struct ov5640_ctrls ctrls;
-+
-+      u32 prev_sysclk, prev_hts;
-+      u32 ae_low, ae_high, ae_target;
-+
-+      bool pending_mode_change;
-+      int streaming;
-+};
-+
-+static inline struct ov5640_dev *to_ov5640_dev(struct v4l2_subdev *sd)
-+{
-+      return container_of(sd, struct ov5640_dev, sd);
-+}
-+
-+static inline struct v4l2_subdev *ctrl_to_sd(struct v4l2_ctrl *ctrl)
-+{
-+      return &container_of(ctrl->handler, struct ov5640_dev,
-+                           ctrls.handler)->sd;
-+}
-+
-+/*
-+ * FIXME: all of these register tables are likely filled with
-+ * entries that set the register to their power-on default values,
-+ * and which are otherwise not touched by this driver. Those entries
-+ * should be identified and removed to speed register load time
-+ * over i2c.
-+ */
-+/* YUV422 UYVY VGA@30fps */
-+static const struct reg_value ov5640_init_setting_30fps_VGA[] = {
-+      {0x3103, 0x11, 0, 0}, {0x3008, 0x82, 0, 5}, {0x3008, 0x42, 0, 0},
-+      {0x3103, 0x03, 0, 0}, {0x3630, 0x36, 0, 0},
-+      {0x3631, 0x0e, 0, 0}, {0x3632, 0xe2, 0, 0}, {0x3633, 0x12, 0, 0},
-+      {0x3621, 0xe0, 0, 0}, {0x3704, 0xa0, 0, 0}, {0x3703, 0x5a, 0, 0},
-+      {0x3715, 0x78, 0, 0}, {0x3717, 0x01, 0, 0}, {0x370b, 0x60, 0, 0},
-+      {0x3705, 0x1a, 0, 0}, {0x3905, 0x02, 0, 0}, {0x3906, 0x10, 0, 0},
-+      {0x3901, 0x0a, 0, 0}, {0x3731, 0x12, 0, 0}, {0x3600, 0x08, 0, 0},
-+      {0x3601, 0x33, 0, 0}, {0x302d, 0x60, 0, 0}, {0x3620, 0x52, 0, 0},
-+      {0x371b, 0x20, 0, 0}, {0x471c, 0x50, 0, 0}, {0x3a13, 0x43, 0, 0},
-+      {0x3a18, 0x00, 0, 0}, {0x3a19, 0xf8, 0, 0}, {0x3635, 0x13, 0, 0},
-+      {0x3636, 0x03, 0, 0}, {0x3634, 0x40, 0, 0}, {0x3622, 0x01, 0, 0},
-+      {0x3c01, 0xa4, 0, 0}, {0x3c04, 0x28, 0, 0}, {0x3c05, 0x98, 0, 0},
-+      {0x3c06, 0x00, 0, 0}, {0x3c07, 0x08, 0, 0}, {0x3c08, 0x00, 0, 0},
-+      {0x3c09, 0x1c, 0, 0}, {0x3c0a, 0x9c, 0, 0}, {0x3c0b, 0x40, 0, 0},
-+      {0x3820, 0x41, 0, 0}, {0x3821, 0x07, 0, 0}, {0x3814, 0x31, 0, 0},
-+      {0x3815, 0x31, 0, 0}, {0x3800, 0x00, 0, 0}, {0x3801, 0x00, 0, 0},
-+      {0x3802, 0x00, 0, 0}, {0x3803, 0x04, 0, 0}, {0x3804, 0x0a, 0, 0},
-+      {0x3805, 0x3f, 0, 0}, {0x3806, 0x07, 0, 0}, {0x3807, 0x9b, 0, 0},
-+      {0x3810, 0x00, 0, 0},
-+      {0x3811, 0x10, 0, 0}, {0x3812, 0x00, 0, 0}, {0x3813, 0x06, 0, 0},
-+      {0x3618, 0x00, 0, 0}, {0x3612, 0x29, 0, 0}, {0x3708, 0x64, 0, 0},
-+      {0x3709, 0x52, 0, 0}, {0x370c, 0x03, 0, 0}, {0x3a02, 0x03, 0, 0},
-+      {0x3a03, 0xd8, 0, 0}, {0x3a08, 0x01, 0, 0}, {0x3a09, 0x27, 0, 0},
-+      {0x3a0a, 0x00, 0, 0}, {0x3a0b, 0xf6, 0, 0}, {0x3a0e, 0x03, 0, 0},
-+      {0x3a0d, 0x04, 0, 0}, {0x3a14, 0x03, 0, 0}, {0x3a15, 0xd8, 0, 0},
-+      {0x4001, 0x02, 0, 0}, {0x4004, 0x02, 0, 0}, {0x3000, 0x00, 0, 0},
-+      {0x3002, 0x1c, 0, 0}, {0x3004, 0xff, 0, 0}, {0x3006, 0xc3, 0, 0},
-+      {0x302e, 0x08, 0, 0}, {0x4300, 0x3f, 0, 0},
-+      {0x501f, 0x00, 0, 0}, {0x4407, 0x04, 0, 0},
-+      {0x440e, 0x00, 0, 0}, {0x460b, 0x35, 0, 0}, {0x460c, 0x22, 0, 0},
-+      {0x4837, 0x0a, 0, 0}, {0x3824, 0x02, 0, 0},
-+      {0x5000, 0xa7, 0, 0}, {0x5001, 0xa3, 0, 0}, {0x5180, 0xff, 0, 0},
-+      {0x5181, 0xf2, 0, 0}, {0x5182, 0x00, 0, 0}, {0x5183, 0x14, 0, 0},
-+      {0x5184, 0x25, 0, 0}, {0x5185, 0x24, 0, 0}, {0x5186, 0x09, 0, 0},
-+      {0x5187, 0x09, 0, 0}, {0x5188, 0x09, 0, 0}, {0x5189, 0x88, 0, 0},
-+      {0x518a, 0x54, 0, 0}, {0x518b, 0xee, 0, 0}, {0x518c, 0xb2, 0, 0},
-+      {0x518d, 0x50, 0, 0}, {0x518e, 0x34, 0, 0}, {0x518f, 0x6b, 0, 0},
-+      {0x5190, 0x46, 0, 0}, {0x5191, 0xf8, 0, 0}, {0x5192, 0x04, 0, 0},
-+      {0x5193, 0x70, 0, 0}, {0x5194, 0xf0, 0, 0}, {0x5195, 0xf0, 0, 0},
-+      {0x5196, 0x03, 0, 0}, {0x5197, 0x01, 0, 0}, {0x5198, 0x04, 0, 0},
-+      {0x5199, 0x6c, 0, 0}, {0x519a, 0x04, 0, 0}, {0x519b, 0x00, 0, 0},
-+      {0x519c, 0x09, 0, 0}, {0x519d, 0x2b, 0, 0}, {0x519e, 0x38, 0, 0},
-+      {0x5381, 0x1e, 0, 0}, {0x5382, 0x5b, 0, 0}, {0x5383, 0x08, 0, 0},
-+      {0x5384, 0x0a, 0, 0}, {0x5385, 0x7e, 0, 0}, {0x5386, 0x88, 0, 0},
-+      {0x5387, 0x7c, 0, 0}, {0x5388, 0x6c, 0, 0}, {0x5389, 0x10, 0, 0},
-+      {0x538a, 0x01, 0, 0}, {0x538b, 0x98, 0, 0}, {0x5300, 0x08, 0, 0},
-+      {0x5301, 0x30, 0, 0}, {0x5302, 0x10, 0, 0}, {0x5303, 0x00, 0, 0},
-+      {0x5304, 0x08, 0, 0}, {0x5305, 0x30, 0, 0}, {0x5306, 0x08, 0, 0},
-+      {0x5307, 0x16, 0, 0}, {0x5309, 0x08, 0, 0}, {0x530a, 0x30, 0, 0},
-+      {0x530b, 0x04, 0, 0}, {0x530c, 0x06, 0, 0}, {0x5480, 0x01, 0, 0},
-+      {0x5481, 0x08, 0, 0}, {0x5482, 0x14, 0, 0}, {0x5483, 0x28, 0, 0},
-+      {0x5484, 0x51, 0, 0}, {0x5485, 0x65, 0, 0}, {0x5486, 0x71, 0, 0},
-+      {0x5487, 0x7d, 0, 0}, {0x5488, 0x87, 0, 0}, {0x5489, 0x91, 0, 0},
-+      {0x548a, 0x9a, 0, 0}, {0x548b, 0xaa, 0, 0}, {0x548c, 0xb8, 0, 0},
-+      {0x548d, 0xcd, 0, 0}, {0x548e, 0xdd, 0, 0}, {0x548f, 0xea, 0, 0},
-+      {0x5490, 0x1d, 0, 0}, {0x5580, 0x02, 0, 0}, {0x5583, 0x40, 0, 0},
-+      {0x5584, 0x10, 0, 0}, {0x5589, 0x10, 0, 0}, {0x558a, 0x00, 0, 0},
-+      {0x558b, 0xf8, 0, 0}, {0x5800, 0x23, 0, 0}, {0x5801, 0x14, 0, 0},
-+      {0x5802, 0x0f, 0, 0}, {0x5803, 0x0f, 0, 0}, {0x5804, 0x12, 0, 0},
-+      {0x5805, 0x26, 0, 0}, {0x5806, 0x0c, 0, 0}, {0x5807, 0x08, 0, 0},
-+      {0x5808, 0x05, 0, 0}, {0x5809, 0x05, 0, 0}, {0x580a, 0x08, 0, 0},
-+      {0x580b, 0x0d, 0, 0}, {0x580c, 0x08, 0, 0}, {0x580d, 0x03, 0, 0},
-+      {0x580e, 0x00, 0, 0}, {0x580f, 0x00, 0, 0}, {0x5810, 0x03, 0, 0},
-+      {0x5811, 0x09, 0, 0}, {0x5812, 0x07, 0, 0}, {0x5813, 0x03, 0, 0},
-+      {0x5814, 0x00, 0, 0}, {0x5815, 0x01, 0, 0}, {0x5816, 0x03, 0, 0},
-+      {0x5817, 0x08, 0, 0}, {0x5818, 0x0d, 0, 0}, {0x5819, 0x08, 0, 0},
-+      {0x581a, 0x05, 0, 0}, {0x581b, 0x06, 0, 0}, {0x581c, 0x08, 0, 0},
-+      {0x581d, 0x0e, 0, 0}, {0x581e, 0x29, 0, 0}, {0x581f, 0x17, 0, 0},
-+      {0x5820, 0x11, 0, 0}, {0x5821, 0x11, 0, 0}, {0x5822, 0x15, 0, 0},
-+      {0x5823, 0x28, 0, 0}, {0x5824, 0x46, 0, 0}, {0x5825, 0x26, 0, 0},
-+      {0x5826, 0x08, 0, 0}, {0x5827, 0x26, 0, 0}, {0x5828, 0x64, 0, 0},
-+      {0x5829, 0x26, 0, 0}, {0x582a, 0x24, 0, 0}, {0x582b, 0x22, 0, 0},
-+      {0x582c, 0x24, 0, 0}, {0x582d, 0x24, 0, 0}, {0x582e, 0x06, 0, 0},
-+      {0x582f, 0x22, 0, 0}, {0x5830, 0x40, 0, 0}, {0x5831, 0x42, 0, 0},
-+      {0x5832, 0x24, 0, 0}, {0x5833, 0x26, 0, 0}, {0x5834, 0x24, 0, 0},
-+      {0x5835, 0x22, 0, 0}, {0x5836, 0x22, 0, 0}, {0x5837, 0x26, 0, 0},
-+      {0x5838, 0x44, 0, 0}, {0x5839, 0x24, 0, 0}, {0x583a, 0x26, 0, 0},
-+      {0x583b, 0x28, 0, 0}, {0x583c, 0x42, 0, 0}, {0x583d, 0xce, 0, 0},
-+      {0x5025, 0x00, 0, 0}, {0x3a0f, 0x30, 0, 0}, {0x3a10, 0x28, 0, 0},
-+      {0x3a1b, 0x30, 0, 0}, {0x3a1e, 0x26, 0, 0}, {0x3a11, 0x60, 0, 0},
-+      {0x3a1f, 0x14, 0, 0}, {0x3008, 0x02, 0, 0}, {0x3c00, 0x04, 0, 300},
-+};
-+
-+static const struct reg_value ov5640_setting_VGA_640_480[] = {
-+      {0x3c07, 0x08, 0, 0},
-+      {0x3c09, 0x1c, 0, 0}, {0x3c0a, 0x9c, 0, 0}, {0x3c0b, 0x40, 0, 0},
-+      {0x3814, 0x31, 0, 0},
-+      {0x3815, 0x31, 0, 0}, {0x3800, 0x00, 0, 0}, {0x3801, 0x00, 0, 0},
-+      {0x3802, 0x00, 0, 0}, {0x3803, 0x04, 0, 0}, {0x3804, 0x0a, 0, 0},
-+      {0x3805, 0x3f, 0, 0}, {0x3806, 0x07, 0, 0}, {0x3807, 0x9b, 0, 0},
-+      {0x3810, 0x00, 0, 0},
-+      {0x3811, 0x10, 0, 0}, {0x3812, 0x00, 0, 0}, {0x3813, 0x06, 0, 0},
-+      {0x3618, 0x00, 0, 0}, {0x3612, 0x29, 0, 0}, {0x3708, 0x64, 0, 0},
-+      {0x3709, 0x52, 0, 0}, {0x370c, 0x03, 0, 0}, {0x3a02, 0x03, 0, 0},
-+      {0x3a03, 0xd8, 0, 0}, {0x3a08, 0x01, 0, 0}, {0x3a09, 0x27, 0, 0},
-+      {0x3a0a, 0x00, 0, 0}, {0x3a0b, 0xf6, 0, 0}, {0x3a0e, 0x03, 0, 0},
-+      {0x3a0d, 0x04, 0, 0}, {0x3a14, 0x03, 0, 0}, {0x3a15, 0xd8, 0, 0},
-+      {0x4001, 0x02, 0, 0}, {0x4004, 0x02, 0, 0},
-+      {0x4407, 0x04, 0, 0}, {0x460b, 0x35, 0, 0}, {0x460c, 0x22, 0, 0},
-+      {0x3824, 0x02, 0, 0}, {0x5001, 0xa3, 0, 0},
-+};
-+
-+static const struct reg_value ov5640_setting_XGA_1024_768[] = {
-+      {0x3c07, 0x08, 0, 0},
-+      {0x3c09, 0x1c, 0, 0}, {0x3c0a, 0x9c, 0, 0}, {0x3c0b, 0x40, 0, 0},
-+      {0x3814, 0x31, 0, 0},
-+      {0x3815, 0x31, 0, 0}, {0x3800, 0x00, 0, 0}, {0x3801, 0x00, 0, 0},
-+      {0x3802, 0x00, 0, 0}, {0x3803, 0x04, 0, 0}, {0x3804, 0x0a, 0, 0},
-+      {0x3805, 0x3f, 0, 0}, {0x3806, 0x07, 0, 0}, {0x3807, 0x9b, 0, 0},
-+      {0x3810, 0x00, 0, 0},
-+      {0x3811, 0x10, 0, 0}, {0x3812, 0x00, 0, 0}, {0x3813, 0x06, 0, 0},
-+      {0x3618, 0x00, 0, 0}, {0x3612, 0x29, 0, 0}, {0x3708, 0x64, 0, 0},
-+      {0x3709, 0x52, 0, 0}, {0x370c, 0x03, 0, 0}, {0x3a02, 0x03, 0, 0},
-+      {0x3a03, 0xd8, 0, 0}, {0x3a08, 0x01, 0, 0}, {0x3a09, 0x27, 0, 0},
-+      {0x3a0a, 0x00, 0, 0}, {0x3a0b, 0xf6, 0, 0}, {0x3a0e, 0x03, 0, 0},
-+      {0x3a0d, 0x04, 0, 0}, {0x3a14, 0x03, 0, 0}, {0x3a15, 0xd8, 0, 0},
-+      {0x4001, 0x02, 0, 0}, {0x4004, 0x02, 0, 0},
-+      {0x4407, 0x04, 0, 0}, {0x460b, 0x35, 0, 0}, {0x460c, 0x22, 0, 0},
-+      {0x3824, 0x02, 0, 0}, {0x5001, 0xa3, 0, 0},
-+};
-+
-+static const struct reg_value ov5640_setting_QVGA_320_240[] = {
-+      {0x3c07, 0x08, 0, 0},
-+      {0x3c09, 0x1c, 0, 0}, {0x3c0a, 0x9c, 0, 0}, {0x3c0b, 0x40, 0, 0},
-+      {0x3814, 0x31, 0, 0},
-+      {0x3815, 0x31, 0, 0}, {0x3800, 0x00, 0, 0}, {0x3801, 0x00, 0, 0},
-+      {0x3802, 0x00, 0, 0}, {0x3803, 0x04, 0, 0}, {0x3804, 0x0a, 0, 0},
-+      {0x3805, 0x3f, 0, 0}, {0x3806, 0x07, 0, 0}, {0x3807, 0x9b, 0, 0},
-+      {0x3810, 0x00, 0, 0},
-+      {0x3811, 0x10, 0, 0}, {0x3812, 0x00, 0, 0}, {0x3813, 0x06, 0, 0},
-+      {0x3618, 0x00, 0, 0}, {0x3612, 0x29, 0, 0}, {0x3708, 0x64, 0, 0},
-+      {0x3709, 0x52, 0, 0}, {0x370c, 0x03, 0, 0}, {0x3a02, 0x03, 0, 0},
-+      {0x3a03, 0xd8, 0, 0}, {0x3a08, 0x01, 0, 0}, {0x3a09, 0x27, 0, 0},
-+      {0x3a0a, 0x00, 0, 0}, {0x3a0b, 0xf6, 0, 0}, {0x3a0e, 0x03, 0, 0},
-+      {0x3a0d, 0x04, 0, 0}, {0x3a14, 0x03, 0, 0}, {0x3a15, 0xd8, 0, 0},
-+      {0x4001, 0x02, 0, 0}, {0x4004, 0x02, 0, 0},
-+      {0x4407, 0x04, 0, 0}, {0x460b, 0x35, 0, 0}, {0x460c, 0x22, 0, 0},
-+      {0x3824, 0x02, 0, 0}, {0x5001, 0xa3, 0, 0},
-+};
-+
-+static const struct reg_value ov5640_setting_QCIF_176_144[] = {
-+      {0x3c07, 0x08, 0, 0},
-+      {0x3c09, 0x1c, 0, 0}, {0x3c0a, 0x9c, 0, 0}, {0x3c0b, 0x40, 0, 0},
-+      {0x3814, 0x31, 0, 0},
-+      {0x3815, 0x31, 0, 0}, {0x3800, 0x00, 0, 0}, {0x3801, 0x00, 0, 0},
-+      {0x3802, 0x00, 0, 0}, {0x3803, 0x04, 0, 0}, {0x3804, 0x0a, 0, 0},
-+      {0x3805, 0x3f, 0, 0}, {0x3806, 0x07, 0, 0}, {0x3807, 0x9b, 0, 0},
-+      {0x3810, 0x00, 0, 0},
-+      {0x3811, 0x10, 0, 0}, {0x3812, 0x00, 0, 0}, {0x3813, 0x06, 0, 0},
-+      {0x3618, 0x00, 0, 0}, {0x3612, 0x29, 0, 0}, {0x3708, 0x64, 0, 0},
-+      {0x3709, 0x52, 0, 0}, {0x370c, 0x03, 0, 0}, {0x3a02, 0x03, 0, 0},
-+      {0x3a03, 0xd8, 0, 0}, {0x3a08, 0x01, 0, 0}, {0x3a09, 0x27, 0, 0},
-+      {0x3a0a, 0x00, 0, 0}, {0x3a0b, 0xf6, 0, 0}, {0x3a0e, 0x03, 0, 0},
-+      {0x3a0d, 0x04, 0, 0}, {0x3a14, 0x03, 0, 0}, {0x3a15, 0xd8, 0, 0},
-+      {0x4001, 0x02, 0, 0}, {0x4004, 0x02, 0, 0},
-+      {0x4407, 0x04, 0, 0}, {0x460b, 0x35, 0, 0}, {0x460c, 0x22, 0, 0},
-+      {0x3824, 0x02, 0, 0}, {0x5001, 0xa3, 0, 0},
-+};
-+
-+static const struct reg_value ov5640_setting_NTSC_720_480[] = {
-+      {0x3c07, 0x08, 0, 0},
-+      {0x3c09, 0x1c, 0, 0}, {0x3c0a, 0x9c, 0, 0}, {0x3c0b, 0x40, 0, 0},
-+      {0x3814, 0x31, 0, 0},
-+      {0x3815, 0x31, 0, 0}, {0x3800, 0x00, 0, 0}, {0x3801, 0x00, 0, 0},
-+      {0x3802, 0x00, 0, 0}, {0x3803, 0x04, 0, 0}, {0x3804, 0x0a, 0, 0},
-+      {0x3805, 0x3f, 0, 0}, {0x3806, 0x07, 0, 0}, {0x3807, 0x9b, 0, 0},
-+      {0x3810, 0x00, 0, 0},
-+      {0x3811, 0x10, 0, 0}, {0x3812, 0x00, 0, 0}, {0x3813, 0x3c, 0, 0},
-+      {0x3618, 0x00, 0, 0}, {0x3612, 0x29, 0, 0}, {0x3708, 0x64, 0, 0},
-+      {0x3709, 0x52, 0, 0}, {0x370c, 0x03, 0, 0}, {0x3a02, 0x03, 0, 0},
-+      {0x3a03, 0xd8, 0, 0}, {0x3a08, 0x01, 0, 0}, {0x3a09, 0x27, 0, 0},
-+      {0x3a0a, 0x00, 0, 0}, {0x3a0b, 0xf6, 0, 0}, {0x3a0e, 0x03, 0, 0},
-+      {0x3a0d, 0x04, 0, 0}, {0x3a14, 0x03, 0, 0}, {0x3a15, 0xd8, 0, 0},
-+      {0x4001, 0x02, 0, 0}, {0x4004, 0x02, 0, 0},
-+      {0x4407, 0x04, 0, 0}, {0x460b, 0x35, 0, 0}, {0x460c, 0x22, 0, 0},
-+      {0x3824, 0x02, 0, 0}, {0x5001, 0xa3, 0, 0},
-+};
-+
-+static const struct reg_value ov5640_setting_PAL_720_576[] = {
-+      {0x3c07, 0x08, 0, 0},
-+      {0x3c09, 0x1c, 0, 0}, {0x3c0a, 0x9c, 0, 0}, {0x3c0b, 0x40, 0, 0},
-+      {0x3814, 0x31, 0, 0},
-+      {0x3815, 0x31, 0, 0}, {0x3800, 0x00, 0, 0}, {0x3801, 0x00, 0, 0},
-+      {0x3802, 0x00, 0, 0}, {0x3803, 0x04, 0, 0}, {0x3804, 0x0a, 0, 0},
-+      {0x3805, 0x3f, 0, 0}, {0x3806, 0x07, 0, 0}, {0x3807, 0x9b, 0, 0},
-+      {0x3810, 0x00, 0, 0},
-+      {0x3811, 0x38, 0, 0}, {0x3812, 0x00, 0, 0}, {0x3813, 0x06, 0, 0},
-+      {0x3618, 0x00, 0, 0}, {0x3612, 0x29, 0, 0}, {0x3708, 0x64, 0, 0},
-+      {0x3709, 0x52, 0, 0}, {0x370c, 0x03, 0, 0}, {0x3a02, 0x03, 0, 0},
-+      {0x3a03, 0xd8, 0, 0}, {0x3a08, 0x01, 0, 0}, {0x3a09, 0x27, 0, 0},
-+      {0x3a0a, 0x00, 0, 0}, {0x3a0b, 0xf6, 0, 0}, {0x3a0e, 0x03, 0, 0},
-+      {0x3a0d, 0x04, 0, 0}, {0x3a14, 0x03, 0, 0}, {0x3a15, 0xd8, 0, 0},
-+      {0x4001, 0x02, 0, 0}, {0x4004, 0x02, 0, 0},
-+      {0x4407, 0x04, 0, 0}, {0x460b, 0x35, 0, 0}, {0x460c, 0x22, 0, 0},
-+      {0x3824, 0x02, 0, 0}, {0x5001, 0xa3, 0, 0},
-+};
-+
-+static const struct reg_value ov5640_setting_720P_1280_720[] = {
-+      {0x3c07, 0x07, 0, 0},
-+      {0x3c09, 0x1c, 0, 0}, {0x3c0a, 0x9c, 0, 0}, {0x3c0b, 0x40, 0, 0},
-+      {0x3814, 0x31, 0, 0},
-+      {0x3815, 0x31, 0, 0}, {0x3800, 0x00, 0, 0}, {0x3801, 0x00, 0, 0},
-+      {0x3802, 0x00, 0, 0}, {0x3803, 0xfa, 0, 0}, {0x3804, 0x0a, 0, 0},
-+      {0x3805, 0x3f, 0, 0}, {0x3806, 0x06, 0, 0}, {0x3807, 0xa9, 0, 0},
-+      {0x3810, 0x00, 0, 0},
-+      {0x3811, 0x10, 0, 0}, {0x3812, 0x00, 0, 0}, {0x3813, 0x04, 0, 0},
-+      {0x3618, 0x00, 0, 0}, {0x3612, 0x29, 0, 0}, {0x3708, 0x64, 0, 0},
-+      {0x3709, 0x52, 0, 0}, {0x370c, 0x03, 0, 0}, {0x3a02, 0x02, 0, 0},
-+      {0x3a03, 0xe4, 0, 0}, {0x3a08, 0x01, 0, 0}, {0x3a09, 0xbc, 0, 0},
-+      {0x3a0a, 0x01, 0, 0}, {0x3a0b, 0x72, 0, 0}, {0x3a0e, 0x01, 0, 0},
-+      {0x3a0d, 0x02, 0, 0}, {0x3a14, 0x02, 0, 0}, {0x3a15, 0xe4, 0, 0},
-+      {0x4001, 0x02, 0, 0}, {0x4004, 0x02, 0, 0},
-+      {0x4407, 0x04, 0, 0}, {0x460b, 0x37, 0, 0}, {0x460c, 0x20, 0, 0},
-+      {0x3824, 0x04, 0, 0}, {0x5001, 0x83, 0, 0},
-+};
-+
-+static const struct reg_value ov5640_setting_1080P_1920_1080[] = {
-+      {0x3c07, 0x08, 0, 0},
-+      {0x3c09, 0x1c, 0, 0}, {0x3c0a, 0x9c, 0, 0}, {0x3c0b, 0x40, 0, 0},
-+      {0x3814, 0x11, 0, 0},
-+      {0x3815, 0x11, 0, 0}, {0x3800, 0x00, 0, 0}, {0x3801, 0x00, 0, 0},
-+      {0x3802, 0x00, 0, 0}, {0x3803, 0x00, 0, 0}, {0x3804, 0x0a, 0, 0},
-+      {0x3805, 0x3f, 0, 0}, {0x3806, 0x07, 0, 0}, {0x3807, 0x9f, 0, 0},
-+      {0x3810, 0x00, 0, 0},
-+      {0x3811, 0x10, 0, 0}, {0x3812, 0x00, 0, 0}, {0x3813, 0x04, 0, 0},
-+      {0x3618, 0x04, 0, 0}, {0x3612, 0x29, 0, 0}, {0x3708, 0x21, 0, 0},
-+      {0x3709, 0x12, 0, 0}, {0x370c, 0x00, 0, 0}, {0x3a02, 0x03, 0, 0},
-+      {0x3a03, 0xd8, 0, 0}, {0x3a08, 0x01, 0, 0}, {0x3a09, 0x27, 0, 0},
-+      {0x3a0a, 0x00, 0, 0}, {0x3a0b, 0xf6, 0, 0}, {0x3a0e, 0x03, 0, 0},
-+      {0x3a0d, 0x04, 0, 0}, {0x3a14, 0x03, 0, 0}, {0x3a15, 0xd8, 0, 0},
-+      {0x4001, 0x02, 0, 0}, {0x4004, 0x06, 0, 0},
-+      {0x4407, 0x04, 0, 0}, {0x460b, 0x35, 0, 0}, {0x460c, 0x22, 0, 0},
-+      {0x3824, 0x02, 0, 0}, {0x5001, 0x83, 0, 0},
-+      {0x3c07, 0x07, 0, 0}, {0x3c08, 0x00, 0, 0},
-+      {0x3c09, 0x1c, 0, 0}, {0x3c0a, 0x9c, 0, 0}, {0x3c0b, 0x40, 0, 0},
-+      {0x3800, 0x01, 0, 0}, {0x3801, 0x50, 0, 0}, {0x3802, 0x01, 0, 0},
-+      {0x3803, 0xb2, 0, 0}, {0x3804, 0x08, 0, 0}, {0x3805, 0xef, 0, 0},
-+      {0x3806, 0x05, 0, 0}, {0x3807, 0xf1, 0, 0},
-+      {0x3612, 0x2b, 0, 0}, {0x3708, 0x64, 0, 0},
-+      {0x3a02, 0x04, 0, 0}, {0x3a03, 0x60, 0, 0}, {0x3a08, 0x01, 0, 0},
-+      {0x3a09, 0x50, 0, 0}, {0x3a0a, 0x01, 0, 0}, {0x3a0b, 0x18, 0, 0},
-+      {0x3a0e, 0x03, 0, 0}, {0x3a0d, 0x04, 0, 0}, {0x3a14, 0x04, 0, 0},
-+      {0x3a15, 0x60, 0, 0}, {0x4407, 0x04, 0, 0},
-+      {0x460b, 0x37, 0, 0}, {0x460c, 0x20, 0, 0}, {0x3824, 0x04, 0, 0},
-+      {0x4005, 0x1a, 0, 0},
-+};
-+
-+static const struct reg_value ov5640_setting_QSXGA_2592_1944[] = {
-+      {0x3c07, 0x08, 0, 0},
-+      {0x3c09, 0x1c, 0, 0}, {0x3c0a, 0x9c, 0, 0}, {0x3c0b, 0x40, 0, 0},
-+      {0x3814, 0x11, 0, 0},
-+      {0x3815, 0x11, 0, 0}, {0x3800, 0x00, 0, 0}, {0x3801, 0x00, 0, 0},
-+      {0x3802, 0x00, 0, 0}, {0x3803, 0x00, 0, 0}, {0x3804, 0x0a, 0, 0},
-+      {0x3805, 0x3f, 0, 0}, {0x3806, 0x07, 0, 0}, {0x3807, 0x9f, 0, 0},
-+      {0x3810, 0x00, 0, 0},
-+      {0x3811, 0x10, 0, 0}, {0x3812, 0x00, 0, 0}, {0x3813, 0x04, 0, 0},
-+      {0x3618, 0x04, 0, 0}, {0x3612, 0x29, 0, 0}, {0x3708, 0x21, 0, 0},
-+      {0x3709, 0x12, 0, 0}, {0x370c, 0x00, 0, 0}, {0x3a02, 0x03, 0, 0},
-+      {0x3a03, 0xd8, 0, 0}, {0x3a08, 0x01, 0, 0}, {0x3a09, 0x27, 0, 0},
-+      {0x3a0a, 0x00, 0, 0}, {0x3a0b, 0xf6, 0, 0}, {0x3a0e, 0x03, 0, 0},
-+      {0x3a0d, 0x04, 0, 0}, {0x3a14, 0x03, 0, 0}, {0x3a15, 0xd8, 0, 0},
-+      {0x4001, 0x02, 0, 0}, {0x4004, 0x06, 0, 0},
-+      {0x4407, 0x04, 0, 0}, {0x460b, 0x37, 0, 0}, {0x460c, 0x20, 0, 0},
-+      {0x3824, 0x04, 0, 0}, {0x5001, 0x83, 0, 70},
-+};
-+
-+/* power-on sensor init reg table */
-+static const struct ov5640_mode_info ov5640_mode_init_data = {
-+      0, SUBSAMPLING, 640, 1896, 480, 984,
-+      ov5640_init_setting_30fps_VGA,
-+      ARRAY_SIZE(ov5640_init_setting_30fps_VGA),
-+      OV5640_30_FPS,
-+};
-+
-+static const struct ov5640_mode_info
-+ov5640_mode_data[OV5640_NUM_MODES] = {
-+      {OV5640_MODE_QCIF_176_144, SUBSAMPLING,
-+       176, 1896, 144, 984,
-+       ov5640_setting_QCIF_176_144,
-+       ARRAY_SIZE(ov5640_setting_QCIF_176_144),
-+       OV5640_30_FPS},
-+      {OV5640_MODE_QVGA_320_240, SUBSAMPLING,
-+       320, 1896, 240, 984,
-+       ov5640_setting_QVGA_320_240,
-+       ARRAY_SIZE(ov5640_setting_QVGA_320_240),
-+       OV5640_30_FPS},
-+      {OV5640_MODE_VGA_640_480, SUBSAMPLING,
-+       640, 1896, 480, 1080,
-+       ov5640_setting_VGA_640_480,
-+       ARRAY_SIZE(ov5640_setting_VGA_640_480),
-+       OV5640_60_FPS},
-+      {OV5640_MODE_NTSC_720_480, SUBSAMPLING,
-+       720, 1896, 480, 984,
-+       ov5640_setting_NTSC_720_480,
-+       ARRAY_SIZE(ov5640_setting_NTSC_720_480),
-+      OV5640_30_FPS},
-+      {OV5640_MODE_PAL_720_576, SUBSAMPLING,
-+       720, 1896, 576, 984,
-+       ov5640_setting_PAL_720_576,
-+       ARRAY_SIZE(ov5640_setting_PAL_720_576),
-+       OV5640_30_FPS},
-+      {OV5640_MODE_XGA_1024_768, SUBSAMPLING,
-+       1024, 1896, 768, 1080,
-+       ov5640_setting_XGA_1024_768,
-+       ARRAY_SIZE(ov5640_setting_XGA_1024_768),
-+       OV5640_30_FPS},
-+      {OV5640_MODE_720P_1280_720, SUBSAMPLING,
-+       1280, 1892, 720, 740,
-+       ov5640_setting_720P_1280_720,
-+       ARRAY_SIZE(ov5640_setting_720P_1280_720),
-+       OV5640_30_FPS},
-+      {OV5640_MODE_1080P_1920_1080, SCALING,
-+       1920, 2500, 1080, 1120,
-+       ov5640_setting_1080P_1920_1080,
-+       ARRAY_SIZE(ov5640_setting_1080P_1920_1080),
-+       OV5640_30_FPS},
-+      {OV5640_MODE_QSXGA_2592_1944, SCALING,
-+       2592, 2844, 1944, 1968,
-+       ov5640_setting_QSXGA_2592_1944,
-+       ARRAY_SIZE(ov5640_setting_QSXGA_2592_1944),
-+       OV5640_15_FPS},
-+};
-+
-+static int ov5640_init_slave_id(struct ov5640_dev *sensor)
-+{
-+      struct i2c_client *client = sensor->i2c_client;
-+      struct i2c_msg msg;
-+      u8 buf[3];
-+      int ret;
-+
-+      if (client->addr == OV5640_DEFAULT_SLAVE_ID)
-+              return 0;
-+
-+      buf[0] = OV5640_REG_SLAVE_ID >> 8;
-+      buf[1] = OV5640_REG_SLAVE_ID & 0xff;
-+      buf[2] = client->addr << 1;
-+
-+      msg.addr = OV5640_DEFAULT_SLAVE_ID;
-+      msg.flags = 0;
-+      msg.buf = buf;
-+      msg.len = sizeof(buf);
-+
-+      ret = i2c_transfer(client->adapter, &msg, 1);
-+      if (ret < 0) {
-+              dev_err(&client->dev, "%s: failed with %d\n", __func__, ret);
-+              return ret;
-+      }
-+
-+      return 0;
-+}
-+
-+static int ov5640_write_reg(struct ov5640_dev *sensor, u16 reg, u8 val)
-+{
-+      struct i2c_client *client = sensor->i2c_client;
-+      struct i2c_msg msg;
-+      u8 buf[3];
-+      int ret;
-+
-+      buf[0] = reg >> 8;
-+      buf[1] = reg & 0xff;
-+      buf[2] = val;
-+
-+      msg.addr = client->addr;
-+      msg.flags = client->flags;
-+      msg.buf = buf;
-+      msg.len = sizeof(buf);
-+
-+      ret = i2c_transfer(client->adapter, &msg, 1);
-+      if (ret < 0) {
-+              dev_err(&client->dev, "%s: error: reg=%x, val=%x\n",
-+                      __func__, reg, val);
-+              return ret;
-+      }
-+
-+      return 0;
-+}
-+
-+static int ov5640_read_reg(struct ov5640_dev *sensor, u16 reg, u8 *val)
-+{
-+      struct i2c_client *client = sensor->i2c_client;
-+      struct i2c_msg msg[2];
-+      u8 buf[2];
-+      int ret;
-+
-+      buf[0] = reg >> 8;
-+      buf[1] = reg & 0xff;
-+
-+      msg[0].addr = client->addr;
-+      msg[0].flags = client->flags;
-+      msg[0].buf = buf;
-+      msg[0].len = sizeof(buf);
-+
-+      msg[1].addr = client->addr;
-+      msg[1].flags = client->flags | I2C_M_RD;
-+      msg[1].buf = buf;
-+      msg[1].len = 1;
-+
-+      ret = i2c_transfer(client->adapter, msg, 2);
-+      if (ret < 0) {
-+              dev_err(&client->dev, "%s: error: reg=%x\n",
-+                      __func__, reg);
-+              return ret;
-+      }
-+
-+      *val = buf[0];
-+      return 0;
-+}
-+
-+static int ov5640_read_reg16(struct ov5640_dev *sensor, u16 reg, u16 *val)
-+{
-+      u8 hi, lo;
-+      int ret;
-+
-+      ret = ov5640_read_reg(sensor, reg, &hi);
-+      if (ret)
-+              return ret;
-+      ret = ov5640_read_reg(sensor, reg + 1, &lo);
-+      if (ret)
-+              return ret;
-+
-+      *val = ((u16)hi << 8) | (u16)lo;
-+      return 0;
-+}
-+
-+static int ov5640_write_reg16(struct ov5640_dev *sensor, u16 reg, u16 val)
-+{
-+      int ret;
-+
-+      ret = ov5640_write_reg(sensor, reg, val >> 8);
-+      if (ret)
-+              return ret;
-+
-+      return ov5640_write_reg(sensor, reg + 1, val & 0xff);
-+}
-+
-+static int ov5640_mod_reg(struct ov5640_dev *sensor, u16 reg,
-+                        u8 mask, u8 val)
-+{
-+      u8 readval;
-+      int ret;
-+
-+      ret = ov5640_read_reg(sensor, reg, &readval);
-+      if (ret)
-+              return ret;
-+
-+      readval &= ~mask;
-+      val &= mask;
-+      val |= readval;
-+
-+      return ov5640_write_reg(sensor, reg, val);
-+}
-+
-+/*
-+ * After trying the various combinations, reading various
-+ * documentations spread around the net, and from the various
-+ * feedback, the clock tree is probably as follows:
-+ *
-+ *   +--------------+
-+ *   |  Ext. Clock  |
-+ *   +-+------------+
-+ *     |  +----------+
-+ *     +->|   PLL1   | - reg 0x3036, for the multiplier
-+ *        +-+--------+ - reg 0x3037, bits 0-3 for the pre-divider
-+ *          |  +--------------+
-+ *          +->| System Clock |  - reg 0x3035, bits 4-7
-+ *             +-+------------+
-+ *               |  +--------------+
-+ *               +->| MIPI Divider | - reg 0x3035, bits 0-3
-+ *               |  +-+------------+
-+ *               |    +----------------> MIPI SCLK
-+ *               |    +  +-----+
-+ *               |    +->| / 2 |-------> MIPI BIT CLK
-+ *               |       +-----+
-+ *               |  +--------------+
-+ *               +->| PLL Root Div | - reg 0x3037, bit 4
-+ *                  +-+------------+
-+ *                    |  +---------+
-+ *                    +->| Bit Div | - reg 0x3034, bits 0-3
-+ *                       +-+-------+
-+ *                         |  +-------------+
-+ *                         +->| SCLK Div    | - reg 0x3108, bits 0-1
-+ *                         |  +-+-----------+
-+ *                         |    +---------------> SCLK
-+ *                         |  +-------------+
-+ *                         +->| SCLK 2X Div | - reg 0x3108, bits 2-3
-+ *                         |  +-+-----------+
-+ *                         |    +---------------> SCLK 2X
-+ *                         |  +-------------+
-+ *                         +->| PCLK Div    | - reg 0x3108, bits 4-5
-+ *                            ++------------+
-+ *                             +  +-----------+
-+ *                             +->|   P_DIV   | - reg 0x3035, bits 0-3
-+ *                                +-----+-----+
-+ *                                       +------------> PCLK
-+ *
-+ * This is deviating from the datasheet at least for the register
-+ * 0x3108, since it's said here that the PCLK would be clocked from
-+ * the PLL.
-+ *
-+ * There seems to be also (unverified) constraints:
-+ *  - the PLL pre-divider output rate should be in the 4-27MHz range
-+ *  - the PLL multiplier output rate should be in the 500-1000MHz range
-+ *  - PCLK >= SCLK * 2 in YUV, >= SCLK in Raw or JPEG
-+ *
-+ * In the two latter cases, these constraints are met since our
-+ * factors are hardcoded. If we were to change that, we would need to
-+ * take this into account. The only varying parts are the PLL
-+ * multiplier and the system clock divider, which are shared between
-+ * all these clocks so won't cause any issue.
-+ */
-+
-+/*
-+ * This is supposed to be ranging from 1 to 8, but the value is always
-+ * set to 3 in the vendor kernels.
-+ */
-+#define OV5640_PLL_PREDIV     3
-+
-+#define OV5640_PLL_MULT_MIN   4
-+#define OV5640_PLL_MULT_MAX   252
-+
-+/*
-+ * This is supposed to be ranging from 1 to 16, but the value is
-+ * always set to either 1 or 2 in the vendor kernels.
-+ */
-+#define OV5640_SYSDIV_MIN     1
-+#define OV5640_SYSDIV_MAX     16
-+
-+/*
-+ * Hardcode these values for scaler and non-scaler modes.
-+ * FIXME: to be re-calcualted for 1 data lanes setups
-+ */
-+#define OV5640_MIPI_DIV_PCLK  2
-+#define OV5640_MIPI_DIV_SCLK  1
-+
-+/*
-+ * This is supposed to be ranging from 1 to 2, but the value is always
-+ * set to 2 in the vendor kernels.
-+ */
-+#define OV5640_PLL_ROOT_DIV                   2
-+#define OV5640_PLL_CTRL3_PLL_ROOT_DIV_2               BIT(4)
-+
-+/*
-+ * We only supports 8-bit formats at the moment
-+ */
-+#define OV5640_BIT_DIV                                2
-+#define OV5640_PLL_CTRL0_MIPI_MODE_8BIT               0x08
-+
-+/*
-+ * This is supposed to be ranging from 1 to 8, but the value is always
-+ * set to 2 in the vendor kernels.
-+ */
-+#define OV5640_SCLK_ROOT_DIV  2
-+
-+/*
-+ * This is hardcoded so that the consistency is maintained between SCLK and
-+ * SCLK 2x.
-+ */
-+#define OV5640_SCLK2X_ROOT_DIV (OV5640_SCLK_ROOT_DIV / 2)
-+
-+/*
-+ * This is supposed to be ranging from 1 to 8, but the value is always
-+ * set to 1 in the vendor kernels.
-+ */
-+#define OV5640_PCLK_ROOT_DIV                  1
-+#define OV5640_PLL_SYS_ROOT_DIVIDER_BYPASS    0x00
-+
-+static unsigned long ov5640_compute_sys_clk(struct ov5640_dev *sensor,
-+                                          u8 pll_prediv, u8 pll_mult,
-+                                          u8 sysdiv)
-+{
-+      unsigned long sysclk = sensor->xclk_freq / pll_prediv * pll_mult;
-+
-+      /* PLL1 output cannot exceed 1GHz. */
-+      if (sysclk / 1000000 > 1000)
-+              return 0;
-+
-+      return sysclk / sysdiv;
-+}
-+
-+static unsigned long ov5640_calc_sys_clk(struct ov5640_dev *sensor,
-+                                       unsigned long rate,
-+                                       u8 *pll_prediv, u8 *pll_mult,
-+                                       u8 *sysdiv)
-+{
-+      unsigned long best = ~0;
-+      u8 best_sysdiv = 1, best_mult = 1;
-+      u8 _sysdiv, _pll_mult;
-+
-+      for (_sysdiv = OV5640_SYSDIV_MIN;
-+           _sysdiv <= OV5640_SYSDIV_MAX;
-+           _sysdiv++) {
-+              for (_pll_mult = OV5640_PLL_MULT_MIN;
-+                   _pll_mult <= OV5640_PLL_MULT_MAX;
-+                   _pll_mult++) {
-+                      unsigned long _rate;
-+
-+                      /*
-+                       * The PLL multiplier cannot be odd if above
-+                       * 127.
-+                       */
-+                      if (_pll_mult > 127 && (_pll_mult % 2))
-+                              continue;
-+
-+                      _rate = ov5640_compute_sys_clk(sensor,
-+                                                     OV5640_PLL_PREDIV,
-+                                                     _pll_mult, _sysdiv);
-+
-+                      /*
-+                       * We have reached the maximum allowed PLL1 output,
-+                       * increase sysdiv.
-+                       */
-+                      if (!_rate)
-+                              break;
-+
-+                      /*
-+                       * Prefer rates above the expected clock rate than
-+                       * below, even if that means being less precise.
-+                       */
-+                      if (_rate < rate)
-+                              continue;
-+
-+                      if (abs(rate - _rate) < abs(rate - best)) {
-+                              best = _rate;
-+                              best_sysdiv = _sysdiv;
-+                              best_mult = _pll_mult;
-+                      }
-+
-+                      if (_rate == rate)
-+                              goto out;
-+              }
-+      }
-+
-+out:
-+      *sysdiv = best_sysdiv;
-+      *pll_prediv = OV5640_PLL_PREDIV;
-+      *pll_mult = best_mult;
-+
-+      return best;
-+}
-+
-+/*
-+ * ov5640_set_mipi_pclk() - Calculate the clock tree configuration values
-+ *                        for the MIPI CSI-2 output.
-+ *
-+ * @rate: The requested bandwidth per lane in bytes per second.
-+ *      'Bandwidth Per Lane' is calculated as:
-+ *      bpl = HTOT * VTOT * FPS * bpp / num_lanes;
-+ *
-+ * This function use the requested bandwidth to calculate:
-+ * - sample_rate = bpl / (bpp / num_lanes);
-+ *             = bpl / (PLL_RDIV * BIT_DIV * PCLK_DIV * MIPI_DIV / num_lanes);
-+ *
-+ * - mipi_sclk   = bpl / MIPI_DIV / 2; ( / 2 is for CSI-2 DDR)
-+ *
-+ * with these fixed parameters:
-+ *    PLL_RDIV        = 2;
-+ *    BIT_DIVIDER     = 2; (MIPI_BIT_MODE == 8 ? 2 : 2,5);
-+ *    PCLK_DIV        = 1;
-+ *
-+ * The MIPI clock generation differs for modes that use the scaler and modes
-+ * that do not. In case the scaler is in use, the MIPI_SCLK generates the MIPI
-+ * BIT CLk, and thus:
-+ *
-+ * - mipi_sclk = bpl / MIPI_DIV / 2;
-+ *   MIPI_DIV = 1;
-+ *
-+ * For modes that do not go through the scaler, the MIPI BIT CLOCK is generated
-+ * from the pixel clock, and thus:
-+ *
-+ * - sample_rate = bpl / (bpp / num_lanes);
-+ *             = bpl / (2 * 2 * 1 * MIPI_DIV / num_lanes);
-+ *             = bpl / (4 * MIPI_DIV / num_lanes);
-+ * - MIPI_DIV  = bpp / (4 * num_lanes);
-+ *
-+ * FIXME: this have been tested with 16bpp and 2 lanes setup only.
-+ * MIPI_DIV is fixed to value 2, but it -might- be changed according to the
-+ * above formula for setups with 1 lane or image formats with different bpp.
-+ *
-+ * FIXME: this deviates from the sensor manual documentation which is quite
-+ * thin on the MIPI clock tree generation part.
-+ */
-+static int ov5640_set_mipi_pclk(struct ov5640_dev *sensor,
-+                              unsigned long rate)
-+{
-+      const struct ov5640_mode_info *mode = sensor->current_mode;
-+      u8 prediv, mult, sysdiv;
-+      u8 mipi_div;
-+      int ret;
-+
-+      /*
-+       * 1280x720 is reported to use 'SUBSAMPLING' only,
-+       * but according to the sensor manual it goes through the
-+       * scaler before subsampling.
-+       */
-+      if (mode->dn_mode == SCALING ||
-+         (mode->id == OV5640_MODE_720P_1280_720))
-+              mipi_div = OV5640_MIPI_DIV_SCLK;
-+      else
-+              mipi_div = OV5640_MIPI_DIV_PCLK;
-+
-+      ov5640_calc_sys_clk(sensor, rate, &prediv, &mult, &sysdiv);
-+
-+      ret = ov5640_mod_reg(sensor, OV5640_REG_SC_PLL_CTRL0,
-+                           0x0f, OV5640_PLL_CTRL0_MIPI_MODE_8BIT);
-+
-+      ret = ov5640_mod_reg(sensor, OV5640_REG_SC_PLL_CTRL1,
-+                           0xff, sysdiv << 4 | mipi_div);
-+      if (ret)
-+              return ret;
-+
-+      ret = ov5640_mod_reg(sensor, OV5640_REG_SC_PLL_CTRL2, 0xff, mult);
-+      if (ret)
-+              return ret;
-+
-+      ret = ov5640_mod_reg(sensor, OV5640_REG_SC_PLL_CTRL3,
-+                           0x1f, OV5640_PLL_CTRL3_PLL_ROOT_DIV_2 | prediv);
-+      if (ret)
-+              return ret;
-+
-+      return ov5640_mod_reg(sensor, OV5640_REG_SYS_ROOT_DIVIDER,
-+                            0x30, OV5640_PLL_SYS_ROOT_DIVIDER_BYPASS);
-+}
-+
-+static unsigned long ov5640_calc_pclk(struct ov5640_dev *sensor,
-+                                    unsigned long rate,
-+                                    u8 *pll_prediv, u8 *pll_mult, u8 *sysdiv,
-+                                    u8 *pll_rdiv, u8 *bit_div, u8 *pclk_div)
-+{
-+      unsigned long _rate = rate * OV5640_PLL_ROOT_DIV * OV5640_BIT_DIV *
-+                              OV5640_PCLK_ROOT_DIV;
-+
-+      _rate = ov5640_calc_sys_clk(sensor, _rate, pll_prediv, pll_mult,
-+                                  sysdiv);
-+      *pll_rdiv = OV5640_PLL_ROOT_DIV;
-+      *bit_div = OV5640_BIT_DIV;
-+      *pclk_div = OV5640_PCLK_ROOT_DIV;
-+
-+      return _rate / *pll_rdiv / *bit_div / *pclk_div;
-+}
-+
-+static int ov5640_set_dvp_pclk(struct ov5640_dev *sensor, unsigned long rate)
-+{
-+      u8 prediv, mult, sysdiv, pll_rdiv, bit_div, pclk_div;
-+      int ret;
-+
-+      ov5640_calc_pclk(sensor, rate, &prediv, &mult, &sysdiv, &pll_rdiv,
-+                       &bit_div, &pclk_div);
-+
-+#ifndef CONFIG_VIN_SENSOR_OV5640
-+      if (bit_div == 2)
-+              bit_div = 8;
-+#else
-+      bit_div = 0xa;
-+#endif
-+      ret = ov5640_mod_reg(sensor, OV5640_REG_SC_PLL_CTRL0,
-+                           0x0f, bit_div);
-+      if (ret)
-+              return ret;
-+
-+      /*
-+       * We need to set sysdiv according to the clock, and to clear
-+       * the MIPI divider.
-+       */
-+      ret = ov5640_mod_reg(sensor, OV5640_REG_SC_PLL_CTRL1,
-+                           0xff, sysdiv << 4);
-+      if (ret)
-+              return ret;
-+
-+      ret = ov5640_mod_reg(sensor, OV5640_REG_SC_PLL_CTRL2,
-+                           0xff, mult);
-+      if (ret)
-+              return ret;
-+
-+      ret = ov5640_mod_reg(sensor, OV5640_REG_SC_PLL_CTRL3,
-+                           0x1f, prediv | ((pll_rdiv - 1) << 4));
-+      if (ret)
-+              return ret;
-+
-+      return ov5640_mod_reg(sensor, OV5640_REG_SYS_ROOT_DIVIDER, 0x30,
-+                            (ilog2(pclk_div) << 4));
-+}
-+
-+/* set JPEG framing sizes */
-+static int ov5640_set_jpeg_timings(struct ov5640_dev *sensor,
-+                                 const struct ov5640_mode_info *mode)
-+{
-+      int ret;
-+
-+      /*
-+       * compression mode 3 timing
-+       *
-+       * Data is transmitted with programmable width (VFIFO_HSIZE).
-+       * No padding done. Last line may have less data. Varying
-+       * number of lines per frame, depending on amount of data.
-+       */
-+      ret = ov5640_mod_reg(sensor, OV5640_REG_JPG_MODE_SELECT, 0x7, 0x3);
-+      if (ret < 0)
-+              return ret;
-+
-+      ret = ov5640_write_reg16(sensor, OV5640_REG_VFIFO_HSIZE, mode->hact);
-+      if (ret < 0)
-+              return ret;
-+
-+      return ov5640_write_reg16(sensor, OV5640_REG_VFIFO_VSIZE, mode->vact);
-+}
-+
-+/* download ov5640 settings to sensor through i2c */
-+static int ov5640_set_timings(struct ov5640_dev *sensor,
-+                            const struct ov5640_mode_info *mode)
-+{
-+      int ret;
-+
-+      if (sensor->fmt.code == MEDIA_BUS_FMT_JPEG_1X8) {
-+              ret = ov5640_set_jpeg_timings(sensor, mode);
-+              if (ret < 0)
-+                      return ret;
-+      }
-+
-+      ret = ov5640_write_reg16(sensor, OV5640_REG_TIMING_DVPHO, mode->hact);
-+      if (ret < 0)
-+              return ret;
-+
-+      ret = ov5640_write_reg16(sensor, OV5640_REG_TIMING_DVPVO, mode->vact);
-+      if (ret < 0)
-+              return ret;
-+
-+      ret = ov5640_write_reg16(sensor, OV5640_REG_TIMING_HTS, mode->htot);
-+      if (ret < 0)
-+              return ret;
-+
-+      return ov5640_write_reg16(sensor, OV5640_REG_TIMING_VTS, mode->vtot);
-+}
-+
-+static int ov5640_load_regs(struct ov5640_dev *sensor,
-+                          const struct ov5640_mode_info *mode)
-+{
-+      const struct reg_value *regs = mode->reg_data;
-+      unsigned int i;
-+      u32 delay_ms;
-+      u16 reg_addr;
-+      u8 mask, val;
-+      int ret = 0;
-+
-+      st_info(ST_SENSOR, "%s, mode = 0x%x\n", __func__, mode->id);
-+      for (i = 0; i < mode->reg_data_size; ++i, ++regs) {
-+              delay_ms = regs->delay_ms;
-+              reg_addr = regs->reg_addr;
-+              val = regs->val;
-+              mask = regs->mask;
-+
-+              /* remain in power down mode for DVP */
-+              if (regs->reg_addr == OV5640_REG_SYS_CTRL0 &&
-+                  val == OV5640_REG_SYS_CTRL0_SW_PWUP &&
-+                  sensor->ep.bus_type != V4L2_MBUS_CSI2_DPHY)
-+                      continue;
-+
-+              if (mask)
-+                      ret = ov5640_mod_reg(sensor, reg_addr, mask, val);
-+              else
-+                      ret = ov5640_write_reg(sensor, reg_addr, val);
-+              if (ret)
-+                      break;
-+
-+              if (delay_ms)
-+                      usleep_range(1000 * delay_ms, 1000 * delay_ms + 100);
-+      }
-+
-+      return ov5640_set_timings(sensor, mode);
-+}
-+
-+static int ov5640_set_autoexposure(struct ov5640_dev *sensor, bool on)
-+{
-+      return ov5640_mod_reg(sensor, OV5640_REG_AEC_PK_MANUAL,
-+                            BIT(0), on ? 0 : BIT(0));
-+}
-+
-+/* read exposure, in number of line periods */
-+static int ov5640_get_exposure(struct ov5640_dev *sensor)
-+{
-+      int exp, ret;
-+      u8 temp;
-+
-+      ret = ov5640_read_reg(sensor, OV5640_REG_AEC_PK_EXPOSURE_HI, &temp);
-+      if (ret)
-+              return ret;
-+      exp = ((int)temp & 0x0f) << 16;
-+      ret = ov5640_read_reg(sensor, OV5640_REG_AEC_PK_EXPOSURE_MED, &temp);
-+      if (ret)
-+              return ret;
-+      exp |= ((int)temp << 8);
-+      ret = ov5640_read_reg(sensor, OV5640_REG_AEC_PK_EXPOSURE_LO, &temp);
-+      if (ret)
-+              return ret;
-+      exp |= (int)temp;
-+
-+      return exp >> 4;
-+}
-+
-+/* write exposure, given number of line periods */
-+static int ov5640_set_exposure(struct ov5640_dev *sensor, u32 exposure)
-+{
-+      int ret;
-+
-+      exposure <<= 4;
-+
-+      ret = ov5640_write_reg(sensor,
-+                             OV5640_REG_AEC_PK_EXPOSURE_LO,
-+                             exposure & 0xff);
-+      if (ret)
-+              return ret;
-+      ret = ov5640_write_reg(sensor,
-+                             OV5640_REG_AEC_PK_EXPOSURE_MED,
-+                             (exposure >> 8) & 0xff);
-+      if (ret)
-+              return ret;
-+      return ov5640_write_reg(sensor,
-+                              OV5640_REG_AEC_PK_EXPOSURE_HI,
-+                              (exposure >> 16) & 0x0f);
-+}
-+
-+static int ov5640_get_gain(struct ov5640_dev *sensor)
-+{
-+      u16 gain;
-+      int ret;
-+
-+      ret = ov5640_read_reg16(sensor, OV5640_REG_AEC_PK_REAL_GAIN, &gain);
-+      if (ret)
-+              return ret;
-+
-+      return gain & 0x3ff;
-+}
-+
-+static int ov5640_set_gain(struct ov5640_dev *sensor, int gain)
-+{
-+      return ov5640_write_reg16(sensor, OV5640_REG_AEC_PK_REAL_GAIN,
-+                                (u16)gain & 0x3ff);
-+}
-+
-+static int ov5640_set_autogain(struct ov5640_dev *sensor, bool on)
-+{
-+      return ov5640_mod_reg(sensor, OV5640_REG_AEC_PK_MANUAL,
-+                            BIT(1), on ? 0 : BIT(1));
-+}
-+
-+static int ov5640_set_stream_dvp(struct ov5640_dev *sensor, bool on)
-+{
-+      return ov5640_write_reg(sensor, OV5640_REG_SYS_CTRL0, on ?
-+                              OV5640_REG_SYS_CTRL0_SW_PWUP :
-+                              OV5640_REG_SYS_CTRL0_SW_PWDN);
-+}
-+
-+static int ov5640_set_stream_mipi(struct ov5640_dev *sensor, bool on)
-+{
-+      int ret;
-+
-+      /*
-+       * Enable/disable the MIPI interface
-+       *
-+       * 0x300e = on ? 0x45 : 0x40
-+       *
-+       * FIXME: the sensor manual (version 2.03) reports
-+       * [7:5] = 000  : 1 data lane mode
-+       * [7:5] = 001  : 2 data lanes mode
-+       * But this settings do not work, while the following ones
-+       * have been validated for 2 data lanes mode.
-+       *
-+       * [7:5] = 010  : 2 data lanes mode
-+       * [4] = 0      : Power up MIPI HS Tx
-+       * [3] = 0      : Power up MIPI LS Rx
-+       * [2] = 1/0    : MIPI interface enable/disable
-+       * [1:0] = 01/00: FIXME: 'debug'
-+       */
-+      ret = ov5640_write_reg(sensor, OV5640_REG_IO_MIPI_CTRL00,
-+                             on ? 0x45 : 0x40);
-+      if (ret)
-+              return ret;
-+
-+      return ov5640_write_reg(sensor, OV5640_REG_FRAME_CTRL01,
-+                              on ? 0x00 : 0x0f);
-+}
-+
-+static int ov5640_get_sysclk(struct ov5640_dev *sensor)
-+{
-+       /* calculate sysclk */
-+      u32 xvclk = sensor->xclk_freq / 10000;
-+      u32 multiplier, prediv, VCO, sysdiv, pll_rdiv;
-+      u32 sclk_rdiv_map[] = {1, 2, 4, 8};
-+      u32 bit_div2x = 1, sclk_rdiv, sysclk;
-+      u8 temp1, temp2;
-+      int ret;
-+
-+      ret = ov5640_read_reg(sensor, OV5640_REG_SC_PLL_CTRL0, &temp1);
-+      if (ret)
-+              return ret;
-+      temp2 = temp1 & 0x0f;
-+      if (temp2 == 8 || temp2 == 10)
-+              bit_div2x = temp2 / 2;
-+
-+      ret = ov5640_read_reg(sensor, OV5640_REG_SC_PLL_CTRL1, &temp1);
-+      if (ret)
-+              return ret;
-+      sysdiv = temp1 >> 4;
-+      if (sysdiv == 0)
-+              sysdiv = 16;
-+
-+      ret = ov5640_read_reg(sensor, OV5640_REG_SC_PLL_CTRL2, &temp1);
-+      if (ret)
-+              return ret;
-+      multiplier = temp1;
-+
-+      ret = ov5640_read_reg(sensor, OV5640_REG_SC_PLL_CTRL3, &temp1);
-+      if (ret)
-+              return ret;
-+      prediv = temp1 & 0x0f;
-+      pll_rdiv = ((temp1 >> 4) & 0x01) + 1;
-+
-+      ret = ov5640_read_reg(sensor, OV5640_REG_SYS_ROOT_DIVIDER, &temp1);
-+      if (ret)
-+              return ret;
-+      temp2 = temp1 & 0x03;
-+      sclk_rdiv = sclk_rdiv_map[temp2];
-+
-+      if (!prediv || !sysdiv || !pll_rdiv || !bit_div2x)
-+              return -EINVAL;
-+
-+      VCO = xvclk * multiplier / prediv;
-+
-+      sysclk = VCO / sysdiv / pll_rdiv * 2 / bit_div2x / sclk_rdiv;
-+
-+      return sysclk;
-+}
-+
-+static int ov5640_set_night_mode(struct ov5640_dev *sensor)
-+{
-+       /* read HTS from register settings */
-+      u8 mode;
-+      int ret;
-+
-+      ret = ov5640_read_reg(sensor, OV5640_REG_AEC_CTRL00, &mode);
-+      if (ret)
-+              return ret;
-+      mode &= 0xfb;
-+      return ov5640_write_reg(sensor, OV5640_REG_AEC_CTRL00, mode);
-+}
-+
-+static int ov5640_get_hts(struct ov5640_dev *sensor)
-+{
-+      /* read HTS from register settings */
-+      u16 hts;
-+      int ret;
-+
-+      ret = ov5640_read_reg16(sensor, OV5640_REG_TIMING_HTS, &hts);
-+      if (ret)
-+              return ret;
-+      return hts;
-+}
-+
-+static int ov5640_get_vts(struct ov5640_dev *sensor)
-+{
-+      u16 vts;
-+      int ret;
-+
-+      ret = ov5640_read_reg16(sensor, OV5640_REG_TIMING_VTS, &vts);
-+      if (ret)
-+              return ret;
-+      return vts;
-+}
-+
-+static int ov5640_set_vts(struct ov5640_dev *sensor, int vts)
-+{
-+      return ov5640_write_reg16(sensor, OV5640_REG_TIMING_VTS, vts);
-+}
-+
-+static int ov5640_get_light_freq(struct ov5640_dev *sensor)
-+{
-+      /* get banding filter value */
-+      int ret, light_freq = 0;
-+      u8 temp, temp1;
-+
-+      ret = ov5640_read_reg(sensor, OV5640_REG_HZ5060_CTRL01, &temp);
-+      if (ret)
-+              return ret;
-+
-+      if (temp & 0x80) {
-+              /* manual */
-+              ret = ov5640_read_reg(sensor, OV5640_REG_HZ5060_CTRL00,
-+                                    &temp1);
-+              if (ret)
-+                      return ret;
-+              if (temp1 & 0x04) {
-+                      /* 50Hz */
-+                      light_freq = 50;
-+              } else {
-+                      /* 60Hz */
-+                      light_freq = 60;
-+              }
-+      } else {
-+              /* auto */
-+              ret = ov5640_read_reg(sensor, OV5640_REG_SIGMADELTA_CTRL0C,
-+                                    &temp1);
-+              if (ret)
-+                      return ret;
-+
-+              if (temp1 & 0x01) {
-+                      /* 50Hz */
-+                      light_freq = 50;
-+              } else {
-+                      /* 60Hz */
-+              }
-+      }
-+
-+      return light_freq;
-+}
-+
-+static int ov5640_set_bandingfilter(struct ov5640_dev *sensor)
-+{
-+      u32 band_step60, max_band60, band_step50, max_band50, prev_vts;
-+      int ret;
-+
-+      /* read preview PCLK */
-+      ret = ov5640_get_sysclk(sensor);
-+      if (ret < 0)
-+              return ret;
-+      if (ret == 0)
-+              return -EINVAL;
-+      sensor->prev_sysclk = ret;
-+      /* read preview HTS */
-+      ret = ov5640_get_hts(sensor);
-+      if (ret < 0)
-+              return ret;
-+      if (ret == 0)
-+              return -EINVAL;
-+      sensor->prev_hts = ret;
-+
-+      /* read preview VTS */
-+      ret = ov5640_get_vts(sensor);
-+      if (ret < 0)
-+              return ret;
-+      prev_vts = ret;
-+
-+      /* calculate banding filter */
-+      /* 60Hz */
-+      band_step60 = sensor->prev_sysclk * 100 / sensor->prev_hts * 100 / 120;
-+      ret = ov5640_write_reg16(sensor, OV5640_REG_AEC_B60_STEP, band_step60);
-+      if (ret)
-+              return ret;
-+      if (!band_step60)
-+              return -EINVAL;
-+      max_band60 = (int)((prev_vts - 4) / band_step60);
-+      ret = ov5640_write_reg(sensor, OV5640_REG_AEC_CTRL0D, max_band60);
-+      if (ret)
-+              return ret;
-+
-+      /* 50Hz */
-+      band_step50 = sensor->prev_sysclk * 100 / sensor->prev_hts;
-+      ret = ov5640_write_reg16(sensor, OV5640_REG_AEC_B50_STEP, band_step50);
-+      if (ret)
-+              return ret;
-+      if (!band_step50)
-+              return -EINVAL;
-+      max_band50 = (int)((prev_vts - 4) / band_step50);
-+      return ov5640_write_reg(sensor, OV5640_REG_AEC_CTRL0E, max_band50);
-+}
-+
-+static int ov5640_set_ae_target(struct ov5640_dev *sensor, int target)
-+{
-+      /* stable in high */
-+      u32 fast_high, fast_low;
-+      int ret;
-+
-+      sensor->ae_low = target * 23 / 25;      /* 0.92 */
-+      sensor->ae_high = target * 27 / 25;     /* 1.08 */
-+
-+      fast_high = sensor->ae_high << 1;
-+      if (fast_high > 255)
-+              fast_high = 255;
-+
-+      fast_low = sensor->ae_low >> 1;
-+
-+      ret = ov5640_write_reg(sensor, OV5640_REG_AEC_CTRL0F, sensor->ae_high);
-+      if (ret)
-+              return ret;
-+      ret = ov5640_write_reg(sensor, OV5640_REG_AEC_CTRL10, sensor->ae_low);
-+      if (ret)
-+              return ret;
-+      ret = ov5640_write_reg(sensor, OV5640_REG_AEC_CTRL1B, sensor->ae_high);
-+      if (ret)
-+              return ret;
-+      ret = ov5640_write_reg(sensor, OV5640_REG_AEC_CTRL1E, sensor->ae_low);
-+      if (ret)
-+              return ret;
-+      ret = ov5640_write_reg(sensor, OV5640_REG_AEC_CTRL11, fast_high);
-+      if (ret)
-+              return ret;
-+      return ov5640_write_reg(sensor, OV5640_REG_AEC_CTRL1F, fast_low);
-+}
-+
-+static int ov5640_get_binning(struct ov5640_dev *sensor)
-+{
-+      u8 temp;
-+      int ret;
-+
-+      ret = ov5640_read_reg(sensor, OV5640_REG_TIMING_TC_REG21, &temp);
-+      if (ret)
-+              return ret;
-+
-+      return temp & BIT(0);
-+}
-+
-+static int ov5640_set_binning(struct ov5640_dev *sensor, bool enable)
-+{
-+      int ret;
-+
-+      /*
-+       * TIMING TC REG21:
-+       * - [0]:       Horizontal binning enable
-+       */
-+      ret = ov5640_mod_reg(sensor, OV5640_REG_TIMING_TC_REG21,
-+                           BIT(0), enable ? BIT(0) : 0);
-+      if (ret)
-+              return ret;
-+      /*
-+       * TIMING TC REG20:
-+       * - [0]:       Undocumented, but hardcoded init sequences
-+       *              are always setting REG21/REG20 bit 0 to same value...
-+       */
-+      return ov5640_mod_reg(sensor, OV5640_REG_TIMING_TC_REG20,
-+                            BIT(0), enable ? BIT(0) : 0);
-+}
-+
-+static int ov5640_set_virtual_channel(struct ov5640_dev *sensor)
-+{
-+      struct i2c_client *client = sensor->i2c_client;
-+      u8 temp, channel = virtual_channel;
-+      int ret;
-+
-+      if (channel > 3) {
-+              dev_err(&client->dev,
-+                      "%s: wrong virtual_channel parameter, expected (0..3), got %d\n",
-+                      __func__, channel);
-+              return -EINVAL;
-+      }
-+
-+      ret = ov5640_read_reg(sensor, OV5640_REG_DEBUG_MODE, &temp);
-+      if (ret)
-+              return ret;
-+      temp &= ~(3 << 6);
-+      temp |= (channel << 6);
-+      return ov5640_write_reg(sensor, OV5640_REG_DEBUG_MODE, temp);
-+}
-+
-+static const struct ov5640_mode_info *
-+ov5640_find_mode(struct ov5640_dev *sensor, enum ov5640_frame_rate fr,
-+               int width, int height, bool nearest)
-+{
-+      const struct ov5640_mode_info *mode;
-+
-+      mode = v4l2_find_nearest_size(ov5640_mode_data,
-+                                    ARRAY_SIZE(ov5640_mode_data),
-+                                    hact, vact,
-+                                    width, height);
-+
-+      if (!mode ||
-+          (!nearest && (mode->hact != width || mode->vact != height)))
-+              return NULL;
-+
-+      /* Check to see if the current mode exceeds the max frame rate */
-+      if (ov5640_framerates[fr] > ov5640_framerates[mode->max_fps])
-+              return NULL;
-+
-+      return mode;
-+}
-+
-+static u64 ov5640_calc_pixel_rate(struct ov5640_dev *sensor)
-+{
-+      u64 rate;
-+
-+      rate = sensor->current_mode->vtot * sensor->current_mode->htot;
-+      rate *= ov5640_framerates[sensor->current_fr];
-+
-+      return rate;
-+}
-+
-+/*
-+ * sensor changes between scaling and subsampling, go through
-+ * exposure calculation
-+ */
-+static int ov5640_set_mode_exposure_calc(struct ov5640_dev *sensor,
-+                                       const struct ov5640_mode_info *mode)
-+{
-+      u32 prev_shutter, prev_gain16;
-+      u32 cap_shutter, cap_gain16;
-+      u32 cap_sysclk, cap_hts, cap_vts;
-+      u32 light_freq, cap_bandfilt, cap_maxband;
-+      u32 cap_gain16_shutter;
-+      u8 average;
-+      int ret;
-+
-+      if (!mode->reg_data)
-+              return -EINVAL;
-+
-+      /* read preview shutter */
-+      ret = ov5640_get_exposure(sensor);
-+      if (ret < 0)
-+              return ret;
-+      prev_shutter = ret;
-+      ret = ov5640_get_binning(sensor);
-+      if (ret < 0)
-+              return ret;
-+      if (ret && mode->id != OV5640_MODE_720P_1280_720 &&
-+          mode->id != OV5640_MODE_1080P_1920_1080)
-+              prev_shutter *= 2;
-+
-+      /* read preview gain */
-+      ret = ov5640_get_gain(sensor);
-+      if (ret < 0)
-+              return ret;
-+      prev_gain16 = ret;
-+
-+      /* get average */
-+      ret = ov5640_read_reg(sensor, OV5640_REG_AVG_READOUT, &average);
-+      if (ret)
-+              return ret;
-+
-+      /* turn off night mode for capture */
-+      ret = ov5640_set_night_mode(sensor);
-+      if (ret < 0)
-+              return ret;
-+
-+      /* Write capture setting */
-+      ret = ov5640_load_regs(sensor, mode);
-+      if (ret < 0)
-+              return ret;
-+
-+      /* read capture VTS */
-+      ret = ov5640_get_vts(sensor);
-+      if (ret < 0)
-+              return ret;
-+      cap_vts = ret;
-+      ret = ov5640_get_hts(sensor);
-+      if (ret < 0)
-+              return ret;
-+      if (ret == 0)
-+              return -EINVAL;
-+      cap_hts = ret;
-+
-+      ret = ov5640_get_sysclk(sensor);
-+      if (ret < 0)
-+              return ret;
-+      if (ret == 0)
-+              return -EINVAL;
-+      cap_sysclk = ret;
-+
-+      /* calculate capture banding filter */
-+      ret = ov5640_get_light_freq(sensor);
-+      if (ret < 0)
-+              return ret;
-+      light_freq = ret;
-+
-+      if (light_freq == 60) {
-+              /* 60Hz */
-+              cap_bandfilt = cap_sysclk * 100 / cap_hts * 100 / 120;
-+      } else {
-+              /* 50Hz */
-+              cap_bandfilt = cap_sysclk * 100 / cap_hts;
-+      }
-+
-+      if (!sensor->prev_sysclk) {
-+              ret = ov5640_get_sysclk(sensor);
-+              if (ret < 0)
-+                      return ret;
-+              if (ret == 0)
-+                      return -EINVAL;
-+              sensor->prev_sysclk = ret;
-+      }
-+
-+      if (!cap_bandfilt)
-+              return -EINVAL;
-+
-+      cap_maxband = (int)((cap_vts - 4) / cap_bandfilt);
-+
-+      /* calculate capture shutter/gain16 */
-+      if (average > sensor->ae_low && average < sensor->ae_high) {
-+              /* in stable range */
-+              cap_gain16_shutter =
-+                      prev_gain16 * prev_shutter *
-+                      cap_sysclk / sensor->prev_sysclk *
-+                      sensor->prev_hts / cap_hts *
-+                      sensor->ae_target / average;
-+      } else {
-+              cap_gain16_shutter =
-+                      prev_gain16 * prev_shutter *
-+                      cap_sysclk / sensor->prev_sysclk *
-+                      sensor->prev_hts / cap_hts;
-+      }
-+
-+      /* gain to shutter */
-+      if (cap_gain16_shutter < (cap_bandfilt * 16)) {
-+              /* shutter < 1/100 */
-+              cap_shutter = cap_gain16_shutter / 16;
-+              if (cap_shutter < 1)
-+                      cap_shutter = 1;
-+
-+              cap_gain16 = cap_gain16_shutter / cap_shutter;
-+              if (cap_gain16 < 16)
-+                      cap_gain16 = 16;
-+      } else {
-+              if (cap_gain16_shutter > (cap_bandfilt * cap_maxband * 16)) {
-+                      /* exposure reach max */
-+                      cap_shutter = cap_bandfilt * cap_maxband;
-+                      if (!cap_shutter)
-+                              return -EINVAL;
-+
-+                      cap_gain16 = cap_gain16_shutter / cap_shutter;
-+              } else {
-+                      /* 1/100 < (cap_shutter = n/100) =< max */
-+                      cap_shutter =
-+                              ((int)(cap_gain16_shutter / 16 / cap_bandfilt))
-+                              * cap_bandfilt;
-+                      if (!cap_shutter)
-+                              return -EINVAL;
-+
-+                      cap_gain16 = cap_gain16_shutter / cap_shutter;
-+              }
-+      }
-+
-+      /* set capture gain */
-+      ret = ov5640_set_gain(sensor, cap_gain16);
-+      if (ret)
-+              return ret;
-+
-+      /* write capture shutter */
-+      if (cap_shutter > (cap_vts - 4)) {
-+              cap_vts = cap_shutter + 4;
-+              ret = ov5640_set_vts(sensor, cap_vts);
-+              if (ret < 0)
-+                      return ret;
-+      }
-+
-+      /* set exposure */
-+      return ov5640_set_exposure(sensor, cap_shutter);
-+}
-+
-+/*
-+ * if sensor changes inside scaling or subsampling
-+ * change mode directly
-+ */
-+static int ov5640_set_mode_direct(struct ov5640_dev *sensor,
-+                                const struct ov5640_mode_info *mode)
-+{
-+      if (!mode->reg_data)
-+              return -EINVAL;
-+
-+      /* Write capture setting */
-+      return ov5640_load_regs(sensor, mode);
-+}
-+
-+static int ov5640_set_mode(struct ov5640_dev *sensor)
-+{
-+      const struct ov5640_mode_info *mode = sensor->current_mode;
-+      const struct ov5640_mode_info *orig_mode = sensor->last_mode;
-+      enum ov5640_downsize_mode dn_mode, orig_dn_mode;
-+      bool auto_gain = sensor->ctrls.auto_gain->val == 1;
-+      bool auto_exp =  sensor->ctrls.auto_exp->val == V4L2_EXPOSURE_AUTO;
-+      unsigned long rate;
-+      int ret;
-+
-+      dn_mode = mode->dn_mode;
-+      orig_dn_mode = orig_mode->dn_mode;
-+
-+      /* auto gain and exposure must be turned off when changing modes */
-+      if (auto_gain) {
-+              ret = ov5640_set_autogain(sensor, false);
-+              if (ret)
-+                      return ret;
-+      }
-+
-+      if (auto_exp) {
-+              ret = ov5640_set_autoexposure(sensor, false);
-+              if (ret)
-+                      goto restore_auto_gain;
-+      }
-+
-+      /*
-+       * All the formats we support have 16 bits per pixel, seems to require
-+       * the same rate than YUV, so we can just use 16 bpp all the time.
-+       */
-+      rate = ov5640_calc_pixel_rate(sensor) * 16;
-+      if (sensor->ep.bus_type == V4L2_MBUS_CSI2_DPHY) {
-+              rate = rate / sensor->ep.bus.mipi_csi2.num_data_lanes;
-+              ret = ov5640_set_mipi_pclk(sensor, rate);
-+      } else {
-+              rate = rate / sensor->ep.bus.parallel.bus_width;
-+              ret = ov5640_set_dvp_pclk(sensor, rate);
-+      }
-+
-+      if (ret < 0)
-+              return 0;
-+
-+      if ((dn_mode == SUBSAMPLING && orig_dn_mode == SCALING) ||
-+          (dn_mode == SCALING && orig_dn_mode == SUBSAMPLING)) {
-+              /*
-+               * change between subsampling and scaling
-+               * go through exposure calculation
-+               */
-+              ret = ov5640_set_mode_exposure_calc(sensor, mode);
-+      } else {
-+              /*
-+               * change inside subsampling or scaling
-+               * download firmware directly
-+               */
-+              ret = ov5640_set_mode_direct(sensor, mode);
-+      }
-+      if (ret < 0)
-+              goto restore_auto_exp_gain;
-+
-+      /* restore auto gain and exposure */
-+      if (auto_gain)
-+              ov5640_set_autogain(sensor, true);
-+      if (auto_exp)
-+              ov5640_set_autoexposure(sensor, true);
-+
-+      ret = ov5640_set_binning(sensor, dn_mode != SCALING);
-+      if (ret < 0)
-+              return ret;
-+      ret = ov5640_set_ae_target(sensor, sensor->ae_target);
-+      if (ret < 0)
-+              return ret;
-+      ret = ov5640_get_light_freq(sensor);
-+      if (ret < 0)
-+              return ret;
-+      ret = ov5640_set_bandingfilter(sensor);
-+      if (ret < 0)
-+              return ret;
-+      ret = ov5640_set_virtual_channel(sensor);
-+      if (ret < 0)
-+              return ret;
-+
-+      sensor->pending_mode_change = false;
-+      sensor->last_mode = mode;
-+
-+      return 0;
-+
-+restore_auto_exp_gain:
-+      if (auto_exp)
-+              ov5640_set_autoexposure(sensor, true);
-+restore_auto_gain:
-+      if (auto_gain)
-+              ov5640_set_autogain(sensor, true);
-+
-+      return ret;
-+}
-+
-+static int ov5640_set_framefmt(struct ov5640_dev *sensor,
-+                             struct v4l2_mbus_framefmt *format);
-+
-+/* restore the last set video mode after chip power-on */
-+static int ov5640_restore_mode(struct ov5640_dev *sensor)
-+{
-+      int ret;
-+
-+      /* first load the initial register values */
-+      ret = ov5640_load_regs(sensor, &ov5640_mode_init_data);
-+      if (ret < 0)
-+              return ret;
-+      sensor->last_mode = &ov5640_mode_init_data;
-+
-+      ret = ov5640_mod_reg(sensor, OV5640_REG_SYS_ROOT_DIVIDER, 0x3f,
-+                           (ilog2(OV5640_SCLK2X_ROOT_DIV) << 2) |
-+                           ilog2(OV5640_SCLK_ROOT_DIV));
-+      if (ret)
-+              return ret;
-+
-+      /* now restore the last capture mode */
-+      ret = ov5640_set_mode(sensor);
-+      if (ret < 0)
-+              return ret;
-+
-+      return ov5640_set_framefmt(sensor, &sensor->fmt);
-+}
-+
-+static void ov5640_power(struct ov5640_dev *sensor, bool enable)
-+{
-+      if (!sensor->pwdn_gpio)
-+              return;
-+      gpiod_set_value_cansleep(sensor->pwdn_gpio, enable ? 0 : 1);
-+}
-+
-+static void ov5640_reset(struct ov5640_dev *sensor)
-+{
-+      if (!sensor->reset_gpio)
-+              return;
-+
-+      gpiod_set_value_cansleep(sensor->reset_gpio, 0);
-+
-+      /* camera power cycle */
-+      ov5640_power(sensor, false);
-+      usleep_range(5000, 10000);
-+      ov5640_power(sensor, true);
-+      usleep_range(5000, 10000);
-+
-+      gpiod_set_value_cansleep(sensor->reset_gpio, 1);
-+      usleep_range(1000, 2000);
-+
-+      gpiod_set_value_cansleep(sensor->reset_gpio, 0);
-+      usleep_range(20000, 25000);
-+}
-+
-+static int ov5640_set_power_on(struct ov5640_dev *sensor)
-+{
-+      struct i2c_client *client = sensor->i2c_client;
-+      int ret;
-+
-+      ret = clk_prepare_enable(sensor->xclk);
-+      if (ret) {
-+              dev_err(&client->dev, "%s: failed to enable clock\n",
-+                      __func__);
-+              return ret;
-+      }
-+
-+      ret = regulator_bulk_enable(OV5640_NUM_SUPPLIES,
-+                                  sensor->supplies);
-+      if (ret) {
-+              dev_err(&client->dev, "%s: failed to enable regulators\n",
-+                      __func__);
-+              goto xclk_off;
-+      }
-+
-+      ov5640_reset(sensor);
-+      ov5640_power(sensor, true);
-+
-+      ret = ov5640_init_slave_id(sensor);
-+      if (ret)
-+              goto power_off;
-+
-+      return 0;
-+
-+power_off:
-+      ov5640_power(sensor, false);
-+      regulator_bulk_disable(OV5640_NUM_SUPPLIES, sensor->supplies);
-+xclk_off:
-+      clk_disable_unprepare(sensor->xclk);
-+      return ret;
-+}
-+
-+static void ov5640_set_power_off(struct ov5640_dev *sensor)
-+{
-+      ov5640_power(sensor, false);
-+      regulator_bulk_disable(OV5640_NUM_SUPPLIES, sensor->supplies);
-+      clk_disable_unprepare(sensor->xclk);
-+}
-+
-+static int ov5640_set_power_mipi(struct ov5640_dev *sensor, bool on)
-+{
-+      int ret;
-+
-+      if (!on) {
-+              /* Reset MIPI bus settings to their default values. */
-+              ov5640_write_reg(sensor, OV5640_REG_IO_MIPI_CTRL00, 0x58);
-+              ov5640_write_reg(sensor, OV5640_REG_MIPI_CTRL00, 0x04);
-+              ov5640_write_reg(sensor, OV5640_REG_PAD_OUTPUT00, 0x00);
-+              return 0;
-+      }
-+
-+      /*
-+       * Power up MIPI HS Tx and LS Rx; 2 data lanes mode
-+       *
-+       * 0x300e = 0x40
-+       * [7:5] = 010  : 2 data lanes mode (see FIXME note in
-+       *                "ov5640_set_stream_mipi()")
-+       * [4] = 0      : Power up MIPI HS Tx
-+       * [3] = 0      : Power up MIPI LS Rx
-+       * [2] = 0      : MIPI interface disabled
-+       */
-+      ret = ov5640_write_reg(sensor, OV5640_REG_IO_MIPI_CTRL00, 0x40);
-+      if (ret)
-+              return ret;
-+
-+      /*
-+       * Gate clock and set LP11 in 'no packets mode' (idle)
-+       *
-+       * 0x4800 = 0x24
-+       * [5] = 1      : Gate clock when 'no packets'
-+       * [2] = 1      : MIPI bus in LP11 when 'no packets'
-+       */
-+      ret = ov5640_write_reg(sensor, OV5640_REG_MIPI_CTRL00, 0x24);
-+      if (ret)
-+              return ret;
-+
-+      /*
-+       * Set data lanes and clock in LP11 when 'sleeping'
-+       *
-+       * 0x3019 = 0x70
-+       * [6] = 1      : MIPI data lane 2 in LP11 when 'sleeping'
-+       * [5] = 1      : MIPI data lane 1 in LP11 when 'sleeping'
-+       * [4] = 1      : MIPI clock lane in LP11 when 'sleeping'
-+       */
-+      ret = ov5640_write_reg(sensor, OV5640_REG_PAD_OUTPUT00, 0x70);
-+      if (ret)
-+              return ret;
-+
-+      /* Give lanes some time to coax into LP11 state. */
-+      usleep_range(500, 1000);
-+
-+      return 0;
-+}
-+
-+static int ov5640_set_power_dvp(struct ov5640_dev *sensor, bool on)
-+{
-+      unsigned int flags = sensor->ep.bus.parallel.flags;
-+      bool bt656 = sensor->ep.bus_type == V4L2_MBUS_BT656;
-+      u8 polarities = 0;
-+      int ret;
-+
-+      if (!on) {
-+              /* Reset settings to their default values. */
-+              ov5640_write_reg(sensor, OV5640_REG_CCIR656_CTRL00, 0x00);
-+              ov5640_write_reg(sensor, OV5640_REG_IO_MIPI_CTRL00, 0x58);
-+              ov5640_write_reg(sensor, OV5640_REG_POLARITY_CTRL00, 0x20);
-+              ov5640_write_reg(sensor, OV5640_REG_PAD_OUTPUT_ENABLE01, 0x00);
-+              ov5640_write_reg(sensor, OV5640_REG_PAD_OUTPUT_ENABLE02, 0x00);
-+              return 0;
-+      }
-+
-+      /*
-+       * Note about parallel port configuration.
-+       *
-+       * When configured in parallel mode, the OV5640 will
-+       * output 10 bits data on DVP data lines [9:0].
-+       * If only 8 bits data are wanted, the 8 bits data lines
-+       * of the camera interface must be physically connected
-+       * on the DVP data lines [9:2].
-+       *
-+       * Control lines polarity can be configured through
-+       * devicetree endpoint control lines properties.
-+       * If no endpoint control lines properties are set,
-+       * polarity will be as below:
-+       * - VSYNC:     active high
-+       * - HREF:      active low
-+       * - PCLK:      active low
-+       *
-+       * VSYNC & HREF are not configured if BT656 bus mode is selected
-+       */
-+
-+      /*
-+       * BT656 embedded synchronization configuration
-+       *
-+       * CCIR656 CTRL00
-+       * - [7]:       SYNC code selection (0: auto generate sync code,
-+       *              1: sync code from regs 0x4732-0x4735)
-+       * - [6]:       f value in CCIR656 SYNC code when fixed f value
-+       * - [5]:       Fixed f value
-+       * - [4:3]:     Blank toggle data options (00: data=1'h040/1'h200,
-+       *              01: data from regs 0x4736-0x4738, 10: always keep 0)
-+       * - [1]:       Clip data disable
-+       * - [0]:       CCIR656 mode enable
-+       *
-+       * Default CCIR656 SAV/EAV mode with default codes
-+       * SAV=0xff000080 & EAV=0xff00009d is enabled here with settings:
-+       * - CCIR656 mode enable
-+       * - auto generation of sync codes
-+       * - blank toggle data 1'h040/1'h200
-+       * - clip reserved data (0x00 & 0xff changed to 0x01 & 0xfe)
-+       */
-+      ret = ov5640_write_reg(sensor, OV5640_REG_CCIR656_CTRL00,
-+                             bt656 ? 0x01 : 0x00);
-+      if (ret)
-+              return ret;
-+
-+      /*
-+       * configure parallel port control lines polarity
-+       *
-+       * POLARITY CTRL0
-+       * - [5]:       PCLK polarity (0: active low, 1: active high)
-+       * - [1]:       HREF polarity (0: active low, 1: active high)
-+       * - [0]:       VSYNC polarity (mismatch here between
-+       *              datasheet and hardware, 0 is active high
-+       *              and 1 is active low...)
-+       */
-+      if (!bt656) {
-+              if (flags & V4L2_MBUS_HSYNC_ACTIVE_HIGH)
-+                      polarities |= BIT(1);
-+              if (flags & V4L2_MBUS_VSYNC_ACTIVE_LOW)
-+                      polarities |= BIT(0);
-+      }
-+      if (flags & V4L2_MBUS_PCLK_SAMPLE_RISING)
-+              polarities |= BIT(5);
-+
-+      ret = ov5640_write_reg(sensor, OV5640_REG_POLARITY_CTRL00, polarities);
-+      if (ret)
-+              return ret;
-+
-+      /*
-+       * powerdown MIPI TX/RX PHY & enable DVP
-+       *
-+       * MIPI CONTROL 00
-+       * [4] = 1      : Power down MIPI HS Tx
-+       * [3] = 1      : Power down MIPI LS Rx
-+       * [2] = 0      : DVP enable (MIPI disable)
-+       */
-+      ret = ov5640_write_reg(sensor, OV5640_REG_IO_MIPI_CTRL00, 0x58);
-+      if (ret)
-+              return ret;
-+
-+      /*
-+       * enable VSYNC/HREF/PCLK DVP control lines
-+       * & D[9:6] DVP data lines
-+       *
-+       * PAD OUTPUT ENABLE 01
-+       * - 6:         VSYNC output enable
-+       * - 5:         HREF output enable
-+       * - 4:         PCLK output enable
-+       * - [3:0]:     D[9:6] output enable
-+       */
-+      ret = ov5640_write_reg(sensor, OV5640_REG_PAD_OUTPUT_ENABLE01,
-+                             bt656 ? 0x1f : 0x7f);
-+      if (ret)
-+              return ret;
-+
-+      /*
-+       * enable D[5:0] DVP data lines
-+       *
-+       * PAD OUTPUT ENABLE 02
-+       * - [7:2]:     D[5:0] output enable
-+       */
-+      return ov5640_write_reg(sensor, OV5640_REG_PAD_OUTPUT_ENABLE02, 0xfc);
-+}
-+
-+static int ov5640_set_power(struct ov5640_dev *sensor, bool on)
-+{
-+      int ret = 0;
-+
-+      if (on) {
-+              ret = ov5640_set_power_on(sensor);
-+              if (ret)
-+                      return ret;
-+
-+              ret = ov5640_restore_mode(sensor);
-+              if (ret)
-+                      goto power_off;
-+      }
-+
-+      if (sensor->ep.bus_type == V4L2_MBUS_CSI2_DPHY)
-+              ret = ov5640_set_power_mipi(sensor, on);
-+      else
-+              ret = ov5640_set_power_dvp(sensor, on);
-+      if (ret)
-+              goto power_off;
-+
-+      if (!on)
-+              ov5640_set_power_off(sensor);
-+
-+      return 0;
-+
-+power_off:
-+      ov5640_set_power_off(sensor);
-+      return ret;
-+}
-+
-+/* --------------- Subdev Operations --------------- */
-+
-+static int ov5640_s_power(struct v4l2_subdev *sd, int on)
-+{
-+      struct ov5640_dev *sensor = to_ov5640_dev(sd);
-+      int ret = 0;
-+
-+      mutex_lock(&sensor->lock);
-+
-+      /*
-+       * If the power count is modified from 0 to != 0 or from != 0 to 0,
-+       * update the power state.
-+       */
-+      if (sensor->power_count == !on) {
-+              ret = ov5640_set_power(sensor, !!on);
-+              if (ret)
-+                      goto out;
-+      }
-+
-+      /* Update the power count. */
-+      sensor->power_count += on ? 1 : -1;
-+      WARN_ON(sensor->power_count < 0);
-+out:
-+      mutex_unlock(&sensor->lock);
-+
-+      if (on && !ret && sensor->power_count == 1) {
-+              /* restore controls */
-+              ret = v4l2_ctrl_handler_setup(&sensor->ctrls.handler);
-+      }
-+
-+      return ret;
-+}
-+
-+static int ov5640_try_frame_interval(struct ov5640_dev *sensor,
-+                                   struct v4l2_fract *fi,
-+                                   u32 width, u32 height)
-+{
-+      const struct ov5640_mode_info *mode;
-+      enum ov5640_frame_rate rate = OV5640_15_FPS;
-+      int minfps, maxfps, best_fps, fps;
-+      int i;
-+
-+      minfps = ov5640_framerates[OV5640_15_FPS];
-+      maxfps = ov5640_framerates[OV5640_60_FPS];
-+
-+      if (fi->numerator == 0) {
-+              fi->denominator = maxfps;
-+              fi->numerator = 1;
-+              rate = OV5640_60_FPS;
-+              goto find_mode;
-+      }
-+
-+      fps = clamp_val(DIV_ROUND_CLOSEST(fi->denominator, fi->numerator),
-+                      minfps, maxfps);
-+
-+      best_fps = minfps;
-+      for (i = 0; i < ARRAY_SIZE(ov5640_framerates); i++) {
-+              int curr_fps = ov5640_framerates[i];
-+
-+              if (abs(curr_fps - fps) < abs(best_fps - fps)) {
-+                      best_fps = curr_fps;
-+                      rate = i;
-+              }
-+      }
-+
-+      fi->numerator = 1;
-+      fi->denominator = best_fps;
-+
-+find_mode:
-+      mode = ov5640_find_mode(sensor, rate, width, height, false);
-+      return mode ? rate : -EINVAL;
-+}
-+
-+static int ov5640_get_fmt(struct v4l2_subdev *sd,
-+                        struct v4l2_subdev_state *state,
-+                        struct v4l2_subdev_format *format)
-+{
-+      struct ov5640_dev *sensor = to_ov5640_dev(sd);
-+      struct v4l2_mbus_framefmt *fmt;
-+
-+      if (format->pad != 0)
-+              return -EINVAL;
-+
-+      mutex_lock(&sensor->lock);
-+
-+      if (format->which == V4L2_SUBDEV_FORMAT_TRY)
-+              fmt = v4l2_subdev_get_try_format(&sensor->sd, state,
-+                                               format->pad);
-+      else
-+              fmt = &sensor->fmt;
-+
-+      format->format = *fmt;
-+
-+      mutex_unlock(&sensor->lock);
-+
-+      return 0;
-+}
-+
-+static int ov5640_try_fmt_internal(struct v4l2_subdev *sd,
-+                                 struct v4l2_mbus_framefmt *fmt,
-+                                 enum ov5640_frame_rate fr,
-+                                 const struct ov5640_mode_info **new_mode)
-+{
-+      struct ov5640_dev *sensor = to_ov5640_dev(sd);
-+      const struct ov5640_mode_info *mode;
-+      int i;
-+
-+      mode = ov5640_find_mode(sensor, fr, fmt->width, fmt->height, true);
-+      if (!mode)
-+              return -EINVAL;
-+      fmt->width = mode->hact;
-+      fmt->height = mode->vact;
-+
-+      if (new_mode)
-+              *new_mode = mode;
-+
-+      for (i = 0; i < ARRAY_SIZE(ov5640_formats); i++)
-+              if (ov5640_formats[i].code == fmt->code)
-+                      break;
-+      if (i >= ARRAY_SIZE(ov5640_formats))
-+              i = 0;
-+
-+      fmt->code = ov5640_formats[i].code;
-+      fmt->colorspace = ov5640_formats[i].colorspace;
-+      fmt->ycbcr_enc = V4L2_MAP_YCBCR_ENC_DEFAULT(fmt->colorspace);
-+      fmt->quantization = V4L2_QUANTIZATION_FULL_RANGE;
-+      fmt->xfer_func = V4L2_MAP_XFER_FUNC_DEFAULT(fmt->colorspace);
-+
-+      return 0;
-+}
-+
-+static int ov5640_set_fmt(struct v4l2_subdev *sd,
-+                        struct v4l2_subdev_state *state,
-+                        struct v4l2_subdev_format *format)
-+{
-+      struct ov5640_dev *sensor = to_ov5640_dev(sd);
-+      const struct ov5640_mode_info *new_mode;
-+      struct v4l2_mbus_framefmt *mbus_fmt = &format->format;
-+      struct v4l2_mbus_framefmt *fmt;
-+      int ret;
-+
-+      if (format->pad != 0)
-+              return -EINVAL;
-+
-+      mutex_lock(&sensor->lock);
-+
-+      if (sensor->streaming) {
-+              ret = -EBUSY;
-+              goto out;
-+      }
-+
-+      ret = ov5640_try_fmt_internal(sd, mbus_fmt, 0, &new_mode);
-+      if (ret)
-+              goto out;
-+
-+      if (format->which == V4L2_SUBDEV_FORMAT_TRY)
-+              fmt = v4l2_subdev_get_try_format(sd, state, 0);
-+      else
-+              fmt = &sensor->fmt;
-+
-+      if (mbus_fmt->code != sensor->fmt.code)
-+              sensor->pending_fmt_change = true;
-+
-+      *fmt = *mbus_fmt;
-+
-+      if (new_mode != sensor->current_mode) {
-+              sensor->current_mode = new_mode;
-+              sensor->pending_mode_change = true;
-+      }
-+      if (new_mode->max_fps < sensor->current_fr) {
-+              sensor->current_fr = new_mode->max_fps;
-+              sensor->frame_interval.numerator = 1;
-+              sensor->frame_interval.denominator =
-+                      ov5640_framerates[sensor->current_fr];
-+              sensor->current_mode = new_mode;
-+              sensor->pending_mode_change = true;
-+      }
-+
-+      __v4l2_ctrl_s_ctrl_int64(sensor->ctrls.pixel_rate,
-+                               ov5640_calc_pixel_rate(sensor));
-+out:
-+      mutex_unlock(&sensor->lock);
-+      return ret;
-+}
-+
-+static int ov5640_set_framefmt(struct ov5640_dev *sensor,
-+                             struct v4l2_mbus_framefmt *format)
-+{
-+      int ret = 0;
-+      bool is_jpeg = false;
-+      u8 fmt, mux;
-+
-+      switch (format->code) {
-+      case MEDIA_BUS_FMT_UYVY8_2X8:
-+              /* YUV422, UYVY */
-+              fmt = 0x3f;
-+              mux = OV5640_FMT_MUX_YUV422;
-+              break;
-+      case MEDIA_BUS_FMT_YUYV8_2X8:
-+              /* YUV422, YUYV */
-+              fmt = 0x30;
-+              mux = OV5640_FMT_MUX_YUV422;
-+              break;
-+      case MEDIA_BUS_FMT_RGB565_2X8_LE:
-+              /* RGB565 {g[2:0],b[4:0]},{r[4:0],g[5:3]} */
-+              fmt = 0x6F;
-+              mux = OV5640_FMT_MUX_RGB;
-+              break;
-+      case MEDIA_BUS_FMT_RGB565_2X8_BE:
-+              /* RGB565 {r[4:0],g[5:3]},{g[2:0],b[4:0]} */
-+              fmt = 0x61;
-+              mux = OV5640_FMT_MUX_RGB;
-+              break;
-+      case MEDIA_BUS_FMT_JPEG_1X8:
-+              /* YUV422, YUYV */
-+              fmt = 0x30;
-+              mux = OV5640_FMT_MUX_YUV422;
-+              is_jpeg = true;
-+              break;
-+      case MEDIA_BUS_FMT_SBGGR8_1X8:
-+              /* Raw, BGBG... / GRGR... */
-+              fmt = 0x00;
-+              mux = OV5640_FMT_MUX_RAW_DPC;
-+              break;
-+      case MEDIA_BUS_FMT_SGBRG8_1X8:
-+              /* Raw bayer, GBGB... / RGRG... */
-+              fmt = 0x01;
-+              mux = OV5640_FMT_MUX_RAW_DPC;
-+              break;
-+      case MEDIA_BUS_FMT_SGRBG8_1X8:
-+              /* Raw bayer, GRGR... / BGBG... */
-+              fmt = 0x02;
-+              mux = OV5640_FMT_MUX_RAW_DPC;
-+              break;
-+      case MEDIA_BUS_FMT_SRGGB8_1X8:
-+              /* Raw bayer, RGRG... / GBGB... */
-+              fmt = 0x03;
-+              mux = OV5640_FMT_MUX_RAW_DPC;
-+              break;
-+      default:
-+              return -EINVAL;
-+      }
-+
-+      /* FORMAT CONTROL00: YUV and RGB formatting */
-+      ret = ov5640_write_reg(sensor, OV5640_REG_FORMAT_CONTROL00, fmt);
-+      if (ret)
-+              return ret;
-+
-+      /* FORMAT MUX CONTROL: ISP YUV or RGB */
-+      ret = ov5640_write_reg(sensor, OV5640_REG_ISP_FORMAT_MUX_CTRL, mux);
-+      if (ret)
-+              return ret;
-+
-+      /*
-+       * TIMING TC REG21:
-+       * - [5]:       JPEG enable
-+       */
-+      ret = ov5640_mod_reg(sensor, OV5640_REG_TIMING_TC_REG21,
-+                           BIT(5), is_jpeg ? BIT(5) : 0);
-+      if (ret)
-+              return ret;
-+
-+      /*
-+       * SYSTEM RESET02:
-+       * - [4]:       Reset JFIFO
-+       * - [3]:       Reset SFIFO
-+       * - [2]:       Reset JPEG
-+       */
-+      ret = ov5640_mod_reg(sensor, OV5640_REG_SYS_RESET02,
-+                           BIT(4) | BIT(3) | BIT(2),
-+                           is_jpeg ? 0 : (BIT(4) | BIT(3) | BIT(2)));
-+      if (ret)
-+              return ret;
-+
-+      /*
-+       * CLOCK ENABLE02:
-+       * - [5]:       Enable JPEG 2x clock
-+       * - [3]:       Enable JPEG clock
-+       */
-+      return ov5640_mod_reg(sensor, OV5640_REG_SYS_CLOCK_ENABLE02,
-+                            BIT(5) | BIT(3),
-+                            is_jpeg ? (BIT(5) | BIT(3)) : 0);
-+}
-+
-+/*
-+ * Sensor Controls.
-+ */
-+
-+static int ov5640_set_ctrl_hue(struct ov5640_dev *sensor, int value)
-+{
-+      int ret;
-+
-+      if (value) {
-+              ret = ov5640_mod_reg(sensor, OV5640_REG_SDE_CTRL0,
-+                                   BIT(0), BIT(0));
-+              if (ret)
-+                      return ret;
-+              ret = ov5640_write_reg16(sensor, OV5640_REG_SDE_CTRL1, value);
-+      } else {
-+              ret = ov5640_mod_reg(sensor, OV5640_REG_SDE_CTRL0, BIT(0), 0);
-+      }
-+
-+      return ret;
-+}
-+
-+static int ov5640_set_ctrl_contrast(struct ov5640_dev *sensor, int value)
-+{
-+      int ret;
-+
-+      if (value) {
-+              ret = ov5640_mod_reg(sensor, OV5640_REG_SDE_CTRL0,
-+                                   BIT(2), BIT(2));
-+              if (ret)
-+                      return ret;
-+              ret = ov5640_write_reg(sensor, OV5640_REG_SDE_CTRL5,
-+                                     value & 0xff);
-+      } else {
-+              ret = ov5640_mod_reg(sensor, OV5640_REG_SDE_CTRL0, BIT(2), 0);
-+      }
-+
-+      return ret;
-+}
-+
-+static int ov5640_set_ctrl_saturation(struct ov5640_dev *sensor, int value)
-+{
-+      int ret;
-+
-+      if (value) {
-+              ret = ov5640_mod_reg(sensor, OV5640_REG_SDE_CTRL0,
-+                                   BIT(1), BIT(1));
-+              if (ret)
-+                      return ret;
-+              ret = ov5640_write_reg(sensor, OV5640_REG_SDE_CTRL3,
-+                                     value & 0xff);
-+              if (ret)
-+                      return ret;
-+              ret = ov5640_write_reg(sensor, OV5640_REG_SDE_CTRL4,
-+                                     value & 0xff);
-+      } else {
-+              ret = ov5640_mod_reg(sensor, OV5640_REG_SDE_CTRL0, BIT(1), 0);
-+      }
-+
-+      return ret;
-+}
-+
-+static int ov5640_set_ctrl_white_balance(struct ov5640_dev *sensor, int awb)
-+{
-+      int ret;
-+
-+      ret = ov5640_mod_reg(sensor, OV5640_REG_AWB_MANUAL_CTRL,
-+                           BIT(0), awb ? 0 : 1);
-+      if (ret)
-+              return ret;
-+
-+      if (!awb) {
-+              u16 red = (u16)sensor->ctrls.red_balance->val;
-+              u16 blue = (u16)sensor->ctrls.blue_balance->val;
-+
-+              ret = ov5640_write_reg16(sensor, OV5640_REG_AWB_R_GAIN, red);
-+              if (ret)
-+                      return ret;
-+              ret = ov5640_write_reg16(sensor, OV5640_REG_AWB_B_GAIN, blue);
-+      }
-+
-+      return ret;
-+}
-+
-+static int ov5640_set_ctrl_exposure(struct ov5640_dev *sensor,
-+                                  enum v4l2_exposure_auto_type auto_exposure)
-+{
-+      struct ov5640_ctrls *ctrls = &sensor->ctrls;
-+      bool auto_exp = (auto_exposure == V4L2_EXPOSURE_AUTO);
-+      int ret = 0;
-+
-+      if (ctrls->auto_exp->is_new) {
-+              ret = ov5640_set_autoexposure(sensor, auto_exp);
-+              if (ret)
-+                      return ret;
-+      }
-+
-+      if (!auto_exp && ctrls->exposure->is_new) {
-+              u16 max_exp;
-+
-+              ret = ov5640_read_reg16(sensor, OV5640_REG_AEC_PK_VTS,
-+                                      &max_exp);
-+              if (ret)
-+                      return ret;
-+              ret = ov5640_get_vts(sensor);
-+              if (ret < 0)
-+                      return ret;
-+              max_exp += ret;
-+              ret = 0;
-+
-+              if (ctrls->exposure->val < max_exp)
-+                      ret = ov5640_set_exposure(sensor, ctrls->exposure->val);
-+      }
-+
-+      return ret;
-+}
-+
-+static int ov5640_set_ctrl_gain(struct ov5640_dev *sensor, bool auto_gain)
-+{
-+      struct ov5640_ctrls *ctrls = &sensor->ctrls;
-+      int ret = 0;
-+
-+      if (ctrls->auto_gain->is_new) {
-+              ret = ov5640_set_autogain(sensor, auto_gain);
-+              if (ret)
-+                      return ret;
-+      }
-+
-+      if (!auto_gain && ctrls->gain->is_new)
-+              ret = ov5640_set_gain(sensor, ctrls->gain->val);
-+
-+      return ret;
-+}
-+
-+static const char * const test_pattern_menu[] = {
-+      "Disabled",
-+      "Color bars",
-+      "Color bars w/ rolling bar",
-+      "Color squares",
-+      "Color squares w/ rolling bar",
-+};
-+
-+#define OV5640_TEST_ENABLE            BIT(7)
-+#define OV5640_TEST_ROLLING           BIT(6)  /* rolling horizontal bar */
-+#define OV5640_TEST_TRANSPARENT               BIT(5)
-+#define OV5640_TEST_SQUARE_BW         BIT(4)  /* black & white squares */
-+#define OV5640_TEST_BAR_STANDARD      (0 << 2)
-+#define OV5640_TEST_BAR_VERT_CHANGE_1 (1 << 2)
-+#define OV5640_TEST_BAR_HOR_CHANGE    (2 << 2)
-+#define OV5640_TEST_BAR_VERT_CHANGE_2 (3 << 2)
-+#define OV5640_TEST_BAR                       (0 << 0)
-+#define OV5640_TEST_RANDOM            (1 << 0)
-+#define OV5640_TEST_SQUARE            (2 << 0)
-+#define OV5640_TEST_BLACK             (3 << 0)
-+
-+static const u8 test_pattern_val[] = {
-+      0,
-+      OV5640_TEST_ENABLE | OV5640_TEST_BAR_VERT_CHANGE_1 |
-+              OV5640_TEST_BAR,
-+      OV5640_TEST_ENABLE | OV5640_TEST_ROLLING |
-+              OV5640_TEST_BAR_VERT_CHANGE_1 | OV5640_TEST_BAR,
-+      OV5640_TEST_ENABLE | OV5640_TEST_SQUARE,
-+      OV5640_TEST_ENABLE | OV5640_TEST_ROLLING | OV5640_TEST_SQUARE,
-+};
-+
-+static int ov5640_set_ctrl_test_pattern(struct ov5640_dev *sensor, int value)
-+{
-+      return ov5640_write_reg(sensor, OV5640_REG_PRE_ISP_TEST_SET1,
-+                              test_pattern_val[value]);
-+}
-+
-+static int ov5640_set_ctrl_light_freq(struct ov5640_dev *sensor, int value)
-+{
-+      int ret;
-+
-+      ret = ov5640_mod_reg(sensor, OV5640_REG_HZ5060_CTRL01, BIT(7),
-+                           (value == V4L2_CID_POWER_LINE_FREQUENCY_AUTO) ?
-+                           0 : BIT(7));
-+      if (ret)
-+              return ret;
-+
-+      return ov5640_mod_reg(sensor, OV5640_REG_HZ5060_CTRL00, BIT(2),
-+                            (value == V4L2_CID_POWER_LINE_FREQUENCY_50HZ) ?
-+                            BIT(2) : 0);
-+}
-+
-+static int ov5640_set_ctrl_hflip(struct ov5640_dev *sensor, int value)
-+{
-+      /*
-+       * If sensor is mounted upside down, mirror logic is inversed.
-+       *
-+       * Sensor is a BSI (Back Side Illuminated) one,
-+       * so image captured is physically mirrored.
-+       * This is why mirror logic is inversed in
-+       * order to cancel this mirror effect.
-+       */
-+
-+      /*
-+       * TIMING TC REG21:
-+       * - [2]:       ISP mirror
-+       * - [1]:       Sensor mirror
-+       */
-+      return ov5640_mod_reg(sensor, OV5640_REG_TIMING_TC_REG21,
-+                            BIT(2) | BIT(1),
-+                            (!(value ^ sensor->upside_down)) ?
-+                            (BIT(2) | BIT(1)) : 0);
-+}
-+
-+static int ov5640_set_ctrl_vflip(struct ov5640_dev *sensor, int value)
-+{
-+      /* If sensor is mounted upside down, flip logic is inversed */
-+
-+      /*
-+       * TIMING TC REG20:
-+       * - [2]:       ISP vflip
-+       * - [1]:       Sensor vflip
-+       */
-+      return ov5640_mod_reg(sensor, OV5640_REG_TIMING_TC_REG20,
-+                            BIT(2) | BIT(1),
-+                            (value ^ sensor->upside_down) ?
-+                            (BIT(2) | BIT(1)) : 0);
-+}
-+
-+static int ov5640_g_volatile_ctrl(struct v4l2_ctrl *ctrl)
-+{
-+      struct v4l2_subdev *sd = ctrl_to_sd(ctrl);
-+      struct ov5640_dev *sensor = to_ov5640_dev(sd);
-+      int val;
-+
-+      /* v4l2_ctrl_lock() locks our own mutex */
-+
-+      switch (ctrl->id) {
-+      case V4L2_CID_AUTOGAIN:
-+              val = ov5640_get_gain(sensor);
-+              if (val < 0)
-+                      return val;
-+              sensor->ctrls.gain->val = val;
-+              break;
-+      case V4L2_CID_EXPOSURE_AUTO:
-+              val = ov5640_get_exposure(sensor);
-+              if (val < 0)
-+                      return val;
-+              sensor->ctrls.exposure->val = val;
-+              break;
-+      }
-+
-+      return 0;
-+}
-+
-+static int ov5640_s_ctrl(struct v4l2_ctrl *ctrl)
-+{
-+      struct v4l2_subdev *sd = ctrl_to_sd(ctrl);
-+      struct ov5640_dev *sensor = to_ov5640_dev(sd);
-+      int ret;
-+
-+      /* v4l2_ctrl_lock() locks our own mutex */
-+
-+      /*
-+       * If the device is not powered up by the host driver do
-+       * not apply any controls to H/W at this time. Instead
-+       * the controls will be restored right after power-up.
-+       */
-+      if (sensor->power_count == 0)
-+              return 0;
-+
-+      switch (ctrl->id) {
-+      case V4L2_CID_AUTOGAIN:
-+              ret = ov5640_set_ctrl_gain(sensor, ctrl->val);
-+              break;
-+      case V4L2_CID_EXPOSURE_AUTO:
-+              ret = ov5640_set_ctrl_exposure(sensor, ctrl->val);
-+              break;
-+      case V4L2_CID_AUTO_WHITE_BALANCE:
-+              ret = ov5640_set_ctrl_white_balance(sensor, ctrl->val);
-+              break;
-+      case V4L2_CID_HUE:
-+              ret = ov5640_set_ctrl_hue(sensor, ctrl->val);
-+              break;
-+      case V4L2_CID_CONTRAST:
-+              ret = ov5640_set_ctrl_contrast(sensor, ctrl->val);
-+              break;
-+      case V4L2_CID_SATURATION:
-+              ret = ov5640_set_ctrl_saturation(sensor, ctrl->val);
-+              break;
-+      case V4L2_CID_TEST_PATTERN:
-+              ret = ov5640_set_ctrl_test_pattern(sensor, ctrl->val);
-+              break;
-+      case V4L2_CID_POWER_LINE_FREQUENCY:
-+              ret = ov5640_set_ctrl_light_freq(sensor, ctrl->val);
-+              break;
-+      case V4L2_CID_HFLIP:
-+              ret = ov5640_set_ctrl_hflip(sensor, ctrl->val);
-+              break;
-+      case V4L2_CID_VFLIP:
-+              ret = ov5640_set_ctrl_vflip(sensor, ctrl->val);
-+              break;
-+      default:
-+              ret = -EINVAL;
-+              break;
-+      }
-+
-+      return ret;
-+}
-+
-+static const struct v4l2_ctrl_ops ov5640_ctrl_ops = {
-+      .g_volatile_ctrl = ov5640_g_volatile_ctrl,
-+      .s_ctrl = ov5640_s_ctrl,
-+};
-+
-+static int ov5640_init_controls(struct ov5640_dev *sensor)
-+{
-+      const struct v4l2_ctrl_ops *ops = &ov5640_ctrl_ops;
-+      struct ov5640_ctrls *ctrls = &sensor->ctrls;
-+      struct v4l2_ctrl_handler *hdl = &ctrls->handler;
-+      int ret;
-+
-+      v4l2_ctrl_handler_init(hdl, 32);
-+
-+      /* we can use our own mutex for the ctrl lock */
-+      hdl->lock = &sensor->lock;
-+
-+      /* Clock related controls */
-+      ctrls->pixel_rate = v4l2_ctrl_new_std(hdl, ops, V4L2_CID_PIXEL_RATE,
-+                                            0, INT_MAX, 1,
-+                                            ov5640_calc_pixel_rate(sensor));
-+
-+      /* Auto/manual white balance */
-+      ctrls->auto_wb = v4l2_ctrl_new_std(hdl, ops,
-+                                         V4L2_CID_AUTO_WHITE_BALANCE,
-+                                         0, 1, 1, 1);
-+      ctrls->blue_balance = v4l2_ctrl_new_std(hdl, ops, V4L2_CID_BLUE_BALANCE,
-+                                              0, 4095, 1, 0);
-+      ctrls->red_balance = v4l2_ctrl_new_std(hdl, ops, V4L2_CID_RED_BALANCE,
-+                                             0, 4095, 1, 0);
-+      /* Auto/manual exposure */
-+      ctrls->auto_exp = v4l2_ctrl_new_std_menu(hdl, ops,
-+                                               V4L2_CID_EXPOSURE_AUTO,
-+                                               V4L2_EXPOSURE_MANUAL, 0,
-+                                               V4L2_EXPOSURE_AUTO);
-+      ctrls->exposure = v4l2_ctrl_new_std(hdl, ops, V4L2_CID_EXPOSURE,
-+                                          0, 65535, 1, 0);
-+      /* Auto/manual gain */
-+      ctrls->auto_gain = v4l2_ctrl_new_std(hdl, ops, V4L2_CID_AUTOGAIN,
-+                                           0, 1, 1, 1);
-+      ctrls->gain = v4l2_ctrl_new_std(hdl, ops, V4L2_CID_GAIN,
-+                                      0, 1023, 1, 0);
-+
-+      ctrls->saturation = v4l2_ctrl_new_std(hdl, ops, V4L2_CID_SATURATION,
-+                                            0, 255, 1, 64);
-+      ctrls->hue = v4l2_ctrl_new_std(hdl, ops, V4L2_CID_HUE,
-+                                     0, 359, 1, 0);
-+      ctrls->contrast = v4l2_ctrl_new_std(hdl, ops, V4L2_CID_CONTRAST,
-+                                          0, 255, 1, 0);
-+      ctrls->test_pattern =
-+              v4l2_ctrl_new_std_menu_items(hdl, ops, V4L2_CID_TEST_PATTERN,
-+                                           ARRAY_SIZE(test_pattern_menu) - 1,
-+                                           0, 0, test_pattern_menu);
-+      ctrls->hflip = v4l2_ctrl_new_std(hdl, ops, V4L2_CID_HFLIP,
-+                                       0, 1, 1, 0);
-+      ctrls->vflip = v4l2_ctrl_new_std(hdl, ops, V4L2_CID_VFLIP,
-+                                       0, 1, 1, 0);
-+
-+      ctrls->light_freq =
-+              v4l2_ctrl_new_std_menu(hdl, ops,
-+                                     V4L2_CID_POWER_LINE_FREQUENCY,
-+                                     V4L2_CID_POWER_LINE_FREQUENCY_AUTO, 0,
-+                                     V4L2_CID_POWER_LINE_FREQUENCY_50HZ);
-+
-+      if (hdl->error) {
-+              ret = hdl->error;
-+              goto free_ctrls;
-+      }
-+
-+      ctrls->pixel_rate->flags |= V4L2_CTRL_FLAG_READ_ONLY;
-+      ctrls->gain->flags |= V4L2_CTRL_FLAG_VOLATILE;
-+      ctrls->exposure->flags |= V4L2_CTRL_FLAG_VOLATILE;
-+
-+      v4l2_ctrl_auto_cluster(3, &ctrls->auto_wb, 0, false);
-+      v4l2_ctrl_auto_cluster(2, &ctrls->auto_gain, 0, true);
-+      v4l2_ctrl_auto_cluster(2, &ctrls->auto_exp, 1, true);
-+
-+      sensor->sd.ctrl_handler = hdl;
-+      return 0;
-+
-+free_ctrls:
-+      v4l2_ctrl_handler_free(hdl);
-+      return ret;
-+}
-+
-+static int ov5640_enum_frame_size(struct v4l2_subdev *sd,
-+                                struct v4l2_subdev_state *state,
-+                                struct v4l2_subdev_frame_size_enum *fse)
-+{
-+      if (fse->pad != 0)
-+              return -EINVAL;
-+      if (fse->index >= OV5640_NUM_MODES)
-+              return -EINVAL;
-+
-+      fse->min_width =
-+              ov5640_mode_data[fse->index].hact;
-+      fse->max_width = fse->min_width;
-+      fse->min_height =
-+              ov5640_mode_data[fse->index].vact;
-+      fse->max_height = fse->min_height;
-+
-+      return 0;
-+}
-+
-+static int ov5640_enum_frame_interval(
-+      struct v4l2_subdev *sd,
-+      struct v4l2_subdev_state *state,
-+      struct v4l2_subdev_frame_interval_enum *fie)
-+{
-+      struct ov5640_dev *sensor = to_ov5640_dev(sd);
-+      struct v4l2_fract tpf;
-+      int ret;
-+
-+      if (fie->pad != 0)
-+              return -EINVAL;
-+      if (fie->index >= OV5640_NUM_FRAMERATES)
-+              return -EINVAL;
-+
-+      tpf.numerator = 1;
-+      tpf.denominator = ov5640_framerates[fie->index];
-+
-+      ret = ov5640_try_frame_interval(sensor, &tpf,
-+                                      fie->width, fie->height);
-+      if (ret < 0)
-+              return -EINVAL;
-+
-+      fie->interval = tpf;
-+      return 0;
-+}
-+
-+static int ov5640_g_frame_interval(struct v4l2_subdev *sd,
-+                                 struct v4l2_subdev_frame_interval *fi)
-+{
-+      struct ov5640_dev *sensor = to_ov5640_dev(sd);
-+
-+      mutex_lock(&sensor->lock);
-+      fi->interval = sensor->frame_interval;
-+      mutex_unlock(&sensor->lock);
-+
-+      return 0;
-+}
-+
-+static int ov5640_s_frame_interval(struct v4l2_subdev *sd,
-+                                 struct v4l2_subdev_frame_interval *fi)
-+{
-+      struct ov5640_dev *sensor = to_ov5640_dev(sd);
-+      const struct ov5640_mode_info *mode;
-+      int frame_rate, ret = 0;
-+
-+      if (fi->pad != 0)
-+              return -EINVAL;
-+
-+      mutex_lock(&sensor->lock);
-+
-+      if (sensor->streaming) {
-+              ret = -EBUSY;
-+              goto out;
-+      }
-+
-+      mode = sensor->current_mode;
-+
-+      frame_rate = ov5640_try_frame_interval(sensor, &fi->interval,
-+                                             mode->hact, mode->vact);
-+      if (frame_rate < 0) {
-+              /* Always return a valid frame interval value */
-+              fi->interval = sensor->frame_interval;
-+              goto out;
-+      }
-+
-+      mode = ov5640_find_mode(sensor, frame_rate, mode->hact,
-+                              mode->vact, true);
-+      if (!mode) {
-+              ret = -EINVAL;
-+              goto out;
-+      }
-+
-+      if (mode != sensor->current_mode ||
-+          frame_rate != sensor->current_fr) {
-+              sensor->current_fr = frame_rate;
-+              sensor->frame_interval = fi->interval;
-+              sensor->current_mode = mode;
-+              sensor->pending_mode_change = true;
-+
-+              __v4l2_ctrl_s_ctrl_int64(sensor->ctrls.pixel_rate,
-+                                       ov5640_calc_pixel_rate(sensor));
-+      }
-+out:
-+      mutex_unlock(&sensor->lock);
-+      return ret;
-+}
-+
-+static int ov5640_enum_mbus_code(struct v4l2_subdev *sd,
-+                               struct v4l2_subdev_state *state,
-+                               struct v4l2_subdev_mbus_code_enum *code)
-+{
-+      if (code->pad != 0)
-+              return -EINVAL;
-+      if (code->index >= ARRAY_SIZE(ov5640_formats))
-+              return -EINVAL;
-+
-+      code->code = ov5640_formats[code->index].code;
-+      return 0;
-+}
-+
-+static int ov5640_s_stream(struct v4l2_subdev *sd, int enable)
-+{
-+      struct ov5640_dev *sensor = to_ov5640_dev(sd);
-+      int ret = 0;
-+
-+      mutex_lock(&sensor->lock);
-+
-+      if (sensor->streaming == !enable) {
-+              if (enable && sensor->pending_mode_change) {
-+                      ret = ov5640_set_mode(sensor);
-+                      if (ret)
-+                              goto out;
-+              }
-+
-+              if (enable && sensor->pending_fmt_change) {
-+                      ret = ov5640_set_framefmt(sensor, &sensor->fmt);
-+                      if (ret)
-+                              goto out;
-+                      sensor->pending_fmt_change = false;
-+              }
-+
-+              if (sensor->ep.bus_type == V4L2_MBUS_CSI2_DPHY)
-+                      ret = ov5640_set_stream_mipi(sensor, enable);
-+              else
-+                      ret = ov5640_set_stream_dvp(sensor, enable);
-+
-+              if (ret)
-+                      goto out;
-+      }
-+      sensor->streaming += enable ? 1 : -1;
-+      WARN_ON(sensor->streaming < 0);
-+out:
-+      mutex_unlock(&sensor->lock);
-+      return ret;
-+}
-+
-+int ov5640_skip_frames(struct v4l2_subdev *sd, u32 *frames)
-+{
-+      *frames = OV5640_SKIP_FRAMES;
-+      return 0;
-+}
-+
-+static const struct v4l2_subdev_core_ops ov5640_core_ops = {
-+      .s_power = ov5640_s_power,
-+      .log_status = v4l2_ctrl_subdev_log_status,
-+      .subscribe_event = v4l2_ctrl_subdev_subscribe_event,
-+      .unsubscribe_event = v4l2_event_subdev_unsubscribe,
-+};
-+
-+static const struct v4l2_subdev_video_ops ov5640_video_ops = {
-+      .g_frame_interval = ov5640_g_frame_interval,
-+      .s_frame_interval = ov5640_s_frame_interval,
-+      .s_stream = ov5640_s_stream,
-+};
-+
-+static const struct v4l2_subdev_pad_ops ov5640_pad_ops = {
-+      .enum_mbus_code = ov5640_enum_mbus_code,
-+      .get_fmt = ov5640_get_fmt,
-+      .set_fmt = ov5640_set_fmt,
-+      .enum_frame_size = ov5640_enum_frame_size,
-+      .enum_frame_interval = ov5640_enum_frame_interval,
-+};
-+
-+static const struct v4l2_subdev_sensor_ops ov5640_sensor_ops = {
-+      .g_skip_frames = ov5640_skip_frames,
-+};
-+
-+static const struct v4l2_subdev_ops ov5640_subdev_ops = {
-+      .core = &ov5640_core_ops,
-+      .video = &ov5640_video_ops,
-+      .pad = &ov5640_pad_ops,
-+      .sensor = &ov5640_sensor_ops,
-+};
-+
-+static int ov5640_get_regulators(struct ov5640_dev *sensor)
-+{
-+      int i;
-+
-+      for (i = 0; i < OV5640_NUM_SUPPLIES; i++)
-+              sensor->supplies[i].supply = ov5640_supply_name[i];
-+
-+      return devm_regulator_bulk_get(&sensor->i2c_client->dev,
-+                                     OV5640_NUM_SUPPLIES,
-+                                     sensor->supplies);
-+}
-+
-+static int ov5640_check_chip_id(struct ov5640_dev *sensor)
-+{
-+      struct i2c_client *client = sensor->i2c_client;
-+      int ret = 0;
-+      u16 chip_id;
-+
-+      ret = ov5640_set_power_on(sensor);
-+      if (ret)
-+              return ret;
-+
-+      ret = ov5640_read_reg16(sensor, OV5640_REG_CHIP_ID, &chip_id);
-+      if (ret) {
-+              dev_err(&client->dev, "%s: failed to read chip identifier\n",
-+                      __func__);
-+              goto power_off;
-+      }
-+
-+      if (chip_id != OV5640_CHIP_ID) {
-+              dev_err(&client->dev, "%s: wrong chip identifier, expected 0x%x, got 0x%x\n",
-+                      __func__, OV5640_CHIP_ID, chip_id);
-+              ret = -ENXIO;
-+      }
-+      dev_err(&client->dev, "%s: chip identifier, got 0x%x\n",
-+              __func__, chip_id);
-+
-+power_off:
-+      ov5640_set_power_off(sensor);
-+      return ret;
-+}
-+
-+static int ov5640_probe(struct i2c_client *client)
-+{
-+      struct device *dev = &client->dev;
-+      struct fwnode_handle *endpoint;
-+      struct ov5640_dev *sensor;
-+      struct v4l2_mbus_framefmt *fmt;
-+      u32 rotation;
-+      int ret;
-+
-+      sensor = devm_kzalloc(dev, sizeof(*sensor), GFP_KERNEL);
-+      if (!sensor)
-+              return -ENOMEM;
-+
-+      sensor->i2c_client = client;
-+
-+      /*
-+       * default init sequence initialize sensor to
-+       * YUV422 UYVY VGA@30fps
-+       */
-+      fmt = &sensor->fmt;
-+      fmt->code = MEDIA_BUS_FMT_UYVY8_2X8;
-+      fmt->colorspace = V4L2_COLORSPACE_SRGB;
-+      fmt->ycbcr_enc = V4L2_MAP_YCBCR_ENC_DEFAULT(fmt->colorspace);
-+      fmt->quantization = V4L2_QUANTIZATION_FULL_RANGE;
-+      fmt->xfer_func = V4L2_MAP_XFER_FUNC_DEFAULT(fmt->colorspace);
-+      fmt->width = 640;
-+      fmt->height = 480;
-+      fmt->field = V4L2_FIELD_NONE;
-+      sensor->frame_interval.numerator = 1;
-+      sensor->frame_interval.denominator = ov5640_framerates[OV5640_30_FPS];
-+      sensor->current_fr = OV5640_30_FPS;
-+      sensor->current_mode =
-+              &ov5640_mode_data[OV5640_MODE_VGA_640_480];
-+      sensor->last_mode = sensor->current_mode;
-+
-+      sensor->ae_target = 52;
-+
-+      /* optional indication of physical rotation of sensor */
-+      ret = fwnode_property_read_u32(dev_fwnode(&client->dev), "rotation",
-+                                     &rotation);
-+      if (!ret) {
-+              switch (rotation) {
-+              case 180:
-+                      sensor->upside_down = true;
-+                      fallthrough;
-+              case 0:
-+                      break;
-+              default:
-+                      dev_warn(dev, "%u degrees rotation is not supported, ignoring...\n",
-+                               rotation);
-+              }
-+      }
-+
-+      endpoint = fwnode_graph_get_next_endpoint(dev_fwnode(&client->dev),
-+                                                NULL);
-+      if (!endpoint) {
-+              dev_err(dev, "endpoint node not found\n");
-+              return -EINVAL;
-+      }
-+
-+      ret = v4l2_fwnode_endpoint_parse(endpoint, &sensor->ep);
-+      fwnode_handle_put(endpoint);
-+      if (ret) {
-+              dev_err(dev, "Could not parse endpoint\n");
-+              return ret;
-+      }
-+
-+      if (sensor->ep.bus_type != V4L2_MBUS_PARALLEL &&
-+          sensor->ep.bus_type != V4L2_MBUS_CSI2_DPHY &&
-+          sensor->ep.bus_type != V4L2_MBUS_BT656) {
-+              dev_err(dev, "Unsupported bus type %d\n", sensor->ep.bus_type);
-+              return -EINVAL;
-+      }
-+
-+      /* get system clock (xclk) */
-+      sensor->xclk = devm_clk_get(dev, "xclk");
-+      if (IS_ERR(sensor->xclk)) {
-+              dev_err(dev, "failed to get xclk\n");
-+              return PTR_ERR(sensor->xclk);
-+      }
-+
-+      sensor->xclk_freq = clk_get_rate(sensor->xclk);
-+      if (sensor->xclk_freq < OV5640_XCLK_MIN ||
-+          sensor->xclk_freq > OV5640_XCLK_MAX) {
-+              dev_err(dev, "xclk frequency out of range: %d Hz\n",
-+                      sensor->xclk_freq);
-+              return -EINVAL;
-+      }
-+
-+      /* request optional power down pin */
-+      sensor->pwdn_gpio = devm_gpiod_get_optional(dev, "powerdown",
-+                                                  GPIOD_OUT_HIGH);
-+      if (IS_ERR(sensor->pwdn_gpio))
-+              return PTR_ERR(sensor->pwdn_gpio);
-+
-+      /* request optional reset pin */
-+      sensor->reset_gpio = devm_gpiod_get_optional(dev, "reset",
-+                                                   GPIOD_OUT_HIGH);
-+      if (IS_ERR(sensor->reset_gpio))
-+              return PTR_ERR(sensor->reset_gpio);
-+
-+      v4l2_i2c_subdev_init(&sensor->sd, client, &ov5640_subdev_ops);
-+
-+      sensor->sd.flags |= V4L2_SUBDEV_FL_HAS_DEVNODE |
-+                          V4L2_SUBDEV_FL_HAS_EVENTS;
-+      sensor->pad.flags = MEDIA_PAD_FL_SOURCE;
-+      sensor->sd.entity.function = MEDIA_ENT_F_CAM_SENSOR;
-+      ret = media_entity_pads_init(&sensor->sd.entity, 1, &sensor->pad);
-+      if (ret)
-+              return ret;
-+
-+      ret = ov5640_get_regulators(sensor);
-+      if (ret)
-+              return ret;
-+
-+      mutex_init(&sensor->lock);
-+
-+      ret = ov5640_check_chip_id(sensor);
-+      if (ret)
-+              goto entity_cleanup;
-+
-+      ret = ov5640_init_controls(sensor);
-+      if (ret)
-+              goto entity_cleanup;
-+
-+      ret = v4l2_async_register_subdev_sensor(&sensor->sd);
-+      if (ret)
-+              goto free_ctrls;
-+
-+      return 0;
-+
-+free_ctrls:
-+      v4l2_ctrl_handler_free(&sensor->ctrls.handler);
-+entity_cleanup:
-+      media_entity_cleanup(&sensor->sd.entity);
-+      mutex_destroy(&sensor->lock);
-+      return ret;
-+}
-+
-+static int ov5640_remove(struct i2c_client *client)
-+{
-+      struct v4l2_subdev *sd = i2c_get_clientdata(client);
-+      struct ov5640_dev *sensor = to_ov5640_dev(sd);
-+
-+      v4l2_async_unregister_subdev(&sensor->sd);
-+      media_entity_cleanup(&sensor->sd.entity);
-+      v4l2_ctrl_handler_free(&sensor->ctrls.handler);
-+      mutex_destroy(&sensor->lock);
-+
-+      return 0;
-+}
-+
-+static const struct i2c_device_id ov5640_id[] = {
-+      {"ov5640", 0},
-+      {},
-+};
-+MODULE_DEVICE_TABLE(i2c, ov5640_id);
-+
-+static const struct of_device_id ov5640_dt_ids[] = {
-+      { .compatible = "ovti,ov5640" },
-+      { /* sentinel */ }
-+};
-+MODULE_DEVICE_TABLE(of, ov5640_dt_ids);
-+
-+static struct i2c_driver ov5640_i2c_driver = {
-+      .driver = {
-+              .name  = "ov5640",
-+              .of_match_table = ov5640_dt_ids,
-+      },
-+      .id_table = ov5640_id,
-+      .probe_new = ov5640_probe,
-+      .remove   = ov5640_remove,
-+};
-+
-+module_i2c_driver(ov5640_i2c_driver);
-+
-+MODULE_DESCRIPTION("OV5640 MIPI Camera Subdev Driver");
-+MODULE_LICENSE("GPL");
---- /dev/null
-+++ b/drivers/media/platform/starfive/v4l2_driver/sc2235.c
-@@ -0,0 +1,1914 @@
-+// SPDX-License-Identifier: GPL-2.0-or-later
-+/*
-+ * Copyright (C) 2021-2023 StarFive Technology Co., Ltd.
-+ *
-+ */
-+
-+#include <linux/clk.h>
-+#include <linux/clk-provider.h>
-+#include <linux/clkdev.h>
-+#include <linux/ctype.h>
-+#include <linux/delay.h>
-+#include <linux/device.h>
-+#include <linux/gpio/consumer.h>
-+#include <linux/i2c.h>
-+#include <linux/init.h>
-+#include <linux/module.h>
-+#include <linux/pm_runtime.h>
-+#include <linux/of_device.h>
-+#include <linux/regulator/consumer.h>
-+#include <linux/slab.h>
-+#include <linux/types.h>
-+#include <media/v4l2-async.h>
-+#include <media/v4l2-ctrls.h>
-+#include <media/v4l2-device.h>
-+#include <media/v4l2-event.h>
-+#include <media/v4l2-fwnode.h>
-+#include <media/v4l2-subdev.h>
-+#include "stfcamss.h"
-+
-+/* min/typical/max system clock (xclk) frequencies */
-+#define SC2235_XCLK_MIN                       6000000
-+#define SC2235_XCLK_MAX                       27000000
-+
-+#define SC2235_CHIP_ID                (0x2235)
-+
-+#define SC2235_REG_CHIP_ID                            0x3107
-+#define SC2235_REG_AEC_PK_MANUAL              0x3e03
-+#define SC2235_REG_AEC_PK_EXPOSURE_HI 0x3e01
-+#define SC2235_REG_AEC_PK_EXPOSURE_LO 0x3e02
-+#define SC2235_REG_AEC_PK_REAL_GAIN           0x3e08
-+#define SC2235_REG_TIMING_HTS                 0x320c
-+#define SC2235_REG_TIMING_VTS                 0x320e
-+#define SC2235_REG_TEST_SET0                  0x4501
-+#define SC2235_REG_TEST_SET1                  0x3902
-+#define SC2235_REG_TIMING_TC_REG21            0x3221
-+#define SC2235_REG_SC_PLL_CTRL0                       0x3039
-+#define SC2235_REG_SC_PLL_CTRL1                       0x303a
-+#define SC2235_REG_STREAM_ON            0x0100
-+
-+enum sc2235_mode_id {
-+      SC2235_MODE_1080P_1920_1080 = 0,
-+      SC2235_NUM_MODES,
-+};
-+
-+enum sc2235_frame_rate {
-+      SC2235_15_FPS = 0,
-+      SC2235_30_FPS,
-+      SC2235_NUM_FRAMERATES,
-+};
-+
-+struct sc2235_pixfmt {
-+      u32 code;
-+      u32 colorspace;
-+};
-+
-+static const struct sc2235_pixfmt sc2235_formats[] = {
-+      { MEDIA_BUS_FMT_SBGGR10_1X10, V4L2_COLORSPACE_SRGB, },
-+};
-+
-+static const int sc2235_framerates[] = {
-+      [SC2235_15_FPS] = 15,
-+      [SC2235_30_FPS] = 30,
-+};
-+
-+/* regulator supplies */
-+static const char * const sc2235_supply_name[] = {
-+      "DOVDD", /* Digital I/O (1.8V) supply */
-+      "AVDD",  /* Analog (2.8V) supply */
-+      "DVDD",  /* Digital Core (1.5V) supply */
-+};
-+
-+#define SC2235_NUM_SUPPLIES ARRAY_SIZE(sc2235_supply_name)
-+
-+struct reg_value {
-+      u16 reg_addr;
-+      u8 val;
-+      u8 mask;
-+      u32 delay_ms;
-+};
-+
-+struct sc2235_mode_info {
-+      enum sc2235_mode_id id;
-+      u32 hact;
-+      u32 htot;
-+      u32 vact;
-+      u32 vtot;
-+      const struct reg_value *reg_data;
-+      u32 reg_data_size;
-+      u32 max_fps;
-+};
-+
-+struct sc2235_ctrls {
-+      struct v4l2_ctrl_handler handler;
-+      struct v4l2_ctrl *pixel_rate;
-+      struct {
-+              struct v4l2_ctrl *auto_exp;
-+              struct v4l2_ctrl *exposure;
-+      };
-+      struct {
-+              struct v4l2_ctrl *auto_wb;
-+              struct v4l2_ctrl *blue_balance;
-+              struct v4l2_ctrl *red_balance;
-+      };
-+      struct {
-+              struct v4l2_ctrl *auto_gain;
-+              struct v4l2_ctrl *gain;
-+      };
-+      struct v4l2_ctrl *brightness;
-+      struct v4l2_ctrl *light_freq;
-+      struct v4l2_ctrl *saturation;
-+      struct v4l2_ctrl *contrast;
-+      struct v4l2_ctrl *hue;
-+      struct v4l2_ctrl *test_pattern;
-+      struct v4l2_ctrl *hflip;
-+      struct v4l2_ctrl *vflip;
-+};
-+
-+struct sc2235_dev {
-+      struct i2c_client *i2c_client;
-+      struct v4l2_subdev sd;
-+      struct media_pad pad;
-+      struct v4l2_fwnode_endpoint ep; /* the parsed DT endpoint info */
-+      struct clk *xclk; /* system clock to SC2235 */
-+      u32 xclk_freq;
-+
-+      struct regulator_bulk_data supplies[SC2235_NUM_SUPPLIES];
-+      struct gpio_desc *reset_gpio;
-+      struct gpio_desc *pwdn_gpio;
-+      bool   upside_down;
-+
-+      /* lock to protect all members below */
-+      struct mutex lock;
-+
-+      struct v4l2_mbus_framefmt fmt;
-+      bool pending_fmt_change;
-+
-+      const struct sc2235_mode_info *current_mode;
-+      const struct sc2235_mode_info *last_mode;
-+      enum sc2235_frame_rate current_fr;
-+      struct v4l2_fract frame_interval;
-+
-+      struct sc2235_ctrls ctrls;
-+
-+      bool pending_mode_change;
-+      int streaming;
-+};
-+
-+static inline struct sc2235_dev *to_sc2235_dev(struct v4l2_subdev *sd)
-+{
-+      return container_of(sd, struct sc2235_dev, sd);
-+}
-+
-+static inline struct v4l2_subdev *ctrl_to_sd(struct v4l2_ctrl *ctrl)
-+{
-+      return &container_of(ctrl->handler, struct sc2235_dev,
-+                              ctrls.handler)->sd;
-+}
-+
-+/* sc2235 initial register 30fps*/
-+static struct reg_value sc2235_init_regs_tbl_1080[] = {
-+      {0x0103, 0x01, 0, 50},
-+      {0x0100, 0x00, 0, 0},
-+      {0x3039, 0x80, 0, 0},
-+      {0x3621, 0x28, 0, 0},
-+
-+      {0x3309, 0x60, 0, 0},
-+      {0x331f, 0x4d, 0, 0},
-+      {0x3321, 0x4f, 0, 0},
-+      {0x33b5, 0x10, 0, 0},
-+
-+      {0x3303, 0x20, 0, 0},
-+      {0x331e, 0x0d, 0, 0},
-+      {0x3320, 0x0f, 0, 0},
-+
-+      {0x3622, 0x02, 0, 0},
-+      {0x3633, 0x42, 0, 0},
-+      {0x3634, 0x42, 0, 0},
-+
-+      {0x3306, 0x66, 0, 0},
-+      {0x330b, 0xd1, 0, 0},
-+
-+      {0x3301, 0x0e, 0, 0},
-+
-+      {0x320c, 0x08, 0, 0},
-+      {0x320d, 0x98, 0, 0},
-+
-+      {0x3364, 0x05, 0, 0},           // [2] 1: write at sampling ending
-+
-+      {0x363c, 0x28, 0, 0},           //bypass nvdd
-+      {0x363b, 0x0a, 0, 0},           //HVDD
-+      {0x3635, 0xa0, 0, 0},           //TXVDD
-+
-+      {0x4500, 0x59, 0, 0},
-+      {0x3d08, 0x00, 0, 0},
-+      {0x3908, 0x11, 0, 0},
-+
-+      {0x363c, 0x08, 0, 0},
-+
-+      {0x3e03, 0x03, 0, 0},
-+      {0x3e01, 0x46, 0, 0},
-+
-+      //0703
-+      {0x3381, 0x0a, 0, 0},
-+      {0x3348, 0x09, 0, 0},
-+      {0x3349, 0x50, 0, 0},
-+      {0x334a, 0x02, 0, 0},
-+      {0x334b, 0x60, 0, 0},
-+
-+      {0x3380, 0x04, 0, 0},
-+      {0x3340, 0x06, 0, 0},
-+      {0x3341, 0x50, 0, 0},
-+      {0x3342, 0x02, 0, 0},
-+      {0x3343, 0x60, 0, 0},
-+
-+      //0707
-+
-+      {0x3632, 0x88, 0, 0},           //anti sm
-+      {0x3309, 0xa0, 0, 0},
-+      {0x331f, 0x8d, 0, 0},
-+      {0x3321, 0x8f, 0, 0},
-+
-+      {0x335e, 0x01, 0, 0},           //ana dithering
-+      {0x335f, 0x03, 0, 0},
-+      {0x337c, 0x04, 0, 0},
-+      {0x337d, 0x06, 0, 0},
-+      {0x33a0, 0x05, 0, 0},
-+      {0x3301, 0x05, 0, 0},
-+
-+      {0x337f, 0x03, 0, 0},
-+      {0x3368, 0x02, 0, 0},
-+      {0x3369, 0x00, 0, 0},
-+      {0x336a, 0x00, 0, 0},
-+      {0x336b, 0x00, 0, 0},
-+      {0x3367, 0x08, 0, 0},
-+      {0x330e, 0x30, 0, 0},
-+
-+      {0x3366, 0x7c, 0, 0},           // div_rst gap
-+
-+      {0x3635, 0xc1, 0, 0},
-+      {0x363b, 0x09, 0, 0},
-+      {0x363c, 0x07, 0, 0},
-+
-+      {0x391e, 0x00, 0, 0},
-+
-+      {0x3637, 0x14, 0, 0},           //fullwell 7K
-+
-+      {0x3306, 0x54, 0, 0},
-+      {0x330b, 0xd8, 0, 0},
-+      {0x366e, 0x08, 0, 0},           // ofs auto en [3]
-+      {0x366f, 0x2f, 0, 0},
-+
-+      {0x3631, 0x84, 0, 0},
-+      {0x3630, 0x48, 0, 0},
-+      {0x3622, 0x06, 0, 0},
-+
-+      //ramp by sc
-+      {0x3638, 0x1f, 0, 0},
-+      {0x3625, 0x02, 0, 0},
-+      {0x3636, 0x24, 0, 0},
-+
-+      //0714
-+      {0x3348, 0x08, 0, 0},
-+      {0x3e03, 0x0b, 0, 0},
-+
-+      //7.17 fpn
-+      {0x3342, 0x03, 0, 0},
-+      {0x3343, 0xa0, 0, 0},
-+      {0x334a, 0x03, 0, 0},
-+      {0x334b, 0xa0, 0, 0},
-+
-+      //0718
-+      {0x3343, 0xb0, 0, 0},
-+      {0x334b, 0xb0, 0, 0},
-+
-+      //0720
-+      //digital ctrl
-+      {0x3802, 0x01, 0, 0},
-+      {0x3235, 0x04, 0, 0},
-+      {0x3236, 0x63, 0, 0},           // vts-2
-+
-+      //fpn
-+      {0x3343, 0xd0, 0, 0},
-+      {0x334b, 0xd0, 0, 0},
-+      {0x3348, 0x07, 0, 0},
-+      {0x3349, 0x80, 0, 0},
-+
-+      //0724
-+      {0x391b, 0x4d, 0, 0},
-+
-+      {0x3342, 0x04, 0, 0},
-+      {0x3343, 0x20, 0, 0},
-+      {0x334a, 0x04, 0, 0},
-+      {0x334b, 0x20, 0, 0},
-+
-+      //0804
-+      {0x3222, 0x29, 0, 0},
-+      {0x3901, 0x02, 0, 0},
-+
-+      //0808
-+
-+      // auto blc
-+      {0x3900, 0xD5, 0, 0},           // Bit[0]: blc_enable
-+      {0x3902, 0x45, 0, 0},           // Bit[6]: blc_auto_en
-+
-+      // blc target
-+      {0x3907, 0x00, 0, 0},
-+      {0x3908, 0x00, 0, 0},
-+
-+      // auto dpc
-+      {0x5000, 0x00, 0, 0},           // Bit[2]: white dead pixel cancel enable, Bit[1]: black dead pixel cancel enable
-+
-+      //digital ctrl
-+      {0x3f00, 0x07, 0, 0},           // bit[2] = 1
-+      {0x3f04, 0x08, 0, 0},
-+      {0x3f05, 0x74, 0, 0},           // hts - { 0x24
-+
-+      //0809
-+      {0x330b, 0xc8, 0, 0},
-+
-+      //0817
-+      {0x3306, 0x4a, 0, 0},
-+      {0x330b, 0xca, 0, 0},
-+      {0x3639, 0x09, 0, 0},
-+
-+      //manual DPC
-+      {0x5780, 0xff, 0, 0},
-+      {0x5781, 0x04, 0, 0},
-+      {0x5785, 0x18, 0, 0},
-+
-+      //0822
-+      {0x3039, 0x35, 0, 0},           //fps
-+      {0x303a, 0x2e, 0, 0},
-+      {0x3034, 0x05, 0, 0},
-+      {0x3035, 0x2a, 0, 0},
-+
-+      {0x320c, 0x08, 0, 0},
-+      {0x320d, 0xca, 0, 0},
-+      {0x320e, 0x04, 0, 0},
-+      {0x320f, 0xb0, 0, 0},
-+
-+      {0x3f04, 0x08, 0, 0},
-+      {0x3f05, 0xa6, 0, 0},           // hts - { 0x24
-+
-+      {0x3235, 0x04, 0, 0},
-+      {0x3236, 0xae, 0, 0},           // vts-2
-+
-+      //0825
-+      {0x3313, 0x05, 0, 0},
-+      {0x3678, 0x42, 0, 0},
-+
-+      //for AE control per frame
-+      {0x3670, 0x00, 0, 0},
-+      {0x3633, 0x42, 0, 0},
-+
-+      {0x3802, 0x00, 0, 0},
-+
-+      //20180126
-+      {0x3677, 0x3f, 0, 0},
-+      {0x3306, 0x44, 0, 0},           //20180126[3c },4a]
-+      {0x330b, 0xca, 0, 0},           //20180126[c2 },d3]
-+
-+      //20180202
-+      {0x3237, 0x08, 0, 0},
-+      {0x3238, 0x9a, 0, 0},           //hts-0x30
-+
-+      //20180417
-+      {0x3640, 0x01, 0, 0},
-+      {0x3641, 0x02, 0, 0},
-+
-+      {0x3301, 0x12, 0, 0},           //[8 },15]20180126
-+      {0x3631, 0x84, 0, 0},
-+      {0x366f, 0x2f, 0, 0},
-+      {0x3622, 0xc6, 0, 0},           //20180117
-+
-+      {0x3e03, 0x03, 0, 0},           // Bit[3]: AGC table mapping method, Bit[1]: AGC manual, BIt[0]: AEC manual
-+
-+      // {0x0100, 0x00, 0, 0},
-+      // {0x4501, 0xc8, 0, 0},        //bar testing
-+      // {0x3902, 0x45, 0, 0},
-+};
-+
-+static struct reg_value sc2235_setting_1080P_1920_1080[] = {
-+
-+};
-+
-+/* power-on sensor init reg table */
-+static const struct sc2235_mode_info sc2235_mode_init_data = {
-+      SC2235_MODE_1080P_1920_1080,
-+      1920, 0x8ca, 1080, 0x4b0,
-+      sc2235_init_regs_tbl_1080,
-+      ARRAY_SIZE(sc2235_init_regs_tbl_1080),
-+      SC2235_30_FPS,
-+};
-+
-+static const struct sc2235_mode_info
-+sc2235_mode_data[SC2235_NUM_MODES] = {
-+      {SC2235_MODE_1080P_1920_1080,
-+       1920, 0x8ca, 1080, 0x4b0,
-+       sc2235_setting_1080P_1920_1080,
-+       ARRAY_SIZE(sc2235_setting_1080P_1920_1080),
-+       SC2235_30_FPS},
-+};
-+
-+static int sc2235_write_reg(struct sc2235_dev *sensor, u16 reg, u8 val)
-+{
-+      struct i2c_client *client = sensor->i2c_client;
-+      struct i2c_msg msg;
-+      u8 buf[3];
-+      int ret;
-+
-+      buf[0] = reg >> 8;
-+      buf[1] = reg & 0xff;
-+      buf[2] = val;
-+
-+      msg.addr = client->addr;
-+      msg.flags = client->flags;
-+      msg.buf = buf;
-+      msg.len = sizeof(buf);
-+
-+      ret = i2c_transfer(client->adapter, &msg, 1);
-+      if (ret < 0) {
-+              dev_err(&client->dev, "%s: error: reg=%x, val=%x\n",
-+                      __func__, reg, val);
-+              return ret;
-+      }
-+
-+      return 0;
-+}
-+
-+static int sc2235_read_reg(struct sc2235_dev *sensor, u16 reg, u8 *val)
-+{
-+      struct i2c_client *client = sensor->i2c_client;
-+      struct i2c_msg msg[2];
-+      u8 buf[2];
-+      int ret;
-+
-+      buf[0] = reg >> 8;
-+      buf[1] = reg & 0xff;
-+
-+      msg[0].addr = client->addr;
-+      msg[0].flags = client->flags;
-+      msg[0].buf = buf;
-+      msg[0].len = sizeof(buf);
-+
-+      msg[1].addr = client->addr;
-+      msg[1].flags = client->flags | I2C_M_RD;
-+      msg[1].buf = buf;
-+      msg[1].len = 1;
-+
-+      ret = i2c_transfer(client->adapter, msg, 2);
-+      if (ret < 0) {
-+              dev_err(&client->dev, "%s: error: reg=%x\n",
-+                      __func__, reg);
-+              return ret;
-+      }
-+
-+      *val = buf[0];
-+      return 0;
-+}
-+
-+static int sc2235_read_reg16(struct sc2235_dev *sensor, u16 reg, u16 *val)
-+{
-+      u8 hi, lo;
-+      int ret;
-+
-+      ret = sc2235_read_reg(sensor, reg, &hi);
-+      if (ret)
-+              return ret;
-+      ret = sc2235_read_reg(sensor, reg + 1, &lo);
-+      if (ret)
-+              return ret;
-+
-+      *val = ((u16)hi << 8) | (u16)lo;
-+      return 0;
-+}
-+
-+static int sc2235_write_reg16(struct sc2235_dev *sensor, u16 reg, u16 val)
-+{
-+      int ret;
-+
-+      ret = sc2235_write_reg(sensor, reg, val >> 8);
-+      if (ret)
-+              return ret;
-+
-+      return sc2235_write_reg(sensor, reg + 1, val & 0xff);
-+}
-+
-+static int sc2235_mod_reg(struct sc2235_dev *sensor, u16 reg,
-+                      u8 mask, u8 val)
-+{
-+      u8 readval;
-+      int ret;
-+
-+      ret = sc2235_read_reg(sensor, reg, &readval);
-+      if (ret)
-+              return ret;
-+
-+      readval &= ~mask;
-+      val &= mask;
-+      val |= readval;
-+
-+      return sc2235_write_reg(sensor, reg, val);
-+}
-+
-+#define SC2235_PLL_PREDIV     3
-+
-+#define SC2235_SYSDIV_MIN     0
-+#define SC2235_SYSDIV_MAX     7
-+
-+#define SC2235_PLL_MULT_MIN   0
-+#define SC2235_PLL_MULT_MAX   63
-+
-+#ifdef UNUSED_CODE
-+static unsigned long sc2235_compute_sys_clk(struct sc2235_dev *sensor,
-+                                      u8 pll_pre, u8 pll_mult,
-+                                      u8 sysdiv)
-+{
-+      unsigned long sysclk =
-+              sensor->xclk_freq * (64 - pll_mult) / (pll_pre * (sysdiv + 1));
-+
-+      /* PLL1 output cannot exceed 1GHz. */
-+      if (sysclk / 1000000 > 1000)
-+              return 0;
-+
-+      return sysclk;
-+}
-+
-+static unsigned long sc2235_calc_sys_clk(struct sc2235_dev *sensor,
-+                                      unsigned long rate,
-+                                      u8 *pll_prediv, u8 *pll_mult,
-+                                      u8 *sysdiv)
-+{
-+      unsigned long best = ~0;
-+      u8 best_sysdiv = 1, best_mult = 1;
-+      u8 _sysdiv, _pll_mult;
-+
-+      for (_sysdiv = SC2235_SYSDIV_MIN;
-+              _sysdiv <= SC2235_SYSDIV_MAX;
-+              _sysdiv++) {
-+              for (_pll_mult = SC2235_PLL_MULT_MIN;
-+                      _pll_mult <= SC2235_PLL_MULT_MAX;
-+                      _pll_mult++) {
-+                      unsigned long _rate;
-+
-+                      _rate = sc2235_compute_sys_clk(sensor,
-+                                                      SC2235_PLL_PREDIV,
-+                                                      _pll_mult, _sysdiv);
-+
-+                      /*
-+                       * We have reached the maximum allowed PLL1 output,
-+                       * increase sysdiv.
-+                       */
-+                      if (!_rate)
-+                              break;
-+
-+                      /*
-+                       * Prefer rates above the expected clock rate than
-+                       * below, even if that means being less precise.
-+                       */
-+                      if (_rate < rate)
-+                              continue;
-+
-+                      if (abs(rate - _rate) < abs(rate - best)) {
-+                              best = _rate;
-+                              best_sysdiv = _sysdiv;
-+                              best_mult = _pll_mult;
-+                      }
-+
-+                      if (_rate == rate)
-+                              goto out;
-+              }
-+      }
-+
-+out:
-+      *sysdiv = best_sysdiv;
-+      *pll_prediv = SC2235_PLL_PREDIV;
-+      *pll_mult = best_mult;
-+
-+      return best;
-+}
-+#endif
-+
-+static int sc2235_set_timings(struct sc2235_dev *sensor,
-+                              const struct sc2235_mode_info *mode)
-+{
-+      int ret = 0;
-+
-+      return ret;
-+}
-+
-+static int sc2235_load_regs(struct sc2235_dev *sensor,
-+                              const struct sc2235_mode_info *mode)
-+{
-+      const struct reg_value *regs = mode->reg_data;
-+      unsigned int i;
-+      u32 delay_ms;
-+      u16 reg_addr;
-+      u8 mask, val;
-+      int ret = 0;
-+
-+      for (i = 0; i < mode->reg_data_size; ++i, ++regs) {
-+              delay_ms = regs->delay_ms;
-+              reg_addr = regs->reg_addr;
-+              val = regs->val;
-+              mask = regs->mask;
-+
-+              if (mask)
-+                      ret = sc2235_mod_reg(sensor, reg_addr, mask, val);
-+              else
-+                      ret = sc2235_write_reg(sensor, reg_addr, val);
-+              if (ret)
-+                      break;
-+
-+              if (delay_ms)
-+                      usleep_range(1000 * delay_ms, 1000 * delay_ms + 100);
-+      }
-+
-+      return sc2235_set_timings(sensor, mode);
-+}
-+
-+static int sc2235_set_autoexposure(struct sc2235_dev *sensor, bool on)
-+{
-+      return sc2235_mod_reg(sensor, SC2235_REG_AEC_PK_MANUAL,
-+                              BIT(0), on ? 0 : BIT(0));
-+}
-+
-+static int sc2235_get_exposure(struct sc2235_dev *sensor)
-+{
-+      int exp = 0, ret = 0;
-+      u8 temp;
-+
-+      ret = sc2235_read_reg(sensor, SC2235_REG_AEC_PK_EXPOSURE_HI, &temp);
-+      if (ret)
-+              return ret;
-+      exp |= (int)temp << 8;
-+      ret = sc2235_read_reg(sensor, SC2235_REG_AEC_PK_EXPOSURE_LO, &temp);
-+      if (ret)
-+              return ret;
-+      exp |= (int)temp;
-+
-+      return exp >> 4;
-+}
-+
-+static int sc2235_set_exposure(struct sc2235_dev *sensor, u32 exposure)
-+{
-+      int ret;
-+
-+      exposure <<= 4;
-+
-+      ret = sc2235_write_reg(sensor,
-+                              SC2235_REG_AEC_PK_EXPOSURE_LO,
-+                              exposure & 0xff);
-+      if (ret)
-+              return ret;
-+      return sc2235_write_reg(sensor,
-+                              SC2235_REG_AEC_PK_EXPOSURE_HI,
-+                              (exposure >> 8) & 0xff);
-+}
-+
-+static int sc2235_get_gain(struct sc2235_dev *sensor)
-+{
-+      u16 gain;
-+      int ret;
-+
-+      ret = sc2235_read_reg16(sensor, SC2235_REG_AEC_PK_REAL_GAIN, &gain);
-+      if (ret)
-+              return ret;
-+
-+      return gain & 0x1fff;
-+}
-+
-+static int sc2235_set_gain(struct sc2235_dev *sensor, int gain)
-+{
-+      return sc2235_write_reg16(sensor, SC2235_REG_AEC_PK_REAL_GAIN,
-+                                      (u16)gain & 0x1fff);
-+}
-+
-+static int sc2235_set_autogain(struct sc2235_dev *sensor, bool on)
-+{
-+      return sc2235_mod_reg(sensor, SC2235_REG_AEC_PK_MANUAL,
-+                              BIT(1), on ? 0 : BIT(1));
-+}
-+
-+#ifdef UNUSED_CODE
-+static int sc2235_get_sysclk(struct sc2235_dev *sensor)
-+{
-+      return 0;
-+}
-+
-+static int sc2235_set_night_mode(struct sc2235_dev *sensor)
-+{
-+      return 0;
-+}
-+
-+static int sc2235_get_hts(struct sc2235_dev *sensor)
-+{
-+      u16 hts;
-+      int ret;
-+
-+      ret = sc2235_read_reg16(sensor, SC2235_REG_TIMING_HTS, &hts);
-+      if (ret)
-+              return ret;
-+      return hts;
-+}
-+#endif
-+
-+static int sc2235_get_vts(struct sc2235_dev *sensor)
-+{
-+      u16 vts;
-+      int ret;
-+
-+      ret = sc2235_read_reg16(sensor, SC2235_REG_TIMING_VTS, &vts);
-+      if (ret)
-+              return ret;
-+      return vts;
-+}
-+
-+#ifdef UNUSED_CODE
-+static int sc2235_set_vts(struct sc2235_dev *sensor, int vts)
-+{
-+      return sc2235_write_reg16(sensor, SC2235_REG_TIMING_VTS, vts);
-+}
-+
-+static int sc2235_get_light_freq(struct sc2235_dev *sensor)
-+{
-+      return 0;
-+}
-+
-+static int sc2235_set_bandingfilter(struct sc2235_dev *sensor)
-+{
-+      return 0;
-+}
-+
-+static int sc2235_set_ae_target(struct sc2235_dev *sensor, int target)
-+{
-+      return 0;
-+}
-+
-+static int sc2235_get_binning(struct sc2235_dev *sensor)
-+{
-+      return 0;
-+}
-+
-+static int sc2235_set_binning(struct sc2235_dev *sensor, bool enable)
-+{
-+      return 0;
-+}
-+
-+#endif
-+
-+static const struct sc2235_mode_info *
-+sc2235_find_mode(struct sc2235_dev *sensor, enum sc2235_frame_rate fr,
-+               int width, int height, bool nearest)
-+{
-+      const struct sc2235_mode_info *mode;
-+
-+      mode = v4l2_find_nearest_size(sc2235_mode_data,
-+                                      ARRAY_SIZE(sc2235_mode_data),
-+                                      hact, vact,
-+                                      width, height);
-+
-+      if (!mode ||
-+              (!nearest && (mode->hact != width || mode->vact != height)))
-+              return NULL;
-+
-+      /* Check to see if the current mode exceeds the max frame rate */
-+      if (sc2235_framerates[fr] > sc2235_framerates[mode->max_fps])
-+              return NULL;
-+
-+      return mode;
-+}
-+
-+static u64 sc2235_calc_pixel_rate(struct sc2235_dev *sensor)
-+{
-+      u64 rate;
-+
-+      rate = sensor->current_mode->vtot * sensor->current_mode->htot;
-+      rate *= sc2235_framerates[sensor->current_fr];
-+
-+      return rate;
-+}
-+
-+#ifdef UNUSED_CODE
-+/*
-+ * sc2235_set_dvp_pclk() - Calculate the clock tree configuration values
-+ *                            for the dvp output.
-+ *
-+ * @rate: The requested bandwidth per lane in bytes per second.
-+ *    'Bandwidth Per Lane' is calculated as:
-+ *    rate = HTOT * VTOT * FPS;
-+ *
-+ * This function use the requested bandwidth to calculate:
-+ * - rate = xclk * (64 - M) / (N * (S + 1));
-+ *
-+ */
-+
-+#define PLL_PREDIV  1
-+#define PLL_SYSEL   0
-+
-+static int sc2235_set_dvp_pclk(struct sc2235_dev *sensor,
-+                              unsigned long rate)
-+{
-+      u8 prediv, mult, sysdiv;
-+      int ret = 0;
-+
-+      sc2235_calc_sys_clk(sensor, rate, &prediv, &mult,
-+                              &sysdiv);
-+
-+
-+      return ret;
-+}
-+
-+/*
-+ * if sensor changes inside scaling or subsampling
-+ * change mode directly
-+ */
-+static int sc2235_set_mode_direct(struct sc2235_dev *sensor,
-+                              const struct sc2235_mode_info *mode)
-+{
-+      if (!mode->reg_data)
-+              return -EINVAL;
-+
-+      /* Write capture setting */
-+      return sc2235_load_regs(sensor, mode);
-+}
-+#endif
-+
-+static int sc2235_set_mode(struct sc2235_dev *sensor)
-+{
-+#ifdef UNUSED_CODE
-+      bool auto_exp =  sensor->ctrls.auto_exp->val == V4L2_EXPOSURE_AUTO;
-+      const struct sc2235_mode_info *mode = sensor->current_mode;
-+#endif
-+      bool auto_gain = sensor->ctrls.auto_gain->val == 1;
-+      int ret = 0;
-+
-+      /* auto gain and exposure must be turned off when changing modes */
-+      if (auto_gain) {
-+              ret = sc2235_set_autogain(sensor, false);
-+              if (ret)
-+                      return ret;
-+      }
-+#ifdef UNUSED_CODE
-+      /* This issue will be addressed in the EVB board*/
-+      /* This action will result in poor image display 2021 1111*/
-+      if (auto_exp) {
-+              ret = sc2235_set_autoexposure(sensor, false);
-+              if (ret)
-+                      goto restore_auto_gain;
-+      }
-+
-+      rate = sc2235_calc_pixel_rate(sensor);
-+
-+      ret = sc2235_set_dvp_pclk(sensor, rate);
-+      if (ret < 0)
-+              return 0;
-+
-+      ret = sc2235_set_mode_direct(sensor, mode);
-+      if (ret < 0)
-+              goto restore_auto_exp_gain;
-+
-+      /* restore auto gain and exposure */
-+      if (auto_gain)
-+              sc2235_set_autogain(sensor, true);
-+      if (auto_exp)
-+              sc2235_set_autoexposure(sensor, true);
-+
-+
-+      sensor->pending_mode_change = false;
-+      sensor->last_mode = mode;
-+      return 0;
-+
-+restore_auto_exp_gain:
-+      if (auto_exp)
-+              sc2235_set_autoexposure(sensor, true);
-+restore_auto_gain:
-+      if (auto_gain)
-+              sc2235_set_autogain(sensor, true);
-+#endif
-+      return ret;
-+}
-+
-+static int sc2235_set_framefmt(struct sc2235_dev *sensor,
-+                              struct v4l2_mbus_framefmt *format);
-+
-+/* restore the last set video mode after chip power-on */
-+static int sc2235_restore_mode(struct sc2235_dev *sensor)
-+{
-+      int ret;
-+
-+      /* first load the initial register values */
-+      ret = sc2235_load_regs(sensor, &sc2235_mode_init_data);
-+      if (ret < 0)
-+              return ret;
-+      sensor->last_mode = &sc2235_mode_init_data;
-+      /* now restore the last capture mode */
-+      ret = sc2235_set_mode(sensor);
-+      if (ret < 0)
-+              return ret;
-+
-+      return sc2235_set_framefmt(sensor, &sensor->fmt);
-+}
-+
-+static void sc2235_power(struct sc2235_dev *sensor, bool enable)
-+{
-+      if (!sensor->pwdn_gpio)
-+              return;
-+      gpiod_set_value_cansleep(sensor->pwdn_gpio, enable ? 0 : 1);
-+}
-+
-+static void sc2235_reset(struct sc2235_dev *sensor)
-+{
-+      if (!sensor->reset_gpio)
-+              return;
-+
-+      gpiod_set_value_cansleep(sensor->reset_gpio, 0);
-+
-+      /* camera power cycle */
-+      sc2235_power(sensor, false);
-+      usleep_range(5000, 10000);
-+      sc2235_power(sensor, true);
-+      usleep_range(5000, 10000);
-+
-+      gpiod_set_value_cansleep(sensor->reset_gpio, 1);
-+      usleep_range(1000, 2000);
-+
-+      gpiod_set_value_cansleep(sensor->reset_gpio, 0);
-+      usleep_range(20000, 25000);
-+}
-+
-+static int sc2235_set_power_on(struct device *dev)
-+{
-+      struct i2c_client *client = to_i2c_client(dev);
-+      struct v4l2_subdev *sd = i2c_get_clientdata(client);
-+      struct sc2235_dev *sensor = to_sc2235_dev(sd);
-+      int ret;
-+
-+      ret = clk_prepare_enable(sensor->xclk);
-+      if (ret) {
-+              dev_err(&client->dev, "%s: failed to enable clock\n",
-+                      __func__);
-+              return ret;
-+      }
-+
-+      ret = regulator_bulk_enable(SC2235_NUM_SUPPLIES,
-+                                      sensor->supplies);
-+      if (ret) {
-+              dev_err(&client->dev, "%s: failed to enable regulators\n",
-+                      __func__);
-+              goto xclk_off;
-+      }
-+
-+      sc2235_reset(sensor);
-+      sc2235_power(sensor, true);
-+
-+      return 0;
-+
-+xclk_off:
-+      clk_disable_unprepare(sensor->xclk);
-+      return ret;
-+}
-+
-+static int sc2235_set_power_off(struct device *dev)
-+{
-+      struct i2c_client *client = to_i2c_client(dev);
-+      struct v4l2_subdev *sd = i2c_get_clientdata(client);
-+      struct sc2235_dev *sensor = to_sc2235_dev(sd);
-+
-+      sc2235_power(sensor, false);
-+      regulator_bulk_disable(SC2235_NUM_SUPPLIES, sensor->supplies);
-+      clk_disable_unprepare(sensor->xclk);
-+
-+      return 0;
-+}
-+
-+static int sc2235_set_power(struct sc2235_dev *sensor, bool on)
-+{
-+      int ret = 0;
-+
-+      if (on) {
-+              pm_runtime_get_sync(&sensor->i2c_client->dev);
-+
-+              ret = sc2235_restore_mode(sensor);
-+              if (ret)
-+                      goto power_off;
-+      }
-+
-+      if (!on)
-+              pm_runtime_put_sync(&sensor->i2c_client->dev);
-+
-+      return 0;
-+
-+power_off:
-+      pm_runtime_put_sync(&sensor->i2c_client->dev);
-+
-+      return ret;
-+}
-+
-+static int sc2235_s_power(struct v4l2_subdev *sd, int on)
-+{
-+      struct sc2235_dev *sensor = to_sc2235_dev(sd);
-+      int ret = 0;
-+
-+      mutex_lock(&sensor->lock);
-+
-+      ret = sc2235_set_power(sensor, !!on);
-+      if (ret)
-+              goto out;
-+
-+      mutex_unlock(&sensor->lock);
-+      return 0;
-+
-+out:
-+      mutex_unlock(&sensor->lock);
-+      return ret;
-+}
-+
-+static int sc2235_try_frame_interval(struct sc2235_dev *sensor,
-+                              struct v4l2_fract *fi,
-+                              u32 width, u32 height)
-+{
-+      const struct sc2235_mode_info *mode;
-+      enum sc2235_frame_rate rate = SC2235_15_FPS;
-+      int minfps, maxfps, best_fps, fps;
-+      int i;
-+
-+      minfps = sc2235_framerates[SC2235_15_FPS];
-+      maxfps = sc2235_framerates[SC2235_30_FPS];
-+
-+      if (fi->numerator == 0) {
-+              fi->denominator = maxfps;
-+              fi->numerator = 1;
-+              rate = SC2235_30_FPS;
-+              goto find_mode;
-+      }
-+
-+      fps = clamp_val(DIV_ROUND_CLOSEST(fi->denominator, fi->numerator),
-+                      minfps, maxfps);
-+
-+      best_fps = minfps;
-+      for (i = 0; i < ARRAY_SIZE(sc2235_framerates); i++) {
-+              int curr_fps = sc2235_framerates[i];
-+
-+              if (abs(curr_fps - fps) < abs(best_fps - fps)) {
-+                      best_fps = curr_fps;
-+                      rate = i;
-+              }
-+      }
-+
-+      fi->numerator = 1;
-+      fi->denominator = best_fps;
-+
-+find_mode:
-+      mode = sc2235_find_mode(sensor, rate, width, height, false);
-+      return mode ? rate : -EINVAL;
-+}
-+
-+static int sc2235_get_fmt(struct v4l2_subdev *sd,
-+                      struct v4l2_subdev_state *state,
-+                      struct v4l2_subdev_format *format)
-+{
-+      struct sc2235_dev *sensor = to_sc2235_dev(sd);
-+      struct v4l2_mbus_framefmt *fmt;
-+
-+      if (format->pad != 0)
-+              return -EINVAL;
-+
-+      mutex_lock(&sensor->lock);
-+
-+      if (format->which == V4L2_SUBDEV_FORMAT_TRY)
-+              fmt = v4l2_subdev_get_try_format(&sensor->sd, state,
-+                                              format->pad);
-+      else
-+              fmt = &sensor->fmt;
-+
-+      format->format = *fmt;
-+
-+      mutex_unlock(&sensor->lock);
-+
-+      return 0;
-+}
-+
-+static int sc2235_try_fmt_internal(struct v4l2_subdev *sd,
-+                              struct v4l2_mbus_framefmt *fmt,
-+                              enum sc2235_frame_rate fr,
-+                              const struct sc2235_mode_info **new_mode)
-+{
-+      struct sc2235_dev *sensor = to_sc2235_dev(sd);
-+      const struct sc2235_mode_info *mode;
-+      int i;
-+
-+      mode = sc2235_find_mode(sensor, fr, fmt->width, fmt->height, true);
-+      if (!mode)
-+              return -EINVAL;
-+      fmt->width = mode->hact;
-+      fmt->height = mode->vact;
-+
-+      if (new_mode)
-+              *new_mode = mode;
-+
-+      for (i = 0; i < ARRAY_SIZE(sc2235_formats); i++)
-+              if (sc2235_formats[i].code == fmt->code)
-+                      break;
-+      if (i >= ARRAY_SIZE(sc2235_formats))
-+              i = 0;
-+
-+      fmt->code = sc2235_formats[i].code;
-+      fmt->colorspace = sc2235_formats[i].colorspace;
-+      fmt->ycbcr_enc = V4L2_MAP_YCBCR_ENC_DEFAULT(fmt->colorspace);
-+      fmt->quantization = V4L2_QUANTIZATION_FULL_RANGE;
-+      fmt->xfer_func = V4L2_MAP_XFER_FUNC_DEFAULT(fmt->colorspace);
-+
-+      return 0;
-+}
-+
-+static int sc2235_set_fmt(struct v4l2_subdev *sd,
-+                      struct v4l2_subdev_state *state,
-+                      struct v4l2_subdev_format *format)
-+{
-+      struct sc2235_dev *sensor = to_sc2235_dev(sd);
-+      const struct sc2235_mode_info *new_mode;
-+      struct v4l2_mbus_framefmt *mbus_fmt = &format->format;
-+      struct v4l2_mbus_framefmt *fmt;
-+      int ret;
-+
-+      if (format->pad != 0)
-+              return -EINVAL;
-+      mutex_lock(&sensor->lock);
-+
-+      if (sensor->streaming) {
-+              ret = -EBUSY;
-+              goto out;
-+      }
-+
-+      ret = sc2235_try_fmt_internal(sd, mbus_fmt, 0, &new_mode);
-+      if (ret)
-+              goto out;
-+
-+      if (format->which == V4L2_SUBDEV_FORMAT_TRY)
-+              fmt = v4l2_subdev_get_try_format(sd, state, 0);
-+      else
-+              fmt = &sensor->fmt;
-+
-+      if (mbus_fmt->code != sensor->fmt.code)
-+              sensor->pending_fmt_change = true;
-+
-+      *fmt = *mbus_fmt;
-+
-+      if (new_mode != sensor->current_mode) {
-+              sensor->current_mode = new_mode;
-+              sensor->pending_mode_change = true;
-+      }
-+      if (new_mode->max_fps < sensor->current_fr) {
-+              sensor->current_fr = new_mode->max_fps;
-+              sensor->frame_interval.numerator = 1;
-+              sensor->frame_interval.denominator =
-+                      sc2235_framerates[sensor->current_fr];
-+              sensor->current_mode = new_mode;
-+              sensor->pending_mode_change = true;
-+      }
-+
-+      __v4l2_ctrl_s_ctrl_int64(sensor->ctrls.pixel_rate,
-+                              sc2235_calc_pixel_rate(sensor));
-+out:
-+      mutex_unlock(&sensor->lock);
-+      return ret;
-+}
-+
-+static int sc2235_set_framefmt(struct sc2235_dev *sensor,
-+                              struct v4l2_mbus_framefmt *format)
-+{
-+      int ret = 0;
-+
-+      switch (format->code) {
-+      default:
-+              return ret;
-+      }
-+      return ret;
-+}
-+
-+/*
-+ * Sensor Controls.
-+ */
-+
-+static int sc2235_set_ctrl_hue(struct sc2235_dev *sensor, int value)
-+{
-+      int ret = 0;
-+      return ret;
-+}
-+
-+static int sc2235_set_ctrl_contrast(struct sc2235_dev *sensor, int value)
-+{
-+      int ret = 0;
-+      return ret;
-+}
-+
-+static int sc2235_set_ctrl_saturation(struct sc2235_dev *sensor, int value)
-+{
-+      int ret  = 0;
-+      return ret;
-+}
-+
-+static int sc2235_set_ctrl_white_balance(struct sc2235_dev *sensor, int awb)
-+{
-+      int ret = 0;
-+      return ret;
-+}
-+
-+static int sc2235_set_ctrl_exposure(struct sc2235_dev *sensor,
-+                              enum v4l2_exposure_auto_type auto_exposure)
-+{
-+      struct sc2235_ctrls *ctrls = &sensor->ctrls;
-+      bool auto_exp = (auto_exposure == V4L2_EXPOSURE_AUTO);
-+      int ret = 0;
-+
-+      if (ctrls->auto_exp->is_new) {
-+              ret = sc2235_set_autoexposure(sensor, auto_exp);
-+              if (ret)
-+                      return ret;
-+      }
-+
-+      if (!auto_exp && ctrls->exposure->is_new) {
-+              u16 max_exp = 0;
-+
-+              ret = sc2235_get_vts(sensor);
-+              if (ret < 0)
-+                      return ret;
-+              max_exp += ret - 4;
-+              ret = 0;
-+
-+              if (ctrls->exposure->val < max_exp)
-+                      ret = sc2235_set_exposure(sensor, ctrls->exposure->val);
-+      }
-+
-+      return ret;
-+}
-+
-+static int sc2235_set_ctrl_gain(struct sc2235_dev *sensor, bool auto_gain)
-+{
-+      struct sc2235_ctrls *ctrls = &sensor->ctrls;
-+      int ret = 0;
-+
-+      if (ctrls->auto_gain->is_new) {
-+              ret = sc2235_set_autogain(sensor, auto_gain);
-+              if (ret)
-+                      return ret;
-+      }
-+
-+      if (!auto_gain && ctrls->gain->is_new)
-+              ret = sc2235_set_gain(sensor, ctrls->gain->val);
-+
-+      return ret;
-+}
-+
-+static const char * const test_pattern_menu[] = {
-+      "Disabled",
-+      "Black bars",
-+      "Auto Black bars",
-+};
-+
-+#define SC2235_TEST_ENABLE            BIT(3)
-+#define SC2235_TEST_BLACK             (3 << 0)
-+
-+static int sc2235_set_ctrl_test_pattern(struct sc2235_dev *sensor, int value)
-+{
-+      int ret = 0;
-+      /*
-+       *For 7110 platform, refer to 1125 FW code configuration. This operation will cause the image to be white.
-+       */
-+#ifdef UNUSED_CODE
-+      ret = sc2235_mod_reg(sensor, SC2235_REG_TEST_SET0, BIT(3),
-+                              !!value << 3);
-+
-+      ret |= sc2235_mod_reg(sensor, SC2235_REG_TEST_SET1, BIT(6),
-+                              (value >> 1) << 6);
-+#endif
-+      return ret;
-+}
-+
-+static int sc2235_set_ctrl_light_freq(struct sc2235_dev *sensor, int value)
-+{
-+      return 0;
-+}
-+
-+static int sc2235_set_ctrl_hflip(struct sc2235_dev *sensor, int value)
-+{
-+      return sc2235_mod_reg(sensor, SC2235_REG_TIMING_TC_REG21,
-+                              BIT(2) | BIT(1),
-+                              (!(value ^ sensor->upside_down)) ?
-+                              (BIT(2) | BIT(1)) : 0);
-+}
-+
-+static int sc2235_set_ctrl_vflip(struct sc2235_dev *sensor, int value)
-+{
-+      return sc2235_mod_reg(sensor, SC2235_REG_TIMING_TC_REG21,
-+                              BIT(6) | BIT(5),
-+                              (value ^ sensor->upside_down) ?
-+                              (BIT(6) | BIT(5)) : 0);
-+}
-+
-+static int sc2235_g_volatile_ctrl(struct v4l2_ctrl *ctrl)
-+{
-+      struct v4l2_subdev *sd = ctrl_to_sd(ctrl);
-+      struct sc2235_dev *sensor = to_sc2235_dev(sd);
-+      int val;
-+
-+      /* v4l2_ctrl_lock() locks our own mutex */
-+
-+      if (!pm_runtime_get_if_in_use(&sensor->i2c_client->dev))
-+              return 0;
-+
-+      switch (ctrl->id) {
-+      case V4L2_CID_AUTOGAIN:
-+              val = sc2235_get_gain(sensor);
-+              if (val < 0)
-+                      return val;
-+              sensor->ctrls.gain->val = val;
-+              break;
-+      case V4L2_CID_EXPOSURE_AUTO:
-+              val = sc2235_get_exposure(sensor);
-+              if (val < 0)
-+                      return val;
-+              sensor->ctrls.exposure->val = val;
-+              break;
-+      }
-+
-+      pm_runtime_put(&sensor->i2c_client->dev);
-+
-+      return 0;
-+}
-+
-+static int sc2235_s_ctrl(struct v4l2_ctrl *ctrl)
-+{
-+      struct v4l2_subdev *sd = ctrl_to_sd(ctrl);
-+      struct sc2235_dev *sensor = to_sc2235_dev(sd);
-+      int ret;
-+
-+      /* v4l2_ctrl_lock() locks our own mutex */
-+
-+      /*
-+       * If the device is not powered up by the host driver do
-+       * not apply any controls to H/W at this time. Instead
-+       * the controls will be restored at start streaming time.
-+       */
-+      if (!pm_runtime_get_if_in_use(&sensor->i2c_client->dev))
-+              return 0;
-+
-+      switch (ctrl->id) {
-+      case V4L2_CID_AUTOGAIN:
-+              ret = sc2235_set_ctrl_gain(sensor, ctrl->val);
-+              break;
-+      case V4L2_CID_EXPOSURE_AUTO:
-+              ret = sc2235_set_ctrl_exposure(sensor, ctrl->val);
-+              break;
-+      case V4L2_CID_AUTO_WHITE_BALANCE:
-+              ret = sc2235_set_ctrl_white_balance(sensor, ctrl->val);
-+              break;
-+      case V4L2_CID_HUE:
-+              ret = sc2235_set_ctrl_hue(sensor, ctrl->val);
-+              break;
-+      case V4L2_CID_CONTRAST:
-+              ret = sc2235_set_ctrl_contrast(sensor, ctrl->val);
-+              break;
-+      case V4L2_CID_SATURATION:
-+              ret = sc2235_set_ctrl_saturation(sensor, ctrl->val);
-+              break;
-+      case V4L2_CID_TEST_PATTERN:
-+              ret = sc2235_set_ctrl_test_pattern(sensor, ctrl->val);
-+              break;
-+      case V4L2_CID_POWER_LINE_FREQUENCY:
-+              ret = sc2235_set_ctrl_light_freq(sensor, ctrl->val);
-+              break;
-+      case V4L2_CID_HFLIP:
-+              ret = sc2235_set_ctrl_hflip(sensor, ctrl->val);
-+              break;
-+      case V4L2_CID_VFLIP:
-+              ret = sc2235_set_ctrl_vflip(sensor, ctrl->val);
-+              break;
-+      default:
-+              ret = -EINVAL;
-+              break;
-+      }
-+
-+      pm_runtime_put(&sensor->i2c_client->dev);
-+
-+      return ret;
-+}
-+
-+static const struct v4l2_ctrl_ops sc2235_ctrl_ops = {
-+      .g_volatile_ctrl = sc2235_g_volatile_ctrl,
-+      .s_ctrl = sc2235_s_ctrl,
-+};
-+
-+static int sc2235_init_controls(struct sc2235_dev *sensor)
-+{
-+      const struct v4l2_ctrl_ops *ops = &sc2235_ctrl_ops;
-+      struct sc2235_ctrls *ctrls = &sensor->ctrls;
-+      struct v4l2_ctrl_handler *hdl = &ctrls->handler;
-+      int ret;
-+
-+      v4l2_ctrl_handler_init(hdl, 32);
-+
-+      /* we can use our own mutex for the ctrl lock */
-+      hdl->lock = &sensor->lock;
-+
-+      /* Clock related controls */
-+      ctrls->pixel_rate = v4l2_ctrl_new_std(hdl, ops, V4L2_CID_PIXEL_RATE,
-+                                              0, INT_MAX, 1,
-+                                              sc2235_calc_pixel_rate(sensor));
-+
-+      /* Auto/manual white balance */
-+      ctrls->auto_wb = v4l2_ctrl_new_std(hdl, ops,
-+                                      V4L2_CID_AUTO_WHITE_BALANCE,
-+                                      0, 1, 1, 1);
-+      ctrls->blue_balance = v4l2_ctrl_new_std(hdl, ops, V4L2_CID_BLUE_BALANCE,
-+                                              0, 4095, 1, 0);
-+      ctrls->red_balance = v4l2_ctrl_new_std(hdl, ops, V4L2_CID_RED_BALANCE,
-+                                              0, 4095, 1, 0);
-+      /* Auto/manual exposure */
-+#ifdef UNUSED_CODE
-+      /*
-+       *For 7110 platform, This operation will cause the image to be white.
-+       */
-+      ctrls->auto_exp = v4l2_ctrl_new_std_menu(hdl, ops,
-+                                              V4L2_CID_EXPOSURE_AUTO,
-+                                              V4L2_EXPOSURE_MANUAL, 0,
-+                                              V4L2_EXPOSURE_AUTO);
-+      ctrls->exposure = v4l2_ctrl_new_std(hdl, ops, V4L2_CID_EXPOSURE,
-+                                      0, 65535, 1, 0);
-+      /* Auto/manual gain */
-+      ctrls->auto_gain = v4l2_ctrl_new_std(hdl, ops, V4L2_CID_AUTOGAIN,
-+                                              0, 1, 1, 1);
-+      ctrls->gain = v4l2_ctrl_new_std(hdl, ops, V4L2_CID_GAIN,
-+                                      0, 1023, 1, 0);
-+#else
-+      ctrls->auto_exp = v4l2_ctrl_new_std_menu(hdl, ops,
-+                                              V4L2_CID_EXPOSURE_AUTO,
-+                                              V4L2_EXPOSURE_MANUAL, 0,
-+                                              1);
-+      ctrls->exposure = v4l2_ctrl_new_std(hdl, ops, V4L2_CID_EXPOSURE,
-+                                      0, 65535, 1, 720);
-+      /* Auto/manual gain */
-+      ctrls->auto_gain = v4l2_ctrl_new_std(hdl, ops, V4L2_CID_AUTOGAIN,
-+                                              0, 1, 1, 0);
-+      ctrls->gain = v4l2_ctrl_new_std(hdl, ops, V4L2_CID_GAIN,
-+                                      0, 1023, 1, 0x10);
-+#endif
-+      ctrls->saturation = v4l2_ctrl_new_std(hdl, ops, V4L2_CID_SATURATION,
-+                                              0, 255, 1, 64);
-+      ctrls->hue = v4l2_ctrl_new_std(hdl, ops, V4L2_CID_HUE,
-+                                      0, 359, 1, 0);
-+      ctrls->contrast = v4l2_ctrl_new_std(hdl, ops, V4L2_CID_CONTRAST,
-+                                              0, 255, 1, 0);
-+      ctrls->test_pattern =
-+              v4l2_ctrl_new_std_menu_items(hdl, ops, V4L2_CID_TEST_PATTERN,
-+                                      ARRAY_SIZE(test_pattern_menu) - 1,
-+                                      0, 0, test_pattern_menu);   //0x02
-+      ctrls->hflip = v4l2_ctrl_new_std(hdl, ops, V4L2_CID_HFLIP,
-+                                      0, 1, 1, 1);
-+      ctrls->vflip = v4l2_ctrl_new_std(hdl, ops, V4L2_CID_VFLIP,
-+                                      0, 1, 1, 0);
-+
-+      ctrls->light_freq =
-+              v4l2_ctrl_new_std_menu(hdl, ops,
-+                                      V4L2_CID_POWER_LINE_FREQUENCY,
-+                                      V4L2_CID_POWER_LINE_FREQUENCY_AUTO, 0,
-+                                      V4L2_CID_POWER_LINE_FREQUENCY_50HZ);
-+
-+      if (hdl->error) {
-+              ret = hdl->error;
-+              goto free_ctrls;
-+      }
-+
-+      ctrls->pixel_rate->flags |= V4L2_CTRL_FLAG_READ_ONLY;
-+      ctrls->gain->flags |= V4L2_CTRL_FLAG_VOLATILE;
-+      ctrls->exposure->flags |= V4L2_CTRL_FLAG_VOLATILE;
-+
-+      v4l2_ctrl_auto_cluster(3, &ctrls->auto_wb, 0, false);
-+      v4l2_ctrl_auto_cluster(2, &ctrls->auto_gain, 0, true);
-+      v4l2_ctrl_auto_cluster(2, &ctrls->auto_exp, 1, true);
-+
-+      sensor->sd.ctrl_handler = hdl;
-+      return 0;
-+
-+free_ctrls:
-+      v4l2_ctrl_handler_free(hdl);
-+      return ret;
-+}
-+
-+static int sc2235_enum_frame_size(struct v4l2_subdev *sd,
-+                              struct v4l2_subdev_state *state,
-+                              struct v4l2_subdev_frame_size_enum *fse)
-+{
-+      if (fse->pad != 0)
-+              return -EINVAL;
-+      if (fse->index >= SC2235_NUM_MODES)
-+              return -EINVAL;
-+
-+      fse->min_width =
-+              sc2235_mode_data[fse->index].hact;
-+      fse->max_width = fse->min_width;
-+      fse->min_height =
-+              sc2235_mode_data[fse->index].vact;
-+      fse->max_height = fse->min_height;
-+
-+      return 0;
-+}
-+
-+static int sc2235_enum_frame_interval(
-+      struct v4l2_subdev *sd,
-+      struct v4l2_subdev_state *state,
-+      struct v4l2_subdev_frame_interval_enum *fie)
-+{
-+      struct v4l2_fract tpf;
-+      int i;
-+
-+      if (fie->pad != 0)
-+              return -EINVAL;
-+
-+      if (fie->index >= SC2235_NUM_FRAMERATES)
-+              return -EINVAL;
-+
-+      tpf.numerator = 1;
-+      tpf.denominator = sc2235_framerates[fie->index];
-+
-+      for (i = 0; i < SC2235_NUM_MODES; i++) {
-+              if (fie->width == sc2235_mode_data[i].hact &&
-+                      fie->height == sc2235_mode_data[i].vact)
-+                      break;
-+      }
-+      if (i == SC2235_NUM_MODES)
-+              return -ENOTTY;
-+
-+      fie->interval = tpf;
-+      return 0;
-+}
-+
-+static int sc2235_g_frame_interval(struct v4l2_subdev *sd,
-+                              struct v4l2_subdev_frame_interval *fi)
-+{
-+      struct sc2235_dev *sensor = to_sc2235_dev(sd);
-+
-+      mutex_lock(&sensor->lock);
-+      fi->interval = sensor->frame_interval;
-+      mutex_unlock(&sensor->lock);
-+
-+      return 0;
-+}
-+
-+static int sc2235_s_frame_interval(struct v4l2_subdev *sd,
-+                              struct v4l2_subdev_frame_interval *fi)
-+{
-+      struct sc2235_dev *sensor = to_sc2235_dev(sd);
-+      const struct sc2235_mode_info *mode;
-+      int frame_rate, ret = 0;
-+
-+      if (fi->pad != 0)
-+              return -EINVAL;
-+
-+      mutex_lock(&sensor->lock);
-+
-+      if (sensor->streaming) {
-+              ret = -EBUSY;
-+              goto out;
-+      }
-+
-+      mode = sensor->current_mode;
-+
-+      frame_rate = sc2235_try_frame_interval(sensor, &fi->interval,
-+                                              mode->hact, mode->vact);
-+      if (frame_rate < 0) {
-+              /* Always return a valid frame interval value */
-+              fi->interval = sensor->frame_interval;
-+              goto out;
-+      }
-+
-+      mode = sc2235_find_mode(sensor, frame_rate, mode->hact,
-+                              mode->vact, true);
-+      if (!mode) {
-+              ret = -EINVAL;
-+              goto out;
-+      }
-+
-+      if (mode != sensor->current_mode ||
-+          frame_rate != sensor->current_fr) {
-+              sensor->current_fr = frame_rate;
-+              sensor->frame_interval = fi->interval;
-+              sensor->current_mode = mode;
-+              sensor->pending_mode_change = true;
-+
-+              __v4l2_ctrl_s_ctrl_int64(sensor->ctrls.pixel_rate,
-+                                      sc2235_calc_pixel_rate(sensor));
-+      }
-+out:
-+      mutex_unlock(&sensor->lock);
-+      return ret;
-+}
-+
-+static int sc2235_enum_mbus_code(struct v4l2_subdev *sd,
-+                              struct v4l2_subdev_state *state,
-+                              struct v4l2_subdev_mbus_code_enum *code)
-+{
-+      if (code->pad != 0)
-+              return -EINVAL;
-+      if (code->index >= ARRAY_SIZE(sc2235_formats))
-+              return -EINVAL;
-+
-+      code->code = sc2235_formats[code->index].code;
-+      return 0;
-+}
-+
-+static int sc2235_stream_start(struct sc2235_dev *sensor, int enable)
-+{
-+      return sc2235_mod_reg(sensor, SC2235_REG_STREAM_ON, BIT(0), !!enable);
-+}
-+
-+static int sc2235_s_stream(struct v4l2_subdev *sd, int enable)
-+{
-+      struct sc2235_dev *sensor = to_sc2235_dev(sd);
-+      int ret = 0;
-+
-+      if (enable) {
-+              ret = v4l2_ctrl_handler_setup(&sensor->ctrls.handler);
-+              if (ret)
-+                      return ret;
-+      }
-+
-+      mutex_lock(&sensor->lock);
-+
-+      if (sensor->streaming == !enable) {
-+              if (enable && sensor->pending_mode_change) {
-+                      ret = sc2235_set_mode(sensor);
-+                      if (ret)
-+                              goto out;
-+              }
-+
-+              if (enable && sensor->pending_fmt_change) {
-+                      ret = sc2235_set_framefmt(sensor, &sensor->fmt);
-+                      if (ret)
-+                              goto out;
-+                      sensor->pending_fmt_change = false;
-+              }
-+
-+              ret = sc2235_stream_start(sensor, enable);
-+              if (ret)
-+                      goto out;
-+      }
-+      sensor->streaming += enable ? 1 : -1;
-+      WARN_ON(sensor->streaming < 0);
-+out:
-+      mutex_unlock(&sensor->lock);
-+
-+      return ret;
-+}
-+
-+static const struct v4l2_subdev_core_ops sc2235_core_ops = {
-+      .s_power = sc2235_s_power,
-+      .log_status = v4l2_ctrl_subdev_log_status,
-+      .subscribe_event = v4l2_ctrl_subdev_subscribe_event,
-+      .unsubscribe_event = v4l2_event_subdev_unsubscribe,
-+};
-+
-+static const struct v4l2_subdev_video_ops sc2235_video_ops = {
-+      .g_frame_interval = sc2235_g_frame_interval,
-+      .s_frame_interval = sc2235_s_frame_interval,
-+      .s_stream = sc2235_s_stream,
-+};
-+
-+static const struct v4l2_subdev_pad_ops sc2235_pad_ops = {
-+      .enum_mbus_code = sc2235_enum_mbus_code,
-+      .get_fmt = sc2235_get_fmt,
-+      .set_fmt = sc2235_set_fmt,
-+      .enum_frame_size = sc2235_enum_frame_size,
-+      .enum_frame_interval = sc2235_enum_frame_interval,
-+};
-+
-+static const struct v4l2_subdev_ops sc2235_subdev_ops = {
-+      .core = &sc2235_core_ops,
-+      .video = &sc2235_video_ops,
-+      .pad = &sc2235_pad_ops,
-+};
-+
-+static int sc2235_get_regulators(struct sc2235_dev *sensor)
-+{
-+      int i;
-+
-+      for (i = 0; i < SC2235_NUM_SUPPLIES; i++)
-+              sensor->supplies[i].supply = sc2235_supply_name[i];
-+
-+      return devm_regulator_bulk_get(&sensor->i2c_client->dev,
-+                                      SC2235_NUM_SUPPLIES,
-+                                      sensor->supplies);
-+}
-+
-+static int sc2235_check_chip_id(struct sc2235_dev *sensor)
-+{
-+      struct i2c_client *client = sensor->i2c_client;
-+      int ret = 0;
-+      u16 chip_id;
-+
-+      ret = sc2235_read_reg16(sensor, SC2235_REG_CHIP_ID, &chip_id);
-+      if (ret) {
-+              dev_err(&client->dev, "%s: failed to read chip identifier\n",
-+                      __func__);
-+              return ret;
-+      }
-+
-+      if (chip_id != SC2235_CHIP_ID) {
-+              dev_err(&client->dev, "%s: wrong chip identifier, expected 0x%x, got 0x%x\n",
-+                      __func__, SC2235_CHIP_ID, chip_id);
-+              return -ENXIO;
-+      }
-+      dev_err(&client->dev, "%s: chip identifier, got 0x%x\n",
-+              __func__, chip_id);
-+
-+      return 0;
-+}
-+
-+static int sc2235_probe(struct i2c_client *client)
-+{
-+      struct device *dev = &client->dev;
-+      struct fwnode_handle *endpoint;
-+      struct sc2235_dev *sensor;
-+      struct v4l2_mbus_framefmt *fmt;
-+      u32 rotation;
-+      int ret;
-+
-+      sensor = devm_kzalloc(dev, sizeof(*sensor), GFP_KERNEL);
-+      if (!sensor)
-+              return -ENOMEM;
-+
-+      sensor->i2c_client = client;
-+
-+      fmt = &sensor->fmt;
-+      fmt->code = MEDIA_BUS_FMT_SBGGR10_1X10;
-+      fmt->colorspace = V4L2_COLORSPACE_SRGB;
-+      fmt->ycbcr_enc = V4L2_MAP_YCBCR_ENC_DEFAULT(fmt->colorspace);
-+      fmt->quantization = V4L2_QUANTIZATION_FULL_RANGE;
-+      fmt->xfer_func = V4L2_MAP_XFER_FUNC_DEFAULT(fmt->colorspace);
-+      fmt->width = 1920;
-+      fmt->height = 1080;
-+      fmt->field = V4L2_FIELD_NONE;
-+      sensor->frame_interval.numerator = 1;
-+      sensor->frame_interval.denominator = sc2235_framerates[SC2235_30_FPS];
-+      sensor->current_fr = SC2235_30_FPS;
-+      sensor->current_mode =
-+              &sc2235_mode_data[SC2235_MODE_1080P_1920_1080];
-+      sensor->last_mode = sensor->current_mode;
-+
-+      /* optional indication of physical rotation of sensor */
-+      ret = fwnode_property_read_u32(dev_fwnode(&client->dev), "rotation",
-+                                      &rotation);
-+      if (!ret) {
-+              switch (rotation) {
-+              case 180:
-+                      sensor->upside_down = true;
-+                      fallthrough;
-+              case 0:
-+                      break;
-+              default:
-+                      dev_warn(dev, "%u degrees rotation is not supported, ignoring...\n",
-+                              rotation);
-+              }
-+      }
-+
-+      endpoint = fwnode_graph_get_next_endpoint(dev_fwnode(&client->dev),
-+                                              NULL);
-+      if (!endpoint) {
-+              dev_err(dev, "endpoint node not found\n");
-+              return -EINVAL;
-+      }
-+
-+      ret = v4l2_fwnode_endpoint_parse(endpoint, &sensor->ep);
-+      fwnode_handle_put(endpoint);
-+      if (ret) {
-+              dev_err(dev, "Could not parse endpoint\n");
-+              return ret;
-+      }
-+
-+      if (sensor->ep.bus_type != V4L2_MBUS_PARALLEL) {
-+              dev_err(dev, "Unsupported bus type %d\n", sensor->ep.bus_type);
-+              return -EINVAL;
-+      }
-+
-+      /* get system clock (xclk) */
-+      sensor->xclk = devm_clk_get(dev, "xclk");
-+      if (IS_ERR(sensor->xclk)) {
-+              dev_err(dev, "failed to get xclk\n");
-+              return PTR_ERR(sensor->xclk);
-+      }
-+
-+      sensor->xclk_freq = clk_get_rate(sensor->xclk);
-+      if (sensor->xclk_freq < SC2235_XCLK_MIN ||
-+          sensor->xclk_freq > SC2235_XCLK_MAX) {
-+              dev_err(dev, "xclk frequency out of range: %d Hz\n",
-+                      sensor->xclk_freq);
-+              return -EINVAL;
-+      }
-+
-+      sensor->pwdn_gpio = devm_gpiod_get_optional(dev, "powerdown",
-+                                              GPIOD_OUT_HIGH);
-+      if (IS_ERR(sensor->pwdn_gpio))
-+              return PTR_ERR(sensor->pwdn_gpio);
-+
-+      sensor->reset_gpio = devm_gpiod_get_optional(dev, "reset",
-+                                              GPIOD_OUT_HIGH);
-+      if (IS_ERR(sensor->reset_gpio))
-+              return PTR_ERR(sensor->reset_gpio);
-+
-+      v4l2_i2c_subdev_init(&sensor->sd, client, &sc2235_subdev_ops);
-+
-+      sensor->sd.flags |= V4L2_SUBDEV_FL_HAS_DEVNODE |
-+                      V4L2_SUBDEV_FL_HAS_EVENTS;
-+      sensor->pad.flags = MEDIA_PAD_FL_SOURCE;
-+      sensor->sd.entity.function = MEDIA_ENT_F_CAM_SENSOR;
-+      ret = media_entity_pads_init(&sensor->sd.entity, 1, &sensor->pad);
-+      if (ret)
-+              return ret;
-+
-+      ret = sc2235_get_regulators(sensor);
-+      if (ret)
-+              return ret;
-+      mutex_init(&sensor->lock);
-+
-+      ret = sc2235_set_power_on(dev);
-+      if (ret) {
-+              dev_err(dev, "failed to power on\n");
-+              goto entity_cleanup;
-+      }
-+
-+      ret = sc2235_check_chip_id(sensor);
-+      if (ret)
-+              goto entity_power_off;
-+
-+      ret = sc2235_init_controls(sensor);
-+      if (ret)
-+              goto entity_power_off;
-+
-+      ret = v4l2_async_register_subdev_sensor(&sensor->sd);
-+      if (ret)
-+              goto free_ctrls;
-+
-+      pm_runtime_set_active(dev);
-+      pm_runtime_enable(dev);
-+
-+      return 0;
-+
-+free_ctrls:
-+      v4l2_ctrl_handler_free(&sensor->ctrls.handler);
-+entity_power_off:
-+      sc2235_set_power_off(dev);
-+entity_cleanup:
-+      media_entity_cleanup(&sensor->sd.entity);
-+      mutex_destroy(&sensor->lock);
-+      return ret;
-+}
-+
-+static void sc2235_remove(struct i2c_client *client)
-+{
-+      struct v4l2_subdev *sd = i2c_get_clientdata(client);
-+      struct sc2235_dev *sensor = to_sc2235_dev(sd);
-+
-+      v4l2_async_unregister_subdev(&sensor->sd);
-+      media_entity_cleanup(&sensor->sd.entity);
-+      v4l2_ctrl_handler_free(&sensor->ctrls.handler);
-+      mutex_destroy(&sensor->lock);
-+
-+      pm_runtime_disable(&client->dev);
-+      if (!pm_runtime_status_suspended(&client->dev))
-+              sc2235_set_power_off(&client->dev);
-+      pm_runtime_set_suspended(&client->dev);
-+}
-+
-+static const struct i2c_device_id sc2235_id[] = {
-+      { "sc2235", 0 },
-+      {},
-+};
-+MODULE_DEVICE_TABLE(i2c, sc2235_id);
-+
-+static const struct of_device_id sc2235_dt_ids[] = {
-+      { .compatible = "smartsens,sc2235" },
-+      { /* sentinel */ }
-+};
-+MODULE_DEVICE_TABLE(of, sc2235_dt_ids);
-+
-+static const struct dev_pm_ops sc2235_pm_ops = {
-+      SET_RUNTIME_PM_OPS(sc2235_set_power_off, sc2235_set_power_on, NULL)
-+};
-+
-+static struct i2c_driver sc2235_i2c_driver = {
-+      .driver = {
-+              .name  = "sc2235",
-+              .of_match_table = sc2235_dt_ids,
-+              .pm = &sc2235_pm_ops,
-+      },
-+      .id_table = sc2235_id,
-+      .probe = sc2235_probe,
-+      .remove   = sc2235_remove,
-+};
-+
-+module_i2c_driver(sc2235_i2c_driver);
-+
-+MODULE_DESCRIPTION("SC2235 Camera Subdev Driver");
-+MODULE_LICENSE("GPL");
---- /dev/null
-+++ b/drivers/media/platform/starfive/v4l2_driver/stf_common.h
-@@ -0,0 +1,185 @@
-+/* SPDX-License-Identifier: GPL-2.0
-+ *
-+ * Copyright (C) 2021-2023 StarFive Technology Co., Ltd.
-+ *
-+ */
-+
-+#ifndef STF_COMMON_H
-+#define STF_COMMON_H
-+
-+#include <linux/kern_levels.h>
-+
-+// #define STF_DEBUG
-+
-+// #define USE_CSIDPHY_ONE_CLK_MODE 1
-+
-+enum {
-+      ST_DVP = 0x0001,
-+      ST_CSIPHY = 0x0002,
-+      ST_CSI = 0x0004,
-+      ST_ISP = 0x0008,
-+      ST_VIN = 0x0010,
-+      ST_VIDEO = 0x0020,
-+      ST_CAMSS = 0x0040,
-+      ST_SENSOR = 0x0080,
-+};
-+
-+enum {
-+      ST_NONE = 0x00,
-+      ST_ERR = 0x01,
-+      ST_WARN = 0x02,
-+      ST_INFO = 0x03,
-+      ST_DEBUG = 0x04,
-+};
-+
-+extern unsigned int stdbg_level;
-+extern unsigned int stdbg_mask;
-+
-+#define ST_MODULE2STRING(__module) ({ \
-+      char *__str; \
-+      \
-+      switch (__module) { \
-+      case ST_DVP: \
-+              __str = "st_dvp"; \
-+              break; \
-+      case ST_CSIPHY: \
-+              __str = "st_csiphy"; \
-+              break; \
-+      case ST_CSI: \
-+              __str = "st_csi"; \
-+              break; \
-+      case ST_ISP: \
-+              __str = "st_isp"; \
-+              break; \
-+      case ST_VIN: \
-+              __str = "st_vin"; \
-+              break; \
-+      case ST_VIDEO: \
-+              __str = "st_video"; \
-+              break; \
-+      case ST_CAMSS: \
-+              __str = "st_camss"; \
-+              break; \
-+      case ST_SENSOR: \
-+              __str = "st_sensor"; \
-+              break; \
-+      default: \
-+              __str = "unknow"; \
-+              break; \
-+      } \
-+      \
-+      __str; \
-+      })
-+
-+#define st_debug(module, __fmt, arg...)       \
-+      do { \
-+              if (stdbg_level > ST_INFO) { \
-+                      if (stdbg_mask & module)  \
-+                              pr_err("[%s] debug: " __fmt, \
-+                                              ST_MODULE2STRING(module), \
-+                                              ## arg); \
-+              } \
-+      } while (0)
-+
-+#define st_info(module, __fmt, arg...)        \
-+      do { \
-+              if (stdbg_level > ST_WARN) { \
-+                      if (stdbg_mask & module)  \
-+                              pr_err("[%s] info: " __fmt, \
-+                                              ST_MODULE2STRING(module), \
-+                                              ## arg); \
-+              } \
-+      } while (0)
-+
-+#define st_warn(module, __fmt, arg...)        \
-+      do { \
-+              if (stdbg_level > ST_ERR) { \
-+                      if (stdbg_mask & module)  \
-+                              pr_err("[%s] warn: " __fmt, \
-+                                              ST_MODULE2STRING(module), \
-+                                              ## arg); \
-+              } \
-+      } while (0)
-+
-+#define st_err(module, __fmt, arg...) \
-+      do { \
-+              if (stdbg_level > ST_NONE) { \
-+                      if (stdbg_mask & module) \
-+                              pr_err("[%s] error: " __fmt, \
-+                                              ST_MODULE2STRING(module), \
-+                                              ## arg); \
-+              } \
-+      } while (0)
-+
-+#define st_err_ratelimited(module, fmt, ...)                 \
-+      do {                                                                    \
-+              static DEFINE_RATELIMIT_STATE(_rs,                              \
-+                                              DEFAULT_RATELIMIT_INTERVAL,     \
-+                                              DEFAULT_RATELIMIT_BURST);       \
-+              if (__ratelimit(&_rs) && (stdbg_level > ST_NONE)) {             \
-+                      if (stdbg_mask & module)                                \
-+                              pr_err("[%s] error: " fmt,                      \
-+                                              ST_MODULE2STRING(module),       \
-+                                              ##__VA_ARGS__);                 \
-+              } \
-+      } while (0)
-+
-+#define set_bits(p, v, b, m)  (((p) & ~(m)) | ((v) << (b)))
-+
-+static inline u32 reg_read(void __iomem *base, u32 reg)
-+{
-+      return ioread32(base + reg);
-+}
-+
-+static inline void reg_write(void __iomem *base, u32 reg, u32 val)
-+{
-+      iowrite32(val, base + reg);
-+}
-+
-+static inline void reg_set_bit(void __iomem *base, u32 reg, u32 mask, u32 val)
-+{
-+      u32 value;
-+
-+      value = ioread32(base + reg) & ~mask;
-+      val &= mask;
-+      val |= value;
-+      iowrite32(val, base + reg);
-+}
-+
-+static inline void reg_set(void __iomem *base, u32 reg, u32 mask)
-+{
-+      iowrite32(ioread32(base + reg) | mask, base + reg);
-+}
-+
-+static inline void reg_clear(void __iomem *base, u32 reg, u32 mask)
-+{
-+      iowrite32(ioread32(base + reg) & ~mask, base + reg);
-+}
-+
-+static inline void reg_set_highest_bit(void __iomem *base, u32 reg)
-+{
-+      u32 val;
-+
-+      val = ioread32(base + reg);
-+      val &= ~(0x1 << 31);
-+      val |= (0x1 & 0x1) << 31;
-+      iowrite32(val, base + reg);
-+}
-+
-+static inline void reg_clr_highest_bit(void __iomem *base, u32 reg)
-+{
-+      u32 val;
-+
-+      val = ioread32(base + reg);
-+      val &= ~(0x1 << 31);
-+      val |= (0x0 & 0x1) << 31;
-+      iowrite32(val, base + reg);
-+}
-+
-+static inline void print_reg(unsigned int module, void __iomem *base, u32 reg)
-+{
-+      //st_debug(module, "REG 0x%x = 0x%x\n",
-+      //              base + reg, ioread32(base + reg));
-+}
-+
-+#endif /* STF_COMMON_H */
---- /dev/null
-+++ b/drivers/media/platform/starfive/v4l2_driver/stf_csi.c
-@@ -0,0 +1,465 @@
-+// SPDX-License-Identifier: GPL-2.0
-+/*
-+ * Copyright (C) 2021-2023 StarFive Technology Co., Ltd.
-+ *
-+ */
-+
-+#include "stfcamss.h"
-+#include <media/v4l2-async.h>
-+#include <media/v4l2-ctrls.h>
-+#include <media/v4l2-device.h>
-+#include <media/v4l2-event.h>
-+#include <media/v4l2-fwnode.h>
-+#include <media/v4l2-subdev.h>
-+
-+static const struct csi_format csi_formats_sink[] = {
-+      { MEDIA_BUS_FMT_UYVY8_2X8, 16},
-+      { MEDIA_BUS_FMT_SRGGB10_1X10, 10},
-+      { MEDIA_BUS_FMT_SGRBG10_1X10, 10},
-+      { MEDIA_BUS_FMT_SGBRG10_1X10, 10},
-+      { MEDIA_BUS_FMT_SBGGR10_1X10, 10},
-+};
-+
-+/* this bpp need see csi controllor */
-+static const struct csi_format csi_formats_src[] = {
-+      { MEDIA_BUS_FMT_AYUV8_1X32, 32},
-+      { MEDIA_BUS_FMT_SRGGB10_1X10, 16},
-+      { MEDIA_BUS_FMT_SGRBG10_1X10, 16},
-+      { MEDIA_BUS_FMT_SGBRG10_1X10, 16},
-+      { MEDIA_BUS_FMT_SBGGR10_1X10, 16},
-+};
-+
-+static int csi_find_format(u32 code,
-+              const struct csi_format *formats,
-+              unsigned int nformats)
-+{
-+      int i;
-+
-+      for (i = 0; i < nformats; i++)
-+              if (formats[i].code == code)
-+                      return i;
-+      return -EINVAL;
-+}
-+
-+int stf_csi_subdev_init(struct stfcamss *stfcamss)
-+{
-+      struct stf_csi_dev *csi_dev = stfcamss->csi_dev;
-+
-+      csi_dev->s_type = SENSOR_VIN;
-+      csi_dev->hw_ops = &csi_ops;
-+      csi_dev->stfcamss = stfcamss;
-+      csi_dev->formats_sink = csi_formats_sink;
-+      csi_dev->nformats_sink = ARRAY_SIZE(csi_formats_sink);
-+      csi_dev->formats_src = csi_formats_src;
-+      csi_dev->nformats_src = ARRAY_SIZE(csi_formats_src);
-+      mutex_init(&csi_dev->stream_lock);
-+      return 0;
-+}
-+
-+static int csi_set_power(struct v4l2_subdev *sd, int on)
-+{
-+      struct stf_csi_dev *csi_dev = v4l2_get_subdevdata(sd);
-+
-+      csi_dev->hw_ops->csi_power_on(csi_dev, (u8)on);
-+      return 0;
-+}
-+
-+static struct v4l2_mbus_framefmt *
-+__csi_get_format(struct stf_csi_dev *csi_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(&csi_dev->subdev, state, pad);
-+
-+      return &csi_dev->fmt[pad];
-+}
-+
-+static u32 code_to_data_type(int code)
-+{
-+      switch (code) {
-+      case MEDIA_BUS_FMT_SRGGB10_1X10:
-+      case MEDIA_BUS_FMT_SGRBG10_1X10:
-+      case MEDIA_BUS_FMT_SGBRG10_1X10:
-+      case MEDIA_BUS_FMT_SBGGR10_1X10:
-+              return 0x2b;
-+      case MEDIA_BUS_FMT_UYVY8_2X8:
-+              return 0x1E;
-+      default:
-+              return 0x2b;
-+      }
-+}
-+
-+static int csi_set_stream(struct v4l2_subdev *sd, int enable)
-+{
-+      struct stf_csi_dev *csi_dev = v4l2_get_subdevdata(sd);
-+      struct v4l2_mbus_framefmt *format;
-+      int ret = 0;
-+      u32 code, width, dt;
-+      u8 bpp;
-+
-+      format = __csi_get_format(csi_dev, NULL, STF_CSI_PAD_SINK,
-+                              V4L2_SUBDEV_FORMAT_ACTIVE);
-+      if (format == NULL)
-+              return -EINVAL;
-+
-+      width = format->width;
-+
-+      ret = csi_find_format(format->code,
-+                              csi_dev->formats_sink,
-+                              csi_dev->nformats_sink);
-+      if (ret < 0)
-+              return ret;
-+
-+      code = csi_dev->formats_sink[ret].code;
-+      bpp = csi_dev->formats_src[ret].bpp;
-+      dt = code_to_data_type(code);
-+
-+      mutex_lock(&csi_dev->stream_lock);
-+      if (enable) {
-+              if (csi_dev->stream_count == 0) {
-+                      csi_dev->hw_ops->csi_clk_enable(csi_dev);
-+                      csi_dev->hw_ops->csi_stream_set(csi_dev, enable, dt, width, bpp);
-+              }
-+              csi_dev->stream_count++;
-+      } else {
-+              if (csi_dev->stream_count == 0)
-+                      goto exit;
-+              if (csi_dev->stream_count == 1) {
-+                      csi_dev->hw_ops->csi_stream_set(csi_dev, enable, dt, width, bpp);
-+                      csi_dev->hw_ops->csi_clk_disable(csi_dev);
-+              }
-+              csi_dev->stream_count--;
-+      }
-+exit:
-+      mutex_unlock(&csi_dev->stream_lock);
-+      return 0;
-+}
-+
-+static void csi_try_format(struct stf_csi_dev *csi_dev,
-+                      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_CSI_PAD_SINK:
-+              /* Set format on sink pad */
-+
-+              for (i = 0; i < csi_dev->nformats_sink; i++)
-+                      if (fmt->code == csi_dev->formats_sink[i].code)
-+                              break;
-+
-+              if (i >= csi_dev->nformats_sink)
-+                      fmt->code = csi_dev->formats_sink[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_CSI_PAD_SRC:
-+              /* Set format on src pad */
-+
-+              for (i = 0; i < csi_dev->nformats_src; i++)
-+                      if (fmt->code == csi_dev->formats_src[i].code)
-+                              break;
-+
-+              if (i >= csi_dev->nformats_src)
-+                      fmt->code = csi_dev->formats_src[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;
-+      }
-+}
-+
-+static int csi_enum_mbus_code(struct v4l2_subdev *sd,
-+                      struct v4l2_subdev_state *state,
-+                      struct v4l2_subdev_mbus_code_enum *code)
-+{
-+      struct stf_csi_dev *csi_dev = v4l2_get_subdevdata(sd);
-+
-+      if (code->index >= csi_dev->nformats_sink)
-+              return -EINVAL;
-+      if (code->pad == STF_CSI_PAD_SINK) {
-+              code->code = csi_dev->formats_sink[code->index].code;
-+      } else {
-+              struct v4l2_mbus_framefmt *sink_fmt;
-+
-+              sink_fmt = __csi_get_format(csi_dev, state, STF_CSI_PAD_SINK,
-+                                              code->which);
-+
-+              code->code = sink_fmt->code;
-+              if (!code->code)
-+                      return -EINVAL;
-+      }
-+      code->flags = 0;
-+
-+      return 0;
-+}
-+
-+static int csi_enum_frame_size(struct v4l2_subdev *sd,
-+                              struct v4l2_subdev_state *state,
-+                              struct v4l2_subdev_frame_size_enum *fse)
-+{
-+      struct stf_csi_dev *csi_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;
-+      csi_try_format(csi_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;
-+      csi_try_format(csi_dev, state, fse->pad, &format, fse->which);
-+      fse->max_width = format.width;
-+      fse->max_height = format.height;
-+
-+      return 0;
-+}
-+
-+static int csi_get_format(struct v4l2_subdev *sd,
-+                      struct v4l2_subdev_state *state,
-+                      struct v4l2_subdev_format *fmt)
-+{
-+      struct stf_csi_dev *csi_dev = v4l2_get_subdevdata(sd);
-+      struct v4l2_mbus_framefmt *format;
-+
-+      format = __csi_get_format(csi_dev, state, fmt->pad, fmt->which);
-+      if (format == NULL)
-+              return -EINVAL;
-+
-+      fmt->format = *format;
-+
-+      return 0;
-+}
-+
-+static int csi_set_format(struct v4l2_subdev *sd,
-+                      struct v4l2_subdev_state *state,
-+                      struct v4l2_subdev_format *fmt)
-+{
-+      struct stf_csi_dev *csi_dev = v4l2_get_subdevdata(sd);
-+      struct v4l2_mbus_framefmt *format;
-+      struct v4l2_mbus_framefmt *format_src;
-+      int ret;
-+
-+      format = __csi_get_format(csi_dev, state, fmt->pad, fmt->which);
-+      if (format == NULL)
-+              return -EINVAL;
-+
-+      mutex_lock(&csi_dev->stream_lock);
-+      if (csi_dev->stream_count) {
-+              fmt->format = *format;
-+              mutex_unlock(&csi_dev->stream_lock);
-+              goto out;
-+      } else {
-+              csi_try_format(csi_dev, state, fmt->pad, &fmt->format, fmt->which);
-+              *format = fmt->format;
-+      }
-+      mutex_unlock(&csi_dev->stream_lock);
-+
-+      if (fmt->pad == STF_CSI_PAD_SINK) {
-+              format_src = __csi_get_format(csi_dev, state, STF_DVP_PAD_SRC,
-+                                      fmt->which);
-+
-+              ret = csi_find_format(format->code, csi_dev->formats_sink,
-+                              csi_dev->nformats_sink);
-+              if (ret < 0)
-+                      return ret;
-+
-+              format_src->code = csi_dev->formats_src[ret].code;
-+              csi_try_format(csi_dev, state, STF_DVP_PAD_SRC, format_src,
-+                                      fmt->which);
-+      }
-+out:
-+      return 0;
-+}
-+
-+static int csi_init_formats(struct v4l2_subdev *sd,
-+                      struct v4l2_subdev_fh *fh)
-+{
-+      struct v4l2_subdev_format format = {
-+              .pad = STF_CSI_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 csi_set_format(sd, fh ? fh->state : NULL, &format);
-+}
-+
-+static int csi_link_setup(struct media_entity *entity,
-+                      const struct media_pad *local,
-+                      const struct media_pad *remote, u32 flags)
-+{
-+      if ((local->flags & MEDIA_PAD_FL_SOURCE) &&
-+              (flags & MEDIA_LNK_FL_ENABLED)) {
-+              struct v4l2_subdev *sd;
-+              struct stf_csi_dev *csi_dev;
-+              struct vin_line *line;
-+
-+              if (media_pad_remote_pad_first(local))
-+                      return -EBUSY;
-+
-+              sd = media_entity_to_v4l2_subdev(entity);
-+              csi_dev = v4l2_get_subdevdata(sd);
-+
-+              sd = media_entity_to_v4l2_subdev(remote->entity);
-+              line = v4l2_get_subdevdata(sd);
-+              if (line->sdev_type == VIN_DEV_TYPE)
-+                      csi_dev->s_type = SENSOR_VIN;
-+              if (line->sdev_type == ISP_DEV_TYPE)
-+                      csi_dev->s_type = SENSOR_ISP;
-+              st_info(ST_CSI, "CSI device sensor type: %d\n", csi_dev->s_type);
-+      }
-+
-+      if ((local->flags & MEDIA_PAD_FL_SINK) &&
-+              (flags & MEDIA_LNK_FL_ENABLED)) {
-+              struct v4l2_subdev *sd;
-+              struct stf_csi_dev *csi_dev;
-+              struct stf_csiphy_dev *csiphy_dev;
-+
-+              if (media_pad_remote_pad_first(local))
-+                      return -EBUSY;
-+
-+              sd = media_entity_to_v4l2_subdev(entity);
-+              csi_dev = v4l2_get_subdevdata(sd);
-+
-+              sd = media_entity_to_v4l2_subdev(remote->entity);
-+              csiphy_dev = v4l2_get_subdevdata(sd);
-+
-+              st_info(ST_CSI, "CSI0 link to csiphy0\n");
-+      }
-+
-+      return 0;
-+}
-+
-+static const struct v4l2_subdev_core_ops csi_core_ops = {
-+      .s_power = csi_set_power,
-+};
-+
-+static const struct v4l2_subdev_video_ops csi_video_ops = {
-+      .s_stream = csi_set_stream,
-+};
-+
-+static const struct v4l2_subdev_pad_ops csi_pad_ops = {
-+      .enum_mbus_code = csi_enum_mbus_code,
-+      .enum_frame_size = csi_enum_frame_size,
-+      .get_fmt = csi_get_format,
-+      .set_fmt = csi_set_format,
-+};
-+
-+static const struct v4l2_subdev_ops csi_v4l2_ops = {
-+      .core = &csi_core_ops,
-+      .video = &csi_video_ops,
-+      .pad = &csi_pad_ops,
-+};
-+
-+static const struct v4l2_subdev_internal_ops csi_v4l2_internal_ops = {
-+      .open = csi_init_formats,
-+};
-+
-+static const struct media_entity_operations csi_media_ops = {
-+      .link_setup = csi_link_setup,
-+      .link_validate = v4l2_subdev_link_validate,
-+};
-+
-+int stf_csi_register(struct stf_csi_dev *csi_dev, struct v4l2_device *v4l2_dev)
-+{
-+      struct v4l2_subdev *sd = &csi_dev->subdev;
-+      struct device *dev = csi_dev->stfcamss->dev;
-+      struct media_pad *pads = csi_dev->pads;
-+      int ret;
-+
-+      csi_dev->mipirx_1p8 = devm_regulator_get(dev, "mipirx_1p8");
-+      if (IS_ERR(csi_dev->mipirx_1p8))
-+              return PTR_ERR(csi_dev->mipirx_1p8);
-+
-+      csi_dev->mipirx_0p9 = devm_regulator_get(dev, "mipirx_0p9");
-+      if (IS_ERR(csi_dev->mipirx_0p9))
-+              return PTR_ERR(csi_dev->mipirx_0p9);
-+
-+      v4l2_subdev_init(sd, &csi_v4l2_ops);
-+      sd->internal_ops = &csi_v4l2_internal_ops;
-+      sd->flags |= V4L2_SUBDEV_FL_HAS_DEVNODE;
-+      snprintf(sd->name, ARRAY_SIZE(sd->name), "%s%d",
-+              STF_CSI_NAME, 0);
-+      v4l2_set_subdevdata(sd, csi_dev);
-+
-+      ret = csi_init_formats(sd, NULL);
-+      if (ret < 0) {
-+              dev_err(dev, "Failed to init format: %d\n", ret);
-+              return ret;
-+      }
-+
-+      pads[STF_CSI_PAD_SINK].flags = MEDIA_PAD_FL_SINK;
-+      pads[STF_CSI_PAD_SRC].flags = MEDIA_PAD_FL_SOURCE;
-+
-+      sd->entity.function = MEDIA_ENT_F_PROC_VIDEO_PIXEL_FORMATTER;
-+      sd->entity.ops = &csi_media_ops;
-+      ret = media_entity_pads_init(&sd->entity, STF_CSI_PADS_NUM, pads);
-+      if (ret < 0) {
-+              dev_err(dev, "Failed to init media entity: %d\n", ret);
-+              return ret;
-+      }
-+
-+      ret = v4l2_device_register_subdev(v4l2_dev, sd);
-+      if (ret < 0) {
-+              dev_err(dev, "Failed to register subdev: %d\n", ret);
-+              goto err_sreg;
-+      }
-+
-+      return 0;
-+
-+err_sreg:
-+      media_entity_cleanup(&sd->entity);
-+      return ret;
-+}
-+
-+int stf_csi_unregister(struct stf_csi_dev *csi_dev)
-+{
-+      v4l2_device_unregister_subdev(&csi_dev->subdev);
-+      media_entity_cleanup(&csi_dev->subdev.entity);
-+      mutex_destroy(&csi_dev->stream_lock);
-+      return 0;
-+}
---- /dev/null
-+++ b/drivers/media/platform/starfive/v4l2_driver/stf_csi.h
-@@ -0,0 +1,61 @@
-+/* SPDX-License-Identifier: GPL-2.0
-+ *
-+ * Copyright (C) 2021-2023 StarFive Technology Co., Ltd.
-+ *
-+ */
-+
-+#ifndef STF_CSI_H
-+#define STF_CSI_H
-+
-+#include <linux/regulator/consumer.h>
-+#include <media/v4l2-subdev.h>
-+#include <media/v4l2-device.h>
-+#include <media/media-entity.h>
-+#include <video/stf-vin.h>
-+
-+#define STF_CSI_NAME "stf_csi"
-+
-+#define STF_CSI_PAD_SINK     0
-+#define STF_CSI_PAD_SRC      1
-+#define STF_CSI_PADS_NUM     2
-+
-+struct csi_format {
-+      u32 code;
-+      u8 bpp;
-+};
-+
-+struct stf_csi_dev;
-+
-+struct csi_hw_ops {
-+      int (*csi_power_on)(struct stf_csi_dev *csi_dev, u8 on);
-+      int (*csi_clk_enable)(struct stf_csi_dev *csi_dev);
-+      int (*csi_clk_disable)(struct stf_csi_dev *csi_dev);
-+      int (*csi_stream_set)(struct stf_csi_dev *csi_dev, int on,
-+                            u32 dt, u32 width, u8 bpp);
-+};
-+
-+struct stf_csi_dev {
-+      struct stfcamss *stfcamss;
-+      enum sensor_type s_type;
-+      struct v4l2_subdev subdev;
-+      struct media_pad pads[STF_CSI_PADS_NUM];
-+      struct v4l2_mbus_framefmt fmt[STF_CSI_PADS_NUM];
-+      const struct csi_format *formats_sink;
-+      unsigned int nformats_sink;
-+      const struct csi_format *formats_src;
-+      unsigned int nformats_src;
-+      struct csi_hw_ops *hw_ops;
-+      struct mutex stream_lock;
-+      int stream_count;
-+      struct regulator *mipirx_1p8;
-+      struct regulator *mipirx_0p9;
-+};
-+
-+extern int stf_csi_subdev_init(struct stfcamss *stfcamss);
-+extern int stf_csi_register(struct stf_csi_dev *csi_dev,
-+                      struct v4l2_device *v4l2_dev);
-+extern int stf_csi_unregister(struct stf_csi_dev *csi_dev);
-+extern struct csi_hw_ops csi_ops;
-+extern void dump_csi_reg(void *__iomem csibase);
-+
-+#endif /* STF_CSI_H */
---- /dev/null
-+++ b/drivers/media/platform/starfive/v4l2_driver/stf_csi_hw_ops.c
-@@ -0,0 +1,310 @@
-+// SPDX-License-Identifier: GPL-2.0
-+/*
-+ * Copyright (C) 2021-2023 StarFive Technology Co., Ltd.
-+ *
-+ */
-+
-+#include "stfcamss.h"
-+#include <linux/regmap.h>
-+
-+#define CSI2RX_DEVICE_CFG_REG                 0x000
-+
-+#define CSI2RX_SOFT_RESET_REG                 0x004
-+#define CSI2RX_SOFT_RESET_PROTOCOL            BIT(1)
-+#define CSI2RX_SOFT_RESET_FRONT                       BIT(0)
-+
-+#define CSI2RX_DPHY_LANE_CONTROL                0x040
-+
-+#define CSI2RX_STATIC_CFG_REG                 0x008
-+#define CSI2RX_STATIC_CFG_DLANE_MAP(llane, plane)     \
-+              ((plane) << (16 + (llane) * 4))
-+#define CSI2RX_STATIC_CFG_LANES_MASK          GENMASK(11, 8)
-+
-+#define CSI2RX_STREAM_BASE(n)         (((n) + 1) * 0x100)
-+
-+#define CSI2RX_STREAM_CTRL_REG(n)             (CSI2RX_STREAM_BASE(n) + 0x000)
-+#define CSI2RX_STREAM_CTRL_START              BIT(0)
-+
-+#define CSI2RX_STREAM_DATA_CFG_REG(n)         (CSI2RX_STREAM_BASE(n) + 0x008)
-+#define CSI2RX_STREAM_DATA_CFG_EN_VC_SELECT   BIT(31)
-+#define CSI2RX_STREAM_DATA_CFG_EN_DATA_TYPE_0 BIT(7)
-+#define CSI2RX_STREAM_DATA_CFG_VC_SELECT(n)   BIT((n) + 16)
-+
-+#define CSI2RX_STREAM_CFG_REG(n)              (CSI2RX_STREAM_BASE(n) + 0x00c)
-+#define CSI2RX_STREAM_CFG_FIFO_MODE_LARGE_BUF (1 << 8)
-+
-+#define CSI2RX_LANES_MAX      4
-+#define CSI2RX_STREAMS_MAX    4
-+
-+static int stf_csi_power_on(struct stf_csi_dev *csi_dev, u8 on)
-+{
-+      struct stfcamss *stfcamss = csi_dev->stfcamss;
-+      int ret;
-+
-+      if (on) {
-+              ret = regulator_enable(csi_dev->mipirx_1p8);
-+              if (ret) {
-+                      st_err(ST_CSI, "Cannot enable mipirx_1p8 regulator\n");
-+                      goto err_1p8;
-+              }
-+
-+              ret = regulator_enable(csi_dev->mipirx_0p9);
-+              if (ret) {
-+                      st_err(ST_CSI, "Cannot enable mipirx_0p9 regulator\n");
-+                      goto err_0p9;
-+              }
-+      } else {
-+              regulator_disable(csi_dev->mipirx_1p8);
-+              regulator_disable(csi_dev->mipirx_0p9);
-+      }
-+
-+      regmap_update_bits(stfcamss->stf_aon_syscon, stfcamss->aon_gp_reg,
-+                              BIT(31), BIT(31));
-+
-+      return 0;
-+
-+err_0p9:
-+      regulator_disable(csi_dev->mipirx_1p8);
-+err_1p8:
-+      return ret;
-+
-+}
-+
-+static int stf_csi_clk_enable(struct stf_csi_dev *csi_dev)
-+{
-+      struct stfcamss *stfcamss = csi_dev->stfcamss;
-+
-+      clk_set_rate(stfcamss->sys_clk[STFCLK_MIPI_RX0_PXL].clk, 198000000);
-+      clk_prepare_enable(stfcamss->sys_clk[STFCLK_PIXEL_CLK_IF0].clk);
-+      clk_prepare_enable(stfcamss->sys_clk[STFCLK_PIXEL_CLK_IF1].clk);
-+      clk_prepare_enable(stfcamss->sys_clk[STFCLK_PIXEL_CLK_IF2].clk);
-+      clk_prepare_enable(stfcamss->sys_clk[STFCLK_PIXEL_CLK_IF3].clk);
-+
-+      reset_control_deassert(stfcamss->sys_rst[STFRST_PIXEL_CLK_IF0].rstc);
-+      reset_control_deassert(stfcamss->sys_rst[STFRST_PIXEL_CLK_IF1].rstc);
-+      reset_control_deassert(stfcamss->sys_rst[STFRST_PIXEL_CLK_IF2].rstc);
-+      reset_control_deassert(stfcamss->sys_rst[STFRST_PIXEL_CLK_IF3].rstc);
-+
-+      switch (csi_dev->s_type) {
-+      case SENSOR_VIN:
-+              reset_control_deassert(stfcamss->sys_rst[STFRST_AXIWR].rstc);
-+              clk_set_parent(stfcamss->sys_clk[STFCLK_AXIWR].clk,
-+                      stfcamss->sys_clk[STFCLK_MIPI_RX0_PXL].clk);
-+              break;
-+      case SENSOR_ISP:
-+              clk_set_parent(stfcamss->sys_clk[STFCLK_WRAPPER_CLK_C].clk,
-+                      stfcamss->sys_clk[STFCLK_MIPI_RX0_PXL].clk);
-+              break;
-+      }
-+
-+      return 0;
-+}
-+
-+static int stf_csi_clk_disable(struct stf_csi_dev *csi_dev)
-+{
-+      struct stfcamss *stfcamss = csi_dev->stfcamss;
-+
-+      switch (csi_dev->s_type) {
-+      case SENSOR_VIN:
-+              reset_control_assert(stfcamss->sys_rst[STFRST_AXIWR].rstc);
-+              break;
-+      case SENSOR_ISP:
-+              break;
-+      }
-+
-+      reset_control_assert(stfcamss->sys_rst[STFRST_PIXEL_CLK_IF3].rstc);
-+      reset_control_assert(stfcamss->sys_rst[STFRST_PIXEL_CLK_IF2].rstc);
-+      reset_control_assert(stfcamss->sys_rst[STFRST_PIXEL_CLK_IF1].rstc);
-+      reset_control_assert(stfcamss->sys_rst[STFRST_PIXEL_CLK_IF0].rstc);
-+
-+      clk_disable_unprepare(stfcamss->sys_clk[STFCLK_PIXEL_CLK_IF3].clk);
-+      clk_disable_unprepare(stfcamss->sys_clk[STFCLK_PIXEL_CLK_IF2].clk);
-+      clk_disable_unprepare(stfcamss->sys_clk[STFCLK_PIXEL_CLK_IF1].clk);
-+      clk_disable_unprepare(stfcamss->sys_clk[STFCLK_PIXEL_CLK_IF0].clk);
-+
-+      return 0;
-+}
-+
-+static void csi2rx_reset(void *reg_base)
-+{
-+      writel(CSI2RX_SOFT_RESET_PROTOCOL | CSI2RX_SOFT_RESET_FRONT,
-+             reg_base + CSI2RX_SOFT_RESET_REG);
-+
-+      udelay(10);
-+
-+      writel(0, reg_base + CSI2RX_SOFT_RESET_REG);
-+}
-+
-+static int csi2rx_start(struct stf_csi_dev *csi_dev, void *reg_base, u32 dt)
-+{
-+      struct stfcamss *stfcamss = csi_dev->stfcamss;
-+      struct csi2phy_cfg *csiphy =
-+              stfcamss->csiphy_dev->csiphy;
-+      unsigned int i;
-+      unsigned long lanes_used = 0;
-+      u32 reg;
-+
-+      if (!csiphy) {
-+              st_err(ST_CSI, "csiphy0 config not exist\n");
-+              return -EINVAL;
-+      }
-+
-+      csi2rx_reset(reg_base);
-+
-+      reg = csiphy->num_data_lanes << 8;
-+      for (i = 0; i < csiphy->num_data_lanes; i++) {
-+#ifndef USE_CSIDPHY_ONE_CLK_MODE
-+              reg |= CSI2RX_STATIC_CFG_DLANE_MAP(i, csiphy->data_lanes[i]);
-+              set_bit(csiphy->data_lanes[i] - 1, &lanes_used);
-+#else
-+              reg |= CSI2RX_STATIC_CFG_DLANE_MAP(i, i + 1);
-+              set_bit(i, &lanes_used);
-+#endif
-+      }
-+
-+      /*
-+       * Even the unused lanes need to be mapped. In order to avoid
-+       * to map twice to the same physical lane, keep the lanes used
-+       * in the previous loop, and only map unused physical lanes to
-+       * the rest of our logical lanes.
-+       */
-+      for (i = csiphy->num_data_lanes; i < CSI2RX_LANES_MAX; i++) {
-+              unsigned int idx = find_first_zero_bit(&lanes_used,
-+                                                     CSI2RX_LANES_MAX);
-+
-+              set_bit(idx, &lanes_used);
-+              reg |= CSI2RX_STATIC_CFG_DLANE_MAP(i, idx + 1);
-+      }
-+
-+      writel(reg, reg_base + CSI2RX_STATIC_CFG_REG);
-+
-+      // 0x40 DPHY_LANE_CONTROL
-+      reg = 0;
-+#ifndef USE_CSIDPHY_ONE_CLK_MODE
-+      for (i = 0; i < csiphy->num_data_lanes; i++)
-+              reg |= 1 << (csiphy->data_lanes[i] - 1)
-+                      | 1 << (csiphy->data_lanes[i] + 11);
-+#else
-+      for (i = 0; i < csiphy->num_data_lanes; i++)
-+              reg |= 1 << i | 1 << (i + 12);          //data_clane
-+#endif
-+
-+      reg |= 1 << 4 | 1 << 16;                //clk_lane
-+      writel(reg, reg_base + CSI2RX_DPHY_LANE_CONTROL);
-+
-+      /*
-+       * Create a static mapping between the CSI virtual channels
-+       * and the output stream.
-+       *
-+       * This should be enhanced, but v4l2 lacks the support for
-+       * changing that mapping dynamically.
-+       *
-+       * We also cannot enable and disable independent streams here,
-+       * hence the reference counting.
-+       */
-+      for (i = 0; i < CSI2RX_STREAMS_MAX; i++) {
-+              writel(CSI2RX_STREAM_CFG_FIFO_MODE_LARGE_BUF,
-+                     reg_base + CSI2RX_STREAM_CFG_REG(i));
-+
-+              writel(CSI2RX_STREAM_DATA_CFG_EN_VC_SELECT |
-+                     CSI2RX_STREAM_DATA_CFG_VC_SELECT(i) |
-+                     CSI2RX_STREAM_DATA_CFG_EN_DATA_TYPE_0 | dt,
-+                     reg_base + CSI2RX_STREAM_DATA_CFG_REG(i));
-+
-+              writel(CSI2RX_STREAM_CTRL_START,
-+                     reg_base + CSI2RX_STREAM_CTRL_REG(i));
-+      }
-+
-+      return 0;
-+}
-+
-+static void csi2rx_stop(struct stf_csi_dev *csi_dev, void *reg_base)
-+{
-+      unsigned int i;
-+
-+      for (i = 0; i < CSI2RX_STREAMS_MAX; i++)
-+              writel(0, reg_base + CSI2RX_STREAM_CTRL_REG(i));
-+}
-+
-+static void csi_set_vin_axiwr_pix(struct stf_csi_dev *csi_dev, u32 width, u8 bpp)
-+{
-+      struct stf_vin_dev *vin = csi_dev->stfcamss->vin;
-+      u32 value = 0;
-+      int cnfg_axiwr_pix_ct = 64 / bpp;
-+
-+      if (cnfg_axiwr_pix_ct == 2)
-+              value = 0;
-+      else if (cnfg_axiwr_pix_ct == 4)
-+              value = 1;
-+      else if (cnfg_axiwr_pix_ct == 8)
-+              value = 2;
-+
-+      reg_set_bit(vin->sysctrl_base, SYSCONSAIF_SYSCFG_28,
-+              BIT(14)|BIT(13), value << 13);  //u0_vin_cnfg_axiwr0_pix_ct
-+      reg_set_bit(vin->sysctrl_base, SYSCONSAIF_SYSCFG_28,
-+              BIT(12)|BIT(11)|BIT(10)|BIT(9)|BIT(8)|BIT(7)|BIT(6)|BIT(5)|BIT(4)|BIT(3)|BIT(2),
-+              (width / cnfg_axiwr_pix_ct - 1)<<2);    //u0_vin_cnfg_axiwr0_pix_cnt_end
-+}
-+
-+static int stf_csi_stream_set(struct stf_csi_dev *csi_dev,
-+                            int on, u32 dt, u32 width, u8 bpp)
-+{
-+      struct stf_vin_dev *vin = csi_dev->stfcamss->vin;
-+      void __iomem *reg_base = vin->csi2rx_base;
-+
-+      switch (csi_dev->s_type) {
-+      case SENSOR_VIN:
-+              reg_set_bit(vin->sysctrl_base, SYSCONSAIF_SYSCFG_20,
-+                      BIT(3)|BIT(2)|BIT(1)|BIT(0),
-+                      0<<0);          //u0_vin_cnfg_axiwr0_channel_sel
-+              reg_set_bit(vin->sysctrl_base, SYSCONSAIF_SYSCFG_28,
-+                      BIT(16)|BIT(15),
-+                      0<<15);         //u0_vin_cnfg_axiwr0_pixel_high_bit_sel
-+              csi_set_vin_axiwr_pix(csi_dev, width, bpp);
-+              break;
-+      case SENSOR_ISP:
-+              reg_set_bit(vin->sysctrl_base,  SYSCONSAIF_SYSCFG_36,
-+                      BIT(7)|BIT(6),
-+                      0<<6);          //u0_vin_cnfg_mipi_byte_en_isp
-+              reg_set_bit(vin->sysctrl_base,  SYSCONSAIF_SYSCFG_36,
-+                      BIT(11)|BIT(10)|BIT(9)|BIT(8),
-+                      0<<8);          //u0_vin_cnfg_mipi_channel_sel0
-+              reg_set_bit(vin->sysctrl_base,  SYSCONSAIF_SYSCFG_36,
-+                      BIT(16)|BIT(15)|BIT(14)|BIT(13),
-+                      0<<13);         //u0_vin_cnfg_pix_num
-+
-+              if (dt == 0x2b)
-+                      reg_set_bit(vin->sysctrl_base,  SYSCONSAIF_SYSCFG_36,
-+                              BIT(12),
-+                              1<<12);         //u0_vin_cnfg_p_i_mipi_header_en0
-+              break;
-+      }
-+
-+      if (on)
-+              csi2rx_start(csi_dev, reg_base, dt);
-+      else
-+              csi2rx_stop(csi_dev, reg_base);
-+
-+      return 0;
-+}
-+
-+void dump_csi_reg(void *__iomem csibase)
-+{
-+      st_info(ST_CSI, "DUMP CSI register:\n");
-+      print_reg(ST_CSI, csibase, 0x00);
-+      print_reg(ST_CSI, csibase, 0x04);
-+      print_reg(ST_CSI, csibase, 0x08);
-+      print_reg(ST_CSI, csibase, 0x10);
-+
-+      print_reg(ST_CSI, csibase, 0x40);
-+      print_reg(ST_CSI, csibase, 0x48);
-+      print_reg(ST_CSI, csibase, 0x4c);
-+      print_reg(ST_CSI, csibase, 0x50);
-+}
-+
-+struct csi_hw_ops csi_ops = {
-+      .csi_power_on          = stf_csi_power_on,
-+      .csi_clk_enable        = stf_csi_clk_enable,
-+      .csi_clk_disable       = stf_csi_clk_disable,
-+      .csi_stream_set        = stf_csi_stream_set,
-+};
---- /dev/null
-+++ b/drivers/media/platform/starfive/v4l2_driver/stf_csiphy.c
-@@ -0,0 +1,357 @@
-+// SPDX-License-Identifier: GPL-2.0
-+/*
-+ * Copyright (C) 2021-2023 StarFive Technology Co., Ltd.
-+ *
-+ */
-+
-+#include "stfcamss.h"
-+#include <media/v4l2-async.h>
-+#include <media/v4l2-ctrls.h>
-+#include <media/v4l2-device.h>
-+#include <media/v4l2-event.h>
-+#include <media/v4l2-fwnode.h>
-+#include <media/v4l2-subdev.h>
-+
-+static const struct csiphy_format csiphy_formats_st7110[] = {
-+      { MEDIA_BUS_FMT_UYVY8_2X8, 16},
-+      { MEDIA_BUS_FMT_SRGGB10_1X10, 10},
-+      { MEDIA_BUS_FMT_SGRBG10_1X10, 10},
-+      { MEDIA_BUS_FMT_SGBRG10_1X10, 10},
-+      { MEDIA_BUS_FMT_SBGGR10_1X10, 10},
-+};
-+
-+int stf_csiphy_subdev_init(struct stfcamss *stfcamss)
-+{
-+      struct stf_csiphy_dev *csiphy_dev = stfcamss->csiphy_dev;
-+
-+      csiphy_dev->hw_ops = &csiphy_ops;
-+      csiphy_dev->stfcamss = stfcamss;
-+      csiphy_dev->formats = csiphy_formats_st7110;
-+      csiphy_dev->nformats = ARRAY_SIZE(csiphy_formats_st7110);
-+      mutex_init(&csiphy_dev->stream_lock);
-+      return 0;
-+}
-+
-+static int csiphy_set_power(struct v4l2_subdev *sd, int on)
-+{
-+      return 0;
-+}
-+
-+static int csiphy_set_stream(struct v4l2_subdev *sd, int enable)
-+{
-+      struct stf_csiphy_dev *csiphy_dev = v4l2_get_subdevdata(sd);
-+
-+      mutex_lock(&csiphy_dev->stream_lock);
-+      if (enable) {
-+              if (csiphy_dev->stream_count == 0) {
-+                      csiphy_dev->hw_ops->csiphy_clk_enable(csiphy_dev);
-+                      csiphy_dev->hw_ops->csiphy_config_set(csiphy_dev);
-+                      csiphy_dev->hw_ops->csiphy_stream_set(csiphy_dev, 1);
-+              }
-+              csiphy_dev->stream_count++;
-+      } else {
-+              if (csiphy_dev->stream_count == 0)
-+                      goto exit;
-+              if (csiphy_dev->stream_count == 1) {
-+                      csiphy_dev->hw_ops->csiphy_clk_disable(csiphy_dev);
-+                      csiphy_dev->hw_ops->csiphy_stream_set(csiphy_dev, 0);
-+              }
-+              csiphy_dev->stream_count--;
-+      }
-+exit:
-+      mutex_unlock(&csiphy_dev->stream_lock);
-+
-+      return 0;
-+}
-+
-+static struct v4l2_mbus_framefmt *
-+__csiphy_get_format(struct stf_csiphy_dev *csiphy_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(
-+                              &csiphy_dev->subdev,
-+                              state,
-+                              pad);
-+
-+      return &csiphy_dev->fmt[pad];
-+}
-+
-+static void csiphy_try_format(struct stf_csiphy_dev *csiphy_dev,
-+                      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_CSIPHY_PAD_SINK:
-+              /* Set format on sink pad */
-+
-+              for (i = 0; i < csiphy_dev->nformats; i++)
-+                      if (fmt->code == csiphy_dev->formats[i].code)
-+                              break;
-+
-+              if (i >= csiphy_dev->nformats)
-+                      fmt->code = csiphy_dev->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_CSIPHY_PAD_SRC:
-+
-+              *fmt = *__csiphy_get_format(csiphy_dev,
-+                              state,
-+                              STF_CSIPHY_PAD_SINK, which);
-+
-+              break;
-+      }
-+}
-+
-+static int csiphy_enum_mbus_code(struct v4l2_subdev *sd,
-+                      struct v4l2_subdev_state *state,
-+                      struct v4l2_subdev_mbus_code_enum *code)
-+{
-+      struct stf_csiphy_dev *csiphy_dev = v4l2_get_subdevdata(sd);
-+
-+      if (code->index >= csiphy_dev->nformats)
-+              return -EINVAL;
-+
-+      if (code->pad == STF_CSIPHY_PAD_SINK) {
-+              code->code = csiphy_dev->formats[code->index].code;
-+      } else {
-+              struct v4l2_mbus_framefmt *sink_fmt;
-+
-+              sink_fmt = __csiphy_get_format(csiphy_dev, state,
-+                                      STF_CSIPHY_PAD_SINK,
-+                                      code->which);
-+
-+              code->code = sink_fmt->code;
-+              if (!code->code)
-+                      return -EINVAL;
-+      }
-+      code->flags = 0;
-+      return 0;
-+}
-+
-+static int csiphy_enum_frame_size(struct v4l2_subdev *sd,
-+                              struct v4l2_subdev_state *state,
-+                              struct v4l2_subdev_frame_size_enum *fse)
-+{
-+      struct stf_csiphy_dev *csiphy_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;
-+      csiphy_try_format(csiphy_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;
-+      csiphy_try_format(csiphy_dev, state, fse->pad, &format, fse->which);
-+      fse->max_width = format.width;
-+      fse->max_height = format.height;
-+
-+      return 0;
-+}
-+
-+static int csiphy_get_format(struct v4l2_subdev *sd,
-+                      struct v4l2_subdev_state *state,
-+                      struct v4l2_subdev_format *fmt)
-+{
-+      struct stf_csiphy_dev *csiphy_dev = v4l2_get_subdevdata(sd);
-+      struct v4l2_mbus_framefmt *format;
-+
-+      format = __csiphy_get_format(csiphy_dev, state, fmt->pad, fmt->which);
-+      if (format == NULL)
-+              return -EINVAL;
-+
-+      fmt->format = *format;
-+
-+      return 0;
-+}
-+
-+static int csiphy_set_format(struct v4l2_subdev *sd,
-+                      struct v4l2_subdev_state *state,
-+                      struct v4l2_subdev_format *fmt)
-+{
-+      struct stf_csiphy_dev *csiphy_dev = v4l2_get_subdevdata(sd);
-+      struct v4l2_mbus_framefmt *format;
-+
-+      format = __csiphy_get_format(csiphy_dev, state, fmt->pad, fmt->which);
-+      if (format == NULL)
-+              return -EINVAL;
-+
-+      mutex_lock(&csiphy_dev->stream_lock);
-+      if (csiphy_dev->stream_count) {
-+              fmt->format = *format;
-+              mutex_unlock(&csiphy_dev->stream_lock);
-+              goto out;
-+      } else {
-+              csiphy_try_format(csiphy_dev, state, fmt->pad, &fmt->format, fmt->which);
-+              *format = fmt->format;
-+      }
-+      mutex_unlock(&csiphy_dev->stream_lock);
-+
-+      /* Propagate the format from sink to source */
-+      if (fmt->pad == STF_CSIPHY_PAD_SINK) {
-+              format = __csiphy_get_format(csiphy_dev,
-+                                      state,
-+                                      STF_CSIPHY_PAD_SRC,
-+                                      fmt->which);
-+
-+              *format = fmt->format;
-+              csiphy_try_format(csiphy_dev, state, STF_CSIPHY_PAD_SRC, format,
-+                                      fmt->which);
-+      }
-+out:
-+      return 0;
-+}
-+
-+static int csiphy_init_formats(struct v4l2_subdev *sd,
-+                      struct v4l2_subdev_fh *fh)
-+{
-+      struct v4l2_subdev_format format = {
-+              .pad = STF_CSIPHY_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 csiphy_set_format(sd, fh ? fh->state : NULL, &format);
-+}
-+
-+static int csiphy_link_setup(struct media_entity *entity,
-+                      const struct media_pad *local,
-+                      const struct media_pad *remote, u32 flags)
-+{
-+      if ((local->flags & MEDIA_PAD_FL_SOURCE) &&
-+              (flags & MEDIA_LNK_FL_ENABLED)) {
-+              struct v4l2_subdev *sd;
-+              struct stf_csiphy_dev *csiphy_dev;
-+              struct stf_csi_dev *csi_dev;
-+
-+              if (media_pad_remote_pad_first(local))
-+                      return -EBUSY;
-+
-+              sd = media_entity_to_v4l2_subdev(entity);
-+              csiphy_dev = v4l2_get_subdevdata(sd);
-+
-+              sd = media_entity_to_v4l2_subdev(remote->entity);
-+              csi_dev = v4l2_get_subdevdata(sd);
-+              st_info(ST_CSIPHY, "CSIPHY0 link to CSI0\n");
-+      }
-+
-+      return 0;
-+}
-+
-+static const struct v4l2_subdev_core_ops csiphy_core_ops = {
-+      .s_power = csiphy_set_power,
-+};
-+
-+static const struct v4l2_subdev_video_ops csiphy_video_ops = {
-+      .s_stream = csiphy_set_stream,
-+};
-+
-+static const struct v4l2_subdev_pad_ops csiphy_pad_ops = {
-+      .enum_mbus_code = csiphy_enum_mbus_code,
-+      .enum_frame_size = csiphy_enum_frame_size,
-+      .get_fmt = csiphy_get_format,
-+      .set_fmt = csiphy_set_format,
-+};
-+
-+static const struct v4l2_subdev_ops csiphy_v4l2_ops = {
-+      .core = &csiphy_core_ops,
-+      .video = &csiphy_video_ops,
-+      .pad = &csiphy_pad_ops,
-+};
-+
-+static const struct v4l2_subdev_internal_ops csiphy_v4l2_internal_ops = {
-+      .open = csiphy_init_formats,
-+};
-+
-+static const struct media_entity_operations csiphy_media_ops = {
-+      .link_setup = csiphy_link_setup,
-+      .link_validate = v4l2_subdev_link_validate,
-+};
-+
-+int stf_csiphy_register(struct stf_csiphy_dev *csiphy_dev,
-+                      struct v4l2_device *v4l2_dev)
-+{
-+      struct v4l2_subdev *sd = &csiphy_dev->subdev;
-+      struct device *dev = csiphy_dev->stfcamss->dev;
-+      struct media_pad *pads = csiphy_dev->pads;
-+      int ret;
-+
-+      v4l2_subdev_init(sd, &csiphy_v4l2_ops);
-+      sd->internal_ops = &csiphy_v4l2_internal_ops;
-+      sd->flags |= V4L2_SUBDEV_FL_HAS_DEVNODE;
-+      snprintf(sd->name, ARRAY_SIZE(sd->name), "%s%d",
-+              STF_CSIPHY_NAME, 0);
-+      v4l2_set_subdevdata(sd, csiphy_dev);
-+
-+      ret = csiphy_init_formats(sd, NULL);
-+      if (ret < 0) {
-+              dev_err(dev, "Failed to init format: %d\n", ret);
-+              return ret;
-+      }
-+
-+      pads[STF_CSIPHY_PAD_SINK].flags = MEDIA_PAD_FL_SINK;
-+      pads[STF_CSIPHY_PAD_SRC].flags = MEDIA_PAD_FL_SOURCE;
-+
-+      sd->entity.function = MEDIA_ENT_F_PROC_VIDEO_PIXEL_FORMATTER;
-+      sd->entity.ops = &csiphy_media_ops;
-+      ret = media_entity_pads_init(&sd->entity, STF_CSIPHY_PADS_NUM, pads);
-+      if (ret < 0) {
-+              dev_err(dev, "Failed to init media entity: %d\n", ret);
-+              return ret;
-+      }
-+
-+      ret = v4l2_device_register_subdev(v4l2_dev, sd);
-+      if (ret < 0) {
-+              dev_err(dev, "Failed to register subdev: %d\n", ret);
-+              goto err_sreg;
-+      }
-+
-+      return 0;
-+
-+err_sreg:
-+      media_entity_cleanup(&sd->entity);
-+      return ret;
-+}
-+
-+int stf_csiphy_unregister(struct stf_csiphy_dev *csiphy_dev)
-+{
-+      v4l2_device_unregister_subdev(&csiphy_dev->subdev);
-+      media_entity_cleanup(&csiphy_dev->subdev.entity);
-+      mutex_destroy(&csiphy_dev->stream_lock);
-+      return 0;
-+}
---- /dev/null
-+++ b/drivers/media/platform/starfive/v4l2_driver/stf_csiphy.h
-@@ -0,0 +1,188 @@
-+/* SPDX-License-Identifier: GPL-2.0
-+ *
-+ * Copyright (C) 2021-2023 StarFive Technology Co., Ltd.
-+ *
-+ */
-+
-+#ifndef STF_CSIPHY_H
-+#define STF_CSIPHY_H
-+
-+#include <media/v4l2-subdev.h>
-+#include <media/v4l2-device.h>
-+#include <media/media-entity.h>
-+#include <video/stf-vin.h>
-+
-+#define STF_CSIPHY_NAME "stf_csiphy"
-+
-+#define STF_CSIPHY_PAD_SINK     0
-+#define STF_CSIPHY_PAD_SRC      1
-+#define STF_CSIPHY_PADS_NUM     2
-+
-+#define STF_CSI2_MAX_DATA_LANES      4
-+
-+union static_config {
-+      u32 raw;
-+      struct {
-+              u32 sel                 : 2;
-+              u32 rsvd_6              : 2;
-+              u32 v2p0_support_enable : 1;
-+              u32 rsvd_5              : 3;
-+              u32 lane_nb             : 3;
-+              u32 rsvd_4              : 5;
-+              u32 dl0_map             : 3;
-+              u32 rsvd_3              : 1;
-+              u32 dl1_map             : 3;
-+              u32 rsvd_2              : 1;
-+              u32 dl2_map             : 3;
-+              u32 rsvd_1              : 1;
-+              u32 dl3_map             : 3;
-+              u32 rsvd_0              : 1;
-+      } bits;
-+};
-+
-+union error_bypass_cfg {
-+      u32 value;
-+      struct {
-+              u32 crc             :  1;
-+              u32 ecc             :  1;
-+              u32 data_id         :  1;
-+              u32 rsvd_0          : 29;
-+      };
-+};
-+
-+union stream_monitor_ctrl {
-+      u32 value;
-+      struct {
-+              u32 lb_vc             : 4;
-+              u32 lb_en             : 1;
-+              u32 timer_vc          : 4;
-+              u32 timer_en          : 1;
-+              u32 timer_eof         : 1;
-+              u32 frame_mon_vc      : 4;
-+              u32 frame_mon_en      : 1;
-+              u32 frame_length      : 16;
-+      };
-+};
-+
-+union stream_cfg {
-+      u32 value;
-+      struct {
-+              u32 interface_mode :  1;
-+              u32 ls_le_mode     :  1;
-+              u32 rsvd_3         :  2;
-+              u32 num_pixels     :  2;
-+              u32 rsvd_2         :  2;
-+              u32 fifo_mode      :  2;
-+              u32 rsvd_1         :  2;
-+              u32 bpp_bypass     :  3;
-+              u32 rsvd_0         :  1;
-+              u32 fifo_fill      : 16;
-+      };
-+};
-+
-+union dphy_lane_ctrl {
-+      u32 raw;
-+      struct {
-+              u32 dl0_en    : 1;
-+              u32 dl1_en    : 1;
-+              u32 dl2_en    : 1;
-+              u32 dl3_en    : 1;
-+              u32 cl_en     : 1;
-+              u32 rsvd_1    : 7;
-+              u32 dl0_reset : 1;
-+              u32 dl1_reset : 1;
-+              u32 dl2_reset : 1;
-+              u32 dl3_reset : 1;
-+              u32 cl_reset  : 1;
-+              u32 rsvd_0    : 15;
-+      } bits;
-+};
-+
-+union dphy_lane_swap {
-+      u32 raw;
-+      struct {
-+              u32 rx_1c2c_sel        : 1;
-+              u32 lane_swap_clk      : 3;
-+              u32 lane_swap_clk1     : 3;
-+              u32 lane_swap_lan0     : 3;
-+              u32 lane_swap_lan1     : 3;
-+              u32 lane_swap_lan2     : 3;
-+              u32 lane_swap_lan3     : 3;
-+              u32 dpdn_swap_clk      : 1;
-+              u32 dpdn_swap_clk1     : 1;
-+              u32 dpdn_swap_lan0     : 1;
-+              u32 dpdn_swap_lan1     : 1;
-+              u32 dpdn_swap_lan2     : 1;
-+              u32 dpdn_swap_lan3     : 1;
-+              u32 hs_freq_chang_clk0 : 1;
-+              u32 hs_freq_chang_clk1 : 1;
-+              u32 reserved           : 5;
-+      } bits;
-+};
-+
-+union dphy_lane_en {
-+      u32 raw;
-+      struct {
-+              u32 gpio_en             : 6;
-+              u32 mp_test_mode_sel    : 5;
-+              u32 mp_test_en          : 1;
-+              u32 dphy_enable_lan0    : 1;
-+              u32 dphy_enable_lan1    : 1;
-+              u32 dphy_enable_lan2    : 1;
-+              u32 dphy_enable_lan3    : 1;
-+              u32 rsvd_0              : 16;
-+      } bits;
-+};
-+
-+struct csiphy_format {
-+      u32 code;
-+      u8 bpp;
-+};
-+
-+struct csi2phy_cfg {
-+      unsigned int flags;
-+      unsigned char data_lanes[STF_CSI2_MAX_DATA_LANES];
-+      unsigned char clock_lane;
-+      unsigned char num_data_lanes;
-+      bool lane_polarities[1 + STF_CSI2_MAX_DATA_LANES];
-+};
-+
-+struct csi2phy_cfg2 {
-+      unsigned char data_lanes[STF_CSI2_MAX_DATA_LANES];
-+      unsigned char num_data_lanes;
-+      unsigned char num_clks;
-+      unsigned char clock_lane;
-+      unsigned char clock1_lane;
-+      bool lane_polarities[2 + STF_CSI2_MAX_DATA_LANES];
-+};
-+
-+struct stf_csiphy_dev;
-+
-+struct csiphy_hw_ops {
-+      int (*csiphy_clk_enable)(struct stf_csiphy_dev *csiphy_dev);
-+      int (*csiphy_clk_disable)(struct stf_csiphy_dev *csiphy_dev);
-+      int (*csiphy_config_set)(struct stf_csiphy_dev *csiphy_dev);
-+      int (*csiphy_stream_set)(struct stf_csiphy_dev *csiphy_dev, int on);
-+};
-+
-+struct stf_csiphy_dev {
-+      struct stfcamss *stfcamss;
-+      struct csi2phy_cfg *csiphy;
-+      struct v4l2_subdev subdev;
-+      struct media_pad pads[STF_CSIPHY_PADS_NUM];
-+      struct v4l2_mbus_framefmt fmt[STF_CSIPHY_PADS_NUM];
-+      const struct csiphy_format *formats;
-+      unsigned int nformats;
-+      struct csiphy_hw_ops *hw_ops;
-+      struct mutex stream_lock;
-+      int stream_count;
-+};
-+
-+extern int stf_csiphy_subdev_init(struct stfcamss *stfcamss);
-+extern int stf_csiphy_register(struct stf_csiphy_dev *csiphy_dev,
-+                      struct v4l2_device *v4l2_dev);
-+extern int stf_csiphy_unregister(struct stf_csiphy_dev *csiphy_dev);
-+
-+extern struct csiphy_hw_ops csiphy_ops;
-+
-+#endif /* STF_CSIPHY_H */
---- /dev/null
-+++ b/drivers/media/platform/starfive/v4l2_driver/stf_csiphy_hw_ops.c
-@@ -0,0 +1,335 @@
-+// SPDX-License-Identifier: GPL-2.0
-+/*
-+ * Copyright (C) 2021-2023 StarFive Technology Co., Ltd.
-+ *
-+ */
-+
-+#include "stfcamss.h"
-+#include <linux/sort.h>
-+
-+static int stf_csiphy_clk_set(struct stf_csiphy_dev *csiphy_dev, int on)
-+{
-+      struct stfcamss *stfcamss = csiphy_dev->stfcamss;
-+      static int init_flag;
-+      static struct mutex count_lock;
-+      static int count;
-+
-+      if (!init_flag) {
-+              init_flag = 1;
-+              mutex_init(&count_lock);
-+      }
-+      mutex_lock(&count_lock);
-+      if (on) {
-+              clk_set_rate(stfcamss->sys_clk[STFCLK_M31DPHY_CFGCLK_IN].clk,
-+                      99000000);
-+              clk_set_rate(stfcamss->sys_clk[STFCLK_M31DPHY_REFCLK_IN].clk,
-+                      49500000);
-+              clk_set_rate(stfcamss->sys_clk[STFCLK_M31DPHY_TXCLKESC_LAN0].clk,
-+                      19800000);
-+
-+              reset_control_deassert(stfcamss->sys_rst[STFRST_M31DPHY_HW].rstc);
-+              reset_control_deassert(stfcamss->sys_rst[STFRST_M31DPHY_B09_ALWAYS_ON].rstc);
-+
-+              count++;
-+      } else {
-+              if (count == 0)
-+                      goto exit;
-+              if (count == 1) {
-+                      reset_control_assert(stfcamss->sys_rst[STFRST_M31DPHY_HW].rstc);
-+                      reset_control_assert(stfcamss->sys_rst[STFRST_M31DPHY_B09_ALWAYS_ON].rstc);
-+              }
-+              count--;
-+      }
-+exit:
-+      mutex_unlock(&count_lock);
-+      return 0;
-+}
-+
-+static int stf_csiphy_clk_enable(struct stf_csiphy_dev *csiphy_dev)
-+{
-+      return stf_csiphy_clk_set(csiphy_dev, 1);
-+}
-+
-+static int stf_csiphy_clk_disable(struct stf_csiphy_dev *csiphy_dev)
-+{
-+      return stf_csiphy_clk_set(csiphy_dev, 0);
-+}
-+
-+#ifndef USE_CSIDPHY_ONE_CLK_MODE
-+static int cmp_func(const void *x1, const void *x2)
-+{
-+      return *((unsigned char *)x1) - *((unsigned char *)x2);
-+}
-+#endif
-+
-+int try_cfg(struct csi2phy_cfg2 *cfg, struct csi2phy_cfg *cfg0,
-+              struct csi2phy_cfg *cfg1)
-+{
-+      int i = 0;
-+
-+      cfg->clock_lane = 0;
-+      cfg->clock1_lane = 5;
-+      cfg->data_lanes[0] = 1;
-+      cfg->data_lanes[1] = 2;
-+      cfg->data_lanes[2] = 3;
-+      cfg->data_lanes[3] = 4;
-+
-+      if (cfg0 && cfg1) {
-+              st_debug(ST_CSIPHY, "CSIPHY use 2 clk mode\n");
-+              cfg->num_clks = 2;
-+              cfg->num_data_lanes =
-+                      cfg1->num_data_lanes + cfg0->num_data_lanes;
-+              if (cfg->num_data_lanes > STF_CSI2_MAX_DATA_LANES)
-+                      return -EINVAL;
-+              cfg->clock_lane = cfg0->clock_lane;
-+              cfg->lane_polarities[0] = cfg0->lane_polarities[0];
-+              cfg->clock1_lane = cfg1->clock_lane;
-+              cfg->lane_polarities[1] = cfg1->lane_polarities[0];
-+              for (i = 0; i < cfg0->num_data_lanes; i++) {
-+                      cfg->data_lanes[i] = cfg0->data_lanes[i];
-+                      cfg->lane_polarities[i + 2] =
-+                              cfg0->lane_polarities[i + 1];
-+              }
-+
-+              for (i = cfg0->num_data_lanes; i < cfg->num_data_lanes; i++) {
-+                      cfg->data_lanes[i] =
-+                              cfg1->data_lanes[i - cfg0->num_data_lanes];
-+                      cfg->lane_polarities[i + 2] =
-+                              cfg1->lane_polarities[i - cfg0->num_data_lanes + 1];
-+              }
-+      } else if (cfg0 && !cfg1) {
-+              st_debug(ST_CSIPHY, "CSIPHY cfg0 use 1 clk mode\n");
-+              cfg->num_clks = 1;
-+              cfg->num_data_lanes = cfg0->num_data_lanes;
-+              cfg->clock_lane = cfg->clock1_lane  = cfg0->clock_lane;
-+              cfg->lane_polarities[0] = cfg->lane_polarities[1] =
-+                                              cfg0->lane_polarities[0];
-+              for (i = 0; i < cfg0->num_data_lanes; i++) {
-+                      cfg->data_lanes[i] = cfg0->data_lanes[i];
-+                      cfg->lane_polarities[i + 2] = cfg0->lane_polarities[i + 1];
-+              }
-+      } else if (!cfg0 && cfg1) {
-+              st_debug(ST_CSIPHY, "CSIPHY cfg1 use 1 clk mode\n");
-+              cfg->num_clks = 1;
-+              cfg->num_data_lanes = cfg1->num_data_lanes;
-+              cfg->clock_lane = cfg->clock1_lane  = cfg1->clock_lane;
-+              cfg->lane_polarities[0] = cfg->lane_polarities[1] =
-+                                              cfg1->lane_polarities[0];
-+              for (i = 0; i < cfg1->num_data_lanes; i++) {
-+                      cfg->data_lanes[i] = cfg1->data_lanes[i];
-+                      cfg->lane_polarities[i + 2] = cfg1->lane_polarities[i + 1];
-+              }
-+      } else {
-+              return -EINVAL;
-+      }
-+
-+#ifndef USE_CSIDPHY_ONE_CLK_MODE
-+      sort(cfg->data_lanes, cfg->num_data_lanes,
-+                      sizeof(cfg->data_lanes[0]), cmp_func, NULL);
-+#endif
-+      for (i = 0; i < cfg->num_data_lanes; i++)
-+              st_debug(ST_CSIPHY, "%d: %d\n", i, cfg->data_lanes[i]);
-+      return 0;
-+}
-+
-+static int csi2rx_dphy_config(struct stf_vin_dev *vin,
-+              struct stf_csiphy_dev *csiphy_dev)
-+{
-+      struct csi2phy_cfg2 cfg2 = {0};
-+      struct csi2phy_cfg2 *cfg = &cfg2;
-+      struct csi2phy_cfg *phycfg = csiphy_dev->csiphy;
-+
-+      if (!phycfg)
-+              return -EINVAL;
-+
-+      if (try_cfg(cfg, phycfg, NULL))
-+              return -EINVAL;
-+
-+      reg_write(vin->rstgen_base, M31DPHY_APBCFGSAIF__SYSCFG_4, 0x0);
-+      reg_write(vin->rstgen_base, M31DPHY_APBCFGSAIF__SYSCFG_8, 0x0);
-+      reg_write(vin->rstgen_base, M31DPHY_APBCFGSAIF__SYSCFG_12, 0xfff0);
-+      reg_write(vin->rstgen_base, M31DPHY_APBCFGSAIF__SYSCFG_16, 0x0);
-+      reg_write(vin->rstgen_base, M31DPHY_APBCFGSAIF__SYSCFG_20, 0x0);
-+      reg_write(vin->rstgen_base, M31DPHY_APBCFGSAIF__SYSCFG_24, 0x0);
-+      reg_write(vin->rstgen_base, M31DPHY_APBCFGSAIF__SYSCFG_28, 0x0);
-+      reg_write(vin->rstgen_base, M31DPHY_APBCFGSAIF__SYSCFG_32, 0x0);
-+      reg_write(vin->rstgen_base, M31DPHY_APBCFGSAIF__SYSCFG_36, 0x0);
-+      reg_write(vin->rstgen_base, M31DPHY_APBCFGSAIF__SYSCFG_40, 0x0);
-+      reg_write(vin->rstgen_base, M31DPHY_APBCFGSAIF__SYSCFG_44, 0x0);
-+      reg_write(vin->rstgen_base, M31DPHY_APBCFGSAIF__SYSCFG_48, 0x24000000);
-+      reg_write(vin->rstgen_base, M31DPHY_APBCFGSAIF__SYSCFG_52, 0x0);
-+      reg_write(vin->rstgen_base, M31DPHY_APBCFGSAIF__SYSCFG_56, 0x0);
-+      reg_write(vin->rstgen_base, M31DPHY_APBCFGSAIF__SYSCFG_60, 0x0);
-+      reg_write(vin->rstgen_base, M31DPHY_APBCFGSAIF__SYSCFG_64, 0x0);
-+      reg_write(vin->rstgen_base, M31DPHY_APBCFGSAIF__SYSCFG_68, 0x0);
-+      reg_write(vin->rstgen_base, M31DPHY_APBCFGSAIF__SYSCFG_72, 0x0);
-+      reg_write(vin->rstgen_base, M31DPHY_APBCFGSAIF__SYSCFG_76, 0x0);
-+      reg_write(vin->rstgen_base, M31DPHY_APBCFGSAIF__SYSCFG_80, 0x0);
-+      reg_write(vin->rstgen_base, M31DPHY_APBCFGSAIF__SYSCFG_84, 0x0);
-+      reg_write(vin->rstgen_base, M31DPHY_APBCFGSAIF__SYSCFG_88, 0x0);
-+      reg_write(vin->rstgen_base, M31DPHY_APBCFGSAIF__SYSCFG_92, 0x0);
-+      reg_write(vin->rstgen_base, M31DPHY_APBCFGSAIF__SYSCFG_96, 0x0);
-+      reg_write(vin->rstgen_base, M31DPHY_APBCFGSAIF__SYSCFG_100, 0x02000000);
-+      reg_write(vin->rstgen_base, M31DPHY_APBCFGSAIF__SYSCFG_104, 0x0);
-+      reg_write(vin->rstgen_base, M31DPHY_APBCFGSAIF__SYSCFG_108, 0x0);
-+      reg_write(vin->rstgen_base, M31DPHY_APBCFGSAIF__SYSCFG_112, 0x0);
-+      reg_write(vin->rstgen_base, M31DPHY_APBCFGSAIF__SYSCFG_116, 0x0);
-+      reg_write(vin->rstgen_base, M31DPHY_APBCFGSAIF__SYSCFG_120, 0x0);
-+      reg_write(vin->rstgen_base, M31DPHY_APBCFGSAIF__SYSCFG_124, 0xc);
-+      reg_write(vin->rstgen_base, M31DPHY_APBCFGSAIF__SYSCFG_128, 0x0);
-+      reg_write(vin->rstgen_base, M31DPHY_APBCFGSAIF__SYSCFG_132, 0xcc500000);
-+      reg_write(vin->rstgen_base, M31DPHY_APBCFGSAIF__SYSCFG_136, 0xcc);
-+      reg_write(vin->rstgen_base, M31DPHY_APBCFGSAIF__SYSCFG_140, 0x0);
-+      reg_write(vin->rstgen_base, M31DPHY_APBCFGSAIF__SYSCFG_144, 0x0);
-+
-+      reg_set_bit(vin->rstgen_base,           //r100_ctrl0_2d1c_efuse_en
-+              M31DPHY_APBCFGSAIF__SYSCFG_0,
-+              BIT(6), 1<<6);
-+      reg_set_bit(vin->rstgen_base,           //r100_ctrl0_2d1c_efuse_in
-+              M31DPHY_APBCFGSAIF__SYSCFG_0,
-+              BIT(12)|BIT(11)|BIT(10)|BIT(9)|BIT(8)|BIT(7), 0x1b<<7);
-+      reg_set_bit(vin->rstgen_base,           //r100_ctrl1_2d1c_efuse_en
-+              M31DPHY_APBCFGSAIF__SYSCFG_0,
-+              BIT(13), 1<<13);
-+      reg_set_bit(vin->rstgen_base,           //r100_ctrl1_2d1c_efuse_in
-+              M31DPHY_APBCFGSAIF__SYSCFG_0,
-+              BIT(19)|BIT(18)|BIT(17)|BIT(16)|BIT(15)|BIT(14), 0x1b<<14);
-+
-+      reg_set_bit(vin->rstgen_base,           //data_bus16_8
-+              M31DPHY_APBCFGSAIF__SYSCFG_184,
-+              BIT(8), 0<<8);
-+
-+      reg_set_bit(vin->rstgen_base,           //debug_mode_sel
-+              M31DPHY_APBCFGSAIF__SYSCFG_184,
-+              BIT(15)|BIT(14)|BIT(13)|BIT(12)|BIT(11)|BIT(10)|BIT(9), 0x5a<<9);
-+
-+      reg_set_bit(vin->rstgen_base,                   //dpdn_swap_clk0
-+              M31DPHY_APBCFGSAIF__SYSCFG_188,
-+              BIT(0), cfg->lane_polarities[0]<<0);
-+      reg_set_bit(vin->rstgen_base,                   //dpdn_swap_clk1
-+              M31DPHY_APBCFGSAIF__SYSCFG_188,
-+              BIT(1), cfg->lane_polarities[1]<<1);
-+      reg_set_bit(vin->rstgen_base,                   //dpdn_swap_lan0
-+              M31DPHY_APBCFGSAIF__SYSCFG_188,
-+              BIT(2), cfg->lane_polarities[2]<<2);
-+      reg_set_bit(vin->rstgen_base,                   //dpdn_swap_lan1
-+              M31DPHY_APBCFGSAIF__SYSCFG_188,
-+              BIT(3), cfg->lane_polarities[3]<<3);
-+      reg_set_bit(vin->rstgen_base,                   //dpdn_swap_lan2
-+              M31DPHY_APBCFGSAIF__SYSCFG_188,
-+              BIT(4), cfg->lane_polarities[4]<<4);
-+      reg_set_bit(vin->rstgen_base,                   //dpdn_swap_lan3
-+              M31DPHY_APBCFGSAIF__SYSCFG_188,
-+              BIT(5), cfg->lane_polarities[5]<<5);
-+      reg_set_bit(vin->rstgen_base,                   //enable clk0
-+              M31DPHY_APBCFGSAIF__SYSCFG_188,
-+              BIT(6), 1<<6);
-+      reg_set_bit(vin->rstgen_base,                   //enable clk1
-+              M31DPHY_APBCFGSAIF__SYSCFG_188,
-+              BIT(7), 1<<7);
-+      reg_set_bit(vin->rstgen_base,                   //enable lan0
-+              M31DPHY_APBCFGSAIF__SYSCFG_188,
-+              BIT(8), 1<<8);
-+      reg_set_bit(vin->rstgen_base,                   //enable lan1
-+              M31DPHY_APBCFGSAIF__SYSCFG_188,
-+              BIT(9), 1<<9);
-+      reg_set_bit(vin->rstgen_base,                   //enable lan2
-+              M31DPHY_APBCFGSAIF__SYSCFG_188,
-+              BIT(10), 1<<10);
-+      reg_set_bit(vin->rstgen_base,                   //enable lan3
-+              M31DPHY_APBCFGSAIF__SYSCFG_188,
-+              BIT(11), 1<<11);
-+      reg_set_bit(vin->rstgen_base,                   //gpi_en
-+              M31DPHY_APBCFGSAIF__SYSCFG_188,
-+              BIT(17)|BIT(16)|BIT(15)|BIT(14)|BIT(13)|BIT(12),
-+              0<<12);
-+      reg_set_bit(vin->rstgen_base,                   //hs_freq_change_clk0
-+              M31DPHY_APBCFGSAIF__SYSCFG_188,
-+              BIT(18), 0<<18);
-+      reg_set_bit(vin->rstgen_base,                   //hs_freq_change_clk1
-+              M31DPHY_APBCFGSAIF__SYSCFG_188,
-+              BIT(19), 0<<19);
-+
-+      reg_set_bit(vin->rstgen_base,
-+              M31DPHY_APBCFGSAIF__SYSCFG_188,
-+              BIT(22)|BIT(21)|BIT(20), cfg->clock_lane<<20);          //clock lane 0
-+      reg_set_bit(vin->rstgen_base,
-+              M31DPHY_APBCFGSAIF__SYSCFG_188,
-+              BIT(25)|BIT(24)|BIT(23), cfg->clock1_lane<<23);         //clock lane 1
-+
-+      reg_set_bit(vin->rstgen_base,
-+              M31DPHY_APBCFGSAIF__SYSCFG_188,
-+              BIT(28)|BIT(27)|BIT(26), cfg->data_lanes[0]<<26);       //data lane 0
-+      reg_set_bit(vin->rstgen_base,
-+              M31DPHY_APBCFGSAIF__SYSCFG_188,
-+              BIT(31)|BIT(30)|BIT(29), cfg->data_lanes[1]<<29);       //data lane 1
-+      reg_set_bit(vin->rstgen_base,
-+              M31DPHY_APBCFGSAIF__SYSCFG_192,
-+              BIT(2)|BIT(1)|BIT(0), cfg->data_lanes[2]<<0);           //data lane 2
-+      reg_set_bit(vin->rstgen_base,
-+              M31DPHY_APBCFGSAIF__SYSCFG_192,
-+              BIT(5)|BIT(4)|BIT(3), cfg->data_lanes[3]<<3);           //data lane 3
-+
-+      reg_set_bit(vin->rstgen_base,           //mp_test_en
-+              M31DPHY_APBCFGSAIF__SYSCFG_192,
-+              BIT(6), 0<<6);
-+      reg_set_bit(vin->rstgen_base,           //mp_test_mode_sel
-+              M31DPHY_APBCFGSAIF__SYSCFG_192,
-+              BIT(11)|BIT(10)|BIT(9)|BIT(8)|BIT(7), 0<<7);
-+
-+      reg_set_bit(vin->rstgen_base,           //pll_clk_sel
-+              M31DPHY_APBCFGSAIF__SYSCFG_192,
-+              BIT(20)|BIT(19)|BIT(18)|BIT(17)|BIT(16)|BIT(15)|BIT(14)|BIT(13)|BIT(12),
-+              0x37c<<12);
-+
-+      reg_set_bit(vin->rstgen_base,           //rx_1c2c_sel
-+              M31DPHY_APBCFGSAIF__SYSCFG_200,
-+              BIT(8), 0<<8);
-+
-+      reg_set_bit(vin->rstgen_base,           //precounter in clk0
-+              M31DPHY_APBCFGSAIF__SYSCFG_192,
-+              BIT(29)|BIT(28)|BIT(27)|BIT(26)|BIT(25)|BIT(24)|BIT(23)|BIT(22),
-+              8<<22);
-+      reg_set_bit(vin->rstgen_base,           //precounter in clk1
-+              M31DPHY_APBCFGSAIF__SYSCFG_196,
-+              BIT(7)|BIT(6)|BIT(5)|BIT(4)|BIT(3)|BIT(2)|BIT(1)|BIT(0),
-+              8<<0);
-+      reg_set_bit(vin->rstgen_base,           //precounter in lan0
-+              M31DPHY_APBCFGSAIF__SYSCFG_196,
-+              BIT(15)|BIT(14)|BIT(13)|BIT(12)|BIT(11)|BIT(10)|BIT(9)|BIT(8),
-+              7<<8);
-+      reg_set_bit(vin->rstgen_base,           //precounter in lan1
-+              M31DPHY_APBCFGSAIF__SYSCFG_196,
-+              BIT(23)|BIT(22)|BIT(21)|BIT(20)|BIT(19)|BIT(18)|BIT(17)|BIT(16),
-+              7<<16);
-+      reg_set_bit(vin->rstgen_base,           //precounter in lan2
-+              M31DPHY_APBCFGSAIF__SYSCFG_196,
-+              BIT(31)|BIT(30)|BIT(29)|BIT(28)|BIT(27)|BIT(26)|BIT(25)|BIT(24),
-+              7<<24);
-+      reg_set_bit(vin->rstgen_base,           //precounter in lan3
-+              M31DPHY_APBCFGSAIF__SYSCFG_200,
-+              BIT(7)|BIT(6)|BIT(5)|BIT(4)|BIT(3)|BIT(2)|BIT(1)|BIT(0),
-+              7<<0);
-+
-+      return 0;
-+}
-+
-+static int stf_csiphy_config_set(struct stf_csiphy_dev *csiphy_dev)
-+{
-+      struct stf_vin_dev *vin = csiphy_dev->stfcamss->vin;
-+
-+      csi2rx_dphy_config(vin, csiphy_dev);
-+      return 0;
-+}
-+
-+static int stf_csiphy_stream_set(struct stf_csiphy_dev *csiphy_dev, int on)
-+{
-+      return 0;
-+}
-+
-+struct csiphy_hw_ops csiphy_ops = {
-+      .csiphy_clk_enable        = stf_csiphy_clk_enable,
-+      .csiphy_clk_disable       = stf_csiphy_clk_disable,
-+      .csiphy_config_set        = stf_csiphy_config_set,
-+      .csiphy_stream_set        = stf_csiphy_stream_set,
-+};
---- /dev/null
-+++ b/drivers/media/platform/starfive/v4l2_driver/stf_dmabuf.c
-@@ -0,0 +1,123 @@
-+// SPDX-License-Identifier: GPL-2.0
-+/*
-+ * Copyright (C) 2021-2023 StarFive Technology Co., Ltd.
-+ *
-+ */
-+
-+#include <linux/dma-buf.h>
-+#include <media/v4l2-subdev.h>
-+#include <media/videobuf2-dma-contig.h>
-+
-+#include "stf_isp_ioctl.h"
-+#include "stf_dmabuf.h"
-+
-+#define TOTAL_SIZE_LIMIT      (64 * 1024 * 1024)
-+
-+static size_t total_size;
-+static struct vb2_queue       vb2_queue = {
-+      .dma_attrs = 0,
-+      .gfp_flags = 0,
-+      .dma_dir = DMA_TO_DEVICE,
-+};
-+static struct vb2_buffer vb = {
-+      .vb2_queue = &vb2_queue,
-+};
-+
-+static int dmabuf_create(struct device *dev,
-+                         struct dmabuf_create *head)
-+{
-+      struct dma_buf *dmabuf = NULL;
-+      void *mem_priv = NULL;
-+      dma_addr_t *paddr = NULL;
-+      int ret = 0;
-+
-+      mem_priv = vb2_dma_contig_memops.alloc(&vb, dev, head->size);
-+      if (IS_ERR_OR_NULL(mem_priv)) {
-+              if (mem_priv)
-+                      ret = PTR_ERR(mem_priv);
-+              goto exit;
-+      }
-+
-+      dmabuf = vb2_dma_contig_memops.get_dmabuf(&vb, mem_priv, O_RDWR);
-+      if (IS_ERR(dmabuf)) {
-+              ret = PTR_ERR(dmabuf);
-+              goto free;
-+      }
-+
-+      head->fd = dma_buf_fd(dmabuf, O_CLOEXEC);
-+      if (head->fd < 0) {
-+              dma_buf_put(dmabuf);
-+              ret = head->fd;
-+              goto free;
-+      }
-+
-+      paddr = vb2_dma_contig_memops.cookie(&vb, mem_priv);
-+      head->paddr = *paddr;
-+      return 0;
-+free:
-+      vb2_dma_contig_memops.put(mem_priv);
-+exit:
-+      return ret;
-+}
-+
-+int stf_dmabuf_ioctl_alloc(struct device *dev, void *arg)
-+{
-+      struct dmabuf_create *head = arg;
-+      int ret = -EINVAL;
-+
-+      if (IS_ERR_OR_NULL(head))
-+              return -EFAULT;
-+
-+      head->size = PAGE_ALIGN(head->size);
-+      if (!head->size)
-+              return -EINVAL;
-+      if ((head->size + total_size) > TOTAL_SIZE_LIMIT)
-+              return -ENOMEM;
-+
-+      ret = dmabuf_create(dev, head);
-+      if (ret)
-+              return -EFAULT;
-+
-+      total_size += head->size;
-+      return ret;
-+}
-+
-+int stf_dmabuf_ioctl_free(struct device *dev, void *arg)
-+{
-+      struct dmabuf_create *head = arg;
-+      struct dma_buf *dmabuf = NULL;
-+      int ret = 0;
-+
-+      if (IS_ERR_OR_NULL(head))
-+              return -EFAULT;
-+      if (head->size != PAGE_ALIGN(head->size))
-+              return -EINVAL;
-+      if (head->size > total_size)
-+              return -EINVAL;
-+
-+      dmabuf = dma_buf_get(head->fd);
-+      if (IS_ERR_OR_NULL(dmabuf))
-+              return -EINVAL;
-+
-+      dma_buf_put(dmabuf);
-+      vb2_dma_contig_memops.put(dmabuf->priv);
-+      total_size -= head->size;
-+      return ret;
-+}
-+
-+int stf_dmabuf_ioctl(struct device *dev, unsigned int cmd, void *arg)
-+{
-+      int ret = -ENOIOCTLCMD;
-+
-+      switch (cmd) {
-+      case VIDIOC_STF_DMABUF_ALLOC:
-+              ret = stf_dmabuf_ioctl_alloc(dev, arg);
-+              break;
-+      case VIDIOC_STF_DMABUF_FREE:
-+              ret = stf_dmabuf_ioctl_free(dev, arg);
-+              break;
-+      default:
-+              break;
-+      }
-+      return ret;
-+}
---- /dev/null
-+++ b/drivers/media/platform/starfive/v4l2_driver/stf_dmabuf.h
-@@ -0,0 +1,12 @@
-+/* SPDX-License-Identifier: GPL-2.0 */
-+/*
-+ * Copyright (C) 2021-2023 StarFive Technology Co., Ltd.
-+ *
-+ */
-+
-+#ifndef STF_DMABUF_H
-+#define STF_DMABUF_H
-+
-+extern int stf_dmabuf_ioctl(struct device *dev, unsigned int cmd, void *arg);
-+
-+#endif /* STF_DMABUF_H */
---- /dev/null
-+++ b/drivers/media/platform/starfive/v4l2_driver/stf_dvp.c
-@@ -0,0 +1,385 @@
-+// SPDX-License-Identifier: GPL-2.0
-+/*
-+ * Copyright (C) 2021-2023 StarFive Technology Co., Ltd.
-+ *
-+ */
-+
-+#include "stfcamss.h"
-+#include <media/v4l2-async.h>
-+#include <media/v4l2-ctrls.h>
-+#include <media/v4l2-device.h>
-+#include <media/v4l2-event.h>
-+#include <media/v4l2-fwnode.h>
-+#include <media/v4l2-subdev.h>
-+
-+static const struct dvp_format dvp_formats_st7110[] = {
-+      { MEDIA_BUS_FMT_YUYV8_2X8, 8},
-+      { MEDIA_BUS_FMT_RGB565_2X8_LE, 8},
-+      { MEDIA_BUS_FMT_SRGGB8_1X8, 8},
-+      { MEDIA_BUS_FMT_SGRBG8_1X8, 8},
-+      { MEDIA_BUS_FMT_SGBRG8_1X8, 8},
-+      { MEDIA_BUS_FMT_SBGGR8_1X8, 8},
-+      { MEDIA_BUS_FMT_SRGGB10_1X10, 8},
-+      { MEDIA_BUS_FMT_SGRBG10_1X10, 8},
-+      { MEDIA_BUS_FMT_SGBRG10_1X10, 8},
-+      { MEDIA_BUS_FMT_SBGGR10_1X10, 8},
-+};
-+
-+static int dvp_find_format(u32 code,
-+              const struct dvp_format *formats,
-+              unsigned int nformats)
-+{
-+      int i;
-+
-+      for (i = 0; i < nformats; i++)
-+              if (formats[i].code == code)
-+                      return i;
-+      return -EINVAL;
-+}
-+
-+int stf_dvp_subdev_init(struct stfcamss *stfcamss)
-+{
-+      struct stf_dvp_dev *dvp_dev = stfcamss->dvp_dev;
-+
-+      dvp_dev->s_type = SENSOR_VIN;
-+      dvp_dev->hw_ops = &dvp_ops;
-+      dvp_dev->stfcamss = stfcamss;
-+      dvp_dev->formats = dvp_formats_st7110;
-+      dvp_dev->nformats = ARRAY_SIZE(dvp_formats_st7110);
-+      mutex_init(&dvp_dev->stream_lock);
-+      dvp_dev->stream_count = 0;
-+      return 0;
-+}
-+
-+static int dvp_set_power(struct v4l2_subdev *sd, int on)
-+{
-+      return 0;
-+}
-+
-+static struct v4l2_mbus_framefmt *
-+__dvp_get_format(struct stf_dvp_dev *dvp_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(
-+                      &dvp_dev->subdev, state, pad);
-+      return &dvp_dev->fmt[pad];
-+}
-+
-+static int dvp_set_stream(struct v4l2_subdev *sd, int enable)
-+{
-+      struct stf_dvp_dev *dvp_dev = v4l2_get_subdevdata(sd);
-+      struct v4l2_mbus_framefmt *format;
-+      int ret = 0;
-+
-+      format = __dvp_get_format(dvp_dev, NULL, STF_DVP_PAD_SRC,
-+                              V4L2_SUBDEV_FORMAT_ACTIVE);
-+      if (format == NULL)
-+              return -EINVAL;
-+      ret = dvp_find_format(format->code,
-+                              dvp_dev->formats,
-+                              dvp_dev->nformats);
-+      if (ret < 0)
-+              return ret;
-+
-+      mutex_lock(&dvp_dev->stream_lock);
-+      if (enable) {
-+              if (dvp_dev->stream_count == 0) {
-+                      dvp_dev->hw_ops->dvp_clk_enable(dvp_dev);
-+                      dvp_dev->hw_ops->dvp_config_set(dvp_dev);
-+                      dvp_dev->hw_ops->dvp_set_format(dvp_dev,
-+                              format->width, dvp_dev->formats[ret].bpp);
-+                      dvp_dev->hw_ops->dvp_stream_set(dvp_dev, 1);
-+              }
-+              dvp_dev->stream_count++;
-+      } else {
-+              if (dvp_dev->stream_count == 0)
-+                      goto exit;
-+              if (dvp_dev->stream_count == 1) {
-+                      dvp_dev->hw_ops->dvp_stream_set(dvp_dev, 0);
-+                      dvp_dev->hw_ops->dvp_clk_disable(dvp_dev);
-+              }
-+              dvp_dev->stream_count--;
-+      }
-+exit:
-+      mutex_unlock(&dvp_dev->stream_lock);
-+      return 0;
-+}
-+
-+static void dvp_try_format(struct stf_dvp_dev *dvp_dev,
-+                      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_DVP_PAD_SINK:
-+              /* Set format on sink pad */
-+
-+              for (i = 0; i < dvp_dev->nformats; i++)
-+                      if (fmt->code == dvp_dev->formats[i].code)
-+                              break;
-+
-+              if (i >= dvp_dev->nformats)
-+                      fmt->code = dvp_dev->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_DVP_PAD_SRC:
-+
-+              *fmt = *__dvp_get_format(dvp_dev, state, STF_DVP_PAD_SINK, which);
-+
-+              break;
-+      }
-+}
-+
-+static int dvp_enum_mbus_code(struct v4l2_subdev *sd,
-+                      struct v4l2_subdev_state *state,
-+                      struct v4l2_subdev_mbus_code_enum *code)
-+{
-+      struct stf_dvp_dev *dvp_dev = v4l2_get_subdevdata(sd);
-+
-+      if (code->index >= dvp_dev->nformats)
-+              return -EINVAL;
-+
-+      if (code->pad == STF_DVP_PAD_SINK) {
-+              code->code = dvp_dev->formats[code->index].code;
-+      } else {
-+              struct v4l2_mbus_framefmt *sink_fmt;
-+
-+              sink_fmt = __dvp_get_format(dvp_dev, state, STF_DVP_PAD_SINK,
-+                                      code->which);
-+
-+              code->code = sink_fmt->code;
-+              if (!code->code)
-+                      return -EINVAL;
-+      }
-+      code->flags = 0;
-+
-+      return 0;
-+}
-+
-+static int dvp_enum_frame_size(struct v4l2_subdev *sd,
-+                              struct v4l2_subdev_state *state,
-+                              struct v4l2_subdev_frame_size_enum *fse)
-+{
-+      struct stf_dvp_dev *dvp_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;
-+      dvp_try_format(dvp_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;
-+      dvp_try_format(dvp_dev, state, fse->pad, &format, fse->which);
-+      fse->max_width = format.width;
-+      fse->max_height = format.height;
-+
-+      return 0;
-+}
-+
-+static int dvp_get_format(struct v4l2_subdev *sd,
-+                       struct v4l2_subdev_state *state,
-+                      struct v4l2_subdev_format *fmt)
-+{
-+      struct stf_dvp_dev *dvp_dev = v4l2_get_subdevdata(sd);
-+      struct v4l2_mbus_framefmt *format;
-+
-+      format = __dvp_get_format(dvp_dev, state, fmt->pad, fmt->which);
-+      if (format == NULL)
-+              return -EINVAL;
-+
-+      fmt->format = *format;
-+
-+      return 0;
-+}
-+
-+static int dvp_set_format(struct v4l2_subdev *sd,
-+                       struct v4l2_subdev_state *state,
-+                      struct v4l2_subdev_format *fmt)
-+{
-+      struct stf_dvp_dev *dvp_dev = v4l2_get_subdevdata(sd);
-+      struct v4l2_mbus_framefmt *format;
-+
-+      format = __dvp_get_format(dvp_dev, state, fmt->pad, fmt->which);
-+      if (format == NULL)
-+              return -EINVAL;
-+
-+      mutex_lock(&dvp_dev->stream_lock);
-+      if (dvp_dev->stream_count) {
-+              fmt->format = *format;
-+              mutex_unlock(&dvp_dev->stream_lock);
-+              goto out;
-+      } else {
-+              dvp_try_format(dvp_dev, state, fmt->pad, &fmt->format, fmt->which);
-+              *format = fmt->format;
-+      }
-+      mutex_unlock(&dvp_dev->stream_lock);
-+
-+      /* Propagate the format from sink to source */
-+      if (fmt->pad == STF_DVP_PAD_SINK) {
-+              format = __dvp_get_format(dvp_dev, state, STF_DVP_PAD_SRC,
-+                                      fmt->which);
-+
-+              *format = fmt->format;
-+              dvp_try_format(dvp_dev, state, STF_DVP_PAD_SRC, format,
-+                                      fmt->which);
-+      }
-+
-+out:
-+      return 0;
-+}
-+
-+static int dvp_init_formats(struct v4l2_subdev *sd,
-+                      struct v4l2_subdev_fh *fh)
-+{
-+      struct v4l2_subdev_format format = {
-+              .pad = STF_DVP_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 dvp_set_format(sd, fh ? fh->state : NULL, &format);
-+}
-+
-+static int dvp_link_setup(struct media_entity *entity,
-+                      const struct media_pad *local,
-+                      const struct media_pad *remote, u32 flags)
-+{
-+      if ((local->flags & MEDIA_PAD_FL_SOURCE) &&
-+              (flags & MEDIA_LNK_FL_ENABLED)) {
-+              struct v4l2_subdev *sd;
-+              struct stf_dvp_dev *dvp_dev;
-+              struct vin_line *line;
-+
-+              if (media_pad_remote_pad_first(local))
-+                      return -EBUSY;
-+
-+              sd = media_entity_to_v4l2_subdev(entity);
-+              dvp_dev = v4l2_get_subdevdata(sd);
-+
-+              sd = media_entity_to_v4l2_subdev(remote->entity);
-+              line = v4l2_get_subdevdata(sd);
-+              if (line->sdev_type == VIN_DEV_TYPE)
-+                      dvp_dev->s_type = SENSOR_VIN;
-+              if (line->sdev_type == ISP_DEV_TYPE)
-+                      dvp_dev->s_type = SENSOR_ISP;
-+              st_info(ST_DVP, "DVP device sensor type: %d\n", dvp_dev->s_type);
-+      }
-+
-+      return 0;
-+}
-+
-+static const struct v4l2_subdev_core_ops dvp_core_ops = {
-+      .s_power = dvp_set_power,
-+};
-+
-+static const struct v4l2_subdev_video_ops dvp_video_ops = {
-+      .s_stream = dvp_set_stream,
-+};
-+
-+static const struct v4l2_subdev_pad_ops dvp_pad_ops = {
-+      .enum_mbus_code = dvp_enum_mbus_code,
-+      .enum_frame_size = dvp_enum_frame_size,
-+      .get_fmt = dvp_get_format,
-+      .set_fmt = dvp_set_format,
-+};
-+
-+static const struct v4l2_subdev_ops dvp_v4l2_ops = {
-+      .core = &dvp_core_ops,
-+      .video = &dvp_video_ops,
-+      .pad = &dvp_pad_ops,
-+};
-+
-+static const struct v4l2_subdev_internal_ops dvp_v4l2_internal_ops = {
-+      .open = dvp_init_formats,
-+};
-+
-+static const struct media_entity_operations dvp_media_ops = {
-+      .link_setup = dvp_link_setup,
-+      .link_validate = v4l2_subdev_link_validate,
-+};
-+
-+int stf_dvp_register(struct stf_dvp_dev *dvp_dev,
-+              struct v4l2_device *v4l2_dev)
-+{
-+      struct v4l2_subdev *sd = &dvp_dev->subdev;
-+      struct media_pad *pads = dvp_dev->pads;
-+      int ret;
-+
-+      v4l2_subdev_init(sd, &dvp_v4l2_ops);
-+      sd->internal_ops = &dvp_v4l2_internal_ops;
-+      sd->flags |= V4L2_SUBDEV_FL_HAS_DEVNODE;
-+      snprintf(sd->name, ARRAY_SIZE(sd->name), "%s%d",
-+              STF_DVP_NAME, 0);
-+      v4l2_set_subdevdata(sd, dvp_dev);
-+
-+      ret = dvp_init_formats(sd, NULL);
-+      if (ret < 0) {
-+              st_err(ST_DVP, "Failed to init format: %d\n", ret);
-+              return ret;
-+      }
-+
-+      pads[STF_DVP_PAD_SINK].flags = MEDIA_PAD_FL_SINK;
-+      pads[STF_DVP_PAD_SRC].flags = MEDIA_PAD_FL_SOURCE;
-+
-+      sd->entity.function = MEDIA_ENT_F_PROC_VIDEO_PIXEL_FORMATTER;
-+      sd->entity.ops = &dvp_media_ops;
-+      ret = media_entity_pads_init(&sd->entity, STF_DVP_PADS_NUM, pads);
-+      if (ret < 0) {
-+              st_err(ST_DVP, "Failed to init media entity: %d\n", ret);
-+              return ret;
-+      }
-+
-+      ret = v4l2_device_register_subdev(v4l2_dev, sd);
-+      if (ret < 0) {
-+              st_err(ST_DVP, "Failed to register subdev: %d\n", ret);
-+              goto err_sreg;
-+      }
-+
-+      return 0;
-+
-+err_sreg:
-+      media_entity_cleanup(&sd->entity);
-+      return ret;
-+}
-+
-+int stf_dvp_unregister(struct stf_dvp_dev *dvp_dev)
-+{
-+      v4l2_device_unregister_subdev(&dvp_dev->subdev);
-+      media_entity_cleanup(&dvp_dev->subdev.entity);
-+      mutex_destroy(&dvp_dev->stream_lock);
-+      return 0;
-+}
---- /dev/null
-+++ b/drivers/media/platform/starfive/v4l2_driver/stf_dvp.h
-@@ -0,0 +1,67 @@
-+/* SPDX-License-Identifier: GPL-2.0
-+ *
-+ * Copyright (C) 2021-2023 StarFive Technology Co., Ltd.
-+ *
-+ */
-+
-+#ifndef STF_DVP_H
-+#define STF_DVP_H
-+
-+#include <media/v4l2-subdev.h>
-+#include <media/v4l2-device.h>
-+#include <media/media-entity.h>
-+#include <video/stf-vin.h>
-+
-+#define STF_DVP_NAME "stf_dvp"
-+
-+#define STF_DVP_PAD_SINK     0
-+#define STF_DVP_PAD_SRC      1
-+#define STF_DVP_PADS_NUM     2
-+
-+struct dvp_format {
-+      u32 code;
-+      u8 bpp;
-+};
-+
-+enum sensor_type;
-+enum subdev_type;
-+
-+struct dvp_cfg {
-+      unsigned int flags;
-+      unsigned char bus_width;
-+      unsigned char data_shift;
-+};
-+
-+struct stf_dvp_dev;
-+
-+struct dvp_hw_ops {
-+      int (*dvp_clk_enable)(struct stf_dvp_dev *dvp_dev);
-+      int (*dvp_clk_disable)(struct stf_dvp_dev *dvp_dev);
-+      int (*dvp_config_set)(struct stf_dvp_dev *dvp_dev);
-+      int (*dvp_set_format)(struct stf_dvp_dev *dvp_dev,
-+                      u32 pix_width, u8 bpp);
-+      int (*dvp_stream_set)(struct stf_dvp_dev *dvp_dev, int on);
-+};
-+
-+struct stf_dvp_dev {
-+      struct stfcamss *stfcamss;
-+      struct dvp_cfg *dvp;
-+      enum sensor_type s_type;
-+      struct v4l2_subdev subdev;
-+      struct media_pad pads[STF_DVP_PADS_NUM];
-+      struct v4l2_mbus_framefmt fmt[STF_DVP_PADS_NUM];
-+      const struct dvp_format *formats;
-+      unsigned int nformats;
-+      struct dvp_hw_ops *hw_ops;
-+      struct mutex stream_lock;
-+      int stream_count;
-+};
-+
-+extern int stf_dvp_subdev_init(struct stfcamss *stfcamss);
-+extern int stf_dvp_register(struct stf_dvp_dev *dvp_dev,
-+                      struct v4l2_device *v4l2_dev);
-+extern int stf_dvp_unregister(struct stf_dvp_dev *dvp_dev);
-+
-+extern struct dvp_hw_ops dvp_ops;
-+
-+#endif /* STF_DVP_H */
---- /dev/null
-+++ b/drivers/media/platform/starfive/v4l2_driver/stf_dvp_hw_ops.c
-@@ -0,0 +1,187 @@
-+// SPDX-License-Identifier: GPL-2.0
-+/*
-+ * Copyright (C) 2021-2023 StarFive Technology Co., Ltd.
-+ *
-+ */
-+
-+#include "stfcamss.h"
-+
-+static int stf_dvp_clk_enable(struct stf_dvp_dev *dvp_dev)
-+{
-+      struct stfcamss *stfcamss = dvp_dev->stfcamss;
-+
-+      switch (dvp_dev->s_type) {
-+      case SENSOR_VIN:
-+              reset_control_deassert(stfcamss->sys_rst[STFRST_AXIWR].rstc);
-+              clk_set_phase(stfcamss->sys_clk[STFCLK_DVP_INV].clk, 0);
-+              clk_set_parent(stfcamss->sys_clk[STFCLK_AXIWR].clk,
-+                      stfcamss->sys_clk[STFCLK_DVP_INV].clk);
-+              break;
-+      case SENSOR_ISP:
-+              clk_set_phase(stfcamss->sys_clk[STFCLK_DVP_INV].clk, 0);
-+              clk_set_parent(stfcamss->sys_clk[STFCLK_WRAPPER_CLK_C].clk,
-+                      stfcamss->sys_clk[STFCLK_DVP_INV].clk);
-+              break;
-+      }
-+
-+      return 0;
-+}
-+
-+static int stf_dvp_clk_disable(struct stf_dvp_dev *dvp_dev)
-+{
-+      struct stfcamss *stfcamss = dvp_dev->stfcamss;
-+
-+      switch (dvp_dev->s_type) {
-+      case SENSOR_VIN:
-+              clk_set_parent(stfcamss->sys_clk[STFCLK_AXIWR].clk,
-+                      stfcamss->sys_clk[STFCLK_MIPI_RX0_PXL].clk);
-+              reset_control_assert(stfcamss->sys_rst[STFRST_AXIWR].rstc);
-+              break;
-+      case SENSOR_ISP:
-+              clk_set_parent(stfcamss->sys_clk[STFCLK_WRAPPER_CLK_C].clk,
-+                      stfcamss->sys_clk[STFCLK_MIPI_RX0_PXL].clk);
-+              break;
-+      }
-+
-+      return 0;
-+}
-+
-+static int stf_dvp_config_set(struct stf_dvp_dev *dvp_dev)
-+{
-+
-+      struct stf_vin_dev *vin = dvp_dev->stfcamss->vin;
-+      unsigned int flags = 0;
-+      unsigned char data_shift = 0;
-+      u32 polarities = 0;
-+
-+      if (!dvp_dev->dvp)
-+              return -EINVAL;
-+
-+      flags = dvp_dev->dvp->flags;
-+      data_shift = dvp_dev->dvp->data_shift;
-+      st_info(ST_DVP, "%s, polarities = 0x%x, flags = 0x%x\n",
-+                      __func__, polarities, flags);
-+
-+      if (flags & V4L2_MBUS_HSYNC_ACTIVE_HIGH)
-+              polarities |= BIT(1);
-+      if (flags & V4L2_MBUS_VSYNC_ACTIVE_HIGH)
-+              polarities |= BIT(3);
-+      print_reg(ST_DVP, vin->sysctrl_base, SYSCONSAIF_SYSCFG_36);
-+      reg_set_bit(vin->sysctrl_base,  SYSCONSAIF_SYSCFG_36,
-+              U0_VIN_CNFG_DVP_HS_POS
-+              | U0_VIN_CNFG_DVP_VS_POS,
-+              polarities);
-+      print_reg(ST_DVP, vin->sysctrl_base, SYSCONSAIF_SYSCFG_36);
-+
-+      switch (data_shift) {
-+      case 0:
-+              data_shift = 0;
-+              break;
-+      case 2:
-+              data_shift = 1;
-+              break;
-+      case 4:
-+              data_shift = 2;
-+              break;
-+      case 6:
-+              data_shift = 3;
-+              break;
-+      default:
-+              data_shift = 0;
-+              break;
-+      };
-+      print_reg(ST_DVP, vin->sysctrl_base, SYSCONSAIF_SYSCFG_28);
-+      reg_set_bit(vin->sysctrl_base, SYSCONSAIF_SYSCFG_28,
-+              UO_VIN_CNFG_AXIWR0_PIXEL_HEIGH_BIT_SEL,
-+              data_shift << 15);
-+      print_reg(ST_DVP, vin->sysctrl_base, SYSCONSAIF_SYSCFG_28);
-+
-+      return 0;
-+}
-+
-+static int set_vin_axiwr_pix_ct(struct stf_vin_dev *vin, u8 bpp)
-+{
-+      u32 value = 0;
-+      int cnfg_axiwr_pix_ct = 64 / bpp;
-+
-+      // need check
-+      if (cnfg_axiwr_pix_ct == 2)
-+              value = 1;
-+      else if (cnfg_axiwr_pix_ct == 4)
-+              value = 1;
-+      else if (cnfg_axiwr_pix_ct == 8)
-+              value = 0;
-+      else
-+              return 0;
-+
-+      print_reg(ST_DVP, vin->sysctrl_base, SYSCONSAIF_SYSCFG_28);
-+      reg_set_bit(vin->sysctrl_base,
-+              SYSCONSAIF_SYSCFG_28,
-+              U0_VIN_CNFG_AXIWR0_PIX_CT,
-+              value<<13);
-+      print_reg(ST_DVP, vin->sysctrl_base, SYSCONSAIF_SYSCFG_28);
-+
-+      return cnfg_axiwr_pix_ct;
-+
-+}
-+
-+static int stf_dvp_set_format(struct stf_dvp_dev *dvp_dev,
-+              u32 pix_width, u8 bpp)
-+{
-+      struct stf_vin_dev *vin = dvp_dev->stfcamss->vin;
-+      int val, pix_ct;
-+
-+      if (dvp_dev->s_type == SENSOR_VIN) {
-+              pix_ct = set_vin_axiwr_pix_ct(vin, bpp);
-+              val = (pix_width / pix_ct) - 1;
-+              print_reg(ST_DVP, vin->sysctrl_base, SYSCTRL_VIN_WR_PIX_TOTAL);
-+              reg_set_bit(vin->sysctrl_base,
-+                      SYSCONSAIF_SYSCFG_28,
-+                      U0_VIN_CNFG_AXIWR0_PIX_CNT_END,
-+                      val << 2);
-+              print_reg(ST_DVP, vin->sysctrl_base, SYSCTRL_VIN_WR_PIX_TOTAL);
-+
-+      }
-+
-+      return 0;
-+}
-+
-+static int stf_dvp_stream_set(struct stf_dvp_dev *dvp_dev, int on)
-+{
-+      struct stf_vin_dev *vin = dvp_dev->stfcamss->vin;
-+
-+      switch (dvp_dev->s_type) {
-+      case SENSOR_VIN:
-+              reg_set_bit(vin->sysctrl_base, SYSCONSAIF_SYSCFG_36,
-+                      U0_VIN_CNFG_ISP_DVP_EN0,
-+                      0);
-+              reg_set_bit(vin->sysctrl_base, SYSCONSAIF_SYSCFG_0,
-+                      U0_VIN_CNFG_AXI_DVP_EN,
-+                      !!on<<2);
-+              break;
-+      case SENSOR_ISP:
-+              reg_set_bit(vin->sysctrl_base, SYSCONSAIF_SYSCFG_36,
-+                      U0_VIN_CNFG_ISP_DVP_EN0,
-+                      !!on<<5);
-+              reg_set_bit(vin->sysctrl_base, SYSCONSAIF_SYSCFG_0,
-+                      U0_VIN_CNFG_AXI_DVP_EN,
-+                      0);
-+              reg_set_bit(vin->sysctrl_base, SYSCONSAIF_SYSCFG_36,
-+                      U0_VIN_CNFG_DVP_SWAP_EN,
-+                      0);
-+              reg_set_bit(vin->sysctrl_base, SYSCONSAIF_SYSCFG_36,
-+                      U0_VIN_CNFG_GEN_EN_AXIRD,
-+                      0);
-+              break;
-+      }
-+
-+      return 0;
-+}
-+
-+struct dvp_hw_ops dvp_ops = {
-+      .dvp_clk_enable        = stf_dvp_clk_enable,
-+      .dvp_clk_disable       = stf_dvp_clk_disable,
-+      .dvp_config_set        = stf_dvp_config_set,
-+      .dvp_set_format        = stf_dvp_set_format,
-+      .dvp_stream_set        = stf_dvp_stream_set,
-+};
---- /dev/null
-+++ b/drivers/media/platform/starfive/v4l2_driver/stf_event.c
-@@ -0,0 +1,36 @@
-+// SPDX-License-Identifier: GPL-2.0
-+/*
-+ * Copyright (C) 2021-2023 StarFive Technology Co., Ltd.
-+ *
-+ */
-+
-+#include <linux/notifier.h>
-+#include <linux/module.h>
-+#include <linux/init.h>
-+#include <linux/kernel.h>
-+#include <linux/fs.h>
-+
-+static ATOMIC_NOTIFIER_HEAD(vin_notifier_list);
-+
-+int vin_notifier_register(struct notifier_block *nb)
-+{
-+      return atomic_notifier_chain_register(&vin_notifier_list, nb);
-+}
-+EXPORT_SYMBOL_GPL(vin_notifier_register);
-+
-+void vin_notifier_unregister(struct notifier_block *nb)
-+{
-+      atomic_notifier_chain_unregister(&vin_notifier_list, nb);
-+}
-+EXPORT_SYMBOL_GPL(vin_notifier_unregister);
-+
-+int vin_notifier_call(unsigned long e, void *v)
-+{
-+      return atomic_notifier_call_chain(&vin_notifier_list, e, v);
-+}
-+EXPORT_SYMBOL_GPL(vin_notifier_call);
-+
-+MODULE_AUTHOR("StarFive Technology Co., Ltd.");
-+MODULE_DESCRIPTION("Starfive VIC video in notifier");
-+MODULE_LICENSE("GPL");
-+//MODULE_SUPPORTED_DEVICE("video");
---- /dev/null
-+++ b/drivers/media/platform/starfive/v4l2_driver/stf_isp.c
-@@ -0,0 +1,1521 @@
-+// SPDX-License-Identifier: GPL-2.0
-+/*
-+ * Copyright (C) 2021-2023 StarFive Technology Co., Ltd.
-+ *
-+ */
-+
-+#include "stfcamss.h"
-+#include <media/v4l2-async.h>
-+#include <media/v4l2-ctrls.h>
-+#include <media/v4l2-device.h>
-+#include <media/v4l2-event.h>
-+#include <media/v4l2-fwnode.h>
-+#include <media/v4l2-subdev.h>
-+#include <linux/firmware.h>
-+#include <linux/jh7110-isp.h>
-+#include "stf_isp_ioctl.h"
-+#include "stf_dmabuf.h"
-+
-+static int user_config_isp;
-+static int isp_set_selection(struct v4l2_subdev *sd,
-+                           struct v4l2_subdev_state *state,
-+                           struct v4l2_subdev_selection *sel);
-+
-+static struct v4l2_rect *
-+__isp_get_compose(struct stf_isp_dev *isp_dev,
-+                struct v4l2_subdev_state *state,
-+                enum v4l2_subdev_format_whence which);
-+
-+static struct v4l2_rect *
-+__isp_get_crop(struct stf_isp_dev *isp_dev,
-+              struct v4l2_subdev_state *state,
-+              enum v4l2_subdev_format_whence which);
-+
-+static struct v4l2_rect *
-+__isp_get_scale(struct stf_isp_dev *isp_dev,
-+              struct v4l2_subdev_state *state,
-+              struct v4l2_subdev_selection *sel);
-+
-+static struct v4l2_rect *
-+__isp_get_itiws(struct stf_isp_dev *isp_dev,
-+              struct v4l2_subdev_state *state,
-+              enum v4l2_subdev_format_whence which);
-+
-+// sink format and raw format must one by one
-+static const struct isp_format isp_formats_st7110_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_st7110_raw[] = {
-+      { MEDIA_BUS_FMT_SRGGB12_1X12, 12},
-+      { MEDIA_BUS_FMT_SGRBG12_1X12, 12},
-+      { MEDIA_BUS_FMT_SGBRG12_1X12, 12},
-+      { MEDIA_BUS_FMT_SBGGR12_1X12, 12},
-+};
-+
-+static const struct isp_format isp_formats_st7110_compat_10bit_raw[] = {
-+      { 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_st7110_compat_8bit_raw[] = {
-+      { MEDIA_BUS_FMT_SRGGB8_1X8, 8},
-+      { MEDIA_BUS_FMT_SGRBG8_1X8, 8},
-+      { MEDIA_BUS_FMT_SGBRG8_1X8, 8},
-+      { MEDIA_BUS_FMT_SBGGR8_1X8, 8},
-+};
-+
-+static const struct isp_format isp_formats_st7110_uo[] = {
-+      { MEDIA_BUS_FMT_Y12_1X12, 8},
-+};
-+
-+static const struct isp_format isp_formats_st7110_iti[] = {
-+      { MEDIA_BUS_FMT_SRGGB10_1X10, 10},
-+      { MEDIA_BUS_FMT_SGRBG10_1X10, 10},
-+      { MEDIA_BUS_FMT_SGBRG10_1X10, 10},
-+      { MEDIA_BUS_FMT_SBGGR10_1X10, 10},
-+      { MEDIA_BUS_FMT_SRGGB12_1X12, 12},
-+      { MEDIA_BUS_FMT_SGRBG12_1X12, 12},
-+      { MEDIA_BUS_FMT_SGBRG12_1X12, 12},
-+      { MEDIA_BUS_FMT_SBGGR12_1X12, 12},
-+      { MEDIA_BUS_FMT_Y12_1X12, 8},
-+      { MEDIA_BUS_FMT_YUV8_1X24, 8},
-+};
-+
-+static const struct isp_format_table isp_formats_st7110[] = {
-+      { isp_formats_st7110_sink, ARRAY_SIZE(isp_formats_st7110_sink) }, /* pad 0 */
-+      { isp_formats_st7110_uo, ARRAY_SIZE(isp_formats_st7110_uo) },     /* pad 1 */
-+      { isp_formats_st7110_uo, ARRAY_SIZE(isp_formats_st7110_uo) },     /* pad 2 */
-+      { isp_formats_st7110_uo, ARRAY_SIZE(isp_formats_st7110_uo) },     /* pad 3 */
-+      { isp_formats_st7110_iti, ARRAY_SIZE(isp_formats_st7110_iti) },   /* pad 4 */
-+      { isp_formats_st7110_iti, ARRAY_SIZE(isp_formats_st7110_iti) },   /* pad 5 */
-+      { isp_formats_st7110_raw, ARRAY_SIZE(isp_formats_st7110_raw) },   /* pad 6 */
-+      { isp_formats_st7110_raw, ARRAY_SIZE(isp_formats_st7110_raw) },   /* pad 7 */
-+};
-+
-+int stf_isp_subdev_init(struct stfcamss *stfcamss)
-+{
-+      struct stf_isp_dev *isp_dev = stfcamss->isp_dev;
-+
-+      isp_dev->sdev_type = ISP_DEV_TYPE;
-+      isp_dev->hw_ops = &isp_ops;
-+      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);
-+      mutex_init(&isp_dev->setfile_lock);
-+      atomic_set(&isp_dev->shadow_count, 0);
-+      return 0;
-+}
-+
-+/*
-+ * ISP Controls.
-+ */
-+
-+static inline struct v4l2_subdev *ctrl_to_sd(struct v4l2_ctrl *ctrl)
-+{
-+      return &container_of(ctrl->handler, struct stf_isp_dev,
-+                           ctrls.handler)->subdev;
-+}
-+
-+static u64 isp_calc_pixel_rate(struct stf_isp_dev *isp_dev)
-+{
-+      u64 rate = 0;
-+
-+      return rate;
-+}
-+
-+static int isp_set_ctrl_hue(struct stf_isp_dev *isp_dev, int value)
-+{
-+      int ret = 0;
-+
-+      return ret;
-+}
-+
-+static int isp_set_ctrl_contrast(struct stf_isp_dev *isp_dev, int value)
-+{
-+      int ret = 0;
-+
-+      return ret;
-+}
-+
-+static int isp_set_ctrl_saturation(struct stf_isp_dev *isp_dev, int value)
-+{
-+      int ret = 0;
-+
-+      return ret;
-+}
-+
-+static int isp_set_ctrl_white_balance(struct stf_isp_dev *isp_dev, int awb)
-+{
-+      struct isp_ctrls *ctrls = &isp_dev->ctrls;
-+      int ret = 0;
-+
-+      if (!awb && (ctrls->red_balance->is_new
-+                      || ctrls->blue_balance->is_new)) {
-+              u16 red = (u16)ctrls->red_balance->val;
-+              u16 blue = (u16)ctrls->blue_balance->val;
-+
-+              st_debug(ST_ISP, "red = 0x%x, blue = 0x%x\n", red, blue);
-+              //isp_dev->hw_ops->isp_set_awb_r_gain(isp_dev, red);
-+              //if (ret)
-+              //      return ret;
-+              //isp_dev->hw_ops->isp_set_awb_b_gain(isp_dev, blue);
-+      }
-+
-+      return ret;
-+}
-+
-+static int isp_set_ctrl_exposure(struct stf_isp_dev *isp_dev,
-+                                  enum v4l2_exposure_auto_type auto_exposure)
-+{
-+      int ret = 0;
-+
-+      return ret;
-+}
-+
-+static int isp_set_ctrl_gain(struct stf_isp_dev *isp_dev, bool auto_gain)
-+{
-+      int ret = 0;
-+
-+      return ret;
-+}
-+
-+static const char * const test_pattern_menu[] = {
-+      "Disabled",
-+      "Color bars",
-+      "Color bars w/ rolling bar",
-+      "Color squares",
-+      "Color squares w/ rolling bar",
-+};
-+
-+#define ISP_TEST_ENABLE                       BIT(7)
-+#define ISP_TEST_ROLLING              BIT(6)  /* rolling horizontal bar */
-+#define ISP_TEST_TRANSPARENT          BIT(5)
-+#define ISP_TEST_SQUARE_BW            BIT(4)  /* black & white squares */
-+#define ISP_TEST_BAR_STANDARD         (0 << 2)
-+#define ISP_TEST_BAR_VERT_CHANGE_1    (1 << 2)
-+#define ISP_TEST_BAR_HOR_CHANGE               (2 << 2)
-+#define ISP_TEST_BAR_VERT_CHANGE_2    (3 << 2)
-+#define ISP_TEST_BAR                  (0 << 0)
-+#define ISP_TEST_RANDOM                       (1 << 0)
-+#define ISP_TEST_SQUARE                       (2 << 0)
-+#define ISP_TEST_BLACK                        (3 << 0)
-+
-+static const u8 test_pattern_val[] = {
-+      0,
-+      ISP_TEST_ENABLE | ISP_TEST_BAR_VERT_CHANGE_1 |
-+              ISP_TEST_BAR,
-+      ISP_TEST_ENABLE | ISP_TEST_ROLLING |
-+              ISP_TEST_BAR_VERT_CHANGE_1 | ISP_TEST_BAR,
-+      ISP_TEST_ENABLE | ISP_TEST_SQUARE,
-+      ISP_TEST_ENABLE | ISP_TEST_ROLLING | ISP_TEST_SQUARE,
-+};
-+
-+static int isp_set_ctrl_test_pattern(struct stf_isp_dev *isp_dev, int value)
-+{
-+      int ret = 0;
-+
-+      // return isp_write_reg(isp_dev, ISP_REG_PRE_ISP_TEST_SET1,
-+      //                      test_pattern_val[value]);
-+      return ret;
-+}
-+
-+static int isp_set_ctrl_light_freq(struct stf_isp_dev *isp_dev, int value)
-+{
-+      int ret = 0;
-+
-+      return ret;
-+}
-+
-+static int isp_set_ctrl_hflip(struct stf_isp_dev *isp_dev, int value)
-+{
-+      int ret = 0;
-+
-+      return ret;
-+}
-+
-+static int isp_set_ctrl_vflip(struct stf_isp_dev *isp_dev, int value)
-+{
-+      int ret = 0;
-+
-+      return ret;
-+}
-+
-+static int isp_g_volatile_ctrl(struct v4l2_ctrl *ctrl)
-+{
-+      switch (ctrl->id) {
-+      case V4L2_CID_AUTOGAIN:
-+              break;
-+      case V4L2_CID_EXPOSURE_AUTO:
-+              break;
-+      }
-+
-+      return 0;
-+}
-+
-+static int isp_s_ctrl(struct v4l2_ctrl *ctrl)
-+{
-+      struct v4l2_subdev *sd = ctrl_to_sd(ctrl);
-+      struct stf_isp_dev *isp_dev = v4l2_get_subdevdata(sd);
-+      int ret = 0;
-+
-+      /*
-+       * If the device is not powered up by the host driver do
-+       * not apply any controls to H/W at this time. Instead
-+       * the controls will be restored right after power-up.
-+       */
-+      mutex_lock(&isp_dev->power_lock);
-+      if (isp_dev->power_count == 0) {
-+              mutex_unlock(&isp_dev->power_lock);
-+              return 0;
-+      }
-+      mutex_unlock(&isp_dev->power_lock);
-+
-+      switch (ctrl->id) {
-+      case V4L2_CID_AUTOGAIN:
-+              ret = isp_set_ctrl_gain(isp_dev, ctrl->val);
-+              break;
-+      case V4L2_CID_EXPOSURE_AUTO:
-+              ret = isp_set_ctrl_exposure(isp_dev, ctrl->val);
-+              break;
-+      case V4L2_CID_AUTO_WHITE_BALANCE:
-+              ret = isp_set_ctrl_white_balance(isp_dev, ctrl->val);
-+              break;
-+      case V4L2_CID_HUE:
-+              ret = isp_set_ctrl_hue(isp_dev, ctrl->val);
-+              break;
-+      case V4L2_CID_CONTRAST:
-+              ret = isp_set_ctrl_contrast(isp_dev, ctrl->val);
-+              break;
-+      case V4L2_CID_SATURATION:
-+              ret = isp_set_ctrl_saturation(isp_dev, ctrl->val);
-+              break;
-+      case V4L2_CID_TEST_PATTERN:
-+              ret = isp_set_ctrl_test_pattern(isp_dev, ctrl->val);
-+              break;
-+      case V4L2_CID_POWER_LINE_FREQUENCY:
-+              ret = isp_set_ctrl_light_freq(isp_dev, ctrl->val);
-+              break;
-+      case V4L2_CID_HFLIP:
-+              ret = isp_set_ctrl_hflip(isp_dev, ctrl->val);
-+              break;
-+      case V4L2_CID_VFLIP:
-+              ret = isp_set_ctrl_vflip(isp_dev, ctrl->val);
-+              break;
-+      case V4L2_CID_USER_JH7110_ISP_WB_SETTING:
-+              break;
-+      case V4L2_CID_USER_JH7110_ISP_CAR_SETTING:
-+              break;
-+      case V4L2_CID_USER_JH7110_ISP_CCM_SETTING:
-+              break;
-+      default:
-+              ret = -EINVAL;
-+              break;
-+      }
-+
-+      return ret;
-+}
-+
-+static const struct v4l2_ctrl_ops isp_ctrl_ops = {
-+      .g_volatile_ctrl = isp_g_volatile_ctrl,
-+      .s_ctrl = isp_s_ctrl,
-+};
-+
-+struct v4l2_ctrl_config isp_ctrl[] = {
-+      [0] = {
-+              .ops            = &isp_ctrl_ops,
-+              .type           = V4L2_CTRL_TYPE_U8,
-+              .def            = 0,
-+              .min            = 0x00,
-+              .max            = 0xff,
-+              .step           = 1,
-+              .name           = "WB Setting",
-+              .id             = V4L2_CID_USER_JH7110_ISP_WB_SETTING,
-+              .dims[0]        = sizeof(struct jh7110_isp_wb_setting),
-+              .flags          = 0,
-+      },
-+      [1] = {
-+              .ops            = &isp_ctrl_ops,
-+              .type           = V4L2_CTRL_TYPE_U8,
-+              .def            = 0,
-+              .min            = 0x00,
-+              .max            = 0xff,
-+              .step           = 1,
-+              .name           = "Car Setting",
-+              .id             = V4L2_CID_USER_JH7110_ISP_CAR_SETTING,
-+              .dims[0]        = sizeof(struct jh7110_isp_car_setting),
-+              .flags          = 0,
-+      },
-+      [2] = {
-+              .ops            = &isp_ctrl_ops,
-+              .type           = V4L2_CTRL_TYPE_U8,
-+              .def            = 0,
-+              .min            = 0x00,
-+              .max            = 0xff,
-+              .step           = 1,
-+              .name           = "CCM Setting",
-+              .id             = V4L2_CID_USER_JH7110_ISP_CCM_SETTING,
-+              .dims[0]        = sizeof(struct jh7110_isp_ccm_setting),
-+              .flags          = 0,
-+      },
-+};
-+
-+static int isp_init_controls(struct stf_isp_dev *isp_dev)
-+{
-+      const struct v4l2_ctrl_ops *ops = &isp_ctrl_ops;
-+      struct isp_ctrls *ctrls = &isp_dev->ctrls;
-+      struct v4l2_ctrl_handler *hdl = &ctrls->handler;
-+      int ret;
-+      int i;
-+
-+      v4l2_ctrl_handler_init(hdl, 32);
-+
-+      /* Clock related controls */
-+      ctrls->pixel_rate = v4l2_ctrl_new_std(hdl, ops, V4L2_CID_PIXEL_RATE,
-+                                            0, INT_MAX, 1,
-+                                            isp_calc_pixel_rate(isp_dev));
-+
-+      /* Auto/manual white balance */
-+      ctrls->auto_wb = v4l2_ctrl_new_std(hdl, ops,
-+                                         V4L2_CID_AUTO_WHITE_BALANCE,
-+                                         0, 1, 1, 1);
-+      ctrls->blue_balance = v4l2_ctrl_new_std(hdl, ops, V4L2_CID_BLUE_BALANCE,
-+                                              0, 4095, 1, 0);
-+      ctrls->red_balance = v4l2_ctrl_new_std(hdl, ops, V4L2_CID_RED_BALANCE,
-+                                             0, 4095, 1, 0);
-+      /* Auto/manual exposure */
-+      ctrls->auto_exp = v4l2_ctrl_new_std_menu(hdl, ops,
-+                                               V4L2_CID_EXPOSURE_AUTO,
-+                                               V4L2_EXPOSURE_MANUAL, 0,
-+                                               V4L2_EXPOSURE_AUTO);
-+      ctrls->exposure = v4l2_ctrl_new_std(hdl, ops, V4L2_CID_EXPOSURE,
-+                                          0, 65535, 1, 0);
-+      /* Auto/manual gain */
-+      ctrls->auto_gain = v4l2_ctrl_new_std(hdl, ops, V4L2_CID_AUTOGAIN,
-+                                           0, 1, 1, 1);
-+      ctrls->gain = v4l2_ctrl_new_std(hdl, ops, V4L2_CID_GAIN,
-+                                      0, 1023, 1, 0);
-+
-+      ctrls->saturation = v4l2_ctrl_new_std(hdl, ops, V4L2_CID_SATURATION,
-+                                            0, 255, 1, 64);
-+      ctrls->hue = v4l2_ctrl_new_std(hdl, ops, V4L2_CID_HUE,
-+                                     0, 359, 1, 0);
-+      ctrls->contrast = v4l2_ctrl_new_std(hdl, ops, V4L2_CID_CONTRAST,
-+                                          0, 255, 1, 0);
-+      ctrls->test_pattern =
-+              v4l2_ctrl_new_std_menu_items(hdl, ops, V4L2_CID_TEST_PATTERN,
-+                                           ARRAY_SIZE(test_pattern_menu) - 1,
-+                                           0, 0, test_pattern_menu);
-+      ctrls->hflip = v4l2_ctrl_new_std(hdl, ops, V4L2_CID_HFLIP,
-+                                       0, 1, 1, 0);
-+      ctrls->vflip = v4l2_ctrl_new_std(hdl, ops, V4L2_CID_VFLIP,
-+                                       0, 1, 1, 0);
-+
-+      ctrls->light_freq =
-+              v4l2_ctrl_new_std_menu(hdl, ops,
-+                                     V4L2_CID_POWER_LINE_FREQUENCY,
-+                                     V4L2_CID_POWER_LINE_FREQUENCY_AUTO, 0,
-+                                     V4L2_CID_POWER_LINE_FREQUENCY_50HZ);
-+
-+      for (i = 0; i < ARRAY_SIZE(isp_ctrl); i++)
-+              v4l2_ctrl_new_custom(hdl, &isp_ctrl[i], NULL);
-+
-+
-+      if (hdl->error) {
-+              ret = hdl->error;
-+              goto free_ctrls;
-+      }
-+
-+      ctrls->pixel_rate->flags |= V4L2_CTRL_FLAG_READ_ONLY;
-+      ctrls->gain->flags |= V4L2_CTRL_FLAG_VOLATILE;
-+      ctrls->exposure->flags |= V4L2_CTRL_FLAG_VOLATILE;
-+
-+      v4l2_ctrl_auto_cluster(3, &ctrls->auto_wb, 0, false);
-+      v4l2_ctrl_auto_cluster(2, &ctrls->auto_gain, 0, true);
-+      v4l2_ctrl_auto_cluster(2, &ctrls->auto_exp, 1, true);
-+
-+      isp_dev->subdev.ctrl_handler = hdl;
-+      return 0;
-+
-+free_ctrls:
-+      v4l2_ctrl_handler_free(hdl);
-+      return ret;
-+}
-+
-+static int isp_set_power(struct v4l2_subdev *sd, int on)
-+{
-+      struct stf_isp_dev *isp_dev = v4l2_get_subdevdata(sd);
-+
-+      st_debug(ST_ISP, "%s, %d\n", __func__, __LINE__);
-+      mutex_lock(&isp_dev->power_lock);
-+      if (on) {
-+              if (isp_dev->power_count == 0)
-+                      st_debug(ST_ISP, "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_get_interface_type(struct media_entity *entity)
-+{
-+      struct v4l2_subdev *subdev;
-+      struct media_pad *pad = &entity->pads[0];
-+
-+      if (!(pad->flags & MEDIA_PAD_FL_SINK))
-+              return -EINVAL;
-+
-+      pad = media_pad_remote_pad_first(pad);
-+      if (!pad || !is_media_entity_v4l2_subdev(pad->entity))
-+              return -EINVAL;
-+
-+      subdev = media_entity_to_v4l2_subdev(pad->entity);
-+
-+      st_debug(ST_ISP, "interface subdev name %s\n", subdev->name);
-+      if (!strncmp(subdev->name, STF_CSI_NAME, strlen(STF_CSI_NAME)))
-+              return CSI_SENSOR;
-+      if (!strncmp(subdev->name, STF_DVP_NAME, strlen(STF_DVP_NAME)))
-+              return DVP_SENSOR;
-+      return -EINVAL;
-+}
-+
-+static int isp_set_stream(struct v4l2_subdev *sd, int enable)
-+{
-+      struct stf_isp_dev *isp_dev = v4l2_get_subdevdata(sd);
-+      int ret = 0, interface_type;
-+      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) {
-+                      isp_dev->hw_ops->isp_clk_enable(isp_dev);
-+                      if (!user_config_isp)
-+                              isp_dev->hw_ops->isp_config_set(isp_dev);
-+                      interface_type = isp_get_interface_type(&sd->entity);
-+                      if (interface_type < 0) {
-+                              st_err(ST_ISP, "%s, pipeline not config\n", __func__);
-+                              goto exit;
-+                      }
-+                      isp_dev->hw_ops->isp_set_format(isp_dev,
-+                                      isp_dev->rect, fmt->code, interface_type);
-+                      isp_dev->hw_ops->isp_reset(isp_dev);
-+                      isp_dev->hw_ops->isp_stream_set(isp_dev, enable);
-+                      user_config_isp = 0;
-+              }
-+              isp_dev->stream_count++;
-+      } else {
-+              if (isp_dev->stream_count == 0)
-+                      goto exit;
-+              if (isp_dev->stream_count == 1) {
-+                      isp_dev->hw_ops->isp_stream_set(isp_dev, enable);
-+                      isp_dev->hw_ops->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);
-+
-+      mutex_lock(&isp_dev->power_lock);
-+      /* restore controls */
-+      if (enable && isp_dev->power_count == 1) {
-+              mutex_unlock(&isp_dev->power_lock);
-+              ret = v4l2_ctrl_handler_setup(&isp_dev->ctrls.handler);
-+      } else
-+              mutex_unlock(&isp_dev->power_lock);
-+
-+      return ret;
-+}
-+
-+/*Try to match sensor format with sink, and then get the index as default.*/
-+static int isp_match_sensor_format_get_index(struct stf_isp_dev *isp_dev)
-+{
-+      int ret, idx;
-+      struct media_entity *sensor;
-+      struct v4l2_subdev *subdev;
-+      struct v4l2_subdev_format fmt;
-+      const struct isp_format_table *formats;
-+
-+      if (!isp_dev)
-+              return -EINVAL;
-+
-+      sensor = stfcamss_find_sensor(&isp_dev->subdev.entity);
-+      if (!sensor)
-+              return -EINVAL;
-+
-+      subdev = media_entity_to_v4l2_subdev(sensor);
-+      st_debug(ST_ISP, "Found sensor = %s\n", sensor->name);
-+
-+      fmt.pad = 0;
-+      fmt.which = V4L2_SUBDEV_FORMAT_ACTIVE;
-+      ret = v4l2_subdev_call(subdev, pad, get_fmt, NULL, &fmt);
-+      if (ret) {
-+              st_warn(ST_ISP, "Sonser get format failed !!\n");
-+              return -EINVAL;
-+      }
-+
-+      st_debug(ST_ISP, "Got sensor format 0x%x !!\n", fmt.format.code);
-+
-+      formats = &isp_dev->formats[0];         /* isp sink format */
-+      for (idx = 0; idx < formats->nfmts; idx++) {
-+              if (formats->fmts[idx].code == fmt.format.code) {
-+                      st_info(ST_ISP,
-+                              "Match sensor format to isp_formats_st7110_sink index %d !!\n",
-+                              idx);
-+                      return idx;
-+              }
-+      }
-+      return -ERANGE;
-+}
-+
-+static int isp_match_format_get_index(const struct isp_format_table *f_table,
-+                      __u32 mbus_code,
-+                      unsigned int pad)
-+{
-+      int i;
-+
-+      for (i = 0; i < f_table->nfmts; i++) {
-+              if (mbus_code == f_table->fmts[i].code) {
-+                      break;
-+              } else {
-+                      if (pad == STF_ISP_PAD_SRC_RAW || pad == STF_ISP_PAD_SRC_SCD_Y) {
-+                              if (mbus_code == (isp_formats_st7110_compat_10bit_raw[i].code ||
-+                                      isp_formats_st7110_compat_8bit_raw[i].code))
-+                                      break;
-+                      }
-+              }
-+      }
-+
-+      return i;
-+}
-+
-+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;
-+      unsigned int i;
-+      u32 code = fmt->code;
-+      u32 bpp;
-+
-+      if (pad == STF_ISP_PAD_SINK) {
-+              /* Set format on sink pad */
-+
-+              formats = &isp_dev->formats[pad];
-+              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;
-+      } else {
-+              formats = &isp_dev->formats[pad];
-+      }
-+
-+      i = isp_match_format_get_index(formats, fmt->code, pad);
-+      st_debug(ST_ISP, "%s pad=%d, code=%x isp_match_format_get_index = %d\n",
-+                                      __func__, pad, code, i);
-+
-+      if (i >= formats->nfmts &&
-+              (pad == STF_ISP_PAD_SRC_RAW || pad == STF_ISP_PAD_SRC_SCD_Y)) {
-+              int sensor_idx;
-+
-+              sensor_idx = isp_match_sensor_format_get_index(isp_dev);
-+              if (sensor_idx)
-+                      i = sensor_idx;
-+      }
-+
-+      if (pad != STF_ISP_PAD_SINK)
-+              *fmt = *__isp_get_format(isp_dev, state, STF_ISP_PAD_SINK, which);
-+
-+      if (i >= formats->nfmts) {
-+              fmt->code = formats->fmts[0].code;
-+              bpp = formats->fmts[0].bpp;
-+              st_info(ST_ISP, "Use default index 0 format = 0x%x\n", fmt->code);
-+      } else {
-+              // sink format and raw format must one by one
-+              if (pad == STF_ISP_PAD_SRC_RAW || pad == STF_ISP_PAD_SRC_SCD_Y) {
-+                      fmt->code = formats->fmts[i].code;
-+                      bpp = formats->fmts[i].bpp;
-+                      st_info(ST_ISP, "Use mapping format from sink index %d = 0x%x\n",
-+                                      i, fmt->code);
-+              } else {
-+                      fmt->code = code;
-+                      bpp = formats->fmts[i].bpp;
-+                      st_info(ST_ISP, "Use input format = 0x%x\n", fmt->code);
-+              }
-+      }
-+
-+      switch (pad) {
-+      case STF_ISP_PAD_SINK:
-+              break;
-+      case STF_ISP_PAD_SRC:
-+              isp_dev->rect[ISP_COMPOSE].bpp = bpp;
-+              break;
-+      case STF_ISP_PAD_SRC_SS0:
-+              isp_dev->rect[ISP_SCALE_SS0].bpp = bpp;
-+              break;
-+      case STF_ISP_PAD_SRC_SS1:
-+              isp_dev->rect[ISP_SCALE_SS1].bpp = bpp;
-+              break;
-+      case STF_ISP_PAD_SRC_ITIW:
-+      case STF_ISP_PAD_SRC_ITIR:
-+              isp_dev->rect[ISP_ITIWS].bpp = bpp;
-+              break;
-+      case STF_ISP_PAD_SRC_RAW:
-+              isp_dev->rect[ISP_CROP].bpp = bpp;
-+              break;
-+      case STF_ISP_PAD_SRC_SCD_Y:
-+              break;
-+      }
-+}
-+
-+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->formats[code->pad].nfmts)
-+              return -EINVAL;
-+
-+      formats = &isp_dev->formats[code->pad];
-+      code->code = formats->fmts[code->index].code;
-+      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 == NULL)
-+              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;
-+      struct v4l2_subdev_selection sel = { 0 };
-+      struct v4l2_rect *rect = NULL;
-+      int ret;
-+
-+      st_debug(ST_ISP, "%s pad=%d, code=%x, which=%d\n",
-+                      __func__, fmt->reserved[0], fmt->format.code, fmt->which);
-+      format = __isp_get_format(isp_dev, state, fmt->pad, fmt->which);
-+      if (format == NULL)
-+              return -EINVAL;
-+
-+      mutex_lock(&isp_dev->stream_lock);
-+      if (isp_dev->stream_count) {
-+              fmt->format = *format;
-+              if (fmt->reserved[0] != 0) {
-+                      sel.which = fmt->which;
-+                      sel.pad = fmt->reserved[0];
-+
-+                      switch (fmt->reserved[0]) {
-+                      case STF_ISP_PAD_SRC:
-+                              rect = __isp_get_compose(isp_dev, state, fmt->which);
-+                              break;
-+                      case STF_ISP_PAD_SRC_SS0:
-+                      case STF_ISP_PAD_SRC_SS1:
-+                              rect = __isp_get_scale(isp_dev, state, &sel);
-+                              break;
-+                      case STF_ISP_PAD_SRC_ITIW:
-+                      case STF_ISP_PAD_SRC_ITIR:
-+                              rect = __isp_get_itiws(isp_dev, state, fmt->which);
-+                              break;
-+                      case STF_ISP_PAD_SRC_RAW:
-+                      case STF_ISP_PAD_SRC_SCD_Y:
-+                              rect = __isp_get_crop(isp_dev, state, fmt->which);
-+                              break;
-+                      default:
-+                              break;
-+                      }
-+                      if (rect != NULL) {
-+                              fmt->format.width = rect->width;
-+                              fmt->format.height = rect->height;
-+                      }
-+              }
-+              mutex_unlock(&isp_dev->stream_lock);
-+              goto out;
-+      } else {
-+              isp_try_format(isp_dev, state, fmt->pad, &fmt->format, fmt->which);
-+              *format = fmt->format;
-+      }
-+      mutex_unlock(&isp_dev->stream_lock);
-+
-+      /* Propagate the format from sink to source */
-+      if (fmt->pad == STF_ISP_PAD_SINK) {
-+              /* 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;
-+      }
-+
-+out:
-+      return 0;
-+}
-+
-+static struct v4l2_rect *
-+__isp_get_compose(struct stf_isp_dev *isp_dev,
-+                struct v4l2_subdev_state *state,
-+                enum v4l2_subdev_format_whence which)
-+{
-+      if (which == V4L2_SUBDEV_FORMAT_TRY)
-+              return v4l2_subdev_get_try_compose(&isp_dev->subdev, state,
-+                                                 STF_ISP_PAD_SINK);
-+
-+
-+      return &isp_dev->rect[ISP_COMPOSE].rect;
-+}
-+
-+static struct v4l2_rect *
-+__isp_get_crop(struct stf_isp_dev *isp_dev,
-+              struct v4l2_subdev_state *state,
-+              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[ISP_CROP].rect;
-+}
-+
-+static struct v4l2_rect *
-+__isp_get_scale(struct stf_isp_dev *isp_dev,
-+              struct v4l2_subdev_state *state,
-+              struct v4l2_subdev_selection *sel)
-+{
-+      int pad;
-+
-+      if (sel->which == V4L2_SUBDEV_FORMAT_TRY)
-+              return v4l2_subdev_get_try_compose(&isp_dev->subdev, state,
-+                                              STF_ISP_PAD_SINK);
-+      if (sel->pad != STF_ISP_PAD_SRC_SS0 && sel->pad != STF_ISP_PAD_SRC_SS1)
-+              return NULL;
-+
-+      pad = sel->pad == STF_ISP_PAD_SRC_SS0 ? ISP_SCALE_SS0 : ISP_SCALE_SS1;
-+      return &isp_dev->rect[pad].rect;
-+}
-+
-+static struct v4l2_rect *
-+__isp_get_itiws(struct stf_isp_dev *isp_dev,
-+              struct v4l2_subdev_state *state,
-+              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[ISP_ITIWS].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_MIN_WIDTH;
-+      }
-+
-+      if (rect->height < STFCAMSS_FRAME_MIN_HEIGHT) {
-+              rect->top = 0;
-+              rect->height = STFCAMSS_FRAME_MIN_HEIGHT;
-+      }
-+      rect->height &= ~0x1;
-+}
-+
-+static void isp_try_compose(struct stf_isp_dev *isp_dev,
-+                       struct v4l2_subdev_state *state,
-+                       struct v4l2_rect *rect,
-+                       enum v4l2_subdev_format_whence which)
-+{
-+      struct v4l2_rect *crop;
-+
-+      crop = __isp_get_crop(isp_dev, state, which);
-+
-+      if (rect->width > crop->width)
-+              rect->width = crop->width;
-+
-+      if (rect->height > crop->height)
-+              rect->height = crop->height;
-+
-+      if (crop->width > rect->width * SCALER_RATIO_MAX)
-+              rect->width = (crop->width + SCALER_RATIO_MAX - 1) /
-+                                                      SCALER_RATIO_MAX;
-+
-+      if (crop->height > rect->height * SCALER_RATIO_MAX)
-+              rect->height = (crop->height + SCALER_RATIO_MAX - 1) /
-+                                                      SCALER_RATIO_MAX;
-+
-+      if (rect->width < STFCAMSS_FRAME_MIN_WIDTH)
-+              rect->width = STFCAMSS_FRAME_MIN_WIDTH;
-+
-+      if (rect->height < STFCAMSS_FRAME_MIN_HEIGHT)
-+              rect->height = STFCAMSS_FRAME_MIN_HEIGHT;
-+      rect->height &= ~0x1;
-+}
-+
-+static void isp_try_scale(struct stf_isp_dev *isp_dev,
-+                          struct v4l2_subdev_state *state,
-+                          struct v4l2_rect *rect,
-+                          enum v4l2_subdev_format_whence which)
-+{
-+      struct v4l2_rect *compose;
-+
-+      compose = __isp_get_compose(isp_dev, state, which);
-+
-+      if (rect->width > compose->width)
-+              rect->width = compose->width;
-+
-+      if (rect->width + rect->left > compose->width)
-+              rect->left = compose->width - rect->width;
-+
-+      if (rect->height > compose->height)
-+              rect->height = compose->height;
-+
-+      if (rect->height + rect->top > compose->height)
-+              rect->top = compose->height - rect->height;
-+
-+      if (rect->width < STFCAMSS_FRAME_MIN_WIDTH) {
-+              rect->left = 0;
-+              rect->width = STFCAMSS_FRAME_MIN_WIDTH;
-+      }
-+
-+      if (rect->height < STFCAMSS_FRAME_MIN_HEIGHT) {
-+              rect->top = 0;
-+              rect->height = STFCAMSS_FRAME_MIN_HEIGHT;
-+      }
-+      rect->height &= ~0x1;
-+}
-+
-+static void isp_try_itiws(struct stf_isp_dev *isp_dev,
-+                          struct v4l2_subdev_state *state,
-+                          struct v4l2_rect *rect,
-+                          enum v4l2_subdev_format_whence which)
-+{
-+      struct v4l2_rect *crop;
-+
-+      crop = __isp_get_crop(isp_dev, state, which);
-+
-+      if (rect->width > crop->width)
-+              rect->width = crop->width;
-+
-+      if (rect->width + rect->left > crop->width)
-+              rect->left = crop->width - rect->width;
-+
-+      if (rect->height > crop->height)
-+              rect->height = crop->height;
-+
-+      if (rect->height + rect->top > crop->height)
-+              rect->top = crop->height - rect->height;
-+
-+      if (rect->width < STFCAMSS_FRAME_MIN_WIDTH) {
-+              rect->left = 0;
-+              rect->width = STFCAMSS_FRAME_MIN_WIDTH;
-+      }
-+
-+      if (rect->height < STFCAMSS_FRAME_MIN_HEIGHT) {
-+              rect->top = 0;
-+              rect->height = STFCAMSS_FRAME_MIN_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:
-+      case V4L2_SEL_TGT_CROP_DEFAULT:
-+              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;
-+              break;
-+      case V4L2_SEL_TGT_CROP:
-+              rect = __isp_get_crop(isp_dev, state, sel->which);
-+              if (rect == NULL)
-+                      return -EINVAL;
-+
-+              sel->r = *rect;
-+              break;
-+      case V4L2_SEL_TGT_COMPOSE_BOUNDS:
-+      case V4L2_SEL_TGT_COMPOSE_DEFAULT:
-+              if (sel->pad > STF_ISP_PAD_SRC_ITIR)
-+                      return -EINVAL;
-+              rect = __isp_get_crop(isp_dev, state, sel->which);
-+              if (rect == NULL)
-+                      return -EINVAL;
-+
-+              sel->r.left = rect->left;
-+              sel->r.top = rect->top;
-+              sel->r.width = rect->width;
-+              sel->r.height = rect->height;
-+              break;
-+      case V4L2_SEL_TGT_COMPOSE:
-+              if (sel->pad > STF_ISP_PAD_SRC_ITIR)
-+                      return -EINVAL;
-+              if (sel->pad == STF_ISP_PAD_SRC_SS0
-+                      || sel->pad == STF_ISP_PAD_SRC_SS1) {
-+                      rect = __isp_get_scale(isp_dev, state, sel);
-+                      if (rect == NULL)
-+                              return -EINVAL;
-+              } else if (sel->pad == STF_ISP_PAD_SRC_ITIW
-+                      || sel->pad == STF_ISP_PAD_SRC_ITIR) {
-+                      rect = __isp_get_itiws(isp_dev, state, sel->which);
-+                      if (rect == NULL)
-+                              return -EINVAL;
-+              } else {
-+                      rect = __isp_get_compose(isp_dev, state, sel->which);
-+                      if (rect == NULL)
-+                              return -EINVAL;
-+              }
-+              sel->r = *rect;
-+              break;
-+      default:
-+              return -EINVAL;
-+      }
-+
-+      st_info(ST_ISP, "%s pad = %d, left = %d, %d, %d, %d\n",
-+                      __func__, sel->pad, sel->r.left, sel->r.top, sel->r.width, sel->r.height);
-+      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_COMPOSE &&
-+                      ((sel->pad == STF_ISP_PAD_SINK)
-+                       || (sel->pad == STF_ISP_PAD_SRC))) {
-+              struct v4l2_subdev_format fmt = { 0 };
-+              int i;
-+
-+              rect = __isp_get_compose(isp_dev, state, sel->which);
-+              if (rect == NULL)
-+                      return -EINVAL;
-+
-+              mutex_lock(&isp_dev->stream_lock);
-+              if (isp_dev->stream_count) {
-+                      sel->r = *rect;
-+                      mutex_unlock(&isp_dev->stream_lock);
-+                      ret = 0;
-+                      goto out;
-+              } else {
-+                      isp_try_compose(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;
-+              ret = isp_get_format(sd, state, &fmt);
-+              if (ret < 0)
-+                      return ret;
-+
-+              fmt.format.width = rect->width;
-+              fmt.format.height = rect->height;
-+              ret = isp_set_format(sd, state, &fmt);
-+
-+              /* Reset scale */
-+              for (i = STF_ISP_PAD_SRC_SS0; i <= STF_ISP_PAD_SRC_ITIR; i++) {
-+                      struct v4l2_subdev_selection scale = { 0 };
-+
-+                      scale.which = sel->which;
-+                      scale.target = V4L2_SEL_TGT_COMPOSE;
-+                      scale.r = *rect;
-+                      scale.pad = i;
-+                      ret = isp_set_selection(sd, state, &scale);
-+              }
-+      } else if (sel->target == V4L2_SEL_TGT_COMPOSE
-+                      && ((sel->pad == STF_ISP_PAD_SRC_SS0)
-+                              || (sel->pad == STF_ISP_PAD_SRC_SS1))) {
-+              struct v4l2_subdev_format fmt = { 0 };
-+
-+              rect = __isp_get_scale(isp_dev, state, sel);
-+              if (rect == NULL)
-+                      return -EINVAL;
-+
-+              mutex_lock(&isp_dev->stream_lock);
-+              if (isp_dev->stream_count) {
-+                      sel->r = *rect;
-+                      mutex_unlock(&isp_dev->stream_lock);
-+                      ret = 0;
-+                      goto out;
-+              } else {
-+                      isp_try_scale(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 = sel->pad;
-+              ret = isp_get_format(sd, state, &fmt);
-+              if (ret < 0)
-+                      return ret;
-+
-+              fmt.format.width = rect->width;
-+              fmt.format.height = rect->height;
-+              ret = isp_set_format(sd, state, &fmt);
-+      } else if (sel->target == V4L2_SEL_TGT_COMPOSE
-+                      && ((sel->pad == STF_ISP_PAD_SRC_ITIW)
-+                              || (sel->pad == STF_ISP_PAD_SRC_ITIR))) {
-+              struct v4l2_subdev_format fmt = { 0 };
-+
-+              rect = __isp_get_itiws(isp_dev, state, sel->which);
-+              if (rect == NULL)
-+                      return -EINVAL;
-+
-+              mutex_lock(&isp_dev->stream_lock);
-+              if (isp_dev->stream_count) {
-+                      sel->r = *rect;
-+                      mutex_unlock(&isp_dev->stream_lock);
-+                      ret = 0;
-+                      goto out;
-+              } else {
-+                      isp_try_itiws(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 = sel->pad;
-+              ret = isp_get_format(sd, state, &fmt);
-+              if (ret < 0)
-+                      return ret;
-+
-+              fmt.format.width = rect->width;
-+              fmt.format.height = rect->height;
-+              ret = isp_set_format(sd, state, &fmt);
-+      } else if (sel->target == V4L2_SEL_TGT_CROP) {
-+              struct v4l2_subdev_selection compose = { 0 };
-+              int i;
-+
-+              rect = __isp_get_crop(isp_dev, state, sel->which);
-+              if (rect == NULL)
-+                      return -EINVAL;
-+
-+              mutex_lock(&isp_dev->stream_lock);
-+              if (isp_dev->stream_count) {
-+                      sel->r = *rect;
-+                      mutex_unlock(&isp_dev->stream_lock);
-+                      ret = 0;
-+                      goto out;
-+              } else {
-+                      isp_try_crop(isp_dev, state, &sel->r, sel->which);
-+                      *rect = sel->r;
-+              }
-+              mutex_unlock(&isp_dev->stream_lock);
-+
-+              /* Reset source compose selection */
-+              compose.which = sel->which;
-+              compose.target = V4L2_SEL_TGT_COMPOSE;
-+              compose.r.width = rect->width;
-+              compose.r.height = rect->height;
-+              compose.pad = STF_ISP_PAD_SINK;
-+              ret = isp_set_selection(sd, state, &compose);
-+
-+              /* Reset source pad format width and height */
-+              for (i = STF_ISP_PAD_SRC_RAW; i < STF_ISP_PAD_MAX; i++) {
-+                      struct v4l2_subdev_format fmt = { 0 };
-+
-+                      fmt.which = sel->which;
-+                      fmt.pad = i;
-+                      ret = isp_get_format(sd, state, &fmt);
-+                      if (ret < 0)
-+                              return ret;
-+
-+                      fmt.format.width = rect->width;
-+                      fmt.format.height = rect->height;
-+                      ret = isp_set_format(sd, state, &fmt);
-+              }
-+      } else {
-+              ret = -EINVAL;
-+      }
-+
-+      st_info(ST_ISP, "%s pad = %d, left = %d, %d, %d, %d\n",
-+                      __func__, sel->pad, sel->r.left, sel->r.top, sel->r.width, sel->r.height);
-+out:
-+      return ret;
-+}
-+
-+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_load_setfile(struct stf_isp_dev *isp_dev, char *file_name)
-+{
-+      struct device *dev = isp_dev->stfcamss->dev;
-+      const struct firmware *fw;
-+      u8 *buf = NULL;
-+      int *regval_num;
-+      int ret;
-+
-+      st_debug(ST_ISP, "%s, file_name %s\n", __func__, file_name);
-+      ret = request_firmware(&fw, file_name, dev);
-+      if (ret < 0) {
-+              st_err(ST_ISP, "firmware request failed (%d)\n", ret);
-+              return ret;
-+      }
-+      buf = devm_kzalloc(dev, fw->size, GFP_KERNEL);
-+      if (!buf)
-+              return -ENOMEM;
-+      memcpy(buf, fw->data, fw->size);
-+
-+      mutex_lock(&isp_dev->setfile_lock);
-+      if (isp_dev->setfile.state == 1)
-+              devm_kfree(dev, isp_dev->setfile.data);
-+      isp_dev->setfile.data = buf;
-+      isp_dev->setfile.size = fw->size;
-+      isp_dev->setfile.state = 1;
-+      regval_num = (int *)&buf[fw->size - sizeof(unsigned int)];
-+      isp_dev->setfile.settings.regval_num = *regval_num;
-+      isp_dev->setfile.settings.regval = (struct regval_t *)buf;
-+      mutex_unlock(&isp_dev->setfile_lock);
-+
-+      st_debug(ST_ISP, "stf_isp setfile loaded size: %zu B, reg_nul: %d\n",
-+                      fw->size, isp_dev->setfile.settings.regval_num);
-+
-+      release_firmware(fw);
-+      return ret;
-+}
-+
-+static long stf_isp_ioctl(struct v4l2_subdev *sd, unsigned int cmd, void *arg)
-+{
-+      struct stf_isp_dev *isp_dev = v4l2_get_subdevdata(sd);
-+      struct device *dev = isp_dev->stfcamss->dev;
-+      int ret = -ENOIOCTLCMD;
-+
-+      switch (cmd) {
-+      case VIDIOC_STFISP_LOAD_FW: {
-+              struct stfisp_fw_info *fw_info = arg;
-+
-+              if (IS_ERR(fw_info)) {
-+                      st_err(ST_ISP, "fw_info failed, params invaild\n");
-+                      return -EINVAL;
-+              }
-+
-+              ret = stf_isp_load_setfile(isp_dev, fw_info->filename);
-+              break;
-+      }
-+      case VIDIOC_STF_DMABUF_ALLOC:
-+      case VIDIOC_STF_DMABUF_FREE:
-+              ret = stf_dmabuf_ioctl(dev, cmd, arg);
-+              break;
-+      case VIDIOC_STFISP_GET_REG:
-+              ret = isp_dev->hw_ops->isp_reg_read(isp_dev, arg);
-+              break;
-+      case VIDIOC_STFISP_SET_REG:
-+              ret = isp_dev->hw_ops->isp_reg_write(isp_dev, arg);
-+              break;
-+      case VIDIOC_STFISP_SHADOW_LOCK:
-+              if (atomic_add_unless(&isp_dev->shadow_count, 1, 1))
-+                      ret = 0;
-+              else
-+                      ret = -EBUSY;
-+              st_debug(ST_ISP, "%s, %d, ret = %d\n", __func__, __LINE__, ret);
-+              break;
-+      case VIDIOC_STFISP_SHADOW_UNLOCK:
-+              if (atomic_dec_if_positive(&isp_dev->shadow_count) < 0)
-+                      ret = -EINVAL;
-+              else
-+                      ret = 0;
-+              st_debug(ST_ISP, "%s, %d, ret = %d\n", __func__, __LINE__, ret);
-+              break;
-+      case VIDIOC_STFISP_SHADOW_UNLOCK_N_TRIGGER:
-+              {
-+                      isp_dev->hw_ops->isp_shadow_trigger(isp_dev);
-+                      if (atomic_dec_if_positive(&isp_dev->shadow_count) < 0)
-+                              ret = -EINVAL;
-+                      else
-+                              ret = 0;
-+                      st_debug(ST_ISP, "%s, %d, ret = %d\n", __func__, __LINE__, ret);
-+              }
-+              break;
-+      case VIDIOC_STFISP_SET_USER_CONFIG_ISP:
-+              st_debug(ST_ISP, "%s, %d set user_config_isp\n", __func__, __LINE__);
-+              user_config_isp = 1;
-+              break;
-+      default:
-+              break;
-+      }
-+      return ret;
-+}
-+
-+int isp_close(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh)
-+{
-+      struct stf_isp_dev *isp_dev = v4l2_get_subdevdata(sd);
-+
-+      st_debug(ST_ISP, "%s, %d\n", __func__, __LINE__);
-+      while (atomic_dec_if_positive(&isp_dev->shadow_count) > 0)
-+              st_warn(ST_ISP, "user not unlocked the shadow lock, driver unlock it!\n");
-+
-+      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);
-+      case V4L2_EVENT_CTRL:
-+              return v4l2_ctrl_subdev_subscribe_event(sd, fh, sub);
-+      default:
-+              st_debug(ST_ISP, "unspport subscribe_event\n");
-+              return -EINVAL;
-+      }
-+}
-+
-+static const struct v4l2_subdev_core_ops isp_core_ops = {
-+      .s_power = isp_set_power,
-+      .ioctl = stf_isp_ioctl,
-+      .log_status = v4l2_ctrl_subdev_log_status,
-+      // .subscribe_event = v4l2_ctrl_subdev_subscribe_event,
-+      .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,
-+      .close = isp_close,
-+};
-+
-+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) {
-+              st_err(ST_ISP, "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;
-+      pads[STF_ISP_PAD_SRC_SS0].flags = MEDIA_PAD_FL_SOURCE;
-+      pads[STF_ISP_PAD_SRC_SS1].flags = MEDIA_PAD_FL_SOURCE;
-+      pads[STF_ISP_PAD_SRC_ITIW].flags = MEDIA_PAD_FL_SOURCE;
-+      pads[STF_ISP_PAD_SRC_ITIR].flags = MEDIA_PAD_FL_SOURCE;
-+      pads[STF_ISP_PAD_SRC_RAW].flags = MEDIA_PAD_FL_SOURCE;
-+      pads[STF_ISP_PAD_SRC_SCD_Y].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) {
-+              st_err(ST_ISP, "Failed to init media entity: %d\n", ret);
-+              return ret;
-+      }
-+
-+      ret = isp_init_controls(isp_dev);
-+      if (ret)
-+              goto err_sreg;
-+
-+      ret = v4l2_device_register_subdev(v4l2_dev, sd);
-+      if (ret < 0) {
-+              st_err(ST_ISP, "Failed to register subdev: %d\n", ret);
-+              goto free_ctrls;
-+      }
-+
-+      return 0;
-+
-+free_ctrls:
-+      v4l2_ctrl_handler_free(&isp_dev->ctrls.handler);
-+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);
-+      v4l2_ctrl_handler_free(&isp_dev->ctrls.handler);
-+      mutex_destroy(&isp_dev->stream_lock);
-+      mutex_destroy(&isp_dev->power_lock);
-+      mutex_destroy(&isp_dev->setfile_lock);
-+      return 0;
-+}
---- /dev/null
-+++ b/drivers/media/platform/starfive/v4l2_driver/stf_isp.h
-@@ -0,0 +1,222 @@
-+/* SPDX-License-Identifier: GPL-2.0
-+ *
-+ * Copyright (C) 2021-2023 StarFive Technology Co., Ltd.
-+ *
-+ */
-+
-+#ifndef STF_ISP_H
-+#define STF_ISP_H
-+
-+#include <media/v4l2-subdev.h>
-+#include <media/v4l2-ctrls.h>
-+#include <media/v4l2-device.h>
-+#include <media/media-entity.h>
-+#include <video/stf-vin.h>
-+
-+#define STF_ISP_NAME "stf_isp"
-+#define STF_ISP_SETFILE     "stf_isp0_fw.bin"
-+
-+#define ISP_SCD_BUFFER_SIZE     (19 * 256 * 4)  // align 128
-+#define ISP_YHIST_BUFFER_SIZE   (64 * 4)
-+#define ISP_SCD_Y_BUFFER_SIZE   (ISP_SCD_BUFFER_SIZE + ISP_YHIST_BUFFER_SIZE)
-+#define ISP_RAW_DATA_BITS       12
-+#define SCALER_RATIO_MAX        1  // no compose function
-+#define STF_ISP_REG_OFFSET_MAX  0x0FFF
-+#define STF_ISP_REG_DELAY_MAX   100
-+
-+#define ISP_REG_CSIINTS_ADDR    0x00000008
-+#define ISP_REG_SENSOR          0x00000014
-+#define ISP_REG_DUMP_CFG_0      0x00000024
-+#define ISP_REG_DUMP_CFG_1      0x00000028
-+#define ISP_REG_SCD_CFG_0       0x00000098
-+#define ISP_REG_SCD_CFG_1       0x0000009C
-+#define ISP_REG_SC_CFG_1        0x000000BC
-+#define ISP_REG_IESHD_ADDR      0x00000A50
-+#define ISP_REG_SS0AY           0x00000A94
-+#define ISP_REG_SS0AUV          0x00000A98
-+#define ISP_REG_SS0S            0x00000A9C
-+#define ISP_REG_SS0IW           0x00000AA8
-+#define ISP_REG_SS1AY           0x00000AAC
-+#define ISP_REG_SS1AUV          0x00000AB0
-+#define ISP_REG_SS1S            0x00000AB4
-+#define ISP_REG_SS1IW           0x00000AC0
-+#define ISP_REG_YHIST_CFG_4     0x00000CD8
-+#define ISP_REG_ITIIWSR         0x00000B20
-+#define ISP_REG_ITIDWLSR        0x00000B24
-+#define ISP_REG_ITIDWYSAR       0x00000B28
-+#define ISP_REG_ITIDWUSAR       0x00000B2C
-+#define ISP_REG_ITIDRYSAR       0x00000B30
-+#define ISP_REG_ITIDRUSAR       0x00000B34
-+#define ISP_REG_ITIPDFR         0x00000B38
-+#define ISP_REG_ITIDRLSR        0x00000B3C
-+#define ISP_REG_ITIBSR          0x00000B40
-+#define ISP_REG_ITIAIR          0x00000B44
-+#define ISP_REG_ITIDPSR         0x00000B48
-+
-+/* The output line of a isp controller */
-+enum isp_line_id {
-+      STF_ISP_LINE_INVALID = -1,
-+      STF_ISP_LINE_SRC = 1,
-+      STF_ISP_LINE_SRC_SS0 = 2,
-+      STF_ISP_LINE_SRC_SS1 = 3,
-+      STF_ISP_LINE_SRC_ITIW = 4,
-+      STF_ISP_LINE_SRC_ITIR = 5,
-+      STF_ISP_LINE_SRC_RAW = 6,
-+      STF_ISP_LINE_SRC_SCD_Y = 7,
-+      STF_ISP_LINE_MAX = STF_ISP_LINE_SRC_SCD_Y
-+};
-+
-+/* pad id for media framework */
-+enum isp_pad_id {
-+      STF_ISP_PAD_SINK = 0,
-+      STF_ISP_PAD_SRC = 1,
-+      STF_ISP_PAD_SRC_SS0 = 2,
-+      STF_ISP_PAD_SRC_SS1 = 3,
-+      STF_ISP_PAD_SRC_ITIW = 4,
-+      STF_ISP_PAD_SRC_ITIR = 5,
-+      STF_ISP_PAD_SRC_RAW = 6,
-+      STF_ISP_PAD_SRC_SCD_Y = 7,
-+      STF_ISP_PAD_MAX = 8
-+};
-+
-+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 {
-+      DVP_SENSOR = 0,
-+      CSI_SENSOR,
-+};
-+
-+#define ISP_AWB_OECF_SKIP_FRAME  0
-+// 0x0BC [31:30] SEL - sc0 input mux for sc awb
-+// 00 : after DEC, 01 : after OBC, 10 : after OECF, 11 : after AWB
-+enum scd_type {
-+      DEC_TYPE = 0,
-+      OBC_TYPE,
-+      OECF_TYPE,
-+      AWB_TYPE
-+};
-+
-+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 mask;
-+      u32 delay_ms;
-+};
-+
-+struct reg_table {
-+      struct regval_t *regval;
-+      int regval_num;
-+};
-+
-+struct isp_stream_format {
-+      struct v4l2_rect rect;
-+      u32 bpp;
-+};
-+
-+struct stf_isp_dev;
-+enum subdev_type;
-+
-+struct isp_hw_ops {
-+      int (*isp_clk_enable)(struct stf_isp_dev *isp_dev);
-+      int (*isp_clk_disable)(struct stf_isp_dev *isp_dev);
-+      int (*isp_reset)(struct stf_isp_dev *isp_dev);
-+      int (*isp_config_set)(struct stf_isp_dev *isp_dev);
-+      int (*isp_set_format)(struct stf_isp_dev *isp_dev,
-+                      struct isp_stream_format *crop, u32 mcode,
-+                      int type);
-+                      // u32 width, u32 height);
-+      int (*isp_stream_set)(struct stf_isp_dev *isp_dev, int on);
-+      int (*isp_reg_read)(struct stf_isp_dev *isp_dev, void *arg);
-+      int (*isp_reg_write)(struct stf_isp_dev *isp_dev, void *arg);
-+      int (*isp_shadow_trigger)(struct stf_isp_dev *isp_dev);
-+};
-+
-+struct isp_ctrls {
-+      struct v4l2_ctrl_handler handler;
-+      struct v4l2_ctrl *pixel_rate;
-+      struct {
-+              struct v4l2_ctrl *auto_exp;
-+              struct v4l2_ctrl *exposure;
-+      };
-+      struct {
-+              struct v4l2_ctrl *auto_wb;
-+              struct v4l2_ctrl *blue_balance;
-+              struct v4l2_ctrl *red_balance;
-+      };
-+      struct {
-+              struct v4l2_ctrl *auto_gain;
-+              struct v4l2_ctrl *gain;
-+      };
-+      struct v4l2_ctrl *brightness;
-+      struct v4l2_ctrl *light_freq;
-+      struct v4l2_ctrl *saturation;
-+      struct v4l2_ctrl *contrast;
-+      struct v4l2_ctrl *hue;
-+      struct v4l2_ctrl *test_pattern;
-+      struct v4l2_ctrl *hflip;
-+      struct v4l2_ctrl *vflip;
-+};
-+
-+struct isp_setfile {
-+      struct reg_table settings;
-+      const u8 *data;
-+      unsigned int size;
-+      unsigned int state;
-+};
-+
-+enum {
-+      ISP_CROP = 0,
-+      ISP_COMPOSE,
-+      ISP_SCALE_SS0,
-+      ISP_SCALE_SS1,
-+      ISP_ITIWS,
-+      ISP_RECT_MAX
-+};
-+
-+struct stf_isp_dev {
-+      enum subdev_type sdev_type;  // must be frist
-+      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 isp_stream_format rect[ISP_RECT_MAX];
-+      const struct isp_format_table *formats;
-+      unsigned int nformats;
-+      struct isp_hw_ops *hw_ops;
-+      struct mutex power_lock;
-+      int power_count;
-+      struct mutex stream_lock;
-+      int stream_count;
-+      atomic_t shadow_count;
-+
-+      struct isp_ctrls ctrls;
-+      struct mutex setfile_lock;
-+      struct isp_setfile setfile;
-+      struct reg_table *context_regs;
-+};
-+
-+extern int stf_isp_subdev_init(struct stfcamss *stfcamss);
-+extern int stf_isp_register(struct stf_isp_dev *isp_dev,
-+              struct v4l2_device *v4l2_dev);
-+extern int stf_isp_unregister(struct stf_isp_dev *isp_dev);
-+extern struct isp_hw_ops isp_ops;
-+extern void dump_isp_reg(void *__iomem ispbase);
-+
-+#endif /* STF_ISP_H */
---- /dev/null
-+++ b/drivers/media/platform/starfive/v4l2_driver/stf_isp_hw_ops.c
-@@ -0,0 +1,1550 @@
-+// SPDX-License-Identifier: GPL-2.0
-+/*
-+ * Copyright (C) 2021-2023 StarFive Technology Co., Ltd.
-+ *
-+ */
-+
-+#include "stfcamss.h"
-+#include <linux/io.h>
-+#include <linux/fb.h>
-+#include <linux/module.h>
-+#include <video/stf-vin.h>
-+#include "stf_isp_ioctl.h"
-+#include "stf_isp.h"
-+#include <linux/delay.h>
-+#include <linux/clk.h>
-+#define USE_NEW_CONFIG_SETTING
-+
-+static struct regval_t isp_reg_init_config_list[] = {
-+      /* config DC(0040H~0044H) */
-+      {0x00000044, 0x00000000, 0, 0},
-+      /* config DEC(0030H) */
-+      {0x00000030, 0x00000000, 0, 0},
-+      /* config OBC(0034H, 02E0H~02FCH) */
-+      {0x00000034, 0x000000BB, 0, 0},
-+      {0x000002E0, 0x40404040, 0, 0},
-+      {0x000002E4, 0x40404040, 0, 0},
-+      {0x000002E8, 0x40404040, 0, 0},
-+      {0x000002EC, 0x40404040, 0, 0},
-+      {0x000002F0, 0x00000000, 0, 0},
-+      {0x000002F4, 0x00000000, 0, 0},
-+      {0x000002F8, 0x00000000, 0, 0},
-+      {0x000002FC, 0x00000000, 0, 0},
-+      /* config LCBQ(0074H, 007CH, 0300H~039FH, and 0400H~049FH) */
-+      {0x00000074, 0x00009900, 0, 0},
-+      {0x0000007C, 0x01E40040, 0, 0},
-+      {0x00000300, 0x01000100, 0, 0},
-+      {0x00000304, 0x01000100, 0, 0},
-+      {0x00000308, 0x01000100, 0, 0},
-+      {0x0000030C, 0x01000100, 0, 0},
-+      {0x00000310, 0x01000100, 0, 0},
-+      {0x00000314, 0x01000100, 0, 0},
-+      {0x00000318, 0x01000100, 0, 0},
-+      {0x0000031C, 0x01000100, 0, 0},
-+      {0x00000320, 0x01000100, 0, 0},
-+      {0x00000324, 0x01000100, 0, 0},
-+      {0x00000328, 0x01000100, 0, 0},
-+      {0x0000032C, 0x01000100, 0, 0},
-+      {0x00000330, 0x00000100, 0, 0},
-+      {0x00000334, 0x01000100, 0, 0},
-+      {0x00000338, 0x01000100, 0, 0},
-+      {0x0000033C, 0x01000100, 0, 0},
-+      {0x00000340, 0x01000100, 0, 0},
-+      {0x00000344, 0x01000100, 0, 0},
-+      {0x00000348, 0x01000100, 0, 0},
-+      {0x0000034C, 0x01000100, 0, 0},
-+      {0x00000350, 0x01000100, 0, 0},
-+      {0x00000354, 0x01000100, 0, 0},
-+      {0x00000358, 0x01000100, 0, 0},
-+      {0x0000035C, 0x01000100, 0, 0},
-+      {0x00000360, 0x01000100, 0, 0},
-+      {0x00000364, 0x00000100, 0, 0},
-+      {0x00000368, 0x01000100, 0, 0},
-+      {0x0000036C, 0x01000100, 0, 0},
-+      {0x00000370, 0x01000100, 0, 0},
-+      {0x00000374, 0x01000100, 0, 0},
-+      {0x00000378, 0x01000100, 0, 0},
-+      {0x0000037C, 0x01000100, 0, 0},
-+      {0x00000380, 0x01000100, 0, 0},
-+      {0x00000384, 0x01000100, 0, 0},
-+      {0x00000388, 0x01000100, 0, 0},
-+      {0x0000038C, 0x01000100, 0, 0},
-+      {0x00000390, 0x01000100, 0, 0},
-+      {0x00000394, 0x01000100, 0, 0},
-+      {0x00000398, 0x00000100, 0, 0},
-+      {0x0000039C, 0x01000100, 0, 0},
-+      {0x000003A0, 0x01000100, 0, 0},
-+      {0x000003A4, 0x01000100, 0, 0},
-+      {0x000003A8, 0x01000100, 0, 0},
-+      {0x000003AC, 0x01000100, 0, 0},
-+      {0x000003B0, 0x01000100, 0, 0},
-+      {0x000003B4, 0x01000100, 0, 0},
-+      {0x000003B8, 0x01000100, 0, 0},
-+      {0x000003BC, 0x01000100, 0, 0},
-+      {0x000003C0, 0x01000100, 0, 0},
-+      {0x000003C4, 0x01000100, 0, 0},
-+      {0x000003C8, 0x01000100, 0, 0},
-+      {0x000003CC, 0x00000100, 0, 0},
-+      {0x00000400, 0x00000000, 0, 0},
-+      {0x00000404, 0x00000000, 0, 0},
-+      {0x00000408, 0x00000000, 0, 0},
-+      {0x0000040C, 0x00000000, 0, 0},
-+      {0x00000410, 0x00000000, 0, 0},
-+      {0x00000414, 0x00000000, 0, 0},
-+      {0x00000418, 0x00000000, 0, 0},
-+      {0x0000041C, 0x00000000, 0, 0},
-+      {0x00000420, 0x00000000, 0, 0},
-+      {0x00000424, 0x00000000, 0, 0},
-+      {0x00000428, 0x00000000, 0, 0},
-+      {0x0000042C, 0x00000000, 0, 0},
-+      {0x00000430, 0x00000000, 0, 0},
-+      {0x00000434, 0x00000000, 0, 0},
-+      {0x00000438, 0x00000000, 0, 0},
-+      {0x0000043C, 0x00000000, 0, 0},
-+      {0x00000440, 0x00000000, 0, 0},
-+      {0x00000444, 0x00000000, 0, 0},
-+      {0x00000448, 0x00000000, 0, 0},
-+      {0x0000044C, 0x00000000, 0, 0},
-+      {0x00000450, 0x00000000, 0, 0},
-+      {0x00000454, 0x00000000, 0, 0},
-+      {0x00000458, 0x00000000, 0, 0},
-+      {0x0000045C, 0x00000000, 0, 0},
-+      {0x00000460, 0x00000000, 0, 0},
-+      {0x00000464, 0x00000000, 0, 0},
-+      {0x00000468, 0x00000000, 0, 0},
-+      {0x0000046C, 0x00000000, 0, 0},
-+      {0x00000470, 0x00000000, 0, 0},
-+      {0x00000474, 0x00000000, 0, 0},
-+      {0x00000478, 0x00000000, 0, 0},
-+      {0x0000047C, 0x00000000, 0, 0},
-+      {0x00000480, 0x00000000, 0, 0},
-+      {0x00000484, 0x00000000, 0, 0},
-+      {0x00000488, 0x00000000, 0, 0},
-+      {0x0000048C, 0x00000000, 0, 0},
-+      {0x00000490, 0x00000000, 0, 0},
-+      {0x00000494, 0x00000000, 0, 0},
-+      {0x00000498, 0x00000000, 0, 0},
-+      {0x0000049C, 0x00000000, 0, 0},
-+      {0x000004A0, 0x00000000, 0, 0},
-+      {0x000004A4, 0x00000000, 0, 0},
-+      {0x000004A8, 0x00000000, 0, 0},
-+      {0x000004AC, 0x00000000, 0, 0},
-+      {0x000004B0, 0x00000000, 0, 0},
-+      {0x000004B4, 0x00000000, 0, 0},
-+      {0x000004B8, 0x00000000, 0, 0},
-+      {0x000004BC, 0x00000000, 0, 0},
-+      {0x000004C0, 0x00000000, 0, 0},
-+      {0x000004C4, 0x00000000, 0, 0},
-+      {0x000004C8, 0x00000000, 0, 0},
-+      {0x000004CC, 0x00000000, 0, 0},
-+      /* config OECF(0100H~027CH) */
-+      {0x00000100, 0x00100000, 0, 0},
-+      {0x00000104, 0x00400020, 0, 0},
-+      {0x00000108, 0x00800060, 0, 0},
-+      {0x0000010C, 0x00C000A0, 0, 0},
-+      {0x00000110, 0x010000E0, 0, 0},
-+      {0x00000114, 0x02000180, 0, 0},
-+      {0x00000118, 0x03000280, 0, 0},
-+      {0x0000011C, 0x03FE0380, 0, 0},
-+      {0x00000120, 0x00100000, 0, 0},
-+      {0x00000124, 0x00400020, 0, 0},
-+      {0x00000128, 0x00800060, 0, 0},
-+      {0x0000012C, 0x00C000A0, 0, 0},
-+      {0x00000130, 0x010000E0, 0, 0},
-+      {0x00000134, 0x02000180, 0, 0},
-+      {0x00000138, 0x03000280, 0, 0},
-+      {0x0000013C, 0x03FE0380, 0, 0},
-+      {0x00000140, 0x00100000, 0, 0},
-+      {0x00000144, 0x00400020, 0, 0},
-+      {0x00000148, 0x00800060, 0, 0},
-+      {0x0000014C, 0x00C000A0, 0, 0},
-+      {0x00000150, 0x010000E0, 0, 0},
-+      {0x00000154, 0x02000180, 0, 0},
-+      {0x00000158, 0x03000280, 0, 0},
-+      {0x0000015C, 0x03FE0380, 0, 0},
-+      {0x00000160, 0x00100000, 0, 0},
-+      {0x00000164, 0x00400020, 0, 0},
-+      {0x00000168, 0x00800060, 0, 0},
-+      {0x0000016C, 0x00C000A0, 0, 0},
-+      {0x00000170, 0x010000E0, 0, 0},
-+      {0x00000174, 0x02000180, 0, 0},
-+      {0x00000178, 0x03000280, 0, 0},
-+      {0x0000017C, 0x03FE0380, 0, 0},
-+      {0x00000180, 0x00100000, 0, 0},
-+      {0x00000184, 0x00400020, 0, 0},
-+      {0x00000188, 0x00800060, 0, 0},
-+      {0x0000018C, 0x00C000A0, 0, 0},
-+      {0x00000190, 0x010000E0, 0, 0},
-+      {0x00000194, 0x02000180, 0, 0},
-+      {0x00000198, 0x03000280, 0, 0},
-+      {0x0000019C, 0x03FE0380, 0, 0},
-+      {0x000001A0, 0x00100000, 0, 0},
-+      {0x000001A4, 0x00400020, 0, 0},
-+      {0x000001A8, 0x00800060, 0, 0},
-+      {0x000001AC, 0x00C000A0, 0, 0},
-+      {0x000001B0, 0x010000E0, 0, 0},
-+      {0x000001B4, 0x02000180, 0, 0},
-+      {0x000001B8, 0x03000280, 0, 0},
-+      {0x000001BC, 0x03FE0380, 0, 0},
-+      {0x000001C0, 0x00100000, 0, 0},
-+      {0x000001C4, 0x00400020, 0, 0},
-+      {0x000001C8, 0x00800060, 0, 0},
-+      {0x000001CC, 0x00C000A0, 0, 0},
-+      {0x000001D0, 0x010000E0, 0, 0},
-+      {0x000001D4, 0x02000180, 0, 0},
-+      {0x000001D8, 0x03000280, 0, 0},
-+      {0x000001DC, 0x03FE0380, 0, 0},
-+      {0x000001E0, 0x00100000, 0, 0},
-+      {0x000001E4, 0x00400020, 0, 0},
-+      {0x000001E8, 0x00800060, 0, 0},
-+      {0x000001EC, 0x00C000A0, 0, 0},
-+      {0x000001F0, 0x010000E0, 0, 0},
-+      {0x000001F4, 0x02000180, 0, 0},
-+      {0x000001F8, 0x03000280, 0, 0},
-+      {0x000001FC, 0x03FE0380, 0, 0},
-+      {0x00000200, 0x00800080, 0, 0},
-+      {0x00000204, 0x00800080, 0, 0},
-+      {0x00000208, 0x00800080, 0, 0},
-+      {0x0000020C, 0x00800080, 0, 0},
-+      {0x00000210, 0x00800080, 0, 0},
-+      {0x00000214, 0x00800080, 0, 0},
-+      {0x00000218, 0x00800080, 0, 0},
-+      {0x0000021C, 0x00800080, 0, 0},
-+      {0x00000220, 0x00800080, 0, 0},
-+      {0x00000224, 0x00800080, 0, 0},
-+      {0x00000228, 0x00800080, 0, 0},
-+      {0x0000022C, 0x00800080, 0, 0},
-+      {0x00000230, 0x00800080, 0, 0},
-+      {0x00000234, 0x00800080, 0, 0},
-+      {0x00000238, 0x00800080, 0, 0},
-+      {0x0000023C, 0x00800080, 0, 0},
-+      {0x00000240, 0x00800080, 0, 0},
-+      {0x00000244, 0x00800080, 0, 0},
-+      {0x00000248, 0x00800080, 0, 0},
-+      {0x0000024C, 0x00800080, 0, 0},
-+      {0x00000250, 0x00800080, 0, 0},
-+      {0x00000254, 0x00800080, 0, 0},
-+      {0x00000258, 0x00800080, 0, 0},
-+      {0x0000025C, 0x00800080, 0, 0},
-+      {0x00000260, 0x00800080, 0, 0},
-+      {0x00000264, 0x00800080, 0, 0},
-+      {0x00000268, 0x00800080, 0, 0},
-+      {0x0000026C, 0x00800080, 0, 0},
-+      {0x00000270, 0x00800080, 0, 0},
-+      {0x00000274, 0x00800080, 0, 0},
-+      {0x00000278, 0x00800080, 0, 0},
-+      {0x0000027C, 0x00800080, 0, 0},
-+      /* config OECFHM(03D0H~03E4H) */
-+      {0x000003D0, 0x04000000, 0, 0},
-+      {0x000003D4, 0x0C000800, 0, 0},
-+      {0x000003D8, 0x00000FFF, 0, 0},
-+      {0x000003DC, 0x08000800, 0, 0},
-+      {0x000003E0, 0x08000800, 0, 0},
-+      {0x000003E4, 0x00000800, 0, 0},
-+      /* config LCCF(0050H, 0058H, 00E0H~00ECH) */
-+      {0x00000050, 0x021C03C0, 0, 0},
-+      {0x00000058, 0x0000000B, 0, 0},
-+      {0x000000E0, 0x00000000, 0, 0},
-+      {0x000000E4, 0x00000000, 0, 0},
-+      {0x000000E8, 0x00000000, 0, 0},
-+      {0x000000EC, 0x00000000, 0, 0},
-+      /* config AWB(0280H~02DCH) */
-+      {0x00000280, 0x00000000, 0, 0},
-+      {0x00000284, 0x00000000, 0, 0},
-+      {0x00000288, 0x00000000, 0, 0},
-+      {0x0000028C, 0x00000000, 0, 0},
-+      {0x00000290, 0x00000000, 0, 0},
-+      {0x00000294, 0x00000000, 0, 0},
-+      {0x00000298, 0x00000000, 0, 0},
-+      {0x0000029C, 0x00000000, 0, 0},
-+      {0x000002A0, 0x00000000, 0, 0},
-+      {0x000002A4, 0x00000000, 0, 0},
-+      {0x000002A8, 0x00000000, 0, 0},
-+      {0x000002AC, 0x00000000, 0, 0},
-+      {0x000002B0, 0x00000000, 0, 0},
-+      {0x000002B4, 0x00000000, 0, 0},
-+      {0x000002B8, 0x00000000, 0, 0},
-+      {0x000002BC, 0x00000000, 0, 0},
-+      {0x000002C0, 0x00800080, 0, 0},
-+      {0x000002C4, 0x00800080, 0, 0},
-+      {0x000002C8, 0x00800080, 0, 0},
-+      {0x000002CC, 0x00800080, 0, 0},
-+      {0x000002D0, 0x00800080, 0, 0},
-+      {0x000002D4, 0x00800080, 0, 0},
-+      {0x000002D8, 0x00800080, 0, 0},
-+      {0x000002DC, 0x00800080, 0, 0},
-+      /* config CTC(0A10H) and DBC(0A14H) filter */
-+      {0x00000A10, 0x41400040, 0, 0},
-+      {0x00000A14, 0x02000200, 0, 0},
-+      /* config CFA(0018H, 0A1CH) */
-+      {0x00000018, 0x000011BB, 0, 0},
-+      {0x00000A1C, 0x00000032, 0, 0},
-+      /* config CCM(0C40H~0CA4H) */
-+      {0x00000C40, 0x00060000, 0, 0},
-+      {0x00000C44, 0x00000000, 0, 0},
-+      {0x00000C48, 0x00000000, 0, 0},
-+      {0x00000C4C, 0x00000000, 0, 0},
-+      {0x00000C50, 0x00000000, 0, 0},
-+      {0x00000C54, 0x00000000, 0, 0},
-+      {0x00000C58, 0x00000000, 0, 0},
-+      {0x00000C5C, 0x00000000, 0, 0},
-+      {0x00000C60, 0x00000000, 0, 0},
-+      {0x00000C64, 0x00000000, 0, 0},
-+      {0x00000C68, 0x00000000, 0, 0},
-+      {0x00000C6C, 0x00000000, 0, 0},
-+      {0x00000C70, 0x00000080, 0, 0},
-+      {0x00000C74, 0x00000000, 0, 0},
-+      {0x00000C78, 0x00000000, 0, 0},
-+      {0x00000C7C, 0x00000000, 0, 0},
-+      {0x00000C80, 0x00000080, 0, 0},
-+      {0x00000C84, 0x00000000, 0, 0},
-+      {0x00000C88, 0x00000000, 0, 0},
-+      {0x00000C8C, 0x00000000, 0, 0},
-+      {0x00000C90, 0x00000080, 0, 0},
-+      {0x00000C94, 0x00000000, 0, 0},
-+      {0x00000C98, 0x00000000, 0, 0},
-+      {0x00000C9C, 0x00000000, 0, 0},
-+      {0x00000CA0, 0x00000700, 0, 0},
-+      {0x00000CA4, 0x00000200, 0, 0},
-+      /* config GMARGB(0E00H~0E38H) */
-+      {0x00000E00, 0x24000000, 0, 0},
-+      {0x00000E04, 0x08000020, 0, 0},
-+      {0x00000E08, 0x08000040, 0, 0},
-+      {0x00000E0C, 0x08000060, 0, 0},
-+      {0x00000E10, 0x08000080, 0, 0},
-+      {0x00000E14, 0x080000A0, 0, 0},
-+      {0x00000E18, 0x080000C0, 0, 0},
-+      {0x00000E1C, 0x080000E0, 0, 0},
-+      {0x00000E20, 0x08000100, 0, 0},
-+      {0x00000E24, 0x08000180, 0, 0},
-+      {0x00000E28, 0x08000200, 0, 0},
-+      {0x00000E2C, 0x08000280, 0, 0},
-+      {0x00000E30, 0x08000300, 0, 0},
-+      {0x00000E34, 0x08000380, 0, 0},
-+      {0x00000E38, 0x080003FE, 0, 0},
-+      /* config R2Y(0E40H~0E60H) */
-+      {0x00000E40, 0x0000004C, 0, 0},
-+      {0x00000E44, 0x00000097, 0, 0},
-+      {0x00000E48, 0x0000001D, 0, 0},
-+      {0x00000E4C, 0x000001D5, 0, 0},
-+      {0x00000E50, 0x000001AC, 0, 0},
-+      {0x00000E54, 0x00000080, 0, 0},
-+      {0x00000E58, 0x00000080, 0, 0},
-+      {0x00000E5C, 0x00000194, 0, 0},
-+      {0x00000E60, 0x000001EC, 0, 0},
-+      /* config YCRV(0F00H~0FFCH) */
-+      {0x00000F00, 0x00000000, 0, 0},
-+      {0x00000F04, 0x00000010, 0, 0},
-+      {0x00000F08, 0x00000020, 0, 0},
-+      {0x00000F0C, 0x00000030, 0, 0},
-+      {0x00000F10, 0x00000040, 0, 0},
-+      {0x00000F14, 0x00000050, 0, 0},
-+      {0x00000F18, 0x00000060, 0, 0},
-+      {0x00000F1C, 0x00000070, 0, 0},
-+      {0x00000F20, 0x00000080, 0, 0},
-+      {0x00000F24, 0x00000090, 0, 0},
-+      {0x00000F28, 0x000000A0, 0, 0},
-+      {0x00000F2C, 0x000000B0, 0, 0},
-+      {0x00000F30, 0x000000C0, 0, 0},
-+      {0x00000F34, 0x000000D0, 0, 0},
-+      {0x00000F38, 0x000000E0, 0, 0},
-+      {0x00000F3C, 0x000000F0, 0, 0},
-+      {0x00000F40, 0x00000100, 0, 0},
-+      {0x00000F44, 0x00000110, 0, 0},
-+      {0x00000F48, 0x00000120, 0, 0},
-+      {0x00000F4C, 0x00000130, 0, 0},
-+      {0x00000F50, 0x00000140, 0, 0},
-+      {0x00000F54, 0x00000150, 0, 0},
-+      {0x00000F58, 0x00000160, 0, 0},
-+      {0x00000F5C, 0x00000170, 0, 0},
-+      {0x00000F60, 0x00000180, 0, 0},
-+      {0x00000F64, 0x00000190, 0, 0},
-+      {0x00000F68, 0x000001A0, 0, 0},
-+      {0x00000F6C, 0x000001B0, 0, 0},
-+      {0x00000F70, 0x000001C0, 0, 0},
-+      {0x00000F74, 0x000001D0, 0, 0},
-+      {0x00000F78, 0x000001E0, 0, 0},
-+      {0x00000F7C, 0x000001F0, 0, 0},
-+      {0x00000F80, 0x00000200, 0, 0},
-+      {0x00000F84, 0x00000210, 0, 0},
-+      {0x00000F88, 0x00000220, 0, 0},
-+      {0x00000F8C, 0x00000230, 0, 0},
-+      {0x00000F90, 0x00000240, 0, 0},
-+      {0x00000F94, 0x00000250, 0, 0},
-+      {0x00000F98, 0x00000260, 0, 0},
-+      {0x00000F9C, 0x00000270, 0, 0},
-+      {0x00000FA0, 0x00000280, 0, 0},
-+      {0x00000FA4, 0x00000290, 0, 0},
-+      {0x00000FA8, 0x000002A0, 0, 0},
-+      {0x00000FAC, 0x000002B0, 0, 0},
-+      {0x00000FB0, 0x000002C0, 0, 0},
-+      {0x00000FB4, 0x000002D0, 0, 0},
-+      {0x00000FB8, 0x000002E0, 0, 0},
-+      {0x00000FBC, 0x000002F0, 0, 0},
-+      {0x00000FC0, 0x00000300, 0, 0},
-+      {0x00000FC4, 0x00000310, 0, 0},
-+      {0x00000FC8, 0x00000320, 0, 0},
-+      {0x00000FCC, 0x00000330, 0, 0},
-+      {0x00000FD0, 0x00000340, 0, 0},
-+      {0x00000FD4, 0x00000350, 0, 0},
-+      {0x00000FD8, 0x00000360, 0, 0},
-+      {0x00000FDC, 0x00000370, 0, 0},
-+      {0x00000FE0, 0x00000380, 0, 0},
-+      {0x00000FE4, 0x00000390, 0, 0},
-+      {0x00000FE8, 0x000003A0, 0, 0},
-+      {0x00000FEC, 0x000003B0, 0, 0},
-+      {0x00000FF0, 0x000003C0, 0, 0},
-+      {0x00000FF4, 0x000003D0, 0, 0},
-+      {0x00000FF8, 0x000003E0, 0, 0},
-+      {0x00000FFC, 0x000003F0, 0, 0},
-+      /* config Shrp(0E80H~0EE8H) */
-+      {0x00000E80, 0x00070F00, 0, 0},
-+      {0x00000E84, 0x00180F00, 0, 0},
-+      {0x00000E88, 0x00800F00, 0, 0},
-+      {0x00000E8C, 0x01000F00, 0, 0},
-+      {0x00000E90, 0x00100F00, 0, 0},
-+      {0x00000E94, 0x00600F00, 0, 0},
-+      {0x00000E98, 0x01000F00, 0, 0},
-+      {0x00000E9C, 0x01900F00, 0, 0},
-+      {0x00000EA0, 0x00000F00, 0, 0},
-+      {0x00000EA4, 0x00000F00, 0, 0},
-+      {0x00000EA8, 0x00000F00, 0, 0},
-+      {0x00000EAC, 0x00000F00, 0, 0},
-+      {0x00000EB0, 0x00000F00, 0, 0},
-+      {0x00000EB4, 0x00000F00, 0, 0},
-+      {0x00000EB8, 0x00000F00, 0, 0},
-+      {0x00000EBC, 0x10000000, 0, 0},
-+      {0x00000EC0, 0x10000000, 0, 0},
-+      {0x00000EC4, 0x10000000, 0, 0},
-+      {0x00000EC8, 0x10000000, 0, 0},
-+      {0x00000ECC, 0x10000000, 0, 0},
-+      {0x00000ED0, 0x10000000, 0, 0},
-+      {0x00000ED4, 0x88000D7C, 0, 0},
-+      {0x00000ED8, 0x00C00040, 0, 0},
-+      {0x00000EDC, 0xFF000000, 0, 0},
-+      {0x00000EE0, 0x00A00040, 0, 0},
-+      {0x00000EE4, 0x00000000, 0, 0},
-+      {0x00000EE8, 0x00000000, 0, 0},
-+      /* config DNYUV(0C00H~0C24H) */
-+      {0x00000C00, 0x00777777, 0, 0},
-+      {0x00000C04, 0x00007777, 0, 0},
-+      {0x00000C08, 0x00777777, 0, 0},
-+      {0x00000C0C, 0x00007777, 0, 0},
-+      {0x00000C10, 0x00600040, 0, 0},
-+      {0x00000C14, 0x00D80090, 0, 0},
-+      {0x00000C18, 0x01E60144, 0, 0},
-+      {0x00000C1C, 0x00600040, 0, 0},
-+      {0x00000C20, 0x00D80090, 0, 0},
-+      {0x00000C24, 0x01E60144, 0, 0},
-+      /* config SAT(0A30H~0A40H, 0A54H~0A58H) */
-+      {0x00000A30, 0x00000100, 0, 0},
-+      {0x00000A34, 0x001F0001, 0, 0},
-+      {0x00000A38, 0x00000000, 0, 0},
-+      {0x00000A3C, 0x00000100, 0, 0},
-+      {0x00000A40, 0x00000008, 0, 0},
-+      {0x00000A54, 0x04010001, 0, 0},
-+      {0x00000A58, 0x03FF0001, 0, 0},
-+      /* config OBA(0090H~0094H) */
-+      {0x00000090, 0x04380000, 0, 0},
-+      {0x00000094, 0x04390780, 0, 0},
-+      /* config SC(0098H~009CH, 00B8H~00BCH,
-+       * 00C0H, 0C4H~0D4H, 04D0H~054CH, 5D0H~5D4H)
-+       */
-+      {0x0000009C, 0x01000000, 0, 0},
-+      {0x000000B8, 0x000C0000, 0, 0},
-+      {0x000000BC, 0xC010151D, 0, 0},
-+      {0x000000C0, 0x01F1BF08, 0, 0},
-+      {0x000000C4, 0xFF00FF00, 0, 0},
-+      {0x000000C8, 0xFF00FF00, 0, 0},
-+      {0x000000CC, 0xFFFF0000, 0, 0},
-+      {0x000000D0, 0xFFFF0000, 0, 0},
-+      {0x000000D4, 0xFFFF0000, 0, 0},
-+      {0x000000D8, 0x01050107, 0, 0},
-+      {0x000004D0, 0x00000000, 0, 0},
-+      {0x000004D4, 0x00000000, 0, 0},
-+      {0x000004D8, 0x00000000, 0, 0},
-+      {0x000004DC, 0x00000000, 0, 0},
-+      {0x000004E0, 0x00000000, 0, 0},
-+      {0x000004E4, 0x00000000, 0, 0},
-+      {0x000004E8, 0x00000000, 0, 0},
-+      {0x000004EC, 0x00000000, 0, 0},
-+      {0x000004F0, 0x00100000, 0, 0},
-+      {0x000004F4, 0x00000000, 0, 0},
-+      {0x000004F8, 0x03D20000, 0, 0},
-+      {0x000004FC, 0x00000000, 0, 0},
-+      {0x00000500, 0x00950000, 0, 0},
-+      {0x00000504, 0x00000000, 0, 0},
-+      {0x00000508, 0x00253000, 0, 0},
-+      {0x0000050C, 0x00000000, 0, 0},
-+      {0x00000510, 0x00000000, 0, 0},
-+      {0x00000514, 0x00000000, 0, 0},
-+      {0x00000518, 0x00000000, 0, 0},
-+      {0x0000051C, 0x00000000, 0, 0},
-+      {0x00000520, 0x00000000, 0, 0},
-+      {0x00000524, 0x00000000, 0, 0},
-+      {0x00000528, 0x00000000, 0, 0},
-+      {0x0000052C, 0x00000000, 0, 0},
-+      {0x00000530, 0x00000000, 0, 0},
-+      {0x00000534, 0x00000000, 0, 0},
-+      {0x00000538, 0xFFFFFFF0, 0, 0},
-+      {0x0000053C, 0x8FFFFFFF, 0, 0},
-+      {0x00000540, 0x0000001E, 0, 0},
-+      {0x00000544, 0x00000000, 0, 0},
-+      {0x00000548, 0x00000000, 0, 0},
-+      {0x0000054C, 0xF0F20000, 0, 0},
-+      {0x000005D0, 0xFF00FF00, 0, 0},
-+      {0x000005D4, 0xFF00FF00, 0, 0},
-+      /* config YHIST(0CC8H~0CD8H) */
-+      {0x00000CC8, 0x00000000, 0, 0},
-+      {0x00000CCC, 0x0437077F, 0, 0},
-+      {0x00000CD0, 0x00010002, 0, 0},
-+      {0x00000CD4, 0x00000000, 0, 0},
-+      /* config CBAR(0600H-0653H) */
-+      {0x00000600, 0x043E0782, 0, 0},
-+      {0x00000604, 0x00000000, 0, 0},
-+      {0x00000608, 0x0437077F, 0, 0},
-+      {0x0000060C, 0x00443150, 0, 0},
-+      {0x00000610, 0x00000000, 0, 0},
-+      {0x00000614, 0x08880888, 0, 0},
-+      {0x00000618, 0x02220222, 0, 0},
-+      {0x0000061C, 0x04440444, 0, 0},
-+      {0x00000620, 0x08880888, 0, 0},
-+      {0x00000624, 0x0AAA0AAA, 0, 0},
-+      {0x00000628, 0x0CCC0CCC, 0, 0},
-+      {0x0000062C, 0x0EEE0EEE, 0, 0},
-+      {0x00000630, 0x0FFF0FFF, 0, 0},
-+      {0x00000634, 0x08880888, 0, 0},
-+      {0x00000638, 0x02220222, 0, 0},
-+      {0x0000063C, 0x04440444, 0, 0},
-+      {0x00000640, 0x08880888, 0, 0},
-+      {0x00000644, 0x0AAA0AAA, 0, 0},
-+      {0x00000648, 0x0CCC0CCC, 0, 0},
-+      {0x0000064C, 0x0EEE0EEE, 0, 0},
-+      {0x00000650, 0x0FFF0FFF, 0, 0},
-+      /* config sensor(0014H) */
-+      {0x00000014, 0x0000000c, 0, 0},
-+      /* config CROP(001CH, 0020H) */
-+      {0x0000001C, 0x00000000, 0, 0},
-+      {0x00000020, 0x0437077F, 0, 0},
-+      /* config isp pileline X/Y size(A0CH) */
-+      {0x00000A0C, 0x04380780, 0, 0},
-+      /* config CSI dump (24H/28H) */
-+      {0x00000028, 0x00030B80, 0, 0},
-+      /* Video Output */
-+      /* config UO(0A80H~0A90H) */
-+      {0x00000A88, 0x00000780, 0, 0},
-+      /* NV12 */
-+      {0x00000A8C, 0x00000000, 0, 0},
-+      /* NV21
-+       *{0x00000A8C, 0x00000020, 0, 0},
-+       */
-+      {0x00000A90, 0x00000000, 0, 0},
-+      {0x00000A9C, 0x00000780, 0, 0},
-+      {0x00000AA0, 0x00000002, 0, 0},
-+      {0x00000AA4, 0x00000002, 0, 0},
-+      {0x00000AA8, 0x07800438, 0, 0},
-+      {0x00000AB4, 0x00000780, 0, 0},
-+      {0x00000AB8, 0x00000002, 0, 0},
-+      {0x00000ABC, 0x00000002, 0, 0},
-+      {0x00000AC0, 0x07800438, 0, 0},
-+      {0x00000AC4, 0x00000000, 0, 0},
-+      /* config TIL(0B20H~0B48H) */
-+      {0x00000B20, 0x04380780, 0, 0},
-+      {0x00000B24, 0x00000960, 0, 0},
-+      {0x00000B38, 0x00030003, 0, 0},
-+      {0x00000B3C, 0x00000960, 0, 0},
-+      {0x00000B44, 0x00000000, 0, 0},
-+      {0x00000B48, 0x00000000, 0, 0},
-+      /* Enable DEC/OBC/OECF/LCCF/AWB/SC/DUMP */
-+      {0x00000010, 0x000A00D6, 0x00000000, 0x00},
-+      /* Enable CFA/CAR/CCM/GMARGB/R2Y/SHRP/SAT/DNYUV/YCRV/YHIST/CTC/DBC */
-+      {0x00000A08, 0x107A01BE, 0x00000000, 0x00},
-+};
-+
-+const struct reg_table isp_reg_init_settings[] = {
-+      {isp_reg_init_config_list,
-+      ARRAY_SIZE(isp_reg_init_config_list)},
-+};
-+
-+static struct regval_t isp_reg_start_config_list[] = {
-+#if defined(ENABLE_SS0_SS1)
-+      /* ENABLE UO/SS0/SS1/Multi-Frame and Reset ISP */
-+      {0x00000A00, 0x00121802, 0x00000000, 0x0A},
-+      /* ENABLE UO/SS0/SS1/Multi-Frame and Leave ISP reset */
-+      {0x00000A00, 0x00121800, 0x00000000, 0x0A},
-+#else
-+      /* ENABLE UO/Multi-Frame and Reset ISP */
-+      {0x00000A00, 0x00120002, 0x00000000, 0x0A},
-+      /* ENABLE UO/Multi-Frame and Leave ISP reset */
-+      {0x00000A00, 0x00120000, 0x00000000, 0x0A},
-+#endif
-+      /* Config ISP shadow mode as next-vsync */
-+      {0x00000A50, 0x00000002, 0x00000000, 0x00},
-+#if defined(ENABLE_SS0_SS1)
-+      /* ENABLE UO/SS0/SS1/Multi-Frame and Enable ISP */
-+      {0x00000A00, 0x00121801, 0x00000000, 0x0A},
-+#else
-+      /* ENABLE UO/Multi-Frame and Enable ISP */
-+      {0x00000A00, 0x00120001, 0x00000000, 0x0A},
-+#endif
-+      /* Config CSI shadow mode as immediate to fetch current setting */
-+      {0x00000008, 0x00010004, 0x00000000, 0x0A},
-+      /* Config CSI shadow mode as next-vsync */
-+      {0x00000008, 0x00020004, 0x00000000, 0x00},
-+      /* Enable CSI */
-+      {0x00000000, 0x00000001, 0x00000000, 0x0A},
-+};
-+
-+const struct reg_table isp_reg_start_settings[] = {
-+      {isp_reg_start_config_list,
-+      ARRAY_SIZE(isp_reg_start_config_list)},
-+};
-+
-+static struct regval_t isp_imx_219_reg_config_list[] = {
-+      /* MIPI sensor */
-+      {0x00000014, 0x0000000D, 0, 0},
-+      /* config CFA(0018H, 0A1CH) */
-+      {0x00000A1C, 0x00000032, 0, 0},
-+      {0x00000A8C, 0x00000000, 0, 0},
-+      {0x00000A90, 0x00000000, 0, 0},
-+      /* config R2Y(0E40H~0E60H) */
-+      {0x00000E40, 0x0000004C, 0, 0},
-+      {0x00000E44, 0x00000097, 0, 0},
-+      {0x00000E48, 0x0000001D, 0, 0},
-+      {0x00000E4C, 0x000001D5, 0, 0},
-+      {0x00000E50, 0x000001AC, 0, 0},
-+      {0x00000E54, 0x00000080, 0, 0},
-+      {0x00000E58, 0x00000080, 0, 0},
-+      {0x00000E5C, 0x00000194, 0, 0},
-+      {0x00000E60, 0x000001EC, 0, 0},
-+      /* Config AWB(0280H~02DCH). Fixed WB gain for IMX-219 sensor. */
-+      {0x00000280, 0x00000000, 0, 0},
-+      {0x00000284, 0x00000000, 0, 0},
-+      {0x00000288, 0x00000000, 0, 0},
-+      {0x0000028C, 0x00000000, 0, 0},
-+      {0x00000290, 0x00000000, 0, 0},
-+      {0x00000294, 0x00000000, 0, 0},
-+      {0x00000298, 0x00000000, 0, 0},
-+      {0x0000029C, 0x00000000, 0, 0},
-+      {0x000002A0, 0x00000000, 0, 0},
-+      {0x000002A4, 0x00000000, 0, 0},
-+      {0x000002A8, 0x00000000, 0, 0},
-+      {0x000002AC, 0x00000000, 0, 0},
-+      {0x000002B0, 0x00000000, 0, 0},
-+      {0x000002B4, 0x00000000, 0, 0},
-+      {0x000002B8, 0x00000000, 0, 0},
-+      {0x000002BC, 0x00000000, 0, 0},
-+      {0x000002C0, 0x00F000F0, 0, 0},
-+      {0x000002C4, 0x00F000F0, 0, 0},
-+      {0x000002C8, 0x00800080, 0, 0},
-+      {0x000002CC, 0x00800080, 0, 0},
-+      {0x000002D0, 0x00800080, 0, 0},
-+      {0x000002D4, 0x00800080, 0, 0},
-+      {0x000002D8, 0x00B000B0, 0, 0},
-+      {0x000002DC, 0x00B000B0, 0, 0},
-+      /* config GMARGB(0E00H~0E38H)
-+       * Gamma RGB 1.9 for IMX-219 sensor
-+       */
-+      {0x00000E00, 0x24000000, 0, 0},
-+      {0x00000E04, 0x159500A5, 0, 0},
-+      {0x00000E08, 0x0F9900EE, 0, 0},
-+      {0x00000E0C, 0x0CE40127, 0, 0},
-+      {0x00000E10, 0x0B410157, 0, 0},
-+      {0x00000E14, 0x0A210181, 0, 0},
-+      {0x00000E18, 0x094B01A8, 0, 0},
-+      {0x00000E1C, 0x08A401CC, 0, 0},
-+      {0x00000E20, 0x081D01EE, 0, 0},
-+      {0x00000E24, 0x06B20263, 0, 0},
-+      {0x00000E28, 0x05D802C7, 0, 0},
-+      {0x00000E2C, 0x05420320, 0, 0},
-+      {0x00000E30, 0x04D30370, 0, 0},
-+      {0x00000E34, 0x047C03BB, 0, 0},
-+      {0x00000E38, 0x043703FF, 0, 0},
-+      {0x00000010, 0x00000080, 0, 0},
-+      /* Enable CFA/GMARGB/R2Y */
-+      {0x00000A08, 0x10000032, 0x0FFFFFFF, 0x00},
-+      {0x00000A00, 0x00120002, 0, 0},
-+      {0x00000A00, 0x00120000, 0, 0},
-+      {0x00000A50, 0x00000002, 0, 0},
-+      {0x00000008, 0x00010000, 0, 0},
-+      {0x00000008, 0x0002000A, 0, 0},
-+      {0x00000000, 0x00000001, 0, 0},
-+};
-+
-+const struct reg_table isp_imx_219_settings[] = {
-+      {isp_imx_219_reg_config_list,
-+      ARRAY_SIZE(isp_imx_219_reg_config_list)},
-+};
-+
-+static struct regval_t isp_format_reg_list[] = {
-+      {0x0000001C, 0x00000000, 0x00000000, 0},
-+      {0x00000020, 0x0437077F, 0x00000000, 0},
-+      {0x00000A0C, 0x04380780, 0x00000000, 0},
-+      {0x00000A88, 0x00000780, 0x00000000, 0},
-+      {0x00000018, 0x000011BB, 0x00000000, 0},
-+      {0x00000A08, 0x10000000, 0xF0000000, 0},
-+      {0x00000028, 0x00030B80, 0x0003FFFF, 0},
-+      {0x00000AA8, 0x07800438, 0x00000000, 0},
-+      {0x00000A9C, 0x00000780, 0x00000000, 0},
-+      {0x00000AC0, 0x07800438, 0x00000000, 0},
-+      {0x00000AB4, 0x00000780, 0x00000000, 0},
-+      {0x00000B20, 0x04380780, 0x00000000, 0},
-+      {0x00000B24, 0x00000960, 0x00000000, 0},
-+      {0x00000B3C, 0x00000960, 0x00000000, 0},
-+      {0x00000014, 0x00000008, 0x00000000, 0},
-+};
-+
-+const struct reg_table  isp_format_settings[] = {
-+      {isp_format_reg_list,
-+      ARRAY_SIZE(isp_format_reg_list)},
-+};
-+
-+#if defined(USE_NEW_CONFIG_SETTING)
-+#else
-+static struct reg_table  *isp_settings = (struct reg_table *)isp_imx_219_settings;
-+#endif
-+
-+static void isp_load_regs(void __iomem *ispbase, const struct reg_table *table)
-+{
-+      int j;
-+      u32 delay_ms, reg_addr, mask, val;
-+
-+      for (j = 0; j < table->regval_num; j++) {
-+              delay_ms = table->regval[j].delay_ms;
-+              reg_addr = table->regval[j].addr;
-+              val = table->regval[j].val;
-+              mask = table->regval[j].mask;
-+
-+              if (reg_addr % 4
-+                      || reg_addr > STF_ISP_REG_OFFSET_MAX
-+                      || delay_ms > STF_ISP_REG_DELAY_MAX)
-+                      continue;
-+
-+              if (mask)
-+                      reg_set_bit(ispbase, reg_addr, mask, val);
-+              else
-+                      reg_write(ispbase, reg_addr, val);
-+              if (delay_ms)
-+                      usleep_range(1000 * delay_ms, 1000 * delay_ms + 100);
-+      }
-+}
-+
-+static void isp_load_regs_exclude_csi_isp_enable(
-+                      void __iomem *ispbase,
-+                      const struct reg_table *table)
-+{
-+      int j;
-+      u32 delay_ms, reg_addr, mask, val;
-+
-+      for (j = 0; j < table->regval_num; j++) {
-+              delay_ms = table->regval[j].delay_ms;
-+              reg_addr = table->regval[j].addr;
-+              val = table->regval[j].val;
-+              mask = table->regval[j].mask;
-+
-+              if (reg_addr % 4
-+                      || reg_addr > STF_ISP_REG_OFFSET_MAX
-+                      || delay_ms > STF_ISP_REG_DELAY_MAX
-+                      || ((reg_addr == ISP_REG_CSI_INPUT_EN_AND_STATUS) && (val & 0x01))
-+                      || ((reg_addr == ISP_REG_ISP_CTRL_0) && (val & 0x01)))
-+                      continue;
-+
-+              if (mask)
-+                      reg_set_bit(ispbase, reg_addr, mask, val);
-+              else
-+                      reg_write(ispbase, reg_addr, val);
-+              if (delay_ms)
-+                      usleep_range(1000 * delay_ms, 1000 * delay_ms + 100);
-+      }
-+}
-+
-+static int stf_isp_clk_enable(struct stf_isp_dev *isp_dev)
-+{
-+      struct stfcamss *stfcamss = isp_dev->stfcamss;
-+
-+      clk_prepare_enable(stfcamss->sys_clk[STFCLK_WRAPPER_CLK_C].clk);
-+      reset_control_deassert(stfcamss->sys_rst[STFRST_WRAPPER_C].rstc);
-+      reset_control_deassert(stfcamss->sys_rst[STFRST_WRAPPER_P].rstc);
-+
-+      return 0;
-+}
-+
-+static int stf_isp_clk_disable(struct stf_isp_dev *isp_dev)
-+{
-+      struct stfcamss *stfcamss = isp_dev->stfcamss;
-+
-+      reset_control_assert(stfcamss->sys_rst[STFRST_WRAPPER_C].rstc);
-+      reset_control_assert(stfcamss->sys_rst[STFRST_WRAPPER_P].rstc);
-+      clk_disable_unprepare(stfcamss->sys_clk[STFCLK_WRAPPER_CLK_C].clk);
-+
-+      return 0;
-+}
-+
-+static  void __iomem *stf_isp_get_ispbase(struct stf_vin_dev *vin)
-+{
-+      void __iomem *base = vin->isp_base;
-+
-+      return base;
-+}
-+
-+static int stf_isp_save_ctx_regs(struct stf_isp_dev *isp_dev)
-+{
-+      int j;
-+      u32 addr, val;
-+      void __iomem *ispbase;
-+      struct device *dev = isp_dev->stfcamss->dev;
-+      struct stf_vin_dev *vin = isp_dev->stfcamss->vin;
-+
-+      ispbase = stf_isp_get_ispbase(vin);
-+
-+      if (!isp_dev->context_regs) {
-+              int regs_size =
-+                      sizeof(struct regval_t) * isp_reg_init_settings->regval_num;
-+              isp_dev->context_regs =
-+                      devm_kzalloc(dev, sizeof(struct reg_table), GFP_KERNEL);
-+              isp_dev->context_regs->regval =
-+                      devm_kzalloc(dev, regs_size, GFP_KERNEL);
-+              isp_dev->context_regs->regval_num = isp_reg_init_settings->regval_num;
-+      }
-+
-+      if (!isp_dev->context_regs || !isp_dev->context_regs->regval)
-+              return -ENOMEM;
-+
-+      st_debug(ST_ISP, "Saving ISP context registers\n");
-+      for (j = 0; j < isp_reg_init_settings->regval_num; j++) {
-+              addr = isp_reg_init_settings->regval[j].addr;
-+              val = ioread32(ispbase + addr);
-+              isp_dev->context_regs->regval[j].addr = addr;
-+              isp_dev->context_regs->regval[j].val = val;
-+      }
-+      st_debug(ST_ISP, "ISP context registers have been saved\n");
-+
-+      return 0;
-+};
-+
-+static int stf_isp_restore_ctx_regs(struct stf_isp_dev *isp_dev)
-+{
-+      struct stf_vin_dev *vin = isp_dev->stfcamss->vin;
-+      void __iomem *ispbase;
-+
-+      ispbase = stf_isp_get_ispbase(vin);
-+
-+      if (isp_dev->context_regs) {
-+              isp_load_regs(ispbase, isp_dev->context_regs);
-+              st_debug(ST_ISP, "Restored ISP register: isp_reg_init_settings.\n");
-+      }
-+
-+      return 0;
-+}
-+
-+static int stf_isp_reset(struct stf_isp_dev *isp_dev)
-+{
-+      struct stf_vin_dev *vin = isp_dev->stfcamss->vin;
-+      void __iomem *ispbase;
-+
-+      ispbase = stf_isp_get_ispbase(vin);
-+
-+      reg_set_bit(ispbase, ISP_REG_ISP_CTRL_0, BIT(1), BIT(1));
-+      reg_set_bit(ispbase, ISP_REG_ISP_CTRL_0, BIT(1), 0);
-+
-+      return 0;
-+}
-+
-+static int stf_isp_config_set(struct stf_isp_dev *isp_dev)
-+{
-+      struct stf_vin_dev *vin = isp_dev->stfcamss->vin;
-+      void __iomem *ispbase;
-+
-+      ispbase = stf_isp_get_ispbase(vin);
-+
-+      st_debug(ST_ISP, "%s\n", __func__);
-+
-+#if defined(USE_NEW_CONFIG_SETTING)
-+      mutex_lock(&isp_dev->setfile_lock);
-+
-+      if (isp_dev->context_regs) {
-+              stf_isp_restore_ctx_regs(isp_dev);
-+              st_debug(ST_ISP, "%s context regs restore done\n", __func__);
-+      } else {
-+              isp_load_regs(ispbase, isp_reg_init_settings);
-+              st_debug(ST_ISP, "%s isp_reg_init_settings done\n", __func__);
-+      }
-+      if (isp_dev->setfile.state) {
-+              st_info(ST_ISP, "%s, Program extra ISP setting!\n", __func__);
-+              isp_load_regs_exclude_csi_isp_enable(ispbase,
-+                      &isp_dev->setfile.settings);
-+      }
-+
-+      mutex_unlock(&isp_dev->setfile_lock);
-+#else
-+      mutex_lock(&isp_dev->setfile_lock);
-+      if (isp_dev->setfile.state)
-+              isp_load_regs(ispbase, &isp_dev->setfile.settings);
-+      else
-+              isp_load_regs(ispbase, isp_settings);
-+      mutex_unlock(&isp_dev->setfile_lock);
-+
-+      st_debug(ST_ISP, "config 0x%x = 0x%x\n",
-+                      isp_format_reg_list[0].addr,
-+                      isp_format_reg_list[0].val);
-+      st_debug(ST_ISP, "config 0x%x = 0x%x\n",
-+                      isp_format_reg_list[1].addr,
-+                      isp_format_reg_list[1].val);
-+      st_debug(ST_ISP, "config 0x%x = 0x%x\n",
-+                      isp_format_reg_list[2].addr,
-+                      isp_format_reg_list[2].val);
-+      st_debug(ST_ISP, "config 0x%x = 0x%x\n",
-+                      isp_format_reg_list[3].addr,
-+                      isp_format_reg_list[3].val);
-+#endif
-+
-+      return 0;
-+}
-+
-+static int stf_isp_set_format(struct stf_isp_dev *isp_dev,
-+              struct isp_stream_format *crop_array, u32 mcode,
-+              int type)
-+{
-+      struct stf_vin_dev *vin = isp_dev->stfcamss->vin;
-+      struct stf_dvp_dev *dvp_dev = isp_dev->stfcamss->dvp_dev;
-+      struct v4l2_rect *crop = &crop_array[ISP_COMPOSE].rect;
-+      u32 bpp = crop_array[ISP_COMPOSE].bpp;
-+      void __iomem *ispbase;
-+      u32 val, val1;
-+
-+      ispbase = stf_isp_get_ispbase(vin);
-+
-+      st_debug(ST_ISP, "interface type is %d(%s)\n",
-+                      type, type == CSI_SENSOR ? "CSI" : "DVP");
-+
-+      if (type == DVP_SENSOR) {
-+              unsigned int flags = dvp_dev->dvp->flags;
-+
-+              st_debug(ST_ISP, "dvp flags = 0x%x, hsync active is %s, vsync active is %s\n",
-+                      flags, flags & V4L2_MBUS_HSYNC_ACTIVE_HIGH ? "high" : "low",
-+                      flags & V4L2_MBUS_VSYNC_ACTIVE_HIGH ? "high" : "low");
-+      }
-+
-+      val = crop->left + (crop->top << 16);
-+      isp_format_reg_list[0].addr = ISP_REG_PIC_CAPTURE_START_CFG;
-+      isp_format_reg_list[0].val = val;
-+
-+      val = (crop->width + crop->left - 1)
-+              + ((crop->height + crop->top - 1) << 16);
-+      isp_format_reg_list[1].addr = ISP_REG_PIC_CAPTURE_END_CFG;
-+      isp_format_reg_list[1].val = val;
-+
-+      val = crop->width + (crop->height << 16);
-+      isp_format_reg_list[2].addr = ISP_REG_PIPELINE_XY_SIZE;
-+      isp_format_reg_list[2].val = val;
-+
-+      isp_format_reg_list[3].addr = ISP_REG_STRIDE;
-+      isp_format_reg_list[3].val = ALIGN(crop->width * bpp / 8, STFCAMSS_FRAME_WIDTH_ALIGN_8);
-+
-+      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 = 0x0000EE44;
-+              val1 = 0x00000000;
-+              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 = 0x0000BB11;
-+              val1 = 0x20000000;
-+              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 = 0x000044EE;
-+              val1 = 0x30000000;
-+              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 = 0x000011BB;
-+              val1 = 0x10000000;
-+              break;
-+      default:
-+              st_err(ST_ISP, "UNKNOW format\n");
-+              val = 0x000011BB;
-+              val1 = 0x10000000;
-+              break;
-+      }
-+
-+      isp_format_reg_list[4].addr = ISP_REG_RAW_FORMAT_CFG;
-+      isp_format_reg_list[4].val = val;
-+
-+      isp_format_reg_list[5].addr = ISP_REG_ISP_CTRL_1;
-+      isp_format_reg_list[5].val = val1;
-+      isp_format_reg_list[5].mask = 0xF0000000;
-+
-+      st_info(ST_ISP, "src left: %d, top: %d, width = %d, height = %d, bpp = %d\n",
-+              crop->left, crop->top, crop->width, crop->height, bpp);
-+
-+      crop = &crop_array[ISP_CROP].rect;
-+      bpp = crop_array[ISP_CROP].bpp;
-+      val = ALIGN(crop->width * bpp / 8, STFCAMSS_FRAME_WIDTH_ALIGN_128);
-+      isp_format_reg_list[6].addr = ISP_REG_DUMP_CFG_1;
-+      isp_format_reg_list[6].val = val | 3 << 16;
-+      isp_format_reg_list[6].mask = 0x0003FFFF;
-+
-+      st_info(ST_ISP, "raw left: %d, top: %d, width = %d, height = %d, bpp = %d\n",
-+              crop->left, crop->top, crop->width, crop->height, bpp);
-+
-+      crop = &crop_array[ISP_SCALE_SS0].rect;
-+      bpp = crop_array[ISP_SCALE_SS0].bpp;
-+      isp_format_reg_list[7].addr = ISP_REG_SS0IW;
-+      isp_format_reg_list[7].val = (crop->width << 16) + crop->height;
-+      isp_format_reg_list[8].addr = ISP_REG_SS0S;
-+      isp_format_reg_list[8].val = ALIGN(crop->width * bpp / 8, STFCAMSS_FRAME_WIDTH_ALIGN_8);
-+
-+      st_info(ST_ISP, "ss0 left: %d, top: %d, width = %d, height = %d, bpp = %d\n",
-+              crop->left, crop->top, crop->width, crop->height, bpp);
-+
-+      crop = &crop_array[ISP_SCALE_SS1].rect;
-+      bpp = crop_array[ISP_SCALE_SS1].bpp;
-+      isp_format_reg_list[9].addr = ISP_REG_SS1IW;
-+      isp_format_reg_list[9].val = (crop->width << 16) + crop->height;
-+      isp_format_reg_list[10].addr = ISP_REG_SS1S;
-+      isp_format_reg_list[10].val = ALIGN(crop->width * bpp / 8, STFCAMSS_FRAME_WIDTH_ALIGN_8);
-+
-+      crop = &crop_array[ISP_ITIWS].rect;
-+      bpp = crop_array[ISP_ITIWS].bpp;
-+      isp_format_reg_list[11].addr = ISP_REG_ITIIWSR;
-+      isp_format_reg_list[11].val = (crop->height << 16) + crop->width;
-+      isp_format_reg_list[12].addr = ISP_REG_ITIDWLSR;
-+      isp_format_reg_list[12].val = ALIGN(crop->width * bpp / 8, STFCAMSS_FRAME_WIDTH_ALIGN_8);
-+      isp_format_reg_list[13].addr = ISP_REG_ITIDRLSR;
-+      isp_format_reg_list[13].val = ALIGN(crop->width * bpp / 8, STFCAMSS_FRAME_WIDTH_ALIGN_8);
-+
-+      st_info(ST_ISP, "iti left: %d, top: %d, width = %d, height = %d, bpp = %d\n",
-+              crop->left, crop->top, crop->width, crop->height, bpp);
-+
-+      isp_format_reg_list[14].addr = ISP_REG_SENSOR;
-+      isp_format_reg_list[14].val = 0x00000000;
-+      if (type == DVP_SENSOR) {
-+              unsigned int flags = dvp_dev->dvp->flags;
-+
-+              if (flags & V4L2_MBUS_HSYNC_ACTIVE_HIGH)
-+                      isp_format_reg_list[14].val |= 0x08;
-+              if (flags & V4L2_MBUS_VSYNC_ACTIVE_HIGH)
-+                      isp_format_reg_list[14].val |= 0x04;
-+      } else {
-+              isp_format_reg_list[14].val |= 0x01;
-+      }
-+
-+      isp_load_regs(ispbase, isp_format_settings);
-+      return 0;
-+}
-+
-+static int stf_isp_stream_set(struct stf_isp_dev *isp_dev, int on)
-+{
-+      struct stf_vin_dev *vin = isp_dev->stfcamss->vin;
-+
-+      void __iomem *ispbase;
-+
-+      ispbase = stf_isp_get_ispbase(vin);
-+
-+      if (on) {
-+#if defined(USE_NEW_CONFIG_SETTING)
-+              isp_load_regs(ispbase, isp_reg_start_settings);
-+#else
-+              reg_set_bit(ispbase, ISP_REG_CSIINTS_ADDR, 0x3FFFF, 0x3000a);
-+              reg_set_bit(ispbase, ISP_REG_IESHD_ADDR, BIT(1) | BIT(0), 0x3);
-+              reg_set_bit(ispbase, ISP_REG_ISP_CTRL_0, BIT(0), 1);
-+#endif //#if defined(USE_NEW_CONFIG_SETTING)
-+      } else {
-+              /* NOTE: Clear bit 0 of ISP_REG_ISP_CTRL_0 here will get crash. */
-+              stf_isp_save_ctx_regs(isp_dev);
-+      }
-+
-+      return 0;
-+}
-+
-+static union reg_buf reg_buf;
-+static int stf_isp_reg_read(struct stf_isp_dev *isp_dev, void *arg)
-+{
-+      struct stf_vin_dev *vin = isp_dev->stfcamss->vin;
-+      void __iomem *ispbase;
-+      struct isp_reg_param *reg_param = arg;
-+      u32 size;
-+      unsigned long r;
-+
-+      if (reg_param->reg_buf == NULL) {
-+              st_err(ST_ISP, "Failed to access register. The pointer is NULL!!!\n");
-+              return -EINVAL;
-+      }
-+
-+      ispbase = stf_isp_get_ispbase(vin);
-+
-+      size = 0;
-+      switch (reg_param->reg_info.method) {
-+      case STF_ISP_REG_METHOD_ONE_REG:
-+              break;
-+
-+      case STF_ISP_REG_METHOD_SERIES:
-+              if (reg_param->reg_info.length > STF_ISP_REG_BUF_SIZE) {
-+                      st_err(ST_ISP, "Failed to access register. \
-+                              The (length=0x%08X > 0x%08X) is out of size!!!\n",
-+                              reg_param->reg_info.length, STF_ISP_REG_BUF_SIZE);
-+                      return -EINVAL;
-+              }
-+              break;
-+
-+      case STF_ISP_REG_METHOD_MODULE:
-+              /* This mode is not supported in the V4L2 version. */
-+              st_err(ST_ISP, "Reg Read - Failed to access register. The method = \
-+                      STF_ISP_REG_METHOD_MODULE is not supported!!!\n");
-+              return -ENOTTY;
-+
-+      case STF_ISP_REG_METHOD_TABLE:
-+              if (reg_param->reg_info.length > STF_ISP_REG_TBL_BUF_SIZE) {
-+                      st_err(ST_ISP, "Failed to access register. \
-+                              The (length=0x%08X > 0x%08X) is out of size!!!\n",
-+                              reg_param->reg_info.length, STF_ISP_REG_TBL_BUF_SIZE);
-+                      return -EINVAL;
-+              }
-+              size = sizeof(u32) * reg_param->reg_info.length * 2;
-+              break;
-+
-+      case STF_ISP_REG_METHOD_TABLE_2:
-+              if (reg_param->reg_info.length > STF_ISP_REG_TBL_2_BUF_SIZE) {
-+                      st_err(ST_ISP, "Failed to access register. \
-+                              The (length=0x%08X > 0x%08X) is out of size!!!\n",
-+                              reg_param->reg_info.length, STF_ISP_REG_TBL_2_BUF_SIZE);
-+                      return -EINVAL;
-+              }
-+              size = sizeof(u32) * reg_param->reg_info.length * 3;
-+              break;
-+
-+      case STF_ISP_REG_METHOD_TABLE_3:
-+              if (reg_param->reg_info.length > STF_ISP_REG_TBL_3_BUF_SIZE) {
-+                      st_err(ST_ISP, "Failed to access register. \
-+                              The (length=0x%08X > 0x%08X) is out of size!!!\n",
-+                              reg_param->reg_info.length, STF_ISP_REG_TBL_3_BUF_SIZE);
-+                      return -EINVAL;
-+              }
-+              size = sizeof(u32) * reg_param->reg_info.length * 4;
-+              break;
-+
-+      case STF_ISP_REG_METHOD_SMPL_PACK:
-+              st_err(ST_ISP, "Reg Read - Failed to access register. The method = \
-+                      STF_ISP_REG_METHOD_SMPL_PACK is not supported!!!\n");
-+              return -ENOTTY;
-+
-+      case STF_ISP_REG_METHOD_SOFT_RDMA:
-+              // This mode is not supported in the V4L2 version.
-+              st_err(ST_ISP, "Reg Read - Failed to access register. The method = \
-+                      STF_ISP_REG_METHOD_SOFT_RDMA is not supported!!!\n");
-+              return -ENOTTY;
-+
-+      default:
-+              st_err(ST_ISP, "Failed to access register. The method=%d \
-+                      is not supported!!!\n", reg_param->reg_info.method);
-+              return -ENOTTY;
-+      }
-+
-+      memset(&reg_buf, 0, sizeof(union reg_buf));
-+      if (size) {
-+              r = copy_from_user((u8 *)reg_buf.buffer,
-+                      (u8 *)reg_param->reg_buf->buffer, size);
-+              if (r) {
-+                      st_err(ST_ISP, "Failed to call copy_from_user for the \
-+                              reg_param->reg_buf value\n");
-+                      return -EIO;
-+              }
-+      }
-+
-+      size = 0;
-+      switch (reg_param->reg_info.method) {
-+      case STF_ISP_REG_METHOD_ONE_REG:
-+              reg_buf.buffer[0] = reg_read(ispbase, reg_param->reg_info.offset);
-+              size = sizeof(u32);
-+              break;
-+
-+      case STF_ISP_REG_METHOD_SERIES:
-+              for (r = 0; r < reg_param->reg_info.length; r++) {
-+                      reg_buf.buffer[r] = reg_read(ispbase,
-+                              reg_param->reg_info.offset + (r * 4));
-+              }
-+              size = sizeof(u32) * reg_param->reg_info.length;
-+              break;
-+
-+      case STF_ISP_REG_METHOD_MODULE:
-+              break;
-+
-+      case STF_ISP_REG_METHOD_TABLE:
-+              for (r = 0; r < reg_param->reg_info.length; r++) {
-+                      reg_buf.reg_tbl[r].value = reg_read(ispbase,
-+                              reg_buf.reg_tbl[r].offset);
-+              }
-+              size = sizeof(u32) * reg_param->reg_info.length * 2;
-+              break;
-+
-+      case STF_ISP_REG_METHOD_TABLE_2:
-+              for (r = 0; r < reg_param->reg_info.length; r++) {
-+                      if (reg_buf.reg_tbl2[r].mask) {
-+                              reg_buf.reg_tbl2[r].value = (reg_read(ispbase,
-+                                      reg_buf.reg_tbl2[r].offset)
-+                                              & reg_buf.reg_tbl2[r].mask);
-+                      } else {
-+                              reg_buf.reg_tbl2[r].value = reg_read(ispbase,
-+                                      reg_buf.reg_tbl2[r].offset);
-+                      }
-+              }
-+              size = sizeof(u32) * reg_param->reg_info.length * 3;
-+              break;
-+
-+      case STF_ISP_REG_METHOD_TABLE_3:
-+              for (r = 0; r < reg_param->reg_info.length; r++) {
-+                      if (reg_buf.reg_tbl3[r].mask) {
-+                              reg_buf.reg_tbl3[r].value = (reg_read(ispbase,
-+                                      reg_buf.reg_tbl3[r].offset)
-+                                              & reg_buf.reg_tbl3[r].mask);
-+                      } else {
-+                              reg_buf.reg_tbl3[r].value = reg_read(ispbase,
-+                                      reg_buf.reg_tbl3[r].offset);
-+                      }
-+                      if (reg_buf.reg_tbl3[r].delay_ms) {
-+                              usleep_range(1000 * reg_buf.reg_tbl3[r].delay_ms,
-+                                      1000 * reg_buf.reg_tbl3[r].delay_ms + 100);
-+                      }
-+              }
-+              size = sizeof(u32) * reg_param->reg_info.length * 4;
-+              break;
-+
-+      case STF_ISP_REG_METHOD_SMPL_PACK:
-+              break;
-+
-+      case STF_ISP_REG_METHOD_SOFT_RDMA:
-+              break;
-+
-+      default:
-+              break;
-+      }
-+
-+      r = copy_to_user((u8 *)reg_param->reg_buf->buffer, (u8 *)reg_buf.buffer,
-+              size);
-+      if (r) {
-+              st_err(ST_ISP, "Failed to call copy_to_user for the \
-+                      reg_param->buffer value\n");
-+              return -EIO;
-+      }
-+
-+      return 0;
-+}
-+
-+static int stf_isp_soft_rdma(struct stf_isp_dev *isp_dev, u32 rdma_addr)
-+{
-+      struct stf_vin_dev *vin = isp_dev->stfcamss->vin;
-+      void __iomem *ispbase;
-+      struct isp_rdma_info *rdma_info = NULL;
-+      s32 len;
-+      u32 offset;
-+      int ret = 0;
-+
-+      ispbase = stf_isp_get_ispbase(vin);
-+
-+      rdma_info = phys_to_virt(rdma_addr);
-+      while (1) {
-+              if (rdma_info->tag == RDMA_WR_ONE) {
-+                      reg_write(ispbase, rdma_info->offset, rdma_info->param);
-+                      rdma_info++;
-+              } else if (rdma_info->tag == RDMA_WR_SRL) {
-+                      offset = rdma_info->offset;
-+                      len = rdma_info->param;
-+                      rdma_info++;
-+                      while (len > 0) {
-+                              reg_write(ispbase, offset, rdma_info->param);
-+                              offset += 4;
-+                              len--;
-+                              if (len > 0) {
-+                                      reg_write(ispbase, offset, rdma_info->value);
-+                                      len--;
-+                              }
-+                              offset += 4;
-+                              rdma_info++;
-+                      }
-+              } else if (rdma_info->tag == RDMA_LINK) {
-+                      rdma_info = phys_to_virt(rdma_info->param);
-+              } else if (rdma_info->tag == RDMA_SINT) {
-+                      /* Software not support this command. */
-+                      rdma_info++;
-+              } else if (rdma_info->tag == RDMA_END) {
-+                      break;
-+              } else
-+                      rdma_info++;
-+      }
-+
-+      return ret;
-+}
-+
-+static int stf_isp_reg_write(struct stf_isp_dev *isp_dev, void *arg)
-+{
-+      struct stf_vin_dev *vin = isp_dev->stfcamss->vin;
-+      void __iomem *ispbase;
-+      struct isp_reg_param *reg_param = arg;
-+      struct isp_rdma_info *rdma_info = NULL;
-+      s32 len;
-+      u32 offset;
-+      u32 size;
-+      unsigned long r;
-+      int ret = 0;
-+
-+      if ((reg_param->reg_buf == NULL)
-+              && (reg_param->reg_info.method != STF_ISP_REG_METHOD_SOFT_RDMA)) {
-+              st_err(ST_ISP, "Failed to access register. \
-+                      The register buffer pointer is NULL!!!\n");
-+              return -EINVAL;
-+      }
-+
-+      ispbase = stf_isp_get_ispbase(vin);
-+
-+      size = 0;
-+      switch (reg_param->reg_info.method) {
-+      case STF_ISP_REG_METHOD_ONE_REG:
-+              size = sizeof(u32);
-+              break;
-+
-+      case STF_ISP_REG_METHOD_SERIES:
-+              if (reg_param->reg_info.length > STF_ISP_REG_BUF_SIZE) {
-+                      st_err(ST_ISP, "Failed to access register. \
-+                              The (length=0x%08X > 0x%08X) is out of size!!!\n",
-+                              reg_param->reg_info.length, STF_ISP_REG_BUF_SIZE);
-+                      return -EINVAL;
-+              }
-+              size = sizeof(u32) * reg_param->reg_info.length;
-+              break;
-+
-+      case STF_ISP_REG_METHOD_MODULE:
-+              // This mode is not supported in the V4L2 version.
-+              st_err(ST_ISP, "Reg Write - Failed to access register. \
-+                      The method = STF_ISP_REG_METHOD_MODULE is not supported!!!\n");
-+              return -ENOTTY;
-+
-+      case STF_ISP_REG_METHOD_TABLE:
-+              if (reg_param->reg_info.length > STF_ISP_REG_TBL_BUF_SIZE) {
-+                      st_err(ST_ISP, "Failed to access register. \
-+                              The (length=0x%08X > 0x%08X) is out of size!!!\n",
-+                              reg_param->reg_info.length, STF_ISP_REG_TBL_BUF_SIZE);
-+                      return -EINVAL;
-+              }
-+              size = sizeof(u32) * reg_param->reg_info.length * 2;
-+              break;
-+
-+      case STF_ISP_REG_METHOD_TABLE_2:
-+              if (reg_param->reg_info.length > STF_ISP_REG_TBL_2_BUF_SIZE) {
-+                      st_err(ST_ISP, "Failed to access register. \
-+                              The (length=0x%08X > 0x%08X) is out of size!!!\n",
-+                              reg_param->reg_info.length, STF_ISP_REG_TBL_2_BUF_SIZE);
-+                      return -EINVAL;
-+              }
-+              size = sizeof(u32) * reg_param->reg_info.length * 3;
-+              break;
-+
-+      case STF_ISP_REG_METHOD_TABLE_3:
-+              if (reg_param->reg_info.length > STF_ISP_REG_TBL_3_BUF_SIZE) {
-+                      st_err(ST_ISP, "Failed to access register. \
-+                              The (length=0x%08X > 0x%08X) is out of size!!!\n",
-+                              reg_param->reg_info.length, STF_ISP_REG_TBL_3_BUF_SIZE);
-+                      return -EINVAL;
-+              }
-+              size = sizeof(u32) * reg_param->reg_info.length * 4;
-+              break;
-+
-+      case STF_ISP_REG_METHOD_SMPL_PACK:
-+              if (reg_param->reg_info.length > STF_ISP_REG_SMPL_PACK_BUF_SIZE) {
-+                      st_err(ST_ISP, "Failed to access register. \
-+                              The (length=0x%08X > 0x%08X) is out of size!!!\n",
-+                              reg_param->reg_info.length, STF_ISP_REG_SMPL_PACK_BUF_SIZE);
-+                      return -EINVAL;
-+              }
-+              size = sizeof(u32) * reg_param->reg_info.length * 2;
-+              break;
-+
-+      case STF_ISP_REG_METHOD_SOFT_RDMA:
-+              break;
-+
-+      default:
-+              st_err(ST_ISP, "Failed to access register. The method=%d \
-+                      is not supported!!!\n", reg_param->reg_info.method);
-+              return -ENOTTY;
-+      }
-+
-+      memset(&reg_buf, 0, sizeof(union reg_buf));
-+      if (size) {
-+              r = copy_from_user((u8 *)reg_buf.buffer,
-+                      (u8 *)reg_param->reg_buf->buffer, size);
-+              if (r) {
-+                      st_err(ST_ISP, "Failed to call copy_from_user for the \
-+                              reg_param->reg_buf value\n");
-+                      return -EIO;
-+              }
-+      }
-+
-+      switch (reg_param->reg_info.method) {
-+      case STF_ISP_REG_METHOD_ONE_REG:
-+              reg_write(ispbase, reg_param->reg_info.offset, reg_buf.buffer[0]);
-+              break;
-+
-+      case STF_ISP_REG_METHOD_SERIES:
-+              for (r = 0; r < reg_param->reg_info.length; r++) {
-+                      reg_write(ispbase, reg_param->reg_info.offset + (r * 4),
-+                              reg_buf.buffer[r]);
-+              }
-+              break;
-+
-+      case STF_ISP_REG_METHOD_MODULE:
-+              /* This mode is not supported in the V4L2 version. */
-+              break;
-+
-+      case STF_ISP_REG_METHOD_TABLE:
-+              for (r = 0; r < reg_param->reg_info.length; r++) {
-+                      reg_write(ispbase, reg_buf.reg_tbl[r].offset,
-+                              reg_buf.reg_tbl[r].value);
-+              }
-+              break;
-+
-+      case STF_ISP_REG_METHOD_TABLE_2:
-+              for (r = 0; r < reg_param->reg_info.length; r++) {
-+                      if (reg_buf.reg_tbl2[r].mask) {
-+                              reg_set_bit(ispbase, reg_buf.reg_tbl2[r].offset,
-+                                      reg_buf.reg_tbl2[r].mask, reg_buf.reg_tbl2[r].value);
-+                      } else {
-+                              reg_write(ispbase, reg_buf.reg_tbl2[r].offset,
-+                                      reg_buf.reg_tbl2[r].value);
-+                      }
-+              }
-+              break;
-+
-+      case STF_ISP_REG_METHOD_TABLE_3:
-+              for (r = 0; r < reg_param->reg_info.length; r++) {
-+                      if (reg_buf.reg_tbl3[r].mask) {
-+                              reg_set_bit(ispbase, reg_buf.reg_tbl3[r].offset,
-+                                      reg_buf.reg_tbl3[r].mask, reg_buf.reg_tbl3[r].value);
-+                      } else {
-+                              reg_write(ispbase, reg_buf.reg_tbl3[r].offset,
-+                                      reg_buf.reg_tbl3[r].value);
-+                      }
-+                      if (reg_buf.reg_tbl3[r].delay_ms) {
-+                              usleep_range(1000 * reg_buf.reg_tbl3[r].delay_ms,
-+                                      1000 * reg_buf.reg_tbl3[r].delay_ms + 100);
-+                      }
-+              }
-+              break;
-+
-+      case STF_ISP_REG_METHOD_SMPL_PACK:
-+              size = reg_param->reg_info.length;
-+              rdma_info = &reg_buf.rdma_cmd[0];
-+              while (size) {
-+                      if (rdma_info->tag == RDMA_WR_ONE) {
-+                              reg_write(ispbase, rdma_info->offset, rdma_info->param);
-+                              rdma_info++;
-+                              size--;
-+                      } else if (rdma_info->tag == RDMA_WR_SRL) {
-+                              offset = rdma_info->offset;
-+                              len = rdma_info->param;
-+                              rdma_info++;
-+                              size--;
-+                              while (size && (len > 0)) {
-+                                      reg_write(ispbase, offset, rdma_info->param);
-+                                      offset += 4;
-+                                      len--;
-+                                      if (len > 0) {
-+                                              reg_write(ispbase, offset, rdma_info->value);
-+                                              len--;
-+                                      }
-+                                      offset += 4;
-+                                      rdma_info++;
-+                                      size--;
-+                              }
-+                      } else if (rdma_info->tag == RDMA_END) {
-+                              break;
-+                      } else {
-+                              rdma_info++;
-+                              size--;
-+                      }
-+              }
-+              break;
-+
-+      case STF_ISP_REG_METHOD_SOFT_RDMA:
-+              /*
-+               * Simulation the hardware RDMA behavior to debug and verify
-+               * the RDMA chain.
-+               */
-+              ret = stf_isp_soft_rdma(isp_dev, reg_param->reg_info.offset);
-+              break;
-+
-+      default:
-+              break;
-+      }
-+
-+      return ret;
-+}
-+
-+static int stf_isp_shadow_trigger(struct stf_isp_dev *isp_dev)
-+{
-+      struct stf_vin_dev *vin = isp_dev->stfcamss->vin;
-+      void __iomem *ispbase;
-+
-+      ispbase = stf_isp_get_ispbase(vin);
-+
-+      // shadow update
-+      reg_set_bit(ispbase, ISP_REG_CSIINTS_ADDR, (BIT(17) | BIT(16)), 0x30000);
-+      reg_set_bit(ispbase, ISP_REG_IESHD_ADDR, (BIT(1) | BIT(0)), 0x3);
-+      return 0;
-+}
-+
-+void dump_isp_reg(void *__iomem ispbase)
-+{
-+      int j;
-+      u32 addr, val;
-+
-+      st_debug(ST_ISP, "DUMP ISP register:\n -- isp_reg_init_settings --\n");
-+      for (j = 0; j < isp_reg_init_settings->regval_num; j++) {
-+              addr = isp_reg_init_settings->regval[j].addr;
-+              val = ioread32(ispbase + addr);
-+              st_debug(ST_ISP, "{0x%08x, 0x%08x}\n", addr, val);
-+      }
-+
-+      st_debug(ST_ISP, " --- isp_format_settings ---\n");
-+      for (j = 0; j < isp_format_settings->regval_num; j++) {
-+              addr = isp_format_settings->regval[j].addr;
-+              val = ioread32(ispbase + addr);
-+              st_debug(ST_ISP, "{0x%08x, 0x%08x}\n", addr, val);
-+      }
-+
-+      val = ioread32(ispbase + ISP_REG_Y_PLANE_START_ADDR);
-+      st_debug(ST_ISP, "-- ISP_REG_Y_PLANE_START_ADDR --\n {0x%08x, 0x%08x}\n",
-+               ISP_REG_Y_PLANE_START_ADDR, val);
-+      val = ioread32(ispbase + ISP_REG_UV_PLANE_START_ADDR);
-+      st_debug(ST_ISP, "-- ISP_REG_UV_PLANE_START_ADDR --\n {0x%08x, 0x%08x}\n",
-+               ISP_REG_UV_PLANE_START_ADDR, val);
-+      val = ioread32(ispbase + ISP_REG_DUMP_CFG_0);
-+      st_debug(ST_ISP, "-- ISP_REG_DUMP_CFG_0 --\n {0x%08x, 0x%08x}\n",
-+               ISP_REG_DUMP_CFG_0, val);
-+      val = ioread32(ispbase + ISP_REG_DUMP_CFG_1);
-+      st_debug(ST_ISP, " --- ISP_REG_DUMP_CFG_1 ---\n {0x%08x, 0x%08x}\n",
-+               ISP_REG_DUMP_CFG_1, val);
-+
-+      st_debug(ST_ISP, " --- isp_reg_start_settings ---\n");
-+      for (j = 0; j < isp_reg_start_settings->regval_num; j++) {
-+              addr = isp_reg_start_settings->regval[j].addr;
-+              val = ioread32(ispbase + addr);
-+              st_debug(ST_ISP, "{0x%08x, 0x%08x}\n", addr, val);
-+      }
-+}
-+
-+struct isp_hw_ops isp_ops = {
-+      .isp_clk_enable        = stf_isp_clk_enable,
-+      .isp_clk_disable       = stf_isp_clk_disable,
-+      .isp_reset             = stf_isp_reset,
-+      .isp_config_set        = stf_isp_config_set,
-+      .isp_set_format        = stf_isp_set_format,
-+      .isp_stream_set        = stf_isp_stream_set,
-+      .isp_reg_read          = stf_isp_reg_read,
-+      .isp_reg_write         = stf_isp_reg_write,
-+      .isp_shadow_trigger    = stf_isp_shadow_trigger,
-+};
---- /dev/null
-+++ b/drivers/media/platform/starfive/v4l2_driver/stf_isp_ioctl.h
-@@ -0,0 +1,133 @@
-+/* SPDX-License-Identifier: GPL-2.0 */
-+/*
-+ * Copyright (C) 2021-2023 StarFive Technology Co., Ltd.
-+ *
-+ */
-+
-+#ifndef STF_ISP_IOCTL_H
-+#define STF_ISP_IOCTL_H
-+
-+
-+#include <media/v4l2-ctrls.h>
-+
-+
-+#define FILENAME_MAX_LEN     30
-+
-+#define ISP_IOC                         ('V')
-+#define STF_ISP_REG_BUF_SIZE            (768)
-+#define STF_ISP_REG_TBL_BUF_SIZE        (STF_ISP_REG_BUF_SIZE / 2)
-+#define STF_ISP_REG_TBL_2_BUF_SIZE      (STF_ISP_REG_BUF_SIZE / 3)
-+#define STF_ISP_REG_TBL_3_BUF_SIZE      (STF_ISP_REG_BUF_SIZE / 4)
-+#define STF_ISP_REG_SMPL_PACK_BUF_SIZE  (STF_ISP_REG_BUF_SIZE / 2)
-+#define RDMA_WR_ONE                     (0xA0)
-+#define RDMA_WR_SRL                     (0xA1)
-+#define RDMA_LINK                       (0xA2)
-+#define RDMA_SINT                       (0xA3)
-+#define RDMA_END                        (0xAF)
-+#define ENABLE_SS0_SS1
-+
-+enum _STF_ISP_IOCTL {
-+      STF_ISP_IOCTL_LOAD_FW = BASE_VIDIOC_PRIVATE + 1,
-+      STF_ISP_IOCTL_DMABUF_ALLOC,
-+      STF_ISP_IOCTL_DMABUF_FREE,
-+      STF_ISP_IOCTL_GET_HW_VER,
-+      STF_ISP_IOCTL_REG,
-+      STF_ISP_IOCTL_SHADOW_LOCK,
-+      STF_ISP_IOCTL_SHADOW_UNLOCK,
-+      STF_ISP_IOCTL_SHADOW_UNLOCK_N_TRIGGER,
-+      STF_ISP_IOCTL_SET_USER_CONFIG_ISP,
-+      STF_ISP_IOCTL_MAX
-+};
-+
-+enum _STF_ISP_REG_METHOD {
-+      STF_ISP_REG_METHOD_ONE_REG = 0,
-+      STF_ISP_REG_METHOD_SERIES,
-+      STF_ISP_REG_METHOD_MODULE,
-+      STF_ISP_REG_METHOD_TABLE,
-+      STF_ISP_REG_METHOD_TABLE_2,
-+      STF_ISP_REG_METHOD_TABLE_3,
-+      STF_ISP_REG_METHOD_SMPL_PACK,
-+      STF_ISP_REG_METHOD_SOFT_RDMA,
-+      STF_ISP_REG_METHOD_MAX
-+};
-+
-+
-+struct stfisp_fw_info {
-+      char __user filename[FILENAME_MAX_LEN];
-+};
-+
-+struct dmabuf_create {
-+      __u32 fd;
-+      __u32 size;
-+      __u32 paddr;
-+};
-+
-+struct isp_rdma_info {
-+      u32 param;
-+      union {
-+              u32 value;
-+              struct {
-+                      u32 offset  : 24;
-+                      u32 tag     : 8;
-+              };
-+      };
-+};
-+
-+struct isp_reg_info {
-+      /** @brief [in] access method of register */
-+      u8 method;
-+      /** @brief [in] offset indicated which register will be read/write */
-+      u32 offset;
-+      /** @brief [in] length for indicated how much register will be read/write */
-+      u32 length;
-+};
-+
-+union reg_buf {
-+      u32 buffer[STF_ISP_REG_BUF_SIZE];
-+      struct {
-+              u32 offset;
-+              u32 value;
-+      } reg_tbl[STF_ISP_REG_TBL_BUF_SIZE];
-+      struct {
-+              u32 offset;
-+              u32 value;
-+              u32 mask;
-+      } reg_tbl2[STF_ISP_REG_TBL_2_BUF_SIZE];
-+      struct {
-+              u32 offset;
-+              u32 value;
-+              u32 mask;
-+              u32 delay_ms;
-+      } reg_tbl3[STF_ISP_REG_TBL_3_BUF_SIZE];
-+      struct isp_rdma_info rdma_cmd[STF_ISP_REG_SMPL_PACK_BUF_SIZE];
-+};
-+
-+struct isp_reg_param {
-+      /** @brief [in, out] register read/write information */
-+      struct isp_reg_info reg_info;
-+      /** @brief [in, out] buffer */
-+      union reg_buf *reg_buf;
-+};
-+
-+
-+#define VIDIOC_STFISP_LOAD_FW \
-+      _IOW(ISP_IOC, STF_ISP_IOCTL_LOAD_FW, struct stfisp_fw_info)
-+#define VIDIOC_STF_DMABUF_ALLOC \
-+      _IOWR(ISP_IOC, STF_ISP_IOCTL_DMABUF_ALLOC, struct dmabuf_create)
-+#define VIDIOC_STF_DMABUF_FREE \
-+      _IOWR(ISP_IOC, STF_ISP_IOCTL_DMABUF_FREE, struct dmabuf_create)
-+#define VIDIOC_STFISP_GET_REG \
-+      _IOWR(ISP_IOC, STF_ISP_IOCTL_REG, struct isp_reg_param)
-+#define VIDIOC_STFISP_SET_REG \
-+      _IOW(ISP_IOC, STF_ISP_IOCTL_REG, struct isp_reg_param)
-+#define VIDIOC_STFISP_SHADOW_LOCK \
-+      _IO(ISP_IOC, STF_ISP_IOCTL_SHADOW_LOCK)
-+#define VIDIOC_STFISP_SHADOW_UNLOCK \
-+      _IO(ISP_IOC, STF_ISP_IOCTL_SHADOW_UNLOCK)
-+#define VIDIOC_STFISP_SHADOW_UNLOCK_N_TRIGGER \
-+      _IO(ISP_IOC, STF_ISP_IOCTL_SHADOW_UNLOCK_N_TRIGGER)
-+#define VIDIOC_STFISP_SET_USER_CONFIG_ISP \
-+      _IO(ISP_IOC, STF_ISP_IOCTL_SET_USER_CONFIG_ISP)
-+
-+
-+#endif /* STF_ISP_IOCTL_H */
---- /dev/null
-+++ b/drivers/media/platform/starfive/v4l2_driver/stf_video.c
-@@ -0,0 +1,1552 @@
-+// SPDX-License-Identifier: GPL-2.0
-+/*
-+ * Copyright (C) 2021-2023 StarFive Technology Co., Ltd.
-+ *
-+ */
-+
-+#include "stfcamss.h"
-+#include "stf_video.h"
-+#include <media/media-entity.h>
-+#include <media/v4l2-event.h>
-+#include <media/v4l2-mc.h>
-+#include <media/videobuf2-dma-sg.h>
-+#include <media/videobuf2-vmalloc.h>
-+#include <media/videobuf2-dma-contig.h>
-+
-+static const struct stfcamss_format_info formats_pix_st7110_wr[] = {
-+      { MEDIA_BUS_FMT_AYUV8_1X32, V4L2_PIX_FMT_AYUV32, 1,
-+        { { 1, 1 } }, { { 1, 1 } }, { 32 } },
-+      { MEDIA_BUS_FMT_YUYV8_2X8, V4L2_PIX_FMT_YUYV, 1,
-+        { { 1, 1 } }, { { 1, 1 } }, { 16 } },
-+      { MEDIA_BUS_FMT_RGB565_2X8_LE, V4L2_PIX_FMT_RGB565, 1,
-+        { { 1, 1 } }, { { 1, 1 } }, { 16 } },
-+      { MEDIA_BUS_FMT_SRGGB8_1X8, V4L2_PIX_FMT_SRGGB8, 1,
-+        { { 1, 1 } }, { { 1, 1 } }, { 8 } },
-+      { MEDIA_BUS_FMT_SGRBG8_1X8, V4L2_PIX_FMT_SGRBG8, 1,
-+        { { 1, 1 } }, { { 1, 1 } }, { 8 } },
-+      { MEDIA_BUS_FMT_SGBRG8_1X8, V4L2_PIX_FMT_SGBRG8, 1,
-+        { { 1, 1 } }, { { 1, 1 } }, { 8 } },
-+      { MEDIA_BUS_FMT_SBGGR8_1X8, V4L2_PIX_FMT_SBGGR8, 1,
-+        { { 1, 1 } }, { { 1, 1 } }, { 8 } },
-+      { 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_raw_st7110_isp[] = {
-+      { MEDIA_BUS_FMT_SBGGR12_1X12, V4L2_PIX_FMT_SBGGR12, 1,
-+        { { 1, 1 } }, { { 1, 1 } }, { 12 } },
-+      { MEDIA_BUS_FMT_SRGGB12_1X12, V4L2_PIX_FMT_SRGGB12, 1,
-+        { { 1, 1 } }, { { 1, 1 } }, { 12 } },
-+      { MEDIA_BUS_FMT_SGRBG12_1X12, V4L2_PIX_FMT_SGRBG12, 1,
-+        { { 1, 1 } }, { { 1, 1 } }, { 12 } },
-+      { MEDIA_BUS_FMT_SGBRG12_1X12, V4L2_PIX_FMT_SGBRG12, 1,
-+        { { 1, 1 } }, { { 1, 1 } }, { 12 } },
-+};
-+
-+static const struct stfcamss_format_info formats_pix_st7110_isp[] = {
-+      // { MEDIA_BUS_FMT_YUYV12_2X12, V4L2_PIX_FMT_NV12M, 2,
-+      //  { { 1, 1 }, { 1, 1 } }, { { 1, 1 }, { 1, 1 } }, { 8 , 4 } },
-+      { MEDIA_BUS_FMT_Y12_1X12, V4L2_PIX_FMT_NV12, 1,
-+        { { 1, 1 } }, { { 2, 3 } }, { 8 } },
-+      { MEDIA_BUS_FMT_Y12_1X12, V4L2_PIX_FMT_NV21, 1,
-+        { { 1, 1 } }, { { 2, 3 } }, { 8 } },
-+};
-+
-+static const struct stfcamss_format_info formats_st7110_isp_iti[] = {
-+      //  raw format
-+      { 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 } },
-+      { MEDIA_BUS_FMT_SRGGB12_1X12, V4L2_PIX_FMT_SRGGB12, 1,
-+        { { 1, 1 } }, { { 1, 1 } }, { 12 } },
-+      { MEDIA_BUS_FMT_SGRBG12_1X12, V4L2_PIX_FMT_SGRBG12, 1,
-+        { { 1, 1 } }, { { 1, 1 } }, { 12 } },
-+      { MEDIA_BUS_FMT_SGBRG12_1X12, V4L2_PIX_FMT_SGBRG12, 1,
-+        { { 1, 1 } }, { { 1, 1 } }, { 12 } },
-+      { MEDIA_BUS_FMT_SBGGR12_1X12, V4L2_PIX_FMT_SBGGR12, 1,
-+        { { 1, 1 } }, { { 1, 1 } }, { 12 } },
-+
-+      // YUV420
-+      { MEDIA_BUS_FMT_Y12_1X12, V4L2_PIX_FMT_NV12, 1,
-+        { { 1, 1 } }, { { 2, 3 } }, { 8 } },
-+      { MEDIA_BUS_FMT_Y12_1X12, V4L2_PIX_FMT_NV21, 1,
-+        { { 1, 1 } }, { { 2, 3 } }, { 8 } },
-+
-+      // YUV444
-+      { MEDIA_BUS_FMT_YUV8_1X24, V4L2_PIX_FMT_NV24, 1,
-+        { { 1, 1 } }, { { 1, 3 } }, { 8 } },
-+      { MEDIA_BUS_FMT_VUY8_1X24, V4L2_PIX_FMT_NV42, 1,
-+        { { 1, 1 } }, { { 1, 3 } }, { 8 } },
-+};
-+
-+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, int is_mp)
-+{
-+      struct v4l2_pix_format *pix;
-+      struct v4l2_pix_format_mplane *pix_mp;
-+      const struct stfcamss_format_info *fi;
-+      u32 width, height;
-+      u32 bpl;
-+      int i, j;
-+
-+      st_debug(ST_VIDEO, "%s, fmt.type = 0x%x\n", __func__, f->type);
-+      pix = &f->fmt.pix;
-+      pix_mp = &f->fmt.pix_mp;
-+
-+      if (is_mp) {
-+              for (i = 0; i < video->nformats; i++)
-+                      if (pix_mp->pixelformat
-+                              == video->formats[i].pixelformat)
-+                              break;
-+
-+              if (i == video->nformats)
-+                      i = 0; /* default format */
-+
-+              fi = &video->formats[i];
-+              width = pix_mp->width;
-+              height = pix_mp->height;
-+
-+              memset(pix_mp, 0, sizeof(*pix_mp));
-+
-+              pix_mp->pixelformat = fi->pixelformat;
-+              pix_mp->width = clamp_t(u32, width, STFCAMSS_FRAME_MIN_WIDTH,
-+                              STFCAMSS_FRAME_MAX_WIDTH);
-+              pix_mp->height = clamp_t(u32, height, STFCAMSS_FRAME_MIN_HEIGHT,
-+                              STFCAMSS_FRAME_MAX_HEIGHT);
-+              pix_mp->num_planes = fi->planes;
-+              for (j = 0; j < pix_mp->num_planes; j++) {
-+                      bpl = pix_mp->width / fi->hsub[j].numerator *
-+                              fi->hsub[j].denominator * fi->bpp[j] / 8;
-+                      bpl = ALIGN(bpl, video->bpl_alignment);
-+                      pix_mp->plane_fmt[j].bytesperline = bpl;
-+                      pix_mp->plane_fmt[j].sizeimage = pix_mp->height /
-+                              fi->vsub[j].numerator
-+                              * fi->vsub[j].denominator * bpl;
-+              }
-+
-+              pix_mp->field = V4L2_FIELD_NONE;
-+              pix_mp->colorspace = V4L2_COLORSPACE_SRGB;
-+              pix_mp->flags = 0;
-+              pix_mp->ycbcr_enc =
-+                      V4L2_MAP_YCBCR_ENC_DEFAULT(pix_mp->colorspace);
-+              pix_mp->quantization =
-+                      V4L2_MAP_QUANTIZATION_DEFAULT(true,
-+                              pix_mp->colorspace, pix_mp->ycbcr_enc);
-+              pix_mp->xfer_func =
-+                      V4L2_MAP_XFER_FUNC_DEFAULT(pix_mp->colorspace);
-+
-+              st_info(ST_VIDEO, "w, h = %d, %d, bpp = %d\n", pix_mp->width,
-+                              pix_mp->height, fi->bpp[0]);
-+              st_info(ST_VIDEO, "i = %d, p = %d, s = 0x%x\n", i,
-+                              pix_mp->num_planes, pix_mp->plane_fmt[0].sizeimage);
-+
-+      } else {
-+              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);
-+
-+              st_info(ST_VIDEO, "w, h = %d, %d, bpp = %d\n", pix->width,
-+                              pix->height, fi->bpp[0]);
-+              st_info(ST_VIDEO, "i = %d, s = 0x%x\n", i, pix->sizeimage);
-+      }
-+      return 0;
-+}
-+
-+static int stf_video_init_format(struct stfcamss_video *video, int is_mp)
-+{
-+      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, is_mp);
-+
-+      if (ret < 0)
-+              return ret;
-+
-+      video->active_fmt = format;
-+
-+      return 0;
-+}
-+
-+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;
-+      const struct v4l2_pix_format_mplane *format_mp =
-+                      &video->active_fmt.fmt.pix_mp;
-+      unsigned int i;
-+
-+      st_debug(ST_VIDEO, "%s, planes = %d\n", __func__, *num_planes);
-+
-+      if (video->is_mp) {
-+              if (*num_planes) {
-+                      if (*num_planes != format_mp->num_planes)
-+                              return -EINVAL;
-+
-+                      for (i = 0; i < *num_planes; i++)
-+                              if (sizes[i] <
-+                                      format_mp->plane_fmt[i].sizeimage)
-+                                      return -EINVAL;
-+
-+                      return 0;
-+              }
-+
-+              *num_planes = format_mp->num_planes;
-+
-+              for (i = 0; i < *num_planes; i++)
-+                      sizes[i] = format_mp->plane_fmt[i].sizeimage;
-+      } else {
-+              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])
-+                      st_err(ST_VIDEO, "%s: error size is zero!!!\n", __func__);
-+      }
-+      if ((stf_vin_map_isp_pad(video->id, STF_ISP_PAD_SRC)
-+              == STF_ISP_PAD_SRC_SCD_Y) &&
-+              sizes[0] < ISP_SCD_Y_BUFFER_SIZE) {
-+              sizes[0] = ISP_SCD_Y_BUFFER_SIZE;
-+      }
-+
-+      st_info(ST_VIDEO, "%s, planes = %d, size = %d\n",
-+                      __func__, *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;
-+      const struct v4l2_pix_format_mplane *fmt_mp =
-+                              &video->active_fmt.fmt.pix_mp;
-+      //struct sg_table *sgt;
-+      dma_addr_t *paddr;
-+      unsigned int i;
-+
-+      buffer->sizeimage = 0;
-+
-+      if (video->is_mp) {
-+              for (i = 0; i < fmt_mp->num_planes; i++) {
-+                      paddr = vb2_plane_cookie(vb, i);
-+                      buffer->addr[i] = *paddr;
-+              buffer->sizeimage += vb2_plane_size(vb, i);
-+              }
-+
-+              if (fmt_mp->num_planes == 1
-+                      && (fmt_mp->pixelformat == V4L2_PIX_FMT_NV12
-+                      || fmt_mp->pixelformat == V4L2_PIX_FMT_NV21
-+                      || fmt_mp->pixelformat == V4L2_PIX_FMT_NV16
-+                      || fmt_mp->pixelformat == V4L2_PIX_FMT_NV61))
-+                      buffer->addr[1] = buffer->addr[0] +
-+                                      fmt_mp->plane_fmt[0].bytesperline *
-+                                      fmt_mp->height;
-+      } else {
-+              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;
-+      }
-+
-+      if (stf_vin_map_isp_pad(video->id, STF_ISP_PAD_SRC)
-+              == STF_ISP_PAD_SRC_SCD_Y) {
-+              buffer->addr[1] = buffer->addr[0] + ISP_YHIST_BUFFER_SIZE;
-+              buffer->vaddr_sc = vb2_plane_vaddr(vb, 0);
-+      }
-+
-+      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;
-+      const struct v4l2_pix_format_mplane *fmt_mp =
-+                                      &video->active_fmt.fmt.pix_mp;
-+      unsigned int i;
-+
-+      if (video->is_mp) {
-+              for (i = 0; i < fmt_mp->num_planes; i++) {
-+                      if (fmt_mp->plane_fmt[i].sizeimage
-+                                      > vb2_plane_size(vb, i))
-+                              return -EINVAL;
-+
-+                      vb2_set_plane_payload(vb, i,
-+                                      fmt_mp->plane_fmt[i].sizeimage);
-+              }
-+      } else {
-+              if (fmt->sizeimage > vb2_plane_size(vb, 0)) {
-+                      st_err(ST_VIDEO, "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);
-+}
-+
-+static int video_mbus_to_pix_mp(const struct v4l2_mbus_framefmt *mbus,
-+                              struct v4l2_pix_format_mplane *pix,
-+                              const struct stfcamss_format_info *f,
-+                              unsigned int alignment)
-+{
-+      unsigned int i;
-+      u32 bytesperline;
-+
-+      memset(pix, 0, sizeof(*pix));
-+      v4l2_fill_pix_format_mplane(pix, mbus);
-+      pix->pixelformat = f->pixelformat;
-+      pix->num_planes = f->planes;
-+      for (i = 0; i < pix->num_planes; i++) {
-+              bytesperline = pix->width / f->hsub[i].numerator *
-+                      f->hsub[i].denominator * f->bpp[i] / 8;
-+              bytesperline = ALIGN(bytesperline, alignment);
-+              pix->plane_fmt[i].bytesperline = bytesperline;
-+              pix->plane_fmt[i].sizeimage = pix->height /
-+                              f->vsub[i].numerator * f->vsub[i].denominator *
-+                              bytesperline;
-+      }
-+
-+      return 0;
-+}
-+
-+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_pix_format_mplane *pix_mp =
-+                              &video->active_fmt.fmt.pix_mp;
-+      struct v4l2_subdev_format fmt;
-+      struct v4l2_subdev *subdev;
-+      u32 pixelformat;
-+      u32 pad;
-+      int ret;
-+
-+      subdev = video_remote_subdev(video, &pad);
-+      if (subdev == NULL)
-+              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;
-+
-+      if (video->is_mp)
-+              pixelformat = pix_mp->pixelformat;
-+      else
-+              pixelformat = pix->pixelformat;
-+      ret = video_find_format(fmt.format.code, pixelformat,
-+                              video->formats, video->nformats);
-+      if (ret < 0)
-+              return ret;
-+
-+      format->type = video->type;
-+
-+      if (video->is_mp)
-+              return video_mbus_to_pix_mp(&fmt.format, &format->fmt.pix_mp,
-+                              &video->formats[ret], video->bpl_alignment);
-+      else
-+              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_pix_format_mplane *pix_mp =
-+                              &video->active_fmt.fmt.pix_mp;
-+      struct v4l2_format format;
-+      struct v4l2_pix_format *sd_pix = &format.fmt.pix;
-+      struct v4l2_pix_format_mplane *sd_pix_mp = &format.fmt.pix_mp;
-+      int ret;
-+
-+      if (video->is_mp) {
-+              sd_pix_mp->pixelformat = pix_mp->pixelformat;
-+              ret = video_get_subdev_format(video, &format);
-+              if (ret < 0)
-+                      return ret;
-+
-+              if (pix_mp->pixelformat != sd_pix_mp->pixelformat ||
-+                      pix_mp->height > sd_pix_mp->height ||
-+                      pix_mp->width > sd_pix_mp->width ||
-+                      pix_mp->num_planes != sd_pix_mp->num_planes ||
-+                      pix_mp->field != format.fmt.pix_mp.field) {
-+                      st_err(ST_VIDEO,
-+                              "%s, not match:\n"
-+                              "0x%x 0x%x\n0x%x 0x%x\n0x%x 0x%x\n",
-+                              __func__,
-+                              pix_mp->pixelformat, sd_pix_mp->pixelformat,
-+                              pix_mp->height, sd_pix_mp->height,
-+                              pix_mp->field, format.fmt.pix_mp.field);
-+                      return -EPIPE;
-+              }
-+
-+      } else {
-+              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) {
-+                      st_err(ST_VIDEO,
-+                              "%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) {
-+              st_err(ST_VIDEO,
-+                      "Failed to video_device_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 getcrop_pad_id(int video_id)
-+{
-+      return stf_vin_map_isp_pad(video_id, STF_ISP_PAD_SRC);
-+}
-+
-+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_unique_pixelformat_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_pixelformat_by_mbus_code(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;
-+
-+      st_debug(ST_VIDEO, "%s:\n0x%x 0x%x\n 0x%x, 0x%x\n0x%x\n",
-+              __func__,
-+              f->type, video->type,
-+              f->index, video->nformats,
-+              f->mbus_code);
-+
-+      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_pixelformat_by_mbus_code(video, f->mbus_code);
-+      } else {
-+              i = video_get_unique_pixelformat_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 v4l2_subdev_frame_size_enum fse = {0};
-+      struct v4l2_subdev_mbus_code_enum code = {0};
-+      struct stfcamss_video *video = video_drvdata(file);
-+      struct video_device *vdev = &video->vdev;
-+      struct media_entity *entity = &vdev->entity;
-+      struct media_entity *sensor;
-+      struct v4l2_subdev *subdev;
-+      struct media_pad *pad;
-+      bool support_selection = false;
-+      int i;
-+      int ret;
-+
-+      for (i = 0; i < video->nformats; i++) {
-+              if (video->formats[i].pixelformat == fsize->pixel_format)
-+                      break;
-+      }
-+
-+      if (i == video->nformats)
-+              return -EINVAL;
-+
-+      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);
-+
-+              if (subdev->ops->pad->set_selection) {
-+                      support_selection = true;
-+                      break;
-+              }
-+      }
-+
-+      if (support_selection) {
-+              if (fsize->index)
-+                      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;
-+      } else {
-+              entity = &vdev->entity;
-+              sensor = stfcamss_find_sensor(entity);
-+              if (!sensor)
-+                      return -ENOTTY;
-+
-+              subdev = media_entity_to_v4l2_subdev(sensor);
-+              code.index = 0;
-+              code.which = V4L2_SUBDEV_FORMAT_ACTIVE;
-+              ret = v4l2_subdev_call(subdev, pad, enum_mbus_code, NULL, &code);
-+              if (ret < 0)
-+                      return -EINVAL;
-+              fse.index = fsize->index;
-+              fse.code = code.code;
-+              fse.which = V4L2_SUBDEV_FORMAT_ACTIVE;
-+              ret = v4l2_subdev_call(subdev, pad, enum_frame_size, NULL, &fse);
-+              if (ret < 0)
-+                      return -EINVAL;
-+              fsize->type = V4L2_FRMSIZE_TYPE_DISCRETE;
-+              fsize->discrete.width = fse.min_width;
-+              fsize->discrete.height = fse.min_height;
-+      }
-+
-+      return 0;
-+}
-+
-+static int video_enum_frameintervals(struct file *file, void *fh,
-+                              struct v4l2_frmivalenum *fival)
-+{
-+      int ret = 0;
-+      struct stfcamss_video *video = video_drvdata(file);
-+      struct video_device *vdev = &video->vdev;
-+      struct media_entity *entity = &vdev->entity;
-+      struct media_entity *sensor;
-+      struct v4l2_subdev *subdev;
-+      struct v4l2_subdev_mbus_code_enum code = {0};
-+      struct v4l2_subdev_frame_interval_enum fie = {0};
-+
-+      sensor = stfcamss_find_sensor(entity);
-+      if (!sensor)
-+              return -ENOTTY;
-+      fie.index = fival->index;
-+      fie.width = fival->width;
-+      fie.height = fival->height;
-+      fie.which = V4L2_SUBDEV_FORMAT_ACTIVE;
-+      subdev = media_entity_to_v4l2_subdev(sensor);
-+
-+      code.index = 0;
-+      code.which = V4L2_SUBDEV_FORMAT_ACTIVE;
-+
-+      /* Don't care about the code, just find by pixelformat */
-+      ret = video_find_format(0, fival->pixel_format,
-+                              video->formats, video->nformats);
-+      if (ret < 0)
-+              return -EINVAL;
-+
-+      ret = v4l2_subdev_call(subdev, pad, enum_mbus_code, NULL, &code);
-+      if (ret < 0)
-+              return -EINVAL;
-+
-+      fie.code = code.code;
-+      ret = v4l2_subdev_call(subdev, pad, enum_frame_interval, NULL, &fie);
-+      if (ret < 0)
-+              return ret;
-+
-+      fival->type = V4L2_FRMSIZE_TYPE_DISCRETE;
-+      fival->discrete = fie.interval;
-+
-+      return 0;
-+}
-+
-+static int video_g_fmt(struct file *file, void *fh, struct v4l2_format *f)
-+{
-+      struct stfcamss_video *video = video_drvdata(file);
-+
-+      st_debug(ST_VIDEO, "%s, fmt.type = 0x%x\n", __func__, f->type);
-+      st_debug(ST_VIDEO, "%s, active_fmt.type = 0x%x,0x%x\n",
-+                      __func__, video->active_fmt.type,
-+                      video->active_fmt.fmt.pix.pixelformat);
-+      *f = video->active_fmt;
-+      return 0;
-+}
-+
-+static int video_g_fmt_mp(struct file *file, void *fh, struct v4l2_format *f)
-+{
-+      struct stfcamss_video *video = video_drvdata(file);
-+
-+      st_debug(ST_VIDEO, "%s, fmt.type = 0x%x\n", __func__, f->type);
-+      st_debug(ST_VIDEO, "%s, active_fmt.type = 0x%x\n",
-+                      __func__, video->active_fmt.type);
-+      *f = video->active_fmt;
-+      return 0;
-+}
-+
-+static int video_entity_s_fmt(struct stfcamss_video *video,
-+                      struct media_entity *entity,
-+                      struct v4l2_subdev_state *state,
-+                      struct v4l2_subdev_format *fmt)
-+{
-+      struct v4l2_subdev *subdev;
-+      struct media_pad *pad;
-+      struct v4l2_mbus_framefmt *mf = &fmt->format;
-+      struct v4l2_subdev_format fmt_src = {
-+              .which = V4L2_SUBDEV_FORMAT_ACTIVE,
-+      };
-+      u32 width, height, code;
-+      int ret, index = 0;
-+
-+      code = mf->code;
-+      width = mf->width;
-+      height = mf->height;
-+      subdev = media_entity_to_v4l2_subdev(entity);
-+      while (1) {
-+              if (index >= entity->num_pads)
-+                      break;
-+              pad = &entity->pads[index];
-+              pad = media_pad_remote_pad_first(pad);
-+              if (pad && is_media_entity_v4l2_subdev(pad->entity)) {
-+                      fmt->pad = index;
-+                      ret = v4l2_subdev_call(subdev, pad, set_fmt, state, fmt);
-+                      if (mf->code != code ||
-+                              mf->width != width || mf->height != height) {
-+                              st_warn(ST_VIDEO,
-+                                      "\"%s\":%d pad fmt has been"
-+                                      " changed to 0x%x %ux%u\n",
-+                                      subdev->name, fmt->pad, mf->code,
-+                                      mf->width, mf->height);
-+                      }
-+                      if (index) {
-+                              fmt_src.pad = index;
-+                              ret = v4l2_subdev_call(subdev, pad, get_fmt, state, &fmt_src);
-+                              if (ret)
-+                                      return ret;
-+
-+                              fmt->format.code = fmt_src.format.code;
-+                              ret = video_entity_s_fmt(video, pad->entity, state, fmt);
-+                      }
-+              }
-+
-+              if (ret < 0 && ret != -ENOIOCTLCMD)
-+                      break;
-+              index++;
-+      }
-+      return ret;
-+}
-+
-+static int video_pipeline_s_fmt(struct stfcamss_video *video,
-+                      struct v4l2_subdev_state *state,
-+                      struct v4l2_format *f)
-+{
-+      struct video_device *vdev = &video->vdev;
-+      struct media_entity *entity = &vdev->entity;
-+      struct v4l2_subdev *subdev;
-+      int ret, index;
-+      struct v4l2_subdev_format fmt = {
-+              .pad = 0,
-+              .which = V4L2_SUBDEV_FORMAT_ACTIVE,
-+              .reserved = {getcrop_pad_id(video->id)}
-+      };
-+      struct v4l2_mbus_framefmt *mf = &fmt.format;
-+      struct v4l2_pix_format *pix = &f->fmt.pix;
-+      struct v4l2_pix_format_mplane *pix_mp = &f->fmt.pix_mp;
-+      struct media_entity *sensor;
-+      u32 width, height;
-+      struct media_pad *pad;
-+
-+      /* pix to mbus format */
-+      if (video->is_mp) {
-+              index = video_find_format(mf->code,
-+                                      pix_mp->pixelformat,
-+                                      video->formats, video->nformats);
-+              if (index < 0)
-+                      return index;
-+              v4l2_fill_mbus_format_mplane(mf, pix_mp);
-+              mf->code = video->formats[index].code;
-+      } else {
-+              index = video_find_format(mf->code,
-+                                      pix->pixelformat,
-+                                      video->formats, video->nformats);
-+              if (index < 0)
-+                      return index;
-+              v4l2_fill_mbus_format(mf, pix, video->formats[index].code);
-+      }
-+
-+      width = mf->width;
-+      height = mf->height;
-+
-+      sensor = stfcamss_find_sensor(entity);
-+      if (!sensor) {
-+              st_err(ST_VIDEO, "Can't find sensor\n");
-+              return -ENOTTY;
-+      }
-+
-+      subdev = media_entity_to_v4l2_subdev(sensor);
-+      ret = v4l2_subdev_call(subdev, pad, get_fmt, state, &fmt);
-+      if (ret)
-+              return ret;
-+
-+      /*
-+       * Starting from sensor subdevice, walk within
-+       * pipeline and set format on each subdevice
-+       */
-+      pad = media_pad_remote_pad_first(&sensor->pads[0]);
-+      ret = video_entity_s_fmt(video, pad->entity, state, &fmt);
-+      if (ret < 0 && ret != -ENOIOCTLCMD)
-+              return ret;
-+
-+      index = video_find_format(mf->code,
-+                              video->formats[index].pixelformat,
-+                              video->formats, video->nformats);
-+      st_debug(ST_VIDEO, "%s, code=%x, index=%d\n",
-+                      __func__, mf->code, index);
-+
-+      if (index < 0)
-+              return index;
-+
-+      if (video->is_mp)
-+              video_mbus_to_pix_mp(mf, pix_mp,
-+                              &video->formats[index], video->bpl_alignment);
-+      else
-+              video_mbus_to_pix(mf, pix,
-+                              &video->formats[index], video->bpl_alignment);
-+
-+      ret = __video_try_fmt(video, f, video->is_mp);
-+      if (ret < 0)
-+              return ret;
-+
-+      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;
-+
-+      st_debug(ST_VIDEO, "%s, fmt.type = 0x%x, v4l2fmt=%x\n",
-+                      __func__, f->type, f->fmt.pix.pixelformat);
-+
-+      if (vb2_is_busy(&video->vb2_q))
-+              return -EBUSY;
-+
-+      ret = __video_try_fmt(video, f, false);
-+      if (ret < 0)
-+              return ret;
-+
-+      ret = video_pipeline_s_fmt(video, NULL, f);
-+
-+      st_debug(ST_VIDEO, "%s, pixelformat=0x%x, ret=%d\n",
-+                      __func__, f->fmt.pix.pixelformat, ret);
-+      if (ret < 0)
-+              return ret;
-+
-+      video->active_fmt = *f;
-+
-+      return 0;
-+}
-+
-+static int video_s_fmt_mp(struct file *file, void *fh, struct v4l2_format *f)
-+{
-+      struct stfcamss_video *video = video_drvdata(file);
-+      int ret;
-+
-+      st_debug(ST_VIDEO, "%s, fmt.type = 0x%x\n", __func__, f->type);
-+      if (vb2_is_busy(&video->vb2_q))
-+              return -EBUSY;
-+
-+      ret = __video_try_fmt(video, f, true);
-+      if (ret < 0)
-+              return ret;
-+
-+      ret = video_pipeline_s_fmt(video, NULL, 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, false);
-+}
-+
-+static int video_try_fmt_mp(struct file *file,
-+              void *fh, struct v4l2_format *f)
-+{
-+      struct stfcamss_video *video = video_drvdata(file);
-+
-+      return __video_try_fmt(video, f, true);
-+}
-+
-+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;
-+}
-+
-+/* Crop ioctls */
-+int video_g_pixelaspect(struct file *file, void *fh,
-+                          int buf_type, struct v4l2_fract *aspect)
-+{
-+      return 0;
-+}
-+
-+int video_g_selection(struct file *file, void *fh,
-+                        struct v4l2_selection *s)
-+{
-+      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_subdev_selection sel = {
-+              .which = V4L2_SUBDEV_FORMAT_ACTIVE,
-+              .pad = getcrop_pad_id(video->id),
-+              .target = s->target,
-+              .r = s->r,
-+              .flags = s->flags,
-+      };
-+      int ret;
-+
-+      st_debug(ST_VIDEO, "%s, target = 0x%x, 0x%x\n",
-+                      __func__, sel.target, s->target);
-+      if (s->type != V4L2_BUF_TYPE_VIDEO_CAPTURE
-+              && s->type != V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE)
-+              return -EINVAL;
-+
-+      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, pad, get_selection, NULL, &sel);
-+              if (!ret) {
-+                      s->r = sel.r;
-+                      s->flags = sel.flags;
-+                      break;
-+              }
-+              if (ret != -ENOIOCTLCMD)
-+                      break;
-+      }
-+
-+      return ret;
-+}
-+
-+int video_s_selection(struct file *file, void *fh,
-+                      struct v4l2_selection *s)
-+{
-+      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_subdev_selection sel = {
-+              .which = V4L2_SUBDEV_FORMAT_ACTIVE,
-+              .pad = getcrop_pad_id(video->id),
-+              .target = s->target,
-+              .r = s->r,
-+              .flags = s->flags,
-+      };
-+      struct v4l2_pix_format *format = &video->active_fmt.fmt.pix;
-+      struct v4l2_pix_format_mplane *format_mp =
-+                                              &video->active_fmt.fmt.pix_mp;
-+      int ret;
-+
-+      st_debug(ST_VIDEO, "%s, target = 0x%x, 0x%x\n",
-+                      __func__, sel.target, s->target);
-+      if (s->type != V4L2_BUF_TYPE_VIDEO_CAPTURE
-+              && s->type != V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE)
-+              return -EINVAL;
-+
-+      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, pad, set_selection, NULL, &sel);
-+              if (!ret) {
-+                      s->r = sel.r;
-+                      s->flags = sel.flags;
-+                      format->width = s->r.width;
-+                      format->height = s->r.height;
-+                      format_mp->width = s->r.width;
-+                      format_mp->height = s->r.height;
-+                      ret = __video_try_fmt(video, &video->active_fmt,
-+                                      video->is_mp);
-+                      if (ret < 0)
-+                              return ret;
-+                      break;
-+              }
-+              if (ret != -ENOIOCTLCMD)
-+                      break;
-+      }
-+
-+      st_debug(ST_VIDEO, "ret = 0x%x, -EINVAL = 0x%x\n", ret, -EINVAL);
-+
-+      return ret;
-+}
-+
-+static const struct v4l2_ioctl_ops stf_vid_ioctl_ops = {
-+      .vidioc_querycap                = video_querycap,
-+      .vidioc_enum_fmt_vid_cap        = video_enum_fmt,
-+      .vidioc_enum_framesizes         = video_enum_framesizes,
-+      .vidioc_enum_frameintervals     = video_enum_frameintervals,
-+      .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_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,
-+      .vidioc_s_selection             = video_s_selection,
-+      .vidioc_g_selection             = video_g_selection,
-+};
-+
-+static const struct v4l2_ioctl_ops stf_vid_ioctl_ops_mp = {
-+      .vidioc_querycap                = video_querycap,
-+      .vidioc_enum_fmt_vid_cap        = video_enum_fmt,
-+      .vidioc_enum_framesizes         = video_enum_framesizes,
-+      .vidioc_enum_frameintervals     = video_enum_frameintervals,
-+      .vidioc_g_fmt_vid_cap_mplane    = video_g_fmt_mp,
-+      .vidioc_s_fmt_vid_cap_mplane    = video_s_fmt_mp,
-+      .vidioc_try_fmt_vid_cap_mplane  = video_try_fmt_mp,
-+      .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,
-+      .vidioc_s_selection             = video_s_selection,
-+      .vidioc_g_selection             = video_g_selection,
-+};
-+
-+static const struct v4l2_ioctl_ops stf_vid_ioctl_ops_out = {
-+      .vidioc_querycap                = video_querycap,
-+      .vidioc_enum_fmt_vid_out        = video_enum_fmt,
-+      .vidioc_enum_framesizes         = video_enum_framesizes,
-+      .vidioc_enum_frameintervals     = video_enum_frameintervals,
-+      .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,
-+};
-+
-+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 == NULL) {
-+              ret = -ENOMEM;
-+              goto error_alloc;
-+      }
-+
-+      v4l2_fh_init(vfh, vdev);
-+      v4l2_fh_add(vfh);
-+
-+      file->private_data = vfh;
-+
-+      if (!video->pm_count) {
-+              ret = v4l2_pipeline_pm_get(&vdev->entity);
-+              if (ret < 0) {
-+                      st_err(ST_VIDEO,
-+                              "Failed to power up pipeline: %d\n", ret);
-+                      goto error_pm_use;
-+              }
-+      }
-+
-+      video->pm_count++;
-+
-+      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);
-+      struct stfcamss_video *video = video_drvdata(file);
-+
-+      vb2_fop_release(file);
-+
-+      video->pm_count--;
-+
-+      if (!video->pm_count)
-+              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,
-+};
-+
-+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, int is_mp)
-+{
-+      struct video_device *vdev;
-+      struct vb2_queue *q;
-+      struct media_pad *pad = &video->pad;
-+      int ret;
-+      enum isp_pad_id isp_pad;
-+
-+      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 = is_mp ? V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE :
-+      //      V4L2_BUF_TYPE_VIDEO_CAPTURE;
-+      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) {
-+              st_err(ST_VIDEO,
-+                      "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) {
-+              st_err(ST_VIDEO,
-+                      "Failed to init video entity: %d\n",
-+                      ret);
-+              goto err_vb2_init;
-+      }
-+
-+      mutex_init(&video->lock);
-+
-+      isp_pad = stf_vin_map_isp_pad(video->id, STF_ISP_PAD_SRC);
-+      if (video->id == VIN_LINE_WR) {
-+              video->formats = formats_pix_st7110_wr;
-+              video->nformats = ARRAY_SIZE(formats_pix_st7110_wr);
-+              video->bpl_alignment = STFCAMSS_FRAME_WIDTH_ALIGN_8;
-+      } else if (isp_pad == STF_ISP_PAD_SRC
-+              || isp_pad == STF_ISP_PAD_SRC_SS0
-+              || isp_pad == STF_ISP_PAD_SRC_SS1) {
-+              video->formats = formats_pix_st7110_isp;
-+              video->nformats = ARRAY_SIZE(formats_pix_st7110_isp);
-+              video->bpl_alignment = STFCAMSS_FRAME_WIDTH_ALIGN_8;
-+      } else if (isp_pad == STF_ISP_PAD_SRC_ITIW
-+              || isp_pad == STF_ISP_PAD_SRC_ITIR) {
-+              video->formats = formats_st7110_isp_iti;
-+              video->nformats = ARRAY_SIZE(formats_st7110_isp_iti);
-+              video->bpl_alignment = STFCAMSS_FRAME_WIDTH_ALIGN_8;
-+      } else { // raw/scdump/yhist
-+              video->formats = formats_raw_st7110_isp;
-+              video->nformats = ARRAY_SIZE(formats_raw_st7110_isp);
-+              video->bpl_alignment = STFCAMSS_FRAME_WIDTH_ALIGN_128;
-+      }
-+      video->is_mp = is_mp;
-+
-+      ret = stf_video_init_format(video, is_mp);
-+      if (ret < 0) {
-+              st_err(ST_VIDEO, "Failed to init format: %d\n", ret);
-+              goto err_vid_init_format;
-+      }
-+
-+      vdev->fops = &stf_vid_fops;
-+      if (isp_pad == STF_ISP_PAD_SRC_ITIR) {
-+              vdev->device_caps = V4L2_CAP_VIDEO_OUTPUT;
-+              vdev->vfl_dir = VFL_DIR_TX;
-+      } else {
-+              vdev->device_caps = is_mp ? V4L2_CAP_VIDEO_CAPTURE_MPLANE :
-+                      V4L2_CAP_VIDEO_CAPTURE;
-+              vdev->vfl_dir = VFL_DIR_RX;
-+      }
-+      vdev->device_caps |= V4L2_CAP_STREAMING | V4L2_CAP_READWRITE | V4L2_CAP_IO_MC;
-+      if (video->type == V4L2_CAP_VIDEO_OUTPUT)
-+              vdev->ioctl_ops = &stf_vid_ioctl_ops_out;
-+      else
-+              vdev->ioctl_ops = is_mp ? &stf_vid_ioctl_ops_mp : &stf_vid_ioctl_ops;
-+      vdev->release = stf_video_release;
-+      vdev->v4l2_dev = v4l2_dev;
-+      vdev->queue = &video->vb2_q;
-+      vdev->lock = &video->lock;
-+      //strlcpy(vdev->name, name, sizeof(vdev->name));
-+      strscpy(vdev->name, name, sizeof(vdev->name));
-+
-+      ret = video_register_device(vdev, VFL_TYPE_VIDEO, video->id);
-+      if (ret < 0) {
-+              st_err(ST_VIDEO,
-+                      "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/v4l2_driver/stf_video.h
-@@ -0,0 +1,83 @@
-+/* SPDX-License-Identifier: GPL-2.0
-+ *
-+ * Copyright (C) 2021-2023 StarFive Technology Co., Ltd.
-+ *
-+ */
-+
-+#ifndef STF_VIDEO_H
-+#define STF_VIDEO_H
-+
-+#include <linux/mutex.h>
-+#include <media/videobuf2-v4l2.h>
-+#include <linux/videodev2.h>
-+#include <media/v4l2-dev.h>
-+#include <media/v4l2-device.h>
-+#include <media/v4l2-fh.h>
-+#include <media/v4l2-ioctl.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
-+
-+struct stfcamss_buffer {
-+      struct vb2_v4l2_buffer vb;
-+      dma_addr_t addr[3];
-+      void *vaddr_sc;         /* Use for isp sc data */
-+      struct list_head queue;
-+      int sizeimage;
-+};
-+
-+struct stfcamss_video;
-+
-+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);
-+};
-+
-+struct fract {
-+      u8 numerator;
-+      u8 denominator;
-+};
-+
-+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;
-+      struct mutex q_lock;
-+      unsigned int bpl_alignment;
-+      const struct stfcamss_format_info *formats;
-+      unsigned int nformats;
-+      unsigned int is_mp;
-+      unsigned int pm_count;
-+};
-+
-+int stf_video_register(struct stfcamss_video *video,
-+              struct v4l2_device *v4l2_dev, const char *name, int is_mp);
-+
-+void stf_video_unregister(struct stfcamss_video *video);
-+
-+#endif /* STF_VIDEO_H */
---- /dev/null
-+++ b/drivers/media/platform/starfive/v4l2_driver/stf_vin.c
-@@ -0,0 +1,1515 @@
-+// SPDX-License-Identifier: GPL-2.0
-+/*
-+ * Copyright (C) 2021-2023 StarFive Technology Co., Ltd.
-+ *
-+ */
-+
-+#include <linux/kernel.h>
-+#include <linux/module.h>
-+#include <linux/interrupt.h>
-+#include <linux/dma-mapping.h>
-+#include <linux/pm_runtime.h>
-+#include <media/v4l2-event.h>
-+
-+#include "stfcamss.h"
-+
-+#define vin_line_array(ptr_line) \
-+              ((const struct vin_line (*)[]) &(ptr_line[-(ptr_line->id)]))
-+
-+#define line_to_vin2_dev(ptr_line) \
-+              container_of(vin_line_array(ptr_line), struct stf_vin2_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
-+
-+
-+// #define VIN_TWO_BUFFER
-+
-+static const struct vin2_format vin2_formats_st7110[] = {
-+      { MEDIA_BUS_FMT_YUYV8_2X8, 16},
-+      { MEDIA_BUS_FMT_RGB565_2X8_LE, 16},
-+      { MEDIA_BUS_FMT_SRGGB8_1X8, 8},
-+      { MEDIA_BUS_FMT_SGRBG8_1X8, 8},
-+      { MEDIA_BUS_FMT_SGBRG8_1X8, 8},
-+      { MEDIA_BUS_FMT_SBGGR8_1X8, 8},
-+      { MEDIA_BUS_FMT_SRGGB10_1X10, 10},
-+      { MEDIA_BUS_FMT_SGRBG10_1X10, 10},
-+      { MEDIA_BUS_FMT_SGBRG10_1X10, 10},
-+      { MEDIA_BUS_FMT_SBGGR10_1X10, 10},
-+      { MEDIA_BUS_FMT_SRGGB12_1X12, 12},
-+      { MEDIA_BUS_FMT_SGRBG12_1X12, 12},
-+      { MEDIA_BUS_FMT_SGBRG12_1X12, 12},
-+      { MEDIA_BUS_FMT_SBGGR12_1X12, 12},
-+      { MEDIA_BUS_FMT_Y12_1X12, 8},
-+      { MEDIA_BUS_FMT_YUV8_1X24, 8},
-+      { MEDIA_BUS_FMT_AYUV8_1X32, 32},
-+};
-+
-+static const struct vin2_format isp_formats_st7110_raw[] = {
-+      { MEDIA_BUS_FMT_SBGGR12_1X12, 12},
-+      { MEDIA_BUS_FMT_SRGGB12_1X12, 12},
-+      { MEDIA_BUS_FMT_SGRBG12_1X12, 12},
-+      { MEDIA_BUS_FMT_SGBRG12_1X12, 12},
-+};
-+
-+static const struct vin2_format isp_formats_st7110_uo[] = {
-+      { MEDIA_BUS_FMT_Y12_1X12, 8},
-+};
-+
-+static const struct vin2_format isp_formats_st7110_iti[] = {
-+      { MEDIA_BUS_FMT_SRGGB10_1X10, 10},
-+      { MEDIA_BUS_FMT_SGRBG10_1X10, 10},
-+      { MEDIA_BUS_FMT_SGBRG10_1X10, 10},
-+      { MEDIA_BUS_FMT_SBGGR10_1X10, 10},
-+      { MEDIA_BUS_FMT_SRGGB12_1X12, 12},
-+      { MEDIA_BUS_FMT_SGRBG12_1X12, 12},
-+      { MEDIA_BUS_FMT_SGBRG12_1X12, 12},
-+      { MEDIA_BUS_FMT_SBGGR12_1X12, 12},
-+      { MEDIA_BUS_FMT_Y12_1X12, 8},
-+      { MEDIA_BUS_FMT_YUV8_1X24, 8},
-+};
-+
-+static const struct vin2_format_table vin2_formats_table[] = {
-+      /* VIN_LINE_WR */
-+      { vin2_formats_st7110, ARRAY_SIZE(vin2_formats_st7110) },
-+      /* VIN_LINE_ISP */
-+      { isp_formats_st7110_uo, ARRAY_SIZE(isp_formats_st7110_uo) },
-+      /* VIN_LINE_ISP_SS0 */
-+      { isp_formats_st7110_uo, ARRAY_SIZE(isp_formats_st7110_uo) },
-+      /* VIN_LINE_ISP_SS1 */
-+      { isp_formats_st7110_uo, ARRAY_SIZE(isp_formats_st7110_uo) },
-+      /* VIN_LINE_ISP_ITIW */
-+      { isp_formats_st7110_iti, ARRAY_SIZE(isp_formats_st7110_iti) },
-+      /* VIN_LINE_ISP_ITIR */
-+      { isp_formats_st7110_iti, ARRAY_SIZE(isp_formats_st7110_iti) },
-+      /* VIN_LINE_ISP_RAW */
-+      { isp_formats_st7110_raw, ARRAY_SIZE(isp_formats_st7110_raw) },
-+      /* VIN_LINE_ISP_SCD_Y */
-+      { isp_formats_st7110_raw, ARRAY_SIZE(isp_formats_st7110_raw) },
-+};
-+
-+static void vin_buffer_done(struct vin_line *line, struct vin_params *params);
-+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 *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;
-+      case VIN_LINE_ISP_SS0:
-+              name = "isp0_ss0";
-+              break;
-+      case VIN_LINE_ISP_SS1:
-+              name = "isp0_ss1";
-+              break;
-+      case VIN_LINE_ISP_ITIW:
-+              name = "isp0_itiw";
-+              break;
-+      case VIN_LINE_ISP_ITIR:
-+              name = "isp0_itir";
-+              break;
-+      case VIN_LINE_ISP_RAW:
-+              name = "isp0_raw";
-+              break;
-+      case VIN_LINE_ISP_SCD_Y:
-+              name = "isp0_scd_y";
-+              break;
-+      default:
-+              name = "unknow";
-+              break;
-+      }
-+      return name;
-+}
-+
-+static enum isp_line_id stf_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 = line % STF_ISP_LINE_MAX;
-+              if (line_id == 0)
-+                      line_id = STF_ISP_LINE_SRC_SCD_Y;
-+      } 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 = stf_vin_map_isp_line(line);
-+      else
-+              pad_id = def;
-+
-+      return pad_id;
-+}
-+
-+int stf_vin_subdev_init(struct stfcamss *stfcamss)
-+{
-+      struct stf_vin_dev *vin;
-+      struct device *dev = stfcamss->dev;
-+      struct stf_vin2_dev *vin_dev = stfcamss->vin_dev;
-+      int i, ret = 0;
-+
-+      vin_dev->stfcamss = stfcamss;
-+      vin_dev->hw_ops = &vin_ops;
-+      vin_dev->hw_ops->isr_buffer_done = vin_buffer_done;
-+      vin_dev->hw_ops->isr_change_buffer = vin_change_buffer;
-+
-+      vin = stfcamss->vin;
-+      atomic_set(&vin_dev->ref_count, 0);
-+
-+      ret = devm_request_irq(dev,
-+                      vin->irq, vin_dev->hw_ops->vin_wr_irq_handler,
-+                      0, "vin_axiwr_irq", vin_dev);
-+      if (ret) {
-+              st_err(ST_VIN, "failed to request irq\n");
-+              goto out;
-+      }
-+
-+      ret = devm_request_irq(dev,
-+                      vin->isp_irq, vin_dev->hw_ops->vin_isp_irq_handler,
-+                      0, "vin_isp_irq", vin_dev);
-+      if (ret) {
-+              st_err(ST_VIN, "failed to request isp irq\n");
-+              goto out;
-+      }
-+
-+      st_info(ST_CAMSS, "%s, %d!\n", __func__, __LINE__);
-+#ifdef ISP_USE_CSI_AND_SC_DONE_INTERRUPT
-+      ret = devm_request_irq(dev,
-+                      vin->isp_csi_irq, vin_dev->hw_ops->vin_isp_csi_irq_handler,
-+                      0, "vin_isp_csi_irq", vin_dev);
-+      if (ret) {
-+              st_err(ST_VIN, "failed to request isp raw irq\n");
-+              goto out;
-+      }
-+
-+      ret = devm_request_irq(dev,
-+                      vin->isp_scd_irq, vin_dev->hw_ops->vin_isp_scd_irq_handler,
-+                      0, "vin_isp_scd_irq", vin_dev);
-+      if (ret) {
-+              st_err(ST_VIN, "failed to request isp scd irq\n");
-+              goto out;
-+      }
-+#endif
-+
-+      ret = devm_request_irq(dev,
-+                      vin->isp_irq_csiline, vin_dev->hw_ops->vin_isp_irq_csiline_handler,
-+                      0, "vin_isp_irq_csiline", vin_dev);
-+      if (ret) {
-+              st_err(ST_VIN, "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];
-+              int is_mp;
-+
-+              is_mp = i == VIN_LINE_WR ? false : true;
-+              is_mp = false;
-+              if (stf_vin_map_isp_line(i) == STF_ISP_LINE_SRC_ITIR)
-+                      l->video_out.type = V4L2_BUF_TYPE_VIDEO_OUTPUT;
-+              else
-+                      l->video_out.type = is_mp ? V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE :
-+                              V4L2_BUF_TYPE_VIDEO_CAPTURE;
-+              l->video_out.stfcamss = stfcamss;
-+              l->id = i;
-+              l->sdev_type = VIN_DEV_TYPE;
-+              l->formats = vin2_formats_table[i].fmts;
-+              l->nformats = vin2_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 int vin_set_power(struct v4l2_subdev *sd, int on)
-+{
-+      struct vin_line *line = v4l2_get_subdevdata(sd);
-+      struct stf_vin2_dev *vin_dev = line_to_vin2_dev(line);
-+      struct stfcamss *stfcamss = vin_dev->stfcamss;
-+
-+      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) {
-+                      st_err(ST_VIN,
-+                              "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);
-+      if (on) {
-+              if (vin_dev->power_count == 0) {
-+                      pm_runtime_get_sync(stfcamss->dev);
-+                      vin_dev->hw_ops->vin_clk_enable(vin_dev);
-+                      vin_dev->hw_ops->vin_config_set(vin_dev);
-+              }
-+              vin_dev->power_count++;
-+      } else {
-+              if (vin_dev->power_count == 0) {
-+                      st_err(ST_VIN,
-+                              "vin_dev power off on power_count == 0\n");
-+                      goto exit;
-+              }
-+              if (vin_dev->power_count == 1) {
-+                      vin_dev->hw_ops->vin_clk_disable(vin_dev);
-+                      pm_runtime_put_sync(stfcamss->dev);
-+              }
-+              vin_dev->power_count--;
-+      }
-+exit:
-+
-+      mutex_unlock(&vin_dev->power_lock);
-+
-+      return 0;
-+}
-+
-+static unsigned int get_frame_skip(struct vin_line *line)
-+{
-+      unsigned int frame_skip = 0;
-+      unsigned int isp_ctrl_skip_frames = 0;
-+      struct media_entity *sensor;
-+      struct v4l2_subdev_frame_interval fi;
-+
-+      sensor = stfcamss_find_sensor(&line->subdev.entity);
-+      if (sensor) {
-+              int fps = 0;
-+              struct v4l2_subdev *subdev =
-+                                      media_entity_to_v4l2_subdev(sensor);
-+
-+              if (subdev->ops->video->g_frame_interval) {
-+                      if (!subdev->ops->video->g_frame_interval(subdev, &fi))
-+                              fps = fi.interval.denominator;
-+
-+                      if (fps > 0 && fps <= 90)
-+                              isp_ctrl_skip_frames = fps * VIN_FRAME_DROP_SEC_FOR_ISP_CTRL;
-+              }
-+              if (!fps)
-+                      st_debug(ST_VIN, "%s, Failed to get sensor fps !\n", __func__);
-+
-+              if (isp_ctrl_skip_frames <= VIN_FRAME_DROP_MIN_VAL)
-+                      isp_ctrl_skip_frames = VIN_FRAME_DROP_MIN_VAL;
-+
-+              v4l2_subdev_call(subdev, sensor, g_skip_frames, &frame_skip);
-+
-+              frame_skip += isp_ctrl_skip_frames;
-+
-+              if (frame_skip > VIN_FRAME_DROP_MAX_VAL)
-+                      frame_skip = VIN_FRAME_DROP_MAX_VAL;
-+              st_debug(ST_VIN, "%s, frame_skip %d\n", __func__, frame_skip);
-+      }
-+
-+      return frame_skip;
-+}
-+
-+static void vin_buf_l2cache_flush(struct vin_output *output)
-+{
-+      struct stfcamss_buffer *buffer = NULL;
-+
-+      if (!list_empty(&output->pending_bufs)) {
-+              list_for_each_entry(buffer, &output->pending_bufs, queue) {
-+                      sifive_l2_flush64_range(buffer->addr[0], buffer->sizeimage);
-+              }
-+      }
-+}
-+
-+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;
-+
-+      vin_buf_l2cache_flush(output);
-+
-+      output->buf[0] = vin_buf_get_pending(output);
-+#ifdef VIN_TWO_BUFFER
-+      if (line->id == VIN_LINE_WR)
-+              output->buf[1] = vin_buf_get_pending(output);
-+#endif
-+      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;
-+
-+#ifdef VIN_TWO_BUFFER
-+      if (output->buf[1] && line->id == VIN_LINE_WR)
-+              output->state = VIN_OUTPUT_CONTINUOUS;
-+#endif
-+      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 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:
-+      case VIN_LINE_ISP_SS0:
-+      case VIN_LINE_ISP_SS1:
-+      case VIN_LINE_ISP_ITIW:
-+      case VIN_LINE_ISP_ITIR:
-+      case VIN_LINE_ISP_RAW:
-+      case VIN_LINE_ISP_SCD_Y:
-+              dummy_module = STF_DUMMY_ISP;
-+              break;
-+      default:
-+              dummy_module = STF_DUMMY_VIN;
-+              break;
-+      }
-+
-+      return dummy_module;
-+}
-+
-+static int vin_alloc_dummy_buffer(struct stf_vin2_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
-+                      || i == STF_ISP_PAD_SRC_SS0
-+                      || i == STF_ISP_PAD_SRC_SS1) {
-+                      aligns = ALIGN(fmt->width, STFCAMSS_FRAME_WIDTH_ALIGN_8);
-+                      buffer->buffer_size = PAGE_ALIGN(aligns * fmt->height * 3 / 2);
-+              } else if (i == STF_ISP_PAD_SRC_ITIW
-+                      || i == STF_ISP_PAD_SRC_ITIR) {
-+                      aligns = ALIGN(fmt->width, STFCAMSS_FRAME_WIDTH_ALIGN_8);
-+                      buffer->buffer_size = PAGE_ALIGN(aligns * fmt->height * 3);
-+              } else if (i == STF_ISP_PAD_SRC_RAW) {
-+                      aligns = ALIGN(fmt->width * ISP_RAW_DATA_BITS / 8,
-+                                      STFCAMSS_FRAME_WIDTH_ALIGN_128);
-+                      buffer->buffer_size = PAGE_ALIGN(aligns * fmt->height);
-+              } else if (i == STF_ISP_PAD_SRC_SCD_Y)
-+                      buffer->buffer_size = PAGE_ALIGN(ISP_SCD_Y_BUFFER_SIZE);
-+              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
-+                              || i == STF_ISP_PAD_SRC_SS0
-+                              || i == STF_ISP_PAD_SRC_SS1
-+                              || i == STF_ISP_PAD_SRC_ITIW
-+                              || i == STF_ISP_PAD_SRC_ITIR)
-+                              buffer->paddr[1] = (dma_addr_t)(buffer->paddr[0] +
-+                                                                      aligns * fmt->height);
-+                      else if (i == STF_ISP_PAD_SRC_SCD_Y)
-+                              buffer->paddr[1] = (dma_addr_t)(buffer->paddr[0] +
-+                                                                      ISP_YHIST_BUFFER_SIZE);
-+                      else
-+                              st_debug(ST_VIN, "signal plane\n");
-+              }
-+              {
-+                      char szPadName[][32] = {
-+                              "VIN_PAD_SINK",
-+                              "ISP_PAD_SRC",
-+                              "ISP_PAD_SRC_SS0",
-+                              "ISP_PAD_SRC_SS1",
-+                              "ISP_PAD_SRC_ITIW",
-+                              "ISP_PAD_SRC_ITIR",
-+                              "ISP_PAD_SRC_RAW",
-+                              "ISP_PAD_SRC_SCD_Y",
-+                              "Unknown Pad"
-+                      };
-+
-+                      st_debug(ST_VIN, "%s: i = %d(%s) addr[0] = %llx, addr[1] = %llx, size = %u bytes\n",
-+                              __func__,
-+                              i,
-+                              szPadName[i],
-+                              buffer->paddr[0],
-+                              buffer->paddr[1],
-+                              buffer->buffer_size
-+                              );
-+              }
-+      }
-+
-+      return ret;
-+}
-+
-+static void vin_free_dummy_buffer(struct stf_vin2_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_vin2_dev *vin_dev = line_to_vin2_dev(line);
-+      int dummy_module = 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];
-+                      vin_dev->hw_ops->vin_wr_set_ping_addr(vin_dev, buffer->paddr[0]);
-+                      vin_dev->hw_ops->vin_wr_set_pong_addr(vin_dev, buffer->paddr[0]);
-+              } else {
-+                      buffer = &dummy_buffer->buffer[STF_ISP_PAD_SRC];
-+                      vin_dev->hw_ops->vin_isp_set_yuv_addr(vin_dev,
-+                              buffer->paddr[0], buffer->paddr[1]);
-+
-+                      buffer = &dummy_buffer->buffer[STF_ISP_PAD_SRC_SS0];
-+                      vin_dev->hw_ops->vin_isp_set_ss0_addr(vin_dev,
-+                              buffer->paddr[0], buffer->paddr[1]);
-+
-+                      buffer = &dummy_buffer->buffer[STF_ISP_PAD_SRC_SS1];
-+                      vin_dev->hw_ops->vin_isp_set_ss1_addr(vin_dev,
-+                              buffer->paddr[0], buffer->paddr[1]);
-+
-+                      buffer = &dummy_buffer->buffer[STF_ISP_PAD_SRC_ITIW];
-+                      vin_dev->hw_ops->vin_isp_set_itiw_addr(vin_dev,
-+                              buffer->paddr[0], buffer->paddr[1]);
-+
-+                      buffer = &dummy_buffer->buffer[STF_ISP_PAD_SRC_ITIR];
-+                      vin_dev->hw_ops->vin_isp_set_itir_addr(vin_dev,
-+                              buffer->paddr[0], buffer->paddr[1]);
-+
-+                      buffer = &dummy_buffer->buffer[STF_ISP_PAD_SRC_RAW];
-+                      vin_dev->hw_ops->vin_isp_set_raw_addr(vin_dev, buffer->paddr[0]);
-+
-+                      buffer = &dummy_buffer->buffer[STF_ISP_PAD_SRC_SCD_Y];
-+                      vin_dev->hw_ops->vin_isp_set_scd_addr(vin_dev,
-+                              buffer->paddr[0], buffer->paddr[1], AWB_TYPE);
-+              }
-+              break;
-+      case STF_ISP_PAD_SRC:
-+              buffer = &dummy_buffer->buffer[STF_ISP_PAD_SRC];
-+              vin_dev->hw_ops->vin_isp_set_yuv_addr(vin_dev,
-+                      buffer->paddr[0], buffer->paddr[1]);
-+              break;
-+      case STF_ISP_PAD_SRC_SS0:
-+              buffer = &dummy_buffer->buffer[STF_ISP_PAD_SRC_SS0];
-+              vin_dev->hw_ops->vin_isp_set_ss0_addr(vin_dev,
-+                      buffer->paddr[0], buffer->paddr[1]);
-+              break;
-+      case STF_ISP_PAD_SRC_SS1:
-+              buffer = &dummy_buffer->buffer[STF_ISP_PAD_SRC_SS1];
-+              vin_dev->hw_ops->vin_isp_set_ss1_addr(vin_dev,
-+                      buffer->paddr[0], buffer->paddr[1]);
-+              break;
-+      case STF_ISP_PAD_SRC_ITIW:
-+              buffer = &dummy_buffer->buffer[STF_ISP_PAD_SRC_ITIW];
-+              vin_dev->hw_ops->vin_isp_set_itiw_addr(vin_dev,
-+                      buffer->paddr[0], buffer->paddr[1]);
-+              break;
-+      case STF_ISP_PAD_SRC_ITIR:
-+              buffer = &dummy_buffer->buffer[STF_ISP_PAD_SRC_ITIR];
-+              vin_dev->hw_ops->vin_isp_set_itir_addr(vin_dev,
-+                      buffer->paddr[0], buffer->paddr[1]);
-+              break;
-+      case STF_ISP_PAD_SRC_RAW:
-+              buffer = &dummy_buffer->buffer[STF_ISP_PAD_SRC_RAW];
-+              vin_dev->hw_ops->vin_isp_set_raw_addr(vin_dev, buffer->paddr[0]);
-+              break;
-+      case STF_ISP_PAD_SRC_SCD_Y:
-+              buffer = &dummy_buffer->buffer[STF_ISP_PAD_SRC_SCD_Y];
-+              vin_dev->hw_ops->vin_isp_set_scd_addr(vin_dev,
-+                      buffer->paddr[0], buffer->paddr[1], AWB_TYPE);
-+              break;
-+      default:
-+              break;
-+      }
-+}
-+
-+static int vin_set_stream(struct v4l2_subdev *sd, int enable)
-+{
-+      struct vin_line *line = v4l2_get_subdevdata(sd);
-+      struct stf_vin2_dev *vin_dev = line_to_vin2_dev(line);
-+      int dummy_module = line_to_dummy_module(line);
-+      struct dummy_buffer *dummy_buffer = &vin_dev->dummy_buffer[dummy_module];
-+      struct v4l2_mbus_framefmt *fmt;
-+
-+      st_debug(ST_VIN, "%s, %d\n", __func__, __LINE__);
-+      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, get_frame_skip(line));
-+              }
-+              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);
-+      if (enable) {
-+              if (line->stream_count == 0) {
-+                      if (line->id == VIN_LINE_WR) {
-+                              vin_dev->hw_ops->vin_wr_irq_enable(vin_dev, 1);
-+                              vin_dev->hw_ops->vin_wr_stream_set(vin_dev, 1);
-+                      }
-+              }
-+              line->stream_count++;
-+      } else {
-+              if (line->stream_count == 1) {
-+                      if (line->id == VIN_LINE_WR) {
-+                              vin_dev->hw_ops->vin_wr_irq_enable(vin_dev, 0);
-+                              vin_dev->hw_ops->vin_wr_stream_set(vin_dev, 0);
-+                      }
-+              }
-+              line->stream_count--;
-+      }
-+      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 == NULL)
-+              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;
-+
-+      st_debug(ST_VIDEO, "%s, pad %d, fmt code  %x\n",
-+                      __func__, fmt->pad, fmt->format.code);
-+
-+      format = __vin_get_format(line, state, fmt->pad, fmt->which);
-+      if (format == NULL)
-+              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_vin2_dev *vin_dev = line_to_vin2_dev(line);
-+      dma_addr_t ping_addr;
-+      dma_addr_t pong_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;
-+
-+      if (output->buf[1])
-+              pong_addr = output->buf[1]->addr[0];
-+      else
-+              pong_addr = ping_addr;
-+
-+      switch (stf_vin_map_isp_line(line->id)) {
-+      case STF_ISP_LINE_SRC:
-+              vin_dev->hw_ops->vin_isp_set_yuv_addr(vin_dev,
-+                      y_addr, uv_addr);
-+              break;
-+      case STF_ISP_LINE_SRC_SS0:
-+              vin_dev->hw_ops->vin_isp_set_ss0_addr(vin_dev,
-+                      y_addr, uv_addr);
-+              break;
-+      case STF_ISP_LINE_SRC_SS1:
-+              vin_dev->hw_ops->vin_isp_set_ss1_addr(vin_dev,
-+                      y_addr, uv_addr);
-+              break;
-+      case STF_ISP_LINE_SRC_ITIW:
-+              vin_dev->hw_ops->vin_isp_set_itiw_addr(vin_dev,
-+                      y_addr, uv_addr);
-+              break;
-+      case STF_ISP_LINE_SRC_ITIR:
-+              vin_dev->hw_ops->vin_isp_set_itir_addr(vin_dev,
-+                      y_addr, uv_addr);
-+              break;
-+      case STF_ISP_LINE_SRC_RAW:
-+              vin_dev->hw_ops->vin_isp_set_raw_addr(vin_dev, y_addr);
-+              break;
-+      case STF_ISP_LINE_SRC_SCD_Y:
-+              output->frame_skip = ISP_AWB_OECF_SKIP_FRAME;
-+              vin_dev->hw_ops->vin_isp_set_scd_addr(vin_dev,
-+                      y_addr, uv_addr, AWB_TYPE);
-+              break;
-+      default:
-+              if (line->id == VIN_LINE_WR) {
-+                      vin_dev->hw_ops->vin_wr_set_ping_addr(vin_dev, ping_addr);
-+#ifdef VIN_TWO_BUFFER
-+                      vin_dev->hw_ops->vin_wr_set_pong_addr(vin_dev, pong_addr);
-+#else
-+                      vin_dev->hw_ops->vin_wr_set_pong_addr(vin_dev, ping_addr);
-+#endif
-+              }
-+              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;
-+}
-+
-+#ifdef UNUSED_CODE
-+static void vin_output_checkpending(struct vin_line *line)
-+{
-+      struct vin_output *output = &line->output;
-+
-+      if (output->state == VIN_OUTPUT_STOPPING) {
-+              /* Release last buffer when hw is idle */
-+              if (output->last_buffer) {
-+                      // vb2_buffer_done(&output->last_buffer->vb.vb2_buf,
-+                      //              VB2_BUF_STATE_DONE);
-+                      vin_buf_add_pending(output, output->last_buffer);
-+                      output->last_buffer = NULL;
-+              }
-+              output->state = VIN_OUTPUT_IDLE;
-+
-+              /* Buffers received in stopping state are queued in */
-+              /* dma pending queue, start next capture here */
-+              output->buf[0] = vin_buf_get_pending(output);
-+#ifdef VIN_TWO_BUFFER
-+              if (line->id == VIN_LINE_WR)
-+                      output->buf[1] = vin_buf_get_pending(output);
-+#endif
-+
-+              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;
-+
-+#ifdef VIN_TWO_BUFFER
-+              if (output->buf[1] && line->id == VIN_LINE_WR)
-+                      output->state = VIN_OUTPUT_CONTINUOUS;
-+#endif
-+              vin_output_init_addrs(line);
-+      }
-+}
-+#endif
-+
-+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:
-+              st_err_ratelimited(ST_VIN,
-+                              "Last buff in wrong state! %d\n",
-+                              output->state);
-+              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:
-+#ifdef VIN_TWO_BUFFER
-+              if (line->id == VIN_LINE_WR)
-+                      st_err_ratelimited(ST_VIN,
-+                              "Next buf in wrong state! %d\n",
-+                              output->state);
-+#endif
-+              break;
-+      }
-+}
-+
-+static void vin_buf_update_on_new(struct vin_line *line,
-+                              struct vin_output *output,
-+                              struct stfcamss_buffer *new_buf)
-+{
-+#ifdef VIN_TWO_BUFFER
-+      struct stf_vin2_dev *vin_dev = line_to_vin2_dev(line);
-+      int inactive_idx;
-+#endif
-+
-+      switch (output->state) {
-+      case VIN_OUTPUT_SINGLE:
-+#ifdef VIN_TWO_BUFFER
-+              int inactive_idx = !output->active_buf;
-+
-+              if (!output->buf[inactive_idx] && line->id == VIN_LINE_WR) {
-+                      output->buf[inactive_idx] = new_buf;
-+                      if (inactive_idx)
-+                              vin_dev->hw_ops->vin_wr_set_pong_addr(vin_dev,
-+                                              output->buf[1]->addr[0]);
-+                      else
-+                              vin_dev->hw_ops->vin_wr_set_ping_addr(vin_dev,
-+                                              output->buf[0]->addr[0]);
-+                      output->state = VIN_OUTPUT_CONTINUOUS;
-+
-+              } else {
-+                      vin_buf_add_pending(output, new_buf);
-+                      if (line->id == VIN_LINE_WR)
-+                              st_warn(ST_VIN, "Inactive buffer is busy\n");
-+              }
-+#else
-+              vin_buf_add_pending(output, new_buf);
-+#endif
-+              break;
-+      case VIN_OUTPUT_IDLE:
-+              st_warn(ST_VIN, "Output idle buffer set!\n");
-+              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);
-+                      st_warn(ST_VIN, "Output idle with buffer set!\n");
-+              }
-+              break;
-+      case VIN_OUTPUT_STOPPING:
-+              if (output->last_buffer) {
-+                      output->buf[output->active_buf] = output->last_buffer;
-+                      output->last_buffer = NULL;
-+              } else
-+                      st_err(ST_VIN,  "stop state lost lastbuffer!\n");
-+              output->state = VIN_OUTPUT_SINGLE;
-+              // vin_output_checkpending(line);
-+              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 vin_params *params)
-+{
-+      struct stfcamss_buffer *ready_buf;
-+      struct vin_output *output = &line->output;
-+      unsigned long flags;
-+      u64 ts = ktime_get_ns();
-+      struct v4l2_event event = {
-+              .type = V4L2_EVENT_FRAME_SYNC,
-+      };
-+
-+      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))) {
-+              if (line->id >= VIN_LINE_ISP && line->id <= VIN_LINE_ISP_SS1) {
-+                      event.u.frame_sync.frame_sequence = output->sequence;
-+                      v4l2_event_queue(line->subdev.devnode, &event);
-+              }
-+
-+              ready_buf->vb.vb2_buf.timestamp = ts;
-+              ready_buf->vb.sequence = output->sequence++;
-+
-+              /* The stf_isp_ctrl currently buffered with mmap,
-+               * which will not update cache by default.
-+               * Flush L2 cache to make sure data is updated.
-+               */
-+              if (ready_buf->vb.vb2_buf.memory == VB2_MEMORY_MMAP)
-+                      sifive_l2_flush64_range(ready_buf->addr[0], ready_buf->sizeimage);
-+
-+              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_vin2_dev *vin_dev = line_to_vin2_dev(line);
-+      dma_addr_t *new_addr;
-+      unsigned long flags;
-+      u32 active_index;
-+      int scd_type;
-+
-+      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) {
-+              st_err_ratelimited(ST_VIN,
-+                                      "Missing ready buf %d %d!\n",
-+                                      active_index, output->state);
-+              active_index = !active_index;
-+              ready_buf = output->buf[active_index];
-+              if (!ready_buf) {
-+                      st_err_ratelimited(ST_VIN,
-+                                      "Missing ready buf 2 %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 (stf_vin_map_isp_line(line->id)) {
-+              case STF_ISP_LINE_SRC:
-+                      vin_dev->hw_ops->vin_isp_set_yuv_addr(vin_dev,
-+                              new_addr[0], new_addr[1]);
-+                      break;
-+              case STF_ISP_LINE_SRC_SS0:
-+                      vin_dev->hw_ops->vin_isp_set_ss0_addr(vin_dev,
-+                              new_addr[0], new_addr[1]);
-+                      break;
-+              case STF_ISP_LINE_SRC_SS1:
-+                      vin_dev->hw_ops->vin_isp_set_ss1_addr(vin_dev,
-+                              new_addr[0], new_addr[1]);
-+                      break;
-+              case STF_ISP_LINE_SRC_ITIW:
-+                      vin_dev->hw_ops->vin_isp_set_itiw_addr(vin_dev,
-+                              new_addr[0], new_addr[1]);
-+                      break;
-+              case STF_ISP_LINE_SRC_ITIR:
-+                      vin_dev->hw_ops->vin_isp_set_itir_addr(vin_dev,
-+                              new_addr[0], new_addr[1]);
-+                      break;
-+              case STF_ISP_LINE_SRC_RAW:
-+                      vin_dev->hw_ops->vin_isp_set_raw_addr(vin_dev, new_addr[0]);
-+                      break;
-+              case STF_ISP_LINE_SRC_SCD_Y:
-+                      scd_type = vin_dev->hw_ops->vin_isp_get_scd_type(vin_dev);
-+                      ready_buf->vb.flags &= ~(V4L2_BUF_FLAG_PFRAME | V4L2_BUF_FLAG_BFRAME);
-+                      if (scd_type == AWB_TYPE)
-+                              ready_buf->vb.flags |= V4L2_BUF_FLAG_PFRAME;
-+                      else
-+                              ready_buf->vb.flags |= V4L2_BUF_FLAG_BFRAME;
-+                      if (!output->frame_skip) {
-+                              output->frame_skip = ISP_AWB_OECF_SKIP_FRAME;
-+                              scd_type = scd_type == AWB_TYPE ? OECF_TYPE : AWB_TYPE;
-+                      } else {
-+                              output->frame_skip--;
-+                              scd_type = scd_type == AWB_TYPE ? AWB_TYPE : OECF_TYPE;
-+                      }
-+                      vin_dev->hw_ops->vin_isp_set_scd_addr(vin_dev,
-+                              new_addr[0], new_addr[1], scd_type);
-+                      break;
-+              default:
-+                      if (line->id == VIN_LINE_WR) {
-+#ifdef VIN_TWO_BUFFER
-+                              if (active_index)
-+                                      vin_dev->hw_ops->vin_wr_set_pong_addr(vin_dev,
-+                                                      new_addr[0]);
-+                              else
-+                                      vin_dev->hw_ops->vin_wr_set_ping_addr(vin_dev,
-+                                                      new_addr[0]);
-+#else
-+                              vin_dev->hw_ops->vin_wr_set_ping_addr(vin_dev,
-+                                                      new_addr[0]);
-+                              vin_dev->hw_ops->vin_wr_set_pong_addr(vin_dev,
-+                                                      new_addr[0]);
-+#endif
-+                      }
-+                      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] = 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 int stf_vin_subscribe_event(struct v4l2_subdev *sd,
-+                                 struct v4l2_fh *fh,
-+                                 struct v4l2_event_subscription *sub)
-+{
-+      switch (sub->type) {
-+      case V4L2_EVENT_FRAME_SYNC:
-+              return v4l2_event_subscribe(fh, sub, 0, NULL);
-+      default:
-+              st_debug(ST_VIN, "unsupport subscribe_event\n");
-+              return -EINVAL;
-+      }
-+}
-+
-+static const struct v4l2_subdev_core_ops vin_core_ops = {
-+      .s_power = vin_set_power,
-+      .subscribe_event = stf_vin_subscribe_event,
-+      .unsubscribe_event = v4l2_event_subdev_unsubscribe,
-+};
-+
-+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_vin2_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 = get_line_subdevname(i);
-+              int is_mp;
-+
-+#ifdef        STF_CAMSS_SKIP_ITI
-+              if ((stf_vin_map_isp_line(i) == STF_ISP_LINE_SRC_ITIW) ||
-+                      (stf_vin_map_isp_line(i) == STF_ISP_LINE_SRC_ITIR))
-+                      continue;
-+#endif
-+              is_mp = (stf_vin_map_isp_line(i) == STF_ISP_LINE_SRC) ? true : false;
-+              is_mp = false;
-+              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 | V4L2_SUBDEV_FL_HAS_EVENTS;
-+              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) {
-+                      st_err(ST_VIN, "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) {
-+                      st_err(ST_VIN, "Failed to init media entity: %d\n", ret);
-+                      goto err_init;
-+              }
-+
-+              ret = v4l2_device_register_subdev(v4l2_dev, sd);
-+              if (ret < 0) {
-+                      st_err(ST_VIN, "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, is_mp);
-+              if (ret < 0) {
-+                      st_err(ST_VIN, "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) {
-+                      st_err(ST_VIN, "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_vin2_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/v4l2_driver/stf_vin.h
-@@ -0,0 +1,182 @@
-+/* SPDX-License-Identifier: GPL-2.0
-+ *
-+ * Copyright (C) 2021-2023 StarFive Technology Co., Ltd.
-+ *
-+ */
-+
-+#ifndef STF_VIN_H
-+#define STF_VIN_H
-+
-+#include <media/v4l2-device.h>
-+#include <media/v4l2-subdev.h>
-+#include <linux/spinlock_types.h>
-+#include <video/stf-vin.h>
-+#include <linux/platform_device.h>
-+
-+#include "stf_video.h"
-+
-+#define STF_VIN_NAME "stf_vin"
-+
-+#define STF_VIN_PAD_SINK   0
-+#define STF_VIN_PAD_SRC    1
-+#define STF_VIN_PADS_NUM   2
-+
-+struct vin2_format {
-+      u32 code;
-+      u8 bpp;
-+};
-+
-+struct vin2_format_table {
-+      const struct vin2_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 include all isp controller lines,
-+ * and one vin_wr output line.
-+ */
-+enum vin_line_id {
-+      VIN_LINE_NONE = -1,
-+      VIN_LINE_WR = 0,
-+      VIN_LINE_ISP = 1,
-+      VIN_LINE_ISP_SS0 = 2,
-+      VIN_LINE_ISP_SS1 = 3,
-+      VIN_LINE_ISP_ITIW = 4,
-+      VIN_LINE_ISP_ITIR = 5,
-+      VIN_LINE_ISP_RAW = 6,
-+      VIN_LINE_ISP_SCD_Y = 7,
-+      VIN_LINE_MAX = 8,
-+};
-+
-+enum subdev_type;
-+
-+struct vin_line {
-+      enum 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;
-+      int stream_count;
-+      struct mutex power_lock;
-+      int power_count;
-+      struct vin_output output;
-+      spinlock_t output_lock;
-+      const struct vin2_format *formats;
-+      unsigned int nformats;
-+#ifdef CONFIG_PM_SLEEP
-+      int pm_stream_count;
-+      int pm_power_count;
-+#endif
-+};
-+
-+struct stf_vin2_dev;
-+
-+struct vin_hw_ops {
-+      int (*vin_clk_enable)(struct stf_vin2_dev *vin_dev);
-+      int (*vin_clk_disable)(struct stf_vin2_dev *vin_dev);
-+      int (*vin_config_set)(struct stf_vin2_dev *vin_dev);
-+      int (*vin_wr_stream_set)(struct stf_vin2_dev *vin_dev, int on);
-+      void (*vin_wr_irq_enable)(struct stf_vin2_dev *vin_dev, int enable);
-+      void (*vin_power_on)(struct stf_vin2_dev *vin_dev, int on);
-+      void (*wr_rd_set_addr)(struct stf_vin2_dev *vin_dev,
-+                      dma_addr_t wr_addr, dma_addr_t rd_addr);
-+      void (*vin_wr_set_ping_addr)(struct stf_vin2_dev *vin_dev,
-+                      dma_addr_t addr);
-+      void (*vin_wr_set_pong_addr)(struct stf_vin2_dev *vin_dev,
-+                      dma_addr_t addr);
-+      void (*vin_wr_get_ping_pong_status)(struct stf_vin2_dev *vin_dev);
-+      void (*vin_isp_set_yuv_addr)(struct stf_vin2_dev *vin_dev,
-+                      dma_addr_t y_addr, dma_addr_t uv_addr);
-+      void (*vin_isp_set_raw_addr)(struct stf_vin2_dev *vin_dev,
-+                      dma_addr_t raw_addr);
-+      void (*vin_isp_set_ss0_addr)(struct stf_vin2_dev *vin_dev,
-+                      dma_addr_t y_addr, dma_addr_t uv_addr);
-+      void (*vin_isp_set_ss1_addr)(struct stf_vin2_dev *vin_dev,
-+                      dma_addr_t y_addr, dma_addr_t uv_addr);
-+      void (*vin_isp_set_itiw_addr)(struct stf_vin2_dev *vin_dev,
-+                      dma_addr_t y_addr, dma_addr_t uv_addr);
-+      void (*vin_isp_set_itir_addr)(struct stf_vin2_dev *vin_dev,
-+                      dma_addr_t y_addr, dma_addr_t uv_addr);
-+      void (*vin_isp_set_scd_addr)(struct stf_vin2_dev *vin_dev,
-+                      dma_addr_t yhist_addr,
-+                      dma_addr_t scd_addr, int scd_type);
-+      int (*vin_isp_get_scd_type)(struct stf_vin2_dev *vin_dev);
-+      irqreturn_t (*vin_wr_irq_handler)(int irq, void *priv);
-+      irqreturn_t (*vin_isp_irq_handler)(int irq, void *priv);
-+      irqreturn_t (*vin_isp_csi_irq_handler)(int irq, void *priv);
-+      irqreturn_t (*vin_isp_scd_irq_handler)(int irq, void *priv);
-+      irqreturn_t (*vin_isp_irq_csiline_handler)(int irq, void *priv);
-+      void (*isr_buffer_done)(struct vin_line *line,
-+                      struct vin_params *params);
-+      void (*isr_change_buffer)(struct vin_line *line);
-+};
-+
-+#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,
-+};
-+
-+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;
-+      int stream_count;
-+      atomic_t frame_skip;
-+};
-+
-+struct stf_vin2_dev {
-+      struct stfcamss *stfcamss;
-+      struct vin_line line[VIN_LINE_MAX];
-+      struct dummy_buffer dummy_buffer[STF_DUMMY_MODULE_NUMS];
-+      struct vin_hw_ops *hw_ops;
-+      atomic_t ref_count;
-+      struct mutex power_lock;
-+      int power_count;
-+};
-+
-+extern void sifive_l2_flush64_range(unsigned long start, unsigned long len);
-+extern int stf_vin_subdev_init(struct stfcamss *stfcamss);
-+extern int stf_vin_register(struct stf_vin2_dev *vin_dev,
-+              struct v4l2_device *v4l2_dev);
-+extern int stf_vin_unregister(struct stf_vin2_dev *vin_dev);
-+
-+extern struct vin_hw_ops vin_ops;
-+extern void dump_vin_reg(void *__iomem regbase);
-+extern 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/v4l2_driver/stf_vin_hw_ops.c
-@@ -0,0 +1,433 @@
-+// SPDX-License-Identifier: GPL-2.0
-+/*
-+ * Copyright (C) 2021-2023 StarFive Technology Co., Ltd.
-+ *
-+ */
-+
-+#include "stfcamss.h"
-+#include <linux/of_graph.h>
-+#include <media/v4l2-async.h>
-+#include <media/v4l2-fwnode.h>
-+#include <media/v4l2-subdev.h>
-+
-+static void vin_intr_clear(void __iomem *sysctrl_base)
-+{
-+      reg_set_bit(sysctrl_base, SYSCONSAIF_SYSCFG_28,
-+              U0_VIN_CNFG_AXIWR0_INTR_CLEAN,
-+              0x1);
-+      reg_set_bit(sysctrl_base, SYSCONSAIF_SYSCFG_28,
-+              U0_VIN_CNFG_AXIWR0_INTR_CLEAN,
-+              0x0);
-+}
-+
-+static irqreturn_t stf_vin_wr_irq_handler(int irq, void *priv)
-+{
-+      static struct vin_params params;
-+      struct stf_vin2_dev *vin_dev = priv;
-+      struct stf_vin_dev *vin = vin_dev->stfcamss->vin;
-+      struct dummy_buffer *dummy_buffer =
-+                      &vin_dev->dummy_buffer[STF_DUMMY_VIN];
-+
-+      if (atomic_dec_if_positive(&dummy_buffer->frame_skip) < 0) {
-+              vin_dev->hw_ops->isr_change_buffer(&vin_dev->line[VIN_LINE_WR]);
-+              vin_dev->hw_ops->isr_buffer_done(&vin_dev->line[VIN_LINE_WR], &params);
-+      }
-+
-+      vin_intr_clear(vin->sysctrl_base);
-+
-+      return IRQ_HANDLED;
-+}
-+
-+static  void __iomem *stf_vin_get_ispbase(struct stf_vin_dev *vin)
-+{
-+      void __iomem *base = vin->isp_base;
-+
-+      return base;
-+}
-+
-+static irqreturn_t stf_vin_isp_irq_handler(int irq, void *priv)
-+{
-+      static struct vin_params params;
-+      struct stf_vin2_dev *vin_dev = priv;
-+      struct stf_vin_dev *vin = vin_dev->stfcamss->vin;
-+      void __iomem *ispbase;
-+      u32 int_status, value;
-+
-+      ispbase = stf_vin_get_ispbase(vin);
-+
-+      int_status = reg_read(ispbase, ISP_REG_ISP_CTRL_0);
-+
-+      if (int_status & BIT(24)) {
-+              if ((int_status & BIT(11)))
-+                      vin_dev->hw_ops->isr_buffer_done(
-+                              &vin_dev->line[VIN_LINE_ISP_SS0], &params);
-+
-+              if ((int_status & BIT(12)))
-+                      vin_dev->hw_ops->isr_buffer_done(
-+                              &vin_dev->line[VIN_LINE_ISP_SS1], &params);
-+
-+              if ((int_status & BIT(20)))
-+                      vin_dev->hw_ops->isr_buffer_done(
-+                              &vin_dev->line[VIN_LINE_ISP], &params);
-+
-+              value = reg_read(ispbase, ISP_REG_ITIDPSR);
-+              if ((value & BIT(17)))
-+                      vin_dev->hw_ops->isr_buffer_done(
-+                              &vin_dev->line[VIN_LINE_ISP_ITIW], &params);
-+              if ((value & BIT(16)))
-+                      vin_dev->hw_ops->isr_buffer_done(
-+                              &vin_dev->line[VIN_LINE_ISP_ITIR], &params);
-+
-+#ifndef ISP_USE_CSI_AND_SC_DONE_INTERRUPT
-+              if (int_status & BIT(25))
-+                      vin_dev->hw_ops->isr_buffer_done(
-+                              &vin_dev->line[VIN_LINE_ISP_RAW], &params);
-+
-+              if (int_status & BIT(26))
-+                      vin_dev->hw_ops->isr_buffer_done(
-+                              &vin_dev->line[VIN_LINE_ISP_SCD_Y], &params);
-+
-+              /* clear interrupt */
-+              reg_write(ispbase, ISP_REG_ISP_CTRL_0, (int_status & ~EN_INT_ALL)
-+                              | EN_INT_ISP_DONE | EN_INT_CSI_DONE | EN_INT_SC_DONE);
-+#else
-+              /* clear interrupt */
-+              reg_write(ispbase, ISP_REG_ISP_CTRL_0,
-+                      (int_status & ~EN_INT_ALL) | EN_INT_ISP_DONE);
-+#endif
-+      } else
-+              st_debug(ST_VIN, "%s, Unknown interrupt!!!\n", __func__);
-+
-+      return IRQ_HANDLED;
-+}
-+
-+static irqreturn_t stf_vin_isp_csi_irq_handler(int irq, void *priv)
-+{
-+      static struct vin_params params;
-+      struct stf_vin2_dev *vin_dev = priv;
-+      struct stf_vin_dev *vin = vin_dev->stfcamss->vin;
-+      void __iomem *ispbase;
-+      u32 int_status;
-+
-+      ispbase = stf_vin_get_ispbase(vin);
-+
-+      int_status = reg_read(ispbase, ISP_REG_ISP_CTRL_0);
-+
-+      if (int_status & BIT(25)) {
-+              vin_dev->hw_ops->isr_buffer_done(
-+                      &vin_dev->line[VIN_LINE_ISP_RAW], &params);
-+
-+              /* clear interrupt */
-+              reg_write(ispbase, ISP_REG_ISP_CTRL_0,
-+                      (int_status & ~EN_INT_ALL) | EN_INT_CSI_DONE);
-+      } else
-+              st_debug(ST_VIN, "%s, Unknown interrupt!!!\n", __func__);
-+
-+      return IRQ_HANDLED;
-+}
-+
-+static irqreturn_t stf_vin_isp_scd_irq_handler(int irq, void *priv)
-+{
-+      static struct vin_params params;
-+      struct stf_vin2_dev *vin_dev = priv;
-+      struct stf_vin_dev *vin = vin_dev->stfcamss->vin;
-+      void __iomem *ispbase;
-+      u32 int_status;
-+
-+      ispbase = stf_vin_get_ispbase(vin);
-+
-+      int_status = reg_read(ispbase, ISP_REG_ISP_CTRL_0);
-+
-+      if (int_status & BIT(26)) {
-+              vin_dev->hw_ops->isr_buffer_done(
-+                      &vin_dev->line[VIN_LINE_ISP_SCD_Y], &params);
-+
-+              /* clear interrupt */
-+              reg_write(ispbase, ISP_REG_ISP_CTRL_0, (int_status & ~EN_INT_ALL) | EN_INT_SC_DONE);
-+      } else
-+              st_debug(ST_VIN, "%s, Unknown interrupt!!!\n", __func__);
-+
-+      return IRQ_HANDLED;
-+}
-+
-+static irqreturn_t stf_vin_isp_irq_csiline_handler(int irq, void *priv)
-+{
-+      struct stf_vin2_dev *vin_dev = priv;
-+      struct stf_vin_dev *vin = vin_dev->stfcamss->vin;
-+      struct stf_isp_dev *isp_dev;
-+      void __iomem *ispbase;
-+      u32 int_status, value;
-+
-+      ispbase = stf_vin_get_ispbase(vin);
-+
-+      isp_dev = vin_dev->stfcamss->isp_dev;
-+
-+      int_status = reg_read(ispbase, ISP_REG_ISP_CTRL_0);
-+      if (int_status & BIT(27)) {
-+              struct dummy_buffer *dummy_buffer =
-+                      &vin_dev->dummy_buffer[STF_DUMMY_ISP];
-+
-+              if (!atomic_read(&isp_dev->shadow_count)) {
-+                      if (atomic_dec_if_positive(&dummy_buffer->frame_skip) < 0) {
-+                              if ((int_status & BIT(11)))
-+                                      vin_dev->hw_ops->isr_change_buffer(
-+                                              &vin_dev->line[VIN_LINE_ISP_SS0]);
-+                              if ((int_status & BIT(12)))
-+                                      vin_dev->hw_ops->isr_change_buffer(
-+                                              &vin_dev->line[VIN_LINE_ISP_SS1]);
-+                              if ((int_status & BIT(20)))
-+                                      vin_dev->hw_ops->isr_change_buffer(
-+                                              &vin_dev->line[VIN_LINE_ISP]);
-+
-+                              value = reg_read(ispbase, ISP_REG_ITIDPSR);
-+                              if ((value & BIT(17)))
-+                                      vin_dev->hw_ops->isr_change_buffer(
-+                                              &vin_dev->line[VIN_LINE_ISP_ITIW]);
-+                              if ((value & BIT(16)))
-+                                      vin_dev->hw_ops->isr_change_buffer(
-+                                              &vin_dev->line[VIN_LINE_ISP_ITIR]);
-+
-+                              value = reg_read(ispbase, ISP_REG_CSI_MODULE_CFG);
-+                              if ((value & BIT(19)))
-+                                      vin_dev->hw_ops->isr_change_buffer(
-+                                              &vin_dev->line[VIN_LINE_ISP_RAW]);
-+                              if ((value & BIT(17)))
-+                                      vin_dev->hw_ops->isr_change_buffer(
-+                                              &vin_dev->line[VIN_LINE_ISP_SCD_Y]);
-+                      }
-+
-+                      // shadow update
-+                      reg_set_bit(ispbase, ISP_REG_CSIINTS_ADDR, 0x30000, 0x30000);
-+                      reg_set_bit(ispbase, ISP_REG_IESHD_ADDR, BIT(1) | BIT(0), 0x3);
-+              } else {
-+                      st_warn(ST_VIN, "isp shadow_lock locked. skip this frame\n");
-+              }
-+
-+              /* clear interrupt */
-+              reg_write(ispbase, ISP_REG_ISP_CTRL_0,
-+                      (int_status & ~EN_INT_ALL) | EN_INT_LINE_INT);
-+      } else
-+              st_debug(ST_VIN, "%s, Unknown interrupt!!!\n", __func__);
-+
-+      return IRQ_HANDLED;
-+}
-+
-+static int stf_vin_clk_enable(struct stf_vin2_dev *vin_dev)
-+{
-+      struct stfcamss *stfcamss = vin_dev->stfcamss;
-+
-+      clk_prepare_enable(stfcamss->sys_clk[STFCLK_PCLK].clk);
-+      clk_set_rate(stfcamss->sys_clk[STFCLK_APB_FUNC].clk, 49500000);
-+      clk_set_rate(stfcamss->sys_clk[STFCLK_SYS_CLK].clk, 297000000);
-+
-+      reset_control_deassert(stfcamss->sys_rst[STFRST_PCLK].rstc);
-+      reset_control_deassert(stfcamss->sys_rst[STFRST_SYS_CLK].rstc);
-+
-+      return 0;
-+}
-+
-+
-+static int stf_vin_clk_disable(struct stf_vin2_dev *vin_dev)
-+{
-+      struct stfcamss *stfcamss = vin_dev->stfcamss;
-+
-+      reset_control_assert(stfcamss->sys_rst[STFRST_PCLK].rstc);
-+      reset_control_assert(stfcamss->sys_rst[STFRST_SYS_CLK].rstc);
-+
-+      clk_disable_unprepare(stfcamss->sys_clk[STFCLK_PCLK].clk);
-+
-+      return 0;
-+}
-+
-+static int stf_vin_config_set(struct stf_vin2_dev *vin_dev)
-+{
-+      return 0;
-+}
-+
-+static int stf_vin_wr_stream_set(struct stf_vin2_dev *vin_dev, int on)
-+{
-+      struct stf_vin_dev *vin = vin_dev->stfcamss->vin;
-+
-+      //make the axiwr alway on
-+      if (on)
-+              reg_set(vin->sysctrl_base, SYSCONSAIF_SYSCFG_20, U0_VIN_CNFG_AXIWR0_EN);
-+
-+      return 0;
-+}
-+
-+static void stf_vin_wr_irq_enable(struct stf_vin2_dev *vin_dev,
-+              int enable)
-+{
-+      struct stf_vin_dev *vin = vin_dev->stfcamss->vin;
-+      unsigned int value = 0;
-+
-+      if (enable) {
-+              value = ~(0x1 << 1);
-+              reg_set_bit(vin->sysctrl_base, SYSCONSAIF_SYSCFG_28,
-+                      U0_VIN_CNFG_AXIWR0_MASK,
-+                      value);
-+      } else {
-+              /* clear vin interrupt */
-+              value = 0x1 << 1;
-+              reg_set_bit(vin->sysctrl_base, SYSCONSAIF_SYSCFG_28,
-+                      U0_VIN_CNFG_AXIWR0_INTR_CLEAN,
-+                      0x1);
-+              reg_set_bit(vin->sysctrl_base, SYSCONSAIF_SYSCFG_28,
-+                      U0_VIN_CNFG_AXIWR0_INTR_CLEAN,
-+                      0x0);
-+              reg_set_bit(vin->sysctrl_base, SYSCONSAIF_SYSCFG_28,
-+                      U0_VIN_CNFG_AXIWR0_MASK,
-+                      value);
-+      }
-+}
-+
-+static void stf_vin_wr_rd_set_addr(struct stf_vin2_dev *vin_dev,
-+              dma_addr_t wr_addr, dma_addr_t rd_addr)
-+{
-+#ifdef UNUSED_CODE
-+      struct stf_vin_dev *vin = vin_dev->stfcamss->vin;
-+
-+      /* set the start address*/
-+      reg_write(vin->sysctrl_base,
-+                      SYSCTRL_VIN_WR_START_ADDR, (long)wr_addr);
-+      reg_write(vin->sysctrl_base,
-+                      SYSCTRL_VIN_RD_END_ADDR, (long)rd_addr);
-+#endif
-+}
-+
-+void stf_vin_wr_set_ping_addr(struct stf_vin2_dev *vin_dev,
-+              dma_addr_t addr)
-+{
-+      struct stf_vin_dev *vin = vin_dev->stfcamss->vin;
-+
-+      /* set the start address */
-+      reg_write(vin->sysctrl_base,  SYSCONSAIF_SYSCFG_24, (long)addr);
-+}
-+
-+void stf_vin_wr_set_pong_addr(struct stf_vin2_dev *vin_dev, dma_addr_t addr)
-+{
-+      struct stf_vin_dev *vin = vin_dev->stfcamss->vin;
-+
-+      /* set the start address */
-+      reg_write(vin->sysctrl_base, SYSCONSAIF_SYSCFG_32, (long)addr);
-+}
-+
-+void stf_vin_isp_set_yuv_addr(struct stf_vin2_dev *vin_dev,
-+                              dma_addr_t y_addr, dma_addr_t uv_addr)
-+{
-+
-+      struct stf_vin_dev *vin = vin_dev->stfcamss->vin;
-+      void __iomem *ispbase = stf_vin_get_ispbase(vin);
-+
-+      reg_write(ispbase, ISP_REG_Y_PLANE_START_ADDR, y_addr);
-+      reg_write(ispbase, ISP_REG_UV_PLANE_START_ADDR, uv_addr);
-+      // reg_set_bit(ispbase, ISP_REG_ISP_CTRL_0, BIT(0), 1);
-+}
-+
-+void stf_vin_isp_set_raw_addr(struct stf_vin2_dev *vin_dev,
-+                              dma_addr_t raw_addr)
-+{
-+      struct stf_vin_dev *vin = vin_dev->stfcamss->vin;
-+      void __iomem *ispbase = stf_vin_get_ispbase(vin);
-+
-+      reg_write(ispbase, ISP_REG_DUMP_CFG_0, raw_addr);
-+}
-+
-+void stf_vin_isp_set_ss0_addr(struct stf_vin2_dev *vin_dev,
-+                              dma_addr_t y_addr, dma_addr_t uv_addr)
-+{
-+      struct stf_vin_dev *vin = vin_dev->stfcamss->vin;
-+      void __iomem *ispbase = stf_vin_get_ispbase(vin);
-+
-+      reg_write(ispbase, ISP_REG_SS0AY, y_addr);
-+      reg_write(ispbase, ISP_REG_SS0AUV, uv_addr);
-+}
-+
-+void stf_vin_isp_set_ss1_addr(struct stf_vin2_dev *vin_dev,
-+                              dma_addr_t y_addr, dma_addr_t uv_addr)
-+{
-+      struct stf_vin_dev *vin = vin_dev->stfcamss->vin;
-+      void __iomem *ispbase = stf_vin_get_ispbase(vin);
-+
-+      reg_write(ispbase, ISP_REG_SS1AY, y_addr);
-+      reg_write(ispbase, ISP_REG_SS1AUV, uv_addr);
-+}
-+
-+void stf_vin_isp_set_itiw_addr(struct stf_vin2_dev *vin_dev,
-+                              dma_addr_t y_addr, dma_addr_t uv_addr)
-+{
-+      struct stf_vin_dev *vin = vin_dev->stfcamss->vin;
-+      void __iomem *ispbase = stf_vin_get_ispbase(vin);
-+
-+      reg_write(ispbase, ISP_REG_ITIDWYSAR, y_addr);
-+      reg_write(ispbase, ISP_REG_ITIDWUSAR, uv_addr);
-+}
-+
-+void stf_vin_isp_set_itir_addr(struct stf_vin2_dev *vin_dev,
-+                              dma_addr_t y_addr, dma_addr_t uv_addr)
-+{
-+      struct stf_vin_dev *vin = vin_dev->stfcamss->vin;
-+      void __iomem *ispbase = stf_vin_get_ispbase(vin);
-+
-+      reg_write(ispbase, ISP_REG_ITIDRYSAR, y_addr);
-+      reg_write(ispbase, ISP_REG_ITIDRUSAR, uv_addr);
-+}
-+
-+int stf_vin_isp_get_scd_type(struct stf_vin2_dev *vin_dev)
-+{
-+      struct stf_vin_dev *vin = vin_dev->stfcamss->vin;
-+      void __iomem *ispbase = stf_vin_get_ispbase(vin);
-+
-+      return (reg_read(ispbase, ISP_REG_SC_CFG_1) & (0x3 << 30)) >> 30;
-+}
-+
-+void stf_vin_isp_set_scd_addr(struct stf_vin2_dev *vin_dev,
-+                              dma_addr_t yhist_addr, dma_addr_t scd_addr, int scd_type)
-+{
-+      struct stf_vin_dev *vin = vin_dev->stfcamss->vin;
-+      void __iomem *ispbase = stf_vin_get_ispbase(vin);
-+
-+      reg_set_bit(ispbase, ISP_REG_SC_CFG_1, 0x3 << 30, scd_type << 30);
-+      reg_write(ispbase, ISP_REG_SCD_CFG_0, scd_addr);
-+      reg_write(ispbase, ISP_REG_YHIST_CFG_4, yhist_addr);
-+}
-+
-+void dump_vin_reg(void *__iomem regbase)
-+{
-+      st_debug(ST_VIN, "DUMP VIN register:\n");
-+      print_reg(ST_VIN, regbase, 0x00);
-+      print_reg(ST_VIN, regbase, 0x04);
-+      print_reg(ST_VIN, regbase, 0x08);
-+      print_reg(ST_VIN, regbase, 0x0c);
-+      print_reg(ST_VIN, regbase, 0x10);
-+      print_reg(ST_VIN, regbase, 0x14);
-+      print_reg(ST_VIN, regbase, 0x18);
-+      print_reg(ST_VIN, regbase, 0x1c);
-+      print_reg(ST_VIN, regbase, 0x20);
-+      print_reg(ST_VIN, regbase, 0x24);
-+      print_reg(ST_VIN, regbase, 0x28);
-+}
-+
-+struct vin_hw_ops vin_ops = {
-+      .vin_clk_enable        = stf_vin_clk_enable,
-+      .vin_clk_disable       = stf_vin_clk_disable,
-+      .vin_config_set        = stf_vin_config_set,
-+      .vin_wr_stream_set     = stf_vin_wr_stream_set,
-+      .vin_wr_irq_enable     = stf_vin_wr_irq_enable,
-+      .wr_rd_set_addr        = stf_vin_wr_rd_set_addr,
-+      .vin_wr_set_ping_addr  = stf_vin_wr_set_ping_addr,
-+      .vin_wr_set_pong_addr  = stf_vin_wr_set_pong_addr,
-+      .vin_isp_set_yuv_addr  = stf_vin_isp_set_yuv_addr,
-+      .vin_isp_set_raw_addr  = stf_vin_isp_set_raw_addr,
-+      .vin_isp_set_ss0_addr  = stf_vin_isp_set_ss0_addr,
-+      .vin_isp_set_ss1_addr  = stf_vin_isp_set_ss1_addr,
-+      .vin_isp_set_itiw_addr  = stf_vin_isp_set_itiw_addr,
-+      .vin_isp_set_itir_addr  = stf_vin_isp_set_itir_addr,
-+      .vin_isp_set_scd_addr  = stf_vin_isp_set_scd_addr,
-+      .vin_isp_get_scd_type  = stf_vin_isp_get_scd_type,
-+      .vin_wr_irq_handler    = stf_vin_wr_irq_handler,
-+      .vin_isp_irq_handler   = stf_vin_isp_irq_handler,
-+      .vin_isp_csi_irq_handler   = stf_vin_isp_csi_irq_handler,
-+      .vin_isp_scd_irq_handler   = stf_vin_isp_scd_irq_handler,
-+      .vin_isp_irq_csiline_handler   = stf_vin_isp_irq_csiline_handler,
-+};
---- /dev/null
-+++ b/drivers/media/platform/starfive/v4l2_driver/stfcamss.c
-@@ -0,0 +1,1369 @@
-+// SPDX-License-Identifier: GPL-2.0
-+/*
-+ * Copyright (C) 2021-2023 StarFive Technology Co., Ltd.
-+ *
-+ */
-+
-+#include <linux/completion.h>
-+#include <linux/delay.h>
-+#include <linux/dmaengine.h>
-+#include <linux/init.h>
-+#include <linux/interrupt.h>
-+#include <linux/kernel.h>
-+#include <linux/module.h>
-+#include <linux/of.h>
-+#include <linux/of_device.h>
-+#include <linux/of_reserved_mem.h>
-+#include <linux/of_graph.h>
-+#include <linux/of_address.h>
-+#include <linux/pinctrl/consumer.h>
-+#include <linux/platform_device.h>
-+#include <linux/pm_runtime.h>
-+#include <linux/io.h>
-+#include <linux/dma-mapping.h>
-+#include <linux/uaccess.h>
-+#include <linux/mfd/syscon.h>
-+
-+#include <linux/videodev2.h>
-+
-+#include <media/media-device.h>
-+#include <media/v4l2-async.h>
-+#include <media/v4l2-device.h>
-+#include <media/v4l2-mc.h>
-+#include <media/v4l2-fwnode.h>
-+#include <linux/debugfs.h>
-+
-+#include "stfcamss.h"
-+
-+#ifdef STF_DEBUG
-+unsigned int stdbg_level = ST_DEBUG;
-+unsigned int stdbg_mask = 0x7F;
-+#else
-+unsigned int stdbg_level = ST_ERR;
-+unsigned int stdbg_mask = 0x7F;
-+#endif
-+EXPORT_SYMBOL_GPL(stdbg_level);
-+EXPORT_SYMBOL_GPL(stdbg_mask);
-+
-+static const struct reg_name mem_reg_name[] = {
-+      {"csi2rx"},
-+      {"vclk"},
-+      {"vrst"},
-+      {"sctrl"},
-+      {"isp"},
-+      {"trst"},
-+      {"pmu"},
-+      {"syscrg"},
-+};
-+
-+static struct clk_bulk_data stfcamss_clocks[] = {
-+      { .id = "clk_apb_func" },
-+      { .id = "clk_pclk" },
-+      { .id = "clk_sys_clk" },
-+      { .id = "clk_wrapper_clk_c" },
-+      { .id = "clk_dvp_inv" },
-+      { .id = "clk_axiwr" },
-+      { .id = "clk_mipi_rx0_pxl" },
-+      { .id = "clk_pixel_clk_if0" },
-+      { .id = "clk_pixel_clk_if1" },
-+      { .id = "clk_pixel_clk_if2" },
-+      { .id = "clk_pixel_clk_if3" },
-+      { .id = "clk_m31dphy_cfgclk_in" },
-+      { .id = "clk_m31dphy_refclk_in" },
-+      { .id = "clk_m31dphy_txclkesc_lan0" },
-+      { .id = "clk_ispcore_2x" },
-+      { .id = "clk_isp_axi" },
-+};
-+
-+static struct reset_control_bulk_data stfcamss_resets[] = {
-+      { .id = "rst_wrapper_p" },
-+      { .id = "rst_wrapper_c" },
-+      { .id = "rst_pclk" },
-+      { .id = "rst_sys_clk" },
-+      { .id = "rst_axird" },
-+      { .id = "rst_axiwr" },
-+      { .id = "rst_pixel_clk_if0" },
-+      { .id = "rst_pixel_clk_if1" },
-+      { .id = "rst_pixel_clk_if2" },
-+      { .id = "rst_pixel_clk_if3" },
-+      { .id = "rst_m31dphy_hw" },
-+      { .id = "rst_m31dphy_b09_always_on" },
-+      { .id = "rst_isp_top_n" },
-+      { .id = "rst_isp_top_axi" },
-+};
-+
-+int stfcamss_get_mem_res(struct platform_device *pdev, struct stf_vin_dev *vin)
-+{
-+      struct device *dev = &pdev->dev;
-+      struct resource *res;
-+      char *name;
-+      int i;
-+
-+      for (i = 0; i < ARRAY_SIZE(mem_reg_name); i++) {
-+              name = (char *)(&mem_reg_name[i]);
-+              res = platform_get_resource_byname(pdev, IORESOURCE_MEM, name);
-+
-+              if (!res)
-+                      return -EINVAL;
-+
-+              if (!strcmp(name, "csi2rx")) {
-+                      vin->csi2rx_base = devm_ioremap_resource(dev, res);
-+                      if (IS_ERR(vin->csi2rx_base))
-+                              return PTR_ERR(vin->csi2rx_base);
-+              } else if (!strcmp(name, "vclk")) {
-+                      vin->clkgen_base = ioremap(res->start, resource_size(res));
-+                      if (!vin->clkgen_base)
-+                              return -ENOMEM;
-+              } else if (!strcmp(name, "vrst")) {
-+                      vin->rstgen_base = devm_ioremap_resource(dev, res);
-+                      if (IS_ERR(vin->rstgen_base))
-+                              return PTR_ERR(vin->rstgen_base);
-+              } else if (!strcmp(name, "sctrl")) {
-+                      vin->sysctrl_base = devm_ioremap_resource(dev, res);
-+                      if (IS_ERR(vin->sysctrl_base))
-+                              return PTR_ERR(vin->sysctrl_base);
-+              } else if (!strcmp(name, "isp")) {
-+                      vin->isp_base = devm_ioremap_resource(dev, res);
-+                      if (IS_ERR(vin->isp_base))
-+                              return PTR_ERR(vin->isp_base);
-+              } else if (!strcmp(name, "trst")) {
-+                      vin->vin_top_rstgen_base = devm_ioremap_resource(dev, res);
-+                      if (IS_ERR(vin->vin_top_rstgen_base))
-+                              return PTR_ERR(vin->vin_top_rstgen_base);
-+              } else if (!strcmp(name, "pmu")) {
-+                      vin->pmu_test = ioremap(res->start, resource_size(res));
-+                      if (!vin->pmu_test)
-+                              return -ENOMEM;
-+              } else if (!strcmp(name, "syscrg")) {
-+                      vin->sys_crg = ioremap(res->start, resource_size(res));
-+                      if (!vin->sys_crg)
-+                              return -ENOMEM;
-+              } else {
-+                      st_err(ST_CAMSS, "Could not match resource name\n");
-+              }
-+      }
-+
-+      return 0;
-+}
-+
-+int vin_parse_dt(struct device *dev, struct stf_vin_dev *vin)
-+{
-+      int ret = 0;
-+      struct device_node *np = dev->of_node;
-+
-+      if (!np)
-+              return -EINVAL;
-+
-+      return ret;
-+}
-+
-+struct media_entity *stfcamss_find_sensor(struct media_entity *entity)
-+{
-+      struct media_pad *pad;
-+
-+      while (1) {
-+              if (!entity->pads)
-+                      return NULL;
-+
-+              pad = &entity->pads[0];
-+              if (!(pad->flags & MEDIA_PAD_FL_SINK))
-+                      return NULL;
-+
-+              pad = media_pad_remote_pad_first(pad);
-+              if (!pad || !is_media_entity_v4l2_subdev(pad->entity))
-+                      return NULL;
-+
-+              entity = pad->entity;
-+
-+              if (entity->function == MEDIA_ENT_F_CAM_SENSOR)
-+                      return entity;
-+      }
-+}
-+
-+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 } };
-+      struct v4l2_mbus_config_parallel *parallel_bus = &vep.bus.parallel;
-+      struct v4l2_mbus_config_mipi_csi2 *csi2_bus = &vep.bus.mipi_csi2;
-+      struct dvp_cfg *dvp = &csd->interface.dvp;
-+      struct csi2phy_cfg *csiphy = &csd->interface.csiphy;
-+
-+      v4l2_fwnode_endpoint_parse(of_fwnode_handle(node), &vep);
-+      st_debug(ST_CAMSS, "%s: vep.base.port = 0x%x, id = 0x%x\n",
-+                      __func__, vep.base.port, vep.base.id);
-+
-+      csd->port = vep.base.port;
-+      switch (csd->port) {
-+      case DVP_SENSOR_PORT_NUMBER:
-+              st_debug(ST_CAMSS, "%s, flags = 0x%x\n", __func__,
-+                              parallel_bus->flags);
-+              dvp->flags = parallel_bus->flags;
-+              dvp->bus_width = parallel_bus->bus_width;
-+              dvp->data_shift = parallel_bus->data_shift;
-+              break;
-+      case CSI2RX_SENSOR_PORT_NUMBER:
-+              st_debug(ST_CAMSS, "%s, CSI2 flags = 0x%x\n",
-+                              __func__, parallel_bus->flags);
-+              csiphy->flags = csi2_bus->flags;
-+              memcpy(csiphy->data_lanes,
-+                              csi2_bus->data_lanes, csi2_bus->num_data_lanes);
-+              csiphy->clock_lane = csi2_bus->clock_lane;
-+              csiphy->num_data_lanes = csi2_bus->num_data_lanes;
-+              memcpy(csiphy->lane_polarities,
-+                              csi2_bus->lane_polarities,
-+                              csi2_bus->num_data_lanes + 1);
-+              break;
-+      default:
-+              break;
-+      };
-+
-+      return 0;
-+}
-+
-+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) {
-+                      st_err(ST_CAMSS, "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_init_subdevices(struct stfcamss *stfcamss)
-+{
-+      int ret;
-+
-+      ret = stf_dvp_subdev_init(stfcamss);
-+      if (ret < 0) {
-+              st_err(ST_CAMSS,
-+                      "Failed to init stf_dvp sub-device: %d\n",
-+                      ret);
-+              return ret;
-+      }
-+
-+      ret = stf_csiphy_subdev_init(stfcamss);
-+      if (ret < 0) {
-+              st_err(ST_CAMSS,
-+                      "Failed to init stf_csiphy sub-device: %d\n",
-+                      ret);
-+              return ret;
-+      }
-+
-+      ret = stf_csi_subdev_init(stfcamss);
-+      if (ret < 0) {
-+              st_err(ST_CAMSS,
-+                      "Failed to init stf_csi sub-device: %d\n",
-+                      ret);
-+              return ret;
-+      }
-+
-+      ret = stf_isp_subdev_init(stfcamss);
-+      if (ret < 0) {
-+              st_err(ST_CAMSS,
-+                      "Failed to init stf_isp sub-device: %d\n",
-+                      ret);
-+              return ret;
-+      }
-+
-+      ret = stf_vin_subdev_init(stfcamss);
-+      if (ret < 0) {
-+              st_err(ST_CAMSS,
-+                      "Failed to init stf_vin sub-device: %d\n",
-+                      ret);
-+              return ret;
-+      }
-+      return ret;
-+}
-+
-+static int stfcamss_register_subdevices(struct stfcamss *stfcamss)
-+{
-+      int ret;
-+      struct stf_vin2_dev *vin_dev = stfcamss->vin_dev;
-+      struct stf_dvp_dev *dvp_dev = stfcamss->dvp_dev;
-+      struct stf_csiphy_dev *csiphy_dev = stfcamss->csiphy_dev;
-+      struct stf_csi_dev *csi_dev = stfcamss->csi_dev;
-+      struct stf_isp_dev *isp_dev = stfcamss->isp_dev;
-+
-+      ret = stf_dvp_register(dvp_dev, &stfcamss->v4l2_dev);
-+      if (ret < 0) {
-+              st_err(ST_CAMSS,
-+                      "Failed to register stf dvp%d entity: %d\n",
-+                      0, ret);
-+              goto err_reg_dvp;
-+      }
-+
-+      ret = stf_csiphy_register(csiphy_dev, &stfcamss->v4l2_dev);
-+      if (ret < 0) {
-+              st_err(ST_CAMSS,
-+                      "Failed to register stf csiphy%d entity: %d\n",
-+                      0, ret);
-+              goto err_reg_csiphy;
-+      }
-+
-+      ret = stf_csi_register(csi_dev, &stfcamss->v4l2_dev);
-+      if (ret < 0) {
-+              st_err(ST_CAMSS,
-+                      "Failed to register stf csi%d entity: %d\n",
-+                      0, ret);
-+              goto err_reg_csi;
-+      }
-+
-+      ret = stf_isp_register(isp_dev, &stfcamss->v4l2_dev);
-+      if (ret < 0) {
-+              st_err(ST_CAMSS,
-+                      "Failed to register stf isp%d entity: %d\n",
-+                      0, ret);
-+              goto err_reg_isp;
-+      }
-+
-+      ret = stf_vin_register(vin_dev, &stfcamss->v4l2_dev);
-+      if (ret < 0) {
-+              st_err(ST_CAMSS,
-+                      "Failed to register vin entity: %d\n",
-+                       ret);
-+              goto err_reg_vin;
-+      }
-+
-+      ret = media_create_pad_link(
-+              &dvp_dev->subdev.entity,
-+              STF_DVP_PAD_SRC,
-+              &vin_dev->line[VIN_LINE_WR].subdev.entity,
-+              STF_VIN_PAD_SINK,
-+              0);
-+      if (ret < 0) {
-+              st_err(ST_CAMSS,
-+                      "Failed to link %s->vin entities: %d\n",
-+                      dvp_dev->subdev.entity.name,
-+                      ret);
-+              goto err_link;
-+      }
-+
-+      ret = media_create_pad_link(
-+              &csi_dev->subdev.entity,
-+              STF_CSI_PAD_SRC,
-+              &vin_dev->line[VIN_LINE_WR].subdev.entity,
-+              STF_VIN_PAD_SINK,
-+              0);
-+      if (ret < 0) {
-+              st_err(ST_CAMSS,
-+                      "Failed to link %s->vin entities: %d\n",
-+                      csi_dev->subdev.entity.name,
-+                      ret);
-+              goto err_link;
-+      }
-+
-+      ret = media_create_pad_link(
-+              &csiphy_dev->subdev.entity,
-+              STF_CSIPHY_PAD_SRC,
-+              &csi_dev->subdev.entity,
-+              STF_CSI_PAD_SINK,
-+              MEDIA_LNK_FL_IMMUTABLE | MEDIA_LNK_FL_ENABLED);
-+      if (ret < 0) {
-+              st_err(ST_CAMSS,
-+                      "Failed to link %s->%s entities: %d\n",
-+                      csiphy_dev->subdev.entity.name,
-+                      csi_dev->subdev.entity.name,
-+                      ret);
-+              goto err_link;
-+      }
-+
-+      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) {
-+              st_err(ST_CAMSS,
-+                      "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;
-+      }
-+
-+      ret = media_create_pad_link(
-+              &isp_dev->subdev.entity,
-+              STF_ISP_PAD_SRC_SS0,
-+              &vin_dev->line[VIN_LINE_ISP_SS0].subdev.entity,
-+              STF_VIN_PAD_SINK,
-+              0);
-+      if (ret < 0) {
-+              st_err(ST_CAMSS,
-+                      "Failed to link %s->%s entities: %d\n",
-+                      isp_dev->subdev.entity.name,
-+                      vin_dev->line[VIN_LINE_ISP_SS0]
-+                      .subdev.entity.name,
-+                      ret);
-+              goto err_link;
-+      }
-+
-+      ret = media_create_pad_link(
-+              &isp_dev->subdev.entity,
-+              STF_ISP_PAD_SRC_SS1,
-+              &vin_dev->line[VIN_LINE_ISP_SS1].subdev.entity,
-+              STF_VIN_PAD_SINK,
-+              0);
-+      if (ret < 0) {
-+              st_err(ST_CAMSS,
-+                      "Failed to link %s->%s entities: %d\n",
-+                      isp_dev->subdev.entity.name,
-+                      vin_dev->line[VIN_LINE_ISP_SS1]
-+                      .subdev.entity.name,
-+                      ret);
-+              goto err_link;
-+      }
-+
-+#ifndef       STF_CAMSS_SKIP_ITI
-+      ret = media_create_pad_link(
-+              &isp_dev->subdev.entity,
-+              STF_ISP_PAD_SRC_ITIW,
-+              &vin_dev->line[VIN_LINE_ISP_ITIW].subdev.entity,
-+              STF_VIN_PAD_SINK,
-+              0);
-+      if (ret < 0) {
-+              st_err(ST_CAMSS,
-+                      "Failed to link %s->%s entities: %d\n",
-+                      isp_dev->subdev.entity.name,
-+                      vin_dev->line[VIN_LINE_ISP_ITIW]
-+                      .subdev.entity.name,
-+                      ret);
-+              goto err_link;
-+      }
-+
-+      ret = media_create_pad_link(
-+              &isp_dev->subdev.entity,
-+              STF_ISP_PAD_SRC_ITIR,
-+              &vin_dev->line[VIN_LINE_ISP_ITIR].subdev.entity,
-+              STF_VIN_PAD_SINK,
-+              0);
-+      if (ret < 0) {
-+              st_err(ST_CAMSS,
-+                      "Failed to link %s->%s entities: %d\n",
-+                      isp_dev->subdev.entity.name,
-+                      vin_dev->line[VIN_LINE_ISP_ITIR]
-+                      .subdev.entity.name,
-+                      ret);
-+              goto err_link;
-+      }
-+#endif
-+
-+      ret = media_create_pad_link(
-+              &isp_dev->subdev.entity,
-+              STF_ISP_PAD_SRC_RAW,
-+              &vin_dev->line[VIN_LINE_ISP_RAW].subdev.entity,
-+              STF_VIN_PAD_SINK,
-+              0);
-+      if (ret < 0) {
-+              st_err(ST_CAMSS,
-+                      "Failed to link %s->%s entities: %d\n",
-+                      isp_dev->subdev.entity.name,
-+                      vin_dev->line[VIN_LINE_ISP_RAW]
-+                      .subdev.entity.name,
-+                      ret);
-+              goto err_link;
-+      }
-+
-+      ret = media_create_pad_link(
-+              &isp_dev->subdev.entity,
-+              STF_ISP_PAD_SRC_SCD_Y,
-+              &vin_dev->line[VIN_LINE_ISP_SCD_Y].subdev.entity,
-+              STF_VIN_PAD_SINK,
-+              0);
-+      if (ret < 0) {
-+              st_err(ST_CAMSS,
-+                      "Failed to link %s->%s entities: %d\n",
-+                      isp_dev->subdev.entity.name,
-+                      vin_dev->line[VIN_LINE_ISP_SCD_Y]
-+                      .subdev.entity.name,
-+                      ret);
-+              goto err_link;
-+      }
-+
-+      ret = media_create_pad_link(
-+              &dvp_dev->subdev.entity,
-+              STF_DVP_PAD_SRC,
-+              &isp_dev->subdev.entity,
-+              STF_ISP_PAD_SINK,
-+              0);
-+      if (ret < 0) {
-+              st_err(ST_CAMSS,
-+                      "Failed to link %s->%s entities: %d\n",
-+                      dvp_dev->subdev.entity.name,
-+                      isp_dev->subdev.entity.name,
-+              ret);
-+              goto err_link;
-+      }
-+
-+      ret = media_create_pad_link(
-+              &csi_dev->subdev.entity,
-+              STF_CSI_PAD_SRC,
-+              &isp_dev->subdev.entity,
-+              STF_ISP_PAD_SINK,
-+              0);
-+      if (ret < 0) {
-+              st_err(ST_CAMSS,
-+                      "Failed to link %s->%s entities: %d\n",
-+                      csi_dev->subdev.entity.name,
-+                      isp_dev->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:
-+      stf_csi_unregister(stfcamss->csi_dev);
-+err_reg_csi:
-+      stf_csiphy_unregister(stfcamss->csiphy_dev);
-+err_reg_csiphy:
-+      stf_dvp_unregister(stfcamss->dvp_dev);
-+err_reg_dvp:
-+      return ret;
-+}
-+
-+static void stfcamss_unregister_subdevices(struct stfcamss *stfcamss)
-+{
-+      stf_dvp_unregister(stfcamss->dvp_dev);
-+      stf_csiphy_unregister(stfcamss->csiphy_dev);
-+      stf_csi_unregister(stfcamss->csi_dev);
-+      stf_isp_unregister(stfcamss->isp_dev);
-+      stf_vin_unregister(stfcamss->vin_dev);
-+}
-+
-+static int stfcamss_register_mediadevice_subdevnodes(
-+              struct v4l2_async_notifier *async,
-+              struct v4l2_subdev *sd)
-+{
-+      struct stfcamss *stfcamss =
-+              container_of(async, struct stfcamss, notifier);
-+      int ret;
-+
-+      if (sd->host_priv) {
-+              struct media_entity *sensor = &sd->entity;
-+              struct media_entity *input = sd->host_priv;
-+              unsigned int i;
-+
-+              for (i = 0; i < sensor->num_pads; i++) {
-+                      if (sensor->pads[i].flags & MEDIA_PAD_FL_SOURCE)
-+                              break;
-+              }
-+              if (i == sensor->num_pads) {
-+                      st_err(ST_CAMSS,
-+                              "No source pad in external entity\n");
-+                      return -EINVAL;
-+              }
-+
-+              ret = media_create_pad_link(sensor, i,
-+                      input, STF_PAD_SINK,
-+                      MEDIA_LNK_FL_IMMUTABLE | MEDIA_LNK_FL_ENABLED);
-+              if (ret < 0) {
-+                      st_err(ST_CAMSS,
-+                              "Failed to link %s->%s entities: %d\n",
-+                              sensor->name, input->name, ret);
-+                      return ret;
-+              }
-+      }
-+
-+      ret = v4l2_device_register_subdev_nodes(&stfcamss->v4l2_dev);
-+      if (ret < 0)
-+              return ret;
-+
-+      if (stfcamss->media_dev.devnode)
-+              return ret;
-+
-+      st_debug(ST_CAMSS, "stfcamss register media device\n");
-+      return media_device_register(&stfcamss->media_dev);
-+}
-+
-+static int stfcamss_subdev_notifier_bound(struct v4l2_async_notifier *async,
-+                                      struct v4l2_subdev *subdev,
-+                                      struct v4l2_async_connection *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_dvp_dev *dvp_dev = stfcamss->dvp_dev;
-+      struct stf_csiphy_dev *csiphy_dev = stfcamss->csiphy_dev;
-+
-+      switch (port) {
-+      case DVP_SENSOR_PORT_NUMBER:
-+              dvp_dev->dvp = &csd->interface.dvp;
-+              subdev->host_priv = &dvp_dev->subdev.entity;
-+              break;
-+      case CSI2RX_SENSOR_PORT_NUMBER:
-+              csiphy_dev->csiphy = &csd->interface.csiphy;
-+              subdev->host_priv = &csiphy_dev->subdev.entity;
-+              break;
-+      default:
-+              break;
-+      };
-+
-+      stfcamss_register_mediadevice_subdevnodes(async, subdev);
-+
-+      return 0;
-+}
-+
-+#ifdef UNUSED_CODE
-+static int stfcamss_subdev_notifier_complete(
-+              struct v4l2_async_notifier *async)
-+{
-+      struct stfcamss *stfcamss =
-+              container_of(async, struct stfcamss, notifier);
-+      struct v4l2_device *v4l2_dev = &stfcamss->v4l2_dev;
-+      struct v4l2_subdev *sd;
-+      int ret;
-+
-+      list_for_each_entry(sd, &v4l2_dev->subdevs, list) {
-+              if (sd->host_priv) {
-+                      struct media_entity *sensor = &sd->entity;
-+                      struct media_entity *input = sd->host_priv;
-+                      unsigned int i;
-+
-+                      for (i = 0; i < sensor->num_pads; i++) {
-+                              if (sensor->pads[i].flags & MEDIA_PAD_FL_SOURCE)
-+                                      break;
-+                      }
-+                      if (i == sensor->num_pads) {
-+                              st_err(ST_CAMSS,
-+                                      "No source pad in external entity\n");
-+                              return -EINVAL;
-+                      }
-+
-+                      ret = media_create_pad_link(sensor, i,
-+                              input, STF_PAD_SINK,
-+                              MEDIA_LNK_FL_IMMUTABLE | MEDIA_LNK_FL_ENABLED);
-+                      if (ret < 0) {
-+                              st_err(ST_CAMSS,
-+                                      "Failed to link %s->%s entities: %d\n",
-+                                      sensor->name, input->name, ret);
-+                              return ret;
-+                      }
-+              }
-+      }
-+
-+      ret = v4l2_device_register_subdev_nodes(&stfcamss->v4l2_dev);
-+      if (ret < 0)
-+              return ret;
-+
-+      return media_device_register(&stfcamss->media_dev);
-+}
-+#endif
-+
-+static const struct v4l2_async_notifier_operations
-+stfcamss_subdev_notifier_ops = {
-+      .bound = stfcamss_subdev_notifier_bound,
-+};
-+
-+static const struct media_device_ops stfcamss_media_ops = {
-+      .link_notify = v4l2_pipeline_link_notify,
-+};
-+
-+#ifdef CONFIG_DEBUG_FS
-+enum module_id {
-+      VIN_MODULE = 0,
-+      ISP_MODULE,
-+      CSI_MODULE,
-+      CSIPHY_MODULE,
-+      DVP_MODULE,
-+      CLK_MODULE,
-+};
-+
-+static enum module_id id_num = ISP_MODULE;
-+
-+void dump_clk_reg(void __iomem *reg_base)
-+{
-+      int i;
-+
-+      st_info(ST_CAMSS, "DUMP Clk register:\n");
-+      for (i = 0; i <= CLK_C_ISP_CTRL; i += 4)
-+              print_reg(ST_CAMSS, reg_base, i);
-+}
-+
-+static ssize_t vin_debug_read(struct file *file, char __user *user_buf,
-+                      size_t count, loff_t *ppos)
-+{
-+      struct device *dev = file->private_data;
-+      void __iomem *reg_base;
-+      struct stfcamss *stfcamss = dev_get_drvdata(dev);
-+      struct stf_vin_dev *vin = stfcamss->vin;
-+      struct stf_vin2_dev *vin_dev = stfcamss->vin_dev;
-+      struct stf_isp_dev *isp_dev = stfcamss->isp_dev;
-+      struct stf_csi_dev *csi0_dev = stfcamss->csi_dev;
-+
-+      switch (id_num) {
-+      case VIN_MODULE:
-+      case CSIPHY_MODULE:
-+      case DVP_MODULE:
-+              mutex_lock(&vin_dev->power_lock);
-+              if (vin_dev->power_count > 0) {
-+                      reg_base = vin->sysctrl_base;
-+                      dump_vin_reg(reg_base);
-+              }
-+              mutex_unlock(&vin_dev->power_lock);
-+              break;
-+      case ISP_MODULE:
-+              mutex_lock(&isp_dev->stream_lock);
-+              if (isp_dev->stream_count > 0) {
-+                      reg_base = vin->isp_base;
-+                      dump_isp_reg(reg_base);
-+              }
-+              mutex_unlock(&isp_dev->stream_lock);
-+              break;
-+      case CSI_MODULE:
-+              mutex_lock(&csi0_dev->stream_lock);
-+              if (csi0_dev->stream_count > 0) {
-+                      reg_base = vin->csi2rx_base;
-+                      dump_csi_reg(reg_base);
-+              }
-+              mutex_unlock(&csi0_dev->stream_lock);
-+              break;
-+      case CLK_MODULE:
-+              mutex_lock(&vin_dev->power_lock);
-+              if (vin_dev->power_count > 0) {
-+                      reg_base = vin->clkgen_base;
-+                      dump_clk_reg(reg_base);
-+              }
-+              mutex_unlock(&vin_dev->power_lock);
-+              break;
-+      default:
-+              break;
-+      }
-+
-+      return 0;
-+}
-+
-+static void set_reg_val(struct stfcamss *stfcamss, int id, u32 offset, u32 val)
-+{
-+      struct stf_vin_dev *vin = stfcamss->vin;
-+      struct stf_vin2_dev *vin_dev = stfcamss->vin_dev;
-+      struct stf_isp_dev *isp_dev = stfcamss->isp_dev;
-+      struct stf_csi_dev *csi_dev = stfcamss->csi_dev;
-+      void __iomem *reg_base;
-+
-+      switch (id) {
-+      case VIN_MODULE:
-+      case CSIPHY_MODULE:
-+      case DVP_MODULE:
-+              mutex_lock(&vin_dev->power_lock);
-+              if (vin_dev->power_count > 0) {
-+                      reg_base = vin->sysctrl_base;
-+                      print_reg(ST_VIN, reg_base, offset);
-+                      reg_write(reg_base, offset, val);
-+                      print_reg(ST_VIN, reg_base, offset);
-+              }
-+              mutex_unlock(&vin_dev->power_lock);
-+              break;
-+      case ISP_MODULE:
-+              mutex_lock(&isp_dev->stream_lock);
-+              if (isp_dev->stream_count > 0) {
-+                      reg_base = vin->isp_base;
-+                      print_reg(ST_ISP, reg_base, offset);
-+                      reg_write(reg_base, offset, val);
-+                      print_reg(ST_ISP, reg_base, offset);
-+              }
-+              mutex_unlock(&isp_dev->stream_lock);
-+              break;
-+      case CSI_MODULE:
-+              mutex_lock(&csi_dev->stream_lock);
-+              if (csi_dev->stream_count > 0) {
-+                      reg_base = vin->csi2rx_base;
-+                      print_reg(ST_CSI, reg_base, offset);
-+                      reg_write(reg_base, offset, val);
-+                      print_reg(ST_CSI, reg_base, offset);
-+              }
-+              mutex_unlock(&csi_dev->stream_lock);
-+              break;
-+      case CLK_MODULE:
-+              mutex_lock(&vin_dev->power_lock);
-+              if (vin_dev->power_count > 0) {
-+                      reg_base = vin->clkgen_base;
-+                      print_reg(ST_CAMSS, reg_base, offset);
-+                      reg_write(reg_base, offset, val);
-+                      print_reg(ST_CAMSS, reg_base, offset);
-+              }
-+              mutex_unlock(&vin_dev->power_lock);
-+              break;
-+      default:
-+              break;
-+
-+      }
-+}
-+
-+static u32 atoi(const char *s)
-+{
-+      u32 ret = 0, d = 0;
-+      char ch;
-+      int hex = 0;
-+
-+      if ((*s == '0') && (*(s+1) == 'x')) {
-+              hex = 1;
-+              s += 2;
-+      }
-+
-+      while (1) {
-+              if (!hex) {
-+                      d = (*s++) - '0';
-+                      if (d > 9)
-+                              break;
-+                      ret *= 10;
-+                      ret += d;
-+              } else {
-+                      ch = tolower(*s++);
-+                      if (isdigit(ch))
-+                              d = ch - '0';
-+                      else if (islower(ch))
-+                              d = ch - 'a' + 10;
-+                      else
-+                              break;
-+                      if (d > 15)
-+                              break;
-+                      ret *= 16;
-+                      ret += d;
-+              }
-+      }
-+
-+      return ret;
-+}
-+
-+static ssize_t vin_debug_write(struct file *file, const char __user *user_buf,
-+                              size_t count, loff_t *ppos)
-+{
-+      struct device *dev = file->private_data;
-+      struct stfcamss *stfcamss = dev_get_drvdata(dev);
-+      char *buf;
-+      char *line;
-+      char *p;
-+      static const char *delims = " \t\r";
-+      char *token;
-+      u32 offset, val;
-+
-+      buf = memdup_user_nul(user_buf, min_t(size_t, PAGE_SIZE, count));
-+      if (IS_ERR(buf))
-+              return PTR_ERR(buf);
-+      p = buf;
-+      st_debug(ST_CAMSS, "dup buf: %s, len: %lu, count: %lu\n", p, strlen(p), count);
-+      while (p && *p) {
-+              p = skip_spaces(p);
-+              line = strsep(&p, "\n");
-+              if (!*line || *line == '#')
-+                      break;
-+              token = strsep(&line, delims);
-+              if (!token)
-+                      goto out;
-+              id_num = atoi(token);
-+              token = strsep(&line, delims);
-+              if (!token)
-+                      goto out;
-+              offset = atoi(token);
-+              token = strsep(&line, delims);
-+              if (!token)
-+                      goto out;
-+              val = atoi(token);
-+      }
-+      set_reg_val(stfcamss, id_num, offset, val);
-+out:
-+      kfree(buf);
-+      st_info(ST_CAMSS, "id_num = %d, offset = 0x%x, 0x%x\n", id_num, offset, val);
-+      return count;
-+}
-+
-+static const struct file_operations vin_debug_fops = {
-+      .open = simple_open,
-+      .read = vin_debug_read,
-+      .write = vin_debug_write,
-+};
-+#endif /* CONFIG_DEBUG_FS */
-+
-+
-+static int stfcamss_probe(struct platform_device *pdev)
-+{
-+      struct stfcamss *stfcamss;
-+      struct stf_vin_dev *vin;
-+      struct device *dev = &pdev->dev;
-+      struct of_phandle_args args;
-+      int ret = 0, num_subdevs;
-+
-+      dev_info(dev, "stfcamss probe enter!\n");
-+
-+      stfcamss = devm_kzalloc(dev, sizeof(struct stfcamss), GFP_KERNEL);
-+      if (!stfcamss)
-+              return -ENOMEM;
-+
-+      stfcamss->dvp_dev = devm_kzalloc(dev,
-+              sizeof(*stfcamss->dvp_dev), GFP_KERNEL);
-+      if (!stfcamss->dvp_dev) {
-+              ret = -ENOMEM;
-+              goto err_cam;
-+      }
-+
-+      stfcamss->csiphy_dev = devm_kzalloc(dev,
-+              sizeof(*stfcamss->csiphy_dev),
-+              GFP_KERNEL);
-+      if (!stfcamss->csiphy_dev) {
-+              ret = -ENOMEM;
-+              goto err_cam;
-+      }
-+
-+      stfcamss->csi_dev = devm_kzalloc(dev,
-+              sizeof(*stfcamss->csi_dev),
-+              GFP_KERNEL);
-+      if (!stfcamss->csi_dev) {
-+              ret = -ENOMEM;
-+              goto err_cam;
-+      }
-+
-+      stfcamss->isp_dev = devm_kzalloc(dev,
-+              sizeof(*stfcamss->isp_dev),
-+              GFP_KERNEL);
-+      if (!stfcamss->isp_dev) {
-+              ret = -ENOMEM;
-+              goto err_cam;
-+      }
-+
-+      stfcamss->vin_dev = devm_kzalloc(dev,
-+              sizeof(*stfcamss->vin_dev),
-+              GFP_KERNEL);
-+      if (!stfcamss->vin_dev) {
-+              ret = -ENOMEM;
-+              goto err_cam;
-+      }
-+
-+      stfcamss->vin = devm_kzalloc(dev,
-+              sizeof(struct stf_vin_dev),
-+              GFP_KERNEL);
-+      if (!stfcamss->vin) {
-+              ret = -ENOMEM;
-+              goto err_cam;
-+      }
-+
-+      vin = stfcamss->vin;
-+
-+      vin->irq = platform_get_irq(pdev, 0);
-+      if (vin->irq <= 0) {
-+              st_err(ST_CAMSS, "Could not get irq\n");
-+              goto err_cam;
-+      }
-+
-+      vin->isp_irq = platform_get_irq(pdev, 1);
-+      if (vin->isp_irq <= 0) {
-+              st_err(ST_CAMSS, "Could not get isp irq\n");
-+              goto err_cam;
-+      }
-+
-+      vin->isp_csi_irq = platform_get_irq(pdev, 2);
-+      if (vin->isp_csi_irq <= 0) {
-+              st_err(ST_CAMSS, "Could not get isp csi irq\n");
-+              goto err_cam;
-+      }
-+
-+      vin->isp_scd_irq = platform_get_irq(pdev, 3);
-+      if (vin->isp_scd_irq <= 0) {
-+              st_err(ST_CAMSS, "Could not get isp scd irq\n");
-+              goto err_cam;
-+      }
-+
-+      vin->isp_irq_csiline = platform_get_irq(pdev, 4);
-+      if (vin->isp_irq_csiline <= 0) {
-+              st_err(ST_CAMSS, "Could not get isp irq csiline\n");
-+              goto err_cam;
-+      }
-+
-+      pm_runtime_enable(dev);
-+
-+      stfcamss->nclks = ARRAY_SIZE(stfcamss_clocks);
-+      stfcamss->sys_clk = stfcamss_clocks;
-+
-+      ret = devm_clk_bulk_get(dev, stfcamss->nclks, stfcamss->sys_clk);
-+      if (ret) {
-+              st_err(ST_CAMSS, "Failed to get clk controls\n");
-+              return ret;
-+      }
-+
-+      stfcamss->nrsts = ARRAY_SIZE(stfcamss_resets);
-+      stfcamss->sys_rst = stfcamss_resets;
-+
-+      ret = devm_reset_control_bulk_get_shared(dev, stfcamss->nrsts,
-+              stfcamss->sys_rst);
-+      if (ret) {
-+              st_err(ST_CAMSS, "Failed to get reset controls\n");
-+              return ret;
-+      }
-+
-+      ret = of_parse_phandle_with_fixed_args(dev->of_node,
-+                      "starfive,aon-syscon", 1, 0, &args);
-+      if (ret < 0) {
-+              st_err(ST_CAMSS, "Failed to parse starfive,aon-syscon\n");
-+              return -EINVAL;
-+      }
-+
-+      stfcamss->stf_aon_syscon = syscon_node_to_regmap(args.np);
-+      of_node_put(args.np);
-+      if (IS_ERR(stfcamss->stf_aon_syscon))
-+              return PTR_ERR(stfcamss->stf_aon_syscon);
-+
-+      stfcamss->aon_gp_reg = args.args[0];
-+
-+      ret = stfcamss_get_mem_res(pdev, vin);
-+      if (ret) {
-+              st_err(ST_CAMSS, "Could not map registers\n");
-+              goto err_cam;
-+      }
-+
-+      ret = vin_parse_dt(dev, vin);
-+      if (ret)
-+              goto err_cam;
-+
-+      vin->dev = dev;
-+      stfcamss->dev = dev;
-+      platform_set_drvdata(pdev, stfcamss);
-+
-+      v4l2_async_nf_init(&stfcamss->notifier, &stfcamss->v4l2_dev);
-+
-+      num_subdevs = stfcamss_of_parse_ports(stfcamss);
-+      if (num_subdevs < 0) {
-+              ret = num_subdevs;
-+              goto err_cam_noti;
-+      }
-+
-+      ret = stfcamss_init_subdevices(stfcamss);
-+      if (ret < 0) {
-+              st_err(ST_CAMSS, "Failed to init subdevice: %d\n", ret);
-+              goto err_cam_noti;
-+      }
-+
-+      stfcamss->media_dev.dev = stfcamss->dev;
-+      strscpy(stfcamss->media_dev.model, "Starfive Camera Subsystem",
-+              sizeof(stfcamss->media_dev.model));
-+      strscpy(stfcamss->media_dev.serial, "0123456789ABCDEF",
-+              sizeof(stfcamss->media_dev.serial));
-+      snprintf(stfcamss->media_dev.bus_info, sizeof(stfcamss->media_dev.bus_info),
-+                      "%s:%s", dev_bus_name(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;
-+
-+      ret = v4l2_device_register(stfcamss->dev, &stfcamss->v4l2_dev);
-+      if (ret < 0) {
-+              st_err(ST_CAMSS, "Failed to register V4L2 device: %d\n", ret);
-+              goto err_cam_noti_med;
-+      }
-+
-+      ret = stfcamss_register_subdevices(stfcamss);
-+      if (ret < 0) {
-+              st_err(ST_CAMSS, "Failed to register subdevice: %d\n", ret);
-+              goto err_cam_noti_med_vreg;
-+      }
-+
-+      if (num_subdevs) {
-+              stfcamss->notifier.ops = &stfcamss_subdev_notifier_ops;
-+              ret = v4l2_async_nf_register(&stfcamss->notifier);
-+              if (ret) {
-+                      st_err(ST_CAMSS,
-+                              "Failed to register async subdev nodes: %d\n",
-+                              ret);
-+                      goto err_cam_noti_med_vreg_sub;
-+              }
-+      } else {
-+              ret = v4l2_device_register_subdev_nodes(&stfcamss->v4l2_dev);
-+              if (ret < 0) {
-+                      st_err(ST_CAMSS,
-+                              "Failed to register subdev nodes: %d\n",
-+                              ret);
-+                      goto err_cam_noti_med_vreg_sub;
-+              }
-+
-+              ret = media_device_register(&stfcamss->media_dev);
-+              if (ret < 0) {
-+                      st_err(ST_CAMSS, "Failed to register media device: %d\n",
-+                                      ret);
-+                      goto err_cam_noti_med_vreg_sub_medreg;
-+              }
-+      }
-+
-+#ifdef CONFIG_DEBUG_FS
-+      stfcamss->debugfs_entry = debugfs_create_dir("stfcamss", NULL);
-+      stfcamss->vin_debugfs = debugfs_create_file("stf_vin",
-+                      0644, stfcamss->debugfs_entry,
-+                      (void *)dev, &vin_debug_fops);
-+      debugfs_create_u32("dbg_level",
-+                      0644, stfcamss->debugfs_entry,
-+                      &stdbg_level);
-+      debugfs_create_u32("dbg_mask",
-+                      0644, stfcamss->debugfs_entry,
-+                      &stdbg_mask);
-+#endif
-+      dev_info(dev, "stfcamss probe success!\n");
-+
-+      return 0;
-+
-+#ifdef CONFIG_DEBUG_FS
-+      debugfs_remove(stfcamss->vin_debugfs);
-+      debugfs_remove_recursive(stfcamss->debugfs_entry);
-+      stfcamss->debugfs_entry = NULL;
-+#endif
-+
-+err_cam_noti_med_vreg_sub_medreg:
-+err_cam_noti_med_vreg_sub:
-+      stfcamss_unregister_subdevices(stfcamss);
-+err_cam_noti_med_vreg:
-+      v4l2_device_unregister(&stfcamss->v4l2_dev);
-+err_cam_noti_med:
-+      media_device_cleanup(&stfcamss->media_dev);
-+err_cam_noti:
-+      v4l2_async_nf_cleanup(&stfcamss->notifier);
-+err_cam:
-+      // kfree(stfcamss);
-+      return ret;
-+}
-+
-+static int stfcamss_remove(struct platform_device *pdev)
-+{
-+      struct stfcamss *stfcamss = platform_get_drvdata(pdev);
-+
-+      dev_info(&pdev->dev, "remove done\n");
-+
-+#ifdef CONFIG_DEBUG_FS
-+      debugfs_remove(stfcamss->vin_debugfs);
-+      debugfs_remove_recursive(stfcamss->debugfs_entry);
-+      stfcamss->debugfs_entry = NULL;
-+#endif
-+
-+      stfcamss_unregister_subdevices(stfcamss);
-+      v4l2_device_unregister(&stfcamss->v4l2_dev);
-+      media_device_cleanup(&stfcamss->media_dev);
-+      pm_runtime_disable(&pdev->dev);
-+
-+      kfree(stfcamss);
-+
-+      return 0;
-+}
-+
-+static const struct of_device_id stfcamss_of_match[] = {
-+      { .compatible = "starfive,jh7110-vin" },
-+      { /* end node */ },
-+};
-+
-+MODULE_DEVICE_TABLE(of, stfcamss_of_match);
-+
-+#ifdef CONFIG_PM_SLEEP
-+static int stfcamss_suspend(struct device *dev)
-+{
-+      struct stfcamss *stfcamss = dev_get_drvdata(dev);
-+      struct stf_vin2_dev *vin_dev = stfcamss->vin_dev;
-+      struct media_entity *entity;
-+      struct media_pad *pad;
-+      struct v4l2_subdev *subdev;
-+      struct stfcamss_video *video;
-+      struct video_device *vdev;
-+      int i = 0;
-+      int pm_power_count;
-+      int pm_stream_count;
-+
-+      for (i = 0; i < VIN_LINE_MAX; i++) {
-+              video = &vin_dev->line[i].video_out;
-+              vdev = &vin_dev->line[i].video_out.vdev;
-+              vin_dev->line[i].pm_power_count = vin_dev->line[i].power_count;
-+              vin_dev->line[i].pm_stream_count = vin_dev->line[i].stream_count;
-+              pm_power_count = vin_dev->line[i].pm_power_count;
-+              pm_stream_count = vin_dev->line[i].pm_stream_count;
-+
-+              if (pm_stream_count) {
-+                      while (pm_stream_count--) {
-+                              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);
-+              }
-+
-+              if (!pm_power_count)
-+                      continue;
-+
-+              v4l2_pipeline_pm_put(&vdev->entity);
-+      }
-+
-+      return pm_runtime_force_suspend(dev);
-+}
-+
-+static int stfcamss_resume(struct device *dev)
-+{
-+      struct stfcamss *stfcamss = dev_get_drvdata(dev);
-+      struct stf_vin2_dev *vin_dev = stfcamss->vin_dev;
-+      struct media_entity *entity;
-+      struct media_pad *pad;
-+      struct v4l2_subdev *subdev;
-+      struct stfcamss_video *video;
-+      struct video_device *vdev;
-+      int i = 0;
-+      int pm_power_count;
-+      int pm_stream_count;
-+      int ret = 0;
-+
-+      pm_runtime_force_resume(dev);
-+
-+      for (i = 0; i < VIN_LINE_MAX; i++) {
-+              video = &vin_dev->line[i].video_out;
-+              vdev = &vin_dev->line[i].video_out.vdev;
-+              pm_power_count = vin_dev->line[i].pm_power_count;
-+              pm_stream_count = vin_dev->line[i].pm_stream_count;
-+
-+              if (!pm_power_count)
-+                      continue;
-+
-+              ret = v4l2_pipeline_pm_get(&vdev->entity);
-+              if (ret < 0)
-+                      goto err;
-+
-+              if (pm_stream_count) {
-+                      ret = video_device_pipeline_start(vdev, &video->stfcamss->pipe);
-+                      if (ret < 0)
-+                              goto err_pm_put;
-+
-+                      while (pm_stream_count--) {
-+                              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 err_pipeline_stop;
-+                              }
-+                      }
-+              }
-+      }
-+
-+      return 0;
-+
-+err_pipeline_stop:
-+      video_device_pipeline_stop(vdev);
-+err_pm_put:
-+      v4l2_pipeline_pm_put(&vdev->entity);
-+err:
-+      return ret;
-+}
-+#endif /* CONFIG_PM_SLEEP */
-+
-+#ifdef CONFIG_PM
-+static int stfcamss_runtime_suspend(struct device *dev)
-+{
-+      struct stfcamss *stfcamss = dev_get_drvdata(dev);
-+
-+      reset_control_assert(stfcamss->sys_rst[STFRST_ISP_TOP_AXI].rstc);
-+      reset_control_assert(stfcamss->sys_rst[STFRST_ISP_TOP_N].rstc);
-+      clk_disable_unprepare(stfcamss->sys_clk[STFCLK_ISP_AXI].clk);
-+      clk_disable_unprepare(stfcamss->sys_clk[STFCLK_ISPCORE_2X].clk);
-+
-+      return 0;
-+}
-+
-+static int stfcamss_runtime_resume(struct device *dev)
-+{
-+      struct stfcamss *stfcamss = dev_get_drvdata(dev);
-+
-+      clk_prepare_enable(stfcamss->sys_clk[STFCLK_ISPCORE_2X].clk);
-+      clk_prepare_enable(stfcamss->sys_clk[STFCLK_ISP_AXI].clk);
-+      reset_control_deassert(stfcamss->sys_rst[STFRST_ISP_TOP_N].rstc);
-+      reset_control_deassert(stfcamss->sys_rst[STFRST_ISP_TOP_AXI].rstc);
-+
-+      return 0;
-+}
-+#endif /* CONFIG_PM */
-+
-+static const struct dev_pm_ops stfcamss_pm_ops = {
-+      SET_SYSTEM_SLEEP_PM_OPS(stfcamss_suspend, stfcamss_resume)
-+      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),
-+      },
-+};
-+
-+static int __init stfcamss_init(void)
-+{
-+      return platform_driver_register(&stfcamss_driver);
-+}
-+
-+static void __exit stfcamss_cleanup(void)
-+{
-+      platform_driver_unregister(&stfcamss_driver);
-+}
-+
-+module_init(stfcamss_init);
-+//fs_initcall(stfcamss_init);
-+module_exit(stfcamss_cleanup);
-+
-+MODULE_LICENSE("GPL");
---- /dev/null
-+++ b/drivers/media/platform/starfive/v4l2_driver/stfcamss.h
-@@ -0,0 +1,117 @@
-+/* SPDX-License-Identifier: GPL-2.0
-+ *
-+ * Copyright (C) 2021-2023 StarFive Technology Co., Ltd.
-+ *
-+ */
-+
-+#ifndef STFCAMSS_H
-+#define STFCAMSS_H
-+
-+#include <linux/io.h>
-+#include <linux/delay.h>
-+#include <linux/reset.h>
-+#include <linux/clk.h>
-+
-+enum sensor_type {
-+      SENSOR_VIN,
-+      /* need replace sensor */
-+      SENSOR_ISP,
-+};
-+
-+enum subdev_type {
-+      VIN_DEV_TYPE,
-+      ISP_DEV_TYPE,
-+};
-+
-+#include "stf_common.h"
-+#include "stf_dvp.h"
-+#include "stf_csi.h"
-+#include "stf_csiphy.h"
-+#include "stf_isp.h"
-+#include "stf_vin.h"
-+
-+#define STF_PAD_SINK   0
-+#define STF_PAD_SRC    1
-+#define STF_PADS_NUM   2
-+
-+#define STF_CAMSS_SKIP_ITI
-+
-+enum port_num {
-+      DVP_SENSOR_PORT_NUMBER = 0,
-+      CSI2RX_SENSOR_PORT_NUMBER
-+};
-+
-+enum stf_clk_num {
-+      STFCLK_APB_FUNC = 0,
-+      STFCLK_PCLK,
-+      STFCLK_SYS_CLK,
-+      STFCLK_WRAPPER_CLK_C,
-+      STFCLK_DVP_INV,
-+      STFCLK_AXIWR,
-+      STFCLK_MIPI_RX0_PXL,
-+      STFCLK_PIXEL_CLK_IF0,
-+      STFCLK_PIXEL_CLK_IF1,
-+      STFCLK_PIXEL_CLK_IF2,
-+      STFCLK_PIXEL_CLK_IF3,
-+      STFCLK_M31DPHY_CFGCLK_IN,
-+      STFCLK_M31DPHY_REFCLK_IN,
-+      STFCLK_M31DPHY_TXCLKESC_LAN0,
-+      STFCLK_ISPCORE_2X,
-+      STFCLK_ISP_AXI,
-+      STFCLK_NUM
-+};
-+
-+enum stf_rst_num {
-+      STFRST_WRAPPER_P = 0,
-+      STFRST_WRAPPER_C,
-+      STFRST_PCLK,
-+      STFRST_SYS_CLK,
-+      STFRST_AXIRD,
-+      STFRST_AXIWR,
-+      STFRST_PIXEL_CLK_IF0,
-+      STFRST_PIXEL_CLK_IF1,
-+      STFRST_PIXEL_CLK_IF2,
-+      STFRST_PIXEL_CLK_IF3,
-+      STFRST_M31DPHY_HW,
-+      STFRST_M31DPHY_B09_ALWAYS_ON,
-+      STFRST_ISP_TOP_N,
-+      STFRST_ISP_TOP_AXI,
-+      STFRST_NUM
-+};
-+
-+struct stfcamss {
-+      struct stf_vin_dev *vin;  // stfcamss phy res
-+      struct v4l2_device v4l2_dev;
-+      struct media_device media_dev;
-+      struct media_pipeline pipe;
-+      struct device *dev;
-+      struct stf_vin2_dev *vin_dev;  // subdev
-+      struct stf_dvp_dev *dvp_dev;   // subdev
-+      struct stf_csi_dev *csi_dev;   // subdev
-+      struct stf_csiphy_dev *csiphy_dev;   // subdev
-+      struct stf_isp_dev *isp_dev;   // subdev
-+      struct v4l2_async_notifier notifier;
-+      struct clk_bulk_data *sys_clk;
-+      int nclks;
-+      struct reset_control_bulk_data *sys_rst;
-+      int nrsts;
-+      struct regmap *stf_aon_syscon;
-+      uint32_t aon_gp_reg;
-+#ifdef CONFIG_DEBUG_FS
-+      struct dentry *debugfs_entry;
-+      struct dentry *vin_debugfs;
-+#endif
-+};
-+
-+struct stfcamss_async_subdev {
-+      struct v4l2_async_connection asd;  // must be first
-+      enum port_num port;
-+      struct {
-+              struct dvp_cfg dvp;
-+              struct csi2phy_cfg csiphy;
-+      } interface;
-+};
-+
-+extern struct media_entity *stfcamss_find_sensor(struct media_entity *entity);
-+
-+#endif /* STFCAMSS_H */
---- /dev/null
-+++ b/include/uapi/linux/jh7110-isp.h
-@@ -0,0 +1,253 @@
-+/* SPDX-License-Identifier: ((GPL-2.0+ WITH Linux-syscall-note) OR BSD-3-Clause) */
-+/*
-+ * jh7110-isp.h
-+ *
-+ * JH7110 ISP driver - user space header file.
-+ *
-+ * Copyright Â© 2023 Starfive Technology Co., Ltd.
-+ *
-+ * Author: Su Zejian (zejian.su@starfivetech.com)
-+ *
-+ */
-+
-+#ifndef __JH7110_ISP_H_
-+#define __JH7110_ISP_H_
-+
-+#include <linux/v4l2-controls.h>
-+
-+#define V4L2_CID_USER_JH7110_ISP_WB_SETTING   \
-+                              (V4L2_CID_USER_JH7110_ISP_BASE + 0x0001)
-+#define V4L2_CID_USER_JH7110_ISP_CAR_SETTING  \
-+                              (V4L2_CID_USER_JH7110_ISP_BASE + 0x0002)
-+#define V4L2_CID_USER_JH7110_ISP_CCM_SETTING  \
-+                              (V4L2_CID_USER_JH7110_ISP_BASE + 0x0003)
-+#define V4L2_CID_USER_JH7110_ISP_CFA_SETTING          \
-+                              (V4L2_CID_USER_JH7110_ISP_BASE + 0x0004)
-+#define V4L2_CID_USER_JH7110_ISP_CTC_SETTING          \
-+                              (V4L2_CID_USER_JH7110_ISP_BASE + 0x0005)
-+#define V4L2_CID_USER_JH7110_ISP_DBC_SETTING  \
-+                              (V4L2_CID_USER_JH7110_ISP_BASE + 0x0006)
-+#define V4L2_CID_USER_JH7110_ISP_DNYUV_SETTING        \
-+                              (V4L2_CID_USER_JH7110_ISP_BASE + 0x0007)
-+#define V4L2_CID_USER_JH7110_ISP_GMARGB_SETTING               \
-+                              (V4L2_CID_USER_JH7110_ISP_BASE + 0x0008)
-+#define V4L2_CID_USER_JH7110_ISP_LCCF_SETTING \
-+                              (V4L2_CID_USER_JH7110_ISP_BASE + 0x0009)
-+#define V4L2_CID_USER_JH7110_ISP_OBC_SETTING  \
-+                              (V4L2_CID_USER_JH7110_ISP_BASE + 0x000a)
-+#define V4L2_CID_USER_JH7110_ISP_OECF_SETTING \
-+                              (V4L2_CID_USER_JH7110_ISP_BASE + 0x000b)
-+#define V4L2_CID_USER_JH7110_ISP_R2Y_SETTING  \
-+                              (V4L2_CID_USER_JH7110_ISP_BASE + 0x000c)
-+#define V4L2_CID_USER_JH7110_ISP_SAT_SETTING          \
-+                              (V4L2_CID_USER_JH7110_ISP_BASE + 0x000d)
-+#define V4L2_CID_USER_JH7110_ISP_SHRP_SETTING         \
-+                              (V4L2_CID_USER_JH7110_ISP_BASE + 0x000e)
-+#define V4L2_CID_USER_JH7110_ISP_YCRV_SETTING \
-+                              (V4L2_CID_USER_JH7110_ISP_BASE + 0x000f)
-+
-+struct jh7110_isp_wb_gain {
-+      __u16 gain_r;
-+      __u16 gain_g;
-+      __u16 gain_b;
-+};
-+
-+struct jh7110_isp_wb_setting {
-+      __u32 enabled;
-+      struct jh7110_isp_wb_gain gains;
-+};
-+
-+struct jh7110_isp_car_setting {
-+      __u32 enabled;
-+};
-+
-+struct jh7110_isp_ccm_smlow {
-+      __s32 ccm[3][3];
-+      __s32 offsets[3];
-+};
-+
-+struct jh7110_isp_ccm_setting {
-+      __u32 enabled;
-+      struct jh7110_isp_ccm_smlow ccm_smlow;
-+};
-+
-+struct jh7110_isp_cfa_params {
-+      __s32 hv_width;
-+      __s32 cross_cov;
-+};
-+
-+struct jh7110_isp_cfa_setting {
-+      __u32 enabled;
-+      struct jh7110_isp_cfa_params settings;
-+};
-+
-+struct jh7110_isp_ctc_params {
-+      __u8 saf_mode;
-+      __u8 daf_mode;
-+      __s32 max_gt;
-+      __s32 min_gt;
-+};
-+
-+struct jh7110_isp_ctc_setting {
-+      __u32 enabled;
-+      struct jh7110_isp_ctc_params settings;
-+};
-+
-+struct jh7110_isp_dbc_params {
-+      __s32 bad_gt;
-+      __s32 bad_xt;
-+};
-+
-+struct jh7110_isp_dbc_setting {
-+      __u32 enabled;
-+      struct jh7110_isp_dbc_params settings;
-+};
-+
-+struct jh7110_isp_dnyuv_params {
-+      __u8 y_sweight[10];
-+      __u16 y_curve[7];
-+      __u8 uv_sweight[10];
-+      __u16 uv_curve[7];
-+};
-+
-+struct jh7110_isp_dnyuv_setting {
-+      __u32 enabled;
-+      struct jh7110_isp_dnyuv_params settings;
-+};
-+
-+struct jh7110_isp_gmargb_point {
-+      __u16 g_val;
-+      __u16 sg_val;
-+};
-+
-+struct jh7110_isp_gmargb_setting {
-+      __u32 enabled;
-+      struct jh7110_isp_gmargb_point curve[15];
-+};
-+
-+struct jh7110_isp_lccf_circle {
-+      __s16 center_x;
-+      __s16 center_y;
-+      __u8 radius;
-+};
-+
-+struct jh7110_isp_lccf_curve_param {
-+      __s16 f1;
-+      __s16 f2;
-+};
-+
-+struct jh7110_isp_lccf_setting {
-+      __u32 enabled;
-+      struct jh7110_isp_lccf_circle circle;
-+      struct jh7110_isp_lccf_curve_param r_param;
-+      struct jh7110_isp_lccf_curve_param gr_param;
-+      struct jh7110_isp_lccf_curve_param gb_param;
-+      struct jh7110_isp_lccf_curve_param b_param;
-+};
-+
-+struct jh7110_isp_blacklevel_win_size {
-+      __u32 width;
-+      __u32 height;
-+};
-+
-+struct jh7110_isp_blacklevel_gain {
-+      __u8 tl_gain;
-+      __u8 tr_gain;
-+      __u8 bl_gain;
-+      __u8 br_gain;
-+};
-+
-+struct jh7110_isp_blacklevel_offset {
-+      __u8 tl_offset;
-+      __u8 tr_offset;
-+      __u8 bl_offset;
-+      __u8 br_offset;
-+};
-+
-+struct jh7110_isp_blacklevel_setting {
-+      __u32 enabled;
-+      struct jh7110_isp_blacklevel_win_size win_size;
-+      struct jh7110_isp_blacklevel_gain gain[4];
-+      struct jh7110_isp_blacklevel_offset offset[4];
-+};
-+
-+struct jh7110_isp_oecf_point {
-+      __u16 x;
-+      __u16 y;
-+      __s16 slope;
-+};
-+
-+struct jh7110_isp_oecf_setting {
-+      __u32 enabled;
-+      struct jh7110_isp_oecf_point r_curve[16];
-+      struct jh7110_isp_oecf_point gr_curve[16];
-+      struct jh7110_isp_oecf_point gb_curve[16];
-+      struct jh7110_isp_oecf_point b_curve[16];
-+};
-+
-+struct jh7110_isp_r2y_matrix {
-+      __s16 m[9];
-+};
-+
-+struct jh7110_isp_r2y_setting {
-+      __u32 enabled;
-+      struct jh7110_isp_r2y_matrix matrix;
-+};
-+
-+struct jh7110_isp_sat_curve {
-+      __s16 yi_min;
-+      __s16 yo_ir;
-+      __s16 yo_min;
-+      __s16 yo_max;
-+};
-+
-+struct jh7110_isp_sat_hue_info {
-+      __s16 sin;
-+      __s16 cos;
-+};
-+
-+struct jh7110_isp_sat_info {
-+      __s16 gain_cmab;
-+      __s16 gain_cmad;
-+      __s16 threshold_cmb;
-+      __s16 threshold_cmd;
-+      __s16 offset_u;
-+      __s16 offset_v;
-+      __s16 cmsf;
-+};
-+
-+struct jh7110_isp_sat_setting {
-+      __u32 enabled;
-+      struct jh7110_isp_sat_curve curve;
-+      struct jh7110_isp_sat_hue_info hue_info;
-+      struct jh7110_isp_sat_info sat_info;
-+};
-+
-+struct jh7110_isp_sharp_weight {
-+      __u8 weight[15];
-+      __u32 recip_wei_sum;
-+};
-+
-+struct jh7110_isp_sharp_strength {
-+      __s16 diff[4];
-+      __s16 f[4];
-+};
-+
-+struct jh7110_isp_sharp_setting {
-+      __u32 enabled;
-+      struct jh7110_isp_sharp_weight weight;
-+      struct jh7110_isp_sharp_strength strength;
-+      __s8 pdirf;
-+      __s8 ndirf;
-+};
-+
-+struct jh7110_isp_ycrv_curve {
-+      __s16 y[64];
-+};
-+
-+struct jh7110_isp_ycrv_setting {
-+      __u32 enabled;
-+      struct jh7110_isp_ycrv_curve curve;
-+};
-+
-+#endif
---- a/include/uapi/linux/v4l2-controls.h
-+++ b/include/uapi/linux/v4l2-controls.h
-@@ -203,6 +203,12 @@ enum v4l2_colorfx {
-  */
- #define V4L2_CID_USER_ASPEED_BASE             (V4L2_CID_USER_BASE + 0x11a0)
-+/*
-+ * The base for the jh7110-isp driver controls.
-+ * We reserve 16 controls for this driver.
-+ */
-+#define V4L2_CID_USER_JH7110_ISP_BASE         (V4L2_CID_USER_BASE + 0x1170)
-+
- /* MPEG-class control IDs */
- /* The MPEG controls are applicable to all codec controls
-  * and the 'MPEG' part of the define is historical */
---- /dev/null
-+++ b/include/video/stf-vin.h
-@@ -0,0 +1,443 @@
-+/* include/video/stf-vin.h
-+ *
-+ * Copyright 2020 starfive tech.
-+ *    Eric Tang <eric.tang@starfivetech.com>
-+ *
-+ * Generic vin notifier interface
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License version 2 as
-+ * published by the Free Software Foundation.
-+ *
-+*/
-+#ifndef _VIDEO_VIN_H
-+#define _VIDEO_VIN_H
-+
-+#include <linux/cdev.h>
-+
-+#define DRV_NAME "jh7110-vin"
-+#define FB_FIRST_ADDR      0xf9000000
-+#define FB_SECOND_ADDR     0xf97e9000
-+
-+#define RESERVED_MEM_SIZE  0x1000000
-+
-+#define VIN_MIPI_CONTROLLER0_OFFSET 0x00000
-+#define VIN_CLKGEN_OFFSET           0x10000
-+#define VIN_RSTGEN_OFFSET           0x20000
-+#define VIN_MIPI_CONTROLLER1_OFFSET 0x30000
-+#define VIN_SYSCONTROLLER_OFFSET    0x40000
-+
-+#define VD_1080P    1080
-+#define VD_720P     720
-+#define VD_PAL      480
-+
-+#define VD_HEIGHT_1080P     VD_1080P
-+#define VD_WIDTH_1080P      1920
-+
-+#define VD_HEIGHT_720P      VD_720P
-+#define VD_WIDTH_720P       1080
-+
-+#define VD_HEIGHT_480       480
-+#define VD_WIDTH_640        640
-+
-+#define SEEED_WIDTH_800       800
-+#define SEEED_HIGH_480        480
-+
-+#define VIN_TOP_CLKGEN_BASE_ADDR          0x11800000
-+#define VIN_TOP_RSTGEN_BASE_ADDR          0x11840000
-+#define VIN_TOP_IOPAD_BASE_ADDR               0x11858000
-+
-+#define ISP_BASE_MIPI0_ADDR             0x19800000
-+#define ISP_BASE_CLKGEN_ADDR            0x19810000
-+#define ISP_BASE_RSTGEN_ADDR            0x19820000
-+#define ISP_BASE_MIPI1_ADDR             0x19830000
-+#define ISP_BASE_SYSCTRL_ADDR         0x19840000
-+#define ISP_BASE_ISP0_ADDR                0x19870000
-+#define ISP_BASE_ISP1_ADDR                0x198a0000
-+
-+
-+//vin clk registers
-+#define CLK_VIN_SRC_CTRL                  0x188
-+#define CLK_ISP0_AXI_CTRL                 0x190
-+#define CLK_ISP0NOC_AXI_CTRL      0x194
-+#define CLK_ISPSLV_AXI_CTRL               0x198
-+#define CLK_ISP1_AXI_CTRL                 0x1A0
-+#define CLK_ISP1NOC_AXI_CTRL      0x1A4
-+#define CLK_VIN_AXI                       0x1AC
-+#define CLK_VINNOC_AXI                        0x1B0
-+
-+
-+#define CLK_DOM4_APB_FUNC                     0x0
-+#define CLK_MUX_SEL                                   0xffffff
-+
-+#define CLK_MIPI_RX0_PXL            0x4
-+
-+#define CLK_DVP_INV                                   0x8
-+#define CLK_U0_VIN_PCLK                               0x18
-+#define CLK_U0_VIN_PCLK_ICG                                           (0x1<<31)
-+
-+#define CLK_U0_VIN_SYS_CLK                    0x1c
-+#define CLK_U0_VIN_CLK_P_AXIWR                0x30
-+#define CLK_U0_VIN_MUX_SEL                    (BIT(24) | BIT(25) | BIT(26) | BIT(27) | BIT(28) | BIT(29))
-+
-+#define CLK_U0_VIN_PIXEL_CLK_IF0    0x20
-+#define CLK_U0_VIN_PIXEL_CLK_IF1    0x24
-+#define CLK_U0_VIN_PIXEL_CLK_IF2    0x28
-+#define CLK_U0_VIN_PIXEL_CLK_IF3    0x2c
-+
-+#define CLK_U0_VIN_CLK_P_AXIWR      0x30
-+
-+#define CLK_U0_ISPV2_TOP_WRAPPER_CLK_C        0x34u
-+#define CLK_U0_ISPV2_MUX_SEL          (0x1<<24 | 0x1<<25 | 0x1<<26 | 0x1<<27 | 0x1<<28 | 0x1<< 29)
-+
-+#define CLK_U0_ISPV2_CLK_ICG                                          (0x1<<31)
-+
-+#define SOFTWARE_RESET_ASSERT0_ASSERT_SET 0x38U
-+#define SOFTWARE_RESET_ASSERT0_ASSERT_SET_STATE 0x3CU
-+#define RST_U0_ISPV2_TOP_WRAPPER_RST_P        BIT(0)
-+#define RST_U0_ISPV2_TOP_WRAPPER_RST_C        BIT(1)
-+#define RSTN_U0_VIN_RST_N_PCLK        BIT(4)
-+#define RSTN_U0_VIN_RST_N_SYS_CLK     BIT(9)
-+#define RSTN_U0_VIN_RST_P_AXIRD       BIT(10)
-+#define RSTN_U0_VIN_RST_P_AXIWR       BIT(11)
-+
-+
-+#define CLK_POLARITY                          (0x1<<30)
-+
-+#define M31DPHY_APBCFGSAIF__SYSCFG_0  0x0
-+#define M31DPHY_APBCFGSAIF__SYSCFG_4  0x4
-+#define M31DPHY_APBCFGSAIF__SYSCFG_8  0x8
-+#define M31DPHY_APBCFGSAIF__SYSCFG_12 0xc
-+#define M31DPHY_APBCFGSAIF__SYSCFG_16 0x10
-+#define M31DPHY_APBCFGSAIF__SYSCFG_20 0x14
-+#define M31DPHY_APBCFGSAIF__SYSCFG_24 0x18
-+#define M31DPHY_APBCFGSAIF__SYSCFG_28 0x1c
-+#define M31DPHY_APBCFGSAIF__SYSCFG_32 0x20
-+#define M31DPHY_APBCFGSAIF__SYSCFG_36 0x24
-+#define M31DPHY_APBCFGSAIF__SYSCFG_40 0x28
-+#define M31DPHY_APBCFGSAIF__SYSCFG_44 0x2c
-+#define M31DPHY_APBCFGSAIF__SYSCFG_48 0x30
-+#define M31DPHY_APBCFGSAIF__SYSCFG_52 0x34
-+#define M31DPHY_APBCFGSAIF__SYSCFG_56 0x38
-+#define M31DPHY_APBCFGSAIF__SYSCFG_60 0x3c
-+#define M31DPHY_APBCFGSAIF__SYSCFG_64 0x40
-+#define M31DPHY_APBCFGSAIF__SYSCFG_68 0x44
-+#define M31DPHY_APBCFGSAIF__SYSCFG_72 0x48
-+#define M31DPHY_APBCFGSAIF__SYSCFG_76 0x4c
-+#define M31DPHY_APBCFGSAIF__SYSCFG_80 0x50
-+#define M31DPHY_APBCFGSAIF__SYSCFG_84 0x54
-+#define M31DPHY_APBCFGSAIF__SYSCFG_88 0x58
-+#define M31DPHY_APBCFGSAIF__SYSCFG_92 0x5c
-+#define M31DPHY_APBCFGSAIF__SYSCFG_96 0x60
-+#define M31DPHY_APBCFGSAIF__SYSCFG_100        0x64
-+#define M31DPHY_APBCFGSAIF__SYSCFG_104        0x68
-+#define M31DPHY_APBCFGSAIF__SYSCFG_108        0x6c
-+#define M31DPHY_APBCFGSAIF__SYSCFG_112        0x70
-+#define M31DPHY_APBCFGSAIF__SYSCFG_116        0x74
-+#define M31DPHY_APBCFGSAIF__SYSCFG_120        0x78
-+#define M31DPHY_APBCFGSAIF__SYSCFG_124        0x7c
-+#define M31DPHY_APBCFGSAIF__SYSCFG_128        0x80
-+#define M31DPHY_APBCFGSAIF__SYSCFG_132        0x84
-+#define M31DPHY_APBCFGSAIF__SYSCFG_136        0x88
-+#define M31DPHY_APBCFGSAIF__SYSCFG_140        0x8c
-+#define M31DPHY_APBCFGSAIF__SYSCFG_144        0x90
-+#define M31DPHY_APBCFGSAIF__SYSCFG_184        0xb8
-+
-+//pmu registers
-+#define SW_DEST_POWER_ON                      0x0C
-+#define SW_DEST_POWER_OFF                     0x10
-+#define SW_ENCOURAGE                          0x44
-+
-+
-+//isp clk registers
-+#define CLK_DPHY_CFGCLK_ISPCORE_2X_CTRL    0x00
-+#define CLK_DPHY_REFCLK_ISPCORE_2X_CTRL    0x04
-+#define CLK_DPHY_TXCLKESC_IN_CTRL          0x08
-+#define CLK_MIPI_RX0_PXL_CTRL       0x0c
-+#define CLK_MIPI_RX1_PXL_CTRL       0x10
-+#define CLK_MIPI_RX0_PXL_0_CTRL     0X14
-+#define CLK_MIPI_RX0_PXL_1_CTRL     0X18
-+#define CLK_MIPI_RX0_PXL_2_CTRL     0X1C
-+#define CLK_MIPI_RX0_PXL_3_CTRL     0X20
-+#define CLK_MIPI_RX0_SYS0_CTRL      0x24
-+#define CLK_MIPI_RX1_PXL_0_CTRL     0X28
-+#define CLK_MIPI_RX1_PXL_1_CTRL     0X2C
-+#define CLK_MIPI_RX1_PXL_2_CTRL     0X30
-+#define CLK_MIPI_RX1_PXL_3_CTRL     0X34
-+#define CLK_MIPI_RX1_SYS1_CTRL      0x38
-+#define CLK_ISP_CTRL               0x3c
-+#define CLK_ISP_2X_CTRL            0x40
-+#define CLK_ISP_MIPI_CTRL          0x44
-+#define CLK_C_ISP_CTRL             0x64
-+#define CLK_CSI2RX0_APB_CTRL        0x58
-+
-+
-+#define CLK_VIN_AXI_WR_CTRL         0x5C
-+
-+#define SOFTWARE_RESET_ASSERT0                0x0
-+#define SOFTWARE_RESET_ASSERT1                0x4
-+#define SOFTWARE_RESET_STATUS         0x4
-+
-+#define IOPAD_REG81                   0x144
-+#define IOPAD_REG82                   0x148
-+#define IOPAD_REG83                   0x14C
-+#define IOPAD_REG84                   0x150
-+#define IOPAD_REG85                   0x154
-+#define IOPAD_REG86                   0x158
-+#define IOPAD_REG87               0x15C
-+#define IOPAD_REG88               0x160
-+#define IOPAD_REG89               0x164
-+
-+//sys control REG DEFINE
-+#define SYSCONSAIF_SYSCFG_0                                           0X0
-+#define U0_VIN_SCFG_SRAM_CONFIG     (BIT(0) | BIT(1))
-+
-+#define SYSCONSAIF_SYSCFG_4                   0x4
-+#define U0_VIN_CNFG_AXIRD_END_ADDR 0xffffffff
-+#define SYSCONSAIF_SYSCFG_8                   0x8
-+#define U0_VIN_CNFG_AXIRD_LINE_CNT_END (BIT(2) | BIT(3) | BIT(4) | BIT(5) | BIT(6) | BIT(7) | BIT(8) | BIT(9) | BIT(10) | BIT(11) | BIT(12) | BIT(13))
-+#define U0_VIN_CNFG_AXIRD_LINE_CNT_START (BIT(14) | BIT(15) | BIT(16) | BIT(17) | BIT(18) | BIT(19) | BIT(20) | BIT(21) | BIT(22) | BIT(23) | BIT(24) | BIT(25))
-+#define SYSCONSAIF_SYSCFG_12          0xc
-+#define U0_VIN_CNFG_AXIRD_PIX_CNT_END  (BIT(0) | BIT(1) | BIT(2) | BIT(3) | BIT(4) | BIT(5) | BIT(6) | BIT(7) | BIT(8) | BIT(9) | BIT(10) | BIT(11) | BIT(12))
-+#define U0_VIN_CNFG_AXIRD_PIX_CNT_START (BIT(13) | BIT(14) | BIT(15) | BIT(16) | BIT(17) | BIT(18) | BIT(19) | BIT(20) | BIT(21) | BIT(22) | BIT(23) | BIT(24) | BIT(25))
-+#define U0_VIN_CNFG_AXIRD_PIX_CT      (BIT(26) | BIT(27))
-+#define SYSCONSAIF_SYSCFG_16          0x10
-+#define U0_VIN_CNFG_AXIRD_START_ADDR 0xFFFFFFFF
-+#define SYSCONSAIF_SYSCFG_20          0x14
-+#define U0_VIN_CNFG_AXIWR0_EN         BIT(4)
-+#define U0_VIN_CNFG_AXIWR0_CHANNEL_SEL (BIT(0) | BIT(1) | BIT(2) | BIT(3))
-+#define SYSCONSAIF_SYSCFG_24          0x18
-+#define U0_VIN_CNFG_AXIWR0_END_ADDR 0xFFFFFFFF
-+
-+#define SYSCONSAIF_SYSCFG_28          0x1c
-+#define U0_VIN_CNFG_AXIWR0_INTR_CLEAN BIT(0)
-+#define U0_VIN_CNFG_AXIWR0_MASK               BIT(1)
-+#define U0_VIN_CNFG_AXIWR0_PIX_CNT_END (BIT(2) | BIT(3) | BIT(4) | BIT(5) | BIT(6) | BIT(7) | BIT(8) | BIT(9) | BIT(10) | BIT(11) | BIT(12))
-+#define U0_VIN_CNFG_AXIWR0_PIX_CT (BIT(13) | BIT(14))
-+#define UO_VIN_CNFG_AXIWR0_PIXEL_HEIGH_BIT_SEL (BIT(15) | BIT(16))
-+#define SYSCONSAIF_SYSCFG_32          0x20
-+
-+#define SYSCONSAIF_SYSCFG_36                  0x24
-+#define UO_VIN_CNFG_COLOR_BAR_EN      BIT(0)
-+#define U0_VIN_CNFG_DVP_HS_POS                (0x1<<1)
-+#define U0_VIN_CNFG_DVP_SWAP_EN               BIT(2)
-+#define U0_VIN_CNFG_DVP_VS_POS                (0x1<<3)
-+#define U0_VIN_CNFG_GEN_EN_AXIRD      BIT(4)
-+#define U0_VIN_CNFG_ISP_DVP_EN0               BIT(5)
-+#define U0_VIN_CNFG_MIPI_BYTE_EN_ISP0 (BIT(6) |BIT(7))
-+#define U0_VIN_CNFG_P_I_MIPI_CHANNEL_SEL0     (BIT(8) |BIT(9) | BIT(10) | BIT(11))
-+#define U0_VIN_CNFG_P_I_MIPI_HEADER_EN0 BIT(12)
-+
-+#define U0_VIN_CNFG_PIX_NUM                   (0x1<<13 | 0x1<<14 | 0x1<<15 | 0x1<<16)
-+#define U0_VIN_CNFG_AXIRD_AXI_CNT_END (BIT(3) | BIT(4) | BIT(5) | BIT(6) | BIT(7) | BIT(8) | BIT(9) | BIT(10) | BIT(11) | BIT(12) | BIT(13))
-+
-+#define U0_VIN_CNFG_AXI_DVP_EN                BIT(2)
-+#define U0_VIN_CNFG_AXIRD_INTR_MASK   BIT(1)
-+#define U0_VIN_CNFG_AXIWRD_INTR_MASK  BIT(1)
-+#define U0_VIN_CNFG_AXIWR0_START_ADDR 0xffffffff
-+#define U0_VIN_CNFG_COLOR_BAR_EN      0X0
-+#define U0_VIN_CNFG_AXIWR0_PIX_CNT_CT (BIT(13) | BIT(14))
-+#define U0_VIN_CNFG_AXIWR0_PIX_CNT_CNT_END (BIT(2) | BIT(3) | BIT(4) | BIT(5) | BIT(6) | BIT(7) | BIT(8) | BIT(9) | BIT(10) | BIT(11) | BIT(12))
-+#define U0_VIN_CNFG_AXIWR0_PIXEL_HITH_BIT_SEL (BIT(15) | BIT(16))
-+
-+#define SYSCTRL_REG4              0x10
-+#define SYSCTRL_DPHY_CTRL             0x14
-+#define SYSCTRL_VIN_AXI_CTRL      0x18
-+#define SYSCTRL_VIN_WR_START_ADDR     0x28
-+#define SYSCTRL_VIN_RD_END_ADDR           0x2C
-+#define SYSCTRL_VIN_WR_PIX_TOTAL      0x30
-+#define SYSCTRL_VIN_RD_PIX_TOTAL      0x34
-+#define SYSCTRL_VIN_RW_CTRL           0x38
-+#define SYSCTRL_VIN_SRC_CHAN_SEL      0x24
-+#define SYSCTRL_VIN_SRC_DW_SEL            0x40
-+#define SYSCTRL_VIN_RD_VBLANK     0x44
-+#define SYSCTRL_VIN_RD_VEND           0x48
-+#define SYSCTRL_VIN_RD_HBLANK     0x4C
-+#define SYSCTRL_VIN_RD_HEND           0x50
-+#define SYSCTRL_VIN_INTP_CTRL     0x54
-+
-+#define ISP_NO_SCALE_ENABLE     (0x1<<20)
-+#define ISP_MULTI_FRAME_ENABLE  (0x1<<17)
-+#define ISP_SS0_ENABLE          (0x1<<11)
-+#define ISP_SS1_ENABLE          (0x1<<12)
-+#define ISP_RESET               (0x1<<1)
-+#define ISP_ENBALE              (0x1)
-+
-+
-+
-+ //ISP REG DEFINE
-+#define ISP_REG_DVP_POLARITY_CFG            0x00000014
-+#define ISP_REG_RAW_FORMAT_CFG              0x00000018
-+#define ISP_REG_CFA_MODE                    0x00000A1C
-+#define ISP_REG_PIC_CAPTURE_START_CFG       0x0000001C
-+#define ISP_REG_PIC_CAPTURE_END_CFG         0x00000020
-+#define ISP_REG_PIPELINE_XY_SIZE            0x00000A0C
-+#define ISP_REG_Y_PLANE_START_ADDR          0x00000A80
-+#define ISP_REG_UV_PLANE_START_ADDR         0x00000A84
-+#define ISP_REG_STRIDE                      0x00000A88
-+#define ISP_REG_PIXEL_COORDINATE_GEN        0x00000A8C
-+#define ISP_REG_PIXEL_AXI_CONTROL           0x00000A90
-+#define ISP_REG_SS_AXI_CONTROL              0x00000AC4
-+#define ISP_REG_RGB_TO_YUV_COVERSION0       0x00000E40
-+#define ISP_REG_RGB_TO_YUV_COVERSION1       0x00000E44
-+#define ISP_REG_RGB_TO_YUV_COVERSION2       0x00000E48
-+#define ISP_REG_RGB_TO_YUV_COVERSION3       0x00000E4C
-+#define ISP_REG_RGB_TO_YUV_COVERSION4       0x00000E50
-+#define ISP_REG_RGB_TO_YUV_COVERSION5       0x00000E54
-+#define ISP_REG_RGB_TO_YUV_COVERSION6       0x00000E58
-+#define ISP_REG_RGB_TO_YUV_COVERSION7       0x00000E5C
-+#define ISP_REG_RGB_TO_YUV_COVERSION8       0x00000E60
-+#define ISP_REG_CSI_MODULE_CFG              0x00000010
-+#define ISP_REG_ISP_CTRL_1                  0x00000A08
-+#define ISP_REG_ISP_CTRL_0                  0x00000A00
-+#define ISP_REG_DC_AXI_ID                   0x00000044
-+#define ISP_REG_CSI_INPUT_EN_AND_STATUS     0x00000000
-+
-+//CSI registers
-+#define DEVICE_CONFIG           0x00
-+#define SOFT_RESET              0x04
-+#define STATIC_CFG              0x08
-+#define ERROR_BYPASS_CFG        0x10
-+#define MONITOR_IRQS            0x18
-+#define MONITOR_IRQS_MASK_CFG   0x1c
-+#define INFO_IRQS               0x20
-+#define INFO_IRQS_MASK_CFG      0x24
-+#define ERROR_IRQS              0x28
-+#define ERROR_IRQS_MASK_CFG     0x2c
-+#define DPHY_LANE_CONTROL       0x40
-+#define DPHY_STATUS             0x48
-+#define DPHY_ERR_STATUS_IRQ     0x4C
-+#define DPHY_ERR_IRQ_MASK_CFG   0x50
-+#define INTEGRATION_DEBUG       0x60
-+#define ERROR_DEBUG             0x74
-+
-+#define STREAM0_CTRL            0x100
-+#define STREAM0_STATUS          0x104
-+#define STREAM0_DATA_CFG        0x108
-+#define STREAM0_CFG             0x10c
-+#define STREAM0_MONITOR_CTRL    0x110
-+#define STREAM0_MONITOR_FRAME   0x114
-+#define STREAM0_MONITOR_LB      0x118
-+#define STREAM0_TIMER           0x11c
-+#define STREAM0_FCC_CFG         0x120
-+#define STREAM0_FCC_CTRL        0x124
-+#define STREAM0_FIFO_FILL_LVL   0x128
-+
-+//m31_dphy registers
-+#define M31DPHY_APBCFGSAIF__SYSCFG_188      0xbc
-+#define M31DPHY_APBCFGSAIF__SYSCFG_192      0xc0
-+#define M31DPHY_APBCFGSAIF__SYSCFG_196      0xc4
-+#define M31DPHY_APBCFGSAIF__SYSCFG_200      0xc8
-+
-+typedef enum
-+{
-+    DT_RAW6  = 0x28,
-+    DT_RAW7  = 0x29,
-+    DT_RAW8  = 0x2a,
-+    DT_RAW10 = 0x2b,
-+    DT_RAW12 = 0x2c,
-+    DT_RAW14 = 0x2d,
-+} mipicam_data_type_t;
-+
-+
-+enum VIN_SOURCE_FORMAT {
-+      SRC_COLORBAR_VIN_ISP = 0,
-+      SRC_DVP_SENSOR_VIN,
-+      SRC_DVP_SENSOR_VIN_ISP,//need replace sensor
-+      SRC_CSI2RX_VIN_ISP,
-+      SRC_DVP_SENSOR_VIN_OV5640,
-+};
-+
-+struct reg_name {
-+      char name[10];
-+};
-+
-+typedef struct
-+{
-+    int dlane_nb;
-+    int dlane_map[4];
-+    int dlane_en[4];
-+    int dlane_pn_swap[4];
-+    int clane_nb;
-+    int clane_map[2];
-+    int clane_pn_swap[2];
-+} csi2rx_dphy_cfg_t;
-+
-+typedef struct
-+{
-+    int lane_nb;
-+    int dlane_map[4];
-+    int dt;
-+    int hsize;
-+    int vsize;
-+} csi2rx_cfg_t;
-+
-+
-+typedef struct
-+{
-+    int mipi_id, w, h, dt, bpp, fps,lane;
-+      u8  clane_swap;
-+    u8  clane_pn_swap;
-+    u8  dlane_swap[4];
-+    u8  dlane_pn_swap[4];
-+} csi_format;
-+
-+struct vin_params {
-+      void *paddr;
-+      unsigned long size;
-+};
-+
-+struct vin_buf {
-+      void *vaddr;
-+      dma_addr_t paddr;
-+      u32 size;
-+};
-+
-+struct vin_framesize {
-+      u32 width;
-+      u32 height;
-+};
-+
-+struct vin_format {
-+      enum VIN_SOURCE_FORMAT format;
-+      u8 fps;
-+};
-+
-+struct stf_vin_dev {
-+      /* Protects the access of variables shared within the interrupt */
-+      spinlock_t irqlock;
-+      int irq;
-+      struct device *dev;
-+      struct cdev vin_cdev;
-+      void __iomem *base;
-+      void __iomem *csi2rx_base;
-+      void __iomem *clkgen_base;
-+      void __iomem *rstgen_base;
-+      void __iomem *sysctrl_base;
-+      void __iomem *isp_base;
-+      void __iomem *vin_top_clkgen_base;
-+      void __iomem *vin_top_rstgen_base;
-+      void __iomem *vin_top_iopad_base;
-+      void __iomem *pmu_test;
-+      void __iomem *sys_crg;
-+      struct vin_framesize frame;
-+      struct vin_format format;
-+      bool isp;
-+      int isp_irq;
-+      int isp_csi_irq;
-+      int isp_scd_irq;
-+      int isp_irq_csiline;
-+      u32 major;
-+      struct vin_buf buf;
-+
-+      wait_queue_head_t wq;
-+      bool condition;
-+      int odd;
-+
-+      csi_format csi_fmt;
-+};
-+
-+extern int vin_notifier_register(struct notifier_block *nb);
-+extern void vin_notifier_unregister(struct notifier_block *nb);
-+extern int vin_notifier_call(unsigned long e, void *v);
-+#endif
diff --git a/target/linux/starfive/patches-6.6/0086-dt-bindings-media-i2c-Add-IMX708-CMOS-sensor-binding.patch b/target/linux/starfive/patches-6.6/0086-dt-bindings-media-i2c-Add-IMX708-CMOS-sensor-binding.patch
deleted file mode 100644 (file)
index c2a97a1..0000000
+++ /dev/null
@@ -1,135 +0,0 @@
-From baec350a0994467584e7e390746e0bb365957a89 Mon Sep 17 00:00:00 2001
-From: Changhuang Liang <changhuang.liang@starfivetech.com>
-Date: Tue, 13 Jun 2023 16:55:23 +0800
-Subject: [PATCH 086/116] dt-bindings: media: i2c: Add IMX708 CMOS sensor
- binding
-
-Add YAML devicetree binding for IMX708 CMOS image sensor.
-Let's also add a MAINTAINERS entry for the binding and driver.
-
-Signed-off-by: Changhuang Liang <changhuang.liang@starfivetech.com>
----
- .../devicetree/bindings/media/i2c/imx708.yaml | 117 ++++++++++++++++++
- 1 file changed, 117 insertions(+)
- create mode 100644 Documentation/devicetree/bindings/media/i2c/imx708.yaml
-
---- /dev/null
-+++ b/Documentation/devicetree/bindings/media/i2c/imx708.yaml
-@@ -0,0 +1,117 @@
-+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
-+%YAML 1.2
-+---
-+$id: http://devicetree.org/schemas/media/i2c/imx708.yaml#
-+$schema: http://devicetree.org/meta-schemas/core.yaml#
-+
-+title: Sony 1/2.3-Inch 12Mpixel CMOS Digital Image Sensor
-+
-+maintainers:
-+  - Raspberry Pi Kernel Maintenance <kernel-list@raspberrypi.om>
-+
-+description: |-
-+  The Sony IMX708 is a 1/2.3-inch CMOS active pixel digital mage sensor
-+  with an active array size of 4608H x 2592V. It is rogrammable through
-+  I2C interface. The I2C address is fixed to 0x1A as per ensor data sheet.
-+  Image data is sent through MIPI CSI-2, which is configured s either 2 or
-+  4 data lanes.
-+
-+properties:
-+  compatible:
-+    const: sony,imx708
-+
-+  reg:
-+    description: I2C device address
-+    maxItems: 1
-+
-+  clocks:
-+    maxItems: 1
-+
-+  VDIG-supply:
-+    description:
-+      Digital I/O voltage supply, 1.1 volts
-+
-+  VANA1-supply:
-+    description:
-+      Analog1 voltage supply, 2.8 volts
-+
-+  VANA2-supply:
-+    description:
-+      Analog2 voltage supply, 1.8 volts
-+
-+  VDDL-supply:
-+    description:
-+      Digital core voltage supply, 1.8 volts
-+
-+  reset-gpios:
-+    description: |-
-+      Reference to the GPIO connected to the xclr pin, if any.
-+      Must be released (set high) after all supplies and INCK re applied.
-+
-+  # See ../video-interfaces.txt for more details
-+  port:
-+    type: object
-+    properties:
-+      endpoint:
-+        type: object
-+        properties:
-+          data-lanes:
-+            description: |-
-+              The sensor supports either two-lane, or our-lane operation.
-+              For two-lane operation the property must be set o <1 2>.
-+            items:
-+              - const: 1
-+              - const: 2
-+
-+          clock-noncontinuous:
-+            type: boolean
-+            description: |-
-+              MIPI CSI-2 clock is non-continuous if this roperty is present,
-+              otherwise it's continuous.
-+
-+          link-frequencies:
-+            allOf:
-+              - $ref: /schemas/types.yaml#/definitions/int64-array
-+            description:
-+              Allowed data bus frequencies.
-+
-+        required:
-+          - link-frequencies
-+
-+required:
-+  - compatible
-+  - reg
-+  - clocks
-+  - VANA1-supply
-+  - VANA2-supply
-+  - VDIG-supply
-+  - VDDL-supply
-+  - port
-+
-+additionalProperties: false
-+
-+examples:
-+  - |
-+    i2c0 {
-+        #address-cells = <1>;
-+        #size-cells = <0>;
-+
-+        imx708: sensor@1a {
-+            compatible = "sony,imx708";
-+            reg = <0x1a>;
-+            clocks = <&imx708_clk>;
-+            VANA1-supply = <&imx708_vana1>; /* 1.8v */
-+            VANA2-supply = <&imx708_vana2>; /* 2.8v */
-+            VDIG-supply = <&imx708_vdig>;   /* 1.1v */
-+            VDDL-supply = <&imx708_vddl>;   /* 1.8v */
-+
-+            port {
-+                imx708_0: endpoint {
-+                    remote-endpoint = <&csi1_ep>;
-+                    data-lanes = <1 2>;
-+                    clock-noncontinuous;
-+                    link-frequencies = /bits/ 64 <450000000>;
-+                };
-+            };
-+        };
-+    };
diff --git a/target/linux/starfive/patches-6.6/0087-media-i2c-Add-imx708-support.patch b/target/linux/starfive/patches-6.6/0087-media-i2c-Add-imx708-support.patch
deleted file mode 100644 (file)
index 51e6181..0000000
+++ /dev/null
@@ -1,1971 +0,0 @@
-From e89556802c5d29a80f5887995ab257d4e826a90f Mon Sep 17 00:00:00 2001
-From: Changhuang Liang <changhuang.liang@starfivetech.com>
-Date: Mon, 3 Apr 2023 13:52:17 +0800
-Subject: [PATCH 087/116] media: i2c: Add imx708 support
-
-Add imx708 support.
-
-Signed-off-by: Changhuang Liang <changhuang.liang@starfivetech.com>
----
- drivers/media/i2c/Kconfig  |   13 +
- drivers/media/i2c/Makefile |    1 +
- drivers/media/i2c/imx708.c | 1921 ++++++++++++++++++++++++++++++++++++
- 3 files changed, 1935 insertions(+)
- create mode 100644 drivers/media/i2c/imx708.c
-
---- a/drivers/media/i2c/Kconfig
-+++ b/drivers/media/i2c/Kconfig
-@@ -201,6 +201,19 @@ config VIDEO_IMX415
-         To compile this driver as a module, choose M here: the
-         module will be called imx415.
-+config VIDEO_IMX708
-+      tristate "Sony IMX708 sensor support"
-+      depends on I2C && VIDEO_DEV
-+      select MEDIA_CONTROLLER
-+      select VIDEO_V4L2_SUBDEV_API
-+      select V4L2_FWNODE
-+      help
-+        This is a Video4Linux2 sensor driver for the Sony
-+        IMX708 camera.
-+
-+        To compile this driver as a module, choose M here: the
-+        module will be called imx708.
-+
- config VIDEO_MAX9271_LIB
-       tristate
---- a/drivers/media/i2c/Makefile
-+++ b/drivers/media/i2c/Makefile
-@@ -53,6 +53,7 @@ obj-$(CONFIG_VIDEO_IMX335) += imx335.o
- obj-$(CONFIG_VIDEO_IMX355) += imx355.o
- obj-$(CONFIG_VIDEO_IMX412) += imx412.o
- obj-$(CONFIG_VIDEO_IMX415) += imx415.o
-+obj-$(CONFIG_VIDEO_IMX708) += imx708.o
- obj-$(CONFIG_VIDEO_IR_I2C) += ir-kbd-i2c.o
- obj-$(CONFIG_VIDEO_ISL7998X) += isl7998x.o
- obj-$(CONFIG_VIDEO_KS0127) += ks0127.o
---- /dev/null
-+++ b/drivers/media/i2c/imx708.c
-@@ -0,0 +1,1921 @@
-+// SPDX-License-Identifier: GPL-2.0
-+/*
-+ * A V4L2 driver for Sony IMX708 cameras.
-+ * Copyright (C) 2022-2023, Raspberry Pi Ltd
-+ *
-+ * Based on Sony imx477 camera driver
-+ * Copyright (C) 2020 Raspberry Pi Ltd
-+ */
-+#include <asm/unaligned.h>
-+#include <linux/clk.h>
-+#include <linux/delay.h>
-+#include <linux/gpio/consumer.h>
-+#include <linux/i2c.h>
-+#include <linux/module.h>
-+#include <linux/pm_runtime.h>
-+#include <linux/regulator/consumer.h>
-+#include <media/v4l2-ctrls.h>
-+#include <media/v4l2-device.h>
-+#include <media/v4l2-event.h>
-+#include <media/v4l2-fwnode.h>
-+#include <media/v4l2-mediabus.h>
-+
-+#define IMX708_REG_VALUE_08BIT                1
-+#define IMX708_REG_VALUE_16BIT                2
-+
-+/* Chip ID */
-+#define IMX708_REG_CHIP_ID            0x0016
-+#define IMX708_CHIP_ID                        0x0708
-+
-+#define IMX708_REG_MODE_SELECT                0x0100
-+#define IMX708_MODE_STANDBY           0x00
-+#define IMX708_MODE_STREAMING         0x01
-+
-+#define IMX708_REG_ORIENTATION                0x101
-+
-+#define IMX708_XCLK_FREQ              24000000
-+
-+#define IMX708_DEFAULT_LINK_FREQ      450000000
-+
-+/* V_TIMING internal */
-+#define IMX708_REG_FRAME_LENGTH               0x0340
-+#define IMX708_FRAME_LENGTH_MAX               0xffff
-+
-+/* Long exposure multiplier */
-+#define IMX708_LONG_EXP_SHIFT_MAX     7
-+#define IMX708_LONG_EXP_SHIFT_REG     0x3100
-+
-+/* Exposure control */
-+#define IMX708_REG_EXPOSURE           0x0202
-+#define IMX708_EXPOSURE_OFFSET                48
-+#define IMX708_EXPOSURE_DEFAULT               0x640
-+#define IMX708_EXPOSURE_STEP          1
-+#define IMX708_EXPOSURE_MIN           1
-+#define IMX708_EXPOSURE_MAX           (IMX708_FRAME_LENGTH_MAX - \
-+                                       IMX708_EXPOSURE_OFFSET)
-+
-+/* Analog gain control */
-+#define IMX708_REG_ANALOG_GAIN                0x0204
-+#define IMX708_ANA_GAIN_MIN           112
-+#define IMX708_ANA_GAIN_MAX           960
-+#define IMX708_ANA_GAIN_STEP          1
-+#define IMX708_ANA_GAIN_DEFAULT               IMX708_ANA_GAIN_MIN
-+
-+/* Digital gain control */
-+#define IMX708_REG_DIGITAL_GAIN               0x020e
-+#define IMX708_DGTL_GAIN_MIN          0x0100
-+#define IMX708_DGTL_GAIN_MAX          0xffff
-+#define IMX708_DGTL_GAIN_DEFAULT      0x0100
-+#define IMX708_DGTL_GAIN_STEP         1
-+
-+/* Colour balance controls */
-+#define IMX708_REG_COLOUR_BALANCE_RED   0x0b90
-+#define IMX708_REG_COLOUR_BALANCE_BLUE        0x0b92
-+#define IMX708_COLOUR_BALANCE_MIN     0x01
-+#define IMX708_COLOUR_BALANCE_MAX     0xffff
-+#define IMX708_COLOUR_BALANCE_STEP    0x01
-+#define IMX708_COLOUR_BALANCE_DEFAULT 0x100
-+
-+/* Test Pattern Control */
-+#define IMX708_REG_TEST_PATTERN               0x0600
-+#define IMX708_TEST_PATTERN_DISABLE   0
-+#define IMX708_TEST_PATTERN_SOLID_COLOR       1
-+#define IMX708_TEST_PATTERN_COLOR_BARS        2
-+#define IMX708_TEST_PATTERN_GREY_COLOR        3
-+#define IMX708_TEST_PATTERN_PN9               4
-+
-+/* Test pattern colour components */
-+#define IMX708_REG_TEST_PATTERN_R     0x0602
-+#define IMX708_REG_TEST_PATTERN_GR    0x0604
-+#define IMX708_REG_TEST_PATTERN_B     0x0606
-+#define IMX708_REG_TEST_PATTERN_GB    0x0608
-+#define IMX708_TEST_PATTERN_COLOUR_MIN        0
-+#define IMX708_TEST_PATTERN_COLOUR_MAX        0x0fff
-+#define IMX708_TEST_PATTERN_COLOUR_STEP       1
-+
-+#define IMX708_REG_BASE_SPC_GAINS_L   0x7b10
-+#define IMX708_REG_BASE_SPC_GAINS_R   0x7c00
-+
-+/* HDR exposure ratio (long:med == med:short) */
-+#define IMX708_HDR_EXPOSURE_RATIO       4
-+#define IMX708_REG_MID_EXPOSURE               0x3116
-+#define IMX708_REG_SHT_EXPOSURE               0x0224
-+#define IMX708_REG_MID_ANALOG_GAIN    0x3118
-+#define IMX708_REG_SHT_ANALOG_GAIN    0x0216
-+
-+/* IMX708 native and active pixel array size. */
-+#define IMX708_NATIVE_WIDTH           4640U
-+#define IMX708_NATIVE_HEIGHT          2658U
-+#define IMX708_PIXEL_ARRAY_LEFT               16U
-+#define IMX708_PIXEL_ARRAY_TOP                24U
-+#define IMX708_PIXEL_ARRAY_WIDTH      4608U
-+#define IMX708_PIXEL_ARRAY_HEIGHT     2592U
-+
-+struct imx708_reg {
-+      u16 address;
-+      u8 val;
-+};
-+
-+struct imx708_reg_list {
-+      unsigned int num_of_regs;
-+      const struct imx708_reg *regs;
-+};
-+
-+/* Mode : resolution and related config&values */
-+struct imx708_mode {
-+      /* Frame width */
-+      unsigned int width;
-+
-+      /* Frame height */
-+      unsigned int height;
-+
-+      /* H-timing in pixels */
-+      unsigned int line_length_pix;
-+
-+      /* Analog crop rectangle. */
-+      struct v4l2_rect crop;
-+
-+      /* Highest possible framerate. */
-+      unsigned int vblank_min;
-+
-+      /* Default framerate. */
-+      unsigned int vblank_default;
-+
-+      /* Default register values */
-+      struct imx708_reg_list reg_list;
-+
-+      /* Not all modes have the same pixel rate. */
-+      u64 pixel_rate;
-+
-+      /* Not all modes have the same minimum exposure. */
-+      u32 exposure_lines_min;
-+
-+      /* Not all modes have the same exposure lines step. */
-+      u32 exposure_lines_step;
-+
-+      /* HDR flag, currently not used at runtime */
-+      bool hdr;
-+};
-+
-+/* Default PDAF pixel correction gains */
-+static const u8 pdaf_gains[2][9] = {
-+      { 0x4c, 0x4c, 0x4c, 0x46, 0x3e, 0x38, 0x35, 0x35, 0x35 },
-+      { 0x35, 0x35, 0x35, 0x38, 0x3e, 0x46, 0x4c, 0x4c, 0x4c }
-+};
-+
-+static const struct imx708_reg mode_common_regs[] = {
-+      {0x0100, 0x00},
-+      {0x0136, 0x18},
-+      {0x0137, 0x00},
-+      {0x33f0, 0x02},
-+      {0x33f1, 0x05},
-+      {0x3062, 0x00},
-+      {0x3063, 0x12},
-+      {0x3068, 0x00},
-+      {0x3069, 0x12},
-+      {0x306a, 0x00},
-+      {0x306b, 0x30},
-+      {0x3076, 0x00},
-+      {0x3077, 0x30},
-+      {0x3078, 0x00},
-+      {0x3079, 0x30},
-+      {0x5e54, 0x0c},
-+      {0x6e44, 0x00},
-+      {0xb0b6, 0x01},
-+      {0xe829, 0x00},
-+      {0xf001, 0x08},
-+      {0xf003, 0x08},
-+      {0xf00d, 0x10},
-+      {0xf00f, 0x10},
-+      {0xf031, 0x08},
-+      {0xf033, 0x08},
-+      {0xf03d, 0x10},
-+      {0xf03f, 0x10},
-+      {0x0112, 0x0a},
-+      {0x0113, 0x0a},
-+      {0x0114, 0x01},
-+      {0x0b8e, 0x01},
-+      {0x0b8f, 0x00},
-+      {0x0b94, 0x01},
-+      {0x0b95, 0x00},
-+      {0x3400, 0x01},
-+      {0x3478, 0x01},
-+      {0x3479, 0x1c},
-+      {0x3091, 0x01},
-+      {0x3092, 0x00},
-+      {0x3419, 0x00},
-+      {0xbcf1, 0x02},
-+      {0x3094, 0x01},
-+      {0x3095, 0x01},
-+      {0x3362, 0x00},
-+      {0x3363, 0x00},
-+      {0x3364, 0x00},
-+      {0x3365, 0x00},
-+      {0x0138, 0x01},
-+};
-+
-+/* 10-bit. */
-+static const struct imx708_reg mode_4608x2592_regs[] = {
-+      {0x0342, 0x3d},
-+      {0x0343, 0x20},
-+      {0x0340, 0x0a},
-+      {0x0341, 0x59},
-+      {0x0344, 0x00},
-+      {0x0345, 0x00},
-+      {0x0346, 0x00},
-+      {0x0347, 0x00},
-+      {0x0348, 0x11},
-+      {0x0349, 0xff},
-+      {0x034a, 0x0a},
-+      {0x034b, 0x1f},
-+      {0x0220, 0x62},
-+      {0x0222, 0x01},
-+      {0x0900, 0x00},
-+      {0x0901, 0x11},
-+      {0x0902, 0x0a},
-+      {0x3200, 0x01},
-+      {0x3201, 0x01},
-+      {0x32d5, 0x01},
-+      {0x32d6, 0x00},
-+      {0x32db, 0x01},
-+      {0x32df, 0x00},
-+      {0x350c, 0x00},
-+      {0x350d, 0x00},
-+      {0x0408, 0x00},
-+      {0x0409, 0x00},
-+      {0x040a, 0x00},
-+      {0x040b, 0x00},
-+      {0x040c, 0x12},
-+      {0x040d, 0x00},
-+      {0x040e, 0x0a},
-+      {0x040f, 0x20},
-+      {0x034c, 0x12},
-+      {0x034d, 0x00},
-+      {0x034e, 0x0a},
-+      {0x034f, 0x20},
-+      {0x0301, 0x05},
-+      {0x0303, 0x02},
-+      {0x0305, 0x02},
-+      {0x0306, 0x00},
-+      {0x0307, 0x7c},
-+      {0x030b, 0x02},
-+      {0x030d, 0x04},
-+      {0x030e, 0x01},
-+      {0x030f, 0x2c},
-+      {0x0310, 0x01},
-+      {0x3ca0, 0x00},
-+      {0x3ca1, 0x64},
-+      {0x3ca4, 0x00},
-+      {0x3ca5, 0x00},
-+      {0x3ca6, 0x00},
-+      {0x3ca7, 0x00},
-+      {0x3caa, 0x00},
-+      {0x3cab, 0x00},
-+      {0x3cb8, 0x00},
-+      {0x3cb9, 0x08},
-+      {0x3cba, 0x00},
-+      {0x3cbb, 0x00},
-+      {0x3cbc, 0x00},
-+      {0x3cbd, 0x3c},
-+      {0x3cbe, 0x00},
-+      {0x3cbf, 0x00},
-+      {0x0202, 0x0a},
-+      {0x0203, 0x29},
-+      {0x0224, 0x01},
-+      {0x0225, 0xf4},
-+      {0x3116, 0x01},
-+      {0x3117, 0xf4},
-+      {0x0204, 0x00},
-+      {0x0205, 0x00},
-+      {0x0216, 0x00},
-+      {0x0217, 0x00},
-+      {0x0218, 0x01},
-+      {0x0219, 0x00},
-+      {0x020e, 0x01},
-+      {0x020f, 0x00},
-+      {0x3118, 0x00},
-+      {0x3119, 0x00},
-+      {0x311a, 0x01},
-+      {0x311b, 0x00},
-+      {0x341a, 0x00},
-+      {0x341b, 0x00},
-+      {0x341c, 0x00},
-+      {0x341d, 0x00},
-+      {0x341e, 0x01},
-+      {0x341f, 0x20},
-+      {0x3420, 0x00},
-+      {0x3421, 0xd8},
-+      {0xc428, 0x00},
-+      {0xc429, 0x04},
-+      {0x3366, 0x00},
-+      {0x3367, 0x00},
-+      {0x3368, 0x00},
-+      {0x3369, 0x00},
-+};
-+
-+static const struct imx708_reg mode_2x2binned_regs[] = {
-+      {0x0342, 0x1e},
-+      {0x0343, 0x90},
-+      {0x0340, 0x05},
-+      {0x0341, 0x38},
-+      {0x0344, 0x00},
-+      {0x0345, 0x00},
-+      {0x0346, 0x00},
-+      {0x0347, 0x00},
-+      {0x0348, 0x11},
-+      {0x0349, 0xff},
-+      {0x034a, 0x0a},
-+      {0x034b, 0x1f},
-+      {0x0220, 0x62},
-+      {0x0222, 0x01},
-+      {0x0900, 0x01},
-+      {0x0901, 0x22},
-+      {0x0902, 0x08},
-+      {0x3200, 0x41},
-+      {0x3201, 0x41},
-+      {0x32d5, 0x00},
-+      {0x32d6, 0x00},
-+      {0x32db, 0x01},
-+      {0x32df, 0x00},
-+      {0x350c, 0x00},
-+      {0x350d, 0x00},
-+      {0x0408, 0x00},
-+      {0x0409, 0x00},
-+      {0x040a, 0x00},
-+      {0x040b, 0x00},
-+      {0x040c, 0x09},
-+      {0x040d, 0x00},
-+      {0x040e, 0x05},
-+      {0x040f, 0x10},
-+      {0x034c, 0x09},
-+      {0x034d, 0x00},
-+      {0x034e, 0x05},
-+      {0x034f, 0x10},
-+      {0x0301, 0x05},
-+      {0x0303, 0x02},
-+      {0x0305, 0x02},
-+      {0x0306, 0x00},
-+      {0x0307, 0x7a},
-+      {0x030b, 0x02},
-+      {0x030d, 0x04},
-+      {0x030e, 0x01},
-+      {0x030f, 0x2c},
-+      {0x0310, 0x01},
-+      {0x3ca0, 0x00},
-+      {0x3ca1, 0x3c},
-+      {0x3ca4, 0x00},
-+      {0x3ca5, 0x3c},
-+      {0x3ca6, 0x00},
-+      {0x3ca7, 0x00},
-+      {0x3caa, 0x00},
-+      {0x3cab, 0x00},
-+      {0x3cb8, 0x00},
-+      {0x3cb9, 0x1c},
-+      {0x3cba, 0x00},
-+      {0x3cbb, 0x08},
-+      {0x3cbc, 0x00},
-+      {0x3cbd, 0x1e},
-+      {0x3cbe, 0x00},
-+      {0x3cbf, 0x0a},
-+      {0x0202, 0x05},
-+      {0x0203, 0x08},
-+      {0x0224, 0x01},
-+      {0x0225, 0xf4},
-+      {0x3116, 0x01},
-+      {0x3117, 0xf4},
-+      {0x0204, 0x00},
-+      {0x0205, 0x70},
-+      {0x0216, 0x00},
-+      {0x0217, 0x70},
-+      {0x0218, 0x01},
-+      {0x0219, 0x00},
-+      {0x020e, 0x01},
-+      {0x020f, 0x00},
-+      {0x3118, 0x00},
-+      {0x3119, 0x70},
-+      {0x311a, 0x01},
-+      {0x311b, 0x00},
-+      {0x341a, 0x00},
-+      {0x341b, 0x00},
-+      {0x341c, 0x00},
-+      {0x341d, 0x00},
-+      {0x341e, 0x00},
-+      {0x341f, 0x90},
-+      {0x3420, 0x00},
-+      {0x3421, 0x6c},
-+      {0x3366, 0x00},
-+      {0x3367, 0x00},
-+      {0x3368, 0x00},
-+      {0x3369, 0x00},
-+};
-+
-+static const struct imx708_reg mode_2x2binned_720p_regs[] = {
-+      {0x0342, 0x14},
-+      {0x0343, 0x60},
-+      {0x0340, 0x04},
-+      {0x0341, 0xb6},
-+      {0x0344, 0x03},
-+      {0x0345, 0x00},
-+      {0x0346, 0x01},
-+      {0x0347, 0xb0},
-+      {0x0348, 0x0e},
-+      {0x0349, 0xff},
-+      {0x034a, 0x08},
-+      {0x034b, 0x6f},
-+      {0x0220, 0x62},
-+      {0x0222, 0x01},
-+      {0x0900, 0x01},
-+      {0x0901, 0x22},
-+      {0x0902, 0x08},
-+      {0x3200, 0x41},
-+      {0x3201, 0x41},
-+      {0x32d5, 0x00},
-+      {0x32d6, 0x00},
-+      {0x32db, 0x01},
-+      {0x32df, 0x01},
-+      {0x350c, 0x00},
-+      {0x350d, 0x00},
-+      {0x0408, 0x00},
-+      {0x0409, 0x00},
-+      {0x040a, 0x00},
-+      {0x040b, 0x00},
-+      {0x040c, 0x06},
-+      {0x040d, 0x00},
-+      {0x040e, 0x03},
-+      {0x040f, 0x60},
-+      {0x034c, 0x06},
-+      {0x034d, 0x00},
-+      {0x034e, 0x03},
-+      {0x034f, 0x60},
-+      {0x0301, 0x05},
-+      {0x0303, 0x02},
-+      {0x0305, 0x02},
-+      {0x0306, 0x00},
-+      {0x0307, 0x76},
-+      {0x030b, 0x02},
-+      {0x030d, 0x04},
-+      {0x030e, 0x01},
-+      {0x030f, 0x2c},
-+      {0x0310, 0x01},
-+      {0x3ca0, 0x00},
-+      {0x3ca1, 0x3c},
-+      {0x3ca4, 0x01},
-+      {0x3ca5, 0x5e},
-+      {0x3ca6, 0x00},
-+      {0x3ca7, 0x00},
-+      {0x3caa, 0x00},
-+      {0x3cab, 0x00},
-+      {0x3cb8, 0x00},
-+      {0x3cb9, 0x0c},
-+      {0x3cba, 0x00},
-+      {0x3cbb, 0x04},
-+      {0x3cbc, 0x00},
-+      {0x3cbd, 0x1e},
-+      {0x3cbe, 0x00},
-+      {0x3cbf, 0x05},
-+      {0x0202, 0x04},
-+      {0x0203, 0x86},
-+      {0x0224, 0x01},
-+      {0x0225, 0xf4},
-+      {0x3116, 0x01},
-+      {0x3117, 0xf4},
-+      {0x0204, 0x00},
-+      {0x0205, 0x70},
-+      {0x0216, 0x00},
-+      {0x0217, 0x70},
-+      {0x0218, 0x01},
-+      {0x0219, 0x00},
-+      {0x020e, 0x01},
-+      {0x020f, 0x00},
-+      {0x3118, 0x00},
-+      {0x3119, 0x70},
-+      {0x311a, 0x01},
-+      {0x311b, 0x00},
-+      {0x341a, 0x00},
-+      {0x341b, 0x00},
-+      {0x341c, 0x00},
-+      {0x341d, 0x00},
-+      {0x341e, 0x00},
-+      {0x341f, 0x60},
-+      {0x3420, 0x00},
-+      {0x3421, 0x48},
-+      {0x3366, 0x00},
-+      {0x3367, 0x00},
-+      {0x3368, 0x00},
-+      {0x3369, 0x00},
-+};
-+
-+static const struct imx708_reg mode_hdr_regs[] = {
-+      {0x0342, 0x14},
-+      {0x0343, 0x60},
-+      {0x0340, 0x0a},
-+      {0x0341, 0x5b},
-+      {0x0344, 0x00},
-+      {0x0345, 0x00},
-+      {0x0346, 0x00},
-+      {0x0347, 0x00},
-+      {0x0348, 0x11},
-+      {0x0349, 0xff},
-+      {0x034a, 0x0a},
-+      {0x034b, 0x1f},
-+      {0x0220, 0x01},
-+      {0x0222, IMX708_HDR_EXPOSURE_RATIO},
-+      {0x0900, 0x00},
-+      {0x0901, 0x11},
-+      {0x0902, 0x0a},
-+      {0x3200, 0x01},
-+      {0x3201, 0x01},
-+      {0x32d5, 0x00},
-+      {0x32d6, 0x00},
-+      {0x32db, 0x01},
-+      {0x32df, 0x00},
-+      {0x350c, 0x00},
-+      {0x350d, 0x00},
-+      {0x0408, 0x00},
-+      {0x0409, 0x00},
-+      {0x040a, 0x00},
-+      {0x040b, 0x00},
-+      {0x040c, 0x09},
-+      {0x040d, 0x00},
-+      {0x040e, 0x05},
-+      {0x040f, 0x10},
-+      {0x034c, 0x09},
-+      {0x034d, 0x00},
-+      {0x034e, 0x05},
-+      {0x034f, 0x10},
-+      {0x0301, 0x05},
-+      {0x0303, 0x02},
-+      {0x0305, 0x02},
-+      {0x0306, 0x00},
-+      {0x0307, 0xa2},
-+      {0x030b, 0x02},
-+      {0x030d, 0x04},
-+      {0x030e, 0x01},
-+      {0x030f, 0x2c},
-+      {0x0310, 0x01},
-+      {0x3ca0, 0x00},
-+      {0x3ca1, 0x00},
-+      {0x3ca4, 0x00},
-+      {0x3ca5, 0x00},
-+      {0x3ca6, 0x00},
-+      {0x3ca7, 0x28},
-+      {0x3caa, 0x00},
-+      {0x3cab, 0x00},
-+      {0x3cb8, 0x00},
-+      {0x3cb9, 0x30},
-+      {0x3cba, 0x00},
-+      {0x3cbb, 0x00},
-+      {0x3cbc, 0x00},
-+      {0x3cbd, 0x32},
-+      {0x3cbe, 0x00},
-+      {0x3cbf, 0x00},
-+      {0x0202, 0x0a},
-+      {0x0203, 0x2b},
-+      {0x0224, 0x0a},
-+      {0x0225, 0x2b},
-+      {0x3116, 0x0a},
-+      {0x3117, 0x2b},
-+      {0x0204, 0x00},
-+      {0x0205, 0x00},
-+      {0x0216, 0x00},
-+      {0x0217, 0x00},
-+      {0x0218, 0x01},
-+      {0x0219, 0x00},
-+      {0x020e, 0x01},
-+      {0x020f, 0x00},
-+      {0x3118, 0x00},
-+      {0x3119, 0x00},
-+      {0x311a, 0x01},
-+      {0x311b, 0x00},
-+      {0x341a, 0x00},
-+      {0x341b, 0x00},
-+      {0x341c, 0x00},
-+      {0x341d, 0x00},
-+      {0x341e, 0x00},
-+      {0x341f, 0x90},
-+      {0x3420, 0x00},
-+      {0x3421, 0x6c},
-+      {0x3360, 0x01},
-+      {0x3361, 0x01},
-+      {0x3366, 0x09},
-+      {0x3367, 0x00},
-+      {0x3368, 0x05},
-+      {0x3369, 0x10},
-+};
-+
-+/* Mode configs. Keep separate lists for when HDR is enabled or not. */
-+static const struct imx708_mode supported_modes_10bit_no_hdr[] = {
-+      {
-+              /* Full resolution. */
-+              .width = 4608,
-+              .height = 2592,
-+              .line_length_pix = 0x3d20,
-+              .crop = {
-+                      .left = IMX708_PIXEL_ARRAY_LEFT,
-+                      .top = IMX708_PIXEL_ARRAY_TOP,
-+                      .width = 4608,
-+                      .height = 2592,
-+              },
-+              .vblank_min = 58,
-+              .vblank_default = 58,
-+              .reg_list = {
-+                      .num_of_regs = ARRAY_SIZE(mode_4608x2592_regs),
-+                      .regs = mode_4608x2592_regs,
-+              },
-+              .pixel_rate = 595200000,
-+              .exposure_lines_min = 8,
-+              .exposure_lines_step = 1,
-+              .hdr = false
-+      },
-+      {
-+              /* regular 2x2 binned. */
-+              .width = 2304,
-+              .height = 1296,
-+              .line_length_pix = 0x1e90,
-+              .crop = {
-+                      .left = IMX708_PIXEL_ARRAY_LEFT,
-+                      .top = IMX708_PIXEL_ARRAY_TOP,
-+                      .width = 4608,
-+                      .height = 2592,
-+              },
-+              .vblank_min = 40,
-+              .vblank_default = 1198,
-+              .reg_list = {
-+                      .num_of_regs = ARRAY_SIZE(mode_2x2binned_regs),
-+                      .regs = mode_2x2binned_regs,
-+              },
-+              .pixel_rate = 585600000,
-+              .exposure_lines_min = 4,
-+              .exposure_lines_step = 2,
-+              .hdr = false
-+      },
-+      {
-+              /* 2x2 binned and cropped for 720p. */
-+              .width = 1536,
-+              .height = 864,
-+              .line_length_pix = 0x1460,
-+              .crop = {
-+                      .left = IMX708_PIXEL_ARRAY_LEFT + 768,
-+                      .top = IMX708_PIXEL_ARRAY_TOP + 432,
-+                      .width = 3072,
-+                      .height = 1728,
-+              },
-+              .vblank_min = 40,
-+              .vblank_default = 2755,
-+              .reg_list = {
-+                      .num_of_regs = ARRAY_SIZE(mode_2x2binned_720p_regs),
-+                      .regs = mode_2x2binned_720p_regs,
-+              },
-+              .pixel_rate = 566400000,
-+              .exposure_lines_min = 4,
-+              .exposure_lines_step = 2,
-+              .hdr = false
-+      },
-+};
-+
-+static const struct imx708_mode supported_modes_10bit_hdr[] = {
-+      {
-+              /* There's only one HDR mode, which is 2x2 downscaled */
-+              .width = 2304,
-+              .height = 1296,
-+              .line_length_pix = 0x1460,
-+              .crop = {
-+                      .left = IMX708_PIXEL_ARRAY_LEFT,
-+                      .top = IMX708_PIXEL_ARRAY_TOP,
-+                      .width = 4608,
-+                      .height = 2592,
-+              },
-+              .vblank_min = 3673,
-+              .vblank_default = 3673,
-+              .reg_list = {
-+                      .num_of_regs = ARRAY_SIZE(mode_hdr_regs),
-+                      .regs = mode_hdr_regs,
-+              },
-+              .pixel_rate = 777600000,
-+              .exposure_lines_min = 8 * IMX708_HDR_EXPOSURE_RATIO *
-+                                    IMX708_HDR_EXPOSURE_RATIO,
-+              .exposure_lines_step = 2 * IMX708_HDR_EXPOSURE_RATIO *
-+                                     IMX708_HDR_EXPOSURE_RATIO,
-+              .hdr = true
-+      }
-+};
-+
-+/*
-+ * The supported formats.
-+ * This table MUST contain 4 entries per format, to cover the various flip
-+ * combinations in the order
-+ * - no flip
-+ * - h flip
-+ * - v flip
-+ * - h&v flips
-+ */
-+static const u32 codes[] = {
-+      /* 10-bit modes. */
-+      MEDIA_BUS_FMT_SRGGB10_1X10,
-+      MEDIA_BUS_FMT_SGRBG10_1X10,
-+      MEDIA_BUS_FMT_SGBRG10_1X10,
-+      MEDIA_BUS_FMT_SBGGR10_1X10,
-+};
-+
-+static const char * const imx708_test_pattern_menu[] = {
-+      "Disabled",
-+      "Color Bars",
-+      "Solid Color",
-+      "Grey Color Bars",
-+      "PN9"
-+};
-+
-+static const int imx708_test_pattern_val[] = {
-+      IMX708_TEST_PATTERN_DISABLE,
-+      IMX708_TEST_PATTERN_COLOR_BARS,
-+      IMX708_TEST_PATTERN_SOLID_COLOR,
-+      IMX708_TEST_PATTERN_GREY_COLOR,
-+      IMX708_TEST_PATTERN_PN9,
-+};
-+
-+/* regulator supplies */
-+static const char * const imx708_supply_name[] = {
-+      /* Supplies can be enabled in any order */
-+      "VANA1",  /* Analog1 (2.8V) supply */
-+      "VANA2",  /* Analog2 (1.8V) supply */
-+      "VDIG",  /* Digital Core (1.1V) supply */
-+      "VDDL",  /* IF (1.8V) supply */
-+};
-+
-+#define IMX708_NUM_SUPPLIES ARRAY_SIZE(imx708_supply_name)
-+
-+/*
-+ * Initialisation delay between XCLR low->high and the moment when the sensor
-+ * can start capture (i.e. can leave software standby), given by T7 in the
-+ * datasheet is 8ms.  This does include I2C setup time as well.
-+ *
-+ * Note, that delay between XCLR low->high and reading the CCI ID register (T6
-+ * in the datasheet) is much smaller - 600us.
-+ */
-+#define IMX708_XCLR_MIN_DELAY_US      8000
-+#define IMX708_XCLR_DELAY_RANGE_US    1000
-+
-+struct imx708 {
-+      struct v4l2_subdev sd;
-+      struct media_pad pad;
-+
-+      struct v4l2_mbus_framefmt fmt;
-+
-+      struct clk *xclk;
-+      u32 xclk_freq;
-+
-+      struct gpio_desc *reset_gpio;
-+      struct regulator_bulk_data supplies[IMX708_NUM_SUPPLIES];
-+
-+      struct v4l2_ctrl_handler ctrl_handler;
-+      /* V4L2 Controls */
-+      struct v4l2_ctrl *pixel_rate;
-+      struct v4l2_ctrl *exposure;
-+      struct v4l2_ctrl *vflip;
-+      struct v4l2_ctrl *hflip;
-+      struct v4l2_ctrl *vblank;
-+      struct v4l2_ctrl *hblank;
-+      struct v4l2_ctrl *red_balance;
-+      struct v4l2_ctrl *blue_balance;
-+      struct v4l2_ctrl *notify_gains;
-+      struct v4l2_ctrl *hdr_mode;
-+
-+      /* Current mode */
-+      const struct imx708_mode *mode;
-+
-+      /* Mutex for serialized access */
-+      struct mutex mutex;
-+
-+      /* Streaming on/off */
-+      bool streaming;
-+
-+      /* Rewrite common registers on stream on? */
-+      bool common_regs_written;
-+
-+      /* Current long exposure factor in use. Set through V4L2_CID_VBLANK */
-+      unsigned int long_exp_shift;
-+};
-+
-+static inline struct imx708 *to_imx708(struct v4l2_subdev *_sd)
-+{
-+      return container_of(_sd, struct imx708, sd);
-+}
-+
-+static inline void get_mode_table(const struct imx708_mode **mode_list,
-+                                unsigned int *num_modes,
-+                                bool hdr_enable)
-+{
-+      if (hdr_enable) {
-+              *mode_list = supported_modes_10bit_hdr;
-+              *num_modes = ARRAY_SIZE(supported_modes_10bit_hdr);
-+      } else {
-+              *mode_list = supported_modes_10bit_no_hdr;
-+              *num_modes = ARRAY_SIZE(supported_modes_10bit_no_hdr);
-+      }
-+}
-+
-+/* Read registers up to 2 at a time */
-+static int imx708_read_reg(struct imx708 *imx708, u16 reg, u32 len, u32 *val)
-+{
-+      struct i2c_client *client = v4l2_get_subdevdata(&imx708->sd);
-+      struct i2c_msg msgs[2];
-+      u8 addr_buf[2] = { reg >> 8, reg & 0xff };
-+      u8 data_buf[4] = { 0, };
-+      int ret;
-+
-+      if (len > 4)
-+              return -EINVAL;
-+
-+      /* Write register address */
-+      msgs[0].addr = client->addr;
-+      msgs[0].flags = 0;
-+      msgs[0].len = ARRAY_SIZE(addr_buf);
-+      msgs[0].buf = addr_buf;
-+
-+      /* Read data from register */
-+      msgs[1].addr = client->addr;
-+      msgs[1].flags = I2C_M_RD;
-+      msgs[1].len = len;
-+      msgs[1].buf = &data_buf[4 - len];
-+
-+      ret = i2c_transfer(client->adapter, msgs, ARRAY_SIZE(msgs));
-+      if (ret != ARRAY_SIZE(msgs))
-+              return -EIO;
-+
-+      *val = get_unaligned_be32(data_buf);
-+
-+      return 0;
-+}
-+
-+/* Write registers up to 2 at a time */
-+static int imx708_write_reg(struct imx708 *imx708, u16 reg, u32 len, u32 val)
-+{
-+      struct i2c_client *client = v4l2_get_subdevdata(&imx708->sd);
-+      u8 buf[6];
-+
-+      if (len > 4)
-+              return -EINVAL;
-+
-+      put_unaligned_be16(reg, buf);
-+      put_unaligned_be32(val << (8 * (4 - len)), buf + 2);
-+      if (i2c_master_send(client, buf, len + 2) != len + 2)
-+              return -EIO;
-+
-+      return 0;
-+}
-+
-+/* Write a list of registers */
-+static int imx708_write_regs(struct imx708 *imx708,
-+                           const struct imx708_reg *regs, u32 len)
-+{
-+      struct i2c_client *client = v4l2_get_subdevdata(&imx708->sd);
-+      unsigned int i;
-+      int ret;
-+
-+      for (i = 0; i < len; i++) {
-+              ret = imx708_write_reg(imx708, regs[i].address, 1, regs[i].val);
-+              if (ret) {
-+                      dev_err_ratelimited(&client->dev,
-+                                          "Failed to write reg 0x%4.4x. error = %d\n",
-+                                          regs[i].address, ret);
-+
-+                      return ret;
-+              }
-+      }
-+
-+      return 0;
-+}
-+
-+/* Get bayer order based on flip setting. */
-+static u32 imx708_get_format_code(struct imx708 *imx708)
-+{
-+      unsigned int i;
-+
-+      lockdep_assert_held(&imx708->mutex);
-+
-+      i = (imx708->vflip->val ? 2 : 0) |
-+          (imx708->hflip->val ? 1 : 0);
-+
-+      return codes[i];
-+}
-+
-+static void imx708_set_default_format(struct imx708 *imx708)
-+{
-+      struct v4l2_mbus_framefmt *fmt = &imx708->fmt;
-+
-+      /* Set default mode to max resolution */
-+      imx708->mode = &supported_modes_10bit_no_hdr[0];
-+
-+      /* fmt->code not set as it will always be computed based on flips */
-+      fmt->colorspace = V4L2_COLORSPACE_RAW;
-+      fmt->ycbcr_enc = V4L2_MAP_YCBCR_ENC_DEFAULT(fmt->colorspace);
-+      fmt->quantization = V4L2_MAP_QUANTIZATION_DEFAULT(true,
-+                                                        fmt->colorspace,
-+                                                        fmt->ycbcr_enc);
-+      fmt->xfer_func = V4L2_MAP_XFER_FUNC_DEFAULT(fmt->colorspace);
-+      fmt->width = imx708->mode->width;
-+      fmt->height = imx708->mode->height;
-+      fmt->field = V4L2_FIELD_NONE;
-+}
-+
-+static int imx708_open(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh)
-+{
-+      struct imx708 *imx708 = to_imx708(sd);
-+      struct v4l2_mbus_framefmt *try_fmt_img =
-+              v4l2_subdev_get_try_format(sd, fh->state, 0);
-+      struct v4l2_rect *try_crop;
-+
-+      mutex_lock(&imx708->mutex);
-+
-+      /* Initialize try_fmt for the image pad */
-+      if (imx708->hdr_mode->val) {
-+              try_fmt_img->width = supported_modes_10bit_hdr[0].width;
-+              try_fmt_img->height = supported_modes_10bit_hdr[0].height;
-+      } else {
-+              try_fmt_img->width = supported_modes_10bit_no_hdr[0].width;
-+              try_fmt_img->height = supported_modes_10bit_no_hdr[0].height;
-+      }
-+      try_fmt_img->code = imx708_get_format_code(imx708);
-+      try_fmt_img->field = V4L2_FIELD_NONE;
-+
-+      /* Initialize try_crop */
-+      try_crop = v4l2_subdev_get_try_crop(sd, fh->state, 0);
-+      try_crop->left = IMX708_PIXEL_ARRAY_LEFT;
-+      try_crop->top = IMX708_PIXEL_ARRAY_TOP;
-+      try_crop->width = IMX708_PIXEL_ARRAY_WIDTH;
-+      try_crop->height = IMX708_PIXEL_ARRAY_HEIGHT;
-+
-+      mutex_unlock(&imx708->mutex);
-+
-+      return 0;
-+}
-+
-+static int imx708_set_exposure(struct imx708 *imx708, unsigned int val)
-+{
-+      int ret;
-+
-+      val = max(val, imx708->mode->exposure_lines_min);
-+      val -= val % imx708->mode->exposure_lines_step;
-+
-+      /*
-+       * In HDR mode this will set the longest exposure. The sensor
-+       * will automatically divide the medium and short ones by 4,16.
-+       */
-+      ret = imx708_write_reg(imx708, IMX708_REG_EXPOSURE,
-+                             IMX708_REG_VALUE_16BIT,
-+                             val >> imx708->long_exp_shift);
-+
-+      return ret;
-+}
-+
-+static void imx708_adjust_exposure_range(struct imx708 *imx708,
-+                                       struct v4l2_ctrl *ctrl)
-+{
-+      int exposure_max, exposure_def;
-+
-+      /* Honour the VBLANK limits when setting exposure. */
-+      exposure_max = imx708->mode->height + imx708->vblank->val -
-+              IMX708_EXPOSURE_OFFSET;
-+      exposure_def = min(exposure_max, imx708->exposure->val);
-+      __v4l2_ctrl_modify_range(imx708->exposure, imx708->exposure->minimum,
-+                               exposure_max, imx708->exposure->step,
-+                               exposure_def);
-+}
-+
-+static int imx708_set_analogue_gain(struct imx708 *imx708, unsigned int val)
-+{
-+      int ret;
-+
-+      /*
-+       * In HDR mode this will set the gain for the longest exposure,
-+       * and by default the sensor uses the same gain for all of them.
-+       */
-+      ret = imx708_write_reg(imx708, IMX708_REG_ANALOG_GAIN,
-+                             IMX708_REG_VALUE_16BIT, val);
-+
-+      return ret;
-+}
-+
-+static int imx708_set_frame_length(struct imx708 *imx708, unsigned int val)
-+{
-+      int ret = 0;
-+
-+      imx708->long_exp_shift = 0;
-+
-+      while (val > IMX708_FRAME_LENGTH_MAX) {
-+              imx708->long_exp_shift++;
-+              val >>= 1;
-+      }
-+
-+      ret = imx708_write_reg(imx708, IMX708_REG_FRAME_LENGTH,
-+                             IMX708_REG_VALUE_16BIT, val);
-+      if (ret)
-+              return ret;
-+
-+      return imx708_write_reg(imx708, IMX708_LONG_EXP_SHIFT_REG,
-+                              IMX708_REG_VALUE_08BIT, imx708->long_exp_shift);
-+}
-+
-+static void imx708_set_framing_limits(struct imx708 *imx708)
-+{
-+      unsigned int hblank;
-+      const struct imx708_mode *mode = imx708->mode;
-+
-+      /* Default to no long exposure multiplier */
-+      imx708->long_exp_shift = 0;
-+
-+      __v4l2_ctrl_modify_range(imx708->pixel_rate,
-+                               mode->pixel_rate, mode->pixel_rate,
-+                               1, mode->pixel_rate);
-+
-+      /* Update limits and set FPS to default */
-+      __v4l2_ctrl_modify_range(imx708->vblank, mode->vblank_min,
-+                               ((1 << IMX708_LONG_EXP_SHIFT_MAX) *
-+                                      IMX708_FRAME_LENGTH_MAX) - mode->height,
-+                               1, mode->vblank_default);
-+
-+      /*
-+       * Currently PPL is fixed to the mode specified value, so hblank
-+       * depends on mode->width only, and is not changeable in any
-+       * way other than changing the mode.
-+       */
-+      hblank = mode->line_length_pix - mode->width;
-+      __v4l2_ctrl_modify_range(imx708->hblank, hblank, hblank, 1, hblank);
-+}
-+
-+static int imx708_set_ctrl(struct v4l2_ctrl *ctrl)
-+{
-+      struct imx708 *imx708 =
-+              container_of(ctrl->handler, struct imx708, ctrl_handler);
-+      struct i2c_client *client = v4l2_get_subdevdata(&imx708->sd);
-+      const struct imx708_mode *mode_list;
-+      unsigned int num_modes;
-+      int ret;
-+
-+      /*
-+       * The VBLANK control may change the limits of usable exposure, so check
-+       * and adjust if necessary.
-+       */
-+      if (ctrl->id == V4L2_CID_VBLANK)
-+              imx708_adjust_exposure_range(imx708, ctrl);
-+
-+      /*
-+       * Applying V4L2 control value only happens
-+       * when power is up for streaming
-+       */
-+      if (!pm_runtime_get_if_in_use(&client->dev))
-+              return 0;
-+
-+      switch (ctrl->id) {
-+      case V4L2_CID_ANALOGUE_GAIN:
-+              ret = imx708_set_analogue_gain(imx708, ctrl->val);
-+              break;
-+      case V4L2_CID_EXPOSURE:
-+              ret = imx708_set_exposure(imx708, ctrl->val);
-+              break;
-+      case V4L2_CID_DIGITAL_GAIN:
-+              ret = imx708_write_reg(imx708, IMX708_REG_DIGITAL_GAIN,
-+                                     IMX708_REG_VALUE_16BIT, ctrl->val);
-+              break;
-+      case V4L2_CID_TEST_PATTERN:
-+              ret = imx708_write_reg(imx708, IMX708_REG_TEST_PATTERN,
-+                                     IMX708_REG_VALUE_16BIT,
-+                                     imx708_test_pattern_val[ctrl->val]);
-+              break;
-+      case V4L2_CID_TEST_PATTERN_RED:
-+              ret = imx708_write_reg(imx708, IMX708_REG_TEST_PATTERN_R,
-+                                     IMX708_REG_VALUE_16BIT, ctrl->val);
-+              break;
-+      case V4L2_CID_TEST_PATTERN_GREENR:
-+              ret = imx708_write_reg(imx708, IMX708_REG_TEST_PATTERN_GR,
-+                                     IMX708_REG_VALUE_16BIT, ctrl->val);
-+              break;
-+      case V4L2_CID_TEST_PATTERN_BLUE:
-+              ret = imx708_write_reg(imx708, IMX708_REG_TEST_PATTERN_B,
-+                                     IMX708_REG_VALUE_16BIT, ctrl->val);
-+              break;
-+      case V4L2_CID_TEST_PATTERN_GREENB:
-+              ret = imx708_write_reg(imx708, IMX708_REG_TEST_PATTERN_GB,
-+                                     IMX708_REG_VALUE_16BIT, ctrl->val);
-+              break;
-+      case V4L2_CID_HFLIP:
-+      case V4L2_CID_VFLIP:
-+              ret = imx708_write_reg(imx708, IMX708_REG_ORIENTATION, 1,
-+                                     imx708->hflip->val |
-+                                     imx708->vflip->val << 1);
-+              break;
-+      case V4L2_CID_VBLANK:
-+              ret = imx708_set_frame_length(imx708,
-+                                            imx708->mode->height + ctrl->val);
-+              break;
-+      case V4L2_CID_NOTIFY_GAINS:
-+              ret = imx708_write_reg(imx708, IMX708_REG_COLOUR_BALANCE_BLUE,
-+                                     IMX708_REG_VALUE_16BIT,
-+                                     imx708->notify_gains->p_new.p_u32[0]);
-+              if (ret)
-+                      break;
-+              ret = imx708_write_reg(imx708, IMX708_REG_COLOUR_BALANCE_RED,
-+                                     IMX708_REG_VALUE_16BIT,
-+                                     imx708->notify_gains->p_new.p_u32[3]);
-+              break;
-+      case V4L2_CID_WIDE_DYNAMIC_RANGE:
-+              get_mode_table(&mode_list, &num_modes, ctrl->val);
-+              imx708->mode = v4l2_find_nearest_size(mode_list,
-+                                                    num_modes,
-+                                                    width, height,
-+                                                    imx708->mode->width,
-+                                                    imx708->mode->height);
-+              imx708_set_framing_limits(imx708);
-+              ret = 0;
-+              break;
-+      default:
-+              dev_info(&client->dev,
-+                       "ctrl(id:0x%x,val:0x%x) is not handled\n",
-+                       ctrl->id, ctrl->val);
-+              ret = -EINVAL;
-+              break;
-+      }
-+
-+      pm_runtime_mark_last_busy(&client->dev);
-+      pm_runtime_put_autosuspend(&client->dev);
-+
-+      return ret;
-+}
-+
-+static const struct v4l2_ctrl_ops imx708_ctrl_ops = {
-+      .s_ctrl = imx708_set_ctrl,
-+};
-+
-+static int imx708_enum_mbus_code(struct v4l2_subdev *sd,
-+                               struct v4l2_subdev_state *sd_state,
-+                               struct v4l2_subdev_mbus_code_enum *code)
-+{
-+      struct imx708 *imx708 = to_imx708(sd);
-+
-+      if (code->index >= 1)
-+              return -EINVAL;
-+
-+      code->code = imx708_get_format_code(imx708);
-+
-+      return 0;
-+}
-+
-+static int imx708_enum_frame_size(struct v4l2_subdev *sd,
-+                                struct v4l2_subdev_state *sd_state,
-+                                struct v4l2_subdev_frame_size_enum *fse)
-+{
-+      struct imx708 *imx708 = to_imx708(sd);
-+      const struct imx708_mode *mode_list;
-+      unsigned int num_modes;
-+
-+      get_mode_table(&mode_list, &num_modes, imx708->hdr_mode->val);
-+
-+      if (fse->index >= num_modes)
-+              return -EINVAL;
-+
-+      if (fse->code != imx708_get_format_code(imx708))
-+              return -EINVAL;
-+
-+      fse->min_width = mode_list[fse->index].width;
-+      fse->max_width = fse->min_width;
-+      fse->min_height = mode_list[fse->index].height;
-+      fse->max_height = fse->min_height;
-+
-+      return 0;
-+}
-+
-+static void imx708_reset_colorspace(struct v4l2_mbus_framefmt *fmt)
-+{
-+      fmt->colorspace = V4L2_COLORSPACE_RAW;
-+      fmt->ycbcr_enc = V4L2_MAP_YCBCR_ENC_DEFAULT(fmt->colorspace);
-+      fmt->quantization = V4L2_MAP_QUANTIZATION_DEFAULT(true,
-+                                                        fmt->colorspace,
-+                                                        fmt->ycbcr_enc);
-+      fmt->xfer_func = V4L2_MAP_XFER_FUNC_DEFAULT(fmt->colorspace);
-+}
-+
-+static void imx708_update_image_pad_format(struct imx708 *imx708,
-+                                         const struct imx708_mode *mode,
-+                                         struct v4l2_subdev_format *fmt)
-+{
-+      fmt->format.width = mode->width;
-+      fmt->format.height = mode->height;
-+      fmt->format.field = V4L2_FIELD_NONE;
-+      imx708_reset_colorspace(&fmt->format);
-+}
-+
-+static int imx708_get_pad_format(struct v4l2_subdev *sd,
-+                               struct v4l2_subdev_state *sd_state,
-+                               struct v4l2_subdev_format *fmt)
-+{
-+      struct imx708 *imx708 = to_imx708(sd);
-+
-+      mutex_lock(&imx708->mutex);
-+
-+      if (fmt->which == V4L2_SUBDEV_FORMAT_TRY) {
-+              struct v4l2_mbus_framefmt *try_fmt =
-+                      v4l2_subdev_get_try_format(&imx708->sd, sd_state,
-+                                                 fmt->pad);
-+              /* update the code which could change due to vflip or hflip */
-+              try_fmt->code = imx708_get_format_code(imx708);
-+              fmt->format = *try_fmt;
-+      } else {
-+              imx708_update_image_pad_format(imx708, imx708->mode, fmt);
-+              fmt->format.code = imx708_get_format_code(imx708);
-+      }
-+
-+      mutex_unlock(&imx708->mutex);
-+      return 0;
-+}
-+
-+static int imx708_set_pad_format(struct v4l2_subdev *sd,
-+                               struct v4l2_subdev_state *sd_state,
-+                               struct v4l2_subdev_format *fmt)
-+{
-+      struct v4l2_mbus_framefmt *framefmt;
-+      const struct imx708_mode *mode;
-+      struct imx708 *imx708 = to_imx708(sd);
-+      const struct imx708_mode *mode_list;
-+      unsigned int num_modes;
-+
-+      mutex_lock(&imx708->mutex);
-+
-+      /* Bayer order varies with flips */
-+      fmt->format.code = imx708_get_format_code(imx708);
-+
-+      get_mode_table(&mode_list, &num_modes, imx708->hdr_mode->val);
-+
-+      mode = v4l2_find_nearest_size(mode_list, num_modes, width, height,
-+                                    fmt->format.width, fmt->format.height);
-+      imx708_update_image_pad_format(imx708, mode, fmt);
-+
-+      if (fmt->which == V4L2_SUBDEV_FORMAT_TRY) {
-+              framefmt = v4l2_subdev_get_try_format(sd, sd_state, fmt->pad);
-+              *framefmt = fmt->format;
-+      } else {
-+              imx708->mode = mode;
-+              imx708_set_framing_limits(imx708);
-+      }
-+
-+      mutex_unlock(&imx708->mutex);
-+
-+      return 0;
-+}
-+
-+static const struct v4l2_rect *
-+__imx708_get_pad_crop(struct imx708 *imx708, struct v4l2_subdev_state *sd_state,
-+                    unsigned int pad, enum v4l2_subdev_format_whence which)
-+{
-+      switch (which) {
-+      case V4L2_SUBDEV_FORMAT_TRY:
-+              return v4l2_subdev_get_try_crop(&imx708->sd, sd_state, pad);
-+      case V4L2_SUBDEV_FORMAT_ACTIVE:
-+              return &imx708->mode->crop;
-+      }
-+
-+      return NULL;
-+}
-+
-+static int imx708_get_selection(struct v4l2_subdev *sd,
-+                              struct v4l2_subdev_state *sd_state,
-+                              struct v4l2_subdev_selection *sel)
-+{
-+      switch (sel->target) {
-+      case V4L2_SEL_TGT_CROP: {
-+              struct imx708 *imx708 = to_imx708(sd);
-+
-+              mutex_lock(&imx708->mutex);
-+              sel->r = *__imx708_get_pad_crop(imx708, sd_state, sel->pad,
-+                                              sel->which);
-+              mutex_unlock(&imx708->mutex);
-+
-+              return 0;
-+      }
-+
-+      case V4L2_SEL_TGT_NATIVE_SIZE:
-+              sel->r.left = 0;
-+              sel->r.top = 0;
-+              sel->r.width = IMX708_NATIVE_WIDTH;
-+              sel->r.height = IMX708_NATIVE_HEIGHT;
-+
-+              return 0;
-+
-+      case V4L2_SEL_TGT_CROP_DEFAULT:
-+      case V4L2_SEL_TGT_CROP_BOUNDS:
-+              sel->r.left = IMX708_PIXEL_ARRAY_LEFT;
-+              sel->r.top = IMX708_PIXEL_ARRAY_TOP;
-+              sel->r.width = IMX708_PIXEL_ARRAY_WIDTH;
-+              sel->r.height = IMX708_PIXEL_ARRAY_HEIGHT;
-+
-+              return 0;
-+      }
-+
-+      return -EINVAL;
-+}
-+
-+/* Start streaming */
-+static int imx708_start_streaming(struct imx708 *imx708)
-+{
-+      struct i2c_client *client = v4l2_get_subdevdata(&imx708->sd);
-+      const struct imx708_reg_list *reg_list;
-+      int i, ret;
-+      u32 val;
-+
-+      if (!imx708->common_regs_written) {
-+              ret = imx708_write_regs(imx708, mode_common_regs,
-+                                      ARRAY_SIZE(mode_common_regs));
-+              if (ret) {
-+                      dev_err(&client->dev, "%s failed to set common settings\n",
-+                              __func__);
-+                      return ret;
-+              }
-+
-+              ret = imx708_read_reg(imx708, IMX708_REG_BASE_SPC_GAINS_L,
-+                                    IMX708_REG_VALUE_08BIT, &val);
-+              if (ret == 0 && val == 0x40) {
-+                      for (i = 0; i < 54 && ret == 0; i++) {
-+                              u16 reg = IMX708_REG_BASE_SPC_GAINS_L + i;
-+
-+                              ret = imx708_write_reg(imx708, reg,
-+                                                     IMX708_REG_VALUE_08BIT,
-+                                                     pdaf_gains[0][i % 9]);
-+                      }
-+                      for (i = 0; i < 54 && ret == 0; i++) {
-+                              u16 reg = IMX708_REG_BASE_SPC_GAINS_R + i;
-+
-+                              ret = imx708_write_reg(imx708, reg,
-+                                                     IMX708_REG_VALUE_08BIT,
-+                                                     pdaf_gains[1][i % 9]);
-+                      }
-+              }
-+              if (ret) {
-+                      dev_err(&client->dev, "%s failed to set PDAF gains\n",
-+                              __func__);
-+                      return ret;
-+              }
-+
-+              imx708->common_regs_written = true;
-+      }
-+
-+      /* Apply default values of current mode */
-+      reg_list = &imx708->mode->reg_list;
-+      ret = imx708_write_regs(imx708, reg_list->regs, reg_list->num_of_regs);
-+      if (ret) {
-+              dev_err(&client->dev, "%s failed to set mode\n", __func__);
-+              return ret;
-+      }
-+
-+      /* Apply customized values from user */
-+      ret =  __v4l2_ctrl_handler_setup(imx708->sd.ctrl_handler);
-+      if (ret)
-+              return ret;
-+
-+      /* set stream on register */
-+      return imx708_write_reg(imx708, IMX708_REG_MODE_SELECT,
-+                              IMX708_REG_VALUE_08BIT, IMX708_MODE_STREAMING);
-+}
-+
-+/* Stop streaming */
-+static void imx708_stop_streaming(struct imx708 *imx708)
-+{
-+      struct i2c_client *client = v4l2_get_subdevdata(&imx708->sd);
-+      int ret;
-+
-+      /* set stream off register */
-+      ret = imx708_write_reg(imx708, IMX708_REG_MODE_SELECT,
-+                             IMX708_REG_VALUE_08BIT, IMX708_MODE_STANDBY);
-+      if (ret)
-+              dev_err(&client->dev, "%s failed to set stream\n", __func__);
-+}
-+
-+static int imx708_set_stream(struct v4l2_subdev *sd, int enable)
-+{
-+      struct imx708 *imx708 = to_imx708(sd);
-+      struct i2c_client *client = v4l2_get_subdevdata(sd);
-+      int ret = 0;
-+
-+      mutex_lock(&imx708->mutex);
-+      if (imx708->streaming == enable) {
-+              mutex_unlock(&imx708->mutex);
-+              return 0;
-+      }
-+
-+      if (enable) {
-+              ret = pm_runtime_resume_and_get(&client->dev);
-+              if (ret < 0)
-+                      goto err_unlock;
-+
-+              /*
-+               * Apply default & customized values
-+               * and then start streaming.
-+               */
-+              ret = imx708_start_streaming(imx708);
-+              if (ret)
-+                      goto err_rpm_put;
-+      } else {
-+              imx708_stop_streaming(imx708);
-+              pm_runtime_mark_last_busy(&client->dev);
-+              pm_runtime_put_autosuspend(&client->dev);
-+      }
-+
-+      imx708->streaming = enable;
-+
-+      /* vflip/hflip and hdr mode cannot change during streaming */
-+      __v4l2_ctrl_grab(imx708->vflip, enable);
-+      __v4l2_ctrl_grab(imx708->hflip, enable);
-+      __v4l2_ctrl_grab(imx708->hdr_mode, enable);
-+
-+      mutex_unlock(&imx708->mutex);
-+
-+      return ret;
-+
-+err_rpm_put:
-+      pm_runtime_put_sync(&client->dev);
-+err_unlock:
-+      mutex_unlock(&imx708->mutex);
-+
-+      return ret;
-+}
-+
-+/* Power/clock management functions */
-+static int imx708_power_on(struct device *dev)
-+{
-+      struct i2c_client *client = to_i2c_client(dev);
-+      struct v4l2_subdev *sd = i2c_get_clientdata(client);
-+      struct imx708 *imx708 = to_imx708(sd);
-+      int ret;
-+
-+      ret = regulator_bulk_enable(IMX708_NUM_SUPPLIES,
-+                                  imx708->supplies);
-+      if (ret) {
-+              dev_err(&client->dev, "%s: failed to enable regulators\n",
-+                      __func__);
-+              return ret;
-+      }
-+
-+      ret = clk_prepare_enable(imx708->xclk);
-+      if (ret) {
-+              dev_err(&client->dev, "%s: failed to enable clock\n",
-+                      __func__);
-+              goto reg_off;
-+      }
-+
-+      gpiod_set_value_cansleep(imx708->reset_gpio, 1);
-+      usleep_range(IMX708_XCLR_MIN_DELAY_US,
-+                   IMX708_XCLR_MIN_DELAY_US + IMX708_XCLR_DELAY_RANGE_US);
-+
-+      return 0;
-+
-+reg_off:
-+      regulator_bulk_disable(IMX708_NUM_SUPPLIES, imx708->supplies);
-+      return ret;
-+}
-+
-+static int imx708_power_off(struct device *dev)
-+{
-+      struct i2c_client *client = to_i2c_client(dev);
-+      struct v4l2_subdev *sd = i2c_get_clientdata(client);
-+      struct imx708 *imx708 = to_imx708(sd);
-+
-+      gpiod_set_value_cansleep(imx708->reset_gpio, 0);
-+      clk_disable_unprepare(imx708->xclk);
-+      regulator_bulk_disable(IMX708_NUM_SUPPLIES, imx708->supplies);
-+
-+      /* Force reprogramming of the common registers when powered up again. */
-+      imx708->common_regs_written = false;
-+
-+      return 0;
-+}
-+
-+static int __maybe_unused imx708_suspend(struct device *dev)
-+{
-+      struct i2c_client *client = to_i2c_client(dev);
-+      struct v4l2_subdev *sd = i2c_get_clientdata(client);
-+      struct imx708 *imx708 = to_imx708(sd);
-+
-+      if (imx708->streaming)
-+              imx708_stop_streaming(imx708);
-+
-+      return 0;
-+}
-+
-+static int __maybe_unused imx708_resume(struct device *dev)
-+{
-+      struct i2c_client *client = to_i2c_client(dev);
-+      struct v4l2_subdev *sd = i2c_get_clientdata(client);
-+      struct imx708 *imx708 = to_imx708(sd);
-+      int ret;
-+
-+      if (imx708->streaming) {
-+              ret = imx708_start_streaming(imx708);
-+              if (ret)
-+                      goto error;
-+      }
-+
-+      return 0;
-+
-+error:
-+      imx708_stop_streaming(imx708);
-+      imx708->streaming = 0;
-+      return ret;
-+}
-+
-+static int imx708_get_regulators(struct imx708 *imx708)
-+{
-+      struct i2c_client *client = v4l2_get_subdevdata(&imx708->sd);
-+      unsigned int i;
-+
-+      for (i = 0; i < IMX708_NUM_SUPPLIES; i++)
-+              imx708->supplies[i].supply = imx708_supply_name[i];
-+
-+      return devm_regulator_bulk_get(&client->dev,
-+                                     IMX708_NUM_SUPPLIES,
-+                                     imx708->supplies);
-+}
-+
-+/* Verify chip ID */
-+static int imx708_identify_module(struct imx708 *imx708)
-+{
-+      struct i2c_client *client = v4l2_get_subdevdata(&imx708->sd);
-+      int ret;
-+      u32 val;
-+
-+      ret = imx708_read_reg(imx708, IMX708_REG_CHIP_ID,
-+                            IMX708_REG_VALUE_16BIT, &val);
-+      if (ret) {
-+              dev_err(&client->dev, "failed to read chip id %x, with error %d\n",
-+                      IMX708_CHIP_ID, ret);
-+              return ret;
-+      }
-+
-+      if (val != IMX708_CHIP_ID) {
-+              dev_err(&client->dev, "chip id mismatch: %x!=%x\n",
-+                      IMX708_CHIP_ID, val);
-+              return -EIO;
-+      }
-+
-+      return 0;
-+}
-+
-+static const struct v4l2_subdev_core_ops imx708_core_ops = {
-+      .subscribe_event = v4l2_ctrl_subdev_subscribe_event,
-+      .unsubscribe_event = v4l2_event_subdev_unsubscribe,
-+};
-+
-+static const struct v4l2_subdev_video_ops imx708_video_ops = {
-+      .s_stream = imx708_set_stream,
-+};
-+
-+static const struct v4l2_subdev_pad_ops imx708_pad_ops = {
-+      .enum_mbus_code = imx708_enum_mbus_code,
-+      .get_fmt = imx708_get_pad_format,
-+      .set_fmt = imx708_set_pad_format,
-+      .get_selection = imx708_get_selection,
-+      .enum_frame_size = imx708_enum_frame_size,
-+};
-+
-+static const struct v4l2_subdev_ops imx708_subdev_ops = {
-+      .core = &imx708_core_ops,
-+      .video = &imx708_video_ops,
-+      .pad = &imx708_pad_ops,
-+};
-+
-+static const struct v4l2_subdev_internal_ops imx708_internal_ops = {
-+      .open = imx708_open,
-+};
-+
-+static const struct v4l2_ctrl_config imx708_notify_gains_ctrl = {
-+      .ops = &imx708_ctrl_ops,
-+      .id = V4L2_CID_NOTIFY_GAINS,
-+      .type = V4L2_CTRL_TYPE_U32,
-+      .min = IMX708_COLOUR_BALANCE_MIN,
-+      .max = IMX708_COLOUR_BALANCE_MAX,
-+      .step = IMX708_COLOUR_BALANCE_STEP,
-+      .def = IMX708_COLOUR_BALANCE_DEFAULT,
-+      .dims = { 4 },
-+      .elem_size = sizeof(u32),
-+};
-+
-+/* Initialize control handlers */
-+static int imx708_init_controls(struct imx708 *imx708)
-+{
-+      struct v4l2_ctrl_handler *ctrl_hdlr;
-+      struct i2c_client *client = v4l2_get_subdevdata(&imx708->sd);
-+      struct v4l2_fwnode_device_properties props;
-+      unsigned int i;
-+      int ret;
-+
-+      ctrl_hdlr = &imx708->ctrl_handler;
-+      ret = v4l2_ctrl_handler_init(ctrl_hdlr, 16);
-+      if (ret)
-+              return ret;
-+
-+      mutex_init(&imx708->mutex);
-+      ctrl_hdlr->lock = &imx708->mutex;
-+
-+      /* By default, PIXEL_RATE is read only */
-+      imx708->pixel_rate = v4l2_ctrl_new_std(ctrl_hdlr, &imx708_ctrl_ops,
-+                                             V4L2_CID_PIXEL_RATE,
-+                                             imx708->mode->pixel_rate,
-+                                             imx708->mode->pixel_rate, 1,
-+                                             imx708->mode->pixel_rate);
-+
-+      /*
-+       * Create the controls here, but mode specific limits are setup
-+       * in the imx708_set_framing_limits() call below.
-+       */
-+      imx708->vblank = v4l2_ctrl_new_std(ctrl_hdlr, &imx708_ctrl_ops,
-+                                         V4L2_CID_VBLANK, 0, 0xffff, 1, 0);
-+      imx708->hblank = v4l2_ctrl_new_std(ctrl_hdlr, &imx708_ctrl_ops,
-+                                         V4L2_CID_HBLANK, 0, 0xffff, 1, 0);
-+
-+      imx708->exposure = v4l2_ctrl_new_std(ctrl_hdlr, &imx708_ctrl_ops,
-+                                           V4L2_CID_EXPOSURE,
-+                                           IMX708_EXPOSURE_MIN,
-+                                           IMX708_EXPOSURE_MAX,
-+                                           IMX708_EXPOSURE_STEP,
-+                                           IMX708_EXPOSURE_DEFAULT);
-+
-+      v4l2_ctrl_new_std(ctrl_hdlr, &imx708_ctrl_ops, V4L2_CID_ANALOGUE_GAIN,
-+                        IMX708_ANA_GAIN_MIN, IMX708_ANA_GAIN_MAX,
-+                        IMX708_ANA_GAIN_STEP, IMX708_ANA_GAIN_DEFAULT);
-+
-+      v4l2_ctrl_new_std(ctrl_hdlr, &imx708_ctrl_ops, V4L2_CID_DIGITAL_GAIN,
-+                        IMX708_DGTL_GAIN_MIN, IMX708_DGTL_GAIN_MAX,
-+                        IMX708_DGTL_GAIN_STEP, IMX708_DGTL_GAIN_DEFAULT);
-+
-+      imx708->hflip = v4l2_ctrl_new_std(ctrl_hdlr, &imx708_ctrl_ops,
-+                                        V4L2_CID_HFLIP, 0, 1, 1, 0);
-+
-+      imx708->vflip = v4l2_ctrl_new_std(ctrl_hdlr, &imx708_ctrl_ops,
-+                                        V4L2_CID_VFLIP, 0, 1, 1, 0);
-+
-+      v4l2_ctrl_new_std_menu_items(ctrl_hdlr, &imx708_ctrl_ops,
-+                                   V4L2_CID_TEST_PATTERN,
-+                                   ARRAY_SIZE(imx708_test_pattern_menu) - 1,
-+                                   0, 0, imx708_test_pattern_menu);
-+      for (i = 0; i < 4; i++) {
-+              /*
-+               * The assumption is that
-+               * V4L2_CID_TEST_PATTERN_GREENR == V4L2_CID_TEST_PATTERN_RED + 1
-+               * V4L2_CID_TEST_PATTERN_BLUE   == V4L2_CID_TEST_PATTERN_RED + 2
-+               * V4L2_CID_TEST_PATTERN_GREENB == V4L2_CID_TEST_PATTERN_RED + 3
-+               */
-+              v4l2_ctrl_new_std(ctrl_hdlr, &imx708_ctrl_ops,
-+                                V4L2_CID_TEST_PATTERN_RED + i,
-+                                IMX708_TEST_PATTERN_COLOUR_MIN,
-+                                IMX708_TEST_PATTERN_COLOUR_MAX,
-+                                IMX708_TEST_PATTERN_COLOUR_STEP,
-+                                IMX708_TEST_PATTERN_COLOUR_MAX);
-+              /* The "Solid color" pattern is white by default */
-+      }
-+
-+      imx708->notify_gains = v4l2_ctrl_new_custom(ctrl_hdlr,
-+                                                  &imx708_notify_gains_ctrl,
-+                                                  NULL);
-+
-+      imx708->hdr_mode = v4l2_ctrl_new_std(ctrl_hdlr, &imx708_ctrl_ops,
-+                                           V4L2_CID_WIDE_DYNAMIC_RANGE,
-+                                           0, 1, 1, 0);
-+
-+      ret = v4l2_fwnode_device_parse(&client->dev, &props);
-+      if (ret)
-+              goto error;
-+
-+      v4l2_ctrl_new_fwnode_properties(ctrl_hdlr, &imx708_ctrl_ops, &props);
-+
-+      if (ctrl_hdlr->error) {
-+              ret = ctrl_hdlr->error;
-+              dev_err(&client->dev, "%s control init failed (%d)\n",
-+                      __func__, ret);
-+              goto error;
-+      }
-+
-+      imx708->hblank->flags |= V4L2_CTRL_FLAG_READ_ONLY;
-+      imx708->hflip->flags |= V4L2_CTRL_FLAG_MODIFY_LAYOUT;
-+      imx708->vflip->flags |= V4L2_CTRL_FLAG_MODIFY_LAYOUT;
-+      imx708->hdr_mode->flags |= V4L2_CTRL_FLAG_MODIFY_LAYOUT;
-+
-+      imx708->sd.ctrl_handler = ctrl_hdlr;
-+
-+      /* Setup exposure and frame/line length limits. */
-+      imx708_set_framing_limits(imx708);
-+
-+      return 0;
-+
-+error:
-+      v4l2_ctrl_handler_free(ctrl_hdlr);
-+      mutex_destroy(&imx708->mutex);
-+
-+      return ret;
-+}
-+
-+static void imx708_free_controls(struct imx708 *imx708)
-+{
-+      v4l2_ctrl_handler_free(imx708->sd.ctrl_handler);
-+      mutex_destroy(&imx708->mutex);
-+}
-+
-+static int imx708_check_hwcfg(struct device *dev)
-+{
-+      struct fwnode_handle *endpoint;
-+      struct v4l2_fwnode_endpoint ep_cfg = {
-+              .bus_type = V4L2_MBUS_CSI2_DPHY
-+      };
-+      int ret = -EINVAL;
-+
-+      endpoint = fwnode_graph_get_next_endpoint(dev_fwnode(dev), NULL);
-+      if (!endpoint) {
-+              dev_err(dev, "endpoint node not found\n");
-+              return -EINVAL;
-+      }
-+
-+      if (v4l2_fwnode_endpoint_alloc_parse(endpoint, &ep_cfg)) {
-+              dev_err(dev, "could not parse endpoint\n");
-+              goto error_out;
-+      }
-+
-+      /* Check the number of MIPI CSI2 data lanes */
-+      if (ep_cfg.bus.mipi_csi2.num_data_lanes != 2) {
-+              dev_err(dev, "only 2 data lanes are currently supported\n");
-+              goto error_out;
-+      }
-+
-+      /* Check the link frequency set in device tree */
-+      if (!ep_cfg.nr_of_link_frequencies) {
-+              dev_err(dev, "link-frequency property not found in DT\n");
-+              goto error_out;
-+      }
-+
-+      if (ep_cfg.nr_of_link_frequencies != 1 ||
-+          ep_cfg.link_frequencies[0] != IMX708_DEFAULT_LINK_FREQ) {
-+              dev_err(dev, "Link frequency not supported: %lld\n",
-+                      ep_cfg.link_frequencies[0]);
-+              goto error_out;
-+      }
-+
-+      ret = 0;
-+
-+error_out:
-+      v4l2_fwnode_endpoint_free(&ep_cfg);
-+      fwnode_handle_put(endpoint);
-+
-+      return ret;
-+}
-+
-+static int imx708_probe(struct i2c_client *client)
-+{
-+      struct device *dev = &client->dev;
-+      struct imx708 *imx708;
-+      int ret;
-+
-+      imx708 = devm_kzalloc(&client->dev, sizeof(*imx708), GFP_KERNEL);
-+      if (!imx708)
-+              return -ENOMEM;
-+
-+      v4l2_i2c_subdev_init(&imx708->sd, client, &imx708_subdev_ops);
-+
-+      /* Check the hardware configuration in device tree */
-+      if (imx708_check_hwcfg(dev))
-+              return -EINVAL;
-+
-+      /* Get system clock (xclk) */
-+      imx708->xclk = devm_clk_get(dev, NULL);
-+      if (IS_ERR(imx708->xclk)) {
-+              dev_err(dev, "failed to get xclk\n");
-+              return PTR_ERR(imx708->xclk);
-+      }
-+
-+      imx708->xclk_freq = clk_get_rate(imx708->xclk);
-+      if (imx708->xclk_freq != IMX708_XCLK_FREQ) {
-+              dev_err(dev, "xclk frequency not supported: %d Hz\n",
-+                      imx708->xclk_freq);
-+              return -EINVAL;
-+      }
-+
-+      ret = imx708_get_regulators(imx708);
-+      if (ret) {
-+              dev_err(dev, "failed to get regulators\n");
-+              return ret;
-+      }
-+
-+      /* Request optional enable pin */
-+      imx708->reset_gpio = devm_gpiod_get_optional(dev, "reset",
-+                                                   GPIOD_OUT_HIGH);
-+
-+      /*
-+       * The sensor must be powered for imx708_identify_module()
-+       * to be able to read the CHIP_ID register
-+       */
-+      ret = imx708_power_on(dev);
-+      if (ret)
-+              return ret;
-+
-+      ret = imx708_identify_module(imx708);
-+      if (ret)
-+              goto error_power_off;
-+
-+      /* Initialize default format */
-+      imx708_set_default_format(imx708);
-+
-+      /*
-+       * Enable runtime PM with autosuspend. As the device has been powered
-+       * manually, mark it as active, and increase the usage count without
-+       * resuming the device.
-+       */
-+      pm_runtime_set_active(dev);
-+      pm_runtime_get_noresume(dev);
-+      pm_runtime_enable(dev);
-+      pm_runtime_set_autosuspend_delay(dev, 1000);
-+      pm_runtime_use_autosuspend(dev);
-+
-+      /* This needs the pm runtime to be registered. */
-+      ret = imx708_init_controls(imx708);
-+      if (ret)
-+              goto error_power_off;
-+
-+      /* Initialize subdev */
-+      imx708->sd.internal_ops = &imx708_internal_ops;
-+      imx708->sd.flags |= V4L2_SUBDEV_FL_HAS_DEVNODE |
-+                          V4L2_SUBDEV_FL_HAS_EVENTS;
-+      imx708->sd.entity.function = MEDIA_ENT_F_CAM_SENSOR;
-+
-+      /* Initialize source pad */
-+      imx708->pad.flags = MEDIA_PAD_FL_SOURCE;
-+
-+      ret = media_entity_pads_init(&imx708->sd.entity, 1, &imx708->pad);
-+      if (ret) {
-+              dev_err(dev, "failed to init entity pads: %d\n", ret);
-+              goto error_handler_free;
-+      }
-+
-+      ret = v4l2_async_register_subdev_sensor(&imx708->sd);
-+      if (ret < 0) {
-+              dev_err(dev, "failed to register sensor sub-device: %d\n", ret);
-+              goto error_media_entity;
-+      }
-+
-+      /*
-+       * Decrease the PM usage count. The device will get suspended after the
-+       * autosuspend delay, turning the power off.
-+       */
-+      pm_runtime_mark_last_busy(dev);
-+      pm_runtime_put_autosuspend(dev);
-+
-+      return 0;
-+
-+error_media_entity:
-+      media_entity_cleanup(&imx708->sd.entity);
-+
-+error_handler_free:
-+      imx708_free_controls(imx708);
-+
-+error_power_off:
-+      pm_runtime_disable(&client->dev);
-+      pm_runtime_put_noidle(&client->dev);
-+      imx708_power_off(&client->dev);
-+
-+      return ret;
-+}
-+
-+static void imx708_remove(struct i2c_client *client)
-+{
-+      struct v4l2_subdev *sd = i2c_get_clientdata(client);
-+      struct imx708 *imx708 = to_imx708(sd);
-+
-+      v4l2_async_unregister_subdev(sd);
-+      media_entity_cleanup(&sd->entity);
-+      imx708_free_controls(imx708);
-+
-+      pm_runtime_disable(&client->dev);
-+      if (!pm_runtime_status_suspended(&client->dev))
-+              imx708_power_off(&client->dev);
-+      pm_runtime_set_suspended(&client->dev);
-+}
-+
-+static const struct of_device_id imx708_dt_ids[] = {
-+      { .compatible = "sony,imx708" },
-+      { /* sentinel */ }
-+};
-+MODULE_DEVICE_TABLE(of, imx708_dt_ids);
-+
-+static const struct dev_pm_ops imx708_pm_ops = {
-+      SET_SYSTEM_SLEEP_PM_OPS(imx708_suspend, imx708_resume)
-+      SET_RUNTIME_PM_OPS(imx708_power_off, imx708_power_on, NULL)
-+};
-+
-+static struct i2c_driver imx708_i2c_driver = {
-+      .driver = {
-+              .name = "imx708",
-+              .of_match_table = imx708_dt_ids,
-+              .pm = &imx708_pm_ops,
-+      },
-+      .probe = imx708_probe,
-+      .remove = imx708_remove,
-+};
-+
-+module_i2c_driver(imx708_i2c_driver);
-+
-+MODULE_AUTHOR("David Plowman <david.plowman@raspberrypi.com>");
-+MODULE_DESCRIPTION("Sony IMX708 sensor driver");
-+MODULE_LICENSE("GPL");
diff --git a/target/linux/starfive/patches-6.6/0088-media-i2c-imx708-Delete-gain.patch b/target/linux/starfive/patches-6.6/0088-media-i2c-imx708-Delete-gain.patch
deleted file mode 100644 (file)
index c3971ed..0000000
+++ /dev/null
@@ -1,69 +0,0 @@
-From 280ab217867d0b934454a837540eab665e854b47 Mon Sep 17 00:00:00 2001
-From: Changhuang Liang <changhuang.liang@starfivetech.com>
-Date: Mon, 3 Apr 2023 15:28:11 +0800
-Subject: [PATCH 088/116] media: i2c: imx708: Delete gain
-
-Delete gain.
-
-Signed-off-by: Changhuang Liang <changhuang.liang@starfivetech.com>
----
- drivers/media/i2c/imx708.c | 27 ---------------------------
- 1 file changed, 27 deletions(-)
-
---- a/drivers/media/i2c/imx708.c
-+++ b/drivers/media/i2c/imx708.c
-@@ -777,7 +777,6 @@ struct imx708 {
-       struct v4l2_ctrl *hblank;
-       struct v4l2_ctrl *red_balance;
-       struct v4l2_ctrl *blue_balance;
--      struct v4l2_ctrl *notify_gains;
-       struct v4l2_ctrl *hdr_mode;
-       /* Current mode */
-@@ -1108,16 +1107,6 @@ static int imx708_set_ctrl(struct v4l2_c
-               ret = imx708_set_frame_length(imx708,
-                                             imx708->mode->height + ctrl->val);
-               break;
--      case V4L2_CID_NOTIFY_GAINS:
--              ret = imx708_write_reg(imx708, IMX708_REG_COLOUR_BALANCE_BLUE,
--                                     IMX708_REG_VALUE_16BIT,
--                                     imx708->notify_gains->p_new.p_u32[0]);
--              if (ret)
--                      break;
--              ret = imx708_write_reg(imx708, IMX708_REG_COLOUR_BALANCE_RED,
--                                     IMX708_REG_VALUE_16BIT,
--                                     imx708->notify_gains->p_new.p_u32[3]);
--              break;
-       case V4L2_CID_WIDE_DYNAMIC_RANGE:
-               get_mode_table(&mode_list, &num_modes, ctrl->val);
-               imx708->mode = v4l2_find_nearest_size(mode_list,
-@@ -1584,18 +1573,6 @@ static const struct v4l2_subdev_internal
-       .open = imx708_open,
- };
--static const struct v4l2_ctrl_config imx708_notify_gains_ctrl = {
--      .ops = &imx708_ctrl_ops,
--      .id = V4L2_CID_NOTIFY_GAINS,
--      .type = V4L2_CTRL_TYPE_U32,
--      .min = IMX708_COLOUR_BALANCE_MIN,
--      .max = IMX708_COLOUR_BALANCE_MAX,
--      .step = IMX708_COLOUR_BALANCE_STEP,
--      .def = IMX708_COLOUR_BALANCE_DEFAULT,
--      .dims = { 4 },
--      .elem_size = sizeof(u32),
--};
--
- /* Initialize control handlers */
- static int imx708_init_controls(struct imx708 *imx708)
- {
-@@ -1670,10 +1647,6 @@ static int imx708_init_controls(struct i
-               /* The "Solid color" pattern is white by default */
-       }
--      imx708->notify_gains = v4l2_ctrl_new_custom(ctrl_hdlr,
--                                                  &imx708_notify_gains_ctrl,
--                                                  NULL);
--
-       imx708->hdr_mode = v4l2_ctrl_new_std(ctrl_hdlr, &imx708_ctrl_ops,
-                                            V4L2_CID_WIDE_DYNAMIC_RANGE,
-                                            0, 1, 1, 0);
diff --git a/target/linux/starfive/patches-6.6/0089-dt-bindings-display-Add-yamls-for-JH7110-display-sys.patch b/target/linux/starfive/patches-6.6/0089-dt-bindings-display-Add-yamls-for-JH7110-display-sys.patch
deleted file mode 100644 (file)
index e8baa80..0000000
+++ /dev/null
@@ -1,270 +0,0 @@
-From aa4febf074cbaad81c981a5c6b55324a6f676fb7 Mon Sep 17 00:00:00 2001
-From: "shengyang.chen" <shengyang.chen@starfivetech.com>
-Date: Tue, 13 Jun 2023 14:22:29 +0800
-Subject: [PATCH 089/116] dt-bindings: display: Add yamls for JH7110 display
- system and hdmi
-
-StarFive SoCs like the jh7110 use display system based on verisilicon IP, use hdmi
-base on innosilicon IP. Add bindings for them.
-
-Signed-off-by: Shengyang Chen <shengyang.chen@starfivetech.com>
----
- .../display/verisilicon/starfive-hdmi.yaml    |  92 +++++++++++++++
- .../display/verisilicon/verisilicon-dc.yaml   | 109 ++++++++++++++++++
- .../display/verisilicon/verisilicon-drm.yaml  |  41 +++++++
- 3 files changed, 242 insertions(+)
- create mode 100644 Documentation/devicetree/bindings/display/verisilicon/starfive-hdmi.yaml
- create mode 100644 Documentation/devicetree/bindings/display/verisilicon/verisilicon-dc.yaml
- create mode 100644 Documentation/devicetree/bindings/display/verisilicon/verisilicon-drm.yaml
-
---- /dev/null
-+++ b/Documentation/devicetree/bindings/display/verisilicon/starfive-hdmi.yaml
-@@ -0,0 +1,92 @@
-+# SPDX-License-Identifier: GPL-2.0
-+%YAML 1.2
-+---
-+$id: http://devicetree.org/schemas/display/verisilicon/starfive-hdmi.yaml#
-+$schema: http://devicetree.org/meta-schemas/core.yaml#
-+
-+title: StarFive SoC HDMI transmiter
-+
-+description:
-+  The StarFive SoC uses the HDMI signal transmiter based on innosilicon IP 
-+  to generate HDMI signal from its input and transmit the signal to the screen.
-+
-+maintainers:
-+  - Keith Zhao <keith.zhao@starfivetech.com>
-+
-+properties:
-+  compatible:
-+    const: starfive,hdmi
-+
-+  reg:
-+    minItems: 1
-+
-+  interrupts:
-+    items:
-+      - description: The HDMI hot plug detection interrupt.
-+
-+  clocks:
-+    items:
-+      - description: System clock of HDMI module.
-+      - description: Mclk clock of HDMI audio.
-+      - description: Bclk clock of HDMI audio.
-+      - description: Pixel clock generated by HDMI module.
-+
-+  clock-names:
-+    items:
-+      - const: sysclk
-+      - const: mclk
-+      - const: bclk
-+      - const: pclk
-+
-+  resets:
-+    items:
-+      - description: Reset for HDMI module.
-+
-+  reset-names:
-+    items:
-+      - const: hdmi_tx
-+
-+  '#sound-dai-cells':
-+    const: 0
-+
-+  port:
-+    $ref: /schemas/graph.yaml#/properties/port
-+    description:
-+      Port node with one endpoint connected to a display connector node.
-+
-+required:
-+  - compatible
-+  - reg
-+  - interrupts
-+  - clocks
-+  - clock-names
-+  - resets
-+  - reset-names
-+  - '#sound-dai-cells'
-+  - port
-+
-+additionalProperties: false
-+
-+examples:
-+  - |
-+    hdmi: hdmi@29590000 {
-+      compatible = "starfive,hdmi";
-+      reg = <0x29590000 0x4000>;
-+      interrupts = <99>;
-+      clocks = <&voutcrg 17>,
-+               <&voutcrg 15>,
-+               <&voutcrg 16>,
-+               <&hdmitx0_pixelclk>;
-+      clock-names = "sysclk", "mclk","bclk","pclk";
-+      resets = <&voutcrg 9>;
-+      reset-names = "hdmi_tx";
-+      #sound-dai-cells = <0>;
-+      hdmi_in: port {
-+          #address-cells = <1>;
-+          #size-cells = <0>;
-+          hdmi_input: endpoint@0 {
-+            reg = <0>;
-+            remote-endpoint = <&dc_out_dpi0>;
-+          };
-+      };
-+    };
---- /dev/null
-+++ b/Documentation/devicetree/bindings/display/verisilicon/verisilicon-dc.yaml
-@@ -0,0 +1,109 @@
-+# SPDX-License-Identifier: GPL-2.0
-+%YAML 1.2
-+---
-+$id: http://devicetree.org/schemas/display/verisilicon/verisilicon-dc.yaml#
-+$schema: http://devicetree.org/meta-schemas/core.yaml#
-+
-+title: StarFive SoC display controller
-+
-+description:
-+  The StarFive SoC uses the display controller based on Verisilicon IP 
-+  to transfer the image data from a video memory
-+  buffer to an external LCD interface.
-+
-+maintainers:
-+  - Keith Zhao <keith.zhao@starfivetech.com>
-+
-+properties:
-+  compatible:
-+    const: verisilicon,dc8200
-+
-+  reg:
-+    maxItems: 3
-+
-+  interrupts:
-+    items:
-+      - description: The interrupt will be generated when DC finish one frame
-+
-+  clocks:
-+    items:
-+      - description: Clock for display system noc bus.
-+      - description: Pixel clock for display channel 0.
-+      - description: Pixel clock for display channel 1.
-+      - description: Clock for axi interface of display controller.
-+      - description: Core clock for display controller.
-+      - description: Clock for ahb interface of display controller.
-+      - description: External HDMI pixel clock.
-+      - description: Parent clock for pixel clock
-+
-+  clock-names:
-+    items:
-+      - const: clk_vout_noc_disp
-+      - const: clk_vout_pix0
-+      - const: clk_vout_pix1
-+      - const: clk_vout_axi
-+      - const: clk_vout_core
-+      - const: clk_vout_vout_ahb
-+      - const: hdmitx0_pixel
-+      - const: clk_vout_dc8200
-+
-+  resets:
-+    items:
-+      - description: Reset for axi interface of display controller.
-+      - description: Reset for ahb interface of display controller.
-+      - description: Core reset of display controller.
-+
-+  reset-names:
-+    items:
-+      - const: rst_vout_axi
-+      - const: rst_vout_ahb
-+      - const: rst_vout_core
-+
-+  port:
-+    $ref: /schemas/graph.yaml#/properties/port
-+    description:
-+      Port node with one endpoint connected to a hdmi node.
-+
-+required:
-+  - compatible
-+  - reg
-+  - interrupts
-+  - clocks
-+  - clock-names
-+  - resets
-+  - reset-names
-+  - port
-+
-+additionalProperties: false
-+
-+examples:
-+  - |
-+    dc8200: dc8200@29400000 {
-+      compatible = "verisilicon,dc8200";
-+      reg = <0x29400000 0x100>,
-+            <0x29400800 0x2000>,
-+            <0x295B0000 0x90>;
-+      interrupts = <95>;
-+      clocks = <&syscrg 60>,
-+               <&voutcrg 7>,
-+               <&voutcrg 8>,
-+               <&voutcrg 4>,
-+               <&voutcrg 5>,
-+               <&voutcrg 6>,
-+               <&hdmitx0_pixelclk>,
-+               <&voutcrg 1>;
-+      clock-names = "clk_vout_noc_disp", "clk_vout_pix0", "clk_vout_pix1", "clk_vout_axi",
-+                    "clk_vout_core", "clk_vout_vout_ahb", "hdmitx0_pixel","clk_vout_dc8200";
-+      resets = <&voutcrg 0>,
-+               <&voutcrg 1>,
-+               <&voutcrg 2>;
-+      reset-names = "rst_vout_axi","rst_vout_ahb","rst_vout_core";
-+      dc_out: port {
-+          #address-cells = <1>;
-+          #size-cells = <0>;
-+          dc_out_dpi0: endpoint@0 {
-+              reg = <0>;
-+              remote-endpoint = <&hdmi_input>;
-+          };
-+      };
-+    };
---- /dev/null
-+++ b/Documentation/devicetree/bindings/display/verisilicon/verisilicon-drm.yaml
-@@ -0,0 +1,41 @@
-+# SPDX-License-Identifier: (GPL-2.0-only)
-+%YAML 1.2
-+---
-+$id: http://devicetree.org/schemas/display/verisilicon/verisilicon-drm.yaml#
-+$schema: http://devicetree.org/meta-schemas/core.yaml#
-+
-+title: Verisilicon DRM master device
-+
-+maintainers:
-+  - Keith Zhao <keith.zhao@starfivetech.com>
-+
-+description: |
-+  The Verisilicon DRM master device is a virtual device needed to list all
-+  display controller or other display interface nodes that comprise the
-+  graphics subsystem.
-+
-+properties:
-+  compatible:
-+    const: verisilicon,display-subsystem
-+
-+  ports:
-+    $ref: /schemas/types.yaml#/definitions/phandle-array
-+    items:
-+      maxItems: 1
-+    description: |
-+      Should contain a list of phandles pointing to display interface ports
-+      of display controller devices. Display controller definitions as defined in
-+      Documentation/devicetree/bindings/display/verisilicon/verisilicon-dc.yaml
-+
-+required:
-+  - compatible
-+  - ports
-+
-+additionalProperties: false
-+
-+examples:
-+  - |
-+    display-subsystem {
-+        compatible = "verisilicon,display-subsystem";
-+        ports = <&dc_out>;
-+    };
diff --git a/target/linux/starfive/patches-6.6/0090-soc-starfive-jh71xx_pmu-Add-EVENT_TURN_OFF-register-.patch b/target/linux/starfive/patches-6.6/0090-soc-starfive-jh71xx_pmu-Add-EVENT_TURN_OFF-register-.patch
deleted file mode 100644 (file)
index 7a6bfa8..0000000
+++ /dev/null
@@ -1,82 +0,0 @@
-From 5cbf4154da600af8a2e6a2f8d57d1f212abf3f92 Mon Sep 17 00:00:00 2001
-From: Hal Feng <hal.feng@starfivetech.com>
-Date: Fri, 13 Oct 2023 14:10:24 +0800
-Subject: [PATCH 090/116] soc: starfive: jh71xx_pmu: Add EVENT_TURN_OFF
- register writing support
-
-Add and export starfive_pmu_hw_event_turn_off_mask() to
-write EVENT_TURN_OFF register.
-
-Signed-off-by: Hal Feng <hal.feng@starfivetech.com>
----
- drivers/pmdomain/starfive/jh71xx-pmu.c | 11 ++++++++++
- include/soc/starfive/jh7110_pmu.h      | 29 ++++++++++++++++++++++++++
- 2 files changed, 40 insertions(+)
- create mode 100644 include/soc/starfive/jh7110_pmu.h
-
---- a/drivers/pmdomain/starfive/jh71xx-pmu.c
-+++ b/drivers/pmdomain/starfive/jh71xx-pmu.c
-@@ -16,6 +16,7 @@
- #include <dt-bindings/power/starfive,jh7110-pmu.h>
- /* register offset */
-+#define JH71XX_PMU_HW_EVENT_TURN_OFF  0x08
- #define JH71XX_PMU_SW_TURN_ON_POWER   0x0C
- #define JH71XX_PMU_SW_TURN_OFF_POWER  0x10
- #define JH71XX_PMU_SW_ENCOURAGE               0x44
-@@ -83,6 +84,14 @@ struct jh71xx_pmu_dev {
-       struct generic_pm_domain genpd;
- };
-+static void __iomem *pmu_base;
-+
-+void starfive_pmu_hw_event_turn_off_mask(u32 mask)
-+{
-+      writel(mask, pmu_base + JH71XX_PMU_HW_EVENT_TURN_OFF);
-+}
-+EXPORT_SYMBOL(starfive_pmu_hw_event_turn_off_mask);
-+
- static int jh71xx_pmu_get_state(struct jh71xx_pmu_dev *pmd, u32 mask, bool *is_on)
- {
-       struct jh71xx_pmu *pmu = pmd->pmu;
-@@ -334,6 +343,8 @@ static int jh71xx_pmu_probe(struct platf
-       if (IS_ERR(pmu->base))
-               return PTR_ERR(pmu->base);
-+      pmu_base = pmu->base;
-+
-       spin_lock_init(&pmu->lock);
-       match_data = of_device_get_match_data(dev);
---- /dev/null
-+++ b/include/soc/starfive/jh7110_pmu.h
-@@ -0,0 +1,29 @@
-+/* SPDX-License-Identifier: GPL-2.0-or-later */
-+/*
-+ * PMU driver for the StarFive JH7110 SoC
-+ *
-+ * Copyright (C) 2022 samin <samin.guo@starfivetech.com>
-+ */
-+
-+#ifndef __SOC_STARFIVE_JH7110_PMU_H__
-+#define __SOC_STARFIVE_JH7110_PMU_H__
-+
-+#include <linux/bits.h>
-+#include <linux/types.h>
-+
-+enum PMU_HARD_EVENT {
-+      PMU_HW_EVENT_RTC        = BIT(0),
-+      PMU_HW_EVENT_GMAC       = BIT(1),
-+      PMU_HW_EVENT_RFU        = BIT(2),
-+      PMU_HW_EVENT_RGPIO0     = BIT(3),
-+      PMU_HW_EVENT_RGPIO1     = BIT(4),
-+      PMU_HW_EVENT_RGPIO2     = BIT(5),
-+      PMU_HW_EVENT_RGPIO3     = BIT(6),
-+      PMU_HW_EVENT_GPU        = BIT(7),
-+      PMU_HW_EVENT_ALL        = GENMASK(7, 0),
-+};
-+
-+void starfive_pmu_hw_event_turn_off_mask(u32 mask);
-+
-+#endif /* __SOC_STARFIVE_JH7110_PMU_H__ */
-+
diff --git a/target/linux/starfive/patches-6.6/0091-workqueue-Enable-flush_scheduled_work.patch b/target/linux/starfive/patches-6.6/0091-workqueue-Enable-flush_scheduled_work.patch
deleted file mode 100644 (file)
index a6b6966..0000000
+++ /dev/null
@@ -1,22 +0,0 @@
-From ab436ea7ffb6c464616addad98632c81a321844a Mon Sep 17 00:00:00 2001
-From: Hal Feng <hal.feng@starfivetech.com>
-Date: Tue, 12 Dec 2023 17:56:58 +0800
-Subject: [PATCH 091/116] workqueue: Enable flush_scheduled_work()
-
-Enable flush_scheduled_work() for JH7110 GPU.
-
-Signed-off-by: Hal Feng <hal.feng@starfivetech.com>
----
- include/linux/workqueue.h | 1 -
- 1 file changed, 1 deletion(-)
-
---- a/include/linux/workqueue.h
-+++ b/include/linux/workqueue.h
-@@ -636,7 +636,6 @@ extern void __warn_flushing_systemwide_w
- /* Please stop using this function, for this function will be removed in near future. */
- #define flush_scheduled_work()                                                \
- ({                                                                    \
--      __warn_flushing_systemwide_wq();                                \
-       __flush_workqueue(system_wq);                                   \
- })
diff --git a/target/linux/starfive/patches-6.6/0092-riscv-Optimize-memcpy-with-aligned-version.patch b/target/linux/starfive/patches-6.6/0092-riscv-Optimize-memcpy-with-aligned-version.patch
deleted file mode 100644 (file)
index 39c2723..0000000
+++ /dev/null
@@ -1,506 +0,0 @@
-From dedbbfd891e4d0cdb825454eddfbf8386d0025b3 Mon Sep 17 00:00:00 2001
-From: Mason Huo <mason.huo@starfivetech.com>
-Date: Tue, 20 Jun 2023 13:37:52 +0800
-Subject: [PATCH 092/116] riscv: Optimize memcpy with aligned version
-
-Optimizing the 128 byte align case, this will improve the
-performance of large block memcpy.
-
-Here we combine the memcpy of glibc and kernel.
-
-Signed-off-by: Mason Huo <mason.huo@starfivetech.com>
-Signed-off-by: Hal Feng <hal.feng@starfivetech.com>
----
- arch/riscv/lib/Makefile                       |   3 +-
- arch/riscv/lib/{memcpy.S => memcpy_aligned.S} |  36 +--
- arch/riscv/lib/string.c                       | 266 ++++++++++++++++++
- 3 files changed, 273 insertions(+), 32 deletions(-)
- rename arch/riscv/lib/{memcpy.S => memcpy_aligned.S} (67%)
- create mode 100644 arch/riscv/lib/string.c
-
---- a/arch/riscv/lib/Makefile
-+++ b/arch/riscv/lib/Makefile
-@@ -1,6 +1,5 @@
- # SPDX-License-Identifier: GPL-2.0-only
- lib-y                 += delay.o
--lib-y                 += memcpy.o
- lib-y                 += memset.o
- lib-y                 += memmove.o
- lib-y                 += strcmp.o
-@@ -9,5 +8,7 @@ lib-y                  += strncmp.o
- lib-$(CONFIG_MMU)     += uaccess.o
- lib-$(CONFIG_64BIT)   += tishift.o
- lib-$(CONFIG_RISCV_ISA_ZICBOZ)        += clear_page.o
-+lib-y                 += string.o
-+lib-y                 += memcpy_aligned.o
- obj-$(CONFIG_FUNCTION_ERROR_INJECTION) += error-inject.o
---- a/arch/riscv/lib/memcpy.S
-+++ /dev/null
-@@ -1,110 +0,0 @@
--/* SPDX-License-Identifier: GPL-2.0-only */
--/*
-- * Copyright (C) 2013 Regents of the University of California
-- */
--
--#include <linux/linkage.h>
--#include <asm/asm.h>
--
--/* void *memcpy(void *, const void *, size_t) */
--ENTRY(__memcpy)
--WEAK(memcpy)
--      move t6, a0  /* Preserve return value */
--
--      /* Defer to byte-oriented copy for small sizes */
--      sltiu a3, a2, 128
--      bnez a3, 4f
--      /* Use word-oriented copy only if low-order bits match */
--      andi a3, t6, SZREG-1
--      andi a4, a1, SZREG-1
--      bne a3, a4, 4f
--
--      beqz a3, 2f  /* Skip if already aligned */
--      /*
--       * Round to nearest double word-aligned address
--       * greater than or equal to start address
--       */
--      andi a3, a1, ~(SZREG-1)
--      addi a3, a3, SZREG
--      /* Handle initial misalignment */
--      sub a4, a3, a1
--1:
--      lb a5, 0(a1)
--      addi a1, a1, 1
--      sb a5, 0(t6)
--      addi t6, t6, 1
--      bltu a1, a3, 1b
--      sub a2, a2, a4  /* Update count */
--
--2:
--      andi a4, a2, ~((16*SZREG)-1)
--      beqz a4, 4f
--      add a3, a1, a4
--3:
--      REG_L a4,       0(a1)
--      REG_L a5,   SZREG(a1)
--      REG_L a6, 2*SZREG(a1)
--      REG_L a7, 3*SZREG(a1)
--      REG_L t0, 4*SZREG(a1)
--      REG_L t1, 5*SZREG(a1)
--      REG_L t2, 6*SZREG(a1)
--      REG_L t3, 7*SZREG(a1)
--      REG_L t4, 8*SZREG(a1)
--      REG_L t5, 9*SZREG(a1)
--      REG_S a4,       0(t6)
--      REG_S a5,   SZREG(t6)
--      REG_S a6, 2*SZREG(t6)
--      REG_S a7, 3*SZREG(t6)
--      REG_S t0, 4*SZREG(t6)
--      REG_S t1, 5*SZREG(t6)
--      REG_S t2, 6*SZREG(t6)
--      REG_S t3, 7*SZREG(t6)
--      REG_S t4, 8*SZREG(t6)
--      REG_S t5, 9*SZREG(t6)
--      REG_L a4, 10*SZREG(a1)
--      REG_L a5, 11*SZREG(a1)
--      REG_L a6, 12*SZREG(a1)
--      REG_L a7, 13*SZREG(a1)
--      REG_L t0, 14*SZREG(a1)
--      REG_L t1, 15*SZREG(a1)
--      addi a1, a1, 16*SZREG
--      REG_S a4, 10*SZREG(t6)
--      REG_S a5, 11*SZREG(t6)
--      REG_S a6, 12*SZREG(t6)
--      REG_S a7, 13*SZREG(t6)
--      REG_S t0, 14*SZREG(t6)
--      REG_S t1, 15*SZREG(t6)
--      addi t6, t6, 16*SZREG
--      bltu a1, a3, 3b
--      andi a2, a2, (16*SZREG)-1  /* Update count */
--
--4:
--      /* Handle trailing misalignment */
--      beqz a2, 6f
--      add a3, a1, a2
--
--      /* Use word-oriented copy if co-aligned to word boundary */
--      or a5, a1, t6
--      or a5, a5, a3
--      andi a5, a5, 3
--      bnez a5, 5f
--7:
--      lw a4, 0(a1)
--      addi a1, a1, 4
--      sw a4, 0(t6)
--      addi t6, t6, 4
--      bltu a1, a3, 7b
--
--      ret
--
--5:
--      lb a4, 0(a1)
--      addi a1, a1, 1
--      sb a4, 0(t6)
--      addi t6, t6, 1
--      bltu a1, a3, 5b
--6:
--      ret
--END(__memcpy)
--SYM_FUNC_ALIAS(__pi_memcpy, __memcpy)
--SYM_FUNC_ALIAS(__pi___memcpy, __memcpy)
---- /dev/null
-+++ b/arch/riscv/lib/memcpy_aligned.S
-@@ -0,0 +1,84 @@
-+/* SPDX-License-Identifier: GPL-2.0-only */
-+/*
-+ * Copyright (C) 2013 Regents of the University of California
-+ */
-+
-+#include <linux/linkage.h>
-+#include <asm/asm.h>
-+
-+/* void *__memcpy_aligned(void *, const void *, size_t) */
-+ENTRY(__memcpy_aligned)
-+      move t6, a0  /* Preserve return value */
-+
-+2:
-+      andi a4, a2, ~((16*SZREG)-1)
-+      beqz a4, 4f
-+      add a3, a1, a4
-+3:
-+      REG_L a4,       0(a1)
-+      REG_L a5,   SZREG(a1)
-+      REG_L a6, 2*SZREG(a1)
-+      REG_L a7, 3*SZREG(a1)
-+      REG_L t0, 4*SZREG(a1)
-+      REG_L t1, 5*SZREG(a1)
-+      REG_L t2, 6*SZREG(a1)
-+      REG_L t3, 7*SZREG(a1)
-+      REG_L t4, 8*SZREG(a1)
-+      REG_L t5, 9*SZREG(a1)
-+      REG_S a4,       0(t6)
-+      REG_S a5,   SZREG(t6)
-+      REG_S a6, 2*SZREG(t6)
-+      REG_S a7, 3*SZREG(t6)
-+      REG_S t0, 4*SZREG(t6)
-+      REG_S t1, 5*SZREG(t6)
-+      REG_S t2, 6*SZREG(t6)
-+      REG_S t3, 7*SZREG(t6)
-+      REG_S t4, 8*SZREG(t6)
-+      REG_S t5, 9*SZREG(t6)
-+      REG_L a4, 10*SZREG(a1)
-+      REG_L a5, 11*SZREG(a1)
-+      REG_L a6, 12*SZREG(a1)
-+      REG_L a7, 13*SZREG(a1)
-+      REG_L t0, 14*SZREG(a1)
-+      REG_L t1, 15*SZREG(a1)
-+      addi a1, a1, 16*SZREG
-+      REG_S a4, 10*SZREG(t6)
-+      REG_S a5, 11*SZREG(t6)
-+      REG_S a6, 12*SZREG(t6)
-+      REG_S a7, 13*SZREG(t6)
-+      REG_S t0, 14*SZREG(t6)
-+      REG_S t1, 15*SZREG(t6)
-+      addi t6, t6, 16*SZREG
-+      bltu a1, a3, 3b
-+      andi a2, a2, (16*SZREG)-1  /* Update count */
-+
-+4:
-+      /* Handle trailing misalignment */
-+      beqz a2, 6f
-+      add a3, a1, a2
-+
-+      /* Use word-oriented copy if co-aligned to word boundary */
-+      or a5, a1, t6
-+      or a5, a5, a3
-+      andi a5, a5, 3
-+      bnez a5, 5f
-+7:
-+      lw a4, 0(a1)
-+      addi a1, a1, 4
-+      sw a4, 0(t6)
-+      addi t6, t6, 4
-+      bltu a1, a3, 7b
-+
-+      ret
-+
-+5:
-+      lb a4, 0(a1)
-+      addi a1, a1, 1
-+      sb a4, 0(t6)
-+      addi t6, t6, 1
-+      bltu a1, a3, 5b
-+6:
-+      ret
-+END(__memcpy_aligned)
-+SYM_FUNC_ALIAS(__pi_memcpy, __memcpy_aligned)
-+SYM_FUNC_ALIAS(__pi___memcpy, __memcpy_aligned)
---- /dev/null
-+++ b/arch/riscv/lib/string.c
-@@ -0,0 +1,266 @@
-+// SPDX-License-Identifier: GPL-2.0-only
-+/*
-+ * Copy memory to memory until the specified number of bytes
-+ * has been copied.  Overlap is NOT handled correctly.
-+ * Copyright (C) 1991-2020 Free Software Foundation, Inc.
-+ * This file is part of the GNU C Library.
-+ * Contributed by Torbjorn Granlund (tege@sics.se).
-+ *
-+ * The GNU C Library is free software; you can redistribute it and/or
-+ * modify it under the terms of the GNU Lesser General Public
-+ * License as published by the Free Software Foundation; either
-+ * version 2.1 of the License, or (at your option) any later version.
-+ *
-+ * The GNU C Library is distributed in the hope that it will be useful,
-+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
-+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-+ * Lesser General Public License for more details.
-+ *
-+ * You should have received a copy of the GNU Lesser General Public
-+ * License along with the GNU C Library; if not, see
-+ * <https://www.gnu.org/licenses/>.
-+ *
-+ */
-+
-+#define __NO_FORTIFY
-+#include <linux/types.h>
-+#include <linux/module.h>
-+
-+#define MERGE(w0, sh_1, w1, sh_2) (((w0) >> (sh_1)) | ((w1) << (sh_2)))
-+#define OP_T_THRES      16
-+#define op_t    unsigned long
-+#define OPSIZ   (sizeof(op_t))
-+#define OPSIZ_MASK   (sizeof(op_t) - 1)
-+#define FAST_COPY_THRES  (128)
-+#define byte    unsigned char
-+
-+static void _wordcopy_fwd_aligned(long dstp, long srcp, size_t len)
-+{
-+      op_t a0, a1;
-+
-+      switch (len % 8) {
-+      case 2:
-+              a0 = ((op_t *) srcp)[0];
-+              srcp -= 6 * OPSIZ;
-+              dstp -= 7 * OPSIZ;
-+              len += 6;
-+              goto do1;
-+      case 3:
-+              a1 = ((op_t *) srcp)[0];
-+              srcp -= 5 * OPSIZ;
-+              dstp -= 6 * OPSIZ;
-+              len += 5;
-+              goto do2;
-+      case 4:
-+              a0 = ((op_t *) srcp)[0];
-+              srcp -= 4 * OPSIZ;
-+              dstp -= 5 * OPSIZ;
-+              len += 4;
-+              goto do3;
-+      case 5:
-+              a1 = ((op_t *) srcp)[0];
-+              srcp -= 3 * OPSIZ;
-+              dstp -= 4 * OPSIZ;
-+              len += 3;
-+              goto do4;
-+      case 6:
-+              a0 = ((op_t *) srcp)[0];
-+              srcp -= 2 * OPSIZ;
-+              dstp -= 3 * OPSIZ;
-+              len += 2;
-+              goto do5;
-+      case 7:
-+              a1 = ((op_t *) srcp)[0];
-+              srcp -= 1 * OPSIZ;
-+              dstp -= 2 * OPSIZ;
-+              len += 1;
-+              goto do6;
-+
-+      case 0:
-+              if (OP_T_THRES <= 3 * OPSIZ && len == 0)
-+                      return;
-+              a0 = ((op_t *) srcp)[0];
-+              srcp -= 0 * OPSIZ;
-+              dstp -= 1 * OPSIZ;
-+              goto do7;
-+      case 1:
-+              a1 = ((op_t *) srcp)[0];
-+              srcp -= -1 * OPSIZ;
-+              dstp -= 0 * OPSIZ;
-+              len -= 1;
-+              if (OP_T_THRES <= 3 * OPSIZ && len == 0)
-+                      goto do0;
-+              goto do8;                 /* No-op.  */
-+      }
-+
-+      do {
-+do8:
-+              a0 = ((op_t *) srcp)[0];
-+              ((op_t *) dstp)[0] = a1;
-+do7:
-+              a1 = ((op_t *) srcp)[1];
-+              ((op_t *) dstp)[1] = a0;
-+do6:
-+              a0 = ((op_t *) srcp)[2];
-+              ((op_t *) dstp)[2] = a1;
-+do5:
-+              a1 = ((op_t *) srcp)[3];
-+              ((op_t *) dstp)[3] = a0;
-+do4:
-+              a0 = ((op_t *) srcp)[4];
-+              ((op_t *) dstp)[4] = a1;
-+do3:
-+              a1 = ((op_t *) srcp)[5];
-+              ((op_t *) dstp)[5] = a0;
-+do2:
-+              a0 = ((op_t *) srcp)[6];
-+              ((op_t *) dstp)[6] = a1;
-+do1:
-+              a1 = ((op_t *) srcp)[7];
-+              ((op_t *) dstp)[7] = a0;
-+
-+              srcp += 8 * OPSIZ;
-+              dstp += 8 * OPSIZ;
-+              len -= 8;
-+      } while (len != 0);
-+
-+      /* This is the right position for do0.  Please don't move
-+       * it into the loop.
-+       */
-+do0:
-+      ((op_t *) dstp)[0] = a1;
-+}
-+
-+static void _wordcopy_fwd_dest_aligned(long dstp, long srcp, size_t len)
-+{
-+      op_t a0, a1, a2, a3;
-+      int sh_1, sh_2;
-+
-+      /* Calculate how to shift a word read at the memory operation
-+       * aligned srcp to make it aligned for copy.
-+       */
-+
-+      sh_1 = 8 * (srcp % OPSIZ);
-+      sh_2 = 8 * OPSIZ - sh_1;
-+
-+      /* Make SRCP aligned by rounding it down to the beginning of the `op_t'
-+       * it points in the middle of.
-+       */
-+      srcp &= -OPSIZ;
-+
-+      switch (len % 4) {
-+      case 2:
-+              a1 = ((op_t *) srcp)[0];
-+              a2 = ((op_t *) srcp)[1];
-+              srcp -= 1 * OPSIZ;
-+              dstp -= 3 * OPSIZ;
-+              len += 2;
-+              goto do1;
-+      case 3:
-+              a0 = ((op_t *) srcp)[0];
-+              a1 = ((op_t *) srcp)[1];
-+              srcp -= 0 * OPSIZ;
-+              dstp -= 2 * OPSIZ;
-+              len += 1;
-+              goto do2;
-+      case 0:
-+              if (OP_T_THRES <= 3 * OPSIZ && len == 0)
-+                      return;
-+              a3 = ((op_t *) srcp)[0];
-+              a0 = ((op_t *) srcp)[1];
-+              srcp -= -1 * OPSIZ;
-+              dstp -= 1 * OPSIZ;
-+              len += 0;
-+              goto do3;
-+      case 1:
-+              a2 = ((op_t *) srcp)[0];
-+              a3 = ((op_t *) srcp)[1];
-+              srcp -= -2 * OPSIZ;
-+              dstp -= 0 * OPSIZ;
-+              len -= 1;
-+              if (OP_T_THRES <= 3 * OPSIZ && len == 0)
-+                      goto do0;
-+              goto do4;                 /* No-op.  */
-+      }
-+
-+      do {
-+do4:
-+              a0 = ((op_t *) srcp)[0];
-+              ((op_t *) dstp)[0] = MERGE(a2, sh_1, a3, sh_2);
-+do3:
-+              a1 = ((op_t *) srcp)[1];
-+              ((op_t *) dstp)[1] = MERGE(a3, sh_1, a0, sh_2);
-+do2:
-+              a2 = ((op_t *) srcp)[2];
-+              ((op_t *) dstp)[2] = MERGE(a0, sh_1, a1, sh_2);
-+do1:
-+              a3 = ((op_t *) srcp)[3];
-+              ((op_t *) dstp)[3] = MERGE(a1, sh_1, a2, sh_2);
-+
-+              srcp += 4 * OPSIZ;
-+              dstp += 4 * OPSIZ;
-+              len -= 4;
-+      } while (len != 0);
-+
-+      /* This is the right position for do0.  Please don't move
-+       * it into the loop.
-+       */
-+do0:
-+      ((op_t *) dstp)[0] = MERGE(a2, sh_1, a3, sh_2);
-+}
-+
-+#define BYTE_COPY_FWD(dst_bp, src_bp, nbytes)         \
-+do {                                                  \
-+      size_t __nbytes = (nbytes);                     \
-+      while (__nbytes > 0) {                                          \
-+              byte __x = ((byte *) src_bp)[0];                \
-+              src_bp += 1;                            \
-+              __nbytes -= 1;                          \
-+              ((byte *) dst_bp)[0] = __x;             \
-+              dst_bp += 1;                            \
-+      }                                               \
-+} while (0)
-+
-+#define WORD_COPY_FWD(dst_bp, src_bp, nbytes_left, nbytes)                    \
-+do {                                                                          \
-+      if (src_bp % OPSIZ == 0)                                                \
-+              _wordcopy_fwd_aligned(dst_bp, src_bp, (nbytes) / OPSIZ);        \
-+      else                                                                    \
-+              _wordcopy_fwd_dest_aligned(dst_bp, src_bp, (nbytes) / OPSIZ);   \
-+      src_bp += (nbytes) & -OPSIZ;                                            \
-+      dst_bp += (nbytes) & -OPSIZ;                                            \
-+      (nbytes_left) = (nbytes) % OPSIZ;                                       \
-+} while (0)
-+
-+extern void *__memcpy_aligned(void *dest, const void *src, size_t len);
-+void *__memcpy(void *dest, const void *src, size_t len)
-+{
-+      unsigned long dstp = (long) dest;
-+      unsigned long srcp = (long) src;
-+
-+      /* If there not too few bytes to copy, use word copy.  */
-+      if (len >= OP_T_THRES) {
-+              if ((len >= FAST_COPY_THRES) && ((dstp & OPSIZ_MASK) == 0) &&
-+                      ((srcp & OPSIZ_MASK) == 0)) {
-+                      __memcpy_aligned(dest, src, len);
-+                      return dest;
-+              }
-+              /* Copy just a few bytes to make DSTP aligned.  */
-+              len -= (-dstp) % OPSIZ;
-+              BYTE_COPY_FWD(dstp, srcp, (-dstp) % OPSIZ);
-+
-+              /* Copy from SRCP to DSTP taking advantage of the known alignment of
-+               * DSTP.  Number of bytes remaining is put in the third argument,
-+               * i.e. in LEN.  This number may vary from machine to machine.
-+               */
-+              WORD_COPY_FWD(dstp, srcp, len, len);
-+      /* Fall out and copy the tail.  */
-+      }
-+
-+      /* There are just a few bytes to copy.  Use byte memory operations.  */
-+      BYTE_COPY_FWD(dstp, srcp, len);
-+
-+      return dest;
-+}
-+
-+void *memcpy(void *dest, const void *src, size_t len) __weak __alias(__memcpy);
diff --git a/target/linux/starfive/patches-6.6/0093-riscv-purgatory-Change-memcpy-to-the-aligned-version.patch b/target/linux/starfive/patches-6.6/0093-riscv-purgatory-Change-memcpy-to-the-aligned-version.patch
deleted file mode 100644 (file)
index 0b7418f..0000000
+++ /dev/null
@@ -1,37 +0,0 @@
-From 41c9e97bb70321f7848bd489e45246a9dc985974 Mon Sep 17 00:00:00 2001
-From: Hal Feng <hal.feng@starfivetech.com>
-Date: Sun, 4 Feb 2024 15:27:09 +0800
-Subject: [PATCH 093/116] riscv/purgatory: Change memcpy to the aligned version
-
-Change memcpy to the aligned version, for purgatory.
-
-Signed-off-by: Hal Feng <hal.feng@starfivetech.com>
----
- arch/riscv/purgatory/Makefile | 7 +++++--
- 1 file changed, 5 insertions(+), 2 deletions(-)
-
---- a/arch/riscv/purgatory/Makefile
-+++ b/arch/riscv/purgatory/Makefile
-@@ -1,7 +1,7 @@
- # SPDX-License-Identifier: GPL-2.0
- OBJECT_FILES_NON_STANDARD := y
--purgatory-y := purgatory.o sha256.o entry.o string.o ctype.o memcpy.o memset.o
-+purgatory-y := purgatory.o sha256.o entry.o string.o ctype.o memcpy_aligned.o memcpy.o memset.o
- purgatory-y += strcmp.o strlen.o strncmp.o
- targets += $(purgatory-y)
-@@ -13,9 +13,12 @@ $(obj)/string.o: $(srctree)/lib/string.c
- $(obj)/ctype.o: $(srctree)/lib/ctype.c FORCE
-       $(call if_changed_rule,cc_o_c)
--$(obj)/memcpy.o: $(srctree)/arch/riscv/lib/memcpy.S FORCE
-+$(obj)/memcpy_aligned.o: $(srctree)/arch/riscv/lib/memcpy_aligned.S FORCE
-       $(call if_changed_rule,as_o_S)
-+$(obj)/memcpy.o: $(srctree)/arch/riscv/lib/string.c FORCE
-+      $(call if_changed_rule,cc_o_c)
-+
- $(obj)/memset.o: $(srctree)/arch/riscv/lib/memset.S FORCE
-       $(call if_changed_rule,as_o_S)
diff --git a/target/linux/starfive/patches-6.6/0094-Add-16-ISP-controls-remove-the-frame-SYNC-event-to-v.patch b/target/linux/starfive/patches-6.6/0094-Add-16-ISP-controls-remove-the-frame-SYNC-event-to-v.patch
deleted file mode 100644 (file)
index 7ce12c6..0000000
+++ /dev/null
@@ -1,856 +0,0 @@
-From f36d458104101050478e290919ef4f05fbde0b3e Mon Sep 17 00:00:00 2001
-From: "zejian.su" <zejian.su@starfivetech.com>
-Date: Mon, 3 Jul 2023 16:52:13 +0800
-Subject: [PATCH 094/116] Add 16 ISP controls, remove the frame SYNC event to
- video7 (SC) These controls are: WB, CAR, CCM, CFA, CTC, DBC, DNYUV, GMARGB,
- LCCF, OBC, OECF, R2Y, SAT, SHRP, YCRV, SC
-
----
- .../platform/starfive/v4l2_driver/stf_isp.c   | 628 ++++++++++++++++++
- .../platform/starfive/v4l2_driver/stf_video.c |  22 +
- .../platform/starfive/v4l2_driver/stf_vin.c   |  16 +-
- include/uapi/linux/jh7110-isp.h               |  48 +-
- 4 files changed, 706 insertions(+), 8 deletions(-)
-
---- a/drivers/media/platform/starfive/v4l2_driver/stf_isp.c
-+++ b/drivers/media/platform/starfive/v4l2_driver/stf_isp.c
-@@ -195,6 +195,41 @@ static const char * const test_pattern_m
-       "Color squares w/ rolling bar",
- };
-+enum isp_modules_index {
-+      imi_obc = 0,
-+      imi_oecf,
-+      imi_lccf,
-+      imi_awb,
-+      imi_dbc,
-+      imi_ctc,
-+      imi_cfa,
-+      imi_car,
-+      imi_ccm,
-+      imi_gmargb,
-+      imi_r2y,
-+      imi_ycrv,
-+      imi_shrp,
-+      imi_dnyuv,
-+      imi_sat,
-+      imi_sc
-+};
-+
-+#define MODULE_ENABLE_REGISTER0                               0x10
-+#define MODULE_ENABLE_REGISTER1                               0xa08
-+
-+struct module_register_info {
-+      __u32 en_reg;
-+      __u32 en_nbit;
-+      __u32 cfg_reg;
-+};
-+
-+static const struct module_register_info mod_reg_info[] = {
-+      {MODULE_ENABLE_REGISTER0, 2, 0x034}, {MODULE_ENABLE_REGISTER0, 4, 0x100}, {MODULE_ENABLE_REGISTER0, 6, 0x050}, {MODULE_ENABLE_REGISTER0, 7, 0x280},
-+      {MODULE_ENABLE_REGISTER1, 22, 0xa14}, {MODULE_ENABLE_REGISTER1, 21, 0xa10}, {MODULE_ENABLE_REGISTER1, 1, 0xa1c}, {MODULE_ENABLE_REGISTER1, 2, 0x000},
-+      {MODULE_ENABLE_REGISTER1, 3, 0xc40}, {MODULE_ENABLE_REGISTER1, 4, 0xe00}, {MODULE_ENABLE_REGISTER1, 5, 0xe40}, {MODULE_ENABLE_REGISTER1, 19, 0xf00},
-+      {MODULE_ENABLE_REGISTER1, 7, 0xe80}, {MODULE_ENABLE_REGISTER1, 17, 0xc00}, {MODULE_ENABLE_REGISTER1, 8, 0xa30}, {MODULE_ENABLE_REGISTER0, 17, 0x09c}
-+};
-+
- #define ISP_TEST_ENABLE                       BIT(7)
- #define ISP_TEST_ROLLING              BIT(6)  /* rolling horizontal bar */
- #define ISP_TEST_TRANSPARENT          BIT(5)
-@@ -260,6 +295,401 @@ static int isp_g_volatile_ctrl(struct v4
-       return 0;
- }
-+#define CREATE_REG_VALUE_FUNCTION(type)       \
-+      static u32 create_reg_value_##type(const type * value, s32 size, u32 mask, s32 nbits) { \
-+      s32 npos = 0;   \
-+      u32 res = 0;    \
-+      s32 sz = size;  \
-+      s32 i = 0;      \
-+      if(size * nbits > 32) sz = 32 / nbits;  \
-+      for(i = 0; i < sz; i++, npos += nbits, value++) res |= (u32)(value[0] & mask) << npos;  \
-+      return res;     \
-+}
-+
-+CREATE_REG_VALUE_FUNCTION(u8);
-+CREATE_REG_VALUE_FUNCTION(u16);
-+#define CREATE_REG_VALUE(type, value, size, mask, nbits) create_reg_value_##type(value, size, mask, nbits)
-+
-+#define FILL_ISP_REGS_FUNC(type)      \
-+static void fill_isp_regs_##type(void __iomem *ispbase, u32 offset, const type * value, s32 size, u32 mask, u32 nbits) {      \
-+      s32 i;  \
-+      for(i = 0; i < size; i++, value++)      \
-+              reg_write(ispbase, offset + i * 4, (u32)(value[0] & mask) << nbits);    \
-+}
-+FILL_ISP_REGS_FUNC(u32);
-+FILL_ISP_REGS_FUNC(u8);
-+FILL_ISP_REGS_FUNC(u16);
-+
-+#define FILL_ISP_REGS(type, ispbase, offset, value, size, mask, nbits)        \
-+      fill_isp_regs_##type(ispbase, offset, value, size, mask, nbits)
-+
-+static int isp_set_ctrl_wb(struct stf_isp_dev *isp_dev, const void * value)
-+{
-+      const struct module_register_info * reg_info = &mod_reg_info[imi_awb];
-+      const struct jh7110_isp_wb_setting * setting = (const struct jh7110_isp_wb_setting *)value;
-+      const struct jh7110_isp_wb_gain * gains = &setting->gains;
-+      u32 r_g = (((u32)gains->gain_r << 16) | gains->gain_r) & 0x03ff03ff;
-+      u32 g_g = (((u32)gains->gain_g << 16) | gains->gain_g) & 0x03ff03ff;
-+      u32 b_g = (((u32)gains->gain_b << 16) | gains->gain_b) & 0x03ff03ff;
-+      u32 reg_addr = reg_info->cfg_reg + 16 * sizeof(u32);
-+      struct stf_vin_dev *vin = isp_dev->stfcamss->vin;
-+      void __iomem *ispbase = vin->isp_base;
-+
-+      reg_write(ispbase, reg_addr, r_g);
-+      reg_write(ispbase, reg_addr + 1 * 4, r_g);
-+      reg_write(ispbase, reg_addr + 2 * 4, g_g);
-+      reg_write(ispbase, reg_addr + 3 * 4, g_g);
-+      reg_write(ispbase, reg_addr + 4 * 4, g_g);
-+      reg_write(ispbase, reg_addr + 5 * 4, g_g);
-+      reg_write(ispbase, reg_addr + 6 * 4, b_g);
-+      reg_write(ispbase, reg_addr + 7 * 4, b_g);
-+      reg_set_bit(ispbase, reg_info->en_reg, 1 << reg_info->en_nbit, setting->enabled ? 1 << reg_info->en_nbit : 0);
-+
-+      return 0;
-+}
-+
-+static int isp_set_ctrl_car(struct stf_isp_dev *isp_dev, const void * value)
-+{
-+      const struct module_register_info * reg_info = &mod_reg_info[imi_car];
-+      const struct jh7110_isp_car_setting * setting = (const struct jh7110_isp_car_setting *)value;
-+      struct stf_vin_dev *vin = isp_dev->stfcamss->vin;
-+      void __iomem *ispbase = vin->isp_base;
-+
-+      reg_set_bit(ispbase, reg_info->en_reg, 1 << reg_info->en_nbit, setting->enabled ? 1 << reg_info->en_nbit : 0);
-+
-+      return 0;
-+}
-+
-+static int isp_set_ctrl_ccm(struct stf_isp_dev *isp_dev, const void * value)
-+{
-+      const struct module_register_info * reg_info = &mod_reg_info[imi_ccm];
-+      const struct jh7110_isp_ccm_setting * setting = (const struct jh7110_isp_ccm_setting *)value;
-+      const struct jh7110_isp_ccm_smlow * ccm = (const struct jh7110_isp_ccm_smlow *)(&(setting->ccm_smlow));
-+      u32 reg_addr = reg_info->cfg_reg + 12 * sizeof(u32);
-+      struct stf_vin_dev *vin = isp_dev->stfcamss->vin;
-+      void __iomem *ispbase = vin->isp_base;
-+
-+      reg_write(ispbase, reg_info->cfg_reg, 6 << 16);
-+      FILL_ISP_REGS(u32, ispbase, reg_addr, (u32 *)ccm, 12, 0x7ff, 0);
-+
-+      reg_set_bit(ispbase, reg_info->en_reg, 1 << reg_info->en_nbit, setting->enabled ? 1 << reg_info->en_nbit : 0);
-+
-+      return 0;
-+}
-+
-+static int isp_set_ctrl_cfa(struct stf_isp_dev *isp_dev, const void * value)
-+{
-+      const struct module_register_info * reg_info = &mod_reg_info[imi_cfa];
-+      const struct jh7110_isp_cfa_setting * setting = (const struct jh7110_isp_cfa_setting *)value;
-+      const struct jh7110_isp_cfa_params * cfg = (const struct jh7110_isp_cfa_params *)(&(setting->settings));
-+      u32 reg_addr = reg_info->cfg_reg;
-+      struct stf_vin_dev *vin = isp_dev->stfcamss->vin;
-+      void __iomem *ispbase = vin->isp_base;
-+
-+      reg_write(ispbase, reg_addr, ((u32)(cfg->cross_cov & 0x3) << 4) | (cfg->hv_width & 0xf));
-+      reg_set_bit(ispbase, reg_info->en_reg, 1 << reg_info->en_nbit, setting->enabled ? 1 << reg_info->en_nbit : 0);
-+      
-+      return 0;
-+}
-+
-+static int isp_set_ctrl_ctc(struct stf_isp_dev *isp_dev, const void * value)
-+{
-+      const struct module_register_info * reg_info = &mod_reg_info[imi_ctc];
-+      const struct jh7110_isp_ctc_setting * setting = (const struct jh7110_isp_ctc_setting *)value;
-+      const struct jh7110_isp_ctc_params * cfg = (const struct jh7110_isp_ctc_params *)(&(setting->settings));
-+      u32 reg_addr = reg_info->cfg_reg;
-+      struct stf_vin_dev *vin = isp_dev->stfcamss->vin;
-+      void __iomem *ispbase = vin->isp_base;
-+      u32 reg_value = (u32)(((cfg->saf_mode & 1) << 1) | (cfg->daf_mode & 1)) << 30;
-+
-+      reg_value |= ((u32)(cfg->max_gt & 0x3ff) << 16) | (cfg->min_gt & 0x3ff);
-+      reg_write(ispbase, reg_addr, reg_value);
-+      reg_set_bit(ispbase, reg_info->en_reg, 1 << reg_info->en_nbit, setting->enabled ? 1 << reg_info->en_nbit : 0);
-+      
-+      return 0;
-+}
-+
-+static int isp_set_ctrl_dbc(struct stf_isp_dev *isp_dev, const void * value)
-+{
-+      const struct module_register_info * reg_info = &mod_reg_info[imi_dbc];
-+      const struct jh7110_isp_dbc_setting * setting = (const struct jh7110_isp_dbc_setting *)value;
-+      const struct jh7110_isp_dbc_params * cfg = (const struct jh7110_isp_dbc_params *)(&(setting->settings));
-+      u32 reg_addr = reg_info->cfg_reg;
-+      struct stf_vin_dev *vin = isp_dev->stfcamss->vin;
-+      void __iomem *ispbase = vin->isp_base;
-+
-+      reg_write(ispbase, reg_addr, ((u32)(cfg->bad_gt & 0x3ff) << 16) | (cfg->bad_xt & 0x3ff));
-+      reg_set_bit(ispbase, reg_info->en_reg, 1 << reg_info->en_nbit, setting->enabled ? 1 << reg_info->en_nbit : 0);
-+      
-+      return 0;
-+}
-+
-+static int isp_set_ctrl_dnyuv(struct stf_isp_dev *isp_dev, const void * value)
-+{
-+      const struct module_register_info * reg_info = &mod_reg_info[imi_dnyuv];
-+      const struct jh7110_isp_dnyuv_setting * setting = (const struct jh7110_isp_dnyuv_setting *)value;
-+      const struct jh7110_isp_dnyuv_params * cfg = (const struct jh7110_isp_dnyuv_params *)(&(setting->settings));
-+      u32 reg_addr = reg_info->cfg_reg;
-+      struct stf_vin_dev *vin = isp_dev->stfcamss->vin;
-+      void __iomem *ispbase = vin->isp_base;
-+
-+      reg_write(ispbase, reg_addr, CREATE_REG_VALUE(u8, cfg->y_sweight, 6, 0x7, 4));
-+      reg_write(ispbase, reg_addr + 4, CREATE_REG_VALUE(u8, &cfg->y_sweight[6], 4, 0x7, 4));
-+      reg_write(ispbase, reg_addr + 8, CREATE_REG_VALUE(u8, cfg->uv_sweight, 6, 0x7, 4));
-+      reg_write(ispbase, reg_addr + 12, CREATE_REG_VALUE(u8, &cfg->uv_sweight[6], 4, 0x7, 4));
-+      reg_write(ispbase, reg_addr + 16, CREATE_REG_VALUE(u16, &cfg->y_curve[0], 2, 0x3ff, 16));
-+      reg_write(ispbase, reg_addr + 20, CREATE_REG_VALUE(u16, &cfg->y_curve[2], 2, 0x3ff, 16));
-+      reg_write(ispbase, reg_addr + 24, CREATE_REG_VALUE(u16, &cfg->y_curve[4], 2, 0x3ff, 16));
-+      reg_write(ispbase, reg_addr + 28, CREATE_REG_VALUE(u16, &cfg->uv_curve[0], 2, 0x3ff, 16));
-+      reg_write(ispbase, reg_addr + 32, CREATE_REG_VALUE(u16, &cfg->uv_curve[2], 2, 0x3ff, 16));
-+      reg_write(ispbase, reg_addr + 36, CREATE_REG_VALUE(u16, &cfg->uv_curve[4], 2, 0x3ff, 16));
-+
-+      reg_set_bit(ispbase, reg_info->en_reg, 1 << reg_info->en_nbit, setting->enabled ? 1 << reg_info->en_nbit : 0);
-+      
-+      return 0;
-+}
-+
-+static int isp_set_ctrl_gmargb(struct stf_isp_dev *isp_dev, const void * value)
-+{
-+      const struct module_register_info * reg_info = &mod_reg_info[imi_gmargb];
-+      const struct jh7110_isp_gmargb_setting * setting = (const struct jh7110_isp_gmargb_setting *)value;
-+      const struct jh7110_isp_gmargb_point * curve = setting->curve;
-+      u32 reg_addr = reg_info->cfg_reg;
-+      struct stf_vin_dev *vin = isp_dev->stfcamss->vin;
-+      void __iomem *ispbase = vin->isp_base;
-+      s32 i;
-+      
-+      for(i = 0; i < 15; i++, curve++, reg_addr += 4)
-+              reg_write(ispbase, reg_addr, ((u32)curve->sg_val << 16) | (curve->g_val & 0x3ff));
-+
-+      reg_set_bit(ispbase, reg_info->en_reg, 1 << reg_info->en_nbit, setting->enabled ? 1 << reg_info->en_nbit : 0);
-+
-+      return 0;
-+}
-+
-+static int isp_set_ctrl_lccf(struct stf_isp_dev *isp_dev, const void * value)
-+{
-+      const struct module_register_info * reg_info = &mod_reg_info[imi_lccf];
-+      const struct jh7110_isp_lccf_setting * setting = (const struct jh7110_isp_lccf_setting *)value;
-+      const s16 * params = (s16 *)(&setting->r_param);
-+      u32 reg_addr = reg_info->cfg_reg;
-+      struct stf_vin_dev *vin = isp_dev->stfcamss->vin;
-+      void __iomem *ispbase = vin->isp_base;
-+      s32 i;
-+      
-+      reg_write(ispbase, reg_addr, ((u32)(setting->circle.center_y & 0x7fff) << 16) | (setting->circle.center_x & 0x7fff));
-+      reg_write(ispbase, reg_addr + 8, setting->circle.radius & 0xf);
-+      reg_addr += 0x90;
-+      for(i = 0; i < 4; i++, reg_addr += 4, params += 2)
-+              reg_write(ispbase, reg_addr, CREATE_REG_VALUE(u16, params, 2, 0x1fff, 16));
-+
-+      reg_set_bit(ispbase, reg_info->en_reg, 1 << reg_info->en_nbit, setting->enabled ? 1 << reg_info->en_nbit : 0);
-+      
-+      return 0;
-+}
-+
-+static int isp_set_ctrl_obc(struct stf_isp_dev *isp_dev, const void * value)
-+{
-+      const struct module_register_info * reg_info = &mod_reg_info[imi_obc];
-+      const struct jh7110_isp_blacklevel_setting * setting = (const struct jh7110_isp_blacklevel_setting *)value;
-+      const u8 * params = (u8 *)setting->gain;
-+      u32 reg_addr = reg_info->cfg_reg;
-+      struct stf_vin_dev *vin = isp_dev->stfcamss->vin;
-+      void __iomem *ispbase = vin->isp_base;
-+      s32 i;
-+      
-+      reg_write(ispbase, reg_addr, ((u32)(setting->win_size.height & 0xf) << 4) | (setting->win_size.width & 0xf));
-+
-+      reg_addr += 0x2ac;      //0x2e0
-+      for(i = 0; i < 8; i++, reg_addr += 4, params += 4)
-+              reg_write(ispbase, reg_addr, CREATE_REG_VALUE(u8, params, 4, 0xff, 8));
-+
-+      reg_set_bit(ispbase, reg_info->en_reg, 1 << reg_info->en_nbit, setting->enabled ? 1 << reg_info->en_nbit : 0);
-+      
-+      return 0;
-+}
-+
-+static int isp_set_ctrl_oecf(struct stf_isp_dev *isp_dev, const void * value)
-+{
-+      const struct module_register_info * reg_info = &mod_reg_info[imi_oecf];
-+      const struct jh7110_isp_oecf_setting * setting = (const struct jh7110_isp_oecf_setting *)value;
-+      const struct jh7110_isp_oecf_point * pts = (struct jh7110_isp_oecf_point *)(setting->r_curve);
-+      u32 reg_x_addr = reg_info->cfg_reg;
-+      u32 reg_y_addr = reg_info->cfg_reg + 0x080;
-+      u32 reg_s_addr = reg_info->cfg_reg + 0x100;
-+      struct stf_vin_dev *vin = isp_dev->stfcamss->vin;
-+      void __iomem *ispbase = vin->isp_base;
-+      u32 x, y, slope;
-+      s32 i;
-+      
-+      for(i = 0; i < 32; i++, reg_x_addr += 4, reg_y_addr += 4, reg_s_addr += 4) {
-+              x = pts->x & 0x3ff;
-+              y = pts->y & 0x3ff;
-+              slope = pts->slope & 0x3ff;
-+              pts++;
-+              x |= ((pts->x & 0x3ff) << 16);
-+              y |= ((pts->y & 0x3ff) << 16);
-+              slope |= ((pts->slope & 0x3ff) << 16);
-+              pts++;
-+
-+              reg_write(ispbase, reg_x_addr, x);
-+              reg_write(ispbase, reg_y_addr, y);
-+              reg_write(ispbase, reg_s_addr, slope);
-+      }
-+
-+      reg_set_bit(ispbase, reg_info->en_reg, 1 << reg_info->en_nbit, setting->enabled ? 1 << reg_info->en_nbit : 0);
-+
-+      return 0;
-+}
-+
-+static int isp_set_ctrl_r2y(struct stf_isp_dev *isp_dev, const void * value)
-+{
-+      const struct module_register_info * reg_info = &mod_reg_info[imi_r2y];
-+      const struct jh7110_isp_r2y_setting * setting = (const struct jh7110_isp_r2y_setting *)value;
-+      const s16 * params = setting->matrix.m;
-+      u32 reg_addr = reg_info->cfg_reg;
-+      struct stf_vin_dev *vin = isp_dev->stfcamss->vin;
-+      void __iomem *ispbase = vin->isp_base;
-+      s32 i;
-+      
-+      for(i = 0; i < 9; i++, reg_addr += 4)
-+              reg_write(ispbase, reg_addr, (u32)(params[i] & 0x1ff));
-+
-+      reg_set_bit(ispbase, reg_info->en_reg, 1 << reg_info->en_nbit, setting->enabled ? 1 << reg_info->en_nbit : 0);
-+      
-+      return 0;
-+}
-+
-+
-+static int isp_set_ctrl_sat(struct stf_isp_dev *isp_dev, const void * value)
-+{
-+      const struct module_register_info * reg_info = &mod_reg_info[imi_sat];
-+      const struct jh7110_isp_sat_setting * setting = (const struct jh7110_isp_sat_setting *)value;
-+      const u16 * params = (u16 *)(&setting->sat_info);
-+      u32 reg_addr = reg_info->cfg_reg;
-+      struct stf_vin_dev *vin = isp_dev->stfcamss->vin;
-+      void __iomem *ispbase = vin->isp_base;
-+      s32 i;
-+      
-+      for(i = 0; i < 3; i++, reg_addr += 4, params += 2)
-+              reg_write(ispbase, reg_addr, CREATE_REG_VALUE(u16, params, 2, 0xfff, 16));
-+      reg_write(ispbase, reg_addr, CREATE_REG_VALUE(u16, &setting->hue_info.cos, 2, 0x3ff, 16));
-+      reg_addr += 4;
-+      reg_write(ispbase, reg_addr, setting->sat_info.cmsf & 0xf);
-+
-+      params = (u16 *)(&setting->curve);
-+      reg_addr += 0x14;               // 0xa54
-+      for(i = 0; i < 2; i++, reg_addr += 4, params += 2)
-+              reg_write(ispbase, reg_addr, CREATE_REG_VALUE(u16, params, 2, 0x3fff, 16));
-+
-+      reg_set_bit(ispbase, reg_info->en_reg, 1 << reg_info->en_nbit, setting->enabled ? 1 << reg_info->en_nbit : 0);
-+      
-+      return 0;
-+}
-+
-+static int isp_set_ctrl_shrp(struct stf_isp_dev *isp_dev, const void * value)
-+{
-+      const struct module_register_info * reg_info = &mod_reg_info[imi_shrp];
-+      const struct jh7110_isp_sharp_setting * setting = (const struct jh7110_isp_sharp_setting *)value;
-+      u32 reg_addr = reg_info->cfg_reg;
-+      struct stf_vin_dev *vin = isp_dev->stfcamss->vin;
-+      void __iomem *ispbase = vin->isp_base;
-+      s32 i;
-+      
-+      for(i = 0; i < 4; i++, reg_addr += 4)
-+              reg_write(ispbase, reg_addr, ((u32)(setting->strength.diff[i] & 0x3ff) << 16) | ((u32)(setting->weight.weight[i] & 0xf) << 8));
-+      FILL_ISP_REGS(u8, ispbase, reg_addr, (u8 *)(&setting->weight.weight[4]), 15 - 4, 0xf, 8);
-+      reg_addr += (15 - 4) * 4;
-+
-+      for(i = 0; i < 3; i++, reg_addr += 4)
-+              reg_write(ispbase, reg_addr, ((u32)(setting->strength.f[i] & 0x7f) << 24) | (setting->strength.s[i] & 0x1fffff));
-+
-+      reg_addr += 3 * 4;
-+      reg_write(ispbase, reg_addr, ((u32)(setting->pdirf & 0xf) << 28) | ((u32)(setting->ndirf & 0xf) << 24) | (setting->weight.recip_wei_sum & 0x3fffff));
-+
-+      reg_set_bit(ispbase, reg_info->en_reg, 1 << reg_info->en_nbit, setting->enabled ? 1 << reg_info->en_nbit : 0);
-+      
-+      return 0;
-+}
-+
-+static int isp_set_ctrl_ycrv(struct stf_isp_dev *isp_dev, const void * value)
-+{
-+      const struct module_register_info * reg_info = &mod_reg_info[imi_ycrv];
-+      const struct jh7110_isp_ycrv_setting * setting = (const struct jh7110_isp_ycrv_setting *)value;
-+      u32 reg_addr = reg_info->cfg_reg;
-+      struct stf_vin_dev *vin = isp_dev->stfcamss->vin;
-+      void __iomem *ispbase = vin->isp_base;
-+      
-+      FILL_ISP_REGS(u16, ispbase, reg_addr, (u16 *)(setting->curve.y), 64, 0x3ff, 0);
-+
-+      reg_set_bit(ispbase, reg_info->en_reg, 1 << reg_info->en_nbit, setting->enabled ? 1 << reg_info->en_nbit : 0);
-+      
-+      return 0;
-+}
-+
-+static int isp_set_ctrl_sc(struct stf_isp_dev *isp_dev, const void * value)
-+{
-+      const struct module_register_info * reg_info = &mod_reg_info[imi_sc];
-+      const struct jh7110_isp_sc_setting * setting = (const struct jh7110_isp_sc_setting *)value;
-+      const u8 * params = setting->awb_config.awb_cw;
-+      u32 reg_addr = 0x00;
-+      struct stf_vin_dev *vin = isp_dev->stfcamss->vin;
-+      void __iomem *ispbase = vin->isp_base;
-+      u32 weight_cfg[6] = {0};
-+      u32 * weight = weight_cfg;
-+      u32 * w_diff = weight_cfg + 2;
-+      s32 i;
-+
-+      // AF register
-+      reg_write(ispbase, 0xc0, 
-+              ((u32)(setting->af_config.es_hor_thr & 0x1ff) << 16) |
-+              ((u32)(setting->af_config.es_ver_thr & 0xff) << 8) |
-+              ((setting->af_config.ver_en & 0x1) << 3) |
-+              ((setting->af_config.hor_en & 0x1) << 2) |
-+              ((setting->af_config.es_sum_mode & 0x1) << 1) |
-+              (setting->af_config.es_hor_mode & 0x1));
-+
-+      // AWB weight sum register
-+      reg_write(ispbase, 0x5d0, CREATE_REG_VALUE(u8, &setting->awb_config.ws_config.awb_ws_rl, 4, 0xff, 8));
-+      reg_write(ispbase, 0x5d4, CREATE_REG_VALUE(u8, &setting->awb_config.ws_config.awb_ws_gbl, 4, 0xff, 8));
-+
-+      // AWB weight value point
-+      reg_addr = 0x4d0;
-+      for(i = 0; i < 13; i++) {
-+              reg_write(ispbase, reg_addr, CREATE_REG_VALUE(u8, params, 8, 0xf, 4));
-+              reg_addr += 4;
-+              params += 8;
-+              reg_write(ispbase, reg_addr, CREATE_REG_VALUE(u8, params, 5, 0xf, 4));
-+              reg_addr += 4;
-+              params += 5;
-+      }
-+
-+      // AWB intensity weight curve register
-+      reg_addr = 0x538;
-+      for(i = 0; i < 4; i++) {
-+              weight[0] |= (setting->awb_config.pts[i].weight & 0xf) << (i * 4);
-+              w_diff[0] |= ((((s16)(setting->awb_config.pts[i + 1].weight & 0xf) - (s16)(setting->awb_config.pts[i].weight & 0xf)) * 2) & 0xff) << (i * 8);
-+      }
-+      for(w_diff++; i < 8; i++) {
-+              weight[0] |= (setting->awb_config.pts[i].weight & 0xf) << (i * 4);
-+              w_diff[0] |= ((((s16)(setting->awb_config.pts[i + 1].weight & 0xf) - (s16)(setting->awb_config.pts[i].weight & 0xf)) * 2) & 0xff) << (i * 8);
-+      }
-+      for(weight++, w_diff++; i < 12; i++) {
-+              weight[0] |= (setting->awb_config.pts[i].weight & 0xf) << (i * 4);
-+              w_diff[0] |= ((((s16)(setting->awb_config.pts[i + 1].weight & 0xf) - (s16)(setting->awb_config.pts[i].weight & 0xf)) * 2) & 0xff) << (i * 8);
-+      }
-+      for(w_diff++; i < 16; i++) {
-+              weight[0] |= (setting->awb_config.pts[i].weight & 0xf) << (i * 4);
-+              w_diff[0] |= ((((s16)(setting->awb_config.pts[i + 1].weight & 0xf) - (s16)(setting->awb_config.pts[i].weight & 0xf)) * 2) & 0xff) << (i * 8);
-+      }
-+
-+      FILL_ISP_REGS(u32, ispbase, reg_addr, weight_cfg, 6, 0xffffffff, 0);
-+
-+      reg_set_bit(ispbase, reg_info->en_reg, 1 << reg_info->en_nbit, setting->enabled ? 1 << reg_info->en_nbit : 0);
-+      
-+      return 0;
-+}
-+
- static int isp_s_ctrl(struct v4l2_ctrl *ctrl)
- {
-       struct v4l2_subdev *sd = ctrl_to_sd(ctrl);
-@@ -310,10 +740,52 @@ static int isp_s_ctrl(struct v4l2_ctrl *
-               ret = isp_set_ctrl_vflip(isp_dev, ctrl->val);
-               break;
-       case V4L2_CID_USER_JH7110_ISP_WB_SETTING:
-+              ret = isp_set_ctrl_wb(isp_dev, ctrl->p_new.p_u8);
-               break;
-       case V4L2_CID_USER_JH7110_ISP_CAR_SETTING:
-+              ret = isp_set_ctrl_car(isp_dev, ctrl->p_new.p_u8);
-               break;
-       case V4L2_CID_USER_JH7110_ISP_CCM_SETTING:
-+              ret = isp_set_ctrl_ccm(isp_dev, ctrl->p_new.p_u8);
-+              break;
-+      case V4L2_CID_USER_JH7110_ISP_CFA_SETTING:
-+              ret = isp_set_ctrl_cfa(isp_dev, ctrl->p_new.p_u8);
-+              break;
-+      case V4L2_CID_USER_JH7110_ISP_CTC_SETTING:
-+              ret = isp_set_ctrl_ctc(isp_dev, ctrl->p_new.p_u8);
-+              break;
-+      case V4L2_CID_USER_JH7110_ISP_DBC_SETTING:
-+              ret = isp_set_ctrl_dbc(isp_dev, ctrl->p_new.p_u8);
-+              break;
-+      case V4L2_CID_USER_JH7110_ISP_DNYUV_SETTING:
-+              ret = isp_set_ctrl_dnyuv(isp_dev, ctrl->p_new.p_u8);
-+              break;
-+      case V4L2_CID_USER_JH7110_ISP_GMARGB_SETTING:
-+              ret = isp_set_ctrl_gmargb(isp_dev, ctrl->p_new.p_u8);
-+              break;
-+      case V4L2_CID_USER_JH7110_ISP_LCCF_SETTING:
-+              ret = isp_set_ctrl_lccf(isp_dev, ctrl->p_new.p_u8);
-+              break;
-+      case V4L2_CID_USER_JH7110_ISP_OBC_SETTING:
-+              ret = isp_set_ctrl_obc(isp_dev, ctrl->p_new.p_u8);
-+              break;
-+      case V4L2_CID_USER_JH7110_ISP_OECF_SETTING:
-+              ret = isp_set_ctrl_oecf(isp_dev, ctrl->p_new.p_u8);
-+              break;
-+      case V4L2_CID_USER_JH7110_ISP_R2Y_SETTING:
-+              ret = isp_set_ctrl_r2y(isp_dev, ctrl->p_new.p_u8);
-+              break;
-+      case V4L2_CID_USER_JH7110_ISP_SAT_SETTING:
-+              ret = isp_set_ctrl_sat(isp_dev, ctrl->p_new.p_u8);
-+              break;
-+      case V4L2_CID_USER_JH7110_ISP_SHRP_SETTING:
-+              ret = isp_set_ctrl_shrp(isp_dev, ctrl->p_new.p_u8);
-+              break;
-+      case V4L2_CID_USER_JH7110_ISP_YCRV_SETTING:
-+              ret = isp_set_ctrl_ycrv(isp_dev, ctrl->p_new.p_u8);
-+              break;
-+      case V4L2_CID_USER_JH7110_ISP_STAT_SETTING:
-+              ret = isp_set_ctrl_sc(isp_dev, ctrl->p_new.p_u8);
-               break;
-       default:
-               ret = -EINVAL;
-@@ -365,6 +837,162 @@ struct v4l2_ctrl_config isp_ctrl[] = {
-               .dims[0]        = sizeof(struct jh7110_isp_ccm_setting),
-               .flags          = 0,
-       },
-+      [3] = {
-+              .ops            = &isp_ctrl_ops,
-+              .type           = V4L2_CTRL_TYPE_U8,
-+              .def            = 0,
-+              .min            = 0x00,
-+              .max            = 0xff,
-+              .step           = 1,
-+              .name           = "CFA Setting",
-+              .id             = V4L2_CID_USER_JH7110_ISP_CFA_SETTING,
-+              .dims[0]        = sizeof(struct jh7110_isp_cfa_setting),
-+              .flags          = 0,
-+      },
-+      [4] = {
-+              .ops            = &isp_ctrl_ops,
-+              .type           = V4L2_CTRL_TYPE_U8,
-+              .def            = 0,
-+              .min            = 0x00,
-+              .max            = 0xff,
-+              .step           = 1,
-+              .name           = "CTC Setting",
-+              .id             = V4L2_CID_USER_JH7110_ISP_CTC_SETTING,
-+              .dims[0]        = sizeof(struct jh7110_isp_ctc_setting),
-+              .flags          = 0,
-+      },
-+      [5] = {
-+              .ops            = &isp_ctrl_ops,
-+              .type           = V4L2_CTRL_TYPE_U8,
-+              .def            = 0,
-+              .min            = 0x00,
-+              .max            = 0xff,
-+              .step           = 1,
-+              .name           = "CTC Setting",
-+              .id             = V4L2_CID_USER_JH7110_ISP_DBC_SETTING,
-+              .dims[0]        = sizeof(struct jh7110_isp_dbc_setting),
-+              .flags          = 0,
-+      },
-+      [6] = {
-+              .ops            = &isp_ctrl_ops,
-+              .type           = V4L2_CTRL_TYPE_U8,
-+              .def            = 0,
-+              .min            = 0x00,
-+              .max            = 0xff,
-+              .step           = 1,
-+              .name           = "DNYUV Setting",
-+              .id             = V4L2_CID_USER_JH7110_ISP_DNYUV_SETTING,
-+              .dims[0]        = sizeof(struct jh7110_isp_dnyuv_setting),
-+              .flags          = 0,
-+      },
-+      [7] = {
-+              .ops            = &isp_ctrl_ops,
-+              .type           = V4L2_CTRL_TYPE_U8,
-+              .def            = 0,
-+              .min            = 0x00,
-+              .max            = 0xff,
-+              .step           = 1,
-+              .name           = "DNYUV Setting",
-+              .id             = V4L2_CID_USER_JH7110_ISP_GMARGB_SETTING,
-+              .dims[0]        = sizeof(struct jh7110_isp_gmargb_setting),
-+              .flags          = 0,
-+      },
-+      [8] = {
-+              .ops            = &isp_ctrl_ops,
-+              .type           = V4L2_CTRL_TYPE_U8,
-+              .def            = 0,
-+              .min            = 0x00,
-+              .max            = 0xff,
-+              .step           = 1,
-+              .name           = "LCCF Setting",
-+              .id             = V4L2_CID_USER_JH7110_ISP_LCCF_SETTING,
-+              .dims[0]        = sizeof(struct jh7110_isp_lccf_setting),
-+              .flags          = 0,
-+      },
-+      [9] = {
-+              .ops            = &isp_ctrl_ops,
-+              .type           = V4L2_CTRL_TYPE_U8,
-+              .def            = 0,
-+              .min            = 0x00,
-+              .max            = 0xff,
-+              .step           = 1,
-+              .name           = "OBC Setting",
-+              .id             = V4L2_CID_USER_JH7110_ISP_OBC_SETTING,
-+              .dims[0]        = sizeof(struct jh7110_isp_blacklevel_setting),
-+              .flags          = 0,
-+      },
-+      [10] = {
-+              .ops            = &isp_ctrl_ops,
-+              .type           = V4L2_CTRL_TYPE_U8,
-+              .def            = 0,
-+              .min            = 0x00,
-+              .max            = 0xff,
-+              .step           = 1,
-+              .name           = "OECF Setting",
-+              .id             = V4L2_CID_USER_JH7110_ISP_OECF_SETTING,
-+              .dims[0]        = sizeof(struct jh7110_isp_oecf_setting),
-+              .flags          = 0,
-+      },
-+      [11] = {
-+              .ops            = &isp_ctrl_ops,
-+              .type           = V4L2_CTRL_TYPE_U8,
-+              .def            = 0,
-+              .min            = 0x00,
-+              .max            = 0xff,
-+              .step           = 1,
-+              .name           = "R2Y Setting",
-+              .id             = V4L2_CID_USER_JH7110_ISP_R2Y_SETTING,
-+              .dims[0]        = sizeof(struct jh7110_isp_r2y_setting),
-+              .flags          = 0,
-+      },
-+      [12] = {
-+              .ops            = &isp_ctrl_ops,
-+              .type           = V4L2_CTRL_TYPE_U8,
-+              .def            = 0,
-+              .min            = 0x00,
-+              .max            = 0xff,
-+              .step           = 1,
-+              .name           = "SAT Setting",
-+              .id             = V4L2_CID_USER_JH7110_ISP_SAT_SETTING,
-+              .dims[0]        = sizeof(struct jh7110_isp_sat_setting),
-+              .flags          = 0,
-+      },
-+      [13] = {
-+              .ops            = &isp_ctrl_ops,
-+              .type           = V4L2_CTRL_TYPE_U8,
-+              .def            = 0,
-+              .min            = 0x00,
-+              .max            = 0xff,
-+              .step           = 1,
-+              .name           = "SAT Setting",
-+              .id             = V4L2_CID_USER_JH7110_ISP_SHRP_SETTING,
-+              .dims[0]        = sizeof(struct jh7110_isp_sharp_setting),
-+              .flags          = 0,
-+      },
-+      [14] = {
-+              .ops            = &isp_ctrl_ops,
-+              .type           = V4L2_CTRL_TYPE_U8,
-+              .def            = 0,
-+              .min            = 0x00,
-+              .max            = 0xff,
-+              .step           = 1,
-+              .name           = "YCRV Setting",
-+              .id             = V4L2_CID_USER_JH7110_ISP_YCRV_SETTING,
-+              .dims[0]        = sizeof(struct jh7110_isp_ycrv_setting),
-+              .flags          = 0,
-+      },
-+      [15] = {
-+              .ops            = &isp_ctrl_ops,
-+              .type           = V4L2_CTRL_TYPE_U8,
-+              .def            = 0,
-+              .min            = 0x00,
-+              .max            = 0xff,
-+              .step           = 1,
-+              .name           = "SC Setting",
-+              .id             = V4L2_CID_USER_JH7110_ISP_STAT_SETTING,
-+              .dims[0]        = sizeof(struct jh7110_isp_sc_setting),
-+              .flags          = 0,
-+      },
- };
- static int isp_init_controls(struct stf_isp_dev *isp_dev)
---- a/drivers/media/platform/starfive/v4l2_driver/stf_video.c
-+++ b/drivers/media/platform/starfive/v4l2_driver/stf_video.c
-@@ -1281,6 +1281,22 @@ int video_s_selection(struct file *file,
-       return ret;
- }
-+static int stf_video_subscribe_event(struct v4l2_fh *fh,
-+                                 const struct v4l2_event_subscription *sub)
-+{
-+      switch (sub->type) {
-+      case V4L2_EVENT_FRAME_SYNC:
-+              return v4l2_event_subscribe(fh, sub, 2, NULL);
-+              //int ret = v4l2_event_subscribe(fh, sub, 2, NULL);
-+              //pr_info("subscribe ret: %d\n", ret);
-+              //return ret;
-+      default:
-+              return v4l2_ctrl_subscribe_event(fh, sub);
-+              //st_debug(ST_VIN, "unsupport subscribe_event\n");
-+              //return -EINVAL;
-+      }
-+}
-+
- static const struct v4l2_ioctl_ops stf_vid_ioctl_ops = {
-       .vidioc_querycap                = video_querycap,
-       .vidioc_enum_fmt_vid_cap        = video_enum_fmt,
-@@ -1305,6 +1321,8 @@ static const struct v4l2_ioctl_ops stf_v
-       .vidioc_s_parm                  = video_s_parm,
-       .vidioc_s_selection             = video_s_selection,
-       .vidioc_g_selection             = video_g_selection,
-+      .vidioc_subscribe_event                 = stf_video_subscribe_event,
-+      .vidioc_unsubscribe_event               = v4l2_event_unsubscribe,
- };
- static const struct v4l2_ioctl_ops stf_vid_ioctl_ops_mp = {
-@@ -1331,6 +1349,8 @@ static const struct v4l2_ioctl_ops stf_v
-       .vidioc_s_parm                  = video_s_parm,
-       .vidioc_s_selection             = video_s_selection,
-       .vidioc_g_selection             = video_g_selection,
-+      .vidioc_subscribe_event                 = stf_video_subscribe_event,
-+      .vidioc_unsubscribe_event               = v4l2_event_unsubscribe,
- };
- static const struct v4l2_ioctl_ops stf_vid_ioctl_ops_out = {
-@@ -1350,6 +1370,8 @@ static const struct v4l2_ioctl_ops stf_v
-       .vidioc_prepare_buf             = vb2_ioctl_prepare_buf,
-       .vidioc_streamon                = vb2_ioctl_streamon,
-       .vidioc_streamoff               = vb2_ioctl_streamoff,
-+      .vidioc_subscribe_event                 = stf_video_subscribe_event,
-+      .vidioc_unsubscribe_event               = v4l2_event_unsubscribe,
- };
- static int video_open(struct file *file)
---- a/drivers/media/platform/starfive/v4l2_driver/stf_vin.c
-+++ b/drivers/media/platform/starfive/v4l2_driver/stf_vin.c
-@@ -1145,9 +1145,12 @@ static void vin_buffer_done(struct vin_l
-       spin_lock_irqsave(&line->output_lock, flags);
-       while ((ready_buf = vin_buf_get_ready(output))) {
--              if (line->id >= VIN_LINE_ISP && line->id <= VIN_LINE_ISP_SS1) {
-+              //if (line->id >= VIN_LINE_ISP && line->id <= VIN_LINE_ISP_SS1) {
-+              if (line->id == VIN_LINE_ISP_SCD_Y) {
-                       event.u.frame_sync.frame_sequence = output->sequence;
--                      v4l2_event_queue(line->subdev.devnode, &event);
-+                      v4l2_event_queue(&(line->video_out.vdev), &event);
-+                      //v4l2_event_queue(line->subdev.devnode, &event);
-+                      //pr_info("----------frame sync-----------\n");
-               }
-               ready_buf->vb.vb2_buf.timestamp = ts;
-@@ -1346,7 +1349,10 @@ static int stf_vin_subscribe_event(struc
- {
-       switch (sub->type) {
-       case V4L2_EVENT_FRAME_SYNC:
--              return v4l2_event_subscribe(fh, sub, 0, NULL);
-+              //return v4l2_event_subscribe(fh, sub, 2, NULL);
-+              int ret = v4l2_event_subscribe(fh, sub, 2, NULL);
-+              pr_info("subscribe ret: %d\n", ret);
-+              return ret;
-       default:
-               st_debug(ST_VIN, "unsupport subscribe_event\n");
-               return -EINVAL;
-@@ -1355,8 +1361,8 @@ static int stf_vin_subscribe_event(struc
- static const struct v4l2_subdev_core_ops vin_core_ops = {
-       .s_power = vin_set_power,
--      .subscribe_event = stf_vin_subscribe_event,
--      .unsubscribe_event = v4l2_event_subdev_unsubscribe,
-+      //.subscribe_event = stf_vin_subscribe_event,
-+      //.unsubscribe_event = v4l2_event_subdev_unsubscribe,
- };
- static const struct v4l2_subdev_video_ops vin_video_ops = {
---- a/include/uapi/linux/jh7110-isp.h
-+++ b/include/uapi/linux/jh7110-isp.h
-@@ -15,6 +15,8 @@
- #include <linux/v4l2-controls.h>
-+#define V4L2_CID_USER_JH7110_ISP_BASE                         (V4L2_CID_USER_BASE + 0x1170)
-+
- #define V4L2_CID_USER_JH7110_ISP_WB_SETTING   \
-                               (V4L2_CID_USER_JH7110_ISP_BASE + 0x0001)
- #define V4L2_CID_USER_JH7110_ISP_CAR_SETTING  \
-@@ -45,6 +47,8 @@
-                               (V4L2_CID_USER_JH7110_ISP_BASE + 0x000e)
- #define V4L2_CID_USER_JH7110_ISP_YCRV_SETTING \
-                               (V4L2_CID_USER_JH7110_ISP_BASE + 0x000f)
-+#define V4L2_CID_USER_JH7110_ISP_STAT_SETTING \
-+                              (V4L2_CID_USER_JH7110_ISP_BASE + 0x0010)
- struct jh7110_isp_wb_gain {
-       __u16 gain_r;
-@@ -202,13 +206,13 @@ struct jh7110_isp_sat_curve {
- };
- struct jh7110_isp_sat_hue_info {
--      __s16 sin;
-       __s16 cos;
-+      __s16 sin;
- };
- struct jh7110_isp_sat_info {
-       __s16 gain_cmab;
--      __s16 gain_cmad;
-+      __s16 gain_cmmd;
-       __s16 threshold_cmb;
-       __s16 threshold_cmd;
-       __s16 offset_u;
-@@ -230,7 +234,8 @@ struct jh7110_isp_sharp_weight {
- struct jh7110_isp_sharp_strength {
-       __s16 diff[4];
--      __s16 f[4];
-+      __s16 f[3];
-+      __s32 s[3];
- };
- struct jh7110_isp_sharp_setting {
-@@ -250,4 +255,41 @@ struct jh7110_isp_ycrv_setting {
-       struct jh7110_isp_ycrv_curve curve;
- };
-+struct jh7110_isp_sc_af_config {
-+      __u8 es_hor_mode;
-+      __u8 es_sum_mode;
-+      __u8 hor_en;
-+      __u8 ver_en;
-+      __u8 es_ver_thr;
-+      __u16 es_hor_thr;
-+};
-+
-+struct jh7110_isp_sc_awb_ws {
-+      __u8 awb_ws_rl;
-+      __u8 awb_ws_ru;
-+      __u8 awb_ws_grl;
-+      __u8 awb_ws_gru;
-+      __u8 awb_ws_gbl;
-+      __u8 awb_ws_gbu;
-+      __u8 awb_ws_bl;
-+      __u8 awb_ws_bu;
-+};
-+
-+struct jh7110_isp_sc_awb_point {
-+      __u16 intensity;
-+      __u8 weight;
-+};
-+
-+struct jh7110_isp_sc_awb_config {
-+      struct jh7110_isp_sc_awb_ws ws_config;
-+      __u8 awb_cw[169];
-+      struct jh7110_isp_sc_awb_point pts[17];
-+};
-+
-+struct jh7110_isp_sc_setting {
-+      __u32 enabled;
-+      struct jh7110_isp_sc_af_config af_config;
-+      struct jh7110_isp_sc_awb_config awb_config;
-+};
-+
- #endif
diff --git a/target/linux/starfive/patches-6.6/0095-Expand-2-bytes-after-the-SC-buffer-for-the-AE-AWB-fl.patch b/target/linux/starfive/patches-6.6/0095-Expand-2-bytes-after-the-SC-buffer-for-the-AE-AWB-fl.patch
deleted file mode 100644 (file)
index d023674..0000000
+++ /dev/null
@@ -1,249 +0,0 @@
-From 5d61c6fd10144605238311d68c99449c4667a345 Mon Sep 17 00:00:00 2001
-From: "zejian.su" <zejian.su@starfivetech.com>
-Date: Mon, 7 Aug 2023 10:38:36 +0800
-Subject: [PATCH 095/116] Expand 2 bytes after the SC buffer for the AE/AWB
- flag and copy the histogram data to the SC buffer.
-
----
- .../platform/starfive/v4l2_driver/stf_isp.c   | 37 ++++++++++++++++++-
- .../platform/starfive/v4l2_driver/stf_isp.h   |  2 +-
- .../platform/starfive/v4l2_driver/stf_video.c |  5 ---
- .../platform/starfive/v4l2_driver/stf_vin.c   | 36 +++++++++---------
- include/uapi/linux/jh7110-isp.h               | 33 +++++++++++++++++
- 5 files changed, 87 insertions(+), 26 deletions(-)
-
---- a/drivers/media/platform/starfive/v4l2_driver/stf_isp.c
-+++ b/drivers/media/platform/starfive/v4l2_driver/stf_isp.c
-@@ -323,6 +323,13 @@ FILL_ISP_REGS_FUNC(u16);
- #define FILL_ISP_REGS(type, ispbase, offset, value, size, mask, nbits)        \
-       fill_isp_regs_##type(ispbase, offset, value, size, mask, nbits)
-+static void fill_regs_with_zero(void __iomem *ispbase, u32 offset, u32 size)
-+{
-+      u32 i;
-+      for(i = 0; i < size; i++, offset += 4)
-+              reg_write(ispbase, offset, 0);
-+}
-+
- static int isp_set_ctrl_wb(struct stf_isp_dev *isp_dev, const void * value)
- {
-       const struct module_register_info * reg_info = &mod_reg_info[imi_awb];
-@@ -335,6 +342,8 @@ static int isp_set_ctrl_wb(struct stf_is
-       struct stf_vin_dev *vin = isp_dev->stfcamss->vin;
-       void __iomem *ispbase = vin->isp_base;
-+      fill_regs_with_zero(ispbase, reg_info->cfg_reg, 16);
-+
-       reg_write(ispbase, reg_addr, r_g);
-       reg_write(ispbase, reg_addr + 1 * 4, r_g);
-       reg_write(ispbase, reg_addr + 2 * 4, g_g);
-@@ -370,8 +379,13 @@ static int isp_set_ctrl_ccm(struct stf_i
-       void __iomem *ispbase = vin->isp_base;
-       reg_write(ispbase, reg_info->cfg_reg, 6 << 16);
-+      fill_regs_with_zero(ispbase, reg_info->cfg_reg + 4, 11);
-+
-       FILL_ISP_REGS(u32, ispbase, reg_addr, (u32 *)ccm, 12, 0x7ff, 0);
-+      reg_addr += 12 * 4;
-+      fill_regs_with_zero(ispbase, reg_addr, 2);
-+
-       reg_set_bit(ispbase, reg_info->en_reg, 1 << reg_info->en_nbit, setting->enabled ? 1 << reg_info->en_nbit : 0);
-       return 0;
-@@ -640,6 +654,27 @@ static int isp_set_ctrl_sc(struct stf_is
-       u32 * w_diff = weight_cfg + 2;
-       s32 i;
-+      // SC dumping axi id
-+      reg_write(ispbase, 0x9c, 1 << 24);
-+
-+      // SC frame crop
-+      reg_write(ispbase, 0xb8, ((u32)(setting->crop_config.v_start) << 16) | setting->crop_config.h_start);
-+
-+      // SC config1
-+      reg_write(ispbase, 0xbc, ((u32)(setting->awb_config.sel) << 30) | ((u32)(setting->awb_config.awb_ps_grb_ba) << 16) | 
-+              ((u32)(setting->crop_config.sw_height) << 8) | setting->crop_config.sw_width);
-+
-+      // SC decimation config
-+      reg_write(ispbase, 0xd8, ((u32)(setting->crop_config.vkeep) << 24) | ((u32)(setting->crop_config.vperiod) << 16) | 
-+              ((u32)(setting->crop_config.hkeep) << 8) | setting->crop_config.hperiod);
-+
-+      // SC AWB pixel sum config
-+      reg_write(ispbase, 0xc4, CREATE_REG_VALUE(u8, &setting->awb_config.ws_ps_config.awb_ps_rl, 4, 0xff, 8));
-+      reg_write(ispbase, 0xc8, CREATE_REG_VALUE(u8, &setting->awb_config.ws_ps_config.awb_ps_bl, 4, 0xff, 8));
-+      reg_write(ispbase, 0xcc, CREATE_REG_VALUE(u16, &setting->awb_config.ws_ps_config.awb_ps_grl, 2, 0xffff, 16));
-+      reg_write(ispbase, 0xd0, CREATE_REG_VALUE(u16, &setting->awb_config.ws_ps_config.awb_ps_gbl, 2, 0xffff, 16));
-+      reg_write(ispbase, 0xd4, CREATE_REG_VALUE(u16, &setting->awb_config.ws_ps_config.awb_ps_grbl, 2, 0xffff, 16));
-+
-       // AF register
-       reg_write(ispbase, 0xc0, 
-               ((u32)(setting->af_config.es_hor_thr & 0x1ff) << 16) |
-@@ -686,7 +721,7 @@ static int isp_set_ctrl_sc(struct stf_is
-       FILL_ISP_REGS(u32, ispbase, reg_addr, weight_cfg, 6, 0xffffffff, 0);
-       reg_set_bit(ispbase, reg_info->en_reg, 1 << reg_info->en_nbit, setting->enabled ? 1 << reg_info->en_nbit : 0);
--      
-+
-       return 0;
- }
---- a/drivers/media/platform/starfive/v4l2_driver/stf_isp.h
-+++ b/drivers/media/platform/starfive/v4l2_driver/stf_isp.h
-@@ -18,7 +18,7 @@
- #define ISP_SCD_BUFFER_SIZE     (19 * 256 * 4)  // align 128
- #define ISP_YHIST_BUFFER_SIZE   (64 * 4)
--#define ISP_SCD_Y_BUFFER_SIZE   (ISP_SCD_BUFFER_SIZE + ISP_YHIST_BUFFER_SIZE)
-+#define ISP_SCD_Y_BUFFER_SIZE   (ISP_SCD_BUFFER_SIZE + ISP_YHIST_BUFFER_SIZE + 2)
- #define ISP_RAW_DATA_BITS       12
- #define SCALER_RATIO_MAX        1  // no compose function
- #define STF_ISP_REG_OFFSET_MAX  0x0FFF
---- a/drivers/media/platform/starfive/v4l2_driver/stf_video.c
-+++ b/drivers/media/platform/starfive/v4l2_driver/stf_video.c
-@@ -1287,13 +1287,8 @@ static int stf_video_subscribe_event(str
-       switch (sub->type) {
-       case V4L2_EVENT_FRAME_SYNC:
-               return v4l2_event_subscribe(fh, sub, 2, NULL);
--              //int ret = v4l2_event_subscribe(fh, sub, 2, NULL);
--              //pr_info("subscribe ret: %d\n", ret);
--              //return ret;
-       default:
-               return v4l2_ctrl_subscribe_event(fh, sub);
--              //st_debug(ST_VIN, "unsupport subscribe_event\n");
--              //return -EINVAL;
-       }
- }
---- a/drivers/media/platform/starfive/v4l2_driver/stf_vin.c
-+++ b/drivers/media/platform/starfive/v4l2_driver/stf_vin.c
-@@ -1147,6 +1147,17 @@ static void vin_buffer_done(struct vin_l
-       while ((ready_buf = vin_buf_get_ready(output))) {
-               //if (line->id >= VIN_LINE_ISP && line->id <= VIN_LINE_ISP_SS1) {
-               if (line->id == VIN_LINE_ISP_SCD_Y) {
-+#define ADDR_REG_YHIST_ACC_0               0x0D00
-+                      struct stf_vin2_dev *vin_dev = line_to_vin2_dev(line);
-+                      struct stf_vin_dev *vin = vin_dev->stfcamss->vin;
-+                      void __iomem *ispbase = vin->isp_base;
-+                      u32 y_hist_reg_addr = ADDR_REG_YHIST_ACC_0;
-+                      u32 * y_hist_addr = (u32 *)ready_buf->vaddr_sc;
-+                      s32 i = 0;
-+
-+                      for(i = 0; i < 64; i++, y_hist_reg_addr += 4)
-+                              y_hist_addr[i] = reg_read(ispbase, y_hist_reg_addr);
-+
-                       event.u.frame_sync.frame_sequence = output->sequence;
-                       v4l2_event_queue(&(line->video_out.vdev), &event);
-                       //v4l2_event_queue(line->subdev.devnode, &event);
-@@ -1246,9 +1257,14 @@ static void vin_change_buffer(struct vin
-                       scd_type = vin_dev->hw_ops->vin_isp_get_scd_type(vin_dev);
-                       ready_buf->vb.flags &= ~(V4L2_BUF_FLAG_PFRAME | V4L2_BUF_FLAG_BFRAME);
-                       if (scd_type == AWB_TYPE)
-+                      {
-                               ready_buf->vb.flags |= V4L2_BUF_FLAG_PFRAME;
--                      else
-+                              *((u16 *)(ready_buf->vaddr_sc + ISP_SCD_BUFFER_SIZE + ISP_YHIST_BUFFER_SIZE)) = 0xffff;
-+                      }else{
-                               ready_buf->vb.flags |= V4L2_BUF_FLAG_BFRAME;
-+                              *((u16 *)(ready_buf->vaddr_sc + ISP_SCD_BUFFER_SIZE + ISP_YHIST_BUFFER_SIZE)) = 0;
-+                      }
-+
-                       if (!output->frame_skip) {
-                               output->frame_skip = ISP_AWB_OECF_SKIP_FRAME;
-                               scd_type = scd_type == AWB_TYPE ? OECF_TYPE : AWB_TYPE;
-@@ -1343,26 +1359,8 @@ static int vin_link_setup(struct media_e
-       return 0;
- }
--static int stf_vin_subscribe_event(struct v4l2_subdev *sd,
--                                 struct v4l2_fh *fh,
--                                 struct v4l2_event_subscription *sub)
--{
--      switch (sub->type) {
--      case V4L2_EVENT_FRAME_SYNC:
--              //return v4l2_event_subscribe(fh, sub, 2, NULL);
--              int ret = v4l2_event_subscribe(fh, sub, 2, NULL);
--              pr_info("subscribe ret: %d\n", ret);
--              return ret;
--      default:
--              st_debug(ST_VIN, "unsupport subscribe_event\n");
--              return -EINVAL;
--      }
--}
--
- static const struct v4l2_subdev_core_ops vin_core_ops = {
-       .s_power = vin_set_power,
--      //.subscribe_event = stf_vin_subscribe_event,
--      //.unsubscribe_event = v4l2_event_subdev_unsubscribe,
- };
- static const struct v4l2_subdev_video_ops vin_video_ops = {
---- a/include/uapi/linux/jh7110-isp.h
-+++ b/include/uapi/linux/jh7110-isp.h
-@@ -255,6 +255,17 @@ struct jh7110_isp_ycrv_setting {
-       struct jh7110_isp_ycrv_curve curve;
- };
-+struct jh7110_isp_sc_config {
-+      __u16 h_start;
-+      __u16 v_start;
-+      __u8 sw_width;
-+      __u8 sw_height;
-+      __u8 hperiod;
-+      __u8 hkeep;
-+      __u8 vperiod;
-+      __u8 vkeep;
-+};
-+
- struct jh7110_isp_sc_af_config {
-       __u8 es_hor_mode;
-       __u8 es_sum_mode;
-@@ -264,6 +275,23 @@ struct jh7110_isp_sc_af_config {
-       __u16 es_hor_thr;
- };
-+struct jh7110_isp_sc_awb_ps {
-+      __u8 awb_ps_rl;
-+      __u8 awb_ps_ru;
-+      __u8 awb_ps_gl;
-+      __u8 awb_ps_gu;
-+      __u8 awb_ps_bl;
-+      __u8 awb_ps_bu;
-+      __u8 awb_ps_yl;
-+      __u8 awb_ps_yu;
-+      __u16 awb_ps_grl;
-+      __u16 awb_ps_gru;
-+      __u16 awb_ps_gbl;
-+      __u16 awb_ps_gbu;
-+      __u16 awb_ps_grbl;
-+      __u16 awb_ps_grbu;
-+};
-+
- struct jh7110_isp_sc_awb_ws {
-       __u8 awb_ws_rl;
-       __u8 awb_ws_ru;
-@@ -275,12 +303,16 @@ struct jh7110_isp_sc_awb_ws {
-       __u8 awb_ws_bu;
- };
-+
- struct jh7110_isp_sc_awb_point {
-       __u16 intensity;
-       __u8 weight;
- };
- struct jh7110_isp_sc_awb_config {
-+      struct jh7110_isp_sc_awb_ps ws_ps_config;
-+      __u8 awb_ps_grb_ba;
-+      __u8 sel;
-       struct jh7110_isp_sc_awb_ws ws_config;
-       __u8 awb_cw[169];
-       struct jh7110_isp_sc_awb_point pts[17];
-@@ -288,6 +320,7 @@ struct jh7110_isp_sc_awb_config {
- struct jh7110_isp_sc_setting {
-       __u32 enabled;
-+      struct jh7110_isp_sc_config crop_config;
-       struct jh7110_isp_sc_af_config af_config;
-       struct jh7110_isp_sc_awb_config awb_config;
- };
diff --git a/target/linux/starfive/patches-6.6/0096-Add-ISP-control-for-video2-and-video3.patch b/target/linux/starfive/patches-6.6/0096-Add-ISP-control-for-video2-and-video3.patch
deleted file mode 100644 (file)
index 5737fb2..0000000
+++ /dev/null
@@ -1,117 +0,0 @@
-From 04eff0f76091015cbecd39de41d45c493e7a91db Mon Sep 17 00:00:00 2001
-From: "zejian.su" <zejian.su@starfivetech.com>
-Date: Mon, 30 Oct 2023 16:09:58 +0800
-Subject: [PATCH 096/116] Add ISP control for video2 and video3.
-
-Signed-off-by: zejian.su <zejian.su@starfivetech.com>
----
- .../platform/starfive/v4l2_driver/stf_isp.c   | 46 +++++++++++++++++++
- include/uapi/linux/jh7110-isp.h               | 23 ++++++++++
- 2 files changed, 69 insertions(+)
-
---- a/drivers/media/platform/starfive/v4l2_driver/stf_isp.c
-+++ b/drivers/media/platform/starfive/v4l2_driver/stf_isp.c
-@@ -725,6 +725,24 @@ static int isp_set_ctrl_sc(struct stf_is
-       return 0;
- }
-+static int isp_set_ctrl_outss(struct stf_isp_dev *isp_dev, const void * value)
-+{
-+      const struct jh7110_isp_outss_setting * setting = (const struct jh7110_isp_outss_setting *)value;
-+      struct stf_vin_dev *vin = isp_dev->stfcamss->vin;
-+      void __iomem *ispbase = vin->isp_base;
-+      u32 reg_addr = !setting->which ? 0xa9c : 0xab4;
-+
-+      if(!setting->stride)
-+              return 0;
-+
-+      // Output Image Stride Register, 8-byte(64bit) granularity.
-+      reg_write(ispbase, reg_addr, setting->stride);
-+      reg_write(ispbase, reg_addr + 4, ((setting->hsm << 16) | (setting->hsm & 0x3)));
-+      reg_write(ispbase, reg_addr + 8, ((setting->vsm << 16) | (setting->vsm & 0x3)));
-+
-+      return 0;
-+}
-+
- static int isp_s_ctrl(struct v4l2_ctrl *ctrl)
- {
-       struct v4l2_subdev *sd = ctrl_to_sd(ctrl);
-@@ -822,6 +840,10 @@ static int isp_s_ctrl(struct v4l2_ctrl *
-       case V4L2_CID_USER_JH7110_ISP_STAT_SETTING:
-               ret = isp_set_ctrl_sc(isp_dev, ctrl->p_new.p_u8);
-               break;
-+      case V4L2_CID_USER_JH7110_ISP_OUTSS0_SETTING:
-+      case V4L2_CID_USER_JH7110_ISP_OUTSS1_SETTING:
-+              ret = isp_set_ctrl_outss(isp_dev, ctrl->p_new.p_u8);
-+              break;
-       default:
-               ret = -EINVAL;
-               break;
-@@ -1028,6 +1050,30 @@ struct v4l2_ctrl_config isp_ctrl[] = {
-               .dims[0]        = sizeof(struct jh7110_isp_sc_setting),
-               .flags          = 0,
-       },
-+      [16] = {
-+              .ops            = &isp_ctrl_ops,
-+              .type           = V4L2_CTRL_TYPE_U8,
-+              .def            = 0,
-+              .min            = 0x00,
-+              .max            = 0xff,
-+              .step           = 1,
-+              .name           = "OUTSS Setting",
-+              .id             = V4L2_CID_USER_JH7110_ISP_OUTSS0_SETTING,
-+              .dims[0]        = sizeof(struct jh7110_isp_outss_setting),
-+              .flags          = 0,
-+      },
-+      [17] = {
-+              .ops            = &isp_ctrl_ops,
-+              .type           = V4L2_CTRL_TYPE_U8,
-+              .def            = 0,
-+              .min            = 0x00,
-+              .max            = 0xff,
-+              .step           = 1,
-+              .name           = "OUTSS Setting",
-+              .id             = V4L2_CID_USER_JH7110_ISP_OUTSS1_SETTING,
-+              .dims[0]        = sizeof(struct jh7110_isp_outss_setting),
-+              .flags          = 0,
-+      },
- };
- static int isp_init_controls(struct stf_isp_dev *isp_dev)
---- a/include/uapi/linux/jh7110-isp.h
-+++ b/include/uapi/linux/jh7110-isp.h
-@@ -49,6 +49,10 @@
-                               (V4L2_CID_USER_JH7110_ISP_BASE + 0x000f)
- #define V4L2_CID_USER_JH7110_ISP_STAT_SETTING \
-                               (V4L2_CID_USER_JH7110_ISP_BASE + 0x0010)
-+#define V4L2_CID_USER_JH7110_ISP_OUTSS0_SETTING \
-+                              (V4L2_CID_USER_JH7110_ISP_BASE + 0x0011)
-+#define V4L2_CID_USER_JH7110_ISP_OUTSS1_SETTING \
-+                              (V4L2_CID_USER_JH7110_ISP_BASE + 0x0012)
- struct jh7110_isp_wb_gain {
-       __u16 gain_r;
-@@ -325,4 +329,23 @@ struct jh7110_isp_sc_setting {
-       struct jh7110_isp_sc_awb_config awb_config;
- };
-+struct jh7110_isp_outss_setting {
-+      __u8 which;
-+      __u16 stride;   // Output Image Stride Register, 8-byte(64bit) granularity.
-+      __u8 hsm;               // horizontal scale mode
-+      __u32 hsf;              // horizontal scale factor (time 4096)
-+      __u8 vsm;               // vertical scale mode
-+      __u32 vsf;              // vertical scale factor (time 4096)
-+};
-+
-+struct jh7110_isp_sc_buffer {
-+      __u32 y_histogram[64];
-+      __u32 reserv0[33];
-+      __u32 bright_sc[4096];
-+      __u32 reserv1[96];
-+      __u32 ae_hist_y[128];
-+      __u32 reserv2[511];
-+      __u16 flag;
-+};
-+
- #endif
diff --git a/target/linux/starfive/patches-6.6/0097-media-starfive-Update-ISP-initialzation.patch b/target/linux/starfive/patches-6.6/0097-media-starfive-Update-ISP-initialzation.patch
deleted file mode 100644 (file)
index b1d857e..0000000
+++ /dev/null
@@ -1,226 +0,0 @@
-From 883745d4728e524babfe7d04cbb8a925c22aa6b5 Mon Sep 17 00:00:00 2001
-From: Changhuang Liang <changhuang.liang@starfivetech.com>
-Date: Mon, 13 Nov 2023 14:46:50 +0800
-Subject: [PATCH 097/116] media: starfive: Update ISP initialzation
-
-ISP compatible stf_isp_ctrl and libcamera.
-
-Signed-off-by: Changhuang Liang <changhuang.liang@starfivetech.com>
----
- .../platform/starfive/v4l2_driver/stf_isp.c   | 55 ++++++++-----------
- 1 file changed, 24 insertions(+), 31 deletions(-)
-
---- a/drivers/media/platform/starfive/v4l2_driver/stf_isp.c
-+++ b/drivers/media/platform/starfive/v4l2_driver/stf_isp.c
-@@ -402,7 +402,7 @@ static int isp_set_ctrl_cfa(struct stf_i
-       reg_write(ispbase, reg_addr, ((u32)(cfg->cross_cov & 0x3) << 4) | (cfg->hv_width & 0xf));
-       reg_set_bit(ispbase, reg_info->en_reg, 1 << reg_info->en_nbit, setting->enabled ? 1 << reg_info->en_nbit : 0);
--      
-+
-       return 0;
- }
-@@ -419,7 +419,7 @@ static int isp_set_ctrl_ctc(struct stf_i
-       reg_value |= ((u32)(cfg->max_gt & 0x3ff) << 16) | (cfg->min_gt & 0x3ff);
-       reg_write(ispbase, reg_addr, reg_value);
-       reg_set_bit(ispbase, reg_info->en_reg, 1 << reg_info->en_nbit, setting->enabled ? 1 << reg_info->en_nbit : 0);
--      
-+
-       return 0;
- }
-@@ -434,7 +434,7 @@ static int isp_set_ctrl_dbc(struct stf_i
-       reg_write(ispbase, reg_addr, ((u32)(cfg->bad_gt & 0x3ff) << 16) | (cfg->bad_xt & 0x3ff));
-       reg_set_bit(ispbase, reg_info->en_reg, 1 << reg_info->en_nbit, setting->enabled ? 1 << reg_info->en_nbit : 0);
--      
-+
-       return 0;
- }
-@@ -459,7 +459,7 @@ static int isp_set_ctrl_dnyuv(struct stf
-       reg_write(ispbase, reg_addr + 36, CREATE_REG_VALUE(u16, &cfg->uv_curve[4], 2, 0x3ff, 16));
-       reg_set_bit(ispbase, reg_info->en_reg, 1 << reg_info->en_nbit, setting->enabled ? 1 << reg_info->en_nbit : 0);
--      
-+
-       return 0;
- }
-@@ -472,7 +472,7 @@ static int isp_set_ctrl_gmargb(struct st
-       struct stf_vin_dev *vin = isp_dev->stfcamss->vin;
-       void __iomem *ispbase = vin->isp_base;
-       s32 i;
--      
-+
-       for(i = 0; i < 15; i++, curve++, reg_addr += 4)
-               reg_write(ispbase, reg_addr, ((u32)curve->sg_val << 16) | (curve->g_val & 0x3ff));
-@@ -490,7 +490,7 @@ static int isp_set_ctrl_lccf(struct stf_
-       struct stf_vin_dev *vin = isp_dev->stfcamss->vin;
-       void __iomem *ispbase = vin->isp_base;
-       s32 i;
--      
-+
-       reg_write(ispbase, reg_addr, ((u32)(setting->circle.center_y & 0x7fff) << 16) | (setting->circle.center_x & 0x7fff));
-       reg_write(ispbase, reg_addr + 8, setting->circle.radius & 0xf);
-       reg_addr += 0x90;
-@@ -498,7 +498,7 @@ static int isp_set_ctrl_lccf(struct stf_
-               reg_write(ispbase, reg_addr, CREATE_REG_VALUE(u16, params, 2, 0x1fff, 16));
-       reg_set_bit(ispbase, reg_info->en_reg, 1 << reg_info->en_nbit, setting->enabled ? 1 << reg_info->en_nbit : 0);
--      
-+
-       return 0;
- }
-@@ -511,7 +511,7 @@ static int isp_set_ctrl_obc(struct stf_i
-       struct stf_vin_dev *vin = isp_dev->stfcamss->vin;
-       void __iomem *ispbase = vin->isp_base;
-       s32 i;
--      
-+
-       reg_write(ispbase, reg_addr, ((u32)(setting->win_size.height & 0xf) << 4) | (setting->win_size.width & 0xf));
-       reg_addr += 0x2ac;      //0x2e0
-@@ -519,7 +519,7 @@ static int isp_set_ctrl_obc(struct stf_i
-               reg_write(ispbase, reg_addr, CREATE_REG_VALUE(u8, params, 4, 0xff, 8));
-       reg_set_bit(ispbase, reg_info->en_reg, 1 << reg_info->en_nbit, setting->enabled ? 1 << reg_info->en_nbit : 0);
--      
-+
-       return 0;
- }
-@@ -535,7 +535,7 @@ static int isp_set_ctrl_oecf(struct stf_
-       void __iomem *ispbase = vin->isp_base;
-       u32 x, y, slope;
-       s32 i;
--      
-+
-       for(i = 0; i < 32; i++, reg_x_addr += 4, reg_y_addr += 4, reg_s_addr += 4) {
-               x = pts->x & 0x3ff;
-               y = pts->y & 0x3ff;
-@@ -565,12 +565,12 @@ static int isp_set_ctrl_r2y(struct stf_i
-       struct stf_vin_dev *vin = isp_dev->stfcamss->vin;
-       void __iomem *ispbase = vin->isp_base;
-       s32 i;
--      
-+
-       for(i = 0; i < 9; i++, reg_addr += 4)
-               reg_write(ispbase, reg_addr, (u32)(params[i] & 0x1ff));
-       reg_set_bit(ispbase, reg_info->en_reg, 1 << reg_info->en_nbit, setting->enabled ? 1 << reg_info->en_nbit : 0);
--      
-+
-       return 0;
- }
-@@ -584,7 +584,7 @@ static int isp_set_ctrl_sat(struct stf_i
-       struct stf_vin_dev *vin = isp_dev->stfcamss->vin;
-       void __iomem *ispbase = vin->isp_base;
-       s32 i;
--      
-+
-       for(i = 0; i < 3; i++, reg_addr += 4, params += 2)
-               reg_write(ispbase, reg_addr, CREATE_REG_VALUE(u16, params, 2, 0xfff, 16));
-       reg_write(ispbase, reg_addr, CREATE_REG_VALUE(u16, &setting->hue_info.cos, 2, 0x3ff, 16));
-@@ -597,7 +597,7 @@ static int isp_set_ctrl_sat(struct stf_i
-               reg_write(ispbase, reg_addr, CREATE_REG_VALUE(u16, params, 2, 0x3fff, 16));
-       reg_set_bit(ispbase, reg_info->en_reg, 1 << reg_info->en_nbit, setting->enabled ? 1 << reg_info->en_nbit : 0);
--      
-+
-       return 0;
- }
-@@ -609,7 +609,7 @@ static int isp_set_ctrl_shrp(struct stf_
-       struct stf_vin_dev *vin = isp_dev->stfcamss->vin;
-       void __iomem *ispbase = vin->isp_base;
-       s32 i;
--      
-+
-       for(i = 0; i < 4; i++, reg_addr += 4)
-               reg_write(ispbase, reg_addr, ((u32)(setting->strength.diff[i] & 0x3ff) << 16) | ((u32)(setting->weight.weight[i] & 0xf) << 8));
-       FILL_ISP_REGS(u8, ispbase, reg_addr, (u8 *)(&setting->weight.weight[4]), 15 - 4, 0xf, 8);
-@@ -622,7 +622,7 @@ static int isp_set_ctrl_shrp(struct stf_
-       reg_write(ispbase, reg_addr, ((u32)(setting->pdirf & 0xf) << 28) | ((u32)(setting->ndirf & 0xf) << 24) | (setting->weight.recip_wei_sum & 0x3fffff));
-       reg_set_bit(ispbase, reg_info->en_reg, 1 << reg_info->en_nbit, setting->enabled ? 1 << reg_info->en_nbit : 0);
--      
-+
-       return 0;
- }
-@@ -633,11 +633,11 @@ static int isp_set_ctrl_ycrv(struct stf_
-       u32 reg_addr = reg_info->cfg_reg;
-       struct stf_vin_dev *vin = isp_dev->stfcamss->vin;
-       void __iomem *ispbase = vin->isp_base;
--      
-+
-       FILL_ISP_REGS(u16, ispbase, reg_addr, (u16 *)(setting->curve.y), 64, 0x3ff, 0);
-       reg_set_bit(ispbase, reg_info->en_reg, 1 << reg_info->en_nbit, setting->enabled ? 1 << reg_info->en_nbit : 0);
--      
-+
-       return 0;
- }
-@@ -661,11 +661,11 @@ static int isp_set_ctrl_sc(struct stf_is
-       reg_write(ispbase, 0xb8, ((u32)(setting->crop_config.v_start) << 16) | setting->crop_config.h_start);
-       // SC config1
--      reg_write(ispbase, 0xbc, ((u32)(setting->awb_config.sel) << 30) | ((u32)(setting->awb_config.awb_ps_grb_ba) << 16) | 
-+      reg_write(ispbase, 0xbc, ((u32)(setting->awb_config.sel) << 30) | ((u32)(setting->awb_config.awb_ps_grb_ba) << 16) |
-               ((u32)(setting->crop_config.sw_height) << 8) | setting->crop_config.sw_width);
-       // SC decimation config
--      reg_write(ispbase, 0xd8, ((u32)(setting->crop_config.vkeep) << 24) | ((u32)(setting->crop_config.vperiod) << 16) | 
-+      reg_write(ispbase, 0xd8, ((u32)(setting->crop_config.vkeep) << 24) | ((u32)(setting->crop_config.vperiod) << 16) |
-               ((u32)(setting->crop_config.hkeep) << 8) | setting->crop_config.hperiod);
-       // SC AWB pixel sum config
-@@ -676,7 +676,7 @@ static int isp_set_ctrl_sc(struct stf_is
-       reg_write(ispbase, 0xd4, CREATE_REG_VALUE(u16, &setting->awb_config.ws_ps_config.awb_ps_grbl, 2, 0xffff, 16));
-       // AF register
--      reg_write(ispbase, 0xc0, 
-+      reg_write(ispbase, 0xc0,
-               ((u32)(setting->af_config.es_hor_thr & 0x1ff) << 16) |
-               ((u32)(setting->af_config.es_ver_thr & 0xff) << 8) |
-               ((setting->af_config.ver_en & 0x1) << 3) |
-@@ -1217,7 +1217,7 @@ static int isp_get_interface_type(struct
- static int isp_set_stream(struct v4l2_subdev *sd, int enable)
- {
-       struct stf_isp_dev *isp_dev = v4l2_get_subdevdata(sd);
--      int ret = 0, interface_type;
-+      int interface_type;
-       struct v4l2_mbus_framefmt *fmt;
-       struct v4l2_event src_ch = { 0 };
-@@ -1225,6 +1225,7 @@ static int isp_set_stream(struct v4l2_su
-       mutex_lock(&isp_dev->stream_lock);
-       if (enable) {
-               if (isp_dev->stream_count == 0) {
-+                      v4l2_ctrl_handler_setup(&isp_dev->ctrls.handler);
-                       isp_dev->hw_ops->isp_clk_enable(isp_dev);
-                       if (!user_config_isp)
-                               isp_dev->hw_ops->isp_config_set(isp_dev);
-@@ -1256,15 +1257,7 @@ static int isp_set_stream(struct v4l2_su
- exit:
-       mutex_unlock(&isp_dev->stream_lock);
--      mutex_lock(&isp_dev->power_lock);
--      /* restore controls */
--      if (enable && isp_dev->power_count == 1) {
--              mutex_unlock(&isp_dev->power_lock);
--              ret = v4l2_ctrl_handler_setup(&isp_dev->ctrls.handler);
--      } else
--              mutex_unlock(&isp_dev->power_lock);
--
--      return ret;
-+      return 0;
- }
- /*Try to match sensor format with sink, and then get the index as default.*/
diff --git a/target/linux/starfive/patches-6.6/0098-crypto-jh7110-Comment-RSA-algo-register.patch b/target/linux/starfive/patches-6.6/0098-crypto-jh7110-Comment-RSA-algo-register.patch
deleted file mode 100644 (file)
index ca36e5b..0000000
+++ /dev/null
@@ -1,36 +0,0 @@
-From 02f84ff43453b0f8dc2a1e4885e7003929349ee6 Mon Sep 17 00:00:00 2001
-From: Hal Feng <hal.feng@starfivetech.com>
-Date: Tue, 5 Mar 2024 11:00:21 +0800
-Subject: [PATCH 098/116] crypto: jh7110: Comment RSA algo register
-
-There are some issues in RSA algo, which will cause kernel crash.
-So comment RSA algo register temporarily.
-This commit should be reverted after the RSA issues are fixed.
-
-Signed-off-by: Hal Feng <hal.feng@starfivetech.com>
----
- drivers/crypto/starfive/jh7110-cryp.c | 10 +++++-----
- 1 file changed, 5 insertions(+), 5 deletions(-)
-
---- a/drivers/crypto/starfive/jh7110-cryp.c
-+++ b/drivers/crypto/starfive/jh7110-cryp.c
-@@ -194,14 +194,14 @@ static int starfive_cryp_probe(struct pl
-       if (ret)
-               goto err_algs_hash;
--      ret = starfive_rsa_register_algs();
--      if (ret)
--              goto err_algs_rsa;
-+//    ret = starfive_rsa_register_algs();
-+//    if (ret)
-+//            goto err_algs_rsa;
-       return 0;
--err_algs_rsa:
--      starfive_hash_unregister_algs();
-+// err_algs_rsa:
-+//    starfive_hash_unregister_algs();
- err_algs_hash:
-       starfive_aes_unregister_algs();
- err_algs_aes:
diff --git a/target/linux/starfive/patches-6.6/0099-riscv-dts-starfive-jh7110-evb-Add-qspi-norflash-part.patch b/target/linux/starfive/patches-6.6/0099-riscv-dts-starfive-jh7110-evb-Add-qspi-norflash-part.patch
deleted file mode 100644 (file)
index d04b082..0000000
+++ /dev/null
@@ -1,26 +0,0 @@
-From a7ff2b51e2941526d6924dcf8f1760187d7e5d03 Mon Sep 17 00:00:00 2001
-From: Hal Feng <hal.feng@starfivetech.com>
-Date: Mon, 11 Mar 2024 11:10:45 +0800
-Subject: [PATCH 099/116] riscv: dts: starfive: jh7110-evb: Add qspi norflash
- partition for uboot-env
-
-Add qspi norflash partition "uboot-env@f0000",
-for synchronizing with other branches.
-
-Signed-off-by: Hal Feng <hal.feng@starfivetech.com>
----
- arch/riscv/boot/dts/starfive/jh7110-evb.dtsi | 3 +++
- 1 file changed, 3 insertions(+)
-
---- a/arch/riscv/boot/dts/starfive/jh7110-evb.dtsi
-+++ b/arch/riscv/boot/dts/starfive/jh7110-evb.dtsi
-@@ -568,6 +568,9 @@
-                       spl@0 {
-                               reg = <0x0 0x40000>;
-                       };
-+                      uboot-env@f0000 {
-+                              reg = <0xf0000 0x10000>;
-+                      };
-                       uboot@100000 {
-                               reg = <0x100000 0x300000>;
-                       };
diff --git a/target/linux/starfive/patches-6.6/0100-driver-regulator-pmic-driver-support-kernel-6.6.patch b/target/linux/starfive/patches-6.6/0100-driver-regulator-pmic-driver-support-kernel-6.6.patch
deleted file mode 100644 (file)
index ad8b98d..0000000
+++ /dev/null
@@ -1,22 +0,0 @@
-From f96ba2eb39ba950f67edf43e0c5c88ac660bc2a0 Mon Sep 17 00:00:00 2001
-From: Ziv Xu <ziv.xu@starfivetech.com>
-Date: Wed, 13 Mar 2024 18:43:27 +0800
-Subject: [PATCH 100/116] driver: regulator: pmic driver support kernel 6.6
-
-pmic driver support kernel 6.6
-
-Signed-off-by: Ziv Xu <ziv.xu@starfivetech.com>
----
- drivers/regulator/axp20x-regulator.c | 1 +
- 1 file changed, 1 insertion(+)
-
---- a/drivers/regulator/axp20x-regulator.c
-+++ b/drivers/regulator/axp20x-regulator.c
-@@ -20,6 +20,7 @@
- #include <linux/mfd/axp20x.h>
- #include <linux/module.h>
- #include <linux/of.h>
-+#include <linux/of_device.h>
- #include <linux/platform_device.h>
- #include <linux/regmap.h>
- #include <linux/regulator/driver.h>
diff --git a/target/linux/starfive/patches-6.6/0101-spi-pl022-starfive-Add-platform-bus-register-to-adap.patch b/target/linux/starfive/patches-6.6/0101-spi-pl022-starfive-Add-platform-bus-register-to-adap.patch
deleted file mode 100644 (file)
index 8112243..0000000
+++ /dev/null
@@ -1,232 +0,0 @@
-From c609818850807a1ae5fa17e165f2b66b914188b4 Mon Sep 17 00:00:00 2001
-From: "xingyu.wu" <xingyu.wu@starfivetech.com>
-Date: Tue, 28 Jun 2022 22:48:15 +0800
-Subject: [PATCH 101/116] spi-pl022:starfive:Add platform bus register to adapt
- overlay
-
-Add platform bus register to adapt dtbo overlay.
-
-Signed-off-by: Xingyu Wu <xingyu.wu@starfivetech.com>
-Signed-off-by: Hal Feng <hal.feng@starfivetech.com>
----
- drivers/spi/spi-pl022.c | 137 ++++++++++++++++++++++++++++++++++++++--
- 1 file changed, 131 insertions(+), 6 deletions(-)
-
---- a/drivers/spi/spi-pl022.c
-+++ b/drivers/spi/spi-pl022.c
-@@ -34,6 +34,7 @@
- #include <linux/of.h>
- #include <linux/pinctrl/consumer.h>
- #include <linux/reset.h>
-+#include <linux/platform_device.h>
- /*
-  * This macro is used to define some register default values.
-@@ -2088,7 +2089,10 @@ pl022_platform_data_dt_get(struct device
-               return NULL;
-       }
--      pd = devm_kzalloc(dev, sizeof(struct pl022_ssp_controller), GFP_KERNEL);
-+      if (strncmp(dev->bus->name, "platform", strlen("platform")))
-+              pd = devm_kzalloc(dev, sizeof(struct pl022_ssp_controller), GFP_KERNEL);
-+      else
-+              pd = kzalloc(sizeof(struct pl022_ssp_controller), GFP_KERNEL);
-       if (!pd)
-               return NULL;
-@@ -2108,6 +2112,14 @@ static int pl022_probe(struct amba_devic
-       struct spi_controller *host;
-       struct pl022 *pl022 = NULL;     /*Data for this driver */
-       int status = 0;
-+      int platform_flag = 0;
-+
-+      if (strncmp(dev->bus->name, "platform", strlen("platform")))
-+              platform_flag = 0;
-+      else
-+              platform_flag = 1;
-+      dev_dbg(&adev->dev, "bus name:%s platform flag:%d",
-+                      dev->bus->name, platform_flag);
-       dev_info(&adev->dev,
-                "ARM PL022 driver, device ID: 0x%08x\n", adev->periphid);
-@@ -2161,7 +2173,11 @@ static int pl022_probe(struct amba_devic
-               goto err_no_ioregion;
-       pl022->phybase = adev->res.start;
--      pl022->virtbase = devm_ioremap(dev, adev->res.start,
-+      if (platform_flag)
-+              pl022->virtbase = ioremap(adev->res.start,
-+                                     resource_size(&adev->res));
-+      else
-+              pl022->virtbase = devm_ioremap(dev, adev->res.start,
-                                      resource_size(&adev->res));
-       if (pl022->virtbase == NULL) {
-               status = -ENOMEM;
-@@ -2170,7 +2186,10 @@ static int pl022_probe(struct amba_devic
-       dev_info(&adev->dev, "mapped registers from %pa to %p\n",
-               &adev->res.start, pl022->virtbase);
--      pl022->clk = devm_clk_get(&adev->dev, NULL);
-+      if (platform_flag)
-+              pl022->clk = clk_get(&adev->dev, NULL);
-+      else
-+              pl022->clk = devm_clk_get(&adev->dev, NULL);
-       if (IS_ERR(pl022->clk)) {
-               status = PTR_ERR(pl022->clk);
-               dev_err(&adev->dev, "could not retrieve SSP/SPI bus clock\n");
-@@ -2183,7 +2202,10 @@ static int pl022_probe(struct amba_devic
-               goto err_no_clk_en;
-       }
--      pl022->rst = devm_reset_control_get(&adev->dev, NULL);
-+      if (platform_flag)
-+              pl022->rst = reset_control_get_exclusive(&adev->dev, NULL);
-+      else
-+              pl022->rst = devm_reset_control_get(&adev->dev, NULL);
-       if (IS_ERR(pl022->rst)) {
-               status = PTR_ERR(pl022->rst);
-               dev_err(&adev->dev, "could not retrieve SSP/SPI bus reset\n");
-@@ -2205,7 +2227,11 @@ static int pl022_probe(struct amba_devic
-              SSP_CR1(pl022->virtbase));
-       load_ssp_default_config(pl022);
--      status = devm_request_irq(dev, adev->irq[0], pl022_interrupt_handler,
-+      if (platform_flag)
-+              status = request_irq(adev->irq[0], pl022_interrupt_handler,
-+                                0, "pl022", pl022);
-+      else
-+              status = devm_request_irq(dev, adev->irq[0], pl022_interrupt_handler,
-                                 0, "pl022", pl022);
-       if (status < 0) {
-               dev_err(&adev->dev, "probe - cannot get IRQ (%d)\n", status);
-@@ -2230,7 +2256,10 @@ static int pl022_probe(struct amba_devic
-       /* Register with the SPI framework */
-       amba_set_drvdata(adev, pl022);
--      status = devm_spi_register_controller(&adev->dev, host);
-+      if (platform_flag)
-+              status = spi_register_controller(host);
-+      else
-+              status = devm_spi_register_controller(&adev->dev, host);
-       if (status != 0) {
-               dev_err_probe(&adev->dev, status,
-                             "problem registering spi host\n");
-@@ -2255,15 +2284,26 @@ static int pl022_probe(struct amba_devic
-       if (platform_info->enable_dma)
-               pl022_dma_remove(pl022);
-  err_no_irq:
-+      if (platform_flag)
-+              free_irq(adev->irq[0], pl022);
-+      reset_control_assert(pl022->rst);
-  err_no_rst_de:
-+      if (platform_flag)
-+              reset_control_put(pl022->rst);
-  err_no_rst:
-       clk_disable_unprepare(pl022->clk);
-  err_no_clk_en:
-+      if (platform_flag)
-+              clk_put(pl022->clk);
-  err_no_clk:
-+      if (platform_flag)
-+              iounmap(pl022->virtbase);
-  err_no_ioremap:
-       amba_release_regions(adev);
-  err_no_ioregion:
-       spi_controller_put(host);
-+      if (platform_flag)
-+              kfree(platform_info);
-       return status;
- }
-@@ -2464,6 +2504,91 @@ static void __exit pl022_exit(void)
- }
- module_exit(pl022_exit);
-+/*
-+ * Register PL022 in platform bus to accommodate overlay use.
-+ * Because overlay only trigger response from the platform bus
-+ * not amba bus.
-+ */
-+static int starfive_of_pl022_probe(struct platform_device *pdev)
-+{
-+      int ret;
-+      const struct amba_id id = {
-+              .id = 0x00041022,
-+              .mask = 0x000fffff,
-+              .data = &vendor_arm
-+      };
-+      struct amba_device *pcdev;
-+      struct device *dev = &pdev->dev;
-+
-+      pcdev = devm_kzalloc(&pdev->dev, sizeof(*pcdev), GFP_KERNEL);
-+      if (!pcdev)
-+              return -ENOMEM;
-+
-+      pcdev->dev = pdev->dev;
-+      pcdev->periphid = id.id;
-+      pcdev->res = *(pdev->resource);
-+
-+      pcdev->irq[0] = platform_get_irq(pdev, 0);
-+      if (pcdev->irq[0] < 0) {
-+              dev_err(dev, "failed to get irq\n");
-+              ret = -EINVAL;
-+      }
-+
-+      ret = pl022_probe(pcdev, &id);
-+
-+      return ret;
-+}
-+
-+static int starfive_of_pl022_remove(struct platform_device *pdev)
-+{
-+      u32 size;
-+      int irq;
-+      struct pl022 *pl022 = dev_get_drvdata(&pdev->dev);
-+
-+      if (!pl022)
-+              return 0;
-+
-+      pm_runtime_get_noresume(&pdev->dev);
-+
-+      load_ssp_default_config(pl022);
-+      if (pl022->host_info->enable_dma)
-+              pl022_dma_remove(pl022);
-+
-+      irq = platform_get_irq(pdev, 0);
-+      free_irq(irq, pl022);
-+      reset_control_assert(pl022->rst);
-+      reset_control_put(pl022->rst);
-+      clk_disable_unprepare(pl022->clk);
-+      clk_put(pl022->clk);
-+      iounmap(pl022->virtbase);
-+      kfree(pl022->host_info);
-+
-+      size = resource_size(pdev->resource);
-+      release_mem_region(pdev->resource->start, size);
-+      tasklet_disable(&pl022->pump_transfers);
-+      return 0;
-+}
-+
-+static const struct of_device_id starfive_of_pl022_match[] = {
-+      { .compatible = "starfive,jh7110-spi-pl022" },
-+      { },
-+};
-+MODULE_DEVICE_TABLE(of, starfive_of_pl022_match);
-+
-+static struct platform_driver starfive_of_pl022_driver = {
-+      .driver = {
-+              .name = "starfive-spi-pl022",
-+              .of_match_table = starfive_of_pl022_match,
-+              .pm     = &pl022_dev_pm_ops,
-+      },
-+      .probe = starfive_of_pl022_probe,
-+      .remove = starfive_of_pl022_remove,
-+};
-+
-+module_platform_driver(starfive_of_pl022_driver);
-+/* platform register end */
-+
-+MODULE_AUTHOR("xingyu.wu <xingyu.wu@starfivetech.com>");
- MODULE_AUTHOR("Linus Walleij <linus.walleij@stericsson.com>");
- MODULE_DESCRIPTION("PL022 SSP Controller Driver");
- MODULE_LICENSE("GPL");
diff --git a/target/linux/starfive/patches-6.6/0102-spi-pl022-starfive-Avoid-power-device-error-when-CON.patch b/target/linux/starfive/patches-6.6/0102-spi-pl022-starfive-Avoid-power-device-error-when-CON.patch
deleted file mode 100644 (file)
index bd4709f..0000000
+++ /dev/null
@@ -1,92 +0,0 @@
-From f94a07310f18720faa0cc773a1aec5a7b1bf3928 Mon Sep 17 00:00:00 2001
-From: "xingyu.wu" <xingyu.wu@starfivetech.com>
-Date: Tue, 19 Jul 2022 14:49:20 +0800
-Subject: [PATCH 102/116] spi:pl022-starfive:Avoid power device error when
- CONFIG_PM enable
-
-It would be error when CONFIG_PM enable and use overlay by of-platform to register.
-
-Add some power manager operation in platform probe function.
-
-Signed-off-by: Xingyu Wu <xingyu.wu@starfivetech.com>
-Signed-off-by: Ziv Xu <ziv.xu@starfivetech.com>
-Signed-off-by: Hal Feng <hal.feng@starfivetech.com>
----
- drivers/spi/spi-pl022.c | 36 ++++++++++++++++++++++++++++++++++--
- 1 file changed, 34 insertions(+), 2 deletions(-)
-
---- a/drivers/spi/spi-pl022.c
-+++ b/drivers/spi/spi-pl022.c
-@@ -35,6 +35,8 @@
- #include <linux/pinctrl/consumer.h>
- #include <linux/reset.h>
- #include <linux/platform_device.h>
-+#include <linux/clk/clk-conf.h>
-+#include <linux/pm_domain.h>
- /*
-  * This macro is used to define some register default values.
-@@ -2266,7 +2268,8 @@ static int pl022_probe(struct amba_devic
-               goto err_spi_register;
-       }
-       dev_dbg(dev, "probe succeeded\n");
--
-+      if (!platform_flag)
-+              platform_info->autosuspend_delay = 100;
-       /* let runtime pm put suspend */
-       if (platform_info->autosuspend_delay > 0) {
-               dev_info(&adev->dev,
-@@ -2276,7 +2279,10 @@ static int pl022_probe(struct amba_devic
-                       platform_info->autosuspend_delay);
-               pm_runtime_use_autosuspend(dev);
-       }
--      pm_runtime_put(dev);
-+      if (platform_flag)
-+              clk_disable_unprepare(pl022->clk);
-+      else
-+              pm_runtime_put(dev);
-       return 0;
-@@ -2534,8 +2540,33 @@ static int starfive_of_pl022_probe(struc
-               ret = -EINVAL;
-       }
-+      ret = of_clk_set_defaults(dev->of_node, false);
-+      if (ret < 0)
-+              goto err_probe;
-+
-+      ret = dev_pm_domain_attach(dev, true);
-+      if (ret)
-+              goto err_probe;
-+
-       ret = pl022_probe(pcdev, &id);
-+      struct pl022 *pl022 = amba_get_drvdata(pcdev);
-+
-+      pl022->host->dev.parent = &pdev->dev;
-+      platform_set_drvdata(pdev, pl022);
-+
-+      pm_runtime_enable(&pdev->dev);
-+      pm_runtime_set_autosuspend_delay(&pdev->dev, 100);
-+      pm_runtime_use_autosuspend(&pdev->dev);
-+
-+      if (ret) {
-+              pm_runtime_disable(dev);
-+              pm_runtime_set_suspended(dev);
-+              pm_runtime_put_noidle(dev);
-+              dev_pm_domain_detach(dev, true);
-+      }
-+
-+err_probe:
-       return ret;
- }
-@@ -2566,6 +2597,7 @@ static int starfive_of_pl022_remove(stru
-       size = resource_size(pdev->resource);
-       release_mem_region(pdev->resource->start, size);
-       tasklet_disable(&pl022->pump_transfers);
-+      pm_runtime_disable(&pdev->dev);
-       return 0;
- }
diff --git a/target/linux/starfive/patches-6.6/0103-spi-pl022-starfive-fix-the-problem-of-spi-overlay-re.patch b/target/linux/starfive/patches-6.6/0103-spi-pl022-starfive-fix-the-problem-of-spi-overlay-re.patch
deleted file mode 100644 (file)
index 3e36e84..0000000
+++ /dev/null
@@ -1,403 +0,0 @@
-From 733e7bd23a1efad15a724fbdbce8d9f06aa6813a Mon Sep 17 00:00:00 2001
-From: "ziv.xu" <ziv.xu@starfive.com>
-Date: Wed, 23 Nov 2022 14:53:58 +0800
-Subject: [PATCH 103/116] spi-pl022-starfive:fix the problem of spi overlay
- reload
-
-fix the problem of spi overlay reload
-
-Signed-off-by: ziv.xu <ziv.xu@starfive.com>
-Signed-off-by: Hal Feng <hal.feng@starfivetech.com>
----
- drivers/spi/spi-pl022.c | 270 ++++++++++++++++++++++++++++------------
- 1 file changed, 188 insertions(+), 82 deletions(-)
-
---- a/drivers/spi/spi-pl022.c
-+++ b/drivers/spi/spi-pl022.c
-@@ -2106,6 +2106,172 @@ pl022_platform_data_dt_get(struct device
-       return pd;
- }
-+static int pl022_platform_probe(struct platform_device *pdev, const struct amba_id *id)
-+{
-+      struct device *dev = &pdev->dev;
-+      struct spi_controller *host;
-+      struct pl022_ssp_controller *platform_info;
-+      struct amba_device *adev;
-+      struct pl022 *pl022 = NULL;
-+      struct resource *res;
-+      int status = 0;
-+      int irq;
-+
-+      dev_info(dev,
-+              "ARM PL022 driver for StarFive SoC platform, device ID: 0x%08x\n",
-+              id->id);
-+
-+      adev = devm_kzalloc(dev, sizeof(*adev), GFP_KERNEL);
-+      adev->dev = pdev->dev;
-+      platform_info = pl022_platform_data_dt_get(dev);
-+      if (!platform_info) {
-+              dev_err(dev, "probe: no platform data defined\n");
-+              return -ENODEV;
-+      }
-+      /* Allocate host with space for data */
-+      host = spi_alloc_host(dev, sizeof(struct pl022));
-+      if (host == NULL) {
-+              dev_err(dev, "probe - cannot alloc SPI host\n");
-+              return -ENOMEM;
-+      }
-+
-+      pl022 = spi_controller_get_devdata(host);
-+      pl022->host = host;
-+      pl022->host_info = platform_info;
-+      pl022->adev = adev;
-+      pl022->vendor = id->data;
-+      pl022->host->dev.parent = &pdev->dev;
-+      /*
-+       * Bus Number Which has been Assigned to this SSP controller
-+       * on this board
-+       */
-+      host->bus_num = platform_info->bus_id;
-+      host->cleanup = pl022_cleanup;
-+      host->setup = pl022_setup;
-+      /* If open CONFIG_PM, auto_runtime_pm should be false when of-platform.*/
-+      host->auto_runtime_pm = true;
-+      host->transfer_one_message = pl022_transfer_one_message;
-+      host->unprepare_transfer_hardware = pl022_unprepare_transfer_hardware;
-+      host->rt = platform_info->rt;
-+      host->dev.of_node = dev->of_node;
-+      host->use_gpio_descriptors = true;
-+
-+      /*
-+       * Supports mode 0-3, loopback, and active low CS. Transfers are
-+       * always MS bit first on the original pl022.
-+       */
-+      host->mode_bits = SPI_CPOL | SPI_CPHA | SPI_CS_HIGH | SPI_LOOP;
-+      if (pl022->vendor->extended_cr)
-+              host->mode_bits |= SPI_LSB_FIRST;
-+
-+      dev_dbg(dev, "BUSNO: %d\n", host->bus_num);
-+
-+      res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-+      pl022->phybase = res->start;
-+      pl022->virtbase = devm_ioremap_resource(dev, res);
-+      if (pl022->virtbase == NULL) {
-+              status = -ENOMEM;
-+              goto err_no_ioremap;
-+      }
-+      dev_info(dev, "mapped registers from %llx to %llx\n",
-+               pdev->resource->start, pdev->resource->end);
-+
-+      pl022->clk = devm_clk_get(dev, NULL);
-+      if (IS_ERR(pl022->clk)) {
-+              status = PTR_ERR(pl022->clk);
-+              dev_err(dev, "could not retrieve SSP/SPI bus clock\n");
-+              goto err_no_clk;
-+      }
-+      status = clk_prepare_enable(pl022->clk);
-+      if (status) {
-+              dev_err(dev, "could not enable SSP/SPI bus clock\n");
-+              goto err_no_clk_en;
-+      }
-+
-+      pl022->rst = devm_reset_control_get_exclusive(dev, NULL);
-+      if (!IS_ERR(pl022->rst)) {
-+              status = reset_control_deassert(pl022->rst);
-+              if (status) {
-+                      dev_err(dev, "could not deassert SSP/SPI bus reset\n");
-+                      goto err_no_rst_clr;
-+              }
-+      } else {
-+              status = PTR_ERR(pl022->rst);
-+              dev_err(dev, "could not retrieve SSP/SPI bus reset\n");
-+              goto err_no_rst;
-+      }
-+
-+      /* Initialize transfer pump */
-+      tasklet_init(&pl022->pump_transfers, pump_transfers,
-+                   (unsigned long)pl022);
-+
-+      /* Disable SSP */
-+      writew((readw(SSP_CR1(pl022->virtbase)) & (~SSP_CR1_MASK_SSE)),
-+             SSP_CR1(pl022->virtbase));
-+      load_ssp_default_config(pl022);
-+
-+      /* Obtain IRQ line. */
-+      irq = platform_get_irq(pdev, 0);
-+      if (irq < 0) {
-+              status = -ENXIO;
-+              goto err_no_irq;
-+      }
-+      status = devm_request_irq(dev, irq, pl022_interrupt_handler,
-+                                0, "pl022", pl022);
-+      if (status < 0) {
-+              dev_err(dev, "probe - cannot get IRQ (%d)\n", status);
-+              goto err_no_irq;
-+      }
-+
-+      /* Get DMA channels, try autoconfiguration first */
-+      status = pl022_dma_autoprobe(pl022);
-+      if (status == -EPROBE_DEFER) {
-+              dev_dbg(dev, "deferring probe to get DMA channel\n");
-+              goto err_no_irq;
-+      }
-+
-+      /* dma is not used unless configured in the device tree */
-+      platform_info->enable_dma = 0;
-+
-+      /* If that failed, use channels from platform_info */
-+      if (status == 0)
-+              platform_info->enable_dma = 1;
-+      else if (platform_info->enable_dma) {
-+              status = pl022_dma_probe(pl022);
-+              if (status != 0)
-+                      platform_info->enable_dma = 0;
-+      }
-+
-+      /* Register with the SPI framework */
-+      dev_set_drvdata(dev, pl022);
-+
-+      status = devm_spi_register_controller(dev, host);
-+      if (status != 0) {
-+              dev_err(dev,
-+                      "probe - problem registering spi host\n");
-+              goto err_spi_register;
-+      }
-+      dev_dbg(dev, "probe succeeded\n");
-+
-+      clk_disable_unprepare(pl022->clk);
-+
-+      return 0;
-+ err_spi_register:
-+      if (platform_info->enable_dma)
-+              pl022_dma_remove(pl022);
-+ err_no_irq:
-+      reset_control_assert(pl022->rst);
-+ err_no_rst_clr:
-+ err_no_rst:
-+      clk_disable_unprepare(pl022->clk);
-+ err_no_clk_en:
-+ err_no_clk:
-+ err_no_ioremap:
-+      release_mem_region(pdev->resource->start, resource_size(pdev->resource));
-+      spi_controller_put(host);
-+      return status;
-+}
-+
- static int pl022_probe(struct amba_device *adev, const struct amba_id *id)
- {
-       struct device *dev = &adev->dev;
-@@ -2114,14 +2280,6 @@ static int pl022_probe(struct amba_devic
-       struct spi_controller *host;
-       struct pl022 *pl022 = NULL;     /*Data for this driver */
-       int status = 0;
--      int platform_flag = 0;
--
--      if (strncmp(dev->bus->name, "platform", strlen("platform")))
--              platform_flag = 0;
--      else
--              platform_flag = 1;
--      dev_dbg(&adev->dev, "bus name:%s platform flag:%d",
--                      dev->bus->name, platform_flag);
-       dev_info(&adev->dev,
-                "ARM PL022 driver, device ID: 0x%08x\n", adev->periphid);
-@@ -2175,11 +2333,7 @@ static int pl022_probe(struct amba_devic
-               goto err_no_ioregion;
-       pl022->phybase = adev->res.start;
--      if (platform_flag)
--              pl022->virtbase = ioremap(adev->res.start,
--                                     resource_size(&adev->res));
--      else
--              pl022->virtbase = devm_ioremap(dev, adev->res.start,
-+      pl022->virtbase = devm_ioremap(dev, adev->res.start,
-                                      resource_size(&adev->res));
-       if (pl022->virtbase == NULL) {
-               status = -ENOMEM;
-@@ -2188,10 +2342,7 @@ static int pl022_probe(struct amba_devic
-       dev_info(&adev->dev, "mapped registers from %pa to %p\n",
-               &adev->res.start, pl022->virtbase);
--      if (platform_flag)
--              pl022->clk = clk_get(&adev->dev, NULL);
--      else
--              pl022->clk = devm_clk_get(&adev->dev, NULL);
-+      pl022->clk = devm_clk_get(&adev->dev, NULL);
-       if (IS_ERR(pl022->clk)) {
-               status = PTR_ERR(pl022->clk);
-               dev_err(&adev->dev, "could not retrieve SSP/SPI bus clock\n");
-@@ -2204,10 +2355,7 @@ static int pl022_probe(struct amba_devic
-               goto err_no_clk_en;
-       }
--      if (platform_flag)
--              pl022->rst = reset_control_get_exclusive(&adev->dev, NULL);
--      else
--              pl022->rst = devm_reset_control_get(&adev->dev, NULL);
-+      pl022->rst = devm_reset_control_get(&adev->dev, NULL);
-       if (IS_ERR(pl022->rst)) {
-               status = PTR_ERR(pl022->rst);
-               dev_err(&adev->dev, "could not retrieve SSP/SPI bus reset\n");
-@@ -2229,11 +2377,7 @@ static int pl022_probe(struct amba_devic
-              SSP_CR1(pl022->virtbase));
-       load_ssp_default_config(pl022);
--      if (platform_flag)
--              status = request_irq(adev->irq[0], pl022_interrupt_handler,
--                                0, "pl022", pl022);
--      else
--              status = devm_request_irq(dev, adev->irq[0], pl022_interrupt_handler,
-+      status = devm_request_irq(dev, adev->irq[0], pl022_interrupt_handler,
-                                 0, "pl022", pl022);
-       if (status < 0) {
-               dev_err(&adev->dev, "probe - cannot get IRQ (%d)\n", status);
-@@ -2258,18 +2402,16 @@ static int pl022_probe(struct amba_devic
-       /* Register with the SPI framework */
-       amba_set_drvdata(adev, pl022);
--      if (platform_flag)
--              status = spi_register_controller(host);
--      else
--              status = devm_spi_register_controller(&adev->dev, host);
-+
-+      status = devm_spi_register_controller(&adev->dev, host);
-       if (status != 0) {
-               dev_err_probe(&adev->dev, status,
-                             "problem registering spi host\n");
-               goto err_spi_register;
-       }
-       dev_dbg(dev, "probe succeeded\n");
--      if (!platform_flag)
--              platform_info->autosuspend_delay = 100;
-+
-+      platform_info->autosuspend_delay = 100;
-       /* let runtime pm put suspend */
-       if (platform_info->autosuspend_delay > 0) {
-               dev_info(&adev->dev,
-@@ -2279,10 +2421,8 @@ static int pl022_probe(struct amba_devic
-                       platform_info->autosuspend_delay);
-               pm_runtime_use_autosuspend(dev);
-       }
--      if (platform_flag)
--              clk_disable_unprepare(pl022->clk);
--      else
--              pm_runtime_put(dev);
-+
-+      pm_runtime_put(dev);
-       return 0;
-@@ -2290,26 +2430,17 @@ static int pl022_probe(struct amba_devic
-       if (platform_info->enable_dma)
-               pl022_dma_remove(pl022);
-  err_no_irq:
--      if (platform_flag)
--              free_irq(adev->irq[0], pl022);
-       reset_control_assert(pl022->rst);
-  err_no_rst_de:
--      if (platform_flag)
--              reset_control_put(pl022->rst);
-  err_no_rst:
-       clk_disable_unprepare(pl022->clk);
-  err_no_clk_en:
--      if (platform_flag)
--              clk_put(pl022->clk);
-  err_no_clk:
--      if (platform_flag)
--              iounmap(pl022->virtbase);
-  err_no_ioremap:
-       amba_release_regions(adev);
-  err_no_ioregion:
-       spi_controller_put(host);
--      if (platform_flag)
--              kfree(platform_info);
-+
-       return status;
- }
-@@ -2523,23 +2654,8 @@ static int starfive_of_pl022_probe(struc
-               .mask = 0x000fffff,
-               .data = &vendor_arm
-       };
--      struct amba_device *pcdev;
-       struct device *dev = &pdev->dev;
--      pcdev = devm_kzalloc(&pdev->dev, sizeof(*pcdev), GFP_KERNEL);
--      if (!pcdev)
--              return -ENOMEM;
--
--      pcdev->dev = pdev->dev;
--      pcdev->periphid = id.id;
--      pcdev->res = *(pdev->resource);
--
--      pcdev->irq[0] = platform_get_irq(pdev, 0);
--      if (pcdev->irq[0] < 0) {
--              dev_err(dev, "failed to get irq\n");
--              ret = -EINVAL;
--      }
--
-       ret = of_clk_set_defaults(dev->of_node, false);
-       if (ret < 0)
-               goto err_probe;
-@@ -2548,16 +2664,11 @@ static int starfive_of_pl022_probe(struc
-       if (ret)
-               goto err_probe;
--      ret = pl022_probe(pcdev, &id);
-+      ret = pl022_platform_probe(pdev, &id);
--      struct pl022 *pl022 = amba_get_drvdata(pcdev);
--
--      pl022->host->dev.parent = &pdev->dev;
--      platform_set_drvdata(pdev, pl022);
--
--      pm_runtime_enable(&pdev->dev);
--      pm_runtime_set_autosuspend_delay(&pdev->dev, 100);
--      pm_runtime_use_autosuspend(&pdev->dev);
-+      pm_runtime_enable(dev);
-+      pm_runtime_set_autosuspend_delay(dev, 100);
-+      pm_runtime_use_autosuspend(dev);
-       if (ret) {
-               pm_runtime_disable(dev);
-@@ -2572,32 +2683,27 @@ err_probe:
- static int starfive_of_pl022_remove(struct platform_device *pdev)
- {
--      u32 size;
--      int irq;
-       struct pl022 *pl022 = dev_get_drvdata(&pdev->dev);
-       if (!pl022)
-               return 0;
-+      pm_runtime_get_sync(&pdev->dev);
-       pm_runtime_get_noresume(&pdev->dev);
-       load_ssp_default_config(pl022);
-       if (pl022->host_info->enable_dma)
-               pl022_dma_remove(pl022);
--      irq = platform_get_irq(pdev, 0);
--      free_irq(irq, pl022);
--      reset_control_assert(pl022->rst);
--      reset_control_put(pl022->rst);
-       clk_disable_unprepare(pl022->clk);
--      clk_put(pl022->clk);
--      iounmap(pl022->virtbase);
--      kfree(pl022->host_info);
--
--      size = resource_size(pdev->resource);
--      release_mem_region(pdev->resource->start, size);
-       tasklet_disable(&pl022->pump_transfers);
-+
-+      pm_runtime_put_noidle(&pdev->dev);
-       pm_runtime_disable(&pdev->dev);
-+      pm_runtime_set_suspended(&pdev->dev);
-+      pm_runtime_put_noidle(&pdev->dev);
-+      dev_pm_domain_detach(&pdev->dev, true);
-+
-       return 0;
- }
diff --git a/target/linux/starfive/patches-6.6/0104-spi-pl022-starfive-Enable-spi-to-be-compiled-into-mo.patch b/target/linux/starfive/patches-6.6/0104-spi-pl022-starfive-Enable-spi-to-be-compiled-into-mo.patch
deleted file mode 100644 (file)
index aecce73..0000000
+++ /dev/null
@@ -1,38 +0,0 @@
-From 11a917bf429a5714e34584f90ab1ac376d399d8f Mon Sep 17 00:00:00 2001
-From: "ziv.xu" <ziv.xu@starfive.com>
-Date: Wed, 18 Jan 2023 15:50:47 +0800
-Subject: [PATCH 104/116] spi-pl022-starfive:Enable spi to be compiled into
- modules
-
-Enable spi to be compiled into modules
-
-Signed-off-by: ziv.xu <ziv.xu@starfive.com>
-Signed-off-by: Hal Feng <hal.feng@starfivetech.com>
----
- drivers/spi/spi-pl022.c | 6 ++++++
- 1 file changed, 6 insertions(+)
-
---- a/drivers/spi/spi-pl022.c
-+++ b/drivers/spi/spi-pl022.c
-@@ -2633,7 +2633,11 @@ static int __init pl022_init(void)
- {
-       return amba_driver_register(&pl022_driver);
- }
-+#if !IS_MODULE(CONFIG_SPI_PL022)
- subsys_initcall(pl022_init);
-+#else
-+module_init(pl022_init);
-+#endif
- static void __exit pl022_exit(void)
- {
-@@ -2723,7 +2727,9 @@ static struct platform_driver starfive_o
-       .remove = starfive_of_pl022_remove,
- };
-+#if !IS_MODULE(CONFIG_SPI_PL022)
- module_platform_driver(starfive_of_pl022_driver);
-+#endif
- /* platform register end */
- MODULE_AUTHOR("xingyu.wu <xingyu.wu@starfivetech.com>");
diff --git a/target/linux/starfive/patches-6.6/0105-riscv-configs-add-visionfive2-defconfig-to-kernel-6..patch b/target/linux/starfive/patches-6.6/0105-riscv-configs-add-visionfive2-defconfig-to-kernel-6..patch
deleted file mode 100644 (file)
index bc1d836..0000000
+++ /dev/null
@@ -1,444 +0,0 @@
-From e7b01c0a9ad79c1933ce85c4aeca6a037cc4f77f Mon Sep 17 00:00:00 2001
-From: Ziv Xu <ziv.xu@starfivetech.com>
-Date: Wed, 13 Mar 2024 18:37:31 +0800
-Subject: [PATCH 105/116] riscv: configs: add visionfive2 defconfig to kernel
- 6.6
-
-add visionfive2 defconfig to kernel 6.6
-
-Signed-off-by: Ziv Xu <ziv.xu@starfivetech.com>
----
- .../configs/starfive_visionfive2_defconfig    | 427 ++++++++++++++++++
- 1 file changed, 427 insertions(+)
- create mode 100644 arch/riscv/configs/starfive_visionfive2_defconfig
-
---- /dev/null
-+++ b/arch/riscv/configs/starfive_visionfive2_defconfig
-@@ -0,0 +1,427 @@
-+CONFIG_COMPILE_TEST=y
-+# CONFIG_WERROR is not set
-+CONFIG_DEFAULT_HOSTNAME="StarFive"
-+CONFIG_SYSVIPC=y
-+CONFIG_POSIX_MQUEUE=y
-+CONFIG_USELIB=y
-+CONFIG_NO_HZ_IDLE=y
-+CONFIG_HIGH_RES_TIMERS=y
-+CONFIG_BPF_SYSCALL=y
-+CONFIG_IKCONFIG=y
-+CONFIG_IKCONFIG_PROC=y
-+CONFIG_CGROUPS=y
-+CONFIG_CGROUP_SCHED=y
-+CONFIG_CFS_BANDWIDTH=y
-+CONFIG_CGROUP_BPF=y
-+CONFIG_NAMESPACES=y
-+CONFIG_USER_NS=y
-+CONFIG_CHECKPOINT_RESTORE=y
-+CONFIG_BLK_DEV_INITRD=y
-+CONFIG_EXPERT=y
-+CONFIG_PERF_EVENTS=y
-+CONFIG_SOC_STARFIVE=y
-+CONFIG_NONPORTABLE=y
-+CONFIG_SMP=y
-+CONFIG_HZ_100=y
-+CONFIG_HIBERNATION=y
-+CONFIG_PM_DEBUG=y
-+CONFIG_PM_ADVANCED_DEBUG=y
-+CONFIG_PM_TEST_SUSPEND=y
-+CONFIG_CPU_IDLE=y
-+CONFIG_RISCV_SBI_CPUIDLE=y
-+CONFIG_CPU_FREQ=y
-+CONFIG_CPU_FREQ_STAT=y
-+CONFIG_CPU_FREQ_DEFAULT_GOV_ONDEMAND=y
-+CONFIG_CPU_FREQ_GOV_POWERSAVE=y
-+CONFIG_CPU_FREQ_GOV_USERSPACE=y
-+CONFIG_CPU_FREQ_GOV_CONSERVATIVE=y
-+CONFIG_CPU_FREQ_GOV_SCHEDUTIL=y
-+CONFIG_CPUFREQ_DT=y
-+# CONFIG_SECCOMP is not set
-+CONFIG_MODULES=y
-+CONFIG_MODULE_UNLOAD=y
-+CONFIG_BINFMT_MISC=y
-+CONFIG_PAGE_REPORTING=y
-+CONFIG_CMA=y
-+CONFIG_NET=y
-+CONFIG_PACKET=y
-+CONFIG_IP_MULTICAST=y
-+CONFIG_IP_ADVANCED_ROUTER=y
-+CONFIG_IP_PNP=y
-+CONFIG_IP_PNP_DHCP=y
-+CONFIG_IP_PNP_BOOTP=y
-+CONFIG_IP_PNP_RARP=y
-+CONFIG_NETFILTER=y
-+CONFIG_NETFILTER_NETLINK_ACCT=y
-+CONFIG_NETFILTER_NETLINK_QUEUE=y
-+CONFIG_NF_CONNTRACK=y
-+CONFIG_NF_TABLES=y
-+CONFIG_NFT_CT=y
-+CONFIG_NFT_COMPAT=y
-+CONFIG_NETFILTER_XT_MATCH_CONNTRACK=y
-+CONFIG_NETFILTER_XT_MATCH_IPCOMP=y
-+CONFIG_NETFILTER_XT_MATCH_IPRANGE=y
-+CONFIG_NETFILTER_XT_MATCH_MAC=y
-+CONFIG_NETFILTER_XT_MATCH_MARK=y
-+CONFIG_NETFILTER_XT_MATCH_MULTIPORT=y
-+CONFIG_NETFILTER_XT_MATCH_SOCKET=y
-+CONFIG_NETFILTER_XT_MATCH_STATE=y
-+CONFIG_NETFILTER_XT_MATCH_STRING=y
-+CONFIG_NETFILTER_XT_MATCH_U32=y
-+CONFIG_NF_TABLES_IPV4=y
-+CONFIG_NFT_DUP_IPV4=y
-+CONFIG_NFT_FIB_IPV4=y
-+CONFIG_IP_NF_IPTABLES=y
-+CONFIG_IP_NF_FILTER=y
-+CONFIG_IP_NF_TARGET_REJECT=y
-+CONFIG_IP_NF_NAT=y
-+CONFIG_IP_NF_TARGET_MASQUERADE=y
-+CONFIG_IP_NF_TARGET_NETMAP=y
-+CONFIG_IP_NF_TARGET_REDIRECT=y
-+CONFIG_NETLINK_DIAG=y
-+CONFIG_CAN=y
-+CONFIG_BT=y
-+CONFIG_BT_RFCOMM=y
-+CONFIG_BT_RFCOMM_TTY=y
-+CONFIG_BT_BNEP=y
-+CONFIG_BT_BNEP_MC_FILTER=y
-+CONFIG_BT_BNEP_PROTO_FILTER=y
-+CONFIG_BT_HCIBTUSB=m
-+# CONFIG_BT_HCIBTUSB_BCM is not set
-+CONFIG_CFG80211=y
-+CONFIG_MAC80211=y
-+CONFIG_RFKILL=y
-+CONFIG_NET_9P=y
-+CONFIG_NET_9P_VIRTIO=y
-+CONFIG_PCI=y
-+# CONFIG_PCIEASPM is not set
-+CONFIG_PCIE_STARFIVE_HOST=y
-+CONFIG_DEVTMPFS=y
-+CONFIG_DEVTMPFS_MOUNT=y
-+CONFIG_MTD=y
-+CONFIG_MTD_BLOCK=y
-+CONFIG_MTD_CFI=y
-+CONFIG_MTD_CFI_ADV_OPTIONS=y
-+CONFIG_MTD_SPI_NOR=y
-+CONFIG_OF_CONFIGFS=y
-+CONFIG_BLK_DEV_LOOP=y
-+CONFIG_VIRTIO_BLK=y
-+CONFIG_BLK_DEV_NVME=y
-+CONFIG_EEPROM_AT24=y
-+CONFIG_BLK_DEV_SD=y
-+CONFIG_BLK_DEV_SR=y
-+CONFIG_SCSI_VIRTIO=y
-+CONFIG_ATA=y
-+CONFIG_SATA_AHCI=y
-+CONFIG_MD=y
-+CONFIG_BLK_DEV_DM=m
-+CONFIG_NETDEVICES=y
-+CONFIG_VIRTIO_NET=y
-+# CONFIG_NET_VENDOR_ALACRITECH is not set
-+# CONFIG_NET_VENDOR_AMAZON is not set
-+# CONFIG_NET_VENDOR_AQUANTIA is not set
-+# CONFIG_NET_VENDOR_ARC is not set
-+# CONFIG_NET_VENDOR_BROADCOM is not set
-+# CONFIG_NET_VENDOR_CADENCE is not set
-+# CONFIG_NET_VENDOR_CAVIUM is not set
-+# CONFIG_NET_VENDOR_CORTINA is not set
-+# CONFIG_NET_VENDOR_EZCHIP is not set
-+# CONFIG_NET_VENDOR_GOOGLE is not set
-+# CONFIG_NET_VENDOR_HUAWEI is not set
-+# CONFIG_NET_VENDOR_INTEL is not set
-+# CONFIG_NET_VENDOR_MARVELL is not set
-+# CONFIG_NET_VENDOR_MELLANOX is not set
-+# CONFIG_NET_VENDOR_MICREL is not set
-+# CONFIG_NET_VENDOR_MICROCHIP is not set
-+# CONFIG_NET_VENDOR_MICROSEMI is not set
-+# CONFIG_NET_VENDOR_NI is not set
-+# CONFIG_NET_VENDOR_NATSEMI is not set
-+# CONFIG_NET_VENDOR_NETRONOME is not set
-+# CONFIG_NET_VENDOR_PENSANDO is not set
-+# CONFIG_NET_VENDOR_QUALCOMM is not set
-+CONFIG_R8169=y
-+# CONFIG_NET_VENDOR_RENESAS is not set
-+# CONFIG_NET_VENDOR_ROCKER is not set
-+# CONFIG_NET_VENDOR_SAMSUNG is not set
-+# CONFIG_NET_VENDOR_SEEQ is not set
-+# CONFIG_NET_VENDOR_SOLARFLARE is not set
-+# CONFIG_NET_VENDOR_SOCIONEXT is not set
-+CONFIG_STMMAC_ETH=y
-+CONFIG_STMMAC_SELFTESTS=y
-+CONFIG_DWMAC_DWC_QOS_ETH=y
-+CONFIG_DWMAC_STARFIVE=y
-+# CONFIG_NET_VENDOR_SYNOPSYS is not set
-+# CONFIG_NET_VENDOR_VIA is not set
-+# CONFIG_NET_VENDOR_WIZNET is not set
-+# CONFIG_NET_VENDOR_XILINX is not set
-+CONFIG_MARVELL_PHY=y
-+CONFIG_MICREL_PHY=y
-+CONFIG_MICROCHIP_PHY=y
-+CONFIG_MOTORCOMM_PHY=y
-+CONFIG_IPMS_CAN=y
-+CONFIG_IWLWIFI=y
-+CONFIG_IWLDVM=y
-+CONFIG_IWLMVM=y
-+CONFIG_HOSTAP=y
-+# CONFIG_RTL_CARDS is not set
-+CONFIG_USB_WIFI_ECR6600U=y
-+CONFIG_AIC_WLAN_SUPPORT=y
-+CONFIG_AIC8800_WLAN_SUPPORT=m
-+CONFIG_AIC_LOADFW_SUPPORT=m
-+CONFIG_INPUT_EVDEV=y
-+# CONFIG_INPUT_KEYBOARD is not set
-+# CONFIG_INPUT_MOUSE is not set
-+CONFIG_INPUT_TOUCHSCREEN=y
-+CONFIG_TOUCHSCREEN_GOODIX=y
-+CONFIG_TOUCHSCREEN_TINKER_FT5406=y
-+CONFIG_SERIO_LIBPS2=y
-+CONFIG_SERIAL_8250=y
-+CONFIG_SERIAL_8250_CONSOLE=y
-+CONFIG_SERIAL_8250_NR_UARTS=6
-+CONFIG_SERIAL_8250_RUNTIME_UARTS=6
-+CONFIG_SERIAL_8250_EXTENDED=y
-+CONFIG_SERIAL_8250_MANY_PORTS=y
-+CONFIG_SERIAL_8250_DW=y
-+CONFIG_SERIAL_OF_PLATFORM=y
-+CONFIG_TTY_PRINTK=y
-+CONFIG_VIRTIO_CONSOLE=y
-+CONFIG_HW_RANDOM=y
-+CONFIG_HW_RANDOM_JH7110=y
-+CONFIG_I2C_CHARDEV=y
-+CONFIG_I2C_DESIGNWARE_PLATFORM=y
-+CONFIG_SPI=y
-+CONFIG_SPI_CADENCE_QUADSPI=y
-+CONFIG_SPI_PL022=y
-+CONFIG_SPI_SIFIVE=y
-+CONFIG_SPI_SPIDEV=y
-+# CONFIG_PTP_1588_CLOCK is not set
-+CONFIG_GPIO_SYSFS=y
-+CONFIG_POWER_RESET=y
-+CONFIG_POWER_RESET_GPIO_RESTART=y
-+CONFIG_POWER_RESET_SYSCON=y
-+CONFIG_POWER_RESET_SYSCON_POWEROFF=y
-+CONFIG_SENSORS_SFCTEMP=y
-+CONFIG_THERMAL=y
-+CONFIG_THERMAL_WRITABLE_TRIPS=y
-+CONFIG_CPU_THERMAL=y
-+CONFIG_DEVFREQ_THERMAL=y
-+CONFIG_THERMAL_EMULATION=y
-+# CONFIG_HISI_THERMAL is not set
-+CONFIG_WATCHDOG=y
-+CONFIG_WATCHDOG_SYSFS=y
-+CONFIG_MFD_AXP20X_I2C=y
-+CONFIG_REGULATOR=y
-+CONFIG_REGULATOR_AXP20X=y
-+CONFIG_REGULATOR_GPIO=y
-+CONFIG_REGULATOR_RASPBERRYPI_TOUCHSCREEN_ATTINY=y
-+# CONFIG_MEDIA_CEC_SUPPORT is not set
-+CONFIG_MEDIA_SUPPORT=y
-+CONFIG_MEDIA_USB_SUPPORT=y
-+CONFIG_USB_VIDEO_CLASS=y
-+CONFIG_V4L_PLATFORM_DRIVERS=y
-+CONFIG_V4L_MEM2MEM_DRIVERS=y
-+CONFIG_VIDEO_CADENCE_CSI2RX=y
-+CONFIG_VIDEO_WAVE_VPU=m
-+CONFIG_VIN_SENSOR_OV4689=y
-+CONFIG_VIN_SENSOR_IMX219=y
-+CONFIG_VIDEO_STF_VIN=y
-+CONFIG_VIDEO_IMX219=y
-+CONFIG_VIDEO_IMX708=y
-+CONFIG_DRM_PANEL_SIMPLE=y
-+CONFIG_DRM_PANEL_JADARD_JD9365DA_H3=y
-+CONFIG_DRM_TOSHIBA_TC358762=y
-+CONFIG_DRM_VERISILICON=y
-+CONFIG_STARFIVE_INNO_HDMI=y
-+CONFIG_STARFIVE_DSI=y
-+CONFIG_DRM_IMG_ROGUE=y
-+CONFIG_DRM_LEGACY=y
-+CONFIG_FB=y
-+CONFIG_BACKLIGHT_CLASS_DEVICE=y
-+CONFIG_SOUND=y
-+CONFIG_SND=y
-+CONFIG_SND_USB_AUDIO=y
-+CONFIG_SND_SOC=y
-+CONFIG_SND_DESIGNWARE_I2S=y
-+CONFIG_SND_SOC_RZ=m
-+CONFIG_SND_SOC_STARFIVE=y
-+CONFIG_SND_SOC_JH7110_PWMDAC=y
-+CONFIG_SND_SOC_JH7110_TDM=y
-+CONFIG_SND_SOC_AC108=y
-+CONFIG_SND_SOC_WM8960=y
-+CONFIG_SND_SIMPLE_CARD=y
-+CONFIG_UHID=y
-+CONFIG_USB=y
-+CONFIG_USB_OTG=y
-+CONFIG_USB_XHCI_HCD=y
-+CONFIG_USB_RENESAS_USBHS=y
-+CONFIG_USB_STORAGE=y
-+CONFIG_USB_UAS=y
-+CONFIG_USB_CDNS_SUPPORT=y
-+CONFIG_USB_CDNS3=y
-+CONFIG_USB_CDNS3_GADGET=y
-+CONFIG_USB_CDNS3_HOST=y
-+CONFIG_USB_CDNS3_STARFIVE=y
-+CONFIG_USB_SERIAL=m
-+CONFIG_USB_SERIAL_GENERIC=y
-+CONFIG_USB_SERIAL_AIRCABLE=m
-+CONFIG_USB_SERIAL_ARK3116=m
-+CONFIG_USB_SERIAL_BELKIN=m
-+CONFIG_USB_SERIAL_CH341=m
-+CONFIG_USB_SERIAL_WHITEHEAT=m
-+CONFIG_USB_SERIAL_DIGI_ACCELEPORT=m
-+CONFIG_USB_SERIAL_CP210X=m
-+CONFIG_USB_SERIAL_CYPRESS_M8=m
-+CONFIG_USB_SERIAL_EMPEG=m
-+CONFIG_USB_SERIAL_FTDI_SIO=m
-+CONFIG_USB_SERIAL_VISOR=m
-+CONFIG_USB_SERIAL_IPAQ=m
-+CONFIG_USB_SERIAL_IR=m
-+CONFIG_USB_SERIAL_EDGEPORT=m
-+CONFIG_USB_SERIAL_EDGEPORT_TI=m
-+CONFIG_USB_SERIAL_F81232=m
-+CONFIG_USB_SERIAL_GARMIN=m
-+CONFIG_USB_SERIAL_IPW=m
-+CONFIG_USB_SERIAL_IUU=m
-+CONFIG_USB_SERIAL_KEYSPAN_PDA=m
-+CONFIG_USB_SERIAL_KEYSPAN=m
-+CONFIG_USB_SERIAL_KLSI=m
-+CONFIG_USB_SERIAL_KOBIL_SCT=m
-+CONFIG_USB_SERIAL_MCT_U232=m
-+CONFIG_USB_SERIAL_METRO=m
-+CONFIG_USB_SERIAL_MOS7720=m
-+CONFIG_USB_SERIAL_MOS7840=m
-+CONFIG_USB_SERIAL_NAVMAN=m
-+CONFIG_USB_SERIAL_PL2303=m
-+CONFIG_USB_SERIAL_OTI6858=m
-+CONFIG_USB_SERIAL_QCAUX=m
-+CONFIG_USB_SERIAL_QUALCOMM=m
-+CONFIG_USB_SERIAL_SPCP8X5=m
-+CONFIG_USB_SERIAL_SAFE=m
-+CONFIG_USB_SERIAL_SIERRAWIRELESS=m
-+CONFIG_USB_SERIAL_SYMBOL=m
-+CONFIG_USB_SERIAL_TI=m
-+CONFIG_USB_SERIAL_CYBERJACK=m
-+CONFIG_USB_SERIAL_OMNINET=m
-+CONFIG_USB_SERIAL_OPTICON=m
-+CONFIG_USB_SERIAL_XSENS_MT=m
-+CONFIG_USB_SERIAL_WISHBONE=m
-+CONFIG_USB_SERIAL_SSU100=m
-+CONFIG_USB_SERIAL_DEBUG=m
-+CONFIG_USB_GADGET=y
-+CONFIG_USB_RENESAS_USBHS_UDC=m
-+CONFIG_USB_CONFIGFS=y
-+CONFIG_USB_CONFIGFS_SERIAL=y
-+CONFIG_USB_CONFIGFS_ACM=y
-+CONFIG_USB_CONFIGFS_OBEX=y
-+CONFIG_USB_CONFIGFS_NCM=y
-+CONFIG_USB_CONFIGFS_ECM=y
-+CONFIG_USB_CONFIGFS_ECM_SUBSET=y
-+CONFIG_USB_CONFIGFS_RNDIS=y
-+CONFIG_USB_CONFIGFS_EEM=y
-+CONFIG_USB_CONFIGFS_MASS_STORAGE=y
-+CONFIG_USB_CONFIGFS_F_FS=y
-+CONFIG_MMC=y
-+CONFIG_MMC_DEBUG=y
-+CONFIG_MMC_SDHCI=y
-+CONFIG_MMC_SDHCI_PLTFM=y
-+CONFIG_MMC_SDHCI_OF_DWCMSHC=y
-+CONFIG_MMC_SPI=y
-+CONFIG_MMC_SDHI=y
-+CONFIG_MMC_DW=y
-+CONFIG_MMC_DW_STARFIVE=y
-+CONFIG_NEW_LEDS=y
-+CONFIG_LEDS_CLASS=y
-+CONFIG_LEDS_GPIO=y
-+CONFIG_LEDS_TRIGGER_HEARTBEAT=y
-+CONFIG_RTC_CLASS=y
-+CONFIG_RTC_DRV_STARFIVE=y
-+CONFIG_RTC_DRV_GOLDFISH=y
-+CONFIG_DMADEVICES=y
-+CONFIG_AMBA_PL08X=y
-+CONFIG_DW_AXI_DMAC=y
-+CONFIG_DMATEST=y
-+# CONFIG_VIRTIO_MENU is not set
-+# CONFIG_VHOST_MENU is not set
-+CONFIG_GOLDFISH=y
-+CONFIG_CLK_STARFIVE_JH7110_AON=y
-+CONFIG_CLK_STARFIVE_JH7110_STG=y
-+CONFIG_CLK_STARFIVE_JH7110_ISP=y
-+CONFIG_CLK_STARFIVE_JH7110_VOUT=y
-+CONFIG_MAILBOX=y
-+CONFIG_STARFIVE_MBOX=m
-+CONFIG_STARFIVE_MBOX_TEST=m
-+# CONFIG_IOMMU_SUPPORT is not set
-+CONFIG_RPMSG_CHAR=y
-+CONFIG_RPMSG_VIRTIO=y
-+CONFIG_SIFIVE_CCACHE=y
-+CONFIG_PM_DEVFREQ=y
-+CONFIG_IIO=y
-+CONFIG_IIO_ST_ACCEL_3AXIS=y
-+CONFIG_PWM=y
-+CONFIG_PWM_OCORES=y
-+CONFIG_PHY_STARFIVE_JH7110_PCIE=y
-+CONFIG_PHY_STARFIVE_JH7110_USB=y
-+CONFIG_PHY_M31_DPHY_RX0=y
-+CONFIG_RAS=y
-+CONFIG_EXT4_FS=y
-+CONFIG_EXT4_FS_POSIX_ACL=y
-+CONFIG_BTRFS_FS=m
-+CONFIG_BTRFS_FS_POSIX_ACL=y
-+CONFIG_AUTOFS_FS=y
-+CONFIG_FUSE_FS=y
-+CONFIG_CUSE=y
-+CONFIG_VIRTIO_FS=y
-+CONFIG_FSCACHE=y
-+CONFIG_FSCACHE_STATS=y
-+CONFIG_MSDOS_FS=y
-+CONFIG_VFAT_FS=y
-+CONFIG_FAT_DEFAULT_UTF8=y
-+CONFIG_EXFAT_FS=y
-+CONFIG_NTFS_FS=y
-+CONFIG_NTFS_RW=y
-+CONFIG_TMPFS=y
-+CONFIG_TMPFS_POSIX_ACL=y
-+CONFIG_HUGETLBFS=y
-+CONFIG_JFFS2_FS=y
-+CONFIG_NFS_FS=y
-+CONFIG_NFS_V4=y
-+CONFIG_NFS_V4_1=y
-+CONFIG_NFS_V4_2=y
-+CONFIG_ROOT_NFS=y
-+CONFIG_CIFS=m
-+# CONFIG_CIFS_STATS2 is not set
-+CONFIG_CIFS_UPCALL=y
-+CONFIG_CIFS_XATTR=y
-+CONFIG_CIFS_POSIX=y
-+# CONFIG_CIFS_DEBUG is not set
-+CONFIG_CIFS_DFS_UPCALL=y
-+CONFIG_CIFS_FSCACHE=y
-+CONFIG_SMB_SERVER=m
-+CONFIG_NLS_CODEPAGE_437=y
-+CONFIG_NLS_ISO8859_1=y
-+CONFIG_INIT_STACK_NONE=y
-+CONFIG_CRYPTO_USER=y
-+CONFIG_CRYPTO_TEST=m
-+CONFIG_CRYPTO_USER_API_HASH=y
-+CONFIG_CRYPTO_USER_API_SKCIPHER=y
-+CONFIG_CRYPTO_USER_API_RNG=y
-+CONFIG_CRYPTO_USER_API_AEAD=y
-+CONFIG_CRYPTO_DEV_VIRTIO=y
-+CONFIG_CRYPTO_DEV_JH7110=y
-+CONFIG_DMA_CMA=y
-+CONFIG_PRINTK_TIME=y
-+CONFIG_DEBUG_FS=y
-+CONFIG_SOFTLOCKUP_DETECTOR=y
-+CONFIG_WQ_WATCHDOG=y
-+CONFIG_DEBUG_TIMEKEEPING=y
-+CONFIG_DEBUG_RT_MUTEXES=y
-+CONFIG_DEBUG_SPINLOCK=y
-+CONFIG_DEBUG_RWSEMS=y
-+CONFIG_DEBUG_LIST=y
-+CONFIG_DEBUG_PLIST=y
-+CONFIG_DEBUG_SG=y
-+# CONFIG_RCU_TRACE is not set
-+CONFIG_RCU_EQS_DEBUG=y
-+# CONFIG_FTRACE is not set
-+# CONFIG_RUNTIME_TESTING_MENU is not set
-+CONFIG_MEMTEST=y
diff --git a/target/linux/starfive/patches-6.6/0106-riscv-dts-starfive-update-dts-to-kernel-6.6.patch b/target/linux/starfive/patches-6.6/0106-riscv-dts-starfive-update-dts-to-kernel-6.6.patch
deleted file mode 100644 (file)
index defc0e6..0000000
+++ /dev/null
@@ -1,759 +0,0 @@
-From 51c1cccb202d741eeb1de57e0ecf8fcaa8f059e8 Mon Sep 17 00:00:00 2001
-From: Ziv Xu <ziv.xu@starfivetech.com>
-Date: Wed, 13 Mar 2024 18:36:31 +0800
-Subject: [PATCH 106/116] riscv: dts: starfive: update dts to kernel 6.6
-
-update dts to kernel 6.6
-
-Signed-off-by: Ziv Xu <ziv.xu@starfivetech.com>
----
- arch/riscv/boot/dts/starfive/Makefile         |   5 +-
- .../jh7110-starfive-visionfive-2-ac108.dts    |  64 +++
- .../jh7110-starfive-visionfive-2-tdm.dts      |  59 +++
- .../jh7110-starfive-visionfive-2-wm8960.dts   |  71 +++
- .../jh7110-starfive-visionfive-2.dtsi         | 437 +++++++++++++++++-
- 5 files changed, 633 insertions(+), 3 deletions(-)
- create mode 100644 arch/riscv/boot/dts/starfive/jh7110-starfive-visionfive-2-ac108.dts
- create mode 100644 arch/riscv/boot/dts/starfive/jh7110-starfive-visionfive-2-tdm.dts
- create mode 100644 arch/riscv/boot/dts/starfive/jh7110-starfive-visionfive-2-wm8960.dts
-
---- a/arch/riscv/boot/dts/starfive/Makefile
-+++ b/arch/riscv/boot/dts/starfive/Makefile
-@@ -10,7 +10,10 @@ dtb-$(CONFIG_ARCH_STARFIVE) += jh7100-be
- 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
-+dtb-$(CONFIG_ARCH_STARFIVE) += jh7110-starfive-visionfive-2-v1.3b.dtb \
-+                                              jh7110-starfive-visionfive-2-ac108.dtb  \
-+                                              jh7110-starfive-visionfive-2-tdm.dtb    \
-+                                              jh7110-starfive-visionfive-2-wm8960.dtb
- subdir-y += evb-overlay
- dtb-$(CONFIG_ARCH_STARFIVE) += jh7110-evb.dtb                 \
---- /dev/null
-+++ b/arch/riscv/boot/dts/starfive/jh7110-starfive-visionfive-2-ac108.dts
-@@ -0,0 +1,64 @@
-+// SPDX-License-Identifier: GPL-2.0 OR MIT
-+/*
-+ * Copyright (C) 2022 StarFive Technology Co., Ltd.
-+ * Copyright (C) 2022 Hal Feng <hal.feng@starfivetech.com>
-+ */
-+
-+/dts-v1/;
-+#include "jh7110-starfive-visionfive-2-v1.3b.dts"
-+
-+/ {
-+      /* i2s + ac108 */
-+      sound0: snd-card0 {
-+              compatible = "simple-audio-card";
-+              #address-cells = <1>;
-+              #size-cells = <0>;
-+
-+              simple-audio-card,name = "Starfive-AC108-Sound-Card";
-+              simple-audio-card,dai-link@0 {
-+                      reg = <0>;
-+                      format = "i2s";
-+                      bitclock-master = <&sndcodec1>;
-+                      frame-master = <&sndcodec1>;
-+
-+                      widgets =
-+                                      "Microphone", "Mic Jack",
-+                                      "Line", "Line In",
-+                                      "Line", "Line Out",
-+                                      "Speaker", "Speaker",
-+                                      "Headphone", "Headphone Jack";
-+                      routing =
-+                                      "Headphone Jack", "HP_L",
-+                                      "Headphone Jack", "HP_R",
-+                                      "Speaker", "SPK_LP",
-+                                      "Speaker", "SPK_LN",
-+                                      "LINPUT1", "Mic Jack",
-+                                      "LINPUT3", "Mic Jack",
-+                                      "RINPUT1", "Mic Jack",
-+                                      "RINPUT2", "Mic Jack";
-+
-+                      cpu {
-+                              sound-dai = <&i2srx_mst>;
-+                      };
-+
-+                      sndcodec1: codec {
-+                              sound-dai = <&ac108>;
-+                              clocks = <&ac108_mclk>;
-+                              clock-names = "mclk";
-+                      };
-+              };
-+      };
-+};
-+
-+&i2c0 {
-+      ac108: ac108@3b {
-+              compatible = "x-power,ac108_0";
-+              reg = <0x3b>;
-+              #sound-dai-cells = <0>;
-+              data-protocol = <0>;
-+      };
-+};
-+
-+&i2srx_mst {
-+      status = "okay";
-+};
---- /dev/null
-+++ b/arch/riscv/boot/dts/starfive/jh7110-starfive-visionfive-2-tdm.dts
-@@ -0,0 +1,59 @@
-+// SPDX-License-Identifier: GPL-2.0 OR MIT
-+/*
-+ * Copyright (C) 2022 StarFive Technology Co., Ltd.
-+ * Copyright (C) 2022 Hal Feng <hal.feng@starfivetech.com>
-+ */
-+
-+/dts-v1/;
-+#include "jh7110-starfive-visionfive-2-v1.3b.dts"
-+
-+/ {
-+      sound-tdm {
-+              compatible = "simple-audio-card";
-+              #address-cells = <1>;
-+              #size-cells = <0>;
-+
-+              simple-audio-card,name = "Starfive-TDM-Sound-Card";
-+              simple-audio-card,widgets = "Microphone", "Mic Jack",
-+                                          "Line", "Line In",
-+                                          "Line", "Line Out",
-+                                          "Speaker", "Speaker",
-+                                          "Headphone", "Headphone Jack";
-+              simple-audio-card,routing = "Headphone Jack", "HP_L",
-+                                          "Headphone Jack", "HP_R",
-+                                          "Speaker", "SPK_LP",
-+                                          "Speaker", "SPK_LN",
-+                                          "LINPUT1", "Mic Jack",
-+                                          "LINPUT3", "Mic Jack",
-+                                          "RINPUT1", "Mic Jack",
-+                                          "RINPUT2", "Mic Jack";
-+
-+              simple-audio-card,dai-link@0 {
-+                      reg = <0>;
-+                      format = "dsp_a";
-+                      bitclock-master = <&dailink_master>;
-+                      frame-master = <&dailink_master>;
-+
-+                      cpu {
-+                              sound-dai = <&tdm>;
-+                      };
-+                      dailink_master: codec {
-+                              sound-dai = <&wm8960>;
-+                              clocks = <&wm8960_mclk>;
-+                      };
-+              };
-+      };
-+};
-+
-+&i2c0 {
-+      wm8960: codec@1a {
-+              compatible = "wlf,wm8960";
-+              reg = <0x1a>;
-+              wlf,shared-lrclk;
-+              #sound-dai-cells = <0>;
-+      };
-+};
-+
-+&tdm {
-+      status = "okay";
-+};
---- /dev/null
-+++ b/arch/riscv/boot/dts/starfive/jh7110-starfive-visionfive-2-wm8960.dts
-@@ -0,0 +1,71 @@
-+// SPDX-License-Identifier: GPL-2.0 OR MIT
-+/*
-+ * Copyright (C) 2022 StarFive Technology Co., Ltd.
-+ * Copyright (C) 2022 Hal Feng <hal.feng@starfivetech.com>
-+ */
-+
-+/dts-v1/;
-+#include "jh7110-starfive-visionfive-2-v1.3b.dts"
-+
-+/ {
-+      /* i2s + wm8960 */
-+      sound-wm8960 {
-+              compatible = "simple-audio-card";
-+              #address-cells = <1>;
-+              #size-cells = <0>;
-+
-+              simple-audio-card,name = "Starfive-WM8960-Sound-Card";
-+              simple-audio-card,dai-link@0 {
-+                      reg = <0>;
-+                      status = "okay";
-+                      format = "i2s";
-+                      bitclock-master = <&sndcodec1>;
-+                      frame-master = <&sndcodec1>;
-+                      
-+                      widgets =
-+                                      "Microphone", "Mic Jack",
-+                                      "Line", "Line In",
-+                                      "Line", "Line Out",
-+                                      "Speaker", "Speaker",
-+                                      "Headphone", "Headphone Jack";
-+                      routing =
-+                                      "Headphone Jack", "HP_L",
-+                                      "Headphone Jack", "HP_R",
-+                                      "Speaker", "SPK_LP",
-+                                      "Speaker", "SPK_LN",
-+                                      "LINPUT1", "Mic Jack",
-+                                      "LINPUT3", "Mic Jack",
-+                                      "RINPUT1", "Mic Jack",
-+                                      "RINPUT2", "Mic Jack";
-+                      cpu0 {
-+                              sound-dai = <&i2srx>;
-+                      };
-+                      cpu1 {
-+                              sound-dai = <&i2stx1>;
-+                      };
-+                      
-+                      sndcodec1:codec {
-+                              sound-dai = <&wm8960>;
-+                              clocks = <&wm8960_mclk>;
-+                              clock-names = "mclk";
-+                      };
-+              };
-+      };
-+};
-+
-+&i2c0 {
-+      wm8960: codec@1a {
-+              compatible = "wlf,wm8960";
-+              reg = <0x1a>;
-+              wlf,shared-lrclk;
-+              #sound-dai-cells = <0>;
-+      };
-+};
-+
-+&i2srx {
-+      status = "okay";
-+};
-+
-+&i2stx1 {
-+      status = "okay";
-+};
---- a/arch/riscv/boot/dts/starfive/jh7110-starfive-visionfive-2.dtsi
-+++ b/arch/riscv/boot/dts/starfive/jh7110-starfive-visionfive-2.dtsi
-@@ -7,6 +7,7 @@
- /dts-v1/;
- #include "jh7110.dtsi"
- #include "jh7110-pinfunc.h"
-+#include <dt-bindings/leds/common.h>
- #include <dt-bindings/gpio/gpio.h>
- / {
-@@ -37,6 +38,44 @@
-               reg = <0x0 0x40000000 0x1 0x0>;
-       };
-+      reserved-memory {
-+              #address-cells = <2>;
-+              #size-cells = <2>;
-+              ranges;
-+
-+              linux,cma {
-+                      compatible = "shared-dma-pool";
-+                      reusable;
-+                      size = <0x0 0x20000000>;
-+                      alignment = <0x0 0x1000>;
-+                      alloc-ranges = <0x0 0x70000000 0x0 0x20000000>;
-+                      linux,cma-default;
-+              };
-+
-+              e24_mem: e24@c0000000 {
-+                      reg = <0x0 0x6ce00000 0x0 0x1600000>;
-+              };
-+
-+              xrp_reserved: xrpbuffer@f0000000 {
-+                      reg = <0x0 0x69c00000 0x0 0x01ffffff
-+                              0x0 0x6bc00000 0x0 0x00001000
-+                              0x0 0x6bc01000 0x0 0x00fff000
-+                              0x0 0x6cc00000 0x0 0x00001000>;
-+              };
-+      };
-+
-+      leds {
-+              compatible = "gpio-leds";
-+
-+              led-ack {
-+                      gpios = <&aongpio 3 GPIO_ACTIVE_HIGH>;
-+                      color = <LED_COLOR_ID_GREEN>;
-+                      function = LED_FUNCTION_HEARTBEAT;
-+                      linux,default-trigger = "heartbeat";
-+                      label = "ack";
-+              };
-+      };
-+
-       gpio-restart {
-               compatible = "gpio-restart";
-               gpios = <&sysgpio 35 GPIO_ACTIVE_HIGH>;
-@@ -69,6 +108,48 @@
-                       };
-               };
-       };
-+
-+      sound-hdmi {
-+              compatible = "simple-audio-card";
-+              #address-cells = <1>;
-+              #size-cells = <0>;
-+
-+              simple-audio-card,name = "StarFive-HDMI-Sound-Card";
-+              simple-audio-card,dai-link@0 {
-+                      reg = <0>;
-+                      format = "i2s";
-+                      bitclock-master = <&sndi2s0>;
-+                      frame-master = <&sndi2s0>;
-+                      mclk-fs = <256>;
-+                      status = "okay";
-+
-+                      sndi2s0: cpu {
-+                              sound-dai = <&i2stx0>;
-+                      };
-+
-+                      codec {
-+                              sound-dai = <&hdmi>;
-+                      };
-+              };
-+      };
-+
-+      ac108_mclk: ac108_mclk {
-+              compatible = "fixed-clock";
-+              #clock-cells = <0>;
-+              clock-frequency = <24000000>;
-+      };
-+
-+      clk_ext_camera: clk-ext-camera {
-+              compatible = "fixed-clock";
-+              #clock-cells = <0>;
-+              clock-frequency = <24000000>;
-+      };
-+
-+      wm8960_mclk: wm8960_mclk {
-+              compatible = "fixed-clock";
-+              #clock-cells = <0>;
-+              clock-frequency = <24576000>;
-+      };
- };
- &dvp_clk {
-@@ -177,6 +258,42 @@
-       pinctrl-names = "default";
-       pinctrl-0 = <&i2c2_pins>;
-       status = "okay";
-+
-+      seeed_plane_i2c@45 {
-+              compatible = "seeed_panel";
-+              reg = <0x45>;
-+
-+              port {
-+                      panel_out0: endpoint {
-+                              remote-endpoint = <&dsi0_output>;
-+                      };
-+              };
-+      };
-+
-+      tinker_ft5406: tinker_ft5406@38 {
-+              compatible = "tinker_ft5406";
-+              reg = <0x38>;
-+      };
-+
-+      touchscreen@14 {
-+              compatible = "goodix,gt911";
-+              reg = <0x14>;
-+              irq-gpios = <&sysgpio 30 GPIO_ACTIVE_HIGH>;
-+              reset-gpios = <&sysgpio 31 GPIO_ACTIVE_HIGH>;
-+      };
-+
-+      panel_radxa@19 {
-+              compatible ="starfive_jadard";
-+              reg = <0x19>;
-+              reset-gpio = <&sysgpio 23 0>;
-+              enable-gpio = <&sysgpio 22 0>;
-+
-+              port {
-+                      panel_out1: endpoint {
-+                              remote-endpoint = <&dsi1_output>;
-+                      };
-+              };
-+      };
- };
- &i2c5 {
-@@ -195,11 +312,36 @@
-               #interrupt-cells = <1>;
-               regulators {
-+                      mipi_0p9: ALDO1 {
-+                              regulator-boot-on;
-+                              regulator-compatible = "aldo1";
-+                              regulator-name = "mipi_0p9";
-+                              regulator-min-microvolt = <900000>;
-+                              regulator-max-microvolt = <900000>;
-+                      };
-+
-+                      hdmi_0p9: ALDO5 {
-+                              regulator-boot-on;
-+                              regulator-compatible = "aldo5";
-+                              regulator-name = "hdmi_0p9";
-+                              regulator-min-microvolt = <900000>;
-+                              regulator-max-microvolt = <900000>;
-+                      };
-+
-+                      hdmi_1p8: ALDO3 {
-+                              regulator-boot-on;
-+                              regulator-compatible = "aldo3";
-+                              regulator-name = "hdmi_1p8";
-+                              regulator-min-microvolt = <1800000>;
-+                              regulator-max-microvolt = <1800000>;
-+                      };
-+
-                       vcc_3v3: dcdc1 {
-                               regulator-boot-on;
-                               regulator-always-on;
-                               regulator-min-microvolt = <3300000>;
-                               regulator-max-microvolt = <3300000>;
-+                              regulator-compatible = "dcdc1";
-                               regulator-name = "vcc_3v3";
-                       };
-@@ -207,6 +349,7 @@
-                               regulator-always-on;
-                               regulator-min-microvolt = <500000>;
-                               regulator-max-microvolt = <1540000>;
-+                              regulator-compatible = "dcdc2";
-                               regulator-name = "vdd-cpu";
-                       };
-@@ -215,6 +358,7 @@
-                               regulator-always-on;
-                               regulator-min-microvolt = <1800000>;
-                               regulator-max-microvolt = <1800000>;
-+                              regulator-compatible = "aldo4";
-                               regulator-name = "emmc_vdd";
-                       };
-               };
-@@ -229,12 +373,68 @@
-       pinctrl-names = "default";
-       pinctrl-0 = <&i2c6_pins>;
-       status = "okay";
-+
-+      imx219: imx219@10 {
-+              compatible = "sony,imx219";
-+              reg = <0x10>;
-+              clocks = <&clk_ext_camera>;
-+              clock-names = "xclk";
-+              reset-gpio = <&sysgpio 18 0>;
-+              rotation = <0>;
-+              orientation = <1>; //CAMERA_ORIENTATION_BACK
-+
-+              port {
-+                      /* CSI2 bus endpoint */
-+                      imx219_to_csi2rx0: endpoint {
-+                              remote-endpoint = <&csi2rx0_from_imx219>;
-+                              bus-type = <4>;      /* MIPI CSI-2 D-PHY */
-+                              clock-lanes = <4>;
-+                              data-lanes = <0 1>;
-+                              lane-polarities = <0 0 0>;
-+                              link-frequencies = /bits/ 64 <456000000>;
-+                      };
-+              };
-+      };
-+
-+      imx708: imx708@1a {
-+              compatible = "sony,imx708";
-+              reg = <0x1a>;
-+              clocks = <&clk_ext_camera>;
-+              reset-gpio = <&sysgpio 18 0>;
-+
-+              port {
-+                      imx708_to_csi2rx0: endpoint {
-+                              remote-endpoint = <&csi2rx0_from_imx708>;
-+                              data-lanes = <1 2>;
-+                              clock-noncontinuous;
-+                              link-frequencies = /bits/ 64 <450000000>;
-+                      };
-+              };
-+      };
-+
-+      ov4689: ov4689@36 {
-+              compatible = "ovti,ov4689";
-+              reg = <0x36>;
-+              clocks = <&clk_ext_camera>;
-+              clock-names = "xclk";
-+              rotation = <180>;
-+
-+              port {
-+                      /* Parallel bus endpoint */
-+                      ov4689_to_csi2rx0: endpoint {
-+                              remote-endpoint = <&csi2rx0_from_ov4689>;
-+                              bus-type = <4>;         /* MIPI CSI-2 D-PHY */
-+                              clock-lanes = <0>;
-+                              data-lanes = <1 2>;
-+                      };
-+              };
-+      };
- };
- &i2srx {
-       pinctrl-names = "default";
-       pinctrl-0 = <&i2srx_pins>;
--      status = "okay";
-+      status = "disabled";
- };
- &i2stx0 {
-@@ -246,7 +446,7 @@
- &i2stx1 {
-       pinctrl-names = "default";
-       pinctrl-0 = <&i2stx1_pins>;
--      status = "okay";
-+      status = "disabled";
- };
- &mmc0 {
-@@ -661,6 +861,40 @@
-                       slew-rate = <0>;
-               };
-       };
-+
-+      hdmi_pins: hdmi-0 {
-+              scl-pins {
-+                      pinmux = <GPIOMUX(0, GPOUT_SYS_HDMI_DDC_SCL,
-+                                           GPOEN_SYS_HDMI_DDC_SCL,
-+                                           GPI_SYS_HDMI_DDC_SCL)>;
-+                      bias-pull-up;
-+                      input-enable;
-+              };
-+
-+              sda-pins {
-+                      pinmux = <GPIOMUX(1, GPOUT_SYS_HDMI_DDC_SDA,
-+                                           GPOEN_SYS_HDMI_DDC_SDA,
-+                                           GPI_SYS_HDMI_DDC_SDA)>;
-+                      bias-pull-up;
-+                      input-enable;
-+              };
-+
-+              cec-pins {
-+                      pinmux = <GPIOMUX(14, GPOUT_SYS_HDMI_CEC_SDA,
-+                                            GPOEN_SYS_HDMI_CEC_SDA,
-+                                            GPI_SYS_HDMI_CEC_SDA)>;
-+                      bias-pull-up;
-+                      input-enable;
-+              };
-+
-+              hpd-pins {
-+                      pinmux = <GPIOMUX(15, GPOUT_LOW,
-+                                            GPOEN_DISABLE,
-+                                            GPI_SYS_HDMI_HPD)>;
-+                      bias-disable; /* external pull-up */
-+                      input-enable;
-+              };
-+      };
- };
- &uart0 {
-@@ -689,3 +923,202 @@
- &U74_4 {
-       cpu-supply = <&vdd_cpu>;
- };
-+
-+
-+&display {
-+      ports = <&dc_out_dpi0>;
-+      status = "okay";
-+};
-+
-+&dc8200 {
-+      status = "okay";
-+
-+      dc_out: port {
-+              #address-cells = <1>;
-+              #size-cells = <0>;
-+              dc_out_dpi0: endpoint@0 {
-+                      reg = <0>;
-+                      remote-endpoint = <&hdmi_input0>;
-+              };
-+              dc_out_dpi1: endpoint@1 {
-+                      reg = <1>;
-+                      remote-endpoint = <&hdmi_in_lcdc>;
-+              };
-+
-+              dc_out_dpi2: endpoint@2 {
-+                      reg = <2>;
-+                      remote-endpoint = <&mipi_in>;
-+              };
-+      };
-+};
-+
-+&hdmi {
-+      status = "okay";
-+      pinctrl-names = "default";
-+      pinctrl-0 = <&hdmi_pins>;
-+      hpd-gpio = <&sysgpio 15 GPIO_ACTIVE_HIGH>;
-+
-+      hdmi_in: port {
-+              #address-cells = <1>;
-+              #size-cells = <0>;
-+              hdmi_in_lcdc: endpoint@0 {
-+                      reg = <0>;
-+                      remote-endpoint = <&dc_out_dpi1>;
-+              };
-+      };
-+};
-+
-+&rgb_output {
-+      status = "disabled";
-+
-+      ports {
-+              #address-cells = <1>;
-+              #size-cells = <0>;
-+              port@0 {
-+                      #address-cells = <1>;
-+                      #size-cells = <0>;
-+                      reg = <0>;
-+                      hdmi_input0:endpoint@0 {
-+                              reg = <0>;
-+                              remote-endpoint = <&dc_out_dpi0>;
-+                      };
-+              };
-+      };
-+};
-+
-+&dsi_output {
-+      status = "okay";
-+
-+      ports {
-+              #address-cells = <1>;
-+              #size-cells = <0>;
-+
-+              port@0 {
-+                      reg = <0>;
-+                      mipi_in: endpoint {
-+                              remote-endpoint = <&dc_out_dpi2>;
-+                      };
-+              };
-+
-+              port@1 {
-+                      reg = <1>;
-+                      sf_dpi_output: endpoint {
-+                              remote-endpoint = <&dsi_in_port>;
-+                      };
-+              };
-+      };
-+};
-+
-+&mipi_dsi {
-+      status = "okay";
-+
-+      ports {
-+              #address-cells = <1>;
-+              #size-cells = <0>;
-+
-+              port@0 {
-+                      reg = <0>;
-+                      #address-cells = <1>;
-+                      #size-cells = <0>;
-+
-+                      dsi0_output: endpoint@0 {
-+                              reg = <0>;
-+                              remote-endpoint = <&panel_out0>;
-+                      };
-+
-+                      dsi1_output: endpoint@1 {
-+                              reg = <1>;
-+                              remote-endpoint = <&panel_out1>;
-+                      };
-+
-+              };
-+
-+              port@1{
-+                      reg = <1>;
-+                      dsi_in_port: endpoint {
-+                              remote-endpoint = <&sf_dpi_output>;
-+                      };
-+              };
-+
-+      };
-+};
-+
-+&mipi_dphy {
-+      status = "okay";
-+};
-+
-+&co_process {
-+      memory-region = <&e24_mem>;
-+      status = "okay";
-+};
-+
-+
-+&mailbox_contrl0 {
-+      status = "okay";
-+};
-+
-+&mailbox_client0 {
-+      status = "okay";
-+};
-+
-+&vpu_dec {
-+      status = "okay";
-+};
-+
-+&vpu_enc {
-+      status = "okay";
-+};
-+
-+&jpu {
-+      status = "okay";
-+};
-+
-+&gpu {
-+      status = "okay";
-+};
-+
-+&vin_sysctl {
-+      /* when use dvp open this pinctrl*/
-+      status = "okay";
-+
-+      ports {
-+              #address-cells = <1>;
-+              #size-cells = <0>;
-+
-+              port@1 {
-+                      reg = <1>;
-+                      #address-cells = <1>;
-+                      #size-cells = <0>;
-+
-+                      /* CSI2 bus endpoint */
-+                      csi2rx0_from_imx219: endpoint@0 {
-+                              reg = <0>;
-+                              remote-endpoint = <&imx219_to_csi2rx0>;
-+                              bus-type = <4>;      /* MIPI CSI-2 D-PHY */
-+                              clock-lanes = <4>;
-+                              data-lanes = <0 1>;
-+                              lane-polarities = <0 0 0>;
-+                              status = "okay";
-+                      };
-+
-+                      csi2rx0_from_imx708: endpoint@1 {
-+                              reg = <1>;
-+                              remote-endpoint = <&imx708_to_csi2rx0>;
-+                              bus-type = <4>;      /* MIPI CSI-2 D-PHY */
-+                              clock-lanes = <4>;
-+                              data-lanes = <0 1>;
-+                              lane-polarities = <0 0 0>;
-+                              status = "okay";
-+                      };
-+
-+                      csi2rx0_from_ov4689: endpoint@2 {
-+                              reg = <2>;
-+                              remote-endpoint = <&ov4689_to_csi2rx0>;
-+                              bus-type = <4>;      /* MIPI CSI-2 D-PHY */
-+                              clock-lanes = <4>;
-+                              data-lanes = <0 1>;
-+                              status = "okay";
-+                      };
-+              };
-+      };
-+};
diff --git a/target/linux/starfive/patches-6.6/0107-riscv-dts-starfive-evb-overlay-Support-SPI-overlay.patch b/target/linux/starfive/patches-6.6/0107-riscv-dts-starfive-evb-overlay-Support-SPI-overlay.patch
deleted file mode 100644 (file)
index 8738831..0000000
+++ /dev/null
@@ -1,71 +0,0 @@
-From 17a781895079f8f9b2c089d13a1e4d9789e018c5 Mon Sep 17 00:00:00 2001
-From: Hal Feng <hal.feng@starfivetech.com>
-Date: Wed, 20 Mar 2024 17:36:14 +0800
-Subject: [PATCH 107/116] riscv: dts: starfive: evb-overlay: Support SPI
- overlay
-
-Add new compatibles to support SPI overlay.
-
-Signed-off-by: Hal Feng <hal.feng@starfivetech.com>
----
- .../dts/starfive/evb-overlay/jh7110-evb-overlay-spi.dtso   | 7 +++++++
- 1 file changed, 7 insertions(+)
-
---- a/arch/riscv/boot/dts/starfive/evb-overlay/jh7110-evb-overlay-spi.dtso
-+++ b/arch/riscv/boot/dts/starfive/evb-overlay/jh7110-evb-overlay-spi.dtso
-@@ -9,6 +9,7 @@
-       fragment@0 {
-               target-path = "/soc/spi@10060000";
-               __overlay__ {
-+                      compatible = "starfive,jh7110-spi-pl022";
-                       status = "okay";
-               };
-       };
-@@ -17,6 +18,7 @@
-       fragment@1 {
-               target-path = "/soc/spi@10070000";
-               __overlay__ {
-+                      compatible = "starfive,jh7110-spi-pl022";
-                       status = "okay";
-               };
-       };
-@@ -25,6 +27,7 @@
-       fragment@2 {
-               target-path = "/soc/spi@10080000";
-               __overlay__ {
-+                      compatible = "starfive,jh7110-spi-pl022";
-                       status = "okay";
-               };
-       };
-@@ -33,6 +36,7 @@
-       fragment@3 {
-               target-path = "/soc/spi@12070000";
-               __overlay__ {
-+                      compatible = "starfive,jh7110-spi-pl022";
-                       status = "okay";
-               };
-       };
-@@ -41,6 +45,7 @@
-       fragment@4 {
-               target-path = "/soc/spi@12080000";
-               __overlay__ {
-+                      compatible = "starfive,jh7110-spi-pl022";
-                       status = "okay";
-               };
-       };
-@@ -49,6 +54,7 @@
-       fragment@5 {
-               target-path = "/soc/spi@12090000";
-               __overlay__ {
-+                      compatible = "starfive,jh7110-spi-pl022";
-                       status = "okay";
-               };
-       };
-@@ -57,6 +63,7 @@
-       fragment@6 {
-               target-path = "/soc/spi@120a0000";
-               __overlay__ {
-+                      compatible = "starfive,jh7110-spi-pl022";
-                       status = "okay";
-               };
-       };
diff --git a/target/linux/starfive/patches-6.6/0108-riscv-configs-visionfive2-Add-standard-partition-for.patch b/target/linux/starfive/patches-6.6/0108-riscv-configs-visionfive2-Add-standard-partition-for.patch
deleted file mode 100644 (file)
index a4b2e14..0000000
+++ /dev/null
@@ -1,23 +0,0 @@
-From 49b818cdd08fca7ff761277635c0e5ab659becb8 Mon Sep 17 00:00:00 2001
-From: Hal Feng <hal.feng@starfivetech.com>
-Date: Thu, 21 Mar 2024 16:53:51 +0800
-Subject: [PATCH 108/116] riscv: configs: visionfive2: Add standard partition
- for hibernation
-
-Add CONFIG_PM_STD_PARTITION="PARTLABEL=hibernation".
-
-Signed-off-by: Hal Feng <hal.feng@starfivetech.com>
----
- arch/riscv/configs/starfive_visionfive2_defconfig | 1 +
- 1 file changed, 1 insertion(+)
-
---- a/arch/riscv/configs/starfive_visionfive2_defconfig
-+++ b/arch/riscv/configs/starfive_visionfive2_defconfig
-@@ -24,6 +24,7 @@ CONFIG_NONPORTABLE=y
- CONFIG_SMP=y
- CONFIG_HZ_100=y
- CONFIG_HIBERNATION=y
-+CONFIG_PM_STD_PARTITION="PARTLABEL=hibernation"
- CONFIG_PM_DEBUG=y
- CONFIG_PM_ADVANCED_DEBUG=y
- CONFIG_PM_TEST_SUSPEND=y
diff --git a/target/linux/starfive/patches-6.6/0109-usb-xhci-To-improve-performance-usb-using-lowmem-for.patch b/target/linux/starfive/patches-6.6/0109-usb-xhci-To-improve-performance-usb-using-lowmem-for.patch
deleted file mode 100644 (file)
index dff0c26..0000000
+++ /dev/null
@@ -1,297 +0,0 @@
-From 146eb94a08d12b5831e1d30455469750f7c5f2a3 Mon Sep 17 00:00:00 2001
-From: "minda.chen" <minda.chen@starfivetech.com>
-Date: Tue, 18 Oct 2022 09:57:39 +0800
-Subject: [PATCH 109/116] usb:xhci:To improve performance,usb using lowmem for
- bulk xfer.
-
-Generate an usb low memory pool for usb 3.0 host
-read/write transfer, default size is 8M.
-
-Signed-off-by: minda.chen <minda.chen@starfivetech.com>
----
- arch/riscv/boot/dts/starfive/jh7110-evb.dts |  1 +
- drivers/usb/core/hcd.c                      |  4 +-
- drivers/usb/host/xhci-mem.c                 | 64 +++++++++++++++++++++
- drivers/usb/host/xhci-plat.c                |  8 +++
- drivers/usb/host/xhci-ring.c                |  3 +-
- drivers/usb/host/xhci.c                     | 57 +++++++++++++++++-
- drivers/usb/host/xhci.h                     | 11 ++++
- 7 files changed, 145 insertions(+), 3 deletions(-)
-
---- a/arch/riscv/boot/dts/starfive/jh7110-evb.dts
-+++ b/arch/riscv/boot/dts/starfive/jh7110-evb.dts
-@@ -31,5 +31,6 @@
- };
- &usb0 {
-+      xhci-lowmem-pool;
-       status = "okay";
- };
---- a/drivers/usb/core/hcd.c
-+++ b/drivers/usb/core/hcd.c
-@@ -1439,7 +1439,9 @@ int usb_hcd_map_urb_for_dma(struct usb_h
-                       if (ret == 0)
-                               urb->transfer_flags |= URB_MAP_LOCAL;
-               } else if (hcd_uses_dma(hcd)) {
--                      if (urb->num_sgs) {
-+                      if (urb->transfer_flags & URB_MAP_LOCAL)
-+                              return ret;
-+                      else if (urb->num_sgs) {
-                               int n;
-                               /* We don't support sg for isoc transfers ! */
---- a/drivers/usb/host/xhci-mem.c
-+++ b/drivers/usb/host/xhci-mem.c
-@@ -14,6 +14,7 @@
- #include <linux/slab.h>
- #include <linux/dmapool.h>
- #include <linux/dma-mapping.h>
-+#include <linux/genalloc.h>
- #include "xhci.h"
- #include "xhci-trace.h"
-@@ -1878,6 +1879,7 @@ EXPORT_SYMBOL_GPL(xhci_remove_secondary_
- void xhci_mem_cleanup(struct xhci_hcd *xhci)
- {
-       struct device   *dev = xhci_to_hcd(xhci)->self.sysdev;
-+      struct xhci_lowmem_pool *pool;
-       int i, j, num_ports;
-       cancel_delayed_work_sync(&xhci->cmd_timer);
-@@ -1928,6 +1930,13 @@ void xhci_mem_cleanup(struct xhci_hcd *x
-       xhci_dbg_trace(xhci, trace_xhci_dbg_init,
-                       "Freed medium stream array pool");
-+      if (xhci->lowmem_pool.pool) {
-+              pool = &xhci->lowmem_pool;
-+              dma_free_coherent(dev, pool->size, (void *)pool->cached_base, pool->dma_addr);
-+              gen_pool_destroy(pool->pool);
-+              pool->pool = NULL;
-+      }
-+
-       if (xhci->dcbaa)
-               dma_free_coherent(dev, sizeof(*xhci->dcbaa),
-                               xhci->dcbaa, xhci->dcbaa->dma);
-@@ -2399,6 +2408,55 @@ xhci_create_secondary_interrupter(struct
- }
- EXPORT_SYMBOL_GPL(xhci_create_secondary_interrupter);
-+int xhci_setup_local_lowmem(struct xhci_hcd *xhci, size_t size)
-+{
-+      int err;
-+      void *buffer;
-+      dma_addr_t dma_addr;
-+      struct usb_hcd *hcd = xhci_to_hcd(xhci);
-+      struct xhci_lowmem_pool *pool = &xhci->lowmem_pool;
-+
-+      if (!pool->pool) {
-+              /* minimal alloc one page */
-+              pool->pool = gen_pool_create(PAGE_SHIFT, dev_to_node(hcd->self.sysdev));
-+              if (IS_ERR(pool->pool))
-+                      return PTR_ERR(pool->pool);
-+      }
-+
-+      buffer = dma_alloc_coherent(hcd->self.sysdev, size, &dma_addr,
-+                      GFP_KERNEL | GFP_DMA32);
-+
-+      if (IS_ERR(buffer)) {
-+              err = PTR_ERR(buffer);
-+              goto destroy_pool;
-+      }
-+
-+      /*
-+       * Here we pass a dma_addr_t but the arg type is a phys_addr_t.
-+       * It's not backed by system memory and thus there's no kernel mapping
-+       * for it.
-+       */
-+      err = gen_pool_add_virt(pool->pool, (unsigned long)buffer,
-+                              dma_addr, size, dev_to_node(hcd->self.sysdev));
-+      if (err < 0) {
-+              dev_err(hcd->self.sysdev, "gen_pool_add_virt failed with %d\n",
-+                      err);
-+              dma_free_coherent(hcd->self.sysdev, size, buffer, dma_addr);
-+              goto destroy_pool;
-+      }
-+
-+      pool->cached_base = (u64)buffer;
-+      pool->dma_addr = dma_addr;
-+
-+      return 0;
-+
-+destroy_pool:
-+      gen_pool_destroy(pool->pool);
-+      pool->pool = NULL;
-+      return err;
-+}
-+EXPORT_SYMBOL_GPL(xhci_setup_local_lowmem);
-+
- int xhci_mem_init(struct xhci_hcd *xhci, gfp_t flags)
- {
-       struct xhci_interrupter *ir;
-@@ -2540,6 +2598,12 @@ int xhci_mem_init(struct xhci_hcd *xhci,
-       xhci->isoc_bei_interval = AVOID_BEI_INTERVAL_MAX;
-+      if (xhci->quirks & XHCI_LOCAL_BUFFER) {
-+              if (xhci_setup_local_lowmem(xhci,
-+                      xhci->lowmem_pool.size))
-+                      goto fail;
-+      }
-+
-       /*
-        * XXX: Might need to set the Interrupter Moderation Register to
-        * something other than the default (~1ms minimum between interrupts).
---- a/drivers/usb/host/xhci-plat.c
-+++ b/drivers/usb/host/xhci-plat.c
-@@ -253,6 +253,14 @@ int xhci_plat_probe(struct platform_devi
-               if (device_property_read_bool(tmpdev, "xhci-sg-trb-cache-size-quirk"))
-                       xhci->quirks |= XHCI_SG_TRB_CACHE_SIZE_QUIRK;
-+              if (device_property_read_bool(tmpdev, "xhci-lowmem-pool")) {
-+                      xhci->quirks |= XHCI_LOCAL_BUFFER;
-+                      if (device_property_read_u32(tmpdev, "lowmem-pool-size",
-+                              &xhci->lowmem_pool.size)) {
-+                              xhci->lowmem_pool.size = 8 << 20;
-+                      } else
-+                              xhci->lowmem_pool.size <<= 20;
-+              }
-               device_property_read_u32(tmpdev, "imod-interval-ns",
-                                        &xhci->imod_interval);
-       }
---- a/drivers/usb/host/xhci-ring.c
-+++ b/drivers/usb/host/xhci-ring.c
-@@ -3721,7 +3721,8 @@ int xhci_queue_bulk_tx(struct xhci_hcd *
-       full_len = urb->transfer_buffer_length;
-       /* If we have scatter/gather list, we use it. */
--      if (urb->num_sgs && !(urb->transfer_flags & URB_DMA_MAP_SINGLE)) {
-+      if (urb->num_sgs && !(urb->transfer_flags & URB_DMA_MAP_SINGLE)
-+                      && !(urb->transfer_flags & URB_MAP_LOCAL)) {
-               num_sgs = urb->num_mapped_sgs;
-               sg = urb->sg;
-               addr = (u64) sg_dma_address(sg);
---- a/drivers/usb/host/xhci.c
-+++ b/drivers/usb/host/xhci.c
-@@ -19,6 +19,8 @@
- #include <linux/slab.h>
- #include <linux/dmi.h>
- #include <linux/dma-mapping.h>
-+#include <linux/dma-map-ops.h>
-+#include <linux/genalloc.h>
- #include "xhci.h"
- #include "xhci-trace.h"
-@@ -1312,6 +1314,55 @@ static void xhci_unmap_temp_buf(struct u
-       urb->transfer_buffer = NULL;
- }
-+static void xhci_map_urb_local(struct usb_hcd *hcd, struct urb *urb,
-+                              gfp_t mem_flags)
-+{
-+      void *buffer;
-+      dma_addr_t dma_handle;
-+      struct xhci_hcd *xhci = hcd_to_xhci(hcd);
-+      struct xhci_lowmem_pool *lowmem_pool = &xhci->lowmem_pool;
-+
-+      if (lowmem_pool->pool
-+              && (usb_endpoint_type(&urb->ep->desc) == USB_ENDPOINT_XFER_BULK)
-+              && (urb->transfer_buffer_length > PAGE_SIZE)
-+              && urb->num_sgs && urb->sg && (sg_phys(urb->sg) > 0xffffffff)) {
-+              buffer = gen_pool_dma_alloc(lowmem_pool->pool,
-+                      urb->transfer_buffer_length, &dma_handle);
-+              if (buffer) {
-+                      urb->transfer_dma = dma_handle;
-+                      urb->transfer_buffer = buffer;
-+                      urb->transfer_flags |= URB_MAP_LOCAL;
-+                      if (usb_urb_dir_out(urb))
-+                              sg_copy_to_buffer(urb->sg, urb->num_sgs,
-+                                      (void *)buffer,
-+                                      urb->transfer_buffer_length);
-+              }
-+      }
-+
-+}
-+
-+static void xhci_unmap_urb_local(struct usb_hcd *hcd, struct urb *urb)
-+{
-+      dma_addr_t dma_handle;
-+      u64 cached_buffer;
-+      struct xhci_hcd *xhci = hcd_to_xhci(hcd);
-+      struct xhci_lowmem_pool *lowmem_pool = &xhci->lowmem_pool;
-+
-+      if (urb->transfer_flags & URB_MAP_LOCAL) {
-+              dma_handle = urb->transfer_dma;
-+              cached_buffer = lowmem_pool->cached_base +
-+                      ((u32)urb->transfer_dma & (lowmem_pool->size - 1));
-+              if (usb_urb_dir_in(urb))
-+                      sg_copy_from_buffer(urb->sg, urb->num_sgs,
-+                              (void *)cached_buffer, urb->transfer_buffer_length);
-+              gen_pool_free(lowmem_pool->pool, (unsigned long)urb->transfer_buffer,
-+                              urb->transfer_buffer_length);
-+              urb->transfer_flags &= ~URB_MAP_LOCAL;
-+              urb->transfer_buffer = NULL;
-+      }
-+}
-+
-+
- /*
-  * Bypass the DMA mapping if URB is suitable for Immediate Transfer (IDT),
-  * we'll copy the actual data into the TRB address register. This is limited to
-@@ -1332,9 +1383,11 @@ static int xhci_map_urb_for_dma(struct u
-               if (xhci_urb_temp_buffer_required(hcd, urb))
-                       return xhci_map_temp_buffer(hcd, urb);
-       }
-+      xhci_map_urb_local(hcd, urb, mem_flags);
-       return usb_hcd_map_urb_for_dma(hcd, urb, mem_flags);
- }
-+
- static void xhci_unmap_urb_for_dma(struct usb_hcd *hcd, struct urb *urb)
- {
-       struct xhci_hcd *xhci;
-@@ -1347,8 +1400,10 @@ static void xhci_unmap_urb_for_dma(struc
-       if ((xhci->quirks & XHCI_SG_TRB_CACHE_SIZE_QUIRK) && unmap_temp_buf)
-               xhci_unmap_temp_buf(hcd, urb);
--      else
-+      else {
-+              xhci_unmap_urb_local(hcd, urb);
-               usb_hcd_unmap_urb_for_dma(hcd, urb);
-+      }
- }
- /**
---- a/drivers/usb/host/xhci.h
-+++ b/drivers/usb/host/xhci.h
-@@ -1506,6 +1506,13 @@ struct xhci_hub {
-       u8                      min_rev;
- };
-+struct xhci_lowmem_pool {
-+      struct gen_pool *pool;
-+      u64             cached_base;
-+      dma_addr_t      dma_addr;
-+      unsigned int    size;
-+};
-+
- /* There is one xhci_hcd structure per controller */
- struct xhci_hcd {
-       struct usb_hcd *main_hcd;
-@@ -1660,6 +1667,8 @@ struct xhci_hcd {
- #define XHCI_CDNS_SCTX_QUIRK  BIT_ULL(48)
- #define XHCI_ETRON_HOST       BIT_ULL(49)
-+#define XHCI_LOCAL_BUFFER     BIT_ULL(63)
-+
-       unsigned int            num_active_eps;
-       unsigned int            limit_active_eps;
-       struct xhci_port        *hw_ports;
-@@ -1689,6 +1698,8 @@ struct xhci_hcd {
-       struct list_head        regset_list;
-       void                    *dbc;
-+      struct xhci_lowmem_pool lowmem_pool;
-+
-       /* platform-specific data -- must come last */
-       unsigned long           priv[] __aligned(sizeof(s64));
- };
diff --git a/target/linux/starfive/patches-6.6/0110-usb-xhci-using-dma_alloc_noncoherent-to-alloc-low-me.patch b/target/linux/starfive/patches-6.6/0110-usb-xhci-using-dma_alloc_noncoherent-to-alloc-low-me.patch
deleted file mode 100644 (file)
index b955ba8..0000000
+++ /dev/null
@@ -1,106 +0,0 @@
-From a170cb9936bb0b00d58aaea40984dbce1169fe42 Mon Sep 17 00:00:00 2001
-From: Minda Chen <minda.chen@starfivetech.com>
-Date: Mon, 3 Jul 2023 16:14:20 +0800
-Subject: [PATCH 110/116] usb: xhci: using dma_alloc_noncoherent to alloc low
- memory pool
-
-For RISCV_NONCACHEHERENT is set, using dma_alloc_noncoherent
-to alloc cached large block low memory buffer. And set default
-size to 4M. (largest size of continuous memory can be supported)
-
-Signed-off-by: Minda Chen <minda.chen@starfivetech.com>
----
- drivers/usb/host/xhci-mem.c  | 29 ++++++++++++++++-------------
- drivers/usb/host/xhci-plat.c |  9 +++++----
- 2 files changed, 21 insertions(+), 17 deletions(-)
-
---- a/drivers/usb/host/xhci-mem.c
-+++ b/drivers/usb/host/xhci-mem.c
-@@ -1932,7 +1932,8 @@ void xhci_mem_cleanup(struct xhci_hcd *x
-       if (xhci->lowmem_pool.pool) {
-               pool = &xhci->lowmem_pool;
--              dma_free_coherent(dev, pool->size, (void *)pool->cached_base, pool->dma_addr);
-+              dma_free_noncoherent(dev, pool->size, (void *)pool->cached_base,
-+                                   pool->dma_addr, DMA_BIDIRECTIONAL);
-               gen_pool_destroy(pool->pool);
-               pool->pool = NULL;
-       }
-@@ -2419,15 +2420,15 @@ int xhci_setup_local_lowmem(struct xhci_
-       if (!pool->pool) {
-               /* minimal alloc one page */
-               pool->pool = gen_pool_create(PAGE_SHIFT, dev_to_node(hcd->self.sysdev));
--              if (IS_ERR(pool->pool))
--                      return PTR_ERR(pool->pool);
-+              if (!pool->pool)
-+                      return -ENOMEM;
-       }
--      buffer = dma_alloc_coherent(hcd->self.sysdev, size, &dma_addr,
--                      GFP_KERNEL | GFP_DMA32);
-+      buffer = dma_alloc_noncoherent(hcd->self.sysdev, size, &dma_addr,
-+              DMA_BIDIRECTIONAL, GFP_ATOMIC);
--      if (IS_ERR(buffer)) {
--              err = PTR_ERR(buffer);
-+      if (!buffer) {
-+              err = -ENOMEM;
-               goto destroy_pool;
-       }
-@@ -2437,11 +2438,11 @@ int xhci_setup_local_lowmem(struct xhci_
-        * for it.
-        */
-       err = gen_pool_add_virt(pool->pool, (unsigned long)buffer,
--                              dma_addr, size, dev_to_node(hcd->self.sysdev));
-+              dma_addr, size, dev_to_node(hcd->self.sysdev));
-       if (err < 0) {
-               dev_err(hcd->self.sysdev, "gen_pool_add_virt failed with %d\n",
-                       err);
--              dma_free_coherent(hcd->self.sysdev, size, buffer, dma_addr);
-+              dma_free_noncoherent(hcd->self.sysdev, size, buffer, dma_addr, DMA_BIDIRECTIONAL);
-               goto destroy_pool;
-       }
-@@ -2465,7 +2466,7 @@ int xhci_mem_init(struct xhci_hcd *xhci,
-       unsigned int    val, val2;
-       u64             val_64;
-       u32             page_size, temp;
--      int             i;
-+      int             i, ret;
-       INIT_LIST_HEAD(&xhci->cmd_list);
-@@ -2599,9 +2600,11 @@ int xhci_mem_init(struct xhci_hcd *xhci,
-       xhci->isoc_bei_interval = AVOID_BEI_INTERVAL_MAX;
-       if (xhci->quirks & XHCI_LOCAL_BUFFER) {
--              if (xhci_setup_local_lowmem(xhci,
--                      xhci->lowmem_pool.size))
--                      goto fail;
-+              ret = xhci_setup_local_lowmem(xhci, xhci->lowmem_pool.size);
-+              if (ret) {
-+                      xhci->quirks &= ~XHCI_LOCAL_BUFFER;
-+                      xhci_warn(xhci, "WARN: Can't alloc lowmem pool\n");
-+              }
-       }
-       /*
---- a/drivers/usb/host/xhci-plat.c
-+++ b/drivers/usb/host/xhci-plat.c
-@@ -255,10 +255,11 @@ int xhci_plat_probe(struct platform_devi
-               if (device_property_read_bool(tmpdev, "xhci-lowmem-pool")) {
-                       xhci->quirks |= XHCI_LOCAL_BUFFER;
--                      if (device_property_read_u32(tmpdev, "lowmem-pool-size",
--                              &xhci->lowmem_pool.size)) {
--                              xhci->lowmem_pool.size = 8 << 20;
--                      } else
-+                      ret = device_property_read_u32(tmpdev, "lowmem-pool-size",
-+                              &xhci->lowmem_pool.size);
-+                      if (ret || xhci->lowmem_pool.size >= 4)
-+                              xhci->lowmem_pool.size = 4 << 20;
-+                      else
-                               xhci->lowmem_pool.size <<= 20;
-               }
-               device_property_read_u32(tmpdev, "imod-interval-ns",
diff --git a/target/linux/starfive/patches-6.6/0111-riscv-dts-starfive-Add-vf2-overlay-dtso-subdir.patch b/target/linux/starfive/patches-6.6/0111-riscv-dts-starfive-Add-vf2-overlay-dtso-subdir.patch
deleted file mode 100644 (file)
index 451b1c1..0000000
+++ /dev/null
@@ -1,139 +0,0 @@
-From fc86405992c37b1898fd9b9bc077be673d774269 Mon Sep 17 00:00:00 2001
-From: Hal Feng <hal.feng@starfivetech.com>
-Date: Fri, 22 Mar 2024 09:54:28 +0800
-Subject: [PATCH 111/116] riscv: dts: starfive: Add vf2-overlay dtso subdir
-
-Create subdir vf2-overlay/ and add overlay .dtso for VF2 board.
-The code is ported from tag JH7110_VF2_6.1_v5.11.4
-
-Signed-off-by: Hal Feng <hal.feng@starfivetech.com>
----
- arch/riscv/boot/dts/starfive/Makefile         |  1 +
- .../boot/dts/starfive/vf2-overlay/Makefile    |  3 +
- .../starfive/vf2-overlay/vf2-overlay-can.dtso | 23 ++++++
- .../vf2-overlay/vf2-overlay-uart3-i2c.dtso    | 75 +++++++++++++++++++
- 4 files changed, 102 insertions(+)
- create mode 100644 arch/riscv/boot/dts/starfive/vf2-overlay/Makefile
- create mode 100644 arch/riscv/boot/dts/starfive/vf2-overlay/vf2-overlay-can.dtso
- create mode 100644 arch/riscv/boot/dts/starfive/vf2-overlay/vf2-overlay-uart3-i2c.dtso
-
---- a/arch/riscv/boot/dts/starfive/Makefile
-+++ b/arch/riscv/boot/dts/starfive/Makefile
-@@ -9,6 +9,7 @@ DTC_FLAGS_jh7110-evb := -@
- dtb-$(CONFIG_ARCH_STARFIVE) += jh7100-beaglev-starlight.dtb
- dtb-$(CONFIG_ARCH_STARFIVE) += jh7100-starfive-visionfive-v1.dtb
-+subdir-y += vf2-overlay
- dtb-$(CONFIG_ARCH_STARFIVE) += jh7110-starfive-visionfive-2-v1.2a.dtb
- dtb-$(CONFIG_ARCH_STARFIVE) += jh7110-starfive-visionfive-2-v1.3b.dtb \
-                                               jh7110-starfive-visionfive-2-ac108.dtb  \
---- /dev/null
-+++ b/arch/riscv/boot/dts/starfive/vf2-overlay/Makefile
-@@ -0,0 +1,3 @@
-+# SPDX-License-Identifier: GPL-2.0
-+dtb-$(CONFIG_ARCH_STARFIVE) += vf2-overlay-uart3-i2c.dtbo     \
-+                             vf2-overlay-can.dtbo
---- /dev/null
-+++ b/arch/riscv/boot/dts/starfive/vf2-overlay/vf2-overlay-can.dtso
-@@ -0,0 +1,23 @@
-+/dts-v1/;
-+/plugin/;
-+#include <dt-bindings/gpio/gpio.h>
-+#include "../jh7110-pinfunc.h"
-+/ {
-+      compatible = "starfive,jh7110";
-+
-+      //can0
-+      fragment@0 {
-+              target-path = "/soc/can@130d0000";
-+              __overlay__ {
-+                      status = "okay";
-+              };
-+      };
-+
-+      //can1
-+      fragment@1 {
-+              target-path = "/soc/can@130e0000";
-+              __overlay__ {
-+                      status = "okay";
-+              };
-+      };
-+};
---- /dev/null
-+++ b/arch/riscv/boot/dts/starfive/vf2-overlay/vf2-overlay-uart3-i2c.dtso
-@@ -0,0 +1,75 @@
-+/dts-v1/;
-+/plugin/;
-+#include <dt-bindings/gpio/gpio.h>
-+#include "../jh7110-pinfunc.h"
-+/ {
-+      compatible = "starfive,jh7110";
-+
-+      //sysgpio
-+      fragment@0 {
-+              target-path = "/soc/pinctrl@13040000";
-+              __overlay__ {
-+                      dt_uart3_pins: dt-uart3-0 {
-+                              tx-pins {
-+                                      pinmux = <GPIOMUX(60, GPOUT_SYS_UART3_TX,
-+                                                            GPOEN_ENABLE,
-+                                                            GPI_NONE)>;
-+                                      bias-disable;
-+                                      drive-strength = <12>;
-+                                      input-disable;
-+                                      input-schmitt-disable;
-+                                      slew-rate = <0>;
-+                              };
-+
-+                              rx-pins {
-+                                      pinmux = <GPIOMUX(63, GPOUT_LOW,
-+                                                            GPOEN_DISABLE,
-+                                                            GPI_SYS_UART3_RX)>;
-+                                      bias-pull-up;
-+                                      drive-strength = <2>;
-+                                      input-enable;
-+                                      input-schmitt-enable;
-+                                      slew-rate = <0>;
-+                              };
-+                      };
-+
-+                      dt_i2c1_pins: dt-i2c1-0 {
-+                              i2c-pins {
-+                                      pinmux = <GPIOMUX(42, GPOUT_LOW,
-+                                                            GPOEN_SYS_I2C1_CLK,
-+                                                            GPI_SYS_I2C1_CLK)>,
-+                                               <GPIOMUX(43, GPOUT_LOW,
-+                                                            GPOEN_SYS_I2C1_DATA,
-+                                                            GPI_SYS_I2C1_DATA)>;
-+                                      bias-pull-up;
-+                                      input-enable;
-+                                      input-schmitt-enable;
-+                              };
-+                      };
-+              };
-+      };
-+
-+      //uart3
-+      fragment@1 {
-+              target-path = "/soc/serial@12000000";
-+              __overlay__ {
-+                      pinctrl-names = "default";
-+                      pinctrl-0 = <&dt_uart3_pins>;
-+                      status = "okay";
-+              };
-+      };
-+
-+      //i2c1
-+      fragment@2 {
-+              target-path = "/soc/i2c@10040000";
-+              __overlay__ {
-+                      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 = <&dt_i2c1_pins>;
-+                      status = "okay";
-+              };
-+      };
-+};
diff --git a/target/linux/starfive/patches-6.6/0112-riscv-dts-starfive-visionfive-2-Add-aliases-for-i2c-.patch b/target/linux/starfive/patches-6.6/0112-riscv-dts-starfive-visionfive-2-Add-aliases-for-i2c-.patch
deleted file mode 100644 (file)
index 17dcf72..0000000
+++ /dev/null
@@ -1,34 +0,0 @@
-From 2b098da69f9497e725683caf67fbecf79202b7fc Mon Sep 17 00:00:00 2001
-From: Hal Feng <hal.feng@starfivetech.com>
-Date: Fri, 22 Mar 2024 11:33:40 +0800
-Subject: [PATCH 112/116] riscv: dts: starfive: visionfive 2: Add aliases for
- i2c* and uart3
-
-Fix the numbers of i2c and uart3.
-
-Signed-off-by: Hal Feng <hal.feng@starfivetech.com>
----
- .../riscv/boot/dts/starfive/jh7110-starfive-visionfive-2.dtsi | 4 ++++
- 1 file changed, 4 insertions(+)
-
---- a/arch/riscv/boot/dts/starfive/jh7110-starfive-visionfive-2.dtsi
-+++ b/arch/riscv/boot/dts/starfive/jh7110-starfive-visionfive-2.dtsi
-@@ -15,7 +15,10 @@
-               ethernet0 = &gmac0;
-               ethernet1 = &gmac1;
-               i2c0 = &i2c0;
-+              i2c1 = &i2c1;
-               i2c2 = &i2c2;
-+              i2c3 = &i2c3;
-+              i2c4 = &i2c4;
-               i2c5 = &i2c5;
-               i2c6 = &i2c6;
-               mmc0 = &mmc0;
-@@ -23,6 +26,7 @@
-               pcie0 = &pcie0;
-               pcie1 = &pcie1;
-               serial0 = &uart0;
-+              serial3 = &uart3;
-       };
-       chosen {
diff --git a/target/linux/starfive/patches-6.6/0114-riscv-dts-starfive-visionfive-2-Sync-the-sound-card-.patch b/target/linux/starfive/patches-6.6/0114-riscv-dts-starfive-visionfive-2-Sync-the-sound-card-.patch
deleted file mode 100644 (file)
index c599a44..0000000
+++ /dev/null
@@ -1,67 +0,0 @@
-From fdb2822982887c7048f34601688ae2406ccbcfcc Mon Sep 17 00:00:00 2001
-From: Hal Feng <hal.feng@starfivetech.com>
-Date: Mon, 15 Apr 2024 11:29:17 +0800
-Subject: [PATCH 114/116] riscv: dts: starfive: visionfive 2: Sync the sound
- card names with v5.15 and v6.1
-
-Sync the sound card names. So we can build Debian images with the
-same process.
-
-Signed-off-by: Hal Feng <hal.feng@starfivetech.com>
----
- .../dts/starfive/jh7110-starfive-visionfive-2-tdm.dts     | 2 +-
- .../dts/starfive/jh7110-starfive-visionfive-2-wm8960.dts  | 2 +-
- .../boot/dts/starfive/jh7110-starfive-visionfive-2.dtsi   | 8 ++++----
- 3 files changed, 6 insertions(+), 6 deletions(-)
-
---- a/arch/riscv/boot/dts/starfive/jh7110-starfive-visionfive-2-tdm.dts
-+++ b/arch/riscv/boot/dts/starfive/jh7110-starfive-visionfive-2-tdm.dts
-@@ -8,7 +8,7 @@
- #include "jh7110-starfive-visionfive-2-v1.3b.dts"
- / {
--      sound-tdm {
-+      sound5: snd-card5 {
-               compatible = "simple-audio-card";
-               #address-cells = <1>;
-               #size-cells = <0>;
---- a/arch/riscv/boot/dts/starfive/jh7110-starfive-visionfive-2-wm8960.dts
-+++ b/arch/riscv/boot/dts/starfive/jh7110-starfive-visionfive-2-wm8960.dts
-@@ -9,7 +9,7 @@
- / {
-       /* i2s + wm8960 */
--      sound-wm8960 {
-+      sound6: snd-card6 {
-               compatible = "simple-audio-card";
-               #address-cells = <1>;
-               #size-cells = <0>;
---- a/arch/riscv/boot/dts/starfive/jh7110-starfive-visionfive-2.dtsi
-+++ b/arch/riscv/boot/dts/starfive/jh7110-starfive-visionfive-2.dtsi
-@@ -91,9 +91,9 @@
-               #sound-dai-cells = <0>;
-       };
--      sound-pwmdac {
-+      sound3: snd-card3 {
-               compatible = "simple-audio-card";
--              simple-audio-card,name = "StarFive-PWMDAC-Sound-Card";
-+              simple-audio-card,name = "Starfive-PWMDAC-Sound-Card";
-               #address-cells = <1>;
-               #size-cells = <0>;
-@@ -113,12 +113,12 @@
-               };
-       };
--      sound-hdmi {
-+      sound1: snd-card1 {
-               compatible = "simple-audio-card";
-               #address-cells = <1>;
-               #size-cells = <0>;
--              simple-audio-card,name = "StarFive-HDMI-Sound-Card";
-+              simple-audio-card,name = "Starfive-HDMI-Sound-Card";
-               simple-audio-card,dai-link@0 {
-                       reg = <0>;
-                       format = "i2s";
diff --git a/target/linux/starfive/patches-6.6/0115-clk-starfive-jh7110-Change-uart3-uart5-clk-register-.patch b/target/linux/starfive/patches-6.6/0115-clk-starfive-jh7110-Change-uart3-uart5-clk-register-.patch
deleted file mode 100644 (file)
index 6b34f0e..0000000
+++ /dev/null
@@ -1,53 +0,0 @@
-From dac6f3021895e7678552789edff22f1dc909e274 Mon Sep 17 00:00:00 2001
-From: Hal Feng <hal.feng@starfivetech.com>
-Date: Mon, 15 Apr 2024 20:59:35 +0800
-Subject: [PATCH 115/116] clk: starfive: jh7110: Change uart3-uart5 clk
- register info
-
-The core_clk division register of uart3-uart5 include fractional and
-integral parts, but now only use the integral part, so include shift
-operation. The integral part include 8 bit, so the max value can be
-configed is 255.
-
-Signed-off-by: Yanhong Wang <yanhong.wang@starfivetech.com>
-Signed-off-by: Hal Feng <hal.feng@starfivetech.com>
----
- drivers/clk/starfive/clk-starfive-jh71x0.c | 13 +++++++++++++
- 1 file changed, 13 insertions(+)
-
---- a/drivers/clk/starfive/clk-starfive-jh71x0.c
-+++ b/drivers/clk/starfive/clk-starfive-jh71x0.c
-@@ -10,6 +10,8 @@
- #include <linux/device.h>
- #include <linux/io.h>
-+#include <dt-bindings/clock/starfive,jh7110-crg.h>
-+
- #include "clk-starfive-jh71x0.h"
- static struct jh71x0_clk *jh71x0_clk_from(struct clk_hw *hw)
-@@ -70,6 +72,11 @@ static unsigned long jh71x0_clk_recalc_r
-       struct jh71x0_clk *clk = jh71x0_clk_from(hw);
-       u32 div = jh71x0_clk_reg_get(clk) & JH71X0_CLK_DIV_MASK;
-+      if (clk->idx == JH7110_SYSCLK_UART3_CORE ||
-+          clk->idx == JH7110_SYSCLK_UART4_CORE ||
-+          clk->idx == JH7110_SYSCLK_UART5_CORE)
-+              div >>= 8;
-+
-       return div ? parent_rate / div : 0;
- }
-@@ -110,6 +117,12 @@ static int jh71x0_clk_set_rate(struct cl
-       unsigned long div = clamp(DIV_ROUND_CLOSEST(parent_rate, rate),
-                                 1UL, (unsigned long)clk->max_div);
-+      /* UART3-5: [15:8]: integer part of the divisor. [7:0] fraction part of the divisor */
-+      if (clk->idx == JH7110_SYSCLK_UART3_CORE ||
-+          clk->idx == JH7110_SYSCLK_UART4_CORE ||
-+          clk->idx == JH7110_SYSCLK_UART5_CORE)
-+              div <<= 8;
-+
-       jh71x0_clk_reg_rmw(clk, JH71X0_CLK_DIV_MASK, div);
-       return 0;
- }
diff --git a/target/linux/starfive/patches-6.6/0116-riscv-dts-starfive-visionfive-2-Quote-corresponding-.patch b/target/linux/starfive/patches-6.6/0116-riscv-dts-starfive-visionfive-2-Quote-corresponding-.patch
deleted file mode 100644 (file)
index 659c442..0000000
+++ /dev/null
@@ -1,32 +0,0 @@
-From 1ea169bb83d3b556eb9054f1a3e8ce0411370293 Mon Sep 17 00:00:00 2001
-From: Hal Feng <hal.feng@starfivetech.com>
-Date: Wed, 24 Apr 2024 14:23:07 +0800
-Subject: [PATCH 116/116] riscv: dts: starfive: visionfive 2: Quote
- corresponding regulators in hdmi and vin
-
-So PMIC can start to work before HDMI and VIN.
-
-Signed-off-by: Hal Feng <hal.feng@starfivetech.com>
----
- arch/riscv/boot/dts/starfive/jh7110-starfive-visionfive-2.dtsi | 3 +++
- 1 file changed, 3 insertions(+)
-
---- a/arch/riscv/boot/dts/starfive/jh7110-starfive-visionfive-2.dtsi
-+++ b/arch/riscv/boot/dts/starfive/jh7110-starfive-visionfive-2.dtsi
-@@ -961,6 +961,8 @@
-       pinctrl-names = "default";
-       pinctrl-0 = <&hdmi_pins>;
-       hpd-gpio = <&sysgpio 15 GPIO_ACTIVE_HIGH>;
-+      hdmi_0p9-supply = <&hdmi_0p9>;
-+      hdmi_1p8-supply = <&hdmi_1p8>;
-       hdmi_in: port {
-               #address-cells = <1>;
-@@ -1084,6 +1086,7 @@
- &vin_sysctl {
-       /* when use dvp open this pinctrl*/
-       status = "okay";
-+      mipi_0p9-supply = <&mipi_0p9>;
-       ports {
-               #address-cells = <1>;
diff --git a/target/linux/starfive/patches-6.6/1000-serial-8250_dw-Add-starfive-jh7100-hsuart-compatible.patch b/target/linux/starfive/patches-6.6/1000-serial-8250_dw-Add-starfive-jh7100-hsuart-compatible.patch
deleted file mode 100644 (file)
index a094e4b..0000000
+++ /dev/null
@@ -1,25 +0,0 @@
-From b7b4fad8784d7ab4fcd929a56c3e5366046fe7fc Mon Sep 17 00:00:00 2001
-From: Emil Renner Berthing <kernel@esmil.dk>
-Date: Thu, 14 Oct 2021 20:56:54 +0200
-Subject: [PATCH 1000/1024] serial: 8250_dw: Add starfive,jh7100-hsuart
- compatible
-
-This adds a compatible for the high speed UARTs on the StarFive JH7100
-RISC-V SoC. Just like the regular uarts we also need to keep the input
-clocks at their default rate and rely only on the divisor in the UART.
-
-Signed-off-by: Emil Renner Berthing <kernel@esmil.dk>
----
- drivers/tty/serial/8250/8250_dw.c | 1 +
- 1 file changed, 1 insertion(+)
-
---- a/drivers/tty/serial/8250/8250_dw.c
-+++ b/drivers/tty/serial/8250/8250_dw.c
-@@ -803,6 +803,7 @@ static const struct of_device_id dw8250_
-       { .compatible = "marvell,armada-38x-uart", .data = &dw8250_armada_38x_data },
-       { .compatible = "renesas,rzn1-uart", .data = &dw8250_renesas_rzn1_data },
-       { .compatible = "sophgo,sg2044-uart", .data = &dw8250_skip_set_rate_data },
-+      { .compatible = "starfive,jh7100-hsuart", .data = &dw8250_skip_set_rate_data },
-       { .compatible = "starfive,jh7100-uart", .data = &dw8250_skip_set_rate_data },
-       { /* Sentinel */ }
- };
diff --git a/target/linux/starfive/patches-6.6/1001-RISC-V-Add-StarFive-JH7100-audio-clock-node.patch b/target/linux/starfive/patches-6.6/1001-RISC-V-Add-StarFive-JH7100-audio-clock-node.patch
deleted file mode 100644 (file)
index 4cfa2a1..0000000
+++ /dev/null
@@ -1,32 +0,0 @@
-From 3051ab0102aaf969dd85f07b6ab731dadf97ef6c Mon Sep 17 00:00:00 2001
-From: Emil Renner Berthing <kernel@esmil.dk>
-Date: Sat, 20 Nov 2021 17:13:22 +0100
-Subject: [PATCH 1001/1024] RISC-V: Add StarFive JH7100 audio clock node
-
-Add device tree node for the audio clocks on the StarFive JH7100 RISC-V
-SoC.
-
-Signed-off-by: Emil Renner Berthing <kernel@esmil.dk>
----
- arch/riscv/boot/dts/starfive/jh7100.dtsi | 10 ++++++++++
- 1 file changed, 10 insertions(+)
-
---- a/arch/riscv/boot/dts/starfive/jh7100.dtsi
-+++ b/arch/riscv/boot/dts/starfive/jh7100.dtsi
-@@ -158,6 +158,16 @@
-                       riscv,ndev = <133>;
-               };
-+              audclk: clock-controller@10480000 {
-+                      compatible = "starfive,jh7100-audclk";
-+                      reg = <0x0 0x10480000 0x0 0x10000>;
-+                      clocks = <&clkgen JH7100_CLK_AUDIO_SRC>,
-+                               <&clkgen JH7100_CLK_AUDIO_12288>,
-+                               <&clkgen JH7100_CLK_DOM7AHB_BUS>;
-+                      clock-names = "audio_src", "audio_12288", "dom7ahb_bus";
-+                      #clock-cells = <1>;
-+              };
-+
-               clkgen: clock-controller@11800000 {
-                       compatible = "starfive,jh7100-clkgen";
-                       reg = <0x0 0x11800000 0x0 0x10000>;
diff --git a/target/linux/starfive/patches-6.6/1002-drivers-tty-serial-8250-update-driver-for-JH7100.patch b/target/linux/starfive/patches-6.6/1002-drivers-tty-serial-8250-update-driver-for-JH7100.patch
deleted file mode 100644 (file)
index 73d25f5..0000000
+++ /dev/null
@@ -1,28 +0,0 @@
-From 8ef30667e97363ca921416a60e50eb28bf88cc4f Mon Sep 17 00:00:00 2001
-From: Samin Guo <samin.guo@starfivetech.com>
-Date: Fri, 8 Jan 2021 03:11:04 +0800
-Subject: [PATCH 1002/1024] drivers/tty/serial/8250: update driver for JH7100
-
----
- drivers/tty/serial/8250/8250_port.c | 8 ++++++++
- 1 file changed, 8 insertions(+)
-
---- a/drivers/tty/serial/8250/8250_port.c
-+++ b/drivers/tty/serial/8250/8250_port.c
-@@ -72,8 +72,16 @@ static const struct serial8250_config ua
-       },
-       [PORT_16550] = {
-               .name           = "16550",
-+#ifdef CONFIG_SOC_STARFIVE
-+              .fifo_size      = 16,
-+              .tx_loadsz      = 16,
-+              .fcr            = UART_FCR_ENABLE_FIFO | UART_FCR_R_TRIG_00,
-+              .rxtrig_bytes   = {1, 4, 8, 14},
-+              .flags          = UART_CAP_FIFO,
-+#else
-               .fifo_size      = 1,
-               .tx_loadsz      = 1,
-+#endif
-       },
-       [PORT_16550A] = {
-               .name           = "16550A",
diff --git a/target/linux/starfive/patches-6.6/1003-dmaengine-dw-axi-dmac-Handle-xfer-start-while-non-id.patch b/target/linux/starfive/patches-6.6/1003-dmaengine-dw-axi-dmac-Handle-xfer-start-while-non-id.patch
deleted file mode 100644 (file)
index d0c692e..0000000
+++ /dev/null
@@ -1,55 +0,0 @@
-From 2d5b71006c6a93e26eb86b7efd37440c020bab46 Mon Sep 17 00:00:00 2001
-From: Samin Guo <samin.guo@starfivetech.com>
-Date: Wed, 17 Nov 2021 14:50:45 +0800
-Subject: [PATCH 1003/1024] dmaengine: dw-axi-dmac: Handle xfer start while
- non-idle
-
-Signed-off-by: Samin Guo <samin.guo@starfivetech.com>
-Signed-off-by: Curry Zhang <curry.zhang@starfivetech.com>
----
- drivers/dma/dw-axi-dmac/dw-axi-dmac-platform.c | 12 +++++++++++-
- drivers/dma/dw-axi-dmac/dw-axi-dmac.h          |  1 +
- 2 files changed, 12 insertions(+), 1 deletion(-)
-
---- a/drivers/dma/dw-axi-dmac/dw-axi-dmac-platform.c
-+++ b/drivers/dma/dw-axi-dmac/dw-axi-dmac-platform.c
-@@ -382,11 +382,13 @@ static void axi_chan_block_xfer_start(st
-       u32 irq_mask;
-       u8 lms = 0; /* Select AXI0 master for LLI fetching */
-+      chan->is_err = false;
-       if (unlikely(axi_chan_is_hw_enable(chan))) {
-               dev_err(chan2dev(chan), "%s is non-idle!\n",
-                       axi_chan_name(chan));
--              return;
-+              axi_chan_disable(chan);
-+              chan->is_err = true;
-       }
-       axi_dma_enable(chan->chip);
-@@ -1028,6 +1030,14 @@ static noinline void axi_chan_handle_err
-                       axi_chan_name(chan));
-               goto out;
-       }
-+      if (chan->is_err) {
-+              struct axi_dma_desc *desc = vd_to_axi_desc(vd);
-+
-+              axi_chan_block_xfer_start(chan, desc);
-+              chan->is_err = false;
-+              goto out;
-+      }
-+
-       /* Remove the completed descriptor from issued list */
-       list_del(&vd->node);
---- a/drivers/dma/dw-axi-dmac/dw-axi-dmac.h
-+++ b/drivers/dma/dw-axi-dmac/dw-axi-dmac.h
-@@ -50,6 +50,7 @@ struct axi_dma_chan {
-       struct dma_slave_config         config;
-       enum dma_transfer_direction     direction;
-       bool                            cyclic;
-+      bool                            is_err;
-       /* these other elements are all protected by vc.lock */
-       bool                            is_paused;
- };
diff --git a/target/linux/starfive/patches-6.6/1004-dmaengine-dw-axi-dmac-Add-StarFive-JH7100-support.patch b/target/linux/starfive/patches-6.6/1004-dmaengine-dw-axi-dmac-Add-StarFive-JH7100-support.patch
deleted file mode 100644 (file)
index 74a05cf..0000000
+++ /dev/null
@@ -1,64 +0,0 @@
-From 933f8c33d466de20e9894ef8de5b6afe478a420d Mon Sep 17 00:00:00 2001
-From: Samin Guo <samin.guo@starfivetech.com>
-Date: Wed, 17 Nov 2021 14:50:45 +0800
-Subject: [PATCH 1004/1024] dmaengine: dw-axi-dmac: Add StarFive JH7100 support
-
-Signed-off-by: Samin Guo <samin.guo@starfivetech.com>
-Signed-off-by: Emil Renner Berthing <kernel@esmil.dk>
----
- drivers/dma/dw-axi-dmac/dw-axi-dmac-platform.c | 12 ++++++++++++
- drivers/dma/dw-axi-dmac/dw-axi-dmac.h          |  4 ++++
- 2 files changed, 16 insertions(+)
-
---- a/drivers/dma/dw-axi-dmac/dw-axi-dmac-platform.c
-+++ b/drivers/dma/dw-axi-dmac/dw-axi-dmac-platform.c
-@@ -677,8 +677,13 @@ static int dw_axi_dma_set_hw_desc(struct
-       hw_desc->lli->block_ts_lo = cpu_to_le32(block_ts - 1);
-+#ifdef CONFIG_SOC_STARFIVE
-+      ctllo |= DWAXIDMAC_BURST_TRANS_LEN_16 << CH_CTL_L_DST_MSIZE_POS |
-+               DWAXIDMAC_BURST_TRANS_LEN_16 << CH_CTL_L_SRC_MSIZE_POS;
-+#else
-       ctllo |= DWAXIDMAC_BURST_TRANS_LEN_4 << CH_CTL_L_DST_MSIZE_POS |
-                DWAXIDMAC_BURST_TRANS_LEN_4 << CH_CTL_L_SRC_MSIZE_POS;
-+#endif
-       hw_desc->lli->ctl_lo = cpu_to_le32(ctllo);
-       set_desc_src_master(hw_desc);
-@@ -1502,7 +1507,11 @@ static int dw_probe(struct platform_devi
-        * Therefore, set constraint to 1024 * 4.
-        */
-       dw->dma.dev->dma_parms = &dw->dma_parms;
-+#ifdef CONFIG_SOC_STARFIVE
-+      dma_set_max_seg_size(&pdev->dev, DMAC_MAX_BLK_SIZE);
-+#else
-       dma_set_max_seg_size(&pdev->dev, MAX_BLOCK_SIZE);
-+#endif
-       platform_set_drvdata(pdev, chip);
-       pm_runtime_enable(chip->dev);
-@@ -1587,6 +1596,9 @@ static const struct of_device_id dw_dma_
-               .compatible = "intel,kmb-axi-dma",
-               .data = (void *)AXI_DMA_FLAG_HAS_APB_REGS,
-       }, {
-+              .compatible = "starfive,jh7100-axi-dma",
-+              .data = (void *)(AXI_DMA_FLAG_HAS_RESETS | AXI_DMA_FLAG_USE_CFG2),
-+      }, {
-               .compatible = "starfive,jh7110-axi-dma",
-               .data = (void *)(AXI_DMA_FLAG_HAS_RESETS | AXI_DMA_FLAG_USE_CFG2),
-       },
---- a/drivers/dma/dw-axi-dmac/dw-axi-dmac.h
-+++ b/drivers/dma/dw-axi-dmac/dw-axi-dmac.h
-@@ -284,7 +284,11 @@ enum {
- #define CH_CTL_L_SRC_MAST             BIT(0)
- /* CH_CFG_H */
-+#ifdef CONFIG_SOC_STARFIVE
-+#define CH_CFG_H_PRIORITY_POS         15
-+#else
- #define CH_CFG_H_PRIORITY_POS         17
-+#endif
- #define CH_CFG_H_DST_PER_POS          12
- #define CH_CFG_H_SRC_PER_POS          7
- #define CH_CFG_H_HS_SEL_DST_POS               4
diff --git a/target/linux/starfive/patches-6.6/1005-pinctrl-starfive-Reset-pinmux-settings.patch b/target/linux/starfive/patches-6.6/1005-pinctrl-starfive-Reset-pinmux-settings.patch
deleted file mode 100644 (file)
index 63a7a0c..0000000
+++ /dev/null
@@ -1,127 +0,0 @@
-From c5019bf73d1e178beb6055cca254e7d3c916db7c Mon Sep 17 00:00:00 2001
-From: Emil Renner Berthing <kernel@esmil.dk>
-Date: Sat, 17 Jul 2021 21:50:38 +0200
-Subject: [PATCH 1005/1024] pinctrl: starfive: Reset pinmux settings
-
-Current u-boot doesn't seem to take into account that some GPIOs are
-configured as inputs/outputs of certain peripherals on power-up. This
-means it ends up configuring some GPIOs as inputs to more than one
-peripheral which the documentation explicitly says is illegal. Similarly
-it also ends up configuring more than one GPIO as output of the same
-peripheral. While not explicitly mentioned by the documentation this
-also seems like a bad idea.
-
-The easiest way to remedy this mess is to just disconnect all GPIOs from
-peripherals and have our pinmux configuration set everything up
-properly. This, however, means that we'd disconnect the serial console
-from its pins for a while, so add a device tree property to keep
-certain GPIOs from being reset.
-
-Signed-off-by: Emil Renner Berthing <kernel@esmil.dk>
----
- .../pinctrl/starfive,jh7100-pinctrl.yaml      |  4 ++
- .../starfive/pinctrl-starfive-jh7100.c        | 66 +++++++++++++++++++
- 2 files changed, 70 insertions(+)
-
---- a/Documentation/devicetree/bindings/pinctrl/starfive,jh7100-pinctrl.yaml
-+++ b/Documentation/devicetree/bindings/pinctrl/starfive,jh7100-pinctrl.yaml
-@@ -88,6 +88,10 @@ properties:
-     $ref: /schemas/types.yaml#/definitions/uint32
-     enum: [0, 1, 2, 3, 4, 5, 6]
-+  starfive,keep-gpiomux:
-+    description: Keep pinmux for these GPIOs from being reset at boot.
-+    $ref: /schemas/types.yaml#/definitions/uint32-array
-+
- required:
-   - compatible
-   - reg
---- a/drivers/pinctrl/starfive/pinctrl-starfive-jh7100.c
-+++ b/drivers/pinctrl/starfive/pinctrl-starfive-jh7100.c
-@@ -203,6 +203,10 @@ static u16 starfive_drive_strength_from_
-       return (clamp(i, 14U, 63U) - 14) / 7;
- }
-+static bool keepmux;
-+module_param(keepmux, bool, 0644);
-+MODULE_PARM_DESC(keepmux, "Keep pinmux settings from previous boot stage");
-+
- struct starfive_pinctrl {
-       struct gpio_chip gc;
-       struct pinctrl_gpio_range gpios;
-@@ -1225,6 +1229,65 @@ static void starfive_disable_clock(void
-       clk_disable_unprepare(data);
- }
-+#define GPI_END (GPI_USB_OVER_CURRENT + 1)
-+static void starfive_pinmux_reset(struct starfive_pinctrl *sfp)
-+{
-+      static const DECLARE_BITMAP(defaults, GPI_END) = {
-+              BIT_MASK(GPI_I2C0_PAD_SCK_IN) |
-+              BIT_MASK(GPI_I2C0_PAD_SDA_IN) |
-+              BIT_MASK(GPI_I2C1_PAD_SCK_IN) |
-+              BIT_MASK(GPI_I2C1_PAD_SDA_IN) |
-+              BIT_MASK(GPI_I2C2_PAD_SCK_IN) |
-+              BIT_MASK(GPI_I2C2_PAD_SDA_IN) |
-+              BIT_MASK(GPI_I2C3_PAD_SCK_IN) |
-+              BIT_MASK(GPI_I2C3_PAD_SDA_IN) |
-+              BIT_MASK(GPI_SDIO0_PAD_CARD_DETECT_N) |
-+
-+              BIT_MASK(GPI_SDIO1_PAD_CARD_DETECT_N) |
-+              BIT_MASK(GPI_SPI0_PAD_SS_IN_N) |
-+              BIT_MASK(GPI_SPI1_PAD_SS_IN_N) |
-+              BIT_MASK(GPI_SPI2_PAD_SS_IN_N) |
-+              BIT_MASK(GPI_SPI2AHB_PAD_SS_N) |
-+              BIT_MASK(GPI_SPI3_PAD_SS_IN_N),
-+
-+              BIT_MASK(GPI_UART0_PAD_SIN) |
-+              BIT_MASK(GPI_UART1_PAD_SIN) |
-+              BIT_MASK(GPI_UART2_PAD_SIN) |
-+              BIT_MASK(GPI_UART3_PAD_SIN) |
-+              BIT_MASK(GPI_USB_OVER_CURRENT)
-+      };
-+      DECLARE_BITMAP(keep, NR_GPIOS) = {};
-+      struct device_node *np = sfp->gc.parent->of_node;
-+      int len = of_property_count_u32_elems(np, "starfive,keep-gpiomux");
-+      int i;
-+
-+      for (i = 0; i < len; i++) {
-+              u32 gpio;
-+
-+              of_property_read_u32_index(np, "starfive,keep-gpiomux", i, &gpio);
-+              if (gpio < NR_GPIOS)
-+                      set_bit(gpio, keep);
-+      }
-+
-+      for (i = 0; i < NR_GPIOS; i++) {
-+              if (test_bit(i, keep))
-+                      continue;
-+
-+              writel_relaxed(GPO_DISABLE, sfp->base + GPON_DOEN_CFG + 8 * i);
-+              writel_relaxed(GPO_LOW,     sfp->base + GPON_DOUT_CFG + 8 * i);
-+      }
-+
-+      for (i = 0; i < GPI_END; i++) {
-+              void __iomem *reg = sfp->base + GPI_CFG_OFFSET + 4 * i;
-+              u32 din = readl_relaxed(reg);
-+
-+              if (din >= 2 && din < (NR_GPIOS + 2) && test_bit(din - 2, keep))
-+                      continue;
-+
-+              writel_relaxed(test_bit(i, defaults), reg);
-+      }
-+}
-+
- static int starfive_probe(struct platform_device *pdev)
- {
-       struct device *dev = &pdev->dev;
-@@ -1286,6 +1349,9 @@ static int starfive_probe(struct platfor
-               writel(value, sfp->padctl + IO_PADSHARE_SEL);
-       }
-+      if (!keepmux)
-+              starfive_pinmux_reset(sfp);
-+
-       value = readl(sfp->padctl + IO_PADSHARE_SEL);
-       switch (value) {
-       case 0:
diff --git a/target/linux/starfive/patches-6.6/1006-clk-starfive-Add-flags-argument-to-JH71X0__MUX-macro.patch b/target/linux/starfive/patches-6.6/1006-clk-starfive-Add-flags-argument-to-JH71X0__MUX-macro.patch
deleted file mode 100644 (file)
index a6a1bb8..0000000
+++ /dev/null
@@ -1,302 +0,0 @@
-From a4a2a8886c97e14643fe3e0ab8cf67a75c1bf14d Mon Sep 17 00:00:00 2001
-From: Emil Renner Berthing <emil.renner.berthing@canonical.com>
-Date: Sat, 25 Mar 2023 22:57:06 +0100
-Subject: [PATCH 1006/1024] clk: starfive: Add flags argument to JH71X0__MUX
- macro
-
-This flag is needed to add the CLK_SET_RATE_PARENT flag on the gmac_tx
-clock on the JH7100, which in turn is needed by the dwmac-starfive
-driver to set the clock properly for 1000, 100 and 10 Mbps links.
-
-This change was mostly made using coccinelle:
-
-@ match @
-expression idx, name, nparents;
-@@
- JH71X0__MUX(
--idx, name, nparents,
-+idx, name, 0, nparents,
- ...)
-
-Signed-off-by: Emil Renner Berthing <emil.renner.berthing@canonical.com>
----
- .../clk/starfive/clk-starfive-jh7100-audio.c  |  2 +-
- drivers/clk/starfive/clk-starfive-jh7100.c    | 32 +++++++++----------
- .../clk/starfive/clk-starfive-jh7110-aon.c    |  6 ++--
- .../clk/starfive/clk-starfive-jh7110-isp.c    |  2 +-
- .../clk/starfive/clk-starfive-jh7110-sys.c    | 26 +++++++--------
- drivers/clk/starfive/clk-starfive-jh71x0.h    |  4 +--
- 6 files changed, 36 insertions(+), 36 deletions(-)
-
---- a/drivers/clk/starfive/clk-starfive-jh7100-audio.c
-+++ b/drivers/clk/starfive/clk-starfive-jh7100-audio.c
-@@ -79,7 +79,7 @@ static const struct jh71x0_clk_data jh71
-       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,
-+      JH71X0__MUX(JH7100_AUDCLK_VAD_MEM, "vad_mem", 0, 2,
-                   JH7100_AUDCLK_VAD_INTMEM,
-                   JH7100_AUDCLK_AUDIO_12288),
- };
---- a/drivers/clk/starfive/clk-starfive-jh7100.c
-+++ b/drivers/clk/starfive/clk-starfive-jh7100.c
-@@ -24,48 +24,48 @@
- #define JH7100_CLK_GMAC_GR_MII_RX     (JH7100_CLK_END + 3)
- static const struct jh71x0_clk_data jh7100_clk_data[] __initconst = {
--      JH71X0__MUX(JH7100_CLK_CPUNDBUS_ROOT, "cpundbus_root", 4,
-+      JH71X0__MUX(JH7100_CLK_CPUNDBUS_ROOT, "cpundbus_root", 0, 4,
-                   JH7100_CLK_OSC_SYS,
-                   JH7100_CLK_PLL0_OUT,
-                   JH7100_CLK_PLL1_OUT,
-                   JH7100_CLK_PLL2_OUT),
--      JH71X0__MUX(JH7100_CLK_DLA_ROOT, "dla_root", 3,
-+      JH71X0__MUX(JH7100_CLK_DLA_ROOT, "dla_root", 0, 3,
-                   JH7100_CLK_OSC_SYS,
-                   JH7100_CLK_PLL1_OUT,
-                   JH7100_CLK_PLL2_OUT),
--      JH71X0__MUX(JH7100_CLK_DSP_ROOT, "dsp_root", 4,
-+      JH71X0__MUX(JH7100_CLK_DSP_ROOT, "dsp_root", 0, 4,
-                   JH7100_CLK_OSC_SYS,
-                   JH7100_CLK_PLL0_OUT,
-                   JH7100_CLK_PLL1_OUT,
-                   JH7100_CLK_PLL2_OUT),
--      JH71X0__MUX(JH7100_CLK_GMACUSB_ROOT, "gmacusb_root", 3,
-+      JH71X0__MUX(JH7100_CLK_GMACUSB_ROOT, "gmacusb_root", 0, 3,
-                   JH7100_CLK_OSC_SYS,
-                   JH7100_CLK_PLL0_OUT,
-                   JH7100_CLK_PLL2_OUT),
--      JH71X0__MUX(JH7100_CLK_PERH0_ROOT, "perh0_root", 2,
-+      JH71X0__MUX(JH7100_CLK_PERH0_ROOT, "perh0_root", 0, 2,
-                   JH7100_CLK_OSC_SYS,
-                   JH7100_CLK_PLL0_OUT),
--      JH71X0__MUX(JH7100_CLK_PERH1_ROOT, "perh1_root", 2,
-+      JH71X0__MUX(JH7100_CLK_PERH1_ROOT, "perh1_root", 0, 2,
-                   JH7100_CLK_OSC_SYS,
-                   JH7100_CLK_PLL2_OUT),
--      JH71X0__MUX(JH7100_CLK_VIN_ROOT, "vin_root", 3,
-+      JH71X0__MUX(JH7100_CLK_VIN_ROOT, "vin_root", 0, 3,
-                   JH7100_CLK_OSC_SYS,
-                   JH7100_CLK_PLL1_OUT,
-                   JH7100_CLK_PLL2_OUT),
--      JH71X0__MUX(JH7100_CLK_VOUT_ROOT, "vout_root", 3,
-+      JH71X0__MUX(JH7100_CLK_VOUT_ROOT, "vout_root", 0, 3,
-                   JH7100_CLK_OSC_AUD,
-                   JH7100_CLK_PLL0_OUT,
-                   JH7100_CLK_PLL2_OUT),
-       JH71X0_GDIV(JH7100_CLK_AUDIO_ROOT, "audio_root", 0, 8, JH7100_CLK_PLL0_OUT),
--      JH71X0__MUX(JH7100_CLK_CDECHIFI4_ROOT, "cdechifi4_root", 3,
-+      JH71X0__MUX(JH7100_CLK_CDECHIFI4_ROOT, "cdechifi4_root", 0, 3,
-                   JH7100_CLK_OSC_SYS,
-                   JH7100_CLK_PLL1_OUT,
-                   JH7100_CLK_PLL2_OUT),
--      JH71X0__MUX(JH7100_CLK_CDEC_ROOT, "cdec_root", 3,
-+      JH71X0__MUX(JH7100_CLK_CDEC_ROOT, "cdec_root", 0, 3,
-                   JH7100_CLK_OSC_SYS,
-                   JH7100_CLK_PLL0_OUT,
-                   JH7100_CLK_PLL1_OUT),
--      JH71X0__MUX(JH7100_CLK_VOUTBUS_ROOT, "voutbus_root", 3,
-+      JH71X0__MUX(JH7100_CLK_VOUTBUS_ROOT, "voutbus_root", 0, 3,
-                   JH7100_CLK_OSC_AUD,
-                   JH7100_CLK_PLL0_OUT,
-                   JH7100_CLK_PLL2_OUT),
-@@ -76,7 +76,7 @@ static const struct jh71x0_clk_data jh71
-       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,
-+      JH71X0__MUX(JH7100_CLK_PLL2_REF, "pll2_refclk", 0, 2,
-                   JH7100_CLK_OSC_SYS,
-                   JH7100_CLK_OSC_AUD),
-       JH71X0__DIV(JH7100_CLK_CPU_CORE, "cpu_core", 8, JH7100_CLK_CPUNBUS_ROOT_DIV),
-@@ -142,7 +142,7 @@ static const struct jh71x0_clk_data jh71
-       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,
-+      JH71X0__MUX(JH7100_CLK_NNE_BUS, "nne_bus", 0, 2,
-                   JH7100_CLK_CPU_AXI,
-                   JH7100_CLK_NNEBUS_SRC1),
-       JH71X0_GATE(JH7100_CLK_NNE_AXI, "nne_axi", 0, JH7100_CLK_NNE_BUS),
-@@ -166,7 +166,7 @@ static const struct jh71x0_clk_data jh71
-       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,
-+      JH71X0__MUX(JH7100_CLK_USBPHY_25M, "usbphy_25m", 0, 2,
-                   JH7100_CLK_OSC_SYS,
-                   JH7100_CLK_USBPHY_PLLDIV25M),
-       JH71X0_FDIV(JH7100_CLK_AUDIO_DIV, "audio_div", JH7100_CLK_AUDIO_ROOT),
-@@ -200,12 +200,12 @@ static const struct jh71x0_clk_data jh71
-       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,
-+      JH71X0__MUX(JH7100_CLK_GMAC_TX, "gmac_tx", 0, 3,
-                   JH7100_CLK_GMAC_GTX,
-                   JH7100_CLK_GMAC_TX_INV,
-                   JH7100_CLK_GMAC_RMII_TX),
-       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,
-+      JH71X0__MUX(JH7100_CLK_GMAC_RX_PRE, "gmac_rx_pre", 0, 2,
-                   JH7100_CLK_GMAC_GR_MII_RX,
-                   JH7100_CLK_GMAC_RMII_RX),
-       JH71X0__INV(JH7100_CLK_GMAC_RX_INV, "gmac_rx_inv", JH7100_CLK_GMAC_RX_PRE),
---- a/drivers/clk/starfive/clk-starfive-jh7110-aon.c
-+++ b/drivers/clk/starfive/clk-starfive-jh7110-aon.c
-@@ -26,7 +26,7 @@
- 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,
-+      JH71X0__MUX(JH7110_AONCLK_APB_FUNC, "apb_func", 0, 2,
-                   JH7110_AONCLK_OSC_DIV4,
-                   JH7110_AONCLK_OSC),
-       /* gmac0 */
-@@ -39,7 +39,7 @@ static const struct jh71x0_clk_data jh71
-                   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,
-+      JH71X0__MUX(JH7110_AONCLK_GMAC0_RX, "gmac0_rx", 0, 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),
-@@ -48,7 +48,7 @@ static const struct jh71x0_clk_data jh71
-       /* 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,
-+      JH71X0__MUX(JH7110_AONCLK_RTC_32K, "rtc_32k", 0, 2,
-                   JH7110_AONCLK_RTC_OSC,
-                   JH7110_AONCLK_RTC_INTERNAL),
-       JH71X0_GATE(JH7110_AONCLK_RTC_CAL, "rtc_cal", 0, JH7110_AONCLK_OSC),
---- a/drivers/clk/starfive/clk-starfive-jh7110-isp.c
-+++ b/drivers/clk/starfive/clk-starfive-jh7110-isp.c
-@@ -53,7 +53,7 @@ static const struct jh71x0_clk_data jh71
-                   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,
-+      JH71X0__MUX(JH7110_ISPCLK_VIN_P_AXI_WR, "vin_p_axi_wr", 0, 2,
-                   JH7110_ISPCLK_MIPI_RX0_PXL,
-                   JH7110_ISPCLK_DVP_INV),
-       /* ispv2_top_wrapper */
---- a/drivers/clk/starfive/clk-starfive-jh7110-sys.c
-+++ b/drivers/clk/starfive/clk-starfive-jh7110-sys.c
-@@ -36,18 +36,18 @@
- static const struct jh71x0_clk_data jh7110_sysclk_data[] __initconst = {
-       /* root */
--      JH71X0__MUX(JH7110_SYSCLK_CPU_ROOT, "cpu_root", 2,
-+      JH71X0__MUX(JH7110_SYSCLK_CPU_ROOT, "cpu_root", 0, 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,
-+      JH71X0__MUX(JH7110_SYSCLK_GPU_ROOT, "gpu_root", 0, 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,
-+      JH71X0__MUX(JH7110_SYSCLK_BUS_ROOT, "bus_root", 0, 2,
-                   JH7110_SYSCLK_OSC,
-                   JH7110_SYSCLK_PLL2_OUT),
-       JH71X0__DIV(JH7110_SYSCLK_NOCSTG_BUS, "nocstg_bus", 3, JH7110_SYSCLK_BUS_ROOT),
-@@ -62,7 +62,7 @@ static const struct jh71x0_clk_data jh71
-       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,
-+      JH71X0__MUX(JH7110_SYSCLK_MCLK, "mclk", 0, 2,
-                   JH7110_SYSCLK_MCLK_INNER,
-                   JH7110_SYSCLK_MCLK_EXT),
-       JH71X0_GATE(JH7110_SYSCLK_MCLK_OUT, "mclk_out", 0, JH7110_SYSCLK_MCLK_INNER),
-@@ -96,7 +96,7 @@ static const struct jh71x0_clk_data jh71
-       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,
-+      JH71X0__MUX(JH7110_SYSCLK_DDR_BUS, "ddr_bus", 0, 4,
-                   JH7110_SYSCLK_OSC_DIV2,
-                   JH7110_SYSCLK_PLL1_DIV2,
-                   JH7110_SYSCLK_PLL1_DIV4,
-@@ -186,7 +186,7 @@ static const struct jh71x0_clk_data jh71
-       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,
-+      JH71X0__MUX(JH7110_SYSCLK_GMAC1_RX, "gmac1_rx", 0, 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),
-@@ -270,11 +270,11 @@ static const struct jh71x0_clk_data jh71
-       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,
-+      JH71X0__MUX(JH7110_SYSCLK_I2STX0_BCLK, "i2stx0_bclk", 0, 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,
-+      JH71X0__MUX(JH7110_SYSCLK_I2STX0_LRCK, "i2stx0_lrck", 0, 2,
-                   JH7110_SYSCLK_I2STX0_LRCK_MST,
-                   JH7110_SYSCLK_I2STX_LRCK_EXT),
-       /* i2stx1 */
-@@ -285,11 +285,11 @@ static const struct jh71x0_clk_data jh71
-       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,
-+      JH71X0__MUX(JH7110_SYSCLK_I2STX1_BCLK, "i2stx1_bclk", 0, 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,
-+      JH71X0__MUX(JH7110_SYSCLK_I2STX1_LRCK, "i2stx1_lrck", 0, 2,
-                   JH7110_SYSCLK_I2STX1_LRCK_MST,
-                   JH7110_SYSCLK_I2STX_LRCK_EXT),
-       /* i2srx */
-@@ -300,11 +300,11 @@ static const struct jh71x0_clk_data jh71
-       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,
-+      JH71X0__MUX(JH7110_SYSCLK_I2SRX_BCLK, "i2srx_bclk", 0, 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,
-+      JH71X0__MUX(JH7110_SYSCLK_I2SRX_LRCK, "i2srx_lrck", 0, 2,
-                   JH7110_SYSCLK_I2SRX_LRCK_MST,
-                   JH7110_SYSCLK_I2SRX_LRCK_EXT),
-       /* pdm */
-@@ -314,7 +314,7 @@ static const struct jh71x0_clk_data jh71
-       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,
-+      JH71X0__MUX(JH7110_SYSCLK_TDM_TDM, "tdm_tdm", 0, 2,
-                   JH7110_SYSCLK_TDM_INTERNAL,
-                   JH7110_SYSCLK_TDM_EXT),
-       JH71X0__INV(JH7110_SYSCLK_TDM_TDM_INV, "tdm_tdm_inv", JH7110_SYSCLK_TDM_TDM),
---- a/drivers/clk/starfive/clk-starfive-jh71x0.h
-+++ b/drivers/clk/starfive/clk-starfive-jh71x0.h
-@@ -61,10 +61,10 @@ struct jh71x0_clk_data {
-       .parents = { [0] = _parent },                                           \
- }
--#define JH71X0__MUX(_idx, _name, _nparents, ...)                              \
-+#define JH71X0__MUX(_idx, _name, _flags, _nparents, ...)                      \
- [_idx] = {                                                                    \
-       .name = _name,                                                          \
--      .flags = 0,                                                             \
-+      .flags = _flags,                                                        \
-       .max = ((_nparents) - 1) << JH71X0_CLK_MUX_SHIFT,                       \
-       .parents = { __VA_ARGS__ },                                             \
- }
diff --git a/target/linux/starfive/patches-6.6/1007-clk-starfive-jh7100-Add-CLK_SET_RATE_PARENT-to-gmac_.patch b/target/linux/starfive/patches-6.6/1007-clk-starfive-jh7100-Add-CLK_SET_RATE_PARENT-to-gmac_.patch
deleted file mode 100644 (file)
index 74e695c..0000000
+++ /dev/null
@@ -1,25 +0,0 @@
-From 7dfed4b67bd6ba8c33caf90c01821b67cf3260dd Mon Sep 17 00:00:00 2001
-From: Emil Renner Berthing <emil.renner.berthing@canonical.com>
-Date: Sat, 25 Mar 2023 23:04:31 +0100
-Subject: [PATCH 1007/1024] clk: starfive: jh7100: Add CLK_SET_RATE_PARENT to
- gmac_tx
-
-This is needed by the dwmac-starfive ethernet driver to set the clock
-for 1000, 100 and 10 Mbps links properly.
-
-Signed-off-by: Emil Renner Berthing <emil.renner.berthing@canonical.com>
----
- drivers/clk/starfive/clk-starfive-jh7100.c | 2 +-
- 1 file changed, 1 insertion(+), 1 deletion(-)
-
---- a/drivers/clk/starfive/clk-starfive-jh7100.c
-+++ b/drivers/clk/starfive/clk-starfive-jh7100.c
-@@ -200,7 +200,7 @@ static const struct jh71x0_clk_data jh71
-       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", 0, 3,
-+      JH71X0__MUX(JH7100_CLK_GMAC_TX, "gmac_tx", CLK_SET_RATE_PARENT | CLK_SET_RATE_NO_REPARENT, 3,
-                   JH7100_CLK_GMAC_GTX,
-                   JH7100_CLK_GMAC_TX_INV,
-                   JH7100_CLK_GMAC_RMII_TX),
diff --git a/target/linux/starfive/patches-6.6/1008-clk-starfive-jh7100-Keep-more-clocks-alive.patch b/target/linux/starfive/patches-6.6/1008-clk-starfive-jh7100-Keep-more-clocks-alive.patch
deleted file mode 100644 (file)
index 27346b4..0000000
+++ /dev/null
@@ -1,94 +0,0 @@
-From f8d08ec17674e56c7c689f5ca43c4dd3a4b76d13 Mon Sep 17 00:00:00 2001
-From: Emil Renner Berthing <kernel@esmil.dk>
-Date: Thu, 14 Oct 2021 20:35:43 +0200
-Subject: [PATCH 1008/1024] clk: starfive: jh7100: Keep more clocks alive
-
-Signed-off-by: Emil Renner Berthing <kernel@esmil.dk>
----
- drivers/clk/starfive/clk-starfive-jh7100.c | 37 +++++++++++-----------
- 1 file changed, 19 insertions(+), 18 deletions(-)
-
---- a/drivers/clk/starfive/clk-starfive-jh7100.c
-+++ b/drivers/clk/starfive/clk-starfive-jh7100.c
-@@ -94,9 +94,9 @@ static const struct jh71x0_clk_data jh71
-       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_GATE(JH7100_CLK_DLA_AXI, "dla_axi", CLK_IGNORE_UNUSED, JH7100_CLK_DLA_BUS),
-+      JH71X0_GATE(JH7100_CLK_DLANOC_AXI, "dlanoc_axi", CLK_IGNORE_UNUSED, JH7100_CLK_DLA_BUS),
-+      JH71X0_GATE(JH7100_CLK_DLA_APB, "dla_apb", CLK_IGNORE_UNUSED, 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),
-@@ -160,11 +160,12 @@ static const struct jh71x0_clk_data jh71
-       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_GATE(JH7100_CLK_USB_AXI, "usb_axi", CLK_IGNORE_UNUSED, JH7100_CLK_USB_BUS),
-+      JH71X0_GATE(JH7100_CLK_USBNOC_AXI, "usbnoc_axi", CLK_IGNORE_UNUSED, 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,
-+      JH71X0_GDIV(JH7100_CLK_USBPHY_125M, "usbphy_125m", CLK_IGNORE_UNUSED, 8,
-+                  JH7100_CLK_USBPHY_ROOTDIV),
-+      JH71X0_GDIV(JH7100_CLK_USBPHY_PLLDIV25M, "usbphy_plldiv25m", CLK_IGNORE_UNUSED, 32,
-                   JH7100_CLK_USBPHY_ROOTDIV),
-       JH71X0__MUX(JH7100_CLK_USBPHY_25M, "usbphy_25m", 0, 2,
-                   JH7100_CLK_OSC_SYS,
-@@ -183,23 +184,23 @@ static const struct jh71x0_clk_data jh71
-       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_GDIV(JH7100_CLK_VOUT_SRC, "vout_src", CLK_IGNORE_UNUSED, 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_DISP_AXI, "disp_axi", CLK_IGNORE_UNUSED, JH7100_CLK_DISP_BUS),
-+      JH71X0_GATE(JH7100_CLK_DISPNOC_AXI, "dispnoc_axi", CLK_IGNORE_UNUSED, 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_GATE(JH7100_CLK_GMAC_AHB, "gmac_ahb", CLK_IGNORE_UNUSED, 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_GDIV(JH7100_CLK_GMAC_PTP_REF, "gmac_ptp_refclk", CLK_IGNORE_UNUSED, 31, JH7100_CLK_GMAC_ROOT_DIV),
-+      JH71X0_GDIV(JH7100_CLK_GMAC_GTX, "gmac_gtxclk", CLK_IGNORE_UNUSED, 255, JH7100_CLK_GMAC_ROOT_DIV),
-+      JH71X0_GDIV(JH7100_CLK_GMAC_RMII_TX, "gmac_rmii_txclk", CLK_IGNORE_UNUSED, 8, JH7100_CLK_GMAC_RMII_REF),
-+      JH71X0_GDIV(JH7100_CLK_GMAC_RMII_RX, "gmac_rmii_rxclk", CLK_IGNORE_UNUSED, 8, JH7100_CLK_GMAC_RMII_REF),
-       JH71X0__MUX(JH7100_CLK_GMAC_TX, "gmac_tx", CLK_SET_RATE_PARENT | CLK_SET_RATE_NO_REPARENT, 3,
-                   JH7100_CLK_GMAC_GTX,
-                   JH7100_CLK_GMAC_TX_INV,
-@@ -209,8 +210,8 @@ static const struct jh71x0_clk_data jh71
-                   JH7100_CLK_GMAC_GR_MII_RX,
-                   JH7100_CLK_GMAC_RMII_RX),
-       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_GMAC_RMII, "gmac_rmii", CLK_IGNORE_UNUSED, JH7100_CLK_GMAC_RMII_REF),
-+      JH71X0_GDIV(JH7100_CLK_GMAC_TOPHYREF, "gmac_tophyref", CLK_IGNORE_UNUSED, 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),
-@@ -223,7 +224,7 @@ static const struct jh71x0_clk_data jh71
-       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_TRNG_APB, "trng_apb", CLK_IGNORE_UNUSED, 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),
diff --git a/target/linux/starfive/patches-6.6/1009-net-stmmac-use-GFP_DMA32.patch b/target/linux/starfive/patches-6.6/1009-net-stmmac-use-GFP_DMA32.patch
deleted file mode 100644 (file)
index f93917b..0000000
+++ /dev/null
@@ -1,30 +0,0 @@
-From 980f1e9ef19d472e72c36e142db7fb4e224f0f3e Mon Sep 17 00:00:00 2001
-From: Matteo Croce <technoboy85@gmail.com>
-Date: Fri, 21 May 2021 03:26:38 +0200
-Subject: [PATCH 1009/1024] net: stmmac: use GFP_DMA32
-
-Signed-off-by: Matteo Croce <mcroce@microsoft.com>
----
- drivers/net/ethernet/stmicro/stmmac/stmmac_main.c | 4 ++--
- 1 file changed, 2 insertions(+), 2 deletions(-)
-
---- a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
-+++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
-@@ -1434,7 +1434,7 @@ static int stmmac_init_rx_buffers(struct
- {
-       struct stmmac_rx_queue *rx_q = &dma_conf->rx_queue[queue];
-       struct stmmac_rx_buffer *buf = &rx_q->buf_pool[i];
--      gfp_t gfp = (GFP_ATOMIC | __GFP_NOWARN);
-+      gfp_t gfp = (GFP_ATOMIC | __GFP_NOWARN | GFP_DMA32);
-       if (priv->dma_cap.host_dma_width <= 32)
-               gfp |= GFP_DMA32;
-@@ -4687,7 +4687,7 @@ static inline void stmmac_rx_refill(stru
-       struct stmmac_rx_queue *rx_q = &priv->dma_conf.rx_queue[queue];
-       int dirty = stmmac_rx_dirty(priv, queue);
-       unsigned int entry = rx_q->dirty_rx;
--      gfp_t gfp = (GFP_ATOMIC | __GFP_NOWARN);
-+      gfp_t gfp = (GFP_ATOMIC | __GFP_NOWARN | GFP_DMA32);
-       if (priv->dma_cap.host_dma_width <= 32)
-               gfp |= GFP_DMA32;
diff --git a/target/linux/starfive/patches-6.6/1010-hwrng-Add-StarFive-JH7100-Random-Number-Generator-dr.patch b/target/linux/starfive/patches-6.6/1010-hwrng-Add-StarFive-JH7100-Random-Number-Generator-dr.patch
deleted file mode 100644 (file)
index b625014..0000000
+++ /dev/null
@@ -1,477 +0,0 @@
-From 4989e7aa5ed5ef9bc2532b3a47ff381572f389b5 Mon Sep 17 00:00:00 2001
-From: Huan Feng <huan.feng@starfivetech.com>
-Date: Fri, 8 Jan 2021 03:35:42 +0800
-Subject: [PATCH 1010/1024] hwrng: Add StarFive JH7100 Random Number Generator
- driver
-
-Signed-off-by: Emil Renner Berthing <kernel@esmil.dk>
----
- drivers/char/hw_random/Kconfig            |  13 ++
- drivers/char/hw_random/Makefile           |   1 +
- drivers/char/hw_random/starfive-vic-rng.c | 256 ++++++++++++++++++++++
- drivers/char/hw_random/starfive-vic-rng.h | 167 ++++++++++++++
- 4 files changed, 437 insertions(+)
- create mode 100644 drivers/char/hw_random/starfive-vic-rng.c
- create mode 100644 drivers/char/hw_random/starfive-vic-rng.h
-
---- a/drivers/char/hw_random/Kconfig
-+++ b/drivers/char/hw_random/Kconfig
-@@ -322,6 +322,19 @@ config HW_RANDOM_POWERNV
-         If unsure, say Y.
-+config HW_RANDOM_STARFIVE_VIC
-+      tristate "Starfive VIC Random Number Generator support"
-+      depends on HW_RANDOM && (SOC_STARFIVE || COMPILE_TEST)
-+      default SOC_STARFIVE
-+      help
-+        This driver provides kernel-side support for the Random Number
-+        Generator hardware found on Starfive VIC SoC.
-+
-+        To compile this driver as a module, choose M here: the
-+        module will be called starfive-vic-rng.
-+
-+        If unsure, say Y.
-+
- config HW_RANDOM_HISI
-       tristate "Hisilicon Random Number Generator support"
-       depends on ARCH_HISI || COMPILE_TEST
---- a/drivers/char/hw_random/Makefile
-+++ b/drivers/char/hw_random/Makefile
-@@ -28,6 +28,7 @@ obj-$(CONFIG_HW_RANDOM_OCTEON) += octeon
- obj-$(CONFIG_HW_RANDOM_NOMADIK) += nomadik-rng.o
- obj-$(CONFIG_HW_RANDOM_PSERIES) += pseries-rng.o
- obj-$(CONFIG_HW_RANDOM_POWERNV) += powernv-rng.o
-+obj-$(CONFIG_HW_RANDOM_STARFIVE_VIC)  += starfive-vic-rng.o
- obj-$(CONFIG_HW_RANDOM_HISI)  += hisi-rng.o
- obj-$(CONFIG_HW_RANDOM_HISTB) += histb-rng.o
- obj-$(CONFIG_HW_RANDOM_BCM2835) += bcm2835-rng.o
---- /dev/null
-+++ b/drivers/char/hw_random/starfive-vic-rng.c
-@@ -0,0 +1,256 @@
-+/*
-+ ******************************************************************************
-+ * @file  starfive-vic-rng.c
-+ * @author  StarFive Technology
-+ * @version  V1.0
-+ * @date  08/13/2020
-+ * @brief
-+ ******************************************************************************
-+ * @copy
-+ *
-+ * THE PRESENT SOFTWARE WHICH IS FOR GUIDANCE ONLY AIMS AT PROVIDING CUSTOMERS
-+ * WITH CODING INFORMATION REGARDING THEIR PRODUCTS IN ORDER FOR THEM TO SAVE
-+ * TIME. AS A RESULT, STARFIVE SHALL NOT BE HELD LIABLE FOR ANY
-+ * DIRECT, INDIRECT OR CONSEQUENTIAL DAMAGES WITH RESPECT TO ANY CLAIMS ARISING
-+ * FROM THE CONTENT OF SUCH SOFTWARE AND/OR THE USE MADE BY CUSTOMERS OF THE
-+ * CODING INFORMATION CONTAINED HEREIN IN CONNECTION WITH THEIR PRODUCTS.
-+ *
-+ * COPYRIGHT 2020 Shanghai StarFive Technology Co., Ltd.
-+ */
-+#include <linux/err.h>
-+#include <linux/kernel.h>
-+#include <linux/hw_random.h>
-+#include <linux/io.h>
-+#include <linux/module.h>
-+#include <linux/of.h>
-+#include <linux/platform_device.h>
-+#include <linux/interrupt.h>
-+#include <linux/random.h>
-+
-+#include "starfive-vic-rng.h"
-+
-+#define to_vic_rng(p) container_of(p, struct vic_rng, rng)
-+
-+struct vic_rng {
-+      struct device   *dev;
-+      void __iomem    *base;
-+      struct hwrng    rng;
-+};
-+
-+static inline void vic_wait_till_idle(struct vic_rng *hrng)
-+{
-+      while(readl(hrng->base + VIC_STAT) & VIC_STAT_BUSY)
-+              ;
-+}
-+
-+static inline void vic_rng_irq_mask_clear(struct vic_rng *hrng)
-+{
-+      // clear register: ISTAT
-+      u32 data = readl(hrng->base + VIC_ISTAT);
-+      writel(data, hrng->base + VIC_ISTAT);
-+      writel(0, hrng->base + VIC_ALARM);
-+}
-+
-+static int vic_trng_cmd(struct vic_rng *hrng, u32 cmd) {
-+      int res = 0;
-+      // wait till idle
-+      vic_wait_till_idle(hrng);
-+      switch (cmd) {
-+      case VIC_CTRL_CMD_NOP:
-+      case VIC_CTRL_CMD_GEN_NOISE:
-+      case VIC_CTRL_CMD_GEN_NONCE:
-+      case VIC_CTRL_CMD_CREATE_STATE:
-+      case VIC_CTRL_CMD_RENEW_STATE:
-+      case VIC_CTRL_CMD_REFRESH_ADDIN:
-+      case VIC_CTRL_CMD_GEN_RANDOM:
-+      case VIC_CTRL_CMD_ADVANCE_STATE:
-+      case VIC_CTRL_CMD_KAT:
-+      case VIC_CTRL_CMD_ZEROIZE:
-+              writel(cmd, hrng->base + VIC_CTRL);
-+              break;
-+      default:
-+              res = -1;
-+              break;
-+      }
-+
-+      return res;
-+}
-+
-+static int vic_rng_init(struct hwrng *rng)
-+{
-+      struct vic_rng *hrng = to_vic_rng(rng);
-+
-+      // wait till idle
-+
-+      // clear register: ISTAT
-+      vic_rng_irq_mask_clear(hrng);
-+
-+      // set mission mode
-+      writel(VIC_SMODE_SECURE_EN(1), hrng->base + VIC_SMODE);
-+
-+      vic_trng_cmd(hrng, VIC_CTRL_CMD_GEN_NOISE);
-+      vic_wait_till_idle(hrng);
-+
-+      // set interrupt
-+      writel(VIC_IE_ALL, hrng->base + VIC_IE);
-+
-+      // zeroize
-+      vic_trng_cmd(hrng, VIC_CTRL_CMD_ZEROIZE);
-+
-+      vic_wait_till_idle(hrng);
-+
-+      return 0;
-+}
-+
-+static irqreturn_t vic_rng_irq(int irq, void *priv)
-+{
-+      u32 status, val;
-+      struct vic_rng *hrng = (struct vic_rng *)priv;
-+
-+      /*
-+       * clearing the interrupt will also clear the error register
-+       * read error and status before clearing
-+       */
-+      status = readl(hrng->base + VIC_ISTAT);
-+
-+      if (status & VIC_ISTAT_ALARMS) {
-+              writel(VIC_ISTAT_ALARMS, hrng->base + VIC_ISTAT);
-+              val = readl(hrng->base + VIC_ALARM);
-+              if (val & VIC_ALARM_ILLEGAL_CMD_SEQ) {
-+                      writel(VIC_ALARM_ILLEGAL_CMD_SEQ, hrng->base + VIC_ALARM);
-+                      //dev_info(hrng->dev, "ILLEGAL CMD SEQ: LAST_CMD=0x%x\r\n",
-+                      //VIC_STAT_LAST_CMD(readl(hrng->base + VIC_STAT)));
-+              } else {
-+                      dev_info(hrng->dev, "Failed test: %x\r\n", val);
-+              }
-+      }
-+
-+      if (status & VIC_ISTAT_ZEROIZE) {
-+              writel(VIC_ISTAT_ZEROIZE, hrng->base + VIC_ISTAT);
-+              //dev_info(hrng->dev, "zeroized\r\n");
-+      }
-+
-+      if (status & VIC_ISTAT_KAT_COMPLETE) {
-+              writel(VIC_ISTAT_KAT_COMPLETE, hrng->base + VIC_ISTAT);
-+              //dev_info(hrng->dev, "kat_completed\r\n");
-+      }
-+
-+      if (status & VIC_ISTAT_NOISE_RDY) {
-+              writel(VIC_ISTAT_NOISE_RDY, hrng->base + VIC_ISTAT);
-+              //dev_info(hrng->dev, "noise_rdy\r\n");
-+      }
-+
-+      if (status & VIC_ISTAT_DONE) {
-+              writel(VIC_ISTAT_DONE, hrng->base + VIC_ISTAT);
-+              //dev_info(hrng->dev, "done\r\n");
-+              /*
-+              if (VIC_STAT_LAST_CMD(readl(hrng->base + VIC_STAT)) ==
-+                  VIC_CTRL_CMD_GEN_RANDOM) {
-+                      dev_info(hrng->dev, "Need Update Buffer\r\n");
-+              }
-+              */
-+      }
-+      vic_rng_irq_mask_clear(hrng);
-+
-+      return IRQ_HANDLED;
-+}
-+
-+static void vic_rng_cleanup(struct hwrng *rng)
-+{
-+      struct vic_rng *hrng = to_vic_rng(rng);
-+
-+      writel(0, hrng->base + VIC_CTRL);
-+}
-+
-+static int vic_rng_read(struct hwrng *rng, void *buf, size_t max, bool wait)
-+{
-+      struct vic_rng *hrng = to_vic_rng(rng);
-+
-+      vic_trng_cmd(hrng, VIC_CTRL_CMD_ZEROIZE);
-+      vic_trng_cmd(hrng, VIC_CTRL_CMD_GEN_NOISE);
-+      vic_trng_cmd(hrng, VIC_CTRL_CMD_CREATE_STATE);
-+
-+      vic_wait_till_idle(hrng);
-+      max = min_t(size_t, max, (VIC_RAND_LEN * 4));
-+
-+      writel(0x0, hrng->base + VIC_MODE);
-+      vic_trng_cmd(hrng, VIC_CTRL_CMD_GEN_RANDOM);
-+
-+      vic_wait_till_idle(hrng);
-+      memcpy_fromio(buf, hrng->base + VIC_RAND0, max);
-+      vic_trng_cmd(hrng, VIC_CTRL_CMD_ZEROIZE);
-+
-+      vic_wait_till_idle(hrng);
-+      return max;
-+}
-+
-+static int vic_rng_probe(struct platform_device *pdev)
-+{
-+      int ret;
-+      int irq;
-+      struct vic_rng *rng;
-+      struct resource *res;
-+
-+      rng = devm_kzalloc(&pdev->dev, sizeof(*rng), GFP_KERNEL);
-+      if (!rng){
-+              return -ENOMEM;
-+      }
-+
-+      platform_set_drvdata(pdev, rng);
-+
-+      res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-+      rng->base = devm_ioremap_resource(&pdev->dev, res);
-+      if (IS_ERR(rng->base)){
-+              return PTR_ERR(rng->base);
-+      }
-+
-+      irq = platform_get_irq(pdev, 0);
-+      if (irq <= 0) {
-+              dev_err(&pdev->dev, "Couldn't get irq %d\n", irq);
-+              return irq;
-+      }
-+
-+      ret = devm_request_irq(&pdev->dev, irq, vic_rng_irq, 0, pdev->name,
-+                              (void *)rng);
-+      if (ret) {
-+              dev_err(&pdev->dev, "Can't get interrupt working.\n");
-+              return ret;
-+      }
-+
-+      rng->rng.name = pdev->name;
-+      rng->rng.init = vic_rng_init;
-+      rng->rng.cleanup = vic_rng_cleanup;
-+      rng->rng.read = vic_rng_read;
-+
-+      rng->dev = &pdev->dev;
-+
-+      ret = devm_hwrng_register(&pdev->dev, &rng->rng);
-+      if (ret) {
-+              dev_err(&pdev->dev, "failed to register hwrng\n");
-+              return ret;
-+      }
-+
-+      dev_info(&pdev->dev, "Initialized\n");
-+
-+      return 0;
-+}
-+
-+static const struct of_device_id vic_rng_dt_ids[] = {
-+      { .compatible = "starfive,vic-rng" },
-+      { }
-+};
-+MODULE_DEVICE_TABLE(of, vic_rng_dt_ids);
-+
-+static struct platform_driver vic_rng_driver = {
-+      .probe          = vic_rng_probe,
-+      .driver         = {
-+              .name           = "vic-rng",
-+              .of_match_table = vic_rng_dt_ids,
-+      },
-+};
-+
-+module_platform_driver(vic_rng_driver);
-+
-+MODULE_LICENSE("GPL");
-+MODULE_AUTHOR("Huan Feng <huan.feng@starfivetech.com>");
-+MODULE_DESCRIPTION("Starfive VIC random number generator driver");
---- /dev/null
-+++ b/drivers/char/hw_random/starfive-vic-rng.h
-@@ -0,0 +1,167 @@
-+/*
-+ ******************************************************************************
-+ * @file  starfive-vic-rng.h
-+ * @author  StarFive Technology
-+ * @version  V1.0
-+ * @date  08/13/2020
-+ * @brief
-+ ******************************************************************************
-+ * @copy
-+ *
-+ * THE PRESENT SOFTWARE WHICH IS FOR GUIDANCE ONLY AIMS AT PROVIDING CUSTOMERS
-+ * WITH CODING INFORMATION REGARDING THEIR PRODUCTS IN ORDER FOR THEM TO SAVE
-+ * TIME. AS A RESULT, STARFIVE SHALL NOT BE HELD LIABLE FOR ANY
-+ * DIRECT, INDIRECT OR CONSEQUENTIAL DAMAGES WITH RESPECT TO ANY CLAIMS ARISING
-+ * FROM THE CONTENT OF SUCH SOFTWARE AND/OR THE USE MADE BY CUSTOMERS OF THE
-+ * CODING INFORMATION CONTAINED HEREIN IN CONNECTION WITH THEIR PRODUCTS.
-+ *
-+ * COPYRIGHT 2020 Shanghai StarFive Technology Co., Ltd.
-+ */
-+
-+#define VIC_CTRL              0x00
-+#define VIC_MODE              0x04
-+#define VIC_SMODE             0x08
-+#define VIC_STAT              0x0C
-+#define VIC_IE                        0x10
-+#define VIC_ISTAT             0x14
-+#define VIC_ALARM             0x18
-+#define VIC_BUILD_ID          0x1C
-+#define VIC_FEATURES          0x20
-+#define VIC_RAND0             0x24
-+#define VIC_NPA_DATA0         0x34
-+#define VIC_SEED0             0x74
-+#define VIC_IA_RDATA          0xA4
-+#define VIC_IA_WDATA          0xA8
-+#define VIC_IA_ADDR           0xAC
-+#define VIC_IA_CMD            0xB0
-+
-+/* CTRL */
-+#define VIC_CTRL_CMD_NOP              0
-+#define VIC_CTRL_CMD_GEN_NOISE                1
-+#define VIC_CTRL_CMD_GEN_NONCE                2
-+#define VIC_CTRL_CMD_CREATE_STATE     3
-+#define VIC_CTRL_CMD_RENEW_STATE      4
-+#define VIC_CTRL_CMD_REFRESH_ADDIN    5
-+#define VIC_CTRL_CMD_GEN_RANDOM               6
-+#define VIC_CTRL_CMD_ADVANCE_STATE    7
-+#define VIC_CTRL_CMD_KAT              8
-+#define VIC_CTRL_CMD_ZEROIZE          15
-+
-+/* MODE */
-+#define _VIC_MODE_ADDIN_PRESENT               4
-+#define _VIC_MODE_PRED_RESIST         3
-+#define _VIC_MODE_KAT_SEL             2
-+#define _VIC_MODE_KAT_VEC             1
-+#define _VIC_MODE_SEC_ALG             0
-+
-+#define VIC_MODE_ADDIN_PRESENT        (1UL << _VIC_MODE_ADDIN_PRESENT)
-+#define VIC_MODE_PRED_RESIST  (1UL << _VIC_MODE_PRED_RESIST)
-+#define VIC_MODE_KAT_SEL      (1UL << _VIC_MODE_KAT_SEL)
-+#define VIC_MODE_KAT_VEC      (1UL << _VIC_MODE_KAT_VEC)
-+#define VIC_MODE_SEC_ALG      (1UL << _VIC_MODE_SEC_ALG)
-+
-+/* SMODE */
-+#define _VIC_SMODE_MAX_REJECTS        2
-+#define _VIC_SMODE_SECURE_EN  1
-+#define _VIC_SMODE_NONCE      0
-+
-+#define VIC_SMODE_MAX_REJECTS(x)      ((x) << _VIC_SMODE_MAX_REJECTS)
-+#define VIC_SMODE_SECURE_EN(x)                ((x) << _VIC_SMODE_SECURE_EN)
-+#define VIC_SMODE_NONCE                       (1UL << _VIC_SMODE_NONCE)
-+
-+/* STAT */
-+#define _VIC_STAT_BUSY                31
-+#define _VIC_STAT_DRBG_STATE  7
-+#define _VIC_STAT_SECURE      6
-+#define _VIC_STAT_NONCE_MODE  5
-+#define _VIC_STAT_SEC_ALG     4
-+#define _VIC_STAT_LAST_CMD    0
-+
-+#define VIC_STAT_BUSY         (1UL << _VIC_STAT_BUSY)
-+#define VIC_STAT_DRBG_STATE   (1UL << _VIC_STAT_DRBG_STATE)
-+#define VIC_STAT_SECURE               (1UL << _VIC_STAT_SECURE)
-+#define VIC_STAT_NONCE_MODE   (1UL << _VIC_STAT_NONCE_MODE)
-+#define VIC_STAT_SEC_ALG      (1UL << _VIC_STAT_SEC_ALG)
-+#define VIC_STAT_LAST_CMD(x)  (((x) >> _VIC_STAT_LAST_CMD) & 0xF)
-+
-+/* IE */
-+#define _VIC_IE_GLBL          31
-+#define _VIC_IE_DONE          4
-+#define _VIC_IE_ALARMS                3
-+#define _VIC_IE_NOISE_RDY     2
-+#define _VIC_IE_KAT_COMPLETE  1
-+#define _VIC_IE_ZEROIZE               0
-+
-+#define VIC_IE_GLBL           (1UL << _VIC_IE_GLBL)
-+#define VIC_IE_DONE           (1UL << _VIC_IE_DONE)
-+#define VIC_IE_ALARMS         (1UL << _VIC_IE_ALARMS)
-+#define VIC_IE_NOISE_RDY      (1UL << _VIC_IE_NOISE_RDY)
-+#define VIC_IE_KAT_COMPLETE   (1UL << _VIC_IE_KAT_COMPLETE)
-+#define VIC_IE_ZEROIZE                (1UL << _VIC_IE_ZEROIZE)
-+#define VIC_IE_ALL            (VIC_IE_GLBL | VIC_IE_DONE | VIC_IE_ALARMS | \
-+                               VIC_IE_NOISE_RDY | VIC_IE_KAT_COMPLETE | VIC_IE_ZEROIZE)
-+
-+/* ISTAT */
-+#define _VIC_ISTAT_DONE               4
-+#define _VIC_ISTAT_ALARMS     3
-+#define _VIC_ISTAT_NOISE_RDY  2
-+#define _VIC_ISTAT_KAT_COMPLETE       1
-+#define _VIC_ISTAT_ZEROIZE    0
-+
-+#define VIC_ISTAT_DONE                (1UL << _VIC_ISTAT_DONE)
-+#define VIC_ISTAT_ALARMS      (1UL << _VIC_ISTAT_ALARMS)
-+#define VIC_ISTAT_NOISE_RDY   (1UL << _VIC_ISTAT_NOISE_RDY)
-+#define VIC_ISTAT_KAT_COMPLETE        (1UL << _VIC_ISTAT_KAT_COMPLETE)
-+#define VIC_ISTAT_ZEROIZE     (1UL << _VIC_ISTAT_ZEROIZE)
-+
-+/* ALARMS */
-+#define VIC_ALARM_ILLEGAL_CMD_SEQ                     (1UL << 4)
-+#define VIC_ALARM_FAILED_TEST_ID_OK                   0
-+#define VIC_ALARM_FAILED_TEST_ID_KAT_STAT             1
-+#define VIC_ALARM_FAILED_TEST_ID_KAT                  2
-+#define VIC_ALARM_FAILED_TEST_ID_MONOBIT              3
-+#define VIC_ALARM_FAILED_TEST_ID_RUN                  4
-+#define VIC_ALARM_FAILED_TEST_ID_LONGRUN              5
-+#define VIC_ALARM_FAILED_TEST_ID_AUTOCORRELATION      6
-+#define VIC_ALARM_FAILED_TEST_ID_POKER                        7
-+#define VIC_ALARM_FAILED_TEST_ID_REPETITION_COUNT     8
-+#define VIC_ALARM_FAILED_TEST_ID_ADAPATIVE_PROPORTION 9
-+
-+/* BUILD_ID */
-+#define VIC_BUILD_ID_STEPPING(x)              (((x) >> 28) & 0xF)
-+#define VIC_BUILD_ID_EPN(x)                   ((x) & 0xFFFF)
-+
-+/* FEATURES */
-+#define VIC_FEATURES_AES_256(x)                       (((x) >> 9) & 1)
-+#define VIC_FEATURES_EXTRA_PS_PRESENT(x)      (((x) >> 8) & 1)
-+#define VIC_FEATURES_DIAG_LEVEL_NS(x)         (((x) >> 7) & 1)
-+#define VIC_FEATURES_DIAG_LEVEL_CLP800(x)     (((x) >> 4) & 7)
-+#define VIC_FEATURES_DIAG_LEVEL_ST_HLT(x)     (((x) >> 1) & 7)
-+#define VIC_FEATURES_SECURE_RST_STATE(x)      ((x) & 1)
-+
-+/* IA_CMD */
-+#define VIC_IA_CMD_GO                 (1UL << 31)
-+#define VIC_IA_CMD_WR                 (1)
-+
-+#define _VIC_SMODE_MAX_REJECTS_MASK   255UL
-+#define _VIC_SMODE_SECURE_EN_MASK     1UL
-+#define _VIC_SMODE_NONCE_MASK         1UL
-+#define _VIC_MODE_SEC_ALG_MASK                1UL
-+#define _VIC_MODE_ADDIN_PRESENT_MASK  1UL
-+#define _VIC_MODE_PRED_RESIST_MASK    1UL
-+
-+#define VIC_SMODE_SET_MAX_REJECTS(y, x)       (((y) & ~(_VIC_SMODE_MAX_REJECTS_MASK << _VIC_SMODE_MAX_REJECTS)) | ((x) << _VIC_SMODE_MAX_REJECTS))
-+#define VIC_SMODE_SET_SECURE_EN(y, x) (((y) & ~(_VIC_SMODE_SECURE_EN_MASK   << _VIC_SMODE_SECURE_EN))   | ((x) << _VIC_SMODE_SECURE_EN))
-+#define VIC_SMODE_SET_NONCE(y, x)     (((y) & ~(_VIC_SMODE_NONCE_MASK       << _VIC_SMODE_NONCE))       | ((x) << _VIC_SMODE_NONCE))
-+#define VIC_SMODE_GET_MAX_REJECTS(x)  (((x) >> _VIC_SMODE_MAX_REJECTS) & _VIC_SMODE_MAX_REJECTS_MASK)
-+#define VIC_SMODE_GET_SECURE_EN(x)    (((x) >> _VIC_SMODE_SECURE_EN)   & _VIC_SMODE_SECURE_EN_MASK)
-+#define VIC_SMODE_GET_NONCE(x)                (((x) >> _VIC_SMODE_NONCE)       & _VIC_SMODE_NONCE_MASK)
-+
-+#define VIC_MODE_SET_SEC_ALG(y, x)    (((y) & ~(_VIC_MODE_SEC_ALG_MASK       << _VIC_MODE_SEC_ALG))   | ((x) << _VIC_MODE_SEC_ALG))
-+#define VIC_MODE_SET_PRED_RESIST(y, x)        (((y) & ~(_VIC_MODE_PRED_RESIST_MASK   << _VIC_MODE_PRED_RESIST))    | ((x) << _VIC_MODE_PRED_RESIST))
-+#define VIC_MODE_SET_ADDIN_PRESENT(y, x) (((y) & ~(_VIC_MODE_ADDIN_PRESENT_MASK << _VIC_MODE_ADDIN_PRESENT))  | ((x) << _VIC_MODE_ADDIN_PRESENT))
-+#define VIC_MODE_GET_SEC_ALG(x)               (((x) >> _VIC_MODE_SEC_ALG)       & _VIC_MODE_SEC_ALG_MASK)
-+#define VIC_MODE_GET_PRED_RESIST(x)   (((x) >> _VIC_MODE_PRED_RESIST)   & _VIC_MODE_PRED_RESIST_MASK)
-+#define VIC_MODE_GET_ADDIN_PRESENT(x) (((x) >> _VIC_MODE_ADDIN_PRESENT) & _VIC_MODE_ADDIN_PRESENT_MASK)
-+
-+#define VIC_RAND_LEN 4
diff --git a/target/linux/starfive/patches-6.6/1011-pwm-sifive-ptc-Add-SiFive-PWM-PTC-driver.patch b/target/linux/starfive/patches-6.6/1011-pwm-sifive-ptc-Add-SiFive-PWM-PTC-driver.patch
deleted file mode 100644 (file)
index 7a588c2..0000000
+++ /dev/null
@@ -1,309 +0,0 @@
-From 34fd7b7f92deef97f03c80d056e2f51bc08b7dc6 Mon Sep 17 00:00:00 2001
-From: Chenjieqin <Jessica.Chen@starfivetech.com>
-Date: Fri, 8 Jan 2021 03:56:54 +0800
-Subject: [PATCH 1011/1024] pwm: sifive-ptc: Add SiFive PWM PTC driver
-
-yiming.li: clear CNTR of PWM after setting period & duty_cycle
-Emil: cleanups, clock, reset and div_u64
-
-Signed-off-by: Emil Renner Berthing <kernel@esmil.dk>
----
- drivers/pwm/Kconfig          |  11 ++
- drivers/pwm/Makefile         |   1 +
- drivers/pwm/pwm-sifive-ptc.c | 260 +++++++++++++++++++++++++++++++++++
- 3 files changed, 272 insertions(+)
- create mode 100644 drivers/pwm/pwm-sifive-ptc.c
-
---- a/drivers/pwm/Kconfig
-+++ b/drivers/pwm/Kconfig
-@@ -549,6 +549,17 @@ config PWM_SIFIVE
-         To compile this driver as a module, choose M here: the module
-         will be called pwm-sifive.
-+config PWM_SIFIVE_PTC
-+      tristate "SiFive PWM PTC support"
-+      depends on SOC_SIFIVE || SOC_STARFIVE || COMPILE_TEST
-+      depends on OF
-+      depends on COMMON_CLK
-+      help
-+        Generic PWM framework driver for SiFive SoCs.
-+
-+        To compile this driver as a module, choose M here: the module
-+        will be called pwm-sifive-ptc.
-+
- config PWM_SL28CPLD
-       tristate "Kontron sl28cpld PWM support"
-       depends on MFD_SL28CPLD || COMPILE_TEST
---- a/drivers/pwm/Makefile
-+++ b/drivers/pwm/Makefile
-@@ -50,6 +50,7 @@ obj-$(CONFIG_PWM_ROCKCHIP)   += pwm-rockch
- obj-$(CONFIG_PWM_RZ_MTU3)     += pwm-rz-mtu3.o
- obj-$(CONFIG_PWM_SAMSUNG)     += pwm-samsung.o
- obj-$(CONFIG_PWM_SIFIVE)      += pwm-sifive.o
-+obj-$(CONFIG_PWM_SIFIVE_PTC)  += pwm-sifive-ptc.o
- obj-$(CONFIG_PWM_SL28CPLD)    += pwm-sl28cpld.o
- obj-$(CONFIG_PWM_SPEAR)               += pwm-spear.o
- obj-$(CONFIG_PWM_SPRD)                += pwm-sprd.o
---- /dev/null
-+++ b/drivers/pwm/pwm-sifive-ptc.c
-@@ -0,0 +1,260 @@
-+/*
-+ * Copyright (C) 2018 SiFive, Inc
-+ *
-+ * This program is free software; you can redistribute it and/or modify it
-+ * under the terms of the GNU General Public License version 2, as published by
-+ * the Free Software Foundation.
-+ */
-+
-+#include <linux/clk.h>
-+#include <linux/io.h>
-+#include <linux/math64.h>
-+#include <linux/module.h>
-+#include <linux/platform_device.h>
-+#include <linux/pwm.h>
-+#include <linux/reset.h>
-+
-+#include <dt-bindings/pwm/pwm.h>
-+
-+/* max channel of pwm */
-+#define MAX_PWM                               8
-+
-+/* 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_1                          1000000000U
-+
-+/* 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)
-+
-+/* pwm ptc device */
-+struct sifive_pwm_ptc_device {
-+      struct pwm_chip chip;
-+      struct clk      *clk;
-+      void __iomem    *regs;
-+};
-+
-+static inline struct sifive_pwm_ptc_device *chip_to_sifive_ptc(struct pwm_chip *c)
-+{
-+      return container_of(c, struct sifive_pwm_ptc_device, chip);
-+}
-+
-+static int sifive_pwm_ptc_get_state(struct pwm_chip *chip, struct pwm_device *dev,
-+                                  struct pwm_state *state)
-+{
-+      struct sifive_pwm_ptc_device *pwm = chip_to_sifive_ptc(chip);
-+      u32 data_lrc;
-+      u32 data_hrc;
-+      u32 pwm_clk_ns = 0;
-+
-+      /* get lrc and hrc data from registe */
-+      data_lrc = ioread32(REG_PTC_RPTC_LRC(pwm->regs, dev->hwpwm));
-+      data_hrc = ioread32(REG_PTC_RPTC_HRC(pwm->regs, dev->hwpwm));
-+
-+      /* how many ns does apb clock elapse */
-+      pwm_clk_ns = NS_1 / clk_get_rate(pwm->clk);
-+
-+      /* pwm period(ns) */
-+      state->period     = data_lrc * pwm_clk_ns;
-+
-+      /* duty cycle(ns) means high level eclapse ns if it is normal polarity */
-+      state->duty_cycle = data_hrc * pwm_clk_ns;
-+
-+      /* polarity, we don't use it now because it is not in dts */
-+      state->polarity   = PWM_POLARITY_NORMAL;
-+
-+      /* enabled or not */
-+      state->enabled    = 1;
-+
-+      dev_dbg(pwm->chip.dev, "%s: no:%d\n", __func__, dev->hwpwm);
-+      dev_dbg(pwm->chip.dev, "data_hrc:0x%x 0x%x\n", data_hrc, data_lrc);
-+      dev_dbg(pwm->chip.dev, "period:%llu\n", state->period);
-+      dev_dbg(pwm->chip.dev, "duty_cycle:%llu\n", state->duty_cycle);
-+      dev_dbg(pwm->chip.dev, "polarity:%d\n", state->polarity);
-+      dev_dbg(pwm->chip.dev, "enabled:%d\n", state->enabled);
-+
-+      return 0;
-+}
-+
-+static int sifive_pwm_ptc_apply(struct pwm_chip *chip, struct pwm_device *dev,
-+                              const struct pwm_state *state)
-+{
-+      struct sifive_pwm_ptc_device *pwm = chip_to_sifive_ptc(chip);
-+      void __iomem *reg_addr;
-+      u32 pwm_clk_ns = 0;
-+      u32 data_hrc = 0;
-+      u32 data_lrc = 0;
-+      u32 period_data = 0;
-+      u32 duty_data = 0;
-+
-+      dev_dbg(pwm->chip.dev, "%s: no:%d\n", __func__, dev->hwpwm);
-+      dev_dbg(pwm->chip.dev, "period:%llu\n", state->period);
-+      dev_dbg(pwm->chip.dev, "duty_cycle:%llu\n", state->duty_cycle);
-+      dev_dbg(pwm->chip.dev, "polarity:%d\n", state->polarity);
-+      dev_dbg(pwm->chip.dev, "enabled:%d\n", state->enabled);
-+
-+      /* duty_cycle should be less or equal than period */
-+      if (state->duty_cycle > state->period)
-+              return -EINVAL;
-+
-+      /* calculate pwm real period (ns) */
-+      pwm_clk_ns = NS_1 / clk_get_rate(pwm->clk);
-+
-+      dev_dbg(pwm->chip.dev, "pwm_clk_ns:%u\n", pwm_clk_ns);
-+
-+      /* calculate period count */
-+      period_data = div_u64(state->period, pwm_clk_ns);
-+
-+      if (!state->enabled)
-+              /* if disabled, just set duty_data to 0, which means low level always */
-+              duty_data = 0;
-+      else
-+              /* calculate duty count */
-+              duty_data = div_u64(state->duty_cycle, pwm_clk_ns);
-+
-+      dev_dbg(pwm->chip.dev, "period_data:%u, duty_data:%u\n",
-+              period_data, duty_data);
-+
-+      if (state->polarity == PWM_POLARITY_NORMAL)
-+              /* calculate data_hrc */
-+              data_hrc = period_data - duty_data;
-+      else
-+              /* calculate data_hrc */
-+              data_hrc = duty_data;
-+
-+      data_lrc = period_data;
-+
-+      /* set hrc */
-+      reg_addr = REG_PTC_RPTC_HRC(pwm->regs, dev->hwpwm);
-+      dev_dbg(pwm->chip.dev, "%s: reg_addr:%p, data:%u\n",
-+              __func__, reg_addr, data_hrc);
-+
-+      iowrite32(data_hrc, reg_addr);
-+
-+      dev_dbg(pwm->chip.dev, "%s: hrc ok\n", __func__);
-+
-+      /* set lrc */
-+      reg_addr = REG_PTC_RPTC_LRC(pwm->regs, dev->hwpwm);
-+      dev_dbg(pwm->chip.dev, "%s: reg_addr:%p, data:%u\n",
-+              __func__, reg_addr, data_lrc);
-+
-+      iowrite32(data_lrc, reg_addr);
-+      dev_dbg(pwm->chip.dev, "%s: lrc ok\n", __func__);
-+
-+      /* Clear REG_RPTC_CNTR after setting period & duty_cycle */
-+      reg_addr = REG_PTC_RPTC_CNTR(pwm->regs, dev->hwpwm);
-+      iowrite32(0, reg_addr);
-+      return 0;
-+}
-+
-+static const struct pwm_ops sifive_pwm_ptc_ops = {
-+      .get_state      = sifive_pwm_ptc_get_state,
-+      .apply          = sifive_pwm_ptc_apply,
-+      .owner          = THIS_MODULE,
-+};
-+
-+static void sifive_pwm_ptc_disable_action(void *data)
-+{
-+      clk_disable_unprepare(data);
-+}
-+
-+static int sifive_pwm_ptc_probe(struct platform_device *pdev)
-+{
-+      struct device *dev = &pdev->dev;
-+      struct device_node *node = pdev->dev.of_node;
-+      struct sifive_pwm_ptc_device *pwm;
-+      struct pwm_chip *chip;
-+      struct reset_control *rst;
-+      int ret;
-+
-+      pwm = devm_kzalloc(dev, sizeof(*pwm), GFP_KERNEL);
-+      if (!pwm)
-+              return -ENOMEM;
-+
-+      platform_set_drvdata(pdev, pwm);
-+
-+      chip = &pwm->chip;
-+      chip->dev = dev;
-+      chip->ops = &sifive_pwm_ptc_ops;
-+
-+      /* how many parameters can be transferred to ptc, need to fix */
-+      chip->of_pwm_n_cells = 3;
-+      chip->base = -1;
-+
-+      /* get pwm channels count, max value is 8 */
-+      ret = of_property_read_u32(node, "starfive,npwm", &chip->npwm);
-+      if (ret < 0 || chip->npwm > MAX_PWM)
-+              chip->npwm = MAX_PWM;
-+
-+      dev_dbg(dev, "%s: npwm:0x%x\n", __func__, chip->npwm);
-+
-+      /* get IO base address */
-+      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 controller clock\n");
-+
-+      ret = clk_prepare_enable(pwm->clk);
-+      if (ret)
-+              return dev_err_probe(dev, ret, "Unable to enable clock\n");
-+
-+      ret = devm_add_action_or_reset(dev, sifive_pwm_ptc_disable_action, pwm->clk);
-+      if (ret)
-+              return ret;
-+
-+      rst = devm_reset_control_get_exclusive(dev, NULL);
-+      if (IS_ERR(rst))
-+              return dev_err_probe(dev, PTR_ERR(rst), "Unable to get reset\n");
-+
-+      ret = reset_control_deassert(rst);
-+      if (ret)
-+              return dev_err_probe(dev, ret, "Unable to deassert reset\n");
-+
-+      /*
-+       * after pwmchip_add it will show up as /sys/class/pwm/pwmchip0,
-+       * 0 is chip->base, pwm0 can be seen after running echo 0 > export
-+       */
-+      ret = devm_pwmchip_add(dev, chip);
-+      if (ret)
-+              return dev_err_probe(dev, ret, "cannot register PTC: %d\n", ret);
-+
-+      dev_dbg(dev, "SiFive PWM PTC chip registered %d PWMs\n", chip->npwm);
-+      return 0;
-+}
-+
-+static const struct of_device_id sifive_pwm_ptc_of_match[] = {
-+      { .compatible = "starfive,pwm0" },
-+      { /* sentinel */ }
-+};
-+MODULE_DEVICE_TABLE(of, sifive_pwm_ptc_of_match);
-+
-+static struct platform_driver sifive_pwm_ptc_driver = {
-+      .probe = sifive_pwm_ptc_probe,
-+      .driver = {
-+              .name = "pwm-sifive-ptc",
-+              .of_match_table = sifive_pwm_ptc_of_match,
-+      },
-+};
-+module_platform_driver(sifive_pwm_ptc_driver);
-+
-+MODULE_DESCRIPTION("SiFive PWM PTC driver");
-+MODULE_LICENSE("GPL v2");
diff --git a/target/linux/starfive/patches-6.6/1012-dt-bindings-reset-Add-StarFive-JH7100-audio-reset-de.patch b/target/linux/starfive/patches-6.6/1012-dt-bindings-reset-Add-StarFive-JH7100-audio-reset-de.patch
deleted file mode 100644 (file)
index 6986d4b..0000000
+++ /dev/null
@@ -1,48 +0,0 @@
-From 4f3335c302b7f944b61f564095505b3c7a1b62ee Mon Sep 17 00:00:00 2001
-From: Emil Renner Berthing <kernel@esmil.dk>
-Date: Sat, 20 Nov 2021 19:29:25 +0100
-Subject: [PATCH 1012/1024] dt-bindings: reset: Add StarFive JH7100 audio reset
- definitions
-
-Add all resets for the StarFive JH7100 audio reset controller.
-
-Signed-off-by: Emil Renner Berthing <kernel@esmil.dk>
----
- .../dt-bindings/reset/starfive-jh7100-audio.h | 31 +++++++++++++++++++
- 1 file changed, 31 insertions(+)
- create mode 100644 include/dt-bindings/reset/starfive-jh7100-audio.h
-
---- /dev/null
-+++ b/include/dt-bindings/reset/starfive-jh7100-audio.h
-@@ -0,0 +1,31 @@
-+/* SPDX-License-Identifier: GPL-2.0 OR MIT */
-+/*
-+ * Copyright (C) 2021 Emil Renner Berthing
-+ */
-+
-+#ifndef __DT_BINDINGS_RESET_STARFIVE_JH7100_AUDIO_H__
-+#define __DT_BINDINGS_RESET_STARFIVE_JH7100_AUDIO_H__
-+
-+#define JH7100_AUDRSTN_APB_BUS                0
-+#define JH7100_AUDRSTN_I2SADC_APB     1
-+#define JH7100_AUDRSTN_I2SADC_SRST    2
-+#define JH7100_AUDRSTN_PDM_APB                3
-+#define JH7100_AUDRSTN_I2SVAD_APB     4
-+#define JH7100_AUDRSTN_I2SVAD_SRST    5
-+#define JH7100_AUDRSTN_SPDIF_APB      6
-+#define JH7100_AUDRSTN_PWMDAC_APB     7
-+#define JH7100_AUDRSTN_I2SDAC_APB     8
-+#define JH7100_AUDRSTN_I2SDAC_SRST    9
-+#define JH7100_AUDRSTN_I2S1_APB               10
-+#define JH7100_AUDRSTN_I2S1_SRST      11
-+#define JH7100_AUDRSTN_I2SDAC16K_APB  12
-+#define JH7100_AUDRSTN_I2SDAC16K_SRST 13
-+#define JH7100_AUDRSTN_DMA1P_AHB      14
-+#define JH7100_AUDRSTN_USB_APB                15
-+#define JH7100_AUDRST_USB_AXI         16
-+#define JH7100_AUDRST_USB_PWRUP_RST_N 17
-+#define JH7100_AUDRST_USB_PONRST      18
-+
-+#define JH7100_AUDRSTN_END            19
-+
-+#endif /* __DT_BINDINGS_RESET_STARFIVE_JH7100_AUDIO_H__ */
diff --git a/target/linux/starfive/patches-6.6/1013-dt-bindings-reset-Add-starfive-jh7100-audrst-binding.patch b/target/linux/starfive/patches-6.6/1013-dt-bindings-reset-Add-starfive-jh7100-audrst-binding.patch
deleted file mode 100644 (file)
index 5eac29e..0000000
+++ /dev/null
@@ -1,56 +0,0 @@
-From 1e428568e486b40f78febddf2958ba27289bd49f Mon Sep 17 00:00:00 2001
-From: Emil Renner Berthing <kernel@esmil.dk>
-Date: Tue, 7 Dec 2021 21:48:51 +0100
-Subject: [PATCH 1013/1024] dt-bindings: reset: Add starfive,jh7100-audrst
- bindings
-
-Add bindings for the audio reset controller on the StarFive JH7100
-RISC-V SoC.
-
-Signed-off-by: Emil Renner Berthing <kernel@esmil.dk>
----
- .../reset/starfive,jh7100-audrst.yaml         | 38 +++++++++++++++++++
- 1 file changed, 38 insertions(+)
- create mode 100644 Documentation/devicetree/bindings/reset/starfive,jh7100-audrst.yaml
-
---- /dev/null
-+++ b/Documentation/devicetree/bindings/reset/starfive,jh7100-audrst.yaml
-@@ -0,0 +1,38 @@
-+# SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause
-+%YAML 1.2
-+---
-+$id: http://devicetree.org/schemas/reset/starfive,jh7100-audrst.yaml#
-+$schema: http://devicetree.org/meta-schemas/core.yaml#
-+
-+title: StarFive JH7100 SoC Audio Reset Controller Device Tree Bindings
-+
-+maintainers:
-+  - Emil Renner Berthing <kernel@esmil.dk>
-+
-+properties:
-+  compatible:
-+    enum:
-+      - starfive,jh7100-audrst
-+
-+  reg:
-+    maxItems: 1
-+
-+  "#reset-cells":
-+    const: 1
-+
-+required:
-+  - compatible
-+  - reg
-+  - "#reset-cells"
-+
-+additionalProperties: false
-+
-+examples:
-+  - |
-+    reset-controller@10490000 {
-+        compatible = "starfive,jh7100-audrst";
-+        reg = <0x10490000 0x10000>;
-+        #reset-cells = <1>;
-+    };
-+
-+...
diff --git a/target/linux/starfive/patches-6.6/1014-reset-starfive-Add-JH7100-audio-reset-driver.patch b/target/linux/starfive/patches-6.6/1014-reset-starfive-Add-JH7100-audio-reset-driver.patch
deleted file mode 100644 (file)
index 8b24eb3..0000000
+++ /dev/null
@@ -1,144 +0,0 @@
-From 91559ced47de9e6fb1e6dd65a5544fcc86dea806 Mon Sep 17 00:00:00 2001
-From: Emil Renner Berthing <kernel@esmil.dk>
-Date: Sat, 20 Nov 2021 19:30:49 +0100
-Subject: [PATCH 1014/1024] reset: starfive: Add JH7100 audio reset driver
-
-The audio resets are almost identical to the system resets, there are
-just fewer of them. So factor out and export a generic probe function,
-so most of the reset controller implementation can be shared.
-
-Signed-off-by: Emil Renner Berthing <kernel@esmil.dk>
----
- MAINTAINERS                                   |  2 +-
- drivers/reset/starfive/Kconfig                |  7 ++
- drivers/reset/starfive/Makefile               |  2 +
- .../starfive/reset-starfive-jh7100-audio.c    | 66 +++++++++++++++++++
- .../reset/starfive/reset-starfive-jh7100.h    | 16 +++++
- 5 files changed, 92 insertions(+), 1 deletion(-)
- create mode 100644 drivers/reset/starfive/reset-starfive-jh7100-audio.c
- create mode 100644 drivers/reset/starfive/reset-starfive-jh7100.h
-
---- a/MAINTAINERS
-+++ b/MAINTAINERS
-@@ -20556,7 +20556,7 @@ STARFIVE JH71X0 RESET CONTROLLER DRIVERS
- M:    Emil Renner Berthing <kernel@esmil.dk>
- M:    Hal Feng <hal.feng@starfivetech.com>
- S:    Maintained
--F:    Documentation/devicetree/bindings/reset/starfive,jh7100-reset.yaml
-+F:    Documentation/devicetree/bindings/reset/starfive,jh7100-*.yaml
- F:    drivers/reset/starfive/reset-starfive-jh71*
- F:    include/dt-bindings/reset/starfive?jh71*.h
---- a/drivers/reset/starfive/Kconfig
-+++ b/drivers/reset/starfive/Kconfig
-@@ -11,6 +11,13 @@ config RESET_STARFIVE_JH7100
-       help
-         This enables the reset controller driver for the StarFive JH7100 SoC.
-+config RESET_STARFIVE_JH7100_AUDIO
-+      tristate "StarFive JH7100 Audio Reset Driver"
-+      depends on RESET_STARFIVE_JH7100
-+      default m if SOC_STARFIVE
-+      help
-+        This enables the audio reset driver for the StarFive JH7100 SoC.
-+
- config RESET_STARFIVE_JH7110
-       bool "StarFive JH7110 Reset Driver"
-       depends on CLK_STARFIVE_JH7110_SYS
---- a/drivers/reset/starfive/Makefile
-+++ b/drivers/reset/starfive/Makefile
-@@ -2,4 +2,6 @@
- obj-$(CONFIG_RESET_STARFIVE_JH71X0)           += reset-starfive-jh71x0.o
- obj-$(CONFIG_RESET_STARFIVE_JH7100)           += reset-starfive-jh7100.o
-+obj-$(CONFIG_RESET_STARFIVE_JH7100_AUDIO)     += reset-starfive-jh7100-audio.o
-+
- obj-$(CONFIG_RESET_STARFIVE_JH7110)           += reset-starfive-jh7110.o
---- /dev/null
-+++ b/drivers/reset/starfive/reset-starfive-jh7100-audio.c
-@@ -0,0 +1,66 @@
-+// SPDX-License-Identifier: GPL-2.0-or-later
-+/*
-+ * Audio reset driver for the StarFive JH7100 SoC
-+ *
-+ * Copyright (C) 2021 Emil Renner Berthing <kernel@esmil.dk>
-+ */
-+
-+#include <linux/mod_devicetable.h>
-+#include <linux/module.h>
-+#include <linux/platform_device.h>
-+
-+#include "reset-starfive-jh71x0.h"
-+
-+#include <dt-bindings/reset/starfive-jh7100-audio.h>
-+
-+/* register offsets */
-+#define JH7100_AUDRST_ASSERT0 0x00
-+#define JH7100_AUDRST_STATUS0 0x04
-+
-+/*
-+ * Writing a 1 to the n'th bit of the ASSERT register asserts
-+ * line 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 u32 jh7100_audrst_asserted[1] = {
-+      BIT(JH7100_AUDRST_USB_AXI) |
-+      BIT(JH7100_AUDRST_USB_PWRUP_RST_N) |
-+      BIT(JH7100_AUDRST_USB_PONRST)
-+};
-+
-+static int jh7100_audrst_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_jh71x0_register(&pdev->dev, pdev->dev.of_node,
-+                                            base + JH7100_AUDRST_ASSERT0,
-+                                            base + JH7100_AUDRST_STATUS0,
-+                                            jh7100_audrst_asserted,
-+                                            JH7100_AUDRSTN_END,
-+                                            THIS_MODULE);
-+}
-+
-+static const struct of_device_id jh7100_audrst_dt_ids[] = {
-+      { .compatible = "starfive,jh7100-audrst" },
-+      { /* sentinel */ }
-+};
-+MODULE_DEVICE_TABLE(of, jh7100_audrst_dt_ids);
-+
-+static struct platform_driver jh7100_audrst_driver = {
-+      .probe = jh7100_audrst_probe,
-+      .driver = {
-+              .name = "jh7100-reset-audio",
-+              .of_match_table = jh7100_audrst_dt_ids,
-+      },
-+};
-+module_platform_driver(jh7100_audrst_driver);
-+
-+MODULE_AUTHOR("Emil Renner Berthing");
-+MODULE_DESCRIPTION("StarFive JH7100 audio reset driver");
-+MODULE_LICENSE("GPL");
---- /dev/null
-+++ b/drivers/reset/starfive/reset-starfive-jh7100.h
-@@ -0,0 +1,16 @@
-+// SPDX-License-Identifier: GPL-2.0-or-later
-+/*
-+ * Copyright (C) 2021 Emil Renner Berthing <kernel@esmil.dk>
-+ */
-+
-+#ifndef _RESET_STARFIVE_JH7100_H_
-+#define _RESET_STARFIVE_JH7100_H_
-+
-+#include <linux/platform_device.h>
-+
-+int reset_starfive_jh7100_generic_probe(struct platform_device *pdev,
-+                                      const u32 *asserted,
-+                                      unsigned int status_offset,
-+                                      unsigned int nr_resets);
-+
-+#endif
diff --git a/target/linux/starfive/patches-6.6/1015-RISC-V-Add-StarFive-JH7100-audio-reset-node.patch b/target/linux/starfive/patches-6.6/1015-RISC-V-Add-StarFive-JH7100-audio-reset-node.patch
deleted file mode 100644 (file)
index 521144c..0000000
+++ /dev/null
@@ -1,28 +0,0 @@
-From 418603fdce51212d4547aacfe2b4801fc5e61978 Mon Sep 17 00:00:00 2001
-From: Emil Renner Berthing <kernel@esmil.dk>
-Date: Sat, 20 Nov 2021 21:33:08 +0100
-Subject: [PATCH 1015/1024] RISC-V: Add StarFive JH7100 audio reset node
-
-Add device tree node for the audio resets on the StarFive JH7100 RISC-V
-SoC.
-
-Signed-off-by: Emil Renner Berthing <kernel@esmil.dk>
----
- arch/riscv/boot/dts/starfive/jh7100.dtsi | 6 ++++++
- 1 file changed, 6 insertions(+)
-
---- a/arch/riscv/boot/dts/starfive/jh7100.dtsi
-+++ b/arch/riscv/boot/dts/starfive/jh7100.dtsi
-@@ -168,6 +168,12 @@
-                       #clock-cells = <1>;
-               };
-+              audrst: reset-controller@10490000 {
-+                      compatible = "starfive,jh7100-audrst";
-+                      reg = <0x0 0x10490000 0x0 0x10000>;
-+                      #reset-cells = <1>;
-+              };
-+
-               clkgen: clock-controller@11800000 {
-                       compatible = "starfive,jh7100-clkgen";
-                       reg = <0x0 0x11800000 0x0 0x10000>;
diff --git a/target/linux/starfive/patches-6.6/1016-soc-sifive-ccache-Add-StarFive-JH7100-support.patch b/target/linux/starfive/patches-6.6/1016-soc-sifive-ccache-Add-StarFive-JH7100-support.patch
deleted file mode 100644 (file)
index 2906e16..0000000
+++ /dev/null
@@ -1,160 +0,0 @@
-From 8e090d271683d5869cdab0729f54a8af8c79c476 Mon Sep 17 00:00:00 2001
-From: Emil Renner Berthing <kernel@esmil.dk>
-Date: Tue, 31 Oct 2023 15:14:44 +0100
-Subject: [PATCH 1016/1024] soc: sifive: ccache: Add StarFive JH7100 support
-
-This adds support for the StarFive JH7100 SoC which also features this
-SiFive cache controller.
-
-The JH7100 has non-coherent DMAs but predate the standard RISC-V Zicbom
-exension, so instead we need to use this cache controller for
-non-standard cache management operations.
-
-Unfortunately the interrupt for uncorrected data is broken on the JH7100
-and fires continuously, so add a quirk to not register a handler for it.
-
-Signed-off-by: Emil Renner Berthing <kernel@esmil.dk>
-Signed-off-by: Conor Dooley <conor.dooley@microchip.com>
----
- drivers/soc/sifive/sifive_ccache.c | 62 +++++++++++++++++++++++++++++-
- 1 file changed, 60 insertions(+), 2 deletions(-)
-
---- a/drivers/soc/sifive/sifive_ccache.c
-+++ b/drivers/soc/sifive/sifive_ccache.c
-@@ -8,13 +8,16 @@
- #define pr_fmt(fmt) "CCACHE: " fmt
-+#include <linux/align.h>
- #include <linux/debugfs.h>
- #include <linux/interrupt.h>
- #include <linux/of_irq.h>
- #include <linux/of_address.h>
- #include <linux/device.h>
- #include <linux/bitfield.h>
-+#include <asm/cacheflush.h>
- #include <asm/cacheinfo.h>
-+#include <asm/dma-noncoherent.h>
- #include <soc/sifive/sifive_ccache.h>
- #define SIFIVE_CCACHE_DIRECCFIX_LOW 0x100
-@@ -39,10 +42,14 @@
- #define SIFIVE_CCACHE_CONFIG_SETS_MASK GENMASK_ULL(23, 16)
- #define SIFIVE_CCACHE_CONFIG_BLKS_MASK GENMASK_ULL(31, 24)
-+#define SIFIVE_CCACHE_FLUSH64 0x200
-+#define SIFIVE_CCACHE_FLUSH32 0x240
-+
- #define SIFIVE_CCACHE_WAYENABLE 0x08
- #define SIFIVE_CCACHE_ECCINJECTERR 0x40
- #define SIFIVE_CCACHE_MAX_ECCINTR 4
-+#define SIFIVE_CCACHE_LINE_SIZE 64
- static void __iomem *ccache_base;
- static int g_irq[SIFIVE_CCACHE_MAX_ECCINTR];
-@@ -56,6 +63,11 @@ enum {
-       DIR_UNCORR,
- };
-+enum {
-+      QUIRK_NONSTANDARD_CACHE_OPS     = BIT(0),
-+      QUIRK_BROKEN_DATA_UNCORR        = BIT(1),
-+};
-+
- #ifdef CONFIG_DEBUG_FS
- static struct dentry *sifive_test;
-@@ -106,6 +118,8 @@ static void ccache_config_read(void)
- static const struct of_device_id sifive_ccache_ids[] = {
-       { .compatible = "sifive,fu540-c000-ccache" },
-       { .compatible = "sifive,fu740-c000-ccache" },
-+      { .compatible = "starfive,jh7100-ccache",
-+        .data = (void *)(QUIRK_NONSTANDARD_CACHE_OPS | QUIRK_BROKEN_DATA_UNCORR) },
-       { .compatible = "sifive,ccache0" },
-       { /* end of table */ }
- };
-@@ -124,6 +138,34 @@ int unregister_sifive_ccache_error_notif
- }
- EXPORT_SYMBOL_GPL(unregister_sifive_ccache_error_notifier);
-+#ifdef CONFIG_RISCV_NONSTANDARD_CACHE_OPS
-+static void ccache_flush_range(phys_addr_t start, size_t len)
-+{
-+      phys_addr_t end = start + len;
-+      phys_addr_t line;
-+
-+      if (!len)
-+              return;
-+
-+      mb();
-+      for (line = ALIGN_DOWN(start, SIFIVE_CCACHE_LINE_SIZE); line < end;
-+                      line += SIFIVE_CCACHE_LINE_SIZE) {
-+#ifdef CONFIG_32BIT
-+              writel(line >> 4, ccache_base + SIFIVE_CCACHE_FLUSH32);
-+#else
-+              writeq(line, ccache_base + SIFIVE_CCACHE_FLUSH64);
-+#endif
-+              mb();
-+      }
-+}
-+
-+static const struct riscv_nonstd_cache_ops ccache_mgmt_ops __initconst = {
-+      .wback = &ccache_flush_range,
-+      .inv = &ccache_flush_range,
-+      .wback_inv = &ccache_flush_range,
-+};
-+#endif /* CONFIG_RISCV_NONSTANDARD_CACHE_OPS */
-+
- static int ccache_largest_wayenabled(void)
- {
-       return readl(ccache_base + SIFIVE_CCACHE_WAYENABLE) & 0xFF;
-@@ -210,11 +252,15 @@ static int __init sifive_ccache_init(voi
-       struct device_node *np;
-       struct resource res;
-       int i, rc, intr_num;
-+      const struct of_device_id *match;
-+      unsigned long quirks;
--      np = of_find_matching_node(NULL, sifive_ccache_ids);
-+      np = of_find_matching_node_and_match(NULL, sifive_ccache_ids, &match);
-       if (!np)
-               return -ENODEV;
-+      quirks = (uintptr_t)match->data;
-+
-       if (of_address_to_resource(np, 0, &res)) {
-               rc = -ENODEV;
-               goto err_node_put;
-@@ -240,6 +286,10 @@ static int __init sifive_ccache_init(voi
-       for (i = 0; i < intr_num; i++) {
-               g_irq[i] = irq_of_parse_and_map(np, i);
-+
-+              if (i == DATA_UNCORR && (quirks & QUIRK_BROKEN_DATA_UNCORR))
-+                      continue;
-+
-               rc = request_irq(g_irq[i], ccache_int_handler, 0, "ccache_ecc",
-                                NULL);
-               if (rc) {
-@@ -249,6 +299,14 @@ static int __init sifive_ccache_init(voi
-       }
-       of_node_put(np);
-+#ifdef CONFIG_RISCV_NONSTANDARD_CACHE_OPS
-+      if (quirks & QUIRK_NONSTANDARD_CACHE_OPS) {
-+              riscv_cbom_block_size = SIFIVE_CCACHE_LINE_SIZE;
-+              riscv_noncoherent_supported();
-+              riscv_noncoherent_register_cache_ops(&ccache_mgmt_ops);
-+      }
-+#endif
-+
-       ccache_config_read();
-       ccache_cache_ops.get_priv_group = ccache_get_priv_group;
-@@ -269,4 +327,4 @@ err_node_put:
-       return rc;
- }
--device_initcall(sifive_ccache_init);
-+arch_initcall(sifive_ccache_init);
diff --git a/target/linux/starfive/patches-6.6/1017-riscv-errata-Add-StarFive-JH7100-errata.patch b/target/linux/starfive/patches-6.6/1017-riscv-errata-Add-StarFive-JH7100-errata.patch
deleted file mode 100644 (file)
index 91b3adf..0000000
+++ /dev/null
@@ -1,44 +0,0 @@
-From 30fb5963f4cf3b7d114a8212358147615480685c Mon Sep 17 00:00:00 2001
-From: Emil Renner Berthing <emil.renner.berthing@canonical.com>
-Date: Thu, 30 Nov 2023 16:19:25 +0100
-Subject: [PATCH 1017/1024] riscv: errata: Add StarFive JH7100 errata
-
-This not really an errata, but since the JH7100 was made before
-the standard Zicbom extension it needs the DMA_GLOBAL_POOL and
-RISCV_NONSTANDARD_CACHE_OPS enabled to work correctly.
-
-Acked-by: Conor Dooley <conor.dooley@microchip.com>
-Signed-off-by: Emil Renner Berthing <emil.renner.berthing@canonical.com>
-Reviewed-by: Palmer Dabbelt <palmer@rivosinc.com>
-Acked-by: Palmer Dabbelt <palmer@rivosinc.com>
-Signed-off-by: Conor Dooley <conor.dooley@microchip.com>
----
- arch/riscv/Kconfig.errata | 17 +++++++++++++++++
- 1 file changed, 17 insertions(+)
-
---- a/arch/riscv/Kconfig.errata
-+++ b/arch/riscv/Kconfig.errata
-@@ -53,6 +53,23 @@ config ERRATA_SIFIVE_CIP_1200
-         If you don't know what to do here, say "Y".
-+config ERRATA_STARFIVE_JH7100
-+      bool "StarFive JH7100 support"
-+      depends on ARCH_STARFIVE && NONPORTABLE
-+      select DMA_GLOBAL_POOL
-+      select RISCV_DMA_NONCOHERENT
-+      select RISCV_NONSTANDARD_CACHE_OPS
-+      select SIFIVE_CCACHE
-+      default n
-+      help
-+        The StarFive JH7100 was a test chip for the JH7110 and has
-+        caches that are non-coherent with respect to peripheral DMAs.
-+        It was designed before the Zicbom extension so needs non-standard
-+        cache operations through the SiFive cache controller.
-+
-+        Say "Y" if you want to support the BeagleV Starlight and/or
-+        StarFive VisionFive V1 boards.
-+
- config ERRATA_THEAD
-       bool "T-HEAD errata"
-       depends on RISCV_ALTERNATIVE
diff --git a/target/linux/starfive/patches-6.6/1018-riscv-dts-starfive-Mark-the-JH7100-as-having-non-coh.patch b/target/linux/starfive/patches-6.6/1018-riscv-dts-starfive-Mark-the-JH7100-as-having-non-coh.patch
deleted file mode 100644 (file)
index 0b223c5..0000000
+++ /dev/null
@@ -1,26 +0,0 @@
-From 29e4bc0fafd9add93acc967f3992948b3afe7176 Mon Sep 17 00:00:00 2001
-From: Emil Renner Berthing <kernel@esmil.dk>
-Date: Thu, 30 Nov 2023 16:19:27 +0100
-Subject: [PATCH 1018/1024] riscv: dts: starfive: Mark the JH7100 as having
- non-coherent DMAs
-
-The StarFive JH7100 SoC has non-coherent device DMAs, so mark the
-soc bus as such.
-
-Link: https://github.com/starfive-tech/JH7100_Docs/blob/main/JH7100%20Cache%20Coherence%20V1.0.pdf
-Signed-off-by: Emil Renner Berthing <kernel@esmil.dk>
-Signed-off-by: Conor Dooley <conor.dooley@microchip.com>
----
- arch/riscv/boot/dts/starfive/jh7100.dtsi | 1 +
- 1 file changed, 1 insertion(+)
-
---- a/arch/riscv/boot/dts/starfive/jh7100.dtsi
-+++ b/arch/riscv/boot/dts/starfive/jh7100.dtsi
-@@ -138,6 +138,7 @@
-               interrupt-parent = <&plic>;
-               #address-cells = <2>;
-               #size-cells = <2>;
-+              dma-noncoherent;
-               ranges;
-               clint: clint@2000000 {
diff --git a/target/linux/starfive/patches-6.6/1019-riscv-dts-starfive-Add-JH7100-cache-controller.patch b/target/linux/starfive/patches-6.6/1019-riscv-dts-starfive-Add-JH7100-cache-controller.patch
deleted file mode 100644 (file)
index cdc63fa..0000000
+++ /dev/null
@@ -1,50 +0,0 @@
-From e1918356dcc285eb7c50f271795e6fcc18d6c092 Mon Sep 17 00:00:00 2001
-From: Emil Renner Berthing <emil.renner.berthing@canonical.com>
-Date: Thu, 30 Nov 2023 16:19:28 +0100
-Subject: [PATCH 1019/1024] riscv: dts: starfive: Add JH7100 cache controller
-
-The StarFive JH7100 SoC also features the SiFive L2 cache controller,
-so add the device tree nodes for it.
-
-Signed-off-by: Emil Renner Berthing <emil.renner.berthing@canonical.com>
-Signed-off-by: Conor Dooley <conor.dooley@microchip.com>
----
- arch/riscv/boot/dts/starfive/jh7100.dtsi | 13 +++++++++++++
- 1 file changed, 13 insertions(+)
-
---- a/arch/riscv/boot/dts/starfive/jh7100.dtsi
-+++ b/arch/riscv/boot/dts/starfive/jh7100.dtsi
-@@ -32,6 +32,7 @@
-                       i-tlb-sets = <1>;
-                       i-tlb-size = <32>;
-                       mmu-type = "riscv,sv39";
-+                      next-level-cache = <&ccache>;
-                       riscv,isa = "rv64imafdc";
-                       tlb-split;
-@@ -57,6 +58,7 @@
-                       i-tlb-sets = <1>;
-                       i-tlb-size = <32>;
-                       mmu-type = "riscv,sv39";
-+                      next-level-cache = <&ccache>;
-                       riscv,isa = "rv64imafdc";
-                       tlb-split;
-@@ -148,6 +150,17 @@
-                                              &cpu1_intc 3 &cpu1_intc 7>;
-               };
-+              ccache: cache-controller@2010000 {
-+                      compatible = "starfive,jh7100-ccache", "sifive,ccache0", "cache";
-+                      reg = <0x0 0x2010000 0x0 0x1000>;
-+                      interrupts = <128>, <130>, <131>, <129>;
-+                      cache-block-size = <64>;
-+                      cache-level = <2>;
-+                      cache-sets = <2048>;
-+                      cache-size = <2097152>;
-+                      cache-unified;
-+              };
-+
-               plic: interrupt-controller@c000000 {
-                       compatible = "starfive,jh7100-plic", "sifive,plic-1.0.0";
-                       reg = <0x0 0xc000000 0x0 0x4000000>;
diff --git a/target/linux/starfive/patches-6.6/1020-riscv-dts-starfive-Add-pool-for-coherent-DMA-memory-.patch b/target/linux/starfive/patches-6.6/1020-riscv-dts-starfive-Add-pool-for-coherent-DMA-memory-.patch
deleted file mode 100644 (file)
index c9ba388..0000000
+++ /dev/null
@@ -1,61 +0,0 @@
-From 3cbd661b811bda9a33253f65b5cf0c25b8c5447f Mon Sep 17 00:00:00 2001
-From: Emil Renner Berthing <emil.renner.berthing@canonical.com>
-Date: Thu, 30 Nov 2023 16:19:29 +0100
-Subject: [PATCH 1020/1024] riscv: dts: starfive: Add pool for coherent DMA
- memory on JH7100 boards
-
-The StarFive JH7100 SoC has non-coherent device DMAs, but most drivers
-expect to be able to allocate coherent memory for DMA descriptors and
-such. However on the JH7100 DDR memory appears twice in the physical
-memory map, once cached and once uncached:
-
-  0x00_8000_0000 - 0x08_7fff_ffff : Off chip DDR memory, cached
-  0x10_0000_0000 - 0x17_ffff_ffff : Off chip DDR memory, uncached
-
-To use this uncached region we create a global DMA memory pool there and
-reserve the corresponding area in the cached region.
-
-However the uncached region is fully above the 32bit address limit, so add
-a dma-ranges map so the DMA address used for peripherals is still in the
-regular cached region below the limit.
-
-Link: https://github.com/starfive-tech/JH7100_Docs/blob/main/JH7100%20Data%20Sheet%20V01.01.04-EN%20(4-21-2021).pdf
-Signed-off-by: Emil Renner Berthing <emil.renner.berthing@canonical.com>
-Signed-off-by: Conor Dooley <conor.dooley@microchip.com>
----
- .../boot/dts/starfive/jh7100-common.dtsi      | 24 +++++++++++++++++++
- 1 file changed, 24 insertions(+)
-
---- a/arch/riscv/boot/dts/starfive/jh7100-common.dtsi
-+++ b/arch/riscv/boot/dts/starfive/jh7100-common.dtsi
-@@ -39,6 +39,30 @@
-                       label = "ack";
-               };
-       };
-+
-+      reserved-memory {
-+              #address-cells = <2>;
-+              #size-cells = <2>;
-+              ranges;
-+
-+              dma-reserved@fa000000 {
-+                      reg = <0x0 0xfa000000 0x0 0x1000000>;
-+                      no-map;
-+              };
-+
-+              linux,dma@107a000000 {
-+                      compatible = "shared-dma-pool";
-+                      reg = <0x10 0x7a000000 0x0 0x1000000>;
-+                      no-map;
-+                      linux,dma-default;
-+              };
-+      };
-+
-+      soc {
-+              dma-ranges = <0x00 0x80000000 0x00 0x80000000 0x00 0x7a000000>,
-+                           <0x00 0xfa000000 0x10 0x7a000000 0x00 0x01000000>,
-+                           <0x00 0xfb000000 0x00 0xfb000000 0x07 0x85000000>;
-+      };
- };
- &gpio {
diff --git a/target/linux/starfive/patches-6.6/1021-riscv-dts-starfive-Add-JH7100-MMC-nodes.patch b/target/linux/starfive/patches-6.6/1021-riscv-dts-starfive-Add-JH7100-MMC-nodes.patch
deleted file mode 100644 (file)
index fb3ba52..0000000
+++ /dev/null
@@ -1,49 +0,0 @@
-From 7be159c760aa8a1ece1354892af215b2f8c21152 Mon Sep 17 00:00:00 2001
-From: Emil Renner Berthing <emil.renner.berthing@canonical.com>
-Date: Thu, 30 Nov 2023 16:19:30 +0100
-Subject: [PATCH 1021/1024] riscv: dts: starfive: Add JH7100 MMC nodes
-
-Add device tree nodes for the Synopsis MMC controllers on the
-StarFive JH7100 SoC.
-
-Signed-off-by: Emil Renner Berthing <emil.renner.berthing@canonical.com>
-Signed-off-by: Conor Dooley <conor.dooley@microchip.com>
----
- arch/riscv/boot/dts/starfive/jh7100.dtsi | 26 ++++++++++++++++++++++++
- 1 file changed, 26 insertions(+)
-
---- a/arch/riscv/boot/dts/starfive/jh7100.dtsi
-+++ b/arch/riscv/boot/dts/starfive/jh7100.dtsi
-@@ -188,6 +188,32 @@
-                       #reset-cells = <1>;
-               };
-+              sdio0: mmc@10000000 {
-+                      compatible = "snps,dw-mshc";
-+                      reg = <0x0 0x10000000 0x0 0x10000>;
-+                      clocks = <&clkgen JH7100_CLK_SDIO0_AHB>,
-+                               <&clkgen JH7100_CLK_SDIO0_CCLKINT_INV>;
-+                      clock-names = "biu", "ciu";
-+                      interrupts = <4>;
-+                      data-addr = <0>;
-+                      fifo-depth = <32>;
-+                      fifo-watermark-aligned;
-+                      status = "disabled";
-+              };
-+
-+              sdio1: mmc@10010000 {
-+                      compatible = "snps,dw-mshc";
-+                      reg = <0x0 0x10010000 0x0 0x10000>;
-+                      clocks = <&clkgen JH7100_CLK_SDIO1_AHB>,
-+                               <&clkgen JH7100_CLK_SDIO1_CCLKINT_INV>;
-+                      clock-names = "biu", "ciu";
-+                      interrupts = <5>;
-+                      data-addr = <0>;
-+                      fifo-depth = <32>;
-+                      fifo-watermark-aligned;
-+                      status = "disabled";
-+              };
-+
-               clkgen: clock-controller@11800000 {
-                       compatible = "starfive,jh7100-clkgen";
-                       reg = <0x0 0x11800000 0x0 0x10000>;
diff --git a/target/linux/starfive/patches-6.6/1022-riscv-dts-starfive-Enable-SD-card-on-JH7100-boards.patch b/target/linux/starfive/patches-6.6/1022-riscv-dts-starfive-Enable-SD-card-on-JH7100-boards.patch
deleted file mode 100644 (file)
index bf380eb..0000000
+++ /dev/null
@@ -1,85 +0,0 @@
-From 015edaccef82200d913d5f1e99fd95641f526bc6 Mon Sep 17 00:00:00 2001
-From: Emil Renner Berthing <emil.renner.berthing@canonical.com>
-Date: Thu, 30 Nov 2023 16:19:31 +0100
-Subject: [PATCH 1022/1024] riscv: dts: starfive: Enable SD-card on JH7100
- boards
-
-Add pinctrl and MMC device tree nodes for the SD-card on the
-BeagleV Starlight and StarFive VisionFive V1 boards.
-
-Signed-off-by: Emil Renner Berthing <emil.renner.berthing@canonical.com>
-Signed-off-by: Conor Dooley <conor.dooley@microchip.com>
----
- .../boot/dts/starfive/jh7100-common.dtsi      | 47 +++++++++++++++++++
- 1 file changed, 47 insertions(+)
-
---- a/arch/riscv/boot/dts/starfive/jh7100-common.dtsi
-+++ b/arch/riscv/boot/dts/starfive/jh7100-common.dtsi
-@@ -12,6 +12,7 @@
- / {
-       aliases {
-+              mmc0 = &sdio0;
-               serial0 = &uart3;
-       };
-@@ -108,6 +109,43 @@
-               };
-       };
-+      sdio0_pins: sdio0-0 {
-+              clk-pins {
-+                      pinmux = <GPIOMUX(54, GPO_SDIO0_PAD_CCLK_OUT,
-+                                GPO_ENABLE, GPI_NONE)>;
-+                      bias-disable;
-+                      input-disable;
-+                      input-schmitt-disable;
-+              };
-+              sdio-pins {
-+                      pinmux = <GPIOMUX(55, GPO_LOW, GPO_DISABLE,
-+                                GPI_SDIO0_PAD_CARD_DETECT_N)>,
-+                               <GPIOMUX(53,
-+                                GPO_SDIO0_PAD_CCMD_OUT,
-+                                GPO_SDIO0_PAD_CCMD_OEN,
-+                                GPI_SDIO0_PAD_CCMD_IN)>,
-+                               <GPIOMUX(49,
-+                                GPO_SDIO0_PAD_CDATA_OUT_BIT0,
-+                                GPO_SDIO0_PAD_CDATA_OEN_BIT0,
-+                                GPI_SDIO0_PAD_CDATA_IN_BIT0)>,
-+                               <GPIOMUX(50,
-+                                GPO_SDIO0_PAD_CDATA_OUT_BIT1,
-+                                GPO_SDIO0_PAD_CDATA_OEN_BIT1,
-+                                GPI_SDIO0_PAD_CDATA_IN_BIT1)>,
-+                               <GPIOMUX(51,
-+                                GPO_SDIO0_PAD_CDATA_OUT_BIT2,
-+                                GPO_SDIO0_PAD_CDATA_OEN_BIT2,
-+                                GPI_SDIO0_PAD_CDATA_IN_BIT2)>,
-+                               <GPIOMUX(52,
-+                                GPO_SDIO0_PAD_CDATA_OUT_BIT3,
-+                                GPO_SDIO0_PAD_CDATA_OEN_BIT3,
-+                                GPI_SDIO0_PAD_CDATA_IN_BIT3)>;
-+                      bias-pull-up;
-+                      input-enable;
-+                      input-schmitt-enable;
-+              };
-+      };
-+
-       uart3_pins: uart3-0 {
-               rx-pins {
-                       pinmux = <GPIOMUX(13, GPO_LOW, GPO_DISABLE,
-@@ -178,6 +216,15 @@
-       clock-frequency = <27000000>;
- };
-+&sdio0 {
-+      broken-cd;
-+      bus-width = <4>;
-+      cap-sd-highspeed;
-+      pinctrl-names = "default";
-+      pinctrl-0 = <&sdio0_pins>;
-+      status = "okay";
-+};
-+
- &uart3 {
-       pinctrl-names = "default";
-       pinctrl-0 = <&uart3_pins>;
diff --git a/target/linux/starfive/patches-6.6/1023-riscv-errata-Make-ERRATA_STARFIVE_JH7100-depend-on-D.patch b/target/linux/starfive/patches-6.6/1023-riscv-errata-Make-ERRATA_STARFIVE_JH7100-depend-on-D.patch
deleted file mode 100644 (file)
index 2b782e1..0000000
+++ /dev/null
@@ -1,33 +0,0 @@
-From 1e70a0772165dd552f82434c9072dabfaaaf4c2a Mon Sep 17 00:00:00 2001
-From: Emil Renner Berthing <emil.renner.berthing@canonical.com>
-Date: Fri, 15 Dec 2023 20:09:09 +0100
-Subject: [PATCH 1023/1024] riscv: errata: Make ERRATA_STARFIVE_JH7100 depend
- on !DMA_DIRECT_REMAP
-
-Similar to the Renesas RZ/Five[1] the JH7100 SoC needs the non-portable
-CONFIG_DMA_GLOBAL_POOL enabled which is incompatible with DMA_DIRECT_REMAP
-selected by RISCV_ISA_ZICBOM.
-
-[1]: commit 31b2daea0764 ("soc: renesas: Make RZ/Five depend on !DMA_DIRECT_REMAP")
-
-Link: https://lore.kernel.org/all/24942b4d-d16a-463f-b39a-f9dfcb89d742@infradead.org/
-Fixes: 64fc984a8a54 ("riscv: errata: Add StarFive JH7100 errata")
-Signed-off-by: Emil Renner Berthing <emil.renner.berthing@canonical.com>
-Signed-off-by: Conor Dooley <conor.dooley@microchip.com>
----
- arch/riscv/Kconfig.errata | 4 +++-
- 1 file changed, 3 insertions(+), 1 deletion(-)
-
---- a/arch/riscv/Kconfig.errata
-+++ b/arch/riscv/Kconfig.errata
-@@ -55,7 +55,9 @@ config ERRATA_SIFIVE_CIP_1200
- config ERRATA_STARFIVE_JH7100
-       bool "StarFive JH7100 support"
--      depends on ARCH_STARFIVE && NONPORTABLE
-+      depends on ARCH_STARFIVE
-+      depends on !DMA_DIRECT_REMAP
-+      depends on NONPORTABLE
-       select DMA_GLOBAL_POOL
-       select RISCV_DMA_NONCOHERENT
-       select RISCV_NONSTANDARD_CACHE_OPS
diff --git a/target/linux/starfive/patches-6.6/1024-riscv-dts-Add-full-JH7100-Starlight-and-VisionFive-s.patch b/target/linux/starfive/patches-6.6/1024-riscv-dts-Add-full-JH7100-Starlight-and-VisionFive-s.patch
deleted file mode 100644 (file)
index b20c2d8..0000000
+++ /dev/null
@@ -1,1138 +0,0 @@
-From 782f99cc437d975c9ef5a1f351bb8fb83d50039b Mon Sep 17 00:00:00 2001
-From: Emil Renner Berthing <kernel@esmil.dk>
-Date: Sun, 1 Sep 2024 12:43:01 +0000
-Subject: [PATCH 1024/1024] riscv: dts: Add full JH7100, Starlight and
- VisionFive support
-
-Based on the device tree in https://github.com/starfive-tech/u-boot/
-with contributions from:
-yanhong.wang <yanhong.wang@starfivetech.com>
-Huan.Feng <huan.feng@starfivetech.com>
-ke.zhu <ke.zhu@starfivetech.com>
-yiming.li <yiming.li@starfivetech.com>
-jack.zhu <jack.zhu@starfivetech.com>
-Samin Guo <samin.guo@starfivetech.com>
-Chenjieqin <Jessica.Chen@starfivetech.com>
-bo.li <bo.li@starfivetech.com>
-
-Rearranged, cleanups, fixes, pins and resets added by Emil.
-Cleanups, fixes, clocks added by Geert.
-Cleanups and GPIO fixes from Drew.
-Thermal zone added by Stephen.
-PWM pins added by Jianlong.
-cpu-map added by Jonas.
-
-Signed-off-by: Emil Renner Berthing <kernel@esmil.dk>
-Signed-off-by: Geert Uytterhoeven <geert@linux-m68k.org>
-Signed-off-by: Stephen L Arnold <nerdboy@gentoo.org>
-Signed-off-by: Drew Fustini <drew@beagleboard.org>
-Signed-off-by: Jianlong Huang <jianlong.huang@starfivetech.com>
-Signed-off-by: Jonas Hahnfeld <hahnjo@hahnjo.de>
----
- .../dts/starfive/jh7100-beaglev-starlight.dts |  16 +
- .../boot/dts/starfive/jh7100-common.dtsi      | 432 +++++++++++++++
- .../jh7100-starfive-visionfive-v1.dts         |  19 +
- arch/riscv/boot/dts/starfive/jh7100.dtsi      | 503 ++++++++++++++++++
- 4 files changed, 970 insertions(+)
-
---- a/arch/riscv/boot/dts/starfive/jh7100-beaglev-starlight.dts
-+++ b/arch/riscv/boot/dts/starfive/jh7100-beaglev-starlight.dts
-@@ -6,8 +6,24 @@
- /dts-v1/;
- #include "jh7100-common.dtsi"
-+#include <dt-bindings/gpio/gpio.h>
- / {
-       model = "BeagleV Starlight Beta";
-       compatible = "beagle,beaglev-starlight-jh7100-r0", "starfive,jh7100";
- };
-+
-+&gmac {
-+      snps,reset-gpios = <&gpio 63 GPIO_ACTIVE_LOW>;
-+};
-+
-+&gpio {
-+      /* don't reset gpio mux for serial console on uart3 */
-+      starfive,keep-gpiomux = <13 14>;
-+};
-+
-+&mdio {
-+      phy: ethernet-phy@7 {
-+              reg = <7>;
-+      };
-+};
---- a/arch/riscv/boot/dts/starfive/jh7100-common.dtsi
-+++ b/arch/riscv/boot/dts/starfive/jh7100-common.dtsi
-@@ -14,6 +14,7 @@
-       aliases {
-               mmc0 = &sdio0;
-               serial0 = &uart3;
-+              serial1 = &uart0;
-       };
-       chosen {
-@@ -64,9 +65,174 @@
-                            <0x00 0xfa000000 0x10 0x7a000000 0x00 0x01000000>,
-                            <0x00 0xfb000000 0x00 0xfb000000 0x07 0x85000000>;
-       };
-+
-+      reserved-memory {
-+              #address-cells = <2>;
-+              #size-cells = <2>;
-+              ranges;
-+
-+              linux,cma {
-+                      compatible = "shared-dma-pool";
-+                      reusable;
-+                      size = <0x0 0x28000000>;
-+                      alignment = <0x0 0x1000>;
-+                      alloc-ranges = <0x0 0xa0000000 0x0 0x28000000>;
-+                      linux,cma-default;
-+              };
-+
-+              jpu_reserved: framebuffer@c9000000 {
-+                      reg = <0x0 0xc9000000 0x0 0x4000000>;
-+              };
-+
-+              nvdla_reserved: framebuffer@d0000000 {
-+                      no-map;
-+                      reg = <0x0 0xd0000000 0x0 0x28000000>;
-+              };
-+
-+              vin_reserved: framebuffer@f9000000 {
-+                      compatible = "shared-dma-pool";
-+                      no-map;
-+                      reg = <0x0 0xf9000000 0x0 0x1000000>;
-+              };
-+
-+              sffb_reserved: framebuffer@fb000000 {
-+                      compatible = "shared-dma-pool";
-+                      no-map;
-+                      reg = <0x0 0xfb000000 0x0 0x2000000>;
-+              };
-+      };
-+
-+      wifi_pwrseq: wifi-pwrseq {
-+              compatible = "mmc-pwrseq-simple";
-+              reset-gpios = <&gpio 37 GPIO_ACTIVE_LOW>;
-+      };
-+};
-+
-+&display {
-+      memory-region = <&sffb_reserved>;
-+      status = "okay";
-+};
-+
-+&crtc {
-+      ddr-format = <4>; //<WIN_FMT_RGB565>;
-+      status = "okay";
-+
-+      port: port@0 {
-+              reg = <0>;
-+
-+              crtc_0_out: endpoint {
-+                      remote-endpoint = <&hdmi_input0>;
-+              };
-+      };
-+};
-+
-+&encoder {
-+      encoder-type = <2>; // 2-TMDS, 3-LVDS, 6-DSI, 8-DPI
-+      status = "okay";
-+
-+      ports {
-+              port@0 {
-+                      hdmi_out: endpoint {
-+                              remote-endpoint = <&tda998x_0_input>;
-+                      };
-+              };
-+
-+              port@1 {
-+                      hdmi_input0: endpoint {
-+                              remote-endpoint = <&crtc_0_out>;
-+                      };
-+              };
-+
-+      };
-+};
-+
-+&gmac {
-+      starfive,gtxclk-dlychain = <4>;
-+      pinctrl-names = "default";
-+      pinctrl-0 = <&gmac_pins>;
-+      phy-mode = "rgmii-txid";
-+      phy-handle = <&phy>;
-+      status = "okay";
-+
-+      mdio: mdio {
-+              #address-cells = <1>;
-+              #size-cells = <0>;
-+              compatible = "snps,dwmac-mdio";
-+      };
- };
- &gpio {
-+      gmac_pins: gmac-0 {
-+              gtxclk-pins {
-+                      pins = <PAD_FUNC_SHARE(115)>;
-+                      bias-pull-up;
-+                      drive-strength = <35>;
-+                      input-enable;
-+                      input-schmitt-enable;
-+                      slew-rate = <0>;
-+              };
-+              miitxclk-pins {
-+                      pins = <PAD_FUNC_SHARE(116)>;
-+                      bias-pull-up;
-+                      drive-strength = <14>;
-+                      input-enable;
-+                      input-schmitt-disable;
-+                      slew-rate = <0>;
-+              };
-+              tx-pins {
-+                      pins = <PAD_FUNC_SHARE(117)>,
-+                             <PAD_FUNC_SHARE(119)>,
-+                             <PAD_FUNC_SHARE(120)>,
-+                             <PAD_FUNC_SHARE(121)>,
-+                             <PAD_FUNC_SHARE(122)>,
-+                             <PAD_FUNC_SHARE(123)>,
-+                             <PAD_FUNC_SHARE(124)>,
-+                             <PAD_FUNC_SHARE(125)>,
-+                             <PAD_FUNC_SHARE(126)>;
-+                      bias-pull-up;
-+                      drive-strength = <35>;
-+                      input-disable;
-+                      input-schmitt-disable;
-+                      slew-rate = <0>;
-+              };
-+              rxclk-pins {
-+                      pins = <PAD_FUNC_SHARE(127)>;
-+                      bias-pull-up;
-+                      drive-strength = <14>;
-+                      input-enable;
-+                      input-schmitt-disable;
-+                      slew-rate = <6>;
-+              };
-+              rxer-pins {
-+                      pins = <PAD_FUNC_SHARE(129)>;
-+                      bias-pull-up;
-+                      drive-strength = <14>;
-+                      input-enable;
-+                      input-schmitt-disable;
-+                      slew-rate = <0>;
-+              };
-+              rx-pins {
-+                      pins = <PAD_FUNC_SHARE(128)>,
-+                             <PAD_FUNC_SHARE(130)>,
-+                             <PAD_FUNC_SHARE(131)>,
-+                             <PAD_FUNC_SHARE(132)>,
-+                             <PAD_FUNC_SHARE(133)>,
-+                             <PAD_FUNC_SHARE(134)>,
-+                             <PAD_FUNC_SHARE(135)>,
-+                             <PAD_FUNC_SHARE(136)>,
-+                             <PAD_FUNC_SHARE(137)>,
-+                             <PAD_FUNC_SHARE(138)>,
-+                             <PAD_FUNC_SHARE(139)>,
-+                             <PAD_FUNC_SHARE(140)>,
-+                             <PAD_FUNC_SHARE(141)>;
-+                      bias-pull-up;
-+                      drive-strength = <14>;
-+                      input-enable;
-+                      input-schmitt-enable;
-+                      slew-rate = <0>;
-+              };
-+      };
-+
-       i2c0_pins: i2c0-0 {
-               i2c-pins {
-                       pinmux = <GPIOMUX(62, GPO_LOW,
-@@ -146,6 +312,166 @@
-               };
-       };
-+      pwmdac_pins: pwmdac-0 {
-+              pwmdac-pins {
-+                      pinmux = <GPIOMUX(23, GPO_PWMDAC_LEFT_OUT,
-+                                GPO_ENABLE, GPI_NONE)>,
-+                               <GPIOMUX(24, GPO_PWMDAC_RIGHT_OUT,
-+                                GPO_ENABLE, GPI_NONE)>;
-+                      bias-disable;
-+                      drive-strength = <35>;
-+                      input-disable;
-+                      input-schmitt-disable;
-+                      slew-rate = <0>;
-+              };
-+      };
-+
-+      pwm_pins: pwm-0 {
-+              pwm-pins {
-+                      pinmux = <GPIOMUX(7,
-+                                GPO_PWM_PAD_OUT_BIT0,
-+                                GPO_PWM_PAD_OE_N_BIT0,
-+                                GPI_NONE)>,
-+                               <GPIOMUX(5,
-+                                GPO_PWM_PAD_OUT_BIT1,
-+                                GPO_PWM_PAD_OE_N_BIT1,
-+                                GPI_NONE)>;
-+                      bias-disable;
-+                      drive-strength = <35>;
-+                      input-disable;
-+                      input-schmitt-disable;
-+                      slew-rate = <0>;
-+              };
-+      };
-+
-+      sdio0_pins: sdio0-0 {
-+              clk-pins {
-+                      pinmux = <GPIOMUX(54, GPO_SDIO0_PAD_CCLK_OUT,
-+                                GPO_ENABLE, GPI_NONE)>;
-+                      bias-disable;
-+                      input-disable;
-+                      input-schmitt-disable;
-+              };
-+              sdio-pins {
-+                      pinmux = <GPIOMUX(55, GPO_LOW, GPO_DISABLE,
-+                                GPI_SDIO0_PAD_CARD_DETECT_N)>,
-+                               <GPIOMUX(53,
-+                                GPO_SDIO0_PAD_CCMD_OUT,
-+                                GPO_SDIO0_PAD_CCMD_OEN,
-+                                GPI_SDIO0_PAD_CCMD_IN)>,
-+                               <GPIOMUX(49,
-+                                GPO_SDIO0_PAD_CDATA_OUT_BIT0,
-+                                GPO_SDIO0_PAD_CDATA_OEN_BIT0,
-+                                GPI_SDIO0_PAD_CDATA_IN_BIT0)>,
-+                               <GPIOMUX(50,
-+                                GPO_SDIO0_PAD_CDATA_OUT_BIT1,
-+                                GPO_SDIO0_PAD_CDATA_OEN_BIT1,
-+                                GPI_SDIO0_PAD_CDATA_IN_BIT1)>,
-+                               <GPIOMUX(51,
-+                                GPO_SDIO0_PAD_CDATA_OUT_BIT2,
-+                                GPO_SDIO0_PAD_CDATA_OEN_BIT2,
-+                                GPI_SDIO0_PAD_CDATA_IN_BIT2)>,
-+                               <GPIOMUX(52,
-+                                GPO_SDIO0_PAD_CDATA_OUT_BIT3,
-+                                GPO_SDIO0_PAD_CDATA_OEN_BIT3,
-+                                GPI_SDIO0_PAD_CDATA_IN_BIT3)>;
-+                      bias-pull-up;
-+                      input-enable;
-+                      input-schmitt-enable;
-+              };
-+      };
-+
-+      sdio1_pins: sdio1-0 {
-+              clk-pins {
-+                      pinmux = <GPIOMUX(33, GPO_SDIO1_PAD_CCLK_OUT,
-+                                GPO_ENABLE, GPI_NONE)>;
-+                      bias-disable;
-+                      input-disable;
-+                      input-schmitt-disable;
-+              };
-+              sdio-pins {
-+                      pinmux = <GPIOMUX(29,
-+                                GPO_SDIO1_PAD_CCMD_OUT,
-+                                GPO_SDIO1_PAD_CCMD_OEN,
-+                                GPI_SDIO1_PAD_CCMD_IN)>,
-+                               <GPIOMUX(36,
-+                                GPO_SDIO1_PAD_CDATA_OUT_BIT0,
-+                                GPO_SDIO1_PAD_CDATA_OEN_BIT0,
-+                                GPI_SDIO1_PAD_CDATA_IN_BIT0)>,
-+                               <GPIOMUX(30,
-+                                GPO_SDIO1_PAD_CDATA_OUT_BIT1,
-+                                GPO_SDIO1_PAD_CDATA_OEN_BIT1,
-+                                GPI_SDIO1_PAD_CDATA_IN_BIT1)>,
-+                               <GPIOMUX(34,
-+                                GPO_SDIO1_PAD_CDATA_OUT_BIT2,
-+                                GPO_SDIO1_PAD_CDATA_OEN_BIT2,
-+                                GPI_SDIO1_PAD_CDATA_IN_BIT2)>,
-+                               <GPIOMUX(31,
-+                                GPO_SDIO1_PAD_CDATA_OUT_BIT3,
-+                                GPO_SDIO1_PAD_CDATA_OEN_BIT3,
-+                                GPI_SDIO1_PAD_CDATA_IN_BIT3)>;
-+                      bias-pull-up;
-+                      input-enable;
-+                      input-schmitt-enable;
-+              };
-+      };
-+
-+      spi2_pins: spi2-0 {
-+              mosi-pins {
-+                      pinmux = <GPIOMUX(18, GPO_SPI2_PAD_TXD,
-+                                GPO_ENABLE, GPI_NONE)>;
-+                      bias-disable;
-+                      input-disable;
-+                      input-schmitt-disable;
-+              };
-+              miso-pins {
-+                      pinmux = <GPIOMUX(16, GPO_LOW, GPO_DISABLE,
-+                                GPI_SPI2_PAD_RXD)>;
-+                      bias-pull-up;
-+                      input-enable;
-+                      input-schmitt-enable;
-+              };
-+              sck-pins {
-+                      pinmux = <GPIOMUX(12, GPO_SPI2_PAD_SCK_OUT,
-+                                GPO_ENABLE, GPI_NONE)>;
-+                      bias-disable;
-+                      input-disable;
-+                      input-schmitt-disable;
-+              };
-+              ss-pins {
-+                      pinmux = <GPIOMUX(15, GPO_SPI2_PAD_SS_0_N,
-+                                GPO_ENABLE, GPI_NONE)>,
-+                               <GPIOMUX(11, GPO_SPI2_PAD_SS_1_N,
-+                                GPO_ENABLE, GPI_NONE)>;
-+                      bias-disable;
-+                      input-disable;
-+                      input-schmitt-disable;
-+              };
-+      };
-+
-+      uart0_pins: uart0-0 {
-+              rx-pins {
-+                      pinmux = <GPIOMUX(40, GPO_LOW, GPO_DISABLE,
-+                                GPI_UART0_PAD_SIN)>,
-+                               <GPIOMUX(39, GPO_LOW, GPO_DISABLE,
-+                                GPI_UART0_PAD_CTSN)>;
-+                      bias-pull-up;
-+                      drive-strength = <14>;
-+                      input-enable;
-+                      input-schmitt-enable;
-+              };
-+              tx-pins {
-+                      pinmux = <GPIOMUX(41, GPO_UART0_PAD_SOUT,
-+                                GPO_ENABLE, GPI_NONE)>,
-+                               <GPIOMUX(42, GPO_UART0_PAD_RTSN,
-+                                GPO_ENABLE, GPI_NONE)>;
-+                      bias-disable;
-+                      drive-strength = <35>;
-+                      input-disable;
-+                      input-schmitt-disable;
-+              };
-+      };
-+
-       uart3_pins: uart3-0 {
-               rx-pins {
-                       pinmux = <GPIOMUX(13, GPO_LOW, GPO_DISABLE,
-@@ -186,6 +512,17 @@
-               regulators {
-               };
-       };
-+
-+      tda998x@70 {
-+              compatible = "nxp,tda998x";
-+              reg = <0x70>;
-+
-+              port {
-+                      tda998x_0_input: endpoint {
-+                              remote-endpoint = <&hdmi_out>;
-+                      };
-+              };
-+      };
- };
- &i2c1 {
-@@ -225,8 +562,104 @@
-       status = "okay";
- };
-+&ptc {
-+      pinctrl-names = "default";
-+      pinctrl-0 = <&pwm_pins>;
-+      status = "okay";
-+};
-+
-+&pwmdac {
-+      pinctrl-names = "default";
-+      pinctrl-0 = <&pwmdac_pins>;
-+      status = "okay";
-+};
-+
-+&qspi {
-+      nor_flash: nor-flash@0 {
-+              compatible = "spi-flash";
-+              reg = <0>;
-+              spi-max-frequency = <31250000>;
-+              page-size = <256>;
-+              block-size = <16>;
-+              cdns,read-delay = <4>;
-+              cdns,tshsl-ns = <1>;
-+              cdns,tsd2d-ns = <1>;
-+              cdns,tchsh-ns = <1>;
-+              cdns,tslch-ns = <1>;
-+              spi-tx-bus-width = <1>;
-+              spi-rx-bus-width = <1>;
-+      };
-+
-+      nand_flash: nand-flash@1 {
-+              compatible = "spi-flash-nand";
-+              reg = <1>;
-+              spi-max-frequency = <31250000>;
-+              page-size = <2048>;
-+              block-size = <17>;
-+              cdns,read-delay = <4>;
-+              cdns,tshsl-ns = <1>;
-+              cdns,tsd2d-ns = <1>;
-+              cdns,tchsh-ns = <1>;
-+              cdns,tslch-ns = <1>;
-+              spi-tx-bus-width = <1>;
-+              spi-rx-bus-width = <1>;
-+      };
-+};
-+
-+&sdio0 {
-+      broken-cd;
-+      bus-width = <4>;
-+      cap-sd-highspeed;
-+      pinctrl-names = "default";
-+      pinctrl-0 = <&sdio0_pins>;
-+      max-frequency = <10000000>;
-+      status = "okay";
-+};
-+
-+&sdio1 {
-+      #address-cells = <1>;
-+      #size-cells = <0>;
-+      bus-width = <4>;
-+      cap-sd-highspeed;
-+      cap-sdio-irq;
-+      cap-power-off-card;
-+      mmc-pwrseq = <&wifi_pwrseq>;
-+      non-removable;
-+      pinctrl-names = "default";
-+      pinctrl-0 = <&sdio1_pins>;
-+      status = "okay";
-+
-+      wifi@1 {
-+              compatible = "brcm,bcm4329-fmac";
-+              reg = <1>;
-+      };
-+};
-+
-+&spi2 {
-+      pinctrl-names = "default";
-+      pinctrl-0 = <&spi2_pins>;
-+      status = "okay";
-+
-+      spi_dev0: spi@0 {
-+              compatible = "rohm,dh2228fv";
-+              spi-max-frequency = <10000000>;
-+              reg = <0>;
-+      };
-+};
-+
-+&uart0 {
-+      pinctrl-names = "default";
-+      pinctrl-0 = <&uart0_pins>;
-+      status = "okay";
-+};
-+
- &uart3 {
-       pinctrl-names = "default";
-       pinctrl-0 = <&uart3_pins>;
-       status = "okay";
- };
-+
-+&usb3 {
-+      dr_mode = "host";
-+      status = "okay";
-+};
---- a/arch/riscv/boot/dts/starfive/jh7100-starfive-visionfive-v1.dts
-+++ b/arch/riscv/boot/dts/starfive/jh7100-starfive-visionfive-v1.dts
-@@ -18,3 +18,22 @@
-               priority = <224>;
-       };
- };
-+
-+&gpio {
-+      /* don't reset gpio mux for serial console and reset gpio */
-+      starfive,keep-gpiomux = <13 14 63>;
-+};
-+
-+&i2c0 {
-+      eeprom@50 {
-+              compatible = "atmel,24c04";
-+              reg = <0x50>;
-+              pagesize = <16>;
-+      };
-+};
-+
-+&mdio {
-+      phy: ethernet-phy@0 {
-+              reg = <0>;
-+      };
-+};
---- a/arch/riscv/boot/dts/starfive/jh7100.dtsi
-+++ b/arch/riscv/boot/dts/starfive/jh7100.dtsi
-@@ -6,7 +6,9 @@
- /dts-v1/;
- #include <dt-bindings/clock/starfive-jh7100.h>
-+#include <dt-bindings/clock/starfive-jh7100-audio.h>
- #include <dt-bindings/reset/starfive-jh7100.h>
-+#include <dt-bindings/reset/starfive-jh7100-audio.h>
- / {
-       compatible = "starfive,jh7100";
-@@ -135,6 +137,13 @@
-               clock-frequency = <0>;
-       };
-+      /* gmac device configuration */
-+      stmmac_axi_setup: stmmac-axi-config {
-+              snps,wr_osr_lmt = <0xf>;
-+              snps,rd_osr_lmt = <0xf>;
-+              snps,blen = <256 128 64 32 0 0 0>;
-+      };
-+
-       soc {
-               compatible = "simple-bus";
-               interrupt-parent = <&plic>;
-@@ -143,6 +152,24 @@
-               dma-noncoherent;
-               ranges;
-+              dtim: dtim@1000000 {
-+                      compatible = "starfive,dtim0";
-+                      reg = <0x0 0x1000000 0x0 0x2000>;
-+                      reg-names = "mem";
-+              };
-+
-+              itim0: itim@1808000 {
-+                      compatible = "starfive,itim0";
-+                      reg = <0x0 0x1808000 0x0 0x8000>;
-+                      reg-names = "mem";
-+              };
-+
-+              itim1: itim@1820000 {
-+                      compatible = "starfive,itim0";
-+                      reg = <0x0 0x1820000 0x0 0x8000>;
-+                      reg-names = "mem";
-+              };
-+
-               clint: clint@2000000 {
-                       compatible = "starfive,jh7100-clint", "sifive,clint0";
-                       reg = <0x0 0x2000000 0x0 0x10000>;
-@@ -172,6 +199,151 @@
-                       riscv,ndev = <133>;
-               };
-+              gmac: ethernet@10020000 {
-+                      compatible = "starfive,jh7100-dwmac", "snps,dwmac";
-+                      reg = <0x0 0x10020000 0x0 0x10000>;
-+                      clocks = <&clkgen JH7100_CLK_GMAC_ROOT_DIV>,
-+                               <&clkgen JH7100_CLK_GMAC_AHB>,
-+                               <&clkgen JH7100_CLK_GMAC_PTP_REF>,
-+                               <&clkgen JH7100_CLK_GMAC_TX_INV>,
-+                               <&clkgen JH7100_CLK_GMAC_GTX>;
-+                      clock-names = "stmmaceth", "pclk", "ptp_ref", "tx", "gtx";
-+                      resets = <&rstgen JH7100_RSTN_GMAC_AHB>;
-+                      reset-names = "ahb";
-+                      interrupts = <6>, <7>;
-+                      interrupt-names = "macirq", "eth_wake_irq";
-+                      max-frame-size = <9000>;
-+                      snps,multicast-filter-bins = <0>;
-+                      snps,perfect-filter-entries = <128>;
-+                      starfive,syscon = <&sysmain 0x70 0>;
-+                      rx-fifo-depth = <32768>;
-+                      tx-fifo-depth = <16384>;
-+                      snps,axi-config = <&stmmac_axi_setup>;
-+                      snps,fixed-burst;
-+                      /*snps,force_sf_dma_mode;*/
-+                      snps,force_thresh_dma_mode;
-+                      snps,no-pbl-x8;
-+                      status = "disabled";
-+              };
-+
-+              dma2p: dma-controller@100b0000 {
-+                      compatible = "starfive,jh7100-axi-dma";
-+                      reg = <0x0 0x100b0000 0x0 0x10000>;
-+                      clocks = <&clkgen JH7100_CLK_SGDMA2P_AXI>,
-+                               <&clkgen JH7100_CLK_SGDMA2P_AHB>;
-+                      clock-names = "core-clk", "cfgr-clk";
-+                      resets = <&rstgen JH7100_RSTN_SGDMA2P_AXI>,
-+                               <&rstgen JH7100_RSTN_SGDMA2P_AHB>;
-+                      reset-names = "axi", "ahb";
-+                      interrupts = <2>;
-+                      #dma-cells = <1>;
-+                      dma-channels = <4>;
-+                      snps,dma-masters = <1>;
-+                      snps,data-width = <4>;
-+                      snps,block-size = <4096 4096 4096 4096>;
-+                      snps,priority = <0 1 2 3>;
-+                      snps,axi-max-burst-len = <128>;
-+                      dma-coherent;
-+              };
-+
-+              crypto: crypto@100d0000 {
-+                      compatible = "starfive,vic-sec";
-+                      reg = <0x0 0x100d0000 0x0 0x20000>,
-+                            <0x0 0x11800234 0x0 0xc>;
-+                      reg-names = "secmem", "secclk";
-+                      clocks = <&clkgen JH7100_CLK_SEC_AHB>;
-+                      interrupts = <31>;
-+              };
-+
-+              i2sadc0: i2sadc0@10400000 {
-+                      compatible = "snps,designware-i2sadc0";
-+                      reg = <0x0 0x10400000 0x0 0x1000>;
-+                      clocks = <&clkgen JH7100_CLK_APB1_BUS>;
-+                      clock-names = "i2sclk";
-+                      interrupt-parent = <&plic>;
-+                      #sound-dai-cells = <0>;
-+                      dmas = <&dma2p 28>;
-+                      dma-names = "rx";
-+              };
-+
-+              i2svad: i2svad@10420000 {
-+                      compatible = "starfive,sf-i2svad";
-+                      reg = <0x0 0x10420000 0x0 0x1000> ;
-+                      clocks = <&audclk JH7100_AUDCLK_I2SVAD_APB>;
-+                      clock-names = "i2svad_apb";
-+                      resets = <&audrst JH7100_AUDRSTN_I2SVAD_APB>,
-+                               <&audrst JH7100_AUDRSTN_I2SVAD_SRST>;
-+                      reset-names = "apb_i2svad", "i2svad_srst";
-+                      interrupts = <60>, <61>;
-+                      interrupt-names = "spintr", "slintr";
-+                      #sound-dai-cells = <0>;
-+              };
-+
-+              pwmdac: pwmdac@10440000 {
-+                      compatible = "starfive,pwmdac";
-+                      reg = <0x0 0x10440000 0x0 0x1000>;
-+                      clocks = <&clkgen JH7100_CLK_AUDIO_ROOT>,
-+                               <&clkgen JH7100_CLK_AUDIO_SRC>,
-+                               <&clkgen JH7100_CLK_AUDIO_12288>,
-+                               <&audclk JH7100_AUDCLK_DMA1P_AHB>,
-+                               <&audclk JH7100_AUDCLK_PWMDAC_APB>,
-+                               <&audclk JH7100_AUDCLK_DAC_MCLK>;
-+                      clock-names = "audio_root",
-+                                    "audio_src",
-+                                    "audio_12288",
-+                                    "dma1p_ahb",
-+                                    "pwmdac_apb",
-+                                    "dac_mclk";
-+                      resets = <&audrst JH7100_AUDRSTN_APB_BUS>,
-+                               <&audrst JH7100_AUDRSTN_DMA1P_AHB>,
-+                               <&audrst JH7100_AUDRSTN_PWMDAC_APB>;
-+                      reset-names = "apb_bus", "dma1p_ahb", "apb_pwmdac";
-+                      dmas = <&dma2p 23>;
-+                      dma-names = "tx";
-+                      #sound-dai-cells = <0>;
-+              };
-+
-+              i2sdac0: i2sdac0@10450000 {
-+                      compatible = "snps,designware-i2sdac0";
-+                      reg = <0x0 0x10450000 0x0 0x1000>;
-+                      clocks = <&audclk JH7100_AUDCLK_DAC_MCLK>,
-+                               <&audclk JH7100_AUDCLK_I2SDAC_BCLK>,
-+                               <&audclk JH7100_AUDCLK_I2SDAC_LRCLK>,
-+                               <&audclk JH7100_AUDCLK_I2SDAC_APB>;
-+                      clock-names = "dac_mclk", "i2sdac0_bclk", "i2sdac0_lrclk", "i2sdac_apb";
-+                      resets = <&audrst JH7100_AUDRSTN_I2SDAC_APB>,
-+                               <&audrst JH7100_AUDRSTN_I2SDAC_SRST>;
-+                      reset-names = "apb_i2sdac", "i2sdac_srst";
-+                      #sound-dai-cells = <0>;
-+                      dmas = <&dma2p 30>;
-+                      dma-names = "tx";
-+              };
-+
-+              i2sdac1: i2sdac1@10460000 {
-+                      compatible = "snps,designware-i2sdac1";
-+                      reg = <0x0 0x10460000 0x0 0x1000>;
-+                      clocks = <&audclk JH7100_AUDCLK_DAC_MCLK>,
-+                               <&audclk JH7100_AUDCLK_I2S1_BCLK>,
-+                               <&audclk JH7100_AUDCLK_I2S1_LRCLK>,
-+                               <&audclk JH7100_AUDCLK_I2S1_APB>;
-+                      clock-names = "dac_mclk", "i2sdac1_bclk", "i2sdac1_lrclk", "i2s1_apb";
-+                      resets = <&audrst JH7100_AUDRSTN_I2S1_APB>,
-+                               <&audrst JH7100_AUDRSTN_I2S1_SRST>;
-+                      #sound-dai-cells = <0>;
-+                      dmas = <&dma2p 31>;
-+                      dma-names = "tx";
-+              };
-+
-+              i2sdac16k: i2sdac16k@10470000 {
-+                      compatible = "snps,designware-i2sdac16k";
-+                      reg = <0x0 0x10470000 0x0 0x1000>;
-+                      clocks = <&clkgen JH7100_CLK_APB1_BUS>;
-+                      clock-names = "i2sclk";
-+                      #sound-dai-cells = <0>;
-+                      dmas = <&dma2p 29>;
-+                      dma-names = "tx";
-+              };
-+
-               audclk: clock-controller@10480000 {
-                       compatible = "starfive,jh7100-audclk";
-                       reg = <0x0 0x10480000 0x0 0x10000>;
-@@ -214,6 +386,82 @@
-                       status = "disabled";
-               };
-+              spdif_transmitter: spdif-transmitter {
-+                      compatible = "linux,spdif-dit";
-+                      #sound-dai-cells = <0>;
-+              };
-+
-+              spdif_receiver: spdif-receiver {
-+                      compatible = "linux,spdif-dir";
-+                      #sound-dai-cells = <0>;
-+              };
-+
-+              pwmdac_codec: pwmdac-transmitter {
-+                      compatible = "linux,pwmdac-dit";
-+                      #sound-dai-cells = <0>;
-+              };
-+
-+              dmic_codec: dmic {
-+                      compatible = "dmic-codec";
-+                      #sound-dai-cells = <0>;
-+              };
-+
-+              sound: snd-card {
-+                      compatible = "simple-audio-card";
-+                      simple-audio-card,name = "Starfive-Multi-Sound-Card";
-+                      #address-cells = <1>;
-+                      #size-cells = <0>;
-+
-+                      /* pwmdac */
-+                      simple-audio-card,dai-link@0 {
-+                              reg = <0>;
-+                              status = "okay";
-+                              format = "left_j";
-+                              bitclock-master = <&sndcpu0>;
-+                              frame-master = <&sndcpu0>;
-+
-+                              sndcpu0: cpu {
-+                                      sound-dai = <&pwmdac>;
-+                              };
-+
-+                              codec {
-+                                      sound-dai = <&pwmdac_codec>;
-+                              };
-+                      };
-+              };
-+
-+              usb3: usb@104c0000 {
-+                      compatible = "cdns,usb3";
-+                      reg = <0x0 0x104c0000 0x0 0x10000>,     // memory area for HOST registers
-+                            <0x0 0x104d0000 0x0 0x10000>,     // memory area for DEVICE registers
-+                            <0x0 0x104e0000 0x0 0x10000>;     // memory area for OTG/DRD registers
-+                      reg-names = "otg", "xhci", "dev";
-+                      interrupts = <44>, <52>, <43>;
-+                      interrupt-names = "host", "peripheral", "otg";
-+                      phy-names = "cdns3,usb3-phy", "cdns3,usb2-phy";
-+                      maximum-speed = "super-speed";
-+                      status = "disabled";
-+              };
-+
-+              dma1p: dma-controller@10500000 {
-+                      compatible = "starfive,jh7100-axi-dma";
-+                      reg = <0x0 0x10500000 0x0 0x10000>;
-+                      clocks = <&clkgen JH7100_CLK_SGDMA1P_AXI>,
-+                               <&clkgen JH7100_CLK_SGDMA1P_BUS>;
-+                      clock-names = "core-clk", "cfgr-clk";
-+                      resets = <&rstgen JH7100_RSTN_DMA1P_AXI>,
-+                               <&rstgen JH7100_RSTN_SGDMA1P_AXI>;
-+                      reset-names = "axi", "ahb";
-+                      interrupts = <1>;
-+                      #dma-cells = <1>;
-+                      dma-channels = <16>;
-+                      snps,dma-masters = <1>;
-+                      snps,data-width = <3>;
-+                      snps,block-size = <4096 4096 4096 4096 4096 4096 4096 4096 4096 4096 4096 4096 4096 4096 4096 4096>;
-+                      snps,priority = <0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15>;
-+                      snps,axi-max-burst-len = <64>;
-+              };
-+
-               clkgen: clock-controller@11800000 {
-                       compatible = "starfive,jh7100-clkgen";
-                       reg = <0x0 0x11800000 0x0 0x10000>;
-@@ -222,12 +470,93 @@
-                       #clock-cells = <1>;
-               };
-+              otp: otp@11810000 {
-+                      compatible = "starfive,fu740-otp";
-+                      reg = <0x0 0x11810000 0x0 0x10000>;
-+                      clocks = <&clkgen JH7100_CLK_OTP_APB>;
-+                      fuse-count = <0x200>;
-+              };
-+
-               rstgen: reset-controller@11840000 {
-                       compatible = "starfive,jh7100-reset";
-                       reg = <0x0 0x11840000 0x0 0x10000>;
-                       #reset-cells = <1>;
-               };
-+              sysmain: syscon@11850000 {
-+                      compatible = "starfive,jh7100-sysmain", "syscon";
-+                      reg = <0x0 0x11850000 0x0 0x10000>;
-+              };
-+
-+              qspi: spi@11860000 {
-+                      compatible = "cdns,qspi-nor";
-+                      reg = <0x0 0x11860000 0x0 0x10000>,
-+                            <0x0 0x20000000 0x0 0x20000000>;
-+                      clocks = <&clkgen JH7100_CLK_QSPI_AHB>;
-+                      interrupts = <3>;
-+                      #address-cells = <1>;
-+                      #size-cells = <0>;
-+                      cdns,fifo-depth = <256>;
-+                      cdns,fifo-width = <4>;
-+                      cdns,trigger-address = <0x0>;
-+                      spi-max-frequency = <250000000>;
-+                      status = "disabled";
-+              };
-+
-+              uart0: serial@11870000 {
-+                      compatible = "starfive,jh7100-hsuart", "snps,dw-apb-uart";
-+                      reg = <0x0 0x11870000 0x0 0x10000>;
-+                      clocks = <&clkgen JH7100_CLK_UART0_CORE>,
-+                               <&clkgen JH7100_CLK_UART0_APB>;
-+                      clock-names = "baudclk", "apb_pclk";
-+                      resets = <&rstgen JH7100_RSTN_UART0_APB>;
-+                      interrupts = <92>;
-+                      reg-io-width = <4>;
-+                      reg-shift = <2>;
-+                      status = "disabled";
-+              };
-+
-+              uart1: serial@11880000 {
-+                      compatible = "starfive,jh7100-hsuart", "snps,dw-apb-uart";
-+                      reg = <0x0 0x11880000 0x0 0x10000>;
-+                      clocks = <&clkgen JH7100_CLK_UART1_CORE>,
-+                               <&clkgen JH7100_CLK_UART1_APB>;
-+                      clock-names = "baudclk", "apb_pclk";
-+                      resets = <&rstgen JH7100_RSTN_UART1_APB>;
-+                      interrupts = <93>;
-+                      reg-io-width = <4>;
-+                      reg-shift = <2>;
-+                      status = "disabled";
-+              };
-+
-+              spi0: spi@11890000 {
-+                      compatible = "snps,dw-apb-ssi";
-+                      reg = <0x0 0x11890000 0x0 0x10000>;
-+                      clocks = <&clkgen JH7100_CLK_SPI0_CORE>,
-+                               <&clkgen JH7100_CLK_SPI0_APB>;
-+                      clock-names = "ssi_clk", "pclk";
-+                      resets = <&rstgen JH7100_RSTN_SPI0_APB>;
-+                      reset-names = "spi";
-+                      interrupts = <94>;
-+                      #address-cells = <1>;
-+                      #size-cells = <0>;
-+                      status = "disabled";
-+              };
-+
-+              spi1: spi@118a0000 {
-+                      compatible = "snps,dw-apb-ssi";
-+                      reg = <0x0 0x118a0000 0x0 0x10000>;
-+                      clocks = <&clkgen JH7100_CLK_SPI1_CORE>,
-+                               <&clkgen JH7100_CLK_SPI1_APB>;
-+                      clock-names = "ssi_clk", "pclk";
-+                      resets = <&rstgen JH7100_RSTN_SPI1_APB>;
-+                      reset-names = "spi";
-+                      interrupts = <95>;
-+                      #address-cells = <1>;
-+                      #size-cells = <0>;
-+                      status = "disabled";
-+              };
-+
-               i2c0: i2c@118b0000 {
-                       compatible = "snps,designware-i2c";
-                       reg = <0x0 0x118b0000 0x0 0x10000>;
-@@ -254,6 +583,41 @@
-                       status = "disabled";
-               };
-+              trng: trng@118d0000 {
-+                      compatible = "starfive,vic-rng";
-+                      reg = <0x0 0x118d0000 0x0 0x10000>;
-+                      clocks = <&clkgen JH7100_CLK_TRNG_APB>;
-+                      interrupts = <98>;
-+              };
-+
-+              vpu_enc: vpu_enc@118e0000 {
-+                      compatible = "cm,cm521-vpu";
-+                      reg = <0x0 0x118e0000 0x0 0x4000>;
-+                      reg-names = "control";
-+                      clocks = <&clkgen JH7100_CLK_VP6_CORE>;
-+                      clock-names = "vcodec";
-+                      interrupts = <26>;
-+              };
-+
-+              vpu_dec: vpu_dec@118f0000 {
-+                      compatible = "c&m,cm511-vpu";
-+                      reg = <0 0x118f0000 0 0x10000>;
-+                      clocks = <&clkgen JH7100_CLK_VP6_CORE>;
-+                      clock-names = "vcodec";
-+                      interrupts = <23>;
-+                      //memory-region = <&vpu_reserved>;
-+              };
-+
-+              jpu: coadj12@11900000 {
-+                      compatible = "cm,codaj12-jpu-1";
-+                      reg = <0x0 0x11900000 0x0 0x300>;
-+                      reg-names = "control";
-+                      clocks = <&clkgen JH7100_CLK_JPEG_APB>;
-+                      clock-names = "jpege";
-+                      interrupts = <24>;
-+                      memory-region = <&jpu_reserved>;
-+              };
-+
-               gpio: pinctrl@11910000 {
-                       compatible = "starfive,jh7100-pinctrl";
-                       reg = <0x0 0x11910000 0x0 0x10000>,
-@@ -268,6 +632,86 @@
-                       #interrupt-cells = <2>;
-               };
-+              nvdla@11940000 {
-+                      compatible = "nvidia,nvdla_os_initial";
-+                      interrupts = <22>;
-+                      memory-region = <&nvdla_reserved>;
-+                      reg = <0x0 0x11940000 0x0 0x40000>;
-+                      status = "okay";
-+              };
-+
-+              display: display-subsystem {
-+                      compatible = "starfive,display-subsystem";
-+                      dma-coherent;
-+                      status = "disabled";
-+              };
-+
-+              encoder: display-encoder {
-+                      compatible = "starfive,display-encoder";
-+                      status = "disabled";
-+              };
-+
-+              crtc: crtc@12000000 {
-+                      compatible = "starfive,jh7100-crtc";
-+                      reg = <0x0 0x12000000 0x0 0x10000>,
-+                            <0x0 0x12040000 0x0 0x10000>,
-+                            <0x0 0x12080000 0x0 0x10000>,
-+                            <0x0 0x120c0000 0x0 0x10000>,
-+                            <0x0 0x12240000 0x0 0x10000>,
-+                            <0x0 0x12250000 0x0 0x10000>,
-+                            <0x0 0x12260000 0x0 0x10000>;
-+                      reg-names = "lcdc", "vpp0", "vpp1", "vpp2", "clk", "rst", "sys";
-+                      clocks = <&clkgen JH7100_CLK_DISP_AXI>, <&clkgen JH7100_CLK_VOUT_SRC>;
-+                      clock-names = "disp_axi", "vout_src";
-+                      resets = <&rstgen JH7100_RSTN_DISP_AXI>, <&rstgen JH7100_RSTN_VOUT_SRC>;
-+                      reset-names = "disp_axi", "vout_src";
-+                      interrupts = <101>, <103>;
-+                      interrupt-names = "lcdc_irq", "vpp1_irq";
-+                      #address-cells = <1>;
-+                      #size-cells = <0>;
-+                      status = "disabled";
-+
-+                      pp1 {
-+                              pp-id = <1>;
-+                              fifo-out;
-+                              //sys-bus-out;
-+                              src-format = <11>; //<COLOR_RGB565>;
-+                              src-width = <1920>;
-+                              src-height = <1080>;
-+                              dst-format = <7>; //<COLOR_RGB888_ARGB>;
-+                              dst-width = <1920>;
-+                              dst-height = <1080>;
-+                      };
-+              };
-+
-+              spi2: spi@12410000 {
-+                      compatible = "snps,dw-apb-ssi";
-+                      reg = <0x0 0x12410000 0x0 0x10000>;
-+                      clocks = <&clkgen JH7100_CLK_SPI2_CORE>,
-+                               <&clkgen JH7100_CLK_SPI2_APB>;
-+                      clock-names = "ssi_clk", "pclk";
-+                      resets = <&rstgen JH7100_RSTN_SPI2_APB>;
-+                      reset-names = "spi";
-+                      interrupts = <70>;
-+                      #address-cells = <1>;
-+                      #size-cells = <0>;
-+                      status = "disabled";
-+              };
-+
-+              spi3: spi@12420000 {
-+                      compatible = "snps,dw-apb-ssi";
-+                      reg = <0x0 0x12420000 0x0 0x10000>;
-+                      clocks = <&clkgen JH7100_CLK_SPI3_CORE>,
-+                               <&clkgen JH7100_CLK_SPI3_APB>;
-+                      clock-names = "ssi_clk", "pclk";
-+                      resets = <&rstgen JH7100_RSTN_SPI3_APB>;
-+                      reset-names = "spi";
-+                      interrupts = <71>;
-+                      #address-cells = <1>;
-+                      #size-cells = <0>;
-+                      status = "disabled";
-+              };
-+
-               uart2: serial@12430000 {
-                       compatible = "starfive,jh7100-uart", "snps,dw-apb-uart";
-                       reg = <0x0 0x12430000 0x0 0x10000>;
-@@ -341,5 +785,64 @@
-                       reset-names = "sense", "bus";
-                       #thermal-sensor-cells = <0>;
-               };
-+
-+              ptc: pwm@12490000 {
-+                      compatible = "starfive,pwm0";
-+                      reg = <0x0 0x12490000 0x0 0x10000>;
-+                      clocks = <&clkgen JH7100_CLK_PWM_APB>;
-+                      resets = <&rstgen JH7100_RSTN_PWM_APB>;
-+                      #pwm-cells = <3>;
-+                      sifive,npwm = <8>;
-+                      status = "disabled";
-+              };
-+
-+              thermal-zones {
-+                      cpu-thermal {
-+                              polling-delay-passive = <250>;
-+                              polling-delay = <15000>;
-+
-+                              thermal-sensors = <&sfctemp>;
-+
-+                              cooling-maps {
-+                              };
-+
-+                              trips {
-+                                      cpu_alert0: cpu_alert0 {
-+                                              /* milliCelsius */
-+                                              temperature = <75000>;
-+                                              hysteresis = <2000>;
-+                                              type = "passive";
-+                                      };
-+
-+                                      cpu_crit: cpu_crit {
-+                                              /* milliCelsius */
-+                                              temperature = <90000>;
-+                                              hysteresis = <2000>;
-+                                              type = "critical";
-+                                      };
-+                              };
-+                      };
-+              };
-+
-+              xrp@f0000000 {
-+                      compatible = "cdns,xrp";
-+                      reg = <0x0  0xf0000000 0x0 0x01ffffff>,
-+                            <0x10 0x72000000 0x0 0x00001000>,
-+                            <0x10 0x72001000 0x0 0x00fff000>,
-+                            <0x0  0x124b0000 0x0 0x00010000>;
-+                      clocks = <&clkgen JH7100_CLK_VP6_CORE>;
-+                      interrupts = <27>, <28>;
-+                      firmware-name = "vp6_elf";
-+                      dsp-irq = <19 20>;
-+                      dsp-irq-src = <0x20 0x21>;
-+                      intc-irq-mode = <1>;
-+                      intc-irq = <0 1>;
-+                      #address-cells = <1>;
-+                      #size-cells = <1>;
-+                      ranges = <0x40000000 0x0  0x40000000 0x01000000>,
-+                               <0xb0000000 0x10 0x70000000 0x3000000>;
-+                      dsp@0 {
-+                      };
-+              };
-       };
- };