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