hifiveu: add new target for HiFive Unleashed/Unmatched RISC-V boards riscv-upstream
authorZoltan HERPAI <wigyori@uid0.hu>
Sun, 16 Dec 2018 10:05:58 +0000 (11:05 +0100)
committerZoltan HERPAI <wigyori@uid0.hu>
Sun, 7 Nov 2021 17:16:02 +0000 (18:16 +0100)
RISC-V is a new CPU architecture aimed to be fully free and open. This
target will add support for it, based on 5.10.

Supports running on:
 - HiFive Unleashed - FU540, first generation
 - HiFive Unmatched - FU740, current latest generation, PCIe

SD-card images are generated, where the partitions are required to have
specific type codes. As it is commonplace nowadays, OpenSBI is used as the
first stage, with U-boot following as the proper bootloader.

Specifications:

HiFive Unleashed:
 - CPU: SiFive FU540 quad-core RISC-V (U54, RV64IMAFDC)
 - Memory: 8Gb
 - Ethernet: 1x 10/100/1000
 - Console: via microUSB

HiFive Unmatched:
 - CPU: SiFive FU740 quad-core RISC-V (U74, RV64IMAFDC)
 - Memory: 16Gb
 - Ethernet: 1x 10/100/1000
 - USB: 4x USB 3.2
 - PCIe:  - 1x PCIe Gen3 x8
          - 1x M.2 key M (PCIe x4)
          - 1x M.2 Key E (PCIe x1 / USB2.0)
 - Console: via microUSB

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

Signed-off-by: Zoltan HERPAI <wigyori@uid0.hu>
53 files changed:
target/linux/hifiveu/Makefile [new file with mode: 0644]
target/linux/hifiveu/base-files/etc/board.d/01_leds [new file with mode: 0644]
target/linux/hifiveu/base-files/etc/board.d/02_network [new file with mode: 0644]
target/linux/hifiveu/base-files/etc/inittab [new file with mode: 0644]
target/linux/hifiveu/config-5.10 [new file with mode: 0644]
target/linux/hifiveu/image/Config.in [new file with mode: 0644]
target/linux/hifiveu/image/Makefile [new file with mode: 0644]
target/linux/hifiveu/image/gen_hifiveu_sdcard_img.sh [new file with mode: 0755]
target/linux/hifiveu/patches-5.10/0001-clk-sifive-Extract-prci-core-to-common-base.patch [new file with mode: 0644]
target/linux/hifiveu/patches-5.10/0002-clk-sifive-Use-common-name-for-prci-configuration.patch [new file with mode: 0644]
target/linux/hifiveu/patches-5.10/0003-clk-sifive-Add-a-driver-for-the-SiFive-FU740-PRCI-IP.patch [new file with mode: 0644]
target/linux/hifiveu/patches-5.10/0004-clk-sifive-Fix-the-wrong-bit-field-shift.patch [new file with mode: 0644]
target/linux/hifiveu/patches-5.10/0005-clk-sifive-Add-clock-enable-and-disable-ops.patch [new file with mode: 0644]
target/linux/hifiveu/patches-5.10/0006-dt-bindings-riscv-Update-DT-binding-docs-to-support-.patch [new file with mode: 0644]
target/linux/hifiveu/patches-5.10/0007-dt-bindings-spi-Update-DT-binding-docs-to-support-Si.patch [new file with mode: 0644]
target/linux/hifiveu/patches-5.10/0008-dt-bindings-pwm-Update-DT-binding-docs-to-support-Si.patch [new file with mode: 0644]
target/linux/hifiveu/patches-5.10/0009-dt-bindings-serial-Update-DT-binding-docs-to-support.patch [new file with mode: 0644]
target/linux/hifiveu/patches-5.10/0010-dt-bindings-gpio-Update-DT-binding-docs-to-support-S.patch [new file with mode: 0644]
target/linux/hifiveu/patches-5.10/0011-dt-bindings-i2c-Update-DT-binding-docs-to-support-Si.patch [new file with mode: 0644]
target/linux/hifiveu/patches-5.10/0012-riscv-dts-add-initial-support-for-the-SiFive-FU740-C.patch [new file with mode: 0644]
target/linux/hifiveu/patches-5.10/0013-dt-bindings-riscv-Update-YAML-doc-to-support-SiFive-.patch [new file with mode: 0644]
target/linux/hifiveu/patches-5.10/0014-riscv-dts-add-initial-board-data-for-the-SiFive-HiFi.patch [new file with mode: 0644]
target/linux/hifiveu/patches-5.10/0016-RISC-V-sifive_l2_cache-Update-L2-cache-driver-to-sup.patch [new file with mode: 0644]
target/linux/hifiveu/patches-5.10/0017-gpio-sifive-To-get-gpio-irq-offset-from-device-tree-.patch [new file with mode: 0644]
target/linux/hifiveu/patches-5.10/0018-riscv-Add-3-SBI-wrapper-functions-to-get-cpu-manufac.patch [new file with mode: 0644]
target/linux/hifiveu/patches-5.10/0019-riscv-Get-CPU-manufactory-information.patch [new file with mode: 0644]
target/linux/hifiveu/patches-5.10/0020-riscv-Introduce-alternative-mechanism-to-apply-errat.patch [new file with mode: 0644]
target/linux/hifiveu/patches-5.10/0021-riscv-sifive-apply-errata-cip-453-patch.patch [new file with mode: 0644]
target/linux/hifiveu/patches-5.10/0022-riscv-dts-fu740-fix-cache-controller-interrupts.patch [new file with mode: 0644]
target/linux/hifiveu/patches-5.10/0023-riscv-sifive-fu740-cpu-1-2-3-4-set-compatible-to-sif.patch [new file with mode: 0644]
target/linux/hifiveu/patches-5.10/0024-riscv-dts-Add-PCIe-support-for-the-SiFive-FU740-C000.patch [new file with mode: 0644]
target/linux/hifiveu/patches-5.10/0025-clk-sifive-Add-pcie_aux-clock-in-prci-driver-for-PCI.patch [new file with mode: 0644]
target/linux/hifiveu/patches-5.10/0026-clk-sifive-Use-reset-simple-in-prci-driver-for-PCIe-.patch [new file with mode: 0644]
target/linux/hifiveu/patches-5.10/0027-MAINTAINERS-Add-maintainers-for-SiFive-FU740-PCIe-dr.patch [new file with mode: 0644]
target/linux/hifiveu/patches-5.10/0028-dt-bindings-PCI-Add-SiFive-FU740-PCIe-host-controlle.patch [new file with mode: 0644]
target/linux/hifiveu/patches-5.10/0029-PCI-designware-Add-SiFive-FU740-PCIe-host-controller.patch [new file with mode: 0644]
target/linux/hifiveu/patches-5.10/0030-riscv-enable-generic-PCI-resource-mapping.patch [new file with mode: 0644]
target/linux/hifiveu/patches-5.10/0031-SiFive-Unleashed-CPUFreq.patch [new file with mode: 0644]
target/linux/hifiveu/patches-5.10/0040-riscv-sifive-unmatched-add-D12-PWM-LED.patch [new file with mode: 0644]
target/linux/hifiveu/patches-5.10/0041-riscv-sifive-unmatched-add-gpio-poweroff-node.patch [new file with mode: 0644]
target/linux/hifiveu/patches-5.10/0042-riscv-sifive-unmatched-add-D2-RGB-LED.patch [new file with mode: 0644]
target/linux/hifiveu/patches-5.10/0043-riscv-sifive-unmatched-remove-A00-from-model.patch [new file with mode: 0644]
target/linux/hifiveu/patches-5.10/0044-riscv-sifive-unmatched-define-LEDs-color.patch [new file with mode: 0644]
target/linux/hifiveu/patches-5.10/0045-Add-PWM-LEDs-D1-D2-D3-D4.patch [new file with mode: 0644]
target/linux/hifiveu/patches-5.10/0100-hifiveu-openwrt-led-changes.patch [new file with mode: 0644]
target/linux/hifiveu/patches-5.10/0101-riscv_dts_sifive-unmatched_Expose_the_FU740_regulator.patch [new file with mode: 0644]
target/linux/hifiveu/patches-5.10/0102-riscv_dts_sifive-unmatched_Link_tmp451_with_its_psup.patch [new file with mode: 0644]
target/linux/hifiveu/patches-5.10/0103-riscv_dts_sifive-unmatched_Expose_board_ID_EEPROM.patch [new file with mode: 0644]
target/linux/hifiveu/patches-5.10/0104-riscv_dts_sifive_unmatched-Expose_PMIC_sub-funcs.patch [new file with mode: 0644]
target/linux/hifiveu/patches-5.10/0105-riscv_dts_sifive_unmatched_Expose_fan_PWM.patch [new file with mode: 0644]
target/linux/hifiveu/patches-5.10/0106-mfd_da9063_Add_HWMON_deps.patch [new file with mode: 0644]
target/linux/hifiveu/patches-5.10/0107-hwmon-da9063_HWMON_driver.patch [new file with mode: 0644]
target/linux/hifiveu/profiles/00-default.mk [new file with mode: 0644]

diff --git a/target/linux/hifiveu/Makefile b/target/linux/hifiveu/Makefile
new file mode 100644 (file)
index 0000000..5575f2f
--- /dev/null
@@ -0,0 +1,22 @@
+# SPDX-License-Identifier: GPL-2.0-only
+#
+# Copyright (C) 2021 OpenWrt.org
+#
+include $(TOPDIR)/rules.mk
+
+ARCH:=riscv64
+BOARD:=hifiveu
+BOARDNAME:=SiFive RISC-V boards
+FEATURES:=ext4
+KERNELNAME:=Image dtbs
+MAINTAINER:=Zoltan HERPAI <wigyori@uid0.hu>
+
+KERNEL_PATCHVER:=5.10
+
+include $(INCLUDE_DIR)/target.mk
+
+define Target/Description
+       Build firmware images for the HiFive boards
+endef
+
+$(eval $(call BuildTarget))
diff --git a/target/linux/hifiveu/base-files/etc/board.d/01_leds b/target/linux/hifiveu/base-files/etc/board.d/01_leds
new file mode 100644 (file)
index 0000000..7ba9dfe
--- /dev/null
@@ -0,0 +1,21 @@
+# SPDX-License-Identifier: GPL-2.0-only
+#
+# Copyright (C) 2021 OpenWrt.org
+#
+
+. /lib/functions/uci-defaults.sh
+
+board_config_update
+
+case "$(board_name)" in
+sifive,hifive-unleashed-a00)
+       ucidef_set_led_netdev "lan" "LAN" "green:d3" "eth0"
+       ;;
+sifive,hifive-unmatched-a00)
+       ucidef_set_led_netdev "lan" "LAN" "green:d2" "eth0"
+       ;;
+esac
+
+board_config_flush
+
+exit 0
diff --git a/target/linux/hifiveu/base-files/etc/board.d/02_network b/target/linux/hifiveu/base-files/etc/board.d/02_network
new file mode 100644 (file)
index 0000000..7ef10d0
--- /dev/null
@@ -0,0 +1,18 @@
+# SPDX-License-Identifier: GPL-2.0-only
+#
+# Copyright (C) 2021 OpenWrt.org
+#
+
+. /lib/functions/uci-defaults.sh
+
+board_config_update
+
+case "$(board_name)" in
+*)
+       ucidef_set_interface_lan 'eth0'
+       ;;
+esac
+
+board_config_flush
+
+exit 0
diff --git a/target/linux/hifiveu/base-files/etc/inittab b/target/linux/hifiveu/base-files/etc/inittab
new file mode 100644 (file)
index 0000000..93cb948
--- /dev/null
@@ -0,0 +1,6 @@
+::sysinit:/etc/init.d/rcS S boot
+::shutdown:/etc/init.d/rcS K shutdown
+tts/0::askfirst:/usr/libexec/login.sh
+ttyS0::askfirst:/usr/libexec/login.sh
+ttySIF0::askfirst:/usr/libexec/login.sh
+tty1::askfirst:/usr/libexec/login.sh
diff --git a/target/linux/hifiveu/config-5.10 b/target/linux/hifiveu/config-5.10
new file mode 100644 (file)
index 0000000..306f34b
--- /dev/null
@@ -0,0 +1,346 @@
+CONFIG_64BIT=y
+CONFIG_ARCH_CLOCKSOURCE_INIT=y
+CONFIG_ARCH_DMA_ADDR_T_64BIT=y
+CONFIG_ARCH_MMAP_RND_BITS=18
+CONFIG_ARCH_MMAP_RND_BITS_MAX=24
+CONFIG_ARCH_MMAP_RND_BITS_MIN=18
+CONFIG_ARCH_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_SPARSEMEM_ENABLE=y
+CONFIG_ASN1=y
+CONFIG_ASSOCIATIVE_ARRAY=y
+CONFIG_ASYMMETRIC_KEY_TYPE=y
+CONFIG_ASYMMETRIC_PUBLIC_KEY_SUBTYPE=y
+CONFIG_ASYMMETRIC_TPM_KEY_SUBTYPE=y
+CONFIG_ATA=y
+CONFIG_ATA_VERBOSE_ERROR=y
+CONFIG_BLK_DEV_SD=y
+CONFIG_BLK_MQ_PCI=y
+CONFIG_BLK_MQ_VIRTIO=y
+CONFIG_BLK_SCSI_REQUEST=y
+CONFIG_CAVIUM_PTP=y
+CONFIG_CLKDEV_LOOKUP=y
+CONFIG_CLK_ANALOGBITS_WRPLL_CLN28HPC=y
+CONFIG_CLK_SIFIVE=y
+CONFIG_CLK_SIFIVE_FU540_PRCI=y
+CONFIG_CLONE_BACKWARDS=y
+CONFIG_CLZ_TAB=y
+CONFIG_CMODEL_MEDANY=y
+# CONFIG_CMODEL_MEDLOW is not set
+CONFIG_COMMON_CLK=y
+# CONFIG_COMPAT_32BIT_TIME is not set
+CONFIG_COMPAT_BRK=y
+CONFIG_COREDUMP=y
+CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS=y
+CONFIG_CPU_ISOLATION=y
+CONFIG_CPU_RMAP=y
+CONFIG_CRC16=y
+# CONFIG_CRC32_SARWATE is not set
+CONFIG_CRC32_SLICEBY8=y
+CONFIG_CRC7=y
+CONFIG_CRC_ITU_T=y
+CONFIG_CRYPTO_CRC32C=y
+CONFIG_CRYPTO_DRBG=y
+CONFIG_CRYPTO_DRBG_HMAC=y
+CONFIG_CRYPTO_DRBG_MENU=y
+CONFIG_CRYPTO_ECHAINIV=y
+CONFIG_CRYPTO_GF128MUL=y
+CONFIG_CRYPTO_HASH_INFO=y
+CONFIG_CRYPTO_HMAC=y
+CONFIG_CRYPTO_JITTERENTROPY=y
+CONFIG_CRYPTO_LIB_POLY1305_RSIZE=1
+CONFIG_CRYPTO_LIB_SHA256=y
+CONFIG_CRYPTO_NULL2=y
+CONFIG_CRYPTO_RNG=y
+CONFIG_CRYPTO_RNG2=y
+CONFIG_CRYPTO_RNG_DEFAULT=y
+CONFIG_CRYPTO_RSA=y
+CONFIG_CRYPTO_SHA256=y
+CONFIG_DA9063_WATCHDOG=y
+CONFIG_DEBUG_BUGVERBOSE=y
+CONFIG_DECOMPRESS_GZIP=y
+CONFIG_DEVMEM=y
+CONFIG_DEVTMPFS=y
+CONFIG_DEVTMPFS_MOUNT=y
+CONFIG_DNOTIFY=y
+CONFIG_DTC=y
+CONFIG_EDAC=y
+# CONFIG_EDAC_DEBUG is not set
+CONFIG_EDAC_LEGACY_SYSFS=y
+CONFIG_EDAC_SUPPORT=y
+CONFIG_EDAC_SIFIVE=y
+CONFIG_ELF_CORE=y
+CONFIG_ENABLE_MUST_CHECK=y
+CONFIG_ERRATA_SIFIVE_CIP_453=y
+CONFIG_ERRATA_SIFIVE_CIP_1200=y
+CONFIG_EXT4_FS=y
+CONFIG_FAILOVER=y
+CONFIG_FHANDLE=y
+CONFIG_FIXED_PHY=y
+CONFIG_FIX_EARLYCON_MEM=y
+CONFIG_FPU=y
+CONFIG_FRAME_POINTER=y
+CONFIG_FRAME_WARN=2048
+CONFIG_FS_IOMAP=y
+CONFIG_FS_MBCACHE=y
+CONFIG_FW_LOADER_PAGED_BUF=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_CSUM=y
+CONFIG_GENERIC_EARLY_IOREMAP=y
+CONFIG_GENERIC_GETTIMEOFDAY=y
+CONFIG_GENERIC_IOREMAP=y
+CONFIG_GENERIC_IRQ_MULTI_HANDLER=y
+CONFIG_GENERIC_IRQ_SHOW=y
+CONFIG_GENERIC_MSI_IRQ=y
+CONFIG_GENERIC_MSI_IRQ_DOMAIN=y
+CONFIG_GENERIC_PCI_IOMAP=y
+CONFIG_GENERIC_SCHED_CLOCK=y
+CONFIG_GENERIC_SMP_IDLE_THREAD=y
+CONFIG_GENERIC_STRNCPY_FROM_USER=y
+CONFIG_GENERIC_STRNLEN_USER=y
+CONFIG_GENERIC_TIME_VSYSCALL=y
+CONFIG_GLOB=y
+CONFIG_GOLDFISH=y
+# CONFIG_GOLDFISH_AUDIO is not set
+# CONFIG_GOLDFISH_PIPE is not set
+# CONFIG_GOLDFISH_TTY is not set
+CONFIG_GPIOLIB=y
+CONFIG_GPIO_SIFIVE=y
+CONFIG_HANDLE_DOMAIN_IRQ=y
+CONFIG_HAS_DMA=y
+CONFIG_HAS_IOMEM=y
+CONFIG_HAS_IOPORT_MAP=y
+CONFIG_HID=y
+CONFIG_HID_GENERIC=y
+CONFIG_HOTPLUG_PCI=y
+# CONFIG_HOTPLUG_PCI_CPCI is not set
+CONFIG_HOTPLUG_PCI_PCIE=y
+CONFIG_HOTPLUG_PCI_SHPC=y
+CONFIG_HVC_DRIVER=y
+CONFIG_HVC_RISCV_SBI=y
+CONFIG_HZ=250
+# CONFIG_HZ_100 is not set
+CONFIG_HZ_250=y
+CONFIG_HZ_PERIODIC=y
+CONFIG_I2C=y
+CONFIG_I2C_BOARDINFO=y
+CONFIG_I2C_COMPAT=y
+CONFIG_I2C_HELPER_AUTO=y
+CONFIG_I2C_OCORES=y
+CONFIG_INITRAMFS_SOURCE=""
+CONFIG_INPUT=y
+# CONFIG_INPUT_DA9063_ONKEY is not set
+CONFIG_IO_URING=y
+CONFIG_IRQCHIP=y
+CONFIG_IRQ_DOMAIN=y
+CONFIG_IRQ_DOMAIN_HIERARCHY=y
+CONFIG_IRQ_WORK=y
+CONFIG_JBD2=y
+CONFIG_KALLSYMS=y
+CONFIG_KEYS=y
+# CONFIG_KEYBOARD_GOLDFISH_EVENTS is not set
+CONFIG_LEDS_PWM=y
+CONFIG_LEDS_TRIGGER_DISK=y
+CONFIG_LEGACY_PTYS=y
+CONFIG_LEGACY_PTY_COUNT=256
+CONFIG_LIBFDT=y
+CONFIG_LLD_VERSION=0
+CONFIG_LOCALVERSION_AUTO=y
+CONFIG_LOCK_DEBUGGING_SUPPORT=y
+CONFIG_LOCK_SPIN_ON_OWNER=y
+CONFIG_MACB=y
+# CONFIG_MACB_PCI is not set
+CONFIG_MACB_USE_HWSTAMP=y
+CONFIG_MANDATORY_FILE_LOCKING=y
+CONFIG_MAXPHYSMEM_128GB=y
+CONFIG_MDIO_BUS=y
+CONFIG_MDIO_DEVICE=y
+CONFIG_MDIO_DEVRES=y
+CONFIG_MEMFD_CREATE=y
+CONFIG_MFD_SYSCON=y
+CONFIG_MFD_DA9063=y
+CONFIG_MICROSEMI_PHY=y
+CONFIG_MIGRATION=y
+CONFIG_MMC=y
+CONFIG_MMC_BLOCK=y
+# CONFIG_MMC_GOLDFISH is not set
+CONFIG_MMC_SPI=y
+CONFIG_MMIOWB=y
+CONFIG_MODULES_USE_ELF_RELA=y
+CONFIG_MODULE_SECTIONS=y
+CONFIG_MPILIB=y
+CONFIG_MQ_IOSCHED_DEADLINE=y
+CONFIG_MQ_IOSCHED_KYBER=y
+CONFIG_MTD_SPI_NOR=y
+CONFIG_MTD_SPI_NOR_USE_4K_SECTORS=y
+CONFIG_MUTEX_SPIN_ON_OWNER=y
+CONFIG_NAMESPACES=y
+CONFIG_NEED_DMA_MAP_STATE=y
+CONFIG_NET_FAILOVER=y
+CONFIG_NET_FLOW_LIMIT=y
+CONFIG_NET_NS=y
+CONFIG_NET_PTP_CLASSIFY=y
+CONFIG_NLS=y
+CONFIG_NR_CPUS=8
+CONFIG_NVMEM=y
+CONFIG_NVMEM_SYSFS=y
+CONFIG_OF=y
+CONFIG_OF_ADDRESS=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_NET=y
+CONFIG_OID_REGISTRY=y
+CONFIG_PADATA=y
+CONFIG_PAGE_OFFSET=0xffffffe000000000
+CONFIG_PANIC_TIMEOUT=0
+CONFIG_PA_BITS=56
+CONFIG_PCI=y
+CONFIG_PCI_DEBUG=y
+CONFIG_PCI_DOMAINS=y
+CONFIG_PCI_DOMAINS_GENERIC=y
+CONFIG_PCI_ECAM=y
+CONFIG_PCI_HOST_COMMON=y
+CONFIG_PCI_HOST_GENERIC=y
+CONFIG_PCI_MSI=y
+CONFIG_PCI_MSI_IRQ_DOMAIN=y
+CONFIG_PCI_SW_SWITCHTEC=y
+CONFIG_PCIEPORTBUS=y
+CONFIG_PCIEAER=y
+CONFIG_PCIEAER_INJECT=m
+CONFIG_PCIE_ECRC=y
+CONFIG_PCIEASPM=y
+CONFIG_PCIEASPM_DEFAULT=y
+# CONFIG_PCIEASPM_POWERSAVE is not set
+# CONFIG_PCIEASPM_POWER_SUPERSAVE is not set
+# CONFIG_PCIEASPM_PERFORMANCE is not set
+CONFIG_PCIE_PME=y
+CONFIG_PCIE_DPC=y
+CONFIG_PCIE_PTM=y
+# CONFIG_PCIE_BW is not set
+CONFIG_PCIE_EDR=y
+CONFIG_PCIE_FU740=y
+CONFIG_PCIE_XILINX=y
+CONFIG_PGTABLE_LEVELS=3
+CONFIG_PHYLIB=y
+CONFIG_PHYLINK=y
+CONFIG_PHYS_ADDR_T_64BIT=y
+CONFIG_PID_NS=y
+CONFIG_PKCS7_MESSAGE_PARSER=y
+# CONFIG_PKCS8_PRIVATE_KEY_PARSER is not set
+CONFIG_POWER_RESET=y
+CONFIG_POWER_RESET_RESTART=y
+CONFIG_POWER_RESET_GPIO=y
+CONFIG_POWER_RESET_GPIO_RESTART=y
+CONFIG_POWER_RESET_SYSCON=y
+CONFIG_POWER_RESET_SYSCON_POWEROFF=y
+CONFIG_PPS=y
+CONFIG_PRINTK_TIME=y
+CONFIG_PTP_1588_CLOCK=y
+CONFIG_PWM=y
+CONFIG_PWM_SIFIVE=y
+CONFIG_PWM_SYSFS=y
+CONFIG_R8169=y
+CONFIG_RATIONAL=y
+CONFIG_RCU_TRACE=y
+CONFIG_RD_GZIP=y
+CONFIG_REALTEK_PHY=y
+CONFIG_REGMAP=y
+CONFIG_REGMAP_MMIO=y
+CONFIG_RFS_ACCEL=y
+CONFIG_RISCV=y
+CONFIG_RISCV_ERRATA_ALTERNATIVE=y
+CONFIG_RISCV_INTC=y
+CONFIG_RISCV_ISA_C=y
+CONFIG_RISCV_SBI=y
+CONFIG_RISCV_SBI_V01=y
+CONFIG_RISCV_TIMER=y
+CONFIG_RPS=y
+CONFIG_RTC_CLASS=y
+CONFIG_RTC_DRV_DA9063=y
+CONFIG_RTC_DRV_GOLDFISH=y
+CONFIG_RTC_I2C_AND_SPI=y
+CONFIG_RWSEM_SPIN_ON_OWNER=y
+CONFIG_SCHED_DEBUG=y
+CONFIG_SCSI=y
+CONFIG_SENSORS_DA9063=y
+CONFIG_SERIAL_8250_DEPRECATED_OPTIONS=y
+CONFIG_SERIAL_8250_NR_UARTS=4
+CONFIG_SERIAL_8250_RUNTIME_UARTS=4
+CONFIG_SERIAL_EARLYCON_RISCV_SBI=y
+CONFIG_SERIAL_MCTRL_GPIO=y
+CONFIG_SERIAL_OF_PLATFORM=y
+CONFIG_SERIAL_SIFIVE=y
+CONFIG_SERIAL_SIFIVE_CONSOLE=y
+CONFIG_SERIO=y
+CONFIG_SERIO_SERPORT=y
+CONFIG_SG_POOL=y
+CONFIG_SIFIVE_L2=y
+CONFIG_SIFIVE_PLIC=y
+CONFIG_SLUB_DEBUG=y
+CONFIG_SMP=y
+CONFIG_SOC_SIFIVE=y
+CONFIG_SOC_VIRT=y
+CONFIG_SPARSEMEM_VMEMMAP_ENABLE=y
+CONFIG_SPARSE_IRQ=y
+CONFIG_SPI=y
+CONFIG_SPI_BITBANG=y
+CONFIG_SPI_MASTER=y
+CONFIG_SPI_MEM=y
+CONFIG_SPI_SIFIVE=y
+CONFIG_SRCU=y
+CONFIG_STACKTRACE=y
+CONFIG_SWIOTLB=y
+CONFIG_SWPHY=y
+CONFIG_SYSCTL_EXCEPTION_TRACE=y
+CONFIG_SYSFS_SYSCALL=y
+CONFIG_SYS_SUPPORTS_HUGETLBFS=y
+CONFIG_THREAD_INFO_IN_TASK=y
+CONFIG_TICK_CPU_ACCOUNTING=y
+CONFIG_TIMER_OF=y
+CONFIG_TIMER_PROBE=y
+# CONFIG_TPM_KEY_PARSER is not set
+CONFIG_TRACE_CLOCK=y
+CONFIG_TREE_RCU=y
+CONFIG_TREE_SRCU=y
+CONFIG_TUNE_GENERIC=y
+CONFIG_UEVENT_HELPER_PATH=""
+CONFIG_USB=y
+CONFIG_USB_COMMON=y
+CONFIG_USB_EHCI_HCD=y
+# CONFIG_USB_EHCI_HCD_PLATFORM is not set
+CONFIG_USB_EHCI_PCI=y
+CONFIG_USB_HID=y
+CONFIG_USB_NET_DRIVERS=y
+CONFIG_USB_PCI=y
+CONFIG_USB_STORAGE=y
+CONFIG_USB_SUPPORT=y
+# CONFIG_USB_UHCI_HCD is not set
+CONFIG_USB_XHCI_HCD=y
+CONFIG_USB_XHCI_PCI=y
+# CONFIG_USB_XHCI_PLATFORM is not set
+# CONFIG_USER_NS is not set
+CONFIG_UTS_NS=y
+CONFIG_VA_BITS=39
+CONFIG_VGA_ARB=y
+CONFIG_VGA_ARB_MAX_GPUS=16
+CONFIG_VIRTIO=y
+CONFIG_VIRTIO_BLK=y
+CONFIG_VIRTIO_CONSOLE=y
+CONFIG_VIRTIO_MMIO=y
+CONFIG_VIRTIO_NET=y
+CONFIG_VM_EVENT_COUNTERS=y
+CONFIG_X509_CERTIFICATE_PARSER=y
+CONFIG_XPS=y
+CONFIG_ZLIB_INFLATE=y
+CONFIG_ZONE_DMA32=y
diff --git a/target/linux/hifiveu/image/Config.in b/target/linux/hifiveu/image/Config.in
new file mode 100644 (file)
index 0000000..2488a52
--- /dev/null
@@ -0,0 +1,5 @@
+config HIFIVEU_SD_BOOT_PARTSIZE
+       int "Boot (SD Card) filesystem partition size (in MB)"
+       depends on TARGET_hifiveu
+       default 32
+
diff --git a/target/linux/hifiveu/image/Makefile b/target/linux/hifiveu/image/Makefile
new file mode 100644 (file)
index 0000000..430cff3
--- /dev/null
@@ -0,0 +1,70 @@
+# SPDX-License-Identifier: GPL-2.0-only
+#
+# Copyright (C) 2021 OpenWrt.org
+#
+include $(TOPDIR)/rules.mk
+include $(INCLUDE_DIR)/image.mk
+
+FAT32_BLOCK_SIZE=1024
+FAT32_BLOCKS=$(shell echo $$(($(CONFIG_HIFIVEU_SD_BOOT_PARTSIZE)*1024*1024/$(FAT32_BLOCK_SIZE))))
+
+KERNEL_LOADADDR:=0x80200000
+
+define Build/riscv-sdcard
+       rm -f $@.boot #$(KDIR_TMP)/$(IMG_PREFIX)-$(PROFILE)-boot.img
+       mkfs.fat $@.boot  -C $(FAT32_BLOCKS)
+
+       mcopy -i $@.boot $(STAGING_DIR_IMAGE)/$(DEVICE_NAME)-boot.scr ::boot.scr
+       mcopy -i $@.boot $(DTS_DIR)/$(DEVICE_DTS).dtb ::dtb
+       mcopy -i $@.boot $(IMAGE_KERNEL) ::uImage
+
+       ./gen_hifiveu_sdcard_img.sh \
+               $@ \
+               $@.boot \
+               $(IMAGE_ROOTFS) \
+               $(CONFIG_HIFIVEU_SD_BOOT_PARTSIZE) \
+               $(CONFIG_TARGET_ROOTFS_PARTSIZE) \
+               $(STAGING_DIR_IMAGE)/$(DEVICE_NAME)-u-boot.itb \
+               $(STAGING_DIR_IMAGE)/$(DEVICE_NAME)-u-boot.itb-spl
+endef
+
+define Device/Default
+  PROFILES := Default
+  KERNEL_NAME := Image
+  KERNEL := kernel-bin | uImage none -a $(KERNEL_LOADADDR)
+  IMAGES := sdcard.img.gz
+  IMAGE/sdcard.img.gz := riscv-sdcard | append-metadata | gzip
+endef
+
+define Device/FitImageGzip
+       KERNEL_SUFFIX := -fit-uImage.itb
+       KERNEL = kernel-bin | gzip | fit gzip $$(DTS_DIR)/$$(DEVICE_DTS).dtb
+       KERNEL_NAME := Image
+endef
+
+define Device/FitImage
+       KERNEL_SUFFIX := -fit-uImage.itb
+       KERNEL = kernel-bin | fit none $$(DTS_DIR)/$$(DEVICE_DTS).dtb
+       KERNEL_NAME := Image
+endef
+
+define Device/sifive_unleashed
+  $(call Device/FitImage)
+  DEVICE_VENDOR := SiFive
+  DEVICE_MODEL := Unleashed (FU540)
+  DEVICE_DTS := sifive/hifive-unleashed-a00
+  UBOOT := sifive_unleashed
+endef
+TARGET_DEVICES += sifive_unleashed
+
+define Device/sifive_unmatched
+  $(call Device/FitImage)
+  DEVICE_VENDOR := SiFive
+  DEVICE_MODEL := Unmatched (FU740)
+  DEVICE_DTS := sifive/hifive-unmatched-a00
+  DEVICE_PACKAGES += kmod-eeprom-at24 kmod-hwmon-lm90
+  UBOOT := sifive_unmatched
+endef
+TARGET_DEVICES += sifive_unmatched
+
+$(eval $(call BuildImage))
diff --git a/target/linux/hifiveu/image/gen_hifiveu_sdcard_img.sh b/target/linux/hifiveu/image/gen_hifiveu_sdcard_img.sh
new file mode 100755 (executable)
index 0000000..047a6da
--- /dev/null
@@ -0,0 +1,50 @@
+#!/usr/bin/env bash
+# SPDX-License-Identifier: GPL-2.0-only
+#
+# Copyright (C) 2021 OpenWrt.org
+#
+
+set -ex
+[ $# -eq 7 ] || {
+    echo "SYNTAX: $0 <file> <bbl/sbl image> <rootfs image> <bbl/sbl size> <rootfs size> <u-boot ITB image> <u-boot SPL>"
+    exit 1
+}
+
+SPL_UUID="5B193300-FC78-40CD-8002-E86C45580B47"
+UBOOT_UUID="2E54B353-1271-4842-806F-E436D6AF6985"
+BOOT_UUID="EF00"
+LINUX_UUID="0FC63DAF-8483-4772-8E79-3D69D8477DE4"
+
+#BBL_SIZE=4
+OUTPUT="$1"
+BOOTFS="$2"
+ROOTFS="$3"
+BOOTFSSIZE="$4"
+ROOTFSSIZE="$5"
+UBOOT="$6"
+UBOOT_SPL="$7"
+
+FULLSIZE="$(($BOOTFSSIZE+$ROOTFSSIZE+6))"
+#echo "Full size is: ${FULLSIZE}M"
+
+BOOTFSOFFSET="$(($BOOTFSSIZE * 1048576 / 512 + 10274))"
+BOOTFSEND="$(( ($BBL_SIZE+$BOOTFSSIZE) * 1048576 / 512 + 10274 ))"
+echo "Bootfs is: $BOOTFSOFFSET - $BOOTFSEND"
+
+ROOTFSOFFSET="$((($BOOTFSSIZE) * 1048576 / 512 + 10274 + 2 ))"
+ROOTFSEND="$((($BOOTFSSIZE+$ROOTFSSIZE) * 1048576 / 512 + 10274 + 2))"
+echo "Rootfs is: $ROOTFSOFFSET - $ROOTFSEND"
+
+dd if=/dev/zero of=$OUTPUT bs=1M count=$FULLSIZE
+
+sgdisk --clear \
+    --set-alignment=2 \
+    --new=1:34:2081            --change-name=1:loader1 --typecode=1:${SPL_UUID} \
+    --new=2:2082:10273         --change-name=2:loader2 --typecode=2:${UBOOT_UUID} \
+    --new=3:10274:${BOOTFSEND} --change-name=3:boot    --typecode=3:${BOOT_UUID} \
+    --new=4:${ROOTFSOFFSET}:${ROOTFSEND}       --change-name=4:rootfs  --typecode=4:${LINUX_UUID} $OUTPUT
+
+dd bs=512 if="$UBOOT_SPL" of="$OUTPUT" seek=34 conv=notrunc
+dd bs=512 if="$UBOOT" of="$OUTPUT" seek=2082 conv=notrunc
+dd bs=512 if="$BOOTFS" of="$OUTPUT" seek=10274 conv=notrunc
+dd bs=512 if="$ROOTFS" of="$OUTPUT" seek=${ROOTFSOFFSET} conv=notrunc
diff --git a/target/linux/hifiveu/patches-5.10/0001-clk-sifive-Extract-prci-core-to-common-base.patch b/target/linux/hifiveu/patches-5.10/0001-clk-sifive-Extract-prci-core-to-common-base.patch
new file mode 100644 (file)
index 0000000..bbfc25d
--- /dev/null
@@ -0,0 +1,1306 @@
+From fe033b899ca3461c0439d6cd775476ae7595e327 Mon Sep 17 00:00:00 2001
+From: Zong Li <zong.li@sifive.com>
+Date: Wed, 9 Dec 2020 17:49:12 +0800
+Subject: [PATCH 01/29] clk: sifive: Extract prci core to common base
+
+Extract common core of prci driver to an independent file, it could
+allow other chips to reuse it. Separate SoCs-dependent code 'fu540'
+from prci core, then we can easily add 'fu740' later.
+
+Almost these changes are code movement. The different is adding the
+private data for each SoC use, so it needs to get match data in probe
+callback function, then use the data for initialization.
+
+Signed-off-by: Zong Li <zong.li@sifive.com>
+Reviewed-by: Pragnesh Patel <Pragnesh.patel@sifive.com>
+Acked-by: Palmer Dabbelt <palmerdabbelt@google.com>
+---
+ drivers/clk/sifive/Makefile      |   2 +-
+ drivers/clk/sifive/fu540-prci.c  | 592 ++-------------------------------------
+ drivers/clk/sifive/fu540-prci.h  |  21 ++
+ drivers/clk/sifive/sifive-prci.c | 395 ++++++++++++++++++++++++++
+ drivers/clk/sifive/sifive-prci.h | 201 +++++++++++++
+ 5 files changed, 639 insertions(+), 572 deletions(-)
+ create mode 100644 drivers/clk/sifive/fu540-prci.h
+ create mode 100644 drivers/clk/sifive/sifive-prci.c
+ create mode 100644 drivers/clk/sifive/sifive-prci.h
+
+diff --git a/drivers/clk/sifive/Makefile b/drivers/clk/sifive/Makefile
+index 0797f14..51b6ebc 100644
+--- a/drivers/clk/sifive/Makefile
++++ b/drivers/clk/sifive/Makefile
+@@ -1,2 +1,2 @@
+ # SPDX-License-Identifier: GPL-2.0-only
+-obj-$(CONFIG_CLK_SIFIVE_FU540_PRCI)   += fu540-prci.o
++obj-$(CONFIG_CLK_SIFIVE_FU540_PRCI)   += sifive-prci.o fu540-prci.o
+diff --git a/drivers/clk/sifive/fu540-prci.c b/drivers/clk/sifive/fu540-prci.c
+index a8901f9..e2353de 100644
+--- a/drivers/clk/sifive/fu540-prci.c
++++ b/drivers/clk/sifive/fu540-prci.c
+@@ -1,17 +1,9 @@
+ // SPDX-License-Identifier: GPL-2.0
+ /*
+  * Copyright (C) 2018-2019 SiFive, Inc.
+- * Wesley Terpstra
+- * Paul Walmsley
+- *
+- * This program is free software; you can redistribute it and/or modify
+- * it under the terms of the GNU General Public License version 2 as
+- * published by the Free Software Foundation.
+- *
+- * 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.
++ * Copyright (C) 2018-2019 Wesley Terpstra
++ * Copyright (C) 2018-2019 Paul Walmsley
++ * Copyright (C) 2020 Zong Li
+  *
+  * The FU540 PRCI implements clock and reset control for the SiFive
+  * FU540-C000 chip.  This driver assumes that it has sole control
+@@ -25,463 +17,43 @@
+  */
+ #include <dt-bindings/clock/sifive-fu540-prci.h>
+-#include <linux/clkdev.h>
+-#include <linux/clk-provider.h>
+-#include <linux/clk/analogbits-wrpll-cln28hpc.h>
+-#include <linux/delay.h>
+-#include <linux/err.h>
+-#include <linux/io.h>
+ #include <linux/module.h>
+-#include <linux/of.h>
+-#include <linux/of_clk.h>
+-#include <linux/platform_device.h>
+-#include <linux/slab.h>
+-
+-/*
+- * EXPECTED_CLK_PARENT_COUNT: how many parent clocks this driver expects:
+- *     hfclk and rtcclk
+- */
+-#define EXPECTED_CLK_PARENT_COUNT             2
+-
+-/*
+- * Register offsets and bitmasks
+- */
+-
+-/* COREPLLCFG0 */
+-#define PRCI_COREPLLCFG0_OFFSET                       0x4
+-# define PRCI_COREPLLCFG0_DIVR_SHIFT          0
+-# define PRCI_COREPLLCFG0_DIVR_MASK           (0x3f << PRCI_COREPLLCFG0_DIVR_SHIFT)
+-# define PRCI_COREPLLCFG0_DIVF_SHIFT          6
+-# define PRCI_COREPLLCFG0_DIVF_MASK           (0x1ff << PRCI_COREPLLCFG0_DIVF_SHIFT)
+-# define PRCI_COREPLLCFG0_DIVQ_SHIFT          15
+-# define PRCI_COREPLLCFG0_DIVQ_MASK           (0x7 << PRCI_COREPLLCFG0_DIVQ_SHIFT)
+-# define PRCI_COREPLLCFG0_RANGE_SHIFT         18
+-# define PRCI_COREPLLCFG0_RANGE_MASK          (0x7 << PRCI_COREPLLCFG0_RANGE_SHIFT)
+-# define PRCI_COREPLLCFG0_BYPASS_SHIFT                24
+-# define PRCI_COREPLLCFG0_BYPASS_MASK         (0x1 << PRCI_COREPLLCFG0_BYPASS_SHIFT)
+-# define PRCI_COREPLLCFG0_FSE_SHIFT           25
+-# define PRCI_COREPLLCFG0_FSE_MASK            (0x1 << PRCI_COREPLLCFG0_FSE_SHIFT)
+-# define PRCI_COREPLLCFG0_LOCK_SHIFT          31
+-# define PRCI_COREPLLCFG0_LOCK_MASK           (0x1 << PRCI_COREPLLCFG0_LOCK_SHIFT)
+-
+-/* DDRPLLCFG0 */
+-#define PRCI_DDRPLLCFG0_OFFSET                        0xc
+-# define PRCI_DDRPLLCFG0_DIVR_SHIFT           0
+-# define PRCI_DDRPLLCFG0_DIVR_MASK            (0x3f << PRCI_DDRPLLCFG0_DIVR_SHIFT)
+-# define PRCI_DDRPLLCFG0_DIVF_SHIFT           6
+-# define PRCI_DDRPLLCFG0_DIVF_MASK            (0x1ff << PRCI_DDRPLLCFG0_DIVF_SHIFT)
+-# define PRCI_DDRPLLCFG0_DIVQ_SHIFT           15
+-# define PRCI_DDRPLLCFG0_DIVQ_MASK            (0x7 << PRCI_DDRPLLCFG0_DIVQ_SHIFT)
+-# define PRCI_DDRPLLCFG0_RANGE_SHIFT          18
+-# define PRCI_DDRPLLCFG0_RANGE_MASK           (0x7 << PRCI_DDRPLLCFG0_RANGE_SHIFT)
+-# define PRCI_DDRPLLCFG0_BYPASS_SHIFT         24
+-# define PRCI_DDRPLLCFG0_BYPASS_MASK          (0x1 << PRCI_DDRPLLCFG0_BYPASS_SHIFT)
+-# define PRCI_DDRPLLCFG0_FSE_SHIFT            25
+-# define PRCI_DDRPLLCFG0_FSE_MASK             (0x1 << PRCI_DDRPLLCFG0_FSE_SHIFT)
+-# define PRCI_DDRPLLCFG0_LOCK_SHIFT           31
+-# define PRCI_DDRPLLCFG0_LOCK_MASK            (0x1 << PRCI_DDRPLLCFG0_LOCK_SHIFT)
++#include "sifive-prci.h"
+-/* DDRPLLCFG1 */
+-#define PRCI_DDRPLLCFG1_OFFSET                        0x10
+-# define PRCI_DDRPLLCFG1_CKE_SHIFT            24
+-# define PRCI_DDRPLLCFG1_CKE_MASK             (0x1 << PRCI_DDRPLLCFG1_CKE_SHIFT)
++/* PRCI integration data for each WRPLL instance */
+-/* GEMGXLPLLCFG0 */
+-#define PRCI_GEMGXLPLLCFG0_OFFSET             0x1c
+-# define PRCI_GEMGXLPLLCFG0_DIVR_SHIFT                0
+-# define PRCI_GEMGXLPLLCFG0_DIVR_MASK         (0x3f << PRCI_GEMGXLPLLCFG0_DIVR_SHIFT)
+-# define PRCI_GEMGXLPLLCFG0_DIVF_SHIFT                6
+-# define PRCI_GEMGXLPLLCFG0_DIVF_MASK         (0x1ff << PRCI_GEMGXLPLLCFG0_DIVF_SHIFT)
+-# define PRCI_GEMGXLPLLCFG0_DIVQ_SHIFT                15
+-# define PRCI_GEMGXLPLLCFG0_DIVQ_MASK         (0x7 << PRCI_GEMGXLPLLCFG0_DIVQ_SHIFT)
+-# define PRCI_GEMGXLPLLCFG0_RANGE_SHIFT               18
+-# define PRCI_GEMGXLPLLCFG0_RANGE_MASK                (0x7 << PRCI_GEMGXLPLLCFG0_RANGE_SHIFT)
+-# define PRCI_GEMGXLPLLCFG0_BYPASS_SHIFT      24
+-# define PRCI_GEMGXLPLLCFG0_BYPASS_MASK               (0x1 << PRCI_GEMGXLPLLCFG0_BYPASS_SHIFT)
+-# define PRCI_GEMGXLPLLCFG0_FSE_SHIFT         25
+-# define PRCI_GEMGXLPLLCFG0_FSE_MASK          (0x1 << PRCI_GEMGXLPLLCFG0_FSE_SHIFT)
+-# define PRCI_GEMGXLPLLCFG0_LOCK_SHIFT                31
+-# define PRCI_GEMGXLPLLCFG0_LOCK_MASK         (0x1 << PRCI_GEMGXLPLLCFG0_LOCK_SHIFT)
+-
+-/* GEMGXLPLLCFG1 */
+-#define PRCI_GEMGXLPLLCFG1_OFFSET             0x20
+-# define PRCI_GEMGXLPLLCFG1_CKE_SHIFT         24
+-# define PRCI_GEMGXLPLLCFG1_CKE_MASK          (0x1 << PRCI_GEMGXLPLLCFG1_CKE_SHIFT)
+-
+-/* CORECLKSEL */
+-#define PRCI_CORECLKSEL_OFFSET                        0x24
+-# define PRCI_CORECLKSEL_CORECLKSEL_SHIFT     0
+-# define PRCI_CORECLKSEL_CORECLKSEL_MASK      (0x1 << PRCI_CORECLKSEL_CORECLKSEL_SHIFT)
+-
+-/* DEVICESRESETREG */
+-#define PRCI_DEVICESRESETREG_OFFSET                   0x28
+-# define PRCI_DEVICESRESETREG_DDR_CTRL_RST_N_SHIFT    0
+-# define PRCI_DEVICESRESETREG_DDR_CTRL_RST_N_MASK     (0x1 << PRCI_DEVICESRESETREG_DDR_CTRL_RST_N_SHIFT)
+-# define PRCI_DEVICESRESETREG_DDR_AXI_RST_N_SHIFT     1
+-# define PRCI_DEVICESRESETREG_DDR_AXI_RST_N_MASK      (0x1 << PRCI_DEVICESRESETREG_DDR_AXI_RST_N_SHIFT)
+-# define PRCI_DEVICESRESETREG_DDR_AHB_RST_N_SHIFT     2
+-# define PRCI_DEVICESRESETREG_DDR_AHB_RST_N_MASK      (0x1 << PRCI_DEVICESRESETREG_DDR_AHB_RST_N_SHIFT)
+-# define PRCI_DEVICESRESETREG_DDR_PHY_RST_N_SHIFT     3
+-# define PRCI_DEVICESRESETREG_DDR_PHY_RST_N_MASK      (0x1 << PRCI_DEVICESRESETREG_DDR_PHY_RST_N_SHIFT)
+-# define PRCI_DEVICESRESETREG_GEMGXL_RST_N_SHIFT      5
+-# define PRCI_DEVICESRESETREG_GEMGXL_RST_N_MASK               (0x1 << PRCI_DEVICESRESETREG_GEMGXL_RST_N_SHIFT)
+-
+-/* CLKMUXSTATUSREG */
+-#define PRCI_CLKMUXSTATUSREG_OFFSET                   0x2c
+-# define PRCI_CLKMUXSTATUSREG_TLCLKSEL_STATUS_SHIFT   1
+-# define PRCI_CLKMUXSTATUSREG_TLCLKSEL_STATUS_MASK    (0x1 << PRCI_CLKMUXSTATUSREG_TLCLKSEL_STATUS_SHIFT)
+-
+-/*
+- * Private structures
+- */
+-
+-/**
+- * struct __prci_data - per-device-instance data
+- * @va: base virtual address of the PRCI IP block
+- * @hw_clks: encapsulates struct clk_hw records
+- *
+- * PRCI per-device instance data
+- */
+-struct __prci_data {
+-      void __iomem *va;
+-      struct clk_hw_onecell_data hw_clks;
++static struct __prci_wrpll_data __prci_corepll_data = {
++      .cfg0_offs = PRCI_COREPLLCFG0_OFFSET,
++      .enable_bypass = sifive_prci_coreclksel_use_hfclk,
++      .disable_bypass = sifive_prci_coreclksel_use_corepll,
+ };
+-/**
+- * struct __prci_wrpll_data - WRPLL configuration and integration data
+- * @c: WRPLL current configuration record
+- * @enable_bypass: fn ptr to code to bypass the WRPLL (if applicable; else NULL)
+- * @disable_bypass: fn ptr to code to not bypass the WRPLL (or NULL)
+- * @cfg0_offs: WRPLL CFG0 register offset (in bytes) from the PRCI base address
+- *
+- * @enable_bypass and @disable_bypass are used for WRPLL instances
+- * that contain a separate external glitchless clock mux downstream
+- * from the PLL.  The WRPLL internal bypass mux is not glitchless.
+- */
+-struct __prci_wrpll_data {
+-      struct wrpll_cfg c;
+-      void (*enable_bypass)(struct __prci_data *pd);
+-      void (*disable_bypass)(struct __prci_data *pd);
+-      u8 cfg0_offs;
++static struct __prci_wrpll_data __prci_ddrpll_data = {
++      .cfg0_offs = PRCI_DDRPLLCFG0_OFFSET,
+ };
+-/**
+- * struct __prci_clock - describes a clock device managed by PRCI
+- * @name: user-readable clock name string - should match the manual
+- * @parent_name: parent name for this clock
+- * @ops: struct clk_ops for the Linux clock framework to use for control
+- * @hw: Linux-private clock data
+- * @pwd: WRPLL-specific data, associated with this clock (if not NULL)
+- * @pd: PRCI-specific data associated with this clock (if not NULL)
+- *
+- * PRCI clock data.  Used by the PRCI driver to register PRCI-provided
+- * clocks to the Linux clock infrastructure.
+- */
+-struct __prci_clock {
+-      const char *name;
+-      const char *parent_name;
+-      const struct clk_ops *ops;
+-      struct clk_hw hw;
+-      struct __prci_wrpll_data *pwd;
+-      struct __prci_data *pd;
++static struct __prci_wrpll_data __prci_gemgxlpll_data = {
++      .cfg0_offs = PRCI_GEMGXLPLLCFG0_OFFSET,
+ };
+-#define clk_hw_to_prci_clock(pwd) container_of(pwd, struct __prci_clock, hw)
+-
+-/*
+- * Private functions
+- */
+-
+-/**
+- * __prci_readl() - read from a PRCI register
+- * @pd: PRCI context
+- * @offs: register offset to read from (in bytes, from PRCI base address)
+- *
+- * Read the register located at offset @offs from the base virtual
+- * address of the PRCI register target described by @pd, and return
+- * the value to the caller.
+- *
+- * Context: Any context.
+- *
+- * Return: the contents of the register described by @pd and @offs.
+- */
+-static u32 __prci_readl(struct __prci_data *pd, u32 offs)
+-{
+-      return readl_relaxed(pd->va + offs);
+-}
+-
+-static void __prci_writel(u32 v, u32 offs, struct __prci_data *pd)
+-{
+-      writel_relaxed(v, pd->va + offs);
+-}
+-
+-/* WRPLL-related private functions */
+-
+-/**
+- * __prci_wrpll_unpack() - unpack WRPLL configuration registers into parameters
+- * @c: ptr to a struct wrpll_cfg record to write config into
+- * @r: value read from the PRCI PLL configuration register
+- *
+- * Given a value @r read from an FU540 PRCI PLL configuration register,
+- * split it into fields and populate it into the WRPLL configuration record
+- * pointed to by @c.
+- *
+- * The COREPLLCFG0 macros are used below, but the other *PLLCFG0 macros
+- * have the same register layout.
+- *
+- * Context: Any context.
+- */
+-static void __prci_wrpll_unpack(struct wrpll_cfg *c, u32 r)
+-{
+-      u32 v;
+-
+-      v = r & PRCI_COREPLLCFG0_DIVR_MASK;
+-      v >>= PRCI_COREPLLCFG0_DIVR_SHIFT;
+-      c->divr = v;
+-
+-      v = r & PRCI_COREPLLCFG0_DIVF_MASK;
+-      v >>= PRCI_COREPLLCFG0_DIVF_SHIFT;
+-      c->divf = v;
+-
+-      v = r & PRCI_COREPLLCFG0_DIVQ_MASK;
+-      v >>= PRCI_COREPLLCFG0_DIVQ_SHIFT;
+-      c->divq = v;
+-
+-      v = r & PRCI_COREPLLCFG0_RANGE_MASK;
+-      v >>= PRCI_COREPLLCFG0_RANGE_SHIFT;
+-      c->range = v;
+-
+-      c->flags &= (WRPLL_FLAGS_INT_FEEDBACK_MASK |
+-                   WRPLL_FLAGS_EXT_FEEDBACK_MASK);
+-
+-      /* external feedback mode not supported */
+-      c->flags |= WRPLL_FLAGS_INT_FEEDBACK_MASK;
+-}
+-
+-/**
+- * __prci_wrpll_pack() - pack PLL configuration parameters into a register value
+- * @c: pointer to a struct wrpll_cfg record containing the PLL's cfg
+- *
+- * Using a set of WRPLL configuration values pointed to by @c,
+- * assemble a PRCI PLL configuration register value, and return it to
+- * the caller.
+- *
+- * Context: Any context.  Caller must ensure that the contents of the
+- *          record pointed to by @c do not change during the execution
+- *          of this function.
+- *
+- * Returns: a value suitable for writing into a PRCI PLL configuration
+- *          register
+- */
+-static u32 __prci_wrpll_pack(const struct wrpll_cfg *c)
+-{
+-      u32 r = 0;
+-
+-      r |= c->divr << PRCI_COREPLLCFG0_DIVR_SHIFT;
+-      r |= c->divf << PRCI_COREPLLCFG0_DIVF_SHIFT;
+-      r |= c->divq << PRCI_COREPLLCFG0_DIVQ_SHIFT;
+-      r |= c->range << PRCI_COREPLLCFG0_RANGE_SHIFT;
+-
+-      /* external feedback mode not supported */
+-      r |= PRCI_COREPLLCFG0_FSE_MASK;
+-
+-      return r;
+-}
+-
+-/**
+- * __prci_wrpll_read_cfg() - read the WRPLL configuration from the PRCI
+- * @pd: PRCI context
+- * @pwd: PRCI WRPLL metadata
+- *
+- * Read the current configuration of the PLL identified by @pwd from
+- * the PRCI identified by @pd, and store it into the local configuration
+- * cache in @pwd.
+- *
+- * Context: Any context.  Caller must prevent the records pointed to by
+- *          @pd and @pwd from changing during execution.
+- */
+-static void __prci_wrpll_read_cfg(struct __prci_data *pd,
+-                                struct __prci_wrpll_data *pwd)
+-{
+-      __prci_wrpll_unpack(&pwd->c, __prci_readl(pd, pwd->cfg0_offs));
+-}
+-
+-/**
+- * __prci_wrpll_write_cfg() - write WRPLL configuration into the PRCI
+- * @pd: PRCI context
+- * @pwd: PRCI WRPLL metadata
+- * @c: WRPLL configuration record to write
+- *
+- * Write the WRPLL configuration described by @c into the WRPLL
+- * configuration register identified by @pwd in the PRCI instance
+- * described by @c.  Make a cached copy of the WRPLL's current
+- * configuration so it can be used by other code.
+- *
+- * Context: Any context.  Caller must prevent the records pointed to by
+- *          @pd and @pwd from changing during execution.
+- */
+-static void __prci_wrpll_write_cfg(struct __prci_data *pd,
+-                                 struct __prci_wrpll_data *pwd,
+-                                 struct wrpll_cfg *c)
+-{
+-      __prci_writel(__prci_wrpll_pack(c), pwd->cfg0_offs, pd);
+-
+-      memcpy(&pwd->c, c, sizeof(*c));
+-}
+-
+-/* Core clock mux control */
+-
+-/**
+- * __prci_coreclksel_use_hfclk() - switch the CORECLK mux to output HFCLK
+- * @pd: struct __prci_data * for the PRCI containing the CORECLK mux reg
+- *
+- * Switch the CORECLK mux to the HFCLK input source; return once complete.
+- *
+- * Context: Any context.  Caller must prevent concurrent changes to the
+- *          PRCI_CORECLKSEL_OFFSET register.
+- */
+-static void __prci_coreclksel_use_hfclk(struct __prci_data *pd)
+-{
+-      u32 r;
+-
+-      r = __prci_readl(pd, PRCI_CORECLKSEL_OFFSET);
+-      r |= PRCI_CORECLKSEL_CORECLKSEL_MASK;
+-      __prci_writel(r, PRCI_CORECLKSEL_OFFSET, pd);
+-
+-      r = __prci_readl(pd, PRCI_CORECLKSEL_OFFSET); /* barrier */
+-}
+-
+-/**
+- * __prci_coreclksel_use_corepll() - switch the CORECLK mux to output COREPLL
+- * @pd: struct __prci_data * for the PRCI containing the CORECLK mux reg
+- *
+- * Switch the CORECLK mux to the PLL output clock; return once complete.
+- *
+- * Context: Any context.  Caller must prevent concurrent changes to the
+- *          PRCI_CORECLKSEL_OFFSET register.
+- */
+-static void __prci_coreclksel_use_corepll(struct __prci_data *pd)
+-{
+-      u32 r;
+-
+-      r = __prci_readl(pd, PRCI_CORECLKSEL_OFFSET);
+-      r &= ~PRCI_CORECLKSEL_CORECLKSEL_MASK;
+-      __prci_writel(r, PRCI_CORECLKSEL_OFFSET, pd);
+-
+-      r = __prci_readl(pd, PRCI_CORECLKSEL_OFFSET); /* barrier */
+-}
+-
+-/*
+- * Linux clock framework integration
+- *
+- * See the Linux clock framework documentation for more information on
+- * these functions.
+- */
+-
+-static unsigned long sifive_fu540_prci_wrpll_recalc_rate(struct clk_hw *hw,
+-                                                       unsigned long parent_rate)
+-{
+-      struct __prci_clock *pc = clk_hw_to_prci_clock(hw);
+-      struct __prci_wrpll_data *pwd = pc->pwd;
+-
+-      return wrpll_calc_output_rate(&pwd->c, parent_rate);
+-}
+-
+-static long sifive_fu540_prci_wrpll_round_rate(struct clk_hw *hw,
+-                                             unsigned long rate,
+-                                             unsigned long *parent_rate)
+-{
+-      struct __prci_clock *pc = clk_hw_to_prci_clock(hw);
+-      struct __prci_wrpll_data *pwd = pc->pwd;
+-      struct wrpll_cfg c;
+-
+-      memcpy(&c, &pwd->c, sizeof(c));
+-
+-      wrpll_configure_for_rate(&c, rate, *parent_rate);
+-
+-      return wrpll_calc_output_rate(&c, *parent_rate);
+-}
+-
+-static int sifive_fu540_prci_wrpll_set_rate(struct clk_hw *hw,
+-                                          unsigned long rate,
+-                                          unsigned long parent_rate)
+-{
+-      struct __prci_clock *pc = clk_hw_to_prci_clock(hw);
+-      struct __prci_wrpll_data *pwd = pc->pwd;
+-      struct __prci_data *pd = pc->pd;
+-      int r;
+-
+-      r = wrpll_configure_for_rate(&pwd->c, rate, parent_rate);
+-      if (r)
+-              return r;
+-
+-      if (pwd->enable_bypass)
+-              pwd->enable_bypass(pd);
+-
+-      __prci_wrpll_write_cfg(pd, pwd, &pwd->c);
+-
+-      udelay(wrpll_calc_max_lock_us(&pwd->c));
+-
+-      if (pwd->disable_bypass)
+-              pwd->disable_bypass(pd);
+-
+-      return 0;
+-}
++/* Linux clock framework integration */
+ static const struct clk_ops sifive_fu540_prci_wrpll_clk_ops = {
+-      .set_rate = sifive_fu540_prci_wrpll_set_rate,
+-      .round_rate = sifive_fu540_prci_wrpll_round_rate,
+-      .recalc_rate = sifive_fu540_prci_wrpll_recalc_rate,
++      .set_rate = sifive_prci_wrpll_set_rate,
++      .round_rate = sifive_prci_wrpll_round_rate,
++      .recalc_rate = sifive_prci_wrpll_recalc_rate,
+ };
+ static const struct clk_ops sifive_fu540_prci_wrpll_ro_clk_ops = {
+-      .recalc_rate = sifive_fu540_prci_wrpll_recalc_rate,
++      .recalc_rate = sifive_prci_wrpll_recalc_rate,
+ };
+-/* TLCLKSEL clock integration */
+-
+-static unsigned long sifive_fu540_prci_tlclksel_recalc_rate(struct clk_hw *hw,
+-                                                          unsigned long parent_rate)
+-{
+-      struct __prci_clock *pc = clk_hw_to_prci_clock(hw);
+-      struct __prci_data *pd = pc->pd;
+-      u32 v;
+-      u8 div;
+-
+-      v = __prci_readl(pd, PRCI_CLKMUXSTATUSREG_OFFSET);
+-      v &= PRCI_CLKMUXSTATUSREG_TLCLKSEL_STATUS_MASK;
+-      div = v ? 1 : 2;
+-
+-      return div_u64(parent_rate, div);
+-}
+-
+ static const struct clk_ops sifive_fu540_prci_tlclksel_clk_ops = {
+-      .recalc_rate = sifive_fu540_prci_tlclksel_recalc_rate,
+-};
+-
+-/*
+- * PRCI integration data for each WRPLL instance
+- */
+-
+-static struct __prci_wrpll_data __prci_corepll_data = {
+-      .cfg0_offs = PRCI_COREPLLCFG0_OFFSET,
+-      .enable_bypass = __prci_coreclksel_use_hfclk,
+-      .disable_bypass = __prci_coreclksel_use_corepll,
+-};
+-
+-static struct __prci_wrpll_data __prci_ddrpll_data = {
+-      .cfg0_offs = PRCI_DDRPLLCFG0_OFFSET,
++      .recalc_rate = sifive_prci_tlclksel_recalc_rate,
+ };
+-static struct __prci_wrpll_data __prci_gemgxlpll_data = {
+-      .cfg0_offs = PRCI_GEMGXLPLLCFG0_OFFSET,
+-};
+-
+-/*
+- * List of clock controls provided by the PRCI
+- */
+-
+-static struct __prci_clock __prci_init_clocks[] = {
++/* List of clock controls provided by the PRCI */
++struct __prci_clock __prci_init_clocks_fu540[] = {
+       [PRCI_CLK_COREPLL] = {
+               .name = "corepll",
+               .parent_name = "hfclk",
+@@ -506,125 +78,3 @@ static struct __prci_clock __prci_init_clocks[] = {
+               .ops = &sifive_fu540_prci_tlclksel_clk_ops,
+       },
+ };
+-
+-/**
+- * __prci_register_clocks() - register clock controls in the PRCI with Linux
+- * @dev: Linux struct device *
+- *
+- * Register the list of clock controls described in __prci_init_plls[] with
+- * the Linux clock framework.
+- *
+- * Return: 0 upon success or a negative error code upon failure.
+- */
+-static int __prci_register_clocks(struct device *dev, struct __prci_data *pd)
+-{
+-      struct clk_init_data init = { };
+-      struct __prci_clock *pic;
+-      int parent_count, i, r;
+-
+-      parent_count = of_clk_get_parent_count(dev->of_node);
+-      if (parent_count != EXPECTED_CLK_PARENT_COUNT) {
+-              dev_err(dev, "expected only two parent clocks, found %d\n",
+-                      parent_count);
+-              return -EINVAL;
+-      }
+-
+-      /* Register PLLs */
+-      for (i = 0; i < ARRAY_SIZE(__prci_init_clocks); ++i) {
+-              pic = &__prci_init_clocks[i];
+-
+-              init.name = pic->name;
+-              init.parent_names = &pic->parent_name;
+-              init.num_parents = 1;
+-              init.ops = pic->ops;
+-              pic->hw.init = &init;
+-
+-              pic->pd = pd;
+-
+-              if (pic->pwd)
+-                      __prci_wrpll_read_cfg(pd, pic->pwd);
+-
+-              r = devm_clk_hw_register(dev, &pic->hw);
+-              if (r) {
+-                      dev_warn(dev, "Failed to register clock %s: %d\n",
+-                               init.name, r);
+-                      return r;
+-              }
+-
+-              r = clk_hw_register_clkdev(&pic->hw, pic->name, dev_name(dev));
+-              if (r) {
+-                      dev_warn(dev, "Failed to register clkdev for %s: %d\n",
+-                               init.name, r);
+-                      return r;
+-              }
+-
+-              pd->hw_clks.hws[i] = &pic->hw;
+-      }
+-
+-      pd->hw_clks.num = i;
+-
+-      r = devm_of_clk_add_hw_provider(dev, of_clk_hw_onecell_get,
+-                                      &pd->hw_clks);
+-      if (r) {
+-              dev_err(dev, "could not add hw_provider: %d\n", r);
+-              return r;
+-      }
+-
+-      return 0;
+-}
+-
+-/*
+- * Linux device model integration
+- *
+- * See the Linux device model documentation for more information about
+- * these functions.
+- */
+-static int sifive_fu540_prci_probe(struct platform_device *pdev)
+-{
+-      struct device *dev = &pdev->dev;
+-      struct resource *res;
+-      struct __prci_data *pd;
+-      int r;
+-
+-      pd = devm_kzalloc(dev,
+-                        struct_size(pd, hw_clks.hws,
+-                                    ARRAY_SIZE(__prci_init_clocks)),
+-                        GFP_KERNEL);
+-      if (!pd)
+-              return -ENOMEM;
+-
+-      res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+-      pd->va = devm_ioremap_resource(dev, res);
+-      if (IS_ERR(pd->va))
+-              return PTR_ERR(pd->va);
+-
+-      r = __prci_register_clocks(dev, pd);
+-      if (r) {
+-              dev_err(dev, "could not register clocks: %d\n", r);
+-              return r;
+-      }
+-
+-      dev_dbg(dev, "SiFive FU540 PRCI probed\n");
+-
+-      return 0;
+-}
+-
+-static const struct of_device_id sifive_fu540_prci_of_match[] = {
+-      { .compatible = "sifive,fu540-c000-prci", },
+-      {}
+-};
+-MODULE_DEVICE_TABLE(of, sifive_fu540_prci_of_match);
+-
+-static struct platform_driver sifive_fu540_prci_driver = {
+-      .driver = {
+-              .name = "sifive-fu540-prci",
+-              .of_match_table = sifive_fu540_prci_of_match,
+-      },
+-      .probe = sifive_fu540_prci_probe,
+-};
+-
+-static int __init sifive_fu540_prci_init(void)
+-{
+-      return platform_driver_register(&sifive_fu540_prci_driver);
+-}
+-core_initcall(sifive_fu540_prci_init);
+diff --git a/drivers/clk/sifive/fu540-prci.h b/drivers/clk/sifive/fu540-prci.h
+new file mode 100644
+index 00000000..c8271ef
+--- /dev/null
++++ b/drivers/clk/sifive/fu540-prci.h
+@@ -0,0 +1,21 @@
++/* SPDX-License-Identifier: GPL-2.0 */
++/*
++ * Copyright (C) 2020 SiFive, Inc.
++ * Zong Li
++ */
++
++#ifndef __SIFIVE_CLK_FU540_PRCI_H
++#define __SIFIVE_CLK_FU540_PRCI_H
++
++#include "sifive-prci.h"
++
++#define NUM_CLOCK_FU540       4
++
++extern struct __prci_clock __prci_init_clocks_fu540[NUM_CLOCK_FU540];
++
++static const struct prci_clk_desc prci_clk_fu540 = {
++      .clks = __prci_init_clocks_fu540,
++      .num_clks = ARRAY_SIZE(__prci_init_clocks_fu540),
++};
++
++#endif /* __SIFIVE_CLK_FU540_PRCI_H */
+diff --git a/drivers/clk/sifive/sifive-prci.c b/drivers/clk/sifive/sifive-prci.c
+new file mode 100644
+index 00000000..70653d3
+--- /dev/null
++++ b/drivers/clk/sifive/sifive-prci.c
+@@ -0,0 +1,395 @@
++// SPDX-License-Identifier: GPL-2.0
++/*
++ * Copyright (C) 2020 SiFive, Inc.
++ * Copyright (C) 2020 Zong Li
++ */
++
++#include <linux/clkdev.h>
++#include <linux/delay.h>
++#include <linux/io.h>
++#include <linux/of_device.h>
++#include "sifive-prci.h"
++#include "fu540-prci.h"
++
++/*
++ * Private functions
++ */
++
++/**
++ * __prci_readl() - read from a PRCI register
++ * @pd: PRCI context
++ * @offs: register offset to read from (in bytes, from PRCI base address)
++ *
++ * Read the register located at offset @offs from the base virtual
++ * address of the PRCI register target described by @pd, and return
++ * the value to the caller.
++ *
++ * Context: Any context.
++ *
++ * Return: the contents of the register described by @pd and @offs.
++ */
++static u32 __prci_readl(struct __prci_data *pd, u32 offs)
++{
++      return readl_relaxed(pd->va + offs);
++}
++
++static void __prci_writel(u32 v, u32 offs, struct __prci_data *pd)
++{
++      writel_relaxed(v, pd->va + offs);
++}
++
++/* WRPLL-related private functions */
++
++/**
++ * __prci_wrpll_unpack() - unpack WRPLL configuration registers into parameters
++ * @c: ptr to a struct wrpll_cfg record to write config into
++ * @r: value read from the PRCI PLL configuration register
++ *
++ * Given a value @r read from an FU740 PRCI PLL configuration register,
++ * split it into fields and populate it into the WRPLL configuration record
++ * pointed to by @c.
++ *
++ * The COREPLLCFG0 macros are used below, but the other *PLLCFG0 macros
++ * have the same register layout.
++ *
++ * Context: Any context.
++ */
++static void __prci_wrpll_unpack(struct wrpll_cfg *c, u32 r)
++{
++      u32 v;
++
++      v = r & PRCI_COREPLLCFG0_DIVR_MASK;
++      v >>= PRCI_COREPLLCFG0_DIVR_SHIFT;
++      c->divr = v;
++
++      v = r & PRCI_COREPLLCFG0_DIVF_MASK;
++      v >>= PRCI_COREPLLCFG0_DIVF_SHIFT;
++      c->divf = v;
++
++      v = r & PRCI_COREPLLCFG0_DIVQ_MASK;
++      v >>= PRCI_COREPLLCFG0_DIVQ_SHIFT;
++      c->divq = v;
++
++      v = r & PRCI_COREPLLCFG0_RANGE_MASK;
++      v >>= PRCI_COREPLLCFG0_RANGE_SHIFT;
++      c->range = v;
++
++      c->flags &=
++          (WRPLL_FLAGS_INT_FEEDBACK_MASK | WRPLL_FLAGS_EXT_FEEDBACK_MASK);
++
++      /* external feedback mode not supported */
++      c->flags |= WRPLL_FLAGS_INT_FEEDBACK_MASK;
++}
++
++/**
++ * __prci_wrpll_pack() - pack PLL configuration parameters into a register value
++ * @c: pointer to a struct wrpll_cfg record containing the PLL's cfg
++ *
++ * Using a set of WRPLL configuration values pointed to by @c,
++ * assemble a PRCI PLL configuration register value, and return it to
++ * the caller.
++ *
++ * Context: Any context.  Caller must ensure that the contents of the
++ *          record pointed to by @c do not change during the execution
++ *          of this function.
++ *
++ * Returns: a value suitable for writing into a PRCI PLL configuration
++ *          register
++ */
++static u32 __prci_wrpll_pack(const struct wrpll_cfg *c)
++{
++      u32 r = 0;
++
++      r |= c->divr << PRCI_COREPLLCFG0_DIVR_SHIFT;
++      r |= c->divf << PRCI_COREPLLCFG0_DIVF_SHIFT;
++      r |= c->divq << PRCI_COREPLLCFG0_DIVQ_SHIFT;
++      r |= c->range << PRCI_COREPLLCFG0_RANGE_SHIFT;
++
++      /* external feedback mode not supported */
++      r |= PRCI_COREPLLCFG0_FSE_MASK;
++
++      return r;
++}
++
++/**
++ * __prci_wrpll_read_cfg() - read the WRPLL configuration from the PRCI
++ * @pd: PRCI context
++ * @pwd: PRCI WRPLL metadata
++ *
++ * Read the current configuration of the PLL identified by @pwd from
++ * the PRCI identified by @pd, and store it into the local configuration
++ * cache in @pwd.
++ *
++ * Context: Any context.  Caller must prevent the records pointed to by
++ *          @pd and @pwd from changing during execution.
++ */
++static void __prci_wrpll_read_cfg(struct __prci_data *pd,
++                                struct __prci_wrpll_data *pwd)
++{
++      __prci_wrpll_unpack(&pwd->c, __prci_readl(pd, pwd->cfg0_offs));
++}
++
++/**
++ * __prci_wrpll_write_cfg() - write WRPLL configuration into the PRCI
++ * @pd: PRCI context
++ * @pwd: PRCI WRPLL metadata
++ * @c: WRPLL configuration record to write
++ *
++ * Write the WRPLL configuration described by @c into the WRPLL
++ * configuration register identified by @pwd in the PRCI instance
++ * described by @c.  Make a cached copy of the WRPLL's current
++ * configuration so it can be used by other code.
++ *
++ * Context: Any context.  Caller must prevent the records pointed to by
++ *          @pd and @pwd from changing during execution.
++ */
++static void __prci_wrpll_write_cfg(struct __prci_data *pd,
++                                 struct __prci_wrpll_data *pwd,
++                                 struct wrpll_cfg *c)
++{
++      __prci_writel(__prci_wrpll_pack(c), pwd->cfg0_offs, pd);
++
++      memcpy(&pwd->c, c, sizeof(*c));
++}
++
++/*
++ * Linux clock framework integration
++ *
++ * See the Linux clock framework documentation for more information on
++ * these functions.
++ */
++
++unsigned long sifive_prci_wrpll_recalc_rate(struct clk_hw *hw,
++                                          unsigned long parent_rate)
++{
++      struct __prci_clock *pc = clk_hw_to_prci_clock(hw);
++      struct __prci_wrpll_data *pwd = pc->pwd;
++
++      return wrpll_calc_output_rate(&pwd->c, parent_rate);
++}
++
++long sifive_prci_wrpll_round_rate(struct clk_hw *hw,
++                                unsigned long rate,
++                                unsigned long *parent_rate)
++{
++      struct __prci_clock *pc = clk_hw_to_prci_clock(hw);
++      struct __prci_wrpll_data *pwd = pc->pwd;
++      struct wrpll_cfg c;
++
++      memcpy(&c, &pwd->c, sizeof(c));
++
++      wrpll_configure_for_rate(&c, rate, *parent_rate);
++
++      return wrpll_calc_output_rate(&c, *parent_rate);
++}
++
++int sifive_prci_wrpll_set_rate(struct clk_hw *hw,
++                             unsigned long rate, unsigned long parent_rate)
++{
++      struct __prci_clock *pc = clk_hw_to_prci_clock(hw);
++      struct __prci_wrpll_data *pwd = pc->pwd;
++      struct __prci_data *pd = pc->pd;
++      int r;
++
++      r = wrpll_configure_for_rate(&pwd->c, rate, parent_rate);
++      if (r)
++              return r;
++
++      if (pwd->enable_bypass)
++              pwd->enable_bypass(pd);
++
++      __prci_wrpll_write_cfg(pd, pwd, &pwd->c);
++
++      udelay(wrpll_calc_max_lock_us(&pwd->c));
++
++      if (pwd->disable_bypass)
++              pwd->disable_bypass(pd);
++
++      return 0;
++}
++
++/* TLCLKSEL clock integration */
++
++unsigned long sifive_prci_tlclksel_recalc_rate(struct clk_hw *hw,
++                                             unsigned long parent_rate)
++{
++      struct __prci_clock *pc = clk_hw_to_prci_clock(hw);
++      struct __prci_data *pd = pc->pd;
++      u32 v;
++      u8 div;
++
++      v = __prci_readl(pd, PRCI_CLKMUXSTATUSREG_OFFSET);
++      v &= PRCI_CLKMUXSTATUSREG_TLCLKSEL_STATUS_MASK;
++      div = v ? 1 : 2;
++
++      return div_u64(parent_rate, div);
++}
++
++/*
++ * Core clock mux control
++ */
++
++/**
++ * sifive_prci_coreclksel_use_hfclk() - switch the CORECLK mux to output HFCLK
++ * @pd: struct __prci_data * for the PRCI containing the CORECLK mux reg
++ *
++ * Switch the CORECLK mux to the HFCLK input source; return once complete.
++ *
++ * Context: Any context.  Caller must prevent concurrent changes to the
++ *          PRCI_CORECLKSEL_OFFSET register.
++ */
++void sifive_prci_coreclksel_use_hfclk(struct __prci_data *pd)
++{
++      u32 r;
++
++      r = __prci_readl(pd, PRCI_CORECLKSEL_OFFSET);
++      r |= PRCI_CORECLKSEL_CORECLKSEL_MASK;
++      __prci_writel(r, PRCI_CORECLKSEL_OFFSET, pd);
++
++      r = __prci_readl(pd, PRCI_CORECLKSEL_OFFSET);   /* barrier */
++}
++
++/**
++ * sifive_prci_coreclksel_use_corepll() - switch the CORECLK mux to output
++ * COREPLL
++ * @pd: struct __prci_data * for the PRCI containing the CORECLK mux reg
++ *
++ * Switch the CORECLK mux to the COREPLL output clock; return once complete.
++ *
++ * Context: Any context.  Caller must prevent concurrent changes to the
++ *          PRCI_CORECLKSEL_OFFSET register.
++ */
++void sifive_prci_coreclksel_use_corepll(struct __prci_data *pd)
++{
++      u32 r;
++
++      r = __prci_readl(pd, PRCI_CORECLKSEL_OFFSET);
++      r &= ~PRCI_CORECLKSEL_CORECLKSEL_MASK;
++      __prci_writel(r, PRCI_CORECLKSEL_OFFSET, pd);
++
++      r = __prci_readl(pd, PRCI_CORECLKSEL_OFFSET);   /* barrier */
++}
++
++/**
++ * __prci_register_clocks() - register clock controls in the PRCI
++ * @dev: Linux struct device
++ * @pd: The pointer for PRCI per-device instance data
++ * @desc: The pointer for the information of clocks of each SoCs
++ *
++ * Register the list of clock controls described in __prci_init_clocks[] with
++ * the Linux clock framework.
++ *
++ * Return: 0 upon success or a negative error code upon failure.
++ */
++static int __prci_register_clocks(struct device *dev, struct __prci_data *pd,
++                                const struct prci_clk_desc *desc)
++{
++      struct clk_init_data init = { };
++      struct __prci_clock *pic;
++      int parent_count, i, r;
++
++      parent_count = of_clk_get_parent_count(dev->of_node);
++      if (parent_count != EXPECTED_CLK_PARENT_COUNT) {
++              dev_err(dev, "expected only two parent clocks, found %d\n",
++                      parent_count);
++              return -EINVAL;
++      }
++
++      /* Register PLLs */
++      for (i = 0; i < desc->num_clks; ++i) {
++              pic = &(desc->clks[i]);
++
++              init.name = pic->name;
++              init.parent_names = &pic->parent_name;
++              init.num_parents = 1;
++              init.ops = pic->ops;
++              pic->hw.init = &init;
++
++              pic->pd = pd;
++
++              if (pic->pwd)
++                      __prci_wrpll_read_cfg(pd, pic->pwd);
++
++              r = devm_clk_hw_register(dev, &pic->hw);
++              if (r) {
++                      dev_warn(dev, "Failed to register clock %s: %d\n",
++                               init.name, r);
++                      return r;
++              }
++
++              r = clk_hw_register_clkdev(&pic->hw, pic->name, dev_name(dev));
++              if (r) {
++                      dev_warn(dev, "Failed to register clkdev for %s: %d\n",
++                               init.name, r);
++                      return r;
++              }
++
++              pd->hw_clks.hws[i] = &pic->hw;
++      }
++
++      pd->hw_clks.num = i;
++
++      r = devm_of_clk_add_hw_provider(dev, of_clk_hw_onecell_get,
++                                      &pd->hw_clks);
++      if (r) {
++              dev_err(dev, "could not add hw_provider: %d\n", r);
++              return r;
++      }
++
++      return 0;
++}
++
++/**
++ * sifive_prci_init() - initialize prci data and check parent count
++ * @pdev: platform device pointer for the prci
++ *
++ * Return: 0 upon success or a negative error code upon failure.
++ */
++static int sifive_prci_probe(struct platform_device *pdev)
++{
++      struct device *dev = &pdev->dev;
++      struct resource *res;
++      struct __prci_data *pd;
++      const struct prci_clk_desc *desc;
++      int r;
++
++      desc = of_device_get_match_data(&pdev->dev);
++
++      pd = devm_kzalloc(dev, struct_size(pd, hw_clks.hws, desc->num_clks), GFP_KERNEL);
++      if (!pd)
++              return -ENOMEM;
++
++      res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
++      pd->va = devm_ioremap_resource(dev, res);
++      if (IS_ERR(pd->va))
++              return PTR_ERR(pd->va);
++
++      r = __prci_register_clocks(dev, pd, desc);
++      if (r) {
++              dev_err(dev, "could not register clocks: %d\n", r);
++              return r;
++      }
++
++      dev_dbg(dev, "SiFive PRCI probed\n");
++
++      return 0;
++}
++
++static const struct of_device_id sifive_prci_of_match[] = {
++      {.compatible = "sifive,fu540-c000-prci", .data = &prci_clk_fu540},
++      {}
++};
++
++static struct platform_driver sifive_prci_driver = {
++      .driver = {
++              .name = "sifive-clk-prci",
++              .of_match_table = sifive_prci_of_match,
++      },
++      .probe = sifive_prci_probe,
++};
++
++static int __init sifive_prci_init(void)
++{
++      return platform_driver_register(&sifive_prci_driver);
++}
++core_initcall(sifive_prci_init);
+diff --git a/drivers/clk/sifive/sifive-prci.h b/drivers/clk/sifive/sifive-prci.h
+new file mode 100644
+index 00000000..280df63
+--- /dev/null
++++ b/drivers/clk/sifive/sifive-prci.h
+@@ -0,0 +1,201 @@
++/* SPDX-License-Identifier: GPL-2.0 */
++/*
++ * Copyright (C) 2018-2019 SiFive, Inc.
++ * Wesley Terpstra
++ * Paul Walmsley
++ * Zong Li
++ */
++
++#ifndef __SIFIVE_CLK_SIFIVE_PRCI_H
++#define __SIFIVE_CLK_SIFIVE_PRCI_H
++
++#include <linux/clk/analogbits-wrpll-cln28hpc.h>
++#include <linux/clk-provider.h>
++#include <linux/platform_device.h>
++
++/*
++ * EXPECTED_CLK_PARENT_COUNT: how many parent clocks this driver expects:
++ *     hfclk and rtcclk
++ */
++#define EXPECTED_CLK_PARENT_COUNT 2
++
++/*
++ * Register offsets and bitmasks
++ */
++
++/* COREPLLCFG0 */
++#define PRCI_COREPLLCFG0_OFFSET               0x4
++#define PRCI_COREPLLCFG0_DIVR_SHIFT   0
++#define PRCI_COREPLLCFG0_DIVR_MASK    (0x3f << PRCI_COREPLLCFG0_DIVR_SHIFT)
++#define PRCI_COREPLLCFG0_DIVF_SHIFT   6
++#define PRCI_COREPLLCFG0_DIVF_MASK    (0x1ff << PRCI_COREPLLCFG0_DIVF_SHIFT)
++#define PRCI_COREPLLCFG0_DIVQ_SHIFT   15
++#define PRCI_COREPLLCFG0_DIVQ_MASK    (0x7 << PRCI_COREPLLCFG0_DIVQ_SHIFT)
++#define PRCI_COREPLLCFG0_RANGE_SHIFT  18
++#define PRCI_COREPLLCFG0_RANGE_MASK   (0x7 << PRCI_COREPLLCFG0_RANGE_SHIFT)
++#define PRCI_COREPLLCFG0_BYPASS_SHIFT 24
++#define PRCI_COREPLLCFG0_BYPASS_MASK  (0x1 << PRCI_COREPLLCFG0_BYPASS_SHIFT)
++#define PRCI_COREPLLCFG0_FSE_SHIFT    25
++#define PRCI_COREPLLCFG0_FSE_MASK     (0x1 << PRCI_COREPLLCFG0_FSE_SHIFT)
++#define PRCI_COREPLLCFG0_LOCK_SHIFT   31
++#define PRCI_COREPLLCFG0_LOCK_MASK    (0x1 << PRCI_COREPLLCFG0_LOCK_SHIFT)
++
++/* DDRPLLCFG0 */
++#define PRCI_DDRPLLCFG0_OFFSET                0xc
++#define PRCI_DDRPLLCFG0_DIVR_SHIFT    0
++#define PRCI_DDRPLLCFG0_DIVR_MASK     (0x3f << PRCI_DDRPLLCFG0_DIVR_SHIFT)
++#define PRCI_DDRPLLCFG0_DIVF_SHIFT    6
++#define PRCI_DDRPLLCFG0_DIVF_MASK     (0x1ff << PRCI_DDRPLLCFG0_DIVF_SHIFT)
++#define PRCI_DDRPLLCFG0_DIVQ_SHIFT    15
++#define PRCI_DDRPLLCFG0_DIVQ_MASK     (0x7 << PRCI_DDRPLLCFG0_DIVQ_SHIFT)
++#define PRCI_DDRPLLCFG0_RANGE_SHIFT   18
++#define PRCI_DDRPLLCFG0_RANGE_MASK    (0x7 << PRCI_DDRPLLCFG0_RANGE_SHIFT)
++#define PRCI_DDRPLLCFG0_BYPASS_SHIFT  24
++#define PRCI_DDRPLLCFG0_BYPASS_MASK   (0x1 << PRCI_DDRPLLCFG0_BYPASS_SHIFT)
++#define PRCI_DDRPLLCFG0_FSE_SHIFT     25
++#define PRCI_DDRPLLCFG0_FSE_MASK      (0x1 << PRCI_DDRPLLCFG0_FSE_SHIFT)
++#define PRCI_DDRPLLCFG0_LOCK_SHIFT    31
++#define PRCI_DDRPLLCFG0_LOCK_MASK     (0x1 << PRCI_DDRPLLCFG0_LOCK_SHIFT)
++
++/* DDRPLLCFG1 */
++#define PRCI_DDRPLLCFG1_OFFSET                0x10
++#define PRCI_DDRPLLCFG1_CKE_SHIFT     24
++#define PRCI_DDRPLLCFG1_CKE_MASK      (0x1 << PRCI_DDRPLLCFG1_CKE_SHIFT)
++
++/* GEMGXLPLLCFG0 */
++#define PRCI_GEMGXLPLLCFG0_OFFSET     0x1c
++#define PRCI_GEMGXLPLLCFG0_DIVR_SHIFT 0
++#define PRCI_GEMGXLPLLCFG0_DIVR_MASK  (0x3f << PRCI_GEMGXLPLLCFG0_DIVR_SHIFT)
++#define PRCI_GEMGXLPLLCFG0_DIVF_SHIFT 6
++#define PRCI_GEMGXLPLLCFG0_DIVF_MASK  (0x1ff << PRCI_GEMGXLPLLCFG0_DIVF_SHIFT)
++#define PRCI_GEMGXLPLLCFG0_DIVQ_SHIFT 15
++#define PRCI_GEMGXLPLLCFG0_DIVQ_MASK  (0x7 << PRCI_GEMGXLPLLCFG0_DIVQ_SHIFT)
++#define PRCI_GEMGXLPLLCFG0_RANGE_SHIFT        18
++#define PRCI_GEMGXLPLLCFG0_RANGE_MASK (0x7 << PRCI_GEMGXLPLLCFG0_RANGE_SHIFT)
++#define PRCI_GEMGXLPLLCFG0_BYPASS_SHIFT       24
++#define PRCI_GEMGXLPLLCFG0_BYPASS_MASK        (0x1 << PRCI_GEMGXLPLLCFG0_BYPASS_SHIFT)
++#define PRCI_GEMGXLPLLCFG0_FSE_SHIFT  25
++#define PRCI_GEMGXLPLLCFG0_FSE_MASK   (0x1 << PRCI_GEMGXLPLLCFG0_FSE_SHIFT)
++#define PRCI_GEMGXLPLLCFG0_LOCK_SHIFT 31
++#define PRCI_GEMGXLPLLCFG0_LOCK_MASK  (0x1 << PRCI_GEMGXLPLLCFG0_LOCK_SHIFT)
++
++/* GEMGXLPLLCFG1 */
++#define PRCI_GEMGXLPLLCFG1_OFFSET     0x20
++#define PRCI_GEMGXLPLLCFG1_CKE_SHIFT  24
++#define PRCI_GEMGXLPLLCFG1_CKE_MASK   (0x1 << PRCI_GEMGXLPLLCFG1_CKE_SHIFT)
++
++/* CORECLKSEL */
++#define PRCI_CORECLKSEL_OFFSET                        0x24
++#define PRCI_CORECLKSEL_CORECLKSEL_SHIFT      0
++#define PRCI_CORECLKSEL_CORECLKSEL_MASK                                       \
++              (0x1 << PRCI_CORECLKSEL_CORECLKSEL_SHIFT)
++
++/* DEVICESRESETREG */
++#define PRCI_DEVICESRESETREG_OFFSET                           0x28
++#define PRCI_DEVICESRESETREG_DDR_CTRL_RST_N_SHIFT             0
++#define PRCI_DEVICESRESETREG_DDR_CTRL_RST_N_MASK                      \
++              (0x1 << PRCI_DEVICESRESETREG_DDR_CTRL_RST_N_SHIFT)
++#define PRCI_DEVICESRESETREG_DDR_AXI_RST_N_SHIFT              1
++#define PRCI_DEVICESRESETREG_DDR_AXI_RST_N_MASK                               \
++              (0x1 << PRCI_DEVICESRESETREG_DDR_AXI_RST_N_SHIFT)
++#define PRCI_DEVICESRESETREG_DDR_AHB_RST_N_SHIFT              2
++#define PRCI_DEVICESRESETREG_DDR_AHB_RST_N_MASK                               \
++              (0x1 << PRCI_DEVICESRESETREG_DDR_AHB_RST_N_SHIFT)
++#define PRCI_DEVICESRESETREG_DDR_PHY_RST_N_SHIFT              3
++#define PRCI_DEVICESRESETREG_DDR_PHY_RST_N_MASK                               \
++              (0x1 << PRCI_DEVICESRESETREG_DDR_PHY_RST_N_SHIFT)
++#define PRCI_DEVICESRESETREG_GEMGXL_RST_N_SHIFT                       5
++#define PRCI_DEVICESRESETREG_GEMGXL_RST_N_MASK                                \
++              (0x1 << PRCI_DEVICESRESETREG_GEMGXL_RST_N_SHIFT)
++#define PRCI_DEVICESRESETREG_CHIPLINK_RST_N_SHIFT             6
++#define PRCI_DEVICESRESETREG_CHIPLINK_RST_N_MASK                      \
++              (0x1 << PRCI_DEVICESRESETREG_CHIPLINK_RST_N_SHIFT)
++
++/* CLKMUXSTATUSREG */
++#define PRCI_CLKMUXSTATUSREG_OFFSET                           0x2c
++#define PRCI_CLKMUXSTATUSREG_TLCLKSEL_STATUS_SHIFT            1
++#define PRCI_CLKMUXSTATUSREG_TLCLKSEL_STATUS_MASK                     \
++              (0x1 << PRCI_CLKMUXSTATUSREG_TLCLKSEL_STATUS_SHIFT)
++
++/*
++ * Private structures
++ */
++
++/**
++ * struct __prci_data - per-device-instance data
++ * @va: base virtual address of the PRCI IP block
++ * @hw_clks: encapsulates struct clk_hw records
++ *
++ * PRCI per-device instance data
++ */
++struct __prci_data {
++      void __iomem *va;
++      struct clk_hw_onecell_data hw_clks;
++};
++
++/**
++ * struct __prci_wrpll_data - WRPLL configuration and integration data
++ * @c: WRPLL current configuration record
++ * @enable_bypass: fn ptr to code to bypass the WRPLL (if applicable; else NULL)
++ * @disable_bypass: fn ptr to code to not bypass the WRPLL (or NULL)
++ * @cfg0_offs: WRPLL CFG0 register offset (in bytes) from the PRCI base address
++ *
++ * @enable_bypass and @disable_bypass are used for WRPLL instances
++ * that contain a separate external glitchless clock mux downstream
++ * from the PLL.  The WRPLL internal bypass mux is not glitchless.
++ */
++struct __prci_wrpll_data {
++      struct wrpll_cfg c;
++      void (*enable_bypass)(struct __prci_data *pd);
++      void (*disable_bypass)(struct __prci_data *pd);
++      u8 cfg0_offs;
++};
++
++/**
++ * struct __prci_clock - describes a clock device managed by PRCI
++ * @name: user-readable clock name string - should match the manual
++ * @parent_name: parent name for this clock
++ * @ops: struct clk_ops for the Linux clock framework to use for control
++ * @hw: Linux-private clock data
++ * @pwd: WRPLL-specific data, associated with this clock (if not NULL)
++ * @pd: PRCI-specific data associated with this clock (if not NULL)
++ *
++ * PRCI clock data.  Used by the PRCI driver to register PRCI-provided
++ * clocks to the Linux clock infrastructure.
++ */
++struct __prci_clock {
++      const char *name;
++      const char *parent_name;
++      const struct clk_ops *ops;
++      struct clk_hw hw;
++      struct __prci_wrpll_data *pwd;
++      struct __prci_data *pd;
++};
++
++#define clk_hw_to_prci_clock(pwd) container_of(pwd, struct __prci_clock, hw)
++
++/*
++ * struct prci_clk_desc - describes the information of clocks of each SoCs
++ * @clks: point to a array of __prci_clock
++ * @num_clks: the number of element of clks
++ */
++struct prci_clk_desc {
++      struct __prci_clock *clks;
++      size_t num_clks;
++};
++
++/* Core clock mux control */
++void sifive_prci_coreclksel_use_hfclk(struct __prci_data *pd);
++void sifive_prci_coreclksel_use_corepll(struct __prci_data *pd);
++
++/* Linux clock framework integration */
++long sifive_prci_wrpll_round_rate(struct clk_hw *hw, unsigned long rate,
++                                unsigned long *parent_rate);
++int sifive_prci_wrpll_set_rate(struct clk_hw *hw, unsigned long rate,
++                             unsigned long parent_rate);
++unsigned long sifive_prci_wrpll_recalc_rate(struct clk_hw *hw,
++                                          unsigned long parent_rate);
++unsigned long sifive_prci_tlclksel_recalc_rate(struct clk_hw *hw,
++                                             unsigned long parent_rate);
++
++#endif /* __SIFIVE_CLK_SIFIVE_PRCI_H */
+-- 
+2.7.4
+
diff --git a/target/linux/hifiveu/patches-5.10/0002-clk-sifive-Use-common-name-for-prci-configuration.patch b/target/linux/hifiveu/patches-5.10/0002-clk-sifive-Use-common-name-for-prci-configuration.patch
new file mode 100644 (file)
index 0000000..0f51ff0
--- /dev/null
@@ -0,0 +1,62 @@
+From df86ca5b9416ebeacb5ecee63118170c7ea20035 Mon Sep 17 00:00:00 2001
+From: Zong Li <zong.li@sifive.com>
+Date: Wed, 9 Dec 2020 17:49:13 +0800
+Subject: [PATCH 02/29] clk: sifive: Use common name for prci configuration
+
+Use generic name CLK_SIFIVE_PRCI instead of CLK_SIFIVE_FU540_PRCI. This
+patch is prepared for fu740 support.
+
+Signed-off-by: Zong Li <zong.li@sifive.com>
+Reviewed-by: Palmer Dabbelt <palmerdabbelt@google.com>
+Acked-by: Palmer Dabbelt <palmerdabbelt@google.com>
+Reviewed-by: Pragnesh Patel <Pragnesh.patel@sifive.com>
+---
+ arch/riscv/Kconfig.socs     | 2 +-
+ drivers/clk/sifive/Kconfig  | 6 +++---
+ drivers/clk/sifive/Makefile | 2 +-
+ 3 files changed, 5 insertions(+), 5 deletions(-)
+
+diff --git a/arch/riscv/Kconfig.socs b/arch/riscv/Kconfig.socs
+index 8a55f61..3284d5c 100644
+--- a/arch/riscv/Kconfig.socs
++++ b/arch/riscv/Kconfig.socs
+@@ -5,7 +5,7 @@ config SOC_SIFIVE
+       select SERIAL_SIFIVE if TTY
+       select SERIAL_SIFIVE_CONSOLE if TTY
+       select CLK_SIFIVE
+-      select CLK_SIFIVE_FU540_PRCI
++      select CLK_SIFIVE_PRCI
+       select SIFIVE_PLIC
+       help
+         This enables support for SiFive SoC platform hardware.
+diff --git a/drivers/clk/sifive/Kconfig b/drivers/clk/sifive/Kconfig
+index f3b4eb9..ab48cf7 100644
+--- a/drivers/clk/sifive/Kconfig
++++ b/drivers/clk/sifive/Kconfig
+@@ -8,12 +8,12 @@ menuconfig CLK_SIFIVE
+ if CLK_SIFIVE
+-config CLK_SIFIVE_FU540_PRCI
+-      bool "PRCI driver for SiFive FU540 SoCs"
++config CLK_SIFIVE_PRCI
++      bool "PRCI driver for SiFive SoCs"
+       select CLK_ANALOGBITS_WRPLL_CLN28HPC
+       help
+         Supports the Power Reset Clock interface (PRCI) IP block found in
+-        FU540 SoCs.  If this kernel is meant to run on a SiFive FU540 SoC,
++        FU540 SoCs. If this kernel is meant to run on a SiFive FU540 SoC,
+         enable this driver.
+ endif
+diff --git a/drivers/clk/sifive/Makefile b/drivers/clk/sifive/Makefile
+index 51b6ebc..3074cdb 100644
+--- a/drivers/clk/sifive/Makefile
++++ b/drivers/clk/sifive/Makefile
+@@ -1,2 +1,2 @@
+ # SPDX-License-Identifier: GPL-2.0-only
+-obj-$(CONFIG_CLK_SIFIVE_FU540_PRCI)   += sifive-prci.o fu540-prci.o
++obj-$(CONFIG_CLK_SIFIVE_PRCI) += sifive-prci.o fu540-prci.o
+-- 
+2.7.4
+
diff --git a/target/linux/hifiveu/patches-5.10/0003-clk-sifive-Add-a-driver-for-the-SiFive-FU740-PRCI-IP.patch b/target/linux/hifiveu/patches-5.10/0003-clk-sifive-Add-a-driver-for-the-SiFive-FU740-PRCI-IP.patch
new file mode 100644 (file)
index 0000000..8b2022b
--- /dev/null
@@ -0,0 +1,500 @@
+From c5d3ecfcbdcf2e2d24b636fb739501e1a3e85f14 Mon Sep 17 00:00:00 2001
+From: Zong Li <zong.li@sifive.com>
+Date: Wed, 9 Dec 2020 17:49:14 +0800
+Subject: [PATCH 03/29] clk: sifive: Add a driver for the SiFive FU740 PRCI IP
+ block
+
+Add driver code for the SiFive FU740 PRCI IP block. This IP block
+handles reset and clock control for the SiFive FU740 device and
+implements SoC-level clock tree controls and dividers.
+
+The link of unmatched as follow, and the U740-C000 manual would
+be present in the same page as soon.
+https://www.sifive.com/boards/hifive-unmatched
+
+This driver contains bug fixes and contributions from
+Henry Styles <hes@sifive.com>
+Erik Danie <erik.danie@sifive.com>
+Pragnesh Patel <pragnesh.patel@sifive.com>
+
+Signed-off-by: Zong Li <zong.li@sifive.com>
+Reviewed-by: Pragnesh Patel <Pragnesh.patel@sifive.com>
+Acked-by: Palmer Dabbelt <palmerdabbelt@google.com>
+Cc: Henry Styles <hes@sifive.com>
+Cc: Erik Danie <erik.danie@sifive.com>
+Cc: Pragnesh Patel <pragnesh.patel@sifive.com>
+---
+ drivers/clk/sifive/Kconfig                    |   4 +-
+ drivers/clk/sifive/Makefile                   |   2 +-
+ drivers/clk/sifive/fu740-prci.c               | 111 ++++++++++++++++++++++++
+ drivers/clk/sifive/fu740-prci.h               |  21 +++++
+ drivers/clk/sifive/sifive-prci.c              | 120 ++++++++++++++++++++++++++
+ drivers/clk/sifive/sifive-prci.h              |  88 +++++++++++++++++++
+ include/dt-bindings/clock/sifive-fu740-prci.h |  23 +++++
+ 7 files changed, 366 insertions(+), 3 deletions(-)
+ create mode 100644 drivers/clk/sifive/fu740-prci.c
+ create mode 100644 drivers/clk/sifive/fu740-prci.h
+ create mode 100644 include/dt-bindings/clock/sifive-fu740-prci.h
+
+diff --git a/drivers/clk/sifive/Kconfig b/drivers/clk/sifive/Kconfig
+index ab48cf7..1c14eb2 100644
+--- a/drivers/clk/sifive/Kconfig
++++ b/drivers/clk/sifive/Kconfig
+@@ -13,7 +13,7 @@ config CLK_SIFIVE_PRCI
+       select CLK_ANALOGBITS_WRPLL_CLN28HPC
+       help
+         Supports the Power Reset Clock interface (PRCI) IP block found in
+-        FU540 SoCs. If this kernel is meant to run on a SiFive FU540 SoC,
+-        enable this driver.
++        FU540/FU740 SoCs. If this kernel is meant to run on a SiFive FU540/
++        FU740 SoCs, enable this driver.
+ endif
+diff --git a/drivers/clk/sifive/Makefile b/drivers/clk/sifive/Makefile
+index 3074cdb..7b06fc0 100644
+--- a/drivers/clk/sifive/Makefile
++++ b/drivers/clk/sifive/Makefile
+@@ -1,2 +1,2 @@
+ # SPDX-License-Identifier: GPL-2.0-only
+-obj-$(CONFIG_CLK_SIFIVE_PRCI) += sifive-prci.o fu540-prci.o
++obj-$(CONFIG_CLK_SIFIVE_PRCI) += sifive-prci.o fu540-prci.o fu740-prci.o
+diff --git a/drivers/clk/sifive/fu740-prci.c b/drivers/clk/sifive/fu740-prci.c
+new file mode 100644
+index 00000000..41ddd44
+--- /dev/null
++++ b/drivers/clk/sifive/fu740-prci.c
+@@ -0,0 +1,111 @@
++// SPDX-License-Identifier: GPL-2.0
++/*
++ * Copyright (C) 2020 SiFive, Inc.
++ * Copyright (C) 2020 Zong Li
++ */
++
++#include <dt-bindings/clock/sifive-fu740-prci.h>
++#include <linux/module.h>
++#include "sifive-prci.h"
++
++/* PRCI integration data for each WRPLL instance */
++
++static struct __prci_wrpll_data __prci_corepll_data = {
++      .cfg0_offs = PRCI_COREPLLCFG0_OFFSET,
++      .enable_bypass = sifive_prci_coreclksel_use_hfclk,
++      .disable_bypass = sifive_prci_coreclksel_use_final_corepll,
++};
++
++static struct __prci_wrpll_data __prci_ddrpll_data = {
++      .cfg0_offs = PRCI_DDRPLLCFG0_OFFSET,
++};
++
++static struct __prci_wrpll_data __prci_gemgxlpll_data = {
++      .cfg0_offs = PRCI_GEMGXLPLLCFG0_OFFSET,
++};
++
++static struct __prci_wrpll_data __prci_dvfscorepll_data = {
++      .cfg0_offs = PRCI_DVFSCOREPLLCFG0_OFFSET,
++      .enable_bypass = sifive_prci_corepllsel_use_corepll,
++      .disable_bypass = sifive_prci_corepllsel_use_dvfscorepll,
++};
++
++static struct __prci_wrpll_data __prci_hfpclkpll_data = {
++      .cfg0_offs = PRCI_HFPCLKPLLCFG0_OFFSET,
++      .enable_bypass = sifive_prci_hfpclkpllsel_use_hfclk,
++      .disable_bypass = sifive_prci_hfpclkpllsel_use_hfpclkpll,
++};
++
++static struct __prci_wrpll_data __prci_cltxpll_data = {
++      .cfg0_offs = PRCI_CLTXPLLCFG0_OFFSET,
++};
++
++/* Linux clock framework integration */
++
++static const struct clk_ops sifive_fu740_prci_wrpll_clk_ops = {
++      .set_rate = sifive_prci_wrpll_set_rate,
++      .round_rate = sifive_prci_wrpll_round_rate,
++      .recalc_rate = sifive_prci_wrpll_recalc_rate,
++};
++
++static const struct clk_ops sifive_fu740_prci_wrpll_ro_clk_ops = {
++      .recalc_rate = sifive_prci_wrpll_recalc_rate,
++};
++
++static const struct clk_ops sifive_fu740_prci_tlclksel_clk_ops = {
++      .recalc_rate = sifive_prci_tlclksel_recalc_rate,
++};
++
++static const struct clk_ops sifive_fu740_prci_hfpclkplldiv_clk_ops = {
++      .recalc_rate = sifive_prci_hfpclkplldiv_recalc_rate,
++};
++
++/* List of clock controls provided by the PRCI */
++struct __prci_clock __prci_init_clocks_fu740[] = {
++      [PRCI_CLK_COREPLL] = {
++              .name = "corepll",
++              .parent_name = "hfclk",
++              .ops = &sifive_fu740_prci_wrpll_clk_ops,
++              .pwd = &__prci_corepll_data,
++      },
++      [PRCI_CLK_DDRPLL] = {
++              .name = "ddrpll",
++              .parent_name = "hfclk",
++              .ops = &sifive_fu740_prci_wrpll_ro_clk_ops,
++              .pwd = &__prci_ddrpll_data,
++      },
++      [PRCI_CLK_GEMGXLPLL] = {
++              .name = "gemgxlpll",
++              .parent_name = "hfclk",
++              .ops = &sifive_fu740_prci_wrpll_clk_ops,
++              .pwd = &__prci_gemgxlpll_data,
++      },
++      [PRCI_CLK_DVFSCOREPLL] = {
++              .name = "dvfscorepll",
++              .parent_name = "hfclk",
++              .ops = &sifive_fu740_prci_wrpll_clk_ops,
++              .pwd = &__prci_dvfscorepll_data,
++      },
++      [PRCI_CLK_HFPCLKPLL] = {
++              .name = "hfpclkpll",
++              .parent_name = "hfclk",
++              .ops = &sifive_fu740_prci_wrpll_clk_ops,
++              .pwd = &__prci_hfpclkpll_data,
++      },
++      [PRCI_CLK_CLTXPLL] = {
++              .name = "cltxpll",
++              .parent_name = "hfclk",
++              .ops = &sifive_fu740_prci_wrpll_clk_ops,
++              .pwd = &__prci_cltxpll_data,
++      },
++      [PRCI_CLK_TLCLK] = {
++              .name = "tlclk",
++              .parent_name = "corepll",
++              .ops = &sifive_fu740_prci_tlclksel_clk_ops,
++      },
++      [PRCI_CLK_PCLK] = {
++              .name = "pclk",
++              .parent_name = "hfpclkpll",
++              .ops = &sifive_fu740_prci_hfpclkplldiv_clk_ops,
++      },
++};
+diff --git a/drivers/clk/sifive/fu740-prci.h b/drivers/clk/sifive/fu740-prci.h
+new file mode 100644
+index 00000000..13ef971f7
+--- /dev/null
++++ b/drivers/clk/sifive/fu740-prci.h
+@@ -0,0 +1,21 @@
++/* SPDX-License-Identifier: GPL-2.0 */
++/*
++ * Copyright (C) 2020 SiFive, Inc.
++ * Zong Li
++ */
++
++#ifndef __SIFIVE_CLK_FU740_PRCI_H
++#define __SIFIVE_CLK_FU740_PRCI_H
++
++#include "sifive-prci.h"
++
++#define NUM_CLOCK_FU740       8
++
++extern struct __prci_clock __prci_init_clocks_fu740[NUM_CLOCK_FU740];
++
++static const struct prci_clk_desc prci_clk_fu740 = {
++      .clks = __prci_init_clocks_fu740,
++      .num_clks = ARRAY_SIZE(__prci_init_clocks_fu740),
++};
++
++#endif /* __SIFIVE_CLK_FU740_PRCI_H */
+diff --git a/drivers/clk/sifive/sifive-prci.c b/drivers/clk/sifive/sifive-prci.c
+index 70653d3..cc4b4c6 100644
+--- a/drivers/clk/sifive/sifive-prci.c
++++ b/drivers/clk/sifive/sifive-prci.c
+@@ -10,6 +10,7 @@
+ #include <linux/of_device.h>
+ #include "sifive-prci.h"
+ #include "fu540-prci.h"
++#include "fu740-prci.h"
+ /*
+  * Private functions
+@@ -225,6 +226,18 @@ unsigned long sifive_prci_tlclksel_recalc_rate(struct clk_hw *hw,
+       return div_u64(parent_rate, div);
+ }
++/* HFPCLK clock integration */
++
++unsigned long sifive_prci_hfpclkplldiv_recalc_rate(struct clk_hw *hw,
++                                                 unsigned long parent_rate)
++{
++      struct __prci_clock *pc = clk_hw_to_prci_clock(hw);
++      struct __prci_data *pd = pc->pd;
++      u32 div = __prci_readl(pd, PRCI_HFPCLKPLLDIV_OFFSET);
++
++      return div_u64(parent_rate, div + 2);
++}
++
+ /*
+  * Core clock mux control
+  */
+@@ -271,6 +284,112 @@ void sifive_prci_coreclksel_use_corepll(struct __prci_data *pd)
+ }
+ /**
++ * sifive_prci_coreclksel_use_final_corepll() - switch the CORECLK mux to output
++ * FINAL_COREPLL
++ * @pd: struct __prci_data * for the PRCI containing the CORECLK mux reg
++ *
++ * Switch the CORECLK mux to the final COREPLL output clock; return once
++ * complete.
++ *
++ * Context: Any context.  Caller must prevent concurrent changes to the
++ *          PRCI_CORECLKSEL_OFFSET register.
++ */
++void sifive_prci_coreclksel_use_final_corepll(struct __prci_data *pd)
++{
++      u32 r;
++
++      r = __prci_readl(pd, PRCI_CORECLKSEL_OFFSET);
++      r &= ~PRCI_CORECLKSEL_CORECLKSEL_MASK;
++      __prci_writel(r, PRCI_CORECLKSEL_OFFSET, pd);
++
++      r = __prci_readl(pd, PRCI_CORECLKSEL_OFFSET);   /* barrier */
++}
++
++/**
++ * sifive_prci_corepllsel_use_dvfscorepll() - switch the COREPLL mux to
++ * output DVFS_COREPLL
++ * @pd: struct __prci_data * for the PRCI containing the COREPLL mux reg
++ *
++ * Switch the COREPLL mux to the DVFSCOREPLL output clock; return once complete.
++ *
++ * Context: Any context.  Caller must prevent concurrent changes to the
++ *          PRCI_COREPLLSEL_OFFSET register.
++ */
++void sifive_prci_corepllsel_use_dvfscorepll(struct __prci_data *pd)
++{
++      u32 r;
++
++      r = __prci_readl(pd, PRCI_COREPLLSEL_OFFSET);
++      r |= PRCI_COREPLLSEL_COREPLLSEL_MASK;
++      __prci_writel(r, PRCI_COREPLLSEL_OFFSET, pd);
++
++      r = __prci_readl(pd, PRCI_COREPLLSEL_OFFSET);   /* barrier */
++}
++
++/**
++ * sifive_prci_corepllsel_use_corepll() - switch the COREPLL mux to
++ * output COREPLL
++ * @pd: struct __prci_data * for the PRCI containing the COREPLL mux reg
++ *
++ * Switch the COREPLL mux to the COREPLL output clock; return once complete.
++ *
++ * Context: Any context.  Caller must prevent concurrent changes to the
++ *          PRCI_COREPLLSEL_OFFSET register.
++ */
++void sifive_prci_corepllsel_use_corepll(struct __prci_data *pd)
++{
++      u32 r;
++
++      r = __prci_readl(pd, PRCI_COREPLLSEL_OFFSET);
++      r &= ~PRCI_COREPLLSEL_COREPLLSEL_MASK;
++      __prci_writel(r, PRCI_COREPLLSEL_OFFSET, pd);
++
++      r = __prci_readl(pd, PRCI_COREPLLSEL_OFFSET);   /* barrier */
++}
++
++/**
++ * sifive_prci_hfpclkpllsel_use_hfclk() - switch the HFPCLKPLL mux to
++ * output HFCLK
++ * @pd: struct __prci_data * for the PRCI containing the HFPCLKPLL mux reg
++ *
++ * Switch the HFPCLKPLL mux to the HFCLK input source; return once complete.
++ *
++ * Context: Any context.  Caller must prevent concurrent changes to the
++ *          PRCI_HFPCLKPLLSEL_OFFSET register.
++ */
++void sifive_prci_hfpclkpllsel_use_hfclk(struct __prci_data *pd)
++{
++      u32 r;
++
++      r = __prci_readl(pd, PRCI_HFPCLKPLLSEL_OFFSET);
++      r |= PRCI_HFPCLKPLLSEL_HFPCLKPLLSEL_MASK;
++      __prci_writel(r, PRCI_HFPCLKPLLSEL_OFFSET, pd);
++
++      r = __prci_readl(pd, PRCI_HFPCLKPLLSEL_OFFSET); /* barrier */
++}
++
++/**
++ * sifive_prci_hfpclkpllsel_use_hfpclkpll() - switch the HFPCLKPLL mux to
++ * output HFPCLKPLL
++ * @pd: struct __prci_data * for the PRCI containing the HFPCLKPLL mux reg
++ *
++ * Switch the HFPCLKPLL mux to the HFPCLKPLL output clock; return once complete.
++ *
++ * Context: Any context.  Caller must prevent concurrent changes to the
++ *          PRCI_HFPCLKPLLSEL_OFFSET register.
++ */
++void sifive_prci_hfpclkpllsel_use_hfpclkpll(struct __prci_data *pd)
++{
++      u32 r;
++
++      r = __prci_readl(pd, PRCI_HFPCLKPLLSEL_OFFSET);
++      r &= ~PRCI_HFPCLKPLLSEL_HFPCLKPLLSEL_MASK;
++      __prci_writel(r, PRCI_HFPCLKPLLSEL_OFFSET, pd);
++
++      r = __prci_readl(pd, PRCI_HFPCLKPLLSEL_OFFSET); /* barrier */
++}
++
++/**
+  * __prci_register_clocks() - register clock controls in the PRCI
+  * @dev: Linux struct device
+  * @pd: The pointer for PRCI per-device instance data
+@@ -377,6 +496,7 @@ static int sifive_prci_probe(struct platform_device *pdev)
+ static const struct of_device_id sifive_prci_of_match[] = {
+       {.compatible = "sifive,fu540-c000-prci", .data = &prci_clk_fu540},
++      {.compatible = "sifive,fu740-c000-prci", .data = &prci_clk_fu740},
+       {}
+ };
+diff --git a/drivers/clk/sifive/sifive-prci.h b/drivers/clk/sifive/sifive-prci.h
+index 280df63..7e509df 100644
+--- a/drivers/clk/sifive/sifive-prci.h
++++ b/drivers/clk/sifive/sifive-prci.h
+@@ -117,6 +117,87 @@
+ #define PRCI_CLKMUXSTATUSREG_TLCLKSEL_STATUS_MASK                     \
+               (0x1 << PRCI_CLKMUXSTATUSREG_TLCLKSEL_STATUS_SHIFT)
++/* CLTXPLLCFG0 */
++#define PRCI_CLTXPLLCFG0_OFFSET               0x30
++#define PRCI_CLTXPLLCFG0_DIVR_SHIFT   0
++#define PRCI_CLTXPLLCFG0_DIVR_MASK    (0x3f << PRCI_CLTXPLLCFG0_DIVR_SHIFT)
++#define PRCI_CLTXPLLCFG0_DIVF_SHIFT   6
++#define PRCI_CLTXPLLCFG0_DIVF_MASK    (0x1ff << PRCI_CLTXPLLCFG0_DIVF_SHIFT)
++#define PRCI_CLTXPLLCFG0_DIVQ_SHIFT   15
++#define PRCI_CLTXPLLCFG0_DIVQ_MASK    (0x7 << PRCI_CLTXPLLCFG0_DIVQ_SHIFT)
++#define PRCI_CLTXPLLCFG0_RANGE_SHIFT  18
++#define PRCI_CLTXPLLCFG0_RANGE_MASK   (0x7 << PRCI_CLTXPLLCFG0_RANGE_SHIFT)
++#define PRCI_CLTXPLLCFG0_BYPASS_SHIFT 24
++#define PRCI_CLTXPLLCFG0_BYPASS_MASK  (0x1 << PRCI_CLTXPLLCFG0_BYPASS_SHIFT)
++#define PRCI_CLTXPLLCFG0_FSE_SHIFT    25
++#define PRCI_CLTXPLLCFG0_FSE_MASK     (0x1 << PRCI_CLTXPLLCFG0_FSE_SHIFT)
++#define PRCI_CLTXPLLCFG0_LOCK_SHIFT   31
++#define PRCI_CLTXPLLCFG0_LOCK_MASK    (0x1 << PRCI_CLTXPLLCFG0_LOCK_SHIFT)
++
++/* CLTXPLLCFG1 */
++#define PRCI_CLTXPLLCFG1_OFFSET               0x34
++#define PRCI_CLTXPLLCFG1_CKE_SHIFT    31
++#define PRCI_CLTXPLLCFG1_CKE_MASK     (0x1 << PRCI_CLTXPLLCFG1_CKE_SHIFT)
++
++/* DVFSCOREPLLCFG0 */
++#define PRCI_DVFSCOREPLLCFG0_OFFSET   0x38
++
++/* DVFSCOREPLLCFG1 */
++#define PRCI_DVFSCOREPLLCFG1_OFFSET   0x3c
++#define PRCI_DVFSCOREPLLCFG1_CKE_SHIFT        31
++#define PRCI_DVFSCOREPLLCFG1_CKE_MASK (0x1 << PRCI_DVFSCOREPLLCFG1_CKE_SHIFT)
++
++/* COREPLLSEL */
++#define PRCI_COREPLLSEL_OFFSET                        0x40
++#define PRCI_COREPLLSEL_COREPLLSEL_SHIFT      0
++#define PRCI_COREPLLSEL_COREPLLSEL_MASK                                       \
++              (0x1 << PRCI_COREPLLSEL_COREPLLSEL_SHIFT)
++
++/* HFPCLKPLLCFG0 */
++#define PRCI_HFPCLKPLLCFG0_OFFSET             0x50
++#define PRCI_HFPCLKPLL_CFG0_DIVR_SHIFT                0
++#define PRCI_HFPCLKPLL_CFG0_DIVR_MASK                                 \
++              (0x3f << PRCI_HFPCLKPLLCFG0_DIVR_SHIFT)
++#define PRCI_HFPCLKPLL_CFG0_DIVF_SHIFT                6
++#define PRCI_HFPCLKPLL_CFG0_DIVF_MASK                                 \
++              (0x1ff << PRCI_HFPCLKPLLCFG0_DIVF_SHIFT)
++#define PRCI_HFPCLKPLL_CFG0_DIVQ_SHIFT                15
++#define PRCI_HFPCLKPLL_CFG0_DIVQ_MASK                                 \
++              (0x7 << PRCI_HFPCLKPLLCFG0_DIVQ_SHIFT)
++#define PRCI_HFPCLKPLL_CFG0_RANGE_SHIFT               18
++#define PRCI_HFPCLKPLL_CFG0_RANGE_MASK                                        \
++              (0x7 << PRCI_HFPCLKPLLCFG0_RANGE_SHIFT)
++#define PRCI_HFPCLKPLL_CFG0_BYPASS_SHIFT      24
++#define PRCI_HFPCLKPLL_CFG0_BYPASS_MASK                                       \
++              (0x1 << PRCI_HFPCLKPLLCFG0_BYPASS_SHIFT)
++#define PRCI_HFPCLKPLL_CFG0_FSE_SHIFT         25
++#define PRCI_HFPCLKPLL_CFG0_FSE_MASK                                  \
++              (0x1 << PRCI_HFPCLKPLLCFG0_FSE_SHIFT)
++#define PRCI_HFPCLKPLL_CFG0_LOCK_SHIFT                31
++#define PRCI_HFPCLKPLL_CFG0_LOCK_MASK                                 \
++              (0x1 << PRCI_HFPCLKPLLCFG0_LOCK_SHIFT)
++
++/* HFPCLKPLLCFG1 */
++#define PRCI_HFPCLKPLLCFG1_OFFSET             0x54
++#define PRCI_HFPCLKPLLCFG1_CKE_SHIFT          31
++#define PRCI_HFPCLKPLLCFG1_CKE_MASK                                   \
++              (0x1 << PRCI_HFPCLKPLLCFG1_CKE_SHIFT)
++
++/* HFPCLKPLLSEL */
++#define PRCI_HFPCLKPLLSEL_OFFSET              0x58
++#define PRCI_HFPCLKPLLSEL_HFPCLKPLLSEL_SHIFT  0
++#define PRCI_HFPCLKPLLSEL_HFPCLKPLLSEL_MASK                           \
++              (0x1 << PRCI_HFPCLKPLLSEL_HFPCLKPLLSEL_SHIFT)
++
++/* HFPCLKPLLDIV */
++#define PRCI_HFPCLKPLLDIV_OFFSET              0x5c
++
++/* PRCIPLL */
++#define PRCI_PRCIPLL_OFFSET                   0xe0
++
++/* PROCMONCFG */
++#define PRCI_PROCMONCFG_OFFSET                        0xf0
++
+ /*
+  * Private structures
+  */
+@@ -187,6 +268,11 @@ struct prci_clk_desc {
+ /* Core clock mux control */
+ void sifive_prci_coreclksel_use_hfclk(struct __prci_data *pd);
+ void sifive_prci_coreclksel_use_corepll(struct __prci_data *pd);
++void sifive_prci_coreclksel_use_final_corepll(struct __prci_data *pd);
++void sifive_prci_corepllsel_use_dvfscorepll(struct __prci_data *pd);
++void sifive_prci_corepllsel_use_corepll(struct __prci_data *pd);
++void sifive_prci_hfpclkpllsel_use_hfclk(struct __prci_data *pd);
++void sifive_prci_hfpclkpllsel_use_hfpclkpll(struct __prci_data *pd);
+ /* Linux clock framework integration */
+ long sifive_prci_wrpll_round_rate(struct clk_hw *hw, unsigned long rate,
+@@ -197,5 +283,7 @@ unsigned long sifive_prci_wrpll_recalc_rate(struct clk_hw *hw,
+                                           unsigned long parent_rate);
+ unsigned long sifive_prci_tlclksel_recalc_rate(struct clk_hw *hw,
+                                              unsigned long parent_rate);
++unsigned long sifive_prci_hfpclkplldiv_recalc_rate(struct clk_hw *hw,
++                                                 unsigned long parent_rate);
+ #endif /* __SIFIVE_CLK_SIFIVE_PRCI_H */
+diff --git a/include/dt-bindings/clock/sifive-fu740-prci.h b/include/dt-bindings/clock/sifive-fu740-prci.h
+new file mode 100644
+index 00000000..cd7706e
+--- /dev/null
++++ b/include/dt-bindings/clock/sifive-fu740-prci.h
+@@ -0,0 +1,23 @@
++/* SPDX-License-Identifier: (GPL-2.0 OR MIT) */
++/*
++ * Copyright (C) 2019 SiFive, Inc.
++ * Wesley Terpstra
++ * Paul Walmsley
++ * Zong Li
++ */
++
++#ifndef __DT_BINDINGS_CLOCK_SIFIVE_FU740_PRCI_H
++#define __DT_BINDINGS_CLOCK_SIFIVE_FU740_PRCI_H
++
++/* Clock indexes for use by Device Tree data and the PRCI driver */
++
++#define PRCI_CLK_COREPLL             0
++#define PRCI_CLK_DDRPLL                      1
++#define PRCI_CLK_GEMGXLPLL           2
++#define PRCI_CLK_DVFSCOREPLL         3
++#define PRCI_CLK_HFPCLKPLL           4
++#define PRCI_CLK_CLTXPLL             5
++#define PRCI_CLK_TLCLK                       6
++#define PRCI_CLK_PCLK                7
++
++#endif        /* __DT_BINDINGS_CLOCK_SIFIVE_FU740_PRCI_H */
+-- 
+2.7.4
+
diff --git a/target/linux/hifiveu/patches-5.10/0004-clk-sifive-Fix-the-wrong-bit-field-shift.patch b/target/linux/hifiveu/patches-5.10/0004-clk-sifive-Fix-the-wrong-bit-field-shift.patch
new file mode 100644 (file)
index 0000000..05b7951
--- /dev/null
@@ -0,0 +1,38 @@
+From ff2bcef458e1fc95c6f3da7304df4119628f92c5 Mon Sep 17 00:00:00 2001
+From: Zong Li <zong.li@sifive.com>
+Date: Wed, 9 Dec 2020 17:49:15 +0800
+Subject: [PATCH 04/29] clk: sifive: Fix the wrong bit field shift
+
+The clk enable bit should be 31 instead of 24.
+
+Signed-off-by: Zong Li <zong.li@sifive.com>
+Reported-by: Pragnesh Patel <pragnesh.patel@sifive.com>
+---
+ drivers/clk/sifive/sifive-prci.h | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+diff --git a/drivers/clk/sifive/sifive-prci.h b/drivers/clk/sifive/sifive-prci.h
+index 7e509df..88493f3 100644
+--- a/drivers/clk/sifive/sifive-prci.h
++++ b/drivers/clk/sifive/sifive-prci.h
+@@ -59,7 +59,7 @@
+ /* DDRPLLCFG1 */
+ #define PRCI_DDRPLLCFG1_OFFSET                0x10
+-#define PRCI_DDRPLLCFG1_CKE_SHIFT     24
++#define PRCI_DDRPLLCFG1_CKE_SHIFT     31
+ #define PRCI_DDRPLLCFG1_CKE_MASK      (0x1 << PRCI_DDRPLLCFG1_CKE_SHIFT)
+ /* GEMGXLPLLCFG0 */
+@@ -81,7 +81,7 @@
+ /* GEMGXLPLLCFG1 */
+ #define PRCI_GEMGXLPLLCFG1_OFFSET     0x20
+-#define PRCI_GEMGXLPLLCFG1_CKE_SHIFT  24
++#define PRCI_GEMGXLPLLCFG1_CKE_SHIFT  31
+ #define PRCI_GEMGXLPLLCFG1_CKE_MASK   (0x1 << PRCI_GEMGXLPLLCFG1_CKE_SHIFT)
+ /* CORECLKSEL */
+-- 
+2.7.4
+
diff --git a/target/linux/hifiveu/patches-5.10/0005-clk-sifive-Add-clock-enable-and-disable-ops.patch b/target/linux/hifiveu/patches-5.10/0005-clk-sifive-Add-clock-enable-and-disable-ops.patch
new file mode 100644 (file)
index 0000000..67fe101
--- /dev/null
@@ -0,0 +1,285 @@
+From 37338a04280c6add6e376ed03d094276fb2759ba Mon Sep 17 00:00:00 2001
+From: Pragnesh Patel <pragnesh.patel@sifive.com>
+Date: Wed, 9 Dec 2020 17:49:16 +0800
+Subject: [PATCH 05/29] clk: sifive: Add clock enable and disable ops
+
+Add new functions "sifive_prci_clock_enable(), sifive_prci_clock_disable()
+and sifive_clk_is_enabled()" to enable or disable the PRCI clock
+
+Signed-off-by: Pragnesh Patel <pragnesh.patel@sifive.com>
+Tested-by: Zong Li <zong.li@sifive.com>
+---
+ drivers/clk/sifive/fu540-prci.c  |  6 ++++
+ drivers/clk/sifive/fu740-prci.c  |  9 +++++
+ drivers/clk/sifive/sifive-prci.c | 77 +++++++++++++++++++++++++++++++++++-----
+ drivers/clk/sifive/sifive-prci.h | 10 ++++++
+ 4 files changed, 93 insertions(+), 9 deletions(-)
+
+diff --git a/drivers/clk/sifive/fu540-prci.c b/drivers/clk/sifive/fu540-prci.c
+index e2353de..3b55883 100644
+--- a/drivers/clk/sifive/fu540-prci.c
++++ b/drivers/clk/sifive/fu540-prci.c
+@@ -24,16 +24,19 @@
+ static struct __prci_wrpll_data __prci_corepll_data = {
+       .cfg0_offs = PRCI_COREPLLCFG0_OFFSET,
++      .cfg1_offs = PRCI_COREPLLCFG1_OFFSET,
+       .enable_bypass = sifive_prci_coreclksel_use_hfclk,
+       .disable_bypass = sifive_prci_coreclksel_use_corepll,
+ };
+ static struct __prci_wrpll_data __prci_ddrpll_data = {
+       .cfg0_offs = PRCI_DDRPLLCFG0_OFFSET,
++      .cfg1_offs = PRCI_DDRPLLCFG1_OFFSET,
+ };
+ static struct __prci_wrpll_data __prci_gemgxlpll_data = {
+       .cfg0_offs = PRCI_GEMGXLPLLCFG0_OFFSET,
++      .cfg1_offs = PRCI_GEMGXLPLLCFG1_OFFSET,
+ };
+ /* Linux clock framework integration */
+@@ -42,6 +45,9 @@ static const struct clk_ops sifive_fu540_prci_wrpll_clk_ops = {
+       .set_rate = sifive_prci_wrpll_set_rate,
+       .round_rate = sifive_prci_wrpll_round_rate,
+       .recalc_rate = sifive_prci_wrpll_recalc_rate,
++      .enable = sifive_prci_clock_enable,
++      .disable = sifive_prci_clock_disable,
++      .is_enabled = sifive_clk_is_enabled,
+ };
+ static const struct clk_ops sifive_fu540_prci_wrpll_ro_clk_ops = {
+diff --git a/drivers/clk/sifive/fu740-prci.c b/drivers/clk/sifive/fu740-prci.c
+index 41ddd44..db83002 100644
+--- a/drivers/clk/sifive/fu740-prci.c
++++ b/drivers/clk/sifive/fu740-prci.c
+@@ -12,32 +12,38 @@
+ static struct __prci_wrpll_data __prci_corepll_data = {
+       .cfg0_offs = PRCI_COREPLLCFG0_OFFSET,
++      .cfg1_offs = PRCI_COREPLLCFG1_OFFSET,
+       .enable_bypass = sifive_prci_coreclksel_use_hfclk,
+       .disable_bypass = sifive_prci_coreclksel_use_final_corepll,
+ };
+ static struct __prci_wrpll_data __prci_ddrpll_data = {
+       .cfg0_offs = PRCI_DDRPLLCFG0_OFFSET,
++      .cfg1_offs = PRCI_DDRPLLCFG1_OFFSET,
+ };
+ static struct __prci_wrpll_data __prci_gemgxlpll_data = {
+       .cfg0_offs = PRCI_GEMGXLPLLCFG0_OFFSET,
++      .cfg1_offs = PRCI_GEMGXLPLLCFG1_OFFSET,
+ };
+ static struct __prci_wrpll_data __prci_dvfscorepll_data = {
+       .cfg0_offs = PRCI_DVFSCOREPLLCFG0_OFFSET,
++      .cfg1_offs = PRCI_DVFSCOREPLLCFG1_OFFSET,
+       .enable_bypass = sifive_prci_corepllsel_use_corepll,
+       .disable_bypass = sifive_prci_corepllsel_use_dvfscorepll,
+ };
+ static struct __prci_wrpll_data __prci_hfpclkpll_data = {
+       .cfg0_offs = PRCI_HFPCLKPLLCFG0_OFFSET,
++      .cfg1_offs = PRCI_HFPCLKPLLCFG1_OFFSET,
+       .enable_bypass = sifive_prci_hfpclkpllsel_use_hfclk,
+       .disable_bypass = sifive_prci_hfpclkpllsel_use_hfpclkpll,
+ };
+ static struct __prci_wrpll_data __prci_cltxpll_data = {
+       .cfg0_offs = PRCI_CLTXPLLCFG0_OFFSET,
++      .cfg1_offs = PRCI_CLTXPLLCFG1_OFFSET,
+ };
+ /* Linux clock framework integration */
+@@ -46,6 +52,9 @@ static const struct clk_ops sifive_fu740_prci_wrpll_clk_ops = {
+       .set_rate = sifive_prci_wrpll_set_rate,
+       .round_rate = sifive_prci_wrpll_round_rate,
+       .recalc_rate = sifive_prci_wrpll_recalc_rate,
++      .enable = sifive_prci_clock_enable,
++      .disable = sifive_prci_clock_disable,
++      .is_enabled = sifive_clk_is_enabled,
+ };
+ static const struct clk_ops sifive_fu740_prci_wrpll_ro_clk_ops = {
+diff --git a/drivers/clk/sifive/sifive-prci.c b/drivers/clk/sifive/sifive-prci.c
+index cc4b4c6..c78b042 100644
+--- a/drivers/clk/sifive/sifive-prci.c
++++ b/drivers/clk/sifive/sifive-prci.c
+@@ -113,7 +113,7 @@ static u32 __prci_wrpll_pack(const struct wrpll_cfg *c)
+ }
+ /**
+- * __prci_wrpll_read_cfg() - read the WRPLL configuration from the PRCI
++ * __prci_wrpll_read_cfg0() - read the WRPLL configuration from the PRCI
+  * @pd: PRCI context
+  * @pwd: PRCI WRPLL metadata
+  *
+@@ -124,14 +124,14 @@ static u32 __prci_wrpll_pack(const struct wrpll_cfg *c)
+  * Context: Any context.  Caller must prevent the records pointed to by
+  *          @pd and @pwd from changing during execution.
+  */
+-static void __prci_wrpll_read_cfg(struct __prci_data *pd,
+-                                struct __prci_wrpll_data *pwd)
++static void __prci_wrpll_read_cfg0(struct __prci_data *pd,
++                                 struct __prci_wrpll_data *pwd)
+ {
+       __prci_wrpll_unpack(&pwd->c, __prci_readl(pd, pwd->cfg0_offs));
+ }
+ /**
+- * __prci_wrpll_write_cfg() - write WRPLL configuration into the PRCI
++ * __prci_wrpll_write_cfg0() - write WRPLL configuration into the PRCI
+  * @pd: PRCI context
+  * @pwd: PRCI WRPLL metadata
+  * @c: WRPLL configuration record to write
+@@ -144,15 +144,29 @@ static void __prci_wrpll_read_cfg(struct __prci_data *pd,
+  * Context: Any context.  Caller must prevent the records pointed to by
+  *          @pd and @pwd from changing during execution.
+  */
+-static void __prci_wrpll_write_cfg(struct __prci_data *pd,
+-                                 struct __prci_wrpll_data *pwd,
+-                                 struct wrpll_cfg *c)
++static void __prci_wrpll_write_cfg0(struct __prci_data *pd,
++                                  struct __prci_wrpll_data *pwd,
++                                  struct wrpll_cfg *c)
+ {
+       __prci_writel(__prci_wrpll_pack(c), pwd->cfg0_offs, pd);
+       memcpy(&pwd->c, c, sizeof(*c));
+ }
++/**
++ * __prci_wrpll_write_cfg1() - write Clock enable/disable configuration
++ * into the PRCI
++ * @pd: PRCI context
++ * @pwd: PRCI WRPLL metadata
++ * @enable: Clock enable or disable value
++ */
++static void __prci_wrpll_write_cfg1(struct __prci_data *pd,
++                                  struct __prci_wrpll_data *pwd,
++                                  u32 enable)
++{
++      __prci_writel(enable, pwd->cfg1_offs, pd);
++}
++
+ /*
+  * Linux clock framework integration
+  *
+@@ -199,16 +213,61 @@ int sifive_prci_wrpll_set_rate(struct clk_hw *hw,
+       if (pwd->enable_bypass)
+               pwd->enable_bypass(pd);
+-      __prci_wrpll_write_cfg(pd, pwd, &pwd->c);
++      __prci_wrpll_write_cfg0(pd, pwd, &pwd->c);
+       udelay(wrpll_calc_max_lock_us(&pwd->c));
++      return 0;
++}
++
++int sifive_clk_is_enabled(struct clk_hw *hw)
++{
++      struct __prci_clock *pc = clk_hw_to_prci_clock(hw);
++      struct __prci_wrpll_data *pwd = pc->pwd;
++      struct __prci_data *pd = pc->pd;
++      u32 r;
++
++      r = __prci_readl(pd, pwd->cfg1_offs);
++
++      if (r & PRCI_COREPLLCFG1_CKE_MASK)
++              return 1;
++      else
++              return 0;
++}
++
++int sifive_prci_clock_enable(struct clk_hw *hw)
++{
++      struct __prci_clock *pc = clk_hw_to_prci_clock(hw);
++      struct __prci_wrpll_data *pwd = pc->pwd;
++      struct __prci_data *pd = pc->pd;
++
++      if (sifive_clk_is_enabled(hw))
++              return 0;
++
++      __prci_wrpll_write_cfg1(pd, pwd, PRCI_COREPLLCFG1_CKE_MASK);
++
+       if (pwd->disable_bypass)
+               pwd->disable_bypass(pd);
+       return 0;
+ }
++void sifive_prci_clock_disable(struct clk_hw *hw)
++{
++      struct __prci_clock *pc = clk_hw_to_prci_clock(hw);
++      struct __prci_wrpll_data *pwd = pc->pwd;
++      struct __prci_data *pd = pc->pd;
++      u32 r;
++
++      if (pwd->enable_bypass)
++              pwd->enable_bypass(pd);
++
++      r = __prci_readl(pd, pwd->cfg1_offs);
++      r &= ~PRCI_COREPLLCFG1_CKE_MASK;
++
++      __prci_wrpll_write_cfg1(pd, pwd, r);
++}
++
+ /* TLCLKSEL clock integration */
+ unsigned long sifive_prci_tlclksel_recalc_rate(struct clk_hw *hw,
+@@ -427,7 +486,7 @@ static int __prci_register_clocks(struct device *dev, struct __prci_data *pd,
+               pic->pd = pd;
+               if (pic->pwd)
+-                      __prci_wrpll_read_cfg(pd, pic->pwd);
++                      __prci_wrpll_read_cfg0(pd, pic->pwd);
+               r = devm_clk_hw_register(dev, &pic->hw);
+               if (r) {
+diff --git a/drivers/clk/sifive/sifive-prci.h b/drivers/clk/sifive/sifive-prci.h
+index 88493f3..dbdbd17 100644
+--- a/drivers/clk/sifive/sifive-prci.h
++++ b/drivers/clk/sifive/sifive-prci.h
+@@ -40,6 +40,11 @@
+ #define PRCI_COREPLLCFG0_LOCK_SHIFT   31
+ #define PRCI_COREPLLCFG0_LOCK_MASK    (0x1 << PRCI_COREPLLCFG0_LOCK_SHIFT)
++/* COREPLLCFG1 */
++#define PRCI_COREPLLCFG1_OFFSET               0x8
++#define PRCI_COREPLLCFG1_CKE_SHIFT    31
++#define PRCI_COREPLLCFG1_CKE_MASK     (0x1 << PRCI_COREPLLCFG1_CKE_SHIFT)
++
+ /* DDRPLLCFG0 */
+ #define PRCI_DDRPLLCFG0_OFFSET                0xc
+ #define PRCI_DDRPLLCFG0_DIVR_SHIFT    0
+@@ -220,6 +225,7 @@ struct __prci_data {
+  * @enable_bypass: fn ptr to code to bypass the WRPLL (if applicable; else NULL)
+  * @disable_bypass: fn ptr to code to not bypass the WRPLL (or NULL)
+  * @cfg0_offs: WRPLL CFG0 register offset (in bytes) from the PRCI base address
++ * @cfg1_offs: WRPLL CFG1 register offset (in bytes) from the PRCI base address
+  *
+  * @enable_bypass and @disable_bypass are used for WRPLL instances
+  * that contain a separate external glitchless clock mux downstream
+@@ -230,6 +236,7 @@ struct __prci_wrpll_data {
+       void (*enable_bypass)(struct __prci_data *pd);
+       void (*disable_bypass)(struct __prci_data *pd);
+       u8 cfg0_offs;
++      u8 cfg1_offs;
+ };
+ /**
+@@ -279,6 +286,9 @@ long sifive_prci_wrpll_round_rate(struct clk_hw *hw, unsigned long rate,
+                                 unsigned long *parent_rate);
+ int sifive_prci_wrpll_set_rate(struct clk_hw *hw, unsigned long rate,
+                              unsigned long parent_rate);
++int sifive_clk_is_enabled(struct clk_hw *hw);
++int sifive_prci_clock_enable(struct clk_hw *hw);
++void sifive_prci_clock_disable(struct clk_hw *hw);
+ unsigned long sifive_prci_wrpll_recalc_rate(struct clk_hw *hw,
+                                           unsigned long parent_rate);
+ unsigned long sifive_prci_tlclksel_recalc_rate(struct clk_hw *hw,
+-- 
+2.7.4
+
diff --git a/target/linux/hifiveu/patches-5.10/0006-dt-bindings-riscv-Update-DT-binding-docs-to-support-.patch b/target/linux/hifiveu/patches-5.10/0006-dt-bindings-riscv-Update-DT-binding-docs-to-support-.patch
new file mode 100644 (file)
index 0000000..8a0d566
--- /dev/null
@@ -0,0 +1,41 @@
+From 34d032292a2b6db16fc60e7c6706b1b508c2d932 Mon Sep 17 00:00:00 2001
+From: Yash Shah <yash.shah@sifive.com>
+Date: Tue, 8 Dec 2020 10:25:33 +0530
+Subject: [PATCH 06/29] dt-bindings: riscv: Update DT binding docs to support
+ SiFive FU740 SoC
+
+Add new compatible strings in cpus.yaml to support the E71 and U74 CPU
+cores ("harts") that are present on FU740-C000 SoC.
+
+Signed-off-by: Yash Shah <yash.shah@sifive.com>
+Reviewed-by: Rob Herring <robh@kernel.org>
+Reviewed-by: Bin Meng <bin.meng@windriver.com>
+---
+ Documentation/devicetree/bindings/riscv/cpus.yaml | 6 ++++++
+ 1 file changed, 6 insertions(+)
+
+diff --git a/Documentation/devicetree/bindings/riscv/cpus.yaml b/Documentation/devicetree/bindings/riscv/cpus.yaml
+index c6925e0..eb6843f 100644
+--- a/Documentation/devicetree/bindings/riscv/cpus.yaml
++++ b/Documentation/devicetree/bindings/riscv/cpus.yaml
+@@ -28,11 +28,17 @@ properties:
+       - items:
+           - enum:
+               - sifive,rocket0
++              - sifive,bullet0
+               - sifive,e5
++              - sifive,e7
+               - sifive,e51
++              - sifive,e71
+               - sifive,u54-mc
++              - sifive,u74-mc
+               - sifive,u54
++              - sifive,u74
+               - sifive,u5
++              - sifive,u7
+           - const: riscv
+       - const: riscv    # Simulator only
+     description:
+-- 
+2.7.4
+
diff --git a/target/linux/hifiveu/patches-5.10/0007-dt-bindings-spi-Update-DT-binding-docs-to-support-Si.patch b/target/linux/hifiveu/patches-5.10/0007-dt-bindings-spi-Update-DT-binding-docs-to-support-Si.patch
new file mode 100644 (file)
index 0000000..770fb3a
--- /dev/null
@@ -0,0 +1,43 @@
+From 8a3d7aa89632d354932a621eb4fe22c560a406bd Mon Sep 17 00:00:00 2001
+From: Yash Shah <yash.shah@sifive.com>
+Date: Tue, 8 Dec 2020 10:25:34 +0530
+Subject: [PATCH 07/29] dt-bindings: spi: Update DT binding docs to support
+ SiFive FU740 SoC
+
+Add new compatible strings to the DT binding documents to support SiFive
+FU740-C000.
+
+Signed-off-by: Yash Shah <yash.shah@sifive.com>
+---
+ Documentation/devicetree/bindings/spi/spi-sifive.yaml | 10 ++++++----
+ 1 file changed, 6 insertions(+), 4 deletions(-)
+
+diff --git a/Documentation/devicetree/bindings/spi/spi-sifive.yaml b/Documentation/devicetree/bindings/spi/spi-sifive.yaml
+index 56dcf1d..6e7e394 100644
+--- a/Documentation/devicetree/bindings/spi/spi-sifive.yaml
++++ b/Documentation/devicetree/bindings/spi/spi-sifive.yaml
+@@ -17,15 +17,17 @@ allOf:
+ properties:
+   compatible:
+     items:
+-      - const: sifive,fu540-c000-spi
++      - enum:
++          - sifive,fu540-c000-spi
++          - sifive,fu740-c000-spi
+       - const: sifive,spi0
+     description:
+       Should be "sifive,<chip>-spi" and "sifive,spi<version>".
+       Supported compatible strings are -
+-      "sifive,fu540-c000-spi" for the SiFive SPI v0 as integrated
+-      onto the SiFive FU540 chip, and "sifive,spi0" for the SiFive
+-      SPI v0 IP block with no chip integration tweaks.
++      "sifive,fu540-c000-spi" and "sifive,fu740-c000-spi" for the SiFive SPI v0
++      as integrated onto the SiFive FU540 and FU740 chip resp, and "sifive,spi0"
++      for the SiFive SPI v0 IP block with no chip integration tweaks.
+       Please refer to sifive-blocks-ip-versioning.txt for details
+       SPI RTL that corresponds to the IP block version numbers can be found here -
+-- 
+2.7.4
+
diff --git a/target/linux/hifiveu/patches-5.10/0008-dt-bindings-pwm-Update-DT-binding-docs-to-support-Si.patch b/target/linux/hifiveu/patches-5.10/0008-dt-bindings-pwm-Update-DT-binding-docs-to-support-Si.patch
new file mode 100644 (file)
index 0000000..0d53c58
--- /dev/null
@@ -0,0 +1,40 @@
+From 789dc44312525e9669d0c6e01ccfc01bbdfb0e10 Mon Sep 17 00:00:00 2001
+From: Yash Shah <yash.shah@sifive.com>
+Date: Tue, 8 Dec 2020 10:25:35 +0530
+Subject: [PATCH 08/29] dt-bindings: pwm: Update DT binding docs to support
+ SiFive FU740 SoC
+
+Add new compatible strings to the DT binding documents to support SiFive
+FU740-C000.
+
+Signed-off-by: Yash Shah <yash.shah@sifive.com>
+---
+ Documentation/devicetree/bindings/pwm/pwm-sifive.yaml | 9 ++++++---
+ 1 file changed, 6 insertions(+), 3 deletions(-)
+
+diff --git a/Documentation/devicetree/bindings/pwm/pwm-sifive.yaml b/Documentation/devicetree/bindings/pwm/pwm-sifive.yaml
+index 5ac2527..84e6691 100644
+--- a/Documentation/devicetree/bindings/pwm/pwm-sifive.yaml
++++ b/Documentation/devicetree/bindings/pwm/pwm-sifive.yaml
+@@ -25,12 +25,15 @@ description:
+ properties:
+   compatible:
+     items:
+-      - const: sifive,fu540-c000-pwm
++      - enum:
++          - sifive,fu540-c000-pwm
++          - sifive,fu740-c000-pwm
+       - const: sifive,pwm0
+     description:
+       Should be "sifive,<chip>-pwm" and "sifive,pwm<version>". Supported
+-      compatible strings are "sifive,fu540-c000-pwm" for the SiFive PWM v0
+-      as integrated onto the SiFive FU540 chip, and "sifive,pwm0" for the
++      compatible strings are "sifive,fu540-c000-pwm" and
++      "sifive,fu740-c000-pwm" for the SiFive PWM v0 as integrated onto the
++      SiFive FU540 and FU740 chip respectively, and "sifive,pwm0" for the
+       SiFive PWM v0 IP block with no chip integration tweaks.
+       Please refer to sifive-blocks-ip-versioning.txt for details.
+-- 
+2.7.4
+
diff --git a/target/linux/hifiveu/patches-5.10/0009-dt-bindings-serial-Update-DT-binding-docs-to-support.patch b/target/linux/hifiveu/patches-5.10/0009-dt-bindings-serial-Update-DT-binding-docs-to-support.patch
new file mode 100644 (file)
index 0000000..9efd9f7
--- /dev/null
@@ -0,0 +1,33 @@
+From 6bc4ee53eaffad7385babe568a7889b13752606f Mon Sep 17 00:00:00 2001
+From: Yash Shah <yash.shah@sifive.com>
+Date: Tue, 8 Dec 2020 10:25:36 +0530
+Subject: [PATCH 09/29] dt-bindings: serial: Update DT binding docs to support
+ SiFive FU740 SoC
+
+Add new compatible strings to the DT binding documents to support SiFive
+FU740-C000.
+
+Signed-off-by: Yash Shah <yash.shah@sifive.com>
+Reviewed-by: Rob Herring <robh@kernel.org>
+---
+ Documentation/devicetree/bindings/serial/sifive-serial.yaml | 4 +++-
+ 1 file changed, 3 insertions(+), 1 deletion(-)
+
+diff --git a/Documentation/devicetree/bindings/serial/sifive-serial.yaml b/Documentation/devicetree/bindings/serial/sifive-serial.yaml
+index 92283f6..3ac5c7f 100644
+--- a/Documentation/devicetree/bindings/serial/sifive-serial.yaml
++++ b/Documentation/devicetree/bindings/serial/sifive-serial.yaml
+@@ -17,7 +17,9 @@ allOf:
+ properties:
+   compatible:
+     items:
+-      - const: sifive,fu540-c000-uart
++      - enum:
++          - sifive,fu540-c000-uart
++          - sifive,fu740-c000-uart
+       - const: sifive,uart0
+     description:
+-- 
+2.7.4
+
diff --git a/target/linux/hifiveu/patches-5.10/0010-dt-bindings-gpio-Update-DT-binding-docs-to-support-S.patch b/target/linux/hifiveu/patches-5.10/0010-dt-bindings-gpio-Update-DT-binding-docs-to-support-S.patch
new file mode 100644 (file)
index 0000000..ca75f15
--- /dev/null
@@ -0,0 +1,33 @@
+From 9791e30869ff598c0faede92500d4d35c8bbba45 Mon Sep 17 00:00:00 2001
+From: Yash Shah <yash.shah@sifive.com>
+Date: Tue, 8 Dec 2020 10:25:37 +0530
+Subject: [PATCH 10/29] dt-bindings: gpio: Update DT binding docs to support
+ SiFive FU740 SoC
+
+Add new compatible strings to the DT binding documents to support SiFive
+FU740-C000.
+
+Signed-off-by: Yash Shah <yash.shah@sifive.com>
+Reviewed-by: Rob Herring <robh@kernel.org>
+---
+ Documentation/devicetree/bindings/gpio/sifive,gpio.yaml | 4 +++-
+ 1 file changed, 3 insertions(+), 1 deletion(-)
+
+diff --git a/Documentation/devicetree/bindings/gpio/sifive,gpio.yaml b/Documentation/devicetree/bindings/gpio/sifive,gpio.yaml
+index a0efd8d..ab22056 100644
+--- a/Documentation/devicetree/bindings/gpio/sifive,gpio.yaml
++++ b/Documentation/devicetree/bindings/gpio/sifive,gpio.yaml
+@@ -13,7 +13,9 @@ maintainers:
+ properties:
+   compatible:
+     items:
+-      - const: sifive,fu540-c000-gpio
++      - enum:
++          - sifive,fu540-c000-gpio
++          - sifive,fu740-c000-gpio
+       - const: sifive,gpio0
+   reg:
+-- 
+2.7.4
+
diff --git a/target/linux/hifiveu/patches-5.10/0011-dt-bindings-i2c-Update-DT-binding-docs-to-support-Si.patch b/target/linux/hifiveu/patches-5.10/0011-dt-bindings-i2c-Update-DT-binding-docs-to-support-Si.patch
new file mode 100644 (file)
index 0000000..2c6946e
--- /dev/null
@@ -0,0 +1,37 @@
+From 909e7d4601aa183dbdd3e8edb964e4c683a2c9e1 Mon Sep 17 00:00:00 2001
+From: Yash Shah <yash.shah@sifive.com>
+Date: Tue, 8 Dec 2020 10:25:38 +0530
+Subject: [PATCH 11/29] dt-bindings: i2c: Update DT binding docs to support
+ SiFive FU740 SoC
+
+Add new compatible strings to the DT binding documents to support SiFive
+FU740-C000.
+
+Signed-off-by: Yash Shah <yash.shah@sifive.com>
+Reviewed-by: Rob Herring <robh@kernel.org>
+---
+ Documentation/devicetree/bindings/i2c/i2c-ocores.txt | 8 ++++++--
+ 1 file changed, 6 insertions(+), 2 deletions(-)
+
+diff --git a/Documentation/devicetree/bindings/i2c/i2c-ocores.txt b/Documentation/devicetree/bindings/i2c/i2c-ocores.txt
+index 6b25a80..a37c945 100644
+--- a/Documentation/devicetree/bindings/i2c/i2c-ocores.txt
++++ b/Documentation/devicetree/bindings/i2c/i2c-ocores.txt
+@@ -5,8 +5,12 @@ Required properties:
+                     "aeroflexgaisler,i2cmst"
+                     "sifive,fu540-c000-i2c", "sifive,i2c0"
+                     For Opencore based I2C IP block reimplemented in
+-                    FU540-C000 SoC. Please refer to sifive-blocks-ip-versioning.txt
+-                    for additional details.
++                    FU540-C000 SoC.
++                    "sifive,fu740-c000-i2c", "sifive,i2c0"
++                    For Opencore based I2C IP block reimplemented in
++                    FU740-C000 SoC.
++                    Please refer to sifive-blocks-ip-versioning.txt for
++                    additional details.
+ - reg             : bus address start and address range size of device
+ - clocks          : handle to the controller clock; see the note below.
+                     Mutually exclusive with opencores,ip-clock-frequency
+-- 
+2.7.4
+
diff --git a/target/linux/hifiveu/patches-5.10/0012-riscv-dts-add-initial-support-for-the-SiFive-FU740-C.patch b/target/linux/hifiveu/patches-5.10/0012-riscv-dts-add-initial-support-for-the-SiFive-FU740-C.patch
new file mode 100644 (file)
index 0000000..2593ae8
--- /dev/null
@@ -0,0 +1,320 @@
+From 7d2e730f1281b5530e55ebca1b0d9165e0298c00 Mon Sep 17 00:00:00 2001
+From: Yash Shah <yash.shah@sifive.com>
+Date: Tue, 8 Dec 2020 10:25:39 +0530
+Subject: [PATCH 12/29] riscv: dts: add initial support for the SiFive
+ FU740-C000 SoC
+
+Add initial support for the SiFive FU540-C000 SoC. FU740-C000 is built
+around the SiFIve U7 Core Complex and a TileLink interconnect.
+
+This file is expected to grow as more device drivers are added to the
+kernel.
+
+Signed-off-by: Yash Shah <yash.shah@sifive.com>
+---
+ arch/riscv/boot/dts/sifive/fu740-c000.dtsi | 293 +++++++++++++++++++++++++++++
+ 1 file changed, 293 insertions(+)
+ create mode 100644 arch/riscv/boot/dts/sifive/fu740-c000.dtsi
+
+diff --git a/arch/riscv/boot/dts/sifive/fu740-c000.dtsi b/arch/riscv/boot/dts/sifive/fu740-c000.dtsi
+new file mode 100644
+index 00000000..eeb4f8c3
+--- /dev/null
++++ b/arch/riscv/boot/dts/sifive/fu740-c000.dtsi
+@@ -0,0 +1,293 @@
++// SPDX-License-Identifier: (GPL-2.0 OR MIT)
++/* Copyright (c) 2020 SiFive, Inc */
++
++/dts-v1/;
++
++#include <dt-bindings/clock/sifive-fu740-prci.h>
++
++/ {
++      #address-cells = <2>;
++      #size-cells = <2>;
++      compatible = "sifive,fu740-c000", "sifive,fu740";
++
++      aliases {
++              serial0 = &uart0;
++              serial1 = &uart1;
++              ethernet0 = &eth0;
++      };
++
++      chosen {
++      };
++
++      cpus {
++              #address-cells = <1>;
++              #size-cells = <0>;
++              cpu0: cpu@0 {
++                      compatible = "sifive,bullet0", "riscv";
++                      device_type = "cpu";
++                      i-cache-block-size = <64>;
++                      i-cache-sets = <128>;
++                      i-cache-size = <16384>;
++                      next-level-cache = <&ccache>;
++                      reg = <0x0>;
++                      riscv,isa = "rv64imac";
++                      status = "disabled";
++                      cpu0_intc: interrupt-controller {
++                              #interrupt-cells = <1>;
++                              compatible = "riscv,cpu-intc";
++                              interrupt-controller;
++                      };
++              };
++              cpu1: cpu@1 {
++                      compatible = "sifive,bullet0", "riscv";
++                      d-cache-block-size = <64>;
++                      d-cache-sets = <64>;
++                      d-cache-size = <32768>;
++                      d-tlb-sets = <1>;
++                      d-tlb-size = <40>;
++                      device_type = "cpu";
++                      i-cache-block-size = <64>;
++                      i-cache-sets = <128>;
++                      i-cache-size = <32768>;
++                      i-tlb-sets = <1>;
++                      i-tlb-size = <40>;
++                      mmu-type = "riscv,sv39";
++                      next-level-cache = <&ccache>;
++                      reg = <0x1>;
++                      riscv,isa = "rv64imafdc";
++                      tlb-split;
++                      cpu1_intc: interrupt-controller {
++                              #interrupt-cells = <1>;
++                              compatible = "riscv,cpu-intc";
++                              interrupt-controller;
++                      };
++              };
++              cpu2: cpu@2 {
++                      compatible = "sifive,bullet0", "riscv";
++                      d-cache-block-size = <64>;
++                      d-cache-sets = <64>;
++                      d-cache-size = <32768>;
++                      d-tlb-sets = <1>;
++                      d-tlb-size = <40>;
++                      device_type = "cpu";
++                      i-cache-block-size = <64>;
++                      i-cache-sets = <128>;
++                      i-cache-size = <32768>;
++                      i-tlb-sets = <1>;
++                      i-tlb-size = <40>;
++                      mmu-type = "riscv,sv39";
++                      next-level-cache = <&ccache>;
++                      reg = <0x2>;
++                      riscv,isa = "rv64imafdc";
++                      tlb-split;
++                      cpu2_intc: interrupt-controller {
++                              #interrupt-cells = <1>;
++                              compatible = "riscv,cpu-intc";
++                              interrupt-controller;
++                      };
++              };
++              cpu3: cpu@3 {
++                      compatible = "sifive,bullet0", "riscv";
++                      d-cache-block-size = <64>;
++                      d-cache-sets = <64>;
++                      d-cache-size = <32768>;
++                      d-tlb-sets = <1>;
++                      d-tlb-size = <40>;
++                      device_type = "cpu";
++                      i-cache-block-size = <64>;
++                      i-cache-sets = <128>;
++                      i-cache-size = <32768>;
++                      i-tlb-sets = <1>;
++                      i-tlb-size = <40>;
++                      mmu-type = "riscv,sv39";
++                      next-level-cache = <&ccache>;
++                      reg = <0x3>;
++                      riscv,isa = "rv64imafdc";
++                      tlb-split;
++                      cpu3_intc: interrupt-controller {
++                              #interrupt-cells = <1>;
++                              compatible = "riscv,cpu-intc";
++                              interrupt-controller;
++                      };
++              };
++              cpu4: cpu@4 {
++                      compatible = "sifive,bullet0", "riscv";
++                      d-cache-block-size = <64>;
++                      d-cache-sets = <64>;
++                      d-cache-size = <32768>;
++                      d-tlb-sets = <1>;
++                      d-tlb-size = <40>;
++                      device_type = "cpu";
++                      i-cache-block-size = <64>;
++                      i-cache-sets = <128>;
++                      i-cache-size = <32768>;
++                      i-tlb-sets = <1>;
++                      i-tlb-size = <40>;
++                      mmu-type = "riscv,sv39";
++                      next-level-cache = <&ccache>;
++                      reg = <0x4>;
++                      riscv,isa = "rv64imafdc";
++                      tlb-split;
++                      cpu4_intc: interrupt-controller {
++                              #interrupt-cells = <1>;
++                              compatible = "riscv,cpu-intc";
++                              interrupt-controller;
++                      };
++              };
++      };
++      soc {
++              #address-cells = <2>;
++              #size-cells = <2>;
++              compatible = "simple-bus";
++              ranges;
++              plic0: interrupt-controller@c000000 {
++                      #interrupt-cells = <1>;
++                      #address-cells = <0>;
++                      compatible = "sifive,fu540-c000-plic", "sifive,plic-1.0.0";
++                      reg = <0x0 0xc000000 0x0 0x4000000>;
++                      riscv,ndev = <69>;
++                      interrupt-controller;
++                      interrupts-extended = <
++                              &cpu0_intc 0xffffffff
++                              &cpu1_intc 0xffffffff &cpu1_intc 9
++                              &cpu2_intc 0xffffffff &cpu2_intc 9
++                              &cpu3_intc 0xffffffff &cpu3_intc 9
++                              &cpu4_intc 0xffffffff &cpu4_intc 9>;
++              };
++              prci: clock-controller@10000000 {
++                      compatible = "sifive,fu740-c000-prci";
++                      reg = <0x0 0x10000000 0x0 0x1000>;
++                      clocks = <&hfclk>, <&rtcclk>;
++                      #clock-cells = <1>;
++              };
++              uart0: serial@10010000 {
++                      compatible = "sifive,fu740-c000-uart", "sifive,uart0";
++                      reg = <0x0 0x10010000 0x0 0x1000>;
++                      interrupt-parent = <&plic0>;
++                      interrupts = <39>;
++                      clocks = <&prci PRCI_CLK_PCLK>;
++                      status = "disabled";
++              };
++              uart1: serial@10011000 {
++                      compatible = "sifive,fu740-c000-uart", "sifive,uart0";
++                      reg = <0x0 0x10011000 0x0 0x1000>;
++                      interrupt-parent = <&plic0>;
++                      interrupts = <40>;
++                      clocks = <&prci PRCI_CLK_PCLK>;
++                      status = "disabled";
++              };
++              i2c0: i2c@10030000 {
++                      compatible = "sifive,fu740-c000-i2c", "sifive,i2c0";
++                      reg = <0x0 0x10030000 0x0 0x1000>;
++                      interrupt-parent = <&plic0>;
++                      interrupts = <52>;
++                      clocks = <&prci PRCI_CLK_PCLK>;
++                      reg-shift = <2>;
++                      reg-io-width = <1>;
++                      #address-cells = <1>;
++                      #size-cells = <0>;
++                      status = "disabled";
++              };
++              i2c1: i2c@10031000 {
++                      compatible = "sifive,fu740-c000-i2c", "sifive,i2c0";
++                      reg = <0x0 0x10031000 0x0 0x1000>;
++                      interrupt-parent = <&plic0>;
++                      interrupts = <53>;
++                      clocks = <&prci PRCI_CLK_PCLK>;
++                      reg-shift = <2>;
++                      reg-io-width = <1>;
++                      #address-cells = <1>;
++                      #size-cells = <0>;
++                      status = "disabled";
++              };
++              qspi0: spi@10040000 {
++                      compatible = "sifive,fu740-c000-spi", "sifive,spi0";
++                      reg = <0x0 0x10040000 0x0 0x1000>,
++                            <0x0 0x20000000 0x0 0x10000000>;
++                      interrupt-parent = <&plic0>;
++                      interrupts = <41>;
++                      clocks = <&prci PRCI_CLK_PCLK>;
++                      #address-cells = <1>;
++                      #size-cells = <0>;
++                      status = "disabled";
++              };
++              qspi1: spi@10041000 {
++                      compatible = "sifive,fu740-c000-spi", "sifive,spi0";
++                      reg = <0x0 0x10041000 0x0 0x1000>,
++                            <0x0 0x30000000 0x0 0x10000000>;
++                      interrupt-parent = <&plic0>;
++                      interrupts = <42>;
++                      clocks = <&prci PRCI_CLK_PCLK>;
++                      #address-cells = <1>;
++                      #size-cells = <0>;
++                      status = "disabled";
++              };
++              spi0: spi@10050000 {
++                      compatible = "sifive,fu740-c000-spi", "sifive,spi0";
++                      reg = <0x0 0x10050000 0x0 0x1000>;
++                      interrupt-parent = <&plic0>;
++                      interrupts = <43>;
++                      clocks = <&prci PRCI_CLK_PCLK>;
++                      #address-cells = <1>;
++                      #size-cells = <0>;
++                      status = "disabled";
++              };
++              eth0: ethernet@10090000 {
++                      compatible = "sifive,fu540-c000-gem";
++                      interrupt-parent = <&plic0>;
++                      interrupts = <55>;
++                      reg = <0x0 0x10090000 0x0 0x2000>,
++                            <0x0 0x100a0000 0x0 0x1000>;
++                      local-mac-address = [00 00 00 00 00 00];
++                      clock-names = "pclk", "hclk";
++                      clocks = <&prci PRCI_CLK_GEMGXLPLL>,
++                               <&prci PRCI_CLK_GEMGXLPLL>;
++                      #address-cells = <1>;
++                      #size-cells = <0>;
++                      status = "disabled";
++              };
++              pwm0: pwm@10020000 {
++                      compatible = "sifive,fu740-c000-pwm", "sifive,pwm0";
++                      reg = <0x0 0x10020000 0x0 0x1000>;
++                      interrupt-parent = <&plic0>;
++                      interrupts = <44>, <45>, <46>, <47>;
++                      clocks = <&prci PRCI_CLK_PCLK>;
++                      #pwm-cells = <3>;
++                      status = "disabled";
++              };
++              pwm1: pwm@10021000 {
++                      compatible = "sifive,fu740-c000-pwm", "sifive,pwm0";
++                      reg = <0x0 0x10021000 0x0 0x1000>;
++                      interrupt-parent = <&plic0>;
++                      interrupts = <48>, <49>, <50>, <51>;
++                      clocks = <&prci PRCI_CLK_PCLK>;
++                      #pwm-cells = <3>;
++                      status = "disabled";
++              };
++              ccache: cache-controller@2010000 {
++                      compatible = "sifive,fu740-c000-ccache", "cache";
++                      cache-block-size = <64>;
++                      cache-level = <2>;
++                      cache-sets = <2048>;
++                      cache-size = <2097152>;
++                      cache-unified;
++                      interrupt-parent = <&plic0>;
++                      interrupts = <19 20 21 22>;
++                      reg = <0x0 0x2010000 0x0 0x1000>;
++              };
++              gpio: gpio@10060000 {
++                      compatible = "sifive,fu740-c000-gpio", "sifive,gpio0";
++                      interrupt-parent = <&plic0>;
++                      interrupts = <23>, <24>, <25>, <26>, <27>, <28>, <29>,
++                                   <30>, <31>, <32>, <33>, <34>, <35>, <36>,
++                                   <37>, <38>;
++                      reg = <0x0 0x10060000 0x0 0x1000>;
++                      gpio-controller;
++                      #gpio-cells = <2>;
++                      interrupt-controller;
++                      #interrupt-cells = <2>;
++                      clocks = <&prci PRCI_CLK_PCLK>;
++                      status = "disabled";
++              };
++      };
++};
+-- 
+2.7.4
+
diff --git a/target/linux/hifiveu/patches-5.10/0013-dt-bindings-riscv-Update-YAML-doc-to-support-SiFive-.patch b/target/linux/hifiveu/patches-5.10/0013-dt-bindings-riscv-Update-YAML-doc-to-support-SiFive-.patch
new file mode 100644 (file)
index 0000000..1cf2538
--- /dev/null
@@ -0,0 +1,47 @@
+From 323c7d104a6fbe22100fdd7b62d53a4f4739affa Mon Sep 17 00:00:00 2001
+From: Yash Shah <yash.shah@sifive.com>
+Date: Tue, 8 Dec 2020 10:25:40 +0530
+Subject: [PATCH 13/29] dt-bindings: riscv: Update YAML doc to support SiFive
+ HiFive Unmatched board
+
+Add new compatible strings to the YAML DT binding document to support
+SiFive's HiFive Unmatched board
+
+Signed-off-by: Yash Shah <yash.shah@sifive.com>
+Reviewed-by: Rob Herring <robh@kernel.org>
+Reviewed-by: Bin Meng <bin.meng@windriver.com>
+---
+ Documentation/devicetree/bindings/riscv/sifive.yaml | 17 ++++++++++++-----
+ 1 file changed, 12 insertions(+), 5 deletions(-)
+
+diff --git a/Documentation/devicetree/bindings/riscv/sifive.yaml b/Documentation/devicetree/bindings/riscv/sifive.yaml
+index 3a8647d..ee0a239 100644
+--- a/Documentation/devicetree/bindings/riscv/sifive.yaml
++++ b/Documentation/devicetree/bindings/riscv/sifive.yaml
+@@ -17,11 +17,18 @@ properties:
+   $nodename:
+     const: '/'
+   compatible:
+-    items:
+-      - enum:
+-          - sifive,hifive-unleashed-a00
+-      - const: sifive,fu540-c000
+-      - const: sifive,fu540
++    oneOf:
++      - items:
++          - enum:
++              - sifive,hifive-unleashed-a00
++          - const: sifive,fu540-c000
++          - const: sifive,fu540
++
++      - items:
++          - enum:
++              - sifive,hifive-unmatched-a00
++          - const: sifive,fu740-c000
++          - const: sifive,fu740
+ additionalProperties: true
+-- 
+2.7.4
+
diff --git a/target/linux/hifiveu/patches-5.10/0014-riscv-dts-add-initial-board-data-for-the-SiFive-HiFi.patch b/target/linux/hifiveu/patches-5.10/0014-riscv-dts-add-initial-board-data-for-the-SiFive-HiFi.patch
new file mode 100644 (file)
index 0000000..69ae175
--- /dev/null
@@ -0,0 +1,290 @@
+From 721f85343651f07ab6ed8064680ad8bbadf76d3f Mon Sep 17 00:00:00 2001
+From: Yash Shah <yash.shah@sifive.com>
+Date: Tue, 8 Dec 2020 10:25:41 +0530
+Subject: [PATCH 14/29] riscv: dts: add initial board data for the SiFive
+ HiFive Unmatched
+
+Add initial board data for the SiFive HiFive Unmatched A00.
+This patch is dependent on Zong's Patchset[0].
+
+[0]: https://lore.kernel.org/linux-riscv/20201130082330.77268-4-zong.li@sifive.com/T/#u
+
+Signed-off-by: Yash Shah <yash.shah@sifive.com>
+Reviewed-by: Bin Meng <bin.meng@windriver.com>
+---
+ arch/riscv/boot/dts/sifive/Makefile                |   3 +-
+ .../riscv/boot/dts/sifive/hifive-unmatched-a00.dts | 253 +++++++++++++++++++++
+ 2 files changed, 255 insertions(+), 1 deletion(-)
+ create mode 100644 arch/riscv/boot/dts/sifive/hifive-unmatched-a00.dts
+
+diff --git a/arch/riscv/boot/dts/sifive/Makefile b/arch/riscv/boot/dts/sifive/Makefile
+index 6d6189e..74c47fe 100644
+--- a/arch/riscv/boot/dts/sifive/Makefile
++++ b/arch/riscv/boot/dts/sifive/Makefile
+@@ -1,2 +1,3 @@
+ # SPDX-License-Identifier: GPL-2.0
+-dtb-$(CONFIG_SOC_SIFIVE) += hifive-unleashed-a00.dtb
++dtb-$(CONFIG_SOC_SIFIVE) += hifive-unleashed-a00.dtb \
++                          hifive-unmatched-a00.dtb
+diff --git a/arch/riscv/boot/dts/sifive/hifive-unmatched-a00.dts b/arch/riscv/boot/dts/sifive/hifive-unmatched-a00.dts
+new file mode 100644
+index 00000000..b1c3c59
+--- /dev/null
++++ b/arch/riscv/boot/dts/sifive/hifive-unmatched-a00.dts
+@@ -0,0 +1,253 @@
++// SPDX-License-Identifier: (GPL-2.0 OR MIT)
++/* Copyright (c) 2020 SiFive, Inc */
++
++#include "fu740-c000.dtsi"
++#include <dt-bindings/interrupt-controller/irq.h>
++
++/* Clock frequency (in Hz) of the PCB crystal for rtcclk */
++#define RTCCLK_FREQ           1000000
++
++/ {
++      #address-cells = <2>;
++      #size-cells = <2>;
++      model = "SiFive HiFive Unmatched A00";
++      compatible = "sifive,hifive-unmatched-a00", "sifive,fu740-c000",
++                   "sifive,fu740";
++
++      chosen {
++              stdout-path = "serial0";
++      };
++
++      cpus {
++              timebase-frequency = <RTCCLK_FREQ>;
++      };
++
++      memory@80000000 {
++              device_type = "memory";
++              reg = <0x0 0x80000000 0x2 0x00000000>;
++      };
++
++      soc {
++      };
++
++      hfclk: hfclk {
++              #clock-cells = <0>;
++              compatible = "fixed-clock";
++              clock-frequency = <26000000>;
++              clock-output-names = "hfclk";
++      };
++
++      rtcclk: rtcclk {
++              #clock-cells = <0>;
++              compatible = "fixed-clock";
++              clock-frequency = <RTCCLK_FREQ>;
++              clock-output-names = "rtcclk";
++      };
++};
++
++&uart0 {
++      status = "okay";
++};
++
++&uart1 {
++      status = "okay";
++};
++
++&i2c0 {
++      status = "okay";
++
++      temperature-sensor@4c {
++              compatible = "ti,tmp451";
++              reg = <0x4c>;
++              interrupt-parent = <&gpio>;
++              interrupts = <6 IRQ_TYPE_LEVEL_LOW>;
++      };
++
++      pmic@58 {
++              compatible = "dlg,da9063";
++              reg = <0x58>;
++              interrupt-parent = <&gpio>;
++              interrupts = <1 IRQ_TYPE_LEVEL_LOW>;
++              interrupt-controller;
++
++              regulators {
++                      vdd_bcore1: bcore1 {
++                              regulator-min-microvolt = <900000>;
++                              regulator-max-microvolt = <900000>;
++                              regulator-min-microamp = <5000000>;
++                              regulator-max-microamp = <5000000>;
++                              regulator-always-on;
++                      };
++
++                      vdd_bcore2: bcore2 {
++                              regulator-min-microvolt = <900000>;
++                              regulator-max-microvolt = <900000>;
++                              regulator-min-microamp = <5000000>;
++                              regulator-max-microamp = <5000000>;
++                              regulator-always-on;
++                      };
++
++                      vdd_bpro: bpro {
++                              regulator-min-microvolt = <1800000>;
++                              regulator-max-microvolt = <1800000>;
++                              regulator-min-microamp = <2500000>;
++                              regulator-max-microamp = <2500000>;
++                              regulator-always-on;
++                      };
++
++                      vdd_bperi: bperi {
++                              regulator-min-microvolt = <1050000>;
++                              regulator-max-microvolt = <1050000>;
++                              regulator-min-microamp = <1500000>;
++                              regulator-max-microamp = <1500000>;
++                              regulator-always-on;
++                      };
++
++                      vdd_bmem: bmem {
++                              regulator-min-microvolt = <1200000>;
++                              regulator-max-microvolt = <1200000>;
++                              regulator-min-microamp = <3000000>;
++                              regulator-max-microamp = <3000000>;
++                              regulator-always-on;
++                      };
++
++                      vdd_bio: bio {
++                              regulator-min-microvolt = <1200000>;
++                              regulator-max-microvolt = <1200000>;
++                              regulator-min-microamp = <3000000>;
++                              regulator-max-microamp = <3000000>;
++                              regulator-always-on;
++                      };
++
++                      vdd_ldo1: ldo1 {
++                              regulator-min-microvolt = <1800000>;
++                              regulator-max-microvolt = <1800000>;
++                              regulator-min-microamp = <100000>;
++                              regulator-max-microamp = <100000>;
++                              regulator-always-on;
++                      };
++
++                      vdd_ldo2: ldo2 {
++                              regulator-min-microvolt = <1800000>;
++                              regulator-max-microvolt = <1800000>;
++                              regulator-min-microamp = <200000>;
++                              regulator-max-microamp = <200000>;
++                              regulator-always-on;
++                      };
++
++                      vdd_ldo3: ldo3 {
++                              regulator-min-microvolt = <1800000>;
++                              regulator-max-microvolt = <1800000>;
++                              regulator-min-microamp = <200000>;
++                              regulator-max-microamp = <200000>;
++                              regulator-always-on;
++                      };
++
++                      vdd_ldo4: ldo4 {
++                              regulator-min-microvolt = <1800000>;
++                              regulator-max-microvolt = <1800000>;
++                              regulator-min-microamp = <200000>;
++                              regulator-max-microamp = <200000>;
++                              regulator-always-on;
++                      };
++
++                      vdd_ldo5: ldo5 {
++                              regulator-min-microvolt = <1800000>;
++                              regulator-max-microvolt = <1800000>;
++                              regulator-min-microamp = <100000>;
++                              regulator-max-microamp = <100000>;
++                              regulator-always-on;
++                      };
++
++                      vdd_ldo6: ldo6 {
++                              regulator-min-microvolt = <3300000>;
++                              regulator-max-microvolt = <3300000>;
++                              regulator-min-microamp = <200000>;
++                              regulator-max-microamp = <200000>;
++                              regulator-always-on;
++                      };
++
++                      vdd_ldo7: ldo7 {
++                              regulator-min-microvolt = <1800000>;
++                              regulator-max-microvolt = <1800000>;
++                              regulator-min-microamp = <200000>;
++                              regulator-max-microamp = <200000>;
++                              regulator-always-on;
++                      };
++
++                      vdd_ldo8: ldo8 {
++                              regulator-min-microvolt = <1800000>;
++                              regulator-max-microvolt = <1800000>;
++                              regulator-min-microamp = <200000>;
++                              regulator-max-microamp = <200000>;
++                              regulator-always-on;
++                      };
++
++                      vdd_ld09: ldo9 {
++                              regulator-min-microvolt = <1050000>;
++                              regulator-max-microvolt = <1050000>;
++                              regulator-min-microamp = <200000>;
++                              regulator-max-microamp = <200000>;
++                      };
++
++                      vdd_ldo10: ldo10 {
++                              regulator-min-microvolt = <1000000>;
++                              regulator-max-microvolt = <1000000>;
++                              regulator-min-microamp = <300000>;
++                              regulator-max-microamp = <300000>;
++                      };
++
++                      vdd_ldo11: ldo11 {
++                              regulator-min-microvolt = <2500000>;
++                              regulator-max-microvolt = <2500000>;
++                              regulator-min-microamp = <300000>;
++                              regulator-max-microamp = <300000>;
++                              regulator-always-on;
++                      };
++              };
++      };
++};
++
++&qspi0 {
++      status = "okay";
++      flash@0 {
++              compatible = "issi,is25wp256", "jedec,spi-nor";
++              reg = <0>;
++              spi-max-frequency = <50000000>;
++              m25p,fast-read;
++              spi-tx-bus-width = <4>;
++              spi-rx-bus-width = <4>;
++      };
++};
++
++&spi0 {
++      status = "okay";
++      mmc@0 {
++              compatible = "mmc-spi-slot";
++              reg = <0>;
++              spi-max-frequency = <20000000>;
++              voltage-ranges = <3300 3300>;
++              disable-wp;
++      };
++};
++
++&eth0 {
++      status = "okay";
++      phy-mode = "gmii";
++      phy-handle = <&phy0>;
++      phy0: ethernet-phy@0 {
++              reg = <0>;
++      };
++};
++
++&pwm0 {
++      status = "okay";
++};
++
++&pwm1 {
++      status = "okay";
++};
++
++&gpio {
++      status = "okay";
++};
+-- 
+2.7.4
+
diff --git a/target/linux/hifiveu/patches-5.10/0016-RISC-V-sifive_l2_cache-Update-L2-cache-driver-to-sup.patch b/target/linux/hifiveu/patches-5.10/0016-RISC-V-sifive_l2_cache-Update-L2-cache-driver-to-sup.patch
new file mode 100644 (file)
index 0000000..2f6cd67
--- /dev/null
@@ -0,0 +1,98 @@
+From f4a28f41637429a1784ab2bf5e16222ec91da575 Mon Sep 17 00:00:00 2001
+From: Yash Shah <yash.shah@sifive.com>
+Date: Thu, 10 Dec 2020 15:58:03 +0530
+Subject: [PATCH 16/29] RISC-V: sifive_l2_cache: Update L2 cache driver to
+ support SiFive FU740
+
+SiFive FU740 has 4 ECC interrupt sources as compared to 3 in FU540.
+Update the L2 cache controller driver to support this additional
+interrupt in case of FU740-C000 chip.
+
+Signed-off-by: Yash Shah <yash.shah@sifive.com>
+---
+ drivers/soc/sifive/sifive_l2_cache.c | 27 ++++++++++++++++++++++++---
+ 1 file changed, 24 insertions(+), 3 deletions(-)
+
+diff --git a/drivers/soc/sifive/sifive_l2_cache.c b/drivers/soc/sifive/sifive_l2_cache.c
+index 44d7e1951..59640a1 100644
+--- a/drivers/soc/sifive/sifive_l2_cache.c
++++ b/drivers/soc/sifive/sifive_l2_cache.c
+@@ -17,6 +17,10 @@
+ #define SIFIVE_L2_DIRECCFIX_HIGH 0x104
+ #define SIFIVE_L2_DIRECCFIX_COUNT 0x108
++#define SIFIVE_L2_DIRECCFAIL_LOW 0x120
++#define SIFIVE_L2_DIRECCFAIL_HIGH 0x124
++#define SIFIVE_L2_DIRECCFAIL_COUNT 0x128
++
+ #define SIFIVE_L2_DATECCFIX_LOW 0x140
+ #define SIFIVE_L2_DATECCFIX_HIGH 0x144
+ #define SIFIVE_L2_DATECCFIX_COUNT 0x148
+@@ -29,7 +33,7 @@
+ #define SIFIVE_L2_WAYENABLE 0x08
+ #define SIFIVE_L2_ECCINJECTERR 0x40
+-#define SIFIVE_L2_MAX_ECCINTR 3
++#define SIFIVE_L2_MAX_ECCINTR 4
+ static void __iomem *l2_base;
+ static int g_irq[SIFIVE_L2_MAX_ECCINTR];
+@@ -39,6 +43,7 @@ enum {
+       DIR_CORR = 0,
+       DATA_CORR,
+       DATA_UNCORR,
++      DIR_UNCORR,
+ };
+ #ifdef CONFIG_DEBUG_FS
+@@ -93,6 +98,7 @@ static void l2_config_read(void)
+ static const struct of_device_id sifive_l2_ids[] = {
+       { .compatible = "sifive,fu540-c000-ccache" },
++      { .compatible = "sifive,fu740-c000-ccache" },
+       { /* end of table */ },
+ };
+@@ -155,6 +161,15 @@ static irqreturn_t l2_int_handler(int irq, void *device)
+               atomic_notifier_call_chain(&l2_err_chain, SIFIVE_L2_ERR_TYPE_CE,
+                                          "DirECCFix");
+       }
++      if (irq == g_irq[DIR_UNCORR]) {
++              add_h = readl(l2_base + SIFIVE_L2_DIRECCFAIL_HIGH);
++              add_l = readl(l2_base + SIFIVE_L2_DIRECCFAIL_LOW);
++              /* Reading this register clears the DirFail interrupt sig */
++              readl(l2_base + SIFIVE_L2_DIRECCFAIL_COUNT);
++              atomic_notifier_call_chain(&l2_err_chain, SIFIVE_L2_ERR_TYPE_UE,
++                                         "DirECCFail");
++              panic("L2CACHE: DirFail @ 0x%08X.%08X\n", add_h, add_l);
++      }
+       if (irq == g_irq[DATA_CORR]) {
+               add_h = readl(l2_base + SIFIVE_L2_DATECCFIX_HIGH);
+               add_l = readl(l2_base + SIFIVE_L2_DATECCFIX_LOW);
+@@ -181,7 +196,7 @@ static int __init sifive_l2_init(void)
+ {
+       struct device_node *np;
+       struct resource res;
+-      int i, rc;
++      int i, rc, intr_num;
+       np = of_find_matching_node(NULL, sifive_l2_ids);
+       if (!np)
+@@ -194,7 +209,13 @@ static int __init sifive_l2_init(void)
+       if (!l2_base)
+               return -ENOMEM;
+-      for (i = 0; i < SIFIVE_L2_MAX_ECCINTR; i++) {
++      intr_num = of_property_count_u32_elems(np, "interrupts");
++      if (!intr_num) {
++              pr_err("L2CACHE: no interrupts property\n");
++              return -ENODEV;
++      }
++
++      for (i = 0; i < intr_num; i++) {
+               g_irq[i] = irq_of_parse_and_map(np, i);
+               rc = request_irq(g_irq[i], l2_int_handler, 0, "l2_ecc", NULL);
+               if (rc) {
+-- 
+2.7.4
+
diff --git a/target/linux/hifiveu/patches-5.10/0017-gpio-sifive-To-get-gpio-irq-offset-from-device-tree-.patch b/target/linux/hifiveu/patches-5.10/0017-gpio-sifive-To-get-gpio-irq-offset-from-device-tree-.patch
new file mode 100644 (file)
index 0000000..01b21a2
--- /dev/null
@@ -0,0 +1,72 @@
+From e00f15b712b61f35fec747912dd5d3e9553d89a1 Mon Sep 17 00:00:00 2001
+From: Greentime Hu <greentime.hu@sifive.com>
+Date: Fri, 13 Nov 2020 10:33:55 +0800
+Subject: [PATCH 17/29] gpio: sifive: To get gpio irq offset from device tree
+ data
+
+We can get hwirq number of the gpio by its irq_data->hwirq so that we don't
+need to add more macros for different platforms. This patch is tested in
+SiFive Unleashed board and SiFive Unmatched board.
+
+Signed-off-by: Greentime Hu <greentime.hu@sifive.com>
+---
+ drivers/gpio/gpio-sifive.c | 14 ++++++++++----
+ 1 file changed, 10 insertions(+), 4 deletions(-)
+
+diff --git a/drivers/gpio/gpio-sifive.c b/drivers/gpio/gpio-sifive.c
+index d5eb9ca..63593c2 100644
+--- a/drivers/gpio/gpio-sifive.c
++++ b/drivers/gpio/gpio-sifive.c
+@@ -29,7 +29,6 @@
+ #define SIFIVE_GPIO_OUTPUT_XOR        0x40
+ #define SIFIVE_GPIO_MAX               32
+-#define SIFIVE_GPIO_IRQ_OFFSET        7
+ struct sifive_gpio {
+       void __iomem            *base;
+@@ -37,7 +36,7 @@ struct sifive_gpio {
+       struct regmap           *regs;
+       unsigned long           irq_state;
+       unsigned int            trigger[SIFIVE_GPIO_MAX];
+-      unsigned int            irq_parent[SIFIVE_GPIO_MAX];
++      unsigned int            irq_number[SIFIVE_GPIO_MAX];
+ };
+ static void sifive_gpio_set_ie(struct sifive_gpio *chip, unsigned int offset)
+@@ -144,8 +143,12 @@ static int sifive_gpio_child_to_parent_hwirq(struct gpio_chip *gc,
+                                            unsigned int *parent,
+                                            unsigned int *parent_type)
+ {
++      struct sifive_gpio *chip = gpiochip_get_data(gc);
++      struct irq_data *d = irq_get_irq_data(chip->irq_number[child]);
++
+       *parent_type = IRQ_TYPE_NONE;
+-      *parent = child + SIFIVE_GPIO_IRQ_OFFSET;
++      *parent = irqd_to_hwirq(d);
++
+       return 0;
+ }
+@@ -165,7 +168,7 @@ static int sifive_gpio_probe(struct platform_device *pdev)
+       struct irq_domain *parent;
+       struct gpio_irq_chip *girq;
+       struct sifive_gpio *chip;
+-      int ret, ngpio;
++      int ret, ngpio, i;
+       chip = devm_kzalloc(dev, sizeof(*chip), GFP_KERNEL);
+       if (!chip)
+@@ -200,6 +203,9 @@ static int sifive_gpio_probe(struct platform_device *pdev)
+               return -ENODEV;
+       }
++      for (i = 0; i < ngpio; i++)
++              chip->irq_number[i] = platform_get_irq(pdev, i);
++
+       ret = bgpio_init(&chip->gc, dev, 4,
+                        chip->base + SIFIVE_GPIO_INPUT_VAL,
+                        chip->base + SIFIVE_GPIO_OUTPUT_VAL,
+-- 
+2.7.4
+
diff --git a/target/linux/hifiveu/patches-5.10/0018-riscv-Add-3-SBI-wrapper-functions-to-get-cpu-manufac.patch b/target/linux/hifiveu/patches-5.10/0018-riscv-Add-3-SBI-wrapper-functions-to-get-cpu-manufac.patch
new file mode 100644 (file)
index 0000000..66a3ffe
--- /dev/null
@@ -0,0 +1,58 @@
+From 49e87f076a3d9d4b1ebadfe2b19250977be6d668 Mon Sep 17 00:00:00 2001
+From: Vincent Chen <vincent.chen@sifive.com>
+Date: Tue, 12 Jan 2021 14:43:50 +0800
+Subject: [PATCH 18/29] riscv: Add 3 SBI wrapper functions to get cpu
+ manufactory information
+
+Add 3 wrapper functions to get vendor id, architecture id and implement id
+from M-mode
+
+Signed-off-by: Vincent Chen <vincent.chen@sifive.com>
+---
+ arch/riscv/include/asm/sbi.h |  3 +++
+ arch/riscv/kernel/sbi.c      | 15 +++++++++++++++
+ 2 files changed, 18 insertions(+)
+
+diff --git a/arch/riscv/include/asm/sbi.h b/arch/riscv/include/asm/sbi.h
+index 653edb2..97eb78d 100644
+--- a/arch/riscv/include/asm/sbi.h
++++ b/arch/riscv/include/asm/sbi.h
+@@ -97,6 +97,9 @@ struct sbiret sbi_ecall(int ext, int fid, unsigned long arg0,
+ void sbi_console_putchar(int ch);
+ int sbi_console_getchar(void);
++long sbi_get_vendorid(void);
++long sbi_get_archid(void);
++long sbi_get_impid(void);
+ void sbi_set_timer(uint64_t stime_value);
+ void sbi_shutdown(void);
+ void sbi_clear_ipi(void);
+diff --git a/arch/riscv/kernel/sbi.c b/arch/riscv/kernel/sbi.c
+index 226ccce..b8f82c7 100644
+--- a/arch/riscv/kernel/sbi.c
++++ b/arch/riscv/kernel/sbi.c
+@@ -547,6 +547,21 @@ static inline long sbi_get_firmware_version(void)
+       return __sbi_base_ecall(SBI_EXT_BASE_GET_IMP_VERSION);
+ }
++long sbi_get_vendorid(void)
++{
++      return __sbi_base_ecall(SBI_EXT_BASE_GET_MVENDORID);
++}
++
++long sbi_get_archid(void)
++{
++      return __sbi_base_ecall(SBI_EXT_BASE_GET_MARCHID);
++}
++
++long sbi_get_impid(void)
++{
++      return __sbi_base_ecall(SBI_EXT_BASE_GET_MIMPID);
++}
++
+ static void sbi_send_cpumask_ipi(const struct cpumask *target)
+ {
+       struct cpumask hartid_mask;
+-- 
+2.7.4
+
diff --git a/target/linux/hifiveu/patches-5.10/0019-riscv-Get-CPU-manufactory-information.patch b/target/linux/hifiveu/patches-5.10/0019-riscv-Get-CPU-manufactory-information.patch
new file mode 100644 (file)
index 0000000..69c3786
--- /dev/null
@@ -0,0 +1,116 @@
+From 34c4f71f957e4e15776493d094593970178ddc9e Mon Sep 17 00:00:00 2001
+From: Vincent Chen <vincent.chen@sifive.com>
+Date: Tue, 12 Jan 2021 15:15:23 +0800
+Subject: [PATCH 19/29] riscv: Get CPU manufactory information
+
+Issue 3 SBI calls to get the vendor ID, architecture ID and
+implementataion ID.
+
+Signed-off-by: Vincent Chen <vincent.chen@sifive.com>
+---
+ arch/riscv/include/asm/csr.h       |  3 +++
+ arch/riscv/include/asm/hwcap.h     |  6 ++++++
+ arch/riscv/include/asm/processor.h |  2 ++
+ arch/riscv/kernel/cpufeature.c     | 17 +++++++++++++++++
+ arch/riscv/kernel/setup.c          |  2 ++
+ 5 files changed, 30 insertions(+)
+
+diff --git a/arch/riscv/include/asm/csr.h b/arch/riscv/include/asm/csr.h
+index cec462e..076beb9 100644
+--- a/arch/riscv/include/asm/csr.h
++++ b/arch/riscv/include/asm/csr.h
+@@ -109,6 +109,9 @@
+ #define CSR_MIP                       0x344
+ #define CSR_PMPCFG0           0x3a0
+ #define CSR_PMPADDR0          0x3b0
++#define CSR_MVENDORID         0xf11
++#define CSR_MARCHID           0xf12
++#define CSR_MIMPID            0xf13
+ #define CSR_MHARTID           0xf14
+ #ifdef CONFIG_RISCV_M_MODE
+diff --git a/arch/riscv/include/asm/hwcap.h b/arch/riscv/include/asm/hwcap.h
+index 5ce5046..952fe76 100644
+--- a/arch/riscv/include/asm/hwcap.h
++++ b/arch/riscv/include/asm/hwcap.h
+@@ -44,6 +44,12 @@ bool __riscv_isa_extension_available(const unsigned long *isa_bitmap, int bit);
+ #define riscv_isa_extension_available(isa_bitmap, ext)        \
+       __riscv_isa_extension_available(isa_bitmap, RISCV_ISA_EXT_##ext)
++struct cpu_manufactor_info_t {
++      unsigned long vendorid;
++      unsigned long archid;
++      unsigned long impid;
++};
++
+ #endif
+ #endif /* _ASM_RISCV_HWCAP_H */
+diff --git a/arch/riscv/include/asm/processor.h b/arch/riscv/include/asm/processor.h
+index bdddcd5..c9639b5 100644
+--- a/arch/riscv/include/asm/processor.h
++++ b/arch/riscv/include/asm/processor.h
+@@ -71,6 +71,8 @@ int riscv_of_parent_hartid(struct device_node *node);
+ extern void riscv_fill_hwcap(void);
++void riscv_fill_cpu_manufactor_info(void);
++
+ #endif /* __ASSEMBLY__ */
+ #endif /* _ASM_RISCV_PROCESSOR_H */
+diff --git a/arch/riscv/kernel/cpufeature.c b/arch/riscv/kernel/cpufeature.c
+index ac202f4..0315297 100644
+--- a/arch/riscv/kernel/cpufeature.c
++++ b/arch/riscv/kernel/cpufeature.c
+@@ -12,6 +12,8 @@
+ #include <asm/hwcap.h>
+ #include <asm/smp.h>
+ #include <asm/switch_to.h>
++#include <asm/sbi.h>
++#include <asm/csr.h>
+ unsigned long elf_hwcap __read_mostly;
+@@ -22,6 +24,8 @@ static DECLARE_BITMAP(riscv_isa, RISCV_ISA_EXT_MAX) __read_mostly;
+ bool has_fpu __read_mostly;
+ #endif
++struct cpu_manufactor_info_t cpu_manufactor_info;
++
+ /**
+  * riscv_isa_extension_base() - Get base extension word
+  *
+@@ -149,3 +153,16 @@ void riscv_fill_hwcap(void)
+               has_fpu = true;
+ #endif
+ }
++
++void riscv_fill_cpu_manufactor_info(void)
++{
++#ifndef CONFIG_RISCV_M_MODE
++      cpu_manufactor_info.vendorid = sbi_get_vendorid();
++      cpu_manufactor_info.archid = sbi_get_archid();
++      cpu_manufactor_info.impid = sbi_get_impid();
++#else
++      cpu_manufactor_info.vendorid = csr_read(CSR_MVENDORID);
++      cpu_manufactor_info.archid = csr_read(CSR_MARCHID);
++      cpu_manufactor_info.impid = csr_read(CSR_MIMPID);
++#endif
++}
+diff --git a/arch/riscv/kernel/setup.c b/arch/riscv/kernel/setup.c
+index 117f321..c7c1ae9 100644
+--- a/arch/riscv/kernel/setup.c
++++ b/arch/riscv/kernel/setup.c
+@@ -107,6 +107,8 @@ void __init setup_arch(char **cmdline_p)
+ #endif
+       riscv_fill_hwcap();
++
++      riscv_fill_cpu_manufactor_info();
+ }
+ static int __init topology_init(void)
+-- 
+2.7.4
+
diff --git a/target/linux/hifiveu/patches-5.10/0020-riscv-Introduce-alternative-mechanism-to-apply-errat.patch b/target/linux/hifiveu/patches-5.10/0020-riscv-Introduce-alternative-mechanism-to-apply-errat.patch
new file mode 100644 (file)
index 0000000..b47bf35
--- /dev/null
@@ -0,0 +1,433 @@
+From a3e6ca97499c444fee45c7efafcdef311142952c Mon Sep 17 00:00:00 2001
+From: Vincent Chen <vincent.chen@sifive.com>
+Date: Tue, 19 Jan 2021 03:30:22 -0800
+Subject: [PATCH 20/29] riscv: Introduce alternative mechanism to apply errata
+ solution
+
+Introduce the "alternative" mechanism from ARM64 and x86 to apply the CPU
+vendors' errata solution at runtime. The main purpose of this patch is
+to provide a framework. Therefore, the implementation is quite basic for
+now so that some scenarios could not use this scheme such as patching code
+to a module, relocating the patching code and heterogeneous CPU topology.
+
+Users could use the two macros ALTINSN and ALTDATA to modify the existing
+instruction and data respectively. By specifying the parameters vendorid,
+archid and impid, the kernel can probably apply the patch codes based on
+the same information of the running CPU. To keep the flexibility, the user
+can pass the specific kernel configure to the alternative macro to enable
+or disable the errata solution at compile time.
+
+Rebased for v5.10.8 by David Abdurachmanov.
+
+Signed-off-by: David Abdurachmanov <david.abdurachmanov@sifive.com>
+---
+ arch/riscv/Kconfig                          |   7 ++
+ arch/riscv/Makefile                         |   1 +
+ arch/riscv/errata/Makefile                  |   1 +
+ arch/riscv/errata/alternative.c             |  74 ++++++++++++++++
+ arch/riscv/include/asm/alternative-macros.h | 133 ++++++++++++++++++++++++++++
+ arch/riscv/include/asm/alternative.h        |  43 +++++++++
+ arch/riscv/include/asm/asm.h                |   1 +
+ arch/riscv/include/asm/sections.h           |   3 +
+ arch/riscv/kernel/smpboot.c                 |   4 +
+ arch/riscv/kernel/vmlinux.lds.S             |  21 +++++
+ 10 files changed, 288 insertions(+)
+ create mode 100644 arch/riscv/errata/Makefile
+ create mode 100644 arch/riscv/errata/alternative.c
+ create mode 100644 arch/riscv/include/asm/alternative-macros.h
+ create mode 100644 arch/riscv/include/asm/alternative.h
+
+diff --git a/arch/riscv/Kconfig b/arch/riscv/Kconfig
+index 3474286..2717aa0 100644
+--- a/arch/riscv/Kconfig
++++ b/arch/riscv/Kconfig
+@@ -84,6 +84,7 @@ config RISCV
+       select PCI_MSI if PCI
+       select RISCV_INTC
+       select RISCV_TIMER if RISCV_SBI
++      select RISCV_ERRATA
+       select SPARSE_IRQ
+       select SYSCTL_EXCEPTION_TRACE
+       select THREAD_INFO_IN_TASK
+@@ -423,6 +424,12 @@ config BUILTIN_DTB
+       depends on RISCV_M_MODE
+       depends on OF
++config RISCV_ERRATA
++      bool "Runtime apply errata patch"
++      help
++        This option provides the support for applying the errata patch
++        at runtime.
++
+ menu "Power management options"
+ source "kernel/power/Kconfig"
+diff --git a/arch/riscv/Makefile b/arch/riscv/Makefile
+index 0289a97..cd23fb0 100644
+--- a/arch/riscv/Makefile
++++ b/arch/riscv/Makefile
+@@ -75,6 +75,7 @@ KBUILD_IMAGE := $(boot)/Image.gz
+ head-y := arch/riscv/kernel/head.o
+ core-y += arch/riscv/
++core-$(CONFIG_RISCV_ERRATA) += arch/riscv/errata/
+ libs-y += arch/riscv/lib/
+ libs-$(CONFIG_EFI_STUB) += $(objtree)/drivers/firmware/efi/libstub/lib.a
+diff --git a/arch/riscv/errata/Makefile b/arch/riscv/errata/Makefile
+new file mode 100644
+index 00000000..43e6d54
+--- /dev/null
++++ b/arch/riscv/errata/Makefile
+@@ -0,0 +1 @@
++obj-y += alternative.o
+diff --git a/arch/riscv/errata/alternative.c b/arch/riscv/errata/alternative.c
+new file mode 100644
+index 00000000..0827c05
+--- /dev/null
++++ b/arch/riscv/errata/alternative.c
+@@ -0,0 +1,74 @@
++// SPDX-License-Identifier: GPL-2.0-only
++/*
++ * alternative runtime patching
++ * inspired by the ARM64 and x86 version
++ *
++ * Copyright (C) 2021 Sifive.
++ */
++
++#include <linux/init.h>
++#include <linux/cpu.h>
++#include <linux/uaccess.h>
++#include <asm/patch.h>
++#include <asm/alternative.h>
++#include <asm/sections.h>
++
++struct alt_region {
++      struct alt_entry *begin;
++      struct alt_entry *end;
++};
++
++static bool __init default_checkfunc(struct alt_entry *alt)
++{
++      return false;
++}
++
++static bool (*errata_checkfunc)(struct alt_entry *alt) = default_checkfunc;
++typedef int (*patch_func_t)(void *addr, const void *insn, size_t size);
++
++static void __apply_alternatives(void *alt_region, void *alt_patch_func)
++{
++      struct alt_entry *alt;
++      struct alt_region *region = alt_region;
++
++      for (alt = region->begin; alt < region->end; alt++) {
++              if (!errata_checkfunc(alt))
++                      continue;
++              ((patch_func_t)alt_patch_func)(alt->old_ptr, alt->alt_ptr, alt->old_len);
++      }
++}
++
++static void __init init_alternatvie(void)
++{
++      struct errata_checkfunc_id *ptr;
++
++      for (ptr = (struct errata_checkfunc_id *)__alt_checkfunc_table;
++           ptr < (struct errata_checkfunc_id *)__alt_checkfunc_table_end;
++           ptr++) {
++              if (cpu_manufactor_info.vendorid == ptr->vendorid)
++                      errata_checkfunc = ptr->func;
++      }
++}
++
++/*
++ * This is called very early in the boot process (directly after we run
++ * a feature detect on the boot CPU). No need to worry about other CPUs
++ * here.
++ */
++void __init apply_boot_alternatives(void)
++{
++      struct alt_region region;
++
++      init_alternatvie();
++      /* If called on non-boot cpu things could go wrong */
++      WARN_ON(smp_processor_id() != 0);
++
++      region.begin = (struct alt_entry *)__alt_insn;
++      region.end = (struct alt_entry *)__alt_insn_end;
++      __apply_alternatives(&region, patch_text_nosync);
++
++      region.begin = (struct alt_entry *)__alt_data;
++      region.end = (struct alt_entry *)__alt_data_end;
++      __apply_alternatives(&region, copy_to_kernel_nofault);
++}
++
+diff --git a/arch/riscv/include/asm/alternative-macros.h b/arch/riscv/include/asm/alternative-macros.h
+new file mode 100644
+index 00000000..dd06ded
+--- /dev/null
++++ b/arch/riscv/include/asm/alternative-macros.h
+@@ -0,0 +1,133 @@
++/* SPDX-License-Identifier: GPL-2.0 */
++#ifndef __ASM_ALTERNATIVE_MACROS_H
++#define __ASM_ALTERNATIVE_MACROS_H
++
++#ifndef __ASSEMBLY__
++
++#include <asm/asm.h>
++#include <linux/stringify.h>
++
++#define ALT_ENTRY(oldptr, altptr, vendorid, archid, impid, oldlen, altlen) \
++      RISCV_PTR " " oldptr "\n" \
++      RISCV_PTR " " altptr "\n" \
++      REG_ASM " " vendorid "\n" \
++      REG_ASM " " archid "\ n" \
++      REG_ASM " " impid "\n" \
++      ".word " oldlen "\n" \
++      ".word " altlen "\n" \
++
++#define __ALTINSN_CFG(oldinsn, altinsn, vendorid, archid, impid, enable) \
++      ".if " __stringify(enable) " == 1\n"                            \
++      "886 :\n\t"                                                     \
++      oldinsn "\n"                                                    \
++      "887 :\n"                                                       \
++      ".pushsection .altinsn, \"a\"\n"                                \
++      ALT_ENTRY("886b", "888f", vendorid, archid, impid, "887b - 886b", "889f - 888f") \
++      ".popsection\n"                                                 \
++      ".subsection 1\n"                                               \
++      "888 :\n\t"                                                     \
++      altinsn "\n"                                                    \
++      "889 :\n\t"                                                     \
++      ".previous\n"                                                   \
++      ".org   . - (887b - 886b) + (889b - 888b)\n\t"                  \
++      ".org   . - (889b - 888b) + (887b - 886b)\n\t"                  \
++      ".endif\n"
++
++#define _ALTINSN_CFG(oldinsn, altinsn, vendorid, archid, impid, CONFIG_k, ...)        \
++      __ALTINSN_CFG(oldinsn, altinsn, vendorid, archid, impid, IS_ENABLED(CONFIG_k))
++
++#define __ALTDATA_CFG(oldptr, altptr, vendorid, archid, impid, oldlen, altlen, enable) \
++      ".if " __stringify(enable) " == 1\n"                                    \
++      ".pushsection .altdata, \"a\"\n"                                        \
++      ALT_ENTRY(oldptr, altptr, vendorid, archid, impid, oldlen, altlen)      \
++      ".popsection\n"                                                         \
++      ".previous\n"                                                           \
++      ".endif\n"
++
++#define _ALTDATA_CFG(oldptr, altptr, vendorid, archid, impid, oldlen, altlen, CONFIG_k, ...)  \
++      __ALTDATA_CFG(oldptr, altptr, vendorid, archid, impid, oldlen, altlen, IS_ENABLED(CONFIG_k))
++
++#else
++.macro ALT_ENTRY oldptr altptr vendorid archid impid oldlen alt_len
++      RISCV_PTR \oldptr
++      RISCV_PTR \altptr
++      REG_ASM \vendorid
++      REG_ASM \archid
++      REG_ASM \impid
++      .word \oldlen
++      .word \alt_len
++.endm
++
++.macro __ALTINSN_CFG insn1 insn2 vendorid archid impid enable = 1
++      .if \enable
++886 :
++      \insn1
++887 :
++      .pushsection .altinsn, "a"
++      ALT_ENTRY 886b, 888f, \vendorid, \archid, \impid, 887b - 886b, 889f - 888f
++      .popsection
++      .subsection 1
++888 :
++      \insn2
++889 :
++      .previous
++      .org    . - (889b - 888b) + (887b - 886b)
++      .org    . - (887b - 886b) + (889b - 888b)
++      .endif
++.endm
++
++#define _ALTINSN_CFG(oldinsn, altinsn, vendorid, archid, impid, CONFIG_k, ...) \
++      __ALTINSN_CFG oldinsn, altinsn, vendorid, archid, impid, IS_ENABLED(CONFIG_k)
++
++.macro __ALTDATA_CFG oldptr altptr vendorid archid impid oldlen altlen enable = 1
++      .if \enable
++      .pushsection .altdata, "a"
++      ALT_ENTRY \oldptr \altptr \vendorid \archid \impid \oldlen \altlen
++      .popsection
++      .org    . - \oldlen + \altlen
++      .org    . - \altlen + \oldlen
++      .endif
++.endm
++
++#define _ALTDATA_CFG(oldptr, altptr, vendorid, archid, impid, oldlen, altlen, CONFIG_k, ...)  \
++      __ALTDATA_CFG oldptr, altptr, vendorid, archid, impid, oldlen, altlen, IS_ENABLED(CONFIG_k)
++
++#endif
++
++/*
++ * Usage: asm(ALTINSN(oldinsn, altinsn, vendorid, archid, impid));
++ *
++ * Usage: asm(ALTERNATIVE(oldinsn, altinsn, vendorid, archid, impid, CONFIG_FOO));
++ *
++ * oldinsn: The old instruction which will be replaced.
++ * altinsn: The replacement instruction.
++ * vendorid: The CPU vendor ID.
++ * archid: The CPU architecture ID.
++ * impid: The CPU implement ID.
++ *
++ * N.B. If CONFIG_FOO is specified, but not selected, the whole block
++ *      will be omitted, including oldinstr.
++ */
++#define ALTINSN(oldinsn, altinsn, ...)   \
++      _ALTINSN_CFG(oldinsn, altinsn, __VA_ARGS__, 1)
++
++/*
++ * Usage: asm(ALTDATA(oldptr, altptr, vendorid, archid, impid, oldlen, altlen));
++ *
++ * Usage: asm(ALTERNATIVE(oldptr, altptr, feature, CONFIG_FOO));
++ *
++ * oldptr: The address of old data.
++ * altinsn: The address of replacement data.
++ * vendorid: The CPU vendor ID.
++ * archid: The CPU architecture ID.
++ * impid: The CPU implement ID.
++ * oldlen: The data length of old data.
++ * newlen: The data length of new data.
++ *
++ * N.B. If CONFIG_FOO is specified, but not selected, the whole block
++ *      will be omitted.
++ */
++
++#define ALTDATA(oldptr, altptr, ...)   \
++      _ALTDATA_CFG(oldptr, altptr, __VA_ARGS__, 1)
++#endif
+diff --git a/arch/riscv/include/asm/alternative.h b/arch/riscv/include/asm/alternative.h
+new file mode 100644
+index 00000000..fc1d929
+--- /dev/null
++++ b/arch/riscv/include/asm/alternative.h
+@@ -0,0 +1,43 @@
++/* SPDX-License-Identifier: GPL-2.0-only */
++/*
++ * Copyright (C) 2021 Sifive.
++ */
++
++#ifndef __ASM_ALTERNATIVE_H
++#define __ASM_ALTERNATIVE_H
++
++#include <asm/alternative-macros.h>
++#ifndef __ASSEMBLY__
++
++#include <linux/init.h>
++#include <linux/types.h>
++#include <linux/stddef.h>
++#include <asm/hwcap.h>
++
++void __init apply_boot_alternatives(void);
++
++struct alt_entry {
++      void *old_ptr;          /* address of original instruciton or data  */
++      void *alt_ptr;          /* address of replacement instruction or data */
++      unsigned long vendorid; /* cpu vendor id */
++      unsigned long archid;   /* cpu architecture id */
++      unsigned long impid;    /* cpu implement id */
++      unsigned int old_len;   /* size of original instruction(s) or data(s) */
++      unsigned int alt_len;   /* size of new instruction(s) or data(s) */
++};
++
++struct errata_checkfunc_id {
++      unsigned long vendorid;
++      bool (*func)(struct alt_entry *alt);
++};
++
++extern struct cpu_manufactor_info_t cpu_manufactor_info;
++
++#define REGISTER_ERRATA_CHECKFUNC(checkfunc, vendor_id)                         \
++      static const struct errata_checkfunc_id _errata_check_##vendor_id \
++      __used __section(".alt_checkfunc_table")                          \
++      __aligned(__alignof__(struct errata_checkfunc_id)) =              \
++      { .vendorid = vendor_id,                                          \
++        .func = checkfunc }
++#endif
++#endif
+diff --git a/arch/riscv/include/asm/asm.h b/arch/riscv/include/asm/asm.h
+index 9c992a8..618d7c5 100644
+--- a/arch/riscv/include/asm/asm.h
++++ b/arch/riscv/include/asm/asm.h
+@@ -23,6 +23,7 @@
+ #define REG_L         __REG_SEL(ld, lw)
+ #define REG_S         __REG_SEL(sd, sw)
+ #define REG_SC                __REG_SEL(sc.d, sc.w)
++#define REG_ASM               __REG_SEL(.dword, .word)
+ #define SZREG         __REG_SEL(8, 4)
+ #define LGREG         __REG_SEL(3, 2)
+diff --git a/arch/riscv/include/asm/sections.h b/arch/riscv/include/asm/sections.h
+index 3a9971b..2ee8e12 100644
+--- a/arch/riscv/include/asm/sections.h
++++ b/arch/riscv/include/asm/sections.h
+@@ -9,5 +9,8 @@
+ extern char _start[];
+ extern char _start_kernel[];
++extern char __alt_checkfunc_table[], __alt_checkfunc_table_end[];
++extern char __alt_data[], __alt_data_end[];
++extern char __alt_insn[], __alt_insn_end[];
+ #endif /* __ASM_SECTIONS_H */
+diff --git a/arch/riscv/kernel/smpboot.c b/arch/riscv/kernel/smpboot.c
+index 96167d5..7177ee2 100644
+--- a/arch/riscv/kernel/smpboot.c
++++ b/arch/riscv/kernel/smpboot.c
+@@ -31,6 +31,7 @@
+ #include <asm/sections.h>
+ #include <asm/sbi.h>
+ #include <asm/smp.h>
++#include <asm/alternative.h>
+ #include "head.h"
+@@ -39,6 +40,9 @@ static DECLARE_COMPLETION(cpu_running);
+ void __init smp_prepare_boot_cpu(void)
+ {
+       init_cpu_topology();
++#ifdef CONFIG_RISCV_ERRATA
++      apply_boot_alternatives();
++#endif
+ }
+ void __init smp_prepare_cpus(unsigned int max_cpus)
+diff --git a/arch/riscv/kernel/vmlinux.lds.S b/arch/riscv/kernel/vmlinux.lds.S
+index 3ffbd6c..9df933c 100644
+--- a/arch/riscv/kernel/vmlinux.lds.S
++++ b/arch/riscv/kernel/vmlinux.lds.S
+@@ -77,6 +77,27 @@ SECTIONS
+       INIT_DATA_SECTION(16)
++      . = ALIGN(8);
++      .alt_checkfunc_table : {
++              __alt_checkfunc_table = .;
++              *(.alt_checkfunc_table)
++              __alt_checkfunc_table_end = .;
++      }
++
++      . = ALIGN(8);
++      .altinsn : {
++              __alt_insn = .;
++              *(.altinsn)
++              __alt_insn_end = .;
++      }
++
++      . = ALIGN(8);
++      .altdata : {
++              __alt_data = .;
++              *(.altdata)
++              __alt_data_end = .;
++      }
++
+       /* Start of data section */
+       _sdata = .;
+       RO_DATA(SECTION_ALIGN)
+-- 
+2.7.4
+
diff --git a/target/linux/hifiveu/patches-5.10/0021-riscv-sifive-apply-errata-cip-453-patch.patch b/target/linux/hifiveu/patches-5.10/0021-riscv-sifive-apply-errata-cip-453-patch.patch
new file mode 100644 (file)
index 0000000..806cde0
--- /dev/null
@@ -0,0 +1,153 @@
+From fb63756f6b2e49160aaf85789f8ed88135eeea50 Mon Sep 17 00:00:00 2001
+From: Vincent Chen <vincent.chen@sifive.com>
+Date: Tue, 12 Jan 2021 15:29:29 +0800
+Subject: [PATCH 21/29] riscv: sifive: apply errata cip-453 patch
+
+Add sign extension to the $badaddr when the exception type is instruction
+page fault or instruciton access fault to workaround the errata cip-453.
+
+To avoid affecting the existing code sequence, this patch creates a
+trampoline to add sign extension to the $baddaddr, and then replaces
+the original exception handlers with this trampoline by ALTDATA. In this
+case, only the specific sifive CPU jumps to the do_page_fault through
+this trampoline. Other CPUs are not affected.
+
+Signed-off-by: Vincent Chen <vincent.chen@sifive.com>
+---
+ arch/riscv/errata/Makefile                |  1 +
+ arch/riscv/errata/sifive/Makefile         |  2 +
+ arch/riscv/errata/sifive/altern_ops.c     | 20 ++++++++++
+ arch/riscv/errata/sifive/errata.h         |  6 +++
+ arch/riscv/errata/sifive/errata_cip_453.S | 64 +++++++++++++++++++++++++++++++
+ 5 files changed, 93 insertions(+)
+ create mode 100644 arch/riscv/errata/sifive/Makefile
+ create mode 100644 arch/riscv/errata/sifive/altern_ops.c
+ create mode 100644 arch/riscv/errata/sifive/errata.h
+ create mode 100644 arch/riscv/errata/sifive/errata_cip_453.S
+
+diff --git a/arch/riscv/errata/Makefile b/arch/riscv/errata/Makefile
+index 43e6d54..be93ded 100644
+--- a/arch/riscv/errata/Makefile
++++ b/arch/riscv/errata/Makefile
+@@ -1 +1,2 @@
+ obj-y += alternative.o
++obj-$(CONFIG_SOC_SIFIVE) += sifive/
+diff --git a/arch/riscv/errata/sifive/Makefile b/arch/riscv/errata/sifive/Makefile
+new file mode 100644
+index 00000000..b7f4cd7
+--- /dev/null
++++ b/arch/riscv/errata/sifive/Makefile
+@@ -0,0 +1,2 @@
++obj-y += altern_ops.o
++obj-y += errata_cip_453.o
+diff --git a/arch/riscv/errata/sifive/altern_ops.c b/arch/riscv/errata/sifive/altern_ops.c
+new file mode 100644
+index 00000000..0dcec17
+--- /dev/null
++++ b/arch/riscv/errata/sifive/altern_ops.c
+@@ -0,0 +1,20 @@
++// SPDX-License-Identifier: GPL-2.0-only
++/*
++ * Copyright (C) 2021 Sifive.
++ */
++
++#include <asm/alternative.h>
++#include <linux/kernel.h>
++
++#include "errata.h"
++
++static bool __init sifive_errata_check(struct alt_entry *alt)
++{
++      if (cpu_manufactor_info.vendorid == alt->vendorid &&
++          cpu_manufactor_info.archid == alt->archid &&
++          cpu_manufactor_info.impid == alt->impid)
++              return true;
++      return false;
++}
++
++REGISTER_ERRATA_CHECKFUNC(sifive_errata_check, SIFIVE_VENDOR_ID);
+diff --git a/arch/riscv/errata/sifive/errata.h b/arch/riscv/errata/sifive/errata.h
+new file mode 100644
+index 00000000..1f3be47
+--- /dev/null
++++ b/arch/riscv/errata/sifive/errata.h
+@@ -0,0 +1,6 @@
++/* SPDX-License-Identifier: GPL-2.0-only */
++/*
++ * Copyright (C) 2021 SiFive
++ */
++
++#define SIFIVE_VENDOR_ID      0x489
+diff --git a/arch/riscv/errata/sifive/errata_cip_453.S b/arch/riscv/errata/sifive/errata_cip_453.S
+new file mode 100644
+index 00000000..c1ea974
+--- /dev/null
++++ b/arch/riscv/errata/sifive/errata_cip_453.S
+@@ -0,0 +1,64 @@
++/* SPDX-License-Identifier: GPL-2.0-only */
++/*
++ * Copyright (C) 2021 SiFive
++ */
++
++#include <linux/linkage.h>
++#include <asm/asm.h>
++#include <asm/asm-offsets.h>
++#include <asm/alternative.h>
++#include "errata.h"
++
++#define INSN_PAGE_FAULT       excp_vect_table + 12 << RISCV_LGPTR
++#define INSN_ACCESS_FAULT     excp_vect_table + 1 << RISCV_LGPTR
++#define P_TRAMPOLINE          sifive_ipage_fault_trampoline
++#define A_TRAMPOLINE          sifive_iaccess_fault_trampoline
++#define MARCHID               0x8000000000000007
++#define MIMPID                0x20181004
++#define LEN                   1 << RISCV_LGPTR
++
++.macro ADD_SIGN_EXT pt_reg badaddr tmp_reg
++      REG_L \badaddr, PT_BADADDR(\pt_reg)
++      li \tmp_reg,1
++      slli \tmp_reg,\tmp_reg,0x26
++      and \tmp_reg,\tmp_reg,\badaddr
++      beqz \tmp_reg, 1f
++      li \tmp_reg,-1
++      slli \tmp_reg,\tmp_reg,0x27
++      or \badaddr,\tmp_reg,\badaddr
++      REG_S \badaddr, PT_BADADDR(\pt_reg)
++1:
++.endm
++
++
++.globl sifive_ipage_fault_trampoline
++.type  sifive_ipage_fault_trampoline, @object
++.size  sifive_ipage_fault_trampoline, 8
++sifive_ipage_fault_trampoline:
++.dword do_page_fault_trampoline
++
++ENTRY(do_page_fault_trampoline)
++      ADD_SIGN_EXT a0, t0, t1
++      la t0, do_page_fault
++      jr t0
++END(do_page_fault_trampoline)
++
++.globl sifive_iaccess_fault_trampoline
++.type  sifive_iaccess_fault_trampoline, @object
++.size  sifive_iaccess_fault_trampoline, 8
++sifive_iaccess_fault_trampoline:
++.dword do_trap_insn_fault_trampoline
++
++ENTRY(do_trap_insn_fault_trampoline)
++      ADD_SIGN_EXT a0, t0, t1
++      la t0, do_trap_insn_fault
++      jr t0
++END(do_trap_insn_fault_trampoline)
++
++/*
++ * Replace the page fault exception handler with sifive_page_fault_trampoline
++ * function
++ */
++ALTDATA(INSN_PAGE_FAULT, P_TRAMPOLINE, SIFIVE_VENDOR_ID, MARCHID, MIMPID, LEN, LEN)
++ALTDATA(INSN_ACCESS_FAULT, A_TRAMPOLINE, SIFIVE_VENDOR_ID, MARCHID, MIMPID, LEN, LEN)
++
+-- 
+2.7.4
+
diff --git a/target/linux/hifiveu/patches-5.10/0022-riscv-dts-fu740-fix-cache-controller-interrupts.patch b/target/linux/hifiveu/patches-5.10/0022-riscv-dts-fu740-fix-cache-controller-interrupts.patch
new file mode 100644 (file)
index 0000000..c678f74
--- /dev/null
@@ -0,0 +1,36 @@
+From 8a0380c3eee96adf57daf2f54fec5089c4dee576 Mon Sep 17 00:00:00 2001
+From: David Abdurachmanov <david.abdurachmanov@sifive.com>
+Date: Wed, 3 Feb 2021 07:00:15 -0800
+Subject: [PATCH 22/29] riscv: dts: fu740: fix cache-controller interrupts
+
+The order of interrupt numbers is incorrect.
+
+The order for FU740 is: DirError, DataError, DataFail, DirFail
+
+From SiFive FU740-C000 Manual:
+19 - L2 Cache DirError
+20 - L2 Cache DirFail
+21 - L2 Cache DataError
+22 - L2 Cache DataFail
+
+Signed-off-by: David Abdurachmanov <david.abdurachmanov@sifive.com>
+---
+ arch/riscv/boot/dts/sifive/fu740-c000.dtsi | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/arch/riscv/boot/dts/sifive/fu740-c000.dtsi b/arch/riscv/boot/dts/sifive/fu740-c000.dtsi
+index eeb4f8c3..d0d206c 100644
+--- a/arch/riscv/boot/dts/sifive/fu740-c000.dtsi
++++ b/arch/riscv/boot/dts/sifive/fu740-c000.dtsi
+@@ -272,7 +272,7 @@
+                       cache-size = <2097152>;
+                       cache-unified;
+                       interrupt-parent = <&plic0>;
+-                      interrupts = <19 20 21 22>;
++                      interrupts = <19 21 22 20>;
+                       reg = <0x0 0x2010000 0x0 0x1000>;
+               };
+               gpio: gpio@10060000 {
+-- 
+2.7.4
+
diff --git a/target/linux/hifiveu/patches-5.10/0023-riscv-sifive-fu740-cpu-1-2-3-4-set-compatible-to-sif.patch b/target/linux/hifiveu/patches-5.10/0023-riscv-sifive-fu740-cpu-1-2-3-4-set-compatible-to-sif.patch
new file mode 100644 (file)
index 0000000..bfd1f4e
--- /dev/null
@@ -0,0 +1,54 @@
+From 58231edb72ab61199226250483038159b2c56c65 Mon Sep 17 00:00:00 2001
+From: David Abdurachmanov <david.abdurachmanov@sifive.com>
+Date: Wed, 17 Feb 2021 06:06:14 -0800
+Subject: [PATCH 23/29] riscv: sifive: fu740: cpu{1,2,3,4} set compatible to
+ sifive,u74-mc
+
+Signed-off-by: David Abdurachmanov <david.abdurachmanov@sifive.com>
+---
+ arch/riscv/boot/dts/sifive/fu740-c000.dtsi | 8 ++++----
+ 1 file changed, 4 insertions(+), 4 deletions(-)
+
+diff --git a/arch/riscv/boot/dts/sifive/fu740-c000.dtsi b/arch/riscv/boot/dts/sifive/fu740-c000.dtsi
+index d0d206c..cd9cc02 100644
+--- a/arch/riscv/boot/dts/sifive/fu740-c000.dtsi
++++ b/arch/riscv/boot/dts/sifive/fu740-c000.dtsi
+@@ -39,7 +39,7 @@
+                       };
+               };
+               cpu1: cpu@1 {
+-                      compatible = "sifive,bullet0", "riscv";
++                      compatible = "sifive,u74-mc", "sifive,bullet0", "riscv";
+                       d-cache-block-size = <64>;
+                       d-cache-sets = <64>;
+                       d-cache-size = <32768>;
+@@ -63,7 +63,7 @@
+                       };
+               };
+               cpu2: cpu@2 {
+-                      compatible = "sifive,bullet0", "riscv";
++                      compatible = "sifive,u74-mc", "sifive,bullet0", "riscv";
+                       d-cache-block-size = <64>;
+                       d-cache-sets = <64>;
+                       d-cache-size = <32768>;
+@@ -87,7 +87,7 @@
+                       };
+               };
+               cpu3: cpu@3 {
+-                      compatible = "sifive,bullet0", "riscv";
++                      compatible = "sifive,u74-mc", "sifive,bullet0", "riscv";
+                       d-cache-block-size = <64>;
+                       d-cache-sets = <64>;
+                       d-cache-size = <32768>;
+@@ -111,7 +111,7 @@
+                       };
+               };
+               cpu4: cpu@4 {
+-                      compatible = "sifive,bullet0", "riscv";
++                      compatible = "sifive,u74-mc", "sifive,bullet0", "riscv";
+                       d-cache-block-size = <64>;
+                       d-cache-sets = <64>;
+                       d-cache-size = <32768>;
+-- 
+2.7.4
+
diff --git a/target/linux/hifiveu/patches-5.10/0024-riscv-dts-Add-PCIe-support-for-the-SiFive-FU740-C000.patch b/target/linux/hifiveu/patches-5.10/0024-riscv-dts-Add-PCIe-support-for-the-SiFive-FU740-C000.patch
new file mode 100644 (file)
index 0000000..3b941d0
--- /dev/null
@@ -0,0 +1,66 @@
+From 34222949288ef8b2666facee9ca9001c8cd93486 Mon Sep 17 00:00:00 2001
+From: Greentime Hu <greentime.hu@sifive.com>
+Date: Wed, 3 Feb 2021 11:22:10 +0800
+Subject: [PATCH 24/29] riscv: dts: Add PCIe support for the SiFive FU740-C000
+ SoC
+
+Signed-off-by: Greentime Hu <greentime.hu@sifive.com>
+---
+ arch/riscv/boot/dts/sifive/fu740-c000.dtsi | 35 ++++++++++++++++++++++++++++++
+ 1 file changed, 35 insertions(+)
+
+diff --git a/arch/riscv/boot/dts/sifive/fu740-c000.dtsi b/arch/riscv/boot/dts/sifive/fu740-c000.dtsi
+index cd9cc02..727fd91 100644
+--- a/arch/riscv/boot/dts/sifive/fu740-c000.dtsi
++++ b/arch/riscv/boot/dts/sifive/fu740-c000.dtsi
+@@ -159,6 +159,7 @@
+                       reg = <0x0 0x10000000 0x0 0x1000>;
+                       clocks = <&hfclk>, <&rtcclk>;
+                       #clock-cells = <1>;
++                      #reset-cells = <1>;
+               };
+               uart0: serial@10010000 {
+                       compatible = "sifive,fu740-c000-uart", "sifive,uart0";
+@@ -289,5 +290,39 @@
+                       clocks = <&prci PRCI_CLK_PCLK>;
+                       status = "disabled";
+               };
++              pcie@e00000000 {
++                      #address-cells = <3>;
++                      #interrupt-cells = <1>;
++                      #num-lanes = <8>;
++                      #size-cells = <2>;
++                      compatible = "sifive,fu740-pcie";
++                      reg = <0xe 0x00000000 0x1 0x0
++                             0xd 0xf0000000 0x0 0x10000000
++                             0x0 0x100d0000 0x0 0x1000>;
++                      reg-names = "dbi", "config", "mgmt";
++                      device_type = "pci";
++                      dma-coherent;
++                      bus-range = <0x0 0xff>;
++                      ranges = <0x81000000  0x0 0x60080000  0x0 0x60080000 0x0 0x10000        /* I/O */
++                                0x82000000  0x0 0x60090000  0x0 0x60090000 0x0 0xff70000      /* mem */
++                                0x82000000  0x0 0x70000000  0x0 0x70000000 0x0 0x1000000      /* mem */
++                                0xc3000000 0x20 0x00000000 0x20 0x00000000 0x20 0x00000000>;  /* mem prefetchable */
++                      num-lanes = <0x8>;
++                      msi-parent = <&plic0>;
++                      interrupts = <56 57 58 59 60 61 62 63 64>;
++                      interrupt-names = "msi", "inta", "intb", "intc", "intd";
++                      interrupt-parent = <&plic0>;
++                      interrupt-map-mask = <0x0 0x0 0x0 0x7>;
++                      interrupt-map = <0x0 0x0 0x0 0x1 &plic0 57>,
++                                      <0x0 0x0 0x0 0x2 &plic0 58>,
++                                      <0x0 0x0 0x0 0x3 &plic0 59>,
++                                      <0x0 0x0 0x0 0x4 &plic0 60>;
++                      clock-names = "pcie_aux";
++                      clocks = <&prci PRCI_CLK_PCIE_AUX>;
++                      pwren-gpios = <&gpio 5 0>;
++                      perstn-gpios = <&gpio 8 0>;
++                      resets = <&prci 4>;
++                      status = "okay";
++              };
+       };
+ };
+-- 
+2.7.4
+
diff --git a/target/linux/hifiveu/patches-5.10/0025-clk-sifive-Add-pcie_aux-clock-in-prci-driver-for-PCI.patch b/target/linux/hifiveu/patches-5.10/0025-clk-sifive-Add-pcie_aux-clock-in-prci-driver-for-PCI.patch
new file mode 100644 (file)
index 0000000..6be8467
--- /dev/null
@@ -0,0 +1,150 @@
+From 90591acb975baa3bedc7178e04bc92daaca3740f Mon Sep 17 00:00:00 2001
+From: Greentime Hu <greentime.hu@sifive.com>
+Date: Wed, 3 Feb 2021 11:00:32 +0800
+Subject: [PATCH 25/29] clk: sifive: Add pcie_aux clock in prci driver for PCIe
+ driver
+
+We add pcie_aux clock in this patch so that pcie driver can use
+clk_prepare_enable() and clk_disable_unprepare() to enable and disable
+pcie_aux clock.
+
+Signed-off-by: Greentime Hu <greentime.hu@sifive.com>
+---
+ drivers/clk/sifive/fu740-prci.c               | 11 +++++++
+ drivers/clk/sifive/fu740-prci.h               |  2 +-
+ drivers/clk/sifive/sifive-prci.c              | 41 +++++++++++++++++++++++++++
+ drivers/clk/sifive/sifive-prci.h              |  9 ++++++
+ include/dt-bindings/clock/sifive-fu740-prci.h |  1 +
+ 5 files changed, 63 insertions(+), 1 deletion(-)
+
+diff --git a/drivers/clk/sifive/fu740-prci.c b/drivers/clk/sifive/fu740-prci.c
+index db83002..76cbfb1 100644
+--- a/drivers/clk/sifive/fu740-prci.c
++++ b/drivers/clk/sifive/fu740-prci.c
+@@ -69,6 +69,12 @@ static const struct clk_ops sifive_fu740_prci_hfpclkplldiv_clk_ops = {
+       .recalc_rate = sifive_prci_hfpclkplldiv_recalc_rate,
+ };
++static const struct clk_ops sifive_fu740_prci_pcie_aux_clk_ops = {
++      .enable = sifive_prci_pcie_aux_clock_enable,
++      .disable = sifive_prci_pcie_aux_clock_disable,
++      .is_enabled = sifive_prci_pcie_aux_clock_is_enabled,
++};
++
+ /* List of clock controls provided by the PRCI */
+ struct __prci_clock __prci_init_clocks_fu740[] = {
+       [PRCI_CLK_COREPLL] = {
+@@ -117,4 +123,9 @@ struct __prci_clock __prci_init_clocks_fu740[] = {
+               .parent_name = "hfpclkpll",
+               .ops = &sifive_fu740_prci_hfpclkplldiv_clk_ops,
+       },
++      [PRCI_CLK_PCIE_AUX] = {
++              .name = "pcie_aux",
++              .parent_name = "hfclk",
++              .ops = &sifive_fu740_prci_pcie_aux_clk_ops,
++      },
+ };
+diff --git a/drivers/clk/sifive/fu740-prci.h b/drivers/clk/sifive/fu740-prci.h
+index 13ef971f7..511a0bf 100644
+--- a/drivers/clk/sifive/fu740-prci.h
++++ b/drivers/clk/sifive/fu740-prci.h
+@@ -9,7 +9,7 @@
+ #include "sifive-prci.h"
+-#define NUM_CLOCK_FU740       8
++#define NUM_CLOCK_FU740       9
+ extern struct __prci_clock __prci_init_clocks_fu740[NUM_CLOCK_FU740];
+diff --git a/drivers/clk/sifive/sifive-prci.c b/drivers/clk/sifive/sifive-prci.c
+index c78b042..baf7313 100644
+--- a/drivers/clk/sifive/sifive-prci.c
++++ b/drivers/clk/sifive/sifive-prci.c
+@@ -448,6 +448,47 @@ void sifive_prci_hfpclkpllsel_use_hfpclkpll(struct __prci_data *pd)
+       r = __prci_readl(pd, PRCI_HFPCLKPLLSEL_OFFSET); /* barrier */
+ }
++/* PCIE AUX clock APIs for enable, disable. */
++int sifive_prci_pcie_aux_clock_is_enabled(struct clk_hw *hw)
++{
++      struct __prci_clock *pc = clk_hw_to_prci_clock(hw);
++      struct __prci_data *pd = pc->pd;
++      u32 r;
++
++      r = __prci_readl(pd, PRCI_PCIE_AUX_OFFSET);
++
++      if (r & PRCI_PCIE_AUX_EN_MASK)
++              return 1;
++      else
++              return 0;
++}
++
++int sifive_prci_pcie_aux_clock_enable(struct clk_hw *hw)
++{
++      struct __prci_clock *pc = clk_hw_to_prci_clock(hw);
++      struct __prci_data *pd = pc->pd;
++      u32 r;
++
++      if (sifive_prci_pcie_aux_clock_is_enabled(hw))
++              return 0;
++
++      __prci_writel(1, PRCI_PCIE_AUX_OFFSET, pd);
++      r = __prci_readl(pd, PRCI_PCIE_AUX_OFFSET);     /* barrier */
++
++      return 0;
++}
++
++void sifive_prci_pcie_aux_clock_disable(struct clk_hw *hw)
++{
++      struct __prci_clock *pc = clk_hw_to_prci_clock(hw);
++      struct __prci_data *pd = pc->pd;
++      u32 r;
++
++      __prci_writel(0, PRCI_PCIE_AUX_OFFSET, pd);
++      r = __prci_readl(pd, PRCI_PCIE_AUX_OFFSET);     /* barrier */
++
++}
++
+ /**
+  * __prci_register_clocks() - register clock controls in the PRCI
+  * @dev: Linux struct device
+diff --git a/drivers/clk/sifive/sifive-prci.h b/drivers/clk/sifive/sifive-prci.h
+index dbdbd17..022c67c 100644
+--- a/drivers/clk/sifive/sifive-prci.h
++++ b/drivers/clk/sifive/sifive-prci.h
+@@ -67,6 +67,11 @@
+ #define PRCI_DDRPLLCFG1_CKE_SHIFT     31
+ #define PRCI_DDRPLLCFG1_CKE_MASK      (0x1 << PRCI_DDRPLLCFG1_CKE_SHIFT)
++/* PCIEAUX */
++#define PRCI_PCIE_AUX_OFFSET          0x14
++#define PRCI_PCIE_AUX_EN_SHIFT                0
++#define PRCI_PCIE_AUX_EN_MASK         (0x1 << PRCI_PCIE_AUX_EN_SHIFT)
++
+ /* GEMGXLPLLCFG0 */
+ #define PRCI_GEMGXLPLLCFG0_OFFSET     0x1c
+ #define PRCI_GEMGXLPLLCFG0_DIVR_SHIFT 0
+@@ -296,4 +301,8 @@ unsigned long sifive_prci_tlclksel_recalc_rate(struct clk_hw *hw,
+ unsigned long sifive_prci_hfpclkplldiv_recalc_rate(struct clk_hw *hw,
+                                                  unsigned long parent_rate);
++int sifive_prci_pcie_aux_clock_is_enabled(struct clk_hw *hw);
++int sifive_prci_pcie_aux_clock_enable(struct clk_hw *hw);
++void sifive_prci_pcie_aux_clock_disable(struct clk_hw *hw);
++
+ #endif /* __SIFIVE_CLK_SIFIVE_PRCI_H */
+diff --git a/include/dt-bindings/clock/sifive-fu740-prci.h b/include/dt-bindings/clock/sifive-fu740-prci.h
+index cd7706e..7899b7f 100644
+--- a/include/dt-bindings/clock/sifive-fu740-prci.h
++++ b/include/dt-bindings/clock/sifive-fu740-prci.h
+@@ -19,5 +19,6 @@
+ #define PRCI_CLK_CLTXPLL             5
+ #define PRCI_CLK_TLCLK                       6
+ #define PRCI_CLK_PCLK                7
++#define PRCI_CLK_PCIE_AUX            8
+ #endif        /* __DT_BINDINGS_CLOCK_SIFIVE_FU740_PRCI_H */
+-- 
+2.7.4
+
diff --git a/target/linux/hifiveu/patches-5.10/0026-clk-sifive-Use-reset-simple-in-prci-driver-for-PCIe-.patch b/target/linux/hifiveu/patches-5.10/0026-clk-sifive-Use-reset-simple-in-prci-driver-for-PCIe-.patch
new file mode 100644 (file)
index 0000000..118c927
--- /dev/null
@@ -0,0 +1,110 @@
+From a9b30eacb76d59ea18f138e0ad2b66e8a50ef24d Mon Sep 17 00:00:00 2001
+From: Greentime Hu <greentime.hu@sifive.com>
+Date: Wed, 3 Feb 2021 11:07:16 +0800
+Subject: [PATCH 26/29] clk: sifive: Use reset-simple in prci driver for PCIe
+ driver
+
+We use reset-simple in this patch so that pcie driver can use
+devm_reset_control_get() to get this reset data structure and use
+reset_control_deassert() to deassert pcie_power_up_rst_n.
+
+Signed-off-by: Greentime Hu <greentime.hu@sifive.com>
+---
+ drivers/clk/sifive/Kconfig       |  2 ++
+ drivers/clk/sifive/sifive-prci.c | 14 ++++++++++++++
+ drivers/clk/sifive/sifive-prci.h |  4 ++++
+ drivers/reset/Kconfig            |  3 ++-
+ 4 files changed, 22 insertions(+), 1 deletion(-)
+
+diff --git a/drivers/clk/sifive/Kconfig b/drivers/clk/sifive/Kconfig
+index 1c14eb2..9132c3c 100644
+--- a/drivers/clk/sifive/Kconfig
++++ b/drivers/clk/sifive/Kconfig
+@@ -10,6 +10,8 @@ if CLK_SIFIVE
+ config CLK_SIFIVE_PRCI
+       bool "PRCI driver for SiFive SoCs"
++      select RESET_CONTROLLER
++      select RESET_SIMPLE
+       select CLK_ANALOGBITS_WRPLL_CLN28HPC
+       help
+         Supports the Power Reset Clock interface (PRCI) IP block found in
+diff --git a/drivers/clk/sifive/sifive-prci.c b/drivers/clk/sifive/sifive-prci.c
+index baf7313..925affc 100644
+--- a/drivers/clk/sifive/sifive-prci.c
++++ b/drivers/clk/sifive/sifive-prci.c
+@@ -583,7 +583,21 @@ static int sifive_prci_probe(struct platform_device *pdev)
+       if (IS_ERR(pd->va))
+               return PTR_ERR(pd->va);
++      pd->reset.rcdev.owner = THIS_MODULE;
++      pd->reset.rcdev.nr_resets = PRCI_RST_NR;
++      pd->reset.rcdev.ops = &reset_simple_ops;
++      pd->reset.rcdev.of_node = pdev->dev.of_node;
++      pd->reset.active_low = true;
++      pd->reset.membase = pd->va + PRCI_DEVICESRESETREG_OFFSET;
++      spin_lock_init(&pd->reset.lock);
++
++      r = devm_reset_controller_register(&pdev->dev, &pd->reset.rcdev);
++      if (r) {
++              dev_err(dev, "could not register reset controller: %d\n", r);
++              return r;
++      }
+       r = __prci_register_clocks(dev, pd, desc);
++
+       if (r) {
+               dev_err(dev, "could not register clocks: %d\n", r);
+               return r;
+diff --git a/drivers/clk/sifive/sifive-prci.h b/drivers/clk/sifive/sifive-prci.h
+index 022c67c..91658a8 100644
+--- a/drivers/clk/sifive/sifive-prci.h
++++ b/drivers/clk/sifive/sifive-prci.h
+@@ -11,6 +11,7 @@
+ #include <linux/clk/analogbits-wrpll-cln28hpc.h>
+ #include <linux/clk-provider.h>
++#include <linux/reset/reset-simple.h>
+ #include <linux/platform_device.h>
+ /*
+@@ -121,6 +122,8 @@
+ #define PRCI_DEVICESRESETREG_CHIPLINK_RST_N_MASK                      \
+               (0x1 << PRCI_DEVICESRESETREG_CHIPLINK_RST_N_SHIFT)
++#define PRCI_RST_NR                                           7
++
+ /* CLKMUXSTATUSREG */
+ #define PRCI_CLKMUXSTATUSREG_OFFSET                           0x2c
+ #define PRCI_CLKMUXSTATUSREG_TLCLKSEL_STATUS_SHIFT            1
+@@ -221,6 +224,7 @@
+  */
+ struct __prci_data {
+       void __iomem *va;
++      struct reset_simple_data reset;
+       struct clk_hw_onecell_data hw_clks;
+ };
+diff --git a/drivers/reset/Kconfig b/drivers/reset/Kconfig
+index 07d162b..124f4dc 100644
+--- a/drivers/reset/Kconfig
++++ b/drivers/reset/Kconfig
+@@ -165,7 +165,7 @@ config RESET_SCMI
+ config RESET_SIMPLE
+       bool "Simple Reset Controller Driver" if COMPILE_TEST
+-      default ARCH_AGILEX || ARCH_ASPEED || ARCH_BITMAIN || ARCH_REALTEK || ARCH_STM32 || ARCH_STRATIX10 || ARCH_SUNXI || ARCH_ZX || ARC
++      default ARCH_AGILEX || ARCH_ASPEED || ARCH_BITMAIN || ARCH_REALTEK || ARCH_STM32 || ARCH_STRATIX10 || ARCH_SUNXI || ARCH_ZX || ARC || RISCV
+       help
+         This enables a simple reset controller driver for reset lines that
+         that can be asserted and deasserted by toggling bits in a contiguous,
+@@ -179,6 +179,7 @@ config RESET_SIMPLE
+          - RCC reset controller in STM32 MCUs
+          - Allwinner SoCs
+          - ZTE's zx2967 family
++         - SiFive FU740 SoCs
+ config RESET_STM32MP157
+       bool "STM32MP157 Reset Driver" if COMPILE_TEST
+-- 
+2.7.4
+
diff --git a/target/linux/hifiveu/patches-5.10/0027-MAINTAINERS-Add-maintainers-for-SiFive-FU740-PCIe-dr.patch b/target/linux/hifiveu/patches-5.10/0027-MAINTAINERS-Add-maintainers-for-SiFive-FU740-PCIe-dr.patch
new file mode 100644 (file)
index 0000000..88d38a5
--- /dev/null
@@ -0,0 +1,35 @@
+From a57464df4cfa31061f665d2bac4222d625ec5ca9 Mon Sep 17 00:00:00 2001
+From: Greentime Hu <greentime.hu@sifive.com>
+Date: Wed, 3 Feb 2021 11:11:57 +0800
+Subject: [PATCH 27/29] MAINTAINERS: Add maintainers for SiFive FU740 PCIe
+ driver
+
+Here add maintainer information for SiFive FU740 PCIe driver.
+
+Signed-off-by: Greentime Hu <greentime.hu@sifive.com>
+---
+ MAINTAINERS | 8 ++++++++
+ 1 file changed, 8 insertions(+)
+
+diff --git a/MAINTAINERS b/MAINTAINERS
+index 281de21..5980c85 100644
+--- a/MAINTAINERS
++++ b/MAINTAINERS
+@@ -13389,6 +13389,14 @@ S:    Maintained
+ F:    Documentation/devicetree/bindings/pci/fsl,imx6q-pcie.txt
+ F:    drivers/pci/controller/dwc/*imx6*
++PCI DRIVER FOR FU740
++M:    Paul Walmsley <paul.walmsley@sifive.com>
++M:    Greentime Hu <greentime.hu@sifive.com>
++L:    linux-pci@vger.kernel.org
++S:    Maintained
++F:    Documentation/devicetree/bindings/pci/sifive,fu740-pcie.yaml
++F:    drivers/pci/controller/dwc/pcie-fu740.c
++
+ PCI DRIVER FOR INTEL VOLUME MANAGEMENT DEVICE (VMD)
+ M:    Jonathan Derrick <jonathan.derrick@intel.com>
+ L:    linux-pci@vger.kernel.org
+-- 
+2.7.4
+
diff --git a/target/linux/hifiveu/patches-5.10/0028-dt-bindings-PCI-Add-SiFive-FU740-PCIe-host-controlle.patch b/target/linux/hifiveu/patches-5.10/0028-dt-bindings-PCI-Add-SiFive-FU740-PCIe-host-controlle.patch
new file mode 100644 (file)
index 0000000..f37b8c1
--- /dev/null
@@ -0,0 +1,143 @@
+From 38fecc0dae7765bcd4de25863ef3156a18992040 Mon Sep 17 00:00:00 2001
+From: Greentime Hu <greentime.hu@sifive.com>
+Date: Wed, 3 Feb 2021 11:17:35 +0800
+Subject: [PATCH 28/29] dt-bindings: PCI: Add SiFive FU740 PCIe host controller
+
+Add PCIe host controller DT bindings of SiFive FU740.
+
+Signed-off-by: Greentime Hu <greentime.hu@sifive.com>
+---
+ .../devicetree/bindings/pci/sifive,fu740-pcie.yaml | 121 +++++++++++++++++++++
+ 1 file changed, 121 insertions(+)
+ create mode 100644 Documentation/devicetree/bindings/pci/sifive,fu740-pcie.yaml
+
+diff --git a/Documentation/devicetree/bindings/pci/sifive,fu740-pcie.yaml b/Documentation/devicetree/bindings/pci/sifive,fu740-pcie.yaml
+new file mode 100644
+index 00000000..bcd1d18
+--- /dev/null
++++ b/Documentation/devicetree/bindings/pci/sifive,fu740-pcie.yaml
+@@ -0,0 +1,121 @@
++# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
++%YAML 1.2
++---
++$id: http://devicetree.org/schemas/pci/sifive,fu740-pcie.yaml#
++$schema: http://devicetree.org/meta-schemas/core.yaml#
++
++title: SiFive fu740 PCIe host controller
++
++description: |
++  SiFive fu740 PCIe host controller is based on the Synopsys DesignWare
++  PCI core. It shares common features with the PCIe DesignWare core and
++  inherits common properties defined in
++  Documentation/devicetree/bindings/pci/designware-pcie.txt.
++
++maintainers:
++  - Paul Walmsley <paul.walmsley@sifive.com>
++  - Greentime Hu <greentime.hu@sifive.com>
++
++allOf:
++  - $ref: /schemas/pci/pci-bus.yaml#
++
++properties:
++  compatible:
++    const: sifive,fu740-pcie
++
++  reg:
++    maxItems: 4
++
++  reg-names:
++    items:
++      - const: dbi
++      - const: config
++      - const: mgmt
++
++  device_type:
++    const: pci
++
++  dma-coherent:
++    description: Indicates that the PCIe IP block can ensure the coherency
++
++  bus-range:
++    description: Range of bus numbers associated with this controller.
++
++  num-lanes: true
++
++  msi-parent: true
++
++  interrupt-names:
++    items:
++      - const: msi
++      - const: inta
++      - const: intb
++      - const: intc
++      - const: intd
++
++  resets:
++    description: A phandle to the PCIe power up reset line
++
++  pwren-gpios:
++    description: Should specify the GPIO for controlling the PCI bus device power on
++
++  perstn-gpios:
++    description: Should specify the GPIO for controlling the PCI bus device reset
++
++required:
++  - compatible
++  - reg
++  - reg-names
++  - device_type
++  - dma-coherent
++  - bus-range
++  - ranges
++  - num-lanes
++  - msi-parent
++  - interrupts
++  - interrupt-names
++  - interrupt-parent
++  - interrupt-map-mask
++  - interrupt-map
++  - clock-names
++  - clocks
++  - resets
++  - pwren-gpios
++  - perstn-gpios
++
++additionalProperties: false
++
++examples:
++  - |
++    pcie@e00000000 {
++        #address-cells = <3>;
++        #interrupt-cells = <1>;
++        #size-cells = <2>;
++        compatible = "sifive,fu740-pcie";
++        reg = <0xe 0x00000000 0x1 0x0
++               0xd 0xf0000000 0x0 0x10000000
++               0x0 0x100d0000 0x0 0x1000>;
++        reg-names = "dbi", "config", "mgmt";
++        device_type = "pci";
++        dma-coherent;
++        bus-range = <0x0 0xff>;
++        ranges = <0x81000000  0x0 0x60080000  0x0 0x60080000 0x0 0x10000        /* I/O */
++                  0x82000000  0x0 0x60090000  0x0 0x60090000 0x0 0xff70000      /* mem */
++                  0x82000000  0x0 0x70000000  0x0 0x70000000 0x0 0x1000000      /* mem */
++                  0xc3000000 0x20 0x00000000 0x20 0x00000000 0x20 0x00000000>;  /* mem prefetchable */
++        num-lanes = <0x8>;
++        msi-parent = <&plic0>;
++        interrupts = <56 57 58 59 60 61 62 63 64>;
++        interrupt-names = "msi", "inta", "intb", "intc", "intd";
++        interrupt-parent = <&plic0>;
++        interrupt-map-mask = <0x0 0x0 0x0 0x7>;
++        interrupt-map = <0x0 0x0 0x0 0x1 &plic0 57>,
++                        <0x0 0x0 0x0 0x2 &plic0 58>,
++                        <0x0 0x0 0x0 0x3 &plic0 59>,
++                        <0x0 0x0 0x0 0x4 &plic0 60>;
++      clock-names = "pcie_aux";
++        clocks = <&prci PRCI_CLK_PCIE_AUX>;
++        resets = <&prci 4>;
++        pwren-gpios = <&gpio 5 0>;
++        perstn-gpios = <&gpio 8 0>;
++    };
+-- 
+2.7.4
+
diff --git a/target/linux/hifiveu/patches-5.10/0029-PCI-designware-Add-SiFive-FU740-PCIe-host-controller.patch b/target/linux/hifiveu/patches-5.10/0029-PCI-designware-Add-SiFive-FU740-PCIe-host-controller.patch
new file mode 100644 (file)
index 0000000..52dfd98
--- /dev/null
@@ -0,0 +1,614 @@
+From 6da0f49824ae1fca4d0bf1ce433c870cf1b424ea Mon Sep 17 00:00:00 2001
+From: Paul Walmsley <paul.walmsley@sifive.com>
+Date: Wed, 3 Feb 2021 11:19:08 +0800
+Subject: [PATCH 29/29] PCI: designware: Add SiFive FU740 PCIe host controller
+ driver
+
+Add driver for the SiFive FU740 PCIe host controller.
+This controller is based on the DesignWare PCIe core.
+
+Co-developed-by: Henry Styles <hes@sifive.com>
+Signed-off-by: Henry Styles <hes@sifive.com>
+Co-developed-by: Erik Danie <erik.danie@sifive.com>
+Signed-off-by: Erik Danie <erik.danie@sifive.com>
+Co-developed-by: Greentime Hu <greentime.hu@sifive.com>
+Signed-off-by: Greentime Hu <greentime.hu@sifive.com>
+Signed-off-by: Paul Walmsley <paul.walmsley@sifive.com>
+---
+ drivers/pci/controller/dwc/Kconfig      |   9 +
+ drivers/pci/controller/dwc/Makefile     |   1 +
+ drivers/pci/controller/dwc/pcie-fu740.c | 552 ++++++++++++++++++++++++++++++++
+ 3 files changed, 562 insertions(+)
+ create mode 100644 drivers/pci/controller/dwc/pcie-fu740.c
+
+diff --git a/drivers/pci/controller/dwc/Kconfig b/drivers/pci/controller/dwc/Kconfig
+index bc04986..ee13834 100644
+--- a/drivers/pci/controller/dwc/Kconfig
++++ b/drivers/pci/controller/dwc/Kconfig
+@@ -312,4 +312,13 @@ config PCIE_AL
+         required only for DT-based platforms. ACPI platforms with the
+         Annapurna Labs PCIe controller don't need to enable this.
++config PCIE_FU740
++      bool "SiFive FU740 PCIe host controller"
++      depends on PCI_MSI_IRQ_DOMAIN
++      depends on SOC_SIFIVE || COMPILE_TEST
++      select PCIE_DW_HOST
++      help
++        Say Y here if you want PCIe controller support for the SiFive
++        FU740.
++
+ endmenu
+diff --git a/drivers/pci/controller/dwc/Makefile b/drivers/pci/controller/dwc/Makefile
+index a751553..625f6aa 100644
+--- a/drivers/pci/controller/dwc/Makefile
++++ b/drivers/pci/controller/dwc/Makefile
+@@ -5,6 +5,7 @@ obj-$(CONFIG_PCIE_DW_EP) += pcie-designware-ep.o
+ obj-$(CONFIG_PCIE_DW_PLAT) += pcie-designware-plat.o
+ obj-$(CONFIG_PCI_DRA7XX) += pci-dra7xx.o
+ obj-$(CONFIG_PCI_EXYNOS) += pci-exynos.o
++obj-$(CONFIG_PCIE_FU740) += pcie-fu740.o
+ obj-$(CONFIG_PCI_IMX6) += pci-imx6.o
+ obj-$(CONFIG_PCIE_SPEAR13XX) += pcie-spear13xx.o
+ obj-$(CONFIG_PCI_KEYSTONE) += pci-keystone.o
+diff --git a/drivers/pci/controller/dwc/pcie-fu740.c b/drivers/pci/controller/dwc/pcie-fu740.c
+new file mode 100644
+index 00000000..afb0404
+--- /dev/null
++++ b/drivers/pci/controller/dwc/pcie-fu740.c
+@@ -0,0 +1,552 @@
++// SPDX-License-Identifier: GPL-2.0
++/*
++ * FU740 DesignWare PCIe Controller integration
++ * Copyright (C) 2019-2021 SiFive, Inc.
++ * Paul Walmsley
++ * Greentime Hu
++ *
++ * Based in part on the i.MX6 PCIe host controller shim which is:
++ *
++ * Copyright (C) 2013 Kosagi
++ *            http://www.kosagi.com
++ */
++
++#include <linux/clk.h>
++#include <linux/delay.h>
++#include <linux/gpio.h>
++#include <linux/kernel.h>
++#include <linux/mfd/syscon.h>
++#include <linux/module.h>
++#include <linux/of_gpio.h>
++#include <linux/of_device.h>
++#include <linux/pci.h>
++#include <linux/platform_device.h>
++#include <linux/regmap.h>
++#include <linux/regulator/consumer.h>
++#include <linux/resource.h>
++#include <linux/signal.h>
++#include <linux/types.h>
++#include <linux/interrupt.h>
++#include <linux/reset.h>
++#include <linux/pm_domain.h>
++#include <linux/pm_runtime.h>
++
++#include "pcie-designware.h"
++
++#define to_fu740_pcie(x)      dev_get_drvdata((x)->dev)
++
++struct fu740_pcie {
++      struct dw_pcie *pci;
++      void __iomem *mgmt_base;
++      int perstn_gpio;
++      int pwren_gpio;
++      struct clk *pcie_aux;
++      struct reset_control *rst;
++};
++
++#define SIFIVE_DEVICESRESETREG                        0x28
++
++#define PCIEX8MGMT_PERST_N                    0x0
++#define PCIEX8MGMT_APP_LTSSM_ENABLE           0x10
++#define PCIEX8MGMT_APP_HOLD_PHY_RST           0x18
++#define PCIEX8MGMT_DEVICE_TYPE                        0x708
++#define PCIEX8MGMT_PHY0_CR_PARA_ADDR          0x860
++#define PCIEX8MGMT_PHY0_CR_PARA_RD_EN         0x870
++#define PCIEX8MGMT_PHY0_CR_PARA_RD_DATA               0x878
++#define PCIEX8MGMT_PHY0_CR_PARA_SEL           0x880
++#define PCIEX8MGMT_PHY0_CR_PARA_WR_DATA               0x888
++#define PCIEX8MGMT_PHY0_CR_PARA_WR_EN         0x890
++#define PCIEX8MGMT_PHY0_CR_PARA_ACK           0x898
++#define PCIEX8MGMT_PHY1_CR_PARA_ADDR          0x8a0
++#define PCIEX8MGMT_PHY1_CR_PARA_RD_EN         0x8b0
++#define PCIEX8MGMT_PHY1_CR_PARA_RD_DATA               0x8b8
++#define PCIEX8MGMT_PHY1_CR_PARA_SEL           0x8c0
++#define PCIEX8MGMT_PHY1_CR_PARA_WR_DATA               0x8c8
++#define PCIEX8MGMT_PHY1_CR_PARA_WR_EN         0x8d0
++#define PCIEX8MGMT_PHY1_CR_PARA_ACK           0x8d8
++
++/* PCIe Root Complex registers (memory-mapped) */
++#define PCIE_RC_PF0_MSI_CAP                   0x50
++#define PCI_MSI_CAP_ID_NEXT_CTRL_REG          (PCIE_RC_PF0_MSI_CAP + 0x0)
++
++#define PCIE_DSP_PF0_PCIE_CAP_BASE            0x70
++#define PCIE_RC_LCR                           (PCIE_DSP_PF0_PCIE_CAP_BASE + 0xc)
++#define PCIE_RC_LCR_MAX_LINK_SPEEDS_GEN1      0x1
++#define PCIE_RC_LCR_MAX_LINK_SPEEDS_GEN2      0x2
++#define PCIE_RC_LCR_MAX_LINK_SPEEDS_GEN3      0x3
++#define PCIE_RC_LCR_MAX_LINK_SPEEDS_MASK      0xf
++
++#define PCIE_RC_LCSR                          (PCIE_DSP_PF0_PCIE_CAP_BASE + 0x10)
++
++/* PCIe Port Logic registers (memory-mapped) */
++#define PL_OFFSET                             0x700
++#define PCIE_PL_PFLR                          (PL_OFFSET + 0x08)
++#define PCIE_PL_PFLR_LINK_STATE_MASK          (0x3f << 16)
++#define PCIE_PL_PFLR_FORCE_LINK                       (1 << 15)
++#define PCIE_PHY_DEBUG_R0                     (PL_OFFSET + 0x28)
++#define PCIE_PHY_DEBUG_R1                     (PL_OFFSET + 0x2c)
++#define PCIE_PL_GEN2_CTRL_OFF                 (PL_OFFSET + 0x10c)
++#define PCIE_PL_DIRECTED_SPEED_CHANGE_OFF     0x20000
++
++#define PCIE_PHY_CTRL                         (PL_OFFSET + 0x114)
++#define PCIE_PHY_CTRL_DATA_LOC                        0
++#define PCIE_PHY_CTRL_CAP_ADR_LOC             16
++#define PCIE_PHY_CTRL_CAP_DAT_LOC             17
++#define PCIE_PHY_CTRL_WR_LOC                  18
++#define PCIE_PHY_CTRL_RD_LOC                  19
++
++#define PCIE_PHY_STAT                         (PL_OFFSET + 0x110)
++#define PCIE_PHY_STAT_ACK_LOC                 16
++
++#define PCIE_LINK_WIDTH_SPEED_CONTROL         0x80C
++
++#define PCIE_PHY_MAX_RETRY_CNT                        1000
++
++static void fu740_pcie_assert_perstn(struct fu740_pcie *afp)
++{
++      /* PERST_N GPIO */
++      if (gpio_is_valid(afp->perstn_gpio))
++              gpio_direction_output(afp->perstn_gpio, 0);
++
++      /* Controller PERST_N */
++      __raw_writel(0x0, afp->mgmt_base + PCIEX8MGMT_PERST_N);
++}
++
++static void fu740_pcie_deassert_perstn(struct fu740_pcie *afp)
++{
++      /* Controller PERST_N */
++      __raw_writel(0x1, afp->mgmt_base + PCIEX8MGMT_PERST_N);
++      /* PERST_N GPIO */
++      if (gpio_is_valid(afp->perstn_gpio))
++              gpio_direction_output(afp->perstn_gpio, 1);
++}
++
++static void fu740_pcie_power_on(struct fu740_pcie *afp)
++{
++      if (gpio_is_valid(afp->pwren_gpio)) {
++              gpio_direction_output(afp->pwren_gpio, 1);
++              mdelay(100);
++      }
++}
++
++static void fu740_pcie_drive_perstn(struct fu740_pcie *afp)
++{
++      fu740_pcie_assert_perstn(afp);
++      fu740_pcie_power_on(afp);
++      fu740_pcie_deassert_perstn(afp);
++}
++
++static void fu740_phyregreadwrite(const uint8_t phy, const uint8_t write,
++                              const uint16_t addr,
++                              const uint16_t wrdata, uint16_t *rddata,
++                              struct fu740_pcie *afp)
++{
++      unsigned char ack = 0;
++      unsigned int cnt = 0;
++      struct device *dev = afp->pci->dev;
++
++      /* setup */
++      __raw_writel(addr,
++                   afp->mgmt_base +
++                   (phy ? PCIEX8MGMT_PHY1_CR_PARA_ADDR :
++                    PCIEX8MGMT_PHY0_CR_PARA_ADDR));
++      if (write)
++              __raw_writel(wrdata,
++                           afp->mgmt_base +
++                           (phy ? PCIEX8MGMT_PHY1_CR_PARA_WR_DATA :
++                            PCIEX8MGMT_PHY0_CR_PARA_WR_DATA));
++      if (write)
++              __raw_writel(1,
++                           afp->mgmt_base +
++                           (phy ? PCIEX8MGMT_PHY1_CR_PARA_WR_EN :
++                            PCIEX8MGMT_PHY0_CR_PARA_WR_EN));
++      else
++              __raw_writel(1,
++                           afp->mgmt_base +
++                           (phy ? PCIEX8MGMT_PHY1_CR_PARA_RD_EN :
++                            PCIEX8MGMT_PHY0_CR_PARA_RD_EN));
++
++      /* wait for wait_idle */
++      do {
++              if (__raw_readl
++                  (afp->mgmt_base +
++                   (phy ? PCIEX8MGMT_PHY1_CR_PARA_ACK :
++                    PCIEX8MGMT_PHY0_CR_PARA_ACK))) {
++                      ack = 1;
++                      if (!write)
++                              __raw_readl(afp->mgmt_base +
++                                          (phy ?
++                                           PCIEX8MGMT_PHY1_CR_PARA_RD_DATA :
++                                           PCIEX8MGMT_PHY0_CR_PARA_RD_DATA));
++              }
++      } while (!ack);
++
++      /* clear */
++      if (write)
++              __raw_writel(0,
++                           afp->mgmt_base +
++                           (phy ? PCIEX8MGMT_PHY1_CR_PARA_WR_EN :
++                            PCIEX8MGMT_PHY0_CR_PARA_WR_EN));
++      else
++              __raw_writel(0,
++                           afp->mgmt_base +
++                           (phy ? PCIEX8MGMT_PHY1_CR_PARA_RD_EN :
++                            PCIEX8MGMT_PHY0_CR_PARA_RD_EN));
++
++      /* wait for ~wait_idle */
++      while (__raw_readl
++             (afp->mgmt_base +
++              (phy ? PCIEX8MGMT_PHY1_CR_PARA_ACK :
++               PCIEX8MGMT_PHY0_CR_PARA_ACK))) {
++              cpu_relax();
++              cnt++;
++              if (cnt > PCIE_PHY_MAX_RETRY_CNT) {
++                      dev_err(dev, "PCIE phy doesn't enter idle state.\n");
++                      break;
++              }
++      }
++}
++
++static void fu740_pcie_init_phy(struct fu740_pcie *afp)
++{
++      int lane;
++
++      /* enable phy cr_para_sel interfaces */
++      __raw_writel(0x1, afp->mgmt_base + PCIEX8MGMT_PHY0_CR_PARA_SEL);
++      __raw_writel(0x1, afp->mgmt_base + PCIEX8MGMT_PHY1_CR_PARA_SEL);
++
++      /* wait 10 cr_para cycles */
++      msleep(1);
++
++      /* set PHY AC termination mode */
++      for (lane = 0; lane < 4; lane++) {
++              fu740_phyregreadwrite(0, 1,
++                                   0x1008 + (0x100 * lane),
++                                   0x0e21, NULL, afp);
++              fu740_phyregreadwrite(1, 1,
++                                   0x1008 + (0x100 * lane),
++                                   0x0e21, NULL, afp);
++      }
++
++}
++
++static int fu740_pcie_wait_for_link(struct fu740_pcie *afp)
++{
++      struct dw_pcie *pci = afp->pci;
++
++      /* check if the link is up or not */
++      if (!dw_pcie_wait_for_link(pci))
++              return 0;
++
++      return -ETIMEDOUT;
++}
++
++static void fu740_pcie_ltssm_enable(struct device *dev)
++{
++      struct fu740_pcie *afp = dev_get_drvdata(dev);
++
++      /* Enable LTSSM */
++      __raw_writel(0x1, afp->mgmt_base + PCIEX8MGMT_APP_LTSSM_ENABLE);
++}
++
++static int fu740_pcie_establish_link(struct fu740_pcie *afp)
++{
++      struct dw_pcie *pci = afp->pci;
++      struct device *dev = pci->dev;
++      u32 tmp;
++      int ret;
++
++      /*
++       * Force Gen1 operation when starting the link.  In case the link is
++       * started in Gen2 mode, there is a possibility the devices on the
++       * bus will not be detected at all.  This happens with PCIe switches.
++       */
++      dw_pcie_dbi_ro_wr_en(pci);
++      tmp = dw_pcie_readl_dbi(pci, PCIE_RC_LCR);
++      tmp &= ~PCIE_RC_LCR_MAX_LINK_SPEEDS_MASK;
++      tmp |= PCIE_RC_LCR_MAX_LINK_SPEEDS_GEN1;
++      dw_pcie_writel_dbi(pci, PCIE_RC_LCR, tmp);
++      dw_pcie_dbi_ro_wr_dis(pci);
++
++      /* Start LTSSM. */
++      fu740_pcie_ltssm_enable(dev);
++
++      ret = fu740_pcie_wait_for_link(afp);
++      if (ret)
++              goto err_reset_phy;
++
++      /* Now set it to operate in Gen3 */
++      dw_pcie_dbi_ro_wr_en(pci);
++      tmp = dw_pcie_readl_dbi(pci, PCIE_RC_LCR);
++      tmp &= ~PCIE_RC_LCR_MAX_LINK_SPEEDS_MASK;
++      tmp |= PCIE_RC_LCR_MAX_LINK_SPEEDS_GEN3;
++      dw_pcie_writel_dbi(pci, PCIE_RC_LCR, tmp);
++      /* Enable DIRECTED SPEED CHANGE bit of GEN2_CTRL_OFF register */
++      tmp = dw_pcie_readl_dbi(pci, PCIE_PL_GEN2_CTRL_OFF);
++      tmp |= PCIE_PL_DIRECTED_SPEED_CHANGE_OFF;
++      dw_pcie_writel_dbi(pci, PCIE_PL_GEN2_CTRL_OFF, tmp);
++      dw_pcie_dbi_ro_wr_dis(pci);
++
++      ret = fu740_pcie_wait_for_link(afp);
++      if (ret)
++              goto err_reset_phy;
++
++      /*
++       * Reenable DIRECTED SPEED CHANGE.
++       *
++       * You need to set this bit after each speed change, but after
++       * reaching G1, setting it once doesn't seem to work (it reaches G3
++       * equalization states and then times out, falls back to G1). But
++       * If after that, you set it again, it then reaches G3 perfectly
++       * fine.
++       */
++      dw_pcie_dbi_ro_wr_en(pci);
++      tmp = dw_pcie_readl_dbi(pci, PCIE_PL_GEN2_CTRL_OFF);
++      tmp |= PCIE_PL_DIRECTED_SPEED_CHANGE_OFF;
++      dw_pcie_writel_dbi(pci, PCIE_PL_GEN2_CTRL_OFF, tmp);
++      dw_pcie_dbi_ro_wr_dis(pci);
++
++      ret = fu740_pcie_wait_for_link(afp);
++      if (ret)
++              goto err_reset_phy;
++
++      tmp = dw_pcie_readl_dbi(pci, PCIE_RC_LCSR);
++      dev_info(dev, "Link up, Gen%i\n", (tmp >> 16) & 0xf);
++      return 0;
++
++ err_reset_phy:
++      dev_err(dev, "PHY DEBUG_R0=0x%08x DEBUG_R1=0x%08x\n",
++              dw_pcie_readl_dbi(pci, PCIE_PHY_DEBUG_R0),
++              dw_pcie_readl_dbi(pci, PCIE_PHY_DEBUG_R1));
++      return ret;
++}
++
++static int fu740_pcie_host_init(struct pcie_port *pp)
++{
++      struct dw_pcie *pci = to_dw_pcie_from_pp(pp);
++      struct fu740_pcie *afp = to_fu740_pcie(pci);
++      struct device *dev = pci->dev;
++      int ret = 0;
++
++      /* power on reset */
++      fu740_pcie_drive_perstn(afp);
++
++      /* enable pcieauxclk */
++      ret = clk_prepare_enable(afp->pcie_aux);
++      if (ret)
++              dev_err(dev, "unable to enable pcie_aux clock\n");
++
++      /*
++       * assert hold_phy_rst (hold the controller LTSSM in reset after
++       * power_up_rst_n
++       * for register programming with cr_para)
++       */
++      __raw_writel(0x1, afp->mgmt_base + PCIEX8MGMT_APP_HOLD_PHY_RST);
++
++      /* deassert power_up_rst_n */
++      ret = reset_control_deassert(afp->rst);
++      if (ret)
++              dev_err(dev, "unable to deassert pcie_power_up_rst_n\n");
++
++      fu740_pcie_init_phy(afp);
++
++      /* disable pcieauxclk */
++      clk_disable_unprepare(afp->pcie_aux);
++      /* clear hold_phy_rst */
++      __raw_writel(0x0, afp->mgmt_base + PCIEX8MGMT_APP_HOLD_PHY_RST);
++      /* enable pcieauxclk */
++      ret = clk_prepare_enable(afp->pcie_aux);
++      /* set RC mode */
++      __raw_writel(0x4, afp->mgmt_base + PCIEX8MGMT_DEVICE_TYPE);
++
++      dw_pcie_setup_rc(pp);
++      fu740_pcie_establish_link(afp);
++
++      if (IS_ENABLED(CONFIG_PCI_MSI))
++              dw_pcie_msi_init(pp);
++
++      return 0;
++}
++
++static const struct dw_pcie_host_ops fu740_pcie_host_ops = {
++      .host_init = fu740_pcie_host_init,
++};
++
++static irqreturn_t fu740_pcie_msi_handler(int irq, void *arg)
++{
++      struct fu740_pcie *afp = arg;
++      struct dw_pcie *pci = afp->pci;
++      struct pcie_port *pp = &pci->pp;
++
++      return dw_handle_msi_irq(pp);
++}
++
++static int fu740_pcie_add_pcie_port(struct fu740_pcie *afp,
++                                 struct platform_device *pdev)
++{
++      struct dw_pcie *pci = afp->pci;
++      struct pcie_port *pp = &pci->pp;
++      struct device *dev = &pdev->dev;
++      int ret;
++
++      if (IS_ENABLED(CONFIG_PCI_MSI)) {
++              pp->msi_irq = platform_get_irq_byname(pdev, "msi");
++              if (pp->msi_irq <= 0) {
++                      dev_err(dev, "failed to get MSI irq\n");
++                      return -ENODEV;
++              }
++
++              ret = devm_request_irq(dev, pp->msi_irq,
++                                     fu740_pcie_msi_handler,
++                                     IRQF_SHARED | IRQF_NO_THREAD,
++                                     "fu740-pcie-msi", afp);
++              if (ret) {
++                      dev_err(dev, "failed to request MSI irq\n");
++                      return ret;
++              }
++      }
++
++      pp->ops = &fu740_pcie_host_ops;
++
++      ret = dw_pcie_host_init(pp);
++      if (ret) {
++              dev_err(dev, "failed to initialize host\n");
++              return ret;
++      }
++
++      return 0;
++}
++
++static const struct dw_pcie_ops dw_pcie_ops = { };
++
++static const struct dev_pm_ops fu740_pcie_pm_ops = {
++      SET_NOIRQ_SYSTEM_SLEEP_PM_OPS(fu740_pcie_suspend_noirq,
++                                    fu740_pcie_resume_noirq)
++};
++
++static int fu740_pcie_probe(struct platform_device *pdev)
++{
++      struct device *dev = &pdev->dev;
++      struct dw_pcie *pci;
++      struct fu740_pcie *afp;
++      struct resource *dbi_res, *mgmt_res;
++      struct device_node *node = dev->of_node;
++      int ret;
++      u16 val;
++
++      afp = devm_kzalloc(dev, sizeof(*afp), GFP_KERNEL);
++      if (!afp)
++              return -ENOMEM;
++
++      pci = devm_kzalloc(dev, sizeof(*pci), GFP_KERNEL);
++      if (!pci)
++              return -ENOMEM;
++
++      pci->dev = dev;
++      pci->ops = &dw_pcie_ops;
++
++      afp->pci = pci;
++
++      dbi_res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "dbi");
++      if (!dbi_res) {
++              dev_warn(dev, "missing required dbi address range");
++              return -ENOENT;
++      }
++      pci->dbi_base = devm_ioremap_resource(dev, dbi_res);
++      if (IS_ERR(pci->dbi_base))
++              return PTR_ERR(pci->dbi_base);
++
++      mgmt_res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "mgmt");
++      if (!mgmt_res) {
++              dev_warn(dev, "missing required mgmt address range");
++              return -ENOENT;
++      }
++      afp->mgmt_base = devm_ioremap_resource(dev, mgmt_res);
++      if (IS_ERR(afp->mgmt_base))
++              return PTR_ERR(afp->mgmt_base);
++
++      /* Fetch GPIOs */
++      afp->perstn_gpio = of_get_named_gpio(node, "perstn-gpios", 0);
++      if (gpio_is_valid(afp->perstn_gpio)) {
++              ret = devm_gpio_request_one(dev, afp->perstn_gpio,
++                                          GPIOF_OUT_INIT_LOW, "perstn-gpios");
++              if (ret) {
++                      dev_err(dev, "unable to get perstn gpio\n");
++                      return ret;
++              }
++      } else if (afp->perstn_gpio == -EPROBE_DEFER) {
++              dev_err(dev, "perst-gpios EPROBE_DEFER\n");
++              return afp->perstn_gpio;
++      }
++
++      afp->pwren_gpio = of_get_named_gpio(node, "pwren-gpios", 0);
++      if (gpio_is_valid(afp->pwren_gpio)) {
++              ret = devm_gpio_request_one(dev, afp->pwren_gpio,
++                                          GPIOF_OUT_INIT_LOW, "pwren-gpios");
++              if (ret) {
++                      dev_err(dev, "unable to get pwren gpio\n");
++                      return ret;
++              }
++      } else if (afp->pwren_gpio == -EPROBE_DEFER) {
++              dev_err(dev, "pwren-gpios EPROBE_DEFER\n");
++              return afp->pwren_gpio;
++      }
++
++      /* Fetch clocks */
++      afp->pcie_aux = devm_clk_get(dev, "pcie_aux");
++      if (IS_ERR(afp->pcie_aux))
++              return dev_err_probe(dev, PTR_ERR(afp->pcie_aux),
++                                           "pcie_aux clock source missing or invalid\n");
++
++      /* Fetch reset */
++      afp->rst = devm_reset_control_get(dev, NULL);
++      if (IS_ERR(afp->rst))
++              return dev_err_probe(dev, PTR_ERR(afp->rst), "unable to get reset\n");
++
++      platform_set_drvdata(pdev, afp);
++
++      ret = fu740_pcie_add_pcie_port(afp, pdev);
++      if (ret < 0)
++              return ret;
++
++      if (pci_msi_enabled()) {
++              val = dw_pcie_readw_dbi(pci, PCI_MSI_CAP_ID_NEXT_CTRL_REG +
++                                      PCI_MSI_FLAGS);
++              val |= PCI_MSI_FLAGS_ENABLE;
++              dw_pcie_writew_dbi(pci, PCI_MSI_CAP_ID_NEXT_CTRL_REG +
++                                 PCI_MSI_FLAGS, val);
++      }
++
++      return 0;
++}
++
++static void fu740_pcie_shutdown(struct platform_device *pdev)
++{
++      struct fu740_pcie *afp = platform_get_drvdata(pdev);
++
++      /* bring down link, so bootloader gets clean state in case of reboot */
++      fu740_pcie_assert_perstn(afp);
++}
++
++static const struct of_device_id fu740_pcie_of_match[] = {
++      {.compatible = "sifive,fu740-pcie"},
++      {},
++};
++
++static struct platform_driver fu740_pcie_driver = {
++      .driver = {
++                 .name = "fu740-pcie",
++                 .of_match_table = fu740_pcie_of_match,
++                 .suppress_bind_attrs = true,
++                 .pm = &fu740_pcie_pm_ops,
++                 },
++      .probe = fu740_pcie_probe,
++      .shutdown = fu740_pcie_shutdown,
++};
++
++static int __init fu740_pcie_init(void)
++{
++      return platform_driver_register(&fu740_pcie_driver);
++}
++
++device_initcall(fu740_pcie_init);
+-- 
+2.7.4
+
diff --git a/target/linux/hifiveu/patches-5.10/0030-riscv-enable-generic-PCI-resource-mapping.patch b/target/linux/hifiveu/patches-5.10/0030-riscv-enable-generic-PCI-resource-mapping.patch
new file mode 100644 (file)
index 0000000..f27007b
--- /dev/null
@@ -0,0 +1,32 @@
+From 63d7d0e6553ed2990fec51b3f449e50153461650 Mon Sep 17 00:00:00 2001
+From: Stanislaw Kardach <kda@semihalf.com>
+Date: Mon, 12 Apr 2021 13:10:12 +0200
+Subject: [PATCH 28/28] riscv: enable generic PCI resource mapping
+
+Enable the PCI resource mapping on RISC-V using the generic framework.
+This allows userspace applications to mmap PCI resources using
+/sys/devices/pci*/*/resource* interface.
+The mmap has been tested with Intel x520-DA2 NIC card on a HiFive
+Unmatched board (SiFive FU740 SoC).
+
+Signed-off-by: Stanislaw Kardach <kda@semihalf.com>
+---
+ arch/riscv/include/asm/pci.h | 2 ++
+ 1 file changed, 2 insertions(+)
+
+diff --git a/arch/riscv/include/asm/pci.h b/arch/riscv/include/asm/pci.h
+index 1c473a1..46e844f 100644
+--- a/arch/riscv/include/asm/pci.h
++++ b/arch/riscv/include/asm/pci.h
+@@ -18,6 +18,8 @@
+ /* RISC-V shim does not initialize PCI bus */
+ #define pcibios_assign_all_busses() 1
++#define ARCH_GENERIC_PCI_MMAP_RESOURCE 1
++
+ extern int isa_dma_bridge_buggy;
+ #ifdef CONFIG_PCI
+-- 
+2.7.4
+
diff --git a/target/linux/hifiveu/patches-5.10/0031-SiFive-Unleashed-CPUFreq.patch b/target/linux/hifiveu/patches-5.10/0031-SiFive-Unleashed-CPUFreq.patch
new file mode 100644 (file)
index 0000000..aab74c0
--- /dev/null
@@ -0,0 +1,129 @@
+From 35f046065b988ea1b29df78728f5dbb6877aadc4 Mon Sep 17 00:00:00 2001
+From: David Abdurachmanov <david.abdurachmanov@sifive.com>
+Date: Tue, 28 Jan 2020 02:55:56 -0800
+Subject: [PATCH 4/7] SiFive Unleashed CPUFreq
+
+Source: https://github.com/sifive/riscv-linux/commits/dev/paulw/cpufreq-dt-aloe-v5.3-rc4
+
+Signed-off-by: David Abdurachmanov <david.abdurachmanov@sifive.com>
+Upstream-Status: Not posted for a review
+---
+ arch/riscv/Kconfig                                 |  8 +++++
+ arch/riscv/boot/dts/sifive/fu540-c000.dtsi         |  5 ++++
+ .../riscv/boot/dts/sifive/hifive-unleashed-a00.dts | 34 ++++++++++++++++++++++
+ arch/riscv/configs/defconfig                       |  5 ++++
+ 4 files changed, 52 insertions(+)
+
+diff --git a/arch/riscv/Kconfig b/arch/riscv/Kconfig
+index fa7dc03..73b1138 100644
+--- a/arch/riscv/Kconfig
++++ b/arch/riscv/Kconfig
+@@ -356,6 +356,14 @@ endchoice
+ endmenu
++menu "CPU Power Management"
++
++source "drivers/cpuidle/Kconfig"
++
++source "drivers/cpufreq/Kconfig"
++
++endmenu
++
+ menu "Power management options"
+ source "kernel/power/Kconfig"
+diff --git a/arch/riscv/boot/dts/sifive/fu540-c000.dtsi b/arch/riscv/boot/dts/sifive/fu540-c000.dtsi
+index a2e3d54..a380bc7 100644
+--- a/arch/riscv/boot/dts/sifive/fu540-c000.dtsi
++++ b/arch/riscv/boot/dts/sifive/fu540-c000.dtsi
+@@ -30,6 +30,7 @@
+                       i-cache-size = <16384>;
+                       reg = <0>;
+                       riscv,isa = "rv64imac";
++                      clocks = <&prci PRCI_CLK_COREPLL>;
+                       status = "disabled";
+                       cpu0_intc: interrupt-controller {
+                               #interrupt-cells = <1>;
+@@ -54,6 +55,7 @@
+                       reg = <1>;
+                       riscv,isa = "rv64imafdc";
+                       tlb-split;
++                      clocks = <&prci PRCI_CLK_COREPLL>;
+                       next-level-cache = <&l2cache>;
+                       cpu1_intc: interrupt-controller {
+                               #interrupt-cells = <1>;
+@@ -78,6 +80,7 @@
+                       reg = <2>;
+                       riscv,isa = "rv64imafdc";
+                       tlb-split;
++                      clocks = <&prci PRCI_CLK_COREPLL>;
+                       next-level-cache = <&l2cache>;
+                       cpu2_intc: interrupt-controller {
+                               #interrupt-cells = <1>;
+@@ -102,6 +105,7 @@
+                       reg = <3>;
+                       riscv,isa = "rv64imafdc";
+                       tlb-split;
++                      clocks = <&prci PRCI_CLK_COREPLL>;
+                       next-level-cache = <&l2cache>;
+                       cpu3_intc: interrupt-controller {
+                               #interrupt-cells = <1>;
+@@ -126,6 +130,7 @@
+                       reg = <4>;
+                       riscv,isa = "rv64imafdc";
+                       tlb-split;
++                      clocks = <&prci PRCI_CLK_COREPLL>;
+                       next-level-cache = <&l2cache>;
+                       cpu4_intc: interrupt-controller {
+                               #interrupt-cells = <1>;
+diff --git a/arch/riscv/boot/dts/sifive/hifive-unleashed-a00.dts b/arch/riscv/boot/dts/sifive/hifive-unleashed-a00.dts
+index 88cfcb9..e1724e3 100644
+--- a/arch/riscv/boot/dts/sifive/hifive-unleashed-a00.dts
++++ b/arch/riscv/boot/dts/sifive/hifive-unleashed-a00.dts
+@@ -41,6 +41,40 @@
+               clock-frequency = <RTCCLK_FREQ>;
+               clock-output-names = "rtcclk";
+       };
++
++      fu540_c000_opp_table: opp-table {
++              compatible = "operating-points-v2";
++              opp-shared;
++
++              opp-350000000 {
++                      opp-hz = /bits/ 64 <350000000>;
++              };
++              opp-700000000 {
++                      opp-hz = /bits/ 64 <700000000>;
++              };
++              opp-999999999 {
++                      opp-hz = /bits/ 64 <999999999>;
++              };
++              opp-1400000000 {
++                      opp-hz = /bits/ 64 <1400000000>;
++              };
++      };
++};
++
++&cpu0 {
++      operating-points-v2 = <&fu540_c000_opp_table>;
++};
++&cpu1 {
++      operating-points-v2 = <&fu540_c000_opp_table>;
++};
++&cpu2 {
++      operating-points-v2 = <&fu540_c000_opp_table>;
++};
++&cpu3 {
++      operating-points-v2 = <&fu540_c000_opp_table>;
++};
++&cpu4 {
++      operating-points-v2 = <&fu540_c000_opp_table>;
+ };
+ &uart0 {
+diff --git a/arch/riscv/configs/defconfig b/arch/riscv/configs/defconfig
+index e2ff95c..a2fb392 100644
+-- 
+2.7.4
+
diff --git a/target/linux/hifiveu/patches-5.10/0040-riscv-sifive-unmatched-add-D12-PWM-LED.patch b/target/linux/hifiveu/patches-5.10/0040-riscv-sifive-unmatched-add-D12-PWM-LED.patch
new file mode 100644 (file)
index 0000000..9650bed
--- /dev/null
@@ -0,0 +1,43 @@
+From ce24ba4d603a19690548b986d87ae2d9af26d015 Mon Sep 17 00:00:00 2001
+From: David Abdurachmanov <david.abdurachmanov@sifive.com>
+Date: Thu, 25 Mar 2021 04:34:52 -0700
+Subject: [PATCH 23/28] riscv: sifive: unmatched: add D12 PWM LED
+
+Signed-off-by: David Abdurachmanov <david.abdurachmanov@sifive.com>
+---
+ arch/riscv/boot/dts/sifive/hifive-unmatched-a00.dts | 12 ++++++++++++
+ 1 file changed, 12 insertions(+)
+
+diff --git a/arch/riscv/boot/dts/sifive/hifive-unmatched-a00.dts b/arch/riscv/boot/dts/sifive/hifive-unmatched-a00.dts
+index e026f60..8461b33 100644
+--- a/arch/riscv/boot/dts/sifive/hifive-unmatched-a00.dts
++++ b/arch/riscv/boot/dts/sifive/hifive-unmatched-a00.dts
+@@ -3,6 +3,7 @@
+ #include "fu740-c000.dtsi"
+ #include <dt-bindings/interrupt-controller/irq.h>
++#include <dt-bindings/pwm/pwm.h>
+ /* Clock frequency (in Hz) of the PCB crystal for rtcclk */
+ #define RTCCLK_FREQ           1000000
+@@ -30,6 +31,17 @@
+       soc {
+       };
++      pwmleds {
++              compatible = "pwm-leds";
++              d12 {
++                      label = "green:d12";
++                      pwms = <&pwm0 0 7812500 PWM_POLARITY_INVERTED>;
++                      active-low = <1>;
++                      max-brightness = <255>;
++                      linux,default-trigger = "none";
++              };
++      };
++
+       hfclk: hfclk {
+               #clock-cells = <0>;
+               compatible = "fixed-clock";
+-- 
+2.7.4
+
diff --git a/target/linux/hifiveu/patches-5.10/0041-riscv-sifive-unmatched-add-gpio-poweroff-node.patch b/target/linux/hifiveu/patches-5.10/0041-riscv-sifive-unmatched-add-gpio-poweroff-node.patch
new file mode 100644 (file)
index 0000000..a44c774
--- /dev/null
@@ -0,0 +1,37 @@
+From f19634daf24481664cdc89dc0b5abd9b622718f5 Mon Sep 17 00:00:00 2001
+From: David Abdurachmanov <david.abdurachmanov@sifive.com>
+Date: Thu, 25 Mar 2021 04:37:20 -0700
+Subject: [PATCH 24/28] riscv: sifive: unmatched: add gpio-poweroff node
+
+Signed-off-by: David Abdurachmanov <david.abdurachmanov@sifive.com>
+---
+ arch/riscv/boot/dts/sifive/hifive-unmatched-a00.dts | 6 ++++++
+ 1 file changed, 6 insertions(+)
+
+diff --git a/arch/riscv/boot/dts/sifive/hifive-unmatched-a00.dts b/arch/riscv/boot/dts/sifive/hifive-unmatched-a00.dts
+index 8461b33..9a7fa9b 100644
+--- a/arch/riscv/boot/dts/sifive/hifive-unmatched-a00.dts
++++ b/arch/riscv/boot/dts/sifive/hifive-unmatched-a00.dts
+@@ -2,6 +2,7 @@
+ /* Copyright (c) 2020 SiFive, Inc */
+ #include "fu740-c000.dtsi"
++#include <dt-bindings/gpio/gpio.h>
+ #include <dt-bindings/interrupt-controller/irq.h>
+ #include <dt-bindings/pwm/pwm.h>
+@@ -55,6 +56,11 @@
+               clock-frequency = <RTCCLK_FREQ>;
+               clock-output-names = "rtcclk";
+       };
++
++      gpio-poweroff {
++              compatible = "gpio-poweroff";
++              gpios = <&gpio 2 GPIO_ACTIVE_LOW>;
++      };
+ };
+ &uart0 {
+-- 
+2.7.4
+
diff --git a/target/linux/hifiveu/patches-5.10/0042-riscv-sifive-unmatched-add-D2-RGB-LED.patch b/target/linux/hifiveu/patches-5.10/0042-riscv-sifive-unmatched-add-D2-RGB-LED.patch
new file mode 100644 (file)
index 0000000..ad989eb
--- /dev/null
@@ -0,0 +1,56 @@
+From 2d375478fd6b5eeea711d081502cc8fd1a22987d Mon Sep 17 00:00:00 2001
+From: David Abdurachmanov <david.abdurachmanov@sifive.com>
+Date: Fri, 2 Apr 2021 06:31:07 -0700
+Subject: [PATCH 25/28] riscv: sifive: unmatched: add D2 RGB LED
+
+Signed-off-by: David Abdurachmanov <david.abdurachmanov@sifive.com>
+---
+ .../riscv/boot/dts/sifive/hifive-unmatched-a00.dts | 26 +++++++++++++++++++++-
+ 1 file changed, 25 insertions(+), 1 deletion(-)
+
+diff --git a/arch/riscv/boot/dts/sifive/hifive-unmatched-a00.dts b/arch/riscv/boot/dts/sifive/hifive-unmatched-a00.dts
+index 9a7fa9b..235f78a 100644
+--- a/arch/riscv/boot/dts/sifive/hifive-unmatched-a00.dts
++++ b/arch/riscv/boot/dts/sifive/hifive-unmatched-a00.dts
+@@ -34,13 +34,37 @@
+       pwmleds {
+               compatible = "pwm-leds";
+-              d12 {
++              green-d12 {
+                       label = "green:d12";
+                       pwms = <&pwm0 0 7812500 PWM_POLARITY_INVERTED>;
+                       active-low = <1>;
+                       max-brightness = <255>;
+                       linux,default-trigger = "none";
+               };
++
++              green-d2 {
++                      label = "green:d2";
++                      pwms = <&pwm0 1 7812500 PWM_POLARITY_INVERTED>;
++                      active-low = <1>;
++                      max-brightness = <255>;
++                      linux,default-trigger = "none";
++              };
++
++              red-d2 {
++                      label = "red:d2";
++                      pwms = <&pwm0 2 7812500 PWM_POLARITY_INVERTED>;
++                      active-low = <1>;
++                      max-brightness = <255>;
++                      linux,default-trigger = "none";
++              };
++
++              blue-d2 {
++                      label = "blue:d2";
++                      pwms = <&pwm0 3 7812500 PWM_POLARITY_INVERTED>;
++                      active-low = <1>;
++                      max-brightness = <255>;
++                      linux,default-trigger = "none";
++              };
+       };
+       hfclk: hfclk {
+-- 
+2.7.4
+
diff --git a/target/linux/hifiveu/patches-5.10/0043-riscv-sifive-unmatched-remove-A00-from-model.patch b/target/linux/hifiveu/patches-5.10/0043-riscv-sifive-unmatched-remove-A00-from-model.patch
new file mode 100644 (file)
index 0000000..b3c3483
--- /dev/null
@@ -0,0 +1,26 @@
+From 45ed220373844f72e9ddb05ef0a8f2bd391e0980 Mon Sep 17 00:00:00 2001
+From: David Abdurachmanov <david.abdurachmanov@sifive.com>
+Date: Tue, 6 Apr 2021 05:00:11 -0700
+Subject: [PATCH 26/28] riscv: sifive: unmatched: remove "A00" from model
+
+Signed-off-by: David Abdurachmanov <david.abdurachmanov@sifive.com>
+---
+ arch/riscv/boot/dts/sifive/hifive-unmatched-a00.dts | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/arch/riscv/boot/dts/sifive/hifive-unmatched-a00.dts b/arch/riscv/boot/dts/sifive/hifive-unmatched-a00.dts
+index 235f78a..5fdd183 100644
+--- a/arch/riscv/boot/dts/sifive/hifive-unmatched-a00.dts
++++ b/arch/riscv/boot/dts/sifive/hifive-unmatched-a00.dts
+@@ -12,7 +12,7 @@
+ / {
+       #address-cells = <2>;
+       #size-cells = <2>;
+-      model = "SiFive HiFive Unmatched A00";
++      model = "SiFive HiFive Unmatched";
+       compatible = "sifive,hifive-unmatched-a00", "sifive,fu740-c000",
+                    "sifive,fu740";
+-- 
+2.7.4
+
diff --git a/target/linux/hifiveu/patches-5.10/0044-riscv-sifive-unmatched-define-LEDs-color.patch b/target/linux/hifiveu/patches-5.10/0044-riscv-sifive-unmatched-define-LEDs-color.patch
new file mode 100644 (file)
index 0000000..8d5d606
--- /dev/null
@@ -0,0 +1,57 @@
+From 665297adfa377a3682b261b23f2a6f3ec56daa8b Mon Sep 17 00:00:00 2001
+From: David Abdurachmanov <david.abdurachmanov@sifive.com>
+Date: Wed, 7 Apr 2021 06:08:33 -0700
+Subject: [PATCH 27/28] riscv: sifive: unmatched: define LEDs color
+
+Signed-off-by: David Abdurachmanov <david.abdurachmanov@sifive.com>
+---
+ arch/riscv/boot/dts/sifive/hifive-unmatched-a00.dts | 5 +++++
+ 1 file changed, 5 insertions(+)
+
+diff --git a/arch/riscv/boot/dts/sifive/hifive-unmatched-a00.dts b/arch/riscv/boot/dts/sifive/hifive-unmatched-a00.dts
+index 5fdd183..9be0564 100644
+--- a/arch/riscv/boot/dts/sifive/hifive-unmatched-a00.dts
++++ b/arch/riscv/boot/dts/sifive/hifive-unmatched-a00.dts
+@@ -4,6 +4,7 @@
+ #include "fu740-c000.dtsi"
+ #include <dt-bindings/gpio/gpio.h>
+ #include <dt-bindings/interrupt-controller/irq.h>
++#include <dt-bindings/leds/common.h>
+ #include <dt-bindings/pwm/pwm.h>
+ /* Clock frequency (in Hz) of the PCB crystal for rtcclk */
+@@ -36,6 +37,7 @@
+               compatible = "pwm-leds";
+               green-d12 {
+                       label = "green:d12";
++                      color = <LED_COLOR_ID_GREEN>;
+                       pwms = <&pwm0 0 7812500 PWM_POLARITY_INVERTED>;
+                       active-low = <1>;
+                       max-brightness = <255>;
+@@ -44,6 +46,7 @@
+               green-d2 {
+                       label = "green:d2";
++                      color = <LED_COLOR_ID_GREEN>;
+                       pwms = <&pwm0 1 7812500 PWM_POLARITY_INVERTED>;
+                       active-low = <1>;
+                       max-brightness = <255>;
+@@ -52,6 +55,7 @@
+               red-d2 {
+                       label = "red:d2";
++                      color = <LED_COLOR_ID_RED>;
+                       pwms = <&pwm0 2 7812500 PWM_POLARITY_INVERTED>;
+                       active-low = <1>;
+                       max-brightness = <255>;
+@@ -60,6 +64,7 @@
+               blue-d2 {
+                       label = "blue:d2";
++                      color = <LED_COLOR_ID_BLUE>;
+                       pwms = <&pwm0 3 7812500 PWM_POLARITY_INVERTED>;
+                       active-low = <1>;
+                       max-brightness = <255>;
+-- 
+2.7.4
+
diff --git a/target/linux/hifiveu/patches-5.10/0045-Add-PWM-LEDs-D1-D2-D3-D4.patch b/target/linux/hifiveu/patches-5.10/0045-Add-PWM-LEDs-D1-D2-D3-D4.patch
new file mode 100644 (file)
index 0000000..c79d1a1
--- /dev/null
@@ -0,0 +1,66 @@
+From c1c831af223931219b7bf9158b1306b500116167 Mon Sep 17 00:00:00 2001
+From: David Abdurachmanov <david.abdurachmanov@sifive.com>
+Date: Fri, 5 Jun 2020 07:02:10 +0000
+Subject: [PATCH] SiFive HiFive Unleashed: Add PWM LEDs (D1, D2, D3, D4)
+
+By default no functions are assigned to LEDs. It's up to user/distribution
+to provide udev rules to configure them.
+
+Signed-off-by: David Abdurachmanov <david.abdurachmanov@sifive.com>
+---
+ .../riscv/boot/dts/sifive/hifive-unleashed-a00.dts | 32 ++++++++++++++++++++++
+ 1 file changed, 32 insertions(+)
+
+diff --git a/arch/riscv/boot/dts/sifive/hifive-unleashed-a00.dts b/arch/riscv/boot/dts/sifive/hifive-unleashed-a00.dts
+index 6dd6fa4..c8a47bf 100644
+--- a/arch/riscv/boot/dts/sifive/hifive-unleashed-a00.dts
++++ b/arch/riscv/boot/dts/sifive/hifive-unleashed-a00.dts
+@@ -3,6 +3,7 @@
+ #include "fu540-c000.dtsi"
+ #include <dt-bindings/gpio/gpio.h>
++#include <dt-bindings/pwm/pwm.h>
+ /* Clock frequency (in Hz) of the PCB crystal for rtcclk */
+ #define RTCCLK_FREQ           1000000
+@@ -27,6 +28,37 @@
+       };
+       soc {
++              pwmleds {
++                      compatible = "pwm-leds";
++                      d1 {
++                              label = "green:d1";
++                              pwms = <&pwm0 0 7812500 PWM_POLARITY_INVERTED>;
++                              active-low = <1>;
++                              max-brightness = <255>;
++                              linux,default-trigger = "none";
++                      };
++                      d2 {
++                              label = "green:d2";
++                              pwms = <&pwm0 1 7812500 PWM_POLARITY_INVERTED>;
++                              active-low = <1>;
++                              max-brightness = <255>;
++                              linux,default-trigger = "none";
++                      };
++                      d3 {
++                              label = "green:d3";
++                              pwms = <&pwm0 2 7812500 PWM_POLARITY_INVERTED>;
++                              active-low = <1>;
++                              max-brightness = <255>;
++                              linux,default-trigger = "none";
++                      };
++                      d4 {
++                              label = "green:d4";
++                              pwms = <&pwm0 3 7812500 PWM_POLARITY_INVERTED>;
++                              active-low = <1>;
++                              max-brightness = <255>;
++                              linux,default-trigger = "none";
++                      };
++              };
+       };
+       hfclk: hfclk {
+-- 
+2.7.4
+
diff --git a/target/linux/hifiveu/patches-5.10/0100-hifiveu-openwrt-led-changes.patch b/target/linux/hifiveu/patches-5.10/0100-hifiveu-openwrt-led-changes.patch
new file mode 100644 (file)
index 0000000..166abe6
--- /dev/null
@@ -0,0 +1,61 @@
+diff -ruN a/arch/riscv/boot/dts/sifive/hifive-unleashed-a00.dts b/arch/riscv/boot/dts/sifive/hifive-unleashed-a00.dts
+--- a/arch/riscv/boot/dts/sifive/hifive-unleashed-a00.dts      2021-11-06 19:23:11.657526676 +0100
++++ b/arch/riscv/boot/dts/sifive/hifive-unleashed-a00.dts      2021-11-06 19:00:10.140770182 +0100
+@@ -14,6 +14,13 @@
+       model = "SiFive HiFive Unleashed A00";
+       compatible = "sifive,hifive-unleashed-a00", "sifive,fu540-c000";
++      aliases {
++              led-boot = &power_green;
++              led-failsafe = &power_green;
++              led-running = &power_green;
++              led-upgrade = &power_green;
++      };
++
+       chosen {
+               stdout-path = "serial0";
+       };
+@@ -30,7 +37,7 @@
+       soc {
+               pwmleds {
+                       compatible = "pwm-leds";
+-                      d1 {
++                      power_green: d1 {
+                               label = "green:d1";
+                               pwms = <&pwm0 0 7812500 PWM_POLARITY_INVERTED>;
+                               active-low = <1>;
+@@ -56,7 +63,7 @@
+                               pwms = <&pwm0 3 7812500 PWM_POLARITY_INVERTED>;
+                               active-low = <1>;
+                               max-brightness = <255>;
+-                              linux,default-trigger = "none";
++                              linux,default-trigger = "mmc0";
+                       };
+               };
+       };
+diff -ruN a/arch/riscv/boot/dts/sifive/hifive-unmatched-a00.dts b/arch/riscv/boot/dts/sifive/hifive-unmatched-a00.dts
+--- a/arch/riscv/boot/dts/sifive/hifive-unmatched-a00.dts      2021-11-06 19:23:21.949472627 +0100
++++ b/arch/riscv/boot/dts/sifive/hifive-unmatched-a00.dts      2021-11-06 19:21:08.002175934 +0100
+@@ -17,6 +17,13 @@
+       compatible = "sifive,hifive-unmatched-a00", "sifive,fu740-c000",
+                    "sifive,fu740";
++      aliases {
++              led-boot = &power_green;
++              led-failsafe = &power_green;
++              led-running = &power_green;
++              led-upgrade = &power_green;
++      };
++
+       chosen {
+               stdout-path = "serial0";
+       };
+@@ -35,7 +42,7 @@
+       pwmleds {
+               compatible = "pwm-leds";
+-              green-d12 {
++              power_green: green-d12 {
+                       label = "green:d12";
+                       color = <LED_COLOR_ID_GREEN>;
+                       pwms = <&pwm0 0 7812500 PWM_POLARITY_INVERTED>;
diff --git a/target/linux/hifiveu/patches-5.10/0101-riscv_dts_sifive-unmatched_Expose_the_FU740_regulator.patch b/target/linux/hifiveu/patches-5.10/0101-riscv_dts_sifive-unmatched_Expose_the_FU740_regulator.patch
new file mode 100644 (file)
index 0000000..5672b5e
--- /dev/null
@@ -0,0 +1,27 @@
+From 89c9a963944ed10a890b627e2e63e96fbff3aa36 Mon Sep 17 00:00:00 2001
+From: Vincent Pelletier <plr.vincent@gmail.com>
+Date: Sat, 19 Jun 2021 14:36:47 +0000
+Subject: [PATCH] riscv: dts: sifive unmatched: Expose the FU740 core supply
+ regulator.
+
+Signed-off-by: Vincent Pelletier <plr.vincent@gmail.com>
+---
+ arch/riscv/boot/dts/sifive/hifive-unmatched-a00.dts | 5 +++++
+ 1 file changed, 5 insertions(+)
+
+diff --git a/arch/riscv/boot/dts/sifive/hifive-unmatched-a00.dts b/arch/riscv/boot/dts/sifive/hifive-unmatched-a00.dts
+index 9be05644e3c02a..8728391b4a81ef 100644
+--- a/arch/riscv/boot/dts/sifive/hifive-unmatched-a00.dts
++++ b/arch/riscv/boot/dts/sifive/hifive-unmatched-a00.dts
+@@ -103,6 +103,11 @@
+ &i2c0 {
+       status = "okay";
++      tps544b20@1e {
++              compatible = "tps544b20";
++              reg = <0x1e>;
++      };
++
+       temperature-sensor@4c {
+               compatible = "ti,tmp451";
+               reg = <0x4c>;
diff --git a/target/linux/hifiveu/patches-5.10/0102-riscv_dts_sifive-unmatched_Link_tmp451_with_its_psup.patch b/target/linux/hifiveu/patches-5.10/0102-riscv_dts_sifive-unmatched_Link_tmp451_with_its_psup.patch
new file mode 100644 (file)
index 0000000..5692afb
--- /dev/null
@@ -0,0 +1,23 @@
+From c5faf98f30ef3e1a3f56ace78741ccef2e4856aa Mon Sep 17 00:00:00 2001
+From: Vincent Pelletier <plr.vincent@gmail.com>
+Date: Sat, 19 Jun 2021 14:37:27 +0000
+Subject: [PATCH] riscv: dts: sifive unmatched: Link the tmp451 with its power
+ supply.
+
+Signed-off-by: Vincent Pelletier <plr.vincent@gmail.com>
+---
+ arch/riscv/boot/dts/sifive/hifive-unmatched-a00.dts | 1 +
+ 1 file changed, 1 insertion(+)
+
+diff --git a/arch/riscv/boot/dts/sifive/hifive-unmatched-a00.dts b/arch/riscv/boot/dts/sifive/hifive-unmatched-a00.dts
+index 8728391b4a81ef..a6f3556c82ba15 100644
+--- a/arch/riscv/boot/dts/sifive/hifive-unmatched-a00.dts
++++ b/arch/riscv/boot/dts/sifive/hifive-unmatched-a00.dts
+@@ -111,6 +111,7 @@
+       temperature-sensor@4c {
+               compatible = "ti,tmp451";
+               reg = <0x4c>;
++              vcc-supply = <&vdd_bpro>;
+               interrupt-parent = <&gpio>;
+               interrupts = <6 IRQ_TYPE_LEVEL_LOW>;
+       };
diff --git a/target/linux/hifiveu/patches-5.10/0103-riscv_dts_sifive-unmatched_Expose_board_ID_EEPROM.patch b/target/linux/hifiveu/patches-5.10/0103-riscv_dts_sifive-unmatched_Expose_board_ID_EEPROM.patch
new file mode 100644 (file)
index 0000000..e38c39f
--- /dev/null
@@ -0,0 +1,31 @@
+From 3eb8033e1f318477cf87e6e0ea837e75a87856e9 Mon Sep 17 00:00:00 2001
+From: Vincent Pelletier <plr.vincent@gmail.com>
+Date: Sat, 19 Jun 2021 14:37:53 +0000
+Subject: [PATCH] riscv: dts: sifive unmatched: Expose the board ID eeprom.
+
+Signed-off-by: Vincent Pelletier <plr.vincent@gmail.com>
+---
+ arch/riscv/boot/dts/sifive/hifive-unmatched-a00.dts | 10 ++++++++++
+ 1 file changed, 10 insertions(+)
+
+diff --git a/arch/riscv/boot/dts/sifive/hifive-unmatched-a00.dts b/arch/riscv/boot/dts/sifive/hifive-unmatched-a00.dts
+index a6f3556c82ba15..4a7a7352b46dde 100644
+--- a/arch/riscv/boot/dts/sifive/hifive-unmatched-a00.dts
++++ b/arch/riscv/boot/dts/sifive/hifive-unmatched-a00.dts
+@@ -116,6 +116,16 @@
+               interrupts = <6 IRQ_TYPE_LEVEL_LOW>;
+       };
++      eeprom@54 {
++              compatible = "microchip,24c02", "atmel,24c02";
++              reg = <0x54>;
++              vcc-supply = <&vdd_bpro>;
++              label = "board-id";
++              pagesize = <16>;
++              read-only;
++              size = <256>;
++      };
++
+       pmic@58 {
+               compatible = "dlg,da9063";
+               reg = <0x58>;
diff --git a/target/linux/hifiveu/patches-5.10/0104-riscv_dts_sifive_unmatched-Expose_PMIC_sub-funcs.patch b/target/linux/hifiveu/patches-5.10/0104-riscv_dts_sifive_unmatched-Expose_PMIC_sub-funcs.patch
new file mode 100644 (file)
index 0000000..f93e175
--- /dev/null
@@ -0,0 +1,33 @@
+From eeaad1f6ab4fa5f854780587296c71dda9cda3b5 Mon Sep 17 00:00:00 2001
+From: Vincent Pelletier <plr.vincent@gmail.com>
+Date: Sat, 19 Jun 2021 14:40:14 +0000
+Subject: [PATCH] riscv: dts: sifive unmatched: Expose the PMIC sub-functions.
+
+Signed-off-by: Vincent Pelletier <plr.vincent@gmail.com>
+---
+ arch/riscv/boot/dts/sifive/hifive-unmatched-a00.dts | 12 ++++++++++++
+ 1 file changed, 12 insertions(+)
+
+diff --git a/arch/riscv/boot/dts/sifive/hifive-unmatched-a00.dts b/arch/riscv/boot/dts/sifive/hifive-unmatched-a00.dts
+index 4a7a7352b46dde..66d3c50213443a 100644
+--- a/arch/riscv/boot/dts/sifive/hifive-unmatched-a00.dts
++++ b/arch/riscv/boot/dts/sifive/hifive-unmatched-a00.dts
+@@ -133,6 +133,18 @@
+               interrupts = <1 IRQ_TYPE_LEVEL_LOW>;
+               interrupt-controller;
++              onkey {
++                      compatible = "dlg,da9063-onkey";
++              };
++
++              rtc {
++                      compatible = "dlg,da9063-rtc";
++              };
++
++              wdt {
++                      compatible = "dlg,da9063-watchdog";
++              };
++
+               regulators {
+                       vdd_bcore1: bcore1 {
+                               regulator-min-microvolt = <1050000>;
diff --git a/target/linux/hifiveu/patches-5.10/0105-riscv_dts_sifive_unmatched_Expose_fan_PWM.patch b/target/linux/hifiveu/patches-5.10/0105-riscv_dts_sifive_unmatched_Expose_fan_PWM.patch
new file mode 100644 (file)
index 0000000..04e7d19
--- /dev/null
@@ -0,0 +1,33 @@
+From 00a903b88b10f77b053e910f72bd9feb0d5c7c17 Mon Sep 17 00:00:00 2001
+From: Vincent Pelletier <plr.vincent@gmail.com>
+Date: Sat, 19 Jun 2021 14:36:12 +0000
+Subject: [PATCH] riscv: dts: sifive unmatched: Expose fan PWM.
+
+Signed-off-by: Vincent Pelletier <plr.vincent@gmail.com>
+---
+ arch/riscv/boot/dts/sifive/hifive-unmatched-a00.dts | 12 ++++++++++++
+ 1 file changed, 12 insertions(+)
+
+diff --git a/arch/riscv/boot/dts/sifive/hifive-unmatched-a00.dts b/arch/riscv/boot/dts/sifive/hifive-unmatched-a00.dts
+index 73b3f787773859..888a0aa3b7f475 100644
+--- a/arch/riscv/boot/dts/sifive/hifive-unmatched-a00.dts
++++ b/arch/riscv/boot/dts/sifive/hifive-unmatched-a00.dts
+@@ -90,6 +90,18 @@
+               compatible = "gpio-poweroff";
+               gpios = <&gpio 2 GPIO_ACTIVE_LOW>;
+       };
++
++      fan0: asm2824-fan {
++              compatible = "pwm-fan";
++              pwms = <&pwm1 2 7812500 PWM_POLARITY_INVERTED>;
++              cooling-levels = <255 153 85 25 0>;
++      };
++
++      fan1: chassis-fan {
++              compatible = "pwm-fan";
++              pwms = <&pwm1 3 7812500 PWM_POLARITY_INVERTED>;
++              cooling-levels = <255 153 85 25 0>;
++      };
+ };
+ &uart0 {
diff --git a/target/linux/hifiveu/patches-5.10/0106-mfd_da9063_Add_HWMON_deps.patch b/target/linux/hifiveu/patches-5.10/0106-mfd_da9063_Add_HWMON_deps.patch
new file mode 100644 (file)
index 0000000..3ce5ca9
--- /dev/null
@@ -0,0 +1,89 @@
+From 1690b165f7a5b4858eac60abf221666e9cdb90de Mon Sep 17 00:00:00 2001
+From: "Opensource [Steve Twiss]" <stwiss.opensource@diasemi.com>
+Date: Sun, 23 Mar 2014 20:37:30 +0000
+Subject: [PATCH] mfd: da9063: Add HWMON dependencies
+
+Dependencies required for DA9063 HWMON support.
+
+Signed-off-by: Opensource [Steve Twiss] <stwiss.opensource@diasemi.com>
+
+Moved temperature offset reading to hwmon driver.
+
+Signed-off-by: Vincent Pelletier <plr.vincent@gmail.com>
+---
+ include/linux/mfd/da9063/registers.h | 34 ++++++++++++++++++++++++++++
+ 1 file changed, 34 insertions(+)
+
+diff --git a/include/linux/mfd/da9063/registers.h b/include/linux/mfd/da9063/registers.h
+index 6e0f66a2e7279f..297631ddda3994 100644
+--- a/include/linux/mfd/da9063/registers.h
++++ b/include/linux/mfd/da9063/registers.h
+@@ -512,6 +512,7 @@
+ /* DA9063_REG_GPIO_0_1 (addr=0x15) */
+ #define       DA9063_GPIO0_PIN_MASK                   0x03
++#define       DA9063_GPIO0_PIN_MASK_SHIFT             0
+ #define               DA9063_GPIO0_PIN_ADCIN1         0x00
+ #define               DA9063_GPIO0_PIN_GPI            0x01
+ #define               DA9063_GPIO0_PIN_GPO_OD         0x02
+@@ -523,6 +524,7 @@
+ #define               DA9063_GPIO0_TYPE_GPO_VDD_IO2   0x04
+ #define       DA9063_GPIO0_NO_WAKEUP                  0x08
+ #define       DA9063_GPIO1_PIN_MASK                   0x30
++#define       DA9063_GPIO1_PIN_MASK_SHIFT             4
+ #define               DA9063_GPIO1_PIN_ADCIN2_COMP    0x00
+ #define               DA9063_GPIO1_PIN_GPI            0x10
+ #define               DA9063_GPIO1_PIN_GPO_OD         0x20
+@@ -536,6 +538,7 @@
+ /* DA9063_REG_GPIO_2_3 (addr=0x16) */
+ #define       DA9063_GPIO2_PIN_MASK                   0x03
++#define       DA9063_GPIO2_PIN_MASK_SHIFT             0
+ #define               DA9063_GPIO2_PIN_ADCIN3         0x00
+ #define               DA9063_GPIO2_PIN_GPI            0x01
+ #define               DA9063_GPIO2_PIN_GPO_PSS        0x02
+@@ -851,6 +854,7 @@
+ #define       DA9063_VSYS_VAL_BASE                    0x00
+ /* DA9063_REG_ADC_RES_L (addr=0x37) */
++#define       DA9063_ADC_RES_L_SHIFT                  6
+ #define       DA9063_ADC_RES_L_BITS                   2
+ #define       DA9063_ADC_RES_L_MASK                   0xC0
+@@ -1014,6 +1018,36 @@
+ #define DA9063_GPIO_DIM                               0x80
+ #define DA9063_GPIO_PWM_MASK                  0x7F
++/* DA9063_REG_ADC_CFG (addr=0xC9) */
++#define DA9063_REG_ADCIN1_CUR_MASK            0x03
++#define DA9063_REG_ADCIN1_CUR_SHIFT           0
++#define               DA9063_ADCIN1_CUR_1UA           0x00
++#define               DA9063_ADCIN1_CUR_2UA           0x01
++#define               DA9063_ADCIN1_CUR_10UA          0x02
++#define               DA9063_ADCIN1_CUR_40UA          0x03
++#define DA9063_REG_ADCIN2_CUR_MASK            0x0C
++#define DA9063_REG_ADCIN2_CUR_SHIFT           2
++#define               DA9063_ADCIN2_CUR_1UA           0x00
++#define               DA9063_ADCIN2_CUR_2UA           0x01
++#define               DA9063_ADCIN2_CUR_10UA          0x02
++#define               DA9063_ADCIN2_CUR_40UA          0x03
++#define DA9063_REG_ADCIN3_CUR_MASK            0x10
++#define DA9063_REG_ADCIN3_CUR_SHIFT           4
++#define               DA9063_ADCIN3_CUR_10UA          0x00
++#define               DA9063_ADCIN3_CUR_40UA          0x01
++#define DA9063_REG_ADCIN1_DEB_MASK            0x20
++#define DA9063_REG_ADCIN1_DEB_SHIFT           5
++#define               DA9063_ADCIN1_DEB_OFF           0x00
++#define               DA9063_ADCIN1_DEB_ON            0x01
++#define DA9063_REG_ADCIN2_DEB_MASK            0x40
++#define DA9063_REG_ADCIN2_DEB_SHIFT           6
++#define               DA9063_ADCIN2_DEB_OFF           0x00
++#define               DA9063_ADCIN2_DEB_ON            0x01
++#define DA9063_REG_ADCIN3_DEB_MASK            0x80
++#define DA9063_REG_ADCIN3_DEB_SHIFT           7
++#define               DA9063_ADCIN3_DEB_OFF           0x00
++#define               DA9063_ADCIN3_DEB_ON            0x01
++
+ /* DA9063_REG_CONFIG_H (addr=0x10D) */
+ #define DA9063_PWM_CLK_MASK                   0x01
+ #define               DA9063_PWM_CLK_PWM2MHZ          0x00
diff --git a/target/linux/hifiveu/patches-5.10/0107-hwmon-da9063_HWMON_driver.patch b/target/linux/hifiveu/patches-5.10/0107-hwmon-da9063_HWMON_driver.patch
new file mode 100644 (file)
index 0000000..5b0fecc
--- /dev/null
@@ -0,0 +1,315 @@
+From a829b924463d46792484ab6341b9c606cc7269a7 Mon Sep 17 00:00:00 2001
+From: Vincent Pelletier <plr.vincent@gmail.com>
+Date: Sun, 23 Mar 2014 20:37:30 +0000
+Subject: [PATCH] hwmon: da9063: HWMON driver
+
+Add the HWMON driver for DA9063
+
+Originally-from: Opensource [Steve Twiss] <stwiss.opensource@diasemi.com>
+Signed-off-by: Vincent Pelletier <plr.vincent@gmail.com>
+---
+ drivers/hwmon/Kconfig        |  10 ++
+ drivers/hwmon/Makefile       |   1 +
+ drivers/hwmon/da9063-hwmon.c | 260 +++++++++++++++++++++++++++++++++++
+ 3 files changed, 271 insertions(+)
+ create mode 100644 drivers/hwmon/da9063-hwmon.c
+
+diff --git a/drivers/hwmon/Kconfig b/drivers/hwmon/Kconfig
+index 87624902ea8090..17244cfaa855db 100644
+--- a/drivers/hwmon/Kconfig
++++ b/drivers/hwmon/Kconfig
+@@ -515,6 +515,16 @@ config SENSORS_DA9055
+         This driver can also be built as a module. If so, the module
+         will be called da9055-hwmon.
++config SENSORS_DA9063
++      tristate "Dialog Semiconductor DA9063"
++      depends on MFD_DA9063
++      help
++        If you say yes here you get support for the hardware
++        monitoring features of the DA9063 Power Management IC.
++
++        This driver can also be built as a module. If so, the module
++        will be called da9063-hwmon.
++
+ config SENSORS_I5K_AMB
+       tristate "FB-DIMM AMB temperature sensor on Intel 5000 series chipsets"
+       depends on PCI
+diff --git a/drivers/hwmon/Makefile b/drivers/hwmon/Makefile
+index 59e78bc212cf3c..6855711ed9ec0f 100644
+--- a/drivers/hwmon/Makefile
++++ b/drivers/hwmon/Makefile
+@@ -60,6 +60,7 @@ obj-$(CONFIG_SENSORS_CORSAIR_CPRO) += corsair-cpro.o
+ obj-$(CONFIG_SENSORS_CORSAIR_PSU) += corsair-psu.o
+ obj-$(CONFIG_SENSORS_DA9052_ADC)+= da9052-hwmon.o
+ obj-$(CONFIG_SENSORS_DA9055)+= da9055-hwmon.o
++obj-$(CONFIG_SENSORS_DA9063)  += da9063-hwmon.o
+ obj-$(CONFIG_SENSORS_DELL_SMM)        += dell-smm-hwmon.o
+ obj-$(CONFIG_SENSORS_DME1737) += dme1737.o
+ obj-$(CONFIG_SENSORS_DRIVETEMP)       += drivetemp.o
+diff --git a/drivers/hwmon/da9063-hwmon.c b/drivers/hwmon/da9063-hwmon.c
+new file mode 100644
+index 00000000000000..6367685536a179
+--- /dev/null
++++ b/drivers/hwmon/da9063-hwmon.c
+@@ -0,0 +1,260 @@
++// SPDX-License-Identifier: GPL-2.0-or-later
++/* da9063-hwmon.c - Hardware monitor support for DA9063
++ * Copyright (C) 2014 Dialog Semiconductor Ltd.
++ * Copyright (C) 2021 Vincent Pelletier <plr.vincent@gmail.com>
++ */
++
++#include <linux/delay.h>
++#include <linux/err.h>
++#include <linux/hwmon.h>
++#include <linux/hwmon-sysfs.h>
++#include <linux/init.h>
++#include <linux/kernel.h>
++#include <linux/mfd/da9063/core.h>
++#include <linux/mod_devicetable.h>
++#include <linux/module.h>
++#include <linux/platform_device.h>
++#include <linux/regmap.h>
++#include <linux/slab.h>
++#include <linux/string.h>
++
++#define DA9063_ADC_RES        (1 << (DA9063_ADC_RES_L_BITS + DA9063_ADC_RES_M_BITS))
++#define DA9063_ADC_MAX        (DA9063_ADC_RES - 1)
++#define DA9063_2V5    2500
++#define DA9063_5V0    5000
++#define DA9063_5V5    5500
++#define DA9063_TJUNC_M        -398
++#define DA9063_TJUNC_O        330000
++#define DA9063_VBBAT_M        2048
++
++enum da9063_adc {
++      DA9063_CHAN_VSYS = DA9063_ADC_MUX_VSYS,
++      DA9063_CHAN_ADCIN1 = DA9063_ADC_MUX_ADCIN1,
++      DA9063_CHAN_ADCIN2 = DA9063_ADC_MUX_ADCIN2,
++      DA9063_CHAN_ADCIN3 = DA9063_ADC_MUX_ADCIN3,
++      DA9063_CHAN_TJUNC = DA9063_ADC_MUX_T_SENSE,
++      DA9063_CHAN_VBBAT = DA9063_ADC_MUX_VBBAT,
++      DA9063_CHAN_LDO_G1 = DA9063_ADC_MUX_LDO_G1,
++      DA9063_CHAN_LDO_G2 = DA9063_ADC_MUX_LDO_G2,
++      DA9063_CHAN_LDO_G3 = DA9063_ADC_MUX_LDO_G3
++};
++
++struct da9063_hwmon {
++      struct da9063 *da9063;
++      struct mutex hwmon_mutex;
++      struct completion adc_ready;
++      signed char tjunc_offset;
++};
++
++static int da9063_adc_manual_read(struct da9063_hwmon *hwmon, int channel)
++{
++      int ret;
++      unsigned char val;
++      unsigned char data[2];
++      int adc_man;
++
++      mutex_lock(&hwmon->hwmon_mutex);
++
++      val = (channel & DA9063_ADC_MUX_MASK) | DA9063_ADC_MAN;
++      ret = regmap_update_bits(hwmon->da9063->regmap, DA9063_REG_ADC_MAN,
++                               DA9063_ADC_MUX_MASK | DA9063_ADC_MAN, val);
++      if (ret < 0)
++              goto err_mread;
++
++      ret = wait_for_completion_timeout(&hwmon->adc_ready,
++                                        msecs_to_jiffies(100));
++      reinit_completion(&hwmon->adc_ready);
++      if (ret == 0)
++              dev_dbg(hwmon->da9063->dev,
++                      "Timeout while waiting for ADC completion IRQ\n");
++
++      ret = regmap_read(hwmon->da9063->regmap, DA9063_REG_ADC_MAN, &adc_man);
++      if (ret < 0)
++              goto err_mread;
++
++      /* data value is not ready */
++      if (adc_man & DA9063_ADC_MAN) {
++              ret = -ETIMEDOUT;
++              goto err_mread;
++      }
++
++      ret = regmap_bulk_read(hwmon->da9063->regmap,
++                             DA9063_REG_ADC_RES_L, data, 2);
++      if (ret < 0)
++              goto err_mread;
++
++      ret = (data[0] & DA9063_ADC_RES_L_MASK) >> DA9063_ADC_RES_L_SHIFT;
++      ret |= data[1] << DA9063_ADC_RES_L_BITS;
++err_mread:
++      mutex_unlock(&hwmon->hwmon_mutex);
++      return ret;
++}
++
++static irqreturn_t da9063_hwmon_irq_handler(int irq, void *irq_data)
++{
++      struct da9063_hwmon *hwmon = irq_data;
++
++      complete(&hwmon->adc_ready);
++      return IRQ_HANDLED;
++}
++
++static umode_t da9063_is_visible(const void *drvdata, enum
++                               hwmon_sensor_types type, u32 attr, int channel)
++{
++      return 0444;
++}
++
++static const enum da9063_adc da9063_in_index[] = {
++      DA9063_CHAN_VSYS, DA9063_CHAN_VBBAT
++};
++
++static int da9063_read(struct device *dev, enum hwmon_sensor_types type,
++                     u32 attr, int channel, long *val)
++{
++      struct da9063_hwmon *hwmon = dev_get_drvdata(dev);
++      enum da9063_adc adc_channel;
++      int tmp;
++
++      switch (type) {
++      case hwmon_in:
++              if (attr != hwmon_in_input)
++                      return -EOPNOTSUPP;
++              adc_channel = da9063_in_index[channel];
++              break;
++      case hwmon_temp:
++              if (attr != hwmon_temp_input)
++                      return -EOPNOTSUPP;
++              adc_channel = DA9063_CHAN_TJUNC;
++              break;
++      default:
++              return -EOPNOTSUPP;
++      }
++
++      tmp = da9063_adc_manual_read(hwmon, adc_channel);
++      if (tmp < 0)
++              return tmp;
++
++      switch (adc_channel) {
++      case DA9063_CHAN_VSYS:
++              *val = ((DA9063_5V5 - DA9063_2V5) * tmp) / DA9063_ADC_MAX +
++                      DA9063_2V5;
++              break;
++      case DA9063_CHAN_TJUNC:
++              tmp -= hwmon->tjunc_offset;
++              *val = DA9063_TJUNC_M * tmp + DA9063_TJUNC_O;
++              break;
++      case DA9063_CHAN_VBBAT:
++              *val = (DA9063_5V0 * tmp) / DA9063_ADC_MAX;
++              break;
++      default:
++              return -EINVAL;
++      }
++
++      return 0;
++}
++
++static const char * const da9063_in_name[] = {
++      "VSYS", "VBBAT"
++};
++
++static int da9063_read_string(struct device *dev, enum hwmon_sensor_types type,
++                            u32 attr, int channel, const char **str)
++{
++      switch (type) {
++      case hwmon_in:
++              if (attr != hwmon_in_label)
++                      return -EOPNOTSUPP;
++              *str = da9063_in_name[channel];
++              break;
++      case hwmon_temp:
++              if (attr != hwmon_temp_label)
++                      return -EOPNOTSUPP;
++              *str = "TJUNC";
++              break;
++      default:
++              return -EOPNOTSUPP;
++      }
++
++      return 0;
++}
++
++static const struct hwmon_ops da9063_ops = {
++      .is_visible = da9063_is_visible,
++      .read = da9063_read,
++      .read_string = da9063_read_string,
++};
++
++static const struct hwmon_channel_info *da9063_channel_info[] = {
++      HWMON_CHANNEL_INFO(chip, HWMON_C_REGISTER_TZ),
++      HWMON_CHANNEL_INFO(in,
++                         HWMON_I_INPUT | HWMON_I_LABEL,
++                         HWMON_I_INPUT | HWMON_I_LABEL),
++      HWMON_CHANNEL_INFO(temp,
++                         HWMON_T_INPUT | HWMON_T_LABEL),
++      NULL
++};
++
++static const struct hwmon_chip_info da9063_chip_info = {
++      .ops = &da9063_ops,
++      .info = da9063_channel_info,
++};
++
++static int da9063_hwmon_probe(struct platform_device *pdev)
++{
++      struct da9063 *da9063 = dev_get_drvdata(pdev->dev.parent);
++      struct da9063_hwmon *hwmon;
++      struct device *hwmon_dev;
++      unsigned int tmp;
++      int irq;
++      int ret;
++
++      hwmon = devm_kzalloc(&pdev->dev, sizeof(struct da9063_hwmon),
++                           GFP_KERNEL);
++      if (!hwmon)
++              return -ENOMEM;
++
++      mutex_init(&hwmon->hwmon_mutex);
++      init_completion(&hwmon->adc_ready);
++      hwmon->da9063 = da9063;
++
++      irq = platform_get_irq_byname(pdev, DA9063_DRVNAME_HWMON);
++      if (irq < 0)
++              return irq;
++
++      ret = devm_request_threaded_irq(&pdev->dev, irq, NULL,
++                                      da9063_hwmon_irq_handler,
++                                      IRQF_TRIGGER_LOW | IRQF_ONESHOT,
++                                      "HWMON", hwmon);
++      if (ret) {
++              dev_err(&pdev->dev, "Failed to request IRQ.\n");
++              return ret;
++      }
++
++      ret = regmap_read(da9063->regmap, DA9063_REG_T_OFFSET, &tmp);
++      if (ret < 0) {
++              tmp = 0;
++              dev_warn(&pdev->dev,
++                       "Temperature trimming value cannot be read (defaulting to 0)\n");
++      }
++      hwmon->tjunc_offset = (signed char) tmp;
++
++      hwmon_dev = devm_hwmon_device_register_with_info(&pdev->dev, "da9063",
++                                                       hwmon,
++                                                       &da9063_chip_info,
++                                                       NULL);
++
++      return PTR_ERR_OR_ZERO(hwmon_dev);
++}
++
++static struct platform_driver da9063_hwmon_driver = {
++      .probe = da9063_hwmon_probe,
++      .driver = {
++              .name = DA9063_DRVNAME_HWMON,
++      },
++};
++module_platform_driver(da9063_hwmon_driver);
++
++MODULE_DESCRIPTION("Hardware monitor support device driver for Dialog DA9063");
++MODULE_AUTHOR("Vincent Pelletier <plr.vincent@gmail.com>");
++MODULE_LICENSE("GPL v2");
++MODULE_ALIAS("platform:" DA9063_DRVNAME_HWMON);
diff --git a/target/linux/hifiveu/profiles/00-default.mk b/target/linux/hifiveu/profiles/00-default.mk
new file mode 100644 (file)
index 0000000..b47a12f
--- /dev/null
@@ -0,0 +1,14 @@
+# SPDX-License-Identifier: GPL-2.0-only
+#
+# Copyright (C) 2021 OpenWrt.org
+#
+
+define Profile/Default
+  NAME:=Default Profile
+  PRIORITY := 1
+endef
+
+define Profile/Default/Description
+  Default package set compatible with most boards.
+endef
+$(eval $(call Profile,Default))