[U-Boot] [PATCH 1/1] board: arm: Add support for Broadcom BCM7445D0
Thomas Fitzsimmons
fitzsim at fitzsim.org
Sun May 6 11:09:22 UTC 2018
Add support for loading U-Boot on the Broadcom 7445D0 SoC. This port
assumes Broadcom's BOLT bootloader is acting as the second stage
bootloader, and U-Boot is acting as the third stage bootloader, loaded
as an ELF program by BOLT.
Signed-off-by: Thomas Fitzsimmons <fitzsim at fitzsim.org>
Cc: Stefan Roese <sr at denx.de>
---
arch/arm/Kconfig | 12 +
arch/arm/cpu/armv7/Makefile | 1 +
arch/arm/cpu/armv7/bcm7445d0/Makefile | 11 +
arch/arm/cpu/armv7/bcm7445d0/lowlevel_init.S | 24 ++
arch/arm/lib/crt0.S | 2 +
arch/arm/mach-bcm7445d0/include/mach/gpio.h | 12 +
arch/arm/mach-bcm7445d0/include/mach/hardware.h | 12 +
arch/arm/mach-bcm7445d0/include/mach/sdhci.h | 15 +
board/broadcom/bcm7445d0/Kconfig | 132 ++++++++
board/broadcom/bcm7445d0/Makefile | 11 +
board/broadcom/bcm7445d0/bcm7445d0.c | 147 ++++++++
common/fdt_support.c | 9 +-
common/image-fit.c | 2 +
configs/bcm7445d0_defconfig | 21 ++
drivers/mmc/Makefile | 1 +
drivers/mmc/bcmstb_sdhci.c | 59 ++++
drivers/spi/Kconfig | 7 +
drivers/spi/Makefile | 1 +
drivers/spi/bcmstb_spi.c | 428 ++++++++++++++++++++++++
dts/Kconfig | 6 +
include/configs/bcm7445d0.h | 227 +++++++++++++
include/configs/bcmstb.h | 57 ++++
lib/fdtdec.c | 8 +
23 files changed, 1204 insertions(+), 1 deletion(-)
create mode 100644 arch/arm/cpu/armv7/bcm7445d0/Makefile
create mode 100644 arch/arm/cpu/armv7/bcm7445d0/lowlevel_init.S
create mode 100644 arch/arm/mach-bcm7445d0/include/mach/gpio.h
create mode 100644 arch/arm/mach-bcm7445d0/include/mach/hardware.h
create mode 100644 arch/arm/mach-bcm7445d0/include/mach/sdhci.h
create mode 100644 board/broadcom/bcm7445d0/Kconfig
create mode 100644 board/broadcom/bcm7445d0/Makefile
create mode 100644 board/broadcom/bcm7445d0/bcm7445d0.c
create mode 100644 configs/bcm7445d0_defconfig
create mode 100644 drivers/mmc/bcmstb_sdhci.c
create mode 100644 drivers/spi/bcmstb_spi.c
create mode 100644 include/configs/bcm7445d0.h
create mode 100644 include/configs/bcmstb.h
diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig
index 9bd70f4..b2df30a 100644
--- a/arch/arm/Kconfig
+++ b/arch/arm/Kconfig
@@ -498,6 +498,17 @@ config TARGET_VEXPRESS_CA15_TC2
select CPU_V7_HAS_VIRT
select PL011_SERIAL
+config TARGET_BCM7445D0
+ bool "Broadcom 7445D0 TSBL"
+ select CPU_V7
+ select SUPPORT_SPL
+ help
+ Support for the Broadcom 7445D0 SoC. This port assumes Bolt
+ is acting as the second stage bootloader, and U-Boot is
+ acting as the third stage bootloader (TSBL), loaded by Bolt.
+ This port may work on other BCM7xxx boards with
+ configuration changes.
+
config TARGET_VEXPRESS_CA5X2
bool "Support vexpress_ca5x2"
select CPU_V7
@@ -1320,6 +1331,7 @@ source "board/armltd/vexpress/Kconfig"
source "board/armltd/vexpress64/Kconfig"
source "board/broadcom/bcm23550_w1d/Kconfig"
source "board/broadcom/bcm28155_ap/Kconfig"
+source "board/broadcom/bcm7445d0/Kconfig"
source "board/broadcom/bcmcygnus/Kconfig"
source "board/broadcom/bcmnsp/Kconfig"
source "board/broadcom/bcmns2/Kconfig"
diff --git a/arch/arm/cpu/armv7/Makefile b/arch/arm/cpu/armv7/Makefile
index b14ee54..7183d4d 100644
--- a/arch/arm/cpu/armv7/Makefile
+++ b/arch/arm/cpu/armv7/Makefile
@@ -30,6 +30,7 @@ endif
obj-$(if $(filter bcm235xx,$(SOC)),y) += bcm235xx/
obj-$(if $(filter bcm281xx,$(SOC)),y) += bcm281xx/
+obj-$(if $(filter bcm7445d0,$(SOC)),y) += bcm7445d0/
obj-$(if $(filter bcmcygnus,$(SOC)),y) += bcmcygnus/
obj-$(if $(filter bcmnsp,$(SOC)),y) += bcmnsp/
obj-$(if $(filter ls102xa,$(SOC)),y) += ls102xa/
diff --git a/arch/arm/cpu/armv7/bcm7445d0/Makefile b/arch/arm/cpu/armv7/bcm7445d0/Makefile
new file mode 100644
index 0000000..796f482
--- /dev/null
+++ b/arch/arm/cpu/armv7/bcm7445d0/Makefile
@@ -0,0 +1,11 @@
+#
+# (C) Copyright 2018
+# Cisco Systems, Inc. <www.cisco.com>
+#
+# Author :
+# Thomas Fitzsimmons <fitzsim at fitzsim.org>
+#
+# SPDX-License-Identifier: GPL-2.0+
+#
+
+obj-y := lowlevel_init.o
diff --git a/arch/arm/cpu/armv7/bcm7445d0/lowlevel_init.S b/arch/arm/cpu/armv7/bcm7445d0/lowlevel_init.S
new file mode 100644
index 0000000..1eb67a0
--- /dev/null
+++ b/arch/arm/cpu/armv7/bcm7445d0/lowlevel_init.S
@@ -0,0 +1,24 @@
+/*
+ * (C) Copyright 2018
+ * Cisco Systems, Inc. <www.cisco.com>
+ *
+ * Author :
+ * Thomas Fitzsimmons <fitzsim at fitzsim.org>
+ *
+ * SPDX-License-Identifier: GPL-2.0+
+ */
+
+#include <linux/linkage.h>
+
+ENTRY(save_boot_params)
+ ldr r6, =bcm7445d0_boot_parameters
+ str r0, [r6, #0]
+ str r1, [r6, #4]
+ str r2, [r6, #8]
+ str r3, [r6, #12]
+ str sp, [r6, #16]
+ str lr, [r6, #20]
+ ldr r6, =prior_stage_fdt_address
+ str r2, [r6]
+ b save_boot_params_ret
+ENDPROC(save_boot_params)
diff --git a/arch/arm/lib/crt0.S b/arch/arm/lib/crt0.S
index fa81317..f1a6f35 100644
--- a/arch/arm/lib/crt0.S
+++ b/arch/arm/lib/crt0.S
@@ -94,6 +94,7 @@ ENTRY(_main)
* 'here' but relocated.
*/
+#if !defined(CONFIG_OF_PRIOR_STAGE)
ldr r0, [r9, #GD_START_ADDR_SP] /* sp = gd->start_addr_sp */
bic r0, r0, #7 /* 8-byte alignment for ABI compliance */
mov sp, r0
@@ -108,6 +109,7 @@ ENTRY(_main)
#endif
ldr r0, [r9, #GD_RELOCADDR] /* r0 = gd->relocaddr */
b relocate_code
+#endif
here:
/*
* now relocate vectors
diff --git a/arch/arm/mach-bcm7445d0/include/mach/gpio.h b/arch/arm/mach-bcm7445d0/include/mach/gpio.h
new file mode 100644
index 0000000..f7163e4
--- /dev/null
+++ b/arch/arm/mach-bcm7445d0/include/mach/gpio.h
@@ -0,0 +1,12 @@
+/*
+ * (C) Copyright 2018
+ * Cisco Systems, Inc. <www.cisco.com>
+ *
+ * Author :
+ * Thomas Fitzsimmons <fitzsim at fitzsim.org>
+ *
+ * SPDX-License-Identifier: GPL-2.0+
+ */
+#ifndef _BCM7445D0_GPIO_H
+#define _BCM7445D0_GPIO_H
+#endif /* _BCM7445D0_GPIO_H */
diff --git a/arch/arm/mach-bcm7445d0/include/mach/hardware.h b/arch/arm/mach-bcm7445d0/include/mach/hardware.h
new file mode 100644
index 0000000..28418bf
--- /dev/null
+++ b/arch/arm/mach-bcm7445d0/include/mach/hardware.h
@@ -0,0 +1,12 @@
+/*
+ * (C) Copyright 2018
+ * Cisco Systems, Inc. <www.cisco.com>
+ *
+ * Author :
+ * Thomas Fitzsimmons <fitzsim at fitzsim.org>
+ *
+ * SPDX-License-Identifier: GPL-2.0+
+ */
+#ifndef _BCM7445D0_HARDWARE_H
+#define _BCM7445D0_HARDWARE_H
+#endif /* _BCM7445D0_HARDWARE_H */
diff --git a/arch/arm/mach-bcm7445d0/include/mach/sdhci.h b/arch/arm/mach-bcm7445d0/include/mach/sdhci.h
new file mode 100644
index 0000000..2c7fb09
--- /dev/null
+++ b/arch/arm/mach-bcm7445d0/include/mach/sdhci.h
@@ -0,0 +1,15 @@
+/*
+ * (C) Copyright 2018
+ * Cisco Systems, Inc. <www.cisco.com>
+ *
+ * Author :
+ * Thomas Fitzsimmons <fitzsim at fitzsim.org>
+ *
+ * SPDX-License-Identifier: GPL-2.0+
+ */
+#ifndef _BCM7445D0_SDHCI_H
+#define _BCM7445D0_SDHCI_H
+
+int bcmstb_sdhci_init(phys_addr_t regbase);
+
+#endif /* _BCM7445D0_SDHCI_H */
diff --git a/board/broadcom/bcm7445d0/Kconfig b/board/broadcom/bcm7445d0/Kconfig
new file mode 100644
index 0000000..d710503
--- /dev/null
+++ b/board/broadcom/bcm7445d0/Kconfig
@@ -0,0 +1,132 @@
+if TARGET_BCM7445D0
+
+config SYS_BOARD
+ default "bcm7445d0"
+
+config SYS_VENDOR
+ default "broadcom"
+
+config SYS_CONFIG_NAME
+ default "bcm7445d0"
+
+config SYS_SOC
+ default "bcm7445d0"
+
+config BCHP_BSPI_MAST_N_BOOT_CTRL
+ hex ""
+ default 0x003e3208
+
+config BCHP_EBI_CS_SPI_SELECT
+ hex ""
+ default 0x003e0920
+
+config BCHP_HIF_MSPI_SPCR2_CONT_AFTER_CMD_MASK
+ hex ""
+ default 0x00000080
+
+config BCHP_HIF_MSPI_SPCR2_SPE_MASK
+ hex ""
+ default 0x00000040
+
+config BCHP_HIF_MSPI_SPCR2_SPIFIE_MASK
+ hex ""
+ default 0x00000020
+
+config BCHP_HIF_MSPI_WRITE_LOCK
+ hex ""
+ default 0x003e3580
+
+config BCHP_HIF_MSPI_WRITE_LOCK_WRITE_LOCK_DEFAULT
+ hex ""
+ default 0x00000000
+
+config BCHP_HIF_MSPI_WRITE_LOCK_WRITE_LOCK_MASK
+ hex ""
+ default 0x00000001
+
+config BCHP_HIF_MSPI_WRITE_LOCK_WRITE_LOCK_SHIFT
+ hex ""
+ default 0
+
+config BCHP_HIF_SPI_INTR2_CPU_CLEAR
+ hex ""
+ default 0x003e1a08
+
+config BCHP_HIF_SPI_INTR2_CPU_MASK_CLEAR
+ hex ""
+ default 0x003e1a14
+
+config BCHP_HIF_SPI_INTR2_CPU_MASK_SET
+ hex ""
+ default 0x003e1a10
+
+config BCHP_HIF_SPI_INTR2_CPU_SET_MSPI_DONE_MASK
+ hex ""
+ default 0x00000020
+
+config BCMSTB_ACCOMMODATE_STBLINUX
+ bool ""
+ default y
+ help
+ This prevents U-Boot from adding memory reservations for the
+ lengths of initramfs and DTB. Without skipping these,
+ stblinux's "contiguous memory allocator" (CMA) Linux driver
+ (cma_driver) will allocate memory ranges smaller than what
+ are actually available, because it only checks reservation
+ sizes. It doesn't check if the reserved range overlaps the
+ range it allocates. stblinux also tries to move the DTB to
+ a lower memory location early in the Linux boot. If the FIT
+ image specifies a load address for the initramfs then
+ sometimes the DTB is moved into the range where the
+ initramfs image is loaded. Defining this will mean that
+ FIT-provided initramfs load addresses are ignored.
+
+config BCMSTB_SDHCI
+ bool ""
+ default y
+
+config BCMSTB_SDHCI_BASE
+ hex ""
+ default 0xf03e0200
+
+config BCMSTB_SPI_BASE
+ hex ""
+ default 0xf03e3400
+
+config CMD_FDT_MAX_DUMP
+ int ""
+ default 256
+
+config GENERIC_MMC
+ bool ""
+ default y
+
+config MMC_SDMA
+ bool ""
+ default y
+
+config SDHCI
+ bool ""
+ default y
+
+config SYS_BCMSTB_SPI_WAIT
+ int ""
+ default 10
+
+config SYS_FDT_SAVE_ADDRESS
+ hex ""
+ default 0x1f00000
+
+config SYS_NO_FLASH
+ bool ""
+ default y
+
+config TIMER_FREQUENCY_REGISTER_ADDRESS
+ hex ""
+ default 0xf0412020
+
+config TIMER_LOW_REGISTER_ADDRESS
+ hex ""
+ default 0xf0412008
+
+endif
diff --git a/board/broadcom/bcm7445d0/Makefile b/board/broadcom/bcm7445d0/Makefile
new file mode 100644
index 0000000..265bc74
--- /dev/null
+++ b/board/broadcom/bcm7445d0/Makefile
@@ -0,0 +1,11 @@
+#
+# (C) Copyright 2018
+# Cisco Systems, Inc. <www.cisco.com>
+#
+# Author :
+# Thomas Fitzsimmons <fitzsim at fitzsim.org>
+#
+# SPDX-License-Identifier: GPL-2.0+
+#
+
+obj-y := bcm7445d0.o
diff --git a/board/broadcom/bcm7445d0/bcm7445d0.c b/board/broadcom/bcm7445d0/bcm7445d0.c
new file mode 100644
index 0000000..7f8e1f6
--- /dev/null
+++ b/board/broadcom/bcm7445d0/bcm7445d0.c
@@ -0,0 +1,147 @@
+/*
+ * (C) Copyright 2018
+ * Cisco Systems, Inc. <www.cisco.com>
+ *
+ * Author :
+ * Thomas Fitzsimmons <fitzsim at fitzsim.org>
+ *
+ * SPDX-License-Identifier: GPL-2.0+
+ */
+
+#include <linux/types.h>
+#include <common.h>
+#include <asm/io.h>
+#include <asm/arch/sdhci.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+struct bcm7445d0_boot_parameters {
+ u32 r0;
+ u32 r1;
+ u32 r2;
+ u32 r3;
+ u32 sp;
+ u32 lr;
+};
+
+struct bcm7445d0_boot_parameters bcm7445d0_boot_parameters \
+__attribute__((section(".data")));
+
+phys_addr_t prior_stage_fdt_address __attribute__((section(".data")));
+
+union reg_value_union {
+ const char *data;
+ const phys_addr_t *address;
+};
+
+int board_init(void)
+{
+ return 0;
+}
+
+u32 get_board_rev(void)
+{
+ return 0;
+}
+
+void reset_cpu(ulong ignored)
+{
+}
+
+int print_cpuinfo(void)
+{
+ return 0;
+}
+
+int dram_init(void)
+{
+ gd->ram_size = 0xc0000000;
+
+ return 0;
+}
+
+int dram_init_banksize(void)
+{
+ bd_t *bd = gd->bd;
+
+ bd->bi_dram[0].start = 0x00000000;
+ bd->bi_dram[0].size = 0x40000000;
+ bd->bi_dram[1].start = 0x40000000;
+ bd->bi_dram[1].size = 0x40000000;
+ bd->bi_dram[2].start = 0x80000000;
+ bd->bi_dram[2].size = 0x40000000;
+
+ return 0;
+}
+
+void enable_caches(void)
+{
+ /*
+ * Nothing required here, since the prior stage bootloader has
+ * enabled I-cache and D-cache already. Implementing this
+ * function silences the warning in the default function.
+ */
+}
+
+int board_mmc_init(bd_t *bis)
+{
+ /* Just use the hard-coded SDHCI base address, though it could
+ * be determined from the DTB provided by the prior stage
+ * bootloader.
+ */
+ bcmstb_sdhci_init(CONFIG_BCMSTB_SDHCI_BASE);
+
+ return 0;
+}
+
+int timer_init(void)
+{
+ gd->arch.timer_rate_hz = readl(CONFIG_TIMER_FREQUENCY_REGISTER_ADDRESS);
+
+ return 0;
+}
+
+ulong get_tbclk(void)
+{
+ return gd->arch.timer_rate_hz;
+}
+
+unsigned long timer_read_counter(void)
+{
+ return readl(CONFIG_TIMER_LOW_REGISTER_ADDRESS);
+}
+
+int board_late_init(void)
+{
+ printf("Arguments from prior stage bootloader:\n");
+ printf("General Purpose Register 0: 0x%x\n",
+ bcm7445d0_boot_parameters.r0);
+ printf("General Purpose Register 1: 0x%x\n",
+ bcm7445d0_boot_parameters.r1);
+ printf("General Purpose Register 2: 0x%x\n",
+ bcm7445d0_boot_parameters.r2);
+ printf("General Purpose Register 3: 0x%x\n",
+ bcm7445d0_boot_parameters.r3);
+ printf("Stack Pointer Register: 0x%x\n",
+ bcm7445d0_boot_parameters.sp);
+ printf("Link Register: 0x%x\n",
+ bcm7445d0_boot_parameters.lr);
+ printf("Assuming timer frequency register at: 0x%x\n",
+ CONFIG_TIMER_FREQUENCY_REGISTER_ADDRESS);
+ printf("Read timer frequency (in Hz): %ld\n", gd->arch.timer_rate_hz);
+ printf("Prior stage provided DTB at: 0x%p\n",
+ (void *)prior_stage_fdt_address);
+ /*
+ * Set fdtcontroladdr in the environment so that scripts can
+ * refer to it, for example, to reuse it for fdtaddr.
+ */
+ env_set_hex("fdtcontroladdr", prior_stage_fdt_address);
+ /*
+ * Do not set machid to the machine identifier value provided
+ * by the prior stage bootloader
+ * (bcm7445d0_boot_parameters.r1) because we're using a device
+ * tree to boot Linux.
+ */
+
+ return 0;
+}
diff --git a/common/fdt_support.c b/common/fdt_support.c
index 66a313e..f07dfe3 100644
--- a/common/fdt_support.c
+++ b/common/fdt_support.c
@@ -242,11 +242,13 @@ int fdt_initrd(void *fdt, ulong initrd_start, ulong initrd_end)
}
}
+#if !defined(CONFIG_BCMSTB_ACCOMMODATE_STBLINUX)
err = fdt_add_mem_rsv(fdt, initrd_start, initrd_end - initrd_start);
if (err < 0) {
printf("fdt_initrd: %s\n", fdt_strerror(err));
return err;
}
+#endif
is_u64 = (fdt_address_cells(fdt, 0) == 2);
@@ -602,7 +604,10 @@ int fdt_shrink_to_minimum(void *blob, uint extrasize)
{
int i;
uint64_t addr, size;
- int total, ret;
+ int total;
+#if !defined(CONFIG_BCMSTB_ACCOMMODATE_STBLINUX)
+ int ret;
+#endif
uint actualsize;
if (!blob)
@@ -635,9 +640,11 @@ int fdt_shrink_to_minimum(void *blob, uint extrasize)
fdt_set_totalsize(blob, actualsize);
/* Add the new reservation */
+#if !defined(CONFIG_BCMSTB_ACCOMMODATE_STBLINUX)
ret = fdt_add_mem_rsv(blob, (uintptr_t)blob, actualsize);
if (ret < 0)
return ret;
+#endif
return actualsize;
}
diff --git a/common/image-fit.c b/common/image-fit.c
index 030a3e5..a346f8c 100644
--- a/common/image-fit.c
+++ b/common/image-fit.c
@@ -1905,6 +1905,7 @@ int fit_image_load(bootm_headers_t *images, ulong addr,
return -EBADF;
}
} else if (load_op != FIT_LOAD_OPTIONAL_NON_ZERO || load) {
+#if !defined(CONFIG_BCMSTB_ACCOMMODATE_STBLINUX)
ulong image_start, image_end;
ulong load_end;
void *dst;
@@ -1929,6 +1930,7 @@ int fit_image_load(bootm_headers_t *images, ulong addr,
dst = map_sysmem(load, len);
memmove(dst, buf, len);
data = load;
+#endif
}
bootstage_mark(bootstage_id + BOOTSTAGE_SUB_LOAD);
diff --git a/configs/bcm7445d0_defconfig b/configs/bcm7445d0_defconfig
new file mode 100644
index 0000000..1e1162e
--- /dev/null
+++ b/configs/bcm7445d0_defconfig
@@ -0,0 +1,21 @@
+CONFIG_ARM=y
+CONFIG_SYS_TEXT_BASE=0x80100000
+CONFIG_TARGET_BCM7445D0=y
+CONFIG_USE_PRIVATE_LIBGCC=y
+CONFIG_OF_CONTROL=y
+CONFIG_OF_PRIOR_STAGE=y
+CONFIG_DM=y
+CONFIG_DM_SPI=y
+CONFIG_DM_SPI_FLASH=y
+CONFIG_SPI=y
+CONFIG_SPI_FLASH=y
+CONFIG_ENV_IS_IN_SPI_FLASH=y
+CONFIG_FIT=y
+CONFIG_FIT_SIGNATURE=y
+CONFIG_RSA=y
+CONFIG_BLK=n
+CONFIG_MMC_SDHCI=y
+CONFIG_CONS_INDEX=3
+CONFIG_BOOTDELAY=1
+CONFIG_SYS_PROMPT="U-Boot>"
+CONFIG_HUSH_PARSER=y
diff --git a/drivers/mmc/Makefile b/drivers/mmc/Makefile
index cf46c33..959f410 100644
--- a/drivers/mmc/Makefile
+++ b/drivers/mmc/Makefile
@@ -26,6 +26,7 @@ obj-$(CONFIG_MMC_DW_EXYNOS) += exynos_dw_mmc.o
obj-$(CONFIG_MMC_DW_K3) += hi6220_dw_mmc.o
obj-$(CONFIG_MMC_DW_ROCKCHIP) += rockchip_dw_mmc.o
obj-$(CONFIG_MMC_DW_SOCFPGA) += socfpga_dw_mmc.o
+obj-$(CONFIG_BCMSTB_SDHCI) += bcmstb_sdhci.o
obj-$(CONFIG_FSL_ESDHC) += fsl_esdhc.o
obj-$(CONFIG_FTSDC010) += ftsdc010_mci.o
obj-$(CONFIG_GENERIC_ATMEL_MCI) += gen_atmel_mci.o
diff --git a/drivers/mmc/bcmstb_sdhci.c b/drivers/mmc/bcmstb_sdhci.c
new file mode 100644
index 0000000..933c546
--- /dev/null
+++ b/drivers/mmc/bcmstb_sdhci.c
@@ -0,0 +1,59 @@
+#include <common.h>
+#include <malloc.h>
+#include <sdhci.h>
+
+/*
+ * The BCMSTB SDHCI has a quirk in that its actual maximum frequency
+ * capability is 100 MHz. The divisor that is eventually written to
+ * SDHCI_CLOCK_CONTROL is calculated based on what the MMC device
+ * reports, and relative to this maximum frequency.
+ *
+ * This define used to be set to 52000000 (52 MHz), the desired
+ * maximum frequency, but that would result in the communication
+ * actually running at 100 MHz (seemingly without issue), which is
+ * out-of-spec.
+ *
+ * Now, by setting this to 0 (auto-detect), 100 MHz will be read from
+ * the capabilities register, and the resulting divisor will be
+ * doubled, meaning that the clock control register will be set to the
+ * in-spec 52 MHz value.
+ */
+#define BCMSTB_SDHCI_MAXIMUM_CLOCK_FREQUENCY 0
+/*
+ * When the minimum clock frequency is set to 0 (auto-detect), U-Boot
+ * sets it to 100 MHz divided by SDHCI_MAX_DIV_SPEC_300, or 48,875 Hz,
+ * which results in the controller timing out when trying to
+ * communicate with the MMC device. Hard-code this value to 400000
+ * (400 kHz) to prevent this.
+ */
+#define BCMSTB_SDHCI_MINIMUM_CLOCK_FREQUENCY 400000
+
+static char *BCMSTB_SDHCI_NAME = "bcmstb-sdhci";
+
+/*
+ * This driver has only been tested with eMMC devices; SD devices may
+ * not work.
+ */
+int bcmstb_sdhci_init(phys_addr_t regbase)
+{
+ struct sdhci_host *host = NULL;
+
+ host = (struct sdhci_host *)malloc(sizeof(struct sdhci_host));
+ if (!host) {
+ printf("bcmstb-sdhci malloc fail!\n");
+ return 1;
+ }
+ memset(host, 0, sizeof(*host));
+
+ host->name = BCMSTB_SDHCI_NAME;
+ host->ioaddr = (void *)regbase;
+ host->quirks = 0;
+
+ host->cfg.part_type = PART_TYPE_DOS;
+
+ host->version = sdhci_readw(host, SDHCI_HOST_VERSION);
+
+ return add_sdhci(host,
+ BCMSTB_SDHCI_MAXIMUM_CLOCK_FREQUENCY,
+ BCMSTB_SDHCI_MINIMUM_CLOCK_FREQUENCY);
+}
diff --git a/drivers/spi/Kconfig b/drivers/spi/Kconfig
index 6667f73..c4a6c8d 100644
--- a/drivers/spi/Kconfig
+++ b/drivers/spi/Kconfig
@@ -66,6 +66,13 @@ config BCM63XX_SPI
access the SPI NOR flash on platforms embedding these Broadcom
SPI cores.
+config BCMSTB_SPI
+ bool "Broadcom Set Top Box SPI driver"
+ help
+ Enable the Broadcom Set Top Box SPI driver. This driver can
+ be used to access the SPI flash on platforms embedding this
+ Broadcom SPI core.
+
config CADENCE_QSPI
bool "Cadence QSPI driver"
help
diff --git a/drivers/spi/Makefile b/drivers/spi/Makefile
index 176bfa0..0f864be 100644
--- a/drivers/spi/Makefile
+++ b/drivers/spi/Makefile
@@ -20,6 +20,7 @@ obj-$(CONFIG_ATH79_SPI) += ath79_spi.o
obj-$(CONFIG_ATMEL_SPI) += atmel_spi.o
obj-$(CONFIG_BCM63XX_HSSPI) += bcm63xx_hsspi.o
obj-$(CONFIG_BCM63XX_SPI) += bcm63xx_spi.o
+obj-$(CONFIG_BCMSTB_SPI) += bcmstb_spi.o
obj-$(CONFIG_CADENCE_QSPI) += cadence_qspi.o cadence_qspi_apb.o
obj-$(CONFIG_CF_SPI) += cf_spi.o
obj-$(CONFIG_DAVINCI_SPI) += davinci_spi.o
diff --git a/drivers/spi/bcmstb_spi.c b/drivers/spi/bcmstb_spi.c
new file mode 100644
index 0000000..183a547
--- /dev/null
+++ b/drivers/spi/bcmstb_spi.c
@@ -0,0 +1,428 @@
+/*
+ * (C) Copyright 2018
+ * Cisco Systems, Inc. <www.cisco.com>
+ *
+ * Author :
+ * Thomas Fitzsimmons <fitzsim at fitzsim.org>
+ *
+ * SPDX-License-Identifier: GPL-2.0+
+ */
+
+#include <asm/io.h>
+#include <common.h>
+#include <config.h>
+#include <dm.h>
+#include <errno.h>
+#include <fdtdec.h>
+#include <malloc.h>
+#include <spi.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+#define SPBR_MIN 8
+#define BITS_PER_WORD 8
+
+#define NUM_TXRAM 32
+#define NUM_RXRAM 32
+#define NUM_CDRAM 16
+
+#ifdef DEBUG
+static int debug_tx_rx;
+#define D(fmt, args...) debug_cond(debug_tx_rx, fmt, ##args)
+#else
+#define D(fmt, args...)
+#endif
+
+/* MSPI registers. BSPI is disabled. */
+struct bcmstb_spi_regs {
+ u32 spcr0_lsb; /* 0x000 */
+ u32 spcr0_msb; /* 0x004 */
+ u32 spcr1_lsb; /* 0x008 */
+ u32 spcr1_msb; /* 0x00c */
+ u32 newqp; /* 0x010 */
+ u32 endqp; /* 0x014 */
+ u32 spcr2; /* 0x018 */
+ u32 reserved0; /* 0x01c */
+ u32 mspi_status; /* 0x020 */
+ u32 cptqp; /* 0x024 */
+ u32 spcr3; /* 0x028 */
+ u32 revision; /* 0x02c */
+ u32 reserved1[4]; /* 0x030 */
+ u32 txram[NUM_TXRAM]; /* 0x040 */
+ u32 rxram[NUM_RXRAM]; /* 0x0c0 */
+ u32 cdram[NUM_CDRAM]; /* 0x140 */
+};
+
+struct bcmstb_spi_platdata {
+ struct bcmstb_spi_regs *regs;
+};
+
+struct bcmstb_spi_priv {
+ struct bcmstb_spi_regs *regs;
+ int default_cs;
+ int curr_cs;
+ uint tx_slot;
+ uint rx_slot;
+ u8 saved_cmd[NUM_CDRAM];
+ uint saved_cmd_len;
+ void *saved_din_addr;
+};
+
+/*
+ * If we could rely on the prior stage bootloader to insert a "spi0"
+ * alias, we could enable CONFIG_DM_SEQ_ALIAS and omit
+ * bcmstb_spi_bind. We cannot rely on this behaviour, so we have to
+ * handle binding explicitly.
+ */
+static int bcmstb_spi_bind(struct udevice *bus)
+{
+ char spi0_name[30];
+ int node = dev_of_offset(bus);
+
+ memset(spi0_name, 0, sizeof(spi0_name));
+
+ debug("bcmstb_spi_bind: %s, ", bus->name);
+
+ snprintf(spi0_name, sizeof(spi0_name), "spi@%08x",
+ CONFIG_BCMSTB_SPI_BASE);
+ if (strcmp(fdt_get_name(gd->fdt_blob, node, NULL),
+ spi0_name) == 0) {
+ bus->req_seq = 0;
+ }
+
+ debug("%d\n", bus->req_seq);
+
+ return 0;
+}
+
+static int bcmstb_spi_ofdata_to_platdata(struct udevice *bus)
+{
+ struct bcmstb_spi_platdata *plat = dev_get_platdata(bus);
+ const void *blob = gd->fdt_blob;
+ int node = dev_of_offset(bus);
+ u32 address = 0;
+ int code = 0;
+
+ code = fdtdec_get_int_array(blob, node, "reg", &address, 1);
+ if (code != 0) {
+ printf("bcmstb_spi_ofdata_to_platdata:"
+ " Failed to read reg property\n");
+ return code;
+ }
+
+ plat->regs = (struct bcmstb_spi_regs *)address;
+ D("spi_xfer: tx regs: %p\n", &plat->regs->txram[0]);
+ D("spi_xfer: rx regs: %p\n", &plat->regs->rxram[0]);
+
+ return 0;
+}
+
+static void bcmstb_spi_hw_set_parms(struct bcmstb_spi_priv *priv)
+{
+ writel(SPBR_MIN, &priv->regs->spcr0_lsb);
+ writel(BITS_PER_WORD << 2 | SPI_MODE_3, &priv->regs->spcr0_msb);
+}
+
+static void bcmstb_spi_enable_interrupt(u32 mask)
+{
+ BDEV_SET_RB(CONFIG_BCHP_HIF_SPI_INTR2_CPU_MASK_CLEAR, mask);
+}
+
+static void bcmstb_spi_disable_interrupt(u32 mask)
+{
+ BDEV_SET_RB(CONFIG_BCHP_HIF_SPI_INTR2_CPU_MASK_SET, mask);
+}
+
+static void bcmstb_spi_clear_interrupt(u32 mask)
+{
+ BDEV_SET_RB(CONFIG_BCHP_HIF_SPI_INTR2_CPU_CLEAR, mask);
+}
+
+static int bcmstb_spi_probe(struct udevice *bus)
+{
+ struct bcmstb_spi_platdata *plat = dev_get_platdata(bus);
+ struct bcmstb_spi_priv *priv = dev_get_priv(bus);
+
+ priv->regs = plat->regs;
+ priv->default_cs = 0;
+ priv->curr_cs = -1;
+ priv->tx_slot = 0;
+ priv->rx_slot = 0;
+ memset(priv->saved_cmd, 0, NUM_CDRAM);
+ priv->saved_cmd_len = 0;
+ priv->saved_din_addr = NULL;
+
+ /* Disable BSPI. */
+ BDEV_WR_RB(CONFIG_BCHP_BSPI_MAST_N_BOOT_CTRL, 1);
+
+ /* Set up interrupts. */
+ bcmstb_spi_disable_interrupt(0xffffffff);
+ bcmstb_spi_clear_interrupt(0xffffffff);
+ bcmstb_spi_enable_interrupt(
+ CONFIG_BCHP_HIF_SPI_INTR2_CPU_SET_MSPI_DONE_MASK);
+
+ /* Set up control registers. */
+ writel(0, &priv->regs->spcr1_lsb);
+ writel(0, &priv->regs->spcr1_msb);
+ writel(0, &priv->regs->newqp);
+ writel(0, &priv->regs->endqp);
+ writel(CONFIG_BCHP_HIF_MSPI_SPCR2_SPIFIE_MASK, &priv->regs->spcr2);
+ writel(0, &priv->regs->spcr3);
+
+ bcmstb_spi_hw_set_parms(priv);
+
+ return 0;
+}
+
+static int bcmstb_spi_remove(struct udevice *dev)
+{
+ return 0;
+}
+
+static int bcmstb_spi_claim_bus(struct udevice *dev)
+{
+ return 0;
+}
+
+static int bcmstb_spi_release_bus(struct udevice *dev)
+{
+ return 0;
+}
+
+static void bcmstb_spi_submit(struct bcmstb_spi_priv *priv, bool done)
+{
+ D("WR NEWQP: %d\n", 0);
+ writel(0, &priv->regs->newqp);
+
+ D("WR ENDQP: %d\n", priv->tx_slot - 1);
+ writel(priv->tx_slot - 1, &priv->regs->endqp);
+
+ if (done) {
+ D("WR CDRAM[%d]: %02x\n", priv->tx_slot - 1,
+ readl(&priv->regs->cdram[priv->tx_slot - 1]) & ~0x80);
+ writel(readl(&priv->regs->cdram[priv->tx_slot - 1]) & ~0x80,
+ &priv->regs->cdram[priv->tx_slot - 1]);
+ }
+
+ /* Force chip select first time. */
+ if (priv->curr_cs != priv->default_cs) {
+ D("spi_xfer: switching chip select to %d\n",
+ priv->default_cs);
+ BDEV_WR_RB(CONFIG_BCHP_EBI_CS_SPI_SELECT,
+ (BDEV_RD(CONFIG_BCHP_EBI_CS_SPI_SELECT) &
+ ~0xff) | (1 << priv->default_cs));
+ udelay(10);
+ priv->curr_cs = priv->default_cs;
+ }
+
+ D("WR WRITE_LOCK: %02x\n", 1);
+ BDEV_WR_F_RB(HIF_MSPI_WRITE_LOCK, WRITE_LOCK, 1);
+
+ D("WR SPCR2: %02x\n",
+ CONFIG_BCHP_HIF_MSPI_SPCR2_SPIFIE_MASK |
+ CONFIG_BCHP_HIF_MSPI_SPCR2_SPE_MASK |
+ CONFIG_BCHP_HIF_MSPI_SPCR2_CONT_AFTER_CMD_MASK);
+ writel(CONFIG_BCHP_HIF_MSPI_SPCR2_SPIFIE_MASK |
+ CONFIG_BCHP_HIF_MSPI_SPCR2_SPE_MASK |
+ CONFIG_BCHP_HIF_MSPI_SPCR2_CONT_AFTER_CMD_MASK,
+ &priv->regs->spcr2);
+}
+
+static int bcmstb_spi_wait(struct bcmstb_spi_regs *regs)
+{
+ u32 start_time = get_timer(0);
+ u32 status = readl(®s->mspi_status);
+
+ while (!(status & 1)) {
+ if (get_timer(start_time) >
+ CONFIG_SYS_BCMSTB_SPI_WAIT) {
+ return -ETIMEDOUT;
+ }
+ status = readl(®s->mspi_status);
+ }
+
+ writel(readl(®s->mspi_status) & ~1, ®s->mspi_status);
+ bcmstb_spi_clear_interrupt(
+ CONFIG_BCHP_HIF_SPI_INTR2_CPU_SET_MSPI_DONE_MASK);
+
+ return 0;
+}
+
+static int bcmstb_spi_xfer(struct udevice *dev, unsigned int bitlen,
+ const void *dout, void *din, unsigned long flags)
+{
+ uint len = bitlen / 8;
+ uint tx_len = len;
+ uint rx_len = len;
+ const u8 *out_bytes = (u8 *)dout;
+ u8 *in_bytes = (u8 *)din;
+ struct udevice *bus = dev_get_parent(dev);
+ struct bcmstb_spi_priv *priv = dev_get_priv(bus);
+ struct bcmstb_spi_regs *regs = priv->regs;
+
+ D("spi_xfer: %d, t: %p, r: %p, f: %lx\n", len, dout, din, flags);
+ D("spi_xfer: chip select: %x\n",
+ readl(CONFIG_BCHP_EBI_CS_SPI_SELECT) & 0xff);
+ D("spi_xfer: tx addr: %p\n", ®s->txram[0]);
+ D("spi_xfer: rx addr: %p\n", ®s->rxram[0]);
+ D("spi_xfer: cd addr: %p\n", ®s->cdram[0]);
+
+ if (flags & SPI_XFER_END) {
+ D("spi_xfer: clearing saved din address: %p\n",
+ priv->saved_din_addr);
+ priv->saved_din_addr = NULL;
+ priv->saved_cmd_len = 0;
+ memset(priv->saved_cmd, 0, NUM_CDRAM);
+ }
+
+ if (bitlen == 0)
+ return 0;
+
+ if (bitlen % 8) {
+ printf("bcmstb_spi_xfer: Non-byte-aligned transfer\n");
+ return -EOPNOTSUPP;
+ }
+
+ if (flags & ~(SPI_XFER_BEGIN | SPI_XFER_END)) {
+ printf("bcmstb_spi_xfer: Unsupported flags: %lx\n", flags);
+ return -EOPNOTSUPP;
+ }
+
+ if (flags & SPI_XFER_BEGIN) {
+ priv->tx_slot = 0;
+ priv->rx_slot = 0;
+
+ if (out_bytes && len > NUM_CDRAM) {
+ printf("bcmstb_spi_xfer: Unable to save transfer\n");
+ return -EOPNOTSUPP;
+ }
+
+ if (out_bytes && !(flags & SPI_XFER_END)) {
+ /*
+ * This is the start of a transmit operation
+ * that will need repeating if the calling
+ * code polls for the result. Save it for
+ * subsequent transmission.
+ */
+ D("spi_xfer: saving command: %x, %d\n",
+ out_bytes[0], len);
+ priv->saved_cmd_len = len;
+ memcpy(priv->saved_cmd, out_bytes, priv->saved_cmd_len);
+ }
+ }
+
+ if (!(flags & (SPI_XFER_BEGIN | SPI_XFER_END))) {
+ if (priv->saved_din_addr == din) {
+ /*
+ * The caller is polling for status. Repeat
+ * the last transmission.
+ */
+ int code = 0;
+
+ D("spi_xfer: Making recursive call\n");
+ code = bcmstb_spi_xfer(dev, priv->saved_cmd_len * 8,
+ priv->saved_cmd, NULL,
+ SPI_XFER_BEGIN);
+ if (code) {
+ printf("bcmstb_spi_xfer:"
+ " Recursive call failed\n");
+ return code;
+ }
+ } else {
+ D("spi_xfer: saving din address: %p\n", din);
+ priv->saved_din_addr = din;
+ }
+ }
+
+ while (rx_len > 0) {
+ priv->rx_slot = priv->tx_slot;
+
+ while (priv->tx_slot < NUM_CDRAM && tx_len > 0) {
+ bcmstb_spi_hw_set_parms(priv);
+ D("WR TXRAM[%d]: %02x\n", priv->tx_slot,
+ out_bytes ? out_bytes[len - tx_len] : 0xff);
+ writel(out_bytes ? out_bytes[len - tx_len] : 0xff,
+ ®s->txram[priv->tx_slot << 1]);
+ D("WR CDRAM[%d]: %02x\n", priv->tx_slot, 0x8e);
+ writel(0x8e, ®s->cdram[priv->tx_slot]);
+ priv->tx_slot++;
+ tx_len--;
+ if (!in_bytes)
+ rx_len--;
+ }
+
+ D("spi_xfer: early return clauses: %d, %d, %d\n",
+ len <= NUM_CDRAM,
+ !in_bytes,
+ (flags & (SPI_XFER_BEGIN | SPI_XFER_END)) == SPI_XFER_BEGIN);
+ if (len <= NUM_CDRAM &&
+ !in_bytes &&
+ (flags & (SPI_XFER_BEGIN | SPI_XFER_END)) == SPI_XFER_BEGIN)
+ return 0;
+
+ bcmstb_spi_submit(priv, tx_len == 0);
+
+ if (bcmstb_spi_wait(regs) == -ETIMEDOUT) {
+ printf("bcmstb_spi_xfer: Timed out\n");
+ return -ETIMEDOUT;
+ }
+
+ priv->tx_slot %= NUM_CDRAM;
+
+ if (in_bytes) {
+ while (priv->rx_slot < NUM_CDRAM && rx_len > 0) {
+ in_bytes[len - rx_len] =
+ readl(®s->rxram[(priv->rx_slot << 1)
+ + 1])
+ & 0xff;
+ D("RD RXRAM[%d]: %02x\n",
+ priv->rx_slot, in_bytes[len - rx_len]);
+ priv->rx_slot++;
+ rx_len--;
+ }
+ }
+ }
+
+ if (flags & SPI_XFER_END) {
+ D("WR WRITE_LOCK: %02x\n", 0);
+ BDEV_WR_F_RB(HIF_MSPI_WRITE_LOCK, WRITE_LOCK, 0);
+ }
+
+ return 0;
+}
+
+static int bcmstb_spi_set_speed(struct udevice *dev, uint speed)
+{
+ return 0;
+}
+
+static int bcmstb_spi_set_mode(struct udevice *dev, uint mode)
+{
+ return 0;
+}
+
+static const struct dm_spi_ops bcmstb_spi_ops = {
+ .claim_bus = bcmstb_spi_claim_bus,
+ .release_bus = bcmstb_spi_release_bus,
+ .xfer = bcmstb_spi_xfer,
+ .set_speed = bcmstb_spi_set_speed,
+ .set_mode = bcmstb_spi_set_mode,
+};
+
+static const struct udevice_id bcmstb_spi_ids[] = {
+ { .compatible = "brcm,spi-brcmstb" },
+ { }
+};
+
+U_BOOT_DRIVER(bcmstb_spi) = {
+ .name = "bcmstb_spi",
+ .id = UCLASS_SPI,
+ .of_match = bcmstb_spi_ids,
+ .ops = &bcmstb_spi_ops,
+ .ofdata_to_platdata = bcmstb_spi_ofdata_to_platdata,
+ .probe = bcmstb_spi_probe,
+ .remove = bcmstb_spi_remove,
+ .platdata_auto_alloc_size = sizeof(struct bcmstb_spi_platdata),
+ .priv_auto_alloc_size = sizeof(struct bcmstb_spi_priv),
+ .bind = bcmstb_spi_bind,
+};
diff --git a/dts/Kconfig b/dts/Kconfig
index 0cef225..074784b 100644
--- a/dts/Kconfig
+++ b/dts/Kconfig
@@ -101,6 +101,12 @@ config OF_HOSTFILE
This is only useful for Sandbox. Use the -d flag to U-Boot to
specify the file to read.
+config OF_PRIOR_STAGE
+ bool "Prior stage bootloader DTB for DT control"
+ help
+ If this option is enabled, DTB will be read from a memory
+ location passed to U-Boot by the prior stage bootloader.
+
endchoice
config DEFAULT_DEVICE_TREE
diff --git a/include/configs/bcm7445d0.h b/include/configs/bcm7445d0.h
new file mode 100644
index 0000000..36155c7
--- /dev/null
+++ b/include/configs/bcm7445d0.h
@@ -0,0 +1,227 @@
+/*
+ * (C) Copyright 2018
+ * Cisco Systems, Inc. <www.cisco.com>
+ *
+ * Author :
+ * Thomas Fitzsimmons <fitzsim at fitzsim.org>
+ *
+ * Configuration settings for the Broadcom BCM7445D0 SoC.
+ *
+ * SPDX-License-Identifier: GPL-2.0+
+ */
+
+#ifndef __CONFIG_H
+#define __CONFIG_H
+
+#include "bcmstb.h"
+#include "version.h"
+
+/*
+ * Generic board configuration.
+ */
+#define CONFIG_SYS_GENERIC_BOARD
+
+/*
+ * CPU configuration.
+ */
+#define CONFIG_SKIP_LOWLEVEL_INIT
+
+/*
+ * Memory configuration.
+ *
+ * The prior stage BOLT bootloader sets up memory for us. An example
+ * invocation is:
+ *
+ * BOLT> boot -bsu -elf flash0.u-boot1
+ *
+ * An example boot memory layout after loading everything is:
+ *
+ * 0x0000 8000 vmlinux.bin.gz
+ * : [31 MiB uncompressed max]
+ * 0x01ef f000 FIT containing signed public key
+ * : [~2 KiB in size]
+ * 0x01f0 0000 DTB copied from prior-stage-provided region
+ * : [~1 MiB max]
+ * ~0x01ff 4000 DTB modified by U-Boot (fdt_high - DTB size)
+ * : [~40 KiB in size]
+ * 0x0200 0000 FIT containing initramfs.cpio.gz
+ * : [208 MiB uncompressed max, to CMA low address]
+ * : [80 MiB compressed max, to PSB low address]
+ * 0x0700 0000 Prior stage bootloader (PSB)
+ * :
+ * 0x0761 7000 Prior-stage-provided device tree blob (DTB)
+ * : [~40 KiB in size]
+ * 0x0f00 0000 Contiguous memory allocator (CMA) low address
+ * :
+ * 0x8010 0000 U-Boot code at ELF load address
+ * : [~500 KiB in size, stripped]
+ * 0xc000 0000 Top of RAM
+ *
+ * CONFIG_OF_PRIOR_STAGE=y prevents U-Boot from relocating itself when
+ * it is run as an ELF program by the prior stage bootloader.
+ *
+ * The maximum value for fdt_high is the lowest physical address from
+ * which stblinux's CMA driver starts allocating, which is 0x0f000000.
+ * But a good setting for fdt_high is the default load address.
+ *
+ * Relocating the prior stage DTB prevents it from being overwritten
+ * when large initramfs images are loaded. Then the upper limit for
+ * the initramfs load region becomes the CMA low address.
+ *
+ * Overwriting the prior stage bootloader causes memory instability,
+ * so the compressed initramfs needs to fit between the load address
+ * and the PSB low address. In BOLT's default configuration this
+ * limits the compressed size of the initramfs to approximately 80
+ * MiB. However, BOLT can be configured to allow loading larger
+ * initramfs images, in which case this limitation is eliminated.
+ *
+ * Newer versions of stblinux use the bmem mechanism for reserving
+ * physical regions of memory. In practice CMA/bmem values require
+ * experimentation and tuning to achieve a stable U-Boot memory layout
+ * and the desired Linux memory layout (see also
+ * BCMSTB_ACCOMMODATE_STBLINUX).
+ */
+#define CONFIG_NR_DRAM_BANKS 3
+
+#define CONFIG_SYS_SDRAM_BASE 0x00000000
+#define CONFIG_SYS_TEXT_BASE 0x80100000
+#define CONFIG_SYS_INIT_RAM_ADDR 0x80200000
+#define CONFIG_SYS_INIT_RAM_SIZE 0x100000
+#define CONFIG_SYS_INIT_SP_ADDR (CONFIG_SYS_INIT_RAM_ADDR + \
+ CONFIG_SYS_INIT_RAM_SIZE - \
+ GENERATED_GBL_DATA_SIZE)
+#define CONFIG_SYS_MALLOC_LEN ((10 * 1024) << 10) /* 10 MiB */
+#define CONFIG_SYS_LOAD_ADDR 0x2000000
+/*
+ * CONFIG_SYS_LOAD_ADDR - 1 MiB.
+ */
+#define CONFIG_SYS_FDT_SAVE_ADDRESS 0x1f00000
+#define CONFIG_SYS_CBSIZE 512
+#define CONFIG_SYS_MAXARGS 32
+
+/*
+ * Timer configuration.
+ */
+#define CONFIG_TIMER_FREQUENCY_REGISTER_ADDRESS 0xf0412020
+#define CONFIG_TIMER_LOW_REGISTER_ADDRESS 0xf0412008
+
+/*
+ * NS16550 configuration.
+ */
+#define V_NS16550_CLK 81000000
+
+#define CONFIG_SYS_NS16550
+#define CONFIG_SYS_NS16550_SERIAL
+#define CONFIG_SYS_NS16550_REG_SIZE (-4)
+#define CONFIG_SYS_NS16550_CLK V_NS16550_CLK
+
+/*
+ * Serial console configuration.
+ */
+#define CONFIG_SERIAL3 3
+/*
+ * For now, this must be a pre-defined macro, not looked up from the
+ * prior-stage-provided DTB.
+ */
+#define CONFIG_SYS_NS16550_COM3 0xf040ab00
+#define CONFIG_BAUDRATE 115200
+#define CONFIG_SYS_BAUDRATE_TABLE {4800, 9600, 19200, 38400, 57600,\
+ 115200}
+
+/*
+ * Informational display configuration.
+ */
+#define CONFIG_REVISION_TAG
+
+/*
+ * Command configuration.
+ */
+#define CONFIG_CMD_ASKENV
+#define CONFIG_CMD_CACHE
+#define CONFIG_CMD_EXT2
+#define CONFIG_CMD_SF
+#define CONFIG_CMD_SPI
+#define CONFIG_CMD_SF_TEST
+#define CONFIG_CMD_MMC
+
+/*
+ * Flattened device tree configuration.
+ */
+#define CONFIG_CMD_FDT_MAX_DUMP 256
+
+/*
+ * Flash configuration.
+ */
+#define CONFIG_ST_SMI
+#define CONFIG_BCMSTB_SPI
+#define CONFIG_SPI_FLASH_STMICRO
+#define CONFIG_SPI_FLASH_MACRONIX
+
+#define CONFIG_BCMSTB_SPI_BASE 0xf03e3400
+
+/*
+ * Copied from stblinux, include/linux/brcmstb/7445d0/bchp_hif_mspi.h.
+ */
+#define CONFIG_BCHP_HIF_MSPI_SPCR2_SPIFIE_MASK 0x00000020
+#define CONFIG_BCHP_HIF_MSPI_SPCR2_SPE_MASK 0x00000040
+#define CONFIG_BCHP_HIF_MSPI_SPCR2_CONT_AFTER_CMD_MASK 0x00000080
+#define CONFIG_BCHP_HIF_MSPI_WRITE_LOCK 0x003e3580
+#define CONFIG_BCHP_HIF_MSPI_WRITE_LOCK_WRITE_LOCK_MASK 0x00000001
+#define CONFIG_BCHP_HIF_MSPI_WRITE_LOCK_WRITE_LOCK_DEFAULT 0x00000000
+
+/*
+ * Copied from stblinux, include/linux/brcmstb/7445d0/bchp_hif_spi_intr2.h.
+ */
+#define CONFIG_BCHP_HIF_SPI_INTR2_CPU_CLEAR 0x003e1a08
+#define CONFIG_BCHP_HIF_SPI_INTR2_CPU_MASK_SET 0x003e1a10
+#define CONFIG_BCHP_HIF_SPI_INTR2_CPU_MASK_CLEAR 0x003e1a14
+#define CONFIG_BCHP_HIF_SPI_INTR2_CPU_SET_MSPI_DONE_MASK 0x00000020
+
+/*
+ * Copied from stblinux, include/linux/brcmstb/7445d0/bchp_ebi.h.
+ */
+#define CONFIG_BCHP_EBI_CS_SPI_SELECT 0x003e0920
+
+/*
+ * Copied from stblinux, include/linux/brcmstb/7445d0/bchp_bspi.h.
+ */
+#define CONFIG_BCHP_BSPI_MAST_N_BOOT_CTRL 0x003e3208
+
+/*
+ * Filesystem configuration.
+ */
+#define CONFIG_DOS_PARTITION
+#define CONFIG_CMD_EXT4
+#define CONFIG_FS_EXT4
+#define CONFIG_CMD_FS_GENERIC
+
+/*
+ * Environment configuration.
+ */
+#define CONFIG_SYS_REDUNDAND_ENVIRONMENT
+
+#define CONFIG_ENV_IS_IN_SPI_FLASH 1
+#define CONFIG_ENV_OFFSET 0x1e0000
+#define CONFIG_ENV_SIZE (64 << 10) /* 64 KiB */
+#define CONFIG_ENV_SECT_SIZE CONFIG_ENV_SIZE
+#define CONFIG_ENV_OFFSET_REDUND (CONFIG_ENV_OFFSET + CONFIG_ENV_SIZE)
+#define CONFIG_ENV_OVERWRITE
+
+#define CONFIG_PREBOOT \
+ "fdt addr ${fdtcontroladdr};" \
+ "fdt move ${fdtcontroladdr} ${fdtsaveaddr};" \
+ "fdt addr ${fdtsaveaddr};"
+#define CONFIG_EXTRA_ENV_SETTINGS \
+ "fdtsaveaddr=" __stringify(CONFIG_SYS_FDT_SAVE_ADDRESS) "\0"
+
+/*
+ * Set fdtaddr to prior stage-provided DTB in board_late_init, when
+ * writeable environment is available.
+ */
+#define CONFIG_BOARD_LATE_INIT
+
+#define CONFIG_SYS_MAX_FLASH_BANKS 1
+
+#define CONFIG_DM_SPI 1
+
+#endif /* __CONFIG_H */
diff --git a/include/configs/bcmstb.h b/include/configs/bcmstb.h
new file mode 100644
index 0000000..33d1efc
--- /dev/null
+++ b/include/configs/bcmstb.h
@@ -0,0 +1,57 @@
+/*
+ * (C) Copyright 2009
+ * Broadcom Corporation
+ *
+ * Author :
+ * Thomas Fitzsimmons <fitzsim at fitzsim.org>
+ *
+ * Macros imported from Broadcom stblinux.
+ *
+ * SPDX-License-Identifier: GPL-2.0
+ */
+
+#ifndef __BCMSTB_H
+#define __BCMSTB_H
+
+/* Copied from stblinux, include/linux/brcmstb/brcmstb.h. */
+#define DEV_RD(x) (readl((x)))
+#define DEV_WR(x, y) do { writel((y), (x)); } while (0)
+#define DEV_UNSET(x, y) do { DEV_WR((x), DEV_RD(x) & ~(y)); } while (0)
+#define DEV_SET(x, y) do { DEV_WR((x), DEV_RD(x) | (y)); } while (0)
+
+#define DEV_WR_RB(x, y) do { DEV_WR((x), (y)); DEV_RD(x); } while (0)
+#define DEV_SET_RB(x, y) do { DEV_SET((x), (y)); DEV_RD(x); } while (0)
+#define DEV_UNSET_RB(x, y) do { DEV_UNSET((x), (y)); DEV_RD(x); } while (0)
+
+/* Adjusted for U-Boot. */
+#define BRCMSTB_PERIPH_VIRT 0xf0000000
+
+#define BVIRTADDR(x) (BRCMSTB_PERIPH_VIRT + ((x) & 0x0fffffff))
+
+#define BDEV_RD(x) (DEV_RD(BVIRTADDR(x)))
+#define BDEV_WR(x, y) do { DEV_WR(BVIRTADDR(x), (y)); } while (0)
+#define BDEV_UNSET(x, y) do { BDEV_WR((x), BDEV_RD(x) & ~(y)); } while (0)
+#define BDEV_SET(x, y) do { BDEV_WR((x), BDEV_RD(x) | (y)); } while (0)
+
+#define BDEV_SET_RB(x, y) do { BDEV_SET((x), (y)); BDEV_RD(x); } while (0)
+#define BDEV_UNSET_RB(x, y) do { BDEV_UNSET((x), (y)); BDEV_RD(x); } while (0)
+#define BDEV_WR_RB(x, y) do { BDEV_WR((x), (y)); BDEV_RD(x); } while (0)
+
+#define BDEV_RD_F(reg, field) \
+ ((BDEV_RD(BCHP_##reg) & BCHP_##reg##_##field##_MASK) >> \
+ BCHP_##reg##_##field##_SHIFT)
+#define BDEV_WR_F(reg, field, val) do { \
+ BDEV_WR(BCHP_##reg, \
+ (BDEV_RD(BCHP_##reg) & ~BCHP_##reg##_##field##_MASK) | \
+ (((val) << BCHP_##reg##_##field##_SHIFT) & \
+ BCHP_##reg##_##field##_MASK)); \
+ } while (0)
+#define BDEV_WR_F_RB(reg, field, val) do { \
+ BDEV_WR(CONFIG_BCHP_##reg, \
+ (BDEV_RD(CONFIG_BCHP_##reg) & ~CONFIG_BCHP_##reg##_##field##_MASK) | \
+ (((val) << CONFIG_BCHP_##reg##_##field##_SHIFT) & \
+ CONFIG_BCHP_##reg##_##field##_MASK)); \
+ BDEV_RD(CONFIG_BCHP_##reg); \
+ } while (0)
+
+#endif /* __BCMSTB_H */
diff --git a/lib/fdtdec.c b/lib/fdtdec.c
index 320ee1d..aec12f2 100644
--- a/lib/fdtdec.c
+++ b/lib/fdtdec.c
@@ -1299,6 +1299,10 @@ __weak void *board_fdt_blob_setup(void)
}
#endif
+#if defined(CONFIG_OF_PRIOR_STAGE)
+extern phys_addr_t prior_stage_fdt_address;
+#endif
+
int fdtdec_setup(void)
{
#if CONFIG_IS_ENABLED(OF_CONTROL)
@@ -1323,8 +1327,12 @@ int fdtdec_setup(void)
# endif
# ifndef CONFIG_SPL_BUILD
/* Allow the early environment to override the fdt address */
+# if defined(CONFIG_OF_PRIOR_STAGE)
+ gd->fdt_blob = (void *)prior_stage_fdt_address;
+# else
gd->fdt_blob = (void *)env_get_ulong("fdtcontroladdr", 16,
(uintptr_t)gd->fdt_blob);
+# endif
# endif
# if CONFIG_IS_ENABLED(MULTI_DTB_FIT)
--
1.8.3.1
More information about the U-Boot
mailing list