diff options
author | Tom Rini <trini@konsulko.com> | 2024-04-09 14:18:55 -0600 |
---|---|---|
committer | Tom Rini <trini@konsulko.com> | 2024-04-09 14:18:55 -0600 |
commit | 2d357e4dbea0dd2fd23002bdf2e18f901aec2d99 (patch) | |
tree | 877abee81b69a531fa33314f9361eda27d2d0c5c | |
parent | 069d07396e30aa9be396c1dd3fc158ac199e6843 (diff) | |
parent | c1f78a4f632276bb4d77f8c79fe203709a9fa397 (diff) | |
download | u-boot-WIP/09Apr2024.zip u-boot-WIP/09Apr2024.tar.gz u-boot-WIP/09Apr2024.tar.bz2 |
Merge branch 'master' of https://source.denx.de/u-boot/custodians/u-boot-riscvWIP/09Apr2024
CI: https://source.denx.de/u-boot/custodians/u-boot-riscv/-/pipelines/20256
- RISC-V: Support backtrace and improve isa extension parsing
- cpu: Add cv1800b SoC support
- board: Add Milk-V Mars board support
- board: Add Milk-V Duo SD card support
29 files changed, 649 insertions, 64 deletions
diff --git a/arch/riscv/Kconfig b/arch/riscv/Kconfig index 6c26f91f..7e20ef6 100644 --- a/arch/riscv/Kconfig +++ b/arch/riscv/Kconfig @@ -22,6 +22,7 @@ config TARGET_OPENPITON_RISCV64 config TARGET_QEMU_VIRT bool "Support QEMU Virt Board" + select BOARD_LATE_INIT config TARGET_SIFIVE_UNLEASHED bool "Support SiFive Unleashed Board" @@ -93,6 +94,7 @@ source "board/xilinx/mbv/Kconfig" # platform-specific options below source "arch/riscv/cpu/andesv5/Kconfig" +source "arch/riscv/cpu/cv1800b/Kconfig" source "arch/riscv/cpu/fu540/Kconfig" source "arch/riscv/cpu/fu740/Kconfig" source "arch/riscv/cpu/generic/Kconfig" @@ -119,6 +121,26 @@ config ARCH_RV64I endchoice +config FRAMEPOINTER + bool "Build with frame pointer for stack unwinding" + help + Choose this option to use the frame pointer so the stack can be + unwound if needed. This is useful for tracing where faults came + from as the source may be several functions back + + If you say Y here, then the code size will be increased due to + having to store the fp. + +config SPL_FRAMEPOINTER + bool "Build SPL with frame pointer for stack unwinding" + help + Choose this option to use the frame pointer so the stack can be + unwound if needed. This is useful for tracing where faults came + from as the source may be several functions back + + If you say Y here, then the code size will be increased due to + having to store the fp. + choice prompt "Code Model" default CMODEL_MEDLOW diff --git a/arch/riscv/Makefile b/arch/riscv/Makefile index b3ef870..c36a853 100644 --- a/arch/riscv/Makefile +++ b/arch/riscv/Makefile @@ -48,6 +48,10 @@ endif ARCH_FLAGS = -march=$(RISCV_MARCH) -mabi=$(ABI) \ -mcmodel=$(CMODEL) +ifeq ($(CONFIG_$(SPL_)FRAMEPOINTER),y) + ARCH_FLAGS += -fno-omit-frame-pointer +endif + PLATFORM_CPPFLAGS += $(ARCH_FLAGS) CFLAGS_EFI += $(ARCH_FLAGS) diff --git a/arch/riscv/cpu/cpu.c b/arch/riscv/cpu/cpu.c index ecfefa1..affe700 100644 --- a/arch/riscv/cpu/cpu.c +++ b/arch/riscv/cpu/cpu.c @@ -38,35 +38,51 @@ static inline bool supports_extension(char ext) #if CONFIG_IS_ENABLED(RISCV_MMODE) return csr_read(CSR_MISA) & (1 << (ext - 'a')); #elif CONFIG_CPU + char sext[2] = {ext}; struct udevice *dev; - char desc[32]; - int i; + const char *isa; + int ret, i; uclass_find_first_device(UCLASS_CPU, &dev); if (!dev) { debug("unable to find the RISC-V cpu device\n"); return false; } - if (!cpu_get_desc(dev, desc, sizeof(desc))) { - /* - * skip the first 4 characters (rv32|rv64) - */ - for (i = 4; i < sizeof(desc); i++) { - switch (desc[i]) { - case 's': - case 'x': - case 'z': - case '_': - case '\0': - /* - * Any of these characters mean the single - * letter extensions have all been consumed. - */ - return false; - default: - if (desc[i] == ext) - return true; - } + + ret = dev_read_stringlist_search(dev, "riscv,isa-extensions", sext); + if (ret >= 0) + return true; + + /* + * Only if the property is not found (ENODATA) is the fallback to + * riscv,isa used, otherwise the extension is not present in this + * CPU. + */ + if (ret != -ENODATA) + return false; + + isa = dev_read_string(dev, "riscv,isa"); + if (!isa) + return false; + + /* + * Skip the first 4 characters (rv32|rv64). + */ + for (i = 4; i < sizeof(isa); i++) { + switch (isa[i]) { + case 's': + case 'x': + case 'z': + case '_': + case '\0': + /* + * Any of these characters mean the single + * letter extensions have all been consumed. + */ + return false; + default: + if (isa[i] == ext) + return true; } } diff --git a/arch/riscv/cpu/cv1800b/Kconfig b/arch/riscv/cpu/cv1800b/Kconfig new file mode 100644 index 0000000..7225b12 --- /dev/null +++ b/arch/riscv/cpu/cv1800b/Kconfig @@ -0,0 +1,12 @@ +# SPDX-License-Identifier: GPL-2.0+ +# +# Copyright (c) 2024, Kongyang Liu <seashell11234455@gmail.com> + +config SOPHGO_CV1800B + bool + select ARCH_EARLY_INIT_R + select SYS_CACHE_SHIFT_6 + imply CPU + imply CPU_RISCV + imply RISCV_TIMER + imply CMD_CPU diff --git a/arch/riscv/cpu/cv1800b/Makefile b/arch/riscv/cpu/cv1800b/Makefile new file mode 100644 index 0000000..95beb34 --- /dev/null +++ b/arch/riscv/cpu/cv1800b/Makefile @@ -0,0 +1,7 @@ +# SPDX-License-Identifier: GPL-2.0+ +# +# Copyright (c) 2024, Kongyang Liu <seashell11234455@gmail.com> + +obj-y += dram.o +obj-y += cpu.o +obj-y += cache.o diff --git a/arch/riscv/cpu/cv1800b/cache.c b/arch/riscv/cpu/cv1800b/cache.c new file mode 100644 index 0000000..b8051e2 --- /dev/null +++ b/arch/riscv/cpu/cv1800b/cache.c @@ -0,0 +1,45 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright (c) 2024, Kongyang Liu <seashell11234455@gmail.com> + */ + +#include <cpu_func.h> + +/* + * dcache.ipa rs1 (invalidate) + * | 31 - 25 | 24 - 20 | 19 - 15 | 14 - 12 | 11 - 7 | 6 - 0 | + * 0000001 01010 rs1 000 00000 0001011 + * + * dcache.cpa rs1 (clean) + * | 31 - 25 | 24 - 20 | 19 - 15 | 14 - 12 | 11 - 7 | 6 - 0 | + * 0000001 01001 rs1 000 00000 0001011 + * + * dcache.cipa rs1 (clean then invalidate) + * | 31 - 25 | 24 - 20 | 19 - 15 | 14 - 12 | 11 - 7 | 6 - 0 | + * 0000001 01011 rs1 000 00000 0001011 + * + * sync.s + * | 31 - 25 | 24 - 20 | 19 - 15 | 14 - 12 | 11 - 7 | 6 - 0 | + * 0000000 11001 00000 000 00000 0001011 + */ +#define DCACHE_IPA_A0 ".long 0x02a5000b" +#define DCACHE_CPA_A0 ".long 0x0295000b" +#define DCACHE_CIPA_A0 ".long 0x02b5000b" + +#define SYNC_S ".long 0x0190000b" + +void invalidate_dcache_range(unsigned long start, unsigned long end) +{ + register unsigned long i asm("a0") = start & ~(CONFIG_SYS_CACHELINE_SIZE - 1); + for (; i < end; i += CONFIG_SYS_CACHELINE_SIZE) + __asm__ __volatile__(DCACHE_IPA_A0); + __asm__ __volatile__(SYNC_S); +} + +void flush_dcache_range(unsigned long start, unsigned long end) +{ + register unsigned long i asm("a0") = start & ~(CONFIG_SYS_CACHELINE_SIZE - 1); + for (; i < end; i += CONFIG_SYS_CACHELINE_SIZE) + __asm__ __volatile__(DCACHE_CPA_A0); + __asm__ __volatile__(SYNC_S); +} diff --git a/arch/riscv/cpu/cv1800b/cpu.c b/arch/riscv/cpu/cv1800b/cpu.c new file mode 100644 index 0000000..233a6a3 --- /dev/null +++ b/arch/riscv/cpu/cv1800b/cpu.c @@ -0,0 +1,9 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright (c) 2024, Kongyang Liu <seashell11234455@gmail.com> + */ + +int cleanup_before_linux(void) +{ + return 0; +} diff --git a/arch/riscv/cpu/cv1800b/dram.c b/arch/riscv/cpu/cv1800b/dram.c new file mode 100644 index 0000000..91007c0 --- /dev/null +++ b/arch/riscv/cpu/cv1800b/dram.c @@ -0,0 +1,21 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright (C) 2018, Bin Meng <bmeng.cn@gmail.com> + */ + +#include <fdtdec.h> +#include <init.h> +#include <asm/global_data.h> +#include <linux/sizes.h> + +DECLARE_GLOBAL_DATA_PTR; + +int dram_init(void) +{ + return fdtdec_setup_mem_size_base(); +} + +int dram_init_banksize(void) +{ + return fdtdec_setup_memory_banksize(); +} diff --git a/arch/riscv/cpu/start.S b/arch/riscv/cpu/start.S index 6cecadf..a9e1935 100644 --- a/arch/riscv/cpu/start.S +++ b/arch/riscv/cpu/start.S @@ -418,6 +418,7 @@ call_board_init_r: */ mv a0, s3 /* gd_t */ mv a1, s4 /* dest_addr */ + mv s0, zero /* fp == NULL */ /* * jump to it ... diff --git a/arch/riscv/dts/cv1800b-milkv-duo.dts b/arch/riscv/dts/cv1800b-milkv-duo.dts index 3af9e34..94e64dd 100644 --- a/arch/riscv/dts/cv1800b-milkv-duo.dts +++ b/arch/riscv/dts/cv1800b-milkv-duo.dts @@ -33,6 +33,14 @@ clock-frequency = <25000000>; }; +&sdhci0 { + status = "okay"; + bus-width = <4>; + no-1-8-v; + no-mmc; + no-sdio; +}; + &uart0 { status = "okay"; }; diff --git a/arch/riscv/dts/cv1800b.dtsi b/arch/riscv/dts/cv1800b.dtsi index 165e9e3..baf6418 100644 --- a/arch/riscv/dts/cv1800b.dtsi +++ b/arch/riscv/dts/cv1800b.dtsi @@ -16,3 +16,7 @@ &clint { compatible = "sophgo,cv1800b-clint", "thead,c900-clint"; }; + +&clk { + compatible = "sophgo,cv1800-clk"; +}; diff --git a/arch/riscv/dts/cv18xx.dtsi b/arch/riscv/dts/cv18xx.dtsi index 2d6f4a4..ec99c4d 100644 --- a/arch/riscv/dts/cv18xx.dtsi +++ b/arch/riscv/dts/cv18xx.dtsi @@ -45,6 +45,13 @@ #clock-cells = <0>; }; + sdhci_clk: sdhci-clock { + compatible = "fixed-clock"; + clock-frequency = <375000000>; + clock-output-names = "sdhci_clk"; + #clock-cells = <0>; + }; + soc { compatible = "simple-bus"; interrupt-parent = <&plic>; @@ -53,6 +60,12 @@ dma-noncoherent; ranges; + clk: clock-controller@3002000 { + reg = <0x03002000 0x1000>; + clocks = <&osc>; + #clock-cells = <1>; + }; + gpio0: gpio@3020000 { compatible = "snps,dw-apb-gpio"; reg = <0x3020000 0x1000>; @@ -175,6 +188,15 @@ status = "disabled"; }; + sdhci0: mmc@4310000 { + compatible = "sophgo,cv1800b-dwcmshc"; + reg = <0x4310000 0x1000>; + interrupts = <36 IRQ_TYPE_LEVEL_HIGH>; + clocks = <&sdhci_clk>; + clock-names = "core"; + status = "disabled"; + }; + plic: interrupt-controller@70000000 { reg = <0x70000000 0x4000000>; interrupts-extended = <&cpu0_intc 11>, <&cpu0_intc 9>; diff --git a/arch/riscv/dts/jh7110-starfive-visionfive-2.dtsi b/arch/riscv/dts/jh7110-starfive-visionfive-2.dtsi index f2c6bec..e11babc 100644 --- a/arch/riscv/dts/jh7110-starfive-visionfive-2.dtsi +++ b/arch/riscv/dts/jh7110-starfive-visionfive-2.dtsi @@ -298,7 +298,7 @@ pinctrl-0 = <&mmc1_pins>; no-sdio; no-mmc; - broken-cd; + cd-gpios = <&sysgpio 41 GPIO_ACTIVE_LOW>; cap-sd-highspeed; post-power-on-delay-ms = <200>; status = "okay"; diff --git a/arch/riscv/include/asm/arch-jh7110/eeprom.h b/arch/riscv/include/asm/arch-jh7110/eeprom.h index d2776d5..62d184a 100644 --- a/arch/riscv/include/asm/arch-jh7110/eeprom.h +++ b/arch/riscv/include/asm/arch-jh7110/eeprom.h @@ -12,4 +12,13 @@ u8 get_pcb_revision_from_eeprom(void); u32 get_ddr_size_from_eeprom(void); +/** + * get_product_id_from_eeprom - get product ID string + * + * A string like "VF7110A1-2228-D008E000-00000001" is returned. + * + * Return: product ID string + */ +const char *get_product_id_from_eeprom(void); + #endif /* _ASM_RISCV_EEPROM_H */ diff --git a/arch/riscv/lib/interrupts.c b/arch/riscv/lib/interrupts.c index a26ccc7..7350e2c 100644 --- a/arch/riscv/lib/interrupts.c +++ b/arch/riscv/lib/interrupts.c @@ -60,6 +60,40 @@ static void show_regs(struct pt_regs *regs) #endif } +#if defined(CONFIG_FRAMEPOINTER) || defined(CONFIG_SPL_FRAMEPOINTER) +static void show_backtrace(struct pt_regs *regs) +{ + uintptr_t *fp = (uintptr_t *)regs->s0; + unsigned count = 0; + ulong ra; + + printf("backtrace:\n"); + + /* there are a few entry points where the s0 register is + * set to gd, so to avoid changing those, just abort if + * the value is the same */ + while (fp != NULL && fp != (uintptr_t *)gd) { + ra = fp[-1]; + printf("backtrace %2d: FP: " REG_FMT " RA: " REG_FMT, + count, (ulong)fp, ra); + + if (gd && gd->flags & GD_FLG_RELOC) + printf(" - RA: " REG_FMT " reloc adjusted\n", + ra - gd->reloc_off); + else + printf("\n"); + + fp = (uintptr_t *)fp[-2]; + count++; + } +} +#else +static void show_backtrace(struct pt_regs *regs) +{ + printf("No backtrace support enabled\n"); +} +#endif + /** * instr_len() - get instruction length * @@ -131,6 +165,7 @@ static void _exit_trap(ulong code, ulong epc, ulong tval, struct pt_regs *regs) epc - gd->reloc_off, regs->ra - gd->reloc_off); show_regs(regs); + show_backtrace(regs); show_code(epc); show_efi_loaded_images(epc); panic("\n"); diff --git a/board/emulation/qemu-riscv/qemu-riscv.c b/board/emulation/qemu-riscv/qemu-riscv.c index 181abbb..173245b 100644 --- a/board/emulation/qemu-riscv/qemu-riscv.c +++ b/board/emulation/qemu-riscv/qemu-riscv.c @@ -31,12 +31,6 @@ int is_flash_available(void) int board_init(void) { - /* - * Make sure virtio bus is enumerated so that peripherals - * on the virtio bus can be discovered by their drivers - */ - virtio_init(); - return 0; } @@ -46,6 +40,12 @@ int board_late_init(void) if (CONFIG_IS_ENABLED(USB_KEYBOARD)) usb_init(); + /* + * Make sure virtio bus is enumerated so that peripherals + * on the virtio bus can be discovered by their drivers + */ + virtio_init(); + return 0; } diff --git a/board/sophgo/milkv_duo/Kconfig b/board/sophgo/milkv_duo/Kconfig index 2a458f2..040a748 100644 --- a/board/sophgo/milkv_duo/Kconfig +++ b/board/sophgo/milkv_duo/Kconfig @@ -7,7 +7,7 @@ config SYS_VENDOR default "sophgo" config SYS_CPU - default "generic" + default "cv1800b" config SYS_CONFIG_NAME default "milkv_duo" @@ -23,6 +23,6 @@ config ENV_SECT_SIZE config BOARD_SPECIFIC_OPTIONS def_bool y - select GENERIC_RISCV + select SOPHGO_CV1800B endif diff --git a/board/starfive/visionfive2/spl.c b/board/starfive/visionfive2/spl.c index 1b49945..45848db 100644 --- a/board/starfive/visionfive2/spl.c +++ b/board/starfive/visionfive2/spl.c @@ -4,7 +4,6 @@ * Author: Yanhong Wang<yanhong.wang@starfivetech.com> */ -#include <common.h> #include <asm/arch/eeprom.h> #include <asm/arch/gpio.h> #include <asm/arch/regs.h> @@ -27,6 +26,26 @@ struct starfive_vf2_pro { const char *value; }; +static const struct starfive_vf2_pro milk_v_mars[] = { + {"/soc/ethernet@16030000", "starfive,tx-use-rgmii-clk", NULL}, + {"/soc/ethernet@16040000", "starfive,tx-use-rgmii-clk", NULL}, + + {"/soc/ethernet@16030000/mdio/ethernet-phy@0", + "motorcomm,tx-clk-adj-enabled", NULL}, + {"/soc/ethernet@16030000/mdio/ethernet-phy@0", + "motorcomm,tx-clk-100-inverted", NULL}, + {"/soc/ethernet@16030000/mdio/ethernet-phy@0", + "motorcomm,tx-clk-1000-inverted", NULL}, + {"/soc/ethernet@16030000/mdio/ethernet-phy@0", + "motorcomm,rx-clk-drv-microamp", "3970"}, + {"/soc/ethernet@16030000/mdio/ethernet-phy@0", + "motorcomm,rx-data-drv-microamp", "2910"}, + {"/soc/ethernet@16030000/mdio/ethernet-phy@0", + "rx-internal-delay-ps", "1900"}, + {"/soc/ethernet@16030000/mdio/ethernet-phy@0", + "tx-internal-delay-ps", "1500"}, +}; + static const struct starfive_vf2_pro starfive_vera[] = { {"/soc/ethernet@16030000/mdio/ethernet-phy@0", "rx-internal-delay-ps", "1900"}, @@ -67,6 +86,49 @@ static const struct starfive_vf2_pro starfive_verb[] = { "tx-internal-delay-ps", "0"}, }; +void spl_fdt_fixup_mars(void *fdt) +{ + static const char compat[] = "milkv,mars\0starfive,jh7110"; + u32 phandle; + u8 i; + int offset; + int ret; + + fdt_setprop(fdt, fdt_path_offset(fdt, "/"), "compatible", compat, sizeof(compat)); + fdt_setprop_string(fdt, fdt_path_offset(fdt, "/"), "model", + "Milk-V Mars"); + + /* gmac0 */ + offset = fdt_path_offset(fdt, "/soc/clock-controller@17000000"); + phandle = fdt_get_phandle(fdt, offset); + offset = fdt_path_offset(fdt, "/soc/ethernet@16030000"); + + fdt_setprop_u32(fdt, offset, "assigned-clocks", phandle); + fdt_appendprop_u32(fdt, offset, "assigned-clocks", JH7110_AONCLK_GMAC0_TX); + fdt_setprop_u32(fdt, offset, "assigned-clock-parents", phandle); + fdt_appendprop_u32(fdt, offset, "assigned-clock-parents", + JH7110_AONCLK_GMAC0_RMII_RTX); + + /* gmac1 */ + fdt_setprop_string(fdt, fdt_path_offset(fdt, "/soc/ethernet@16040000"), + "status", "disabled"); + + for (i = 0; i < ARRAY_SIZE(milk_v_mars); i++) { + offset = fdt_path_offset(fdt, milk_v_mars[i].path); + + if (milk_v_mars[i].value) + ret = fdt_setprop_u32(fdt, offset, milk_v_mars[i].name, + dectoul(milk_v_mars[i].value, NULL)); + else + ret = fdt_setprop_empty(fdt, offset, milk_v_mars[i].name); + + if (ret) { + pr_err("%s set prop %s fail.\n", __func__, milk_v_mars[i].name); + break; + } + } +} + void spl_fdt_fixup_version_a(void *fdt) { static const char compat[] = "starfive,visionfive-2-v1.2a\0starfive,jh7110"; @@ -167,22 +229,34 @@ void spl_fdt_fixup_version_b(void *fdt) void spl_perform_fixups(struct spl_image_info *spl_image) { u8 version; + const char *product_id; - version = get_pcb_revision_from_eeprom(); - switch (version) { - case 'a': - case 'A': - spl_fdt_fixup_version_a(spl_image->fdt_addr); - break; - - case 'b': - case 'B': - default: - spl_fdt_fixup_version_b(spl_image->fdt_addr); + product_id = get_product_id_from_eeprom(); + if (!product_id) { + pr_err("Can't read EEPROM\n"); + return; + } + if (!strncmp(product_id, "MARS", 4)) { + spl_fdt_fixup_mars(spl_image->fdt_addr); + } else if (!strncmp(product_id, "VF7110", 6)) { + version = get_pcb_revision_from_eeprom(); + switch (version) { + case 'a': + case 'A': + spl_fdt_fixup_version_a(spl_image->fdt_addr); + break; + + case 'b': + case 'B': + default: + spl_fdt_fixup_version_b(spl_image->fdt_addr); break; + }; + } else { + pr_err("Unknown product %s\n", product_id); }; - /* Update the memory size which read form eeprom or DT */ + /* Update the memory size which read from eeprom or DT */ fdt_fixup_memory(spl_image->fdt_addr, 0x40000000, gd->ram_size); } diff --git a/board/starfive/visionfive2/starfive_visionfive2.c b/board/starfive/visionfive2/starfive_visionfive2.c index 78e118d..a86bca5 100644 --- a/board/starfive/visionfive2/starfive_visionfive2.c +++ b/board/starfive/visionfive2/starfive_visionfive2.c @@ -4,11 +4,11 @@ * Author: Yanhong Wang<yanhong.wang@starfivetech.com> */ -#include <common.h> #include <cpu_func.h> #include <dm.h> #include <fdt_support.h> #include <env.h> +#include <log.h> #include <asm/arch/eeprom.h> #include <asm/io.h> #include <asm/sections.h> @@ -17,6 +17,8 @@ DECLARE_GLOBAL_DATA_PTR; #define JH7110_L2_PREFETCHER_BASE_ADDR 0x2030000 #define JH7110_L2_PREFETCHER_HART_OFFSET 0x2000 +#define FDTFILE_MILK_V_MARS \ + "starfive/jh7110-milkv-mars.dtb" #define FDTFILE_VISIONFIVE2_1_2A \ "starfive/jh7110-starfive-visionfive-2-v1.2a.dtb" #define FDTFILE_VISIONFIVE2_1_3B \ @@ -48,20 +50,38 @@ static void set_fdtfile(void) { u8 version; const char *fdtfile; + const char *product_id; - version = get_pcb_revision_from_eeprom(); - switch (version) { - case 'a': - case 'A': - fdtfile = FDTFILE_VISIONFIVE2_1_2A; - break; - - case 'b': - case 'B': - default: - fdtfile = FDTFILE_VISIONFIVE2_1_3B; - break; - }; + fdtfile = env_get("fdtfile"); + if (fdtfile) + return; + + product_id = get_product_id_from_eeprom(); + if (!product_id) { + log_err("Can't read EEPROM\n"); + return; + } + if (!strncmp(product_id, "MARS", 4)) { + fdtfile = FDTFILE_MILK_V_MARS; + } else if (!strncmp(product_id, "VF7110", 6)) { + version = get_pcb_revision_from_eeprom(); + + switch (version) { + case 'a': + case 'A': + fdtfile = FDTFILE_VISIONFIVE2_1_2A; + break; + + case 'b': + case 'B': + default: + fdtfile = FDTFILE_VISIONFIVE2_1_3B; + break; + } + } else { + log_err("Unknown product\n"); + return; + } env_set("fdtfile", fdtfile); } diff --git a/board/starfive/visionfive2/visionfive2-i2c-eeprom.c b/board/starfive/visionfive2/visionfive2-i2c-eeprom.c index c36de1a..ddef7d6 100644 --- a/board/starfive/visionfive2/visionfive2-i2c-eeprom.c +++ b/board/starfive/visionfive2/visionfive2-i2c-eeprom.c @@ -4,7 +4,6 @@ * Author: Yanhong Wang<yanhong.wang@starfivetech.com> */ -#include <common.h> #include <command.h> #include <env.h> #include <i2c.h> @@ -405,6 +404,14 @@ static void set_product_id(char *string) update_crc(); } +const char *get_product_id_from_eeprom(void) +{ + if (read_eeprom()) + return NULL; + + return pbuf.eeprom.atom1.data.pstr; +} + int do_mac(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[]) { char *cmd; diff --git a/configs/milkv_duo_defconfig b/configs/milkv_duo_defconfig index 548adf1..e8413d7 100644 --- a/configs/milkv_duo_defconfig +++ b/configs/milkv_duo_defconfig @@ -17,6 +17,16 @@ CONFIG_SYS_CBSIZE=512 CONFIG_SYS_PBSIZE=544 CONFIG_HUSH_PARSER=y CONFIG_SYS_PROMPT="milkv_duo# " +CONFIG_CMD_MMC=y +CONFIG_CMD_PART=y +CONFIG_CMD_FAT=y +CONFIG_CMD_FS_GENERIC=y CONFIG_ENV_OVERWRITE=y +CONFIG_MMC=y +CONFIG_MMC_IO_VOLTAGE=y +CONFIG_MMC_UHS_SUPPORT=y +CONFIG_MMC_SDHCI=y +CONFIG_MMC_SDHCI_ADMA=y +CONFIG_MMC_SDHCI_CV1800B=y CONFIG_SYS_NS16550=y CONFIG_SYS_NS16550_MEM32=y diff --git a/configs/starfive_visionfive2_defconfig b/configs/starfive_visionfive2_defconfig index 7a3f1d4..fa80d48 100644 --- a/configs/starfive_visionfive2_defconfig +++ b/configs/starfive_visionfive2_defconfig @@ -40,7 +40,6 @@ CONFIG_USE_BOOTARGS=y CONFIG_BOOTARGS="console=ttyS0,115200 debug rootwait earlycon=sbi" CONFIG_USE_PREBOOT=y CONFIG_PREBOOT="nvme scan; usb start; setenv fdt_addr ${fdtcontroladdr}; fdt addr ${fdtcontroladdr};" -CONFIG_DEFAULT_FDT_FILE="starfive/jh7110-starfive-visionfive-2.dtb" CONFIG_SYS_CBSIZE=256 CONFIG_SYS_PBSIZE=276 CONFIG_DISPLAY_CPUINFO=y diff --git a/doc/board/starfive/index.rst b/doc/board/starfive/index.rst index 0c52dc7..2762bf7 100644 --- a/doc/board/starfive/index.rst +++ b/doc/board/starfive/index.rst @@ -6,4 +6,5 @@ StarFive .. toctree:: :maxdepth: 1 + milk-v_mars.rst visionfive2 diff --git a/doc/board/starfive/milk-v_mars.rst b/doc/board/starfive/milk-v_mars.rst new file mode 100644 index 0000000..554932e --- /dev/null +++ b/doc/board/starfive/milk-v_mars.rst @@ -0,0 +1,111 @@ +.. SPDX-License-Identifier: GPL-2.0+ + +Milk-V Mars +=========== + +U-Boot for the Milk-V Mars uses the same U-Boot binaries as the VisionFive 2 +board. In U-Boot SPL the actual board is detected and the device-tree patched +accordingly. + +Building +~~~~~~~~ + +1. Add the RISC-V toolchain to your PATH. +2. Setup ARCH & cross compilation environment variable: + +.. code-block:: none + + export CROSS_COMPILE=<riscv64 toolchain prefix> + +The M-mode software OpenSBI provides the supervisor binary interface (SBI) and +is responsible for the switch to S-Mode. It is a prerequisite to build U-Boot. +Support for the JH7110 was introduced in OpenSBI 1.2. It is recommended to use +a current release. + +.. code-block:: console + + git clone https://github.com/riscv/opensbi.git + cd opensbi + make PLATFORM=generic FW_TEXT_START=0x40000000 FW_OPTIONS=0 + +Now build the U-Boot SPL and U-Boot proper. + +.. code-block:: console + + cd <U-Boot-dir> + make starfive_visionfive2_defconfig + make OPENSBI=$(opensbi_dir)/build/platform/generic/firmware/fw_dynamic.bin + +This will generate the U-Boot SPL image (spl/u-boot-spl.bin.normal.out) as well +as the FIT image (u-boot.itb) with OpenSBI and U-Boot. + +Device-tree selection +~~~~~~~~~~~~~~~~~~~~~ + +Depending on the board version U-Boot set variable $fdtfile to either +starfive/jh7110-starfive-visionfive-2-v1.2a.dtb or +starfive/jh7110-starfive-visionfive-2-v1.3b.dtb. + +To overrule this selection the variable can be set manually and saved in the +environment + +:: + + setenv fdtfile my_device-tree.dtb + env save + +or the configuration variable CONFIG_DEFAULT_FDT_FILE can be used to set to +provide a default value. + +Boot source selection +~~~~~~~~~~~~~~~~~~~~~ + +The board provides the DIP switches MSEL[1:0] to select the boot device out of +SPI flash, eMMC, SD-card, UART. To select booting from SD-card set the DIP +switches MSEL[1:0] to 10. + +Preparing the SD-Card +~~~~~~~~~~~~~~~~~~~~~ + +The device firmware loads U-Boot SPL (u-boot-spl.bin.normal.out) from the +partition with type GUID 2E54B353-1271-4842-806F-E436D6AF6985. You are free +to choose any partition number. + +With the default configuration U-Boot SPL loads the U-Boot FIT image +(u-boot.itb) from partition 2 (CONFIG_SYS_MMCSD_RAW_MODE_U_BOOT_PARTITION=0x2). +When formatting it is recommended to use GUID +BC13C2FF-59E6-4262-A352-B275FD6F7172 for this partition. + +The FIT image (u-boot.itb) is a combination of OpenSBI's fw_dynamic.bin, +u-boot-nodtb.bin and the device tree blob. + +Format the SD card (make sure the disk has GPT, otherwise use gdisk to switch) + +.. code-block:: bash + + sudo sgdisk --clear \ + --set-alignment=2 \ + --new=1:4096:8191 --change-name=1:spl --typecode=1:2E54B353-1271-4842-806F-E436D6AF6985\ + --new=2:8192:16383 --change-name=2:uboot --typecode=2:BC13C2FF-59E6-4262-A352-B275FD6F7172 \ + --new=3:16384:1654784 --change-name=3:system --typecode=3:EBD0A0A2-B9E5-4433-87C0-68B6B72699C7 \ + /dev/sdb + +Copy U-Boot to the SD card + +.. code-block:: bash + + sudo dd if=u-boot-spl.bin.normal.out of=/dev/sdb1 + sudo dd if=u-boot.itb of=/dev/sdb2 + + sudo mount /dev/sdb3 /mnt/ + sudo cp u-boot-spl.bin.normal.out /mnt/ + sudo cp u-boot.itb /mnt/ + sudo cp Image.gz /mnt/ + sudo cp initramfs.cpio.gz /mnt/ + sudo cp jh7110-starfive-visionfive-2.dtb /mnt/ + sudo umount /mnt + +Booting +~~~~~~~ + +Once you plugin the sdcard and power up, you should see the U-Boot prompt. diff --git a/doc/board/starfive/visionfive2.rst b/doc/board/starfive/visionfive2.rst index abda8ac..2c68df3 100644 --- a/doc/board/starfive/visionfive2.rst +++ b/doc/board/starfive/visionfive2.rst @@ -71,6 +71,24 @@ Now build the U-Boot SPL and U-Boot proper This will generate the U-Boot SPL image (spl/u-boot-spl.bin.normal.out) as well as the FIT image (u-boot.itb) with OpenSBI and U-Boot. +Device-tree selection +~~~~~~~~~~~~~~~~~~~~~ + +Depending on the board version U-Boot set variable $fdtfile to either +starfive/jh7110-starfive-visionfive-2-v1.2a.dtb or +starfive/jh7110-starfive-visionfive-2-v1.3b.dtb. + +To overrule this selection the variable can be set manually and saved in the +environment + +:: + + setenv fdtfile my_device-tree.dtb + env save + +or the configuration variable CONFIG_DEFAULT_FDT_FILE can be used to provide +a default value. + Flashing ~~~~~~~~ diff --git a/drivers/cpu/riscv_cpu.c b/drivers/cpu/riscv_cpu.c index 5d1026b..9b1950e 100644 --- a/drivers/cpu/riscv_cpu.c +++ b/drivers/cpu/riscv_cpu.c @@ -21,13 +21,13 @@ DECLARE_GLOBAL_DATA_PTR; static int riscv_cpu_get_desc(const struct udevice *dev, char *buf, int size) { - const char *isa; + const char *cpu; - isa = dev_read_string(dev, "riscv,isa"); - if (size < (strlen(isa) + 1)) + cpu = dev_read_string(dev, "compatible"); + if (size < (strlen(cpu) + 1)) return -ENOSPC; - strcpy(buf, isa); + strcpy(buf, cpu); return 0; } diff --git a/drivers/mmc/Kconfig b/drivers/mmc/Kconfig index cef0579..f7fe6d1 100644 --- a/drivers/mmc/Kconfig +++ b/drivers/mmc/Kconfig @@ -568,6 +568,19 @@ config MMC_SDHCI_CADENCE If unsure, say N. +config MMC_SDHCI_CV1800B + bool "SDHCI support for the CV1800B SD/SDIO/eMMC controller" + depends on BLK && DM_MMC + depends on MMC_SDHCI + depends on OF_CONTROL + help + This selects the CV1800B SD/SDIO/eMMC driver. + + If you have a controller with this interface, + say Y here. + + If unsure, say N. + config MMC_SDHCI_AM654 bool "SDHCI Controller on TI's Am654 devices" depends on ARCH_K3 diff --git a/drivers/mmc/Makefile b/drivers/mmc/Makefile index e9cf1fc..3374321 100644 --- a/drivers/mmc/Makefile +++ b/drivers/mmc/Makefile @@ -60,6 +60,7 @@ obj-$(CONFIG_MMC_SDHCI_ATMEL) += atmel_sdhci.o obj-$(CONFIG_MMC_SDHCI_BCM2835) += bcm2835_sdhci.o obj-$(CONFIG_MMC_SDHCI_BCMSTB) += bcmstb_sdhci.o obj-$(CONFIG_MMC_SDHCI_CADENCE) += sdhci-cadence.o +obj-$(CONFIG_MMC_SDHCI_CV1800B) += cv1800b_sdhci.o obj-$(CONFIG_MMC_SDHCI_AM654) += am654_sdhci.o obj-$(CONFIG_MMC_SDHCI_IPROC) += iproc_sdhci.o obj-$(CONFIG_MMC_SDHCI_KONA) += kona_sdhci.o diff --git a/drivers/mmc/cv1800b_sdhci.c b/drivers/mmc/cv1800b_sdhci.c new file mode 100644 index 0000000..2275c53 --- /dev/null +++ b/drivers/mmc/cv1800b_sdhci.c @@ -0,0 +1,116 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright (c) 2024, Kongyang Liu <seashell11234455@gmail.com> + */ + +#include <dm.h> +#include <mmc.h> +#include <sdhci.h> +#include <linux/delay.h> + +#define SDHCI_PHY_TX_RX_DLY 0x240 +#define MMC_MAX_CLOCK 375000000 +#define TUNE_MAX_PHCODE 128 + +struct cv1800b_sdhci_plat { + struct mmc_config cfg; + struct mmc mmc; +}; + +static void cv1800b_set_tap_delay(struct sdhci_host *host, u16 tap) +{ + sdhci_writel(host, tap << 16, SDHCI_PHY_TX_RX_DLY); +} + +static void cv1800b_sdhci_reset(struct sdhci_host *host, u8 mask) +{ + sdhci_writeb(host, mask, SDHCI_SOFTWARE_RESET); + while (sdhci_readb(host, SDHCI_SOFTWARE_RESET) & mask) + udelay(10); +} + +static int cv1800b_execute_tuning(struct mmc *mmc, u8 opcode) +{ + struct sdhci_host *host = dev_get_priv(mmc->dev); + + u16 tap; + + int current_size = 0; + int max_size = 0; + int max_window = 0; + + for (tap = 0; tap < TUNE_MAX_PHCODE; tap++) { + cv1800b_set_tap_delay(host, tap); + + if (mmc_send_tuning(host->mmc, opcode, NULL)) { + current_size = 0; + } else { + current_size++; + if (current_size > max_size) { + max_size = current_size; + max_window = tap; + } + } + } + + cv1800b_sdhci_reset(host, SDHCI_RESET_CMD | SDHCI_RESET_DATA); + + cv1800b_set_tap_delay(host, max_window - max_size / 2); + + return 0; +} + +const struct sdhci_ops cv1800b_sdhci_sd_ops = { + .platform_execute_tuning = cv1800b_execute_tuning, +}; + +static int cv1800b_sdhci_bind(struct udevice *dev) +{ + struct cv1800b_sdhci_plat *plat = dev_get_plat(dev); + + return sdhci_bind(dev, &plat->mmc, &plat->cfg); +} + +static int cv1800b_sdhci_probe(struct udevice *dev) +{ + struct mmc_uclass_priv *upriv = dev_get_uclass_priv(dev); + struct cv1800b_sdhci_plat *plat = dev_get_plat(dev); + struct sdhci_host *host = dev_get_priv(dev); + int ret; + + host->name = dev->name; + host->ioaddr = devfdt_get_addr_ptr(dev); + + upriv->mmc = &plat->mmc; + host->mmc = &plat->mmc; + host->mmc->priv = host; + host->mmc->dev = dev; + host->ops = &cv1800b_sdhci_sd_ops; + host->max_clk = MMC_MAX_CLOCK; + + ret = mmc_of_parse(dev, &plat->cfg); + if (ret) + return ret; + + ret = sdhci_setup_cfg(&plat->cfg, host, 0, 200000); + if (ret) + return ret; + + return sdhci_probe(dev); +} + +static const struct udevice_id cv1800b_sdhci_match[] = { + { .compatible = "sophgo,cv1800b-dwcmshc" }, + { } +}; + +U_BOOT_DRIVER(cv1800b_sdhci) = { + .name = "sdhci-cv1800b", + .id = UCLASS_MMC, + .of_match = cv1800b_sdhci_match, + .bind = cv1800b_sdhci_bind, + .probe = cv1800b_sdhci_probe, + .priv_auto = sizeof(struct sdhci_host), + .plat_auto = sizeof(struct cv1800b_sdhci_plat), + .ops = &sdhci_ops, +}; |