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
This commit is contained in:
Tom Rini
2024-04-09 14:18:55 -06:00
29 changed files with 647 additions and 62 deletions

View File

@@ -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

View File

@@ -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)

View File

@@ -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;
}
}

View File

@@ -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

View File

@@ -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

View File

@@ -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);
}

View File

@@ -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;
}

View File

@@ -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();
}

View File

@@ -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 ...

View File

@@ -33,6 +33,14 @@
clock-frequency = <25000000>;
};
&sdhci0 {
status = "okay";
bus-width = <4>;
no-1-8-v;
no-mmc;
no-sdio;
};
&uart0 {
status = "okay";
};

View File

@@ -16,3 +16,7 @@
&clint {
compatible = "sophgo,cv1800b-clint", "thead,c900-clint";
};
&clk {
compatible = "sophgo,cv1800-clk";
};

View File

@@ -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>;

View File

@@ -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";

View File

@@ -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 */

View File

@@ -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");

View File

@@ -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;
}

View File

@@ -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

View File

@@ -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;
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);
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);
}

View File

@@ -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;
fdtfile = env_get("fdtfile");
if (fdtfile)
return;
case 'b':
case 'B':
default:
fdtfile = FDTFILE_VISIONFIVE2_1_3B;
break;
};
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);
}

View File

@@ -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;

View File

@@ -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

View File

@@ -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

View File

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

View File

@@ -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.

View File

@@ -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
~~~~~~~~

View File

@@ -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;
}

View File

@@ -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

View File

@@ -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

116
drivers/mmc/cv1800b_sdhci.c Normal file
View File

@@ -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,
};