From: Zoltan HERPAI Date: Thu, 4 Oct 2018 15:22:39 +0000 (+0200) Subject: riscv64: update target X-Git-Url: http://git.lede-project.org./?a=commitdiff_plain;h=08d7ff8be61f36fdf76963e5b8db8d9d7fc3e519;p=openwrt%2Fstaging%2Fwigyori.git riscv64: update target - For booting kernel, use BBL (Berkeley Bootloader) - Add SD-card image generation - backport patches for 4.18 - bump target to use 4.18 Signed-off-by: Zoltan HERPAI --- diff --git a/target/linux/riscv64/Makefile b/target/linux/riscv64/Makefile index ee4e2599f0..ff1d0b43b8 100644 --- a/target/linux/riscv64/Makefile +++ b/target/linux/riscv64/Makefile @@ -13,7 +13,7 @@ FEATURES:=squashfs DEVICE_TYPE:=developerboard MAINTAINER:=Zoltan HERPAI , Alex Guo -KERNEL_PATCHVER:=4.17 +KERNEL_PATCHVER:=4.18 include $(INCLUDE_DIR)/target.mk diff --git a/target/linux/riscv64/config-4.18 b/target/linux/riscv64/config-4.18 new file mode 100644 index 0000000000..27b26ad032 --- /dev/null +++ b/target/linux/riscv64/config-4.18 @@ -0,0 +1,365 @@ +CONFIG_64BIT=y +CONFIG_ARCH_DMA_ADDR_T_64BIT=y +CONFIG_ARCH_HAS_PTE_SPECIAL=y +# CONFIG_ARCH_RV32I is not set +CONFIG_ARCH_RV64I=y +CONFIG_ARCH_WANT_FRAME_POINTERS=y +# CONFIG_ASIX_PHY is not set +CONFIG_ASN1=y +CONFIG_ASSOCIATIVE_ARRAY=y +CONFIG_ASYMMETRIC_KEY_TYPE=y +CONFIG_ASYMMETRIC_PUBLIC_KEY_SUBTYPE=y +CONFIG_ATA=y +CONFIG_ATA_VERBOSE_ERROR=y +# CONFIG_ATH5K_PCI is not set +# CONFIG_AUTOFS_FS is not set +CONFIG_BLK_DEV_SD=y +CONFIG_BLK_MQ_PCI=y +CONFIG_BLK_MQ_VIRTIO=y +CONFIG_BLK_SCSI_REQUEST=y +# CONFIG_BPFILTER is not set +CONFIG_CAVIUM_PTP=y +CONFIG_CC_HAS_SANCOV_TRACE_PC=y +CONFIG_CC_HAS_STACKPROTECTOR_NONE=y +CONFIG_CC_IS_GCC=y +CONFIG_CLANG_VERSION=0 +CONFIG_CLKDEV_LOOKUP=y +CONFIG_CLONE_BACKWARDS=y +CONFIG_CLZ_TAB=y +CONFIG_CMDLINE="earlyprintk root=/dev/mmcblk0p2 rootwait" +CONFIG_CMDLINE_BOOL=y +CONFIG_CMODEL_MEDANY=y +# CONFIG_CMODEL_MEDLOW is not set +CONFIG_COMMON_CLK=y +# CONFIG_COMMON_CLK_SI544 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_ACOMP2=y +CONFIG_CRYPTO_AEAD=y +CONFIG_CRYPTO_AEAD2=y +# CONFIG_CRYPTO_AEGIS128 is not set +# CONFIG_CRYPTO_AEGIS128L is not set +# CONFIG_CRYPTO_AEGIS256 is not set +CONFIG_CRYPTO_AKCIPHER=y +CONFIG_CRYPTO_AKCIPHER2=y +# CONFIG_CRYPTO_CFB is not set +CONFIG_CRYPTO_CRC32C=y +CONFIG_CRYPTO_DRBG=y +CONFIG_CRYPTO_DRBG_HMAC=y +CONFIG_CRYPTO_DRBG_MENU=y +CONFIG_CRYPTO_ECHAINIV=y +CONFIG_CRYPTO_HASH=y +CONFIG_CRYPTO_HASH2=y +CONFIG_CRYPTO_HASH_INFO=y +CONFIG_CRYPTO_HMAC=y +CONFIG_CRYPTO_JITTERENTROPY=y +CONFIG_CRYPTO_KPP2=y +CONFIG_CRYPTO_MANAGER=y +CONFIG_CRYPTO_MANAGER2=y +# CONFIG_CRYPTO_MORUS1280 is not set +# CONFIG_CRYPTO_MORUS640 is not set +CONFIG_CRYPTO_NULL=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_CRYPTO_SM3 is not set +# CONFIG_CRYPTO_SM4 is not set +# CONFIG_CRYPTO_SPECK is not set +CONFIG_CRYPTO_WORKQUEUE=y +# CONFIG_CRYPTO_ZSTD is not set +CONFIG_DEBUG_BUGVERBOSE=y +# CONFIG_DEBUG_FS is not set +CONFIG_DEBUG_SECTION_MISMATCH=y +CONFIG_DECOMPRESS_GZIP=y +# CONFIG_DEFAULT_CFQ is not set +CONFIG_DEVMEM=y +CONFIG_DEVTMPFS=y +CONFIG_DEVTMPFS_MOUNT=y +CONFIG_DMA_DIRECT_OPS=y +CONFIG_DNOTIFY=y +# CONFIG_DP83822_PHY is not set +# CONFIG_DP83TC811_PHY is not set +CONFIG_DTC=y +CONFIG_E1000E=y +CONFIG_EARLY_PRINTK=y +CONFIG_ELF_CORE=y +CONFIG_ENABLE_MUST_CHECK=y +CONFIG_EXPORTFS=y +CONFIG_EXT3_FS=y +# CONFIG_EXT3_FS_POSIX_ACL is not set +# CONFIG_EXT3_FS_SECURITY is not set +CONFIG_EXT4_FS=y +CONFIG_FAILOVER=y +CONFIG_FHANDLE=y +CONFIG_FIXED_PHY=y +CONFIG_FRAME_POINTER=y +CONFIG_FRAME_WARN=2048 +CONFIG_FS_IOMAP=y +CONFIG_FS_MBCACHE=y +CONFIG_FUTEX_PI=y +CONFIG_GCC_VERSION=80100 +# CONFIG_GEMINI_ETHERNET is not set +CONFIG_GENERIC_BUG=y +CONFIG_GENERIC_BUG_RELATIVE_POINTERS=y +CONFIG_GENERIC_CLOCKEVENTS=y +CONFIG_GENERIC_CPU_DEVICES=y +CONFIG_GENERIC_CSUM=y +CONFIG_GENERIC_IRQ_MULTI_HANDLER=y +CONFIG_GENERIC_IRQ_SHOW=y +CONFIG_GENERIC_MSI_IRQ=y +CONFIG_GENERIC_PCI_IOMAP=y +CONFIG_GENERIC_SMP_IDLE_THREAD=y +CONFIG_GENERIC_STRNCPY_FROM_USER=y +CONFIG_GENERIC_STRNLEN_USER=y +CONFIG_GLOB=y +CONFIG_GPIOLIB=y +CONFIG_GPIOLIB_FASTPATH_LIMIT=512 +# CONFIG_GPIO_HLWD is not set +# CONFIG_GPIO_MAX3191X is not set +# CONFIG_GPIO_MB86S7X is not set +# CONFIG_GPIO_PCIE_IDIO_24 is not set +# CONFIG_GUP_BENCHMARK is not set +CONFIG_HAS_DMA=y +CONFIG_HAS_IOMEM=y +CONFIG_HAS_IOPORT_MAP=y +CONFIG_HAVE_64BIT_ALIGNED_ACCESS=y +CONFIG_HAVE_ARCH_TRACEHOOK=y +CONFIG_HAVE_CLK=y +CONFIG_HAVE_CLK_PREPARE=y +CONFIG_HAVE_DMA_CONTIGUOUS=y +CONFIG_HAVE_DYNAMIC_FTRACE=y +CONFIG_HAVE_DYNAMIC_FTRACE_WITH_REGS=y +CONFIG_HAVE_FTRACE_MCOUNT_RECORD=y +CONFIG_HAVE_FUNCTION_GRAPH_TRACER=y +CONFIG_HAVE_FUNCTION_TRACER=y +CONFIG_HAVE_GENERIC_DMA_COHERENT=y +CONFIG_HAVE_MEMBLOCK=y +CONFIG_HAVE_MEMBLOCK_NODE_MAP=y +CONFIG_HAVE_MOD_ARCH_SPECIFIC=y +CONFIG_HAVE_NET_DSA=y +CONFIG_HAVE_PERF_EVENTS=y +CONFIG_HAVE_VIRT_CPU_ACCOUNTING_GEN=y +CONFIG_HID=y +# CONFIG_HID_ELAN is not set +CONFIG_HID_GENERIC=y +# CONFIG_HID_GOOGLE_HAMMER is not set +# CONFIG_HID_JABRA is not set +# CONFIG_HID_REDRAGON is not set +# CONFIG_HID_STEAM is not set +CONFIG_HVC_DRIVER=y +CONFIG_HVC_RISCV_SBI=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_ICE is not set +CONFIG_INITRAMFS_SOURCE="" +CONFIG_INPUT=y +CONFIG_IOSCHED_CFQ=y +CONFIG_IRQCHIP=y +CONFIG_IRQ_DOMAIN=y +CONFIG_IRQ_WORK=y +CONFIG_JBD2=y +CONFIG_KALLSYMS=y +CONFIG_KEYS=y +# CONFIG_LAN743X is not set +# CONFIG_LEDS_CR0014114 is not set +# CONFIG_LEDS_LM3692X is not set +# CONFIG_LEDS_MLXREG is not set +# CONFIG_LEDS_TRIGGER_ACTIVITY is not set +CONFIG_LEGACY_PTYS=y +CONFIG_LEGACY_PTY_COUNT=256 +CONFIG_LIBFDT=y +CONFIG_LOCALVERSION_AUTO=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_MAXPHYSMEM_2GB is not set +CONFIG_MDIO_BUS=y +CONFIG_MDIO_DEVICE=y +# CONFIG_MDIO_MSCC_MIIM is not set +CONFIG_MEMFD_CREATE=y +# CONFIG_MICROCHIP_T1_PHY is not set +CONFIG_MICROSEMI_PHY=y +# CONFIG_MISC_RTSX_PCI is not set +# CONFIG_MISC_RTSX_USB is not set +CONFIG_MMC=y +CONFIG_MMC_BLOCK=y +# CONFIG_MMC_CQHCI is not set +CONFIG_MMC_SPI=y +# CONFIG_MMC_TIFM_SD is not set +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_M25P80=y +CONFIG_MTD_SPI_NOR=y +CONFIG_MTD_SPI_NOR_USE_4K_SECTORS=y +# CONFIG_MTK_MMC is not set +CONFIG_NAMESPACES=y +CONFIG_NEED_DMA_MAP_STATE=y +CONFIG_NET_FAILOVER=y +CONFIG_NET_FLOW_LIMIT=y +CONFIG_NET_NS=y +CONFIG_NET_PACKET_ENGINE=y +CONFIG_NET_PTP_CLASSIFY=y +# CONFIG_NET_SCH_CBS is not set +CONFIG_NET_VENDOR_CORTINA=y +CONFIG_NET_VENDOR_MICROSEMI=y +CONFIG_NET_VENDOR_NI=y +CONFIG_NET_VENDOR_SOCIONEXT=y +CONFIG_NLS=y +CONFIG_NO_BOOTMEM=y +CONFIG_NR_CPUS=8 +CONFIG_NVMEM=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_OVERLAY_FS_REDIRECT_ALWAYS_FOLLOW=y +# CONFIG_OVERLAY_FS_XINO_AUTO is not set +CONFIG_PADATA=y +CONFIG_PAGE_OFFSET=0xffffffe000000000 +CONFIG_PANIC_TIMEOUT=0 +CONFIG_PCI=y +# CONFIG_PCIE_CADENCE_HOST is not set +CONFIG_PCI_DEBUG=y +CONFIG_PCI_DOMAINS=y +CONFIG_PCI_DOMAINS_GENERIC=y +CONFIG_PCI_MSI=y +CONFIG_PGTABLE_LEVELS=3 +CONFIG_PHYLIB=y +CONFIG_PHYS_ADDR_T_64BIT=y +# CONFIG_PHY_MAPPHONE_MDM6600 is not set +CONFIG_PID_NS=y +CONFIG_PKCS7_MESSAGE_PARSER=y +CONFIG_PLUGIN_HOSTCC="" +CONFIG_PPS=y +CONFIG_PRINTK_TIME=y +CONFIG_PTP_1588_CLOCK=y +CONFIG_PWM=y +CONFIG_PWM_SYSFS=y +CONFIG_R8169=y +CONFIG_RATIONAL=y +CONFIG_RCU_NEED_SEGCBLIST=y +CONFIG_RCU_STALL_COMMON=y +CONFIG_RCU_TRACE=y +CONFIG_RD_GZIP=y +CONFIG_REGMAP=y +CONFIG_REGMAP_I2C=y +CONFIG_REGMAP_SPI=y +# CONFIG_RENESAS_PHY is not set +CONFIG_RFKILL_LEDS=y +CONFIG_RFS_ACCEL=y +CONFIG_RISCV=y +CONFIG_RISCV_INTC=y +CONFIG_RISCV_ISA_A=y +CONFIG_RISCV_ISA_C=y +CONFIG_RISCV_PLIC=y +CONFIG_RISCV_TIMER=y +# CONFIG_RPMSG_VIRTIO is not set +CONFIG_RPS=y +CONFIG_RTC_CLASS=y +# CONFIG_RTC_DRV_ISL12026 is not set +# CONFIG_RTC_DRV_PCF85363 is not set +CONFIG_RTC_I2C_AND_SPI=y +# CONFIG_RUNTIME_TESTING_MENU is not set +CONFIG_SATA_AHCI=y +CONFIG_SATA_MOBILE_LPM_POLICY=0 +CONFIG_SATA_PMP=y +CONFIG_SATA_SIL24=y +CONFIG_SCHED_DEBUG=y +CONFIG_SCSI=y +# CONFIG_SECONDARY_TRUSTED_KEYRING is not set +CONFIG_SERIAL_8250_DEPRECATED_OPTIONS=y +CONFIG_SERIAL_8250_NR_UARTS=4 +CONFIG_SERIAL_8250_RUNTIME_UARTS=4 +CONFIG_SERIAL_OF_PLATFORM=y +CONFIG_SERIO=y +CONFIG_SERIO_SERPORT=y +CONFIG_SGL_ALLOC=y +CONFIG_SG_POOL=y +# CONFIG_SIOX is not set +# CONFIG_SLIMBUS is not set +CONFIG_SLUB_DEBUG=y +CONFIG_SMP=y +# CONFIG_SOUNDWIRE is not set +CONFIG_SPARSE_IRQ=y +CONFIG_SPI=y +CONFIG_SPI_BITBANG=y +CONFIG_SPI_MASTER=y +CONFIG_SPI_MEM=y +CONFIG_SRCU=y +CONFIG_STACKTRACE=y +CONFIG_SWIOTLB=y +CONFIG_SWPHY=y +CONFIG_SYSCTL_EXCEPTION_TRACE=y +CONFIG_SYSFS_SYSCALL=y +# CONFIG_SYSTEM_EXTRA_CERTIFICATE is not set +CONFIG_THREAD_INFO_IN_TASK=y +CONFIG_TICK_CPU_ACCOUNTING=y +CONFIG_TIMER_OF=y +CONFIG_TIMER_PROBE=y +CONFIG_TRACE_CLOCK=y +CONFIG_TREE_RCU=y +CONFIG_TREE_SRCU=y +CONFIG_TUNE_GENERIC=y +# CONFIG_TYPEC is not set +CONFIG_UEVENT_HELPER_PATH="" +# CONFIG_UNISYSSPAR is not set +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_DBGCAP is not set +CONFIG_USB_XHCI_HCD=y +CONFIG_USB_XHCI_PCI=y +# CONFIG_USB_XHCI_PLATFORM is not set +# CONFIG_USERIO is not set +# CONFIG_USER_NS is not set +CONFIG_UTS_NS=y +CONFIG_VGA_ARB=y +CONFIG_VGA_ARB_MAX_GPUS=16 +CONFIG_VIRTIO=y +CONFIG_VIRTIO_BLK=y +CONFIG_VIRTIO_CONSOLE=y +CONFIG_VIRTIO_MENU=y +CONFIG_VIRTIO_MMIO=y +# CONFIG_VIRTIO_MMIO_CMDLINE_DEVICES is not set +CONFIG_VIRTIO_NET=y +CONFIG_VM_EVENT_COUNTERS=y +CONFIG_X509_CERTIFICATE_PARSER=y +# CONFIG_XDP_SOCKETS is not set +# CONFIG_XILINX_VCU is not set +CONFIG_XPS=y +CONFIG_ZLIB_INFLATE=y +CONFIG_ZONE_DMA32=y diff --git a/target/linux/riscv64/image/Config.in b/target/linux/riscv64/image/Config.in new file mode 100644 index 0000000000..244f78975b --- /dev/null +++ b/target/linux/riscv64/image/Config.in @@ -0,0 +1,5 @@ +config RISCV64_SD_BOOT_PARTSIZE + int "Boot (SD Card) filesystem partition size (in MB)" + depends on TARGET_riscv64 + default 32 + diff --git a/target/linux/riscv64/image/Makefile b/target/linux/riscv64/image/Makefile index e2303f6e78..7e1581d093 100644 --- a/target/linux/riscv64/image/Makefile +++ b/target/linux/riscv64/image/Makefile @@ -1,46 +1,45 @@ # -# Copyright (C) 2007-2015 OpenWrt.org +# Copyright (C) 2010 OpenWrt.org # # This is free software, licensed under the GNU General Public License v2. # See /LICENSE for more information. # - -JFFS2_BLOCKSIZE=256k - include $(TOPDIR)/rules.mk include $(INCLUDE_DIR)/image.mk +#define Build/Clean +# $(MAKE) -C bbl clean +#endef + +#define Build/Compile +# $(MAKE) -C bbl compile +#endef define Image/Prepare - $(LINUX_DIR)/scripts/dtc/dtc -O dtb -R 4 -S 0x20000 $(DTS_DIR)/canyonlands.dts > $(KDIR)/openwrt-canyonlands.dtb + # sneak in a cleanup here + $(MAKE) -C bbl clean + cp $(KDIR)/vmlinux.elf $(BIN_DIR)/$(IMG_PREFIX)-vmlinux.elf endef -define Image/BuildKernel - cp $(KDIR)/uImage $(BIN_DIR)/$(IMG_PREFIX)-uImage +define Image/Build/riscv-sdcard + ./gen_riscv64_sdcard_img.sh \ + $(BIN_DIR)/sdcard.img \ + $(BIN_DIR)/bbl.bin \ + $(KDIR)/root.$(1) \ + $(CONFIG_RISCV64_SD_BOOT_PARTSIZE) \ + $(CONFIG_TARGET_ROOTFS_PARTSIZE) +# $(STAGING_DIR_IMAGE)/$(DEVICE_NAME)-u-boot-with-spl.bin endef define Image/Build - $(call Image/Build/$(1),$(1)) -endef - -define Image/Build/jffs2-256k - ( \ - dd if=$(KDIR)/uImage bs=2048k conv=sync; \ - dd if=$(KDIR)/root.$(1) bs=256k conv=sync; \ - ) > $(BIN_DIR)/$(IMG_PREFIX)-jffs2.img -endef - -define Image/Build/squashfs - $(call prepare_generic_squashfs,$(KDIR)/root.squashfs) - ( \ - dd if=$(KDIR)/cuImage.taishan bs=256k conv=sync; \ - dd if=$(KDIR)/root.$(1) bs=256k conv=sync; \ - ) > $(BIN_DIR)/$(IMG_PREFIX)-taishan-$(1).img - ( \ - dd if=$(KDIR)/uImage bs=1920k conv=sync; \ - dd if=$(KDIR)/openwrt-canyonlands.dtb bs=128k conv=sync; \ - dd if=$(KDIR)/root.$(1) bs=256k conv=sync; \ - ) > $(BIN_DIR)/$(IMG_PREFIX)-canyonlands-$(1).img + echo "BUILD: $(1)" + echo "PROFILE: $(PROFILE)" + $(MAKE) -C bbl compile +# cp $(BIN_DIR)/bbl.bin +# cp $(KDIR)/root.$(1) $(BIN_DIR)/$(IMG_PREFIX)-$(1).img + $(call Image/Build/riscv-sdcard,$(1),$(IMG_PREFIX)-$(PROFILE)-sdcard.img) + +# rm -f $@.boot endef $(eval $(call BuildImage)) diff --git a/target/linux/riscv64/image/bbl/Makefile b/target/linux/riscv64/image/bbl/Makefile new file mode 100644 index 0000000000..422b5d6229 --- /dev/null +++ b/target/linux/riscv64/image/bbl/Makefile @@ -0,0 +1,42 @@ +# +# Copyright (C) 2018 OpenWrt.org +# +# This is free software, licensed under the GNU General Public License v2. +# See /LICENSE for more information. +# + +include $(TOPDIR)/rules.mk +include $(INCLUDE_DIR)/kernel.mk + +PKG_NAME:=bbl +PKG_RELEASE:=1 + +PKG_SOURCE_PROTO:=git +PKG_SOURCE_DATE:=2018-08-16 +PKG_SOURCE_URL:=https://github.com/riscv/riscv-pk.git +PKG_SOURCE_VERSION:=706cc77c369fd3e4734b5a6aa813d421347f1814 +PKG_MIRROR_HASH:=440a1544258caca1edc1b7d8e89c085438fdcbe010465b5d55ff93b01dd519f3 + +include $(INCLUDE_DIR)/package.mk + +CONFIGURE_ARGS += \ + --enable-logo \ + --with-arch=rv64imafdc \ + --with-abi=lp64d \ + --with-payload=$(KERNEL_BUILD_DIR)/vmlinux \ + --prefix=$(KERNEL_BUILD_DIR) \ + --srcdir=.. + +define Build/Configure + mkdir -p $(PKG_BUILD_DIR)/work + (cd $(PKG_BUILD_DIR)/work; ../configure $(CONFIGURE_ARGS) ); +endef + +#mabi=lp64d -march=rv64imafdc + +define Build/Compile + $(MAKE) -C $(PKG_BUILD_DIR)/work bbl + $(TARGET_CROSS)objcopy -S -O binary --change-addresses -0x80000000 $(PKG_BUILD_DIR)/work/bbl $(BIN_DIR)/bbl.bin +endef + +$(eval $(call Build/DefaultTargets)) diff --git a/target/linux/riscv64/image/bbl/patches.dontuse/001-add-mabi-config-support.patch b/target/linux/riscv64/image/bbl/patches.dontuse/001-add-mabi-config-support.patch new file mode 100644 index 0000000000..36ffe0f019 --- /dev/null +++ b/target/linux/riscv64/image/bbl/patches.dontuse/001-add-mabi-config-support.patch @@ -0,0 +1,12 @@ +--- a/Makefile.in.old 2018-08-15 11:46:11.000000000 +0200 ++++ b/Makefile.in 2018-08-16 19:50:21.961398086 +0200 +@@ -61,7 +61,8 @@ + march := -march=@WITH_ARCH@ + endif + is_32bit := $(findstring 32,$(march)) +-mabi := -mabi=$(if $(is_32bit),ilp32,lp64) ++#mabi := -mabi=$(if $(is_32bit),ilp32,lp64) ++mabi := @WITH_ABI@ + + # Installation directories + diff --git a/target/linux/riscv64/image/bbl/patches.dontuse/002-add-mabi-config.patch b/target/linux/riscv64/image/bbl/patches.dontuse/002-add-mabi-config.patch new file mode 100644 index 0000000000..95899ad46a --- /dev/null +++ b/target/linux/riscv64/image/bbl/patches.dontuse/002-add-mabi-config.patch @@ -0,0 +1,12 @@ +--- a/configure.ac.old 2018-08-15 11:46:11.000000000 +0200 ++++ b/configure.ac 2018-08-16 19:52:37.140188650 +0200 +@@ -83,6 +83,9 @@ + AC_ARG_WITH([arch], AS_HELP_STRING([--with-arch], [Set the RISC-V architecture]), + [AC_SUBST([WITH_ARCH], $with_arch, [Specify architecture to build the project])]) + ++AC_ARG_WITH([abi], AS_HELP_STRING([--with-abi], [Set the RISC-V ABI]), ++ [AC_SUBST([WITH_ABI], $with_abi, [Specify ABI to build the project])]) ++ + AC_ARG_ENABLE([print-device-tree], AS_HELP_STRING([--enable-print-device-tree], [Print DTS when booting])) + AS_IF([test "x$enable_print_device_tree" == "xyes"], [ + AC_DEFINE([PK_PRINT_DEVICE_TREE],,[Define if the DTS is to be displayed]) diff --git a/target/linux/riscv64/image/bbl/patches/001-add-mabi-config-support.patch b/target/linux/riscv64/image/bbl/patches/001-add-mabi-config-support.patch new file mode 100644 index 0000000000..0a19714118 --- /dev/null +++ b/target/linux/riscv64/image/bbl/patches/001-add-mabi-config-support.patch @@ -0,0 +1,12 @@ +--- a/Makefile.in.old 2018-08-15 11:46:11.000000000 +0200 ++++ b/Makefile.in 2018-08-16 19:50:21.961398086 +0200 +@@ -61,7 +61,8 @@ + march := -march=@WITH_ARCH@ + endif + is_32bit := $(findstring 32,$(march)) +-mabi := -mabi=$(if $(is_32bit),ilp32,lp64) ++#mabi := -mabi=$(if $(is_32bit),ilp32,lp64) ++mabi := -mabi=lp64d + + # Installation directories + diff --git a/target/linux/riscv64/image/gen_riscv64_sdcard_img.sh b/target/linux/riscv64/image/gen_riscv64_sdcard_img.sh new file mode 100644 index 0000000000..f637cdaa20 --- /dev/null +++ b/target/linux/riscv64/image/gen_riscv64_sdcard_img.sh @@ -0,0 +1,39 @@ +#!/usr/bin/env bash +# +# Copyright (C) 2013 OpenWrt.org +# +# This is free software, licensed under the GNU General Public License v2. +# See /LICENSE for more information. +# + +set -ex +[ $# -eq 5 ] || { + echo "SYNTAX: $0 " + exit 1 +} + +BBL_UUID="2E54B353-1271-4842-806F-E436D6AF6985" +LINUX_UUID="0FC63DAF-8483-4772-8E79-3D69D8477DE4" + +OUTPUT="$1" +BOOTFS="$2" +ROOTFS="$3" +BOOTFSSIZE="$4" +ROOTFSSIZE="$5" +#UBOOT="$6" + +FULLSIZE="$(($BOOTFSSIZE+$ROOTFSSIZE+1))" +echo "Full size is: ${FULLSIZE}M" + +ROOTFSOFFSET="$(($BOOTFSSIZE*1048576 / 512 + 2048))" +echo "Rootfs offset is: $ROOTFSOFFSET" + +dd if=/dev/zero of=$OUTPUT bs=1M count=$FULLSIZE + +sgdisk --clear \ + --new=1:2048:${BOOTFSSIZE}M --change-name=1:bootloader --typecode=1:${BBL_UUID} \ + --new=2:${ROOTFSOFFSET}: --change-name=2:root --typecode=2:${LINUX_UUID} \ + $OUTPUT + +dd bs=512 if="$BOOTFS" of="$OUTPUT" seek=2048 conv=notrunc +dd bs=512 if="$ROOTFS" of="$OUTPUT" seek="$ROOTFSOFFSET" conv=notrunc diff --git a/target/linux/riscv64/patches/0001-base-fix-order-of-OF-initialization.patch b/target/linux/riscv64/patches/0001-base-fix-order-of-OF-initialization.patch new file mode 100644 index 0000000000..024b51ef2c --- /dev/null +++ b/target/linux/riscv64/patches/0001-base-fix-order-of-OF-initialization.patch @@ -0,0 +1,33 @@ +From 6de0b16fb7a2cea47e9a75534b4ec59f36998616 Mon Sep 17 00:00:00 2001 +From: "Wesley W. Terpstra" +Date: Fri, 12 May 2017 16:01:18 -0700 +Subject: [PATCH 01/11] base: fix order of OF initialization + +This fixes: [ 0.010000] cpu cpu0: Error -2 creating of_node link +... which you get for every CPU on all architectures with a OF cpu/ node. + +This affects riscv, nios, etc. + +Signed-off-by: Palmer Dabbelt +--- + drivers/base/init.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/base/init.c b/drivers/base/init.c +index dd85b05..908e652 100644 +--- a/drivers/base/init.c ++++ b/drivers/base/init.c +@@ -30,9 +30,9 @@ void __init driver_init(void) + /* These are also core pieces, but must come after the + * core core pieces. + */ ++ of_core_init(); + platform_bus_init(); + cpu_dev_init(); + memory_dev_init(); + container_dev_init(); +- of_core_init(); + } +-- +2.1.4 + diff --git a/target/linux/riscv64/patches/0002-dt-bindings-Correct-RISC-V-s-timebase-frequency.patch b/target/linux/riscv64/patches/0002-dt-bindings-Correct-RISC-V-s-timebase-frequency.patch new file mode 100644 index 0000000000..032738c369 --- /dev/null +++ b/target/linux/riscv64/patches/0002-dt-bindings-Correct-RISC-V-s-timebase-frequency.patch @@ -0,0 +1,69 @@ +From 7866ef38a00cd390596a67e19d23d8ffd6058732 Mon Sep 17 00:00:00 2001 +From: Palmer Dabbelt +Date: Tue, 21 Nov 2017 15:29:07 -0800 +Subject: [PATCH 02/11] dt-bindings: Correct RISC-V's timebase-frequency + +Someone must have read the device tree specification incorrectly, +because we were putting timebase-frequency in the wrong place. This +corrects the issue, moving it from + +/ { + cpus { + timebase-frequency = X; + } +} + +to + +/ { + cpus { + cpu@0 { + timebase-frequency = X; + } + } +} + +This is great, because the timer's frequency should really be a per-cpu +quantity on RISC-V systems since there's a timer per CPU. This should +lead to some cleanups in our timer driver. + +CC: Wesley Terpstra +Signed-off-by: Palmer Dabbelt +--- + Documentation/devicetree/bindings/riscv/cpus.txt | 4 +++- + 1 file changed, 3 insertions(+), 1 deletion(-) + +diff --git a/Documentation/devicetree/bindings/riscv/cpus.txt b/Documentation/devicetree/bindings/riscv/cpus.txt +index adf7b7a..b0b038d 100644 +--- a/Documentation/devicetree/bindings/riscv/cpus.txt ++++ b/Documentation/devicetree/bindings/riscv/cpus.txt +@@ -93,9 +93,9 @@ Linux is allowed to run on. + cpus { + #address-cells = <1>; + #size-cells = <0>; +- timebase-frequency = <1000000>; + cpu@0 { + clock-frequency = <1600000000>; ++ timebase-frequency = <1000000>; + compatible = "sifive,rocket0", "riscv"; + device_type = "cpu"; + i-cache-block-size = <64>; +@@ -113,6 +113,7 @@ Linux is allowed to run on. + }; + cpu@1 { + clock-frequency = <1600000000>; ++ timebase-frequency = <1000000>; + compatible = "sifive,rocket0", "riscv"; + d-cache-block-size = <64>; + d-cache-sets = <64>; +@@ -145,6 +146,7 @@ Example: Spike ISA Simulator with 1 Hart + This device tree matches the Spike ISA golden model as run with `spike -p1`. + + cpus { ++ timebase-frequency = <1000000>; + cpu@0 { + device_type = "cpu"; + reg = <0x00000000>; +-- +2.1.4 + diff --git a/target/linux/riscv64/patches/0003-dt-bindings-Add-an-enable-method-to-RISC-V.patch b/target/linux/riscv64/patches/0003-dt-bindings-Add-an-enable-method-to-RISC-V.patch new file mode 100644 index 0000000000..8c6e297352 --- /dev/null +++ b/target/linux/riscv64/patches/0003-dt-bindings-Add-an-enable-method-to-RISC-V.patch @@ -0,0 +1,44 @@ +From fd7aef2aae3b2d250f0c04224b3c85646c2e9c56 Mon Sep 17 00:00:00 2001 +From: Palmer Dabbelt +Date: Mon, 20 Nov 2017 11:26:36 -0800 +Subject: [PATCH 03/11] dt-bindings: Add an enable method to RISC-V + +RISC-V doesn't currently specify a mechanism for enabling or disabling +CPUs. Instead, we assume that all CPUs are enabled on boot, and if +someone wants to save power we instead put a CPU to sleep via a WFI +loop. Future systems may have an explicit mechanism for putting a CPU +to sleep, so we're standardizing the device tree entry for when that +happens. + +We're not defining a spin-table based interface to the firmware, as the +plan is to handle this entirely within the kernel instead. + +CC: Mark Rutland +Signed-off-by: Palmer Dabbelt +--- + Documentation/devicetree/bindings/riscv/cpus.txt | 9 +++++++++ + 1 file changed, 9 insertions(+) + +diff --git a/Documentation/devicetree/bindings/riscv/cpus.txt b/Documentation/devicetree/bindings/riscv/cpus.txt +index b0b038d..6aa9cd0 100644 +--- a/Documentation/devicetree/bindings/riscv/cpus.txt ++++ b/Documentation/devicetree/bindings/riscv/cpus.txt +@@ -82,6 +82,15 @@ described below. + Value type: + Definition: Contains the RISC-V ISA string of this hart. These + ISA strings are defined by the RISC-V ISA manual. ++ - cpu-enable-method: ++ Usage: optional ++ Value type: ++ Definition: When absent, default is either "always-disabled" ++ "always-enabled", depending on the current state ++ of the CPU. ++ Must be one of: ++ * "always-disabled": This CPU cannot be enabled. ++ * "always-enabled": This CPU cannot be disabled. + + Example: SiFive Freedom U540G Development Kit + --------------------------------------------- +-- +2.1.4 + diff --git a/target/linux/riscv64/patches/0004-RISC-V-Add-early-printk-support-via-the-SBI-console.patch b/target/linux/riscv64/patches/0004-RISC-V-Add-early-printk-support-via-the-SBI-console.patch new file mode 100644 index 0000000000..5bffed5e19 --- /dev/null +++ b/target/linux/riscv64/patches/0004-RISC-V-Add-early-printk-support-via-the-SBI-console.patch @@ -0,0 +1,63 @@ +From 577949829e04d23f58ef4ad5c448689c2ed70a49 Mon Sep 17 00:00:00 2001 +From: Palmer Dabbelt +Date: Fri, 8 Dec 2017 15:10:35 -0800 +Subject: [PATCH 04/11] RISC-V: Add early printk support via the SBI console + +This code lives entirely within the RISC-V arch code. I've left it +within an "#ifdef CONFIG_EARLY_PRINTK" despite always having +EARLY_PRINTK support on RISC-V just in case someone wants to remove +it. + +Signed-off-by: Palmer Dabbelt +--- + arch/riscv/kernel/setup.c | 27 +++++++++++++++++++++++++++ + 1 file changed, 27 insertions(+) + +diff --git a/arch/riscv/kernel/setup.c b/arch/riscv/kernel/setup.c +index f0d2070..2e56af3 100644 +--- a/arch/riscv/kernel/setup.c ++++ b/arch/riscv/kernel/setup.c +@@ -39,6 +39,27 @@ + #include + #include + ++#ifdef CONFIG_EARLY_PRINTK ++static void sbi_console_write(struct console *co, const char *buf, ++ unsigned int n) ++{ ++ int i; ++ ++ for (i = 0; i < n; ++i) { ++ if (buf[i] == '\n') ++ sbi_console_putchar('\r'); ++ sbi_console_putchar(buf[i]); ++ } ++} ++ ++struct console riscv_sbi_early_console_dev __initdata = { ++ .name = "early", ++ .write = sbi_console_write, ++ .flags = CON_PRINTBUFFER | CON_BOOT | CON_ANYTIME, ++ .index = -1 ++}; ++#endif ++ + #ifdef CONFIG_DUMMY_CONSOLE + struct screen_info screen_info = { + .orig_video_lines = 30, +@@ -195,6 +216,12 @@ static void __init setup_bootmem(void) + + void __init setup_arch(char **cmdline_p) + { ++#ifdef CONFIG_EARLY_PRINTK ++ if (likely(!early_console)) { ++ early_console = &riscv_sbi_early_console_dev; ++ register_console(early_console); ++ } ++#endif + *cmdline_p = boot_command_line; + + parse_early_param(); +-- +2.1.4 + diff --git a/target/linux/riscv64/patches/0005-RISC-V-simplify-software-interrupt-IPI-code.patch b/target/linux/riscv64/patches/0005-RISC-V-simplify-software-interrupt-IPI-code.patch new file mode 100644 index 0000000000..4c5fce0561 --- /dev/null +++ b/target/linux/riscv64/patches/0005-RISC-V-simplify-software-interrupt-IPI-code.patch @@ -0,0 +1,74 @@ +From b3b48cbc8a19fc3e3abd3ae9b5d271c12a1a0b87 Mon Sep 17 00:00:00 2001 +From: Christoph Hellwig +Date: Wed, 25 Jul 2018 08:11:13 +0200 +Subject: [PATCH 05/11] RISC-V: simplify software interrupt / IPI code + +Rename handle_ipi to riscv_software_interrupt, drop the unused return +value and provide a stub for the !SMP build. This allows simplifying +the upcoming interrupt controller driver by not providing a wrapper +for it. + +Signed-off-by: Christoph Hellwig +--- + arch/riscv/include/asm/smp.h | 13 +++++++++++-- + arch/riscv/kernel/smp.c | 6 ++---- + 2 files changed, 13 insertions(+), 6 deletions(-) + +diff --git a/arch/riscv/include/asm/smp.h b/arch/riscv/include/asm/smp.h +index 85e4220..80ecb95 100644 +--- a/arch/riscv/include/asm/smp.h ++++ b/arch/riscv/include/asm/smp.h +@@ -44,8 +44,17 @@ void arch_send_call_function_single_ipi(int cpu); + */ + #define raw_smp_processor_id() (*((int*)((char*)get_current() + TASK_TI_CPU))) + +-/* Interprocessor interrupt handler */ +-irqreturn_t handle_ipi(void); ++/* Software interrupt handler */ ++void riscv_software_interrupt(void); ++ ++#else /* CONFIG_SMP */ ++ ++/* ++ * We currently only use software interrupts to pass inter-processor ++ * interrupts, so if a non-SMP system gets a software interrupt then we ++ * don't know what to do. ++ */ ++#define riscv_software_interrupt() WARN_ON() + + #endif /* CONFIG_SMP */ + +diff --git a/arch/riscv/kernel/smp.c b/arch/riscv/kernel/smp.c +index 6d39624..906fe21 100644 +--- a/arch/riscv/kernel/smp.c ++++ b/arch/riscv/kernel/smp.c +@@ -45,7 +45,7 @@ int setup_profiling_timer(unsigned int multiplier) + return -EINVAL; + } + +-irqreturn_t handle_ipi(void) ++void riscv_software_interrupt(void) + { + unsigned long *pending_ipis = &ipi_data[smp_processor_id()].bits; + +@@ -60,7 +60,7 @@ irqreturn_t handle_ipi(void) + + ops = xchg(pending_ipis, 0); + if (ops == 0) +- return IRQ_HANDLED; ++ return; + + if (ops & (1 << IPI_RESCHEDULE)) + scheduler_ipi(); +@@ -73,8 +73,6 @@ irqreturn_t handle_ipi(void) + /* Order data access and bit testing. */ + mb(); + } +- +- return IRQ_HANDLED; + } + + static void +-- +2.1.4 + diff --git a/target/linux/riscv64/patches/0006-RISC-V-remove-INTERRUPT_CAUSE_-defines-from-asm-irq..patch b/target/linux/riscv64/patches/0006-RISC-V-remove-INTERRUPT_CAUSE_-defines-from-asm-irq..patch new file mode 100644 index 0000000000..1f22061d18 --- /dev/null +++ b/target/linux/riscv64/patches/0006-RISC-V-remove-INTERRUPT_CAUSE_-defines-from-asm-irq..patch @@ -0,0 +1,31 @@ +From 422e21b7ab41a21d7342b01fea7d1c6b91d986d8 Mon Sep 17 00:00:00 2001 +From: Christoph Hellwig +Date: Wed, 25 Jul 2018 08:23:21 +0200 +Subject: [PATCH 06/11] RISC-V: remove INTERRUPT_CAUSE_* defines from asm/irq.h + +These are only of use to the local irq controller driver, so add them in +that driver implementation instead, which will be submitted soon. + +Signed-off-by: Christoph Hellwig +--- + arch/riscv/include/asm/irq.h | 4 ---- + 1 file changed, 4 deletions(-) + +diff --git a/arch/riscv/include/asm/irq.h b/arch/riscv/include/asm/irq.h +index 4dee9d4..93eb75e 100644 +--- a/arch/riscv/include/asm/irq.h ++++ b/arch/riscv/include/asm/irq.h +@@ -17,10 +17,6 @@ + + #define NR_IRQS 0 + +-#define INTERRUPT_CAUSE_SOFTWARE 1 +-#define INTERRUPT_CAUSE_TIMER 5 +-#define INTERRUPT_CAUSE_EXTERNAL 9 +- + void riscv_timer_interrupt(void); + + #include +-- +2.1.4 + diff --git a/target/linux/riscv64/patches/0007-irqchip-RISC-V-Local-Interrupt-Controller-Driver.patch b/target/linux/riscv64/patches/0007-irqchip-RISC-V-Local-Interrupt-Controller-Driver.patch new file mode 100644 index 0000000000..107b6b7ee9 --- /dev/null +++ b/target/linux/riscv64/patches/0007-irqchip-RISC-V-Local-Interrupt-Controller-Driver.patch @@ -0,0 +1,249 @@ +From e07e6be7ef8b44155aebac95dde19a39498ebd00 Mon Sep 17 00:00:00 2001 +From: Palmer Dabbelt +Date: Tue, 19 Jun 2018 17:34:53 +0200 +Subject: [PATCH 07/11] irqchip: RISC-V Local Interrupt Controller Driver + +This patch adds a driver that manages the local interrupts on each +RISC-V hart, as specifiec by the RISC-V supervisor level ISA manual. +The local interrupt controller manages software interrupts, timer +interrupts, and hardware interrupts (which are routed via the +platform level interrupt controller). Per-hart local interrupt +controllers are found on all RISC-V systems. + +Signed-off-by: Palmer Dabbelt +[hch: Kconfig simplifications, various cleanups] +Signed-off-by: Christoph Hellwig +--- + drivers/irqchip/Kconfig | 4 + + drivers/irqchip/Makefile | 1 + + drivers/irqchip/irq-riscv-intc.c | 197 +++++++++++++++++++++++++++++++++++++++ + 3 files changed, 202 insertions(+) + create mode 100644 drivers/irqchip/irq-riscv-intc.c + +diff --git a/drivers/irqchip/Kconfig b/drivers/irqchip/Kconfig +index e9233db..8460fdce 100644 +--- a/drivers/irqchip/Kconfig ++++ b/drivers/irqchip/Kconfig +@@ -372,3 +372,7 @@ config QCOM_PDC + IRQs for Qualcomm Technologies Inc (QTI) mobile chips. + + endmenu ++ ++config RISCV_INTC ++ def_bool y ++ depends on RISCV +diff --git a/drivers/irqchip/Makefile b/drivers/irqchip/Makefile +index 15f268f..74e333c 100644 +--- a/drivers/irqchip/Makefile ++++ b/drivers/irqchip/Makefile +@@ -87,3 +87,4 @@ obj-$(CONFIG_MESON_IRQ_GPIO) += irq-meson-gpio.o + obj-$(CONFIG_GOLDFISH_PIC) += irq-goldfish-pic.o + obj-$(CONFIG_NDS32) += irq-ativic32.o + obj-$(CONFIG_QCOM_PDC) += qcom-pdc.o ++obj-$(CONFIG_RISCV_INTC) += irq-riscv-intc.o +diff --git a/drivers/irqchip/irq-riscv-intc.c b/drivers/irqchip/irq-riscv-intc.c +new file mode 100644 +index 0000000..883efaa +--- /dev/null ++++ b/drivers/irqchip/irq-riscv-intc.c +@@ -0,0 +1,197 @@ ++// SPDX-License-Identifier: GPL-2.0 ++/* ++ * Copyright (C) 2012 Regents of the University of California ++ * Copyright (C) 2017 SiFive ++ */ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#define NR_RISCV_IRQS (8 * sizeof(uintptr_t)) ++ ++/* ++ * Possible interrupt causes: ++ */ ++#define INTERRUPT_CAUSE_SOFTWARE 1 ++#define INTERRUPT_CAUSE_TIMER 5 ++#define INTERRUPT_CAUSE_EXTERNAL 9 ++ ++/* ++ * The high order bit of the trap cause register is always set for ++ * interrupts, which allows us to differentiate them from exceptions ++ * quickly. The INTERRUPT_CAUSE_* macros don't contain that bit, so we ++ * need to mask it off. ++ */ ++#define INTERRUPT_CAUSE_MASK (1UL << (NR_RISCV_IRQS - 1)) ++ ++struct riscv_irq_data { ++ struct irq_chip chip; ++ struct irq_domain *domain; ++ int hart; ++ char name[20]; ++}; ++ ++static DEFINE_PER_CPU(struct riscv_irq_data, riscv_irq_data); ++ ++static void riscv_intc_irq(struct pt_regs *regs) ++{ ++ struct pt_regs *old_regs = set_irq_regs(regs); ++ unsigned long cause = csr_read(scause); ++ struct irq_domain *domain; ++ ++ WARN_ON((cause & INTERRUPT_CAUSE_MASK) == 0); ++ cause &= ~INTERRUPT_CAUSE_MASK; ++ ++ irq_enter(); ++ ++ /* ++ * There are three classes of interrupt: timer, software, and ++ * external devices. We dispatch between them here. External ++ * device interrupts use the generic IRQ mechanisms. ++ */ ++ switch (cause) { ++ case INTERRUPT_CAUSE_TIMER: ++ riscv_timer_interrupt(); ++ break; ++ case INTERRUPT_CAUSE_SOFTWARE: ++ riscv_software_interrupt(); ++ break; ++ default: ++ domain = per_cpu(riscv_irq_data, smp_processor_id()).domain; ++ generic_handle_irq(irq_find_mapping(domain, cause)); ++ break; ++ } ++ ++ irq_exit(); ++ set_irq_regs(old_regs); ++} ++ ++static int riscv_irqdomain_map(struct irq_domain *d, unsigned int irq, ++ irq_hw_number_t hwirq) ++{ ++ struct riscv_irq_data *data = d->host_data; ++ ++ irq_set_chip_and_handler(irq, &data->chip, handle_simple_irq); ++ irq_set_chip_data(irq, data); ++ irq_set_noprobe(irq); ++ irq_set_affinity(irq, cpumask_of(data->hart)); ++ return 0; ++} ++ ++static const struct irq_domain_ops riscv_irqdomain_ops = { ++ .map = riscv_irqdomain_map, ++ .xlate = irq_domain_xlate_onecell, ++}; ++ ++/* ++ * On RISC-V systems local interrupts are masked or unmasked by writing the SIE ++ * (Supervisor Interrupt Enable) CSR. As CSRs can only be written on the local ++ * hart, these functions can only be called on the hart that corresponds to the ++ * IRQ chip. They are only called internally to this module, so they BUG_ON if ++ * this condition is violated rather than attempting to handle the error by ++ * forwarding to the target hart, as that's already expected to have been done. ++ */ ++static void riscv_irq_mask(struct irq_data *d) ++{ ++ struct riscv_irq_data *data = irq_data_get_irq_chip_data(d); ++ ++ BUG_ON(smp_processor_id() != data->hart); ++ csr_clear(sie, 1 << d->hwirq); ++} ++ ++static void riscv_irq_unmask(struct irq_data *d) ++{ ++ struct riscv_irq_data *data = irq_data_get_irq_chip_data(d); ++ ++ BUG_ON(smp_processor_id() != data->hart); ++ csr_set(sie, 1 << d->hwirq); ++} ++ ++/* Callbacks for twiddling SIE on another hart. */ ++static void riscv_irq_enable_helper(void *d) ++{ ++ riscv_irq_unmask(d); ++} ++ ++static void riscv_irq_disable_helper(void *d) ++{ ++ riscv_irq_mask(d); ++} ++ ++static void riscv_remote_ctrl(unsigned int cpu, void (*fn)(void *d), ++ struct irq_data *data) ++{ ++ smp_call_function_single(cpu, fn, data, true); ++} ++ ++static void riscv_irq_enable(struct irq_data *d) ++{ ++ struct riscv_irq_data *data = irq_data_get_irq_chip_data(d); ++ ++ /* ++ * It's only possible to write SIE on the current hart. This jumps ++ * over to the target hart if it's not the current one. It's invalid ++ * to write SIE on a hart that's not currently running. ++ */ ++ if (data->hart == smp_processor_id()) ++ riscv_irq_unmask(d); ++ else if (cpu_online(data->hart)) ++ riscv_remote_ctrl(data->hart, riscv_irq_enable_helper, d); ++ else ++ WARN_ON_ONCE(1); ++} ++ ++static void riscv_irq_disable(struct irq_data *d) ++{ ++ struct riscv_irq_data *data = irq_data_get_irq_chip_data(d); ++ ++ /* ++ * It's only possible to write SIE on the current hart. This jumps ++ * over to the target hart if it's not the current one. It's invalid ++ * to write SIE on a hart that's not currently running. ++ */ ++ if (data->hart == smp_processor_id()) ++ riscv_irq_mask(d); ++ else if (cpu_online(data->hart)) ++ riscv_remote_ctrl(data->hart, riscv_irq_disable_helper, d); ++ else ++ WARN_ON_ONCE(1); ++} ++ ++static int __init riscv_intc_init(struct device_node *node, ++ struct device_node *parent) ++{ ++ struct riscv_irq_data *data; ++ int hart; ++ ++ hart = riscv_of_processor_hart(node->parent); ++ if (hart < 0) ++ return -EIO; ++ ++ data = &per_cpu(riscv_irq_data, hart); ++ snprintf(data->name, sizeof(data->name), "riscv,cpu_intc,%d", hart); ++ data->hart = hart; ++ data->chip.name = data->name; ++ data->chip.irq_mask = riscv_irq_mask; ++ data->chip.irq_unmask = riscv_irq_unmask; ++ data->chip.irq_enable = riscv_irq_enable; ++ data->chip.irq_disable = riscv_irq_disable; ++ data->domain = irq_domain_add_linear(node, NR_RISCV_IRQS, ++ &riscv_irqdomain_ops, data); ++ if (!data->domain) ++ goto error_add_linear; ++ ++ set_handle_irq(&riscv_intc_irq); ++ pr_info("%s: %lu local interrupts mapped\n", data->name, NR_RISCV_IRQS); ++ return 0; ++ ++error_add_linear: ++ pr_warn("%s: unable to add IRQ domain\n", data->name); ++ return -ENXIO; ++} ++ ++IRQCHIP_DECLARE(riscv, "riscv,cpu-intc", riscv_intc_init); +-- +2.1.4 + diff --git a/target/linux/riscv64/patches/0008-dt-bindings-interrupt-controller-RISC-V-local-interr.patch b/target/linux/riscv64/patches/0008-dt-bindings-interrupt-controller-RISC-V-local-interr.patch new file mode 100644 index 0000000000..34379e3edb --- /dev/null +++ b/target/linux/riscv64/patches/0008-dt-bindings-interrupt-controller-RISC-V-local-interr.patch @@ -0,0 +1,67 @@ +From 1da2fd31207d1687f5edc6ba8f0402bbecc423f2 Mon Sep 17 00:00:00 2001 +From: Palmer Dabbelt +Date: Mon, 26 Jun 2017 22:07:50 -0700 +Subject: [PATCH 08/11] dt-bindings: interrupt-controller: RISC-V local + interrupt controller docs + +This patch adds documentation on the RISC-V local interrupt controller, +which is a per-hart interrupt controller that manages all interrupts +entering a RISC-V hart. This interrupt controller is present on all +RISC-V systems. + +Signed-off-by: Palmer Dabbelt +--- + .../interrupt-controller/riscv,cpu-intc.txt | 41 ++++++++++++++++++++++ + 1 file changed, 41 insertions(+) + create mode 100644 Documentation/devicetree/bindings/interrupt-controller/riscv,cpu-intc.txt + +diff --git a/Documentation/devicetree/bindings/interrupt-controller/riscv,cpu-intc.txt b/Documentation/devicetree/bindings/interrupt-controller/riscv,cpu-intc.txt +new file mode 100644 +index 0000000..61900e2 +--- /dev/null ++++ b/Documentation/devicetree/bindings/interrupt-controller/riscv,cpu-intc.txt +@@ -0,0 +1,41 @@ ++RISC-V Hart-Level Interrupt Controller (HLIC) ++--------------------------------------------- ++ ++RISC-V cores include Control Status Registers (CSRs) which are local to each ++hart and can be read or written by software. Some of these CSRs are used to ++control local interrupts connected to the core. Every interrupt is ultimately ++routed through a hart's HLIC before it interrupts that hart. ++ ++The RISC-V supervisor ISA manual specifies three interrupt sources that are ++attached to every HLIC: software interrupts, the timer interrupt, and external ++interrupts. Software interrupts are used to send IPIs between cores. The ++timer interrupt comes from an architecturally mandated real-time timer that is ++controller via SBI calls and CSR reads. External interrupts connect all other ++device interrupts to the HLIC, which are routed via the platform-level ++interrupt controller (PLIC). ++ ++All RISC-V systems that conform to the supervisor ISA specification are ++required to have a HLIC with these three interrupt sources present. Since the ++interrupt map is defined by the ISA it's not listed in the HLIC's device tree ++entry, though external interrupt controllers (like the PLIC, for example) will ++need to define how their interrupts map to the relevant HLICs. ++ ++Required properties: ++- compatible : "riscv,cpu-intc" ++- #interrupt-cells : should be <1> ++- interrupt-controller : Identifies the node as an interrupt controller ++ ++Furthermore, this interrupt-controller MUST be embedded inside the cpu ++definition of the hart whose CSRs control these local interrupts. ++ ++An example device tree entry for a HLIC is show below. ++ ++ cpu1: cpu@1 { ++ compatible = "riscv"; ++ ... ++ cpu1-intc: interrupt-controller { ++ #interrupt-cells = <1>; ++ compatible = "riscv,cpu-intc"; ++ interrupt-controller; ++ }; ++ }; +-- +2.1.4 + diff --git a/target/linux/riscv64/patches/0009-irqchip-New-RISC-V-PLIC-Driver.patch b/target/linux/riscv64/patches/0009-irqchip-New-RISC-V-PLIC-Driver.patch new file mode 100644 index 0000000000..478f987e00 --- /dev/null +++ b/target/linux/riscv64/patches/0009-irqchip-New-RISC-V-PLIC-Driver.patch @@ -0,0 +1,354 @@ +From 8e3e7dfba04d314cfbade03237a3ec16f436b779 Mon Sep 17 00:00:00 2001 +From: Palmer Dabbelt +Date: Tue, 19 Jun 2018 18:10:08 +0200 +Subject: [PATCH 09/11] irqchip: New RISC-V PLIC Driver + +This patch adds a driver for the Platform Level Interrupt Controller +(PLIC) specified as part of the RISC-V supervisor level ISA manual. +The PLIC connects global interrupt sources to the local interrupt +controller on each hart. + +Signed-off-by: Palmer Dabbelt +[hch: various cleanups, fixed typos, added SPDX tag] +Signed-off-by: Christoph Hellwig +--- + drivers/irqchip/Kconfig | 13 ++ + drivers/irqchip/Makefile | 1 + + drivers/irqchip/irq-riscv-plic.c | 295 +++++++++++++++++++++++++++++++++++++++ + 3 files changed, 309 insertions(+) + create mode 100644 drivers/irqchip/irq-riscv-plic.c + +diff --git a/drivers/irqchip/Kconfig b/drivers/irqchip/Kconfig +index 8460fdce..d1afac8 100644 +--- a/drivers/irqchip/Kconfig ++++ b/drivers/irqchip/Kconfig +@@ -376,3 +376,16 @@ endmenu + config RISCV_INTC + def_bool y + depends on RISCV ++ ++config RISCV_PLIC ++ bool "Platform-Level Interrupt Controller" ++ depends on RISCV ++ default y ++ help ++ This enables support for the PLIC chip found in standard RISC-V ++ systems. The PLIC controls devices interrupts and connects them to ++ each core's local interrupt controller. Aside from timer and ++ software interrupts, all other interrupt sources (MSI, GPIO, etc) ++ are subordinate to the PLIC. ++ ++ If you don't know what to do here, say Y. +diff --git a/drivers/irqchip/Makefile b/drivers/irqchip/Makefile +index 74e333c..7954f4c 100644 +--- a/drivers/irqchip/Makefile ++++ b/drivers/irqchip/Makefile +@@ -88,3 +88,4 @@ obj-$(CONFIG_GOLDFISH_PIC) += irq-goldfish-pic.o + obj-$(CONFIG_NDS32) += irq-ativic32.o + obj-$(CONFIG_QCOM_PDC) += qcom-pdc.o + obj-$(CONFIG_RISCV_INTC) += irq-riscv-intc.o ++obj-$(CONFIG_RISCV_PLIC) += irq-riscv-plic.o +diff --git a/drivers/irqchip/irq-riscv-plic.c b/drivers/irqchip/irq-riscv-plic.c +new file mode 100644 +index 0000000..7b80b73 +--- /dev/null ++++ b/drivers/irqchip/irq-riscv-plic.c +@@ -0,0 +1,295 @@ ++// SPDX-License-Identifier: GPL-2.0 ++/* ++ * Copyright (C) 2017 SiFive ++ */ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++/* ++ * From the RISC-V Priviledged Spec v1.10: ++ * ++ * Global interrupt sources are assigned small unsigned integer identifiers, ++ * beginning at the value 1. An interrupt ID of 0 is reserved to mean "no ++ * interrupt". Interrupt identifiers are also used to break ties when two or ++ * more interrupt sources have the same assigned priority. Smaller values of ++ * interrupt ID take precedence over larger values of interrupt ID. ++ * ++ * While the RISC-V supervisor spec doesn't define the maximum number of ++ * devices supported by the PLIC, the largest number supported by devices ++ * marked as 'riscv,plic0' (which is the only device type this driver supports, ++ * and is the only extant PLIC as of now) is 1024. As mentioned above, device ++ * 0 is defined to be non-existent so this device really only supports 1023 ++ * devices. ++ */ ++#define MAX_DEVICES 1024 ++#define MAX_CONTEXTS 15872 ++ ++struct plic_handler { ++ bool present; ++ int contextid; ++ struct plic_data *data; ++}; ++ ++/* ++ * PLIC devices are named like 'riscv,plic0,%llx', this is enough space to ++ * store that name. ++ */ ++#define PLIC_DATA_NAME_SIZE 30 ++ ++struct plic_data { ++ struct irq_chip chip; ++ struct irq_domain *domain; ++ u32 ndev; ++ void __iomem *reg; ++ int handlers; ++ struct plic_handler *handler; ++ char name[PLIC_DATA_NAME_SIZE]; ++ spinlock_t lock; ++}; ++ ++/* ++ * Each interrupt source has a priority register associated with it. ++ * We always hardwire it to one in Linux. ++ */ ++static inline u32 __iomem *plic_priority(struct plic_data *data, int hwirq) ++{ ++ return data->reg + hwirq * 0x04; ++} ++ ++/* ++ * Each hart context has a vector of interrupt enable bits associated with it. ++ * There is one bit for each interrupt source. ++ */ ++static inline u32 __iomem *plic_enable_vector(struct plic_data *data, ++ int contextid) ++{ ++ return data->reg + (1 << 13) + contextid * 0x80; ++} ++ ++/* ++ * Each hart context has a set of control registers associated with it. Right ++ * now there's only two: a source priority threshold over which the hart will ++ * take an interrupt, and a register to claim interrupts. ++ */ ++#define CONTEXT_THRESHOLD 0 ++#define CONTEXT_CLAIM 4 ++ ++static inline u32 __iomem *plic_hart_data(struct plic_data *data, ++ int contextid) ++{ ++ return data->reg + (1 << 21) + contextid * 0x1000; ++} ++ ++/* Explicit interrupt masking. */ ++static void plic_disable(struct plic_data *data, int contextid, int hwirq) ++{ ++ u32 __iomem *reg = plic_enable_vector(data, contextid) + (hwirq / 32); ++ u32 mask = ~(1 << (hwirq % 32)); ++ ++ spin_lock(&data->lock); ++ writel(readl(reg) & mask, reg); ++ spin_unlock(&data->lock); ++} ++ ++static void plic_enable(struct plic_data *data, int contextid, int hwirq) ++{ ++ u32 __iomem *reg = plic_enable_vector(data, contextid) + (hwirq / 32); ++ u32 bit = 1 << (hwirq % 32); ++ ++ spin_lock(&data->lock); ++ writel(readl(reg) | bit, reg); ++ spin_unlock(&data->lock); ++} ++ ++/* ++ * There is no need to mask/unmask PLIC interrupts ++ * They are "masked" by reading claim and "unmasked" when writing it back. ++ */ ++static void plic_irq_mask(struct irq_data *d) ++{ ++} ++ ++static void plic_irq_unmask(struct irq_data *d) ++{ ++} ++ ++static void plic_irq_enable(struct irq_data *d) ++{ ++ struct plic_data *data = irq_data_get_irq_chip_data(d); ++ int i; ++ ++ writel(1, plic_priority(data, d->hwirq)); ++ for (i = 0; i < data->handlers; ++i) ++ if (data->handler[i].present) ++ plic_enable(data, i, d->hwirq); ++} ++ ++static void plic_irq_disable(struct irq_data *d) ++{ ++ struct plic_data *data = irq_data_get_irq_chip_data(d); ++ int i; ++ ++ writel(0, plic_priority(data, d->hwirq)); ++ for (i = 0; i < data->handlers; ++i) ++ if (data->handler[i].present) ++ plic_disable(data, i, d->hwirq); ++} ++ ++static int plic_irqdomain_map(struct irq_domain *d, unsigned int irq, ++ irq_hw_number_t hwirq) ++{ ++ struct plic_data *data = d->host_data; ++ ++ irq_set_chip_and_handler(irq, &data->chip, handle_simple_irq); ++ irq_set_chip_data(irq, data); ++ irq_set_noprobe(irq); ++ return 0; ++} ++ ++static const struct irq_domain_ops plic_irqdomain_ops = { ++ .map = plic_irqdomain_map, ++ .xlate = irq_domain_xlate_onecell, ++}; ++ ++/* ++ * Handling an interrupt is a two-step process: first you claim the interrupt ++ * by reading the claim register, then you complete the interrupt by writing ++ * that source ID back to the same claim register. This automatically enables ++ * and disables the interrupt, so there's nothing else to do. ++ */ ++static void plic_chained_handle_irq(struct irq_desc *desc) ++{ ++ struct plic_handler *handler = irq_desc_get_handler_data(desc); ++ struct irq_chip *chip = irq_desc_get_chip(desc); ++ struct irq_domain *domain = handler->data->domain; ++ void __iomem *ph = plic_hart_data(handler->data, handler->contextid); ++ u32 what; ++ ++ chained_irq_enter(chip, desc); ++ while ((what = readl(ph + CONTEXT_CLAIM))) { ++ int irq = irq_find_mapping(domain, what); ++ ++ if (irq > 0) ++ generic_handle_irq(irq); ++ else ++ handle_bad_irq(desc); ++ writel(what, ph + CONTEXT_CLAIM); ++ } ++ chained_irq_exit(chip, desc); ++} ++ ++static int plic_init(struct device_node *node, struct device_node *parent) ++{ ++ struct plic_data *data; ++ struct resource resource; ++ int i, ok = 0; ++ int out = -1; ++ ++ data = kzalloc(sizeof(*data), GFP_KERNEL); ++ if (WARN_ON(!data)) ++ return -ENOMEM; ++ ++ spin_lock_init(&data->lock); ++ ++ data->reg = of_iomap(node, 0); ++ if (WARN_ON(!data->reg)) { ++ out = -EIO; ++ goto free_data; ++ } ++ ++ of_property_read_u32(node, "riscv,ndev", &data->ndev); ++ if (WARN_ON(!data->ndev)) { ++ out = -EINVAL; ++ goto free_reg; ++ } ++ ++ data->handlers = of_irq_count(node); ++ if (WARN_ON(!data->handlers)) { ++ out = -EINVAL; ++ goto free_reg; ++ } ++ ++ data->handler = ++ kcalloc(data->handlers, sizeof(*data->handler), GFP_KERNEL); ++ if (WARN_ON(!data->handler)) { ++ out = -ENOMEM; ++ goto free_reg; ++ } ++ ++ data->domain = irq_domain_add_linear(node, data->ndev + 1, ++ &plic_irqdomain_ops, data); ++ if (WARN_ON(!data->domain)) { ++ out = -ENOMEM; ++ goto free_handler; ++ } ++ ++ of_address_to_resource(node, 0, &resource); ++ snprintf(data->name, sizeof(data->name), ++ "riscv,plic0,%llx", resource.start); ++ data->chip.name = data->name; ++ data->chip.irq_mask = plic_irq_mask; ++ data->chip.irq_unmask = plic_irq_unmask; ++ data->chip.irq_enable = plic_irq_enable; ++ data->chip.irq_disable = plic_irq_disable; ++ ++ for (i = 0; i < data->handlers; ++i) { ++ struct plic_handler *handler = &data->handler[i]; ++ struct of_phandle_args parent; ++ int parent_irq, hwirq; ++ ++ handler->present = false; ++ ++ if (of_irq_parse_one(node, i, &parent)) ++ continue; ++ /* skip context holes */ ++ if (parent.args[0] == -1) ++ continue; ++ ++ /* skip any contexts that lead to inactive harts */ ++ if (of_device_is_compatible(parent.np, "riscv,cpu-intc") && ++ parent.np->parent && ++ riscv_of_processor_hart(parent.np->parent) < 0) ++ continue; ++ ++ parent_irq = irq_create_of_mapping(&parent); ++ if (!parent_irq) ++ continue; ++ ++ handler->present = true; ++ handler->contextid = i; ++ handler->data = data; ++ /* hwirq prio must be > this to trigger an interrupt */ ++ writel(0, plic_hart_data(data, i) + CONTEXT_THRESHOLD); ++ ++ for (hwirq = 1; hwirq <= data->ndev; ++hwirq) ++ plic_disable(data, i, hwirq); ++ irq_set_chained_handler_and_data(parent_irq, ++ plic_chained_handle_irq, handler); ++ ++ok; ++ } ++ ++ pr_info("%s: mapped %d interrupts to %d/%d handlers\n", ++ data->name, data->ndev, ok, data->handlers); ++ WARN_ON(!ok); ++ return 0; ++ ++free_handler: ++ kfree(data->handler); ++free_reg: ++ iounmap(data->reg); ++free_data: ++ kfree(data); ++ return out; ++} ++ ++IRQCHIP_DECLARE(plic0, "riscv,plic0", plic_init); +-- +2.1.4 + diff --git a/target/linux/riscv64/patches/0010-dt-bindings-interrupt-controller-RISC-V-PLIC-documen.patch b/target/linux/riscv64/patches/0010-dt-bindings-interrupt-controller-RISC-V-PLIC-documen.patch new file mode 100644 index 0000000000..6a05e9d336 --- /dev/null +++ b/target/linux/riscv64/patches/0010-dt-bindings-interrupt-controller-RISC-V-PLIC-documen.patch @@ -0,0 +1,84 @@ +From 634a87822bc9939c99068e72612e3c5df40bff18 Mon Sep 17 00:00:00 2001 +From: Palmer Dabbelt +Date: Mon, 26 Jun 2017 22:09:07 -0700 +Subject: [PATCH 10/11] dt-bindings: interrupt-controller: RISC-V PLIC + documentation + +This patch adds documentation for the platform-level interrupt +controller (PLIC) found in all RISC-V systems. This interrupt +controller routes interrupts from all the devices in the system to each +hart-local interrupt controller. + +Note: the DTS bindings for the PLIC aren't set in stone yet, as we might +want to change how we're specifying holes in the hart list. + +Signed-off-by: Palmer Dabbelt +--- + .../bindings/interrupt-controller/riscv,plic0.txt | 55 ++++++++++++++++++++++ + 1 file changed, 55 insertions(+) + create mode 100644 Documentation/devicetree/bindings/interrupt-controller/riscv,plic0.txt + +diff --git a/Documentation/devicetree/bindings/interrupt-controller/riscv,plic0.txt b/Documentation/devicetree/bindings/interrupt-controller/riscv,plic0.txt +new file mode 100644 +index 0000000..99cd359 +--- /dev/null ++++ b/Documentation/devicetree/bindings/interrupt-controller/riscv,plic0.txt +@@ -0,0 +1,55 @@ ++RISC-V Platform-Level Interrupt Controller (PLIC) ++------------------------------------------------- ++ ++The RISC-V supervisor ISA specification allows for the presence of a ++platform-level interrupt controller (PLIC). The PLIC connects all external ++interrupts in the system to all hart contexts in the system, via the external ++interrupt source in each hart's hart-local interrupt controller (HLIC). A hart ++context is a privilege mode in a hardware execution thread. For example, in ++an 4 core system with 2-way SMT, you have 8 harts and probably at least two ++privilege modes per hart; machine mode and supervisor mode. ++ ++Each interrupt can be enabled on per-context basis. Any context can claim ++a pending enabled interrupt and then release it once it has been handled. ++ ++Each interrupt has a configurable priority. Higher priority interrupts are ++serviced firs. Each context can specify a priority threshold. Interrupts ++with priority below this threshold will not cause the PLIC to raise its ++interrupt line leading to the context. ++ ++While the PLIC supports both edge-triggered and level-triggered interrupts, ++interrupt handlers are oblivious to this distinction and therefor it is not ++specific in the PLIC device-tree binding. ++ ++While the RISC-V ISA doesn't specify a memory layout for the PLIC, the ++"riscv,plic0" device is a concrete implementation of the PLIC that contains a ++specific memory layout. More details about the memory layout of the ++"riscv,plic0" device can be found as a comment in the device driver, or as part ++of the SiFive U5 Coreplex Series Manual (page 22 of the PDF of version 1.0) ++ ++ ++Required properties: ++- compatible : "riscv,plic0" ++- #address-cells : should be <0> ++- #interrupt-cells : should be <1> ++- interrupt-controller : Identifies the node as an interrupt controller ++- reg : Should contain 1 register range (address and length) ++- interrupts-extended : Specifies which contexts are connected to the PLIC, ++ with "-1" specifying that a context is not present. ++ ++Example: ++ ++ plic: interrupt-controller@c000000 { ++ #address-cells = <0>; ++ #interrupt-cells = <1>; ++ compatible = "riscv,plic0"; ++ interrupt-controller; ++ interrupts-extended = < ++ &cpu0-intc 11 ++ &cpu1-intc 11 &cpu1-intc 9 ++ &cpu2-intc 11 &cpu2-intc 9 ++ &cpu3-intc 11 &cpu3-intc 9 ++ &cpu4-intc 11 &cpu4-intc 9>; ++ reg = <0xc000000 0x4000000>; ++ riscv,ndev = <10>; ++ }; +-- +2.1.4 + diff --git a/target/linux/riscv64/patches/0011-clocksource-new-RISC-V-SBI-timer-driver.patch b/target/linux/riscv64/patches/0011-clocksource-new-RISC-V-SBI-timer-driver.patch new file mode 100644 index 0000000000..bcc89d4e35 --- /dev/null +++ b/target/linux/riscv64/patches/0011-clocksource-new-RISC-V-SBI-timer-driver.patch @@ -0,0 +1,204 @@ +From 406087706427cdd610ce2dc3fbffa655064944d3 Mon Sep 17 00:00:00 2001 +From: Palmer Dabbelt +Date: Tue, 19 Jun 2018 17:36:28 +0200 +Subject: [PATCH 11/11] clocksource: new RISC-V SBI timer driver + +The RISC-V ISA defines a per-hart real-time clock and timer, which is +present on all systems. The clock is accessed via the 'rdtime' +pseudo-instruction (which reads a CSR), and the timer is set via an SBI +call. + +Signed-off-by: Dmitriy Cherkasov +Signed-off-by: Palmer Dabbelt +[hch: remove dead code, add SPDX tags, minor cleanups] +Signed-off-by: Christoph Hellwig +--- + arch/riscv/include/asm/timer.h | 7 +++ + arch/riscv/kernel/time.c | 9 +--- + drivers/clocksource/Kconfig | 10 ++++ + drivers/clocksource/Makefile | 1 + + drivers/clocksource/riscv_timer.c | 97 +++++++++++++++++++++++++++++++++++++++ + 5 files changed, 116 insertions(+), 8 deletions(-) + create mode 100644 arch/riscv/include/asm/timer.h + create mode 100644 drivers/clocksource/riscv_timer.c + +diff --git a/arch/riscv/include/asm/timer.h b/arch/riscv/include/asm/timer.h +new file mode 100644 +index 0000000..ae20dd9 +--- /dev/null ++++ b/arch/riscv/include/asm/timer.h +@@ -0,0 +1,7 @@ ++/* SPDX-License-Identifier: GPL-2.0 */ ++#ifndef _ASM_RISCV_TIMER_H ++#define _ASM_RISCV_TIMER_H ++ ++DECLARE_PER_CPU(struct clock_event_device, riscv_clock_event); ++ ++#endif /* _ASM_RISCV_TIMER_H */ +diff --git a/arch/riscv/kernel/time.c b/arch/riscv/kernel/time.c +index 2463fcc..bba28fc 100644 +--- a/arch/riscv/kernel/time.c ++++ b/arch/riscv/kernel/time.c +@@ -16,19 +16,13 @@ + #include + #include + +-#ifdef CONFIG_RISCV_TIMER +-#include +-#endif +- + #include ++#include + + unsigned long riscv_timebase; + +-DECLARE_PER_CPU(struct clock_event_device, riscv_clock_event); +- + void riscv_timer_interrupt(void) + { +-#ifdef CONFIG_RISCV_TIMER + /* + * FIXME: This needs to be cleaned up along with the rest of the IRQ + * handling cleanup. See irq.c for more details. +@@ -36,7 +30,6 @@ void riscv_timer_interrupt(void) + struct clock_event_device *evdev = this_cpu_ptr(&riscv_clock_event); + + evdev->event_handler(evdev); +-#endif + } + + void __init init_clockevent(void) +diff --git a/drivers/clocksource/Kconfig b/drivers/clocksource/Kconfig +index dec0dd8..a57083e 100644 +--- a/drivers/clocksource/Kconfig ++++ b/drivers/clocksource/Kconfig +@@ -609,4 +609,14 @@ config ATCPIT100_TIMER + help + This option enables support for the Andestech ATCPIT100 timers. + ++config RISCV_TIMER ++ bool "Timer for the RISC-V platform" ++ depends on RISCV || COMPILE_TEST ++ select TIMER_PROBE ++ select TIMER_OF ++ help ++ This enables the per-hart timer built into all RISC-V systems, which ++ is accessed via both the SBI and the rdcycle instruction. This is ++ required for all RISC-V systems. ++ + endmenu +diff --git a/drivers/clocksource/Makefile b/drivers/clocksource/Makefile +index 00caf37..ded31f7 100644 +--- a/drivers/clocksource/Makefile ++++ b/drivers/clocksource/Makefile +@@ -78,3 +78,4 @@ obj-$(CONFIG_H8300_TPU) += h8300_tpu.o + obj-$(CONFIG_CLKSRC_ST_LPC) += clksrc_st_lpc.o + obj-$(CONFIG_X86_NUMACHIP) += numachip.o + obj-$(CONFIG_ATCPIT100_TIMER) += timer-atcpit100.o ++obj-$(CONFIG_RISCV_TIMER) += riscv_timer.o +diff --git a/drivers/clocksource/riscv_timer.c b/drivers/clocksource/riscv_timer.c +new file mode 100644 +index 0000000..48196b2 +--- /dev/null ++++ b/drivers/clocksource/riscv_timer.c +@@ -0,0 +1,97 @@ ++// SPDX-License-Identifier: GPL-2.0 ++/* ++ * Copyright (C) 2012 Regents of the University of California ++ * Copyright (C) 2017 SiFive ++ */ ++#include ++#include ++#include ++#include ++#include ++ ++#define MINDELTA 100 ++#define MAXDELTA 0x7fffffff ++ ++/* ++ * All RISC-V systems have a timer attached to every hart. These timers can be ++ * read by the 'rdcycle' pseudo instruction, and can use the SBI to setup ++ * events. In order to abstract the architecture-specific timer reading and ++ * setting functions away from the clock event insertion code, we provide ++ * function pointers to the clockevent subsystem that perform two basic ++ * operations: rdtime() reads the timer on the current CPU, and ++ * next_event(delta) sets the next timer event to 'delta' cycles in the future. ++ * As the timers are inherently a per-cpu resource, these callbacks perform ++ * operations on the current hart. There is guaranteed to be exactly one timer ++ * per hart on all RISC-V systems. ++ */ ++//DECLARE_PER_CPU(struct clocksource, riscv_clocksource); ++ ++static int next_event(unsigned long delta, struct clock_event_device *ce) ++{ ++ /* ++ * time_init() allocates a timer for each CPU. Since we're writing the ++ * timer comparison register here we can't allow the timers to cross ++ * harts. ++ */ ++ BUG_ON(ce != this_cpu_ptr(&riscv_clock_event)); ++ sbi_set_timer(get_cycles64() + delta); ++ return 0; ++} ++ ++DEFINE_PER_CPU(struct clock_event_device, riscv_clock_event) = { ++ .name = "riscv_timer_clockevent", ++ .features = CLOCK_EVT_FEAT_ONESHOT, ++ .rating = 100, ++ .set_next_event = next_event, ++}; ++ ++/* ++ * It is guarnteed that all the timers across all the harts are synchronized ++ * within one tick of each other, so while this could technically go ++ * backwards when hopping between CPUs, practically it won't happen. ++ */ ++static unsigned long long rdtime(struct clocksource *cs) ++{ ++ return get_cycles64(); ++} ++ ++DEFINE_PER_CPU(struct clocksource, riscv_clocksource) = { ++ .name = "riscv_clocksource", ++ .rating = 300, ++ .mask = CLOCKSOURCE_MASK(BITS_PER_LONG), ++ .flags = CLOCK_SOURCE_IS_CONTINUOUS, ++ .read = rdtime, ++}; ++ ++static int hart_of_timer(struct device_node *dev) ++{ ++ u32 hart; ++ ++ if (!dev) ++ return -1; ++ if (!of_device_is_compatible(dev, "riscv")) ++ return -1; ++ if (of_property_read_u32(dev, "reg", &hart)) ++ return -1; ++ ++ return hart; ++} ++ ++static int timer_riscv_init_dt(struct device_node *n) ++{ ++ int cpu_id = hart_of_timer(n); ++ struct clock_event_device *ce = per_cpu_ptr(&riscv_clock_event, cpu_id); ++ struct clocksource *cs = per_cpu_ptr(&riscv_clocksource, cpu_id); ++ ++ if (cpu_id == smp_processor_id()) { ++ clocksource_register_hz(cs, riscv_timebase); ++ ++ ce->cpumask = cpumask_of(cpu_id); ++ clockevents_config_and_register(ce, riscv_timebase, ++ MINDELTA, MAXDELTA); ++ } ++ ++ return 0; ++} ++ ++TIMER_OF_DECLARE(riscv_timer, "riscv", timer_riscv_init_dt); +-- +2.1.4 +