This implements esdhc xload support for LS1028a. Unlike LS1046a we use TF-A rather than obsoleted PPA for EL3, so this code also starts the TF-A. Signed-off-by: Sascha Hauer <s.hauer@xxxxxxxxxxxxxx> --- drivers/mci/imx-esdhc-pbl.c | 55 +++++++++++++++++++++++++++- firmware/Kconfig | 3 ++ firmware/Makefile | 1 + include/mach/layerscape/layerscape.h | 12 ++++++ include/mach/layerscape/xload.h | 4 ++ 5 files changed, 74 insertions(+), 1 deletion(-) diff --git a/drivers/mci/imx-esdhc-pbl.c b/drivers/mci/imx-esdhc-pbl.c index c13830d726..2c74d101e4 100644 --- a/drivers/mci/imx-esdhc-pbl.c +++ b/drivers/mci/imx-esdhc-pbl.c @@ -9,6 +9,8 @@ #include <asm/sections.h> #include <asm/cache.h> #include <mach/imx/xload.h> +#include <firmware.h> +#include <asm/atf_common.h> #ifdef CONFIG_ARCH_IMX #include <mach/imx/atf.h> #include <mach/imx/imx6-regs.h> @@ -319,7 +321,8 @@ static int layerscape_esdhc_load_image(struct fsl_esdhc_host *host, void *adr, u val |= div_val; sdhci_write32(&host->sdhci, SDHCI_CLOCK_CONTROL__TIMEOUT_CONTROL__SOFTWARE_RESET, val); - sdhci_write32(&host->sdhci, ESDHC_DMA_SYSCTL, ESDHC_SYSCTL_DMA_SNOOP); + sdhci_write32(&host->sdhci, ESDHC_DMA_SYSCTL, + ESDHC_SYSCTL_DMA_SNOOP | ESDHC_SYSCTL_PERIPHERAL_CLK_SEL); ret = esdhc_read_blocks(host, adr, size); if (ret) { @@ -373,4 +376,54 @@ int ls1046a_esdhc_start_image(unsigned long r0, unsigned long r1, unsigned long return -EINVAL; } + +static int ls1028a_esdhc_start_image(void __iomem *base, struct dram_regions_info *dram_info) +{ + struct esdhc_soc_data data = { + .flags = ESDHC_FLAG_MULTIBLK_NO_INT, + }; + struct fsl_esdhc_host host = { + .sdhci.base = base, + .socdata = &data, + }; + void *sdram = (void *)0x80000000; + void (*bl31)(void) = (void *)0xfbe00000; + size_t bl31_size; + void *bl31_image; + struct bl2_to_bl31_params_mem_v2 *params; + unsigned long size = ALIGN(barebox_image_size + LS1046A_SD_IMAGE_OFFSET, 512); + void (*barebox)(unsigned long, unsigned long, unsigned long) = + (sdram + LS1046A_SD_IMAGE_OFFSET); + int ret; + + ret = layerscape_esdhc_load_image(&host, sdram, size, 8 << 4); + if (ret) + return ret; + + get_builtin_firmware_ext(ls1028a_bl31_bin, barebox, &bl31_image, &bl31_size); + memcpy(bl31, bl31_image, bl31_size); + + /* Setup an initial stack for EL2 */ + asm volatile("msr sp_el2, %0" : : "r" ((unsigned long)barebox - 16) : "cc"); + + params = bl2_plat_get_bl31_params_v2(0, (uintptr_t)barebox, 0); + params->bl31_ep_info.args.arg3 = (unsigned long)dram_info; + + printf("Starting bl31\n"); + + bl31_entry_v2((uintptr_t)bl31, ¶ms->bl_params, NULL); + + return -EINVAL; +} + +int ls1028a_esdhc1_start_image(struct dram_regions_info *dram_info) +{ + return ls1028a_esdhc_start_image(IOMEM(0x2140000), dram_info); +} + +int ls1028a_esdhc2_start_image(struct dram_regions_info *dram_info) +{ + return ls1028a_esdhc_start_image(IOMEM(0x2150000), dram_info); +} + #endif diff --git a/firmware/Kconfig b/firmware/Kconfig index 38fbf85555..2785c4aabe 100644 --- a/firmware/Kconfig +++ b/firmware/Kconfig @@ -58,4 +58,7 @@ config FIRMWARE_CCBV2_OPTEE depends on MACH_WEBASTO_CCBV2 && PBL_OPTEE default y +config FIRMWARE_LS1028A_ATF + bool + endmenu diff --git a/firmware/Makefile b/firmware/Makefile index 51d98d54bf..9c3ffa4289 100644 --- a/firmware/Makefile +++ b/firmware/Makefile @@ -29,6 +29,7 @@ pbl-firmware-$(CONFIG_ARCH_RK3399_OPTEE) += rk3399-op-tee.bin firmware-$(CONFIG_DRIVER_NET_FSL_FMAN) += fsl_fman_ucode_ls1046_r1.0_106_4_18.bin firmware-$(CONFIG_ARCH_LAYERSCAPE_PPA) += ppa-ls1046a.bin +fw-external-$(CONFIG_FIRMWARE_LS1028A_ATF) += ls1028a-bl31.bin pbl-firmware-$(CONFIG_FIRMWARE_CCBV2_OPTEE) += ccbv2_optee.bin diff --git a/include/mach/layerscape/layerscape.h b/include/mach/layerscape/layerscape.h index 95c230b8f3..ceb7b983f6 100644 --- a/include/mach/layerscape/layerscape.h +++ b/include/mach/layerscape/layerscape.h @@ -29,4 +29,16 @@ static inline int ls1046a_ppa_init(resource_size_t ppa_start, } #endif +struct dram_region_info { + uint64_t addr; + uint64_t size; +}; +#define NUM_DRAM_REGIONS 3 + +struct dram_regions_info { + uint64_t num_dram_regions; + int64_t total_dram_size; + struct dram_region_info region[NUM_DRAM_REGIONS]; +}; + #endif /* __MACH_LAYERSCAPE_H */ diff --git a/include/mach/layerscape/xload.h b/include/mach/layerscape/xload.h index 0aeedc2834..86327c63e6 100644 --- a/include/mach/layerscape/xload.h +++ b/include/mach/layerscape/xload.h @@ -3,7 +3,11 @@ #ifndef __MACH_LAYERSCAPE_XLOAD_H #define __MACH_LAYERSCAPE_XLOAD_H +struct dram_regions_info; + int ls1046a_esdhc_start_image(unsigned long r0, unsigned long r1, unsigned long r2); +int ls1028a_esdhc1_start_image(struct dram_regions_info *dram_info); +int ls1028a_esdhc2_start_image(struct dram_regions_info *dram_info); int ls1046a_qspi_start_image(unsigned long r0, unsigned long r1, unsigned long r2); int ls1021a_qspi_start_image(unsigned long r0, unsigned long r1, -- 2.39.2