
-----Original Message----- From: Bin Meng bmeng.cn@gmail.com Sent: 03 January 2020 21:05 To: Pragnesh Patel pragnesh.patel@sifive.com Cc: U-Boot Mailing List u-boot@lists.denx.de; Rick Chen rick@andestech.com; Paul Walmsley ( Sifive) paul.walmsley@sifive.com; Palmer Dabbelt ( Sifive) palmer@sifive.com; Anup Patel anup.patel@wdc.com; Atish Patra atish.patra@wdc.com; Lukas Auer lukas.auer@aisec.fraunhofer.de; AKASHI Takahiro takahiro.akashi@linaro.org; Simon Glass sjg@chromium.org; Marek BehĂșn marek.behun@nic.cz; Simon Goldschmidt simon.k.r.goldschmidt@gmail.com; Peng Fan peng.fan@nxp.com; Boris Brezillon bbrezillon@kernel.org; Alexander Graf agraf@csgraf.de Subject: Re: [PATCH 3/3] riscv: sifive: fu540: add SPL configuration
Hi Pragnesh,
On Tue, Dec 31, 2019 at 2:31 PM Pragnesh Patel pragnesh.patel@sifive.com wrote:
This patch provides sifive_fu540_spl_defconfig which can support U-boot SPL to boot from L2 LIM (0x0800_0000) and then boot FIT
nits: U-Boot
image including OpenSBI FW_DYNAMIC firmware and U-Boot proper images from MMC boot devices.
With sifive_fu540_spl_defconfig:
U-Boot SPL will be loaded by ZSBL from SD card (replace fsbl.bin with u-boot-spl.bin) and runs in L2 LIM in machine mode and then load FIT image u-boot.itb from SD card (replace fw_payload.bin with u-boot.itb) into RAM.
SPL related code is leverage from FSBL (https://github.com/sifive/freedom-u540-c000-bootloader.git)
Signed-off-by: Pragnesh Patel pragnesh.patel@sifive.com
arch/riscv/cpu/u-boot-spl.lds | 1 + arch/riscv/dts/fu540-c000-u-boot.dtsi | 65 + .../dts/hifive-unleashed-a00-u-boot.dtsi | 24 + arch/riscv/include/asm/csr.h | 2 + board/sifive/fu540/Kconfig | 8 + board/sifive/fu540/MAINTAINERS | 1 + board/sifive/fu540/Makefile | 6 + board/sifive/fu540/ememoryotp.c | 143 ++ board/sifive/fu540/fu540.c | 31 +- board/sifive/fu540/include/ccache.h | 47 + board/sifive/fu540/include/clkutils.h | 75 + board/sifive/fu540/include/ddrregs.h | 622 +++++++++ board/sifive/fu540/include/ememoryotp.h | 24 + board/sifive/fu540/include/fu540-memory-map.h | 427 ++++++ board/sifive/fu540/include/i2c.h | 49 + board/sifive/fu540/include/regconfig-ctl.h | 274 ++++ board/sifive/fu540/include/regconfig-phy.h | 1224 +++++++++++++++++ board/sifive/fu540/include/spi.h | 233 ++++ board/sifive/fu540/include/uart.h | 54 + board/sifive/fu540/include/ux00ddr.h | 268 ++++ board/sifive/fu540/include/ux00prci.h | 206 +++ board/sifive/fu540/spl.c | 321 +++++ board/sifive/fu540/uart.c | 64 + configs/sifive_fu540_spl_defconfig | 23 + include/configs/sifive-fu540.h | 17 + lib/Makefile | 1 + 26 files changed, 4209 insertions(+), 1 deletion(-) create mode 100644 arch/riscv/dts/fu540-c000-u-boot.dtsi create mode 100644 arch/riscv/dts/hifive-unleashed-a00-u-boot.dtsi create mode 100644 board/sifive/fu540/ememoryotp.c create mode 100644 board/sifive/fu540/include/ccache.h create mode 100644 board/sifive/fu540/include/clkutils.h create mode 100644 board/sifive/fu540/include/ddrregs.h create mode 100644 board/sifive/fu540/include/ememoryotp.h create mode 100644 board/sifive/fu540/include/fu540-memory-map.h create mode 100644 board/sifive/fu540/include/i2c.h create mode 100644 board/sifive/fu540/include/regconfig-ctl.h create mode 100644 board/sifive/fu540/include/regconfig-phy.h create mode 100644 board/sifive/fu540/include/spi.h create mode 100644 board/sifive/fu540/include/uart.h create mode 100644 board/sifive/fu540/include/ux00ddr.h create mode 100644 board/sifive/fu540/include/ux00prci.h create mode 100644 board/sifive/fu540/spl.c create mode 100644 board/sifive/fu540/uart.c create mode 100644 configs/sifive_fu540_spl_defconfig
diff --git a/arch/riscv/cpu/u-boot-spl.lds b/arch/riscv/cpu/u-boot-spl.lds index 955dd3106d..d0495ce248 100644 --- a/arch/riscv/cpu/u-boot-spl.lds +++ b/arch/riscv/cpu/u-boot-spl.lds @@ -72,6 +72,7 @@ SECTIONS . = ALIGN(4);
_end = .;
_image_binary_end = .;
This should be a separate patch.
Sure.
.bss : { __bss_start = .;
diff --git a/arch/riscv/dts/fu540-c000-u-boot.dtsi b/arch/riscv/dts/fu540-
c000-u-boot.dtsi
new file mode 100644 index 0000000000..b86cdfb38d --- /dev/null +++ b/arch/riscv/dts/fu540-c000-u-boot.dtsi @@ -0,0 +1,65 @@ +// SPDX-License-Identifier: GPL-2.0+ +/*
- (C) Copyright 2019 SiFive, Inc
- */
+/ {
cpus {
u-boot,dm-spl;
cpu0: cpu@0 {
u-boot,dm-spl;
status = "okay";
cpu0_intc: interrupt-controller {
u-boot,dm-spl;
};
};
cpu1: cpu@1 {
u-boot,dm-spl;
cpu1_intc: interrupt-controller {
u-boot,dm-spl;
};
};
cpu2: cpu@2 {
u-boot,dm-spl;
cpu2_intc: interrupt-controller {
u-boot,dm-spl;
};
};
cpu3: cpu@3 {
u-boot,dm-spl;
cpu3_intc: interrupt-controller {
u-boot,dm-spl;
};
};
cpu4: cpu@4 {
u-boot,dm-spl;
cpu4_intc: interrupt-controller {
u-boot,dm-spl;
};
};
};
soc {
u-boot,dm-spl;
clint@2000000 {
compatible = "riscv,clint0";
interrupts-extended = <&cpu0_intc 3 &cpu0_intc 7 >;
reg = <0x0 0x2000000 0x0 0xc0000>;
u-boot,dm-spl;
};
};
+};
+&prci {
u-boot,dm-spl;
+};
+&uart0 {
u-boot,dm-spl;
+};
+&qspi2 {
u-boot,dm-spl;
+};
Are all of these peripherals needed in SPL?
As far as I know they are all needed, I will recheck and remove any not needed peripherals in v2.
diff --git a/arch/riscv/dts/hifive-unleashed-a00-u-boot.dtsi
b/arch/riscv/dts/hifive-unleashed-a00-u-boot.dtsi
new file mode 100644 index 0000000000..9b59f4ee14 --- /dev/null +++ b/arch/riscv/dts/hifive-unleashed-a00-u-boot.dtsi @@ -0,0 +1,24 @@ +// SPDX-License-Identifier: GPL-2.0+ +/*
- Copyright (C) 2019 SiFive, Inc
- */
+#include "fu540-c000-u-boot.dtsi"
+/ {
hfclk {
u-boot,dm-spl;
};
rtcclk {
u-boot,dm-spl;
};
+};
+&qspi2 {
mmc@0 {
u-boot,dm-spl;
};
+}; diff --git a/arch/riscv/include/asm/csr.h b/arch/riscv/include/asm/csr.h index d1520743a2..125c05dd8a 100644 --- a/arch/riscv/include/asm/csr.h +++ b/arch/riscv/include/asm/csr.h @@ -103,6 +103,8 @@ #define CSR_TIMEH 0xc81 #define CSR_INSTRETH 0xc82 #define CSR_MHARTID 0xf14 +#define CSR_MCYCLE 0xb00 +#define CSR_MCYCLEH 0xb80
#ifndef __ASSEMBLY__
diff --git a/board/sifive/fu540/Kconfig b/board/sifive/fu540/Kconfig index 816a135b21..ac7c6bff37 100644 --- a/board/sifive/fu540/Kconfig +++ b/board/sifive/fu540/Kconfig @@ -16,12 +16,20 @@ config SYS_SOC default "fu540"
config SYS_TEXT_BASE
default 0x80200000 if SPL default 0x80000000 if !RISCV_SMODE default 0x80200000 if RISCV_SMODE
+config SPL_TEXT_BASE
default 0x08000000
+config SPL_OPENSBI_LOAD_ADDR
default 0x80000000
config BOARD_SPECIFIC_OPTIONS # dummy def_bool y select GENERIC_RISCV
select SUPPORT_SPL imply CMD_DHCP imply CMD_EXT2 imply CMD_EXT4
diff --git a/board/sifive/fu540/MAINTAINERS
b/board/sifive/fu540/MAINTAINERS
index 702d803ad8..42c3f3deb0 100644 --- a/board/sifive/fu540/MAINTAINERS +++ b/board/sifive/fu540/MAINTAINERS @@ -7,3 +7,4 @@ S: Maintained F: board/sifive/fu540/ F: include/configs/sifive-fu540.h F: configs/sifive_fu540_defconfig +F: configs/sifive_fu540_spl_defconfig diff --git a/board/sifive/fu540/Makefile b/board/sifive/fu540/Makefile index 6e1862c475..e532beb9d5 100644 --- a/board/sifive/fu540/Makefile +++ b/board/sifive/fu540/Makefile @@ -3,3 +3,9 @@ # Copyright (c) 2019 Western Digital Corporation or its affiliates.
obj-y += fu540.o
+ifdef CONFIG_SPL_BUILD +obj-y += spl.o +obj-y += ememoryotp.o +obj-y += uart.o +endif diff --git a/board/sifive/fu540/ememoryotp.c
b/board/sifive/fu540/ememoryotp.c
new file mode 100644 index 0000000000..994724af37 --- /dev/null +++ b/board/sifive/fu540/ememoryotp.c @@ -0,0 +1,143 @@ +// SPDX-License-Identifier: GPL-2.0+ +/*
- Copyright (c) 2019 SiFive, Inc
- Authors:
- Pragnesh Patel pragnesh.patel@sifive.com
- Troy Benjegerdes troy.benjegerdes@sifive.com
- */
+#include <stdint.h> +#include "include/fu540-memory-map.h" +#include "include/clkutils.h" +#include "include/ememoryotp.h"
+#define max(x, y) ((x) > (y) ? (x) : (y))
+extern inline void clkutils_delay_ns(int delay_ns);
+void ememory_otp_power_up_sequence(void) +{
// Probably don't need to do this, since
// all the other stuff has been happening.
// But it is on the wave form.
clkutils_delay_ns(EMEMORYOTP_MIN_TVDS * 1000);
EMEMORYOTP_REG(EMEMORYOTP_PDSTB) = 1;
clkutils_delay_ns(EMEMORYOTP_MIN_TSAS * 1000);
EMEMORYOTP_REG(EMEMORYOTP_PTRIM) = 1;
clkutils_delay_ns(EMEMORYOTP_MIN_TTAS * 1000);
+}
+void ememory_otp_power_down_sequence(void) +{
clkutils_delay_ns(EMEMORYOTP_MIN_TTAH * 1000);
EMEMORYOTP_REG(EMEMORYOTP_PTRIM) = 0;
clkutils_delay_ns(EMEMORYOTP_MIN_TASH * 1000);
EMEMORYOTP_REG(EMEMORYOTP_PDSTB) = 0;
// No delay indicated after this
+}
+void ememory_otp_begin_read(void) +{
// Initialize
EMEMORYOTP_REG(EMEMORYOTP_PCLK) = 0;
EMEMORYOTP_REG(EMEMORYOTP_PA) = 0;
EMEMORYOTP_REG(EMEMORYOTP_PDIN) = 0;
EMEMORYOTP_REG(EMEMORYOTP_PWE) = 0;
EMEMORYOTP_REG(EMEMORYOTP_PTM) = 0;
clkutils_delay_ns(EMEMORYOTP_MIN_TMS * 1000);
// Enable chip select
EMEMORYOTP_REG(EMEMORYOTP_PCE) = 1;
clkutils_delay_ns(EMEMORYOTP_MIN_TCS * 1000);
+}
+void ememory_otp_exit_read(void) +{
EMEMORYOTP_REG(EMEMORYOTP_PCLK) = 0;
EMEMORYOTP_REG(EMEMORYOTP_PA) = 0;
EMEMORYOTP_REG(EMEMORYOTP_PDIN) = 0;
EMEMORYOTP_REG(EMEMORYOTP_PWE) = 0;
// Disable chip select
EMEMORYOTP_REG(EMEMORYOTP_PCE) = 0;
// Wait before changing PTM
clkutils_delay_ns(EMEMORYOTP_MIN_TMH * 1000);
+}
+unsigned int ememory_otp_read(int address) +{
unsigned int read_value;
EMEMORYOTP_REG(EMEMORYOTP_PA) = address;
// Toggle clock
clkutils_delay_ns(EMEMORYOTP_MIN_TAS * 1000);
EMEMORYOTP_REG(EMEMORYOTP_PCLK) = 1;
// Insert delay until data is ready.
// There are lots of delays
// on the chart, but I think this is the most relevant.
int delay = max(EMEMORYOTP_MAX_TCD, EMEMORYOTP_MIN_TKH);
clkutils_delay_ns(delay * 1000);
EMEMORYOTP_REG(EMEMORYOTP_PCLK) = 0;
read_value = EMEMORYOTP_REG(EMEMORYOTP_PDOUT);
// Could check here for things like TCYC < TAH + TCD
return read_value;
+}
+void ememory_otp_pgm_entry(void) +{
EMEMORYOTP_REG(EMEMORYOTP_PCLK) = 0;
EMEMORYOTP_REG(EMEMORYOTP_PA) = 0;
EMEMORYOTP_REG(EMEMORYOTP_PAS) = 0;
EMEMORYOTP_REG(EMEMORYOTP_PAIO) = 0;
EMEMORYOTP_REG(EMEMORYOTP_PDIN) = 0;
EMEMORYOTP_REG(EMEMORYOTP_PWE) = 0;
EMEMORYOTP_REG(EMEMORYOTP_PTM) = 2;
clkutils_delay_ns(EMEMORYOTP_MIN_TMS * 1000);
EMEMORYOTP_REG(EMEMORYOTP_PCE) = 1;
clkutils_delay_ns(EMEMORYOTP_TYP_TCSP * 1000);
EMEMORYOTP_REG(EMEMORYOTP_PPROG) = 1;
clkutils_delay_ns(EMEMORYOTP_TYP_TPPS * 1000);
EMEMORYOTP_REG(EMEMORYOTP_PTRIM) = 1;
+}
+void ememory_otp_pgm_exit(void) +{
EMEMORYOTP_REG(EMEMORYOTP_PWE) = 0;
clkutils_delay_ns(EMEMORYOTP_TYP_TPPH * 1000);
EMEMORYOTP_REG(EMEMORYOTP_PPROG) = 0;
clkutils_delay_ns(EMEMORYOTP_TYP_TPPR * 1000);
EMEMORYOTP_REG(EMEMORYOTP_PCE) = 0;
clkutils_delay_ns(EMEMORYOTP_MIN_TMH * 1000);
EMEMORYOTP_REG(EMEMORYOTP_PTM) = 0;
+}
+void ememory_otp_pgm_access(int address, unsigned int write_data) +{
int i;
EMEMORYOTP_REG(EMEMORYOTP_PA) = address;
for (int pas = 0; pas < 2; pas++) {
EMEMORYOTP_REG(EMEMORYOTP_PAS) = pas;
for (i = 0; i < 32; i++) {
EMEMORYOTP_REG(EMEMORYOTP_PAIO) = i;
EMEMORYOTP_REG(EMEMORYOTP_PDIN) = ((write_data >> i)
&
1);
int delay = max(EMEMORYOTP_MIN_TASP,
EMEMORYOTP_MIN_TDSP);
clkutils_delay_ns(delay * 1000);
EMEMORYOTP_REG(EMEMORYOTP_PWE) = 1;
clkutils_delay_ns(EMEMORYOTP_TYP_TPW * 1000);
EMEMORYOTP_REG(EMEMORYOTP_PWE) = 0;
delay = max(EMEMORYOTP_MIN_TAHP,
EMEMORYOTP_MIN_TDHP);
delay = max(delay, EMEMORYOTP_TYP_TPWI);
clkutils_delay_ns(delay * 1000);
}
}
EMEMORYOTP_REG(EMEMORYOTP_PAS) = 0;
+} diff --git a/board/sifive/fu540/fu540.c b/board/sifive/fu540/fu540.c index 47a2090251..e91418a88a 100644 --- a/board/sifive/fu540/fu540.c +++ b/board/sifive/fu540/fu540.c @@ -10,6 +10,9 @@ #include <dm.h> #include <linux/delay.h> #include <linux/io.h> +#include <spl.h> +#include "include/ccache.h" +#include "include/fu540-memory-map.h"
#ifdef CONFIG_MISC_INIT_R
@@ -143,7 +146,33 @@ int misc_init_r(void)
int board_init(void) {
/* For now nothing to do here. */
/* enable all cache ways */
ccache_enable_ways(CCACHE_CTRL_ADDR, 15);
return 0;
+}
+#ifdef CONFIG_SPL +void board_boot_order(u32 *spl_boot_list) +{
u8 i;
u32 boot_devices[] = {
+#ifdef CONFIG_SPL_RAM_SUPPORT
BOOT_DEVICE_RAM,
+#endif +#ifdef CONFIG_SPL_MMC_SUPPORT
BOOT_DEVICE_MMC1,
+#endif
};
for (i = 0; i < ARRAY_SIZE(boot_devices); i++)
spl_boot_list[i] = boot_devices[i];
+} +#endif
+#ifdef CONFIG_SPL_LOAD_FIT +int board_fit_config_name_match(const char *name) +{
/* boot using first FIT config */ return 0;
} +#endif diff --git a/board/sifive/fu540/include/ccache.h
b/board/sifive/fu540/include/ccache.h
new file mode 100644 index 0000000000..c7978ebdee --- /dev/null +++ b/board/sifive/fu540/include/ccache.h @@ -0,0 +1,47 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ +/*
- Copyright (c) 2019 SiFive, Inc
- Authors:
- Pragnesh Patel pragnesh.patel@sifive.com
- Troy Benjegerdes troy.benjegerdes@sifive.com
- */
+#ifndef FU540_CCACHE_H +#define FU540_CCACHE_H
+#include <asm/arch/cache.h>
+#ifndef __ASSEMBLER__
+#include <stdint.h> +#include <stdatomic.h> +#include <linux/types.h>
+// Block memory access until operation completed +static inline void ccache_barrier_0(void) +{
asm volatile("fence rw, io" : : : "memory");
+}
+static inline void ccache_barrier_1(void) +{
asm volatile("fence io, rw" : : : "memory");
+}
+// Enable ways; allow cache to use these ways +static inline u8 ccache_enable_ways(u64 base_addr, u8 value) +{
u32 old;
volatile _Atomic(u32) * enable = (_Atomic(u32) *)(base_addr +
CCACHE_ENABLE);
ccache_barrier_0();
old = atomic_exchange_explicit(enable, value,
memory_order_relaxed);
How does this work as we are calling a C11 API?
I will check this and update in v2.
ccache_barrier_1();
return old;
+}
+#endif
+#endif /* FU540_CCACHE_H */ diff --git a/board/sifive/fu540/include/clkutils.h
b/board/sifive/fu540/include/clkutils.h
new file mode 100644 index 0000000000..dbb260a1c3 --- /dev/null +++ b/board/sifive/fu540/include/clkutils.h @@ -0,0 +1,75 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ +/*
- Copyright (c) 2019 SiFive, Inc
- Authors:
- Pragnesh Patel pragnesh.patel@sifive.com
- Troy Benjegerdes troy.benjegerdes@sifive.com
- */
+#ifndef __ASSEMBLER__
+#include <stdint.h> +#include <asm/encoding.h> +#include "fu540-memory-map.h"
+// Inlining header functions in C +// https://stackoverflow.com/a/23699777/7433423 +inline u64 clkutils_read_mtime(void) +{ +#if __riscv_xlen == 32
u32 mtime_hi_0;
u32 mtime_lo;
u32 mtime_hi_1;
do {
mtime_hi_0 = CLINT_REG(CLINT_MTIME + 4);
mtime_lo = CLINT_REG(CLINT_MTIME + 0);
mtime_hi_1 = CLINT_REG(CLINT_MTIME + 4);
} while (mtime_hi_0 != mtime_hi_1);
return (((u64)mtime_hi_1 << 32) | ((u64)mtime_lo));
+#else
return CLINT_REG64(CLINT_MTIME);
+#endif +}
+static inline u64 clkutils_read_mcycle(void) +{ +#if __riscv_xlen == 32
u32 mcycle_hi_0;
u32 mcycle_lo;
u32 mcycle_hi_1;
do {
mcycle_hi_0 = read_csr(mcycleh);
mcycle_lo = read_csr(mcycle);
mcycle_hi_1 = read_csr(mcycleh);
} while (mcycle_hi_0 != mcycle_hi_1);
return (((u64)mcycle_hi_1 << 32) | ((u64)mcycle_lo));
+#else
return csr_read(CSR_MCYCLE);
+#endif +}
+// Note that since this runs off RTC, which is +// currently ~1-10MHz, this function is +// not acccurate for small delays. +// In the future, we may want to determine whether to +// use RTC vs mcycle, or create a different function +// based off mcycle. +// We add 1 to the then value because otherwise, if you wanted +// to delay up to RTC_PERIOD_NS-1 (for example), you wouldn't delay +// at all. So this function delays AT LEAST delay_ns. +inline void clkutils_delay_ns(int delay_ns) +{
u64 now = clkutils_read_mtime();
u64 then = now + delay_ns / RTC_PERIOD_NS + 1;
do {
now = clkutils_read_mtime();
} while (now < then);
+}
+#endif /* !__ASSEMBLER__ */ diff --git a/board/sifive/fu540/include/ddrregs.h
b/board/sifive/fu540/include/ddrregs.h
new file mode 100644 index 0000000000..e436496d87 --- /dev/null +++ b/board/sifive/fu540/include/ddrregs.h @@ -0,0 +1,622 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ +/*
- Copyright (c) 2019 SiFive, Inc
- Authors:
- Pragnesh Patel pragnesh.patel@sifive.com
- Troy Benjegerdes troy.benjegerdes@sifive.com
- */
+#include <stdint.h>
+u32 DENALI_PHY_DATA[1215] = {
This is declaring a variable and should not be put in a header file.
I will update in v2, thanks for the review.
DENALI_PHY_00_DATA, DENALI_PHY_01_DATA,
[......]
diff --git a/board/sifive/fu540/include/ememoryotp.h
b/board/sifive/fu540/include/ememoryotp.h
new file mode 100644 index 0000000000..274283c4db --- /dev/null +++ b/board/sifive/fu540/include/ememoryotp.h @@ -0,0 +1,24 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ +/*
- Copyright (c) 2019 SiFive, Inc
- Authors:
- Pragnesh Patel pragnesh.patel@sifive.com
- Troy Benjegerdes troy.benjegerdes@sifive.com
- */
+#ifndef FU540_EMEMORYOTP_H +#define FU540_EMEMORYOTP_H
+#include <asm/arch/otp.h>
+void ememory_otp_power_up_sequence(void); +void ememory_otp_power_down_sequence(void); +}
+#endif /* __ASSEMBLER__ */
+#endif /* FU540_UX00DDR_H */
[....]
diff --git a/board/sifive/fu540/include/ux00prci.h
b/board/sifive/fu540/include/ux00prci.h
new file mode 100644 index 0000000000..21f4aeb465 --- /dev/null +++ b/board/sifive/fu540/include/ux00prci.h @@ -0,0 +1,206 @@ +/* SPDX-License-Identifier: GPL-2.0+ */
+/*
- Copyright (c) 2019 SiFive, Inc
- Authors:
- Pragnesh Patel pragnesh.patel@sifive.com
- Troy Benjegerdes troy.benjegerdes@sifive.com
- */
+#ifndef _SIFIVE_UX00PRCI_H +#define _SIFIVE_UX00PRCI_H
+/* Register offsets */
+#define UX00PRCI_HFROSCCFG (0x0000) +#define UX00PRCI_COREPLLCFG (0x0004) +#define UX00PRCI_COREPLLOUT (0x0008) +#define UX00PRCI_DDRPLLCFG (0x000C) +#define UX00PRCI_DDRPLLOUT (0x0010) +#define UX00PRCI_GEMGXLPLLCFG (0x001C) +#define UX00PRCI_GEMGXLPLLOUT (0x0020) +#define UX00PRCI_CORECLKSELREG (0x0024) +#define UX00PRCI_DEVICESRESETREG (0x0028) +#define UX00PRCI_CLKMUXSTATUSREG (0x002C) +#define UX00PRCI_PROCMONCFG (0x00F0)
+/* Fields */ +#define XOSC_EN(x) (((x) & 0x1) << 30) +#define XOSC_RDY(x) (((x) & 0x1) << 31)
+#define PLL_R(x) (((x) & 0x3F) << 0) +#define PLL_F(x) (((x) & 0x1FF) << 6) +#define PLL_Q(x) (((x) & 0x7) << 15) +#define PLL_RANGE(x) (((x) & 0x7) << 18) +#define PLL_BYPASS(x) (((x) & 0x1) << 24) +#define PLL_FSE(x) (((x) & 0x1) << 25) +#define PLL_LOCK(x) (((x) & 0x1) << 31)
+#define PLLOUT_DIV(x) (((x) & 0x7F) << 0) +#define PLLOUT_DIV_BY_1(x) (((x) & 0x1) << 8) +#define PLLOUT_CLK_EN(x) (((x) & 0x1) << 31)
+#define PLL_R_default 0x1 +#define PLL_F_default 0x1F +#define PLL_Q_default 0x3 +#define PLL_RANGE_default 0x0 +#define PLL_BYPASS_default 0x1 +#define PLL_FSE_default 0x1
+#define PLLOUT_DIV_default 0x0 +#define PLLOUT_DIV_BY_1_default 0x0 +#define PLLOUT_CLK_EN_default 0x0
+#define PLL_CORECLKSEL_HFXIN 0x1 +#define PLL_CORECLKSEL_COREPLL 0x0
+#define DEVICESRESET_DDR_CTRL_RST_N(x) (((x) & 0x1) << 0) +#define DEVICESRESET_DDR_AXI_RST_N(x) (((x) & 0x1) << 1) +#define DEVICESRESET_DDR_AHB_RST_N(x) (((x) & 0x1) << 2) +#define DEVICESRESET_DDR_PHY_RST_N(x) (((x) & 0x1) << 3) +#define DEVICESRESET_GEMGXL_RST_N(x) (((x) & 0x1) << 5)
+#define CLKMUX_STATUS_CORECLKPLLSEL (0x1 << 0) +#define CLKMUX_STATUS_TLCLKSEL (0x1 << 1) +#define CLKMUX_STATUS_RTCXSEL (0x1 << 2) +#define CLKMUX_STATUS_DDRCTRLCLKSEL (0x1 << 3) +#define CLKMUX_STATUS_DDRPHYCLKSEL (0x1 << 4) +#define CLKMUX_STATUS_GEMGXLCLKSEL (0x1 << 6)
+#ifndef __ASSEMBLER__
+#include <stdint.h> +#include <linux/types.h>
+static inline int ux00prci_select_corepll(volatile u32 *coreclkselreg,
volatile u32 *corepllcfg,
volatile u32 *corepllout,
u32 pllconfigval)
+{
(*corepllcfg) = pllconfigval;
// Wait for lock
while (((*corepllcfg) & (PLL_LOCK(1))) == 0)
;
u32 core_out =
(PLLOUT_DIV(PLLOUT_DIV_default)) |
(PLLOUT_DIV_BY_1(PLLOUT_DIV_BY_1_default)) |
(PLLOUT_CLK_EN(1));
(*corepllout) = core_out;
// Set CORECLKSELREG to select COREPLL
(*coreclkselreg) = PLL_CORECLKSEL_COREPLL;
return 0;
+}
+static inline int ux00prci_select_corepll_1_4ghz(volatile u32 *coreclkselreg,
volatile u32 *corepllcfg,
volatile u32 *corepllout)
+{
//
// CORE pll init
// Set corepll 33MHz -> 1GHz
//
u32 core14ghz =
(PLL_R(0)) |
(PLL_F(41)) | /*2800MHz VCO*/
(PLL_Q(1)) | /* /2 Output divider */
(PLL_RANGE(0x4)) |
(PLL_BYPASS(0)) |
(PLL_FSE(1));
return ux00prci_select_corepll(coreclkselreg, corepllcfg, corepllout,
core14ghz);
+}
+static inline int ux00prci_select_corepll_1_5ghz(volatile u32 *coreclkselreg,
volatile u32 *corepllcfg,
volatile u32 *corepllout)
+{
//
// CORE pll init
// Set corepll 33MHz -> 1GHz
//
u32 core15ghz =
(PLL_R(0)) |
(PLL_F(44)) | /*3000MHz VCO*/
(PLL_Q(1)) | /* /2 Output divider */
(PLL_RANGE(0x4)) |
(PLL_BYPASS(0)) |
(PLL_FSE(1));
return ux00prci_select_corepll(coreclkselreg, corepllcfg, corepllout,
core15ghz);
+}
+static inline int ux00prci_select_corepll_1_6ghz(volatile u32 *coreclkselreg,
volatile u32 *corepllcfg,
volatile u32 *corepllout)
+{
//
// CORE pll init
// Set corepll 33MHz -> 1GHz
//
u32 core16ghz =
(PLL_R(0)) |
(PLL_F(47)) | /*3200MHz VCO*/
(PLL_Q(1)) | /* /2 Output divider */
(PLL_RANGE(0x4)) |
(PLL_BYPASS(0)) |
(PLL_FSE(1));
return ux00prci_select_corepll(coreclkselreg, corepllcfg, corepllout,
core16ghz);
+}
+static inline int ux00prci_select_corepll_1ghz(volatile u32 *coreclkselreg,
volatile u32 *corepllcfg,
volatile u32 *corepllout)
+{
//
// CORE pll init
// Set corepll 33MHz -> 1GHz
//
u32 core1ghz =
(PLL_R(0)) |
(PLL_F(59)) | /*4000MHz VCO*/
(PLL_Q(2)) | /* /4 Output divider */
(PLL_RANGE(0x4)) |
(PLL_BYPASS(0)) |
(PLL_FSE(1));
return ux00prci_select_corepll(coreclkselreg, corepllcfg, corepllout,
core1ghz);
+}
+static inline int ux00prci_select_corepll_500mhz(volatile u32 *coreclkselreg,
volatile u32 *corepllcfg,
volatile u32 *corepllout)
+{
//
// CORE pll init
// Set corepll 33MHz -> 1GHz
//
u32 core500mhz =
(PLL_R(0)) |
(PLL_F(59)) | /*4000MHz VCO*/
(PLL_Q(3)) | /* /8 Output divider */
(PLL_RANGE(0x4)) |
(PLL_BYPASS(0)) |
(PLL_FSE(1));
return ux00prci_select_corepll(coreclkselreg, corepllcfg, corepllout,
core500mhz);
+}
Can we reuse the U-Boot PRCI driver for SPL? If not, could we update it instead of creating another ad-hoc driver?
I agreed with you but for preload_console_init(), UART clock needs to be enabled and that is provided by tlclk (corepll).
This clock initialization is necessary for SPL but I will move this code to spl.c from header file. Let me know if you have any other suggestion.
+#endif
+#endif // _SIFIVE_UX00PRCI_H diff --git a/board/sifive/fu540/spl.c b/board/sifive/fu540/spl.c new file mode 100644 index 0000000000..69187066ba --- /dev/null +++ b/board/sifive/fu540/spl.c @@ -0,0 +1,321 @@ +// SPDX-License-Identifier: GPL-2.0+ +/*
- Copyright (c) 2019 SiFive, Inc
- Authors:
- Pragnesh Patel pragnesh.patel@sifive.com
- Troy Benjegerdes troy.benjegerdes@sifive.com
- */
+#include <common.h> +#include <spl.h>
+#include "include/regconfig-ctl.h" +#include "include/regconfig-phy.h" +#include "include/ux00ddr.h" +#include "include/ddrregs.h"
+#include "include/fu540-memory-map.h" +#include <stdatomic.h>
+#define ddr_phy_settings DENALI_PHY_DATA +#define ddr_ctl_settings DENALI_CTL_DATA
+#define DDR_SIZE (8UL * 1024UL * 1024UL * 1024UL) +#define DDRCTLPLL_F 55 +#define DDRCTLPLL_Q 2
+#define PHY_NRESET 0x1000 +#define FIRST_SLOT 0xfe +#define LAST_SLOT 0x80
+static const uintptr_t i2c_devices[] = {
I2C_CTRL_ADDR,
+};
+static spi_ctrl * const spi_devices[] = {
(spi_ctrl *)SPI0_CTRL_ADDR,
(spi_ctrl *)SPI1_CTRL_ADDR,
(spi_ctrl *)SPI2_CTRL_ADDR,
+};
+static const uintptr_t uart_devices[] = {
UART0_CTRL_ADDR,
UART1_CTRL_ADDR,
+};
+unsigned int serial_to_burn = ~0;
+/**
- Scale peripheral clock dividers before changing core PLL.
- */
+void update_peripheral_clock_dividers(unsigned int peripheral_input_khz)
Are these a must-have? ie: can we have individual device driver (ie: sifive i2c, or sifive spi driver to do such work in their probe() routine)?
Yes, you are right. Only UART clock divider needs to be updated. Will update in v2.
+{
unsigned int i2c_target_khz = 400;
u16 prescaler = i2c_min_clk_prescaler(peripheral_input_khz,
i2c_target_khz);
for (size_t i = 0; i < ARRAY_SIZE(i2c_devices); i++) {
_REG32(i2c_devices[i], I2C_PRESCALER_LO) = prescaler & 0xff;
_REG32(i2c_devices[i], I2C_PRESCALER_HI) = (prescaler >> 8) &
0xff;
}
unsigned int spi_target_khz = 50000;
unsigned int spi_div = spi_min_clk_divisor(peripheral_input_khz,
spi_target_khz);
for (size_t i = 0; i < ARRAY_SIZE(spi_devices); i++)
spi_devices[i]->sckdiv = spi_div;
unsigned int uart_target_hz = 115200ULL;
unsigned int uart_div = uart_min_clk_divisor(peripheral_input_khz *
1000ULL, uart_target_hz);
for (size_t i = 0; i < ARRAY_SIZE(uart_devices); i++)
_REG32(uart_devices[i], UART_REG_DIV) = uart_div;
+}
+long nsec_per_cyc = 300; // 33.333MHz +void nsleep(long nsec) +{
long step = nsec_per_cyc * 2; // 2 instructions per loop iteration
while (nsec > 0)
nsec -= step;
+}
+void init_clk_and_ddr(void) +{
// PRCI init
// Initialize UART divider for 33MHz core clock in case if
// trap is taken prior to core clock bump.
unsigned long long uart_target_hz = 115200ULL;
const u32 initial_core_clk_khz = 33000;
unsigned long peripheral_input_khz;
if (UX00PRCI_REG(UX00PRCI_CLKMUXSTATUSREG) &
CLKMUX_STATUS_TLCLKSEL)
peripheral_input_khz = initial_core_clk_khz;
else
peripheral_input_khz = initial_core_clk_khz / 2;
UART0_REG(UART_REG_DIV) =
uart_min_clk_divisor(peripheral_input_khz *
1000ULL, uart_target_hz);
// Check Reset Values (lock don't care)
u32 pll_default =
(PLL_R(PLL_R_default)) |
(PLL_F(PLL_F_default)) |
(PLL_Q(PLL_Q_default)) |
(PLL_RANGE(PLL_RANGE_default)) |
(PLL_BYPASS(PLL_BYPASS_default)) |
(PLL_FSE(PLL_FSE_default));
u32 lockmask = ~PLL_LOCK(1);
u32 pllout_default =
(PLLOUT_DIV(PLLOUT_DIV_default)) |
(PLLOUT_DIV_BY_1(PLLOUT_DIV_BY_1_default)) |
(PLLOUT_CLK_EN(PLLOUT_CLK_EN_default));
if ((UX00PRCI_REG(UX00PRCI_COREPLLCFG) ^ pll_default) &
lockmask)
return;
if ((UX00PRCI_REG(UX00PRCI_COREPLLOUT) ^ pllout_default))
return;
if ((UX00PRCI_REG(UX00PRCI_DDRPLLCFG) ^ pll_default) & lockmask)
return;
if ((UX00PRCI_REG(UX00PRCI_DDRPLLOUT) ^ pllout_default))
return;
if (((UX00PRCI_REG(UX00PRCI_GEMGXLPLLCFG)) ^ pll_default) &
lockmask)
return;
if (((UX00PRCI_REG(UX00PRCI_GEMGXLPLLOUT)) ^ pllout_default))
return;
//CORE pll init
// If tlclksel is set for 2:1 operation,
// Set corepll 33Mhz -> 1GHz
// Otherwise, set corepll 33MHz -> 500MHz.
if (UX00PRCI_REG(UX00PRCI_CLKMUXSTATUSREG) &
CLKMUX_STATUS_TLCLKSEL) {
nsec_per_cyc = 2;
peripheral_input_khz = 500000; // peripheral_clk = tlclk
update_peripheral_clock_dividers(peripheral_input_khz);
ux00prci_select_corepll_500mhz
(&UX00PRCI_REG(UX00PRCI_CORECLKSELREG),
&UX00PRCI_REG(UX00PRCI_COREPLLCFG),
&UX00PRCI_REG(UX00PRCI_COREPLLOUT));
} else {
nsec_per_cyc = 1;
peripheral_input_khz = (1000000 / 2); // peripheral_clk = tlclk
update_peripheral_clock_dividers(peripheral_input_khz);
ux00prci_select_corepll_1ghz
(&UX00PRCI_REG(UX00PRCI_CORECLKSELREG),
&UX00PRCI_REG(UX00PRCI_COREPLLCFG),
&UX00PRCI_REG(UX00PRCI_COREPLLOUT));
}
//
//DDR init
//
u32 ddrctlmhz =
(PLL_R(0)) |
(PLL_F(DDRCTLPLL_F)) |
(PLL_Q(DDRCTLPLL_Q)) |
(PLL_RANGE(0x4)) |
(PLL_BYPASS(0)) |
(PLL_FSE(1));
UX00PRCI_REG(UX00PRCI_DDRPLLCFG) = ddrctlmhz;
// Wait for lock
while ((UX00PRCI_REG(UX00PRCI_DDRPLLCFG) & PLL_LOCK(1)) == 0)
;
u32 ddrctl_out =
(PLLOUT_DIV(PLLOUT_DIV_default)) |
(PLLOUT_DIV_BY_1(PLLOUT_DIV_BY_1_default)) |
(PLLOUT_CLK_EN(1));
(UX00PRCI_REG(UX00PRCI_DDRPLLOUT)) = ddrctl_out;
//Release DDR reset.
UX00PRCI_REG(UX00PRCI_DEVICESRESETREG) |=
DEVICESRESET_DDR_CTRL_RST_N(1);
// HACK to get the '1 full controller clock cycle'.
asm volatile ("fence");
UX00PRCI_REG(UX00PRCI_DEVICESRESETREG) |=
DEVICESRESET_DDR_AXI_RST_N(1)
| DEVICESRESET_DDR_AHB_RST_N(1) |
DEVICESRESET_DDR_PHY_RST_N(1);
// HACK to get the '1 full controller clock cycle'.
asm volatile ("fence");
// These take like 16 cycles to actually propagate. We can't go sending
// stuff before they come out of reset. So wait. (TODO: Add a register
// to read the current reset states, or DDR Control device?)
for (int i = 0; i < 256; i++)
asm volatile ("nop");
ux00ddr_writeregmap(UX00DDR_CTRL_ADDR, ddr_ctl_settings,
ddr_phy_settings);
ux00ddr_disableaxireadinterleave(UX00DDR_CTRL_ADDR);
ux00ddr_disableoptimalrmodw(UX00DDR_CTRL_ADDR);
ux00ddr_enablewriteleveling(UX00DDR_CTRL_ADDR);
ux00ddr_enablereadleveling(UX00DDR_CTRL_ADDR);
ux00ddr_enablereadlevelinggate(UX00DDR_CTRL_ADDR);
if (ux00ddr_getdramclass(UX00DDR_CTRL_ADDR) ==
DRAM_CLASS_DDR4)
ux00ddr_enablevreftraining(UX00DDR_CTRL_ADDR);
//mask off interrupts for leveling completion
ux00ddr_mask_leveling_completed_interrupt(UX00DDR_CTRL_ADDR);
ux00ddr_mask_mc_init_complete_interrupt(UX00DDR_CTRL_ADDR);
ux00ddr_mask_outofrange_interrupts(UX00DDR_CTRL_ADDR);
ux00ddr_setuprangeprotection(UX00DDR_CTRL_ADDR, DDR_SIZE);
ux00ddr_mask_port_command_error_interrupt(UX00DDR_CTRL_ADDR);
const u64 ddr_size = DDR_SIZE;
const u64 ddr_end = CONFIG_SYS_SDRAM_BASE + ddr_size;
ux00ddr_start(UX00DDR_CTRL_ADDR, PHYSICAL_FILTER_CTRL_ADDR,
ddr_end);
ux00ddr_phy_fixup(UX00DDR_CTRL_ADDR);
//
//GEMGXL init
//
u32 gemgxl125mhz =
(PLL_R(0)) |
(PLL_F(59)) | /*4000Mhz VCO*/
(PLL_Q(5)) | /* /32 */
(PLL_RANGE(0x4)) |
(PLL_BYPASS(0)) |
(PLL_FSE(1));
UX00PRCI_REG(UX00PRCI_GEMGXLPLLCFG) = gemgxl125mhz;
// Wait for lock
while ((UX00PRCI_REG(UX00PRCI_GEMGXLPLLCFG) & PLL_LOCK(1)) ==
;
u32 gemgxlctl_out =
(PLLOUT_DIV(PLLOUT_DIV_default)) |
(PLLOUT_DIV_BY_1(PLLOUT_DIV_BY_1_default)) |
(PLLOUT_CLK_EN(1));
UX00PRCI_REG(UX00PRCI_GEMGXLPLLOUT) = gemgxlctl_out;
//Release GEMGXL reset (set bit DEVICESRESET_GEMGXL to 1)
UX00PRCI_REG(UX00PRCI_DEVICESRESETREG) |=
DEVICESRESET_GEMGXL_RST_N(1);
// VSC8541 PHY reset sequence; leave pull-down active for 2ms
nsleep(2000000);
// Set GPIO 12 (PHY NRESET) to OE=1 and OVAL=1
atomic_fetch_or(&GPIO_REG(GPIO_OUTPUT_VAL), PHY_NRESET);
atomic_fetch_or(&GPIO_REG(GPIO_OUTPUT_EN), PHY_NRESET);
nsleep(100);
// Procmon => core clock
UX00PRCI_REG(UX00PRCI_PROCMONCFG) = 0x1 << 24;
// Post the serial number and build info
UART0_REG(UART_REG_TXCTRL) = UART_TXEN;
puts("\r\nPRCI Initialized: ");
unsigned int serial = ~0;
int serial_slot;
unsigned int pos;
unsigned int neg;
ememory_otp_power_up_sequence();
ememory_otp_begin_read();
for (serial_slot = FIRST_SLOT; serial_slot >= LAST_SLOT;
serial_slot -= 2) {
pos = ememory_otp_read(serial_slot);
neg = ememory_otp_read(serial_slot + 1);
serial = pos;
if (pos == ~neg)
break; // legal serial #
if (pos == ~0 && neg == ~0)
break; // empty slot encountered
}
ememory_otp_exit_read();
void *uart = (void *)UART0_CTRL_ADDR;
uart_puts(uart, "\r\nHiFive-U serial #: ");
uart_put_hex(uart, serial);
I don't this we really need this.
I will remove this.
// Program the OTP?
if (serial_to_burn != ~0 && serial != serial_to_burn &&
serial_slot > LAST_SLOT) {
uart_puts(uart, "Programming serial: ");
uart_put_hex(uart, serial_to_burn);
uart_puts(uart, "\r\n");
ememory_otp_pgm_entry();
if (serial != ~0) {
// erase the current serial
uart_puts(uart, "Erasing prior serial\r\n");
ememory_otp_pgm_access(serial_slot, 0);
ememory_otp_pgm_access(serial_slot + 1, 0);
serial_slot -= 2;
}
ememory_otp_pgm_access(serial_slot, serial_to_burn);
ememory_otp_pgm_access(serial_slot + 1, ~serial_to_burn);
ememory_otp_pgm_exit();
uart_puts(uart, "Resuming boot\r\n");
serial = serial_to_burn;
}
ememory_otp_power_down_sequence();
uart_puts(uart, "\r\n");
+}
+void board_init_f(ulong dummy) +{
int ret;
init_clk_and_ddr();
ret = spl_early_init();
if (ret)
panic("spl_early_init() failed: %d\n", ret);
arch_cpu_init_dm();
preloader_console_init();
+} diff --git a/board/sifive/fu540/uart.c b/board/sifive/fu540/uart.c new file mode 100644 index 0000000000..d16f6add47 --- /dev/null +++ b/board/sifive/fu540/uart.c
Can we drop this, instead use the sifive uart driver directory?
Will update in v2.
@@ -0,0 +1,64 @@ +// SPDX-License-Identifier: GPL-2.0+ +/*
- Copyright (c) 2019 SiFive, Inc
- Authors:
- Pragnesh Patel pragnesh.patel@sifive.com
- Troy Benjegerdes troy.benjegerdes@sifive.com
- */
+#include <stdatomic.h> +#include "include/fu540-memory-map.h" +#include "include/uart.h"
+void uart_putc(void *uartctrl, char c) +{ +#if __riscv_atomic
s32 r;
do {
asm volatile ("amoor.w %0, %2, %1\n" : "=r" (r),
"+A" (_REG32(uartctrl, UART_REG_TXFIFO))
: "r" (c)
);
} while (r < 0);
+#else
while ((int)_REG32(uartctrl, UART_REG_TXFIFO) < 0)
;
_REG32(uartctrl, UART_REG_TXFIFO) = c;
+#endif +}
+char uart_getc(void *uartctrl) +{
s32 val = -1;
while (val < 0)
val = (s32)_REG32(uartctrl, UART_REG_RXFIFO);
return val & 0xFF;
+}
+void uart_puts(void *uartctrl, const char *s) +{
while (*s != '\0')
uart_putc(uartctrl, *s++);
+}
+void uart_put_hex(void *uartctrl, u32 hex) +{
int num_nibbles = sizeof(hex) * 2;
for (int nibble_idx = num_nibbles - 1; nibble_idx >= 0; nibble_idx--) {
char nibble = (hex >> (nibble_idx * 4)) & 0xf;
uart_putc(uartctrl, (nibble < 0xa) ? ('0' + nibble) :
('a' + nibble - 0xa));
}
+}
+void uart_put_hex64(void *uartctrl, uint64_t hex) +{
uart_put_hex(uartctrl, hex >> 32);
uart_put_hex(uartctrl, hex & 0xFFFFFFFF);
+} diff --git a/configs/sifive_fu540_spl_defconfig
b/configs/sifive_fu540_spl_defconfig
new file mode 100644 index 0000000000..6f9a70ee3e --- /dev/null +++ b/configs/sifive_fu540_spl_defconfig @@ -0,0 +1,23 @@ +CONFIG_RISCV=y +CONFIG_ENV_SIZE=0x20000 +CONFIG_NR_DRAM_BANKS=1 +CONFIG_TARGET_SIFIVE_FU540=y +CONFIG_ARCH_RV64I=y +CONFIG_RISCV_SMODE=y +CONFIG_DISTRO_DEFAULTS=y +CONFIG_FIT=y +CONFIG_MISC_INIT_R=y +CONFIG_DEFAULT_DEVICE_TREE="hifive-unleashed-a00" +CONFIG_DISPLAY_CPUINFO=y +CONFIG_DISPLAY_BOARDINFO=y +CONFIG_OF_SEPARATE=y +CONFIG_SPL_SEPARATE_BSS=y +CONFIG_SYS_RELOC_GD_ENV_ADDR=y +CONFIG_SPL=y +CONFIG_SPL_MMC_SUPPORT=y +CONFIG_SPL_SPI_SUPPORT=y +CONFIG_SPL_YMODEM_SUPPORT=y +CONFIG_SYS_MMCSD_RAW_MODE_U_BOOT_USE_PARTITION=y +CONFIG_SYS_MMCSD_RAW_MODE_U_BOOT_PARTITION=1 +CONFIG_SPL_CLK=y +CONFIG_SPL_PAYLOAD="u-boot.itb" diff --git a/include/configs/sifive-fu540.h b/include/configs/sifive-fu540.h index 2756ed5a77..5afc7ddb66 100644 --- a/include/configs/sifive-fu540.h +++ b/include/configs/sifive-fu540.h @@ -11,6 +11,21 @@
#include <linux/sizes.h>
+#ifdef CONFIG_SPL
+#define CONFIG_SPL_MAX_SIZE 0x00100000 +#define CONFIG_SPL_BSS_START_ADDR 0x85000000 +#define CONFIG_SPL_BSS_MAX_SIZE 0x00100000 +#define CONFIG_SYS_SPL_MALLOC_START
(CONFIG_SPL_BSS_START_ADDR + \
CONFIG_SPL_BSS_MAX_SIZE)
+#define CONFIG_SYS_SPL_MALLOC_SIZE 0x00100000
+#define CONFIG_SPL_LOAD_FIT_ADDRESS 0x84000000
+#define CONFIG_SPL_STACK (0x08000000 + 0x001D0000 -
GENERATED_GBL_DATA_SIZE)
+#endif
#define CONFIG_SYS_SDRAM_BASE 0x80000000 #define CONFIG_SYS_INIT_SP_ADDR (CONFIG_SYS_SDRAM_BASE +
SZ_2M)
@@ -24,6 +39,7 @@
/* Environment options */
+#ifndef CONFIG_SPL_BUILD #define BOOT_TARGET_DEVICES(func) \ func(MMC, mmc, 0) \ func(DHCP, dhcp, na) @@ -43,5 +59,6 @@ #define CONFIG_PREBOOT \ "setenv fdt_addr ${fdtcontroladdr};" \ "fdt addr ${fdtcontroladdr};" +#endif
#endif /* __CONFIG_H */ diff --git a/lib/Makefile b/lib/Makefile index 1fb650cd90..2d88c2ab5e 100644 --- a/lib/Makefile +++ b/lib/Makefile @@ -76,6 +76,7 @@ endif
ifdef CONFIG_SPL_BUILD obj-$(CONFIG_SPL_YMODEM_SUPPORT) += crc16.o +obj-$(CONFIG_MMC_SPI) += crc7.o obj-$(CONFIG_$(SPL_TPL_)HASH_SUPPORT) += crc16.o obj-$(CONFIG_SPL_NET_SUPPORT) += net_utils.o endif
One generic comment, the style in this patch is not aligned with U-Boot's.
Regards, Bin