aboutsummaryrefslogtreecommitdiff
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/Kconfig4
-rw-r--r--arch/arm/mach-imx/Makefile2
-rw-r--r--arch/arm/mach-imx/cpu.c4
-rw-r--r--arch/arm/mach-imx/imx8m/Kconfig11
-rw-r--r--arch/arm/mach-imx/imx8m/Makefile2
-rw-r--r--arch/arm/mach-imx/imx8m/clock_slice.c4
-rw-r--r--arch/arm/mach-imx/imx8m/imximage-8mn-ddr4.cfg17
-rw-r--r--arch/arm/mach-imx/imx8m/soc.c68
-rw-r--r--arch/arm/mach-imx/spl.c2
-rw-r--r--arch/arm/mach-imx/spl_imx_romapi.c292
10 files changed, 394 insertions, 12 deletions
diff --git a/arch/arm/mach-imx/Kconfig b/arch/arm/mach-imx/Kconfig
index 3f93fe5174..751c0b52d7 100644
--- a/arch/arm/mach-imx/Kconfig
+++ b/arch/arm/mach-imx/Kconfig
@@ -109,3 +109,7 @@ config DDRMC_VF610_CALIBRATION
NXP does NOT recommend to perform this calibration at each boot. One
shall perform it on a new PCB and then use those values to program
the ddrmc_cr_setting on relevant board file.
+
+config SPL_IMX_ROMAPI_LOADADDR
+ hex "Default load address to load image through ROM API"
+ depends on IMX8MN
diff --git a/arch/arm/mach-imx/Makefile b/arch/arm/mach-imx/Makefile
index 6e87dc58a0..e14713c5c4 100644
--- a/arch/arm/mach-imx/Makefile
+++ b/arch/arm/mach-imx/Makefile
@@ -226,3 +226,5 @@ obj-$(CONFIG_MX7) += mx7/
obj-$(CONFIG_ARCH_MX7ULP) += mx7ulp/
obj-$(CONFIG_IMX8M) += imx8m/
obj-$(CONFIG_ARCH_IMX8) += imx8/
+
+obj-$(CONFIG_SPL_BOOTROM_SUPPORT) += spl_imx_romapi.o
diff --git a/arch/arm/mach-imx/cpu.c b/arch/arm/mach-imx/cpu.c
index d39f607e3f..51c7c05f04 100644
--- a/arch/arm/mach-imx/cpu.c
+++ b/arch/arm/mach-imx/cpu.c
@@ -92,6 +92,8 @@ static char *get_reset_cause(void)
const char *get_imx_type(u32 imxtype)
{
switch (imxtype) {
+ case MXC_CPU_IMX8MN:
+ return "8MNano";/* Quad-core version of the imx8mn */
case MXC_CPU_IMX8MM:
return "8MMQ"; /* Quad-core version of the imx8mm */
case MXC_CPU_IMX8MML:
@@ -375,7 +377,7 @@ u32 get_cpu_temp_grade(int *minc, int *maxc)
}
#endif
-#if defined(CONFIG_MX7) || defined(CONFIG_IMX8M)
+#if defined(CONFIG_MX7) || defined(CONFIG_IMX8MQ) || defined(CONFIG_IMX8MM)
enum boot_device get_boot_device(void)
{
struct bootrom_sw_info **p =
diff --git a/arch/arm/mach-imx/imx8m/Kconfig b/arch/arm/mach-imx/imx8m/Kconfig
index f520075875..eb4a73b3e2 100644
--- a/arch/arm/mach-imx/imx8m/Kconfig
+++ b/arch/arm/mach-imx/imx8m/Kconfig
@@ -12,6 +12,10 @@ config IMX8MM
bool
select IMX8M
+config IMX8MN
+ bool
+ select IMX8M
+
config SYS_SOC
default "imx8m"
@@ -30,9 +34,16 @@ config TARGET_IMX8MM_EVK
select SUPPORT_SPL
select IMX8M_LPDDR4
+config TARGET_IMX8MN_EVK
+ bool "imx8mn DDR4 EVK board"
+ select IMX8MN
+ select SUPPORT_SPL
+ select IMX8M_DDR4
+
endchoice
source "board/freescale/imx8mq_evk/Kconfig"
source "board/freescale/imx8mm_evk/Kconfig"
+source "board/freescale/imx8mn_evk/Kconfig"
endif
diff --git a/arch/arm/mach-imx/imx8m/Makefile b/arch/arm/mach-imx/imx8m/Makefile
index 92184f3135..db4ba30c24 100644
--- a/arch/arm/mach-imx/imx8m/Makefile
+++ b/arch/arm/mach-imx/imx8m/Makefile
@@ -5,4 +5,4 @@
obj-y += lowlevel_init.o
obj-y += clock_slice.o soc.o
obj-$(CONFIG_IMX8MQ) += clock_imx8mq.o
-obj-$(CONFIG_IMX8MM) += clock_imx8mm.o
+obj-$(CONFIG_IMX8MM)$(CONFIG_IMX8MN) += clock_imx8mm.o
diff --git a/arch/arm/mach-imx/imx8m/clock_slice.c b/arch/arm/mach-imx/imx8m/clock_slice.c
index 780f64314d..09c5615004 100644
--- a/arch/arm/mach-imx/imx8m/clock_slice.c
+++ b/arch/arm/mach-imx/imx8m/clock_slice.c
@@ -475,7 +475,7 @@ static struct clk_root_map root_array[] = {
{DRAM_PLL1_CLK}
},
};
-#elif defined(CONFIG_IMX8MM)
+#elif defined(CONFIG_IMX8MM) || defined(CONFIG_IMX8MN)
static struct clk_root_map root_array[] = {
{NAND_USDHC_BUS_CLK_ROOT, BUS_CLOCK_SLICE, 2,
{OSC_24M_CLK, SYSTEM_PLL1_266M_CLK, SYSTEM_PLL1_800M_CLK,
@@ -487,11 +487,13 @@ static struct clk_root_map root_array[] = {
SYSTEM_PLL2_1000M_CLK, SYSTEM_PLL2_500M_CLK,
AUDIO_PLL1_CLK, VIDEO_PLL_CLK, AUDIO_PLL2_CLK}
},
+#ifdef CONFIG_IMX8MM
{NOC_APB_CLK_ROOT, BUS_CLOCK_SLICE, 11,
{OSC_24M_CLK, SYSTEM_PLL1_400M_CLK, SYSTEM_PLL3_CLK,
SYSTEM_PLL2_333M_CLK, SYSTEM_PLL2_200M_CLK,
SYSTEM_PLL1_800M_CLK, AUDIO_PLL1_CLK, VIDEO_PLL_CLK}
},
+#endif
{DRAM_ALT_CLK_ROOT, IP_CLOCK_SLICE, 0,
{OSC_24M_CLK, SYSTEM_PLL1_800M_CLK, SYSTEM_PLL1_100M_CLK,
SYSTEM_PLL2_500M_CLK, SYSTEM_PLL2_1000M_CLK,
diff --git a/arch/arm/mach-imx/imx8m/imximage-8mn-ddr4.cfg b/arch/arm/mach-imx/imx8m/imximage-8mn-ddr4.cfg
new file mode 100644
index 0000000000..1405c6560c
--- /dev/null
+++ b/arch/arm/mach-imx/imx8m/imximage-8mn-ddr4.cfg
@@ -0,0 +1,17 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+/*
+ * Copyright 2019 NXP
+ */
+
+#define __ASSEMBLY__
+
+FIT
+ROM_VERSION v2
+BOOT_FROM sd
+LOADER spl/u-boot-spl-ddr.bin 0x912000
+SECOND_LOADER u-boot.itb 0x40200000 0x60000
+
+DDR_FW ddr4_imem_1d.bin
+DDR_FW ddr4_dmem_1d.bin
+DDR_FW ddr4_imem_2d.bin
+DDR_FW ddr4_dmem_2d.bin
diff --git a/arch/arm/mach-imx/imx8m/soc.c b/arch/arm/mach-imx/imx8m/soc.c
index a924af431c..9a203e4736 100644
--- a/arch/arm/mach-imx/imx8m/soc.c
+++ b/arch/arm/mach-imx/imx8m/soc.c
@@ -56,7 +56,7 @@ void enable_tzc380(void)
/* Enable TZASC and lock setting */
setbits_le32(&gpr->gpr[10], GPR_TZASC_EN);
setbits_le32(&gpr->gpr[10], GPR_TZASC_EN_LOCK);
- if (IS_ENABLED(CONFIG_IMX8MM))
+ if (is_imx8mm() || is_imx8mn())
setbits_le32(&gpr->gpr[10], BIT(1));
/*
* set Region 0 attribute to allow secure and non-secure
@@ -197,7 +197,9 @@ u32 get_cpu_rev(void)
reg &= 0xff;
/* i.MX8MM */
- if (major_low == 0x41) {
+ if (major_low == 0x42) {
+ return (MXC_CPU_IMX8MN << 12) | reg;
+ } else if (major_low == 0x41) {
type = get_cpu_variant_type(MXC_CPU_IMX8MM);
} else {
if (reg == CHIP_REV_1_0) {
@@ -241,12 +243,14 @@ int arch_cpu_init_dm(void)
struct udevice *dev;
int ret;
- ret = uclass_get_device_by_name(UCLASS_CLK,
- "clock-controller@30380000",
- &dev);
- if (ret < 0) {
- printf("Failed to find clock node. Check device tree\n");
- return ret;
+ if (CONFIG_IS_ENABLED(CLK)) {
+ ret = uclass_get_device_by_name(UCLASS_CLK,
+ "clock-controller@30380000",
+ &dev);
+ if (ret < 0) {
+ printf("Failed to find clock node. Check device tree\n");
+ return ret;
+ }
}
return 0;
@@ -281,6 +285,54 @@ int arch_cpu_init(void)
return 0;
}
+#if defined(CONFIG_IMX8MN) || defined(CONFIG_IMX8MP)
+struct rom_api *g_rom_api = (struct rom_api *)0x980;
+
+enum boot_device get_boot_device(void)
+{
+ volatile gd_t *pgd = gd;
+ int ret;
+ u32 boot;
+ u16 boot_type;
+ u8 boot_instance;
+ enum boot_device boot_dev = SD1_BOOT;
+
+ ret = g_rom_api->query_boot_infor(QUERY_BT_DEV, &boot,
+ ((uintptr_t)&boot) ^ QUERY_BT_DEV);
+ gd = pgd;
+
+ if (ret != ROM_API_OKAY) {
+ puts("ROMAPI: failure at query_boot_info\n");
+ return -1;
+ }
+
+ boot_type = boot >> 16;
+ boot_instance = (boot >> 8) & 0xff;
+
+ switch (boot_type) {
+ case BT_DEV_TYPE_SD:
+ boot_dev = boot_instance + SD1_BOOT;
+ break;
+ case BT_DEV_TYPE_MMC:
+ boot_dev = boot_instance + MMC1_BOOT;
+ break;
+ case BT_DEV_TYPE_NAND:
+ boot_dev = NAND_BOOT;
+ break;
+ case BT_DEV_TYPE_FLEXSPINOR:
+ boot_dev = QSPI_BOOT;
+ break;
+ case BT_DEV_TYPE_USB:
+ boot_dev = USB_BOOT;
+ break;
+ default:
+ break;
+ }
+
+ return boot_dev;
+}
+#endif
+
bool is_usb_boot(void)
{
return get_boot_device() == USB_BOOT;
diff --git a/arch/arm/mach-imx/spl.c b/arch/arm/mach-imx/spl.c
index 5cc74b6f9b..dde1635a9d 100644
--- a/arch/arm/mach-imx/spl.c
+++ b/arch/arm/mach-imx/spl.c
@@ -135,7 +135,7 @@ u32 spl_boot_device(void)
enum boot_device boot_device_spl = get_boot_device();
- if (IS_ENABLED(CONFIG_IMX8MM))
+ if (IS_ENABLED(CONFIG_IMX8MM) || IS_ENABLED(CONFIG_IMX8MN))
return spl_board_boot_device(boot_device_spl);
switch (boot_device_spl) {
diff --git a/arch/arm/mach-imx/spl_imx_romapi.c b/arch/arm/mach-imx/spl_imx_romapi.c
new file mode 100644
index 0000000000..5dc0f7174e
--- /dev/null
+++ b/arch/arm/mach-imx/spl_imx_romapi.c
@@ -0,0 +1,292 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright 2019 NXP
+ */
+
+#include <common.h>
+#include <errno.h>
+#include <image.h>
+#include <linux/libfdt.h>
+#include <spl.h>
+
+#include <asm/arch/sys_proto.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+static int is_boot_from_stream_device(u32 boot)
+{
+ u32 interface;
+
+ interface = boot >> 16;
+ if (interface >= BT_DEV_TYPE_USB)
+ return 1;
+
+ if (interface == BT_DEV_TYPE_MMC && (boot & 1))
+ return 1;
+
+ return 0;
+}
+
+static ulong spl_romapi_read_seekable(struct spl_load_info *load,
+ ulong sector, ulong count,
+ void *buf)
+{
+ u32 pagesize = *(u32 *)load->priv;
+ volatile gd_t *pgd = gd;
+ ulong byte = count * pagesize;
+ int ret;
+ u32 offset;
+
+ offset = sector * pagesize;
+
+ debug("ROM API load from 0x%x, size 0x%x\n", offset, (u32)byte);
+
+ ret = g_rom_api->download_image(buf, offset, byte,
+ ((uintptr_t)buf) ^ offset ^ byte);
+ gd = pgd;
+
+ if (ret == ROM_API_OKAY)
+ return count;
+
+ printf("ROM API Failure when load 0x%x\n", offset);
+
+ return 0;
+}
+
+static int spl_romapi_load_image_seekable(struct spl_image_info *spl_image,
+ struct spl_boot_device *bootdev,
+ u32 rom_bt_dev)
+{
+ volatile gd_t *pgd = gd;
+ int ret;
+ u32 offset;
+ u32 pagesize, size;
+ struct image_header *header;
+ u32 image_offset;
+
+ ret = g_rom_api->query_boot_infor(QUERY_IVT_OFF, &offset,
+ ((uintptr_t)&offset) ^ QUERY_IVT_OFF);
+ ret |= g_rom_api->query_boot_infor(QUERY_PAGE_SZ, &pagesize,
+ ((uintptr_t)&pagesize) ^ QUERY_PAGE_SZ);
+ ret |= g_rom_api->query_boot_infor(QUERY_IMG_OFF, &image_offset,
+ ((uintptr_t)&image_offset) ^ QUERY_IMG_OFF);
+
+ gd = pgd;
+
+ if (ret != ROM_API_OKAY) {
+ puts("ROMAPI: Failure query boot infor pagesize/offset\n");
+ return -1;
+ }
+
+ header = (struct image_header *)(CONFIG_SPL_IMX_ROMAPI_LOADADDR);
+
+ printf("image offset 0x%x, pagesize 0x%x, ivt offset 0x%x\n",
+ image_offset, pagesize, offset);
+
+ if (((rom_bt_dev >> 16) & 0xff) == BT_DEV_TYPE_FLEXSPINOR)
+ offset = CONFIG_SYS_MMCSD_RAW_MODE_U_BOOT_SECTOR * 512;
+ else
+ offset = image_offset +
+ CONFIG_SYS_MMCSD_RAW_MODE_U_BOOT_SECTOR * 512 - 0x8000;
+
+ size = ALIGN(sizeof(struct image_header), pagesize);
+ ret = g_rom_api->download_image((u8 *)header, offset, size,
+ ((uintptr_t)header) ^ offset ^ size);
+ gd = pgd;
+
+ if (ret != ROM_API_OKAY) {
+ printf("ROMAPI: download failure offset 0x%x size 0x%x\n",
+ offset, size);
+ return -1;
+ }
+
+ if (IS_ENABLED(CONFIG_SPL_LOAD_FIT) &&
+ image_get_magic(header) == FDT_MAGIC) {
+ struct spl_load_info load;
+
+ memset(&load, 0, sizeof(load));
+ load.bl_len = pagesize;
+ load.read = spl_romapi_read_seekable;
+ load.priv = &pagesize;
+ return spl_load_simple_fit(spl_image, &load,
+ offset / pagesize, header);
+ } else {
+ /* TODO */
+ puts("Can't support legacy image\n");
+ return -1;
+ }
+
+ return 0;
+}
+
+static ulong spl_ram_load_read(struct spl_load_info *load, ulong sector,
+ ulong count, void *buf)
+{
+ memcpy(buf, (void *)(sector), count);
+
+ if (load->priv) {
+ ulong *p = (ulong *)load->priv;
+ ulong total = sector + count;
+
+ if (total > *p)
+ *p = total;
+ }
+
+ return count;
+}
+
+static ulong get_fit_image_size(void *fit)
+{
+ struct spl_image_info spl_image;
+ struct spl_load_info spl_load_info;
+ ulong last = (ulong)fit;
+
+ memset(&spl_load_info, 0, sizeof(spl_load_info));
+ spl_load_info.bl_len = 1;
+ spl_load_info.read = spl_ram_load_read;
+ spl_load_info.priv = &last;
+
+ spl_load_simple_fit(&spl_image, &spl_load_info,
+ (uintptr_t)fit, fit);
+
+ return last - (ulong)fit;
+}
+
+u8 *search_fit_header(u8 *p, int size)
+{
+ int i;
+
+ for (i = 0; i < size; i += 4)
+ if (genimg_get_format(p + i) == IMAGE_FORMAT_FIT)
+ return p + i;
+
+ return NULL;
+}
+
+static int spl_romapi_load_image_stream(struct spl_image_info *spl_image,
+ struct spl_boot_device *bootdev)
+{
+ struct spl_load_info load;
+ volatile gd_t *pgd = gd;
+ u32 pagesize, pg;
+ int ret;
+ int i = 0;
+ u8 *p = (u8 *)CONFIG_SPL_IMX_ROMAPI_LOADADDR;
+ u8 *pfit = NULL;
+ int imagesize;
+ int total;
+
+ ret = g_rom_api->query_boot_infor(QUERY_PAGE_SZ, &pagesize,
+ ((uintptr_t)&pagesize) ^ QUERY_PAGE_SZ);
+ gd = pgd;
+
+ if (ret != ROM_API_OKAY)
+ puts("failure at query_boot_info\n");
+
+ pg = pagesize;
+ if (pg < 1024)
+ pg = 1024;
+
+ for (i = 0; i < 640; i++) {
+ ret = g_rom_api->download_image(p, 0, pg,
+ ((uintptr_t)p) ^ pg);
+ gd = pgd;
+
+ if (ret != ROM_API_OKAY) {
+ puts("Steam(USB) download failure\n");
+ return -1;
+ }
+
+ pfit = search_fit_header(p, pg);
+ p += pg;
+
+ if (pfit)
+ break;
+ }
+
+ if (!pfit) {
+ puts("Can't found uboot FIT image in 640K range \n");
+ return -1;
+ }
+
+ if (p - pfit < sizeof(struct fdt_header)) {
+ ret = g_rom_api->download_image(p, 0, pg, ((uintptr_t)p) ^ pg);
+ gd = pgd;
+
+ if (ret != ROM_API_OKAY) {
+ puts("Steam(USB) download failure\n");
+ return -1;
+ }
+
+ p += pg;
+ }
+
+ imagesize = fit_get_size(pfit);
+ printf("Find FIT header 0x&%p, size %d\n", pfit, imagesize);
+
+ if (p - pfit < imagesize) {
+ imagesize -= p - pfit;
+ /*need pagesize hear after ROM fix USB problme*/
+ imagesize += pg - 1;
+ imagesize /= pg;
+ imagesize *= pg;
+
+ printf("Need continue download %d\n", imagesize);
+
+ ret = g_rom_api->download_image(p, 0, imagesize,
+ ((uintptr_t)p) ^ imagesize);
+ gd = pgd;
+
+ p += imagesize;
+
+ if (ret != ROM_API_OKAY) {
+ printf("Failure download %d\n", imagesize);
+ return -1;
+ }
+ }
+
+ total = get_fit_image_size(pfit);
+ total += 3;
+ total &= ~0x3;
+
+ imagesize = total - (p - pfit);
+
+ imagesize += pagesize - 1;
+ imagesize /= pagesize;
+ imagesize *= pagesize;
+
+ printf("Download %d, total fit %d\n", imagesize, total);
+
+ ret = g_rom_api->download_image(p, 0, imagesize,
+ ((uintptr_t)p) ^ imagesize);
+ if (ret != ROM_API_OKAY)
+ printf("ROM download failure %d\n", imagesize);
+
+ memset(&load, 0, sizeof(load));
+ load.bl_len = 1;
+ load.read = spl_ram_load_read;
+
+ return spl_load_simple_fit(spl_image, &load, (ulong)pfit, pfit);
+}
+
+int board_return_to_bootrom(struct spl_image_info *spl_image,
+ struct spl_boot_device *bootdev)
+{
+ volatile gd_t *pgd = gd;
+ int ret;
+ u32 boot;
+
+ ret = g_rom_api->query_boot_infor(QUERY_BT_DEV, &boot,
+ ((uintptr_t)&boot) ^ QUERY_BT_DEV);
+ gd = pgd;
+
+ if (ret != ROM_API_OKAY) {
+ puts("ROMAPI: failure at query_boot_info\n");
+ return -1;
+ }
+
+ if (is_boot_from_stream_device(boot))
+ return spl_romapi_load_image_stream(spl_image, bootdev);
+
+ return spl_romapi_load_image_seekable(spl_image, bootdev, boot);
+}