diff options
Diffstat (limited to 'arch/arm/mach-imx')
-rw-r--r-- | arch/arm/mach-imx/Kconfig | 2 | ||||
-rw-r--r-- | arch/arm/mach-imx/Makefile | 2 | ||||
-rw-r--r-- | arch/arm/mach-imx/atf.c | 41 | ||||
-rw-r--r-- | arch/arm/mach-imx/boot.c | 99 | ||||
-rw-r--r-- | arch/arm/mach-imx/cpu_init.c | 3 | ||||
-rw-r--r-- | arch/arm/mach-imx/imx.c | 11 | ||||
-rw-r--r-- | arch/arm/mach-imx/imx7.c | 11 | ||||
-rw-r--r-- | arch/arm/mach-imx/imx8mq.c | 84 | ||||
-rw-r--r-- | arch/arm/mach-imx/include/mach/atf.h | 13 | ||||
-rw-r--r-- | arch/arm/mach-imx/include/mach/imx-header.h | 128 | ||||
-rw-r--r-- | arch/arm/mach-imx/include/mach/imx8mq.h | 43 | ||||
-rw-r--r-- | arch/arm/mach-imx/include/mach/ocotp.h | 1 | ||||
-rw-r--r-- | arch/arm/mach-imx/include/mach/reset-reason.h | 1 | ||||
-rw-r--r-- | arch/arm/mach-imx/xload-esdhc.c | 51 |
14 files changed, 357 insertions, 133 deletions
diff --git a/arch/arm/mach-imx/Kconfig b/arch/arm/mach-imx/Kconfig index 73b7ea1b66..7cb9138d24 100644 --- a/arch/arm/mach-imx/Kconfig +++ b/arch/arm/mach-imx/Kconfig @@ -461,6 +461,8 @@ config MACH_NXP_IMX8MQ_EVK bool "NXP i.MX8MQ EVK Board" select ARCH_IMX8MQ select FIRMWARE_IMX_LPDDR4_PMU_TRAIN + select FIRMWARE_IMX8MQ_ATF + select ARM_SMCCC endif diff --git a/arch/arm/mach-imx/Makefile b/arch/arm/mach-imx/Makefile index 28fe60dba2..595a7512ce 100644 --- a/arch/arm/mach-imx/Makefile +++ b/arch/arm/mach-imx/Makefile @@ -17,7 +17,7 @@ lwl-$(CONFIG_ARCH_IMX6) += imx6-mmdc.o obj-$(CONFIG_ARCH_IMX7) += imx7.o obj-$(CONFIG_ARCH_VF610) += vf610.o obj-$(CONFIG_ARCH_IMX8MQ) += imx8mq.o -lwl-$(CONFIG_ARCH_IMX8MQ) += imx8-ddrc.o +lwl-$(CONFIG_ARCH_IMX8MQ) += imx8-ddrc.o atf.o obj-$(CONFIG_ARCH_IMX_XLOAD) += xload.o obj-$(CONFIG_IMX_IIM) += iim.o obj-$(CONFIG_NAND_IMX) += nand.o diff --git a/arch/arm/mach-imx/atf.c b/arch/arm/mach-imx/atf.c new file mode 100644 index 0000000000..c1b358d125 --- /dev/null +++ b/arch/arm/mach-imx/atf.c @@ -0,0 +1,41 @@ +#include <common.h> +#include <mach/atf.h> + +/** + * imx8mq_atf_load_bl31 - Load ATF BL31 blob and transfer control to it + * + * @fw: Pointer to the BL31 blob + * @fw_size: Size of the BL31 blob + * + * This function: + + * 1. Copies built-in BL31 blob to an address i.MX8M's BL31 + * expects to be placed + * + * 2. Sets up temporary stack pointer for EL2, which is execution + * level that BL31 will drop us off at after it completes its + * initialization routine + * + * 3. Transfers control to BL31 + * + * NOTE: This function expects NXP's implementation of ATF that can be + * found at: + * https://source.codeaurora.org/external/imx/imx-atf + * + * any other implementation may or may not work + * + */ +void imx8mq_atf_load_bl31(const void *fw, size_t fw_size) +{ + void __noreturn (*bl31)(void) = (void *)MX8MQ_ATF_BL31_BASE_ADDR; + + if (WARN_ON(fw_size > MX8MQ_ATF_BL31_SIZE_LIMIT)) + return; + + memcpy(bl31, fw, fw_size); + + asm volatile("msr sp_el2, %0" : : + "r" (MX8MQ_ATF_BL33_BASE_ADDR - 16) : + "cc"); + bl31(); +}
\ No newline at end of file diff --git a/arch/arm/mach-imx/boot.c b/arch/arm/mach-imx/boot.c index ab25f75b2a..f1fc40479d 100644 --- a/arch/arm/mach-imx/boot.c +++ b/arch/arm/mach-imx/boot.c @@ -28,6 +28,7 @@ #include <mach/imx6-regs.h> #include <mach/imx7-regs.h> #include <mach/vf610-regs.h> +#include <mach/imx8mq.h> static void @@ -424,32 +425,12 @@ void imx6_boot_save_loc(void) imx_boot_save_loc(imx6_get_boot_source); } -#define IMX7_SRC_SBMR1 0x58 -#define IMX7_SRC_SBMR2 0x70 +#define IMX7_BOOT_SW_INFO_POINTER_ADDR 0x000001E8 +#define IMX8M_BOOT_SW_INFO_POINTER_ADDR_A0 0x000009e8 +#define IMX8M_BOOT_SW_INFO_POINTER_ADDR_B0 0x00000968 -/* - * Re-defined to match the naming in reference manual - */ -#define BOOT_CFG(m, l) BOOT_CFG1(m, l) - -#define IMX_BOOT_SW_INFO_POINTER_ADDR 0x000001E8 #define IMX_BOOT_SW_INFO_BDT_SD 0x1 -static unsigned int imx7_bootsource_internal(uint32_t r) -{ - return FIELD_GET(BOOT_CFG(15, 12), r); -} - -static int imx7_boot_instance_spi_nor(uint32_t r) -{ - return FIELD_GET(BOOT_CFG(11, 9), r); -} - -static int imx7_boot_instance_mmc(uint32_t r) -{ - return FIELD_GET(BOOT_CFG(11, 10), r); -} - struct imx_boot_sw_info { uint8_t reserved_1; uint8_t boot_device_instance; @@ -460,60 +441,26 @@ struct imx_boot_sw_info { uint32_t reserved_3[3]; } __packed; -void imx7_get_boot_source(enum bootsource *src, int *instance) +static void __imx7_get_boot_source(enum bootsource *src, int *instance, + unsigned long boot_sw_info_pointer_addr) { - void __iomem *src_base = IOMEM(MX7_SRC_BASE_ADDR); - uint32_t sbmr1 = readl(src_base + IMX7_SRC_SBMR1); - uint32_t sbmr2 = readl(src_base + IMX7_SRC_SBMR2); + const struct imx_boot_sw_info *info; - if (imx6_bootsource_reserved(sbmr2)) - return; + info = (const void *)(unsigned long) + readl(boot_sw_info_pointer_addr); - if (imx6_bootsource_serial(sbmr2)) { - /* - * On i.MX7 ROM code will try to bood from uSDHC1 - * before entering serial mode. It doesn't seem to be - * reflected in the contents of SBMR1 in any way when - * that happens, so we check "Boot_SW_Info" structure - * (per 6.6.14 Boot information for software) to see - * if that really happened. - * - * FIXME: This behaviour can be inhibited by - * DISABLE_SDMMC_MFG, but location of that fuse - * doesn't seem to be documented anywhere. Once that - * is known it should be taken into account here. - */ - const struct imx_boot_sw_info *info; - - info = (const void *)(unsigned long) - readl(IMX_BOOT_SW_INFO_POINTER_ADDR); - - if (info->boot_device_type == IMX_BOOT_SW_INFO_BDT_SD) { - *src = BOOTSOURCE_MMC; - /* - * We are expecting to only ever boot from - * uSDHC1 here - */ - WARN_ON(*instance = info->boot_device_instance); - return; - } - - *src = BOOTSOURCE_SERIAL; - return; - } - - switch (imx7_bootsource_internal(sbmr1)) { + switch (info->boot_device_type) { case 1: case 2: *src = BOOTSOURCE_MMC; - *instance = imx7_boot_instance_mmc(sbmr1); + *instance = info->boot_device_instance; break; case 3: *src = BOOTSOURCE_NAND; break; case 6: - *src = BOOTSOURCE_SPI_NOR, - *instance = imx7_boot_instance_spi_nor(sbmr1); + *src = BOOTSOURCE_SPI_NOR; + *instance = info->boot_device_instance; break; case 4: *src = BOOTSOURCE_SPI; /* Really: qspi */ @@ -526,6 +473,11 @@ void imx7_get_boot_source(enum bootsource *src, int *instance) } } +void imx7_get_boot_source(enum bootsource *src, int *instance) +{ + __imx7_get_boot_source(src, instance, IMX7_BOOT_SW_INFO_POINTER_ADDR); +} + void imx7_boot_save_loc(void) { imx_boot_save_loc(imx7_get_boot_source); @@ -626,6 +578,17 @@ void vf610_boot_save_loc(void) } void imx8_get_boot_source(enum bootsource *src, int *instance) - __alias(imx7_get_boot_source); +{ + unsigned long addr; + + addr = (imx8mq_cpu_revision() == IMX_CHIP_REV_1_0) ? + IMX8M_BOOT_SW_INFO_POINTER_ADDR_A0 : + IMX8M_BOOT_SW_INFO_POINTER_ADDR_B0; -void imx8_boot_save_loc(void) __alias(imx7_boot_save_loc); + __imx7_get_boot_source(src, instance, addr); +} + +void imx8_boot_save_loc(void) +{ + imx_boot_save_loc(imx8_get_boot_source); +} diff --git a/arch/arm/mach-imx/cpu_init.c b/arch/arm/mach-imx/cpu_init.c index 5b93d12da9..dfbd5ba6c1 100644 --- a/arch/arm/mach-imx/cpu_init.c +++ b/arch/arm/mach-imx/cpu_init.c @@ -22,6 +22,7 @@ void imx5_cpu_lowlevel_init(void) arm_cpu_lowlevel_init(); enable_arm_errata_709718_war(); + enable_arm_errata_cortexa8_enable_ibe(); } void imx6_cpu_lowlevel_init(void) @@ -51,4 +52,4 @@ void vf610_cpu_lowlevel_init(void) { arm_cpu_lowlevel_init(); } -#endif
\ No newline at end of file +#endif diff --git a/arch/arm/mach-imx/imx.c b/arch/arm/mach-imx/imx.c index 6fe53f3140..ad227663dd 100644 --- a/arch/arm/mach-imx/imx.c +++ b/arch/arm/mach-imx/imx.c @@ -157,6 +157,17 @@ static int imx_init(void) } postcore_initcall(imx_init); +const struct imx_reset_reason imx7_reset_reasons[] = { + { IMX_SRC_SRSR_IPP_RESET, RESET_POR, 0 }, + { IMX_SRC_SRSR_WDOG1_RESET, RESET_WDG, 0 }, + { IMX_SRC_SRSR_JTAG_RESET, RESET_JTAG, 0 }, + { IMX_SRC_SRSR_JTAG_SW_RESET, RESET_JTAG, 0 }, + { IMX_SRC_SRSR_WDOG3_RESET, RESET_WDG, 1 }, + { IMX_SRC_SRSR_WDOG4_RESET, RESET_WDG, 2 }, + { IMX_SRC_SRSR_TEMPSENSE_RESET, RESET_THERM, 0 }, + { /* sentinel */ } +}; + const struct imx_reset_reason imx_reset_reasons[] = { { IMX_SRC_SRSR_IPP_RESET, RESET_POR, 0 }, { IMX_SRC_SRSR_WDOG1_RESET, RESET_WDG, 0 }, diff --git a/arch/arm/mach-imx/imx7.c b/arch/arm/mach-imx/imx7.c index e49baf6f77..ca11e83456 100644 --- a/arch/arm/mach-imx/imx7.c +++ b/arch/arm/mach-imx/imx7.c @@ -168,17 +168,6 @@ static struct psci_ops imx7_psci_ops = { .cpu_off = imx7_cpu_off, }; -static const struct imx_reset_reason imx7_reset_reasons[] = { - { IMX_SRC_SRSR_IPP_RESET, RESET_POR, 0 }, - { IMX_SRC_SRSR_WDOG1_RESET, RESET_WDG, 0 }, - { IMX_SRC_SRSR_JTAG_RESET, RESET_JTAG, 0 }, - { IMX_SRC_SRSR_JTAG_SW_RESET, RESET_JTAG, 0 }, - { IMX_SRC_SRSR_WDOG3_RESET, RESET_WDG, 1 }, - { IMX_SRC_SRSR_WDOG4_RESET, RESET_WDG, 2 }, - { IMX_SRC_SRSR_TEMPSENSE_RESET, RESET_THERM, 0 }, - { /* sentinel */ } -}; - int imx7_init(void) { const char *cputypestr; diff --git a/arch/arm/mach-imx/imx8mq.c b/arch/arm/mach-imx/imx8mq.c index f3246e4373..4d00da5f0d 100644 --- a/arch/arm/mach-imx/imx8mq.c +++ b/arch/arm/mach-imx/imx8mq.c @@ -18,38 +18,46 @@ #include <asm/system.h> #include <mach/generic.h> #include <mach/revision.h> -#include <mach/imx8mq-regs.h> +#include <mach/imx8mq.h> +#include <mach/reset-reason.h> -#define IMX8MQ_ROM_VERSION_A0 0x800 -#define IMX8MQ_ROM_VERSION_B0 0x83C +#include <linux/arm-smccc.h> -#define MX8MQ_ANATOP_DIGPROG 0x6c +#define FSL_SIP_BUILDINFO 0xC2000003 +#define FSL_SIP_BUILDINFO_GET_COMMITHASH 0x00 -static void imx8mq_silicon_revision(void) +static int imx8mq_init_syscnt_frequency(void) { - void __iomem *anatop = IOMEM(MX8MQ_ANATOP_BASE_ADDR); - uint32_t reg = readl(anatop + MX8MQ_ANATOP_DIGPROG); - uint32_t type = (reg >> 16) & 0xff; - uint32_t rom_version; - const char *cputypestr; - - reg &= 0xff; - - if (reg == IMX_CHIP_REV_1_0) { + if (current_el() == 3) { + void __iomem *syscnt = IOMEM(MX8MQ_SYSCNT_CTRL_BASE_ADDR); /* - * For B0 chip, the DIGPROG is not updated, still TO1.0. - * we have to check ROM version further + * Update with accurate clock frequency */ - rom_version = readl(IOMEM(IMX8MQ_ROM_VERSION_A0)); - if (rom_version != IMX_CHIP_REV_1_0) { - rom_version = readl(IOMEM(IMX8MQ_ROM_VERSION_B0)); - if (rom_version >= IMX_CHIP_REV_2_0) - reg = IMX_CHIP_REV_2_0; - } + set_cntfrq(syscnt_get_cntfrq(syscnt)); + syscnt_enable(syscnt); } + return 0; +} +/* + * This call needs to happen before timer driver gets probed and + * requests its update frequency via cntfrq_el0 + */ +core_initcall(imx8mq_init_syscnt_frequency); + +int imx8mq_init(void) +{ + void __iomem *anatop = IOMEM(MX8MQ_ANATOP_BASE_ADDR); + void __iomem *src = IOMEM(MX8MQ_SRC_BASE_ADDR); + uint32_t type = FIELD_GET(DIGPROG_MAJOR, + readl(anatop + MX8MQ_ANATOP_DIGPROG)); + struct arm_smccc_res res; + const char *cputypestr; + + imx8_boot_save_loc(); + switch (type) { - case 0x82: + case IMX8M_CPUTYPE_IMX8MQ: cputypestr = "i.MX8MQ"; break; default: @@ -57,29 +65,19 @@ static void imx8mq_silicon_revision(void) break; }; - imx_set_silicon_revision(cputypestr, reg); -} - -static int imx8mq_init_syscnt_frequency(void) -{ - void __iomem *syscnt = IOMEM(MX8MQ_SYSCNT_CTRL_BASE_ADDR); + imx_set_silicon_revision(cputypestr, imx8mq_cpu_revision()); /* - * Update with accurate clock frequency + * Reset reasons seem to be identical to that of i.MX7 */ - set_cntfrq(syscnt_get_cntfrq(syscnt)); - syscnt_enable(syscnt); + imx_set_reset_reason(src + IMX7_SRC_SRSR, imx7_reset_reasons); - return 0; -} -/* - * This call needs to happen before timer driver gets probed and - * requests its update frequency via cntfrq_el0 - */ -core_initcall(imx8mq_init_syscnt_frequency); - -int imx8mq_init(void) -{ - imx8mq_silicon_revision(); + if (IS_ENABLED(CONFIG_ARM_SMCCC) && + IS_ENABLED(CONFIG_FIRMWARE_IMX8MQ_ATF)) { + arm_smccc_smc(FSL_SIP_BUILDINFO, + FSL_SIP_BUILDINFO_GET_COMMITHASH, + 0, 0, 0, 0, 0, 0, &res); + pr_info("i.MX ARM Trusted Firmware: %s\n", (char *)&res.a0); + } return 0; } diff --git a/arch/arm/mach-imx/include/mach/atf.h b/arch/arm/mach-imx/include/mach/atf.h new file mode 100644 index 0000000000..aeb24bad00 --- /dev/null +++ b/arch/arm/mach-imx/include/mach/atf.h @@ -0,0 +1,13 @@ +#ifndef __IMX_ATF_H__ +#define __IMX_ATF_H__ + +#include <linux/sizes.h> +#include <asm/system.h> + +#define MX8MQ_ATF_BL31_SIZE_LIMIT SZ_64K +#define MX8MQ_ATF_BL31_BASE_ADDR 0x00910000 +#define MX8MQ_ATF_BL33_BASE_ADDR 0x40200000 + +void imx8mq_atf_load_bl31(const void *fw, size_t fw_size); + +#endif
\ No newline at end of file diff --git a/arch/arm/mach-imx/include/mach/imx-header.h b/arch/arm/mach-imx/include/mach/imx-header.h new file mode 100644 index 0000000000..c9b2a58819 --- /dev/null +++ b/arch/arm/mach-imx/include/mach/imx-header.h @@ -0,0 +1,128 @@ +#ifndef __IMX_HEADER_H__ +#define __IMX_HEADER_H__ + +#include <linux/types.h> + +#define HEADER_LEN 0x1000 /* length of the blank area + IVT + DCD */ + +/* + * ============================================================================ + * i.MX flash header v1 handling. Found on i.MX35 and i.MX51 + * ============================================================================ + */ +#define DCD_BARKER 0xb17219e9 + +struct imx_flash_header { + uint32_t app_code_jump_vector; + uint32_t app_code_barker; + uint32_t app_code_csf; + uint32_t dcd_ptr_ptr; + uint32_t super_root_key; + uint32_t dcd; + uint32_t app_dest; + uint32_t dcd_barker; + uint32_t dcd_block_len; +} __attribute__((packed)); + +struct imx_boot_data { + uint32_t start; + uint32_t size; + uint32_t plugin; +} __attribute__((packed)); + +struct imx_dcd_rec_v1 { + uint32_t type; + uint32_t addr; + uint32_t val; +} __attribute__((packed)); + +#define TAG_IVT_HEADER 0xd1 +#define IVT_VERSION 0x40 +#define TAG_DCD_HEADER 0xd2 +#define DCD_VERSION 0x40 +#define TAG_UNLOCK 0xb2 +#define TAG_NOP 0xc0 +#define TAG_WRITE 0xcc +#define TAG_CHECK 0xcf +#define PARAMETER_FLAG_MASK (1 << 3) +#define PARAMETER_FLAG_SET (1 << 4) + +struct imx_ivt_header { + uint8_t tag; + uint16_t length; + uint8_t version; +} __attribute__((packed)); + +struct imx_flash_header_v2 { + struct imx_ivt_header header; + + uint32_t entry; + uint32_t reserved1; + uint32_t dcd_ptr; + uint32_t boot_data_ptr; + uint32_t self; + uint32_t csf; + uint32_t reserved2; + + struct imx_boot_data boot_data; + struct imx_ivt_header dcd_header; +} __attribute__((packed)); + +static inline bool is_imx_flash_header_v2(const void *blob) +{ + const struct imx_flash_header_v2 *hdr = blob; + + return hdr->header.tag == TAG_IVT_HEADER && + hdr->header.version >= IVT_VERSION; +} + +struct config_data { + uint32_t image_load_addr; + uint32_t image_dcd_offset; + uint32_t image_size; + uint32_t load_size; + char *outfile; + char *srkfile; + int header_version; + off_t header_gap; + uint32_t first_opcode; + int cpu_type; + int (*check)(const struct config_data *data, uint32_t cmd, + uint32_t addr, uint32_t mask); + int (*write_mem)(const struct config_data *data, uint32_t addr, + uint32_t val, int width, int set_bits, int clear_bits); + int (*nop)(const struct config_data *data); + int csf_space; + char *csf; +}; + +#define MAX_RECORDS_DCD_V2 1024 +struct imx_dcd_v2_write_rec { + uint32_t addr; + uint32_t val; +} __attribute__((packed)); + +struct imx_dcd_v2_write { + uint8_t tag; + uint16_t length; + uint8_t param; + struct imx_dcd_v2_write_rec data[MAX_RECORDS_DCD_V2]; +} __attribute__((packed)); + +struct imx_dcd_v2_check { + uint8_t tag; + uint16_t length; + uint8_t param; + uint32_t addr; + uint32_t mask; + uint32_t count; +} __attribute__((packed)); + +enum imx_dcd_v2_check_cond { + until_all_bits_clear = 0, /* until ((*address & mask) == 0) { ...} */ + until_any_bit_clear = 1, /* until ((*address & mask) != mask) { ...} */ + until_all_bits_set = 2, /* until ((*address & mask) == mask) { ...} */ + until_any_bit_set = 3, /* until ((*address & mask) != 0) { ...} */ +} __attribute__((packed)); + +#endif diff --git a/arch/arm/mach-imx/include/mach/imx8mq.h b/arch/arm/mach-imx/include/mach/imx8mq.h new file mode 100644 index 0000000000..f4a537d2b1 --- /dev/null +++ b/arch/arm/mach-imx/include/mach/imx8mq.h @@ -0,0 +1,43 @@ +#ifndef __MACH_IMX8MQ_H +#define __MACH_IMX8MQ_H + +#include <io.h> +#include <mach/generic.h> +#include <mach/imx8mq-regs.h> +#include <mach/revision.h> +#include <linux/bitfield.h> + +#define IMX8MQ_ROM_VERSION_A0 0x800 +#define IMX8MQ_ROM_VERSION_B0 0x83C + +#define MX8MQ_ANATOP_DIGPROG 0x6c + +#define DIGPROG_MAJOR GENMASK(23, 8) +#define DIGPROG_MINOR GENMASK(7, 0) + +#define IMX8M_CPUTYPE_IMX8MQ 0x8240 + +static inline int imx8mq_cpu_revision(void) +{ + void __iomem *anatop = IOMEM(MX8MQ_ANATOP_BASE_ADDR); + uint32_t revision = FIELD_GET(DIGPROG_MINOR, + readl(anatop + MX8MQ_ANATOP_DIGPROG)); + + if (revision == IMX_CHIP_REV_1_0) { + uint32_t rom_version; + /* + * For B0 chip, the DIGPROG is not updated, still TO1.0. + * we have to check ROM version further + */ + rom_version = readl(IOMEM(IMX8MQ_ROM_VERSION_A0)); + if (rom_version != IMX_CHIP_REV_1_0) { + rom_version = readl(IOMEM(IMX8MQ_ROM_VERSION_B0)); + if (rom_version >= IMX_CHIP_REV_2_0) + revision = IMX_CHIP_REV_2_0; + } + } + + return revision; +} + +#endif /* __MACH_IMX8_H */
\ No newline at end of file diff --git a/arch/arm/mach-imx/include/mach/ocotp.h b/arch/arm/mach-imx/include/mach/ocotp.h index 76a6da53de..e758238cb9 100644 --- a/arch/arm/mach-imx/include/mach/ocotp.h +++ b/arch/arm/mach-imx/include/mach/ocotp.h @@ -2,6 +2,7 @@ #define __MACH_IMX_OCOTP_H #include <linux/bitfield.h> +#include <linux/types.h> #define OCOTP_SHADOW_OFFSET 0x400 #define OCOTP_SHADOW_SPACING 0x10 diff --git a/arch/arm/mach-imx/include/mach/reset-reason.h b/arch/arm/mach-imx/include/mach/reset-reason.h index 0f644a8c1d..91a8171896 100644 --- a/arch/arm/mach-imx/include/mach/reset-reason.h +++ b/arch/arm/mach-imx/include/mach/reset-reason.h @@ -33,5 +33,6 @@ struct imx_reset_reason { void imx_set_reset_reason(void __iomem *, const struct imx_reset_reason *); extern const struct imx_reset_reason imx_reset_reasons[]; +extern const struct imx_reset_reason imx7_reset_reasons[]; #endif /* __MACH_RESET_REASON_H__ */ diff --git a/arch/arm/mach-imx/xload-esdhc.c b/arch/arm/mach-imx/xload-esdhc.c index 08ba9b08dc..55d6c69299 100644 --- a/arch/arm/mach-imx/xload-esdhc.c +++ b/arch/arm/mach-imx/xload-esdhc.c @@ -14,10 +14,12 @@ #include <common.h> #include <io.h> #include <mci.h> +#include <mach/atf.h> #include <mach/imx6-regs.h> #include <mach/imx8mq-regs.h> #include <mach/xload.h> #include <linux/sizes.h> +#include <mach/imx-header.h> #include "../../../drivers/mci/sdhci.h" #include "../../../drivers/mci/imx-esdhc.h" @@ -218,10 +220,11 @@ static int esdhc_read_blocks(struct esdhc *esdhc, void *dst, size_t len) } static int -esdhc_start_image(struct esdhc *esdhc, ptrdiff_t address, u32 offset) +esdhc_start_image(struct esdhc *esdhc, ptrdiff_t address, ptrdiff_t entry, u32 offset) { + void *buf = (void *)address; - u32 *ivt = buf + offset + SZ_1K; + struct imx_flash_header_v2 *hdr = buf + offset + SZ_1K; int ret, len; void __noreturn (*bb)(void); unsigned int ofs; @@ -233,14 +236,45 @@ esdhc_start_image(struct esdhc *esdhc, ptrdiff_t address, u32 offset) if (ret) return ret; - if (*(u32 *)(ivt) != 0x402000d1) { - pr_debug("IVT header not found on SD card. Found 0x%08x instead of 0x402000d1\n", - *ivt); + if (!is_imx_flash_header_v2(hdr)) { + pr_debug("IVT header not found on SD card. " + "Found tag: 0x%02x length: 0x%04x version: %02x\n", + hdr->header.tag, hdr->header.length, + hdr->header.version); return -EINVAL; } pr_debug("Check ok, loading image\n"); + ofs = offset + hdr->entry - hdr->boot_data.start; + + if (entry != address) { + /* + * Passing entry different from address is interpreted + * as a request to place the image such that its entry + * point would be exactly at 'entry', that is: + * + * buf + ofs = entry + * + * solving the above for 'buf' gvies us the + * adjustement that needs to be made: + * + * buf = entry - ofs + * + */ + if (WARN_ON(entry - ofs < address)) { + /* + * We want to make sure we won't try to place + * the start of the image before the beginning + * of the memory buffer we were given in + * address. + */ + return -EINVAL; + } + + buf = (void *)(entry - ofs); + } + ret = esdhc_read_blocks(esdhc, buf, offset + len); if (ret) { pr_err("Loading image failed with %d\n", ret); @@ -249,8 +283,6 @@ esdhc_start_image(struct esdhc *esdhc, ptrdiff_t address, u32 offset) pr_debug("Image loaded successfully\n"); - ofs = offset + *(ivt + 1) - *(ivt + 8); - bb = buf + ofs; bb(); @@ -291,7 +323,7 @@ int imx6_esdhc_start_image(int instance) esdhc.is_mx6 = 1; - return esdhc_start_image(&esdhc, 0x10000000, 0); + return esdhc_start_image(&esdhc, 0x10000000, 0x10000000, 0); } /** @@ -323,5 +355,6 @@ int imx8_esdhc_start_image(int instance) esdhc.is_mx6 = 1; - return esdhc_start_image(&esdhc, MX8MQ_DDR_CSD1_BASE_ADDR, SZ_32K); + return esdhc_start_image(&esdhc, MX8MQ_DDR_CSD1_BASE_ADDR, + MX8MQ_ATF_BL33_BASE_ADDR, SZ_32K); }
\ No newline at end of file |