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