summaryrefslogtreecommitdiffstats
path: root/arch/arm/mach-imx
diff options
context:
space:
mode:
Diffstat (limited to 'arch/arm/mach-imx')
-rw-r--r--arch/arm/mach-imx/Kconfig2
-rw-r--r--arch/arm/mach-imx/Makefile2
-rw-r--r--arch/arm/mach-imx/atf.c41
-rw-r--r--arch/arm/mach-imx/boot.c99
-rw-r--r--arch/arm/mach-imx/cpu_init.c3
-rw-r--r--arch/arm/mach-imx/imx.c11
-rw-r--r--arch/arm/mach-imx/imx7.c11
-rw-r--r--arch/arm/mach-imx/imx8mq.c84
-rw-r--r--arch/arm/mach-imx/include/mach/atf.h13
-rw-r--r--arch/arm/mach-imx/include/mach/imx-header.h128
-rw-r--r--arch/arm/mach-imx/include/mach/imx8mq.h43
-rw-r--r--arch/arm/mach-imx/include/mach/ocotp.h1
-rw-r--r--arch/arm/mach-imx/include/mach/reset-reason.h1
-rw-r--r--arch/arm/mach-imx/xload-esdhc.c51
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