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