All of lore.kernel.org
 help / color / mirror / Atom feed
* [U-Boot] [PATCH 0/1] board: arm: Add support for Broadcom BCM7445D0
@ 2018-05-06 11:09 Thomas Fitzsimmons
  2018-05-06 11:09 ` [U-Boot] [PATCH 1/1] " Thomas Fitzsimmons
  2018-05-24  1:24 ` [U-Boot] [PATCH v2 0/1] board: arm: Add support for Broadcom BCM7445 Thomas Fitzsimmons
  0 siblings, 2 replies; 37+ messages in thread
From: Thomas Fitzsimmons @ 2018-05-06 11:09 UTC (permalink / raw)
  To: u-boot

Hi,

This patch adds support for loading U-Boot on the Broadcom 7445D0 SoC,
as a third stage bootloader loaded by Broadcom's BOLT bootloader.

While this is only a partial port, it does enable some of U-Boot's
flexibility on this SoC, functionality beyond what BOLT provides.
Specifically, it brings:

   - ext4 file system traversal

   - support for loading FIT images

   - advanced scripting

   - support for FIT-provided DTBs instead of relying on the
     BOLT-provided DTB

My team at Cisco is using a customized version of this port in
production.  The same approach may work on other BCM7xxx boards, with
some configuration adjustments and memory layout experimentation.

Stefan Roese reviewed (off-list) some early revisions of these
changes.  This patch is my attempt to rebase on the current U-Boot
master branch.  I'm submitting it in case there is interest in
including this port in upstream U-Boot.

Thomas

Thomas Fitzsimmons (1):
  board: arm: Add support for Broadcom BCM7445D0

 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

-- 
1.8.3.1

^ permalink raw reply	[flat|nested] 37+ messages in thread

* [U-Boot] [PATCH 1/1] board: arm: Add support for Broadcom BCM7445D0
  2018-05-06 11:09 [U-Boot] [PATCH 0/1] board: arm: Add support for Broadcom BCM7445D0 Thomas Fitzsimmons
@ 2018-05-06 11:09 ` Thomas Fitzsimmons
  2018-05-07 23:48   ` Tom Rini
  2018-05-08 17:44   ` Florian Fainelli
  2018-05-24  1:24 ` [U-Boot] [PATCH v2 0/1] board: arm: Add support for Broadcom BCM7445 Thomas Fitzsimmons
  1 sibling, 2 replies; 37+ messages in thread
