diff options
author | Sascha Hauer <s.hauer@pengutronix.de> | 2021-07-18 07:13:55 +0200 |
---|---|---|
committer | Sascha Hauer <s.hauer@pengutronix.de> | 2021-07-18 07:13:55 +0200 |
commit | 33f8f53317659cd2c61dd118bfa7150f33aa30fb (patch) | |
tree | cec893f4b273f4a78e1d84326d15e97b75a456df | |
parent | ca922d6044e49b1ed9782aa8eb28d1ed70931978 (diff) | |
parent | b60bdac8a5870dc136c9b028771371dd123a2431 (diff) | |
download | barebox-33f8f53317659cd2c61dd118bfa7150f33aa30fb.tar.gz barebox-33f8f53317659cd2c61dd118bfa7150f33aa30fb.tar.xz |
Merge branch 'for-next/riscv'
102 files changed, 4930 insertions, 171 deletions
diff --git a/Documentation/boards/riscv.rst b/Documentation/boards/riscv.rst index 53d13550f3..97f4d1deb7 100644 --- a/Documentation/boards/riscv.rst +++ b/Documentation/boards/riscv.rst @@ -60,6 +60,43 @@ into the config file. See https://barebox.org/jsbarebox/?graphic=1 for a live example. +BeagleV +------- + +barebox has second-stage support for the BeagleV Starlight:: + + make ARCH=riscv starfive_defconfig + make + +Thie resulting ``./images/barebox-beaglev-starlight.img`` can be used as payload +to opensbi:: + + git clone https://github.com/starfive-tech/opensbi + cd opensbi + export ARCH=riscv + export PLATFORM=starfive/vic7100 + export FW_PAYLOAD_PATH=$BAREBOX/build/images/barebox-beaglev-starlight.img + + make ARCH=riscv + ./fsz.sh ./build/platform/starfive/vic7100/firmware/fw_payload.bin fw_payload.bin.out + ls -l $OPENSBI/build/platform/starfive/vic7100/firmware/fw_payload.bin.out + +The resulting ``./platform/starfive/vic7100/firmware/fw_payload.bin.out`` can then +be flashed via Xmodem to the board:: + + picocom -b 115200 /dev/ttyUSB0 --send-cmd "sx -vv" --receive-cmd "rx -vv" + 0:update uboot + select the function: 0 + send file by xmodem + ^A^S./platform/starfive/vic7100/firmware/fw_payload.bin.out + +After reset, barebox should then boot to shell and attempt booting kernel ``Image`` +and device tree ``jh7100-starlight.dtb`` from the first root partition with the same +partition as rootfs. Note that while barebox does take over some initialization, +because of lack of Linux drivers, it doesn't yet do everything. If you experience +boot hangs, you may need to disable devices (or extend the starfive-pwrseq driver +to initialize it for you). + Erizo ----- diff --git a/arch/riscv/Kconfig b/arch/riscv/Kconfig index a4aa799acf..a814a1a45b 100644 --- a/arch/riscv/Kconfig +++ b/arch/riscv/Kconfig @@ -77,6 +77,11 @@ config RISCV_OPTIMZED_STRING_FUNCTIONS These functions work faster than the normal versions but increase your binary size. +config RISCV_EXCEPTIONS + bool "enable exception handling support" + default y + select ARCH_HAS_DATA_ABORT_MASK + config HAS_NMON bool @@ -97,14 +102,18 @@ config NMON_HELP Say yes here to get the nmon commands message on every nmon start. -# set if we run in machine mode, cleared if we run in supervisor mode +# selected by boards where barebox runs in machine mode config RISCV_M_MODE bool -# set if we are running in S-mode and can use SBI calls -config RISCV_SBI +# selected by boards where barebox runs in supervisor mode +config RISCV_S_MODE bool - depends on !RISCV_M_MODE - default y + +config RISCV_MULTI_MODE + def_bool RISCV_S_MODE && RISCV_M_MODE + +config RISCV_SBI + def_bool RISCV_S_MODE endmenu diff --git a/arch/riscv/Kconfig.socs b/arch/riscv/Kconfig.socs index c6875738d0..221ea133d4 100644 --- a/arch/riscv/Kconfig.socs +++ b/arch/riscv/Kconfig.socs @@ -15,14 +15,21 @@ config BOARD_ERIZO_GENERIC config SOC_VIRT bool "QEMU Virt Machine" + select RISCV_S_MODE select BOARD_RISCV_GENERIC_DT - select CLINT_TIMER + select HAS_CACHE help Generates an image tht can be be booted by QEMU. The image is called barebox-dt-2nd.img +config CPU_SIFIVE + bool + select HAS_CACHE + config SOC_SIFIVE bool "SiFive SoCs" + select CPU_SIFIVE + select RISCV_S_MODE select CLK_SIFIVE select CLK_SIFIVE_PRCI select RISCV_TIMER @@ -40,4 +47,52 @@ config BOARD_HIFIVE endif +config SOC_STARFIVE + bool "StarFive SoCs" + select ARCH_HAS_RESET_CONTROLLER + select RISCV_S_MODE + select HAS_ASM_DEBUG_LL + select HAS_NMON + help + This enables support for SiFive SoC platform hardware. + +if SOC_STARFIVE + +config SOC_STARFIVE_JH71XX + bool + select CPU_SIFIVE + +config SOC_STARFIVE_JH7100 + bool + select SOC_STARFIVE_JH71XX + select SIFIVE_L2 + help + Unlike JH7110 and later, CPU on the JH7100 are not cache-coherent + with respect to DMA masters like GMAC and DW MMC controller. + Select this if barebox needs to do DMA on this SoC. + +config BOARD_BEAGLEV + bool "BeagleV" + depends on ARCH_RV64I + select SOC_STARFIVE_JH71XX + select USE_COMPRESSED_DTB + +config BOARD_BEAGLEV_BETA + bool "BeagleV Beta (with JH7100)" + depends on BOARD_BEAGLEV + select SOC_STARFIVE_JH7100 + help + Select this for hardware using the earlier JH7100 SoC. The JH7110 + used with later production runs is cache-coherent and thus can do + without the special DMA handling enabled by this option. It's safe + to enable this option for other SoCs. + +endif + +comment "CPU features" + +config SIFIVE_L2 + bool "SiFive L2 cache controller" + depends on CPU_SIFIVE + endmenu diff --git a/arch/riscv/boards/Makefile b/arch/riscv/boards/Makefile index 99f22f32b4..cb28a25d8b 100644 --- a/arch/riscv/boards/Makefile +++ b/arch/riscv/boards/Makefile @@ -1,3 +1,4 @@ # SPDX-License-Identifier: GPL-2.0 obj-$(CONFIG_BOARD_ERIZO_GENERIC) += erizo/ obj-$(CONFIG_BOARD_HIFIVE) += hifive/ +obj-$(CONFIG_BOARD_BEAGLEV) += beaglev/ diff --git a/arch/riscv/boards/beaglev/Makefile b/arch/riscv/boards/beaglev/Makefile new file mode 100644 index 0000000000..23efc273ee --- /dev/null +++ b/arch/riscv/boards/beaglev/Makefile @@ -0,0 +1,5 @@ +# SPDX-License-Identifier: GPL-2.0 + +pbl-y += lowlevel.o +obj-y += board.o +bbenv-y += defaultenv-beaglev diff --git a/arch/riscv/boards/beaglev/board.c b/arch/riscv/boards/beaglev/board.c new file mode 100644 index 0000000000..110754ea95 --- /dev/null +++ b/arch/riscv/boards/beaglev/board.c @@ -0,0 +1,30 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright (C) 2021 Ahmad Fatoum, Pengutronix + */ + +#include <common.h> +#include <driver.h> +#include <bbu.h> +#include <envfs.h> + +static int beaglev_probe(struct device_d *dev) +{ + barebox_set_hostname("beaglev-starlight"); + + defaultenv_append_directory(defaultenv_beaglev); + + return 0; +} + +static const struct of_device_id beaglev_of_match[] = { + { .compatible = "beagle,beaglev-starlight-jh7100" }, + { /* sentinel */ }, +}; + +static struct driver_d beaglev_board_driver = { + .name = "board-beaglev", + .probe = beaglev_probe, + .of_compatible = beaglev_of_match, +}; +device_platform_driver(beaglev_board_driver); diff --git a/arch/riscv/boards/beaglev/defaultenv-beaglev/boot/buildroot b/arch/riscv/boards/beaglev/defaultenv-beaglev/boot/buildroot new file mode 100755 index 0000000000..157223bbee --- /dev/null +++ b/arch/riscv/boards/beaglev/defaultenv-beaglev/boot/buildroot @@ -0,0 +1,13 @@ +#!/bin/sh + +BOOT=/mnt/mmc0.0/boot + +detect mmc0 + +global.linux.bootargs.base="rhgb stmmaceth=chain_mode:1" + +global.bootm.oftree=$BOOT/jh7100-starlight.dtb +global.bootm.image=$BOOT/Image +global linux.bootargs.root=rootwait +global linux.bootargs.earlycon=earlycon +global.bootm.appendroot=1 diff --git a/arch/riscv/boards/beaglev/defaultenv-beaglev/boot/fedora b/arch/riscv/boards/beaglev/defaultenv-beaglev/boot/fedora new file mode 100755 index 0000000000..4f9ab16f82 --- /dev/null +++ b/arch/riscv/boards/beaglev/defaultenv-beaglev/boot/fedora @@ -0,0 +1,16 @@ +#!/bin/sh + +BOOT=/mnt/mmc0.0 +VERSION=5.10.6-210.0.riscv64.fc33.riscv64 + +detect mmc0 + +global.linux.bootargs.base="root=UUID=ae1e722a-d01b-4cdc-ab56-7b68abcdd0fe rhgb stmmaceth=chain_mode:1 selinux=0 LANG=en_US.UTF-8" + +global.bootm.oftree=${BOOT}/starfive_vic7100_beagle_v.dtb +global.bootm.initrd=${BOOT}/initramfs-${VERSION}.img +global.bootm.image=${BOOT}/vmlinuz-${VERSION} +global linux.bootargs.root=rootwait +global linux.bootargs.earlycon=earlycon +#global.bootm.root_dev=mmc0.1 +#global.bootm.appendroot=1 diff --git a/arch/riscv/boards/beaglev/defaultenv-beaglev/nv/boot.default b/arch/riscv/boards/beaglev/defaultenv-beaglev/nv/boot.default new file mode 100644 index 0000000000..880a6b1d8c --- /dev/null +++ b/arch/riscv/boards/beaglev/defaultenv-beaglev/nv/boot.default @@ -0,0 +1 @@ +buildroot net diff --git a/arch/riscv/boards/beaglev/lowlevel.c b/arch/riscv/boards/beaglev/lowlevel.c new file mode 100644 index 0000000000..db884dc762 --- /dev/null +++ b/arch/riscv/boards/beaglev/lowlevel.c @@ -0,0 +1,20 @@ +// SPDX-License-Identifier: GPL-2.0-only + +#include <common.h> +#include <debug_ll.h> +#include <asm/barebox-riscv.h> +#include <asm/riscv_nmon.h> + +ENTRY_FUNCTION(start_beaglev_starlight, a0, a1, a2) +{ + extern char __dtb_z_jh7100_beaglev_starlight_start[]; + void *fdt; + + debug_ll_init(); + barebox_nmon_entry(); + putc_ll('>'); + + fdt = __dtb_z_jh7100_beaglev_starlight_start + get_runtime_offset(); + + barebox_riscv_supervisor_entry(0x84000000, SZ_512M, a0, fdt); +} diff --git a/arch/riscv/boards/erizo/lowlevel.c b/arch/riscv/boards/erizo/lowlevel.c index 6acf15931c..ab06634bdb 100644 --- a/arch/riscv/boards/erizo/lowlevel.c +++ b/arch/riscv/boards/erizo/lowlevel.c @@ -3,16 +3,20 @@ #include <common.h> #include <asm/barebox-riscv.h> #include <debug_ll.h> +#include <asm/riscv_nmon.h> ENTRY_FUNCTION(start_erizo_generic, a0, a1, a2) { extern char __dtb_z_erizo_generic_start[]; + void *fdt; debug_ll_init(); + barebox_nmon_entry(); putc_ll('>'); /* On POR, we are running from read-only memory here. */ - barebox_riscv_entry(0x80000000, SZ_8M, - __dtb_z_erizo_generic_start + get_runtime_offset()); + fdt = __dtb_z_erizo_generic_start + get_runtime_offset(); + + barebox_riscv_machine_entry(0x80000000, SZ_8M, fdt); } diff --git a/arch/riscv/boards/hifive/lowlevel.c b/arch/riscv/boards/hifive/lowlevel.c index 1de13cac16..5e8969bef1 100644 --- a/arch/riscv/boards/hifive/lowlevel.c +++ b/arch/riscv/boards/hifive/lowlevel.c @@ -4,22 +4,23 @@ #include <asm/barebox-riscv.h> #include <debug_ll.h> +static __always_inline void start_hifive(unsigned long hartid, void *fdt) +{ + putc_ll('>'); + + barebox_riscv_supervisor_entry(0x80000000, SZ_128M, hartid, fdt); +} + ENTRY_FUNCTION(start_hifive_unmatched, a0, a1, a2) { extern char __dtb_z_hifive_unmatched_a00_start[]; - putc_ll('>'); - - barebox_riscv_entry(0x80000000, SZ_128M, - __dtb_z_hifive_unmatched_a00_start + get_runtime_offset()); + start_hifive(a0, __dtb_z_hifive_unmatched_a00_start + get_runtime_offset()); } ENTRY_FUNCTION(start_hifive_unleashed, a0, a1, a2) { extern char __dtb_z_hifive_unleashed_a00_start[]; - putc_ll('>'); - - barebox_riscv_entry(0x80000000, SZ_128M, - __dtb_z_hifive_unleashed_a00_start + get_runtime_offset()); + start_hifive(a0, __dtb_z_hifive_unleashed_a00_start + get_runtime_offset()); } diff --git a/arch/riscv/boot/Makefile b/arch/riscv/boot/Makefile index 968a826d16..80f63a4a0a 100644 --- a/arch/riscv/boot/Makefile +++ b/arch/riscv/boot/Makefile @@ -1,4 +1,5 @@ # SPDX-License-Identifier: GPL-2.0 obj-y += start.o pbl-y += entry.o uncompress.o +pbl-y += nmon_entry.o pbl-$(CONFIG_BOARD_GENERIC_DT) += board-dt-2nd.o diff --git a/arch/riscv/boot/board-dt-2nd.c b/arch/riscv/boot/board-dt-2nd.c index e9810f8add..f31c48a906 100644 --- a/arch/riscv/boot/board-dt-2nd.c +++ b/arch/riscv/boot/board-dt-2nd.c @@ -40,7 +40,7 @@ static const struct fdt_device_id console_ids[] = { { /* sentinel */ } }; -ENTRY_FUNCTION(start_dt_2nd, a0, _fdt, a2) +ENTRY_FUNCTION(start_dt_2nd, hartid, _fdt, a2) { unsigned long membase, memsize, endmem, endfdt, uncompressed_len; struct fdt_header *fdt = (void *)_fdt; @@ -73,5 +73,5 @@ ENTRY_FUNCTION(start_dt_2nd, a0, _fdt, a2) _fdt < riscv_mem_stack_top(membase, endmem)) memsize = ALIGN_DOWN(_fdt - membase, SZ_1M); - barebox_riscv_entry(membase, memsize, fdt); + barebox_riscv_supervisor_entry(membase, memsize, hartid, fdt); } diff --git a/arch/riscv/boot/entry.c b/arch/riscv/boot/entry.c index eb286423d8..e4a5c2208d 100644 --- a/arch/riscv/boot/entry.c +++ b/arch/riscv/boot/entry.c @@ -20,10 +20,11 @@ */ void __noreturn __naked barebox_riscv_entry(unsigned long membase, - unsigned long memsize, void *boarddata) + unsigned long memsize, void *boarddata, + unsigned flags) { unsigned long stack_top = riscv_mem_stack_top(membase, membase + memsize); asm volatile ("move sp, %0" : : "r"(stack_top)); - barebox_pbl_start(membase, memsize, boarddata); + barebox_pbl_start(membase, memsize, boarddata, flags); } diff --git a/arch/riscv/boot/entry.h b/arch/riscv/boot/entry.h index b3a24d2783..fb4af5eae5 100644 --- a/arch/riscv/boot/entry.h +++ b/arch/riscv/boot/entry.h @@ -6,10 +6,12 @@ void __noreturn barebox_non_pbl_start(unsigned long membase, unsigned long memsize, - void *boarddata); + void *boarddata, + unsigned flags); void __noreturn barebox_pbl_start(unsigned long membase, unsigned long memsize, - void *boarddata); + void *boarddata, + unsigned flags); #endif diff --git a/arch/riscv/boot/nmon_entry.S b/arch/riscv/boot/nmon_entry.S new file mode 100644 index 0000000000..ae017d2a1c --- /dev/null +++ b/arch/riscv/boot/nmon_entry.S @@ -0,0 +1,13 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +#include <linux/linkage.h> +#include <asm/sections.h> + +#include "asm/debug_ll.h" +#include "asm/riscv_nmon.h" + +.section .text_bare_init + +ENTRY(__barebox_nmon_entry) + riscv_nmon + ret +ENDPROC(__barebox_nmon_entry) diff --git a/arch/riscv/boot/start.c b/arch/riscv/boot/start.c index 05f6c6231f..72ab93cb76 100644 --- a/arch/riscv/boot/start.c +++ b/arch/riscv/boot/start.c @@ -16,6 +16,7 @@ #include <uncompress.h> #include <malloc.h> #include <compressed-dtb.h> +#include <asm/irq.h> #include <debug_ll.h> @@ -26,6 +27,7 @@ static unsigned long riscv_barebox_size; static unsigned long riscv_endmem; static void *barebox_boarddata; static unsigned long barebox_boarddata_size; +unsigned barebox_riscv_pbl_flags; void *barebox_riscv_boot_dtb(void) { @@ -107,7 +109,8 @@ device_initcall(barebox_memory_areas_init); * the pbl. The stack already has been set up by the pbl. */ __noreturn __no_sanitize_address __section(.text_entry) -void barebox_non_pbl_start(unsigned long membase, unsigned long memsize, void *boarddata) +void barebox_non_pbl_start(unsigned long membase, unsigned long memsize, + void *boarddata, unsigned flags) { unsigned long endmem = membase + memsize; unsigned long malloc_start, malloc_end; @@ -120,6 +123,8 @@ void barebox_non_pbl_start(unsigned long membase, unsigned long memsize, void *b barrier(); + irq_init_vector(__riscv_mode(flags)); + pr_debug("memory at 0x%08lx, size 0x%08lx\n", membase, memsize); riscv_endmem = endmem; @@ -168,18 +173,20 @@ void barebox_non_pbl_start(unsigned long membase, unsigned long memsize, void *b mem_malloc_init((void *)malloc_start, (void *)malloc_end - 1); + barebox_riscv_pbl_flags = flags; + pr_debug("starting barebox...\n"); start_barebox(); } -void start(unsigned long membase, unsigned long memsize, void *boarddata); +void start(unsigned long membase, unsigned long memsize, void *boarddata, unsigned flags); /* * First function in the uncompressed image. We get here from * the pbl. The stack already has been set up by the pbl. */ void __no_sanitize_address __section(.text_entry) start(unsigned long membase, - unsigned long memsize, void *boarddata) + unsigned long memsize, void *boarddata, unsigned flags) { - barebox_non_pbl_start(membase, memsize, boarddata); + barebox_non_pbl_start(membase, memsize, boarddata, flags); } diff --git a/arch/riscv/boot/uncompress.c b/arch/riscv/boot/uncompress.c index b4e010998a..4ed9b4d371 100644 --- a/arch/riscv/boot/uncompress.c +++ b/arch/riscv/boot/uncompress.c @@ -14,6 +14,7 @@ #include <asm-generic/memory_layout.h> #include <asm/sections.h> #include <asm/unaligned.h> +#include <asm/irq.h> #include <debug_ll.h> @@ -23,15 +24,17 @@ unsigned long free_mem_ptr; unsigned long free_mem_end_ptr; void __noreturn barebox_pbl_start(unsigned long membase, unsigned long memsize, - void *fdt) + void *fdt, unsigned flags) { uint32_t pg_len, uncompressed_len; - void __noreturn (*barebox)(unsigned long, unsigned long, void *); + void __noreturn (*barebox)(unsigned long, unsigned long, void *, unsigned); unsigned long endmem = membase + memsize; unsigned long barebox_base; void *pg_start, *pg_end; unsigned long pc = get_pc(); + irq_init_vector(__riscv_mode(flags)); + /* piggy data is not relocated, so determine the bounds now */ pg_start = input_data + get_runtime_offset(); pg_end = input_data_end + get_runtime_offset(); @@ -63,9 +66,11 @@ void __noreturn barebox_pbl_start(unsigned long membase, unsigned long memsize, pbl_barebox_uncompress((void*)barebox_base, pg_start, pg_len); + sync_caches_for_execution(); + barebox = (void *)barebox_base; pr_debug("jumping to uncompressed image at 0x%p. dtb=0x%p\n", barebox, fdt); - barebox(membase, memsize, fdt); + barebox(membase, memsize, fdt, flags); } diff --git a/arch/riscv/configs/starfive_defconfig b/arch/riscv/configs/starfive_defconfig new file mode 100644 index 0000000000..c4df2256f5 --- /dev/null +++ b/arch/riscv/configs/starfive_defconfig @@ -0,0 +1,131 @@ +CONFIG_ARCH_RV64I=y +CONFIG_SOC_STARFIVE=y +CONFIG_BOARD_BEAGLEV=y +CONFIG_BOARD_BEAGLEV_BETA=y +CONFIG_BOARD_RISCV_GENERIC_DT=y +CONFIG_RISCV_OPTIMZED_STRING_FUNCTIONS=y +CONFIG_STACK_SIZE=0x20000 +CONFIG_MALLOC_SIZE=0x0 +CONFIG_MALLOC_TLSF=y +CONFIG_KALLSYMS=y +CONFIG_RELOCATABLE=y +CONFIG_PANIC_HANG=y +CONFIG_HUSH_FANCY_PROMPT=y +CONFIG_CMDLINE_EDITING=y +CONFIG_AUTO_COMPLETE=y +CONFIG_MENU=y +CONFIG_BOOTM_INITRD=y +CONFIG_SYSTEM_PARTITIONS=y +CONFIG_IMD_TARGET=y +CONFIG_CONSOLE_ALLOW_COLOR=y +CONFIG_PBL_CONSOLE=y +CONFIG_PARTITION_DISK_EFI=y +CONFIG_DEFAULT_ENVIRONMENT_GENERIC_NEW=y +CONFIG_BAREBOXENV_TARGET=y +CONFIG_BAREBOXCRC32_TARGET=y +CONFIG_STATE=y +CONFIG_STATE_CRYPTO=y +CONFIG_BOOTCHOOSER=y +CONFIG_RESET_SOURCE=y +CONFIG_MACHINE_ID=y +CONFIG_CMD_DMESG=y +CONFIG_LONGHELP=y +CONFIG_CMD_IOMEM=y +CONFIG_CMD_IMD=y +CONFIG_CMD_MEMINFO=y +CONFIG_CMD_POLLER=y +CONFIG_CMD_SLICE=y +CONFIG_CMD_GO=y +CONFIG_CMD_LOADY=y +CONFIG_CMD_RESET=y +CONFIG_CMD_BOOTCHOOSER=y +CONFIG_CMD_EXPORT=y +CONFIG_CMD_PRINTENV=y +CONFIG_CMD_MAGICVAR=y +CONFIG_CMD_MAGICVAR_HELP=y +CONFIG_CMD_SAVEENV=y +CONFIG_CMD_CMP=y +CONFIG_CMD_FILETYPE=y +CONFIG_CMD_LN=y +CONFIG_CMD_MD5SUM=y +CONFIG_CMD_SHA1SUM=y +CONFIG_CMD_SHA256SUM=y +CONFIG_CMD_UNCOMPRESS=y +CONFIG_CMD_MSLEEP=y +CONFIG_CMD_SLEEP=y +CONFIG_CMD_DHCP=y +CONFIG_CMD_PING=y +CONFIG_CMD_EDIT=y +CONFIG_CMD_READLINE=y +CONFIG_CMD_TIMEOUT=y +CONFIG_CMD_MEMTEST=y +CONFIG_CMD_MM=y +CONFIG_CMD_CLK=y +CONFIG_CMD_DETECT=y +CONFIG_CMD_FLASH=y +CONFIG_CMD_GPIO=y +CONFIG_CMD_POWEROFF=y +CONFIG_CMD_SPI=y +CONFIG_CMD_WD=y +CONFIG_CMD_2048=y +CONFIG_CMD_BAREBOX_UPDATE=y +CONFIG_CMD_OF_DIFF=y +CONFIG_CMD_OF_NODE=y +CONFIG_CMD_OF_PROPERTY=y +CONFIG_CMD_OF_DISPLAY_TIMINGS=y +CONFIG_CMD_OF_FIXUP_STATUS=y +CONFIG_CMD_OF_OVERLAY=y +CONFIG_CMD_OFTREE=y +CONFIG_CMD_TIME=y +CONFIG_CMD_DHRYSTONE=y +CONFIG_NET=y +CONFIG_NET_NFS=y +CONFIG_DRIVER_SERIAL_NS16550=y +CONFIG_DRIVER_NET_DESIGNWARE=y +CONFIG_DRIVER_NET_DESIGNWARE_GENERIC=y +CONFIG_DRIVER_NET_DESIGNWARE_STARFIVE=y +CONFIG_MICREL_PHY=y +CONFIG_SPI_MEM=y +CONFIG_DRIVER_SPI_GPIO=y +CONFIG_MCI=y +CONFIG_MCI_DW=y +CONFIG_CLOCKSOURCE_DUMMY_RATE=60000 +CONFIG_SRAM=y +CONFIG_STARFIVE_PWRSEQ=y +CONFIG_LED=y +CONFIG_LED_GPIO=y +CONFIG_LED_GPIO_OF=y +CONFIG_LED_TRIGGERS=y +CONFIG_WATCHDOG=y +CONFIG_STARFIVE_WDT=y +CONFIG_HWRNG=y +CONFIG_HW_RANDOM_STARFIVE=y +CONFIG_GPIO_GENERIC_PLATFORM=y +CONFIG_GPIO_STARFIVE=y +CONFIG_PINCTRL_SINGLE=y +CONFIG_NVMEM=y +CONFIG_NVMEM_RMEM=y +CONFIG_STARFIVE_OTP=y +CONFIG_SYSCON_REBOOT_MODE=y +CONFIG_NVMEM_REBOOT_MODE=y +CONFIG_POWER_RESET_SYSCON=y +CONFIG_POWER_RESET_SYSCON_POWEROFF=y +CONFIG_POWER_RESET_GPIO=y +CONFIG_POWER_RESET_GPIO_RESTART=y +# CONFIG_VIRTIO_MENU is not set +CONFIG_FS_EXT4=y +CONFIG_FS_TFTP=y +CONFIG_FS_NFS=y +CONFIG_FS_FAT=y +CONFIG_FS_FAT_WRITE=y +CONFIG_FS_FAT_LFN=y +CONFIG_FS_UIMAGEFS=y +CONFIG_FS_PSTORE=y +CONFIG_FS_SQUASHFS=y +CONFIG_ZLIB=y +CONFIG_BZLIB=y +CONFIG_LZ4_DECOMPRESS=y +CONFIG_ZSTD_DECOMPRESS=y +CONFIG_XZ_DECOMPRESS=y +CONFIG_BASE64=y +CONFIG_DIGEST_CRC32_GENERIC=y diff --git a/arch/riscv/cpu/Makefile b/arch/riscv/cpu/Makefile index f1312be699..717baaaaa7 100644 --- a/arch/riscv/cpu/Makefile +++ b/arch/riscv/cpu/Makefile @@ -1,3 +1,7 @@ # SPDX-License-Identifier: GPL-2.0 obj-y += core.o time.o +obj-$(CONFIG_HAS_DMA) += dma.o +obj-pbl-$(CONFIG_RISCV_M_MODE) += mtrap.o +obj-pbl-$(CONFIG_RISCV_S_MODE) += strap.o +obj-pbl-y += interrupts.o diff --git a/arch/riscv/cpu/core.c b/arch/riscv/cpu/core.c index 982d378edd..80730c05b5 100644 --- a/arch/riscv/cpu/core.c +++ b/arch/riscv/cpu/core.c @@ -18,7 +18,11 @@ #include <linux/clk.h> #include <linux/err.h> #include <memory.h> +#include <asm/barebox-riscv.h> #include <asm-generic/memory_layout.h> +#include <globalvar.h> +#include <magicvar.h> +#include <asm/system.h> #include <io.h> static int riscv_request_stack(void) @@ -30,6 +34,31 @@ coredevice_initcall(riscv_request_stack); static struct device_d timer_dev; +static s64 hartid; + +BAREBOX_MAGICVAR(global.hartid, "RISC-V hartid"); + +static int riscv_fixup_cpus(struct device_node *root, void *context) +{ + struct device_node *cpus_node, *np, *tmp; + + cpus_node = of_find_node_by_name(root, "cpus"); + if (!cpus_node) + return 0; + + for_each_child_of_node_safe(cpus_node, tmp, np) { + u32 cpu_index; + + if (of_property_read_u32(np, "reg", &cpu_index)) + continue; + + if (cpu_index != hartid) + of_delete_node(np); + } + + return 0; +} + static int riscv_probe(struct device_d *parent) { int ret; @@ -46,7 +75,11 @@ static int riscv_probe(struct device_d *parent) return ret; } - return 0; + hartid = riscv_hartid(); + if (hartid >= 0) + globalvar_add_simple_uint64("hartid", &hartid, "%llu"); + + return of_register_fixup(riscv_fixup_cpus, NULL); } static struct of_device_id riscv_dt_ids[] = { @@ -60,3 +93,9 @@ static struct driver_d riscv_driver = { .of_compatible = riscv_dt_ids, }; postcore_platform_driver(riscv_driver); + +static void arch_shutdown(void) +{ + sync_caches_for_execution(); +} +archshutdown_exitcall(arch_shutdown); diff --git a/arch/riscv/cpu/dma.c b/arch/riscv/cpu/dma.c new file mode 100644 index 0000000000..5a4d714e5e --- /dev/null +++ b/arch/riscv/cpu/dma.c @@ -0,0 +1,74 @@ +/* SPDX-License-Identifier: GPL-2.0 */ + +#include <common.h> +#include <xfuncs.h> +#include <asm/dma.h> +#include <malloc.h> + +static void __dma_flush_range(dma_addr_t start, dma_addr_t end) +{ +} + +static void *__dma_alloc_coherent(size_t size, dma_addr_t *dma_handle) +{ + void *ret; + + ret = xmemalign(PAGE_SIZE, size); + + memset(ret, 0, size); + + if (dma_handle) + *dma_handle = (dma_addr_t)ret; + + return ret; +} + +static void __dma_free_coherent(void *vaddr, dma_addr_t dma_handle, size_t size) +{ + free(vaddr); +} + +static const struct dma_ops coherent_dma_ops = { + .alloc_coherent = __dma_alloc_coherent, + .free_coherent = __dma_free_coherent, + .flush_range = __dma_flush_range, + .inv_range = __dma_flush_range, +}; + +static const struct dma_ops *dma_ops = &coherent_dma_ops; + +void *dma_alloc_coherent(size_t size, dma_addr_t *dma_handle) +{ + return dma_ops->alloc_coherent(size, dma_handle); +} + +void dma_free_coherent(void *vaddr, dma_addr_t dma_handle, size_t size) +{ + dma_ops->free_coherent(vaddr, dma_handle, size); +} + +void dma_set_ops(const struct dma_ops *ops) +{ + dma_ops = ops; +} + +void dma_sync_single_for_cpu(dma_addr_t address, size_t size, enum dma_data_direction dir) +{ + /* + * FIXME: This function needs a device argument to support non 1:1 mappings + */ + if (dir != DMA_TO_DEVICE) + dma_ops->inv_range(address, address + size); +} + +void dma_sync_single_for_device(dma_addr_t address, size_t size, enum dma_data_direction dir) +{ + /* + * FIXME: This function needs a device argument to support non 1:1 mappings + */ + + if (dir == DMA_FROM_DEVICE) + dma_ops->inv_range(address, address + size); + else + dma_ops->flush_range(address, address + size); +} diff --git a/arch/riscv/cpu/interrupts.c b/arch/riscv/cpu/interrupts.c new file mode 100644 index 0000000000..0e8951b619 --- /dev/null +++ b/arch/riscv/cpu/interrupts.c @@ -0,0 +1,139 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright (c) 2016-17 Microsemi Corporation. + * Padmarao Begari, Microsemi Corporation <padmarao.begari@microsemi.com> + * + * Copyright (C) 2017 Andes Technology Corporation + * Rick Chen, Andes Technology Corporation <rick@andestech.com> + * + * Copyright (C) 2019 Sean Anderson <seanga2@gmail.com> + */ + +#include <common.h> +#include <asm/system.h> +#include <asm/ptrace.h> +#include <asm/irq.h> +#include <asm/csr.h> +#include <abort.h> +#include <pbl.h> + +#define MCAUSE32_INT 0x80000000 +#define MCAUSE64_INT 0x8000000000000000 + +#ifdef CONFIG_64BIT +# define MCAUSE_INT MCAUSE64_INT +#else +# define MCAUSE_INT MCAUSE32_INT +#endif + +static void show_regs(const struct pt_regs *regs) +{ + printf("\nsp: " REG_FMT " gp: " REG_FMT " tp: " REG_FMT "\n", + regs->sp, regs->gp, regs->tp); + printf("t0: " REG_FMT " t1: " REG_FMT " t2: " REG_FMT "\n", + regs->t0, regs->t1, regs->t2); + printf("s0: " REG_FMT " s1: " REG_FMT " a0: " REG_FMT "\n", + regs->s0, regs->s1, regs->a0); + printf("a1: " REG_FMT " a2: " REG_FMT " a3: " REG_FMT "\n", + regs->a1, regs->a2, regs->a3); + printf("a4: " REG_FMT " a5: " REG_FMT " a6: " REG_FMT "\n", + regs->a4, regs->a5, regs->a6); + printf("a7: " REG_FMT " s2: " REG_FMT " s3: " REG_FMT "\n", + regs->a7, regs->s2, regs->s3); + printf("s4: " REG_FMT " s5: " REG_FMT " s6: " REG_FMT "\n", + regs->s4, regs->s5, regs->s6); + printf("s7: " REG_FMT " s8: " REG_FMT " s9: " REG_FMT "\n", + regs->s7, regs->s8, regs->s9); + printf("s10: " REG_FMT " s11: " REG_FMT " t3: " REG_FMT "\n", + regs->s10, regs->s11, regs->t3); + printf("t4: " REG_FMT " t5: " REG_FMT " t6: " REG_FMT "\n", + regs->t4, regs->t5, regs->t6); +} + +static void report_trap(const struct pt_regs *regs) +{ + static const char * const exception_code[] = { + [0] = "Instruction address misaligned", + [1] = "Instruction access fault", + [2] = "Illegal instruction", + [3] = "Breakpoint", + [4] = "Load address misaligned", + [5] = "Load access fault", + [6] = "Store/AMO address misaligned", + [7] = "Store/AMO access fault", + [8] = "Environment call from U-mode", + [9] = "Environment call from S-mode", + [10] = "Reserved", + [11] = "Environment call from M-mode", + [12] = "Instruction page fault", + [13] = "Load page fault", + [14] = "Reserved", + [15] = "Store/AMO page fault", + + }; + + printf("Unhandled exception: %ld", regs->cause); + + if (regs->cause < ARRAY_SIZE(exception_code)) + printf(" \"%s\"\n", exception_code[regs->cause]); + + printf("E [<" REG_FMT ">] ra: [<" REG_FMT ">] tval: " REG_FMT "\n", + regs->epc, regs->ra, regs->badaddr); + + show_regs(regs); +} + + + +#ifdef __PBL__ + +static inline bool skip_data_abort(struct pt_regs *regs) +{ + return false; +} + +#else + +static volatile bool riscv_data_abort_occurred; +static volatile bool riscv_ignore_data_abort; + +void data_abort_mask(void) +{ + riscv_data_abort_occurred = false; + riscv_ignore_data_abort = true; +} + +int data_abort_unmask(void) +{ + riscv_ignore_data_abort = false; + return riscv_data_abort_occurred; +} + +static inline bool skip_data_abort(struct pt_regs *regs) +{ + return regs->cause == EXC_LOAD_ACCESS && riscv_ignore_data_abort; +} + +#endif + +unsigned long handle_trap(struct pt_regs *regs) +{ + if (skip_data_abort(regs)) + goto skip; + + if (regs->cause == 2) { /* illegal instruction */ + switch(*(unsigned long *)regs->epc) { + case 0x0000100f: /* fence.i */ + goto skip; + default: + break; + } + } + + report_trap(regs); + hang(); + +skip: + return regs->epc + 4; +} + diff --git a/arch/riscv/cpu/mtrap.S b/arch/riscv/cpu/mtrap.S new file mode 100644 index 0000000000..e4aba7d694 --- /dev/null +++ b/arch/riscv/cpu/mtrap.S @@ -0,0 +1,30 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Copyright (C) 2020 FORTH-ICS/CARV + * Nick Kossifidis <mick@ics.forth.gr> + */ + +#include <asm/asm.h> +#include <asm/irq.h> +#include <linux/linkage.h> + +.section .text.mtrap_entry +ENTRY(mtrap_entry) + addi sp, sp, -PT_SIZE_ON_STACK + pt_regs_push sp + csrr t1, mstatus + csrr t2, mepc + csrr t3, mtval + csrr t4, mcause + + REG_S t1, PT_STATUS(sp) + REG_S t2, PT_EPC(sp) + REG_S t3, PT_BADADDR(sp) + REG_S t4, PT_CAUSE(sp) + mv a0, sp + jal handle_trap + csrw mepc, a0 + pt_regs_pop sp + addi sp, sp, PT_SIZE_ON_STACK + mret +ENDPROC(mtrap_entry) diff --git a/arch/riscv/cpu/strap.S b/arch/riscv/cpu/strap.S new file mode 100644 index 0000000000..c1d684c194 --- /dev/null +++ b/arch/riscv/cpu/strap.S @@ -0,0 +1,30 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Copyright (C) 2020 FORTH-ICS/CARV + * Nick Kossifidis <mick@ics.forth.gr> + */ + +#include <asm/asm.h> +#include <asm/irq.h> +#include <linux/linkage.h> + +.section .text.strap_entry +ENTRY(strap_entry) + addi sp, sp, -PT_SIZE_ON_STACK + pt_regs_push sp + csrr t1, sstatus + csrr t2, sepc + csrr t3, stval + csrr t4, scause + + REG_S t1, PT_STATUS(sp) + REG_S t2, PT_EPC(sp) + REG_S t3, PT_BADADDR(sp) + REG_S t4, PT_CAUSE(sp) + mv a0, sp + jal handle_trap + csrw sepc, a0 + pt_regs_pop sp + addi sp, sp, PT_SIZE_ON_STACK + sret +ENDPROC(strap_entry) diff --git a/arch/riscv/dts/Makefile b/arch/riscv/dts/Makefile index 17fdc9445b..4a15423b7f 100644 --- a/arch/riscv/dts/Makefile +++ b/arch/riscv/dts/Makefile @@ -7,5 +7,6 @@ obj- += dummy.o pbl-$(CONFIG_BOARD_ERIZO_GENERIC) += erizo-generic.dtb.o pbl-$(CONFIG_BOARD_HIFIVE) += hifive-unmatched-a00.dtb.o \ hifive-unleashed-a00.dtb.o +pbl-$(CONFIG_BOARD_BEAGLEV) += jh7100-beaglev-starlight.dtb.o clean-files := *.dtb *.dtb.S .*.dtc .*.pre .*.dts diff --git a/arch/riscv/dts/jh7100-beaglev-starlight.dts b/arch/riscv/dts/jh7100-beaglev-starlight.dts new file mode 100644 index 0000000000..8b4c1ac0ea --- /dev/null +++ b/arch/riscv/dts/jh7100-beaglev-starlight.dts @@ -0,0 +1,54 @@ +// SPDX-License-Identifier: GPL-2.0 + +/dts-v1/; + +#include "jh7100-beaglev-starlight.dtsi" +#include <dt-bindings/gpio/gpio.h> + +/ { + #address-cells = <2>; + #size-cells = <2>; + compatible = "beagle,beaglev-starlight-jh7100", "starfive,jh7100"; + model = "BeagleV Starlight Beta"; + + aliases { + serial0 = &uart3; + serial1 = &uart0; + }; + + chosen { + environment { + compatible = "barebox,environment"; + device-path = &qpsi_env; + status = "disabled"; /* QSPI writes don't work yet */ + }; + }; +}; + +&nor_flash { + partitions { + compatible = "fixed-partitions"; + #address-cells = <1>; + #size-cells = <1>; + + partition@0 { + label = "secondboot"; + reg = <0x0 0x10000>; + }; + + partition@10000 { + label = "ddrinit"; + reg = <0x10000 0x10000>; + }; + + partition@20000 { + label = "sbi"; + reg = <0x20000 0x1e0000>; + }; + + qpsi_env: partition@200000 { + label = "environment"; + reg = <0x200000 0x1e00000>; + }; + }; +}; diff --git a/arch/riscv/dts/jh7100-beaglev-starlight.dtsi b/arch/riscv/dts/jh7100-beaglev-starlight.dtsi new file mode 100644 index 0000000000..13238f087f --- /dev/null +++ b/arch/riscv/dts/jh7100-beaglev-starlight.dtsi @@ -0,0 +1,369 @@ +// SPDX-License-Identifier: GPL-2.0 + +#include "jh7100.dtsi" +#include <dt-bindings/gpio/gpio.h> + +/ { + #address-cells = <2>; + #size-cells = <2>; + compatible = "beagle,beaglev-starlight-jh7100", "starfive,jh7100"; + model = "BeagleV Starlight Beta"; + + aliases { + serial0 = &uart3; + serial1 = &uart0; + }; + + chosen { + stdout-path = "serial0:115200"; + }; + + cpus { + timebase-frequency = <6250000>; + }; + + gpiopof: gpio-poweroff { + compatible = "gpio-poweroff"; + gpios = <&gpio 63 GPIO_ACTIVE_HIGH>; + }; + + leds { + compatible = "gpio-leds"; + + led-0 { + label = "beaglev:green:ack"; + gpios = <&gpio 43 GPIO_ACTIVE_HIGH>; + }; + }; + + memory@80000000 { + device_type = "memory"; + reg = <0x0 0x80000000 0x2 0x0>; + }; + + memory@3000000000 { + device_type = "memory"; + reg = <0x30 0x0 0x0 0x0>; + }; +}; + +&gmac { + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_rgmii>; + phy-mode = "rgmii-txid"; + nvmem-cell-names = "mac-address"; + nvmem-cells = <ðaddr>; +}; + +&gpio { + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_gpio>; +}; + +&sdio0 { + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_sdio0>; + bus-width = <4>; + cap-sd-highspeed; + broken-cd; + no-sdio; + status = "okay"; +}; + +&sdio1 { + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_sdio1>; + status = "okay"; +}; + +&uart0 { + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_uart0>; + status = "okay"; +}; + +&uart3 { + status = "okay"; +}; + +&usb3 { + dr_mode = "host"; + status = "okay"; +}; + +&i2c0 { + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_i2c0>; + status = "okay"; + + imx219@10 { + compatible = "imx219"; + reg = <0x10>; + reset-gpio = <&gpio 58 0>; + }; + + tps65086@5e { + compatible = "ti,tps65086"; + reg = <0x5e>; + gpio-controller; + #gpio-cells = <2>; + }; + + tda998x@70 { + compatible = "nxp,tda998x"; + reg = <0x70>; + }; +}; + +&i2c1 { + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_i2c1>; + status = "okay"; +}; + +&i2c2 { + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_i2c2>; + status = "okay"; + + seeed_plane_i2c@45 { + compatible = "seeed_panel"; + reg = <0x45>; + }; +}; + +&qspi { + nor_flash: nor-flash@0 { + compatible = "spi-flash"; + reg = <0>; + spi-max-frequency = <31250000>; + cdns,page-size = <256>; + cdns,block-size = <16>; + cdns,read-delay = <4>; + cdns,tshsl-ns = <1>; + cdns,tsd2d-ns = <1>; + cdns,tchsh-ns = <1>; + cdns,tslch-ns = <1>; + spi-tx-bus-width = <1>; + spi-rx-bus-width = <1>; + }; +}; + +&spi2 { + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_spi2>; + status = "okay"; + + spi_dev0: spi@0 { + compatible = "rohm,dh2228fv"; + spi-max-frequency = <10000000>; + reg = <0>; + status = "okay"; + }; +}; + +&qspi { + status = "okay"; +}; + +&spi2 { + status = "okay"; +}; + +&otp { + power-gpios = <&gpio 56 GPIO_ACTIVE_HIGH>; + #address-cells = <1>; + #size-cells = <1>; + + ethaddr: ethaddr@28 { + reg = <0x28 6>; + label = "mac-address"; + }; +}; + +&gpio { + pinctrl_uart0: uart0_pins { + pinctrl-single,pins = < + 0x358 0x2a /* GPIO40: uart0_pad_sin */ + 0x194 0x1 /* GPIO40: doen_HIGH */ + 0x198 0x7f /* GPIO41: dout_uart0_pad_sout */ + 0x19c 0x0 /* GPIO41: doen_LOW */ + 0x1a0 0x7e /* GPIO42: dout_uart0_pad_rtsn */ + 0x1a4 0x0 /* GPIO42: doen_LOW */ + 0x348 0x29 /* GPIO39: uart0_pad_ctsn */ + 0x18c 0x1 /* GPIO39: doen_HIGH */ + 0x16c 0x0 /* GPIO35: doen_LOW */ + 0x168 0x1 /* GPIO35: dout_HIGH */ + >; + }; + + pinctrl_i2c0: i2c0_pins { + pinctrl-single,pins = < + 0x240 0x0 /* GPIO62: dout_LOW */ + 0x238 0x0 /* GPIO61: dout_LOW */ + 0x244 0x80000008 /* GPIO62: doen_i2c0_pad_sck_oe + doen_reverse_(1) */ + 0x23c 0x80000009 /* GPIO61: doen_i2c0_pad_sda_oe + doen_reverse_(1) */ + 0x278 0x40 /* GPIO62: i2c0_pad_sck_in */ + 0x27c 0x3f /* GPIO61: i2c0_pad_sda_in */ + >; + }; + + pinctrl_i2c1: i2c1_pins { + pinctrl-single,pins = < + 0x1c8 0x0 /* GPIO47: dout_LOW */ + 0x1d0 0x0 /* GPIO48: dout_LOW */ + 0x1cc 0x8000000a /* GPIO47: doen_i2c1_pad_sck_oe + doen_reverse_(1) */ + 0x1d4 0x8000000b /* GPIO48: doen_i2c1_pad_sda_oe + doen_reverse_(1) */ + 0x280 0x31 /* GPIO47: i2c1_pad_sck_in */ + 0x284 0x32 /* GPIO48: i2c1_pad_sda_in */ + >; + }; + + pinctrl_i2c2: i2c2_pins { + pinctrl-single,pins = < + 0x230 0x0 /* GPIO60: dout_LOW */ + 0x228 0x0 /* GPIO59: dout_LOW */ + 0x234 0x8000000c /* GPIO60: doen_i2c2_pad_sck_oe + doen_reverse_(1) */ + 0x22c 0x8000000d /* GPIO59: doen_i2c2_pad_sda_oe + doen_reverse_(1) */ + 0x288 0x3e /* GPIO60: i2c2_pad_sck_in */ + 0x28c 0x3d /* GPIO59: i2c2_pad_sda_in */ + >; + }; + + pinctrl_spi2: spi2_pins { + pinctrl-single,pins = < + /* MISO */ + 0xa8 0x6f /* GPIO11: dout_spi2_pad_txd */ + 0xac 0x0 /* GPIO11: doen_LOW */ + /* MOSI */ + 0x320 0xe /* GPIO12: spi2_pad_rxd */ + 0xb4 0x1 /* GPIO12: doen_HIGH */ + /* SCLK */ + 0xe0 0x6c /* GPIO18: dout_spi2_pad_sck_out */ + 0xe4 0x0 /* GPIO18: doen_LOW */ + /* CS */ + 0xe8 0x6d /* GPIO19: dout_spi2_pad_ss_0_n */ + 0xec 0x0 /* GPIO19: doen_LOW */ + >; + + }; + + pinctrl_sdio0: sdio0_pins { + pinctrl-single,pins = < + 0x2b4 0x39 /* GPIO55: sdio0_pad_card_detect_n */ + 0x20c 0x1 /* GPIO55: doen_HIGH */ + 0x200 0x36 /* GPIO54: dout_sdio0_pad_cclk_out */ + 0x204 0x0 /* GPIO54: doen_LOW */ + 0x1fc 0x80000037 /* GPIO53: doen_sdio0_pad_ccmd_oe + doen_reverse_(1) */ + 0x1f8 0x38 /* GPIO53: dout_sdio0_pad_ccmd_out */ + 0x2bc 0x37 /* GPIO53: _sdio0_pad_ccmd_in */ + 0x1dc 0x80000039 /* GPIO49: doen_sdio0_pad_cdata_oe_bit0 + doen_reverse_(1) */ + 0x1d8 0x41 /* GPIO49: dout_sdio0_pad_cdata_out_bit0 */ + 0x2c0 0x33 /* GPIO49: sdio0_pad_cdata_in_bit0 */ + 0x1e4 0x8000003a /* GPIO50: doen_sdio0_pad_cdata_oe_bit1 + doen_reverse_(1) */ + 0x1e0 0x42 /* GPIO50: dout_sdio0_pad_cdata_out_bit1 */ + 0x2c4 0x34 /* GPIO50: sdio0_pad_cdata_in_bit1 */ + 0x1ec 0x8000003b /* GPIO51: doen_sdio0_pad_cdata_oe_bit2 + doen_reverse_(1) */ + 0x1e8 0x43 /* GPIO51: dout_sdio0_pad_cdata_out_bit2 */ + 0x2c8 0x35 /* GPIO51: sdio0_pad_cdata_in_bit2 */ + 0x1f4 0x8000003c /* GPIO52: doen_sdio0_pad_cdata_oe_bit3 + doen_reverse_(1) */ + 0x1f0 0x44 /* GPIO52: dout_sdio0_pad_cdata_out_bit3 */ + 0x2cc 0x36 /* GPIO52: sdio0_pad_cdata_in_bit3(52) */ + >; + }; + + pinctrl_sdio1: sdio1_pins { + pinctrl-single,pins = < + 0x158 0x4b /* GPIO33: dout_sdio1_pad_cclk_out */ + 0x15c 0x0 /* GPIO33: doen_LOW */ + 0x13c 0x8000004c /* GPIO29: doen_sdio1_pad_ccmd_oe + doen_reverse_(1) */ + 0x138 0x4d /* GPIO29: dout_sdio1_pad_ccmd_out */ + 0x2e8 0x1f /* GPIO29: sdio1_pad_ccmd_in */ + 0x174 0x8000004e /* GPIO36: doen_sdio1_pad_cdata_oe_bit0 + doen_reverse_(1) */ + 0x170 0x56 /* GPIO36: dout_sdio1_pad_cdata_out_bit0 */ + 0x2ec 0x26 /* GPIO36: sdio1_pad_cdata_in_bit0 */ + 0x144 0x8000004f /* GPIO30: doen_sdio1_pad_cdata_oe_bit1 + doen_reverse_(1) */ + 0x140 0x57 /* GPIO30: dout_sdio1_pad_cdata_out_bit1 */ + 0x2f0 0x20 /* GPIO30: sdio1_pad_cdata_in_bit1 */ + 0x164 0x80000050 /* GPIO34: doen_sdio1_pad_cdata_oe_bit2 + doen_reverse_(1) */ + 0x160 0x58 /* GPIO34: dout_sdio1_pad_cdata_out_bit2 */ + 0x2f4 0x24 /* GPIO34: sdio1_pad_cdata_in_bit2 */ + 0x14c 0x80000051 /* GPIO31: doen_sdio1_pad_cdata_oe_bit3 + doen_reverse_(1) */ + 0x148 0x59 /* GPIO31: dout_sdio1_pad_cdata_out_bit3 */ + 0x2f8 0x21 /* GPIO31: sdio1_pad_cdata_in_bit3 */ + >; + }; +}; + +&pinconf { + pinctrl_rgmii: rgmii_pins { + pinctrl-single,pins = < + 0x164 0xC30080 + 0x168 0x30080 + + 0x16c 0x30003 + 0x170 0x30003 + 0x174 0x30003 + 0x178 0x30003 + + 0x17c 0xC800003 + + 0x180 0x8000C0 + 0x184 0xC000C0 + 0x188 0xC000C0 + 0x18c 0xC000C0 + 0x190 0xC000C0 + 0x194 0xC000C0 + 0x198 0xC000C0 + >; + }; + + /* Force most pins to input. Taken from vendor's sys_funcshare_io_input_en */ + pinctrl_gpio: gpio_pins { + pinctrl-single,pins = < + 0x80 0xc000c0 /* gpio0 */ + 0x90 0xc000c0 /* gpio8-9 */ + 0x94 0xc000c0 /* gpio10-11 */ + 0x98 0xc000c0 /* gpio12 */ + 0xa0 0xc000c0 /* gpio16-17 */ + 0xa4 0xc000c0 /* gpio18-19 */ + 0xa8 0xc000c0 /* gpio20-21 */ + 0xac 0xc000c0 /* gpio22-23 */ + 0xb0 0xc000c0 /* gpio24-25 */ + 0xb4 0xc000c0 /* gpio26-27 */ + 0xb8 0xc000c0 /* gpio28-29 */ + 0xbc 0xc000c0 /* gpio30-31 */ + 0xc0 0xc000c0 /* gpio32-33 */ + 0xc4 0xc000c0 /* gpio34-35 */ + 0xcc 0xc000c0 /* gpio38-39 */ + 0xd0 0xc000c0 /* gpio40-41 */ + 0xd4 0xc000c0 /* gpio42-43 */ + 0xd8 0xc000c0 /* gpio44-45 */ + 0xdc 0xc000c0 /* gpio46-47 */ + 0xe0 0xc000c0 /* gpio48-49 */ + 0xe4 0xc000c0 /* gpio50-51 */ + 0xe8 0xc000c0 /* gpio52-53 */ + 0xec 0xc000c0 /* gpio54-55 */ + 0xf0 0xc000c0 /* gpio56-57 */ + 0xf4 0xc000c0 /* gpio58-59 */ + 0xf8 0xc000c0 /* gpio60-61 */ + 0xfc 0xc000c0 /* gpio62-63 */ + >; + }; +}; diff --git a/arch/riscv/dts/jh7100.dtsi b/arch/riscv/dts/jh7100.dtsi new file mode 100644 index 0000000000..e3990582af --- /dev/null +++ b/arch/riscv/dts/jh7100.dtsi @@ -0,0 +1,798 @@ +// SPDX-License-Identifier: GPL-2.0 + +#include <dt-bindings/reset-controller/starfive-jh7100.h> +#include <dt-bindings/clock/starfive-jh7100.h> + +/ { + #address-cells = <2>; + #size-cells = <2>; + compatible = "starfive,jh7100"; + + aliases { + spi0 = &qspi; + mmc0 = &sdio0; + mmc1 = &sdio1; + usb0 = &usb3; + }; + + chosen { + }; + + cpus { + #address-cells = <1>; + #size-cells = <0>; + cpu@0 { + compatible = "sifive,u74-mc", "riscv"; + d-cache-block-size = <64>; + d-cache-sets = <64>; + d-cache-size = <32768>; + d-tlb-sets = <1>; + d-tlb-size = <32>; + device_type = "cpu"; + i-cache-block-size = <64>; + i-cache-sets = <64>; + i-cache-size = <32768>; + i-tlb-sets = <1>; + i-tlb-size = <32>; + mmu-type = "riscv,sv39"; + next-level-cache = <&ccache>; + reg = <0>; + riscv,isa = "rv64imafdc"; + starfive,itim = <&itim0>; + status = "okay"; + tlb-split; + cpu0_intc: interrupt-controller { + #interrupt-cells = <1>; + compatible = "riscv,cpu-intc"; + interrupt-controller; + }; + }; + + cpu@1 { + compatible = "sifive,u74-mc", "riscv"; + d-cache-block-size = <64>; + d-cache-sets = <64>; + d-cache-size = <32768>; + d-tlb-sets = <1>; + d-tlb-size = <32>; + device_type = "cpu"; + i-cache-block-size = <64>; + i-cache-sets = <64>; + i-cache-size = <32768>; + i-tlb-sets = <1>; + i-tlb-size = <32>; + mmu-type = "riscv,sv39"; + next-level-cache = <&ccache>; + reg = <1>; + riscv,isa = "rv64imafdc"; + starfive,itim = <&itim1>; + status = "okay"; + tlb-split; + cpu1_intc: interrupt-controller { + #interrupt-cells = <1>; + compatible = "riscv,cpu-intc"; + interrupt-controller; + }; + }; + }; + + osc_sys: clock-osc-sys { + compatible = "fixed-clock"; + #clock-cells = <0>; + clock-frequency = <25000000>; + clock-output-names = "osc_sys"; + }; + + osc_aud: clock-osc-audio { + compatible = "fixed-clock"; + #clock-cells = <0>; + clock-frequency = <27000000>; + clock-output-names = "osc_aud"; + }; + + i2c0clk: i2c0clk { + #clock-cells = <0>; + compatible = "fixed-clock"; + clock-frequency = <49500000>; + clock-output-names = "i2c0clk"; + }; + + i2c2clk: i2c2clk { + #clock-cells = <0>; + compatible = "fixed-clock"; + clock-frequency = <49500000>; + clock-output-names = "i2c2clk"; + }; + + axiclk: axiclk { + #clock-cells = <0>; + compatible = "fixed-clock"; + clock-frequency = <500000000>; + clock-output-names = "axiclk"; + }; + + ahb0clk: ahb0clk { + #clock-cells = <0>; + compatible = "fixed-clock"; + clock-frequency = <250000000>; + }; + + apb1clk: apb1clk { + #clock-cells = <0>; + compatible = "fixed-clock"; + clock-frequency = <125000000>; + }; + + apb2clk: apb2clk { + #clock-cells = <0>; + compatible = "fixed-clock"; + clock-frequency = <125000000>; + }; + + jpuclk: jpuclk { + #clock-cells = <0>; + compatible = "fixed-clock"; + clock-frequency = <333333333>; + }; + + vpuclk: vpuclk { + #clock-cells = <0>; + compatible = "fixed-clock"; + clock-frequency = <400000000>; + }; + + qspi_clk: qspi-clk@0 { + #clock-cells = <0>; + compatible = "fixed-clock"; + clock-frequency = <50000000>; + }; + + uartclk: uartclk { + #clock-cells = <0>; + compatible = "fixed-clock"; + clock-frequency = <100000000>; + }; + + hs_uartclk: hs_uartclk { + #clock-cells = <0>; + compatible = "fixed-clock"; + clock-frequency = <74250000>; + }; + + spiclk: spiclk { + #clock-cells = <0>; + compatible = "fixed-clock"; + clock-frequency = <50000000>; + }; + + pwmclk: pwmclk { + #clock-cells = <0>; + compatible = "fixed-clock"; + clock-frequency = <125000000>; + }; + + reserved-memory { + #address-cells = <2>; + #size-cells = <2>; + ranges; + + linux,cma { + compatible = "shared-dma-pool"; + reusable; + size = <0x0 0x28000000>; + alignment = <0x0 0x1000>; + alloc-ranges = <0x0 0xa0000000 0x0 0x28000000>; + linux,cma-default; + }; + + jpu_reserved: framebuffer@c9000000 { + reg = <0x0 0xc9000000 0x0 0x4000000>; + }; + + nvdla_reserved:framebuffer@d0000000 { + reg = <0x0 0xd0000000 0x0 0x28000000>; + }; + + vin_reserved: framebuffer@f9000000 { + compatible = "shared-dma-pool"; + no-map; + reg = <0x0 0xf9000000 0x0 0x1000000>; + }; + + sffb_reserved: framebuffer@fb000000 { + compatible = "shared-dma-pool"; + no-map; + reg = <0x0 0xfb000000 0x0 0x2000000>; + }; + }; + + soc { + #address-cells = <2>; + #size-cells = <2>; + #clock-cells = <1>; + compatible = "simple-bus"; + ranges; + + intram0: sram@18000000 { + compatible = "mmio-sram"; + reg = <0x0 0x18000000 0x0 0x20000>; + }; + + intram1: sram@18080000 { + compatible = "mmio-sram"; + reg = <0x0 0x18080000 0x0 0x8000>; + }; + + ccache: cache-controller@2010000 { + cache-block-size = <64>; + cache-level = <2>; + cache-sets = <2048>; + cache-size = <2097152>; + cache-unified; + compatible = "sifive,fu540-c000-ccache", "starfive,ccache0", "cache"; + interrupt-parent = <&plic>; + interrupts = <128 131 129 130>; + /*next-level-cache = <&L40 &L36>;*/ + reg = <0x0 0x2010000 0x0 0x1000 0x0 0x8000000 0x0 0x2000000>; + reg-names = "control", "sideband"; + }; + + dtim: dtim@1000000 { + compatible = "starfive,dtim0"; + reg = <0x0 0x1000000 0x0 0x2000>; + reg-names = "mem"; + }; + + itim0: itim@1808000 { + compatible = "starfive,itim0"; + reg = <0x0 0x1808000 0x0 0x8000>; + reg-names = "mem"; + }; + + itim1: itim@1820000 { + compatible = "starfive,itim0"; + reg = <0x0 0x1820000 0x0 0x8000>; + reg-names = "mem"; + }; + + clint: clint@2000000 { + #interrupt-cells = <1>; + compatible = "riscv,clint0"; + interrupts-extended = <&cpu0_intc 3 &cpu0_intc 7 &cpu1_intc 3 &cpu1_intc 7>; + reg = <0x0 0x2000000 0x0 0x10000>; + reg-names = "control"; + }; + + plic: plic@c000000 { + #interrupt-cells = <1>; + compatible = "riscv,plic0"; + interrupt-controller; + interrupts-extended = <&cpu0_intc 11 &cpu0_intc 9 &cpu1_intc 11 &cpu1_intc 9>; + reg = <0x0 0xc000000 0x0 0x4000000>; + reg-names = "control"; + riscv,max-priority = <7>; + riscv,ndev = <127>; + }; + + sysmain: syscon@11850000 { + compatible = "syscon"; + reg = <0x0 0x11850000 0x0 0x4000>; + }; + + pinconf: pinctrl@11858000 { + compatible = "pinctrl-single"; + reg = <0x0 0x11858000 0x0 0x4000>; + #pinctrl-cells = <1>; + pinctrl-single,register-width = <32>; + pinctrl-single,function-mask = <0xffffffff>; + }; + + uart0: hs_serial@11870000 { + compatible = "snps,dw-apb-uart"; + interrupt-parent = <&plic>; + interrupts = <92>; + reg = <0x0 0x11870000 0x0 0x10000>; + reg-io-width = <4>; + reg-shift = <2>; + clocks = <&hs_uartclk>, <&apb1clk>; + clock-names = "baudclk", "apb_pclk"; + current-clock = <74250000>; + current-speed = <115200>; + status = "disabled"; + }; + + uart1: hs_serial@11880000 { + compatible = "snps,dw-apb-uart"; + interrupt-parent = <&plic>; + interrupts = <93>; + reg = <0x0 0x11880000 0x0 0x10000>; + reg-io-width = <4>; + reg-shift = <2>; + clocks = <&hs_uartclk>, <&apb1clk>; + clock-names = "baudclk", "apb_pclk"; + current-clock = <74250000>; + current-speed = <115200>; + status = "disabled"; + }; + + uart2: serial@12430000 { + compatible = "snps,dw-apb-uart"; + interrupt-parent = <&plic>; + interrupts = <72>; + reg = <0x0 0x12430000 0x0 0x10000>; + reg-io-width = <4>; + reg-shift = <2>; + clocks = <&uartclk>, <&apb2clk>; + clock-names = "baudclk", "apb_pclk"; + current-clock = <100000000>; + current-speed = <115200>; + status = "disabled"; + }; + + uart3: serial@12440000 { + compatible = "snps,dw-apb-uart", "starfive,uart0"; + interrupt-parent = <&plic>; + interrupts = <73>; + reg = <0x0 0x12440000 0x0 0x10000>; + reg-io-width = <4>; + reg-shift = <2>; + clocks = <&uartclk>, <&apb2clk>; + clock-names = "baudclk", "apb_pclk"; + current-clock = <100000000>; + current-speed = <115200>; + status = "disabled"; + }; + + nne50: nne@10800000 { + compatible = "starfive,nne50"; + reg = <0x0 0x10800000 0x0 0x10000>; + resets = <&rstgen RSTN_DLA_AXI>, + <&rstgen RSTN_DLANOC_AXI>, + <&rstgen RSTN_DLA_APB>, + <&rstgen RSTN_NNENOC_AXI>, + <&rstgen RSTN_DLASLV_AXI>; + + assigned-clocks = <&clkgen CLK_NNE_BUS>; + assigned-clocks-parents = <&clkgen CLK_CPU_AXI>; + status = "okay"; + }; + + dma2p: sgdma2p@100b0000 { + compatible = "starfive,axi-dma", "snps,axi-dma-1.01a"; + reg = <0x0 0x100b0000 0x0 0x10000>; + clocks = <&axiclk>, <&ahb0clk>; + clock-names = "core-clk", "cfgr-clk"; + resets = <&rstgen RSTN_DMA2PNOC_AXI>, <&rstgen RSTN_SGDMA2P_AXI>, <&rstgen RSTN_SGDMA2P_AHB>; + reset-names = "noc", "axi", "ahb"; + interrupt-parent = <&plic>; + interrupts = <2>; + dma-channels = <4>; + snps,dma-masters = <1>; + snps,data-width = <4>; + snps,block-size = <4096 4096 4096 4096>; + snps,priority = <0 1 2 3>; + snps,axi-max-burst-len = <128>; + status = "okay"; + }; + + dma1p: sgdma1p@10500000 { + compatible = "starfive,axi-dma", "snps,axi-dma-1.01a"; + reg = <0x0 0x10500000 0x0 0x10000>; + clocks = <&axiclk>, <&ahb0clk>; + clock-names = "core-clk", "cfgr-clk"; + resets = <&rstgen RSTN_SGDMA1P_AXI>; + interrupt-parent = <&plic>; + interrupts = <1>; + dma-channels = <16>; + snps,dma-masters = <1>; + snps,data-width = <3>; + snps,block-size = <4096 4096 4096 4096 4096 4096 4096 4096 4096 4096 4096 4096 4096 4096 4096 4096>; + snps,priority = <0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15>; + snps,axi-max-burst-len = <64>; + status = "okay"; + }; + + usb3: usb@104c0000 { + compatible = "cdns,usb3"; + reg = <0x0 0x104c0000 0x0 0x10000>, // memory area for HOST registers + <0x0 0x104d0000 0x0 0x10000>, // memory area for DEVICE registers + <0x0 0x104e0000 0x0 0x10000>; // memory area for OTG/DRD registers + reg-names = "otg", "xhci", "dev"; + interrupt-parent = <&plic>; + interrupts = <43>, <44>, <52>; + interrupt-names = "otg", + "host", + "peripheral"; + phy-names = "cdns3,usb3-phy", "cdns3,usb2-phy"; + maximum-speed = "super-speed"; + status = "disabled"; + }; + + gpio: gpio@11910000 { + compatible = "starfive,gpio0"; + interrupt-parent = <&plic>; + interrupts = <32>; + resets = <&rstgen RSTN_GPIO_APB>; + clocks = <&clkgen CLK_GPIO_APB>; + reg = <0x0 0x11910000 0x0 0x10000>; + reg-names = "control"; + interrupt-controller; + #gpio-cells = <2>; + #pinctrl-cells = <1>; + pinctrl-single,register-width = <32>; + pinctrl-single,function-mask = <0xffffffff>; + }; + + i2c0: i2c@118b0000 { + #address-cells = <1>; + #size-cells = <0>; + #clock-cells = <0>; + compatible = "snps,designware-i2c"; + reg = <0x0 0x118b0000 0x0 0x10000>; + interrupt-parent = <&plic>; + interrupts = <96>; + clocks = <&i2c0clk>; + clock-frequency = <100000>; + i2c-sda-hold-time-ns = <300>; + i2c-sda-falling-time-ns = <500>; + i2c-scl-falling-time-ns = <500>; + scl-gpio = <&gpio 62 0>; + sda-gpio = <&gpio 61 0>; + status = "disabled"; + }; + + i2c1: i2c@118c0000 { + #address-cells = <1>; + #size-cells = <0>; + #clock-cells = <0>; + compatible = "snps,designware-i2c"; + reg = <0x0 0x118c0000 0x0 0x10000>; + interrupt-parent = <&plic>; + interrupts = <97>; + clocks = <&i2c0clk>; + clock-frequency = <400000>; + i2c-sda-hold-time-ns = <300>; + i2c-sda-falling-time-ns = <100>; + i2c-scl-falling-time-ns = <100>; + scl-gpio = <&gpio 47 0>; + sda-gpio = <&gpio 48 0>; + status = "disabled"; + }; + + i2c2: i2c@12450000 { + #address-cells = <1>; + #size-cells = <0>; + #clock-cells = <0>; + compatible = "snps,designware-i2c"; + reg = <0x0 0x12450000 0x0 0x10000>; + interrupt-parent = <&plic>; + interrupts = <74>; + clocks = <&i2c2clk>; + clock-frequency = <100000>; + i2c-sda-hold-time-ns = <300>; + i2c-sda-falling-time-ns = <500>; + i2c-scl-falling-time-ns = <500>; + scl-gpio = <&gpio 60 0>; + sda-gpio = <&gpio 59 0>; + status = "disabled"; + }; + + trng: trng@118d0000 { + compatible = "starfive,vic-rng"; + reg = <0x0 0x118d0000 0x0 0x10000>; + interrupt-parent = <&plic>; + interrupts = <98>; + clocks = <&clkgen CLK_TRNG_APB>; + resets = <&rstgen RSTN_TRNG_APB>; + }; + + crypto: crypto@100d0000 { + compatible = "starfive,vic-sec"; + reg = <0x0 0x100d0000 0x0 0x20000>, + <0x0 0x11800234 0x0 0xc>; + reg-names = "secmem", "secclk"; + resets = <&rstgen RSTN_SEC_AHB>, <&rstgen RSTN_AES>, + <&rstgen RSTN_PKA>, <&rstgen RSTN_SHA>; + interrupt-parent = <&plic>; + interrupts = <31>; + clocks = <&osc_sys>; + }; + + /* gmac device configuration */ + stmmac_axi_setup: stmmac-axi-config { + snps,wr_osr_lmt = <0xf>; + snps,rd_osr_lmt = <0xf>; + snps,blen = <256 128 64 32 0 0 0>; + }; + + gmac: gmac@10020000 { + compatible = "starfive,stmmac"; + reg = <0x0 0x10020000 0x0 0x10000>; + interrupt-parent = <&plic>; + interrupts = <6 7>; + interrupt-names = "macirq", "eth_wake_irq"; + resets = <&rstgen RSTN_GMAC_AHB>; + reset-names = "stmmaceth"; + clocks = <&clkgen CLK_GMAC_AHB>, <&clkgen CLK_GMAC_PTP_REF>, + <&clkgen CLK_GMAC_GTX>; + clock-names = "stmmaceth", "ptp_ref", "tx"; + max-frame-size = <9000>; + snps,multicast-filter-bins = <256>; + snps,perfect-filter-entries = <128>; + rx-fifo-depth = <32768>; + tx-fifo-depth = <16384>; + snps,fixed-burst = <1>; + snps,no-pbl-x8 = <1>; + /*snps,force_sf_dma_mode;*/ + snps,force_thresh_dma_mode; + snps,axi-config = <&stmmac_axi_setup>; + starfive,sysmain = <&sysmain>; + }; + + nbdla: nvdla@11940000 { + compatible = "nvidia,nvdla_os_initial"; + interrupt-parent = <&plic>; + resets = <&rstgen RSTN_DLA_AXI>, + <&rstgen RSTN_DLANOC_AXI>, + <&rstgen RSTN_DLA_APB>, + <&rstgen RSTN_NNENOC_AXI>, + <&rstgen RSTN_DLASLV_AXI>; + interrupts = <22>; + memory-region = <&nvdla_reserved>; + reg = <0x0 0x11940000 0x0 0x40000>; + status = "okay"; + }; + + jpu: coadj12@11900000 { + compatible = "cm,codaj12-jpu-1"; + reg = <0x0 0x11900000 0x0 0x300>; + memory-region = <&jpu_reserved>; + interrupt-parent = <&plic>; + interrupts = <24>; + clocks = <&jpuclk>; + clock-names = "jpege"; + reg-names = "control"; + resets = <&rstgen RSTN_JPEG_AXI>, <&rstgen RSTN_JPEG_CCLK>, + <&rstgen RSTN_JPEG_APB>; + status = "okay"; + }; + + clkgen: clock-controller@11800000 { + compatible = "starfive,jh7100-clkgen"; + reg = <0x0 0x11800000 0x0 0x10000>; + clocks = <&osc_sys>, <&osc_aud>; + clock-names = "osc_sys", "osc_aud"; + #clock-cells = <1>; + }; + + vpu_dec: vpu_dec@118f0000 { + compatible = "cm,cm511-vpu"; + reg = <0 0x118f0000 0 0x10000>; + //memory-region = <&vpu_reserved>; + interrupt-parent = <&plic>; + interrupts = <23>; + clocks = <&vpuclk>; + clock-names = "vcodec"; + resets = <&rstgen RSTN_VDEC_AXI>, <&rstgen RSTN_VDECBRG_MAIN>, + <&rstgen RSTN_VDEC_BCLK>, <&rstgen RSTN_VDEC_CCLK>, + <&rstgen RSTN_VDEC_APB>; + status = "okay"; + }; + + vpu_enc: vpu_enc@118e0000 { + compatible = "cm,cm521-vpu"; + reg = <0x0 0x118e0000 0x0 0x4000>; + interrupt-parent = <&plic>; + interrupts = <26>; + clocks = <&vpuclk>; + clock-names = "vcodec"; + resets = <&rstgen RSTN_VENC_AXI>, <&rstgen RSTN_VENCBRG_MAIN>, + <&rstgen RSTN_VENC_BCLK>, <&rstgen RSTN_VENC_CCLK>, + <&rstgen RSTN_VENC_APB>; + reg-names = "control"; + }; + + wdt: watchdogm@12480000 { + compatible = "starfive,wdt"; + reg = <0x0 0x12480000 0x0 0x10000>; + clocks = <&clkgen CLK_WDTIMER_APB>,<&clkgen CLK_WDT_CORE>; + clock-names = "bus", "core"; + resets = <&rstgen RSTN_WDTIMER_APB>, <&rstgen RSTN_WDT>; + reset-names = "bus", "core"; + }; + + ptc: pwm@12490000 { + compatible = "starfive,pwm0"; + reg = <0x0 0x12490000 0x0 0x10000>; + reg-names = "control"; + sifive,approx-period = <100000000>; + clocks = <&pwmclk>; + #pwm-cells = <3>; + sifive,npwm = <8>; + + }; + + rstgen: reset-controller@11840000 { + compatible = "starfive,jh7100-rstgen"; + reg = <0x0 0x11840000 0x0 0x10000>; + #reset-cells = <1>; + }; + + spi2ahb { + #address-cells = <2>; + #size-cells = <2>; + ranges; + compatible = "starfive,spi2ahb"; + resets = <&rstgen RSTN_SPI2AHB_AHB>, <&rstgen RSTN_SPI2AHB_CORE>; + + qspi: spi@11860000 { + compatible = "cadence,qspi", "cdns,qspi-nor"; + #address-cells = <1>; + #size-cells = <0>; + reg = <0x0 0x11860000 0x0 0x10000 0x0 0x20000000 0x0 0x20000000>; + interrupts = <3>; + interrupt-parent = <&plic>; + clocks = <&qspi_clk>; + cdns,fifo-depth = <256>; + cdns,fifo-width = <4>; + cdns,trigger-address = <0x00000000>; + status = "disabled"; + spi-max-frequency = <250000000>; + }; + + spi2: spi@12410000 { + compatible = "snps,dw-apb-ssi"; + #address-cells = <1>; + #size-cells = <0>; + interrupt-parent = <&plic>; + interrupts = <70>; + reg = <0x0 0x12410000 0x0 0x10000>; + clocks = <&spiclk>; + status = "disabled"; + /* + num-cs = <1>; + cs-gpios = <&gpio 0 0>; + */ + }; + }; + + xrp@f0000000 { + compatible = "cdns,xrp"; + reg = <0x0 0xf0000000 0x0 0x01ffffff + 0x10 0x72000000 0x0 0x00001000 + 0x10 0x72001000 0x0 0x00fff000 + 0x0 0x124b0000 0x0 0x00010000>; + clocks = <&osc_sys>; + interrupt-parent = <&plic>; + firmware-name = "vp6_elf"; + resets = <&rstgen RSTN_VP6INTC_APB>; + dsp-irq = <19 20>; + dsp-irq-src = <0x20 0x21>; + intc-irq-mode = <1>; + intc-irq = <0 1>; + interrupts = <27 28>; + #address-cells = <1>; + #size-cells = <1>; + ranges = <0x40000000 0x0 0x40000000 0x01000000 + 0xb0000000 0x10 0x70000000 0x3000000>; + dsp@0 { + }; + }; + + sdio0: sdio0@10000000 { + compatible = "starfive,jh7100-dw-mshc", "snps,dw-mshc"; + reg = <0x0 0x10000000 0x0 0x10000>; + interrupts = <4>; + interrupt-parent = <&plic>; + clocks = <&clkgen CLK_SDIO0_AHB>, <&clkgen CLK_SDIO0_CCLKINT>; + clock-names = "biu", "ciu"; + resets = <&rstgen RSTN_SDIO0_AHB>; + reset-names = "reset"; + clock-frequency = <100000000>; + max-frequency = <10000000>; + fifo-depth = <32>; + card-detect-delay = <300>; + fifo-watermark-aligned; + data-addr = <0>; + post-power-on-delay-ms = <200>; + status = "disabled"; + }; + + sdio1: sdio1@10010000 { + compatible = "starfive,jh7100-dw-mshc", "snps,dw-mshc"; + reg = <0x0 0x10010000 0x0 0x10000>; + interrupts = <5>; + interrupt-parent = <&plic>; + clocks = <&clkgen CLK_SDIO1_AHB>, <&clkgen CLK_SDIO1_CCLKINT>; + clock-names = "biu", "ciu"; + resets = <&rstgen RSTN_SDIO1_AHB>; + reset-names = "reset"; + clock-frequency = <100000000>; + max-frequency = <10000000>; + fifo-depth = <32>; + card-detect-delay = <300>; + fifo-watermark-aligned; + data-addr = <0>; + bus-width = <4>; + cap-sd-highspeed; + cap-sdio-irq; + cap-mmc-hw-reset; + enable-sdio-wakeup; + keep-power-in-suspend; + cap-mmc-highspeed; + post-power-on-delay-ms = <200>; + status = "disabled"; + }; + + sfivefb: sfivefb@12000000 { + compatible = "starfive,vpp-lcdc"; + interrupt-parent = <&plic>; + interrupts = <101>, <103>; + interrupt-names = "lcdc_irq", "vpp1_irq"; + reg = <0x0 0x12000000 0x0 0x10000>, + <0x0 0x12100000 0x0 0x10000>, + <0x0 0x12040000 0x0 0x10000>, + <0x0 0x12080000 0x0 0x10000>, + <0x0 0x120c0000 0x0 0x10000>, + <0x0 0x12240000 0x0 0x10000>, + <0x0 0x12250000 0x0 0x10000>, + <0x0 0x12260000 0x0 0x10000>; + reg-names = "lcdc", "dsitx", "vpp0", "vpp1", "vpp2", "clk", "rst", "sys"; + memory-region = <&sffb_reserved>; + clocks = <&uartclk>, <&apb2clk>; + clock-names = "baudclk", "apb_pclk"; + status = "okay"; + ddr-format = <4>;/* LCDC win_format WIN_FMT_RGB565 */ + }; + + vin_sysctl: vin_sysctl@19800000 { + compatible = "starfive,stf-vin"; + reg = <0x0 0x19800000 0x0 0x10000>, + <0x0 0x19810000 0x0 0x10000>, + <0x0 0x19820000 0x0 0x10000>, + <0x0 0x19830000 0x0 0x10000>, + <0x0 0x19840000 0x0 0x10000>, + <0x0 0x19870000 0x0 0x30000>, + <0x0 0x198a0000 0x0 0x30000>, + <0x0 0x11800000 0x0 0x10000>, + <0x0 0x11840000 0x0 0x10000>, + <0x0 0x11858000 0x0 0x10000>; + reg-names = "mipi0", "vclk", "vrst", "mipi1", "sctrl", + "isp0", "isp1", "tclk", "trst", "iopad"; + interrupt-parent = <&plic>; + interrupts = <119 109>; + memory-region = <&vin_reserved>; + /*defaule config for imx219 vin&isp*/ + format = <3>; /* SRC_CSI2RX_VIN_ISP */ + frame-width = <800>; + frame-height =<480>; + isp0_enable; + csi-lane = <2>; + csi-dlane-swaps = /bits/ 8 <1>,/bits/ 8 <2>,/bits/ 8 <3>,/bits/ 8 <4>; + csi-dlane-pn-swaps = /bits/ 8 <0>,/bits/ 8 <0>,/bits/ 8 <0>,/bits/ 8 <0>; + csi-clane-swap = /bits/ 8 <0>; + csi-clane-pn-swap = /bits/ 8 <0>; + csi-mipiID = <0>; + csi-width = <1920>; + csi-height = <1080>; + csi-dt = <0x2b>; + }; + + sfc_tmp: tmpsensor@124a0000 { + compatible = "sfc,tempsensor"; + reg = <0x0 0x124a0000 0x0 0x1000>; + interrupt-parent = <&plic>; + interrupts = <122>; + resets = <&rstgen RSTN_TEMP_APB>, <&rstgen RSTN_TEMP_SENSE>; + status = "okay"; + }; + + otp: otp@11810000 { + compatible = "starfive,fu740-otp"; + reg = <0x0 0x11810000 0x0 0x10000>; + fuse-count = <0x200>; + resets = <&rstgen RSTN_OTP_APB>; + clocks = <&clkgen CLK_OTP_APB>; + }; + }; +}; diff --git a/arch/riscv/include/asm/asm-offsets.h b/arch/riscv/include/asm/asm-offsets.h new file mode 100644 index 0000000000..d370ee36a1 --- /dev/null +++ b/arch/riscv/include/asm/asm-offsets.h @@ -0,0 +1 @@ +#include <generated/asm-offsets.h> diff --git a/arch/riscv/include/asm/barebox-riscv.h b/arch/riscv/include/asm/barebox-riscv.h index bb1d15308b..abb3202427 100644 --- a/arch/riscv/include/asm/barebox-riscv.h +++ b/arch/riscv/include/asm/barebox-riscv.h @@ -19,14 +19,26 @@ #include <linux/compiler.h> #include <asm/sections.h> #include <asm/barebox-riscv-head.h> +#include <asm/system.h> unsigned long get_runtime_offset(void); void setup_c(void); void relocate_to_current_adr(void); void relocate_to_adr(unsigned long target); + +void sync_caches_for_execution(void); + void __noreturn __naked barebox_riscv_entry(unsigned long membase, unsigned long memsize, - void *boarddata); + void *boarddata, unsigned int flags); + +#define barebox_riscv_machine_entry(membase, memsize, boarddata) \ + barebox_riscv_entry(membase, memsize, boarddata, RISCV_M_MODE) + +#define barebox_riscv_supervisor_entry(membase, memsize, hartid, boarddata) do { \ + __asm__ volatile("mv tp, %0\n" : : "r"(hartid)); \ + barebox_riscv_entry(membase, memsize, boarddata, RISCV_S_MODE); \ +} while (0) unsigned long riscv_mem_ramoops_get(void); unsigned long riscv_mem_endmem_get(void); diff --git a/arch/riscv/include/asm/barrier.h b/arch/riscv/include/asm/barrier.h new file mode 100644 index 0000000000..eff529307a --- /dev/null +++ b/arch/riscv/include/asm/barrier.h @@ -0,0 +1,27 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * Based on arch/arm/include/asm/barrier.h + * + * Copyright (C) 2012 ARM Ltd. + * Copyright (C) 2013 Regents of the University of California + * Copyright (C) 2017 SiFive + */ + +#ifndef _ASM_RISCV_BARRIER_H +#define _ASM_RISCV_BARRIER_H + +#ifndef __ASSEMBLY__ + +#define nop() __asm__ __volatile__ ("nop") + +#define RISCV_FENCE(p, s) \ + __asm__ __volatile__ ("fence " #p "," #s : : : "memory") + +/* These barriers need to enforce ordering on both devices or memory. */ +#define mb() RISCV_FENCE(iorw,iorw) +#define rmb() RISCV_FENCE(ir,ir) +#define wmb() RISCV_FENCE(ow,ow) + +#endif /* __ASSEMBLY__ */ + +#endif /* _ASM_RISCV_BARRIER_H */ diff --git a/arch/riscv/include/asm/cacheflush.h b/arch/riscv/include/asm/cacheflush.h new file mode 100644 index 0000000000..9ff25740c6 --- /dev/null +++ b/arch/riscv/include/asm/cacheflush.h @@ -0,0 +1,16 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * Copyright (C) 2015 Regents of the University of California + */ + +#ifndef _ASM_RISCV_CACHEFLUSH_H +#define _ASM_RISCV_CACHEFLUSH_H + +static inline void local_flush_icache_all(void) +{ +#ifdef HAS_CACHE + asm volatile ("fence.i" ::: "memory"); +#endif +} + +#endif /* _ASM_RISCV_CACHEFLUSH_H */ diff --git a/arch/riscv/include/asm/debug_ll.h b/arch/riscv/include/asm/debug_ll.h index 6904460af9..b4caa0597a 100644 --- a/arch/riscv/include/asm/debug_ll.h +++ b/arch/riscv/include/asm/debug_ll.h @@ -12,13 +12,19 @@ #include <linux/kconfig.h> -#ifdef CONFIG_DEBUG_ERIZO +#ifdef CONFIG_DEBUG_LL_NS16550 +#if defined CONFIG_DEBUG_ERIZO #define DEBUG_LL_UART_ADDR 0x90000000 +#define DEBUG_LL_UART_CLK (24000000 / 16) +#elif defined CONFIG_DEBUG_STARFIVE +#define DEBUG_LL_UART_ADDR 0x12440000 +#define DEBUG_LL_UART_CLK (100000000 / 16) +#endif + #define DEBUG_LL_UART_SHIFT 2 #define DEBUG_LL_UART_IOSIZE32 -#define DEBUG_LL_UART_CLK (24000000 / 16) #define DEBUG_LL_UART_BPS CONFIG_BAUDRATE #define DEBUG_LL_UART_DIVISOR (DEBUG_LL_UART_CLK / DEBUG_LL_UART_BPS) diff --git a/arch/riscv/include/asm/dma.h b/arch/riscv/include/asm/dma.h index 4204653984..56bcf06cc4 100644 --- a/arch/riscv/include/asm/dma.h +++ b/arch/riscv/include/asm/dma.h @@ -1,44 +1,22 @@ /* SPDX-License-Identifier: GPL-2.0 */ -#ifndef _ASM_DMA_MAPPING_H -#define _ASM_DMA_MAPPING_H +#ifndef _RISCV_ASM_DMA_H +#define _RISCV_ASM_DMA_H -#include <common.h> -#include <xfuncs.h> -#include <linux/build_bug.h> -#include <malloc.h> +#include <linux/types.h> -#ifdef CONFIG_MMU -#error DMA stubs need be replaced when using MMU and caches -#endif +struct dma_ops { + void *(*alloc_coherent)(size_t size, dma_addr_t *dma_handle); + void (*free_coherent)(void *vaddr, dma_addr_t dma_handle, size_t size); -static inline void *dma_alloc_coherent(size_t size, dma_addr_t *dma_handle) -{ - void *ret; + void (*flush_range)(dma_addr_t start, dma_addr_t end); + void (*inv_range)(dma_addr_t start, dma_addr_t end); +}; - ret = xmemalign(PAGE_SIZE, size); +/* Override for SoCs with cache-incoherent DMA masters */ +void dma_set_ops(const struct dma_ops *ops); - memset(ret, 0, size); +#define DMA_ALIGNMENT 64 - if (dma_handle) - *dma_handle = (dma_addr_t)ret; - - return ret; -} - -static inline void dma_free_coherent(void *vaddr, dma_addr_t dma_handle, - size_t size) -{ - free(vaddr); -} - -static inline void dma_sync_single_for_cpu(dma_addr_t address, size_t size, - enum dma_data_direction dir) -{ -} - -static inline void dma_sync_single_for_device(dma_addr_t address, size_t size, - enum dma_data_direction dir) -{ -} +#include <dma.h> #endif /* _ASM_DMA_MAPPING_H */ diff --git a/arch/riscv/include/asm/io.h b/arch/riscv/include/asm/io.h index 3cdea7fcac..795e670e3b 100644 --- a/arch/riscv/include/asm/io.h +++ b/arch/riscv/include/asm/io.h @@ -5,4 +5,14 @@ #include <asm-generic/io.h> +static inline void *phys_to_virt(unsigned long phys) +{ + return (void *)phys; +} + +static inline unsigned long virt_to_phys(volatile void *mem) +{ + return (unsigned long)mem; +} + #endif /* __ASM_RISCV_IO_H */ diff --git a/arch/riscv/include/asm/irq.h b/arch/riscv/include/asm/irq.h new file mode 100644 index 0000000000..fde7589baa --- /dev/null +++ b/arch/riscv/include/asm/irq.h @@ -0,0 +1,107 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +#ifndef RISCV_ASM_IRQ_H__ +#define RISCV_ASM_IRQ_H__ + +#include <asm/csr.h> +#include <asm/system.h> +#include <asm/asm.h> +#include <asm/asm-offsets.h> +#include <asm/ptrace.h> + +#ifndef __ASSEMBLY__ +#include <asm/barebox-riscv.h> +void strap_entry(void); +void mtrap_entry(void); +unsigned long handle_trap(struct pt_regs *regs); + +static inline void irq_init_vector(enum riscv_mode mode) +{ + switch (mode) { +#ifdef CONFIG_RISCV_EXCEPTIONS + case RISCV_S_MODE: + asm volatile ("csrw stvec, %0; csrw sie, zero" : : + "r"(strap_entry + get_runtime_offset())); + break; + case RISCV_M_MODE: + asm volatile ("csrw mtvec, %0; csrw mie, zero" : : + "r"(mtrap_entry + get_runtime_offset())); + break; +#endif + default: + break; + } +} + +#else + +.macro pt_regs_push ptr + REG_S ra, PT_RA(\ptr) /* x1 */ + REG_S sp, PT_SP(\ptr) /* x2 */ + REG_S gp, PT_GP(\ptr) /* x3 */ + REG_S tp, PT_TP(\ptr) /* x4 */ + REG_S t0, PT_T0(\ptr) /* x5 */ + REG_S t1, PT_T1(\ptr) /* x6 */ + REG_S t2, PT_T2(\ptr) /* x7 */ + REG_S s0, PT_S0(\ptr) /* x8/fp */ + REG_S s1, PT_S1(\ptr) /* x9 */ + REG_S a0, PT_A0(\ptr) /* x10 */ + REG_S a1, PT_A1(\ptr) /* x11 */ + REG_S a2, PT_A2(\ptr) /* x12 */ + REG_S a3, PT_A3(\ptr) /* x13 */ + REG_S a4, PT_A4(\ptr) /* x14 */ + REG_S a5, PT_A5(\ptr) /* x15 */ + REG_S a6, PT_A6(\ptr) /* x16 */ + REG_S a7, PT_A7(\ptr) /* x17 */ + REG_S s2, PT_S2(\ptr) /* x18 */ + REG_S s3, PT_S3(\ptr) /* x19 */ + REG_S s4, PT_S4(\ptr) /* x20 */ + REG_S s5, PT_S5(\ptr) /* x21 */ + REG_S s6, PT_S6(\ptr) /* x22 */ + REG_S s7, PT_S7(\ptr) /* x23 */ + REG_S s8, PT_S8(\ptr) /* x24 */ + REG_S s9, PT_S9(\ptr) /* x25 */ + REG_S s10, PT_S10(\ptr) /* x26 */ + REG_S s11, PT_S11(\ptr) /* x27 */ + REG_S t3, PT_T3(\ptr) /* x28 */ + REG_S t4, PT_T4(\ptr) /* x29 */ + REG_S t5, PT_T5(\ptr) /* x30 */ + REG_S t6, PT_T6(\ptr) /* x31 */ +.endm + +.macro pt_regs_pop ptr + REG_L ra, PT_RA(\ptr) /* x1 */ + REG_L sp, PT_SP(\ptr) /* x2 */ + REG_L gp, PT_GP(\ptr) /* x3 */ + REG_L tp, PT_TP(\ptr) /* x4 */ + REG_L t0, PT_T0(\ptr) /* x5 */ + REG_L t1, PT_T1(\ptr) /* x6 */ + REG_L t2, PT_T2(\ptr) /* x7 */ + REG_L s0, PT_S0(\ptr) /* x8/fp */ + REG_L s1, PT_S1(\ptr) /* x9 */ + REG_L a0, PT_A0(\ptr) /* x10 */ + REG_L a1, PT_A1(\ptr) /* x11 */ + REG_L a2, PT_A2(\ptr) /* x12 */ + REG_L a3, PT_A3(\ptr) /* x13 */ + REG_L a4, PT_A4(\ptr) /* x14 */ + REG_L a5, PT_A5(\ptr) /* x15 */ + REG_L a6, PT_A6(\ptr) /* x16 */ + REG_L a7, PT_A7(\ptr) /* x17 */ + REG_L s2, PT_S2(\ptr) /* x18 */ + REG_L s3, PT_S3(\ptr) /* x19 */ + REG_L s4, PT_S4(\ptr) /* x20 */ + REG_L s5, PT_S5(\ptr) /* x21 */ + REG_L s6, PT_S6(\ptr) /* x22 */ + REG_L s7, PT_S7(\ptr) /* x23 */ + REG_L s8, PT_S8(\ptr) /* x24 */ + REG_L s9, PT_S9(\ptr) /* x25 */ + REG_L s10, PT_S10(\ptr) /* x26 */ + REG_L s11, PT_S11(\ptr) /* x27 */ + REG_L t3, PT_T3(\ptr) /* x28 */ + REG_L t4, PT_T4(\ptr) /* x29 */ + REG_L t5, PT_T5(\ptr) /* x30 */ + REG_L t6, PT_T6(\ptr) /* x31 */ +.endm + +#endif + +#endif diff --git a/arch/riscv/include/asm/ptrace.h b/arch/riscv/include/asm/ptrace.h new file mode 100644 index 0000000000..b5e792f666 --- /dev/null +++ b/arch/riscv/include/asm/ptrace.h @@ -0,0 +1,143 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * Copyright (C) 2012 Regents of the University of California + */ + +#ifndef _ASM_RISCV_PTRACE_H +#define _ASM_RISCV_PTRACE_H + +#include <asm/csr.h> +#include <linux/compiler.h> + +#ifndef __ASSEMBLY__ + +struct pt_regs { + unsigned long epc; + unsigned long ra; + unsigned long sp; + unsigned long gp; + unsigned long tp; + unsigned long t0; + unsigned long t1; + unsigned long t2; + unsigned long s0; + unsigned long s1; + unsigned long a0; + unsigned long a1; + unsigned long a2; + unsigned long a3; + unsigned long a4; + unsigned long a5; + unsigned long a6; + unsigned long a7; + unsigned long s2; + unsigned long s3; + unsigned long s4; + unsigned long s5; + unsigned long s6; + unsigned long s7; + unsigned long s8; + unsigned long s9; + unsigned long s10; + unsigned long s11; + unsigned long t3; + unsigned long t4; + unsigned long t5; + unsigned long t6; + /* Supervisor/Machine CSRs */ + unsigned long status; + unsigned long badaddr; + unsigned long cause; +}; + +#ifdef CONFIG_64BIT +#define REG_FMT "%016lx" +#else +#define REG_FMT "%08lx" +#endif + +#define user_mode(regs) (((regs)->status & SR_PP) == 0) + +#define MAX_REG_OFFSET offsetof(struct pt_regs, cause) + +/* Helpers for working with the instruction pointer */ +static inline unsigned long instruction_pointer(struct pt_regs *regs) +{ + return regs->epc; +} +static inline void instruction_pointer_set(struct pt_regs *regs, + unsigned long val) +{ + regs->epc = val; +} + +#define profile_pc(regs) instruction_pointer(regs) + +/* Helpers for working with the user stack pointer */ +static inline unsigned long user_stack_pointer(struct pt_regs *regs) +{ + return regs->sp; +} +static inline void user_stack_pointer_set(struct pt_regs *regs, + unsigned long val) +{ + regs->sp = val; +} + +/* Valid only for Kernel mode traps. */ +static inline unsigned long kernel_stack_pointer(struct pt_regs *regs) +{ + return regs->sp; +} + +/* Helpers for working with the frame pointer */ +static inline unsigned long frame_pointer(struct pt_regs *regs) +{ + return regs->s0; +} +static inline void frame_pointer_set(struct pt_regs *regs, + unsigned long val) +{ + regs->s0 = val; +} + +static inline unsigned long regs_return_value(struct pt_regs *regs) +{ + return regs->a0; +} + +static inline void regs_set_return_value(struct pt_regs *regs, + unsigned long val) +{ + regs->a0 = val; +} + +extern int regs_query_register_offset(const char *name); +extern unsigned long regs_get_kernel_stack_nth(struct pt_regs *regs, + unsigned int n); + +void prepare_ftrace_return(unsigned long *parent, unsigned long self_addr, + unsigned long frame_pointer); +int do_syscall_trace_enter(struct pt_regs *regs); +void do_syscall_trace_exit(struct pt_regs *regs); + +/** + * regs_get_register() - get register value from its offset + * @regs: pt_regs from which register value is gotten + * @offset: offset of the register. + * + * regs_get_register returns the value of a register whose offset from @regs. + * The @offset is the offset of the register in struct pt_regs. + * If @offset is bigger than MAX_REG_OFFSET, this returns 0. + */ +static inline unsigned long regs_get_register(struct pt_regs *regs, + unsigned int offset) +{ + if (unlikely(offset > MAX_REG_OFFSET)) + return 0; + + return *(unsigned long *)((unsigned long)regs + offset); +} +#endif /* __ASSEMBLY__ */ + +#endif /* _ASM_RISCV_PTRACE_H */ diff --git a/arch/riscv/include/asm/riscv_nmon.h b/arch/riscv/include/asm/riscv_nmon.h index caf213cdd8..8a44e216d7 100644 --- a/arch/riscv/include/asm/riscv_nmon.h +++ b/arch/riscv/include/asm/riscv_nmon.h @@ -16,13 +16,26 @@ #ifndef __ASM_RISCV_NMON_H #define __ASM_RISCV_NMON_H +#include <linux/kconfig.h> + #define CODE_ESC 0x1b -.macro nmon_outs msg +#ifndef __ASSEMBLY__ - la a1, \msg +extern void __barebox_nmon_entry(void); - jal _nmon_outs +static inline void barebox_nmon_entry(void) +{ + if (IS_ENABLED(CONFIG_NMON)) + __barebox_nmon_entry(); +} + +#else + +.macro nmon_outs msg + + lla a1, \msg + jal a2, _nmon_outs .endm @@ -73,7 +86,7 @@ nmon_main: li a0, 'q' bne s0, a0, 3f - jal _nmon_outc_a0 + jal a2, _nmon_outc_a0 j nmon_exit @@ -90,12 +103,12 @@ nmon_main: j nmon_main_help nmon_cmd_d: - jal _nmon_outc_a0 + jal a2, _nmon_outc_a0 li a0, ' ' - jal _nmon_outc_a0 + jal a2, _nmon_outc_a0 - jal _nmon_gethexw + jal a2, _nmon_gethexw nmon_outs msg_nl @@ -105,28 +118,28 @@ nmon_cmd_d: j nmon_main nmon_cmd_w: - jal _nmon_outc_a0 + jal a2, _nmon_outc_a0 li a0, ' ' - jal _nmon_outc_a0 + jal a2, _nmon_outc_a0 - jal _nmon_gethexw + jal a2, _nmon_gethexw move s2, s0 li a0, ' ' - jal _nmon_outc_a0 - jal _nmon_gethexw + jal a2, _nmon_outc_a0 + jal a2, _nmon_gethexw sw s0, 0(s2) j nmon_main nmon_cmd_g: - jal _nmon_outc_a0 + jal a2, _nmon_outc_a0 li a0, ' ' - jal _nmon_outc_a0 + jal a2, _nmon_outc_a0 - jal _nmon_gethexw + jal a2, _nmon_gethexw move s2, s0 nmon_outs msg_nl @@ -136,7 +149,7 @@ nmon_cmd_g: _nmon_outc_a0: debug_ll_outc_a0 - jr ra + jr a2 _nmon_outs: @@ -202,7 +215,7 @@ _get_hex_digit: move s0, t2 _nmon_jr_ra_exit: - jr ra + jr a2 msg_prompt: .asciz "\r\nnmon> " @@ -231,4 +244,6 @@ nmon_exit: .endm +#endif /* __ASSEMBLY__ */ + #endif /* __ASM_RISCV_NMON_H */ diff --git a/arch/riscv/include/asm/sbi.h b/arch/riscv/include/asm/sbi.h index ab1fc9a128..eb4018de38 100644 --- a/arch/riscv/include/asm/sbi.h +++ b/arch/riscv/include/asm/sbi.h @@ -9,9 +9,7 @@ #include <linux/types.h> -#ifdef CONFIG_RISCV_SBI enum sbi_ext_id { -#ifdef CONFIG_RISCV_SBI_V01 SBI_EXT_0_1_SET_TIMER = 0x0, SBI_EXT_0_1_CONSOLE_PUTCHAR = 0x1, SBI_EXT_0_1_CONSOLE_GETCHAR = 0x2, @@ -21,7 +19,7 @@ enum sbi_ext_id { SBI_EXT_0_1_REMOTE_SFENCE_VMA = 0x6, SBI_EXT_0_1_REMOTE_SFENCE_VMA_ASID = 0x7, SBI_EXT_0_1_SHUTDOWN = 0x8, -#endif + SBI_EXT_BASE = 0x10, SBI_EXT_TIME = 0x54494D45, SBI_EXT_IPI = 0x735049, @@ -167,7 +165,5 @@ static inline unsigned long sbi_minor_version(void) } int sbi_err_map_linux_errno(int err); -#else /* CONFIG_RISCV_SBI */ -static inline int sbi_remote_fence_i(const unsigned long *hart_mask) { return -1; } -#endif /* CONFIG_RISCV_SBI */ + #endif /* _ASM_RISCV_SBI_H */ diff --git a/arch/riscv/include/asm/system.h b/arch/riscv/include/asm/system.h new file mode 100644 index 0000000000..adf856f9e9 --- /dev/null +++ b/arch/riscv/include/asm/system.h @@ -0,0 +1,61 @@ +/* SPDX-License-Identifier: GPL-2.0 */ + +#ifndef __ASM_SYSTEM_H_ +#define __ASM_SYSTEM_H_ + +#ifndef __ASSEMBLY__ + +#define RISCV_MODE_MASK 0x3 +enum riscv_mode { + RISCV_U_MODE = 0, + RISCV_S_MODE = 1, + RISCV_HS_MODE = 2, + RISCV_M_MODE = 3, +}; + +static inline enum riscv_mode __riscv_mode(u32 flags) +{ + /* allow non-LTO builds to discard code for unused modes */ + if (!IS_ENABLED(CONFIG_RISCV_MULTI_MODE)) { + if (IS_ENABLED(CONFIG_RISCV_M_MODE)) + return RISCV_M_MODE; + if (IS_ENABLED(CONFIG_RISCV_S_MODE)) + return RISCV_S_MODE; + } + + return flags & RISCV_MODE_MASK; +} + +static inline long __riscv_hartid(u32 flags) +{ + long hartid = -1; + + switch (__riscv_mode(flags)) { + case RISCV_S_MODE: + __asm__ volatile("mv %0, tp\n" : "=r"(hartid) :); + break; + default: + /* unimplemented */ + break; + } + + return hartid; +} + +#ifndef __PBL__ +extern unsigned barebox_riscv_pbl_flags; + +static inline enum riscv_mode riscv_mode(void) +{ + return __riscv_mode(barebox_riscv_pbl_flags); +} + +static inline long riscv_hartid(void) +{ + return __riscv_hartid(barebox_riscv_pbl_flags); +} +#endif + +#endif + +#endif diff --git a/arch/riscv/include/asm/unwind.h b/arch/riscv/include/asm/unwind.h new file mode 100644 index 0000000000..9e5c8b5420 --- /dev/null +++ b/arch/riscv/include/asm/unwind.h @@ -0,0 +1,9 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +#ifndef RISCV_ASM_UNWIND_H__ +#define RISCV_ASM_UNWIND_H__ + +struct pt_regs; + +void unwind_backtrace(struct pt_regs *regs); + +#endif diff --git a/arch/riscv/lib/asm-offsets.c b/arch/riscv/lib/asm-offsets.c index 22f382b71e..4b869690f1 100644 --- a/arch/riscv/lib/asm-offsets.c +++ b/arch/riscv/lib/asm-offsets.c @@ -5,8 +5,54 @@ */ #include <linux/kbuild.h> +#include <linux/kernel.h> +#include <asm/ptrace.h> + +#define STACK_ALIGN 16 int main(void) { + DEFINE(PT_SIZE, sizeof(struct pt_regs)); + OFFSET(PT_EPC, pt_regs, epc); + OFFSET(PT_RA, pt_regs, ra); + OFFSET(PT_FP, pt_regs, s0); + OFFSET(PT_S0, pt_regs, s0); + OFFSET(PT_S1, pt_regs, s1); + OFFSET(PT_S2, pt_regs, s2); + OFFSET(PT_S3, pt_regs, s3); + OFFSET(PT_S4, pt_regs, s4); + OFFSET(PT_S5, pt_regs, s5); + OFFSET(PT_S6, pt_regs, s6); + OFFSET(PT_S7, pt_regs, s7); + OFFSET(PT_S8, pt_regs, s8); + OFFSET(PT_S9, pt_regs, s9); + OFFSET(PT_S10, pt_regs, s10); + OFFSET(PT_S11, pt_regs, s11); + OFFSET(PT_SP, pt_regs, sp); + OFFSET(PT_TP, pt_regs, tp); + OFFSET(PT_A0, pt_regs, a0); + OFFSET(PT_A1, pt_regs, a1); + OFFSET(PT_A2, pt_regs, a2); + OFFSET(PT_A3, pt_regs, a3); + OFFSET(PT_A4, pt_regs, a4); + OFFSET(PT_A5, pt_regs, a5); + OFFSET(PT_A6, pt_regs, a6); + OFFSET(PT_A7, pt_regs, a7); + OFFSET(PT_T0, pt_regs, t0); + OFFSET(PT_T1, pt_regs, t1); + OFFSET(PT_T2, pt_regs, t2); + OFFSET(PT_T3, pt_regs, t3); + OFFSET(PT_T4, pt_regs, t4); + OFFSET(PT_T5, pt_regs, t5); + OFFSET(PT_T6, pt_regs, t6); + OFFSET(PT_GP, pt_regs, gp); + OFFSET(PT_STATUS, pt_regs, status); + OFFSET(PT_BADADDR, pt_regs, badaddr); + OFFSET(PT_CAUSE, pt_regs, cause); + + /* + * We allocate a pt_regs on the stack. This ensures the alignment is sane. + */ + DEFINE(PT_SIZE_ON_STACK, ALIGN(sizeof(struct pt_regs), STACK_ALIGN)); return 0; } diff --git a/arch/riscv/lib/bootm.c b/arch/riscv/lib/bootm.c index 1b96edcd1b..6984f282be 100644 --- a/arch/riscv/lib/bootm.c +++ b/arch/riscv/lib/bootm.c @@ -3,11 +3,13 @@ #include <common.h> #include <bootm.h> +#include <asm/system.h> static int do_bootm_linux(struct image_data *data) { void (*fn)(unsigned long a0, unsigned long dtb, unsigned long a2); phys_addr_t devicetree; + long hartid = riscv_hartid(); int ret; fn = booti_load_image(data, &devicetree); @@ -23,7 +25,7 @@ static int do_bootm_linux(struct image_data *data) shutdown_barebox(); - fn(0, devicetree, 0); + fn(hartid >= 0 ? hartid : 0, devicetree, 0); return -EINVAL; } diff --git a/arch/riscv/lib/cpuinfo.c b/arch/riscv/lib/cpuinfo.c index 21b99a990a..2d9cee2a62 100644 --- a/arch/riscv/lib/cpuinfo.c +++ b/arch/riscv/lib/cpuinfo.c @@ -2,6 +2,7 @@ #include <common.h> #include <command.h> #include <asm/sbi.h> +#include <asm/system.h> static const char *implementations[] = { [0] = "\"Berkeley Boot Loader (BBL)\" ", @@ -12,34 +13,57 @@ static const char *implementations[] = { [5] = "\"Diosix\" ", }; +static const char *modes[] = { + [RISCV_U_MODE] = "U", + [RISCV_S_MODE] = "S", + [RISCV_HS_MODE] = "HS", + [RISCV_M_MODE] = "M", +}; + static int do_cpuinfo(int argc, char *argv[]) { const char *implementation = ""; + enum riscv_mode mode; unsigned long impid; - printf("SBI specification v%lu.%lu detected\n", - sbi_major_version(), sbi_minor_version()); + mode = riscv_mode() & RISCV_MODE_MASK; + + printf("%s barebox for %s-Mode\n", + IS_ENABLED(CONFIG_ARCH_RV64I) ? "RV64I" : "RV32I", + modes[mode]); + + switch (mode) { + case RISCV_S_MODE: + printf("Hart ID=%lu\n", riscv_hartid()); + if (!IS_ENABLED(CONFIG_RISCV_SBI)) + break; + printf("SBI specification v%lu.%lu detected\n", + sbi_major_version(), sbi_minor_version()); - if (sbi_spec_is_0_1()) - return 0; + if (sbi_spec_is_0_1()) + return 0; - impid = __sbi_base_ecall(SBI_EXT_BASE_GET_IMP_ID); - if (impid < ARRAY_SIZE(implementations)) - implementation = implementations[impid]; + impid = __sbi_base_ecall(SBI_EXT_BASE_GET_IMP_ID); + if (impid < ARRAY_SIZE(implementations)) + implementation = implementations[impid]; - printf("SBI implementation ID=0x%lx %sVersion=0x%lx\n", - impid, implementation, __sbi_base_ecall(SBI_EXT_BASE_GET_IMP_VERSION)); + printf("SBI implementation ID=0x%lx %sVersion=0x%lx\n", + impid, implementation, __sbi_base_ecall(SBI_EXT_BASE_GET_IMP_VERSION)); - printf("SBI Machine VENDORID=0x%lx ARCHID=0x%lx MIMPID=0x%lx\n", - __sbi_base_ecall(SBI_EXT_BASE_GET_MVENDORID), - __sbi_base_ecall(SBI_EXT_BASE_GET_MARCHID), - __sbi_base_ecall(SBI_EXT_BASE_GET_MIMPID)); + printf("SBI Machine VENDORID=0x%lx ARCHID=0x%lx MIMPID=0x%lx\n", + __sbi_base_ecall(SBI_EXT_BASE_GET_MVENDORID), + __sbi_base_ecall(SBI_EXT_BASE_GET_MARCHID), + __sbi_base_ecall(SBI_EXT_BASE_GET_MIMPID)); + break; + default: + break; + } return 0; } BAREBOX_CMD_START(cpuinfo) .cmd = do_cpuinfo, -BAREBOX_CMD_DESC("show CPU information") -BAREBOX_CMD_GROUP(CMD_GRP_INFO) - BAREBOX_CMD_END + BAREBOX_CMD_DESC("show CPU information") + BAREBOX_CMD_GROUP(CMD_GRP_INFO) +BAREBOX_CMD_END diff --git a/arch/riscv/lib/reloc.c b/arch/riscv/lib/reloc.c index 2fc8818cd6..479d586afd 100644 --- a/arch/riscv/lib/reloc.c +++ b/arch/riscv/lib/reloc.c @@ -5,6 +5,7 @@ #include <linux/linkage.h> #include <asm/sections.h> #include <asm/barebox-riscv.h> +#include <asm/cacheflush.h> #include <debug_ll.h> #include <asm-generic/module.h> @@ -24,6 +25,11 @@ #define RISC_R_TYPE(x) ((x) & 0xFF) +void sync_caches_for_execution(void) +{ + local_flush_icache_all(); +} + void relocate_to_current_adr(void) { unsigned long offset; @@ -63,4 +69,6 @@ void relocate_to_current_adr(void) panic(""); } } + + sync_caches_for_execution(); } diff --git a/arch/riscv/lib/sbi.c b/arch/riscv/lib/sbi.c index 973c9d9d0f..45a04fb821 100644 --- a/arch/riscv/lib/sbi.c +++ b/arch/riscv/lib/sbi.c @@ -6,6 +6,7 @@ */ #include <asm/sbi.h> +#include <asm/system.h> #include <linux/export.h> #include <errno.h> #include <init.h> @@ -53,6 +54,9 @@ static int sbi_init(void) { int ret; + if (riscv_mode() != RISCV_S_MODE) + return 0; + ret = sbi_get_spec_version(); if (ret > 0) sbi_spec_version = ret; diff --git a/arch/riscv/lib/setupc.S b/arch/riscv/lib/setupc.S index 5fdd81c2c3..d225186c79 100644 --- a/arch/riscv/lib/setupc.S +++ b/arch/riscv/lib/setupc.S @@ -46,6 +46,8 @@ ENTRY(relocate_to_adr) jal __memcpy + jal sync_caches_for_execution + REG_L a0, (SZREG * 1)(sp) jr a0 /* jump to relocated address */ copied: diff --git a/commands/Kconfig b/commands/Kconfig index 7bb36d6e41..2237536088 100644 --- a/commands/Kconfig +++ b/commands/Kconfig @@ -47,9 +47,9 @@ config CMD_ARM_CPUINFO config CMD_RISCV_CPUINFO bool "cpuinfo command" default y - depends on RISCV_SBI + depends on RISCV help - Show SBI info about RISC-V CPU + Show info about RISC-V CPU config CMD_DEVINFO tristate diff --git a/common/Kconfig b/common/Kconfig index 1ece3f7318..2d7888b9fa 100644 --- a/common/Kconfig +++ b/common/Kconfig @@ -1376,6 +1376,12 @@ config DEBUG_RPI3_MINI_UART config DEBUG_ERIZO bool "Erizo ns16550 port" depends on SOC_ERIZO + select DEBUG_LL_NS16550 + +config DEBUG_STARFIVE + bool "Starfive ns16550 serial0 port" + depends on SOC_STARFIVE + select DEBUG_LL_NS16550 config DEBUG_SIFIVE bool "SiFive serial0 port" @@ -1383,6 +1389,11 @@ config DEBUG_SIFIVE endchoice +config DEBUG_LL_NS16550 + bool + help + Selected by RISC-V platforms that use ns16550 for debug_ll + config DEBUG_IMX_UART_PORT int "i.MX Debug UART Port Selection" if DEBUG_IMX1_UART || \ DEBUG_IMX21_UART || \ diff --git a/common/globalvar.c b/common/globalvar.c index 8bb5015ce4..9e5a99f793 100644 --- a/common/globalvar.c +++ b/common/globalvar.c @@ -565,6 +565,27 @@ int globalvar_add_simple_int(const char *name, int *value, return 0; } +int globalvar_add_simple_uint64(const char *name, u64 *value, + const char *format) +{ + struct param_d *p; + int ret; + + ret = globalvar_remove_unqualified(name); + if (ret) + return ret; + + p = dev_add_param_uint64(&global_device, name, NULL, NULL, + value, format, NULL); + + if (IS_ERR(p)) + return PTR_ERR(p); + + globalvar_nv_sync(name); + + return 0; +} + int globalvar_add_bool(const char *name, int (*set)(struct param_d *, void *), int *value, void *priv) diff --git a/common/oftree.c b/common/oftree.c index 7028c49aca..962fff244d 100644 --- a/common/oftree.c +++ b/common/oftree.c @@ -232,7 +232,24 @@ static int of_fixup_bootargs(struct device_node *root, void *unused) return err; } - return of_fixup_bootargs_bootsource(root, node); + err = of_fixup_bootargs_bootsource(root, node); + if (err) + return err; + + if (IS_ENABLED(CONFIG_RISCV)) { + const char *hartid; + + hartid = getenv("global.hartid"); + if (hartid) { + unsigned long id; + + err = kstrtoul(hartid, 10, &id); + if (!err) + err = of_property_write_u32(node, "boot-hartid", id); + } + } + + return err; } static int of_register_bootargs_fixup(void) diff --git a/drivers/Makefile b/drivers/Makefile index e21ac7095c..9958b748eb 100644 --- a/drivers/Makefile +++ b/drivers/Makefile @@ -40,7 +40,7 @@ obj-$(CONFIG_HAB) += hab/ obj-$(CONFIG_CRYPTO_HW) += crypto/ obj-$(CONFIG_AIODEV) += aiodev/ obj-y += memory/ -obj-y += soc/imx/ +obj-y += soc/ obj-y += nvme/ obj-y += ddr/ obj-y += power/ diff --git a/drivers/clk/Makefile b/drivers/clk/Makefile index b0be8d1bd8..499df2fe39 100644 --- a/drivers/clk/Makefile +++ b/drivers/clk/Makefile @@ -23,3 +23,4 @@ obj-$(CONFIG_MACH_MIPS_LOONGSON)+= loongson/ obj-$(CONFIG_ARCH_LAYERSCAPE) += clk-qoric.o obj-y += analogbits/ obj-$(CONFIG_CLK_SIFIVE) += sifive/ +obj-$(CONFIG_SOC_STARFIVE) += starfive/ diff --git a/drivers/clk/starfive/Makefile b/drivers/clk/starfive/Makefile new file mode 100644 index 0000000000..4e9bf7f2ba --- /dev/null +++ b/drivers/clk/starfive/Makefile @@ -0,0 +1,3 @@ +# SPDX-License-Identifier: GPL-2.0 + +obj-$(CONFIG_SOC_STARFIVE_JH71XX) += jh7100-clkgen.o diff --git a/drivers/clk/starfive/clk.h b/drivers/clk/starfive/clk.h new file mode 100644 index 0000000000..cfbf116dcb --- /dev/null +++ b/drivers/clk/starfive/clk.h @@ -0,0 +1,64 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Copyright 2021 Ahmad Fatoum, Pengutronix + */ + +#ifndef STARFIVE_CLK_H_ +#define STARFIVE_CLK_H_ + +#include <linux/clk.h> + +#define STARFIVE_CLK_ENABLE_SHIFT 31 +#define STARFIVE_CLK_INVERT_SHIFT 30 +#define STARFIVE_CLK_MUX_SHIFT 24 + +static inline struct clk *starfive_clk_underspecifid(const char *name, const char *parent) +{ + /* + * TODO With documentation available, all users of this functions can be + * migrated to one of the above or to a clk_fixed_factor with + * appropriate factor + */ + return clk_fixed_factor(name, parent, 1, 1, 0); +} + +static inline struct clk *starfive_clk_divider(const char *name, const char *parent, + void __iomem *reg, u8 width) +{ + return starfive_clk_underspecifid(name, parent); +} + +static inline struct clk *starfive_clk_gate(const char *name, const char *parent, + void __iomem *reg) +{ + return clk_gate(name, parent, reg, STARFIVE_CLK_ENABLE_SHIFT, CLK_SET_RATE_PARENT, 0); +} + +static inline struct clk *starfive_clk_divider_table(const char *name, + const char *parent, void __iomem *reg, u8 width, + const struct clk_div_table *table) +{ + return clk_divider_table(name, parent, CLK_SET_RATE_PARENT, reg, 0, + width, table, 0); +} + +static inline struct clk *starfive_clk_gated_divider(const char *name, + const char *parent, void __iomem *reg, u8 width) +{ + /* TODO divider part */ + return clk_gate(name, parent, reg, STARFIVE_CLK_ENABLE_SHIFT, CLK_SET_RATE_PARENT, 0); +} + +static inline struct clk *starfive_clk_gate_dis(const char *name, const char *parent, + void __iomem *reg) +{ + return clk_gate_inverted(name, parent, reg, STARFIVE_CLK_INVERT_SHIFT, CLK_SET_RATE_PARENT); +} + +static inline struct clk *starfive_clk_mux(const char *name, void __iomem *reg, + u8 width, const char * const *parents, u8 num_parents) +{ + return clk_mux(name, 0, reg, STARFIVE_CLK_MUX_SHIFT, width, parents, num_parents, 0); +} + +#endif diff --git a/drivers/clk/starfive/jh7100-clkgen.c b/drivers/clk/starfive/jh7100-clkgen.c new file mode 100644 index 0000000000..df5353e8e6 --- /dev/null +++ b/drivers/clk/starfive/jh7100-clkgen.c @@ -0,0 +1,363 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright 2021 Ahmad Fatoum, Pengutronix + */ + +#include <common.h> +#include <init.h> +#include <driver.h> +#include <linux/clk.h> +#include <io.h> +#include <of.h> +#include <linux/clkdev.h> +#include <linux/err.h> +#include <dt-bindings/clock/starfive-jh7100.h> + +#include "clk.h" + + +static const char *cpundbus_root_sels[4] = { + [0] = "osc_sys", + [1] = "pll0_out", + [2] = "pll1_out", + [3] = "pll2_out", +}; + +static const char *dla_root_sels[4] = { + [0] = "osc_sys", + [1] = "pll1_out", + [2] = "pll2_out", + [3] = "dummy", +}; + +static const char *dsp_root_sels[4] = { + [0] = "osc_sys", + [1] = "pll0_out", + [2] = "pll1_out", + [3] = "pll2_out", +}; + +static const char *gmacusb_root_sels[4] = { + [0] = "osc_sys", + [1] = "pll0_out", + [2] = "pll2_out", + [3] = "dummy", +}; + +static const char *perh0_root_sels[2] = { + [0] = "osc_sys", + [1] = "pll0_out", +}; + +static const char *perh1_root_sels[2] = { + [0] = "osc_sys", + [1] = "pll2_out", +}; + +static const char *vin_root_sels[4] = { + [0] = "osc_sys", + [1] = "pll1_out", + [2] = "pll2_out", + [3] = "dummy", +}; + +static const char *vout_root_sels[4] = { + [0] = "osc_aud", + [1] = "pll0_out", + [2] = "pll2_out", + [3] = "dummy", +}; + +static const char *cdechifi4_root_sels[4] = { + [0] = "osc_sys", + [1] = "pll1_out", + [2] = "pll2_out", + [3] = "dummy", +}; + +static const char *cdec_root_sels[4] = { + [0] = "osc_sys", + [1] = "pll0_out", + [2] = "pll1_out", + [3] = "dummy", +}; + +static const char *voutbus_root_sels[4] = { + [0] = "osc_aud", + [1] = "pll0_out", + [2] = "pll2_out", + [3] = "dummy", +}; + +static const char *pll2_refclk_sels[2] = { + [0] = "osc_sys", + [1] = "osc_aud", +}; + +static const char *ddrc0_sels[4] = { + [0] = "ddrosc_div2", + [1] = "ddrpll_div2", + [2] = "ddrpll_div4", + [3] = "ddrpll_div8", +}; + +static const char *ddrc1_sels[4] = { + [0] = "ddrosc_div2", + [1] = "ddrpll_div2", + [2] = "ddrpll_div4", + [3] = "ddrpll_div8", +}; + +static const char *nne_bus_sels[2] = { + [0] = "cpu_axi", + [1] = "nnebus_src1", +}; + +static const char *usbphy_25m_sels[2] = { + [0] = "osc_sys", + [1] = "usbphy_plldiv25m", +}; + +static const char *gmac_tx_sels[4] = { + [0] = "gmac_gtxclk", + [1] = "gmac_mii_txclk", + [2] = "gmac_rmii_txclk", + [3] = "dummy", +}; + +static const char *gmac_rx_pre_sels[2] = { + [0] = "gmac_gr_mii_rxclk", + [1] = "gmac_rmii_rxclk", +}; + +static struct clk *clks[CLK_END]; + +/* assume osc_sys as direct parent for clocks of yet unknown lineage */ +#define UNKNOWN "osc_sys" + +static void starfive_clkgen_init(struct device_node *np, void __iomem *base) +{ + clks[CLK_OSC_SYS] = of_clk_get_by_name(np, "osc_sys"); + clks[CLK_OSC_AUD] = of_clk_get_by_name(np, "osc_aud"); + clks[CLK_PLL0_OUT] = starfive_clk_underspecifid("pll0_out", "osc_sys"); + clks[CLK_PLL1_OUT] = starfive_clk_underspecifid("pll1_out", "osc_sys"); + clks[CLK_PLL2_OUT] = starfive_clk_underspecifid("pll2_out", "pll2_refclk"); + clks[CLK_CPUNDBUS_ROOT] = starfive_clk_mux("cpundbus_root", base + 0x0, 2, cpundbus_root_sels, ARRAY_SIZE(cpundbus_root_sels)); + clks[CLK_DLA_ROOT] = starfive_clk_mux("dla_root", base + 0x4, 2, dla_root_sels, ARRAY_SIZE(dla_root_sels)); + clks[CLK_DSP_ROOT] = starfive_clk_mux("dsp_root", base + 0x8, 2, dsp_root_sels, ARRAY_SIZE(dsp_root_sels)); + clks[CLK_GMACUSB_ROOT] = starfive_clk_mux("gmacusb_root", base + 0xC, 2, gmacusb_root_sels, ARRAY_SIZE(gmacusb_root_sels)); + clks[CLK_PERH0_ROOT] = starfive_clk_mux("perh0_root", base + 0x10, 1, perh0_root_sels, ARRAY_SIZE(perh0_root_sels)); + clks[CLK_PERH1_ROOT] = starfive_clk_mux("perh1_root", base + 0x14, 1, perh1_root_sels, ARRAY_SIZE(perh1_root_sels)); + clks[CLK_VIN_ROOT] = starfive_clk_mux("vin_root", base + 0x18, 2, vin_root_sels, ARRAY_SIZE(vin_root_sels)); + clks[CLK_VOUT_ROOT] = starfive_clk_mux("vout_root", base + 0x1C, 2, vout_root_sels, ARRAY_SIZE(vout_root_sels)); + clks[CLK_AUDIO_ROOT] = starfive_clk_gated_divider("audio_root", UNKNOWN, base + 0x20, 4); + clks[CLK_CDECHIFI4_ROOT] = starfive_clk_mux("cdechifi4_root", base + 0x24, 2, cdechifi4_root_sels, ARRAY_SIZE(cdechifi4_root_sels)); + clks[CLK_CDEC_ROOT] = starfive_clk_mux("cdec_root", base + 0x28, 2, cdec_root_sels, ARRAY_SIZE(cdec_root_sels)); + clks[CLK_VOUTBUS_ROOT] = starfive_clk_mux("voutbus_root", base + 0x2C, 2, voutbus_root_sels, ARRAY_SIZE(voutbus_root_sels)); + clks[CLK_CPUNBUS_ROOT_DIV] = starfive_clk_divider("cpunbus_root_div", "cpunbus_root", base + 0x30, 2); + clks[CLK_DSP_ROOT_DIV] = starfive_clk_divider("dsp_root_div", "dsp_root", base + 0x34, 3); + clks[CLK_PERH0_SRC] = starfive_clk_divider("perh0_src", "perh0_root", base + 0x38, 3); + clks[CLK_PERH1_SRC] = starfive_clk_divider("perh1_src", "perh1_root", base + 0x3C, 3); + clks[CLK_PLL0_TESTOUT] = starfive_clk_gated_divider("pll0_testout", "pll0_out", base + 0x40, 5); + clks[CLK_PLL1_TESTOUT] = starfive_clk_gated_divider("pll1_testout", "pll1_out", base + 0x44, 5); + clks[CLK_PLL2_TESTOUT] = starfive_clk_gated_divider("pll2_testout", "pll2_out", base + 0x48, 5); + clks[CLK_PLL2_REF] = starfive_clk_mux("pll2_refclk", base + 0x4C, 1, pll2_refclk_sels, ARRAY_SIZE(pll2_refclk_sels)); + clks[CLK_CPU_CORE] = starfive_clk_divider("cpu_core", UNKNOWN, base + 0x50, 4); + clks[CLK_CPU_AXI] = starfive_clk_divider("cpu_axi", UNKNOWN, base + 0x54, 4); + clks[CLK_AHB_BUS] = starfive_clk_divider("ahb_bus", UNKNOWN, base + 0x58, 4); + clks[CLK_APB1_BUS] = starfive_clk_divider("apb1_bus", UNKNOWN, base + 0x5C, 4); + clks[CLK_APB2_BUS] = starfive_clk_divider("apb2_bus", UNKNOWN, base + 0x60, 4); + clks[CLK_DOM3AHB_BUS] = starfive_clk_gate("dom3ahb_bus", UNKNOWN, base + 0x64); + clks[CLK_DOM7AHB_BUS] = starfive_clk_gate("dom7ahb_bus", UNKNOWN, base + 0x68); + clks[CLK_U74_CORE0] = starfive_clk_gate("u74_core0", UNKNOWN, base + 0x6C); + clks[CLK_U74_CORE1] = starfive_clk_gated_divider("u74_core1", "", base + 0x70, 4); + clks[CLK_U74_AXI] = starfive_clk_gate("u74_axi", UNKNOWN, base + 0x74); + clks[CLK_U74RTC_TOGGLE] = starfive_clk_gate("u74rtc_toggle", UNKNOWN, base + 0x78); + clks[CLK_SGDMA2P_AXI] = starfive_clk_gate("sgdma2p_axi", UNKNOWN, base + 0x7C); + clks[CLK_DMA2PNOC_AXI] = starfive_clk_gate("dma2pnoc_axi", UNKNOWN, base + 0x80); + clks[CLK_SGDMA2P_AHB] = starfive_clk_gate("sgdma2p_ahb", UNKNOWN, base + 0x84); + clks[CLK_DLA_BUS] = starfive_clk_divider("dla_bus", UNKNOWN, base + 0x88, 3); + clks[CLK_DLA_AXI] = starfive_clk_gate("dla_axi", UNKNOWN, base + 0x8C); + clks[CLK_DLANOC_AXI] = starfive_clk_gate("dlanoc_axi", UNKNOWN, base + 0x90); + clks[CLK_DLA_APB] = starfive_clk_gate("dla_apb", UNKNOWN, base + 0x94); + clks[CLK_VP6_CORE] = starfive_clk_gated_divider("vp6_core", UNKNOWN, base + 0x98, 3); + clks[CLK_VP6BUS_SRC] = starfive_clk_divider("vp6bus_src", UNKNOWN, base + 0x9C, 3); + clks[CLK_VP6_AXI] = starfive_clk_gated_divider("vp6_axi", UNKNOWN, base + 0xA0, 3); + clks[CLK_VCDECBUS_SRC] = starfive_clk_divider("vcdecbus_src", UNKNOWN, base + 0xA4, 3); + clks[CLK_VDEC_BUS] = starfive_clk_divider("vdec_bus", UNKNOWN, base + 0xA8, 4); + clks[CLK_VDEC_AXI] = starfive_clk_gate("vdec_axi", UNKNOWN, base + 0xAC); + clks[CLK_VDECBRG_MAIN] = starfive_clk_gate("vdecbrg_mainclk", UNKNOWN, base + 0xB0); + clks[CLK_VDEC_BCLK] = starfive_clk_gated_divider("vdec_bclk", UNKNOWN, base + 0xB4, 4); + clks[CLK_VDEC_CCLK] = starfive_clk_gated_divider("vdec_cclk", UNKNOWN, base + 0xB8, 4); + clks[CLK_VDEC_APB] = starfive_clk_gate("vdec_apb", UNKNOWN, base + 0xBC); + clks[CLK_JPEG_AXI] = starfive_clk_gated_divider("jpeg_axi", UNKNOWN, base + 0xC0, 4); + clks[CLK_JPEG_CCLK] = starfive_clk_gated_divider("jpeg_cclk", UNKNOWN, base + 0xC4, 4); + clks[CLK_JPEG_APB] = starfive_clk_gate("jpeg_apb", UNKNOWN, base + 0xC8); + clks[CLK_GC300_2X] = starfive_clk_gated_divider("gc300_2x", UNKNOWN, base + 0xCC, 4); + clks[CLK_GC300_AHB] = starfive_clk_gate("gc300_ahb", UNKNOWN, base + 0xD0); + clks[CLK_JPCGC300_AXIBUS] = starfive_clk_divider("jpcgc300_axibus", UNKNOWN, base + 0xD4, 4); + clks[CLK_GC300_AXI] = starfive_clk_gate("gc300_axi", UNKNOWN, base + 0xD8); + clks[CLK_JPCGC300_MAIN] = starfive_clk_gate("jpcgc300_mainclk", UNKNOWN, base + 0xDC); + clks[CLK_VENC_BUS] = starfive_clk_divider("venc_bus", UNKNOWN, base + 0xE0, 4); + clks[CLK_VENC_AXI] = starfive_clk_gate("venc_axi", UNKNOWN, base + 0xE4); + clks[CLK_VENCBRG_MAIN] = starfive_clk_gate("vencbrg_mainclk", UNKNOWN, base + 0xE8); + clks[CLK_VENC_BCLK] = starfive_clk_gated_divider("venc_bclk", UNKNOWN, base + 0xEC, 4); + clks[CLK_VENC_CCLK] = starfive_clk_gated_divider("venc_cclk", UNKNOWN, base + 0xF0, 4); + clks[CLK_VENC_APB] = starfive_clk_gate("venc_apb", UNKNOWN, base + 0xF4); + clks[CLK_DDRPLL_DIV2] = starfive_clk_gated_divider("ddrpll_div2", UNKNOWN, base + 0xF8, 2); + clks[CLK_DDRPLL_DIV4] = starfive_clk_gated_divider("ddrpll_div4", UNKNOWN, base + 0xFC, 2); + clks[CLK_DDRPLL_DIV8] = starfive_clk_gated_divider("ddrpll_div8", UNKNOWN, base + 0x100, 2); + clks[CLK_DDROSC_DIV2] = starfive_clk_gated_divider("ddrosc_div2", UNKNOWN, base + 0x104, 2); + clks[CLK_DDRC0] = starfive_clk_mux("ddrc0", base + 0x108, 2, ddrc0_sels, ARRAY_SIZE(ddrc0_sels)); + clks[CLK_DDRC1] = starfive_clk_mux("ddrc1", base + 0x10C, 2, ddrc1_sels, ARRAY_SIZE(ddrc1_sels)); + clks[CLK_DDRPHY_APB] = starfive_clk_gate("ddrphy_apb", UNKNOWN, base + 0x110); + clks[CLK_NOC_ROB] = starfive_clk_divider("noc_rob", UNKNOWN, base + 0x114, 4); + clks[CLK_NOC_COG] = starfive_clk_divider("noc_cog", UNKNOWN, base + 0x118, 4); + clks[CLK_NNE_AHB] = starfive_clk_gate("nne_ahb", UNKNOWN, base + 0x11C); + clks[CLK_NNEBUS_SRC1] = starfive_clk_divider("nnebus_src1", UNKNOWN, base + 0x120, 3); + clks[CLK_NNE_BUS] = starfive_clk_mux("nne_bus", base + 0x124, 2, nne_bus_sels, ARRAY_SIZE(nne_bus_sels)); + clks[CLK_NNE_AXI] = starfive_clk_gate("nne_axi", UNKNOWN, base + 0x128); + clks[CLK_NNENOC_AXI] = starfive_clk_gate("nnenoc_axi", UNKNOWN, base + 0x12C); + clks[CLK_DLASLV_AXI] = starfive_clk_gate("dlaslv_axi", UNKNOWN, base + 0x130); + clks[CLK_DSPX2C_AXI] = starfive_clk_gate("dspx2c_axi", UNKNOWN, base + 0x134); + clks[CLK_HIFI4_SRC] = starfive_clk_divider("hifi4_src", UNKNOWN, base + 0x138, 3); + clks[CLK_HIFI4_COREFREE] = starfive_clk_divider("hifi4_corefree", UNKNOWN, base + 0x13C, 4); + clks[CLK_HIFI4_CORE] = starfive_clk_gate("hifi4_core", UNKNOWN, base + 0x140); + clks[CLK_HIFI4_BUS] = starfive_clk_divider("hifi4_bus", UNKNOWN, base + 0x144, 4); + clks[CLK_HIFI4_AXI] = starfive_clk_gate("hifi4_axi", UNKNOWN, base + 0x148); + clks[CLK_HIFI4NOC_AXI] = starfive_clk_gate("hifi4noc_axi", UNKNOWN, base + 0x14C); + clks[CLK_SGDMA1P_BUS] = starfive_clk_divider("sgdma1p_bus", UNKNOWN, base + 0x150, 4); + clks[CLK_SGDMA1P_AXI] = starfive_clk_gate("sgdma1p_axi", UNKNOWN, base + 0x154); + clks[CLK_DMA1P_AXI] = starfive_clk_gate("dma1p_axi", UNKNOWN, base + 0x158); + clks[CLK_X2C_AXI] = starfive_clk_gated_divider("x2c_axi", UNKNOWN, base + 0x15C, 4); + clks[CLK_USB_BUS] = starfive_clk_divider("usb_bus", UNKNOWN, base + 0x160, 4); + clks[CLK_USB_AXI] = starfive_clk_gate("usb_axi", UNKNOWN, base + 0x164); + clks[CLK_USBNOC_AXI] = starfive_clk_gate("usbnoc_axi", UNKNOWN, base + 0x168); + clks[CLK_USBPHY_ROOTDIV] = starfive_clk_divider("usbphy_rootdiv", UNKNOWN, base + 0x16C, 3); + clks[CLK_USBPHY_125M] = starfive_clk_gated_divider("usbphy_125m", UNKNOWN, base + 0x170, 4); + clks[CLK_USBPHY_PLLDIV25M] = starfive_clk_gated_divider("usbphy_plldiv25m", UNKNOWN, base + 0x174, 6); + clks[CLK_USBPHY_25M] = starfive_clk_mux("usbphy_25m", base + 0x178, 1, usbphy_25m_sels, ARRAY_SIZE(usbphy_25m_sels)); + clks[CLK_AUDIO_DIV] = starfive_clk_divider("audio_div", UNKNOWN, base + 0x17C, 18); + clks[CLK_AUDIO_SRC] = starfive_clk_gate("audio_src", UNKNOWN, base + 0x180); + clks[CLK_AUDIO_12288] = starfive_clk_gate("audio_12288", UNKNOWN, base + 0x184); + clks[CLK_VIN_SRC] = starfive_clk_gated_divider("vin_src", UNKNOWN, base + 0x188, 3); + clks[CLK_ISP0_BUS] = starfive_clk_divider("isp0_bus", UNKNOWN, base + 0x18C, 4); + clks[CLK_ISP0_AXI] = starfive_clk_gate("isp0_axi", UNKNOWN, base + 0x190); + clks[CLK_ISP0NOC_AXI] = starfive_clk_gate("isp0noc_axi", UNKNOWN, base + 0x194); + clks[CLK_ISPSLV_AXI] = starfive_clk_gate("ispslv_axi", UNKNOWN, base + 0x198); + clks[CLK_ISP1_BUS] = starfive_clk_divider("isp1_bus", UNKNOWN, base + 0x19C, 4); + clks[CLK_ISP1_AXI] = starfive_clk_gate("isp1_axi", UNKNOWN, base + 0x1A0); + clks[CLK_ISP1NOC_AXI] = starfive_clk_gate("isp1noc_axi", UNKNOWN, base + 0x1A4); + clks[CLK_VIN_BUS] = starfive_clk_divider("vin_bus", UNKNOWN, base + 0x1A8, 4); + clks[CLK_VIN_AXI] = starfive_clk_gate("vin_axi", UNKNOWN, base + 0x1AC); + clks[CLK_VINNOC_AXI] = starfive_clk_gate("vinnoc_axi", UNKNOWN, base + 0x1B0); + clks[CLK_VOUT_SRC] = starfive_clk_gated_divider("vout_src", UNKNOWN, base + 0x1B4, 3); + clks[CLK_DISPBUS_SRC] = starfive_clk_divider("dispbus_src", UNKNOWN, base + 0x1B8, 3); + clks[CLK_DISP_BUS] = starfive_clk_divider("disp_bus", UNKNOWN, base + 0x1BC, 3); + clks[CLK_DISP_AXI] = starfive_clk_gate("disp_axi", UNKNOWN, base + 0x1C0); + clks[CLK_DISPNOC_AXI] = starfive_clk_gate("dispnoc_axi", UNKNOWN, base + 0x1C4); + clks[CLK_SDIO0_AHB] = starfive_clk_gate("sdio0_ahb", UNKNOWN, base + 0x1C8); + clks[CLK_SDIO0_CCLKINT] = starfive_clk_gated_divider("sdio0_cclkint", UNKNOWN, base + 0x1CC, 5); + clks[CLK_SDIO0_CCLKINT_INV] = starfive_clk_gate_dis("sdio0_cclkint_inv", UNKNOWN, base + 0x1D0); + clks[CLK_SDIO1_AHB] = starfive_clk_gate("sdio1_ahb", UNKNOWN, base + 0x1D4); + clks[CLK_SDIO1_CCLKINT] = starfive_clk_gated_divider("sdio1_cclkint", UNKNOWN, base + 0x1D8, 5); + clks[CLK_SDIO1_CCLKINT_INV] = starfive_clk_gate_dis("sdio1_cclkint_inv", UNKNOWN, base + 0x1DC); + clks[CLK_GMAC_AHB] = starfive_clk_gate("gmac_ahb", UNKNOWN, base + 0x1E0); + clks[CLK_GMAC_ROOT_DIV] = starfive_clk_divider("gmac_root_div", UNKNOWN, base + 0x1E4, 4); + clks[CLK_GMAC_PTP_REF] = starfive_clk_gated_divider("gmac_ptp_refclk", UNKNOWN, base + 0x1E8, 5); + clks[CLK_GMAC_GTX] = starfive_clk_gated_divider("gmac_gtxclk", UNKNOWN, base + 0x1EC, 8); + clks[CLK_GMAC_RMII_TX] = starfive_clk_gated_divider("gmac_rmii_txclk", UNKNOWN, base + 0x1F0, 4); + clks[CLK_GMAC_RMII_RX] = starfive_clk_gated_divider("gmac_rmii_rxclk", UNKNOWN, base + 0x1F4, 4); + clks[CLK_GMAC_TX] = starfive_clk_mux("gmac_tx", base + 0x1F8, 2, gmac_tx_sels, ARRAY_SIZE(gmac_tx_sels)); + clks[CLK_GMAC_TX_INV] = starfive_clk_gate_dis("gmac_tx_inv", UNKNOWN, base + 0x1FC); + clks[CLK_GMAC_RX_PRE] = starfive_clk_mux("gmac_rx_pre", base + 0x200, 1, gmac_rx_pre_sels, ARRAY_SIZE(gmac_rx_pre_sels)); + clks[CLK_GMAC_RX_INV] = starfive_clk_gate_dis("gmac_rx_inv", UNKNOWN, base + 0x204); + clks[CLK_GMAC_RMII] = starfive_clk_gate("gmac_rmii", UNKNOWN, base + 0x208); + clks[CLK_GMAC_TOPHYREF] = starfive_clk_gated_divider("gmac_tophyref", UNKNOWN, base + 0x20C, 7); + clks[CLK_SPI2AHB_AHB] = starfive_clk_gate("spi2ahb_ahb", UNKNOWN, base + 0x210); + clks[CLK_SPI2AHB_CORE] = starfive_clk_gated_divider("spi2ahb_core", UNKNOWN, base + 0x214, 5); + clks[CLK_EZMASTER_AHB] = starfive_clk_gate("ezmaster_ahb", UNKNOWN, base + 0x218); + clks[CLK_E24_AHB] = starfive_clk_gate("e24_ahb", UNKNOWN, base + 0x21C); + clks[CLK_E24RTC_TOGGLE] = starfive_clk_gate("e24rtc_toggle", UNKNOWN, base + 0x220); + clks[CLK_QSPI_AHB] = starfive_clk_gate("qspi_ahb", UNKNOWN, base + 0x224); + clks[CLK_QSPI_APB] = starfive_clk_gate("qspi_apb", UNKNOWN, base + 0x228); + clks[CLK_QSPI_REF] = starfive_clk_gated_divider("qspi_refclk", UNKNOWN, base + 0x22C, 5); + clks[CLK_SEC_AHB] = starfive_clk_gate("sec_ahb", UNKNOWN, base + 0x230); + clks[CLK_AES] = starfive_clk_gate("aes_clk", UNKNOWN, base + 0x234); + clks[CLK_SHA] = starfive_clk_gate("sha_clk", UNKNOWN, base + 0x238); + clks[CLK_PKA] = starfive_clk_gate("pka_clk", UNKNOWN, base + 0x23C); + clks[CLK_TRNG_APB] = starfive_clk_gate("trng_apb", UNKNOWN, base + 0x240); + clks[CLK_OTP_APB] = starfive_clk_gate("otp_apb", UNKNOWN, base + 0x244); + clks[CLK_UART0_APB] = starfive_clk_gate("uart0_apb", UNKNOWN, base + 0x248); + clks[CLK_UART0_CORE] = starfive_clk_gated_divider("uart0_core", UNKNOWN, base + 0x24C, 6); + clks[CLK_UART1_APB] = starfive_clk_gate("uart1_apb", UNKNOWN, base + 0x250); + clks[CLK_UART1_CORE] = starfive_clk_gated_divider("uart1_core", UNKNOWN, base + 0x254, 6); + clks[CLK_SPI0_APB] = starfive_clk_gate("spi0_apb", UNKNOWN, base + 0x258); + clks[CLK_SPI0_CORE] = starfive_clk_gated_divider("spi0_core", UNKNOWN, base + 0x25C, 6); + clks[CLK_SPI1_APB] = starfive_clk_gate("spi1_apb", UNKNOWN, base + 0x260); + clks[CLK_SPI1_CORE] = starfive_clk_gated_divider("spi1_core", UNKNOWN, base + 0x264, 6); + clks[CLK_I2C0_APB] = starfive_clk_gate("i2c0_apb", UNKNOWN, base + 0x268); + clks[CLK_I2C0_CORE] = starfive_clk_gated_divider("i2c0_core", UNKNOWN, base + 0x26C, 6); + clks[CLK_I2C1_APB] = starfive_clk_gate("i2c1_apb", UNKNOWN, base + 0x270); + clks[CLK_I2C1_CORE] = starfive_clk_gated_divider("i2c1_core", UNKNOWN, base + 0x274, 6); + clks[CLK_GPIO_APB] = starfive_clk_gate("gpio_apb", UNKNOWN, base + 0x278); + clks[CLK_UART2_APB] = starfive_clk_gate("uart2_apb", UNKNOWN, base + 0x27C); + clks[CLK_UART2_CORE] = starfive_clk_gated_divider("uart2_core", UNKNOWN, base + 0x280, 6); + clks[CLK_UART3_APB] = starfive_clk_gate("uart3_apb", UNKNOWN, base + 0x284); + clks[CLK_UART3_CORE] = starfive_clk_gated_divider("uart3_core", UNKNOWN, base + 0x288, 6); + clks[CLK_SPI2_APB] = starfive_clk_gate("spi2_apb", UNKNOWN, base + 0x28C); + clks[CLK_SPI2_CORE] = starfive_clk_gated_divider("spi2_core", UNKNOWN, base + 0x290, 6); + clks[CLK_SPI3_APB] = starfive_clk_gate("spi3_apb", UNKNOWN, base + 0x294); + clks[CLK_SPI3_CORE] = starfive_clk_gated_divider("spi3_core", UNKNOWN, base + 0x298, 6); + clks[CLK_I2C2_APB] = starfive_clk_gate("i2c2_apb", UNKNOWN, base + 0x29C); + clks[CLK_I2C2_CORE] = starfive_clk_gated_divider("i2c2_core", UNKNOWN, base + 0x2A0, 6); + clks[CLK_I2C3_APB] = starfive_clk_gate("i2c3_apb", UNKNOWN, base + 0x2A4); + clks[CLK_I2C3_CORE] = starfive_clk_gated_divider("i2c3_core", UNKNOWN, base + 0x2A8, 6); + clks[CLK_WDTIMER_APB] = starfive_clk_gate("wdtimer_apb", UNKNOWN, base + 0x2AC); + clks[CLK_WDT_CORE] = starfive_clk_gated_divider("wdt_coreclk", UNKNOWN, base + 0x2B0, 6); + clks[CLK_TIMER0_CORE] = starfive_clk_gated_divider("timer0_coreclk", UNKNOWN, base + 0x2B4, 6); + clks[CLK_TIMER1_CORE] = starfive_clk_gated_divider("timer1_coreclk", UNKNOWN, base + 0x2B8, 6); + clks[CLK_TIMER2_CORE] = starfive_clk_gated_divider("timer2_coreclk", UNKNOWN, base + 0x2BC, 6); + clks[CLK_TIMER3_CORE] = starfive_clk_gated_divider("timer3_coreclk", UNKNOWN, base + 0x2C0, 6); + clks[CLK_TIMER4_CORE] = starfive_clk_gated_divider("timer4_coreclk", UNKNOWN, base + 0x2C4, 6); + clks[CLK_TIMER5_CORE] = starfive_clk_gated_divider("timer5_coreclk", UNKNOWN, base + 0x2C8, 6); + clks[CLK_TIMER6_CORE] = starfive_clk_gated_divider("timer6_coreclk", UNKNOWN, base + 0x2CC, 6); + clks[CLK_VP6INTC_APB] = starfive_clk_gate("vp6intc_apb", UNKNOWN, base + 0x2D0); + clks[CLK_PWM_APB] = starfive_clk_gate("pwm_apb", UNKNOWN, base + 0x2D4); + clks[CLK_MSI_APB] = starfive_clk_gate("msi_apb", UNKNOWN, base + 0x2D8); + clks[CLK_TEMP_APB] = starfive_clk_gate("temp_apb", UNKNOWN, base + 0x2DC); + clks[CLK_TEMP_SENSE] = starfive_clk_gated_divider("temp_sense", UNKNOWN, base + 0x2E0, 5); + clks[CLK_SYSERR_APB] = starfive_clk_gate("syserr_apb", UNKNOWN, base + 0x2E4); +} + +static struct clk_onecell_data clk_data; + +static int starfive_clkgen_clk_probe(struct device_d *dev) +{ + struct resource *iores; + + iores = dev_request_mem_resource(dev, 0); + if (IS_ERR(iores)) + return PTR_ERR(iores); + + starfive_clkgen_init(dev->device_node, IOMEM(iores->start)); + + clk_data.clks = clks; + clk_data.clk_num = ARRAY_SIZE(clks); + of_clk_add_provider(dev->device_node, of_clk_src_onecell_get, + &clk_data); + + return 0; +} + +static __maybe_unused struct of_device_id starfive_clkgen_clk_dt_ids[] = { + { .compatible = "starfive,jh7100-clkgen" }, + { /* sentinel */ } +}; + +static struct driver_d starfive_clkgen_clk_driver = { + .probe = starfive_clkgen_clk_probe, + .name = "starfive-clkgen", + .of_compatible = starfive_clkgen_clk_dt_ids, +}; +core_platform_driver(starfive_clkgen_clk_driver); diff --git a/drivers/clocksource/timer-clint.c b/drivers/clocksource/timer-clint.c index b7360010bd..412ce3e1e9 100644 --- a/drivers/clocksource/timer-clint.c +++ b/drivers/clocksource/timer-clint.c @@ -17,6 +17,7 @@ #include <linux/err.h> #include <io.h> #include <asm/timer.h> +#include <asm/system.h> #define CLINT_TIMER_VAL_OFF 0xbff8 @@ -63,8 +64,8 @@ static int clint_timer_init_dt(struct device_d* dev) { struct resource *iores; - /* one timer is enough */ - if (clint_timer_val) + /* one timer is enough. Only M-Mode */ + if (clint_timer_val || riscv_mode() != RISCV_M_MODE) return 0; iores = dev_request_mem_resource(dev, 0); @@ -72,7 +73,7 @@ static int clint_timer_init_dt(struct device_d* dev) return PTR_ERR(iores); clint_timer_val = IOMEM(iores->start) + CLINT_TIMER_VAL_OFF; - dev_info(dev, "running at %lu Hz\n", riscv_timebase); + dev_dbg(dev, "running at %lu Hz\n", riscv_timebase); clint_clocksource.mult = clocksource_hz2mult(riscv_timebase, clint_clocksource.shift); diff --git a/drivers/clocksource/timer-riscv.c b/drivers/clocksource/timer-riscv.c index ef67cff475..5a517fe6b4 100644 --- a/drivers/clocksource/timer-riscv.c +++ b/drivers/clocksource/timer-riscv.c @@ -12,6 +12,7 @@ #include <clock.h> #include <asm/timer.h> #include <asm/csr.h> +#include <asm/system.h> static u64 notrace riscv_timer_get_count_sbi(void) { @@ -45,7 +46,7 @@ static u64 notrace riscv_timer_get_count_rdcycle(void) static u64 notrace riscv_timer_get_count(void) { - if (IS_ENABLED(CONFIG_RISCV_SBI)) + if (riscv_mode() == RISCV_S_MODE) return riscv_timer_get_count_sbi(); else return riscv_timer_get_count_rdcycle(); @@ -59,7 +60,7 @@ static struct clocksource riscv_clocksource = { static int riscv_timer_init(struct device_d* dev) { - dev_info(dev, "running at %lu Hz\n", riscv_timebase); + dev_dbg(dev, "running at %lu Hz\n", riscv_timebase); riscv_clocksource.mult = clocksource_hz2mult(riscv_timebase, riscv_clocksource.shift); diff --git a/drivers/gpio/Kconfig b/drivers/gpio/Kconfig index a8ee9e58b8..98a44fbbb5 100644 --- a/drivers/gpio/Kconfig +++ b/drivers/gpio/Kconfig @@ -171,6 +171,14 @@ config GPIO_SIFIVE help Say yes here to support the GPIO device on SiFive SoCs. +config GPIO_STARFIVE + bool "StarFive GPIO support" + depends on SOC_STARFIVE || CROSS_COMPILE + depends on OF_GPIO + select GPIO_GENERIC + help + Say yes here to support the GPIO device on StarFive SoCs. + config GPIO_LIBFTDI1 bool "libftdi1 driver" depends on SANDBOX diff --git a/drivers/gpio/Makefile b/drivers/gpio/Makefile index 25e12105d8..638cbb19a3 100644 --- a/drivers/gpio/Makefile +++ b/drivers/gpio/Makefile @@ -24,3 +24,4 @@ obj-$(CONFIG_GPIO_SX150X) += gpio-sx150x.o obj-$(CONFIG_GPIO_VF610) += gpio-vf610.o obj-$(CONFIG_GPIO_RASPBERRYPI_EXP) += gpio-raspberrypi-exp.o obj-$(CONFIG_GPIO_SIFIVE) += gpio-sifive.o +obj-$(CONFIG_GPIO_STARFIVE) += gpio-starfive-vic.o diff --git a/drivers/gpio/gpio-starfive-vic.c b/drivers/gpio/gpio-starfive-vic.c new file mode 100644 index 0000000000..baa4f584d5 --- /dev/null +++ b/drivers/gpio/gpio-starfive-vic.c @@ -0,0 +1,177 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * COPYRIGHT 2020 Shanghai StarFive Technology Co., Ltd. + */ + +#include <linux/basic_mmio_gpio.h> +#include <linux/reset.h> +#include <linux/clk.h> +#include <printk.h> +#include <driver.h> +#include <errno.h> +#include <pinctrl.h> + +#define GPIO_EN 0x0 +#define GPIO_IS_LOW 0x10 +#define GPIO_IS_HIGH 0x14 +#define GPIO_IBE_LOW 0x18 +#define GPIO_IBE_HIGH 0x1c +#define GPIO_IEV_LOW 0x20 +#define GPIO_IEV_HIGH 0x24 +#define GPIO_IE_LOW 0x28 +#define GPIO_IE_HIGH 0x2c +#define GPIO_IC_LOW 0x30 +#define GPIO_IC_HIGH 0x34 +//read only +#define GPIO_RIS_LOW 0x38 +#define GPIO_RIS_HIGH 0x3c +#define GPIO_MIS_LOW 0x40 +#define GPIO_MIS_HIGH 0x44 +#define GPIO_DIN_LOW 0x48 +#define GPIO_DIN_HIGH 0x4c + +#define GPIO_DOUT_X_REG 0x50 +#define GPIO_DOEN_X_REG 0x54 + +#define MAX_GPIO 64 + +struct starfive_gpio { + void __iomem *base; + struct gpio_chip gc; +}; + +#define to_starfive_gpio(gc) container_of(gc, struct starfive_gpio, gc) + +static int starfive_direction_input(struct gpio_chip *gc, unsigned offset) +{ + struct starfive_gpio *chip = to_starfive_gpio(gc); + + if (offset >= gc->ngpio) + return -EINVAL; + + writel(0x1, chip->base + GPIO_DOEN_X_REG + offset * 8); + + return 0; +} + +static int starfive_direction_output(struct gpio_chip *gc, unsigned offset, int value) +{ + struct starfive_gpio *chip = to_starfive_gpio(gc); + + if (offset >= gc->ngpio) + return -EINVAL; + writel(0x0, chip->base + GPIO_DOEN_X_REG + offset * 8); + writel(value, chip->base + GPIO_DOUT_X_REG + offset * 8); + + return 0; +} + +static int starfive_get_direction(struct gpio_chip *gc, unsigned offset) +{ + struct starfive_gpio *chip = to_starfive_gpio(gc); + + if (offset >= gc->ngpio) + return -EINVAL; + + return readl(chip->base + GPIO_DOEN_X_REG + offset * 8) & 0x1; +} + +static int starfive_get_value(struct gpio_chip *gc, unsigned offset) +{ + struct starfive_gpio *chip = to_starfive_gpio(gc); + int value; + + if (offset >= gc->ngpio) + return -EINVAL; + + if(offset < 32){ + value = readl(chip->base + GPIO_DIN_LOW); + return (value >> offset) & 0x1; + } else { + value = readl(chip->base + GPIO_DIN_HIGH); + return (value >> (offset - 32)) & 0x1; + } +} + +static void starfive_set_value(struct gpio_chip *gc, unsigned offset, int value) +{ + struct starfive_gpio *chip = to_starfive_gpio(gc); + + if (offset >= gc->ngpio) + return; + + writel(value, chip->base + GPIO_DOUT_X_REG + offset * 8); +} + +static struct gpio_ops starfive_gpio_ops = { + .direction_input = starfive_direction_input, + .direction_output = starfive_direction_output, + .get_direction = starfive_get_direction, + .get = starfive_get_value, + .set = starfive_set_value, +}; + +static int starfive_gpio_probe(struct device_d *dev) +{ + struct starfive_gpio *chip; + struct resource *res; + struct clk *clk; + int ret; + + clk = clk_get(dev, NULL); + if (IS_ERR(clk)) + return PTR_ERR(clk); + + clk_enable(clk); + + ret = device_reset(dev); + if (ret) + return ret; + + ret = pinctrl_single_probe(dev); + if (ret) + return ret; + + res = dev_get_resource(dev, IORESOURCE_MEM, 0); + if (IS_ERR(res)) + return PTR_ERR(res); + + chip = xzalloc(sizeof(*chip)); + chip->base = IOMEM(res->start); + + chip->gc.base = -1; + chip->gc.ngpio = MAX_GPIO; + chip->gc.dev = dev; + chip->gc.ops = &starfive_gpio_ops; + + /* Disable all GPIO interrupts */ + iowrite32(0, chip->base + GPIO_IE_HIGH); + iowrite32(0, chip->base + GPIO_IE_LOW); + + ret = gpiochip_add(&chip->gc); + if (ret) { + dev_err(dev, "could not add gpiochip\n"); + gpiochip_remove(&chip->gc); + return ret; + } + + writel(1, chip->base + GPIO_EN); + + return 0; +} + +static const struct of_device_id starfive_gpio_match[] = { + { .compatible = "starfive,gpio0", }, + { }, +}; + +static struct driver_d starfive_gpio_driver = { + .probe = starfive_gpio_probe, + .name = "starfive_gpio", + .of_compatible = starfive_gpio_match, +}; +postcore_platform_driver(starfive_gpio_driver); + +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Huan Feng <huan.feng@starfivetech.com>"); +MODULE_DESCRIPTION("Starfive VIC GPIO generator driver"); diff --git a/drivers/hw_random/Kconfig b/drivers/hw_random/Kconfig index a84c03efef..764911f4d3 100644 --- a/drivers/hw_random/Kconfig +++ b/drivers/hw_random/Kconfig @@ -36,4 +36,11 @@ config HW_RANDOM_VIRTIO This driver provides guest-side support for the virtual Random Number Generator hardware. +config HW_RANDOM_STARFIVE + tristate "StarFive Random Number Generator" + depends on SOC_STARFIVE || COMPILE_TEST + help + This driver provides barebox support for the Random Number + Generator hardware found on the StarFive family of SoCs. + endif diff --git a/drivers/hw_random/Makefile b/drivers/hw_random/Makefile index 4bab3967fc..4cf33d2d93 100644 --- a/drivers/hw_random/Makefile +++ b/drivers/hw_random/Makefile @@ -3,3 +3,4 @@ obj-$(CONFIG_HWRNG_MXC_RNGC) += mxc-rngc.o obj-$(CONFIG_HWRNG_STM32) += stm32-rng.o obj-$(CONFIG_HWRNG_DEV_RANDOM) += dev-random.o obj-$(CONFIG_HW_RANDOM_VIRTIO) += virtio-rng.o +obj-$(CONFIG_HW_RANDOM_STARFIVE) += starfive-vic-rng.o diff --git a/drivers/hw_random/starfive-vic-rng.c b/drivers/hw_random/starfive-vic-rng.c new file mode 100644 index 0000000000..f7b7585884 --- /dev/null +++ b/drivers/hw_random/starfive-vic-rng.c @@ -0,0 +1,208 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * COPYRIGHT 2020 Shanghai StarFive Technology Co., Ltd. + */ +#include <common.h> +#include <linux/err.h> +#include <io.h> +#include <of.h> +#include <driver.h> +#include <linux/hw_random.h> +#include <linux/reset.h> +#include <linux/clk.h> + +#define VIC_RAND_LEN 4 + +#define VIC_CTRL 0x00 +#define VIC_MODE 0x04 +#define VIC_SMODE 0x08 +#define VIC_STAT 0x0C +#define VIC_IE 0x10 +#define VIC_ISTAT 0x14 +#define VIC_ALARM 0x18 +#define VIC_BUILD_ID 0x1C +#define VIC_FEATURES 0x20 +#define VIC_RAND0 0x24 +#define VIC_NPA_DATA0 0x34 +#define VIC_SEED0 0x74 +#define VIC_IA_RDATA 0xA4 +#define VIC_IA_WDATA 0xA8 +#define VIC_IA_ADDR 0xAC +#define VIC_IA_CMD 0xB0 + +/* CTRL */ +#define VIC_CTRL_CMD_NOP 0 +#define VIC_CTRL_CMD_GEN_NOISE 1 +#define VIC_CTRL_CMD_GEN_NONCE 2 +#define VIC_CTRL_CMD_CREATE_STATE 3 +#define VIC_CTRL_CMD_RENEW_STATE 4 +#define VIC_CTRL_CMD_REFRESH_ADDIN 5 +#define VIC_CTRL_CMD_GEN_RANDOM 6 +#define VIC_CTRL_CMD_ADVANCE_STATE 7 +#define VIC_CTRL_CMD_KAT 8 +#define VIC_CTRL_CMD_ZEROIZE 15 + +/* SMODE */ +#define _VIC_SMODE_SECURE_EN 1 + +#define VIC_SMODE_SECURE_EN(x) ((x) << _VIC_SMODE_SECURE_EN) + +/* STAT */ +#define _VIC_STAT_BUSY 31 + +#define VIC_STAT_BUSY (1UL << _VIC_STAT_BUSY) + +/* IE */ +#define _VIC_IE_GLBL 31 +#define _VIC_IE_DONE 4 +#define _VIC_IE_ALARMS 3 +#define _VIC_IE_NOISE_RDY 2 +#define _VIC_IE_KAT_COMPLETE 1 +#define _VIC_IE_ZEROIZE 0 + +#define VIC_IE_GLBL (1UL << _VIC_IE_GLBL) +#define VIC_IE_DONE (1UL << _VIC_IE_DONE) +#define VIC_IE_ALARMS (1UL << _VIC_IE_ALARMS) +#define VIC_IE_NOISE_RDY (1UL << _VIC_IE_NOISE_RDY) +#define VIC_IE_KAT_COMPLETE (1UL << _VIC_IE_KAT_COMPLETE) +#define VIC_IE_ZEROIZE (1UL << _VIC_IE_ZEROIZE) +#define VIC_IE_ALL (VIC_IE_GLBL | VIC_IE_DONE | VIC_IE_ALARMS | \ + VIC_IE_NOISE_RDY | VIC_IE_KAT_COMPLETE | VIC_IE_ZEROIZE) + +#define to_vic_rng(p) container_of(p, struct vic_rng, rng) + +struct vic_rng { + struct device_d *dev; + void __iomem *base; + struct hwrng rng; +}; + +static inline void vic_wait_till_idle(struct vic_rng *hrng) +{ + while(readl(hrng->base + VIC_STAT) & VIC_STAT_BUSY) + ; +} + +static inline void vic_rng_irq_mask_clear(struct vic_rng *hrng) +{ + u32 data = readl(hrng->base + VIC_ISTAT); + writel(data, hrng->base + VIC_ISTAT); + writel(0, hrng->base + VIC_ALARM); +} + +static int vic_trng_cmd(struct vic_rng *hrng, u32 cmd) +{ + vic_wait_till_idle(hrng); + + switch (cmd) { + case VIC_CTRL_CMD_NOP: + case VIC_CTRL_CMD_GEN_NOISE: + case VIC_CTRL_CMD_GEN_NONCE: + case VIC_CTRL_CMD_CREATE_STATE: + case VIC_CTRL_CMD_RENEW_STATE: + case VIC_CTRL_CMD_REFRESH_ADDIN: + case VIC_CTRL_CMD_GEN_RANDOM: + case VIC_CTRL_CMD_ADVANCE_STATE: + case VIC_CTRL_CMD_KAT: + case VIC_CTRL_CMD_ZEROIZE: + writel(cmd, hrng->base + VIC_CTRL); + return 0; + default: + return -EINVAL; + } +} + +static int vic_rng_init(struct hwrng *rng) +{ + struct vic_rng *hrng = to_vic_rng(rng); + struct clk *clk; + int ret; + + clk = clk_get(rng->dev, NULL); + if (IS_ERR(clk)) + return PTR_ERR(clk); + + clk_enable(clk); + + ret = device_reset(rng->dev); + if (ret) + return ret; + + // clear register: ISTAT + vic_rng_irq_mask_clear(hrng); + + // set mission mode + writel(VIC_SMODE_SECURE_EN(1), hrng->base + VIC_SMODE); + + vic_trng_cmd(hrng, VIC_CTRL_CMD_GEN_NOISE); + vic_wait_till_idle(hrng); + + // set interrupt + writel(VIC_IE_ALL, hrng->base + VIC_IE); + + // zeroize + vic_trng_cmd(hrng, VIC_CTRL_CMD_ZEROIZE); + + vic_wait_till_idle(hrng); + + return 0; +} + +static int vic_rng_read(struct hwrng *rng, void *buf, size_t max, bool wait) +{ + struct vic_rng *hrng = to_vic_rng(rng); + + vic_trng_cmd(hrng, VIC_CTRL_CMD_ZEROIZE); + vic_trng_cmd(hrng, VIC_CTRL_CMD_GEN_NOISE); + vic_trng_cmd(hrng, VIC_CTRL_CMD_CREATE_STATE); + + vic_wait_till_idle(hrng); + max = min_t(size_t, max, VIC_RAND_LEN * 4); + + writel(0x0, hrng->base + VIC_MODE); + vic_trng_cmd(hrng, VIC_CTRL_CMD_GEN_RANDOM); + + vic_wait_till_idle(hrng); + memcpy_fromio(buf, hrng->base + VIC_RAND0, max); + vic_trng_cmd(hrng, VIC_CTRL_CMD_ZEROIZE); + + vic_wait_till_idle(hrng); + return max; +} + +static int vic_rng_probe(struct device_d *dev) +{ + struct vic_rng *hrng; + struct resource *res; + + hrng = xzalloc(sizeof(*hrng)); + + res = dev_request_mem_resource(dev, 0); + if (IS_ERR(res)) + return PTR_ERR(res); + + hrng->base = IOMEM(res->start); + hrng->dev = dev; + + hrng->rng.name = dev_name(dev); + hrng->rng.init = vic_rng_init; + hrng->rng.read = vic_rng_read; + + return hwrng_register(dev, &hrng->rng); +} + +static const struct of_device_id vic_rng_dt_ids[] = { + { .compatible = "starfive,vic-rng" }, + { /* sentinel */ } +}; + +static struct driver_d vic_rng_driver = { + .name = "vic-rng", + .probe = vic_rng_probe, + .of_compatible = vic_rng_dt_ids, +}; +device_platform_driver(vic_rng_driver); + +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Huan Feng <huan.feng@starfivetech.com>"); +MODULE_DESCRIPTION("Starfive VIC random number generator driver"); diff --git a/drivers/mci/dw_mmc.c b/drivers/mci/dw_mmc.c index 930b538adc..b402090ab3 100644 --- a/drivers/mci/dw_mmc.c +++ b/drivers/mci/dw_mmc.c @@ -17,6 +17,7 @@ #include <io.h> #include <platform_data/dw_mmc.h> #include <linux/bitops.h> +#include <linux/reset.h> #include <linux/clk.h> #include <linux/err.h> #include <errno.h> @@ -31,7 +32,7 @@ struct dwmci_host { unsigned int fifo_size_bytes; struct dwmci_idmac *idmac; - unsigned long clkrate; + u32 clkrate; int ciu_div; u32 fifoth_val; u32 pwren_value; @@ -548,6 +549,7 @@ static int dwmci_init(struct mci_host *mci, struct device_d *dev) static int dw_mmc_probe(struct device_d *dev) { + struct reset_control *rst; struct resource *iores; struct dwmci_host *host; struct dw_mmc_platform_data *pdata = dev->platform_data; @@ -568,6 +570,15 @@ static int dw_mmc_probe(struct device_d *dev) clk_enable(host->clk_biu); clk_enable(host->clk_ciu); + rst = reset_control_get(dev, "reset"); + if (IS_ERR(rst)) { + return PTR_ERR(rst); + } else if (rst) { + reset_control_assert(rst); + udelay(10); + reset_control_deassert(rst); + } + iores = dev_request_mem_resource(dev, 0); if (IS_ERR(iores)) return PTR_ERR(iores); @@ -606,7 +617,11 @@ static int dw_mmc_probe(struct device_d *dev) else host->pwren_value = 1; - host->clkrate = clk_get_rate(host->clk_ciu); + if (of_device_is_compatible(dev->device_node, "starfive,jh7100-dw-mshc")) + of_property_read_u32(dev->device_node, "clock-frequency", &host->clkrate); + if (!host->clkrate) + host->clkrate = clk_get_rate(host->clk_ciu); + host->mci.f_min = host->clkrate / 510 / host->ciu_div; if (host->mci.f_min < 200000) host->mci.f_min = 200000; @@ -625,6 +640,10 @@ static __maybe_unused struct of_device_id dw_mmc_compatible[] = { }, { .compatible = "rockchip,rk3288-dw-mshc", }, { + .compatible = "snps,dw-mshc", + }, { + .compatible = "starfive,jh7100-dw-mshc", + }, { /* sentinel */ } }; diff --git a/drivers/mci/mci-core.c b/drivers/mci/mci-core.c index a094f3cbf5..92a73c8f1d 100644 --- a/drivers/mci/mci-core.c +++ b/drivers/mci/mci-core.c @@ -21,6 +21,7 @@ #include <of.h> #include <linux/err.h> #include <linux/sizes.h> +#include <dma.h> #define MAX_BUFFER_NUMBER 0xffffffff @@ -1789,6 +1790,11 @@ static int mci_card_probe(struct mci *mci) mci->cdevname = basprintf("disk%d", disknum); } + if (!sector_buf) + sector_buf = dma_alloc(SECTOR_SIZE); + + /* FIXME we don't check sector_buf against the device dma mask here */ + rc = mci_startup(mci); if (rc) { dev_warn(&mci->dev, "Card's startup fails with %d\n", rc); @@ -1850,15 +1856,6 @@ static int mci_set_probe(struct param_d *param, void *priv) return 0; } -static int mci_init(void) -{ - sector_buf = xmemalign(32, SECTOR_SIZE); - - return 0; -} - -device_initcall(mci_init); - int mci_detect_card(struct mci_host *host) { int rc; diff --git a/drivers/misc/Kconfig b/drivers/misc/Kconfig index 87674a2a29..7426dfc463 100644 --- a/drivers/misc/Kconfig +++ b/drivers/misc/Kconfig @@ -42,4 +42,14 @@ config ACPI_TEST help This is a simple Test driver to test the ACPI bus. +config STARFIVE_PWRSEQ + bool "StarFive power sequencing driver" + depends on SOC_STARFIVE + help + This driver sets up a number of StarFive peripherals not matched + by more specific barebox drivers by deasserting reset lines, muxing + pins and/or enabling clocks. Peripherals set up by this can then + be accessed over /dev/mem or used from kernels which still depend + on bootloader for initialization. + endmenu diff --git a/drivers/misc/Makefile b/drivers/misc/Makefile index 4d92465a1e..36743e6ae6 100644 --- a/drivers/misc/Makefile +++ b/drivers/misc/Makefile @@ -8,3 +8,4 @@ obj-$(CONFIG_STATE_DRV) += state.o obj-$(CONFIG_DEV_MEM) += mem.o obj-$(CONFIG_UBOOTVAR) += ubootvar.o obj-$(CONFIG_ACPI_TEST) += acpi-test.o +obj-$(CONFIG_STARFIVE_PWRSEQ) += starfive-pwrseq.o diff --git a/drivers/misc/starfive-pwrseq.c b/drivers/misc/starfive-pwrseq.c new file mode 100644 index 0000000000..6236547bc5 --- /dev/null +++ b/drivers/misc/starfive-pwrseq.c @@ -0,0 +1,92 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (c) 2021 Ahmad Fatoum, Pengutronix + */ + +#include <driver.h> +#include <init.h> +#include <linux/reset.h> +#include <dt-bindings/clock/starfive-jh7100.h> +#include <linux/clk.h> + +struct starfive_pwrseq { + const char **names; +}; + +static int starfive_pwrseq_probe(struct device_d *dev) +{ + int ret; + + ret = device_reset_all(dev); + if (ret) + return ret; + + return of_platform_populate(dev->device_node, NULL, dev); +} + +static struct of_device_id starfive_pwrseq_dt_ids[] = { + { .compatible = "starfive,axi-dma" }, + { .compatible = "cm,cm521-vpu" }, + { .compatible = "starfive,vic-sec" }, + { .compatible = "sfc,tempsensor" }, + { .compatible = "cm,codaj12-jpu-1" }, + { .compatible = "cdns,xrp" }, + { .compatible = "starfive,nne50" }, + { .compatible = "nvidia,nvdla_os_initial" }, + { .compatible = "starfive,spi2ahb" }, + { /* sentinel */ } +}; + +static struct driver_d starfive_pwrseq_driver = { + .name = "starfive_pwrseq", + .probe = starfive_pwrseq_probe, + .of_compatible = starfive_pwrseq_dt_ids, +}; + +static const int clks[] = { + CLK_VDEC_AXI, CLK_VDECBRG_MAIN, CLK_VDEC_BCLK, CLK_VDEC_CCLK, CLK_VDEC_APB, + CLK_JPEG_AXI, CLK_JPEG_CCLK, CLK_JPEG_APB, + CLK_DLA_AXI, CLK_DLANOC_AXI, CLK_DLA_APB, CLK_NNENOC_AXI, CLK_DLASLV_AXI, + CLK_VENC_AXI, CLK_VENCBRG_MAIN, CLK_VENC_BCLK, CLK_VENC_CCLK, CLK_VENC_APB, + CLK_SGDMA1P_AXI, + CLK_DMA2PNOC_AXI, CLK_SGDMA2P_AXI, CLK_SGDMA2P_AHB, + CLK_SDIO0_AHB, + CLK_SDIO1_AHB, + CLK_SPI2AHB_AHB, CLK_SPI2AHB_CORE, + CLK_EZMASTER_AHB, + CLK_SEC_AHB, CLK_AES, CLK_SHA, CLK_PKA, + CLK_UART0_APB, CLK_UART0_CORE, + CLK_UART1_APB, CLK_UART1_CORE, + CLK_UART2_APB, CLK_UART2_CORE, + CLK_UART3_APB, CLK_UART3_CORE, + CLK_SPI0_APB, CLK_SPI0_CORE, + CLK_SPI1_APB, CLK_SPI1_CORE, + CLK_SPI2_APB, CLK_SPI2_CORE, + CLK_SPI3_APB, CLK_SPI3_CORE, + CLK_I2C0_APB, CLK_I2C0_CORE, + CLK_I2C1_APB, CLK_I2C1_CORE, + CLK_I2C2_APB, CLK_I2C2_CORE, + CLK_I2C3_APB, CLK_I2C3_CORE, + CLK_VP6INTC_APB, + CLK_TEMP_APB, CLK_TEMP_SENSE, + + CLK_END +}; + +static int __init starfive_pwrseq_driver_register(void) +{ + struct of_phandle_args clkspec; + int i; + + clkspec.args_count = 1; + clkspec.np = of_find_compatible_node(NULL, NULL, "starfive,jh7100-clkgen"); + if (clkspec.np) { + for (i = 0; clks[i] != CLK_END; i++) { + clkspec.args[0] = clks[i]; + clk_enable(of_clk_get_from_provider(&clkspec)); + } + } + + return platform_driver_register(&starfive_pwrseq_driver); +} +device_initcall(starfive_pwrseq_driver_register); diff --git a/drivers/net/Kconfig b/drivers/net/Kconfig index 18931211b5..802169a86e 100644 --- a/drivers/net/Kconfig +++ b/drivers/net/Kconfig @@ -82,6 +82,14 @@ config DRIVER_NET_DESIGNWARE_SOCFPGA This option enables support for the Synopsys Designware Core Univesal MAC 10M/100M/1G ethernet IP on SoCFPGA. +config DRIVER_NET_DESIGNWARE_STARFIVE + bool "Designware Universal MAC ethernet driver for StarFive platforms" + depends on SOC_STARFIVE || COMPILE_TEST + select MFD_SYSCON + help + This option enables support for the Synopsys + Designware Core Univesal MAC 10M/100M/1G ethernet IP on StarFive. + endif config DRIVER_NET_DESIGNWARE_EQOS diff --git a/drivers/net/Makefile b/drivers/net/Makefile index 1674d53dff..fb3e3bdee4 100644 --- a/drivers/net/Makefile +++ b/drivers/net/Makefile @@ -11,6 +11,7 @@ obj-$(CONFIG_DRIVER_NET_DAVINCI_EMAC) += davinci_emac.o obj-$(CONFIG_DRIVER_NET_DESIGNWARE) += designware.o obj-$(CONFIG_DRIVER_NET_DESIGNWARE_GENERIC) += designware_generic.o obj-$(CONFIG_DRIVER_NET_DESIGNWARE_SOCFPGA) += designware_socfpga.o +obj-$(CONFIG_DRIVER_NET_DESIGNWARE_STARFIVE) += designware_starfive.o obj-$(CONFIG_DRIVER_NET_DESIGNWARE_EQOS) += designware_eqos.o obj-$(CONFIG_DRIVER_NET_DESIGNWARE_STM32) += designware_stm32.o obj-$(CONFIG_DRIVER_NET_DESIGNWARE_TEGRA186) += designware_tegra186.o diff --git a/drivers/net/designware.c b/drivers/net/designware.c index 0ee6d3d78a..afc275e81e 100644 --- a/drivers/net/designware.c +++ b/drivers/net/designware.c @@ -104,15 +104,15 @@ static void tx_descs_init(struct eth_device *dev) { struct dw_eth_dev *priv = dev->priv; struct eth_dma_regs *dma_p = priv->dma_regs_p; - struct dmamacdescr *desc_table_p = &priv->tx_mac_descrtable[0]; + struct dmamacdescr *desc_table_p = &priv->tx_mac_descrtable_cpu[0]; char *txbuffs = &priv->txbuffs[0]; struct dmamacdescr *desc_p; u32 idx; for (idx = 0; idx < CONFIG_TX_DESCR_NUM; idx++) { desc_p = &desc_table_p[idx]; - desc_p->dmamac_addr = &txbuffs[idx * CONFIG_ETH_BUFSIZE]; - desc_p->dmamac_next = &desc_table_p[idx + 1]; + desc_p->dmamac_addr = virt_to_phys(&txbuffs[idx * CONFIG_ETH_BUFSIZE]); + desc_p->dmamac_next = tx_dma_addr(priv, &desc_table_p[idx + 1]); if (priv->enh_desc) { desc_p->txrx_status &= ~(DESC_ENH_TXSTS_TXINT | DESC_ENH_TXSTS_TXLAST | @@ -130,9 +130,9 @@ static void tx_descs_init(struct eth_device *dev) } /* Correcting the last pointer of the chain */ - desc_p->dmamac_next = &desc_table_p[0]; + desc_p->dmamac_next = tx_dma_addr(priv, &desc_table_p[0]); - writel((ulong)&desc_table_p[0], &dma_p->txdesclistaddr); + writel(desc_p->dmamac_next, &dma_p->txdesclistaddr); priv->tx_currdescnum = 0; } @@ -140,15 +140,15 @@ static void rx_descs_init(struct eth_device *dev) { struct dw_eth_dev *priv = dev->priv; struct eth_dma_regs *dma_p = priv->dma_regs_p; - struct dmamacdescr *desc_table_p = &priv->rx_mac_descrtable[0]; + struct dmamacdescr *desc_table_p = &priv->rx_mac_descrtable_cpu[0]; char *rxbuffs = &priv->rxbuffs[0]; struct dmamacdescr *desc_p; u32 idx; for (idx = 0; idx < CONFIG_RX_DESCR_NUM; idx++) { desc_p = &desc_table_p[idx]; - desc_p->dmamac_addr = &rxbuffs[idx * CONFIG_ETH_BUFSIZE]; - desc_p->dmamac_next = &desc_table_p[idx + 1]; + desc_p->dmamac_addr = virt_to_phys(&rxbuffs[idx * CONFIG_ETH_BUFSIZE]); + desc_p->dmamac_next = rx_dma_addr(priv, &desc_table_p[idx + 1]); desc_p->dmamac_cntl = MAC_MAX_FRAME_SZ; if (priv->enh_desc) @@ -156,15 +156,15 @@ static void rx_descs_init(struct eth_device *dev) else desc_p->dmamac_cntl |= DESC_RXCTRL_RXCHAIN; - dma_sync_single_for_cpu((unsigned long)desc_p->dmamac_addr, + dma_sync_single_for_cpu(desc_p->dmamac_addr, CONFIG_ETH_BUFSIZE, DMA_FROM_DEVICE); desc_p->txrx_status = DESC_RXSTS_OWNBYDMA; } /* Correcting the last pointer of the chain */ - desc_p->dmamac_next = &desc_table_p[0]; + desc_p->dmamac_next = rx_dma_addr(priv, &desc_table_p[0]); - writel((ulong)&desc_table_p[0], &dma_p->rxdesclistaddr); + writel(desc_p->dmamac_next, &dma_p->rxdesclistaddr); priv->rx_currdescnum = 0; } @@ -276,7 +276,7 @@ static int dwc_ether_send(struct eth_device *dev, void *packet, int length) struct dw_eth_dev *priv = dev->priv; struct eth_dma_regs *dma_p = priv->dma_regs_p; u32 owndma, desc_num = priv->tx_currdescnum; - struct dmamacdescr *desc_p = &priv->tx_mac_descrtable[desc_num]; + struct dmamacdescr *desc_p = &priv->tx_mac_descrtable_cpu[desc_num]; owndma = priv->enh_desc ? DESC_ENH_TXSTS_OWNBYDMA : DESC_TXSTS_OWNBYDMA; /* Check if the descriptor is owned by CPU */ @@ -285,8 +285,8 @@ static int dwc_ether_send(struct eth_device *dev, void *packet, int length) return -1; } - memcpy((void *)desc_p->dmamac_addr, packet, length); - dma_sync_single_for_device((unsigned long)desc_p->dmamac_addr, length, + memcpy(dmamac_addr(desc_p), packet, length); + dma_sync_single_for_device(desc_p->dmamac_addr, length, DMA_TO_DEVICE); if (priv->enh_desc) { @@ -314,7 +314,7 @@ static int dwc_ether_send(struct eth_device *dev, void *packet, int length) /* Start the transmission */ writel(POLL_DATA, &dma_p->txpolldemand); - dma_sync_single_for_cpu((unsigned long)desc_p->dmamac_addr, length, + dma_sync_single_for_cpu(desc_p->dmamac_addr, length, DMA_TO_DEVICE); return 0; @@ -324,7 +324,7 @@ static int dwc_ether_rx(struct eth_device *dev) { struct dw_eth_dev *priv = dev->priv; u32 desc_num = priv->rx_currdescnum; - struct dmamacdescr *desc_p = &priv->rx_mac_descrtable[desc_num]; + struct dmamacdescr *desc_p = &priv->rx_mac_descrtable_cpu[desc_num]; u32 status = desc_p->txrx_status; int length = 0; @@ -358,10 +358,10 @@ static int dwc_ether_rx(struct eth_device *dev) length = (status & DESC_RXSTS_FRMLENMSK) >> DESC_RXSTS_FRMLENSHFT; - dma_sync_single_for_cpu((unsigned long)desc_p->dmamac_addr, + dma_sync_single_for_cpu(desc_p->dmamac_addr, length, DMA_FROM_DEVICE); - net_receive(dev, desc_p->dmamac_addr, length); - dma_sync_single_for_device((unsigned long)desc_p->dmamac_addr, + net_receive(dev, dmamac_addr(desc_p), length); + dma_sync_single_for_device(desc_p->dmamac_addr, length, DMA_FROM_DEVICE); ret = length; } @@ -451,17 +451,20 @@ struct dw_eth_dev *dwc_drv_probe(struct device_d *dev) int ret; struct dw_eth_drvdata *drvdata; + dma_set_mask(dev, DMA_BIT_MASK(32)); + priv = xzalloc(sizeof(struct dw_eth_dev)); ret = dev_get_drvdata(dev, (const void **)&drvdata); if (ret) return ERR_PTR(ret); - if (drvdata && drvdata->enh_desc) + if (drvdata) { priv->enh_desc = drvdata->enh_desc; - else + priv->fix_mac_speed = drvdata->fix_mac_speed; + } else { dev_warn(dev, "No drvdata specified\n"); - + } if (pdata) { priv->phy_addr = pdata->phy_addr; @@ -481,12 +484,21 @@ struct dw_eth_dev *dwc_drv_probe(struct device_d *dev) priv->mac_regs_p = base; dwc_version(dev, readl(&priv->mac_regs_p->version)); priv->dma_regs_p = base + DW_DMA_BASE_OFFSET; - priv->tx_mac_descrtable = dma_alloc_coherent( + + priv->tx_mac_descrtable_cpu = dma_alloc_coherent( CONFIG_TX_DESCR_NUM * sizeof(struct dmamacdescr), - DMA_ADDRESS_BROKEN); - priv->rx_mac_descrtable = dma_alloc_coherent( + &priv->tx_mac_descrtable_dev); + + if (dma_mapping_error(dev, priv->tx_mac_descrtable_dev)) + return ERR_PTR(-EFAULT); + + priv->rx_mac_descrtable_cpu = dma_alloc_coherent( CONFIG_RX_DESCR_NUM * sizeof(struct dmamacdescr), - DMA_ADDRESS_BROKEN); + &priv->rx_mac_descrtable_dev); + + if (dma_mapping_error(dev, priv->rx_mac_descrtable_dev)) + return ERR_PTR(-EFAULT); + priv->txbuffs = dma_alloc(TX_TOTAL_BUFSIZE); priv->rxbuffs = dma_alloc(RX_TOTAL_BUFSIZE); diff --git a/drivers/net/designware.h b/drivers/net/designware.h index 0a6a6bf1a4..8f6234aec5 100644 --- a/drivers/net/designware.h +++ b/drivers/net/designware.h @@ -8,6 +8,7 @@ #define __DESIGNWARE_ETH_H #include <net.h> +#include <linux/types.h> struct dw_eth_dev { struct eth_device netdev; @@ -18,8 +19,11 @@ struct dw_eth_dev { u32 tx_currdescnum; u32 rx_currdescnum; - struct dmamacdescr *tx_mac_descrtable; - struct dmamacdescr *rx_mac_descrtable; + struct dmamacdescr *tx_mac_descrtable_cpu; + struct dmamacdescr *rx_mac_descrtable_cpu; + + dma_addr_t tx_mac_descrtable_dev; + dma_addr_t rx_mac_descrtable_dev; u8 *txbuffs; u8 *rxbuffs; @@ -35,9 +39,24 @@ struct dw_eth_dev { struct dw_eth_drvdata { bool enh_desc; + void (*fix_mac_speed)(int speed); void *priv; }; +static inline dma_addr_t tx_dma_addr(struct dw_eth_dev *priv, + struct dmamacdescr *desc) +{ + return priv->tx_mac_descrtable_dev + + ((u8 *)desc - (u8 *)priv->tx_mac_descrtable_cpu); +} + +static inline dma_addr_t rx_dma_addr(struct dw_eth_dev *priv, + struct dmamacdescr *desc) +{ + return priv->rx_mac_descrtable_dev + + ((u8 *)desc - (u8 *)priv->rx_mac_descrtable_cpu); +} + struct dw_eth_dev *dwc_drv_probe(struct device_d *dev); void dwc_drv_remove(struct device_d *dev); @@ -138,10 +157,12 @@ struct eth_dma_regs { struct dmamacdescr { u32 txrx_status; u32 dmamac_cntl; - void *dmamac_addr; - struct dmamacdescr *dmamac_next; + u32 dmamac_addr; + u32 dmamac_next; }; +#define dmamac_addr(descr) (phys_to_virt((descr)->dmamac_addr)) + /* * txrx_status definitions */ diff --git a/drivers/net/designware_starfive.c b/drivers/net/designware_starfive.c new file mode 100644 index 0000000000..3dc9d14e11 --- /dev/null +++ b/drivers/net/designware_starfive.c @@ -0,0 +1,110 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +/* + * Copyright (c) 2021 Ahmad Fatoum, Pengutronix + */ + +#include <common.h> +#include <init.h> +#include <linux/reset.h> +#include <linux/clk.h> +#include <mfd/syscon.h> +#include <soc/starfive/sysmain.h> +#include "designware.h" + +/* + * GMAC_GTXCLK + * bit name access default description + * [31] _gmac_gtxclk enable RW 0x0 "1:enable; 0:disable" + * [30] reserved - 0x0 reserved + * [29:8] reserved - 0x0 reserved + * [7:0] gmac_gtxclk ratio RW 0x4 divider value + * + * 1000M: gtxclk@125M => 500/125 = 0x4 + * 100M: gtxclk@25M => 500/25 = 0x14 + * 10M: gtxclk@2.5M => 500/2.5 = 0xc8 + */ + +#define CLKGEN_BASE 0x11800000 +#define CLKGEN_GMAC_GTXCLK_OFFSET 0x1EC +#define CLKGEN_GMAC_GTXCLK_ADDR (CLKGEN_BASE + CLKGEN_GMAC_GTXCLK_OFFSET) + + +#define CLKGEN_125M_DIV 0x4 +#define CLKGEN_25M_DIV 0x14 +#define CLKGEN_2_5M_DIV 0xc8 + +static void dwmac_fixed_speed(int speed) +{ + /* TODO: move this into clk driver */ + void __iomem *addr = IOMEM(CLKGEN_GMAC_GTXCLK_ADDR); + u32 value; + + value = readl(addr) & (~0x000000FF); + + switch (speed) { + case SPEED_1000: value |= CLKGEN_125M_DIV; break; + case SPEED_100: value |= CLKGEN_25M_DIV; break; + case SPEED_10: value |= CLKGEN_2_5M_DIV; break; + default: return; + } + + writel(value, addr); +} + +static struct dw_eth_drvdata starfive_drvdata = { + .enh_desc = 1, + .fix_mac_speed = dwmac_fixed_speed, +}; + +static int starfive_dwc_ether_probe(struct device_d *dev) +{ + struct dw_eth_dev *dwc; + struct regmap *regmap; + int ret; + struct clk_bulk_data clks[] = { + { .id = "stmmaceth" }, + { .id = "ptp_ref" }, + { .id = "tx" }, + }; + + regmap = syscon_regmap_lookup_by_phandle(dev->device_node, "starfive,sysmain"); + if (IS_ERR(regmap)) { + dev_err(dev, "Could not get starfive,sysmain node\n"); + return PTR_ERR(regmap); + } + + ret = clk_bulk_get(dev, ARRAY_SIZE(clks), clks); + if (ret) + return ret; + + ret = clk_bulk_enable(ARRAY_SIZE(clks), clks); + if (ret < 0) + return ret; + + ret = device_reset(dev); + if (ret) + return ret; + + dwc = dwc_drv_probe(dev); + if (IS_ERR(dwc)) + return PTR_ERR(dwc); + + if (phy_interface_mode_is_rgmii(dwc->interface)) { + regmap_update_bits(regmap, SYSMAIN_GMAC_PHY_INTF_SEL, 0x7, 0x1); + regmap_write(regmap, SYSMAIN_GMAC_GTXCLK_DLYCHAIN_SEL, 0x4); + } + + return 0; +} + +static struct of_device_id starfive_dwc_ether_compatible[] = { + { .compatible = "starfive,stmmac", .data = &starfive_drvdata }, + { /* sentinel */ } +}; + +static struct driver_d starfive_dwc_ether_driver = { + .name = "starfive-designware_eth", + .probe = starfive_dwc_ether_probe, + .of_compatible = starfive_dwc_ether_compatible, +}; +device_platform_driver(starfive_dwc_ether_driver); diff --git a/drivers/nvmem/Kconfig b/drivers/nvmem/Kconfig index 0d7c0b7b9e..3781f7a839 100644 --- a/drivers/nvmem/Kconfig +++ b/drivers/nvmem/Kconfig @@ -65,4 +65,12 @@ config STM32_BSEC This adds support for the STM32 OTP controller. Reads and writes to will go to the shadow RAM, not the OTP fuses themselvers. +config STARFIVE_OTP + tristate "Starfive OTP Supprot" + depends on SOC_STARFIVE + depends on OFDEVICE + help + This adds support for the StarFive OTP controller. Only reading + is currently supported. + endif diff --git a/drivers/nvmem/Makefile b/drivers/nvmem/Makefile index 53c02dc785..55507f5441 100644 --- a/drivers/nvmem/Makefile +++ b/drivers/nvmem/Makefile @@ -22,3 +22,5 @@ nvmem_eeprom_93xx46-y := eeprom_93xx46.o obj-$(CONFIG_STM32_BSEC) += nvmem_bsec.o nvmem_bsec-y := bsec.o + +obj-$(CONFIG_STARFIVE_OTP) += starfive-otp.o diff --git a/drivers/nvmem/starfive-otp.c b/drivers/nvmem/starfive-otp.c new file mode 100644 index 0000000000..f9bf05ca87 --- /dev/null +++ b/drivers/nvmem/starfive-otp.c @@ -0,0 +1,201 @@ +// SPDX_License-Identifier: GPL-2.0 +/* + * Copyright 2021 StarFive, Inc + */ + +#include <common.h> +#include <driver.h> +#include <malloc.h> +#include <xfuncs.h> +#include <errno.h> +#include <gpiod.h> +#include <init.h> +#include <net.h> +#include <io.h> +#include <of.h> +#include <regmap.h> +#include <machine_id.h> +#include <linux/reset.h> +#include <linux/clk.h> +#include <linux/nvmem-provider.h> + +// otp reg offset +#define OTP_CFGR 0x00 +#define OTPC_IER 0x04 +#define OTPC_SRR 0x08 +#define OTP_OPRR 0x0c +#define OTPC_CTLR 0x10 +#define OTPC_ADDRR 0x14 +#define OTPC_DINR 0x18 +#define OTPC_DOUTR 0x1c + +#define OTP_EMPTY_CELL_VALUE 0xffffffffUL + +// cfgr (offset 0x00) +#define OTP_CFGR_PRG_CNT_MASK 0xff +#define OTP_CFGR_PRG_CNT_SHIFT 0 +#define OTP_CFGR_DIV_1US_MASK 0xff +#define OTP_CFGR_DIV_1US_SHIFT 8 +#define OTP_CFGR_RD_CYC_MASK 0x0f +#define OTP_CFGR_RD_CYC_SHIFT 16 + +// ier (offset 0x04) +#define OTPC_IER_DONE_IE BIT(0) +#define OTPC_IER_BUSY_OPR_IE BIT(1) + +// srr (offset 0x08) +#define OTPC_SRR_DONE BIT(0) +#define OTPC_SRR_BUSY_OPR BIT(1) +#define OTPC_SRR_INFO_RD_LOCK BIT(29) +#define OTPC_SRR_INFO_WR_LOCK BIT(30) +#define OTPC_SRR_BUSY BIT(31) + +// oprr (offset 0x0c) +#define OTP_OPRR_OPR_MASK 0x00000007 +#define OTP_OPRR_OPR_SHIFT 0 + +#define OTP_OPR_STANDBY 0x0 // user mode +#define OTP_OPR_READ 0x1 // user mode +#define OTP_OPR_MARGIN_READ_PROG 0x2 // testing mode +#define OTP_OPR_MARGIN_READ_INIT 0x3 // testing mode +#define OTP_OPR_PROGRAM 0x4 // user mode +#define OTP_OPR_DEEP_STANDBY 0x5 // user mode +#define OTP_OPR_DEBUG 0x6 // user mode + +// ctlr (offset 0x10, see EG512X32TH028CW01_v1.0.pdf "Pin Description") +#define OTPC_CTLR_PCE BIT(0) +#define OTPC_CTLR_PTM_MASK 0x0000000e +#define OTPC_CTLR_PTM_SHIFT 1 +#define OTPC_CTLR_PDSTB BIT(4) +#define OTPC_CTLR_PTR BIT(5) +#define OTPC_CTLR_PPROG BIT(6) +#define OTPC_CTLR_PWE BIT(7) +#define OTPC_CTLR_PCLK BIT(8) + +// addrr (offset 0x14) +#define OTPC_ADDRR_PA_MASK 0x000001ff +#define OTPC_ADDRR_PA_SHIFT 0 + +/* + * data format: + * struct starfive_otp_data{ + * char vendor[32]; + * uint64_t sn; + * uint8_t mac_addr[6]; + * uint8_t padding_0[2]; + * } + */ + +struct starfive_otp { + int power_gpio; + struct starfive_otp_regs __iomem *regs; +}; + +struct starfive_otp_regs { + /* TODO: add otp ememory_eg512x32 registers define */ + u32 otp_cfg; /* timing Register */ + u32 otpc_ie; /* interrupt Enable */ + u32 otpc_sr; /* status Register */ + u32 otp_opr; /* operation mode select Register */ + u32 otpc_ctl; /* otp control port */ + u32 otpc_addr; /* otp pa port */ + u32 otpc_din; /* otp pdin port */ + u32 otpc_dout; /* otp pdout */ + u32 reserved[504]; + u32 mem[512]; +}; + +/* + * offset and size are assumed aligned to the size of the fuses (32-bit). + */ +static int starfive_otp_read(void *ctx, unsigned offset, unsigned *val) +{ + struct starfive_otp *priv = ctx; + + gpio_set_active(priv->power_gpio, true); + mdelay(10); + + //otp set to read mode + writel(OTP_OPR_READ, &priv->regs->otp_opr); + mdelay(5); + + /* read all requested fuses */ + *val = readl(&priv->regs->mem[offset / 4]); + + gpio_set_active(priv->power_gpio, false); + mdelay(5); + + return 0; +} + +static int starfive_otp_write(void *ctx, unsigned offset, unsigned val) +{ + return -EOPNOTSUPP; +} + +static struct regmap_bus starfive_otp_regmap_bus = { + .reg_read = starfive_otp_read, + .reg_write = starfive_otp_write, +}; + +static int starfive_otp_probe(struct device_d *dev) +{ + struct starfive_otp *priv; + struct regmap_config config = {}; + struct resource *iores; + struct regmap *map; + struct clk *clk; + u32 total_fuses; + int ret; + + clk = clk_get(dev, NULL); + if (IS_ERR(clk)) + return PTR_ERR(clk); + + clk_enable(clk); + + ret = device_reset(dev); + if (ret) + return ret; + + iores = dev_request_mem_resource(dev, 0); + if (IS_ERR(iores)) + return PTR_ERR(iores); + + ret = of_property_read_u32(dev->device_node, "fuse-count", &total_fuses); + if (ret < 0) { + dev_err(dev, "missing required fuse-count property\n"); + return ret; + } + + config.name = "starfive-otp"; + config.reg_bits = 32; + config.val_bits = 32; + config.reg_stride = 4; + config.max_register = total_fuses; + + priv = xzalloc(sizeof(*priv)); + + priv->regs = IOMEM(iores->start); + priv->power_gpio = gpiod_get(dev, "power", GPIOD_OUT_LOW); + if (priv->power_gpio < 0) + return priv->power_gpio; + + map = regmap_init(dev, &starfive_otp_regmap_bus, priv, &config); + if (IS_ERR(map)) + return PTR_ERR(map); + + return PTR_ERR_OR_ZERO(nvmem_regmap_register(map, "starfive-otp")); +} + +static struct of_device_id starfive_otp_dt_ids[] = { + { .compatible = "starfive,fu740-otp" }, + { /* sentinel */ } +}; + +static struct driver_d starfive_otp_driver = { + .name = "starfive_otp", + .probe = starfive_otp_probe, + .of_compatible = starfive_otp_dt_ids, +}; +device_platform_driver(starfive_otp_driver); diff --git a/drivers/pinctrl/pinctrl-single.c b/drivers/pinctrl/pinctrl-single.c index c774660232..cf2f724d18 100644 --- a/drivers/pinctrl/pinctrl-single.c +++ b/drivers/pinctrl/pinctrl-single.c @@ -128,7 +128,7 @@ static struct pinctrl_ops pcs_ops = { .set_state = pcs_set_state, }; -static int pcs_probe(struct device_d *dev) +int pinctrl_single_probe(struct device_d *dev) { struct resource *iores; struct pinctrl_single *pcs; @@ -215,7 +215,7 @@ static __maybe_unused struct of_device_id pcs_dt_ids[] = { static struct driver_d pcs_driver = { .name = "pinctrl-single", - .probe = pcs_probe, + .probe = pinctrl_single_probe, .of_compatible = DRV_OF_COMPAT(pcs_dt_ids), }; diff --git a/drivers/reset/Kconfig b/drivers/reset/Kconfig index 316ece9e71..9429f107bb 100644 --- a/drivers/reset/Kconfig +++ b/drivers/reset/Kconfig @@ -27,4 +27,10 @@ config RESET_STM32 help This enables the reset controller driver for STM32MP and STM32 MCUs. +config RESET_STARFIVE + bool "StarFive Controller Driver" if COMPILE_TEST + default SOC_STARFIVE + help + This enables the reset controller driver for the StarFive JH7100. + endif diff --git a/drivers/reset/Makefile b/drivers/reset/Makefile index 8460c4b154..ce494baae5 100644 --- a/drivers/reset/Makefile +++ b/drivers/reset/Makefile @@ -2,3 +2,4 @@ obj-$(CONFIG_RESET_CONTROLLER) += core.o obj-$(CONFIG_ARCH_SOCFPGA) += reset-socfpga.o obj-$(CONFIG_RESET_IMX7) += reset-imx7.o obj-$(CONFIG_RESET_STM32) += reset-stm32.o +obj-$(CONFIG_RESET_STARFIVE) += reset-starfive-vic.o diff --git a/drivers/reset/core.c b/drivers/reset/core.c index 1dd071635f..9f5a642539 100644 --- a/drivers/reset/core.c +++ b/drivers/reset/core.c @@ -139,30 +139,35 @@ int reset_control_deassert(struct reset_control *rstc) EXPORT_SYMBOL_GPL(reset_control_deassert); /** - * of_reset_control_get - Lookup and obtain a reference to a reset controller. + * of_reset_control_count - Count reset lines + * @node: device node + * + * Returns number of resets, 0 if none specified + */ +static int of_reset_control_count(struct device_node *node) +{ + return of_count_phandle_with_args(node, "resets", "#reset-cells"); +} + +/** + * of_reset_control_get_by_index - Lookup and obtain a reference to a reset controller. * @node: device to be reset by the controller - * @id: reset line name + * @index: reset line index * * Returns a struct reset_control or IS_ERR() condition containing errno. - * - * Use of id names is optional. */ -struct reset_control *of_reset_control_get(struct device_node *node, - const char *id) +static struct reset_control *of_reset_control_get_by_index(struct device_node *node, + int index) { struct reset_control *rstc; struct reset_controller_dev *r, *rcdev; struct of_phandle_args args; - int index = 0; int rstc_id; int ret; if (!of_get_property(node, "resets", NULL)) return NULL; - if (id) - index = of_property_match_string(node, - "reset-names", id); ret = of_parse_phandle_with_args(node, "resets", "#reset-cells", index, &args); if (ret) @@ -199,6 +204,26 @@ struct reset_control *of_reset_control_get(struct device_node *node, return rstc; } +/** + * of_reset_control_get - Lookup and obtain a reference to a reset controller. + * @node: device to be reset by the controller + * @id: reset line name + * + * Returns a struct reset_control or IS_ERR() condition containing errno. + * + * Use of id names is optional. + */ +struct reset_control *of_reset_control_get(struct device_node *node, + const char *id) +{ + int index = 0; + + if (id) + index = of_property_match_string(node, "reset-names", id); + + return of_reset_control_get_by_index(node, index); +} + static struct reset_control * gpio_reset_control_get(struct device_d *dev, const char *id) { @@ -306,6 +331,39 @@ int device_reset(struct device_d *dev) } EXPORT_SYMBOL_GPL(device_reset); +int device_reset_all(struct device_d *dev) +{ + struct reset_control *rstc; + int ret, i; + + for (i = 0; i < of_reset_control_count(dev->device_node); i++) { + int ret; + + rstc = of_reset_control_get_by_index(dev->device_node, i); + if (IS_ERR(rstc)) + return PTR_ERR(rstc); + + ret = reset_control_reset(rstc); + if (ret) + return ret; + + reset_control_put(rstc); + } + + if (i == 0) { + rstc = gpio_reset_control_get(dev, NULL); + + ret = reset_control_reset(rstc); + if (ret) + return ret; + + reset_control_put(rstc); + } + + return 0; +} +EXPORT_SYMBOL_GPL(device_reset_all); + int device_reset_us(struct device_d *dev, int us) { struct reset_control *rstc; diff --git a/drivers/reset/reset-starfive-vic.c b/drivers/reset/reset-starfive-vic.c new file mode 100644 index 0000000000..bcf615da0a --- /dev/null +++ b/drivers/reset/reset-starfive-vic.c @@ -0,0 +1,234 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (c) 2021 Ahmad Fatoum, Pengutronix + * + * StarFive Reset Controller driver + */ +#define pr_fmt(fmt) "reset-starfive: " fmt + +#include <common.h> +#include <init.h> +#include <linux/clk.h> +#include <linux/err.h> +#include <linux/reset-controller.h> +#include <soc/starfive/rstgen.h> +#include <dt-bindings/reset-controller/starfive-jh7100.h> +#include <dt-bindings/clock/starfive-jh7100.h> + +struct starfive_rstgen { + void __iomem *base; + struct reset_controller_dev rcdev; + const struct starfive_rstgen_ops *ops; + struct device_node *clknp; + const int *sync_resets; +}; + +static struct starfive_rstgen *to_starfive_rstgen(struct reset_controller_dev *rcdev) +{ + return container_of(rcdev, struct starfive_rstgen, rcdev); +} + +static const int jh7110_rstgen_sync_resets[RSTN_END] = { + [RSTN_SGDMA2P_AHB] = CLK_SGDMA2P_AHB, + [RSTN_SGDMA2P_AXI] = CLK_SGDMA2P_AXI, + [RSTN_DMA2PNOC_AXI] = CLK_DMA2PNOC_AXI, + [RSTN_DLA_AXI] = CLK_DLA_AXI, + [RSTN_DLANOC_AXI] = CLK_DLANOC_AXI, + [RSTN_DLA_APB] = CLK_DLA_APB, + [RSTN_VDECBRG_MAIN] = CLK_VDECBRG_MAIN, + [RSTN_VDEC_AXI] = CLK_VDEC_AXI, + [RSTN_VDEC_BCLK] = CLK_VDEC_BCLK, + [RSTN_VDEC_CCLK] = CLK_VDEC_CCLK, + [RSTN_VDEC_APB] = CLK_VDEC_APB, + [RSTN_JPEG_AXI] = CLK_JPEG_AXI, + [RSTN_JPEG_CCLK] = CLK_JPEG_CCLK, + [RSTN_JPEG_APB] = CLK_JPEG_APB, + [RSTN_JPCGC300_MAIN] = CLK_JPCGC300_MAIN, + [RSTN_GC300_2X] = CLK_GC300_2X, + [RSTN_GC300_AXI] = CLK_GC300_AXI, + [RSTN_GC300_AHB] = CLK_GC300_AHB, + [RSTN_VENC_AXI] = CLK_VENC_AXI, + [RSTN_VENCBRG_MAIN] = CLK_VENCBRG_MAIN, + [RSTN_VENC_BCLK] = CLK_VENC_BCLK, + [RSTN_VENC_CCLK] = CLK_VENC_CCLK, + [RSTN_VENC_APB] = CLK_VENC_APB, + [RSTN_DDRPHY_APB] = CLK_DDRPHY_APB, + [RSTN_USB_AXI] = CLK_USB_AXI, + [RSTN_SGDMA1P_AXI] = CLK_SGDMA1P_AXI, + [RSTN_DMA1P_AXI] = CLK_DMA1P_AXI, + [RSTN_NNE_AHB] = CLK_NNE_AHB, + [RSTN_NNE_AXI] = CLK_NNE_AXI, + [RSTN_NNENOC_AXI] = CLK_NNENOC_AXI, + [RSTN_DLASLV_AXI] = CLK_DLASLV_AXI, + [RSTN_VOUT_SRC] = CLK_VOUT_SRC, + [RSTN_DISP_AXI] = CLK_DISP_AXI, + [RSTN_DISPNOC_AXI] = CLK_DISPNOC_AXI, + [RSTN_SDIO0_AHB] = CLK_SDIO0_AHB, + [RSTN_SDIO1_AHB] = CLK_SDIO1_AHB, + [RSTN_GMAC_AHB] = CLK_GMAC_AHB, + [RSTN_SPI2AHB_AHB] = CLK_SPI2AHB_AHB, + [RSTN_SPI2AHB_CORE] = CLK_SPI2AHB_CORE, + [RSTN_EZMASTER_AHB] = CLK_EZMASTER_AHB, + [RSTN_SEC_AHB] = CLK_SEC_AHB, + [RSTN_AES] = CLK_AES, + [RSTN_PKA] = CLK_PKA, + [RSTN_SHA] = CLK_SHA, + [RSTN_TRNG_APB] = CLK_TRNG_APB, + [RSTN_OTP_APB] = CLK_OTP_APB, + [RSTN_UART0_APB] = CLK_UART0_APB, + [RSTN_UART0_CORE] = CLK_UART0_CORE, + [RSTN_UART1_APB] = CLK_UART1_APB, + [RSTN_UART1_CORE] = CLK_UART1_CORE, + [RSTN_SPI0_APB] = CLK_SPI0_APB, + [RSTN_SPI0_CORE] = CLK_SPI0_CORE, + [RSTN_SPI1_APB] = CLK_SPI1_APB, + [RSTN_SPI1_CORE] = CLK_SPI1_CORE, + [RSTN_I2C0_APB] = CLK_I2C0_APB, + [RSTN_I2C0_CORE] = CLK_I2C0_CORE, + [RSTN_I2C1_APB] = CLK_I2C1_APB, + [RSTN_I2C1_CORE] = CLK_I2C1_CORE, + [RSTN_GPIO_APB] = CLK_GPIO_APB, + [RSTN_UART2_APB] = CLK_UART2_APB, + [RSTN_UART2_CORE] = CLK_UART2_CORE, + [RSTN_UART3_APB] = CLK_UART3_APB, + [RSTN_UART3_CORE] = CLK_UART3_CORE, + [RSTN_SPI2_APB] = CLK_SPI2_APB, + [RSTN_SPI2_CORE] = CLK_SPI2_CORE, + [RSTN_SPI3_APB] = CLK_SPI3_APB, + [RSTN_SPI3_CORE] = CLK_SPI3_CORE, + [RSTN_I2C2_APB] = CLK_I2C2_APB, + [RSTN_I2C2_CORE] = CLK_I2C2_CORE, + [RSTN_I2C3_APB] = CLK_I2C3_APB, + [RSTN_I2C3_CORE] = CLK_I2C3_CORE, + [RSTN_WDTIMER_APB] = CLK_WDTIMER_APB, + [RSTN_WDT] = CLK_WDT_CORE, + [RSTN_VP6INTC_APB] = CLK_VP6INTC_APB, + [RSTN_TEMP_APB] = CLK_TEMP_APB, + [RSTN_TEMP_SENSE] = CLK_TEMP_SENSE, +}; + +static struct clk *starfive_reset_clk_get(struct starfive_rstgen *priv, unsigned id) +{ + struct of_phandle_args clkspec = { + .np = priv->clknp, + .args_count = 1, + }; + + if (!priv->sync_resets || !priv->sync_resets[id]) + return 0; + + clkspec.args[0] = priv->sync_resets[id]; + + pr_debug("synchronous reset=%u clk=%u\n", id, priv->sync_resets[id]); + + return of_clk_get_from_provider(&clkspec); +} + +static int starfive_reset_clk_enable(struct starfive_rstgen *priv, unsigned id) +{ + return clk_enable(starfive_reset_clk_get(priv, id)); +} + +static void starfive_reset_clk_disable(struct starfive_rstgen *priv, unsigned id) +{ + clk_disable(starfive_reset_clk_get(priv, id)); +} + +static int starfive_rstgen(struct starfive_rstgen *priv, unsigned id, bool assert) +{ + void __iomem *base = priv->base; + + __starfive_rstgen(base, id, assert); + + return wait_on_timeout(NSEC_PER_MSEC, __starfive_rstgen_asserted(base, id) == assert); +} + +static int starfive_rstgen_assert(struct reset_controller_dev *rcdev, + unsigned long id) +{ + struct starfive_rstgen *priv = to_starfive_rstgen(rcdev); + int ret; + + starfive_reset_clk_enable(priv, id); + ret = starfive_rstgen(priv, id, true); + starfive_reset_clk_disable(priv, id); + + return ret; +} + +static int starfive_rstgen_deassert(struct reset_controller_dev *rcdev, + unsigned long id) +{ + struct starfive_rstgen *priv = to_starfive_rstgen(rcdev); + int ret; + + starfive_reset_clk_enable(priv, id); + ret = starfive_rstgen(priv, id, false); + starfive_reset_clk_disable(priv, id); + + return ret; +} + +static int starfive_reset(struct reset_controller_dev *rcdev, unsigned long id) +{ + struct starfive_rstgen *priv = to_starfive_rstgen(rcdev); + int ret; + + starfive_reset_clk_enable(priv, id); + + ret = starfive_rstgen(priv, id, true); + if (ret) + goto out; + + udelay(2); + + ret = starfive_rstgen(priv, id, false); + +out: + starfive_reset_clk_disable(priv, id); + + return ret; +} + +static const struct reset_control_ops starfive_rstgen_ops = { + .assert = starfive_rstgen_assert, + .deassert = starfive_rstgen_deassert, + .reset = starfive_reset, +}; + +static int starfive_rstgen_probe(struct device_d *dev) +{ + struct starfive_rstgen *priv; + struct resource *iores; + + priv = xzalloc(sizeof(*priv)); + + iores = dev_request_mem_resource(dev, 0); + if (IS_ERR(iores)) + return PTR_ERR(iores); + + if ((priv->sync_resets = device_get_match_data(dev))) { + priv->clknp = of_find_compatible_node(NULL, NULL, "starfive,jh7100-clkgen"); + if (!priv->clknp) + return -ENODEV; + } + + priv->base = IOMEM(iores->start); + priv->rcdev.nr_resets = RSTN_END; + priv->rcdev.ops = &starfive_rstgen_ops; + priv->rcdev.of_node = dev->device_node; + + return reset_controller_register(&priv->rcdev); +} + +static const struct of_device_id starfive_rstgen_reset_dt_ids[] = { + { .compatible = "starfive,jh7100-rstgen", .data = jh7110_rstgen_sync_resets }, + { /* sentinel */ }, +}; + +static struct driver_d starfive_rstgen_reset_driver = { + .name = "starfive_rstgen", + .probe = starfive_rstgen_probe, + .of_compatible = starfive_rstgen_reset_dt_ids, +}; +core_platform_driver(starfive_rstgen_reset_driver); diff --git a/drivers/soc/Makefile b/drivers/soc/Makefile new file mode 100644 index 0000000000..c3499c0c7f --- /dev/null +++ b/drivers/soc/Makefile @@ -0,0 +1,5 @@ +# SPDX-License-Identifier: GPL-2.0 + +obj-y += imx/ +obj-$(CONFIG_CPU_SIFIVE) += sifive/ +obj-$(CONFIG_SOC_STARFIVE) += starfive/ diff --git a/drivers/soc/sifive/Makefile b/drivers/soc/sifive/Makefile new file mode 100644 index 0000000000..e8113c66f5 --- /dev/null +++ b/drivers/soc/sifive/Makefile @@ -0,0 +1 @@ +obj-$(CONFIG_SIFIVE_L2) += sifive_l2_cache.o diff --git a/drivers/soc/sifive/sifive_l2_cache.c b/drivers/soc/sifive/sifive_l2_cache.c new file mode 100644 index 0000000000..a1e9a10622 --- /dev/null +++ b/drivers/soc/sifive/sifive_l2_cache.c @@ -0,0 +1,136 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * SiFive L2 cache controller Driver + * + * Copyright (C) 2018-2019 SiFive, Inc. + * + */ + +#define pr_fmt(fmt) "sifive-l2: " fmt + +#include <io.h> +#include <printk.h> +#include <stdio.h> +#include <driver.h> +#include <init.h> +#include <soc/sifive/l2_cache.h> +#include <asm/barrier.h> +#include <linux/bitops.h> + +#define SIFIVE_L2_DIRECCFIX_LOW 0x100 +#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 + +#define SIFIVE_L2_DATECCFAIL_LOW 0x160 +#define SIFIVE_L2_DATECCFAIL_HIGH 0x164 +#define SIFIVE_L2_DATECCFAIL_COUNT 0x168 + +#define SIFIVE_L2_FLUSH64 0x200 + +#define SIFIVE_L2_CONFIG 0x00 +#define SIFIVE_L2_WAYENABLE 0x08 +#define SIFIVE_L2_ECCINJECTERR 0x40 + +#define SIFIVE_L2_MAX_ECCINTR 4 + +#define MASK_NUM_WAYS GENMASK(15, 8) +#define NUM_WAYS_SHIFT 8 + +#define SIFIVE_L2_FLUSH64_LINE_LEN 64 + +static void __iomem *l2_base = NULL; + +static void sifive_l2_config_read(struct device_d *dev) +{ + u32 regval, val; + + printf("Cache configuration:\n"); + + regval = readl(l2_base + SIFIVE_L2_CONFIG); + val = regval & 0xFF; + printf(" #Banks: %d\n", val); + val = (regval & 0xFF00) >> 8; + printf(" #Ways per bank: %d\n", val); + val = (regval & 0xFF0000) >> 16; + printf(" #Sets per bank: %llu\n", 1llu << val); + val = (regval & 0xFF000000) >> 24; + printf(" #Bytes per cache block: %llu\n", 1llu << val); + + regval = readl(l2_base + SIFIVE_L2_WAYENABLE); + printf(" #Index of the largest way enabled: %d\n", regval); +} + +void sifive_l2_flush64_range(dma_addr_t start, dma_addr_t end) +{ + unsigned long line; + + start = ALIGN_DOWN(start, 64); + end = ALIGN(end, 64); + + if (WARN_ON(!l2_base)) + return; + + if (start == end) + return; + + mb(); + for (line = start; line < end; line += SIFIVE_L2_FLUSH64_LINE_LEN) { + writeq(line, l2_base + SIFIVE_L2_FLUSH64); + mb(); + } +} + +static void sifive_l2_enable_ways(void) +{ + u32 config; + u32 ways; + + config = readl(l2_base + SIFIVE_L2_CONFIG); + ways = (config & MASK_NUM_WAYS) >> NUM_WAYS_SHIFT; + + mb(); + writel(ways - 1, l2_base + SIFIVE_L2_WAYENABLE); + mb(); +} + +static int sifive_l2_probe(struct device_d *dev) +{ + struct resource *iores; + + if (l2_base) + return -EBUSY; + + iores = dev_request_mem_resource(dev, 0); + if (IS_ERR(iores)) + return PTR_ERR(iores); + + l2_base = IOMEM(iores->start); + + sifive_l2_enable_ways(); + + dev->info = sifive_l2_config_read; + + return 0; +} + +static const struct of_device_id sifive_l2_ids[] = { + { .compatible = "sifive,fu540-c000-ccache" }, + { .compatible = "sifive,fu740-c000-ccache" }, + { .compatible = "starfive,ccache0" }, + { /* end of table */ }, +}; + +static struct driver_d sifive_l2_driver = { + .name = "sfive-l2cache", + .probe = sifive_l2_probe, + .of_compatible = sifive_l2_ids, +}; +postcore_platform_driver(sifive_l2_driver); diff --git a/drivers/soc/starfive/Makefile b/drivers/soc/starfive/Makefile new file mode 100644 index 0000000000..72504b3bef --- /dev/null +++ b/drivers/soc/starfive/Makefile @@ -0,0 +1 @@ +obj-$(CONFIG_SOC_STARFIVE_JH7100) += jh7100_dma.o diff --git a/drivers/soc/starfive/jh7100_dma.c b/drivers/soc/starfive/jh7100_dma.c new file mode 100644 index 0000000000..a1dc48e73f --- /dev/null +++ b/drivers/soc/starfive/jh7100_dma.c @@ -0,0 +1,55 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (C) 2021 Ahmad Fatoum, Pengutronix + */ + +#include <common.h> +#include <asm/dma.h> +#include <soc/sifive/l2_cache.h> + +#define SDRAM_CACHED_BASE 0x80000000 +#define SDRAM_UNCACHED_BASE 0x1000000000 + +static inline void *jh7100_alloc_coherent(size_t size, dma_addr_t *dma_handle) +{ + dma_addr_t cpu_base; + void *ret; + + ret = xmemalign(PAGE_SIZE, size); + + memset(ret, 0, size); + + cpu_base = (dma_addr_t)ret; + + if (dma_handle) + *dma_handle = cpu_base; + + sifive_l2_flush64_range(cpu_base, cpu_base + size); + + return ret - SDRAM_CACHED_BASE + SDRAM_UNCACHED_BASE; + +} + +static inline void jh7100_free_coherent(void *vaddr, dma_addr_t dma_handle, size_t size) +{ + free((void *)dma_handle); +} + +static const struct dma_ops jh7100_dma_ops = { + .alloc_coherent = jh7100_alloc_coherent, + .free_coherent = jh7100_free_coherent, + .flush_range = sifive_l2_flush64_range, + .inv_range = sifive_l2_flush64_range, +}; + +static int jh7100_dma_init(void) +{ + /* board drivers can claim the machine compatible, so no driver here */ + if (!of_machine_is_compatible("starfive,jh7100")) + return 0; + + dma_set_ops(&jh7100_dma_ops); + + return 0; +} +mmu_initcall(jh7100_dma_init); diff --git a/drivers/watchdog/Kconfig b/drivers/watchdog/Kconfig index b785181c59..080bc91ff7 100644 --- a/drivers/watchdog/Kconfig +++ b/drivers/watchdog/Kconfig @@ -141,4 +141,11 @@ config ITCO_WDT NO_REBOOT flag which prevents the watchdog from rebooting the machine. +config STARFIVE_WDT + tristate "StarFive Watchdog Timer" + depends on SOC_STARFIVE && OFDEVICE + help + If you say yes here you get support for the watchdog device + on StarFive SoCs. + endif diff --git a/drivers/watchdog/Makefile b/drivers/watchdog/Makefile index 0b598af402..4e784b5aaa 100644 --- a/drivers/watchdog/Makefile +++ b/drivers/watchdog/Makefile @@ -18,3 +18,4 @@ obj-$(CONFIG_STPMIC1_WATCHDOG) += stpmic1_wdt.o obj-$(CONFIG_F71808E_WDT) += f71808e_wdt.o obj-$(CONFIG_GPIO_WATCHDOG) += gpio_wdt.o obj-$(CONFIG_ITCO_WDT) += itco_wdt.o +obj-$(CONFIG_STARFIVE_WDT) += starfive_wdt.o diff --git a/drivers/watchdog/starfive_wdt.c b/drivers/watchdog/starfive_wdt.c new file mode 100644 index 0000000000..6779566fd6 --- /dev/null +++ b/drivers/watchdog/starfive_wdt.c @@ -0,0 +1,106 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +/* + * Copyright (C) 2018 Kalray Inc. + */ + +#include <common.h> +#include <init.h> +#include <io.h> +#include <of.h> +#include <watchdog.h> +#include <linux/reset.h> + +#include <linux/clk.h> +#include <linux/err.h> + +#define WDT_REG_RESET_EN 0x104 +#define WDT_REG_TIMEOUT 0x108 +#define WDT_REG_CONTROL 0x110 +#define WDT_REG_UNLOCK 0x13c + +#define WDT_UNLOCK_KEY 0x378f0765 + +#define WDT_TICKS_PER_SEC 50000000 + +struct starfive_wdt { + u32 clk_rate; + struct watchdog wdd; + void __iomem *base; + bool setup; +}; + +static int starfive_wdt_set_timeout(struct watchdog *wdd, unsigned int timeout) +{ + struct starfive_wdt *wd = container_of(wdd, struct starfive_wdt, wdd); + + writel(0, wd->base + WDT_REG_CONTROL); + + if (timeout > 0) { + timeout *= wd->clk_rate; + writel(timeout, wd->base + WDT_REG_TIMEOUT); + writel(1, wd->base + WDT_REG_CONTROL); + } + + return 0; +} + +static int starfive_wdt_drv_probe(struct device_d *dev) +{ + struct starfive_wdt *wd; + struct resource *iores; + struct watchdog *wdd; + struct clk_bulk_data clks[] = { + { .id = "bus" }, + { .id = "core" }, + }; + int ret; + + ret = clk_bulk_get(dev, ARRAY_SIZE(clks), clks); + if (ret) + return ret; + + ret = clk_bulk_enable(ARRAY_SIZE(clks), clks); + if (ret < 0) + return ret; + + ret = device_reset_all(dev); + if (ret) + return ret; + + iores = dev_request_mem_resource(dev, 0); + if (IS_ERR(iores)) + return PTR_ERR(iores); + + wd = xzalloc(sizeof(*wd)); + wd->base = IOMEM(iores->start); + + wd->clk_rate = WDT_TICKS_PER_SEC; + + writel(WDT_UNLOCK_KEY, wd->base + WDT_REG_UNLOCK); + wd->base = IOMEM(iores->start); + /* reset, not interrupt, on timer expiry */ + writel(1, wd->base + WDT_REG_RESET_EN); + + wdd = &wd->wdd; + wdd->name = "starfive_wdt"; + wdd->hwdev = dev; + wdd->set_timeout = starfive_wdt_set_timeout; + wdd->timeout_max = U32_MAX / wd->clk_rate; + + wdd->running = readl(wd->base + WDT_REG_CONTROL) & 1 ? + WDOG_HW_RUNNING : WDOG_HW_NOT_RUNNING; + + return watchdog_register(wdd); +} + +static struct of_device_id starfive_wdt_of_match[] = { + { .compatible = "starfive,wdt", }, + { /* sentinel */ } +}; + +static struct driver_d starfive_wdt_driver = { + .name = "starfive-wdt", + .probe = starfive_wdt_drv_probe, + .of_compatible = starfive_wdt_of_match, +}; +device_platform_driver(starfive_wdt_driver); diff --git a/images/Makefile.riscv b/images/Makefile.riscv index c44c683431..4410765cf6 100644 --- a/images/Makefile.riscv +++ b/images/Makefile.riscv @@ -15,3 +15,7 @@ pblb-$(CONFIG_BOARD_HIFIVE) += start_hifive_unmatched start_hifive_unleashed FILE_barebox-hifive-unmatched.img = start_hifive_unmatched.pblb FILE_barebox-hifive-unleashed.img = start_hifive_unleashed.pblb image-$(CONFIG_BOARD_HIFIVE) += barebox-hifive-unmatched.img barebox-hifive-unleashed.img + +pblb-$(CONFIG_BOARD_BEAGLEV) += start_beaglev_starlight +FILE_barebox-beaglev-starlight.img = start_beaglev_starlight.pblb +image-$(CONFIG_BOARD_BEAGLEV) += barebox-beaglev-starlight.img diff --git a/include/dma.h b/include/dma.h index 1b1cb3a407..90f9254ea8 100644 --- a/include/dma.h +++ b/include/dma.h @@ -8,6 +8,7 @@ #include <malloc.h> #include <xfuncs.h> +#include <linux/kernel.h> #include <dma-dir.h> #include <asm/dma.h> @@ -15,10 +16,14 @@ #define DMA_ADDRESS_BROKEN NULL +#ifndef DMA_ALIGNMENT +#define DMA_ALIGNMENT 32 +#endif + #ifndef dma_alloc static inline void *dma_alloc(size_t size) { - return xmalloc(size); + return xmemalign(DMA_ALIGNMENT, ALIGN(size, DMA_ALIGNMENT)); } #endif diff --git a/include/dt-bindings/clock/starfive-jh7100.h b/include/dt-bindings/clock/starfive-jh7100.h new file mode 100644 index 0000000000..2512bb810e --- /dev/null +++ b/include/dt-bindings/clock/starfive-jh7100.h @@ -0,0 +1,203 @@ +/* SPDX-License-Identifier: GPL-2.0 OR X11 */ +/* + * Copyright (C) 2021 Ahmad Fatoum, Pengutronix + */ + +#ifndef __DT_BINDINGS_CLOCK_STARFIVE_JH7100_H +#define __DT_BINDINGS_CLOCK_STARFIVE_JH7100_H + +#define CLK_OSC_SYS 0 +#define CLK_OSC_AUD 1 +#define CLK_PLL0_OUT 2 +#define CLK_PLL1_OUT 3 +#define CLK_PLL2_OUT 4 +#define CLK_CPUNDBUS_ROOT 5 +#define CLK_DLA_ROOT 6 +#define CLK_DSP_ROOT 7 +#define CLK_GMACUSB_ROOT 8 +#define CLK_PERH0_ROOT 9 +#define CLK_PERH1_ROOT 10 +#define CLK_VIN_ROOT 11 +#define CLK_VOUT_ROOT 12 +#define CLK_AUDIO_ROOT 13 +#define CLK_CDECHIFI4_ROOT 14 +#define CLK_CDEC_ROOT 15 +#define CLK_VOUTBUS_ROOT 16 +#define CLK_CPUNBUS_ROOT_DIV 17 +#define CLK_DSP_ROOT_DIV 18 +#define CLK_PERH0_SRC 19 +#define CLK_PERH1_SRC 20 +#define CLK_PLL0_TESTOUT 21 +#define CLK_PLL1_TESTOUT 22 +#define CLK_PLL2_TESTOUT 23 +#define CLK_PLL2_REF 24 +#define CLK_CPU_CORE 25 +#define CLK_CPU_AXI 26 +#define CLK_AHB_BUS 27 +#define CLK_APB1_BUS 28 +#define CLK_APB2_BUS 29 +#define CLK_DOM3AHB_BUS 30 +#define CLK_DOM7AHB_BUS 31 +#define CLK_U74_CORE0 32 +#define CLK_U74_CORE1 33 +#define CLK_U74_AXI 34 +#define CLK_U74RTC_TOGGLE 35 +#define CLK_SGDMA2P_AXI 36 +#define CLK_DMA2PNOC_AXI 37 +#define CLK_SGDMA2P_AHB 38 +#define CLK_DLA_BUS 39 +#define CLK_DLA_AXI 40 +#define CLK_DLANOC_AXI 41 +#define CLK_DLA_APB 42 +#define CLK_VP6_CORE 43 +#define CLK_VP6BUS_SRC 44 +#define CLK_VP6_AXI 45 +#define CLK_VCDECBUS_SRC 46 +#define CLK_VDEC_BUS 47 +#define CLK_VDEC_AXI 48 +#define CLK_VDECBRG_MAIN 49 +#define CLK_VDEC_BCLK 50 +#define CLK_VDEC_CCLK 51 +#define CLK_VDEC_APB 52 +#define CLK_JPEG_AXI 53 +#define CLK_JPEG_CCLK 54 +#define CLK_JPEG_APB 55 +#define CLK_GC300_2X 56 +#define CLK_GC300_AHB 57 +#define CLK_JPCGC300_AXIBUS 58 +#define CLK_GC300_AXI 59 +#define CLK_JPCGC300_MAIN 60 +#define CLK_VENC_BUS 61 +#define CLK_VENC_AXI 62 +#define CLK_VENCBRG_MAIN 63 +#define CLK_VENC_BCLK 64 +#define CLK_VENC_CCLK 65 +#define CLK_VENC_APB 66 +#define CLK_DDRPLL_DIV2 67 +#define CLK_DDRPLL_DIV4 68 +#define CLK_DDRPLL_DIV8 69 +#define CLK_DDROSC_DIV2 70 +#define CLK_DDRC0 71 +#define CLK_DDRC1 72 +#define CLK_DDRPHY_APB 73 +#define CLK_NOC_ROB 74 +#define CLK_NOC_COG 75 +#define CLK_NNE_AHB 76 +#define CLK_NNEBUS_SRC1 77 +#define CLK_NNE_BUS 78 +#define CLK_NNE_AXI 79 +#define CLK_NNENOC_AXI 80 +#define CLK_DLASLV_AXI 81 +#define CLK_DSPX2C_AXI 82 +#define CLK_HIFI4_SRC 83 +#define CLK_HIFI4_COREFREE 84 +#define CLK_HIFI4_CORE 85 +#define CLK_HIFI4_BUS 86 +#define CLK_HIFI4_AXI 87 +#define CLK_HIFI4NOC_AXI 88 +#define CLK_SGDMA1P_BUS 89 +#define CLK_SGDMA1P_AXI 90 +#define CLK_DMA1P_AXI 91 +#define CLK_X2C_AXI 92 +#define CLK_USB_BUS 93 +#define CLK_USB_AXI 94 +#define CLK_USBNOC_AXI 95 +#define CLK_USBPHY_ROOTDIV 96 +#define CLK_USBPHY_125M 97 +#define CLK_USBPHY_PLLDIV25M 98 +#define CLK_USBPHY_25M 99 +#define CLK_AUDIO_DIV 100 +#define CLK_AUDIO_SRC 101 +#define CLK_AUDIO_12288 102 +#define CLK_VIN_SRC 103 +#define CLK_ISP0_BUS 104 +#define CLK_ISP0_AXI 105 +#define CLK_ISP0NOC_AXI 106 +#define CLK_ISPSLV_AXI 107 +#define CLK_ISP1_BUS 108 +#define CLK_ISP1_AXI 109 +#define CLK_ISP1NOC_AXI 110 +#define CLK_VIN_BUS 111 +#define CLK_VIN_AXI 112 +#define CLK_VINNOC_AXI 113 +#define CLK_VOUT_SRC 114 +#define CLK_DISPBUS_SRC 115 +#define CLK_DISP_BUS 116 +#define CLK_DISP_AXI 117 +#define CLK_DISPNOC_AXI 118 +#define CLK_SDIO0_AHB 119 +#define CLK_SDIO0_CCLKINT 120 +#define CLK_SDIO0_CCLKINT_INV 121 +#define CLK_SDIO1_AHB 122 +#define CLK_SDIO1_CCLKINT 123 +#define CLK_SDIO1_CCLKINT_INV 124 +#define CLK_GMAC_AHB 125 +#define CLK_GMAC_ROOT_DIV 126 +#define CLK_GMAC_PTP_REF 127 +#define CLK_GMAC_GTX 128 +#define CLK_GMAC_RMII_TX 129 +#define CLK_GMAC_RMII_RX 130 +#define CLK_GMAC_TX 131 +#define CLK_GMAC_TX_INV 132 +#define CLK_GMAC_RX_PRE 133 +#define CLK_GMAC_RX_INV 134 +#define CLK_GMAC_RMII 135 +#define CLK_GMAC_TOPHYREF 136 +#define CLK_SPI2AHB_AHB 137 +#define CLK_SPI2AHB_CORE 138 +#define CLK_EZMASTER_AHB 139 +#define CLK_E24_AHB 140 +#define CLK_E24RTC_TOGGLE 141 +#define CLK_QSPI_AHB 142 +#define CLK_QSPI_APB 143 +#define CLK_QSPI_REF 144 +#define CLK_SEC_AHB 145 +#define CLK_AES 146 +#define CLK_SHA 147 +#define CLK_PKA 148 +#define CLK_TRNG_APB 149 +#define CLK_OTP_APB 150 +#define CLK_UART0_APB 151 +#define CLK_UART0_CORE 152 +#define CLK_UART1_APB 153 +#define CLK_UART1_CORE 154 +#define CLK_SPI0_APB 155 +#define CLK_SPI0_CORE 156 +#define CLK_SPI1_APB 157 +#define CLK_SPI1_CORE 158 +#define CLK_I2C0_APB 159 +#define CLK_I2C0_CORE 160 +#define CLK_I2C1_APB 161 +#define CLK_I2C1_CORE 162 +#define CLK_GPIO_APB 163 +#define CLK_UART2_APB 164 +#define CLK_UART2_CORE 165 +#define CLK_UART3_APB 166 +#define CLK_UART3_CORE 167 +#define CLK_SPI2_APB 168 +#define CLK_SPI2_CORE 169 +#define CLK_SPI3_APB 170 +#define CLK_SPI3_CORE 171 +#define CLK_I2C2_APB 172 +#define CLK_I2C2_CORE 173 +#define CLK_I2C3_APB 174 +#define CLK_I2C3_CORE 175 +#define CLK_WDTIMER_APB 176 +#define CLK_WDT_CORE 177 +#define CLK_TIMER0_CORE 178 +#define CLK_TIMER1_CORE 179 +#define CLK_TIMER2_CORE 180 +#define CLK_TIMER3_CORE 181 +#define CLK_TIMER4_CORE 182 +#define CLK_TIMER5_CORE 183 +#define CLK_TIMER6_CORE 184 +#define CLK_VP6INTC_APB 185 +#define CLK_PWM_APB 186 +#define CLK_MSI_APB 187 +#define CLK_TEMP_APB 188 +#define CLK_TEMP_SENSE 189 +#define CLK_SYSERR_APB 190 + +#define CLK_END 191 + +#endif diff --git a/include/dt-bindings/reset-controller/starfive-jh7100.h b/include/dt-bindings/reset-controller/starfive-jh7100.h new file mode 100644 index 0000000000..390a528576 --- /dev/null +++ b/include/dt-bindings/reset-controller/starfive-jh7100.h @@ -0,0 +1,126 @@ +/* SPDX-License-Identifier: GPL-2.0 OR X11 */ +/* + * Copyright (c) 2021 Ahmad Fatoum, Pengutronix + */ + +#ifndef _DT_BINDINGS_RESET_CONTROLLER_STARFIVE_JH7100 +#define _DT_BINDINGS_RESET_CONTROLLER_STARFIVE_JH7100 + +#define RSTN_DOM3AHB_BUS 0 +#define RSTN_DOM7AHB_BUS 1 +#define RST_U74 2 +#define RSTN_U74_AXI 3 +#define RSTN_SGDMA2P_AHB 4 +#define RSTN_SGDMA2P_AXI 5 +#define RSTN_DMA2PNOC_AXI 6 +#define RSTN_DLA_AXI 7 +#define RSTN_DLANOC_AXI 8 +#define RSTN_DLA_APB 9 +#define RST_VP6_DRESET 10 +#define RST_VP6_BRESET 11 +#define RSTN_VP6_AXI 12 +#define RSTN_VDECBRG_MAIN 13 +#define RSTN_VDEC_AXI 14 +#define RSTN_VDEC_BCLK 15 +#define RSTN_VDEC_CCLK 16 +#define RSTN_VDEC_APB 17 +#define RSTN_JPEG_AXI 18 +#define RSTN_JPEG_CCLK 19 +#define RSTN_JPEG_APB 20 +#define RSTN_JPCGC300_MAIN 21 +#define RSTN_GC300_2X 22 +#define RSTN_GC300_AXI 23 +#define RSTN_GC300_AHB 24 +#define RSTN_VENC_AXI 25 +#define RSTN_VENCBRG_MAIN 26 +#define RSTN_VENC_BCLK 27 +#define RSTN_VENC_CCLK 28 +#define RSTN_VENC_APB 29 +#define RSTN_DDRPHY_APB 30 +#define RSTN_NOC_ROB 31 +#define RSTN_NOC_COG 32 +#define RSTN_HIFI4_AXI 33 +#define RSTN_HIFI4NOC_AXI 34 +#define RST_HIFI4_drESET 35 +#define RST_HIFI4_bRESET 36 +#define RSTN_USB_AXI 37 +#define RSTN_USBNOC_AXI 38 +#define RSTN_SGDMA1P_AXI 39 +#define RSTN_DMA1P_AXI 40 +#define RSTN_X2C_AXI 41 +#define RSTN_NNE_AHB 42 +#define RSTN_NNE_AXI 43 +#define RSTN_NNENOC_AXI 44 +#define RSTN_DLASLV_AXI 45 +#define RSTN_DSPX2C_AXI 46 +#define RSTN_VIN_SRC 47 +#define RSTN_ISPSLV_AXI 48 +#define RSTN_VIN_AXI 49 +#define RSTN_VINNOC_AXI 50 +#define RSTN_ISP0_AXI 51 +#define RSTN_ISP0NOC_AXI 52 +#define RSTN_ISP1_AXI 53 +#define RSTN_ISP1NOC_AXI 54 +#define RSTN_VOUT_SRC 55 +#define RSTN_DISP_AXI 56 +#define RSTN_DISPNOC_AXI 57 +#define RSTN_SDIO0_AHB 58 +#define RSTN_SDIO1_AHB 59 +#define RSTN_GMAC_AHB 60 +#define RSTN_SPI2AHB_AHB 61 +#define RSTN_SPI2AHB_CORE 62 +#define RSTN_EZMASTER_AHB 63 +#define RST_E24 64 +#define RSTN_QSPI_AHB 65 +#define RSTN_QSPI_CORE 66 +#define RSTN_QSPI_APB 67 +#define RSTN_SEC_AHB 68 +#define RSTN_AES 69 +#define RSTN_PKA 70 +#define RSTN_SHA 71 +#define RSTN_TRNG_APB 72 +#define RSTN_OTP_APB 73 +#define RSTN_UART0_APB 74 +#define RSTN_UART0_CORE 75 +#define RSTN_UART1_APB 76 +#define RSTN_UART1_CORE 77 +#define RSTN_SPI0_APB 78 +#define RSTN_SPI0_CORE 79 +#define RSTN_SPI1_APB 80 +#define RSTN_SPI1_CORE 81 +#define RSTN_I2C0_APB 82 +#define RSTN_I2C0_CORE 83 +#define RSTN_I2C1_APB 84 +#define RSTN_I2C1_CORE 85 +#define RSTN_GPIO_APB 86 +#define RSTN_UART2_APB 87 +#define RSTN_UART2_CORE 88 +#define RSTN_UART3_APB 89 +#define RSTN_UART3_CORE 90 +#define RSTN_SPI2_APB 91 +#define RSTN_SPI2_CORE 92 +#define RSTN_SPI3_APB 93 +#define RSTN_SPI3_CORE 94 +#define RSTN_I2C2_APB 95 +#define RSTN_I2C2_CORE 96 +#define RSTN_I2C3_APB 97 +#define RSTN_I2C3_CORE 98 +#define RSTN_WDTIMER_APB 99 +#define RSTN_WDT 100 +#define RSTN_TIMER0 101 +#define RSTN_TIMER1 102 +#define RSTN_TIMER2 103 +#define RSTN_TIMER3 104 +#define RSTN_TIMER4 105 +#define RSTN_TIMER5 106 +#define RSTN_TIMER6 107 +#define RSTN_VP6INTC_APB 108 +#define RSTN_PWM_APB 109 +#define RSTN_MSI_APB 110 +#define RSTN_TEMP_APB 111 +#define RSTN_TEMP_SENSE 112 +#define RSTN_SYSERR_APB 113 + +#define RSTN_END 114 + +#endif diff --git a/include/globalvar.h b/include/globalvar.h index 84bee9102c..476bb920f3 100644 --- a/include/globalvar.h +++ b/include/globalvar.h @@ -20,6 +20,8 @@ void globalvar_set(const char *name, const char *val); int globalvar_add_simple_string(const char *name, char **value); int globalvar_add_simple_int(const char *name, int *value, const char *format); +int globalvar_add_simple_uint64(const char *name, u64 *value, + const char *format); int globalvar_add_bool(const char *name, int (*set)(struct param_d *, void *), int *value, void *priv); @@ -55,6 +57,12 @@ static inline int globalvar_add_simple_int(const char *name, return 0; } +static inline int globalvar_add_simple_uint64(const char *name, + u64 *value, const char *format) +{ + return 0; +} + static inline int globalvar_add_bool(const char *name, int (*set)(struct param_d *, void *), int *value, void *priv) diff --git a/include/linux/reset.h b/include/linux/reset.h index 726cb5c205..818b06412f 100644 --- a/include/linux/reset.h +++ b/include/linux/reset.h @@ -19,6 +19,8 @@ int __must_check device_reset(struct device_d *dev); int __must_check device_reset_us(struct device_d *dev, int us); +int __must_check device_reset_all(struct device_d *dev); + #else static inline int reset_control_reset(struct reset_control *rstc) @@ -56,6 +58,11 @@ static inline int device_reset(struct device_d *dev) return 0; } +static inline int device_reset_all(struct device_d *dev) +{ + return 0; +} + #endif /* CONFIG_RESET_CONTROLLER */ #endif diff --git a/include/pinctrl.h b/include/pinctrl.h index 0fd7f49118..a628c3aac9 100644 --- a/include/pinctrl.h +++ b/include/pinctrl.h @@ -29,6 +29,7 @@ int of_pinctrl_select_state_default(struct device_node *np); int pinctrl_gpio_direction_input(unsigned pin); int pinctrl_gpio_direction_output(unsigned int pin); int pinctrl_gpio_get_direction(unsigned pin); +int pinctrl_single_probe(struct device_d *dev); #else static inline int pinctrl_select_state(struct device_d *dev, const char *state) { @@ -64,6 +65,11 @@ static inline int pinctrl_gpio_get_direction(unsigned pin) { return -ENOTSUPP; } + +static inline int pinctrl_single_probe(struct device_d *dev) +{ + return -ENOSYS; +} #endif #endif /* PINCTRL_H */ diff --git a/include/soc/sifive/l2_cache.h b/include/soc/sifive/l2_cache.h new file mode 100644 index 0000000000..0da655cd4e --- /dev/null +++ b/include/soc/sifive/l2_cache.h @@ -0,0 +1,10 @@ +/* SPDX-License-Identifier: GPL-2.0 */ + +#ifndef __SOC_SIFIVE_L2_CACHE_H_ +#define __SOC_SIFIVE_L2_CACHE_H_ + +#include <linux/types.h> + +void sifive_l2_flush64_range(dma_addr_t start, dma_addr_t end); + +#endif diff --git a/include/soc/starfive/rstgen.h b/include/soc/starfive/rstgen.h new file mode 100644 index 0000000000..7a674aabe9 --- /dev/null +++ b/include/soc/starfive/rstgen.h @@ -0,0 +1,41 @@ +/* SPDX-License-Identifier: GPL-2.0 */ + +#ifndef __SOC_STARFIVE_RSTGEN_H_ +#define __SOC_STARFIVE_RSTGEN_H_ + +#include <dt-bindings/reset-controller/starfive-jh7100.h> +#include <linux/bitops.h> +#include <linux/types.h> + +#define STARFIVE_RSTGEN_STATUS 0x10 + +static inline void __iomem *starfive_rstgen_bank(void __iomem *base, unsigned long *id) +{ + void __iomem *bank = base + *id / (4 * BITS_PER_BYTE) * 4; + *id %= 4 * BITS_PER_BYTE; + return bank; +} + +static inline void __starfive_rstgen(void __iomem *base, unsigned long id, bool assert) +{ + void __iomem *bank = starfive_rstgen_bank(base, &id); + u32 val; + + val = readl(bank); + + if (assert) + val |= BIT(id); + else + val &= ~BIT(id); + + writel(val, bank); +} + +static bool __starfive_rstgen_asserted(void __iomem *base, unsigned long id) +{ + void __iomem *bank = starfive_rstgen_bank(base, &id); + + return !(readl(bank + STARFIVE_RSTGEN_STATUS) & BIT(id)); +} + +#endif diff --git a/include/soc/starfive/sysmain.h b/include/soc/starfive/sysmain.h new file mode 100644 index 0000000000..b58f8d9825 --- /dev/null +++ b/include/soc/starfive/sysmain.h @@ -0,0 +1,15 @@ +/* SPDX-License-Identifier: GPL-2.0 */ + +#ifndef _STARFIVE_SYSMAIN_H_ +#define _STARFIVE_SYSMAIN_H_ + +#define SYSMAIN_PLL0_REG 0x00 +#define SYSMAIN_PLL1_REG 0x04 +#define SYSMAIN_PLL2_REG 0x08 +#define SYSMAIN_PLLS_STAT 0x0c + +#define SYSMAIN_GMAC_PHY_INTF_SEL 0x70 +#define SYSMAIN_GMAC_GTXCLK_DLYCHAIN_SEL 0xC8 + + +#endif //_SYSCON_SYSMAIN_CTRL_MACRO_H_ |