>-----Original Message----- >From: Pragnesh Patel >Sent: 06 January 2020 15:39 >To: Jagan Teki <ja...@amarulasolutions.com> >Cc: U-Boot-Denx <u-boot@lists.denx.de>; Atish Patra ><atish.pa...@wdc.com>; Alexander Graf <ag...@csgraf.de>; Boris Brezillon ><bbrezil...@kernel.org>; Rick Chen <r...@andestech.com>; Anup Patel ><anup.pa...@wdc.com>; palmerdabb...@google.com >Subject: RE: [PATCH 3/3] riscv: sifive: fu540: add SPL configuration > >>-----Original Message----- >>From: Jagan Teki <ja...@amarulasolutions.com> >>Sent: 02 January 2020 10:29 >>To: Pragnesh Patel <pragnesh.pa...@sifive.com> >>Cc: U-Boot-Denx <u-boot@lists.denx.de>; Palmer Dabbelt ( Sifive) >><pal...@sifive.com>; Atish Patra <atish.pa...@wdc.com>; Alexander Graf >><ag...@csgraf.de>; Boris Brezillon <bbrezil...@kernel.org>; Rick Chen >><r...@andestech.com>; Anup Patel <anup.pa...@wdc.com> >>Subject: Re: [PATCH 3/3] riscv: sifive: fu540: add SPL configuration >> >>+ Rick, Anup >> >>Thanks for the patch, scratching my head to get SPL running on this board. >> >>On Tue, Dec 31, 2019 at 7:30 PM Pragnesh Patel >><pragnesh.pa...@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 >>> 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.pa...@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 + >> >>This patch need to divide into multiple patches since it has multiple >>functionalities all in one which indeed difficult for review and not >>good to go for merging. > >Will spilt this into multiple patches in v2. Thanks for the suggestion. > >> >>> 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 = .; >>> >>> .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; >>> +}; >>> 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.pa...@sifive.com> >>> + * Troy Benjegerdes <troy.benjeger...@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; >>> +} >> >>Please add dm driver for this. > >I will add dm driver in v2. > >> >>> 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 >> >>You may skip if you haven't tested Boot from RAM yet? > >I have tested the BOOT from RAM. > >> >>> +#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.pa...@sifive.com> >>> + * Troy Benjegerdes <troy.benjeger...@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); >>> + 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.pa...@sifive.com> >>> + * Troy Benjegerdes <troy.benjeger...@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. >> >>Improper syntax for multiple comments. > >I will update this in v2. > >> >>> +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.pa...@sifive.com> >>> + * Troy Benjegerdes <troy.benjeger...@sifive.com> >>> + */ >>> + >>> +#include <stdint.h> >>> + >>> +u32 DENALI_PHY_DATA[1215] = { >>> + DENALI_PHY_00_DATA, DENALI_PHY_01_DATA, >>DENALI_PHY_02_DATA, >>> + DENALI_PHY_03_DATA, DENALI_PHY_04_DATA, >>DENALI_PHY_05_DATA, >>> + DENALI_PHY_06_DATA, DENALI_PHY_07_DATA, >>DENALI_PHY_08_DATA, >> >>Can this handle to write separate driver for ram like drivers/ram ?
We can add DM driver for RAM later. Right now, I want to get U-boot SPL running for FU540. > >I didn't get you. > >>> 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.pa...@sifive.com> >>> + * Troy Benjegerdes <troy.benjeger...@sifive.com> >>> + */ >>> + > >[...] > >>> + >>> +#ifndef __ASSEMBLER__ >>> + >>> +#include <stdint.h> >>> +#include <stddef.h> >>> +#include <stdbool.h> >>> +#include "uart.h" >>> +#include "fu540-memory-map.h" >>> + >>> +#define DRAM_CLASS_OFFSET 8 >>> +#define DRAM_CLASS_DDR4 0xA >>> +#define OPTIMAL_RMODW_EN_OFFSET 0 >>> +#define DISABLE_RD_INTERLEAVE_OFFSET 16 >>> +#define OUT_OF_RANGE_OFFSET 1 >>> +#define MULTIPLE_OUT_OF_RANGE_OFFSET 2 >>> +# >> >>Sorry, too much stuff in single patch. it is worth require multiple patches. > >Sure, will split this into multiple patches. > >> >>Jagan.