starfive: add new target for StarFive JH7100/7110 SoC

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

Specifications:

SoCs:

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

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

Boards:

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

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

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

Signed-off-by: Zoltan HERPAI <wigyori@uid0.hu>
This commit is contained in:
Zoltan HERPAI 2023-05-28 15:14:02 +02:00
parent db0d7cf6a1
commit 4070e2a64c
161 changed files with 36656 additions and 0 deletions

View File

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

View File

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

View File

@ -0,0 +1,4 @@
::sysinit:/etc/init.d/rcS S boot
::shutdown:/etc/init.d/rcS K shutdown
ttyS0::askfirst:/usr/libexec/login.sh
tty1::askfirst:/usr/libexec/login.sh

View File

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

View File

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

View File

@ -0,0 +1,555 @@
CONFIG_64BIT=y
CONFIG_AMBA_PL08X=y
CONFIG_ARCH_CLOCKSOURCE_INIT=y
CONFIG_ARCH_DMA_ADDR_T_64BIT=y
CONFIG_ARCH_HIBERNATION_POSSIBLE=y
CONFIG_ARCH_MMAP_RND_BITS=18
CONFIG_ARCH_MMAP_RND_BITS_MAX=24
CONFIG_ARCH_MMAP_RND_BITS_MIN=18
CONFIG_ARCH_MMAP_RND_COMPAT_BITS_MAX=17
CONFIG_ARCH_OPTIONAL_KERNEL_RWX=y
CONFIG_ARCH_OPTIONAL_KERNEL_RWX_DEFAULT=y
CONFIG_ARCH_RV64I=y
CONFIG_ARCH_SELECT_MEMORY_MODEL=y
CONFIG_ARCH_SIFIVE=y
CONFIG_ARCH_SPARSEMEM_ENABLE=y
CONFIG_ARCH_STACKWALK=y
CONFIG_ARCH_STARFIVE=y
CONFIG_ARCH_WANTS_THP_SWAP=y
CONFIG_ARM_AMBA=y
# CONFIG_ARM_MHU_V2 is not set
CONFIG_ASN1=y
CONFIG_ASSOCIATIVE_ARRAY=y
CONFIG_AUXILIARY_BUS=y
CONFIG_CC_HAVE_STACKPROTECTOR_TLS=y
CONFIG_CC_IMPLICIT_FALLTHROUGH="-Wimplicit-fallthrough=5"
CONFIG_CC_NO_ARRAY_BOUNDS=y
CONFIG_CHECKPOINT_RESTORE=y
CONFIG_CLKSRC_MMIO=y
CONFIG_CLK_ANALOGBITS_WRPLL_CLN28HPC=y
CONFIG_CLK_SIFIVE=y
CONFIG_CLK_SIFIVE_PRCI=y
CONFIG_CLK_STARFIVE_JH7100=y
CONFIG_CLK_STARFIVE_JH7100_AUDIO=y
CONFIG_CLK_STARFIVE_JH7110_AON=y
CONFIG_CLK_STARFIVE_JH7110_ISP=y
CONFIG_CLK_STARFIVE_JH7110_PLL=y
CONFIG_CLK_STARFIVE_JH7110_STG=y
CONFIG_CLK_STARFIVE_JH7110_SYS=y
CONFIG_CLK_STARFIVE_JH7110_VOUT=y
CONFIG_CLK_STARFIVE_JH71X0=y
CONFIG_CLONE_BACKWARDS=y
CONFIG_CLZ_TAB=y
CONFIG_CMODEL_MEDANY=y
# CONFIG_CMODEL_MEDLOW is not set
CONFIG_COMMON_CLK=y
CONFIG_COMPACT_UNEVICTABLE_DEFAULT=1
# CONFIG_COMPAT_32BIT_TIME is not set
CONFIG_CONFIGFS_FS=y
CONFIG_CONTEXT_TRACKING=y
CONFIG_CONTEXT_TRACKING_IDLE=y
CONFIG_CONTIG_ALLOC=y
CONFIG_CPUFREQ_DT=y
CONFIG_CPUFREQ_DT_PLATDEV=y
CONFIG_CPU_FREQ=y
CONFIG_CPU_FREQ_DEFAULT_GOV_PERFORMANCE=y
CONFIG_CPU_FREQ_GOV_ATTR_SET=y
CONFIG_CPU_FREQ_GOV_COMMON=y
CONFIG_CPU_FREQ_GOV_CONSERVATIVE=y
CONFIG_CPU_FREQ_GOV_ONDEMAND=y
CONFIG_CPU_FREQ_GOV_PERFORMANCE=y
CONFIG_CPU_FREQ_GOV_POWERSAVE=y
CONFIG_CPU_FREQ_GOV_USERSPACE=y
CONFIG_CPU_FREQ_STAT=y
CONFIG_CPU_IDLE=y
CONFIG_CPU_IDLE_GOV_MENU=y
CONFIG_CPU_IDLE_MULTIPLE_DRIVERS=y
CONFIG_CPU_PM=y
CONFIG_CPU_RMAP=y
CONFIG_CRASH_CORE=y
CONFIG_CRC16=y
CONFIG_CRC7=y
CONFIG_CRC_ITU_T=y
CONFIG_CRYPTO_BLAKE2B=y
CONFIG_CRYPTO_CMAC=y
CONFIG_CRYPTO_CRC32C=y
CONFIG_CRYPTO_DEV_JH7110=y
CONFIG_CRYPTO_DRBG=y
CONFIG_CRYPTO_DRBG_HMAC=y
CONFIG_CRYPTO_DRBG_MENU=y
CONFIG_CRYPTO_ECB=y
CONFIG_CRYPTO_ECC=y
CONFIG_CRYPTO_ECDH=y
CONFIG_CRYPTO_ENGINE=y
CONFIG_CRYPTO_HASH_INFO=y
CONFIG_CRYPTO_HMAC=y
CONFIG_CRYPTO_HW=y
CONFIG_CRYPTO_JITTERENTROPY=y
CONFIG_CRYPTO_LIB_BLAKE2S_GENERIC=y
CONFIG_CRYPTO_LIB_POLY1305_RSIZE=1
CONFIG_CRYPTO_LIB_SHA1=y
CONFIG_CRYPTO_LIB_SHA256=y
CONFIG_CRYPTO_LIB_UTILS=y
CONFIG_CRYPTO_RNG=y
CONFIG_CRYPTO_RNG2=y
CONFIG_CRYPTO_RNG_DEFAULT=y
CONFIG_CRYPTO_RSA=y
CONFIG_CRYPTO_SHA256=y
CONFIG_CRYPTO_SHA512=y
CONFIG_CRYPTO_SM3=y
CONFIG_CRYPTO_SM3_GENERIC=y
CONFIG_CRYPTO_USER=y
CONFIG_CRYPTO_USER_API=y
CONFIG_CRYPTO_USER_API_AEAD=y
CONFIG_CRYPTO_USER_API_HASH=y
CONFIG_CRYPTO_USER_API_RNG=y
CONFIG_CRYPTO_USER_API_SKCIPHER=y
CONFIG_CRYPTO_XXHASH=y
CONFIG_CRYPTO_ZSTD=y
CONFIG_DEBUG_ATOMIC_SLEEP=y
CONFIG_DEBUG_GPIO=y
CONFIG_DEBUG_INFO=y
CONFIG_DEBUG_PINCTRL=y
CONFIG_DEBUG_RODATA_TEST=y
CONFIG_DEBUG_RT_MUTEXES=y
CONFIG_DEBUG_RWSEMS=y
CONFIG_DEBUG_SECTION_MISMATCH=y
CONFIG_DEBUG_SG=y
CONFIG_DEBUG_SPINLOCK=y
CONFIG_DEBUG_TIMEKEEPING=y
CONFIG_DEBUG_WX=y
CONFIG_DECOMPRESS_GZIP=y
# CONFIG_DEVFREQ_GOV_PASSIVE is not set
# CONFIG_DEVFREQ_GOV_PERFORMANCE is not set
# CONFIG_DEVFREQ_GOV_POWERSAVE is not set
# CONFIG_DEVFREQ_GOV_SIMPLE_ONDEMAND is not set
# CONFIG_DEVFREQ_GOV_USERSPACE is not set
# CONFIG_DEVFREQ_THERMAL is not set
CONFIG_DEVTMPFS=y
CONFIG_DEVTMPFS_MOUNT=y
# CONFIG_DEVTMPFS_SAFE is not set
CONFIG_DMADEVICES=y
CONFIG_DMADEVICES_DEBUG=y
CONFIG_DMADEVICES_VDEBUG=y
CONFIG_DMA_ENGINE=y
CONFIG_DMA_OF=y
CONFIG_DMA_SHARED_BUFFER=y
CONFIG_DMA_VIRTUAL_CHANNELS=y
# CONFIG_DPM_WATCHDOG is not set
CONFIG_DTC=y
CONFIG_DT_IDLE_GENPD=y
CONFIG_DT_IDLE_STATES=y
CONFIG_DWMAC_DWC_QOS_ETH=y
# CONFIG_DWMAC_GENERIC is not set
CONFIG_DWMAC_STARFIVE=y
CONFIG_DW_AXI_DMAC=y
CONFIG_EDAC_SUPPORT=y
CONFIG_EEPROM_AT24=y
CONFIG_EFI=y
CONFIG_EFIVAR_FS=y
# CONFIG_EFI_BOOTLOADER_CONTROL is not set
# CONFIG_EFI_CAPSULE_LOADER is not set
# CONFIG_EFI_COCO_SECRET is not set
# CONFIG_EFI_DISABLE_PCI_DMA is not set
CONFIG_EFI_DISABLE_RUNTIME=y
CONFIG_EFI_EARLYCON=y
CONFIG_EFI_ESRT=y
CONFIG_EFI_GENERIC_STUB=y
CONFIG_EFI_PARAMS_FROM_FDT=y
CONFIG_EFI_RUNTIME_WRAPPERS=y
CONFIG_EFI_STUB=y
# CONFIG_EFI_TEST is not set
# CONFIG_EFI_ZBOOT is not set
CONFIG_ERRATA_SIFIVE=y
CONFIG_ERRATA_SIFIVE_CIP_1200=y
CONFIG_ERRATA_SIFIVE_CIP_453=y
# CONFIG_ERRATA_THEAD is not set
CONFIG_EXCLUSIVE_SYSTEM_RAM=y
CONFIG_EXT4_FS=y
CONFIG_EXT4_FS_POSIX_ACL=y
CONFIG_EXTCON=y
CONFIG_FAILOVER=y
CONFIG_FANOTIFY=y
CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-15"
CONFIG_FAT_DEFAULT_UTF8=y
CONFIG_FAT_FS=y
CONFIG_FIXED_PHY=y
CONFIG_FIX_EARLYCON_MEM=y
CONFIG_FONT_8x16=y
CONFIG_FONT_AUTOSELECT=y
CONFIG_FONT_SUPPORT=y
CONFIG_FPU=y
CONFIG_FS_IOMAP=y
CONFIG_FS_MBCACHE=y
CONFIG_FS_POSIX_ACL=y
CONFIG_FWNODE_MDIO=y
CONFIG_FW_LOADER_PAGED_BUF=y
CONFIG_FW_LOADER_SYSFS=y
CONFIG_GCC11_NO_ARRAY_BOUNDS=y
CONFIG_GENERIC_ALLOCATOR=y
CONFIG_GENERIC_ARCH_TOPOLOGY=y
CONFIG_GENERIC_BUG=y
CONFIG_GENERIC_BUG_RELATIVE_POINTERS=y
CONFIG_GENERIC_CLOCKEVENTS=y
CONFIG_GENERIC_CLOCKEVENTS_BROADCAST=y
CONFIG_GENERIC_CSUM=y
CONFIG_GENERIC_EARLY_IOREMAP=y
CONFIG_GENERIC_GETTIMEOFDAY=y
CONFIG_GENERIC_IDLE_POLL_SETUP=y
CONFIG_GENERIC_IOREMAP=y
CONFIG_GENERIC_IRQ_EFFECTIVE_AFF_MASK=y
CONFIG_GENERIC_IRQ_MIGRATION=y
CONFIG_GENERIC_IRQ_MULTI_HANDLER=y
CONFIG_GENERIC_IRQ_SHOW=y
CONFIG_GENERIC_IRQ_SHOW_LEVEL=y
CONFIG_GENERIC_LIB_DEVMEM_IS_ALLOWED=y
CONFIG_GENERIC_MSI_IRQ=y
CONFIG_GENERIC_MSI_IRQ_DOMAIN=y
CONFIG_GENERIC_PCI_IOMAP=y
CONFIG_GENERIC_PHY=y
CONFIG_GENERIC_PHY_MIPI_DPHY=y
CONFIG_GENERIC_PINCONF=y
CONFIG_GENERIC_PINCTRL_GROUPS=y
CONFIG_GENERIC_PINMUX_FUNCTIONS=y
CONFIG_GENERIC_SCHED_CLOCK=y
CONFIG_GENERIC_SMP_IDLE_THREAD=y
CONFIG_GENERIC_STRNCPY_FROM_USER=y
CONFIG_GENERIC_STRNLEN_USER=y
CONFIG_GENERIC_TIME_VSYSCALL=y
CONFIG_GLOB=y
CONFIG_GPIOLIB_FASTPATH_LIMIT=128
CONFIG_GPIOLIB_IRQCHIP=y
CONFIG_GPIO_CDEV=y
CONFIG_GPIO_TPS65086=y
CONFIG_HARDIRQS_SW_RESEND=y
CONFIG_HAS_DMA=y
CONFIG_HAS_IOMEM=y
CONFIG_HAS_IOPORT_MAP=y
CONFIG_HOTPLUG_CPU=y
CONFIG_HUGETLBFS=y
CONFIG_HUGETLB_PAGE=y
CONFIG_HVC_DRIVER=y
CONFIG_HVC_RISCV_SBI=y
CONFIG_HWMON=y
CONFIG_HW_RANDOM=y
CONFIG_HW_RANDOM_JH7110=y
CONFIG_HW_RANDOM_STARFIVE_VIC=y
CONFIG_I2C=y
CONFIG_I2C_ALGOBIT=y
CONFIG_I2C_BOARDINFO=y
CONFIG_I2C_CHARDEV=y
CONFIG_I2C_DESIGNWARE_CORE=y
CONFIG_I2C_DESIGNWARE_PLATFORM=y
CONFIG_IKCONFIG=y
CONFIG_IKCONFIG_PROC=y
CONFIG_INITRAMFS_SOURCE=""
CONFIG_IRQCHIP=y
CONFIG_IRQ_DOMAIN=y
CONFIG_IRQ_DOMAIN_HIERARCHY=y
CONFIG_IRQ_FORCED_THREADING=y
CONFIG_IRQ_WORK=y
CONFIG_JBD2=y
CONFIG_JH71XX_PMU=y
CONFIG_JUMP_LABEL=y
CONFIG_LIBFDT=y
CONFIG_LOCKUP_DETECTOR=y
CONFIG_LOCK_DEBUGGING_SUPPORT=y
CONFIG_LOCK_SPIN_ON_OWNER=y
CONFIG_LSM=""
CONFIG_MARVELL_PHY=y
CONFIG_MDIO_BUS=y
CONFIG_MDIO_DEVICE=y
CONFIG_MDIO_DEVRES=y
CONFIG_MEMFD_CREATE=y
CONFIG_MEMORY_ISOLATION=y
CONFIG_MEMTEST=y
CONFIG_MFD_AXP20X=y
CONFIG_MFD_AXP20X_I2C=y
CONFIG_MFD_CORE=y
CONFIG_MFD_SYSCON=y
CONFIG_MFD_TPS65086=y
CONFIG_MICREL_PHY=y
CONFIG_MICROCHIP_PHY=y
CONFIG_MIGRATION=y
CONFIG_MMC=y
CONFIG_MMC_BLOCK=y
CONFIG_MMC_DEBUG=y
CONFIG_MMC_DW=y
# CONFIG_MMC_DW_BLUEFIELD is not set
# CONFIG_MMC_DW_EXYNOS is not set
# CONFIG_MMC_DW_HI3798CV200 is not set
# CONFIG_MMC_DW_K3 is not set
# CONFIG_MMC_DW_PCI is not set
CONFIG_MMC_DW_PLTFM=y
CONFIG_MMC_DW_STARFIVE=y
CONFIG_MMIOWB=y
CONFIG_MODULES_TREE_LOOKUP=y
CONFIG_MODULES_USE_ELF_RELA=y
CONFIG_MODULE_SECTIONS=y
CONFIG_MOTORCOMM_PHY=y
CONFIG_MPILIB=y
CONFIG_MTD_SPI_NOR=y
CONFIG_MUTEX_SPIN_ON_OWNER=y
CONFIG_NAMESPACES=y
CONFIG_NEED_DMA_MAP_STATE=y
CONFIG_NET_FAILOVER=y
CONFIG_NET_FLOW_LIMIT=y
CONFIG_NET_NS=y
CONFIG_NET_SELFTESTS=y
CONFIG_NLS=y
CONFIG_NLS_CODEPAGE_437=y
CONFIG_NLS_DEFAULT="iso8859-15"
CONFIG_NLS_ISO8859_1=y
CONFIG_NLS_ISO8859_15=y
CONFIG_NO_HZ_COMMON=y
CONFIG_NO_HZ_IDLE=y
# CONFIG_NONPORTABLE is not set
CONFIG_NR_CPUS=8
CONFIG_NVMEM=y
CONFIG_NVMEM_SYSFS=y
CONFIG_NVME_CORE=y
CONFIG_NVME_HWMON=y
# CONFIG_NVME_MULTIPATH is not set
CONFIG_OF=y
CONFIG_OF_ADDRESS=y
CONFIG_OF_DMA_DEFAULT_COHERENT=y
CONFIG_OF_DYNAMIC=y
CONFIG_OF_EARLY_FLATTREE=y
CONFIG_OF_FLATTREE=y
CONFIG_OF_GPIO=y
CONFIG_OF_IRQ=y
CONFIG_OF_KOBJ=y
CONFIG_OF_MDIO=y
CONFIG_OF_OVERLAY=y
CONFIG_OF_RESOLVE=y
CONFIG_OID_REGISTRY=y
CONFIG_OVERLAY_FS_INDEX=y
CONFIG_OVERLAY_FS_METACOPY=y
CONFIG_OVERLAY_FS_REDIRECT_DIR=y
CONFIG_PADATA=y
CONFIG_PAGE_EXTENSION=y
CONFIG_PAGE_OFFSET=0xff60000000000000
CONFIG_PAGE_POOL=y
CONFIG_PAGE_REPORTING=y
CONFIG_PAGE_SIZE_LESS_THAN_256KB=y
CONFIG_PAGE_SIZE_LESS_THAN_64KB=y
CONFIG_PCI=y
CONFIG_PCIE_CADENCE=y
CONFIG_PCIE_CADENCE_HOST=y
CONFIG_PCIE_CADENCE_PLAT=y
CONFIG_PCIE_CADENCE_PLAT_HOST=y
# CONFIG_PCIE_FU740 is not set
# CONFIG_PCIE_STARFIVE is not set
CONFIG_PCI_DOMAINS=y
CONFIG_PCI_DOMAINS_GENERIC=y
CONFIG_PCI_MSI=y
CONFIG_PCI_MSI_IRQ_DOMAIN=y
CONFIG_PCS_XPCS=y
CONFIG_PERF_EVENTS=y
CONFIG_PGTABLE_LEVELS=5
CONFIG_PHYLIB=y
CONFIG_PHYLINK=y
CONFIG_PHYS_ADDR_T_64BIT=y
CONFIG_PHY_STARFIVE_DPHY_RX=y
CONFIG_PHY_STARFIVE_JH7110_PCIE=y
CONFIG_PHY_STARFIVE_JH7110_USB=y
CONFIG_PINCTRL=y
CONFIG_PINCTRL_STARFIVE_JH7100=y
CONFIG_PINCTRL_STARFIVE_JH7110=y
CONFIG_PINCTRL_STARFIVE_JH7110_AON=y
CONFIG_PINCTRL_STARFIVE_JH7110_SYS=y
CONFIG_PM=y
CONFIG_PM_ADVANCED_DEBUG=y
CONFIG_PM_CLK=y
CONFIG_PM_DEBUG=y
CONFIG_PM_DEVFREQ=y
# CONFIG_PM_DEVFREQ_EVENT is not set
CONFIG_PM_GENERIC_DOMAINS=y
CONFIG_PM_GENERIC_DOMAINS_OF=y
CONFIG_PM_OPP=y
CONFIG_PORTABLE=y
CONFIG_POSIX_CPU_TIMERS_TASK_WORK=y
CONFIG_POSIX_MQUEUE=y
CONFIG_POSIX_MQUEUE_SYSCTL=y
CONFIG_POWER_RESET=y
CONFIG_POWER_RESET_GPIO_RESTART=y
CONFIG_POWER_RESET_SYSCON=y
CONFIG_POWER_RESET_SYSCON_POWEROFF=y
# CONFIG_POWER_RESET_TPS65086 is not set
CONFIG_PPS=y
CONFIG_PREEMPT_COUNT=y
CONFIG_PREEMPT_NONE_BUILD=y
CONFIG_PRINTK_TIME=y
CONFIG_PROC_CHILDREN=y
CONFIG_PROC_KCORE=y
CONFIG_PTDUMP_CORE=y
CONFIG_PTP_1588_CLOCK=y
CONFIG_PTP_1588_CLOCK_OPTIONAL=y
CONFIG_PWM=y
# CONFIG_PWM_SIFIVE is not set
CONFIG_PWM_SIFIVE_PTC=y
CONFIG_PWM_STARFIVE_PTC=y
CONFIG_PWM_SYSFS=y
CONFIG_QUEUED_RWLOCKS=y
CONFIG_RANDSTRUCT_NONE=y
CONFIG_RATIONAL=y
CONFIG_RCU_EQS_DEBUG=y
CONFIG_RD_GZIP=y
CONFIG_REALTEK_PHY=y
CONFIG_REGMAP=y
CONFIG_REGMAP_I2C=y
CONFIG_REGMAP_IRQ=y
CONFIG_REGMAP_MMIO=y
CONFIG_REGULATOR=y
CONFIG_REGULATOR_AXP20X=y
CONFIG_REGULATOR_TPS65086=y
# CONFIG_RESET_ATTACK_MITIGATION is not set
CONFIG_RESET_CONTROLLER=y
CONFIG_RESET_SIMPLE=y
CONFIG_RESET_STARFIVE_JH7100=y
CONFIG_RESET_STARFIVE_JH7100_AUDIO=y
CONFIG_RESET_STARFIVE_JH7110=y
CONFIG_RESET_STARFIVE_JH71X0=y
CONFIG_RFS_ACCEL=y
CONFIG_RISCV=y
CONFIG_RISCV_ALTERNATIVE=y
CONFIG_RISCV_BOOT_SPINWAIT=y
CONFIG_RISCV_DMA_NONCOHERENT=y
CONFIG_RISCV_INTC=y
CONFIG_RISCV_ISA_C=y
# CONFIG_RISCV_ISA_SVPBMT is not set
CONFIG_RISCV_ISA_ZICBOM=y
CONFIG_RISCV_PMU=y
CONFIG_RISCV_PMU_LEGACY=y
CONFIG_RISCV_PMU_SBI=y
CONFIG_RISCV_SBI=y
CONFIG_RISCV_SBI_CPUIDLE=y
CONFIG_RISCV_SBI_V01=y
CONFIG_RISCV_TIMER=y
CONFIG_RPMSG=y
CONFIG_RPMSG_CHAR=y
# CONFIG_RPMSG_CTRL is not set
CONFIG_RPMSG_NS=y
# CONFIG_RPMSG_TTY is not set
CONFIG_RPMSG_VIRTIO=y
CONFIG_RPS=y
CONFIG_RTC_CLASS=y
# CONFIG_RTC_DRV_EFI is not set
CONFIG_RTC_DRV_GOLDFISH=y
CONFIG_RTC_DRV_HYM8563=y
CONFIG_RTC_I2C_AND_SPI=y
CONFIG_RWSEM_SPIN_ON_OWNER=y
CONFIG_SCSI=y
CONFIG_SCSI_COMMON=y
CONFIG_SCSI_VIRTIO=y
CONFIG_SENSORS_SFCTEMP=y
# CONFIG_SERIAL_8250_16550A_VARIANTS is not set
CONFIG_SERIAL_8250_DW=y
CONFIG_SERIAL_8250_DWLIB=y
CONFIG_SERIAL_8250_EXTENDED=y
CONFIG_SERIAL_8250_MANY_PORTS=y
CONFIG_SERIAL_8250_NR_UARTS=6
CONFIG_SERIAL_8250_RUNTIME_UARTS=6
# CONFIG_SERIAL_8250_SHARE_IRQ is not set
CONFIG_SERIAL_EARLYCON_RISCV_SBI=y
CONFIG_SERIAL_MCTRL_GPIO=y
CONFIG_SERIAL_OF_PLATFORM=y
CONFIG_SERIAL_SIFIVE=y
CONFIG_SERIAL_SIFIVE_CONSOLE=y
CONFIG_SGL_ALLOC=y
CONFIG_SG_POOL=y
CONFIG_SIFIVE_CCACHE=y
CONFIG_SIFIVE_PLIC=y
CONFIG_SMP=y
# CONFIG_SND_SOC_STARFIVE is not set
CONFIG_SOCK_DIAG=y
CONFIG_SOCK_RX_QUEUE_MAPPING=y
# CONFIG_SOC_MICROCHIP_POLARFIRE is not set
CONFIG_SOC_SIFIVE=y
CONFIG_SOC_STARFIVE=y
# CONFIG_SOC_VIRT is not set
CONFIG_SOFTLOCKUP_DETECTOR=y
CONFIG_SOUND=y
CONFIG_SPARSEMEM_VMEMMAP_ENABLE=y
CONFIG_SPARSE_IRQ=y
CONFIG_SPI=y
CONFIG_SPI_CADENCE_QUADSPI=y
CONFIG_SPI_DYNAMIC=y
CONFIG_SPI_MASTER=y
CONFIG_SPI_MEM=y
CONFIG_SPI_SPIDEV=y
CONFIG_SRCU=y
CONFIG_STARFIVE_TIMER=y
CONFIG_STARFIVE_WATCHDOG=y
CONFIG_STMMAC_ETH=y
CONFIG_STMMAC_PLATFORM=y
CONFIG_STMMAC_SELFTESTS=y
CONFIG_SWIOTLB=y
CONFIG_SWPHY=y
CONFIG_SYNC_FILE=y
CONFIG_SYSCTL_EXCEPTION_TRACE=y
# CONFIG_SYSFB_SIMPLEFB is not set
CONFIG_THERMAL=y
CONFIG_THERMAL_DEFAULT_GOV_STEP_WISE=y
CONFIG_THERMAL_EMERGENCY_POWEROFF_DELAY_MS=0
CONFIG_THERMAL_GOV_STEP_WISE=y
CONFIG_THERMAL_OF=y
CONFIG_THREAD_INFO_IN_TASK=y
CONFIG_TICK_CPU_ACCOUNTING=y
CONFIG_TIMER_OF=y
CONFIG_TIMER_PROBE=y
CONFIG_TMPFS_POSIX_ACL=y
CONFIG_TOOLCHAIN_HAS_ZICBOM=y
CONFIG_TOOLCHAIN_HAS_ZIHINTPAUSE=y
CONFIG_TOOLCHAIN_NEEDS_EXPLICIT_ZICSR_ZIFENCEI=y
CONFIG_TREE_RCU=y
CONFIG_TREE_SRCU=y
CONFIG_TTY_PRINTK=y
CONFIG_TTY_PRINTK_LEVEL=6
CONFIG_TUNE_GENERIC=y
CONFIG_UCS2_STRING=y
CONFIG_UNINLINE_SPIN_UNLOCK=y
CONFIG_USB=y
CONFIG_USB_COMMON=y
CONFIG_USB_CONFIGFS=y
# CONFIG_USB_CONFIGFS_ACM is not set
# CONFIG_USB_CONFIGFS_ECM is not set
# CONFIG_USB_CONFIGFS_ECM_SUBSET is not set
# CONFIG_USB_CONFIGFS_EEM is not set
CONFIG_USB_CONFIGFS_F_FS=y
# CONFIG_USB_CONFIGFS_F_HID is not set
# CONFIG_USB_CONFIGFS_F_LB_SS is not set
# CONFIG_USB_CONFIGFS_F_MIDI is not set
# CONFIG_USB_CONFIGFS_F_PRINTER is not set
# CONFIG_USB_CONFIGFS_F_UAC1 is not set
# CONFIG_USB_CONFIGFS_F_UAC1_LEGACY is not set
# CONFIG_USB_CONFIGFS_F_UAC2 is not set
# CONFIG_USB_CONFIGFS_F_UVC is not set
CONFIG_USB_CONFIGFS_MASS_STORAGE=y
# CONFIG_USB_CONFIGFS_NCM is not set
# CONFIG_USB_CONFIGFS_OBEX is not set
# CONFIG_USB_CONFIGFS_RNDIS is not set
# CONFIG_USB_CONFIGFS_SERIAL is not set
CONFIG_USB_F_FS=y
CONFIG_USB_F_MASS_STORAGE=y
CONFIG_USB_GADGET=y
CONFIG_USB_LIBCOMPOSITE=y
CONFIG_USB_PCI=y
CONFIG_USB_PHY=y
CONFIG_USB_ROLE_SWITCH=y
CONFIG_USB_SUPPORT=y
# CONFIG_USB_UHCI_HCD is not set
CONFIG_USELIB=y
CONFIG_USER_NS=y
CONFIG_VFAT_FS=y
# CONFIG_VIRTIO_BLK is not set
# CONFIG_VIRTIO_NET is not set
CONFIG_VMAP_STACK=y
CONFIG_WATCHDOG_CORE=y
CONFIG_WATCHDOG_SYSFS=y
CONFIG_WERROR=y
CONFIG_WQ_WATCHDOG=y
CONFIG_XPS=y
CONFIG_XXHASH=y
CONFIG_ZLIB_INFLATE=y
CONFIG_ZONE_DMA32=y

