uboot/common/spl/spl_spi.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0+
   2/*
   3 * Copyright (C) 2011 OMICRON electronics GmbH
   4 *
   5 * based on drivers/mtd/nand/raw/nand_spl_load.c
   6 *
   7 * Copyright (C) 2011
   8 * Heiko Schocher, DENX Software Engineering, hs@denx.de.
   9 */
  10
  11#include <common.h>
  12#include <image.h>
  13#include <log.h>
  14#include <spi.h>
  15#include <spi_flash.h>
  16#include <errno.h>
  17#include <spl.h>
  18#include <asm/global_data.h>
  19#include <dm/ofnode.h>
  20
  21#if CONFIG_IS_ENABLED(OS_BOOT)
  22/*
  23 * Load the kernel, check for a valid header we can parse, and if found load
  24 * the kernel and then device tree.
  25 */
  26static int spi_load_image_os(struct spl_image_info *spl_image,
  27                             struct spl_boot_device *bootdev,
  28                             struct spi_flash *flash,
  29                             struct image_header *header)
  30{
  31        int err;
  32
  33        /* Read for a header, parse or error out. */
  34        spi_flash_read(flash, CONFIG_SYS_SPI_KERNEL_OFFS, sizeof(*header),
  35                       (void *)header);
  36
  37        if (image_get_magic(header) != IH_MAGIC)
  38                return -1;
  39
  40        err = spl_parse_image_header(spl_image, bootdev, header);
  41        if (err)
  42                return err;
  43
  44        spi_flash_read(flash, CONFIG_SYS_SPI_KERNEL_OFFS,
  45                       spl_image->size, (void *)spl_image->load_addr);
  46
  47        /* Read device tree. */
  48        spi_flash_read(flash, CONFIG_SYS_SPI_ARGS_OFFS,
  49                       CONFIG_SYS_SPI_ARGS_SIZE,
  50                       (void *)CONFIG_SYS_SPL_ARGS_ADDR);
  51
  52        return 0;
  53}
  54#endif
  55
  56static ulong spl_spi_fit_read(struct spl_load_info *load, ulong sector,
  57                              ulong count, void *buf)
  58{
  59        struct spi_flash *flash = load->dev;
  60        ulong ret;
  61
  62        ret = spi_flash_read(flash, sector, count, buf);
  63        if (!ret)
  64                return count;
  65        else
  66                return 0;
  67}
  68
  69unsigned int __weak spl_spi_get_uboot_offs(struct spi_flash *flash)
  70{
  71        return CONFIG_SYS_SPI_U_BOOT_OFFS;
  72}
  73
  74u32 __weak spl_spi_boot_bus(void)
  75{
  76        return CONFIG_SF_DEFAULT_BUS;
  77}
  78
  79u32 __weak spl_spi_boot_cs(void)
  80{
  81        return CONFIG_SF_DEFAULT_CS;
  82}
  83
  84/*
  85 * The main entry for SPI booting. It's necessary that SDRAM is already
  86 * configured and available since this code loads the main U-Boot image
  87 * from SPI into SDRAM and starts it from there.
  88 */
  89static int spl_spi_load_image(struct spl_image_info *spl_image,
  90                              struct spl_boot_device *bootdev)
  91{
  92        int err = 0;
  93        unsigned int payload_offs;
  94        struct spi_flash *flash;
  95        struct image_header *header;
  96        unsigned int sf_bus = spl_spi_boot_bus();
  97        unsigned int sf_cs = spl_spi_boot_cs();
  98
  99        /*
 100         * Load U-Boot image from SPI flash into RAM
 101         * In DM mode: defaults speed and mode will be
 102         * taken from DT when available
 103         */
 104        flash = spi_flash_probe(sf_bus, sf_cs,
 105                                CONFIG_SF_DEFAULT_SPEED,
 106                                CONFIG_SF_DEFAULT_MODE);
 107        if (!flash) {
 108                puts("SPI probe failed.\n");
 109                return -ENODEV;
 110        }
 111
 112        payload_offs = spl_spi_get_uboot_offs(flash);
 113
 114        header = spl_get_load_buffer(-sizeof(*header), sizeof(*header));
 115
 116        if (CONFIG_IS_ENABLED(OF_REAL)) {
 117                payload_offs = ofnode_conf_read_int("u-boot,spl-payload-offset",
 118                                                    payload_offs);
 119        }
 120
 121#if CONFIG_IS_ENABLED(OS_BOOT)
 122        if (spl_start_uboot() || spi_load_image_os(spl_image, bootdev, flash, header))
 123#endif
 124        {
 125                /* Load u-boot, mkimage header is 64 bytes. */
 126                err = spi_flash_read(flash, payload_offs, sizeof(*header),
 127                                     (void *)header);
 128                if (err) {
 129                        debug("%s: Failed to read from SPI flash (err=%d)\n",
 130                              __func__, err);
 131                        return err;
 132                }
 133
 134                if (IS_ENABLED(CONFIG_SPL_LOAD_FIT_FULL) &&
 135                    image_get_magic(header) == FDT_MAGIC) {
 136                        err = spi_flash_read(flash, payload_offs,
 137                                             roundup(fdt_totalsize(header), 4),
 138                                             (void *)CONFIG_SYS_LOAD_ADDR);
 139                        if (err)
 140                                return err;
 141                        err = spl_parse_image_header(spl_image, bootdev,
 142                                        (struct image_header *)CONFIG_SYS_LOAD_ADDR);
 143                } else if (IS_ENABLED(CONFIG_SPL_LOAD_FIT) &&
 144                           image_get_magic(header) == FDT_MAGIC) {
 145                        struct spl_load_info load;
 146
 147                        debug("Found FIT\n");
 148                        load.dev = flash;
 149                        load.priv = NULL;
 150                        load.filename = NULL;
 151                        load.bl_len = 1;
 152                        load.read = spl_spi_fit_read;
 153                        err = spl_load_simple_fit(spl_image, &load,
 154                                                  payload_offs,
 155                                                  header);
 156                } else if (IS_ENABLED(CONFIG_SPL_LOAD_IMX_CONTAINER)) {
 157                        struct spl_load_info load;
 158
 159                        load.dev = flash;
 160                        load.priv = NULL;
 161                        load.filename = NULL;
 162                        load.bl_len = 1;
 163                        load.read = spl_spi_fit_read;
 164
 165                        err = spl_load_imx_container(spl_image, &load,
 166                                                     payload_offs);
 167                } else {
 168                        err = spl_parse_image_header(spl_image, bootdev, header);
 169                        if (err)
 170                                return err;
 171                        err = spi_flash_read(flash, payload_offs + spl_image->offset,
 172                                             spl_image->size,
 173                                             (void *)spl_image->load_addr);
 174                }
 175                if (IS_ENABLED(CONFIG_SPI_FLASH_SOFT_RESET)) {
 176                        err = spi_nor_remove(flash);
 177                        if (err)
 178                                return err;
 179                }
 180        }
 181
 182        return err;
 183}
 184/* Use priorty 1 so that boards can override this */
 185SPL_LOAD_IMAGE_METHOD("SPI", 1, BOOT_DEVICE_SPI, spl_spi_load_image);
 186