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