Merge Official Source

Signed-off-by: Tianling Shen <cnsztl@immortalwrt.org>
This commit is contained in:
Tianling Shen 2024-09-03 15:09:11 +08:00
commit 0b9180b7cb
No known key found for this signature in database
GPG Key ID: 6850B6345C862176
156 changed files with 68565 additions and 31 deletions

View File

@ -110,10 +110,10 @@ define Build/U-Boot/Target
endef
define Build/Configure/U-Boot
+$(MAKE) $(PKG_JOBS) -C $(PKG_BUILD_DIR) $(UBOOT_CONFIGURE_VARS) $(UBOOT_CONFIG)_config
+$(MAKE) $(PKG_JOBS) -C $(PKG_BUILD_DIR) CROSS_COMPILE=$(TARGET_CROSS) $(UBOOT_CONFIGURE_VARS) $(UBOOT_CONFIG)_config
$(if $(strip $(UBOOT_CUSTOMIZE_CONFIG)),
$(PKG_BUILD_DIR)/scripts/config --file $(PKG_BUILD_DIR)/.config $(UBOOT_CUSTOMIZE_CONFIG)
+$(MAKE) $(PKG_JOBS) -C $(PKG_BUILD_DIR) $(UBOOT_CONFIGURE_VARS) oldconfig)
+$(MAKE) $(PKG_JOBS) -C $(PKG_BUILD_DIR) CROSS_COMPILE=$(TARGET_CROSS) $(UBOOT_CONFIGURE_VARS) oldconfig)
endef
ifndef UBOOT_USE_INTREE_DTC

View File

@ -686,7 +686,7 @@ define U-Boot/mt7988_rfb-spim-nand
BL2_BOOTDEV:=spim-nand
BL2_SOC:=mt7988
BL2_DDRTYPE:=comb
DEPENDS:=+trusted-firmware-a-mt7988-spim-nand-comb
DEPENDS:=+trusted-firmware-a-mt7988-spim-nand-comb +trusted-firmware-a-mt7988-spim-nand-ubi-comb
endef
define U-Boot/mt7988_rfb-snand

View File

@ -87,7 +87,7 @@
CONFIG_CLK=y
--- a/configs/mt7981_rfb_defconfig
+++ b/configs/mt7981_rfb_defconfig
@@ -11,7 +11,23 @@ CONFIG_DEBUG_UART_BASE=0x11002000
@@ -11,7 +11,22 @@ CONFIG_DEBUG_UART_BASE=0x11002000
CONFIG_DEBUG_UART_CLOCK=40000000
CONFIG_SYS_LOAD_ADDR=0x46000000
CONFIG_DEBUG_UART=y
@ -106,13 +106,12 @@
+CONFIG_LED_BLINK=y
+CONFIG_LED_GPIO=y
+CONFIG_SPI_BOOT=y
+CONFIG_NAND_BOOT=y
+CONFIG_BOOTSTD_DEFAULTS=y
+CONFIG_BOOTSTD_FULL=y
CONFIG_DEFAULT_FDT_FILE="mt7981-rfb"
CONFIG_SYS_CBSIZE=512
CONFIG_SYS_PBSIZE=1049
@@ -22,23 +38,74 @@ CONFIG_SYS_PROMPT="MT7981> "
@@ -22,23 +37,74 @@ CONFIG_SYS_PROMPT="MT7981> "
# CONFIG_BOOTM_PLAN9 is not set
# CONFIG_BOOTM_RTEMS is not set
# CONFIG_BOOTM_VXWORKS is not set
@ -278,7 +277,7 @@
CONFIG_CLK=y
--- a/configs/mt7981_snfi_nand_rfb_defconfig
+++ b/configs/mt7981_snfi_nand_rfb_defconfig
@@ -12,7 +12,23 @@ CONFIG_DEBUG_UART_BASE=0x11002000
@@ -12,7 +12,22 @@ CONFIG_DEBUG_UART_BASE=0x11002000
CONFIG_DEBUG_UART_CLOCK=40000000
CONFIG_SYS_LOAD_ADDR=0x46000000
CONFIG_DEBUG_UART=y
@ -297,13 +296,12 @@
+CONFIG_LED_BLINK=y
+CONFIG_LED_GPIO=y
+CONFIG_SPI_BOOT=y
+CONFIG_NAND_BOOT=y
+CONFIG_BOOTSTD_DEFAULTS=y
+CONFIG_BOOTSTD_FULL=y
CONFIG_DEFAULT_FDT_FILE="mt7981-snfi-nand-rfb"
CONFIG_LOGLEVEL=7
CONFIG_LOG=y
@@ -22,22 +38,73 @@ CONFIG_SYS_PBSIZE=1049
@@ -22,22 +37,73 @@ CONFIG_SYS_PBSIZE=1049
# CONFIG_BOOTM_PLAN9 is not set
# CONFIG_BOOTM_RTEMS is not set
# CONFIG_BOOTM_VXWORKS is not set

View File

@ -81,7 +81,7 @@
+CONFIG_OF_SYSTEM_SETUP=y
--- a/configs/mt7981_rfb_defconfig
+++ b/configs/mt7981_rfb_defconfig
@@ -135,3 +135,4 @@ CONFIG_DM_SPI=y
@@ -134,3 +134,4 @@ CONFIG_DM_SPI=y
CONFIG_MTK_SPIM=y
CONFIG_HEXDUMP=y
CONFIG_LMB_MAX_REGIONS=64
@ -95,7 +95,7 @@
+CONFIG_OF_SYSTEM_SETUP=y
--- a/configs/mt7981_snfi_nand_rfb_defconfig
+++ b/configs/mt7981_snfi_nand_rfb_defconfig
@@ -120,3 +120,4 @@ CONFIG_DM_SERIAL=y
@@ -119,3 +119,4 @@ CONFIG_DM_SERIAL=y
CONFIG_MTK_SERIAL=y
CONFIG_HEXDUMP=y
CONFIG_LMB_MAX_REGIONS=64

View File

@ -1,3 +1,4 @@
--- /dev/null
+++ b/configs/mt7986_xiaomi_redmi-ax6000_defconfig
@@ -0,0 +1,104 @@
+CONFIG_ARM=y

View File

@ -206,7 +206,7 @@
+};
--- /dev/null
+++ b/configs/mt7981_openwrt-one-nor_defconfig
@@ -0,0 +1,129 @@
@@ -0,0 +1,128 @@
+CONFIG_ARM=y
+CONFIG_SYS_HAS_NONCACHED_MEMORY=y
+CONFIG_POSITION_INDEPENDENT=y
@ -224,7 +224,6 @@
+CONFIG_SYS_LOAD_ADDR=0x46000000
+CONFIG_DEBUG_UART=y
+CONFIG_FIT=y
+CONFIG_NAND_BOOT=y
+CONFIG_SPI_BOOT=y
+CONFIG_AUTOBOOT_MENU_SHOW=y
+CONFIG_USE_PREBOOT=y
@ -338,7 +337,7 @@
+CONFIG_LMB_MAX_REGIONS=64
--- /dev/null
+++ b/configs/mt7981_openwrt-one-spi-nand_defconfig
@@ -0,0 +1,130 @@
@@ -0,0 +1,129 @@
+CONFIG_ARM=y
+CONFIG_SYS_HAS_NONCACHED_MEMORY=y
+CONFIG_POSITION_INDEPENDENT=y
@ -355,7 +354,6 @@
+CONFIG_SYS_LOAD_ADDR=0x46000000
+CONFIG_DEBUG_UART=y
+CONFIG_FIT=y
+CONFIG_NAND_BOOT=y
+CONFIG_SPI_BOOT=y
+CONFIG_AUTOBOOT_MENU_SHOW=y
+CONFIG_USE_PREBOOT=y

View File

@ -90,7 +90,7 @@ mediatek_setup_interfaces()
ucidef_set_interfaces_lan_wan "lan0 lan1 lan2 lan3" eth1
;;
mediatek,mt7988a-rfb)
ucidef_set_interfaces_lan_wan "lan0 lan1 lan2 lan3 eth1" eth2
ucidef_set_interfaces_lan_wan "lan0 lan1 lan2 lan3 eth2" eth1
;;
mercusys,mr90x-v1)
ucidef_set_interfaces_lan_wan "lan0 lan1 lan2" eth1

View File

@ -4,28 +4,46 @@ move_config() {
. /lib/upgrade/common.sh
local device="$1"
local fstype="$2"
[ -n "$device" ] && [ -b "$device" ] && {
mount -t vfat "$device" /mnt
mount -t "${fstype}" "$device" /mnt
[ -f "/mnt/$BACKUP_FILE" ] && mv -f "/mnt/$BACKUP_FILE" /
umount /mnt
}
}
octeon_get_n821_disk() {
local partnum=$1
local MAJOR MINOR DEVNAME DEVTYPE
while read line; do
export -n "${line}"
done < $(find /sys/bus/platform/devices/16f0000000000.ehci/ -path \*block/sd[a-z]/uevent)
echo "/dev/${DEVNAME}${partnum}"
}
octeon_move_config() {
. /lib/functions.sh
case "$(board_name)" in
erlite|\
ubnt,usg)
move_config "/dev/sda1"
move_config "/dev/sda1" "vfat"
;;
itus,shield-router)
move_config "/dev/mmcblk1p1"
move_config "/dev/mmcblk1p1" "vfat"
;;
ubnt,edgerouter-4 | \
er|\
ubnt,edgerouter-4|\
ubnt,edgerouter-6p)
move_config "/dev/mmcblk0p1"
move_config "/dev/mmcblk0p1" "vfat"
;;
cisco,vedge1000)
# Copy from the internal USB disk's first partition.
# It is resolved from the device path to not be dependent on which
# /dev/sd? path it is at, nor which UUID it happens to have.
move_config "$(octeon_get_n821_disk 1)" "ext2"
;;
esac
}

View File

@ -2,11 +2,21 @@
# Copyright (C) 2021 OpenWrt.org
#
if [ -x /usr/sbin/blkid ]; then
RAMFS_COPY_BIN="/usr/sbin/blkid"
fi
platform_get_rootfs() {
local rootfsdev
local rootpartuuid
if read cmdline < /proc/cmdline; then
case "$cmdline" in
*root=PARTUUID=*)
rootpartuuid="${cmdline##*root=PARTUUID=}"
rootpartuuid="${rootpartuuid%% *}"
rootfsdev="$(blkid -o device -t PARTUUID="${rootpartuuid}")"
;;
*root=*)
rootfsdev="${cmdline##*root=}"
rootfsdev="${rootfsdev%% *}"
@ -17,10 +27,20 @@ platform_get_rootfs() {
fi
}
platform_get_n821_disk() {
local partnum=$1
local DEVNAME
while read line; do
export -n "${line}"
done < $(find /sys/bus/platform/devices/16f0000000000.ehci/ -path \*block/sd[a-z]/uevent)
echo "/dev/${DEVNAME}${partnum}"
}
platform_copy_config_helper() {
local device=$1
local fstype=$2
mount -t vfat "$device" /mnt
mount -t "${fstype}" "$device" /mnt
cp -af "$UPGRADE_BACKUP" "/mnt/$BACKUP_FILE"
umount /mnt
}
@ -29,14 +49,18 @@ platform_copy_config() {
case "$(board_name)" in
erlite|\
ubnt,usg)
platform_copy_config_helper /dev/sda1
platform_copy_config_helper /dev/sda1 vfat
;;
itus,shield-router)
platform_copy_config_helper /dev/mmcblk1p1
platform_copy_config_helper /dev/mmcblk1p1 vfat
;;
er|\
ubnt,edgerouter-4|\
ubnt,edgerouter-6p)
platform_copy_config_helper /dev/mmcblk0p1
platform_copy_config_helper /dev/mmcblk0p1 vfat
;;
cisco,vedge1000)
platform_copy_config_helper "$(platform_get_n821_disk 1)" ext2
;;
esac
}
@ -60,14 +84,26 @@ platform_do_flash() {
echo "flashing Itus Kernel to /boot/$kernel (/dev/mmblk1p1)"
tar -Oxf $tar_file "$board_dir/kernel" > /boot/$kernel
else
mount -t vfat /dev/$kernel /boot
if [ "${board}" = "cisco,vedge1000" ]; then
local rootpartuuid
rootpartuuid="$(/usr/sbin/blkid -o value -s PARTUUID "${rootfs}")"
if [ -n "${rootpartuuid}" ]; then
echo "setting root partition to PARTUUID=${rootpartuuid}"
fw_setenv bootcmd 'usb start; ext2load usb 0:1 $loadaddr vmlinux.64; bootoctlinux $loadaddr coremask=f endbootargs rootfstype=squashfs rootwait root=PARTUUID='"${rootpartuuid}"
else
echo "WARNING: unable to figure out root partition UUID, leaving bootcmd unchanged"
fi
mount -t ext2 "${kernel}" /boot
else
mount -t vfat "${kernel}" /boot
fi
[ -f /boot/vmlinux.64 -a ! -L /boot/vmlinux.64 ] && {
mv /boot/vmlinux.64 /boot/vmlinux.64.previous
mv /boot/vmlinux.64.md5 /boot/vmlinux.64.md5.previous
}
echo "flashing kernel to /dev/$kernel"
echo "flashing kernel to $(awk '/\/boot/ {print $1}' /proc/mounts)"
tar xf $tar_file $board_dir/kernel -O > /boot/vmlinux.64
md5sum /boot/vmlinux.64 | cut -f1 -d " " > /boot/vmlinux.64.md5
fi
@ -85,20 +121,27 @@ platform_do_upgrade() {
local rootfs="$(platform_get_rootfs)"
local kernel=
if [ ! -b "${rootfs}" ] && [ "${board}" = "cisco,vedge1000" ]; then
# Default to the built-in USB disk for N821
rootfs="$(platform_get_n821_disk 2)"
fi
[ -b "${rootfs}" ] || return 1
case "$board" in
er | \
ubnt,edgerouter-4 | \
ubnt,edgerouter-6p)
kernel=mmcblk0p1
kernel=/dev/mmcblk0p1
;;
erlite|\
ubnt,usg)
kernel=sda1
kernel=/dev/sda1
;;
itus,shield-router)
kernel=ItusrouterImage
;;
cisco,vedge1000)
kernel="$(platform_get_n821_disk 1)"
;;
*)
return 1
esac
@ -122,7 +165,8 @@ platform_check_image() {
itus,shield-router | \
ubnt,edgerouter-4 | \
ubnt,edgerouter-6p | \
ubnt,usg)
ubnt,usg | \
cisco,vedge1000)
local kernel_length=$(tar xf $tar_file $board_dir/kernel -O | wc -c 2> /dev/null)
local rootfs_length=$(tar xf $tar_file $board_dir/root -O | wc -c 2> /dev/null)
[ "$kernel_length" = 0 -o "$rootfs_length" = 0 ] && {

View File

@ -100,13 +100,16 @@ define Device/cisco_vedge1000
DEVICE_MODEL := vEdge 1000
BOARD_NAME := cisco,vedge1000
DEVICE_PACKAGES += \
blkid \
kmod-hwmon-jc42 \
kmod-hwmon-max6697 \
kmod-of-mdio \
kmod-rtc-ds1307 \
kmod-usb-dwc3 \
kmod-usb-storage-uas \
kmod-usb3
kmod-usb3 \
sfdisk \
uboot-envtools
KERNEL := kernel-bin | append-dtb-elf
KERNEL_DEPENDS := $$(wildcard $(DTS_DIR)/$(DEVICE_DTS).dts)
DEVICE_DTS := cn6130_cisco_vedge1000

View File

@ -0,0 +1,164 @@
#include "mt7628an.dtsi"
#include <dt-bindings/gpio/gpio.h>
#include <dt-bindings/input/input.h>
#include <dt-bindings/leds/common.h>
/ {
compatible = "yuncore,cpe200", "mediatek,mt7628an-soc";
chosen {
bootargs = "console=ttyS0,57600";
};
aliases {
label-mac = &ethernet;
led-boot = &led_power;
led-failsafe = &led_power;
led-running = &led_power;
led-upgrade = &led_power;
};
keys {
compatible = "gpio-keys";
reset {
label = "reset";
gpios = <&gpio 38 GPIO_ACTIVE_LOW>;
linux,code = <KEY_RESTART>;
};
mode {
label = "mode";
linux,input-type = <EV_SW>;
linux,code = <BTN_0>;
gpios = <&gpio 0 GPIO_ACTIVE_LOW>;
debounce-interval = <60>;
};
};
leds {
compatible = "gpio-leds";
led_power: power {
function = LED_FUNCTION_POWER;
color = <LED_COLOR_ID_GREEN>;
gpios = <&gpio 11 GPIO_ACTIVE_LOW>;
};
lan {
function = LED_FUNCTION_LAN;
color = <LED_COLOR_ID_GREEN>;
gpios = <&gpio 43 GPIO_ACTIVE_LOW>;
};
wan {
function = LED_FUNCTION_WAN;
color = <LED_COLOR_ID_GREEN>;
gpios = <&gpio 39 GPIO_ACTIVE_LOW>;
};
};
watchdog {
compatible = "linux,wdt-gpio";
gpios = <&gpio 37 GPIO_ACTIVE_HIGH>;
hw_algo = "toggle";
hw_margin_ms = <20000>;
always-running;
};
};
&spi0 {
status = "okay";
flash@0 {
compatible = "jedec,spi-nor";
reg = <0>;
spi-max-frequency = <10000000>;
partitions {
compatible = "fixed-partitions";
#address-cells = <1>;
#size-cells = <1>;
partition@0 {
label = "u-boot";
reg = <0x0 0x30000>;
read-only;
};
partition@30000 {
label = "u-boot-env";
reg = <0x30000 0x10000>;
read-only;
};
partition@40000 {
label = "factory";
reg = <0x40000 0x10000>;
read-only;
nvmem-layout {
compatible = "fixed-layout";
#address-cells = <1>;
#size-cells = <1>;
macaddr_factory_4: macaddr@4 {
reg = <0x4 0x6>;
};
eeprom_factory_8000: eeprom@8000 {
reg = <0x8000 0x600>;
};
macaddr_factory_8004: macaddr@8004 {
reg = <0x8004 0x6>;
};
};
};
partition@50000 {
compatible = "denx,uimage";
label = "firmware";
reg = <0x50000 0x7b0000>;
};
};
};
};
&ethernet {
nvmem-cells = <&macaddr_factory_4>;
nvmem-cell-names = "mac-address";
};
&esw {
mediatek,portmap = <0x2f>;
};
&pcie {
status = "okay";
};
&pcie0 {
mt76@0,0 {
reg = <0x0000 0 0 0 0>;
ieee80211-freq-limit = <5000000 6000000>;
nvmem-cells = <&eeprom_factory_8000>, <&macaddr_factory_8004>;
nvmem-cell-names = "eeprom", "mac-address";
led {
led-sources = <0>;
led-active-low;
};
};
};
&state_default {
gpio {
groups = "pwm0", "i2c", "refclk", "wdt", "i2s", "spi cs1",
"spis", "gpio", "p0led_an", "p1led_an", "p2led_an",
"p3led_an", "p4led_an", "wled_kn", "p0led_kn",
"p1led_kn", "p2led_kn", "p3led_kn", "p4led_kn", "wled_an";
function = "gpio";
};
};

View File

@ -1141,6 +1141,14 @@ define Device/xiaomi_mi-ra75
endef
TARGET_DEVICES += xiaomi_mi-ra75
define Device/yuncore_cpe200
IMAGE_SIZE := 7872k
DEVICE_VENDOR := Yuncore
DEVICE_MODEL := CPE200
DEVICE_PACKAGES := -kmod-mt7603 kmod-mt7615e kmod-mt7663-firmware-ap kmod-mt7663-firmware-sta
endef
TARGET_DEVICES += yuncore_cpe200
define Device/yuncore_m300
IMAGE_SIZE := 7872k
DEVICE_VENDOR := Yuncore

View File

@ -19,6 +19,7 @@ asus,rt-n12-vp-b1|\
netgear,r6020|\
netgear,r6080|\
netgear,r6120|\
yuncore,cpe200|\
yuncore,m300)
ucidef_set_led_switch "lan" "lan" "green:lan" "switch0" "0xf"
ucidef_set_led_switch "wan" "wan" "green:wan" "switch0" "0x10"

View File

@ -204,6 +204,10 @@ ramips_setup_interfaces()
ucidef_add_switch "switch0" \
"0:lan:2" "2:lan:1" "4:wan" "6@eth0"
;;
yuncore,cpe200)
ucidef_add_switch "switch0" \
"0:lan" "4:wan" "6@eth0"
;;
zbtlink,zbt-we1226)
ucidef_add_switch "switch0" \
"0:lan:2" "1:lan:1" "4:wan" "6@eth0"

View File

@ -11,6 +11,7 @@ FEATURES:=ext4
KERNELNAME:=Image dtbs
KERNEL_PATCHVER:=6.1
KERNEL_TESTING_PATCHVER:=6.6
include $(INCLUDE_DIR)/target.mk

View File

@ -0,0 +1,582 @@
CONFIG_64BIT=y
# CONFIG_ACPI is not set
CONFIG_AMBA_PL08X=y
CONFIG_ARCH_CLOCKSOURCE_INIT=y
CONFIG_ARCH_DMA_ADDR_T_64BIT=y
CONFIG_ARCH_HIBERNATION_POSSIBLE=y
CONFIG_ARCH_MMAP_RND_BITS=18
CONFIG_ARCH_MMAP_RND_BITS_MAX=24
CONFIG_ARCH_MMAP_RND_BITS_MIN=18
CONFIG_ARCH_MMAP_RND_COMPAT_BITS_MAX=17
CONFIG_ARCH_OPTIONAL_KERNEL_RWX=y
CONFIG_ARCH_OPTIONAL_KERNEL_RWX_DEFAULT=y
# CONFIG_ARCH_RV32I is not set
CONFIG_ARCH_RV64I=y
CONFIG_ARCH_SELECT_MEMORY_MODEL=y
CONFIG_ARCH_SIFIVE=y
CONFIG_ARCH_SPARSEMEM_ENABLE=y
CONFIG_ARCH_STACKWALK=y
CONFIG_ARCH_STARFIVE=y
# CONFIG_ARCH_THEAD is not set
CONFIG_ARCH_WANTS_THP_SWAP=y
CONFIG_ARM_AMBA=y
# CONFIG_ARM_MHU_V2 is not set
CONFIG_ASN1=y
CONFIG_ASSOCIATIVE_ARRAY=y
CONFIG_AUXILIARY_BUS=y
# CONFIG_AX45MP_L2_CACHE is not set
# CONFIG_BT_AICUSB is not set
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_ANDES is not set
CONFIG_ERRATA_STARFIVE_JH7100=y
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_IPMS_CAN is not set
CONFIG_IRQCHIP=y
CONFIG_IRQ_DOMAIN=y
CONFIG_IRQ_DOMAIN_HIERARCHY=y
CONFIG_IRQ_FORCED_THREADING=y
CONFIG_IRQ_STACKS=y
CONFIG_IRQ_WORK=y
CONFIG_JBD2=y
CONFIG_JH71XX_PMU=y
CONFIG_JUMP_LABEL=y
CONFIG_LIBFDT=y
CONFIG_LOCKUP_DETECTOR=y
CONFIG_LOCK_DEBUGGING_SUPPORT=y
CONFIG_LOCK_SPIN_ON_OWNER=y
CONFIG_LSM=""
CONFIG_MARVELL_PHY=y
CONFIG_MDIO_BUS=y
CONFIG_MDIO_DEVICE=y
CONFIG_MDIO_DEVRES=y
CONFIG_MEMFD_CREATE=y
CONFIG_MEMORY_ISOLATION=y
CONFIG_MEMTEST=y
CONFIG_MFD_AXP20X=y
CONFIG_MFD_AXP20X_I2C=y
CONFIG_MFD_CORE=y
CONFIG_MFD_SYSCON=y
CONFIG_MFD_TPS65086=y
CONFIG_MICREL_PHY=y
CONFIG_MICROCHIP_PHY=y
CONFIG_MIGRATION=y
CONFIG_MMC=y
CONFIG_MMC_BLOCK=y
CONFIG_MMC_DEBUG=y
CONFIG_MMC_DW=y
# CONFIG_MMC_DW_BLUEFIELD is not set
# CONFIG_MMC_DW_EXYNOS is not set
# CONFIG_MMC_DW_HI3798CV200 is not set
# CONFIG_MMC_DW_K3 is not set
# CONFIG_MMC_DW_PCI is not set
CONFIG_MMC_DW_PLTFM=y
CONFIG_MMC_DW_STARFIVE=y
CONFIG_MMIOWB=y
CONFIG_MODULES_TREE_LOOKUP=y
CONFIG_MODULES_USE_ELF_RELA=y
CONFIG_MODULE_SECTIONS=y
CONFIG_MOTORCOMM_PHY=y
CONFIG_MPILIB=y
CONFIG_MTD_SPI_NOR=y
CONFIG_MUTEX_SPIN_ON_OWNER=y
CONFIG_NAMESPACES=y
CONFIG_NEED_DMA_MAP_STATE=y
CONFIG_NET_FAILOVER=y
CONFIG_NET_FLOW_LIMIT=y
CONFIG_NET_NS=y
CONFIG_NET_SELFTESTS=y
CONFIG_NLS=y
CONFIG_NLS_CODEPAGE_437=y
CONFIG_NLS_DEFAULT="iso8859-15"
CONFIG_NLS_ISO8859_1=y
CONFIG_NLS_ISO8859_15=y
CONFIG_NO_HZ_COMMON=y
CONFIG_NO_HZ_IDLE=y
CONFIG_NONPORTABLE=y
CONFIG_NR_CPUS=8
CONFIG_NVMEM=y
CONFIG_NVMEM_SYSFS=y
CONFIG_NVME_CORE=y
CONFIG_NVME_HWMON=y
# CONFIG_NVME_MULTIPATH is not set
CONFIG_OF=y
CONFIG_OF_ADDRESS=y
# CONFIG_OF_CONFIGFS is not set
CONFIG_OF_DMA_DEFAULT_COHERENT=y
CONFIG_OF_DYNAMIC=y
CONFIG_OF_EARLY_FLATTREE=y
CONFIG_OF_FLATTREE=y
CONFIG_OF_GPIO=y
CONFIG_OF_IRQ=y
CONFIG_OF_KOBJ=y
CONFIG_OF_MDIO=y
CONFIG_OF_OVERLAY=y
CONFIG_OF_RESOLVE=y
CONFIG_OID_REGISTRY=y
CONFIG_OVERLAY_FS_INDEX=y
CONFIG_OVERLAY_FS_METACOPY=y
CONFIG_OVERLAY_FS_REDIRECT_DIR=y
CONFIG_PADATA=y
CONFIG_PAGE_EXTENSION=y
CONFIG_PAGE_OFFSET=0xff60000000000000
CONFIG_PAGE_POOL=y
CONFIG_PAGE_REPORTING=y
CONFIG_PAGE_SIZE_LESS_THAN_256KB=y
CONFIG_PAGE_SIZE_LESS_THAN_64KB=y
CONFIG_PCI=y
CONFIG_PCIE_CADENCE=y
CONFIG_PCIE_CADENCE_HOST=y
CONFIG_PCIE_CADENCE_PLAT=y
CONFIG_PCIE_CADENCE_PLAT_HOST=y
# CONFIG_PCIE_FU740 is not set
CONFIG_PCIE_STARFIVE_HOST=y
CONFIG_PCI_DOMAINS=y
CONFIG_PCI_DOMAINS_GENERIC=y
CONFIG_PCI_MSI=y
CONFIG_PCI_MSI_IRQ_DOMAIN=y
CONFIG_PCS_XPCS=y
CONFIG_PERF_EVENTS=y
CONFIG_PGTABLE_LEVELS=5
CONFIG_PHYLIB=y
CONFIG_PHYLINK=y
CONFIG_PHYS_ADDR_T_64BIT=y
# CONFIG_PHYS_RAM_BASE_FIXED is not set
CONFIG_PHY_STARFIVE_DPHY_RX=y
CONFIG_PHY_STARFIVE_JH7110_DPHY_RX=y
CONFIG_PHY_STARFIVE_JH7110_PCIE=y
CONFIG_PHY_STARFIVE_JH7110_USB=y
CONFIG_PINCTRL=y
CONFIG_PINCTRL_STARFIVE_JH7100=y
CONFIG_PINCTRL_STARFIVE_JH7110=y
CONFIG_PINCTRL_STARFIVE_JH7110_AON=y
CONFIG_PINCTRL_STARFIVE_JH7110_SYS=y
CONFIG_PM=y
CONFIG_PM_ADVANCED_DEBUG=y
CONFIG_PM_CLK=y
CONFIG_PM_DEBUG=y
CONFIG_PM_DEVFREQ=y
# CONFIG_PM_DEVFREQ_EVENT is not set
CONFIG_PM_GENERIC_DOMAINS=y
CONFIG_PM_GENERIC_DOMAINS_OF=y
CONFIG_PM_OPP=y
CONFIG_PORTABLE=y
CONFIG_POSIX_CPU_TIMERS_TASK_WORK=y
CONFIG_POSIX_MQUEUE=y
CONFIG_POSIX_MQUEUE_SYSCTL=y
CONFIG_POWER_RESET=y
CONFIG_POWER_RESET_GPIO_RESTART=y
CONFIG_POWER_RESET_SYSCON=y
CONFIG_POWER_RESET_SYSCON_POWEROFF=y
# CONFIG_POWER_RESET_TPS65086 is not set
CONFIG_PPS=y
CONFIG_PREEMPT_COUNT=y
CONFIG_PREEMPT_NONE_BUILD=y
CONFIG_PRINTK_TIME=y
CONFIG_PROC_CHILDREN=y
CONFIG_PROC_KCORE=y
CONFIG_PTDUMP_CORE=y
CONFIG_PTP_1588_CLOCK=y
CONFIG_PTP_1588_CLOCK_OPTIONAL=y
CONFIG_PWM=y
CONFIG_PWM_OCORES=y
# CONFIG_PWM_SIFIVE is not set
CONFIG_PWM_SIFIVE_PTC=y
CONFIG_PWM_STARFIVE_PTC=y
CONFIG_PWM_SYSFS=y
CONFIG_QUEUED_RWLOCKS=y
CONFIG_RANDSTRUCT_NONE=y
CONFIG_RATIONAL=y
CONFIG_RCU_EQS_DEBUG=y
CONFIG_RD_GZIP=y
CONFIG_REALTEK_PHY=y
CONFIG_REGMAP=y
CONFIG_REGMAP_I2C=y
CONFIG_REGMAP_IRQ=y
CONFIG_REGMAP_MMIO=y
CONFIG_REGULATOR=y
CONFIG_REGULATOR_AXP20X=y
CONFIG_REGULATOR_STARFIVE_JH7110=y
CONFIG_REGULATOR_TPS65086=y
# CONFIG_RESET_ATTACK_MITIGATION is not set
CONFIG_RESET_CONTROLLER=y
CONFIG_RESET_SIMPLE=y
CONFIG_RESET_STARFIVE_JH7100=y
CONFIG_RESET_STARFIVE_JH7100_AUDIO=y
CONFIG_RESET_STARFIVE_JH7110=y
CONFIG_RESET_STARFIVE_JH71X0=y
CONFIG_RFS_ACCEL=y
CONFIG_RISCV=y
CONFIG_RISCV_ALTERNATIVE=y
CONFIG_RISCV_BOOT_SPINWAIT=y
CONFIG_RISCV_DMA_NONCOHERENT=y
CONFIG_RISCV_INTC=y
CONFIG_RISCV_ISA_C=y
CONFIG_RISCV_ISA_FALLBACK=y
CONFIG_RISCV_ISA_SVNAPOT=y
# CONFIG_RISCV_ISA_SVPBMT is not set
CONFIG_RISCV_ISA_V=y
CONFIG_RISCV_ISA_V_DEFAULT_ENABLE=y
CONFIG_RISCV_ISA_ZBB=y
# CONFIG_RISCV_ISA_ZICBOM is not set
CONFIG_RISCV_ISA_ZICBOZ=y
CONFIG_RISCV_PMU=y
CONFIG_RISCV_PMU_LEGACY=y
CONFIG_RISCV_PMU_SBI=y
CONFIG_RISCV_SBI=y
CONFIG_RISCV_SBI_CPUIDLE=y
CONFIG_RISCV_SBI_V01=y
CONFIG_RISCV_TIMER=y
CONFIG_RPMSG=y
CONFIG_RPMSG_CHAR=y
# CONFIG_RPMSG_CTRL is not set
CONFIG_RPMSG_NS=y
# CONFIG_RPMSG_TTY is not set
CONFIG_RPMSG_VIRTIO=y
CONFIG_RPS=y
CONFIG_RTC_CLASS=y
# CONFIG_RTC_DRV_EFI is not set
CONFIG_RTC_DRV_GOLDFISH=y
CONFIG_RTC_DRV_HYM8563=y
CONFIG_RTC_DRV_STARFIVE=y
CONFIG_RTC_I2C_AND_SPI=y
CONFIG_RWSEM_SPIN_ON_OWNER=y
CONFIG_SCSI=y
CONFIG_SCSI_COMMON=y
CONFIG_SCSI_VIRTIO=y
CONFIG_SENSORS_SFCTEMP=y
# CONFIG_SERIAL_8250_16550A_VARIANTS is not set
CONFIG_SERIAL_8250_DW=y
CONFIG_SERIAL_8250_DWLIB=y
CONFIG_SERIAL_8250_EXTENDED=y
CONFIG_SERIAL_8250_MANY_PORTS=y
CONFIG_SERIAL_8250_NR_UARTS=6
CONFIG_SERIAL_8250_RUNTIME_UARTS=6
# CONFIG_SERIAL_8250_SHARE_IRQ is not set
CONFIG_SERIAL_EARLYCON_RISCV_SBI=y
CONFIG_SERIAL_MCTRL_GPIO=y
CONFIG_SERIAL_OF_PLATFORM=y
CONFIG_SERIAL_SIFIVE=y
CONFIG_SERIAL_SIFIVE_CONSOLE=y
CONFIG_SGL_ALLOC=y
CONFIG_SG_POOL=y
CONFIG_SIFIVE_CCACHE=y
CONFIG_SIFIVE_PLIC=y
CONFIG_SMP=y
# CONFIG_SND_SOC_AC108 is not set
# CONFIG_SND_SOC_STARFIVE is not set
CONFIG_SOCK_DIAG=y
CONFIG_SOCK_RX_QUEUE_MAPPING=y
# CONFIG_SOC_MICROCHIP_POLARFIRE is not set
CONFIG_SOC_SIFIVE=y
CONFIG_SOC_STARFIVE=y
# CONFIG_SOC_VIRT is not set
CONFIG_SOFTLOCKUP_DETECTOR=y
CONFIG_SOUND=y
CONFIG_SPARSEMEM_VMEMMAP_ENABLE=y
CONFIG_SPARSE_IRQ=y
CONFIG_SPI=y
CONFIG_SPI_CADENCE_QUADSPI=y
CONFIG_SPI_DYNAMIC=y
CONFIG_SPI_MASTER=y
CONFIG_SPI_MEM=y
CONFIG_SPI_SPIDEV=y
CONFIG_SRCU=y
CONFIG_STARFIVE_TIMER=y
CONFIG_STARFIVE_JH7110_TIMER=y
CONFIG_STARFIVE_WATCHDOG=y
CONFIG_STMMAC_ETH=y
CONFIG_STMMAC_PLATFORM=y
CONFIG_STMMAC_SELFTESTS=y
CONFIG_SWIOTLB=y
CONFIG_SWPHY=y
CONFIG_SYNC_FILE=y
CONFIG_SYSCTL_EXCEPTION_TRACE=y
# CONFIG_SYSFB_SIMPLEFB is not set
CONFIG_THERMAL=y
CONFIG_THERMAL_DEFAULT_GOV_STEP_WISE=y
CONFIG_THERMAL_EMERGENCY_POWEROFF_DELAY_MS=0
CONFIG_THERMAL_GOV_STEP_WISE=y
CONFIG_THERMAL_OF=y
CONFIG_THREAD_INFO_IN_TASK=y
CONFIG_THREAD_SIZE_ORDER=2
CONFIG_TICK_CPU_ACCOUNTING=y
CONFIG_TIMER_OF=y
CONFIG_TIMER_PROBE=y
CONFIG_TMPFS_POSIX_ACL=y
CONFIG_TOOLCHAIN_HAS_ZICBOM=y
CONFIG_TOOLCHAIN_HAS_ZIHINTPAUSE=y
CONFIG_TOOLCHAIN_NEEDS_EXPLICIT_ZICSR_ZIFENCEI=y
# CONFIG_TOUCHSCREEN_TINKER_FT5406 is not set
CONFIG_TREE_RCU=y
CONFIG_TREE_SRCU=y
CONFIG_TTY_PRINTK=y
CONFIG_TTY_PRINTK_LEVEL=6
CONFIG_TUNE_GENERIC=y
CONFIG_UCS2_STRING=y
CONFIG_UNINLINE_SPIN_UNLOCK=y
CONFIG_USB=y
CONFIG_USB_COMMON=y
CONFIG_USB_CONFIGFS=y
# CONFIG_USB_CONFIGFS_ACM is not set
# CONFIG_USB_CONFIGFS_ECM is not set
# CONFIG_USB_CONFIGFS_ECM_SUBSET is not set
# CONFIG_USB_CONFIGFS_EEM is not set
CONFIG_USB_CONFIGFS_F_FS=y
# CONFIG_USB_CONFIGFS_F_HID is not set
# CONFIG_USB_CONFIGFS_F_LB_SS is not set
# CONFIG_USB_CONFIGFS_F_MIDI is not set
# CONFIG_USB_CONFIGFS_F_MIDI2 is not set
# CONFIG_USB_CONFIGFS_F_PRINTER is not set
# CONFIG_USB_CONFIGFS_F_UAC1 is not set
# CONFIG_USB_CONFIGFS_F_UAC1_LEGACY is not set
# CONFIG_USB_CONFIGFS_F_UAC2 is not set
# CONFIG_USB_CONFIGFS_F_UVC is not set
CONFIG_USB_CONFIGFS_MASS_STORAGE=y
# CONFIG_USB_CONFIGFS_NCM is not set
# CONFIG_USB_CONFIGFS_OBEX is not set
# CONFIG_USB_CONFIGFS_RNDIS is not set
# CONFIG_USB_CONFIGFS_SERIAL is not set
CONFIG_USB_F_FS=y
CONFIG_USB_F_MASS_STORAGE=y
CONFIG_USB_GADGET=y
CONFIG_USB_LIBCOMPOSITE=y
CONFIG_USB_PCI=y
CONFIG_USB_PHY=y
CONFIG_USB_ROLE_SWITCH=y
CONFIG_USB_SUPPORT=y
# CONFIG_USB_UHCI_HCD is not set
CONFIG_USELIB=y
CONFIG_USER_NS=y
CONFIG_VFAT_FS=y
# CONFIG_VIDEO_STF_VIN is not set
# CONFIG_VIRTIO_BLK is not set
# CONFIG_VIRTIO_NET is not set
CONFIG_VMAP_STACK=y
CONFIG_WATCHDOG_CORE=y
CONFIG_WATCHDOG_SYSFS=y
CONFIG_WERROR=y
CONFIG_WQ_WATCHDOG=y
CONFIG_XPS=y
CONFIG_XXHASH=y
CONFIG_ZLIB_INFLATE=y
CONFIG_ZONE_DMA32=y

View File

@ -0,0 +1,76 @@
From 69275b667bd930cf5d5f577ba0ab1987c9d13987 Mon Sep 17 00:00:00 2001
From: Xingyu Wu <xingyu.wu@starfivetech.com>
Date: Mon, 21 Aug 2023 23:29:15 +0800
Subject: [PATCH 001/116] clk: starfive: jh7110-sys: Fix lower rate of CPUfreq
by setting PLL0 rate to 1.5GHz
CPUfreq supports 4 cpu frequency loads on 375/500/750/1500MHz.
But now PLL0 rate is 1GHz and the cpu frequency loads become
333/500/500/1000MHz in fact.
So PLL0 rate should be set to 1.5GHz. Change the parent of cpu_root clock
and the divider of cpu_core before the setting.
Reviewed-by: Hal Feng <hal.feng@starfivetech.com>
Fixes: e2c510d6d630 ("riscv: dts: starfive: Add cpu scaling for JH7110 SoC")
Signed-off-by: Xingyu Wu <xingyu.wu@starfivetech.com>
---
.../clk/starfive/clk-starfive-jh7110-sys.c | 47 ++++++++++++++++++-
1 file changed, 46 insertions(+), 1 deletion(-)
--- a/drivers/clk/starfive/clk-starfive-jh7110-sys.c
+++ b/drivers/clk/starfive/clk-starfive-jh7110-sys.c
@@ -501,7 +501,52 @@ static int __init jh7110_syscrg_probe(st
if (ret)
return ret;
- return jh7110_reset_controller_register(priv, "rst-sys", 0);
+ ret = jh7110_reset_controller_register(priv, "rst-sys", 0);
+ if (ret)
+ return ret;
+
+ /*
+ * Set PLL0 rate to 1.5GHz
+ * In order to not affect the cpu when the PLL0 rate is changing,
+ * we need to switch the parent of cpu_root clock to osc clock first,
+ * and then switch back after setting the PLL0 rate.
+ */
+ pllclk = clk_get(priv->dev, "pll0_out");
+ if (!IS_ERR(pllclk)) {
+ struct clk *osc = clk_get(&pdev->dev, "osc");
+ struct clk *cpu_root = priv->reg[JH7110_SYSCLK_CPU_ROOT].hw.clk;
+ struct clk *cpu_core = priv->reg[JH7110_SYSCLK_CPU_CORE].hw.clk;
+
+ if (IS_ERR(osc)) {
+ clk_put(pllclk);
+ return PTR_ERR(osc);
+ }
+
+ /*
+ * CPU need voltage regulation by CPUfreq if set 1.5GHz.
+ * So in this driver, cpu_core need to be set the divider to be 2 first
+ * and will be 750M after setting parent.
+ */
+ ret = clk_set_rate(cpu_core, clk_get_rate(cpu_core) / 2);
+ if (ret)
+ goto failed_set;
+
+ ret = clk_set_parent(cpu_root, osc);
+ if (ret)
+ goto failed_set;
+
+ ret = clk_set_rate(pllclk, 1500000000);
+ if (ret)
+ goto failed_set;
+
+ ret = clk_set_parent(cpu_root, pllclk);
+
+failed_set:
+ clk_put(pllclk);
+ clk_put(osc);
+ }
+
+ return ret;
}
static const struct of_device_id jh7110_syscrg_match[] = {

View File

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

View File

@ -0,0 +1,428 @@
From 7cb47848f8a10aed6e050c0ea483b4bb5eaa62a4 Mon Sep 17 00:00:00 2001
From: Xingyu Wu <xingyu.wu@starfivetech.com>
Date: Thu, 19 Oct 2023 13:35:00 +0800
Subject: [PATCH 003/116] clocksource: Add JH7110 timer driver
Add timer driver for the StarFive JH7110 SoC.
Signed-off-by: Xingyu Wu <xingyu.wu@starfivetech.com>
---
drivers/clocksource/Kconfig | 11 +
drivers/clocksource/Makefile | 1 +
drivers/clocksource/timer-jh7110.c | 380 +++++++++++++++++++++++++++++
3 files changed, 392 insertions(+)
create mode 100644 drivers/clocksource/timer-jh7110.c
--- a/drivers/clocksource/Kconfig
+++ b/drivers/clocksource/Kconfig
@@ -641,6 +641,17 @@ config RISCV_TIMER
is accessed via both the SBI and the rdcycle instruction. This is
required for all RISC-V systems.
+config STARFIVE_JH7110_TIMER
+ bool "Timer for the STARFIVE JH7110 SoC"
+ depends on ARCH_STARFIVE || COMPILE_TEST
+ select TIMER_OF
+ select CLKSRC_MMIO
+ default ARCH_STARFIVE
+ help
+ This enables the timer for StarFive JH7110 SoC. On RISC-V platform,
+ the system has started RISCV_TIMER, but you can also use this timer
+ which can provide four channels to do a lot more things on JH7110 SoC.
+
config CLINT_TIMER
bool "CLINT Timer for the RISC-V platform" if COMPILE_TEST
depends on GENERIC_SCHED_CLOCK && RISCV
--- a/drivers/clocksource/Makefile
+++ b/drivers/clocksource/Makefile
@@ -80,6 +80,7 @@ obj-$(CONFIG_INGENIC_TIMER) += ingenic-
obj-$(CONFIG_CLKSRC_ST_LPC) += clksrc_st_lpc.o
obj-$(CONFIG_X86_NUMACHIP) += numachip.o
obj-$(CONFIG_RISCV_TIMER) += timer-riscv.o
+obj-$(CONFIG_STARFIVE_JH7110_TIMER) += timer-jh7110.o
obj-$(CONFIG_CLINT_TIMER) += timer-clint.o
obj-$(CONFIG_CSKY_MP_TIMER) += timer-mp-csky.o
obj-$(CONFIG_GX6605S_TIMER) += timer-gx6605s.o
--- /dev/null
+++ b/drivers/clocksource/timer-jh7110.c
@@ -0,0 +1,380 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Starfive JH7110 Timer driver
+ *
+ * Copyright (C) 2022-2023 StarFive Technology Co., Ltd.
+ *
+ * Author:
+ * Xingyu Wu <xingyu.wu@starfivetech.com>
+ * Samin Guo <samin.guo@starfivetech.com>
+ */
+
+#include <linux/clk.h>
+#include <linux/clockchips.h>
+#include <linux/clocksource.h>
+#include <linux/err.h>
+#include <linux/interrupt.h>
+#include <linux/io.h>
+#include <linux/iopoll.h>
+#include <linux/irq.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/of_device.h>
+#include <linux/platform_device.h>
+#include <linux/reset.h>
+#include <linux/sched_clock.h>
+
+/* Bias: Ch0-0x0, Ch1-0x40, Ch2-0x80, and so on. */
+#define JH7110_TIMER_CH_LEN 0x40
+#define JH7110_TIMER_CH_BASE(x) ((x) * JH7110_TIMER_CH_LEN)
+#define JH7110_TIMER_CH_MAX 4
+
+#define JH7110_CLOCK_SOURCE_RATING 200
+#define JH7110_VALID_BITS 32
+#define JH7110_DELAY_US 0
+#define JH7110_TIMEOUT_US 10000
+#define JH7110_CLOCKEVENT_RATING 300
+#define JH7110_TIMER_MAX_TICKS 0xffffffff
+#define JH7110_TIMER_MIN_TICKS 0xf
+#define JH7110_TIMER_RELOAD_VALUE 0
+
+#define JH7110_TIMER_INT_STATUS 0x00 /* RO[0:4]: Interrupt Status for channel0~4 */
+#define JH7110_TIMER_CTL 0x04 /* RW[0]: 0-continuous run, 1-single run */
+#define JH7110_TIMER_LOAD 0x08 /* RW: load value to counter */
+#define JH7110_TIMER_ENABLE 0x10 /* RW[0]: timer enable register */
+#define JH7110_TIMER_RELOAD 0x14 /* RW: write 1 or 0 both reload counter */
+#define JH7110_TIMER_VALUE 0x18 /* RO: timer value register */
+#define JH7110_TIMER_INT_CLR 0x20 /* RW: timer interrupt clear register */
+#define JH7110_TIMER_INT_MASK 0x24 /* RW[0]: timer interrupt mask register */
+
+#define JH7110_TIMER_INT_CLR_ENA BIT(0)
+#define JH7110_TIMER_INT_CLR_AVA_MASK BIT(1)
+
+struct jh7110_clkevt {
+ struct clock_event_device evt;
+ struct clocksource cs;
+ bool cs_is_valid;
+ struct clk *clk;
+ struct reset_control *rst;
+ u32 rate;
+ u32 reload_val;
+ void __iomem *base;
+ char name[sizeof("jh7110-timer.chX")];
+};
+
+struct jh7110_timer_priv {
+ struct clk *pclk;
+ struct reset_control *prst;
+ struct jh7110_clkevt clkevt[JH7110_TIMER_CH_MAX];
+};
+
+/* 0:continuous-run mode, 1:single-run mode */
+enum jh7110_timer_mode {
+ JH7110_TIMER_MODE_CONTIN,
+ JH7110_TIMER_MODE_SINGLE,
+};
+
+/* Interrupt Mask, 0:Unmask, 1:Mask */
+enum jh7110_timer_int_mask {
+ JH7110_TIMER_INT_ENA,
+ JH7110_TIMER_INT_DIS,
+};
+
+enum jh7110_timer_enable {
+ JH7110_TIMER_DIS,
+ JH7110_TIMER_ENA,
+};
+
+static inline struct jh7110_clkevt *to_jh7110_clkevt(struct clock_event_device *evt)
+{
+ return container_of(evt, struct jh7110_clkevt, evt);
+}
+
+/*
+ * BIT(0): Read value represent channel int status.
+ * Write 1 to this bit to clear interrupt. Write 0 has no effects.
+ * BIT(1): "1" means that it is clearing interrupt. BIT(0) can not be written.
+ */
+static inline int jh7110_timer_int_clear(struct jh7110_clkevt *clkevt)
+{
+ u32 value;
+ int ret;
+
+ /* Waiting interrupt can be cleared */
+ ret = readl_poll_timeout_atomic(clkevt->base + JH7110_TIMER_INT_CLR, value,
+ !(value & JH7110_TIMER_INT_CLR_AVA_MASK),
+ JH7110_DELAY_US, JH7110_TIMEOUT_US);
+ if (!ret)
+ writel(JH7110_TIMER_INT_CLR_ENA, clkevt->base + JH7110_TIMER_INT_CLR);
+
+ return ret;
+}
+
+static int jh7110_timer_start(struct jh7110_clkevt *clkevt)
+{
+ int ret;
+
+ /* Disable and clear interrupt first */
+ writel(JH7110_TIMER_INT_DIS, clkevt->base + JH7110_TIMER_INT_MASK);
+ ret = jh7110_timer_int_clear(clkevt);
+ if (ret)
+ return ret;
+
+ writel(JH7110_TIMER_INT_ENA, clkevt->base + JH7110_TIMER_INT_MASK);
+ writel(JH7110_TIMER_ENA, clkevt->base + JH7110_TIMER_ENABLE);
+
+ return 0;
+}
+
+static int jh7110_timer_shutdown(struct clock_event_device *evt)
+{
+ struct jh7110_clkevt *clkevt = to_jh7110_clkevt(evt);
+
+ writel(JH7110_TIMER_DIS, clkevt->base + JH7110_TIMER_ENABLE);
+ return jh7110_timer_int_clear(clkevt);
+}
+
+static void jh7110_timer_suspend(struct clock_event_device *evt)
+{
+ struct jh7110_clkevt *clkevt = to_jh7110_clkevt(evt);
+
+ clkevt->reload_val = readl(clkevt->base + JH7110_TIMER_LOAD);
+ jh7110_timer_shutdown(evt);
+}
+
+static void jh7110_timer_resume(struct clock_event_device *evt)
+{
+ struct jh7110_clkevt *clkevt = to_jh7110_clkevt(evt);
+
+ writel(clkevt->reload_val, clkevt->base + JH7110_TIMER_LOAD);
+ writel(JH7110_TIMER_RELOAD_VALUE, clkevt->base + JH7110_TIMER_RELOAD);
+ jh7110_timer_start(clkevt);
+}
+
+static int jh7110_timer_tick_resume(struct clock_event_device *evt)
+{
+ jh7110_timer_resume(evt);
+
+ return 0;
+}
+
+/* IRQ handler for the timer */
+static irqreturn_t jh7110_timer_interrupt(int irq, void *priv)
+{
+ struct clock_event_device *evt = (struct clock_event_device *)priv;
+ struct jh7110_clkevt *clkevt = to_jh7110_clkevt(evt);
+
+ if (jh7110_timer_int_clear(clkevt))
+ return IRQ_NONE;
+
+ if (evt->event_handler)
+ evt->event_handler(evt);
+
+ return IRQ_HANDLED;
+}
+
+static int jh7110_timer_set_periodic(struct clock_event_device *evt)
+{
+ struct jh7110_clkevt *clkevt = to_jh7110_clkevt(evt);
+ u32 periodic = DIV_ROUND_CLOSEST(clkevt->rate, HZ);
+
+ writel(JH7110_TIMER_MODE_CONTIN, clkevt->base + JH7110_TIMER_CTL);
+ writel(periodic, clkevt->base + JH7110_TIMER_LOAD);
+
+ return jh7110_timer_start(clkevt);
+}
+
+static int jh7110_timer_set_oneshot(struct clock_event_device *evt)
+{
+ struct jh7110_clkevt *clkevt = to_jh7110_clkevt(evt);
+
+ writel(JH7110_TIMER_MODE_SINGLE, clkevt->base + JH7110_TIMER_CTL);
+ writel(JH7110_TIMER_MAX_TICKS, clkevt->base + JH7110_TIMER_LOAD);
+
+ return jh7110_timer_start(clkevt);
+}
+
+static int jh7110_timer_set_next_event(unsigned long next,
+ struct clock_event_device *evt)
+{
+ struct jh7110_clkevt *clkevt = to_jh7110_clkevt(evt);
+
+ writel(JH7110_TIMER_MODE_SINGLE, clkevt->base + JH7110_TIMER_CTL);
+ writel(next, clkevt->base + JH7110_TIMER_LOAD);
+
+ return jh7110_timer_start(clkevt);
+}
+
+static void jh7110_set_clockevent(struct clock_event_device *evt)
+{
+ evt->features = CLOCK_EVT_FEAT_PERIODIC |
+ CLOCK_EVT_FEAT_ONESHOT |
+ CLOCK_EVT_FEAT_DYNIRQ;
+ evt->set_state_shutdown = jh7110_timer_shutdown;
+ evt->set_state_periodic = jh7110_timer_set_periodic;
+ evt->set_state_oneshot = jh7110_timer_set_oneshot;
+ evt->set_state_oneshot_stopped = jh7110_timer_shutdown;
+ evt->tick_resume = jh7110_timer_tick_resume;
+ evt->set_next_event = jh7110_timer_set_next_event;
+ evt->suspend = jh7110_timer_suspend;
+ evt->resume = jh7110_timer_resume;
+ evt->rating = JH7110_CLOCKEVENT_RATING;
+}
+
+static u64 jh7110_timer_clocksource_read(struct clocksource *cs)
+{
+ struct jh7110_clkevt *clkevt = container_of(cs, struct jh7110_clkevt, cs);
+
+ return (u64)readl(clkevt->base + JH7110_TIMER_VALUE);
+}
+
+static int jh7110_clocksource_init(struct jh7110_clkevt *clkevt)
+{
+ int ret;
+
+ clkevt->cs.name = clkevt->name;
+ clkevt->cs.rating = JH7110_CLOCK_SOURCE_RATING;
+ clkevt->cs.read = jh7110_timer_clocksource_read;
+ clkevt->cs.mask = CLOCKSOURCE_MASK(JH7110_VALID_BITS);
+ clkevt->cs.flags = CLOCK_SOURCE_IS_CONTINUOUS;
+
+ ret = clocksource_register_hz(&clkevt->cs, clkevt->rate);
+ if (ret)
+ return ret;
+
+ clkevt->cs_is_valid = true; /* clocksource register done */
+ writel(JH7110_TIMER_MODE_CONTIN, clkevt->base + JH7110_TIMER_CTL);
+ writel(JH7110_TIMER_MAX_TICKS, clkevt->base + JH7110_TIMER_LOAD);
+
+ return jh7110_timer_start(clkevt);
+}
+
+static void jh7110_clockevents_register(struct jh7110_clkevt *clkevt)
+{
+ clkevt->rate = clk_get_rate(clkevt->clk);
+
+ jh7110_set_clockevent(&clkevt->evt);
+ clkevt->evt.name = clkevt->name;
+ clkevt->evt.cpumask = cpu_possible_mask;
+
+ clockevents_config_and_register(&clkevt->evt, clkevt->rate,
+ JH7110_TIMER_MIN_TICKS, JH7110_TIMER_MAX_TICKS);
+}
+
+static void jh7110_timer_release(void *data)
+{
+ struct jh7110_timer_priv *priv = data;
+ int i;
+
+ for (i = 0; i < JH7110_TIMER_CH_MAX; i++) {
+ /* Disable each channel of timer */
+ if (priv->clkevt[i].base)
+ writel(JH7110_TIMER_DIS, priv->clkevt[i].base + JH7110_TIMER_ENABLE);
+
+ /* Avoid no initialization in the loop of the probe */
+ if (!IS_ERR_OR_NULL(priv->clkevt[i].rst))
+ reset_control_assert(priv->clkevt[i].rst);
+
+ if (priv->clkevt[i].cs_is_valid)
+ clocksource_unregister(&priv->clkevt[i].cs);
+ }
+
+ reset_control_assert(priv->prst);
+}
+
+static int jh7110_timer_probe(struct platform_device *pdev)
+{
+ struct jh7110_timer_priv *priv;
+ struct jh7110_clkevt *clkevt;
+ char name[sizeof("chX")];
+ int ch;
+ int ret;
+ void __iomem *base;
+
+ priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL);
+ if (!priv)
+ return -ENOMEM;
+
+ base = devm_platform_ioremap_resource(pdev, 0);
+ if (IS_ERR(base))
+ return dev_err_probe(&pdev->dev, PTR_ERR(base),
+ "failed to map registers\n");
+
+ priv->prst = devm_reset_control_get_exclusive(&pdev->dev, "apb");
+ if (IS_ERR(priv->prst))
+ return dev_err_probe(&pdev->dev, PTR_ERR(priv->prst),
+ "failed to get apb reset\n");
+
+ priv->pclk = devm_clk_get_enabled(&pdev->dev, "apb");
+ if (IS_ERR(priv->pclk))
+ return dev_err_probe(&pdev->dev, PTR_ERR(priv->pclk),
+ "failed to get & enable apb clock\n");
+
+ ret = reset_control_deassert(priv->prst);
+ if (ret)
+ return dev_err_probe(&pdev->dev, ret, "failed to deassert apb reset\n");
+
+ ret = devm_add_action_or_reset(&pdev->dev, jh7110_timer_release, priv);
+ if (ret)
+ return ret;
+
+ for (ch = 0; ch < JH7110_TIMER_CH_MAX; ch++) {
+ clkevt = &priv->clkevt[ch];
+ snprintf(name, sizeof(name), "ch%d", ch);
+
+ clkevt->base = base + JH7110_TIMER_CH_BASE(ch);
+ /* Ensure timer is disabled */
+ writel(JH7110_TIMER_DIS, clkevt->base + JH7110_TIMER_ENABLE);
+
+ clkevt->rst = devm_reset_control_get_exclusive(&pdev->dev, name);
+ if (IS_ERR(clkevt->rst))
+ return PTR_ERR(clkevt->rst);
+
+ clkevt->clk = devm_clk_get_enabled(&pdev->dev, name);
+ if (IS_ERR(clkevt->clk))
+ return PTR_ERR(clkevt->clk);
+
+ ret = reset_control_deassert(clkevt->rst);
+ if (ret)
+ return ret;
+
+ clkevt->evt.irq = platform_get_irq(pdev, ch);
+ if (clkevt->evt.irq < 0)
+ return clkevt->evt.irq;
+
+ snprintf(clkevt->name, sizeof(clkevt->name), "jh7110-timer.ch%d", ch);
+ jh7110_clockevents_register(clkevt);
+
+ ret = devm_request_irq(&pdev->dev, clkevt->evt.irq, jh7110_timer_interrupt,
+ IRQF_TIMER | IRQF_IRQPOLL,
+ clkevt->name, &clkevt->evt);
+ if (ret)
+ return ret;
+
+ ret = jh7110_clocksource_init(clkevt);
+ if (ret)
+ return ret;
+ }
+
+ return 0;
+}
+
+static const struct of_device_id jh7110_timer_match[] = {
+ { .compatible = "starfive,jh7110-timer", },
+ { /* sentinel */ }
+};
+MODULE_DEVICE_TABLE(of, jh7110_timer_match);
+
+static struct platform_driver jh7110_timer_driver = {
+ .probe = jh7110_timer_probe,
+ .driver = {
+ .name = "jh7110-timer",
+ .of_match_table = jh7110_timer_match,
+ },
+};
+module_platform_driver(jh7110_timer_driver);
+
+MODULE_AUTHOR("Xingyu Wu <xingyu.wu@starfivetech.com>");
+MODULE_DESCRIPTION("StarFive JH7110 timer driver");
+MODULE_LICENSE("GPL");

View File

@ -0,0 +1,34 @@
From b513eb2cabee212ba1a23839f18c0026a21e653e Mon Sep 17 00:00:00 2001
From: William Qiu <william.qiu@starfivetech.com>
Date: Fri, 22 Sep 2023 14:28:32 +0800
Subject: [PATCH 004/116] dt-bindings: mmc: starfive: Remove properties from
required
Due to the change of tuning implementation, it's no longer necessary to
use the "starfive,sysreg" property in dts, so remove it from required.
Signed-off-by: William Qiu <william.qiu@starfivetech.com>
Acked-by: Conor Dooley <conor.dooley@microchip.com>
Reviewed-by: Emil Renner Berthing <emil.renner.berthing@canonical.com>
Link: https://lore.kernel.org/r/20230922062834.39212-2-william.qiu@starfivetech.com
Signed-off-by: Ulf Hansson <ulf.hansson@linaro.org>
---
Documentation/devicetree/bindings/mmc/starfive,jh7110-mmc.yaml | 2 --
1 file changed, 2 deletions(-)
--- a/Documentation/devicetree/bindings/mmc/starfive,jh7110-mmc.yaml
+++ b/Documentation/devicetree/bindings/mmc/starfive,jh7110-mmc.yaml
@@ -55,7 +55,6 @@ required:
- clocks
- clock-names
- interrupts
- - starfive,sysreg
unevaluatedProperties: false
@@ -73,5 +72,4 @@ examples:
fifo-depth = <32>;
fifo-watermark-aligned;
data-addr = <0>;
- starfive,sysreg = <&sys_syscon 0x14 0x1a 0x7c000000>;
};

View File

@ -0,0 +1,199 @@
From 3ae8cec8fd28e18847edb67dfea04718c2f3369f Mon Sep 17 00:00:00 2001
From: William Qiu <william.qiu@starfivetech.com>
Date: Fri, 22 Sep 2023 14:28:33 +0800
Subject: [PATCH 005/116] mmc: starfive: Change tuning implementation
Before, we used syscon to achieve tuning, but the actual measurement
showed little effect, so the tuning implementation was modified here,
and it was realized by reading and writing the UHS_REG_EXT register.
Signed-off-by: William Qiu <william.qiu@starfivetech.com>
Reviewed-by: Emil Renner Berthing <emil.renner.berthing@canonical.com>
Link: https://lore.kernel.org/r/20230922062834.39212-3-william.qiu@starfivetech.com
Signed-off-by: Ulf Hansson <ulf.hansson@linaro.org>
---
drivers/mmc/host/dw_mmc-starfive.c | 137 +++++++++--------------------
1 file changed, 40 insertions(+), 97 deletions(-)
--- a/drivers/mmc/host/dw_mmc-starfive.c
+++ b/drivers/mmc/host/dw_mmc-starfive.c
@@ -5,6 +5,7 @@
* Copyright (c) 2022 StarFive Technology Co., Ltd.
*/
+#include <linux/bitfield.h>
#include <linux/clk.h>
#include <linux/delay.h>
#include <linux/mfd/syscon.h>
@@ -20,13 +21,7 @@
#define ALL_INT_CLR 0x1ffff
#define MAX_DELAY_CHAIN 32
-struct starfive_priv {
- struct device *dev;
- struct regmap *reg_syscon;
- u32 syscon_offset;
- u32 syscon_shift;
- u32 syscon_mask;
-};
+#define STARFIVE_SMPL_PHASE GENMASK(20, 16)
static void dw_mci_starfive_set_ios(struct dw_mci *host, struct mmc_ios *ios)
{
@@ -44,117 +39,65 @@ static void dw_mci_starfive_set_ios(stru
}
}
+static void dw_mci_starfive_set_sample_phase(struct dw_mci *host, u32 smpl_phase)
+{
+ /* change driver phase and sample phase */
+ u32 reg_value = mci_readl(host, UHS_REG_EXT);
+
+ /* In UHS_REG_EXT, only 5 bits valid in DRV_PHASE and SMPL_PHASE */
+ reg_value &= ~STARFIVE_SMPL_PHASE;
+ reg_value |= FIELD_PREP(STARFIVE_SMPL_PHASE, smpl_phase);
+ mci_writel(host, UHS_REG_EXT, reg_value);
+
+ /* We should delay 1ms wait for timing setting finished. */
+ mdelay(1);
+}
+
static int dw_mci_starfive_execute_tuning(struct dw_mci_slot *slot,
u32 opcode)
{
static const int grade = MAX_DELAY_CHAIN;
struct dw_mci *host = slot->host;
- struct starfive_priv *priv = host->priv;
- int rise_point = -1, fall_point = -1;
- int err, prev_err = 0;
- int i;
- bool found = 0;
- u32 regval;
-
- /*
- * Use grade as the max delay chain, and use the rise_point and
- * fall_point to ensure the best sampling point of a data input
- * signals.
- */
- for (i = 0; i < grade; i++) {
- regval = i << priv->syscon_shift;
- err = regmap_update_bits(priv->reg_syscon, priv->syscon_offset,
- priv->syscon_mask, regval);
- if (err)
- return err;
- mci_writel(host, RINTSTS, ALL_INT_CLR);
-
- err = mmc_send_tuning(slot->mmc, opcode, NULL);
- if (!err)
- found = 1;
-
- if (i > 0) {
- if (err && !prev_err)
- fall_point = i - 1;
- if (!err && prev_err)
- rise_point = i;
- }
+ int smpl_phase, smpl_raise = -1, smpl_fall = -1;
+ int ret;
- if (rise_point != -1 && fall_point != -1)
- goto tuning_out;
+ for (smpl_phase = 0; smpl_phase < grade; smpl_phase++) {
+ dw_mci_starfive_set_sample_phase(host, smpl_phase);
+ mci_writel(host, RINTSTS, ALL_INT_CLR);
- prev_err = err;
- err = 0;
- }
+ ret = mmc_send_tuning(slot->mmc, opcode, NULL);
-tuning_out:
- if (found) {
- if (rise_point == -1)
- rise_point = 0;
- if (fall_point == -1)
- fall_point = grade - 1;
- if (fall_point < rise_point) {
- if ((rise_point + fall_point) >
- (grade - 1))
- i = fall_point / 2;
- else
- i = (rise_point + grade - 1) / 2;
- } else {
- i = (rise_point + fall_point) / 2;
+ if (!ret && smpl_raise < 0) {
+ smpl_raise = smpl_phase;
+ } else if (ret && smpl_raise >= 0) {
+ smpl_fall = smpl_phase - 1;
+ break;
}
-
- regval = i << priv->syscon_shift;
- err = regmap_update_bits(priv->reg_syscon, priv->syscon_offset,
- priv->syscon_mask, regval);
- if (err)
- return err;
- mci_writel(host, RINTSTS, ALL_INT_CLR);
-
- dev_info(host->dev, "Found valid delay chain! use it [delay=%d]\n", i);
- } else {
- dev_err(host->dev, "No valid delay chain! use default\n");
- err = -EINVAL;
}
- mci_writel(host, RINTSTS, ALL_INT_CLR);
- return err;
-}
-
-static int dw_mci_starfive_parse_dt(struct dw_mci *host)
-{
- struct of_phandle_args args;
- struct starfive_priv *priv;
- int ret;
+ if (smpl_phase >= grade)
+ smpl_fall = grade - 1;
- priv = devm_kzalloc(host->dev, sizeof(*priv), GFP_KERNEL);
- if (!priv)
- return -ENOMEM;
-
- ret = of_parse_phandle_with_fixed_args(host->dev->of_node,
- "starfive,sysreg", 3, 0, &args);
- if (ret) {
- dev_err(host->dev, "Failed to parse starfive,sysreg\n");
- return -EINVAL;
+ if (smpl_raise < 0) {
+ smpl_phase = 0;
+ dev_err(host->dev, "No valid delay chain! use default\n");
+ ret = -EINVAL;
+ goto out;
}
- priv->reg_syscon = syscon_node_to_regmap(args.np);
- of_node_put(args.np);
- if (IS_ERR(priv->reg_syscon))
- return PTR_ERR(priv->reg_syscon);
-
- priv->syscon_offset = args.args[0];
- priv->syscon_shift = args.args[1];
- priv->syscon_mask = args.args[2];
-
- host->priv = priv;
+ smpl_phase = (smpl_raise + smpl_fall) / 2;
+ dev_dbg(host->dev, "Found valid delay chain! use it [delay=%d]\n", smpl_phase);
+ ret = 0;
- return 0;
+out:
+ dw_mci_starfive_set_sample_phase(host, smpl_phase);
+ mci_writel(host, RINTSTS, ALL_INT_CLR);
+ return ret;
}
static const struct dw_mci_drv_data starfive_data = {
.common_caps = MMC_CAP_CMD23,
.set_ios = dw_mci_starfive_set_ios,
- .parse_dt = dw_mci_starfive_parse_dt,
.execute_tuning = dw_mci_starfive_execute_tuning,
};

View File

@ -0,0 +1,79 @@
From e366df2ff64e9f93a5b35eea6a198b005d5a0911 Mon Sep 17 00:00:00 2001
From: William Qiu <william.qiu@starfivetech.com>
Date: Fri, 22 Dec 2023 17:45:45 +0800
Subject: [PATCH 006/116] dt-bindings: pwm: Add bindings for OpenCores PWM
Controller
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
Add bindings for OpenCores PWM Controller.
Signed-off-by: William Qiu <william.qiu@starfivetech.com>
Reviewed-by: Hal Feng <hal.feng@starfivetech.com>
Reviewed-by: Conor Dooley <conor.dooley@microchip.com>
Reviewed-by: Uwe Kleine-König <u.kleine-koenig@pengutronix.de>
Acked-by: Uwe Kleine-König <u.kleine-koenig@pengutronix.de>
---
.../bindings/pwm/opencores,pwm.yaml | 55 +++++++++++++++++++
1 file changed, 55 insertions(+)
create mode 100644 Documentation/devicetree/bindings/pwm/opencores,pwm.yaml
--- /dev/null
+++ b/Documentation/devicetree/bindings/pwm/opencores,pwm.yaml
@@ -0,0 +1,55 @@
+# SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/pwm/opencores,pwm.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: OpenCores PWM controller
+
+maintainers:
+ - William Qiu <william.qiu@starfivetech.com>
+
+description:
+ The OpenCores PTC ip core contains a PWM controller. When operating in PWM
+ mode, the PTC core generates binary signal with user-programmable low and
+ high periods. All PTC counters and registers are 32-bit.
+
+allOf:
+ - $ref: pwm.yaml#
+
+properties:
+ compatible:
+ items:
+ - enum:
+ - starfive,jh7100-pwm
+ - starfive,jh7110-pwm
+ - const: opencores,pwm-v1
+
+ reg:
+ maxItems: 1
+
+ clocks:
+ maxItems: 1
+
+ resets:
+ maxItems: 1
+
+ "#pwm-cells":
+ const: 3
+
+required:
+ - compatible
+ - reg
+ - clocks
+
+additionalProperties: false
+
+examples:
+ - |
+ pwm@12490000 {
+ compatible = "starfive,jh7110-pwm", "opencores,pwm-v1";
+ reg = <0x12490000 0x10000>;
+ clocks = <&clkgen 181>;
+ resets = <&rstgen 109>;
+ #pwm-cells = <3>;
+ };

View File

@ -0,0 +1,285 @@
From 644bfe581dde9b762460a4916da4d71c148be06e Mon Sep 17 00:00:00 2001
From: William Qiu <william.qiu@starfivetech.com>
Date: Fri, 22 Dec 2023 17:45:46 +0800
Subject: [PATCH 007/116] pwm: opencores: Add PWM driver support
Add driver for OpenCores PWM Controller. And add compatibility code
which based on StarFive SoC.
Co-developed-by: Hal Feng <hal.feng@starfivetech.com>
Signed-off-by: Hal Feng <hal.feng@starfivetech.com>
Signed-off-by: William Qiu <william.qiu@starfivetech.com>
---
drivers/pwm/Kconfig | 12 ++
drivers/pwm/Makefile | 1 +
drivers/pwm/pwm-ocores.c | 233 +++++++++++++++++++++++++++++++++++++++
3 files changed, 246 insertions(+)
create mode 100644 drivers/pwm/pwm-ocores.c
--- a/drivers/pwm/Kconfig
+++ b/drivers/pwm/Kconfig
@@ -434,6 +434,18 @@ config PWM_NTXEC
controller found in certain e-book readers designed by the original
design manufacturer Netronix.
+config PWM_OCORES
+ tristate "OpenCores PWM support"
+ depends on HAS_IOMEM && OF
+ depends on COMMON_CLK
+ depends on ARCH_STARFIVE || COMPILE_TEST
+ help
+ If you say yes to this option, support will be included for the
+ OpenCores PWM. For details see https://opencores.org/projects/ptc.
+
+ To compile this driver as a module, choose M here: the module
+ will be called pwm-ocores.
+
config PWM_OMAP_DMTIMER
tristate "OMAP Dual-Mode Timer PWM support"
depends on OF
--- a/drivers/pwm/Makefile
+++ b/drivers/pwm/Makefile
@@ -39,6 +39,7 @@ obj-$(CONFIG_PWM_MICROCHIP_CORE) += pwm-
obj-$(CONFIG_PWM_MTK_DISP) += pwm-mtk-disp.o
obj-$(CONFIG_PWM_MXS) += pwm-mxs.o
obj-$(CONFIG_PWM_NTXEC) += pwm-ntxec.o
+obj-$(CONFIG_PWM_OCORES) += pwm-ocores.o
obj-$(CONFIG_PWM_OMAP_DMTIMER) += pwm-omap-dmtimer.o
obj-$(CONFIG_PWM_PCA9685) += pwm-pca9685.o
obj-$(CONFIG_PWM_PXA) += pwm-pxa.o
--- /dev/null
+++ b/drivers/pwm/pwm-ocores.c
@@ -0,0 +1,233 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * OpenCores PWM Driver
+ *
+ * https://opencores.org/projects/ptc
+ *
+ * Copyright (C) 2018-2023 StarFive Technology Co., Ltd.
+ *
+ * Limitations:
+ * - The hardware only do inverted polarity.
+ * - The hardware minimum period / duty_cycle is (1 / pwm_apb clock frequency) ns.
+ * - The hardware maximum period / duty_cycle is (U32_MAX / pwm_apb clock frequency) ns.
+ */
+
+#include <linux/clk.h>
+#include <linux/io.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/of_device.h>
+#include <linux/platform_device.h>
+#include <linux/pwm.h>
+#include <linux/reset.h>
+#include <linux/slab.h>
+
+/* OCPWM_CTRL register bits*/
+#define REG_OCPWM_EN BIT(0)
+#define REG_OCPWM_ECLK BIT(1)
+#define REG_OCPWM_NEC BIT(2)
+#define REG_OCPWM_OE BIT(3)
+#define REG_OCPWM_SIGNLE BIT(4)
+#define REG_OCPWM_INTE BIT(5)
+#define REG_OCPWM_INT BIT(6)
+#define REG_OCPWM_CNTRRST BIT(7)
+#define REG_OCPWM_CAPTE BIT(8)
+
+struct ocores_pwm_device {
+ struct pwm_chip chip;
+ struct clk *clk;
+ struct reset_control *rst;
+ const struct ocores_pwm_data *data;
+ void __iomem *regs;
+ u32 clk_rate; /* PWM APB clock frequency */
+};
+
+struct ocores_pwm_data {
+ void __iomem *(*get_ch_base)(void __iomem *base, unsigned int channel);
+};
+
+static inline u32 ocores_readl(struct ocores_pwm_device *ddata,
+ unsigned int channel,
+ unsigned int offset)
+{
+ void __iomem *base = ddata->data->get_ch_base ?
+ ddata->data->get_ch_base(ddata->regs, channel) : ddata->regs;
+
+ return readl(base + offset);
+}
+
+static inline void ocores_writel(struct ocores_pwm_device *ddata,
+ unsigned int channel,
+ unsigned int offset, u32 val)
+{
+ void __iomem *base = ddata->data->get_ch_base ?
+ ddata->data->get_ch_base(ddata->regs, channel) : ddata->regs;
+
+ writel(val, base + offset);
+}
+
+static inline struct ocores_pwm_device *chip_to_ocores(struct pwm_chip *chip)
+{
+ return container_of(chip, struct ocores_pwm_device, chip);
+}
+
+static void __iomem *starfive_jh71x0_get_ch_base(void __iomem *base,
+ unsigned int channel)
+{
+ unsigned int offset = (channel > 3 ? 1 << 15 : 0) + (channel & 3) * 0x10;
+
+ return base + offset;
+}
+
+static int ocores_pwm_get_state(struct pwm_chip *chip,
+ struct pwm_device *pwm,
+ struct pwm_state *state)
+{
+ struct ocores_pwm_device *ddata = chip_to_ocores(chip);
+ u32 period_data, duty_data, ctrl_data;
+
+ period_data = ocores_readl(ddata, pwm->hwpwm, 0x8);
+ duty_data = ocores_readl(ddata, pwm->hwpwm, 0x4);
+ ctrl_data = ocores_readl(ddata, pwm->hwpwm, 0xC);
+
+ state->period = DIV_ROUND_UP_ULL((u64)period_data * NSEC_PER_SEC, ddata->clk_rate);
+ state->duty_cycle = DIV_ROUND_UP_ULL((u64)duty_data * NSEC_PER_SEC, ddata->clk_rate);
+ state->polarity = PWM_POLARITY_INVERSED;
+ state->enabled = (ctrl_data & REG_OCPWM_EN) ? true : false;
+
+ return 0;
+}
+
+static int ocores_pwm_apply(struct pwm_chip *chip,
+ struct pwm_device *pwm,
+ const struct pwm_state *state)
+{
+ struct ocores_pwm_device *ddata = chip_to_ocores(chip);
+ u32 ctrl_data = 0;
+ u64 period_data, duty_data;
+
+ if (state->polarity != PWM_POLARITY_INVERSED)
+ return -EINVAL;
+
+ ctrl_data = ocores_readl(ddata, pwm->hwpwm, 0xC);
+ ocores_writel(ddata, pwm->hwpwm, 0xC, 0);
+
+ period_data = DIV_ROUND_DOWN_ULL(state->period * ddata->clk_rate, NSEC_PER_SEC);
+ if (period_data <= U32_MAX)
+ ocores_writel(ddata, pwm->hwpwm, 0x8, (u32)period_data);
+ else
+ return -EINVAL;
+
+ duty_data = DIV_ROUND_DOWN_ULL(state->duty_cycle * ddata->clk_rate, NSEC_PER_SEC);
+ if (duty_data <= U32_MAX)
+ ocores_writel(ddata, pwm->hwpwm, 0x4, (u32)duty_data);
+ else
+ return -EINVAL;
+
+ ocores_writel(ddata, pwm->hwpwm, 0xC, 0);
+
+ if (state->enabled) {
+ ctrl_data = ocores_readl(ddata, pwm->hwpwm, 0xC);
+ ocores_writel(ddata, pwm->hwpwm, 0xC, ctrl_data | REG_OCPWM_EN | REG_OCPWM_OE);
+ }
+
+ return 0;
+}
+
+static const struct pwm_ops ocores_pwm_ops = {
+ .get_state = ocores_pwm_get_state,
+ .apply = ocores_pwm_apply,
+};
+
+static const struct ocores_pwm_data jh7100_pwm_data = {
+ .get_ch_base = starfive_jh71x0_get_ch_base,
+};
+
+static const struct ocores_pwm_data jh7110_pwm_data = {
+ .get_ch_base = starfive_jh71x0_get_ch_base,
+};
+
+static const struct of_device_id ocores_pwm_of_match[] = {
+ { .compatible = "opencores,pwm-v1" },
+ { .compatible = "starfive,jh7100-pwm", .data = &jh7100_pwm_data},
+ { .compatible = "starfive,jh7110-pwm", .data = &jh7110_pwm_data},
+ { /* sentinel */ }
+};
+MODULE_DEVICE_TABLE(of, ocores_pwm_of_match);
+
+static void ocores_reset_control_assert(void *data)
+{
+ reset_control_assert(data);
+}
+
+static int ocores_pwm_probe(struct platform_device *pdev)
+{
+ const struct of_device_id *id;
+ struct device *dev = &pdev->dev;
+ struct ocores_pwm_device *ddata;
+ struct pwm_chip *chip;
+ int ret;
+
+ id = of_match_device(ocores_pwm_of_match, dev);
+ if (!id)
+ return -EINVAL;
+
+ ddata = devm_kzalloc(dev, sizeof(*ddata), GFP_KERNEL);
+ if (!ddata)
+ return -ENOMEM;
+
+ ddata->data = id->data;
+ chip = &ddata->chip;
+ chip->dev = dev;
+ chip->ops = &ocores_pwm_ops;
+ chip->npwm = 8;
+ chip->of_pwm_n_cells = 3;
+
+ ddata->regs = devm_platform_ioremap_resource(pdev, 0);
+ if (IS_ERR(ddata->regs))
+ return dev_err_probe(dev, PTR_ERR(ddata->regs),
+ "Unable to map IO resources\n");
+
+ ddata->clk = devm_clk_get_enabled(dev, NULL);
+ if (IS_ERR(ddata->clk))
+ return dev_err_probe(dev, PTR_ERR(ddata->clk),
+ "Unable to get pwm's clock\n");
+
+ ddata->rst = devm_reset_control_get_optional_exclusive(dev, NULL);
+ if (IS_ERR(ddata->rst))
+ return dev_err_probe(dev, PTR_ERR(ddata->rst),
+ "Unable to get pwm's reset\n");
+
+ reset_control_deassert(ddata->rst);
+
+ ret = devm_add_action_or_reset(dev, ocores_reset_control_assert, ddata->rst);
+ if (ret)
+ return ret;
+
+ ddata->clk_rate = clk_get_rate(ddata->clk);
+ if (ddata->clk_rate <= 0)
+ return dev_err_probe(dev, ddata->clk_rate,
+ "Unable to get clock's rate\n");
+
+ ret = devm_pwmchip_add(dev, chip);
+ if (ret < 0)
+ return dev_err_probe(dev, ret, "Could not register PWM chip\n");
+
+ platform_set_drvdata(pdev, ddata);
+
+ return ret;
+}
+
+static struct platform_driver ocores_pwm_driver = {
+ .probe = ocores_pwm_probe,
+ .driver = {
+ .name = "ocores-pwm",
+ .of_match_table = ocores_pwm_of_match,
+ },
+};
+module_platform_driver(ocores_pwm_driver);
+
+MODULE_AUTHOR("Jieqin Chen");
+MODULE_AUTHOR("Hal Feng <hal.feng@starfivetech.com>");
+MODULE_DESCRIPTION("OpenCores PWM PTC driver");
+MODULE_LICENSE("GPL");

View File

@ -0,0 +1,117 @@
From 7d9521cad6474d45e9056176982e6da54d40bc19 Mon Sep 17 00:00:00 2001
From: Eric Biggers <ebiggers@google.com>
Date: Sun, 22 Oct 2023 01:10:42 -0700
Subject: [PATCH 008/116] crypto: starfive - remove unnecessary alignmask for
ahashes
The crypto API's support for alignmasks for ahash algorithms is nearly
useless, as its only effect is to cause the API to align the key and
result buffers. The drivers that happen to be specifying an alignmask
for ahash rarely actually need it. When they do, it's easily fixable,
especially considering that these buffers cannot be used for DMA.
In preparation for removing alignmask support from ahash, this patch
makes the starfive driver no longer use it. This driver did actually
rely on it, but only for storing to the result buffer using int stores
in starfive_hash_copy_hash(). This patch makes
starfive_hash_copy_hash() use put_unaligned() instead. (It really
should use a specific endianness, but that's an existing bug.)
Signed-off-by: Eric Biggers <ebiggers@google.com>
Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
---
drivers/crypto/starfive/jh7110-hash.c | 13 ++-----------
1 file changed, 2 insertions(+), 11 deletions(-)
--- a/drivers/crypto/starfive/jh7110-hash.c
+++ b/drivers/crypto/starfive/jh7110-hash.c
@@ -209,7 +209,8 @@ static int starfive_hash_copy_hash(struc
data = (u32 *)req->result;
for (count = 0; count < mlen; count++)
- data[count] = readl(ctx->cryp->base + STARFIVE_HASH_SHARDR);
+ put_unaligned(readl(ctx->cryp->base + STARFIVE_HASH_SHARDR),
+ &data[count]);
return 0;
}
@@ -628,7 +629,6 @@ static struct ahash_engine_alg algs_sha2
CRYPTO_ALG_NEED_FALLBACK,
.cra_blocksize = SHA224_BLOCK_SIZE,
.cra_ctxsize = sizeof(struct starfive_cryp_ctx),
- .cra_alignmask = 3,
.cra_module = THIS_MODULE,
}
},
@@ -658,7 +658,6 @@ static struct ahash_engine_alg algs_sha2
CRYPTO_ALG_NEED_FALLBACK,
.cra_blocksize = SHA224_BLOCK_SIZE,
.cra_ctxsize = sizeof(struct starfive_cryp_ctx),
- .cra_alignmask = 3,
.cra_module = THIS_MODULE,
}
},
@@ -687,7 +686,6 @@ static struct ahash_engine_alg algs_sha2
CRYPTO_ALG_NEED_FALLBACK,
.cra_blocksize = SHA256_BLOCK_SIZE,
.cra_ctxsize = sizeof(struct starfive_cryp_ctx),
- .cra_alignmask = 3,
.cra_module = THIS_MODULE,
}
},
@@ -717,7 +715,6 @@ static struct ahash_engine_alg algs_sha2
CRYPTO_ALG_NEED_FALLBACK,
.cra_blocksize = SHA256_BLOCK_SIZE,
.cra_ctxsize = sizeof(struct starfive_cryp_ctx),
- .cra_alignmask = 3,
.cra_module = THIS_MODULE,
}
},
@@ -746,7 +743,6 @@ static struct ahash_engine_alg algs_sha2
CRYPTO_ALG_NEED_FALLBACK,
.cra_blocksize = SHA384_BLOCK_SIZE,
.cra_ctxsize = sizeof(struct starfive_cryp_ctx),
- .cra_alignmask = 3,
.cra_module = THIS_MODULE,
}
},
@@ -776,7 +772,6 @@ static struct ahash_engine_alg algs_sha2
CRYPTO_ALG_NEED_FALLBACK,
.cra_blocksize = SHA384_BLOCK_SIZE,
.cra_ctxsize = sizeof(struct starfive_cryp_ctx),
- .cra_alignmask = 3,
.cra_module = THIS_MODULE,
}
},
@@ -805,7 +800,6 @@ static struct ahash_engine_alg algs_sha2
CRYPTO_ALG_NEED_FALLBACK,
.cra_blocksize = SHA512_BLOCK_SIZE,
.cra_ctxsize = sizeof(struct starfive_cryp_ctx),
- .cra_alignmask = 3,
.cra_module = THIS_MODULE,
}
},
@@ -835,7 +829,6 @@ static struct ahash_engine_alg algs_sha2
CRYPTO_ALG_NEED_FALLBACK,
.cra_blocksize = SHA512_BLOCK_SIZE,
.cra_ctxsize = sizeof(struct starfive_cryp_ctx),
- .cra_alignmask = 3,
.cra_module = THIS_MODULE,
}
},
@@ -864,7 +857,6 @@ static struct ahash_engine_alg algs_sha2
CRYPTO_ALG_NEED_FALLBACK,
.cra_blocksize = SM3_BLOCK_SIZE,
.cra_ctxsize = sizeof(struct starfive_cryp_ctx),
- .cra_alignmask = 3,
.cra_module = THIS_MODULE,
}
},
@@ -894,7 +886,6 @@ static struct ahash_engine_alg algs_sha2
CRYPTO_ALG_NEED_FALLBACK,
.cra_blocksize = SM3_BLOCK_SIZE,
.cra_ctxsize = sizeof(struct starfive_cryp_ctx),
- .cra_alignmask = 3,
.cra_module = THIS_MODULE,
}
},

View File

@ -0,0 +1,25 @@
From 52de0270ed6453727936b5a793dc367d75280e84 Mon Sep 17 00:00:00 2001
From: Jia Jie Ho <jiajie.ho@starfivetech.com>
Date: Wed, 15 Nov 2023 01:12:13 +0800
Subject: [PATCH 009/116] crypto: starfive - Update driver dependencies
Change AMBA_PL08X to required dependency as the hash ops depends on it
for data transfer.
Signed-off-by: Jia Jie Ho <jiajie.ho@starfivetech.com>
Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
---
drivers/crypto/starfive/Kconfig | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
--- a/drivers/crypto/starfive/Kconfig
+++ b/drivers/crypto/starfive/Kconfig
@@ -4,7 +4,7 @@
config CRYPTO_DEV_JH7110
tristate "StarFive JH7110 cryptographic engine driver"
- depends on SOC_STARFIVE || AMBA_PL08X || COMPILE_TEST
+ depends on (SOC_STARFIVE && AMBA_PL08X) || COMPILE_TEST
depends on HAS_DMA
select CRYPTO_ENGINE
select CRYPTO_HMAC

View File

@ -0,0 +1,200 @@
From 68a1bbb99455fd5ea80b7e21ec726f369abc9572 Mon Sep 17 00:00:00 2001
From: Jia Jie Ho <jiajie.ho@starfivetech.com>
Date: Wed, 15 Nov 2023 01:12:14 +0800
Subject: [PATCH 010/116] crypto: starfive - RSA poll csr for done status
Hardware could not clear irq status without resetting the entire module.
Driver receives irq immediately when mask bit is cleared causing
intermittent errors in RSA calculations. Switch to use csr polling for
done status instead.
Signed-off-by: Jia Jie Ho <jiajie.ho@starfivetech.com>
Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
---
drivers/crypto/starfive/jh7110-cryp.c | 8 -----
drivers/crypto/starfive/jh7110-cryp.h | 10 +++++-
drivers/crypto/starfive/jh7110-rsa.c | 49 +++++++--------------------
3 files changed, 22 insertions(+), 45 deletions(-)
--- a/drivers/crypto/starfive/jh7110-cryp.c
+++ b/drivers/crypto/starfive/jh7110-cryp.c
@@ -109,12 +109,6 @@ static irqreturn_t starfive_cryp_irq(int
tasklet_schedule(&cryp->hash_done);
}
- if (status & STARFIVE_IE_FLAG_PKA_DONE) {
- mask |= STARFIVE_IE_MASK_PKA_DONE;
- writel(mask, cryp->base + STARFIVE_IE_MASK_OFFSET);
- complete(&cryp->pka_done);
- }
-
return IRQ_HANDLED;
}
@@ -159,8 +153,6 @@ static int starfive_cryp_probe(struct pl
return dev_err_probe(&pdev->dev, PTR_ERR(cryp->rst),
"Error getting hardware reset line\n");
- init_completion(&cryp->pka_done);
-
irq = platform_get_irq(pdev, 0);
if (irq < 0)
return irq;
--- a/drivers/crypto/starfive/jh7110-cryp.h
+++ b/drivers/crypto/starfive/jh7110-cryp.h
@@ -125,6 +125,15 @@ union starfive_pka_cacr {
};
};
+union starfive_pka_casr {
+ u32 v;
+ struct {
+#define STARFIVE_PKA_DONE BIT(0)
+ u32 done :1;
+ u32 rsvd_0 :31;
+ };
+};
+
struct starfive_rsa_key {
u8 *n;
u8 *e;
@@ -183,7 +192,6 @@ struct starfive_cryp_dev {
struct crypto_engine *engine;
struct tasklet_struct aes_done;
struct tasklet_struct hash_done;
- struct completion pka_done;
size_t assoclen;
size_t total_in;
size_t total_out;
--- a/drivers/crypto/starfive/jh7110-rsa.c
+++ b/drivers/crypto/starfive/jh7110-rsa.c
@@ -6,13 +6,7 @@
*/
#include <linux/crypto.h>
-#include <linux/delay.h>
-#include <linux/device.h>
-#include <linux/dma-direct.h>
-#include <linux/interrupt.h>
#include <linux/iopoll.h>
-#include <linux/io.h>
-#include <linux/mod_devicetable.h>
#include <crypto/akcipher.h>
#include <crypto/algapi.h>
#include <crypto/internal/akcipher.h>
@@ -28,13 +22,13 @@
#define STARFIVE_PKA_CAER_OFFSET (STARFIVE_PKA_REGS_OFFSET + 0x108)
#define STARFIVE_PKA_CANR_OFFSET (STARFIVE_PKA_REGS_OFFSET + 0x208)
-// R^2 mod N and N0'
+/* R ^ 2 mod N and N0' */
#define CRYPTO_CMD_PRE 0x0
-// A * R mod N ==> A
+/* A * R mod N ==> A */
#define CRYPTO_CMD_ARN 0x5
-// A * E * R mod N ==> A
+/* A * E * R mod N ==> A */
#define CRYPTO_CMD_AERN 0x6
-// A * A * R mod N ==> A
+/* A * A * R mod N ==> A */
#define CRYPTO_CMD_AARN 0x7
#define STARFIVE_RSA_MAX_KEYSZ 256
@@ -43,21 +37,10 @@
static inline int starfive_pka_wait_done(struct starfive_cryp_ctx *ctx)
{
struct starfive_cryp_dev *cryp = ctx->cryp;
+ u32 status;
- return wait_for_completion_timeout(&cryp->pka_done,
- usecs_to_jiffies(100000));
-}
-
-static inline void starfive_pka_irq_mask_clear(struct starfive_cryp_ctx *ctx)
-{
- struct starfive_cryp_dev *cryp = ctx->cryp;
- u32 stat;
-
- stat = readl(cryp->base + STARFIVE_IE_MASK_OFFSET);
- stat &= ~STARFIVE_IE_MASK_PKA_DONE;
- writel(stat, cryp->base + STARFIVE_IE_MASK_OFFSET);
-
- reinit_completion(&cryp->pka_done);
+ return readl_relaxed_poll_timeout(cryp->base + STARFIVE_PKA_CASR_OFFSET, status,
+ status & STARFIVE_PKA_DONE, 10, 100000);
}
static void starfive_rsa_free_key(struct starfive_rsa_key *key)
@@ -114,10 +97,9 @@ static int starfive_rsa_montgomery_form(
rctx->csr.pka.not_r2 = 1;
rctx->csr.pka.ie = 1;
- starfive_pka_irq_mask_clear(ctx);
writel(rctx->csr.pka.v, cryp->base + STARFIVE_PKA_CACR_OFFSET);
- if (!starfive_pka_wait_done(ctx))
+ if (starfive_pka_wait_done(ctx))
return -ETIMEDOUT;
for (loop = 0; loop <= opsize; loop++)
@@ -136,10 +118,9 @@ static int starfive_rsa_montgomery_form(
rctx->csr.pka.start = 1;
rctx->csr.pka.ie = 1;
- starfive_pka_irq_mask_clear(ctx);
writel(rctx->csr.pka.v, cryp->base + STARFIVE_PKA_CACR_OFFSET);
- if (!starfive_pka_wait_done(ctx))
+ if (starfive_pka_wait_done(ctx))
return -ETIMEDOUT;
} else {
rctx->csr.pka.v = 0;
@@ -151,10 +132,9 @@ static int starfive_rsa_montgomery_form(
rctx->csr.pka.pre_expf = 1;
rctx->csr.pka.ie = 1;
- starfive_pka_irq_mask_clear(ctx);
writel(rctx->csr.pka.v, cryp->base + STARFIVE_PKA_CACR_OFFSET);
- if (!starfive_pka_wait_done(ctx))
+ if (starfive_pka_wait_done(ctx))
return -ETIMEDOUT;
for (loop = 0; loop <= count; loop++)
@@ -172,10 +152,9 @@ static int starfive_rsa_montgomery_form(
rctx->csr.pka.start = 1;
rctx->csr.pka.ie = 1;
- starfive_pka_irq_mask_clear(ctx);
writel(rctx->csr.pka.v, cryp->base + STARFIVE_PKA_CACR_OFFSET);
- if (!starfive_pka_wait_done(ctx))
+ if (starfive_pka_wait_done(ctx))
return -ETIMEDOUT;
}
@@ -226,11 +205,10 @@ static int starfive_rsa_cpu_start(struct
rctx->csr.pka.start = 1;
rctx->csr.pka.ie = 1;
- starfive_pka_irq_mask_clear(ctx);
writel(rctx->csr.pka.v, cryp->base + STARFIVE_PKA_CACR_OFFSET);
ret = -ETIMEDOUT;
- if (!starfive_pka_wait_done(ctx))
+ if (starfive_pka_wait_done(ctx))
goto rsa_err;
if (mlen) {
@@ -242,10 +220,9 @@ static int starfive_rsa_cpu_start(struct
rctx->csr.pka.start = 1;
rctx->csr.pka.ie = 1;
- starfive_pka_irq_mask_clear(ctx);
writel(rctx->csr.pka.v, cryp->base + STARFIVE_PKA_CACR_OFFSET);
- if (!starfive_pka_wait_done(ctx))
+ if (starfive_pka_wait_done(ctx))
goto rsa_err;
}
}

View File

@ -0,0 +1,46 @@
From eea9f2c55cf944bbd5cdd43eb655416a867846af Mon Sep 17 00:00:00 2001
From: Jia Jie Ho <jiajie.ho@starfivetech.com>
Date: Mon, 20 Nov 2023 11:12:42 +0800
Subject: [PATCH 011/116] crypto: starfive - Pad adata with zeroes
Aad requires padding with zeroes up to 15 bytes in some cases. This
patch increases the allocated buffer size for aad and prevents the
driver accessing uninitialized memory region.
v1->v2: Specify reason for alloc size change in descriptions.
Signed-off-by: Jia Jie Ho <jiajie.ho@starfivetech.com>
Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
---
drivers/crypto/starfive/jh7110-aes.c | 6 ++++--
1 file changed, 4 insertions(+), 2 deletions(-)
--- a/drivers/crypto/starfive/jh7110-aes.c
+++ b/drivers/crypto/starfive/jh7110-aes.c
@@ -500,7 +500,7 @@ static int starfive_aes_prepare_req(stru
scatterwalk_start(&cryp->out_walk, rctx->out_sg);
if (cryp->assoclen) {
- rctx->adata = kzalloc(ALIGN(cryp->assoclen, AES_BLOCK_SIZE), GFP_KERNEL);
+ rctx->adata = kzalloc(cryp->assoclen + AES_BLOCK_SIZE, GFP_KERNEL);
if (!rctx->adata)
return dev_err_probe(cryp->dev, -ENOMEM,
"Failed to alloc memory for adata");
@@ -569,7 +569,7 @@ static int starfive_aes_aead_do_one_req(
struct starfive_cryp_ctx *ctx =
crypto_aead_ctx(crypto_aead_reqtfm(req));
struct starfive_cryp_dev *cryp = ctx->cryp;
- struct starfive_cryp_request_ctx *rctx = ctx->rctx;
+ struct starfive_cryp_request_ctx *rctx;
u32 block[AES_BLOCK_32];
u32 stat;
int err;
@@ -579,6 +579,8 @@ static int starfive_aes_aead_do_one_req(
if (err)
return err;
+ rctx = ctx->rctx;
+
if (!cryp->assoclen)
goto write_text;

View File

@ -0,0 +1,125 @@
From 922b213ad22f93fb2788ce119084622ab3d25bf8 Mon Sep 17 00:00:00 2001
From: Herbert Xu <herbert@gondor.apana.org.au>
Date: Thu, 30 Nov 2023 18:12:55 +0800
Subject: [PATCH 012/116] crypto: starfive - Remove cfb and ofb
Remove the unused CFB/OFB implementation.
Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
---
drivers/crypto/starfive/jh7110-aes.c | 71 +--------------------------
drivers/crypto/starfive/jh7110-cryp.h | 2 -
2 files changed, 1 insertion(+), 72 deletions(-)
--- a/drivers/crypto/starfive/jh7110-aes.c
+++ b/drivers/crypto/starfive/jh7110-aes.c
@@ -262,12 +262,7 @@ static int starfive_aes_hw_init(struct s
rctx->csr.aes.mode = hw_mode;
rctx->csr.aes.cmode = !is_encrypt(cryp);
rctx->csr.aes.ie = 1;
-
- if (hw_mode == STARFIVE_AES_MODE_CFB ||
- hw_mode == STARFIVE_AES_MODE_OFB)
- rctx->csr.aes.stmode = STARFIVE_AES_MODE_XFB_128;
- else
- rctx->csr.aes.stmode = STARFIVE_AES_MODE_XFB_1;
+ rctx->csr.aes.stmode = STARFIVE_AES_MODE_XFB_1;
if (cryp->side_chan) {
rctx->csr.aes.delay_aes = 1;
@@ -294,8 +289,6 @@ static int starfive_aes_hw_init(struct s
starfive_aes_ccm_init(ctx);
starfive_aes_aead_hw_start(ctx, hw_mode);
break;
- case STARFIVE_AES_MODE_OFB:
- case STARFIVE_AES_MODE_CFB:
case STARFIVE_AES_MODE_CBC:
case STARFIVE_AES_MODE_CTR:
starfive_aes_write_iv(ctx, (void *)cryp->req.sreq->iv);
@@ -785,26 +778,6 @@ static int starfive_aes_cbc_decrypt(stru
return starfive_aes_crypt(req, STARFIVE_AES_MODE_CBC);
}
-static int starfive_aes_cfb_encrypt(struct skcipher_request *req)
-{
- return starfive_aes_crypt(req, STARFIVE_AES_MODE_CFB | FLG_ENCRYPT);
-}
-
-static int starfive_aes_cfb_decrypt(struct skcipher_request *req)
-{
- return starfive_aes_crypt(req, STARFIVE_AES_MODE_CFB);
-}
-
-static int starfive_aes_ofb_encrypt(struct skcipher_request *req)
-{
- return starfive_aes_crypt(req, STARFIVE_AES_MODE_OFB | FLG_ENCRYPT);
-}
-
-static int starfive_aes_ofb_decrypt(struct skcipher_request *req)
-{
- return starfive_aes_crypt(req, STARFIVE_AES_MODE_OFB);
-}
-
static int starfive_aes_ctr_encrypt(struct skcipher_request *req)
{
return starfive_aes_crypt(req, STARFIVE_AES_MODE_CTR | FLG_ENCRYPT);
@@ -903,48 +876,6 @@ static struct skcipher_engine_alg skciph
.cra_priority = 200,
.cra_flags = CRYPTO_ALG_ASYNC,
.cra_blocksize = 1,
- .cra_ctxsize = sizeof(struct starfive_cryp_ctx),
- .cra_alignmask = 0xf,
- .cra_module = THIS_MODULE,
- },
- .op = {
- .do_one_request = starfive_aes_do_one_req,
- },
-}, {
- .base.init = starfive_aes_init_tfm,
- .base.setkey = starfive_aes_setkey,
- .base.encrypt = starfive_aes_cfb_encrypt,
- .base.decrypt = starfive_aes_cfb_decrypt,
- .base.min_keysize = AES_MIN_KEY_SIZE,
- .base.max_keysize = AES_MAX_KEY_SIZE,
- .base.ivsize = AES_BLOCK_SIZE,
- .base.base = {
- .cra_name = "cfb(aes)",
- .cra_driver_name = "starfive-cfb-aes",
- .cra_priority = 200,
- .cra_flags = CRYPTO_ALG_ASYNC,
- .cra_blocksize = 1,
- .cra_ctxsize = sizeof(struct starfive_cryp_ctx),
- .cra_alignmask = 0xf,
- .cra_module = THIS_MODULE,
- },
- .op = {
- .do_one_request = starfive_aes_do_one_req,
- },
-}, {
- .base.init = starfive_aes_init_tfm,
- .base.setkey = starfive_aes_setkey,
- .base.encrypt = starfive_aes_ofb_encrypt,
- .base.decrypt = starfive_aes_ofb_decrypt,
- .base.min_keysize = AES_MIN_KEY_SIZE,
- .base.max_keysize = AES_MAX_KEY_SIZE,
- .base.ivsize = AES_BLOCK_SIZE,
- .base.base = {
- .cra_name = "ofb(aes)",
- .cra_driver_name = "starfive-ofb-aes",
- .cra_priority = 200,
- .cra_flags = CRYPTO_ALG_ASYNC,
- .cra_blocksize = 1,
.cra_ctxsize = sizeof(struct starfive_cryp_ctx),
.cra_alignmask = 0xf,
.cra_module = THIS_MODULE,
--- a/drivers/crypto/starfive/jh7110-cryp.h
+++ b/drivers/crypto/starfive/jh7110-cryp.h
@@ -50,8 +50,6 @@ union starfive_aes_csr {
u32 ccm_start :1;
#define STARFIVE_AES_MODE_ECB 0x0
#define STARFIVE_AES_MODE_CBC 0x1
-#define STARFIVE_AES_MODE_CFB 0x2
-#define STARFIVE_AES_MODE_OFB 0x3
#define STARFIVE_AES_MODE_CTR 0x4
#define STARFIVE_AES_MODE_CCM 0x5
#define STARFIVE_AES_MODE_GCM 0x6

View File

@ -0,0 +1,33 @@
From 0dbdc763f10c5cfa968dffc290a7c060ee740172 Mon Sep 17 00:00:00 2001
From: Jia Jie Ho <jiajie.ho@starfivetech.com>
Date: Mon, 4 Dec 2023 11:02:39 +0800
Subject: [PATCH 013/116] crypto: starfive - Remove unneeded NULL checks
NULL check before kfree_sensitive function is not needed.
Signed-off-by: Jia Jie Ho <jiajie.ho@starfivetech.com>
Reported-by: kernel test robot <lkp@intel.com>
Closes: https://lore.kernel.org/oe-kbuild-all/202311301702.LxswfETY-lkp@intel.com/
Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
---
drivers/crypto/starfive/jh7110-rsa.c | 9 +++------
1 file changed, 3 insertions(+), 6 deletions(-)
--- a/drivers/crypto/starfive/jh7110-rsa.c
+++ b/drivers/crypto/starfive/jh7110-rsa.c
@@ -45,12 +45,9 @@ static inline int starfive_pka_wait_done
static void starfive_rsa_free_key(struct starfive_rsa_key *key)
{
- if (key->d)
- kfree_sensitive(key->d);
- if (key->e)
- kfree_sensitive(key->e);
- if (key->n)
- kfree_sensitive(key->n);
+ kfree_sensitive(key->d);
+ kfree_sensitive(key->e);
+ kfree_sensitive(key->n);
memset(key, 0, sizeof(*key));
}

View File

@ -0,0 +1,183 @@
From 708695ebf1a779de9a1fd2f72f7938afa6c14ada Mon Sep 17 00:00:00 2001
From: Minda Chen <minda.chen@starfivetech.com>
Date: Mon, 8 Jan 2024 19:05:51 +0800
Subject: [PATCH 014/116] dt-bindings: PCI: Add PLDA XpressRICH PCIe host
common properties
Add PLDA XpressRICH PCIe host common properties dt-binding doc.
PolarFire PCIe host using PLDA IP. Move common properties from Microchip
PolarFire PCIe host to PLDA files.
Signed-off-by: Minda Chen <minda.chen@starfivetech.com>
Reviewed-by: Hal Feng <hal.feng@starfivetech.com>
Reviewed-by: Conor Dooley <conor.dooley@microchip.com>
Reviewed-by: Rob Herring <robh@kernel.org>
Tested-by: John Clark <inindev@gmail.com>
---
.../bindings/pci/microchip,pcie-host.yaml | 55 +-------------
.../pci/plda,xpressrich3-axi-common.yaml | 75 +++++++++++++++++++
2 files changed, 76 insertions(+), 54 deletions(-)
create mode 100644 Documentation/devicetree/bindings/pci/plda,xpressrich3-axi-common.yaml
--- a/Documentation/devicetree/bindings/pci/microchip,pcie-host.yaml
+++ b/Documentation/devicetree/bindings/pci/microchip,pcie-host.yaml
@@ -10,21 +10,13 @@ maintainers:
- Daire McNamara <daire.mcnamara@microchip.com>
allOf:
- - $ref: /schemas/pci/pci-bus.yaml#
+ - $ref: plda,xpressrich3-axi-common.yaml#
- $ref: /schemas/interrupt-controller/msi-controller.yaml#
properties:
compatible:
const: microchip,pcie-host-1.0 # PolarFire
- reg:
- maxItems: 2
-
- reg-names:
- items:
- - const: cfg
- - const: apb
-
clocks:
description:
Fabric Interface Controllers, FICs, are the interface between the FPGA
@@ -52,18 +44,6 @@ properties:
items:
pattern: '^fic[0-3]$'
- interrupts:
- minItems: 1
- items:
- - description: PCIe host controller
- - description: builtin MSI controller
-
- interrupt-names:
- minItems: 1
- items:
- - const: pcie
- - const: msi
-
ranges:
maxItems: 1
@@ -71,39 +51,6 @@ properties:
minItems: 1
maxItems: 6
- msi-controller:
- description: Identifies the node as an MSI controller.
-
- msi-parent:
- description: MSI controller the device is capable of using.
-
- interrupt-controller:
- type: object
- properties:
- '#address-cells':
- const: 0
-
- '#interrupt-cells':
- const: 1
-
- interrupt-controller: true
-
- required:
- - '#address-cells'
- - '#interrupt-cells'
- - interrupt-controller
-
- additionalProperties: false
-
-required:
- - reg
- - reg-names
- - "#interrupt-cells"
- - interrupts
- - interrupt-map-mask
- - interrupt-map
- - msi-controller
-
unevaluatedProperties: false
examples:
--- /dev/null
+++ b/Documentation/devicetree/bindings/pci/plda,xpressrich3-axi-common.yaml
@@ -0,0 +1,75 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/pci/plda,xpressrich3-axi-common.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: PLDA XpressRICH PCIe host common properties
+
+maintainers:
+ - Daire McNamara <daire.mcnamara@microchip.com>
+ - Kevin Xie <kevin.xie@starfivetech.com>
+
+description:
+ Generic PLDA XpressRICH PCIe host common properties.
+
+allOf:
+ - $ref: /schemas/pci/pci-bus.yaml#
+
+properties:
+ reg:
+ maxItems: 2
+
+ reg-names:
+ items:
+ - const: cfg
+ - const: apb
+
+ interrupts:
+ minItems: 1
+ items:
+ - description: PCIe host controller
+ - description: builtin MSI controller
+
+ interrupt-names:
+ minItems: 1
+ items:
+ - const: pcie
+ - const: msi
+
+ msi-controller:
+ description: Identifies the node as an MSI controller.
+
+ msi-parent:
+ description: MSI controller the device is capable of using.
+
+ interrupt-controller:
+ type: object
+ properties:
+ '#address-cells':
+ const: 0
+
+ '#interrupt-cells':
+ const: 1
+
+ interrupt-controller: true
+
+ required:
+ - '#address-cells'
+ - '#interrupt-cells'
+ - interrupt-controller
+
+ additionalProperties: false
+
+required:
+ - reg
+ - reg-names
+ - interrupts
+ - msi-controller
+ - "#interrupt-cells"
+ - interrupt-map-mask
+ - interrupt-map
+
+additionalProperties: true
+
+...

View File

@ -0,0 +1,259 @@
From eca1b864bb2d4e8d9811506979560a89351c2e37 Mon Sep 17 00:00:00 2001
From: Minda Chen <minda.chen@starfivetech.com>
Date: Mon, 8 Jan 2024 19:05:53 +0800
Subject: [PATCH 016/116] PCI: microchip: Move PLDA IP register macros to
pcie-plda.h
Move PLDA PCIe host controller IP registers macros to pcie-plda.h,
including bridge registers and local IRQ event number.
Signed-off-by: Minda Chen <minda.chen@starfivetech.com>
Reviewed-by: Conor Dooley <conor.dooley@microchip.com>
---
.../pci/controller/plda/pcie-microchip-host.c | 108 +++---------------
drivers/pci/controller/plda/pcie-plda.h | 108 ++++++++++++++++++
2 files changed, 124 insertions(+), 92 deletions(-)
create mode 100644 drivers/pci/controller/plda/pcie-plda.h
--- a/drivers/pci/controller/plda/pcie-microchip-host.c
+++ b/drivers/pci/controller/plda/pcie-microchip-host.c
@@ -19,6 +19,7 @@
#include <linux/platform_device.h>
#include "../../pci.h"
+#include "pcie-plda.h"
/* Number of MSI IRQs */
#define MC_MAX_NUM_MSI_IRQS 32
@@ -30,84 +31,6 @@
#define MC_PCIE_BRIDGE_ADDR (MC_PCIE1_BRIDGE_ADDR)
#define MC_PCIE_CTRL_ADDR (MC_PCIE1_CTRL_ADDR)
-/* PCIe Bridge Phy Regs */
-#define PCIE_PCI_IRQ_DW0 0xa8
-#define MSIX_CAP_MASK BIT(31)
-#define NUM_MSI_MSGS_MASK GENMASK(6, 4)
-#define NUM_MSI_MSGS_SHIFT 4
-
-#define IMASK_LOCAL 0x180
-#define DMA_END_ENGINE_0_MASK 0x00000000u
-#define DMA_END_ENGINE_0_SHIFT 0
-#define DMA_END_ENGINE_1_MASK 0x00000000u
-#define DMA_END_ENGINE_1_SHIFT 1
-#define DMA_ERROR_ENGINE_0_MASK 0x00000100u
-#define DMA_ERROR_ENGINE_0_SHIFT 8
-#define DMA_ERROR_ENGINE_1_MASK 0x00000200u
-#define DMA_ERROR_ENGINE_1_SHIFT 9
-#define A_ATR_EVT_POST_ERR_MASK 0x00010000u
-#define A_ATR_EVT_POST_ERR_SHIFT 16
-#define A_ATR_EVT_FETCH_ERR_MASK 0x00020000u
-#define A_ATR_EVT_FETCH_ERR_SHIFT 17
-#define A_ATR_EVT_DISCARD_ERR_MASK 0x00040000u
-#define A_ATR_EVT_DISCARD_ERR_SHIFT 18
-#define A_ATR_EVT_DOORBELL_MASK 0x00000000u
-#define A_ATR_EVT_DOORBELL_SHIFT 19
-#define P_ATR_EVT_POST_ERR_MASK 0x00100000u
-#define P_ATR_EVT_POST_ERR_SHIFT 20
-#define P_ATR_EVT_FETCH_ERR_MASK 0x00200000u
-#define P_ATR_EVT_FETCH_ERR_SHIFT 21
-#define P_ATR_EVT_DISCARD_ERR_MASK 0x00400000u
-#define P_ATR_EVT_DISCARD_ERR_SHIFT 22
-#define P_ATR_EVT_DOORBELL_MASK 0x00000000u
-#define P_ATR_EVT_DOORBELL_SHIFT 23
-#define PM_MSI_INT_INTA_MASK 0x01000000u
-#define PM_MSI_INT_INTA_SHIFT 24
-#define PM_MSI_INT_INTB_MASK 0x02000000u
-#define PM_MSI_INT_INTB_SHIFT 25
-#define PM_MSI_INT_INTC_MASK 0x04000000u
-#define PM_MSI_INT_INTC_SHIFT 26
-#define PM_MSI_INT_INTD_MASK 0x08000000u
-#define PM_MSI_INT_INTD_SHIFT 27
-#define PM_MSI_INT_INTX_MASK 0x0f000000u
-#define PM_MSI_INT_INTX_SHIFT 24
-#define PM_MSI_INT_MSI_MASK 0x10000000u
-#define PM_MSI_INT_MSI_SHIFT 28
-#define PM_MSI_INT_AER_EVT_MASK 0x20000000u
-#define PM_MSI_INT_AER_EVT_SHIFT 29
-#define PM_MSI_INT_EVENTS_MASK 0x40000000u
-#define PM_MSI_INT_EVENTS_SHIFT 30
-#define PM_MSI_INT_SYS_ERR_MASK 0x80000000u
-#define PM_MSI_INT_SYS_ERR_SHIFT 31
-#define NUM_LOCAL_EVENTS 15
-#define ISTATUS_LOCAL 0x184
-#define IMASK_HOST 0x188
-#define ISTATUS_HOST 0x18c
-#define IMSI_ADDR 0x190
-#define ISTATUS_MSI 0x194
-
-/* PCIe Master table init defines */
-#define ATR0_PCIE_WIN0_SRCADDR_PARAM 0x600u
-#define ATR0_PCIE_ATR_SIZE 0x25
-#define ATR0_PCIE_ATR_SIZE_SHIFT 1
-#define ATR0_PCIE_WIN0_SRC_ADDR 0x604u
-#define ATR0_PCIE_WIN0_TRSL_ADDR_LSB 0x608u
-#define ATR0_PCIE_WIN0_TRSL_ADDR_UDW 0x60cu
-#define ATR0_PCIE_WIN0_TRSL_PARAM 0x610u
-
-/* PCIe AXI slave table init defines */
-#define ATR0_AXI4_SLV0_SRCADDR_PARAM 0x800u
-#define ATR_SIZE_SHIFT 1
-#define ATR_IMPL_ENABLE 1
-#define ATR0_AXI4_SLV0_SRC_ADDR 0x804u
-#define ATR0_AXI4_SLV0_TRSL_ADDR_LSB 0x808u
-#define ATR0_AXI4_SLV0_TRSL_ADDR_UDW 0x80cu
-#define ATR0_AXI4_SLV0_TRSL_PARAM 0x810u
-#define PCIE_TX_RX_INTERFACE 0x00000000u
-#define PCIE_CONFIG_INTERFACE 0x00000001u
-
-#define ATR_ENTRY_SIZE 32
-
/* PCIe Controller Phy Regs */
#define SEC_ERROR_EVENT_CNT 0x20
#define DED_ERROR_EVENT_CNT 0x24
@@ -179,20 +102,21 @@
#define EVENT_LOCAL_DMA_END_ENGINE_1 12
#define EVENT_LOCAL_DMA_ERROR_ENGINE_0 13
#define EVENT_LOCAL_DMA_ERROR_ENGINE_1 14
-#define EVENT_LOCAL_A_ATR_EVT_POST_ERR 15
-#define EVENT_LOCAL_A_ATR_EVT_FETCH_ERR 16
-#define EVENT_LOCAL_A_ATR_EVT_DISCARD_ERR 17
-#define EVENT_LOCAL_A_ATR_EVT_DOORBELL 18
-#define EVENT_LOCAL_P_ATR_EVT_POST_ERR 19
-#define EVENT_LOCAL_P_ATR_EVT_FETCH_ERR 20
-#define EVENT_LOCAL_P_ATR_EVT_DISCARD_ERR 21
-#define EVENT_LOCAL_P_ATR_EVT_DOORBELL 22
-#define EVENT_LOCAL_PM_MSI_INT_INTX 23
-#define EVENT_LOCAL_PM_MSI_INT_MSI 24
-#define EVENT_LOCAL_PM_MSI_INT_AER_EVT 25
-#define EVENT_LOCAL_PM_MSI_INT_EVENTS 26
-#define EVENT_LOCAL_PM_MSI_INT_SYS_ERR 27
-#define NUM_EVENTS 28
+#define NUM_MC_EVENTS 15
+#define EVENT_LOCAL_A_ATR_EVT_POST_ERR (NUM_MC_EVENTS + PLDA_AXI_POST_ERR)
+#define EVENT_LOCAL_A_ATR_EVT_FETCH_ERR (NUM_MC_EVENTS + PLDA_AXI_FETCH_ERR)
+#define EVENT_LOCAL_A_ATR_EVT_DISCARD_ERR (NUM_MC_EVENTS + PLDA_AXI_DISCARD_ERR)
+#define EVENT_LOCAL_A_ATR_EVT_DOORBELL (NUM_MC_EVENTS + PLDA_AXI_DOORBELL)
+#define EVENT_LOCAL_P_ATR_EVT_POST_ERR (NUM_MC_EVENTS + PLDA_PCIE_POST_ERR)
+#define EVENT_LOCAL_P_ATR_EVT_FETCH_ERR (NUM_MC_EVENTS + PLDA_PCIE_FETCH_ERR)
+#define EVENT_LOCAL_P_ATR_EVT_DISCARD_ERR (NUM_MC_EVENTS + PLDA_PCIE_DISCARD_ERR)
+#define EVENT_LOCAL_P_ATR_EVT_DOORBELL (NUM_MC_EVENTS + PLDA_PCIE_DOORBELL)
+#define EVENT_LOCAL_PM_MSI_INT_INTX (NUM_MC_EVENTS + PLDA_INTX)
+#define EVENT_LOCAL_PM_MSI_INT_MSI (NUM_MC_EVENTS + PLDA_MSI)
+#define EVENT_LOCAL_PM_MSI_INT_AER_EVT (NUM_MC_EVENTS + PLDA_AER_EVENT)
+#define EVENT_LOCAL_PM_MSI_INT_EVENTS (NUM_MC_EVENTS + PLDA_MISC_EVENTS)
+#define EVENT_LOCAL_PM_MSI_INT_SYS_ERR (NUM_MC_EVENTS + PLDA_SYS_ERR)
+#define NUM_EVENTS (NUM_MC_EVENTS + PLDA_INT_EVENT_NUM)
#define PCIE_EVENT_CAUSE(x, s) \
[EVENT_PCIE_ ## x] = { __stringify(x), s }
--- /dev/null
+++ b/drivers/pci/controller/plda/pcie-plda.h
@@ -0,0 +1,108 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * PLDA PCIe host controller driver
+ */
+
+#ifndef _PCIE_PLDA_H
+#define _PCIE_PLDA_H
+
+/* PCIe Bridge Phy Regs */
+#define PCIE_PCI_IRQ_DW0 0xa8
+#define MSIX_CAP_MASK BIT(31)
+#define NUM_MSI_MSGS_MASK GENMASK(6, 4)
+#define NUM_MSI_MSGS_SHIFT 4
+
+#define IMASK_LOCAL 0x180
+#define DMA_END_ENGINE_0_MASK 0x00000000u
+#define DMA_END_ENGINE_0_SHIFT 0
+#define DMA_END_ENGINE_1_MASK 0x00000000u
+#define DMA_END_ENGINE_1_SHIFT 1
+#define DMA_ERROR_ENGINE_0_MASK 0x00000100u
+#define DMA_ERROR_ENGINE_0_SHIFT 8
+#define DMA_ERROR_ENGINE_1_MASK 0x00000200u
+#define DMA_ERROR_ENGINE_1_SHIFT 9
+#define A_ATR_EVT_POST_ERR_MASK 0x00010000u
+#define A_ATR_EVT_POST_ERR_SHIFT 16
+#define A_ATR_EVT_FETCH_ERR_MASK 0x00020000u
+#define A_ATR_EVT_FETCH_ERR_SHIFT 17
+#define A_ATR_EVT_DISCARD_ERR_MASK 0x00040000u
+#define A_ATR_EVT_DISCARD_ERR_SHIFT 18
+#define A_ATR_EVT_DOORBELL_MASK 0x00000000u
+#define A_ATR_EVT_DOORBELL_SHIFT 19
+#define P_ATR_EVT_POST_ERR_MASK 0x00100000u
+#define P_ATR_EVT_POST_ERR_SHIFT 20
+#define P_ATR_EVT_FETCH_ERR_MASK 0x00200000u
+#define P_ATR_EVT_FETCH_ERR_SHIFT 21
+#define P_ATR_EVT_DISCARD_ERR_MASK 0x00400000u
+#define P_ATR_EVT_DISCARD_ERR_SHIFT 22
+#define P_ATR_EVT_DOORBELL_MASK 0x00000000u
+#define P_ATR_EVT_DOORBELL_SHIFT 23
+#define PM_MSI_INT_INTA_MASK 0x01000000u
+#define PM_MSI_INT_INTA_SHIFT 24
+#define PM_MSI_INT_INTB_MASK 0x02000000u
+#define PM_MSI_INT_INTB_SHIFT 25
+#define PM_MSI_INT_INTC_MASK 0x04000000u
+#define PM_MSI_INT_INTC_SHIFT 26
+#define PM_MSI_INT_INTD_MASK 0x08000000u
+#define PM_MSI_INT_INTD_SHIFT 27
+#define PM_MSI_INT_INTX_MASK 0x0f000000u
+#define PM_MSI_INT_INTX_SHIFT 24
+#define PM_MSI_INT_MSI_MASK 0x10000000u
+#define PM_MSI_INT_MSI_SHIFT 28
+#define PM_MSI_INT_AER_EVT_MASK 0x20000000u
+#define PM_MSI_INT_AER_EVT_SHIFT 29
+#define PM_MSI_INT_EVENTS_MASK 0x40000000u
+#define PM_MSI_INT_EVENTS_SHIFT 30
+#define PM_MSI_INT_SYS_ERR_MASK 0x80000000u
+#define PM_MSI_INT_SYS_ERR_SHIFT 31
+#define NUM_LOCAL_EVENTS 15
+#define ISTATUS_LOCAL 0x184
+#define IMASK_HOST 0x188
+#define ISTATUS_HOST 0x18c
+#define IMSI_ADDR 0x190
+#define ISTATUS_MSI 0x194
+
+/* PCIe Master table init defines */
+#define ATR0_PCIE_WIN0_SRCADDR_PARAM 0x600u
+#define ATR0_PCIE_ATR_SIZE 0x25
+#define ATR0_PCIE_ATR_SIZE_SHIFT 1
+#define ATR0_PCIE_WIN0_SRC_ADDR 0x604u
+#define ATR0_PCIE_WIN0_TRSL_ADDR_LSB 0x608u
+#define ATR0_PCIE_WIN0_TRSL_ADDR_UDW 0x60cu
+#define ATR0_PCIE_WIN0_TRSL_PARAM 0x610u
+
+/* PCIe AXI slave table init defines */
+#define ATR0_AXI4_SLV0_SRCADDR_PARAM 0x800u
+#define ATR_SIZE_SHIFT 1
+#define ATR_IMPL_ENABLE 1
+#define ATR0_AXI4_SLV0_SRC_ADDR 0x804u
+#define ATR0_AXI4_SLV0_TRSL_ADDR_LSB 0x808u
+#define ATR0_AXI4_SLV0_TRSL_ADDR_UDW 0x80cu
+#define ATR0_AXI4_SLV0_TRSL_PARAM 0x810u
+#define PCIE_TX_RX_INTERFACE 0x00000000u
+#define PCIE_CONFIG_INTERFACE 0x00000001u
+
+#define ATR_ENTRY_SIZE 32
+
+enum plda_int_event {
+ PLDA_AXI_POST_ERR,
+ PLDA_AXI_FETCH_ERR,
+ PLDA_AXI_DISCARD_ERR,
+ PLDA_AXI_DOORBELL,
+ PLDA_PCIE_POST_ERR,
+ PLDA_PCIE_FETCH_ERR,
+ PLDA_PCIE_DISCARD_ERR,
+ PLDA_PCIE_DOORBELL,
+ PLDA_INTX,
+ PLDA_MSI,
+ PLDA_AER_EVENT,
+ PLDA_MISC_EVENTS,
+ PLDA_SYS_ERR,
+ PLDA_INT_EVENT_NUM
+};
+
+#define PLDA_NUM_DMA_EVENTS 16
+
+#define PLDA_MAX_INT_NUM (PLDA_NUM_DMA_EVENTS + PLDA_INT_EVENT_NUM)
+
+#endif

View File

@ -0,0 +1,107 @@
From 6ee4d4568314425079ae88229bb9abbff9b92b8b Mon Sep 17 00:00:00 2001
From: Minda Chen <minda.chen@starfivetech.com>
Date: Mon, 8 Jan 2024 19:05:54 +0800
Subject: [PATCH 017/116] PCI: microchip: Add bridge_addr field to struct
mc_pcie
For bridge address base is common PLDA field, Add this to struct mc_pcie
first.
INTx and MSI codes interrupts codes will get the bridge base address from
port->bridge_addr. These codes will be changed to common codes.
axi_base_addr is Microchip its own data.
Signed-off-by: Minda Chen <minda.chen@starfivetech.com>
Reviewed-by: Conor Dooley <conor.dooley@microchip.com>
---
.../pci/controller/plda/pcie-microchip-host.c | 23 ++++++++-----------
1 file changed, 9 insertions(+), 14 deletions(-)
--- a/drivers/pci/controller/plda/pcie-microchip-host.c
+++ b/drivers/pci/controller/plda/pcie-microchip-host.c
@@ -195,6 +195,7 @@ struct mc_pcie {
struct irq_domain *event_domain;
raw_spinlock_t lock;
struct mc_msi msi;
+ void __iomem *bridge_addr;
};
struct cause {
@@ -339,8 +340,7 @@ static void mc_handle_msi(struct irq_des
struct irq_chip *chip = irq_desc_get_chip(desc);
struct device *dev = port->dev;
struct mc_msi *msi = &port->msi;
- void __iomem *bridge_base_addr =
- port->axi_base_addr + MC_PCIE_BRIDGE_ADDR;
+ void __iomem *bridge_base_addr = port->bridge_addr;
unsigned long status;
u32 bit;
int ret;
@@ -365,8 +365,7 @@ static void mc_handle_msi(struct irq_des
static void mc_msi_bottom_irq_ack(struct irq_data *data)
{
struct mc_pcie *port = irq_data_get_irq_chip_data(data);
- void __iomem *bridge_base_addr =
- port->axi_base_addr + MC_PCIE_BRIDGE_ADDR;
+ void __iomem *bridge_base_addr = port->bridge_addr;
u32 bitpos = data->hwirq;
writel_relaxed(BIT(bitpos), bridge_base_addr + ISTATUS_MSI);
@@ -488,8 +487,7 @@ static void mc_handle_intx(struct irq_de
struct mc_pcie *port = irq_desc_get_handler_data(desc);
struct irq_chip *chip = irq_desc_get_chip(desc);
struct device *dev = port->dev;
- void __iomem *bridge_base_addr =
- port->axi_base_addr + MC_PCIE_BRIDGE_ADDR;
+ void __iomem *bridge_base_addr = port->bridge_addr;
unsigned long status;
u32 bit;
int ret;
@@ -514,8 +512,7 @@ static void mc_handle_intx(struct irq_de
static void mc_ack_intx_irq(struct irq_data *data)
{
struct mc_pcie *port = irq_data_get_irq_chip_data(data);
- void __iomem *bridge_base_addr =
- port->axi_base_addr + MC_PCIE_BRIDGE_ADDR;
+ void __iomem *bridge_base_addr = port->bridge_addr;
u32 mask = BIT(data->hwirq + PM_MSI_INT_INTX_SHIFT);
writel_relaxed(mask, bridge_base_addr + ISTATUS_LOCAL);
@@ -524,8 +521,7 @@ static void mc_ack_intx_irq(struct irq_d
static void mc_mask_intx_irq(struct irq_data *data)
{
struct mc_pcie *port = irq_data_get_irq_chip_data(data);
- void __iomem *bridge_base_addr =
- port->axi_base_addr + MC_PCIE_BRIDGE_ADDR;
+ void __iomem *bridge_base_addr = port->bridge_addr;
unsigned long flags;
u32 mask = BIT(data->hwirq + PM_MSI_INT_INTX_SHIFT);
u32 val;
@@ -540,8 +536,7 @@ static void mc_mask_intx_irq(struct irq_
static void mc_unmask_intx_irq(struct irq_data *data)
{
struct mc_pcie *port = irq_data_get_irq_chip_data(data);
- void __iomem *bridge_base_addr =
- port->axi_base_addr + MC_PCIE_BRIDGE_ADDR;
+ void __iomem *bridge_base_addr = port->bridge_addr;
unsigned long flags;
u32 mask = BIT(data->hwirq + PM_MSI_INT_INTX_SHIFT);
u32 val;
@@ -896,8 +891,7 @@ static void mc_pcie_setup_window(void __
static int mc_pcie_setup_windows(struct platform_device *pdev,
struct mc_pcie *port)
{
- void __iomem *bridge_base_addr =
- port->axi_base_addr + MC_PCIE_BRIDGE_ADDR;
+ void __iomem *bridge_base_addr = port->bridge_addr;
struct pci_host_bridge *bridge = platform_get_drvdata(pdev);
struct resource_entry *entry;
u64 pci_addr;
@@ -1081,6 +1075,7 @@ static int mc_host_probe(struct platform
mc_disable_interrupts(port);
bridge_base_addr = port->axi_base_addr + MC_PCIE_BRIDGE_ADDR;
+ port->bridge_addr = bridge_base_addr;
/* Allow enabling MSI by disabling MSI-X */
val = readl(bridge_base_addr + PCIE_PCI_IRQ_DW0);

View File

@ -0,0 +1,347 @@
From 7c1c679bdd0b6b727248edbee77836024c935f91 Mon Sep 17 00:00:00 2001
From: Minda Chen <minda.chen@starfivetech.com>
Date: Mon, 8 Jan 2024 19:05:55 +0800
Subject: [PATCH 018/116] PCI: microchip: Rename two PCIe data structures
Add PLDA PCIe related data structures by rename data structure name from
mc_* to plda_*.
axi_base_addr is stayed in struct mc_pcie for it's microchip its own data.
The event interrupt codes is still using struct mc_pcie because the event
interrupt codes can not be re-used.
Signed-off-by: Minda Chen <minda.chen@starfivetech.com>
Reviewed-by: Conor Dooley <conor.dooley@microchip.com>
---
.../pci/controller/plda/pcie-microchip-host.c | 96 ++++++++++---------
1 file changed, 53 insertions(+), 43 deletions(-)
--- a/drivers/pci/controller/plda/pcie-microchip-host.c
+++ b/drivers/pci/controller/plda/pcie-microchip-host.c
@@ -22,7 +22,7 @@
#include "pcie-plda.h"
/* Number of MSI IRQs */
-#define MC_MAX_NUM_MSI_IRQS 32
+#define PLDA_MAX_NUM_MSI_IRQS 32
/* PCIe Bridge Phy and Controller Phy offsets */
#define MC_PCIE1_BRIDGE_ADDR 0x00008000u
@@ -179,25 +179,29 @@ struct event_map {
u32 event_bit;
};
-struct mc_msi {
+struct plda_msi {
struct mutex lock; /* Protect used bitmap */
struct irq_domain *msi_domain;
struct irq_domain *dev_domain;
u32 num_vectors;
u64 vector_phy;
- DECLARE_BITMAP(used, MC_MAX_NUM_MSI_IRQS);
+ DECLARE_BITMAP(used, PLDA_MAX_NUM_MSI_IRQS);
};
-struct mc_pcie {
- void __iomem *axi_base_addr;
+struct plda_pcie_rp {
struct device *dev;
struct irq_domain *intx_domain;
struct irq_domain *event_domain;
raw_spinlock_t lock;
- struct mc_msi msi;
+ struct plda_msi msi;
void __iomem *bridge_addr;
};
+struct mc_pcie {
+ struct plda_pcie_rp plda;
+ void __iomem *axi_base_addr;
+};
+
struct cause {
const char *sym;
const char *str;
@@ -313,7 +317,7 @@ static struct mc_pcie *port;
static void mc_pcie_enable_msi(struct mc_pcie *port, void __iomem *ecam)
{
- struct mc_msi *msi = &port->msi;
+ struct plda_msi *msi = &port->plda.msi;
u16 reg;
u8 queue_size;
@@ -336,10 +340,10 @@ static void mc_pcie_enable_msi(struct mc
static void mc_handle_msi(struct irq_desc *desc)
{
- struct mc_pcie *port = irq_desc_get_handler_data(desc);
+ struct plda_pcie_rp *port = irq_desc_get_handler_data(desc);
struct irq_chip *chip = irq_desc_get_chip(desc);
struct device *dev = port->dev;
- struct mc_msi *msi = &port->msi;
+ struct plda_msi *msi = &port->msi;
void __iomem *bridge_base_addr = port->bridge_addr;
unsigned long status;
u32 bit;
@@ -364,7 +368,7 @@ static void mc_handle_msi(struct irq_des
static void mc_msi_bottom_irq_ack(struct irq_data *data)
{
- struct mc_pcie *port = irq_data_get_irq_chip_data(data);
+ struct plda_pcie_rp *port = irq_data_get_irq_chip_data(data);
void __iomem *bridge_base_addr = port->bridge_addr;
u32 bitpos = data->hwirq;
@@ -373,7 +377,7 @@ static void mc_msi_bottom_irq_ack(struct
static void mc_compose_msi_msg(struct irq_data *data, struct msi_msg *msg)
{
- struct mc_pcie *port = irq_data_get_irq_chip_data(data);
+ struct plda_pcie_rp *port = irq_data_get_irq_chip_data(data);
phys_addr_t addr = port->msi.vector_phy;
msg->address_lo = lower_32_bits(addr);
@@ -400,8 +404,8 @@ static struct irq_chip mc_msi_bottom_irq
static int mc_irq_msi_domain_alloc(struct irq_domain *domain, unsigned int virq,
unsigned int nr_irqs, void *args)
{
- struct mc_pcie *port = domain->host_data;
- struct mc_msi *msi = &port->msi;
+ struct plda_pcie_rp *port = domain->host_data;
+ struct plda_msi *msi = &port->msi;
unsigned long bit;
mutex_lock(&msi->lock);
@@ -425,8 +429,8 @@ static void mc_irq_msi_domain_free(struc
unsigned int nr_irqs)
{
struct irq_data *d = irq_domain_get_irq_data(domain, virq);
- struct mc_pcie *port = irq_data_get_irq_chip_data(d);
- struct mc_msi *msi = &port->msi;
+ struct plda_pcie_rp *port = irq_data_get_irq_chip_data(d);
+ struct plda_msi *msi = &port->msi;
mutex_lock(&msi->lock);
@@ -456,11 +460,11 @@ static struct msi_domain_info mc_msi_dom
.chip = &mc_msi_irq_chip,
};
-static int mc_allocate_msi_domains(struct mc_pcie *port)
+static int mc_allocate_msi_domains(struct plda_pcie_rp *port)
{
struct device *dev = port->dev;
struct fwnode_handle *fwnode = of_node_to_fwnode(dev->of_node);
- struct mc_msi *msi = &port->msi;
+ struct plda_msi *msi = &port->msi;
mutex_init(&port->msi.lock);
@@ -484,7 +488,7 @@ static int mc_allocate_msi_domains(struc
static void mc_handle_intx(struct irq_desc *desc)
{
- struct mc_pcie *port = irq_desc_get_handler_data(desc);
+ struct plda_pcie_rp *port = irq_desc_get_handler_data(desc);
struct irq_chip *chip = irq_desc_get_chip(desc);
struct device *dev = port->dev;
void __iomem *bridge_base_addr = port->bridge_addr;
@@ -511,7 +515,7 @@ static void mc_handle_intx(struct irq_de
static void mc_ack_intx_irq(struct irq_data *data)
{
- struct mc_pcie *port = irq_data_get_irq_chip_data(data);
+ struct plda_pcie_rp *port = irq_data_get_irq_chip_data(data);
void __iomem *bridge_base_addr = port->bridge_addr;
u32 mask = BIT(data->hwirq + PM_MSI_INT_INTX_SHIFT);
@@ -520,7 +524,7 @@ static void mc_ack_intx_irq(struct irq_d
static void mc_mask_intx_irq(struct irq_data *data)
{
- struct mc_pcie *port = irq_data_get_irq_chip_data(data);
+ struct plda_pcie_rp *port = irq_data_get_irq_chip_data(data);
void __iomem *bridge_base_addr = port->bridge_addr;
unsigned long flags;
u32 mask = BIT(data->hwirq + PM_MSI_INT_INTX_SHIFT);
@@ -535,7 +539,7 @@ static void mc_mask_intx_irq(struct irq_
static void mc_unmask_intx_irq(struct irq_data *data)
{
- struct mc_pcie *port = irq_data_get_irq_chip_data(data);
+ struct plda_pcie_rp *port = irq_data_get_irq_chip_data(data);
void __iomem *bridge_base_addr = port->bridge_addr;
unsigned long flags;
u32 mask = BIT(data->hwirq + PM_MSI_INT_INTX_SHIFT);
@@ -625,21 +629,22 @@ static u32 local_events(struct mc_pcie *
return val;
}
-static u32 get_events(struct mc_pcie *port)
+static u32 get_events(struct plda_pcie_rp *port)
{
+ struct mc_pcie *mc_port = container_of(port, struct mc_pcie, plda);
u32 events = 0;
- events |= pcie_events(port);
- events |= sec_errors(port);
- events |= ded_errors(port);
- events |= local_events(port);
+ events |= pcie_events(mc_port);
+ events |= sec_errors(mc_port);
+ events |= ded_errors(mc_port);
+ events |= local_events(mc_port);
return events;
}
static irqreturn_t mc_event_handler(int irq, void *dev_id)
{
- struct mc_pcie *port = dev_id;
+ struct plda_pcie_rp *port = dev_id;
struct device *dev = port->dev;
struct irq_data *data;
@@ -655,7 +660,7 @@ static irqreturn_t mc_event_handler(int
static void mc_handle_event(struct irq_desc *desc)
{
- struct mc_pcie *port = irq_desc_get_handler_data(desc);
+ struct plda_pcie_rp *port = irq_desc_get_handler_data(desc);
unsigned long events;
u32 bit;
struct irq_chip *chip = irq_desc_get_chip(desc);
@@ -672,12 +677,13 @@ static void mc_handle_event(struct irq_d
static void mc_ack_event_irq(struct irq_data *data)
{
- struct mc_pcie *port = irq_data_get_irq_chip_data(data);
+ struct plda_pcie_rp *port = irq_data_get_irq_chip_data(data);
+ struct mc_pcie *mc_port = container_of(port, struct mc_pcie, plda);
u32 event = data->hwirq;
void __iomem *addr;
u32 mask;
- addr = port->axi_base_addr + event_descs[event].base +
+ addr = mc_port->axi_base_addr + event_descs[event].base +
event_descs[event].offset;
mask = event_descs[event].mask;
mask |= event_descs[event].enb_mask;
@@ -687,13 +693,14 @@ static void mc_ack_event_irq(struct irq_
static void mc_mask_event_irq(struct irq_data *data)
{
- struct mc_pcie *port = irq_data_get_irq_chip_data(data);
+ struct plda_pcie_rp *port = irq_data_get_irq_chip_data(data);
+ struct mc_pcie *mc_port = container_of(port, struct mc_pcie, plda);
u32 event = data->hwirq;
void __iomem *addr;
u32 mask;
u32 val;
- addr = port->axi_base_addr + event_descs[event].base +
+ addr = mc_port->axi_base_addr + event_descs[event].base +
event_descs[event].mask_offset;
mask = event_descs[event].mask;
if (event_descs[event].enb_mask) {
@@ -717,13 +724,14 @@ static void mc_mask_event_irq(struct irq
static void mc_unmask_event_irq(struct irq_data *data)
{
- struct mc_pcie *port = irq_data_get_irq_chip_data(data);
+ struct plda_pcie_rp *port = irq_data_get_irq_chip_data(data);
+ struct mc_pcie *mc_port = container_of(port, struct mc_pcie, plda);
u32 event = data->hwirq;
void __iomem *addr;
u32 mask;
u32 val;
- addr = port->axi_base_addr + event_descs[event].base +
+ addr = mc_port->axi_base_addr + event_descs[event].base +
event_descs[event].mask_offset;
mask = event_descs[event].mask;
@@ -811,7 +819,7 @@ static int mc_pcie_init_clks(struct devi
return 0;
}
-static int mc_pcie_init_irq_domains(struct mc_pcie *port)
+static int mc_pcie_init_irq_domains(struct plda_pcie_rp *port)
{
struct device *dev = port->dev;
struct device_node *node = dev->of_node;
@@ -889,7 +897,7 @@ static void mc_pcie_setup_window(void __
}
static int mc_pcie_setup_windows(struct platform_device *pdev,
- struct mc_pcie *port)
+ struct plda_pcie_rp *port)
{
void __iomem *bridge_base_addr = port->bridge_addr;
struct pci_host_bridge *bridge = platform_get_drvdata(pdev);
@@ -970,7 +978,7 @@ static void mc_disable_interrupts(struct
writel_relaxed(GENMASK(31, 0), bridge_base_addr + ISTATUS_HOST);
}
-static int mc_init_interrupts(struct platform_device *pdev, struct mc_pcie *port)
+static int mc_init_interrupts(struct platform_device *pdev, struct plda_pcie_rp *port)
{
struct device *dev = &pdev->dev;
int irq;
@@ -1043,12 +1051,12 @@ static int mc_platform_init(struct pci_c
mc_pcie_enable_msi(port, cfg->win);
/* Configure non-config space outbound ranges */
- ret = mc_pcie_setup_windows(pdev, port);
+ ret = mc_pcie_setup_windows(pdev, &port->plda);
if (ret)
return ret;
/* Address translation is up; safe to enable interrupts */
- ret = mc_init_interrupts(pdev, port);
+ ret = mc_init_interrupts(pdev, &port->plda);
if (ret)
return ret;
@@ -1059,6 +1067,7 @@ static int mc_host_probe(struct platform
{
struct device *dev = &pdev->dev;
void __iomem *bridge_base_addr;
+ struct plda_pcie_rp *plda;
int ret;
u32 val;
@@ -1066,7 +1075,8 @@ static int mc_host_probe(struct platform
if (!port)
return -ENOMEM;
- port->dev = dev;
+ plda = &port->plda;
+ plda->dev = dev;
port->axi_base_addr = devm_platform_ioremap_resource(pdev, 1);
if (IS_ERR(port->axi_base_addr))
@@ -1075,7 +1085,7 @@ static int mc_host_probe(struct platform
mc_disable_interrupts(port);
bridge_base_addr = port->axi_base_addr + MC_PCIE_BRIDGE_ADDR;
- port->bridge_addr = bridge_base_addr;
+ plda->bridge_addr = bridge_base_addr;
/* Allow enabling MSI by disabling MSI-X */
val = readl(bridge_base_addr + PCIE_PCI_IRQ_DW0);
@@ -1087,10 +1097,10 @@ static int mc_host_probe(struct platform
val &= NUM_MSI_MSGS_MASK;
val >>= NUM_MSI_MSGS_SHIFT;
- port->msi.num_vectors = 1 << val;
+ plda->msi.num_vectors = 1 << val;
/* Pick vector address from design */
- port->msi.vector_phy = readl_relaxed(bridge_base_addr + IMSI_ADDR);
+ plda->msi.vector_phy = readl_relaxed(bridge_base_addr + IMSI_ADDR);
ret = mc_pcie_init_clks(dev);
if (ret) {

View File

@ -0,0 +1,87 @@
From a53cf9b237dd53c9538b51a8df592888935c8411 Mon Sep 17 00:00:00 2001
From: Minda Chen <minda.chen@starfivetech.com>
Date: Mon, 8 Jan 2024 19:05:56 +0800
Subject: [PATCH 019/116] PCI: microchip: Move PCIe host data structures to
plda-pcie.h
Move the common data structures definition to head file for these two data
structures can be re-used.
Signed-off-by: Minda Chen <minda.chen@starfivetech.com>
Reviewed-by: Conor Dooley <conor.dooley@microchip.com>
---
.../pci/controller/plda/pcie-microchip-host.c | 20 ------------------
drivers/pci/controller/plda/pcie-plda.h | 21 +++++++++++++++++++
2 files changed, 21 insertions(+), 20 deletions(-)
--- a/drivers/pci/controller/plda/pcie-microchip-host.c
+++ b/drivers/pci/controller/plda/pcie-microchip-host.c
@@ -21,9 +21,6 @@
#include "../../pci.h"
#include "pcie-plda.h"
-/* Number of MSI IRQs */
-#define PLDA_MAX_NUM_MSI_IRQS 32
-
/* PCIe Bridge Phy and Controller Phy offsets */
#define MC_PCIE1_BRIDGE_ADDR 0x00008000u
#define MC_PCIE1_CTRL_ADDR 0x0000a000u
@@ -179,23 +176,6 @@ struct event_map {
u32 event_bit;
};
-struct plda_msi {
- struct mutex lock; /* Protect used bitmap */
- struct irq_domain *msi_domain;
- struct irq_domain *dev_domain;
- u32 num_vectors;
- u64 vector_phy;
- DECLARE_BITMAP(used, PLDA_MAX_NUM_MSI_IRQS);
-};
-
-struct plda_pcie_rp {
- struct device *dev;
- struct irq_domain *intx_domain;
- struct irq_domain *event_domain;
- raw_spinlock_t lock;
- struct plda_msi msi;
- void __iomem *bridge_addr;
-};
struct mc_pcie {
struct plda_pcie_rp plda;
--- a/drivers/pci/controller/plda/pcie-plda.h
+++ b/drivers/pci/controller/plda/pcie-plda.h
@@ -6,6 +6,9 @@
#ifndef _PCIE_PLDA_H
#define _PCIE_PLDA_H
+/* Number of MSI IRQs */
+#define PLDA_MAX_NUM_MSI_IRQS 32
+
/* PCIe Bridge Phy Regs */
#define PCIE_PCI_IRQ_DW0 0xa8
#define MSIX_CAP_MASK BIT(31)
@@ -105,4 +108,22 @@ enum plda_int_event {
#define PLDA_MAX_INT_NUM (PLDA_NUM_DMA_EVENTS + PLDA_INT_EVENT_NUM)
+struct plda_msi {
+ struct mutex lock; /* Protect used bitmap */
+ struct irq_domain *msi_domain;
+ struct irq_domain *dev_domain;
+ u32 num_vectors;
+ u64 vector_phy;
+ DECLARE_BITMAP(used, PLDA_MAX_NUM_MSI_IRQS);
+};
+
+struct plda_pcie_rp {
+ struct device *dev;
+ struct irq_domain *intx_domain;
+ struct irq_domain *event_domain;
+ raw_spinlock_t lock;
+ struct plda_msi msi;
+ void __iomem *bridge_addr;
+};
+
#endif

View File

@ -0,0 +1,76 @@
From d0e56d1ef7398bbf76be6e48d77943cbf644688e Mon Sep 17 00:00:00 2001
From: Minda Chen <minda.chen@starfivetech.com>
Date: Mon, 8 Jan 2024 19:05:57 +0800
Subject: [PATCH 020/116] PCI: microchip: Rename two setup functions
Rename two setup functions to plda prefix. Prepare to re-use these two
setup function.
For two setup functions names are similar, rename mc_pcie_setup_windows()
to plda_pcie_setup_iomems().
Signed-off-by: Minda Chen <minda.chen@starfivetech.com>
Reviewed-by: Conor Dooley <conor.dooley@microchip.com>
---
.../pci/controller/plda/pcie-microchip-host.c | 24 +++++++++----------
1 file changed, 12 insertions(+), 12 deletions(-)
--- a/drivers/pci/controller/plda/pcie-microchip-host.c
+++ b/drivers/pci/controller/plda/pcie-microchip-host.c
@@ -838,9 +838,9 @@ static int mc_pcie_init_irq_domains(stru
return mc_allocate_msi_domains(port);
}
-static void mc_pcie_setup_window(void __iomem *bridge_base_addr, u32 index,
- phys_addr_t axi_addr, phys_addr_t pci_addr,
- size_t size)
+static void plda_pcie_setup_window(void __iomem *bridge_base_addr, u32 index,
+ phys_addr_t axi_addr, phys_addr_t pci_addr,
+ size_t size)
{
u32 atr_sz = ilog2(size) - 1;
u32 val;
@@ -876,8 +876,8 @@ static void mc_pcie_setup_window(void __
writel(0, bridge_base_addr + ATR0_PCIE_WIN0_SRC_ADDR);
}
-static int mc_pcie_setup_windows(struct platform_device *pdev,
- struct plda_pcie_rp *port)
+static int plda_pcie_setup_iomems(struct platform_device *pdev,
+ struct plda_pcie_rp *port)
{
void __iomem *bridge_base_addr = port->bridge_addr;
struct pci_host_bridge *bridge = platform_get_drvdata(pdev);
@@ -888,9 +888,9 @@ static int mc_pcie_setup_windows(struct
resource_list_for_each_entry(entry, &bridge->windows) {
if (resource_type(entry->res) == IORESOURCE_MEM) {
pci_addr = entry->res->start - entry->offset;
- mc_pcie_setup_window(bridge_base_addr, index,
- entry->res->start, pci_addr,
- resource_size(entry->res));
+ plda_pcie_setup_window(bridge_base_addr, index,
+ entry->res->start, pci_addr,
+ resource_size(entry->res));
index++;
}
}
@@ -1023,15 +1023,15 @@ static int mc_platform_init(struct pci_c
int ret;
/* Configure address translation table 0 for PCIe config space */
- mc_pcie_setup_window(bridge_base_addr, 0, cfg->res.start,
- cfg->res.start,
- resource_size(&cfg->res));
+ plda_pcie_setup_window(bridge_base_addr, 0, cfg->res.start,
+ cfg->res.start,
+ resource_size(&cfg->res));
/* Need some fixups in config space */
mc_pcie_enable_msi(port, cfg->win);
/* Configure non-config space outbound ranges */
- ret = mc_pcie_setup_windows(pdev, &port->plda);
+ ret = plda_pcie_setup_iomems(pdev, &port->plda);
if (ret)
return ret;

View File

@ -0,0 +1,49 @@
From 2fd7c88ef318fd39023ce1eb73f37a29fbd25d74 Mon Sep 17 00:00:00 2001
From: Minda Chen <minda.chen@starfivetech.com>
Date: Mon, 8 Jan 2024 19:05:58 +0800
Subject: [PATCH 021/116] PCI: microchip: Change the argument of
plda_pcie_setup_iomems()
If other vendor do not select PCI_HOST_COMMON, the driver data is not
struct pci_host_bridge.
Move calling platform_get_drvdata() to mc_platform_init().
Signed-off-by: Minda Chen <minda.chen@starfivetech.com>
Reviewed-by: Conor Dooley <conor.dooley@microchip.com>
---
drivers/pci/controller/plda/pcie-microchip-host.c | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
--- a/drivers/pci/controller/plda/pcie-microchip-host.c
+++ b/drivers/pci/controller/plda/pcie-microchip-host.c
@@ -876,11 +876,10 @@ static void plda_pcie_setup_window(void
writel(0, bridge_base_addr + ATR0_PCIE_WIN0_SRC_ADDR);
}
-static int plda_pcie_setup_iomems(struct platform_device *pdev,
+static int plda_pcie_setup_iomems(struct pci_host_bridge *bridge,
struct plda_pcie_rp *port)
{
void __iomem *bridge_base_addr = port->bridge_addr;
- struct pci_host_bridge *bridge = platform_get_drvdata(pdev);
struct resource_entry *entry;
u64 pci_addr;
u32 index = 1;
@@ -1018,6 +1017,7 @@ static int mc_platform_init(struct pci_c
{
struct device *dev = cfg->parent;
struct platform_device *pdev = to_platform_device(dev);
+ struct pci_host_bridge *bridge = platform_get_drvdata(pdev);
void __iomem *bridge_base_addr =
port->axi_base_addr + MC_PCIE_BRIDGE_ADDR;
int ret;
@@ -1031,7 +1031,7 @@ static int mc_platform_init(struct pci_c
mc_pcie_enable_msi(port, cfg->win);
/* Configure non-config space outbound ranges */
- ret = plda_pcie_setup_iomems(pdev, &port->plda);
+ ret = plda_pcie_setup_iomems(bridge, &port->plda);
if (ret)
return ret;

View File

@ -0,0 +1,200 @@
From 201ce99897ff5fff2612cb633406e90c1b2acbcf Mon Sep 17 00:00:00 2001
From: Minda Chen <minda.chen@starfivetech.com>
Date: Mon, 8 Jan 2024 19:05:59 +0800
Subject: [PATCH 022/116] PCI: microchip: Move setup functions to
pcie-plda-host.c
Move setup functions to common pcie-plda-host.c. So these two functions
can be re-used.
Signed-off-by: Minda Chen <minda.chen@starfivetech.com>
Reviewed-by: Conor Dooley <conor.dooley@microchip.com>
---
drivers/pci/controller/plda/Kconfig | 4 +
drivers/pci/controller/plda/Makefile | 1 +
.../pci/controller/plda/pcie-microchip-host.c | 59 ---------------
drivers/pci/controller/plda/pcie-plda-host.c | 74 +++++++++++++++++++
drivers/pci/controller/plda/pcie-plda.h | 5 ++
5 files changed, 84 insertions(+), 59 deletions(-)
create mode 100644 drivers/pci/controller/plda/pcie-plda-host.c
--- a/drivers/pci/controller/plda/Kconfig
+++ b/drivers/pci/controller/plda/Kconfig
@@ -3,10 +3,14 @@
menu "PLDA-based PCIe controllers"
depends on PCI
+config PCIE_PLDA_HOST
+ bool
+
config PCIE_MICROCHIP_HOST
tristate "Microchip AXI PCIe controller"
depends on PCI_MSI && OF
select PCI_HOST_COMMON
+ select PCIE_PLDA_HOST
help
Say Y here if you want kernel to support the Microchip AXI PCIe
Host Bridge driver.
--- a/drivers/pci/controller/plda/Makefile
+++ b/drivers/pci/controller/plda/Makefile
@@ -1,2 +1,3 @@
# SPDX-License-Identifier: GPL-2.0
+obj-$(CONFIG_PCIE_PLDA_HOST) += pcie-plda-host.o
obj-$(CONFIG_PCIE_MICROCHIP_HOST) += pcie-microchip-host.o
--- a/drivers/pci/controller/plda/pcie-microchip-host.c
+++ b/drivers/pci/controller/plda/pcie-microchip-host.c
@@ -838,65 +838,6 @@ static int mc_pcie_init_irq_domains(stru
return mc_allocate_msi_domains(port);
}
-static void plda_pcie_setup_window(void __iomem *bridge_base_addr, u32 index,
- phys_addr_t axi_addr, phys_addr_t pci_addr,
- size_t size)
-{
- u32 atr_sz = ilog2(size) - 1;
- u32 val;
-
- if (index == 0)
- val = PCIE_CONFIG_INTERFACE;
- else
- val = PCIE_TX_RX_INTERFACE;
-
- writel(val, bridge_base_addr + (index * ATR_ENTRY_SIZE) +
- ATR0_AXI4_SLV0_TRSL_PARAM);
-
- val = lower_32_bits(axi_addr) | (atr_sz << ATR_SIZE_SHIFT) |
- ATR_IMPL_ENABLE;
- writel(val, bridge_base_addr + (index * ATR_ENTRY_SIZE) +
- ATR0_AXI4_SLV0_SRCADDR_PARAM);
-
- val = upper_32_bits(axi_addr);
- writel(val, bridge_base_addr + (index * ATR_ENTRY_SIZE) +
- ATR0_AXI4_SLV0_SRC_ADDR);
-
- val = lower_32_bits(pci_addr);
- writel(val, bridge_base_addr + (index * ATR_ENTRY_SIZE) +
- ATR0_AXI4_SLV0_TRSL_ADDR_LSB);
-
- val = upper_32_bits(pci_addr);
- writel(val, bridge_base_addr + (index * ATR_ENTRY_SIZE) +
- ATR0_AXI4_SLV0_TRSL_ADDR_UDW);
-
- val = readl(bridge_base_addr + ATR0_PCIE_WIN0_SRCADDR_PARAM);
- val |= (ATR0_PCIE_ATR_SIZE << ATR0_PCIE_ATR_SIZE_SHIFT);
- writel(val, bridge_base_addr + ATR0_PCIE_WIN0_SRCADDR_PARAM);
- writel(0, bridge_base_addr + ATR0_PCIE_WIN0_SRC_ADDR);
-}
-
-static int plda_pcie_setup_iomems(struct pci_host_bridge *bridge,
- struct plda_pcie_rp *port)
-{
- void __iomem *bridge_base_addr = port->bridge_addr;
- struct resource_entry *entry;
- u64 pci_addr;
- u32 index = 1;
-
- resource_list_for_each_entry(entry, &bridge->windows) {
- if (resource_type(entry->res) == IORESOURCE_MEM) {
- pci_addr = entry->res->start - entry->offset;
- plda_pcie_setup_window(bridge_base_addr, index,
- entry->res->start, pci_addr,
- resource_size(entry->res));
- index++;
- }
- }
-
- return 0;
-}
-
static inline void mc_clear_secs(struct mc_pcie *port)
{
void __iomem *ctrl_base_addr = port->axi_base_addr + MC_PCIE_CTRL_ADDR;
--- /dev/null
+++ b/drivers/pci/controller/plda/pcie-plda-host.c
@@ -0,0 +1,74 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * PLDA PCIe XpressRich host controller driver
+ *
+ * Copyright (C) 2023 Microchip Co. Ltd
+ *
+ * Author: Daire McNamara <daire.mcnamara@microchip.com>
+ */
+
+#include <linux/pci_regs.h>
+#include <linux/pci-ecam.h>
+
+#include "pcie-plda.h"
+
+void plda_pcie_setup_window(void __iomem *bridge_base_addr, u32 index,
+ phys_addr_t axi_addr, phys_addr_t pci_addr,
+ size_t size)
+{
+ u32 atr_sz = ilog2(size) - 1;
+ u32 val;
+
+ if (index == 0)
+ val = PCIE_CONFIG_INTERFACE;
+ else
+ val = PCIE_TX_RX_INTERFACE;
+
+ writel(val, bridge_base_addr + (index * ATR_ENTRY_SIZE) +
+ ATR0_AXI4_SLV0_TRSL_PARAM);
+
+ val = lower_32_bits(axi_addr) | (atr_sz << ATR_SIZE_SHIFT) |
+ ATR_IMPL_ENABLE;
+ writel(val, bridge_base_addr + (index * ATR_ENTRY_SIZE) +
+ ATR0_AXI4_SLV0_SRCADDR_PARAM);
+
+ val = upper_32_bits(axi_addr);
+ writel(val, bridge_base_addr + (index * ATR_ENTRY_SIZE) +
+ ATR0_AXI4_SLV0_SRC_ADDR);
+
+ val = lower_32_bits(pci_addr);
+ writel(val, bridge_base_addr + (index * ATR_ENTRY_SIZE) +
+ ATR0_AXI4_SLV0_TRSL_ADDR_LSB);
+
+ val = upper_32_bits(pci_addr);
+ writel(val, bridge_base_addr + (index * ATR_ENTRY_SIZE) +
+ ATR0_AXI4_SLV0_TRSL_ADDR_UDW);
+
+ val = readl(bridge_base_addr + ATR0_PCIE_WIN0_SRCADDR_PARAM);
+ val |= (ATR0_PCIE_ATR_SIZE << ATR0_PCIE_ATR_SIZE_SHIFT);
+ writel(val, bridge_base_addr + ATR0_PCIE_WIN0_SRCADDR_PARAM);
+ writel(0, bridge_base_addr + ATR0_PCIE_WIN0_SRC_ADDR);
+}
+EXPORT_SYMBOL_GPL(plda_pcie_setup_window);
+
+int plda_pcie_setup_iomems(struct pci_host_bridge *bridge,
+ struct plda_pcie_rp *port)
+{
+ void __iomem *bridge_base_addr = port->bridge_addr;
+ struct resource_entry *entry;
+ u64 pci_addr;
+ u32 index = 1;
+
+ resource_list_for_each_entry(entry, &bridge->windows) {
+ if (resource_type(entry->res) == IORESOURCE_MEM) {
+ pci_addr = entry->res->start - entry->offset;
+ plda_pcie_setup_window(bridge_base_addr, index,
+ entry->res->start, pci_addr,
+ resource_size(entry->res));
+ index++;
+ }
+ }
+
+ return 0;
+}
+EXPORT_SYMBOL_GPL(plda_pcie_setup_iomems);
--- a/drivers/pci/controller/plda/pcie-plda.h
+++ b/drivers/pci/controller/plda/pcie-plda.h
@@ -126,4 +126,9 @@ struct plda_pcie_rp {
void __iomem *bridge_addr;
};
+void plda_pcie_setup_window(void __iomem *bridge_base_addr, u32 index,
+ phys_addr_t axi_addr, phys_addr_t pci_addr,
+ size_t size);
+int plda_pcie_setup_iomems(struct pci_host_bridge *bridge,
+ struct plda_pcie_rp *port);
#endif

View File

@ -0,0 +1,336 @@
From 2a48bc45dcf8cbe736b594d013cfa9d682214c43 Mon Sep 17 00:00:00 2001
From: Minda Chen <minda.chen@starfivetech.com>
Date: Mon, 8 Jan 2024 19:06:00 +0800
Subject: [PATCH 023/116] PCI: microchip: Rename interrupt related functions
Rename mc_* to plda_* for IRQ functions and related IRQ domain ops data
instances.
MSI, INTx interrupt code and IRQ init code are all can be re-used.
Signed-off-by: Minda Chen <minda.chen@starfivetech.com>
Acked-by: Conor Dooley <conor.dooley@microchip.com>
---
.../pci/controller/plda/pcie-microchip-host.c | 109 +++++++++---------
1 file changed, 57 insertions(+), 52 deletions(-)
--- a/drivers/pci/controller/plda/pcie-microchip-host.c
+++ b/drivers/pci/controller/plda/pcie-microchip-host.c
@@ -318,7 +318,7 @@ static void mc_pcie_enable_msi(struct mc
ecam + MC_MSI_CAP_CTRL_OFFSET + PCI_MSI_ADDRESS_HI);
}
-static void mc_handle_msi(struct irq_desc *desc)
+static void plda_handle_msi(struct irq_desc *desc)
{
struct plda_pcie_rp *port = irq_desc_get_handler_data(desc);
struct irq_chip *chip = irq_desc_get_chip(desc);
@@ -346,7 +346,7 @@ static void mc_handle_msi(struct irq_des
chained_irq_exit(chip, desc);
}
-static void mc_msi_bottom_irq_ack(struct irq_data *data)
+static void plda_msi_bottom_irq_ack(struct irq_data *data)
{
struct plda_pcie_rp *port = irq_data_get_irq_chip_data(data);
void __iomem *bridge_base_addr = port->bridge_addr;
@@ -355,7 +355,7 @@ static void mc_msi_bottom_irq_ack(struct
writel_relaxed(BIT(bitpos), bridge_base_addr + ISTATUS_MSI);
}
-static void mc_compose_msi_msg(struct irq_data *data, struct msi_msg *msg)
+static void plda_compose_msi_msg(struct irq_data *data, struct msi_msg *msg)
{
struct plda_pcie_rp *port = irq_data_get_irq_chip_data(data);
phys_addr_t addr = port->msi.vector_phy;
@@ -368,21 +368,23 @@ static void mc_compose_msi_msg(struct ir
(int)data->hwirq, msg->address_hi, msg->address_lo);
}
-static int mc_msi_set_affinity(struct irq_data *irq_data,
- const struct cpumask *mask, bool force)
+static int plda_msi_set_affinity(struct irq_data *irq_data,
+ const struct cpumask *mask, bool force)
{
return -EINVAL;
}
-static struct irq_chip mc_msi_bottom_irq_chip = {
- .name = "Microchip MSI",
- .irq_ack = mc_msi_bottom_irq_ack,
- .irq_compose_msi_msg = mc_compose_msi_msg,
- .irq_set_affinity = mc_msi_set_affinity,
+static struct irq_chip plda_msi_bottom_irq_chip = {
+ .name = "PLDA MSI",
+ .irq_ack = plda_msi_bottom_irq_ack,
+ .irq_compose_msi_msg = plda_compose_msi_msg,
+ .irq_set_affinity = plda_msi_set_affinity,
};
-static int mc_irq_msi_domain_alloc(struct irq_domain *domain, unsigned int virq,
- unsigned int nr_irqs, void *args)
+static int plda_irq_msi_domain_alloc(struct irq_domain *domain,
+ unsigned int virq,
+ unsigned int nr_irqs,
+ void *args)
{
struct plda_pcie_rp *port = domain->host_data;
struct plda_msi *msi = &port->msi;
@@ -397,7 +399,7 @@ static int mc_irq_msi_domain_alloc(struc
set_bit(bit, msi->used);
- irq_domain_set_info(domain, virq, bit, &mc_msi_bottom_irq_chip,
+ irq_domain_set_info(domain, virq, bit, &plda_msi_bottom_irq_chip,
domain->host_data, handle_edge_irq, NULL, NULL);
mutex_unlock(&msi->lock);
@@ -405,8 +407,9 @@ static int mc_irq_msi_domain_alloc(struc
return 0;
}
-static void mc_irq_msi_domain_free(struct irq_domain *domain, unsigned int virq,
- unsigned int nr_irqs)
+static void plda_irq_msi_domain_free(struct irq_domain *domain,
+ unsigned int virq,
+ unsigned int nr_irqs)
{
struct irq_data *d = irq_domain_get_irq_data(domain, virq);
struct plda_pcie_rp *port = irq_data_get_irq_chip_data(d);
@@ -423,24 +426,24 @@ static void mc_irq_msi_domain_free(struc
}
static const struct irq_domain_ops msi_domain_ops = {
- .alloc = mc_irq_msi_domain_alloc,
- .free = mc_irq_msi_domain_free,
+ .alloc = plda_irq_msi_domain_alloc,
+ .free = plda_irq_msi_domain_free,
};
-static struct irq_chip mc_msi_irq_chip = {
- .name = "Microchip PCIe MSI",
+static struct irq_chip plda_msi_irq_chip = {
+ .name = "PLDA PCIe MSI",
.irq_ack = irq_chip_ack_parent,
.irq_mask = pci_msi_mask_irq,
.irq_unmask = pci_msi_unmask_irq,
};
-static struct msi_domain_info mc_msi_domain_info = {
+static struct msi_domain_info plda_msi_domain_info = {
.flags = (MSI_FLAG_USE_DEF_DOM_OPS | MSI_FLAG_USE_DEF_CHIP_OPS |
MSI_FLAG_PCI_MSIX),
- .chip = &mc_msi_irq_chip,
+ .chip = &plda_msi_irq_chip,
};
-static int mc_allocate_msi_domains(struct plda_pcie_rp *port)
+static int plda_allocate_msi_domains(struct plda_pcie_rp *port)
{
struct device *dev = port->dev;
struct fwnode_handle *fwnode = of_node_to_fwnode(dev->of_node);
@@ -455,7 +458,8 @@ static int mc_allocate_msi_domains(struc
return -ENOMEM;
}
- msi->msi_domain = pci_msi_create_irq_domain(fwnode, &mc_msi_domain_info,
+ msi->msi_domain = pci_msi_create_irq_domain(fwnode,
+ &plda_msi_domain_info,
msi->dev_domain);
if (!msi->msi_domain) {
dev_err(dev, "failed to create MSI domain\n");
@@ -466,7 +470,7 @@ static int mc_allocate_msi_domains(struc
return 0;
}
-static void mc_handle_intx(struct irq_desc *desc)
+static void plda_handle_intx(struct irq_desc *desc)
{
struct plda_pcie_rp *port = irq_desc_get_handler_data(desc);
struct irq_chip *chip = irq_desc_get_chip(desc);
@@ -493,7 +497,7 @@ static void mc_handle_intx(struct irq_de
chained_irq_exit(chip, desc);
}
-static void mc_ack_intx_irq(struct irq_data *data)
+static void plda_ack_intx_irq(struct irq_data *data)
{
struct plda_pcie_rp *port = irq_data_get_irq_chip_data(data);
void __iomem *bridge_base_addr = port->bridge_addr;
@@ -502,7 +506,7 @@ static void mc_ack_intx_irq(struct irq_d
writel_relaxed(mask, bridge_base_addr + ISTATUS_LOCAL);
}
-static void mc_mask_intx_irq(struct irq_data *data)
+static void plda_mask_intx_irq(struct irq_data *data)
{
struct plda_pcie_rp *port = irq_data_get_irq_chip_data(data);
void __iomem *bridge_base_addr = port->bridge_addr;
@@ -517,7 +521,7 @@ static void mc_mask_intx_irq(struct irq_
raw_spin_unlock_irqrestore(&port->lock, flags);
}
-static void mc_unmask_intx_irq(struct irq_data *data)
+static void plda_unmask_intx_irq(struct irq_data *data)
{
struct plda_pcie_rp *port = irq_data_get_irq_chip_data(data);
void __iomem *bridge_base_addr = port->bridge_addr;
@@ -532,24 +536,24 @@ static void mc_unmask_intx_irq(struct ir
raw_spin_unlock_irqrestore(&port->lock, flags);
}
-static struct irq_chip mc_intx_irq_chip = {
- .name = "Microchip PCIe INTx",
- .irq_ack = mc_ack_intx_irq,
- .irq_mask = mc_mask_intx_irq,
- .irq_unmask = mc_unmask_intx_irq,
+static struct irq_chip plda_intx_irq_chip = {
+ .name = "PLDA PCIe INTx",
+ .irq_ack = plda_ack_intx_irq,
+ .irq_mask = plda_mask_intx_irq,
+ .irq_unmask = plda_unmask_intx_irq,
};
-static int mc_pcie_intx_map(struct irq_domain *domain, unsigned int irq,
- irq_hw_number_t hwirq)
+static int plda_pcie_intx_map(struct irq_domain *domain, unsigned int irq,
+ irq_hw_number_t hwirq)
{
- irq_set_chip_and_handler(irq, &mc_intx_irq_chip, handle_level_irq);
+ irq_set_chip_and_handler(irq, &plda_intx_irq_chip, handle_level_irq);
irq_set_chip_data(irq, domain->host_data);
return 0;
}
static const struct irq_domain_ops intx_domain_ops = {
- .map = mc_pcie_intx_map,
+ .map = plda_pcie_intx_map,
};
static inline u32 reg_to_event(u32 reg, struct event_map field)
@@ -609,7 +613,7 @@ static u32 local_events(struct mc_pcie *
return val;
}
-static u32 get_events(struct plda_pcie_rp *port)
+static u32 mc_get_events(struct plda_pcie_rp *port)
{
struct mc_pcie *mc_port = container_of(port, struct mc_pcie, plda);
u32 events = 0;
@@ -638,7 +642,7 @@ static irqreturn_t mc_event_handler(int
return IRQ_HANDLED;
}
-static void mc_handle_event(struct irq_desc *desc)
+static void plda_handle_event(struct irq_desc *desc)
{
struct plda_pcie_rp *port = irq_desc_get_handler_data(desc);
unsigned long events;
@@ -647,7 +651,7 @@ static void mc_handle_event(struct irq_d
chained_irq_enter(chip, desc);
- events = get_events(port);
+ events = mc_get_events(port);
for_each_set_bit(bit, &events, NUM_EVENTS)
generic_handle_domain_irq(port->event_domain, bit);
@@ -741,8 +745,8 @@ static struct irq_chip mc_event_irq_chip
.irq_unmask = mc_unmask_event_irq,
};
-static int mc_pcie_event_map(struct irq_domain *domain, unsigned int irq,
- irq_hw_number_t hwirq)
+static int plda_pcie_event_map(struct irq_domain *domain, unsigned int irq,
+ irq_hw_number_t hwirq)
{
irq_set_chip_and_handler(irq, &mc_event_irq_chip, handle_level_irq);
irq_set_chip_data(irq, domain->host_data);
@@ -750,8 +754,8 @@ static int mc_pcie_event_map(struct irq_
return 0;
}
-static const struct irq_domain_ops event_domain_ops = {
- .map = mc_pcie_event_map,
+static const struct irq_domain_ops plda_event_domain_ops = {
+ .map = plda_pcie_event_map,
};
static inline void mc_pcie_deinit_clk(void *data)
@@ -799,7 +803,7 @@ static int mc_pcie_init_clks(struct devi
return 0;
}
-static int mc_pcie_init_irq_domains(struct plda_pcie_rp *port)
+static int plda_pcie_init_irq_domains(struct plda_pcie_rp *port)
{
struct device *dev = port->dev;
struct device_node *node = dev->of_node;
@@ -813,7 +817,8 @@ static int mc_pcie_init_irq_domains(stru
}
port->event_domain = irq_domain_add_linear(pcie_intc_node, NUM_EVENTS,
- &event_domain_ops, port);
+ &plda_event_domain_ops,
+ port);
if (!port->event_domain) {
dev_err(dev, "failed to get event domain\n");
of_node_put(pcie_intc_node);
@@ -835,7 +840,7 @@ static int mc_pcie_init_irq_domains(stru
of_node_put(pcie_intc_node);
raw_spin_lock_init(&port->lock);
- return mc_allocate_msi_domains(port);
+ return plda_allocate_msi_domains(port);
}
static inline void mc_clear_secs(struct mc_pcie *port)
@@ -898,14 +903,14 @@ static void mc_disable_interrupts(struct
writel_relaxed(GENMASK(31, 0), bridge_base_addr + ISTATUS_HOST);
}
-static int mc_init_interrupts(struct platform_device *pdev, struct plda_pcie_rp *port)
+static int plda_init_interrupts(struct platform_device *pdev, struct plda_pcie_rp *port)
{
struct device *dev = &pdev->dev;
int irq;
int i, intx_irq, msi_irq, event_irq;
int ret;
- ret = mc_pcie_init_irq_domains(port);
+ ret = plda_pcie_init_irq_domains(port);
if (ret) {
dev_err(dev, "failed creating IRQ domains\n");
return ret;
@@ -938,7 +943,7 @@ static int mc_init_interrupts(struct pla
}
/* Plug the INTx chained handler */
- irq_set_chained_handler_and_data(intx_irq, mc_handle_intx, port);
+ irq_set_chained_handler_and_data(intx_irq, plda_handle_intx, port);
msi_irq = irq_create_mapping(port->event_domain,
EVENT_LOCAL_PM_MSI_INT_MSI);
@@ -946,10 +951,10 @@ static int mc_init_interrupts(struct pla
return -ENXIO;
/* Plug the MSI chained handler */
- irq_set_chained_handler_and_data(msi_irq, mc_handle_msi, port);
+ irq_set_chained_handler_and_data(msi_irq, plda_handle_msi, port);
/* Plug the main event chained handler */
- irq_set_chained_handler_and_data(irq, mc_handle_event, port);
+ irq_set_chained_handler_and_data(irq, plda_handle_event, port);
return 0;
}
@@ -977,7 +982,7 @@ static int mc_platform_init(struct pci_c
return ret;
/* Address translation is up; safe to enable interrupts */
- ret = mc_init_interrupts(pdev, &port->plda);
+ ret = plda_init_interrupts(pdev, &port->plda);
if (ret)
return ret;

View File

@ -0,0 +1,65 @@
From ab04dadb45a4150c9fd55b97fdd7397f4739a629 Mon Sep 17 00:00:00 2001
From: Minda Chen <minda.chen@starfivetech.com>
Date: Mon, 8 Jan 2024 19:06:01 +0800
Subject: [PATCH 024/116] PCI: microchip: Add num_events field to struct
plda_pcie_rp
The number of events is different across platforms. In order to share
interrupt processing code, add a variable that defines the number of
events so that it can be set per-platform instead of hardcoding it.
Signed-off-by: Minda Chen <minda.chen@starfivetech.com>
Reviewed-by: Conor Dooley <conor.dooley@microchip.com>
---
drivers/pci/controller/plda/pcie-microchip-host.c | 8 +++++---
drivers/pci/controller/plda/pcie-plda.h | 1 +
2 files changed, 6 insertions(+), 3 deletions(-)
--- a/drivers/pci/controller/plda/pcie-microchip-host.c
+++ b/drivers/pci/controller/plda/pcie-microchip-host.c
@@ -653,7 +653,7 @@ static void plda_handle_event(struct irq
events = mc_get_events(port);
- for_each_set_bit(bit, &events, NUM_EVENTS)
+ for_each_set_bit(bit, &events, port->num_events)
generic_handle_domain_irq(port->event_domain, bit);
chained_irq_exit(chip, desc);
@@ -816,7 +816,8 @@ static int plda_pcie_init_irq_domains(st
return -EINVAL;
}
- port->event_domain = irq_domain_add_linear(pcie_intc_node, NUM_EVENTS,
+ port->event_domain = irq_domain_add_linear(pcie_intc_node,
+ port->num_events,
&plda_event_domain_ops,
port);
if (!port->event_domain) {
@@ -920,7 +921,7 @@ static int plda_init_interrupts(struct p
if (irq < 0)
return -ENODEV;
- for (i = 0; i < NUM_EVENTS; i++) {
+ for (i = 0; i < port->num_events; i++) {
event_irq = irq_create_mapping(port->event_domain, i);
if (!event_irq) {
dev_err(dev, "failed to map hwirq %d\n", i);
@@ -1012,6 +1013,7 @@ static int mc_host_probe(struct platform
bridge_base_addr = port->axi_base_addr + MC_PCIE_BRIDGE_ADDR;
plda->bridge_addr = bridge_base_addr;
+ plda->num_events = NUM_EVENTS;
/* Allow enabling MSI by disabling MSI-X */
val = readl(bridge_base_addr + PCIE_PCI_IRQ_DW0);
--- a/drivers/pci/controller/plda/pcie-plda.h
+++ b/drivers/pci/controller/plda/pcie-plda.h
@@ -124,6 +124,7 @@ struct plda_pcie_rp {
raw_spinlock_t lock;
struct plda_msi msi;
void __iomem *bridge_addr;
+ int num_events;
};
void plda_pcie_setup_window(void __iomem *bridge_base_addr, u32 index,

View File

@ -0,0 +1,114 @@
From 9f202f211cc79eefecbb03715c884e54eb95a62c Mon Sep 17 00:00:00 2001
From: Minda Chen <minda.chen@starfivetech.com>
Date: Mon, 8 Jan 2024 19:06:02 +0800
Subject: [PATCH 025/116] PCI: microchip: Add request_event_irq() callback
function
As PLDA dts binding doc(Documentation/devicetree/bindings/pci/
plda,xpressrich3-axi-common.yaml) showes, PLDA PCIe contains an interrupt
controller. Microchip Polarfire PCIe add some PCIe interrupts base on
PLDA IP interrupt controller.
Microchip Polarfire PCIe additional intrerrupts:
EVENT_PCIE_L2_EXIT
EVENT_PCIE_HOTRST_EXIT
EVENT_PCIE_DLUP_EXIT
EVENT_SEC_TX_RAM_SEC_ERR
EVENT_SEC_RX_RAM_SEC_ERR
....
Both codes of register interrupts and mc_event_handler() contain
additional interrupts symbol names, these can not be re-used. So add a
new plda_event_handler() functions, which implements PLDA interrupt
defalt handler. Add request_event_irq() callback function to
compat Microchip Polorfire PCIe additional interrupts.
Signed-off-by: Minda Chen <minda.chen@starfivetech.com>
Acked-by: Conor Dooley <conor.dooley@microchip.com>
---
.../pci/controller/plda/pcie-microchip-host.c | 31 ++++++++++++++++---
drivers/pci/controller/plda/pcie-plda.h | 5 +++
2 files changed, 32 insertions(+), 4 deletions(-)
--- a/drivers/pci/controller/plda/pcie-microchip-host.c
+++ b/drivers/pci/controller/plda/pcie-microchip-host.c
@@ -642,6 +642,11 @@ static irqreturn_t mc_event_handler(int
return IRQ_HANDLED;
}
+static irqreturn_t plda_event_handler(int irq, void *dev_id)
+{
+ return IRQ_HANDLED;
+}
+
static void plda_handle_event(struct irq_desc *desc)
{
struct plda_pcie_rp *port = irq_desc_get_handler_data(desc);
@@ -803,6 +808,17 @@ static int mc_pcie_init_clks(struct devi
return 0;
}
+static int mc_request_event_irq(struct plda_pcie_rp *plda, int event_irq,
+ int event)
+{
+ return devm_request_irq(plda->dev, event_irq, mc_event_handler,
+ 0, event_cause[event].sym, plda);
+}
+
+static const struct plda_event mc_event = {
+ .request_event_irq = mc_request_event_irq,
+};
+
static int plda_pcie_init_irq_domains(struct plda_pcie_rp *port)
{
struct device *dev = port->dev;
@@ -904,7 +920,9 @@ static void mc_disable_interrupts(struct
writel_relaxed(GENMASK(31, 0), bridge_base_addr + ISTATUS_HOST);
}
-static int plda_init_interrupts(struct platform_device *pdev, struct plda_pcie_rp *port)
+static int plda_init_interrupts(struct platform_device *pdev,
+ struct plda_pcie_rp *port,
+ const struct plda_event *event)
{
struct device *dev = &pdev->dev;
int irq;
@@ -928,8 +946,13 @@ static int plda_init_interrupts(struct p
return -ENXIO;
}
- ret = devm_request_irq(dev, event_irq, mc_event_handler,
- 0, event_cause[i].sym, port);
+ if (event->request_event_irq)
+ ret = event->request_event_irq(port, event_irq, i);
+ else
+ ret = devm_request_irq(dev, event_irq,
+ plda_event_handler,
+ 0, NULL, port);
+
if (ret) {
dev_err(dev, "failed to request IRQ %d\n", event_irq);
return ret;
@@ -983,7 +1006,7 @@ static int mc_platform_init(struct pci_c
return ret;
/* Address translation is up; safe to enable interrupts */
- ret = plda_init_interrupts(pdev, &port->plda);
+ ret = plda_init_interrupts(pdev, &port->plda, &mc_event);
if (ret)
return ret;
--- a/drivers/pci/controller/plda/pcie-plda.h
+++ b/drivers/pci/controller/plda/pcie-plda.h
@@ -127,6 +127,11 @@ struct plda_pcie_rp {
int num_events;
};
+struct plda_event {
+ int (*request_event_irq)(struct plda_pcie_rp *pcie,
+ int event_irq, int event);
+};
+
void plda_pcie_setup_window(void __iomem *bridge_base_addr, u32 index,
phys_addr_t axi_addr, phys_addr_t pci_addr,
size_t size);

View File

@ -0,0 +1,56 @@
From 3cdc20d9cc029ba9444be111bf4e55fd5331ccbe Mon Sep 17 00:00:00 2001
From: Minda Chen <minda.chen@starfivetech.com>
Date: Mon, 8 Jan 2024 19:06:03 +0800
Subject: [PATCH 026/116] PCI: microchip: Add INTx and MSI event num to struct
plda_event
The INTx and MSI interrupt event num is different in Microchip and
StarFive platform.
Signed-off-by: Minda Chen <minda.chen@starfivetech.com>
Acked-by: Conor Dooley <conor.dooley@microchip.com>
---
drivers/pci/controller/plda/pcie-microchip-host.c | 6 ++++--
drivers/pci/controller/plda/pcie-plda.h | 2 ++
2 files changed, 6 insertions(+), 2 deletions(-)
--- a/drivers/pci/controller/plda/pcie-microchip-host.c
+++ b/drivers/pci/controller/plda/pcie-microchip-host.c
@@ -817,6 +817,8 @@ static int mc_request_event_irq(struct p
static const struct plda_event mc_event = {
.request_event_irq = mc_request_event_irq,
+ .intx_event = EVENT_LOCAL_PM_MSI_INT_INTX,
+ .msi_event = EVENT_LOCAL_PM_MSI_INT_MSI,
};
static int plda_pcie_init_irq_domains(struct plda_pcie_rp *port)
@@ -960,7 +962,7 @@ static int plda_init_interrupts(struct p
}
intx_irq = irq_create_mapping(port->event_domain,
- EVENT_LOCAL_PM_MSI_INT_INTX);
+ event->intx_event);
if (!intx_irq) {
dev_err(dev, "failed to map INTx interrupt\n");
return -ENXIO;
@@ -970,7 +972,7 @@ static int plda_init_interrupts(struct p
irq_set_chained_handler_and_data(intx_irq, plda_handle_intx, port);
msi_irq = irq_create_mapping(port->event_domain,
- EVENT_LOCAL_PM_MSI_INT_MSI);
+ event->msi_event);
if (!msi_irq)
return -ENXIO;
--- a/drivers/pci/controller/plda/pcie-plda.h
+++ b/drivers/pci/controller/plda/pcie-plda.h
@@ -130,6 +130,8 @@ struct plda_pcie_rp {
struct plda_event {
int (*request_event_irq)(struct plda_pcie_rp *pcie,
int event_irq, int event);
+ int intx_event;
+ int msi_event;
};
void plda_pcie_setup_window(void __iomem *bridge_base_addr, u32 index,

View File

@ -0,0 +1,167 @@
From b4a38ef87661f21fe2fb3e085ae98f25f78aaf99 Mon Sep 17 00:00:00 2001
From: Minda Chen <minda.chen@starfivetech.com>
Date: Mon, 8 Jan 2024 19:06:04 +0800
Subject: [PATCH 027/116] PCI: microchip: Add get_events() callback and add
PLDA get_event()
As PLDA dts binding doc(Documentation/devicetree/bindings/pci/
plda,xpressrich3-axi-common.yaml) showes, PLDA PCIe contains an interrupt
controller.
PolarFire implements its own PCIe interrupts, additional to the regular
PCIe interrupts, due to lack of an MSI controller, so the interrupt to
event number mapping is different to the PLDA regular interrupts,
necessitating a custom get_events() implementation.
Microchip Polarfire PCIe additional intrerrupts:
EVENT_PCIE_L2_EXIT
EVENT_PCIE_HOTRST_EXIT
EVENT_PCIE_DLUP_EXIT
EVENT_SEC_TX_RAM_SEC_ERR
EVENT_SEC_RX_RAM_SEC_ERR
....
plda_get_events() adds interrupt register to PLDA local event num mapping
codes. All The PLDA interrupts can be seen in new added graph.
Signed-off-by: Minda Chen <minda.chen@starfivetech.com>
Acked-by: Conor Dooley <conor.dooley@microchip.com>
---
.../pci/controller/plda/pcie-microchip-host.c | 35 ++++++++++++++++++-
drivers/pci/controller/plda/pcie-plda.h | 32 +++++++++++++++++
2 files changed, 66 insertions(+), 1 deletion(-)
--- a/drivers/pci/controller/plda/pcie-microchip-host.c
+++ b/drivers/pci/controller/plda/pcie-microchip-host.c
@@ -626,6 +626,26 @@ static u32 mc_get_events(struct plda_pci
return events;
}
+static u32 plda_get_events(struct plda_pcie_rp *port)
+{
+ u32 events, val, origin;
+
+ origin = readl_relaxed(port->bridge_addr + ISTATUS_LOCAL);
+
+ /* MSI event and sys events */
+ val = (origin & SYS_AND_MSI_MASK) >> PM_MSI_INT_MSI_SHIFT;
+ events = val << (PM_MSI_INT_MSI_SHIFT - PCI_NUM_INTX + 1);
+
+ /* INTx events */
+ if (origin & PM_MSI_INT_INTX_MASK)
+ events |= BIT(PM_MSI_INT_INTX_SHIFT);
+
+ /* remains are same with register */
+ events |= origin & GENMASK(P_ATR_EVT_DOORBELL_SHIFT, 0);
+
+ return events;
+}
+
static irqreturn_t mc_event_handler(int irq, void *dev_id)
{
struct plda_pcie_rp *port = dev_id;
@@ -656,7 +676,7 @@ static void plda_handle_event(struct irq
chained_irq_enter(chip, desc);
- events = mc_get_events(port);
+ events = port->event_ops->get_events(port);
for_each_set_bit(bit, &events, port->num_events)
generic_handle_domain_irq(port->event_domain, bit);
@@ -750,6 +770,10 @@ static struct irq_chip mc_event_irq_chip
.irq_unmask = mc_unmask_event_irq,
};
+static const struct plda_event_ops plda_event_ops = {
+ .get_events = plda_get_events,
+};
+
static int plda_pcie_event_map(struct irq_domain *domain, unsigned int irq,
irq_hw_number_t hwirq)
{
@@ -815,6 +839,10 @@ static int mc_request_event_irq(struct p
0, event_cause[event].sym, plda);
}
+static const struct plda_event_ops mc_event_ops = {
+ .get_events = mc_get_events,
+};
+
static const struct plda_event mc_event = {
.request_event_irq = mc_request_event_irq,
.intx_event = EVENT_LOCAL_PM_MSI_INT_INTX,
@@ -931,6 +959,9 @@ static int plda_init_interrupts(struct p
int i, intx_irq, msi_irq, event_irq;
int ret;
+ if (!port->event_ops)
+ port->event_ops = &plda_event_ops;
+
ret = plda_pcie_init_irq_domains(port);
if (ret) {
dev_err(dev, "failed creating IRQ domains\n");
@@ -1007,6 +1038,8 @@ static int mc_platform_init(struct pci_c
if (ret)
return ret;
+ port->plda.event_ops = &mc_event_ops;
+
/* Address translation is up; safe to enable interrupts */
ret = plda_init_interrupts(pdev, &port->plda, &mc_event);
if (ret)
--- a/drivers/pci/controller/plda/pcie-plda.h
+++ b/drivers/pci/controller/plda/pcie-plda.h
@@ -58,6 +58,7 @@
#define PM_MSI_INT_EVENTS_SHIFT 30
#define PM_MSI_INT_SYS_ERR_MASK 0x80000000u
#define PM_MSI_INT_SYS_ERR_SHIFT 31
+#define SYS_AND_MSI_MASK GENMASK(31, 28)
#define NUM_LOCAL_EVENTS 15
#define ISTATUS_LOCAL 0x184
#define IMASK_HOST 0x188
@@ -108,6 +109,36 @@ enum plda_int_event {
#define PLDA_MAX_INT_NUM (PLDA_NUM_DMA_EVENTS + PLDA_INT_EVENT_NUM)
+/*
+ * PLDA interrupt register
+ *
+ * 31 27 23 15 7 0
+ * +--+--+--+-+------+-+-+-+-+-+-+-+-+-----------+-----------+
+ * |12|11|10|9| intx |7|6|5|4|3|2|1|0| DMA error | DMA end |
+ * +--+--+--+-+------+-+-+-+-+-+-+-+-+-----------+-----------+
+ * bit 0-7 DMA interrupt end : reserved for vendor implement
+ * bit 8-15 DMA error : reserved for vendor implement
+ * 0: AXI post error (PLDA_AXI_POST_ERR)
+ * 1: AXI fetch error (PLDA_AXI_FETCH_ERR)
+ * 2: AXI discard error (PLDA_AXI_DISCARD_ERR)
+ * 3: AXI doorbell (PLDA_PCIE_DOORBELL)
+ * 4: PCIe post error (PLDA_PCIE_POST_ERR)
+ * 5: PCIe fetch error (PLDA_PCIE_FETCH_ERR)
+ * 6: PCIe discard error (PLDA_PCIE_DISCARD_ERR)
+ * 7: PCIe doorbell (PLDA_PCIE_DOORBELL)
+ * 8: 4 INTx interruts (PLDA_INTX)
+ * 9: MSI interrupt (PLDA_MSI)
+ * 10: AER event (PLDA_AER_EVENT)
+ * 11: PM/LTR/Hotplug (PLDA_MISC_EVENTS)
+ * 12: System error (PLDA_SYS_ERR)
+ */
+
+struct plda_pcie_rp;
+
+struct plda_event_ops {
+ u32 (*get_events)(struct plda_pcie_rp *pcie);
+};
+
struct plda_msi {
struct mutex lock; /* Protect used bitmap */
struct irq_domain *msi_domain;
@@ -123,6 +154,7 @@ struct plda_pcie_rp {
struct irq_domain *event_domain;
raw_spinlock_t lock;
struct plda_msi msi;
+ const struct plda_event_ops *event_ops;
void __iomem *bridge_addr;
int num_events;
};

View File

@ -0,0 +1,144 @@
From 229ea8e7b674eb5c9bc4f70d43df1bd02a79862a Mon Sep 17 00:00:00 2001
From: Minda Chen <minda.chen@starfivetech.com>
Date: Mon, 8 Jan 2024 19:06:05 +0800
Subject: [PATCH 028/116] PCI: microchip: Add event irqchip field to host port
and add PLDA irqchip
As PLDA dts binding doc(Documentation/devicetree/bindings/pci/
plda,xpressrich3-axi-common.yaml) showes, PLDA PCIe contains an interrupt
controller.
Microchip PolarFire PCIE event IRQs includes PLDA interrupts and
Polarfire their own interrupts. The interrupt irqchip ops includes
ack/mask/unmask interrupt ops, which will write correct registers.
Microchip Polarfire PCIe additional interrupts require to write Polarfire
SoC self-defined registers. So Microchip PCIe event irqchip ops can not
be re-used.
To support PLDA its own event IRQ process, implements PLDA irqchip ops and
add event irqchip field to struct pcie_plda_rp.
Signed-off-by: Minda Chen <minda.chen@starfivetech.com>
Acked-by: Conor Dooley <conor.dooley@microchip.com>
---
.../pci/controller/plda/pcie-microchip-host.c | 66 ++++++++++++++++++-
drivers/pci/controller/plda/pcie-plda.h | 5 +-
2 files changed, 69 insertions(+), 2 deletions(-)
--- a/drivers/pci/controller/plda/pcie-microchip-host.c
+++ b/drivers/pci/controller/plda/pcie-microchip-host.c
@@ -770,6 +770,64 @@ static struct irq_chip mc_event_irq_chip
.irq_unmask = mc_unmask_event_irq,
};
+static u32 plda_hwirq_to_mask(int hwirq)
+{
+ u32 mask;
+
+ /* hwirq 23 - 0 are the same with register */
+ if (hwirq < EVENT_PM_MSI_INT_INTX)
+ mask = BIT(hwirq);
+ else if (hwirq == EVENT_PM_MSI_INT_INTX)
+ mask = PM_MSI_INT_INTX_MASK;
+ else
+ mask = BIT(hwirq + PCI_NUM_INTX - 1);
+
+ return mask;
+}
+
+static void plda_ack_event_irq(struct irq_data *data)
+{
+ struct plda_pcie_rp *port = irq_data_get_irq_chip_data(data);
+
+ writel_relaxed(plda_hwirq_to_mask(data->hwirq),
+ port->bridge_addr + ISTATUS_LOCAL);
+}
+
+static void plda_mask_event_irq(struct irq_data *data)
+{
+ struct plda_pcie_rp *port = irq_data_get_irq_chip_data(data);
+ u32 mask, val;
+
+ mask = plda_hwirq_to_mask(data->hwirq);
+
+ raw_spin_lock(&port->lock);
+ val = readl_relaxed(port->bridge_addr + IMASK_LOCAL);
+ val &= ~mask;
+ writel_relaxed(val, port->bridge_addr + IMASK_LOCAL);
+ raw_spin_unlock(&port->lock);
+}
+
+static void plda_unmask_event_irq(struct irq_data *data)
+{
+ struct plda_pcie_rp *port = irq_data_get_irq_chip_data(data);
+ u32 mask, val;
+
+ mask = plda_hwirq_to_mask(data->hwirq);
+
+ raw_spin_lock(&port->lock);
+ val = readl_relaxed(port->bridge_addr + IMASK_LOCAL);
+ val |= mask;
+ writel_relaxed(val, port->bridge_addr + IMASK_LOCAL);
+ raw_spin_unlock(&port->lock);
+}
+
+static struct irq_chip plda_event_irq_chip = {
+ .name = "PLDA PCIe EVENT",
+ .irq_ack = plda_ack_event_irq,
+ .irq_mask = plda_mask_event_irq,
+ .irq_unmask = plda_unmask_event_irq,
+};
+
static const struct plda_event_ops plda_event_ops = {
.get_events = plda_get_events,
};
@@ -777,7 +835,9 @@ static const struct plda_event_ops plda_
static int plda_pcie_event_map(struct irq_domain *domain, unsigned int irq,
irq_hw_number_t hwirq)
{
- irq_set_chip_and_handler(irq, &mc_event_irq_chip, handle_level_irq);
+ struct plda_pcie_rp *port = (void *)domain->host_data;
+
+ irq_set_chip_and_handler(irq, port->event_irq_chip, handle_level_irq);
irq_set_chip_data(irq, domain->host_data);
return 0;
@@ -962,6 +1022,9 @@ static int plda_init_interrupts(struct p
if (!port->event_ops)
port->event_ops = &plda_event_ops;
+ if (!port->event_irq_chip)
+ port->event_irq_chip = &plda_event_irq_chip;
+
ret = plda_pcie_init_irq_domains(port);
if (ret) {
dev_err(dev, "failed creating IRQ domains\n");
@@ -1039,6 +1102,7 @@ static int mc_platform_init(struct pci_c
return ret;
port->plda.event_ops = &mc_event_ops;
+ port->plda.event_irq_chip = &mc_event_irq_chip;
/* Address translation is up; safe to enable interrupts */
ret = plda_init_interrupts(pdev, &port->plda, &mc_event);
--- a/drivers/pci/controller/plda/pcie-plda.h
+++ b/drivers/pci/controller/plda/pcie-plda.h
@@ -107,7 +107,9 @@ enum plda_int_event {
#define PLDA_NUM_DMA_EVENTS 16
-#define PLDA_MAX_INT_NUM (PLDA_NUM_DMA_EVENTS + PLDA_INT_EVENT_NUM)
+#define EVENT_PM_MSI_INT_INTX (PLDA_NUM_DMA_EVENTS + PLDA_INTX)
+#define EVENT_PM_MSI_INT_MSI (PLDA_NUM_DMA_EVENTS + PLDA_MSI)
+#define PLDA_MAX_EVENT_NUM (PLDA_NUM_DMA_EVENTS + PLDA_INT_EVENT_NUM)
/*
* PLDA interrupt register
@@ -155,6 +157,7 @@ struct plda_pcie_rp {
raw_spinlock_t lock;
struct plda_msi msi;
const struct plda_event_ops *event_ops;
+ const struct irq_chip *event_irq_chip;
void __iomem *bridge_addr;
int num_events;
};

View File

@ -0,0 +1,67 @@
From 142fc300fd7511a217783dcfa342031d8ad70188 Mon Sep 17 00:00:00 2001
From: Minda Chen <minda.chen@starfivetech.com>
Date: Mon, 8 Jan 2024 19:06:07 +0800
Subject: [PATCH 030/116] pci: plda: Add event bitmap field to struct
plda_pcie_rp
For PLDA DMA interrupts are not all implemented. The non-implemented
interrupts should be masked. So add a bitmap field to mask the non-
implemented interrupts.
Signed-off-by: Minda Chen <minda.chen@starfivetech.com>
---
drivers/pci/controller/plda/pcie-microchip-host.c | 1 +
drivers/pci/controller/plda/pcie-plda-host.c | 6 ++++--
drivers/pci/controller/plda/pcie-plda.h | 1 +
3 files changed, 6 insertions(+), 2 deletions(-)
--- a/drivers/pci/controller/plda/pcie-microchip-host.c
+++ b/drivers/pci/controller/plda/pcie-microchip-host.c
@@ -636,6 +636,7 @@ static int mc_platform_init(struct pci_c
port->plda.event_ops = &mc_event_ops;
port->plda.event_irq_chip = &mc_event_irq_chip;
+ port->plda.events_bitmap = GENMASK(NUM_EVENTS - 1, 0);
/* Address translation is up; safe to enable interrupts */
ret = plda_init_interrupts(pdev, &port->plda, &mc_event);
--- a/drivers/pci/controller/plda/pcie-plda-host.c
+++ b/drivers/pci/controller/plda/pcie-plda-host.c
@@ -290,6 +290,7 @@ static void plda_handle_event(struct irq
events = port->event_ops->get_events(port);
+ events &= port->events_bitmap;
for_each_set_bit(bit, &events, port->num_events)
generic_handle_domain_irq(port->event_domain, bit);
@@ -420,8 +421,9 @@ int plda_init_interrupts(struct platform
{
struct device *dev = &pdev->dev;
int irq;
- int i, intx_irq, msi_irq, event_irq;
+ int intx_irq, msi_irq, event_irq;
int ret;
+ u32 i;
if (!port->event_ops)
port->event_ops = &plda_event_ops;
@@ -439,7 +441,7 @@ int plda_init_interrupts(struct platform
if (irq < 0)
return -ENODEV;
- for (i = 0; i < port->num_events; i++) {
+ for_each_set_bit(i, &port->events_bitmap, port->num_events) {
event_irq = irq_create_mapping(port->event_domain, i);
if (!event_irq) {
dev_err(dev, "failed to map hwirq %d\n", i);
--- a/drivers/pci/controller/plda/pcie-plda.h
+++ b/drivers/pci/controller/plda/pcie-plda.h
@@ -159,6 +159,7 @@ struct plda_pcie_rp {
const struct plda_event_ops *event_ops;
const struct irq_chip *event_irq_chip;
void __iomem *bridge_addr;
+ unsigned long events_bitmap;
int num_events;
};

View File

@ -0,0 +1,256 @@
From 3b9991438094dc472dacb4555603bdc379653411 Mon Sep 17 00:00:00 2001
From: Minda Chen <minda.chen@starfivetech.com>
Date: Mon, 8 Jan 2024 19:06:08 +0800
Subject: [PATCH 031/116] PCI: plda: Add host init/deinit and map bus functions
Add PLDA host plda_pcie_host_init()/plda_pcie_host_deinit() and map bus
function. So vendor can use it to init PLDA PCIe host core.
Signed-off-by: Minda Chen <minda.chen@starfivetech.com>
Reviewed-by: Mason Huo <mason.huo@starfivetech.com>
---
drivers/pci/controller/plda/pcie-plda-host.c | 131 +++++++++++++++++--
drivers/pci/controller/plda/pcie-plda.h | 22 ++++
2 files changed, 139 insertions(+), 14 deletions(-)
--- a/drivers/pci/controller/plda/pcie-plda-host.c
+++ b/drivers/pci/controller/plda/pcie-plda-host.c
@@ -3,6 +3,7 @@
* PLDA PCIe XpressRich host controller driver
*
* Copyright (C) 2023 Microchip Co. Ltd
+ * StarFive Co. Ltd
*
* Author: Daire McNamara <daire.mcnamara@microchip.com>
*/
@@ -15,6 +16,15 @@
#include "pcie-plda.h"
+void __iomem *plda_pcie_map_bus(struct pci_bus *bus, unsigned int devfn,
+ int where)
+{
+ struct plda_pcie_rp *pcie = bus->sysdata;
+
+ return pcie->config_base + PCIE_ECAM_OFFSET(bus->number, devfn, where);
+}
+EXPORT_SYMBOL_GPL(plda_pcie_map_bus);
+
static void plda_handle_msi(struct irq_desc *desc)
{
struct plda_pcie_rp *port = irq_desc_get_handler_data(desc);
@@ -420,9 +430,7 @@ int plda_init_interrupts(struct platform
const struct plda_event *event)
{
struct device *dev = &pdev->dev;
- int irq;
- int intx_irq, msi_irq, event_irq;
- int ret;
+ int event_irq, ret;
u32 i;
if (!port->event_ops)
@@ -437,8 +445,8 @@ int plda_init_interrupts(struct platform
return ret;
}
- irq = platform_get_irq(pdev, 0);
- if (irq < 0)
+ port->irq = platform_get_irq(pdev, 0);
+ if (port->irq < 0)
return -ENODEV;
for_each_set_bit(i, &port->events_bitmap, port->num_events) {
@@ -461,26 +469,26 @@ int plda_init_interrupts(struct platform
}
}
- intx_irq = irq_create_mapping(port->event_domain,
- event->intx_event);
- if (!intx_irq) {
+ port->intx_irq = irq_create_mapping(port->event_domain,
+ event->intx_event);
+ if (!port->intx_irq) {
dev_err(dev, "failed to map INTx interrupt\n");
return -ENXIO;
}
/* Plug the INTx chained handler */
- irq_set_chained_handler_and_data(intx_irq, plda_handle_intx, port);
+ irq_set_chained_handler_and_data(port->intx_irq, plda_handle_intx, port);
- msi_irq = irq_create_mapping(port->event_domain,
- event->msi_event);
- if (!msi_irq)
+ port->msi_irq = irq_create_mapping(port->event_domain,
+ event->msi_event);
+ if (!port->msi_irq)
return -ENXIO;
/* Plug the MSI chained handler */
- irq_set_chained_handler_and_data(msi_irq, plda_handle_msi, port);
+ irq_set_chained_handler_and_data(port->msi_irq, plda_handle_msi, port);
/* Plug the main event chained handler */
- irq_set_chained_handler_and_data(irq, plda_handle_event, port);
+ irq_set_chained_handler_and_data(port->irq, plda_handle_event, port);
return 0;
}
@@ -546,3 +554,98 @@ int plda_pcie_setup_iomems(struct pci_ho
return 0;
}
EXPORT_SYMBOL_GPL(plda_pcie_setup_iomems);
+
+static void plda_pcie_irq_domain_deinit(struct plda_pcie_rp *pcie)
+{
+ irq_set_chained_handler_and_data(pcie->irq, NULL, NULL);
+ irq_set_chained_handler_and_data(pcie->msi_irq, NULL, NULL);
+ irq_set_chained_handler_and_data(pcie->intx_irq, NULL, NULL);
+
+ irq_domain_remove(pcie->msi.msi_domain);
+ irq_domain_remove(pcie->msi.dev_domain);
+
+ irq_domain_remove(pcie->intx_domain);
+ irq_domain_remove(pcie->event_domain);
+}
+
+int plda_pcie_host_init(struct plda_pcie_rp *port, struct pci_ops *ops,
+ const struct plda_event *plda_event)
+{
+ struct device *dev = port->dev;
+ struct pci_host_bridge *bridge;
+ struct platform_device *pdev = to_platform_device(dev);
+ struct resource *cfg_res;
+ int ret;
+
+ pdev = to_platform_device(dev);
+
+ port->bridge_addr =
+ devm_platform_ioremap_resource_byname(pdev, "apb");
+
+ if (IS_ERR(port->bridge_addr))
+ return dev_err_probe(dev, PTR_ERR(port->bridge_addr),
+ "failed to map reg memory\n");
+
+ cfg_res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "cfg");
+ if (!cfg_res)
+ return dev_err_probe(dev, -ENODEV,
+ "failed to get config memory\n");
+
+ port->config_base = devm_ioremap_resource(dev, cfg_res);
+ if (IS_ERR(port->config_base))
+ return dev_err_probe(dev, PTR_ERR(port->config_base),
+ "failed to map config memory\n");
+
+ bridge = devm_pci_alloc_host_bridge(dev, 0);
+ if (!bridge)
+ return dev_err_probe(dev, -ENOMEM,
+ "failed to alloc bridge\n");
+
+ if (port->host_ops && port->host_ops->host_init) {
+ ret = port->host_ops->host_init(port);
+ if (ret)
+ return ret;
+ }
+
+ port->bridge = bridge;
+ plda_pcie_setup_window(port->bridge_addr, 0, cfg_res->start, 0,
+ resource_size(cfg_res));
+ plda_pcie_setup_iomems(bridge, port);
+ plda_set_default_msi(&port->msi);
+ ret = plda_init_interrupts(pdev, port, plda_event);
+ if (ret)
+ goto err_host;
+
+ /* Set default bus ops */
+ bridge->ops = ops;
+ bridge->sysdata = port;
+
+ ret = pci_host_probe(bridge);
+ if (ret < 0) {
+ dev_err_probe(dev, ret, "failed to probe pci host\n");
+ goto err_probe;
+ }
+
+ return ret;
+
+err_probe:
+ plda_pcie_irq_domain_deinit(port);
+err_host:
+ if (port->host_ops && port->host_ops->host_deinit)
+ port->host_ops->host_deinit(port);
+
+ return ret;
+}
+EXPORT_SYMBOL_GPL(plda_pcie_host_init);
+
+void plda_pcie_host_deinit(struct plda_pcie_rp *port)
+{
+ pci_stop_root_bus(port->bridge->bus);
+ pci_remove_root_bus(port->bridge->bus);
+
+ plda_pcie_irq_domain_deinit(port);
+
+ if (port->host_ops && port->host_ops->host_deinit)
+ port->host_ops->host_deinit(port);
+}
+EXPORT_SYMBOL_GPL(plda_pcie_host_deinit);
--- a/drivers/pci/controller/plda/pcie-plda.h
+++ b/drivers/pci/controller/plda/pcie-plda.h
@@ -141,6 +141,11 @@ struct plda_event_ops {
u32 (*get_events)(struct plda_pcie_rp *pcie);
};
+struct plda_pcie_host_ops {
+ int (*host_init)(struct plda_pcie_rp *pcie);
+ void (*host_deinit)(struct plda_pcie_rp *pcie);
+};
+
struct plda_msi {
struct mutex lock; /* Protect used bitmap */
struct irq_domain *msi_domain;
@@ -152,14 +157,20 @@ struct plda_msi {
struct plda_pcie_rp {
struct device *dev;
+ struct pci_host_bridge *bridge;
struct irq_domain *intx_domain;
struct irq_domain *event_domain;
raw_spinlock_t lock;
struct plda_msi msi;
const struct plda_event_ops *event_ops;
const struct irq_chip *event_irq_chip;
+ const struct plda_pcie_host_ops *host_ops;
void __iomem *bridge_addr;
+ void __iomem *config_base;
unsigned long events_bitmap;
+ int irq;
+ int msi_irq;
+ int intx_irq;
int num_events;
};
@@ -170,6 +181,8 @@ struct plda_event {
int msi_event;
};
+void __iomem *plda_pcie_map_bus(struct pci_bus *bus, unsigned int devfn,
+ int where);
int plda_init_interrupts(struct platform_device *pdev,
struct plda_pcie_rp *port,
const struct plda_event *event);
@@ -178,4 +191,13 @@ void plda_pcie_setup_window(void __iomem
size_t size);
int plda_pcie_setup_iomems(struct pci_host_bridge *bridge,
struct plda_pcie_rp *port);
+int plda_pcie_host_init(struct plda_pcie_rp *port, struct pci_ops *ops,
+ const struct plda_event *plda_event);
+void plda_pcie_host_deinit(struct plda_pcie_rp *pcie);
+
+static inline void plda_set_default_msi(struct plda_msi *msi)
+{
+ msi->vector_phy = IMSI_ADDR;
+ msi->num_vectors = PLDA_MAX_NUM_MSI_IRQS;
+}
#endif

View File

@ -0,0 +1,140 @@
From bc3f8207d9f0af3cb96a7eae232074a644a175f6 Mon Sep 17 00:00:00 2001
From: Minda Chen <minda.chen@starfivetech.com>
Date: Mon, 8 Jan 2024 19:06:09 +0800
Subject: [PATCH 032/116] dt-bindings: PCI: Add StarFive JH7110 PCIe controller
Add StarFive JH7110 SoC PCIe controller dt-bindings. JH7110 using PLDA
XpressRICH PCIe host controller IP.
Signed-off-by: Minda Chen <minda.chen@starfivetech.com>
Reviewed-by: Hal Feng <hal.feng@starfivetech.com>
Reviewed-by: Conor Dooley <conor.dooley@microchip.com>
Reviewed-by: Rob Herring <robh@kernel.org>
---
.../bindings/pci/starfive,jh7110-pcie.yaml | 120 ++++++++++++++++++
1 file changed, 120 insertions(+)
create mode 100644 Documentation/devicetree/bindings/pci/starfive,jh7110-pcie.yaml
--- /dev/null
+++ b/Documentation/devicetree/bindings/pci/starfive,jh7110-pcie.yaml
@@ -0,0 +1,120 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/pci/starfive,jh7110-pcie.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: StarFive JH7110 PCIe host controller
+
+maintainers:
+ - Kevin Xie <kevin.xie@starfivetech.com>
+
+allOf:
+ - $ref: plda,xpressrich3-axi-common.yaml#
+
+properties:
+ compatible:
+ const: starfive,jh7110-pcie
+
+ clocks:
+ items:
+ - description: NOC bus clock
+ - description: Transport layer clock
+ - description: AXI MST0 clock
+ - description: APB clock
+
+ clock-names:
+ items:
+ - const: noc
+ - const: tl
+ - const: axi_mst0
+ - const: apb
+
+ resets:
+ items:
+ - description: AXI MST0 reset
+ - description: AXI SLAVE0 reset
+ - description: AXI SLAVE reset
+ - description: PCIE BRIDGE reset
+ - description: PCIE CORE reset
+ - description: PCIE APB reset
+
+ reset-names:
+ items:
+ - const: mst0
+ - const: slv0
+ - const: slv
+ - const: brg
+ - const: core
+ - const: apb
+
+ starfive,stg-syscon:
+ $ref: /schemas/types.yaml#/definitions/phandle-array
+ description:
+ The phandle to System Register Controller syscon node.
+
+ perst-gpios:
+ description: GPIO controlled connection to PERST# signal
+ maxItems: 1
+
+ phys:
+ description:
+ Specified PHY is attached to PCIe controller.
+ maxItems: 1
+
+required:
+ - clocks
+ - resets
+ - starfive,stg-syscon
+
+unevaluatedProperties: false
+
+examples:
+ - |
+ #include <dt-bindings/gpio/gpio.h>
+ soc {
+ #address-cells = <2>;
+ #size-cells = <2>;
+
+ pcie@940000000 {
+ compatible = "starfive,jh7110-pcie";
+ reg = <0x9 0x40000000 0x0 0x10000000>,
+ <0x0 0x2b000000 0x0 0x1000000>;
+ reg-names = "cfg", "apb";
+ #address-cells = <3>;
+ #size-cells = <2>;
+ #interrupt-cells = <1>;
+ device_type = "pci";
+ ranges = <0x82000000 0x0 0x30000000 0x0 0x30000000 0x0 0x08000000>,
+ <0xc3000000 0x9 0x00000000 0x9 0x00000000 0x0 0x40000000>;
+ starfive,stg-syscon = <&stg_syscon>;
+ bus-range = <0x0 0xff>;
+ interrupt-parent = <&plic>;
+ interrupts = <56>;
+ interrupt-map-mask = <0x0 0x0 0x0 0x7>;
+ interrupt-map = <0x0 0x0 0x0 0x1 &pcie_intc0 0x1>,
+ <0x0 0x0 0x0 0x2 &pcie_intc0 0x2>,
+ <0x0 0x0 0x0 0x3 &pcie_intc0 0x3>,
+ <0x0 0x0 0x0 0x4 &pcie_intc0 0x4>;
+ msi-controller;
+ clocks = <&syscrg 86>,
+ <&stgcrg 10>,
+ <&stgcrg 8>,
+ <&stgcrg 9>;
+ clock-names = "noc", "tl", "axi_mst0", "apb";
+ resets = <&stgcrg 11>,
+ <&stgcrg 12>,
+ <&stgcrg 13>,
+ <&stgcrg 14>,
+ <&stgcrg 15>,
+ <&stgcrg 16>;
+ perst-gpios = <&gpios 26 GPIO_ACTIVE_LOW>;
+ phys = <&pciephy0>;
+
+ pcie_intc0: interrupt-controller {
+ #address-cells = <0>;
+ #interrupt-cells = <1>;
+ interrupt-controller;
+ };
+ };
+ };

View File

@ -0,0 +1,55 @@
From abb20b7b8f5e3a7f36dbd6264e6d346275434154 Mon Sep 17 00:00:00 2001
From: Kevin Xie <kevin.xie@starfivetech.com>
Date: Mon, 8 Jan 2024 19:06:10 +0800
Subject: [PATCH 033/116] PCI: Add PCIE_RESET_CONFIG_DEVICE_WAIT_MS waiting
time value
Add the PCIE_RESET_CONFIG_DEVICE_WAIT_MS macro to define the minimum
waiting time between exit from a conventional reset and sending the
first configuration request to the device.
As described in PCI base specification r6.0, section 6.6.1 <Conventional
Reset>, there are two different use cases of the value:
- "With a Downstream Port that does not support Link speeds greater
than 5.0 GT/s, software must wait a minimum of 100 ms following exit
from a Conventional Reset before sending a Configuration Request to
the device immediately below that Port."
- "With a Downstream Port that supports Link speeds greater than
5.0 GT/s, software must wait a minimum of 100 ms after Link training
completes before sending a Configuration Request to the device
immediately below that Port."
Signed-off-by: Kevin Xie <kevin.xie@starfivetech.com>
Reviewed-by: Mason Huo <mason.huo@starfivetech.com>
Acked-by: Bjorn Helgaas <bhelgaas@google.com>
---
drivers/pci/pci.h | 16 ++++++++++++++++
1 file changed, 16 insertions(+)
--- a/drivers/pci/pci.h
+++ b/drivers/pci/pci.h
@@ -19,6 +19,22 @@
*/
#define PCIE_PME_TO_L2_TIMEOUT_US 10000
+/*
+ * As described in PCI base specification r6.0, section 6.6.1 <Conventional
+ * Reset>, there are two different use cases of the value:
+ *
+ * - "With a Downstream Port that does not support Link speeds greater
+ * than 5.0 GT/s, software must wait a minimum of 100 ms following exit
+ * from a Conventional Reset before sending a Configuration Request to
+ * the device immediately below that Port."
+ *
+ * - "With a Downstream Port that supports Link speeds greater than
+ * 5.0 GT/s, software must wait a minimum of 100 ms after Link training
+ * completes before sending a Configuration Request to the device
+ * immediately below that Port."
+ */
+#define PCIE_RESET_CONFIG_DEVICE_WAIT_MS 100
+
extern const unsigned char pcie_link_speed[];
extern bool pci_early_dump;

View File

@ -0,0 +1,623 @@
From 323aedef34315b758dc30ba23e2cabca259bb4b2 Mon Sep 17 00:00:00 2001
From: Minda Chen <minda.chen@starfivetech.com>
Date: Mon, 8 Jan 2024 19:06:11 +0800
Subject: [PATCH 034/116] PCI: starfive: Add JH7110 PCIe controller
Add StarFive JH7110 SoC PCIe controller platform driver codes, JH7110
with PLDA host PCIe core.
Signed-off-by: Minda Chen <minda.chen@starfivetech.com>
Co-developed-by: Kevin Xie <kevin.xie@starfivetech.com>
Reviewed-by: Mason Huo <mason.huo@starfivetech.com>
---
drivers/pci/controller/plda/Kconfig | 12 +
drivers/pci/controller/plda/Makefile | 1 +
drivers/pci/controller/plda/pcie-plda.h | 71 ++-
drivers/pci/controller/plda/pcie-starfive.c | 473 ++++++++++++++++++++
4 files changed, 556 insertions(+), 1 deletion(-)
create mode 100644 drivers/pci/controller/plda/pcie-starfive.c
--- a/drivers/pci/controller/plda/Kconfig
+++ b/drivers/pci/controller/plda/Kconfig
@@ -15,4 +15,16 @@ config PCIE_MICROCHIP_HOST
Say Y here if you want kernel to support the Microchip AXI PCIe
Host Bridge driver.
+config PCIE_STARFIVE_HOST
+ tristate "StarFive PCIe host controller"
+ depends on PCI_MSI && OF
+ depends on ARCH_STARFIVE || COMPILE_TEST
+ select PCIE_PLDA_HOST
+ help
+ Say Y here if you want to support the StarFive PCIe controller in
+ host mode. StarFive PCIe controller uses PLDA PCIe core.
+
+ If you choose to build this driver as module it will be dynamically
+ linked and module will be called pcie-starfive.ko.
+
endmenu
--- a/drivers/pci/controller/plda/Makefile
+++ b/drivers/pci/controller/plda/Makefile
@@ -1,3 +1,4 @@
# SPDX-License-Identifier: GPL-2.0
obj-$(CONFIG_PCIE_PLDA_HOST) += pcie-plda-host.o
obj-$(CONFIG_PCIE_MICROCHIP_HOST) += pcie-microchip-host.o
+obj-$(CONFIG_PCIE_STARFIVE_HOST) += pcie-starfive.o
--- a/drivers/pci/controller/plda/pcie-plda.h
+++ b/drivers/pci/controller/plda/pcie-plda.h
@@ -10,10 +10,20 @@
#define PLDA_MAX_NUM_MSI_IRQS 32
/* PCIe Bridge Phy Regs */
+#define GEN_SETTINGS 0x80
+#define RP_ENABLE 1
+#define PCIE_PCI_IDS_DW1 0x9c
+#define IDS_CLASS_CODE_SHIFT 16
+#define REVISION_ID_MASK GENMASK(7, 0)
+#define CLASS_CODE_ID_MASK GENMASK(31, 8)
#define PCIE_PCI_IRQ_DW0 0xa8
#define MSIX_CAP_MASK BIT(31)
#define NUM_MSI_MSGS_MASK GENMASK(6, 4)
#define NUM_MSI_MSGS_SHIFT 4
+#define PCI_MISC 0xb4
+#define PHY_FUNCTION_DIS BIT(15)
+#define PCIE_WINROM 0xfc
+#define PREF_MEM_WIN_64_SUPPORT BIT(3)
#define IMASK_LOCAL 0x180
#define DMA_END_ENGINE_0_MASK 0x00000000u
@@ -65,6 +75,8 @@
#define ISTATUS_HOST 0x18c
#define IMSI_ADDR 0x190
#define ISTATUS_MSI 0x194
+#define PMSG_SUPPORT_RX 0x3f0
+#define PMSG_LTR_SUPPORT BIT(2)
/* PCIe Master table init defines */
#define ATR0_PCIE_WIN0_SRCADDR_PARAM 0x600u
@@ -86,6 +98,8 @@
#define PCIE_TX_RX_INTERFACE 0x00000000u
#define PCIE_CONFIG_INTERFACE 0x00000001u
+#define CONFIG_SPACE_ADDR_OFFSET 0x1000u
+
#define ATR_ENTRY_SIZE 32
enum plda_int_event {
@@ -200,4 +214,59 @@ static inline void plda_set_default_msi(
msi->vector_phy = IMSI_ADDR;
msi->num_vectors = PLDA_MAX_NUM_MSI_IRQS;
}
-#endif
+
+static inline void plda_pcie_enable_root_port(struct plda_pcie_rp *plda)
+{
+ u32 value;
+
+ value = readl_relaxed(plda->bridge_addr + GEN_SETTINGS);
+ value |= RP_ENABLE;
+ writel_relaxed(value, plda->bridge_addr + GEN_SETTINGS);
+}
+
+static inline void plda_pcie_set_standard_class(struct plda_pcie_rp *plda)
+{
+ u32 value;
+
+ /* set class code and reserve revision id */
+ value = readl_relaxed(plda->bridge_addr + PCIE_PCI_IDS_DW1);
+ value &= REVISION_ID_MASK;
+ value |= (PCI_CLASS_BRIDGE_PCI << IDS_CLASS_CODE_SHIFT);
+ writel_relaxed(value, plda->bridge_addr + PCIE_PCI_IDS_DW1);
+}
+
+static inline void plda_pcie_set_pref_win_64bit(struct plda_pcie_rp *plda)
+{
+ u32 value;
+
+ value = readl_relaxed(plda->bridge_addr + PCIE_WINROM);
+ value |= PREF_MEM_WIN_64_SUPPORT;
+ writel_relaxed(value, plda->bridge_addr + PCIE_WINROM);
+}
+
+static inline void plda_pcie_disable_ltr(struct plda_pcie_rp *plda)
+{
+ u32 value;
+
+ value = readl_relaxed(plda->bridge_addr + PMSG_SUPPORT_RX);
+ value &= ~PMSG_LTR_SUPPORT;
+ writel_relaxed(value, plda->bridge_addr + PMSG_SUPPORT_RX);
+}
+
+static inline void plda_pcie_disable_func(struct plda_pcie_rp *plda)
+{
+ u32 value;
+
+ value = readl_relaxed(plda->bridge_addr + PCI_MISC);
+ value |= PHY_FUNCTION_DIS;
+ writel_relaxed(value, plda->bridge_addr + PCI_MISC);
+}
+
+static inline void plda_pcie_write_rc_bar(struct plda_pcie_rp *plda, u64 val)
+{
+ void __iomem *addr = plda->bridge_addr + CONFIG_SPACE_ADDR_OFFSET;
+
+ writel_relaxed(lower_32_bits(val), addr + PCI_BASE_ADDRESS_0);
+ writel_relaxed(upper_32_bits(val), addr + PCI_BASE_ADDRESS_1);
+}
+#endif /* _PCIE_PLDA_H */
--- /dev/null
+++ b/drivers/pci/controller/plda/pcie-starfive.c
@@ -0,0 +1,473 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * PCIe host controller driver for StarFive JH7110 Soc.
+ *
+ * Copyright (C) 2023 StarFive Technology Co., Ltd.
+ */
+
+#include <linux/bitfield.h>
+#include <linux/clk.h>
+#include <linux/delay.h>
+#include <linux/gpio/consumer.h>
+#include <linux/interrupt.h>
+#include <linux/kernel.h>
+#include <linux/mfd/syscon.h>
+#include <linux/module.h>
+#include <linux/of_address.h>
+#include <linux/of_irq.h>
+#include <linux/of_pci.h>
+#include <linux/pci.h>
+#include <linux/phy/phy.h>
+#include <linux/platform_device.h>
+#include <linux/pm_runtime.h>
+#include <linux/regmap.h>
+#include <linux/reset.h>
+#include "../../pci.h"
+
+#include "pcie-plda.h"
+
+#define PCIE_FUNC_NUM 4
+
+/* system control */
+#define STG_SYSCON_PCIE0_BASE 0x48
+#define STG_SYSCON_PCIE1_BASE 0x1f8
+
+#define STG_SYSCON_AR_OFFSET 0x78
+#define STG_SYSCON_AXI4_SLVL_AR_MASK GENMASK(22, 8)
+#define STG_SYSCON_AXI4_SLVL_PHY_AR(x) FIELD_PREP(GENMASK(20, 17), x)
+#define STG_SYSCON_AW_OFFSET 0x7c
+#define STG_SYSCON_AXI4_SLVL_AW_MASK GENMASK(14, 0)
+#define STG_SYSCON_AXI4_SLVL_PHY_AW(x) FIELD_PREP(GENMASK(12, 9), x)
+#define STG_SYSCON_CLKREQ BIT(22)
+#define STG_SYSCON_CKREF_SRC_MASK GENMASK(19, 18)
+#define STG_SYSCON_RP_NEP_OFFSET 0xe8
+#define STG_SYSCON_K_RP_NEP BIT(8)
+#define STG_SYSCON_LNKSTA_OFFSET 0x170
+#define DATA_LINK_ACTIVE BIT(5)
+
+/* Parameters for the waiting for link up routine */
+#define LINK_WAIT_MAX_RETRIES 10
+#define LINK_WAIT_USLEEP_MIN 90000
+#define LINK_WAIT_USLEEP_MAX 100000
+
+struct starfive_jh7110_pcie {
+ struct plda_pcie_rp plda;
+ struct reset_control *resets;
+ struct clk_bulk_data *clks;
+ struct regmap *reg_syscon;
+ struct gpio_desc *power_gpio;
+ struct gpio_desc *reset_gpio;
+ struct phy *phy;
+
+ unsigned int stg_pcie_base;
+ int num_clks;
+};
+
+/*
+ * The BAR0/1 of bridge should be hidden during enumeration to
+ * avoid the sizing and resource allocation by PCIe core.
+ */
+static bool starfive_pcie_hide_rc_bar(struct pci_bus *bus, unsigned int devfn,
+ int offset)
+{
+ if (pci_is_root_bus(bus) && !devfn &&
+ (offset == PCI_BASE_ADDRESS_0 || offset == PCI_BASE_ADDRESS_1))
+ return true;
+
+ return false;
+}
+
+static int starfive_pcie_config_write(struct pci_bus *bus, unsigned int devfn,
+ int where, int size, u32 value)
+{
+ if (starfive_pcie_hide_rc_bar(bus, devfn, where))
+ return PCIBIOS_SUCCESSFUL;
+
+ return pci_generic_config_write(bus, devfn, where, size, value);
+}
+
+static int starfive_pcie_config_read(struct pci_bus *bus, unsigned int devfn,
+ int where, int size, u32 *value)
+{
+ if (starfive_pcie_hide_rc_bar(bus, devfn, where)) {
+ *value = 0;
+ return PCIBIOS_SUCCESSFUL;
+ }
+
+ return pci_generic_config_read(bus, devfn, where, size, value);
+}
+
+static int starfive_pcie_parse_dt(struct starfive_jh7110_pcie *pcie,
+ struct device *dev)
+{
+ int domain_nr;
+
+ pcie->num_clks = devm_clk_bulk_get_all(dev, &pcie->clks);
+ if (pcie->num_clks < 0)
+ return dev_err_probe(dev, pcie->num_clks,
+ "failed to get pcie clocks\n");
+
+ pcie->resets = devm_reset_control_array_get_exclusive(dev);
+ if (IS_ERR(pcie->resets))
+ return dev_err_probe(dev, PTR_ERR(pcie->resets),
+ "failed to get pcie resets");
+
+ pcie->reg_syscon =
+ syscon_regmap_lookup_by_phandle(dev->of_node,
+ "starfive,stg-syscon");
+
+ if (IS_ERR(pcie->reg_syscon))
+ return dev_err_probe(dev, PTR_ERR(pcie->reg_syscon),
+ "failed to parse starfive,stg-syscon\n");
+
+ pcie->phy = devm_phy_optional_get(dev, NULL);
+ if (IS_ERR(pcie->phy))
+ return dev_err_probe(dev, PTR_ERR(pcie->phy),
+ "failed to get pcie phy\n");
+
+ domain_nr = of_get_pci_domain_nr(dev->of_node);
+
+ if (domain_nr < 0 || domain_nr > 1)
+ return dev_err_probe(dev, -ENODEV,
+ "failed to get valid pcie domain\n");
+
+ if (domain_nr == 0)
+ pcie->stg_pcie_base = STG_SYSCON_PCIE0_BASE;
+ else
+ pcie->stg_pcie_base = STG_SYSCON_PCIE1_BASE;
+
+ pcie->reset_gpio = devm_gpiod_get_optional(dev, "perst",
+ GPIOD_OUT_HIGH);
+ if (IS_ERR(pcie->reset_gpio))
+ return dev_err_probe(dev, PTR_ERR(pcie->reset_gpio),
+ "failed to get perst-gpio\n");
+
+ pcie->power_gpio = devm_gpiod_get_optional(dev, "enable",
+ GPIOD_OUT_LOW);
+ if (IS_ERR(pcie->power_gpio))
+ return dev_err_probe(dev, PTR_ERR(pcie->power_gpio),
+ "failed to get power-gpio\n");
+
+ return 0;
+}
+
+static struct pci_ops starfive_pcie_ops = {
+ .map_bus = plda_pcie_map_bus,
+ .read = starfive_pcie_config_read,
+ .write = starfive_pcie_config_write,
+};
+
+static int starfive_pcie_clk_rst_init(struct starfive_jh7110_pcie *pcie)
+{
+ struct device *dev = pcie->plda.dev;
+ int ret;
+
+ ret = clk_bulk_prepare_enable(pcie->num_clks, pcie->clks);
+ if (ret)
+ return dev_err_probe(dev, ret, "failed to enable clocks\n");
+
+ ret = reset_control_deassert(pcie->resets);
+ if (ret) {
+ clk_bulk_disable_unprepare(pcie->num_clks, pcie->clks);
+ dev_err_probe(dev, ret, "failed to deassert resets\n");
+ }
+
+ return ret;
+}
+
+static void starfive_pcie_clk_rst_deinit(struct starfive_jh7110_pcie *pcie)
+{
+ reset_control_assert(pcie->resets);
+ clk_bulk_disable_unprepare(pcie->num_clks, pcie->clks);
+}
+
+static bool starfive_pcie_link_up(struct plda_pcie_rp *plda)
+{
+ struct starfive_jh7110_pcie *pcie =
+ container_of(plda, struct starfive_jh7110_pcie, plda);
+ int ret;
+ u32 stg_reg_val;
+
+ ret = regmap_read(pcie->reg_syscon,
+ pcie->stg_pcie_base + STG_SYSCON_LNKSTA_OFFSET,
+ &stg_reg_val);
+ if (ret) {
+ dev_err(pcie->plda.dev, "failed to read link status\n");
+ return false;
+ }
+
+ return !!(stg_reg_val & DATA_LINK_ACTIVE);
+}
+
+static int starfive_pcie_host_wait_for_link(struct starfive_jh7110_pcie *pcie)
+{
+ int retries;
+
+ /* Check if the link is up or not */
+ for (retries = 0; retries < LINK_WAIT_MAX_RETRIES; retries++) {
+ if (starfive_pcie_link_up(&pcie->plda)) {
+ dev_info(pcie->plda.dev, "port link up\n");
+ return 0;
+ }
+ usleep_range(LINK_WAIT_USLEEP_MIN, LINK_WAIT_USLEEP_MAX);
+ }
+
+ return -ETIMEDOUT;
+}
+
+static int starfive_pcie_enable_phy(struct device *dev,
+ struct starfive_jh7110_pcie *pcie)
+{
+ int ret;
+
+ if (!pcie->phy)
+ return 0;
+
+ ret = phy_init(pcie->phy);
+ if (ret)
+ return dev_err_probe(dev, ret,
+ "failed to initialize pcie phy\n");
+
+ ret = phy_set_mode(pcie->phy, PHY_MODE_PCIE);
+ if (ret) {
+ dev_err_probe(dev, ret, "failed to set pcie mode\n");
+ goto err_phy_on;
+ }
+
+ ret = phy_power_on(pcie->phy);
+ if (ret) {
+ dev_err_probe(dev, ret, "failed to power on pcie phy\n");
+ goto err_phy_on;
+ }
+
+ return 0;
+
+err_phy_on:
+ phy_exit(pcie->phy);
+ return ret;
+}
+
+static void starfive_pcie_disable_phy(struct starfive_jh7110_pcie *pcie)
+{
+ phy_power_off(pcie->phy);
+ phy_exit(pcie->phy);
+}
+
+static void starfive_pcie_host_deinit(struct plda_pcie_rp *plda)
+{
+ struct starfive_jh7110_pcie *pcie =
+ container_of(plda, struct starfive_jh7110_pcie, plda);
+
+ starfive_pcie_clk_rst_deinit(pcie);
+ if (pcie->power_gpio)
+ gpiod_set_value_cansleep(pcie->power_gpio, 0);
+ starfive_pcie_disable_phy(pcie);
+}
+
+static int starfive_pcie_host_init(struct plda_pcie_rp *plda)
+{
+ struct starfive_jh7110_pcie *pcie =
+ container_of(plda, struct starfive_jh7110_pcie, plda);
+ struct device *dev = plda->dev;
+ int ret;
+ int i;
+
+ ret = starfive_pcie_enable_phy(dev, pcie);
+ if (ret)
+ return ret;
+
+ regmap_update_bits(pcie->reg_syscon,
+ pcie->stg_pcie_base + STG_SYSCON_RP_NEP_OFFSET,
+ STG_SYSCON_K_RP_NEP, STG_SYSCON_K_RP_NEP);
+
+ regmap_update_bits(pcie->reg_syscon,
+ pcie->stg_pcie_base + STG_SYSCON_AW_OFFSET,
+ STG_SYSCON_CKREF_SRC_MASK,
+ FIELD_PREP(STG_SYSCON_CKREF_SRC_MASK, 2));
+
+ regmap_update_bits(pcie->reg_syscon,
+ pcie->stg_pcie_base + STG_SYSCON_AW_OFFSET,
+ STG_SYSCON_CLKREQ, STG_SYSCON_CLKREQ);
+
+ ret = starfive_pcie_clk_rst_init(pcie);
+ if (ret)
+ return ret;
+
+ if (pcie->power_gpio)
+ gpiod_set_value_cansleep(pcie->power_gpio, 1);
+
+ if (pcie->reset_gpio)
+ gpiod_set_value_cansleep(pcie->reset_gpio, 1);
+
+ /* Disable physical functions except #0 */
+ for (i = 1; i < PCIE_FUNC_NUM; i++) {
+ regmap_update_bits(pcie->reg_syscon,
+ pcie->stg_pcie_base + STG_SYSCON_AR_OFFSET,
+ STG_SYSCON_AXI4_SLVL_AR_MASK,
+ STG_SYSCON_AXI4_SLVL_PHY_AR(i));
+
+ regmap_update_bits(pcie->reg_syscon,
+ pcie->stg_pcie_base + STG_SYSCON_AW_OFFSET,
+ STG_SYSCON_AXI4_SLVL_AW_MASK,
+ STG_SYSCON_AXI4_SLVL_PHY_AW(i));
+
+ plda_pcie_disable_func(plda);
+ }
+
+ regmap_update_bits(pcie->reg_syscon,
+ pcie->stg_pcie_base + STG_SYSCON_AR_OFFSET,
+ STG_SYSCON_AXI4_SLVL_AR_MASK, 0);
+ regmap_update_bits(pcie->reg_syscon,
+ pcie->stg_pcie_base + STG_SYSCON_AW_OFFSET,
+ STG_SYSCON_AXI4_SLVL_AW_MASK, 0);
+
+ plda_pcie_enable_root_port(plda);
+ plda_pcie_write_rc_bar(plda, 0);
+
+ /* PCIe PCI Standard Configuration Identification Settings. */
+ plda_pcie_set_standard_class(plda);
+
+ /*
+ * The LTR message forwarding of PCIe Message Reception was set by core
+ * as default, but the forward id & addr are also need to be reset.
+ * If we do not disable LTR message forwarding here, or set a legal
+ * forwarding address, the kernel will get stuck after the driver probe.
+ * To workaround, disable the LTR message forwarding support on
+ * PCIe Message Reception.
+ */
+ plda_pcie_disable_ltr(plda);
+
+ /* Prefetchable memory window 64-bit addressing support */
+ plda_pcie_set_pref_win_64bit(plda);
+
+ /*
+ * Ensure that PERST has been asserted for at least 100 ms,
+ * the sleep value is T_PVPERL from PCIe CEM spec r2.0 (Table 2-4)
+ */
+ msleep(100);
+ if (pcie->reset_gpio)
+ gpiod_set_value_cansleep(pcie->reset_gpio, 0);
+
+ /*
+ * With a Downstream Port (<=5GT/s), software must wait a minimum
+ * of 100ms following exit from a conventional reset before
+ * sending a configuration request to the device.
+ */
+ msleep(PCIE_RESET_CONFIG_DEVICE_WAIT_MS);
+
+ if (starfive_pcie_host_wait_for_link(pcie))
+ dev_info(dev, "port link down\n");
+
+ return 0;
+}
+
+static const struct plda_pcie_host_ops sf_host_ops = {
+ .host_init = starfive_pcie_host_init,
+ .host_deinit = starfive_pcie_host_deinit,
+};
+
+static const struct plda_event stf_pcie_event = {
+ .intx_event = EVENT_PM_MSI_INT_INTX,
+ .msi_event = EVENT_PM_MSI_INT_MSI
+};
+
+static int starfive_pcie_probe(struct platform_device *pdev)
+{
+ struct starfive_jh7110_pcie *pcie;
+ struct device *dev = &pdev->dev;
+ struct plda_pcie_rp *plda;
+ int ret;
+
+ pcie = devm_kzalloc(dev, sizeof(*pcie), GFP_KERNEL);
+ if (!pcie)
+ return -ENOMEM;
+
+ plda = &pcie->plda;
+ plda->dev = dev;
+
+ ret = starfive_pcie_parse_dt(pcie, dev);
+ if (ret)
+ return ret;
+
+ plda->host_ops = &sf_host_ops;
+ plda->num_events = PLDA_MAX_EVENT_NUM;
+ /* mask doorbell event */
+ plda->events_bitmap = GENMASK(PLDA_INT_EVENT_NUM - 1, 0)
+ & ~BIT(PLDA_AXI_DOORBELL)
+ & ~BIT(PLDA_PCIE_DOORBELL);
+ plda->events_bitmap <<= PLDA_NUM_DMA_EVENTS;
+ ret = plda_pcie_host_init(&pcie->plda, &starfive_pcie_ops,
+ &stf_pcie_event);
+ if (ret)
+ return ret;
+
+ pm_runtime_enable(&pdev->dev);
+ pm_runtime_get_sync(&pdev->dev);
+ platform_set_drvdata(pdev, pcie);
+
+ return 0;
+}
+
+static void starfive_pcie_remove(struct platform_device *pdev)
+{
+ struct starfive_jh7110_pcie *pcie = platform_get_drvdata(pdev);
+
+ pm_runtime_put(&pdev->dev);
+ pm_runtime_disable(&pdev->dev);
+ plda_pcie_host_deinit(&pcie->plda);
+ platform_set_drvdata(pdev, NULL);
+}
+
+static int starfive_pcie_suspend_noirq(struct device *dev)
+{
+ struct starfive_jh7110_pcie *pcie = dev_get_drvdata(dev);
+
+ clk_bulk_disable_unprepare(pcie->num_clks, pcie->clks);
+ starfive_pcie_disable_phy(pcie);
+
+ return 0;
+}
+
+static int starfive_pcie_resume_noirq(struct device *dev)
+{
+ struct starfive_jh7110_pcie *pcie = dev_get_drvdata(dev);
+ int ret;
+
+ ret = starfive_pcie_enable_phy(dev, pcie);
+ if (ret)
+ return ret;
+
+ ret = clk_bulk_prepare_enable(pcie->num_clks, pcie->clks);
+ if (ret) {
+ dev_err(dev, "failed to enable clocks\n");
+ starfive_pcie_disable_phy(pcie);
+ return ret;
+ }
+
+ return 0;
+}
+
+static const struct dev_pm_ops starfive_pcie_pm_ops = {
+ NOIRQ_SYSTEM_SLEEP_PM_OPS(starfive_pcie_suspend_noirq,
+ starfive_pcie_resume_noirq)
+};
+
+static const struct of_device_id starfive_pcie_of_match[] = {
+ { .compatible = "starfive,jh7110-pcie", },
+ { /* sentinel */ }
+};
+MODULE_DEVICE_TABLE(of, starfive_pcie_of_match);
+
+static struct platform_driver starfive_pcie_driver = {
+ .driver = {
+ .name = "pcie-starfive",
+ .of_match_table = of_match_ptr(starfive_pcie_of_match),
+ .pm = pm_sleep_ptr(&starfive_pcie_pm_ops),
+ },
+ .probe = starfive_pcie_probe,
+ .remove_new = starfive_pcie_remove,
+};
+module_platform_driver(starfive_pcie_driver);
+
+MODULE_DESCRIPTION("StarFive JH7110 PCIe host driver");
+MODULE_LICENSE("GPL v2");

View File

@ -0,0 +1,97 @@
From a306724fd4f32808d1e27efbd87019d56f60db20 Mon Sep 17 00:00:00 2001
From: Hal Feng <hal.feng@starfivetech.com>
Date: Mon, 14 Aug 2023 16:06:16 +0800
Subject: [PATCH 035/116] ASoC: dt-bindings: Add StarFive JH7110 PWM-DAC
controller
Add bindings for the PWM-DAC controller on the JH7110
RISC-V SoC by StarFive Ltd.
Reviewed-by: Krzysztof Kozlowski <krzysztof.kozlowski@linaro.org>
Signed-off-by: Hal Feng <hal.feng@starfivetech.com>
Link: https://lore.kernel.org/r/20230814080618.10036-2-hal.feng@starfivetech.com
Signed-off-by: Mark Brown <broonie@kernel.org>
---
.../sound/starfive,jh7110-pwmdac.yaml | 76 +++++++++++++++++++
1 file changed, 76 insertions(+)
create mode 100644 Documentation/devicetree/bindings/sound/starfive,jh7110-pwmdac.yaml
--- /dev/null
+++ b/Documentation/devicetree/bindings/sound/starfive,jh7110-pwmdac.yaml
@@ -0,0 +1,76 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/sound/starfive,jh7110-pwmdac.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: StarFive JH7110 PWM-DAC Controller
+
+description:
+ The PWM-DAC Controller uses PWM square wave generators plus RC filters to
+ form a DAC for audio play in StarFive JH7110 SoC. This audio play controller
+ supports 16 bit audio format, up to 48K sampling frequency, up to left and
+ right dual channels.
+
+maintainers:
+ - Hal Feng <hal.feng@starfivetech.com>
+
+allOf:
+ - $ref: dai-common.yaml#
+
+properties:
+ compatible:
+ const: starfive,jh7110-pwmdac
+
+ reg:
+ maxItems: 1
+
+ clocks:
+ items:
+ - description: PWMDAC APB
+ - description: PWMDAC CORE
+
+ clock-names:
+ items:
+ - const: apb
+ - const: core
+
+ resets:
+ maxItems: 1
+ description: PWMDAC APB
+
+ dmas:
+ maxItems: 1
+ description: TX DMA Channel
+
+ dma-names:
+ const: tx
+
+ "#sound-dai-cells":
+ const: 0
+
+required:
+ - compatible
+ - reg
+ - clocks
+ - clock-names
+ - resets
+ - dmas
+ - dma-names
+ - "#sound-dai-cells"
+
+additionalProperties: false
+
+examples:
+ - |
+ pwmdac@100b0000 {
+ compatible = "starfive,jh7110-pwmdac";
+ reg = <0x100b0000 0x1000>;
+ clocks = <&syscrg 157>,
+ <&syscrg 158>;
+ clock-names = "apb", "core";
+ resets = <&syscrg 96>;
+ dmas = <&dma 22>;
+ dma-names = "tx";
+ #sound-dai-cells = <0>;
+ };

View File

@ -0,0 +1,574 @@
From a79d2ec524012e35e32a2c4ae2401d0aa763697d Mon Sep 17 00:00:00 2001
From: Hal Feng <hal.feng@starfivetech.com>
Date: Mon, 14 Aug 2023 16:06:17 +0800
Subject: [PATCH 036/116] ASoC: starfive: Add JH7110 PWM-DAC driver
Add PWM-DAC driver support for the StarFive JH7110 SoC.
Reviewed-by: Walker Chen <walker.chen@starfivetech.com>
Signed-off-by: Hal Feng <hal.feng@starfivetech.com>
Link: https://lore.kernel.org/r/20230814080618.10036-3-hal.feng@starfivetech.com
Signed-off-by: Mark Brown <broonie@kernel.org>
---
sound/soc/starfive/Kconfig | 9 +
sound/soc/starfive/Makefile | 1 +
sound/soc/starfive/jh7110_pwmdac.c | 529 +++++++++++++++++++++++++++++
3 files changed, 539 insertions(+)
create mode 100644 sound/soc/starfive/jh7110_pwmdac.c
--- a/sound/soc/starfive/Kconfig
+++ b/sound/soc/starfive/Kconfig
@@ -7,6 +7,15 @@ config SND_SOC_STARFIVE
the Starfive SoCs' Audio interfaces. You will also need to
select the audio interfaces to support below.
+config SND_SOC_JH7110_PWMDAC
+ tristate "JH7110 PWM-DAC device driver"
+ depends on HAVE_CLK && SND_SOC_STARFIVE
+ select SND_SOC_GENERIC_DMAENGINE_PCM
+ select SND_SOC_SPDIF
+ help
+ Say Y or M if you want to add support for StarFive JH7110
+ PWM-DAC driver.
+
config SND_SOC_JH7110_TDM
tristate "JH7110 TDM device driver"
depends on HAVE_CLK && SND_SOC_STARFIVE
--- a/sound/soc/starfive/Makefile
+++ b/sound/soc/starfive/Makefile
@@ -1,2 +1,3 @@
# StarFive Platform Support
+obj-$(CONFIG_SND_SOC_JH7110_PWMDAC) += jh7110_pwmdac.o
obj-$(CONFIG_SND_SOC_JH7110_TDM) += jh7110_tdm.o
--- /dev/null
+++ b/sound/soc/starfive/jh7110_pwmdac.c
@@ -0,0 +1,529 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * jh7110_pwmdac.c -- StarFive JH7110 PWM-DAC driver
+ *
+ * Copyright (C) 2021-2023 StarFive Technology Co., Ltd.
+ *
+ * Authors: Jenny Zhang
+ * Curry Zhang
+ * Xingyu Wu <xingyu.wu@starfivetech.com>
+ * Hal Feng <hal.feng@starfivetech.com>
+ */
+
+#include <linux/clk.h>
+#include <linux/device.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/io.h>
+#include <linux/module.h>
+#include <linux/pm_runtime.h>
+#include <linux/reset.h>
+#include <linux/slab.h>
+#include <linux/types.h>
+#include <sound/dmaengine_pcm.h>
+#include <sound/pcm.h>
+#include <sound/pcm_params.h>
+#include <sound/soc.h>
+
+#define JH7110_PWMDAC_WDATA 0x00
+#define JH7110_PWMDAC_CTRL 0x04
+ #define JH7110_PWMDAC_ENABLE BIT(0)
+ #define JH7110_PWMDAC_SHIFT BIT(1)
+ #define JH7110_PWMDAC_DUTY_CYCLE_SHIFT 2
+ #define JH7110_PWMDAC_DUTY_CYCLE_MASK GENMASK(3, 2)
+ #define JH7110_PWMDAC_CNT_N_SHIFT 4
+ #define JH7110_PWMDAC_CNT_N_MASK GENMASK(12, 4)
+ #define JH7110_PWMDAC_DATA_CHANGE BIT(13)
+ #define JH7110_PWMDAC_DATA_MODE BIT(14)
+ #define JH7110_PWMDAC_DATA_SHIFT_SHIFT 15
+ #define JH7110_PWMDAC_DATA_SHIFT_MASK GENMASK(17, 15)
+
+enum JH7110_PWMDAC_SHIFT_VAL {
+ PWMDAC_SHIFT_8 = 0,
+ PWMDAC_SHIFT_10,
+};
+
+enum JH7110_PWMDAC_DUTY_CYCLE_VAL {
+ PWMDAC_CYCLE_LEFT = 0,
+ PWMDAC_CYCLE_RIGHT,
+ PWMDAC_CYCLE_CENTER,
+};
+
+enum JH7110_PWMDAC_CNT_N_VAL {
+ PWMDAC_SAMPLE_CNT_1 = 1,
+ PWMDAC_SAMPLE_CNT_2,
+ PWMDAC_SAMPLE_CNT_3,
+ PWMDAC_SAMPLE_CNT_512 = 512, /* max */
+};
+
+enum JH7110_PWMDAC_DATA_CHANGE_VAL {
+ NO_CHANGE = 0,
+ CHANGE,
+};
+
+enum JH7110_PWMDAC_DATA_MODE_VAL {
+ UNSIGNED_DATA = 0,
+ INVERTER_DATA_MSB,
+};
+
+enum JH7110_PWMDAC_DATA_SHIFT_VAL {
+ PWMDAC_DATA_LEFT_SHIFT_BIT_0 = 0,
+ PWMDAC_DATA_LEFT_SHIFT_BIT_1,
+ PWMDAC_DATA_LEFT_SHIFT_BIT_2,
+ PWMDAC_DATA_LEFT_SHIFT_BIT_3,
+ PWMDAC_DATA_LEFT_SHIFT_BIT_4,
+ PWMDAC_DATA_LEFT_SHIFT_BIT_5,
+ PWMDAC_DATA_LEFT_SHIFT_BIT_6,
+ PWMDAC_DATA_LEFT_SHIFT_BIT_7,
+};
+
+struct jh7110_pwmdac_cfg {
+ enum JH7110_PWMDAC_SHIFT_VAL shift;
+ enum JH7110_PWMDAC_DUTY_CYCLE_VAL duty_cycle;
+ u16 cnt_n;
+ enum JH7110_PWMDAC_DATA_CHANGE_VAL data_change;
+ enum JH7110_PWMDAC_DATA_MODE_VAL data_mode;
+ enum JH7110_PWMDAC_DATA_SHIFT_VAL data_shift;
+};
+
+struct jh7110_pwmdac_dev {
+ void __iomem *base;
+ resource_size_t mapbase;
+ struct jh7110_pwmdac_cfg cfg;
+
+ struct clk_bulk_data clks[2];
+ struct reset_control *rst_apb;
+ struct device *dev;
+ struct snd_dmaengine_dai_dma_data play_dma_data;
+ u32 saved_ctrl;
+};
+
+static inline void jh7110_pwmdac_write_reg(void __iomem *io_base, int reg, u32 val)
+{
+ writel(val, io_base + reg);
+}
+
+static inline u32 jh7110_pwmdac_read_reg(void __iomem *io_base, int reg)
+{
+ return readl(io_base + reg);
+}
+
+static void jh7110_pwmdac_set_enable(struct jh7110_pwmdac_dev *dev, bool enable)
+{
+ u32 value;
+
+ value = jh7110_pwmdac_read_reg(dev->base, JH7110_PWMDAC_CTRL);
+ if (enable)
+ value |= JH7110_PWMDAC_ENABLE;
+ else
+ value &= ~JH7110_PWMDAC_ENABLE;
+
+ jh7110_pwmdac_write_reg(dev->base, JH7110_PWMDAC_CTRL, value);
+}
+
+static void jh7110_pwmdac_set_shift(struct jh7110_pwmdac_dev *dev)
+{
+ u32 value;
+
+ value = jh7110_pwmdac_read_reg(dev->base, JH7110_PWMDAC_CTRL);
+ if (dev->cfg.shift == PWMDAC_SHIFT_8)
+ value &= ~JH7110_PWMDAC_SHIFT;
+ else if (dev->cfg.shift == PWMDAC_SHIFT_10)
+ value |= JH7110_PWMDAC_SHIFT;
+
+ jh7110_pwmdac_write_reg(dev->base, JH7110_PWMDAC_CTRL, value);
+}
+
+static void jh7110_pwmdac_set_duty_cycle(struct jh7110_pwmdac_dev *dev)
+{
+ u32 value;
+
+ value = jh7110_pwmdac_read_reg(dev->base, JH7110_PWMDAC_CTRL);
+ value &= ~JH7110_PWMDAC_DUTY_CYCLE_MASK;
+ value |= (dev->cfg.duty_cycle & 0x3) << JH7110_PWMDAC_DUTY_CYCLE_SHIFT;
+
+ jh7110_pwmdac_write_reg(dev->base, JH7110_PWMDAC_CTRL, value);
+}
+
+static void jh7110_pwmdac_set_cnt_n(struct jh7110_pwmdac_dev *dev)
+{
+ u32 value;
+
+ value = jh7110_pwmdac_read_reg(dev->base, JH7110_PWMDAC_CTRL);
+ value &= ~JH7110_PWMDAC_CNT_N_MASK;
+ value |= ((dev->cfg.cnt_n - 1) & 0x1ff) << JH7110_PWMDAC_CNT_N_SHIFT;
+
+ jh7110_pwmdac_write_reg(dev->base, JH7110_PWMDAC_CTRL, value);
+}
+
+static void jh7110_pwmdac_set_data_change(struct jh7110_pwmdac_dev *dev)
+{
+ u32 value;
+
+ value = jh7110_pwmdac_read_reg(dev->base, JH7110_PWMDAC_CTRL);
+ if (dev->cfg.data_change == NO_CHANGE)
+ value &= ~JH7110_PWMDAC_DATA_CHANGE;
+ else if (dev->cfg.data_change == CHANGE)
+ value |= JH7110_PWMDAC_DATA_CHANGE;
+
+ jh7110_pwmdac_write_reg(dev->base, JH7110_PWMDAC_CTRL, value);
+}
+
+static void jh7110_pwmdac_set_data_mode(struct jh7110_pwmdac_dev *dev)
+{
+ u32 value;
+
+ value = jh7110_pwmdac_read_reg(dev->base, JH7110_PWMDAC_CTRL);
+ if (dev->cfg.data_mode == UNSIGNED_DATA)
+ value &= ~JH7110_PWMDAC_DATA_MODE;
+ else if (dev->cfg.data_mode == INVERTER_DATA_MSB)
+ value |= JH7110_PWMDAC_DATA_MODE;
+
+ jh7110_pwmdac_write_reg(dev->base, JH7110_PWMDAC_CTRL, value);
+}
+
+static void jh7110_pwmdac_set_data_shift(struct jh7110_pwmdac_dev *dev)
+{
+ u32 value;
+
+ value = jh7110_pwmdac_read_reg(dev->base, JH7110_PWMDAC_CTRL);
+ value &= ~JH7110_PWMDAC_DATA_SHIFT_MASK;
+ value |= (dev->cfg.data_shift & 0x7) << JH7110_PWMDAC_DATA_SHIFT_SHIFT;
+
+ jh7110_pwmdac_write_reg(dev->base, JH7110_PWMDAC_CTRL, value);
+}
+
+static void jh7110_pwmdac_set(struct jh7110_pwmdac_dev *dev)
+{
+ jh7110_pwmdac_set_shift(dev);
+ jh7110_pwmdac_set_duty_cycle(dev);
+ jh7110_pwmdac_set_cnt_n(dev);
+ jh7110_pwmdac_set_enable(dev, true);
+
+ jh7110_pwmdac_set_data_change(dev);
+ jh7110_pwmdac_set_data_mode(dev);
+ jh7110_pwmdac_set_data_shift(dev);
+}
+
+static void jh7110_pwmdac_stop(struct jh7110_pwmdac_dev *dev)
+{
+ jh7110_pwmdac_set_enable(dev, false);
+}
+
+static int jh7110_pwmdac_startup(struct snd_pcm_substream *substream,
+ struct snd_soc_dai *dai)
+{
+ struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream);
+ struct snd_soc_dai_link *dai_link = rtd->dai_link;
+
+ dai_link->trigger_stop = SND_SOC_TRIGGER_ORDER_LDC;
+
+ return 0;
+}
+
+static int jh7110_pwmdac_hw_params(struct snd_pcm_substream *substream,
+ struct snd_pcm_hw_params *params,
+ struct snd_soc_dai *dai)
+{
+ struct jh7110_pwmdac_dev *dev = dev_get_drvdata(dai->dev);
+ unsigned long core_clk_rate;
+ int ret;
+
+ switch (params_rate(params)) {
+ case 8000:
+ dev->cfg.cnt_n = PWMDAC_SAMPLE_CNT_3;
+ core_clk_rate = 6144000;
+ break;
+ case 11025:
+ dev->cfg.cnt_n = PWMDAC_SAMPLE_CNT_2;
+ core_clk_rate = 5644800;
+ break;
+ case 16000:
+ dev->cfg.cnt_n = PWMDAC_SAMPLE_CNT_3;
+ core_clk_rate = 12288000;
+ break;
+ case 22050:
+ dev->cfg.cnt_n = PWMDAC_SAMPLE_CNT_1;
+ core_clk_rate = 5644800;
+ break;
+ case 32000:
+ dev->cfg.cnt_n = PWMDAC_SAMPLE_CNT_1;
+ core_clk_rate = 8192000;
+ break;
+ case 44100:
+ dev->cfg.cnt_n = PWMDAC_SAMPLE_CNT_1;
+ core_clk_rate = 11289600;
+ break;
+ case 48000:
+ dev->cfg.cnt_n = PWMDAC_SAMPLE_CNT_1;
+ core_clk_rate = 12288000;
+ break;
+ default:
+ dev_err(dai->dev, "%d rate not supported\n",
+ params_rate(params));
+ return -EINVAL;
+ }
+
+ switch (params_channels(params)) {
+ case 1:
+ dev->play_dma_data.addr_width = DMA_SLAVE_BUSWIDTH_2_BYTES;
+ break;
+ case 2:
+ dev->play_dma_data.addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES;
+ break;
+ default:
+ dev_err(dai->dev, "%d channels not supported\n",
+ params_channels(params));
+ return -EINVAL;
+ }
+
+ /*
+ * The clock rate always rounds down when using clk_set_rate()
+ * so increase the rate a bit
+ */
+ core_clk_rate += 64;
+ jh7110_pwmdac_set(dev);
+
+ ret = clk_set_rate(dev->clks[1].clk, core_clk_rate);
+ if (ret)
+ return dev_err_probe(dai->dev, ret,
+ "failed to set rate %lu for core clock\n",
+ core_clk_rate);
+
+ return 0;
+}
+
+static int jh7110_pwmdac_trigger(struct snd_pcm_substream *substream, int cmd,
+ struct snd_soc_dai *dai)
+{
+ struct jh7110_pwmdac_dev *dev = snd_soc_dai_get_drvdata(dai);
+ int ret = 0;
+
+ switch (cmd) {
+ case SNDRV_PCM_TRIGGER_START:
+ case SNDRV_PCM_TRIGGER_RESUME:
+ case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
+ jh7110_pwmdac_set(dev);
+ break;
+
+ case SNDRV_PCM_TRIGGER_STOP:
+ case SNDRV_PCM_TRIGGER_SUSPEND:
+ case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
+ jh7110_pwmdac_stop(dev);
+ break;
+ default:
+ ret = -EINVAL;
+ break;
+ }
+
+ return ret;
+}
+
+static int jh7110_pwmdac_crg_enable(struct jh7110_pwmdac_dev *dev, bool enable)
+{
+ int ret;
+
+ if (enable) {
+ ret = clk_bulk_prepare_enable(ARRAY_SIZE(dev->clks), dev->clks);
+ if (ret)
+ return dev_err_probe(dev->dev, ret,
+ "failed to enable pwmdac clocks\n");
+
+ ret = reset_control_deassert(dev->rst_apb);
+ if (ret) {
+ dev_err(dev->dev, "failed to deassert pwmdac apb reset\n");
+ goto err_rst_apb;
+ }
+ } else {
+ clk_bulk_disable_unprepare(ARRAY_SIZE(dev->clks), dev->clks);
+ }
+
+ return 0;
+
+err_rst_apb:
+ clk_bulk_disable_unprepare(ARRAY_SIZE(dev->clks), dev->clks);
+
+ return ret;
+}
+
+static int jh7110_pwmdac_dai_probe(struct snd_soc_dai *dai)
+{
+ struct jh7110_pwmdac_dev *dev = dev_get_drvdata(dai->dev);
+
+ snd_soc_dai_init_dma_data(dai, &dev->play_dma_data, NULL);
+ snd_soc_dai_set_drvdata(dai, dev);
+
+ return 0;
+}
+
+static const struct snd_soc_dai_ops jh7110_pwmdac_dai_ops = {
+ .startup = jh7110_pwmdac_startup,
+ .hw_params = jh7110_pwmdac_hw_params,
+ .trigger = jh7110_pwmdac_trigger,
+};
+
+static const struct snd_soc_component_driver jh7110_pwmdac_component = {
+ .name = "jh7110-pwmdac",
+};
+
+static struct snd_soc_dai_driver jh7110_pwmdac_dai = {
+ .name = "jh7110-pwmdac",
+ .id = 0,
+ .probe = jh7110_pwmdac_dai_probe,
+ .playback = {
+ .channels_min = 1,
+ .channels_max = 2,
+ .rates = SNDRV_PCM_RATE_8000_48000,
+ .formats = SNDRV_PCM_FMTBIT_S16_LE,
+ },
+ .ops = &jh7110_pwmdac_dai_ops,
+};
+
+static int jh7110_pwmdac_runtime_suspend(struct device *dev)
+{
+ struct jh7110_pwmdac_dev *pwmdac = dev_get_drvdata(dev);
+
+ return jh7110_pwmdac_crg_enable(pwmdac, false);
+}
+
+static int jh7110_pwmdac_runtime_resume(struct device *dev)
+{
+ struct jh7110_pwmdac_dev *pwmdac = dev_get_drvdata(dev);
+
+ return jh7110_pwmdac_crg_enable(pwmdac, true);
+}
+
+static int jh7110_pwmdac_system_suspend(struct device *dev)
+{
+ struct jh7110_pwmdac_dev *pwmdac = dev_get_drvdata(dev);
+
+ /* save the CTRL register value */
+ pwmdac->saved_ctrl = jh7110_pwmdac_read_reg(pwmdac->base,
+ JH7110_PWMDAC_CTRL);
+ return pm_runtime_force_suspend(dev);
+}
+
+static int jh7110_pwmdac_system_resume(struct device *dev)
+{
+ struct jh7110_pwmdac_dev *pwmdac = dev_get_drvdata(dev);
+ int ret;
+
+ ret = pm_runtime_force_resume(dev);
+ if (ret)
+ return ret;
+
+ /* restore the CTRL register value */
+ jh7110_pwmdac_write_reg(pwmdac->base, JH7110_PWMDAC_CTRL,
+ pwmdac->saved_ctrl);
+ return 0;
+}
+
+static const struct dev_pm_ops jh7110_pwmdac_pm_ops = {
+ RUNTIME_PM_OPS(jh7110_pwmdac_runtime_suspend,
+ jh7110_pwmdac_runtime_resume, NULL)
+ SYSTEM_SLEEP_PM_OPS(jh7110_pwmdac_system_suspend,
+ jh7110_pwmdac_system_resume)
+};
+
+static void jh7110_pwmdac_init_params(struct jh7110_pwmdac_dev *dev)
+{
+ dev->cfg.shift = PWMDAC_SHIFT_8;
+ dev->cfg.duty_cycle = PWMDAC_CYCLE_CENTER;
+ dev->cfg.cnt_n = PWMDAC_SAMPLE_CNT_1;
+ dev->cfg.data_change = NO_CHANGE;
+ dev->cfg.data_mode = INVERTER_DATA_MSB;
+ dev->cfg.data_shift = PWMDAC_DATA_LEFT_SHIFT_BIT_0;
+
+ dev->play_dma_data.addr = dev->mapbase + JH7110_PWMDAC_WDATA;
+ dev->play_dma_data.addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES;
+ dev->play_dma_data.fifo_size = 1;
+ dev->play_dma_data.maxburst = 16;
+}
+
+static int jh7110_pwmdac_probe(struct platform_device *pdev)
+{
+ struct jh7110_pwmdac_dev *dev;
+ struct resource *res;
+ int ret;
+
+ dev = devm_kzalloc(&pdev->dev, sizeof(*dev), GFP_KERNEL);
+ if (!dev)
+ return -ENOMEM;
+
+ dev->base = devm_platform_get_and_ioremap_resource(pdev, 0, &res);
+ if (IS_ERR(dev->base))
+ return PTR_ERR(dev->base);
+
+ dev->mapbase = res->start;
+
+ dev->clks[0].id = "apb";
+ dev->clks[1].id = "core";
+
+ ret = devm_clk_bulk_get(&pdev->dev, ARRAY_SIZE(dev->clks), dev->clks);
+ if (ret)
+ return dev_err_probe(&pdev->dev, ret,
+ "failed to get pwmdac clocks\n");
+
+ dev->rst_apb = devm_reset_control_get_exclusive(&pdev->dev, NULL);
+ if (IS_ERR(dev->rst_apb))
+ return dev_err_probe(&pdev->dev, PTR_ERR(dev->rst_apb),
+ "failed to get pwmdac apb reset\n");
+
+ jh7110_pwmdac_init_params(dev);
+
+ dev->dev = &pdev->dev;
+ dev_set_drvdata(&pdev->dev, dev);
+ ret = devm_snd_soc_register_component(&pdev->dev,
+ &jh7110_pwmdac_component,
+ &jh7110_pwmdac_dai, 1);
+ if (ret)
+ return dev_err_probe(&pdev->dev, ret, "failed to register dai\n");
+
+ ret = devm_snd_dmaengine_pcm_register(&pdev->dev, NULL, 0);
+ if (ret)
+ return dev_err_probe(&pdev->dev, ret, "failed to register pcm\n");
+
+ pm_runtime_enable(dev->dev);
+ if (!pm_runtime_enabled(&pdev->dev)) {
+ ret = jh7110_pwmdac_runtime_resume(&pdev->dev);
+ if (ret)
+ goto err_pm_disable;
+ }
+
+ return 0;
+
+err_pm_disable:
+ pm_runtime_disable(&pdev->dev);
+
+ return ret;
+}
+
+static int jh7110_pwmdac_remove(struct platform_device *pdev)
+{
+ pm_runtime_disable(&pdev->dev);
+ return 0;
+}
+
+static const struct of_device_id jh7110_pwmdac_of_match[] = {
+ { .compatible = "starfive,jh7110-pwmdac" },
+ { /* sentinel */ }
+};
+MODULE_DEVICE_TABLE(of, jh7110_pwmdac_of_match);
+
+static struct platform_driver jh7110_pwmdac_driver = {
+ .driver = {
+ .name = "jh7110-pwmdac",
+ .of_match_table = jh7110_pwmdac_of_match,
+ .pm = pm_ptr(&jh7110_pwmdac_pm_ops),
+ },
+ .probe = jh7110_pwmdac_probe,
+ .remove = jh7110_pwmdac_remove,
+};
+module_platform_driver(jh7110_pwmdac_driver);
+
+MODULE_AUTHOR("Jenny Zhang");
+MODULE_AUTHOR("Curry Zhang");
+MODULE_AUTHOR("Xingyu Wu <xingyu.wu@starfivetech.com>");
+MODULE_AUTHOR("Hal Feng <hal.feng@starfivetech.com>");
+MODULE_DESCRIPTION("StarFive JH7110 PWM-DAC driver");
+MODULE_LICENSE("GPL");

View File

@ -0,0 +1,32 @@
From c6b693f990e1f89ab5af0a139da31401b8cda74f Mon Sep 17 00:00:00 2001
From: Mark Brown <broonie@kernel.org>
Date: Mon, 11 Sep 2023 23:48:39 +0100
Subject: [PATCH 037/116] ASoC: Update jh7110 PWM DAC for ops move
For some reason the JH7110 PWM DAC driver made it through build testing
in spite of not being updated for the move of probe() to the ops struct.
Make the required update.
Signed-off-by: Mark Brown <broonie@kernel.org>
---
sound/soc/starfive/jh7110_pwmdac.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
--- a/sound/soc/starfive/jh7110_pwmdac.c
+++ b/sound/soc/starfive/jh7110_pwmdac.c
@@ -357,6 +357,7 @@ static int jh7110_pwmdac_dai_probe(struc
}
static const struct snd_soc_dai_ops jh7110_pwmdac_dai_ops = {
+ .probe = jh7110_pwmdac_dai_probe,
.startup = jh7110_pwmdac_startup,
.hw_params = jh7110_pwmdac_hw_params,
.trigger = jh7110_pwmdac_trigger,
@@ -369,7 +370,6 @@ static const struct snd_soc_component_dr
static struct snd_soc_dai_driver jh7110_pwmdac_dai = {
.name = "jh7110-pwmdac",
.id = 0,
- .probe = jh7110_pwmdac_dai_probe,
.playback = {
.channels_min = 1,
.channels_max = 2,

View File

@ -0,0 +1,52 @@
From 312c3c407c363f0ec7417d2d389cbe936c503729 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Uwe=20Kleine-K=C3=B6nig?= <u.kleine-koenig@pengutronix.de>
Date: Sat, 14 Oct 2023 00:19:49 +0200
Subject: [PATCH 038/116] ASoC: starfive/jh7110-pwmdac: Convert to platform
remove callback returning void
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
The .remove() callback for a platform driver returns an int which makes
many driver authors wrongly assume it's possible to do error handling by
returning an error code. However the value returned is ignored (apart
from emitting a warning) and this typically results in resource leaks.
To improve here there is a quest to make the remove callback return
void. In the first step of this quest all drivers are converted to
.remove_new(), which already returns void. Eventually after all drivers
are converted, .remove_new() will be renamed to .remove().
Trivially convert this driver from always returning zero in the remove
callback to the void returning variant.
Signed-off-by: Uwe Kleine-König <u.kleine-koenig@pengutronix.de>
Link: https://lore.kernel.org/r/20231013221945.1489203-12-u.kleine-koenig@pengutronix.de
Signed-off-by: Mark Brown <broonie@kernel.org>
---
sound/soc/starfive/jh7110_pwmdac.c | 5 ++---
1 file changed, 2 insertions(+), 3 deletions(-)
--- a/sound/soc/starfive/jh7110_pwmdac.c
+++ b/sound/soc/starfive/jh7110_pwmdac.c
@@ -498,10 +498,9 @@ err_pm_disable:
return ret;
}
-static int jh7110_pwmdac_remove(struct platform_device *pdev)
+static void jh7110_pwmdac_remove(struct platform_device *pdev)
{
pm_runtime_disable(&pdev->dev);
- return 0;
}
static const struct of_device_id jh7110_pwmdac_of_match[] = {
@@ -517,7 +516,7 @@ static struct platform_driver jh7110_pwm
.pm = pm_ptr(&jh7110_pwmdac_pm_ops),
},
.probe = jh7110_pwmdac_probe,
- .remove = jh7110_pwmdac_remove,
+ .remove_new = jh7110_pwmdac_remove,
};
module_platform_driver(jh7110_pwmdac_driver);

View File

@ -0,0 +1,35 @@
From 8d84bac6d7471ba2e29b33d19a2ef887822e9cce Mon Sep 17 00:00:00 2001
From: Changhuang Liang <changhuang.liang@starfivetech.com>
Date: Wed, 13 Sep 2023 14:54:25 +0100
Subject: [PATCH 039/116] dt-bindings: power: Add power-domain header for
JH7110
Add power-domain header for JH7110 SoC, it can use to operate dphy
power.
Signed-off-by: Changhuang Liang <changhuang.liang@starfivetech.com>
Signed-off-by: Conor Dooley <conor.dooley@microchip.com>
Link: https://lore.kernel.org/r/20230913-grumbly-rewrite-34c85539f2ed@spud
Signed-off-by: Ulf Hansson <ulf.hansson@linaro.org>
---
include/dt-bindings/power/starfive,jh7110-pmu.h | 5 ++++-
1 file changed, 4 insertions(+), 1 deletion(-)
--- a/include/dt-bindings/power/starfive,jh7110-pmu.h
+++ b/include/dt-bindings/power/starfive,jh7110-pmu.h
@@ -1,6 +1,6 @@
/* SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) */
/*
- * Copyright (C) 2022 StarFive Technology Co., Ltd.
+ * Copyright (C) 2022-2023 StarFive Technology Co., Ltd.
* Author: Walker Chen <walker.chen@starfivetech.com>
*/
#ifndef __DT_BINDINGS_POWER_JH7110_POWER_H__
@@ -14,4 +14,7 @@
#define JH7110_PD_ISP 5
#define JH7110_PD_VENC 6
+#define JH7110_PD_DPHY_TX 0
+#define JH7110_PD_DPHY_RX 1
+
#endif

View File

@ -0,0 +1,31 @@
From 0ac8e8b0e65d242f455401df0cc6c6d4772216e6 Mon Sep 17 00:00:00 2001
From: Changhuang Liang <changhuang.liang@starfivetech.com>
Date: Wed, 13 Sep 2023 14:54:26 +0100
Subject: [PATCH 040/116] pmdomain: starfive: Replace SOC_STARFIVE with
ARCH_STARFIVE
Using ARCH_FOO symbol is preferred than SOC_FOO.
Reviewed-by: Conor Dooley <conor.dooley@microchip.com>
Reviewed-by: Walker Chen <walker.chen@starfivetech.com>
Signed-off-by: Changhuang Liang <changhuang.liang@starfivetech.com>
Signed-off-by: Conor Dooley <conor.dooley@microchip.com>
Link: https://lore.kernel.org/r/20230913-legibly-treachery-567cffcb5604@spud
Signed-off-by: Ulf Hansson <ulf.hansson@linaro.org>
---
drivers/soc/starfive/Kconfig | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
--- a/drivers/soc/starfive/Kconfig
+++ b/drivers/soc/starfive/Kconfig
@@ -3,8 +3,8 @@
config JH71XX_PMU
bool "Support PMU for StarFive JH71XX Soc"
depends on PM
- depends on SOC_STARFIVE || COMPILE_TEST
- default SOC_STARFIVE
+ depends on ARCH_STARFIVE || COMPILE_TEST
+ default ARCH_STARFIVE
select PM_GENERIC_DOMAINS
help
Say 'y' here to enable support power domain support.

View File

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

View File

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

View File

@ -0,0 +1,36 @@
From dff6605dcd1fc1e2af1437e59187a6f71ce389cd Mon Sep 17 00:00:00 2001
From: Ulf Hansson <ulf.hansson@linaro.org>
Date: Mon, 11 Sep 2023 17:22:15 +0200
Subject: [PATCH 043/116] pmdomain: Prepare to move Kconfig files into the
pmdomain subsystem
Rather than having the various Kconfig files for the genpd providers
sprinkled across subsystems, let's prepare to move them into the pmdomain
subsystem along with the implementations.
Reviewed-by: Geert Uytterhoeven <geert+renesas@glider.be>
Signed-off-by: Ulf Hansson <ulf.hansson@linaro.org>
---
drivers/Kconfig | 2 ++
drivers/pmdomain/Kconfig | 4 ++++
2 files changed, 6 insertions(+)
create mode 100644 drivers/pmdomain/Kconfig
--- a/drivers/Kconfig
+++ b/drivers/Kconfig
@@ -175,6 +175,8 @@ source "drivers/soundwire/Kconfig"
source "drivers/soc/Kconfig"
+source "drivers/pmdomain/Kconfig"
+
source "drivers/devfreq/Kconfig"
source "drivers/extcon/Kconfig"
--- /dev/null
+++ b/drivers/pmdomain/Kconfig
@@ -0,0 +1,4 @@
+# SPDX-License-Identifier: GPL-2.0-only
+menu "PM Domains"
+
+endmenu

View File

@ -0,0 +1,69 @@
From de12fe43dbd0ea9fa980ffa05822bd7fd5eed330 Mon Sep 17 00:00:00 2001
From: Ulf Hansson <ulf.hansson@linaro.org>
Date: Tue, 12 Sep 2023 13:31:44 +0200
Subject: [PATCH 044/116] pmdomain: starfive: Move Kconfig file to the pmdomain
subsystem
The Kconfig belongs closer to the corresponding implementation, hence let's
move it from the soc subsystem to the pmdomain subsystem.
Cc: Walker Chen <walker.chen@starfivetech.com>
Cc: Conor Dooley <conor@kernel.org>
Acked-by: Conor Dooley <conor.dooley@microchip.com>
Signed-off-by: Ulf Hansson <ulf.hansson@linaro.org>
---
drivers/pmdomain/Kconfig | 2 ++
drivers/{soc => pmdomain}/starfive/Kconfig | 0
drivers/soc/Kconfig | 1 -
3 files changed, 2 insertions(+), 1 deletion(-)
rename drivers/{soc => pmdomain}/starfive/Kconfig (100%)
--- a/drivers/pmdomain/Kconfig
+++ b/drivers/pmdomain/Kconfig
@@ -1,4 +1,6 @@
# SPDX-License-Identifier: GPL-2.0-only
menu "PM Domains"
+source "drivers/pmdomain/starfive/Kconfig"
+
endmenu
--- a/drivers/soc/Kconfig
+++ b/drivers/soc/Kconfig
@@ -24,7 +24,6 @@ source "drivers/soc/renesas/Kconfig"
source "drivers/soc/rockchip/Kconfig"
source "drivers/soc/samsung/Kconfig"
source "drivers/soc/sifive/Kconfig"
-source "drivers/soc/starfive/Kconfig"
source "drivers/soc/sunxi/Kconfig"
source "drivers/soc/tegra/Kconfig"
source "drivers/soc/ti/Kconfig"
--- /dev/null
+++ b/drivers/pmdomain/starfive/Kconfig
@@ -0,0 +1,12 @@
+# SPDX-License-Identifier: GPL-2.0
+
+config JH71XX_PMU
+ bool "Support PMU for StarFive JH71XX Soc"
+ depends on PM
+ depends on ARCH_STARFIVE || COMPILE_TEST
+ default ARCH_STARFIVE
+ select PM_GENERIC_DOMAINS
+ help
+ Say 'y' here to enable support power domain support.
+ In order to meet low power requirements, a Power Management Unit (PMU)
+ is designed for controlling power resources in StarFive JH71XX SoCs.
--- a/drivers/soc/starfive/Kconfig
+++ /dev/null
@@ -1,12 +0,0 @@
-# SPDX-License-Identifier: GPL-2.0
-
-config JH71XX_PMU
- bool "Support PMU for StarFive JH71XX Soc"
- depends on PM
- depends on ARCH_STARFIVE || COMPILE_TEST
- default ARCH_STARFIVE
- select PM_GENERIC_DOMAINS
- help
- Say 'y' here to enable support power domain support.
- In order to meet low power requirements, a Power Management Unit (PMU)
- is designed for controlling power resources in StarFive JH71XX SoCs.

View File

@ -0,0 +1,31 @@
From cac9ce9c7f388a741389b1ec47af65420254db55 Mon Sep 17 00:00:00 2001
From: Changhuang Liang <changhuang.liang@starfivetech.com>
Date: Wed, 27 Sep 2023 06:07:33 -0700
Subject: [PATCH 045/116] dt-bindings: power: Update prefixes for AON power
domain
Use "JH7110_AON_PD_" prefix for AON power domain for JH7110 SoC.
Reviewed-by: Walker Chen <walker.chen@starfivetech.com>
Signed-off-by: Changhuang Liang <changhuang.liang@starfivetech.com>
Acked-by: Conor Dooley <conor.dooley@microchip.com>
Reviewed-by: Geert Uytterhoeven <geert+renesas@glider.be>
Link: https://lore.kernel.org/r/20230927130734.9921-2-changhuang.liang@starfivetech.com
Signed-off-by: Ulf Hansson <ulf.hansson@linaro.org>
---
include/dt-bindings/power/starfive,jh7110-pmu.h | 5 +++--
1 file changed, 3 insertions(+), 2 deletions(-)
--- a/include/dt-bindings/power/starfive,jh7110-pmu.h
+++ b/include/dt-bindings/power/starfive,jh7110-pmu.h
@@ -14,7 +14,8 @@
#define JH7110_PD_ISP 5
#define JH7110_PD_VENC 6
-#define JH7110_PD_DPHY_TX 0
-#define JH7110_PD_DPHY_RX 1
+/* AON Power Domain */
+#define JH7110_AON_PD_DPHY_TX 0
+#define JH7110_AON_PD_DPHY_RX 1
#endif

View File

@ -0,0 +1,32 @@
From 3ea89ffbd6cc5a15acca6bc2130572f8bd85b9d4 Mon Sep 17 00:00:00 2001
From: Changhuang Liang <changhuang.liang@starfivetech.com>
Date: Wed, 27 Sep 2023 06:07:34 -0700
Subject: [PATCH 046/116] pmdomain: starfive: Update prefixes for AON power
domain
Use "JH7110_AON_PD_" prefix for AON power doamin for JH7110 SoC.
Reviewed-by: Walker Chen <walker.chen@starfivetech.com>
Signed-off-by: Changhuang Liang <changhuang.liang@starfivetech.com>
Link: https://lore.kernel.org/r/20230927130734.9921-3-changhuang.liang@starfivetech.com
Signed-off-by: Ulf Hansson <ulf.hansson@linaro.org>
---
drivers/pmdomain/starfive/jh71xx-pmu.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
--- a/drivers/pmdomain/starfive/jh71xx-pmu.c
+++ b/drivers/pmdomain/starfive/jh71xx-pmu.c
@@ -420,11 +420,11 @@ static const struct jh71xx_pmu_match_dat
};
static const struct jh71xx_domain_info jh7110_aon_power_domains[] = {
- [JH7110_PD_DPHY_TX] = {
+ [JH7110_AON_PD_DPHY_TX] = {
.name = "DPHY-TX",
.bit = 30,
},
- [JH7110_PD_DPHY_RX] = {
+ [JH7110_AON_PD_DPHY_RX] = {
.name = "DPHY-RX",
.bit = 31,
},

View File

@ -0,0 +1,30 @@
From e7e3d62b7a470ddf15e30574232b52b2e23ba606 Mon Sep 17 00:00:00 2001
From: Xingyu Wu <xingyu.wu@starfivetech.com>
Date: Mon, 21 Aug 2023 22:41:50 +0800
Subject: [PATCH 047/116] riscv: dts: starfive: pinfunc: Fix the pins name of
I2STX1
These pins are actually I2STX1 clock input, not I2STX0,
so their names should be changed.
Signed-off-by: Xingyu Wu <xingyu.wu@starfivetech.com>
Reviewed-by: Walker Chen <walker.chen@starfivetech.com>
Acked-by: Rob Herring <robh@kernel.org>
Signed-off-by: Conor Dooley <conor.dooley@microchip.com>
---
arch/riscv/boot/dts/starfive/jh7110-pinfunc.h | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
--- a/arch/riscv/boot/dts/starfive/jh7110-pinfunc.h
+++ b/arch/riscv/boot/dts/starfive/jh7110-pinfunc.h
@@ -240,8 +240,8 @@
#define GPI_SYS_MCLK_EXT 30
#define GPI_SYS_I2SRX_BCLK 31
#define GPI_SYS_I2SRX_LRCK 32
-#define GPI_SYS_I2STX0_BCLK 33
-#define GPI_SYS_I2STX0_LRCK 34
+#define GPI_SYS_I2STX1_BCLK 33
+#define GPI_SYS_I2STX1_LRCK 34
#define GPI_SYS_TDM_CLK 35
#define GPI_SYS_TDM_RXD 36
#define GPI_SYS_TDM_SYNC 37

View File

@ -0,0 +1,549 @@
From a3d3f611f31fa2dca3deefa7cd443abca02e03fa Mon Sep 17 00:00:00 2001
From: Hal Feng <hal.feng@starfivetech.com>
Date: Tue, 11 Apr 2023 16:31:15 +0800
Subject: [PATCH 048/116] riscv: dts: starfive: Add full support (except VIN
and VOUT) for JH7110 and VisionFive 2 board
Merge all StarFive dts patches together except VIN and VOUT.
Signed-off-by: Hal Feng <hal.feng@starfivetech.com>
---
.../jh7110-starfive-visionfive-2.dtsi | 199 +++++++++++++++
arch/riscv/boot/dts/starfive/jh7110.dtsi | 233 ++++++++++++++++++
2 files changed, 432 insertions(+)
--- a/arch/riscv/boot/dts/starfive/jh7110-starfive-visionfive-2.dtsi
+++ b/arch/riscv/boot/dts/starfive/jh7110-starfive-visionfive-2.dtsi
@@ -19,6 +19,8 @@
i2c6 = &i2c6;
mmc0 = &mmc0;
mmc1 = &mmc1;
+ pcie0 = &pcie0;
+ pcie1 = &pcie1;
serial0 = &uart0;
};
@@ -40,6 +42,33 @@
gpios = <&sysgpio 35 GPIO_ACTIVE_HIGH>;
priority = <224>;
};
+
+ pwmdac_codec: pwmdac-codec {
+ compatible = "linux,spdif-dit";
+ #sound-dai-cells = <0>;
+ };
+
+ sound-pwmdac {
+ compatible = "simple-audio-card";
+ simple-audio-card,name = "StarFive-PWMDAC-Sound-Card";
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ simple-audio-card,dai-link@0 {
+ reg = <0>;
+ format = "left_j";
+ bitclock-master = <&sndcpu0>;
+ frame-master = <&sndcpu0>;
+
+ sndcpu0: cpu {
+ sound-dai = <&pwmdac>;
+ };
+
+ codec {
+ sound-dai = <&pwmdac_codec>;
+ };
+ };
+ };
};
&dvp_clk {
@@ -202,8 +231,28 @@
status = "okay";
};
+&i2srx {
+ pinctrl-names = "default";
+ pinctrl-0 = <&i2srx_pins>;
+ status = "okay";
+};
+
+&i2stx0 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&mclk_ext_pins>;
+ status = "okay";
+};
+
+&i2stx1 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&i2stx1_pins>;
+ status = "okay";
+};
+
&mmc0 {
max-frequency = <100000000>;
+ assigned-clocks = <&syscrg JH7110_SYSCLK_SDIO0_SDCARD>;
+ assigned-clock-rates = <50000000>;
bus-width = <8>;
cap-mmc-highspeed;
mmc-ddr-1_8v;
@@ -220,6 +269,8 @@
&mmc1 {
max-frequency = <100000000>;
+ assigned-clocks = <&syscrg JH7110_SYSCLK_SDIO1_SDCARD>;
+ assigned-clock-rates = <50000000>;
bus-width = <4>;
no-sdio;
no-mmc;
@@ -231,6 +282,34 @@
status = "okay";
};
+&pcie0 {
+ perst-gpios = <&sysgpio 26 GPIO_ACTIVE_LOW>;
+ phys = <&pciephy0>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&pcie0_pins>;
+ status = "okay";
+};
+
+&pcie1 {
+ perst-gpios = <&sysgpio 28 GPIO_ACTIVE_LOW>;
+ phys = <&pciephy1>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&pcie1_pins>;
+ status = "okay";
+};
+
+&pwm {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pwm_pins>;
+ status = "okay";
+};
+
+&pwmdac {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pwmdac_pins>;
+ status = "okay";
+};
+
&qspi {
#address-cells = <1>;
#size-cells = <0>;
@@ -336,6 +415,46 @@
};
};
+ i2srx_pins: i2srx-0 {
+ clk-sd-pins {
+ pinmux = <GPIOMUX(38, GPOUT_LOW,
+ GPOEN_DISABLE,
+ GPI_SYS_I2SRX_BCLK)>,
+ <GPIOMUX(63, GPOUT_LOW,
+ GPOEN_DISABLE,
+ GPI_SYS_I2SRX_LRCK)>,
+ <GPIOMUX(38, GPOUT_LOW,
+ GPOEN_DISABLE,
+ GPI_SYS_I2STX1_BCLK)>,
+ <GPIOMUX(63, GPOUT_LOW,
+ GPOEN_DISABLE,
+ GPI_SYS_I2STX1_LRCK)>,
+ <GPIOMUX(61, GPOUT_LOW,
+ GPOEN_DISABLE,
+ GPI_SYS_I2SRX_SDIN0)>;
+ input-enable;
+ };
+ };
+
+ i2stx1_pins: i2stx1-0 {
+ sd-pins {
+ pinmux = <GPIOMUX(44, GPOUT_SYS_I2STX1_SDO0,
+ GPOEN_ENABLE,
+ GPI_NONE)>;
+ bias-disable;
+ input-disable;
+ };
+ };
+
+ mclk_ext_pins: mclk-ext-0 {
+ mclk-ext-pins {
+ pinmux = <GPIOMUX(4, GPOUT_LOW,
+ GPOEN_DISABLE,
+ GPI_SYS_MCLK_EXT)>;
+ input-enable;
+ };
+ };
+
mmc0_pins: mmc0-0 {
rst-pins {
pinmux = <GPIOMUX(62, GPOUT_SYS_SDIO0_RST,
@@ -400,6 +519,86 @@
slew-rate = <0>;
};
};
+
+ pcie0_pins: pcie0-0 {
+ clkreq-pins {
+ pinmux = <GPIOMUX(27, GPOUT_LOW,
+ GPOEN_DISABLE,
+ GPI_NONE)>;
+ bias-pull-down;
+ drive-strength = <2>;
+ input-enable;
+ input-schmitt-disable;
+ slew-rate = <0>;
+ };
+
+ wake-pins {
+ pinmux = <GPIOMUX(32, GPOUT_LOW,
+ GPOEN_DISABLE,
+ GPI_NONE)>;
+ bias-pull-up;
+ drive-strength = <2>;
+ input-enable;
+ input-schmitt-disable;
+ slew-rate = <0>;
+ };
+ };
+
+ pcie1_pins: pcie1-0 {
+ clkreq-pins {
+ pinmux = <GPIOMUX(29, GPOUT_LOW,
+ GPOEN_DISABLE,
+ GPI_NONE)>;
+ bias-pull-down;
+ drive-strength = <2>;
+ input-enable;
+ input-schmitt-disable;
+ slew-rate = <0>;
+ };
+
+ wake-pins {
+ pinmux = <GPIOMUX(21, GPOUT_LOW,
+ GPOEN_DISABLE,
+ GPI_NONE)>;
+ bias-pull-up;
+ drive-strength = <2>;
+ input-enable;
+ input-schmitt-disable;
+ slew-rate = <0>;
+ };
+ };
+
+ pwm_pins: pwm-0 {
+ pwm-pins {
+ pinmux = <GPIOMUX(46, GPOUT_SYS_PWM_CHANNEL0,
+ GPOEN_SYS_PWM0_CHANNEL0,
+ GPI_NONE)>,
+ <GPIOMUX(59, GPOUT_SYS_PWM_CHANNEL1,
+ GPOEN_SYS_PWM0_CHANNEL1,
+ GPI_NONE)>;
+ bias-disable;
+ drive-strength = <12>;
+ input-disable;
+ input-schmitt-disable;
+ slew-rate = <0>;
+ };
+ };
+
+ pwmdac_pins: pwmdac-0 {
+ pwmdac-pins {
+ pinmux = <GPIOMUX(33, GPOUT_SYS_PWMDAC_LEFT,
+ GPOEN_ENABLE,
+ GPI_NONE)>,
+ <GPIOMUX(34, GPOUT_SYS_PWMDAC_RIGHT,
+ GPOEN_ENABLE,
+ GPI_NONE)>;
+ bias-disable;
+ drive-strength = <2>;
+ input-disable;
+ input-schmitt-disable;
+ slew-rate = <0>;
+ };
+ };
spi0_pins: spi0-0 {
mosi-pins {
--- a/arch/riscv/boot/dts/starfive/jh7110.dtsi
+++ b/arch/riscv/boot/dts/starfive/jh7110.dtsi
@@ -244,6 +244,7 @@
clock-output-names = "dvp_clk";
#clock-cells = <0>;
};
+
gmac0_rgmii_rxin: gmac0-rgmii-rxin-clock {
compatible = "fixed-clock";
clock-output-names = "gmac0_rgmii_rxin";
@@ -512,6 +513,43 @@
status = "disabled";
};
+ pwmdac: pwmdac@100b0000 {
+ compatible = "starfive,jh7110-pwmdac";
+ reg = <0x0 0x100b0000 0x0 0x1000>;
+ clocks = <&syscrg JH7110_SYSCLK_PWMDAC_APB>,
+ <&syscrg JH7110_SYSCLK_PWMDAC_CORE>;
+ clock-names = "apb", "core";
+ resets = <&syscrg JH7110_SYSRST_PWMDAC_APB>;
+ dmas = <&dma 22>;
+ dma-names = "tx";
+ #sound-dai-cells = <0>;
+ status = "disabled";
+ };
+
+ i2srx: i2s@100e0000 {
+ compatible = "starfive,jh7110-i2srx";
+ reg = <0x0 0x100e0000 0x0 0x1000>;
+ clocks = <&syscrg JH7110_SYSCLK_I2SRX_BCLK_MST>,
+ <&syscrg JH7110_SYSCLK_I2SRX_APB>,
+ <&syscrg JH7110_SYSCLK_MCLK>,
+ <&syscrg JH7110_SYSCLK_MCLK_INNER>,
+ <&mclk_ext>,
+ <&syscrg JH7110_SYSCLK_I2SRX_BCLK>,
+ <&syscrg JH7110_SYSCLK_I2SRX_LRCK>,
+ <&i2srx_bclk_ext>,
+ <&i2srx_lrck_ext>;
+ clock-names = "i2sclk", "apb", "mclk",
+ "mclk_inner", "mclk_ext", "bclk",
+ "lrck", "bclk_ext", "lrck_ext";
+ resets = <&syscrg JH7110_SYSRST_I2SRX_APB>,
+ <&syscrg JH7110_SYSRST_I2SRX_BCLK>;
+ dmas = <0>, <&dma 24>;
+ dma-names = "tx", "rx";
+ starfive,syscon = <&sys_syscon 0x18 0x2>;
+ #sound-dai-cells = <0>;
+ status = "disabled";
+ };
+
usb0: usb@10100000 {
compatible = "starfive,jh7110-usb";
ranges = <0x0 0x0 0x10100000 0x100000>;
@@ -736,6 +774,56 @@
status = "disabled";
};
+ i2stx0: i2s@120b0000 {
+ compatible = "starfive,jh7110-i2stx0";
+ reg = <0x0 0x120b0000 0x0 0x1000>;
+ clocks = <&syscrg JH7110_SYSCLK_I2STX0_BCLK_MST>,
+ <&syscrg JH7110_SYSCLK_I2STX0_APB>,
+ <&syscrg JH7110_SYSCLK_MCLK>,
+ <&syscrg JH7110_SYSCLK_MCLK_INNER>,
+ <&mclk_ext>;
+ clock-names = "i2sclk", "apb", "mclk",
+ "mclk_inner","mclk_ext";
+ resets = <&syscrg JH7110_SYSRST_I2STX0_APB>,
+ <&syscrg JH7110_SYSRST_I2STX0_BCLK>;
+ dmas = <&dma 47>;
+ dma-names = "tx";
+ #sound-dai-cells = <0>;
+ status = "disabled";
+ };
+
+ i2stx1: i2s@120c0000 {
+ compatible = "starfive,jh7110-i2stx1";
+ reg = <0x0 0x120c0000 0x0 0x1000>;
+ clocks = <&syscrg JH7110_SYSCLK_I2STX1_BCLK_MST>,
+ <&syscrg JH7110_SYSCLK_I2STX1_APB>,
+ <&syscrg JH7110_SYSCLK_MCLK>,
+ <&syscrg JH7110_SYSCLK_MCLK_INNER>,
+ <&mclk_ext>,
+ <&syscrg JH7110_SYSCLK_I2STX1_BCLK>,
+ <&syscrg JH7110_SYSCLK_I2STX1_LRCK>,
+ <&i2stx_bclk_ext>,
+ <&i2stx_lrck_ext>;
+ clock-names = "i2sclk", "apb", "mclk",
+ "mclk_inner", "mclk_ext", "bclk",
+ "lrck", "bclk_ext", "lrck_ext";
+ resets = <&syscrg JH7110_SYSRST_I2STX1_APB>,
+ <&syscrg JH7110_SYSRST_I2STX1_BCLK>;
+ dmas = <&dma 48>;
+ dma-names = "tx";
+ #sound-dai-cells = <0>;
+ status = "disabled";
+ };
+
+ pwm: pwm@120d0000 {
+ compatible = "starfive,jh7110-pwm", "opencores,pwm-v1";
+ reg = <0x0 0x120d0000 0x0 0x10000>;
+ clocks = <&syscrg JH7110_SYSCLK_PWM_APB>;
+ resets = <&syscrg JH7110_SYSRST_PWM_APB>;
+ #pwm-cells = <3>;
+ status = "disabled";
+ };
+
sfctemp: temperature-sensor@120e0000 {
compatible = "starfive,jh7110-temp";
reg = <0x0 0x120e0000 0x0 0x10000>;
@@ -811,6 +899,26 @@
#gpio-cells = <2>;
};
+ timer@13050000 {
+ compatible = "starfive,jh7110-timer";
+ reg = <0x0 0x13050000 0x0 0x10000>;
+ interrupts = <69>, <70>, <71>, <72>;
+ clocks = <&syscrg JH7110_SYSCLK_TIMER_APB>,
+ <&syscrg JH7110_SYSCLK_TIMER0>,
+ <&syscrg JH7110_SYSCLK_TIMER1>,
+ <&syscrg JH7110_SYSCLK_TIMER2>,
+ <&syscrg JH7110_SYSCLK_TIMER3>;
+ clock-names = "apb", "ch0", "ch1",
+ "ch2", "ch3";
+ resets = <&syscrg JH7110_SYSRST_TIMER_APB>,
+ <&syscrg JH7110_SYSRST_TIMER0>,
+ <&syscrg JH7110_SYSRST_TIMER1>,
+ <&syscrg JH7110_SYSRST_TIMER2>,
+ <&syscrg JH7110_SYSRST_TIMER3>;
+ reset-names = "apb", "ch0", "ch1",
+ "ch2", "ch3";
+ };
+
watchdog@13070000 {
compatible = "starfive,jh7110-wdt";
reg = <0x0 0x13070000 0x0 0x10000>;
@@ -1011,6 +1119,32 @@
#power-domain-cells = <1>;
};
+ csi2rx: csi-bridge@19800000 {
+ compatible = "starfive,jh7110-csi2rx";
+ reg = <0x0 0x19800000 0x0 0x10000>;
+ clocks = <&ispcrg JH7110_ISPCLK_VIN_SYS>,
+ <&ispcrg JH7110_ISPCLK_VIN_APB>,
+ <&ispcrg JH7110_ISPCLK_VIN_PIXEL_IF0>,
+ <&ispcrg JH7110_ISPCLK_VIN_PIXEL_IF1>,
+ <&ispcrg JH7110_ISPCLK_VIN_PIXEL_IF2>,
+ <&ispcrg JH7110_ISPCLK_VIN_PIXEL_IF3>;
+ clock-names = "sys_clk", "p_clk",
+ "pixel_if0_clk", "pixel_if1_clk",
+ "pixel_if2_clk", "pixel_if3_clk";
+ resets = <&ispcrg JH7110_ISPRST_VIN_SYS>,
+ <&ispcrg JH7110_ISPRST_VIN_APB>,
+ <&ispcrg JH7110_ISPRST_VIN_PIXEL_IF0>,
+ <&ispcrg JH7110_ISPRST_VIN_PIXEL_IF1>,
+ <&ispcrg JH7110_ISPRST_VIN_PIXEL_IF2>,
+ <&ispcrg JH7110_ISPRST_VIN_PIXEL_IF3>;
+ reset-names = "sys", "reg_bank",
+ "pixel_if0", "pixel_if1",
+ "pixel_if2", "pixel_if3";
+ phys = <&csi_phy>;
+ phy-names = "dphy";
+ status = "disabled";
+ };
+
ispcrg: clock-controller@19810000 {
compatible = "starfive,jh7110-ispcrg";
reg = <0x0 0x19810000 0x0 0x10000>;
@@ -1028,6 +1162,19 @@
power-domains = <&pwrc JH7110_PD_ISP>;
};
+ csi_phy: phy@19820000 {
+ compatible = "starfive,jh7110-dphy-rx";
+ reg = <0x0 0x19820000 0x0 0x10000>;
+ clocks = <&ispcrg JH7110_ISPCLK_M31DPHY_CFG_IN>,
+ <&ispcrg JH7110_ISPCLK_M31DPHY_REF_IN>,
+ <&ispcrg JH7110_ISPCLK_M31DPHY_TX_ESC_LAN0>;
+ clock-names = "cfg", "ref", "tx";
+ resets = <&ispcrg JH7110_ISPRST_M31DPHY_HW>,
+ <&ispcrg JH7110_ISPRST_M31DPHY_B09_AON>;
+ power-domains = <&aon_syscon JH7110_AON_PD_DPHY_RX>;
+ #phy-cells = <0>;
+ };
+
voutcrg: clock-controller@295c0000 {
compatible = "starfive,jh7110-voutcrg";
reg = <0x0 0x295c0000 0x0 0x10000>;
@@ -1045,5 +1192,91 @@
#reset-cells = <1>;
power-domains = <&pwrc JH7110_PD_VOUT>;
};
+
+ pcie0: pcie@940000000 {
+ compatible = "starfive,jh7110-pcie";
+ reg = <0x9 0x40000000 0x0 0x1000000>,
+ <0x0 0x2b000000 0x0 0x100000>;
+ reg-names = "cfg", "apb";
+ linux,pci-domain = <0>;
+ #address-cells = <3>;
+ #size-cells = <2>;
+ #interrupt-cells = <1>;
+ ranges = <0x82000000 0x0 0x30000000 0x0 0x30000000 0x0 0x08000000>,
+ <0xc3000000 0x9 0x00000000 0x9 0x00000000 0x0 0x40000000>;
+ interrupts = <56>;
+ interrupt-map-mask = <0x0 0x0 0x0 0x7>;
+ interrupt-map = <0x0 0x0 0x0 0x1 &pcie_intc0 0x1>,
+ <0x0 0x0 0x0 0x2 &pcie_intc0 0x2>,
+ <0x0 0x0 0x0 0x3 &pcie_intc0 0x3>,
+ <0x0 0x0 0x0 0x4 &pcie_intc0 0x4>;
+ msi-controller;
+ device_type = "pci";
+ starfive,stg-syscon = <&stg_syscon>;
+ bus-range = <0x0 0xff>;
+ clocks = <&syscrg JH7110_SYSCLK_NOC_BUS_STG_AXI>,
+ <&stgcrg JH7110_STGCLK_PCIE0_TL>,
+ <&stgcrg JH7110_STGCLK_PCIE0_AXI_MST0>,
+ <&stgcrg JH7110_STGCLK_PCIE0_APB>;
+ clock-names = "noc", "tl", "axi_mst0", "apb";
+ resets = <&stgcrg JH7110_STGRST_PCIE0_AXI_MST0>,
+ <&stgcrg JH7110_STGRST_PCIE0_AXI_SLV0>,
+ <&stgcrg JH7110_STGRST_PCIE0_AXI_SLV>,
+ <&stgcrg JH7110_STGRST_PCIE0_BRG>,
+ <&stgcrg JH7110_STGRST_PCIE0_CORE>,
+ <&stgcrg JH7110_STGRST_PCIE0_APB>;
+ reset-names = "mst0", "slv0", "slv", "brg",
+ "core", "apb";
+ status = "disabled";
+
+ pcie_intc0: interrupt-controller {
+ #address-cells = <0>;
+ #interrupt-cells = <1>;
+ interrupt-controller;
+ };
+ };
+
+ pcie1: pcie@9c0000000 {
+ compatible = "starfive,jh7110-pcie";
+ reg = <0x9 0xc0000000 0x0 0x1000000>,
+ <0x0 0x2c000000 0x0 0x100000>;
+ reg-names = "cfg", "apb";
+ linux,pci-domain = <1>;
+ #address-cells = <3>;
+ #size-cells = <2>;
+ #interrupt-cells = <1>;
+ ranges = <0x82000000 0x0 0x38000000 0x0 0x38000000 0x0 0x08000000>,
+ <0xc3000000 0x9 0x80000000 0x9 0x80000000 0x0 0x40000000>;
+ interrupts = <57>;
+ interrupt-map-mask = <0x0 0x0 0x0 0x7>;
+ interrupt-map = <0x0 0x0 0x0 0x1 &pcie_intc1 0x1>,
+ <0x0 0x0 0x0 0x2 &pcie_intc1 0x2>,
+ <0x0 0x0 0x0 0x3 &pcie_intc1 0x3>,
+ <0x0 0x0 0x0 0x4 &pcie_intc1 0x4>;
+ msi-controller;
+ device_type = "pci";
+ starfive,stg-syscon = <&stg_syscon>;
+ bus-range = <0x0 0xff>;
+ clocks = <&syscrg JH7110_SYSCLK_NOC_BUS_STG_AXI>,
+ <&stgcrg JH7110_STGCLK_PCIE1_TL>,
+ <&stgcrg JH7110_STGCLK_PCIE1_AXI_MST0>,
+ <&stgcrg JH7110_STGCLK_PCIE1_APB>;
+ clock-names = "noc", "tl", "axi_mst0", "apb";
+ resets = <&stgcrg JH7110_STGRST_PCIE1_AXI_MST0>,
+ <&stgcrg JH7110_STGRST_PCIE1_AXI_SLV0>,
+ <&stgcrg JH7110_STGRST_PCIE1_AXI_SLV>,
+ <&stgcrg JH7110_STGRST_PCIE1_BRG>,
+ <&stgcrg JH7110_STGRST_PCIE1_CORE>,
+ <&stgcrg JH7110_STGRST_PCIE1_APB>;
+ reset-names = "mst0", "slv0", "slv", "brg",
+ "core", "apb";
+ status = "disabled";
+
+ pcie_intc1: interrupt-controller {
+ #address-cells = <0>;
+ #interrupt-cells = <1>;
+ interrupt-controller;
+ };
+ };
};
};

View File

@ -0,0 +1,147 @@
From ae7b57a0c69953f5ec06a378aedeed4c86637998 Mon Sep 17 00:00:00 2001
From: Hal Feng <hal.feng@starfivetech.com>
Date: Tue, 11 Apr 2023 16:25:57 +0800
Subject: [PATCH 049/116] MAINTAINERS: Update all StarFive entries
Merge all StarFive maintainers changes together.
Signed-off-by: Hal Feng <hal.feng@starfivetech.com>
---
MAINTAINERS | 61 +++++++++++++++++++++++++++++++++++++++++++++++++----
1 file changed, 57 insertions(+), 4 deletions(-)
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -7053,6 +7053,14 @@ T: git git://anongit.freedesktop.org/drm
F: Documentation/devicetree/bindings/display/rockchip/
F: drivers/gpu/drm/rockchip/
+DRM DRIVERS FOR STARFIVE
+M: Keith Zhao <keith.zhao@starfivetech.com>
+L: dri-devel@lists.freedesktop.org
+S: Maintained
+T: git git://anongit.freedesktop.org/drm/drm-misc
+F: Documentation/devicetree/bindings/display/starfive/
+F: drivers/gpu/drm/verisilicon/
+
DRM DRIVERS FOR STI
M: Alain Volmat <alain.volmat@foss.st.com>
L: dri-devel@lists.freedesktop.org
@@ -16016,6 +16024,13 @@ F: Documentation/i2c/busses/i2c-ocores.r
F: drivers/i2c/busses/i2c-ocores.c
F: include/linux/platform_data/i2c-ocores.h
+OPENCORES PWM DRIVER
+M: William Qiu <william.qiu@starfivetech.com>
+M: Hal Feng <hal.feng@starfivetech.com>
+S: Supported
+F: Documentation/devicetree/bindings/pwm/opencores,pwm.yaml
+F: drivers/pwm/pwm-ocores.c
+
OPENRISC ARCHITECTURE
M: Jonas Bonn <jonas@southpole.se>
M: Stefan Kristiansson <stefan.kristiansson@saunalahti.fi>
@@ -16427,6 +16442,14 @@ S: Maintained
F: Documentation/devicetree/bindings/pci/layerscape-pcie-gen4.txt
F: drivers/pci/controller/mobiveil/pcie-layerscape-gen4.c
+PCI DRIVER FOR PLDA PCIE IP
+M: Daire McNamara <daire.mcnamara@microchip.com>
+M: Kevin Xie <kevin.xie@starfivetech.com>
+L: linux-pci@vger.kernel.org
+S: Maintained
+F: Documentation/devicetree/bindings/pci/plda,*
+F: drivers/pci/controller/plda/*plda*
+
PCI DRIVER FOR RENESAS R-CAR
M: Marek Vasut <marek.vasut+renesas@gmail.com>
M: Yoshihiro Shimoda <yoshihiro.shimoda.uh@renesas.com>
@@ -16658,7 +16681,7 @@ M: Daire McNamara <daire.mcnamara@microc
L: linux-pci@vger.kernel.org
S: Supported
F: Documentation/devicetree/bindings/pci/microchip*
-F: drivers/pci/controller/*microchip*
+F: drivers/pci/controller/plda/*microchip*
PCIE DRIVER FOR QUALCOMM MSM
M: Manivannan Sadhasivam <manivannan.sadhasivam@linaro.org>
@@ -16682,6 +16705,13 @@ S: Maintained
F: Documentation/devicetree/bindings/pci/socionext,uniphier-pcie*
F: drivers/pci/controller/dwc/pcie-uniphier*
+PCIE DRIVER FOR STARFIVE JH71x0
+M: Kevin Xie <kevin.xie@starfivetech.com>
+L: linux-pci@vger.kernel.org
+S: Maintained
+F: Documentation/devicetree/bindings/pci/starfive*
+F: drivers/pci/controller/plda/pcie-starfive.c
+
PCIE DRIVER FOR ST SPEAR13XX
M: Pratyush Anand <pratyush.anand@gmail.com>
L: linux-pci@vger.kernel.org
@@ -18454,7 +18484,7 @@ F: drivers/char/hw_random/mpfs-rng.c
F: drivers/clk/microchip/clk-mpfs*.c
F: drivers/i2c/busses/i2c-microchip-corei2c.c
F: drivers/mailbox/mailbox-mpfs.c
-F: drivers/pci/controller/pcie-microchip-host.c
+F: drivers/pci/controller/plda/pcie-microchip-host.c
F: drivers/pwm/pwm-microchip-core.c
F: drivers/reset/reset-mpfs.c
F: drivers/rtc/rtc-mpfs.c
@@ -20435,6 +20465,15 @@ M: Ion Badulescu <ionut@badula.org>
S: Odd Fixes
F: drivers/net/ethernet/adaptec/starfire*
+STARFIVE CAMERA SUBSYSTEM DRIVER
+M: Jack Zhu <jack.zhu@starfivetech.com>
+M: Changhuang Liang <changhuang.liang@starfivetech.com>
+L: linux-media@vger.kernel.org
+S: Maintained
+F: Documentation/admin-guide/media/starfive_camss.rst
+F: Documentation/devicetree/bindings/media/starfive,jh7110-camss.yaml
+F: drivers/staging/media/starfive/camss
+
STARFIVE CRYPTO DRIVER
M: Jia Jie Ho <jiajie.ho@starfivetech.com>
M: William Qiu <william.qiu@starfivetech.com>
@@ -20473,6 +20512,13 @@ S: Supported
F: Documentation/devicetree/bindings/clock/starfive,jh7110-pll.yaml
F: drivers/clk/starfive/clk-starfive-jh7110-pll.c
+STARFIVE JH7110 PWMDAC DRIVER
+M: Hal Feng <hal.feng@starfivetech.com>
+M: Xingyu Wu <xingyu.wu@starfivetech.com>
+S: Supported
+F: Documentation/devicetree/bindings/sound/starfive,jh7110-pwmdac.yaml
+F: sound/soc/starfive/jh7110_pwmdac.c
+
STARFIVE JH7110 SYSCON
M: William Qiu <william.qiu@starfivetech.com>
M: Xingyu Wu <xingyu.wu@starfivetech.com>
@@ -20520,9 +20566,10 @@ F: drivers/usb/cdns3/cdns3-starfive.c
STARFIVE JH71XX PMU CONTROLLER DRIVER
M: Walker Chen <walker.chen@starfivetech.com>
+M: Changhuang Liang <changhuang.liang@starfivetech.com>
S: Supported
F: Documentation/devicetree/bindings/power/starfive*
-F: drivers/pmdomain/starfive/jh71xx-pmu.c
+F: drivers/pmdomain/starfive/
F: include/dt-bindings/power/starfive,jh7110-pmu.h
STARFIVE SOC DRIVERS
@@ -20530,7 +20577,13 @@ M: Conor Dooley <conor@kernel.org>
S: Maintained
T: git https://git.kernel.org/pub/scm/linux/kernel/git/conor/linux.git/
F: Documentation/devicetree/bindings/soc/starfive/
-F: drivers/soc/starfive/
+
+STARFIVE JH7110 TIMER DRIVER
+M: Samin Guo <samin.guo@starfivetech.com>
+M: Xingyu Wu <xingyu.wu@starfivetech.com>
+S: Supported
+F: Documentation/devicetree/bindings/timer/starfive,jh7110-timer.yaml
+F: drivers/clocksource/timer-jh7110.c
STARFIVE TRNG DRIVER
M: Jia Jie Ho <jiajie.ho@starfivetech.com>

View File

@ -0,0 +1,64 @@
From e394195396995456ef98f52ac123c0cb64687748 Mon Sep 17 00:00:00 2001
From: William Qiu <william.qiu@starfivetech.com>
Date: Mon, 9 Oct 2023 10:59:03 +0800
Subject: [PATCH 050/116] mmc: starfive: Change the voltage to adapt to JH7110
EVB
Change the voltage, so the driver can adapt to JH7110 EVB.
Signed-off-by: William Qiu <william.qiu@starfivetech.com>
Signed-off-by: Hal Feng <hal.feng@starfivetech.com>
---
drivers/mmc/host/dw_mmc-starfive.c | 30 ++++++++++++++++++++++++++++++
1 file changed, 30 insertions(+)
--- a/drivers/mmc/host/dw_mmc-starfive.c
+++ b/drivers/mmc/host/dw_mmc-starfive.c
@@ -8,6 +8,7 @@
#include <linux/bitfield.h>
#include <linux/clk.h>
#include <linux/delay.h>
+#include <linux/gpio.h>
#include <linux/mfd/syscon.h>
#include <linux/mmc/host.h>
#include <linux/module.h>
@@ -95,10 +96,39 @@ out:
return ret;
}
+static int dw_mci_starfive_switch_voltage(struct mmc_host *mmc, struct mmc_ios *ios)
+{
+
+ struct dw_mci_slot *slot = mmc_priv(mmc);
+ struct dw_mci *host = slot->host;
+ u32 ret;
+
+ if (ios->signal_voltage == MMC_SIGNAL_VOLTAGE_330)
+ ret = gpio_direction_output(25, 0);
+ else if (ios->signal_voltage == MMC_SIGNAL_VOLTAGE_180)
+ ret = gpio_direction_output(25, 1);
+ if (ret)
+ return ret;
+
+ if (!IS_ERR(mmc->supply.vqmmc)) {
+ ret = mmc_regulator_set_vqmmc(mmc, ios);
+ if (ret < 0) {
+ dev_err(host->dev, "Regulator set error %d\n", ret);
+ return ret;
+ }
+ }
+
+ /* We should delay 20ms wait for timing setting finished. */
+ mdelay(20);
+
+ return 0;
+}
+
static const struct dw_mci_drv_data starfive_data = {
.common_caps = MMC_CAP_CMD23,
.set_ios = dw_mci_starfive_set_ios,
.execute_tuning = dw_mci_starfive_execute_tuning,
+ .switch_voltage = dw_mci_starfive_switch_voltage,
};
static const struct of_device_id dw_mci_starfive_match[] = {

View File

@ -0,0 +1,60 @@
From 2cd3e51cb76d49d8db6274ebdc1ba1eb5c872f10 Mon Sep 17 00:00:00 2001
From: "ziv.xu" <ziv.xu@starfivetech.com>
Date: Sun, 4 Feb 2024 10:35:24 +0800
Subject: [PATCH 051/116] spi: spl022: Get and deassert reset in probe()
This fix spi1~6 communication time out.
Signed-off-by: ziv.xu <ziv.xu@starfivetech.com>
Signed-off-by: Hal Feng <hal.feng@starfivetech.com>
---
drivers/spi/spi-pl022.c | 17 +++++++++++++++++
1 file changed, 17 insertions(+)
--- a/drivers/spi/spi-pl022.c
+++ b/drivers/spi/spi-pl022.c
@@ -33,6 +33,7 @@
#include <linux/pm_runtime.h>
#include <linux/of.h>
#include <linux/pinctrl/consumer.h>
+#include <linux/reset.h>
/*
* This macro is used to define some register default values.
@@ -370,6 +371,7 @@ struct pl022 {
resource_size_t phybase;
void __iomem *virtbase;
struct clk *clk;
+ struct reset_control *rst;
struct spi_controller *host;
struct pl022_ssp_controller *host_info;
/* Message per-transfer pump */
@@ -2181,6 +2183,19 @@ static int pl022_probe(struct amba_devic
goto err_no_clk_en;
}
+ pl022->rst = devm_reset_control_get(&adev->dev, NULL);
+ if (IS_ERR(pl022->rst)) {
+ status = PTR_ERR(pl022->rst);
+ dev_err(&adev->dev, "could not retrieve SSP/SPI bus reset\n");
+ goto err_no_rst;
+ }
+
+ status = reset_control_deassert(pl022->rst);
+ if (status) {
+ dev_err(&adev->dev, "could not deassert SSP/SPI bus reset\n");
+ goto err_no_rst_de;
+ }
+
/* Initialize transfer pump */
tasklet_init(&pl022->pump_transfers, pump_transfers,
(unsigned long)pl022);
@@ -2240,6 +2255,8 @@ static int pl022_probe(struct amba_devic
if (platform_info->enable_dma)
pl022_dma_remove(pl022);
err_no_irq:
+ err_no_rst_de:
+ err_no_rst:
clk_disable_unprepare(pl022->clk);
err_no_clk_en:
err_no_clk:

View File

@ -0,0 +1,30 @@
From 9cc8de0cdc1600f460f618e342e1f524adad07c4 Mon Sep 17 00:00:00 2001
From: Xingyu Wu <xingyu.wu@starfivetech.com>
Date: Wed, 21 Feb 2024 10:23:48 +0800
Subject: [PATCH 052/116] ASoC: dwc: i2s: Fix getting platform data error for
StarFive JH7110
JH7110 need to use a DT specific function to get the platform data,
otherwise, it fails in probe().
Fixes: 9c97790a07dc ("ASoC: dwc: Fix non-DT instantiation")
Signed-off-by: Xingyu Wu <xingyu.wu@starfivetech.com>
Signed-off-by: Hal Feng <hal.feng@starfivetech.com>
---
sound/soc/dwc/dwc-i2s.c | 4 ++++
1 file changed, 4 insertions(+)
--- a/sound/soc/dwc/dwc-i2s.c
+++ b/sound/soc/dwc/dwc-i2s.c
@@ -917,7 +917,11 @@ static int jh7110_i2stx0_clk_cfg(struct
static int dw_i2s_probe(struct platform_device *pdev)
{
+#ifdef CONFIG_OF
+ const struct i2s_platform_data *pdata = of_device_get_match_data(&pdev->dev);
+#else
const struct i2s_platform_data *pdata = pdev->dev.platform_data;
+#endif
struct dw_i2s_dev *dev;
struct resource *res;
int ret, irq;

View File

@ -0,0 +1,67 @@
From 1be9bd37fdb5f50162dba0158e1fee295ebca9aa Mon Sep 17 00:00:00 2001
From: Xingyu Wu <xingyu.wu@starfivetech.com>
Date: Tue, 17 Oct 2023 17:22:52 +0800
Subject: [PATCH 053/116] ASoC: dwc: i2s: Add RX master support for StarFive
JH7110 SoC
Add JH7110 I2S RX master support, so the PDM can work on JH7110
EVB board.
Signed-off-by: Xingyu Wu <xingyu.wu@starfivetech.com>
Signed-off-by: Hal Feng <hal.feng@starfivetech.com>
---
sound/soc/dwc/dwc-i2s.c | 31 +++++++++++++++++++++++++++++++
1 file changed, 31 insertions(+)
--- a/sound/soc/dwc/dwc-i2s.c
+++ b/sound/soc/dwc/dwc-i2s.c
@@ -906,6 +906,27 @@ static int jh7110_i2srx_crg_init(struct
return jh7110_i2s_crg_slave_init(dev);
}
+/* Special syscon initialization about RX channel with master mode on JH7110 SoC */
+static int jh7110_i2srx_mst_crg_init(struct dw_i2s_dev *dev)
+{
+ struct regmap *regmap;
+ unsigned int args[5];
+
+ regmap = syscon_regmap_lookup_by_phandle_args(dev->dev->of_node,
+ "starfive,syscon",
+ 5, args);
+ if (IS_ERR(regmap))
+ return dev_err_probe(dev->dev, PTR_ERR(regmap), "getting the regmap failed\n");
+
+ /* Enable I2Srx with syscon register, args[0]: offset, args[1]: mask */
+ regmap_update_bits(regmap, args[0], args[1], args[1]);
+
+ /* Change I2Srx source (PDM) with syscon register, args[0]: offset, args[1]: mask */
+ regmap_update_bits(regmap, args[2], args[3], args[4]);
+
+ return jh7110_i2s_crg_master_init(dev);
+}
+
static int jh7110_i2stx0_clk_cfg(struct i2s_clk_config_data *config)
{
struct dw_i2s_dev *dev = container_of(config, struct dw_i2s_dev, config);
@@ -1086,11 +1107,21 @@ static const struct i2s_platform_data jh
.i2s_pd_init = jh7110_i2srx_crg_init,
};
+static const struct i2s_platform_data jh7110_i2srx_mst_data = {
+ .cap = DWC_I2S_RECORD | DW_I2S_MASTER,
+ .channel = TWO_CHANNEL_SUPPORT,
+ .snd_fmts = SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S32_LE,
+ .snd_rates = SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_11025 | SNDRV_PCM_RATE_16000,
+ .i2s_clk_cfg = jh7110_i2stx0_clk_cfg,
+ .i2s_pd_init = jh7110_i2srx_mst_crg_init,
+};
+
static const struct of_device_id dw_i2s_of_match[] = {
{ .compatible = "snps,designware-i2s", },
{ .compatible = "starfive,jh7110-i2stx0", .data = &jh7110_i2stx0_data, },
{ .compatible = "starfive,jh7110-i2stx1", .data = &jh7110_i2stx1_data,},
{ .compatible = "starfive,jh7110-i2srx", .data = &jh7110_i2srx_data,},
+ { .compatible = "starfive,jh7110-i2srx-master", .data = &jh7110_i2srx_mst_data,},
{},
};

View File

@ -0,0 +1,24 @@
From 1ec26ba377d8ae59cd09811ec78623a750a9c150 Mon Sep 17 00:00:00 2001
From: Hal Feng <hal.feng@starfivetech.com>
Date: Mon, 26 Feb 2024 11:35:44 +0800
Subject: [PATCH 054/116] pinctrl: starfive: jh7110: Unset .strict in
pinmux_ops
Allow simultaneous use of the same pin for GPIO and another function.
This feature is used in HDMI hot plug detect.
Signed-off-by: Hal Feng <hal.feng@starfivetech.com>
---
drivers/pinctrl/starfive/pinctrl-starfive-jh7110.c | 1 -
1 file changed, 1 deletion(-)
--- a/drivers/pinctrl/starfive/pinctrl-starfive-jh7110.c
+++ b/drivers/pinctrl/starfive/pinctrl-starfive-jh7110.c
@@ -327,7 +327,6 @@ static const struct pinmux_ops jh7110_pi
.get_function_name = pinmux_generic_get_function_name,
.get_function_groups = pinmux_generic_get_function_groups,
.set_mux = jh7110_set_mux,
- .strict = true,
};
static const u8 jh7110_drive_strength_mA[4] = { 2, 4, 8, 12 };

View File

@ -0,0 +1,22 @@
From 005549a2bd839335b0e3dc4152f00f642b524f07 Mon Sep 17 00:00:00 2001
From: Hal Feng <hal.feng@starfivetech.com>
Date: Sat, 7 Oct 2023 18:10:20 +0800
Subject: [PATCH 055/116] mm/pgtable-generic.c: Export symbol __pte_offset_map
So JH7110 vdec can call pte_offset_map() when it is built as a module.
Signed-off-by: Hal Feng <hal.feng@starfivetech.com>
---
mm/pgtable-generic.c | 1 +
1 file changed, 1 insertion(+)
--- a/mm/pgtable-generic.c
+++ b/mm/pgtable-generic.c
@@ -304,6 +304,7 @@ nomap:
rcu_read_unlock();
return NULL;
}
+EXPORT_SYMBOL(__pte_offset_map);
pte_t *pte_offset_map_nolock(struct mm_struct *mm, pmd_t *pmd,
unsigned long addr, spinlock_t **ptlp)

View File

@ -0,0 +1,728 @@
From cae7550054ca0cd940bbc1501ae5611f5d2957e6 Mon Sep 17 00:00:00 2001
From: Hal Feng <hal.feng@starfivetech.com>
Date: Wed, 20 Sep 2023 14:53:22 +0800
Subject: [PATCH 057/116] riscv: dts: starfive: Add JH7110 EVB expanded device
tree
Add JH7110 EVB expanded device tree.
The code is ported from tag JH7110_SDK_6.1_v5.11.3
Signed-off-by: Hal Feng <hal.feng@starfivetech.com>
---
arch/riscv/boot/dts/starfive/Makefile | 11 +-
.../starfive/jh7110-evb-can-pdm-pwmdac.dts | 102 ++++++++++++++++
.../dts/starfive/jh7110-evb-dvp-rgb2hdmi.dts | 37 ++++++
.../dts/starfive/jh7110-evb-i2s-ac108.dts | 72 ++++++++++++
.../dts/starfive/jh7110-evb-pcie-i2s-sd.dts | 111 ++++++++++++++++++
.../dts/starfive/jh7110-evb-spi-uart2.dts | 65 ++++++++++
.../starfive/jh7110-evb-uart1-rgb2hdmi.dts | 57 +++++++++
.../starfive/jh7110-evb-uart4-emmc-spdif.dts | 78 ++++++++++++
.../starfive/jh7110-evb-uart5-pwm-i2c-tdm.dts | 95 +++++++++++++++
.../dts/starfive/jh7110-evb-usbdevice.dts | 35 ++++++
10 files changed, 662 insertions(+), 1 deletion(-)
create mode 100644 arch/riscv/boot/dts/starfive/jh7110-evb-can-pdm-pwmdac.dts
create mode 100644 arch/riscv/boot/dts/starfive/jh7110-evb-dvp-rgb2hdmi.dts
create mode 100644 arch/riscv/boot/dts/starfive/jh7110-evb-i2s-ac108.dts
create mode 100644 arch/riscv/boot/dts/starfive/jh7110-evb-pcie-i2s-sd.dts
create mode 100644 arch/riscv/boot/dts/starfive/jh7110-evb-spi-uart2.dts
create mode 100644 arch/riscv/boot/dts/starfive/jh7110-evb-uart1-rgb2hdmi.dts
create mode 100644 arch/riscv/boot/dts/starfive/jh7110-evb-uart4-emmc-spdif.dts
create mode 100644 arch/riscv/boot/dts/starfive/jh7110-evb-uart5-pwm-i2c-tdm.dts
create mode 100644 arch/riscv/boot/dts/starfive/jh7110-evb-usbdevice.dts
--- a/arch/riscv/boot/dts/starfive/Makefile
+++ b/arch/riscv/boot/dts/starfive/Makefile
@@ -12,4 +12,13 @@ dtb-$(CONFIG_ARCH_STARFIVE) += jh7100-st
dtb-$(CONFIG_ARCH_STARFIVE) += jh7110-starfive-visionfive-2-v1.2a.dtb
dtb-$(CONFIG_ARCH_STARFIVE) += jh7110-starfive-visionfive-2-v1.3b.dtb
-dtb-$(CONFIG_ARCH_STARFIVE) += jh7110-evb.dtb
+dtb-$(CONFIG_ARCH_STARFIVE) += jh7110-evb.dtb \
+ jh7110-evb-pcie-i2s-sd.dtb \
+ jh7110-evb-spi-uart2.dtb \
+ jh7110-evb-uart4-emmc-spdif.dtb \
+ jh7110-evb-uart5-pwm-i2c-tdm.dtb \
+ jh7110-evb-dvp-rgb2hdmi.dtb \
+ jh7110-evb-can-pdm-pwmdac.dtb \
+ jh7110-evb-i2s-ac108.dtb \
+ jh7110-evb-usbdevice.dtb \
+ jh7110-evb-uart1-rgb2hdmi.dtb
--- /dev/null
+++ b/arch/riscv/boot/dts/starfive/jh7110-evb-can-pdm-pwmdac.dts
@@ -0,0 +1,102 @@
+// SPDX-License-Identifier: GPL-2.0 OR MIT
+/*
+ * Copyright (C) 2022 StarFive Technology Co., Ltd.
+ */
+
+/dts-v1/;
+#include "jh7110-evb.dtsi"
+
+/ {
+ model = "StarFive JH7110 EVB";
+ compatible = "starfive,jh7110-evb", "starfive,jh7110";
+
+ sound2: snd-card2 {
+ compatible = "simple-audio-card";
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ simple-audio-card,name = "StarFive-PDM-Sound-Card";
+ simple-audio-card,dai-link@0 {
+ reg = <0>;
+ format = "i2s";
+ bitclock-master = <&dailink_master>;
+ frame-master = <&dailink_master>;
+
+ dailink_master:cpu {
+ sound-dai = <&i2srx_mst>;
+ };
+
+ dailink_slave:codec {
+ sound-dai = <&pdm>;
+ };
+ };
+ };
+
+ pwmdac_codec: pwmdac-codec {
+ compatible = "linux,spdif-dit";
+ #sound-dai-cells = <0>;
+ };
+
+ sound3: snd-card3 {
+ compatible = "simple-audio-card";
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ simple-audio-card,name = "StarFive-PWMDAC-Sound-Card";
+ simple-audio-card,dai-link@0 {
+ reg = <0>;
+ format = "left_j";
+ bitclock-master = <&sndcpu0>;
+ frame-master = <&sndcpu0>;
+
+ sndcpu0: cpu {
+ sound-dai = <&pwmdac>;
+ };
+
+ codec {
+ sound-dai = <&pwmdac_codec>;
+ };
+ };
+ };
+};
+
+&mmc0 {
+ assigned-clocks = <&syscrg JH7110_SYSCLK_SDIO0_SDCARD>;
+ assigned-clock-rates = <50000000>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&sdcard0_pins>;
+ max-frequency = <100000000>;
+ card-detect-delay = <300>;
+ bus-width = <4>;
+ broken-cd;
+ post-power-on-delay-ms = <200>;
+ status = "okay";
+};
+
+&usb0 {
+ status = "okay";
+};
+
+&pcie1 {
+ status = "okay";
+};
+
+&can0 {
+ status = "okay";
+};
+
+&can1 {
+ status = "okay";
+};
+
+&i2srx_mst {
+ status = "okay";
+};
+
+&pwmdac {
+ status = "okay";
+};
+
+&pdm {
+ status = "okay";
+};
--- /dev/null
+++ b/arch/riscv/boot/dts/starfive/jh7110-evb-dvp-rgb2hdmi.dts
@@ -0,0 +1,37 @@
+// SPDX-License-Identifier: GPL-2.0 OR MIT
+/*
+ * Copyright (C) 2022 StarFive Technology Co., Ltd.
+ */
+
+/dts-v1/;
+#include "jh7110-evb.dtsi"
+
+/ {
+ model = "StarFive JH7110 EVB";
+ compatible = "starfive,jh7110-evb", "starfive,jh7110";
+};
+
+&vin_sysctl {
+ pinctrl-names = "default";
+ pinctrl-0 = <&dvp_pins>;
+};
+
+&rgb_output {
+ status = "okay";
+};
+
+&tda988x_pin {
+ status = "okay";
+};
+
+&dsi_output {
+ status = "disabled";
+};
+
+&mipi_dsi {
+ status = "disabled";
+};
+
+&mipi_dphy {
+ status = "disabled";
+};
--- /dev/null
+++ b/arch/riscv/boot/dts/starfive/jh7110-evb-i2s-ac108.dts
@@ -0,0 +1,72 @@
+// SPDX-License-Identifier: GPL-2.0 OR MIT
+/*
+ * Copyright (C) 2022 StarFive Technology Co., Ltd.
+ */
+
+/dts-v1/;
+#include "jh7110-evb.dtsi"
+
+/ {
+ model = "StarFive JH7110 EVB";
+ compatible = "starfive,jh7110-evb", "starfive,jh7110";
+
+ /* i2s + ac108 */
+ sound0: snd-card0 {
+ compatible = "simple-audio-card";
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ simple-audio-card,name = "StarFive-AC108-Sound-Card";
+ simple-audio-card,dai-link@0 {
+ reg = <0>;
+ format = "i2s";
+ bitclock-master = <&sndcodec1>;
+ frame-master = <&sndcodec1>;
+
+ widgets = "Microphone", "Mic Jack",
+ "Line", "Line In",
+ "Line", "Line Out",
+ "Speaker", "Speaker",
+ "Headphone", "Headphone Jack";
+ routing = "Headphone Jack", "HP_L",
+ "Headphone Jack", "HP_R",
+ "Speaker", "SPK_LP",
+ "Speaker", "SPK_LN",
+ "LINPUT1", "Mic Jack",
+ "LINPUT3", "Mic Jack",
+ "RINPUT1", "Mic Jack",
+ "RINPUT2", "Mic Jack";
+
+ cpu {
+ sound-dai = <&i2srx>;
+ };
+
+ sndcodec1: codec {
+ sound-dai = <&ac108>;
+ clocks = <&ac108_mclk>;
+ clock-names = "mclk";
+ };
+ };
+ };
+};
+
+&mmc0 {
+ assigned-clocks = <&syscrg JH7110_SYSCLK_SDIO0_SDCARD>;
+ assigned-clock-rates = <50000000>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&sdcard0_pins>;
+ max-frequency = <100000000>;
+ card-detect-delay = <300>;
+ bus-width = <4>;
+ broken-cd;
+ post-power-on-delay-ms = <200>;
+ status = "okay";
+};
+
+&i2c0 {
+ status = "okay";
+};
+
+&i2srx {
+ status = "okay";
+};
--- /dev/null
+++ b/arch/riscv/boot/dts/starfive/jh7110-evb-pcie-i2s-sd.dts
@@ -0,0 +1,111 @@
+// SPDX-License-Identifier: GPL-2.0 OR MIT
+/*
+ * Copyright (C) 2022 StarFive Technology Co., Ltd.
+ */
+
+/dts-v1/;
+#include "jh7110-evb.dtsi"
+
+/ {
+ model = "StarFive JH7110 EVB";
+ compatible = "starfive,jh7110-evb", "starfive,jh7110";
+
+ /* i2s + wm8960 */
+ sound6: snd-card6 {
+ compatible = "simple-audio-card";
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ simple-audio-card,name = "StarFive-WM8960-Sound-Card";
+ simple-audio-card,dai-link@0 {
+ reg = <0>;
+ status = "okay";
+ format = "i2s";
+ bitclock-master = <&sndcodec1>;
+ frame-master = <&sndcodec1>;
+
+ widgets = "Microphone", "Mic Jack",
+ "Line", "Line In",
+ "Line", "Line Out",
+ "Speaker", "Speaker",
+ "Headphone", "Headphone Jack";
+ routing = "Headphone Jack", "HP_L",
+ "Headphone Jack", "HP_R",
+ "Speaker", "SPK_LP",
+ "Speaker", "SPK_LN",
+ "LINPUT1", "Mic Jack",
+ "LINPUT3", "Mic Jack",
+ "RINPUT1", "Mic Jack",
+ "RINPUT2", "Mic Jack";
+ cpu0 {
+ sound-dai = <&i2srx>;
+ };
+ cpu1 {
+ sound-dai = <&i2stx1>;
+ };
+
+ sndcodec1:codec {
+ sound-dai = <&wm8960>;
+ clocks = <&wm8960_mclk>;
+ clock-names = "mclk";
+ };
+ };
+ };
+};
+
+&mmc0 {
+ assigned-clocks = <&syscrg JH7110_SYSCLK_SDIO0_SDCARD>;
+ assigned-clock-rates = <50000000>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&sdcard0_pins>;
+ max-frequency = <100000000>;
+ card-detect-delay = <300>;
+ bus-width = <4>;
+ broken-cd;
+ post-power-on-delay-ms = <200>;
+ status = "okay";
+};
+
+&pcie1 {
+ status = "okay";
+};
+
+&pcie0 {
+ status = "okay";
+};
+
+&uart3 {
+ status = "okay";
+};
+
+&i2c0 {
+ status = "okay";
+};
+
+&usb0 {
+ clocks = <&stgcrg JH7110_STGCLK_USB0_LPM>,
+ <&stgcrg JH7110_STGCLK_USB0_STB>,
+ <&stgcrg JH7110_STGCLK_USB0_APB>,
+ <&stgcrg JH7110_STGCLK_USB0_AXI>,
+ <&stgcrg JH7110_STGCLK_USB0_UTMI_APB>;
+ clock-names = "lpm", "stb", "apb", "axi", "utmi_apb";
+ resets = <&stgcrg JH7110_STGRST_USB0_PWRUP>,
+ <&stgcrg JH7110_STGRST_USB0_APB>,
+ <&stgcrg JH7110_STGRST_USB0_AXI>,
+ <&stgcrg JH7110_STGRST_USB0_UTMI_APB>;
+ reset-names = "pwrup", "apb", "axi", "utmi_apb";
+ dr_mode = "host"; /*host or peripheral*/
+ starfive,usb2-only;
+ pinctrl-names = "default";
+ pinctrl-0 = <&usb_pins>;
+ status = "okay";
+};
+
+&i2srx {
+ status = "okay";
+};
+
+&i2stx1 {
+ status = "okay";
+};
+
--- /dev/null
+++ b/arch/riscv/boot/dts/starfive/jh7110-evb-spi-uart2.dts
@@ -0,0 +1,65 @@
+// SPDX-License-Identifier: GPL-2.0 OR MIT
+/*
+ * Copyright (C) 2022 StarFive Technology Co., Ltd.
+ */
+
+/dts-v1/;
+#include "jh7110-evb.dtsi"
+
+/ {
+ model = "StarFive JH7110 EVB";
+ compatible = "starfive,jh7110-evb", "starfive,jh7110";
+};
+
+&mmc0 {
+ assigned-clocks = <&syscrg JH7110_SYSCLK_SDIO0_SDCARD>;
+ assigned-clock-rates = <50000000>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&sdcard0_pins>;
+ max-frequency = <100000000>;
+ card-detect-delay = <300>;
+ bus-width = <4>;
+ broken-cd;
+ post-power-on-delay-ms = <200>;
+ status = "okay";
+};
+
+&usb0 {
+ status = "okay";
+};
+
+&pcie1 {
+ status = "okay";
+};
+
+&uart2 {
+ status = "okay";
+};
+
+&spi0 {
+ status = "okay";
+};
+
+&spi1 {
+ status = "okay";
+};
+
+&spi2 {
+ status = "okay";
+};
+
+&spi3 {
+ status = "okay";
+};
+
+&spi4 {
+ status = "okay";
+};
+
+&spi5 {
+ status = "okay";
+};
+
+&spi6 {
+ status = "okay";
+};
--- /dev/null
+++ b/arch/riscv/boot/dts/starfive/jh7110-evb-uart1-rgb2hdmi.dts
@@ -0,0 +1,57 @@
+// SPDX-License-Identifier: GPL-2.0 OR MIT
+/*
+ * Copyright (C) 2022 StarFive Technology Co., Ltd.
+ */
+
+/dts-v1/;
+#include "jh7110-evb.dtsi"
+
+/ {
+ model = "StarFive JH7110 EVB";
+ compatible = "starfive,jh7110-evb", "starfive,jh7110";
+};
+
+&mmc0 {
+ assigned-clocks = <&syscrg JH7110_SYSCLK_SDIO0_SDCARD>;
+ assigned-clock-rates = <50000000>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&sdcard0_pins>;
+ max-frequency = <100000000>;
+ card-detect-delay = <300>;
+ bus-width = <4>;
+ broken-cd;
+ post-power-on-delay-ms = <200>;
+ status = "okay";
+};
+
+&usb0 {
+ status = "okay";
+};
+
+&pcie1 {
+ status = "okay";
+};
+
+&uart1 {
+ status = "okay";
+};
+
+&rgb_output {
+ status = "okay";
+};
+
+&tda988x_pin {
+ status = "okay";
+};
+
+&dsi_output {
+ status = "disabled";
+};
+
+&mipi_dsi {
+ status = "disabled";
+};
+
+&mipi_dphy {
+ status = "disabled";
+};
--- /dev/null
+++ b/arch/riscv/boot/dts/starfive/jh7110-evb-uart4-emmc-spdif.dts
@@ -0,0 +1,78 @@
+// SPDX-License-Identifier: GPL-2.0 OR MIT
+/*
+ * Copyright (C) 2022 StarFive Technology Co., Ltd.
+ */
+
+/dts-v1/;
+#include "jh7110-evb.dtsi"
+
+/ {
+ model = "StarFive JH7110 EVB";
+ compatible = "starfive,jh7110-evb", "starfive,jh7110";
+
+ spdif_transmitter: spdif_transmitter {
+ compatible = "linux,spdif-dit";
+ #sound-dai-cells = <0>;
+ };
+
+ sound4: snd-card4 {
+ compatible = "simple-audio-card";
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ simple-audio-card,name = "StarFive-SPDIF-Sound-Card";
+ simple-audio-card,dai-link@0 {
+ reg = <0>;
+ format = "left_j";
+ bitclock-master = <&sndcpu0>;
+ frame-master = <&sndcpu0>;
+
+ sndcpu0: cpu {
+ sound-dai = <&spdif>;
+ };
+
+ codec {
+ sound-dai = <&spdif_transmitter>;
+ };
+ };
+ };
+};
+
+&usb0 {
+ status = "okay";
+};
+
+&pcie1 {
+ status = "okay";
+};
+
+&uart4 {
+ status = "okay";
+};
+
+&mmc0 {
+ assigned-clocks = <&syscrg JH7110_SYSCLK_SDIO0_SDCARD>;
+ assigned-clock-rates = <50000000>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&emmc0_pins>;
+ max-frequency = <100000000>;
+ card-detect-delay = <300>;
+ bus-width = <8>;
+ cap-mmc-highspeed;
+ mmc-hs200-1_8v;
+ non-removable;
+ cap-mmc-hw-reset;
+ board-is-evb;
+ post-power-on-delay-ms = <200>;
+ status = "okay";
+};
+
+&pwm {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pwm_ch6to7_pins>;
+ status = "okay";
+};
+
+&spdif {
+ status = "okay";
+};
--- /dev/null
+++ b/arch/riscv/boot/dts/starfive/jh7110-evb-uart5-pwm-i2c-tdm.dts
@@ -0,0 +1,95 @@
+// SPDX-License-Identifier: GPL-2.0 OR MIT
+/*
+ * Copyright (C) 2022 StarFive Technology Co., Ltd.
+ */
+
+/dts-v1/;
+#include "jh7110-evb.dtsi"
+
+/ {
+ model = "StarFive JH7110 EVB";
+ compatible = "starfive,jh7110-evb", "starfive,jh7110";
+
+ sound5: snd-card5 {
+ compatible = "simple-audio-card";
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ simple-audio-card,name = "StarFive-TDM-Sound-Card";
+ simple-audio-card,widgets = "Microphone", "Mic Jack",
+ "Line", "Line In",
+ "Line", "Line Out",
+ "Speaker", "Speaker",
+ "Headphone", "Headphone Jack";
+ simple-audio-card,routing = "Headphone Jack", "HP_L",
+ "Headphone Jack", "HP_R",
+ "Speaker", "SPK_LP",
+ "Speaker", "SPK_LN",
+ "LINPUT1", "Mic Jack",
+ "LINPUT3", "Mic Jack",
+ "RINPUT1", "Mic Jack",
+ "RINPUT2", "Mic Jack";
+
+ simple-audio-card,dai-link@0 {
+ reg = <0>;
+ format = "dsp_a";
+ bitclock-master = <&dailink_master>;
+ frame-master = <&dailink_master>;
+
+ cpu {
+ sound-dai = <&tdm>;
+ };
+ dailink_master: codec {
+ sound-dai = <&wm8960>;
+ clocks = <&wm8960_mclk>;
+ };
+ };
+ };
+};
+
+&mmc0 {
+ assigned-clocks = <&syscrg JH7110_SYSCLK_SDIO0_SDCARD>;
+ assigned-clock-rates = <50000000>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&sdcard0_pins>;
+ max-frequency = <100000000>;
+ card-detect-delay = <300>;
+ bus-width = <4>;
+ broken-cd;
+ post-power-on-delay-ms = <200>;
+ status = "okay";
+};
+
+&usb0 {
+ status = "okay";
+};
+
+&pcie1 {
+ status = "okay";
+};
+
+&uart5 {
+ status = "okay";
+};
+
+&pwm {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pwm_ch0to3_pins &pwm_ch4to5_pins>;
+ status = "okay";
+};
+
+&tdm {
+ status = "okay";
+};
+
+&i2c0 {
+ status = "okay";
+};
+
+&i2c1 {
+ status = "okay";
+};
+
+&i2c3 {
+ status = "okay";
+};
--- /dev/null
+++ b/arch/riscv/boot/dts/starfive/jh7110-evb-usbdevice.dts
@@ -0,0 +1,35 @@
+// SPDX-License-Identifier: GPL-2.0 OR MIT
+/*
+ * Copyright (C) 2022 StarFive Technology Co., Ltd.
+ */
+
+/dts-v1/;
+#include "jh7110-evb.dtsi"
+
+/ {
+ model = "StarFive JH7110 EVB";
+ compatible = "starfive,jh7110-evb", "starfive,jh7110";
+};
+
+/* default sd card */
+&mmc0 {
+ assigned-clocks = <&syscrg JH7110_SYSCLK_SDIO0_SDCARD>;
+ assigned-clock-rates = <50000000>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&sdcard0_pins>;
+ max-frequency = <100000000>;
+ card-detect-delay = <300>;
+ bus-width = <4>;
+ broken-cd;
+ post-power-on-delay-ms = <200>;
+ status = "okay";
+};
+
+&usb0 {
+ dr_mode = "peripheral"; /*host or peripheral*/
+ status = "okay";
+};
+
+&pcie1 {
+ status = "okay";
+};

View File

@ -0,0 +1,485 @@
From e9122ceaf2d8767753e2a126c14b29b78280446d Mon Sep 17 00:00:00 2001
From: Hal Feng <hal.feng@starfivetech.com>
Date: Tue, 19 Sep 2023 21:35:39 +0800
Subject: [PATCH 058/116] riscv: dts: starfive: Add evb-overlay dtso subdir
Create subdir evb-overlay/ and add overlay .dtso for JH7110 EVB.
The code is ported from tag JH7110_SDK_6.1_v5.11.3
Signed-off-by: Hal Feng <hal.feng@starfivetech.com>
---
arch/riscv/boot/dts/starfive/Makefile | 1 +
.../boot/dts/starfive/evb-overlay/Makefile | 7 +
.../evb-overlay/jh7110-evb-overlay-can.dtso | 24 ++++
.../jh7110-evb-overlay-rgb2hdmi.dtso | 24 ++++
.../evb-overlay/jh7110-evb-overlay-sdio.dtso | 78 +++++++++++
.../evb-overlay/jh7110-evb-overlay-spi.dtso | 72 ++++++++++
.../jh7110-evb-overlay-uart4-emmc.dtso | 130 ++++++++++++++++++
.../jh7110-evb-overlay-uart5-pwm.dtso | 92 +++++++++++++
8 files changed, 428 insertions(+)
create mode 100644 arch/riscv/boot/dts/starfive/evb-overlay/Makefile
create mode 100644 arch/riscv/boot/dts/starfive/evb-overlay/jh7110-evb-overlay-can.dtso
create mode 100644 arch/riscv/boot/dts/starfive/evb-overlay/jh7110-evb-overlay-rgb2hdmi.dtso
create mode 100644 arch/riscv/boot/dts/starfive/evb-overlay/jh7110-evb-overlay-sdio.dtso
create mode 100644 arch/riscv/boot/dts/starfive/evb-overlay/jh7110-evb-overlay-spi.dtso
create mode 100644 arch/riscv/boot/dts/starfive/evb-overlay/jh7110-evb-overlay-uart4-emmc.dtso
create mode 100644 arch/riscv/boot/dts/starfive/evb-overlay/jh7110-evb-overlay-uart5-pwm.dtso
--- a/arch/riscv/boot/dts/starfive/Makefile
+++ b/arch/riscv/boot/dts/starfive/Makefile
@@ -12,6 +12,7 @@ dtb-$(CONFIG_ARCH_STARFIVE) += jh7100-st
dtb-$(CONFIG_ARCH_STARFIVE) += jh7110-starfive-visionfive-2-v1.2a.dtb
dtb-$(CONFIG_ARCH_STARFIVE) += jh7110-starfive-visionfive-2-v1.3b.dtb
+subdir-y += evb-overlay
dtb-$(CONFIG_ARCH_STARFIVE) += jh7110-evb.dtb \
jh7110-evb-pcie-i2s-sd.dtb \
jh7110-evb-spi-uart2.dtb \
--- /dev/null
+++ b/arch/riscv/boot/dts/starfive/evb-overlay/Makefile
@@ -0,0 +1,7 @@
+# SPDX-License-Identifier: GPL-2.0
+dtb-$(CONFIG_ARCH_STARFIVE) += jh7110-evb-overlay-can.dtbo \
+ jh7110-evb-overlay-sdio.dtbo \
+ jh7110-evb-overlay-spi.dtbo \
+ jh7110-evb-overlay-uart4-emmc.dtbo \
+ jh7110-evb-overlay-uart5-pwm.dtbo \
+ jh7110-evb-overlay-rgb2hdmi.dtbo
--- /dev/null
+++ b/arch/riscv/boot/dts/starfive/evb-overlay/jh7110-evb-overlay-can.dtso
@@ -0,0 +1,24 @@
+/dts-v1/;
+/plugin/;
+#include <dt-bindings/gpio/gpio.h>
+#include "../jh7110-pinfunc.h"
+/ {
+ compatible = "starfive,jh7110";
+
+ //can0
+ fragment@0 {
+ target-path = "/soc/can@130d0000";
+ __overlay__ {
+ status = "okay";
+ };
+ };
+
+ //can1
+ fragment@1 {
+ target-path = "/soc/can@130e0000";
+ __overlay__ {
+ status = "okay";
+ };
+ };
+};
+
--- /dev/null
+++ b/arch/riscv/boot/dts/starfive/evb-overlay/jh7110-evb-overlay-rgb2hdmi.dtso
@@ -0,0 +1,24 @@
+/dts-v1/;
+/plugin/;
+#include <dt-bindings/gpio/gpio.h>
+#include "../jh7110-pinfunc.h"
+/ {
+ compatible = "starfive,jh7110";
+
+ //hdmi_output
+ fragment@0 {
+ target-path = "/tda988x_pin";
+ __overlay__ {
+ status = "okay";
+ };
+ };
+
+ //uart1
+ fragment@1 {
+ target-path = "/soc/serial@10010000";
+ __overlay__ {
+ status = "okay";
+ };
+ };
+};
+
--- /dev/null
+++ b/arch/riscv/boot/dts/starfive/evb-overlay/jh7110-evb-overlay-sdio.dtso
@@ -0,0 +1,78 @@
+/dts-v1/;
+/plugin/;
+#include <dt-bindings/gpio/gpio.h>
+#include "../jh7110-pinfunc.h"
+/ {
+ compatible = "starfive,jh7110";
+
+ //sysgpio
+ fragment@0 {
+ target-path = "/soc/pinctrl@13040000";
+ __overlay__ {
+ dt_sdcard1_pins: dt-sdcard1-0 {
+ sdcard-pins {
+ pinmux = <GPIOMUX(56, GPOUT_SYS_SDIO1_CLK,
+ GPOEN_ENABLE,
+ GPI_NONE)>,
+ <GPIOMUX(50, GPOUT_SYS_SDIO1_CMD,
+ GPOEN_SYS_SDIO1_CMD,
+ GPI_SYS_SDIO1_CMD)>,
+ <GPIOMUX(49, GPOUT_SYS_SDIO1_DATA0,
+ GPOEN_SYS_SDIO1_DATA0,
+ GPI_SYS_SDIO1_DATA0)>,
+ <GPIOMUX(45, GPOUT_SYS_SDIO1_DATA1,
+ GPOEN_SYS_SDIO1_DATA1,
+ GPI_SYS_SDIO1_DATA1)>,
+ <GPIOMUX(62, GPOUT_SYS_SDIO1_DATA2,
+ GPOEN_SYS_SDIO1_DATA2,
+ GPI_SYS_SDIO1_DATA2)>,
+ <GPIOMUX(40, GPOUT_SYS_SDIO1_DATA3,
+ GPOEN_SYS_SDIO1_DATA3,
+ GPI_SYS_SDIO1_DATA3)>;
+ bias-pull-up;
+ input-enable;
+ };
+ };
+ };
+ };
+
+ //uart3
+ fragment@1 {
+ target-path = "/soc/serial@12000000";
+ __overlay__ {
+ status = "okay";
+ };
+ };
+
+ //i2c0
+ fragment@2 {
+ target-path = "/soc/i2c@10030000";
+ __overlay__ {
+ status = "okay";
+ };
+ };
+
+ //mmc1
+ fragment@3 {
+ target-path = "/soc/mmc@16020000";
+ __overlay__ {
+ max-frequency = <100000000>;
+ card-detect-delay = <300>;
+ bus-width = <4>;
+ no-sdio;
+ no-mmc;
+ broken-cd;
+ sd-uhs-sdr12;
+ sd-uhs-sdr25;
+ sd-uhs-sdr50;
+ sd-uhs-sdr104;
+ sd-uhs-ddr50;
+ cap-sd-highspeed;
+ post-power-on-delay-ms = <200>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&dt_sdcard1_pins>;
+ status = "okay";
+ };
+ };
+};
+
--- /dev/null
+++ b/arch/riscv/boot/dts/starfive/evb-overlay/jh7110-evb-overlay-spi.dtso
@@ -0,0 +1,72 @@
+/dts-v1/;
+/plugin/;
+#include <dt-bindings/gpio/gpio.h>
+#include "../jh7110-pinfunc.h"
+/ {
+ compatible = "starfive,jh7110";
+
+ //spi0
+ fragment@0 {
+ target-path = "/soc/spi@10060000";
+ __overlay__ {
+ status = "okay";
+ };
+ };
+
+ //spi1
+ fragment@1 {
+ target-path = "/soc/spi@10070000";
+ __overlay__ {
+ status = "okay";
+ };
+ };
+
+ //spi2
+ fragment@2 {
+ target-path = "/soc/spi@10080000";
+ __overlay__ {
+ status = "okay";
+ };
+ };
+
+ //spi3
+ fragment@3 {
+ target-path = "/soc/spi@12070000";
+ __overlay__ {
+ status = "okay";
+ };
+ };
+
+ //spi4
+ fragment@4 {
+ target-path = "/soc/spi@12080000";
+ __overlay__ {
+ status = "okay";
+ };
+ };
+
+ //spi5
+ fragment@5 {
+ target-path = "/soc/spi@12090000";
+ __overlay__ {
+ status = "okay";
+ };
+ };
+
+ //spi6
+ fragment@6 {
+ target-path = "/soc/spi@120a0000";
+ __overlay__ {
+ status = "okay";
+ };
+ };
+
+ //uart2
+ fragment@7 {
+ target-path = "/soc/serial@10020000";
+ __overlay__ {
+ status = "okay";
+ };
+ };
+};
+
--- /dev/null
+++ b/arch/riscv/boot/dts/starfive/evb-overlay/jh7110-evb-overlay-uart4-emmc.dtso
@@ -0,0 +1,130 @@
+/dts-v1/;
+/plugin/;
+#include <dt-bindings/gpio/gpio.h>
+#include "../jh7110-pinfunc.h"
+/ {
+ compatible = "starfive,jh7110";
+
+ //sysgpio
+ fragment@0 {
+ target-path = "/soc/pinctrl@13040000";
+ __overlay__ {
+ dt_emmc0_pins: dt-emmc0-0 {
+ emmc-pins {
+ pinmux = <GPIOMUX(22, GPOUT_SYS_SDIO0_RST,
+ GPOEN_ENABLE,
+ GPI_NONE)>,
+ <PINMUX(64, 0)>,
+ <PINMUX(65, 0)>,
+ <PINMUX(66, 0)>,
+ <PINMUX(67, 0)>,
+ <PINMUX(68, 0)>,
+ <PINMUX(69, 0)>,
+ <PINMUX(70, 0)>,
+ <PINMUX(71, 0)>,
+ <PINMUX(72, 0)>,
+ <PINMUX(73, 0)>;
+ bias-pull-up;
+ drive-strength = <12>;
+ input-enable;
+ slew-rate = <1>;
+ };
+ };
+
+ dt_emmc1_pins: dt-emmc1-0 {
+ emmc-pins {
+ pinmux = <GPIOMUX(51, GPOUT_SYS_SDIO1_RST,
+ GPOEN_ENABLE,
+ GPI_NONE)>,
+ <GPIOMUX(38, GPOUT_SYS_SDIO1_CLK,
+ GPOEN_ENABLE,
+ GPI_NONE)>,
+ <GPIOMUX(36, GPOUT_SYS_SDIO1_CMD,
+ GPOEN_SYS_SDIO1_CMD,
+ GPI_SYS_SDIO1_CMD)>,
+ <GPIOMUX(43, GPOUT_SYS_SDIO1_DATA0,
+ GPOEN_SYS_SDIO1_DATA0,
+ GPI_SYS_SDIO1_DATA0)>,
+ <GPIOMUX(48, GPOUT_SYS_SDIO1_DATA1,
+ GPOEN_SYS_SDIO1_DATA1,
+ GPI_SYS_SDIO1_DATA1)>,
+ <GPIOMUX(53, GPOUT_SYS_SDIO1_DATA2,
+ GPOEN_SYS_SDIO1_DATA2,
+ GPI_SYS_SDIO1_DATA2)>,
+ <GPIOMUX(63, GPOUT_SYS_SDIO1_DATA3,
+ GPOEN_SYS_SDIO1_DATA3,
+ GPI_SYS_SDIO1_DATA3)>,
+ <GPIOMUX(52, GPOUT_SYS_SDIO1_DATA4,
+ GPOEN_SYS_SDIO1_DATA4,
+ GPI_SYS_SDIO1_DATA4)>,
+ <GPIOMUX(39, GPOUT_SYS_SDIO1_DATA5,
+ GPOEN_SYS_SDIO1_DATA5,
+ GPI_SYS_SDIO1_DATA5)>,
+ <GPIOMUX(46, GPOUT_SYS_SDIO1_DATA6,
+ GPOEN_SYS_SDIO1_DATA6,
+ GPI_SYS_SDIO1_DATA6)>,
+ <GPIOMUX(47, GPOUT_SYS_SDIO1_DATA7,
+ GPOEN_SYS_SDIO1_DATA7,
+ GPI_SYS_SDIO1_DATA7)>;
+ bias-pull-up;
+ input-enable;
+ };
+ };
+ };
+ };
+
+ //aongpio
+ fragment@1 {
+ target-path = "/soc/pinctrl@17020000";
+ __overlay__ {
+ dt_pwm_ch6to7_pins: dt-pwm-ch6to7-0 {
+ pwm-pins {
+ pinmux = <GPIOMUX(1, GPOUT_AON_PTC0_PWM6, /* PAD_RGPIO0 */
+ GPOEN_AON_PTC0_OE_N_6,
+ GPI_NONE)>,
+ <GPIOMUX(2, GPOUT_AON_PTC0_PWM7, /* PAD_RGPIO1 */
+ GPOEN_AON_PTC0_OE_N_7,
+ GPI_NONE)>;
+ drive-strength = <12>;
+ };
+ };
+ };
+ };
+
+ //uart4
+ fragment@2 {
+ target-path = "/soc/serial@12010000";
+ __overlay__ {
+ status = "okay";
+ };
+ };
+
+ //mmc1
+ fragment@3 {
+ target-path = "/soc/mmc@16020000";
+ __overlay__ {
+ clock-frequency = <102400000>;
+ max-frequency = <100000000>;
+ card-detect-delay = <300>;
+ bus-width = <8>;
+ cap-mmc-hw-reset;
+ non-removable;
+ cap-mmc-highspeed;
+ post-power-on-delay-ms = <200>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&dt_emmc1_pins>;
+ status = "okay";
+ };
+ };
+
+ //ptc
+ fragment@4 {
+ target-path = "/soc/pwm@120d0000";
+ __overlay__ {
+ pinctrl-names = "default";
+ pinctrl-0 = <&dt_pwm_ch6to7_pins>;
+ status = "okay";
+ };
+ };
+};
+
--- /dev/null
+++ b/arch/riscv/boot/dts/starfive/evb-overlay/jh7110-evb-overlay-uart5-pwm.dtso
@@ -0,0 +1,92 @@
+/dts-v1/;
+/plugin/;
+#include <dt-bindings/gpio/gpio.h>
+#include "../jh7110-pinfunc.h"
+/ {
+ compatible = "starfive,jh7110";
+
+ //sysgpio
+ fragment@0 {
+ target-path = "/soc/pinctrl@13040000";
+ __overlay__ {
+ dt_pwm_ch0to3_pins: dt-pwm-ch0to3-0 {
+ pwm-pins {
+ pinmux = <GPIOMUX(45, GPOUT_SYS_PWM_CHANNEL0,
+ GPOEN_SYS_PWM0_CHANNEL0,
+ GPI_NONE)>,
+ <GPIOMUX(46, GPOUT_SYS_PWM_CHANNEL1,
+ GPOEN_SYS_PWM0_CHANNEL1,
+ GPI_NONE)>,
+ <GPIOMUX(47, GPOUT_SYS_PWM_CHANNEL2,
+ GPOEN_SYS_PWM0_CHANNEL2,
+ GPI_NONE)>,
+ <GPIOMUX(48, GPOUT_SYS_PWM_CHANNEL3,
+ GPOEN_SYS_PWM0_CHANNEL3,
+ GPI_NONE)>;
+ drive-strength = <12>;
+ };
+ };
+ };
+ };
+
+ //aongpio
+ fragment@1 {
+ target-path = "/soc/pinctrl@17020000";
+ __overlay__ {
+ dt_pwm_ch4to5_pins: dt-pwm-ch4to5-0 {
+ pwm-pins {
+ pinmux = <GPIOMUX(1, GPOUT_AON_PTC0_PWM4, /* PAD_RGPIO0 */
+ GPOEN_AON_PTC0_OE_N_4,
+ GPI_NONE)>,
+ <GPIOMUX(2, GPOUT_AON_PTC0_PWM5, /* PAD_RGPIO1 */
+ GPOEN_AON_PTC0_OE_N_5,
+ GPI_NONE)>;
+ drive-strength = <12>;
+ };
+ };
+ };
+ };
+
+ //uart5
+ fragment@2 {
+ target-path = "/soc/serial@12020000";
+ __overlay__ {
+ status = "okay";
+ };
+ };
+
+ //ptc
+ fragment@3 {
+ target-path = "/soc/pwm@120d0000";
+ __overlay__ {
+ pinctrl-names = "default";
+ pinctrl-0 = <&dt_pwm_ch0to3_pins &dt_pwm_ch4to5_pins>;
+ status = "okay";
+ };
+ };
+
+ //i2c0
+ fragment@4 {
+ target-path = "/soc/i2c@10030000";
+ __overlay__ {
+ status = "okay";
+ };
+ };
+
+ //i2c1
+ fragment@5 {
+ target-path = "/soc/i2c@10040000";
+ __overlay__ {
+ status = "okay";
+ };
+ };
+
+ //i2c3
+ fragment@6 {
+ target-path = "/soc/i2c@12030000";
+ __overlay__ {
+ status = "okay";
+ };
+ };
+};
+

View File

@ -0,0 +1,385 @@
From 5c888fa081caf5d9473e733931d1c7b3d4b61e61 Mon Sep 17 00:00:00 2001
From: Hal Feng <hal.feng@starfivetech.com>
Date: Fri, 28 Jul 2023 18:42:55 +0800
Subject: [PATCH 059/116] riscv: configs: Add starfive_jh7110_defconfig
Add starfive_jh7110_defconfig for JH7110 EVB.
The code is ported from tag JH7110_SDK_6.1_v5.11.3
Signed-off-by: Hal Feng <hal.feng@starfivetech.com>
---
arch/riscv/configs/starfive_jh7110_defconfig | 368 +++++++++++++++++++
1 file changed, 368 insertions(+)
create mode 100644 arch/riscv/configs/starfive_jh7110_defconfig
--- /dev/null
+++ b/arch/riscv/configs/starfive_jh7110_defconfig
@@ -0,0 +1,368 @@
+CONFIG_COMPILE_TEST=y
+# CONFIG_WERROR is not set
+CONFIG_DEFAULT_HOSTNAME="StarFive"
+CONFIG_SYSVIPC=y
+CONFIG_POSIX_MQUEUE=y
+CONFIG_USELIB=y
+CONFIG_NO_HZ_IDLE=y
+CONFIG_HIGH_RES_TIMERS=y
+CONFIG_BPF_SYSCALL=y
+CONFIG_IKCONFIG=y
+CONFIG_IKCONFIG_PROC=y
+CONFIG_CGROUPS=y
+CONFIG_MEMCG=y
+CONFIG_CGROUP_SCHED=y
+CONFIG_CFS_BANDWIDTH=y
+CONFIG_RT_GROUP_SCHED=y
+CONFIG_CGROUP_PIDS=y
+CONFIG_CGROUP_FREEZER=y
+CONFIG_CGROUP_HUGETLB=y
+CONFIG_CPUSETS=y
+CONFIG_CGROUP_DEVICE=y
+CONFIG_CGROUP_CPUACCT=y
+CONFIG_CGROUP_PERF=y
+CONFIG_CGROUP_BPF=y
+CONFIG_NAMESPACES=y
+CONFIG_USER_NS=y
+CONFIG_CHECKPOINT_RESTORE=y
+CONFIG_BLK_DEV_INITRD=y
+CONFIG_EXPERT=y
+# CONFIG_SYSFS_SYSCALL is not set
+CONFIG_PROFILING=y
+CONFIG_SOC_MICROCHIP_POLARFIRE=y
+CONFIG_SOC_STARFIVE=y
+CONFIG_SOC_VIRT=y
+CONFIG_ERRATA_SIFIVE=y
+CONFIG_NONPORTABLE=y
+CONFIG_SMP=y
+CONFIG_RISCV_SBI_V01=y
+# CONFIG_RISCV_BOOT_SPINWAIT is not set
+CONFIG_HIBERNATION=y
+CONFIG_PM_STD_PARTITION="PARTLABEL=hibernation"
+CONFIG_PM_DEBUG=y
+CONFIG_PM_ADVANCED_DEBUG=y
+CONFIG_PM_TEST_SUSPEND=y
+CONFIG_ENERGY_MODEL=y
+CONFIG_CPU_IDLE=y
+CONFIG_CPU_FREQ=y
+CONFIG_CPU_FREQ_STAT=y
+CONFIG_CPU_FREQ_DEFAULT_GOV_ONDEMAND=y
+CONFIG_CPU_FREQ_GOV_POWERSAVE=y
+CONFIG_CPU_FREQ_GOV_USERSPACE=y
+CONFIG_CPU_FREQ_GOV_CONSERVATIVE=y
+CONFIG_CPU_FREQ_GOV_SCHEDUTIL=y
+CONFIG_CPUFREQ_DT=y
+CONFIG_VIRTUALIZATION=y
+CONFIG_KVM=m
+CONFIG_JUMP_LABEL=y
+CONFIG_MODULES=y
+CONFIG_MODULE_UNLOAD=y
+CONFIG_BINFMT_MISC=y
+CONFIG_CMA=y
+CONFIG_NET=y
+CONFIG_PACKET=y
+CONFIG_XFRM_USER=m
+CONFIG_IP_MULTICAST=y
+CONFIG_IP_ADVANCED_ROUTER=y
+CONFIG_IP_MULTIPLE_TABLES=y
+CONFIG_IP_PNP=y
+CONFIG_IP_PNP_DHCP=y
+CONFIG_IP_PNP_BOOTP=y
+CONFIG_IP_PNP_RARP=y
+CONFIG_INET_ESP=m
+CONFIG_NETFILTER=y
+CONFIG_BRIDGE_NETFILTER=m
+CONFIG_NF_CONNTRACK=m
+CONFIG_NF_CONNTRACK_FTP=m
+CONFIG_NF_CONNTRACK_TFTP=m
+CONFIG_NETFILTER_XT_MARK=m
+CONFIG_NETFILTER_XT_MATCH_ADDRTYPE=m
+CONFIG_NETFILTER_XT_MATCH_CONNTRACK=m
+CONFIG_NETFILTER_XT_MATCH_IPVS=m
+CONFIG_IP_VS=m
+CONFIG_IP_VS_PROTO_TCP=y
+CONFIG_IP_VS_PROTO_UDP=y
+CONFIG_IP_VS_RR=m
+CONFIG_IP_VS_NFCT=y
+CONFIG_NF_LOG_ARP=m
+CONFIG_NF_LOG_IPV4=m
+CONFIG_IP_NF_IPTABLES=m
+CONFIG_IP_NF_FILTER=m
+CONFIG_IP_NF_TARGET_REJECT=m
+CONFIG_IP_NF_NAT=m
+CONFIG_IP_NF_TARGET_MASQUERADE=m
+CONFIG_IP_NF_TARGET_REDIRECT=m
+CONFIG_IP_NF_MANGLE=m
+CONFIG_NF_LOG_IPV6=m
+CONFIG_IP6_NF_IPTABLES=m
+CONFIG_IP6_NF_MATCH_IPV6HEADER=m
+CONFIG_IP6_NF_FILTER=m
+CONFIG_IP6_NF_TARGET_REJECT=m
+CONFIG_IP6_NF_MANGLE=m
+CONFIG_BRIDGE=m
+CONFIG_BRIDGE_VLAN_FILTERING=y
+CONFIG_VLAN_8021Q=m
+CONFIG_NET_SCHED=y
+CONFIG_NET_CLS_CGROUP=m
+CONFIG_NETLINK_DIAG=y
+CONFIG_CGROUP_NET_PRIO=y
+CONFIG_CAN=y
+CONFIG_BT=y
+CONFIG_BT_RFCOMM=y
+CONFIG_BT_RFCOMM_TTY=y
+CONFIG_BT_BNEP=y
+CONFIG_BT_BNEP_MC_FILTER=y
+CONFIG_BT_BNEP_PROTO_FILTER=y
+CONFIG_BT_HCIUART=y
+CONFIG_BT_HCIUART_H4=y
+CONFIG_CFG80211=y
+CONFIG_MAC80211=y
+CONFIG_RFKILL=y
+CONFIG_NET_9P=y
+CONFIG_NET_9P_VIRTIO=y
+CONFIG_PCI=y
+CONFIG_PCIEPORTBUS=y
+# CONFIG_PCIEASPM is not set
+CONFIG_PCI_HOST_GENERIC=y
+CONFIG_PCIE_FU740=y
+CONFIG_PCIE_STARFIVE_HOST=y
+CONFIG_DEVTMPFS=y
+CONFIG_DEVTMPFS_MOUNT=y
+CONFIG_MTD=y
+CONFIG_MTD_BLOCK=y
+CONFIG_MTD_SPI_NOR=y
+CONFIG_OF_CONFIGFS=y
+CONFIG_BLK_DEV_LOOP=y
+CONFIG_VIRTIO_BLK=y
+CONFIG_BLK_DEV_NVME=y
+CONFIG_BLK_DEV_SD=y
+CONFIG_BLK_DEV_SR=y
+CONFIG_SCSI_VIRTIO=y
+CONFIG_ATA=y
+CONFIG_SATA_AHCI=y
+CONFIG_SATA_AHCI_PLATFORM=y
+CONFIG_MD=y
+CONFIG_BLK_DEV_DM=m
+CONFIG_DM_THIN_PROVISIONING=m
+CONFIG_NETDEVICES=y
+CONFIG_DUMMY=m
+CONFIG_MACVLAN=m
+CONFIG_IPVLAN=m
+CONFIG_VXLAN=m
+CONFIG_VETH=m
+CONFIG_VIRTIO_NET=y
+CONFIG_MACB=y
+CONFIG_E1000E=y
+CONFIG_R8169=y
+CONFIG_STMMAC_ETH=y
+CONFIG_DWMAC_DWC_QOS_ETH=y
+# CONFIG_DWMAC_GENERIC is not set
+CONFIG_DWMAC_STARFIVE=y
+CONFIG_MARVELL_PHY=y
+CONFIG_MICREL_PHY=y
+CONFIG_MICROCHIP_PHY=y
+CONFIG_MICROSEMI_PHY=y
+CONFIG_MOTORCOMM_PHY=y
+CONFIG_IPMS_CAN=y
+CONFIG_IWLWIFI=y
+CONFIG_IWLDVM=y
+CONFIG_IWLMVM=y
+CONFIG_INPUT_MOUSEDEV=y
+CONFIG_INPUT_EVDEV=y
+CONFIG_INPUT_TOUCHSCREEN=y
+CONFIG_TOUCHSCREEN_TINKER_FT5406=y
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
+CONFIG_SERIAL_8250_NR_UARTS=6
+CONFIG_SERIAL_8250_RUNTIME_UARTS=6
+CONFIG_SERIAL_8250_EXTENDED=y
+CONFIG_SERIAL_8250_MANY_PORTS=y
+CONFIG_SERIAL_8250_DW=y
+CONFIG_SERIAL_OF_PLATFORM=y
+CONFIG_SERIAL_EARLYCON_RISCV_SBI=y
+CONFIG_TTY_PRINTK=y
+CONFIG_VIRTIO_CONSOLE=y
+CONFIG_HW_RANDOM=y
+CONFIG_HW_RANDOM_VIRTIO=y
+CONFIG_HW_RANDOM_JH7110=y
+CONFIG_I2C_CHARDEV=y
+CONFIG_I2C_DESIGNWARE_PLATFORM=y
+CONFIG_SPI=y
+CONFIG_SPI_CADENCE_QUADSPI=y
+CONFIG_SPI_PL022=y
+CONFIG_SPI_SIFIVE=y
+CONFIG_SPI_SPIDEV=y
+# CONFIG_PTP_1588_CLOCK is not set
+CONFIG_GPIO_SYSFS=y
+CONFIG_GPIO_SIFIVE=y
+CONFIG_SENSORS_SFCTEMP=y
+CONFIG_THERMAL=y
+CONFIG_THERMAL_WRITABLE_TRIPS=y
+CONFIG_CPU_THERMAL=y
+CONFIG_THERMAL_EMULATION=y
+CONFIG_WATCHDOG=y
+CONFIG_WATCHDOG_SYSFS=y
+CONFIG_MFD_AXP20X_I2C=y
+CONFIG_REGULATOR=y
+CONFIG_REGULATOR_AXP20X=y
+CONFIG_REGULATOR_STARFIVE_JH7110=y
+# CONFIG_MEDIA_CEC_SUPPORT is not set
+CONFIG_MEDIA_SUPPORT=y
+CONFIG_MEDIA_USB_SUPPORT=y
+CONFIG_USB_VIDEO_CLASS=y
+CONFIG_V4L_PLATFORM_DRIVERS=y
+CONFIG_V4L_MEM2MEM_DRIVERS=y
+CONFIG_VIDEO_WAVE_VPU=m
+CONFIG_VIN_SENSOR_SC2235=y
+CONFIG_VIN_SENSOR_OV4689=y
+CONFIG_VIN_SENSOR_IMX219=y
+CONFIG_VIDEO_STF_VIN=y
+CONFIG_VIDEO_IMX708=y
+CONFIG_DRM_I2C_NXP_TDA998X=y
+CONFIG_DRM_I2C_NXP_TDA9950=y
+CONFIG_DRM_RADEON=m
+CONFIG_DRM_VIRTIO_GPU=m
+CONFIG_DRM_VERISILICON=y
+CONFIG_STARFIVE_INNO_HDMI=y
+CONFIG_STARFIVE_DSI=y
+CONFIG_DRM_IMG_ROGUE=y
+CONFIG_DRM_LEGACY=y
+CONFIG_FB=y
+CONFIG_SOUND=y
+CONFIG_SND=y
+CONFIG_SND_USB_AUDIO=y
+CONFIG_SND_SOC=y
+CONFIG_SND_DESIGNWARE_I2S=y
+# CONFIG_SND_SOC_INTEL_SST_TOPLEVEL is not set
+CONFIG_SND_SOC_STARFIVE=y
+CONFIG_SND_SOC_JH7110_PDM=y
+CONFIG_SND_SOC_JH7110_PWMDAC=y
+CONFIG_SND_SOC_JH7110_SPDIF=y
+CONFIG_SND_SOC_JH7110_TDM=y
+CONFIG_SND_SOC_AC108=y
+CONFIG_SND_SOC_WM8960=y
+CONFIG_SND_SIMPLE_CARD=y
+CONFIG_USB=y
+CONFIG_USB_XHCI_HCD=y
+CONFIG_USB_EHCI_HCD=y
+CONFIG_USB_EHCI_HCD_PLATFORM=y
+CONFIG_USB_OHCI_HCD=y
+CONFIG_USB_OHCI_HCD_PLATFORM=y
+CONFIG_USB_STORAGE=y
+CONFIG_USB_UAS=y
+CONFIG_USB_CDNS_SUPPORT=y
+CONFIG_USB_CDNS3=y
+CONFIG_USB_CDNS3_GADGET=y
+CONFIG_USB_CDNS3_HOST=y
+CONFIG_USB_CDNS3_STARFIVE=y
+CONFIG_USB_GADGET=y
+CONFIG_USB_CONFIGFS=y
+CONFIG_USB_CONFIGFS_MASS_STORAGE=y
+CONFIG_USB_CONFIGFS_F_FS=y
+CONFIG_MMC=y
+CONFIG_MMC_SDHCI=y
+CONFIG_MMC_SDHCI_PLTFM=y
+CONFIG_MMC_SDHCI_CADENCE=y
+CONFIG_MMC_SPI=y
+CONFIG_MMC_DW=y
+CONFIG_MMC_DW_STARFIVE=y
+CONFIG_RTC_CLASS=y
+# CONFIG_RTC_DRV_SPEAR is not set
+CONFIG_RTC_DRV_STARFIVE=y
+CONFIG_DMADEVICES=y
+CONFIG_AMBA_PL08X=y
+CONFIG_DW_AXI_DMAC=y
+# CONFIG_SH_DMAE_BASE is not set
+# CONFIG_TI_EDMA is not set
+# CONFIG_DMA_OMAP is not set
+CONFIG_DMATEST=y
+CONFIG_VIRTIO_PCI=y
+CONFIG_VIRTIO_BALLOON=y
+CONFIG_VIRTIO_INPUT=y
+CONFIG_VIRTIO_MMIO=y
+CONFIG_STAGING=y
+CONFIG_STAGING_MEDIA=y
+CONFIG_CLK_STARFIVE_JH7110_AON=y
+CONFIG_CLK_STARFIVE_JH7110_STG=y
+CONFIG_CLK_STARFIVE_JH7110_ISP=y
+CONFIG_CLK_STARFIVE_JH7110_VOUT=y
+CONFIG_MAILBOX=y
+CONFIG_STARFIVE_MBOX=m
+CONFIG_STARFIVE_MBOX_TEST=m
+CONFIG_RPMSG_CHAR=y
+CONFIG_RPMSG_CTRL=y
+CONFIG_RPMSG_VIRTIO=y
+CONFIG_SIFIVE_CCACHE=y
+CONFIG_PWM=y
+CONFIG_PWM_OCORES=y
+CONFIG_PHY_STARFIVE_JH7110_PCIE=y
+CONFIG_PHY_STARFIVE_JH7110_USB=y
+CONFIG_PHY_M31_DPHY_RX0=y
+CONFIG_EXT4_FS=y
+CONFIG_EXT4_FS_POSIX_ACL=y
+CONFIG_EXT4_FS_SECURITY=y
+CONFIG_BTRFS_FS=m
+CONFIG_BTRFS_FS_POSIX_ACL=y
+CONFIG_AUTOFS_FS=y
+CONFIG_FUSE_FS=y
+CONFIG_OVERLAY_FS=y
+CONFIG_OVERLAY_FS_INDEX=y
+CONFIG_OVERLAY_FS_XINO_AUTO=y
+CONFIG_OVERLAY_FS_METACOPY=y
+CONFIG_ISO9660_FS=y
+CONFIG_JOLIET=y
+CONFIG_ZISOFS=y
+CONFIG_MSDOS_FS=y
+CONFIG_VFAT_FS=y
+CONFIG_EXFAT_FS=y
+CONFIG_TMPFS=y
+CONFIG_TMPFS_POSIX_ACL=y
+CONFIG_HUGETLBFS=y
+CONFIG_JFFS2_FS=y
+CONFIG_NFS_FS=y
+CONFIG_NFS_V4=y
+CONFIG_NFS_V4_1=y
+CONFIG_NFS_V4_2=y
+CONFIG_ROOT_NFS=y
+CONFIG_9P_FS=y
+CONFIG_NLS_CODEPAGE_437=y
+CONFIG_NLS_ISO8859_1=m
+CONFIG_SECURITY=y
+CONFIG_SECURITY_SELINUX=y
+CONFIG_SECURITY_APPARMOR=y
+CONFIG_DEFAULT_SECURITY_DAC=y
+CONFIG_LSM=""
+CONFIG_INIT_STACK_NONE=y
+CONFIG_CRYPTO_USER=y
+CONFIG_CRYPTO_ZSTD=y
+CONFIG_CRYPTO_USER_API_HASH=y
+CONFIG_CRYPTO_USER_API_SKCIPHER=y
+CONFIG_CRYPTO_USER_API_AEAD=y
+CONFIG_CRYPTO_STATS=y
+CONFIG_CRYPTO_DEV_VIRTIO=y
+CONFIG_CRYPTO_DEV_JH7110=y
+CONFIG_DMA_CMA=y
+CONFIG_PRINTK_TIME=y
+CONFIG_DEBUG_FS=y
+CONFIG_DEBUG_PAGEALLOC=y
+CONFIG_SCHED_STACK_END_CHECK=y
+CONFIG_DEBUG_VM=y
+CONFIG_DEBUG_VM_PGFLAGS=y
+CONFIG_DEBUG_MEMORY_INIT=y
+CONFIG_DEBUG_PER_CPU_MAPS=y
+CONFIG_SOFTLOCKUP_DETECTOR=y
+CONFIG_WQ_WATCHDOG=y
+CONFIG_DEBUG_TIMEKEEPING=y
+CONFIG_DEBUG_RT_MUTEXES=y
+CONFIG_DEBUG_SPINLOCK=y
+CONFIG_DEBUG_MUTEXES=y
+CONFIG_DEBUG_RWSEMS=y
+CONFIG_DEBUG_LIST=y
+CONFIG_DEBUG_PLIST=y
+CONFIG_DEBUG_SG=y
+CONFIG_RCU_CPU_STALL_TIMEOUT=60
+# CONFIG_RCU_TRACE is not set
+CONFIG_RCU_EQS_DEBUG=y
+# CONFIG_FTRACE is not set
+# CONFIG_RUNTIME_TESTING_MENU is not set
+CONFIG_MEMTEST=y

View File

@ -0,0 +1,318 @@
From 95c702022f5e4cb786719fcf90170334b1e562cc Mon Sep 17 00:00:00 2001
From: Jianlong Huang <jianlong.huang@starfivetech.com>
Date: Thu, 16 Jun 2022 17:13:57 +0800
Subject: [PATCH 060/116] of: configfs: Add configfs function
Signed-off-by: Jianlong Huang <jianlong.huang@starfivetech.com>
Signed-off-by: Hal Feng <hal.feng@starfivetech.com>
---
drivers/of/Kconfig | 7 ++
drivers/of/Makefile | 1 +
drivers/of/configfs.c | 277 ++++++++++++++++++++++++++++++++++++++++++
3 files changed, 285 insertions(+)
create mode 100644 drivers/of/configfs.c
--- a/drivers/of/Kconfig
+++ b/drivers/of/Kconfig
@@ -102,4 +102,11 @@ config OF_OVERLAY
config OF_NUMA
bool
+config OF_CONFIGFS
+ bool "Device Tree Overlay ConfigFS interface"
+ select CONFIGFS_FS
+ select OF_OVERLAY
+ help
+ Enable a simple user-space driven DT overlay interface.
+
endif # OF
--- a/drivers/of/Makefile
+++ b/drivers/of/Makefile
@@ -11,6 +11,7 @@ obj-$(CONFIG_OF_UNITTEST) += unittest.o
obj-$(CONFIG_OF_RESERVED_MEM) += of_reserved_mem.o
obj-$(CONFIG_OF_RESOLVE) += resolver.o
obj-$(CONFIG_OF_OVERLAY) += overlay.o
+obj-$(CONFIG_OF_CONFIGFS) += configfs.o
obj-$(CONFIG_OF_NUMA) += of_numa.o
ifdef CONFIG_KEXEC_FILE
--- /dev/null
+++ b/drivers/of/configfs.c
@@ -0,0 +1,277 @@
+/*
+ * Configfs entries for device-tree
+ *
+ * Copyright (C) 2013 - Pantelis Antoniou <panto@antoniou-consulting.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version
+ * 2 of the License, or (at your option) any later version.
+ */
+#include <linux/ctype.h>
+#include <linux/cpu.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/of_fdt.h>
+#include <linux/spinlock.h>
+#include <linux/slab.h>
+#include <linux/proc_fs.h>
+#include <linux/configfs.h>
+#include <linux/types.h>
+#include <linux/stat.h>
+#include <linux/limits.h>
+#include <linux/file.h>
+#include <linux/vmalloc.h>
+#include <linux/firmware.h>
+#include <linux/sizes.h>
+
+#include "of_private.h"
+
+struct cfs_overlay_item {
+ struct config_item item;
+
+ char path[PATH_MAX];
+
+ const struct firmware *fw;
+ struct device_node *overlay;
+ int ov_id;
+
+ void *dtbo;
+ int dtbo_size;
+};
+
+static inline struct cfs_overlay_item *to_cfs_overlay_item(
+ struct config_item *item)
+{
+ return item ? container_of(item, struct cfs_overlay_item, item) : NULL;
+}
+
+static ssize_t cfs_overlay_item_path_show(struct config_item *item,
+ char *page)
+{
+ struct cfs_overlay_item *overlay = to_cfs_overlay_item(item);
+ return sprintf(page, "%s\n", overlay->path);
+}
+
+static ssize_t cfs_overlay_item_path_store(struct config_item *item,
+ const char *page, size_t count)
+{
+ struct cfs_overlay_item *overlay = to_cfs_overlay_item(item);
+ const char *p = page;
+ char *s;
+ int err;
+
+ /* if it's set do not allow changes */
+ if (overlay->path[0] != '\0' || overlay->dtbo_size > 0)
+ return -EPERM;
+
+ /* copy to path buffer (and make sure it's always zero terminated */
+ count = snprintf(overlay->path, sizeof(overlay->path) - 1, "%s", p);
+ overlay->path[sizeof(overlay->path) - 1] = '\0';
+
+ /* strip trailing newlines */
+ s = overlay->path + strlen(overlay->path);
+ while (s > overlay->path && *--s == '\n')
+ *s = '\0';
+
+ pr_debug("%s: path is '%s'\n", __func__, overlay->path);
+
+ err = request_firmware(&overlay->fw, overlay->path, NULL);
+ if (err != 0)
+ return err;
+
+ err = of_overlay_fdt_apply((void *)overlay->fw->data,
+ (u32)overlay->fw->size, &overlay->ov_id, NULL);
+ if (err != 0)
+ goto out_err;
+
+ return count;
+
+out_err:
+
+ release_firmware(overlay->fw);
+ overlay->fw = NULL;
+
+ overlay->path[0] = '\0';
+ return err;
+}
+
+static ssize_t cfs_overlay_item_status_show(struct config_item *item,
+ char *page)
+{
+ struct cfs_overlay_item *overlay = to_cfs_overlay_item(item);
+
+ return sprintf(page, "%s\n",
+ overlay->ov_id > 0 ? "applied" : "unapplied");
+}
+
+CONFIGFS_ATTR(cfs_overlay_item_, path);
+CONFIGFS_ATTR_RO(cfs_overlay_item_, status);
+
+static struct configfs_attribute *cfs_overlay_attrs[] = {
+ &cfs_overlay_item_attr_path,
+ &cfs_overlay_item_attr_status,
+ NULL,
+};
+
+ssize_t cfs_overlay_item_dtbo_read(struct config_item *item,
+ void *buf, size_t max_count)
+{
+ struct cfs_overlay_item *overlay = to_cfs_overlay_item(item);
+
+ pr_debug("%s: buf=%p max_count=%zu\n", __func__,
+ buf, max_count);
+
+ if (overlay->dtbo == NULL)
+ return 0;
+
+ /* copy if buffer provided */
+ if (buf != NULL) {
+ /* the buffer must be large enough */
+ if (overlay->dtbo_size > max_count)
+ return -ENOSPC;
+
+ memcpy(buf, overlay->dtbo, overlay->dtbo_size);
+ }
+
+ return overlay->dtbo_size;
+}
+
+ssize_t cfs_overlay_item_dtbo_write(struct config_item *item,
+ const void *buf, size_t count)
+{
+ struct cfs_overlay_item *overlay = to_cfs_overlay_item(item);
+ int err;
+
+ /* if it's set do not allow changes */
+ if (overlay->path[0] != '\0' || overlay->dtbo_size > 0)
+ return -EPERM;
+
+ /* copy the contents */
+ overlay->dtbo = kmemdup(buf, count, GFP_KERNEL);
+ if (overlay->dtbo == NULL)
+ return -ENOMEM;
+
+ overlay->dtbo_size = count;
+
+ err = of_overlay_fdt_apply(overlay->dtbo, overlay->dtbo_size,
+ &overlay->ov_id, NULL);
+ if (err != 0)
+ goto out_err;
+
+ return count;
+
+out_err:
+ kfree(overlay->dtbo);
+ overlay->dtbo = NULL;
+ overlay->dtbo_size = 0;
+ overlay->ov_id = 0;
+
+ return err;
+}
+
+CONFIGFS_BIN_ATTR(cfs_overlay_item_, dtbo, NULL, SZ_1M);
+
+static struct configfs_bin_attribute *cfs_overlay_bin_attrs[] = {
+ &cfs_overlay_item_attr_dtbo,
+ NULL,
+};
+
+static void cfs_overlay_release(struct config_item *item)
+{
+ struct cfs_overlay_item *overlay = to_cfs_overlay_item(item);
+
+ if (overlay->ov_id > 0)
+ of_overlay_remove(&overlay->ov_id);
+ if (overlay->fw)
+ release_firmware(overlay->fw);
+ /* kfree with NULL is safe */
+ kfree(overlay->dtbo);
+ kfree(overlay);
+}
+
+static struct configfs_item_operations cfs_overlay_item_ops = {
+ .release = cfs_overlay_release,
+};
+
+static struct config_item_type cfs_overlay_type = {
+ .ct_item_ops = &cfs_overlay_item_ops,
+ .ct_attrs = cfs_overlay_attrs,
+ .ct_bin_attrs = cfs_overlay_bin_attrs,
+ .ct_owner = THIS_MODULE,
+};
+
+static struct config_item *cfs_overlay_group_make_item(
+ struct config_group *group, const char *name)
+{
+ struct cfs_overlay_item *overlay;
+
+ overlay = kzalloc(sizeof(*overlay), GFP_KERNEL);
+ if (!overlay)
+ return ERR_PTR(-ENOMEM);
+
+ config_item_init_type_name(&overlay->item, name, &cfs_overlay_type);
+ return &overlay->item;
+}
+
+static void cfs_overlay_group_drop_item(struct config_group *group,
+ struct config_item *item)
+{
+ struct cfs_overlay_item *overlay = to_cfs_overlay_item(item);
+
+ config_item_put(&overlay->item);
+}
+
+static struct configfs_group_operations overlays_ops = {
+ .make_item = cfs_overlay_group_make_item,
+ .drop_item = cfs_overlay_group_drop_item,
+};
+
+static struct config_item_type overlays_type = {
+ .ct_group_ops = &overlays_ops,
+ .ct_owner = THIS_MODULE,
+};
+
+static struct configfs_group_operations of_cfs_ops = {
+ /* empty - we don't allow anything to be created */
+};
+
+static struct config_item_type of_cfs_type = {
+ .ct_group_ops = &of_cfs_ops,
+ .ct_owner = THIS_MODULE,
+};
+
+struct config_group of_cfs_overlay_group;
+
+static struct configfs_subsystem of_cfs_subsys = {
+ .su_group = {
+ .cg_item = {
+ .ci_namebuf = "device-tree",
+ .ci_type = &of_cfs_type,
+ },
+ },
+ .su_mutex = __MUTEX_INITIALIZER(of_cfs_subsys.su_mutex),
+};
+
+static int __init of_cfs_init(void)
+{
+ int ret;
+
+ pr_info("%s\n", __func__);
+
+ config_group_init(&of_cfs_subsys.su_group);
+ config_group_init_type_name(&of_cfs_overlay_group, "overlays",
+ &overlays_type);
+ configfs_add_default_group(&of_cfs_overlay_group,
+ &of_cfs_subsys.su_group);
+
+ ret = configfs_register_subsystem(&of_cfs_subsys);
+ if (ret != 0) {
+ pr_err("%s: failed to register subsys\n", __func__);
+ goto out;
+ }
+ pr_info("%s: OK\n", __func__);
+out:
+ return ret;
+}
+late_initcall(of_cfs_init);

View File

@ -0,0 +1,344 @@
From 7891826f8c2de9ee0f6459cf969f7b082e29b154 Mon Sep 17 00:00:00 2001
From: Hal Feng <hal.feng@starfivetech.com>
Date: Thu, 1 Jun 2023 23:10:09 -0700
Subject: [PATCH 061/116] usr: Add gen_initramfs_list.sh
Add gen_initramfs_list.sh
Signed-off-by: Hal Feng <hal.feng@starfivetech.com>
---
usr/gen_initramfs_list.sh | 328 ++++++++++++++++++++++++++++++++++++++
1 file changed, 328 insertions(+)
create mode 100644 usr/gen_initramfs_list.sh
--- /dev/null
+++ b/usr/gen_initramfs_list.sh
@@ -0,0 +1,328 @@
+#!/bin/sh
+# Copyright (C) Martin Schlemmer <azarah@nosferatu.za.org>
+# Copyright (C) 2006 Sam Ravnborg <sam@ravnborg.org>
+#
+# Released under the terms of the GNU GPL
+#
+# Generate a cpio packed initramfs. It uses gen_init_cpio to generate
+# the cpio archive, and then compresses it.
+# The script may also be used to generate the inputfile used for gen_init_cpio
+# This script assumes that gen_init_cpio is located in usr/ directory
+
+# error out on errors
+set -e
+
+usage() {
+cat << EOF
+Usage:
+$0 [-o <file>] [-u <uid>] [-g <gid>] {-d | <cpio_source>} ...
+ -o <file> Create compressed initramfs file named <file> using
+ gen_init_cpio and compressor depending on the extension
+ -u <uid> User ID to map to user ID 0 (root).
+ <uid> is only meaningful if <cpio_source> is a
+ directory. "squash" forces all files to uid 0.
+ -g <gid> Group ID to map to group ID 0 (root).
+ <gid> is only meaningful if <cpio_source> is a
+ directory. "squash" forces all files to gid 0.
+ <cpio_source> File list or directory for cpio archive.
+ If <cpio_source> is a .cpio file it will be used
+ as direct input to initramfs.
+ -d Output the default cpio list.
+
+All options except -o and -l may be repeated and are interpreted
+sequentially and immediately. -u and -g states are preserved across
+<cpio_source> options so an explicit "-u 0 -g 0" is required
+to reset the root/group mapping.
+EOF
+}
+
+# awk style field access
+# $1 - field number; rest is argument string
+field() {
+ shift $1 ; echo $1
+}
+
+list_default_initramfs() {
+ # echo usr/kinit/kinit
+ :
+}
+
+default_initramfs() {
+ cat <<-EOF >> ${output}
+ # This is a very simple, default initramfs
+
+ dir /dev 0755 0 0
+ nod /dev/console 0600 0 0 c 5 1
+ dir /root 0700 0 0
+ # file /kinit usr/kinit/kinit 0755 0 0
+ # slink /init kinit 0755 0 0
+ EOF
+}
+
+filetype() {
+ local argv1="$1"
+
+ # symlink test must come before file test
+ if [ -L "${argv1}" ]; then
+ echo "slink"
+ elif [ -f "${argv1}" ]; then
+ echo "file"
+ elif [ -d "${argv1}" ]; then
+ echo "dir"
+ elif [ -b "${argv1}" -o -c "${argv1}" ]; then
+ echo "nod"
+ elif [ -p "${argv1}" ]; then
+ echo "pipe"
+ elif [ -S "${argv1}" ]; then
+ echo "sock"
+ else
+ echo "invalid"
+ fi
+ return 0
+}
+
+list_print_mtime() {
+ :
+}
+
+print_mtime() {
+ local my_mtime="0"
+
+ if [ -e "$1" ]; then
+ my_mtime=$(find "$1" -printf "%T@\n" | sort -r | head -n 1)
+ fi
+
+ echo "# Last modified: ${my_mtime}" >> ${output}
+ echo "" >> ${output}
+}
+
+list_parse() {
+ if [ -L "$1" ]; then
+ return
+ fi
+ echo "$1" | sed 's/:/\\:/g; s/$/ \\/'
+}
+
+# for each file print a line in following format
+# <filetype> <name> <path to file> <octal mode> <uid> <gid>
+# for links, devices etc the format differs. See gen_init_cpio for details
+parse() {
+ local location="$1"
+ local name="/${location#${srcdir}}"
+ # change '//' into '/'
+ name=$(echo "$name" | sed -e 's://*:/:g')
+ local mode="$2"
+ local uid="$3"
+ local gid="$4"
+ local ftype=$(filetype "${location}")
+ # remap uid/gid to 0 if necessary
+ [ "$root_uid" = "squash" ] && uid=0 || [ "$uid" -eq "$root_uid" ] && uid=0
+ [ "$root_gid" = "squash" ] && gid=0 || [ "$gid" -eq "$root_gid" ] && gid=0
+ local str="${mode} ${uid} ${gid}"
+
+ [ "${ftype}" = "invalid" ] && return 0
+ [ "${location}" = "${srcdir}" ] && return 0
+
+ case "${ftype}" in
+ "file")
+ str="${ftype} ${name} ${location} ${str}"
+ ;;
+ "nod")
+ local dev=`LC_ALL=C ls -l "${location}"`
+ local maj=`field 5 ${dev}`
+ local min=`field 6 ${dev}`
+ maj=${maj%,}
+
+ [ -b "${location}" ] && dev="b" || dev="c"
+
+ str="${ftype} ${name} ${str} ${dev} ${maj} ${min}"
+ ;;
+ "slink")
+ local target=`readlink "${location}"`
+ str="${ftype} ${name} ${target} ${str}"
+ ;;
+ *)
+ str="${ftype} ${name} ${str}"
+ ;;
+ esac
+
+ echo "${str}" >> ${output}
+
+ return 0
+}
+
+unknown_option() {
+ printf "ERROR: unknown option \"$arg\"\n" >&2
+ printf "If the filename validly begins with '-', " >&2
+ printf "then it must be prefixed\n" >&2
+ printf "by './' so that it won't be interpreted as an option." >&2
+ printf "\n" >&2
+ usage >&2
+ exit 1
+}
+
+list_header() {
+ :
+}
+
+header() {
+ printf "\n#####################\n# $1\n" >> ${output}
+}
+
+# process one directory (incl sub-directories)
+dir_filelist() {
+ ${dep_list}header "$1"
+
+ srcdir=$(echo "$1" | sed -e 's://*:/:g')
+ dirlist=$(find "${srcdir}" -printf "%p %m %U %G\n" | LANG=C sort)
+
+ # If $dirlist is only one line, then the directory is empty
+ if [ "$(echo "${dirlist}" | wc -l)" -gt 1 ]; then
+ ${dep_list}print_mtime "$1"
+
+ echo "${dirlist}" | \
+ while read x; do
+ ${dep_list}parse ${x}
+ done
+ fi
+}
+
+# if only one file is specified and it is .cpio file then use it direct as fs
+# if a directory is specified then add all files in given direcotry to fs
+# if a regular file is specified assume it is in gen_initramfs format
+input_file() {
+ source="$1"
+ if [ -f "$1" ]; then
+ ${dep_list}header "$1"
+ is_cpio="$(echo "$1" | sed 's/^.*\.cpio\(\..*\)\{0,1\}/cpio/')"
+ if [ $2 -eq 0 -a ${is_cpio} = "cpio" ]; then
+ cpio_file=$1
+ echo "$1" | grep -q '^.*\.cpio\..*' && is_cpio_compressed="compressed"
+ [ ! -z ${dep_list} ] && echo "$1"
+ return 0
+ fi
+ if [ -z ${dep_list} ]; then
+ print_mtime "$1" >> ${output}
+ cat "$1" >> ${output}
+ else
+ echo "$1 \\"
+ cat "$1" | while read type dir file perm ; do
+ if [ "$type" = "file" ]; then
+ echo "$file \\";
+ fi
+ done
+ fi
+ elif [ -d "$1" ]; then
+ dir_filelist "$1"
+ else
+ echo " ${prog}: Cannot open '$1'" >&2
+ exit 1
+ fi
+}
+
+prog=$0
+root_uid=0
+root_gid=0
+dep_list=
+cpio_file=
+cpio_list=
+output="/dev/stdout"
+output_file=""
+is_cpio_compressed=
+compr="gzip -n -9 -f"
+
+arg="$1"
+case "$arg" in
+ "-l") # files included in initramfs - used by kbuild
+ dep_list="list_"
+ echo "deps_initramfs := $0 \\"
+ shift
+ ;;
+ "-o") # generate compressed cpio image named $1
+ shift
+ output_file="$1"
+ cpio_list="$(mktemp ${TMPDIR:-/tmp}/cpiolist.XXXXXX)"
+ output=${cpio_list}
+ echo "$output_file" | grep -q "\.gz$" \
+ && [ -x "`which gzip 2> /dev/null`" ] \
+ && compr="gzip -n -9 -f"
+ echo "$output_file" | grep -q "\.bz2$" \
+ && [ -x "`which bzip2 2> /dev/null`" ] \
+ && compr="bzip2 -9 -f"
+ echo "$output_file" | grep -q "\.lzma$" \
+ && [ -x "`which lzma 2> /dev/null`" ] \
+ && compr="lzma -9 -f"
+ echo "$output_file" | grep -q "\.xz$" \
+ && [ -x "`which xz 2> /dev/null`" ] \
+ && compr="xz --check=crc32 --lzma2=dict=1MiB"
+ echo "$output_file" | grep -q "\.lzo$" \
+ && [ -x "`which lzop 2> /dev/null`" ] \
+ && compr="lzop -9 -f"
+ echo "$output_file" | grep -q "\.lz4$" \
+ && [ -x "`which lz4 2> /dev/null`" ] \
+ && compr="lz4 -l -9 -f"
+ echo "$output_file" | grep -q "\.cpio$" && compr="cat"
+ shift
+ ;;
+esac
+while [ $# -gt 0 ]; do
+ arg="$1"
+ shift
+ case "$arg" in
+ "-u") # map $1 to uid=0 (root)
+ root_uid="$1"
+ [ "$root_uid" = "-1" ] && root_uid=$(id -u || echo 0)
+ shift
+ ;;
+ "-g") # map $1 to gid=0 (root)
+ root_gid="$1"
+ [ "$root_gid" = "-1" ] && root_gid=$(id -g || echo 0)
+ shift
+ ;;
+ "-d") # display default initramfs list
+ default_list="$arg"
+ ${dep_list}default_initramfs
+ ;;
+ "-h")
+ usage
+ exit 0
+ ;;
+ *)
+ case "$arg" in
+ "-"*)
+ unknown_option
+ ;;
+ *) # input file/dir - process it
+ input_file "$arg" "$#"
+ ;;
+ esac
+ ;;
+ esac
+done
+
+# If output_file is set we will generate cpio archive and compress it
+# we are careful to delete tmp files
+if [ ! -z ${output_file} ]; then
+ if [ -z ${cpio_file} ]; then
+ timestamp=
+ if test -n "$KBUILD_BUILD_TIMESTAMP"; then
+ timestamp="$(date -d"$KBUILD_BUILD_TIMESTAMP" +%s || :)"
+ if test -n "$timestamp"; then
+ timestamp="-t $timestamp"
+ fi
+ fi
+ cpio_tfile="$(mktemp ${TMPDIR:-/tmp}/cpiofile.XXXXXX)"
+ usr/gen_init_cpio $timestamp ${cpio_list} > ${cpio_tfile}
+ else
+ cpio_tfile=${cpio_file}
+ fi
+ rm ${cpio_list}
+ if [ "${is_cpio_compressed}" = "compressed" ]; then
+ cat ${cpio_tfile} > ${output_file}
+ else
+ (cat ${cpio_tfile} | ${compr} - > ${output_file}) \
+ || (rm -f ${output_file} ; false)
+ fi
+ [ -z ${cpio_file} ] && rm ${cpio_tfile}
+fi
+exit 0

View File

@ -0,0 +1,33 @@
From dcc2827ed6e701a65731c05b0297745559837217 Mon Sep 17 00:00:00 2001
From: Hal Feng <hal.feng@starfivetech.com>
Date: Fri, 12 May 2023 17:33:20 +0800
Subject: [PATCH 062/116] i2c: designware: Delete SMBus functionalities
The driver didn't implement the smbus interface,
so replace the SMBus functionalities with
I2C_FUNC_SMBUS_EMUL.
Signed-off-by: Hal Feng <hal.feng@starfivetech.com>
---
drivers/i2c/busses/i2c-designware-core.h | 10 ++++------
1 file changed, 4 insertions(+), 6 deletions(-)
--- a/drivers/i2c/busses/i2c-designware-core.h
+++ b/drivers/i2c/busses/i2c-designware-core.h
@@ -18,12 +18,10 @@
#include <linux/regmap.h>
#include <linux/types.h>
-#define DW_IC_DEFAULT_FUNCTIONALITY (I2C_FUNC_I2C | \
- I2C_FUNC_SMBUS_BYTE | \
- I2C_FUNC_SMBUS_BYTE_DATA | \
- I2C_FUNC_SMBUS_WORD_DATA | \
- I2C_FUNC_SMBUS_BLOCK_DATA | \
- I2C_FUNC_SMBUS_I2C_BLOCK)
+#define DW_IC_DEFAULT_FUNCTIONALITY (I2C_FUNC_I2C | (I2C_FUNC_SMBUS_EMUL \
+ & ~I2C_FUNC_SMBUS_QUICK \
+ & ~I2C_FUNC_SMBUS_PROC_CALL \
+ & ~I2C_FUNC_SMBUS_PEC))
#define DW_IC_CON_MASTER BIT(0)
#define DW_IC_CON_SPEED_STD (1 << 1)

View File

@ -0,0 +1,26 @@
From b61cefc6c785aa8a7177a0b535db746fd0047bd8 Mon Sep 17 00:00:00 2001
From: Ziv Xu <ziv.xu@starfivetech.com>
Date: Fri, 19 Jan 2024 15:22:55 +0800
Subject: [PATCH 063/116] drivers: mtd: gigadevice: add gd25lq256d 32M flash
support
add gd25lq256d 32M flash support
Signed-off-by: Ziv Xu <ziv.xu@starfivetech.com>
---
drivers/mtd/spi-nor/gigadevice.c | 4 ++++
1 file changed, 4 insertions(+)
--- a/drivers/mtd/spi-nor/gigadevice.c
+++ b/drivers/mtd/spi-nor/gigadevice.c
@@ -66,6 +66,10 @@ static const struct flash_info gigadevic
FLAGS(SPI_NOR_HAS_LOCK | SPI_NOR_HAS_TB)
NO_SFDP_FLAGS(SECT_4K | SPI_NOR_DUAL_READ |
SPI_NOR_QUAD_READ) },
+ { "gd25lq256d", INFO(0xc86019, 0, 64 * 1024, 512)
+ FLAGS( SPI_NOR_HAS_LOCK | SPI_NOR_HAS_TB | SPI_NOR_QUAD_PP)
+ NO_SFDP_FLAGS(SECT_4K | SPI_NOR_DUAL_READ |
+ SPI_NOR_QUAD_READ) },
{ "gd25q256", INFO(0xc84019, 0, 64 * 1024, 512)
PARSE_SFDP
FLAGS(SPI_NOR_HAS_LOCK | SPI_NOR_HAS_TB | SPI_NOR_TB_SR_BIT6)

View File

@ -0,0 +1,808 @@
From 76bc13aa12bd111f5da01e107f8d487b20b5a40c Mon Sep 17 00:00:00 2001
From: "shanlong.li" <shanlong.li@starfivetech.com>
Date: Thu, 8 Jun 2023 00:07:15 -0700
Subject: [PATCH 064/116] driver: mailbox: Add mailbox driver
Add mailbox driver.
Signed-off-by: shanlong.li <shanlong.li@starfivetech.com>
Signed-off-by: Hal Feng <hal.feng@starfivetech.com>
---
drivers/mailbox/Kconfig | 13 +
drivers/mailbox/Makefile | 4 +
drivers/mailbox/starfive_mailbox-test.c | 407 ++++++++++++++++++++++++
drivers/mailbox/starfive_mailbox.c | 347 ++++++++++++++++++++
4 files changed, 771 insertions(+)
create mode 100644 drivers/mailbox/starfive_mailbox-test.c
create mode 100644 drivers/mailbox/starfive_mailbox.c
--- a/drivers/mailbox/Kconfig
+++ b/drivers/mailbox/Kconfig
@@ -295,4 +295,17 @@ config QCOM_IPCC
acts as an interrupt controller for receiving interrupts from clients.
Say Y here if you want to build this driver.
+config STARFIVE_MBOX
+ tristate "Platform Starfive Mailbox"
+ depends on OF
+ help
+ Say Y here if you want to build a platform specific variant RISCV
+ controller driver.
+
+config STARFIVE_MBOX_TEST
+ tristate "Starfive Mailbox Test Client"
+ depends on OF
+ depends on HAS_IOMEM
+ help
+ Test client to help with testing new Controller driver implementations.
endif
--- a/drivers/mailbox/Makefile
+++ b/drivers/mailbox/Makefile
@@ -62,3 +62,7 @@ obj-$(CONFIG_SPRD_MBOX) += sprd-mailbox
obj-$(CONFIG_QCOM_IPCC) += qcom-ipcc.o
obj-$(CONFIG_APPLE_MAILBOX) += apple-mailbox.o
+
+obj-$(CONFIG_STARFIVE_MBOX) += starfive_mailbox.o
+
+obj-$(CONFIG_STARFIVE_MBOX_TEST) += starfive_mailbox-test.o
--- /dev/null
+++ b/drivers/mailbox/starfive_mailbox-test.c
@@ -0,0 +1,407 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * Copyright (C) 2015 ST Microelectronics
+ *
+ * Author: Lee Jones <lee.jones@linaro.org>
+ */
+
+#include <linux/debugfs.h>
+#include <linux/err.h>
+#include <linux/fs.h>
+#include <linux/io.h>
+#include <linux/kernel.h>
+#include <linux/mailbox_client.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/platform_device.h>
+#include <linux/poll.h>
+#include <linux/slab.h>
+#include <linux/uaccess.h>
+#include <linux/sched/signal.h>
+
+#include <linux/mailbox_controller.h>
+
+#define MBOX_MAX_SIG_LEN 8
+#define MBOX_MAX_MSG_LEN 16
+#define MBOX_BYTES_PER_LINE 16
+#define MBOX_HEXDUMP_LINE_LEN ((MBOX_BYTES_PER_LINE * 4) + 2)
+#define MBOX_HEXDUMP_MAX_LEN (MBOX_HEXDUMP_LINE_LEN * (MBOX_MAX_MSG_LEN / MBOX_BYTES_PER_LINE))
+
+static bool mbox_data_ready;
+
+struct mbox_test_device {
+ struct device *dev;
+ void __iomem *tx_mmio;
+ void __iomem *rx_mmio;
+ struct mbox_chan *tx_channel;
+ struct mbox_chan *rx_channel;
+ char *rx_buffer;
+ char *signal;
+ char *message;
+ spinlock_t lock;
+ wait_queue_head_t waitq;
+ struct fasync_struct *async_queue;
+ struct dentry *root_debugfs_dir;
+};
+
+static ssize_t mbox_test_signal_write(struct file *filp,
+ const char __user *userbuf,
+ size_t count, loff_t *ppos)
+{
+ struct mbox_test_device *tdev = filp->private_data;
+
+ if (!tdev->tx_channel) {
+ dev_err(tdev->dev, "Channel cannot do Tx\n");
+ return -EINVAL;
+ }
+
+ if (count > MBOX_MAX_SIG_LEN) {
+ dev_err(tdev->dev,
+ "Signal length %zd greater than max allowed %d\n",
+ count, MBOX_MAX_SIG_LEN);
+ return -EINVAL;
+ }
+
+ /* Only allocate memory if we need to */
+ if (!tdev->signal) {
+ tdev->signal = kzalloc(MBOX_MAX_SIG_LEN, GFP_KERNEL);
+ if (!tdev->signal)
+ return -ENOMEM;
+ }
+
+ if (copy_from_user(tdev->signal, userbuf, count)) {
+ kfree(tdev->signal);
+ tdev->signal = NULL;
+ return -EFAULT;
+ }
+
+ return count;
+}
+
+static const struct file_operations mbox_test_signal_ops = {
+ .write = mbox_test_signal_write,
+ .open = simple_open,
+ .llseek = generic_file_llseek,
+};
+
+static int mbox_test_message_fasync(int fd, struct file *filp, int on)
+{
+ struct mbox_test_device *tdev = filp->private_data;
+
+ return fasync_helper(fd, filp, on, &tdev->async_queue);
+}
+
+static ssize_t mbox_test_message_write(struct file *filp,
+ const char __user *userbuf,
+ size_t count, loff_t *ppos)
+{
+ struct mbox_test_device *tdev = filp->private_data;
+ void *data;
+ int ret;
+
+ if (!tdev->tx_channel) {
+ dev_err(tdev->dev, "Channel cannot do Tx\n");
+ return -EINVAL;
+ }
+
+ if (count > MBOX_MAX_MSG_LEN) {
+ dev_err(tdev->dev,
+ "Message length %zd greater than max allowed %d\n",
+ count, MBOX_MAX_MSG_LEN);
+ return -EINVAL;
+ }
+
+ tdev->message = kzalloc(MBOX_MAX_MSG_LEN, GFP_KERNEL);
+ if (!tdev->message)
+ return -ENOMEM;
+
+ ret = copy_from_user(tdev->message, userbuf, count);
+ if (ret) {
+ ret = -EFAULT;
+ goto out;
+ }
+
+ if (tdev->tx_mmio && tdev->signal) {
+ print_hex_dump_bytes("Client: Sending: Signal: ", DUMP_PREFIX_ADDRESS,
+ tdev->signal, MBOX_MAX_SIG_LEN);
+
+ data = tdev->signal;
+ } else
+ data = tdev->message;
+
+ print_hex_dump_bytes("Client: Sending: Message: ", DUMP_PREFIX_ADDRESS,
+ tdev->message, MBOX_MAX_MSG_LEN);
+
+ ret = mbox_send_message(tdev->tx_channel, data);
+ mbox_chan_txdone(tdev->tx_channel, ret);
+ if (ret < 0)
+ dev_err(tdev->dev, "Failed to send message via mailbox\n");
+
+out:
+ kfree(tdev->signal);
+ kfree(tdev->message);
+ tdev->signal = NULL;
+
+ return ret < 0 ? ret : count;
+}
+
+static bool mbox_test_message_data_ready(struct mbox_test_device *tdev)
+{
+ bool data_ready;
+ unsigned long flags;
+
+ spin_lock_irqsave(&tdev->lock, flags);
+ data_ready = mbox_data_ready;
+ spin_unlock_irqrestore(&tdev->lock, flags);
+
+ return data_ready;
+}
+
+static ssize_t mbox_test_message_read(struct file *filp, char __user *userbuf,
+ size_t count, loff_t *ppos)
+{
+ struct mbox_test_device *tdev = filp->private_data;
+ unsigned long flags;
+ char *touser, *ptr;
+ int ret;
+
+ touser = kzalloc(MBOX_HEXDUMP_MAX_LEN + 1, GFP_KERNEL);
+ if (!touser)
+ return -ENOMEM;
+
+ if (!tdev->rx_channel) {
+ ret = snprintf(touser, 20, "<NO RX CAPABILITY>\n");
+ ret = simple_read_from_buffer(userbuf, count, ppos,
+ touser, ret);
+ goto kfree_err;
+ }
+
+ do {
+ if (mbox_test_message_data_ready(tdev))
+ break;
+
+ if (filp->f_flags & O_NONBLOCK) {
+ ret = -EAGAIN;
+ goto waitq_err;
+ }
+
+ if (signal_pending(current)) {
+ ret = -ERESTARTSYS;
+ goto waitq_err;
+ }
+ schedule();
+
+ } while (1);
+
+ spin_lock_irqsave(&tdev->lock, flags);
+
+ ptr = tdev->rx_buffer;
+
+ mbox_data_ready = false;
+
+ spin_unlock_irqrestore(&tdev->lock, flags);
+ if (copy_to_user((void __user *)userbuf, ptr, 4))
+ ret = -EFAULT;
+
+waitq_err:
+ __set_current_state(TASK_RUNNING);
+kfree_err:
+ kfree(touser);
+ return ret;
+}
+
+static __poll_t
+mbox_test_message_poll(struct file *filp, struct poll_table_struct *wait)
+{
+ struct mbox_test_device *tdev = filp->private_data;
+
+ poll_wait(filp, &tdev->waitq, wait);
+
+ if (mbox_test_message_data_ready(tdev))
+ return EPOLLIN | EPOLLRDNORM;
+ return 0;
+}
+
+static const struct file_operations mbox_test_message_ops = {
+ .write = mbox_test_message_write,
+ .read = mbox_test_message_read,
+ .fasync = mbox_test_message_fasync,
+ .poll = mbox_test_message_poll,
+ .open = simple_open,
+ .llseek = generic_file_llseek,
+};
+
+static int mbox_test_add_debugfs(struct platform_device *pdev,
+ struct mbox_test_device *tdev)
+{
+ if (!debugfs_initialized())
+ return 0;
+
+ tdev->root_debugfs_dir = debugfs_create_dir(dev_name(&pdev->dev), NULL);
+ if (!tdev->root_debugfs_dir) {
+ dev_err(&pdev->dev, "Failed to create Mailbox debugfs\n");
+ return -EINVAL;
+ }
+
+ debugfs_create_file("message", 0600, tdev->root_debugfs_dir,
+ tdev, &mbox_test_message_ops);
+
+ debugfs_create_file("signal", 0200, tdev->root_debugfs_dir,
+ tdev, &mbox_test_signal_ops);
+
+ return 0;
+}
+
+static void mbox_test_receive_message(struct mbox_client *client, void *message)
+{
+ struct mbox_test_device *tdev = dev_get_drvdata(client->dev);
+ unsigned long flags;
+
+ spin_lock_irqsave(&tdev->lock, flags);
+ if (tdev->rx_mmio) {
+ memcpy_fromio(tdev->rx_buffer, tdev->rx_mmio, MBOX_MAX_MSG_LEN);
+ print_hex_dump_bytes("Client: Received [MMIO]: ", DUMP_PREFIX_ADDRESS,
+ tdev->rx_buffer, MBOX_MAX_MSG_LEN);
+ } else if (message) {
+ print_hex_dump_bytes("Client: Received [API]: ", DUMP_PREFIX_ADDRESS,
+ message, MBOX_MAX_MSG_LEN);
+ memcpy(tdev->rx_buffer, message, MBOX_MAX_MSG_LEN);
+ }
+ mbox_data_ready = true;
+ spin_unlock_irqrestore(&tdev->lock, flags);
+}
+
+static void mbox_test_prepare_message(struct mbox_client *client, void *message)
+{
+ struct mbox_test_device *tdev = dev_get_drvdata(client->dev);
+
+ if (tdev->tx_mmio) {
+ if (tdev->signal)
+ memcpy_toio(tdev->tx_mmio, tdev->message, MBOX_MAX_MSG_LEN);
+ else
+ memcpy_toio(tdev->tx_mmio, message, MBOX_MAX_MSG_LEN);
+ }
+}
+
+static struct mbox_chan *
+mbox_test_request_channel(struct platform_device *pdev, const char *name)
+{
+ struct mbox_client *client;
+ struct mbox_chan *channel;
+
+ client = devm_kzalloc(&pdev->dev, sizeof(*client), GFP_KERNEL);
+ if (!client)
+ return ERR_PTR(-ENOMEM);
+
+ client->dev = &pdev->dev;
+ client->rx_callback = mbox_test_receive_message;
+ client->tx_prepare = mbox_test_prepare_message;
+ client->tx_block = false;
+ client->knows_txdone = false;
+ client->tx_tout = 500;
+
+ channel = mbox_request_channel_byname(client, name);
+ if (IS_ERR(channel)) {
+ dev_warn(&pdev->dev, "Failed to request %s channel\n", name);
+ return NULL;
+ }
+
+ return channel;
+}
+
+static int mbox_test_probe(struct platform_device *pdev)
+{
+ struct mbox_test_device *tdev;
+ struct resource *res;
+ resource_size_t size;
+ int ret;
+
+ tdev = devm_kzalloc(&pdev->dev, sizeof(*tdev), GFP_KERNEL);
+ if (!tdev)
+ return -ENOMEM;
+
+ /* It's okay for MMIO to be NULL */
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ tdev->tx_mmio = devm_ioremap_resource(&pdev->dev, res);
+ if (PTR_ERR(tdev->tx_mmio) == -EBUSY) {
+ /* if reserved area in SRAM, try just ioremap */
+ size = resource_size(res);
+ tdev->tx_mmio = devm_ioremap(&pdev->dev, res->start, size);
+ } else if (IS_ERR(tdev->tx_mmio)) {
+ tdev->tx_mmio = NULL;
+ }
+
+ /* If specified, second reg entry is Rx MMIO */
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 1);
+ tdev->rx_mmio = devm_ioremap_resource(&pdev->dev, res);
+ if (PTR_ERR(tdev->rx_mmio) == -EBUSY) {
+ size = resource_size(res);
+ tdev->rx_mmio = devm_ioremap(&pdev->dev, res->start, size);
+ } else if (IS_ERR(tdev->rx_mmio)) {
+ tdev->rx_mmio = tdev->tx_mmio;
+ }
+
+ tdev->tx_channel = mbox_test_request_channel(pdev, "tx");
+ tdev->rx_channel = mbox_test_request_channel(pdev, "rx");
+
+ if (!tdev->tx_channel && !tdev->rx_channel)
+ return -EPROBE_DEFER;
+
+ /* If Rx is not specified but has Rx MMIO, then Rx = Tx */
+ if (!tdev->rx_channel && (tdev->rx_mmio != tdev->tx_mmio))
+ tdev->rx_channel = tdev->tx_channel;
+
+ tdev->dev = &pdev->dev;
+ platform_set_drvdata(pdev, tdev);
+
+ spin_lock_init(&tdev->lock);
+
+ if (tdev->rx_channel) {
+ tdev->rx_buffer = devm_kzalloc(&pdev->dev,
+ MBOX_MAX_MSG_LEN, GFP_KERNEL);
+ if (!tdev->rx_buffer)
+ return -ENOMEM;
+ }
+
+ ret = mbox_test_add_debugfs(pdev, tdev);
+ if (ret)
+ return ret;
+
+ dev_info(&pdev->dev, "Successfully registered\n");
+
+ return 0;
+}
+
+static int mbox_test_remove(struct platform_device *pdev)
+{
+ struct mbox_test_device *tdev = platform_get_drvdata(pdev);
+
+ debugfs_remove_recursive(tdev->root_debugfs_dir);
+
+ if (tdev->tx_channel)
+ mbox_free_channel(tdev->tx_channel);
+ if (tdev->rx_channel)
+ mbox_free_channel(tdev->rx_channel);
+
+ return 0;
+}
+
+static const struct of_device_id mbox_test_match[] = {
+ { .compatible = "starfive,mailbox-test" },
+ {},
+};
+MODULE_DEVICE_TABLE(of, mbox_test_match);
+
+static struct platform_driver mbox_test_driver = {
+ .driver = {
+ .name = "mailbox_test",
+ .of_match_table = mbox_test_match,
+ },
+ .probe = mbox_test_probe,
+ .remove = mbox_test_remove,
+};
+module_platform_driver(mbox_test_driver);
+
+MODULE_DESCRIPTION("Generic Mailbox Testing Facility");
+MODULE_AUTHOR("Lee Jones <lee.jones@linaro.org");
+MODULE_LICENSE("GPL v2");
--- /dev/null
+++ b/drivers/mailbox/starfive_mailbox.c
@@ -0,0 +1,347 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * mailbox driver for StarFive JH7110 SoC
+ *
+ * Copyright (c) 2021 StarFive Technology Co., Ltd.
+ * Author: Shanlong Li <shanlong.li@starfivetech.com>
+ */
+
+#include <linux/bitops.h>
+#include <linux/delay.h>
+#include <linux/device.h>
+#include <linux/err.h>
+#include <linux/interrupt.h>
+#include <linux/io.h>
+#include <linux/iopoll.h>
+#include <linux/mailbox_controller.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/slab.h>
+#include <linux/clk.h>
+#include <linux/reset.h>
+#include <linux/pm_runtime.h>
+
+#include "mailbox.h"
+
+#define MBOX_CHAN_MAX 4
+
+#define MBOX_BASE(mbox, ch) ((mbox)->base + ((ch) * 0x10))
+#define MBOX_IRQ_REG 0x00
+#define MBOX_SET_REG 0x04
+#define MBOX_CLR_REG 0x08
+#define MBOX_CMD_REG 0x0c
+#define MBC_PEND_SMRY 0x100
+
+typedef enum {
+ MAILBOX_CORE_U7 = 0,
+ MAILBOX_CORE_HIFI4,
+ MAILBOX_CORE_E2,
+ MAILBOX_CORE_RSVD0,
+ MAILBOX_CORE_NUM,
+} mailbox_core_t;
+
+struct mailbox_irq_name_c{
+ int id;
+ char name[16];
+};
+
+static const struct mailbox_irq_name_c irq_peer_name[MBOX_CHAN_MAX] = {
+ {MAILBOX_CORE_U7, "u74_core"},
+ {MAILBOX_CORE_HIFI4, "hifi4_core"},
+ {MAILBOX_CORE_E2, "e24_core"},
+ {MAILBOX_CORE_RSVD0, "" },
+};
+
+/**
+ * starfive mailbox channel information
+ *
+ * A channel can be used for TX or RX, it can trigger remote
+ * processor interrupt to notify remote processor and can receive
+ * interrupt if has incoming message.
+ *
+ * @dst_irq: Interrupt vector for remote processor
+ * @core_id: id for remote processor
+ */
+struct starfive_chan_info {
+ unsigned int dst_irq;
+ mailbox_core_t core_id;
+};
+
+/**
+ * starfive mailbox controller data
+ *
+ * Mailbox controller includes 4 channels and can allocate
+ * channel for message transferring.
+ *
+ * @dev: Device to which it is attached
+ * @base: Base address of the register mapping region
+ * @chan: Representation of channels in mailbox controller
+ * @mchan: Representation of channel info
+ * @controller: Representation of a communication channel controller
+ */
+struct starfive_mbox {
+ struct device *dev;
+ void __iomem *base;
+ struct mbox_chan chan[MBOX_CHAN_MAX];
+ struct starfive_chan_info mchan[MBOX_CHAN_MAX];
+ struct mbox_controller controller;
+ struct clk *clk;
+ struct reset_control *rst_rresetn;
+};
+
+static struct starfive_mbox *to_starfive_mbox(struct mbox_controller *mbox)
+{
+ return container_of(mbox, struct starfive_mbox, controller);
+}
+
+static struct mbox_chan *
+starfive_of_mbox_index_xlate(struct mbox_controller *mbox,
+ const struct of_phandle_args *sp)
+{
+ struct starfive_mbox *sbox;
+
+ int ind = sp->args[0];
+ int core_id = sp->args[1];
+
+ if (ind >= mbox->num_chans || core_id >= MAILBOX_CORE_NUM)
+ return ERR_PTR(-EINVAL);
+
+ sbox = to_starfive_mbox(mbox);
+
+ sbox->mchan[ind].core_id = core_id;
+
+ return &mbox->chans[ind];
+}
+
+static irqreturn_t starfive_rx_irq_handler(int irq, void *p)
+{
+ struct mbox_chan *chan = p;
+ unsigned long ch = (unsigned long)chan->con_priv;
+ struct starfive_mbox *mbox = to_starfive_mbox(chan->mbox);
+ void __iomem *base = MBOX_BASE(mbox, ch);
+ u32 val;
+
+ val = readl(base + MBOX_CMD_REG);
+ if (!val)
+ return IRQ_NONE;
+
+ mbox_chan_received_data(chan, (void *)&val);
+ writel(val, base + MBOX_CLR_REG);
+ return IRQ_HANDLED;
+}
+
+static int starfive_mbox_check_state(struct mbox_chan *chan)
+{
+ unsigned long ch = (unsigned long)chan->con_priv;
+ struct starfive_mbox *mbox = to_starfive_mbox(chan->mbox);
+ unsigned long irq_flag = IRQF_SHARED;
+ long ret = 0;
+
+ pm_runtime_get_sync(mbox->dev);
+ /* MAILBOX should be with IRQF_NO_SUSPEND set */
+ if (!mbox->dev->pm_domain)
+ irq_flag |= IRQF_NO_SUSPEND;
+
+ /* Mailbox is idle so directly bail out */
+ if (readl(mbox->base + MBC_PEND_SMRY) & BIT(ch))
+ return -EBUSY;
+
+ if (mbox->mchan[ch].dst_irq > 0) {
+ dev_dbg(mbox->dev, "%s: host IRQ = %d, ch:%ld", __func__, mbox->mchan[ch].dst_irq, ch);
+ ret = devm_request_irq(mbox->dev, mbox->mchan[ch].dst_irq, starfive_rx_irq_handler,
+ irq_flag, irq_peer_name[ch].name, chan);
+ if (ret < 0)
+ dev_err(mbox->dev, "request_irq %d failed\n", mbox->mchan[ch].dst_irq);
+ }
+
+ return ret;
+}
+
+static int starfive_mbox_startup(struct mbox_chan *chan)
+{
+ return starfive_mbox_check_state(chan);
+}
+
+static void starfive_mbox_shutdown(struct mbox_chan *chan)
+{
+ struct starfive_mbox *mbox = to_starfive_mbox(chan->mbox);
+ unsigned long ch = (unsigned long)chan->con_priv;
+ void __iomem *base = MBOX_BASE(mbox, ch);
+
+ writel(0x0, base + MBOX_IRQ_REG);
+ writel(0x0, base + MBOX_CLR_REG);
+
+ if (mbox->mchan[ch].dst_irq > 0)
+ devm_free_irq(mbox->dev, mbox->mchan[ch].dst_irq, chan);
+ pm_runtime_put_sync(mbox->dev);
+}
+
+static int starfive_mbox_send_data(struct mbox_chan *chan, void *msg)
+{
+ unsigned long ch = (unsigned long)chan->con_priv;
+ struct starfive_mbox *mbox = to_starfive_mbox(chan->mbox);
+ struct starfive_chan_info *mchan = &mbox->mchan[ch];
+ void __iomem *base = MBOX_BASE(mbox, ch);
+ u32 *buf = msg;
+
+ /* Ensure channel is released */
+ if (readl(mbox->base + MBC_PEND_SMRY) & BIT(ch)) {
+ pr_debug("%s:%d. busy\n", __func__, __LINE__);
+ return -EBUSY;
+ }
+
+ /* Clear mask for destination interrupt */
+ writel(BIT(mchan->core_id), base + MBOX_IRQ_REG);
+
+ /* Fill message data */
+ writel(*buf, base + MBOX_SET_REG);
+ return 0;
+}
+
+static struct mbox_chan_ops starfive_mbox_ops = {
+ .startup = starfive_mbox_startup,
+ .send_data = starfive_mbox_send_data,
+ .shutdown = starfive_mbox_shutdown,
+};
+
+static const struct of_device_id starfive_mbox_of_match[] = {
+ { .compatible = "starfive,mail_box",},
+ {},
+};
+
+MODULE_DEVICE_TABLE(of, starfive_mbox_of_match);
+
+void starfive_mailbox_init(struct starfive_mbox *mbox)
+{
+ mbox->clk = devm_clk_get_optional(mbox->dev, "clk_apb");
+ if (IS_ERR(mbox->clk)) {
+ dev_err(mbox->dev, "failed to get mailbox\n");
+ return;
+ }
+
+ mbox->rst_rresetn = devm_reset_control_get_exclusive(mbox->dev, "mbx_rre");
+ if (IS_ERR(mbox->rst_rresetn)) {
+ dev_err(mbox->dev, "failed to get mailbox reset\n");
+ return;
+ }
+
+ clk_prepare_enable(mbox->clk);
+ reset_control_deassert(mbox->rst_rresetn);
+}
+
+static int starfive_mbox_probe(struct platform_device *pdev)
+{
+ struct device *dev = &pdev->dev;
+ struct starfive_mbox *mbox;
+ struct mbox_chan *chan;
+ struct resource *res;
+ unsigned long ch;
+ int err;
+
+ mbox = devm_kzalloc(dev, sizeof(*mbox), GFP_KERNEL);
+ if (!mbox)
+ return -ENOMEM;
+
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ mbox->base = devm_ioremap_resource(dev, res);
+ mbox->dev = dev;
+
+ if (IS_ERR(mbox->base))
+ return PTR_ERR(mbox->base);
+
+ starfive_mailbox_init(mbox);
+
+ mbox->controller.dev = dev;
+ mbox->controller.chans = mbox->chan;
+ mbox->controller.num_chans = MBOX_CHAN_MAX;
+ mbox->controller.ops = &starfive_mbox_ops;
+ mbox->controller.of_xlate = starfive_of_mbox_index_xlate;
+ mbox->controller.txdone_irq = true;
+ mbox->controller.txdone_poll = false;
+
+ /* Initialize mailbox channel data */
+ chan = mbox->chan;
+ for (ch = 0; ch < MBOX_CHAN_MAX; ch++) {
+ mbox->mchan[ch].dst_irq = 0;
+ mbox->mchan[ch].core_id = (mailbox_core_t)ch;
+ chan[ch].con_priv = (void *)ch;
+ }
+ mbox->mchan[MAILBOX_CORE_HIFI4].dst_irq = platform_get_irq(pdev, 0);
+ mbox->mchan[MAILBOX_CORE_E2].dst_irq = platform_get_irq(pdev, 1);
+
+ err = mbox_controller_register(&mbox->controller);
+ if (err) {
+ dev_err(dev, "Failed to register mailbox %d\n", err);
+ return err;
+ }
+
+ platform_set_drvdata(pdev, mbox);
+ dev_info(dev, "Mailbox enabled\n");
+ pm_runtime_set_active(dev);
+ pm_runtime_enable(dev);
+
+ return 0;
+}
+
+static int starfive_mbox_remove(struct platform_device *pdev)
+{
+ struct starfive_mbox *mbox = platform_get_drvdata(pdev);
+
+ mbox_controller_unregister(&mbox->controller);
+ devm_clk_put(mbox->dev, mbox->clk);
+ pm_runtime_disable(mbox->dev);
+
+ return 0;
+}
+
+static int __maybe_unused starfive_mbox_suspend(struct device *dev)
+{
+ struct starfive_mbox *mbox = dev_get_drvdata(dev);
+
+ clk_disable_unprepare(mbox->clk);
+
+ return 0;
+}
+
+static int __maybe_unused starfive_mbox_resume(struct device *dev)
+{
+ struct starfive_mbox *mbox = dev_get_drvdata(dev);
+ int ret;
+
+ ret = clk_prepare_enable(mbox->clk);
+ if (ret)
+ dev_err(dev, "failed to enable clock\n");
+
+ return ret;
+}
+
+static const struct dev_pm_ops starfive_mbox_pm_ops = {
+ .suspend = starfive_mbox_suspend,
+ .resume = starfive_mbox_resume,
+ SET_RUNTIME_PM_OPS(starfive_mbox_suspend, starfive_mbox_resume, NULL)
+};
+static struct platform_driver starfive_mbox_driver = {
+ .probe = starfive_mbox_probe,
+ .remove = starfive_mbox_remove,
+ .driver = {
+ .name = "mailbox",
+ .of_match_table = starfive_mbox_of_match,
+ .pm = &starfive_mbox_pm_ops,
+ },
+};
+
+static int __init starfive_mbox_init(void)
+{
+ return platform_driver_register(&starfive_mbox_driver);
+}
+core_initcall(starfive_mbox_init);
+
+static void __exit starfive_mbox_exit(void)
+{
+ platform_driver_unregister(&starfive_mbox_driver);
+}
+module_exit(starfive_mbox_exit);
+
+MODULE_DESCRIPTION("StarFive Mailbox Controller driver");
+MODULE_AUTHOR("Shanlong Li <shanlong.li@starfivetech.com>");
+MODULE_LICENSE("GPL");

View File

@ -0,0 +1,789 @@
From 0f44bd6bec708782f38bba4d03deecf927d1c83d Mon Sep 17 00:00:00 2001
From: "ziv.xu" <ziv.xu@starfivetech.com>
Date: Fri, 9 Jun 2023 15:31:53 +0800
Subject: [PATCH 065/116] driver: rtc: Add StarFive JH7110 rtc driver
Add RTC driver and support for StarFive JH7110 SoC.
Signed-off-by: ziv.xu <ziv.xu@starfivetech.com>
Signed-off-by: Hal Feng <hal.feng@starfivetech.com>
---
drivers/rtc/Kconfig | 8 +
drivers/rtc/Makefile | 1 +
drivers/rtc/rtc-starfive.c | 743 +++++++++++++++++++++++++++++++++++++
3 files changed, 752 insertions(+)
create mode 100644 drivers/rtc/rtc-starfive.c
--- a/drivers/rtc/Kconfig
+++ b/drivers/rtc/Kconfig
@@ -1327,6 +1327,14 @@ config RTC_DRV_NTXEC
embedded controller found in certain e-book readers designed by the
original design manufacturer Netronix.
+config RTC_DRV_STARFIVE
+ tristate "StarFive 32.768k-RTC"
+ depends on ARCH_STARFIVE
+ depends on OF
+ help
+ If you say Y here you will get support for the RTC found on
+ StarFive SOCS.
+
comment "on-CPU RTC drivers"
config RTC_DRV_ASM9260
--- a/drivers/rtc/Makefile
+++ b/drivers/rtc/Makefile
@@ -163,6 +163,7 @@ obj-$(CONFIG_RTC_DRV_SH) += rtc-sh.o
obj-$(CONFIG_RTC_DRV_SNVS) += rtc-snvs.o
obj-$(CONFIG_RTC_DRV_SPEAR) += rtc-spear.o
obj-$(CONFIG_RTC_DRV_STARFIRE) += rtc-starfire.o
+obj-$(CONFIG_RTC_DRV_STARFIVE) += rtc-starfive.o
obj-$(CONFIG_RTC_DRV_STK17TA8) += rtc-stk17ta8.o
obj-$(CONFIG_RTC_DRV_ST_LPC) += rtc-st-lpc.o
obj-$(CONFIG_RTC_DRV_STM32) += rtc-stm32.o
--- /dev/null
+++ b/drivers/rtc/rtc-starfive.c
@@ -0,0 +1,743 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * RTC driver for the StarFive JH7110 SoC
+ *
+ * Copyright (C) 2021 StarFive Technology Co., Ltd.
+ */
+
+#include <asm/delay.h>
+#include <linux/bcd.h>
+#include <linux/bitfield.h>
+#include <linux/clk.h>
+#include <linux/reset.h>
+#include <linux/completion.h>
+#include <linux/interrupt.h>
+#include <linux/io.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/of_irq.h>
+#include <linux/iopoll.h>
+#include <linux/platform_device.h>
+#include <linux/rtc.h>
+
+/* Registers */
+#define SFT_RTC_CFG 0x00
+#define SFT_RTC_SW_CAL_VALUE 0x04
+#define SFT_RTC_HW_CAL_CFG 0x08
+#define SFT_RTC_CMP_CFG 0x0C
+#define SFT_RTC_IRQ_EN 0x10
+#define SFT_RTC_IRQ_EVEVT 0x14
+#define SFT_RTC_IRQ_STATUS 0x18
+#define SFT_RTC_CAL_VALUE 0x24
+#define SFT_RTC_CFG_TIME 0x28
+#define SFT_RTC_CFG_DATE 0x2C
+#define SFT_RTC_ACT_TIME 0x34
+#define SFT_RTC_ACT_DATE 0x38
+#define SFT_RTC_TIME 0x3C
+#define SFT_RTC_DATE 0x40
+#define SFT_RTC_TIME_LATCH 0x44
+#define SFT_RTC_DATE_LATCH 0x48
+
+/* RTC_CFG */
+#define RTC_CFG_ENABLE_SHIFT 0 /* RW: RTC Enable. */
+#define RTC_CFG_CAL_EN_HW_SHIFT 1 /* RW: Enable of hardware calibretion. */
+#define RTC_CFG_CAL_SEL_SHIFT 2 /* RW: select the hw/sw calibretion mode.*/
+#define RTC_CFG_HOUR_MODE_SHIFT 3 /* RW: time hour mode. 24h|12h */
+
+/* RTC_SW_CAL_VALUE */
+#define RTC_SW_CAL_VALUE_MASK GENMASK(15, 0)
+#define RTC_SW_CAL_MAX RTC_SW_CAL_VALUE_MASK
+#define RTC_SW_CAL_MIN 0
+#define RTC_TICKS_PER_SEC 32768 /* Number of ticks per second */
+#define RTC_PPB_MULT 1000000000LL /* Multiplier for ppb conversions */
+
+/* RTC_HW_CAL_CFG */
+#define RTC_HW_CAL_REF_SEL_SHIFT 0
+#define RTC_HW_CAL_FRQ_SEL_SHIFT 1
+
+/* IRQ_EN/IRQ_EVEVT/IRQ_STATUS */
+#define RTC_IRQ_CAL_START BIT(0)
+#define RTC_IRQ_CAL_FINISH BIT(1)
+#define RTC_IRQ_CMP BIT(2)
+#define RTC_IRQ_1SEC BIT(3)
+#define RTC_IRQ_ALAEM BIT(4)
+#define RTC_IRQ_EVT_UPDATE_PSE BIT(31) /* WO: Enable of update time&&date, IRQ_EVEVT only */
+#define RTC_IRQ_ALL (RTC_IRQ_CAL_START \
+ | RTC_IRQ_CAL_FINISH \
+ | RTC_IRQ_CMP \
+ | RTC_IRQ_1SEC \
+ | RTC_IRQ_ALAEM)
+
+/* CAL_VALUE */
+#define RTC_CAL_VALUE_MASK GENMASK(15, 0)
+
+/* CFG_TIME/ACT_TIME/RTC_TIME */
+#define TIME_SEC_MASK GENMASK(6, 0)
+#define TIME_MIN_MASK GENMASK(13, 7)
+#define TIME_HOUR_MASK GENMASK(20, 14)
+
+/* CFG_DATE/ACT_DATE/RTC_DATE */
+#define DATE_DAY_MASK GENMASK(5, 0)
+#define DATE_MON_MASK GENMASK(10, 6)
+#define DATE_YEAR_MASK GENMASK(18, 11)
+
+#define INT_TIMEOUT_US 180
+
+enum RTC_HOUR_MODE {
+ RTC_HOUR_MODE_12H = 0,
+ RTC_HOUR_MODE_24H = 1
+};
+
+enum RTC_CAL_MODE {
+ RTC_CAL_MODE_SW = 0,
+ RTC_CAL_MODE_HW = 1
+};
+
+enum RTC_HW_CAL_REF_MODE {
+ RTC_CAL_CLK_REF = 0,
+ RTC_CAL_CLK_MARK = 1
+};
+
+static const unsigned long refclk_list[] = {
+ 1000000,
+ 2000000,
+ 4000000,
+ 5927000,
+ 6000000,
+ 7200000,
+ 8000000,
+ 10250000,
+ 11059200,
+ 12000000,
+ 12288000,
+ 13560000,
+ 16000000,
+ 19200000,
+ 20000000,
+ 22118000,
+ 24000000,
+ 24567000,
+ 25000000,
+ 26000000,
+ 27000000,
+ 30000000,
+ 32000000,
+ 33868800,
+ 36000000,
+ 36860000,
+ 40000000,
+ 44000000,
+ 50000000,
+ 54000000,
+ 28224000,
+ 28000000,
+};
+
+struct sft_rtc {
+ struct rtc_device *rtc_dev;
+ struct completion cal_done;
+ struct completion onesec_done;
+ struct clk *pclk;
+ struct clk *cal_clk;
+ struct reset_control *rst_array;
+ int hw_cal_map;
+ void __iomem *regs;
+ int rtc_irq;
+ int ms_pulse_irq;
+ int one_sec_pulse_irq;
+};
+
+static inline void sft_rtc_set_enabled(struct sft_rtc *srtc, bool enabled)
+{
+ u32 val;
+
+ if (enabled) {
+ val = readl(srtc->regs + SFT_RTC_CFG);
+ val |= BIT(RTC_CFG_ENABLE_SHIFT);
+ writel(val, srtc->regs + SFT_RTC_CFG);
+ } else {
+ val = readl(srtc->regs + SFT_RTC_CFG);
+ val &= ~BIT(RTC_CFG_ENABLE_SHIFT);
+ writel(val, srtc->regs + SFT_RTC_CFG);
+ }
+}
+
+static inline bool sft_rtc_get_enabled(struct sft_rtc *srtc)
+{
+ return !!(readl(srtc->regs + SFT_RTC_CFG) & BIT(RTC_CFG_ENABLE_SHIFT));
+}
+
+static inline void sft_rtc_set_mode(struct sft_rtc *srtc, enum RTC_HOUR_MODE mode)
+{
+ u32 val;
+
+ val = readl(srtc->regs + SFT_RTC_CFG);
+ val |= mode << RTC_CFG_HOUR_MODE_SHIFT;
+ writel(val, srtc->regs + SFT_RTC_CFG);
+}
+
+static inline int sft_rtc_irq_enable(struct sft_rtc *srtc, u32 irq, bool enable)
+{
+ u32 val;
+
+ if (!(irq & RTC_IRQ_ALL))
+ return -EINVAL;
+
+ if (enable) {
+ val = readl(srtc->regs + SFT_RTC_IRQ_EN);
+ val |= irq;
+ writel(val, srtc->regs + SFT_RTC_IRQ_EN);
+ } else {
+ val = readl(srtc->regs + SFT_RTC_IRQ_EN);
+ val &= ~irq;
+ writel(val, srtc->regs + SFT_RTC_IRQ_EN);
+ }
+ return 0;
+}
+
+static inline void
+sft_rtc_set_cal_hw_enable(struct sft_rtc *srtc, bool enable)
+{
+ u32 val;
+
+ if (enable) {
+ val = readl(srtc->regs + SFT_RTC_CFG);
+ val |= BIT(RTC_CFG_CAL_EN_HW_SHIFT);
+ writel(val, srtc->regs + SFT_RTC_CFG);
+ } else {
+ val = readl(srtc->regs + SFT_RTC_CFG);
+ val &= ~BIT(RTC_CFG_CAL_EN_HW_SHIFT);
+ writel(val, srtc->regs + SFT_RTC_CFG);
+ }
+}
+
+static inline void
+sft_rtc_set_cal_mode(struct sft_rtc *srtc, enum RTC_CAL_MODE mode)
+{
+ u32 val;
+
+ val = readl(srtc->regs + SFT_RTC_CFG);
+ val |= mode << RTC_CFG_CAL_SEL_SHIFT;
+ writel(val, srtc->regs + SFT_RTC_CFG);
+}
+
+static int sft_rtc_get_hw_calclk(struct device *dev, unsigned long freq)
+{
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(refclk_list); i++)
+ if (refclk_list[i] == freq)
+ return i;
+
+ dev_err(dev, "refclk: %ldHz do not support.\n", freq);
+ return -EINVAL;
+}
+
+static inline void sft_rtc_reg2time(struct rtc_time *tm, u32 reg)
+{
+ tm->tm_hour = bcd2bin(FIELD_GET(TIME_HOUR_MASK, reg));
+ tm->tm_min = bcd2bin(FIELD_GET(TIME_MIN_MASK, reg));
+ tm->tm_sec = bcd2bin(FIELD_GET(TIME_SEC_MASK, reg));
+}
+
+static inline void sft_rtc_reg2date(struct rtc_time *tm, u32 reg)
+{
+ tm->tm_year = bcd2bin(FIELD_GET(DATE_YEAR_MASK, reg)) + 100;
+ tm->tm_mon = bcd2bin(FIELD_GET(DATE_MON_MASK, reg)) - 1;
+ tm->tm_mday = bcd2bin(FIELD_GET(DATE_DAY_MASK, reg));
+}
+
+static inline u32 sft_rtc_time2reg(struct rtc_time *tm)
+{
+ return FIELD_PREP(TIME_HOUR_MASK, bin2bcd(tm->tm_hour)) |
+ FIELD_PREP(TIME_MIN_MASK, bin2bcd(tm->tm_min)) |
+ FIELD_PREP(TIME_SEC_MASK, bin2bcd(tm->tm_sec));
+}
+
+static inline u32 sft_rtc_date2reg(struct rtc_time *tm)
+{
+ return FIELD_PREP(DATE_YEAR_MASK, bin2bcd(tm->tm_year - 100)) |
+ FIELD_PREP(DATE_MON_MASK, bin2bcd(tm->tm_mon + 1)) |
+ FIELD_PREP(DATE_DAY_MASK, bin2bcd(tm->tm_mday));
+}
+
+static inline void sft_rtc_update_pulse(struct sft_rtc *srtc)
+{
+ u32 val;
+
+ val = readl(srtc->regs + SFT_RTC_IRQ_EVEVT);
+ val |= RTC_IRQ_EVT_UPDATE_PSE;
+ writel(val, srtc->regs + SFT_RTC_IRQ_EVEVT);
+}
+
+static irqreturn_t sft_rtc_irq_handler(int irq, void *data)
+{
+ struct sft_rtc *srtc = data;
+ struct timerqueue_node *next;
+ u32 irq_flags = 0;
+ u32 irq_mask = 0;
+ u32 val;
+ int ret = 0;
+
+ val = readl(srtc->regs + SFT_RTC_IRQ_EVEVT);
+ if (val & RTC_IRQ_CAL_START)
+ irq_mask |= RTC_IRQ_CAL_START;
+
+ if (val & RTC_IRQ_CAL_FINISH) {
+ irq_mask |= RTC_IRQ_CAL_FINISH;
+ complete(&srtc->cal_done);
+ }
+
+ if (val & RTC_IRQ_CMP)
+ irq_mask |= RTC_IRQ_CMP;
+
+ if (val & RTC_IRQ_1SEC) {
+ irq_flags |= RTC_PF;
+ irq_mask |= RTC_IRQ_1SEC;
+ complete(&srtc->onesec_done);
+ }
+
+ if (val & RTC_IRQ_ALAEM) {
+ irq_flags |= RTC_AF;
+ irq_mask |= RTC_IRQ_ALAEM;
+
+ next = timerqueue_getnext(&srtc->rtc_dev->timerqueue);
+ if (next == &srtc->rtc_dev->aie_timer.node)
+ dev_info(&srtc->rtc_dev->dev, "alarm expires");
+ }
+
+ writel(irq_mask, srtc->regs + SFT_RTC_IRQ_EVEVT);
+
+ /* Wait interrupt flag clear */
+ ret = readl_poll_timeout_atomic(srtc->regs + SFT_RTC_IRQ_EVEVT, val,
+ (val & irq_mask) == 0, 0, INT_TIMEOUT_US);
+ if (ret)
+ dev_warn(&srtc->rtc_dev->dev, "fail to clear rtc interrupt flag\n");
+
+ if (irq_flags)
+ rtc_update_irq(srtc->rtc_dev, 1, irq_flags | RTC_IRQF);
+
+ return IRQ_HANDLED;
+}
+
+static int sft_rtc_read_time(struct device *dev, struct rtc_time *tm)
+{
+ struct sft_rtc *srtc = dev_get_drvdata(dev);
+ u32 val;
+ int irq_1sec_state_start, irq_1sec_state_end;
+
+ /* If the RTC is disabled, assume the values are invalid */
+ if (!sft_rtc_get_enabled(srtc))
+ return -EINVAL;
+
+ irq_1sec_state_start =
+ (readl(srtc->regs + SFT_RTC_IRQ_STATUS) & RTC_IRQ_1SEC) == 0 ? 0 : 1;
+
+read_again:
+ val = readl(srtc->regs + SFT_RTC_TIME);
+ sft_rtc_reg2time(tm, val);
+
+ val = readl(srtc->regs + SFT_RTC_DATE);
+ sft_rtc_reg2date(tm, val);
+
+ if (irq_1sec_state_start == 0) {
+ irq_1sec_state_end =
+ (readl(srtc->regs + SFT_RTC_IRQ_STATUS) & RTC_IRQ_1SEC) == 0 ? 0 : 1;
+ if (irq_1sec_state_end == 1) {
+ irq_1sec_state_start = 1;
+ goto read_again;
+ }
+ }
+
+ return 0;
+}
+
+static int sft_rtc_set_time(struct device *dev, struct rtc_time *tm)
+{
+ struct sft_rtc *srtc = dev_get_drvdata(dev);
+ u32 val;
+ int ret;
+
+ val = sft_rtc_time2reg(tm);
+ writel(val, srtc->regs + SFT_RTC_CFG_TIME);
+
+ val = sft_rtc_date2reg(tm);
+ writel(val, srtc->regs + SFT_RTC_CFG_DATE);
+
+ /* Update pulse */
+ sft_rtc_update_pulse(srtc);
+
+ /* Ensure that data is fully written */
+ ret = wait_for_completion_interruptible_timeout(&srtc->onesec_done,
+ usecs_to_jiffies(120));
+ if (ret) {
+ dev_warn(dev,
+ "rtc wait for completion interruptible timeout.\n");
+ }
+ return 0;
+}
+
+static int sft_rtc_alarm_irq_enable(struct device *dev, unsigned int enabled)
+{
+ struct sft_rtc *srtc = dev_get_drvdata(dev);
+
+ return sft_rtc_irq_enable(srtc, RTC_IRQ_ALAEM, enabled);
+}
+
+static int sft_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alarm)
+{
+ struct sft_rtc *srtc = dev_get_drvdata(dev);
+ u32 val;
+
+ val = readl(srtc->regs + SFT_RTC_ACT_TIME);
+ sft_rtc_reg2time(&alarm->time, val);
+
+ val = readl(srtc->regs + SFT_RTC_ACT_DATE);
+ sft_rtc_reg2date(&alarm->time, val);
+
+ return 0;
+}
+
+static int sft_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alarm)
+{
+ struct sft_rtc *srtc = dev_get_drvdata(dev);
+ u32 val;
+
+ sft_rtc_alarm_irq_enable(dev, 0);
+
+ val = sft_rtc_time2reg(&alarm->time);
+ writel(val, srtc->regs + SFT_RTC_ACT_TIME);
+
+ val = sft_rtc_date2reg(&alarm->time);
+ writel(val, srtc->regs + SFT_RTC_ACT_DATE);
+
+ sft_rtc_alarm_irq_enable(dev, alarm->enabled);
+
+ return 0;
+}
+
+static int sft_rtc_get_offset(struct device *dev, long *offset)
+{
+ struct sft_rtc *srtc = dev_get_drvdata(dev);
+ s64 tmp;
+ u32 val;
+
+ val = readl(srtc->regs + SFT_RTC_CAL_VALUE)
+ & RTC_SW_CAL_VALUE_MASK;
+ val += 1;
+ /*
+ * the adjust val range is [0x0000-0xffff],
+ * the default val is 0x7fff (32768-1),mapping offset=0 ;
+ */
+ tmp = (s64)val - RTC_TICKS_PER_SEC;
+ tmp *= RTC_PPB_MULT;
+ tmp = div_s64(tmp, RTC_TICKS_PER_SEC);
+
+ /* Offset value operates in negative way, so swap sign */
+ *offset = -tmp;
+
+ return 0;
+}
+
+static int sft_rtc_set_offset(struct device *dev, long offset)
+{
+ struct sft_rtc *srtc = dev_get_drvdata(dev);
+ s64 tmp;
+ u32 val;
+
+ tmp = offset * RTC_TICKS_PER_SEC;
+ tmp = div_s64(tmp, RTC_PPB_MULT);
+
+ tmp = RTC_TICKS_PER_SEC - tmp;
+ tmp -= 1;
+ if (tmp > RTC_SW_CAL_MAX || tmp < RTC_SW_CAL_MIN) {
+ dev_err(dev, "offset is out of range.\n");
+ return -EINVAL;
+ }
+
+ val = tmp & RTC_SW_CAL_VALUE_MASK;
+ /* set software calibration value */
+ writel(val, srtc->regs + SFT_RTC_SW_CAL_VALUE);
+
+ /* set CFG_RTC-cal_sel to select calibretion by software. */
+ sft_rtc_set_cal_mode(srtc, RTC_CAL_MODE_SW);
+
+ return 0;
+}
+
+static __maybe_unused int
+sft_rtc_hw_adjustment(struct device *dev, unsigned int enable)
+{
+ struct sft_rtc *srtc = dev_get_drvdata(dev);
+ u32 val;
+
+ if (srtc->hw_cal_map <= 0) {
+ dev_err(dev, "fail to get cal-clock-freq.\n");
+ return -EFAULT;
+ }
+
+ if (enable) {
+ sft_rtc_irq_enable(srtc, RTC_IRQ_CAL_FINISH, true);
+
+ /* Set reference clock frequency value */
+ val = readl(srtc->regs + SFT_RTC_HW_CAL_CFG);
+ val |= (srtc->hw_cal_map << RTC_HW_CAL_FRQ_SEL_SHIFT);
+ writel(val, srtc->regs + SFT_RTC_HW_CAL_CFG);
+
+ /* Set CFG_RTC-cal_sel to select calibretion by hardware. */
+ sft_rtc_set_cal_mode(srtc, RTC_CAL_MODE_HW);
+
+ /* Set CFG_RTC-cal_en_hw to launch hardware calibretion.*/
+ sft_rtc_set_cal_hw_enable(srtc, true);
+
+ wait_for_completion_interruptible_timeout(&srtc->cal_done,
+ usecs_to_jiffies(100));
+
+ sft_rtc_irq_enable(srtc, RTC_IRQ_CAL_FINISH, false);
+ } else {
+ sft_rtc_set_cal_mode(srtc, RTC_CAL_MODE_SW);
+ sft_rtc_set_cal_hw_enable(srtc, false);
+ }
+
+ return 0;
+}
+
+static int sft_rtc_get_cal_clk(struct device *dev, struct sft_rtc *srtc)
+{
+ struct device_node *np = dev->of_node;
+ unsigned long cal_clk_freq;
+ u32 freq;
+ int ret;
+
+ srtc->cal_clk = devm_clk_get(dev, "cal_clk");
+ if (IS_ERR(srtc->cal_clk))
+ return PTR_ERR(srtc->cal_clk);
+
+ clk_prepare_enable(srtc->cal_clk);
+
+ cal_clk_freq = clk_get_rate(srtc->cal_clk);
+ if (!cal_clk_freq) {
+ dev_warn(dev,
+ "get rate failed, next try to get from dts.\n");
+ ret = of_property_read_u32(np, "rtc,cal-clock-freq", &freq);
+ if (!ret) {
+ cal_clk_freq = (u64)freq;
+ } else {
+ dev_err(dev,
+ "Need rtc,cal-clock-freq define in dts.\n");
+ goto err_disable_cal_clk;
+ }
+ }
+
+ srtc->hw_cal_map = sft_rtc_get_hw_calclk(dev, cal_clk_freq);
+ if (srtc->hw_cal_map < 0) {
+ ret = srtc->hw_cal_map;
+ goto err_disable_cal_clk;
+ }
+
+ return 0;
+
+err_disable_cal_clk:
+ clk_disable_unprepare(srtc->cal_clk);
+
+ return ret;
+}
+
+static int sft_rtc_get_irq(struct platform_device *pdev, struct sft_rtc *srtc)
+{
+ int ret;
+
+ srtc->rtc_irq = platform_get_irq_byname(pdev, "rtc");
+ if (srtc->rtc_irq < 0)
+ return -EINVAL;
+
+ ret = devm_request_irq(&pdev->dev, srtc->rtc_irq,
+ sft_rtc_irq_handler, 0,
+ KBUILD_MODNAME, srtc);
+ if (ret)
+ dev_err(&pdev->dev, "Failed to request interrupt, %d\n", ret);
+
+ return ret;
+}
+
+static const struct rtc_class_ops starfive_rtc_ops = {
+ .read_time = sft_rtc_read_time,
+ .set_time = sft_rtc_set_time,
+ .read_alarm = sft_rtc_read_alarm,
+ .set_alarm = sft_rtc_set_alarm,
+ .alarm_irq_enable = sft_rtc_alarm_irq_enable,
+ .set_offset = sft_rtc_set_offset,
+ .read_offset = sft_rtc_get_offset,
+};
+
+static int sft_rtc_probe(struct platform_device *pdev)
+{
+ struct device *dev = &pdev->dev;
+ struct sft_rtc *srtc;
+ struct rtc_time tm;
+ struct irq_desc *desc;
+ int ret;
+
+ srtc = devm_kzalloc(dev, sizeof(*srtc), GFP_KERNEL);
+ if (!srtc)
+ return -ENOMEM;
+
+ srtc->regs = devm_platform_ioremap_resource(pdev, 0);
+ if (IS_ERR(srtc->regs))
+ return PTR_ERR(srtc->regs);
+
+ srtc->pclk = devm_clk_get(dev, "pclk");
+ if (IS_ERR(srtc->pclk)) {
+ ret = PTR_ERR(srtc->pclk);
+ dev_err(dev,
+ "Failed to retrieve the peripheral clock, %d\n", ret);
+ return ret;
+ }
+
+ srtc->rst_array = devm_reset_control_array_get_exclusive(dev);
+ if (IS_ERR(srtc->rst_array)) {
+ ret = PTR_ERR(srtc->rst_array);
+ dev_err(dev,
+ "Failed to retrieve the rtc reset, %d\n", ret);
+ return ret;
+ }
+
+ init_completion(&srtc->cal_done);
+ init_completion(&srtc->onesec_done);
+
+ ret = clk_prepare_enable(srtc->pclk);
+ if (ret) {
+ dev_err(dev,
+ "Failed to enable the peripheral clock, %d\n", ret);
+ return ret;
+ }
+
+ ret = sft_rtc_get_cal_clk(dev, srtc);
+ if (ret)
+ goto err_disable_pclk;
+
+ ret = reset_control_deassert(srtc->rst_array);
+ if (ret) {
+ dev_err(dev,
+ "Failed to deassert rtc resets, %d\n", ret);
+ goto err_disable_cal_clk;
+ }
+
+ ret = sft_rtc_get_irq(pdev, srtc);
+ if (ret)
+ goto err_disable_cal_clk;
+
+ srtc->rtc_dev = devm_rtc_allocate_device(dev);
+ if (IS_ERR(srtc->rtc_dev))
+ return PTR_ERR(srtc->rtc_dev);
+
+ platform_set_drvdata(pdev, srtc);
+
+ /* The RTC supports 01.01.2001 - 31.12.2099 */
+ srtc->rtc_dev->range_min = mktime64(2001, 1, 1, 0, 0, 0);
+ srtc->rtc_dev->range_max = mktime64(2099, 12, 31, 23, 59, 59);
+
+ srtc->rtc_dev->ops = &starfive_rtc_ops;
+ device_init_wakeup(dev, true);
+
+ desc = irq_to_desc(srtc->rtc_irq);
+ irq_desc_get_chip(desc)->flags = IRQCHIP_SKIP_SET_WAKE;
+
+ /* Always use 24-hour mode and keep the RTC values */
+ sft_rtc_set_mode(srtc, RTC_HOUR_MODE_24H);
+
+ sft_rtc_set_enabled(srtc, true);
+
+ if (device_property_read_bool(dev, "rtc,hw-adjustment"))
+ sft_rtc_hw_adjustment(dev, true);
+
+ /*
+ * If rtc time is out of supported range, reset it to the minimum time.
+ * notice that, actual year = 1900 + tm.tm_year
+ * actual month = 1 + tm.tm_mon
+ */
+ sft_rtc_read_time(dev, &tm);
+ if (tm.tm_year < 101 || tm.tm_year > 199 || tm.tm_mon < 0 || tm.tm_mon > 11 ||
+ tm.tm_mday < 1 || tm.tm_mday > 31 || tm.tm_hour < 0 || tm.tm_hour > 23 ||
+ tm.tm_min < 0 || tm.tm_min > 59 || tm.tm_sec < 0 || tm.tm_sec > 59) {
+ rtc_time64_to_tm(srtc->rtc_dev->range_min, &tm);
+ sft_rtc_set_time(dev, &tm);
+ }
+
+ ret = devm_rtc_register_device(srtc->rtc_dev);
+ if (ret)
+ goto err_disable_wakeup;
+
+ return 0;
+
+err_disable_wakeup:
+ device_init_wakeup(dev, false);
+
+err_disable_cal_clk:
+ clk_disable_unprepare(srtc->cal_clk);
+
+err_disable_pclk:
+ clk_disable_unprepare(srtc->pclk);
+
+ return ret;
+}
+
+static int sft_rtc_remove(struct platform_device *pdev)
+{
+ struct sft_rtc *srtc = platform_get_drvdata(pdev);
+
+ sft_rtc_alarm_irq_enable(&pdev->dev, 0);
+ device_init_wakeup(&pdev->dev, 0);
+
+ clk_disable_unprepare(srtc->pclk);
+ clk_disable_unprepare(srtc->cal_clk);
+
+ return 0;
+}
+
+#ifdef CONFIG_PM_SLEEP
+static int sft_rtc_suspend(struct device *dev)
+{
+ struct sft_rtc *srtc = dev_get_drvdata(dev);
+
+ if (device_may_wakeup(dev))
+ enable_irq_wake(srtc->rtc_irq);
+
+ return 0;
+}
+
+static int sft_rtc_resume(struct device *dev)
+{
+ struct sft_rtc *srtc = dev_get_drvdata(dev);
+
+ if (device_may_wakeup(dev))
+ disable_irq_wake(srtc->rtc_irq);
+
+ return 0;
+}
+#endif
+
+static SIMPLE_DEV_PM_OPS(sft_rtc_pm_ops, sft_rtc_suspend, sft_rtc_resume);
+
+static const struct of_device_id sft_rtc_of_match[] = {
+ { .compatible = "starfive,jh7110-rtc" },
+ { },
+};
+MODULE_DEVICE_TABLE(of, sft_rtc_of_match);
+
+static struct platform_driver starfive_rtc_driver = {
+ .driver = {
+ .name = "starfive-rtc",
+ .of_match_table = sft_rtc_of_match,
+ .pm = &sft_rtc_pm_ops,
+ },
+ .probe = sft_rtc_probe,
+ .remove = sft_rtc_remove,
+};
+module_platform_driver(starfive_rtc_driver);
+
+MODULE_AUTHOR("Samin Guo <samin.guo@starfivetech.com>");
+MODULE_AUTHOR("Hal Feng <hal.feng@starfivetech.com>");
+MODULE_DESCRIPTION("StarFive RTC driver");
+MODULE_LICENSE("GPL v2");
+MODULE_ALIAS("platform:starfive-rtc");

View File

@ -0,0 +1,96 @@
From 552114b8cbbd956ad8466261b5f11b059eba82ca Mon Sep 17 00:00:00 2001
From: Minda Chen <minda.chen@starfivetech.com>
Date: Sun, 25 Jun 2023 09:40:29 +0800
Subject: [PATCH 066/116] uart: 8250: Add dw auto flow ctrl support
Add designeware 8250 auto flow ctrl support. Enable
it by add auto-flow-control in dts.
Signed-off-by: Minda Chen <minda.chen@starfivetech.com>
---
drivers/tty/serial/8250/8250_core.c | 2 ++
drivers/tty/serial/8250/8250_dw.c | 3 +++
drivers/tty/serial/8250/8250_port.c | 14 +++++++++++++-
include/linux/serial_8250.h | 1 +
include/uapi/linux/serial_core.h | 2 ++
5 files changed, 21 insertions(+), 1 deletion(-)
--- a/drivers/tty/serial/8250/8250_core.c
+++ b/drivers/tty/serial/8250/8250_core.c
@@ -1129,6 +1129,8 @@ int serial8250_register_8250_port(const
uart->dl_read = up->dl_read;
if (up->dl_write)
uart->dl_write = up->dl_write;
+ if (up->probe)
+ uart->probe = up->probe;
if (uart->port.type != PORT_8250_CIR) {
if (serial8250_isa_config != NULL)
--- a/drivers/tty/serial/8250/8250_dw.c
+++ b/drivers/tty/serial/8250/8250_dw.c
@@ -612,6 +612,9 @@ static int dw8250_probe(struct platform_
data->msr_mask_off |= UART_MSR_TERI;
}
+ if (device_property_read_bool(dev, "auto-flow-control"))
+ up->probe |= UART_PROBE_AFE;
+
/* If there is separate baudclk, get the rate from it. */
data->clk = devm_clk_get_optional(dev, "baudclk");
if (data->clk == NULL)
--- a/drivers/tty/serial/8250/8250_port.c
+++ b/drivers/tty/serial/8250/8250_port.c
@@ -330,6 +330,14 @@ static const struct serial8250_config ua
.rxtrig_bytes = {1, 8, 16, 30},
.flags = UART_CAP_FIFO | UART_CAP_AFE,
},
+ [PORT_16550A_AFE] = {
+ .name = "16550A_AFE",
+ .fifo_size = 16,
+ .tx_loadsz = 16,
+ .fcr = UART_FCR_ENABLE_FIFO | UART_FCR_R_TRIG_10,
+ .rxtrig_bytes = {1, 4, 8, 14},
+ .flags = UART_CAP_FIFO | UART_CAP_AFE,
+ },
};
/* Uart divisor latch read */
@@ -1143,6 +1151,11 @@ static void autoconfig_16550a(struct uar
up->port.type = PORT_U6_16550A;
up->capabilities |= UART_CAP_AFE;
}
+
+ if ((up->port.type == PORT_16550A) && (up->probe & UART_PROBE_AFE)) {
+ up->port.type = PORT_16550A_AFE;
+ up->capabilities |= UART_CAP_AFE;
+ }
}
/*
@@ -2813,7 +2826,6 @@ serial8250_do_set_termios(struct uart_po
if (termios->c_cflag & CRTSCTS)
up->mcr |= UART_MCR_AFE;
}
-
/*
* Update the per-port timeout.
*/
--- a/include/linux/serial_8250.h
+++ b/include/linux/serial_8250.h
@@ -141,6 +141,7 @@ struct uart_8250_port {
unsigned char probe;
struct mctrl_gpios *gpios;
#define UART_PROBE_RSA (1 << 0)
+#define UART_PROBE_AFE (1 << 1)
/*
* Some bits in registers are cleared on a read, so they must
--- a/include/uapi/linux/serial_core.h
+++ b/include/uapi/linux/serial_core.h
@@ -245,4 +245,6 @@
/* Sunplus UART */
#define PORT_SUNPLUS 123
+#define PORT_16550A_AFE 124
+
#endif /* _UAPILINUX_SERIAL_CORE_H */

View File

@ -0,0 +1,29 @@
From 6edee93a89254f30c3387c88231e7ecec06ba84a Mon Sep 17 00:00:00 2001
From: "shanlong.li" <shanlong.li@starfivetech.com>
Date: Mon, 10 Jul 2023 03:07:57 -0700
Subject: [PATCH 067/116] driver:uart: fix up uart communicate fail
fix up uart communicate fail
Signed-off-by: shanlong.li <shanlong.li@starfivetech.com>
---
drivers/tty/serial/8250/8250_dw.c | 8 ++++----
1 file changed, 4 insertions(+), 4 deletions(-)
--- a/drivers/tty/serial/8250/8250_dw.c
+++ b/drivers/tty/serial/8250/8250_dw.c
@@ -652,10 +652,10 @@ static int dw8250_probe(struct platform_
if (err)
return err;
- data->rst = devm_reset_control_get_optional_exclusive(dev, NULL);
- if (IS_ERR(data->rst))
- return PTR_ERR(data->rst);
-
+ data->rst = devm_reset_control_array_get_exclusive(dev);
+ if (IS_ERR(data->rst)) {
+ err = PTR_ERR(data->rst);
+ }
reset_control_deassert(data->rst);
err = devm_add_action_or_reset(dev, dw8250_reset_control_assert, data->rst);

View File

@ -0,0 +1,32 @@
From 777d288f03a0b350f6c2d4367b01a80d9f25cd6e Mon Sep 17 00:00:00 2001
From: William Qiu <william.qiu@starfivetech.com>
Date: Wed, 20 Sep 2023 17:19:59 +0800
Subject: [PATCH 068/116] uart: 8250: add reset operation in runtime PM
add reset operation in runtime PM
Signed-off-by: William Qiu <william.qiu@starfivetech.com>
---
drivers/tty/serial/8250/8250_dw.c | 4 ++++
1 file changed, 4 insertions(+)
--- a/drivers/tty/serial/8250/8250_dw.c
+++ b/drivers/tty/serial/8250/8250_dw.c
@@ -745,6 +745,8 @@ static int dw8250_runtime_suspend(struct
{
struct dw8250_data *data = dev_get_drvdata(dev);
+ reset_control_assert(data->rst);
+
clk_disable_unprepare(data->clk);
clk_disable_unprepare(data->pclk);
@@ -760,6 +762,8 @@ static int dw8250_runtime_resume(struct
clk_prepare_enable(data->clk);
+ reset_control_deassert(data->rst);
+
return 0;
}

View File

@ -0,0 +1,113 @@
From 5eda2331a252436756fb40861f01a7a38b1502c7 Mon Sep 17 00:00:00 2001
From: William Qiu <william.qiu@starfivetech.com>
Date: Thu, 15 Jun 2023 20:14:22 +0800
Subject: [PATCH 069/116] dt-bindings: CAN: Add StarFive CAN module
Add documentation to describe StarFive CAN engine.
Signed-off-by: William Qiu <william.qiu@starfivetech.com>
---
.../devicetree/bindings/net/can/ipms-can.yaml | 97 +++++++++++++++++++
1 file changed, 97 insertions(+)
create mode 100644 Documentation/devicetree/bindings/net/can/ipms-can.yaml
--- /dev/null
+++ b/Documentation/devicetree/bindings/net/can/ipms-can.yaml
@@ -0,0 +1,97 @@
+# SPDX-License-Identifier: GPL-2.0
+%YAML 1.2
+---
+#$id: http://devicetree.org/schemas/net/can/ipms-can.yaml#
+#$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: IPMS CAN/CANFD controller Device Tree Bindings
+
+properties:
+ compatible:
+ const:ipms,can
+
+ reg:
+ maxItems: 1
+ items:
+ - description:CAN controller registers
+
+ interrupts:
+ maxItems: 1
+
+ clocks:
+ minItems: 1
+ items:
+ - description:apb_clk clock
+ - description:core_clk clock
+ - description:timer_clk clock
+
+ clock-names:
+ minItems: 1
+ items:
+ - const:apb_clk
+ - const:core_clk
+ - const:timer_clk
+ resets:
+ minItems: 1
+ items:
+ - description:apb_clk reset
+ - description:core_clk reset
+ - description:timer_clk reset
+ reset-names:
+ minItems: 1
+ items:
+ - const:rst_apb
+ - const:rst_core
+ - const:rst_timer
+ starfive,sys-syscon:
+ format:
+ starfive,sys-syscon = <&arg0 arg1 arg2 arg3>
+ description:
+ arg0:arg0 is sys_syscon.
+ arg1:arg1 is syscon register offset, used to enable can2.0/canfd function, can0 is 0x10, can1 is 0x88.
+ arg2:arg2 is used to enable the register shift of the can2.0/canfd function, can0 is 0x3, can1 is 0x12.
+ arg3:arg3 is used to enable the register mask of the can2.0/canfd function, can0 is 0x8, can1 is 0x40000
+
+ syscon,can_or_canfd:
+ description:
+ IPMS CAN-CTRL core is a serial communications controller that performs serial communication according to the CAN protocol.
+ This CAN bus interface uses the basic CAN principle and meets all constraints of the CAN-specification 2.0B active.
+ Furthermore this CAN core can be configured to meet the specification of CAN with flexible data rate CAN FD.
+ When syscon,can_or_canfd is set to 0, use CAN2.0B.
+ when syscon,can_or_canfd is set to 1, use CAN FD.
+required:
+ - compatible
+ - reg
+ - interrupts
+ - clocks
+ - clock-names
+ - resets
+ - reset-names
+ - starfive,sys-syscon
+ - syscon,can_or_canfd
+additionalProperties:false
+
+examples:
+ - |
+ can0: can@130d0000{
+ compatible = "ipms,can";
+ reg = <0x0 0x130d0000 0x0 0x1000>;
+ interrupts = <112>;
+ interrupt-parent = <&plic>;
+ clocks = <&clkgen JH7110_CAN0_CTRL_CLK_APB>,
+ <&clkgen JH7110_CAN0_CTRL_CLK_CAN>,
+ <&clkgen JH7110_CAN0_CTRL_CLK_TIMER>;
+ clock-names = "apb_clk",
+ "core_clk",
+ "timer_clk";
+ resets = <&rstgen RSTN_U0_CAN_CTRL_APB>,
+ <&rstgen RSTN_U0_CAN_CTRL_CORE>,
+ <&rstgen RSTN_U0_CAN_CTRL_TIMER>;
+ reset-names = "rst_apb",
+ "rst_core",
+ "rst_timer";
+ starfive,sys-syscon = <&sys_syscon, 0x10 0x3 0x8>;
+ syscon,can_or_canfd = <0>;
+ };
+
+...

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,204 @@
From b12213d474966fbf47e7afa36a6655b5b241cf36 Mon Sep 17 00:00:00 2001
From: "Kevin.xie" <kevin.xie@starfivetech.com>
Date: Fri, 9 Jun 2023 14:57:13 +0800
Subject: [PATCH 071/116] regulator: starfive-jh7110: Add regulator support for
JH7110 A type EVB.
Add 7 regulators base on regulator framework for
JH7110 evb HW design.
Signed-off-by: Kevin.xie <kevin.xie@starfivetech.com>
---
drivers/regulator/Kconfig | 10 ++
drivers/regulator/Makefile | 1 +
drivers/regulator/starfive-jh7110-regulator.c | 126 ++++++++++++++++++
include/linux/regulator/jh7110.h | 24 ++++
4 files changed, 161 insertions(+)
create mode 100644 drivers/regulator/starfive-jh7110-regulator.c
create mode 100644 include/linux/regulator/jh7110.h
--- a/drivers/regulator/Kconfig
+++ b/drivers/regulator/Kconfig
@@ -1335,6 +1335,16 @@ config REGULATOR_SM5703
This driver provides support for voltage regulators of SM5703
multi-function device.
+config REGULATOR_STARFIVE_JH7110
+ tristate "Starfive JH7110 PMIC"
+ depends on I2C
+ select REGMAP_I2C
+ help
+ Say y here to select this option to enable the power regulator of
+ Starfive JH7110 PMIC.
+ This driver supports the control of different power rails of device
+ through regulator interface.
+
config REGULATOR_STM32_BOOSTER
tristate "STMicroelectronics STM32 BOOSTER"
depends on ARCH_STM32 || COMPILE_TEST
--- a/drivers/regulator/Makefile
+++ b/drivers/regulator/Makefile
@@ -156,6 +156,7 @@ obj-$(CONFIG_REGULATOR_SC2731) += sc2731
obj-$(CONFIG_REGULATOR_SKY81452) += sky81452-regulator.o
obj-$(CONFIG_REGULATOR_SLG51000) += slg51000-regulator.o
obj-$(CONFIG_REGULATOR_SM5703) += sm5703-regulator.o
+obj-$(CONFIG_REGULATOR_STARFIVE_JH7110) += starfive-jh7110-regulator.o
obj-$(CONFIG_REGULATOR_STM32_BOOSTER) += stm32-booster.o
obj-$(CONFIG_REGULATOR_STM32_VREFBUF) += stm32-vrefbuf.o
obj-$(CONFIG_REGULATOR_STM32_PWR) += stm32-pwr.o
--- /dev/null
+++ b/drivers/regulator/starfive-jh7110-regulator.c
@@ -0,0 +1,126 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (c) 2022 Starfive Technology Co., Ltd.
+ * Author: Mason Huo <mason.huo@starfivetech.com>
+ */
+
+#include <linux/err.h>
+#include <linux/gpio.h>
+#include <linux/i2c.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/module.h>
+#include <linux/regmap.h>
+#include <linux/regulator/driver.h>
+#include <linux/regulator/machine.h>
+#include <linux/regulator/of_regulator.h>
+#include <linux/regulator/jh7110.h>
+#include <linux/slab.h>
+
+#define JH7110_PM_POWER_SW_0 0x80
+#define JH7110_PM_POWER_SW_1 0x81
+#define ENABLE_MASK(id) BIT(id)
+
+
+static const struct regmap_config jh7110_regmap_config = {
+ .reg_bits = 8,
+ .val_bits = 8,
+ .max_register = JH7110_PM_POWER_SW_1,
+ .cache_type = REGCACHE_FLAT,
+};
+
+static const struct regulator_ops jh7110_ldo_ops = {
+ .enable = regulator_enable_regmap,
+ .disable = regulator_disable_regmap,
+ .is_enabled = regulator_is_enabled_regmap,
+};
+
+#define JH7110_LDO(_id, _name, en_reg, en_mask) \
+{\
+ .name = (_name),\
+ .ops = &jh7110_ldo_ops,\
+ .of_match = of_match_ptr(_name),\
+ .regulators_node = of_match_ptr("regulators"),\
+ .type = REGULATOR_VOLTAGE,\
+ .id = JH7110_ID_##_id,\
+ .owner = THIS_MODULE,\
+ .enable_reg = JH7110_PM_POWER_SW_##en_reg,\
+ .enable_mask = ENABLE_MASK(en_mask),\
+}
+
+static const struct regulator_desc jh7110_regulators[] = {
+ JH7110_LDO(LDO_REG1, "hdmi_1p8", 0, 0),
+ JH7110_LDO(LDO_REG2, "mipitx_1p8", 0, 1),
+ JH7110_LDO(LDO_REG3, "mipirx_1p8", 0, 2),
+ JH7110_LDO(LDO_REG4, "hdmi_0p9", 0, 3),
+ JH7110_LDO(LDO_REG5, "mipitx_0p9", 0, 4),
+ JH7110_LDO(LDO_REG6, "mipirx_0p9", 0, 5),
+ JH7110_LDO(LDO_REG7, "sdio_vdd", 1, 0),
+};
+
+static int jh7110_i2c_probe(struct i2c_client *i2c)
+{
+ struct regulator_config config = { };
+ struct regulator_dev *rdev;
+ struct regulator_init_data *init_data;
+ struct regmap *regmap;
+ int i, ret;
+
+ regmap = devm_regmap_init_i2c(i2c, &jh7110_regmap_config);
+ if (IS_ERR(regmap)) {
+ ret = PTR_ERR(regmap);
+ dev_err(&i2c->dev, "Failed to allocate register map: %d\n",
+ ret);
+ return ret;
+ }
+
+ init_data = of_get_regulator_init_data(&i2c->dev, i2c->dev.of_node, NULL);
+ if (!init_data)
+ return -ENOMEM;
+ config.init_data = init_data;
+
+ for (i = 0; i < JH7110_MAX_REGULATORS; i++) {
+ config.dev = &i2c->dev;
+ config.regmap = regmap;
+
+ rdev = devm_regulator_register(&i2c->dev,
+ &jh7110_regulators[i], &config);
+ if (IS_ERR(rdev)) {
+ dev_err(&i2c->dev,
+ "Failed to register JH7110 regulator\n");
+ return PTR_ERR(rdev);
+ }
+ }
+
+ return 0;
+}
+
+static const struct i2c_device_id jh7110_i2c_id[] = {
+ {"jh7110_evb_reg", 0},
+ {},
+};
+MODULE_DEVICE_TABLE(i2c, jh7110_i2c_id);
+
+#ifdef CONFIG_OF
+static const struct of_device_id jh7110_dt_ids[] = {
+ { .compatible = "starfive,jh7110-evb-regulator",
+ .data = &jh7110_i2c_id[0] },
+ {},
+};
+MODULE_DEVICE_TABLE(of, jh7110_dt_ids);
+#endif
+
+static struct i2c_driver jh7110_regulator_driver = {
+ .driver = {
+ .name = "jh7110-evb-regulator",
+ .of_match_table = of_match_ptr(jh7110_dt_ids),
+ },
+ .probe = jh7110_i2c_probe,
+ .id_table = jh7110_i2c_id,
+};
+
+module_i2c_driver(jh7110_regulator_driver);
+
+MODULE_AUTHOR("Mason Huo <mason.huo@starfivetech.com>");
+MODULE_DESCRIPTION("Regulator device driver for Starfive JH7110");
+MODULE_LICENSE("GPL v2");
--- /dev/null
+++ b/include/linux/regulator/jh7110.h
@@ -0,0 +1,24 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+/*
+ * Copyright (c) 2022 Starfive Technology Co., Ltd.
+ * Author: Mason Huo <mason.huo@starfivetech.com>
+ */
+
+#ifndef __LINUX_REGULATOR_JH7110_H
+#define __LINUX_REGULATOR_JH7110_H
+
+#define JH7110_MAX_REGULATORS 7
+
+
+enum jh7110_reg_id {
+ JH7110_ID_LDO_REG1 = 0,
+ JH7110_ID_LDO_REG2,
+ JH7110_ID_LDO_REG3,
+ JH7110_ID_LDO_REG4,
+ JH7110_ID_LDO_REG5,
+ JH7110_ID_LDO_REG6,
+ JH7110_ID_LDO_REG7,
+};
+
+
+#endif /* __LINUX_REGULATOR_JH7110_H */

View File

@ -0,0 +1,40 @@
From f0b4cffe4d1813305f783d208f260747ecc56c50 Mon Sep 17 00:00:00 2001
From: "Kevin.xie" <kevin.xie@starfivetech.com>
Date: Thu, 24 Nov 2022 16:59:12 +0800
Subject: [PATCH 072/116] drivers: nvme: Add precheck and delay for CQE pending
status.
To workaroud the NVMe I/O timeout problem in bootup S10udev case
which caused by the CQE update lantancy.
Signed-off-by: Kevin.xie <kevin.xie@starfivetech.com>
---
drivers/nvme/host/pci.c | 10 ++++++++++
1 file changed, 10 insertions(+)
--- a/drivers/nvme/host/pci.c
+++ b/drivers/nvme/host/pci.c
@@ -28,6 +28,7 @@
#include <linux/io-64-nonatomic-hi-lo.h>
#include <linux/sed-opal.h>
#include <linux/pci-p2pdma.h>
+#include <linux/delay.h>
#include "trace.h"
#include "nvme.h"
@@ -1062,6 +1063,15 @@ static inline int nvme_poll_cq(struct nv
{
int found = 0;
+ /*
+ * In some cases, such as udev trigger, cqe status may update
+ * a little bit later than MSI, which cause an irq handle missing.
+ * To workaound, here we will prefetch the status first, and wait
+ * 1us if we get nothing.
+ */
+ if (!nvme_cqe_pending(nvmeq))
+ udelay(1);
+
while (nvme_cqe_pending(nvmeq)) {
found++;
/*

View File

@ -0,0 +1,93 @@
From eb294df4b9fab46bc5dbf676edf51e28e06d1968 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Jo=C3=A3o=20M=C3=A1rio=20Domingos?=
<joao.mario@tecnico.ulisboa.pt>
Date: Tue, 16 Nov 2021 15:48:09 +0000
Subject: [PATCH 073/116] RISC-V: Create unique identification for SoC PMU
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
The SBI PMU platform driver did not provide any identification for
perf events matching. This patch introduces a new sysfs file inside the
platform device (soc:pmu/id) for pmu identification.
The identification is a 64-bit value generated as:
[63-32]: mvendorid;
[31]: marchid[MSB];
[30-16]: marchid[15-0];
[15-0]: mimpid[15MSBs];
The CSRs are detailed in the RISC-V privileged spec [1].
The marchid is split in MSB + 15LSBs, due to the MSB being used for
open-source architecture identification.
[1] https://github.com/riscv/riscv-isa-manual
Signed-off-by: João Mário Domingos <joao.mario@tecnico.ulisboa.pt>
---
drivers/perf/riscv_pmu_sbi.c | 47 ++++++++++++++++++++++++++++++++++++
1 file changed, 47 insertions(+)
--- a/drivers/perf/riscv_pmu_sbi.c
+++ b/drivers/perf/riscv_pmu_sbi.c
@@ -1019,6 +1019,46 @@ static struct ctl_table sbi_pmu_sysctl_t
{ }
};
+static uint64_t pmu_sbi_get_pmu_id(void)
+{
+ union sbi_pmu_id {
+ uint64_t value;
+ struct {
+ uint16_t imp:16;
+ uint16_t arch:16;
+ uint32_t vendor:32;
+ };
+ } pmuid;
+
+ pmuid.value = 0;
+ pmuid.vendor = (uint32_t) sbi_get_mvendorid();
+ pmuid.arch = (sbi_get_marchid() >> (63 - 15) & (1 << 15)) | (sbi_get_marchid() & 0x7FFF);
+ pmuid.imp = (sbi_get_mimpid() >> 16);
+
+ return pmuid.value;
+}
+
+static ssize_t pmu_sbi_id_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ int len;
+
+ len = sprintf(buf, "0x%llx\n", pmu_sbi_get_pmu_id());
+ if (len <= 0)
+ dev_err(dev, "mydrv: Invalid sprintf len: %dn", len);
+
+ return len;
+}
+
+static DEVICE_ATTR(id, S_IRUGO | S_IWUSR, pmu_sbi_id_show, 0);
+
+static struct attribute *pmu_sbi_attrs[] = {
+ &dev_attr_id.attr,
+ NULL
+};
+
+ATTRIBUTE_GROUPS(pmu_sbi);
+
static int pmu_sbi_device_probe(struct platform_device *pdev)
{
struct riscv_pmu *pmu = NULL;
@@ -1067,6 +1107,13 @@ static int pmu_sbi_device_probe(struct p
pmu->event_unmapped = pmu_sbi_event_unmapped;
pmu->csr_index = pmu_sbi_csr_index;
+ ret = sysfs_create_group(&pdev->dev.kobj, &pmu_sbi_group);
+ if (ret) {
+ dev_err(&pdev->dev, "sysfs creation failed\n");
+ return ret;
+ }
+ pdev->dev.groups = pmu_sbi_groups;
+
ret = cpuhp_state_add_instance(CPUHP_AP_PERF_RISCV_STARTING, &pmu->node);
if (ret)
return ret;

View File

@ -0,0 +1,55 @@
From 1dc069ffadf4ce7817a716f9df2f480254e9b01d Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Jo=C3=A3o=20M=C3=A1rio=20Domingos?=
<joao.mario@tecnico.ulisboa.pt>
Date: Tue, 16 Nov 2021 15:48:10 +0000
Subject: [PATCH 074/116] RISC-V: Support CPUID for risc-v in perf
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
This patch creates the header.c file for the risc-v architecture and introduces support for
PMU identification through sysfs.
It is now possible to configure pmu-events in risc-v.
Depends on patch [1], that introduces the id sysfs file.
Signed-off-by: João Mário Domingos <joao.mario@tecnico.ulisboa.pt>
Signed-off-by: minda.chen <minda.chen@starfivetech.com>
---
drivers/perf/riscv_pmu.c | 18 ++++++++++++++++++
1 file changed, 18 insertions(+)
--- a/drivers/perf/riscv_pmu.c
+++ b/drivers/perf/riscv_pmu.c
@@ -18,6 +18,23 @@
#include <asm/sbi.h>
+PMU_FORMAT_ATTR(event, "config:0-63");
+
+static struct attribute *riscv_arch_formats_attr[] = {
+ &format_attr_event.attr,
+ NULL,
+};
+
+static struct attribute_group riscv_pmu_format_group = {
+ .name = "format",
+ .attrs = riscv_arch_formats_attr,
+};
+
+static const struct attribute_group *riscv_pmu_attr_groups[] = {
+ &riscv_pmu_format_group,
+ NULL,
+};
+
static bool riscv_perf_user_access(struct perf_event *event)
{
return ((event->attr.type == PERF_TYPE_HARDWARE) ||
@@ -410,6 +427,7 @@ struct riscv_pmu *riscv_pmu_alloc(void)
cpuc->events[i] = NULL;
}
pmu->pmu = (struct pmu) {
+ .attr_groups = riscv_pmu_attr_groups,
.event_init = riscv_pmu_event_init,
.event_mapped = riscv_pmu_event_mapped,
.event_unmapped = riscv_pmu_event_unmapped,

View File

@ -0,0 +1,42 @@
From 3e6ea12dda276c01a756764fcafa315b19860c33 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Jo=C3=A3o=20M=C3=A1rio=20Domingos?=
<joao.mario@tecnico.ulisboa.pt>
Date: Tue, 16 Nov 2021 15:48:11 +0000
Subject: [PATCH 075/116] RISC-V: Added generic pmu-events mapfile
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
The pmu-events now supports custom events for RISC-V, plus the cycle,
time and instret events were defined.
Signed-off-by: João Mário Domingos <joao.mario@tecnico.ulisboa.pt>
---
.../pmu-events/arch/riscv/riscv-generic.json | 20 +++++++++++++++++++
1 file changed, 20 insertions(+)
create mode 100644 tools/perf/pmu-events/arch/riscv/riscv-generic.json
--- /dev/null
+++ b/tools/perf/pmu-events/arch/riscv/riscv-generic.json
@@ -0,0 +1,20 @@
+[
+ {
+ "PublicDescription": "CPU Cycles",
+ "EventCode": "0x00",
+ "EventName": "riscv_cycles",
+ "BriefDescription": "CPU cycles RISC-V generic counter"
+ },
+ {
+ "PublicDescription": "CPU Time",
+ "EventCode": "0x01",
+ "EventName": "riscv_time",
+ "BriefDescription": "CPU time RISC-V generic counter"
+ },
+ {
+ "PublicDescription": "CPU Instructions",
+ "EventCode": "0x02",
+ "EventName": "riscv_instret",
+ "BriefDescription": "CPU retired instructions RISC-V generic counter"
+ }
+]
\ No newline at end of file

View File

@ -0,0 +1,30 @@
From 30e0cdcf9e05faa65ecde4ed8b70039568fdb660 Mon Sep 17 00:00:00 2001
From: Minda Chen <minda.chen@starfivetech.com>
Date: Thu, 2 Mar 2023 17:16:01 +0800
Subject: [PATCH 076/116] perf: sbi: disable cpu hotplug callback.
register cpu hotplug callback will cause dhrystone
and coremark benchmark reduce the scores. this CPU
hotplug ops will do in sbi cpu/on and off. So disable
this no side effect.
Signed-off-by: Minda Chen <minda.chen@starfivetech.com>
Signed-off-by: Hal Feng <hal.feng@starfivetech.com>
---
drivers/perf/riscv_pmu_sbi.c | 2 ++
1 file changed, 2 insertions(+)
--- a/drivers/perf/riscv_pmu_sbi.c
+++ b/drivers/perf/riscv_pmu_sbi.c
@@ -1114,9 +1114,11 @@ static int pmu_sbi_device_probe(struct p
}
pdev->dev.groups = pmu_sbi_groups;
+#ifndef CONFIG_ARCH_STARFIVE
ret = cpuhp_state_add_instance(CPUHP_AP_PERF_RISCV_STARTING, &pmu->node);
if (ret)
return ret;
+#endif
ret = riscv_pm_pmu_register(pmu);
if (ret)

View File

@ -0,0 +1,24 @@
From fc4b5c7c27e1b56b1f848e50511c4fd081b1b6c5 Mon Sep 17 00:00:00 2001
From: Walker Chen <walker.chen@starfivetech.com>
Date: Mon, 12 Jun 2023 21:21:45 +0800
Subject: [PATCH 077/116] dmaengine: dw-axi-dmac: Drop unused print message
Removed printing information which is not related to StarFive
platform.
Signed-off-by: Walker Chen <walker.chen@starfivetech.com>
---
drivers/dma/dw-axi-dmac/dw-axi-dmac-platform.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
--- a/drivers/dma/dw-axi-dmac/dw-axi-dmac-platform.c
+++ b/drivers/dma/dw-axi-dmac/dw-axi-dmac-platform.c
@@ -523,7 +523,7 @@ static void dw_axi_dma_set_hw_channel(st
unsigned long reg_value, val;
if (!chip->apb_regs) {
- dev_err(chip->dev, "apb_regs not initialized\n");
+ dev_dbg(chip->dev, "apb_regs not initialized\n");
return;
}

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,537 @@
From 9c4858f9fe4d8f8fe5cf347b3ca727016b7ba492 Mon Sep 17 00:00:00 2001
From: Walker Chen <walker.chen@starfivetech.com>
Date: Tue, 20 Jun 2023 15:57:53 +0800
Subject: [PATCH 081/116] ASoC: starfive: Add JH7110 PDM driver
Add pdm driver support for the StarFive JH7110 SoC.
Signed-off-by: Walker Chen <walker.chen@starfivetech.com>
---
sound/soc/starfive/Kconfig | 8 +
sound/soc/starfive/Makefile | 2 +
sound/soc/starfive/jh7110_pdm.c | 493 ++++++++++++++++++++++++++++++++
3 files changed, 503 insertions(+)
create mode 100644 sound/soc/starfive/jh7110_pdm.c
--- a/sound/soc/starfive/Kconfig
+++ b/sound/soc/starfive/Kconfig
@@ -7,6 +7,14 @@ config SND_SOC_STARFIVE
the Starfive SoCs' Audio interfaces. You will also need to
select the audio interfaces to support below.
+config SND_SOC_JH7110_PDM
+ tristate "JH7110 PDM device driver"
+ depends on HAVE_CLK && SND_SOC_STARFIVE
+ select SND_SOC_JH7110_I2S
+ select REGMAP_MMIO
+ help
+ Say Y or M if you want to add support for StarFive pdm driver.
+
config SND_SOC_JH7110_PWMDAC
tristate "JH7110 PWM-DAC device driver"
depends on HAVE_CLK && SND_SOC_STARFIVE
--- a/sound/soc/starfive/Makefile
+++ b/sound/soc/starfive/Makefile
@@ -1,4 +1,6 @@
# StarFive Platform Support
+obj-$(CONFIG_SND_SOC_JH7110_PDM) += jh7110_pdm.o
+
obj-$(CONFIG_SND_SOC_JH7110_PWMDAC) += jh7110_pwmdac.o
obj-$(CONFIG_SND_SOC_JH7110_SPDIF) += spdif.o
--- /dev/null
+++ b/sound/soc/starfive/jh7110_pdm.c
@@ -0,0 +1,493 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * PDM driver for the StarFive JH7110 SoC
+ *
+ * Copyright (C) 2022 StarFive Technology Co., Ltd.
+ */
+#include <linux/clk.h>
+#include <linux/device.h>
+#include <linux/dmaengine.h>
+#include <linux/reset.h>
+#include <linux/module.h>
+#include <linux/of_irq.h>
+#include <linux/of_platform.h>
+#include <linux/regmap.h>
+#include <linux/pm_runtime.h>
+#include <linux/types.h>
+#include <sound/dmaengine_pcm.h>
+#include <sound/initval.h>
+#include <sound/pcm.h>
+#include <sound/pcm_params.h>
+#include <sound/soc.h>
+#include <sound/soc-dai.h>
+#include <sound/tlv.h>
+
+#define PDM_DMIC_CTRL0 0x00
+#define PDM_DC_SCALE0 0x04
+#define PDM_DMIC_CTRL1 0x10
+#define PDM_DC_SCALE1 0x14
+
+/* PDM CTRL OFFSET */
+#define PDM_DMIC_MSB_SHIFT 1
+#define PDM_DMIC_MSB_MASK (0x7 << PDM_DMIC_MSB_SHIFT)
+#define PDM_DMIC_VOL_SHIFT 16
+#define PDM_DMIC_VOL_MASK (0x3f << PDM_DMIC_VOL_SHIFT)
+#define PDM_VOL_DB_MUTE (0x3f << PDM_DMIC_VOL_SHIFT)
+#define PDM_VOL_DB_MAX 0
+
+#define PDM_DMIC_RVOL_MASK BIT(22)
+#define PDM_DMIC_LVOL_MASK BIT(23)
+#define PDM_DMIC_I2S_SLAVE BIT(24)
+#define PDM_DMIC_HPF_EN BIT(28)
+#define PDM_DMIC_FASTMODE_MASK BIT(29)
+#define PDM_DMIC_DC_BYPASS_MASK BIT(30)
+#define PDM_SW_RST_MASK BIT(31)
+#define PDM_SW_RST_RELEASE BIT(31)
+
+/* PDM SCALE OFFSET */
+#define DMIC_DCOFF3_SHIFT 24
+#define DMIC_DCOFF2_SHIFT 16
+#define DMIC_DCOFF1_SHIFT 8
+
+#define DMIC_DCOFF3_MASK (0xf << DMIC_DCOFF3_SHIFT)
+#define DMIC_DCOFF3_VAL (0xc << DMIC_DCOFF3_SHIFT)
+#define DMIC_DCOFF1_MASK (0xff << DMIC_DCOFF1_SHIFT)
+#define DMIC_DCOFF1_VAL (0x5 << DMIC_DCOFF1_SHIFT)
+#define DMIC_SCALE_MASK 0x3f
+#define DMIC_SCALE_DEF_VAL 0x8
+
+enum PDM_MSB_SHIFT {
+ PDM_MSB_SHIFT_NONE = 0,
+ PDM_MSB_SHIFT_1,
+ PDM_MSB_SHIFT_2,
+ PDM_MSB_SHIFT_3,
+ PDM_MSB_SHIFT_4,
+ PDM_MSB_SHIFT_5,
+ PDM_MSB_SHIFT_6,
+ PDM_MSB_SHIFT_7,
+};
+
+struct sf_pdm {
+ struct regmap *pdm_map;
+ struct device *dev;
+ struct clk *clk_pdm_apb;
+ struct clk *clk_pdm_mclk;
+ struct clk *clk_mclk;
+ struct clk *clk_mclk_ext;
+ struct reset_control *rst_pdm_dmic;
+ struct reset_control *rst_pdm_apb;
+ unsigned char flag_first;
+ unsigned int saved_ctrl0;
+ unsigned int saved_scale0;
+};
+
+static const DECLARE_TLV_DB_SCALE(volume_tlv, -9450, 150, 0);
+
+static const struct snd_kcontrol_new sf_pdm_snd_controls[] = {
+ SOC_SINGLE("DC compensation Control", PDM_DMIC_CTRL0, 30, 1, 0),
+ SOC_SINGLE("High Pass Filter Control", PDM_DMIC_CTRL0, 28, 1, 0),
+ SOC_SINGLE("Left Channel Volume Control", PDM_DMIC_CTRL0, 23, 1, 0),
+ SOC_SINGLE("Right Channel Volume Control", PDM_DMIC_CTRL0, 22, 1, 0),
+ SOC_SINGLE_TLV("Volume", PDM_DMIC_CTRL0, 16, 0x3F, 1, volume_tlv),
+ SOC_SINGLE("Data MSB Shift", PDM_DMIC_CTRL0, 1, 7, 0),
+ SOC_SINGLE("SCALE", PDM_DC_SCALE0, 0, 0x3F, 0),
+ SOC_SINGLE("DC offset", PDM_DC_SCALE0, 8, 0xFFFFF, 0),
+};
+
+static void sf_pdm_enable(struct regmap *map)
+{
+ /* Left and Right Channel Volume Control Enable */
+ regmap_update_bits(map, PDM_DMIC_CTRL0, PDM_DMIC_RVOL_MASK, 0);
+ regmap_update_bits(map, PDM_DMIC_CTRL0, PDM_DMIC_LVOL_MASK, 0);
+}
+
+static void sf_pdm_disable(struct regmap *map)
+{
+ /* Left and Right Channel Volume Control Disable */
+ regmap_update_bits(map, PDM_DMIC_CTRL0,
+ PDM_DMIC_RVOL_MASK, PDM_DMIC_RVOL_MASK);
+ regmap_update_bits(map, PDM_DMIC_CTRL0,
+ PDM_DMIC_LVOL_MASK, PDM_DMIC_LVOL_MASK);
+}
+
+static int sf_pdm_trigger(struct snd_pcm_substream *substream, int cmd,
+ struct snd_soc_dai *dai)
+{
+ struct sf_pdm *priv = snd_soc_dai_get_drvdata(dai);
+
+ switch (cmd) {
+ case SNDRV_PCM_TRIGGER_START:
+ case SNDRV_PCM_TRIGGER_RESUME:
+ case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
+ if (priv->flag_first) {
+ priv->flag_first = 0;
+ mdelay(200);
+ }
+
+ sf_pdm_enable(priv->pdm_map);
+ return 0;
+
+ case SNDRV_PCM_TRIGGER_STOP:
+ case SNDRV_PCM_TRIGGER_SUSPEND:
+ case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
+ sf_pdm_disable(priv->pdm_map);
+ return 0;
+
+ default:
+ return -EINVAL;
+ }
+}
+
+static int sf_pdm_hw_params(struct snd_pcm_substream *substream,
+ struct snd_pcm_hw_params *params,
+ struct snd_soc_dai *dai)
+{
+ struct sf_pdm *priv = snd_soc_dai_get_drvdata(dai);
+ unsigned int sample_rate;
+ unsigned int data_width;
+ int ret;
+ const int pdm_mul = 128;
+
+ sample_rate = params_rate(params);
+ switch (sample_rate) {
+ case 8000:
+ case 11025:
+ case 16000:
+ break;
+ default:
+ dev_err(priv->dev, "can't support sample rate:%d\n", sample_rate);
+ return -EINVAL;
+ }
+
+ data_width = params_width(params);
+ switch (data_width) {
+ case 16:
+ case 32:
+ break;
+ default:
+ dev_err(priv->dev, "can't support bit width %d\n", data_width);
+ return -EINVAL;
+ }
+
+ /* set pdm_mclk, PDM MCLK = 128 * LRCLK */
+ ret = clk_set_rate(priv->clk_pdm_mclk, pdm_mul * sample_rate);
+ if (ret) {
+ dev_err(priv->dev, "Can't set pdm_mclk: %d\n", ret);
+ return ret;
+ }
+
+ return 0;
+}
+
+static const struct snd_soc_dai_ops sf_pdm_dai_ops = {
+ .trigger = sf_pdm_trigger,
+ .hw_params = sf_pdm_hw_params,
+};
+
+static void sf_pdm_module_init(struct sf_pdm *priv)
+{
+ /* Reset */
+ regmap_update_bits(priv->pdm_map, PDM_DMIC_CTRL0,
+ PDM_SW_RST_MASK, 0x00);
+ regmap_update_bits(priv->pdm_map, PDM_DMIC_CTRL0,
+ PDM_SW_RST_MASK, PDM_SW_RST_RELEASE);
+
+ /* Make sure the device is initially disabled */
+ sf_pdm_disable(priv->pdm_map);
+
+ /* MUTE */
+ regmap_update_bits(priv->pdm_map, PDM_DMIC_CTRL0,
+ PDM_DMIC_VOL_MASK, PDM_VOL_DB_MUTE);
+
+ /* UNMUTE */
+ regmap_update_bits(priv->pdm_map, PDM_DMIC_CTRL0,
+ PDM_DMIC_VOL_MASK, PDM_VOL_DB_MAX);
+
+ /* enable high pass filter */
+ regmap_update_bits(priv->pdm_map, PDM_DMIC_CTRL0,
+ PDM_DMIC_HPF_EN, PDM_DMIC_HPF_EN);
+
+ /* PDM work as slave mode */
+ regmap_update_bits(priv->pdm_map, PDM_DMIC_CTRL0,
+ PDM_DMIC_I2S_SLAVE, PDM_DMIC_I2S_SLAVE);
+
+ /* disable fast mode */
+ regmap_update_bits(priv->pdm_map, PDM_DMIC_CTRL0,
+ PDM_DMIC_FASTMODE_MASK, 0);
+
+ /* dmic msb shift 0 */
+ regmap_update_bits(priv->pdm_map, PDM_DMIC_CTRL0,
+ PDM_DMIC_MSB_MASK, 0);
+
+ /* scale: 0x8 */
+ regmap_update_bits(priv->pdm_map, PDM_DC_SCALE0,
+ DMIC_SCALE_MASK, DMIC_SCALE_DEF_VAL);
+
+ regmap_update_bits(priv->pdm_map, PDM_DC_SCALE0,
+ DMIC_DCOFF1_MASK, DMIC_DCOFF1_VAL);
+
+ regmap_update_bits(priv->pdm_map, PDM_DC_SCALE0,
+ DMIC_DCOFF3_MASK, DMIC_DCOFF3_VAL);
+
+ /* scale: 0x3f */
+ regmap_update_bits(priv->pdm_map, PDM_DC_SCALE0,
+ DMIC_SCALE_MASK, DMIC_SCALE_MASK);
+
+ /* dmic msb shift 2 */
+ regmap_update_bits(priv->pdm_map, PDM_DMIC_CTRL0,
+ PDM_DMIC_MSB_MASK, PDM_MSB_SHIFT_4);
+}
+
+#define SF_PDM_RATES (SNDRV_PCM_RATE_8000 | \
+ SNDRV_PCM_RATE_11025 | \
+ SNDRV_PCM_RATE_16000)
+
+#define SF_PDM_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | \
+ SNDRV_PCM_FMTBIT_S32_LE)
+
+static struct snd_soc_dai_driver sf_pdm_dai_drv = {
+ .name = "PDM",
+ .id = 0,
+ .capture = {
+ .stream_name = "Capture",
+ .channels_min = 2,
+ .channels_max = 2,
+ .rates = SF_PDM_RATES,
+ .formats = SF_PDM_FORMATS,
+ },
+ .ops = &sf_pdm_dai_ops,
+ .symmetric_rate = 1,
+};
+
+static int sf_pdm_component_probe(struct snd_soc_component *component)
+{
+ struct sf_pdm *priv = snd_soc_component_get_drvdata(component);
+
+ snd_soc_component_init_regmap(component, priv->pdm_map);
+ snd_soc_add_component_controls(component, sf_pdm_snd_controls,
+ ARRAY_SIZE(sf_pdm_snd_controls));
+
+ return 0;
+}
+
+static int sf_pdm_clock_enable(struct sf_pdm *priv)
+{
+ int ret;
+
+ ret = clk_prepare_enable(priv->clk_pdm_mclk);
+ if (ret) {
+ dev_err(priv->dev, "failed to prepare enable clk_pdm_mclk\n");
+ return ret;
+ }
+
+ ret = clk_prepare_enable(priv->clk_pdm_apb);
+ if (ret) {
+ dev_err(priv->dev, "failed to prepare enable clk_pdm_apb\n");
+ goto disable_pdm_mclk;
+ }
+
+ ret = reset_control_deassert(priv->rst_pdm_dmic);
+ if (ret) {
+ dev_err(priv->dev, "failed to deassert pdm_dmic\n");
+ goto disable_pdm_apb;
+ }
+
+ ret = reset_control_deassert(priv->rst_pdm_apb);
+ if (ret) {
+ dev_err(priv->dev, "failed to deassert pdm_apb\n");
+ goto disable_pdm_apb;
+ }
+
+ ret = clk_set_parent(priv->clk_mclk, priv->clk_mclk_ext);
+ if (ret) {
+ dev_err(priv->dev, "failed to set parent clk_mclk ret=%d\n", ret);
+ goto disable_pdm_apb;
+ }
+
+ return 0;
+
+disable_pdm_apb:
+ clk_disable_unprepare(priv->clk_pdm_apb);
+disable_pdm_mclk:
+ clk_disable_unprepare(priv->clk_pdm_mclk);
+
+ return ret;
+}
+
+#ifdef CONFIG_PM
+static int sf_pdm_runtime_suspend(struct device *dev)
+{
+ struct sf_pdm *priv = dev_get_drvdata(dev);
+
+ clk_disable_unprepare(priv->clk_pdm_apb);
+ clk_disable_unprepare(priv->clk_pdm_mclk);
+
+ return 0;
+}
+
+static int sf_pdm_runtime_resume(struct device *dev)
+{
+ struct sf_pdm *priv = dev_get_drvdata(dev);
+ int ret;
+
+ ret = sf_pdm_clock_enable(priv);
+ if (!ret)
+ sf_pdm_module_init(priv);
+
+ return ret;
+}
+#endif
+
+#ifdef CONFIG_PM_SLEEP
+static int sf_pdm_suspend(struct snd_soc_component *component)
+{
+ return pm_runtime_force_suspend(component->dev);
+}
+
+static int sf_pdm_resume(struct snd_soc_component *component)
+{
+ return pm_runtime_force_resume(component->dev);
+}
+
+#else
+#define sf_pdm_suspend NULL
+#define sf_pdm_resume NULL
+#endif
+
+static const struct snd_soc_component_driver sf_pdm_component_drv = {
+ .name = "jh7110-pdm",
+ .probe = sf_pdm_component_probe,
+ .suspend = sf_pdm_suspend,
+ .resume = sf_pdm_resume,
+};
+
+static const struct regmap_config sf_pdm_regmap_cfg = {
+ .reg_bits = 32,
+ .val_bits = 32,
+ .reg_stride = 4,
+ .max_register = 0x20,
+};
+
+static int sf_pdm_clock_get(struct platform_device *pdev, struct sf_pdm *priv)
+{
+ int ret;
+
+ static struct clk_bulk_data clks[] = {
+ { .id = "pdm_mclk" },
+ { .id = "pdm_apb" },
+ { .id = "clk_mclk" },
+ { .id = "mclk_ext" },
+ };
+
+ ret = devm_clk_bulk_get(&pdev->dev, ARRAY_SIZE(clks), clks);
+ if (ret) {
+ dev_err(&pdev->dev, "failed to get pdm clocks\n");
+ goto exit;
+ }
+
+ priv->clk_pdm_mclk = clks[0].clk;
+ priv->clk_pdm_apb = clks[1].clk;
+ priv->clk_mclk = clks[2].clk;
+ priv->clk_mclk_ext = clks[3].clk;
+
+ priv->rst_pdm_dmic = devm_reset_control_get_exclusive(&pdev->dev, "pdm_dmic");
+ if (IS_ERR(priv->rst_pdm_dmic)) {
+ dev_err(&pdev->dev, "failed to get pdm_dmic reset control\n");
+ ret = PTR_ERR(priv->rst_pdm_dmic);
+ goto exit;
+ }
+
+ priv->rst_pdm_apb = devm_reset_control_get_exclusive(&pdev->dev, "pdm_apb");
+ if (IS_ERR(priv->rst_pdm_apb)) {
+ dev_err(&pdev->dev, "failed to get pdm_apb reset control\n");
+ ret = PTR_ERR(priv->rst_pdm_apb);
+ goto exit;
+ }
+
+ /*
+ * pdm clock must always be enabled as hardware issue that
+ * no data in the first 4 seconds of the first recording
+ */
+ ret = sf_pdm_clock_enable(priv);
+
+exit:
+ return ret;
+}
+
+static int sf_pdm_probe(struct platform_device *pdev)
+{
+ struct sf_pdm *priv;
+ struct resource *res;
+ void __iomem *regs;
+ int ret;
+
+ priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL);
+ if (!priv)
+ return -ENOMEM;
+ platform_set_drvdata(pdev, priv);
+
+ res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "pdm");
+ regs = devm_ioremap_resource(&pdev->dev, res);
+ if (IS_ERR(regs))
+ return PTR_ERR(regs);
+
+ priv->pdm_map = devm_regmap_init_mmio(&pdev->dev, regs, &sf_pdm_regmap_cfg);
+ if (IS_ERR(priv->pdm_map)) {
+ dev_err(&pdev->dev, "failed to init regmap: %ld\n",
+ PTR_ERR(priv->pdm_map));
+ return PTR_ERR(priv->pdm_map);
+ }
+
+ priv->dev = &pdev->dev;
+ priv->flag_first = 1;
+
+ ret = sf_pdm_clock_get(pdev, priv);
+ if (ret) {
+ dev_err(&pdev->dev, "failed to enable audio-pdm clock\n");
+ return ret;
+ }
+
+ dev_set_drvdata(&pdev->dev, priv);
+
+ ret = devm_snd_soc_register_component(&pdev->dev, &sf_pdm_component_drv,
+ &sf_pdm_dai_drv, 1);
+ if (ret) {
+ dev_err(&pdev->dev, "failed to register pdm dai\n");
+ return ret;
+ }
+ pm_runtime_enable(&pdev->dev);
+
+ return 0;
+}
+
+static int sf_pdm_dev_remove(struct platform_device *pdev)
+{
+ pm_runtime_disable(&pdev->dev);
+ return 0;
+}
+
+static const struct of_device_id sf_pdm_of_match[] = {
+ {.compatible = "starfive,jh7110-pdm",},
+ {}
+};
+MODULE_DEVICE_TABLE(of, sf_pdm_of_match);
+
+static const struct dev_pm_ops sf_pdm_pm_ops = {
+ SET_RUNTIME_PM_OPS(sf_pdm_runtime_suspend,
+ sf_pdm_runtime_resume, NULL)
+};
+
+static struct platform_driver sf_pdm_driver = {
+ .driver = {
+ .name = "jh7110-pdm",
+ .of_match_table = sf_pdm_of_match,
+ .pm = &sf_pdm_pm_ops,
+ },
+ .probe = sf_pdm_probe,
+ .remove = sf_pdm_dev_remove,
+};
+module_platform_driver(sf_pdm_driver);
+
+MODULE_AUTHOR("Walker Chen <walker.chen@starfivetech.com>");
+MODULE_DESCRIPTION("Starfive PDM Controller Driver");
+MODULE_LICENSE("GPL v2");

View File

@ -0,0 +1,55 @@
From 59cbdfeee0fc1ad382a0bc8f7fa897a9f5d03df0 Mon Sep 17 00:00:00 2001
From: Changhuang Liang <changhuang.liang@starfivetech.com>
Date: Fri, 9 Jun 2023 16:54:36 +0800
Subject: [PATCH 082/116] dt-binding: input: Add tink_ft5406
Add tink_ft5406.
Signed-off-by: Changhuang Liang <changhuang.liang@starfivetech.com>
---
.../bindings/input/tinker_ft5406.yaml | 39 +++++++++++++++++++
1 file changed, 39 insertions(+)
create mode 100644 Documentation/devicetree/bindings/input/tinker_ft5406.yaml
--- /dev/null
+++ b/Documentation/devicetree/bindings/input/tinker_ft5406.yaml
@@ -0,0 +1,39 @@
+# SPDX-License-Identifier: GPL-2.0
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/input/touchscreen/goodix.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Tinker FT5406 touchscreen controller Bindings
+
+maintainers:
+ - Changhuang Liang <changhuang.liang@starfivetech.com>
+
+allOf:
+ - $ref: touchscreen.yaml#
+
+properties:
+ compatible:
+ const: tinker_ft5406
+
+ reg:
+ const: 0x38
+
+additionalProperties: false
+
+required:
+ - compatible
+ - reg
+
+examples:
+ - |
+ i2c {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ tinker_ft5406@38 {
+ compatible = "tinker_ft5406";
+ reg = <0x38>;
+ };
+ };
+
+...

View File

@ -0,0 +1,444 @@
From 4800b6e0f2190d991cd4e5352167a9422841f195 Mon Sep 17 00:00:00 2001
From: Changhuang Liang <changhuang.liang@starfivetech.com>
Date: Wed, 21 Dec 2022 16:20:04 +0800
Subject: [PATCH 083/116] input: touchscreen: Add tinker_ft5406 driver support
Add tinker_ft5406 driver support
Signed-off-by: Changhuang Liang <changhuang.liang@starfivetech.com>
---
drivers/input/touchscreen/Kconfig | 6 +
drivers/input/touchscreen/Makefile | 1 +
drivers/input/touchscreen/tinker_ft5406.c | 406 ++++++++++++++++++++++
3 files changed, 413 insertions(+)
create mode 100644 drivers/input/touchscreen/tinker_ft5406.c
--- a/drivers/input/touchscreen/Kconfig
+++ b/drivers/input/touchscreen/Kconfig
@@ -1399,4 +1399,10 @@ config TOUCHSCREEN_HIMAX_HX83112B
To compile this driver as a module, choose M here: the
module will be called himax_hx83112b.
+config TOUCHSCREEN_TINKER_FT5406
+ tristate "tinker ft5406"
+ depends on I2C
+ help
+ Control ft5406 touch ic.
+
endif
--- a/drivers/input/touchscreen/Makefile
+++ b/drivers/input/touchscreen/Makefile
@@ -118,3 +118,4 @@ obj-$(CONFIG_TOUCHSCREEN_IQS5XX) += iqs5
obj-$(CONFIG_TOUCHSCREEN_IQS7211) += iqs7211.o
obj-$(CONFIG_TOUCHSCREEN_ZINITIX) += zinitix.o
obj-$(CONFIG_TOUCHSCREEN_HIMAX_HX83112B) += himax_hx83112b.o
+obj-$(CONFIG_TOUCHSCREEN_TINKER_FT5406) += tinker_ft5406.o
--- /dev/null
+++ b/drivers/input/touchscreen/tinker_ft5406.c
@@ -0,0 +1,406 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ *
+ * TINKER BOARD FT5406 touch driver.
+ *
+ * Copyright (c) 2016 ASUSTek Computer Inc.
+ * Copyright (c) 2012-2014, The Linux Foundation. All rights reserved.
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#include <linux/module.h>
+#include <linux/slab.h>
+#include <linux/delay.h>
+#include <linux/i2c.h>
+#include <linux/input.h>
+#include <linux/input/mt.h>
+#include <linux/module.h>
+#include <linux/workqueue.h>
+
+#define RETRY_COUNT 10
+#define FT_ONE_TCH_LEN 6
+
+#define FT_REG_FW_VER 0xA6
+#define FT_REG_FW_MIN_VER 0xB2
+#define FT_REG_FW_SUB_MIN_VER 0xB3
+
+#define VALID_TD_STATUS_VAL 10
+#define MAX_TOUCH_POINTS 5
+
+#define FT_PRESS 0x7F
+#define FT_MAX_ID 0x0F
+
+#define FT_TOUCH_X_H 0
+#define FT_TOUCH_X_L 1
+#define FT_TOUCH_Y_H 2
+#define FT_TOUCH_Y_L 3
+#define FT_TOUCH_EVENT 0
+#define FT_TOUCH_ID 2
+
+#define FT_TOUCH_X_H_REG 3
+#define FT_TOUCH_X_L_REG 4
+#define FT_TOUCH_Y_H_REG 5
+#define FT_TOUCH_Y_L_REG 6
+#define FT_TD_STATUS_REG 2
+#define FT_TOUCH_EVENT_REG 3
+#define FT_TOUCH_ID_REG 5
+
+#define FT_TOUCH_DOWN 0
+#define FT_TOUCH_CONTACT 2
+
+struct ts_event {
+ u16 au16_x[MAX_TOUCH_POINTS]; /*x coordinate */
+ u16 au16_y[MAX_TOUCH_POINTS]; /*y coordinate */
+ u8 au8_touch_event[MAX_TOUCH_POINTS]; /*touch event: 0:down; 1:up; 2:contact */
+ u8 au8_finger_id[MAX_TOUCH_POINTS]; /*touch ID */
+ u16 pressure;
+ u8 touch_point;
+ u8 point_num;
+};
+
+struct tinker_ft5406_data {
+ struct device *dev;
+ struct i2c_client *client;
+ struct input_dev *input_dev;
+ struct ts_event event;
+ struct work_struct ft5406_work;
+
+ int screen_width;
+ int screen_height;
+ int xy_reverse;
+ int known_ids;
+ int retry_count;
+ bool finish_work;
+};
+
+struct tinker_ft5406_data *g_ts_data;
+
+static int fts_i2c_read(struct i2c_client *client, char *writebuf,
+ int writelen, char *readbuf, int readlen)
+{
+ int ret;
+
+ if (writelen > 0) {
+ struct i2c_msg msgs[] = {
+ {
+ .addr = client->addr,
+ .flags = 0,
+ .len = writelen,
+ .buf = writebuf,
+ },
+ {
+ .addr = client->addr,
+ .flags = I2C_M_RD,
+ .len = readlen,
+ .buf = readbuf,
+ },
+ };
+ ret = i2c_transfer(client->adapter, msgs, 2);
+ if (ret < 0)
+ dev_err(&client->dev, "i2c read error, %d\n", ret);
+ } else {
+ struct i2c_msg msgs[] = {
+ {
+ .addr = client->addr,
+ .flags = I2C_M_RD,
+ .len = readlen,
+ .buf = readbuf,
+ },
+ };
+ ret = i2c_transfer(client->adapter, msgs, 1);
+ if (ret < 0)
+ dev_err(&client->dev, "i2c read error, %d\n", ret);
+ }
+
+ return ret;
+}
+
+static int fts_read_reg(struct i2c_client *client, u8 addr, u8 *val)
+{
+ return fts_i2c_read(client, &addr, 1, val, 1);
+}
+
+static int fts_check_fw_ver(struct i2c_client *client)
+{
+ u8 reg_addr, fw_ver[3];
+ int ret;
+
+ reg_addr = FT_REG_FW_VER;
+ ret = fts_i2c_read(client, &reg_addr, 1, &fw_ver[0], 1);
+ if (ret < 0)
+ goto error;
+
+ reg_addr = FT_REG_FW_MIN_VER;
+ ret = fts_i2c_read(client, &reg_addr, 1, &fw_ver[1], 1);
+ if (ret < 0)
+ goto error;
+
+ reg_addr = FT_REG_FW_SUB_MIN_VER;
+ ret = fts_i2c_read(client, &reg_addr, 1, &fw_ver[2], 1);
+ if (ret < 0)
+ goto error;
+
+ dev_info(&client->dev, "Firmware version = %d.%d.%d\n",
+ fw_ver[0], fw_ver[1], fw_ver[2]);
+ return 0;
+
+error:
+ return ret;
+}
+
+static int fts_read_td_status(struct tinker_ft5406_data *ts_data)
+{
+ u8 td_status;
+ int ret = -1;
+
+ ret = fts_read_reg(ts_data->client, FT_TD_STATUS_REG, &td_status);
+ if (ret < 0) {
+ dev_err(&ts_data->client->dev,
+ "Get reg td_status failed, %d\n", ret);
+ return ret;
+ }
+ return (int)td_status;
+}
+
+static int fts_read_touchdata(struct tinker_ft5406_data *ts_data)
+{
+ struct ts_event *event = &ts_data->event;
+ int ret = -1, i;
+ u8 buf[FT_ONE_TCH_LEN-2] = { 0 };
+ u8 reg_addr, pointid = FT_MAX_ID;
+
+ for (i = 0; i < event->touch_point && i < MAX_TOUCH_POINTS; i++) {
+ reg_addr = FT_TOUCH_X_H_REG + (i * FT_ONE_TCH_LEN);
+ ret = fts_i2c_read(ts_data->client, &reg_addr, 1, buf, FT_ONE_TCH_LEN-2);
+ if (ret < 0) {
+ dev_err(&ts_data->client->dev, "Read touchdata failed.\n");
+ return ret;
+ }
+
+ pointid = (buf[FT_TOUCH_ID]) >> 4;
+ if (pointid >= MAX_TOUCH_POINTS)
+ break;
+ event->au8_finger_id[i] = pointid;
+ event->au16_x[i] = (s16) (buf[FT_TOUCH_X_H] & 0x0F) << 8 | (s16) buf[FT_TOUCH_X_L];
+ event->au16_y[i] = (s16) (buf[FT_TOUCH_Y_H] & 0x0F) << 8 | (s16) buf[FT_TOUCH_Y_L];
+ event->au8_touch_event[i] = buf[FT_TOUCH_EVENT] >> 6;
+
+ if (ts_data->xy_reverse) {
+ event->au16_x[i] = ts_data->screen_width - event->au16_x[i] - 1;
+ event->au16_y[i] = ts_data->screen_height - event->au16_y[i] - 1;
+ }
+ }
+ event->pressure = FT_PRESS;
+
+ return 0;
+}
+
+static void fts_report_value(struct tinker_ft5406_data *ts_data)
+{
+ struct ts_event *event = &ts_data->event;
+ int i, modified_ids = 0, released_ids;
+
+ for (i = 0; i < event->touch_point && i < MAX_TOUCH_POINTS; i++) {
+ if (event->au8_touch_event[i] == FT_TOUCH_DOWN ||
+ event->au8_touch_event[i] == FT_TOUCH_CONTACT) {
+ modified_ids |= 1 << event->au8_finger_id[i];
+ input_mt_slot(ts_data->input_dev, event->au8_finger_id[i]);
+ input_mt_report_slot_state(ts_data->input_dev, MT_TOOL_FINGER,
+ true);
+ input_report_abs(ts_data->input_dev, ABS_MT_TOUCH_MAJOR,
+ event->pressure);
+ input_report_abs(ts_data->input_dev, ABS_MT_POSITION_X,
+ event->au16_x[i]);
+ input_report_abs(ts_data->input_dev, ABS_MT_POSITION_Y,
+ event->au16_y[i]);
+
+ if (!((1 << event->au8_finger_id[i]) & ts_data->known_ids))
+ dev_dbg(&ts_data->client->dev, "Touch id-%d: x = %d, y = %d\n",
+ event->au8_finger_id[i],
+ event->au16_x[i],
+ event->au16_y[i]);
+ }
+ }
+
+ released_ids = ts_data->known_ids & ~modified_ids;
+ for (i = 0; released_ids && i < MAX_TOUCH_POINTS; i++) {
+ if (released_ids & (1<<i)) {
+ dev_dbg(&ts_data->client->dev, "Release id-%d, known = %x modified = %x\n",
+ i, ts_data->known_ids, modified_ids);
+ input_mt_slot(ts_data->input_dev, i);
+ input_mt_report_slot_state(ts_data->input_dev, MT_TOOL_FINGER, false);
+ modified_ids &= ~(1 << i);
+ }
+ }
+ ts_data->known_ids = modified_ids;
+ input_mt_report_pointer_emulation(ts_data->input_dev, true);
+ input_sync(ts_data->input_dev);
+}
+
+static void fts_retry_clear(struct tinker_ft5406_data *ts_data)
+{
+ if (ts_data->retry_count != 0)
+ ts_data->retry_count = 0;
+}
+
+static int fts_retry_wait(struct tinker_ft5406_data *ts_data)
+{
+ if (ts_data->retry_count < RETRY_COUNT) {
+ dev_info(&ts_data->client->dev,
+ "Wait and retry, count = %d\n", ts_data->retry_count);
+ ts_data->retry_count++;
+ msleep(1000);
+ return 1;
+ }
+ dev_err(&ts_data->client->dev, "Attach retry count\n");
+ return 0;
+}
+
+static void tinker_ft5406_work(struct work_struct *work)
+{
+ struct ts_event *event = &g_ts_data->event;
+ int ret = 0, td_status;
+
+ /* polling 60fps */
+ while (!g_ts_data->finish_work) {
+ td_status = fts_read_td_status(g_ts_data);
+ if (td_status < 0) {
+ ret = fts_retry_wait(g_ts_data);
+ if (ret == 0) {
+ dev_err(&g_ts_data->client->dev, "Stop touch polling\n");
+ break;
+ }
+ } else if (td_status < VALID_TD_STATUS_VAL + 1 &&
+ (td_status > 0 || g_ts_data->known_ids != 0)) {
+ fts_retry_clear(g_ts_data);
+ memset(event, -1, sizeof(struct ts_event));
+ event->touch_point = td_status;
+ ret = fts_read_touchdata(g_ts_data);
+ if (ret == 0)
+ fts_report_value(g_ts_data);
+ }
+ msleep_interruptible(17);
+ }
+}
+
+static int tinker_ft5406_open(struct input_dev *dev)
+{
+ schedule_work(&g_ts_data->ft5406_work);
+ return 0;
+}
+
+static void tinker_ft5406_close(struct input_dev *dev)
+{
+ g_ts_data->finish_work = true;
+ cancel_work_sync(&g_ts_data->ft5406_work);
+ g_ts_data->finish_work = false;
+}
+
+static int tinker_ft5406_probe(struct i2c_client *client)
+{
+ struct input_dev *input_dev;
+ int ret = 0;
+
+ dev_info(&client->dev, "Address = 0x%x\n", client->addr);
+
+ g_ts_data = kzalloc(sizeof(struct tinker_ft5406_data), GFP_KERNEL);
+ if (g_ts_data == NULL) {
+ dev_err(&client->dev, "No memory for device\n");
+ return -ENOMEM;
+ }
+
+ g_ts_data->client = client;
+ i2c_set_clientdata(client, g_ts_data);
+
+ g_ts_data->screen_width = 800;
+ g_ts_data->screen_height = 480;
+ g_ts_data->xy_reverse = 1;
+
+ dev_info(&client->dev, "width = %d, height = %d, reverse = %d\n",
+ g_ts_data->screen_width, g_ts_data->screen_height, g_ts_data->xy_reverse);
+
+ ret = fts_check_fw_ver(g_ts_data->client);
+ if (ret) {
+ dev_err(&client->dev, "Checking touch ic failed\n");
+ goto check_fw_err;
+ }
+
+ input_dev = input_allocate_device();
+ if (!input_dev) {
+ dev_err(&client->dev, "Failed to allocate input device\n");
+ goto input_allocate_failed;
+ }
+ input_dev->name = "fts_ts";
+ input_dev->id.bustype = BUS_I2C;
+ input_dev->dev.parent = &g_ts_data->client->dev;
+ input_dev->open = tinker_ft5406_open;
+ input_dev->close = tinker_ft5406_close;
+
+ g_ts_data->input_dev = input_dev;
+ input_set_drvdata(input_dev, g_ts_data);
+
+ __set_bit(EV_SYN, input_dev->evbit);
+ __set_bit(EV_KEY, input_dev->evbit);
+ __set_bit(EV_ABS, input_dev->evbit);
+ __set_bit(BTN_TOUCH, input_dev->keybit);
+
+ input_mt_init_slots(input_dev, MAX_TOUCH_POINTS, 0);
+ input_set_abs_params(input_dev, ABS_MT_POSITION_X, 0, g_ts_data->screen_width, 0, 0);
+ input_set_abs_params(input_dev, ABS_MT_POSITION_Y, 0, g_ts_data->screen_height, 0, 0);
+
+ ret = input_register_device(input_dev);
+ if (ret) {
+ dev_err(&client->dev, "Input device registration failed\n");
+ goto input_register_failed;
+ }
+
+ INIT_WORK(&g_ts_data->ft5406_work, tinker_ft5406_work);
+
+ return 0;
+
+input_register_failed:
+ input_free_device(input_dev);
+input_allocate_failed:
+check_fw_err:
+ kfree(g_ts_data);
+ g_ts_data = NULL;
+ return ret;
+}
+
+static void tinker_ft5406_remove(struct i2c_client *client)
+{
+ cancel_work_sync(&g_ts_data->ft5406_work);
+ if (g_ts_data->input_dev) {
+ input_unregister_device(g_ts_data->input_dev);
+ input_free_device(g_ts_data->input_dev);
+ }
+ kfree(g_ts_data);
+ g_ts_data = NULL;
+}
+
+static const struct i2c_device_id tinker_ft5406_id[] = {
+ {"tinker_ft5406", 0},
+ {},
+};
+
+static struct i2c_driver tinker_ft5406_driver = {
+ .driver = {
+ .name = "tinker_ft5406",
+ },
+ .probe = tinker_ft5406_probe,
+ .remove = tinker_ft5406_remove,
+ .id_table = tinker_ft5406_id,
+};
+module_i2c_driver(tinker_ft5406_driver);
+
+MODULE_DESCRIPTION("TINKER BOARD FT5406 Touch driver");
+MODULE_LICENSE("GPL v2");

View File

@ -0,0 +1,246 @@
From b477a1a53553336edcfeb83be1b35817928daed8 Mon Sep 17 00:00:00 2001
From: Changhuang Liang <changhuang.liang@starfivetech.com>
Date: Mon, 5 Jun 2023 14:46:16 +0800
Subject: [PATCH 084/116] dt-binding: media: Add JH7110 Camera Subsystem.
Add the bindings documentation for Starfive JH7110 Camera Subsystem
which is used for handing image sensor data.
Signed-off-by: Changhuang Liang <changhuang.liang@starfivetech.com>
Signed-off-by: Jack Zhu <jack.zhu@starfivetech.com>
---
.../bindings/media/starfive,jh7110-camss.yaml | 228 ++++++++++++++++++
1 file changed, 228 insertions(+)
create mode 100644 Documentation/devicetree/bindings/media/starfive,jh7110-camss.yaml
--- /dev/null
+++ b/Documentation/devicetree/bindings/media/starfive,jh7110-camss.yaml
@@ -0,0 +1,228 @@
+# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/media/starfive,jh7110-camss.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Starfive SoC CAMSS ISP
+
+maintainers:
+ - Jack Zhu <jack.zhu@starfivetech.com>
+ - Changhuang Liang <changhuang.liang@starfivetech.com>
+
+description:
+ The Starfive CAMSS ISP is a Camera interface for Starfive JH7110 SoC. It
+ consists of a VIN controller (Video In Controller, a top-level control unit)
+ and an ISP.
+
+properties:
+ compatible:
+ const: starfive,jh7110-vin
+
+ reg:
+ maxItems: 8
+
+ reg-names:
+ items:
+ - const: csi2rx
+ - const: vclk
+ - const: vrst
+ - const: sctrl
+ - const: isp
+ - const: trst
+ - const: pmu
+ - const: syscrg
+
+ clocks:
+ maxItems: 16
+
+ clock-names:
+ items:
+ - const: clk_apb_func
+ - const: clk_pclk
+ - const: clk_sys_clk
+ - const: clk_wrapper_clk_c
+ - const: clk_dvp_inv
+ - const: clk_axiwr
+ - const: clk_mipi_rx0_pxl
+ - const: clk_pixel_clk_if0
+ - const: clk_pixel_clk_if1
+ - const: clk_pixel_clk_if2
+ - const: clk_pixel_clk_if3
+ - const: clk_m31dphy_cfgclk_in
+ - const: clk_m31dphy_refclk_in
+ - const: clk_m31dphy_txclkesc_lan0
+ - const: clk_ispcore_2x
+ - const: clk_isp_axi
+
+ resets:
+ maxItems: 14
+
+ reset-names:
+ items:
+ - const: rst_wrapper_p
+ - const: rst_wrapper_c
+ - const: rst_pclk
+ - const: rst_sys_clk
+ - const: rst_axird
+ - const: rst_axiwr
+ - const: rst_pixel_clk_if0
+ - const: rst_pixel_clk_if1
+ - const: rst_pixel_clk_if2
+ - const: rst_pixel_clk_if3
+ - const: rst_m31dphy_hw
+ - const: rst_m31dphy_b09_always_on
+ - const: rst_isp_top_n
+ - const: rst_isp_top_axi
+
+ power-domains:
+ items:
+ - description: JH7110 ISP Power Domain Switch Controller.
+
+ interrupts:
+ maxItems: 5
+
+ ports:
+ $ref: /schemas/graph.yaml#/properties/ports
+
+ properties:
+ port@0:
+ $ref: /schemas/graph.yaml#/$defs/port-base
+ unevaluatedProperties: false
+ description: Input port for receiving DVP data.
+
+ properties:
+ endpoint:
+ $ref: video-interfaces.yaml#
+ unevaluatedProperties: false
+
+ properties:
+ bus-type:
+ enum: [5, 6]
+
+ bus-width:
+ enum: [8, 10, 12]
+
+ data-shift:
+ enum: [0, 2]
+ default: 0
+
+ hsync-active:
+ enum: [0, 1]
+ default: 1
+
+ vsync-active:
+ enum: [0, 1]
+ default: 1
+
+ required:
+ - bus-type
+ - bus-width
+
+ port@1:
+ $ref: /schemas/graph.yaml#/properties/port
+ description: Input port for receiving CSI data.
+
+ required:
+ - port@0
+ - port@1
+
+required:
+ - compatible
+ - reg
+ - reg-names
+ - clocks
+ - clock-names
+ - resets
+ - reset-names
+ - power-domains
+ - interrupts
+ - ports
+
+additionalProperties: false
+
+examples:
+ - |
+ vin_sysctl: vin_sysctl@19800000 {
+ compatible = "starfive,jh7110-vin";
+ reg = <0x0 0x19800000 0x0 0x10000>,
+ <0x0 0x19810000 0x0 0x10000>,
+ <0x0 0x19820000 0x0 0x10000>,
+ <0x0 0x19840000 0x0 0x10000>,
+ <0x0 0x19870000 0x0 0x30000>,
+ <0x0 0x11840000 0x0 0x10000>,
+ <0x0 0x17030000 0x0 0x10000>,
+ <0x0 0x13020000 0x0 0x10000>;
+ reg-names = "csi2rx", "vclk", "vrst", "sctrl",
+ "isp", "trst", "pmu", "syscrg";
+ clocks = <&clkisp JH7110_DOM4_APB_FUNC>,
+ <&clkisp JH7110_U0_VIN_PCLK>,
+ <&clkisp JH7110_U0_VIN_SYS_CLK>,
+ <&clkisp JH7110_U0_ISPV2_TOP_WRAPPER_CLK_C>,
+ <&clkisp JH7110_DVP_INV>,
+ <&clkisp JH7110_U0_VIN_CLK_P_AXIWR>,
+ <&clkisp JH7110_MIPI_RX0_PXL>,
+ <&clkisp JH7110_U0_VIN_PIXEL_CLK_IF0>,
+ <&clkisp JH7110_U0_VIN_PIXEL_CLK_IF1>,
+ <&clkisp JH7110_U0_VIN_PIXEL_CLK_IF2>,
+ <&clkisp JH7110_U0_VIN_PIXEL_CLK_IF3>,
+ <&clkisp JH7110_U0_M31DPHY_CFGCLK_IN>,
+ <&clkisp JH7110_U0_M31DPHY_REFCLK_IN>,
+ <&clkisp JH7110_U0_M31DPHY_TXCLKESC_LAN0>,
+ <&clkgen JH7110_ISP_TOP_CLK_ISPCORE_2X>,
+ <&clkgen JH7110_ISP_TOP_CLK_ISP_AXI>;
+ clock-names = "clk_apb_func", "clk_pclk", "clk_sys_clk",
+ "clk_wrapper_clk_c", "clk_dvp_inv", "clk_axiwr",
+ "clk_mipi_rx0_pxl", "clk_pixel_clk_if0",
+ "clk_pixel_clk_if1", "clk_pixel_clk_if2",
+ "clk_pixel_clk_if3", "clk_m31dphy_cfgclk_in",
+ "clk_m31dphy_refclk_in", "clk_m31dphy_txclkesc_lan0",
+ "clk_ispcore_2x", "clk_isp_axi";
+ resets = <&rstgen RSTN_U0_ISPV2_TOP_WRAPPER_P>,
+ <&rstgen RSTN_U0_ISPV2_TOP_WRAPPER_C>,
+ <&rstgen RSTN_U0_VIN_N_PCLK>,
+ <&rstgen RSTN_U0_VIN_N_SYS_CLK>,
+ <&rstgen RSTN_U0_VIN_P_AXIRD>,
+ <&rstgen RSTN_U0_VIN_P_AXIWR>,
+ <&rstgen RSTN_U0_VIN_N_PIXEL_CLK_IF0>,
+ <&rstgen RSTN_U0_VIN_N_PIXEL_CLK_IF1>,
+ <&rstgen RSTN_U0_VIN_N_PIXEL_CLK_IF2>,
+ <&rstgen RSTN_U0_VIN_N_PIXEL_CLK_IF3>,
+ <&rstgen RSTN_U0_M31DPHY_HW>,
+ <&rstgen RSTN_U0_M31DPHY_B09_ALWAYS_ON>,
+ <&rstgen RSTN_U0_DOM_ISP_TOP_N>,
+ <&rstgen RSTN_U0_DOM_ISP_TOP_AXI>;
+ reset-names = "rst_wrapper_p", "rst_wrapper_c", "rst_pclk",
+ "rst_sys_clk", "rst_axird", "rst_axiwr", "rst_pixel_clk_if0",
+ "rst_pixel_clk_if1", "rst_pixel_clk_if2", "rst_pixel_clk_if3",
+ "rst_m31dphy_hw", "rst_m31dphy_b09_always_on",
+ "rst_isp_top_n", "rst_isp_top_axi";
+ starfive,aon-syscon = <&aon_syscon 0x00>;
+ power-domains = <&pwrc JH7110_PD_ISP>;
+ /* irq nr: vin, isp, isp_csi, isp_scd, isp_csiline */
+ interrupts = <92>, <87>, <88>, <89>, <90>;
+
+ ports {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ port@0 {
+ reg = <0>;
+ vin_from_sc2235: endpoint {
+ remote-endpoint = <&sc2235_to_vin>;
+ bus-type = <5>;
+ bus-width = <8>;
+ data-shift = <2>;
+ hsync-active = <1>;
+ vsync-active = <0>;
+ pclk-sample = <1>;
+ };
+ };
+
+ port@1 {
+ reg = <1>;
+ vin_from_csi2rx: endpoint {
+ remote-endpoint = <&csi2rx_to_vin>;
+ };
+ };
+ };
+ };

File diff suppressed because it is too large Load Diff

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