From f8dfabc3819c204a3dd6a4761b5028f376d13b96 Mon Sep 17 00:00:00 2001 From: Zoltan HERPAI Date: Sun, 16 Dec 2018 11:05:58 +0100 Subject: [PATCH] hifiveu: add new target for HiFive Unleashed/Unmatched RISC-V boards 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 --- target/linux/hifiveu/Makefile | 22 + .../hifiveu/base-files/etc/board.d/01_leds | 21 + .../hifiveu/base-files/etc/board.d/02_network | 18 + target/linux/hifiveu/base-files/etc/inittab | 6 + target/linux/hifiveu/config-5.10 | 346 +++++ target/linux/hifiveu/image/Config.in | 5 + target/linux/hifiveu/image/Makefile | 70 + .../hifiveu/image/gen_hifiveu_sdcard_img.sh | 50 + ...ive-Extract-prci-core-to-common-base.patch | 1306 +++++++++++++++++ ...e-common-name-for-prci-configuration.patch | 62 + ...-driver-for-the-SiFive-FU740-PRCI-IP.patch | 500 +++++++ ...sifive-Fix-the-wrong-bit-field-shift.patch | 38 + ...ive-Add-clock-enable-and-disable-ops.patch | 285 ++++ ...v-Update-DT-binding-docs-to-support-.patch | 41 + ...Update-DT-binding-docs-to-support-Si.patch | 43 + ...Update-DT-binding-docs-to-support-Si.patch | 40 + ...al-Update-DT-binding-docs-to-support.patch | 33 + ...-Update-DT-binding-docs-to-support-S.patch | 33 + ...Update-DT-binding-docs-to-support-Si.patch | 37 + ...itial-support-for-the-SiFive-FU740-C.patch | 320 ++++ ...v-Update-YAML-doc-to-support-SiFive-.patch | 47 + ...itial-board-data-for-the-SiFive-HiFi.patch | 290 ++++ ..._cache-Update-L2-cache-driver-to-sup.patch | 98 ++ ...et-gpio-irq-offset-from-device-tree-.patch | 72 + ...wrapper-functions-to-get-cpu-manufac.patch | 58 + ...iscv-Get-CPU-manufactory-information.patch | 116 ++ ...alternative-mechanism-to-apply-errat.patch | 433 ++++++ ...cv-sifive-apply-errata-cip-453-patch.patch | 153 ++ ...u740-fix-cache-controller-interrupts.patch | 36 + ...40-cpu-1-2-3-4-set-compatible-to-sif.patch | 54 + ...Ie-support-for-the-SiFive-FU740-C000.patch | 66 + ...cie_aux-clock-in-prci-driver-for-PCI.patch | 150 ++ ...eset-simple-in-prci-driver-for-PCIe-.patch | 110 ++ ...maintainers-for-SiFive-FU740-PCIe-dr.patch | 35 + ...Add-SiFive-FU740-PCIe-host-controlle.patch | 143 ++ ...dd-SiFive-FU740-PCIe-host-controller.patch | 614 ++++++++ ...-enable-generic-PCI-resource-mapping.patch | 32 + .../0031-SiFive-Unleashed-CPUFreq.patch | 129 ++ ...scv-sifive-unmatched-add-D12-PWM-LED.patch | 43 + ...ive-unmatched-add-gpio-poweroff-node.patch | 37 + ...iscv-sifive-unmatched-add-D2-RGB-LED.patch | 56 + ...five-unmatched-remove-A00-from-model.patch | 26 + ...v-sifive-unmatched-define-LEDs-color.patch | 57 + .../0045-Add-PWM-LEDs-D1-D2-D3-D4.patch | 66 + .../0100-hifiveu-openwrt-led-changes.patch | 61 + ...unmatched_Expose_the_FU740_regulator.patch | 27 + ...-unmatched_Link_tmp451_with_its_psup.patch | 23 + ...ive-unmatched_Expose_board_ID_EEPROM.patch | 31 + ...five_unmatched-Expose_PMIC_sub-funcs.patch | 33 + ..._dts_sifive_unmatched_Expose_fan_PWM.patch | 33 + .../0106-mfd_da9063_Add_HWMON_deps.patch | 89 ++ .../0107-hwmon-da9063_HWMON_driver.patch | 315 ++++ target/linux/hifiveu/profiles/00-default.mk | 14 + 53 files changed, 6823 insertions(+) create mode 100644 target/linux/hifiveu/Makefile create mode 100644 target/linux/hifiveu/base-files/etc/board.d/01_leds create mode 100644 target/linux/hifiveu/base-files/etc/board.d/02_network create mode 100644 target/linux/hifiveu/base-files/etc/inittab create mode 100644 target/linux/hifiveu/config-5.10 create mode 100644 target/linux/hifiveu/image/Config.in create mode 100644 target/linux/hifiveu/image/Makefile create mode 100755 target/linux/hifiveu/image/gen_hifiveu_sdcard_img.sh create mode 100644 target/linux/hifiveu/patches-5.10/0001-clk-sifive-Extract-prci-core-to-common-base.patch create mode 100644 target/linux/hifiveu/patches-5.10/0002-clk-sifive-Use-common-name-for-prci-configuration.patch create mode 100644 target/linux/hifiveu/patches-5.10/0003-clk-sifive-Add-a-driver-for-the-SiFive-FU740-PRCI-IP.patch create mode 100644 target/linux/hifiveu/patches-5.10/0004-clk-sifive-Fix-the-wrong-bit-field-shift.patch create mode 100644 target/linux/hifiveu/patches-5.10/0005-clk-sifive-Add-clock-enable-and-disable-ops.patch create mode 100644 target/linux/hifiveu/patches-5.10/0006-dt-bindings-riscv-Update-DT-binding-docs-to-support-.patch create mode 100644 target/linux/hifiveu/patches-5.10/0007-dt-bindings-spi-Update-DT-binding-docs-to-support-Si.patch create mode 100644 target/linux/hifiveu/patches-5.10/0008-dt-bindings-pwm-Update-DT-binding-docs-to-support-Si.patch create mode 100644 target/linux/hifiveu/patches-5.10/0009-dt-bindings-serial-Update-DT-binding-docs-to-support.patch create mode 100644 target/linux/hifiveu/patches-5.10/0010-dt-bindings-gpio-Update-DT-binding-docs-to-support-S.patch create mode 100644 target/linux/hifiveu/patches-5.10/0011-dt-bindings-i2c-Update-DT-binding-docs-to-support-Si.patch create mode 100644 target/linux/hifiveu/patches-5.10/0012-riscv-dts-add-initial-support-for-the-SiFive-FU740-C.patch create mode 100644 target/linux/hifiveu/patches-5.10/0013-dt-bindings-riscv-Update-YAML-doc-to-support-SiFive-.patch create mode 100644 target/linux/hifiveu/patches-5.10/0014-riscv-dts-add-initial-board-data-for-the-SiFive-HiFi.patch create mode 100644 target/linux/hifiveu/patches-5.10/0016-RISC-V-sifive_l2_cache-Update-L2-cache-driver-to-sup.patch create mode 100644 target/linux/hifiveu/patches-5.10/0017-gpio-sifive-To-get-gpio-irq-offset-from-device-tree-.patch create mode 100644 target/linux/hifiveu/patches-5.10/0018-riscv-Add-3-SBI-wrapper-functions-to-get-cpu-manufac.patch create mode 100644 target/linux/hifiveu/patches-5.10/0019-riscv-Get-CPU-manufactory-information.patch create mode 100644 target/linux/hifiveu/patches-5.10/0020-riscv-Introduce-alternative-mechanism-to-apply-errat.patch create mode 100644 target/linux/hifiveu/patches-5.10/0021-riscv-sifive-apply-errata-cip-453-patch.patch create mode 100644 target/linux/hifiveu/patches-5.10/0022-riscv-dts-fu740-fix-cache-controller-interrupts.patch create mode 100644 target/linux/hifiveu/patches-5.10/0023-riscv-sifive-fu740-cpu-1-2-3-4-set-compatible-to-sif.patch create mode 100644 target/linux/hifiveu/patches-5.10/0024-riscv-dts-Add-PCIe-support-for-the-SiFive-FU740-C000.patch create mode 100644 target/linux/hifiveu/patches-5.10/0025-clk-sifive-Add-pcie_aux-clock-in-prci-driver-for-PCI.patch create mode 100644 target/linux/hifiveu/patches-5.10/0026-clk-sifive-Use-reset-simple-in-prci-driver-for-PCIe-.patch create mode 100644 target/linux/hifiveu/patches-5.10/0027-MAINTAINERS-Add-maintainers-for-SiFive-FU740-PCIe-dr.patch create mode 100644 target/linux/hifiveu/patches-5.10/0028-dt-bindings-PCI-Add-SiFive-FU740-PCIe-host-controlle.patch create mode 100644 target/linux/hifiveu/patches-5.10/0029-PCI-designware-Add-SiFive-FU740-PCIe-host-controller.patch create mode 100644 target/linux/hifiveu/patches-5.10/0030-riscv-enable-generic-PCI-resource-mapping.patch create mode 100644 target/linux/hifiveu/patches-5.10/0031-SiFive-Unleashed-CPUFreq.patch create mode 100644 target/linux/hifiveu/patches-5.10/0040-riscv-sifive-unmatched-add-D12-PWM-LED.patch create mode 100644 target/linux/hifiveu/patches-5.10/0041-riscv-sifive-unmatched-add-gpio-poweroff-node.patch create mode 100644 target/linux/hifiveu/patches-5.10/0042-riscv-sifive-unmatched-add-D2-RGB-LED.patch create mode 100644 target/linux/hifiveu/patches-5.10/0043-riscv-sifive-unmatched-remove-A00-from-model.patch create mode 100644 target/linux/hifiveu/patches-5.10/0044-riscv-sifive-unmatched-define-LEDs-color.patch create mode 100644 target/linux/hifiveu/patches-5.10/0045-Add-PWM-LEDs-D1-D2-D3-D4.patch create mode 100644 target/linux/hifiveu/patches-5.10/0100-hifiveu-openwrt-led-changes.patch create mode 100644 target/linux/hifiveu/patches-5.10/0101-riscv_dts_sifive-unmatched_Expose_the_FU740_regulator.patch create mode 100644 target/linux/hifiveu/patches-5.10/0102-riscv_dts_sifive-unmatched_Link_tmp451_with_its_psup.patch create mode 100644 target/linux/hifiveu/patches-5.10/0103-riscv_dts_sifive-unmatched_Expose_board_ID_EEPROM.patch create mode 100644 target/linux/hifiveu/patches-5.10/0104-riscv_dts_sifive_unmatched-Expose_PMIC_sub-funcs.patch create mode 100644 target/linux/hifiveu/patches-5.10/0105-riscv_dts_sifive_unmatched_Expose_fan_PWM.patch create mode 100644 target/linux/hifiveu/patches-5.10/0106-mfd_da9063_Add_HWMON_deps.patch create mode 100644 target/linux/hifiveu/patches-5.10/0107-hwmon-da9063_HWMON_driver.patch create mode 100644 target/linux/hifiveu/profiles/00-default.mk diff --git a/target/linux/hifiveu/Makefile b/target/linux/hifiveu/Makefile new file mode 100644 index 0000000000..5575f2f125 --- /dev/null +++ b/target/linux/hifiveu/Makefile @@ -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 + +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 index 0000000000..7ba9dfe673 --- /dev/null +++ b/target/linux/hifiveu/base-files/etc/board.d/01_leds @@ -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 index 0000000000..7ef10d00c5 --- /dev/null +++ b/target/linux/hifiveu/base-files/etc/board.d/02_network @@ -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 index 0000000000..93cb94860d --- /dev/null +++ b/target/linux/hifiveu/base-files/etc/inittab @@ -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 index 0000000000..306f34b31f --- /dev/null +++ b/target/linux/hifiveu/config-5.10 @@ -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 index 0000000000..2488a527e4 --- /dev/null +++ b/target/linux/hifiveu/image/Config.in @@ -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 index 0000000000..430cff3fa1 --- /dev/null +++ b/target/linux/hifiveu/image/Makefile @@ -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 index 0000000000..047a6da011 --- /dev/null +++ b/target/linux/hifiveu/image/gen_hifiveu_sdcard_img.sh @@ -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 " + 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 index 0000000000..bbfc25d702 --- /dev/null +++ b/target/linux/hifiveu/patches-5.10/0001-clk-sifive-Extract-prci-core-to-common-base.patch @@ -0,0 +1,1306 @@ +From fe033b899ca3461c0439d6cd775476ae7595e327 Mon Sep 17 00:00:00 2001 +From: Zong Li +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 +Reviewed-by: Pragnesh Patel +Acked-by: Palmer Dabbelt +--- + 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 +-#include +-#include +-#include +-#include +-#include +-#include + #include +-#include +-#include +-#include +-#include +- +-/* +- * 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 ++#include ++#include ++#include ++#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 ++#include ++#include ++ ++/* ++ * 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 index 0000000000..0f51ff0ffe --- /dev/null +++ b/target/linux/hifiveu/patches-5.10/0002-clk-sifive-Use-common-name-for-prci-configuration.patch @@ -0,0 +1,62 @@ +From df86ca5b9416ebeacb5ecee63118170c7ea20035 Mon Sep 17 00:00:00 2001 +From: Zong Li +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 +Reviewed-by: Palmer Dabbelt +Acked-by: Palmer Dabbelt +Reviewed-by: Pragnesh Patel +--- + 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 index 0000000000..8b2022b034 --- /dev/null +++ b/target/linux/hifiveu/patches-5.10/0003-clk-sifive-Add-a-driver-for-the-SiFive-FU740-PRCI-IP.patch @@ -0,0 +1,500 @@ +From c5d3ecfcbdcf2e2d24b636fb739501e1a3e85f14 Mon Sep 17 00:00:00 2001 +From: Zong Li +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 +Erik Danie +Pragnesh Patel + +Signed-off-by: Zong Li +Reviewed-by: Pragnesh Patel +Acked-by: Palmer Dabbelt +Cc: Henry Styles +Cc: Erik Danie +Cc: Pragnesh Patel +--- + 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 ++#include ++#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 + #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 index 0000000000..05b7951d24 --- /dev/null +++ b/target/linux/hifiveu/patches-5.10/0004-clk-sifive-Fix-the-wrong-bit-field-shift.patch @@ -0,0 +1,38 @@ +From ff2bcef458e1fc95c6f3da7304df4119628f92c5 Mon Sep 17 00:00:00 2001 +From: Zong Li +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 +Reported-by: Pragnesh Patel +--- + 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 index 0000000000..67fe10161b --- /dev/null +++ b/target/linux/hifiveu/patches-5.10/0005-clk-sifive-Add-clock-enable-and-disable-ops.patch @@ -0,0 +1,285 @@ +From 37338a04280c6add6e376ed03d094276fb2759ba Mon Sep 17 00:00:00 2001 +From: Pragnesh Patel +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 +Tested-by: Zong Li +--- + 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 index 0000000000..8a0d566b8f --- /dev/null +++ b/target/linux/hifiveu/patches-5.10/0006-dt-bindings-riscv-Update-DT-binding-docs-to-support-.patch @@ -0,0 +1,41 @@ +From 34d032292a2b6db16fc60e7c6706b1b508c2d932 Mon Sep 17 00:00:00 2001 +From: Yash Shah +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 +Reviewed-by: Rob Herring +Reviewed-by: Bin Meng +--- + 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 index 0000000000..770fb3aeff --- /dev/null +++ b/target/linux/hifiveu/patches-5.10/0007-dt-bindings-spi-Update-DT-binding-docs-to-support-Si.patch @@ -0,0 +1,43 @@ +From 8a3d7aa89632d354932a621eb4fe22c560a406bd Mon Sep 17 00:00:00 2001 +From: Yash Shah +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 +--- + 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,-spi" and "sifive,spi". + 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 index 0000000000..0d53c58a68 --- /dev/null +++ b/target/linux/hifiveu/patches-5.10/0008-dt-bindings-pwm-Update-DT-binding-docs-to-support-Si.patch @@ -0,0 +1,40 @@ +From 789dc44312525e9669d0c6e01ccfc01bbdfb0e10 Mon Sep 17 00:00:00 2001 +From: Yash Shah +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 +--- + 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,-pwm" and "sifive,pwm". 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 index 0000000000..9efd9f784f --- /dev/null +++ b/target/linux/hifiveu/patches-5.10/0009-dt-bindings-serial-Update-DT-binding-docs-to-support.patch @@ -0,0 +1,33 @@ +From 6bc4ee53eaffad7385babe568a7889b13752606f Mon Sep 17 00:00:00 2001 +From: Yash Shah +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 +Reviewed-by: Rob Herring +--- + 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 index 0000000000..ca75f15d74 --- /dev/null +++ b/target/linux/hifiveu/patches-5.10/0010-dt-bindings-gpio-Update-DT-binding-docs-to-support-S.patch @@ -0,0 +1,33 @@ +From 9791e30869ff598c0faede92500d4d35c8bbba45 Mon Sep 17 00:00:00 2001 +From: Yash Shah +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 +Reviewed-by: Rob Herring +--- + 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 index 0000000000..2c6946e67b --- /dev/null +++ b/target/linux/hifiveu/patches-5.10/0011-dt-bindings-i2c-Update-DT-binding-docs-to-support-Si.patch @@ -0,0 +1,37 @@ +From 909e7d4601aa183dbdd3e8edb964e4c683a2c9e1 Mon Sep 17 00:00:00 2001 +From: Yash Shah +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 +Reviewed-by: Rob Herring +--- + 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 index 0000000000..2593ae85e4 --- /dev/null +++ b/target/linux/hifiveu/patches-5.10/0012-riscv-dts-add-initial-support-for-the-SiFive-FU740-C.patch @@ -0,0 +1,320 @@ +From 7d2e730f1281b5530e55ebca1b0d9165e0298c00 Mon Sep 17 00:00:00 2001 +From: Yash Shah +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 +--- + 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 ++ ++/ { ++ #address-cells = <2>; ++ #size-cells = <2>; ++ compatible = "sifive,fu740-c000", "sifive,fu740"; ++ ++ aliases { ++ serial0 = &uart0; ++ serial1 = &uart1; ++ ethernet0 = ð0; ++ }; ++ ++ 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 index 0000000000..1cf253895d --- /dev/null +++ b/target/linux/hifiveu/patches-5.10/0013-dt-bindings-riscv-Update-YAML-doc-to-support-SiFive-.patch @@ -0,0 +1,47 @@ +From 323c7d104a6fbe22100fdd7b62d53a4f4739affa Mon Sep 17 00:00:00 2001 +From: Yash Shah +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 +Reviewed-by: Rob Herring +Reviewed-by: Bin Meng +--- + 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 index 0000000000..69ae175cf6 --- /dev/null +++ b/target/linux/hifiveu/patches-5.10/0014-riscv-dts-add-initial-board-data-for-the-SiFive-HiFi.patch @@ -0,0 +1,290 @@ +From 721f85343651f07ab6ed8064680ad8bbadf76d3f Mon Sep 17 00:00:00 2001 +From: Yash Shah +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 +Reviewed-by: Bin Meng +--- + 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 ++ ++/* 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 = ; ++ }; ++ ++ 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 = ; ++ 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; ++ }; ++}; ++ ++ð0 { ++ 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 index 0000000000..2f6cd67d9f --- /dev/null +++ b/target/linux/hifiveu/patches-5.10/0016-RISC-V-sifive_l2_cache-Update-L2-cache-driver-to-sup.patch @@ -0,0 +1,98 @@ +From f4a28f41637429a1784ab2bf5e16222ec91da575 Mon Sep 17 00:00:00 2001 +From: Yash Shah +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 +--- + 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 index 0000000000..01b21a2ab4 --- /dev/null +++ b/target/linux/hifiveu/patches-5.10/0017-gpio-sifive-To-get-gpio-irq-offset-from-device-tree-.patch @@ -0,0 +1,72 @@ +From e00f15b712b61f35fec747912dd5d3e9553d89a1 Mon Sep 17 00:00:00 2001 +From: Greentime Hu +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 +--- + 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 index 0000000000..66a3ffeea1 --- /dev/null +++ b/target/linux/hifiveu/patches-5.10/0018-riscv-Add-3-SBI-wrapper-functions-to-get-cpu-manufac.patch @@ -0,0 +1,58 @@ +From 49e87f076a3d9d4b1ebadfe2b19250977be6d668 Mon Sep 17 00:00:00 2001 +From: Vincent Chen +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 +--- + 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 index 0000000000..69c378617d --- /dev/null +++ b/target/linux/hifiveu/patches-5.10/0019-riscv-Get-CPU-manufactory-information.patch @@ -0,0 +1,116 @@ +From 34c4f71f957e4e15776493d094593970178ddc9e Mon Sep 17 00:00:00 2001 +From: Vincent Chen +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 +--- + 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 + #include + #include ++#include ++#include + + 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 index 0000000000..b47bf35597 --- /dev/null +++ b/target/linux/hifiveu/patches-5.10/0020-riscv-Introduce-alternative-mechanism-to-apply-errat.patch @@ -0,0 +1,433 @@ +From a3e6ca97499c444fee45c7efafcdef311142952c Mon Sep 17 00:00:00 2001 +From: Vincent Chen +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 +--- + 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 ++#include ++#include ++#include ++#include ++#include ++ ++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(®ion, patch_text_nosync); ++ ++ region.begin = (struct alt_entry *)__alt_data; ++ region.end = (struct alt_entry *)__alt_data_end; ++ __apply_alternatives(®ion, 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 ++#include ++ ++#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 ++#ifndef __ASSEMBLY__ ++ ++#include ++#include ++#include ++#include ++ ++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 + #include + #include ++#include + + #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 index 0000000000..806cde0f89 --- /dev/null +++ b/target/linux/hifiveu/patches-5.10/0021-riscv-sifive-apply-errata-cip-453-patch.patch @@ -0,0 +1,153 @@ +From fb63756f6b2e49160aaf85789f8ed88135eeea50 Mon Sep 17 00:00:00 2001 +From: Vincent Chen +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 +--- + 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 ++#include ++ ++#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 ++#include ++#include ++#include ++#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 index 0000000000..c678f747c9 --- /dev/null +++ b/target/linux/hifiveu/patches-5.10/0022-riscv-dts-fu740-fix-cache-controller-interrupts.patch @@ -0,0 +1,36 @@ +From 8a0380c3eee96adf57daf2f54fec5089c4dee576 Mon Sep 17 00:00:00 2001 +From: David Abdurachmanov +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 +--- + 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 index 0000000000..bfd1f4e42b --- /dev/null +++ b/target/linux/hifiveu/patches-5.10/0023-riscv-sifive-fu740-cpu-1-2-3-4-set-compatible-to-sif.patch @@ -0,0 +1,54 @@ +From 58231edb72ab61199226250483038159b2c56c65 Mon Sep 17 00:00:00 2001 +From: David Abdurachmanov +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 +--- + 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 index 0000000000..3b941d07e6 --- /dev/null +++ b/target/linux/hifiveu/patches-5.10/0024-riscv-dts-Add-PCIe-support-for-the-SiFive-FU740-C000.patch @@ -0,0 +1,66 @@ +From 34222949288ef8b2666facee9ca9001c8cd93486 Mon Sep 17 00:00:00 2001 +From: Greentime Hu +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 +--- + 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 index 0000000000..6be8467f57 --- /dev/null +++ b/target/linux/hifiveu/patches-5.10/0025-clk-sifive-Add-pcie_aux-clock-in-prci-driver-for-PCI.patch @@ -0,0 +1,150 @@ +From 90591acb975baa3bedc7178e04bc92daaca3740f Mon Sep 17 00:00:00 2001 +From: Greentime Hu +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 +--- + 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 index 0000000000..118c927ba1 --- /dev/null +++ b/target/linux/hifiveu/patches-5.10/0026-clk-sifive-Use-reset-simple-in-prci-driver-for-PCIe-.patch @@ -0,0 +1,110 @@ +From a9b30eacb76d59ea18f138e0ad2b66e8a50ef24d Mon Sep 17 00:00:00 2001 +From: Greentime Hu +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 +--- + 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 + #include ++#include + #include + + /* +@@ -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 index 0000000000..88d38a55d3 --- /dev/null +++ b/target/linux/hifiveu/patches-5.10/0027-MAINTAINERS-Add-maintainers-for-SiFive-FU740-PCIe-dr.patch @@ -0,0 +1,35 @@ +From a57464df4cfa31061f665d2bac4222d625ec5ca9 Mon Sep 17 00:00:00 2001 +From: Greentime Hu +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 +--- + 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 ++M: Greentime Hu ++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 + 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 index 0000000000..f37b8c13bf --- /dev/null +++ b/target/linux/hifiveu/patches-5.10/0028-dt-bindings-PCI-Add-SiFive-FU740-PCIe-host-controlle.patch @@ -0,0 +1,143 @@ +From 38fecc0dae7765bcd4de25863ef3156a18992040 Mon Sep 17 00:00:00 2001 +From: Greentime Hu +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 +--- + .../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 ++ - Greentime Hu ++ ++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 index 0000000000..52dfd98ffc --- /dev/null +++ b/target/linux/hifiveu/patches-5.10/0029-PCI-designware-Add-SiFive-FU740-PCIe-host-controller.patch @@ -0,0 +1,614 @@ +From 6da0f49824ae1fca4d0bf1ce433c870cf1b424ea Mon Sep 17 00:00:00 2001 +From: Paul Walmsley +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 +Signed-off-by: Henry Styles +Co-developed-by: Erik Danie +Signed-off-by: Erik Danie +Co-developed-by: Greentime Hu +Signed-off-by: Greentime Hu +Signed-off-by: Paul Walmsley +--- + 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 ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#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 index 0000000000..f27007bf03 --- /dev/null +++ b/target/linux/hifiveu/patches-5.10/0030-riscv-enable-generic-PCI-resource-mapping.patch @@ -0,0 +1,32 @@ +From 63d7d0e6553ed2990fec51b3f449e50153461650 Mon Sep 17 00:00:00 2001 +From: Stanislaw Kardach +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 +--- + 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 index 0000000000..aab74c06a5 --- /dev/null +++ b/target/linux/hifiveu/patches-5.10/0031-SiFive-Unleashed-CPUFreq.patch @@ -0,0 +1,129 @@ +From 35f046065b988ea1b29df78728f5dbb6877aadc4 Mon Sep 17 00:00:00 2001 +From: David Abdurachmanov +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 +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 = ; + 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 index 0000000000..9650bedc3e --- /dev/null +++ b/target/linux/hifiveu/patches-5.10/0040-riscv-sifive-unmatched-add-D12-PWM-LED.patch @@ -0,0 +1,43 @@ +From ce24ba4d603a19690548b986d87ae2d9af26d015 Mon Sep 17 00:00:00 2001 +From: David Abdurachmanov +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 +--- + 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 ++#include + + /* 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 index 0000000000..a44c7741ad --- /dev/null +++ b/target/linux/hifiveu/patches-5.10/0041-riscv-sifive-unmatched-add-gpio-poweroff-node.patch @@ -0,0 +1,37 @@ +From f19634daf24481664cdc89dc0b5abd9b622718f5 Mon Sep 17 00:00:00 2001 +From: David Abdurachmanov +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 +--- + 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 + #include + #include + +@@ -55,6 +56,11 @@ + clock-frequency = ; + 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 index 0000000000..ad989ebb3d --- /dev/null +++ b/target/linux/hifiveu/patches-5.10/0042-riscv-sifive-unmatched-add-D2-RGB-LED.patch @@ -0,0 +1,56 @@ +From 2d375478fd6b5eeea711d081502cc8fd1a22987d Mon Sep 17 00:00:00 2001 +From: David Abdurachmanov +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 +--- + .../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 index 0000000000..b3c3483d12 --- /dev/null +++ b/target/linux/hifiveu/patches-5.10/0043-riscv-sifive-unmatched-remove-A00-from-model.patch @@ -0,0 +1,26 @@ +From 45ed220373844f72e9ddb05ef0a8f2bd391e0980 Mon Sep 17 00:00:00 2001 +From: David Abdurachmanov +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 +--- + 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 index 0000000000..8d5d6063d6 --- /dev/null +++ b/target/linux/hifiveu/patches-5.10/0044-riscv-sifive-unmatched-define-LEDs-color.patch @@ -0,0 +1,57 @@ +From 665297adfa377a3682b261b23f2a6f3ec56daa8b Mon Sep 17 00:00:00 2001 +From: David Abdurachmanov +Date: Wed, 7 Apr 2021 06:08:33 -0700 +Subject: [PATCH 27/28] riscv: sifive: unmatched: define LEDs color + +Signed-off-by: David Abdurachmanov +--- + 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 + #include ++#include + #include + + /* Clock frequency (in Hz) of the PCB crystal for rtcclk */ +@@ -36,6 +37,7 @@ + compatible = "pwm-leds"; + green-d12 { + label = "green:d12"; ++ color = ; + pwms = <&pwm0 0 7812500 PWM_POLARITY_INVERTED>; + active-low = <1>; + max-brightness = <255>; +@@ -44,6 +46,7 @@ + + green-d2 { + label = "green:d2"; ++ color = ; + pwms = <&pwm0 1 7812500 PWM_POLARITY_INVERTED>; + active-low = <1>; + max-brightness = <255>; +@@ -52,6 +55,7 @@ + + red-d2 { + label = "red:d2"; ++ color = ; + pwms = <&pwm0 2 7812500 PWM_POLARITY_INVERTED>; + active-low = <1>; + max-brightness = <255>; +@@ -60,6 +64,7 @@ + + blue-d2 { + label = "blue:d2"; ++ color = ; + 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 index 0000000000..c79d1a1c9c --- /dev/null +++ b/target/linux/hifiveu/patches-5.10/0045-Add-PWM-LEDs-D1-D2-D3-D4.patch @@ -0,0 +1,66 @@ +From c1c831af223931219b7bf9158b1306b500116167 Mon Sep 17 00:00:00 2001 +From: David Abdurachmanov +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 +--- + .../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 ++#include + + /* 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 index 0000000000..166abe6da5 --- /dev/null +++ b/target/linux/hifiveu/patches-5.10/0100-hifiveu-openwrt-led-changes.patch @@ -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 = ; + 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 index 0000000000..5672b5eca4 --- /dev/null +++ b/target/linux/hifiveu/patches-5.10/0101-riscv_dts_sifive-unmatched_Expose_the_FU740_regulator.patch @@ -0,0 +1,27 @@ +From 89c9a963944ed10a890b627e2e63e96fbff3aa36 Mon Sep 17 00:00:00 2001 +From: Vincent Pelletier +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 +--- + 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 index 0000000000..5692afb8a2 --- /dev/null +++ b/target/linux/hifiveu/patches-5.10/0102-riscv_dts_sifive-unmatched_Link_tmp451_with_its_psup.patch @@ -0,0 +1,23 @@ +From c5faf98f30ef3e1a3f56ace78741ccef2e4856aa Mon Sep 17 00:00:00 2001 +From: Vincent Pelletier +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 +--- + 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 index 0000000000..e38c39f2dd --- /dev/null +++ b/target/linux/hifiveu/patches-5.10/0103-riscv_dts_sifive-unmatched_Expose_board_ID_EEPROM.patch @@ -0,0 +1,31 @@ +From 3eb8033e1f318477cf87e6e0ea837e75a87856e9 Mon Sep 17 00:00:00 2001 +From: Vincent Pelletier +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 +--- + 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 index 0000000000..f93e175014 --- /dev/null +++ b/target/linux/hifiveu/patches-5.10/0104-riscv_dts_sifive_unmatched-Expose_PMIC_sub-funcs.patch @@ -0,0 +1,33 @@ +From eeaad1f6ab4fa5f854780587296c71dda9cda3b5 Mon Sep 17 00:00:00 2001 +From: Vincent Pelletier +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 +--- + 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 index 0000000000..04e7d19c57 --- /dev/null +++ b/target/linux/hifiveu/patches-5.10/0105-riscv_dts_sifive_unmatched_Expose_fan_PWM.patch @@ -0,0 +1,33 @@ +From 00a903b88b10f77b053e910f72bd9feb0d5c7c17 Mon Sep 17 00:00:00 2001 +From: Vincent Pelletier +Date: Sat, 19 Jun 2021 14:36:12 +0000 +Subject: [PATCH] riscv: dts: sifive unmatched: Expose fan PWM. + +Signed-off-by: Vincent Pelletier +--- + 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 index 0000000000..3ce5ca9fda --- /dev/null +++ b/target/linux/hifiveu/patches-5.10/0106-mfd_da9063_Add_HWMON_deps.patch @@ -0,0 +1,89 @@ +From 1690b165f7a5b4858eac60abf221666e9cdb90de Mon Sep 17 00:00:00 2001 +From: "Opensource [Steve Twiss]" +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] + +Moved temperature offset reading to hwmon driver. + +Signed-off-by: Vincent Pelletier +--- + 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 index 0000000000..5b0fecc94e --- /dev/null +++ b/target/linux/hifiveu/patches-5.10/0107-hwmon-da9063_HWMON_driver.patch @@ -0,0 +1,315 @@ +From a829b924463d46792484ab6341b9c606cc7269a7 Mon Sep 17 00:00:00 2001 +From: Vincent Pelletier +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] +Signed-off-by: Vincent Pelletier +--- + 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 ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#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 "); ++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 index 0000000000..b47a12fd86 --- /dev/null +++ b/target/linux/hifiveu/profiles/00-default.mk @@ -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)) -- 2.30.2