From: Thomas Fitzsimmons @ 2018-05-06 11:09 UTC (permalink / raw)
  To: u-boot

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@fitzsim.org>
Cc: Stefan Roese <sr@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@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@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@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@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@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@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@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@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(&regs->mspi_status);
+
+	while (!(status & 1)) {
+		if (get_timer(start_time) >
+		    CONFIG_SYS_BCMSTB_SPI_WAIT) {
+			return -ETIMEDOUT;
+		}
+		status = readl(&regs->mspi_status);
+	}
+
+	writel(readl(&regs->mspi_status) & ~1, &regs->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", &regs->txram[0]);
+	D("spi_xfer: rx addr: %p\n", &regs->rxram[0]);
+	D("spi_xfer: cd addr: %p\n", &regs->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,
+			       &regs->txram[priv->tx_slot << 1]);
+			D("WR CDRAM[%d]: %02x\n", priv->tx_slot, 0x8e);
+			writel(0x8e, &regs->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(&regs->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@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@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

^ permalink raw reply related	[flat|nested] 37+ messages in thread

* [U-Boot] [PATCH 1/1] board: arm: Add support for Broadcom BCM7445D0
  2018-05-06 11:09 ` [U-Boot] [PATCH 1/1] " Thomas Fitzsimmons
@ 2018-05-07 23:48   ` Tom Rini
  2018-05-24  0:47     ` Thomas Fitzsimmons
  2018-05-08 17:44   ` Florian Fainelli
  1 sibling, 1 reply; 37+ messages in thread
From: Tom Rini @ 2018-05-07 23:48 UTC (permalink / raw)
  To: u-boot

On Sun, May 06, 2018 at 07:09:22AM -0400, Thomas Fitzsimmons wrote:

> 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@fitzsim.org>
> Cc: Stefan Roese <sr@denx.de>
[snip]
> 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

Can you explain this bit a good bit more?

> +config BCHP_BSPI_MAST_N_BOOT_CTRL
> +	hex ""
> +	default 0x003e3208

Doing hex "" seems wrong.  What are you doing here exactly?

> 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

Why do we need this?

> +#ifdef DEBUG
> +static int debug_tx_rx;
> +#define D(fmt, args...) debug_cond(debug_tx_rx, fmt, ##args)
> +#else
> +#define D(fmt, args...)
> +#endif

We have dbg() etc, please use.  Thanks!

-- 
Tom
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 819 bytes
Desc: not available
URL: <http://lists.denx.de/pipermail/u-boot/attachments/20180507/632e355b/attachment.sig>

^ permalink raw reply	[flat|nested] 37+ messages in thread

* [U-Boot] [PATCH 1/1] board: arm: Add support for Broadcom BCM7445D0
  2018-05-06 11:09 ` [U-Boot] [PATCH 1/1] " Thomas Fitzsimmons
  2018-05-07 23:48   ` Tom Rini
@ 2018-05-08 17:44   ` Florian Fainelli
  2018-05-10 13:04     ` Thomas Fitzsimmons
  1 sibling, 1 reply; 37+ messages in thread
From: Florian Fainelli @ 2018-05-08 17:44 UTC (permalink / raw)
  To: u-boot

On 05/06/2018 04:09 AM, Thomas Fitzsimmons wrote:
> 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@fitzsim.org>
> Cc: Stefan Roese <sr@denx.de>

> 
> 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

BOLT

> +	  is acting as the second stage bootloader, and U-Boot is
> +	  acting as the third stage bootloader (TSBL), loaded by Bolt.

again BOLT

> +	  This port may work on other BCM7xxx boards with
> +	  configuration changes.

There are other revisions than D0, so I would just name this
TARGET_BCM7445. You would likely want to create a TARGET_BRCMSTB general
menu which would encompass all ARMv7-A based SoCs from the Broadcom
STB/CM division, and then have per-chip Kconfig options (similar to what
the older <= 3.14 STB Linux kernels did).

> +
> +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.

What STB Linux kernel did you observe this with? I am afraid this is
still true about the ranges vs. allocation even in newer kernels, but
that is kind of intented to keep the logic KISS (because it's already
too complicated IMHO).

> +
> +config BCMSTB_SDHCI
> +	bool ""
> +	default y
> +
> +config BCMSTB_SDHCI_BASE
> +	hex ""
> +	default 0xf03e0200
> +
> +config BCMSTB_SPI_BASE
> +	hex ""
> +	default 0xf03e3400

Why don't you get those from the Device Tree blob that BOLT passes?

> +
> +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

All of these physical address ares not going to change given a
7445-based design, so why not hard code them in a header file unless you
are keen on taking them from the passed Device Tree blob from BOLT?

> +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;

This may be true for your system if you have 3x1GB populated, but 7445
supports additional extension regions, so this must be configurable if
you want to make this flexible enough for other people to use it.


> +/* 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)

I would just flat out drop those macros and instead use standard
accessors. Those happen to work just fine given Broadcom STB's GISB bus,
but if you want portable drivers in u-boot, and you likely would want
those, you should use more standard I/O accessors.
-- 
Florian

^ permalink raw reply	[flat|nested] 37+ messages in thread

* [U-Boot] [PATCH 1/1] board: arm: Add support for Broadcom BCM7445D0
  2018-05-08 17:44   ` Florian Fainelli
@ 2018-05-10 13:04     ` Thomas Fitzsimmons
  2018-05-10 17:43       ` Florian Fainelli
  0 siblings, 1 reply; 37+ messages in thread
From: Thomas Fitzsimmons @ 2018-05-10 13:04 UTC (permalink / raw)
  To: u-boot

Florian Fainelli <f.fainelli@gmail.com> writes:

> On 05/06/2018 04:09 AM, Thomas Fitzsimmons wrote:
>> 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@fitzsim.org>
>> Cc: Stefan Roese <sr@denx.de>
>
>> 
>> 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
>
> BOLT
>
>> +	  is acting as the second stage bootloader, and U-Boot is
>> +	  acting as the third stage bootloader (TSBL), loaded by Bolt.
>
> again BOLT

Oops, will fix in a v2 patch.

>> +	  This port may work on other BCM7xxx boards with
>> +	  configuration changes.
>
> There are other revisions than D0, so I would just name this
> TARGET_BCM7445. You would likely want to create a TARGET_BRCMSTB general
> menu which would encompass all ARMv7-A based SoCs from the Broadcom
> STB/CM division, and then have per-chip Kconfig options (similar to what
> the older <= 3.14 STB Linux kernels did).

OK, will try this in v2.

>> +
>> +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.
>
> What STB Linux kernel did you observe this with? I am afraid this is
> still true about the ranges vs. allocation even in newer kernels, but
> that is kind of intented to keep the logic KISS (because it's already
> too complicated IMHO).

I investigated the allocation discrepancy and wrote the workaround while
we were still using stblinux-3.14.  Since then we've updated to
stblinux-4.1 and I've left the workaround enabled, but I haven't
investigated its interactions with the newer bmem mechanism.  I should
probably revisit this though, with stblinux-4.1 and stblinux-4.9, just
to make sure this macro is still useful.

>> +
>> +config BCMSTB_SDHCI
>> +	bool ""
>> +	default y
>> +
>> +config BCMSTB_SDHCI_BASE
>> +	hex ""
>> +	default 0xf03e0200
>> +
>> +config BCMSTB_SPI_BASE
>> +	hex ""
>> +	default 0xf03e3400
>
> Why don't you get those from the Device Tree blob that BOLT passes?

During development I did implement that for SDHCI_BASE, so it is
possible.  But I ended up #ifdef'ing it out and hard-coding the address
in production, to keep the runtime logic simpler.  Doing DTB traversal
in code adds complexity but it may achieve portability to different
BCM7xxx SoCs without further code changes, which would be nice.

>> +
>> +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
>
> All of these physical address ares not going to change given a
> 7445-based design, so why not hard code them in a header file unless you
> are keen on taking them from the passed Device Tree blob from BOLT?

Agreed, a header file or BOLT DTB lookup for these values would be
better.  I think for a v2 of the patch, I'll move these to a header
file.  If I get to adding another BCM7xxx board (I'm looking at BCM7260
right now) then I can revisit BOLT DTB lookups in the context of
portability between the two SoCs.

>> +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;
>
> This may be true for your system if you have 3x1GB populated, but 7445
> supports additional extension regions, so this must be configurable if
> you want to make this flexible enough for other people to use it.

OK, I'm not familiar with extension regions.  Would it be enough to size
and initialize bi_dram based on different CONFIG_NR_DRAM_BANKS values?

>> +/* 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)
>
> I would just flat out drop those macros and instead use standard
> accessors. Those happen to work just fine given Broadcom STB's GISB bus,
> but if you want portable drivers in u-boot, and you likely would want
> those, you should use more standard I/O accessors.

OK, I'll look into this.

Thanks for reviewing,
Thomas

^ permalink raw reply	[flat|nested] 37+ messages in thread

* [U-Boot] [PATCH 1/1] board: arm: Add support for Broadcom BCM7445D0
  2018-05-10 13:04     ` Thomas Fitzsimmons
@ 2018-05-10 17:43       ` Florian Fainelli
  2018-06-06 20:39         ` Thomas Fitzsimmons
  0 siblings, 1 reply; 37+ messages in thread
From: Florian Fainelli @ 2018-05-10 17:43 UTC (permalink / raw)
  To: u-boot

On 05/10/2018 06:04 AM, Thomas Fitzsimmons wrote:
> Florian Fainelli <f.fainelli@gmail.com> writes:
> 
>> On 05/06/2018 04:09 AM, Thomas Fitzsimmons wrote:
>>> 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@fitzsim.org>
>>> Cc: Stefan Roese <sr@denx.de>
>>
>>>
>>> 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
>>
>> BOLT
>>
>>> +	  is acting as the second stage bootloader, and U-Boot is
>>> +	  acting as the third stage bootloader (TSBL), loaded by Bolt.
>>
>> again BOLT
> 
> Oops, will fix in a v2 patch.
> 
>>> +	  This port may work on other BCM7xxx boards with
>>> +	  configuration changes.
>>
>> There are other revisions than D0, so I would just name this
>> TARGET_BCM7445. You would likely want to create a TARGET_BRCMSTB general
>> menu which would encompass all ARMv7-A based SoCs from the Broadcom
>> STB/CM division, and then have per-chip Kconfig options (similar to what
>> the older <= 3.14 STB Linux kernels did).
> 
> OK, will try this in v2.
> 
>>> +
>>> +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.
>>
>> What STB Linux kernel did you observe this with? I am afraid this is
>> still true about the ranges vs. allocation even in newer kernels, but
>> that is kind of intented to keep the logic KISS (because it's already
>> too complicated IMHO).
> 
> I investigated the allocation discrepancy and wrote the workaround while
> we were still using stblinux-3.14.  Since then we've updated to
> stblinux-4.1 and I've left the workaround enabled, but I haven't
> investigated its interactions with the newer bmem mechanism.  I should
> probably revisit this though, with stblinux-4.1 and stblinux-4.9, just
> to make sure this macro is still useful.

Sounds good, let me know if there is something that does not seem quite
right, we could fix it.

> 
>>> +
>>> +config BCMSTB_SDHCI
>>> +	bool ""
>>> +	default y
>>> +
>>> +config BCMSTB_SDHCI_BASE
>>> +	hex ""
>>> +	default 0xf03e0200
>>> +
>>> +config BCMSTB_SPI_BASE
>>> +	hex ""
>>> +	default 0xf03e3400
>>
>> Why don't you get those from the Device Tree blob that BOLT passes?
> 
> During development I did implement that for SDHCI_BASE, so it is
> possible.  But I ended up #ifdef'ing it out and hard-coding the address
> in production, to keep the runtime logic simpler.  Doing DTB traversal
> in code adds complexity but it may achieve portability to different
> BCM7xxx SoCs without further code changes, which would be nice.

Given what I see with Broadcom STB customers, I don't think there is a
strong push for anything other than BOLT, or another proprietary TSBL,
so with that, I am not sure about whether there would be an use case for
e.g; a single u-boot binary that would run on more than a flavor of a
given SoC. I would be inclined to put the different base register
addresses into a header file and use those constants in the respective
drivers (or even better, in the part of code that does register those).

> 
>>> +
>>> +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
>>
>> All of these physical address ares not going to change given a
>> 7445-based design, so why not hard code them in a header file unless you
>> are keen on taking them from the passed Device Tree blob from BOLT?
> 
> Agreed, a header file or BOLT DTB lookup for these values would be
> better.  I think for a v2 of the patch, I'll move these to a header
> file.  If I get to adding another BCM7xxx board (I'm looking at BCM7260
> right now) then I can revisit BOLT DTB lookups in the context of
> portability between the two SoCs.

Sounds good.

> 
>>> +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;
>>
>> This may be true for your system if you have 3x1GB populated, but 7445
>> supports additional extension regions, so this must be configurable if
>> you want to make this flexible enough for other people to use it.
> 
> OK, I'm not familiar with extension regions.  Would it be enough to size
> and initialize bi_dram based on different CONFIG_NR_DRAM_BANKS values?

Humm, sure that would be a good step forward. This is something that
might be best extracted from the Device Tree provided by BOLT because
there is a standard memory node's "reg" property being provided.

A possible challenge with u-boot's bi_dram structure is that the
extension regions are way above the 4GB PA boundary. As long as you
don't need to access those in u-boot, you should be fine with a
"standard setup" (short page table descriptors etc.).
-- 
Florian

^ permalink raw reply	[flat|nested] 37+ messages in thread

* [U-Boot] [PATCH 1/1] board: arm: Add support for Broadcom BCM7445D0
  2018-05-07 23:48   ` Tom Rini
@ 2018-05-24  0:47     ` Thomas Fitzsimmons
  0 siblings, 0 replies; 37+ messages in thread
From: Thomas Fitzsimmons @ 2018-05-24  0:47 UTC (permalink / raw)
  To: u-boot

Tom Rini <trini@konsulko.com> writes:

> On Sun, May 06, 2018 at 07:09:22AM -0400, Thomas Fitzsimmons wrote:
>
>> 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@fitzsim.org>
>> Cc: Stefan Roese <sr@denx.de>
> [snip]
>> 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
>
> Can you explain this bit a good bit more?

When BOLT loads U-Boot as an ELF program, this relocation code hangs --
I haven't found out why yet -- but if I skip the relocation, U-Boot runs
successfully.  I figured out a different approach to preventing the
relocation, one that only requires logic in an SoC-specific file, so v2
of the patch will not have any crt0.S changes.

>> +config BCHP_BSPI_MAST_N_BOOT_CTRL
>> +	hex ""
>> +	default 0x003e3208
>
> Doing hex "" seems wrong.  What are you doing here exactly?

I've reorganized all these into more appropriate locations, and
documented all the remaining Kconfig items, which you'll see in the v2
patch I'll post shortly.

>> 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
>
> Why do we need this?

The background is that stblinux is designed to use some physical memory
for Linux itself, and leave the rest of physical memory for direct use
by video decode blocks in the SoC.

Basically, without making accommodations for it in U-Boot, stblinux will
allocate less memory for use by the video decode blocks than is actually
available, even if it could safely allocate more.

In v2 of the patch, I've documented a different approach to loading FIT
images (one that keeps the RFS and DTB in-place), which eliminates the
need for this configuration macro.

>> +#ifdef DEBUG
>> +static int debug_tx_rx;
>> +#define D(fmt, args...) debug_cond(debug_tx_rx, fmt, ##args)
>> +#else
>> +#define D(fmt, args...)
>> +#endif
>
> We have dbg() etc, please use.  Thanks!

OK, done in v2 of the patch.

Thanks for reviewing,
Thomas

^ permalink raw reply	[flat|nested] 37+ messages in thread

* [U-Boot] [PATCH v2 0/1] board: arm: Add support for Broadcom BCM7445
  2018-05-06 11:09 [U-Boot] [PATCH 0/1] board: arm: Add support for Broadcom BCM7445D0 Thomas Fitzsimmons
  2018-05-06 11:09 ` [U-Boot] [PATCH 1/1] " Thomas Fitzsimmons
@ 2018-05-24  1:24 ` Thomas Fitzsimmons
  2018-05-24  1:24   ` [U-Boot] [PATCH v2 1/1] " Thomas Fitzsimmons
                     ` (2 more replies)
  1 sibling, 3 replies; 37+ messages in thread
From: Thomas Fitzsimmons @ 2018-05-24  1:24 UTC (permalink / raw)
  To: u-boot

Add support for Broadcom BCM7445

Changes for v2:
   - Reorganize Kconfig to create ARCH_BCMSTB
   - Use generic bcmstb SoC name wherever possible
   - Eliminate crt0.S changes by moving relocation logic to bcmstb.c
   - Use debug() macro where appropriate
   - Read bcmstb_spi register base addresses from prior stage device
     tree, where possible
   - Read bcmstb_sdhci register base address from prior stage DT
   - Make timer register addresses configurable
   - Fix BOLT typos
   - Eliminate CONFIG_BCMSTB_ACCOMMODATE_STBLINUX by keeping FIT
     initramfs and device tree binary in-place
   - Add README.bcm7xxx
   - Read memory configuration from prior stage device tree
   - Add CONFIG_OF_PRIOR_STAGE support in spi-uclass.c
   - Fix issues reported by checkpatch.pl
   - Fix issues reported by sparse
   - Update some comments and formatting
   - Add a MAINTAINERS file

Thomas Fitzsimmons (1):
  board: arm: Add support for Broadcom BCM7445

 arch/arm/Kconfig                                |  12 +
 arch/arm/Makefile                               |   1 +
 arch/arm/mach-bcmstb/Kconfig                    |  64 ++++
 arch/arm/mach-bcmstb/Makefile                   |   9 +
 arch/arm/mach-bcmstb/include/mach/gpio.h        |  12 +
 arch/arm/mach-bcmstb/include/mach/hardware.h    |  12 +
 arch/arm/mach-bcmstb/include/mach/prior_stage.h |  31 ++
 arch/arm/mach-bcmstb/include/mach/sdhci.h       |  16 +
 arch/arm/mach-bcmstb/include/mach/timer.h       |  14 +
 arch/arm/mach-bcmstb/lowlevel_init.S            |  22 ++
 board/broadcom/bcmstb/MAINTAINERS               |   6 +
 board/broadcom/bcmstb/Makefile                  |   9 +
 board/broadcom/bcmstb/bcmstb.c                  | 192 +++++++++++
 configs/bcm7445_defconfig                       |  27 ++
 doc/README.bcm7xxx                              | 147 ++++++++
 drivers/mmc/Kconfig                             |  11 +
 drivers/mmc/Makefile                            |   1 +
 drivers/mmc/bcmstb_sdhci.c                      |  68 ++++
 drivers/spi/Kconfig                             |   7 +
 drivers/spi/Makefile                            |   1 +
 drivers/spi/bcmstb_spi.c                        | 440 ++++++++++++++++++++++++
 drivers/spi/spi-uclass.c                        |   2 +-
 dts/Kconfig                                     |   7 +
 include/configs/bcmstb.h                        | 189 ++++++++++
 include/fdtdec.h                                |   4 +
 lib/fdtdec.c                                    |   4 +
 26 files changed, 1307 insertions(+), 1 deletion(-)
 create mode 100644 arch/arm/mach-bcmstb/Kconfig
 create mode 100644 arch/arm/mach-bcmstb/Makefile
 create mode 100644 arch/arm/mach-bcmstb/include/mach/gpio.h
 create mode 100644 arch/arm/mach-bcmstb/include/mach/hardware.h
 create mode 100644 arch/arm/mach-bcmstb/include/mach/prior_stage.h
 create mode 100644 arch/arm/mach-bcmstb/include/mach/sdhci.h
 create mode 100644 arch/arm/mach-bcmstb/include/mach/timer.h
 create mode 100644 arch/arm/mach-bcmstb/lowlevel_init.S
 create mode 100644 board/broadcom/bcmstb/MAINTAINERS
 create mode 100644 board/broadcom/bcmstb/Makefile
 create mode 100644 board/broadcom/bcmstb/bcmstb.c
 create mode 100644 configs/bcm7445_defconfig
 create mode 100644 doc/README.bcm7xxx
 create mode 100644 drivers/mmc/bcmstb_sdhci.c
 create mode 100644 drivers/spi/bcmstb_spi.c
 create mode 100644 include/configs/bcmstb.h

-- 
1.8.3.1

^ permalink raw reply	[flat|nested] 37+ messages in thread

* [U-Boot] [PATCH v2 1/1] board: arm: Add support for Broadcom BCM7445
  2018-05-24  1:24 ` [U-Boot] [PATCH v2 0/1] board: arm: Add support for Broadcom BCM7445 Thomas Fitzsimmons
@ 2018-05-24  1:24   ` Thomas Fitzsimmons
  2018-06-06 11:16     ` [U-Boot] [U-Boot, v2, " Tom Rini
  2018-06-06 18:35   ` [U-Boot] [PATCH v3 0/1] " Thomas Fitzsimmons
  2019-08-26 15:50   ` [U-Boot] [PATCH v2 0/1] board: arm: Add support for Broadcom BCM7445 Bin Meng
  2 siblings, 1 reply; 37+ messages in thread
From: Thomas Fitzsimmons @ 2018-05-24  1:24 UTC (permalink / raw)
  To: u-boot

Add support for loading U-Boot on the Broadcom 7445 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@fitzsim.org>
Cc: Stefan Roese <sr@denx.de>
Cc: Tom Rini <trini@konsulko.com>
Cc: Florian Fainelli <f.fainelli@gmail.com>
---
Changes for v2:
   - Reorganize Kconfig to create ARCH_BCMSTB
   - Use generic bcmstb SoC name wherever possible
   - Eliminate crt0.S changes by moving relocation logic to bcmstb.c
   - Use debug() macro where appropriate
   - Read bcmstb_spi register base addresses from prior stage device
     tree, where possible
   - Read bcmstb_sdhci register base address from prior stage DT
   - Make timer register addresses configurable
   - Fix BOLT typos
   - Eliminate CONFIG_BCMSTB_ACCOMMODATE_STBLINUX by keeping FIT
     initramfs and device tree binary in-place
   - Add README.bcm7xxx
   - Read memory configuration from prior stage device tree
   - Add CONFIG_OF_PRIOR_STAGE support in spi-uclass.c
   - Fix issues reported by checkpatch.pl
   - Fix issues reported by sparse
   - Update some comments and formatting
   - Add a MAINTAINERS file

 arch/arm/Kconfig                                |  12 +
 arch/arm/Makefile                               |   1 +
 arch/arm/mach-bcmstb/Kconfig                    |  64 ++++
 arch/arm/mach-bcmstb/Makefile                   |   9 +
 arch/arm/mach-bcmstb/include/mach/gpio.h        |  12 +
 arch/arm/mach-bcmstb/include/mach/hardware.h    |  12 +
 arch/arm/mach-bcmstb/include/mach/prior_stage.h |  31 ++
 arch/arm/mach-bcmstb/include/mach/sdhci.h       |  16 +
 arch/arm/mach-bcmstb/include/mach/timer.h       |  14 +
 arch/arm/mach-bcmstb/lowlevel_init.S            |  22 ++
 board/broadcom/bcmstb/MAINTAINERS               |   6 +
 board/broadcom/bcmstb/Makefile                  |   9 +
 board/broadcom/bcmstb/bcmstb.c                  | 192 +++++++++++
 configs/bcm7445_defconfig                       |  27 ++
 doc/README.bcm7xxx                              | 147 ++++++++
 drivers/mmc/Kconfig                             |  11 +
 drivers/mmc/Makefile                            |   1 +
 drivers/mmc/bcmstb_sdhci.c                      |  68 ++++
 drivers/spi/Kconfig                             |   7 +
 drivers/spi/Makefile                            |   1 +
 drivers/spi/bcmstb_spi.c                        | 440 ++++++++++++++++++++++++
 drivers/spi/spi-uclass.c                        |   2 +-
 dts/Kconfig                                     |   7 +
 include/configs/bcmstb.h                        | 189 ++++++++++
 include/fdtdec.h                                |   4 +
 lib/fdtdec.c                                    |   4 +
 26 files changed, 1307 insertions(+), 1 deletion(-)
 create mode 100644 arch/arm/mach-bcmstb/Kconfig
 create mode 100644 arch/arm/mach-bcmstb/Makefile
 create mode 100644 arch/arm/mach-bcmstb/include/mach/gpio.h
 create mode 100644 arch/arm/mach-bcmstb/include/mach/hardware.h
 create mode 100644 arch/arm/mach-bcmstb/include/mach/prior_stage.h
 create mode 100644 arch/arm/mach-bcmstb/include/mach/sdhci.h
 create mode 100644 arch/arm/mach-bcmstb/include/mach/timer.h
 create mode 100644 arch/arm/mach-bcmstb/lowlevel_init.S
 create mode 100644 board/broadcom/bcmstb/MAINTAINERS
 create mode 100644 board/broadcom/bcmstb/Makefile
 create mode 100644 board/broadcom/bcmstb/bcmstb.c
 create mode 100644 configs/bcm7445_defconfig
 create mode 100644 doc/README.bcm7xxx
 create mode 100644 drivers/mmc/bcmstb_sdhci.c
 create mode 100644 drivers/spi/bcmstb_spi.c
 create mode 100644 include/configs/bcmstb.h

diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig
index 9bd70f4..fa3089f 100644
--- a/arch/arm/Kconfig
+++ b/arch/arm/Kconfig
@@ -498,6 +498,16 @@ config TARGET_VEXPRESS_CA15_TC2
 	select CPU_V7_HAS_VIRT
 	select PL011_SERIAL
 
+config ARCH_BCMSTB
+	bool "Broadcom BCM7XXX family"
+	select CPU_V7
+	select DM
+	select OF_CONTROL
+	select OF_PRIOR_STAGE
+	help
+	  This enables support for Broadcom ARM-based set-top box
+	  chipsets, including the 7445 family of chips.
+
 config TARGET_VEXPRESS_CA5X2
 	bool "Support vexpress_ca5x2"
 	select CPU_V7
@@ -1237,6 +1247,8 @@ source "arch/arm/mach-at91/Kconfig"
 
 source "arch/arm/mach-bcm283x/Kconfig"
 
+source "arch/arm/mach-bcmstb/Kconfig"
+
 source "arch/arm/mach-davinci/Kconfig"
 
 source "arch/arm/mach-exynos/Kconfig"
diff --git a/arch/arm/Makefile b/arch/arm/Makefile
index 4fa8b38..b0cd152 100644
--- a/arch/arm/Makefile
+++ b/arch/arm/Makefile
@@ -53,6 +53,7 @@ PLATFORM_CPPFLAGS += $(arch-y) $(tune-y)
 machine-$(CONFIG_ARCH_ASPEED)		+= aspeed
 machine-$(CONFIG_ARCH_AT91)		+= at91
 machine-$(CONFIG_ARCH_BCM283X)		+= bcm283x
+machine-$(CONFIG_ARCH_BCMSTB)		+= bcmstb
 machine-$(CONFIG_ARCH_DAVINCI)		+= davinci
 machine-$(CONFIG_ARCH_EXYNOS)		+= exynos
 machine-$(CONFIG_ARCH_HIGHBANK)		+= highbank
diff --git a/arch/arm/mach-bcmstb/Kconfig b/arch/arm/mach-bcmstb/Kconfig
new file mode 100644
index 0000000..0c9dcda
--- /dev/null
+++ b/arch/arm/mach-bcmstb/Kconfig
@@ -0,0 +1,64 @@
+if ARCH_BCMSTB
+
+config TARGET_BCM7445
+	bool "Broadcom 7445 TSBL"
+	depends on ARCH_BCMSTB
+	help
+	  Support for the Broadcom 7445 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 SYS_CPU
+	default "armv7"
+
+config SYS_BOARD
+	default "bcmstb"
+
+config SYS_VENDOR
+	default "broadcom"
+
+config SYS_SOC
+	default "bcmstb"
+
+config SYS_CONFIG_NAME
+	default "bcmstb"
+
+config SYS_FDT_SAVE_ADDRESS
+	hex "Address to which the prior stage provided DTB will be copied"
+	default 0x1f00000
+
+config BCMSTB_SDHCI_INDEX
+	int "Index of preferred BCMSTB SDHCI alias in DTB"
+	default 1
+
+config BCMSTB_SDHCI_BASE
+	hex "Physical base address of the BCMSTB SDHCI controller"
+	default 0xf03e0200
+
+config BCMSTB_TIMER_LOW
+	hex "Address of BCMSTB timer low register"
+	default 0xf0412008
+
+config BCMSTB_TIMER_FREQUENCY
+	hex "Address of BCMSTB timer frequency register"
+	default 0xf0412020
+
+config BCMSTB_HIF_MSPI_BASE
+	hex "BCMSTB SPI hif_mspi base address"
+	default 0xf03e3400
+
+config BCMSTB_BSPI_BASE
+	hex "BCMSTB SPI bspi base address"
+	default 0xf03e3200
+
+config BCMSTB_HIF_SPI_INTR2
+	hex "BCMSTB SPI hif_spi_intr2 base address"
+	default 0xf03e1a00
+
+config BCMSTB_CS_REG
+	hex "BCMSTB SPI cs_reg address"
+	default 0xf03e0920
+
+endif
diff --git a/arch/arm/mach-bcmstb/Makefile b/arch/arm/mach-bcmstb/Makefile
new file mode 100644
index 0000000..2c5da6b
--- /dev/null
+++ b/arch/arm/mach-bcmstb/Makefile
@@ -0,0 +1,9 @@
+#
+# (C) Copyright 2018  Cisco Systems, Inc.
+#
+# Author: Thomas Fitzsimmons <fitzsim@fitzsim.org>
+#
+# SPDX-License-Identifier:	GPL-2.0+
+#
+
+obj-y	:= lowlevel_init.o
diff --git a/arch/arm/mach-bcmstb/include/mach/gpio.h b/arch/arm/mach-bcmstb/include/mach/gpio.h
new file mode 100644
index 0000000..a1d0d3b
--- /dev/null
+++ b/arch/arm/mach-bcmstb/include/mach/gpio.h
@@ -0,0 +1,12 @@
+/*
+ * (C) Copyright 2018  Cisco Systems, Inc.
+ *
+ * Author: Thomas Fitzsimmons <fitzsim@fitzsim.org>
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+#ifndef _BCMSTB_GPIO_H
+#define _BCMSTB_GPIO_H
+
+#endif /* _BCMSTB_GPIO_H */
diff --git a/arch/arm/mach-bcmstb/include/mach/hardware.h b/arch/arm/mach-bcmstb/include/mach/hardware.h
new file mode 100644
index 0000000..6b0bbbd
--- /dev/null
+++ b/arch/arm/mach-bcmstb/include/mach/hardware.h
@@ -0,0 +1,12 @@
+/*
+ * (C) Copyright 2018  Cisco Systems, Inc.
+ *
+ * Author: Thomas Fitzsimmons <fitzsim@fitzsim.org>
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+#ifndef _BCMSTB_HARDWARE_H
+#define _BCMSTB_HARDWARE_H
+
+#endif /* _BCMSTB_HARDWARE_H */
diff --git a/arch/arm/mach-bcmstb/include/mach/prior_stage.h b/arch/arm/mach-bcmstb/include/mach/prior_stage.h
new file mode 100644
index 0000000..4fa10b0
--- /dev/null
+++ b/arch/arm/mach-bcmstb/include/mach/prior_stage.h
@@ -0,0 +1,31 @@
+/*
+ * (C) Copyright 2018  Cisco Systems, Inc.
+ *
+ * Author: Thomas Fitzsimmons <fitzsim@fitzsim.org>
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+#ifndef _BCMSTB_PRIOR_STAGE_H
+#define _BCMSTB_PRIOR_STAGE_H
+
+#ifndef __ASSEMBLY__
+
+#include <linux/types.h>
+
+struct bcmstb_boot_parameters {
+	u32 r0;
+	u32 r1;
+	u32 r2;
+	u32 r3;
+	u32 sp;
+	u32 lr;
+};
+
+extern struct bcmstb_boot_parameters bcmstb_boot_parameters;
+
+extern phys_addr_t prior_stage_fdt_address;
+
+#endif /* __ASSEMBLY__ */
+
+#endif /* _BCMSTB_PRIOR_STAGE_H */
diff --git a/arch/arm/mach-bcmstb/include/mach/sdhci.h b/arch/arm/mach-bcmstb/include/mach/sdhci.h
new file mode 100644
index 0000000..f3af388
--- /dev/null
+++ b/arch/arm/mach-bcmstb/include/mach/sdhci.h
@@ -0,0 +1,16 @@
+/*
+ * (C) Copyright 2018  Cisco Systems, Inc.
+ *
+ * Author: Thomas Fitzsimmons <fitzsim@fitzsim.org>
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+#ifndef _BCMSTB_SDHCI_H
+#define _BCMSTB_SDHCI_H
+
+#include <linux/types.h>
+
+int bcmstb_sdhci_init(phys_addr_t regbase);
+
+#endif /* _BCMSTB_SDHCI_H */
diff --git a/arch/arm/mach-bcmstb/include/mach/timer.h b/arch/arm/mach-bcmstb/include/mach/timer.h
new file mode 100644
index 0000000..ca125a4
--- /dev/null
+++ b/arch/arm/mach-bcmstb/include/mach/timer.h
@@ -0,0 +1,14 @@
+/*
+ * (C) Copyright 2018  Cisco Systems, Inc.
+ *
+ * Author: Thomas Fitzsimmons <fitzsim@fitzsim.org>
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+#ifndef _BCMSTB_TIMER_H
+#define _BCMSTB_TIMER_H
+
+unsigned long timer_read_counter(void);
+
+#endif /* _BCMSTB_TIMER_H */
diff --git a/arch/arm/mach-bcmstb/lowlevel_init.S b/arch/arm/mach-bcmstb/lowlevel_init.S
new file mode 100644
index 0000000..1eaac87
--- /dev/null
+++ b/arch/arm/mach-bcmstb/lowlevel_init.S
@@ -0,0 +1,22 @@
+/*
+ * (C) Copyright 2018  Cisco Systems, Inc.
+ *
+ * Author: Thomas Fitzsimmons <fitzsim@fitzsim.org>
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+#include <linux/linkage.h>
+
+ENTRY(save_boot_params)
+	ldr	r6, =bcmstb_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/board/broadcom/bcmstb/MAINTAINERS b/board/broadcom/bcmstb/MAINTAINERS
new file mode 100644
index 0000000..5e23ecd
--- /dev/null
+++ b/board/broadcom/bcmstb/MAINTAINERS
@@ -0,0 +1,6 @@
+BCM7445 BOARD
+M:	Thomas Fitzsimmons <fitzsim@fitzsim.org>
+S:	Maintained
+F:	board/broadcom/bcmstb/
+F:	include/configs/bcmstb.h
+F:	configs/bcm7445_defconfig
diff --git a/board/broadcom/bcmstb/Makefile b/board/broadcom/bcmstb/Makefile
new file mode 100644
index 0000000..4f03293
--- /dev/null
+++ b/board/broadcom/bcmstb/Makefile
@@ -0,0 +1,9 @@
+#
+# (C) Copyright 2018  Cisco Systems, Inc.
+#
+# Author: Thomas Fitzsimmons <fitzsim@fitzsim.org>
+#
+# SPDX-License-Identifier:	GPL-2.0+
+#
+
+obj-y	:= bcmstb.o
diff --git a/board/broadcom/bcmstb/bcmstb.c b/board/broadcom/bcmstb/bcmstb.c
new file mode 100644
index 0000000..f38478e
--- /dev/null
+++ b/board/broadcom/bcmstb/bcmstb.c
@@ -0,0 +1,192 @@
+/*
+ * (C) Copyright 2018  Cisco Systems, Inc.
+ *
+ * Author: Thomas Fitzsimmons <fitzsim@fitzsim.org>
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+#include <linux/types.h>
+#include <common.h>
+#include <asm/io.h>
+#include <asm/bootm.h>
+#include <mach/sdhci.h>
+#include <mach/timer.h>
+#include <mmc.h>
+#include <fdtdec.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+#define BCMSTB_DATA_SECTION __attribute__((section(".data")))
+
+struct bcmstb_boot_parameters bcmstb_boot_parameters BCMSTB_DATA_SECTION;
+
+phys_addr_t prior_stage_fdt_address BCMSTB_DATA_SECTION;
+
+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)
+{
+	if (fdtdec_setup_memory_size() != 0)
+		return -EINVAL;
+
+	return 0;
+}
+
+int dram_init_banksize(void)
+{
+	fdtdec_setup_memory_banksize();
+
+	/*
+	 * On this SoC, U-Boot is running as an ELF file.  Change the
+	 * relocation address to CONFIG_SYS_TEXT_BASE, so that in
+	 * setup_reloc, gd->reloc_off works out to 0, effectively
+	 * disabling relocation.  Otherwise U-Boot hangs in the setup
+	 * instructions just before relocate_code in
+	 * arch/arm/lib/crt0.S.
+	 */
+	gd->relocaddr = CONFIG_SYS_TEXT_BASE;
+
+	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.
+	 */
+}
+
+static const phys_addr_t bcmstb_sdhci_address(u32 alias_index)
+{
+	int node = 0;
+	int ret = 0;
+	char sdhci[16] = { 0 };
+	const void *fdt = gd->fdt_blob;
+	const char *path = NULL;
+	struct fdt_resource resource = { 0 };
+
+	if (!fdt) {
+		printf("%s: Invalid gd->fdt_blob\n", __func__);
+		return 0;
+	}
+
+	node = fdt_path_offset(fdt, "/aliases");
+	if (node < 0) {
+		printf("%s: Failed to find /aliases node\n", __func__);
+		return 0;
+	}
+
+	sprintf(sdhci, "sdhci%d", alias_index);
+	path = fdt_getprop(fdt, node, sdhci, NULL);
+	if (!path) {
+		printf("%s: Failed to find alias for %s\n", __func__, sdhci);
+		return 0;
+	}
+
+	node = fdt_path_offset(fdt, path);
+	if (node < 0) {
+		printf("%s: Failed to resolve BCMSTB SDHCI alias\n", __func__);
+		return 0;
+	}
+
+	ret = fdt_get_named_resource(fdt, node, "reg", "reg-names",
+				     "host", &resource);
+	if (ret) {
+		printf("%s: Failed to read BCMSTB SDHCI host resource\n",
+		       __func__);
+		return 0;
+	}
+
+	return resource.start;
+}
+
+int board_mmc_init(bd_t *bis)
+{
+	phys_addr_t sdhci_base_address = 0;
+
+	sdhci_base_address = bcmstb_sdhci_address(CONFIG_BCMSTB_SDHCI_INDEX);
+
+	if (!sdhci_base_address) {
+		sdhci_base_address = CONFIG_BCMSTB_SDHCI_BASE;
+		printf("%s: Assuming BCMSTB SDHCI address: 0x%p\n",
+		       __func__, (void *)sdhci_base_address);
+	}
+
+	debug("BCMSTB SDHCI base address: 0x%p\n", (void *)sdhci_base_address);
+
+	bcmstb_sdhci_init(sdhci_base_address);
+
+	return 0;
+}
+
+int timer_init(void)
+{
+	gd->arch.timer_rate_hz = readl(CONFIG_BCMSTB_TIMER_FREQUENCY);
+
+	return 0;
+}
+
+ulong get_tbclk(void)
+{
+	return gd->arch.timer_rate_hz;
+}
+
+unsigned long timer_read_counter(void)
+{
+	return readl(CONFIG_BCMSTB_TIMER_LOW);
+}
+
+int board_late_init(void)
+{
+	debug("Arguments from prior stage bootloader:\n");
+	debug("General Purpose Register 0: 0x%x\n", bcmstb_boot_parameters.r0);
+	debug("General Purpose Register 1: 0x%x\n", bcmstb_boot_parameters.r1);
+	debug("General Purpose Register 2: 0x%x\n", bcmstb_boot_parameters.r2);
+	debug("General Purpose Register 3: 0x%x\n", bcmstb_boot_parameters.r3);
+	debug("Stack Pointer Register:     0x%x\n", bcmstb_boot_parameters.sp);
+	debug("Link Register:              0x%x\n", bcmstb_boot_parameters.lr);
+	debug("Assuming timer frequency register at: 0x%p\n",
+	      (void *)CONFIG_BCMSTB_TIMER_FREQUENCY);
+	debug("Read timer frequency (in Hz): %ld\n", gd->arch.timer_rate_hz);
+	debug("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 (bcmstb_boot_parameters.r1)
+	 * because we're using a device tree to boot Linux.
+	 */
+
+	return 0;
+}
diff --git a/configs/bcm7445_defconfig b/configs/bcm7445_defconfig
new file mode 100644
index 0000000..46dea17
--- /dev/null
+++ b/configs/bcm7445_defconfig
@@ -0,0 +1,27 @@
+CONFIG_ARM=y
+CONFIG_ARCH_BCMSTB=y
+CONFIG_TARGET_BCM7445=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_BCMSTB_SPI=y
+CONFIG_FIT=y
+CONFIG_FIT_SIGNATURE=y
+CONFIG_RSA=y
+CONFIG_BLK=n
+CONFIG_SDHCI=y
+CONFIG_MMC_SDHCI=y
+CONFIG_MMC_SDHCI_BCMSTB=y
+CONFIG_CONS_INDEX=3
+CONFIG_BOOTDELAY=1
+CONFIG_SYS_PROMPT="U-Boot>"
+CONFIG_HUSH_PARSER=y
+CONFIG_SYS_TEXT_BASE=0x80100000
+CONFIG_SYS_NS16550_COM3=0xf040ab00
+CONFIG_EFI_LOADER=n
diff --git a/doc/README.bcm7xxx b/doc/README.bcm7xxx
new file mode 100644
index 0000000..0545d0b
--- /dev/null
+++ b/doc/README.bcm7xxx
@@ -0,0 +1,147 @@
+Summary
+=======
+
+This document describes how to use U-Boot on the Broadcom 7445 SoC, as
+a third stage bootloader loaded by Broadcom's BOLT bootloader.
+
+BOLT loads U-Boot as a generic ELF binary.  Some U-Boot features such
+as networking are not yet available but other important features are,
+including:
+
+   - ext4 file system traversal
+
+   - support for loading FIT images
+
+   - advanced scripting
+
+   - support for FIT-provided DTBs instead of relying on the
+     BOLT-provided DTB
+
+A customized version of this port has been used in production.  The
+same approach may work on other BCM7xxx boards, with some
+configuration adjustments and memory layout experimentation.
+
+Build
+=====
+
+make bcm7445_defconfig
+make
+${CROSS_COMPILE}strip u-boot
+
+Run
+===
+
+Flash the u-boot binary into board storage, then invoke it from BOLT.
+For example:
+
+BOLT> boot -bsu -elf flash0.u-boot1
+
+Flattened Image Tree Support
+============================
+
+What follows is an example FIT image source file.  Build it with:
+
+mkimage -f image.its image.itb
+
+Booting the resulting image.itb was tested on BOLT v1.20, with the
+following kernels:
+
+https://github.com/Broadcom/stblinux-3.14
+https://github.com/Broadcom/stblinux-4.1
+https://github.com/Broadcom/stblinux-4.9
+
+and with a generic ARMv7 root file system.
+
+image.its:
+/dts-v1/;
+/ {
+	description = "BCM7445 FIT";
+	images {
+		kernel at 1 {
+			description = "Linux kernel";
+			/*
+			 * This kernel image output format can be
+			 * generated with:
+			 *
+			 * make vmlinux
+			 * ${CROSS_COMPILE}objcopy -O binary -S vmlinux vmlinux.bin
+			 * gzip -9 vmlinux.bin
+			 *
+			 * For stblinux-3.14, the specific Broadcom
+			 * board type should be configured in the
+			 * kernel, for example CONFIG_BCM7445D0=y.
+			 */
+			data = /incbin/("<vmlinux.bin.gz>");
+			type = "kernel";
+			arch = "arm";
+			os = "linux";
+			compression = "gzip";
+			load = <0x8000>;
+			entry = <0x8000>;
+			hash at 1 {
+				algo = "sha256";
+			};
+		};
+		ramdisk at 1 {
+			description = "Initramfs root file system";
+			data = /incbin/("<initramfs.cpio.gz>");
+			type = "ramdisk";
+			arch = "arm";
+			os = "linux";
+			compression = "gzip";
+			/*
+			 * Set the environment variable initrd_high to
+			 * 0xffffffff, and set "load" and "entry" here
+			 * to 0x0 to keep initramfs in-place and to
+			 * accommodate stblinux bmem/CMA reservations.
+			 */
+			load = <0x0>;
+			entry = <0x0>;
+			hash at 1 {
+				algo = "sha256";
+			};
+		};
+		fdt at 1 {
+			description = "Device tree dumped from BOLT";
+			/*
+			 * This DTB should be similar to the
+			 * BOLT-generated device tree, after BOLT has
+			 * done its runtime modifications to it.  For
+			 * example, it can be dumped from within
+			 * U-Boot (at ${fdtcontroladdr}), after BOLT
+			 * has loaded U-Boot.  The result can be added
+			 * to the Linux source tree as a .dts file.
+			 *
+			 * To support modifications to the device tree
+			 * in-place in U-Boot, add to Linux's
+			 * arch/arm/boot/dts/Makefile:
+			 *
+			 * DTC_FLAGS ?= -p 4096
+			 *
+			 * This will leave some padding in the DTB and
+			 * thus reserve room for node additions.
+			 *
+			 * Also, set the environment variable fdt_high
+			 * to 0xffffffff to keep the DTB in-place and
+			 * to accommodate stblinux bmem/CMA
+			 * reservations.
+			 */
+			data = /incbin/("<bolt-<version>.dtb");
+			type = "flat_dt";
+			arch = "arm";
+			compression = "none";
+			hash at 1 {
+				algo = "sha256";
+			};
+		};
+	};
+	configurations {
+		default = "conf at bcm7445";
+		conf at bcm7445 {
+			description = "BCM7445 configuration";
+			kernel = "kernel at 1";
+			ramdisk = "ramdisk at 1";
+			fdt = "fdt at 1";
+		};
+	};
+};
diff --git a/drivers/mmc/Kconfig b/drivers/mmc/Kconfig
index 4fa8dd8..c734d18 100644
--- a/drivers/mmc/Kconfig
+++ b/drivers/mmc/Kconfig
@@ -364,6 +364,17 @@ config MMC_SDHCI_BCM2835
 
 	  If unsure, say N.
 
+config MMC_SDHCI_BCMSTB
+	tristate "SDHCI support for the BCMSTB SD/MMC Controller"
+	depends on MMC_SDHCI
+	help
+	  This selects the Broadcom set-top box SD/MMC controller.
+
+	  If you have a BCMSTB platform with SD or MMC devices,
+	  say Y here.
+
+	  If unsure, say N.
+
 config MMC_SDHCI_CADENCE
 	bool "SDHCI support for the Cadence SD/SDIO/eMMC controller"
 	depends on BLK && DM_MMC
diff --git a/drivers/mmc/Makefile b/drivers/mmc/Makefile
index cf46c33..14d5ef4 100644
--- a/drivers/mmc/Makefile
+++ b/drivers/mmc/Makefile
@@ -47,6 +47,7 @@ obj-$(CONFIG_STM32_SDMMC2) += stm32_sdmmc2.o
 obj-$(CONFIG_MMC_SDHCI)			+= sdhci.o
 obj-$(CONFIG_MMC_SDHCI_ATMEL)		+= atmel_sdhci.o
 obj-$(CONFIG_MMC_SDHCI_BCM2835)		+= bcm2835_sdhci.o
+obj-$(CONFIG_MMC_SDHCI_BCMSTB)		+= bcmstb_sdhci.o
 obj-$(CONFIG_MMC_SDHCI_CADENCE)		+= sdhci-cadence.o
 obj-$(CONFIG_MMC_SDHCI_KONA)		+= kona_sdhci.o
 obj-$(CONFIG_MMC_SDHCI_MSM)		+= msm_sdhci.o
diff --git a/drivers/mmc/bcmstb_sdhci.c b/drivers/mmc/bcmstb_sdhci.c
new file mode 100644
index 0000000..16cd1aa
--- /dev/null
+++ b/drivers/mmc/bcmstb_sdhci.c
@@ -0,0 +1,68 @@
+/*
+ * (C) Copyright 2018  Cisco Systems, Inc.
+ *
+ * Author: Thomas Fitzsimmons <fitzsim@fitzsim.org>
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+#include <common.h>
+#include <mach/sdhci.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("%s: Failed to allocate memory\n", __func__);
+		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..e5dccfc 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 "BCMSTB 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..2ca0a06
--- /dev/null
+++ b/drivers/spi/bcmstb_spi.c
@@ -0,0 +1,440 @@
+/*
+ * (C) Copyright 2018  Cisco Systems, Inc.
+ *
+ * Author: Thomas Fitzsimmons <fitzsim@fitzsim.org>
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+#include <asm/io.h>
+#include <command.h>
+#include <config.h>
+#include <dm.h>
+#include <errno.h>
+#include <fdtdec.h>
+#include <linux/bitops.h>
+#include <linux/delay.h>
+#include <log.h>
+#include <malloc.h>
+#include <spi.h>
+#include <time.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
+
+/* hif_mspi register structure. */
+struct bcmstb_hif_mspi_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 */
+	u32 write_lock;		/* 0x180 */
+};
+
+/* hif_mspi masks. */
+#define HIF_MSPI_SPCR2_CONT_AFTER_CMD_MASK	0x00000080
+#define HIF_MSPI_SPCR2_SPE_MASK			0x00000040
+#define HIF_MSPI_SPCR2_SPIFIE_MASK		0x00000020
+#define HIF_MSPI_WRITE_LOCK_WRITE_LOCK_MASK	0x00000001
+
+/* bspi offsets. */
+#define BSPI_MAST_N_BOOT_CTRL			0x008
+
+/* bspi_raf is not used in this driver. */
+
+/* hif_spi_intr2 offsets and masks. */
+#define HIF_SPI_INTR2_CPU_CLEAR			0x08
+#define HIF_SPI_INTR2_CPU_MASK_SET		0x10
+#define HIF_SPI_INTR2_CPU_MASK_CLEAR		0x14
+#define HIF_SPI_INTR2_CPU_SET_MSPI_DONE_MASK	0x00000020
+
+/* SPI transfer timeout in milliseconds. */
+#define HIF_MSPI_WAIT				10
+
+enum bcmstb_base_type {
+	HIF_MSPI,
+	BSPI,
+	HIF_SPI_INTR2,
+	CS_REG,
+	BASE_LAST,
+};
+
+struct bcmstb_spi_platdata {
+	void *base[4];
+};
+
+struct bcmstb_spi_priv {
+	struct bcmstb_hif_mspi_regs *regs;
+	void *bspi;
+	void *hif_spi_intr2;
+	void *cs_reg;
+	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;
+};
+
+static int bcmstb_spi_ofdata_to_platdata(struct udevice *bus)
+{
+	struct bcmstb_spi_platdata *plat = dev_get_platdata(bus);
+	const void *fdt = gd->fdt_blob;
+	int node = dev_of_offset(bus);
+	int ret = 0;
+	int i = 0;
+	struct fdt_resource resource = { 0 };
+	char *names[BASE_LAST] = { "hif_mspi", "bspi", "hif_spi_intr2",
+				   "cs_reg" };
+	const phys_addr_t defaults[BASE_LAST] = { CONFIG_BCMSTB_HIF_MSPI_BASE,
+						  CONFIG_BCMSTB_BSPI_BASE,
+						  CONFIG_BCMSTB_HIF_SPI_INTR2,
+						  CONFIG_BCMSTB_CS_REG };
+
+	for (i = 0; i < BASE_LAST; i++) {
+		plat->base[i] = (void *)defaults[i];
+
+		ret = fdt_get_named_resource(fdt, node, "reg", "reg-names",
+					     names[i], &resource);
+		if (ret) {
+			printf("%s: Assuming BCMSTB SPI %s address 0x0x%p\n",
+			       __func__, names[i], (void *)defaults[i]);
+		} else {
+			plat->base[i] = (void *)resource.start;
+			debug("BCMSTB SPI %s address: 0x0x%p\n",
+			      names[i], (void *)plat->base[i]);
+		}
+	}
+
+	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(void *base, u32 mask)
+{
+	void *reg = base + HIF_SPI_INTR2_CPU_MASK_CLEAR;
+
+	writel(readl(reg) | mask, reg);
+	readl(reg);
+}
+
+static void bcmstb_spi_disable_interrupt(void *base, u32 mask)
+{
+	void *reg = base + HIF_SPI_INTR2_CPU_MASK_SET;
+
+	writel(readl(reg) | mask, reg);
+	readl(reg);
+}
+
+static void bcmstb_spi_clear_interrupt(void *base, u32 mask)
+{
+	void *reg = base + HIF_SPI_INTR2_CPU_CLEAR;
+
+	writel(readl(reg) | mask, reg);
+	readl(reg);
+}
+
+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->base[HIF_MSPI];
+	priv->bspi = plat->base[BSPI];
+	priv->hif_spi_intr2 = plat->base[HIF_SPI_INTR2];
+	priv->cs_reg = plat->base[CS_REG];
+	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;
+
+	debug("spi_xfer: tx regs: 0x%p\n", &priv->regs->txram[0]);
+	debug("spi_xfer: rx regs: 0x%p\n", &priv->regs->rxram[0]);
+
+	/* Disable BSPI. */
+	writel(1, priv->bspi + BSPI_MAST_N_BOOT_CTRL);
+	readl(priv->bspi + BSPI_MAST_N_BOOT_CTRL);
+
+	/* Set up interrupts. */
+	bcmstb_spi_disable_interrupt(priv->hif_spi_intr2, 0xffffffff);
+	bcmstb_spi_clear_interrupt(priv->hif_spi_intr2, 0xffffffff);
+	bcmstb_spi_enable_interrupt(priv->hif_spi_intr2,
+				    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(HIF_MSPI_SPCR2_SPIFIE_MASK, &priv->regs->spcr2);
+	writel(0, &priv->regs->spcr3);
+
+	bcmstb_spi_hw_set_parms(priv);
+
+	return 0;
+}
+
+static void bcmstb_spi_submit(struct bcmstb_spi_priv *priv, bool done)
+{
+	debug("WR NEWQP: %d\n", 0);
+	writel(0, &priv->regs->newqp);
+
+	debug("WR ENDQP: %d\n", priv->tx_slot - 1);
+	writel(priv->tx_slot - 1, &priv->regs->endqp);
+
+	if (done) {
+		debug("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) {
+		debug("spi_xfer: switching chip select to %d\n",
+		      priv->default_cs);
+		writel((readl(priv->cs_reg) & ~0xff) | (1 << priv->default_cs),
+		       priv->cs_reg);
+		readl(priv->cs_reg);
+		udelay(10);
+		priv->curr_cs = priv->default_cs;
+	}
+
+	debug("WR WRITE_LOCK: %02x\n", 1);
+	writel((readl(&priv->regs->write_lock) &
+		~HIF_MSPI_WRITE_LOCK_WRITE_LOCK_MASK) | 1,
+	       &priv->regs->write_lock);
+	readl(&priv->regs->write_lock);
+
+	debug("WR SPCR2: %02x\n",
+	      HIF_MSPI_SPCR2_SPIFIE_MASK |
+	      HIF_MSPI_SPCR2_SPE_MASK |
+	      HIF_MSPI_SPCR2_CONT_AFTER_CMD_MASK);
+	writel(HIF_MSPI_SPCR2_SPIFIE_MASK |
+	       HIF_MSPI_SPCR2_SPE_MASK |
+	       HIF_MSPI_SPCR2_CONT_AFTER_CMD_MASK,
+	       &priv->regs->spcr2);
+}
+
+static int bcmstb_spi_wait(struct bcmstb_spi_priv *priv)
+{
+	u32 start_time = get_timer(0);
+	u32 status = readl(&priv->regs->mspi_status);
+
+	while (!(status & 1)) {
+		if (get_timer(start_time) > HIF_MSPI_WAIT)
+			return -ETIMEDOUT;
+		status = readl(&priv->regs->mspi_status);
+	}
+
+	writel(readl(&priv->regs->mspi_status) & ~1, &priv->regs->mspi_status);
+	bcmstb_spi_clear_interrupt(priv->hif_spi_intr2,
+				   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_hif_mspi_regs *regs = priv->regs;
+
+	debug("spi_xfer: %d, t: 0x%p, r: 0x%p, f: %lx\n",
+	      len, dout, din, flags);
+	debug("spi_xfer: chip select: %x\n", readl(priv->cs_reg) & 0xff);
+	debug("spi_xfer: tx addr: 0x%p\n", &regs->txram[0]);
+	debug("spi_xfer: rx addr: 0x%p\n", &regs->rxram[0]);
+	debug("spi_xfer: cd addr: 0x%p\n", &regs->cdram[0]);
+
+	if (flags & SPI_XFER_END) {
+		debug("spi_xfer: clearing saved din address: 0x%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("%s: Non-byte-aligned transfer\n", __func__);
+		return -EOPNOTSUPP;
+	}
+
+	if (flags & ~(SPI_XFER_BEGIN | SPI_XFER_END)) {
+		printf("%s: Unsupported flags: %lx\n", __func__, flags);
+		return -EOPNOTSUPP;
+	}
+
+	if (flags & SPI_XFER_BEGIN) {
+		priv->tx_slot = 0;
+		priv->rx_slot = 0;
+
+		if (out_bytes && len > NUM_CDRAM) {
+			printf("%s: Unable to save transfer\n", __func__);
+			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.
+			 */
+			debug("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 ret = 0;
+
+			debug("spi_xfer: Making recursive call\n");
+			ret = bcmstb_spi_xfer(dev, priv->saved_cmd_len * 8,
+					      priv->saved_cmd, NULL,
+					      SPI_XFER_BEGIN);
+			if (ret) {
+				printf("%s: Recursive call failed\n", __func__);
+				return ret;
+			}
+		} else {
+			debug("spi_xfer: saving din address: 0x%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);
+			debug("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,
+			       &regs->txram[priv->tx_slot << 1]);
+			debug("WR CDRAM[%d]: %02x\n", priv->tx_slot, 0x8e);
+			writel(0x8e, &regs->cdram[priv->tx_slot]);
+			priv->tx_slot++;
+			tx_len--;
+			if (!in_bytes)
+				rx_len--;
+		}
+
+		debug("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(priv) == -ETIMEDOUT) {
+			printf("%s: Timed out\n", __func__);
+			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(&regs->rxram[(priv->rx_slot << 1)
+							   + 1])
+					& 0xff;
+				debug("RD RXRAM[%d]: %02x\n",
+				      priv->rx_slot, in_bytes[len - rx_len]);
+				priv->rx_slot++;
+				rx_len--;
+			}
+		}
+	}
+
+	if (flags & SPI_XFER_END) {
+		debug("WR WRITE_LOCK: %02x\n", 0);
+		writel((readl(&priv->regs->write_lock) &
+			~HIF_MSPI_WRITE_LOCK_WRITE_LOCK_MASK) | 0,
+		       &priv->regs->write_lock);
+		readl(&priv->regs->write_lock);
+	}
+
+	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 = {
+	.xfer		= bcmstb_spi_xfer,
+	.set_speed	= bcmstb_spi_set_speed,
+	.set_mode	= bcmstb_spi_set_mode,
+};
+
+static const struct udevice_id bcmstb_spi_id[] = {
+	{ .compatible = "brcm,spi-brcmstb" },
+	{ }
+};
+
+U_BOOT_DRIVER(bcmstb_spi) = {
+	.name				= "bcmstb_spi",
+	.id				= UCLASS_SPI,
+	.of_match			= bcmstb_spi_id,
+	.ops				= &bcmstb_spi_ops,
+	.ofdata_to_platdata		= bcmstb_spi_ofdata_to_platdata,
+	.probe				= bcmstb_spi_probe,
+	.platdata_auto_alloc_size	= sizeof(struct bcmstb_spi_platdata),
+	.priv_auto_alloc_size		= sizeof(struct bcmstb_spi_priv),
+};
diff --git a/drivers/spi/spi-uclass.c b/drivers/spi/spi-uclass.c
index 15d90a5..ebb50aa 100644
--- a/drivers/spi/spi-uclass.c
+++ b/drivers/spi/spi-uclass.c
@@ -274,7 +274,7 @@ int spi_get_bus_and_cs(int busnum, int cs, int speed, int mode,
 	bool created = false;
 	int ret;
 
-#if CONFIG_IS_ENABLED(OF_PLATDATA)
+#if CONFIG_IS_ENABLED(OF_PLATDATA) || CONFIG_IS_ENABLED(OF_PRIOR_STAGE)
 	ret = uclass_first_device_err(UCLASS_SPI, &bus);
 #else
 	ret = uclass_get_device_by_seq(UCLASS_SPI, busnum, &bus);
diff --git a/dts/Kconfig b/dts/Kconfig
index 0cef225..a1a92f2 100644
--- a/dts/Kconfig
+++ b/dts/Kconfig
@@ -101,6 +101,13 @@ 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, the device tree used for DT
+	  control will be read from a device tree binary, at a memory
+	  location passed to U-Boot by the prior stage bootloader.
+
 endchoice
 
 config DEFAULT_DEVICE_TREE
diff --git a/include/configs/bcmstb.h b/include/configs/bcmstb.h
new file mode 100644
index 0000000..12aabf1
--- /dev/null
+++ b/include/configs/bcmstb.h
@@ -0,0 +1,189 @@
+/*
+ * (C) Copyright 2018  Cisco Systems, Inc.
+ *
+ * Author: Thomas Fitzsimmons <fitzsim@fitzsim.org>
+ *
+ * Configuration settings for the Broadcom BCM7445 SoC family.
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+#ifndef __CONFIG_H
+#define __CONFIG_H
+
+#include "version.h"
+#include <linux/sizes.h>
+#include <asm/arch/prior_stage.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 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]
+ *	 0x0200 0000	FIT containing ramdisk and device tree
+ *             :	  initramfs.cpio.gz
+ *	       :	  [~208 MiB uncompressed max, to CMA/bmem low address]
+ *	       :	  [~80 MiB compressed max, to PSB low address]
+ *             :	  device tree binary
+ *             :	  [~60 KiB]
+ *	 0x0700 0000	Prior stage bootloader (PSB)
+ *	       :
+ *	 0x0761 7000	Prior-stage-provided device tree binary (DTB)
+ *	       :	[~40 KiB in size]
+ *	 0x0f00 0000	Contiguous memory allocator (CMA/bmem) low address
+ *	       :
+ *	 0x8010 0000	U-Boot code at ELF load address
+ *	       :	[~500 KiB in size, stripped]
+ *	 0xc000 0000	Top of RAM
+ *
+ * Setting gd->relocaddr to CONFIG_SYS_TEXT_BASE in dram_init_banksize
+ * prevents U-Boot from relocating itself when it is run as an ELF
+ * program by the prior stage bootloader.
+ *
+ * We want to keep the ramdisk and FDT in the FIT image in-place, to
+ * accommodate stblinux's bmem and CMA regions.  To accomplish this,
+ * we set initrd_high and fdt_high to 0xffffffff, and the load and
+ * entry addresses of the FIT ramdisk entry to 0x0.
+ *
+ * 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.
+ */
+#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
+
+/*
+ * Large kernel image bootm configuration.
+ */
+#define CONFIG_SYS_BOOTM_LEN		SZ_64M
+
+/*
+ * 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
+
+/*
+ * Flash configuration.
+ */
+#define CONFIG_ST_SMI
+#define CONFIG_SPI_FLASH_STMICRO
+#define CONFIG_SPI_FLASH_MACRONIX
+
+/*
+ * 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
+
+/*
+ * Save the prior stage provided DTB.
+ */
+#define CONFIG_PREBOOT					\
+	"fdt addr ${fdtcontroladdr};"			\
+	"fdt move ${fdtcontroladdr} ${fdtsaveaddr};"	\
+	"fdt addr ${fdtsaveaddr};"
+/*
+ * Enable in-place RFS with this initrd_high setting.
+ */
+#define CONFIG_EXTRA_ENV_SETTINGS					\
+	"fdtsaveaddr=" __stringify(CONFIG_SYS_FDT_SAVE_ADDRESS) "\0"	\
+	"initrd_high=0xffffffff\0"					\
+	"fdt_high=0xffffffff\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/fdtdec.h b/include/fdtdec.h
index 2941a2e..84753e3 100644
--- a/include/fdtdec.h
+++ b/include/fdtdec.h
@@ -47,6 +47,10 @@ struct fdt_memory {
 #define SPL_BUILD	0
 #endif
 
+#if CONFIG_IS_ENABLED(OF_PRIOR_STAGE)
+extern phys_addr_t prior_stage_fdt_address;
+#endif
+
 /*
  * Information about a resource. start is the first address of the resource
  * and end is the last address (inclusive). The length of the resource will
diff --git a/lib/fdtdec.c b/lib/fdtdec.c
index 320ee1d..5473a2d 100644
--- a/lib/fdtdec.c
+++ b/lib/fdtdec.c
@@ -1323,8 +1323,12 @@ int fdtdec_setup(void)
 # endif
 # ifndef CONFIG_SPL_BUILD
 	/* Allow the early environment to override the fdt address */
+#  if CONFIG_IS_ENABLED(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

^ permalink raw reply related	[flat|nested] 37+ messages in thread

* [U-Boot] [U-Boot, v2, 1/1] board: arm: Add support for Broadcom BCM7445
  2018-05-24  1:24   ` [U-Boot] [PATCH v2 1/1] " Thomas Fitzsimmons
@ 2018-06-06 11:16     ` Tom Rini
  2018-06-06 19:32       ` Thomas Fitzsimmons
  0 siblings, 1 reply; 37+ messages in thread
From: Tom Rini @ 2018-06-06 11:16 UTC (permalink / raw)
  To: u-boot

On Wed, May 23, 2018 at 09:24:03PM -0400, Thomas Fitzsimmons wrote:

> Add support for loading U-Boot on the Broadcom 7445 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@fitzsim.org>
> Cc: Stefan Roese <sr@denx.de>
> Cc: Tom Rini <trini@konsulko.com>
> Cc: Florian Fainelli <f.fainelli@gmail.com>

Please rebase this to master.  While I can fixup the SPDX tags (and some
formatting issues from checkpatch.pl) I also run in to:
+(bcm7445) In file included from ../arch/arm/include/asm/system.h:6:0,
+(bcm7445)                  from ../arch/arm/include/asm/cache.h:11,
+(bcm7445)                  from ../include/net.h:15,
+(bcm7445)                  from ../include/common.h:519,
+(bcm7445)                  from ../lib/asm-offsets.c:14:
+(bcm7445) ../arch/arm/include/asm/barriers.h:32:24: error: operator '>=' has no left operand
+(bcm7445)  #if __LINUX_ARM_ARCH__ >= 7
+(bcm7445)                         ^~
+(bcm7445) ../arch/arm/include/asm/barriers.h:36:26: error: operator '==' has no left operand
+(bcm7445)  #elif __LINUX_ARM_ARCH__ == 6
+(bcm7445)                           ^~
+(bcm7445) make[2]: *** [.././Kbuild:44: lib/asm-offsets.s] Error 1
+(bcm7445) make[1]: *** [Makefile:1433: prepare0] Error 2

Please look into, thanks!

-- 
Tom
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 819 bytes
Desc: not available
URL: <http://lists.denx.de/pipermail/u-boot/attachments/20180606/5c2df8be/attachment.sig>

^ permalink raw reply	[flat|nested] 37+ messages in thread

* [U-Boot] [PATCH v3 0/1] board: arm: Add support for Broadcom BCM7445
  2018-05-24  1:24 ` [U-Boot] [PATCH v2 0/1] board: arm: Add support for Broadcom BCM7445 Thomas Fitzsimmons
  2018-05-24  1:24   ` [U-Boot] [PATCH v2 1/1] " Thomas Fitzsimmons
@ 2018-06-06 18:35   ` Thomas Fitzsimmons
  2018-06-06 18:35     ` [U-Boot] [PATCH v3 1/1] " Thomas Fitzsimmons
  2018-06-08 21:59     ` [U-Boot] [PATCH v4 0/1] " Thomas Fitzsimmons
  2019-08-26 15:50   ` [U-Boot] [PATCH v2 0/1] board: arm: Add support for Broadcom BCM7445 Bin Meng
  2 siblings, 2 replies; 37+ messages in thread
From: Thomas Fitzsimmons @ 2018-06-06 18:35 UTC (permalink / raw)
  To: u-boot

Add support for Broadcom BCM7445

Changes for v3:
   - Rebase to master
   - Add "ARM BROADCOM BCMSTB" entry to top-level MAINTAINERS
   - Fix SPDX formatting
   - In Kconfig use CPU_V7A, not CPU_V7, per acf15001...

Thomas Fitzsimmons (1):
  board: arm: Add support for Broadcom BCM7445

 MAINTAINERS                                     |  10 +
 arch/arm/Kconfig                                |  12 +
 arch/arm/Makefile                               |   1 +
 arch/arm/mach-bcmstb/Kconfig                    |  64 ++++
 arch/arm/mach-bcmstb/Makefile                   |   8 +
 arch/arm/mach-bcmstb/include/mach/gpio.h        |  11 +
 arch/arm/mach-bcmstb/include/mach/hardware.h    |  11 +
 arch/arm/mach-bcmstb/include/mach/prior_stage.h |  30 ++
 arch/arm/mach-bcmstb/include/mach/sdhci.h       |  15 +
 arch/arm/mach-bcmstb/include/mach/timer.h       |  13 +
 arch/arm/mach-bcmstb/lowlevel_init.S            |  21 ++
 board/broadcom/bcmstb/MAINTAINERS               |   6 +
 board/broadcom/bcmstb/Makefile                  |   8 +
 board/broadcom/bcmstb/bcmstb.c                  | 191 +++++++++++
 configs/bcm7445_defconfig                       |  27 ++
 doc/README.bcm7xxx                              | 147 ++++++++
 drivers/mmc/Kconfig                             |  11 +
 drivers/mmc/Makefile                            |   1 +
 drivers/mmc/bcmstb_sdhci.c                      |  67 ++++
 drivers/spi/Kconfig                             |   7 +
 drivers/spi/Makefile                            |   1 +
 drivers/spi/bcmstb_spi.c                        | 439 ++++++++++++++++++++++++
 drivers/spi/spi-uclass.c                        |   2 +-
 dts/Kconfig                                     |   7 +
 include/configs/bcmstb.h                        | 188 ++++++++++
 include/fdtdec.h                                |   4 +
 lib/fdtdec.c                                    |   4 +
 27 files changed, 1305 insertions(+), 1 deletion(-)
 create mode 100644 arch/arm/mach-bcmstb/Kconfig
 create mode 100644 arch/arm/mach-bcmstb/Makefile
 create mode 100644 arch/arm/mach-bcmstb/include/mach/gpio.h
 create mode 100644 arch/arm/mach-bcmstb/include/mach/hardware.h
 create mode 100644 arch/arm/mach-bcmstb/include/mach/prior_stage.h
 create mode 100644 arch/arm/mach-bcmstb/include/mach/sdhci.h
 create mode 100644 arch/arm/mach-bcmstb/include/mach/timer.h
 create mode 100644 arch/arm/mach-bcmstb/lowlevel_init.S
 create mode 100644 board/broadcom/bcmstb/MAINTAINERS
 create mode 100644 board/broadcom/bcmstb/Makefile
 create mode 100644 board/broadcom/bcmstb/bcmstb.c
 create mode 100644 configs/bcm7445_defconfig
 create mode 100644 doc/README.bcm7xxx
 create mode 100644 drivers/mmc/bcmstb_sdhci.c
 create mode 100644 drivers/spi/bcmstb_spi.c
 create mode 100644 include/configs/bcmstb.h

-- 
1.8.3.1

^ permalink raw reply	[flat|nested] 37+ messages in thread

* [U-Boot] [PATCH v3 1/1] board: arm: Add support for Broadcom BCM7445
  2018-06-06 18:35   ` [U-Boot] [PATCH v3 0/1] " Thomas Fitzsimmons
@ 2018-06-06 18:35     ` Thomas Fitzsimmons
  2018-06-07 16:54       ` Florian Fainelli
  2018-06-08 21:59     ` [U-Boot] [PATCH v4 0/1] " Thomas Fitzsimmons
  1 sibling, 1 reply; 37+ messages in thread
From: Thomas Fitzsimmons @ 2018-06-06 18:35 UTC (permalink / raw)
  To: u-boot

Add support for loading U-Boot on the Broadcom 7445 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@fitzsim.org>
Cc: Stefan Roese <sr@denx.de>
Cc: Tom Rini <trini@konsulko.com>
Cc: Florian Fainelli <f.fainelli@gmail.com>
---
Changes for v3:
   - Rebase to master
   - Add "ARM BROADCOM BCMSTB" entry to top-level MAINTAINERS
   - Fix SPDX formatting
   - In Kconfig use CPU_V7A, not CPU_V7, per acf15001...

 MAINTAINERS                                     |  10 +
 arch/arm/Kconfig                                |  12 +
 arch/arm/Makefile                               |   1 +
 arch/arm/mach-bcmstb/Kconfig                    |  64 ++++
 arch/arm/mach-bcmstb/Makefile                   |   8 +
 arch/arm/mach-bcmstb/include/mach/gpio.h        |  11 +
 arch/arm/mach-bcmstb/include/mach/hardware.h    |  11 +
 arch/arm/mach-bcmstb/include/mach/prior_stage.h |  30 ++
 arch/arm/mach-bcmstb/include/mach/sdhci.h       |  15 +
 arch/arm/mach-bcmstb/include/mach/timer.h       |  13 +
 arch/arm/mach-bcmstb/lowlevel_init.S            |  21 ++
 board/broadcom/bcmstb/MAINTAINERS               |   6 +
 board/broadcom/bcmstb/Makefile                  |   8 +
 board/broadcom/bcmstb/bcmstb.c                  | 191 +++++++++++
 configs/bcm7445_defconfig                       |  27 ++
 doc/README.bcm7xxx                              | 147 ++++++++
 drivers/mmc/Kconfig                             |  11 +
 drivers/mmc/Makefile                            |   1 +
 drivers/mmc/bcmstb_sdhci.c                      |  67 ++++
 drivers/spi/Kconfig                             |   7 +
 drivers/spi/Makefile                            |   1 +
 drivers/spi/bcmstb_spi.c                        | 439 ++++++++++++++++++++++++
 drivers/spi/spi-uclass.c                        |   2 +-
 dts/Kconfig                                     |   7 +
 include/configs/bcmstb.h                        | 188 ++++++++++
 include/fdtdec.h                                |   4 +
 lib/fdtdec.c                                    |   4 +
 27 files changed, 1305 insertions(+), 1 deletion(-)
 create mode 100644 arch/arm/mach-bcmstb/Kconfig
 create mode 100644 arch/arm/mach-bcmstb/Makefile
 create mode 100644 arch/arm/mach-bcmstb/include/mach/gpio.h
 create mode 100644 arch/arm/mach-bcmstb/include/mach/hardware.h
 create mode 100644 arch/arm/mach-bcmstb/include/mach/prior_stage.h
 create mode 100644 arch/arm/mach-bcmstb/include/mach/sdhci.h
 create mode 100644 arch/arm/mach-bcmstb/include/mach/timer.h
 create mode 100644 arch/arm/mach-bcmstb/lowlevel_init.S
 create mode 100644 board/broadcom/bcmstb/MAINTAINERS
 create mode 100644 board/broadcom/bcmstb/Makefile
 create mode 100644 board/broadcom/bcmstb/bcmstb.c
 create mode 100644 configs/bcm7445_defconfig
 create mode 100644 doc/README.bcm7xxx
 create mode 100644 drivers/mmc/bcmstb_sdhci.c
 create mode 100644 drivers/spi/bcmstb_spi.c
 create mode 100644 include/configs/bcmstb.h

diff --git a/MAINTAINERS b/MAINTAINERS
index 642c448..58634fc 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -107,6 +107,16 @@ F:	drivers/video/bcm2835.c
 F:	include/dm/platform_data/serial_bcm283x_mu.h
 F:	drivers/pinctrl/broadcom/
 
+ARM BROADCOM BCMSTB
+M:	Thomas Fitzsimmons <fitzsim@fitzsim.org>
+S:	Maintained
+F:	arch/arm/mach-bcmstb/
+F:	board/broadcom/bcmstb/
+F:	configs/bcm7445_defconfig
+F:	doc/README.bcm7xxx
+F:	drivers/mmc/bcmstb_sdhci.c
+F:	drivers/spi/bcmstb_spi.c
+
 ARM FREESCALE IMX
 M:	Stefano Babic <sbabic@denx.de>
 M:	Fabio Estevam <fabio.estevam@nxp.com>
diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig
index dde422b..fa2001b 100644
--- a/arch/arm/Kconfig
+++ b/arch/arm/Kconfig
@@ -533,6 +533,16 @@ config TARGET_VEXPRESS_CA15_TC2
 	select CPU_V7_HAS_VIRT
 	select PL011_SERIAL
 
+config ARCH_BCMSTB
+	bool "Broadcom BCM7XXX family"
+	select CPU_V7A
+	select DM
+	select OF_CONTROL
+	select OF_PRIOR_STAGE
+	help
+	  This enables support for Broadcom ARM-based set-top box
+	  chipsets, including the 7445 family of chips.
+
 config TARGET_VEXPRESS_CA5X2
 	bool "Support vexpress_ca5x2"
 	select CPU_V7A
@@ -1297,6 +1307,8 @@ source "arch/arm/mach-at91/Kconfig"
 
 source "arch/arm/mach-bcm283x/Kconfig"
 
+source "arch/arm/mach-bcmstb/Kconfig"
+
 source "arch/arm/mach-davinci/Kconfig"
 
 source "arch/arm/mach-exynos/Kconfig"
diff --git a/arch/arm/Makefile b/arch/arm/Makefile
index 680c6e8..03252fe 100644
--- a/arch/arm/Makefile
+++ b/arch/arm/Makefile
@@ -54,6 +54,7 @@ PLATFORM_CPPFLAGS += $(arch-y) $(tune-y)
 machine-$(CONFIG_ARCH_ASPEED)		+= aspeed
 machine-$(CONFIG_ARCH_AT91)		+= at91
 machine-$(CONFIG_ARCH_BCM283X)		+= bcm283x
+machine-$(CONFIG_ARCH_BCMSTB)		+= bcmstb
 machine-$(CONFIG_ARCH_DAVINCI)		+= davinci
 machine-$(CONFIG_ARCH_EXYNOS)		+= exynos
 machine-$(CONFIG_ARCH_HIGHBANK)		+= highbank
diff --git a/arch/arm/mach-bcmstb/Kconfig b/arch/arm/mach-bcmstb/Kconfig
new file mode 100644
index 0000000..0c9dcda
--- /dev/null
+++ b/arch/arm/mach-bcmstb/Kconfig
@@ -0,0 +1,64 @@
+if ARCH_BCMSTB
+
+config TARGET_BCM7445
+	bool "Broadcom 7445 TSBL"
+	depends on ARCH_BCMSTB
+	help
+	  Support for the Broadcom 7445 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 SYS_CPU
+	default "armv7"
+
+config SYS_BOARD
+	default "bcmstb"
+
+config SYS_VENDOR
+	default "broadcom"
+
+config SYS_SOC
+	default "bcmstb"
+
+config SYS_CONFIG_NAME
+	default "bcmstb"
+
+config SYS_FDT_SAVE_ADDRESS
+	hex "Address to which the prior stage provided DTB will be copied"
+	default 0x1f00000
+
+config BCMSTB_SDHCI_INDEX
+	int "Index of preferred BCMSTB SDHCI alias in DTB"
+	default 1
+
+config BCMSTB_SDHCI_BASE
+	hex "Physical base address of the BCMSTB SDHCI controller"
+	default 0xf03e0200
+
+config BCMSTB_TIMER_LOW
+	hex "Address of BCMSTB timer low register"
+	default 0xf0412008
+
+config BCMSTB_TIMER_FREQUENCY
+	hex "Address of BCMSTB timer frequency register"
+	default 0xf0412020
+
+config BCMSTB_HIF_MSPI_BASE
+	hex "BCMSTB SPI hif_mspi base address"
+	default 0xf03e3400
+
+config BCMSTB_BSPI_BASE
+	hex "BCMSTB SPI bspi base address"
+	default 0xf03e3200
+
+config BCMSTB_HIF_SPI_INTR2
+	hex "BCMSTB SPI hif_spi_intr2 base address"
+	default 0xf03e1a00
+
+config BCMSTB_CS_REG
+	hex "BCMSTB SPI cs_reg address"
+	default 0xf03e0920
+
+endif
diff --git a/arch/arm/mach-bcmstb/Makefile b/arch/arm/mach-bcmstb/Makefile
new file mode 100644
index 0000000..71e5727
--- /dev/null
+++ b/arch/arm/mach-bcmstb/Makefile
@@ -0,0 +1,8 @@
+# SPDX-License-Identifier: GPL-2.0+
+#
+# (C) Copyright 2018  Cisco Systems, Inc.
+#
+# Author: Thomas Fitzsimmons <fitzsim@fitzsim.org>
+#
+
+obj-y	:= lowlevel_init.o
diff --git a/arch/arm/mach-bcmstb/include/mach/gpio.h b/arch/arm/mach-bcmstb/include/mach/gpio.h
new file mode 100644
index 0000000..bffecf9
--- /dev/null
+++ b/arch/arm/mach-bcmstb/include/mach/gpio.h
@@ -0,0 +1,11 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+/*
+ * (C) Copyright 2018  Cisco Systems, Inc.
+ *
+ * Author: Thomas Fitzsimmons <fitzsim@fitzsim.org>
+ */
+
+#ifndef _BCMSTB_GPIO_H
+#define _BCMSTB_GPIO_H
+
+#endif /* _BCMSTB_GPIO_H */
diff --git a/arch/arm/mach-bcmstb/include/mach/hardware.h b/arch/arm/mach-bcmstb/include/mach/hardware.h
new file mode 100644
index 0000000..76f799d
--- /dev/null
+++ b/arch/arm/mach-bcmstb/include/mach/hardware.h
@@ -0,0 +1,11 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+/*
+ * (C) Copyright 2018  Cisco Systems, Inc.
+ *
+ * Author: Thomas Fitzsimmons <fitzsim@fitzsim.org>
+ */
+
+#ifndef _BCMSTB_HARDWARE_H
+#define _BCMSTB_HARDWARE_H
+
+#endif /* _BCMSTB_HARDWARE_H */
diff --git a/arch/arm/mach-bcmstb/include/mach/prior_stage.h b/arch/arm/mach-bcmstb/include/mach/prior_stage.h
new file mode 100644
index 0000000..6c36c68
--- /dev/null
+++ b/arch/arm/mach-bcmstb/include/mach/prior_stage.h
@@ -0,0 +1,30 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+/*
+ * (C) Copyright 2018  Cisco Systems, Inc.
+ *
+ * Author: Thomas Fitzsimmons <fitzsim@fitzsim.org>
+ */
+
+#ifndef _BCMSTB_PRIOR_STAGE_H
+#define _BCMSTB_PRIOR_STAGE_H
+
+#ifndef __ASSEMBLY__
+
+#include <linux/types.h>
+
+struct bcmstb_boot_parameters {
+	u32 r0;
+	u32 r1;
+	u32 r2;
+	u32 r3;
+	u32 sp;
+	u32 lr;
+};
+
+extern struct bcmstb_boot_parameters bcmstb_boot_parameters;
+
+extern phys_addr_t prior_stage_fdt_address;
+
+#endif /* __ASSEMBLY__ */
+
+#endif /* _BCMSTB_PRIOR_STAGE_H */
diff --git a/arch/arm/mach-bcmstb/include/mach/sdhci.h b/arch/arm/mach-bcmstb/include/mach/sdhci.h
new file mode 100644
index 0000000..243783d
--- /dev/null
+++ b/arch/arm/mach-bcmstb/include/mach/sdhci.h
@@ -0,0 +1,15 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+/*
+ * (C) Copyright 2018  Cisco Systems, Inc.
+ *
+ * Author: Thomas Fitzsimmons <fitzsim@fitzsim.org>
+ */
+
+#ifndef _BCMSTB_SDHCI_H
+#define _BCMSTB_SDHCI_H
+
+#include <linux/types.h>
+
+int bcmstb_sdhci_init(phys_addr_t regbase);
+
+#endif /* _BCMSTB_SDHCI_H */
diff --git a/arch/arm/mach-bcmstb/include/mach/timer.h b/arch/arm/mach-bcmstb/include/mach/timer.h
new file mode 100644
index 0000000..d05b4d6
--- /dev/null
+++ b/arch/arm/mach-bcmstb/include/mach/timer.h
@@ -0,0 +1,13 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+/*
+ * (C) Copyright 2018  Cisco Systems, Inc.
+ *
+ * Author: Thomas Fitzsimmons <fitzsim@fitzsim.org>
+ */
+
+#ifndef _BCMSTB_TIMER_H
+#define _BCMSTB_TIMER_H
+
+unsigned long timer_read_counter(void);
+
+#endif /* _BCMSTB_TIMER_H */
diff --git a/arch/arm/mach-bcmstb/lowlevel_init.S b/arch/arm/mach-bcmstb/lowlevel_init.S
new file mode 100644
index 0000000..aa81f70
--- /dev/null
+++ b/arch/arm/mach-bcmstb/lowlevel_init.S
@@ -0,0 +1,21 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+/*
+ * (C) Copyright 2018  Cisco Systems, Inc.
+ *
+ * Author: Thomas Fitzsimmons <fitzsim@fitzsim.org>
+ */
+
+#include <linux/linkage.h>
+
+ENTRY(save_boot_params)
+	ldr	r6, =bcmstb_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/board/broadcom/bcmstb/MAINTAINERS b/board/broadcom/bcmstb/MAINTAINERS
new file mode 100644
index 0000000..5e23ecd
--- /dev/null
+++ b/board/broadcom/bcmstb/MAINTAINERS
@@ -0,0 +1,6 @@
+BCM7445 BOARD
+M:	Thomas Fitzsimmons <fitzsim@fitzsim.org>
+S:	Maintained
+F:	board/broadcom/bcmstb/
+F:	include/configs/bcmstb.h
+F:	configs/bcm7445_defconfig
diff --git a/board/broadcom/bcmstb/Makefile b/board/broadcom/bcmstb/Makefile
new file mode 100644
index 0000000..9609887
--- /dev/null
+++ b/board/broadcom/bcmstb/Makefile
@@ -0,0 +1,8 @@
+# SPDX-License-Identifier: GPL-2.0+
+#
+# (C) Copyright 2018  Cisco Systems, Inc.
+#
+# Author: Thomas Fitzsimmons <fitzsim@fitzsim.org>
+#
+
+obj-y	:= bcmstb.o
diff --git a/board/broadcom/bcmstb/bcmstb.c b/board/broadcom/bcmstb/bcmstb.c
new file mode 100644
index 0000000..2544497
--- /dev/null
+++ b/board/broadcom/bcmstb/bcmstb.c
@@ -0,0 +1,191 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * (C) Copyright 2018  Cisco Systems, Inc.
+ *
+ * Author: Thomas Fitzsimmons <fitzsim@fitzsim.org>
+ */
+
+#include <linux/types.h>
+#include <common.h>
+#include <asm/io.h>
+#include <asm/bootm.h>
+#include <mach/sdhci.h>
+#include <mach/timer.h>
+#include <mmc.h>
+#include <fdtdec.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+#define BCMSTB_DATA_SECTION __attribute__((section(".data")))
+
+struct bcmstb_boot_parameters bcmstb_boot_parameters BCMSTB_DATA_SECTION;
+
+phys_addr_t prior_stage_fdt_address BCMSTB_DATA_SECTION;
+
+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)
+{
+	if (fdtdec_setup_memory_size() != 0)
+		return -EINVAL;
+
+	return 0;
+}
+
+int dram_init_banksize(void)
+{
+	fdtdec_setup_memory_banksize();
+
+	/*
+	 * On this SoC, U-Boot is running as an ELF file.  Change the
+	 * relocation address to CONFIG_SYS_TEXT_BASE, so that in
+	 * setup_reloc, gd->reloc_off works out to 0, effectively
+	 * disabling relocation.  Otherwise U-Boot hangs in the setup
+	 * instructions just before relocate_code in
+	 * arch/arm/lib/crt0.S.
+	 */
+	gd->relocaddr = CONFIG_SYS_TEXT_BASE;
+
+	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.
+	 */
+}
+
+static const phys_addr_t bcmstb_sdhci_address(u32 alias_index)
+{
+	int node = 0;
+	int ret = 0;
+	char sdhci[16] = { 0 };
+	const void *fdt = gd->fdt_blob;
+	const char *path = NULL;
+	struct fdt_resource resource = { 0 };
+
+	if (!fdt) {
+		printf("%s: Invalid gd->fdt_blob\n", __func__);
+		return 0;
+	}
+
+	node = fdt_path_offset(fdt, "/aliases");
+	if (node < 0) {
+		printf("%s: Failed to find /aliases node\n", __func__);
+		return 0;
+	}
+
+	sprintf(sdhci, "sdhci%d", alias_index);
+	path = fdt_getprop(fdt, node, sdhci, NULL);
+	if (!path) {
+		printf("%s: Failed to find alias for %s\n", __func__, sdhci);
+		return 0;
+	}
+
+	node = fdt_path_offset(fdt, path);
+	if (node < 0) {
+		printf("%s: Failed to resolve BCMSTB SDHCI alias\n", __func__);
+		return 0;
+	}
+
+	ret = fdt_get_named_resource(fdt, node, "reg", "reg-names",
+				     "host", &resource);
+	if (ret) {
+		printf("%s: Failed to read BCMSTB SDHCI host resource\n",
+		       __func__);
+		return 0;
+	}
+
+	return resource.start;
+}
+
+int board_mmc_init(bd_t *bis)
+{
+	phys_addr_t sdhci_base_address = 0;
+
+	sdhci_base_address = bcmstb_sdhci_address(CONFIG_BCMSTB_SDHCI_INDEX);
+
+	if (!sdhci_base_address) {
+		sdhci_base_address = CONFIG_BCMSTB_SDHCI_BASE;
+		printf("%s: Assuming BCMSTB SDHCI address: 0x%p\n",
+		       __func__, (void *)sdhci_base_address);
+	}
+
+	debug("BCMSTB SDHCI base address: 0x%p\n", (void *)sdhci_base_address);
+
+	bcmstb_sdhci_init(sdhci_base_address);
+
+	return 0;
+}
+
+int timer_init(void)
+{
+	gd->arch.timer_rate_hz = readl(CONFIG_BCMSTB_TIMER_FREQUENCY);
+
+	return 0;
+}
+
+ulong get_tbclk(void)
+{
+	return gd->arch.timer_rate_hz;
+}
+
+unsigned long timer_read_counter(void)
+{
+	return readl(CONFIG_BCMSTB_TIMER_LOW);
+}
+
+int board_late_init(void)
+{
+	debug("Arguments from prior stage bootloader:\n");
+	debug("General Purpose Register 0: 0x%x\n", bcmstb_boot_parameters.r0);
+	debug("General Purpose Register 1: 0x%x\n", bcmstb_boot_parameters.r1);
+	debug("General Purpose Register 2: 0x%x\n", bcmstb_boot_parameters.r2);
+	debug("General Purpose Register 3: 0x%x\n", bcmstb_boot_parameters.r3);
+	debug("Stack Pointer Register:     0x%x\n", bcmstb_boot_parameters.sp);
+	debug("Link Register:              0x%x\n", bcmstb_boot_parameters.lr);
+	debug("Assuming timer frequency register at: 0x%p\n",
+	      (void *)CONFIG_BCMSTB_TIMER_FREQUENCY);
+	debug("Read timer frequency (in Hz): %ld\n", gd->arch.timer_rate_hz);
+	debug("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 (bcmstb_boot_parameters.r1)
+	 * because we're using a device tree to boot Linux.
+	 */
+
+	return 0;
+}
diff --git a/configs/bcm7445_defconfig b/configs/bcm7445_defconfig
new file mode 100644
index 0000000..46dea17
--- /dev/null
+++ b/configs/bcm7445_defconfig
@@ -0,0 +1,27 @@
+CONFIG_ARM=y
+CONFIG_ARCH_BCMSTB=y
+CONFIG_TARGET_BCM7445=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_BCMSTB_SPI=y
+CONFIG_FIT=y
+CONFIG_FIT_SIGNATURE=y
+CONFIG_RSA=y
+CONFIG_BLK=n
+CONFIG_SDHCI=y
+CONFIG_MMC_SDHCI=y
+CONFIG_MMC_SDHCI_BCMSTB=y
+CONFIG_CONS_INDEX=3
+CONFIG_BOOTDELAY=1
+CONFIG_SYS_PROMPT="U-Boot>"
+CONFIG_HUSH_PARSER=y
+CONFIG_SYS_TEXT_BASE=0x80100000
+CONFIG_SYS_NS16550_COM3=0xf040ab00
+CONFIG_EFI_LOADER=n
diff --git a/doc/README.bcm7xxx b/doc/README.bcm7xxx
new file mode 100644
index 0000000..0545d0b
--- /dev/null
+++ b/doc/README.bcm7xxx
@@ -0,0 +1,147 @@
+Summary
+=======
+
+This document describes how to use U-Boot on the Broadcom 7445 SoC, as
+a third stage bootloader loaded by Broadcom's BOLT bootloader.
+
+BOLT loads U-Boot as a generic ELF binary.  Some U-Boot features such
+as networking are not yet available but other important features are,
+including:
+
+   - ext4 file system traversal
+
+   - support for loading FIT images
+
+   - advanced scripting
+
+   - support for FIT-provided DTBs instead of relying on the
+     BOLT-provided DTB
+
+A customized version of this port has been used in production.  The
+same approach may work on other BCM7xxx boards, with some
+configuration adjustments and memory layout experimentation.
+
+Build
+=====
+
+make bcm7445_defconfig
+make
+${CROSS_COMPILE}strip u-boot
+
+Run
+===
+
+Flash the u-boot binary into board storage, then invoke it from BOLT.
+For example:
+
+BOLT> boot -bsu -elf flash0.u-boot1
+
+Flattened Image Tree Support
+============================
+
+What follows is an example FIT image source file.  Build it with:
+
+mkimage -f image.its image.itb
+
+Booting the resulting image.itb was tested on BOLT v1.20, with the
+following kernels:
+
+https://github.com/Broadcom/stblinux-3.14
+https://github.com/Broadcom/stblinux-4.1
+https://github.com/Broadcom/stblinux-4.9
+
+and with a generic ARMv7 root file system.
+
+image.its:
+/dts-v1/;
+/ {
+	description = "BCM7445 FIT";
+	images {
+		kernel at 1 {
+			description = "Linux kernel";
+			/*
+			 * This kernel image output format can be
+			 * generated with:
+			 *
+			 * make vmlinux
+			 * ${CROSS_COMPILE}objcopy -O binary -S vmlinux vmlinux.bin
+			 * gzip -9 vmlinux.bin
+			 *
+			 * For stblinux-3.14, the specific Broadcom
+			 * board type should be configured in the
+			 * kernel, for example CONFIG_BCM7445D0=y.
+			 */
+			data = /incbin/("<vmlinux.bin.gz>");
+			type = "kernel";
+			arch = "arm";
+			os = "linux";
+			compression = "gzip";
+			load = <0x8000>;
+			entry = <0x8000>;
+			hash at 1 {
+				algo = "sha256";
+			};
+		};
+		ramdisk at 1 {
+			description = "Initramfs root file system";
+			data = /incbin/("<initramfs.cpio.gz>");
+			type = "ramdisk";
+			arch = "arm";
+			os = "linux";
+			compression = "gzip";
+			/*
+			 * Set the environment variable initrd_high to
+			 * 0xffffffff, and set "load" and "entry" here
+			 * to 0x0 to keep initramfs in-place and to
+			 * accommodate stblinux bmem/CMA reservations.
+			 */
+			load = <0x0>;
+			entry = <0x0>;
+			hash at 1 {
+				algo = "sha256";
+			};
+		};
+		fdt at 1 {
+			description = "Device tree dumped from BOLT";
+			/*
+			 * This DTB should be similar to the
+			 * BOLT-generated device tree, after BOLT has
+			 * done its runtime modifications to it.  For
+			 * example, it can be dumped from within
+			 * U-Boot (at ${fdtcontroladdr}), after BOLT
+			 * has loaded U-Boot.  The result can be added
+			 * to the Linux source tree as a .dts file.
+			 *
+			 * To support modifications to the device tree
+			 * in-place in U-Boot, add to Linux's
+			 * arch/arm/boot/dts/Makefile:
+			 *
+			 * DTC_FLAGS ?= -p 4096
+			 *
+			 * This will leave some padding in the DTB and
+			 * thus reserve room for node additions.
+			 *
+			 * Also, set the environment variable fdt_high
+			 * to 0xffffffff to keep the DTB in-place and
+			 * to accommodate stblinux bmem/CMA
+			 * reservations.
+			 */
+			data = /incbin/("<bolt-<version>.dtb");
+			type = "flat_dt";
+			arch = "arm";
+			compression = "none";
+			hash at 1 {
+				algo = "sha256";
+			};
+		};
+	};
+	configurations {
+		default = "conf at bcm7445";
+		conf at bcm7445 {
+			description = "BCM7445 configuration";
+			kernel = "kernel at 1";
+			ramdisk = "ramdisk at 1";
+			fdt = "fdt at 1";
+		};
+	};
+};
diff --git a/drivers/mmc/Kconfig b/drivers/mmc/Kconfig
index 693b3ce..377b1c4 100644
--- a/drivers/mmc/Kconfig
+++ b/drivers/mmc/Kconfig
@@ -379,6 +379,17 @@ config MMC_SDHCI_BCM2835
 
 	  If unsure, say N.
 
+config MMC_SDHCI_BCMSTB
+	tristate "SDHCI support for the BCMSTB SD/MMC Controller"
+	depends on MMC_SDHCI
+	help
+	  This selects the Broadcom set-top box SD/MMC controller.
+
+	  If you have a BCMSTB platform with SD or MMC devices,
+	  say Y here.
+
+	  If unsure, say N.
+
 config MMC_SDHCI_CADENCE
 	bool "SDHCI support for the Cadence SD/SDIO/eMMC controller"
 	depends on BLK && DM_MMC
diff --git a/drivers/mmc/Makefile b/drivers/mmc/Makefile
index 3a9805d..f619186 100644
--- a/drivers/mmc/Makefile
+++ b/drivers/mmc/Makefile
@@ -45,6 +45,7 @@ obj-$(CONFIG_STM32_SDMMC2) += stm32_sdmmc2.o
 obj-$(CONFIG_MMC_SDHCI)			+= sdhci.o
 obj-$(CONFIG_MMC_SDHCI_ATMEL)		+= atmel_sdhci.o
 obj-$(CONFIG_MMC_SDHCI_BCM2835)		+= bcm2835_sdhci.o
+obj-$(CONFIG_MMC_SDHCI_BCMSTB)		+= bcmstb_sdhci.o
 obj-$(CONFIG_MMC_SDHCI_CADENCE)		+= sdhci-cadence.o
 obj-$(CONFIG_MMC_SDHCI_KONA)		+= kona_sdhci.o
 obj-$(CONFIG_MMC_SDHCI_MSM)		+= msm_sdhci.o
diff --git a/drivers/mmc/bcmstb_sdhci.c b/drivers/mmc/bcmstb_sdhci.c
new file mode 100644
index 0000000..443ae8d
--- /dev/null
+++ b/drivers/mmc/bcmstb_sdhci.c
@@ -0,0 +1,67 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * (C) Copyright 2018  Cisco Systems, Inc.
+ *
+ * Author: Thomas Fitzsimmons <fitzsim@fitzsim.org>
+ */
+
+#include <common.h>
+#include <mach/sdhci.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("%s: Failed to allocate memory\n", __func__);
+		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 3532c2a..f5960a7 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 "BCMSTB 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 5a2c00e..e73b0cd 100644
--- a/drivers/spi/Makefile
+++ b/drivers/spi/Makefile
@@ -18,6 +18,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..7be57be
--- /dev/null
+++ b/drivers/spi/bcmstb_spi.c
@@ -0,0 +1,439 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * (C) Copyright 2018  Cisco Systems, Inc.
+ *
+ * Author: Thomas Fitzsimmons <fitzsim@fitzsim.org>
+ */
+
+#include <asm/io.h>
+#include <command.h>
+#include <config.h>
+#include <dm.h>
+#include <errno.h>
+#include <fdtdec.h>
+#include <linux/bitops.h>
+#include <linux/delay.h>
+#include <log.h>
+#include <malloc.h>
+#include <spi.h>
+#include <time.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
+
+/* hif_mspi register structure. */
+struct bcmstb_hif_mspi_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 */
+	u32 write_lock;		/* 0x180 */
+};
+
+/* hif_mspi masks. */
+#define HIF_MSPI_SPCR2_CONT_AFTER_CMD_MASK	0x00000080
+#define HIF_MSPI_SPCR2_SPE_MASK			0x00000040
+#define HIF_MSPI_SPCR2_SPIFIE_MASK		0x00000020
+#define HIF_MSPI_WRITE_LOCK_WRITE_LOCK_MASK	0x00000001
+
+/* bspi offsets. */
+#define BSPI_MAST_N_BOOT_CTRL			0x008
+
+/* bspi_raf is not used in this driver. */
+
+/* hif_spi_intr2 offsets and masks. */
+#define HIF_SPI_INTR2_CPU_CLEAR			0x08
+#define HIF_SPI_INTR2_CPU_MASK_SET		0x10
+#define HIF_SPI_INTR2_CPU_MASK_CLEAR		0x14
+#define HIF_SPI_INTR2_CPU_SET_MSPI_DONE_MASK	0x00000020
+
+/* SPI transfer timeout in milliseconds. */
+#define HIF_MSPI_WAIT				10
+
+enum bcmstb_base_type {
+	HIF_MSPI,
+	BSPI,
+	HIF_SPI_INTR2,
+	CS_REG,
+	BASE_LAST,
+};
+
+struct bcmstb_spi_platdata {
+	void *base[4];
+};
+
+struct bcmstb_spi_priv {
+	struct bcmstb_hif_mspi_regs *regs;
+	void *bspi;
+	void *hif_spi_intr2;
+	void *cs_reg;
+	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;
+};
+
+static int bcmstb_spi_ofdata_to_platdata(struct udevice *bus)
+{
+	struct bcmstb_spi_platdata *plat = dev_get_platdata(bus);
+	const void *fdt = gd->fdt_blob;
+	int node = dev_of_offset(bus);
+	int ret = 0;
+	int i = 0;
+	struct fdt_resource resource = { 0 };
+	char *names[BASE_LAST] = { "hif_mspi", "bspi", "hif_spi_intr2",
+				   "cs_reg" };
+	const phys_addr_t defaults[BASE_LAST] = { CONFIG_BCMSTB_HIF_MSPI_BASE,
+						  CONFIG_BCMSTB_BSPI_BASE,
+						  CONFIG_BCMSTB_HIF_SPI_INTR2,
+						  CONFIG_BCMSTB_CS_REG };
+
+	for (i = 0; i < BASE_LAST; i++) {
+		plat->base[i] = (void *)defaults[i];
+
+		ret = fdt_get_named_resource(fdt, node, "reg", "reg-names",
+					     names[i], &resource);
+		if (ret) {
+			printf("%s: Assuming BCMSTB SPI %s address 0x0x%p\n",
+			       __func__, names[i], (void *)defaults[i]);
+		} else {
+			plat->base[i] = (void *)resource.start;
+			debug("BCMSTB SPI %s address: 0x0x%p\n",
+			      names[i], (void *)plat->base[i]);
+		}
+	}
+
+	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(void *base, u32 mask)
+{
+	void *reg = base + HIF_SPI_INTR2_CPU_MASK_CLEAR;
+
+	writel(readl(reg) | mask, reg);
+	readl(reg);
+}
+
+static void bcmstb_spi_disable_interrupt(void *base, u32 mask)
+{
+	void *reg = base + HIF_SPI_INTR2_CPU_MASK_SET;
+
+	writel(readl(reg) | mask, reg);
+	readl(reg);
+}
+
+static void bcmstb_spi_clear_interrupt(void *base, u32 mask)
+{
+	void *reg = base + HIF_SPI_INTR2_CPU_CLEAR;
+
+	writel(readl(reg) | mask, reg);
+	readl(reg);
+}
+
+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->base[HIF_MSPI];
+	priv->bspi = plat->base[BSPI];
+	priv->hif_spi_intr2 = plat->base[HIF_SPI_INTR2];
+	priv->cs_reg = plat->base[CS_REG];
+	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;
+
+	debug("spi_xfer: tx regs: 0x%p\n", &priv->regs->txram[0]);
+	debug("spi_xfer: rx regs: 0x%p\n", &priv->regs->rxram[0]);
+
+	/* Disable BSPI. */
+	writel(1, priv->bspi + BSPI_MAST_N_BOOT_CTRL);
+	readl(priv->bspi + BSPI_MAST_N_BOOT_CTRL);
+
+	/* Set up interrupts. */
+	bcmstb_spi_disable_interrupt(priv->hif_spi_intr2, 0xffffffff);
+	bcmstb_spi_clear_interrupt(priv->hif_spi_intr2, 0xffffffff);
+	bcmstb_spi_enable_interrupt(priv->hif_spi_intr2,
+				    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(HIF_MSPI_SPCR2_SPIFIE_MASK, &priv->regs->spcr2);
+	writel(0, &priv->regs->spcr3);
+
+	bcmstb_spi_hw_set_parms(priv);
+
+	return 0;
+}
+
+static void bcmstb_spi_submit(struct bcmstb_spi_priv *priv, bool done)
+{
+	debug("WR NEWQP: %d\n", 0);
+	writel(0, &priv->regs->newqp);
+
+	debug("WR ENDQP: %d\n", priv->tx_slot - 1);
+	writel(priv->tx_slot - 1, &priv->regs->endqp);
+
+	if (done) {
+		debug("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) {
+		debug("spi_xfer: switching chip select to %d\n",
+		      priv->default_cs);
+		writel((readl(priv->cs_reg) & ~0xff) | (1 << priv->default_cs),
+		       priv->cs_reg);
+		readl(priv->cs_reg);
+		udelay(10);
+		priv->curr_cs = priv->default_cs;
+	}
+
+	debug("WR WRITE_LOCK: %02x\n", 1);
+	writel((readl(&priv->regs->write_lock) &
+		~HIF_MSPI_WRITE_LOCK_WRITE_LOCK_MASK) | 1,
+	       &priv->regs->write_lock);
+	readl(&priv->regs->write_lock);
+
+	debug("WR SPCR2: %02x\n",
+	      HIF_MSPI_SPCR2_SPIFIE_MASK |
+	      HIF_MSPI_SPCR2_SPE_MASK |
+	      HIF_MSPI_SPCR2_CONT_AFTER_CMD_MASK);
+	writel(HIF_MSPI_SPCR2_SPIFIE_MASK |
+	       HIF_MSPI_SPCR2_SPE_MASK |
+	       HIF_MSPI_SPCR2_CONT_AFTER_CMD_MASK,
+	       &priv->regs->spcr2);
+}
+
+static int bcmstb_spi_wait(struct bcmstb_spi_priv *priv)
+{
+	u32 start_time = get_timer(0);
+	u32 status = readl(&priv->regs->mspi_status);
+
+	while (!(status & 1)) {
+		if (get_timer(start_time) > HIF_MSPI_WAIT)
+			return -ETIMEDOUT;
+		status = readl(&priv->regs->mspi_status);
+	}
+
+	writel(readl(&priv->regs->mspi_status) & ~1, &priv->regs->mspi_status);
+	bcmstb_spi_clear_interrupt(priv->hif_spi_intr2,
+				   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_hif_mspi_regs *regs = priv->regs;
+
+	debug("spi_xfer: %d, t: 0x%p, r: 0x%p, f: %lx\n",
+	      len, dout, din, flags);
+	debug("spi_xfer: chip select: %x\n", readl(priv->cs_reg) & 0xff);
+	debug("spi_xfer: tx addr: 0x%p\n", &regs->txram[0]);
+	debug("spi_xfer: rx addr: 0x%p\n", &regs->rxram[0]);
+	debug("spi_xfer: cd addr: 0x%p\n", &regs->cdram[0]);
+
+	if (flags & SPI_XFER_END) {
+		debug("spi_xfer: clearing saved din address: 0x%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("%s: Non-byte-aligned transfer\n", __func__);
+		return -EOPNOTSUPP;
+	}
+
+	if (flags & ~(SPI_XFER_BEGIN | SPI_XFER_END)) {
+		printf("%s: Unsupported flags: %lx\n", __func__, flags);
+		return -EOPNOTSUPP;
+	}
+
+	if (flags & SPI_XFER_BEGIN) {
+		priv->tx_slot = 0;
+		priv->rx_slot = 0;
+
+		if (out_bytes && len > NUM_CDRAM) {
+			printf("%s: Unable to save transfer\n", __func__);
+			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.
+			 */
+			debug("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 ret = 0;
+
+			debug("spi_xfer: Making recursive call\n");
+			ret = bcmstb_spi_xfer(dev, priv->saved_cmd_len * 8,
+					      priv->saved_cmd, NULL,
+					      SPI_XFER_BEGIN);
+			if (ret) {
+				printf("%s: Recursive call failed\n", __func__);
+				return ret;
+			}
+		} else {
+			debug("spi_xfer: saving din address: 0x%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);
+			debug("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,
+			       &regs->txram[priv->tx_slot << 1]);
+			debug("WR CDRAM[%d]: %02x\n", priv->tx_slot, 0x8e);
+			writel(0x8e, &regs->cdram[priv->tx_slot]);
+			priv->tx_slot++;
+			tx_len--;
+			if (!in_bytes)
+				rx_len--;
+		}
+
+		debug("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(priv) == -ETIMEDOUT) {
+			printf("%s: Timed out\n", __func__);
+			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(&regs->rxram[(priv->rx_slot << 1)
+							   + 1])
+					& 0xff;
+				debug("RD RXRAM[%d]: %02x\n",
+				      priv->rx_slot, in_bytes[len - rx_len]);
+				priv->rx_slot++;
+				rx_len--;
+			}
+		}
+	}
+
+	if (flags & SPI_XFER_END) {
+		debug("WR WRITE_LOCK: %02x\n", 0);
+		writel((readl(&priv->regs->write_lock) &
+			~HIF_MSPI_WRITE_LOCK_WRITE_LOCK_MASK) | 0,
+		       &priv->regs->write_lock);
+		readl(&priv->regs->write_lock);
+	}
+
+	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 = {
+	.xfer		= bcmstb_spi_xfer,
+	.set_speed	= bcmstb_spi_set_speed,
+	.set_mode	= bcmstb_spi_set_mode,
+};
+
+static const struct udevice_id bcmstb_spi_id[] = {
+	{ .compatible = "brcm,spi-brcmstb" },
+	{ }
+};
+
+U_BOOT_DRIVER(bcmstb_spi) = {
+	.name				= "bcmstb_spi",
+	.id				= UCLASS_SPI,
+	.of_match			= bcmstb_spi_id,
+	.ops				= &bcmstb_spi_ops,
+	.ofdata_to_platdata		= bcmstb_spi_ofdata_to_platdata,
+	.probe				= bcmstb_spi_probe,
+	.platdata_auto_alloc_size	= sizeof(struct bcmstb_spi_platdata),
+	.priv_auto_alloc_size		= sizeof(struct bcmstb_spi_priv),
+};
diff --git a/drivers/spi/spi-uclass.c b/drivers/spi/spi-uclass.c
index d2d091f..c517d06 100644
--- a/drivers/spi/spi-uclass.c
+++ b/drivers/spi/spi-uclass.c
@@ -273,7 +273,7 @@ int spi_get_bus_and_cs(int busnum, int cs, int speed, int mode,
 	bool created = false;
 	int ret;
 
-#if CONFIG_IS_ENABLED(OF_PLATDATA)
+#if CONFIG_IS_ENABLED(OF_PLATDATA) || CONFIG_IS_ENABLED(OF_PRIOR_STAGE)
 	ret = uclass_first_device_err(UCLASS_SPI, &bus);
 #else
 	ret = uclass_get_device_by_seq(UCLASS_SPI, busnum, &bus);
diff --git a/dts/Kconfig b/dts/Kconfig
index 0cef225..a1a92f2 100644
--- a/dts/Kconfig
+++ b/dts/Kconfig
@@ -101,6 +101,13 @@ 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, the device tree used for DT
+	  control will be read from a device tree binary, at a memory
+	  location passed to U-Boot by the prior stage bootloader.
+
 endchoice
 
 config DEFAULT_DEVICE_TREE
diff --git a/include/configs/bcmstb.h b/include/configs/bcmstb.h
new file mode 100644
index 0000000..7e61727
--- /dev/null
+++ b/include/configs/bcmstb.h
@@ -0,0 +1,188 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+/*
+ * (C) Copyright 2018  Cisco Systems, Inc.
+ *
+ * Author: Thomas Fitzsimmons <fitzsim@fitzsim.org>
+ *
+ * Configuration settings for the Broadcom BCM7445 SoC family.
+ */
+
+#ifndef __CONFIG_H
+#define __CONFIG_H
+
+#include "version.h"
+#include <linux/sizes.h>
+#include <asm/arch/prior_stage.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 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]
+ *	 0x0200 0000	FIT containing ramdisk and device tree
+ *             :	  initramfs.cpio.gz
+ *	       :	  [~208 MiB uncompressed max, to CMA/bmem low address]
+ *	       :	  [~80 MiB compressed max, to PSB low address]
+ *             :	  device tree binary
+ *             :	  [~60 KiB]
+ *	 0x0700 0000	Prior stage bootloader (PSB)
+ *	       :
+ *	 0x0761 7000	Prior-stage-provided device tree binary (DTB)
+ *	       :	[~40 KiB in size]
+ *	 0x0f00 0000	Contiguous memory allocator (CMA/bmem) low address
+ *	       :
+ *	 0x8010 0000	U-Boot code at ELF load address
+ *	       :	[~500 KiB in size, stripped]
+ *	 0xc000 0000	Top of RAM
+ *
+ * Setting gd->relocaddr to CONFIG_SYS_TEXT_BASE in dram_init_banksize
+ * prevents U-Boot from relocating itself when it is run as an ELF
+ * program by the prior stage bootloader.
+ *
+ * We want to keep the ramdisk and FDT in the FIT image in-place, to
+ * accommodate stblinux's bmem and CMA regions.  To accomplish this,
+ * we set initrd_high and fdt_high to 0xffffffff, and the load and
+ * entry addresses of the FIT ramdisk entry to 0x0.
+ *
+ * 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.
+ */
+#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
+
+/*
+ * Large kernel image bootm configuration.
+ */
+#define CONFIG_SYS_BOOTM_LEN		SZ_64M
+
+/*
+ * 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
+
+/*
+ * Flash configuration.
+ */
+#define CONFIG_ST_SMI
+#define CONFIG_SPI_FLASH_STMICRO
+#define CONFIG_SPI_FLASH_MACRONIX
+
+/*
+ * 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
+
+/*
+ * Save the prior stage provided DTB.
+ */
+#define CONFIG_PREBOOT					\
+	"fdt addr ${fdtcontroladdr};"			\
+	"fdt move ${fdtcontroladdr} ${fdtsaveaddr};"	\
+	"fdt addr ${fdtsaveaddr};"
+/*
+ * Enable in-place RFS with this initrd_high setting.
+ */
+#define CONFIG_EXTRA_ENV_SETTINGS					\
+	"fdtsaveaddr=" __stringify(CONFIG_SYS_FDT_SAVE_ADDRESS) "\0"	\
+	"initrd_high=0xffffffff\0"					\
+	"fdt_high=0xffffffff\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/fdtdec.h b/include/fdtdec.h
index c15b2a0..ff1c5f5 100644
--- a/include/fdtdec.h
+++ b/include/fdtdec.h
@@ -47,6 +47,10 @@ struct fdt_memory {
 #define SPL_BUILD	0
 #endif
 
+#if CONFIG_IS_ENABLED(OF_PRIOR_STAGE)
+extern phys_addr_t prior_stage_fdt_address;
+#endif
+
 /*
  * Information about a resource. start is the first address of the resource
  * and end is the last address (inclusive). The length of the resource will
diff --git a/lib/fdtdec.c b/lib/fdtdec.c
index f4e8dbf..b29b283 100644
--- a/lib/fdtdec.c
+++ b/lib/fdtdec.c
@@ -1323,8 +1323,12 @@ int fdtdec_setup(void)
 # endif
 # ifndef CONFIG_SPL_BUILD
 	/* Allow the early environment to override the fdt address */
+#  if CONFIG_IS_ENABLED(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

^ permalink raw reply related	[flat|nested] 37+ messages in thread

* [U-Boot] [U-Boot, v2, 1/1] board: arm: Add support for Broadcom BCM7445
  2018-06-06 11:16     ` [U-Boot] [U-Boot, v2, " Tom Rini
@ 2018-06-06 19:32       ` Thomas Fitzsimmons
  0 siblings, 0 replies; 37+ messages in thread
From: Thomas Fitzsimmons @ 2018-06-06 19:32 UTC (permalink / raw)
  To: u-boot

Tom Rini <trini@konsulko.com> writes:

> On Wed, May 23, 2018 at 09:24:03PM -0400, Thomas Fitzsimmons wrote:
>
>> Add support for loading U-Boot on the Broadcom 7445 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@fitzsim.org>
>> Cc: Stefan Roese <sr@denx.de>
>> Cc: Tom Rini <trini@konsulko.com>
>> Cc: Florian Fainelli <f.fainelli@gmail.com>
>
> Please rebase this to master.  While I can fixup the SPDX tags (and some
> formatting issues from checkpatch.pl)

I think I fixed all of these in v3 (just posted), by adding an entry to
top-level MAINTAINERS and using the new SPDX formatting rules.

> I also run in to: +(bcm7445) In file included from
> ../arch/arm/include/asm/system.h:6:0, +(bcm7445) from
> ../arch/arm/include/asm/cache.h:11, +(bcm7445) from
> ../include/net.h:15, +(bcm7445) from ../include/common.h:519,
> +(bcm7445) from ../lib/asm-offsets.c:14: +(bcm7445)
> ../arch/arm/include/asm/barriers.h:32:24: error: operator '>=' has no
> left operand +(bcm7445) #if __LINUX_ARM_ARCH__ >= 7 +(bcm7445) ^~
> +(bcm7445) ../arch/arm/include/asm/barriers.h:36:26: error: operator
> '==' has no left operand +(bcm7445) #elif __LINUX_ARM_ARCH__ == 6
> +(bcm7445) ^~ +(bcm7445) make[2]: *** [.././Kbuild:44:
> lib/asm-offsets.s] Error 1 +(bcm7445) make[1]: *** [Makefile:1433:
> prepare0] Error 2
>
> Please look into, thanks!

This was caused by a Kconfig option being renamed on master (CPU_V7 to
CPU_V7A).  Fixed in v3.

Thanks,
Thomas

^ permalink raw reply	[flat|nested] 37+ messages in thread

* [U-Boot] [PATCH 1/1] board: arm: Add support for Broadcom BCM7445D0
  2018-05-10 17:43       ` Florian Fainelli
@ 2018-06-06 20:39         ` Thomas Fitzsimmons
  2018-06-06 22:06           ` Florian Fainelli
  0 siblings, 1 reply; 37+ messages in thread
From: Thomas Fitzsimmons @ 2018-06-06 20:39 UTC (permalink / raw)
  To: u-boot

Florian Fainelli <f.fainelli@gmail.com> writes:

> On 05/10/2018 06:04 AM, Thomas Fitzsimmons wrote:
>> Florian Fainelli <f.fainelli@gmail.com> writes:
>> 
>>> On 05/06/2018 04:09 AM, Thomas Fitzsimmons wrote:

[...]

>>>> +
>>>> +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.
>>>
>>> What STB Linux kernel did you observe this with? I am afraid this is
>>> still true about the ranges vs. allocation even in newer kernels, but
>>> that is kind of intented to keep the logic KISS (because it's already
>>> too complicated IMHO).
>> 
>> I investigated the allocation discrepancy and wrote the workaround while
>> we were still using stblinux-3.14.  Since then we've updated to
>> stblinux-4.1 and I've left the workaround enabled, but I haven't
>> investigated its interactions with the newer bmem mechanism.  I should
>> probably revisit this though, with stblinux-4.1 and stblinux-4.9, just
>> to make sure this macro is still useful.
>
> Sounds good, let me know if there is something that does not seem quite
> right, we could fix it.

[...]

In the v3 patch, I keep the FIT's RFS and DTB in-place.  This approach
eliminates the bmem/cma allocation discrepancies.  I compared bmem/cma
dmesg output for stblinux 3.14, 4.1 and 4.9, zImage and ITB builds, on
my eval board, and they're all the same for the same kernel version.
The only thing I noticed is that in 3.14 and 4.1 (zImage and ITB), the
first bmem region is:

   768 MiB at 0x0000000010000000

whereas in 4.9 (zImage and ITB), it is:

   760 MiB at 0x0000000010800000

This is booting with no kernel command line arguments, so I guess some
default may have changed between stblinux 4.1 and 4.9?

Thomas

^ permalink raw reply	[flat|nested] 37+ messages in thread

* [U-Boot] [PATCH 1/1] board: arm: Add support for Broadcom BCM7445D0
  2018-06-06 20:39         ` Thomas Fitzsimmons
@ 2018-06-06 22:06           ` Florian Fainelli
  0 siblings, 0 replies; 37+ messages in thread
From: Florian Fainelli @ 2018-06-06 22:06 UTC (permalink / raw)
  To: u-boot

On 06/06/2018 01:39 PM, Thomas Fitzsimmons wrote:
> Florian Fainelli <f.fainelli@gmail.com> writes:
> 
>> On 05/10/2018 06:04 AM, Thomas Fitzsimmons wrote:
>>> Florian Fainelli <f.fainelli@gmail.com> writes:
>>>
>>>> On 05/06/2018 04:09 AM, Thomas Fitzsimmons wrote:
> 
> [...]
> 
>>>>> +
>>>>> +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.
>>>>
>>>> What STB Linux kernel did you observe this with? I am afraid this is
>>>> still true about the ranges vs. allocation even in newer kernels, but
>>>> that is kind of intented to keep the logic KISS (because it's already
>>>> too complicated IMHO).
>>>
>>> I investigated the allocation discrepancy and wrote the workaround while
>>> we were still using stblinux-3.14.  Since then we've updated to
>>> stblinux-4.1 and I've left the workaround enabled, but I haven't
>>> investigated its interactions with the newer bmem mechanism.  I should
>>> probably revisit this though, with stblinux-4.1 and stblinux-4.9, just
>>> to make sure this macro is still useful.
>>
>> Sounds good, let me know if there is something that does not seem quite
>> right, we could fix it.
> 
> [...]
> 
> In the v3 patch, I keep the FIT's RFS and DTB in-place.  This approach
> eliminates the bmem/cma allocation discrepancies.  I compared bmem/cma
> dmesg output for stblinux 3.14, 4.1 and 4.9, zImage and ITB builds, on
> my eval board, and they're all the same for the same kernel version.
> The only thing I noticed is that in 3.14 and 4.1 (zImage and ITB), the
> first bmem region is:
> 
>    768 MiB at 0x0000000010000000
> 
> whereas in 4.9 (zImage and ITB), it is:
> 
>    760 MiB at 0x0000000010800000
> 
> This is booting with no kernel command line arguments, so I guess some
> default may have changed between stblinux 4.1 and 4.9?

This upstream commit is responsible for what you see:
6ff0966052c46efb53980b8a1add2e7b49c9f560 ("ARM: 8432/1: move VMALLOC_END
from 0xff000000 to 0xff800000") we've backported that change to our 3.14
and 4.1 kernels since then.
-- 
Florian

^ permalink raw reply	[flat|nested] 37+ messages in thread

* [U-Boot] [PATCH v3 1/1] board: arm: Add support for Broadcom BCM7445
  2018-06-06 18:35     ` [U-Boot] [PATCH v3 1/1] " Thomas Fitzsimmons
@ 2018-06-07 16:54       ` Florian Fainelli
  2018-06-08 22:25         ` Thomas Fitzsimmons
  0 siblings, 1 reply; 37+ messages in thread
From: Florian Fainelli @ 2018-06-07 16:54 UTC (permalink / raw)
  To: u-boot

On 06/06/2018 11:35 AM, Thomas Fitzsimmons wrote:
> Add support for loading U-Boot on the Broadcom 7445 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@fitzsim.org>
> Cc: Stefan Roese <sr@denx.de>
> Cc: Tom Rini <trini@konsulko.com>
> Cc: Florian Fainelli <f.fainelli@gmail.com>
> ---

Looks good, still some minor comments about the choice of representation
for physical addresses of peripherals, see below.

> +config BCMSTB_TIMER_LOW
> +	hex "Address of BCMSTB timer low register"
> +	default 0xf0412008

This looks very simplistic here since the CPU system control timer is a
64-bit timer.

I am really not a big fan of all of those configurable addresses which
are a) fixed given a specific SoC family (7445, 7439 etc.) and b) are
error prone because we let an user change those without necessarily
knowing what is the implication. I really think sticking those constants
into a header file would be much more appropriate.

> +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.
> +	 */

This heavily depends on how you load your binary from BOLT, so you must
be careful about this statement here.
-- 
Florian

^ permalink raw reply	[flat|nested] 37+ messages in thread

* [U-Boot] [PATCH v4 0/1] board: arm: Add support for Broadcom BCM7445
  2018-06-06 18:35   ` [U-Boot] [PATCH v3 0/1] " Thomas Fitzsimmons
  2018-06-06 18:35     ` [U-Boot] [PATCH v3 1/1] " Thomas Fitzsimmons
@ 2018-06-08 21:59     ` Thomas Fitzsimmons
  2018-06-08 21:59       ` [U-Boot] [PATCH v4 1/1] " Thomas Fitzsimmons
  1 sibling, 1 reply; 37+ messages in thread
From: Thomas Fitzsimmons @ 2018-06-08 21:59 UTC (permalink / raw)
  To: u-boot

Add support for Broadcom BCM7445

Changes for v4:
   - Use high timer register for get_ticks
   - Move hard-coded register addresses from Kconfig to header
   - Document I-cache/D-cache expectation

Thomas Fitzsimmons (1):
  board: arm: Add support for Broadcom BCM7445

 MAINTAINERS                                     |  10 +
 arch/arm/Kconfig                                |  12 +
 arch/arm/Makefile                               |   1 +
 arch/arm/mach-bcmstb/Kconfig                    |  36 ++
 arch/arm/mach-bcmstb/Makefile                   |   8 +
 arch/arm/mach-bcmstb/include/mach/gpio.h        |  11 +
 arch/arm/mach-bcmstb/include/mach/hardware.h    |  11 +
 arch/arm/mach-bcmstb/include/mach/prior_stage.h |  30 ++
 arch/arm/mach-bcmstb/include/mach/sdhci.h       |  15 +
 arch/arm/mach-bcmstb/include/mach/timer.h       |  13 +
 arch/arm/mach-bcmstb/lowlevel_init.S            |  21 ++
 board/broadcom/bcmstb/MAINTAINERS               |   7 +
 board/broadcom/bcmstb/Makefile                  |   8 +
 board/broadcom/bcmstb/bcmstb.c                  | 194 +++++++++++
 configs/bcm7445_defconfig                       |  27 ++
 doc/README.bcm7xxx                              | 150 ++++++++
 drivers/mmc/Kconfig                             |  11 +
 drivers/mmc/Makefile                            |   1 +
 drivers/mmc/bcmstb_sdhci.c                      |  67 ++++
 drivers/spi/Kconfig                             |   7 +
 drivers/spi/Makefile                            |   1 +
 drivers/spi/bcmstb_spi.c                        | 439 ++++++++++++++++++++++++
 drivers/spi/spi-uclass.c                        |   2 +-
 dts/Kconfig                                     |   7 +
 include/configs/bcm7445.h                       |  26 ++
 include/configs/bcmstb.h                        | 183 ++++++++++
 include/fdtdec.h                                |   4 +
 lib/fdtdec.c                                    |   4 +
 28 files changed, 1305 insertions(+), 1 deletion(-)
 create mode 100644 arch/arm/mach-bcmstb/Kconfig
 create mode 100644 arch/arm/mach-bcmstb/Makefile
 create mode 100644 arch/arm/mach-bcmstb/include/mach/gpio.h
 create mode 100644 arch/arm/mach-bcmstb/include/mach/hardware.h
 create mode 100644 arch/arm/mach-bcmstb/include/mach/prior_stage.h
 create mode 100644 arch/arm/mach-bcmstb/include/mach/sdhci.h
 create mode 100644 arch/arm/mach-bcmstb/include/mach/timer.h
 create mode 100644 arch/arm/mach-bcmstb/lowlevel_init.S
 create mode 100644 board/broadcom/bcmstb/MAINTAINERS
 create mode 100644 board/broadcom/bcmstb/Makefile
 create mode 100644 board/broadcom/bcmstb/bcmstb.c
 create mode 100644 configs/bcm7445_defconfig
 create mode 100644 doc/README.bcm7xxx
 create mode 100644 drivers/mmc/bcmstb_sdhci.c
 create mode 100644 drivers/spi/bcmstb_spi.c
 create mode 100644 include/configs/bcm7445.h
 create mode 100644 include/configs/bcmstb.h

-- 
1.8.3.1

^ permalink raw reply	[flat|nested] 37+ messages in thread

* [U-Boot] [PATCH v4 1/1] board: arm: Add support for Broadcom BCM7445
  2018-06-08 21:59     ` [U-Boot] [PATCH v4 0/1] " Thomas Fitzsimmons
@ 2018-06-08 21:59       ` Thomas Fitzsimmons
  2018-07-11 12:42         ` [U-Boot] [U-Boot, v4, " Tom Rini
  2019-08-26 15:54         ` [U-Boot] [PATCH v4 " Bin Meng
  0 siblings, 2 replies; 37+ messages in thread
From: Thomas Fitzsimmons @ 2018-06-08 21:59 UTC (permalink / raw)
  To: u-boot

Add support for loading U-Boot on the Broadcom 7445 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@fitzsim.org>
Cc: Stefan Roese <sr@denx.de>
Cc: Tom Rini <trini@konsulko.com>
Cc: Florian Fainelli <f.fainelli@gmail.com>
---
Changes for v4:
   - Use high timer register for get_ticks
   - Move hard-coded register addresses from Kconfig to header
   - Document I-cache/D-cache expectation

 MAINTAINERS                                     |  10 +
 arch/arm/Kconfig                                |  12 +
 arch/arm/Makefile                               |   1 +
 arch/arm/mach-bcmstb/Kconfig                    |  36 ++
 arch/arm/mach-bcmstb/Makefile                   |   8 +
 arch/arm/mach-bcmstb/include/mach/gpio.h        |  11 +
 arch/arm/mach-bcmstb/include/mach/hardware.h    |  11 +
 arch/arm/mach-bcmstb/include/mach/prior_stage.h |  30 ++
 arch/arm/mach-bcmstb/include/mach/sdhci.h       |  15 +
 arch/arm/mach-bcmstb/include/mach/timer.h       |  13 +
 arch/arm/mach-bcmstb/lowlevel_init.S            |  21 ++
 board/broadcom/bcmstb/MAINTAINERS               |   7 +
 board/broadcom/bcmstb/Makefile                  |   8 +
 board/broadcom/bcmstb/bcmstb.c                  | 194 +++++++++++
 configs/bcm7445_defconfig                       |  27 ++
 doc/README.bcm7xxx                              | 150 ++++++++
 drivers/mmc/Kconfig                             |  11 +
 drivers/mmc/Makefile                            |   1 +
 drivers/mmc/bcmstb_sdhci.c                      |  67 ++++
 drivers/spi/Kconfig                             |   7 +
 drivers/spi/Makefile                            |   1 +
 drivers/spi/bcmstb_spi.c                        | 439 ++++++++++++++++++++++++
 drivers/spi/spi-uclass.c                        |   2 +-
 dts/Kconfig                                     |   7 +
 include/configs/bcm7445.h                       |  26 ++
 include/configs/bcmstb.h                        | 183 ++++++++++
 include/fdtdec.h                                |   4 +
 lib/fdtdec.c                                    |   4 +
 28 files changed, 1305 insertions(+), 1 deletion(-)
 create mode 100644 arch/arm/mach-bcmstb/Kconfig
 create mode 100644 arch/arm/mach-bcmstb/Makefile
 create mode 100644 arch/arm/mach-bcmstb/include/mach/gpio.h
 create mode 100644 arch/arm/mach-bcmstb/include/mach/hardware.h
 create mode 100644 arch/arm/mach-bcmstb/include/mach/prior_stage.h
 create mode 100644 arch/arm/mach-bcmstb/include/mach/sdhci.h
 create mode 100644 arch/arm/mach-bcmstb/include/mach/timer.h
 create mode 100644 arch/arm/mach-bcmstb/lowlevel_init.S
 create mode 100644 board/broadcom/bcmstb/MAINTAINERS
 create mode 100644 board/broadcom/bcmstb/Makefile
 create mode 100644 board/broadcom/bcmstb/bcmstb.c
 create mode 100644 configs/bcm7445_defconfig
 create mode 100644 doc/README.bcm7xxx
 create mode 100644 drivers/mmc/bcmstb_sdhci.c
 create mode 100644 drivers/spi/bcmstb_spi.c
 create mode 100644 include/configs/bcm7445.h
 create mode 100644 include/configs/bcmstb.h

diff --git a/MAINTAINERS b/MAINTAINERS
index 642c448..58634fc 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -107,6 +107,16 @@ F:	drivers/video/bcm2835.c
 F:	include/dm/platform_data/serial_bcm283x_mu.h
 F:	drivers/pinctrl/broadcom/
 
+ARM BROADCOM BCMSTB
+M:	Thomas Fitzsimmons <fitzsim@fitzsim.org>
+S:	Maintained
+F:	arch/arm/mach-bcmstb/
+F:	board/broadcom/bcmstb/
+F:	configs/bcm7445_defconfig
+F:	doc/README.bcm7xxx
+F:	drivers/mmc/bcmstb_sdhci.c
+F:	drivers/spi/bcmstb_spi.c
+
 ARM FREESCALE IMX
 M:	Stefano Babic <sbabic@denx.de>
 M:	Fabio Estevam <fabio.estevam@nxp.com>
diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig
index dde422b..fa2001b 100644
--- a/arch/arm/Kconfig
+++ b/arch/arm/Kconfig
@@ -533,6 +533,16 @@ config TARGET_VEXPRESS_CA15_TC2
 	select CPU_V7_HAS_VIRT
 	select PL011_SERIAL
 
+config ARCH_BCMSTB
+	bool "Broadcom BCM7XXX family"
+	select CPU_V7A
+	select DM
+	select OF_CONTROL
+	select OF_PRIOR_STAGE
+	help
+	  This enables support for Broadcom ARM-based set-top box
+	  chipsets, including the 7445 family of chips.
+
 config TARGET_VEXPRESS_CA5X2
 	bool "Support vexpress_ca5x2"
 	select CPU_V7A
@@ -1297,6 +1307,8 @@ source "arch/arm/mach-at91/Kconfig"
 
 source "arch/arm/mach-bcm283x/Kconfig"
 
+source "arch/arm/mach-bcmstb/Kconfig"
+
 source "arch/arm/mach-davinci/Kconfig"
 
 source "arch/arm/mach-exynos/Kconfig"
diff --git a/arch/arm/Makefile b/arch/arm/Makefile
index 680c6e8..03252fe 100644
--- a/arch/arm/Makefile
+++ b/arch/arm/Makefile
@@ -54,6 +54,7 @@ PLATFORM_CPPFLAGS += $(arch-y) $(tune-y)
 machine-$(CONFIG_ARCH_ASPEED)		+= aspeed
 machine-$(CONFIG_ARCH_AT91)		+= at91
 machine-$(CONFIG_ARCH_BCM283X)		+= bcm283x
+machine-$(CONFIG_ARCH_BCMSTB)		+= bcmstb
 machine-$(CONFIG_ARCH_DAVINCI)		+= davinci
 machine-$(CONFIG_ARCH_EXYNOS)		+= exynos
 machine-$(CONFIG_ARCH_HIGHBANK)		+= highbank
diff --git a/arch/arm/mach-bcmstb/Kconfig b/arch/arm/mach-bcmstb/Kconfig
new file mode 100644
index 0000000..6c7952f
--- /dev/null
+++ b/arch/arm/mach-bcmstb/Kconfig
@@ -0,0 +1,36 @@
+if ARCH_BCMSTB
+
+config TARGET_BCM7445
+	bool "Broadcom 7445 TSBL"
+	depends on ARCH_BCMSTB
+	help
+	  Support for the Broadcom 7445 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 SYS_CPU
+	default "armv7"
+
+config SYS_BOARD
+	default "bcmstb"
+
+config SYS_VENDOR
+	default "broadcom"
+
+config SYS_SOC
+	default "bcmstb"
+
+config SYS_CONFIG_NAME
+	default "bcm7445"
+
+config SYS_FDT_SAVE_ADDRESS
+	hex "Address to which the prior stage provided DTB will be copied"
+	default 0x1f00000
+
+config BCMSTB_SDHCI_INDEX
+	int "Index of preferred BCMSTB SDHCI alias in DTB"
+	default 1
+
+endif
diff --git a/arch/arm/mach-bcmstb/Makefile b/arch/arm/mach-bcmstb/Makefile
new file mode 100644
index 0000000..71e5727
--- /dev/null
+++ b/arch/arm/mach-bcmstb/Makefile
@@ -0,0 +1,8 @@
+# SPDX-License-Identifier: GPL-2.0+
+#
+# (C) Copyright 2018  Cisco Systems, Inc.
+#
+# Author: Thomas Fitzsimmons <fitzsim@fitzsim.org>
+#
+
+obj-y	:= lowlevel_init.o
diff --git a/arch/arm/mach-bcmstb/include/mach/gpio.h b/arch/arm/mach-bcmstb/include/mach/gpio.h
new file mode 100644
index 0000000..bffecf9
--- /dev/null
+++ b/arch/arm/mach-bcmstb/include/mach/gpio.h
@@ -0,0 +1,11 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+/*
+ * (C) Copyright 2018  Cisco Systems, Inc.
+ *
+ * Author: Thomas Fitzsimmons <fitzsim@fitzsim.org>
+ */
+
+#ifndef _BCMSTB_GPIO_H
+#define _BCMSTB_GPIO_H
+
+#endif /* _BCMSTB_GPIO_H */
diff --git a/arch/arm/mach-bcmstb/include/mach/hardware.h b/arch/arm/mach-bcmstb/include/mach/hardware.h
new file mode 100644
index 0000000..76f799d
--- /dev/null
+++ b/arch/arm/mach-bcmstb/include/mach/hardware.h
@@ -0,0 +1,11 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+/*
+ * (C) Copyright 2018  Cisco Systems, Inc.
+ *
+ * Author: Thomas Fitzsimmons <fitzsim@fitzsim.org>
+ */
+
+#ifndef _BCMSTB_HARDWARE_H
+#define _BCMSTB_HARDWARE_H
+
+#endif /* _BCMSTB_HARDWARE_H */
diff --git a/arch/arm/mach-bcmstb/include/mach/prior_stage.h b/arch/arm/mach-bcmstb/include/mach/prior_stage.h
new file mode 100644
index 0000000..6c36c68
--- /dev/null
+++ b/arch/arm/mach-bcmstb/include/mach/prior_stage.h
@@ -0,0 +1,30 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+/*
+ * (C) Copyright 2018  Cisco Systems, Inc.
+ *
+ * Author: Thomas Fitzsimmons <fitzsim@fitzsim.org>
+ */
+
+#ifndef _BCMSTB_PRIOR_STAGE_H
+#define _BCMSTB_PRIOR_STAGE_H
+
+#ifndef __ASSEMBLY__
+
+#include <linux/types.h>
+
+struct bcmstb_boot_parameters {
+	u32 r0;
+	u32 r1;
+	u32 r2;
+	u32 r3;
+	u32 sp;
+	u32 lr;
+};
+
+extern struct bcmstb_boot_parameters bcmstb_boot_parameters;
+
+extern phys_addr_t prior_stage_fdt_address;
+
+#endif /* __ASSEMBLY__ */
+
+#endif /* _BCMSTB_PRIOR_STAGE_H */
diff --git a/arch/arm/mach-bcmstb/include/mach/sdhci.h b/arch/arm/mach-bcmstb/include/mach/sdhci.h
new file mode 100644
index 0000000..243783d
--- /dev/null
+++ b/arch/arm/mach-bcmstb/include/mach/sdhci.h
@@ -0,0 +1,15 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+/*
+ * (C) Copyright 2018  Cisco Systems, Inc.
+ *
+ * Author: Thomas Fitzsimmons <fitzsim@fitzsim.org>
+ */
+
+#ifndef _BCMSTB_SDHCI_H
+#define _BCMSTB_SDHCI_H
+
+#include <linux/types.h>
+
+int bcmstb_sdhci_init(phys_addr_t regbase);
+
+#endif /* _BCMSTB_SDHCI_H */
diff --git a/arch/arm/mach-bcmstb/include/mach/timer.h b/arch/arm/mach-bcmstb/include/mach/timer.h
new file mode 100644
index 0000000..d05b4d6
--- /dev/null
+++ b/arch/arm/mach-bcmstb/include/mach/timer.h
@@ -0,0 +1,13 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+/*
+ * (C) Copyright 2018  Cisco Systems, Inc.
+ *
+ * Author: Thomas Fitzsimmons <fitzsim@fitzsim.org>
+ */
+
+#ifndef _BCMSTB_TIMER_H
+#define _BCMSTB_TIMER_H
+
+unsigned long timer_read_counter(void);
+
+#endif /* _BCMSTB_TIMER_H */
diff --git a/arch/arm/mach-bcmstb/lowlevel_init.S b/arch/arm/mach-bcmstb/lowlevel_init.S
new file mode 100644
index 0000000..aa81f70
--- /dev/null
+++ b/arch/arm/mach-bcmstb/lowlevel_init.S
@@ -0,0 +1,21 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+/*
+ * (C) Copyright 2018  Cisco Systems, Inc.
+ *
+ * Author: Thomas Fitzsimmons <fitzsim@fitzsim.org>
+ */
+
+#include <linux/linkage.h>
+
+ENTRY(save_boot_params)
+	ldr	r6, =bcmstb_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/board/broadcom/bcmstb/MAINTAINERS b/board/broadcom/bcmstb/MAINTAINERS
new file mode 100644
index 0000000..5851cb9
--- /dev/null
+++ b/board/broadcom/bcmstb/MAINTAINERS
@@ -0,0 +1,7 @@
+BCM7445 BOARD
+M:	Thomas Fitzsimmons <fitzsim@fitzsim.org>
+S:	Maintained
+F:	board/broadcom/bcmstb/
+F:	include/configs/bcmstb.h
+F:	include/configs/bcm7445.h
+F:	configs/bcm7445_defconfig
diff --git a/board/broadcom/bcmstb/Makefile b/board/broadcom/bcmstb/Makefile
new file mode 100644
index 0000000..9609887
--- /dev/null
+++ b/board/broadcom/bcmstb/Makefile
@@ -0,0 +1,8 @@
+# SPDX-License-Identifier: GPL-2.0+
+#
+# (C) Copyright 2018  Cisco Systems, Inc.
+#
+# Author: Thomas Fitzsimmons <fitzsim@fitzsim.org>
+#
+
+obj-y	:= bcmstb.o
diff --git a/board/broadcom/bcmstb/bcmstb.c b/board/broadcom/bcmstb/bcmstb.c
new file mode 100644
index 0000000..25cd354
--- /dev/null
+++ b/board/broadcom/bcmstb/bcmstb.c
@@ -0,0 +1,194 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * (C) Copyright 2018  Cisco Systems, Inc.
+ *
+ * Author: Thomas Fitzsimmons <fitzsim@fitzsim.org>
+ */
+
+#include <linux/types.h>
+#include <common.h>
+#include <asm/io.h>
+#include <asm/bootm.h>
+#include <mach/sdhci.h>
+#include <mach/timer.h>
+#include <mmc.h>
+#include <fdtdec.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+#define BCMSTB_DATA_SECTION __attribute__((section(".data")))
+
+struct bcmstb_boot_parameters bcmstb_boot_parameters BCMSTB_DATA_SECTION;
+
+phys_addr_t prior_stage_fdt_address BCMSTB_DATA_SECTION;
+
+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)
+{
+	if (fdtdec_setup_memory_size() != 0)
+		return -EINVAL;
+
+	return 0;
+}
+
+int dram_init_banksize(void)
+{
+	fdtdec_setup_memory_banksize();
+
+	/*
+	 * On this SoC, U-Boot is running as an ELF file.  Change the
+	 * relocation address to CONFIG_SYS_TEXT_BASE, so that in
+	 * setup_reloc, gd->reloc_off works out to 0, effectively
+	 * disabling relocation.  Otherwise U-Boot hangs in the setup
+	 * instructions just before relocate_code in
+	 * arch/arm/lib/crt0.S.
+	 */
+	gd->relocaddr = CONFIG_SYS_TEXT_BASE;
+
+	return 0;
+}
+
+void enable_caches(void)
+{
+	/*
+	 * This port assumes that the prior stage bootloader has
+	 * enabled I-cache and D-cache already.  Implementing this
+	 * function silences the warning in the default function.
+	 */
+}
+
+static const phys_addr_t bcmstb_sdhci_address(u32 alias_index)
+{
+	int node = 0;
+	int ret = 0;
+	char sdhci[16] = { 0 };
+	const void *fdt = gd->fdt_blob;
+	const char *path = NULL;
+	struct fdt_resource resource = { 0 };
+
+	if (!fdt) {
+		printf("%s: Invalid gd->fdt_blob\n", __func__);
+		return 0;
+	}
+
+	node = fdt_path_offset(fdt, "/aliases");
+	if (node < 0) {
+		printf("%s: Failed to find /aliases node\n", __func__);
+		return 0;
+	}
+
+	sprintf(sdhci, "sdhci%d", alias_index);
+	path = fdt_getprop(fdt, node, sdhci, NULL);
+	if (!path) {
+		printf("%s: Failed to find alias for %s\n", __func__, sdhci);
+		return 0;
+	}
+
+	node = fdt_path_offset(fdt, path);
+	if (node < 0) {
+		printf("%s: Failed to resolve BCMSTB SDHCI alias\n", __func__);
+		return 0;
+	}
+
+	ret = fdt_get_named_resource(fdt, node, "reg", "reg-names",
+				     "host", &resource);
+	if (ret) {
+		printf("%s: Failed to read BCMSTB SDHCI host resource\n",
+		       __func__);
+		return 0;
+	}
+
+	return resource.start;
+}
+
+int board_mmc_init(bd_t *bis)
+{
+	phys_addr_t sdhci_base_address = 0;
+
+	sdhci_base_address = bcmstb_sdhci_address(CONFIG_BCMSTB_SDHCI_INDEX);
+
+	if (!sdhci_base_address) {
+		sdhci_base_address = BCMSTB_SDHCI_BASE;
+		printf("%s: Assuming BCMSTB SDHCI address: 0x%p\n",
+		       __func__, (void *)sdhci_base_address);
+	}
+
+	debug("BCMSTB SDHCI base address: 0x%p\n", (void *)sdhci_base_address);
+
+	bcmstb_sdhci_init(sdhci_base_address);
+
+	return 0;
+}
+
+int timer_init(void)
+{
+	gd->arch.timer_rate_hz = readl(BCMSTB_TIMER_FREQUENCY);
+
+	return 0;
+}
+
+ulong get_tbclk(void)
+{
+	return gd->arch.timer_rate_hz;
+}
+
+uint64_t get_ticks(void)
+{
+	gd->timebase_h = readl(BCMSTB_TIMER_HIGH);
+	gd->timebase_l = readl(BCMSTB_TIMER_LOW);
+
+	return ((uint64_t)gd->timebase_h << 32) | gd->timebase_l;
+}
+
+int board_late_init(void)
+{
+	debug("Arguments from prior stage bootloader:\n");
+	debug("General Purpose Register 0: 0x%x\n", bcmstb_boot_parameters.r0);
+	debug("General Purpose Register 1: 0x%x\n", bcmstb_boot_parameters.r1);
+	debug("General Purpose Register 2: 0x%x\n", bcmstb_boot_parameters.r2);
+	debug("General Purpose Register 3: 0x%x\n", bcmstb_boot_parameters.r3);
+	debug("Stack Pointer Register:     0x%x\n", bcmstb_boot_parameters.sp);
+	debug("Link Register:              0x%x\n", bcmstb_boot_parameters.lr);
+	debug("Assuming timer frequency register at: 0x%p\n",
+	      (void *)BCMSTB_TIMER_FREQUENCY);
+	debug("Read timer frequency (in Hz): %ld\n", gd->arch.timer_rate_hz);
+	debug("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 (bcmstb_boot_parameters.r1)
+	 * because we're using a device tree to boot Linux.
+	 */
+
+	return 0;
+}
diff --git a/configs/bcm7445_defconfig b/configs/bcm7445_defconfig
new file mode 100644
index 0000000..46dea17
--- /dev/null
+++ b/configs/bcm7445_defconfig
@@ -0,0 +1,27 @@
+CONFIG_ARM=y
+CONFIG_ARCH_BCMSTB=y
+CONFIG_TARGET_BCM7445=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_BCMSTB_SPI=y
+CONFIG_FIT=y
+CONFIG_FIT_SIGNATURE=y
+CONFIG_RSA=y
+CONFIG_BLK=n
+CONFIG_SDHCI=y
+CONFIG_MMC_SDHCI=y
+CONFIG_MMC_SDHCI_BCMSTB=y
+CONFIG_CONS_INDEX=3
+CONFIG_BOOTDELAY=1
+CONFIG_SYS_PROMPT="U-Boot>"
+CONFIG_HUSH_PARSER=y
+CONFIG_SYS_TEXT_BASE=0x80100000
+CONFIG_SYS_NS16550_COM3=0xf040ab00
+CONFIG_EFI_LOADER=n
diff --git a/doc/README.bcm7xxx b/doc/README.bcm7xxx
new file mode 100644
index 0000000..9b5eae4
--- /dev/null
+++ b/doc/README.bcm7xxx
@@ -0,0 +1,150 @@
+Summary
+=======
+
+This document describes how to use U-Boot on the Broadcom 7445 SoC, as
+a third stage bootloader loaded by Broadcom's BOLT bootloader.
+
+BOLT loads U-Boot as a generic ELF binary.  Some U-Boot features such
+as networking are not yet available but other important features are,
+including:
+
+   - ext4 file system traversal
+
+   - support for loading FIT images
+
+   - advanced scripting
+
+   - support for FIT-provided DTBs instead of relying on the
+     BOLT-provided DTB
+
+A customized version of this port has been used in production.  The
+same approach may work on other BCM7xxx boards, with some
+configuration adjustments and memory layout experimentation.
+
+Build
+=====
+
+make bcm7445_defconfig
+make
+${CROSS_COMPILE}strip u-boot
+
+Run
+===
+
+Flash the u-boot binary into board storage, then invoke it from BOLT.
+For example:
+
+BOLT> boot -bsu -elf flash0.u-boot1
+
+This port assumes that I-cache and D-cache are already enabled when
+U-Boot is entered.
+
+Flattened Image Tree Support
+============================
+
+What follows is an example FIT image source file.  Build it with:
+
+mkimage -f image.its image.itb
+
+Booting the resulting image.itb was tested on BOLT v1.20, with the
+following kernels:
+
+https://github.com/Broadcom/stblinux-3.14
+https://github.com/Broadcom/stblinux-4.1
+https://github.com/Broadcom/stblinux-4.9
+
+and with a generic ARMv7 root file system.
+
+image.its:
+/dts-v1/;
+/ {
+	description = "BCM7445 FIT";
+	images {
+		kernel at 1 {
+			description = "Linux kernel";
+			/*
+			 * This kernel image output format can be
+			 * generated with:
+			 *
+			 * make vmlinux
+			 * ${CROSS_COMPILE}objcopy -O binary -S vmlinux vmlinux.bin
+			 * gzip -9 vmlinux.bin
+			 *
+			 * For stblinux-3.14, the specific Broadcom
+			 * board type should be configured in the
+			 * kernel, for example CONFIG_BCM7445D0=y.
+			 */
+			data = /incbin/("<vmlinux.bin.gz>");
+			type = "kernel";
+			arch = "arm";
+			os = "linux";
+			compression = "gzip";
+			load = <0x8000>;
+			entry = <0x8000>;
+			hash at 1 {
+				algo = "sha256";
+			};
+		};
+		ramdisk at 1 {
+			description = "Initramfs root file system";
+			data = /incbin/("<initramfs.cpio.gz>");
+			type = "ramdisk";
+			arch = "arm";
+			os = "linux";
+			compression = "gzip";
+			/*
+			 * Set the environment variable initrd_high to
+			 * 0xffffffff, and set "load" and "entry" here
+			 * to 0x0 to keep initramfs in-place and to
+			 * accommodate stblinux bmem/CMA reservations.
+			 */
+			load = <0x0>;
+			entry = <0x0>;
+			hash at 1 {
+				algo = "sha256";
+			};
+		};
+		fdt at 1 {
+			description = "Device tree dumped from BOLT";
+			/*
+			 * This DTB should be similar to the
+			 * BOLT-generated device tree, after BOLT has
+			 * done its runtime modifications to it.  For
+			 * example, it can be dumped from within
+			 * U-Boot (at ${fdtcontroladdr}), after BOLT
+			 * has loaded U-Boot.  The result can be added
+			 * to the Linux source tree as a .dts file.
+			 *
+			 * To support modifications to the device tree
+			 * in-place in U-Boot, add to Linux's
+			 * arch/arm/boot/dts/Makefile:
+			 *
+			 * DTC_FLAGS ?= -p 4096
+			 *
+			 * This will leave some padding in the DTB and
+			 * thus reserve room for node additions.
+			 *
+			 * Also, set the environment variable fdt_high
+			 * to 0xffffffff to keep the DTB in-place and
+			 * to accommodate stblinux bmem/CMA
+			 * reservations.
+			 */
+			data = /incbin/("<bolt-<version>.dtb");
+			type = "flat_dt";
+			arch = "arm";
+			compression = "none";
+			hash at 1 {
+				algo = "sha256";
+			};
+		};
+	};
+	configurations {
+		default = "conf at bcm7445";
+		conf at bcm7445 {
+			description = "BCM7445 configuration";
+			kernel = "kernel at 1";
+			ramdisk = "ramdisk at 1";
+			fdt = "fdt at 1";
+		};
+	};
+};
diff --git a/drivers/mmc/Kconfig b/drivers/mmc/Kconfig
index 693b3ce..377b1c4 100644
--- a/drivers/mmc/Kconfig
+++ b/drivers/mmc/Kconfig
@@ -379,6 +379,17 @@ config MMC_SDHCI_BCM2835
 
 	  If unsure, say N.
 
+config MMC_SDHCI_BCMSTB
+	tristate "SDHCI support for the BCMSTB SD/MMC Controller"
+	depends on MMC_SDHCI
+	help
+	  This selects the Broadcom set-top box SD/MMC controller.
+
+	  If you have a BCMSTB platform with SD or MMC devices,
+	  say Y here.
+
+	  If unsure, say N.
+
 config MMC_SDHCI_CADENCE
 	bool "SDHCI support for the Cadence SD/SDIO/eMMC controller"
 	depends on BLK && DM_MMC
diff --git a/drivers/mmc/Makefile b/drivers/mmc/Makefile
index 3a9805d..f619186 100644
--- a/drivers/mmc/Makefile
+++ b/drivers/mmc/Makefile
@@ -45,6 +45,7 @@ obj-$(CONFIG_STM32_SDMMC2) += stm32_sdmmc2.o
 obj-$(CONFIG_MMC_SDHCI)			+= sdhci.o
 obj-$(CONFIG_MMC_SDHCI_ATMEL)		+= atmel_sdhci.o
 obj-$(CONFIG_MMC_SDHCI_BCM2835)		+= bcm2835_sdhci.o
+obj-$(CONFIG_MMC_SDHCI_BCMSTB)		+= bcmstb_sdhci.o
 obj-$(CONFIG_MMC_SDHCI_CADENCE)		+= sdhci-cadence.o
 obj-$(CONFIG_MMC_SDHCI_KONA)		+= kona_sdhci.o
 obj-$(CONFIG_MMC_SDHCI_MSM)		+= msm_sdhci.o
diff --git a/drivers/mmc/bcmstb_sdhci.c b/drivers/mmc/bcmstb_sdhci.c
new file mode 100644
index 0000000..443ae8d
--- /dev/null
+++ b/drivers/mmc/bcmstb_sdhci.c
@@ -0,0 +1,67 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * (C) Copyright 2018  Cisco Systems, Inc.
+ *
+ * Author: Thomas Fitzsimmons <fitzsim@fitzsim.org>
+ */
+
+#include <common.h>
+#include <mach/sdhci.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("%s: Failed to allocate memory\n", __func__);
+		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 3532c2a..f5960a7 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 "BCMSTB 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 5a2c00e..e73b0cd 100644
--- a/drivers/spi/Makefile
+++ b/drivers/spi/Makefile
@@ -18,6 +18,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..fb1dc46
--- /dev/null
+++ b/drivers/spi/bcmstb_spi.c
@@ -0,0 +1,439 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * (C) Copyright 2018  Cisco Systems, Inc.
+ *
+ * Author: Thomas Fitzsimmons <fitzsim@fitzsim.org>
+ */
+
+#include <asm/io.h>
+#include <command.h>
+#include <config.h>
+#include <dm.h>
+#include <errno.h>
+#include <fdtdec.h>
+#include <linux/bitops.h>
+#include <linux/delay.h>
+#include <log.h>
+#include <malloc.h>
+#include <spi.h>
+#include <time.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
+
+/* hif_mspi register structure. */
+struct bcmstb_hif_mspi_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 */
+	u32 write_lock;		/* 0x180 */
+};
+
+/* hif_mspi masks. */
+#define HIF_MSPI_SPCR2_CONT_AFTER_CMD_MASK	0x00000080
+#define HIF_MSPI_SPCR2_SPE_MASK			0x00000040
+#define HIF_MSPI_SPCR2_SPIFIE_MASK		0x00000020
+#define HIF_MSPI_WRITE_LOCK_WRITE_LOCK_MASK	0x00000001
+
+/* bspi offsets. */
+#define BSPI_MAST_N_BOOT_CTRL			0x008
+
+/* bspi_raf is not used in this driver. */
+
+/* hif_spi_intr2 offsets and masks. */
+#define HIF_SPI_INTR2_CPU_CLEAR			0x08
+#define HIF_SPI_INTR2_CPU_MASK_SET		0x10
+#define HIF_SPI_INTR2_CPU_MASK_CLEAR		0x14
+#define HIF_SPI_INTR2_CPU_SET_MSPI_DONE_MASK	0x00000020
+
+/* SPI transfer timeout in milliseconds. */
+#define HIF_MSPI_WAIT				10
+
+enum bcmstb_base_type {
+	HIF_MSPI,
+	BSPI,
+	HIF_SPI_INTR2,
+	CS_REG,
+	BASE_LAST,
+};
+
+struct bcmstb_spi_platdata {
+	void *base[4];
+};
+
+struct bcmstb_spi_priv {
+	struct bcmstb_hif_mspi_regs *regs;
+	void *bspi;
+	void *hif_spi_intr2;
+	void *cs_reg;
+	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;
+};
+
+static int bcmstb_spi_ofdata_to_platdata(struct udevice *bus)
+{
+	struct bcmstb_spi_platdata *plat = dev_get_platdata(bus);
+	const void *fdt = gd->fdt_blob;
+	int node = dev_of_offset(bus);
+	int ret = 0;
+	int i = 0;
+	struct fdt_resource resource = { 0 };
+	char *names[BASE_LAST] = { "hif_mspi", "bspi", "hif_spi_intr2",
+				   "cs_reg" };
+	const phys_addr_t defaults[BASE_LAST] = { BCMSTB_HIF_MSPI_BASE,
+						  BCMSTB_BSPI_BASE,
+						  BCMSTB_HIF_SPI_INTR2,
+						  BCMSTB_CS_REG };
+
+	for (i = 0; i < BASE_LAST; i++) {
+		plat->base[i] = (void *)defaults[i];
+
+		ret = fdt_get_named_resource(fdt, node, "reg", "reg-names",
+					     names[i], &resource);
+		if (ret) {
+			printf("%s: Assuming BCMSTB SPI %s address 0x0x%p\n",
+			       __func__, names[i], (void *)defaults[i]);
+		} else {
+			plat->base[i] = (void *)resource.start;
+			debug("BCMSTB SPI %s address: 0x0x%p\n",
+			      names[i], (void *)plat->base[i]);
+		}
+	}
+
+	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(void *base, u32 mask)
+{
+	void *reg = base + HIF_SPI_INTR2_CPU_MASK_CLEAR;
+
+	writel(readl(reg) | mask, reg);
+	readl(reg);
+}
+
+static void bcmstb_spi_disable_interrupt(void *base, u32 mask)
+{
+	void *reg = base + HIF_SPI_INTR2_CPU_MASK_SET;
+
+	writel(readl(reg) | mask, reg);
+	readl(reg);
+}
+
+static void bcmstb_spi_clear_interrupt(void *base, u32 mask)
+{
+	void *reg = base + HIF_SPI_INTR2_CPU_CLEAR;
+
+	writel(readl(reg) | mask, reg);
+	readl(reg);
+}
+
+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->base[HIF_MSPI];
+	priv->bspi = plat->base[BSPI];
+	priv->hif_spi_intr2 = plat->base[HIF_SPI_INTR2];
+	priv->cs_reg = plat->base[CS_REG];
+	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;
+
+	debug("spi_xfer: tx regs: 0x%p\n", &priv->regs->txram[0]);
+	debug("spi_xfer: rx regs: 0x%p\n", &priv->regs->rxram[0]);
+
+	/* Disable BSPI. */
+	writel(1, priv->bspi + BSPI_MAST_N_BOOT_CTRL);
+	readl(priv->bspi + BSPI_MAST_N_BOOT_CTRL);
+
+	/* Set up interrupts. */
+	bcmstb_spi_disable_interrupt(priv->hif_spi_intr2, 0xffffffff);
+	bcmstb_spi_clear_interrupt(priv->hif_spi_intr2, 0xffffffff);
+	bcmstb_spi_enable_interrupt(priv->hif_spi_intr2,
+				    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(HIF_MSPI_SPCR2_SPIFIE_MASK, &priv->regs->spcr2);
+	writel(0, &priv->regs->spcr3);
+
+	bcmstb_spi_hw_set_parms(priv);
+
+	return 0;
+}
+
+static void bcmstb_spi_submit(struct bcmstb_spi_priv *priv, bool done)
+{
+	debug("WR NEWQP: %d\n", 0);
+	writel(0, &priv->regs->newqp);
+
+	debug("WR ENDQP: %d\n", priv->tx_slot - 1);
+	writel(priv->tx_slot - 1, &priv->regs->endqp);
+
+	if (done) {
+		debug("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) {
+		debug("spi_xfer: switching chip select to %d\n",
+		      priv->default_cs);
+		writel((readl(priv->cs_reg) & ~0xff) | (1 << priv->default_cs),
+		       priv->cs_reg);
+		readl(priv->cs_reg);
+		udelay(10);
+		priv->curr_cs = priv->default_cs;
+	}
+
+	debug("WR WRITE_LOCK: %02x\n", 1);
+	writel((readl(&priv->regs->write_lock) &
+		~HIF_MSPI_WRITE_LOCK_WRITE_LOCK_MASK) | 1,
+	       &priv->regs->write_lock);
+	readl(&priv->regs->write_lock);
+
+	debug("WR SPCR2: %02x\n",
+	      HIF_MSPI_SPCR2_SPIFIE_MASK |
+	      HIF_MSPI_SPCR2_SPE_MASK |
+	      HIF_MSPI_SPCR2_CONT_AFTER_CMD_MASK);
+	writel(HIF_MSPI_SPCR2_SPIFIE_MASK |
+	       HIF_MSPI_SPCR2_SPE_MASK |
+	       HIF_MSPI_SPCR2_CONT_AFTER_CMD_MASK,
+	       &priv->regs->spcr2);
+}
+
+static int bcmstb_spi_wait(struct bcmstb_spi_priv *priv)
+{
+	u32 start_time = get_timer(0);
+	u32 status = readl(&priv->regs->mspi_status);
+
+	while (!(status & 1)) {
+		if (get_timer(start_time) > HIF_MSPI_WAIT)
+			return -ETIMEDOUT;
+		status = readl(&priv->regs->mspi_status);
+	}
+
+	writel(readl(&priv->regs->mspi_status) & ~1, &priv->regs->mspi_status);
+	bcmstb_spi_clear_interrupt(priv->hif_spi_intr2,
+				   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_hif_mspi_regs *regs = priv->regs;
+
+	debug("spi_xfer: %d, t: 0x%p, r: 0x%p, f: %lx\n",
+	      len, dout, din, flags);
+	debug("spi_xfer: chip select: %x\n", readl(priv->cs_reg) & 0xff);
+	debug("spi_xfer: tx addr: 0x%p\n", &regs->txram[0]);
+	debug("spi_xfer: rx addr: 0x%p\n", &regs->rxram[0]);
+	debug("spi_xfer: cd addr: 0x%p\n", &regs->cdram[0]);
+
+	if (flags & SPI_XFER_END) {
+		debug("spi_xfer: clearing saved din address: 0x%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("%s: Non-byte-aligned transfer\n", __func__);
+		return -EOPNOTSUPP;
+	}
+
+	if (flags & ~(SPI_XFER_BEGIN | SPI_XFER_END)) {
+		printf("%s: Unsupported flags: %lx\n", __func__, flags);
+		return -EOPNOTSUPP;
+	}
+
+	if (flags & SPI_XFER_BEGIN) {
+		priv->tx_slot = 0;
+		priv->rx_slot = 0;
+
+		if (out_bytes && len > NUM_CDRAM) {
+			printf("%s: Unable to save transfer\n", __func__);
+			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.
+			 */
+			debug("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 ret = 0;
+
+			debug("spi_xfer: Making recursive call\n");
+			ret = bcmstb_spi_xfer(dev, priv->saved_cmd_len * 8,
+					      priv->saved_cmd, NULL,
+					      SPI_XFER_BEGIN);
+			if (ret) {
+				printf("%s: Recursive call failed\n", __func__);
+				return ret;
+			}
+		} else {
+			debug("spi_xfer: saving din address: 0x%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);
+			debug("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,
+			       &regs->txram[priv->tx_slot << 1]);
+			debug("WR CDRAM[%d]: %02x\n", priv->tx_slot, 0x8e);
+			writel(0x8e, &regs->cdram[priv->tx_slot]);
+			priv->tx_slot++;
+			tx_len--;
+			if (!in_bytes)
+				rx_len--;
+		}
+
+		debug("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(priv) == -ETIMEDOUT) {
+			printf("%s: Timed out\n", __func__);
+			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(&regs->rxram[(priv->rx_slot << 1)
+							   + 1])
+					& 0xff;
+				debug("RD RXRAM[%d]: %02x\n",
+				      priv->rx_slot, in_bytes[len - rx_len]);
+				priv->rx_slot++;
+				rx_len--;
+			}
+		}
+	}
+
+	if (flags & SPI_XFER_END) {
+		debug("WR WRITE_LOCK: %02x\n", 0);
+		writel((readl(&priv->regs->write_lock) &
+			~HIF_MSPI_WRITE_LOCK_WRITE_LOCK_MASK) | 0,
+		       &priv->regs->write_lock);
+		readl(&priv->regs->write_lock);
+	}
+
+	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 = {
+	.xfer		= bcmstb_spi_xfer,
+	.set_speed	= bcmstb_spi_set_speed,
+	.set_mode	= bcmstb_spi_set_mode,
+};
+
+static const struct udevice_id bcmstb_spi_id[] = {
+	{ .compatible = "brcm,spi-brcmstb" },
+	{ }
+};
+
+U_BOOT_DRIVER(bcmstb_spi) = {
+	.name				= "bcmstb_spi",
+	.id				= UCLASS_SPI,
+	.of_match			= bcmstb_spi_id,
+	.ops				= &bcmstb_spi_ops,
+	.ofdata_to_platdata		= bcmstb_spi_ofdata_to_platdata,
+	.probe				= bcmstb_spi_probe,
+	.platdata_auto_alloc_size	= sizeof(struct bcmstb_spi_platdata),
+	.priv_auto_alloc_size		= sizeof(struct bcmstb_spi_priv),
+};
diff --git a/drivers/spi/spi-uclass.c b/drivers/spi/spi-uclass.c
index d2d091f..c517d06 100644
--- a/drivers/spi/spi-uclass.c
+++ b/drivers/spi/spi-uclass.c
@@ -273,7 +273,7 @@ int spi_get_bus_and_cs(int busnum, int cs, int speed, int mode,
 	bool created = false;
 	int ret;
 
-#if CONFIG_IS_ENABLED(OF_PLATDATA)
+#if CONFIG_IS_ENABLED(OF_PLATDATA) || CONFIG_IS_ENABLED(OF_PRIOR_STAGE)
 	ret = uclass_first_device_err(UCLASS_SPI, &bus);
 #else
 	ret = uclass_get_device_by_seq(UCLASS_SPI, busnum, &bus);
diff --git a/dts/Kconfig b/dts/Kconfig
index 0cef225..a1a92f2 100644
--- a/dts/Kconfig
+++ b/dts/Kconfig
@@ -101,6 +101,13 @@ 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, the device tree used for DT
+	  control will be read from a device tree binary, at a memory
+	  location passed to U-Boot by the prior stage bootloader.
+
 endchoice
 
 config DEFAULT_DEVICE_TREE
diff --git a/include/configs/bcm7445.h b/include/configs/bcm7445.h
new file mode 100644
index 0000000..f720035
--- /dev/null
+++ b/include/configs/bcm7445.h
@@ -0,0 +1,26 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+/*
+ * (C) Copyright 2018  Cisco Systems, Inc.
+ *
+ * Author: Thomas Fitzsimmons <fitzsim@fitzsim.org>
+ *
+ * Configuration settings for the Broadcom BCM7445 SoC family.
+ */
+
+#ifndef __CONFIG_H
+#define __CONFIG_H
+
+#include "bcmstb.h"
+
+#define CONFIG_SYS_NS16550_COM3	0xf040ab00
+
+#define BCMSTB_SDHCI_BASE	0xf03e0200
+#define BCMSTB_TIMER_LOW	0xf0412008
+#define BCMSTB_TIMER_HIGH	0xf041200c
+#define BCMSTB_TIMER_FREQUENCY	0xf0412020
+#define BCMSTB_HIF_MSPI_BASE	0xf03e3400
+#define BCMSTB_BSPI_BASE	0xf03e3200
+#define BCMSTB_HIF_SPI_INTR2	0xf03e1a00
+#define BCMSTB_CS_REG		0xf03e0920
+
+#endif	/* __CONFIG_H */
diff --git a/include/configs/bcmstb.h b/include/configs/bcmstb.h
new file mode 100644
index 0000000..8c61780
--- /dev/null
+++ b/include/configs/bcmstb.h
@@ -0,0 +1,183 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+/*
+ * (C) Copyright 2018  Cisco Systems, Inc.
+ *
+ * Author: Thomas Fitzsimmons <fitzsim@fitzsim.org>
+ *
+ * Configuration settings for the Broadcom BCMSTB SoC family.
+ */
+
+#ifndef __BCMSTB_H
+#define __BCMSTB_H
+
+#include "version.h"
+#include <linux/sizes.h>
+#include <asm/arch/prior_stage.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 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]
+ *	 0x0200 0000	FIT containing ramdisk and device tree
+ *             :	  initramfs.cpio.gz
+ *	       :	  [~208 MiB uncompressed max, to CMA/bmem low address]
+ *	       :	  [~80 MiB compressed max, to PSB low address]
+ *             :	  device tree binary
+ *             :	  [~60 KiB]
+ *	 0x0700 0000	Prior stage bootloader (PSB)
+ *	       :
+ *	 0x0761 7000	Prior-stage-provided device tree binary (DTB)
+ *	       :	[~40 KiB in size]
+ *	 0x0f00 0000	Contiguous memory allocator (CMA/bmem) low address
+ *	       :
+ *	 0x8010 0000	U-Boot code at ELF load address
+ *	       :	[~500 KiB in size, stripped]
+ *	 0xc000 0000	Top of RAM
+ *
+ * Setting gd->relocaddr to CONFIG_SYS_TEXT_BASE in dram_init_banksize
+ * prevents U-Boot from relocating itself when it is run as an ELF
+ * program by the prior stage bootloader.
+ *
+ * We want to keep the ramdisk and FDT in the FIT image in-place, to
+ * accommodate stblinux's bmem and CMA regions.  To accomplish this,
+ * we set initrd_high and fdt_high to 0xffffffff, and the load and
+ * entry addresses of the FIT ramdisk entry to 0x0.
+ *
+ * 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.
+ */
+#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
+
+/*
+ * Large kernel image bootm configuration.
+ */
+#define CONFIG_SYS_BOOTM_LEN		SZ_64M
+
+/*
+ * 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
+
+#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
+
+/*
+ * Flash configuration.
+ */
+#define CONFIG_ST_SMI
+#define CONFIG_SPI_FLASH_STMICRO
+#define CONFIG_SPI_FLASH_MACRONIX
+
+/*
+ * 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
+
+/*
+ * Save the prior stage provided DTB.
+ */
+#define CONFIG_PREBOOT					\
+	"fdt addr ${fdtcontroladdr};"			\
+	"fdt move ${fdtcontroladdr} ${fdtsaveaddr};"	\
+	"fdt addr ${fdtsaveaddr};"
+/*
+ * Enable in-place RFS with this initrd_high setting.
+ */
+#define CONFIG_EXTRA_ENV_SETTINGS					\
+	"fdtsaveaddr=" __stringify(CONFIG_SYS_FDT_SAVE_ADDRESS) "\0"	\
+	"initrd_high=0xffffffff\0"					\
+	"fdt_high=0xffffffff\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 /* __BCMSTB_H */
diff --git a/include/fdtdec.h b/include/fdtdec.h
index c15b2a0..ff1c5f5 100644
--- a/include/fdtdec.h
+++ b/include/fdtdec.h
@@ -47,6 +47,10 @@ struct fdt_memory {
 #define SPL_BUILD	0
 #endif
 
+#if CONFIG_IS_ENABLED(OF_PRIOR_STAGE)
+extern phys_addr_t prior_stage_fdt_address;
+#endif
+
 /*
  * Information about a resource. start is the first address of the resource
  * and end is the last address (inclusive). The length of the resource will
diff --git a/lib/fdtdec.c b/lib/fdtdec.c
index f4e8dbf..b29b283 100644
--- a/lib/fdtdec.c
+++ b/lib/fdtdec.c
@@ -1323,8 +1323,12 @@ int fdtdec_setup(void)
 # endif
 # ifndef CONFIG_SPL_BUILD
 	/* Allow the early environment to override the fdt address */
+#  if CONFIG_IS_ENABLED(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

^ permalink raw reply related	[flat|nested] 37+ messages in thread

* [U-Boot] [PATCH v3 1/1] board: arm: Add support for Broadcom BCM7445
  2018-06-07 16:54       ` Florian Fainelli
@ 2018-06-08 22:25         ` Thomas Fitzsimmons
  0 siblings, 0 replies; 37+ messages in thread
From: Thomas Fitzsimmons @ 2018-06-08 22:25 UTC (permalink / raw)
  To: u-boot

Florian Fainelli <f.fainelli@gmail.com> writes:

> On 06/06/2018 11:35 AM, Thomas Fitzsimmons wrote:
>> Add support for loading U-Boot on the Broadcom 7445 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@fitzsim.org>
>> Cc: Stefan Roese <sr@denx.de>
>> Cc: Tom Rini <trini@konsulko.com>
>> Cc: Florian Fainelli <f.fainelli@gmail.com>
>> ---
>
> Looks good, still some minor comments about the choice of representation
> for physical addresses of peripherals, see below.
>
>> +config BCMSTB_TIMER_LOW
>> +	hex "Address of BCMSTB timer low register"
>> +	default 0xf0412008
>
> This looks very simplistic here since the CPU system control timer is a
> 64-bit timer.

This worked via the default get_ticks implementation in lib/time.c,
which tracks rollovers and converts to a 64-bit value.  But I agree it's
better to use the high timer register, so that (among other reasons)
get_ticks reflects total uptime including time spent in BOLT.  I
overrode get_ticks in v4 of the patch to use the high and low timer
registers.

> I am really not a big fan of all of those configurable addresses which
> are a) fixed given a specific SoC family (7445, 7439 etc.) and b) are
> error prone because we let an user change those without necessarily
> knowing what is the implication. I really think sticking those constants
> into a header file would be much more appropriate.

Makes sense, moved to a 7445-specific header in v4.

>> +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.
>> +	 */
>
> This heavily depends on how you load your binary from BOLT, so you must
> be careful about this statement here.

In v4 I adjusted the comment and added an entry to the README to
document the expectation.

Thanks,
Thomas

^ permalink raw reply	[flat|nested] 37+ messages in thread

* [U-Boot] [U-Boot, v4, 1/1] board: arm: Add support for Broadcom BCM7445
  2018-06-08 21:59       ` [U-Boot] [PATCH v4 1/1] " Thomas Fitzsimmons
@ 2018-07-11 12:42         ` Tom Rini
  2019-08-26 15:54         ` [U-Boot] [PATCH v4 " Bin Meng
  1 sibling, 0 replies; 37+ messages in thread
From: Tom Rini @ 2018-07-11 12:42 UTC (permalink / raw)
  To: u-boot

On Fri, Jun 08, 2018 at 05:59:45PM -0400, Thomas Fitzsimmons wrote:

> Add support for loading U-Boot on the Broadcom 7445 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@fitzsim.org>
> Cc: Stefan Roese <sr@denx.de>
> Cc: Tom Rini <trini@konsulko.com>
> Cc: Florian Fainelli <f.fainelli@gmail.com>

Applied to u-boot/master, thanks!

-- 
Tom
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 819 bytes
Desc: not available
URL: <http://lists.denx.de/pipermail/u-boot/attachments/20180711/768667e4/attachment.sig>

^ permalink raw reply	[flat|nested] 37+ messages in thread

* [U-Boot] [PATCH v2 0/1] board: arm: Add support for Broadcom BCM7445
  2018-05-24  1:24 ` [U-Boot] [PATCH v2 0/1] board: arm: Add support for Broadcom BCM7445 Thomas Fitzsimmons
  2018-05-24  1:24   ` [U-Boot] [PATCH v2 1/1] " Thomas Fitzsimmons
  2018-06-06 18:35   ` [U-Boot] [PATCH v3 0/1] " Thomas Fitzsimmons
@ 2019-08-26 15:50   ` Bin Meng
  2 siblings, 0 replies; 37+ messages in thread
From: Bin Meng @ 2019-08-26 15:50 UTC (permalink / raw)
  To: u-boot

On Thu, May 24, 2018 at 9:24 AM Thomas Fitzsimmons <fitzsim@fitzsim.org> wrote:
>
> Add support for Broadcom BCM7445
>
> Changes for v2:
>    - Reorganize Kconfig to create ARCH_BCMSTB
>    - Use generic bcmstb SoC name wherever possible
>    - Eliminate crt0.S changes by moving relocation logic to bcmstb.c
>    - Use debug() macro where appropriate
>    - Read bcmstb_spi register base addresses from prior stage device
>      tree, where possible
>    - Read bcmstb_sdhci register base address from prior stage DT
>    - Make timer register addresses configurable
>    - Fix BOLT typos
>    - Eliminate CONFIG_BCMSTB_ACCOMMODATE_STBLINUX by keeping FIT
>      initramfs and device tree binary in-place
>    - Add README.bcm7xxx
>    - Read memory configuration from prior stage device tree
>    - Add CONFIG_OF_PRIOR_STAGE support in spi-uclass.c
>    - Fix issues reported by checkpatch.pl
>    - Fix issues reported by sparse
>    - Update some comments and formatting
>    - Add a MAINTAINERS file
>
> Thomas Fitzsimmons (1):
>   board: arm: Add support for Broadcom BCM7445
>
>  arch/arm/Kconfig                                |  12 +
>  arch/arm/Makefile                               |   1 +
>  arch/arm/mach-bcmstb/Kconfig                    |  64 ++++
>  arch/arm/mach-bcmstb/Makefile                   |   9 +
>  arch/arm/mach-bcmstb/include/mach/gpio.h        |  12 +
>  arch/arm/mach-bcmstb/include/mach/hardware.h    |  12 +
>  arch/arm/mach-bcmstb/include/mach/prior_stage.h |  31 ++
>  arch/arm/mach-bcmstb/include/mach/sdhci.h       |  16 +
>  arch/arm/mach-bcmstb/include/mach/timer.h       |  14 +
>  arch/arm/mach-bcmstb/lowlevel_init.S            |  22 ++
>  board/broadcom/bcmstb/MAINTAINERS               |   6 +
>  board/broadcom/bcmstb/Makefile                  |   9 +
>  board/broadcom/bcmstb/bcmstb.c                  | 192 +++++++++++
>  configs/bcm7445_defconfig                       |  27 ++
>  doc/README.bcm7xxx                              | 147 ++++++++
>  drivers/mmc/Kconfig                             |  11 +
>  drivers/mmc/Makefile                            |   1 +
>  drivers/mmc/bcmstb_sdhci.c                      |  68 ++++
>  drivers/spi/Kconfig                             |   7 +
>  drivers/spi/Makefile                            |   1 +
>  drivers/spi/bcmstb_spi.c                        | 440 ++++++++++++++++++++++++
>  drivers/spi/spi-uclass.c                        |   2 +-
>  dts/Kconfig                                     |   7 +
>  include/configs/bcmstb.h                        | 189 ++++++++++
>  include/fdtdec.h                                |   4 +
>  lib/fdtdec.c                                    |   4 +
>  26 files changed, 1307 insertions(+), 1 deletion(-)
>  create mode 100644 arch/arm/mach-bcmstb/Kconfig
>  create mode 100644 arch/arm/mach-bcmstb/Makefile
>  create mode 100644 arch/arm/mach-bcmstb/include/mach/gpio.h
>  create mode 100644 arch/arm/mach-bcmstb/include/mach/hardware.h
>  create mode 100644 arch/arm/mach-bcmstb/include/mach/prior_stage.h
>  create mode 100644 arch/arm/mach-bcmstb/include/mach/sdhci.h
>  create mode 100644 arch/arm/mach-bcmstb/include/mach/timer.h
>  create mode 100644 arch/arm/mach-bcmstb/lowlevel_init.S
>  create mode 100644 board/broadcom/bcmstb/MAINTAINERS
>  create mode 100644 board/broadcom/bcmstb/Makefile
>  create mode 100644 board/broadcom/bcmstb/bcmstb.c
>  create mode 100644 configs/bcm7445_defconfig
>  create mode 100644 doc/README.bcm7xxx
>  create mode 100644 drivers/mmc/bcmstb_sdhci.c
>  create mode 100644 drivers/spi/bcmstb_spi.c
>  create mode 100644 include/configs/bcmstb.h
>

I am tracing an issue that lead me to this commit, a huge single
commit that changes everywhere. We should not have such a commit
merged, sigh.

Regards,
Bin

^ permalink raw reply	[flat|nested] 37+ messages in thread

* [U-Boot] [PATCH v4 1/1] board: arm: Add support for Broadcom BCM7445
  2018-06-08 21:59       ` [U-Boot] [PATCH v4 1/1] " Thomas Fitzsimmons
  2018-07-11 12:42         ` [U-Boot] [U-Boot, v4, " Tom Rini
@ 2019-08-26 15:54         ` Bin Meng
  2019-08-27 22:31           ` Thomas Fitzsimmons
  1 sibling, 1 reply; 37+ messages in thread
From: Bin Meng @ 2019-08-26 15:54 UTC (permalink / raw)
  To: u-boot

Hi Thomas,

On Sat, Jun 9, 2018 at 6:06 AM Thomas Fitzsimmons <fitzsim@fitzsim.org> wrote:
>
> Add support for loading U-Boot on the Broadcom 7445 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@fitzsim.org>
> Cc: Stefan Roese <sr@denx.de>
> Cc: Tom Rini <trini@konsulko.com>
> Cc: Florian Fainelli <f.fainelli@gmail.com>
> ---
> Changes for v4:
>    - Use high timer register for get_ticks
>    - Move hard-coded register addresses from Kconfig to header
>    - Document I-cache/D-cache expectation
>
>  MAINTAINERS                                     |  10 +
>  arch/arm/Kconfig                                |  12 +
>  arch/arm/Makefile                               |   1 +
>  arch/arm/mach-bcmstb/Kconfig                    |  36 ++
>  arch/arm/mach-bcmstb/Makefile                   |   8 +
>  arch/arm/mach-bcmstb/include/mach/gpio.h        |  11 +
>  arch/arm/mach-bcmstb/include/mach/hardware.h    |  11 +
>  arch/arm/mach-bcmstb/include/mach/prior_stage.h |  30 ++
>  arch/arm/mach-bcmstb/include/mach/sdhci.h       |  15 +
>  arch/arm/mach-bcmstb/include/mach/timer.h       |  13 +
>  arch/arm/mach-bcmstb/lowlevel_init.S            |  21 ++
>  board/broadcom/bcmstb/MAINTAINERS               |   7 +
>  board/broadcom/bcmstb/Makefile                  |   8 +
>  board/broadcom/bcmstb/bcmstb.c                  | 194 +++++++++++
>  configs/bcm7445_defconfig                       |  27 ++
>  doc/README.bcm7xxx                              | 150 ++++++++
>  drivers/mmc/Kconfig                             |  11 +
>  drivers/mmc/Makefile                            |   1 +
>  drivers/mmc/bcmstb_sdhci.c                      |  67 ++++
>  drivers/spi/Kconfig                             |   7 +
>  drivers/spi/Makefile                            |   1 +
>  drivers/spi/bcmstb_spi.c                        | 439 ++++++++++++++++++++++++
>  drivers/spi/spi-uclass.c                        |   2 +-
>  dts/Kconfig                                     |   7 +
>  include/configs/bcm7445.h                       |  26 ++
>  include/configs/bcmstb.h                        | 183 ++++++++++
>  include/fdtdec.h                                |   4 +
>  lib/fdtdec.c                                    |   4 +
>  28 files changed, 1305 insertions(+), 1 deletion(-)
>  create mode 100644 arch/arm/mach-bcmstb/Kconfig
>  create mode 100644 arch/arm/mach-bcmstb/Makefile
>  create mode 100644 arch/arm/mach-bcmstb/include/mach/gpio.h
>  create mode 100644 arch/arm/mach-bcmstb/include/mach/hardware.h
>  create mode 100644 arch/arm/mach-bcmstb/include/mach/prior_stage.h
>  create mode 100644 arch/arm/mach-bcmstb/include/mach/sdhci.h
>  create mode 100644 arch/arm/mach-bcmstb/include/mach/timer.h
>  create mode 100644 arch/arm/mach-bcmstb/lowlevel_init.S
>  create mode 100644 board/broadcom/bcmstb/MAINTAINERS
>  create mode 100644 board/broadcom/bcmstb/Makefile
>  create mode 100644 board/broadcom/bcmstb/bcmstb.c
>  create mode 100644 configs/bcm7445_defconfig
>  create mode 100644 doc/README.bcm7xxx
>  create mode 100644 drivers/mmc/bcmstb_sdhci.c
>  create mode 100644 drivers/spi/bcmstb_spi.c
>  create mode 100644 include/configs/bcm7445.h
>  create mode 100644 include/configs/bcmstb.h
>

[snip]

> diff --git a/drivers/spi/spi-uclass.c b/drivers/spi/spi-uclass.c
> index d2d091f..c517d06 100644
> --- a/drivers/spi/spi-uclass.c
> +++ b/drivers/spi/spi-uclass.c
> @@ -273,7 +273,7 @@ int spi_get_bus_and_cs(int busnum, int cs, int speed, int mode,
>         bool created = false;
>         int ret;
>
> -#if CONFIG_IS_ENABLED(OF_PLATDATA)
> +#if CONFIG_IS_ENABLED(OF_PLATDATA) || CONFIG_IS_ENABLED(OF_PRIOR_STAGE)

Could you please explain this change a little bit? Why should we call
uclass_first_device_err() for OF_PRIOR_STAGE?

>         ret = uclass_first_device_err(UCLASS_SPI, &bus);
>  #else
>         ret = uclass_get_device_by_seq(UCLASS_SPI, busnum, &bus);
> diff --git a/dts/Kconfig b/dts/Kconfig
> index 0cef225..a1a92f2 100644
> --- a/dts/Kconfig
> +++ b/dts/Kconfig
> @@ -101,6 +101,13 @@ 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, the device tree used for DT
> +         control will be read from a device tree binary, at a memory
> +         location passed to U-Boot by the prior stage bootloader.
> +
>  endchoice
>

[snip]

Regards,
Bin

^ permalink raw reply	[flat|nested] 37+ messages in thread

* [U-Boot] [PATCH v4 1/1] board: arm: Add support for Broadcom BCM7445
  2019-08-26 15:54         ` [U-Boot] [PATCH v4 " Bin Meng
@ 2019-08-27 22:31           ` Thomas Fitzsimmons
  2019-08-28 10:19             ` Bin Meng
  0 siblings, 1 reply; 37+ messages in thread
From: Thomas Fitzsimmons @ 2019-08-27 22:31 UTC (permalink / raw)
  To: u-boot

Hi Bin,

Bin Meng <bmeng.cn@gmail.com> writes:

> Hi Thomas,
>
> On Sat, Jun 9, 2018 at 6:06 AM Thomas Fitzsimmons <fitzsim@fitzsim.org> wrote:
>>
>> Add support for loading U-Boot on the Broadcom 7445 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@fitzsim.org>
>> Cc: Stefan Roese <sr@denx.de>
>> Cc: Tom Rini <trini@konsulko.com>
>> Cc: Florian Fainelli <f.fainelli@gmail.com>
>> ---
>> Changes for v4:
>>    - Use high timer register for get_ticks
>>    - Move hard-coded register addresses from Kconfig to header
>>    - Document I-cache/D-cache expectation
>>
>>  MAINTAINERS                                     |  10 +
>>  arch/arm/Kconfig                                |  12 +
>>  arch/arm/Makefile                               |   1 +
>>  arch/arm/mach-bcmstb/Kconfig                    |  36 ++
>>  arch/arm/mach-bcmstb/Makefile                   |   8 +
>>  arch/arm/mach-bcmstb/include/mach/gpio.h        |  11 +
>>  arch/arm/mach-bcmstb/include/mach/hardware.h    |  11 +
>>  arch/arm/mach-bcmstb/include/mach/prior_stage.h |  30 ++
>>  arch/arm/mach-bcmstb/include/mach/sdhci.h       |  15 +
>>  arch/arm/mach-bcmstb/include/mach/timer.h       |  13 +
>>  arch/arm/mach-bcmstb/lowlevel_init.S            |  21 ++
>>  board/broadcom/bcmstb/MAINTAINERS               |   7 +
>>  board/broadcom/bcmstb/Makefile                  |   8 +
>>  board/broadcom/bcmstb/bcmstb.c                  | 194 +++++++++++
>>  configs/bcm7445_defconfig                       |  27 ++
>>  doc/README.bcm7xxx                              | 150 ++++++++
>>  drivers/mmc/Kconfig                             |  11 +
>>  drivers/mmc/Makefile                            |   1 +
>>  drivers/mmc/bcmstb_sdhci.c                      |  67 ++++
>>  drivers/spi/Kconfig                             |   7 +
>>  drivers/spi/Makefile                            |   1 +
>>  drivers/spi/bcmstb_spi.c                        | 439 ++++++++++++++++++++++++
>>  drivers/spi/spi-uclass.c                        |   2 +-
>>  dts/Kconfig                                     |   7 +
>>  include/configs/bcm7445.h                       |  26 ++
>>  include/configs/bcmstb.h                        | 183 ++++++++++
>>  include/fdtdec.h                                |   4 +
>>  lib/fdtdec.c                                    |   4 +
>>  28 files changed, 1305 insertions(+), 1 deletion(-)
>>  create mode 100644 arch/arm/mach-bcmstb/Kconfig
>>  create mode 100644 arch/arm/mach-bcmstb/Makefile
>>  create mode 100644 arch/arm/mach-bcmstb/include/mach/gpio.h
>>  create mode 100644 arch/arm/mach-bcmstb/include/mach/hardware.h
>>  create mode 100644 arch/arm/mach-bcmstb/include/mach/prior_stage.h
>>  create mode 100644 arch/arm/mach-bcmstb/include/mach/sdhci.h
>>  create mode 100644 arch/arm/mach-bcmstb/include/mach/timer.h
>>  create mode 100644 arch/arm/mach-bcmstb/lowlevel_init.S
>>  create mode 100644 board/broadcom/bcmstb/MAINTAINERS
>>  create mode 100644 board/broadcom/bcmstb/Makefile
>>  create mode 100644 board/broadcom/bcmstb/bcmstb.c
>>  create mode 100644 configs/bcm7445_defconfig
>>  create mode 100644 doc/README.bcm7xxx
>>  create mode 100644 drivers/mmc/bcmstb_sdhci.c
>>  create mode 100644 drivers/spi/bcmstb_spi.c
>>  create mode 100644 include/configs/bcm7445.h
>>  create mode 100644 include/configs/bcmstb.h
>>
>
> [snip]
>
>> diff --git a/drivers/spi/spi-uclass.c b/drivers/spi/spi-uclass.c
>> index d2d091f..c517d06 100644
>> --- a/drivers/spi/spi-uclass.c
>> +++ b/drivers/spi/spi-uclass.c
>> @@ -273,7 +273,7 @@ int spi_get_bus_and_cs(int busnum, int cs, int speed, int mode,
>>         bool created = false;
>>         int ret;
>>
>> -#if CONFIG_IS_ENABLED(OF_PLATDATA)
>> +#if CONFIG_IS_ENABLED(OF_PLATDATA) || CONFIG_IS_ENABLED(OF_PRIOR_STAGE)
>
> Could you please explain this change a little bit? Why should we call
> uclass_first_device_err() for OF_PRIOR_STAGE?
>
>>         ret = uclass_first_device_err(UCLASS_SPI, &bus);
>>  #else
>>         ret = uclass_get_device_by_seq(UCLASS_SPI, busnum, &bus);

On the BCM7445 eval board, the prior-stage-provided device tree does not
have an alias for spi0, though it has aliases for other device types; I
don't know why this is the case, but I don't have control over what the
prior stage bootloader (Broadcom's BOLT) provides.  Without that alias,
uclass_get_device_by_seq fails to find the SPI bus (and so U-Boot can't
find the SPI flash device that stores its environment).

At the time, I checked other ARM device trees in the Linux kernel and
not many set an alias for spi0, so I wrote the patch to choose the first
SPI bus.  Doing so was in line with what CONFIG_OF_PLATDATA did on
boards that wanted to avoid device tree accesses.

I see that since I introduced CONFIG_OF_PRIOR_STAGE, several other ports
have started using it, so there's probably a need to generalize this; if
other prior stage bootloaders provide SPI aliases then there should be a
way for this code to use them.

>> diff --git a/dts/Kconfig b/dts/Kconfig
>> index 0cef225..a1a92f2 100644
>> --- a/dts/Kconfig
>> +++ b/dts/Kconfig
>> @@ -101,6 +101,13 @@ 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, the device tree used for DT
>> +         control will be read from a device tree binary, at a memory
>> +         location passed to U-Boot by the prior stage bootloader.
>> +
>>  endchoice
>>
>
> [snip]

Thomas

^ permalink raw reply	[flat|nested] 37+ messages in thread

* [U-Boot] [PATCH v4 1/1] board: arm: Add support for Broadcom BCM7445
  2019-08-27 22:31           ` Thomas Fitzsimmons
@ 2019-08-28 10:19             ` Bin Meng
  2019-08-28 17:24               ` Thomas Fitzsimmons
  0 siblings, 1 reply; 37+ messages in thread
From: Bin Meng @ 2019-08-28 10:19 UTC (permalink / raw)
  To: u-boot

Hi Thomas,

On Wed, Aug 28, 2019 at 6:31 AM Thomas Fitzsimmons <fitzsim@fitzsim.org> wrote:
>
> Hi Bin,
>
> Bin Meng <bmeng.cn@gmail.com> writes:
>
> > Hi Thomas,
> >
> > On Sat, Jun 9, 2018 at 6:06 AM Thomas Fitzsimmons <fitzsim@fitzsim.org> wrote:
> >>
> >> Add support for loading U-Boot on the Broadcom 7445 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@fitzsim.org>
> >> Cc: Stefan Roese <sr@denx.de>
> >> Cc: Tom Rini <trini@konsulko.com>
> >> Cc: Florian Fainelli <f.fainelli@gmail.com>
> >> ---
> >> Changes for v4:
> >>    - Use high timer register for get_ticks
> >>    - Move hard-coded register addresses from Kconfig to header
> >>    - Document I-cache/D-cache expectation
> >>
> >>  MAINTAINERS                                     |  10 +
> >>  arch/arm/Kconfig                                |  12 +
> >>  arch/arm/Makefile                               |   1 +
> >>  arch/arm/mach-bcmstb/Kconfig                    |  36 ++
> >>  arch/arm/mach-bcmstb/Makefile                   |   8 +
> >>  arch/arm/mach-bcmstb/include/mach/gpio.h        |  11 +
> >>  arch/arm/mach-bcmstb/include/mach/hardware.h    |  11 +
> >>  arch/arm/mach-bcmstb/include/mach/prior_stage.h |  30 ++
> >>  arch/arm/mach-bcmstb/include/mach/sdhci.h       |  15 +
> >>  arch/arm/mach-bcmstb/include/mach/timer.h       |  13 +
> >>  arch/arm/mach-bcmstb/lowlevel_init.S            |  21 ++
> >>  board/broadcom/bcmstb/MAINTAINERS               |   7 +
> >>  board/broadcom/bcmstb/Makefile                  |   8 +
> >>  board/broadcom/bcmstb/bcmstb.c                  | 194 +++++++++++
> >>  configs/bcm7445_defconfig                       |  27 ++
> >>  doc/README.bcm7xxx                              | 150 ++++++++
> >>  drivers/mmc/Kconfig                             |  11 +
> >>  drivers/mmc/Makefile                            |   1 +
> >>  drivers/mmc/bcmstb_sdhci.c                      |  67 ++++
> >>  drivers/spi/Kconfig                             |   7 +
> >>  drivers/spi/Makefile                            |   1 +
> >>  drivers/spi/bcmstb_spi.c                        | 439 ++++++++++++++++++++++++
> >>  drivers/spi/spi-uclass.c                        |   2 +-
> >>  dts/Kconfig                                     |   7 +
> >>  include/configs/bcm7445.h                       |  26 ++
> >>  include/configs/bcmstb.h                        | 183 ++++++++++
> >>  include/fdtdec.h                                |   4 +
> >>  lib/fdtdec.c                                    |   4 +
> >>  28 files changed, 1305 insertions(+), 1 deletion(-)
> >>  create mode 100644 arch/arm/mach-bcmstb/Kconfig
> >>  create mode 100644 arch/arm/mach-bcmstb/Makefile
> >>  create mode 100644 arch/arm/mach-bcmstb/include/mach/gpio.h
> >>  create mode 100644 arch/arm/mach-bcmstb/include/mach/hardware.h
> >>  create mode 100644 arch/arm/mach-bcmstb/include/mach/prior_stage.h
> >>  create mode 100644 arch/arm/mach-bcmstb/include/mach/sdhci.h
> >>  create mode 100644 arch/arm/mach-bcmstb/include/mach/timer.h
> >>  create mode 100644 arch/arm/mach-bcmstb/lowlevel_init.S
> >>  create mode 100644 board/broadcom/bcmstb/MAINTAINERS
> >>  create mode 100644 board/broadcom/bcmstb/Makefile
> >>  create mode 100644 board/broadcom/bcmstb/bcmstb.c
> >>  create mode 100644 configs/bcm7445_defconfig
> >>  create mode 100644 doc/README.bcm7xxx
> >>  create mode 100644 drivers/mmc/bcmstb_sdhci.c
> >>  create mode 100644 drivers/spi/bcmstb_spi.c
> >>  create mode 100644 include/configs/bcm7445.h
> >>  create mode 100644 include/configs/bcmstb.h
> >>
> >
> > [snip]
> >
> >> diff --git a/drivers/spi/spi-uclass.c b/drivers/spi/spi-uclass.c
> >> index d2d091f..c517d06 100644
> >> --- a/drivers/spi/spi-uclass.c
> >> +++ b/drivers/spi/spi-uclass.c
> >> @@ -273,7 +273,7 @@ int spi_get_bus_and_cs(int busnum, int cs, int speed, int mode,
> >>         bool created = false;
> >>         int ret;
> >>
> >> -#if CONFIG_IS_ENABLED(OF_PLATDATA)
> >> +#if CONFIG_IS_ENABLED(OF_PLATDATA) || CONFIG_IS_ENABLED(OF_PRIOR_STAGE)
> >
> > Could you please explain this change a little bit? Why should we call
> > uclass_first_device_err() for OF_PRIOR_STAGE?
> >
> >>         ret = uclass_first_device_err(UCLASS_SPI, &bus);
> >>  #else
> >>         ret = uclass_get_device_by_seq(UCLASS_SPI, busnum, &bus);
>
> On the BCM7445 eval board, the prior-stage-provided device tree does not
> have an alias for spi0, though it has aliases for other device types; I
> don't know why this is the case, but I don't have control over what the
> prior stage bootloader (Broadcom's BOLT) provides.  Without that alias,
> uclass_get_device_by_seq fails to find the SPI bus (and so U-Boot can't
> find the SPI flash device that stores its environment).
>

I checked uclass_get_device_by_seq() and did not find any codes that
are trying to read aliases. Am I missing anything?

> At the time, I checked other ARM device trees in the Linux kernel and
> not many set an alias for spi0, so I wrote the patch to choose the first
> SPI bus.  Doing so was in line with what CONFIG_OF_PLATDATA did on
> boards that wanted to avoid device tree accesses.
>

Based on what you said, the adding of OF_PRIOR_STAGE here sounds like a hack.

> I see that since I introduced CONFIG_OF_PRIOR_STAGE, several other ports
> have started using it, so there's probably a need to generalize this; if
> other prior stage bootloaders provide SPI aliases then there should be a
> way for this code to use them.
>

I think the correct way is to call uclass_get_device_by_seq().
CONFIG_OF_PRIOR_STAGE should not imply such behavior.

Regards,
Bin

^ permalink raw reply	[flat|nested] 37+ messages in thread

* [U-Boot] [PATCH v4 1/1] board: arm: Add support for Broadcom BCM7445
  2019-08-28 10:19             ` Bin Meng
@ 2019-08-28 17:24               ` Thomas Fitzsimmons
  2019-08-29 15:24                 ` Bin Meng
  0 siblings, 1 reply; 37+ messages in thread
From: Thomas Fitzsimmons @ 2019-08-28 17:24 UTC (permalink / raw)
  To: u-boot

Hi Bin,

Bin Meng <bmeng.cn@gmail.com> writes:

> Hi Thomas,
>
> On Wed, Aug 28, 2019 at 6:31 AM Thomas Fitzsimmons <fitzsim@fitzsim.org> wrote:
>>
>> Hi Bin,
>>
>> Bin Meng <bmeng.cn@gmail.com> writes:
>>
>> > Hi Thomas,
>> >
>> > On Sat, Jun 9, 2018 at 6:06 AM Thomas Fitzsimmons <fitzsim@fitzsim.org> wrote:
>> >>
>> >> Add support for loading U-Boot on the Broadcom 7445 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@fitzsim.org>
>> >> Cc: Stefan Roese <sr@denx.de>
>> >> Cc: Tom Rini <trini@konsulko.com>
>> >> Cc: Florian Fainelli <f.fainelli@gmail.com>
>> >> ---
>> >> Changes for v4:
>> >>    - Use high timer register for get_ticks
>> >>    - Move hard-coded register addresses from Kconfig to header
>> >>    - Document I-cache/D-cache expectation
>> >>
>> >>  MAINTAINERS                                     |  10 +
>> >>  arch/arm/Kconfig                                |  12 +
>> >>  arch/arm/Makefile                               |   1 +
>> >>  arch/arm/mach-bcmstb/Kconfig                    |  36 ++
>> >>  arch/arm/mach-bcmstb/Makefile                   |   8 +
>> >>  arch/arm/mach-bcmstb/include/mach/gpio.h        |  11 +
>> >>  arch/arm/mach-bcmstb/include/mach/hardware.h    |  11 +
>> >>  arch/arm/mach-bcmstb/include/mach/prior_stage.h |  30 ++
>> >>  arch/arm/mach-bcmstb/include/mach/sdhci.h       |  15 +
>> >>  arch/arm/mach-bcmstb/include/mach/timer.h       |  13 +
>> >>  arch/arm/mach-bcmstb/lowlevel_init.S            |  21 ++
>> >>  board/broadcom/bcmstb/MAINTAINERS               |   7 +
>> >>  board/broadcom/bcmstb/Makefile                  |   8 +
>> >>  board/broadcom/bcmstb/bcmstb.c                  | 194 +++++++++++
>> >>  configs/bcm7445_defconfig                       |  27 ++
>> >>  doc/README.bcm7xxx                              | 150 ++++++++
>> >>  drivers/mmc/Kconfig                             |  11 +
>> >>  drivers/mmc/Makefile                            |   1 +
>> >>  drivers/mmc/bcmstb_sdhci.c                      |  67 ++++
>> >>  drivers/spi/Kconfig                             |   7 +
>> >>  drivers/spi/Makefile                            |   1 +
>> >>  drivers/spi/bcmstb_spi.c                        | 439 ++++++++++++++++++++++++
>> >>  drivers/spi/spi-uclass.c                        |   2 +-
>> >>  dts/Kconfig                                     |   7 +
>> >>  include/configs/bcm7445.h                       |  26 ++
>> >>  include/configs/bcmstb.h                        | 183 ++++++++++
>> >>  include/fdtdec.h                                |   4 +
>> >>  lib/fdtdec.c                                    |   4 +
>> >>  28 files changed, 1305 insertions(+), 1 deletion(-)
>> >>  create mode 100644 arch/arm/mach-bcmstb/Kconfig
>> >>  create mode 100644 arch/arm/mach-bcmstb/Makefile
>> >>  create mode 100644 arch/arm/mach-bcmstb/include/mach/gpio.h
>> >>  create mode 100644 arch/arm/mach-bcmstb/include/mach/hardware.h
>> >>  create mode 100644 arch/arm/mach-bcmstb/include/mach/prior_stage.h
>> >>  create mode 100644 arch/arm/mach-bcmstb/include/mach/sdhci.h
>> >>  create mode 100644 arch/arm/mach-bcmstb/include/mach/timer.h
>> >>  create mode 100644 arch/arm/mach-bcmstb/lowlevel_init.S
>> >>  create mode 100644 board/broadcom/bcmstb/MAINTAINERS
>> >>  create mode 100644 board/broadcom/bcmstb/Makefile
>> >>  create mode 100644 board/broadcom/bcmstb/bcmstb.c
>> >>  create mode 100644 configs/bcm7445_defconfig
>> >>  create mode 100644 doc/README.bcm7xxx
>> >>  create mode 100644 drivers/mmc/bcmstb_sdhci.c
>> >>  create mode 100644 drivers/spi/bcmstb_spi.c
>> >>  create mode 100644 include/configs/bcm7445.h
>> >>  create mode 100644 include/configs/bcmstb.h
>> >>
>> >
>> > [snip]
>> >
>> >> diff --git a/drivers/spi/spi-uclass.c b/drivers/spi/spi-uclass.c
>> >> index d2d091f..c517d06 100644
>> >> --- a/drivers/spi/spi-uclass.c
>> >> +++ b/drivers/spi/spi-uclass.c
>> >> @@ -273,7 +273,7 @@ int spi_get_bus_and_cs(int busnum, int cs, int speed, int mode,
>> >>         bool created = false;
>> >>         int ret;
>> >>
>> >> -#if CONFIG_IS_ENABLED(OF_PLATDATA)
>> >> +#if CONFIG_IS_ENABLED(OF_PLATDATA) || CONFIG_IS_ENABLED(OF_PRIOR_STAGE)
>> >
>> > Could you please explain this change a little bit? Why should we call
>> > uclass_first_device_err() for OF_PRIOR_STAGE?
>> >
>> >>         ret = uclass_first_device_err(UCLASS_SPI, &bus);
>> >>  #else
>> >>         ret = uclass_get_device_by_seq(UCLASS_SPI, busnum, &bus);
>>
>> On the BCM7445 eval board, the prior-stage-provided device tree does not
>> have an alias for spi0, though it has aliases for other device types; I
>> don't know why this is the case, but I don't have control over what the
>> prior stage bootloader (Broadcom's BOLT) provides.  Without that alias,
>> uclass_get_device_by_seq fails to find the SPI bus (and so U-Boot can't
>> find the SPI flash device that stores its environment).
>>
>
> I checked uclass_get_device_by_seq() and did not find any codes that
> are trying to read aliases. Am I missing anything?

Alias handling is not in the direct uclass_get_device_by_seq call chain,
and it took some debugging to find this.  The requested sequence number
is handled earlier in the boot, in device_bind_common:

   dev->seq = -1;
   dev->req_seq = -1;
   if (CONFIG_IS_ENABLED(DM_SEQ_ALIAS) &&
       (uc->uc_drv->flags & DM_UC_FLAG_SEQ_ALIAS)) {
           /*
            * Some devices, such as a SPI bus, I2C bus and serial ports
            * are numbered using aliases.
            *
            * This is just a 'requested' sequence, and will be
            * resolved (and ->seq updated) when the device is probed.
            */
           if (CONFIG_IS_ENABLED(OF_CONTROL) && !CONFIG_IS_ENABLED(OF_PLATDATA)) {
                   if (uc->uc_drv->name && ofnode_valid(node))
                           dev_read_alias_seq(dev, &dev->req_seq);
           } else {
                   dev->req_seq = uclass_find_next_free_req_seq(drv->id);
           }
   }

If the prior stage bootloader provides no SPI bus alias, then
dev_read_alias_seq fails, dev->req_seq stays unset (-1), and later when
an attempt is made to access the SPI bus, the call to
uclass_get_device_by_seq fails.

>> At the time, I checked other ARM device trees in the Linux kernel and
>> not many set an alias for spi0, so I wrote the patch to choose the first
>> SPI bus.  Doing so was in line with what CONFIG_OF_PLATDATA did on
>> boards that wanted to avoid device tree accesses.
>>
>
> Based on what you said, the adding of OF_PRIOR_STAGE here sounds like a hack.

Yeah, it makes an assumption about which SPI bus to use, that may or may
not be valid on other boards.

>> I see that since I introduced CONFIG_OF_PRIOR_STAGE, several other ports
>> have started using it, so there's probably a need to generalize this; if
>> other prior stage bootloaders provide SPI aliases then there should be a
>> way for this code to use them.
>>
>
> I think the correct way is to call uclass_get_device_by_seq().
> CONFIG_OF_PRIOR_STAGE should not imply such behavior.

OK, but without other changes this would break boards that rely on the
above assumption (for example BCM7445).

I'm experimenting with patches that work on BCM7445 and eliminate the
SPI bus assumption but I don't know what effect they might have on other
ports that use OF_PRIOR_STAGE.

In general it seems like a good idea to use the prior-stage-provided
aliases, but the question is what to do when an alias is missing; maybe
always fall back to calling uclass_find_next_free_req_seq?

Have you found a board for which uclass_get_device_by_seq works for SPI
and uclass_first_device_err does the wrong thing?  Is it a publicly
available port that I can have a look at?

Thanks,
Thomas

^ permalink raw reply	[flat|nested] 37+ messages in thread

* [U-Boot] [PATCH v4 1/1] board: arm: Add support for Broadcom BCM7445
  2019-08-28 17:24               ` Thomas Fitzsimmons
@ 2019-08-29 15:24                 ` Bin Meng
  2019-09-05 12:10                   ` Bin Meng
  2019-09-06 11:51                   ` [U-Boot] [PATCH 0/2] dm: CONFIG_OF_PRIOR_STAGE request number fixes Thomas Fitzsimmons
  0 siblings, 2 replies; 37+ messages in thread
From: Bin Meng @ 2019-08-29 15:24 UTC (permalink / raw)
  To: u-boot

+Simon

On Thu, Aug 29, 2019 at 1:24 AM Thomas Fitzsimmons <fitzsim@fitzsim.org> wrote:
>
> Hi Bin,
>
> Bin Meng <bmeng.cn@gmail.com> writes:
>
> > Hi Thomas,
> >
> > On Wed, Aug 28, 2019 at 6:31 AM Thomas Fitzsimmons <fitzsim@fitzsim.org> wrote:
> >>
> >> Hi Bin,
> >>
> >> Bin Meng <bmeng.cn@gmail.com> writes:
> >>
> >> > Hi Thomas,
> >> >
> >> > On Sat, Jun 9, 2018 at 6:06 AM Thomas Fitzsimmons <fitzsim@fitzsim.org> wrote:
> >> >>
> >> >> Add support for loading U-Boot on the Broadcom 7445 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@fitzsim.org>
> >> >> Cc: Stefan Roese <sr@denx.de>
> >> >> Cc: Tom Rini <trini@konsulko.com>
> >> >> Cc: Florian Fainelli <f.fainelli@gmail.com>
> >> >> ---
> >> >> Changes for v4:
> >> >>    - Use high timer register for get_ticks
> >> >>    - Move hard-coded register addresses from Kconfig to header
> >> >>    - Document I-cache/D-cache expectation
> >> >>
> >> >>  MAINTAINERS                                     |  10 +
> >> >>  arch/arm/Kconfig                                |  12 +
> >> >>  arch/arm/Makefile                               |   1 +
> >> >>  arch/arm/mach-bcmstb/Kconfig                    |  36 ++
> >> >>  arch/arm/mach-bcmstb/Makefile                   |   8 +
> >> >>  arch/arm/mach-bcmstb/include/mach/gpio.h        |  11 +
> >> >>  arch/arm/mach-bcmstb/include/mach/hardware.h    |  11 +
> >> >>  arch/arm/mach-bcmstb/include/mach/prior_stage.h |  30 ++
> >> >>  arch/arm/mach-bcmstb/include/mach/sdhci.h       |  15 +
> >> >>  arch/arm/mach-bcmstb/include/mach/timer.h       |  13 +
> >> >>  arch/arm/mach-bcmstb/lowlevel_init.S            |  21 ++
> >> >>  board/broadcom/bcmstb/MAINTAINERS               |   7 +
> >> >>  board/broadcom/bcmstb/Makefile                  |   8 +
> >> >>  board/broadcom/bcmstb/bcmstb.c                  | 194 +++++++++++
> >> >>  configs/bcm7445_defconfig                       |  27 ++
> >> >>  doc/README.bcm7xxx                              | 150 ++++++++
> >> >>  drivers/mmc/Kconfig                             |  11 +
> >> >>  drivers/mmc/Makefile                            |   1 +
> >> >>  drivers/mmc/bcmstb_sdhci.c                      |  67 ++++
> >> >>  drivers/spi/Kconfig                             |   7 +
> >> >>  drivers/spi/Makefile                            |   1 +
> >> >>  drivers/spi/bcmstb_spi.c                        | 439 ++++++++++++++++++++++++
> >> >>  drivers/spi/spi-uclass.c                        |   2 +-
> >> >>  dts/Kconfig                                     |   7 +
> >> >>  include/configs/bcm7445.h                       |  26 ++
> >> >>  include/configs/bcmstb.h                        | 183 ++++++++++
> >> >>  include/fdtdec.h                                |   4 +
> >> >>  lib/fdtdec.c                                    |   4 +
> >> >>  28 files changed, 1305 insertions(+), 1 deletion(-)
> >> >>  create mode 100644 arch/arm/mach-bcmstb/Kconfig
> >> >>  create mode 100644 arch/arm/mach-bcmstb/Makefile
> >> >>  create mode 100644 arch/arm/mach-bcmstb/include/mach/gpio.h
> >> >>  create mode 100644 arch/arm/mach-bcmstb/include/mach/hardware.h
> >> >>  create mode 100644 arch/arm/mach-bcmstb/include/mach/prior_stage.h
> >> >>  create mode 100644 arch/arm/mach-bcmstb/include/mach/sdhci.h
> >> >>  create mode 100644 arch/arm/mach-bcmstb/include/mach/timer.h
> >> >>  create mode 100644 arch/arm/mach-bcmstb/lowlevel_init.S
> >> >>  create mode 100644 board/broadcom/bcmstb/MAINTAINERS
> >> >>  create mode 100644 board/broadcom/bcmstb/Makefile
> >> >>  create mode 100644 board/broadcom/bcmstb/bcmstb.c
> >> >>  create mode 100644 configs/bcm7445_defconfig
> >> >>  create mode 100644 doc/README.bcm7xxx
> >> >>  create mode 100644 drivers/mmc/bcmstb_sdhci.c
> >> >>  create mode 100644 drivers/spi/bcmstb_spi.c
> >> >>  create mode 100644 include/configs/bcm7445.h
> >> >>  create mode 100644 include/configs/bcmstb.h
> >> >>
> >> >
> >> > [snip]
> >> >
> >> >> diff --git a/drivers/spi/spi-uclass.c b/drivers/spi/spi-uclass.c
> >> >> index d2d091f..c517d06 100644
> >> >> --- a/drivers/spi/spi-uclass.c
> >> >> +++ b/drivers/spi/spi-uclass.c
> >> >> @@ -273,7 +273,7 @@ int spi_get_bus_and_cs(int busnum, int cs, int speed, int mode,
> >> >>         bool created = false;
> >> >>         int ret;
> >> >>
> >> >> -#if CONFIG_IS_ENABLED(OF_PLATDATA)
> >> >> +#if CONFIG_IS_ENABLED(OF_PLATDATA) || CONFIG_IS_ENABLED(OF_PRIOR_STAGE)
> >> >
> >> > Could you please explain this change a little bit? Why should we call
> >> > uclass_first_device_err() for OF_PRIOR_STAGE?
> >> >
> >> >>         ret = uclass_first_device_err(UCLASS_SPI, &bus);
> >> >>  #else
> >> >>         ret = uclass_get_device_by_seq(UCLASS_SPI, busnum, &bus);
> >>
> >> On the BCM7445 eval board, the prior-stage-provided device tree does not
> >> have an alias for spi0, though it has aliases for other device types; I
> >> don't know why this is the case, but I don't have control over what the
> >> prior stage bootloader (Broadcom's BOLT) provides.  Without that alias,
> >> uclass_get_device_by_seq fails to find the SPI bus (and so U-Boot can't
> >> find the SPI flash device that stores its environment).
> >>
> >
> > I checked uclass_get_device_by_seq() and did not find any codes that
> > are trying to read aliases. Am I missing anything?
>
> Alias handling is not in the direct uclass_get_device_by_seq call chain,
> and it took some debugging to find this.  The requested sequence number
> is handled earlier in the boot, in device_bind_common:
>
>    dev->seq = -1;
>    dev->req_seq = -1;
>    if (CONFIG_IS_ENABLED(DM_SEQ_ALIAS) &&
>        (uc->uc_drv->flags & DM_UC_FLAG_SEQ_ALIAS)) {
>            /*
>             * Some devices, such as a SPI bus, I2C bus and serial ports
>             * are numbered using aliases.
>             *
>             * This is just a 'requested' sequence, and will be
>             * resolved (and ->seq updated) when the device is probed.
>             */
>            if (CONFIG_IS_ENABLED(OF_CONTROL) && !CONFIG_IS_ENABLED(OF_PLATDATA)) {
>                    if (uc->uc_drv->name && ofnode_valid(node))
>                            dev_read_alias_seq(dev, &dev->req_seq);
>            } else {
>                    dev->req_seq = uclass_find_next_free_req_seq(drv->id);
>            }
>    }
>
> If the prior stage bootloader provides no SPI bus alias, then
> dev_read_alias_seq fails, dev->req_seq stays unset (-1), and later when
> an attempt is made to access the SPI bus, the call to
> uclass_get_device_by_seq fails.

Ah, I see. Thanks!

>
> >> At the time, I checked other ARM device trees in the Linux kernel and
> >> not many set an alias for spi0, so I wrote the patch to choose the first
> >> SPI bus.  Doing so was in line with what CONFIG_OF_PLATDATA did on
> >> boards that wanted to avoid device tree accesses.
> >>
> >
> > Based on what you said, the adding of OF_PRIOR_STAGE here sounds like a hack.
>
> Yeah, it makes an assumption about which SPI bus to use, that may or may
> not be valid on other boards.
>
> >> I see that since I introduced CONFIG_OF_PRIOR_STAGE, several other ports
> >> have started using it, so there's probably a need to generalize this; if
> >> other prior stage bootloaders provide SPI aliases then there should be a
> >> way for this code to use them.
> >>
> >
> > I think the correct way is to call uclass_get_device_by_seq().
> > CONFIG_OF_PRIOR_STAGE should not imply such behavior.
>
> OK, but without other changes this would break boards that rely on the
> above assumption (for example BCM7445).
>
> I'm experimenting with patches that work on BCM7445 and eliminate the
> SPI bus assumption but I don't know what effect they might have on other
> ports that use OF_PRIOR_STAGE.
>
> In general it seems like a good idea to use the prior-stage-provided
> aliases, but the question is what to do when an alias is missing; maybe
> always fall back to calling uclass_find_next_free_req_seq?

I tend to agree. As I see lots of places in U-Boot sources, like below:

drivers/i2c/intel_i2c.c::intel_i2c_bind()

if (device_is_on_pci_bus(dev)) {
               /*
                * ToDo:
                * Setting req_seq in the driver is probably not recommended.
                * But without a DT alias the number is not configured. And
                * using this driver is impossible for PCIe I2C devices.
                * This can be removed, once a better (correct) way for this
                * is found and implemented.
                */
               dev->req_seq = num_cards;

And another example:
drivers/usb/host/ehci-vf.c::vf_usb_bind()

       /*
        * Without this hack, if we return ENODEV for USB Controller 0, on
        * probe for the next controller, USB Controller 1 will be given a
        * sequence number of 0. This conflicts with our requirement of
        * sequence numbers while initialising the peripherals.
        */
       dev->req_seq = num_controllers;

Simon, do you think we should change the behavior of dev->req_seq in
the device bind for uclass drivers with DM_UC_FLAG_SEQ_ALIAS flag?

>
> Have you found a board for which uclass_get_device_by_seq works for SPI
> and uclass_first_device_err does the wrong thing?  Is it a publicly
> available port that I can have a look at?

No, I was not indicating an error like uclass_get_device_by_seq works
for SPI and uclass_first_device_err does the wrong thing. The issue
with your implementation is that it forces probing the first SPI
controller and ignore the "busnum" completely. This makes a board with
multiple SPI controllers unable to probe other controllers than the
very first one.

Regards,
Bin

^ permalink raw reply	[flat|nested] 37+ messages in thread

* [U-Boot] [PATCH v4 1/1] board: arm: Add support for Broadcom BCM7445
  2019-08-29 15:24                 ` Bin Meng
@ 2019-09-05 12:10                   ` Bin Meng
  2019-09-17  5:48                     ` Simon Glass
  2019-09-06 11:51                   ` [U-Boot] [PATCH 0/2] dm: CONFIG_OF_PRIOR_STAGE request number fixes Thomas Fitzsimmons
  1 sibling, 1 reply; 37+ messages in thread
From: Bin Meng @ 2019-09-05 12:10 UTC (permalink / raw)
  To: u-boot

Hi Simon,

On Thu, Aug 29, 2019 at 11:24 PM Bin Meng <bmeng.cn@gmail.com> wrote:
>
> +Simon
>
> On Thu, Aug 29, 2019 at 1:24 AM Thomas Fitzsimmons <fitzsim@fitzsim.org> wrote:
> >
> > Hi Bin,
> >
> > Bin Meng <bmeng.cn@gmail.com> writes:
> >
> > > Hi Thomas,
> > >
> > > On Wed, Aug 28, 2019 at 6:31 AM Thomas Fitzsimmons <fitzsim@fitzsim.org> wrote:
> > >>
> > >> Hi Bin,
> > >>
> > >> Bin Meng <bmeng.cn@gmail.com> writes:
> > >>
> > >> > Hi Thomas,
> > >> >
> > >> > On Sat, Jun 9, 2018 at 6:06 AM Thomas Fitzsimmons <fitzsim@fitzsim.org> wrote:
> > >> >>
> > >> >> Add support for loading U-Boot on the Broadcom 7445 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@fitzsim.org>
> > >> >> Cc: Stefan Roese <sr@denx.de>
> > >> >> Cc: Tom Rini <trini@konsulko.com>
> > >> >> Cc: Florian Fainelli <f.fainelli@gmail.com>
> > >> >> ---
> > >> >> Changes for v4:
> > >> >>    - Use high timer register for get_ticks
> > >> >>    - Move hard-coded register addresses from Kconfig to header
> > >> >>    - Document I-cache/D-cache expectation
> > >> >>
> > >> >>  MAINTAINERS                                     |  10 +
> > >> >>  arch/arm/Kconfig                                |  12 +
> > >> >>  arch/arm/Makefile                               |   1 +
> > >> >>  arch/arm/mach-bcmstb/Kconfig                    |  36 ++
> > >> >>  arch/arm/mach-bcmstb/Makefile                   |   8 +
> > >> >>  arch/arm/mach-bcmstb/include/mach/gpio.h        |  11 +
> > >> >>  arch/arm/mach-bcmstb/include/mach/hardware.h    |  11 +
> > >> >>  arch/arm/mach-bcmstb/include/mach/prior_stage.h |  30 ++
> > >> >>  arch/arm/mach-bcmstb/include/mach/sdhci.h       |  15 +
> > >> >>  arch/arm/mach-bcmstb/include/mach/timer.h       |  13 +
> > >> >>  arch/arm/mach-bcmstb/lowlevel_init.S            |  21 ++
> > >> >>  board/broadcom/bcmstb/MAINTAINERS               |   7 +
> > >> >>  board/broadcom/bcmstb/Makefile                  |   8 +
> > >> >>  board/broadcom/bcmstb/bcmstb.c                  | 194 +++++++++++
> > >> >>  configs/bcm7445_defconfig                       |  27 ++
> > >> >>  doc/README.bcm7xxx                              | 150 ++++++++
> > >> >>  drivers/mmc/Kconfig                             |  11 +
> > >> >>  drivers/mmc/Makefile                            |   1 +
> > >> >>  drivers/mmc/bcmstb_sdhci.c                      |  67 ++++
> > >> >>  drivers/spi/Kconfig                             |   7 +
> > >> >>  drivers/spi/Makefile                            |   1 +
> > >> >>  drivers/spi/bcmstb_spi.c                        | 439 ++++++++++++++++++++++++
> > >> >>  drivers/spi/spi-uclass.c                        |   2 +-
> > >> >>  dts/Kconfig                                     |   7 +
> > >> >>  include/configs/bcm7445.h                       |  26 ++
> > >> >>  include/configs/bcmstb.h                        | 183 ++++++++++
> > >> >>  include/fdtdec.h                                |   4 +
> > >> >>  lib/fdtdec.c                                    |   4 +
> > >> >>  28 files changed, 1305 insertions(+), 1 deletion(-)
> > >> >>  create mode 100644 arch/arm/mach-bcmstb/Kconfig
> > >> >>  create mode 100644 arch/arm/mach-bcmstb/Makefile
> > >> >>  create mode 100644 arch/arm/mach-bcmstb/include/mach/gpio.h
> > >> >>  create mode 100644 arch/arm/mach-bcmstb/include/mach/hardware.h
> > >> >>  create mode 100644 arch/arm/mach-bcmstb/include/mach/prior_stage.h
> > >> >>  create mode 100644 arch/arm/mach-bcmstb/include/mach/sdhci.h
> > >> >>  create mode 100644 arch/arm/mach-bcmstb/include/mach/timer.h
> > >> >>  create mode 100644 arch/arm/mach-bcmstb/lowlevel_init.S
> > >> >>  create mode 100644 board/broadcom/bcmstb/MAINTAINERS
> > >> >>  create mode 100644 board/broadcom/bcmstb/Makefile
> > >> >>  create mode 100644 board/broadcom/bcmstb/bcmstb.c
> > >> >>  create mode 100644 configs/bcm7445_defconfig
> > >> >>  create mode 100644 doc/README.bcm7xxx
> > >> >>  create mode 100644 drivers/mmc/bcmstb_sdhci.c
> > >> >>  create mode 100644 drivers/spi/bcmstb_spi.c
> > >> >>  create mode 100644 include/configs/bcm7445.h
> > >> >>  create mode 100644 include/configs/bcmstb.h
> > >> >>
> > >> >
> > >> > [snip]
> > >> >
> > >> >> diff --git a/drivers/spi/spi-uclass.c b/drivers/spi/spi-uclass.c
> > >> >> index d2d091f..c517d06 100644
> > >> >> --- a/drivers/spi/spi-uclass.c
> > >> >> +++ b/drivers/spi/spi-uclass.c
> > >> >> @@ -273,7 +273,7 @@ int spi_get_bus_and_cs(int busnum, int cs, int speed, int mode,
> > >> >>         bool created = false;
> > >> >>         int ret;
> > >> >>
> > >> >> -#if CONFIG_IS_ENABLED(OF_PLATDATA)
> > >> >> +#if CONFIG_IS_ENABLED(OF_PLATDATA) || CONFIG_IS_ENABLED(OF_PRIOR_STAGE)
> > >> >
> > >> > Could you please explain this change a little bit? Why should we call
> > >> > uclass_first_device_err() for OF_PRIOR_STAGE?
> > >> >
> > >> >>         ret = uclass_first_device_err(UCLASS_SPI, &bus);
> > >> >>  #else
> > >> >>         ret = uclass_get_device_by_seq(UCLASS_SPI, busnum, &bus);
> > >>
> > >> On the BCM7445 eval board, the prior-stage-provided device tree does not
> > >> have an alias for spi0, though it has aliases for other device types; I
> > >> don't know why this is the case, but I don't have control over what the
> > >> prior stage bootloader (Broadcom's BOLT) provides.  Without that alias,
> > >> uclass_get_device_by_seq fails to find the SPI bus (and so U-Boot can't
> > >> find the SPI flash device that stores its environment).
> > >>
> > >
> > > I checked uclass_get_device_by_seq() and did not find any codes that
> > > are trying to read aliases. Am I missing anything?
> >
> > Alias handling is not in the direct uclass_get_device_by_seq call chain,
> > and it took some debugging to find this.  The requested sequence number
> > is handled earlier in the boot, in device_bind_common:
> >
> >    dev->seq = -1;
> >    dev->req_seq = -1;
> >    if (CONFIG_IS_ENABLED(DM_SEQ_ALIAS) &&
> >        (uc->uc_drv->flags & DM_UC_FLAG_SEQ_ALIAS)) {
> >            /*
> >             * Some devices, such as a SPI bus, I2C bus and serial ports
> >             * are numbered using aliases.
> >             *
> >             * This is just a 'requested' sequence, and will be
> >             * resolved (and ->seq updated) when the device is probed.
> >             */
> >            if (CONFIG_IS_ENABLED(OF_CONTROL) && !CONFIG_IS_ENABLED(OF_PLATDATA)) {
> >                    if (uc->uc_drv->name && ofnode_valid(node))
> >                            dev_read_alias_seq(dev, &dev->req_seq);
> >            } else {
> >                    dev->req_seq = uclass_find_next_free_req_seq(drv->id);
> >            }
> >    }
> >
> > If the prior stage bootloader provides no SPI bus alias, then
> > dev_read_alias_seq fails, dev->req_seq stays unset (-1), and later when
> > an attempt is made to access the SPI bus, the call to
> > uclass_get_device_by_seq fails.
>
> Ah, I see. Thanks!
>
> >
> > >> At the time, I checked other ARM device trees in the Linux kernel and
> > >> not many set an alias for spi0, so I wrote the patch to choose the first
> > >> SPI bus.  Doing so was in line with what CONFIG_OF_PLATDATA did on
> > >> boards that wanted to avoid device tree accesses.
> > >>
> > >
> > > Based on what you said, the adding of OF_PRIOR_STAGE here sounds like a hack.
> >
> > Yeah, it makes an assumption about which SPI bus to use, that may or may
> > not be valid on other boards.
> >
> > >> I see that since I introduced CONFIG_OF_PRIOR_STAGE, several other ports
> > >> have started using it, so there's probably a need to generalize this; if
> > >> other prior stage bootloaders provide SPI aliases then there should be a
> > >> way for this code to use them.
> > >>
> > >
> > > I think the correct way is to call uclass_get_device_by_seq().
> > > CONFIG_OF_PRIOR_STAGE should not imply such behavior.
> >
> > OK, but without other changes this would break boards that rely on the
> > above assumption (for example BCM7445).
> >
> > I'm experimenting with patches that work on BCM7445 and eliminate the
> > SPI bus assumption but I don't know what effect they might have on other
> > ports that use OF_PRIOR_STAGE.
> >
> > In general it seems like a good idea to use the prior-stage-provided
> > aliases, but the question is what to do when an alias is missing; maybe
> > always fall back to calling uclass_find_next_free_req_seq?
>
> I tend to agree. As I see lots of places in U-Boot sources, like below:
>
> drivers/i2c/intel_i2c.c::intel_i2c_bind()
>
> if (device_is_on_pci_bus(dev)) {
>                /*
>                 * ToDo:
>                 * Setting req_seq in the driver is probably not recommended.
>                 * But without a DT alias the number is not configured. And
>                 * using this driver is impossible for PCIe I2C devices.
>                 * This can be removed, once a better (correct) way for this
>                 * is found and implemented.
>                 */
>                dev->req_seq = num_cards;
>
> And another example:
> drivers/usb/host/ehci-vf.c::vf_usb_bind()
>
>        /*
>         * Without this hack, if we return ENODEV for USB Controller 0, on
>         * probe for the next controller, USB Controller 1 will be given a
>         * sequence number of 0. This conflicts with our requirement of
>         * sequence numbers while initialising the peripherals.
>         */
>        dev->req_seq = num_controllers;
>
> Simon, do you think we should change the behavior of dev->req_seq in
> the device bind for uclass drivers with DM_UC_FLAG_SEQ_ALIAS flag?
>

Would you please give some comments regarding this?

> >
> > Have you found a board for which uclass_get_device_by_seq works for SPI
> > and uclass_first_device_err does the wrong thing?  Is it a publicly
> > available port that I can have a look at?
>
> No, I was not indicating an error like uclass_get_device_by_seq works
> for SPI and uclass_first_device_err does the wrong thing. The issue
> with your implementation is that it forces probing the first SPI
> controller and ignore the "busnum" completely. This makes a board with
> multiple SPI controllers unable to probe other controllers than the
> very first one.

Regards,
Bin

^ permalink raw reply	[flat|nested] 37+ messages in thread

* [U-Boot] [PATCH 0/2] dm: CONFIG_OF_PRIOR_STAGE request number fixes
  2019-08-29 15:24                 ` Bin Meng
  2019-09-05 12:10                   ` Bin Meng
@ 2019-09-06 11:51                   ` Thomas Fitzsimmons
  2019-09-06 11:51                     ` [U-Boot] [PATCH 1/2] dm: device: Request next sequence number Thomas Fitzsimmons
  2019-09-06 11:51                     ` [U-Boot] [PATCH 2/2] dm: spi: Do not assume first SPI bus Thomas Fitzsimmons
  1 sibling, 2 replies; 37+ messages in thread
From: Thomas Fitzsimmons @ 2019-09-06 11:51 UTC (permalink / raw)
  To: u-boot

These patches remove a workaround that was needed for ports that use
CONFIG_OF_PRIOR_STAGE, that need to probe a SPI bus, and whose prior
stage device tree does not provide SPI bus aliases.

Thomas Fitzsimmons (2):
  dm: device: Request next sequence number
  dm: spi: Do not assume first SPI bus

 drivers/core/device.c    | 5 +++++
 drivers/core/uclass.c    | 4 +++-
 drivers/spi/spi-uclass.c | 2 +-
 3 files changed, 9 insertions(+), 2 deletions(-)

-- 
2.23.0

^ permalink raw reply	[flat|nested] 37+ messages in thread

* [U-Boot] [PATCH 1/2] dm: device: Request next sequence number
  2019-09-06 11:51                   ` [U-Boot] [PATCH 0/2] dm: CONFIG_OF_PRIOR_STAGE request number fixes Thomas Fitzsimmons
@ 2019-09-06 11:51                     ` Thomas Fitzsimmons
  2019-09-06 13:24                       ` Bin Meng
  2019-09-06 11:51                     ` [U-Boot] [PATCH 2/2] dm: spi: Do not assume first SPI bus Thomas Fitzsimmons
  1 sibling, 1 reply; 37+ messages in thread
From: Thomas Fitzsimmons @ 2019-09-06 11:51 UTC (permalink / raw)
  To: u-boot

For CONFIG_OF_PRIOR_STAGE, in the absence of a device tree alias for a
given device, use the next request number for that type of device.
This allows aliases to be used when they're available, while still
allowing unaliased devices to be probed.

Signed-off-by: Thomas Fitzsimmons <fitzsim@fitzsim.org>
Cc: Bin Meng <bmeng.cn@gmail.com>
Cc: Simon Glass <sjg@chromium.org>
---
 drivers/core/device.c | 5 +++++
 drivers/core/uclass.c | 4 +++-
 2 files changed, 8 insertions(+), 1 deletion(-)

diff --git a/drivers/core/device.c b/drivers/core/device.c
index 474c1642ee..ca8be208a9 100644
--- a/drivers/core/device.c
+++ b/drivers/core/device.c
@@ -82,6 +82,11 @@ static int device_bind_common(struct udevice *parent, const struct driver *drv,
 		if (CONFIG_IS_ENABLED(OF_CONTROL) && !CONFIG_IS_ENABLED(OF_PLATDATA)) {
 			if (uc->uc_drv->name && ofnode_valid(node))
 				dev_read_alias_seq(dev, &dev->req_seq);
+#if CONFIG_IS_ENABLED(OF_PRIOR_STAGE)
+			if (dev->req_seq == -1)
+				dev->req_seq =
+					uclass_find_next_free_req_seq(drv->id);
+#endif
 		} else {
 			dev->req_seq = uclass_find_next_free_req_seq(drv->id);
 		}
diff --git a/drivers/core/uclass.c b/drivers/core/uclass.c
index b33296542f..d7aedac351 100644
--- a/drivers/core/uclass.c
+++ b/drivers/core/uclass.c
@@ -269,7 +269,9 @@ int uclass_find_device_by_name(enum uclass_id id, const char *name,
 	return -ENODEV;
 }
 
-#if !CONFIG_IS_ENABLED(OF_CONTROL) || CONFIG_IS_ENABLED(OF_PLATDATA)
+#if !CONFIG_IS_ENABLED(OF_CONTROL) || \
+    CONFIG_IS_ENABLED(OF_PLATDATA) || \
+    CONFIG_IS_ENABLED(OF_PRIOR_STAGE)
 int uclass_find_next_free_req_seq(enum uclass_id id)
 {
 	struct uclass *uc;
-- 
2.23.0

^ permalink raw reply related	[flat|nested] 37+ messages in thread

* [U-Boot] [PATCH 2/2] dm: spi: Do not assume first SPI bus
  2019-09-06 11:51                   ` [U-Boot] [PATCH 0/2] dm: CONFIG_OF_PRIOR_STAGE request number fixes Thomas Fitzsimmons
  2019-09-06 11:51                     ` [U-Boot] [PATCH 1/2] dm: device: Request next sequence number Thomas Fitzsimmons
@ 2019-09-06 11:51                     ` Thomas Fitzsimmons
  2019-09-27  1:49                       ` Simon Glass
  2019-09-27 23:28                       ` sjg at google.com
  1 sibling, 2 replies; 37+ messages in thread
From: Thomas Fitzsimmons @ 2019-09-06 11:51 UTC (permalink / raw)
  To: u-boot

When CONFIG_OF_PRIOR_STAGE is enabled, this workaround was needed
before device_bind_common assigned request numbers sequentially in the
absence of aliases.

Signed-off-by: Thomas Fitzsimmons <fitzsim@fitzsim.org>
Cc: Bin Meng <bmeng.cn@gmail.com>
Cc: Simon Glass <sjg@chromium.org>
---
 drivers/spi/spi-uclass.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/spi/spi-uclass.c b/drivers/spi/spi-uclass.c
index 88cb2a1262..5e1f2232e5 100644
--- a/drivers/spi/spi-uclass.c
+++ b/drivers/spi/spi-uclass.c
@@ -275,7 +275,7 @@ int spi_get_bus_and_cs(int busnum, int cs, int speed, int mode,
 	bool created = false;
 	int ret;
 
-#if CONFIG_IS_ENABLED(OF_PLATDATA) || CONFIG_IS_ENABLED(OF_PRIOR_STAGE)
+#if CONFIG_IS_ENABLED(OF_PLATDATA)
 	ret = uclass_first_device_err(UCLASS_SPI, &bus);
 #else
 	ret = uclass_get_device_by_seq(UCLASS_SPI, busnum, &bus);
-- 
2.23.0

^ permalink raw reply related	[flat|nested] 37+ messages in thread

* [U-Boot] [PATCH 1/2] dm: device: Request next sequence number
  2019-09-06 11:51                     ` [U-Boot] [PATCH 1/2] dm: device: Request next sequence number Thomas Fitzsimmons
@ 2019-09-06 13:24                       ` Bin Meng
  2019-09-14 13:41                         ` Thomas Fitzsimmons
  0 siblings, 1 reply; 37+ messages in thread
From: Bin Meng @ 2019-09-06 13:24 UTC (permalink / raw)
  To: u-boot

Hi Thomas,

On Fri, Sep 6, 2019 at 7:52 PM Thomas Fitzsimmons <fitzsim@fitzsim.org> wrote:
>
> For CONFIG_OF_PRIOR_STAGE, in the absence of a device tree alias for a
> given device, use the next request number for that type of device.
> This allows aliases to be used when they're available, while still
> allowing unaliased devices to be probed.
>
> Signed-off-by: Thomas Fitzsimmons <fitzsim@fitzsim.org>
> Cc: Bin Meng <bmeng.cn@gmail.com>
> Cc: Simon Glass <sjg@chromium.org>
> ---
>  drivers/core/device.c | 5 +++++
>  drivers/core/uclass.c | 4 +++-
>  2 files changed, 8 insertions(+), 1 deletion(-)
>
> diff --git a/drivers/core/device.c b/drivers/core/device.c
> index 474c1642ee..ca8be208a9 100644
> --- a/drivers/core/device.c
> +++ b/drivers/core/device.c
> @@ -82,6 +82,11 @@ static int device_bind_common(struct udevice *parent, const struct driver *drv,
>                 if (CONFIG_IS_ENABLED(OF_CONTROL) && !CONFIG_IS_ENABLED(OF_PLATDATA)) {
>                         if (uc->uc_drv->name && ofnode_valid(node))
>                                 dev_read_alias_seq(dev, &dev->req_seq);
> +#if CONFIG_IS_ENABLED(OF_PRIOR_STAGE)

I was wondering whether we should limit such only for OF_PRIOR_STATE,
instead change the behaviors for all DM devices.

Because as I pointed out in
https://lists.denx.de/pipermail/u-boot/2019-August/382368.html, it
seems there are quite some codes in the existing code base that tried
to workaround such limitation in their own way.

> +                       if (dev->req_seq == -1)
> +                               dev->req_seq =
> +                                       uclass_find_next_free_req_seq(drv->id);
> +#endif
>                 } else {
>                         dev->req_seq = uclass_find_next_free_req_seq(drv->id);
>                 }
> diff --git a/drivers/core/uclass.c b/drivers/core/uclass.c
> index b33296542f..d7aedac351 100644
> --- a/drivers/core/uclass.c
> +++ b/drivers/core/uclass.c
> @@ -269,7 +269,9 @@ int uclass_find_device_by_name(enum uclass_id id, const char *name,
>         return -ENODEV;
>  }
>
> -#if !CONFIG_IS_ENABLED(OF_CONTROL) || CONFIG_IS_ENABLED(OF_PLATDATA)
> +#if !CONFIG_IS_ENABLED(OF_CONTROL) || \
> +    CONFIG_IS_ENABLED(OF_PLATDATA) || \
> +    CONFIG_IS_ENABLED(OF_PRIOR_STAGE)
>  int uclass_find_next_free_req_seq(enum uclass_id id)
>  {
>         struct uclass *uc;
> --

Regards,
Bin

^ permalink raw reply	[flat|nested] 37+ messages in thread

* [U-Boot] [PATCH 1/2] dm: device: Request next sequence number
  2019-09-06 13:24                       ` Bin Meng
@ 2019-09-14 13:41                         ` Thomas Fitzsimmons
  2019-09-27  1:49                           ` Simon Glass
  2019-09-27 23:28                           ` sjg at google.com
  0 siblings, 2 replies; 37+ messages in thread
From: Thomas Fitzsimmons @ 2019-09-14 13:41 UTC (permalink / raw)
  To: u-boot

Hi Bin,

Bin Meng <bmeng.cn@gmail.com> writes:

[...]

> On Fri, Sep 6, 2019 at 7:52 PM Thomas Fitzsimmons <fitzsim@fitzsim.org> wrote:
>>
>> For CONFIG_OF_PRIOR_STAGE, in the absence of a device tree alias for a
>> given device, use the next request number for that type of device.
>> This allows aliases to be used when they're available, while still
>> allowing unaliased devices to be probed.
>>
>> Signed-off-by: Thomas Fitzsimmons <fitzsim@fitzsim.org>
>> Cc: Bin Meng <bmeng.cn@gmail.com>
>> Cc: Simon Glass <sjg@chromium.org>
>> ---
>>  drivers/core/device.c | 5 +++++
>>  drivers/core/uclass.c | 4 +++-
>>  2 files changed, 8 insertions(+), 1 deletion(-)
>>
>> diff --git a/drivers/core/device.c b/drivers/core/device.c
>> index 474c1642ee..ca8be208a9 100644
>> --- a/drivers/core/device.c
>> +++ b/drivers/core/device.c
>> @@ -82,6 +82,11 @@ static int device_bind_common(struct udevice *parent, const struct driver *drv,
>>                 if (CONFIG_IS_ENABLED(OF_CONTROL) && !CONFIG_IS_ENABLED(OF_PLATDATA)) {
>>                         if (uc->uc_drv->name && ofnode_valid(node))
>>                                 dev_read_alias_seq(dev, &dev->req_seq);
>> +#if CONFIG_IS_ENABLED(OF_PRIOR_STAGE)
>
> I was wondering whether we should limit such only for OF_PRIOR_STATE,
> instead change the behaviors for all DM devices.

Maybe, though I wouldn't want to break assumptions made in this area by
non-OF_PRIOR_STAGE boards.

> Because as I pointed out in
> https://lists.denx.de/pipermail/u-boot/2019-August/382368.html, it
> seems there are quite some codes in the existing code base that tried
> to workaround such limitation in their own way.

I could create a separate config option to control this behavior, and
document what it does in Kconfig.  Then other ports could adopt it
gradually, and eventually we could make it unconditional.  I think
OF_PRIOR_STAGE should select the new option, since I can confirm this is
an improvement for my OF_PRIOR_STAGE-using board.

Thomas

^ permalink raw reply	[flat|nested] 37+ messages in thread

* [U-Boot] [PATCH v4 1/1] board: arm: Add support for Broadcom BCM7445
  2019-09-05 12:10                   ` Bin Meng
@ 2019-09-17  5:48                     ` Simon Glass
  0 siblings, 0 replies; 37+ messages in thread
From: Simon Glass @ 2019-09-17  5:48 UTC (permalink / raw)
  To: u-boot

Hi Bin,

On Thu, 5 Sep 2019 at 06:10, Bin Meng <bmeng.cn@gmail.com> wrote:
>
> Hi Simon,
>
> On Thu, Aug 29, 2019 at 11:24 PM Bin Meng <bmeng.cn@gmail.com> wrote:
> >
> > +Simon
> >
> > On Thu, Aug 29, 2019 at 1:24 AM Thomas Fitzsimmons <fitzsim@fitzsim.org> wrote:
> > >
> > > Hi Bin,
> > >
> > > Bin Meng <bmeng.cn@gmail.com> writes:
> > >
> > > > Hi Thomas,
> > > >
> > > > On Wed, Aug 28, 2019 at 6:31 AM Thomas Fitzsimmons <fitzsim@fitzsim.org> wrote:
> > > >>
> > > >> Hi Bin,
> > > >>
> > > >> Bin Meng <bmeng.cn@gmail.com> writes:
> > > >>
> > > >> > Hi Thomas,
> > > >> >
> > > >> > On Sat, Jun 9, 2018 at 6:06 AM Thomas Fitzsimmons <fitzsim@fitzsim.org> wrote:
> > > >> >>
> > > >> >> Add support for loading U-Boot on the Broadcom 7445 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@fitzsim.org>
> > > >> >> Cc: Stefan Roese <sr@denx.de>
> > > >> >> Cc: Tom Rini <trini@konsulko.com>
> > > >> >> Cc: Florian Fainelli <f.fainelli@gmail.com>
> > > >> >> ---
> > > >> >> Changes for v4:
> > > >> >>    - Use high timer register for get_ticks
> > > >> >>    - Move hard-coded register addresses from Kconfig to header
> > > >> >>    - Document I-cache/D-cache expectation
> > > >> >>
> > > >> >>  MAINTAINERS                                     |  10 +
> > > >> >>  arch/arm/Kconfig                                |  12 +
> > > >> >>  arch/arm/Makefile                               |   1 +
> > > >> >>  arch/arm/mach-bcmstb/Kconfig                    |  36 ++
> > > >> >>  arch/arm/mach-bcmstb/Makefile                   |   8 +
> > > >> >>  arch/arm/mach-bcmstb/include/mach/gpio.h        |  11 +
> > > >> >>  arch/arm/mach-bcmstb/include/mach/hardware.h    |  11 +
> > > >> >>  arch/arm/mach-bcmstb/include/mach/prior_stage.h |  30 ++
> > > >> >>  arch/arm/mach-bcmstb/include/mach/sdhci.h       |  15 +
> > > >> >>  arch/arm/mach-bcmstb/include/mach/timer.h       |  13 +
> > > >> >>  arch/arm/mach-bcmstb/lowlevel_init.S            |  21 ++
> > > >> >>  board/broadcom/bcmstb/MAINTAINERS               |   7 +
> > > >> >>  board/broadcom/bcmstb/Makefile                  |   8 +
> > > >> >>  board/broadcom/bcmstb/bcmstb.c                  | 194 +++++++++++
> > > >> >>  configs/bcm7445_defconfig                       |  27 ++
> > > >> >>  doc/README.bcm7xxx                              | 150 ++++++++
> > > >> >>  drivers/mmc/Kconfig                             |  11 +
> > > >> >>  drivers/mmc/Makefile                            |   1 +
> > > >> >>  drivers/mmc/bcmstb_sdhci.c                      |  67 ++++
> > > >> >>  drivers/spi/Kconfig                             |   7 +
> > > >> >>  drivers/spi/Makefile                            |   1 +
> > > >> >>  drivers/spi/bcmstb_spi.c                        | 439 ++++++++++++++++++++++++
> > > >> >>  drivers/spi/spi-uclass.c                        |   2 +-
> > > >> >>  dts/Kconfig                                     |   7 +
> > > >> >>  include/configs/bcm7445.h                       |  26 ++
> > > >> >>  include/configs/bcmstb.h                        | 183 ++++++++++
> > > >> >>  include/fdtdec.h                                |   4 +
> > > >> >>  lib/fdtdec.c                                    |   4 +
> > > >> >>  28 files changed, 1305 insertions(+), 1 deletion(-)
> > > >> >>  create mode 100644 arch/arm/mach-bcmstb/Kconfig
> > > >> >>  create mode 100644 arch/arm/mach-bcmstb/Makefile
> > > >> >>  create mode 100644 arch/arm/mach-bcmstb/include/mach/gpio.h
> > > >> >>  create mode 100644 arch/arm/mach-bcmstb/include/mach/hardware.h
> > > >> >>  create mode 100644 arch/arm/mach-bcmstb/include/mach/prior_stage.h
> > > >> >>  create mode 100644 arch/arm/mach-bcmstb/include/mach/sdhci.h
> > > >> >>  create mode 100644 arch/arm/mach-bcmstb/include/mach/timer.h
> > > >> >>  create mode 100644 arch/arm/mach-bcmstb/lowlevel_init.S
> > > >> >>  create mode 100644 board/broadcom/bcmstb/MAINTAINERS
> > > >> >>  create mode 100644 board/broadcom/bcmstb/Makefile
> > > >> >>  create mode 100644 board/broadcom/bcmstb/bcmstb.c
> > > >> >>  create mode 100644 configs/bcm7445_defconfig
> > > >> >>  create mode 100644 doc/README.bcm7xxx
> > > >> >>  create mode 100644 drivers/mmc/bcmstb_sdhci.c
> > > >> >>  create mode 100644 drivers/spi/bcmstb_spi.c
> > > >> >>  create mode 100644 include/configs/bcm7445.h
> > > >> >>  create mode 100644 include/configs/bcmstb.h
> > > >> >>
> > > >> >
> > > >> > [snip]
> > > >> >
> > > >> >> diff --git a/drivers/spi/spi-uclass.c b/drivers/spi/spi-uclass.c
> > > >> >> index d2d091f..c517d06 100644
> > > >> >> --- a/drivers/spi/spi-uclass.c
> > > >> >> +++ b/drivers/spi/spi-uclass.c
> > > >> >> @@ -273,7 +273,7 @@ int spi_get_bus_and_cs(int busnum, int cs, int speed, int mode,
> > > >> >>         bool created = false;
> > > >> >>         int ret;
> > > >> >>
> > > >> >> -#if CONFIG_IS_ENABLED(OF_PLATDATA)
> > > >> >> +#if CONFIG_IS_ENABLED(OF_PLATDATA) || CONFIG_IS_ENABLED(OF_PRIOR_STAGE)
> > > >> >
> > > >> > Could you please explain this change a little bit? Why should we call
> > > >> > uclass_first_device_err() for OF_PRIOR_STAGE?
> > > >> >
> > > >> >>         ret = uclass_first_device_err(UCLASS_SPI, &bus);
> > > >> >>  #else
> > > >> >>         ret = uclass_get_device_by_seq(UCLASS_SPI, busnum, &bus);
> > > >>
> > > >> On the BCM7445 eval board, the prior-stage-provided device tree does not
> > > >> have an alias for spi0, though it has aliases for other device types; I
> > > >> don't know why this is the case, but I don't have control over what the
> > > >> prior stage bootloader (Broadcom's BOLT) provides.  Without that alias,
> > > >> uclass_get_device_by_seq fails to find the SPI bus (and so U-Boot can't
> > > >> find the SPI flash device that stores its environment).
> > > >>
> > > >
> > > > I checked uclass_get_device_by_seq() and did not find any codes that
> > > > are trying to read aliases. Am I missing anything?
> > >
> > > Alias handling is not in the direct uclass_get_device_by_seq call chain,
> > > and it took some debugging to find this.  The requested sequence number
> > > is handled earlier in the boot, in device_bind_common:
> > >
> > >    dev->seq = -1;
> > >    dev->req_seq = -1;
> > >    if (CONFIG_IS_ENABLED(DM_SEQ_ALIAS) &&
> > >        (uc->uc_drv->flags & DM_UC_FLAG_SEQ_ALIAS)) {
> > >            /*
> > >             * Some devices, such as a SPI bus, I2C bus and serial ports
> > >             * are numbered using aliases.
> > >             *
> > >             * This is just a 'requested' sequence, and will be
> > >             * resolved (and ->seq updated) when the device is probed.
> > >             */
> > >            if (CONFIG_IS_ENABLED(OF_CONTROL) && !CONFIG_IS_ENABLED(OF_PLATDATA)) {
> > >                    if (uc->uc_drv->name && ofnode_valid(node))
> > >                            dev_read_alias_seq(dev, &dev->req_seq);
> > >            } else {
> > >                    dev->req_seq = uclass_find_next_free_req_seq(drv->id);
> > >            }
> > >    }
> > >
> > > If the prior stage bootloader provides no SPI bus alias, then
> > > dev_read_alias_seq fails, dev->req_seq stays unset (-1), and later when
> > > an attempt is made to access the SPI bus, the call to
> > > uclass_get_device_by_seq fails.
> >
> > Ah, I see. Thanks!
> >
> > >
> > > >> At the time, I checked other ARM device trees in the Linux kernel and
> > > >> not many set an alias for spi0, so I wrote the patch to choose the first
> > > >> SPI bus.  Doing so was in line with what CONFIG_OF_PLATDATA did on
> > > >> boards that wanted to avoid device tree accesses.
> > > >>
> > > >
> > > > Based on what you said, the adding of OF_PRIOR_STAGE here sounds like a hack.
> > >
> > > Yeah, it makes an assumption about which SPI bus to use, that may or may
> > > not be valid on other boards.
> > >
> > > >> I see that since I introduced CONFIG_OF_PRIOR_STAGE, several other ports
> > > >> have started using it, so there's probably a need to generalize this; if
> > > >> other prior stage bootloaders provide SPI aliases then there should be a
> > > >> way for this code to use them.
> > > >>
> > > >
> > > > I think the correct way is to call uclass_get_device_by_seq().
> > > > CONFIG_OF_PRIOR_STAGE should not imply such behavior.
> > >
> > > OK, but without other changes this would break boards that rely on the
> > > above assumption (for example BCM7445).
> > >
> > > I'm experimenting with patches that work on BCM7445 and eliminate the
> > > SPI bus assumption but I don't know what effect they might have on other
> > > ports that use OF_PRIOR_STAGE.
> > >
> > > In general it seems like a good idea to use the prior-stage-provided
> > > aliases, but the question is what to do when an alias is missing; maybe
> > > always fall back to calling uclass_find_next_free_req_seq?
> >
> > I tend to agree. As I see lots of places in U-Boot sources, like below:
> >
> > drivers/i2c/intel_i2c.c::intel_i2c_bind()
> >
> > if (device_is_on_pci_bus(dev)) {
> >                /*
> >                 * ToDo:
> >                 * Setting req_seq in the driver is probably not recommended.
> >                 * But without a DT alias the number is not configured. And
> >                 * using this driver is impossible for PCIe I2C devices.
> >                 * This can be removed, once a better (correct) way for this
> >                 * is found and implemented.
> >                 */
> >                dev->req_seq = num_cards;
> >
> > And another example:
> > drivers/usb/host/ehci-vf.c::vf_usb_bind()
> >
> >        /*
> >         * Without this hack, if we return ENODEV for USB Controller 0, on
> >         * probe for the next controller, USB Controller 1 will be given a
> >         * sequence number of 0. This conflicts with our requirement of
> >         * sequence numbers while initialising the peripherals.
> >         */
> >        dev->req_seq = num_controllers;
> >
> > Simon, do you think we should change the behavior of dev->req_seq in
> > the device bind for uclass drivers with DM_UC_FLAG_SEQ_ALIAS flag?
> >
>
> Would you please give some comments regarding this?

Yes I think we should do something here.

I am not quite clear on the best action though.

At present ->seq is set when the device is proved and dropped when it
is removed. This is good in the sense that different devices can 'take
over' a sequence number. But in practice I don't think we have found
that to be very useful.

An alternative would be to do this processing when the device is
bound. We might then remove the two separate values and just have one.
However it would mean processing aliases which could potentially be
slow.

In general I had hoped that sequence numbers would become less
important in U-Boot, as they have in Linux. But for now we need to
deal with it.

>
> > >
> > > Have you found a board for which uclass_get_device_by_seq works for SPI
> > > and uclass_first_device_err does the wrong thing?  Is it a publicly
> > > available port that I can have a look at?
> >
> > No, I was not indicating an error like uclass_get_device_by_seq works
> > for SPI and uclass_first_device_err does the wrong thing. The issue
> > with your implementation is that it forces probing the first SPI
> > controller and ignore the "busnum" completely. This makes a board with
> > multiple SPI controllers unable to probe other controllers than the
> > very first one.
>
> Regards,
> Bin

Regards,
Simon

^ permalink raw reply	[flat|nested] 37+ messages in thread

* [U-Boot] [PATCH 1/2] dm: device: Request next sequence number
  2019-09-14 13:41                         ` Thomas Fitzsimmons
@ 2019-09-27  1:49                           ` Simon Glass
  2019-09-27 23:28                           ` sjg at google.com
  1 sibling, 0 replies; 37+ messages in thread
From: Simon Glass @ 2019-09-27  1:49 UTC (permalink / raw)
  To: u-boot

On Sat, 14 Sep 2019 at 06:41, Thomas Fitzsimmons <fitzsim@fitzsim.org> wrote:
>
> Hi Bin,
>
> Bin Meng <bmeng.cn@gmail.com> writes:
>
> [...]
>
> > On Fri, Sep 6, 2019 at 7:52 PM Thomas Fitzsimmons <fitzsim@fitzsim.org> wrote:
> >>
> >> For CONFIG_OF_PRIOR_STAGE, in the absence of a device tree alias for a
> >> given device, use the next request number for that type of device.
> >> This allows aliases to be used when they're available, while still
> >> allowing unaliased devices to be probed.
> >>
> >> Signed-off-by: Thomas Fitzsimmons <fitzsim@fitzsim.org>
> >> Cc: Bin Meng <bmeng.cn@gmail.com>
> >> Cc: Simon Glass <sjg@chromium.org>
> >> ---
> >>  drivers/core/device.c | 5 +++++
> >>  drivers/core/uclass.c | 4 +++-
> >>  2 files changed, 8 insertions(+), 1 deletion(-)
> >>
> >> diff --git a/drivers/core/device.c b/drivers/core/device.c
> >> index 474c1642ee..ca8be208a9 100644
> >> --- a/drivers/core/device.c
> >> +++ b/drivers/core/device.c
> >> @@ -82,6 +82,11 @@ static int device_bind_common(struct udevice *parent, const struct driver *drv,
> >>                 if (CONFIG_IS_ENABLED(OF_CONTROL) && !CONFIG_IS_ENABLED(OF_PLATDATA)) {
> >>                         if (uc->uc_drv->name && ofnode_valid(node))
> >>                                 dev_read_alias_seq(dev, &dev->req_seq);
> >> +#if CONFIG_IS_ENABLED(OF_PRIOR_STAGE)
> >
> > I was wondering whether we should limit such only for OF_PRIOR_STATE,
> > instead change the behaviors for all DM devices.
>
> Maybe, though I wouldn't want to break assumptions made in this area by
> non-OF_PRIOR_STAGE boards.
>
> > Because as I pointed out in
> > https://lists.denx.de/pipermail/u-boot/2019-August/382368.html, it
> > seems there are quite some codes in the existing code base that tried
> > to workaround such limitation in their own way.
>
> I could create a separate config option to control this behavior, and
> document what it does in Kconfig.  Then other ports could adopt it
> gradually, and eventually we could make it unconditional.  I think
> OF_PRIOR_STAGE should select the new option, since I can confirm this is
> an improvement for my OF_PRIOR_STAGE-using board.
>
> Thomas

Reviewed-by: Simon Glass <sjg@chromium.org>

It is best to use if() instead of #if if possible.

^ permalink raw reply	[flat|nested] 37+ messages in thread

* [U-Boot] [PATCH 2/2] dm: spi: Do not assume first SPI bus
  2019-09-06 11:51                     ` [U-Boot] [PATCH 2/2] dm: spi: Do not assume first SPI bus Thomas Fitzsimmons
@ 2019-09-27  1:49                       ` Simon Glass
  2019-09-27 23:28                       ` sjg at google.com
  1 sibling, 0 replies; 37+ messages in thread
From: Simon Glass @ 2019-09-27  1:49 UTC (permalink / raw)
  To: u-boot

On Fri, 6 Sep 2019 at 04:52, Thomas Fitzsimmons <fitzsim@fitzsim.org> wrote:
>
> When CONFIG_OF_PRIOR_STAGE is enabled, this workaround was needed
> before device_bind_common assigned request numbers sequentially in the
> absence of aliases.
>
> Signed-off-by: Thomas Fitzsimmons <fitzsim@fitzsim.org>
> Cc: Bin Meng <bmeng.cn@gmail.com>
> Cc: Simon Glass <sjg@chromium.org>
> ---
>  drivers/spi/spi-uclass.c | 2 +-
>  1 file changed, 1 insertion(+), 1 deletion(-)

Reviewed-by: Simon Glass <sjg@chromium.org>

^ permalink raw reply	[flat|nested] 37+ messages in thread

* [U-Boot] [PATCH 2/2] dm: spi: Do not assume first SPI bus
  2019-09-06 11:51                     ` [U-Boot] [PATCH 2/2] dm: spi: Do not assume first SPI bus Thomas Fitzsimmons
  2019-09-27  1:49                       ` Simon Glass
@ 2019-09-27 23:28                       ` sjg at google.com
  1 sibling, 0 replies; 37+ messages in thread
From: sjg at google.com @ 2019-09-27 23:28 UTC (permalink / raw)
  To: u-boot

On Fri, 6 Sep 2019 at 04:52, Thomas Fitzsimmons <fitzsim@fitzsim.org> wrote:
>
> When CONFIG_OF_PRIOR_STAGE is enabled, this workaround was needed
> before device_bind_common assigned request numbers sequentially in the
> absence of aliases.
>
> Signed-off-by: Thomas Fitzsimmons <fitzsim@fitzsim.org>
> Cc: Bin Meng <bmeng.cn@gmail.com>
> Cc: Simon Glass <sjg@chromium.org>
> ---
>  drivers/spi/spi-uclass.c | 2 +-
>  1 file changed, 1 insertion(+), 1 deletion(-)

Reviewed-by: Simon Glass <sjg@chromium.org>

Applied to u-boot-dm/next, thanks!

^ permalink raw reply	[flat|nested] 37+ messages in thread

* [U-Boot] [PATCH 1/2] dm: device: Request next sequence number
  2019-09-14 13:41                         ` Thomas Fitzsimmons
  2019-09-27  1:49                           ` Simon Glass
@ 2019-09-27 23:28                           ` sjg at google.com
  1 sibling, 0 replies; 37+ messages in thread
From: sjg at google.com @ 2019-09-27 23:28 UTC (permalink / raw)
  To: u-boot

On Sat, 14 Sep 2019 at 06:41, Thomas Fitzsimmons <fitzsim@fitzsim.org> wrote:
>
> Hi Bin,
>
> Bin Meng <bmeng.cn@gmail.com> writes:
>
> [...]
>
> > On Fri, Sep 6, 2019 at 7:52 PM Thomas Fitzsimmons <fitzsim@fitzsim.org> wrote:
> >>
> >> For CONFIG_OF_PRIOR_STAGE, in the absence of a device tree alias for a
> >> given device, use the next request number for that type of device.
> >> This allows aliases to be used when they're available, while still
> >> allowing unaliased devices to be probed.
> >>
> >> Signed-off-by: Thomas Fitzsimmons <fitzsim@fitzsim.org>
> >> Cc: Bin Meng <bmeng.cn@gmail.com>
> >> Cc: Simon Glass <sjg@chromium.org>
> >> ---
> >>  drivers/core/device.c | 5 +++++
> >>  drivers/core/uclass.c | 4 +++-
> >>  2 files changed, 8 insertions(+), 1 deletion(-)
> >>
Applied to u-boot-dm/next, thanks!

^ permalink raw reply	[flat|nested] 37+ messages in thread

end of thread, other threads:[~2019-09-27 23:28 UTC | newest]

Thread overview: 37+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2018-05-06 11:09 [U-Boot] [PATCH 0/1] board: arm: Add support for Broadcom BCM7445D0 Thomas Fitzsimmons
2018-05-06 11:09 ` [U-Boot] [PATCH 1/1] " Thomas Fitzsimmons
2018-05-07 23:48   ` Tom Rini
2018-05-24  0:47     ` Thomas Fitzsimmons
2018-05-08 17:44   ` Florian Fainelli
2018-05-10 13:04     ` Thomas Fitzsimmons
2018-05-10 17:43       ` Florian Fainelli
2018-06-06 20:39         ` Thomas Fitzsimmons
2018-06-06 22:06           ` Florian Fainelli
2018-05-24  1:24 ` [U-Boot] [PATCH v2 0/1] board: arm: Add support for Broadcom BCM7445 Thomas Fitzsimmons
2018-05-24  1:24   ` [U-Boot] [PATCH v2 1/1] " Thomas Fitzsimmons
2018-06-06 11:16     ` [U-Boot] [U-Boot, v2, " Tom Rini
2018-06-06 19:32       ` Thomas Fitzsimmons
2018-06-06 18:35   ` [U-Boot] [PATCH v3 0/1] " Thomas Fitzsimmons
2018-06-06 18:35     ` [U-Boot] [PATCH v3 1/1] " Thomas Fitzsimmons
2018-06-07 16:54       ` Florian Fainelli
2018-06-08 22:25         ` Thomas Fitzsimmons
2018-06-08 21:59     ` [U-Boot] [PATCH v4 0/1] " Thomas Fitzsimmons
2018-06-08 21:59       ` [U-Boot] [PATCH v4 1/1] " Thomas Fitzsimmons
2018-07-11 12:42         ` [U-Boot] [U-Boot, v4, " Tom Rini
2019-08-26 15:54         ` [U-Boot] [PATCH v4 " Bin Meng
2019-08-27 22:31           ` Thomas Fitzsimmons
2019-08-28 10:19             ` Bin Meng
2019-08-28 17:24               ` Thomas Fitzsimmons
2019-08-29 15:24                 ` Bin Meng
2019-09-05 12:10                   ` Bin Meng
2019-09-17  5:48                     ` Simon Glass
2019-09-06 11:51                   ` [U-Boot] [PATCH 0/2] dm: CONFIG_OF_PRIOR_STAGE request number fixes Thomas Fitzsimmons
2019-09-06 11:51                     ` [U-Boot] [PATCH 1/2] dm: device: Request next sequence number Thomas Fitzsimmons
2019-09-06 13:24                       ` Bin Meng
2019-09-14 13:41                         ` Thomas Fitzsimmons
2019-09-27  1:49                           ` Simon Glass
2019-09-27 23:28                           ` sjg at google.com
2019-09-06 11:51                     ` [U-Boot] [PATCH 2/2] dm: spi: Do not assume first SPI bus Thomas Fitzsimmons
2019-09-27  1:49                       ` Simon Glass
2019-09-27 23:28                       ` sjg at google.com
2019-08-26 15:50   ` [U-Boot] [PATCH v2 0/1] board: arm: Add support for Broadcom BCM7445 Bin Meng

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.