View File

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

View File

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

View File

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

View File

@ -0,0 +1,24 @@
#!/usr/bin/env bash
# SPDX-License-Identifier: GPL-2.0-only
#
# Copyright (C) 2023 OpenWrt.org
#
set -ex
[ $# -eq 5 ] || {
echo "SYNTAX: $0 <file> <bootfs image> <rootfs image> <bootfs size> <rootfs size>"
exit 1
}
OUTPUT="$1"
BOOTFS="$2"
ROOTFS="$3"
BOOTFSSIZE="$4"
ROOTFSSIZE="$5"
set $(ptgen -o $OUTPUT -v -g -T sifiveu_spl -N loader1 -p 1024 -T sifiveu_uboot -N loader2 -p 4096 -t ef -N boot -p ${BOOTFSSIZE}M -N rootfs -p ${ROOTFSSIZE}M)
ROOTFSOFFSET=$(($7 / 512))
dd bs=512 if="$BOOTFS" of="$OUTPUT" seek=10274 conv=notrunc
dd bs=512 if="$ROOTFS" of="$OUTPUT" seek=${ROOTFSOFFSET} conv=notrunc

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -0,0 +1,113 @@
From 944b96d734199642e2ede978c48d754109ca334c Mon Sep 17 00:00:00 2001
From: Xingyu Wu <xingyu.wu@starfivetech.com>
Date: Mon, 20 Mar 2023 21:54:31 +0800
Subject: [PATCH 059/122] dt-bindings: timer: Add timer for StarFive JH7110 SoC
Add bindings for the timer on the JH7110 RISC-V SoC
by StarFive Technology Ltd.
Signed-off-by: Xingyu Wu <xingyu.wu@starfivetech.com>
Reviewed-by: Krzysztof Kozlowski <krzysztof.kozlowski@linaro.org>
---
.../bindings/timer/starfive,jh7110-timer.yaml | 95 +++++++++++++++++++
1 file changed, 95 insertions(+)
create mode 100644 Documentation/devicetree/bindings/timer/starfive,jh7110-timer.yaml
--- /dev/null
+++ b/Documentation/devicetree/bindings/timer/starfive,jh7110-timer.yaml
@@ -0,0 +1,95 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/timer/starfive,jh7110-timer.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: StarFive JH7110 Timer
+maintainers:
+ - Xingyu Wu <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";
+ };
+

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -0,0 +1,32 @@
From 598083825494088f927fa42c5a7bb2872029a7bc Mon Sep 17 00:00:00 2001
From: Changhuang Liang <changhuang.liang@starfivetech.com>
Date: Thu, 18 May 2023 23:01:59 -0700
Subject: [PATCH 070/122] dt-bindings: power: Add power-domain header for
JH7110
Add power-domain header for JH7110 SoC, it can use to operate dphy
power.
Signed-off-by: Changhuang Liang <changhuang.liang@starfivetech.com>
---
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

View File

@ -0,0 +1,28 @@
From d83b51f60997365b80637f71924ab3dec91d5b77 Mon Sep 17 00:00:00 2001
From: Changhuang Liang <changhuang.liang@starfivetech.com>
Date: Thu, 18 May 2023 23:02:00 -0700
Subject: [PATCH 071/122] soc: starfive: Replace SOC_STARFIVE with
ARCH_STARFIVE
Using ARCH_FOO symbol is preferred than SOC_FOO.
Reviewed-by: Conor Dooley <conor.dooley@microchip.com>
Reviewed-by: Walker Chen <walker.chen@starfivetech.com>
Signed-off-by: Changhuang Liang <changhuang.liang@starfivetech.com>
---
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.

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

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

Some files were not shown because too many files have changed in this diff Show More