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) 16 int spl_nand_load_image(void) 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(); 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(int offset, struct image_header *header) 43 { 44 int err; 45 46 err = nand_spl_load_image(offset, sizeof(*header), (void *)header); 47 if (err) 48 return err; 49 50 if (IS_ENABLED(CONFIG_SPL_LOAD_FIT) && 51 image_get_magic(header) == FDT_MAGIC) { 52 struct spl_load_info load; 53 54 debug("Found FIT\n"); 55 load.dev = NULL; 56 load.priv = NULL; 57 load.filename = NULL; 58 load.bl_len = 1; 59 load.read = spl_nand_fit_read; 60 return spl_load_simple_fit(&load, offset, header); 61 } else { 62 err = spl_parse_image_header(header); 63 if (err) 64 return err; 65 return nand_spl_load_image(offset, spl_image.size, 66 (void *)(ulong)spl_image.load_addr); 67 } 68 } 69 70 int spl_nand_load_image(void) 71 { 72 int err; 73 struct image_header *header; 74 int *src __attribute__((unused)); 75 int *dst __attribute__((unused)); 76 77 #ifdef CONFIG_SPL_NAND_SOFTECC 78 debug("spl: nand - using sw ecc\n"); 79 #else 80 debug("spl: nand - using hw ecc\n"); 81 #endif 82 nand_init(); 83 84 /*use CONFIG_SYS_TEXT_BASE as temporary storage area */ 85 header = (struct image_header *)(CONFIG_SYS_TEXT_BASE); 86 #ifdef CONFIG_SPL_OS_BOOT 87 if (!spl_start_uboot()) { 88 /* 89 * load parameter image 90 * load to temp position since nand_spl_load_image reads 91 * a whole block which is typically larger than 92 * CONFIG_CMD_SPL_WRITE_SIZE therefore may overwrite 93 * following sections like BSS 94 */ 95 nand_spl_load_image(CONFIG_CMD_SPL_NAND_OFS, 96 CONFIG_CMD_SPL_WRITE_SIZE, 97 (void *)CONFIG_SYS_TEXT_BASE); 98 /* copy to destintion */ 99 for (dst = (int *)CONFIG_SYS_SPL_ARGS_ADDR, 100 src = (int *)CONFIG_SYS_TEXT_BASE; 101 src < (int *)(CONFIG_SYS_TEXT_BASE + 102 CONFIG_CMD_SPL_WRITE_SIZE); 103 src++, dst++) { 104 writel(readl(src), dst); 105 } 106 107 /* load linux */ 108 nand_spl_load_image(CONFIG_SYS_NAND_SPL_KERNEL_OFFS, 109 sizeof(*header), (void *)header); 110 err = spl_parse_image_header(header); 111 if (err) 112 return err; 113 if (header->ih_os == IH_OS_LINUX) { 114 /* happy - was a linux */ 115 err = nand_spl_load_image( 116 CONFIG_SYS_NAND_SPL_KERNEL_OFFS, 117 spl_image.size, 118 (void *)spl_image.load_addr); 119 nand_deselect(); 120 return err; 121 } else { 122 puts("The Expected Linux image was not " 123 "found. Please check your NAND " 124 "configuration.\n"); 125 puts("Trying to start u-boot now...\n"); 126 } 127 } 128 #endif 129 #ifdef CONFIG_NAND_ENV_DST 130 spl_nand_load_element(CONFIG_ENV_OFFSET, header); 131 #ifdef CONFIG_ENV_OFFSET_REDUND 132 spl_nand_load_element(CONFIG_ENV_OFFSET_REDUND, header); 133 #endif 134 #endif 135 /* Load u-boot */ 136 err = spl_nand_load_element(CONFIG_SYS_NAND_U_BOOT_OFFS, header); 137 nand_deselect(); 138 return err; 139 } 140 #endif 141