From e9bd28829914c56c2be436388ac0cb03bba4e794 Mon Sep 17 00:00:00 2001 From: Ahmad Fatoum Date: Sat, 19 Jun 2021 06:50:28 +0200 Subject: RISC-V: virt: select only one timer S-Mode should use the riscv timer, so no need to select CLINT timer for virt. Signed-off-by: Ahmad Fatoum Link: https://lore.barebox.org/20210619045055.779-3-a.fatoum@pengutronix.de Signed-off-by: Sascha Hauer --- arch/riscv/Kconfig.socs | 1 - 1 file changed, 1 deletion(-) (limited to 'arch/riscv') diff --git a/arch/riscv/Kconfig.socs b/arch/riscv/Kconfig.socs index c6875738d0..fd36745755 100644 --- a/arch/riscv/Kconfig.socs +++ b/arch/riscv/Kconfig.socs @@ -16,7 +16,6 @@ config BOARD_ERIZO_GENERIC config SOC_VIRT bool "QEMU Virt Machine" select BOARD_RISCV_GENERIC_DT - select CLINT_TIMER help Generates an image tht can be be booted by QEMU. The image is called barebox-dt-2nd.img -- cgit v1.2.3 From 2015dc8017ab622810a65f38ff5c11c6938e4098 Mon Sep 17 00:00:00 2001 From: Ahmad Fatoum Date: Sat, 19 Jun 2021 06:50:29 +0200 Subject: RISC-V: extend multi-image to support both S- and M-Mode We can't currently mix S-Mode and M-Mode images in the same build and there's no straight-forward way to determine which mode we are in. Move the decision on which mode barebox is targeted at out of Kconfig and into the PBL. PBL code can call either barebox_riscv_supervisor_entry or barebox_riscv_machine_entry to signal to barebox proper which mode it's running in. Currently the only user of this information is the RISC-V timer clocksource driver. Any new code that does IS_ENABLED(CONFIG_RISCV_SBI) or IS_ENABLED(CONFIG_RISCV_M_MODE) should also be adapted to use riscv_mode(). Signed-off-by: Ahmad Fatoum Link: https://lore.barebox.org/20210619045055.779-4-a.fatoum@pengutronix.de Signed-off-by: Sascha Hauer --- arch/riscv/Kconfig | 14 +++++++----- arch/riscv/Kconfig.socs | 2 ++ arch/riscv/boards/erizo/lowlevel.c | 6 +++-- arch/riscv/boards/hifive/lowlevel.c | 17 +++++++------- arch/riscv/boot/board-dt-2nd.c | 2 +- arch/riscv/boot/entry.c | 5 +++-- arch/riscv/boot/entry.h | 6 +++-- arch/riscv/boot/start.c | 12 ++++++---- arch/riscv/boot/uncompress.c | 6 ++--- arch/riscv/include/asm/barebox-riscv.h | 10 ++++++++- arch/riscv/include/asm/system.h | 41 ++++++++++++++++++++++++++++++++++ arch/riscv/lib/sbi.c | 4 ++++ drivers/clocksource/timer-clint.c | 5 +++-- drivers/clocksource/timer-riscv.c | 3 ++- 14 files changed, 102 insertions(+), 31 deletions(-) create mode 100644 arch/riscv/include/asm/system.h (limited to 'arch/riscv') diff --git a/arch/riscv/Kconfig b/arch/riscv/Kconfig index a4aa799acf..bbafdea1b9 100644 --- a/arch/riscv/Kconfig +++ b/arch/riscv/Kconfig @@ -97,14 +97,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 fd36745755..f1b431555f 100644 --- a/arch/riscv/Kconfig.socs +++ b/arch/riscv/Kconfig.socs @@ -15,6 +15,7 @@ config BOARD_ERIZO_GENERIC config SOC_VIRT bool "QEMU Virt Machine" + select RISCV_S_MODE select BOARD_RISCV_GENERIC_DT help Generates an image tht can be be booted by QEMU. The image is called @@ -22,6 +23,7 @@ config SOC_VIRT config SOC_SIFIVE bool "SiFive SoCs" + select RISCV_S_MODE select CLK_SIFIVE select CLK_SIFIVE_PRCI select RISCV_TIMER diff --git a/arch/riscv/boards/erizo/lowlevel.c b/arch/riscv/boards/erizo/lowlevel.c index 6acf15931c..fc262ed61b 100644 --- a/arch/riscv/boards/erizo/lowlevel.c +++ b/arch/riscv/boards/erizo/lowlevel.c @@ -7,12 +7,14 @@ ENTRY_FUNCTION(start_erizo_generic, a0, a1, a2) { extern char __dtb_z_erizo_generic_start[]; + void *fdt; debug_ll_init(); 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..8a20f3c51d 100644 --- a/arch/riscv/boards/hifive/lowlevel.c +++ b/arch/riscv/boards/hifive/lowlevel.c @@ -4,22 +4,23 @@ #include #include +static __always_inline void start_hifive(void *fdt) +{ + putc_ll('>'); + + barebox_riscv_supervisor_entry(0x80000000, SZ_128M, 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(__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(__dtb_z_hifive_unleashed_a00_start + get_runtime_offset()); } diff --git a/arch/riscv/boot/board-dt-2nd.c b/arch/riscv/boot/board-dt-2nd.c index e9810f8add..48cb23ae5e 100644 --- a/arch/riscv/boot/board-dt-2nd.c +++ b/arch/riscv/boot/board-dt-2nd.c @@ -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, 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/start.c b/arch/riscv/boot/start.c index 05f6c6231f..82bd02d0a0 100644 --- a/arch/riscv/boot/start.c +++ b/arch/riscv/boot/start.c @@ -26,6 +26,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 +108,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; @@ -168,18 +170,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..35a91e8cb6 100644 --- a/arch/riscv/boot/uncompress.c +++ b/arch/riscv/boot/uncompress.c @@ -23,10 +23,10 @@ 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; @@ -67,5 +67,5 @@ void __noreturn barebox_pbl_start(unsigned long membase, unsigned long memsize, 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/include/asm/barebox-riscv.h b/arch/riscv/include/asm/barebox-riscv.h index bb1d15308b..f4081a71f0 100644 --- a/arch/riscv/include/asm/barebox-riscv.h +++ b/arch/riscv/include/asm/barebox-riscv.h @@ -19,14 +19,22 @@ #include #include #include +#include unsigned long get_runtime_offset(void); void setup_c(void); void relocate_to_current_adr(void); void relocate_to_adr(unsigned long target); + 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, boarddata) \ + barebox_riscv_entry(membase, memsize, boarddata, RISCV_S_MODE) unsigned long riscv_mem_ramoops_get(void); unsigned long riscv_mem_endmem_get(void); diff --git a/arch/riscv/include/asm/system.h b/arch/riscv/include/asm/system.h new file mode 100644 index 0000000000..3d57a7d191 --- /dev/null +++ b/arch/riscv/include/asm/system.h @@ -0,0 +1,41 @@ +/* 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; +} + +#ifndef __PBL__ +extern unsigned barebox_riscv_pbl_flags; + +static inline enum riscv_mode riscv_mode(void) +{ + return __riscv_mode(barebox_riscv_pbl_flags); +} + +#endif + +#endif + +#endif 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 +#include #include #include #include @@ -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/drivers/clocksource/timer-clint.c b/drivers/clocksource/timer-clint.c index 4eeb9cf7ff..412ce3e1e9 100644 --- a/drivers/clocksource/timer-clint.c +++ b/drivers/clocksource/timer-clint.c @@ -17,6 +17,7 @@ #include #include #include +#include #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); diff --git a/drivers/clocksource/timer-riscv.c b/drivers/clocksource/timer-riscv.c index c2d32b36bb..5a517fe6b4 100644 --- a/drivers/clocksource/timer-riscv.c +++ b/drivers/clocksource/timer-riscv.c @@ -12,6 +12,7 @@ #include #include #include +#include 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(); -- cgit v1.2.3 From f13e72db3e2e90b57521c0859365dc78fb807aa6 Mon Sep 17 00:00:00 2001 From: Ahmad Fatoum Date: Sat, 19 Jun 2021 06:50:30 +0200 Subject: RISC-V: cpuinfo: return some output for non-SBI systems as well If barebox managed to actually execute the cpuinfo command, it probably means that it's assumption which instructon set is being used and whether it runs in machine or supervisor mode is correct. Add that output to cpuinfo, so it shows at least something for non-SBI configurations. Signed-off-by: Ahmad Fatoum Link: https://lore.barebox.org/20210619045055.779-5-a.fatoum@pengutronix.de Signed-off-by: Sascha Hauer --- arch/riscv/include/asm/sbi.h | 8 ++----- arch/riscv/lib/cpuinfo.c | 55 +++++++++++++++++++++++++++++++------------- commands/Kconfig | 4 ++-- 3 files changed, 43 insertions(+), 24 deletions(-) (limited to 'arch/riscv') 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 -#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/lib/cpuinfo.c b/arch/riscv/lib/cpuinfo.c index 21b99a990a..16305e6c4d 100644 --- a/arch/riscv/lib/cpuinfo.c +++ b/arch/riscv/lib/cpuinfo.c @@ -2,6 +2,7 @@ #include #include #include +#include static const char *implementations[] = { [0] = "\"Berkeley Boot Loader (BBL)\" ", @@ -12,34 +13,56 @@ 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: + 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/commands/Kconfig b/commands/Kconfig index 5ae3cb3dd1..6da68a7f14 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 -- cgit v1.2.3 From 1f3ce24ef52f2ec4473801a4bf49f86f0936b4c2 Mon Sep 17 00:00:00 2001 From: Ahmad Fatoum Date: Sat, 19 Jun 2021 06:50:31 +0200 Subject: RISC-V: S-Mode: propagate Hart ID Unlike other architectures we support, Linux must apparently be booted on all cores by the bootloader. To achieve this, the bootloaders running on the multiple cores synchronize via IPIs. We will get there eventually, but for now, let's restrict barebox to boot Linux on a single core. S-Mode firmware is passed hart (core) id in a0. This is propagated via the thread pointer register, which is unused by GCC and made available as: - cpuinfo output when running in S-Mode - $global.hartid - a0 when booting via bootm - /chosen/boot-hartid fixup: will come in handy when we gain EFI loading support - single /cpus/*/reg: All other CPU nodes are deleted via fixup For M-Mode, we can query hart id via CSR. It's unknown whether erizo supports it and we don't yet have exception support to handle it not being available, so changes are only done for S-Mode for now. Signed-off-by: Ahmad Fatoum Link: https://lore.barebox.org/20210619045055.779-6-a.fatoum@pengutronix.de Signed-off-by: Sascha Hauer --- arch/riscv/boards/hifive/lowlevel.c | 8 ++++---- arch/riscv/boot/board-dt-2nd.c | 4 ++-- arch/riscv/cpu/core.c | 34 +++++++++++++++++++++++++++++++++- arch/riscv/include/asm/barebox-riscv.h | 6 ++++-- arch/riscv/include/asm/system.h | 20 ++++++++++++++++++++ arch/riscv/lib/bootm.c | 4 +++- arch/riscv/lib/cpuinfo.c | 1 + common/globalvar.c | 21 +++++++++++++++++++++ common/oftree.c | 19 ++++++++++++++++++- include/globalvar.h | 8 ++++++++ 10 files changed, 114 insertions(+), 11 deletions(-) (limited to 'arch/riscv') diff --git a/arch/riscv/boards/hifive/lowlevel.c b/arch/riscv/boards/hifive/lowlevel.c index 8a20f3c51d..5e8969bef1 100644 --- a/arch/riscv/boards/hifive/lowlevel.c +++ b/arch/riscv/boards/hifive/lowlevel.c @@ -4,23 +4,23 @@ #include #include -static __always_inline void start_hifive(void *fdt) +static __always_inline void start_hifive(unsigned long hartid, void *fdt) { putc_ll('>'); - barebox_riscv_supervisor_entry(0x80000000, SZ_128M, fdt); + 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[]; - start_hifive(__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[]; - start_hifive(__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/board-dt-2nd.c b/arch/riscv/boot/board-dt-2nd.c index 48cb23ae5e..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_supervisor_entry(membase, memsize, fdt); + barebox_riscv_supervisor_entry(membase, memsize, hartid, fdt); } diff --git a/arch/riscv/cpu/core.c b/arch/riscv/cpu/core.c index 982d378edd..bf6e6608ce 100644 --- a/arch/riscv/cpu/core.c +++ b/arch/riscv/cpu/core.c @@ -19,6 +19,9 @@ #include #include #include +#include +#include +#include #include static int riscv_request_stack(void) @@ -30,6 +33,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 +74,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[] = { diff --git a/arch/riscv/include/asm/barebox-riscv.h b/arch/riscv/include/asm/barebox-riscv.h index f4081a71f0..bbe6cd0406 100644 --- a/arch/riscv/include/asm/barebox-riscv.h +++ b/arch/riscv/include/asm/barebox-riscv.h @@ -33,8 +33,10 @@ void __noreturn __naked barebox_riscv_entry(unsigned long membase, unsigned long #define barebox_riscv_machine_entry(membase, memsize, boarddata) \ barebox_riscv_entry(membase, memsize, boarddata, RISCV_M_MODE) -#define barebox_riscv_supervisor_entry(membase, memsize, boarddata) \ - barebox_riscv_entry(membase, memsize, boarddata, RISCV_S_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/system.h b/arch/riscv/include/asm/system.h index 3d57a7d191..adf856f9e9 100644 --- a/arch/riscv/include/asm/system.h +++ b/arch/riscv/include/asm/system.h @@ -26,6 +26,22 @@ static inline enum riscv_mode __riscv_mode(u32 flags) 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; @@ -34,6 +50,10 @@ 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 diff --git a/arch/riscv/lib/bootm.c b/arch/riscv/lib/bootm.c index b3e41de4a8..835ff345e3 100644 --- a/arch/riscv/lib/bootm.c +++ b/arch/riscv/lib/bootm.c @@ -3,11 +3,13 @@ #include #include +#include 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(); fn = booti_load_image(data, &devicetree); if (IS_ERR(fn)) @@ -15,7 +17,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 16305e6c4d..2d9cee2a62 100644 --- a/arch/riscv/lib/cpuinfo.c +++ b/arch/riscv/lib/cpuinfo.c @@ -34,6 +34,7 @@ static int do_cpuinfo(int argc, char *argv[]) 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", 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 5eaa63ad7e..1fcc5277c5 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/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) -- cgit v1.2.3 From bdbb72b8b3bb76de301d511efd7362008cc8cc3e Mon Sep 17 00:00:00 2001 From: Ahmad Fatoum Date: Sat, 19 Jun 2021 06:50:32 +0200 Subject: RISC-V: erizo: make it easier to reuse ns16550 debug_ll Incoming StarFive support also uses ns16550 compatibles as UART IP. Make reuse easier by making the two most likely parameters to change SoC-specific (base address and baud clock frequency) and move the rest behind the new CONFIG_DEBUG_LL_NS16550. Signed-off-by: Ahmad Fatoum Link: https://lore.barebox.org/20210619045055.779-7-a.fatoum@pengutronix.de Signed-off-by: Sascha Hauer --- arch/riscv/include/asm/debug_ll.h | 7 +++++-- common/Kconfig | 6 ++++++ 2 files changed, 11 insertions(+), 2 deletions(-) (limited to 'arch/riscv') diff --git a/arch/riscv/include/asm/debug_ll.h b/arch/riscv/include/asm/debug_ll.h index 6904460af9..13609d25c5 100644 --- a/arch/riscv/include/asm/debug_ll.h +++ b/arch/riscv/include/asm/debug_ll.h @@ -12,13 +12,16 @@ #include -#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) +#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/common/Kconfig b/common/Kconfig index 8b8f80bbb3..98be9b58ab 100644 --- a/common/Kconfig +++ b/common/Kconfig @@ -1376,6 +1376,7 @@ config DEBUG_RPI3_MINI_UART config DEBUG_ERIZO bool "Erizo ns16550 port" depends on SOC_ERIZO + select DEBUG_LL_NS16550 config DEBUG_SIFIVE bool "SiFive serial0 port" @@ -1383,6 +1384,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 || \ -- cgit v1.2.3 From 02fb23adcd32620724b5e42ee4189b1fbc4febd2 Mon Sep 17 00:00:00 2001 From: Ahmad Fatoum Date: Sat, 19 Jun 2021 06:50:33 +0200 Subject: RISC-V: socs: add Kconfig entry for StarFive JH7100 The JH7100 is the StarFive SoC with SiFive CPUs in the pre-production BeagleV. Th JH7110 in later boards will be cache-coherent, but the JH7100 will need some workarounds. Add Kconfig symbols, so newly introduced symbols can depend on them. Signed-off-by: Ahmad Fatoum Link: https://lore.barebox.org/20210619045055.779-8-a.fatoum@pengutronix.de Signed-off-by: Sascha Hauer --- arch/riscv/Kconfig.socs | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) (limited to 'arch/riscv') diff --git a/arch/riscv/Kconfig.socs b/arch/riscv/Kconfig.socs index f1b431555f..8f955cd4d2 100644 --- a/arch/riscv/Kconfig.socs +++ b/arch/riscv/Kconfig.socs @@ -21,8 +21,12 @@ config SOC_VIRT Generates an image tht can be be booted by QEMU. The image is called barebox-dt-2nd.img +config CPU_SIFIVE + bool + config SOC_SIFIVE bool "SiFive SoCs" + select CPU_SIFIVE select RISCV_S_MODE select CLK_SIFIVE select CLK_SIFIVE_PRCI @@ -41,4 +45,22 @@ config BOARD_HIFIVE endif +config SOC_STARFIVE + bool "StarFive SoCs" + 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 + +endif + + endmenu -- cgit v1.2.3 From 0e885ce81d0e5aca3c73a96a5d8004047035f28a Mon Sep 17 00:00:00 2001 From: Ahmad Fatoum Date: Sat, 19 Jun 2021 06:50:35 +0200 Subject: RISC-V: dma: support multiple dma_alloc_coherent backends StarFive JH7100 is incoherent between CPU and dma masters like GMAC. It has an uncached alias though similar to what we have on MIPS. StarFive JH7110 will fix this and be cache coherent like other SiFive SoCs. Support both by allowing driver to define their own dma_alloc_coherent implementations. Signed-off-by: Ahmad Fatoum Link: https://lore.barebox.org/20210619045055.779-10-a.fatoum@pengutronix.de Signed-off-by: Sascha Hauer --- arch/riscv/cpu/Makefile | 1 + arch/riscv/cpu/dma.c | 74 ++++++++++++++++++++++++++++++++++++++++++++ arch/riscv/include/asm/dma.h | 48 ++++++++-------------------- 3 files changed, 88 insertions(+), 35 deletions(-) create mode 100644 arch/riscv/cpu/dma.c (limited to 'arch/riscv') diff --git a/arch/riscv/cpu/Makefile b/arch/riscv/cpu/Makefile index f1312be699..9ce77ad869 100644 --- a/arch/riscv/cpu/Makefile +++ b/arch/riscv/cpu/Makefile @@ -1,3 +1,4 @@ # SPDX-License-Identifier: GPL-2.0 obj-y += core.o time.o +obj-$(CONFIG_HAS_DMA) += dma.o 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 +#include +#include +#include + +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/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 -#include -#include -#include +#include -#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 #endif /* _ASM_DMA_MAPPING_H */ -- cgit v1.2.3 From 6f60b81ff0dc155161606b057952eadab71806e6 Mon Sep 17 00:00:00 2001 From: Ahmad Fatoum Date: Sat, 19 Jun 2021 06:50:36 +0200 Subject: RISC-V: add exception support Add S- and M-Mode support for dumping registers when catching unexpected CPU exceptions. Load access faults when data_abort_mask is active will be skipped over. This allows outputting xxx when doing md /dev/mem for non-accessible space. Signed-off-by: Ahmad Fatoum Link: https://lore.barebox.org/20210619045055.779-11-a.fatoum@pengutronix.de Signed-off-by: Sascha Hauer --- arch/riscv/Kconfig | 5 ++ arch/riscv/boot/start.c | 3 + arch/riscv/boot/uncompress.c | 3 + arch/riscv/cpu/Makefile | 3 + arch/riscv/cpu/interrupts.c | 130 +++++++++++++++++++++++++++++++ arch/riscv/cpu/mtrap.S | 30 ++++++++ arch/riscv/cpu/strap.S | 30 ++++++++ arch/riscv/include/asm/asm-offsets.h | 1 + arch/riscv/include/asm/irq.h | 107 ++++++++++++++++++++++++++ arch/riscv/include/asm/ptrace.h | 143 +++++++++++++++++++++++++++++++++++ arch/riscv/include/asm/unwind.h | 9 +++ arch/riscv/lib/asm-offsets.c | 46 +++++++++++ 12 files changed, 510 insertions(+) create mode 100644 arch/riscv/cpu/interrupts.c create mode 100644 arch/riscv/cpu/mtrap.S create mode 100644 arch/riscv/cpu/strap.S create mode 100644 arch/riscv/include/asm/asm-offsets.h create mode 100644 arch/riscv/include/asm/irq.h create mode 100644 arch/riscv/include/asm/ptrace.h create mode 100644 arch/riscv/include/asm/unwind.h (limited to 'arch/riscv') diff --git a/arch/riscv/Kconfig b/arch/riscv/Kconfig index bbafdea1b9..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 diff --git a/arch/riscv/boot/start.c b/arch/riscv/boot/start.c index 82bd02d0a0..72ab93cb76 100644 --- a/arch/riscv/boot/start.c +++ b/arch/riscv/boot/start.c @@ -16,6 +16,7 @@ #include #include #include +#include #include @@ -122,6 +123,8 @@ void barebox_non_pbl_start(unsigned long membase, unsigned long memsize, barrier(); + irq_init_vector(__riscv_mode(flags)); + pr_debug("memory at 0x%08lx, size 0x%08lx\n", membase, memsize); riscv_endmem = endmem; diff --git a/arch/riscv/boot/uncompress.c b/arch/riscv/boot/uncompress.c index 35a91e8cb6..c6c20b38e3 100644 --- a/arch/riscv/boot/uncompress.c +++ b/arch/riscv/boot/uncompress.c @@ -14,6 +14,7 @@ #include #include #include +#include #include @@ -32,6 +33,8 @@ void __noreturn barebox_pbl_start(unsigned long membase, unsigned long memsize, 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(); diff --git a/arch/riscv/cpu/Makefile b/arch/riscv/cpu/Makefile index 9ce77ad869..717baaaaa7 100644 --- a/arch/riscv/cpu/Makefile +++ b/arch/riscv/cpu/Makefile @@ -2,3 +2,6 @@ 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/interrupts.c b/arch/riscv/cpu/interrupts.c new file mode 100644 index 0000000000..df6d3e6e01 --- /dev/null +++ b/arch/riscv/cpu/interrupts.c @@ -0,0 +1,130 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright (c) 2016-17 Microsemi Corporation. + * Padmarao Begari, Microsemi Corporation + * + * Copyright (C) 2017 Andes Technology Corporation + * Rick Chen, Andes Technology Corporation + * + * Copyright (C) 2019 Sean Anderson + */ + +#include +#include +#include +#include +#include +#include +#include + +#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; + + 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 + */ + +#include +#include +#include + +.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 + */ + +#include +#include +#include + +.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/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 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 +#include +#include +#include +#include + +#ifndef __ASSEMBLY__ +#include +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 +#include + +#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/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 +#include +#include + +#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; } -- cgit v1.2.3 From fe181ffda91593e6ba975f8d28cb4e5abb5b0bc4 Mon Sep 17 00:00:00 2001 From: Ahmad Fatoum Date: Sat, 19 Jun 2021 06:50:37 +0200 Subject: RISC-V: support incoherent I-Cache SiFive SoCs have separate I-Caches that require self-modifying code like barebox' relocation and PBL extraction code to do cache maintenance. Implement sync_caches_for_execution and use it where appropriate. The underlying fence.i primitive is part of the Zifencei (load/store fence) ISA extension. As we can't be sure it's always available, the exception handler will skip over the instruction if the CPU trips over it. Alternatively, if CONFIG_HAS_CACHE=n, the instruction won't be emitted at all. Signed-off-by: Ahmad Fatoum Link: https://lore.barebox.org/20210619045055.779-12-a.fatoum@pengutronix.de Signed-off-by: Sascha Hauer --- arch/riscv/Kconfig.socs | 2 ++ arch/riscv/boot/uncompress.c | 2 ++ arch/riscv/cpu/core.c | 7 +++++++ arch/riscv/cpu/interrupts.c | 9 +++++++++ arch/riscv/include/asm/barebox-riscv.h | 2 ++ arch/riscv/include/asm/cacheflush.h | 16 ++++++++++++++++ arch/riscv/lib/reloc.c | 8 ++++++++ arch/riscv/lib/setupc.S | 2 ++ 8 files changed, 48 insertions(+) create mode 100644 arch/riscv/include/asm/cacheflush.h (limited to 'arch/riscv') diff --git a/arch/riscv/Kconfig.socs b/arch/riscv/Kconfig.socs index 8f955cd4d2..6ec2315d4e 100644 --- a/arch/riscv/Kconfig.socs +++ b/arch/riscv/Kconfig.socs @@ -17,12 +17,14 @@ config SOC_VIRT bool "QEMU Virt Machine" select RISCV_S_MODE select BOARD_RISCV_GENERIC_DT + 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" diff --git a/arch/riscv/boot/uncompress.c b/arch/riscv/boot/uncompress.c index c6c20b38e3..4ed9b4d371 100644 --- a/arch/riscv/boot/uncompress.c +++ b/arch/riscv/boot/uncompress.c @@ -66,6 +66,8 @@ 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); diff --git a/arch/riscv/cpu/core.c b/arch/riscv/cpu/core.c index bf6e6608ce..80730c05b5 100644 --- a/arch/riscv/cpu/core.c +++ b/arch/riscv/cpu/core.c @@ -18,6 +18,7 @@ #include #include #include +#include #include #include #include @@ -92,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/interrupts.c b/arch/riscv/cpu/interrupts.c index df6d3e6e01..0e8951b619 100644 --- a/arch/riscv/cpu/interrupts.c +++ b/arch/riscv/cpu/interrupts.c @@ -121,6 +121,15 @@ 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(); diff --git a/arch/riscv/include/asm/barebox-riscv.h b/arch/riscv/include/asm/barebox-riscv.h index bbe6cd0406..abb3202427 100644 --- a/arch/riscv/include/asm/barebox-riscv.h +++ b/arch/riscv/include/asm/barebox-riscv.h @@ -27,6 +27,8 @@ 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, unsigned int flags); 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/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 #include #include +#include #include #include @@ -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/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: -- cgit v1.2.3 From 9af34bc9603e70eb328b144d63f14ca1ef0d8cd5 Mon Sep 17 00:00:00 2001 From: Ahmad Fatoum Date: Sat, 19 Jun 2021 06:50:38 +0200 Subject: drivers: soc: sifive: add basic L2 cache controller driver SiFive SoCs are cache coherent with respect to other DMA masters, so there is no need to explicitly flush cache lines. Incoming StarFive SoC uses SiFive CPU and L2 cache controller, but is cache-incoherent and thus needs the maintenance for DMA. Add a basic driver that exports the cache flush function for SoC-specific drivers to use. Signed-off-by: Ahmad Fatoum Link: https://lore.barebox.org/20210619045055.779-13-a.fatoum@pengutronix.de Signed-off-by: Sascha Hauer --- arch/riscv/Kconfig.socs | 5 ++ arch/riscv/include/asm/barrier.h | 27 ++++++++ drivers/Makefile | 2 +- drivers/soc/Makefile | 4 ++ drivers/soc/sifive/Makefile | 1 + drivers/soc/sifive/sifive_l2_cache.c | 116 +++++++++++++++++++++++++++++++++++ include/soc/sifive/l2_cache.h | 10 +++ 7 files changed, 164 insertions(+), 1 deletion(-) create mode 100644 arch/riscv/include/asm/barrier.h create mode 100644 drivers/soc/Makefile create mode 100644 drivers/soc/sifive/Makefile create mode 100644 drivers/soc/sifive/sifive_l2_cache.c create mode 100644 include/soc/sifive/l2_cache.h (limited to 'arch/riscv') diff --git a/arch/riscv/Kconfig.socs b/arch/riscv/Kconfig.socs index 6ec2315d4e..b4fdfd9741 100644 --- a/arch/riscv/Kconfig.socs +++ b/arch/riscv/Kconfig.socs @@ -64,5 +64,10 @@ config SOC_STARFIVE_JH7100 endif +comment "CPU features" + +config SIFIVE_L2 + bool "SiFive L2 cache controller" + depends on CPU_SIFIVE endmenu 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/drivers/Makefile b/drivers/Makefile index be5b0b3b04..aeb097e1f5 100644 --- a/drivers/Makefile +++ b/drivers/Makefile @@ -39,7 +39,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/soc/Makefile b/drivers/soc/Makefile new file mode 100644 index 0000000000..b787379586 --- /dev/null +++ b/drivers/soc/Makefile @@ -0,0 +1,4 @@ +# SPDX-License-Identifier: GPL-2.0 + +obj-y += imx/ +obj-$(CONFIG_CPU_SIFIVE) += sifive/ 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..96d6d4ec47 --- /dev/null +++ b/drivers/soc/sifive/sifive_l2_cache.c @@ -0,0 +1,116 @@ +// 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 +#include +#include +#include +#include +#include +#include + +#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 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 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); + + 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" }, + { /* 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/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 + +void sifive_l2_flush64_range(dma_addr_t start, dma_addr_t end); + +#endif -- cgit v1.2.3 From b1cfdcc407b1f32e9b9df60194278224a1115d13 Mon Sep 17 00:00:00 2001 From: Ahmad Fatoum Date: Sat, 19 Jun 2021 06:50:39 +0200 Subject: soc: starfive: add support for JH7100 incoherent interconnect The preproduction JH7100 used in the BeagleV beta does not ensure cache coherence between CPU and some DMA masters like the Ethernet MAC. Fix this for streaming DMA mappings by implementing cache cleaning and discarding. The Flush64 primitive can be used for both as it will invalidate after flushing and not write-back clean lines. Coherent DMA mapping will be implemented using allocation from uncached SRAM in a follow-up commit. Signed-off-by: Ahmad Fatoum Link: https://lore.barebox.org/20210619045055.779-14-a.fatoum@pengutronix.de Signed-off-by: Sascha Hauer --- arch/riscv/Kconfig.socs | 5 ++++ drivers/soc/Makefile | 1 + drivers/soc/sifive/sifive_l2_cache.c | 1 + drivers/soc/starfive/Makefile | 1 + drivers/soc/starfive/jh7100_dma.c | 55 ++++++++++++++++++++++++++++++++++++ 5 files changed, 63 insertions(+) create mode 100644 drivers/soc/starfive/Makefile create mode 100644 drivers/soc/starfive/jh7100_dma.c (limited to 'arch/riscv') diff --git a/arch/riscv/Kconfig.socs b/arch/riscv/Kconfig.socs index b4fdfd9741..c112fcc82e 100644 --- a/arch/riscv/Kconfig.socs +++ b/arch/riscv/Kconfig.socs @@ -61,6 +61,11 @@ config SOC_STARFIVE_JH71XX 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. endif diff --git a/drivers/soc/Makefile b/drivers/soc/Makefile index b787379586..c3499c0c7f 100644 --- a/drivers/soc/Makefile +++ b/drivers/soc/Makefile @@ -2,3 +2,4 @@ obj-y += imx/ obj-$(CONFIG_CPU_SIFIVE) += sifive/ +obj-$(CONFIG_SOC_STARFIVE) += starfive/ diff --git a/drivers/soc/sifive/sifive_l2_cache.c b/drivers/soc/sifive/sifive_l2_cache.c index 96d6d4ec47..9e54474f7a 100644 --- a/drivers/soc/sifive/sifive_l2_cache.c +++ b/drivers/soc/sifive/sifive_l2_cache.c @@ -105,6 +105,7 @@ static int sifive_l2_probe(struct device_d *dev) 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 */ }, }; 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 +#include +#include + +#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); -- cgit v1.2.3 From 963b55822f6db510c9aff6a6a75aa4d7a5efb460 Mon Sep 17 00:00:00 2001 From: Ahmad Fatoum Date: Sat, 19 Jun 2021 06:50:41 +0200 Subject: net: designware: fix non-1:1 mapped 64-bit systems drivers/net/designware.c handles the older Designware < 4.x MAC IPs, which do not support DMA beyond 32-bit. They are still being integrated into SoCs with 64-bit CPUs like the StarFive JH7100, which additionally needs a non 1:1 mapping for coherent DMA. Fix the driver to support such usage. The driver still has the assumption that barebox core will only pass it 32-bit pointers. This is now made explicit by returning error codes when the DMA mask is violated. Signed-off-by: Ahmad Fatoum Link: https://lore.barebox.org/20210619045055.779-16-a.fatoum@pengutronix.de Signed-off-by: Sascha Hauer --- arch/riscv/include/asm/io.h | 10 ++++++++ drivers/net/designware.c | 57 +++++++++++++++++++++++++++------------------ drivers/net/designware.h | 28 ++++++++++++++++++---- 3 files changed, 68 insertions(+), 27 deletions(-) (limited to 'arch/riscv') 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 +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/drivers/net/designware.c b/drivers/net/designware.c index 0ee6d3d78a..559e202c29 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,6 +451,8 @@ 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); @@ -481,12 +483,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..5851187c0c 100644 --- a/drivers/net/designware.h +++ b/drivers/net/designware.h @@ -8,6 +8,7 @@ #define __DESIGNWARE_ETH_H #include +#include 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; @@ -38,6 +42,20 @@ struct dw_eth_drvdata { 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 +156,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 */ -- cgit v1.2.3 From bccfe152b73097903035b612845cdc33c8c01213 Mon Sep 17 00:00:00 2001 From: Ahmad Fatoum Date: Sat, 19 Jun 2021 06:50:49 +0200 Subject: reset: add StarFive reset controller driver The StarFive SoC has a single reset controller, which seems to control reset of all clocks and peripherals. It differs from the ones supported by the Linux reset-simple driver in that it has a dedicated status registers that needs to be polled to verify the reset has completed. Also special is that most resets (> 70) are synchronous. As the reset status poll would just time out without the clock, have the reset controller enable the clock as part of the reset. OS can decide later, which clocks to disable again. Signed-off-by: Ahmad Fatoum Link: https://lore.barebox.org/20210619045055.779-24-a.fatoum@pengutronix.de Signed-off-by: Sascha Hauer --- arch/riscv/Kconfig.socs | 1 + drivers/reset/Kconfig | 6 + drivers/reset/Makefile | 1 + drivers/reset/reset-starfive-vic.c | 234 +++++++++++++++++++++ .../dt-bindings/reset-controller/starfive-jh7100.h | 126 +++++++++++ include/soc/starfive/rstgen.h | 41 ++++ 6 files changed, 409 insertions(+) create mode 100644 drivers/reset/reset-starfive-vic.c create mode 100644 include/dt-bindings/reset-controller/starfive-jh7100.h create mode 100644 include/soc/starfive/rstgen.h (limited to 'arch/riscv') diff --git a/arch/riscv/Kconfig.socs b/arch/riscv/Kconfig.socs index c112fcc82e..e5603b001c 100644 --- a/arch/riscv/Kconfig.socs +++ b/arch/riscv/Kconfig.socs @@ -49,6 +49,7 @@ endif config SOC_STARFIVE bool "StarFive SoCs" + select ARCH_HAS_RESET_CONTROLLER help This enables support for SiFive SoC platform hardware. 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/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 +#include +#include +#include +#include +#include +#include +#include + +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/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/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 +#include +#include + +#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 -- cgit v1.2.3 From b90af8c6b56954987105dfd2d557edce7837c7c2 Mon Sep 17 00:00:00 2001 From: Ahmad Fatoum Date: Sat, 19 Jun 2021 06:50:55 +0200 Subject: RISC-V: StarFive: add board support for BeagleV Starlight With the different drivers now in place, we have everything to start a barebox image. Signed-off-by: Ahmad Fatoum Link: https://lore.barebox.org/20210619045055.779-30-a.fatoum@pengutronix.de Signed-off-by: Sascha Hauer --- Documentation/boards/riscv.rst | 37 + arch/riscv/Kconfig.socs | 18 + arch/riscv/boards/Makefile | 1 + arch/riscv/boards/beaglev/Makefile | 5 + arch/riscv/boards/beaglev/board.c | 30 + .../beaglev/defaultenv-beaglev/boot/buildroot | 13 + .../boards/beaglev/defaultenv-beaglev/boot/fedora | 16 + .../beaglev/defaultenv-beaglev/nv/boot.default | 1 + arch/riscv/boards/beaglev/lowlevel.c | 18 + arch/riscv/configs/starfive_defconfig | 131 ++++ arch/riscv/dts/Makefile | 1 + arch/riscv/dts/jh7100-beaglev-starlight.dts | 54 ++ arch/riscv/dts/jh7100-beaglev-starlight.dtsi | 369 ++++++++++ arch/riscv/dts/jh7100.dtsi | 798 +++++++++++++++++++++ arch/riscv/include/asm/debug_ll.h | 3 + common/Kconfig | 5 + images/Makefile.riscv | 4 + 17 files changed, 1504 insertions(+) create mode 100644 arch/riscv/boards/beaglev/Makefile create mode 100644 arch/riscv/boards/beaglev/board.c create mode 100755 arch/riscv/boards/beaglev/defaultenv-beaglev/boot/buildroot create mode 100755 arch/riscv/boards/beaglev/defaultenv-beaglev/boot/fedora create mode 100644 arch/riscv/boards/beaglev/defaultenv-beaglev/nv/boot.default create mode 100644 arch/riscv/boards/beaglev/lowlevel.c create mode 100644 arch/riscv/configs/starfive_defconfig create mode 100644 arch/riscv/dts/jh7100-beaglev-starlight.dts create mode 100644 arch/riscv/dts/jh7100-beaglev-starlight.dtsi create mode 100644 arch/riscv/dts/jh7100.dtsi (limited to 'arch/riscv') 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.socs b/arch/riscv/Kconfig.socs index e5603b001c..de74f216a2 100644 --- a/arch/riscv/Kconfig.socs +++ b/arch/riscv/Kconfig.socs @@ -50,6 +50,8 @@ endif config SOC_STARFIVE bool "StarFive SoCs" select ARCH_HAS_RESET_CONTROLLER + select RISCV_S_MODE + select HAS_ASM_DEBUG_LL help This enables support for SiFive SoC platform hardware. @@ -68,6 +70,22 @@ config SOC_STARFIVE_JH7100 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" 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 +#include +#include +#include + +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..cccb928bc8 --- /dev/null +++ b/arch/riscv/boards/beaglev/lowlevel.c @@ -0,0 +1,18 @@ +// SPDX-License-Identifier: GPL-2.0-only + +#include +#include +#include + +ENTRY_FUNCTION(start_beaglev_starlight, a0, a1, a2) +{ + extern char __dtb_z_jh7100_beaglev_starlight_start[]; + void *fdt; + + debug_ll_init(); + 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/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/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 + +/ { + #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 + +/ { + #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 +#include + +/ { + #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/debug_ll.h b/arch/riscv/include/asm/debug_ll.h index 13609d25c5..b4caa0597a 100644 --- a/arch/riscv/include/asm/debug_ll.h +++ b/arch/riscv/include/asm/debug_ll.h @@ -17,6 +17,9 @@ #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 diff --git a/common/Kconfig b/common/Kconfig index 98be9b58ab..d4e518bf8a 100644 --- a/common/Kconfig +++ b/common/Kconfig @@ -1378,6 +1378,11 @@ config DEBUG_ERIZO 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" depends on SOC_SIFIVE 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 -- cgit v1.2.3 From 1e29b4d8024ac33d171669dfd7b77381ffc84ae8 Mon Sep 17 00:00:00 2001 From: Antony Pavlov Date: Thu, 8 Jul 2021 11:30:33 +0300 Subject: RISC-V: make it possible to run nmon from PBL C code After migrating to PBL we can't use nmon assembler macro in C code anymore. Some changes are introduced to invoke nmon from PBL C code: * use 'lla' macro instruction instead of 'la'; * don't touch the 'ra' register, use 'a2' instead; * add wrapper C function for nmon. Signed-off-by: Antony Pavlov Reviewed-by: Ahmad Fatoum Link: https://lore.barebox.org/20210708083035.40814-2-antonynpavlov@gmail.com Signed-off-by: Sascha Hauer --- arch/riscv/boot/Makefile | 1 + arch/riscv/boot/nmon_entry.S | 13 ++++++++++ arch/riscv/include/asm/riscv_nmon.h | 49 ++++++++++++++++++++++++------------- 3 files changed, 46 insertions(+), 17 deletions(-) create mode 100644 arch/riscv/boot/nmon_entry.S (limited to 'arch/riscv') 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/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 +#include + +#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/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 + #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 */ -- cgit v1.2.3 From 439c7c36f59a0e10b718aff8417f483ecd3871c8 Mon Sep 17 00:00:00 2001 From: Antony Pavlov Date: Thu, 8 Jul 2021 11:30:34 +0300 Subject: RISC-V: boards: erizo: make it possible to use nmon Signed-off-by: Antony Pavlov Reviewed-by: Ahmad Fatoum Link: https://lore.barebox.org/20210708083035.40814-3-antonynpavlov@gmail.com Signed-off-by: Sascha Hauer --- arch/riscv/boards/erizo/lowlevel.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'arch/riscv') diff --git a/arch/riscv/boards/erizo/lowlevel.c b/arch/riscv/boards/erizo/lowlevel.c index fc262ed61b..ab06634bdb 100644 --- a/arch/riscv/boards/erizo/lowlevel.c +++ b/arch/riscv/boards/erizo/lowlevel.c @@ -3,6 +3,7 @@ #include #include #include +#include ENTRY_FUNCTION(start_erizo_generic, a0, a1, a2) { @@ -10,6 +11,7 @@ ENTRY_FUNCTION(start_erizo_generic, a0, a1, a2) void *fdt; debug_ll_init(); + barebox_nmon_entry(); putc_ll('>'); /* On POR, we are running from read-only memory here. */ -- cgit v1.2.3 From b60bdac8a5870dc136c9b028771371dd123a2431 Mon Sep 17 00:00:00 2001 From: Antony Pavlov Date: Thu, 8 Jul 2021 11:30:35 +0300 Subject: RISC-V: boards: beaglev: make it possible to use nmon Signed-off-by: Antony Pavlov Link: https://lore.barebox.org/20210708083035.40814-4-antonynpavlov@gmail.com Signed-off-by: Sascha Hauer --- arch/riscv/Kconfig.socs | 1 + arch/riscv/boards/beaglev/lowlevel.c | 2 ++ 2 files changed, 3 insertions(+) (limited to 'arch/riscv') diff --git a/arch/riscv/Kconfig.socs b/arch/riscv/Kconfig.socs index de74f216a2..221ea133d4 100644 --- a/arch/riscv/Kconfig.socs +++ b/arch/riscv/Kconfig.socs @@ -52,6 +52,7 @@ config SOC_STARFIVE 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. diff --git a/arch/riscv/boards/beaglev/lowlevel.c b/arch/riscv/boards/beaglev/lowlevel.c index cccb928bc8..db884dc762 100644 --- a/arch/riscv/boards/beaglev/lowlevel.c +++ b/arch/riscv/boards/beaglev/lowlevel.c @@ -3,6 +3,7 @@ #include #include #include +#include ENTRY_FUNCTION(start_beaglev_starlight, a0, a1, a2) { @@ -10,6 +11,7 @@ ENTRY_FUNCTION(start_beaglev_starlight, a0, a1, a2) void *fdt; debug_ll_init(); + barebox_nmon_entry(); putc_ll('>'); fdt = __dtb_z_jh7100_beaglev_starlight_start + get_runtime_offset(); -- cgit v1.2.3