mirror of
https://source.denx.de/u-boot/u-boot.git
synced 2026-06-13 15:03:58 +03:00
Merge branch 'master' of https://source.denx.de/u-boot/custodians/u-boot-riscv
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:
@@ -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
|
||||
|
||||
@@ -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)
|
||||
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
12
arch/riscv/cpu/cv1800b/Kconfig
Normal file
12
arch/riscv/cpu/cv1800b/Kconfig
Normal 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
|
||||
7
arch/riscv/cpu/cv1800b/Makefile
Normal file
7
arch/riscv/cpu/cv1800b/Makefile
Normal 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
|
||||
45
arch/riscv/cpu/cv1800b/cache.c
Normal file
45
arch/riscv/cpu/cv1800b/cache.c
Normal 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);
|
||||
}
|
||||
9
arch/riscv/cpu/cv1800b/cpu.c
Normal file
9
arch/riscv/cpu/cv1800b/cpu.c
Normal 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;
|
||||
}
|
||||
21
arch/riscv/cpu/cv1800b/dram.c
Normal file
21
arch/riscv/cpu/cv1800b/dram.c
Normal 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();
|
||||
}
|
||||
@@ -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 ...
|
||||
|
||||
@@ -33,6 +33,14 @@
|
||||
clock-frequency = <25000000>;
|
||||
};
|
||||
|
||||
&sdhci0 {
|
||||
status = "okay";
|
||||
bus-width = <4>;
|
||||
no-1-8-v;
|
||||
no-mmc;
|
||||
no-sdio;
|
||||
};
|
||||
|
||||
&uart0 {
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
@@ -16,3 +16,7 @@
|
||||
&clint {
|
||||
compatible = "sophgo,cv1800b-clint", "thead,c900-clint";
|
||||
};
|
||||
|
||||
&clk {
|
||||
compatible = "sophgo,cv1800-clk";
|
||||
};
|
||||
|
||||
@@ -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>;
|
||||
|
||||
@@ -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";
|
||||
|
||||
@@ -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 */
|
||||
|
||||
@@ -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");
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -6,4 +6,5 @@ StarFive
|
||||
.. toctree::
|
||||
:maxdepth: 1
|
||||
|
||||
milk-v_mars.rst
|
||||
visionfive2
|
||||
|
||||
111
doc/board/starfive/milk-v_mars.rst
Normal file
111
doc/board/starfive/milk-v_mars.rst
Normal 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.
|
||||
@@ -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
|
||||
~~~~~~~~
|
||||
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
116
drivers/mmc/cv1800b_sdhci.c
Normal 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,
|
||||
};
|
||||
Reference in New Issue
Block a user