diff options
author | Sascha Hauer <s.hauer@pengutronix.de> | 2023-04-19 08:58:58 +0200 |
---|---|---|
committer | Sascha Hauer <s.hauer@pengutronix.de> | 2023-04-19 08:58:58 +0200 |
commit | c46996d29b49b9d7fc33aa4ae59ea90596da068f (patch) | |
tree | a6cd5e98fbb2a6e47061cb3071fb4a4b083373f4 /arch | |
parent | dc4f31b6c0d121402aead43cb7c13121ad9a3d9d (diff) | |
parent | c20cf77b26f230d40aef3f086f305dfc35a01a9e (diff) | |
download | barebox-c46996d29b49b9d7fc33aa4ae59ea90596da068f.tar.gz |
Merge branch 'for-next/imx-image'
Diffstat (limited to 'arch')
-rw-r--r-- | arch/arm/boards/nxp-imx8mm-evk/board.c | 1 | ||||
-rw-r--r-- | arch/arm/boards/nxp-imx8mm-evk/flash-header-imx8mm-evk.imxcfg | 3 | ||||
-rw-r--r-- | arch/arm/boards/nxp-imx8mm-evk/lowlevel.c | 1 | ||||
-rw-r--r-- | arch/arm/boards/nxp-imx8mn-evk/board.c | 1 | ||||
-rw-r--r-- | arch/arm/boards/nxp-imx8mn-evk/flash-header-imx8mn-evk.imxcfg | 3 | ||||
-rw-r--r-- | arch/arm/boards/nxp-imx8mn-evk/lowlevel.c | 4 | ||||
-rw-r--r-- | arch/arm/boards/nxp-imx8mp-evk/board.c | 1 | ||||
-rw-r--r-- | arch/arm/boards/nxp-imx8mp-evk/flash-header-imx8mp-evk.imxcfg | 3 | ||||
-rw-r--r-- | arch/arm/dts/imx8mm-evk.dtsi | 19 | ||||
-rw-r--r-- | arch/arm/dts/imx8mn-evk.dtsi | 19 | ||||
-rw-r--r-- | arch/arm/dts/imx8mp-evk.dts | 19 | ||||
-rw-r--r-- | arch/arm/mach-imx/Makefile | 1 | ||||
-rw-r--r-- | arch/arm/mach-imx/atf.c | 9 | ||||
-rw-r--r-- | arch/arm/mach-imx/boot.c | 19 | ||||
-rw-r--r-- | arch/arm/mach-imx/imx-bbu-internal.c | 49 | ||||
-rw-r--r-- | arch/arm/mach-imx/xload-common.c | 120 | ||||
-rw-r--r-- | arch/arm/mach-imx/xload-qspi.c | 57 |
17 files changed, 322 insertions, 7 deletions
diff --git a/arch/arm/boards/nxp-imx8mm-evk/board.c b/arch/arm/boards/nxp-imx8mm-evk/board.c index fd748262f7..c8e17570ca 100644 --- a/arch/arm/boards/nxp-imx8mm-evk/board.c +++ b/arch/arm/boards/nxp-imx8mm-evk/board.c @@ -53,6 +53,7 @@ static int imx8mm_evk_probe(struct device *dev) imx8m_bbu_internal_mmc_register_handler("SD", "/dev/mmc1.barebox", sd_bbu_flag); imx8m_bbu_internal_mmcboot_register_handler("eMMC", "/dev/mmc2", emmc_bbu_flag); + imx8m_bbu_internal_flexspi_nor_register_handler("QSPI", "/dev/m25p0.barebox", 0); phy_register_fixup_for_uid(PHY_ID_AR8031, AR_PHY_ID_MASK, ar8031_phy_fixup); diff --git a/arch/arm/boards/nxp-imx8mm-evk/flash-header-imx8mm-evk.imxcfg b/arch/arm/boards/nxp-imx8mm-evk/flash-header-imx8mm-evk.imxcfg index 10606ce29c..d6a536053e 100644 --- a/arch/arm/boards/nxp-imx8mm-evk/flash-header-imx8mm-evk.imxcfg +++ b/arch/arm/boards/nxp-imx8mm-evk/flash-header-imx8mm-evk.imxcfg @@ -5,3 +5,6 @@ soc imx8mm loadaddr 0x007e1000 max_load_size 0x3f000 ivtofs 0x400 + +flexspi_ivtofs 0x1000 +flexspi_fcfbofs 0x0 diff --git a/arch/arm/boards/nxp-imx8mm-evk/lowlevel.c b/arch/arm/boards/nxp-imx8mm-evk/lowlevel.c index 9983f78bab..46b5f317b5 100644 --- a/arch/arm/boards/nxp-imx8mm-evk/lowlevel.c +++ b/arch/arm/boards/nxp-imx8mm-evk/lowlevel.c @@ -161,6 +161,7 @@ ENTRY_FUNCTION(start_nxp_imx8mm_evk, r0, r1, r2) setup_c(); IMD_USED_OF(imx8mm_evk); + IMD_USED_OF(imx8mm_evkb); nxp_imx8mm_evk_start(); } diff --git a/arch/arm/boards/nxp-imx8mn-evk/board.c b/arch/arm/boards/nxp-imx8mn-evk/board.c index 13efc62a58..3e90ba284c 100644 --- a/arch/arm/boards/nxp-imx8mn-evk/board.c +++ b/arch/arm/boards/nxp-imx8mn-evk/board.c @@ -51,6 +51,7 @@ static int imx8mn_evk_probe(struct device *dev) imx8m_bbu_internal_mmc_register_handler("SD", "/dev/mmc1.barebox", sd_bbu_flag); imx8m_bbu_internal_mmcboot_register_handler("eMMC", "/dev/mmc2", emmc_bbu_flag); + imx8m_bbu_internal_flexspi_nor_register_handler("QSPI", "/dev/m25p0.barebox", 0); phy_register_fixup_for_uid(PHY_ID_AR8031, AR_PHY_ID_MASK, ar8031_phy_fixup); diff --git a/arch/arm/boards/nxp-imx8mn-evk/flash-header-imx8mn-evk.imxcfg b/arch/arm/boards/nxp-imx8mn-evk/flash-header-imx8mn-evk.imxcfg index 27a2138e43..a9b592e624 100644 --- a/arch/arm/boards/nxp-imx8mn-evk/flash-header-imx8mn-evk.imxcfg +++ b/arch/arm/boards/nxp-imx8mn-evk/flash-header-imx8mn-evk.imxcfg @@ -5,3 +5,6 @@ soc imx8mn loadaddr 0x912000 max_load_size 0x3f000 ivtofs 0x0 + +flexspi_ivtofs 0x0 +flexspi_fcfbofs 0x400 diff --git a/arch/arm/boards/nxp-imx8mn-evk/lowlevel.c b/arch/arm/boards/nxp-imx8mn-evk/lowlevel.c index 8e7383c9d2..398dfb33ae 100644 --- a/arch/arm/boards/nxp-imx8mn-evk/lowlevel.c +++ b/arch/arm/boards/nxp-imx8mn-evk/lowlevel.c @@ -1,6 +1,7 @@ // SPDX-License-Identifier: GPL-2.0 #include <io.h> +#include <image-metadata.h> #include <common.h> #include <debug_ll.h> #include <mach/imx/debug_ll.h> @@ -154,5 +155,8 @@ ENTRY_FUNCTION(start_nxp_imx8mn_evk, r0, r1, r2) relocate_to_current_adr(); setup_c(); + IMD_USED_OF(imx8mn_evk); + IMD_USED_OF(imx8mn_ddr4_evk); + nxp_imx8mn_evk_start(); } diff --git a/arch/arm/boards/nxp-imx8mp-evk/board.c b/arch/arm/boards/nxp-imx8mp-evk/board.c index 0c9fe7835b..2aa551e504 100644 --- a/arch/arm/boards/nxp-imx8mp-evk/board.c +++ b/arch/arm/boards/nxp-imx8mp-evk/board.c @@ -36,6 +36,7 @@ static int nxp_imx8mp_evk_probe(struct device *dev) imx8m_bbu_internal_mmc_register_handler("SD", "/dev/mmc1.barebox", sd_bbu_flag); imx8m_bbu_internal_mmcboot_register_handler("eMMC", "/dev/mmc2", emmc_bbu_flag); + imx8m_bbu_internal_flexspi_nor_register_handler("QSPI", "/dev/m25p0.barebox", 0); /* Enable RGMII TX clk output */ val = readl(MX8MP_IOMUXC_GPR_BASE_ADDR + MX8MP_IOMUXC_GPR1); diff --git a/arch/arm/boards/nxp-imx8mp-evk/flash-header-imx8mp-evk.imxcfg b/arch/arm/boards/nxp-imx8mp-evk/flash-header-imx8mp-evk.imxcfg index 663bd102e9..3bb44d199c 100644 --- a/arch/arm/boards/nxp-imx8mp-evk/flash-header-imx8mp-evk.imxcfg +++ b/arch/arm/boards/nxp-imx8mp-evk/flash-header-imx8mp-evk.imxcfg @@ -5,3 +5,6 @@ soc imx8mp loadaddr 0x920000 max_load_size 0x3f000 ivtofs 0x0 + +flexspi_ivtofs 0x0 +flexspi_fcfbofs 0x400 diff --git a/arch/arm/dts/imx8mm-evk.dtsi b/arch/arm/dts/imx8mm-evk.dtsi index 4d64dcad1c..a657faa6bc 100644 --- a/arch/arm/dts/imx8mm-evk.dtsi +++ b/arch/arm/dts/imx8mm-evk.dtsi @@ -19,6 +19,25 @@ }; }; +&{flexspi/flash@0} { + partitions { + compatible = "fixed-partitions"; + #address-cells = <1>; + #size-cells = <1>; + + partition@0 { + label = "barebox"; + reg = <0x0 0xe0000>; + }; + + partition@e0000 { + label = "barebox-environment"; + reg = <0xe0000 0x20000>; + }; + }; + +}; + ®_usdhc2_vmmc { off-on-delay-us = <20000>; }; diff --git a/arch/arm/dts/imx8mn-evk.dtsi b/arch/arm/dts/imx8mn-evk.dtsi index d15f66ff40..c23075216e 100644 --- a/arch/arm/dts/imx8mn-evk.dtsi +++ b/arch/arm/dts/imx8mn-evk.dtsi @@ -21,6 +21,25 @@ }; }; +&flash0 { + partitions { + compatible = "fixed-partitions"; + #address-cells = <1>; + #size-cells = <1>; + + partition@0 { + label = "barebox"; + reg = <0x0 0xe0000>; + }; + + partition@e0000 { + label = "barebox-environment"; + reg = <0xe0000 0x20000>; + }; + }; + +}; + &usdhc2 { #address-cells = <1>; #size-cells = <1>; diff --git a/arch/arm/dts/imx8mp-evk.dts b/arch/arm/dts/imx8mp-evk.dts index ecec4d2a66..c7e1f35d2d 100644 --- a/arch/arm/dts/imx8mp-evk.dts +++ b/arch/arm/dts/imx8mp-evk.dts @@ -37,6 +37,25 @@ reset-deassert-us = <100000>; }; +&{flexspi/flash@0} { + partitions { + compatible = "fixed-partitions"; + #address-cells = <1>; + #size-cells = <1>; + + partition@0 { + label = "barebox"; + reg = <0x0 0xe0000>; + }; + + partition@e0000 { + label = "barebox-environment"; + reg = <0xe0000 0x20000>; + }; + }; + +}; + ®_usdhc2_vmmc { off-on-delay-us = <20000>; }; diff --git a/arch/arm/mach-imx/Makefile b/arch/arm/mach-imx/Makefile index 5d70e79b57..f49bbea2b4 100644 --- a/arch/arm/mach-imx/Makefile +++ b/arch/arm/mach-imx/Makefile @@ -31,3 +31,4 @@ obj-$(CONFIG_BAREBOX_UPDATE_IMX_EXTERNAL_NAND) += imx-bbu-external-nand.o obj-$(CONFIG_RESET_IMX_SRC) += src.o lwl-y += cpu_init.o pbl-y += xload-spi.o xload-common.o xload-imx-nand.o xload-gpmi-nand.o +pbl-y += xload-qspi.o diff --git a/arch/arm/mach-imx/atf.c b/arch/arm/mach-imx/atf.c index 2b667cf583..92820d9392 100644 --- a/arch/arm/mach-imx/atf.c +++ b/arch/arm/mach-imx/atf.c @@ -112,6 +112,9 @@ void imx8mm_load_bl33(void *bl33) } break; + case BOOTSOURCE_SPI: + imx8mm_qspi_load_image(instance, false); + break; default: printf("Unhandled bootsource BOOTSOURCE_%d\n", src); hang(); @@ -156,6 +159,9 @@ void imx8mp_load_bl33(void *bl33) case BOOTSOURCE_SERIAL: imx8mp_bootrom_load_image(); break; + case BOOTSOURCE_SPI: + imx8mp_qspi_load_image(instance, false); + break; default: printf("Unhandled bootsource BOOTSOURCE_%d\n", src); hang(); @@ -202,6 +208,9 @@ void imx8mn_load_bl33(void *bl33) case BOOTSOURCE_SERIAL: imx8mn_bootrom_load_image(); break; + case BOOTSOURCE_SPI: + imx8mn_qspi_load_image(instance, false); + break; default: printf("Unhandled bootsource BOOTSOURCE_%d\n", src); hang(); diff --git a/arch/arm/mach-imx/boot.c b/arch/arm/mach-imx/boot.c index a6322e4850..c6134f35b6 100644 --- a/arch/arm/mach-imx/boot.c +++ b/arch/arm/mach-imx/boot.c @@ -243,6 +243,11 @@ static unsigned int imx8mp_get_bmod(uint32_t r) return FIELD_GET(IMX8MP_SRC_SBMR_BMOD, r); } +static unsigned int imx8mm_get_bcfg(uint32_t r) +{ + return FIELD_GET(BOOT_CFG2(6, 4), r); +} + static int imx53_bootsource_internal(uint32_t r) { return FIELD_GET(BOOT_CFG1(7, 4), r); @@ -323,6 +328,7 @@ void imx53_boot_save_loc(void) #define IMX6_SRC_GPR10 0x44 #define IMX6_BMOD_SERIAL 0b01 #define IMX6_BMOD_RESERVED 0b11 +#define IMX8MM_BCFG_FSPI 0b100 #define IMX8MP_BMOD_FUSES 0b0000 #define IMX8MP_BMOD_SERIAL 0b0001 #define IMX6_BMOD_FUSES 0b00 @@ -358,6 +364,11 @@ static bool imx8mp_bootsource_serial(uint32_t sbmr2) !(sbmr2 & BT_FUSE_SEL)); } +static bool imx8mm_bootsource_qspi(uint32_t sbmr1) +{ + return imx8mm_get_bcfg(sbmr1) == IMX8MM_BCFG_FSPI; +} + static bool imx6_bootsource_serial_forced(uint32_t bootmode) { if (cpu_mx6_is_mx6ul() || cpu_mx6_is_mx6ull()) @@ -535,6 +546,7 @@ static void __imx7_get_boot_source(enum bootsource *src, int *instance, break; case 4: *src = BOOTSOURCE_SPI; /* Really: qspi */ + *instance = info->boot_device_instance; break; case 5: *src = BOOTSOURCE_NOR; @@ -691,6 +703,7 @@ void imx8mm_get_boot_source(enum bootsource *src, int *instance) { unsigned long addr; void __iomem *src_base = IOMEM(MX8MM_SRC_BASE_ADDR); + uint32_t sbmr1 = readl(src_base + 0x58); uint32_t sbmr2 = readl(src_base + 0x70); if (imx6_bootsource_serial(sbmr2)) { @@ -698,6 +711,12 @@ void imx8mm_get_boot_source(enum bootsource *src, int *instance) return; } + if (imx8mm_bootsource_qspi(sbmr1)) { + *src = BOOTSOURCE_SPI; /* Really: qspi */ + *instance = 0; + return; + } + addr = IMX8M_BOOT_SW_INFO_POINTER_ADDR_A0; __imx7_get_boot_source(src, instance, addr, sbmr2); diff --git a/arch/arm/mach-imx/imx-bbu-internal.c b/arch/arm/mach-imx/imx-bbu-internal.c index a86bd75253..8cdaab5c16 100644 --- a/arch/arm/mach-imx/imx-bbu-internal.c +++ b/arch/arm/mach-imx/imx-bbu-internal.c @@ -19,15 +19,15 @@ #include <environment.h> #include <mach/imx/bbu.h> #include <mach/imx/generic.h> +#include <mach/imx/imx-header.h> #include <libfile.h> -#define IMX_INTERNAL_FLAG_ERASE BIT(30) - struct imx_internal_bbu_handler { struct bbu_handler handler; int (*write_device)(struct imx_internal_bbu_handler *, struct bbu_data *); unsigned long flash_header_offset; + unsigned long filetype_offset; size_t device_size; enum filetype expected_type; }; @@ -35,7 +35,7 @@ struct imx_internal_bbu_handler { static bool imx_bbu_erase_required(struct imx_internal_bbu_handler *imx_handler) { - return imx_handler->handler.flags & IMX_INTERNAL_FLAG_ERASE; + return imx_handler->handler.flags & IMX_BBU_FLAG_ERASE; } static int imx_bbu_protect(int fd, struct imx_internal_bbu_handler *imx_handler, @@ -163,8 +163,8 @@ static int imx_bbu_check_prereq(struct imx_internal_bbu_handler *imx_handler, if (expected_type == filetype_unknown) break; - blob = data->image + imx_handler->flash_header_offset; - len = data->len - imx_handler->flash_header_offset; + blob = data->image + imx_handler->filetype_offset; + len = data->len - imx_handler->filetype_offset; type = file_detect_type(blob, len); if (type != expected_type) { @@ -472,6 +472,7 @@ imx_bbu_internal_mmc_register_handler(const char *name, const char *devicefile, imx_handler = __init_handler(name, devicefile, flags | IMX_BBU_FLAG_KEEP_HEAD); imx_handler->flash_header_offset = imx_bbu_flash_header_offset_mmc(); + imx_handler->filetype_offset = imx_handler->flash_header_offset; return __register_handler(imx_handler); } @@ -484,8 +485,9 @@ imx_bbu_internal_spi_i2c_register_handler(const char *name, struct imx_internal_bbu_handler *imx_handler; imx_handler = __init_handler(name, devicefile, flags | - IMX_INTERNAL_FLAG_ERASE); + IMX_BBU_FLAG_ERASE); imx_handler->flash_header_offset = imx_bbu_flash_header_offset_mmc(); + imx_handler->filetype_offset = imx_handler->flash_header_offset; return __register_handler(imx_handler); } @@ -531,6 +533,7 @@ int imx53_bbu_internal_nand_register_handler(const char *name, imx_handler = __init_handler(name, "/dev/nand0", flags); imx_handler->flash_header_offset = imx_bbu_flash_header_offset_mmc(); + imx_handler->filetype_offset = imx_handler->flash_header_offset; imx_handler->device_size = partition_size; imx_handler->write_device = imx_bbu_internal_v2_write_nand_dbbt; @@ -582,6 +585,7 @@ static int imx_bbu_internal_mmcboot_register_handler(const char *name, imx_handler = __init_handler(name, devicefile, flags); imx_handler->flash_header_offset = flash_header_offset; + imx_handler->filetype_offset = flash_header_offset; imx_handler->handler.handler = imx_bbu_internal_mmcboot_update; @@ -646,9 +650,40 @@ int imx_bbu_external_nor_register_handler(const char *name, struct imx_internal_bbu_handler *imx_handler; imx_handler = __init_handler(name, devicefile, flags | - IMX_INTERNAL_FLAG_ERASE); + IMX_BBU_FLAG_ERASE); imx_handler->expected_type = filetype_unknown; return __register_handler(imx_handler); } + +static unsigned long imx_bbu_filetype_offset_flexspi(void) +{ + unsigned int sd_flash_header_gap = SZ_32K; + + if (cpu_is_mx8mm()) + return sd_flash_header_gap; + + return sd_flash_header_gap + SZ_1K; +} + +static int +imx_bbu_internal_flexspi_nor_register_handler(const char *name, + const char *devicefile, + unsigned long flags) +{ + struct imx_internal_bbu_handler *imx_handler; + + flags |= IMX_BBU_FLAG_ERASE | IMX_BBU_FLAG_PARTITION_STARTS_AT_HEADER; + imx_handler = __init_handler(name, devicefile, flags); + imx_handler->flash_header_offset = SZ_32K; + imx_handler->expected_type = filetype_nxp_fspi_image; + imx_handler->filetype_offset = imx_bbu_filetype_offset_flexspi(); + + return __register_handler(imx_handler); +} + +int imx8m_bbu_internal_flexspi_nor_register_handler(const char *name, + const char *devicefile, + unsigned long flags) + __alias(imx_bbu_internal_flexspi_nor_register_handler); diff --git a/arch/arm/mach-imx/xload-common.c b/arch/arm/mach-imx/xload-common.c index 5a437b185d..0d3e6be1b1 100644 --- a/arch/arm/mach-imx/xload-common.c +++ b/arch/arm/mach-imx/xload-common.c @@ -1,11 +1,13 @@ // SPDX-License-Identifier: GPL-2.0-only #include <common.h> +#include <asm/cache.h> #include <asm/sections.h> #include <linux/sizes.h> #include <mach/imx/xload.h> #include <mach/imx/esdctl.h> #include <mach/imx/imx8m-regs.h> +#include <mach/imx/imx-header.h> #include <asm/barebox-arm.h> int imx_image_size(void) @@ -26,3 +28,121 @@ struct imx_scratch_space *__imx8m_scratch_space(int ddr_buswidth) return (void *)__arm_mem_scratch(endmem); } + +#define HDR_SIZE 512 + +static int +imx_search_header(struct imx_flash_header_v2 **header_pointer, + void *buffer, u32 *offset, u32 ivt_offset, + int (*read)(void *dest, size_t len, void *priv), + void *priv) +{ + int ret; + int i, header_count = 1; + void *buf = buffer; + struct imx_flash_header_v2 *hdr; + + for (i = 0; i < header_count; i++) { + ret = read(buf, *offset + ivt_offset + HDR_SIZE, priv); + if (ret) + return ret; + + hdr = buf + *offset + ivt_offset; + + if (!is_imx_flash_header_v2(hdr)) { + pr_debug("No IVT header! " + "Found tag: 0x%02x length: 0x%04x " + "version: %02x\n", + hdr->header.tag, hdr->header.length, + hdr->header.version); + return -EINVAL; + } + + if (IS_ENABLED(CONFIG_ARCH_IMX8MQ) && + hdr->boot_data.plugin & PLUGIN_HDMI_IMAGE) { + /* + * In images that include signed HDMI + * firmware, first v2 header would be + * dedicated to that and would not contain any + * useful for us information. In order for us + * to pull the rest of the bootloader image + * in, we need to re-read header from SD/MMC, + * this time skipping anything HDMI firmware + * related. + */ + *offset += hdr->boot_data.size + hdr->header.length; + header_count++; + } + } + *header_pointer = hdr; + return 0; +} + +int imx_load_image(ptrdiff_t address, ptrdiff_t entry, u32 offset, + u32 ivt_offset, bool start, unsigned int alignment, + int (*read)(void *dest, size_t len, void *priv), + void *priv) +{ + + void *buf = (void *)address; + struct imx_flash_header_v2 *hdr = NULL; + int ret, len; + void __noreturn (*bb)(void); + unsigned int ofs; + + len = imx_image_size(); + if (alignment) + len = ALIGN(len, alignment); + + ret = imx_search_header(&hdr, buf, &offset, ivt_offset, read, priv); + if (ret) + return ret; + + 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' gives us the + * adjustment 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 = read(buf, ofs + len, priv); + if (ret) { + pr_err("Loading image failed with %d\n", ret); + return ret; + } + + pr_debug("Image loaded successfully\n"); + + if (!start) + return 0; + + bb = buf + ofs; + + sync_caches_for_execution(); + + bb(); +} diff --git a/arch/arm/mach-imx/xload-qspi.c b/arch/arm/mach-imx/xload-qspi.c new file mode 100644 index 0000000000..6bf5bba5e6 --- /dev/null +++ b/arch/arm/mach-imx/xload-qspi.c @@ -0,0 +1,57 @@ +// SPDX-License-Identifier: GPL-2.0 + +#include <common.h> +#include <linux/sizes.h> +#include <mach/imx/atf.h> +#include <mach/imx/imx8m-regs.h> +#include <mach/imx/xload.h> + +#define IMX8M_QSPI_MMAP 0x8000000 + +/* Make use of AHB reads */ +static +int imx8m_qspi_read(void *dest, size_t len, void *priv) +{ + void __iomem *qspi_ahb = priv; + + memcpy(dest, qspi_ahb, len); + + return 0; +} + +/** + * imx8mm_qspi_start_image - Load and optionally start an image from the + * FlexSPI controller. + * @instance: The FlexSPI controller instance + * @start: Whether to directly start the loaded image + * + * This uses imx8m_qspi_load_image() to load an image from QSPI. It is assumed + * that the image is the currently running barebox image (This information + * is used to calculate the length of the image). + * The image is started afterwards. + * + * Return: If successful, this function does not return (if directly started) + * or 0. A negative error code is returned when this function fails. + */ +static +int imx8m_qspi_load_image(int instance, bool start, off_t offset, off_t ivt_offset) +{ + void __iomem *qspi_ahb = IOMEM(IMX8M_QSPI_MMAP); + + return imx_load_image(MX8M_DDR_CSD1_BASE_ADDR, MX8M_ATF_BL33_BASE_ADDR, + offset, ivt_offset, start, 0, + imx8m_qspi_read, qspi_ahb); +} + +int imx8mm_qspi_load_image(int instance, bool start) +{ + return imx8m_qspi_load_image(instance, start, 0, SZ_4K); +} + +int imx8mn_qspi_load_image(int instance, bool start) +{ + return imx8m_qspi_load_image(instance, start, SZ_4K, 0); +} + +int imx8mp_qspi_load_image(int instance, bool start) + __alias(imx8mn_qspi_load_image); |