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 <fitz...@fitzsim.org> Cc: Stefan Roese <s...@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 <fitz...@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 <fitz...@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 <fitz...@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 <fitz...@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 <fitz...@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 <fitz...@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 <fitz...@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 <fitz...@fitzsim.org> + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include <asm/io.h> +#include <common.h> +#include <config.h> +#include <dm.h> +#include <errno.h> +#include <fdtdec.h> +#include <malloc.h> +#include <spi.h> + +DECLARE_GLOBAL_DATA_PTR; + +#define SPBR_MIN 8 +#define BITS_PER_WORD 8 + +#define NUM_TXRAM 32 +#define NUM_RXRAM 32 +#define NUM_CDRAM 16 + +#ifdef DEBUG +static int debug_tx_rx; +#define D(fmt, args...) debug_cond(debug_tx_rx, fmt, ##args) +#else +#define D(fmt, args...) +#endif + +/* MSPI registers. BSPI is disabled. */ +struct bcmstb_spi_regs { + u32 spcr0_lsb; /* 0x000 */ + u32 spcr0_msb; /* 0x004 */ + u32 spcr1_lsb; /* 0x008 */ + u32 spcr1_msb; /* 0x00c */ + u32 newqp; /* 0x010 */ + u32 endqp; /* 0x014 */ + u32 spcr2; /* 0x018 */ + u32 reserved0; /* 0x01c */ + u32 mspi_status; /* 0x020 */ + u32 cptqp; /* 0x024 */ + u32 spcr3; /* 0x028 */ + u32 revision; /* 0x02c */ + u32 reserved1[4]; /* 0x030 */ + u32 txram[NUM_TXRAM]; /* 0x040 */ + u32 rxram[NUM_RXRAM]; /* 0x0c0 */ + u32 cdram[NUM_CDRAM]; /* 0x140 */ +}; + +struct bcmstb_spi_platdata { + struct bcmstb_spi_regs *regs; +}; + +struct bcmstb_spi_priv { + struct bcmstb_spi_regs *regs; + int default_cs; + int curr_cs; + uint tx_slot; + uint rx_slot; + u8 saved_cmd[NUM_CDRAM]; + uint saved_cmd_len; + void *saved_din_addr; +}; + +/* + * If we could rely on the prior stage bootloader to insert a "spi0" + * alias, we could enable CONFIG_DM_SEQ_ALIAS and omit + * bcmstb_spi_bind. We cannot rely on this behaviour, so we have to + * handle binding explicitly. + */ +static int bcmstb_spi_bind(struct udevice *bus) +{ + char spi0_name[30]; + int node = dev_of_offset(bus); + + memset(spi0_name, 0, sizeof(spi0_name)); + + debug("bcmstb_spi_bind: %s, ", bus->name); + + snprintf(spi0_name, sizeof(spi0_name), "spi@%08x", + CONFIG_BCMSTB_SPI_BASE); + if (strcmp(fdt_get_name(gd->fdt_blob, node, NULL), + spi0_name) == 0) { + bus->req_seq = 0; + } + + debug("%d\n", bus->req_seq); + + return 0; +} + +static int bcmstb_spi_ofdata_to_platdata(struct udevice *bus) +{ + struct bcmstb_spi_platdata *plat = dev_get_platdata(bus); + const void *blob = gd->fdt_blob; + int node = dev_of_offset(bus); + u32 address = 0; + int code = 0; + + code = fdtdec_get_int_array(blob, node, "reg", &address, 1); + if (code != 0) { + printf("bcmstb_spi_ofdata_to_platdata:" + " Failed to read reg property\n"); + return code; + } + + plat->regs = (struct bcmstb_spi_regs *)address; + D("spi_xfer: tx regs: %p\n", &plat->regs->txram[0]); + D("spi_xfer: rx regs: %p\n", &plat->regs->rxram[0]); + + return 0; +} + +static void bcmstb_spi_hw_set_parms(struct bcmstb_spi_priv *priv) +{ + writel(SPBR_MIN, &priv->regs->spcr0_lsb); + writel(BITS_PER_WORD << 2 | SPI_MODE_3, &priv->regs->spcr0_msb); +} + +static void bcmstb_spi_enable_interrupt(u32 mask) +{ + BDEV_SET_RB(CONFIG_BCHP_HIF_SPI_INTR2_CPU_MASK_CLEAR, mask); +} + +static void bcmstb_spi_disable_interrupt(u32 mask) +{ + BDEV_SET_RB(CONFIG_BCHP_HIF_SPI_INTR2_CPU_MASK_SET, mask); +} + +static void bcmstb_spi_clear_interrupt(u32 mask) +{ + BDEV_SET_RB(CONFIG_BCHP_HIF_SPI_INTR2_CPU_CLEAR, mask); +} + +static int bcmstb_spi_probe(struct udevice *bus) +{ + struct bcmstb_spi_platdata *plat = dev_get_platdata(bus); + struct bcmstb_spi_priv *priv = dev_get_priv(bus); + + priv->regs = plat->regs; + priv->default_cs = 0; + priv->curr_cs = -1; + priv->tx_slot = 0; + priv->rx_slot = 0; + memset(priv->saved_cmd, 0, NUM_CDRAM); + priv->saved_cmd_len = 0; + priv->saved_din_addr = NULL; + + /* Disable BSPI. */ + BDEV_WR_RB(CONFIG_BCHP_BSPI_MAST_N_BOOT_CTRL, 1); + + /* Set up interrupts. */ + bcmstb_spi_disable_interrupt(0xffffffff); + bcmstb_spi_clear_interrupt(0xffffffff); + bcmstb_spi_enable_interrupt( + CONFIG_BCHP_HIF_SPI_INTR2_CPU_SET_MSPI_DONE_MASK); + + /* Set up control registers. */ + writel(0, &priv->regs->spcr1_lsb); + writel(0, &priv->regs->spcr1_msb); + writel(0, &priv->regs->newqp); + writel(0, &priv->regs->endqp); + writel(CONFIG_BCHP_HIF_MSPI_SPCR2_SPIFIE_MASK, &priv->regs->spcr2); + writel(0, &priv->regs->spcr3); + + bcmstb_spi_hw_set_parms(priv); + + return 0; +} + +static int bcmstb_spi_remove(struct udevice *dev) +{ + return 0; +} + +static int bcmstb_spi_claim_bus(struct udevice *dev) +{ + return 0; +} + +static int bcmstb_spi_release_bus(struct udevice *dev) +{ + return 0; +} + +static void bcmstb_spi_submit(struct bcmstb_spi_priv *priv, bool done) +{ + D("WR NEWQP: %d\n", 0); + writel(0, &priv->regs->newqp); + + D("WR ENDQP: %d\n", priv->tx_slot - 1); + writel(priv->tx_slot - 1, &priv->regs->endqp); + + if (done) { + D("WR CDRAM[%d]: %02x\n", priv->tx_slot - 1, + readl(&priv->regs->cdram[priv->tx_slot - 1]) & ~0x80); + writel(readl(&priv->regs->cdram[priv->tx_slot - 1]) & ~0x80, + &priv->regs->cdram[priv->tx_slot - 1]); + } + + /* Force chip select first time. */ + if (priv->curr_cs != priv->default_cs) { + D("spi_xfer: switching chip select to %d\n", + priv->default_cs); + BDEV_WR_RB(CONFIG_BCHP_EBI_CS_SPI_SELECT, + (BDEV_RD(CONFIG_BCHP_EBI_CS_SPI_SELECT) & + ~0xff) | (1 << priv->default_cs)); + udelay(10); + priv->curr_cs = priv->default_cs; + } + + D("WR WRITE_LOCK: %02x\n", 1); + BDEV_WR_F_RB(HIF_MSPI_WRITE_LOCK, WRITE_LOCK, 1); + + D("WR SPCR2: %02x\n", + CONFIG_BCHP_HIF_MSPI_SPCR2_SPIFIE_MASK | + CONFIG_BCHP_HIF_MSPI_SPCR2_SPE_MASK | + CONFIG_BCHP_HIF_MSPI_SPCR2_CONT_AFTER_CMD_MASK); + writel(CONFIG_BCHP_HIF_MSPI_SPCR2_SPIFIE_MASK | + CONFIG_BCHP_HIF_MSPI_SPCR2_SPE_MASK | + CONFIG_BCHP_HIF_MSPI_SPCR2_CONT_AFTER_CMD_MASK, + &priv->regs->spcr2); +} + +static int bcmstb_spi_wait(struct bcmstb_spi_regs *regs) +{ + u32 start_time = get_timer(0); + u32 status = readl(®s->mspi_status); + + while (!(status & 1)) { + if (get_timer(start_time) > + CONFIG_SYS_BCMSTB_SPI_WAIT) { + return -ETIMEDOUT; + } + status = readl(®s->mspi_status); + } + + writel(readl(®s->mspi_status) & ~1, ®s->mspi_status); + bcmstb_spi_clear_interrupt( + CONFIG_BCHP_HIF_SPI_INTR2_CPU_SET_MSPI_DONE_MASK); + + return 0; +} + +static int bcmstb_spi_xfer(struct udevice *dev, unsigned int bitlen, + const void *dout, void *din, unsigned long flags) +{ + uint len = bitlen / 8; + uint tx_len = len; + uint rx_len = len; + const u8 *out_bytes = (u8 *)dout; + u8 *in_bytes = (u8 *)din; + struct udevice *bus = dev_get_parent(dev); + struct bcmstb_spi_priv *priv = dev_get_priv(bus); + struct bcmstb_spi_regs *regs = priv->regs; + + D("spi_xfer: %d, t: %p, r: %p, f: %lx\n", len, dout, din, flags); + D("spi_xfer: chip select: %x\n", + readl(CONFIG_BCHP_EBI_CS_SPI_SELECT) & 0xff); + D("spi_xfer: tx addr: %p\n", ®s->txram[0]); + D("spi_xfer: rx addr: %p\n", ®s->rxram[0]); + D("spi_xfer: cd addr: %p\n", ®s->cdram[0]); + + if (flags & SPI_XFER_END) { + D("spi_xfer: clearing saved din address: %p\n", + priv->saved_din_addr); + priv->saved_din_addr = NULL; + priv->saved_cmd_len = 0; + memset(priv->saved_cmd, 0, NUM_CDRAM); + } + + if (bitlen == 0) + return 0; + + if (bitlen % 8) { + printf("bcmstb_spi_xfer: Non-byte-aligned transfer\n"); + return -EOPNOTSUPP; + } + + if (flags & ~(SPI_XFER_BEGIN | SPI_XFER_END)) { + printf("bcmstb_spi_xfer: Unsupported flags: %lx\n", flags); + return -EOPNOTSUPP; + } + + if (flags & SPI_XFER_BEGIN) { + priv->tx_slot = 0; + priv->rx_slot = 0; + + if (out_bytes && len > NUM_CDRAM) { + printf("bcmstb_spi_xfer: Unable to save transfer\n"); + return -EOPNOTSUPP; + } + + if (out_bytes && !(flags & SPI_XFER_END)) { + /* + * This is the start of a transmit operation + * that will need repeating if the calling + * code polls for the result. Save it for + * subsequent transmission. + */ + D("spi_xfer: saving command: %x, %d\n", + out_bytes[0], len); + priv->saved_cmd_len = len; + memcpy(priv->saved_cmd, out_bytes, priv->saved_cmd_len); + } + } + + if (!(flags & (SPI_XFER_BEGIN | SPI_XFER_END))) { + if (priv->saved_din_addr == din) { + /* + * The caller is polling for status. Repeat + * the last transmission. + */ + int code = 0; + + D("spi_xfer: Making recursive call\n"); + code = bcmstb_spi_xfer(dev, priv->saved_cmd_len * 8, + priv->saved_cmd, NULL, + SPI_XFER_BEGIN); + if (code) { + printf("bcmstb_spi_xfer:" + " Recursive call failed\n"); + return code; + } + } else { + D("spi_xfer: saving din address: %p\n", din); + priv->saved_din_addr = din; + } + } + + while (rx_len > 0) { + priv->rx_slot = priv->tx_slot; + + while (priv->tx_slot < NUM_CDRAM && tx_len > 0) { + bcmstb_spi_hw_set_parms(priv); + D("WR TXRAM[%d]: %02x\n", priv->tx_slot, + out_bytes ? out_bytes[len - tx_len] : 0xff); + writel(out_bytes ? out_bytes[len - tx_len] : 0xff, + ®s->txram[priv->tx_slot << 1]); + D("WR CDRAM[%d]: %02x\n", priv->tx_slot, 0x8e); + writel(0x8e, ®s->cdram[priv->tx_slot]); + priv->tx_slot++; + tx_len--; + if (!in_bytes) + rx_len--; + } + + D("spi_xfer: early return clauses: %d, %d, %d\n", + len <= NUM_CDRAM, + !in_bytes, + (flags & (SPI_XFER_BEGIN | SPI_XFER_END)) == SPI_XFER_BEGIN); + if (len <= NUM_CDRAM && + !in_bytes && + (flags & (SPI_XFER_BEGIN | SPI_XFER_END)) == SPI_XFER_BEGIN) + return 0; + + bcmstb_spi_submit(priv, tx_len == 0); + + if (bcmstb_spi_wait(regs) == -ETIMEDOUT) { + printf("bcmstb_spi_xfer: Timed out\n"); + return -ETIMEDOUT; + } + + priv->tx_slot %= NUM_CDRAM; + + if (in_bytes) { + while (priv->rx_slot < NUM_CDRAM && rx_len > 0) { + in_bytes[len - rx_len] = + readl(®s->rxram[(priv->rx_slot << 1) + + 1]) + & 0xff; + D("RD RXRAM[%d]: %02x\n", + priv->rx_slot, in_bytes[len - rx_len]); + priv->rx_slot++; + rx_len--; + } + } + } + + if (flags & SPI_XFER_END) { + D("WR WRITE_LOCK: %02x\n", 0); + BDEV_WR_F_RB(HIF_MSPI_WRITE_LOCK, WRITE_LOCK, 0); + } + + return 0; +} + +static int bcmstb_spi_set_speed(struct udevice *dev, uint speed) +{ + return 0; +} + +static int bcmstb_spi_set_mode(struct udevice *dev, uint mode) +{ + return 0; +} + +static const struct dm_spi_ops bcmstb_spi_ops = { + .claim_bus = bcmstb_spi_claim_bus, + .release_bus = bcmstb_spi_release_bus, + .xfer = bcmstb_spi_xfer, + .set_speed = bcmstb_spi_set_speed, + .set_mode = bcmstb_spi_set_mode, +}; + +static const struct udevice_id bcmstb_spi_ids[] = { + { .compatible = "brcm,spi-brcmstb" }, + { } +}; + +U_BOOT_DRIVER(bcmstb_spi) = { + .name = "bcmstb_spi", + .id = UCLASS_SPI, + .of_match = bcmstb_spi_ids, + .ops = &bcmstb_spi_ops, + .ofdata_to_platdata = bcmstb_spi_ofdata_to_platdata, + .probe = bcmstb_spi_probe, + .remove = bcmstb_spi_remove, + .platdata_auto_alloc_size = sizeof(struct bcmstb_spi_platdata), + .priv_auto_alloc_size = sizeof(struct bcmstb_spi_priv), + .bind = bcmstb_spi_bind, +}; diff --git a/dts/Kconfig b/dts/Kconfig index 0cef225..074784b 100644 --- a/dts/Kconfig +++ b/dts/Kconfig @@ -101,6 +101,12 @@ config OF_HOSTFILE This is only useful for Sandbox. Use the -d flag to U-Boot to specify the file to read. +config OF_PRIOR_STAGE + bool "Prior stage bootloader DTB for DT control" + help + If this option is enabled, DTB will be read from a memory + location passed to U-Boot by the prior stage bootloader. + endchoice config DEFAULT_DEVICE_TREE diff --git a/include/configs/bcm7445d0.h b/include/configs/bcm7445d0.h new file mode 100644 index 0000000..36155c7 --- /dev/null +++ b/include/configs/bcm7445d0.h @@ -0,0 +1,227 @@ +/* + * (C) Copyright 2018 + * Cisco Systems, Inc. <www.cisco.com> + * + * Author : + * Thomas Fitzsimmons <fitz...@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 <fitz...@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 _______________________________________________ U-Boot mailing list U-Boot@lists.denx.de https://lists.denx.de/listinfo/u-boot