CI: https://source.denx.de/u-boot/custodians/u-boot-riscv/-/pipelines/20690

- RISC-V: Add NULL check after parsing compatible string
- Board: Add Milk-V Mars CM board
- Andes: Unify naming policy
This commit is contained in:
Tom Rini
2024-05-14 07:45:49 -06:00
27 changed files with 337 additions and 56 deletions

View File

@@ -80,7 +80,7 @@ config SPL_ZERO_MEM_BEFORE_USE
Sifive core devices that uses L2 cache to store SPL.
# board-specific options below
source "board/AndesTech/ae350/Kconfig"
source "board/andestech/ae350/Kconfig"
source "board/emulation/qemu-riscv/Kconfig"
source "board/microchip/mpfs_icicle/Kconfig"
source "board/openpiton/riscv64/Kconfig"
@@ -93,7 +93,7 @@ source "board/thead/th1520_lpi4a/Kconfig"
source "board/xilinx/mbv/Kconfig"
# platform-specific options below
source "arch/riscv/cpu/andesv5/Kconfig"
source "arch/riscv/cpu/andes/Kconfig"
source "arch/riscv/cpu/cv1800b/Kconfig"
source "arch/riscv/cpu/fu540/Kconfig"
source "arch/riscv/cpu/fu740/Kconfig"

View File

@@ -1,4 +1,4 @@
config RISCV_NDS
config RISCV_ANDES
bool
select ARCH_EARLY_INIT_R
select SYS_CACHE_SHIFT_6
@@ -8,7 +8,7 @@ config RISCV_NDS
imply ANDES_PLMT_TIMER
imply SPL_ANDES_PLMT_TIMER
imply ANDES_PLICSW if (RISCV_MMODE || SPL_RISCV_MMODE)
imply V5L2_CACHE
imply ANDES_L2_CACHE
imply SPL_CPU
imply SPL_OPENSBI
imply SPL_LOAD_FIT

View File

@@ -12,21 +12,21 @@
#include <dm/uclass-internal.h>
#include <asm/arch-andes/csr.h>
#ifdef CONFIG_V5L2_CACHE
#ifdef CONFIG_ANDES_L2_CACHE
void enable_caches(void)
{
struct udevice *dev;
int ret;
ret = uclass_get_device_by_driver(UCLASS_CACHE,
DM_DRIVER_GET(v5l2_cache),
DM_DRIVER_GET(andes_l2_cache),
&dev);
if (ret) {
log_debug("Cannot enable v5l2 cache\n");
log_debug("Cannot enable Andes L2 cache\n");
} else {
ret = cache_enable(dev);
if (ret)
log_debug("v5l2 cache enable failed\n");
log_debug("Failed to enable Andes L2 cache\n");
}
}
@@ -78,7 +78,7 @@ void dcache_enable(void)
asm volatile("csrsi %0, 0x2" :: "i"(CSR_MCACHE_CTL));
#endif
#ifdef CONFIG_V5L2_CACHE
#ifdef CONFIG_ANDES_L2_CACHE
cache_ops(cache_enable);
#endif
}
@@ -89,7 +89,7 @@ void dcache_disable(void)
asm volatile("csrci %0, 0x2" :: "i"(CSR_MCACHE_CTL));
#endif
#ifdef CONFIG_V5L2_CACHE
#ifdef CONFIG_ANDES_L2_CACHE
cache_ops(cache_disable);
#endif
}

View File

