Commit 1cbebc78627607fa3f46b17fecdb4a0819b7e590

Authored by Peng Fan
Committed by Stefano Babic
1 parent a92c7b144f

imx: add rom api support

i.MX8MN support loading images with rom api, so we implement
reuse board_return_to_bootrom to let ROM loading images.

Signed-off-by: Peng Fan <peng.fan@nxp.com>

Showing 4 changed files with 331 additions and 0 deletions Side-by-side Diff

arch/arm/include/asm/mach-imx/sys_proto.h
... ... @@ -106,6 +106,39 @@
106 106  
107 107 #endif /* CONFIG_MX6 */
108 108  
  109 +#ifdef CONFIG_IMX8M
  110 +struct rom_api {
  111 + u16 ver;
  112 + u16 tag;
  113 + u32 reserved1;
  114 + u32 (*download_image)(u8 *dest, u32 offset, u32 size, u32 xor);
  115 + u32 (*query_boot_infor)(u32 info_type, u32 *info, u32 xor);
  116 +};
  117 +
  118 +enum boot_dev_type_e {
  119 + BT_DEV_TYPE_SD = 1,
  120 + BT_DEV_TYPE_MMC = 2,
  121 + BT_DEV_TYPE_NAND = 3,
  122 + BT_DEV_TYPE_FLEXSPINOR = 4,
  123 +
  124 + BT_DEV_TYPE_USB = 0xE,
  125 + BT_DEV_TYPE_MEM_DEV = 0xF,
  126 +
  127 + BT_DEV_TYPE_INVALID = 0xFF
  128 +};
  129 +
  130 +#define QUERY_ROM_VER 1
  131 +#define QUERY_BT_DEV 2
  132 +#define QUERY_PAGE_SZ 3
  133 +#define QUERY_IVT_OFF 4
  134 +#define QUERY_BT_STAGE 5
  135 +#define QUERY_IMG_OFF 6
  136 +
  137 +#define ROM_API_OKAY 0xF0
  138 +
  139 +extern struct rom_api *g_rom_api;
  140 +#endif
  141 +
109 142 u32 get_nr_cpus(void);
110 143 u32 get_cpu_rev(void);
111 144 u32 get_cpu_speed_grade_hz(void);
arch/arm/mach-imx/Kconfig
... ... @@ -109,4 +109,8 @@
109 109 NXP does NOT recommend to perform this calibration at each boot. One
110 110 shall perform it on a new PCB and then use those values to program
111 111 the ddrmc_cr_setting on relevant board file.
  112 +
  113 +config SPL_IMX_ROMAPI_LOADADDR
  114 + hex "Default load address to load image through ROM API"
  115 + depends on IMX8MN
arch/arm/mach-imx/Makefile
... ... @@ -226,4 +226,6 @@
226 226 obj-$(CONFIG_ARCH_MX7ULP) += mx7ulp/
227 227 obj-$(CONFIG_IMX8M) += imx8m/
228 228 obj-$(CONFIG_ARCH_IMX8) += imx8/
  229 +
  230 +obj-$(CONFIG_SPL_BOOTROM_SUPPORT) += spl_imx_romapi.o
