uboot/common/spl/spl_nand.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0+
   2/*
   3 * Copyright (C) 2011
   4 * Corscience GmbH & Co. KG - Simon Schwarz <schwarz@corscience.de>
   5 */
   6#include <common.h>
   7#include <config.h>
   8#include <fdt_support.h>
   9#include <image.h>
  10#include <log.h>
  11#include <spl.h>
  12#include <asm/io.h>
  13#include <nand.h>
  14#include <linux/libfdt_env.h>
  15#include <fdt.h>
  16
  17uint32_t __weak spl_nand_get_uboot_raw_page(void)
  18{
  19        return CONFIG_SYS_NAND_U_BOOT_OFFS;
  20}
  21
  22#if defined(CONFIG_SPL_NAND_RAW_ONLY)
  23static int spl_nand_load_image(struct spl_image_info *spl_image,
  24                        struct spl_boot_device *bootdev)
  25{
  26        nand_init();
  27
  28        printf("Loading U-Boot from 0x%08x (size 0x%08x) to 0x%08x\n",
  29               CONFIG_SYS_NAND_U_BOOT_OFFS, CONFIG_SYS_NAND_U_BOOT_SIZE,
  30               CONFIG_SYS_NAND_U_BOOT_DST);
  31
  32        nand_spl_load_image(spl_nand_get_uboot_raw_page(),
  33                            CONFIG_SYS_NAND_U_BOOT_SIZE,
  34                            (void *)CONFIG_SYS_NAND_U_BOOT_DST);
  35        spl_set_header_raw_uboot(spl_image);
  36        nand_deselect();
  37
  38        return 0;
  39}
  40#else
  41
  42static ulong spl_nand_fit_read(struct spl_load_info *load, ulong offs,
  43                               ulong size, void *dst)
  44{
  45        ulong sector;
  46        int err;
  47
  48        sector = *(int *)load->priv;
  49        offs = sector + nand_spl_adjust_offset(sector, offs - sector);
  50        err = nand_spl_load_image(offs, size, dst);
  51        if (err)
  52                return 0;
  53
  54        return size;
  55}
  56
  57static int spl_nand_load_element(struct spl_image_info *spl_image,
  58                                 int offset, struct image_header *header)
  59{
  60        int err;
  61
  62        err = nand_spl_load_image(offset, sizeof(*header), (void *)header);
  63        if (err)
  64                return err;
  65
  66        if (IS_ENABLED(CONFIG_SPL_LOAD_FIT) &&
  67            image_get_magic(header) == FDT_MAGIC) {
  68                struct spl_load_info load;
  69
  70                debug("Found FIT\n");
  71                load.dev = NULL;
  72                load.priv = &offset;
  73                load.filename = NULL;
  74                load.bl_len = 1;
  75                load.read = spl_nand_fit_read;
  76                return spl_load_simple_fit(spl_image, &load, offset, header);
  77        } else if (IS_ENABLED(CONFIG_SPL_LOAD_IMX_CONTAINER)) {
  78                struct spl_load_info load;
  79
  80                load.dev = NULL;
  81                load.priv = NULL;
  82                load.filename = NULL;
  83                load.bl_len = 1;
  84                load.read = spl_nand_fit_read;
  85                return spl_load_imx_container(spl_image, &load, offset);
  86        } else {
  87                err = spl_parse_image_header(spl_image, header);
  88                if (err)
  89                        return err;
  90                return nand_spl_load_image(offset, spl_image->size,
  91                                           (void *)(ulong)spl_image->load_addr);
  92        }
  93}
  94
  95static int spl_nand_load_image(struct spl_image_info *spl_image,
  96                               struct spl_boot_device *bootdev)
  97{
  98        int err;
  99        struct image_header *header;
 100        int *src __attribute__((unused));
 101        int *dst __attribute__((unused));
 102
 103#ifdef CONFIG_SPL_NAND_SOFTECC
 104        debug("spl: nand - using sw ecc\n");
 105#else
 106        debug("spl: nand - using hw ecc\n");
 107#endif
 108        nand_init();
 109
 110        header = spl_get_load_buffer(0, sizeof(*header));
 111
 112#ifdef CONFIG_SPL_OS_BOOT
 113        if (!spl_start_uboot()) {
 114                /*
 115                 * load parameter image
 116                 * load to temp position since nand_spl_load_image reads
 117                 * a whole block which is typically larger than
 118                 * CONFIG_CMD_SPL_WRITE_SIZE therefore may overwrite
 119                 * following sections like BSS
 120                 */
 121                nand_spl_load_image(CONFIG_CMD_SPL_NAND_OFS,
 122                        CONFIG_CMD_SPL_WRITE_SIZE,
 123                        (void *)CONFIG_SYS_TEXT_BASE);
 124                /* copy to destintion */
 125                for (dst = (int *)CONFIG_SYS_SPL_ARGS_ADDR,
 126                                src = (int *)CONFIG_SYS_TEXT_BASE;
 127                                src < (int *)(CONFIG_SYS_TEXT_BASE +
 128                                CONFIG_CMD_SPL_WRITE_SIZE);
 129                                src++, dst++) {
 130                        writel(readl(src), dst);
 131                }
 132
 133                /* load linux */
 134                nand_spl_load_image(CONFIG_SYS_NAND_SPL_KERNEL_OFFS,
 135                        sizeof(*header), (void *)header);
 136                err = spl_parse_image_header(spl_image, header);
 137                if (err)
 138                        return err;
 139                if (header->ih_os == IH_OS_LINUX) {
 140                        /* happy - was a linux */
 141                        err = nand_spl_load_image(
 142                                CONFIG_SYS_NAND_SPL_KERNEL_OFFS,
 143                                spl_image->size,
 144                                (void *)spl_image->load_addr);
 145                        nand_deselect();
 146                        return err;
 147                } else {
 148                        puts("The Expected Linux image was not "
 149                                "found. Please check your NAND "
 150                                "configuration.\n");
 151                        puts("Trying to start u-boot now...\n");
 152                }
 153        }
 154#endif
 155#ifdef CONFIG_NAND_ENV_DST
 156        spl_nand_load_element(spl_image, CONFIG_ENV_OFFSET, header);
 157#ifdef CONFIG_ENV_OFFSET_REDUND
 158        spl_nand_load_element(spl_image, CONFIG_ENV_OFFSET_REDUND, header);
 159#endif
 160#endif
 161        /* Load u-boot */
 162        err = spl_nand_load_element(spl_image, spl_nand_get_uboot_raw_page(),
 163                                    header);
 164#ifdef CONFIG_SYS_NAND_U_BOOT_OFFS_REDUND
 165#if CONFIG_SYS_NAND_U_BOOT_OFFS != CONFIG_SYS_NAND_U_BOOT_OFFS_REDUND
 166        if (err)
 167                err = spl_nand_load_element(spl_image,
 168                                            CONFIG_SYS_NAND_U_BOOT_OFFS_REDUND,
 169                                            header);
 170#endif
 171#endif
 172        nand_deselect();
 173        return err;
 174}
 175#endif
 176/* Use priorty 1 so that Ubi can override this */
 177SPL_LOAD_IMAGE_METHOD("NAND", 1, BOOT_DEVICE_NAND, spl_nand_load_image);
 178