@@ -12,6 +12,13 @@
u8 get_pcb_revision_from_eeprom(void);
u32 get_ddr_size_from_eeprom(void);
/**
* get_mmc_size_from_eeprom() - read eMMC size from EEPROM
*
* @return: size in GiB or 0 on error.
*/
u32 get_mmc_size_from_eeprom(void);
/**
* get_product_id_from_eeprom - get product ID string
*

View File

@@ -60,21 +60,20 @@ 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)
static void __maybe_unused show_backtrace(struct pt_regs *regs)
{
uintptr_t *fp = (uintptr_t *)regs->s0;
unsigned count = 0;
ulong ra;
printf("backtrace:\n");
printf("\nbacktrace:\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,
printf("%3d: FP: " REG_FMT " RA: " REG_FMT,
count, (ulong)fp, ra);
if (gd && gd->flags & GD_FLG_RELOC)
@@ -87,12 +86,6 @@ static void show_backtrace(struct pt_regs *regs)
count++;
}
}
#else
static void show_backtrace(struct pt_regs *regs)
{
printf("No backtrace support enabled\n");
}
#endif
/**
* instr_len() - get instruction length
@@ -165,7 +158,8 @@ 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);
if (CONFIG_IS_ENABLED(FRAMEPOINTER))
show_backtrace(regs);
show_code(epc);
show_efi_loaded_images(epc);
panic("\n");

View File

@@ -1,13 +1,13 @@
if TARGET_ANDES_AE350
config SYS_CPU
default "andesv5"
default "andes"
config SYS_BOARD
default "ae350"
config SYS_VENDOR
default "AndesTech"
default "andestech"
config SYS_SOC
default "ae350"
@@ -33,7 +33,7 @@ config SYS_FDT_BASE
config BOARD_SPECIFIC_OPTIONS # dummy
def_bool y
select RISCV_NDS
select RISCV_ANDES
select SUPPORT_SPL
select BINMAN if SPL
imply SMP

View File

@@ -1,7 +1,7 @@
AE350 BOARD
M: Rick Chen <rick@andestech.com>
S: Maintained
F: board/AndesTech/ae350/
F: board/andestech/ae350/
F: include/configs/ae350.h
F: configs/ae350_rv32_defconfig
F: configs/ae350_rv32_falcon_defconfig

View File

@@ -99,7 +99,7 @@ void *board_fdt_blob_setup(int *err)
#ifdef CONFIG_SPL_BOARD_INIT
void spl_board_init()
{
/* enable v5l2 cache */
/* enable andes-l2 cache */
if (!CONFIG_IS_ENABLED(SYS_DCACHE_OFF))
enable_caches();
}

View File

@@ -50,4 +50,13 @@ config BOARD_SPECIFIC_OPTIONS # dummy
imply PHY_LIB
imply PHY_MSCC
config STARFIVE_NO_EMMC
bool "Report eMMC size as zero"
help
The serial number string in the EEPROM is meant to report the
size of onboard eMMC. Unfortunately some Milk-V Mars CM Lite
modules without eMMC show a non-zero size here.
Set to 'Y' if you have a Mars CM Lite module.
endif

View File