arch/arm/mach-imx/spl_imx_romapi.c
  1 +// SPDX-License-Identifier: GPL-2.0+
  2 +/*
  3 + * Copyright 2019 NXP
  4 + */
  5 +
  6 +#include <common.h>
  7 +#include <errno.h>
  8 +#include <image.h>
  9 +#include <linux/libfdt.h>
  10 +#include <spl.h>
  11 +
  12 +#include <asm/arch/sys_proto.h>
  13 +
  14 +DECLARE_GLOBAL_DATA_PTR;
  15 +
  16 +static int is_boot_from_stream_device(u32 boot)
  17 +{
  18 + u32 interface;
  19 +
  20 + interface = boot >> 16;
  21 + if (interface >= BT_DEV_TYPE_USB)
  22 + return 1;
  23 +
  24 + if (interface == BT_DEV_TYPE_MMC && (boot & 1))
  25 + return 1;
  26 +
  27 + return 0;
  28 +}
  29 +
  30 +static ulong spl_romapi_read_seekable(struct spl_load_info *load,
  31 + ulong sector, ulong count,
  32 + void *buf)
  33 +{
  34 + u32 pagesize = *(u32 *)load->priv;
  35 + volatile gd_t *pgd = gd;
  36 + ulong byte = count * pagesize;
  37 + int ret;
  38 + u32 offset;
  39 +
  40 + offset = sector * pagesize;
  41 +
  42 + debug("ROM API load from 0x%x, size 0x%x\n", offset, (u32)byte);
  43 +
  44 + ret = g_rom_api->download_image(buf, offset, byte,
  45 + ((uintptr_t)buf) ^ offset ^ byte);
  46 + gd = pgd;
  47 +
  48 + if (ret == ROM_API_OKAY)
  49 + return count;
  50 +
  51 + printf("ROM API Failure when load 0x%x\n", offset);
  52 +
  53 + return 0;
  54 +}
  55 +
  56 +static int spl_romapi_load_image_seekable(struct spl_image_info *spl_image,
  57 + struct spl_boot_device *bootdev,
  58 + u32 rom_bt_dev)
  59 +{
  60 + volatile gd_t *pgd = gd;
  61 + int ret;
  62 + u32 offset;
  63 + u32 pagesize, size;
  64 + struct image_header *header;
  65 + u32 image_offset;
  66 +
  67 + ret = g_rom_api->query_boot_infor(QUERY_IVT_OFF, &offset,
  68 + ((uintptr_t)&offset) ^ QUERY_IVT_OFF);
  69 + ret |= g_rom_api->query_boot_infor(QUERY_PAGE_SZ, &pagesize,
  70 + ((uintptr_t)&pagesize) ^ QUERY_PAGE_SZ);
  71 + ret |= g_rom_api->query_boot_infor(QUERY_IMG_OFF, &image_offset,
  72 + ((uintptr_t)&image_offset) ^ QUERY_IMG_OFF);
  73 +
  74 + gd = pgd;
  75 +
  76 + if (ret != ROM_API_OKAY) {
  77 + puts("ROMAPI: Failure query boot infor pagesize/offset\n");
  78 + return -1;
  79 + }
  80 +
  81 + header = (struct image_header *)(CONFIG_SPL_IMX_ROMAPI_LOADADDR);
  82 +
  83 + printf("image offset 0x%x, pagesize 0x%x, ivt offset 0x%x\n",
  84 + image_offset, pagesize, offset);
  85 +
  86 + if (((rom_bt_dev >> 16) & 0xff) == BT_DEV_TYPE_FLEXSPINOR)
  87 + offset = CONFIG_SYS_MMCSD_RAW_MODE_U_BOOT_SECTOR * 512;
  88 + else
  89 + offset = image_offset +
  90 + CONFIG_SYS_MMCSD_RAW_MODE_U_BOOT_SECTOR * 512 - 0x8000;
  91 +
  92 + size = ALIGN(sizeof(struct image_header), pagesize);
  93 + ret = g_rom_api->download_image((u8 *)header, offset, size,
  94 + ((uintptr_t)header) ^ offset ^ size);
  95 + gd = pgd;
  96 +
  97 + if (ret != ROM_API_OKAY) {
  98 + printf("ROMAPI: download failure offset 0x%x size 0x%x\n",
  99 + offset, size);
  100 + return -1;
  101 + }
  102 +
  103 + if (IS_ENABLED(CONFIG_SPL_LOAD_FIT) &&
  104 + image_get_magic(header) == FDT_MAGIC) {
  105 + struct spl_load_info load;
  106 +
  107 + memset(&load, 0, sizeof(load));
  108 + load.bl_len = pagesize;
  109 + load.read = spl_romapi_read_seekable;
  110 + load.priv = &pagesize;
  111 + return spl_load_simple_fit(spl_image, &load,
  112 + offset / pagesize, header);
  113 + } else {
  114 + /* TODO */
  115 + puts("Can't support legacy image\n");
  116 + return -1;
  117 + }
  118 +
  119 + return 0;
  120 +}
  121 +
  122 +static ulong spl_ram_load_read(struct spl_load_info *load, ulong sector,
  123 + ulong count, void *buf)
  124 +{
  125 + memcpy(buf, (void *)(sector), count);
  126 +
  127 + if (load->priv) {
  128 + ulong *p = (ulong *)load->priv;
  129 + ulong total = sector + count;
  130 +
  131 + if (total > *p)
  132 + *p = total;
  133 + }
  134 +
  135 + return count;
  136 +}
  137 +
  138 +static ulong get_fit_image_size(void *fit)
  139 +{
  140 + struct spl_image_info spl_image;
  141 + struct spl_load_info spl_load_info;
  142 + ulong last = (ulong)fit;
  143 +
  144 + memset(&spl_load_info, 0, sizeof(spl_load_info));
  145 + spl_load_info.bl_len = 1;
  146 + spl_load_info.read = spl_ram_load_read;
  147 + spl_load_info.priv = &last;
  148 +
  149 + spl_load_simple_fit(&spl_image, &spl_load_info,
  150 + (uintptr_t)fit, fit);
  151 +
  152 + return last - (ulong)fit;
  153 +}
  154 +
  155 +u8 *search_fit_header(u8 *p, int size)
  156 +{
  157 + int i;
  158 +
  159 + for (i = 0; i < size; i += 4)
  160 + if (genimg_get_format(p + i) == IMAGE_FORMAT_FIT)
  161 + return p + i;
  162 +
  163 + return NULL;
  164 +}
  165 +
  166 +static int spl_romapi_load_image_stream(struct spl_image_info *spl_image,
  167 + struct spl_boot_device *bootdev)
  168 +{
  169 + struct spl_load_info load;
  170 + volatile gd_t *pgd = gd;
  171 + u32 pagesize, pg;
  172 + int ret;
  173 + int i = 0;
  174 + u8 *p = (u8 *)CONFIG_SPL_IMX_ROMAPI_LOADADDR;
  175 + u8 *pfit = NULL;
  176 + int imagesize;
  177 + int total;
  178 +
  179 + ret = g_rom_api->query_boot_infor(QUERY_PAGE_SZ, &pagesize,
  180 + ((uintptr_t)&pagesize) ^ QUERY_PAGE_SZ);
  181 + gd = pgd;
  182 +
  183 + if (ret != ROM_API_OKAY)
  184 + puts("failure at query_boot_info\n");
  185 +
  186 + pg = pagesize;
  187 + if (pg < 1024)
  188 + pg = 1024;
  189 +
  190 + for (i = 0; i < 640; i++) {
  191 + ret = g_rom_api->download_image(p, 0, pg,
  192 + ((uintptr_t)p) ^ pg);
  193 + gd = pgd;
  194 +
  195 + if (ret != ROM_API_OKAY) {
  196 + puts("Steam(USB) download failure\n");
  197 + return -1;
  198 + }
  199 +
  200 + pfit = search_fit_header(p, pg);
  201 + p += pg;
  202 +
  203 + if (pfit)
  204 + break;
  205 + }
  206 +
  207 + if (!pfit) {
  208 + puts("Can't found uboot FIT image in 640K range \n");
  209 + return -1;
  210 + }
  211 +
  212 + if (p - pfit < sizeof(struct fdt_header)) {
  213 + ret = g_rom_api->download_image(p, 0, pg, ((uintptr_t)p) ^ pg);
  214 + gd = pgd;
  215 +
  216 + if (ret != ROM_API_OKAY) {
  217 + puts("Steam(USB) download failure\n");
  218 + return -1;
  219 + }
  220 +
  221 + p += pg;
  222 + }
  223 +
  224 + imagesize = fit_get_size(pfit);
  225 + printf("Find FIT header 0x&%p, size %d\n", pfit, imagesize);
  226 +
  227 + if (p - pfit < imagesize) {
  228 + imagesize -= p - pfit;
  229 + /*need pagesize hear after ROM fix USB problme*/
  230 + imagesize += pg - 1;
  231 + imagesize /= pg;
  232 + imagesize *= pg;
  233 +
  234 + printf("Need continue download %d\n", imagesize);
  235 +
  236 + ret = g_rom_api->download_image(p, 0, imagesize,
  237 + ((uintptr_t)p) ^ imagesize);
  238 + gd = pgd;
  239 +
  240 + p += imagesize;
  241 +
  242 + if (ret != ROM_API_OKAY) {
  243 + printf("Failure download %d\n", imagesize);
  244 + return -1;
  245 + }
  246 + }
  247 +
  248 + total = get_fit_image_size(pfit);
  249 + total += 3;
  250 + total &= ~0x3;
  251 +
  252 + imagesize = total - (p - pfit);
  253 +
  254 + imagesize += pagesize - 1;
  255 + imagesize /= pagesize;
  256 + imagesize *= pagesize;
  257 +
  258 + printf("Download %d, total fit %d\n", imagesize, total);
  259 +
  260 + ret = g_rom_api->download_image(p, 0, imagesize,
  261 + ((uintptr_t)p) ^ imagesize);
  262 + if (ret != ROM_API_OKAY)
  263 + printf("ROM download failure %d\n", imagesize);
  264 +
  265 + memset(&load, 0, sizeof(load));
  266 + load.bl_len = 1;
  267 + load.read = spl_ram_load_read;
  268 +
  269 + return spl_load_simple_fit(spl_image, &load, (ulong)pfit, pfit);
  270 +}
  271 +
  272 +int board_return_to_bootrom(struct spl_image_info *spl_image,
  273 + struct spl_boot_device *bootdev)
  274 +{
  275 + volatile gd_t *pgd = gd;
  276 + int ret;
  277 + u32 boot;
  278 +
  279 + ret = g_rom_api->query_boot_infor(QUERY_BT_DEV, &boot,
  280 + ((uintptr_t)&boot) ^ QUERY_BT_DEV);
  281 + gd = pgd;
  282 +
  283 + if (ret != ROM_API_OKAY) {
  284 + puts("ROMAPI: failure at query_boot_info\n");
  285 + return -1;
  286 + }
  287 +
  288 + if (is_boot_from_stream_device(boot))
  289 + return spl_romapi_load_image_stream(spl_image, bootdev);
  290 +
  291 + return spl_romapi_load_image_seekable(spl_image, bootdev, boot);
  292 +}