[PATCH v6 00/17] RISC-V SiFive FU540 support SPL

This series add support for SPL to FU540.U-Boot SPL can boot from L2 LIM (0x0800_0000) and jump to OpenSBI(FW_DYNAMIC firmware) and U-Boot proper from MMC devices.
How to test this patch: 1) Go to OpenSBI-dir : make PLATFORM=sifive/fu540 O=build_dir I=install_dir FW_DYNAMIC=y install 2) cp install_dir/platform/sifive/fu540/firmware/fw_dynamic.bin <u-boot-dir>/ 3) Change to u-boot-dir 4) make sifive_fu540_defconfig 5) make all 6) ZSBL loads the U-boot SPL(u-boot-spl.bin) from a partition with GUID type 5B193300-FC78-40CD-8002-E86C45580B47
sudo dd if=spl/u-boot-spl.bin of=/dev/sdc4 bs=1M
7) U-boot SPL expects a u-boot FIT image(u-boot.itb) from 1st partition(/dev/sdc1) of SD card irrespective of GUID
sudo dd if=u-boot.itb of=/dev/sdc1 bs=1M
Thanks to Yash Shah yash.shah@sifive.com for testing the series.
Changes in v6: - Typo Correction - Make fu540-c000-u-boot.dtsi and hifive-unleashed-a00-u-boot.dtsi Dual Licensed - Sync Hifive unleashed dts from Linux - Add arch/riscv/fu540 for FU540 specific code
Changes in v5: - Return read/write bytes for sifive_otp_read and sifive_otp_write - Correct Palmer's email address
Changes in v4: - Split misc DM driver patch into multiple patches - Added new SPL_CRC7_SUPPORT Kconfig option - Added DM driver for DDR - Added clk_enable and clk_disable ops in SiFive PRCI driver - Added early clock initialization for SPL in SiFive PRCI driver - Added SPL config options in sifive_fu540_defconfig instead of creatiing a new config file for SPL - Update fu540.rst on how to build and flash U-boot SPL
Changes in v3: - Remove arch-fu540 and arch-sifive from arch/riscv/include/asm/ - Split SPL patches into DDR and SPL and spl defconfig - Update fu540/MAINTAINERS file - Update fu540.rst on how to build and flash U-boot SPL
Changes in v2: - Add DM driver Sifive OTP - Split SPL patches into multiple patches - Add a seprate patch for _image_binary_end and crc7.c - Add a seprate patch to add board -u-boot.dtsi files - Update FU540 RISC-V documentation
Pragnesh Patel (17): misc: add driver for the SiFive otp controller riscv: sifive: fu540: Use OTP DM driver for serial environment variable riscv: Add _image_binary_end for SPL lib: Makefile: build crc7.c when CONFIG_MMC_SPI riscv: sifive: dts: fu540: Add board -u-boot.dtsi files sifive: fu540: add ddr driver sifive: dts: fu540: Add DDR controller and phy register settings clk: sifive: fu540-prci: Add clock enable and disable ops clk: sifive: fu540-prci: Add clock initialization for SPL riscv: dts: sifive: Sync hifive-unleashed-a00 dts from linux sifive: dts: fu540: Enable gpio in U-Boot SPL riscv: sifive: fu540: add SPL configuration configs: fu540: Add config options for U-Boot SPL sifive: dts: fu540: Enable L2 Cache in U-Boot riscv: sifive: fu540: enable all cache ways from u-boot proper sifive: fix palmer's email address doc: update FU540 RISC-V documentation
arch/riscv/Makefile | 1 + arch/riscv/cpu/u-boot-spl.lds | 1 + arch/riscv/dts/fu540-c000-u-boot.dtsi | 79 + arch/riscv/dts/fu540-c000.dtsi | 37 +- ...fu540-hifive-unleashed-a00-sdram-ddr4.dtsi | 1489 +++++++++++++++++ .../dts/hifive-unleashed-a00-u-boot.dtsi | 27 + arch/riscv/dts/hifive-unleashed-a00.dts | 9 + arch/riscv/fu540/Makefile | 10 + arch/riscv/fu540/cache.c | 58 + arch/riscv/fu540/spl.c | 30 + arch/riscv/include/asm/arch-generic/cache.h | 14 + arch/riscv/include/asm/arch-generic/gpio.h | 3 + arch/riscv/include/asm/arch-generic/spl.h | 14 + board/sifive/fu540/Kconfig | 10 + board/sifive/fu540/MAINTAINERS | 2 +- board/sifive/fu540/Makefile | 4 + board/sifive/fu540/fu540.c | 143 +- board/sifive/fu540/spl.c | 72 + common/spl/Kconfig | 6 + configs/sifive_fu540_defconfig | 11 + doc/board/sifive/fu540.rst | 409 ++++- drivers/clk/sifive/fu540-prci.c | 218 ++- drivers/misc/Kconfig | 7 + drivers/misc/Makefile | 1 + drivers/misc/sifive-otp.c | 255 +++ drivers/mmc/Kconfig | 1 + drivers/ram/Kconfig | 7 + drivers/ram/Makefile | 2 + drivers/ram/sifive/Kconfig | 8 + drivers/ram/sifive/Makefile | 6 + drivers/ram/sifive/sdram_fu540.c | 399 +++++ include/configs/sifive-fu540.h | 18 + lib/Makefile | 1 + 33 files changed, 3241 insertions(+), 111 deletions(-) create mode 100644 arch/riscv/dts/fu540-c000-u-boot.dtsi create mode 100644 arch/riscv/dts/fu540-hifive-unleashed-a00-sdram-ddr4.dtsi create mode 100644 arch/riscv/dts/hifive-unleashed-a00-u-boot.dtsi create mode 100644 arch/riscv/fu540/Makefile create mode 100644 arch/riscv/fu540/cache.c create mode 100644 arch/riscv/fu540/spl.c create mode 100644 arch/riscv/include/asm/arch-generic/cache.h create mode 100644 arch/riscv/include/asm/arch-generic/spl.h create mode 100644 board/sifive/fu540/spl.c create mode 100644 drivers/misc/sifive-otp.c create mode 100644 drivers/ram/sifive/Kconfig create mode 100644 drivers/ram/sifive/Makefile create mode 100644 drivers/ram/sifive/sdram_fu540.c

Added a misc driver to handle OTP memory in SiFive SoCs.
Signed-off-by: Pragnesh Patel pragnesh.patel@sifive.com --- drivers/misc/Kconfig | 7 ++ drivers/misc/Makefile | 1 + drivers/misc/sifive-otp.c | 255 ++++++++++++++++++++++++++++++++++++++ 3 files changed, 263 insertions(+) create mode 100644 drivers/misc/sifive-otp.c
diff --git a/drivers/misc/Kconfig b/drivers/misc/Kconfig index f18aa8f7ba..5caf61d077 100644 --- a/drivers/misc/Kconfig +++ b/drivers/misc/Kconfig @@ -68,6 +68,13 @@ config ROCKCHIP_OTP addressing and a length or through child-nodes that are generated based on the e-fuse map retrieved from the DTS.
+config SIFIVE_OTP + bool "SiFive eMemory OTP driver" + depends on RISCV && MISC + help + Enable support for reading and writing the eMemory OTP on the + SiFive SoCs. + config VEXPRESS_CONFIG bool "Enable support for Arm Versatile Express config bus" depends on MISC diff --git a/drivers/misc/Makefile b/drivers/misc/Makefile index 2b843de93c..ee888631b6 100644 --- a/drivers/misc/Makefile +++ b/drivers/misc/Makefile @@ -58,6 +58,7 @@ obj-$(CONFIG_$(SPL_)PWRSEQ) += pwrseq-uclass.o obj-$(CONFIG_QFW) += qfw.o obj-$(CONFIG_ROCKCHIP_EFUSE) += rockchip-efuse.o obj-$(CONFIG_ROCKCHIP_OTP) += rockchip-otp.o +obj-$(CONFIG_SIFIVE_OTP) += sifive-otp.o obj-$(CONFIG_SANDBOX) += syscon_sandbox.o misc_sandbox.o obj-$(CONFIG_SMSC_LPC47M) += smsc_lpc47m.o obj-$(CONFIG_SMSC_SIO1007) += smsc_sio1007.o diff --git a/drivers/misc/sifive-otp.c b/drivers/misc/sifive-otp.c new file mode 100644 index 0000000000..c1c2386b97 --- /dev/null +++ b/drivers/misc/sifive-otp.c @@ -0,0 +1,255 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * This is a driver for the eMemory EG004K32TQ028XW01 NeoFuse + * One-Time-Programmable (OTP) memory used within the SiFive FU540. + * It is documented in the FU540 manual here: + * https://www.sifive.com/documentation/chips/freedom-u540-c000-manual/ + * + * Copyright (C) 2018 Philipp Hug philipp@hug.cx + * Copyright (C) 2018 Joey Hewitt joey@joeyhewitt.com + * + * Copyright (C) 2020 SiFive, Inc + */ + +/* + * The FU540 stores 4096x32 bit (16KiB) values. + * Index 0x00-0xff are reserved for SiFive internal use. (first 1KiB) + * Right now first 1KiB is used to store only serial number. + */ + +#include <common.h> +#include <dm/device.h> +#include <dm/read.h> +#include <linux/io.h> +#include <misc.h> + +#define BYTES_PER_FUSE 4 + +#define PA_RESET_VAL 0x00 +#define PAS_RESET_VAL 0x00 +#define PAIO_RESET_VAL 0x00 +#define PDIN_RESET_VAL 0x00 +#define PTM_RESET_VAL 0x00 + +#define PCLK_ENABLE_VAL BIT(0) +#define PCLK_DISABLE_VAL 0x00 + +#define PWE_WRITE_ENABLE BIT(0) +#define PWE_WRITE_DISABLE 0x00 + +#define PTM_FUSE_PROGRAM_VAL BIT(1) + +#define PCE_ENABLE_INPUT BIT(0) +#define PCE_DISABLE_INPUT 0x00 + +#define PPROG_ENABLE_INPUT BIT(0) +#define PPROG_DISABLE_INPUT 0x00 + +#define PTRIM_ENABLE_INPUT BIT(0) +#define PTRIM_DISABLE_INPUT 0x00 + +#define PDSTB_DEEP_STANDBY_ENABLE BIT(0) +#define PDSTB_DEEP_STANDBY_DISABLE 0x00 + +struct sifive_otp_regs { + u32 pa; /* Address input */ + u32 paio; /* Program address input */ + u32 pas; /* Program redundancy cell selection input */ + u32 pce; /* OTP Macro enable input */ + u32 pclk; /* Clock input */ + u32 pdin; /* Write data input */ + u32 pdout; /* Read data output */ + u32 pdstb; /* Deep standby mode enable input (active low) */ + u32 pprog; /* Program mode enable input */ + u32 ptc; /* Test column enable input */ + u32 ptm; /* Test mode enable input */ + u32 ptm_rep;/* Repair function test mode enable input */ + u32 ptr; /* Test row enable input */ + u32 ptrim; /* Repair function enable input */ + u32 pwe; /* Write enable input (defines program cycle) */ +}; + +struct sifive_otp_platdata { + struct sifive_otp_regs __iomem *regs; + u32 total_fuses; +}; + +/* + * offset and size are assumed aligned to the size of the fuses (32-bit). + */ +static int sifive_otp_read(struct udevice *dev, int offset, + void *buf, int size) +{ + struct sifive_otp_platdata *plat = dev_get_platdata(dev); + struct sifive_otp_regs *regs = (struct sifive_otp_regs *)plat->regs; + + /* Check if offset and size are multiple of BYTES_PER_FUSE */ + if ((size % BYTES_PER_FUSE) || (offset % BYTES_PER_FUSE)) { + printf("%s: size and offset must be multiple of 4.\n", + __func__); + return -EINVAL; + } + + int fuseidx = offset / BYTES_PER_FUSE; + int fusecount = size / BYTES_PER_FUSE; + + /* check bounds */ + if (offset < 0 || size < 0) + return -EINVAL; + if (fuseidx >= plat->total_fuses) + return -EINVAL; + if ((fuseidx + fusecount) > plat->total_fuses) + return -EINVAL; + + u32 fusebuf[fusecount]; + + /* init OTP */ + writel(PDSTB_DEEP_STANDBY_ENABLE, ®s->pdstb); + writel(PTRIM_ENABLE_INPUT, ®s->ptrim); + writel(PCE_ENABLE_INPUT, ®s->pce); + + /* read all requested fuses */ + for (unsigned int i = 0; i < fusecount; i++, fuseidx++) { + writel(fuseidx, ®s->pa); + + /* cycle clock to read */ + writel(PCLK_ENABLE_VAL, ®s->pclk); + mdelay(1); + writel(PCLK_DISABLE_VAL, ®s->pclk); + mdelay(1); + + /* read the value */ + fusebuf[i] = readl(®s->pdout); + } + + /* shut down */ + writel(PCE_DISABLE_INPUT, ®s->pce); + writel(PTRIM_DISABLE_INPUT, ®s->ptrim); + writel(PDSTB_DEEP_STANDBY_DISABLE, ®s->pdstb); + + /* copy out */ + memcpy(buf, fusebuf, size); + + return size; +} + +/* + * Caution: + * OTP can be written only once, so use carefully. + * + * offset and size are assumed aligned to the size of the fuses (32-bit). + */ +static int sifive_otp_write(struct udevice *dev, int offset, + const void *buf, int size) +{ + struct sifive_otp_platdata *plat = dev_get_platdata(dev); + struct sifive_otp_regs *regs = (struct sifive_otp_regs *)plat->regs; + + /* Check if offset and size are multiple of BYTES_PER_FUSE */ + if ((size % BYTES_PER_FUSE) || (offset % BYTES_PER_FUSE)) { + printf("%s: size and offset must be multiple of 4.\n", + __func__); + return -EINVAL; + } + + int fuseidx = offset / BYTES_PER_FUSE; + int fusecount = size / BYTES_PER_FUSE; + u32 *write_buf = (u32 *)buf; + u32 write_data; + int i, pas, bit; + + /* check bounds */ + if (offset < 0 || size < 0) + return -EINVAL; + if (fuseidx >= plat->total_fuses) + return -EINVAL; + if ((fuseidx + fusecount) > plat->total_fuses) + return -EINVAL; + + /* init OTP */ + writel(PDSTB_DEEP_STANDBY_ENABLE, ®s->pdstb); + writel(PTRIM_ENABLE_INPUT, ®s->ptrim); + + /* reset registers */ + writel(PCLK_DISABLE_VAL, ®s->pclk); + writel(PA_RESET_VAL, ®s->pa); + writel(PAS_RESET_VAL, ®s->pas); + writel(PAIO_RESET_VAL, ®s->paio); + writel(PDIN_RESET_VAL, ®s->pdin); + writel(PWE_WRITE_DISABLE, ®s->pwe); + writel(PTM_FUSE_PROGRAM_VAL, ®s->ptm); + mdelay(1); + + writel(PCE_ENABLE_INPUT, ®s->pce); + writel(PPROG_ENABLE_INPUT, ®s->pprog); + + /* write all requested fuses */ + for (i = 0; i < fusecount; i++, fuseidx++) { + writel(fuseidx, ®s->pa); + write_data = *(write_buf++); + + for (pas = 0; pas < 2; pas++) { + writel(pas, ®s->pas); + + for (bit = 0; bit < 32; bit++) { + writel(bit, ®s->paio); + writel(((write_data >> bit) & 1), + ®s->pdin); + mdelay(1); + + writel(PWE_WRITE_ENABLE, ®s->pwe); + mdelay(1); + writel(PWE_WRITE_DISABLE, ®s->pwe); + mdelay(1); + } + } + + writel(PAS_RESET_VAL, ®s->pas); + } + + /* shut down */ + writel(PWE_WRITE_DISABLE, ®s->pwe); + writel(PPROG_DISABLE_INPUT, ®s->pprog); + writel(PCE_DISABLE_INPUT, ®s->pce); + writel(PTM_RESET_VAL, ®s->ptm); + + writel(PTRIM_DISABLE_INPUT, ®s->ptrim); + writel(PDSTB_DEEP_STANDBY_DISABLE, ®s->pdstb); + + return size; +} + +static int sifive_otp_ofdata_to_platdata(struct udevice *dev) +{ + struct sifive_otp_platdata *plat = dev_get_platdata(dev); + int ret; + + plat->regs = dev_read_addr_ptr(dev); + + ret = dev_read_u32(dev, "fuse-count", &plat->total_fuses); + if (ret < 0) { + pr_err(""fuse-count" not found\n"); + return ret; + } + + return 0; +} + +static const struct misc_ops sifive_otp_ops = { + .read = sifive_otp_read, + .write = sifive_otp_write, +}; + +static const struct udevice_id sifive_otp_ids[] = { + { .compatible = "sifive,fu540-c000-otp" }, + {} +}; + +U_BOOT_DRIVER(sifive_otp) = { + .name = "sifive_otp", + .id = UCLASS_MISC, + .of_match = sifive_otp_ids, + .ofdata_to_platdata = sifive_otp_ofdata_to_platdata, + .platdata_auto_alloc_size = sizeof(struct sifive_otp_platdata), + .ops = &sifive_otp_ops, +};

On Sun, Mar 29, 2020 at 10:36 PM Pragnesh Patel pragnesh.patel@sifive.com wrote:
Added a misc driver to handle OTP memory in SiFive SoCs.
Signed-off-by: Pragnesh Patel pragnesh.patel@sifive.com
drivers/misc/Kconfig | 7 ++ drivers/misc/Makefile | 1 + drivers/misc/sifive-otp.c | 255 ++++++++++++++++++++++++++++++++++++++ 3 files changed, 263 insertions(+) create mode 100644 drivers/misc/sifive-otp.c
diff --git a/drivers/misc/Kconfig b/drivers/misc/Kconfig index f18aa8f7ba..5caf61d077 100644 --- a/drivers/misc/Kconfig +++ b/drivers/misc/Kconfig @@ -68,6 +68,13 @@ config ROCKCHIP_OTP addressing and a length or through child-nodes that are generated based on the e-fuse map retrieved from the DTS.
+config SIFIVE_OTP
bool "SiFive eMemory OTP driver"
depends on RISCV && MISC
help
Enable support for reading and writing the eMemory OTP on the
SiFive SoCs.
config VEXPRESS_CONFIG bool "Enable support for Arm Versatile Express config bus" depends on MISC diff --git a/drivers/misc/Makefile b/drivers/misc/Makefile index 2b843de93c..ee888631b6 100644 --- a/drivers/misc/Makefile +++ b/drivers/misc/Makefile @@ -58,6 +58,7 @@ obj-$(CONFIG_$(SPL_)PWRSEQ) += pwrseq-uclass.o obj-$(CONFIG_QFW) += qfw.o obj-$(CONFIG_ROCKCHIP_EFUSE) += rockchip-efuse.o obj-$(CONFIG_ROCKCHIP_OTP) += rockchip-otp.o +obj-$(CONFIG_SIFIVE_OTP) += sifive-otp.o obj-$(CONFIG_SANDBOX) += syscon_sandbox.o misc_sandbox.o obj-$(CONFIG_SMSC_LPC47M) += smsc_lpc47m.o obj-$(CONFIG_SMSC_SIO1007) += smsc_sio1007.o diff --git a/drivers/misc/sifive-otp.c b/drivers/misc/sifive-otp.c new file mode 100644 index 0000000000..c1c2386b97 --- /dev/null +++ b/drivers/misc/sifive-otp.c @@ -0,0 +1,255 @@ +// SPDX-License-Identifier: GPL-2.0 +/*
- This is a driver for the eMemory EG004K32TQ028XW01 NeoFuse
- One-Time-Programmable (OTP) memory used within the SiFive FU540.
- It is documented in the FU540 manual here:
- Copyright (C) 2018 Philipp Hug philipp@hug.cx
- Copyright (C) 2018 Joey Hewitt joey@joeyhewitt.com
- Copyright (C) 2020 SiFive, Inc
- */
+/*
- The FU540 stores 4096x32 bit (16KiB) values.
- Index 0x00-0xff are reserved for SiFive internal use. (first 1KiB)
- Right now first 1KiB is used to store only serial number.
- */
+#include <common.h> +#include <dm/device.h> +#include <dm/read.h> +#include <linux/io.h> +#include <misc.h>
+#define BYTES_PER_FUSE 4
+#define PA_RESET_VAL 0x00 +#define PAS_RESET_VAL 0x00 +#define PAIO_RESET_VAL 0x00 +#define PDIN_RESET_VAL 0x00 +#define PTM_RESET_VAL 0x00
+#define PCLK_ENABLE_VAL BIT(0) +#define PCLK_DISABLE_VAL 0x00
+#define PWE_WRITE_ENABLE BIT(0) +#define PWE_WRITE_DISABLE 0x00
+#define PTM_FUSE_PROGRAM_VAL BIT(1)
+#define PCE_ENABLE_INPUT BIT(0) +#define PCE_DISABLE_INPUT 0x00
+#define PPROG_ENABLE_INPUT BIT(0) +#define PPROG_DISABLE_INPUT 0x00
+#define PTRIM_ENABLE_INPUT BIT(0) +#define PTRIM_DISABLE_INPUT 0x00
+#define PDSTB_DEEP_STANDBY_ENABLE BIT(0) +#define PDSTB_DEEP_STANDBY_DISABLE 0x00
+struct sifive_otp_regs {
u32 pa; /* Address input */
u32 paio; /* Program address input */
u32 pas; /* Program redundancy cell selection input */
u32 pce; /* OTP Macro enable input */
u32 pclk; /* Clock input */
u32 pdin; /* Write data input */
u32 pdout; /* Read data output */
u32 pdstb; /* Deep standby mode enable input (active low) */
u32 pprog; /* Program mode enable input */
u32 ptc; /* Test column enable input */
u32 ptm; /* Test mode enable input */
u32 ptm_rep;/* Repair function test mode enable input */
u32 ptr; /* Test row enable input */
u32 ptrim; /* Repair function enable input */
u32 pwe; /* Write enable input (defines program cycle) */
+};
+struct sifive_otp_platdata {
struct sifive_otp_regs __iomem *regs;
u32 total_fuses;
+};
+/*
- offset and size are assumed aligned to the size of the fuses (32-bit).
- */
+static int sifive_otp_read(struct udevice *dev, int offset,
void *buf, int size)
+{
struct sifive_otp_platdata *plat = dev_get_platdata(dev);
struct sifive_otp_regs *regs = (struct sifive_otp_regs *)plat->regs;
/* Check if offset and size are multiple of BYTES_PER_FUSE */
if ((size % BYTES_PER_FUSE) || (offset % BYTES_PER_FUSE)) {
printf("%s: size and offset must be multiple of 4.\n",
__func__);
return -EINVAL;
}
int fuseidx = offset / BYTES_PER_FUSE;
int fusecount = size / BYTES_PER_FUSE;
/* check bounds */
if (offset < 0 || size < 0)
return -EINVAL;
if (fuseidx >= plat->total_fuses)
return -EINVAL;
if ((fuseidx + fusecount) > plat->total_fuses)
return -EINVAL;
u32 fusebuf[fusecount];
/* init OTP */
writel(PDSTB_DEEP_STANDBY_ENABLE, ®s->pdstb);
writel(PTRIM_ENABLE_INPUT, ®s->ptrim);
writel(PCE_ENABLE_INPUT, ®s->pce);
/* read all requested fuses */
for (unsigned int i = 0; i < fusecount; i++, fuseidx++) {
writel(fuseidx, ®s->pa);
/* cycle clock to read */
writel(PCLK_ENABLE_VAL, ®s->pclk);
mdelay(1);
writel(PCLK_DISABLE_VAL, ®s->pclk);
mdelay(1);
/* read the value */
fusebuf[i] = readl(®s->pdout);
}
/* shut down */
writel(PCE_DISABLE_INPUT, ®s->pce);
writel(PTRIM_DISABLE_INPUT, ®s->ptrim);
writel(PDSTB_DEEP_STANDBY_DISABLE, ®s->pdstb);
/* copy out */
memcpy(buf, fusebuf, size);
return size;
+}
+/*
- Caution:
- OTP can be written only once, so use carefully.
- offset and size are assumed aligned to the size of the fuses (32-bit).
- */
+static int sifive_otp_write(struct udevice *dev, int offset,
const void *buf, int size)
+{
struct sifive_otp_platdata *plat = dev_get_platdata(dev);
struct sifive_otp_regs *regs = (struct sifive_otp_regs *)plat->regs;
/* Check if offset and size are multiple of BYTES_PER_FUSE */
if ((size % BYTES_PER_FUSE) || (offset % BYTES_PER_FUSE)) {
printf("%s: size and offset must be multiple of 4.\n",
__func__);
return -EINVAL;
}
int fuseidx = offset / BYTES_PER_FUSE;
int fusecount = size / BYTES_PER_FUSE;
u32 *write_buf = (u32 *)buf;
u32 write_data;
int i, pas, bit;
/* check bounds */
if (offset < 0 || size < 0)
return -EINVAL;
if (fuseidx >= plat->total_fuses)
return -EINVAL;
if ((fuseidx + fusecount) > plat->total_fuses)
return -EINVAL;
/* init OTP */
writel(PDSTB_DEEP_STANDBY_ENABLE, ®s->pdstb);
writel(PTRIM_ENABLE_INPUT, ®s->ptrim);
/* reset registers */
writel(PCLK_DISABLE_VAL, ®s->pclk);
writel(PA_RESET_VAL, ®s->pa);
writel(PAS_RESET_VAL, ®s->pas);
writel(PAIO_RESET_VAL, ®s->paio);
writel(PDIN_RESET_VAL, ®s->pdin);
writel(PWE_WRITE_DISABLE, ®s->pwe);
writel(PTM_FUSE_PROGRAM_VAL, ®s->ptm);
mdelay(1);
writel(PCE_ENABLE_INPUT, ®s->pce);
writel(PPROG_ENABLE_INPUT, ®s->pprog);
/* write all requested fuses */
for (i = 0; i < fusecount; i++, fuseidx++) {
writel(fuseidx, ®s->pa);
write_data = *(write_buf++);
for (pas = 0; pas < 2; pas++) {
writel(pas, ®s->pas);
for (bit = 0; bit < 32; bit++) {
writel(bit, ®s->paio);
writel(((write_data >> bit) & 1),
®s->pdin);
mdelay(1);
writel(PWE_WRITE_ENABLE, ®s->pwe);
mdelay(1);
writel(PWE_WRITE_DISABLE, ®s->pwe);
mdelay(1);
are these delays with 1msec are based on the otp programming sequence, if yes please add comments on that. rest looks good to me.
Jagan.

Hi Jagan,
-----Original Message----- From: Jagan Teki jagan@amarulasolutions.com Sent: 02 April 2020 14:46 To: Pragnesh Patel pragnesh.patel@sifive.com Cc: U-Boot-Denx u-boot@lists.denx.de; Atish Patra atish.patra@wdc.com; palmerdabbelt@google.com; Bin Meng bmeng.cn@gmail.com; Paul Walmsley paul.walmsley@sifive.com; Troy Benjegerdes troy.benjegerdes@sifive.com; Anup Patel anup.patel@wdc.com; Sagar Kadam sagar.kadam@sifive.com; Rick Chen rick@andestech.com; Simon Glass sjg@chromium.org; Eugen Hristev eugen.hristev@microchip.com; Tero Kristo t-kristo@ti.com; Marcel Ziswiler marcel.ziswiler@toradex.com; Finley Xiao <finley.xiao@rock- chips.com>; Peng Fan peng.fan@nxp.com Subject: Re: [PATCH v6 01/17] misc: add driver for the SiFive otp controller
[External Email] Do not click links or attachments unless you recognize the sender and know the content is safe
On Sun, Mar 29, 2020 at 10:36 PM Pragnesh Patel pragnesh.patel@sifive.com wrote:
Added a misc driver to handle OTP memory in SiFive SoCs.
Signed-off-by: Pragnesh Patel pragnesh.patel@sifive.com
drivers/misc/Kconfig | 7 ++ drivers/misc/Makefile | 1 + drivers/misc/sifive-otp.c | 255 ++++++++++++++++++++++++++++++++++++++ 3 files changed, 263 insertions(+) create mode 100644 drivers/misc/sifive-otp.c
diff --git a/drivers/misc/Kconfig b/drivers/misc/Kconfig index f18aa8f7ba..5caf61d077 100644 --- a/drivers/misc/Kconfig +++ b/drivers/misc/Kconfig @@ -68,6 +68,13 @@ config ROCKCHIP_OTP addressing and a length or through child-nodes that are generated based on the e-fuse map retrieved from the DTS.
+config SIFIVE_OTP
bool "SiFive eMemory OTP driver"
depends on RISCV && MISC
help
Enable support for reading and writing the eMemory OTP on the
SiFive SoCs.
config VEXPRESS_CONFIG bool "Enable support for Arm Versatile Express config bus" depends on MISC diff --git a/drivers/misc/Makefile b/drivers/misc/Makefile index 2b843de93c..ee888631b6 100644 --- a/drivers/misc/Makefile +++ b/drivers/misc/Makefile @@ -58,6 +58,7 @@ obj-$(CONFIG_$(SPL_)PWRSEQ) += pwrseq-uclass.o obj-$(CONFIG_QFW) += qfw.o obj-$(CONFIG_ROCKCHIP_EFUSE) += rockchip-efuse.o obj-$(CONFIG_ROCKCHIP_OTP) += rockchip-otp.o +obj-$(CONFIG_SIFIVE_OTP) += sifive-otp.o obj-$(CONFIG_SANDBOX) += syscon_sandbox.o misc_sandbox.o obj-$(CONFIG_SMSC_LPC47M) += smsc_lpc47m.o obj-$(CONFIG_SMSC_SIO1007) += smsc_sio1007.o diff --git a/drivers/misc/sifive-otp.c b/drivers/misc/sifive-otp.c new file mode 100644 index 0000000000..c1c2386b97 --- /dev/null +++ b/drivers/misc/sifive-otp.c @@ -0,0 +1,255 @@ +// SPDX-License-Identifier: GPL-2.0 +/*
- This is a driver for the eMemory EG004K32TQ028XW01 NeoFuse
- One-Time-Programmable (OTP) memory used within the SiFive FU540.
- It is documented in the FU540 manual here:
+https://www.sifive.com/documentation/chips/freedom-u540-c000-
manual/
- Copyright (C) 2018 Philipp Hug philipp@hug.cx
- Copyright (C) 2018 Joey Hewitt joey@joeyhewitt.com
- Copyright (C) 2020 SiFive, Inc
- */
+/*
- The FU540 stores 4096x32 bit (16KiB) values.
- Index 0x00-0xff are reserved for SiFive internal use. (first 1KiB)
- Right now first 1KiB is used to store only serial number.
- */
+#include <common.h> +#include <dm/device.h> +#include <dm/read.h> +#include <linux/io.h> +#include <misc.h>
+#define BYTES_PER_FUSE 4
+#define PA_RESET_VAL 0x00 +#define PAS_RESET_VAL 0x00 +#define PAIO_RESET_VAL 0x00 +#define PDIN_RESET_VAL 0x00 +#define PTM_RESET_VAL 0x00
+#define PCLK_ENABLE_VAL BIT(0) +#define PCLK_DISABLE_VAL 0x00
+#define PWE_WRITE_ENABLE BIT(0) +#define PWE_WRITE_DISABLE 0x00
+#define PTM_FUSE_PROGRAM_VAL BIT(1)
+#define PCE_ENABLE_INPUT BIT(0) +#define PCE_DISABLE_INPUT 0x00
+#define PPROG_ENABLE_INPUT BIT(0) +#define PPROG_DISABLE_INPUT 0x00
+#define PTRIM_ENABLE_INPUT BIT(0) +#define PTRIM_DISABLE_INPUT 0x00
+#define PDSTB_DEEP_STANDBY_ENABLE BIT(0) +#define PDSTB_DEEP_STANDBY_DISABLE 0x00
+struct sifive_otp_regs {
u32 pa; /* Address input */
u32 paio; /* Program address input */
u32 pas; /* Program redundancy cell selection input */
u32 pce; /* OTP Macro enable input */
u32 pclk; /* Clock input */
u32 pdin; /* Write data input */
u32 pdout; /* Read data output */
u32 pdstb; /* Deep standby mode enable input (active low) */
u32 pprog; /* Program mode enable input */
u32 ptc; /* Test column enable input */
u32 ptm; /* Test mode enable input */
u32 ptm_rep;/* Repair function test mode enable input */
u32 ptr; /* Test row enable input */
u32 ptrim; /* Repair function enable input */
u32 pwe; /* Write enable input (defines program cycle) */
+};
+struct sifive_otp_platdata {
struct sifive_otp_regs __iomem *regs;
u32 total_fuses;
+};
+/*
- offset and size are assumed aligned to the size of the fuses (32-bit).
- */
+static int sifive_otp_read(struct udevice *dev, int offset,
void *buf, int size) {
struct sifive_otp_platdata *plat = dev_get_platdata(dev);
struct sifive_otp_regs *regs = (struct sifive_otp_regs
+*)plat->regs;
/* Check if offset and size are multiple of BYTES_PER_FUSE */
if ((size % BYTES_PER_FUSE) || (offset % BYTES_PER_FUSE)) {
printf("%s: size and offset must be multiple of 4.\n",
__func__);
return -EINVAL;
}
int fuseidx = offset / BYTES_PER_FUSE;
int fusecount = size / BYTES_PER_FUSE;
/* check bounds */
if (offset < 0 || size < 0)
return -EINVAL;
if (fuseidx >= plat->total_fuses)
return -EINVAL;
if ((fuseidx + fusecount) > plat->total_fuses)
return -EINVAL;
u32 fusebuf[fusecount];
/* init OTP */
writel(PDSTB_DEEP_STANDBY_ENABLE, ®s->pdstb);
writel(PTRIM_ENABLE_INPUT, ®s->ptrim);
writel(PCE_ENABLE_INPUT, ®s->pce);
/* read all requested fuses */
for (unsigned int i = 0; i < fusecount; i++, fuseidx++) {
writel(fuseidx, ®s->pa);
/* cycle clock to read */
writel(PCLK_ENABLE_VAL, ®s->pclk);
mdelay(1);
writel(PCLK_DISABLE_VAL, ®s->pclk);
mdelay(1);
/* read the value */
fusebuf[i] = readl(®s->pdout);
}
/* shut down */
writel(PCE_DISABLE_INPUT, ®s->pce);
writel(PTRIM_DISABLE_INPUT, ®s->ptrim);
writel(PDSTB_DEEP_STANDBY_DISABLE, ®s->pdstb);
/* copy out */
memcpy(buf, fusebuf, size);
return size;
+}
+/*
- Caution:
- OTP can be written only once, so use carefully.
- offset and size are assumed aligned to the size of the fuses (32-bit).
- */
+static int sifive_otp_write(struct udevice *dev, int offset,
const void *buf, int size) {
struct sifive_otp_platdata *plat = dev_get_platdata(dev);
struct sifive_otp_regs *regs = (struct sifive_otp_regs
+*)plat->regs;
/* Check if offset and size are multiple of BYTES_PER_FUSE */
if ((size % BYTES_PER_FUSE) || (offset % BYTES_PER_FUSE)) {
printf("%s: size and offset must be multiple of 4.\n",
__func__);
return -EINVAL;
}
int fuseidx = offset / BYTES_PER_FUSE;
int fusecount = size / BYTES_PER_FUSE;
u32 *write_buf = (u32 *)buf;
u32 write_data;
int i, pas, bit;
/* check bounds */
if (offset < 0 || size < 0)
return -EINVAL;
if (fuseidx >= plat->total_fuses)
return -EINVAL;
if ((fuseidx + fusecount) > plat->total_fuses)
return -EINVAL;
/* init OTP */
writel(PDSTB_DEEP_STANDBY_ENABLE, ®s->pdstb);
writel(PTRIM_ENABLE_INPUT, ®s->ptrim);
/* reset registers */
writel(PCLK_DISABLE_VAL, ®s->pclk);
writel(PA_RESET_VAL, ®s->pa);
writel(PAS_RESET_VAL, ®s->pas);
writel(PAIO_RESET_VAL, ®s->paio);
writel(PDIN_RESET_VAL, ®s->pdin);
writel(PWE_WRITE_DISABLE, ®s->pwe);
writel(PTM_FUSE_PROGRAM_VAL, ®s->ptm);
mdelay(1);
writel(PCE_ENABLE_INPUT, ®s->pce);
writel(PPROG_ENABLE_INPUT, ®s->pprog);
/* write all requested fuses */
for (i = 0; i < fusecount; i++, fuseidx++) {
writel(fuseidx, ®s->pa);
write_data = *(write_buf++);
for (pas = 0; pas < 2; pas++) {
writel(pas, ®s->pas);
for (bit = 0; bit < 32; bit++) {
writel(bit, ®s->paio);
writel(((write_data >> bit) & 1),
®s->pdin);
mdelay(1);
writel(PWE_WRITE_ENABLE, ®s->pwe);
mdelay(1);
writel(PWE_WRITE_DISABLE, ®s->pwe);
mdelay(1);
are these delays with 1msec are based on the otp programming sequence, if yes please add comments on that. rest looks good to me.
Yes, this delays are based on otp programming sequence.
writel(PWE_WRITE_ENABLE, ®s->pwe); mdelay(1); - This is Tpw (Program Pulse width time) and it's range is 10 - 20 micro seconds
writel(PWE_WRITE_DISABLE, ®s->pwe); mdelay(1); - This is Tpwi (Program Pulse interval time) and it's range is 1 - 5 micro seconds
Though I have used mdelay(1) here, it's working fine. I will update delay with description in v7.
Jagan.

On Mon, Mar 30, 2020 at 1:06 AM Pragnesh Patel pragnesh.patel@sifive.com wrote:
Added a misc driver to handle OTP memory in SiFive SoCs.
Signed-off-by: Pragnesh Patel pragnesh.patel@sifive.com
drivers/misc/Kconfig | 7 ++ drivers/misc/Makefile | 1 + drivers/misc/sifive-otp.c | 255 ++++++++++++++++++++++++++++++++++++++ 3 files changed, 263 insertions(+) create mode 100644 drivers/misc/sifive-otp.c
Reviewed-by: Bin Meng bmeng.cn@gmail.com

Use the OTP DM driver to set the serial environment variable.
Signed-off-by: Pragnesh Patel pragnesh.patel@sifive.com --- arch/riscv/dts/fu540-c000-u-boot.dtsi | 14 +++ .../dts/hifive-unleashed-a00-u-boot.dtsi | 6 + board/sifive/fu540/Kconfig | 2 + board/sifive/fu540/fu540.c | 111 ++++++------------ 4 files changed, 61 insertions(+), 72 deletions(-) create mode 100644 arch/riscv/dts/fu540-c000-u-boot.dtsi create mode 100644 arch/riscv/dts/hifive-unleashed-a00-u-boot.dtsi
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..db55773bd2 --- /dev/null +++ b/arch/riscv/dts/fu540-c000-u-boot.dtsi @@ -0,0 +1,14 @@ +// SPDX-License-Identifier: (GPL-2.0 OR MIT) +/* + * (C) Copyright 2019 SiFive, Inc + */ + +/ { + soc { + otp: otp@10070000 { + compatible = "sifive,fu540-c000-otp"; + reg = <0x0 0x10070000 0x0 0x0FFF>; + fuse-count = <0x1000>; + }; + }; +}; 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..f1735c1385 --- /dev/null +++ b/arch/riscv/dts/hifive-unleashed-a00-u-boot.dtsi @@ -0,0 +1,6 @@ +// SPDX-License-Identifier: (GPL-2.0 OR MIT) +/* + * Copyright (C) 2019 SiFive, Inc + */ + +#include "fu540-c000-u-boot.dtsi" diff --git a/board/sifive/fu540/Kconfig b/board/sifive/fu540/Kconfig index 5ca21474de..900197bbb2 100644 --- a/board/sifive/fu540/Kconfig +++ b/board/sifive/fu540/Kconfig @@ -48,5 +48,7 @@ config BOARD_SPECIFIC_OPTIONS # dummy imply SIFIVE_GPIO imply CMD_GPIO imply SMP + imply MISC + imply SIFIVE_OTP
endif diff --git a/board/sifive/fu540/fu540.c b/board/sifive/fu540/fu540.c index 47a2090251..540638c919 100644 --- a/board/sifive/fu540/fu540.c +++ b/board/sifive/fu540/fu540.c @@ -10,94 +10,61 @@ #include <dm.h> #include <linux/delay.h> #include <linux/io.h> +#include <misc.h> + +/* + * This define is a value used for error/unknown serial. + * If we really care about distinguishing errors and 0 is + * valid, we'll need a different one. + */ +#define ERROR_READING_SERIAL_NUMBER 0
#ifdef CONFIG_MISC_INIT_R
-#define FU540_OTP_BASE_ADDR 0x10070000 - -struct fu540_otp_regs { - u32 pa; /* Address input */ - u32 paio; /* Program address input */ - u32 pas; /* Program redundancy cell selection input */ - u32 pce; /* OTP Macro enable input */ - u32 pclk; /* Clock input */ - u32 pdin; /* Write data input */ - u32 pdout; /* Read data output */ - u32 pdstb; /* Deep standby mode enable input (active low) */ - u32 pprog; /* Program mode enable input */ - u32 ptc; /* Test column enable input */ - u32 ptm; /* Test mode enable input */ - u32 ptm_rep;/* Repair function test mode enable input */ - u32 ptr; /* Test row enable input */ - u32 ptrim; /* Repair function enable input */ - u32 pwe; /* Write enable input (defines program cycle) */ -} __packed; - -#define BYTES_PER_FUSE 4 -#define NUM_FUSES 0x1000 - -static int fu540_otp_read(int offset, void *buf, int size) +#if CONFIG_IS_ENABLED(SIFIVE_OTP) +static u32 otp_read_serialnum(struct udevice *dev) { - struct fu540_otp_regs *regs = (void __iomem *)FU540_OTP_BASE_ADDR; - unsigned int i; - int fuseidx = offset / BYTES_PER_FUSE; - int fusecount = size / BYTES_PER_FUSE; - u32 fusebuf[fusecount]; - - /* check bounds */ - if (offset < 0 || size < 0) - return -EINVAL; - if (fuseidx >= NUM_FUSES) - return -EINVAL; - if ((fuseidx + fusecount) > NUM_FUSES) - return -EINVAL; + int ret; + u32 serial[2] = {0};
- /* init OTP */ - writel(0x01, ®s->pdstb); /* wake up from stand-by */ - writel(0x01, ®s->ptrim); /* enable repair function */ - writel(0x01, ®s->pce); /* enable input */ - - /* read all requested fuses */ - for (i = 0; i < fusecount; i++, fuseidx++) { - writel(fuseidx, ®s->pa); - - /* cycle clock to read */ - writel(0x01, ®s->pclk); - mdelay(1); - writel(0x00, ®s->pclk); - mdelay(1); - - /* read the value */ - fusebuf[i] = readl(®s->pdout); - } + for (int i = 0xfe * 4; i > 0; i -= 8) { + ret = misc_read(dev, i, serial, sizeof(serial));
- /* shut down */ - writel(0, ®s->pce); - writel(0, ®s->ptrim); - writel(0, ®s->pdstb); + if (ret != sizeof(serial)) { + printf("%s: error reading serial from OTP\n", __func__); + break; + }
- /* copy out */ - memcpy(buf, fusebuf, size); + if (serial[0] == ~serial[1]) + return serial[0]; + }
- return 0; + return ERROR_READING_SERIAL_NUMBER; } +#endif
static u32 fu540_read_serialnum(void) { + u32 serial = ERROR_READING_SERIAL_NUMBER; + +#if CONFIG_IS_ENABLED(SIFIVE_OTP) + struct udevice *dev; int ret; - u32 serial[2] = {0};
- for (int i = 0xfe * 4; i > 0; i -= 8) { - ret = fu540_otp_read(i, serial, sizeof(serial)); - if (ret) { - printf("%s: error reading from OTP\n", __func__); - break; - } - if (serial[0] == ~serial[1]) - return serial[0]; + /* init OTP */ + ret = uclass_get_device_by_driver(UCLASS_MISC, + DM_GET_DRIVER(sifive_otp), &dev); + + if (ret) { + debug("%s: could not find otp device\n", __func__); + return serial; }
- return 0; + /* read serial from OTP and set env var */ + serial = otp_read_serialnum(dev); +#endif + + return serial; }
static void fu540_setup_macaddr(u32 serialnum)

On Sun, Mar 29, 2020 at 10:36 PM Pragnesh Patel pragnesh.patel@sifive.com wrote:
Use the OTP DM driver to set the serial environment variable.
Signed-off-by: Pragnesh Patel pragnesh.patel@sifive.com
arch/riscv/dts/fu540-c000-u-boot.dtsi | 14 +++ .../dts/hifive-unleashed-a00-u-boot.dtsi | 6 + board/sifive/fu540/Kconfig | 2 + board/sifive/fu540/fu540.c | 111 ++++++------------ 4 files changed, 61 insertions(+), 72 deletions(-) create mode 100644 arch/riscv/dts/fu540-c000-u-boot.dtsi create mode 100644 arch/riscv/dts/hifive-unleashed-a00-u-boot.dtsi
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..db55773bd2 --- /dev/null +++ b/arch/riscv/dts/fu540-c000-u-boot.dtsi @@ -0,0 +1,14 @@ +// SPDX-License-Identifier: (GPL-2.0 OR MIT) +/*
- (C) Copyright 2019 SiFive, Inc
- */
+/ {
soc {
otp: otp@10070000 {
compatible = "sifive,fu540-c000-otp";
reg = <0x0 0x10070000 0x0 0x0FFF>;
fuse-count = <0x1000>;
};
};
+}; 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..f1735c1385 --- /dev/null +++ b/arch/riscv/dts/hifive-unleashed-a00-u-boot.dtsi @@ -0,0 +1,6 @@ +// SPDX-License-Identifier: (GPL-2.0 OR MIT) +/*
- Copyright (C) 2019 SiFive, Inc
- */
+#include "fu540-c000-u-boot.dtsi" diff --git a/board/sifive/fu540/Kconfig b/board/sifive/fu540/Kconfig index 5ca21474de..900197bbb2 100644 --- a/board/sifive/fu540/Kconfig +++ b/board/sifive/fu540/Kconfig @@ -48,5 +48,7 @@ config BOARD_SPECIFIC_OPTIONS # dummy imply SIFIVE_GPIO imply CMD_GPIO imply SMP
imply MISC
imply SIFIVE_OTP
Mark this default y if it is SIFIVE.
Jagan.

Hi Jagan,
-----Original Message----- From: Jagan Teki jagan@amarulasolutions.com Sent: 02 April 2020 14:49 To: Pragnesh Patel pragnesh.patel@sifive.com Cc: U-Boot-Denx u-boot@lists.denx.de; Atish Patra atish.patra@wdc.com; palmerdabbelt@google.com; Bin Meng bmeng.cn@gmail.com; Paul Walmsley paul.walmsley@sifive.com; Troy Benjegerdes troy.benjegerdes@sifive.com; Anup Patel anup.patel@wdc.com; Sagar Kadam sagar.kadam@sifive.com; Rick Chen rick@andestech.com; Palmer Dabbelt palmer@dabbelt.com Subject: Re: [PATCH v6 02/17] riscv: sifive: fu540: Use OTP DM driver for serial environment variable
[External Email] Do not click links or attachments unless you recognize the sender and know the content is safe
On Sun, Mar 29, 2020 at 10:36 PM Pragnesh Patel pragnesh.patel@sifive.com wrote:
Use the OTP DM driver to set the serial environment variable.
Signed-off-by: Pragnesh Patel pragnesh.patel@sifive.com
arch/riscv/dts/fu540-c000-u-boot.dtsi | 14 +++ .../dts/hifive-unleashed-a00-u-boot.dtsi | 6 + board/sifive/fu540/Kconfig | 2 + board/sifive/fu540/fu540.c | 111 ++++++------------ 4 files changed, 61 insertions(+), 72 deletions(-) create mode 100644 arch/riscv/dts/fu540-c000-u-boot.dtsi create mode 100644 arch/riscv/dts/hifive-unleashed-a00-u-boot.dtsi
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..db55773bd2 --- /dev/null +++ b/arch/riscv/dts/fu540-c000-u-boot.dtsi @@ -0,0 +1,14 @@ +// SPDX-License-Identifier: (GPL-2.0 OR MIT) +/*
- (C) Copyright 2019 SiFive, Inc
- */
+/ {
soc {
otp: otp@10070000 {
compatible = "sifive,fu540-c000-otp";
reg = <0x0 0x10070000 0x0 0x0FFF>;
fuse-count = <0x1000>;
};
};
+}; 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..f1735c1385 --- /dev/null +++ b/arch/riscv/dts/hifive-unleashed-a00-u-boot.dtsi @@ -0,0 +1,6 @@ +// SPDX-License-Identifier: (GPL-2.0 OR MIT) +/*
- Copyright (C) 2019 SiFive, Inc
- */
+#include "fu540-c000-u-boot.dtsi" diff --git a/board/sifive/fu540/Kconfig b/board/sifive/fu540/Kconfig index 5ca21474de..900197bbb2 100644 --- a/board/sifive/fu540/Kconfig +++ b/board/sifive/fu540/Kconfig @@ -48,5 +48,7 @@ config BOARD_SPECIFIC_OPTIONS # dummy imply SIFIVE_GPIO imply CMD_GPIO imply SMP
imply MISC
imply SIFIVE_OTP
Mark this default y if it is SIFIVE.
All other SiFive drivers (SPI_SIFIVE, SIFIVE_GPIO) are enabled by "imply", so I am following the same. I think "imply" will make it default y.
Jagan.

On Thu, Apr 2, 2020 at 2:54 PM Pragnesh Patel pragnesh.patel@sifive.com wrote:
Hi Jagan,
-----Original Message----- From: Jagan Teki jagan@amarulasolutions.com Sent: 02 April 2020 14:49 To: Pragnesh Patel pragnesh.patel@sifive.com Cc: U-Boot-Denx u-boot@lists.denx.de; Atish Patra atish.patra@wdc.com; palmerdabbelt@google.com; Bin Meng bmeng.cn@gmail.com; Paul Walmsley paul.walmsley@sifive.com; Troy Benjegerdes troy.benjegerdes@sifive.com; Anup Patel anup.patel@wdc.com; Sagar Kadam sagar.kadam@sifive.com; Rick Chen rick@andestech.com; Palmer Dabbelt palmer@dabbelt.com Subject: Re: [PATCH v6 02/17] riscv: sifive: fu540: Use OTP DM driver for serial environment variable
[External Email] Do not click links or attachments unless you recognize the sender and know the content is safe
On Sun, Mar 29, 2020 at 10:36 PM Pragnesh Patel pragnesh.patel@sifive.com wrote:
Use the OTP DM driver to set the serial environment variable.
Signed-off-by: Pragnesh Patel pragnesh.patel@sifive.com
arch/riscv/dts/fu540-c000-u-boot.dtsi | 14 +++ .../dts/hifive-unleashed-a00-u-boot.dtsi | 6 + board/sifive/fu540/Kconfig | 2 + board/sifive/fu540/fu540.c | 111 ++++++------------ 4 files changed, 61 insertions(+), 72 deletions(-) create mode 100644 arch/riscv/dts/fu540-c000-u-boot.dtsi create mode 100644 arch/riscv/dts/hifive-unleashed-a00-u-boot.dtsi
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..db55773bd2 --- /dev/null +++ b/arch/riscv/dts/fu540-c000-u-boot.dtsi @@ -0,0 +1,14 @@ +// SPDX-License-Identifier: (GPL-2.0 OR MIT) +/*
- (C) Copyright 2019 SiFive, Inc
- */
+/ {
soc {
otp: otp@10070000 {
compatible = "sifive,fu540-c000-otp";
reg = <0x0 0x10070000 0x0 0x0FFF>;
fuse-count = <0x1000>;
};
};
+}; 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..f1735c1385 --- /dev/null +++ b/arch/riscv/dts/hifive-unleashed-a00-u-boot.dtsi @@ -0,0 +1,6 @@ +// SPDX-License-Identifier: (GPL-2.0 OR MIT) +/*
- Copyright (C) 2019 SiFive, Inc
- */
+#include "fu540-c000-u-boot.dtsi" diff --git a/board/sifive/fu540/Kconfig b/board/sifive/fu540/Kconfig index 5ca21474de..900197bbb2 100644 --- a/board/sifive/fu540/Kconfig +++ b/board/sifive/fu540/Kconfig @@ -48,5 +48,7 @@ config BOARD_SPECIFIC_OPTIONS # dummy imply SIFIVE_GPIO imply CMD_GPIO imply SMP
imply MISC
imply SIFIVE_OTP
Mark this default y if it is SIFIVE.
All other SiFive drivers (SPI_SIFIVE, SIFIVE_GPIO) are enabled by "imply", so I am following the same. I think "imply" will make it default y.
Just mark 'default y' on SIFIVE_OTP area of drivers/misc/Kconfig depends on SIFIVE SoC would select this driver so-that you no need to add impy SIFIVE_OTP here.
Jagan.

Hi Jagan,
-----Original Message----- From: Jagan Teki jagan@amarulasolutions.com Sent: 02 April 2020 14:59 To: Pragnesh Patel pragnesh.patel@sifive.com Cc: U-Boot-Denx u-boot@lists.denx.de; Atish Patra atish.patra@wdc.com; palmerdabbelt@google.com; Bin Meng bmeng.cn@gmail.com; Paul Walmsley paul.walmsley@sifive.com; Troy Benjegerdes troy.benjegerdes@sifive.com; Anup Patel anup.patel@wdc.com; Sagar Kadam sagar.kadam@sifive.com; Rick Chen rick@andestech.com; Palmer Dabbelt palmer@dabbelt.com Subject: Re: [PATCH v6 02/17] riscv: sifive: fu540: Use OTP DM driver for serial environment variable
[External Email] Do not click links or attachments unless you recognize the sender and know the content is safe
On Thu, Apr 2, 2020 at 2:54 PM Pragnesh Patel pragnesh.patel@sifive.com wrote:
Hi Jagan,
-----Original Message----- From: Jagan Teki jagan@amarulasolutions.com Sent: 02 April 2020 14:49 To: Pragnesh Patel pragnesh.patel@sifive.com Cc: U-Boot-Denx u-boot@lists.denx.de; Atish Patra atish.patra@wdc.com; palmerdabbelt@google.com; Bin Meng bmeng.cn@gmail.com; Paul Walmsley paul.walmsley@sifive.com;
Troy
Benjegerdes troy.benjegerdes@sifive.com; Anup Patel anup.patel@wdc.com; Sagar Kadam sagar.kadam@sifive.com; Rick
Chen
rick@andestech.com; Palmer Dabbelt palmer@dabbelt.com Subject: Re: [PATCH v6 02/17] riscv: sifive: fu540: Use OTP DM driver for serial environment variable
[External Email] Do not click links or attachments unless you recognize the sender and know the content is safe
On Sun, Mar 29, 2020 at 10:36 PM Pragnesh Patel pragnesh.patel@sifive.com wrote:
Use the OTP DM driver to set the serial environment variable.
Signed-off-by: Pragnesh Patel pragnesh.patel@sifive.com
arch/riscv/dts/fu540-c000-u-boot.dtsi | 14 +++ .../dts/hifive-unleashed-a00-u-boot.dtsi | 6 + board/sifive/fu540/Kconfig | 2 + board/sifive/fu540/fu540.c | 111 ++++++------------ 4 files changed, 61 insertions(+), 72 deletions(-) create mode 100644 arch/riscv/dts/fu540-c000-u-boot.dtsi create mode 100644 arch/riscv/dts/hifive-unleashed-a00-u-boot.dtsi
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..db55773bd2 --- /dev/null +++ b/arch/riscv/dts/fu540-c000-u-boot.dtsi @@ -0,0 +1,14 @@ +// SPDX-License-Identifier: (GPL-2.0 OR MIT) +/*
- (C) Copyright 2019 SiFive, Inc
- */
+/ {
soc {
otp: otp@10070000 {
compatible = "sifive,fu540-c000-otp";
reg = <0x0 0x10070000 0x0 0x0FFF>;
fuse-count = <0x1000>;
};
};
+}; 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..f1735c1385 --- /dev/null +++ b/arch/riscv/dts/hifive-unleashed-a00-u-boot.dtsi @@ -0,0 +1,6 @@ +// SPDX-License-Identifier: (GPL-2.0 OR MIT) +/*
- Copyright (C) 2019 SiFive, Inc
- */
+#include "fu540-c000-u-boot.dtsi" diff --git a/board/sifive/fu540/Kconfig b/board/sifive/fu540/Kconfig index 5ca21474de..900197bbb2 100644 --- a/board/sifive/fu540/Kconfig +++ b/board/sifive/fu540/Kconfig @@ -48,5 +48,7 @@ config BOARD_SPECIFIC_OPTIONS # dummy imply SIFIVE_GPIO imply CMD_GPIO imply SMP
imply MISC
imply SIFIVE_OTP
Mark this default y if it is SIFIVE.
All other SiFive drivers (SPI_SIFIVE, SIFIVE_GPIO) are enabled by "imply", so I
am following the same. I think "imply" will make it default y.
Just mark 'default y' on SIFIVE_OTP area of drivers/misc/Kconfig depends on SIFIVE SoC would select this driver so-that you no need to add impy SIFIVE_OTP here.
I am not sure if all SiFive SoC will contain SiFive OTP controller, so it's better not to make it default y.
If all Sifive SoCs contain OTP controller then I need to add another Kconfig option like "RISCV_SIFIVE" as shown below, config SIFIVE_OTP default y if RISCV_SIFIVE
Jagan.

On Thu, Apr 2, 2020 at 3:47 PM Pragnesh Patel pragnesh.patel@sifive.com wrote:
Hi Jagan,
-----Original Message----- From: Jagan Teki jagan@amarulasolutions.com Sent: 02 April 2020 14:59 To: Pragnesh Patel pragnesh.patel@sifive.com Cc: U-Boot-Denx u-boot@lists.denx.de; Atish Patra atish.patra@wdc.com; palmerdabbelt@google.com; Bin Meng bmeng.cn@gmail.com; Paul Walmsley paul.walmsley@sifive.com; Troy Benjegerdes troy.benjegerdes@sifive.com; Anup Patel anup.patel@wdc.com; Sagar Kadam sagar.kadam@sifive.com; Rick Chen rick@andestech.com; Palmer Dabbelt palmer@dabbelt.com Subject: Re: [PATCH v6 02/17] riscv: sifive: fu540: Use OTP DM driver for serial environment variable
[External Email] Do not click links or attachments unless you recognize the sender and know the content is safe
On Thu, Apr 2, 2020 at 2:54 PM Pragnesh Patel pragnesh.patel@sifive.com wrote:
Hi Jagan,
-----Original Message----- From: Jagan Teki jagan@amarulasolutions.com Sent: 02 April 2020 14:49 To: Pragnesh Patel pragnesh.patel@sifive.com Cc: U-Boot-Denx u-boot@lists.denx.de; Atish Patra atish.patra@wdc.com; palmerdabbelt@google.com; Bin Meng bmeng.cn@gmail.com; Paul Walmsley paul.walmsley@sifive.com;
Troy
Benjegerdes troy.benjegerdes@sifive.com; Anup Patel anup.patel@wdc.com; Sagar Kadam sagar.kadam@sifive.com; Rick
Chen
rick@andestech.com; Palmer Dabbelt palmer@dabbelt.com Subject: Re: [PATCH v6 02/17] riscv: sifive: fu540: Use OTP DM driver for serial environment variable
[External Email] Do not click links or attachments unless you recognize the sender and know the content is safe
On Sun, Mar 29, 2020 at 10:36 PM Pragnesh Patel pragnesh.patel@sifive.com wrote:
Use the OTP DM driver to set the serial environment variable.
Signed-off-by: Pragnesh Patel pragnesh.patel@sifive.com
arch/riscv/dts/fu540-c000-u-boot.dtsi | 14 +++ .../dts/hifive-unleashed-a00-u-boot.dtsi | 6 + board/sifive/fu540/Kconfig | 2 + board/sifive/fu540/fu540.c | 111 ++++++------------ 4 files changed, 61 insertions(+), 72 deletions(-) create mode 100644 arch/riscv/dts/fu540-c000-u-boot.dtsi create mode 100644 arch/riscv/dts/hifive-unleashed-a00-u-boot.dtsi
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..db55773bd2 --- /dev/null +++ b/arch/riscv/dts/fu540-c000-u-boot.dtsi @@ -0,0 +1,14 @@ +// SPDX-License-Identifier: (GPL-2.0 OR MIT) +/*
- (C) Copyright 2019 SiFive, Inc
- */
+/ {
soc {
otp: otp@10070000 {
compatible = "sifive,fu540-c000-otp";
reg = <0x0 0x10070000 0x0 0x0FFF>;
fuse-count = <0x1000>;
};
};
+}; 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..f1735c1385 --- /dev/null +++ b/arch/riscv/dts/hifive-unleashed-a00-u-boot.dtsi @@ -0,0 +1,6 @@ +// SPDX-License-Identifier: (GPL-2.0 OR MIT) +/*
- Copyright (C) 2019 SiFive, Inc
- */
+#include "fu540-c000-u-boot.dtsi" diff --git a/board/sifive/fu540/Kconfig b/board/sifive/fu540/Kconfig index 5ca21474de..900197bbb2 100644 --- a/board/sifive/fu540/Kconfig +++ b/board/sifive/fu540/Kconfig @@ -48,5 +48,7 @@ config BOARD_SPECIFIC_OPTIONS # dummy imply SIFIVE_GPIO imply CMD_GPIO imply SMP
imply MISC
imply SIFIVE_OTP
Mark this default y if it is SIFIVE.
All other SiFive drivers (SPI_SIFIVE, SIFIVE_GPIO) are enabled by "imply", so I
am following the same. I think "imply" will make it default y.
Just mark 'default y' on SIFIVE_OTP area of drivers/misc/Kconfig depends on SIFIVE SoC would select this driver so-that you no need to add impy SIFIVE_OTP here.
I am not sure if all SiFive SoC will contain SiFive OTP controller, so it's better not to make it default y.
If all Sifive SoCs contain OTP controller then I need to add another Kconfig option like "RISCV_SIFIVE" as shown below, config SIFIVE_OTP default y if RISCV_SIFIVE
Yes, use this TARGET_SIFIVE_FU540
Jagan.

Hi Jagan,
-----Original Message----- From: Jagan Teki jagan@amarulasolutions.com Sent: 07 April 2020 13:32 To: Pragnesh Patel pragnesh.patel@sifive.com Cc: U-Boot-Denx u-boot@lists.denx.de; Atish Patra atish.patra@wdc.com; palmerdabbelt@google.com; Bin Meng bmeng.cn@gmail.com; Paul Walmsley paul.walmsley@sifive.com; Troy Benjegerdes troy.benjegerdes@sifive.com; Anup Patel anup.patel@wdc.com; Sagar Kadam sagar.kadam@sifive.com; Rick Chen rick@andestech.com; Palmer Dabbelt palmer@dabbelt.com Subject: Re: [PATCH v6 02/17] riscv: sifive: fu540: Use OTP DM driver for serial environment variable
[External Email] Do not click links or attachments unless you recognize the sender and know the content is safe
On Thu, Apr 2, 2020 at 3:47 PM Pragnesh Patel pragnesh.patel@sifive.com wrote:
Hi Jagan,
-----Original Message----- From: Jagan Teki jagan@amarulasolutions.com Sent: 02 April 2020 14:59 To: Pragnesh Patel pragnesh.patel@sifive.com Cc: U-Boot-Denx u-boot@lists.denx.de; Atish Patra atish.patra@wdc.com; palmerdabbelt@google.com; Bin Meng bmeng.cn@gmail.com; Paul Walmsley paul.walmsley@sifive.com;
Troy
Benjegerdes troy.benjegerdes@sifive.com; Anup Patel anup.patel@wdc.com; Sagar Kadam sagar.kadam@sifive.com; Rick
Chen
rick@andestech.com; Palmer Dabbelt palmer@dabbelt.com Subject: Re: [PATCH v6 02/17] riscv: sifive: fu540: Use OTP DM driver for serial environment variable
[External Email] Do not click links or attachments unless you recognize the sender and know the content is safe
On Thu, Apr 2, 2020 at 2:54 PM Pragnesh Patel pragnesh.patel@sifive.com wrote:
Hi Jagan,
-----Original Message----- From: Jagan Teki jagan@amarulasolutions.com Sent: 02 April 2020 14:49 To: Pragnesh Patel pragnesh.patel@sifive.com Cc: U-Boot-Denx u-boot@lists.denx.de; Atish Patra atish.patra@wdc.com; palmerdabbelt@google.com; Bin Meng bmeng.cn@gmail.com; Paul Walmsley paul.walmsley@sifive.com;
Troy
Benjegerdes troy.benjegerdes@sifive.com; Anup Patel anup.patel@wdc.com; Sagar Kadam sagar.kadam@sifive.com; Rick
Chen
rick@andestech.com; Palmer Dabbelt palmer@dabbelt.com Subject: Re: [PATCH v6 02/17] riscv: sifive: fu540: Use OTP DM driver for serial environment variable
[External Email] Do not click links or attachments unless you recognize the sender and know the content is safe
On Sun, Mar 29, 2020 at 10:36 PM Pragnesh Patel pragnesh.patel@sifive.com wrote:
Use the OTP DM driver to set the serial environment variable.
Signed-off-by: Pragnesh Patel pragnesh.patel@sifive.com
arch/riscv/dts/fu540-c000-u-boot.dtsi | 14 +++ .../dts/hifive-unleashed-a00-u-boot.dtsi | 6 + board/sifive/fu540/Kconfig | 2 + board/sifive/fu540/fu540.c | 111 ++++++------------ 4 files changed, 61 insertions(+), 72 deletions(-) create mode 100644 arch/riscv/dts/fu540-c000-u-boot.dtsi create mode 100644 arch/riscv/dts/hifive-unleashed-a00-u-boot.dtsi
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..db55773bd2 --- /dev/null +++ b/arch/riscv/dts/fu540-c000-u-boot.dtsi @@ -0,0 +1,14 @@ +// SPDX-License-Identifier: (GPL-2.0 OR MIT) +/*
- (C) Copyright 2019 SiFive, Inc */
+/ {
soc {
otp: otp@10070000 {
compatible = "sifive,fu540-c000-otp";
reg = <0x0 0x10070000 0x0 0x0FFF>;
fuse-count = <0x1000>;
};
};
+}; 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..f1735c1385 --- /dev/null +++ b/arch/riscv/dts/hifive-unleashed-a00-u-boot.dtsi @@ -0,0 +1,6 @@ +// SPDX-License-Identifier: (GPL-2.0 OR MIT) +/*
- Copyright (C) 2019 SiFive, Inc */
+#include "fu540-c000-u-boot.dtsi" diff --git a/board/sifive/fu540/Kconfig b/board/sifive/fu540/Kconfig index 5ca21474de..900197bbb2 100644 --- a/board/sifive/fu540/Kconfig +++ b/board/sifive/fu540/Kconfig @@ -48,5 +48,7 @@ config BOARD_SPECIFIC_OPTIONS # dummy imply SIFIVE_GPIO imply CMD_GPIO imply SMP
imply MISC
imply SIFIVE_OTP
Mark this default y if it is SIFIVE.
All other SiFive drivers (SPI_SIFIVE, SIFIVE_GPIO) are enabled by "imply", so I
am following the same. I think "imply" will make it default y.
Just mark 'default y' on SIFIVE_OTP area of drivers/misc/Kconfig depends on SIFIVE SoC would select this driver so-that you no need to add impy SIFIVE_OTP here.
I am not sure if all SiFive SoC will contain SiFive OTP controller, so it's better
not to make it default y.
If all Sifive SoCs contain OTP controller then I need to add another Kconfig option like "RISCV_SIFIVE" as shown below, config SIFIVE_OTP default y if RISCV_SIFIVE
Yes, use this TARGET_SIFIVE_FU540
I am okay with this but if other future SiFive SoCs support this OTP then it would be a long chain. What's your opinion on this ?
Jagan.

On Tue, Apr 7, 2020 at 1:40 PM Pragnesh Patel pragnesh.patel@sifive.com wrote:
Hi Jagan,
-----Original Message----- From: Jagan Teki jagan@amarulasolutions.com Sent: 07 April 2020 13:32 To: Pragnesh Patel pragnesh.patel@sifive.com Cc: U-Boot-Denx u-boot@lists.denx.de; Atish Patra atish.patra@wdc.com; palmerdabbelt@google.com; Bin Meng bmeng.cn@gmail.com; Paul Walmsley paul.walmsley@sifive.com; Troy Benjegerdes troy.benjegerdes@sifive.com; Anup Patel anup.patel@wdc.com; Sagar Kadam sagar.kadam@sifive.com; Rick Chen rick@andestech.com; Palmer Dabbelt palmer@dabbelt.com Subject: Re: [PATCH v6 02/17] riscv: sifive: fu540: Use OTP DM driver for serial environment variable
[External Email] Do not click links or attachments unless you recognize the sender and know the content is safe
On Thu, Apr 2, 2020 at 3:47 PM Pragnesh Patel pragnesh.patel@sifive.com wrote:
Hi Jagan,
-----Original Message----- From: Jagan Teki jagan@amarulasolutions.com Sent: 02 April 2020 14:59 To: Pragnesh Patel pragnesh.patel@sifive.com Cc: U-Boot-Denx u-boot@lists.denx.de; Atish Patra atish.patra@wdc.com; palmerdabbelt@google.com; Bin Meng bmeng.cn@gmail.com; Paul Walmsley paul.walmsley@sifive.com;
Troy
Benjegerdes troy.benjegerdes@sifive.com; Anup Patel anup.patel@wdc.com; Sagar Kadam sagar.kadam@sifive.com; Rick
Chen
rick@andestech.com; Palmer Dabbelt palmer@dabbelt.com Subject: Re: [PATCH v6 02/17] riscv: sifive: fu540: Use OTP DM driver for serial environment variable
[External Email] Do not click links or attachments unless you recognize the sender and know the content is safe
On Thu, Apr 2, 2020 at 2:54 PM Pragnesh Patel pragnesh.patel@sifive.com wrote:
Hi Jagan,
-----Original Message----- From: Jagan Teki jagan@amarulasolutions.com Sent: 02 April 2020 14:49 To: Pragnesh Patel pragnesh.patel@sifive.com Cc: U-Boot-Denx u-boot@lists.denx.de; Atish Patra atish.patra@wdc.com; palmerdabbelt@google.com; Bin Meng bmeng.cn@gmail.com; Paul Walmsley paul.walmsley@sifive.com;
Troy
Benjegerdes troy.benjegerdes@sifive.com; Anup Patel anup.patel@wdc.com; Sagar Kadam sagar.kadam@sifive.com; Rick
Chen
rick@andestech.com; Palmer Dabbelt palmer@dabbelt.com Subject: Re: [PATCH v6 02/17] riscv: sifive: fu540: Use OTP DM driver for serial environment variable
[External Email] Do not click links or attachments unless you recognize the sender and know the content is safe
On Sun, Mar 29, 2020 at 10:36 PM Pragnesh Patel pragnesh.patel@sifive.com wrote: > > Use the OTP DM driver to set the serial environment variable. > > Signed-off-by: Pragnesh Patel pragnesh.patel@sifive.com > --- > arch/riscv/dts/fu540-c000-u-boot.dtsi | 14 +++ > .../dts/hifive-unleashed-a00-u-boot.dtsi | 6 + > board/sifive/fu540/Kconfig | 2 + > board/sifive/fu540/fu540.c | 111 ++++++------------ > 4 files changed, 61 insertions(+), 72 deletions(-) create mode > 100644 arch/riscv/dts/fu540-c000-u-boot.dtsi > create mode 100644 > arch/riscv/dts/hifive-unleashed-a00-u-boot.dtsi > > 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..db55773bd2 > --- /dev/null > +++ b/arch/riscv/dts/fu540-c000-u-boot.dtsi > @@ -0,0 +1,14 @@ > +// SPDX-License-Identifier: (GPL-2.0 OR MIT) > +/* > + * (C) Copyright 2019 SiFive, Inc */ > + > +/ { > + soc { > + otp: otp@10070000 { > + compatible = "sifive,fu540-c000-otp"; > + reg = <0x0 0x10070000 0x0 0x0FFF>; > + fuse-count = <0x1000>; > + }; > + }; > +}; > 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..f1735c1385 > --- /dev/null > +++ b/arch/riscv/dts/hifive-unleashed-a00-u-boot.dtsi > @@ -0,0 +1,6 @@ > +// SPDX-License-Identifier: (GPL-2.0 OR MIT) > +/* > + * Copyright (C) 2019 SiFive, Inc */ > + > +#include "fu540-c000-u-boot.dtsi" > diff --git a/board/sifive/fu540/Kconfig > b/board/sifive/fu540/Kconfig index 5ca21474de..900197bbb2 100644 > --- a/board/sifive/fu540/Kconfig > +++ b/board/sifive/fu540/Kconfig > @@ -48,5 +48,7 @@ config BOARD_SPECIFIC_OPTIONS # dummy > imply SIFIVE_GPIO > imply CMD_GPIO > imply SMP > + imply MISC > + imply SIFIVE_OTP
Mark this default y if it is SIFIVE.
All other SiFive drivers (SPI_SIFIVE, SIFIVE_GPIO) are enabled by "imply", so I
am following the same. I think "imply" will make it default y.
Just mark 'default y' on SIFIVE_OTP area of drivers/misc/Kconfig depends on SIFIVE SoC would select this driver so-that you no need to add impy SIFIVE_OTP here.
I am not sure if all SiFive SoC will contain SiFive OTP controller, so it's better
not to make it default y.
If all Sifive SoCs contain OTP controller then I need to add another Kconfig option like "RISCV_SIFIVE" as shown below, config SIFIVE_OTP default y if RISCV_SIFIVE
Yes, use this TARGET_SIFIVE_FU540
I am okay with this but if other future SiFive SoCs support this OTP then it would be a long chain. What's your opinion on this ?
That is fine, these are at least SoC not boards. boards will increment a lot but SoC may not. Having SoC dependency or select would be meaningful.
Jagan.

Hi Jagan,
-----Original Message----- From: Jagan Teki jagan@amarulasolutions.com Sent: 07 April 2020 14:51 To: Pragnesh Patel pragnesh.patel@sifive.com Cc: U-Boot-Denx u-boot@lists.denx.de; Atish Patra atish.patra@wdc.com; palmerdabbelt@google.com; Bin Meng bmeng.cn@gmail.com; Paul Walmsley paul.walmsley@sifive.com; Troy Benjegerdes troy.benjegerdes@sifive.com; Anup Patel anup.patel@wdc.com; Sagar Kadam sagar.kadam@sifive.com; Rick Chen rick@andestech.com; Palmer Dabbelt palmer@dabbelt.com Subject: Re: [PATCH v6 02/17] riscv: sifive: fu540: Use OTP DM driver for serial environment variable
[External Email] Do not click links or attachments unless you recognize the sender and know the content is safe
On Tue, Apr 7, 2020 at 1:40 PM Pragnesh Patel pragnesh.patel@sifive.com wrote:
Hi Jagan,
-----Original Message----- From: Jagan Teki jagan@amarulasolutions.com Sent: 07 April 2020 13:32 To: Pragnesh Patel pragnesh.patel@sifive.com Cc: U-Boot-Denx u-boot@lists.denx.de; Atish Patra atish.patra@wdc.com; palmerdabbelt@google.com; Bin Meng bmeng.cn@gmail.com; Paul Walmsley paul.walmsley@sifive.com;
Troy
Benjegerdes troy.benjegerdes@sifive.com; Anup Patel anup.patel@wdc.com; Sagar Kadam sagar.kadam@sifive.com; Rick
Chen
rick@andestech.com; Palmer Dabbelt palmer@dabbelt.com Subject: Re: [PATCH v6 02/17] riscv: sifive: fu540: Use OTP DM driver for serial environment variable
[External Email] Do not click links or attachments unless you recognize the sender and know the content is safe
On Thu, Apr 2, 2020 at 3:47 PM Pragnesh Patel pragnesh.patel@sifive.com wrote:
Hi Jagan,
-----Original Message----- From: Jagan Teki jagan@amarulasolutions.com Sent: 02 April 2020 14:59 To: Pragnesh Patel pragnesh.patel@sifive.com Cc: U-Boot-Denx u-boot@lists.denx.de; Atish Patra atish.patra@wdc.com; palmerdabbelt@google.com; Bin Meng bmeng.cn@gmail.com; Paul Walmsley paul.walmsley@sifive.com;
Troy
Benjegerdes troy.benjegerdes@sifive.com; Anup Patel anup.patel@wdc.com; Sagar Kadam sagar.kadam@sifive.com; Rick
Chen
rick@andestech.com; Palmer Dabbelt palmer@dabbelt.com Subject: Re: [PATCH v6 02/17] riscv: sifive: fu540: Use OTP DM driver for serial environment variable
[External Email] Do not click links or attachments unless you recognize the sender and know the content is safe
On Thu, Apr 2, 2020 at 2:54 PM Pragnesh Patel pragnesh.patel@sifive.com wrote:
Hi Jagan,
>-----Original Message----- >From: Jagan Teki jagan@amarulasolutions.com >Sent: 02 April 2020 14:49 >To: Pragnesh Patel pragnesh.patel@sifive.com >Cc: U-Boot-Denx u-boot@lists.denx.de; Atish Patra >atish.patra@wdc.com; palmerdabbelt@google.com; Bin Meng >bmeng.cn@gmail.com; Paul Walmsley
Troy
>Benjegerdes troy.benjegerdes@sifive.com; Anup Patel >anup.patel@wdc.com; Sagar Kadam sagar.kadam@sifive.com; >Rick
Chen
>rick@andestech.com; Palmer Dabbelt palmer@dabbelt.com >Subject: Re: [PATCH v6 02/17] riscv: sifive: fu540: Use OTP DM >driver for serial environment variable > >[External Email] Do not click links or attachments unless you >recognize the sender and know the content is safe > >On Sun, Mar 29, 2020 at 10:36 PM Pragnesh Patel >pragnesh.patel@sifive.com wrote: >> >> Use the OTP DM driver to set the serial environment variable. >> >> Signed-off-by: Pragnesh Patel pragnesh.patel@sifive.com >> --- >> arch/riscv/dts/fu540-c000-u-boot.dtsi | 14 +++ >> .../dts/hifive-unleashed-a00-u-boot.dtsi | 6 + >> board/sifive/fu540/Kconfig | 2 + >> board/sifive/fu540/fu540.c | 111 ++++++------------ >> 4 files changed, 61 insertions(+), 72 deletions(-) create >> mode >> 100644 arch/riscv/dts/fu540-c000-u-boot.dtsi >> create mode 100644 >> arch/riscv/dts/hifive-unleashed-a00-u-boot.dtsi >> >> 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..db55773bd2 >> --- /dev/null >> +++ b/arch/riscv/dts/fu540-c000-u-boot.dtsi >> @@ -0,0 +1,14 @@ >> +// SPDX-License-Identifier: (GPL-2.0 OR MIT) >> +/* >> + * (C) Copyright 2019 SiFive, Inc */ >> + >> +/ { >> + soc { >> + otp: otp@10070000 { >> + compatible = "sifive,fu540-c000-otp"; >> + reg = <0x0 0x10070000 0x0 0x0FFF>; >> + fuse-count = <0x1000>; >> + }; >> + }; >> +}; >> 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..f1735c1385 >> --- /dev/null >> +++ b/arch/riscv/dts/hifive-unleashed-a00-u-boot.dtsi >> @@ -0,0 +1,6 @@ >> +// SPDX-License-Identifier: (GPL-2.0 OR MIT) >> +/* >> + * Copyright (C) 2019 SiFive, Inc */ >> + >> +#include "fu540-c000-u-boot.dtsi" >> diff --git a/board/sifive/fu540/Kconfig >> b/board/sifive/fu540/Kconfig index 5ca21474de..900197bbb2 >> 100644 >> --- a/board/sifive/fu540/Kconfig >> +++ b/board/sifive/fu540/Kconfig >> @@ -48,5 +48,7 @@ config BOARD_SPECIFIC_OPTIONS # dummy >> imply SIFIVE_GPIO >> imply CMD_GPIO >> imply SMP >> + imply MISC >> + imply SIFIVE_OTP > >Mark this default y if it is SIFIVE.
All other SiFive drivers (SPI_SIFIVE, SIFIVE_GPIO) are enabled by "imply", so I
am following the same. I think "imply" will make it default y.
Just mark 'default y' on SIFIVE_OTP area of drivers/misc/Kconfig depends on SIFIVE SoC would select this driver so-that you no need to add impy SIFIVE_OTP here.
I am not sure if all SiFive SoC will contain SiFive OTP controller, so it's better
not to make it default y.
If all Sifive SoCs contain OTP controller then I need to add another Kconfig option like "RISCV_SIFIVE" as shown below, config
SIFIVE_OTP
default y if RISCV_SIFIVE
Yes, use this TARGET_SIFIVE_FU540
I am okay with this but if other future SiFive SoCs support this OTP then it
would be a long chain.
What's your opinion on this ?
That is fine, these are at least SoC not boards. boards will increment a lot but SoC may not. Having SoC dependency or select would be meaningful.
Will update this in v7.
Jagan.

On Wed, Apr 8, 2020 at 12:44 PM Pragnesh Patel pragnesh.patel@sifive.com wrote:
Hi Jagan,
-----Original Message----- From: Jagan Teki jagan@amarulasolutions.com Sent: 07 April 2020 14:51 To: Pragnesh Patel pragnesh.patel@sifive.com Cc: U-Boot-Denx u-boot@lists.denx.de; Atish Patra atish.patra@wdc.com; palmerdabbelt@google.com; Bin Meng bmeng.cn@gmail.com; Paul Walmsley paul.walmsley@sifive.com; Troy Benjegerdes troy.benjegerdes@sifive.com; Anup Patel anup.patel@wdc.com; Sagar Kadam sagar.kadam@sifive.com; Rick Chen rick@andestech.com; Palmer Dabbelt palmer@dabbelt.com Subject: Re: [PATCH v6 02/17] riscv: sifive: fu540: Use OTP DM driver for serial environment variable
[External Email] Do not click links or attachments unless you recognize the sender and know the content is safe
On Tue, Apr 7, 2020 at 1:40 PM Pragnesh Patel pragnesh.patel@sifive.com wrote:
Hi Jagan,
-----Original Message----- From: Jagan Teki jagan@amarulasolutions.com Sent: 07 April 2020 13:32 To: Pragnesh Patel pragnesh.patel@sifive.com Cc: U-Boot-Denx u-boot@lists.denx.de; Atish Patra atish.patra@wdc.com; palmerdabbelt@google.com; Bin Meng bmeng.cn@gmail.com; Paul Walmsley paul.walmsley@sifive.com;
Troy
Benjegerdes troy.benjegerdes@sifive.com; Anup Patel anup.patel@wdc.com; Sagar Kadam sagar.kadam@sifive.com; Rick
Chen
rick@andestech.com; Palmer Dabbelt palmer@dabbelt.com Subject: Re: [PATCH v6 02/17] riscv: sifive: fu540: Use OTP DM driver for serial environment variable
[External Email] Do not click links or attachments unless you recognize the sender and know the content is safe
On Thu, Apr 2, 2020 at 3:47 PM Pragnesh Patel pragnesh.patel@sifive.com wrote:
Hi Jagan,
-----Original Message----- From: Jagan Teki jagan@amarulasolutions.com Sent: 02 April 2020 14:59 To: Pragnesh Patel pragnesh.patel@sifive.com Cc: U-Boot-Denx u-boot@lists.denx.de; Atish Patra atish.patra@wdc.com; palmerdabbelt@google.com; Bin Meng bmeng.cn@gmail.com; Paul Walmsley paul.walmsley@sifive.com;
Troy
Benjegerdes troy.benjegerdes@sifive.com; Anup Patel anup.patel@wdc.com; Sagar Kadam sagar.kadam@sifive.com; Rick
Chen
rick@andestech.com; Palmer Dabbelt palmer@dabbelt.com Subject: Re: [PATCH v6 02/17] riscv: sifive: fu540: Use OTP DM driver for serial environment variable
[External Email] Do not click links or attachments unless you recognize the sender and know the content is safe
On Thu, Apr 2, 2020 at 2:54 PM Pragnesh Patel pragnesh.patel@sifive.com wrote: > > > Hi Jagan, > > >-----Original Message----- > >From: Jagan Teki jagan@amarulasolutions.com > >Sent: 02 April 2020 14:49 > >To: Pragnesh Patel pragnesh.patel@sifive.com > >Cc: U-Boot-Denx u-boot@lists.denx.de; Atish Patra > >atish.patra@wdc.com; palmerdabbelt@google.com; Bin Meng > >bmeng.cn@gmail.com; Paul Walmsley
Troy > >Benjegerdes troy.benjegerdes@sifive.com; Anup Patel > >anup.patel@wdc.com; Sagar Kadam sagar.kadam@sifive.com; > >Rick Chen > >rick@andestech.com; Palmer Dabbelt palmer@dabbelt.com > >Subject: Re: [PATCH v6 02/17] riscv: sifive: fu540: Use OTP DM > >driver for serial environment variable > > > >[External Email] Do not click links or attachments unless you > >recognize the sender and know the content is safe > > > >On Sun, Mar 29, 2020 at 10:36 PM Pragnesh Patel > >pragnesh.patel@sifive.com wrote: > >> > >> Use the OTP DM driver to set the serial environment variable. > >> > >> Signed-off-by: Pragnesh Patel pragnesh.patel@sifive.com > >> --- > >> arch/riscv/dts/fu540-c000-u-boot.dtsi | 14 +++ > >> .../dts/hifive-unleashed-a00-u-boot.dtsi | 6 + > >> board/sifive/fu540/Kconfig | 2 + > >> board/sifive/fu540/fu540.c | 111 ++++++------------ > >> 4 files changed, 61 insertions(+), 72 deletions(-) create > >> mode > >> 100644 arch/riscv/dts/fu540-c000-u-boot.dtsi > >> create mode 100644 > >> arch/riscv/dts/hifive-unleashed-a00-u-boot.dtsi > >> > >> 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..db55773bd2 > >> --- /dev/null > >> +++ b/arch/riscv/dts/fu540-c000-u-boot.dtsi > >> @@ -0,0 +1,14 @@ > >> +// SPDX-License-Identifier: (GPL-2.0 OR MIT) > >> +/* > >> + * (C) Copyright 2019 SiFive, Inc */ > >> + > >> +/ { > >> + soc { > >> + otp: otp@10070000 { > >> + compatible = "sifive,fu540-c000-otp"; > >> + reg = <0x0 0x10070000 0x0 0x0FFF>; > >> + fuse-count = <0x1000>; > >> + }; > >> + }; > >> +}; > >> 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..f1735c1385 > >> --- /dev/null > >> +++ b/arch/riscv/dts/hifive-unleashed-a00-u-boot.dtsi > >> @@ -0,0 +1,6 @@ > >> +// SPDX-License-Identifier: (GPL-2.0 OR MIT) > >> +/* > >> + * Copyright (C) 2019 SiFive, Inc */ > >> + > >> +#include "fu540-c000-u-boot.dtsi" > >> diff --git a/board/sifive/fu540/Kconfig > >> b/board/sifive/fu540/Kconfig index 5ca21474de..900197bbb2 > >> 100644 > >> --- a/board/sifive/fu540/Kconfig > >> +++ b/board/sifive/fu540/Kconfig > >> @@ -48,5 +48,7 @@ config BOARD_SPECIFIC_OPTIONS # dummy > >> imply SIFIVE_GPIO > >> imply CMD_GPIO > >> imply SMP > >> + imply MISC > >> + imply SIFIVE_OTP > > > >Mark this default y if it is SIFIVE. > > All other SiFive drivers (SPI_SIFIVE, SIFIVE_GPIO) are enabled > by "imply", so I am following the same. I think "imply" will make it default y.
Just mark 'default y' on SIFIVE_OTP area of drivers/misc/Kconfig depends on SIFIVE SoC would select this driver so-that you no need to add impy SIFIVE_OTP here.
I am not sure if all SiFive SoC will contain SiFive OTP controller, so it's better
not to make it default y.
If all Sifive SoCs contain OTP controller then I need to add another Kconfig option like "RISCV_SIFIVE" as shown below, config
SIFIVE_OTP
default y if RISCV_SIFIVE
Yes, use this TARGET_SIFIVE_FU540
I am okay with this but if other future SiFive SoCs support this OTP then it
would be a long chain.
What's your opinion on this ?
That is fine, these are at least SoC not boards. boards will increment a lot but SoC may not. Having SoC dependency or select would be meaningful.
Will update this in v7.
Sorry replied the wrong version thread.
We should target to bring the FU540 U-Boot SPL support in U-Boot v2020.07. I would like to have some test on this series.
Regards, Bin

Hi Jagan,
On Tue, Apr 7, 2020 at 5:21 PM Jagan Teki jagan@amarulasolutions.com wrote:
On Tue, Apr 7, 2020 at 1:40 PM Pragnesh Patel pragnesh.patel@sifive.com wrote:
Hi Jagan,
-----Original Message----- From: Jagan Teki jagan@amarulasolutions.com Sent: 07 April 2020 13:32 To: Pragnesh Patel pragnesh.patel@sifive.com Cc: U-Boot-Denx u-boot@lists.denx.de; Atish Patra atish.patra@wdc.com; palmerdabbelt@google.com; Bin Meng bmeng.cn@gmail.com; Paul Walmsley paul.walmsley@sifive.com; Troy Benjegerdes troy.benjegerdes@sifive.com; Anup Patel anup.patel@wdc.com; Sagar Kadam sagar.kadam@sifive.com; Rick Chen rick@andestech.com; Palmer Dabbelt palmer@dabbelt.com Subject: Re: [PATCH v6 02/17] riscv: sifive: fu540: Use OTP DM driver for serial environment variable
[External Email] Do not click links or attachments unless you recognize the sender and know the content is safe
On Thu, Apr 2, 2020 at 3:47 PM Pragnesh Patel pragnesh.patel@sifive.com wrote:
Hi Jagan,
-----Original Message----- From: Jagan Teki jagan@amarulasolutions.com Sent: 02 April 2020 14:59 To: Pragnesh Patel pragnesh.patel@sifive.com Cc: U-Boot-Denx u-boot@lists.denx.de; Atish Patra atish.patra@wdc.com; palmerdabbelt@google.com; Bin Meng bmeng.cn@gmail.com; Paul Walmsley paul.walmsley@sifive.com;
Troy
Benjegerdes troy.benjegerdes@sifive.com; Anup Patel anup.patel@wdc.com; Sagar Kadam sagar.kadam@sifive.com; Rick
Chen
rick@andestech.com; Palmer Dabbelt palmer@dabbelt.com Subject: Re: [PATCH v6 02/17] riscv: sifive: fu540: Use OTP DM driver for serial environment variable
[External Email] Do not click links or attachments unless you recognize the sender and know the content is safe
On Thu, Apr 2, 2020 at 2:54 PM Pragnesh Patel pragnesh.patel@sifive.com wrote:
Hi Jagan,
>-----Original Message----- >From: Jagan Teki jagan@amarulasolutions.com >Sent: 02 April 2020 14:49 >To: Pragnesh Patel pragnesh.patel@sifive.com >Cc: U-Boot-Denx u-boot@lists.denx.de; Atish Patra >atish.patra@wdc.com; palmerdabbelt@google.com; Bin Meng >bmeng.cn@gmail.com; Paul Walmsley paul.walmsley@sifive.com;
Troy
>Benjegerdes troy.benjegerdes@sifive.com; Anup Patel >anup.patel@wdc.com; Sagar Kadam sagar.kadam@sifive.com; Rick
Chen
>rick@andestech.com; Palmer Dabbelt palmer@dabbelt.com >Subject: Re: [PATCH v6 02/17] riscv: sifive: fu540: Use OTP DM >driver for serial environment variable > >[External Email] Do not click links or attachments unless you >recognize the sender and know the content is safe > >On Sun, Mar 29, 2020 at 10:36 PM Pragnesh Patel >pragnesh.patel@sifive.com wrote: >> >> Use the OTP DM driver to set the serial environment variable. >> >> Signed-off-by: Pragnesh Patel pragnesh.patel@sifive.com >> --- >> arch/riscv/dts/fu540-c000-u-boot.dtsi | 14 +++ >> .../dts/hifive-unleashed-a00-u-boot.dtsi | 6 + >> board/sifive/fu540/Kconfig | 2 + >> board/sifive/fu540/fu540.c | 111 ++++++------------ >> 4 files changed, 61 insertions(+), 72 deletions(-) create mode >> 100644 arch/riscv/dts/fu540-c000-u-boot.dtsi >> create mode 100644 >> arch/riscv/dts/hifive-unleashed-a00-u-boot.dtsi >> >> 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..db55773bd2 >> --- /dev/null >> +++ b/arch/riscv/dts/fu540-c000-u-boot.dtsi >> @@ -0,0 +1,14 @@ >> +// SPDX-License-Identifier: (GPL-2.0 OR MIT) >> +/* >> + * (C) Copyright 2019 SiFive, Inc */ >> + >> +/ { >> + soc { >> + otp: otp@10070000 { >> + compatible = "sifive,fu540-c000-otp"; >> + reg = <0x0 0x10070000 0x0 0x0FFF>; >> + fuse-count = <0x1000>; >> + }; >> + }; >> +}; >> 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..f1735c1385 >> --- /dev/null >> +++ b/arch/riscv/dts/hifive-unleashed-a00-u-boot.dtsi >> @@ -0,0 +1,6 @@ >> +// SPDX-License-Identifier: (GPL-2.0 OR MIT) >> +/* >> + * Copyright (C) 2019 SiFive, Inc */ >> + >> +#include "fu540-c000-u-boot.dtsi" >> diff --git a/board/sifive/fu540/Kconfig >> b/board/sifive/fu540/Kconfig index 5ca21474de..900197bbb2 100644 >> --- a/board/sifive/fu540/Kconfig >> +++ b/board/sifive/fu540/Kconfig >> @@ -48,5 +48,7 @@ config BOARD_SPECIFIC_OPTIONS # dummy >> imply SIFIVE_GPIO >> imply CMD_GPIO >> imply SMP >> + imply MISC >> + imply SIFIVE_OTP > >Mark this default y if it is SIFIVE.
All other SiFive drivers (SPI_SIFIVE, SIFIVE_GPIO) are enabled by "imply", so I
am following the same. I think "imply" will make it default y.
Just mark 'default y' on SIFIVE_OTP area of drivers/misc/Kconfig depends on SIFIVE SoC would select this driver so-that you no need to add impy SIFIVE_OTP here.
I am not sure if all SiFive SoC will contain SiFive OTP controller, so it's better
not to make it default y.
If all Sifive SoCs contain OTP controller then I need to add another Kconfig option like "RISCV_SIFIVE" as shown below, config SIFIVE_OTP default y if RISCV_SIFIVE
Yes, use this TARGET_SIFIVE_FU540
I am okay with this but if other future SiFive SoCs support this OTP then it would be a long chain. What's your opinion on this ?
That is fine, these are at least SoC not boards. boards will increment a lot but SoC may not. Having SoC dependency or select would be meaningful.
I am not in favor of adding default y if TARGET_SIFIVE_FU540 in the driver Kconfig file.
I think we can add the "imply" or "select" in the SoC Kconfig file instead if adding such "imply" in the board level Kconfig is a concern.
See an example of arch/x86/cpu/baytrail/Kconfig
config INTEL_BAYTRAIL bool select HAVE_FSP select ARCH_MISC_INIT select CPU_INTEL_TURBO_NOT_PACKAGE_SCOPED imply HAVE_INTEL_ME imply ENABLE_MRC_CACHE imply AHCI_PCI imply ICH_SPI imply INTEL_ICH6_GPIO imply PINCTRL_ICH6 imply MMC imply MMC_PCI imply MMC_SDHCI imply MMC_SDHCI_SDMA imply SCSI imply SCSI_AHCI imply SPI_FLASH imply SYS_NS16550 imply USB imply USB_EHCI_HCD imply USB_XHCI_HCD imply VIDEO_VESA
Regards, Bin

Hi Bin,
On Mon, Apr 20, 2020 at 1:24 PM Bin Meng bmeng.cn@gmail.com wrote:
Hi Jagan,
On Tue, Apr 7, 2020 at 5:21 PM Jagan Teki jagan@amarulasolutions.com wrote:
On Tue, Apr 7, 2020 at 1:40 PM Pragnesh Patel pragnesh.patel@sifive.com wrote:
Hi Jagan,
-----Original Message----- From: Jagan Teki jagan@amarulasolutions.com Sent: 07 April 2020 13:32 To: Pragnesh Patel pragnesh.patel@sifive.com Cc: U-Boot-Denx u-boot@lists.denx.de; Atish Patra atish.patra@wdc.com; palmerdabbelt@google.com; Bin Meng bmeng.cn@gmail.com; Paul Walmsley paul.walmsley@sifive.com; Troy Benjegerdes troy.benjegerdes@sifive.com; Anup Patel anup.patel@wdc.com; Sagar Kadam sagar.kadam@sifive.com; Rick Chen rick@andestech.com; Palmer Dabbelt palmer@dabbelt.com Subject: Re: [PATCH v6 02/17] riscv: sifive: fu540: Use OTP DM driver for serial environment variable
[External Email] Do not click links or attachments unless you recognize the sender and know the content is safe
On Thu, Apr 2, 2020 at 3:47 PM Pragnesh Patel pragnesh.patel@sifive.com wrote:
Hi Jagan,
-----Original Message----- From: Jagan Teki jagan@amarulasolutions.com Sent: 02 April 2020 14:59 To: Pragnesh Patel pragnesh.patel@sifive.com Cc: U-Boot-Denx u-boot@lists.denx.de; Atish Patra atish.patra@wdc.com; palmerdabbelt@google.com; Bin Meng bmeng.cn@gmail.com; Paul Walmsley paul.walmsley@sifive.com;
Troy
Benjegerdes troy.benjegerdes@sifive.com; Anup Patel anup.patel@wdc.com; Sagar Kadam sagar.kadam@sifive.com; Rick
Chen
rick@andestech.com; Palmer Dabbelt palmer@dabbelt.com Subject: Re: [PATCH v6 02/17] riscv: sifive: fu540: Use OTP DM driver for serial environment variable
[External Email] Do not click links or attachments unless you recognize the sender and know the content is safe
On Thu, Apr 2, 2020 at 2:54 PM Pragnesh Patel pragnesh.patel@sifive.com wrote: > > > Hi Jagan, > > >-----Original Message----- > >From: Jagan Teki jagan@amarulasolutions.com > >Sent: 02 April 2020 14:49 > >To: Pragnesh Patel pragnesh.patel@sifive.com > >Cc: U-Boot-Denx u-boot@lists.denx.de; Atish Patra > >atish.patra@wdc.com; palmerdabbelt@google.com; Bin Meng > >bmeng.cn@gmail.com; Paul Walmsley paul.walmsley@sifive.com; Troy > >Benjegerdes troy.benjegerdes@sifive.com; Anup Patel > >anup.patel@wdc.com; Sagar Kadam sagar.kadam@sifive.com; Rick Chen > >rick@andestech.com; Palmer Dabbelt palmer@dabbelt.com > >Subject: Re: [PATCH v6 02/17] riscv: sifive: fu540: Use OTP DM > >driver for serial environment variable > > > >[External Email] Do not click links or attachments unless you > >recognize the sender and know the content is safe > > > >On Sun, Mar 29, 2020 at 10:36 PM Pragnesh Patel > >pragnesh.patel@sifive.com wrote: > >> > >> Use the OTP DM driver to set the serial environment variable. > >> > >> Signed-off-by: Pragnesh Patel pragnesh.patel@sifive.com > >> --- > >> arch/riscv/dts/fu540-c000-u-boot.dtsi | 14 +++ > >> .../dts/hifive-unleashed-a00-u-boot.dtsi | 6 + > >> board/sifive/fu540/Kconfig | 2 + > >> board/sifive/fu540/fu540.c | 111 ++++++------------ > >> 4 files changed, 61 insertions(+), 72 deletions(-) create mode > >> 100644 arch/riscv/dts/fu540-c000-u-boot.dtsi > >> create mode 100644 > >> arch/riscv/dts/hifive-unleashed-a00-u-boot.dtsi > >> > >> 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..db55773bd2 > >> --- /dev/null > >> +++ b/arch/riscv/dts/fu540-c000-u-boot.dtsi > >> @@ -0,0 +1,14 @@ > >> +// SPDX-License-Identifier: (GPL-2.0 OR MIT) > >> +/* > >> + * (C) Copyright 2019 SiFive, Inc */ > >> + > >> +/ { > >> + soc { > >> + otp: otp@10070000 { > >> + compatible = "sifive,fu540-c000-otp"; > >> + reg = <0x0 0x10070000 0x0 0x0FFF>; > >> + fuse-count = <0x1000>; > >> + }; > >> + }; > >> +}; > >> 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..f1735c1385 > >> --- /dev/null > >> +++ b/arch/riscv/dts/hifive-unleashed-a00-u-boot.dtsi > >> @@ -0,0 +1,6 @@ > >> +// SPDX-License-Identifier: (GPL-2.0 OR MIT) > >> +/* > >> + * Copyright (C) 2019 SiFive, Inc */ > >> + > >> +#include "fu540-c000-u-boot.dtsi" > >> diff --git a/board/sifive/fu540/Kconfig > >> b/board/sifive/fu540/Kconfig index 5ca21474de..900197bbb2 100644 > >> --- a/board/sifive/fu540/Kconfig > >> +++ b/board/sifive/fu540/Kconfig > >> @@ -48,5 +48,7 @@ config BOARD_SPECIFIC_OPTIONS # dummy > >> imply SIFIVE_GPIO > >> imply CMD_GPIO > >> imply SMP > >> + imply MISC > >> + imply SIFIVE_OTP > > > >Mark this default y if it is SIFIVE. > > All other SiFive drivers (SPI_SIFIVE, SIFIVE_GPIO) are enabled by > "imply", so I am following the same. I think "imply" will make it default y.
Just mark 'default y' on SIFIVE_OTP area of drivers/misc/Kconfig depends on SIFIVE SoC would select this driver so-that you no need to add impy SIFIVE_OTP here.
I am not sure if all SiFive SoC will contain SiFive OTP controller, so it's better
not to make it default y.
If all Sifive SoCs contain OTP controller then I need to add another Kconfig option like "RISCV_SIFIVE" as shown below, config SIFIVE_OTP default y if RISCV_SIFIVE
Yes, use this TARGET_SIFIVE_FU540
I am okay with this but if other future SiFive SoCs support this OTP then it would be a long chain. What's your opinion on this ?
That is fine, these are at least SoC not boards. boards will increment a lot but SoC may not. Having SoC dependency or select would be meaningful.
I am not in favor of adding default y if TARGET_SIFIVE_FU540 in the driver Kconfig file.
I think we can add the "imply" or "select" in the SoC Kconfig file instead if adding such "imply" in the board level Kconfig is a concern.
Technically this is an SoC driver and doesn't relate to a specific board and to be precise TARGET_SIFIVE_FU540 is SoC not the target(board). We do have several examples of following this strategy and having a driver selecting on board will be redundant to select the same in other boards if they use the same SoC.
On this specific note, I've been encouraged to select it on driver Kconfig if SoC (TARGET_SIFIVE_FU540) is defined.
Jagan.

Hi Jagan,
On Mon, Apr 20, 2020 at 4:15 PM Jagan Teki jagan@amarulasolutions.com wrote:
Hi Bin,
On Mon, Apr 20, 2020 at 1:24 PM Bin Meng bmeng.cn@gmail.com wrote:
Hi Jagan,
On Tue, Apr 7, 2020 at 5:21 PM Jagan Teki jagan@amarulasolutions.com wrote:
On Tue, Apr 7, 2020 at 1:40 PM Pragnesh Patel pragnesh.patel@sifive.com wrote:
Hi Jagan,
-----Original Message----- From: Jagan Teki jagan@amarulasolutions.com Sent: 07 April 2020 13:32 To: Pragnesh Patel pragnesh.patel@sifive.com Cc: U-Boot-Denx u-boot@lists.denx.de; Atish Patra atish.patra@wdc.com; palmerdabbelt@google.com; Bin Meng bmeng.cn@gmail.com; Paul Walmsley paul.walmsley@sifive.com; Troy Benjegerdes troy.benjegerdes@sifive.com; Anup Patel anup.patel@wdc.com; Sagar Kadam sagar.kadam@sifive.com; Rick Chen rick@andestech.com; Palmer Dabbelt palmer@dabbelt.com Subject: Re: [PATCH v6 02/17] riscv: sifive: fu540: Use OTP DM driver for serial environment variable
[External Email] Do not click links or attachments unless you recognize the sender and know the content is safe
On Thu, Apr 2, 2020 at 3:47 PM Pragnesh Patel pragnesh.patel@sifive.com wrote:
Hi Jagan,
>-----Original Message----- >From: Jagan Teki jagan@amarulasolutions.com >Sent: 02 April 2020 14:59 >To: Pragnesh Patel pragnesh.patel@sifive.com >Cc: U-Boot-Denx u-boot@lists.denx.de; Atish Patra >atish.patra@wdc.com; palmerdabbelt@google.com; Bin Meng >bmeng.cn@gmail.com; Paul Walmsley paul.walmsley@sifive.com;
Troy
>Benjegerdes troy.benjegerdes@sifive.com; Anup Patel >anup.patel@wdc.com; Sagar Kadam sagar.kadam@sifive.com; Rick
Chen
>rick@andestech.com; Palmer Dabbelt palmer@dabbelt.com >Subject: Re: [PATCH v6 02/17] riscv: sifive: fu540: Use OTP DM driver >for serial environment variable > >[External Email] Do not click links or attachments unless you >recognize the sender and know the content is safe > >On Thu, Apr 2, 2020 at 2:54 PM Pragnesh Patel >pragnesh.patel@sifive.com >wrote: >> >> >> Hi Jagan, >> >> >-----Original Message----- >> >From: Jagan Teki jagan@amarulasolutions.com >> >Sent: 02 April 2020 14:49 >> >To: Pragnesh Patel pragnesh.patel@sifive.com >> >Cc: U-Boot-Denx u-boot@lists.denx.de; Atish Patra >> >atish.patra@wdc.com; palmerdabbelt@google.com; Bin Meng >> >bmeng.cn@gmail.com; Paul Walmsley paul.walmsley@sifive.com; >Troy >> >Benjegerdes troy.benjegerdes@sifive.com; Anup Patel >> >anup.patel@wdc.com; Sagar Kadam sagar.kadam@sifive.com; Rick >Chen >> >rick@andestech.com; Palmer Dabbelt palmer@dabbelt.com >> >Subject: Re: [PATCH v6 02/17] riscv: sifive: fu540: Use OTP DM >> >driver for serial environment variable >> > >> >[External Email] Do not click links or attachments unless you >> >recognize the sender and know the content is safe >> > >> >On Sun, Mar 29, 2020 at 10:36 PM Pragnesh Patel >> >pragnesh.patel@sifive.com wrote: >> >> >> >> Use the OTP DM driver to set the serial environment variable. >> >> >> >> Signed-off-by: Pragnesh Patel pragnesh.patel@sifive.com >> >> --- >> >> arch/riscv/dts/fu540-c000-u-boot.dtsi | 14 +++ >> >> .../dts/hifive-unleashed-a00-u-boot.dtsi | 6 + >> >> board/sifive/fu540/Kconfig | 2 + >> >> board/sifive/fu540/fu540.c | 111 ++++++------------ >> >> 4 files changed, 61 insertions(+), 72 deletions(-) create mode >> >> 100644 arch/riscv/dts/fu540-c000-u-boot.dtsi >> >> create mode 100644 >> >> arch/riscv/dts/hifive-unleashed-a00-u-boot.dtsi >> >> >> >> 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..db55773bd2 >> >> --- /dev/null >> >> +++ b/arch/riscv/dts/fu540-c000-u-boot.dtsi >> >> @@ -0,0 +1,14 @@ >> >> +// SPDX-License-Identifier: (GPL-2.0 OR MIT) >> >> +/* >> >> + * (C) Copyright 2019 SiFive, Inc */ >> >> + >> >> +/ { >> >> + soc { >> >> + otp: otp@10070000 { >> >> + compatible = "sifive,fu540-c000-otp"; >> >> + reg = <0x0 0x10070000 0x0 0x0FFF>; >> >> + fuse-count = <0x1000>; >> >> + }; >> >> + }; >> >> +}; >> >> 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..f1735c1385 >> >> --- /dev/null >> >> +++ b/arch/riscv/dts/hifive-unleashed-a00-u-boot.dtsi >> >> @@ -0,0 +1,6 @@ >> >> +// SPDX-License-Identifier: (GPL-2.0 OR MIT) >> >> +/* >> >> + * Copyright (C) 2019 SiFive, Inc */ >> >> + >> >> +#include "fu540-c000-u-boot.dtsi" >> >> diff --git a/board/sifive/fu540/Kconfig >> >> b/board/sifive/fu540/Kconfig index 5ca21474de..900197bbb2 100644 >> >> --- a/board/sifive/fu540/Kconfig >> >> +++ b/board/sifive/fu540/Kconfig >> >> @@ -48,5 +48,7 @@ config BOARD_SPECIFIC_OPTIONS # dummy >> >> imply SIFIVE_GPIO >> >> imply CMD_GPIO >> >> imply SMP >> >> + imply MISC >> >> + imply SIFIVE_OTP >> > >> >Mark this default y if it is SIFIVE. >> >> All other SiFive drivers (SPI_SIFIVE, SIFIVE_GPIO) are enabled by >> "imply", so I >am following the same. I think "imply" will make it default y. > >Just mark 'default y' on SIFIVE_OTP area of drivers/misc/Kconfig >depends on SIFIVE SoC would select this driver so-that you no need to >add impy SIFIVE_OTP here.
I am not sure if all SiFive SoC will contain SiFive OTP controller, so it's better
not to make it default y.
If all Sifive SoCs contain OTP controller then I need to add another Kconfig option like "RISCV_SIFIVE" as shown below, config SIFIVE_OTP default y if RISCV_SIFIVE
Yes, use this TARGET_SIFIVE_FU540
I am okay with this but if other future SiFive SoCs support this OTP then it would be a long chain. What's your opinion on this ?
That is fine, these are at least SoC not boards. boards will increment a lot but SoC may not. Having SoC dependency or select would be meaningful.
I am not in favor of adding default y if TARGET_SIFIVE_FU540 in the driver Kconfig file.
I think we can add the "imply" or "select" in the SoC Kconfig file instead if adding such "imply" in the board level Kconfig is a concern.
Technically this is an SoC driver and doesn't relate to a specific board and to be precise TARGET_SIFIVE_FU540 is SoC not the target(board). We do have several examples of following this strategy and having a driver selecting on board will be redundant to select the same in other boards if they use the same SoC.
On this specific note, I've been encouraged to select it on driver Kconfig if SoC (TARGET_SIFIVE_FU540) is defined.
Yes, I understand this is SoC specific. So as I mentioned let's do this in the SoC Kconfig file instead. Linux also is using the SoC Kconfig practice to select drivers.
Regards, Bin

On Mon, Mar 30, 2020 at 1:06 AM Pragnesh Patel pragnesh.patel@sifive.com wrote:
Use the OTP DM driver to set the serial environment variable.
Signed-off-by: Pragnesh Patel pragnesh.patel@sifive.com
arch/riscv/dts/fu540-c000-u-boot.dtsi | 14 +++ .../dts/hifive-unleashed-a00-u-boot.dtsi | 6 + board/sifive/fu540/Kconfig | 2 + board/sifive/fu540/fu540.c | 111 ++++++------------ 4 files changed, 61 insertions(+), 72 deletions(-) create mode 100644 arch/riscv/dts/fu540-c000-u-boot.dtsi create mode 100644 arch/riscv/dts/hifive-unleashed-a00-u-boot.dtsi
Reviewed-by: Bin Meng bmeng.cn@gmail.com

For SPL_SEPARATE_BSS, Device tree will be put at _image_binary_end
Signed-off-by: Pragnesh Patel pragnesh.patel@sifive.com Reviewed-by: Anup Patel anup.patel@wdc.com Reviewed-by: Jagan Teki jagan@amarulasolutions.com --- arch/riscv/cpu/u-boot-spl.lds | 1 + 1 file changed, 1 insertion(+)
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 = .;

On Mon, Mar 30, 2020 at 1:06 AM Pragnesh Patel pragnesh.patel@sifive.com wrote:
For SPL_SEPARATE_BSS, Device tree will be put at _image_binary_end
Signed-off-by: Pragnesh Patel pragnesh.patel@sifive.com Reviewed-by: Anup Patel anup.patel@wdc.com Reviewed-by: Jagan Teki jagan@amarulasolutions.com
arch/riscv/cpu/u-boot-spl.lds | 1 + 1 file changed, 1 insertion(+)
Reviewed-by: Bin Meng bmeng.cn@gmail.com

When build U-Boot SPL, meet an issue of undefined reference to 'crc7' for drivers/mmc/mmc_spi.c, so let's compile crc7.c when CONFIG_MMC_SPI selected.
Signed-off-by: Pragnesh Patel pragnesh.patel@sifive.com --- common/spl/Kconfig | 6 ++++++ drivers/mmc/Kconfig | 1 + lib/Makefile | 1 + 3 files changed, 8 insertions(+)
diff --git a/common/spl/Kconfig b/common/spl/Kconfig index b03a476b9f..07eee56219 100644 --- a/common/spl/Kconfig +++ b/common/spl/Kconfig @@ -401,6 +401,12 @@ config SPL_CRC32_SUPPORT for detected accidental image corruption. For secure applications you should consider SHA1 or SHA256.
+config SPL_CRC7_SUPPORT + bool "Support CRC7" + help + Enable CRC7 hashing for drivers which are using in SPL. + This is a 32-bit checksum value that can be used to verify images. + config SPL_MD5_SUPPORT bool "Support MD5" depends on SPL_FIT diff --git a/drivers/mmc/Kconfig b/drivers/mmc/Kconfig index 2f0eedc22f..f23a3242b3 100644 --- a/drivers/mmc/Kconfig +++ b/drivers/mmc/Kconfig @@ -49,6 +49,7 @@ if MMC config MMC_SPI bool "Support for SPI-based MMC controller" depends on DM_MMC && DM_SPI + select SPL_CRC7_SUPPORT if SPL help This selects SPI-based MMC controllers. If you have an MMC controller on a SPI bus, say Y here. diff --git a/lib/Makefile b/lib/Makefile index 15259d0473..7a50aa56ef 100644 --- a/lib/Makefile +++ b/lib/Makefile @@ -78,6 +78,7 @@ endif
ifdef CONFIG_SPL_BUILD obj-$(CONFIG_SPL_YMODEM_SUPPORT) += crc16.o +obj-$(CONFIG_SPL_CRC7_SUPPORT) += crc7.o obj-$(CONFIG_$(SPL_TPL_)HASH_SUPPORT) += crc16.o obj-y += net_utils.o endif

On Sun, Mar 29, 2020 at 10:36 PM Pragnesh Patel pragnesh.patel@sifive.com wrote:
When build U-Boot SPL, meet an issue of undefined reference to 'crc7' for drivers/mmc/mmc_spi.c, so let's compile crc7.c when CONFIG_MMC_SPI selected.
Signed-off-by: Pragnesh Patel pragnesh.patel@sifive.com
Reviewed-by: Jagan Teki jagan@amarulasolutions.com

On Mon, Mar 30, 2020 at 1:06 AM Pragnesh Patel pragnesh.patel@sifive.com wrote:
When build U-Boot SPL, meet an issue of undefined reference to 'crc7' for drivers/mmc/mmc_spi.c, so let's compile crc7.c when CONFIG_MMC_SPI selected.
Signed-off-by: Pragnesh Patel pragnesh.patel@sifive.com
common/spl/Kconfig | 6 ++++++ drivers/mmc/Kconfig | 1 + lib/Makefile | 1 + 3 files changed, 8 insertions(+)
Reviewed-by: Bin Meng bmeng.cn@gmail.com

Devicetree files in FU540 platform is synced from Linux, like other platforms does. Apart from these U-Boot in FU540 would also require some U-Boot specific node like clint.
So, create board specific -u-boot.dtsi files. This would help of maintain U-Boot specific changes separately without touching Linux dts(i) files which indeed easy for syncing from Linux between releases.
Signed-off-by: Pragnesh Patel pragnesh.patel@sifive.com Reviewed-by: Anup Patel anup.patel@wdc.com Reviewed-by: Bin Meng bmeng.cn@gmail.com --- arch/riscv/dts/fu540-c000-u-boot.dtsi | 54 +++++++++++++++++++ .../dts/hifive-unleashed-a00-u-boot.dtsi | 16 ++++++ 2 files changed, 70 insertions(+)
diff --git a/arch/riscv/dts/fu540-c000-u-boot.dtsi b/arch/riscv/dts/fu540-c000-u-boot.dtsi index db55773bd2..387b13bdfb 100644 --- a/arch/riscv/dts/fu540-c000-u-boot.dtsi +++ b/arch/riscv/dts/fu540-c000-u-boot.dtsi @@ -4,11 +4,65 @@ */
/ { + 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; otp: otp@10070000 { compatible = "sifive,fu540-c000-otp"; reg = <0x0 0x10070000 0x0 0x0FFF>; fuse-count = <0x1000>; }; + clint@2000000 { + compatible = "riscv,clint0"; + interrupts-extended = <&cpu0_intc 3 &cpu0_intc 7 &cpu1_intc 3 &cpu1_intc 7 &cpu2_intc 3 &cpu2_intc 7 &cpu3_intc 3 &cpu3_intc 7 &cpu4_intc 3 &cpu4_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 index f1735c1385..efa7cbb75d 100644 --- a/arch/riscv/dts/hifive-unleashed-a00-u-boot.dtsi +++ b/arch/riscv/dts/hifive-unleashed-a00-u-boot.dtsi @@ -4,3 +4,19 @@ */
#include "fu540-c000-u-boot.dtsi" + +/ { + hfclk { + u-boot,dm-spl; + }; + + rtcclk { + u-boot,dm-spl; + }; +}; + +&qspi2 { + mmc@0 { + u-boot,dm-spl; + }; +};

On Sun, Mar 29, 2020 at 10:36 PM Pragnesh Patel pragnesh.patel@sifive.com wrote:
Devicetree files in FU540 platform is synced from Linux, like other platforms does. Apart from these U-Boot in FU540 would also require some U-Boot specific node like clint.
So, create board specific -u-boot.dtsi files. This would help of maintain U-Boot specific changes separately without touching Linux dts(i) files which indeed easy for syncing from Linux between releases.
Signed-off-by: Pragnesh Patel pragnesh.patel@sifive.com Reviewed-by: Anup Patel anup.patel@wdc.com Reviewed-by: Bin Meng bmeng.cn@gmail.com
Reviewed-by: Jagan Teki jagan@amarulasolutions.com

Add driver for fu540 to support ddr initialization in SPL. This driver is based on FSBL (https://github.com/sifive/freedom-u540-c000-bootloader.git)
Signed-off-by: Pragnesh Patel pragnesh.patel@sifive.com --- drivers/ram/Kconfig | 7 + drivers/ram/Makefile | 2 + drivers/ram/sifive/Kconfig | 8 + drivers/ram/sifive/Makefile | 6 + drivers/ram/sifive/sdram_fu540.c | 399 +++++++++++++++++++++++++++++++ 5 files changed, 422 insertions(+) create mode 100644 drivers/ram/sifive/Kconfig create mode 100644 drivers/ram/sifive/Makefile create mode 100644 drivers/ram/sifive/sdram_fu540.c
diff --git a/drivers/ram/Kconfig b/drivers/ram/Kconfig index 56fea7c94c..c60c63204c 100644 --- a/drivers/ram/Kconfig +++ b/drivers/ram/Kconfig @@ -73,5 +73,12 @@ config IMXRT_SDRAM to support external memories like sdram, psram & nand. This driver is for the sdram memory interface with the SEMC.
+config SIFIVE_DDR + bool "Enable SiFive DDR support" + depends on RAM + help + Enable support for the internal DDR Memory Controller of SiFive SoCs. + source "drivers/ram/rockchip/Kconfig" source "drivers/ram/stm32mp1/Kconfig" +source "drivers/ram/sifive/Kconfig" diff --git a/drivers/ram/Makefile b/drivers/ram/Makefile index 5c897410c6..12bf61510b 100644 --- a/drivers/ram/Makefile +++ b/drivers/ram/Makefile @@ -17,3 +17,5 @@ obj-$(CONFIG_ARCH_MEDIATEK) += mediatek/ obj-$(CONFIG_K3_J721E_DDRSS) += k3-j721e/
obj-$(CONFIG_IMXRT_SDRAM) += imxrt_sdram.o + +obj-$(CONFIG_SIFIVE_DDR) += sifive/ diff --git a/drivers/ram/sifive/Kconfig b/drivers/ram/sifive/Kconfig new file mode 100644 index 0000000000..b754700db8 --- /dev/null +++ b/drivers/ram/sifive/Kconfig @@ -0,0 +1,8 @@ +config SIFIVE_FU540_DDR + bool "SiFive FU540 DDR driver" + depends on DM && OF_CONTROL + select RAM + select SPL_RAM if SPL + select SIFIVE_DDR + help + This enables DDR support for the platforms based on SiFive FU540 SoC. diff --git a/drivers/ram/sifive/Makefile b/drivers/ram/sifive/Makefile new file mode 100644 index 0000000000..0187805199 --- /dev/null +++ b/drivers/ram/sifive/Makefile @@ -0,0 +1,6 @@ +# SPDX-License-Identifier: GPL-2.0+ +# +# Copyright (c) 2020 SiFive, Inc +# + +obj-$(CONFIG_SIFIVE_FU540_DDR) += sdram_fu540.o diff --git a/drivers/ram/sifive/sdram_fu540.c b/drivers/ram/sifive/sdram_fu540.c new file mode 100644 index 0000000000..6e6c551ced --- /dev/null +++ b/drivers/ram/sifive/sdram_fu540.c @@ -0,0 +1,399 @@ +// SPDX-License-Identifier: GPL-2.0+ OR BSD-3-Clause +/* + * (C) Copyright 2020 SiFive, Inc. + * + * Authors: + * Pragnesh Patel pragnesh.patel@sifive.com + */ + +#include <common.h> +#include <dm.h> +#include <init.h> +#include <ram.h> +#include <regmap.h> +#include <syscon.h> +#include <asm/io.h> + +#define DENALI_CTL_0 0 +#define DENALI_CTL_21 21 +#define DENALI_CTL_120 120 +#define DENALI_CTL_132 132 +#define DENALI_CTL_136 136 +#define DENALI_CTL_170 170 +#define DENALI_CTL_181 181 +#define DENALI_CTL_182 182 +#define DENALI_CTL_184 184 +#define DENALI_CTL_208 208 +#define DENALI_CTL_209 209 +#define DENALI_CTL_210 210 +#define DENALI_CTL_212 212 +#define DENALI_CTL_214 214 +#define DENALI_CTL_216 216 +#define DENALI_CTL_224 224 +#define DENALI_CTL_225 225 +#define DENALI_CTL_260 260 + +#define DENALI_PHY_1152 1152 +#define DENALI_PHY_1214 1214 + +#define PAYLOAD_DEST 0x80000000 +#define DDR_MEM_SIZE (8UL * 1024UL * 1024UL * 1024UL) + +#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 +#define PORT_COMMAND_CHANNEL_ERROR_OFFSET 7 +#define MC_INIT_COMPLETE_OFFSET 8 +#define LEVELING_OPERATION_COMPLETED_OFFSET 22 +#define DFI_PHY_WRLELV_MODE_OFFSET 24 +#define DFI_PHY_RDLVL_MODE_OFFSET 24 +#define DFI_PHY_RDLVL_GATE_MODE_OFFSET 0 +#define VREF_EN_OFFSET 24 +#define PORT_ADDR_PROTECTION_EN_OFFSET 0 +#define AXI0_ADDRESS_RANGE_ENABLE 8 +#define AXI0_RANGE_PROT_BITS_0_OFFSET 24 +#define RDLVL_EN_OFFSET 16 +#define RDLVL_GATE_EN_OFFSET 24 +#define WRLVL_EN_OFFSET 0 + +#define PHY_RX_CAL_DQ0_0_OFFSET 0 +#define PHY_RX_CAL_DQ1_0_OFFSET 16 + +struct fu540_ddrctl { + volatile u32 denali_ctl[265]; +}; + +struct fu540_ddrphy { + volatile u32 denali_phy[1215]; +}; + +/** + * struct ddr_info + * + * @dev : pointer for the device + * @info : UCLASS RAM information + * @ctl : DDR controller base address + * @phy : DDR PHY base address + * @ctrl : DDR control base address + * @physical_filter_ctrl : DDR physical filter control base address + */ +struct ddr_info { + struct udevice *dev; + struct ram_info info; + struct fu540_ddrctl *ctl; + struct fu540_ddrphy *phy; + u32 *physical_filter_ctrl; +}; + +#if defined(CONFIG_TPL_BUILD) || \ + (!defined(CONFIG_TPL) && defined(CONFIG_SPL_BUILD)) + +struct fu540_sdram_params { + struct fu540_ddrctl pctl_regs; + struct fu540_ddrphy phy_regs; +}; + +struct sifive_dmc_plat { +#if CONFIG_IS_ENABLED(OF_PLATDATA) + struct dtd_sifive_fu540_dmc dtplat; +#else + struct fu540_sdram_params sdram_params; +#endif +}; + +/* n: Unit bytes */ +static void sdram_copy_to_reg(volatile u32 *dest, + volatile u32 *src, u32 n) +{ + int i; + + for (i = 0; i < n / sizeof(u32); i++) { + writel(*src, dest); + src++; + dest++; + } +} + +static void ddr_setuprangeprotection(volatile u32 *ctl, u64 end_addr) +{ + u32 end_addr_16kblocks = ((end_addr >> 14) & 0x7FFFFF) - 1; + + writel(0x0, DENALI_CTL_209 + ctl); + writel(end_addr_16kblocks, DENALI_CTL_210 + ctl); + writel(0x0, DENALI_CTL_212 + ctl); + writel(0x0, DENALI_CTL_214 + ctl); + writel(0x0, DENALI_CTL_216 + ctl); + setbits_le32(DENALI_CTL_224 + ctl, + 0x3 << AXI0_RANGE_PROT_BITS_0_OFFSET); + writel(0xFFFFFFFF, DENALI_CTL_225 + ctl); + setbits_le32(DENALI_CTL_208 + ctl, 0x1 << AXI0_ADDRESS_RANGE_ENABLE); + setbits_le32(DENALI_CTL_208 + ctl, + 0x1 << PORT_ADDR_PROTECTION_EN_OFFSET); +} + +static void ddr_start(volatile u32 *ctl, u32 *physical_filter_ctrl, u64 ddr_end) +{ + int val; + + volatile u64 *filterreg = (volatile u64 *)physical_filter_ctrl; + + setbits_le32(DENALI_CTL_0 + ctl, 0x1); + + do { + val = readl(DENALI_CTL_132 + ctl) & + (1 << MC_INIT_COMPLETE_OFFSET); + } while (val == 0); + + /* Disable the BusBlocker in front of the controller AXI slave ports */ + filterreg[0] = 0x0f00000000000000UL | (ddr_end >> 2); +} + +static void check_errata(u32 regbase, u32 updownreg) +{ + /* return bitmask of failed lanes */ + u64 fails = 0; + u32 dq = 0; + u32 down, up; + u8 failc0, failc1; + u32 phy_rx_cal_dqn_0_offset; + + for (u32 bit = 0; bit < 2; bit++) { + if (bit == 0) { + phy_rx_cal_dqn_0_offset = + PHY_RX_CAL_DQ0_0_OFFSET; + } else { + phy_rx_cal_dqn_0_offset = + PHY_RX_CAL_DQ1_0_OFFSET; + } + + down = (updownreg >> + phy_rx_cal_dqn_0_offset) & 0x3F; + up = (updownreg >> + (phy_rx_cal_dqn_0_offset + 6)) & + 0x3F; + + failc0 = ((down == 0) && (up == 0x3F)); + failc1 = ((up == 0) && (down == 0x3F)); + + /* print error message on failure */ + if (failc0 || failc1) { + if (fails == 0) + printf("DDR error in fixing up\n"); + + fails |= (1 << dq); + + char slicelsc = '0'; + char slicemsc = '0'; + + slicelsc += (dq % 10); + slicemsc += (dq / 10); + printf("S "); + printf("%c", slicemsc); + printf("%c", slicelsc); + + if (failc0) + printf("U"); + else + printf("D"); + + printf("\n"); + } + dq++; + } +} + +static u64 ddr_phy_fixup(volatile u32 *ddrphyreg) +{ + u32 slicebase = 0; + + /* check errata condition */ + for (u32 slice = 0; slice < 8; slice++) { + u32 regbase = slicebase + 34; + + for (u32 reg = 0; reg < 4; reg++) { + u32 updownreg = readl(regbase + reg + ddrphyreg); + + check_errata(regbase, updownreg); + } + slicebase += 128; + } + + return(0); +} + +static u32 ddr_getdramclass(volatile u32 *ctl) +{ + u32 reg = readl(DENALI_CTL_0 + ctl); + + return ((reg >> DRAM_CLASS_OFFSET) & 0xF); +} + +static int fu540_ddr_setup(struct udevice *dev) +{ + struct ddr_info *priv = dev_get_priv(dev); + struct sifive_dmc_plat *plat = dev_get_platdata(dev); + struct fu540_sdram_params *params = &plat->sdram_params; + + int ret, i; + u32 physet; + const u64 ddr_size = DDR_MEM_SIZE; + const u64 ddr_end = PAYLOAD_DEST + ddr_size; + + volatile u32 *denali_ctl = &priv->ctl->denali_ctl[0]; + volatile u32 *denali_phy = &priv->phy->denali_phy[0]; + + ret = dev_read_u32_array(dev, "sifive,sdram-params", + (u32 *)&plat->sdram_params, + sizeof(plat->sdram_params) / sizeof(u32)); + if (ret) { + printf("%s: Cannot read sifive,sdram-params %d\n", + __func__, ret); + return ret; + } + + sdram_copy_to_reg(&priv->ctl->denali_ctl[0], + ¶ms->pctl_regs.denali_ctl[0], + sizeof(struct fu540_ddrctl)); + + /* phy reset */ + for (i = DENALI_PHY_1152; i <= DENALI_PHY_1214; i++) { + physet = params->phy_regs.denali_phy[i]; + priv->phy->denali_phy[i] = physet; + } + + for (i = 0; i < DENALI_PHY_1152; i++) { + physet = params->phy_regs.denali_phy[i]; + priv->phy->denali_phy[i] = physet; + } + + /* Disable read interleave DENALI_CTL_120 */ + setbits_le32(DENALI_CTL_120 + denali_ctl, + 1 << DISABLE_RD_INTERLEAVE_OFFSET); + + /* Disable optimal read/modify/write logic DENALI_CTL_21 */ + clrbits_le32(DENALI_CTL_21 + denali_ctl, 1 << OPTIMAL_RMODW_EN_OFFSET); + + /* Enable write Leveling DENALI_CTL_170 */ + setbits_le32(DENALI_CTL_170 + denali_ctl, (1 << WRLVL_EN_OFFSET) + | (1 << DFI_PHY_WRLELV_MODE_OFFSET)); + + /* Enable read leveling DENALI_CTL_181 and DENALI_CTL_260 */ + setbits_le32(DENALI_CTL_181 + denali_ctl, + 1 << DFI_PHY_RDLVL_MODE_OFFSET); + setbits_le32(DENALI_CTL_260 + denali_ctl, 1 << RDLVL_EN_OFFSET); + + /* Enable read leveling gate DENALI_CTL_260 and DENALI_CTL_182 */ + setbits_le32(DENALI_CTL_260 + denali_ctl, 1 << RDLVL_GATE_EN_OFFSET); + setbits_le32(DENALI_CTL_182 + denali_ctl, + 1 << DFI_PHY_RDLVL_GATE_MODE_OFFSET); + + if (ddr_getdramclass(denali_ctl) == DRAM_CLASS_DDR4) { + /* Enable vref training DENALI_CTL_184 */ + setbits_le32(DENALI_CTL_184 + denali_ctl, 1 << VREF_EN_OFFSET); + } + + /* Mask off leveling completion interrupt DENALI_CTL_136 */ + setbits_le32(DENALI_CTL_136 + denali_ctl, + 1 << LEVELING_OPERATION_COMPLETED_OFFSET); + + /* Mask off MC init complete interrupt DENALI_CTL_136 */ + setbits_le32(DENALI_CTL_136 + denali_ctl, 1 << MC_INIT_COMPLETE_OFFSET); + + /* Mask off out of range interrupts DENALI_CTL_136 */ + setbits_le32(DENALI_CTL_136 + denali_ctl, (1 << OUT_OF_RANGE_OFFSET) + | (1 << MULTIPLE_OUT_OF_RANGE_OFFSET)); + + /* set up range protection */ + ddr_setuprangeprotection(denali_ctl, DDR_MEM_SIZE); + + /* Mask off port command error interrupt DENALI_CTL_136 */ + setbits_le32(DENALI_CTL_136 + denali_ctl, + 1 << PORT_COMMAND_CHANNEL_ERROR_OFFSET); + + ddr_start(denali_ctl, priv->physical_filter_ctrl, ddr_end); + + ddr_phy_fixup(denali_phy); + + /* check size */ + priv->info.size = get_ram_size((long *)priv->info.base, + DDR_MEM_SIZE); + + printf("priv->info.size = %lx\n", priv->info.size); + debug("%s : %lx\n", __func__, priv->info.size); + + /* check memory access for all memory */ + + if (priv->info.size != DDR_MEM_SIZE) { + printf("DDR invalid size : 0x%lx, expected 0x%lx\n", + priv->info.size, DDR_MEM_SIZE); + return -EINVAL; + } + + return 0; +} +#endif + +static int fu540_ddr_probe(struct udevice *dev) +{ + struct ddr_info *priv = dev_get_priv(dev); + +#if defined(CONFIG_TPL_BUILD) || \ + (!defined(CONFIG_TPL) && defined(CONFIG_SPL_BUILD)) + struct regmap *map; + int ret; + + debug("FU540 DDR probe\n"); + priv->dev = dev; + + ret = regmap_init_mem(dev_ofnode(dev), &map); + if (ret) + return ret; + + priv->ctl = regmap_get_range(map, 0); + priv->phy = regmap_get_range(map, 1); + priv->physical_filter_ctrl = regmap_get_range(map, 2); + + priv->info.base = CONFIG_SYS_SDRAM_BASE; + + priv->info.size = 0; + return fu540_ddr_setup(dev); +#else + priv->info.base = CONFIG_SYS_SDRAM_BASE; + priv->info.size = DDR_MEM_SIZE; +#endif + return 0; +} + +static int fu540_ddr_get_info(struct udevice *dev, struct ram_info *info) +{ + struct ddr_info *priv = dev_get_priv(dev); + + *info = priv->info; + + return 0; +} + +static struct ram_ops fu540_ddr_ops = { + .get_info = fu540_ddr_get_info, +}; + +static const struct udevice_id fu540_ddr_ids[] = { + { .compatible = "sifive,fu540-c000-ddr" }, + { } +}; + +U_BOOT_DRIVER(fu540_ddr) = { + .name = "fu540_ddr", + .id = UCLASS_RAM, + .of_match = fu540_ddr_ids, + .ops = &fu540_ddr_ops, + .probe = fu540_ddr_probe, + .priv_auto_alloc_size = sizeof(struct ddr_info), +#if defined(CONFIG_TPL_BUILD) || \ + (!defined(CONFIG_TPL) && defined(CONFIG_SPL_BUILD)) + .platdata_auto_alloc_size = sizeof(struct sifive_dmc_plat), +#endif +};

On Sun, Mar 29, 2020 at 10:36 PM Pragnesh Patel pragnesh.patel@sifive.com wrote:
Add driver for fu540 to support ddr initialization in SPL. This driver is based on FSBL (https://github.com/sifive/freedom-u540-c000-bootloader.git)
Signed-off-by: Pragnesh Patel pragnesh.patel@sifive.com
drivers/ram/Kconfig | 7 + drivers/ram/Makefile | 2 + drivers/ram/sifive/Kconfig | 8 + drivers/ram/sifive/Makefile | 6 + drivers/ram/sifive/sdram_fu540.c | 399 +++++++++++++++++++++++++++++++ 5 files changed, 422 insertions(+) create mode 100644 drivers/ram/sifive/Kconfig create mode 100644 drivers/ram/sifive/Makefile create mode 100644 drivers/ram/sifive/sdram_fu540.c
diff --git a/drivers/ram/Kconfig b/drivers/ram/Kconfig index 56fea7c94c..c60c63204c 100644 --- a/drivers/ram/Kconfig +++ b/drivers/ram/Kconfig @@ -73,5 +73,12 @@ config IMXRT_SDRAM to support external memories like sdram, psram & nand. This driver is for the sdram memory interface with the SEMC.
+config SIFIVE_DDR
bool "Enable SiFive DDR support"
depends on RAM
help
Enable support for the internal DDR Memory Controller of SiFive SoCs.
source "drivers/ram/rockchip/Kconfig" source "drivers/ram/stm32mp1/Kconfig" +source "drivers/ram/sifive/Kconfig" diff --git a/drivers/ram/Makefile b/drivers/ram/Makefile index 5c897410c6..12bf61510b 100644 --- a/drivers/ram/Makefile +++ b/drivers/ram/Makefile @@ -17,3 +17,5 @@ obj-$(CONFIG_ARCH_MEDIATEK) += mediatek/ obj-$(CONFIG_K3_J721E_DDRSS) += k3-j721e/
obj-$(CONFIG_IMXRT_SDRAM) += imxrt_sdram.o
+obj-$(CONFIG_SIFIVE_DDR) += sifive/ diff --git a/drivers/ram/sifive/Kconfig b/drivers/ram/sifive/Kconfig new file mode 100644 index 0000000000..b754700db8 --- /dev/null +++ b/drivers/ram/sifive/Kconfig @@ -0,0 +1,8 @@ +config SIFIVE_FU540_DDR
bool "SiFive FU540 DDR driver"
depends on DM && OF_CONTROL
DM is already attached for ram drivers, OF_CONTROL for sifive board. So drop these.
select RAM
select SPL_RAM if SPL
select SIFIVE_DDR
This looks an unconventional way to select the root ram config, try this.
config RAM_SIFIVE bool "Ram drivers support for SiFive SoCs" depends on RAM help Enable support for the internal DDR Memory Controller of SiFive SoCs.
if RAM_SIFIVE
config RAM_SIFIVE_FU540 bool "SiFive FU540 DDR driver" default TARGET_SIFIVE_FU540 help
endif # RAM_SIFIVE
in defconfig or board kconfig
select RAM select SPL_RAM if SPL
help
This enables DDR support for the platforms based on SiFive FU540 SoC.
diff --git a/drivers/ram/sifive/Makefile b/drivers/ram/sifive/Makefile new file mode 100644 index 0000000000..0187805199 --- /dev/null +++ b/drivers/ram/sifive/Makefile @@ -0,0 +1,6 @@ +# SPDX-License-Identifier: GPL-2.0+ +# +# Copyright (c) 2020 SiFive, Inc +#
+obj-$(CONFIG_SIFIVE_FU540_DDR) += sdram_fu540.o diff --git a/drivers/ram/sifive/sdram_fu540.c b/drivers/ram/sifive/sdram_fu540.c new file mode 100644 index 0000000000..6e6c551ced --- /dev/null +++ b/drivers/ram/sifive/sdram_fu540.c @@ -0,0 +1,399 @@ +// SPDX-License-Identifier: GPL-2.0+ OR BSD-3-Clause +/*
- (C) Copyright 2020 SiFive, Inc.
- Authors:
- Pragnesh Patel pragnesh.patel@sifive.com
- */
+#include <common.h> +#include <dm.h> +#include <init.h> +#include <ram.h> +#include <regmap.h> +#include <syscon.h> +#include <asm/io.h>
+#define DENALI_CTL_0 0 +#define DENALI_CTL_21 21 +#define DENALI_CTL_120 120 +#define DENALI_CTL_132 132 +#define DENALI_CTL_136 136 +#define DENALI_CTL_170 170 +#define DENALI_CTL_181 181 +#define DENALI_CTL_182 182 +#define DENALI_CTL_184 184 +#define DENALI_CTL_208 208 +#define DENALI_CTL_209 209 +#define DENALI_CTL_210 210 +#define DENALI_CTL_212 212 +#define DENALI_CTL_214 214 +#define DENALI_CTL_216 216 +#define DENALI_CTL_224 224 +#define DENALI_CTL_225 225 +#define DENALI_CTL_260 260
+#define DENALI_PHY_1152 1152 +#define DENALI_PHY_1214 1214
+#define PAYLOAD_DEST 0x80000000 +#define DDR_MEM_SIZE (8UL * 1024UL * 1024UL * 1024UL)
+#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 +#define PORT_COMMAND_CHANNEL_ERROR_OFFSET 7 +#define MC_INIT_COMPLETE_OFFSET 8 +#define LEVELING_OPERATION_COMPLETED_OFFSET 22 +#define DFI_PHY_WRLELV_MODE_OFFSET 24 +#define DFI_PHY_RDLVL_MODE_OFFSET 24 +#define DFI_PHY_RDLVL_GATE_MODE_OFFSET 0 +#define VREF_EN_OFFSET 24 +#define PORT_ADDR_PROTECTION_EN_OFFSET 0 +#define AXI0_ADDRESS_RANGE_ENABLE 8 +#define AXI0_RANGE_PROT_BITS_0_OFFSET 24 +#define RDLVL_EN_OFFSET 16 +#define RDLVL_GATE_EN_OFFSET 24 +#define WRLVL_EN_OFFSET 0
+#define PHY_RX_CAL_DQ0_0_OFFSET 0 +#define PHY_RX_CAL_DQ1_0_OFFSET 16
+struct fu540_ddrctl {
volatile u32 denali_ctl[265];
+};
+struct fu540_ddrphy {
volatile u32 denali_phy[1215];
+};
+/**
- struct ddr_info
- @dev : pointer for the device
- @info : UCLASS RAM information
- @ctl : DDR controller base address
- @phy : DDR PHY base address
- @ctrl : DDR control base address
- @physical_filter_ctrl : DDR physical filter control base address
- */
+struct ddr_info {
struct udevice *dev;
struct ram_info info;
struct fu540_ddrctl *ctl;
struct fu540_ddrphy *phy;
u32 *physical_filter_ctrl;
+};
+#if defined(CONFIG_TPL_BUILD) || \
(!defined(CONFIG_TPL) && defined(CONFIG_SPL_BUILD))
+struct fu540_sdram_params {
struct fu540_ddrctl pctl_regs;
struct fu540_ddrphy phy_regs;
+};
+struct sifive_dmc_plat { +#if CONFIG_IS_ENABLED(OF_PLATDATA)
struct dtd_sifive_fu540_dmc dtplat;
+#else
struct fu540_sdram_params sdram_params;
+#endif +};
+/* n: Unit bytes */ +static void sdram_copy_to_reg(volatile u32 *dest,
volatile u32 *src, u32 n)
+{
int i;
for (i = 0; i < n / sizeof(u32); i++) {
writel(*src, dest);
src++;
dest++;
}
+}
Can you push to the common code area, there are some other drivers using this similar.
+static void ddr_setuprangeprotection(volatile u32 *ctl, u64 end_addr) +{
u32 end_addr_16kblocks = ((end_addr >> 14) & 0x7FFFFF) - 1;
writel(0x0, DENALI_CTL_209 + ctl);
writel(end_addr_16kblocks, DENALI_CTL_210 + ctl);
writel(0x0, DENALI_CTL_212 + ctl);
writel(0x0, DENALI_CTL_214 + ctl);
writel(0x0, DENALI_CTL_216 + ctl);
setbits_le32(DENALI_CTL_224 + ctl,
0x3 << AXI0_RANGE_PROT_BITS_0_OFFSET);
writel(0xFFFFFFFF, DENALI_CTL_225 + ctl);
setbits_le32(DENALI_CTL_208 + ctl, 0x1 << AXI0_ADDRESS_RANGE_ENABLE);
setbits_le32(DENALI_CTL_208 + ctl,
0x1 << PORT_ADDR_PROTECTION_EN_OFFSET);
Any macros for these magic numbers., at least for what you know of.
+}
+static void ddr_start(volatile u32 *ctl, u32 *physical_filter_ctrl, u64 ddr_end) +{
int val;
volatile u64 *filterreg = (volatile u64 *)physical_filter_ctrl;
setbits_le32(DENALI_CTL_0 + ctl, 0x1);
do {
val = readl(DENALI_CTL_132 + ctl) &
(1 << MC_INIT_COMPLETE_OFFSET);
} while (val == 0);
/* Disable the BusBlocker in front of the controller AXI slave ports */
filterreg[0] = 0x0f00000000000000UL | (ddr_end >> 2);
ditto.
+}
+static void check_errata(u32 regbase, u32 updownreg) +{
/* return bitmask of failed lanes */
unconventional comment at beginning of function.
u64 fails = 0;
u32 dq = 0;
u32 down, up;
u8 failc0, failc1;
u32 phy_rx_cal_dqn_0_offset;
for (u32 bit = 0; bit < 2; bit++) {
if (bit == 0) {
phy_rx_cal_dqn_0_offset =
PHY_RX_CAL_DQ0_0_OFFSET;
} else {
phy_rx_cal_dqn_0_offset =
PHY_RX_CAL_DQ1_0_OFFSET;
}
down = (updownreg >>
phy_rx_cal_dqn_0_offset) & 0x3F;
up = (updownreg >>
(phy_rx_cal_dqn_0_offset + 6)) &
0x3F;
failc0 = ((down == 0) && (up == 0x3F));
failc1 = ((up == 0) && (down == 0x3F));
magic numbers?
/* print error message on failure */
if (failc0 || failc1) {
if (fails == 0)
printf("DDR error in fixing up\n");
fails |= (1 << dq);
char slicelsc = '0';
char slicemsc = '0';
slicelsc += (dq % 10);
slicemsc += (dq / 10);
printf("S ");
printf("%c", slicemsc);
printf("%c", slicelsc);
if (failc0)
printf("U");
else
printf("D");
printf("\n");
}
dq++;
}
+}
+static u64 ddr_phy_fixup(volatile u32 *ddrphyreg) +{
u32 slicebase = 0;
/* check errata condition */
for (u32 slice = 0; slice < 8; slice++) {
u32 regbase = slicebase + 34;
for (u32 reg = 0; reg < 4; reg++) {
u32 updownreg = readl(regbase + reg + ddrphyreg);
check_errata(regbase, updownreg);
}
slicebase += 128;
}
return(0);
+}
+static u32 ddr_getdramclass(volatile u32 *ctl) +{
u32 reg = readl(DENALI_CTL_0 + ctl);
return ((reg >> DRAM_CLASS_OFFSET) & 0xF);
ditto
+}
+static int fu540_ddr_setup(struct udevice *dev) +{
struct ddr_info *priv = dev_get_priv(dev);
struct sifive_dmc_plat *plat = dev_get_platdata(dev);
struct fu540_sdram_params *params = &plat->sdram_params;
int ret, i;
u32 physet;
const u64 ddr_size = DDR_MEM_SIZE;
const u64 ddr_end = PAYLOAD_DEST + ddr_size;
volatile u32 *denali_ctl = &priv->ctl->denali_ctl[0];
volatile u32 *denali_phy = &priv->phy->denali_phy[0];
drop the above spaces.
ret = dev_read_u32_array(dev, "sifive,sdram-params",
(u32 *)&plat->sdram_params,
sizeof(plat->sdram_params) / sizeof(u32));
if (ret) {
printf("%s: Cannot read sifive,sdram-params %d\n",
__func__, ret);
return ret;
}
sdram_copy_to_reg(&priv->ctl->denali_ctl[0],
¶ms->pctl_regs.denali_ctl[0],
sizeof(struct fu540_ddrctl));
/* phy reset */
for (i = DENALI_PHY_1152; i <= DENALI_PHY_1214; i++) {
physet = params->phy_regs.denali_phy[i];
priv->phy->denali_phy[i] = physet;
}
for (i = 0; i < DENALI_PHY_1152; i++) {
physet = params->phy_regs.denali_phy[i];
priv->phy->denali_phy[i] = physet;
}
/* Disable read interleave DENALI_CTL_120 */
setbits_le32(DENALI_CTL_120 + denali_ctl,
1 << DISABLE_RD_INTERLEAVE_OFFSET);
/* Disable optimal read/modify/write logic DENALI_CTL_21 */
clrbits_le32(DENALI_CTL_21 + denali_ctl, 1 << OPTIMAL_RMODW_EN_OFFSET);
/* Enable write Leveling DENALI_CTL_170 */
setbits_le32(DENALI_CTL_170 + denali_ctl, (1 << WRLVL_EN_OFFSET)
| (1 << DFI_PHY_WRLELV_MODE_OFFSET));
/* Enable read leveling DENALI_CTL_181 and DENALI_CTL_260 */
setbits_le32(DENALI_CTL_181 + denali_ctl,
1 << DFI_PHY_RDLVL_MODE_OFFSET);
setbits_le32(DENALI_CTL_260 + denali_ctl, 1 << RDLVL_EN_OFFSET);
/* Enable read leveling gate DENALI_CTL_260 and DENALI_CTL_182 */
setbits_le32(DENALI_CTL_260 + denali_ctl, 1 << RDLVL_GATE_EN_OFFSET);
setbits_le32(DENALI_CTL_182 + denali_ctl,
1 << DFI_PHY_RDLVL_GATE_MODE_OFFSET);
if (ddr_getdramclass(denali_ctl) == DRAM_CLASS_DDR4) {
/* Enable vref training DENALI_CTL_184 */
setbits_le32(DENALI_CTL_184 + denali_ctl, 1 << VREF_EN_OFFSET);
}
/* Mask off leveling completion interrupt DENALI_CTL_136 */
setbits_le32(DENALI_CTL_136 + denali_ctl,
1 << LEVELING_OPERATION_COMPLETED_OFFSET);
/* Mask off MC init complete interrupt DENALI_CTL_136 */
setbits_le32(DENALI_CTL_136 + denali_ctl, 1 << MC_INIT_COMPLETE_OFFSET);
/* Mask off out of range interrupts DENALI_CTL_136 */
setbits_le32(DENALI_CTL_136 + denali_ctl, (1 << OUT_OF_RANGE_OFFSET)
| (1 << MULTIPLE_OUT_OF_RANGE_OFFSET));
/* set up range protection */
ddr_setuprangeprotection(denali_ctl, DDR_MEM_SIZE);
/* Mask off port command error interrupt DENALI_CTL_136 */
setbits_le32(DENALI_CTL_136 + denali_ctl,
1 << PORT_COMMAND_CHANNEL_ERROR_OFFSET);
ddr_start(denali_ctl, priv->physical_filter_ctrl, ddr_end);
ddr_phy_fixup(denali_phy);
/* check size */
priv->info.size = get_ram_size((long *)priv->info.base,
DDR_MEM_SIZE);
printf("priv->info.size = %lx\n", priv->info.size);
debug("%s : %lx\n", __func__, priv->info.size);
/* check memory access for all memory */
no space.
Jagan.

Hi Jagan,
-----Original Message----- From: Jagan Teki jagan@amarulasolutions.com Sent: 07 April 2020 00:58 To: Pragnesh Patel pragnesh.patel@sifive.com Cc: U-Boot-Denx u-boot@lists.denx.de; Atish Patra atish.patra@wdc.com; palmerdabbelt@google.com; Bin Meng bmeng.cn@gmail.com; Paul Walmsley paul.walmsley@sifive.com; Troy Benjegerdes troy.benjegerdes@sifive.com; Anup Patel anup.patel@wdc.com; Sagar Kadam sagar.kadam@sifive.com; Rick Chen rick@andestech.com; Kever Yang kever.yang@rock-chips.com; Lokesh Vutla lokeshvutla@ti.com; YouMin Chen cym@rock-chips.com; Giulio Benetti giulio.benetti@benettiengineering.com; Kevin Scholz <k- scholz@ti.com> Subject: Re: [PATCH v6 06/17] sifive: fu540: add ddr driver
[External Email] Do not click links or attachments unless you recognize the sender and know the content is safe
On Sun, Mar 29, 2020 at 10:36 PM Pragnesh Patel pragnesh.patel@sifive.com wrote:
Add driver for fu540 to support ddr initialization in SPL. This driver is based on FSBL (https://github.com/sifive/freedom-u540-c000-bootloader.git)
Signed-off-by: Pragnesh Patel pragnesh.patel@sifive.com
drivers/ram/Kconfig | 7 + drivers/ram/Makefile | 2 + drivers/ram/sifive/Kconfig | 8 + drivers/ram/sifive/Makefile | 6 + drivers/ram/sifive/sdram_fu540.c | 399 +++++++++++++++++++++++++++++++ 5 files changed, 422 insertions(+) create mode 100644 drivers/ram/sifive/Kconfig create mode 100644 drivers/ram/sifive/Makefile create mode 100644 drivers/ram/sifive/sdram_fu540.c
diff --git a/drivers/ram/Kconfig b/drivers/ram/Kconfig index 56fea7c94c..c60c63204c 100644 --- a/drivers/ram/Kconfig +++ b/drivers/ram/Kconfig @@ -73,5 +73,12 @@ config IMXRT_SDRAM to support external memories like sdram, psram & nand. This driver is for the sdram memory interface with the SEMC.
+config SIFIVE_DDR
bool "Enable SiFive DDR support"
depends on RAM
help
Enable support for the internal DDR Memory Controller of SiFive SoCs.
source "drivers/ram/rockchip/Kconfig" source "drivers/ram/stm32mp1/Kconfig" +source "drivers/ram/sifive/Kconfig" diff --git a/drivers/ram/Makefile b/drivers/ram/Makefile index 5c897410c6..12bf61510b 100644 --- a/drivers/ram/Makefile +++ b/drivers/ram/Makefile @@ -17,3 +17,5 @@ obj-$(CONFIG_ARCH_MEDIATEK) += mediatek/ obj-$(CONFIG_K3_J721E_DDRSS) += k3-j721e/
obj-$(CONFIG_IMXRT_SDRAM) += imxrt_sdram.o
+obj-$(CONFIG_SIFIVE_DDR) += sifive/ diff --git a/drivers/ram/sifive/Kconfig b/drivers/ram/sifive/Kconfig new file mode 100644 index 0000000000..b754700db8 --- /dev/null +++ b/drivers/ram/sifive/Kconfig @@ -0,0 +1,8 @@ +config SIFIVE_FU540_DDR
bool "SiFive FU540 DDR driver"
depends on DM && OF_CONTROL
DM is already attached for ram drivers, OF_CONTROL for sifive board. So drop these.
I will remove the DM but I think OF_CONTROL is necessary for RAM driver though it is selected for SiFive board.
select RAM
select SPL_RAM if SPL
select SIFIVE_DDR
This looks an unconventional way to select the root ram config, try this.
config RAM_SIFIVE bool "Ram drivers support for SiFive SoCs" depends on RAM help Enable support for the internal DDR Memory Controller of SiFive SoCs.
if RAM_SIFIVE
config RAM_SIFIVE_FU540 bool "SiFive FU540 DDR driver" default TARGET_SIFIVE_FU540 help
endif # RAM_SIFIVE
in defconfig or board kconfig
select RAM select SPL_RAM if SPL
Thanks for the correction, Will update in v7.
help
This enables DDR support for the platforms based on SiFive FU540
SoC.
diff --git a/drivers/ram/sifive/Makefile b/drivers/ram/sifive/Makefile new file mode 100644 index 0000000000..0187805199 --- /dev/null +++ b/drivers/ram/sifive/Makefile @@ -0,0 +1,6 @@ +# SPDX-License-Identifier: GPL-2.0+ +# +# Copyright (c) 2020 SiFive, Inc +#
+obj-$(CONFIG_SIFIVE_FU540_DDR) += sdram_fu540.o diff --git a/drivers/ram/sifive/sdram_fu540.c b/drivers/ram/sifive/sdram_fu540.c new file mode 100644 index 0000000000..6e6c551ced --- /dev/null +++ b/drivers/ram/sifive/sdram_fu540.c @@ -0,0 +1,399 @@ +// SPDX-License-Identifier: GPL-2.0+ OR BSD-3-Clause +/*
- (C) Copyright 2020 SiFive, Inc.
- Authors:
- Pragnesh Patel pragnesh.patel@sifive.com
- */
+#include <common.h> +#include <dm.h> +#include <init.h> +#include <ram.h> +#include <regmap.h> +#include <syscon.h> +#include <asm/io.h>
+#define DENALI_CTL_0 0 +#define DENALI_CTL_21 21 +#define DENALI_CTL_120 120 +#define DENALI_CTL_132 132 +#define DENALI_CTL_136 136 +#define DENALI_CTL_170 170 +#define DENALI_CTL_181 181 +#define DENALI_CTL_182 182 +#define DENALI_CTL_184 184 +#define DENALI_CTL_208 208 +#define DENALI_CTL_209 209 +#define DENALI_CTL_210 210 +#define DENALI_CTL_212 212 +#define DENALI_CTL_214 214 +#define DENALI_CTL_216 216 +#define DENALI_CTL_224 224 +#define DENALI_CTL_225 225 +#define DENALI_CTL_260 260
+#define DENALI_PHY_1152 1152 +#define DENALI_PHY_1214 1214
+#define PAYLOAD_DEST 0x80000000 +#define DDR_MEM_SIZE (8UL * 1024UL * 1024UL * 1024UL)
+#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 +#define PORT_COMMAND_CHANNEL_ERROR_OFFSET 7 +#define MC_INIT_COMPLETE_OFFSET 8 +#define LEVELING_OPERATION_COMPLETED_OFFSET 22 +#define DFI_PHY_WRLELV_MODE_OFFSET 24 +#define DFI_PHY_RDLVL_MODE_OFFSET 24 +#define DFI_PHY_RDLVL_GATE_MODE_OFFSET 0 +#define VREF_EN_OFFSET 24 +#define PORT_ADDR_PROTECTION_EN_OFFSET 0 +#define AXI0_ADDRESS_RANGE_ENABLE 8 +#define AXI0_RANGE_PROT_BITS_0_OFFSET 24 +#define RDLVL_EN_OFFSET 16 +#define RDLVL_GATE_EN_OFFSET 24 +#define WRLVL_EN_OFFSET 0
+#define PHY_RX_CAL_DQ0_0_OFFSET 0 +#define PHY_RX_CAL_DQ1_0_OFFSET 16
+struct fu540_ddrctl {
volatile u32 denali_ctl[265];
+};
+struct fu540_ddrphy {
volatile u32 denali_phy[1215]; };
+/**
- struct ddr_info
- @dev : pointer for the device
- @info : UCLASS RAM information
- @ctl : DDR controller base address
- @phy : DDR PHY base address
- @ctrl : DDR control base address
- @physical_filter_ctrl : DDR physical filter control base address
- */
+struct ddr_info {
struct udevice *dev;
struct ram_info info;
struct fu540_ddrctl *ctl;
struct fu540_ddrphy *phy;
u32 *physical_filter_ctrl;
+};
+#if defined(CONFIG_TPL_BUILD) || \
(!defined(CONFIG_TPL) && defined(CONFIG_SPL_BUILD))
+struct fu540_sdram_params {
struct fu540_ddrctl pctl_regs;
struct fu540_ddrphy phy_regs;
+};
+struct sifive_dmc_plat { +#if CONFIG_IS_ENABLED(OF_PLATDATA)
struct dtd_sifive_fu540_dmc dtplat; #else
struct fu540_sdram_params sdram_params; #endif };
+/* n: Unit bytes */ +static void sdram_copy_to_reg(volatile u32 *dest,
volatile u32 *src, u32 n) {
int i;
for (i = 0; i < n / sizeof(u32); i++) {
writel(*src, dest);
src++;
dest++;
}
+}
Can you push to the common code area, there are some other drivers using this similar.
Where exactly in common ?
+static void ddr_setuprangeprotection(volatile u32 *ctl, u64 end_addr) +{
u32 end_addr_16kblocks = ((end_addr >> 14) & 0x7FFFFF) - 1;
writel(0x0, DENALI_CTL_209 + ctl);
writel(end_addr_16kblocks, DENALI_CTL_210 + ctl);
writel(0x0, DENALI_CTL_212 + ctl);
writel(0x0, DENALI_CTL_214 + ctl);
writel(0x0, DENALI_CTL_216 + ctl);
setbits_le32(DENALI_CTL_224 + ctl,
0x3 << AXI0_RANGE_PROT_BITS_0_OFFSET);
writel(0xFFFFFFFF, DENALI_CTL_225 + ctl);
setbits_le32(DENALI_CTL_208 + ctl, 0x1 <<
AXI0_ADDRESS_RANGE_ENABLE);
setbits_le32(DENALI_CTL_208 + ctl,
0x1 << PORT_ADDR_PROTECTION_EN_OFFSET);
Any macros for these magic numbers., at least for what you know of.
This is something copied from FSBL. Right now I don't have any idea on this. Due to NDA issues, we can not open source some information.
+}
+static void ddr_start(volatile u32 *ctl, u32 *physical_filter_ctrl, +u64 ddr_end) {
int val;
volatile u64 *filterreg = (volatile u64
- *)physical_filter_ctrl;
setbits_le32(DENALI_CTL_0 + ctl, 0x1);
do {
val = readl(DENALI_CTL_132 + ctl) &
(1 << MC_INIT_COMPLETE_OFFSET);
} while (val == 0);
/* Disable the BusBlocker in front of the controller AXI slave ports */
filterreg[0] = 0x0f00000000000000UL | (ddr_end >> 2);
ditto.
As written above.
+}
+static void check_errata(u32 regbase, u32 updownreg) {
/* return bitmask of failed lanes */
unconventional comment at beginning of function.
Will remove.
u64 fails = 0;
u32 dq = 0;
u32 down, up;
u8 failc0, failc1;
u32 phy_rx_cal_dqn_0_offset;
for (u32 bit = 0; bit < 2; bit++) {
if (bit == 0) {
phy_rx_cal_dqn_0_offset =
PHY_RX_CAL_DQ0_0_OFFSET;
} else {
phy_rx_cal_dqn_0_offset =
PHY_RX_CAL_DQ1_0_OFFSET;
}
down = (updownreg >>
phy_rx_cal_dqn_0_offset) & 0x3F;
up = (updownreg >>
(phy_rx_cal_dqn_0_offset + 6)) &
0x3F;
failc0 = ((down == 0) && (up == 0x3F));
failc1 = ((up == 0) && (down == 0x3F));
magic numbers?
This is something copied from FSBL.
/* print error message on failure */
if (failc0 || failc1) {
if (fails == 0)
printf("DDR error in fixing up\n");
fails |= (1 << dq);
char slicelsc = '0';
char slicemsc = '0';
slicelsc += (dq % 10);
slicemsc += (dq / 10);
printf("S ");
printf("%c", slicemsc);
printf("%c", slicelsc);
if (failc0)
printf("U");
else
printf("D");
printf("\n");
}
dq++;
}
+}
+static u64 ddr_phy_fixup(volatile u32 *ddrphyreg) {
u32 slicebase = 0;
/* check errata condition */
for (u32 slice = 0; slice < 8; slice++) {
u32 regbase = slicebase + 34;
for (u32 reg = 0; reg < 4; reg++) {
u32 updownreg = readl(regbase + reg +
- ddrphyreg);
check_errata(regbase, updownreg);
}
slicebase += 128;
}
return(0);
+}
+static u32 ddr_getdramclass(volatile u32 *ctl) {
u32 reg = readl(DENALI_CTL_0 + ctl);
return ((reg >> DRAM_CLASS_OFFSET) & 0xF);
ditto
Same as above
+}
+static int fu540_ddr_setup(struct udevice *dev) {
struct ddr_info *priv = dev_get_priv(dev);
struct sifive_dmc_plat *plat = dev_get_platdata(dev);
struct fu540_sdram_params *params = &plat->sdram_params;
int ret, i;
u32 physet;
const u64 ddr_size = DDR_MEM_SIZE;
const u64 ddr_end = PAYLOAD_DEST + ddr_size;
volatile u32 *denali_ctl = &priv->ctl->denali_ctl[0];
volatile u32 *denali_phy = &priv->phy->denali_phy[0];
drop the above spaces.
Will do.
ret = dev_read_u32_array(dev, "sifive,sdram-params",
(u32 *)&plat->sdram_params,
sizeof(plat->sdram_params) / sizeof(u32));
if (ret) {
printf("%s: Cannot read sifive,sdram-params %d\n",
__func__, ret);
return ret;
}
sdram_copy_to_reg(&priv->ctl->denali_ctl[0],
¶ms->pctl_regs.denali_ctl[0],
sizeof(struct fu540_ddrctl));
/* phy reset */
for (i = DENALI_PHY_1152; i <= DENALI_PHY_1214; i++) {
physet = params->phy_regs.denali_phy[i];
priv->phy->denali_phy[i] = physet;
}
for (i = 0; i < DENALI_PHY_1152; i++) {
physet = params->phy_regs.denali_phy[i];
priv->phy->denali_phy[i] = physet;
}
/* Disable read interleave DENALI_CTL_120 */
setbits_le32(DENALI_CTL_120 + denali_ctl,
1 << DISABLE_RD_INTERLEAVE_OFFSET);
/* Disable optimal read/modify/write logic DENALI_CTL_21 */
clrbits_le32(DENALI_CTL_21 + denali_ctl, 1 <<
- OPTIMAL_RMODW_EN_OFFSET);
/* Enable write Leveling DENALI_CTL_170 */
setbits_le32(DENALI_CTL_170 + denali_ctl, (1 << WRLVL_EN_OFFSET)
| (1 << DFI_PHY_WRLELV_MODE_OFFSET));
/* Enable read leveling DENALI_CTL_181 and DENALI_CTL_260 */
setbits_le32(DENALI_CTL_181 + denali_ctl,
1 << DFI_PHY_RDLVL_MODE_OFFSET);
setbits_le32(DENALI_CTL_260 + denali_ctl, 1 <<
- RDLVL_EN_OFFSET);
/* Enable read leveling gate DENALI_CTL_260 and DENALI_CTL_182 */
setbits_le32(DENALI_CTL_260 + denali_ctl, 1 <<
RDLVL_GATE_EN_OFFSET);
setbits_le32(DENALI_CTL_182 + denali_ctl,
1 << DFI_PHY_RDLVL_GATE_MODE_OFFSET);
if (ddr_getdramclass(denali_ctl) == DRAM_CLASS_DDR4) {
/* Enable vref training DENALI_CTL_184 */
setbits_le32(DENALI_CTL_184 + denali_ctl, 1 << VREF_EN_OFFSET);
}
/* Mask off leveling completion interrupt DENALI_CTL_136 */
setbits_le32(DENALI_CTL_136 + denali_ctl,
1 << LEVELING_OPERATION_COMPLETED_OFFSET);
/* Mask off MC init complete interrupt DENALI_CTL_136 */
setbits_le32(DENALI_CTL_136 + denali_ctl, 1 <<
- MC_INIT_COMPLETE_OFFSET);
/* Mask off out of range interrupts DENALI_CTL_136 */
setbits_le32(DENALI_CTL_136 + denali_ctl, (1 <<
OUT_OF_RANGE_OFFSET)
| (1 << MULTIPLE_OUT_OF_RANGE_OFFSET));
/* set up range protection */
ddr_setuprangeprotection(denali_ctl, DDR_MEM_SIZE);
/* Mask off port command error interrupt DENALI_CTL_136 */
setbits_le32(DENALI_CTL_136 + denali_ctl,
1 << PORT_COMMAND_CHANNEL_ERROR_OFFSET);
ddr_start(denali_ctl, priv->physical_filter_ctrl, ddr_end);
ddr_phy_fixup(denali_phy);
/* check size */
priv->info.size = get_ram_size((long *)priv->info.base,
DDR_MEM_SIZE);
printf("priv->info.size = %lx\n", priv->info.size);
debug("%s : %lx\n", __func__, priv->info.size);
/* check memory access for all memory */
no space.
Will update.
Jagan.

Add DDR controller and phy register settings, taken from fsbl (https://github.com/sifive/freedom-u540-c000-bootloader.git)
Signed-off-by: Pragnesh Patel pragnesh.patel@sifive.com --- arch/riscv/dts/fu540-c000-u-boot.dtsi | 7 + ...fu540-hifive-unleashed-a00-sdram-ddr4.dtsi | 1489 +++++++++++++++++ .../dts/hifive-unleashed-a00-u-boot.dtsi | 1 + 3 files changed, 1497 insertions(+) create mode 100644 arch/riscv/dts/fu540-hifive-unleashed-a00-sdram-ddr4.dtsi
diff --git a/arch/riscv/dts/fu540-c000-u-boot.dtsi b/arch/riscv/dts/fu540-c000-u-boot.dtsi index 387b13bdfb..56a45371d4 100644 --- a/arch/riscv/dts/fu540-c000-u-boot.dtsi +++ b/arch/riscv/dts/fu540-c000-u-boot.dtsi @@ -52,6 +52,13 @@ reg = <0x0 0x2000000 0x0 0xc0000>; u-boot,dm-spl; }; + dmc: dmc@100b0000 { + compatible = "sifive,fu540-c000-ddr"; + reg = <0x0 0x100b0000 0x0 0x0800 + 0x0 0x100b2000 0x0 0x2000 + 0x0 0x100b8000 0x0 0x0fff>; + u-boot,dm-spl; + }; }; };
diff --git a/arch/riscv/dts/fu540-hifive-unleashed-a00-sdram-ddr4.dtsi b/arch/riscv/dts/fu540-hifive-unleashed-a00-sdram-ddr4.dtsi new file mode 100644 index 0000000000..370c53800d --- /dev/null +++ b/arch/riscv/dts/fu540-hifive-unleashed-a00-sdram-ddr4.dtsi @@ -0,0 +1,1489 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * (C) Copyright 2020 SiFive, Inc + */ + +&dmc { + sifive,sdram-params = < + 0x00000a00 /* DENALI_CTL_00_DATA */ + 0x00000000 /* DENALI_CTL_01_DATA */ + 0x00000000 /* DENALI_CTL_02_DATA */ + 0x00000000 /* DENALI_CTL_03_DATA */ + 0x00000000 /* DENALI_CTL_04_DATA */ + 0x00000000 /* DENALI_CTL_05_DATA */ + 0x0000000a /* DENALI_CTL_06_DATA */ + 0x0002d362 /* DENALI_CTL_07_DATA */ + 0x00071073 /* DENALI_CTL_08_DATA */ + 0x0a1c0255 /* DENALI_CTL_09_DATA */ + 0x1c1c0400 /* DENALI_CTL_10_DATA */ + 0x0404990b /* DENALI_CTL_11_DATA */ + 0x2b050405 /* DENALI_CTL_12_DATA */ + 0x0e0c081e /* DENALI_CTL_13_DATA */ + 0x08090914 /* DENALI_CTL_14_DATA */ + 0x00fde718 /* DENALI_CTL_15_DATA */ + 0x00180a05 /* DENALI_CTL_16_DATA */ + 0x008b130e /* DENALI_CTL_17_DATA */ + 0x01000118 /* DENALI_CTL_18_DATA */ + 0x0e032101 /* DENALI_CTL_19_DATA */ + 0x00000000 /* DENALI_CTL_20_DATA */ + 0x00000101 /* DENALI_CTL_21_DATA */ + 0x00000000 /* DENALI_CTL_22_DATA */ + 0x0a000000 /* DENALI_CTL_23_DATA */ + 0x00000000 /* DENALI_CTL_24_DATA */ + 0x01450100 /* DENALI_CTL_25_DATA */ + 0x00001c36 /* DENALI_CTL_26_DATA */ + 0x00000005 /* DENALI_CTL_27_DATA */ + 0x00170006 /* DENALI_CTL_28_DATA */ + 0x014e0300 /* DENALI_CTL_29_DATA */ + 0x03010000 /* DENALI_CTL_30_DATA */ + 0x000a0e00 /* DENALI_CTL_31_DATA */ + 0x04030200 /* DENALI_CTL_32_DATA */ + 0x0000031f /* DENALI_CTL_33_DATA */ + 0x00070004 /* DENALI_CTL_34_DATA */ + 0x00000000 /* DENALI_CTL_35_DATA */ + 0x00000000 /* DENALI_CTL_36_DATA */ + 0x00000000 /* DENALI_CTL_37_DATA */ + 0x00000000 /* DENALI_CTL_38_DATA */ + 0x00000000 /* DENALI_CTL_39_DATA */ + 0x00000000 /* DENALI_CTL_40_DATA */ + 0x00000000 /* DENALI_CTL_41_DATA */ + 0x00000000 /* DENALI_CTL_42_DATA */ + 0x00000000 /* DENALI_CTL_43_DATA */ + 0x00000000 /* DENALI_CTL_44_DATA */ + 0x00000000 /* DENALI_CTL_45_DATA */ + 0x00000000 /* DENALI_CTL_46_DATA */ + 0x00000000 /* DENALI_CTL_47_DATA */ + 0x00000000 /* DENALI_CTL_48_DATA */ + 0x00000000 /* DENALI_CTL_49_DATA */ + 0x00000000 /* DENALI_CTL_50_DATA */ + 0x00000000 /* DENALI_CTL_51_DATA */ + 0x00000000 /* DENALI_CTL_52_DATA */ + 0x00000000 /* DENALI_CTL_53_DATA */ + 0x00000000 /* DENALI_CTL_54_DATA */ + 0x00000000 /* DENALI_CTL_55_DATA */ + 0x00000000 /* DENALI_CTL_56_DATA */ + 0x00000000 /* DENALI_CTL_57_DATA */ + 0x00000000 /* DENALI_CTL_58_DATA */ + 0x00000000 /* DENALI_CTL_59_DATA */ + 0x00000424 /* DENALI_CTL_60_DATA */ + 0x00000201 /* DENALI_CTL_61_DATA */ + 0x00001008 /* DENALI_CTL_62_DATA */ + 0x00000000 /* DENALI_CTL_63_DATA */ + 0x00000200 /* DENALI_CTL_64_DATA */ + 0x00000000 /* DENALI_CTL_65_DATA */ + 0x00000481 /* DENALI_CTL_66_DATA */ + 0x00000400 /* DENALI_CTL_67_DATA */ + 0x00000424 /* DENALI_CTL_68_DATA */ + 0x00000201 /* DENALI_CTL_69_DATA */ + 0x00001008 /* DENALI_CTL_70_DATA */ + 0x00000000 /* DENALI_CTL_71_DATA */ + 0x00000200 /* DENALI_CTL_72_DATA */ + 0x00000000 /* DENALI_CTL_73_DATA */ + 0x00000481 /* DENALI_CTL_74_DATA */ + 0x00000400 /* DENALI_CTL_75_DATA */ + 0x01010000 /* DENALI_CTL_76_DATA */ + 0x00000000 /* DENALI_CTL_77_DATA */ + 0x00000000 /* DENALI_CTL_78_DATA */ + 0x00000000 /* DENALI_CTL_79_DATA */ + 0x00000000 /* DENALI_CTL_80_DATA */ + 0x00000000 /* DENALI_CTL_81_DATA */ + 0x00000000 /* DENALI_CTL_82_DATA */ + 0x00000000 /* DENALI_CTL_83_DATA */ + 0x00000000 /* DENALI_CTL_84_DATA */ + 0x00000000 /* DENALI_CTL_85_DATA */ + 0x00000000 /* DENALI_CTL_86_DATA */ + 0x00000000 /* DENALI_CTL_87_DATA */ + 0x00000000 /* DENALI_CTL_88_DATA */ + 0x00000000 /* DENALI_CTL_89_DATA */ + 0x00000000 /* DENALI_CTL_90_DATA */ + 0x00000000 /* DENALI_CTL_91_DATA */ + 0x00000000 /* DENALI_CTL_92_DATA */ + 0x00000000 /* DENALI_CTL_93_DATA */ + 0x00000000 /* DENALI_CTL_94_DATA */ + 0x00000000 /* DENALI_CTL_95_DATA */ + 0x00000000 /* DENALI_CTL_96_DATA */ + 0x00000000 /* DENALI_CTL_97_DATA */ + 0x00000000 /* DENALI_CTL_98_DATA */ + 0x00000000 /* DENALI_CTL_99_DATA */ + 0x00000000 /* DENALI_CTL_100_DATA */ + 0x00000000 /* DENALI_CTL_101_DATA */ + 0x00000000 /* DENALI_CTL_102_DATA */ + 0x00000000 /* DENALI_CTL_103_DATA */ + 0x00000000 /* DENALI_CTL_104_DATA */ + 0x00000003 /* DENALI_CTL_105_DATA */ + 0x00000000 /* DENALI_CTL_106_DATA */ + 0x00000000 /* DENALI_CTL_107_DATA */ + 0x00000000 /* DENALI_CTL_108_DATA */ + 0x00000000 /* DENALI_CTL_109_DATA */ + 0x01000000 /* DENALI_CTL_110_DATA */ + 0x00040000 /* DENALI_CTL_111_DATA */ + 0x00800200 /* DENALI_CTL_112_DATA */ + 0x00000200 /* DENALI_CTL_113_DATA */ + 0x00000040 /* DENALI_CTL_114_DATA */ + 0x01000100 /* DENALI_CTL_115_DATA */ + 0x0a000002 /* DENALI_CTL_116_DATA */ + 0x0101ffff /* DENALI_CTL_117_DATA */ + 0x01010101 /* DENALI_CTL_118_DATA */ + 0x01010101 /* DENALI_CTL_119_DATA */ + 0x0000010b /* DENALI_CTL_120_DATA */ + 0x00000c01 /* DENALI_CTL_121_DATA */ + 0x00000000 /* DENALI_CTL_122_DATA */ + 0x00000000 /* DENALI_CTL_123_DATA */ + 0x00000000 /* DENALI_CTL_124_DATA */ + 0x00000000 /* DENALI_CTL_125_DATA */ + 0x00030300 /* DENALI_CTL_126_DATA */ + 0x00000000 /* DENALI_CTL_127_DATA */ + 0x00010001 /* DENALI_CTL_128_DATA */ + 0x00000000 /* DENALI_CTL_129_DATA */ + 0x00000000 /* DENALI_CTL_130_DATA */ + 0x00000000 /* DENALI_CTL_131_DATA */ + 0x00000000 /* DENALI_CTL_132_DATA */ + 0x00000000 /* DENALI_CTL_133_DATA */ + 0x00000000 /* DENALI_CTL_134_DATA */ + 0x00000000 /* DENALI_CTL_135_DATA */ + 0x00000000 /* DENALI_CTL_136_DATA */ + 0x00000000 /* DENALI_CTL_137_DATA */ + 0x00000000 /* DENALI_CTL_138_DATA */ + 0x00000000 /* DENALI_CTL_139_DATA */ + 0x00000000 /* DENALI_CTL_140_DATA */ + 0x00000000 /* DENALI_CTL_141_DATA */ + 0x00000000 /* DENALI_CTL_142_DATA */ + 0x00000000 /* DENALI_CTL_143_DATA */ + 0x00000000 /* DENALI_CTL_144_DATA */ + 0x00000000 /* DENALI_CTL_145_DATA */ + 0x00000000 /* DENALI_CTL_146_DATA */ + 0x00000000 /* DENALI_CTL_147_DATA */ + 0x00000000 /* DENALI_CTL_148_DATA */ + 0x00000000 /* DENALI_CTL_149_DATA */ + 0x00000000 /* DENALI_CTL_150_DATA */ + 0x00000000 /* DENALI_CTL_151_DATA */ + 0x00000000 /* DENALI_CTL_152_DATA */ + 0x00000000 /* DENALI_CTL_153_DATA */ + 0x00000000 /* DENALI_CTL_154_DATA */ + 0x00000000 /* DENALI_CTL_155_DATA */ + 0x00000000 /* DENALI_CTL_156_DATA */ + 0x00000000 /* DENALI_CTL_157_DATA */ + 0x00000000 /* DENALI_CTL_158_DATA */ + 0x00000000 /* DENALI_CTL_159_DATA */ + 0x00000000 /* DENALI_CTL_160_DATA */ + 0x02010102 /* DENALI_CTL_161_DATA */ + 0x0107070d /* DENALI_CTL_162_DATA */ + 0x04040400 /* DENALI_CTL_163_DATA */ + 0x03000503 /* DENALI_CTL_164_DATA */ + 0x00000000 /* DENALI_CTL_165_DATA */ + 0x00000000 /* DENALI_CTL_166_DATA */ + 0x00000000 /* DENALI_CTL_167_DATA */ + 0x00000000 /* DENALI_CTL_168_DATA */ + 0x280d0000 /* DENALI_CTL_169_DATA */ + 0x01000000 /* DENALI_CTL_170_DATA */ + 0x00000000 /* DENALI_CTL_171_DATA */ + 0x00010001 /* DENALI_CTL_172_DATA */ + 0x00000000 /* DENALI_CTL_173_DATA */ + 0x00000000 /* DENALI_CTL_174_DATA */ + 0x00000000 /* DENALI_CTL_175_DATA */ + 0x00000000 /* DENALI_CTL_176_DATA */ + 0x00000000 /* DENALI_CTL_177_DATA */ + 0x00000000 /* DENALI_CTL_178_DATA */ + 0x00000000 /* DENALI_CTL_179_DATA */ + 0x00000000 /* DENALI_CTL_180_DATA */ + 0x01000000 /* DENALI_CTL_181_DATA */ + 0x00000001 /* DENALI_CTL_182_DATA */ + 0x00000100 /* DENALI_CTL_183_DATA */ + 0x00000101 /* DENALI_CTL_184_DATA */ + 0x67676701 /* DENALI_CTL_185_DATA */ + 0x67676767 /* DENALI_CTL_186_DATA */ + 0x67676767 /* DENALI_CTL_187_DATA */ + 0x67676767 /* DENALI_CTL_188_DATA */ + 0x67676767 /* DENALI_CTL_189_DATA */ + 0x67676767 /* DENALI_CTL_190_DATA */ + 0x67676767 /* DENALI_CTL_191_DATA */ + 0x67676767 /* DENALI_CTL_192_DATA */ + 0x67676767 /* DENALI_CTL_193_DATA */ + 0x01000067 /* DENALI_CTL_194_DATA */ + 0x00000001 /* DENALI_CTL_195_DATA */ + 0x00000101 /* DENALI_CTL_196_DATA */ + 0x00000000 /* DENALI_CTL_197_DATA */ + 0x00000000 /* DENALI_CTL_198_DATA */ + 0x00000000 /* DENALI_CTL_199_DATA */ + 0x00000000 /* DENALI_CTL_200_DATA */ + 0x00000000 /* DENALI_CTL_201_DATA */ + 0x00000000 /* DENALI_CTL_202_DATA */ + 0x00000000 /* DENALI_CTL_203_DATA */ + 0x00000000 /* DENALI_CTL_204_DATA */ + 0x00000000 /* DENALI_CTL_205_DATA */ + 0x00000000 /* DENALI_CTL_206_DATA */ + 0x00000000 /* DENALI_CTL_207_DATA */ + 0x00000001 /* DENALI_CTL_208_DATA */ + 0x00000000 /* DENALI_CTL_209_DATA */ + 0x007fffff /* DENALI_CTL_210_DATA */ + 0x00000000 /* DENALI_CTL_211_DATA */ + 0x007fffff /* DENALI_CTL_212_DATA */ + 0x00000000 /* DENALI_CTL_213_DATA */ + 0x007fffff /* DENALI_CTL_214_DATA */ + 0x00000000 /* DENALI_CTL_215_DATA */ + 0x007fffff /* DENALI_CTL_216_DATA */ + 0x00000000 /* DENALI_CTL_217_DATA */ + 0x007fffff /* DENALI_CTL_218_DATA */ + 0x00000000 /* DENALI_CTL_219_DATA */ + 0x007fffff /* DENALI_CTL_220_DATA */ + 0x00000000 /* DENALI_CTL_221_DATA */ + 0x007fffff /* DENALI_CTL_222_DATA */ + 0x00000000 /* DENALI_CTL_223_DATA */ + 0x037fffff /* DENALI_CTL_224_DATA */ + 0xffffffff /* DENALI_CTL_225_DATA */ + 0x000f000f /* DENALI_CTL_226_DATA */ + 0x00ffff03 /* DENALI_CTL_227_DATA */ + 0x000fffff /* DENALI_CTL_228_DATA */ + 0x0003000f /* DENALI_CTL_229_DATA */ + 0xffffffff /* DENALI_CTL_230_DATA */ + 0x000f000f /* DENALI_CTL_231_DATA */ + 0x00ffff03 /* DENALI_CTL_232_DATA */ + 0x000fffff /* DENALI_CTL_233_DATA */ + 0x0003000f /* DENALI_CTL_234_DATA */ + 0xffffffff /* DENALI_CTL_235_DATA */ + 0x000f000f /* DENALI_CTL_236_DATA */ + 0x00ffff03 /* DENALI_CTL_237_DATA */ + 0x000fffff /* DENALI_CTL_238_DATA */ + 0x0003000f /* DENALI_CTL_239_DATA */ + 0xffffffff /* DENALI_CTL_240_DATA */ + 0x000f000f /* DENALI_CTL_241_DATA */ + 0x00ffff03 /* DENALI_CTL_242_DATA */ + 0x000fffff /* DENALI_CTL_243_DATA */ + 0x6407000f /* DENALI_CTL_244_DATA */ + 0x01640001 /* DENALI_CTL_245_DATA */ + 0x00000000 /* DENALI_CTL_246_DATA */ + 0x00000000 /* DENALI_CTL_247_DATA */ + 0x00001700 /* DENALI_CTL_248_DATA */ + 0x00386c05 /* DENALI_CTL_249_DATA */ + 0x02000200 /* DENALI_CTL_250_DATA */ + 0x02000200 /* DENALI_CTL_251_DATA */ + 0x0000386c /* DENALI_CTL_252_DATA */ + 0x00023438 /* DENALI_CTL_253_DATA */ + 0x02020d10 /* DENALI_CTL_254_DATA */ + 0x00140303 /* DENALI_CTL_255_DATA */ + 0x00000000 /* DENALI_CTL_256_DATA */ + 0x00000000 /* DENALI_CTL_257_DATA */ + 0x00001403 /* DENALI_CTL_258_DATA */ + 0x00000000 /* DENALI_CTL_259_DATA */ + 0x00000000 /* DENALI_CTL_260_DATA */ + 0x00000000 /* DENALI_CTL_261_DATA */ + 0x00000000 /* DENALI_CTL_262_DATA */ + 0x0d010000 /* DENALI_CTL_263_DATA */ + 0x00000008 /* DENALI_CTL_264_DATA */ + 0x31706542 /* DENALI_PHY_00_DATA */ + 0x0004c008 /* DENALI_PHY_01_DATA */ + 0x000000da /* DENALI_PHY_02_DATA */ + 0x00000000 /* DENALI_PHY_03_DATA */ + 0x00000000 /* DENALI_PHY_04_DATA */ + 0x00010000 /* DENALI_PHY_05_DATA */ + 0x01DDDD90 /* DENALI_PHY_06_DATA */ + 0x01DDDD90 /* DENALI_PHY_07_DATA */ + 0x01030000 /* DENALI_PHY_08_DATA */ + 0x01000000 /* DENALI_PHY_09_DATA */ + 0x00c00000 /* DENALI_PHY_10_DATA */ + 0x00000007 /* DENALI_PHY_11_DATA */ + 0x00000000 /* DENALI_PHY_12_DATA */ + 0x00000000 /* DENALI_PHY_13_DATA */ + 0x04000408 /* DENALI_PHY_14_DATA */ + 0x00000408 /* DENALI_PHY_15_DATA */ + 0x00e4e400 /* DENALI_PHY_16_DATA */ + 0x00000000 /* DENALI_PHY_17_DATA */ + 0x00000000 /* DENALI_PHY_18_DATA */ + 0x00000000 /* DENALI_PHY_19_DATA */ + 0x00000000 /* DENALI_PHY_20_DATA */ + 0x00000000 /* DENALI_PHY_21_DATA */ + 0x00000000 /* DENALI_PHY_22_DATA */ + 0x00000000 /* DENALI_PHY_23_DATA */ + 0x00000000 /* DENALI_PHY_24_DATA */ + 0x00000000 /* DENALI_PHY_25_DATA */ + 0x00000000 /* DENALI_PHY_26_DATA */ + 0x00000000 /* DENALI_PHY_27_DATA */ + 0x00000000 /* DENALI_PHY_28_DATA */ + 0x00000000 /* DENALI_PHY_29_DATA */ + 0x00000000 /* DENALI_PHY_30_DATA */ + 0x00000000 /* DENALI_PHY_31_DATA */ + 0x00000000 /* DENALI_PHY_32_DATA */ + 0x00200000 /* DENALI_PHY_33_DATA */ + 0x00000000 /* DENALI_PHY_34_DATA */ + 0x00000000 /* DENALI_PHY_35_DATA */ + 0x00000000 /* DENALI_PHY_36_DATA */ + 0x00000000 /* DENALI_PHY_37_DATA */ + 0x00000000 /* DENALI_PHY_38_DATA */ + 0x00000000 /* DENALI_PHY_39_DATA */ + 0x02800280 /* DENALI_PHY_40_DATA */ + 0x02800280 /* DENALI_PHY_41_DATA */ + 0x02800280 /* DENALI_PHY_42_DATA */ + 0x02800280 /* DENALI_PHY_43_DATA */ + 0x00000280 /* DENALI_PHY_44_DATA */ + 0x00000000 /* DENALI_PHY_45_DATA */ + 0x00000000 /* DENALI_PHY_46_DATA */ + 0x00000000 /* DENALI_PHY_47_DATA */ + 0x00000000 /* DENALI_PHY_48_DATA */ + 0x00000000 /* DENALI_PHY_49_DATA */ + 0x00800080 /* DENALI_PHY_50_DATA */ + 0x00800080 /* DENALI_PHY_51_DATA */ + 0x00800080 /* DENALI_PHY_52_DATA */ + 0x00800080 /* DENALI_PHY_53_DATA */ + 0x00800080 /* DENALI_PHY_54_DATA */ + 0x00800080 /* DENALI_PHY_55_DATA */ + 0x00800080 /* DENALI_PHY_56_DATA */ + 0x00800080 /* DENALI_PHY_57_DATA */ + 0x00800080 /* DENALI_PHY_58_DATA */ + 0x000100da /* DENALI_PHY_59_DATA */ + 0x01000200 /* DENALI_PHY_60_DATA */ + 0x00000000 /* DENALI_PHY_61_DATA */ + 0x00000000 /* DENALI_PHY_62_DATA */ + 0x00000002 /* DENALI_PHY_63_DATA */ + 0x51313152 /* DENALI_PHY_64_DATA */ + 0x80013130 /* DENALI_PHY_65_DATA */ + 0x02000080 /* DENALI_PHY_66_DATA */ + 0x00100001 /* DENALI_PHY_67_DATA */ + 0x0c064208 /* DENALI_PHY_68_DATA */ + 0x000f0c0f /* DENALI_PHY_69_DATA */ + 0x01000140 /* DENALI_PHY_70_DATA */ + 0x0000000c /* DENALI_PHY_71_DATA */ + 0x00000000 /* DENALI_PHY_72_DATA */ + 0x00000000 /* DENALI_PHY_73_DATA */ + 0x00000000 /* DENALI_PHY_74_DATA */ + 0x00000000 /* DENALI_PHY_75_DATA */ + 0x00000000 /* DENALI_PHY_76_DATA */ + 0x00000000 /* DENALI_PHY_77_DATA */ + 0x00000000 /* DENALI_PHY_78_DATA */ + 0x00000000 /* DENALI_PHY_79_DATA */ + 0x00000000 /* DENALI_PHY_80_DATA */ + 0x00000000 /* DENALI_PHY_81_DATA */ + 0x00000000 /* DENALI_PHY_82_DATA */ + 0x00000000 /* DENALI_PHY_83_DATA */ + 0x00000000 /* DENALI_PHY_84_DATA */ + 0x00000000 /* DENALI_PHY_85_DATA */ + 0x00000000 /* DENALI_PHY_86_DATA */ + 0x00000000 /* DENALI_PHY_87_DATA */ + 0x00000000 /* DENALI_PHY_88_DATA */ + 0x00000000 /* DENALI_PHY_89_DATA */ + 0x00000000 /* DENALI_PHY_90_DATA */ + 0x00000000 /* DENALI_PHY_91_DATA */ + 0x00000000 /* DENALI_PHY_92_DATA */ + 0x00000000 /* DENALI_PHY_93_DATA */ + 0x00000000 /* DENALI_PHY_94_DATA */ + 0x00000000 /* DENALI_PHY_95_DATA */ + 0x00000000 /* DENALI_PHY_96_DATA */ + 0x00000000 /* DENALI_PHY_97_DATA */ + 0x00000000 /* DENALI_PHY_98_DATA */ + 0x00000000 /* DENALI_PHY_99_DATA */ + 0x00000000 /* DENALI_PHY_100_DATA */ + 0x00000000 /* DENALI_PHY_101_DATA */ + 0x00000000 /* DENALI_PHY_102_DATA */ + 0x00000000 /* DENALI_PHY_103_DATA */ + 0x00000000 /* DENALI_PHY_104_DATA */ + 0x00000000 /* DENALI_PHY_105_DATA */ + 0x00000000 /* DENALI_PHY_106_DATA */ + 0x00000000 /* DENALI_PHY_107_DATA */ + 0x00000000 /* DENALI_PHY_108_DATA */ + 0x00000000 /* DENALI_PHY_109_DATA */ + 0x00000000 /* DENALI_PHY_110_DATA */ + 0x00000000 /* DENALI_PHY_111_DATA */ + 0x00000000 /* DENALI_PHY_112_DATA */ + 0x00000000 /* DENALI_PHY_113_DATA */ + 0x00000000 /* DENALI_PHY_114_DATA */ + 0x00000000 /* DENALI_PHY_115_DATA */ + 0x00000000 /* DENALI_PHY_116_DATA */ + 0x00000000 /* DENALI_PHY_117_DATA */ + 0x00000000 /* DENALI_PHY_118_DATA */ + 0x00000000 /* DENALI_PHY_119_DATA */ + 0x00000000 /* DENALI_PHY_120_DATA */ + 0x00000000 /* DENALI_PHY_121_DATA */ + 0x00000000 /* DENALI_PHY_122_DATA */ + 0x00000000 /* DENALI_PHY_123_DATA */ + 0x00000000 /* DENALI_PHY_124_DATA */ + 0x00000000 /* DENALI_PHY_125_DATA */ + 0x00000000 /* DENALI_PHY_126_DATA */ + 0x00000000 /* DENALI_PHY_127_DATA */ + 0x40263571 /* DENALI_PHY_128_DATA */ + 0x0004c008 /* DENALI_PHY_129_DATA */ + 0x000000da /* DENALI_PHY_130_DATA */ + 0x00000000 /* DENALI_PHY_131_DATA */ + 0x00000000 /* DENALI_PHY_132_DATA */ + 0x00010000 /* DENALI_PHY_133_DATA */ + 0x01DDDD90 /* DENALI_PHY_134_DATA */ + 0x01DDDD90 /* DENALI_PHY_135_DATA */ + 0x01030000 /* DENALI_PHY_136_DATA */ + 0x01000000 /* DENALI_PHY_137_DATA */ + 0x00c00000 /* DENALI_PHY_138_DATA */ + 0x00000007 /* DENALI_PHY_139_DATA */ + 0x00000000 /* DENALI_PHY_140_DATA */ + 0x00000000 /* DENALI_PHY_141_DATA */ + 0x04000408 /* DENALI_PHY_142_DATA */ + 0x00000408 /* DENALI_PHY_143_DATA */ + 0x00e4e400 /* DENALI_PHY_144_DATA */ + 0x00000000 /* DENALI_PHY_145_DATA */ + 0x00000000 /* DENALI_PHY_146_DATA */ + 0x00000000 /* DENALI_PHY_147_DATA */ + 0x00000000 /* DENALI_PHY_148_DATA */ + 0x00000000 /* DENALI_PHY_149_DATA */ + 0x00000000 /* DENALI_PHY_150_DATA */ + 0x00000000 /* DENALI_PHY_151_DATA */ + 0x00000000 /* DENALI_PHY_152_DATA */ + 0x00000000 /* DENALI_PHY_153_DATA */ + 0x00000000 /* DENALI_PHY_154_DATA */ + 0x00000000 /* DENALI_PHY_155_DATA */ + 0x00000000 /* DENALI_PHY_156_DATA */ + 0x00000000 /* DENALI_PHY_157_DATA */ + 0x00000000 /* DENALI_PHY_158_DATA */ + 0x00000000 /* DENALI_PHY_159_DATA */ + 0x00000000 /* DENALI_PHY_160_DATA */ + 0x00200000 /* DENALI_PHY_161_DATA */ + 0x00000000 /* DENALI_PHY_162_DATA */ + 0x00000000 /* DENALI_PHY_163_DATA */ + 0x00000000 /* DENALI_PHY_164_DATA */ + 0x00000000 /* DENALI_PHY_165_DATA */ + 0x00000000 /* DENALI_PHY_166_DATA */ + 0x00000000 /* DENALI_PHY_167_DATA */ + 0x02800280 /* DENALI_PHY_168_DATA */ + 0x02800280 /* DENALI_PHY_169_DATA */ + 0x02800280 /* DENALI_PHY_170_DATA */ + 0x02800280 /* DENALI_PHY_171_DATA */ + 0x00000280 /* DENALI_PHY_172_DATA */ + 0x00000000 /* DENALI_PHY_173_DATA */ + 0x00000000 /* DENALI_PHY_174_DATA */ + 0x00000000 /* DENALI_PHY_175_DATA */ + 0x00000000 /* DENALI_PHY_176_DATA */ + 0x00000000 /* DENALI_PHY_177_DATA */ + 0x00800080 /* DENALI_PHY_178_DATA */ + 0x00800080 /* DENALI_PHY_179_DATA */ + 0x00800080 /* DENALI_PHY_180_DATA */ + 0x00800080 /* DENALI_PHY_181_DATA */ + 0x00800080 /* DENALI_PHY_182_DATA */ + 0x00800080 /* DENALI_PHY_183_DATA */ + 0x00800080 /* DENALI_PHY_184_DATA */ + 0x00800080 /* DENALI_PHY_185_DATA */ + 0x00800080 /* DENALI_PHY_186_DATA */ + 0x000100da /* DENALI_PHY_187_DATA */ + 0x01000200 /* DENALI_PHY_188_DATA */ + 0x00000000 /* DENALI_PHY_189_DATA */ + 0x00000000 /* DENALI_PHY_190_DATA */ + 0x00000002 /* DENALI_PHY_191_DATA */ + 0x51313152 /* DENALI_PHY_192_DATA */ + 0x80013130 /* DENALI_PHY_193_DATA */ + 0x02000080 /* DENALI_PHY_194_DATA */ + 0x00100001 /* DENALI_PHY_195_DATA */ + 0x0c064208 /* DENALI_PHY_196_DATA */ + 0x000f0c0f /* DENALI_PHY_197_DATA */ + 0x01000140 /* DENALI_PHY_198_DATA */ + 0x0000000c /* DENALI_PHY_199_DATA */ + 0x00000000 /* DENALI_PHY_200_DATA */ + 0x00000000 /* DENALI_PHY_201_DATA */ + 0x00000000 /* DENALI_PHY_202_DATA */ + 0x00000000 /* DENALI_PHY_203_DATA */ + 0x00000000 /* DENALI_PHY_204_DATA */ + 0x00000000 /* DENALI_PHY_205_DATA */ + 0x00000000 /* DENALI_PHY_206_DATA */ + 0x00000000 /* DENALI_PHY_207_DATA */ + 0x00000000 /* DENALI_PHY_208_DATA */ + 0x00000000 /* DENALI_PHY_209_DATA */ + 0x00000000 /* DENALI_PHY_210_DATA */ + 0x00000000 /* DENALI_PHY_211_DATA */ + 0x00000000 /* DENALI_PHY_212_DATA */ + 0x00000000 /* DENALI_PHY_213_DATA */ + 0x00000000 /* DENALI_PHY_214_DATA */ + 0x00000000 /* DENALI_PHY_215_DATA */ + 0x00000000 /* DENALI_PHY_216_DATA */ + 0x00000000 /* DENALI_PHY_217_DATA */ + 0x00000000 /* DENALI_PHY_218_DATA */ + 0x00000000 /* DENALI_PHY_219_DATA */ + 0x00000000 /* DENALI_PHY_220_DATA */ + 0x00000000 /* DENALI_PHY_221_DATA */ + 0x00000000 /* DENALI_PHY_222_DATA */ + 0x00000000 /* DENALI_PHY_223_DATA */ + 0x00000000 /* DENALI_PHY_224_DATA */ + 0x00000000 /* DENALI_PHY_225_DATA */ + 0x00000000 /* DENALI_PHY_226_DATA */ + 0x00000000 /* DENALI_PHY_227_DATA */ + 0x00000000 /* DENALI_PHY_228_DATA */ + 0x00000000 /* DENALI_PHY_229_DATA */ + 0x00000000 /* DENALI_PHY_230_DATA */ + 0x00000000 /* DENALI_PHY_231_DATA */ + 0x00000000 /* DENALI_PHY_232_DATA */ + 0x00000000 /* DENALI_PHY_233_DATA */ + 0x00000000 /* DENALI_PHY_234_DATA */ + 0x00000000 /* DENALI_PHY_235_DATA */ + 0x00000000 /* DENALI_PHY_236_DATA */ + 0x00000000 /* DENALI_PHY_237_DATA */ + 0x00000000 /* DENALI_PHY_238_DATA */ + 0x00000000 /* DENALI_PHY_239_DATA */ + 0x00000000 /* DENALI_PHY_240_DATA */ + 0x00000000 /* DENALI_PHY_241_DATA */ + 0x00000000 /* DENALI_PHY_242_DATA */ + 0x00000000 /* DENALI_PHY_243_DATA */ + 0x00000000 /* DENALI_PHY_244_DATA */ + 0x00000000 /* DENALI_PHY_245_DATA */ + 0x00000000 /* DENALI_PHY_246_DATA */ + 0x00000000 /* DENALI_PHY_247_DATA */ + 0x00000000 /* DENALI_PHY_248_DATA */ + 0x00000000 /* DENALI_PHY_249_DATA */ + 0x00000000 /* DENALI_PHY_250_DATA */ + 0x00000000 /* DENALI_PHY_251_DATA */ + 0x00000000 /* DENALI_PHY_252_DATA */ + 0x00000000 /* DENALI_PHY_253_DATA */ + 0x00000000 /* DENALI_PHY_254_DATA */ + 0x00000000 /* DENALI_PHY_255_DATA */ + 0x46052371 /* DENALI_PHY_256_DATA */ + 0x0004c008 /* DENALI_PHY_257_DATA */ + 0x000000da /* DENALI_PHY_258_DATA */ + 0x00000000 /* DENALI_PHY_259_DATA */ + 0x00000000 /* DENALI_PHY_260_DATA */ + 0x00010000 /* DENALI_PHY_261_DATA */ + 0x01DDDD90 /* DENALI_PHY_262_DATA */ + 0x01DDDD90 /* DENALI_PHY_263_DATA */ + 0x01030000 /* DENALI_PHY_264_DATA */ + 0x01000000 /* DENALI_PHY_265_DATA */ + 0x00c00000 /* DENALI_PHY_266_DATA */ + 0x00000007 /* DENALI_PHY_267_DATA */ + 0x00000000 /* DENALI_PHY_268_DATA */ + 0x00000000 /* DENALI_PHY_269_DATA */ + 0x04000408 /* DENALI_PHY_270_DATA */ + 0x00000408 /* DENALI_PHY_271_DATA */ + 0x00e4e400 /* DENALI_PHY_272_DATA */ + 0x00000000 /* DENALI_PHY_273_DATA */ + 0x00000000 /* DENALI_PHY_274_DATA */ + 0x00000000 /* DENALI_PHY_275_DATA */ + 0x00000000 /* DENALI_PHY_276_DATA */ + 0x00000000 /* DENALI_PHY_277_DATA */ + 0x00000000 /* DENALI_PHY_278_DATA */ + 0x00000000 /* DENALI_PHY_279_DATA */ + 0x00000000 /* DENALI_PHY_280_DATA */ + 0x00000000 /* DENALI_PHY_281_DATA */ + 0x00000000 /* DENALI_PHY_282_DATA */ + 0x00000000 /* DENALI_PHY_283_DATA */ + 0x00000000 /* DENALI_PHY_284_DATA */ + 0x00000000 /* DENALI_PHY_285_DATA */ + 0x00000000 /* DENALI_PHY_286_DATA */ + 0x00000000 /* DENALI_PHY_287_DATA */ + 0x00000000 /* DENALI_PHY_288_DATA */ + 0x00200000 /* DENALI_PHY_289_DATA */ + 0x00000000 /* DENALI_PHY_290_DATA */ + 0x00000000 /* DENALI_PHY_291_DATA */ + 0x00000000 /* DENALI_PHY_292_DATA */ + 0x00000000 /* DENALI_PHY_293_DATA */ + 0x00000000 /* DENALI_PHY_294_DATA */ + 0x00000000 /* DENALI_PHY_295_DATA */ + 0x02800280 /* DENALI_PHY_296_DATA */ + 0x02800280 /* DENALI_PHY_297_DATA */ + 0x02800280 /* DENALI_PHY_298_DATA */ + 0x02800280 /* DENALI_PHY_299_DATA */ + 0x00000280 /* DENALI_PHY_300_DATA */ + 0x00000000 /* DENALI_PHY_301_DATA */ + 0x00000000 /* DENALI_PHY_302_DATA */ + 0x00000000 /* DENALI_PHY_303_DATA */ + 0x00000000 /* DENALI_PHY_304_DATA */ + 0x00000000 /* DENALI_PHY_305_DATA */ + 0x00800080 /* DENALI_PHY_306_DATA */ + 0x00800080 /* DENALI_PHY_307_DATA */ + 0x00800080 /* DENALI_PHY_308_DATA */ + 0x00800080 /* DENALI_PHY_309_DATA */ + 0x00800080 /* DENALI_PHY_310_DATA */ + 0x00800080 /* DENALI_PHY_311_DATA */ + 0x00800080 /* DENALI_PHY_312_DATA */ + 0x00800080 /* DENALI_PHY_313_DATA */ + 0x00800080 /* DENALI_PHY_314_DATA */ + 0x000100da /* DENALI_PHY_315_DATA */ + 0x00000200 /* DENALI_PHY_316_DATA */ + 0x00000000 /* DENALI_PHY_317_DATA */ + 0x00000000 /* DENALI_PHY_318_DATA */ + 0x00000002 /* DENALI_PHY_319_DATA */ + 0x51313152 /* DENALI_PHY_320_DATA */ + 0x80013130 /* DENALI_PHY_321_DATA */ + 0x02000080 /* DENALI_PHY_322_DATA */ + 0x00100001 /* DENALI_PHY_323_DATA */ + 0x0c064208 /* DENALI_PHY_324_DATA */ + 0x000f0c0f /* DENALI_PHY_325_DATA */ + 0x01000140 /* DENALI_PHY_326_DATA */ + 0x0000000c /* DENALI_PHY_327_DATA */ + 0x00000000 /* DENALI_PHY_328_DATA */ + 0x00000000 /* DENALI_PHY_329_DATA */ + 0x00000000 /* DENALI_PHY_330_DATA */ + 0x00000000 /* DENALI_PHY_331_DATA */ + 0x00000000 /* DENALI_PHY_332_DATA */ + 0x00000000 /* DENALI_PHY_333_DATA */ + 0x00000000 /* DENALI_PHY_334_DATA */ + 0x00000000 /* DENALI_PHY_335_DATA */ + 0x00000000 /* DENALI_PHY_336_DATA */ + 0x00000000 /* DENALI_PHY_337_DATA */ + 0x00000000 /* DENALI_PHY_338_DATA */ + 0x00000000 /* DENALI_PHY_339_DATA */ + 0x00000000 /* DENALI_PHY_340_DATA */ + 0x00000000 /* DENALI_PHY_341_DATA */ + 0x00000000 /* DENALI_PHY_342_DATA */ + 0x00000000 /* DENALI_PHY_343_DATA */ + 0x00000000 /* DENALI_PHY_344_DATA */ + 0x00000000 /* DENALI_PHY_345_DATA */ + 0x00000000 /* DENALI_PHY_346_DATA */ + 0x00000000 /* DENALI_PHY_347_DATA */ + 0x00000000 /* DENALI_PHY_348_DATA */ + 0x00000000 /* DENALI_PHY_349_DATA */ + 0x00000000 /* DENALI_PHY_350_DATA */ + 0x00000000 /* DENALI_PHY_351_DATA */ + 0x00000000 /* DENALI_PHY_352_DATA */ + 0x00000000 /* DENALI_PHY_353_DATA */ + 0x00000000 /* DENALI_PHY_354_DATA */ + 0x00000000 /* DENALI_PHY_355_DATA */ + 0x00000000 /* DENALI_PHY_356_DATA */ + 0x00000000 /* DENALI_PHY_357_DATA */ + 0x00000000 /* DENALI_PHY_358_DATA */ + 0x00000000 /* DENALI_PHY_359_DATA */ + 0x00000000 /* DENALI_PHY_360_DATA */ + 0x00000000 /* DENALI_PHY_361_DATA */ + 0x00000000 /* DENALI_PHY_362_DATA */ + 0x00000000 /* DENALI_PHY_363_DATA */ + 0x00000000 /* DENALI_PHY_364_DATA */ + 0x00000000 /* DENALI_PHY_365_DATA */ + 0x00000000 /* DENALI_PHY_366_DATA */ + 0x00000000 /* DENALI_PHY_367_DATA */ + 0x00000000 /* DENALI_PHY_368_DATA */ + 0x00000000 /* DENALI_PHY_369_DATA */ + 0x00000000 /* DENALI_PHY_370_DATA */ + 0x00000000 /* DENALI_PHY_371_DATA */ + 0x00000000 /* DENALI_PHY_372_DATA */ + 0x00000000 /* DENALI_PHY_373_DATA */ + 0x00000000 /* DENALI_PHY_374_DATA */ + 0x00000000 /* DENALI_PHY_375_DATA */ + 0x00000000 /* DENALI_PHY_376_DATA */ + 0x00000000 /* DENALI_PHY_377_DATA */ + 0x00000000 /* DENALI_PHY_378_DATA */ + 0x00000000 /* DENALI_PHY_379_DATA */ + 0x00000000 /* DENALI_PHY_380_DATA */ + 0x00000000 /* DENALI_PHY_381_DATA */ + 0x00000000 /* DENALI_PHY_382_DATA */ + 0x00000000 /* DENALI_PHY_383_DATA */ + 0x37654120 /* DENALI_PHY_384_DATA */ + 0x0004c008 /* DENALI_PHY_385_DATA */ + 0x000000da /* DENALI_PHY_386_DATA */ + 0x00000000 /* DENALI_PHY_387_DATA */ + 0x00000000 /* DENALI_PHY_388_DATA */ + 0x00010000 /* DENALI_PHY_389_DATA */ + 0x01DDDD90 /* DENALI_PHY_390_DATA */ + 0x01DDDD90 /* DENALI_PHY_391_DATA */ + 0x01030000 /* DENALI_PHY_392_DATA */ + 0x01000000 /* DENALI_PHY_393_DATA */ + 0x00c00000 /* DENALI_PHY_394_DATA */ + 0x00000007 /* DENALI_PHY_395_DATA */ + 0x00000000 /* DENALI_PHY_396_DATA */ + 0x00000000 /* DENALI_PHY_397_DATA */ + 0x04000408 /* DENALI_PHY_398_DATA */ + 0x00000408 /* DENALI_PHY_399_DATA */ + 0x00e4e400 /* DENALI_PHY_400_DATA */ + 0x00000000 /* DENALI_PHY_401_DATA */ + 0x00000000 /* DENALI_PHY_402_DATA */ + 0x00000000 /* DENALI_PHY_403_DATA */ + 0x00000000 /* DENALI_PHY_404_DATA */ + 0x00000000 /* DENALI_PHY_405_DATA */ + 0x00000000 /* DENALI_PHY_406_DATA */ + 0x00000000 /* DENALI_PHY_407_DATA */ + 0x00000000 /* DENALI_PHY_408_DATA */ + 0x00000000 /* DENALI_PHY_409_DATA */ + 0x00000000 /* DENALI_PHY_410_DATA */ + 0x00000000 /* DENALI_PHY_411_DATA */ + 0x00000000 /* DENALI_PHY_412_DATA */ + 0x00000000 /* DENALI_PHY_413_DATA */ + 0x00000000 /* DENALI_PHY_414_DATA */ + 0x00000000 /* DENALI_PHY_415_DATA */ + 0x00000000 /* DENALI_PHY_416_DATA */ + 0x00200000 /* DENALI_PHY_417_DATA */ + 0x00000000 /* DENALI_PHY_418_DATA */ + 0x00000000 /* DENALI_PHY_419_DATA */ + 0x00000000 /* DENALI_PHY_420_DATA */ + 0x00000000 /* DENALI_PHY_421_DATA */ + 0x00000000 /* DENALI_PHY_422_DATA */ + 0x00000000 /* DENALI_PHY_423_DATA */ + 0x02800280 /* DENALI_PHY_424_DATA */ + 0x02800280 /* DENALI_PHY_425_DATA */ + 0x02800280 /* DENALI_PHY_426_DATA */ + 0x02800280 /* DENALI_PHY_427_DATA */ + 0x00000280 /* DENALI_PHY_428_DATA */ + 0x00000000 /* DENALI_PHY_429_DATA */ + 0x00000000 /* DENALI_PHY_430_DATA */ + 0x00000000 /* DENALI_PHY_431_DATA */ + 0x00000000 /* DENALI_PHY_432_DATA */ + 0x00000000 /* DENALI_PHY_433_DATA */ + 0x00800080 /* DENALI_PHY_434_DATA */ + 0x00800080 /* DENALI_PHY_435_DATA */ + 0x00800080 /* DENALI_PHY_436_DATA */ + 0x00800080 /* DENALI_PHY_437_DATA */ + 0x00800080 /* DENALI_PHY_438_DATA */ + 0x00800080 /* DENALI_PHY_439_DATA */ + 0x00800080 /* DENALI_PHY_440_DATA */ + 0x00800080 /* DENALI_PHY_441_DATA */ + 0x00800080 /* DENALI_PHY_442_DATA */ + 0x000100da /* DENALI_PHY_443_DATA */ + 0x00000200 /* DENALI_PHY_444_DATA */ + 0x00000000 /* DENALI_PHY_445_DATA */ + 0x00000000 /* DENALI_PHY_446_DATA */ + 0x00000002 /* DENALI_PHY_447_DATA */ + 0x51313152 /* DENALI_PHY_448_DATA */ + 0x80013130 /* DENALI_PHY_449_DATA */ + 0x02000080 /* DENALI_PHY_450_DATA */ + 0x00100001 /* DENALI_PHY_451_DATA */ + 0x0c064208 /* DENALI_PHY_452_DATA */ + 0x000f0c0f /* DENALI_PHY_453_DATA */ + 0x01000140 /* DENALI_PHY_454_DATA */ + 0x0000000c /* DENALI_PHY_455_DATA */ + 0x00000000 /* DENALI_PHY_456_DATA */ + 0x00000000 /* DENALI_PHY_457_DATA */ + 0x00000000 /* DENALI_PHY_458_DATA */ + 0x00000000 /* DENALI_PHY_459_DATA */ + 0x00000000 /* DENALI_PHY_460_DATA */ + 0x00000000 /* DENALI_PHY_461_DATA */ + 0x00000000 /* DENALI_PHY_462_DATA */ + 0x00000000 /* DENALI_PHY_463_DATA */ + 0x00000000 /* DENALI_PHY_464_DATA */ + 0x00000000 /* DENALI_PHY_465_DATA */ + 0x00000000 /* DENALI_PHY_466_DATA */ + 0x00000000 /* DENALI_PHY_467_DATA */ + 0x00000000 /* DENALI_PHY_468_DATA */ + 0x00000000 /* DENALI_PHY_469_DATA */ + 0x00000000 /* DENALI_PHY_470_DATA */ + 0x00000000 /* DENALI_PHY_471_DATA */ + 0x00000000 /* DENALI_PHY_472_DATA */ + 0x00000000 /* DENALI_PHY_473_DATA */ + 0x00000000 /* DENALI_PHY_474_DATA */ + 0x00000000 /* DENALI_PHY_475_DATA */ + 0x00000000 /* DENALI_PHY_476_DATA */ + 0x00000000 /* DENALI_PHY_477_DATA */ + 0x00000000 /* DENALI_PHY_478_DATA */ + 0x00000000 /* DENALI_PHY_479_DATA */ + 0x00000000 /* DENALI_PHY_480_DATA */ + 0x00000000 /* DENALI_PHY_481_DATA */ + 0x00000000 /* DENALI_PHY_482_DATA */ + 0x00000000 /* DENALI_PHY_483_DATA */ + 0x00000000 /* DENALI_PHY_484_DATA */ + 0x00000000 /* DENALI_PHY_485_DATA */ + 0x00000000 /* DENALI_PHY_486_DATA */ + 0x00000000 /* DENALI_PHY_487_DATA */ + 0x00000000 /* DENALI_PHY_488_DATA */ + 0x00000000 /* DENALI_PHY_489_DATA */ + 0x00000000 /* DENALI_PHY_490_DATA */ + 0x00000000 /* DENALI_PHY_491_DATA */ + 0x00000000 /* DENALI_PHY_492_DATA */ + 0x00000000 /* DENALI_PHY_493_DATA */ + 0x00000000 /* DENALI_PHY_494_DATA */ + 0x00000000 /* DENALI_PHY_495_DATA */ + 0x00000000 /* DENALI_PHY_496_DATA */ + 0x00000000 /* DENALI_PHY_497_DATA */ + 0x00000000 /* DENALI_PHY_498_DATA */ + 0x00000000 /* DENALI_PHY_499_DATA */ + 0x00000000 /* DENALI_PHY_500_DATA */ + 0x00000000 /* DENALI_PHY_501_DATA */ + 0x00000000 /* DENALI_PHY_502_DATA */ + 0x00000000 /* DENALI_PHY_503_DATA */ + 0x00000000 /* DENALI_PHY_504_DATA */ + 0x00000000 /* DENALI_PHY_505_DATA */ + 0x00000000 /* DENALI_PHY_506_DATA */ + 0x00000000 /* DENALI_PHY_507_DATA */ + 0x00000000 /* DENALI_PHY_508_DATA */ + 0x00000000 /* DENALI_PHY_509_DATA */ + 0x00000000 /* DENALI_PHY_510_DATA */ + 0x00000000 /* DENALI_PHY_511_DATA */ + 0x24316750 /* DENALI_PHY_512_DATA */ + 0x0004c008 /* DENALI_PHY_513_DATA */ + 0x000000da /* DENALI_PHY_514_DATA */ + 0x00000000 /* DENALI_PHY_515_DATA */ + 0x00000000 /* DENALI_PHY_516_DATA */ + 0x00010000 /* DENALI_PHY_517_DATA */ + 0x01DDDD90 /* DENALI_PHY_518_DATA */ + 0x01DDDD90 /* DENALI_PHY_519_DATA */ + 0x01030000 /* DENALI_PHY_520_DATA */ + 0x01000000 /* DENALI_PHY_521_DATA */ + 0x00c00000 /* DENALI_PHY_522_DATA */ + 0x00000007 /* DENALI_PHY_523_DATA */ + 0x00000000 /* DENALI_PHY_524_DATA */ + 0x00000000 /* DENALI_PHY_525_DATA */ + 0x04000408 /* DENALI_PHY_526_DATA */ + 0x00000408 /* DENALI_PHY_527_DATA */ + 0x00e4e400 /* DENALI_PHY_528_DATA */ + 0x00000000 /* DENALI_PHY_529_DATA */ + 0x00000000 /* DENALI_PHY_530_DATA */ + 0x00000000 /* DENALI_PHY_531_DATA */ + 0x00000000 /* DENALI_PHY_532_DATA */ + 0x00000000 /* DENALI_PHY_533_DATA */ + 0x00000000 /* DENALI_PHY_534_DATA */ + 0x00000000 /* DENALI_PHY_535_DATA */ + 0x00000000 /* DENALI_PHY_536_DATA */ + 0x00000000 /* DENALI_PHY_537_DATA */ + 0x00000000 /* DENALI_PHY_538_DATA */ + 0x00000000 /* DENALI_PHY_539_DATA */ + 0x00000000 /* DENALI_PHY_540_DATA */ + 0x00000000 /* DENALI_PHY_541_DATA */ + 0x00000000 /* DENALI_PHY_542_DATA */ + 0x00000000 /* DENALI_PHY_543_DATA */ + 0x00000000 /* DENALI_PHY_544_DATA */ + 0x00200000 /* DENALI_PHY_545_DATA */ + 0x00000000 /* DENALI_PHY_546_DATA */ + 0x00000000 /* DENALI_PHY_547_DATA */ + 0x00000000 /* DENALI_PHY_548_DATA */ + 0x00000000 /* DENALI_PHY_549_DATA */ + 0x00000000 /* DENALI_PHY_550_DATA */ + 0x00000000 /* DENALI_PHY_551_DATA */ + 0x02800280 /* DENALI_PHY_552_DATA */ + 0x02800280 /* DENALI_PHY_553_DATA */ + 0x02800280 /* DENALI_PHY_554_DATA */ + 0x02800280 /* DENALI_PHY_555_DATA */ + 0x00000280 /* DENALI_PHY_556_DATA */ + 0x00000000 /* DENALI_PHY_557_DATA */ + 0x00000000 /* DENALI_PHY_558_DATA */ + 0x00000000 /* DENALI_PHY_559_DATA */ + 0x00000000 /* DENALI_PHY_560_DATA */ + 0x00000000 /* DENALI_PHY_561_DATA */ + 0x00800080 /* DENALI_PHY_562_DATA */ + 0x00800080 /* DENALI_PHY_563_DATA */ + 0x00800080 /* DENALI_PHY_564_DATA */ + 0x00800080 /* DENALI_PHY_565_DATA */ + 0x00800080 /* DENALI_PHY_566_DATA */ + 0x00800080 /* DENALI_PHY_567_DATA */ + 0x00800080 /* DENALI_PHY_568_DATA */ + 0x00800080 /* DENALI_PHY_569_DATA */ + 0x00800080 /* DENALI_PHY_570_DATA */ + 0x000100da /* DENALI_PHY_571_DATA */ + 0x00000200 /* DENALI_PHY_572_DATA */ + 0x00000000 /* DENALI_PHY_573_DATA */ + 0x00000000 /* DENALI_PHY_574_DATA */ + 0x00000002 /* DENALI_PHY_575_DATA */ + 0x51313152 /* DENALI_PHY_576_DATA */ + 0x80013130 /* DENALI_PHY_577_DATA */ + 0x02000080 /* DENALI_PHY_578_DATA */ + 0x00100001 /* DENALI_PHY_579_DATA */ + 0x0c064208 /* DENALI_PHY_580_DATA */ + 0x000f0c0f /* DENALI_PHY_581_DATA */ + 0x01000140 /* DENALI_PHY_582_DATA */ + 0x0000000c /* DENALI_PHY_583_DATA */ + 0x00000000 /* DENALI_PHY_584_DATA */ + 0x00000000 /* DENALI_PHY_585_DATA */ + 0x00000000 /* DENALI_PHY_586_DATA */ + 0x00000000 /* DENALI_PHY_587_DATA */ + 0x00000000 /* DENALI_PHY_588_DATA */ + 0x00000000 /* DENALI_PHY_589_DATA */ + 0x00000000 /* DENALI_PHY_590_DATA */ + 0x00000000 /* DENALI_PHY_591_DATA */ + 0x00000000 /* DENALI_PHY_592_DATA */ + 0x00000000 /* DENALI_PHY_593_DATA */ + 0x00000000 /* DENALI_PHY_594_DATA */ + 0x00000000 /* DENALI_PHY_595_DATA */ + 0x00000000 /* DENALI_PHY_596_DATA */ + 0x00000000 /* DENALI_PHY_597_DATA */ + 0x00000000 /* DENALI_PHY_598_DATA */ + 0x00000000 /* DENALI_PHY_599_DATA */ + 0x00000000 /* DENALI_PHY_600_DATA */ + 0x00000000 /* DENALI_PHY_601_DATA */ + 0x00000000 /* DENALI_PHY_602_DATA */ + 0x00000000 /* DENALI_PHY_603_DATA */ + 0x00000000 /* DENALI_PHY_604_DATA */ + 0x00000000 /* DENALI_PHY_605_DATA */ + 0x00000000 /* DENALI_PHY_606_DATA */ + 0x00000000 /* DENALI_PHY_607_DATA */ + 0x00000000 /* DENALI_PHY_608_DATA */ + 0x00000000 /* DENALI_PHY_609_DATA */ + 0x00000000 /* DENALI_PHY_610_DATA */ + 0x00000000 /* DENALI_PHY_611_DATA */ + 0x00000000 /* DENALI_PHY_612_DATA */ + 0x00000000 /* DENALI_PHY_613_DATA */ + 0x00000000 /* DENALI_PHY_614_DATA */ + 0x00000000 /* DENALI_PHY_615_DATA */ + 0x00000000 /* DENALI_PHY_616_DATA */ + 0x00000000 /* DENALI_PHY_617_DATA */ + 0x00000000 /* DENALI_PHY_618_DATA */ + 0x00000000 /* DENALI_PHY_619_DATA */ + 0x00000000 /* DENALI_PHY_620_DATA */ + 0x00000000 /* DENALI_PHY_621_DATA */ + 0x00000000 /* DENALI_PHY_622_DATA */ + 0x00000000 /* DENALI_PHY_623_DATA */ + 0x00000000 /* DENALI_PHY_624_DATA */ + 0x00000000 /* DENALI_PHY_625_DATA */ + 0x00000000 /* DENALI_PHY_626_DATA */ + 0x00000000 /* DENALI_PHY_627_DATA */ + 0x00000000 /* DENALI_PHY_628_DATA */ + 0x00000000 /* DENALI_PHY_629_DATA */ + 0x00000000 /* DENALI_PHY_630_DATA */ + 0x00000000 /* DENALI_PHY_631_DATA */ + 0x00000000 /* DENALI_PHY_632_DATA */ + 0x00000000 /* DENALI_PHY_633_DATA */ + 0x00000000 /* DENALI_PHY_634_DATA */ + 0x00000000 /* DENALI_PHY_635_DATA */ + 0x00000000 /* DENALI_PHY_636_DATA */ + 0x00000000 /* DENALI_PHY_637_DATA */ + 0x00000000 /* DENALI_PHY_638_DATA */ + 0x00000000 /* DENALI_PHY_639_DATA */ + 0x35174620 /* DENALI_PHY_640_DATA */ + 0x0004c008 /* DENALI_PHY_641_DATA */ + 0x000000da /* DENALI_PHY_642_DATA */ + 0x00000000 /* DENALI_PHY_643_DATA */ + 0x00000000 /* DENALI_PHY_644_DATA */ + 0x00010000 /* DENALI_PHY_645_DATA */ + 0x01DDDD90 /* DENALI_PHY_646_DATA */ + 0x01DDDD90 /* DENALI_PHY_647_DATA */ + 0x01030000 /* DENALI_PHY_648_DATA */ + 0x01000000 /* DENALI_PHY_649_DATA */ + 0x00c00000 /* DENALI_PHY_650_DATA */ + 0x00000007 /* DENALI_PHY_651_DATA */ + 0x00000000 /* DENALI_PHY_652_DATA */ + 0x00000000 /* DENALI_PHY_653_DATA */ + 0x04000408 /* DENALI_PHY_654_DATA */ + 0x00000408 /* DENALI_PHY_655_DATA */ + 0x00e4e400 /* DENALI_PHY_656_DATA */ + 0x00000000 /* DENALI_PHY_657_DATA */ + 0x00000000 /* DENALI_PHY_658_DATA */ + 0x00000000 /* DENALI_PHY_659_DATA */ + 0x00000000 /* DENALI_PHY_660_DATA */ + 0x00000000 /* DENALI_PHY_661_DATA */ + 0x00000000 /* DENALI_PHY_662_DATA */ + 0x00000000 /* DENALI_PHY_663_DATA */ + 0x00000000 /* DENALI_PHY_664_DATA */ + 0x00000000 /* DENALI_PHY_665_DATA */ + 0x00000000 /* DENALI_PHY_666_DATA */ + 0x00000000 /* DENALI_PHY_667_DATA */ + 0x00000000 /* DENALI_PHY_668_DATA */ + 0x00000000 /* DENALI_PHY_669_DATA */ + 0x00000000 /* DENALI_PHY_670_DATA */ + 0x00000000 /* DENALI_PHY_671_DATA */ + 0x00000000 /* DENALI_PHY_672_DATA */ + 0x00200000 /* DENALI_PHY_673_DATA */ + 0x00000000 /* DENALI_PHY_674_DATA */ + 0x00000000 /* DENALI_PHY_675_DATA */ + 0x00000000 /* DENALI_PHY_676_DATA */ + 0x00000000 /* DENALI_PHY_677_DATA */ + 0x00000000 /* DENALI_PHY_678_DATA */ + 0x00000000 /* DENALI_PHY_679_DATA */ + 0x02800280 /* DENALI_PHY_680_DATA */ + 0x02800280 /* DENALI_PHY_681_DATA */ + 0x02800280 /* DENALI_PHY_682_DATA */ + 0x02800280 /* DENALI_PHY_683_DATA */ + 0x00000280 /* DENALI_PHY_684_DATA */ + 0x00000000 /* DENALI_PHY_685_DATA */ + 0x00000000 /* DENALI_PHY_686_DATA */ + 0x00000000 /* DENALI_PHY_687_DATA */ + 0x00000000 /* DENALI_PHY_688_DATA */ + 0x00000000 /* DENALI_PHY_689_DATA */ + 0x00800080 /* DENALI_PHY_690_DATA */ + 0x00800080 /* DENALI_PHY_691_DATA */ + 0x00800080 /* DENALI_PHY_692_DATA */ + 0x00800080 /* DENALI_PHY_693_DATA */ + 0x00800080 /* DENALI_PHY_694_DATA */ + 0x00800080 /* DENALI_PHY_695_DATA */ + 0x00800080 /* DENALI_PHY_696_DATA */ + 0x00800080 /* DENALI_PHY_697_DATA */ + 0x00800080 /* DENALI_PHY_698_DATA */ + 0x000100da /* DENALI_PHY_699_DATA */ + 0x00000200 /* DENALI_PHY_700_DATA */ + 0x00000000 /* DENALI_PHY_701_DATA */ + 0x00000000 /* DENALI_PHY_702_DATA */ + 0x00000002 /* DENALI_PHY_703_DATA */ + 0x51313152 /* DENALI_PHY_704_DATA */ + 0x80013130 /* DENALI_PHY_705_DATA */ + 0x02000080 /* DENALI_PHY_706_DATA */ + 0x00100001 /* DENALI_PHY_707_DATA */ + 0x0c064208 /* DENALI_PHY_708_DATA */ + 0x000f0c0f /* DENALI_PHY_709_DATA */ + 0x01000140 /* DENALI_PHY_710_DATA */ + 0x0000000c /* DENALI_PHY_711_DATA */ + 0x00000000 /* DENALI_PHY_712_DATA */ + 0x00000000 /* DENALI_PHY_713_DATA */ + 0x00000000 /* DENALI_PHY_714_DATA */ + 0x00000000 /* DENALI_PHY_715_DATA */ + 0x00000000 /* DENALI_PHY_716_DATA */ + 0x00000000 /* DENALI_PHY_717_DATA */ + 0x00000000 /* DENALI_PHY_718_DATA */ + 0x00000000 /* DENALI_PHY_719_DATA */ + 0x00000000 /* DENALI_PHY_720_DATA */ + 0x00000000 /* DENALI_PHY_721_DATA */ + 0x00000000 /* DENALI_PHY_722_DATA */ + 0x00000000 /* DENALI_PHY_723_DATA */ + 0x00000000 /* DENALI_PHY_724_DATA */ + 0x00000000 /* DENALI_PHY_725_DATA */ + 0x00000000 /* DENALI_PHY_726_DATA */ + 0x00000000 /* DENALI_PHY_727_DATA */ + 0x00000000 /* DENALI_PHY_728_DATA */ + 0x00000000 /* DENALI_PHY_729_DATA */ + 0x00000000 /* DENALI_PHY_730_DATA */ + 0x00000000 /* DENALI_PHY_731_DATA */ + 0x00000000 /* DENALI_PHY_732_DATA */ + 0x00000000 /* DENALI_PHY_733_DATA */ + 0x00000000 /* DENALI_PHY_734_DATA */ + 0x00000000 /* DENALI_PHY_735_DATA */ + 0x00000000 /* DENALI_PHY_736_DATA */ + 0x00000000 /* DENALI_PHY_737_DATA */ + 0x00000000 /* DENALI_PHY_738_DATA */ + 0x00000000 /* DENALI_PHY_739_DATA */ + 0x00000000 /* DENALI_PHY_740_DATA */ + 0x00000000 /* DENALI_PHY_741_DATA */ + 0x00000000 /* DENALI_PHY_742_DATA */ + 0x00000000 /* DENALI_PHY_743_DATA */ + 0x00000000 /* DENALI_PHY_744_DATA */ + 0x00000000 /* DENALI_PHY_745_DATA */ + 0x00000000 /* DENALI_PHY_746_DATA */ + 0x00000000 /* DENALI_PHY_747_DATA */ + 0x00000000 /* DENALI_PHY_748_DATA */ + 0x00000000 /* DENALI_PHY_749_DATA */ + 0x00000000 /* DENALI_PHY_750_DATA */ + 0x00000000 /* DENALI_PHY_751_DATA */ + 0x00000000 /* DENALI_PHY_752_DATA */ + 0x00000000 /* DENALI_PHY_753_DATA */ + 0x00000000 /* DENALI_PHY_754_DATA */ + 0x00000000 /* DENALI_PHY_755_DATA */ + 0x00000000 /* DENALI_PHY_756_DATA */ + 0x00000000 /* DENALI_PHY_757_DATA */ + 0x00000000 /* DENALI_PHY_758_DATA */ + 0x00000000 /* DENALI_PHY_759_DATA */ + 0x00000000 /* DENALI_PHY_760_DATA */ + 0x00000000 /* DENALI_PHY_761_DATA */ + 0x00000000 /* DENALI_PHY_762_DATA */ + 0x00000000 /* DENALI_PHY_763_DATA */ + 0x00000000 /* DENALI_PHY_764_DATA */ + 0x00000000 /* DENALI_PHY_765_DATA */ + 0x00000000 /* DENALI_PHY_766_DATA */ + 0x00000000 /* DENALI_PHY_767_DATA */ + 0x15203476 /* DENALI_PHY_768_DATA */ + 0x0004c008 /* DENALI_PHY_769_DATA */ + 0x000000da /* DENALI_PHY_770_DATA */ + 0x00000000 /* DENALI_PHY_771_DATA */ + 0x00000000 /* DENALI_PHY_772_DATA */ + 0x00010000 /* DENALI_PHY_773_DATA */ + 0x01DDDD90 /* DENALI_PHY_774_DATA */ + 0x01DDDD90 /* DENALI_PHY_775_DATA */ + 0x01030000 /* DENALI_PHY_776_DATA */ + 0x01000000 /* DENALI_PHY_777_DATA */ + 0x00c00000 /* DENALI_PHY_778_DATA */ + 0x00000007 /* DENALI_PHY_779_DATA */ + 0x00000000 /* DENALI_PHY_780_DATA */ + 0x00000000 /* DENALI_PHY_781_DATA */ + 0x04000408 /* DENALI_PHY_782_DATA */ + 0x00000408 /* DENALI_PHY_783_DATA */ + 0x00e4e400 /* DENALI_PHY_784_DATA */ + 0x00000000 /* DENALI_PHY_785_DATA */ + 0x00000000 /* DENALI_PHY_786_DATA */ + 0x00000000 /* DENALI_PHY_787_DATA */ + 0x00000000 /* DENALI_PHY_788_DATA */ + 0x00000000 /* DENALI_PHY_789_DATA */ + 0x00000000 /* DENALI_PHY_790_DATA */ + 0x00000000 /* DENALI_PHY_791_DATA */ + 0x00000000 /* DENALI_PHY_792_DATA */ + 0x00000000 /* DENALI_PHY_793_DATA */ + 0x00000000 /* DENALI_PHY_794_DATA */ + 0x00000000 /* DENALI_PHY_795_DATA */ + 0x00000000 /* DENALI_PHY_796_DATA */ + 0x00000000 /* DENALI_PHY_797_DATA */ + 0x00000000 /* DENALI_PHY_798_DATA */ + 0x00000000 /* DENALI_PHY_799_DATA */ + 0x00000000 /* DENALI_PHY_800_DATA */ + 0x00200000 /* DENALI_PHY_801_DATA */ + 0x00000000 /* DENALI_PHY_802_DATA */ + 0x00000000 /* DENALI_PHY_803_DATA */ + 0x00000000 /* DENALI_PHY_804_DATA */ + 0x00000000 /* DENALI_PHY_805_DATA */ + 0x00000000 /* DENALI_PHY_806_DATA */ + 0x00000000 /* DENALI_PHY_807_DATA */ + 0x02800280 /* DENALI_PHY_808_DATA */ + 0x02800280 /* DENALI_PHY_809_DATA */ + 0x02800280 /* DENALI_PHY_810_DATA */ + 0x02800280 /* DENALI_PHY_811_DATA */ + 0x00000280 /* DENALI_PHY_812_DATA */ + 0x00000000 /* DENALI_PHY_813_DATA */ + 0x00000000 /* DENALI_PHY_814_DATA */ + 0x00000000 /* DENALI_PHY_815_DATA */ + 0x00000000 /* DENALI_PHY_816_DATA */ + 0x00000000 /* DENALI_PHY_817_DATA */ + 0x00800080 /* DENALI_PHY_818_DATA */ + 0x00800080 /* DENALI_PHY_819_DATA */ + 0x00800080 /* DENALI_PHY_820_DATA */ + 0x00800080 /* DENALI_PHY_821_DATA */ + 0x00800080 /* DENALI_PHY_822_DATA */ + 0x00800080 /* DENALI_PHY_823_DATA */ + 0x00800080 /* DENALI_PHY_824_DATA */ + 0x00800080 /* DENALI_PHY_825_DATA */ + 0x00800080 /* DENALI_PHY_826_DATA */ + 0x000100da /* DENALI_PHY_827_DATA */ + 0x00000200 /* DENALI_PHY_828_DATA */ + 0x00000000 /* DENALI_PHY_829_DATA */ + 0x00000000 /* DENALI_PHY_830_DATA */ + 0x00000002 /* DENALI_PHY_831_DATA */ + 0x51313152 /* DENALI_PHY_832_DATA */ + 0x80013130 /* DENALI_PHY_833_DATA */ + 0x02000080 /* DENALI_PHY_834_DATA */ + 0x00100001 /* DENALI_PHY_835_DATA */ + 0x0c064208 /* DENALI_PHY_836_DATA */ + 0x000f0c0f /* DENALI_PHY_837_DATA */ + 0x01000140 /* DENALI_PHY_838_DATA */ + 0x0000000c /* DENALI_PHY_839_DATA */ + 0x00000000 /* DENALI_PHY_840_DATA */ + 0x00000000 /* DENALI_PHY_841_DATA */ + 0x00000000 /* DENALI_PHY_842_DATA */ + 0x00000000 /* DENALI_PHY_843_DATA */ + 0x00000000 /* DENALI_PHY_844_DATA */ + 0x00000000 /* DENALI_PHY_845_DATA */ + 0x00000000 /* DENALI_PHY_846_DATA */ + 0x00000000 /* DENALI_PHY_847_DATA */ + 0x00000000 /* DENALI_PHY_848_DATA */ + 0x00000000 /* DENALI_PHY_849_DATA */ + 0x00000000 /* DENALI_PHY_850_DATA */ + 0x00000000 /* DENALI_PHY_851_DATA */ + 0x00000000 /* DENALI_PHY_852_DATA */ + 0x00000000 /* DENALI_PHY_853_DATA */ + 0x00000000 /* DENALI_PHY_854_DATA */ + 0x00000000 /* DENALI_PHY_855_DATA */ + 0x00000000 /* DENALI_PHY_856_DATA */ + 0x00000000 /* DENALI_PHY_857_DATA */ + 0x00000000 /* DENALI_PHY_858_DATA */ + 0x00000000 /* DENALI_PHY_859_DATA */ + 0x00000000 /* DENALI_PHY_860_DATA */ + 0x00000000 /* DENALI_PHY_861_DATA */ + 0x00000000 /* DENALI_PHY_862_DATA */ + 0x00000000 /* DENALI_PHY_863_DATA */ + 0x00000000 /* DENALI_PHY_864_DATA */ + 0x00000000 /* DENALI_PHY_865_DATA */ + 0x00000000 /* DENALI_PHY_866_DATA */ + 0x00000000 /* DENALI_PHY_867_DATA */ + 0x00000000 /* DENALI_PHY_868_DATA */ + 0x00000000 /* DENALI_PHY_869_DATA */ + 0x00000000 /* DENALI_PHY_870_DATA */ + 0x00000000 /* DENALI_PHY_871_DATA */ + 0x00000000 /* DENALI_PHY_872_DATA */ + 0x00000000 /* DENALI_PHY_873_DATA */ + 0x00000000 /* DENALI_PHY_874_DATA */ + 0x00000000 /* DENALI_PHY_875_DATA */ + 0x00000000 /* DENALI_PHY_876_DATA */ + 0x00000000 /* DENALI_PHY_877_DATA */ + 0x00000000 /* DENALI_PHY_878_DATA */ + 0x00000000 /* DENALI_PHY_879_DATA */ + 0x00000000 /* DENALI_PHY_880_DATA */ + 0x00000000 /* DENALI_PHY_881_DATA */ + 0x00000000 /* DENALI_PHY_882_DATA */ + 0x00000000 /* DENALI_PHY_883_DATA */ + 0x00000000 /* DENALI_PHY_884_DATA */ + 0x00000000 /* DENALI_PHY_885_DATA */ + 0x00000000 /* DENALI_PHY_886_DATA */ + 0x00000000 /* DENALI_PHY_887_DATA */ + 0x00000000 /* DENALI_PHY_888_DATA */ + 0x00000000 /* DENALI_PHY_889_DATA */ + 0x00000000 /* DENALI_PHY_890_DATA */ + 0x00000000 /* DENALI_PHY_891_DATA */ + 0x00000000 /* DENALI_PHY_892_DATA */ + 0x00000000 /* DENALI_PHY_893_DATA */ + 0x00000000 /* DENALI_PHY_894_DATA */ + 0x00000000 /* DENALI_PHY_895_DATA */ + 0x41753206 /* DENALI_PHY_896_DATA */ + 0x0004c008 /* DENALI_PHY_897_DATA */ + 0x000000da /* DENALI_PHY_898_DATA */ + 0x00000000 /* DENALI_PHY_899_DATA */ + 0x00000000 /* DENALI_PHY_900_DATA */ + 0x00010000 /* DENALI_PHY_901_DATA */ + 0x01DDDD90 /* DENALI_PHY_902_DATA */ + 0x01DDDD90 /* DENALI_PHY_903_DATA */ + 0x01030000 /* DENALI_PHY_904_DATA */ + 0x01000000 /* DENALI_PHY_905_DATA */ + 0x00c00000 /* DENALI_PHY_906_DATA */ + 0x00000007 /* DENALI_PHY_907_DATA */ + 0x00000000 /* DENALI_PHY_908_DATA */ + 0x00000000 /* DENALI_PHY_909_DATA */ + 0x04000408 /* DENALI_PHY_910_DATA */ + 0x00000408 /* DENALI_PHY_911_DATA */ + 0x00e4e400 /* DENALI_PHY_912_DATA */ + 0x00000000 /* DENALI_PHY_913_DATA */ + 0x00000000 /* DENALI_PHY_914_DATA */ + 0x00000000 /* DENALI_PHY_915_DATA */ + 0x00000000 /* DENALI_PHY_916_DATA */ + 0x00000000 /* DENALI_PHY_917_DATA */ + 0x00000000 /* DENALI_PHY_918_DATA */ + 0x00000000 /* DENALI_PHY_919_DATA */ + 0x00000000 /* DENALI_PHY_920_DATA */ + 0x00000000 /* DENALI_PHY_921_DATA */ + 0x00000000 /* DENALI_PHY_922_DATA */ + 0x00000000 /* DENALI_PHY_923_DATA */ + 0x00000000 /* DENALI_PHY_924_DATA */ + 0x00000000 /* DENALI_PHY_925_DATA */ + 0x00000000 /* DENALI_PHY_926_DATA */ + 0x00000000 /* DENALI_PHY_927_DATA */ + 0x00000000 /* DENALI_PHY_928_DATA */ + 0x00200000 /* DENALI_PHY_929_DATA */ + 0x00000000 /* DENALI_PHY_930_DATA */ + 0x00000000 /* DENALI_PHY_931_DATA */ + 0x00000000 /* DENALI_PHY_932_DATA */ + 0x00000000 /* DENALI_PHY_933_DATA */ + 0x00000000 /* DENALI_PHY_934_DATA */ + 0x00000000 /* DENALI_PHY_935_DATA */ + 0x02800280 /* DENALI_PHY_936_DATA */ + 0x02800280 /* DENALI_PHY_937_DATA */ + 0x02800280 /* DENALI_PHY_938_DATA */ + 0x02800280 /* DENALI_PHY_939_DATA */ + 0x00000280 /* DENALI_PHY_940_DATA */ + 0x00000000 /* DENALI_PHY_941_DATA */ + 0x00000000 /* DENALI_PHY_942_DATA */ + 0x00000000 /* DENALI_PHY_943_DATA */ + 0x00000000 /* DENALI_PHY_944_DATA */ + 0x00000000 /* DENALI_PHY_945_DATA */ + 0x00800080 /* DENALI_PHY_946_DATA */ + 0x00800080 /* DENALI_PHY_947_DATA */ + 0x00800080 /* DENALI_PHY_948_DATA */ + 0x00800080 /* DENALI_PHY_949_DATA */ + 0x00800080 /* DENALI_PHY_950_DATA */ + 0x00800080 /* DENALI_PHY_951_DATA */ + 0x00800080 /* DENALI_PHY_952_DATA */ + 0x00800080 /* DENALI_PHY_953_DATA */ + 0x00800080 /* DENALI_PHY_954_DATA */ + 0x000100da /* DENALI_PHY_955_DATA */ + 0x00000200 /* DENALI_PHY_956_DATA */ + 0x00000000 /* DENALI_PHY_957_DATA */ + 0x00000000 /* DENALI_PHY_958_DATA */ + 0x00000002 /* DENALI_PHY_959_DATA */ + 0x51313152 /* DENALI_PHY_960_DATA */ + 0x80013130 /* DENALI_PHY_961_DATA */ + 0x02000080 /* DENALI_PHY_962_DATA */ + 0x00100001 /* DENALI_PHY_963_DATA */ + 0x0c064208 /* DENALI_PHY_964_DATA */ + 0x000f0c0f /* DENALI_PHY_965_DATA */ + 0x01000140 /* DENALI_PHY_966_DATA */ + 0x0000000c /* DENALI_PHY_967_DATA */ + 0x00000000 /* DENALI_PHY_968_DATA */ + 0x00000000 /* DENALI_PHY_969_DATA */ + 0x00000000 /* DENALI_PHY_970_DATA */ + 0x00000000 /* DENALI_PHY_971_DATA */ + 0x00000000 /* DENALI_PHY_972_DATA */ + 0x00000000 /* DENALI_PHY_973_DATA */ + 0x00000000 /* DENALI_PHY_974_DATA */ + 0x00000000 /* DENALI_PHY_975_DATA */ + 0x00000000 /* DENALI_PHY_976_DATA */ + 0x00000000 /* DENALI_PHY_977_DATA */ + 0x00000000 /* DENALI_PHY_978_DATA */ + 0x00000000 /* DENALI_PHY_979_DATA */ + 0x00000000 /* DENALI_PHY_980_DATA */ + 0x00000000 /* DENALI_PHY_981_DATA */ + 0x00000000 /* DENALI_PHY_982_DATA */ + 0x00000000 /* DENALI_PHY_983_DATA */ + 0x00000000 /* DENALI_PHY_984_DATA */ + 0x00000000 /* DENALI_PHY_985_DATA */ + 0x00000000 /* DENALI_PHY_986_DATA */ + 0x00000000 /* DENALI_PHY_987_DATA */ + 0x00000000 /* DENALI_PHY_988_DATA */ + 0x00000000 /* DENALI_PHY_989_DATA */ + 0x00000000 /* DENALI_PHY_990_DATA */ + 0x00000000 /* DENALI_PHY_991_DATA */ + 0x00000000 /* DENALI_PHY_992_DATA */ + 0x00000000 /* DENALI_PHY_993_DATA */ + 0x00000000 /* DENALI_PHY_994_DATA */ + 0x00000000 /* DENALI_PHY_995_DATA */ + 0x00000000 /* DENALI_PHY_996_DATA */ + 0x00000000 /* DENALI_PHY_997_DATA */ + 0x00000000 /* DENALI_PHY_998_DATA */ + 0x00000000 /* DENALI_PHY_999_DATA */ + 0x00000000 /* DENALI_PHY_1000_DATA */ + 0x00000000 /* DENALI_PHY_1001_DATA */ + 0x00000000 /* DENALI_PHY_1002_DATA */ + 0x00000000 /* DENALI_PHY_1003_DATA */ + 0x00000000 /* DENALI_PHY_1004_DATA */ + 0x00000000 /* DENALI_PHY_1005_DATA */ + 0x00000000 /* DENALI_PHY_1006_DATA */ + 0x00000000 /* DENALI_PHY_1007_DATA */ + 0x00000000 /* DENALI_PHY_1008_DATA */ + 0x00000000 /* DENALI_PHY_1009_DATA */ + 0x00000000 /* DENALI_PHY_1010_DATA */ + 0x00000000 /* DENALI_PHY_1011_DATA */ + 0x00000000 /* DENALI_PHY_1012_DATA */ + 0x00000000 /* DENALI_PHY_1013_DATA */ + 0x00000000 /* DENALI_PHY_1014_DATA */ + 0x00000000 /* DENALI_PHY_1015_DATA */ + 0x00000000 /* DENALI_PHY_1016_DATA */ + 0x00000000 /* DENALI_PHY_1017_DATA */ + 0x00000000 /* DENALI_PHY_1018_DATA */ + 0x00000000 /* DENALI_PHY_1019_DATA */ + 0x00000000 /* DENALI_PHY_1020_DATA */ + 0x00000000 /* DENALI_PHY_1021_DATA */ + 0x00000000 /* DENALI_PHY_1022_DATA */ + 0x00000000 /* DENALI_PHY_1023_DATA */ + 0x36025174 /* DENALI_PHY_1024_DATA */ + 0x0004c008 /* DENALI_PHY_1025_DATA */ + 0x000000da /* DENALI_PHY_1026_DATA */ + 0x00000000 /* DENALI_PHY_1027_DATA */ + 0x00000000 /* DENALI_PHY_1028_DATA */ + 0x00010000 /* DENALI_PHY_1029_DATA */ + 0x01DDDD90 /* DENALI_PHY_1030_DATA */ + 0x01DDDD90 /* DENALI_PHY_1031_DATA */ + 0x01030000 /* DENALI_PHY_1032_DATA */ + 0x01000000 /* DENALI_PHY_1033_DATA */ + 0x00c00000 /* DENALI_PHY_1034_DATA */ + 0x00000007 /* DENALI_PHY_1035_DATA */ + 0x00000000 /* DENALI_PHY_1036_DATA */ + 0x00000000 /* DENALI_PHY_1037_DATA */ + 0x04000408 /* DENALI_PHY_1038_DATA */ + 0x00000408 /* DENALI_PHY_1039_DATA */ + 0x00e4e400 /* DENALI_PHY_1040_DATA */ + 0x00000000 /* DENALI_PHY_1041_DATA */ + 0x00000000 /* DENALI_PHY_1042_DATA */ + 0x00000000 /* DENALI_PHY_1043_DATA */ + 0x00000000 /* DENALI_PHY_1044_DATA */ + 0x00000000 /* DENALI_PHY_1045_DATA */ + 0x00000000 /* DENALI_PHY_1046_DATA */ + 0x00000000 /* DENALI_PHY_1047_DATA */ + 0x00000000 /* DENALI_PHY_1048_DATA */ + 0x00000000 /* DENALI_PHY_1049_DATA */ + 0x00000000 /* DENALI_PHY_1050_DATA */ + 0x00000000 /* DENALI_PHY_1051_DATA */ + 0x00000000 /* DENALI_PHY_1052_DATA */ + 0x00000000 /* DENALI_PHY_1053_DATA */ + 0x00000000 /* DENALI_PHY_1054_DATA */ + 0x00000000 /* DENALI_PHY_1055_DATA */ + 0x00000000 /* DENALI_PHY_1056_DATA */ + 0x00200000 /* DENALI_PHY_1057_DATA */ + 0x00000000 /* DENALI_PHY_1058_DATA */ + 0x00000000 /* DENALI_PHY_1059_DATA */ + 0x00000000 /* DENALI_PHY_1060_DATA */ + 0x00000000 /* DENALI_PHY_1061_DATA */ + 0x00000000 /* DENALI_PHY_1062_DATA */ + 0x00000000 /* DENALI_PHY_1063_DATA */ + 0x02800280 /* DENALI_PHY_1064_DATA */ + 0x02800280 /* DENALI_PHY_1065_DATA */ + 0x02800280 /* DENALI_PHY_1066_DATA */ + 0x02800280 /* DENALI_PHY_1067_DATA */ + 0x00000280 /* DENALI_PHY_1068_DATA */ + 0x00000000 /* DENALI_PHY_1069_DATA */ + 0x00000000 /* DENALI_PHY_1070_DATA */ + 0x00000000 /* DENALI_PHY_1071_DATA */ + 0x00000000 /* DENALI_PHY_1072_DATA */ + 0x00000000 /* DENALI_PHY_1073_DATA */ + 0x00800080 /* DENALI_PHY_1074_DATA */ + 0x00800080 /* DENALI_PHY_1075_DATA */ + 0x00800080 /* DENALI_PHY_1076_DATA */ + 0x00800080 /* DENALI_PHY_1077_DATA */ + 0x00800080 /* DENALI_PHY_1078_DATA */ + 0x00800080 /* DENALI_PHY_1079_DATA */ + 0x00800080 /* DENALI_PHY_1080_DATA */ + 0x00800080 /* DENALI_PHY_1081_DATA */ + 0x00800080 /* DENALI_PHY_1082_DATA */ + 0x000100da /* DENALI_PHY_1083_DATA */ + 0x00000200 /* DENALI_PHY_1084_DATA */ + 0x00000000 /* DENALI_PHY_1085_DATA */ + 0x00000000 /* DENALI_PHY_1086_DATA */ + 0x00000002 /* DENALI_PHY_1087_DATA */ + 0x51313152 /* DENALI_PHY_1088_DATA */ + 0x80013130 /* DENALI_PHY_1089_DATA */ + 0x02000080 /* DENALI_PHY_1090_DATA */ + 0x00100001 /* DENALI_PHY_1091_DATA */ + 0x0c064208 /* DENALI_PHY_1092_DATA */ + 0x000f0c0f /* DENALI_PHY_1093_DATA */ + 0x01000140 /* DENALI_PHY_1094_DATA */ + 0x0000000c /* DENALI_PHY_1095_DATA */ + 0x00000000 /* DENALI_PHY_1096_DATA */ + 0x00000000 /* DENALI_PHY_1097_DATA */ + 0x00000000 /* DENALI_PHY_1098_DATA */ + 0x00000000 /* DENALI_PHY_1099_DATA */ + 0x00000000 /* DENALI_PHY_1100_DATA */ + 0x00000000 /* DENALI_PHY_1101_DATA */ + 0x00000000 /* DENALI_PHY_1102_DATA */ + 0x00000000 /* DENALI_PHY_1103_DATA */ + 0x00000000 /* DENALI_PHY_1104_DATA */ + 0x00000000 /* DENALI_PHY_1105_DATA */ + 0x00000000 /* DENALI_PHY_1106_DATA */ + 0x00000000 /* DENALI_PHY_1107_DATA */ + 0x00000000 /* DENALI_PHY_1108_DATA */ + 0x00000000 /* DENALI_PHY_1109_DATA */ + 0x00000000 /* DENALI_PHY_1110_DATA */ + 0x00000000 /* DENALI_PHY_1111_DATA */ + 0x00000000 /* DENALI_PHY_1112_DATA */ + 0x00000000 /* DENALI_PHY_1113_DATA */ + 0x00000000 /* DENALI_PHY_1114_DATA */ + 0x00000000 /* DENALI_PHY_1115_DATA */ + 0x00000000 /* DENALI_PHY_1116_DATA */ + 0x00000000 /* DENALI_PHY_1117_DATA */ + 0x00000000 /* DENALI_PHY_1118_DATA */ + 0x00000000 /* DENALI_PHY_1119_DATA */ + 0x00000000 /* DENALI_PHY_1120_DATA */ + 0x00000000 /* DENALI_PHY_1121_DATA */ + 0x00000000 /* DENALI_PHY_1122_DATA */ + 0x00000000 /* DENALI_PHY_1123_DATA */ + 0x00000000 /* DENALI_PHY_1124_DATA */ + 0x00000000 /* DENALI_PHY_1125_DATA */ + 0x00000000 /* DENALI_PHY_1126_DATA */ + 0x00000000 /* DENALI_PHY_1127_DATA */ + 0x00000000 /* DENALI_PHY_1128_DATA */ + 0x00000000 /* DENALI_PHY_1129_DATA */ + 0x00000000 /* DENALI_PHY_1130_DATA */ + 0x00000000 /* DENALI_PHY_1131_DATA */ + 0x00000000 /* DENALI_PHY_1132_DATA */ + 0x00000000 /* DENALI_PHY_1133_DATA */ + 0x00000000 /* DENALI_PHY_1134_DATA */ + 0x00000000 /* DENALI_PHY_1135_DATA */ + 0x00000000 /* DENALI_PHY_1136_DATA */ + 0x00000000 /* DENALI_PHY_1137_DATA */ + 0x00000000 /* DENALI_PHY_1138_DATA */ + 0x00000000 /* DENALI_PHY_1139_DATA */ + 0x00000000 /* DENALI_PHY_1140_DATA */ + 0x00000000 /* DENALI_PHY_1141_DATA */ + 0x00000000 /* DENALI_PHY_1142_DATA */ + 0x00000000 /* DENALI_PHY_1143_DATA */ + 0x00000000 /* DENALI_PHY_1144_DATA */ + 0x00000000 /* DENALI_PHY_1145_DATA */ + 0x00000000 /* DENALI_PHY_1146_DATA */ + 0x00000000 /* DENALI_PHY_1147_DATA */ + 0x00000000 /* DENALI_PHY_1148_DATA */ + 0x00000000 /* DENALI_PHY_1149_DATA */ + 0x00000000 /* DENALI_PHY_1150_DATA */ + 0x00000000 /* DENALI_PHY_1151_DATA */ + 0x00000000 /* DENALI_PHY_1152_DATA */ + 0x00000000 /* DENALI_PHY_1153_DATA */ + 0x00050000 /* DENALI_PHY_1154_DATA */ + 0x00000000 /* DENALI_PHY_1155_DATA */ + 0x00000000 /* DENALI_PHY_1156_DATA */ + 0x00000000 /* DENALI_PHY_1157_DATA */ + 0x00000100 /* DENALI_PHY_1158_DATA */ + 0x00000000 /* DENALI_PHY_1159_DATA */ + 0x00000000 /* DENALI_PHY_1160_DATA */ + 0x00506401 /* DENALI_PHY_1161_DATA */ + 0x01221102 /* DENALI_PHY_1162_DATA */ + 0x00000122 /* DENALI_PHY_1163_DATA */ + 0x00000000 /* DENALI_PHY_1164_DATA */ + 0x000B1F00 /* DENALI_PHY_1165_DATA */ + 0x0B1F0B1F /* DENALI_PHY_1166_DATA */ + 0x0B1F0B1B /* DENALI_PHY_1167_DATA */ + 0x0B1F0B1F /* DENALI_PHY_1168_DATA */ + 0x0B1F0B1F /* DENALI_PHY_1169_DATA */ + 0x00000B00 /* DENALI_PHY_1170_DATA */ + 0x42080010 /* DENALI_PHY_1171_DATA */ + 0x01000100 /* DENALI_PHY_1172_DATA */ + 0x01000100 /* DENALI_PHY_1173_DATA */ + 0x01000100 /* DENALI_PHY_1174_DATA */ + 0x01000100 /* DENALI_PHY_1175_DATA */ + 0x00000000 /* DENALI_PHY_1176_DATA */ + 0x00000000 /* DENALI_PHY_1177_DATA */ + 0x00000000 /* DENALI_PHY_1178_DATA */ + 0x00000000 /* DENALI_PHY_1179_DATA */ + 0x00000000 /* DENALI_PHY_1180_DATA */ + 0x00000803 /* DENALI_PHY_1181_DATA */ + 0x223FFF00 /* DENALI_PHY_1182_DATA */ + 0x000008FF /* DENALI_PHY_1183_DATA */ + 0x0000057F /* DENALI_PHY_1184_DATA */ + 0x0000057F /* DENALI_PHY_1185_DATA */ + 0x00037FFF /* DENALI_PHY_1186_DATA */ + 0x00037FFF /* DENALI_PHY_1187_DATA */ + 0x00004410 /* DENALI_PHY_1188_DATA */ + 0x00004410 /* DENALI_PHY_1189_DATA */ + 0x00004410 /* DENALI_PHY_1190_DATA */ + 0x00004410 /* DENALI_PHY_1191_DATA */ + 0x00004410 /* DENALI_PHY_1192_DATA */ + 0x00037FFF /* DENALI_PHY_1193_DATA */ + 0x00037FFF /* DENALI_PHY_1194_DATA */ + 0x00000000 /* DENALI_PHY_1195_DATA */ + 0x00000000 /* DENALI_PHY_1196_DATA */ + 0x00000000 /* DENALI_PHY_1197_DATA */ + 0x04000000 /* DENALI_PHY_1198_DATA */ + 0x00000000 /* DENALI_PHY_1199_DATA */ + 0x00000000 /* DENALI_PHY_1200_DATA */ + 0x00000108 /* DENALI_PHY_1201_DATA */ + 0x00000000 /* DENALI_PHY_1202_DATA */ + 0x00000000 /* DENALI_PHY_1203_DATA */ + 0x00000000 /* DENALI_PHY_1204_DATA */ + 0x00000001 /* DENALI_PHY_1205_DATA */ + 0x00000000 /* DENALI_PHY_1206_DATA */ + 0x00000000 /* DENALI_PHY_1207_DATA */ + 0x00000000 /* DENALI_PHY_1208_DATA */ + 0x00000000 /* DENALI_PHY_1209_DATA */ + 0x00000000 /* DENALI_PHY_1210_DATA */ + 0x00000000 /* DENALI_PHY_1211_DATA */ + 0x00020100 /* DENALI_PHY_1212_DATA */ + 0x00000000 /* DENALI_PHY_1213_DATA */ + 0x00000000 /* DENALI_PHY_1214_DATA */ + >; +}; diff --git a/arch/riscv/dts/hifive-unleashed-a00-u-boot.dtsi b/arch/riscv/dts/hifive-unleashed-a00-u-boot.dtsi index efa7cbb75d..af8c3e904c 100644 --- a/arch/riscv/dts/hifive-unleashed-a00-u-boot.dtsi +++ b/arch/riscv/dts/hifive-unleashed-a00-u-boot.dtsi @@ -4,6 +4,7 @@ */
#include "fu540-c000-u-boot.dtsi" +#include "fu540-hifive-unleashed-a00-sdram-ddr4.dtsi"
/ { hfclk {

On Sun, Mar 29, 2020 at 10:36 PM Pragnesh Patel pragnesh.patel@sifive.com wrote:
Add DDR controller and phy register settings, taken from fsbl (https://github.com/sifive/freedom-u540-c000-bootloader.git)
Signed-off-by: Pragnesh Patel pragnesh.patel@sifive.com
arch/riscv/dts/fu540-c000-u-boot.dtsi | 7 +
separate patch
...fu540-hifive-unleashed-a00-sdram-ddr4.dtsi | 1489 +++++++++++++++++
separate patch
.../dts/hifive-unleashed-a00-u-boot.dtsi | 1 +
squash with SPL support patch.
Jagan.

Hi Jagan,
-----Original Message----- From: Jagan Teki jagan@amarulasolutions.com Sent: 07 April 2020 01:00 To: Pragnesh Patel pragnesh.patel@sifive.com Cc: U-Boot-Denx u-boot@lists.denx.de; Atish Patra atish.patra@wdc.com; palmerdabbelt@google.com; Bin Meng bmeng.cn@gmail.com; Paul Walmsley paul.walmsley@sifive.com; Troy Benjegerdes troy.benjegerdes@sifive.com; Anup Patel anup.patel@wdc.com; Sagar Kadam sagar.kadam@sifive.com; Rick Chen rick@andestech.com Subject: Re: [PATCH v6 07/17] sifive: dts: fu540: Add DDR controller and phy register settings
[External Email] Do not click links or attachments unless you recognize the sender and know the content is safe
On Sun, Mar 29, 2020 at 10:36 PM Pragnesh Patel pragnesh.patel@sifive.com wrote:
Add DDR controller and phy register settings, taken from fsbl (https://github.com/sifive/freedom-u540-c000-bootloader.git)
Signed-off-by: Pragnesh Patel pragnesh.patel@sifive.com
arch/riscv/dts/fu540-c000-u-boot.dtsi | 7 +
separate patch
...fu540-hifive-unleashed-a00-sdram-ddr4.dtsi | 1489 +++++++++++++++++
separate patch
.../dts/hifive-unleashed-a00-u-boot.dtsi | 1 +
squash with SPL support patch.
Will update all in v7.
Jagan.

Added clock enable and disable functions in prci ops
Signed-off-by: Pragnesh Patel pragnesh.patel@sifive.com --- drivers/clk/sifive/fu540-prci.c | 100 ++++++++++++++++++++++++++++---- 1 file changed, 88 insertions(+), 12 deletions(-)
diff --git a/drivers/clk/sifive/fu540-prci.c b/drivers/clk/sifive/fu540-prci.c index 8847178001..e6214cd821 100644 --- a/drivers/clk/sifive/fu540-prci.c +++ b/drivers/clk/sifive/fu540-prci.c @@ -68,6 +68,11 @@ #define PRCI_COREPLLCFG0_LOCK_SHIFT 31 #define PRCI_COREPLLCFG0_LOCK_MASK (0x1 << PRCI_COREPLLCFG0_LOCK_SHIFT)
+/* COREPLLCFG1 */ +#define PRCI_COREPLLCFG1_OFFSET 0x8 +#define PRCI_COREPLLCFG1_CKE_SHIFT 31 +#define PRCI_COREPLLCFG1_CKE_MASK (0x1 << PRCI_COREPLLCFG1_CKE_SHIFT) + /* DDRPLLCFG0 */ #define PRCI_DDRPLLCFG0_OFFSET 0xc #define PRCI_DDRPLLCFG0_DIVR_SHIFT 0 @@ -87,7 +92,7 @@
/* DDRPLLCFG1 */ #define PRCI_DDRPLLCFG1_OFFSET 0x10 -#define PRCI_DDRPLLCFG1_CKE_SHIFT 24 +#define PRCI_DDRPLLCFG1_CKE_SHIFT 31 #define PRCI_DDRPLLCFG1_CKE_MASK (0x1 << PRCI_DDRPLLCFG1_CKE_SHIFT)
/* GEMGXLPLLCFG0 */ @@ -114,7 +119,7 @@
/* GEMGXLPLLCFG1 */ #define PRCI_GEMGXLPLLCFG1_OFFSET 0x20 -#define PRCI_GEMGXLPLLCFG1_CKE_SHIFT 24 +#define PRCI_GEMGXLPLLCFG1_CKE_SHIFT 31 #define PRCI_GEMGXLPLLCFG1_CKE_MASK (0x1 << PRCI_GEMGXLPLLCFG1_CKE_SHIFT)
/* CORECLKSEL */ @@ -142,7 +147,7 @@ (0x1 << PRCI_DEVICESRESETREG_GEMGXL_RST_N_SHIFT)
/* CLKMUXSTATUSREG */ -#define PRCI_CLKMUXSTATUSREG_OFFSET 0x2c +#define PRCI_CLKMUXSTATUSREG_OFFSET 0x2c #define PRCI_CLKMUXSTATUSREG_TLCLKSEL_STATUS_SHIFT 1 #define PRCI_CLKMUXSTATUSREG_TLCLKSEL_STATUS_MASK \ (0x1 << PRCI_CLKMUXSTATUSREG_TLCLKSEL_STATUS_SHIFT) @@ -170,6 +175,7 @@ struct __prci_data { * @enable_bypass: fn ptr to code to bypass the WRPLL (if applicable; else NULL) * @disable_bypass: fn ptr to code to not bypass the WRPLL (or NULL) * @cfg0_offs: WRPLL CFG0 register offset (in bytes) from the PRCI base address + * @cfg1_offs: WRPLL CFG1 register offset (in bytes) from the PRCI base address * * @enable_bypass and @disable_bypass are used for WRPLL instances * that contain a separate external glitchless clock mux downstream @@ -180,6 +186,7 @@ struct __prci_wrpll_data { void (*enable_bypass)(struct __prci_data *pd); void (*disable_bypass)(struct __prci_data *pd); u8 cfg0_offs; + u8 cfg1_offs; };
struct __prci_clock; @@ -194,6 +201,7 @@ struct __prci_clock_ops { unsigned long *parent_rate); unsigned long (*recalc_rate)(struct __prci_clock *pc, unsigned long parent_rate); + int (*enable_clk)(struct __prci_clock *pc, bool enable); };
/** @@ -316,7 +324,7 @@ static u32 __prci_wrpll_pack(const struct wrpll_cfg *c) }
/** - * __prci_wrpll_read_cfg() - read the WRPLL configuration from the PRCI + * __prci_wrpll_read_cfg0() - read the WRPLL configuration from the PRCI * @pd: PRCI context * @pwd: PRCI WRPLL metadata * @@ -327,14 +335,14 @@ static u32 __prci_wrpll_pack(const struct wrpll_cfg *c) * Context: Any context. Caller must prevent the records pointed to by * @pd and @pwd from changing during execution. */ -static void __prci_wrpll_read_cfg(struct __prci_data *pd, - struct __prci_wrpll_data *pwd) +static void __prci_wrpll_read_cfg0(struct __prci_data *pd, + struct __prci_wrpll_data *pwd) { __prci_wrpll_unpack(&pwd->c, __prci_readl(pd, pwd->cfg0_offs)); }
/** - * __prci_wrpll_write_cfg() - write WRPLL configuration into the PRCI + * __prci_wrpll_write_cfg0() - write WRPLL configuration into the PRCI * @pd: PRCI context * @pwd: PRCI WRPLL metadata * @c: WRPLL configuration record to write @@ -347,15 +355,29 @@ static void __prci_wrpll_read_cfg(struct __prci_data *pd, * Context: Any context. Caller must prevent the records pointed to by * @pd and @pwd from changing during execution. */ -static void __prci_wrpll_write_cfg(struct __prci_data *pd, - struct __prci_wrpll_data *pwd, - struct wrpll_cfg *c) +static void __prci_wrpll_write_cfg0(struct __prci_data *pd, + struct __prci_wrpll_data *pwd, + struct wrpll_cfg *c) { __prci_writel(__prci_wrpll_pack(c), pwd->cfg0_offs, pd);
memcpy(&pwd->c, c, sizeof(*c)); }
+/** + * __prci_wrpll_write_cfg1() - write Clock enable/disable configuration + * into the PRCI + * @pd: PRCI context + * @pwd: PRCI WRPLL metadata + * @enable: Clock enable or disable value + */ +static void __prci_wrpll_write_cfg1(struct __prci_data *pd, + struct __prci_wrpll_data *pwd, + u32 enable) +{ + __prci_writel(enable, pwd->cfg1_offs, pd); +} + /* Core clock mux control */
/** @@ -437,7 +459,7 @@ static int sifive_fu540_prci_wrpll_set_rate(struct __prci_clock *pc, if (pwd->enable_bypass) pwd->enable_bypass(pd);
- __prci_wrpll_write_cfg(pd, pwd, &pwd->c); + __prci_wrpll_write_cfg0(pd, pwd, &pwd->c);
udelay(wrpll_calc_max_lock_us(&pwd->c));
@@ -447,14 +469,35 @@ static int sifive_fu540_prci_wrpll_set_rate(struct __prci_clock *pc, return 0; }
+static int sifive_fu540_prci_clock_enable(struct __prci_clock *pc, bool enable) +{ + struct __prci_wrpll_data *pwd = pc->pwd; + struct __prci_data *pd = pc->pd; + + if (enable) { + __prci_wrpll_write_cfg1(pd, pwd, PRCI_COREPLLCFG1_CKE_MASK); + } else { + u32 r; + + r = __prci_readl(pd, pwd->cfg1_offs); + r &= ~PRCI_COREPLLCFG1_CKE_MASK; + + __prci_wrpll_write_cfg1(pd, pwd, r); + } + + return 0; +} + static const struct __prci_clock_ops sifive_fu540_prci_wrpll_clk_ops = { .set_rate = sifive_fu540_prci_wrpll_set_rate, .round_rate = sifive_fu540_prci_wrpll_round_rate, .recalc_rate = sifive_fu540_prci_wrpll_recalc_rate, + .enable_clk = sifive_fu540_prci_clock_enable, };
static const struct __prci_clock_ops sifive_fu540_prci_wrpll_ro_clk_ops = { .recalc_rate = sifive_fu540_prci_wrpll_recalc_rate, + .enable_clk = sifive_fu540_prci_clock_enable, };
/* TLCLKSEL clock integration */ @@ -484,16 +527,19 @@ static const struct __prci_clock_ops sifive_fu540_prci_tlclksel_clk_ops = {
static struct __prci_wrpll_data __prci_corepll_data = { .cfg0_offs = PRCI_COREPLLCFG0_OFFSET, + .cfg1_offs = PRCI_COREPLLCFG1_OFFSET, .enable_bypass = __prci_coreclksel_use_hfclk, .disable_bypass = __prci_coreclksel_use_corepll, };
static struct __prci_wrpll_data __prci_ddrpll_data = { .cfg0_offs = PRCI_DDRPLLCFG0_OFFSET, + .cfg1_offs = PRCI_DDRPLLCFG1_OFFSET, };
static struct __prci_wrpll_data __prci_gemgxlpll_data = { .cfg0_offs = PRCI_GEMGXLPLLCFG0_OFFSET, + .cfg1_offs = PRCI_GEMGXLPLLCFG1_OFFSET, };
/* @@ -580,6 +626,34 @@ static ulong sifive_fu540_prci_set_rate(struct clk *clk, ulong rate) return rate; }
+static int sifive_fu540_prci_enable(struct clk *clk) +{ + struct __prci_clock *pc; + + if (ARRAY_SIZE(__prci_init_clocks) <= clk->id) + return -ENXIO; + + pc = &__prci_init_clocks[clk->id]; + if (!pc->pd || !pc->ops->enable_clk) + return -ENXIO; + + return pc->ops->enable_clk(pc, 1); +} + +static int sifive_fu540_prci_disable(struct clk *clk) +{ + struct __prci_clock *pc; + + if (ARRAY_SIZE(__prci_init_clocks) <= clk->id) + return -ENXIO; + + pc = &__prci_init_clocks[clk->id]; + if (!pc->pd || !pc->ops->enable_clk) + return -ENXIO; + + return pc->ops->enable_clk(pc, 0); +} + static int sifive_fu540_prci_probe(struct udevice *dev) { int i, err; @@ -602,7 +676,7 @@ static int sifive_fu540_prci_probe(struct udevice *dev) pc = &__prci_init_clocks[i]; pc->pd = pd; if (pc->pwd) - __prci_wrpll_read_cfg(pd, pc->pwd); + __prci_wrpll_read_cfg0(pd, pc->pwd); }
return 0; @@ -611,6 +685,8 @@ static int sifive_fu540_prci_probe(struct udevice *dev) static struct clk_ops sifive_fu540_prci_ops = { .set_rate = sifive_fu540_prci_set_rate, .get_rate = sifive_fu540_prci_get_rate, + .enable = sifive_fu540_prci_enable, + .disable = sifive_fu540_prci_disable, };
static const struct udevice_id sifive_fu540_prci_ids[] = {

On Mon, Mar 30, 2020 at 1:07 AM Pragnesh Patel pragnesh.patel@sifive.com wrote:
Added clock enable and disable functions in prci ops
Signed-off-by: Pragnesh Patel pragnesh.patel@sifive.com
drivers/clk/sifive/fu540-prci.c | 100 ++++++++++++++++++++++++++++---- 1 file changed, 88 insertions(+), 12 deletions(-)
Reviewed-by: Bin Meng bmeng.cn@gmail.com

Set corepll, ddrpll and ethernet PLL for u-boot-spl
Signed-off-by: Pragnesh Patel pragnesh.patel@sifive.com --- drivers/clk/sifive/fu540-prci.c | 118 ++++++++++++++++++++++++++++++++ 1 file changed, 118 insertions(+)
diff --git a/drivers/clk/sifive/fu540-prci.c b/drivers/clk/sifive/fu540-prci.c index e6214cd821..3a73c2c8d1 100644 --- a/drivers/clk/sifive/fu540-prci.c +++ b/drivers/clk/sifive/fu540-prci.c @@ -41,6 +41,10 @@ #include <linux/clk/analogbits-wrpll-cln28hpc.h> #include <dt-bindings/clock/sifive-fu540-prci.h>
+#define DDRCTLPLL_F 55 +#define DDRCTLPLL_Q 2 +#define MHz 1000000 + /* * EXPECTED_CLK_PARENT_COUNT: how many parent clocks this driver expects: * hfclk and rtcclk @@ -152,6 +156,27 @@ #define PRCI_CLKMUXSTATUSREG_TLCLKSEL_STATUS_MASK \ (0x1 << PRCI_CLKMUXSTATUSREG_TLCLKSEL_STATUS_SHIFT)
+/* PROCMONCFG */ +#define PRCI_PROCMONCFG_OFFSET 0xF0 +#define PRCI_PROCMONCFG_CORE_CLOCK_SHIFT 24 +#define PRCI_PROCMONCFG_CORE_CLOCK_MASK \ + (0x1 << PRCI_PROCMONCFG_CORE_CLOCK_SHIFT) + +#define PLL_R(x) \ + ((x) << PRCI_DDRPLLCFG0_DIVR_SHIFT) & PRCI_DDRPLLCFG0_DIVR_MASK +#define PLL_F(x) \ + ((x) << PRCI_DDRPLLCFG0_DIVF_SHIFT) & PRCI_DDRPLLCFG0_DIVF_MASK +#define PLL_Q(x) \ + ((x) << PRCI_DDRPLLCFG0_DIVQ_SHIFT) & PRCI_DDRPLLCFG0_DIVQ_MASK +#define PLL_RANGE(x) \ + ((x) << PRCI_DDRPLLCFG0_RANGE_SHIFT) & PRCI_DDRPLLCFG0_RANGE_MASK +#define PLL_BYPASS(x) \ + ((x) << PRCI_DDRPLLCFG0_BYPASS_SHIFT) & PRCI_DDRPLLCFG0_BYPASS_MASK +#define PLL_FSE(x) \ + ((x) << PRCI_DDRPLLCFG0_FSE_SHIFT) & PRCI_DDRPLLCFG0_FSE_MASK +#define PLL_LOCK(x) \ + ((x) << PRCI_DDRPLLCFG0_LOCK_SHIFT) & PRCI_DDRPLLCFG0_LOCK_MASK + /* * Private structures */ @@ -654,6 +679,93 @@ static int sifive_fu540_prci_disable(struct clk *clk) return pc->ops->enable_clk(pc, 0); }
+#ifdef CONFIG_SPL_BUILD +static void corepll_init(struct udevice *dev) +{ + u32 v; + struct clk clock; + struct __prci_data *pd = dev_get_priv(dev); + + v = __prci_readl(pd, PRCI_CLKMUXSTATUSREG_OFFSET); + v &= PRCI_CLKMUXSTATUSREG_TLCLKSEL_STATUS_MASK; + + clock.id = PRCI_CLK_COREPLL; + + if (v) { + /* corepll 500 Mhz */ + sifive_fu540_prci_set_rate(&clock, 500UL * MHz); + } else { + /* corepll 1 Ghz */ + sifive_fu540_prci_set_rate(&clock, 1000UL * MHz); + } + + sifive_fu540_prci_clock_enable(&__prci_init_clocks[clock.id], 1); +} + +static void ddr_init(struct udevice *dev) +{ + u32 v; + struct clk clock; + struct __prci_data *pd = dev_get_priv(dev); + + //DDR init + u32 ddrctlmhz = + (PLL_R(0)) | + (PLL_F(DDRCTLPLL_F)) | + (PLL_Q(DDRCTLPLL_Q)) | + (PLL_RANGE(0x4)) | + (PLL_BYPASS(0)) | + (PLL_FSE(1)); + __prci_writel(ddrctlmhz, PRCI_DDRPLLCFG0_OFFSET, pd); + + clock.id = PRCI_CLK_DDRPLL; + sifive_fu540_prci_clock_enable(&__prci_init_clocks[clock.id], 1); + + /* Release DDR reset */ + v = __prci_readl(pd, PRCI_DEVICESRESETREG_OFFSET); + v |= PRCI_DEVICESRESETREG_DDR_CTRL_RST_N_MASK; + __prci_writel(v, PRCI_DEVICESRESETREG_OFFSET, pd); + + // HACK to get the '1 full controller clock cycle'. + asm volatile ("fence"); + v = __prci_readl(pd, PRCI_DEVICESRESETREG_OFFSET); + v |= (PRCI_DEVICESRESETREG_DDR_AXI_RST_N_MASK | + PRCI_DEVICESRESETREG_DDR_AHB_RST_N_MASK | + PRCI_DEVICESRESETREG_DDR_PHY_RST_N_MASK); + __prci_writel(v, PRCI_DEVICESRESETREG_OFFSET, pd); + // 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"); +} + +static void ethernet_init(struct udevice *dev) +{ + u32 v; + struct clk clock; + struct __prci_data *pd = dev_get_priv(dev); + + /* GEMGXL init */ + clock.id = PRCI_CLK_GEMGXLPLL; + sifive_fu540_prci_set_rate(&clock, 125UL * MHz); + sifive_fu540_prci_clock_enable(&__prci_init_clocks[clock.id], 1); + + /* Release GEMGXL reset */ + v = __prci_readl(pd, PRCI_DEVICESRESETREG_OFFSET); + v |= PRCI_DEVICESRESETREG_GEMGXL_RST_N_MASK; + __prci_writel(v, PRCI_DEVICESRESETREG_OFFSET, pd); + + /* Procmon => core clock */ + __prci_writel(PRCI_PROCMONCFG_CORE_CLOCK_MASK, PRCI_PROCMONCFG_OFFSET, + pd); +} +#endif + static int sifive_fu540_prci_probe(struct udevice *dev) { int i, err; @@ -679,6 +791,12 @@ static int sifive_fu540_prci_probe(struct udevice *dev) __prci_wrpll_read_cfg0(pd, pc->pwd); }
+#ifdef CONFIG_SPL_BUILD + corepll_init(dev); + ddr_init(dev); + ethernet_init(dev); +#endif + return 0; }

On Sun, Mar 29, 2020 at 10:37 PM Pragnesh Patel pragnesh.patel@sifive.com wrote:
Set corepll, ddrpll and ethernet PLL for u-boot-spl
Signed-off-by: Pragnesh Patel pragnesh.patel@sifive.com
drivers/clk/sifive/fu540-prci.c | 118 ++++++++++++++++++++++++++++++++ 1 file changed, 118 insertions(+)
diff --git a/drivers/clk/sifive/fu540-prci.c b/drivers/clk/sifive/fu540-prci.c index e6214cd821..3a73c2c8d1 100644 --- a/drivers/clk/sifive/fu540-prci.c +++ b/drivers/clk/sifive/fu540-prci.c @@ -41,6 +41,10 @@ #include <linux/clk/analogbits-wrpll-cln28hpc.h> #include <dt-bindings/clock/sifive-fu540-prci.h>
+#define DDRCTLPLL_F 55 +#define DDRCTLPLL_Q 2 +#define MHz 1000000
/*
- EXPECTED_CLK_PARENT_COUNT: how many parent clocks this driver expects:
hfclk and rtcclk
@@ -152,6 +156,27 @@ #define PRCI_CLKMUXSTATUSREG_TLCLKSEL_STATUS_MASK \ (0x1 << PRCI_CLKMUXSTATUSREG_TLCLKSEL_STATUS_SHIFT)
+/* PROCMONCFG */ +#define PRCI_PROCMONCFG_OFFSET 0xF0 +#define PRCI_PROCMONCFG_CORE_CLOCK_SHIFT 24 +#define PRCI_PROCMONCFG_CORE_CLOCK_MASK \
(0x1 << PRCI_PROCMONCFG_CORE_CLOCK_SHIFT)
+#define PLL_R(x) \
((x) << PRCI_DDRPLLCFG0_DIVR_SHIFT) & PRCI_DDRPLLCFG0_DIVR_MASK
+#define PLL_F(x) \
((x) << PRCI_DDRPLLCFG0_DIVF_SHIFT) & PRCI_DDRPLLCFG0_DIVF_MASK
+#define PLL_Q(x) \
((x) << PRCI_DDRPLLCFG0_DIVQ_SHIFT) & PRCI_DDRPLLCFG0_DIVQ_MASK
+#define PLL_RANGE(x) \
((x) << PRCI_DDRPLLCFG0_RANGE_SHIFT) & PRCI_DDRPLLCFG0_RANGE_MASK
+#define PLL_BYPASS(x) \
((x) << PRCI_DDRPLLCFG0_BYPASS_SHIFT) & PRCI_DDRPLLCFG0_BYPASS_MASK
+#define PLL_FSE(x) \
((x) << PRCI_DDRPLLCFG0_FSE_SHIFT) & PRCI_DDRPLLCFG0_FSE_MASK
+#define PLL_LOCK(x) \
((x) << PRCI_DDRPLLCFG0_LOCK_SHIFT) & PRCI_DDRPLLCFG0_LOCK_MASK
/*
- Private structures
*/ @@ -654,6 +679,93 @@ static int sifive_fu540_prci_disable(struct clk *clk) return pc->ops->enable_clk(pc, 0); }
+#ifdef CONFIG_SPL_BUILD +static void corepll_init(struct udevice *dev) +{
u32 v;
struct clk clock;
struct __prci_data *pd = dev_get_priv(dev);
v = __prci_readl(pd, PRCI_CLKMUXSTATUSREG_OFFSET);
v &= PRCI_CLKMUXSTATUSREG_TLCLKSEL_STATUS_MASK;
clock.id = PRCI_CLK_COREPLL;
if (v) {
/* corepll 500 Mhz */
sifive_fu540_prci_set_rate(&clock, 500UL * MHz);
} else {
/* corepll 1 Ghz */
sifive_fu540_prci_set_rate(&clock, 1000UL * MHz);
}
sifive_fu540_prci_clock_enable(&__prci_init_clocks[clock.id], 1);
+}
+static void ddr_init(struct udevice *dev) +{
u32 v;
struct clk clock;
struct __prci_data *pd = dev_get_priv(dev);
//DDR init
u32 ddrctlmhz =
(PLL_R(0)) |
(PLL_F(DDRCTLPLL_F)) |
(PLL_Q(DDRCTLPLL_Q)) |
(PLL_RANGE(0x4)) |
(PLL_BYPASS(0)) |
(PLL_FSE(1));
__prci_writel(ddrctlmhz, PRCI_DDRPLLCFG0_OFFSET, pd);
clock.id = PRCI_CLK_DDRPLL;
sifive_fu540_prci_clock_enable(&__prci_init_clocks[clock.id], 1);
/* Release DDR reset */
v = __prci_readl(pd, PRCI_DEVICESRESETREG_OFFSET);
v |= PRCI_DEVICESRESETREG_DDR_CTRL_RST_N_MASK;
__prci_writel(v, PRCI_DEVICESRESETREG_OFFSET, pd);
// HACK to get the '1 full controller clock cycle'.
asm volatile ("fence");
v = __prci_readl(pd, PRCI_DEVICESRESETREG_OFFSET);
v |= (PRCI_DEVICESRESETREG_DDR_AXI_RST_N_MASK |
PRCI_DEVICESRESETREG_DDR_AHB_RST_N_MASK |
PRCI_DEVICESRESETREG_DDR_PHY_RST_N_MASK);
__prci_writel(v, PRCI_DEVICESRESETREG_OFFSET, pd);
// 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");
+}
+static void ethernet_init(struct udevice *dev) +{
u32 v;
struct clk clock;
struct __prci_data *pd = dev_get_priv(dev);
/* GEMGXL init */
clock.id = PRCI_CLK_GEMGXLPLL;
sifive_fu540_prci_set_rate(&clock, 125UL * MHz);
sifive_fu540_prci_clock_enable(&__prci_init_clocks[clock.id], 1);
/* Release GEMGXL reset */
v = __prci_readl(pd, PRCI_DEVICESRESETREG_OFFSET);
v |= PRCI_DEVICESRESETREG_GEMGXL_RST_N_MASK;
__prci_writel(v, PRCI_DEVICESRESETREG_OFFSET, pd);
/* Procmon => core clock */
__prci_writel(PRCI_PROCMONCFG_CORE_CLOCK_MASK, PRCI_PROCMONCFG_OFFSET,
pd);
+} +#endif
static int sifive_fu540_prci_probe(struct udevice *dev) { int i, err; @@ -679,6 +791,12 @@ static int sifive_fu540_prci_probe(struct udevice *dev) __prci_wrpll_read_cfg0(pd, pc->pwd); }
+#ifdef CONFIG_SPL_BUILD
corepll_init(dev);
ddr_init(dev);
ethernet_init(dev);
+#endif
1. Why would ethernet clocks require for SPL 2. Why these clocks are special for SPL, can't we use it for U-Boot proper 3. This look like raw clock initialization instead of having in conventional dm way. since these are here just to use pd. May be reuse the required clock of what u-boot proper using or move them into spl code.
Jagan.

Hi Jagan, Pragnesh,
On Tue, Apr 7, 2020 at 3:35 AM Jagan Teki jagan@amarulasolutions.com wrote:
On Sun, Mar 29, 2020 at 10:37 PM Pragnesh Patel pragnesh.patel@sifive.com wrote:
Set corepll, ddrpll and ethernet PLL for u-boot-spl
Signed-off-by: Pragnesh Patel pragnesh.patel@sifive.com
drivers/clk/sifive/fu540-prci.c | 118 ++++++++++++++++++++++++++++++++ 1 file changed, 118 insertions(+)
diff --git a/drivers/clk/sifive/fu540-prci.c b/drivers/clk/sifive/fu540-prci.c index e6214cd821..3a73c2c8d1 100644 --- a/drivers/clk/sifive/fu540-prci.c +++ b/drivers/clk/sifive/fu540-prci.c @@ -41,6 +41,10 @@ #include <linux/clk/analogbits-wrpll-cln28hpc.h> #include <dt-bindings/clock/sifive-fu540-prci.h>
+#define DDRCTLPLL_F 55 +#define DDRCTLPLL_Q 2 +#define MHz 1000000
/*
- EXPECTED_CLK_PARENT_COUNT: how many parent clocks this driver expects:
hfclk and rtcclk
@@ -152,6 +156,27 @@ #define PRCI_CLKMUXSTATUSREG_TLCLKSEL_STATUS_MASK \ (0x1 << PRCI_CLKMUXSTATUSREG_TLCLKSEL_STATUS_SHIFT)
+/* PROCMONCFG */ +#define PRCI_PROCMONCFG_OFFSET 0xF0 +#define PRCI_PROCMONCFG_CORE_CLOCK_SHIFT 24 +#define PRCI_PROCMONCFG_CORE_CLOCK_MASK \
(0x1 << PRCI_PROCMONCFG_CORE_CLOCK_SHIFT)
+#define PLL_R(x) \
((x) << PRCI_DDRPLLCFG0_DIVR_SHIFT) & PRCI_DDRPLLCFG0_DIVR_MASK
+#define PLL_F(x) \
((x) << PRCI_DDRPLLCFG0_DIVF_SHIFT) & PRCI_DDRPLLCFG0_DIVF_MASK
+#define PLL_Q(x) \
((x) << PRCI_DDRPLLCFG0_DIVQ_SHIFT) & PRCI_DDRPLLCFG0_DIVQ_MASK
+#define PLL_RANGE(x) \
((x) << PRCI_DDRPLLCFG0_RANGE_SHIFT) & PRCI_DDRPLLCFG0_RANGE_MASK
+#define PLL_BYPASS(x) \
((x) << PRCI_DDRPLLCFG0_BYPASS_SHIFT) & PRCI_DDRPLLCFG0_BYPASS_MASK
+#define PLL_FSE(x) \
((x) << PRCI_DDRPLLCFG0_FSE_SHIFT) & PRCI_DDRPLLCFG0_FSE_MASK
+#define PLL_LOCK(x) \
((x) << PRCI_DDRPLLCFG0_LOCK_SHIFT) & PRCI_DDRPLLCFG0_LOCK_MASK
/*
- Private structures
*/ @@ -654,6 +679,93 @@ static int sifive_fu540_prci_disable(struct clk *clk) return pc->ops->enable_clk(pc, 0); }
+#ifdef CONFIG_SPL_BUILD +static void corepll_init(struct udevice *dev) +{
u32 v;
struct clk clock;
struct __prci_data *pd = dev_get_priv(dev);
v = __prci_readl(pd, PRCI_CLKMUXSTATUSREG_OFFSET);
v &= PRCI_CLKMUXSTATUSREG_TLCLKSEL_STATUS_MASK;
clock.id = PRCI_CLK_COREPLL;
if (v) {
/* corepll 500 Mhz */
sifive_fu540_prci_set_rate(&clock, 500UL * MHz);
} else {
/* corepll 1 Ghz */
sifive_fu540_prci_set_rate(&clock, 1000UL * MHz);
}
sifive_fu540_prci_clock_enable(&__prci_init_clocks[clock.id], 1);
+}
+static void ddr_init(struct udevice *dev) +{
u32 v;
struct clk clock;
struct __prci_data *pd = dev_get_priv(dev);
//DDR init
u32 ddrctlmhz =
(PLL_R(0)) |
(PLL_F(DDRCTLPLL_F)) |
(PLL_Q(DDRCTLPLL_Q)) |
(PLL_RANGE(0x4)) |
(PLL_BYPASS(0)) |
(PLL_FSE(1));
__prci_writel(ddrctlmhz, PRCI_DDRPLLCFG0_OFFSET, pd);
clock.id = PRCI_CLK_DDRPLL;
sifive_fu540_prci_clock_enable(&__prci_init_clocks[clock.id], 1);
/* Release DDR reset */
v = __prci_readl(pd, PRCI_DEVICESRESETREG_OFFSET);
v |= PRCI_DEVICESRESETREG_DDR_CTRL_RST_N_MASK;
__prci_writel(v, PRCI_DEVICESRESETREG_OFFSET, pd);
// HACK to get the '1 full controller clock cycle'.
asm volatile ("fence");
v = __prci_readl(pd, PRCI_DEVICESRESETREG_OFFSET);
v |= (PRCI_DEVICESRESETREG_DDR_AXI_RST_N_MASK |
PRCI_DEVICESRESETREG_DDR_AHB_RST_N_MASK |
PRCI_DEVICESRESETREG_DDR_PHY_RST_N_MASK);
__prci_writel(v, PRCI_DEVICESRESETREG_OFFSET, pd);
// 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");
+}
+static void ethernet_init(struct udevice *dev) +{
u32 v;
struct clk clock;
struct __prci_data *pd = dev_get_priv(dev);
/* GEMGXL init */
clock.id = PRCI_CLK_GEMGXLPLL;
sifive_fu540_prci_set_rate(&clock, 125UL * MHz);
sifive_fu540_prci_clock_enable(&__prci_init_clocks[clock.id], 1);
/* Release GEMGXL reset */
v = __prci_readl(pd, PRCI_DEVICESRESETREG_OFFSET);
v |= PRCI_DEVICESRESETREG_GEMGXL_RST_N_MASK;
__prci_writel(v, PRCI_DEVICESRESETREG_OFFSET, pd);
/* Procmon => core clock */
__prci_writel(PRCI_PROCMONCFG_CORE_CLOCK_MASK, PRCI_PROCMONCFG_OFFSET,
pd);
+} +#endif
static int sifive_fu540_prci_probe(struct udevice *dev) { int i, err; @@ -679,6 +791,12 @@ static int sifive_fu540_prci_probe(struct udevice *dev) __prci_wrpll_read_cfg0(pd, pc->pwd); }
+#ifdef CONFIG_SPL_BUILD
corepll_init(dev);
ddr_init(dev);
ethernet_init(dev);
+#endif
- Why would ethernet clocks require for SPL
- Why these clocks are special for SPL, can't we use it for U-Boot proper
- This look like raw clock initialization instead of having in
conventional dm way. since these are here just to use pd. May be reuse the required clock of what u-boot proper using or move them into spl code.
I believe Jagan's comments are the same as mine that was mentioned in previous version:
See https://patchwork.ozlabs.org/project/uboot/patch/20200311070320.21323-10-pra...
Regards, Bin

Hi Bin, Jagan
-----Original Message----- From: Bin Meng bmeng.cn@gmail.com Sent: 20 April 2020 14:30 To: Jagan Teki jagan@amarulasolutions.com Cc: Pragnesh Patel pragnesh.patel@sifive.com; U-Boot-Denx <u- boot@lists.denx.de>; Atish Patra atish.patra@wdc.com; Palmer Dabbelt palmerdabbelt@google.com; Paul Walmsley paul.walmsley@sifive.com; Troy Benjegerdes troy.benjegerdes@sifive.com; Anup Patel anup.patel@wdc.com; Sagar Kadam sagar.kadam@sifive.com; Rick Chen rick@andestech.com; Lukasz Majewski lukma@denx.de; Simon Glass sjg@chromium.org Subject: Re: [PATCH v6 09/17] clk: sifive: fu540-prci: Add clock initialization for SPL
[External Email] Do not click links or attachments unless you recognize the sender and know the content is safe
Hi Jagan, Pragnesh,
On Tue, Apr 7, 2020 at 3:35 AM Jagan Teki jagan@amarulasolutions.com wrote:
On Sun, Mar 29, 2020 at 10:37 PM Pragnesh Patel pragnesh.patel@sifive.com wrote:
Set corepll, ddrpll and ethernet PLL for u-boot-spl
Signed-off-by: Pragnesh Patel pragnesh.patel@sifive.com
drivers/clk/sifive/fu540-prci.c | 118 ++++++++++++++++++++++++++++++++ 1 file changed, 118 insertions(+)
diff --git a/drivers/clk/sifive/fu540-prci.c b/drivers/clk/sifive/fu540-prci.c index e6214cd821..3a73c2c8d1 100644 --- a/drivers/clk/sifive/fu540-prci.c +++ b/drivers/clk/sifive/fu540-prci.c @@ -41,6 +41,10 @@ #include <linux/clk/analogbits-wrpll-cln28hpc.h> #include <dt-bindings/clock/sifive-fu540-prci.h>
+#define DDRCTLPLL_F 55 +#define DDRCTLPLL_Q 2 +#define MHz 1000000
/*
- EXPECTED_CLK_PARENT_COUNT: how many parent clocks this driver
expects:
hfclk and rtcclk
@@ -152,6 +156,27 @@ #define PRCI_CLKMUXSTATUSREG_TLCLKSEL_STATUS_MASK \ (0x1 << PRCI_CLKMUXSTATUSREG_TLCLKSEL_STATUS_SHIFT)
+/* PROCMONCFG */ +#define PRCI_PROCMONCFG_OFFSET 0xF0 +#define PRCI_PROCMONCFG_CORE_CLOCK_SHIFT 24 +#define PRCI_PROCMONCFG_CORE_CLOCK_MASK \
(0x1 << PRCI_PROCMONCFG_CORE_CLOCK_SHIFT)
+#define PLL_R(x) \
((x) << PRCI_DDRPLLCFG0_DIVR_SHIFT) &
+PRCI_DDRPLLCFG0_DIVR_MASK #define PLL_F(x) \
((x) << PRCI_DDRPLLCFG0_DIVF_SHIFT) &
+PRCI_DDRPLLCFG0_DIVF_MASK #define PLL_Q(x) \
((x) << PRCI_DDRPLLCFG0_DIVQ_SHIFT) &
+PRCI_DDRPLLCFG0_DIVQ_MASK #define PLL_RANGE(x) \
((x) << PRCI_DDRPLLCFG0_RANGE_SHIFT) &
+PRCI_DDRPLLCFG0_RANGE_MASK #define PLL_BYPASS(x) \
((x) << PRCI_DDRPLLCFG0_BYPASS_SHIFT) &
+PRCI_DDRPLLCFG0_BYPASS_MASK #define PLL_FSE(x) \
((x) << PRCI_DDRPLLCFG0_FSE_SHIFT) &
+PRCI_DDRPLLCFG0_FSE_MASK #define PLL_LOCK(x) \
((x) << PRCI_DDRPLLCFG0_LOCK_SHIFT) &
+PRCI_DDRPLLCFG0_LOCK_MASK
/*
- Private structures
*/ @@ -654,6 +679,93 @@ static int sifive_fu540_prci_disable(struct clk *clk) return pc->ops->enable_clk(pc, 0); }
+#ifdef CONFIG_SPL_BUILD +static void corepll_init(struct udevice *dev) {
u32 v;
struct clk clock;
struct __prci_data *pd = dev_get_priv(dev);
v = __prci_readl(pd, PRCI_CLKMUXSTATUSREG_OFFSET);
v &= PRCI_CLKMUXSTATUSREG_TLCLKSEL_STATUS_MASK;
clock.id = PRCI_CLK_COREPLL;
if (v) {
/* corepll 500 Mhz */
sifive_fu540_prci_set_rate(&clock, 500UL * MHz);
} else {
/* corepll 1 Ghz */
sifive_fu540_prci_set_rate(&clock, 1000UL * MHz);
}
+sifive_fu540_prci_clock_enable(&__prci_init_clocks[clock.id], 1); }
+static void ddr_init(struct udevice *dev) {
u32 v;
struct clk clock;
struct __prci_data *pd = dev_get_priv(dev);
//DDR init
u32 ddrctlmhz =
(PLL_R(0)) |
(PLL_F(DDRCTLPLL_F)) |
(PLL_Q(DDRCTLPLL_Q)) |
(PLL_RANGE(0x4)) |
(PLL_BYPASS(0)) |
(PLL_FSE(1));
__prci_writel(ddrctlmhz, PRCI_DDRPLLCFG0_OFFSET, pd);
clock.id = PRCI_CLK_DDRPLL;
- sifive_fu540_prci_clock_enable(&__prci_init_clocks[clock.id], 1);
/* Release DDR reset */
v = __prci_readl(pd, PRCI_DEVICESRESETREG_OFFSET);
v |= PRCI_DEVICESRESETREG_DDR_CTRL_RST_N_MASK;
__prci_writel(v, PRCI_DEVICESRESETREG_OFFSET, pd);
// HACK to get the '1 full controller clock cycle'.
asm volatile ("fence");
v = __prci_readl(pd, PRCI_DEVICESRESETREG_OFFSET);
v |= (PRCI_DEVICESRESETREG_DDR_AXI_RST_N_MASK |
PRCI_DEVICESRESETREG_DDR_AHB_RST_N_MASK |
PRCI_DEVICESRESETREG_DDR_PHY_RST_N_MASK);
__prci_writel(v, PRCI_DEVICESRESETREG_OFFSET, pd);
// 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"); }
+static void ethernet_init(struct udevice *dev) {
u32 v;
struct clk clock;
struct __prci_data *pd = dev_get_priv(dev);
/* GEMGXL init */
clock.id = PRCI_CLK_GEMGXLPLL;
sifive_fu540_prci_set_rate(&clock, 125UL * MHz);
- sifive_fu540_prci_clock_enable(&__prci_init_clocks[clock.id], 1);
/* Release GEMGXL reset */
v = __prci_readl(pd, PRCI_DEVICESRESETREG_OFFSET);
v |= PRCI_DEVICESRESETREG_GEMGXL_RST_N_MASK;
__prci_writel(v, PRCI_DEVICESRESETREG_OFFSET, pd);
/* Procmon => core clock */
__prci_writel(PRCI_PROCMONCFG_CORE_CLOCK_MASK,
PRCI_PROCMONCFG_OFFSET,
pd);
+} +#endif
static int sifive_fu540_prci_probe(struct udevice *dev) { int i, err; @@ -679,6 +791,12 @@ static int sifive_fu540_prci_probe(struct udevice
*dev)
__prci_wrpll_read_cfg0(pd, pc->pwd); }
+#ifdef CONFIG_SPL_BUILD
corepll_init(dev);
ddr_init(dev);
ethernet_init(dev);
+#endif
- Why would ethernet clocks require for SPL 2. Why these clocks are
special for SPL, can't we use it for U-Boot proper 3. This look like raw clock initialization instead of having in conventional dm way. since these are here just to use pd. May be reuse the required clock of what u-boot proper using or move them into spl code.
1. ethernet clock is not necessary for SPL but SPL performs ethernet PHY reset sequence (board/sifive/fu540/spl.c - "gem_phy_reset") and for that ethernet clock needs to be enabled.
2. There is nothing special of this clocks for SPL, we can use this for U-Boot. I am planning to add this clocks in device tree but I am not sure how to add coreclk (corepll) in device tree Do you guys have any suggestion for this ?
3. I am planning to make dm way.
Any suggestions are welcome
I believe Jagan's comments are the same as mine that was mentioned in previous version:
See https://patchwork.ozlabs.org/project/uboot/patch/20200311070320.21323- 10-pragnesh.patel@sifive.com/
Regards, Bin

Hi Pragnesh,
On Fri, Apr 24, 2020 at 6:08 PM Pragnesh Patel pragnesh.patel@sifive.com wrote:
Hi Bin, Jagan
-----Original Message----- From: Bin Meng bmeng.cn@gmail.com Sent: 20 April 2020 14:30 To: Jagan Teki jagan@amarulasolutions.com Cc: Pragnesh Patel pragnesh.patel@sifive.com; U-Boot-Denx <u- boot@lists.denx.de>; Atish Patra atish.patra@wdc.com; Palmer Dabbelt palmerdabbelt@google.com; Paul Walmsley paul.walmsley@sifive.com; Troy Benjegerdes troy.benjegerdes@sifive.com; Anup Patel anup.patel@wdc.com; Sagar Kadam sagar.kadam@sifive.com; Rick Chen rick@andestech.com; Lukasz Majewski lukma@denx.de; Simon Glass sjg@chromium.org Subject: Re: [PATCH v6 09/17] clk: sifive: fu540-prci: Add clock initialization for SPL
[External Email] Do not click links or attachments unless you recognize the sender and know the content is safe
Hi Jagan, Pragnesh,
On Tue, Apr 7, 2020 at 3:35 AM Jagan Teki jagan@amarulasolutions.com wrote:
On Sun, Mar 29, 2020 at 10:37 PM Pragnesh Patel pragnesh.patel@sifive.com wrote:
Set corepll, ddrpll and ethernet PLL for u-boot-spl
Signed-off-by: Pragnesh Patel pragnesh.patel@sifive.com
drivers/clk/sifive/fu540-prci.c | 118 ++++++++++++++++++++++++++++++++ 1 file changed, 118 insertions(+)
diff --git a/drivers/clk/sifive/fu540-prci.c b/drivers/clk/sifive/fu540-prci.c index e6214cd821..3a73c2c8d1 100644 --- a/drivers/clk/sifive/fu540-prci.c +++ b/drivers/clk/sifive/fu540-prci.c @@ -41,6 +41,10 @@ #include <linux/clk/analogbits-wrpll-cln28hpc.h> #include <dt-bindings/clock/sifive-fu540-prci.h>
+#define DDRCTLPLL_F 55 +#define DDRCTLPLL_Q 2 +#define MHz 1000000
/*
- EXPECTED_CLK_PARENT_COUNT: how many parent clocks this driver
expects:
hfclk and rtcclk
@@ -152,6 +156,27 @@ #define PRCI_CLKMUXSTATUSREG_TLCLKSEL_STATUS_MASK \ (0x1 << PRCI_CLKMUXSTATUSREG_TLCLKSEL_STATUS_SHIFT)
+/* PROCMONCFG */ +#define PRCI_PROCMONCFG_OFFSET 0xF0 +#define PRCI_PROCMONCFG_CORE_CLOCK_SHIFT 24 +#define PRCI_PROCMONCFG_CORE_CLOCK_MASK \
(0x1 << PRCI_PROCMONCFG_CORE_CLOCK_SHIFT)
+#define PLL_R(x) \
((x) << PRCI_DDRPLLCFG0_DIVR_SHIFT) &
+PRCI_DDRPLLCFG0_DIVR_MASK #define PLL_F(x) \
((x) << PRCI_DDRPLLCFG0_DIVF_SHIFT) &
+PRCI_DDRPLLCFG0_DIVF_MASK #define PLL_Q(x) \
((x) << PRCI_DDRPLLCFG0_DIVQ_SHIFT) &
+PRCI_DDRPLLCFG0_DIVQ_MASK #define PLL_RANGE(x) \
((x) << PRCI_DDRPLLCFG0_RANGE_SHIFT) &
+PRCI_DDRPLLCFG0_RANGE_MASK #define PLL_BYPASS(x) \
((x) << PRCI_DDRPLLCFG0_BYPASS_SHIFT) &
+PRCI_DDRPLLCFG0_BYPASS_MASK #define PLL_FSE(x) \
((x) << PRCI_DDRPLLCFG0_FSE_SHIFT) &
+PRCI_DDRPLLCFG0_FSE_MASK #define PLL_LOCK(x) \
((x) << PRCI_DDRPLLCFG0_LOCK_SHIFT) &
+PRCI_DDRPLLCFG0_LOCK_MASK
/*
- Private structures
*/ @@ -654,6 +679,93 @@ static int sifive_fu540_prci_disable(struct clk *clk) return pc->ops->enable_clk(pc, 0); }
+#ifdef CONFIG_SPL_BUILD +static void corepll_init(struct udevice *dev) {
u32 v;
struct clk clock;
struct __prci_data *pd = dev_get_priv(dev);
v = __prci_readl(pd, PRCI_CLKMUXSTATUSREG_OFFSET);
v &= PRCI_CLKMUXSTATUSREG_TLCLKSEL_STATUS_MASK;
clock.id = PRCI_CLK_COREPLL;
if (v) {
/* corepll 500 Mhz */
sifive_fu540_prci_set_rate(&clock, 500UL * MHz);
} else {
/* corepll 1 Ghz */
sifive_fu540_prci_set_rate(&clock, 1000UL * MHz);
}
+sifive_fu540_prci_clock_enable(&__prci_init_clocks[clock.id], 1); }
+static void ddr_init(struct udevice *dev) {
u32 v;
struct clk clock;
struct __prci_data *pd = dev_get_priv(dev);
//DDR init
u32 ddrctlmhz =
(PLL_R(0)) |
(PLL_F(DDRCTLPLL_F)) |
(PLL_Q(DDRCTLPLL_Q)) |
(PLL_RANGE(0x4)) |
(PLL_BYPASS(0)) |
(PLL_FSE(1));
__prci_writel(ddrctlmhz, PRCI_DDRPLLCFG0_OFFSET, pd);
clock.id = PRCI_CLK_DDRPLL;
- sifive_fu540_prci_clock_enable(&__prci_init_clocks[clock.id], 1);
/* Release DDR reset */
v = __prci_readl(pd, PRCI_DEVICESRESETREG_OFFSET);
v |= PRCI_DEVICESRESETREG_DDR_CTRL_RST_N_MASK;
__prci_writel(v, PRCI_DEVICESRESETREG_OFFSET, pd);
// HACK to get the '1 full controller clock cycle'.
asm volatile ("fence");
v = __prci_readl(pd, PRCI_DEVICESRESETREG_OFFSET);
v |= (PRCI_DEVICESRESETREG_DDR_AXI_RST_N_MASK |
PRCI_DEVICESRESETREG_DDR_AHB_RST_N_MASK |
PRCI_DEVICESRESETREG_DDR_PHY_RST_N_MASK);
__prci_writel(v, PRCI_DEVICESRESETREG_OFFSET, pd);
// 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"); }
+static void ethernet_init(struct udevice *dev) {
u32 v;
struct clk clock;
struct __prci_data *pd = dev_get_priv(dev);
/* GEMGXL init */
clock.id = PRCI_CLK_GEMGXLPLL;
sifive_fu540_prci_set_rate(&clock, 125UL * MHz);
- sifive_fu540_prci_clock_enable(&__prci_init_clocks[clock.id], 1);
/* Release GEMGXL reset */
v = __prci_readl(pd, PRCI_DEVICESRESETREG_OFFSET);
v |= PRCI_DEVICESRESETREG_GEMGXL_RST_N_MASK;
__prci_writel(v, PRCI_DEVICESRESETREG_OFFSET, pd);
/* Procmon => core clock */
__prci_writel(PRCI_PROCMONCFG_CORE_CLOCK_MASK,
PRCI_PROCMONCFG_OFFSET,
pd);
+} +#endif
static int sifive_fu540_prci_probe(struct udevice *dev) { int i, err; @@ -679,6 +791,12 @@ static int sifive_fu540_prci_probe(struct udevice
*dev)
__prci_wrpll_read_cfg0(pd, pc->pwd); }
+#ifdef CONFIG_SPL_BUILD
corepll_init(dev);
ddr_init(dev);
ethernet_init(dev);
+#endif
- Why would ethernet clocks require for SPL 2. Why these clocks are
special for SPL, can't we use it for U-Boot proper 3. This look like raw clock initialization instead of having in conventional dm way. since these are here just to use pd. May be reuse the required clock of what u-boot proper using or move them into spl code.
- ethernet clock is not necessary for SPL but SPL performs ethernet PHY reset
sequence (board/sifive/fu540/spl.c - "gem_phy_reset") and for that ethernet clock needs to be enabled.
Can we delay that for U-Boot proper to enable PRCI ethernet clock and reset the PHY ?
- There is nothing special of this clocks for SPL, we can use this for U-Boot.
I am planning to add this clocks in device tree but I am not sure how to add coreclk (corepll) in device tree Do you guys have any suggestion for this ?
Does the example in http://patchwork.ozlabs.org/project/uboot/patch/20200423023320.1380090-20-se... help?
+ cpu0: cpu@0 { + device_type = "cpu"; + compatible = "kendryte,k210", "sifive,rocket0", "riscv"; + reg = <0>; + riscv,isa = "rv64imafdgc"; + mmu-type = "sv39"; + i-cache-block-size = <64>; + i-cache-size = <0x8000>; + d-cache-block-size = <64>; + d-cache-size = <0x8000>; + clocks = <&sysclk K210_CLK_CPU>;
You need this patch to get clock in the CPU node.
http://patchwork.ozlabs.org/project/uboot/patch/20200423023320.1380090-19-se...
- I am planning to make dm way.
Any suggestions are welcome
I believe Jagan's comments are the same as mine that was mentioned in previous version:
See https://patchwork.ozlabs.org/project/uboot/patch/20200311070320.21323- 10-pragnesh.patel@sifive.com/
Regards, Bin

Hi Bin,
-----Original Message----- From: Bin Meng bmeng.cn@gmail.com Sent: 24 April 2020 18:31 To: Pragnesh Patel pragnesh.patel@sifive.com Cc: Jagan Teki jagan@amarulasolutions.com; U-Boot-Denx <u- boot@lists.denx.de>; Atish Patra atish.patra@wdc.com; Palmer Dabbelt palmerdabbelt@google.com; Paul Walmsley paul.walmsley@sifive.com; Troy Benjegerdes troy.benjegerdes@sifive.com; Anup Patel anup.patel@wdc.com; Sagar Kadam sagar.kadam@sifive.com; Rick Chen rick@andestech.com; Lukasz Majewski lukma@denx.de; Simon Glass sjg@chromium.org Subject: Re: [PATCH v6 09/17] clk: sifive: fu540-prci: Add clock initialization for SPL
[External Email] Do not click links or attachments unless you recognize the sender and know the content is safe
Hi Pragnesh,
On Fri, Apr 24, 2020 at 6:08 PM Pragnesh Patel pragnesh.patel@sifive.com wrote:
Hi Bin, Jagan
-----Original Message----- From: Bin Meng bmeng.cn@gmail.com Sent: 20 April 2020 14:30 To: Jagan Teki jagan@amarulasolutions.com Cc: Pragnesh Patel pragnesh.patel@sifive.com; U-Boot-Denx <u- boot@lists.denx.de>; Atish Patra atish.patra@wdc.com; Palmer Dabbelt palmerdabbelt@google.com; Paul Walmsley paul.walmsley@sifive.com; Troy Benjegerdes troy.benjegerdes@sifive.com; Anup Patel anup.patel@wdc.com; Sagar Kadam sagar.kadam@sifive.com; Rick Chen rick@andestech.com; Lukasz Majewski lukma@denx.de; Simon Glass sjg@chromium.org Subject: Re: [PATCH v6 09/17] clk: sifive: fu540-prci: Add clock initialization for SPL
[External Email] Do not click links or attachments unless you recognize the sender and know the content is safe
Hi Jagan, Pragnesh,
On Tue, Apr 7, 2020 at 3:35 AM Jagan Teki jagan@amarulasolutions.com wrote:
On Sun, Mar 29, 2020 at 10:37 PM Pragnesh Patel pragnesh.patel@sifive.com wrote:
Set corepll, ddrpll and ethernet PLL for u-boot-spl
Signed-off-by: Pragnesh Patel pragnesh.patel@sifive.com
drivers/clk/sifive/fu540-prci.c | 118 ++++++++++++++++++++++++++++++++ 1 file changed, 118 insertions(+)
diff --git a/drivers/clk/sifive/fu540-prci.c b/drivers/clk/sifive/fu540-prci.c index e6214cd821..3a73c2c8d1 100644 --- a/drivers/clk/sifive/fu540-prci.c +++ b/drivers/clk/sifive/fu540-prci.c @@ -41,6 +41,10 @@ #include <linux/clk/analogbits-wrpll-cln28hpc.h> #include <dt-bindings/clock/sifive-fu540-prci.h>
+#define DDRCTLPLL_F 55 +#define DDRCTLPLL_Q 2 +#define MHz 1000000
/*
- EXPECTED_CLK_PARENT_COUNT: how many parent clocks this driver
expects:
hfclk and rtcclk
@@ -152,6 +156,27 @@ #define PRCI_CLKMUXSTATUSREG_TLCLKSEL_STATUS_MASK \ (0x1 << PRCI_CLKMUXSTATUSREG_TLCLKSEL_STATUS_SHIFT)
+/* PROCMONCFG */ +#define PRCI_PROCMONCFG_OFFSET 0xF0 +#define PRCI_PROCMONCFG_CORE_CLOCK_SHIFT 24 +#define PRCI_PROCMONCFG_CORE_CLOCK_MASK \
(0x1 << PRCI_PROCMONCFG_CORE_CLOCK_SHIFT)
+#define PLL_R(x) \
((x) << PRCI_DDRPLLCFG0_DIVR_SHIFT) &
+PRCI_DDRPLLCFG0_DIVR_MASK #define PLL_F(x) \
((x) << PRCI_DDRPLLCFG0_DIVF_SHIFT) &
+PRCI_DDRPLLCFG0_DIVF_MASK #define PLL_Q(x) \
((x) << PRCI_DDRPLLCFG0_DIVQ_SHIFT) &
+PRCI_DDRPLLCFG0_DIVQ_MASK #define PLL_RANGE(x) \
((x) << PRCI_DDRPLLCFG0_RANGE_SHIFT) &
+PRCI_DDRPLLCFG0_RANGE_MASK #define PLL_BYPASS(x) \
((x) << PRCI_DDRPLLCFG0_BYPASS_SHIFT) &
+PRCI_DDRPLLCFG0_BYPASS_MASK #define PLL_FSE(x) \
((x) << PRCI_DDRPLLCFG0_FSE_SHIFT) &
+PRCI_DDRPLLCFG0_FSE_MASK #define PLL_LOCK(x) \
((x) << PRCI_DDRPLLCFG0_LOCK_SHIFT) &
+PRCI_DDRPLLCFG0_LOCK_MASK
/*
- Private structures
*/ @@ -654,6 +679,93 @@ static int sifive_fu540_prci_disable(struct clk
*clk)
return pc->ops->enable_clk(pc, 0); }
+#ifdef CONFIG_SPL_BUILD +static void corepll_init(struct udevice *dev) {
u32 v;
struct clk clock;
struct __prci_data *pd = dev_get_priv(dev);
v = __prci_readl(pd, PRCI_CLKMUXSTATUSREG_OFFSET);
v &= PRCI_CLKMUXSTATUSREG_TLCLKSEL_STATUS_MASK;
clock.id = PRCI_CLK_COREPLL;
if (v) {
/* corepll 500 Mhz */
sifive_fu540_prci_set_rate(&clock, 500UL * MHz);
} else {
/* corepll 1 Ghz */
sifive_fu540_prci_set_rate(&clock, 1000UL * MHz);
}
+sifive_fu540_prci_clock_enable(&__prci_init_clocks[clock.id], +1); }
+static void ddr_init(struct udevice *dev) {
u32 v;
struct clk clock;
struct __prci_data *pd = dev_get_priv(dev);
//DDR init
u32 ddrctlmhz =
(PLL_R(0)) |
(PLL_F(DDRCTLPLL_F)) |
(PLL_Q(DDRCTLPLL_Q)) |
(PLL_RANGE(0x4)) |
(PLL_BYPASS(0)) |
(PLL_FSE(1));
__prci_writel(ddrctlmhz, PRCI_DDRPLLCFG0_OFFSET, pd);
clock.id = PRCI_CLK_DDRPLL;
- sifive_fu540_prci_clock_enable(&__prci_init_clocks[clock.id],
- 1);
/* Release DDR reset */
v = __prci_readl(pd, PRCI_DEVICESRESETREG_OFFSET);
v |= PRCI_DEVICESRESETREG_DDR_CTRL_RST_N_MASK;
__prci_writel(v, PRCI_DEVICESRESETREG_OFFSET, pd);
// HACK to get the '1 full controller clock cycle'.
asm volatile ("fence");
v = __prci_readl(pd, PRCI_DEVICESRESETREG_OFFSET);
v |= (PRCI_DEVICESRESETREG_DDR_AXI_RST_N_MASK |
PRCI_DEVICESRESETREG_DDR_AHB_RST_N_MASK |
PRCI_DEVICESRESETREG_DDR_PHY_RST_N_MASK);
__prci_writel(v, PRCI_DEVICESRESETREG_OFFSET, pd);
// 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"); }
+static void ethernet_init(struct udevice *dev) {
u32 v;
struct clk clock;
struct __prci_data *pd = dev_get_priv(dev);
/* GEMGXL init */
clock.id = PRCI_CLK_GEMGXLPLL;
sifive_fu540_prci_set_rate(&clock, 125UL * MHz);
- sifive_fu540_prci_clock_enable(&__prci_init_clocks[clock.id],
- 1);
/* Release GEMGXL reset */
v = __prci_readl(pd, PRCI_DEVICESRESETREG_OFFSET);
v |= PRCI_DEVICESRESETREG_GEMGXL_RST_N_MASK;
__prci_writel(v, PRCI_DEVICESRESETREG_OFFSET, pd);
/* Procmon => core clock */
__prci_writel(PRCI_PROCMONCFG_CORE_CLOCK_MASK,
PRCI_PROCMONCFG_OFFSET,
pd);
+} +#endif
static int sifive_fu540_prci_probe(struct udevice *dev) { int i, err; @@ -679,6 +791,12 @@ static int sifive_fu540_prci_probe(struct udevice
*dev)
__prci_wrpll_read_cfg0(pd, pc->pwd); }
+#ifdef CONFIG_SPL_BUILD
corepll_init(dev);
ddr_init(dev);
ethernet_init(dev);
+#endif
- Why would ethernet clocks require for SPL 2. Why these clocks
are special for SPL, can't we use it for U-Boot proper 3. This look like raw clock initialization instead of having in conventional dm way. since these are here just to use pd. May be reuse the required clock of what u-boot proper using or move them into spl code.
- ethernet clock is not necessary for SPL but SPL performs ethernet
PHY reset sequence (board/sifive/fu540/spl.c - "gem_phy_reset") and for
that ethernet clock needs to be enabled.
Can we delay that for U-Boot proper to enable PRCI ethernet clock and reset the PHY ?
We can but what happens if someone wants to skip U-Boot (SPL -> OpenSBI + Linux) ?
- There is nothing special of this clocks for SPL, we can use this for U-Boot.
I am planning to add this clocks in device tree but I am not sure how to add coreclk (corepll) in device tree Do you guys have any suggestion for
this ?
Does the example in http://patchwork.ozlabs.org/project/uboot/patch/20200423023320.1380090- 20-seanga2@gmail.com/ help?
- cpu0: cpu@0 {
- device_type = "cpu";
- compatible = "kendryte,k210", "sifive,rocket0", "riscv"; reg = <0>;
- riscv,isa = "rv64imafdgc"; mmu-type = "sv39"; i-cache-block-size =
- <64>; i-cache-size = <0x8000>; d-cache-block-size = <64>; d-cache-size
- = <0x8000>; clocks = <&sysclk K210_CLK_CPU>;
You need this patch to get clock in the CPU node.
http://patchwork.ozlabs.org/project/uboot/patch/20200423023320.1380090- 19-seanga2@gmail.com/
Thanks, will update this in v7.
- I am planning to make dm way.
Any suggestions are welcome
I believe Jagan's comments are the same as mine that was mentioned in previous version:
See
https://patchwork.ozlabs.org/project/uboot/patch/20200311070320.21323
10-pragnesh.patel@sifive.com/
Regards, Bin

Hi Pragnesh,
On Fri, Apr 24, 2020 at 9:34 PM Pragnesh Patel pragnesh.patel@sifive.com wrote:
Hi Bin,
-----Original Message----- From: Bin Meng bmeng.cn@gmail.com Sent: 24 April 2020 18:31 To: Pragnesh Patel pragnesh.patel@sifive.com Cc: Jagan Teki jagan@amarulasolutions.com; U-Boot-Denx <u- boot@lists.denx.de>; Atish Patra atish.patra@wdc.com; Palmer Dabbelt palmerdabbelt@google.com; Paul Walmsley paul.walmsley@sifive.com; Troy Benjegerdes troy.benjegerdes@sifive.com; Anup Patel anup.patel@wdc.com; Sagar Kadam sagar.kadam@sifive.com; Rick Chen rick@andestech.com; Lukasz Majewski lukma@denx.de; Simon Glass sjg@chromium.org Subject: Re: [PATCH v6 09/17] clk: sifive: fu540-prci: Add clock initialization for SPL
[External Email] Do not click links or attachments unless you recognize the sender and know the content is safe
Hi Pragnesh,
On Fri, Apr 24, 2020 at 6:08 PM Pragnesh Patel pragnesh.patel@sifive.com wrote:
Hi Bin, Jagan
-----Original Message----- From: Bin Meng bmeng.cn@gmail.com Sent: 20 April 2020 14:30 To: Jagan Teki jagan@amarulasolutions.com Cc: Pragnesh Patel pragnesh.patel@sifive.com; U-Boot-Denx <u- boot@lists.denx.de>; Atish Patra atish.patra@wdc.com; Palmer Dabbelt palmerdabbelt@google.com; Paul Walmsley paul.walmsley@sifive.com; Troy Benjegerdes troy.benjegerdes@sifive.com; Anup Patel anup.patel@wdc.com; Sagar Kadam sagar.kadam@sifive.com; Rick Chen rick@andestech.com; Lukasz Majewski lukma@denx.de; Simon Glass sjg@chromium.org Subject: Re: [PATCH v6 09/17] clk: sifive: fu540-prci: Add clock initialization for SPL
[External Email] Do not click links or attachments unless you recognize the sender and know the content is safe
Hi Jagan, Pragnesh,
On Tue, Apr 7, 2020 at 3:35 AM Jagan Teki jagan@amarulasolutions.com wrote:
On Sun, Mar 29, 2020 at 10:37 PM Pragnesh Patel pragnesh.patel@sifive.com wrote:
Set corepll, ddrpll and ethernet PLL for u-boot-spl
Signed-off-by: Pragnesh Patel pragnesh.patel@sifive.com
drivers/clk/sifive/fu540-prci.c | 118 ++++++++++++++++++++++++++++++++ 1 file changed, 118 insertions(+)
diff --git a/drivers/clk/sifive/fu540-prci.c b/drivers/clk/sifive/fu540-prci.c index e6214cd821..3a73c2c8d1 100644 --- a/drivers/clk/sifive/fu540-prci.c +++ b/drivers/clk/sifive/fu540-prci.c @@ -41,6 +41,10 @@ #include <linux/clk/analogbits-wrpll-cln28hpc.h> #include <dt-bindings/clock/sifive-fu540-prci.h>
+#define DDRCTLPLL_F 55 +#define DDRCTLPLL_Q 2 +#define MHz 1000000
/*
- EXPECTED_CLK_PARENT_COUNT: how many parent clocks this driver
expects:
hfclk and rtcclk
@@ -152,6 +156,27 @@ #define PRCI_CLKMUXSTATUSREG_TLCLKSEL_STATUS_MASK \ (0x1 << PRCI_CLKMUXSTATUSREG_TLCLKSEL_STATUS_SHIFT)
+/* PROCMONCFG */ +#define PRCI_PROCMONCFG_OFFSET 0xF0 +#define PRCI_PROCMONCFG_CORE_CLOCK_SHIFT 24 +#define PRCI_PROCMONCFG_CORE_CLOCK_MASK \
(0x1 << PRCI_PROCMONCFG_CORE_CLOCK_SHIFT)
+#define PLL_R(x) \
((x) << PRCI_DDRPLLCFG0_DIVR_SHIFT) &
+PRCI_DDRPLLCFG0_DIVR_MASK #define PLL_F(x) \
((x) << PRCI_DDRPLLCFG0_DIVF_SHIFT) &
+PRCI_DDRPLLCFG0_DIVF_MASK #define PLL_Q(x) \
((x) << PRCI_DDRPLLCFG0_DIVQ_SHIFT) &
+PRCI_DDRPLLCFG0_DIVQ_MASK #define PLL_RANGE(x) \
((x) << PRCI_DDRPLLCFG0_RANGE_SHIFT) &
+PRCI_DDRPLLCFG0_RANGE_MASK #define PLL_BYPASS(x) \
((x) << PRCI_DDRPLLCFG0_BYPASS_SHIFT) &
+PRCI_DDRPLLCFG0_BYPASS_MASK #define PLL_FSE(x) \
((x) << PRCI_DDRPLLCFG0_FSE_SHIFT) &
+PRCI_DDRPLLCFG0_FSE_MASK #define PLL_LOCK(x) \
((x) << PRCI_DDRPLLCFG0_LOCK_SHIFT) &
+PRCI_DDRPLLCFG0_LOCK_MASK
/*
- Private structures
*/ @@ -654,6 +679,93 @@ static int sifive_fu540_prci_disable(struct clk
*clk)
return pc->ops->enable_clk(pc, 0); }
+#ifdef CONFIG_SPL_BUILD +static void corepll_init(struct udevice *dev) {
u32 v;
struct clk clock;
struct __prci_data *pd = dev_get_priv(dev);
v = __prci_readl(pd, PRCI_CLKMUXSTATUSREG_OFFSET);
v &= PRCI_CLKMUXSTATUSREG_TLCLKSEL_STATUS_MASK;
clock.id = PRCI_CLK_COREPLL;
if (v) {
/* corepll 500 Mhz */
sifive_fu540_prci_set_rate(&clock, 500UL * MHz);
} else {
/* corepll 1 Ghz */
sifive_fu540_prci_set_rate(&clock, 1000UL * MHz);
}
+sifive_fu540_prci_clock_enable(&__prci_init_clocks[clock.id], +1); }
+static void ddr_init(struct udevice *dev) {
u32 v;
struct clk clock;
struct __prci_data *pd = dev_get_priv(dev);
//DDR init
u32 ddrctlmhz =
(PLL_R(0)) |
(PLL_F(DDRCTLPLL_F)) |
(PLL_Q(DDRCTLPLL_Q)) |
(PLL_RANGE(0x4)) |
(PLL_BYPASS(0)) |
(PLL_FSE(1));
__prci_writel(ddrctlmhz, PRCI_DDRPLLCFG0_OFFSET, pd);
clock.id = PRCI_CLK_DDRPLL;
- sifive_fu540_prci_clock_enable(&__prci_init_clocks[clock.id],
- 1);
/* Release DDR reset */
v = __prci_readl(pd, PRCI_DEVICESRESETREG_OFFSET);
v |= PRCI_DEVICESRESETREG_DDR_CTRL_RST_N_MASK;
__prci_writel(v, PRCI_DEVICESRESETREG_OFFSET, pd);
// HACK to get the '1 full controller clock cycle'.
asm volatile ("fence");
v = __prci_readl(pd, PRCI_DEVICESRESETREG_OFFSET);
v |= (PRCI_DEVICESRESETREG_DDR_AXI_RST_N_MASK |
PRCI_DEVICESRESETREG_DDR_AHB_RST_N_MASK |
PRCI_DEVICESRESETREG_DDR_PHY_RST_N_MASK);
__prci_writel(v, PRCI_DEVICESRESETREG_OFFSET, pd);
// 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"); }
+static void ethernet_init(struct udevice *dev) {
u32 v;
struct clk clock;
struct __prci_data *pd = dev_get_priv(dev);
/* GEMGXL init */
clock.id = PRCI_CLK_GEMGXLPLL;
sifive_fu540_prci_set_rate(&clock, 125UL * MHz);
- sifive_fu540_prci_clock_enable(&__prci_init_clocks[clock.id],
- 1);
/* Release GEMGXL reset */
v = __prci_readl(pd, PRCI_DEVICESRESETREG_OFFSET);
v |= PRCI_DEVICESRESETREG_GEMGXL_RST_N_MASK;
__prci_writel(v, PRCI_DEVICESRESETREG_OFFSET, pd);
/* Procmon => core clock */
__prci_writel(PRCI_PROCMONCFG_CORE_CLOCK_MASK,
PRCI_PROCMONCFG_OFFSET,
pd);
+} +#endif
static int sifive_fu540_prci_probe(struct udevice *dev) { int i, err; @@ -679,6 +791,12 @@ static int sifive_fu540_prci_probe(struct udevice
*dev)
__prci_wrpll_read_cfg0(pd, pc->pwd); }
+#ifdef CONFIG_SPL_BUILD
corepll_init(dev);
ddr_init(dev);
ethernet_init(dev);
+#endif
- Why would ethernet clocks require for SPL 2. Why these clocks
are special for SPL, can't we use it for U-Boot proper 3. This look like raw clock initialization instead of having in conventional dm way. since these are here just to use pd. May be reuse the required clock of what u-boot proper using or move them into spl code.
- ethernet clock is not necessary for SPL but SPL performs ethernet
PHY reset sequence (board/sifive/fu540/spl.c - "gem_phy_reset") and for
that ethernet clock needs to be enabled.
Can we delay that for U-Boot proper to enable PRCI ethernet clock and reset the PHY ?
We can but what happens if someone wants to skip U-Boot (SPL -> OpenSBI + Linux) ?
I am not sure if that's a desired boot flow. If that's something we want to support, yes we will have to do it in SPL.
- There is nothing special of this clocks for SPL, we can use this for U-Boot.
I am planning to add this clocks in device tree but I am not sure how to add coreclk (corepll) in device tree Do you guys have any suggestion for
this ?
Does the example in http://patchwork.ozlabs.org/project/uboot/patch/20200423023320.1380090- 20-seanga2@gmail.com/ help?
- cpu0: cpu@0 {
- device_type = "cpu";
- compatible = "kendryte,k210", "sifive,rocket0", "riscv"; reg = <0>;
- riscv,isa = "rv64imafdgc"; mmu-type = "sv39"; i-cache-block-size =
- <64>; i-cache-size = <0x8000>; d-cache-block-size = <64>; d-cache-size
- = <0x8000>; clocks = <&sysclk K210_CLK_CPU>;
You need this patch to get clock in the CPU node.
http://patchwork.ozlabs.org/project/uboot/patch/20200423023320.1380090- 19-seanga2@gmail.com/
Thanks, will update this in v7.
Regards, Bin

Hi Bin,
-----Original Message----- From: Bin Meng bmeng.cn@gmail.com Sent: 24 April 2020 19:25 To: Pragnesh Patel pragnesh.patel@sifive.com Cc: Jagan Teki jagan@amarulasolutions.com; U-Boot-Denx <u- boot@lists.denx.de>; Atish Patra atish.patra@wdc.com; Palmer Dabbelt palmerdabbelt@google.com; Paul Walmsley paul.walmsley@sifive.com; Troy Benjegerdes troy.benjegerdes@sifive.com; Anup Patel anup.patel@wdc.com; Sagar Kadam sagar.kadam@sifive.com; Rick Chen rick@andestech.com; Lukasz Majewski lukma@denx.de; Simon Glass sjg@chromium.org Subject: Re: [PATCH v6 09/17] clk: sifive: fu540-prci: Add clock initialization for SPL
[External Email] Do not click links or attachments unless you recognize the sender and know the content is safe
Hi Pragnesh,
On Fri, Apr 24, 2020 at 9:34 PM Pragnesh Patel pragnesh.patel@sifive.com wrote:
Hi Bin,
-----Original Message----- From: Bin Meng bmeng.cn@gmail.com Sent: 24 April 2020 18:31 To: Pragnesh Patel pragnesh.patel@sifive.com Cc: Jagan Teki jagan@amarulasolutions.com; U-Boot-Denx <u- boot@lists.denx.de>; Atish Patra atish.patra@wdc.com; Palmer Dabbelt palmerdabbelt@google.com; Paul Walmsley paul.walmsley@sifive.com; Troy Benjegerdes troy.benjegerdes@sifive.com; Anup Patel anup.patel@wdc.com; Sagar Kadam sagar.kadam@sifive.com; Rick Chen rick@andestech.com; Lukasz Majewski lukma@denx.de; Simon Glass sjg@chromium.org Subject: Re: [PATCH v6 09/17] clk: sifive: fu540-prci: Add clock initialization for SPL
[External Email] Do not click links or attachments unless you recognize the sender and know the content is safe
Hi Pragnesh,
On Fri, Apr 24, 2020 at 6:08 PM Pragnesh Patel pragnesh.patel@sifive.com wrote:
Hi Bin, Jagan
-----Original Message----- From: Bin Meng bmeng.cn@gmail.com Sent: 20 April 2020 14:30 To: Jagan Teki jagan@amarulasolutions.com Cc: Pragnesh Patel pragnesh.patel@sifive.com; U-Boot-Denx <u- boot@lists.denx.de>; Atish Patra atish.patra@wdc.com; Palmer Dabbelt palmerdabbelt@google.com; Paul Walmsley paul.walmsley@sifive.com; Troy Benjegerdes troy.benjegerdes@sifive.com; Anup Patel anup.patel@wdc.com; Sagar Kadam sagar.kadam@sifive.com; Rick Chen rick@andestech.com; Lukasz Majewski lukma@denx.de; Simon
Glass
sjg@chromium.org Subject: Re: [PATCH v6 09/17] clk: sifive: fu540-prci: Add clock initialization for SPL
[External Email] Do not click links or attachments unless you recognize the sender and know the content is safe
Hi Jagan, Pragnesh,
On Tue, Apr 7, 2020 at 3:35 AM Jagan Teki jagan@amarulasolutions.com wrote:
On Sun, Mar 29, 2020 at 10:37 PM Pragnesh Patel pragnesh.patel@sifive.com wrote: > > Set corepll, ddrpll and ethernet PLL for u-boot-spl > > Signed-off-by: Pragnesh Patel pragnesh.patel@sifive.com > --- > drivers/clk/sifive/fu540-prci.c | 118 > ++++++++++++++++++++++++++++++++ > 1 file changed, 118 insertions(+) > > diff --git a/drivers/clk/sifive/fu540-prci.c > b/drivers/clk/sifive/fu540-prci.c index e6214cd821..3a73c2c8d1 > 100644 > --- a/drivers/clk/sifive/fu540-prci.c > +++ b/drivers/clk/sifive/fu540-prci.c > @@ -41,6 +41,10 @@ > #include <linux/clk/analogbits-wrpll-cln28hpc.h> > #include <dt-bindings/clock/sifive-fu540-prci.h> > > +#define DDRCTLPLL_F 55 > +#define DDRCTLPLL_Q 2 > +#define MHz 1000000 > + > /* > * EXPECTED_CLK_PARENT_COUNT: how many parent clocks this > driver
expects:
> * hfclk and rtcclk > @@ -152,6 +156,27 @@ > #define PRCI_CLKMUXSTATUSREG_TLCLKSEL_STATUS_MASK \ > (0x1 << > PRCI_CLKMUXSTATUSREG_TLCLKSEL_STATUS_SHIFT) > > +/* PROCMONCFG */ > +#define PRCI_PROCMONCFG_OFFSET 0xF0 > +#define PRCI_PROCMONCFG_CORE_CLOCK_SHIFT 24 > +#define PRCI_PROCMONCFG_CORE_CLOCK_MASK \ > + (0x1 << > +PRCI_PROCMONCFG_CORE_CLOCK_SHIFT) > + > +#define PLL_R(x) \ > + ((x) << PRCI_DDRPLLCFG0_DIVR_SHIFT) & > +PRCI_DDRPLLCFG0_DIVR_MASK #define PLL_F(x) \ > + ((x) << PRCI_DDRPLLCFG0_DIVF_SHIFT) & > +PRCI_DDRPLLCFG0_DIVF_MASK #define PLL_Q(x) \ > + ((x) << PRCI_DDRPLLCFG0_DIVQ_SHIFT) & > +PRCI_DDRPLLCFG0_DIVQ_MASK #define PLL_RANGE(x) \ > + ((x) << PRCI_DDRPLLCFG0_RANGE_SHIFT) & > +PRCI_DDRPLLCFG0_RANGE_MASK #define PLL_BYPASS(x) \ > + ((x) << PRCI_DDRPLLCFG0_BYPASS_SHIFT) & > +PRCI_DDRPLLCFG0_BYPASS_MASK #define PLL_FSE(x) \ > + ((x) << PRCI_DDRPLLCFG0_FSE_SHIFT) & > +PRCI_DDRPLLCFG0_FSE_MASK #define PLL_LOCK(x) \ > + ((x) << PRCI_DDRPLLCFG0_LOCK_SHIFT) & > +PRCI_DDRPLLCFG0_LOCK_MASK > + > /* > * Private structures > */ > @@ -654,6 +679,93 @@ static int > sifive_fu540_prci_disable(struct clk
*clk)
> return pc->ops->enable_clk(pc, 0); } > > +#ifdef CONFIG_SPL_BUILD > +static void corepll_init(struct udevice *dev) { > + u32 v; > + struct clk clock; > + struct __prci_data *pd = dev_get_priv(dev); > + > + v = __prci_readl(pd, PRCI_CLKMUXSTATUSREG_OFFSET); > + v &= PRCI_CLKMUXSTATUSREG_TLCLKSEL_STATUS_MASK; > + > + clock.id = PRCI_CLK_COREPLL; > + > + if (v) { > + /* corepll 500 Mhz */ > + sifive_fu540_prci_set_rate(&clock, 500UL * MHz); > + } else { > + /* corepll 1 Ghz */ > + sifive_fu540_prci_set_rate(&clock, 1000UL * MHz); > + } > + > + > +sifive_fu540_prci_clock_enable(&__prci_init_clocks[clock.id], > +1); } > + > +static void ddr_init(struct udevice *dev) { > + u32 v; > + struct clk clock; > + struct __prci_data *pd = dev_get_priv(dev); > + > + //DDR init > + u32 ddrctlmhz = > + (PLL_R(0)) | > + (PLL_F(DDRCTLPLL_F)) | > + (PLL_Q(DDRCTLPLL_Q)) | > + (PLL_RANGE(0x4)) | > + (PLL_BYPASS(0)) | > + (PLL_FSE(1)); > + __prci_writel(ddrctlmhz, PRCI_DDRPLLCFG0_OFFSET, pd); > + > + clock.id = PRCI_CLK_DDRPLL; > + > + sifive_fu540_prci_clock_enable(&__prci_init_clocks[clock.id] > + , > + 1); > + > + /* Release DDR reset */ > + v = __prci_readl(pd, PRCI_DEVICESRESETREG_OFFSET); > + v |= PRCI_DEVICESRESETREG_DDR_CTRL_RST_N_MASK; > + __prci_writel(v, PRCI_DEVICESRESETREG_OFFSET, pd); > + > + // HACK to get the '1 full controller clock cycle'. > + asm volatile ("fence"); > + v = __prci_readl(pd, PRCI_DEVICESRESETREG_OFFSET); > + v |= (PRCI_DEVICESRESETREG_DDR_AXI_RST_N_MASK | > + PRCI_DEVICESRESETREG_DDR_AHB_RST_N_MASK | > + PRCI_DEVICESRESETREG_DDR_PHY_RST_N_MASK); > + __prci_writel(v, PRCI_DEVICESRESETREG_OFFSET, pd); > + // 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"); } > + > +static void ethernet_init(struct udevice *dev) { > + u32 v; > + struct clk clock; > + struct __prci_data *pd = dev_get_priv(dev); > + > + /* GEMGXL init */ > + clock.id = PRCI_CLK_GEMGXLPLL; > + sifive_fu540_prci_set_rate(&clock, 125UL * MHz); > + > + sifive_fu540_prci_clock_enable(&__prci_init_clocks[clock.id] > + , > + 1); > + > + /* Release GEMGXL reset */ > + v = __prci_readl(pd, PRCI_DEVICESRESETREG_OFFSET); > + v |= PRCI_DEVICESRESETREG_GEMGXL_RST_N_MASK; > + __prci_writel(v, PRCI_DEVICESRESETREG_OFFSET, pd); > + > + /* Procmon => core clock */ > + __prci_writel(PRCI_PROCMONCFG_CORE_CLOCK_MASK,
PRCI_PROCMONCFG_OFFSET,
> + pd); > +} > +#endif > + > static int sifive_fu540_prci_probe(struct udevice *dev) { > int i, err; > @@ -679,6 +791,12 @@ static int sifive_fu540_prci_probe(struct > udevice
*dev)
> __prci_wrpll_read_cfg0(pd, pc->pwd); > } > > +#ifdef CONFIG_SPL_BUILD > + corepll_init(dev); > + ddr_init(dev); > + ethernet_init(dev); > +#endif
- Why would ethernet clocks require for SPL 2. Why these clocks
are special for SPL, can't we use it for U-Boot proper 3. This look like raw clock initialization instead of having in conventional dm
way.
since these are here just to use pd. May be reuse the required clock of what u-boot proper using or move them into spl code.
- ethernet clock is not necessary for SPL but SPL performs
ethernet PHY reset sequence (board/sifive/fu540/spl.c - "gem_phy_reset") and for
that ethernet clock needs to be enabled.
Can we delay that for U-Boot proper to enable PRCI ethernet clock and reset the PHY ?
We can but what happens if someone wants to skip U-Boot (SPL -> OpenSBI
- Linux) ?
I am not sure if that's a desired boot flow. If that's something we want to support, yes we will have to do it in SPL.
- There is nothing special of this clocks for SPL, we can use this for U-
Boot.
I am planning to add this clocks in device tree but I am not sure how to add coreclk (corepll) in device tree Do you guys have any suggestion for
this ?
Does the example in
http://patchwork.ozlabs.org/project/uboot/patch/20200423023320.138009
0- 20-seanga2@gmail.com/ help?
- cpu0: cpu@0 {
- device_type = "cpu";
- compatible = "kendryte,k210", "sifive,rocket0", "riscv"; reg = <0>;
- riscv,isa = "rv64imafdgc"; mmu-type = "sv39"; i-cache-block-size =
- <64>; i-cache-size = <0x8000>; d-cache-block-size = <64>;
- d-cache-size = <0x8000>; clocks = <&sysclk K210_CLK_CPU>;
You need this patch to get clock in the CPU node.
http://patchwork.ozlabs.org/project/uboot/patch/20200423023320.138009
0- 19-seanga2@gmail.com/
This patch helps but I also need to do clk_set_rate() for coreclk.
static void corepll_init(struct udevice *dev) { ..... if (v) { /* corepll 500 Mhz */ sifive_fu540_prci_set_rate(&clock, 500UL * MHz); } else { /* corepll 1 Ghz */ sifive_fu540_prci_set_rate(&clock, 1000UL * MHz); } }
I think, if "clock-frequency" is provided in dts then it's better to call clk_set_rate()
Any suggestions are welcome.
Thanks, will update this in v7.
Regards, Bin

Hi Pragnesh,
On Sat, Apr 25, 2020 at 12:27 AM Pragnesh Patel pragnesh.patel@sifive.com wrote:
Hi Bin,
-----Original Message----- From: Bin Meng bmeng.cn@gmail.com Sent: 24 April 2020 19:25 To: Pragnesh Patel pragnesh.patel@sifive.com Cc: Jagan Teki jagan@amarulasolutions.com; U-Boot-Denx <u- boot@lists.denx.de>; Atish Patra atish.patra@wdc.com; Palmer Dabbelt palmerdabbelt@google.com; Paul Walmsley paul.walmsley@sifive.com; Troy Benjegerdes troy.benjegerdes@sifive.com; Anup Patel anup.patel@wdc.com; Sagar Kadam sagar.kadam@sifive.com; Rick Chen rick@andestech.com; Lukasz Majewski lukma@denx.de; Simon Glass sjg@chromium.org Subject: Re: [PATCH v6 09/17] clk: sifive: fu540-prci: Add clock initialization for SPL
[External Email] Do not click links or attachments unless you recognize the sender and know the content is safe
Hi Pragnesh,
On Fri, Apr 24, 2020 at 9:34 PM Pragnesh Patel pragnesh.patel@sifive.com wrote:
Hi Bin,
-----Original Message----- From: Bin Meng bmeng.cn@gmail.com Sent: 24 April 2020 18:31 To: Pragnesh Patel pragnesh.patel@sifive.com Cc: Jagan Teki jagan@amarulasolutions.com; U-Boot-Denx <u- boot@lists.denx.de>; Atish Patra atish.patra@wdc.com; Palmer Dabbelt palmerdabbelt@google.com; Paul Walmsley paul.walmsley@sifive.com; Troy Benjegerdes troy.benjegerdes@sifive.com; Anup Patel anup.patel@wdc.com; Sagar Kadam sagar.kadam@sifive.com; Rick Chen rick@andestech.com; Lukasz Majewski lukma@denx.de; Simon Glass sjg@chromium.org Subject: Re: [PATCH v6 09/17] clk: sifive: fu540-prci: Add clock initialization for SPL
[External Email] Do not click links or attachments unless you recognize the sender and know the content is safe
Hi Pragnesh,
On Fri, Apr 24, 2020 at 6:08 PM Pragnesh Patel pragnesh.patel@sifive.com wrote:
Hi Bin, Jagan
-----Original Message----- From: Bin Meng bmeng.cn@gmail.com Sent: 20 April 2020 14:30 To: Jagan Teki jagan@amarulasolutions.com Cc: Pragnesh Patel pragnesh.patel@sifive.com; U-Boot-Denx <u- boot@lists.denx.de>; Atish Patra atish.patra@wdc.com; Palmer Dabbelt palmerdabbelt@google.com; Paul Walmsley paul.walmsley@sifive.com; Troy Benjegerdes troy.benjegerdes@sifive.com; Anup Patel anup.patel@wdc.com; Sagar Kadam sagar.kadam@sifive.com; Rick Chen rick@andestech.com; Lukasz Majewski lukma@denx.de; Simon
Glass
sjg@chromium.org Subject: Re: [PATCH v6 09/17] clk: sifive: fu540-prci: Add clock initialization for SPL
[External Email] Do not click links or attachments unless you recognize the sender and know the content is safe
Hi Jagan, Pragnesh,
On Tue, Apr 7, 2020 at 3:35 AM Jagan Teki jagan@amarulasolutions.com wrote: > > On Sun, Mar 29, 2020 at 10:37 PM Pragnesh Patel > pragnesh.patel@sifive.com wrote: > > > > Set corepll, ddrpll and ethernet PLL for u-boot-spl > > > > Signed-off-by: Pragnesh Patel pragnesh.patel@sifive.com > > --- > > drivers/clk/sifive/fu540-prci.c | 118 > > ++++++++++++++++++++++++++++++++ > > 1 file changed, 118 insertions(+) > > > > diff --git a/drivers/clk/sifive/fu540-prci.c > > b/drivers/clk/sifive/fu540-prci.c index e6214cd821..3a73c2c8d1 > > 100644 > > --- a/drivers/clk/sifive/fu540-prci.c > > +++ b/drivers/clk/sifive/fu540-prci.c > > @@ -41,6 +41,10 @@ > > #include <linux/clk/analogbits-wrpll-cln28hpc.h> > > #include <dt-bindings/clock/sifive-fu540-prci.h> > > > > +#define DDRCTLPLL_F 55 > > +#define DDRCTLPLL_Q 2 > > +#define MHz 1000000 > > + > > /* > > * EXPECTED_CLK_PARENT_COUNT: how many parent clocks this > > driver expects: > > * hfclk and rtcclk > > @@ -152,6 +156,27 @@ > > #define PRCI_CLKMUXSTATUSREG_TLCLKSEL_STATUS_MASK \ > > (0x1 << > > PRCI_CLKMUXSTATUSREG_TLCLKSEL_STATUS_SHIFT) > > > > +/* PROCMONCFG */ > > +#define PRCI_PROCMONCFG_OFFSET 0xF0 > > +#define PRCI_PROCMONCFG_CORE_CLOCK_SHIFT 24 > > +#define PRCI_PROCMONCFG_CORE_CLOCK_MASK \ > > + (0x1 << > > +PRCI_PROCMONCFG_CORE_CLOCK_SHIFT) > > + > > +#define PLL_R(x) \ > > + ((x) << PRCI_DDRPLLCFG0_DIVR_SHIFT) & > > +PRCI_DDRPLLCFG0_DIVR_MASK #define PLL_F(x) \ > > + ((x) << PRCI_DDRPLLCFG0_DIVF_SHIFT) & > > +PRCI_DDRPLLCFG0_DIVF_MASK #define PLL_Q(x) \ > > + ((x) << PRCI_DDRPLLCFG0_DIVQ_SHIFT) & > > +PRCI_DDRPLLCFG0_DIVQ_MASK #define PLL_RANGE(x) \ > > + ((x) << PRCI_DDRPLLCFG0_RANGE_SHIFT) & > > +PRCI_DDRPLLCFG0_RANGE_MASK #define PLL_BYPASS(x) \ > > + ((x) << PRCI_DDRPLLCFG0_BYPASS_SHIFT) & > > +PRCI_DDRPLLCFG0_BYPASS_MASK #define PLL_FSE(x) \ > > + ((x) << PRCI_DDRPLLCFG0_FSE_SHIFT) & > > +PRCI_DDRPLLCFG0_FSE_MASK #define PLL_LOCK(x) \ > > + ((x) << PRCI_DDRPLLCFG0_LOCK_SHIFT) & > > +PRCI_DDRPLLCFG0_LOCK_MASK > > + > > /* > > * Private structures > > */ > > @@ -654,6 +679,93 @@ static int > > sifive_fu540_prci_disable(struct clk
*clk)
> > return pc->ops->enable_clk(pc, 0); } > > > > +#ifdef CONFIG_SPL_BUILD > > +static void corepll_init(struct udevice *dev) { > > + u32 v; > > + struct clk clock; > > + struct __prci_data *pd = dev_get_priv(dev); > > + > > + v = __prci_readl(pd, PRCI_CLKMUXSTATUSREG_OFFSET); > > + v &= PRCI_CLKMUXSTATUSREG_TLCLKSEL_STATUS_MASK; > > + > > + clock.id = PRCI_CLK_COREPLL; > > + > > + if (v) { > > + /* corepll 500 Mhz */ > > + sifive_fu540_prci_set_rate(&clock, 500UL * MHz); > > + } else { > > + /* corepll 1 Ghz */ > > + sifive_fu540_prci_set_rate(&clock, 1000UL * MHz); > > + } > > + > > + > > +sifive_fu540_prci_clock_enable(&__prci_init_clocks[clock.id], > > +1); } > > + > > +static void ddr_init(struct udevice *dev) { > > + u32 v; > > + struct clk clock; > > + struct __prci_data *pd = dev_get_priv(dev); > > + > > + //DDR init > > + u32 ddrctlmhz = > > + (PLL_R(0)) | > > + (PLL_F(DDRCTLPLL_F)) | > > + (PLL_Q(DDRCTLPLL_Q)) | > > + (PLL_RANGE(0x4)) | > > + (PLL_BYPASS(0)) | > > + (PLL_FSE(1)); > > + __prci_writel(ddrctlmhz, PRCI_DDRPLLCFG0_OFFSET, pd); > > + > > + clock.id = PRCI_CLK_DDRPLL; > > + > > + sifive_fu540_prci_clock_enable(&__prci_init_clocks[clock.id] > > + , > > + 1); > > + > > + /* Release DDR reset */ > > + v = __prci_readl(pd, PRCI_DEVICESRESETREG_OFFSET); > > + v |= PRCI_DEVICESRESETREG_DDR_CTRL_RST_N_MASK; > > + __prci_writel(v, PRCI_DEVICESRESETREG_OFFSET, pd); > > + > > + // HACK to get the '1 full controller clock cycle'. > > + asm volatile ("fence"); > > + v = __prci_readl(pd, PRCI_DEVICESRESETREG_OFFSET); > > + v |= (PRCI_DEVICESRESETREG_DDR_AXI_RST_N_MASK | > > + PRCI_DEVICESRESETREG_DDR_AHB_RST_N_MASK | > > + PRCI_DEVICESRESETREG_DDR_PHY_RST_N_MASK); > > + __prci_writel(v, PRCI_DEVICESRESETREG_OFFSET, pd); > > + // 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"); } > > + > > +static void ethernet_init(struct udevice *dev) { > > + u32 v; > > + struct clk clock; > > + struct __prci_data *pd = dev_get_priv(dev); > > + > > + /* GEMGXL init */ > > + clock.id = PRCI_CLK_GEMGXLPLL; > > + sifive_fu540_prci_set_rate(&clock, 125UL * MHz); > > + > > + sifive_fu540_prci_clock_enable(&__prci_init_clocks[clock.id] > > + , > > + 1); > > + > > + /* Release GEMGXL reset */ > > + v = __prci_readl(pd, PRCI_DEVICESRESETREG_OFFSET); > > + v |= PRCI_DEVICESRESETREG_GEMGXL_RST_N_MASK; > > + __prci_writel(v, PRCI_DEVICESRESETREG_OFFSET, pd); > > + > > + /* Procmon => core clock */ > > + __prci_writel(PRCI_PROCMONCFG_CORE_CLOCK_MASK, PRCI_PROCMONCFG_OFFSET, > > + pd); > > +} > > +#endif > > + > > static int sifive_fu540_prci_probe(struct udevice *dev) { > > int i, err; > > @@ -679,6 +791,12 @@ static int sifive_fu540_prci_probe(struct > > udevice *dev) > > __prci_wrpll_read_cfg0(pd, pc->pwd); > > } > > > > +#ifdef CONFIG_SPL_BUILD > > + corepll_init(dev); > > + ddr_init(dev); > > + ethernet_init(dev); > > +#endif > > 1. Why would ethernet clocks require for SPL 2. Why these clocks > are special for SPL, can't we use it for U-Boot proper 3. This > look like raw clock initialization instead of having in conventional dm
way.
> since these are here just to use pd. May be reuse the required > clock of what u-boot proper using or move them into spl code.
- ethernet clock is not necessary for SPL but SPL performs
ethernet PHY reset sequence (board/sifive/fu540/spl.c - "gem_phy_reset") and for
that ethernet clock needs to be enabled.
Can we delay that for U-Boot proper to enable PRCI ethernet clock and reset the PHY ?
We can but what happens if someone wants to skip U-Boot (SPL -> OpenSBI
- Linux) ?
I am not sure if that's a desired boot flow. If that's something we want to support, yes we will have to do it in SPL.
- There is nothing special of this clocks for SPL, we can use this for U-
Boot.
I am planning to add this clocks in device tree but I am not sure how to add coreclk (corepll) in device tree Do you guys have any suggestion for
this ?
Does the example in
http://patchwork.ozlabs.org/project/uboot/patch/20200423023320.138009
0- 20-seanga2@gmail.com/ help?
- cpu0: cpu@0 {
- device_type = "cpu";
- compatible = "kendryte,k210", "sifive,rocket0", "riscv"; reg = <0>;
- riscv,isa = "rv64imafdgc"; mmu-type = "sv39"; i-cache-block-size =
- <64>; i-cache-size = <0x8000>; d-cache-block-size = <64>;
- d-cache-size = <0x8000>; clocks = <&sysclk K210_CLK_CPU>;
You need this patch to get clock in the CPU node.
http://patchwork.ozlabs.org/project/uboot/patch/20200423023320.138009
0- 19-seanga2@gmail.com/
This patch helps but I also need to do clk_set_rate() for coreclk.
static void corepll_init(struct udevice *dev) { ..... if (v) { /* corepll 500 Mhz */ sifive_fu540_prci_set_rate(&clock, 500UL * MHz); } else { /* corepll 1 Ghz */ sifive_fu540_prci_set_rate(&clock, 1000UL * MHz); } }
I think, if "clock-frequency" is provided in dts then it's better to call clk_set_rate()
I think so.
Any suggestions are welcome.
Regards, Bin

Hi Jagan, Bin
-----Original Message----- From: Jagan Teki jagan@amarulasolutions.com Sent: 07 April 2020 01:06 To: Pragnesh Patel pragnesh.patel@sifive.com Cc: U-Boot-Denx u-boot@lists.denx.de; Atish Patra atish.patra@wdc.com; palmerdabbelt@google.com; Bin Meng bmeng.cn@gmail.com; Paul Walmsley paul.walmsley@sifive.com; Troy Benjegerdes troy.benjegerdes@sifive.com; Anup Patel anup.patel@wdc.com; Sagar Kadam sagar.kadam@sifive.com; Rick Chen rick@andestech.com; Lukasz Majewski lukma@denx.de; Simon Glass sjg@chromium.org Subject: Re: [PATCH v6 09/17] clk: sifive: fu540-prci: Add clock initialization for SPL
[External Email] Do not click links or attachments unless you recognize the sender and know the content is safe
On Sun, Mar 29, 2020 at 10:37 PM Pragnesh Patel pragnesh.patel@sifive.com wrote:
Set corepll, ddrpll and ethernet PLL for u-boot-spl
Signed-off-by: Pragnesh Patel pragnesh.patel@sifive.com
drivers/clk/sifive/fu540-prci.c | 118 ++++++++++++++++++++++++++++++++ 1 file changed, 118 insertions(+)
diff --git a/drivers/clk/sifive/fu540-prci.c b/drivers/clk/sifive/fu540-prci.c index e6214cd821..3a73c2c8d1 100644 --- a/drivers/clk/sifive/fu540-prci.c +++ b/drivers/clk/sifive/fu540-prci.c @@ -41,6 +41,10 @@ #include <linux/clk/analogbits-wrpll-cln28hpc.h> #include <dt-bindings/clock/sifive-fu540-prci.h>
+#define DDRCTLPLL_F 55 +#define DDRCTLPLL_Q 2 +#define MHz 1000000
/*
- EXPECTED_CLK_PARENT_COUNT: how many parent clocks this driver
expects:
hfclk and rtcclk
@@ -152,6 +156,27 @@ #define PRCI_CLKMUXSTATUSREG_TLCLKSEL_STATUS_MASK \ (0x1 << PRCI_CLKMUXSTATUSREG_TLCLKSEL_STATUS_SHIFT)
+/* PROCMONCFG */ +#define PRCI_PROCMONCFG_OFFSET 0xF0 +#define PRCI_PROCMONCFG_CORE_CLOCK_SHIFT 24 +#define PRCI_PROCMONCFG_CORE_CLOCK_MASK \
(0x1 << PRCI_PROCMONCFG_CORE_CLOCK_SHIFT)
+#define PLL_R(x) \
((x) << PRCI_DDRPLLCFG0_DIVR_SHIFT) &
+PRCI_DDRPLLCFG0_DIVR_MASK #define PLL_F(x) \
((x) << PRCI_DDRPLLCFG0_DIVF_SHIFT) &
+PRCI_DDRPLLCFG0_DIVF_MASK #define PLL_Q(x) \
((x) << PRCI_DDRPLLCFG0_DIVQ_SHIFT) &
+PRCI_DDRPLLCFG0_DIVQ_MASK #define PLL_RANGE(x) \
((x) << PRCI_DDRPLLCFG0_RANGE_SHIFT) &
+PRCI_DDRPLLCFG0_RANGE_MASK #define PLL_BYPASS(x) \
((x) << PRCI_DDRPLLCFG0_BYPASS_SHIFT) &
+PRCI_DDRPLLCFG0_BYPASS_MASK #define PLL_FSE(x) \
((x) << PRCI_DDRPLLCFG0_FSE_SHIFT) & PRCI_DDRPLLCFG0_FSE_MASK
+#define PLL_LOCK(x) \
((x) << PRCI_DDRPLLCFG0_LOCK_SHIFT) &
+PRCI_DDRPLLCFG0_LOCK_MASK
/*
- Private structures
*/ @@ -654,6 +679,93 @@ static int sifive_fu540_prci_disable(struct clk *clk) return pc->ops->enable_clk(pc, 0); }
+#ifdef CONFIG_SPL_BUILD +static void corepll_init(struct udevice *dev) {
Will convert corepll into DM
u32 v;
struct clk clock;
struct __prci_data *pd = dev_get_priv(dev);
v = __prci_readl(pd, PRCI_CLKMUXSTATUSREG_OFFSET);
v &= PRCI_CLKMUXSTATUSREG_TLCLKSEL_STATUS_MASK;
clock.id = PRCI_CLK_COREPLL;
if (v) {
/* corepll 500 Mhz */
sifive_fu540_prci_set_rate(&clock, 500UL * MHz);
} else {
/* corepll 1 Ghz */
sifive_fu540_prci_set_rate(&clock, 1000UL * MHz);
}
sifive_fu540_prci_clock_enable(&__prci_init_clocks[clock.id],
+1); }
+static void ddr_init(struct udevice *dev) {
u32 v;
struct clk clock;
struct __prci_data *pd = dev_get_priv(dev);
//DDR init
u32 ddrctlmhz =
(PLL_R(0)) |
(PLL_F(DDRCTLPLL_F)) |
(PLL_Q(DDRCTLPLL_Q)) |
(PLL_RANGE(0x4)) |
(PLL_BYPASS(0)) |
(PLL_FSE(1));
__prci_writel(ddrctlmhz, PRCI_DDRPLLCFG0_OFFSET, pd);
clock.id = PRCI_CLK_DDRPLL;
sifive_fu540_prci_clock_enable(&__prci_init_clocks[clock.id],
- 1);
/* Release DDR reset */
v = __prci_readl(pd, PRCI_DEVICESRESETREG_OFFSET);
v |= PRCI_DEVICESRESETREG_DDR_CTRL_RST_N_MASK;
__prci_writel(v, PRCI_DEVICESRESETREG_OFFSET, pd);
// HACK to get the '1 full controller clock cycle'.
asm volatile ("fence");
v = __prci_readl(pd, PRCI_DEVICESRESETREG_OFFSET);
v |= (PRCI_DEVICESRESETREG_DDR_AXI_RST_N_MASK |
PRCI_DEVICESRESETREG_DDR_AHB_RST_N_MASK |
PRCI_DEVICESRESETREG_DDR_PHY_RST_N_MASK);
__prci_writel(v, PRCI_DEVICESRESETREG_OFFSET, pd);
// 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");
+}
With DDR clock DM, DDR clock can be enabled by clk_enable() and set rate with clk_set_rate() but after this DDR clock Reset needs to be released as shown below,
/* Release DDR reset */ v = __prci_readl(pd, PRCI_DEVICESRESETREG_OFFSET); v |= PRCI_DEVICESRESETREG_DDR_CTRL_RST_N_MASK; __prci_writel(v, PRCI_DEVICESRESETREG_OFFSET, pd);
Do you guys have any suggestion how to Release DDR reset in DM way in SPL or current implementation is fine for DDR clock initialization ?
+static void ethernet_init(struct udevice *dev) {
u32 v;
struct clk clock;
struct __prci_data *pd = dev_get_priv(dev);
/* GEMGXL init */
clock.id = PRCI_CLK_GEMGXLPLL;
sifive_fu540_prci_set_rate(&clock, 125UL * MHz);
sifive_fu540_prci_clock_enable(&__prci_init_clocks[clock.id],
- 1);
/* Release GEMGXL reset */
v = __prci_readl(pd, PRCI_DEVICESRESETREG_OFFSET);
v |= PRCI_DEVICESRESETREG_GEMGXL_RST_N_MASK;
__prci_writel(v, PRCI_DEVICESRESETREG_OFFSET, pd);
/* Procmon => core clock */
__prci_writel(PRCI_PROCMONCFG_CORE_CLOCK_MASK,
PRCI_PROCMONCFG_OFFSET,
pd);
+}
SPL performs ethernet PHY reset sequence (board/sifive/fu540/spl.c - "gem_phy_reset") and for that ethernet clock needs to be enabled. So I am not planning to make any changes in ethernet_init() in v7
Any suggestions are welcome
+#endif
static int sifive_fu540_prci_probe(struct udevice *dev) { int i, err; @@ -679,6 +791,12 @@ static int sifive_fu540_prci_probe(struct udevice
*dev)
__prci_wrpll_read_cfg0(pd, pc->pwd); }
+#ifdef CONFIG_SPL_BUILD
corepll_init(dev);
ddr_init(dev);
ethernet_init(dev);
+#endif
- Why would ethernet clocks require for SPL 2. Why these clocks are special
for SPL, can't we use it for U-Boot proper 3. This look like raw clock initialization instead of having in conventional dm way. since these are here just to use pd. May be reuse the required clock of what u-boot proper using or move them into spl code.
Jagan.

Hi Pragnesh,
On Sun, Apr 26, 2020 at 6:00 PM Pragnesh Patel pragnesh.patel@sifive.com wrote:
Hi Jagan, Bin
-----Original Message----- From: Jagan Teki jagan@amarulasolutions.com Sent: 07 April 2020 01:06 To: Pragnesh Patel pragnesh.patel@sifive.com Cc: U-Boot-Denx u-boot@lists.denx.de; Atish Patra atish.patra@wdc.com; palmerdabbelt@google.com; Bin Meng bmeng.cn@gmail.com; Paul Walmsley paul.walmsley@sifive.com; Troy Benjegerdes troy.benjegerdes@sifive.com; Anup Patel anup.patel@wdc.com; Sagar Kadam sagar.kadam@sifive.com; Rick Chen rick@andestech.com; Lukasz Majewski lukma@denx.de; Simon Glass sjg@chromium.org Subject: Re: [PATCH v6 09/17] clk: sifive: fu540-prci: Add clock initialization for SPL
[External Email] Do not click links or attachments unless you recognize the sender and know the content is safe
On Sun, Mar 29, 2020 at 10:37 PM Pragnesh Patel pragnesh.patel@sifive.com wrote:
Set corepll, ddrpll and ethernet PLL for u-boot-spl
Signed-off-by: Pragnesh Patel pragnesh.patel@sifive.com
drivers/clk/sifive/fu540-prci.c | 118 ++++++++++++++++++++++++++++++++ 1 file changed, 118 insertions(+)
diff --git a/drivers/clk/sifive/fu540-prci.c b/drivers/clk/sifive/fu540-prci.c index e6214cd821..3a73c2c8d1 100644 --- a/drivers/clk/sifive/fu540-prci.c +++ b/drivers/clk/sifive/fu540-prci.c @@ -41,6 +41,10 @@ #include <linux/clk/analogbits-wrpll-cln28hpc.h> #include <dt-bindings/clock/sifive-fu540-prci.h>
+#define DDRCTLPLL_F 55 +#define DDRCTLPLL_Q 2 +#define MHz 1000000
/*
- EXPECTED_CLK_PARENT_COUNT: how many parent clocks this driver
expects:
hfclk and rtcclk
@@ -152,6 +156,27 @@ #define PRCI_CLKMUXSTATUSREG_TLCLKSEL_STATUS_MASK \ (0x1 << PRCI_CLKMUXSTATUSREG_TLCLKSEL_STATUS_SHIFT)
+/* PROCMONCFG */ +#define PRCI_PROCMONCFG_OFFSET 0xF0 +#define PRCI_PROCMONCFG_CORE_CLOCK_SHIFT 24 +#define PRCI_PROCMONCFG_CORE_CLOCK_MASK \
(0x1 << PRCI_PROCMONCFG_CORE_CLOCK_SHIFT)
+#define PLL_R(x) \
((x) << PRCI_DDRPLLCFG0_DIVR_SHIFT) &
+PRCI_DDRPLLCFG0_DIVR_MASK #define PLL_F(x) \
((x) << PRCI_DDRPLLCFG0_DIVF_SHIFT) &
+PRCI_DDRPLLCFG0_DIVF_MASK #define PLL_Q(x) \
((x) << PRCI_DDRPLLCFG0_DIVQ_SHIFT) &
+PRCI_DDRPLLCFG0_DIVQ_MASK #define PLL_RANGE(x) \
((x) << PRCI_DDRPLLCFG0_RANGE_SHIFT) &
+PRCI_DDRPLLCFG0_RANGE_MASK #define PLL_BYPASS(x) \
((x) << PRCI_DDRPLLCFG0_BYPASS_SHIFT) &
+PRCI_DDRPLLCFG0_BYPASS_MASK #define PLL_FSE(x) \
((x) << PRCI_DDRPLLCFG0_FSE_SHIFT) & PRCI_DDRPLLCFG0_FSE_MASK
+#define PLL_LOCK(x) \
((x) << PRCI_DDRPLLCFG0_LOCK_SHIFT) &
+PRCI_DDRPLLCFG0_LOCK_MASK
/*
- Private structures
*/ @@ -654,6 +679,93 @@ static int sifive_fu540_prci_disable(struct clk *clk) return pc->ops->enable_clk(pc, 0); }
+#ifdef CONFIG_SPL_BUILD +static void corepll_init(struct udevice *dev) {
Will convert corepll into DM
u32 v;
struct clk clock;
struct __prci_data *pd = dev_get_priv(dev);
v = __prci_readl(pd, PRCI_CLKMUXSTATUSREG_OFFSET);
v &= PRCI_CLKMUXSTATUSREG_TLCLKSEL_STATUS_MASK;
clock.id = PRCI_CLK_COREPLL;
if (v) {
/* corepll 500 Mhz */
sifive_fu540_prci_set_rate(&clock, 500UL * MHz);
} else {
/* corepll 1 Ghz */
sifive_fu540_prci_set_rate(&clock, 1000UL * MHz);
}
sifive_fu540_prci_clock_enable(&__prci_init_clocks[clock.id],
+1); }
+static void ddr_init(struct udevice *dev) {
u32 v;
struct clk clock;
struct __prci_data *pd = dev_get_priv(dev);
//DDR init
u32 ddrctlmhz =
(PLL_R(0)) |
(PLL_F(DDRCTLPLL_F)) |
(PLL_Q(DDRCTLPLL_Q)) |
(PLL_RANGE(0x4)) |
(PLL_BYPASS(0)) |
(PLL_FSE(1));
__prci_writel(ddrctlmhz, PRCI_DDRPLLCFG0_OFFSET, pd);
clock.id = PRCI_CLK_DDRPLL;
sifive_fu540_prci_clock_enable(&__prci_init_clocks[clock.id],
- 1);
/* Release DDR reset */
v = __prci_readl(pd, PRCI_DEVICESRESETREG_OFFSET);
v |= PRCI_DEVICESRESETREG_DDR_CTRL_RST_N_MASK;
__prci_writel(v, PRCI_DEVICESRESETREG_OFFSET, pd);
// HACK to get the '1 full controller clock cycle'.
asm volatile ("fence");
v = __prci_readl(pd, PRCI_DEVICESRESETREG_OFFSET);
v |= (PRCI_DEVICESRESETREG_DDR_AXI_RST_N_MASK |
PRCI_DEVICESRESETREG_DDR_AHB_RST_N_MASK |
PRCI_DEVICESRESETREG_DDR_PHY_RST_N_MASK);
__prci_writel(v, PRCI_DEVICESRESETREG_OFFSET, pd);
// 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");
+}
With DDR clock DM, DDR clock can be enabled by clk_enable() and set rate with clk_set_rate() but after this DDR clock Reset needs to be released as shown below,
/* Release DDR reset */ v = __prci_readl(pd, PRCI_DEVICESRESETREG_OFFSET); v |= PRCI_DEVICESRESETREG_DDR_CTRL_RST_N_MASK; __prci_writel(v, PRCI_DEVICESRESETREG_OFFSET, pd);
Do you guys have any suggestion how to Release DDR reset in DM way in SPL or current implementation is fine for DDR clock initialization ?
Is it possible to do the DDR reset as part of the clk_enable() for the DDR clock?
+static void ethernet_init(struct udevice *dev) {
u32 v;
struct clk clock;
struct __prci_data *pd = dev_get_priv(dev);
/* GEMGXL init */
clock.id = PRCI_CLK_GEMGXLPLL;
sifive_fu540_prci_set_rate(&clock, 125UL * MHz);
sifive_fu540_prci_clock_enable(&__prci_init_clocks[clock.id],
- 1);
/* Release GEMGXL reset */
v = __prci_readl(pd, PRCI_DEVICESRESETREG_OFFSET);
v |= PRCI_DEVICESRESETREG_GEMGXL_RST_N_MASK;
__prci_writel(v, PRCI_DEVICESRESETREG_OFFSET, pd);
/* Procmon => core clock */
__prci_writel(PRCI_PROCMONCFG_CORE_CLOCK_MASK,
PRCI_PROCMONCFG_OFFSET,
pd);
+}
SPL performs ethernet PHY reset sequence (board/sifive/fu540/spl.c - "gem_phy_reset") and for that ethernet clock needs to be enabled. So I am not planning to make any changes in ethernet_init() in v7
If performing DDR reset is not possible with clk_enable, we can leave that here ...
Any suggestions are welcome
Regards, Bin

Hi Bin,
-----Original Message----- From: Bin Meng bmeng.cn@gmail.com Sent: 27 April 2020 06:54 To: Pragnesh Patel pragnesh.patel@sifive.com Cc: Jagan Teki jagan@amarulasolutions.com; U-Boot-Denx <u- boot@lists.denx.de>; Atish Patra atish.patra@wdc.com; palmerdabbelt@google.com; Paul Walmsley paul.walmsley@sifive.com; Troy Benjegerdes troy.benjegerdes@sifive.com; Anup Patel anup.patel@wdc.com; Sagar Kadam sagar.kadam@sifive.com; Rick Chen rick@andestech.com; Lukasz Majewski lukma@denx.de; Simon Glass sjg@chromium.org Subject: Re: [PATCH v6 09/17] clk: sifive: fu540-prci: Add clock initialization for SPL
[External Email] Do not click links or attachments unless you recognize the sender and know the content is safe
Hi Pragnesh,
On Sun, Apr 26, 2020 at 6:00 PM Pragnesh Patel pragnesh.patel@sifive.com wrote:
Hi Jagan, Bin
-----Original Message----- From: Jagan Teki jagan@amarulasolutions.com Sent: 07 April 2020 01:06 To: Pragnesh Patel pragnesh.patel@sifive.com Cc: U-Boot-Denx u-boot@lists.denx.de; Atish Patra atish.patra@wdc.com; palmerdabbelt@google.com; Bin Meng bmeng.cn@gmail.com; Paul Walmsley paul.walmsley@sifive.com;
Troy
Benjegerdes troy.benjegerdes@sifive.com; Anup Patel anup.patel@wdc.com; Sagar Kadam sagar.kadam@sifive.com; Rick
Chen
rick@andestech.com; Lukasz Majewski lukma@denx.de; Simon Glass sjg@chromium.org Subject: Re: [PATCH v6 09/17] clk: sifive: fu540-prci: Add clock initialization for SPL
[External Email] Do not click links or attachments unless you recognize the sender and know the content is safe
On Sun, Mar 29, 2020 at 10:37 PM Pragnesh Patel pragnesh.patel@sifive.com wrote:
Set corepll, ddrpll and ethernet PLL for u-boot-spl
Signed-off-by: Pragnesh Patel pragnesh.patel@sifive.com
drivers/clk/sifive/fu540-prci.c | 118 ++++++++++++++++++++++++++++++++ 1 file changed, 118 insertions(+)
diff --git a/drivers/clk/sifive/fu540-prci.c b/drivers/clk/sifive/fu540-prci.c index e6214cd821..3a73c2c8d1 100644 --- a/drivers/clk/sifive/fu540-prci.c +++ b/drivers/clk/sifive/fu540-prci.c @@ -41,6 +41,10 @@ #include <linux/clk/analogbits-wrpll-cln28hpc.h> #include <dt-bindings/clock/sifive-fu540-prci.h>
+#define DDRCTLPLL_F 55 +#define DDRCTLPLL_Q 2 +#define MHz 1000000
/*
- EXPECTED_CLK_PARENT_COUNT: how many parent clocks this driver
expects:
hfclk and rtcclk
@@ -152,6 +156,27 @@ #define PRCI_CLKMUXSTATUSREG_TLCLKSEL_STATUS_MASK \ (0x1 << PRCI_CLKMUXSTATUSREG_TLCLKSEL_STATUS_SHIFT)
+/* PROCMONCFG */ +#define PRCI_PROCMONCFG_OFFSET 0xF0 +#define PRCI_PROCMONCFG_CORE_CLOCK_SHIFT 24 +#define PRCI_PROCMONCFG_CORE_CLOCK_MASK \
(0x1 << PRCI_PROCMONCFG_CORE_CLOCK_SHIFT)
+#define PLL_R(x) \
((x) << PRCI_DDRPLLCFG0_DIVR_SHIFT) &
+PRCI_DDRPLLCFG0_DIVR_MASK #define PLL_F(x) \
((x) << PRCI_DDRPLLCFG0_DIVF_SHIFT) &
+PRCI_DDRPLLCFG0_DIVF_MASK #define PLL_Q(x) \
((x) << PRCI_DDRPLLCFG0_DIVQ_SHIFT) &
+PRCI_DDRPLLCFG0_DIVQ_MASK #define PLL_RANGE(x) \
((x) << PRCI_DDRPLLCFG0_RANGE_SHIFT) &
+PRCI_DDRPLLCFG0_RANGE_MASK #define PLL_BYPASS(x) \
((x) << PRCI_DDRPLLCFG0_BYPASS_SHIFT) &
+PRCI_DDRPLLCFG0_BYPASS_MASK #define PLL_FSE(x) \
((x) << PRCI_DDRPLLCFG0_FSE_SHIFT) &
+PRCI_DDRPLLCFG0_FSE_MASK #define PLL_LOCK(x) \
((x) << PRCI_DDRPLLCFG0_LOCK_SHIFT) &
+PRCI_DDRPLLCFG0_LOCK_MASK
/*
- Private structures
*/ @@ -654,6 +679,93 @@ static int sifive_fu540_prci_disable(struct clk
*clk)
return pc->ops->enable_clk(pc, 0); }
+#ifdef CONFIG_SPL_BUILD +static void corepll_init(struct udevice *dev) {
Will convert corepll into DM
u32 v;
struct clk clock;
struct __prci_data *pd = dev_get_priv(dev);
v = __prci_readl(pd, PRCI_CLKMUXSTATUSREG_OFFSET);
v &= PRCI_CLKMUXSTATUSREG_TLCLKSEL_STATUS_MASK;
clock.id = PRCI_CLK_COREPLL;
if (v) {
/* corepll 500 Mhz */
sifive_fu540_prci_set_rate(&clock, 500UL * MHz);
} else {
/* corepll 1 Ghz */
sifive_fu540_prci_set_rate(&clock, 1000UL * MHz);
}
+sifive_fu540_prci_clock_enable(&__prci_init_clocks[clock.id], +1); }
+static void ddr_init(struct udevice *dev) {
u32 v;
struct clk clock;
struct __prci_data *pd = dev_get_priv(dev);
//DDR init
u32 ddrctlmhz =
(PLL_R(0)) |
(PLL_F(DDRCTLPLL_F)) |
(PLL_Q(DDRCTLPLL_Q)) |
(PLL_RANGE(0x4)) |
(PLL_BYPASS(0)) |
(PLL_FSE(1));
__prci_writel(ddrctlmhz, PRCI_DDRPLLCFG0_OFFSET, pd);
clock.id = PRCI_CLK_DDRPLL;
- sifive_fu540_prci_clock_enable(&__prci_init_clocks[clock.id],
- 1);
/* Release DDR reset */
v = __prci_readl(pd, PRCI_DEVICESRESETREG_OFFSET);
v |= PRCI_DEVICESRESETREG_DDR_CTRL_RST_N_MASK;
__prci_writel(v, PRCI_DEVICESRESETREG_OFFSET, pd);
// HACK to get the '1 full controller clock cycle'.
asm volatile ("fence");
v = __prci_readl(pd, PRCI_DEVICESRESETREG_OFFSET);
v |= (PRCI_DEVICESRESETREG_DDR_AXI_RST_N_MASK |
PRCI_DEVICESRESETREG_DDR_AHB_RST_N_MASK |
PRCI_DEVICESRESETREG_DDR_PHY_RST_N_MASK);
__prci_writel(v, PRCI_DEVICESRESETREG_OFFSET, pd);
// 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"); }
With DDR clock DM, DDR clock can be enabled by clk_enable() and set rate with clk_set_rate() but after this DDR clock Reset needs to be released as shown below,
/* Release DDR reset */ v = __prci_readl(pd, PRCI_DEVICESRESETREG_OFFSET); v |= PRCI_DEVICESRESETREG_DDR_CTRL_RST_N_MASK; __prci_writel(v, PRCI_DEVICESRESETREG_OFFSET, pd);
Do you guys have any suggestion how to Release DDR reset in DM way in SPL or current implementation is fine for DDR clock initialization ?
Is it possible to do the DDR reset as part of the clk_enable() for the DDR clock?
Yes, I will do DDR release reset adter clk_enable() in v7.
+static void ethernet_init(struct udevice *dev) {
u32 v;
struct clk clock;
struct __prci_data *pd = dev_get_priv(dev);
/* GEMGXL init */
clock.id = PRCI_CLK_GEMGXLPLL;
sifive_fu540_prci_set_rate(&clock, 125UL * MHz);
- sifive_fu540_prci_clock_enable(&__prci_init_clocks[clock.id],
- 1);
/* Release GEMGXL reset */
v = __prci_readl(pd, PRCI_DEVICESRESETREG_OFFSET);
v |= PRCI_DEVICESRESETREG_GEMGXL_RST_N_MASK;
__prci_writel(v, PRCI_DEVICESRESETREG_OFFSET, pd);
/* Procmon => core clock */
__prci_writel(PRCI_PROCMONCFG_CORE_CLOCK_MASK,
PRCI_PROCMONCFG_OFFSET,
pd);
+}
SPL performs ethernet PHY reset sequence (board/sifive/fu540/spl.c -
"gem_phy_reset") and for that ethernet clock needs to be enabled.
So I am not planning to make any changes in ethernet_init() in v7
If performing DDR reset is not possible with clk_enable, we can leave that here ...
@Bin Meng I think you misunderstood, I am talking about ethernet_init() not DDR. I am not planning to use DM for ethernet clock because of PHY reset sequence.
Any suggestions are welcome
Regards, Bin

This sync has changes required to use GPIO in U-Boot and U-Boot SPL.
Signed-off-by: Pragnesh Patel pragnesh.patel@sifive.com --- arch/riscv/dts/fu540-c000.dtsi | 37 ++++++++++++++++++++++++- arch/riscv/dts/hifive-unleashed-a00.dts | 9 ++++++ 2 files changed, 45 insertions(+), 1 deletion(-)
diff --git a/arch/riscv/dts/fu540-c000.dtsi b/arch/riscv/dts/fu540-c000.dtsi index afa43c7ea3..7db8610534 100644 --- a/arch/riscv/dts/fu540-c000.dtsi +++ b/arch/riscv/dts/fu540-c000.dtsi @@ -54,6 +54,7 @@ reg = <1>; riscv,isa = "rv64imafdc"; tlb-split; + next-level-cache = <&l2cache>; cpu1_intc: interrupt-controller { #interrupt-cells = <1>; compatible = "riscv,cpu-intc"; @@ -77,6 +78,7 @@ reg = <2>; riscv,isa = "rv64imafdc"; tlb-split; + next-level-cache = <&l2cache>; cpu2_intc: interrupt-controller { #interrupt-cells = <1>; compatible = "riscv,cpu-intc"; @@ -100,6 +102,7 @@ reg = <3>; riscv,isa = "rv64imafdc"; tlb-split; + next-level-cache = <&l2cache>; cpu3_intc: interrupt-controller { #interrupt-cells = <1>; compatible = "riscv,cpu-intc"; @@ -123,6 +126,7 @@ reg = <4>; riscv,isa = "rv64imafdc"; tlb-split; + next-level-cache = <&l2cache>; cpu4_intc: interrupt-controller { #interrupt-cells = <1>; compatible = "riscv,cpu-intc"; @@ -162,6 +166,13 @@ clocks = <&prci PRCI_CLK_TLCLK>; status = "disabled"; }; + dma: dma@3000000 { + compatible = "sifive,fu540-c000-pdma"; + reg = <0x0 0x3000000 0x0 0x8000>; + interrupt-parent = <&plic0>; + interrupts = <23 24 25 26 27 28 29 30>; + #dma-cells = <1>; + }; uart1: serial@10011000 { compatible = "sifive,fu540-c000-uart", "sifive,uart0"; reg = <0x0 0x10011000 0x0 0x1000>; @@ -246,6 +257,30 @@ #pwm-cells = <3>; status = "disabled"; }; - + l2cache: cache-controller@2010000 { + compatible = "sifive,fu540-c000-ccache", "cache"; + cache-block-size = <64>; + cache-level = <2>; + cache-sets = <1024>; + cache-size = <2097152>; + cache-unified; + interrupt-parent = <&plic0>; + interrupts = <1 2 3>; + reg = <0x0 0x2010000 0x0 0x1000>; + }; + gpio: gpio@10060000 { + compatible = "sifive,fu540-c000-gpio", "sifive,gpio0"; + interrupt-parent = <&plic0>; + interrupts = <7>, <8>, <9>, <10>, <11>, <12>, <13>, + <14>, <15>, <16>, <17>, <18>, <19>, <20>, + <21>, <22>; + reg = <0x0 0x10060000 0x0 0x1000>; + gpio-controller; + #gpio-cells = <2>; + interrupt-controller; + #interrupt-cells = <2>; + clocks = <&prci PRCI_CLK_TLCLK>; + status = "disabled"; + }; }; }; diff --git a/arch/riscv/dts/hifive-unleashed-a00.dts b/arch/riscv/dts/hifive-unleashed-a00.dts index 88cfcb96bf..4a2729f5ca 100644 --- a/arch/riscv/dts/hifive-unleashed-a00.dts +++ b/arch/riscv/dts/hifive-unleashed-a00.dts @@ -2,6 +2,7 @@ /* Copyright (c) 2018-2019 SiFive, Inc */
#include "fu540-c000.dtsi" +#include <dt-bindings/gpio/gpio.h>
/* Clock frequency (in Hz) of the PCB crystal for rtcclk */ #define RTCCLK_FREQ 1000000 @@ -41,6 +42,10 @@ clock-frequency = <RTCCLK_FREQ>; clock-output-names = "rtcclk"; }; + gpio-restart { + compatible = "gpio-restart"; + gpios = <&gpio 10 GPIO_ACTIVE_LOW>; + }; };
&uart0 { @@ -94,3 +99,7 @@ &pwm1 { status = "okay"; }; + +&gpio { + status = "okay"; +};

On Sun, Mar 29, 2020 at 10:37 PM Pragnesh Patel pragnesh.patel@sifive.com wrote:
This sync has changes required to use GPIO in U-Boot and U-Boot SPL.
Signed-off-by: Pragnesh Patel pragnesh.patel@sifive.com
arch/riscv/dts/fu540-c000.dtsi | 37 ++++++++++++++++++++++++- arch/riscv/dts/hifive-unleashed-a00.dts | 9 ++++++ 2 files changed, 45 insertions(+), 1 deletion(-)
Would be better to sync whole changes with specific sha1 from Linux instead of pulling required pieces, this would help for periodic sync and gets updated with Linux dts.
Jagan.

Hi Jagan,
-----Original Message----- From: Jagan Teki jagan@amarulasolutions.com Sent: 07 April 2020 01:07 To: Pragnesh Patel pragnesh.patel@sifive.com Cc: U-Boot-Denx u-boot@lists.denx.de; Atish Patra atish.patra@wdc.com; palmerdabbelt@google.com; Bin Meng bmeng.cn@gmail.com; Paul Walmsley paul.walmsley@sifive.com; Troy Benjegerdes troy.benjegerdes@sifive.com; Anup Patel anup.patel@wdc.com; Sagar Kadam sagar.kadam@sifive.com; Rick Chen rick@andestech.com Subject: Re: [PATCH v6 10/17] riscv: dts: sifive: Sync hifive-unleashed-a00 dts from linux
[External Email] Do not click links or attachments unless you recognize the sender and know the content is safe
On Sun, Mar 29, 2020 at 10:37 PM Pragnesh Patel pragnesh.patel@sifive.com wrote:
This sync has changes required to use GPIO in U-Boot and U-Boot SPL.
Signed-off-by: Pragnesh Patel pragnesh.patel@sifive.com
arch/riscv/dts/fu540-c000.dtsi | 37 ++++++++++++++++++++++++- arch/riscv/dts/hifive-unleashed-a00.dts | 9 ++++++ 2 files changed, 45 insertions(+), 1 deletion(-)
Would be better to sync whole changes with specific sha1 from Linux instead of pulling required pieces, this would help for periodic sync and gets updated with Linux dts.
This DTS files are copy of Linux DTS but yes it's better to add sha1 in commit description. Will update description in v7.
Jagan.

On Mon, Mar 30, 2020 at 1:07 AM Pragnesh Patel pragnesh.patel@sifive.com wrote:
This sync has changes required to use GPIO in U-Boot and U-Boot SPL.
Signed-off-by: Pragnesh Patel pragnesh.patel@sifive.com
arch/riscv/dts/fu540-c000.dtsi | 37 ++++++++++++++++++++++++- arch/riscv/dts/hifive-unleashed-a00.dts | 9 ++++++ 2 files changed, 45 insertions(+), 1 deletion(-)
Reviewed-by: Bin Meng bmeng.cn@gmail.com

Add gpio node for U-Boot SPL
Signed-off-by: Pragnesh Patel pragnesh.patel@sifive.com --- arch/riscv/dts/hifive-unleashed-a00-u-boot.dtsi | 4 ++++ 1 file changed, 4 insertions(+)
diff --git a/arch/riscv/dts/hifive-unleashed-a00-u-boot.dtsi b/arch/riscv/dts/hifive-unleashed-a00-u-boot.dtsi index af8c3e904c..b83f6afe4f 100644 --- a/arch/riscv/dts/hifive-unleashed-a00-u-boot.dtsi +++ b/arch/riscv/dts/hifive-unleashed-a00-u-boot.dtsi @@ -21,3 +21,7 @@ u-boot,dm-spl; }; }; + +&gpio { + u-boot,dm-spl; +};

On Mon, Mar 30, 2020 at 1:07 AM Pragnesh Patel pragnesh.patel@sifive.com wrote:
Add gpio node for U-Boot SPL
Signed-off-by: Pragnesh Patel pragnesh.patel@sifive.com
arch/riscv/dts/hifive-unleashed-a00-u-boot.dtsi | 4 ++++ 1 file changed, 4 insertions(+)
Reviewed-by: Bin Meng bmeng.cn@gmail.com

Add a support for SPL which will boot from L2 LIM (0x0800_0000) and then boot U-boot FIT image including OpenSBI FW_DYNAMIC firmware and U-Boot proper images from 1st partition of MMC boot devices.
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/Makefile | 1 + arch/riscv/fu540/Makefile | 11 ++++ arch/riscv/fu540/spl.c | 30 +++++++++ arch/riscv/include/asm/arch-generic/gpio.h | 3 + arch/riscv/include/asm/arch-generic/spl.h | 14 +++++ board/sifive/fu540/Kconfig | 8 +++ board/sifive/fu540/Makefile | 4 ++ board/sifive/fu540/fu540.c | 24 ++++++++ board/sifive/fu540/spl.c | 72 ++++++++++++++++++++++ include/configs/sifive-fu540.h | 18 ++++++ 10 files changed, 185 insertions(+) create mode 100644 arch/riscv/fu540/Makefile create mode 100644 arch/riscv/fu540/spl.c create mode 100644 arch/riscv/include/asm/arch-generic/spl.h create mode 100644 board/sifive/fu540/spl.c
diff --git a/arch/riscv/Makefile b/arch/riscv/Makefile index 0b80eb8d86..599ae8d77d 100644 --- a/arch/riscv/Makefile +++ b/arch/riscv/Makefile @@ -35,3 +35,4 @@ head-y := arch/riscv/cpu/start.o libs-y += arch/riscv/cpu/ libs-y += arch/riscv/cpu/$(CPU)/ libs-y += arch/riscv/lib/ +libs-y += arch/riscv/fu540/ diff --git a/arch/riscv/fu540/Makefile b/arch/riscv/fu540/Makefile new file mode 100644 index 0000000000..e3b40ae7d4 --- /dev/null +++ b/arch/riscv/fu540/Makefile @@ -0,0 +1,11 @@ +# SPDX-License-Identifier: GPL-2.0+ +# +# Copyright (C) 2020 SiFive, Inc +# Pragnesh Patel pragnesh.patel@sifive.com + +ifeq ($(CONFIG_SPL_BUILD),y) +obj-$(CONFIG_TARGET_SIFIVE_FU540) += spl.o +else +# necessary to create built-in.o +obj- += __dummy__.o +endif diff --git a/arch/riscv/fu540/spl.c b/arch/riscv/fu540/spl.c new file mode 100644 index 0000000000..3d9dea5e30 --- /dev/null +++ b/arch/riscv/fu540/spl.c @@ -0,0 +1,30 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright (C) 2020 SiFive, Inc + * Pragnesh Patel pragnesh.patel@sifive.com + */ + +#include <common.h> +#include <dm.h> + +int soc_spl_init(void) +{ + int ret; + struct udevice *dev; + + /* PRCI init */ + ret = uclass_get_device(UCLASS_CLK, 0, &dev); + if (ret) { + debug("Clock init failed: %d\n", ret); + return ret; + } + + /* DDR init */ + ret = uclass_get_device(UCLASS_RAM, 0, &dev); + if (ret) { + debug("DRAM init failed: %d\n", ret); + return ret; + } + + return 0; +} diff --git a/arch/riscv/include/asm/arch-generic/gpio.h b/arch/riscv/include/asm/arch-generic/gpio.h index dfcb753051..0d16c59ca6 100644 --- a/arch/riscv/include/asm/arch-generic/gpio.h +++ b/arch/riscv/include/asm/arch-generic/gpio.h @@ -32,4 +32,7 @@ struct sifive_gpio_platdata { void *base; /* address of registers in physical memory */ };
+#define SIFIVE_GENERIC_GPIO_NR(port, index) \ + (((port) * NR_GPIOS) + ((index) & (NR_GPIOS - 1))) + #endif /* _GPIO_SIFIVE_H */ diff --git a/arch/riscv/include/asm/arch-generic/spl.h b/arch/riscv/include/asm/arch-generic/spl.h new file mode 100644 index 0000000000..0c188be747 --- /dev/null +++ b/arch/riscv/include/asm/arch-generic/spl.h @@ -0,0 +1,14 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ +/* + * Copyright (C) 2020 SiFive, Inc. + * + * Authors: + * Pragnesh Patel pragnesh.patel@sifve.com + */ + +#ifndef _SPL_SIFIVE_H +#define _SPL_SIFIVE_H + +int soc_spl_init(void); + +#endif /* _SPL_SIFIVE_H */ diff --git a/board/sifive/fu540/Kconfig b/board/sifive/fu540/Kconfig index 900197bbb2..ebe3472f9a 100644 --- a/board/sifive/fu540/Kconfig +++ b/board/sifive/fu540/Kconfig @@ -13,12 +13,20 @@ config SYS_CONFIG_NAME default "sifive-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/Makefile b/board/sifive/fu540/Makefile index 6e1862c475..b05e2f5807 100644 --- a/board/sifive/fu540/Makefile +++ b/board/sifive/fu540/Makefile @@ -3,3 +3,7 @@ # Copyright (c) 2019 Western Digital Corporation or its affiliates.
obj-y += fu540.o + +ifdef CONFIG_SPL_BUILD +obj-y += spl.o +endif diff --git a/board/sifive/fu540/fu540.c b/board/sifive/fu540/fu540.c index 540638c919..d05529a86b 100644 --- a/board/sifive/fu540/fu540.c +++ b/board/sifive/fu540/fu540.c @@ -11,6 +11,7 @@ #include <linux/delay.h> #include <linux/io.h> #include <misc.h> +#include <spl.h>
/* * This define is a value used for error/unknown serial. @@ -114,3 +115,26 @@ int board_init(void)
return 0; } + +#ifdef CONFIG_SPL +void board_boot_order(u32 *spl_boot_list) +{ + u8 i; + u32 boot_devices[] = { +#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/spl.c b/board/sifive/fu540/spl.c new file mode 100644 index 0000000000..c0bf7f4d81 --- /dev/null +++ b/board/sifive/fu540/spl.c @@ -0,0 +1,72 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright (c) 2019 SiFive, Inc + * + * Authors: + * Pragnesh Patel pragnesh.patel@sifive.com + */ + +#include <common.h> +#include <spl.h> +#include <misc.h> +#include <asm/gpio.h> +#include <asm/arch/gpio.h> +#include <asm/arch/spl.h> + +#define GEM_PHY_RESET SIFIVE_GENERIC_GPIO_NR(0, 12) + +int init_clk_and_ddr(void) +{ + int ret; + + ret = soc_spl_init(); + if (ret) { + debug("FU540 SPL init failed: %d\n", ret); + return ret; + } + + /* + * GEMGXL init VSC8541 PHY reset sequence; + * leave pull-down active for 2ms + */ + udelay(2000); + ret = gpio_request(GEM_PHY_RESET, "gem_phy_reset"); + if (ret) { + debug("gem_phy_reset gpio request failed: %d\n", ret); + return ret; + } + + /* Set GPIO 12 (PHY NRESET) */ + ret = gpio_direction_output(GEM_PHY_RESET, 1); + if (ret) { + debug("gem_phy_reset gpio direction set failed: %d\n", ret); + return ret; + } + + udelay(1); + + /* Reset PHY again to enter unmanaged mode */ + gpio_set_value(GEM_PHY_RESET, 0); + udelay(1); + gpio_set_value(GEM_PHY_RESET, 1); + mdelay(15); + + return 0; +} + +void board_init_f(ulong dummy) +{ + int ret; + + ret = spl_early_init(); + if (ret) + panic("spl_early_init() failed: %d\n", ret); + + arch_cpu_init_dm(); + + ret = init_clk_and_ddr(); + if (ret) + panic("init_clk_and_ddr() failed: %d\n", ret); + + preloader_console_init(); +} diff --git a/include/configs/sifive-fu540.h b/include/configs/sifive-fu540.h index 2756ed5a77..ef3ae9b650 100644 --- a/include/configs/sifive-fu540.h +++ b/include/configs/sifive-fu540.h @@ -11,6 +11,22 @@
#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 +40,7 @@
/* Environment options */
+#ifndef CONFIG_SPL_BUILD #define BOOT_TARGET_DEVICES(func) \ func(MMC, mmc, 0) \ func(DHCP, dhcp, na) @@ -43,5 +60,6 @@ #define CONFIG_PREBOOT \ "setenv fdt_addr ${fdtcontroladdr};" \ "fdt addr ${fdtcontroladdr};" +#endif
#endif /* __CONFIG_H */

Hi Pragnesh,
On Mon, Mar 30, 2020 at 1:07 AM Pragnesh Patel pragnesh.patel@sifive.com wrote:
Add a support for SPL which will boot from L2 LIM (0x0800_0000) and then boot U-boot FIT image including OpenSBI FW_DYNAMIC firmware
nits: U-Boot
and U-Boot proper images from 1st partition of MMC boot devices.
SPL related code is leverage from FSBL
leveraged
(https://github.com/sifive/freedom-u540-c000-bootloader.git)
Signed-off-by: Pragnesh Patel pragnesh.patel@sifive.com
arch/riscv/Makefile | 1 + arch/riscv/fu540/Makefile | 11 ++++ arch/riscv/fu540/spl.c | 30 +++++++++ arch/riscv/include/asm/arch-generic/gpio.h | 3 + arch/riscv/include/asm/arch-generic/spl.h | 14 +++++ board/sifive/fu540/Kconfig | 8 +++ board/sifive/fu540/Makefile | 4 ++ board/sifive/fu540/fu540.c | 24 ++++++++ board/sifive/fu540/spl.c | 72 ++++++++++++++++++++++ include/configs/sifive-fu540.h | 18 ++++++ 10 files changed, 185 insertions(+) create mode 100644 arch/riscv/fu540/Makefile create mode 100644 arch/riscv/fu540/spl.c create mode 100644 arch/riscv/include/asm/arch-generic/spl.h create mode 100644 board/sifive/fu540/spl.c
diff --git a/arch/riscv/Makefile b/arch/riscv/Makefile index 0b80eb8d86..599ae8d77d 100644 --- a/arch/riscv/Makefile +++ b/arch/riscv/Makefile @@ -35,3 +35,4 @@ head-y := arch/riscv/cpu/start.o libs-y += arch/riscv/cpu/ libs-y += arch/riscv/cpu/$(CPU)/ libs-y += arch/riscv/lib/ +libs-y += arch/riscv/fu540/ diff --git a/arch/riscv/fu540/Makefile b/arch/riscv/fu540/Makefile new file mode 100644 index 0000000000..e3b40ae7d4 --- /dev/null +++ b/arch/riscv/fu540/Makefile @@ -0,0 +1,11 @@ +# SPDX-License-Identifier: GPL-2.0+ +# +# Copyright (C) 2020 SiFive, Inc +# Pragnesh Patel pragnesh.patel@sifive.com
+ifeq ($(CONFIG_SPL_BUILD),y) +obj-$(CONFIG_TARGET_SIFIVE_FU540) += spl.o +else +# necessary to create built-in.o +obj- += __dummy__.o +endif diff --git a/arch/riscv/fu540/spl.c b/arch/riscv/fu540/spl.c new file mode 100644 index 0000000000..3d9dea5e30 --- /dev/null +++ b/arch/riscv/fu540/spl.c
This should be put arch/riscv/cpu/fu540 instead
@@ -0,0 +1,30 @@ +// SPDX-License-Identifier: GPL-2.0+ +/*
- Copyright (C) 2020 SiFive, Inc
- Pragnesh Patel pragnesh.patel@sifive.com
- */
+#include <common.h> +#include <dm.h>
+int soc_spl_init(void) +{
int ret;
struct udevice *dev;
/* PRCI init */
ret = uclass_get_device(UCLASS_CLK, 0, &dev);
if (ret) {
debug("Clock init failed: %d\n", ret);
return ret;
}
/* DDR init */
ret = uclass_get_device(UCLASS_RAM, 0, &dev);
if (ret) {
debug("DRAM init failed: %d\n", ret);
return ret;
}
return 0;
+} diff --git a/arch/riscv/include/asm/arch-generic/gpio.h b/arch/riscv/include/asm/arch-generic/gpio.h index dfcb753051..0d16c59ca6 100644 --- a/arch/riscv/include/asm/arch-generic/gpio.h +++ b/arch/riscv/include/asm/arch-generic/gpio.h @@ -32,4 +32,7 @@ struct sifive_gpio_platdata { void *base; /* address of registers in physical memory */ };
+#define SIFIVE_GENERIC_GPIO_NR(port, index) \
(((port) * NR_GPIOS) + ((index) & (NR_GPIOS - 1)))
#endif /* _GPIO_SIFIVE_H */ diff --git a/arch/riscv/include/asm/arch-generic/spl.h b/arch/riscv/include/asm/arch-generic/spl.h new file mode 100644 index 0000000000..0c188be747 --- /dev/null +++ b/arch/riscv/include/asm/arch-generic/spl.h
This should be arch/riscv/include/asm/arch-fu540/spl.h
@@ -0,0 +1,14 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ +/*
- Copyright (C) 2020 SiFive, Inc.
- Authors:
- Pragnesh Patel pragnesh.patel@sifve.com
- */
+#ifndef _SPL_SIFIVE_H +#define _SPL_SIFIVE_H
+int soc_spl_init(void);
+#endif /* _SPL_SIFIVE_H */ diff --git a/board/sifive/fu540/Kconfig b/board/sifive/fu540/Kconfig index 900197bbb2..ebe3472f9a 100644 --- a/board/sifive/fu540/Kconfig +++ b/board/sifive/fu540/Kconfig @@ -13,12 +13,20 @@ config SYS_CONFIG_NAME default "sifive-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/Makefile b/board/sifive/fu540/Makefile index 6e1862c475..b05e2f5807 100644 --- a/board/sifive/fu540/Makefile +++ b/board/sifive/fu540/Makefile @@ -3,3 +3,7 @@ # Copyright (c) 2019 Western Digital Corporation or its affiliates.
obj-y += fu540.o
+ifdef CONFIG_SPL_BUILD +obj-y += spl.o +endif diff --git a/board/sifive/fu540/fu540.c b/board/sifive/fu540/fu540.c index 540638c919..d05529a86b 100644 --- a/board/sifive/fu540/fu540.c +++ b/board/sifive/fu540/fu540.c @@ -11,6 +11,7 @@ #include <linux/delay.h> #include <linux/io.h> #include <misc.h> +#include <spl.h>
/*
- This define is a value used for error/unknown serial.
@@ -114,3 +115,26 @@ int board_init(void)
return 0;
}
+#ifdef CONFIG_SPL +void board_boot_order(u32 *spl_boot_list) +{
u8 i;
u32 boot_devices[] = {
+#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/spl.c b/board/sifive/fu540/spl.c new file mode 100644 index 0000000000..c0bf7f4d81 --- /dev/null +++ b/board/sifive/fu540/spl.c @@ -0,0 +1,72 @@ +// SPDX-License-Identifier: GPL-2.0+ +/*
- Copyright (c) 2019 SiFive, Inc
- Authors:
- Pragnesh Patel pragnesh.patel@sifive.com
- */
+#include <common.h> +#include <spl.h> +#include <misc.h> +#include <asm/gpio.h> +#include <asm/arch/gpio.h> +#include <asm/arch/spl.h>
+#define GEM_PHY_RESET SIFIVE_GENERIC_GPIO_NR(0, 12)
+int init_clk_and_ddr(void) +{
int ret;
ret = soc_spl_init();
if (ret) {
debug("FU540 SPL init failed: %d\n", ret);
return ret;
}
/*
* GEMGXL init VSC8541 PHY reset sequence;
* leave pull-down active for 2ms
*/
udelay(2000);
ret = gpio_request(GEM_PHY_RESET, "gem_phy_reset");
if (ret) {
debug("gem_phy_reset gpio request failed: %d\n", ret);
return ret;
}
/* Set GPIO 12 (PHY NRESET) */
ret = gpio_direction_output(GEM_PHY_RESET, 1);
if (ret) {
debug("gem_phy_reset gpio direction set failed: %d\n", ret);
return ret;
}
udelay(1);
/* Reset PHY again to enter unmanaged mode */
gpio_set_value(GEM_PHY_RESET, 0);
udelay(1);
gpio_set_value(GEM_PHY_RESET, 1);
mdelay(15);
return 0;
+}
+void board_init_f(ulong dummy) +{
int ret;
ret = spl_early_init();
if (ret)
panic("spl_early_init() failed: %d\n", ret);
arch_cpu_init_dm();
ret = init_clk_and_ddr();
if (ret)
panic("init_clk_and_ddr() failed: %d\n", ret);
preloader_console_init();
+} diff --git a/include/configs/sifive-fu540.h b/include/configs/sifive-fu540.h index 2756ed5a77..ef3ae9b650 100644 --- a/include/configs/sifive-fu540.h +++ b/include/configs/sifive-fu540.h @@ -11,6 +11,22 @@
#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 +40,7 @@
/* Environment options */
+#ifndef CONFIG_SPL_BUILD #define BOOT_TARGET_DEVICES(func) \ func(MMC, mmc, 0) \ func(DHCP, dhcp, na) @@ -43,5 +60,6 @@ #define CONFIG_PREBOOT \ "setenv fdt_addr ${fdtcontroladdr};" \ "fdt addr ${fdtcontroladdr};" +#endif
#endif /* __CONFIG_H */
Regards, Bin

Hi Bin,
-----Original Message----- From: Bin Meng bmeng.cn@gmail.com Sent: 20 April 2020 15:05 To: Pragnesh Patel pragnesh.patel@sifive.com Cc: U-Boot Mailing List u-boot@lists.denx.de; Atish Patra atish.patra@wdc.com; Palmer Dabbelt palmerdabbelt@google.com; Paul Walmsley paul.walmsley@sifive.com; Jagan Teki jagan@amarulasolutions.com; Troy Benjegerdes troy.benjegerdes@sifive.com; Anup Patel anup.patel@wdc.com; Sagar Kadam sagar.kadam@sifive.com; Rick Chen rick@andestech.com; Palmer Dabbelt palmer@dabbelt.com Subject: Re: [PATCH v6 12/17] riscv: sifive: fu540: add SPL configuration
[External Email] Do not click links or attachments unless you recognize the sender and know the content is safe
Hi Pragnesh,
On Mon, Mar 30, 2020 at 1:07 AM Pragnesh Patel pragnesh.patel@sifive.com wrote:
Add a support for SPL which will boot from L2 LIM (0x0800_0000) and then boot U-boot FIT image including OpenSBI FW_DYNAMIC firmware
nits: U-Boot
Will update in v7.
and U-Boot proper images from 1st partition of MMC boot devices.
SPL related code is leverage from FSBL
leveraged
Will update
(https://github.com/sifive/freedom-u540-c000-bootloader.git)
Signed-off-by: Pragnesh Patel pragnesh.patel@sifive.com
arch/riscv/Makefile | 1 + arch/riscv/fu540/Makefile | 11 ++++ arch/riscv/fu540/spl.c | 30 +++++++++ arch/riscv/include/asm/arch-generic/gpio.h | 3 + arch/riscv/include/asm/arch-generic/spl.h | 14 +++++ board/sifive/fu540/Kconfig | 8 +++ board/sifive/fu540/Makefile | 4 ++ board/sifive/fu540/fu540.c | 24 ++++++++ board/sifive/fu540/spl.c | 72 ++++++++++++++++++++++ include/configs/sifive-fu540.h | 18 ++++++ 10 files changed, 185 insertions(+) create mode 100644 arch/riscv/fu540/Makefile create mode 100644 arch/riscv/fu540/spl.c create mode 100644 arch/riscv/include/asm/arch-generic/spl.h create mode 100644 board/sifive/fu540/spl.c
diff --git a/arch/riscv/Makefile b/arch/riscv/Makefile index 0b80eb8d86..599ae8d77d 100644 --- a/arch/riscv/Makefile +++ b/arch/riscv/Makefile @@ -35,3 +35,4 @@ head-y := arch/riscv/cpu/start.o libs-y += arch/riscv/cpu/ libs-y += arch/riscv/cpu/$(CPU)/ libs-y += arch/riscv/lib/ +libs-y += arch/riscv/fu540/ diff --git a/arch/riscv/fu540/Makefile b/arch/riscv/fu540/Makefile new file mode 100644 index 0000000000..e3b40ae7d4 --- /dev/null +++ b/arch/riscv/fu540/Makefile @@ -0,0 +1,11 @@ +# SPDX-License-Identifier: GPL-2.0+ +# +# Copyright (C) 2020 SiFive, Inc +# Pragnesh Patel pragnesh.patel@sifive.com
+ifeq ($(CONFIG_SPL_BUILD),y) +obj-$(CONFIG_TARGET_SIFIVE_FU540) += spl.o else # necessary to create +built-in.o +obj- += __dummy__.o +endif diff --git a/arch/riscv/fu540/spl.c b/arch/riscv/fu540/spl.c new file mode 100644 index 0000000000..3d9dea5e30 --- /dev/null +++ b/arch/riscv/fu540/spl.c
This should be put arch/riscv/cpu/fu540 instead
I think same discussion happened in v5 that arch/riscv/cpu/generic is perfectly fine for FU540. Now it's necessary to add arch/riscv/cpu/fu540 directory.
@Anup Patel Do you have any suggestion on this ?
@@ -0,0 +1,30 @@ +// SPDX-License-Identifier: GPL-2.0+ +/*
- Copyright (C) 2020 SiFive, Inc
- Pragnesh Patel pragnesh.patel@sifive.com
- */
+#include <common.h> +#include <dm.h>
+int soc_spl_init(void) +{
int ret;
struct udevice *dev;
/* PRCI init */
ret = uclass_get_device(UCLASS_CLK, 0, &dev);
if (ret) {
debug("Clock init failed: %d\n", ret);
return ret;
}
/* DDR init */
ret = uclass_get_device(UCLASS_RAM, 0, &dev);
if (ret) {
debug("DRAM init failed: %d\n", ret);
return ret;
}
return 0;
+} diff --git a/arch/riscv/include/asm/arch-generic/gpio.h
b/arch/riscv/include/asm/arch-generic/gpio.h
index dfcb753051..0d16c59ca6 100644 --- a/arch/riscv/include/asm/arch-generic/gpio.h +++ b/arch/riscv/include/asm/arch-generic/gpio.h @@ -32,4 +32,7 @@ struct sifive_gpio_platdata { void *base; /* address of registers in physical memory */ };
+#define SIFIVE_GENERIC_GPIO_NR(port, index) \
(((port) * NR_GPIOS) + ((index) & (NR_GPIOS - 1)))
#endif /* _GPIO_SIFIVE_H */ diff --git a/arch/riscv/include/asm/arch-generic/spl.h
b/arch/riscv/include/asm/arch-generic/spl.h
new file mode 100644 index 0000000000..0c188be747 --- /dev/null +++ b/arch/riscv/include/asm/arch-generic/spl.h
This should be arch/riscv/include/asm/arch-fu540/spl.h
Will update in v7.
@@ -0,0 +1,14 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ +/*
- Copyright (C) 2020 SiFive, Inc.
- Authors:
- Pragnesh Patel pragnesh.patel@sifve.com
- */
+#ifndef _SPL_SIFIVE_H +#define _SPL_SIFIVE_H
+int soc_spl_init(void);
+#endif /* _SPL_SIFIVE_H */ diff --git a/board/sifive/fu540/Kconfig b/board/sifive/fu540/Kconfig index 900197bbb2..ebe3472f9a 100644 --- a/board/sifive/fu540/Kconfig +++ b/board/sifive/fu540/Kconfig @@ -13,12 +13,20 @@ config SYS_CONFIG_NAME default "sifive-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/Makefile b/board/sifive/fu540/Makefile index 6e1862c475..b05e2f5807 100644 --- a/board/sifive/fu540/Makefile +++ b/board/sifive/fu540/Makefile @@ -3,3 +3,7 @@ # Copyright (c) 2019 Western Digital Corporation or its affiliates.
obj-y += fu540.o
+ifdef CONFIG_SPL_BUILD +obj-y += spl.o +endif diff --git a/board/sifive/fu540/fu540.c b/board/sifive/fu540/fu540.c index 540638c919..d05529a86b 100644 --- a/board/sifive/fu540/fu540.c +++ b/board/sifive/fu540/fu540.c @@ -11,6 +11,7 @@ #include <linux/delay.h> #include <linux/io.h> #include <misc.h> +#include <spl.h>
/*
- This define is a value used for error/unknown serial.
@@ -114,3 +115,26 @@ int board_init(void)
return 0;
}
+#ifdef CONFIG_SPL +void board_boot_order(u32 *spl_boot_list) +{
u8 i;
u32 boot_devices[] = {
+#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/spl.c b/board/sifive/fu540/spl.c new file mode 100644 index 0000000000..c0bf7f4d81 --- /dev/null +++ b/board/sifive/fu540/spl.c @@ -0,0 +1,72 @@ +// SPDX-License-Identifier: GPL-2.0+ +/*
- Copyright (c) 2019 SiFive, Inc
- Authors:
- Pragnesh Patel pragnesh.patel@sifive.com
- */
+#include <common.h> +#include <spl.h> +#include <misc.h> +#include <asm/gpio.h> +#include <asm/arch/gpio.h> +#include <asm/arch/spl.h>
+#define GEM_PHY_RESET SIFIVE_GENERIC_GPIO_NR(0, 12)
+int init_clk_and_ddr(void) +{
int ret;
ret = soc_spl_init();
if (ret) {
debug("FU540 SPL init failed: %d\n", ret);
return ret;
}
/*
* GEMGXL init VSC8541 PHY reset sequence;
* leave pull-down active for 2ms
*/
udelay(2000);
ret = gpio_request(GEM_PHY_RESET, "gem_phy_reset");
if (ret) {
debug("gem_phy_reset gpio request failed: %d\n", ret);
return ret;
}
/* Set GPIO 12 (PHY NRESET) */
ret = gpio_direction_output(GEM_PHY_RESET, 1);
if (ret) {
debug("gem_phy_reset gpio direction set failed: %d\n", ret);
return ret;
}
udelay(1);
/* Reset PHY again to enter unmanaged mode */
gpio_set_value(GEM_PHY_RESET, 0);
udelay(1);
gpio_set_value(GEM_PHY_RESET, 1);
mdelay(15);
return 0;
+}
+void board_init_f(ulong dummy) +{
int ret;
ret = spl_early_init();
if (ret)
panic("spl_early_init() failed: %d\n", ret);
arch_cpu_init_dm();
ret = init_clk_and_ddr();
if (ret)
panic("init_clk_and_ddr() failed: %d\n", ret);
preloader_console_init();
+} diff --git a/include/configs/sifive-fu540.h b/include/configs/sifive-fu540.h index 2756ed5a77..ef3ae9b650 100644 --- a/include/configs/sifive-fu540.h +++ b/include/configs/sifive-fu540.h @@ -11,6 +11,22 @@
#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 +40,7 @@
/* Environment options */
+#ifndef CONFIG_SPL_BUILD #define BOOT_TARGET_DEVICES(func) \ func(MMC, mmc, 0) \ func(DHCP, dhcp, na) @@ -43,5 +60,6 @@ #define CONFIG_PREBOOT \ "setenv fdt_addr ${fdtcontroladdr};" \ "fdt addr ${fdtcontroladdr};" +#endif
#endif /* __CONFIG_H */
Regards, Bin

With sifive_fu540_defconfig:
User can use FSBL or u-boot-spl.bin anyone at a time.
For FSBL, fsbl->fw_payload.bin(opensbi+u-boot)
For u-boot-spl.bin, u-boot-spl.bin->FIT image(opensbi+u-boot+dtb)
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 1st partition of SD card (replace fw_payload.bin with u-boot.itb) into RAM.
U-Boot SPL expects u-boot.itb FIT image in the 1st partition of SD card irrespective of GUID
Signed-off-by: Pragnesh Patel pragnesh.patel@sifive.com --- configs/sifive_fu540_defconfig | 11 +++++++++++ 1 file changed, 11 insertions(+)
diff --git a/configs/sifive_fu540_defconfig b/configs/sifive_fu540_defconfig index 6d61e6c960..4fa4e1520f 100644 --- a/configs/sifive_fu540_defconfig +++ b/configs/sifive_fu540_defconfig @@ -12,3 +12,14 @@ CONFIG_DISPLAY_BOARDINFO=y CONFIG_DEFAULT_DEVICE_TREE="hifive-unleashed-a00" CONFIG_SYS_RELOC_GD_ENV_ADDR=y CONFIG_DM_MTD=y +CONFIG_SPL_SEPARATE_BSS=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_SPL_CLK=y +CONFIG_SPL_PAYLOAD="u-boot.itb" +CONFIG_SPL_GPIO_SUPPORT=y +CONFIG_SYS_MALLOC_F_LEN=0x3000 +CONFIG_SIFIVE_FU540_DDR=y

Hi Pragnesh,
On Mon, Mar 30, 2020 at 1:07 AM Pragnesh Patel pragnesh.patel@sifive.com wrote:
With sifive_fu540_defconfig:
User can use FSBL or u-boot-spl.bin anyone at a time.
For FSBL, fsbl->fw_payload.bin(opensbi+u-boot)
nits: need a space before ( and around +
For u-boot-spl.bin, u-boot-spl.bin->FIT image(opensbi+u-boot+dtb)
nits: need a space before ( and around +
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 1st partition of SD card (replace fw_payload.bin with u-boot.itb) into RAM.
U-Boot SPL expects u-boot.itb FIT image in the 1st partition of SD card irrespective of GUID
Signed-off-by: Pragnesh Patel pragnesh.patel@sifive.com
configs/sifive_fu540_defconfig | 11 +++++++++++ 1 file changed, 11 insertions(+)
diff --git a/configs/sifive_fu540_defconfig b/configs/sifive_fu540_defconfig index 6d61e6c960..4fa4e1520f 100644 --- a/configs/sifive_fu540_defconfig +++ b/configs/sifive_fu540_defconfig @@ -12,3 +12,14 @@ CONFIG_DISPLAY_BOARDINFO=y CONFIG_DEFAULT_DEVICE_TREE="hifive-unleashed-a00" CONFIG_SYS_RELOC_GD_ENV_ADDR=y CONFIG_DM_MTD=y +CONFIG_SPL_SEPARATE_BSS=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_SPL_CLK=y +CONFIG_SPL_PAYLOAD="u-boot.itb" +CONFIG_SPL_GPIO_SUPPORT=y +CONFIG_SYS_MALLOC_F_LEN=0x3000
+CONFIG_SIFIVE_FU540_DDR=y
Please do the defconfig update via the following way:
$ make sifive_fu540_defconfig $ make savedefconfig $ cp defconfig configs/sifive_fu540_defconfig
Regards, Bin

Hi Bin,
-----Original Message----- From: Bin Meng bmeng.cn@gmail.com Sent: 20 April 2020 15:05 To: Pragnesh Patel pragnesh.patel@sifive.com Cc: U-Boot Mailing List u-boot@lists.denx.de; Atish Patra atish.patra@wdc.com; Palmer Dabbelt palmerdabbelt@google.com; Paul Walmsley paul.walmsley@sifive.com; Jagan Teki jagan@amarulasolutions.com; Troy Benjegerdes troy.benjegerdes@sifive.com; Anup Patel anup.patel@wdc.com; Sagar Kadam sagar.kadam@sifive.com; Rick Chen rick@andestech.com; Palmer Dabbelt palmer@dabbelt.com Subject: Re: [PATCH v6 13/17] configs: fu540: Add config options for U-Boot SPL
[External Email] Do not click links or attachments unless you recognize the sender and know the content is safe
Hi Pragnesh,
On Mon, Mar 30, 2020 at 1:07 AM Pragnesh Patel pragnesh.patel@sifive.com wrote:
With sifive_fu540_defconfig:
User can use FSBL or u-boot-spl.bin anyone at a time.
For FSBL, fsbl->fw_payload.bin(opensbi+u-boot)
nits: need a space before ( and around +
Will update in v7.
For u-boot-spl.bin, u-boot-spl.bin->FIT image(opensbi+u-boot+dtb)
nits: need a space before ( and around +
Will update in v7.
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 1st partition of SD card (replace fw_payload.bin with u-boot.itb) into RAM.
U-Boot SPL expects u-boot.itb FIT image in the 1st partition of SD card irrespective of GUID
Signed-off-by: Pragnesh Patel pragnesh.patel@sifive.com
configs/sifive_fu540_defconfig | 11 +++++++++++ 1 file changed, 11 insertions(+)
diff --git a/configs/sifive_fu540_defconfig b/configs/sifive_fu540_defconfig index 6d61e6c960..4fa4e1520f 100644 --- a/configs/sifive_fu540_defconfig +++ b/configs/sifive_fu540_defconfig @@ -12,3 +12,14 @@ CONFIG_DISPLAY_BOARDINFO=y CONFIG_DEFAULT_DEVICE_TREE="hifive-unleashed-a00" CONFIG_SYS_RELOC_GD_ENV_ADDR=y CONFIG_DM_MTD=y +CONFIG_SPL_SEPARATE_BSS=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_SPL_CLK=y +CONFIG_SPL_PAYLOAD="u-boot.itb" +CONFIG_SPL_GPIO_SUPPORT=y +CONFIG_SYS_MALLOC_F_LEN=0x3000
+CONFIG_SIFIVE_FU540_DDR=y
Please do the defconfig update via the following way:
$ make sifive_fu540_defconfig $ make savedefconfig $ cp defconfig configs/sifive_fu540_defconfig
Will update in v7.
Regards, Bin

Add L2 cache node to enable cache ways from U-Boot
Signed-off-by: Pragnesh Patel pragnesh.patel@sifive.com --- arch/riscv/dts/fu540-c000-u-boot.dtsi | 4 ++++ 1 file changed, 4 insertions(+)
diff --git a/arch/riscv/dts/fu540-c000-u-boot.dtsi b/arch/riscv/dts/fu540-c000-u-boot.dtsi index 56a45371d4..8f6c9f525d 100644 --- a/arch/riscv/dts/fu540-c000-u-boot.dtsi +++ b/arch/riscv/dts/fu540-c000-u-boot.dtsi @@ -73,3 +73,7 @@ &qspi2 { u-boot,dm-spl; }; + +&l2cache { + status = "okay"; +};

On Mon, Mar 30, 2020 at 1:07 AM Pragnesh Patel pragnesh.patel@sifive.com wrote:
Add L2 cache node to enable cache ways from U-Boot
Signed-off-by: Pragnesh Patel pragnesh.patel@sifive.com
arch/riscv/dts/fu540-c000-u-boot.dtsi | 4 ++++ 1 file changed, 4 insertions(+)
Reviewed-by: Bin Meng bmeng.cn@gmail.com

Enable all cache ways from u-boot proper.
Signed-off-by: Pragnesh Patel pragnesh.patel@sifive.com --- arch/riscv/fu540/Makefile | 3 +- arch/riscv/fu540/cache.c | 58 +++++++++++++++++++++ arch/riscv/include/asm/arch-generic/cache.h | 14 +++++ board/sifive/fu540/fu540.c | 10 +++- 4 files changed, 81 insertions(+), 4 deletions(-) create mode 100644 arch/riscv/fu540/cache.c create mode 100644 arch/riscv/include/asm/arch-generic/cache.h
diff --git a/arch/riscv/fu540/Makefile b/arch/riscv/fu540/Makefile index e3b40ae7d4..3f385e8529 100644 --- a/arch/riscv/fu540/Makefile +++ b/arch/riscv/fu540/Makefile @@ -6,6 +6,5 @@ ifeq ($(CONFIG_SPL_BUILD),y) obj-$(CONFIG_TARGET_SIFIVE_FU540) += spl.o else -# necessary to create built-in.o -obj- += __dummy__.o +obj-y += cache.o endif diff --git a/arch/riscv/fu540/cache.c b/arch/riscv/fu540/cache.c new file mode 100644 index 0000000000..3eb71a06d4 --- /dev/null +++ b/arch/riscv/fu540/cache.c @@ -0,0 +1,58 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright (C) 2020 SiFive, Inc + * + * Authors: + * Pragnesh Patel pragnesh.patel@sifive.com + */ + +#include <common.h> +#include <asm/io.h> +#include <linux/bitops.h> + +#ifdef CONFIG_TARGET_SIFIVE_FU540 +/* Register offsets */ +#define CACHE_CONFIG 0x000 +#define CACHE_ENABLE 0x008 + +#define MASK_NUM_WAYS GENMASK(15, 8) +#define NUM_WAYS_SHIFT 8 +#endif + +DECLARE_GLOBAL_DATA_PTR; + +int cache_enable_ways(void) +{ + const void *blob = gd->fdt_blob; + int node = (-FDT_ERR_NOTFOUND); + fdt_addr_t base; + u32 config; + u32 ways; + + volatile u32 *enable; + +#ifdef CONFIG_TARGET_SIFIVE_FU540 + node = fdt_node_offset_by_compatible(blob, -1, + "sifive,fu540-c000-ccache"); + + if (node < 0) + return node; + + base = fdtdec_get_addr(blob, node, "reg"); + if (base == FDT_ADDR_T_NONE) + return FDT_ADDR_T_NONE; + + config = readl((volatile u32 *)base + CACHE_CONFIG); + ways = (config & MASK_NUM_WAYS) >> NUM_WAYS_SHIFT; + + enable = (volatile u32 *)(base + CACHE_ENABLE); + + /* memory barrier */ + mb(); + (*enable) = ways - 1; + /* memory barrier */ + mb(); +#endif /* CONFIG_TARGET_SIFIVE_FU540 */ + + return 0; +} diff --git a/arch/riscv/include/asm/arch-generic/cache.h b/arch/riscv/include/asm/arch-generic/cache.h new file mode 100644 index 0000000000..135a17c679 --- /dev/null +++ b/arch/riscv/include/asm/arch-generic/cache.h @@ -0,0 +1,14 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ +/* + * Copyright (C) 2020 SiFive, Inc. + * + * Authors: + * Pragnesh Patel pragnesh.patel@sifve.com + */ + +#ifndef _CACHE_SIFIVE_H +#define _CACHE_SIFIVE_H + +int cache_enable_ways(void); + +#endif /* _CACHE_SIFIVE_H */ diff --git a/board/sifive/fu540/fu540.c b/board/sifive/fu540/fu540.c index d05529a86b..131fee8898 100644 --- a/board/sifive/fu540/fu540.c +++ b/board/sifive/fu540/fu540.c @@ -12,6 +12,7 @@ #include <linux/io.h> #include <misc.h> #include <spl.h> +#include <asm/arch/cache.h>
/* * This define is a value used for error/unknown serial. @@ -111,8 +112,13 @@ int misc_init_r(void)
int board_init(void) { - /* For now nothing to do here. */ - + int ret; + /* enable all cache ways */ + ret = cache_enable_ways(); + if (ret) { + debug("%s: could not enable cache ways\n", __func__); + return ret; + } return 0; }

Hi Pragnesh,
On Mon, Mar 30, 2020 at 1:07 AM Pragnesh Patel pragnesh.patel@sifive.com wrote:
Enable all cache ways from u-boot proper.
Signed-off-by: Pragnesh Patel pragnesh.patel@sifive.com
arch/riscv/fu540/Makefile | 3 +- arch/riscv/fu540/cache.c | 58 +++++++++++++++++++++ arch/riscv/include/asm/arch-generic/cache.h | 14 +++++ board/sifive/fu540/fu540.c | 10 +++- 4 files changed, 81 insertions(+), 4 deletions(-) create mode 100644 arch/riscv/fu540/cache.c create mode 100644 arch/riscv/include/asm/arch-generic/cache.h
diff --git a/arch/riscv/fu540/Makefile b/arch/riscv/fu540/Makefile index e3b40ae7d4..3f385e8529 100644 --- a/arch/riscv/fu540/Makefile +++ b/arch/riscv/fu540/Makefile @@ -6,6 +6,5 @@ ifeq ($(CONFIG_SPL_BUILD),y) obj-$(CONFIG_TARGET_SIFIVE_FU540) += spl.o else -# necessary to create built-in.o -obj- += __dummy__.o +obj-y += cache.o endif diff --git a/arch/riscv/fu540/cache.c b/arch/riscv/fu540/cache.c
This should be put to arch/riscv/cpu/fu540/cache.c
new file mode 100644 index 0000000000..3eb71a06d4 --- /dev/null +++ b/arch/riscv/fu540/cache.c @@ -0,0 +1,58 @@ +// SPDX-License-Identifier: GPL-2.0+ +/*
- Copyright (C) 2020 SiFive, Inc
- Authors:
- Pragnesh Patel pragnesh.patel@sifive.com
- */
+#include <common.h> +#include <asm/io.h> +#include <linux/bitops.h>
+#ifdef CONFIG_TARGET_SIFIVE_FU540 +/* Register offsets */ +#define CACHE_CONFIG 0x000 +#define CACHE_ENABLE 0x008
+#define MASK_NUM_WAYS GENMASK(15, 8) +#define NUM_WAYS_SHIFT 8 +#endif
+DECLARE_GLOBAL_DATA_PTR;
+int cache_enable_ways(void) +{
const void *blob = gd->fdt_blob;
int node = (-FDT_ERR_NOTFOUND);
fdt_addr_t base;
u32 config;
u32 ways;
volatile u32 *enable;
+#ifdef CONFIG_TARGET_SIFIVE_FU540
There is no need to test CONFIG_TARGET_SIFIVE_FU540 if this driver is put to arch/riscv/cpu/fu540/cache.c
node = fdt_node_offset_by_compatible(blob, -1,
"sifive,fu540-c000-ccache");
if (node < 0)
return node;
base = fdtdec_get_addr(blob, node, "reg");
if (base == FDT_ADDR_T_NONE)
return FDT_ADDR_T_NONE;
config = readl((volatile u32 *)base + CACHE_CONFIG);
ways = (config & MASK_NUM_WAYS) >> NUM_WAYS_SHIFT;
enable = (volatile u32 *)(base + CACHE_ENABLE);
/* memory barrier */
mb();
(*enable) = ways - 1;
/* memory barrier */
mb();
+#endif /* CONFIG_TARGET_SIFIVE_FU540 */
return 0;
+} diff --git a/arch/riscv/include/asm/arch-generic/cache.h b/arch/riscv/include/asm/arch-generic/cache.h new file mode 100644 index 0000000000..135a17c679 --- /dev/null +++ b/arch/riscv/include/asm/arch-generic/cache.h @@ -0,0 +1,14 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ +/*
- Copyright (C) 2020 SiFive, Inc.
- Authors:
- Pragnesh Patel pragnesh.patel@sifve.com
- */
+#ifndef _CACHE_SIFIVE_H +#define _CACHE_SIFIVE_H
+int cache_enable_ways(void);
+#endif /* _CACHE_SIFIVE_H */ diff --git a/board/sifive/fu540/fu540.c b/board/sifive/fu540/fu540.c index d05529a86b..131fee8898 100644 --- a/board/sifive/fu540/fu540.c +++ b/board/sifive/fu540/fu540.c @@ -12,6 +12,7 @@ #include <linux/io.h> #include <misc.h> #include <spl.h> +#include <asm/arch/cache.h>
/*
- This define is a value used for error/unknown serial.
@@ -111,8 +112,13 @@ int misc_init_r(void)
int board_init(void) {
/* For now nothing to do here. */
int ret;
/* enable all cache ways */
ret = cache_enable_ways();
if (ret) {
debug("%s: could not enable cache ways\n", __func__);
return ret;
} return 0;
}
Regards, Bin

Hi Bin,
-----Original Message----- From: Bin Meng bmeng.cn@gmail.com Sent: 20 April 2020 15:05 To: Pragnesh Patel pragnesh.patel@sifive.com Cc: U-Boot Mailing List u-boot@lists.denx.de; Atish Patra atish.patra@wdc.com; Palmer Dabbelt palmerdabbelt@google.com; Paul Walmsley paul.walmsley@sifive.com; Jagan Teki jagan@amarulasolutions.com; Troy Benjegerdes troy.benjegerdes@sifive.com; Anup Patel anup.patel@wdc.com; Sagar Kadam sagar.kadam@sifive.com; Rick Chen rick@andestech.com; Palmer Dabbelt palmer@dabbelt.com Subject: Re: [PATCH v6 15/17] riscv: sifive: fu540: enable all cache ways from u-boot proper
[External Email] Do not click links or attachments unless you recognize the sender and know the content is safe
Hi Pragnesh,
On Mon, Mar 30, 2020 at 1:07 AM Pragnesh Patel pragnesh.patel@sifive.com wrote:
Enable all cache ways from u-boot proper.
Signed-off-by: Pragnesh Patel pragnesh.patel@sifive.com
arch/riscv/fu540/Makefile | 3 +- arch/riscv/fu540/cache.c | 58 +++++++++++++++++++++ arch/riscv/include/asm/arch-generic/cache.h | 14 +++++ board/sifive/fu540/fu540.c | 10 +++- 4 files changed, 81 insertions(+), 4 deletions(-) create mode 100644 arch/riscv/fu540/cache.c create mode 100644 arch/riscv/include/asm/arch-generic/cache.h
diff --git a/arch/riscv/fu540/Makefile b/arch/riscv/fu540/Makefile index e3b40ae7d4..3f385e8529 100644 --- a/arch/riscv/fu540/Makefile +++ b/arch/riscv/fu540/Makefile @@ -6,6 +6,5 @@ ifeq ($(CONFIG_SPL_BUILD),y) obj-$(CONFIG_TARGET_SIFIVE_FU540) += spl.o else -# necessary to create built-in.o -obj- += __dummy__.o +obj-y += cache.o endif diff --git a/arch/riscv/fu540/cache.c b/arch/riscv/fu540/cache.c
This should be put to arch/riscv/cpu/fu540/cache.c
Will update in v7.
new file mode 100644 index 0000000000..3eb71a06d4 --- /dev/null +++ b/arch/riscv/fu540/cache.c @@ -0,0 +1,58 @@ +// SPDX-License-Identifier: GPL-2.0+ +/*
- Copyright (C) 2020 SiFive, Inc
- Authors:
- Pragnesh Patel pragnesh.patel@sifive.com
- */
+#include <common.h> +#include <asm/io.h> +#include <linux/bitops.h>
+#ifdef CONFIG_TARGET_SIFIVE_FU540 +/* Register offsets */ +#define CACHE_CONFIG 0x000 +#define CACHE_ENABLE 0x008
+#define MASK_NUM_WAYS GENMASK(15, 8) #define NUM_WAYS_SHIFT 8
#endif
+DECLARE_GLOBAL_DATA_PTR;
+int cache_enable_ways(void) +{
const void *blob = gd->fdt_blob;
int node = (-FDT_ERR_NOTFOUND);
fdt_addr_t base;
u32 config;
u32 ways;
volatile u32 *enable;
+#ifdef CONFIG_TARGET_SIFIVE_FU540
There is no need to test CONFIG_TARGET_SIFIVE_FU540 if this driver is put to arch/riscv/cpu/fu540/cache.c
Will update in v7.
node = fdt_node_offset_by_compatible(blob, -1,
- "sifive,fu540-c000-ccache");
if (node < 0)
return node;
base = fdtdec_get_addr(blob, node, "reg");
if (base == FDT_ADDR_T_NONE)
return FDT_ADDR_T_NONE;
config = readl((volatile u32 *)base + CACHE_CONFIG);
ways = (config & MASK_NUM_WAYS) >> NUM_WAYS_SHIFT;
enable = (volatile u32 *)(base + CACHE_ENABLE);
/* memory barrier */
mb();
(*enable) = ways - 1;
/* memory barrier */
mb();
+#endif /* CONFIG_TARGET_SIFIVE_FU540 */
return 0;
+} diff --git a/arch/riscv/include/asm/arch-generic/cache.h b/arch/riscv/include/asm/arch-generic/cache.h new file mode 100644 index 0000000000..135a17c679 --- /dev/null +++ b/arch/riscv/include/asm/arch-generic/cache.h @@ -0,0 +1,14 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ +/*
- Copyright (C) 2020 SiFive, Inc.
- Authors:
- Pragnesh Patel pragnesh.patel@sifve.com
- */
+#ifndef _CACHE_SIFIVE_H +#define _CACHE_SIFIVE_H
+int cache_enable_ways(void);
+#endif /* _CACHE_SIFIVE_H */ diff --git a/board/sifive/fu540/fu540.c b/board/sifive/fu540/fu540.c index d05529a86b..131fee8898 100644 --- a/board/sifive/fu540/fu540.c +++ b/board/sifive/fu540/fu540.c @@ -12,6 +12,7 @@ #include <linux/io.h> #include <misc.h> #include <spl.h> +#include <asm/arch/cache.h>
/*
- This define is a value used for error/unknown serial.
@@ -111,8 +112,13 @@ int misc_init_r(void)
int board_init(void) {
/* For now nothing to do here. */
int ret;
/* enable all cache ways */
ret = cache_enable_ways();
if (ret) {
debug("%s: could not enable cache ways\n", __func__);
return ret;
} return 0;
}
Regards, Bin

Fix Palmer's email address
Signed-off-by: Pragnesh Patel pragnesh.patel@sifive.com Reviewed-by: Bin Meng bmeng.cn@gmail.com --- board/sifive/fu540/MAINTAINERS | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/board/sifive/fu540/MAINTAINERS b/board/sifive/fu540/MAINTAINERS index 702d803ad8..5381fc0639 100644 --- a/board/sifive/fu540/MAINTAINERS +++ b/board/sifive/fu540/MAINTAINERS @@ -1,6 +1,6 @@ SiFive FU540 BOARD M: Paul Walmsley paul.walmsley@sifive.com -M: Palmer Dabbelt palmer@sifive.com +M: Palmer Dabbelt palmer@dabbelt.com M: Anup Patel anup.patel@wdc.com M: Atish Patra atish.patra@wdc.com S: Maintained

On Sun, Mar 29, 2020 at 10:37 PM Pragnesh Patel pragnesh.patel@sifive.com wrote:
Fix Palmer's email address
Signed-off-by: Pragnesh Patel pragnesh.patel@sifive.com Reviewed-by: Bin Meng bmeng.cn@gmail.com
Pull out from the series and send it separately.
Jagan.

Hi Jagan,
-----Original Message----- From: Jagan Teki jagan@amarulasolutions.com Sent: 07 April 2020 01:13 To: Pragnesh Patel pragnesh.patel@sifive.com Cc: U-Boot-Denx u-boot@lists.denx.de; Atish Patra atish.patra@wdc.com; palmerdabbelt@google.com; Bin Meng bmeng.cn@gmail.com; Paul Walmsley paul.walmsley@sifive.com; Troy Benjegerdes troy.benjegerdes@sifive.com; Anup Patel anup.patel@wdc.com; Sagar Kadam sagar.kadam@sifive.com; Rick Chen rick@andestech.com; Palmer Dabbelt palmer@dabbelt.com Subject: Re: [PATCH v6 16/17] sifive: fix palmer's email address
[External Email] Do not click links or attachments unless you recognize the sender and know the content is safe
On Sun, Mar 29, 2020 at 10:37 PM Pragnesh Patel pragnesh.patel@sifive.com wrote:
Fix Palmer's email address
Signed-off-by: Pragnesh Patel pragnesh.patel@sifive.com Reviewed-by: Bin Meng bmeng.cn@gmail.com
Pull out from the series and send it separately.
Will do.
Jagan.

Add descriptions about U-Boot SPL feature and how to build and run.
Signed-off-by: Pragnesh Patel pragnesh.patel@sifive.com --- doc/board/sifive/fu540.rst | 409 ++++++++++++++++++++++++++++++++++--- 1 file changed, 385 insertions(+), 24 deletions(-)
diff --git a/doc/board/sifive/fu540.rst b/doc/board/sifive/fu540.rst index 3937222c6c..cf76b88ebc 100644 --- a/doc/board/sifive/fu540.rst +++ b/doc/board/sifive/fu540.rst @@ -42,8 +42,60 @@ Building export ARCH=riscv export CROSS_COMPILE=<riscv64 toolchain prefix>
-3. make sifive_fu540_defconfig -4. make +User can use FSBL or u-boot-spl as the 1st stage bootloader. + +1) Use FSBL as the 1st stage bootloader + +.. code-block:: console + + git clone https://github.com/sifive/freedom-u540-c000-bootloader.git + cd freedom-u540-c000-bootloader + make + + cd <u-boot-dir> + make sifive_fu540_defconfig + make + + git clone https://github.com/riscv/opensbi.git + cd opensbi + make PLATFORM=sifive/fu540 FW_PAYLOAD_PATH=<path to u-boot-dtb.bin> + +This will generate a fw_payload.bin (build/platform/sifive/fu540/firmware/fw_payload.bin) + +u-boot-dtb.bin is used as a payload of the OpenSBI FW_PAYLOAD firmware. + +More detailed description of steps required to build FW_PAYLOAD firmware +is beyond the scope of this document. Please refer OpenSBI documenation. +(Note: OpenSBI git repo is at https://github.com/riscv/opensbi.git) + +2) Use u-boot-spl as the 1st stage bootloader + +Before building U-Boot SPL, OpenSBI must be built first. OpenSBI can be +cloned and built for FU540 as below: + +.. code-block:: console + + git clone https://github.com/riscv/opensbi.git + cd opensbi + make PLATFORM=sifive/fu540 + +Copy OpenSBI FW_DYNAMIC image (build/platform/sifive/fu540/firmware/fw_dynamic.bin) +into U-Boot root directory + +.. code-block:: console + + cp build/platform/sifive/fu540/firmware/fw_dynamic.bin <u-boot-dir> + +Now build the u-boot-spl and U-Boot proper + +.. code-block:: console + + cd <u-boot-dir> + make sifive_fu540_defconfig + make + +This will generate spl/u-boot-spl.bin and FIT image (u-boot.itb) +
Flashing -------- @@ -53,28 +105,55 @@ The current U-Boot port is supported in S-mode only and loaded from DRAM. A prior stage M-mode firmware/bootloader (e.g OpenSBI) is required to boot the u-boot.bin in S-mode and provide M-mode runtime services.
-Currently, the u-boot.bin is used as a payload of the OpenSBI FW_PAYLOAD -firmware. We need to compile OpenSBI with below command: +1) Use FSBL as the 1st stage bootloader + +ZSBL loads the FSBL (fsbl.bin) from a partition with GUID type +5B193300-FC78-40CD-8002-E86C45580B47 + +FSBL loads the fw_payload.bin from a partition with GUID type +2E54B353-1271-4842-806F-E436D6AF6985 + +Once the prior stage firmware/bootloader binary is generated, it should be +copied to the first partition of the sdcard.
.. code-block:: none
-make PLATFORM=sifive/fu540 FW_PAYLOAD_PATH=<path to u-boot-dtb.bin> + sudo dd if=fsbl.bin of=/dev/disk2s4 bs=1024 + sudo dd if=fw_payload.bin of=/dev/disk2s1 bs=1024
-More detailed description of steps required to build FW_PAYLOAD firmware -is beyond the scope of this document. Please refer OpenSBI documenation. -(Note: OpenSBI git repo is at https://github.com/riscv/opensbi.git) +Assuming that /dev/disk2s4 partition is of GUID type +5B193300-FC78-40CD-8002-E86C45580B47 and /dev/disk2s1 partition +is of GUID type 2E54B353-1271-4842-806F-E436D6AF6985 + +2) Use u-boot-spl as the 1st stage bootloader + +ZSBL loads the U-Boot SPL (u-boot-spl.bin) from a partition with GUID type +5B193300-FC78-40CD-8002-E86C45580B47 + +U-boot SPL expects a U-Boot FIT image (u-boot.itb) from 1st partition (/dev/sdc1) +of SD card irrespective of GUID + +FIT image (u-boot.itb) is a combination of fw_dynamic.bin, u-boot-nodtb.bin and +device tree blob (hifive-unleashed-a00.dtb)
Once the prior stage firmware/bootloader binary is generated, it should be copied to the first partition of the sdcard.
.. code-block:: none
- sudo dd if=<prior_stage_firmware_binary> of=/dev/disk2s1 bs=1024 + sudo dd if=spl/u-boot-spl.bin of=/dev/disk2s4 bs=1024 + sudo dd if=u-boot.itb of=/dev/disk2s1 bs=1024 + +Assuming that /dev/disk2s4 partition is of GUID type +5B193300-FC78-40CD-8002-E86C45580B47 and /dev/disk2s1 is of +any GUID type raw partition.
Booting ------- Once you plugin the sdcard and power up, you should see the U-Boot prompt.
+1) Use FSBL as the 1st stage bootloader + Sample boot log from HiFive Unleashed board -------------------------------------------
@@ -145,19 +224,6 @@ load uImage. Filename '/sifive/fu540/Image'. Load address: 0x84000000 Loading: ################################################################# - ################################################################# - ################################################################# - ################################################################# - ################################################################# - ################################################################# - ################################################################# - ################################################################# - ################################################################# - ################################################################# - ################################################################# - ################################################################# - ################################################################# - ################################################################# ################################################################# ################################################################# ################################################################# @@ -184,8 +250,6 @@ load uImage. Filename '/sifive/fu540/uRamdisk'. Load address: 0x88300000 Loading: ################################################################# - ################################################################# - ################################################################# ################################################################# ################################################################# ################################################################# @@ -363,3 +427,300 @@ load uImage.
Please press Enter to activate this console. / # + + +2) Use u-boot-spl as the 1st stage bootloader + +The U-Boot SPL will boot in M mode and load the FIT image which include +OpenSBI and U-Boot proper images. After loading progress, it will jump +to OpenSBI first and then U-Boot proper which will run in S mode. + +Sample boot log from HiFive Unleashed board +------------------------------------------- + +.. code-block:: none + + U-Boot SPL 2020.04-rc1-00212-g375b0a2dad-dirty (Feb 13 2020 - 17:45:44 +0530) + Trying to boot from MMC1 + + + U-Boot 2020.04-rc1-00212-g375b0a2dad-dirty (Feb 13 2020 - 17:45:44 +0530) + + CPU: rv64imafdc + Model: SiFive HiFive Unleashed A00 + DRAM: 8 GiB + MMC: spi@10050000:mmc@0: 0 + In: serial@10010000 + Out: serial@10010000 + Err: serial@10010000 + Board serial number should not be 0 !! + Net: + Warning: ethernet@10090000 (eth0) using random MAC address - 92:79:17:2d:7b:b7 + eth0: ethernet@10090000 + Hit any key to stop autoboot: 0 + => version + U-Boot 2020.04-rc1-00212-g375b0a2dad-dirty (Feb 13 2020 - 17:45:44 +0530) + + riscv64-unknown-linux-gnu-gcc (crosstool-NG 1.24.0.37-3f461da) 9.2.0 + GNU ld (crosstool-NG 1.24.0.37-3f461da) 2.32 + => mmc info + Device: spi@10050000:mmc@0 + Manufacturer ID: 3 + OEM: 5344 + Name: SC16G + Bus Speed: 20000000 + Mode: SD Legacy + Rd Block Len: 512 + SD version 2.0 + High Capacity: Yes + Capacity: 14.8 GiB + Bus Width: 1-bit + Erase Group Size: 512 Bytes + => mmc part + + Partition Map for MMC device 0 -- Partition Type: EFI + + Part Start LBA End LBA Name + Attributes + Type GUID + Partition GUID + 1 0x00000800 0x000107ff "SiFive bare-metal (or stage 2 loader" + attrs: 0x0000000000000000 + type: 2e54b353-1271-4842-806f-e436d6af6985 + guid: 3c9eabe1-b16b-4a2e-9b4e-f065c740bb86 + 2 0x00040800 0x00ecdfde "Linux filesystem" + attrs: 0x0000000000000000 + type: 0fc63daf-8483-4772-8e79-3d69d8477de4 + guid: ad9309ff-d204-42f0-9f99-f3275a83f565 + +Now you can configure your networking, tftp server and use tftp boot method to +load uImage. + +.. code-block:: none + + => setenv serverip 172.16.35.74 + => setenv ipaddr 172.16.35.40 + => tftpboot 0x83000000 fit.itb + ethernet@10090000: PHY present at 0 + ethernet@10090000: Starting autonegotiation... + ethernet@10090000: Autonegotiation complete + ethernet@10090000: link up, 100Mbps full-duplex (lpa: 0x41e1) + Using ethernet@10090000 device + TFTP from server 172.16.35.74; our IP address is 172.16.35.40 + Filename 'fit.itb'. + Load address: 0x83000000 + Loading: ################################################################# + ################################################################# + ################################################################# + ################################################################# + ################################################################# + ################################################################# + ################################################################# + ################################################################# + ################################################################# + ################################################################# + ################################################################# + ################################################################# + ################################################################# + ################################################################# + ################################################################# + ################################################################# + ################################################################# + ################################################################# + ################################################################ + ################################### + 878.9 KiB/s + done + Bytes transferred = 13823823 (d2ef4f hex) + => bootm 0x83000000 + ## Loading kernel from FIT Image at 83000000 ... + Using 'config-1' configuration + Trying 'kernel@1' kernel subimage + Description: Linux kernel + Type: Kernel Image + Compression: uncompressed + Data Start: 0x830000d8 + Data Size: 9247260 Bytes = 8.8 MiB + Architecture: RISC-V + OS: Linux + Load Address: 0x80200000 + Entry Point: 0x80200000 + Verifying Hash Integrity ... OK + ## Loading ramdisk from FIT Image at 83000000 ... + Using 'config-1' configuration + Trying 'ramdisk@1' ramdisk subimage + Description: ramdisk + Type: RAMDisk Image + Compression: gzip compressed + Data Start: 0x838d3378 + Data Size: 4568674 Bytes = 4.4 MiB + Architecture: RISC-V + OS: Linux + Load Address: 0x82000000 + Entry Point: unavailable + Verifying Hash Integrity ... OK + Loading ramdisk from 0x838d3378 to 0x82000000 + WARNING: 'compression' nodes for ramdisks are deprecated, please fix your .its file! + ## Loading fdt from FIT Image at 83000000 ... + Using 'config-1' configuration + Trying 'fdt@1' fdt subimage + Description: unavailable + Type: Flat Device Tree + Compression: uncompressed + Data Start: 0x838d1b80 + Data Size: 6023 Bytes = 5.9 KiB + Architecture: RISC-V + Verifying Hash Integrity ... OK + Booting using the fdt blob at 0x838d1b80 + Loading Kernel Image + Using Device Tree in place at 00000000838d1b80, end 00000000838d6306 + + Starting kernel ... + + [ 0.000000] OF: fdt: Ignoring memory range 0x80000000 - 0x80200000 + [ 0.000000] Linux version 5.3.0-13236-g97f9a3c4eee5 (pragneshp@sachinj2-OptiPlex-7010) (gcc version 8.2.0 (Buildroot 2018.11-rc2-00003-ga0787e9 + [ 0.000000] earlycon: sifive0 at MMIO 0x0000000010010000 (options '') + [ 0.000000] printk: bootconsole [sifive0] enabled + [ 0.000000] Initial ramdisk at: 0x(____ptrval____) (4568674 bytes) + [ 0.000000] Zone ranges: + [ 0.000000] DMA32 [mem 0x0000000080200000-0x00000000ffffffff] + [ 0.000000] Normal [mem 0x0000000100000000-0x000000027fffffff] + [ 0.000000] Movable zone start for each node + [ 0.000000] Early memory node ranges + [ 0.000000] node 0: [mem 0x0000000080200000-0x000000027fffffff] + [ 0.000000] Initmem setup node 0 [mem 0x0000000080200000-0x000000027fffffff] + [ 0.000000] software IO TLB: mapped [mem 0xfbfff000-0xfffff000] (64MB) + [ 0.000000] CPU with hartid=0 is not available + [ 0.000000] CPU with hartid=0 is not available + [ 0.000000] elf_hwcap is 0x112d + [ 0.000000] percpu: Embedded 17 pages/cpu s30680 r8192 d30760 u69632 + [ 0.000000] Built 1 zonelists, mobility grouping on. Total pages: 2067975 + [ 0.000000] Kernel command line: earlycon=sifive,0x10010000 console=ttySIF0,115200 + [ 0.000000] Dentry cache hash table entries: 1048576 (order: 11, 8388608 bytes, linear) + [ 0.000000] Inode-cache hash table entries: 524288 (order: 10, 4194304 bytes, linear) + [ 0.000000] Sorting __ex_table... + [ 0.000000] mem auto-init: stack:off, heap alloc:off, heap free:off + [ 0.000000] Memory: 8179828K/8386560K available (6081K kernel code, 388K rwdata, 2025K rodata, 209K init, 307K bss, 206732K reserved, 0K cma-r) + [ 0.000000] SLUB: HWalign=64, Order=0-3, MinObjects=0, CPUs=4, Nodes=1 + [ 0.000000] rcu: Hierarchical RCU implementation. + [ 0.000000] rcu: RCU restricting CPUs from NR_CPUS=8 to nr_cpu_ids=4. + [ 0.000000] rcu: RCU calculated value of scheduler-enlistment delay is 25 jiffies. + [ 0.000000] rcu: Adjusting geometry for rcu_fanout_leaf=16, nr_cpu_ids=4 + [ 0.000000] NR_IRQS: 0, nr_irqs: 0, preallocated irqs: 0 + [ 0.000000] plic: mapped 53 interrupts with 4 handlers for 9 contexts. + [ 0.000000] riscv_timer_init_dt: Registering clocksource cpuid [0] hartid [2] + [ 0.000000] clocksource: riscv_clocksource: mask: 0xffffffffffffffff max_cycles: 0x1d854df40, max_idle_ns: 3526361616960 ns + [ 0.000006] sched_clock: 64 bits at 1000kHz, resolution 1000ns, wraps every 2199023255500ns + [ 0.008467] Console: colour dummy device 80x25 + [ 0.012819] Calibrating delay loop (skipped), value calculated using timer frequency.. 2.00 BogoMIPS (lpj=4000) + [ 0.022844] pid_max: default: 32768 minimum: 301 + [ 0.027915] Mount-cache hash table entries: 16384 (order: 5, 131072 bytes, linear) + [ 0.035332] Mountpoint-cache hash table entries: 16384 (order: 5, 131072 bytes, linear) + [ 0.044791] rcu: Hierarchical SRCU implementation. + [ 0.049255] smp: Bringing up secondary CPUs ... + [ 0.055034] smp: Brought up 1 node, 4 CPUs + [ 0.059664] devtmpfs: initialized + [ 0.063818] random: get_random_u32 called from bucket_table_alloc.isra.29+0x4e/0x160 with crng_init=0 + [ 0.072588] clocksource: jiffies: mask: 0xffffffff max_cycles: 0xffffffff, max_idle_ns: 7645041785100000 ns + [ 0.082000] futex hash table entries: 1024 (order: 4, 65536 bytes, linear) + [ 0.089513] NET: Registered protocol family 16 + [ 0.105911] vgaarb: loaded + [ 0.108166] SCSI subsystem initialized + [ 0.111946] usbcore: registered new interface driver usbfs + [ 0.117105] usbcore: registered new interface driver hub + [ 0.122486] usbcore: registered new device driver usb + [ 0.128073] clocksource: Switched to clocksource riscv_clocksource + [ 0.140277] NET: Registered protocol family 2 + [ 0.144449] tcp_listen_portaddr_hash hash table entries: 4096 (order: 4, 65536 bytes, linear) + [ 0.152620] TCP established hash table entries: 65536 (order: 7, 524288 bytes, linear) + [ 0.162238] TCP bind hash table entries: 65536 (order: 8, 1048576 bytes, linear) + [ 0.172159] TCP: Hash tables configured (established 65536 bind 65536) + [ 0.178343] UDP hash table entries: 4096 (order: 5, 131072 bytes, linear) + [ 0.185140] UDP-Lite hash table entries: 4096 (order: 5, 131072 bytes, linear) + [ 0.192553] NET: Registered protocol family 1 + [ 0.196752] RPC: Registered named UNIX socket transport module. + [ 0.202145] RPC: Registered udp transport module. + [ 0.206828] RPC: Registered tcp transport module. + [ 0.211512] RPC: Registered tcp NFSv4.1 backchannel transport module. + [ 0.217939] PCI: CLS 0 bytes, default 64 + [ 0.222139] Unpacking initramfs... + [ 0.578803] Freeing initrd memory: 4460K + [ 0.582972] workingset: timestamp_bits=62 max_order=21 bucket_order=0 + [ 0.596643] NFS: Registering the id_resolver key type + [ 0.600950] Key type id_resolver registered + [ 0.605134] Key type id_legacy registered + [ 0.609090] nfs4filelayout_init: NFSv4 File Layout Driver Registering... + [ 0.615928] 9p: Installing v9fs 9p2000 file system support + [ 0.621581] NET: Registered protocol family 38 + [ 0.625700] Block layer SCSI generic (bsg) driver version 0.4 loaded (major 253) + [ 0.633051] io scheduler mq-deadline registered + [ 0.637559] io scheduler kyber registered + [ 0.685592] Serial: 8250/16550 driver, 4 ports, IRQ sharing disabled + [ 0.692184] 10010000.serial: ttySIF0 at MMIO 0x10010000 (irq = 4, base_baud = 0) is a SiFive UART v0 + [ 0.700566] printk: console [ttySIF0] enabled + [ 0.700566] printk: console [ttySIF0] enabled + [ 0.709228] printk: bootconsole [sifive0] disabled + [ 0.709228] printk: bootconsole [sifive0] disabled + [ 0.719030] 10011000.serial: ttySIF1 at MMIO 0x10011000 (irq = 1, base_baud = 0) is a SiFive UART v0 + [ 0.728364] [drm] radeon kernel modesetting enabled. + [ 0.745292] loop: module loaded + [ 0.748208] sifive_spi 10040000.spi: mapped; irq=3, cs=1 + [ 0.753490] sifive_spi 10050000.spi: mapped; irq=5, cs=1 + [ 0.758811] libphy: Fixed MDIO Bus: probed + [ 0.762886] macb 10090000.ethernet: Registered clk switch 'sifive-gemgxl-mgmt' + [ 0.769643] macb: GEM doesn't support hardware ptp. + [ 0.774532] libphy: MACB_mii_bus: probed + [ 0.940349] Microsemi VSC8541 SyncE 10090000.ethernet-ffffffff:00: attached PHY driver [Microsemi VSC8541 SyncE] (mii_bus:phy_addr=10090000.et) + [ 0.954893] macb 10090000.ethernet eth0: Cadence GEM rev 0x10070109 at 0x10090000 irq 6 (92:79:17:2d:7b:b7) + [ 0.964698] e1000e: Intel(R) PRO/1000 Network Driver - 3.2.6-k + [ 0.970417] e1000e: Copyright(c) 1999 - 2015 Intel Corporation. + [ 0.976410] ehci_hcd: USB 2.0 'Enhanced' Host Controller (EHCI) Driver + [ 0.982832] ehci-pci: EHCI PCI platform driver + [ 0.987288] ehci-platform: EHCI generic platform driver + [ 0.992547] ohci_hcd: USB 1.1 'Open' Host Controller (OHCI) Driver + [ 0.998646] ohci-pci: OHCI PCI platform driver + [ 1.003092] ohci-platform: OHCI generic platform driver + [ 1.008557] usbcore: registered new interface driver uas + [ 1.013621] usbcore: registered new interface driver usb-storage + [ 1.019695] mousedev: PS/2 mouse device common for all mice + [ 1.050569] mmc_spi spi1.0: SD/MMC host mmc0, no DMA, no WP, no poweroff, cd polling + [ 1.057714] usbcore: registered new interface driver usbhid + [ 1.063098] usbhid: USB HID core driver + [ 1.067805] NET: Registered protocol family 10 + [ 1.072421] Segment Routing with IPv6 + [ 1.075367] sit: IPv6, IPv4 and MPLS over IPv4 tunneling driver + [ 1.081745] NET: Registered protocol family 17 + [ 1.085867] 9pnet: Installing 9P2000 support + [ 1.089951] Key type dns_resolver registered + [ 1.096367] Freeing unused kernel memory: 208K + [ 1.100023] This architecture does not have kernel memory protection. + [ 1.106468] Run /init as init process + Starting syslogd: OK + Starting klogd: OK + Starting mdev... + /etc/init.d/S10mdev: line 9: can't create /proc/sys/kernel/hotplug: nonexistent directory + [ 1.167972] mmc0: host does not support reading read-only switch, assuming write-enable + [ 1.175224] mmc0: new SDHC card on SPI + [ 1.180428] mmcblk0: mmc0:0000 SC16G 14.8 GiB + [ 1.214935] mmcblk0: p1 p2 p4 + modprobe: can't change directory to '/lib/modules': No such file or directory + Initializing random number generator... [ 1.664435] random: dd: uninitialized urandom read (512 bytes read) + done. + Starting network: udhcpc: started, v1.29.3 + udhcpc: sending discover + [ 3.756700] macb 10090000.ethernet eth0: link up (100/Full) + [ 3.761515] IPv6: ADDRCONF(NETDEV_CHANGE): eth0: link becomes ready + udhcpc: sending discover + udhcpc: sending select for 172.16.35.4 + udhcpc: lease of 172.16.35.4 obtained, lease time 3600 + deleting routers + adding dns 172.16.34.75 + adding dns 172.16.24.25 + OK + Starting dropbear sshd: [ 4.893179] random: dropbear: uninitialized urandom read (32 bytes read) + OK + + Welcome to Buildroot + buildroot login: root + Password: + #

Hi Pragnesh,
On Mon, Mar 30, 2020 at 1:07 AM Pragnesh Patel pragnesh.patel@sifive.com wrote:
Add descriptions about U-Boot SPL feature and how to build and run.
Signed-off-by: Pragnesh Patel pragnesh.patel@sifive.com
doc/board/sifive/fu540.rst | 409 ++++++++++++++++++++++++++++++++++--- 1 file changed, 385 insertions(+), 24 deletions(-)
diff --git a/doc/board/sifive/fu540.rst b/doc/board/sifive/fu540.rst index 3937222c6c..cf76b88ebc 100644 --- a/doc/board/sifive/fu540.rst +++ b/doc/board/sifive/fu540.rst @@ -42,8 +42,60 @@ Building export ARCH=riscv export CROSS_COMPILE=<riscv64 toolchain prefix>
-3. make sifive_fu540_defconfig -4. make +User can use FSBL or u-boot-spl as the 1st stage bootloader.
+1) Use FSBL as the 1st stage bootloader
+.. code-block:: console
git clone https://github.com/sifive/freedom-u540-c000-bootloader.git
cd freedom-u540-c000-bootloader
make
cd <u-boot-dir>
make sifive_fu540_defconfig
make
git clone https://github.com/riscv/opensbi.git
cd opensbi
make PLATFORM=sifive/fu540 FW_PAYLOAD_PATH=<path to u-boot-dtb.bin>
+This will generate a fw_payload.bin (build/platform/sifive/fu540/firmware/fw_payload.bin)
+u-boot-dtb.bin is used as a payload of the OpenSBI FW_PAYLOAD firmware.
+More detailed description of steps required to build FW_PAYLOAD firmware +is beyond the scope of this document. Please refer OpenSBI documenation. +(Note: OpenSBI git repo is at https://github.com/riscv/opensbi.git)
+2) Use u-boot-spl as the 1st stage bootloader
+Before building U-Boot SPL, OpenSBI must be built first. OpenSBI can be +cloned and built for FU540 as below:
+.. code-block:: console
git clone https://github.com/riscv/opensbi.git
cd opensbi
make PLATFORM=sifive/fu540
+Copy OpenSBI FW_DYNAMIC image (build/platform/sifive/fu540/firmware/fw_dynamic.bin) +into U-Boot root directory
+.. code-block:: console
cp build/platform/sifive/fu540/firmware/fw_dynamic.bin <u-boot-dir>
+Now build the u-boot-spl and U-Boot proper
+.. code-block:: console
cd <u-boot-dir>
make sifive_fu540_defconfig
make
+This will generate spl/u-boot-spl.bin and FIT image (u-boot.itb)
Flashing
@@ -53,28 +105,55 @@ The current U-Boot port is supported in S-mode only and loaded from DRAM. A prior stage M-mode firmware/bootloader (e.g OpenSBI) is required to boot the u-boot.bin in S-mode and provide M-mode runtime services.
-Currently, the u-boot.bin is used as a payload of the OpenSBI FW_PAYLOAD -firmware. We need to compile OpenSBI with below command: +1) Use FSBL as the 1st stage bootloader
+ZSBL loads the FSBL (fsbl.bin) from a partition with GUID type +5B193300-FC78-40CD-8002-E86C45580B47
+FSBL loads the fw_payload.bin from a partition with GUID type +2E54B353-1271-4842-806F-E436D6AF6985
+Once the prior stage firmware/bootloader binary is generated, it should be +copied to the first partition of the sdcard.
.. code-block:: none
-make PLATFORM=sifive/fu540 FW_PAYLOAD_PATH=<path to u-boot-dtb.bin>
sudo dd if=fsbl.bin of=/dev/disk2s4 bs=1024
sudo dd if=fw_payload.bin of=/dev/disk2s1 bs=1024
-More detailed description of steps required to build FW_PAYLOAD firmware -is beyond the scope of this document. Please refer OpenSBI documenation. -(Note: OpenSBI git repo is at https://github.com/riscv/opensbi.git) +Assuming that /dev/disk2s4 partition is of GUID type +5B193300-FC78-40CD-8002-E86C45580B47 and /dev/disk2s1 partition +is of GUID type 2E54B353-1271-4842-806F-E436D6AF6985
+2) Use u-boot-spl as the 1st stage bootloader
+ZSBL loads the U-Boot SPL (u-boot-spl.bin) from a partition with GUID type +5B193300-FC78-40CD-8002-E86C45580B47
+U-boot SPL expects a U-Boot FIT image (u-boot.itb) from 1st partition (/dev/sdc1)
nits: U-Boot SPL
+of SD card irrespective of GUID
+FIT image (u-boot.itb) is a combination of fw_dynamic.bin, u-boot-nodtb.bin and +device tree blob (hifive-unleashed-a00.dtb)
Once the prior stage firmware/bootloader binary is generated, it should be copied to the first partition of the sdcard.
.. code-block:: none
- sudo dd if=<prior_stage_firmware_binary> of=/dev/disk2s1 bs=1024
- sudo dd if=spl/u-boot-spl.bin of=/dev/disk2s4 bs=1024
- sudo dd if=u-boot.itb of=/dev/disk2s1 bs=1024
+Assuming that /dev/disk2s4 partition is of GUID type +5B193300-FC78-40CD-8002-E86C45580B47 and /dev/disk2s1 is of +any GUID type raw partition.
Other than above,
Reviewed-by: Bin Meng bmeng.cn@gmail.com
Regards, Bin

Hi Bin,
-----Original Message----- From: Bin Meng bmeng.cn@gmail.com Sent: 20 April 2020 15:16 To: Pragnesh Patel pragnesh.patel@sifive.com Cc: U-Boot Mailing List u-boot@lists.denx.de; Atish Patra atish.patra@wdc.com; Palmer Dabbelt palmerdabbelt@google.com; Paul Walmsley paul.walmsley@sifive.com; Jagan Teki jagan@amarulasolutions.com; Troy Benjegerdes troy.benjegerdes@sifive.com; Anup Patel anup.patel@wdc.com; Sagar Kadam sagar.kadam@sifive.com; Rick Chen rick@andestech.com; Joe Hershberger joe.hershberger@ni.com Subject: Re: [PATCH v6 17/17] doc: update FU540 RISC-V documentation
[External Email] Do not click links or attachments unless you recognize the sender and know the content is safe
Hi Pragnesh,
On Mon, Mar 30, 2020 at 1:07 AM Pragnesh Patel pragnesh.patel@sifive.com wrote:
Add descriptions about U-Boot SPL feature and how to build and run.
Signed-off-by: Pragnesh Patel pragnesh.patel@sifive.com
doc/board/sifive/fu540.rst | 409 ++++++++++++++++++++++++++++++++++--- 1 file changed, 385 insertions(+), 24 deletions(-)
diff --git a/doc/board/sifive/fu540.rst b/doc/board/sifive/fu540.rst index 3937222c6c..cf76b88ebc 100644 --- a/doc/board/sifive/fu540.rst +++ b/doc/board/sifive/fu540.rst @@ -42,8 +42,60 @@ Building export ARCH=riscv export CROSS_COMPILE=<riscv64 toolchain prefix>
-3. make sifive_fu540_defconfig -4. make +User can use FSBL or u-boot-spl as the 1st stage bootloader.
+1) Use FSBL as the 1st stage bootloader
+.. code-block:: console
git clone https://github.com/sifive/freedom-u540-c000-bootloader.git
cd freedom-u540-c000-bootloader
make
cd <u-boot-dir>
make sifive_fu540_defconfig
make
git clone https://github.com/riscv/opensbi.git
cd opensbi
make PLATFORM=sifive/fu540 FW_PAYLOAD_PATH=<path to
- u-boot-dtb.bin>
+This will generate a fw_payload.bin +(build/platform/sifive/fu540/firmware/fw_payload.bin)
+u-boot-dtb.bin is used as a payload of the OpenSBI FW_PAYLOAD
firmware.
+More detailed description of steps required to build FW_PAYLOAD +firmware is beyond the scope of this document. Please refer OpenSBI
documenation.
+(Note: OpenSBI git repo is at https://github.com/riscv/opensbi.git)
+2) Use u-boot-spl as the 1st stage bootloader
+Before building U-Boot SPL, OpenSBI must be built first. OpenSBI can +be cloned and built for FU540 as below:
+.. code-block:: console
git clone https://github.com/riscv/opensbi.git
cd opensbi
make PLATFORM=sifive/fu540
+Copy OpenSBI FW_DYNAMIC image +(build/platform/sifive/fu540/firmware/fw_dynamic.bin) +into U-Boot root directory
+.. code-block:: console
cp build/platform/sifive/fu540/firmware/fw_dynamic.bin
<u-boot-dir>
+Now build the u-boot-spl and U-Boot proper
+.. code-block:: console
cd <u-boot-dir>
make sifive_fu540_defconfig
make
+This will generate spl/u-boot-spl.bin and FIT image (u-boot.itb)
Flashing
@@ -53,28 +105,55 @@ The current U-Boot port is supported in S-mode
only and loaded from DRAM.
A prior stage M-mode firmware/bootloader (e.g OpenSBI) is required to boot the u-boot.bin in S-mode and provide M-mode runtime services.
-Currently, the u-boot.bin is used as a payload of the OpenSBI FW_PAYLOAD -firmware. We need to compile OpenSBI with below
command:
+1) Use FSBL as the 1st stage bootloader
+ZSBL loads the FSBL (fsbl.bin) from a partition with GUID type +5B193300-FC78-40CD-8002-E86C45580B47
+FSBL loads the fw_payload.bin from a partition with GUID type +2E54B353-1271-4842-806F-E436D6AF6985
+Once the prior stage firmware/bootloader binary is generated, it +should be copied to the first partition of the sdcard.
.. code-block:: none
-make PLATFORM=sifive/fu540 FW_PAYLOAD_PATH=<path to u-boot-
dtb.bin>
sudo dd if=fsbl.bin of=/dev/disk2s4 bs=1024
sudo dd if=fw_payload.bin of=/dev/disk2s1 bs=1024
-More detailed description of steps required to build FW_PAYLOAD firmware -is beyond the scope of this document. Please refer OpenSBI
documenation.
-(Note: OpenSBI git repo is at https://github.com/riscv/opensbi.git) +Assuming that /dev/disk2s4 partition is of GUID type +5B193300-FC78-40CD-8002-E86C45580B47 and /dev/disk2s1 partition is of +GUID type 2E54B353-1271-4842-806F-E436D6AF6985
+2) Use u-boot-spl as the 1st stage bootloader
+ZSBL loads the U-Boot SPL (u-boot-spl.bin) from a partition with GUID +type +5B193300-FC78-40CD-8002-E86C45580B47
+U-boot SPL expects a U-Boot FIT image (u-boot.itb) from 1st partition +(/dev/sdc1)
nits: U-Boot SPL
Will update in v7.
+of SD card irrespective of GUID
+FIT image (u-boot.itb) is a combination of fw_dynamic.bin, +u-boot-nodtb.bin and device tree blob (hifive-unleashed-a00.dtb)
Once the prior stage firmware/bootloader binary is generated, it should be copied to the first partition of the sdcard.
.. code-block:: none
- sudo dd if=<prior_stage_firmware_binary> of=/dev/disk2s1 bs=1024
- sudo dd if=spl/u-boot-spl.bin of=/dev/disk2s4 bs=1024
- sudo dd if=u-boot.itb of=/dev/disk2s1 bs=1024
+Assuming that /dev/disk2s4 partition is of GUID type +5B193300-FC78-40CD-8002-E86C45580B47 and /dev/disk2s1 is of any GUID +type raw partition.
Other than above,
Reviewed-by: Bin Meng bmeng.cn@gmail.com
Regards, Bin

On Sun, Mar 29, 2020 at 10:36 PM Pragnesh Patel pragnesh.patel@sifive.com wrote:
This series add support for SPL to FU540.U-Boot SPL can boot from L2 LIM (0x0800_0000) and jump to OpenSBI(FW_DYNAMIC firmware) and U-Boot proper from MMC devices.
How to test this patch:
- Go to OpenSBI-dir : make PLATFORM=sifive/fu540 O=build_dir I=install_dir FW_DYNAMIC=y install
- cp install_dir/platform/sifive/fu540/firmware/fw_dynamic.bin <u-boot-dir>/
I think setting OPENSBI=<path/to/opensbi/install_dir/platform/sifive/fu540/firmware/fw_dynamic.bin> would help to attach the opensbi instead of copying into the source directory. Would you please check that.
Jagan.

Hi Jagan,
-----Original Message----- From: Jagan Teki jagan@amarulasolutions.com Sent: 02 April 2020 14:42 To: Pragnesh Patel pragnesh.patel@sifive.com Cc: U-Boot-Denx u-boot@lists.denx.de; Atish Patra atish.patra@wdc.com; palmerdabbelt@google.com; Bin Meng bmeng.cn@gmail.com; Paul Walmsley paul.walmsley@sifive.com; Troy Benjegerdes troy.benjegerdes@sifive.com; Anup Patel anup.patel@wdc.com; Sagar Kadam sagar.kadam@sifive.com; Rick Chen rick@andestech.com Subject: Re: [PATCH v6 00/17] RISC-V SiFive FU540 support SPL
[External Email] Do not click links or attachments unless you recognize the sender and know the content is safe
On Sun, Mar 29, 2020 at 10:36 PM Pragnesh Patel pragnesh.patel@sifive.com wrote:
This series add support for SPL to FU540.U-Boot SPL can boot from L2 LIM (0x0800_0000) and jump to OpenSBI(FW_DYNAMIC firmware) and U-Boot proper from MMC devices.
How to test this patch:
- Go to OpenSBI-dir : make PLATFORM=sifive/fu540 O=build_dir
I=install_dir FW_DYNAMIC=y install 2) cp install_dir/platform/sifive/fu540/firmware/fw_dynamic.bin <u-boot-dir>/
I think setting OPENSBI=<path/to/opensbi/install_dir/platform/sifive/fu540/firmware/fw_d ynamic.bin> would help to attach the opensbi instead of copying into the source directory. Would you please check that.
Yes that will also work, if I need to submit v7 then will update this.
Jagan.

On Thu, Apr 2, 2020 at 3:12 PM Pragnesh Patel pragnesh.patel@sifive.com wrote:
Hi Jagan,
-----Original Message----- From: Jagan Teki jagan@amarulasolutions.com Sent: 02 April 2020 14:42 To: Pragnesh Patel pragnesh.patel@sifive.com Cc: U-Boot-Denx u-boot@lists.denx.de; Atish Patra atish.patra@wdc.com; palmerdabbelt@google.com; Bin Meng bmeng.cn@gmail.com; Paul Walmsley paul.walmsley@sifive.com; Troy Benjegerdes troy.benjegerdes@sifive.com; Anup Patel anup.patel@wdc.com; Sagar Kadam sagar.kadam@sifive.com; Rick Chen rick@andestech.com Subject: Re: [PATCH v6 00/17] RISC-V SiFive FU540 support SPL
[External Email] Do not click links or attachments unless you recognize the sender and know the content is safe
On Sun, Mar 29, 2020 at 10:36 PM Pragnesh Patel pragnesh.patel@sifive.com wrote:
This series add support for SPL to FU540.U-Boot SPL can boot from L2 LIM (0x0800_0000) and jump to OpenSBI(FW_DYNAMIC firmware) and U-Boot proper from MMC devices.
How to test this patch:
- Go to OpenSBI-dir : make PLATFORM=sifive/fu540 O=build_dir
I=install_dir FW_DYNAMIC=y install 2) cp install_dir/platform/sifive/fu540/firmware/fw_dynamic.bin <u-boot-dir>/
I think setting OPENSBI=<path/to/opensbi/install_dir/platform/sifive/fu540/firmware/fw_d ynamic.bin> would help to attach the opensbi instead of copying into the source directory. Would you please check that.
Yes that will also work, if I need to submit v7 then will update this.
Thanks, please wait for sometime I'll send my comments for the rest of the patches.
Jagan.

Hi Pragnesh,
On Sun, Mar 29, 2020 at 10:36 PM Pragnesh Patel pragnesh.patel@sifive.com wrote:
This series add support for SPL to FU540.U-Boot SPL can boot from L2 LIM (0x0800_0000) and jump to OpenSBI(FW_DYNAMIC firmware) and U-Boot proper from MMC devices.
How to test this patch:
Go to OpenSBI-dir : make PLATFORM=sifive/fu540 O=build_dir I=install_dir FW_DYNAMIC=y install
cp install_dir/platform/sifive/fu540/firmware/fw_dynamic.bin <u-boot-dir>/
Change to u-boot-dir
make sifive_fu540_defconfig
make all
ZSBL loads the U-boot SPL(u-boot-spl.bin) from a partition with GUID type 5B193300-FC78-40CD-8002-E86C45580B47
sudo dd if=spl/u-boot-spl.bin of=/dev/sdc4 bs=1M
U-boot SPL expects a u-boot FIT image(u-boot.itb) from 1st partition(/dev/sdc1) of SD card irrespective of GUID
sudo dd if=u-boot.itb of=/dev/sdc1 bs=1M
Seems like SPL (sdc4) at 4th partition and U-Boot proper at first partition which seems an unconventional way to create partition layouts based on the booting stage hierarchy.
I did send the changes on top of our changes [1] which indeed follow the conventional partition layout. So feel free to incorporate your series while sending the next version.
So from next version, you can drop CONFIG_SYS_MMCSD_RAW_MODE_U_BOOT_USE_PARTITION and write images as,
$ sudo dd if=u-boot.itb of=/dev/sda seek=4096 $ sudo dd if=spl/u-boot-spl.bin of=/dev/sda seek=2048
[1] https://patchwork.ozlabs.org/project/uboot/list/?series=168967
Jagan.

Hi Jagan,
-----Original Message----- From: Jagan Teki jagan@amarulasolutions.com Sent: 07 April 2020 15:02 To: Pragnesh Patel pragnesh.patel@sifive.com Cc: U-Boot-Denx u-boot@lists.denx.de; Atish Patra atish.patra@wdc.com; palmerdabbelt@google.com; Bin Meng bmeng.cn@gmail.com; Paul Walmsley paul.walmsley@sifive.com; Troy Benjegerdes troy.benjegerdes@sifive.com; Anup Patel anup.patel@wdc.com; Sagar Kadam sagar.kadam@sifive.com; Rick Chen rick@andestech.com Subject: Re: [PATCH v6 00/17] RISC-V SiFive FU540 support SPL
[External Email] Do not click links or attachments unless you recognize the sender and know the content is safe
Hi Pragnesh,
On Sun, Mar 29, 2020 at 10:36 PM Pragnesh Patel pragnesh.patel@sifive.com wrote:
This series add support for SPL to FU540.U-Boot SPL can boot from L2 LIM (0x0800_0000) and jump to OpenSBI(FW_DYNAMIC firmware) and U-Boot proper from MMC devices.
How to test this patch:
- Go to OpenSBI-dir : make PLATFORM=sifive/fu540 O=build_dir
I=install_dir FW_DYNAMIC=y install 2) cp install_dir/platform/sifive/fu540/firmware/fw_dynamic.bin <u-boot-dir>/ 3) Change to u-boot-dir 4) make sifive_fu540_defconfig 5) make all 6) ZSBL loads the U-boot SPL(u-boot-spl.bin) from a partition with GUID type 5B193300-FC78-40CD-8002-E86C45580B47
sudo dd if=spl/u-boot-spl.bin of=/dev/sdc4 bs=1M
- U-boot SPL expects a u-boot FIT image(u-boot.itb) from 1st
partition(/dev/sdc1)
of SD card irrespective of GUID
sudo dd if=u-boot.itb of=/dev/sdc1 bs=1M
Seems like SPL (sdc4) at 4th partition and U-Boot proper at first partition which seems an unconventional way to create partition layouts based on the booting stage hierarchy.
I did send the changes on top of our changes [1] which indeed follow the conventional partition layout. So feel free to incorporate your series while sending the next version.
So from next version, you can drop CONFIG_SYS_MMCSD_RAW_MODE_U_BOOT_USE_PARTITION and write images as,
$ sudo dd if=u-boot.itb of=/dev/sda seek=4096 $ sudo dd if=spl/u-boot- spl.bin of=/dev/sda seek=2048
[1] https://patchwork.ozlabs.org/project/uboot/list/?series=168967
Thanks Jagan, will update in v7.
Jagan.

Hi Pragnesh,
On Wed, Apr 8, 2020 at 12:42 PM Pragnesh Patel pragnesh.patel@sifive.com wrote:
Hi Jagan,
-----Original Message----- From: Jagan Teki jagan@amarulasolutions.com Sent: 07 April 2020 15:02 To: Pragnesh Patel pragnesh.patel@sifive.com Cc: U-Boot-Denx u-boot@lists.denx.de; Atish Patra atish.patra@wdc.com; palmerdabbelt@google.com; Bin Meng bmeng.cn@gmail.com; Paul Walmsley paul.walmsley@sifive.com; Troy Benjegerdes troy.benjegerdes@sifive.com; Anup Patel anup.patel@wdc.com; Sagar Kadam sagar.kadam@sifive.com; Rick Chen rick@andestech.com Subject: Re: [PATCH v6 00/17] RISC-V SiFive FU540 support SPL
[External Email] Do not click links or attachments unless you recognize the sender and know the content is safe
Hi Pragnesh,
On Sun, Mar 29, 2020 at 10:36 PM Pragnesh Patel pragnesh.patel@sifive.com wrote:
This series add support for SPL to FU540.U-Boot SPL can boot from L2 LIM (0x0800_0000) and jump to OpenSBI(FW_DYNAMIC firmware) and U-Boot proper from MMC devices.
How to test this patch:
- Go to OpenSBI-dir : make PLATFORM=sifive/fu540 O=build_dir
I=install_dir FW_DYNAMIC=y install 2) cp install_dir/platform/sifive/fu540/firmware/fw_dynamic.bin <u-boot-dir>/ 3) Change to u-boot-dir 4) make sifive_fu540_defconfig 5) make all 6) ZSBL loads the U-boot SPL(u-boot-spl.bin) from a partition with GUID type 5B193300-FC78-40CD-8002-E86C45580B47
sudo dd if=spl/u-boot-spl.bin of=/dev/sdc4 bs=1M
- U-boot SPL expects a u-boot FIT image(u-boot.itb) from 1st
partition(/dev/sdc1)
of SD card irrespective of GUID
sudo dd if=u-boot.itb of=/dev/sdc1 bs=1M
Seems like SPL (sdc4) at 4th partition and U-Boot proper at first partition which seems an unconventional way to create partition layouts based on the booting stage hierarchy.
I did send the changes on top of our changes [1] which indeed follow the conventional partition layout. So feel free to incorporate your series while sending the next version.
So from next version, you can drop CONFIG_SYS_MMCSD_RAW_MODE_U_BOOT_USE_PARTITION and write images as,
$ sudo dd if=u-boot.itb of=/dev/sda seek=4096 $ sudo dd if=spl/u-boot- spl.bin of=/dev/sda seek=2048
[1] https://patchwork.ozlabs.org/project/uboot/list/?series=168967
Thanks Jagan, will update in v7.
I've reviewed the v6 patches. Since Jagan also sent several series related to SPI and booting from SPI that is dependent on this series, would you please post a v7 soon? We need get this SPL support merged as soon as possible. Thank you.
Regards, Bin

Hi Bin,
-----Original Message----- From: Bin Meng bmeng.cn@gmail.com Sent: 20 April 2020 20:13 To: Pragnesh Patel pragnesh.patel@sifive.com Cc: Jagan Teki jagan@amarulasolutions.com; U-Boot-Denx <u- boot@lists.denx.de>; Atish Patra atish.patra@wdc.com; palmerdabbelt@google.com; Paul Walmsley paul.walmsley@sifive.com; Troy Benjegerdes troy.benjegerdes@sifive.com; Anup Patel anup.patel@wdc.com; Sagar Kadam sagar.kadam@sifive.com; Rick Chen rick@andestech.com Subject: Re: [PATCH v6 00/17] RISC-V SiFive FU540 support SPL
[External Email] Do not click links or attachments unless you recognize the sender and know the content is safe
Hi Pragnesh,
On Wed, Apr 8, 2020 at 12:42 PM Pragnesh Patel pragnesh.patel@sifive.com wrote:
Hi Jagan,
-----Original Message----- From: Jagan Teki jagan@amarulasolutions.com Sent: 07 April 2020 15:02 To: Pragnesh Patel pragnesh.patel@sifive.com Cc: U-Boot-Denx u-boot@lists.denx.de; Atish Patra atish.patra@wdc.com; palmerdabbelt@google.com; Bin Meng bmeng.cn@gmail.com; Paul Walmsley paul.walmsley@sifive.com;
Troy
Benjegerdes troy.benjegerdes@sifive.com; Anup Patel anup.patel@wdc.com; Sagar Kadam sagar.kadam@sifive.com; Rick
Chen
rick@andestech.com Subject: Re: [PATCH v6 00/17] RISC-V SiFive FU540 support SPL
[External Email] Do not click links or attachments unless you recognize the sender and know the content is safe
Hi Pragnesh,
On Sun, Mar 29, 2020 at 10:36 PM Pragnesh Patel pragnesh.patel@sifive.com wrote:
This series add support for SPL to FU540.U-Boot SPL can boot from L2 LIM (0x0800_0000) and jump to OpenSBI(FW_DYNAMIC firmware) and U-Boot proper from MMC devices.
How to test this patch:
- Go to OpenSBI-dir : make PLATFORM=sifive/fu540 O=build_dir
I=install_dir FW_DYNAMIC=y install 2) cp install_dir/platform/sifive/fu540/firmware/fw_dynamic.bin <u-boot-dir>/ 3) Change to u-boot-dir 4) make sifive_fu540_defconfig 5) make all 6) ZSBL loads the U-boot SPL(u-boot-spl.bin) from a partition with GUID type 5B193300-FC78-40CD-8002-E86C45580B47
sudo dd if=spl/u-boot-spl.bin of=/dev/sdc4 bs=1M
- U-boot SPL expects a u-boot FIT image(u-boot.itb) from 1st
partition(/dev/sdc1)
of SD card irrespective of GUID
sudo dd if=u-boot.itb of=/dev/sdc1 bs=1M
Seems like SPL (sdc4) at 4th partition and U-Boot proper at first partition which seems an unconventional way to create partition layouts based on the booting stage hierarchy.
I did send the changes on top of our changes [1] which indeed follow the conventional partition layout. So feel free to incorporate your series while sending the next version.
So from next version, you can drop CONFIG_SYS_MMCSD_RAW_MODE_U_BOOT_USE_PARTITION and write
images as,
$ sudo dd if=u-boot.itb of=/dev/sda seek=4096 $ sudo dd if=spl/u-boot- spl.bin of=/dev/sda seek=2048
[1] https://patchwork.ozlabs.org/project/uboot/list/?series=168967
Thanks Jagan, will update in v7.
I've reviewed the v6 patches. Since Jagan also sent several series related to SPI and booting from SPI that is dependent on this series, would you please post a v7 soon? We need get this SPL support merged as soon as possible. Thank you.
Will submit v7 soon.
Regards, Bin
participants (3)
-
Bin Meng
-
Jagan Teki
-
Pragnesh Patel