@@ -129,6 +129,30 @@ void spl_fdt_fixup_mars(void *fdt)
}
}
void spl_fdt_fixup_mars_cm(void *fdt)
{
const char *compat;
const char *model;
spl_fdt_fixup_mars(fdt);
if (!get_mmc_size_from_eeprom()) {
int offset;
model = "Milk-V Mars CM Lite";
compat = "milkv,mars-cm-lite\0starfive,jh7110";
offset = fdt_path_offset(fdt, "/soc/pinctrl/mmc0-pins/mmc0-pins-rest");
/* GPIOMUX(22, GPOUT_SYS_SDIO0_RST, GPOEN_ENABLE, GPI_NONE) */
fdt_setprop_u32(fdt, offset, "pinmux", 0xff130016);
} else {
model = "Milk-V Mars CM";
compat = "milkv,mars-cm\0starfive,jh7110";
}
fdt_setprop(fdt, fdt_path_offset(fdt, "/"), "compatible", compat, sizeof(compat));
fdt_setprop_string(fdt, fdt_path_offset(fdt, "/"), "model", model);
}
void spl_fdt_fixup_version_a(void *fdt)
{
static const char compat[] = "starfive,visionfive-2-v1.2a\0starfive,jh7110";
@@ -236,7 +260,9 @@ void spl_perform_fixups(struct spl_image_info *spl_image)
pr_err("Can't read EEPROM\n");
return;
}
if (!strncmp(product_id, "MARS", 4)) {
if (!strncmp(product_id, "MARC", 4)) {
spl_fdt_fixup_mars_cm(spl_image->fdt_addr);
} else 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();

View File

@@ -19,6 +19,10 @@ DECLARE_GLOBAL_DATA_PTR;
#define JH7110_L2_PREFETCHER_HART_OFFSET 0x2000
#define FDTFILE_MILK_V_MARS \
"starfive/jh7110-milkv-mars.dtb"
#define FDTFILE_MILK_V_MARS_CM \
"starfive/jh7110-milkv-mars-cm.dtb"
#define FDTFILE_MILK_V_MARS_CM_LITE \
"starfive/jh7110-milkv-mars-cm-lite.dtb"
#define FDTFILE_VISIONFIVE2_1_2A \
"starfive/jh7110-starfive-visionfive-2-v1.2a.dtb"
#define FDTFILE_VISIONFIVE2_1_3B \
@@ -61,7 +65,12 @@ static void set_fdtfile(void)
log_err("Can't read EEPROM\n");
return;
}
if (!strncmp(product_id, "MARS", 4)) {
if (!strncmp(product_id, "MARC", 4)) {
if (get_mmc_size_from_eeprom())
fdtfile = FDTFILE_MILK_V_MARS_CM;
else
fdtfile = FDTFILE_MILK_V_MARS_CM_LITE;
} else if (!strncmp(product_id, "MARS", 4)) {
fdtfile = FDTFILE_MILK_V_MARS;
} else if (!strncmp(product_id, "VF7110", 6)) {
version = get_pcb_revision_from_eeprom();

View File

@@ -404,6 +404,24 @@ static void set_product_id(char *string)
update_crc();
}
/**
* set_vendor() - set vendor name
*
* Takes a pointer to a string representing the vendor name, e.g.
* "StarFive Technology Co., Ltd.", stores it in the vendor field
* of the EEPROM local copy, and updates the CRC of the local copy.
*/
static void set_vendor(char *string)
{
memset(pbuf.eeprom.atom1.data.vstr, 0,
sizeof(pbuf.eeprom.atom1.data.vstr));
strncpy(pbuf.eeprom.atom1.data.vstr,
string, sizeof(pbuf.eeprom.atom1.data.vstr) - 1);
update_crc();
}
const char *get_product_id_from_eeprom(void)
{
if (read_eeprom())
@@ -463,6 +481,9 @@ int do_mac(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[])
} else if (!strcmp(cmd, "product_id")) {
set_product_id(argv[2]);
return 0;
} else if (!strcmp(cmd, "vendor")) {
set_vendor(argv[2]);
return 0;
}
return CMD_RET_USAGE;
@@ -548,6 +569,24 @@ u32 get_ddr_size_from_eeprom(void)
return hextoul(&pbuf.eeprom.atom1.data.pstr[14], NULL);
}
u32 get_mmc_size_from_eeprom(void)
{
u32 size;
if (IS_ENABLED(CONFIG_STARFIVE_NO_EMMC))
return 0;
if (read_eeprom())
return 0;
size = dectoul(&pbuf.eeprom.atom1.data.pstr[19], NULL);
if (pbuf.eeprom.atom1.data.pstr[21] == 'T')
size <<= 10;
return size;
}
U_BOOT_LONGHELP(mac,
"\n"
" - display EEPROM content\n"
@@ -568,7 +607,9 @@ U_BOOT_LONGHELP(mac,
"mac bom_revision <A>\n"
" - stores a StarFive BOM revision into the local EEPROM copy\n"
"mac product_id <VF7110A1-2228-D008E000-xxxxxxxx>\n"
" - stores a StarFive product ID into the local EEPROM copy\n");
" - stores a StarFive product ID into the local EEPROM copy\n"
"mac vendor <Vendor Name>\n"
" - set vendor string\n");
U_BOOT_CMD(
mac, 3, 1, do_mac,

View File

@@ -62,6 +62,7 @@ CONFIG_SPL_I2C=y
CONFIG_SPL_DM_SPI_FLASH=y
CONFIG_SPL_DM_RESET=y
CONFIG_SPL_SPI_LOAD=y
CONFIG_SPL_YMODEM_SUPPORT=y
CONFIG_SYS_PROMPT="StarFive # "
CONFIG_CMD_EEPROM=y
CONFIG_SYS_EEPROM_SIZE=512

View File

@@ -8,7 +8,7 @@ Board-specific doc
actions/index
advantech/index
AndesTech/index
andestech/index
allwinner/index
amlogic/index
anbernic/index

View File

@@ -6,5 +6,6 @@ StarFive
.. toctree::
:maxdepth: 1
milk-v_mars.rst
milk-v_mars
milk-v_mars_cm
visionfive2

View File

@@ -0,0 +1,193 @@
.. SPDX-License-Identifier: GPL-2.0+
Milk-V Mars CM
==============
U-Boot for the Milk-V Mars CM 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.
The Milk-V Mars CM Lite comes without eMMC and needs a different pin muxing
than the Milk-V Mars CM. The availability and size of the eMMC shows up in the
serial number displayed by the *mac* command, e.g.
MARC-V10-2340-D002E016-00000304. The number after the E is the MMC size. U-Boot
takes a value of E000 as an indicator for the Lite version. Unfortunately the
vendor has not set this value correctly on some Lite boards.
Please, use CONFIG_STARFIVE_NO_EMMC=y if EEPROM data indicates eMMC is present
on the Milk-V Mars CM Lite. Otherwise you will not be able to read from the
SD-card.
The serial number can be corrected using the *mac* command:
.. code-block::
mac read_eeprom
mac product_id MARC-V10-2340-D002E000-00000304
mac write_eeprom
.. note::
The *mac initialize* command overwrites the vendor string and the MAC
addresses. This is why it is avoided here.
By default the EEPROM is write protected. The write protection may be overcome
by connecting the "GND" and "EN" test pads on top of the module.
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_TEXT_START* is not needed anymore after OpenSBI patch d4d2582eef7a
"firmware: remove FW_TEXT_START" which should appear in OpenSBI 1.5.)
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 sets variable $fdtfile to either
starfive/jh7110-milkv-mars-cm.dtb (with eMMC storage) or
starfive/jh7110-milkv-mars-cm-lite.dtb (without eMMC storage).
To overrule this selection the variable can be set manually and saved in the
environment
::
env set 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.
The variable *$fdtfile* is used in the boot process to automatically load
a device-tree provided by the operating system. For details of the boot
process refer to the :doc:`U-Boot Standard Boot <../../../develop/bootstd>`
description.
Boot source selection
~~~~~~~~~~~~~~~~~~~~~
The low speed connector nRPIBOOT line is used to switch the boot source.
* If nRPIBOOT is connected to ground, the board boots from UART.
* If nRPIBOOT is not connected, the board boots from SPI flash.
Compute module boards typically have a switch or jumper for this line.
Flashing a new U-Boot version
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
U-Boot SPL is provided as file spl/u-boot-spl.bin.normal.out. Main U-Boot is
in file u-boot.itb.
Assuming your new U-Boot version is on partition 1 of an SD-card you could
install it to the SPI flash with:
::
sf probe
load mmc 0:1 $kernel_addr_r u-boot-spl.bin.normal.out
sf update $kernel_addr_r 0 $filesize
load mmc 0:1 $kernel_addr_r u-boot.itb
sf update $kernel_addr_r 0x100000 $filesize
For loading the files from a TFTP server refer to the dhcp and tftpboot
commands.
After updating U-Boot you may want to reboot and reset the environment to the
default.
::
env default -f -a
env save
Booting from UART
~~~~~~~~~~~~~~~~~
For booting via UART U-Boot must be built with CONFIG_SPL_YMODEM_SUPPORT=y.
With nRPIBOOT connected to ground for UART boot, power the board and upload
u-boot-spl.bin.normal.out via XMODEM. Then upload u-boot.itb via YMODEM.
The XMODEM implementation in the boot ROM is not fully specification compliant.
It sends too many NAKs in a row. Tio is a terminal emulation that tolerates
these faults.
::
$ tio -b 115200 --databits 8 --flow none --stopbits 1 /dev/ttyUSB0
[08:14:54.700] tio v2.7
[08:14:54.700] Press ctrl-t q to quit
[08:14:54.701] Connected
(C)StarFive
CCC
(C)StarFive
CCCCCCCC
Press *ctrl-t x* to initiate XMODEM-1K transfer.
::
[08:15:14.778] Send file with XMODEM
[08:15:22.459] Sending file 'u-boot-spl.bin.normal.out'
[08:15:22.459] Press any key to abort transfer
........................................................................
.......................................................................|
[08:15:22.459] Done
U-Boot SPL 2024.07-rc1-00075-gd6a4ab20097 (Apr 25 2024 - 16:32:10 +0200)
DDR version: dc2e84f0.
Trying to boot from UART
CC
Press *ctrl-t y* to initiate YMODEM transfer.
::
[08:15:50.331] Send file with YMODEM
[08:15:53.540] Sending file 'u-boot.itb'
[08:15:53.540] Press any key to abort transfer
........................................................................
…
...............|
[08:15:53.540] Done
Loaded 1040599 bytes
U-Boot 2024.07-rc1-00075-gd6a4ab20097 (Apr 25 2024 - 16:32:10 +0200)
Booting from SPI flash
~~~~~~~~~~~~~~~~~~~~~~
With nRPIBOOT disconnected from ground for SPI boot, power up the board. You
should see the U-Boot prompt on the serial console.

