From f7a43e46065609910bdd2fa6f97ffa1deeda222b Mon Sep 17 00:00:00 2001 From: Matthias Schiffer Date: Sun, 27 Mar 2022 20:57:01 +0200 Subject: mpc85xx: add SPI kernel loader for TP-Link TL-WDR4900 v1 Similar to the lzma-loader on our MIPS targets, the spi-loader acts as a second-stage loader that will then load and start the actual kernel. As the TL-WDR4900 uses SPI-NOR and the P1010 family does not have support for memory mapping of this type of flash, this loader needs to contain a basic driver for the FSL ESPI controller. Signed-off-by: Matthias Schiffer (cherry picked from commit a296055b82fbb20457273492069ce9d62009e2a1) --- target/linux/mpc85xx/image/spi-loader/loader.c | 107 +++++++++++++++++++++++++ 1 file changed, 107 insertions(+) create mode 100644 target/linux/mpc85xx/image/spi-loader/loader.c (limited to 'target/linux/mpc85xx/image/spi-loader/loader.c') diff --git a/target/linux/mpc85xx/image/spi-loader/loader.c b/target/linux/mpc85xx/image/spi-loader/loader.c new file mode 100644 index 0000000000..145a723033 --- /dev/null +++ b/target/linux/mpc85xx/image/spi-loader/loader.c @@ -0,0 +1,107 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright (c) 2022 Matthias Schiffer + */ + +#include +#include +#include +#include +#include +#include + +static bool check_image_header(const image_header_t *header) +{ + if (header->ih_magic != cpu_to_be32(IH_MAGIC_OKLI)) { + puts("Invalid image magic\n"); + return false; + } + + if (header->ih_comp != cpu_to_be32(IH_COMP_NONE)) { + puts("Unsupported compressed image\n"); + return false; + } + + return true; +} + +static uint32_t do_load(void) +{ + image_header_t header; + uint32_t ih_size, ih_load, ih_ep; + + if (spi_nor_read_id()) + return UINT32_MAX; + + puts("Reading image header...\n"); + if (spi_nor_read_data(&header, CONFIG_IMAGE_OFFSET, sizeof(header))) + return UINT32_MAX; + + if (!check_image_header(&header)) + return UINT32_MAX; + + header.ih_name[sizeof(header.ih_name) - 1] = 0; + ih_size = be32_to_cpu(header.ih_size); + ih_load = be32_to_cpu(header.ih_load); + ih_ep = be32_to_cpu(header.ih_ep); + + put_with_label("Image Name: ", puts, (const char *)header.ih_name); + put_with_label("Data Size: ", put_u32, ih_size); + put_with_label("Load Address: ", put_u32, ih_load); + put_with_label("Entry Point: ", put_u32, ih_ep); + + puts("Reading image data...\n"); + void *loadaddr = (void *)ih_load; + if (spi_nor_read_data(loadaddr, CONFIG_IMAGE_OFFSET + sizeof(header), + ih_size)) + return false; + + flush_cache(loadaddr, ih_size); + + return ih_ep; +} + +static void enter_image(uint32_t addr) +{ + typedef void (*entry_t)(void); + entry_t entry = (entry_t)addr; + + puts("Starting image...\n"); + entry(); +} + +static void load(void) +{ + uint32_t addr; + int ret; + + ret = spi_init(0, CONFIG_SPI_MAX_HZ, SPI_MODE_0); + if (ret) { + puts("Failed to initialize SPI controller\n"); + return; + } + + ret = spi_claim_bus(); + if (ret) { + puts("Failed to enable SPI controller\n"); + return; + } + + addr = do_load(); + + spi_release_bus(); + + if (addr != UINT32_MAX) + enter_image(addr); +} + +void start(void) +{ + serial_console_init(); + puts("=== " CONFIG_PROGRAM_NAME " ===\n"); + + load(); + + puts("Halting execution.\n"); + while (true) {} +} -- cgit v1.2.3