View File

@@ -22,11 +22,11 @@ config L2X0_CACHE
ARMv7(32-bit) devices. The driver configures the cache settings
found in the device tree.
config V5L2_CACHE
bool "Andes V5L2 cache driver"
config ANDES_L2_CACHE
bool "Andes L2 cache driver"
select CACHE
help
Support Andes V5L2 cache controller in AE350 platform.
Support Andes L2 cache controller in AE350 platform.
It will configure tag and data ram timing control from the
device tree and enable L2 cache.

View File

@@ -3,6 +3,6 @@ obj-$(CONFIG_$(SPL_TPL_)CACHE) += cache-uclass.o
obj-$(CONFIG_SANDBOX) += sandbox_cache.o
obj-$(CONFIG_L2X0_CACHE) += cache-l2x0.o
obj-$(CONFIG_NCORE_CACHE) += cache-ncore.o
obj-$(CONFIG_V5L2_CACHE) += cache-v5l2.o
obj-$(CONFIG_ANDES_L2_CACHE) += cache-andes-l2.o
obj-$(CONFIG_SIFIVE_CCACHE) += cache-sifive-ccache.o
obj-$(CONFIG_SIFIVE_PL2) += cache-sifive-pl2.o

View File

@@ -72,7 +72,7 @@ static u32 status_bit_offset = 0x4;
DECLARE_GLOBAL_DATA_PTR;
struct v5l2_plat {
struct andes_l2_plat {
struct l2cache *regs;
u32 iprefetch;
u32 dprefetch;
@@ -80,9 +80,9 @@ struct v5l2_plat {
u32 dram_ctl[2];
};
static int v5l2_enable(struct udevice *dev)
static int andes_l2_enable(struct udevice *dev)
{
struct v5l2_plat *plat = dev_get_plat(dev);
struct andes_l2_plat *plat = dev_get_plat(dev);
volatile struct l2cache *regs = plat->regs;
if (regs)
@@ -91,9 +91,9 @@ static int v5l2_enable(struct udevice *dev)
return 0;
}
static int v5l2_disable(struct udevice *dev)
static int andes_l2_disable(struct udevice *dev)
{
struct v5l2_plat *plat = dev_get_plat(dev);
struct andes_l2_plat *plat = dev_get_plat(dev);
volatile struct l2cache *regs = plat->regs;
u8 hart = gd->arch.boot_hart;
void __iomem *cctlcmd = (void __iomem *)CCTL_CMD_REG(regs, hart);
@@ -113,9 +113,9 @@ static int v5l2_disable(struct udevice *dev)
return 0;
}
static int v5l2_of_to_plat(struct udevice *dev)
static int andes_l2_of_to_plat(struct udevice *dev)
{
struct v5l2_plat *plat = dev_get_plat(dev);
struct andes_l2_plat *plat = dev_get_plat(dev);
struct l2cache *regs;
regs = dev_read_addr_ptr(dev);
@@ -137,9 +137,9 @@ static int v5l2_of_to_plat(struct udevice *dev)
return 0;
}
static int v5l2_probe(struct udevice *dev)
static int andes_l2_probe(struct udevice *dev)
{
struct v5l2_plat *plat = dev_get_plat(dev);
struct andes_l2_plat *plat = dev_get_plat(dev);
struct l2cache *regs = plat->regs;
u32 cfg_val, ctl_val;
@@ -182,23 +182,23 @@ static int v5l2_probe(struct udevice *dev)
return 0;
}
static const struct udevice_id v5l2_cache_ids[] = {
static const struct udevice_id andes_l2_cache_ids[] = {
{ .compatible = "cache" },
{}
};
static const struct cache_ops v5l2_cache_ops = {
.enable = v5l2_enable,
.disable = v5l2_disable,
static const struct cache_ops andes_l2_cache_ops = {
.enable = andes_l2_enable,
.disable = andes_l2_disable,
};
U_BOOT_DRIVER(v5l2_cache) = {
.name = "v5l2_cache",
U_BOOT_DRIVER(andes_l2_cache) = {
.name = "andes_l2_cache",
.id = UCLASS_CACHE,
.of_match = v5l2_cache_ids,
.of_to_plat = v5l2_of_to_plat,
.probe = v5l2_probe,
.plat_auto = sizeof(struct v5l2_plat),
.ops = &v5l2_cache_ops,
.of_match = andes_l2_cache_ids,
.of_to_plat = andes_l2_of_to_plat,
.probe = andes_l2_probe,
.plat_auto = sizeof(struct andes_l2_plat),
.ops = &andes_l2_cache_ops,
.flags = DM_FLAG_PRE_RELOC,
};

View File

@@ -23,7 +23,7 @@ static int riscv_cpu_get_desc(const struct udevice *dev, char *buf, int size)
const char *cpu;
cpu = dev_read_string(dev, "compatible");
if (size < (strlen(cpu) + 1))
if (!cpu || size < (strlen(cpu) + 1))
return -ENOSPC;
strcpy(buf, cpu);