]>
Commit | Line | Data |
---|---|---|
83d290c5 | 1 | // SPDX-License-Identifier: GPL-2.0+ |
9ea5c6ef SS |
2 | /* |
3 | * Copyright (C) 2011 | |
4 | * Corscience GmbH & Co. KG - Simon Schwarz <[email protected]> | |
9ea5c6ef SS |
5 | */ |
6 | #include <common.h> | |
d97b4ce8 | 7 | #include <config.h> |
4d72caa5 SG |
8 | #include <fdt_support.h> |
9 | #include <image.h> | |
f7ae49fc | 10 | #include <log.h> |
47f7bcae | 11 | #include <spl.h> |
df163a59 | 12 | #include <asm/io.h> |
9ea5c6ef | 13 | #include <nand.h> |
b08c8c48 | 14 | #include <linux/libfdt_env.h> |
8bd88772 | 15 | #include <fdt.h> |
9ea5c6ef | 16 | |
2c79229c PF |
17 | uint32_t __weak spl_nand_get_uboot_raw_page(void) |
18 | { | |
19 | return CONFIG_SYS_NAND_U_BOOT_OFFS; | |
20 | } | |
21 | ||
0c3117b1 | 22 | #if defined(CONFIG_SPL_NAND_RAW_ONLY) |
25dabd73 | 23 | static int spl_nand_load_image(struct spl_image_info *spl_image, |
2a2ee2ac | 24 | struct spl_boot_device *bootdev) |
0c3117b1 HS |
25 | { |
26 | nand_init(); | |
27 | ||
443b3ce5 SR |
28 | printf("Loading U-Boot from 0x%08x (size 0x%08x) to 0x%08x\n", |
29 | CONFIG_SYS_NAND_U_BOOT_OFFS, CONFIG_SYS_NAND_U_BOOT_SIZE, | |
30 | CONFIG_SYS_NAND_U_BOOT_DST); | |
31 | ||
2c79229c | 32 | nand_spl_load_image(spl_nand_get_uboot_raw_page(), |
0c3117b1 HS |
33 | CONFIG_SYS_NAND_U_BOOT_SIZE, |
34 | (void *)CONFIG_SYS_NAND_U_BOOT_DST); | |
2a2ee2ac | 35 | spl_set_header_raw_uboot(spl_image); |
0c3117b1 | 36 | nand_deselect(); |
36afd451 NK |
37 | |
38 | return 0; | |
0c3117b1 HS |
39 | } |
40 | #else | |
8bd88772 LV |
41 | |
42 | static ulong spl_nand_fit_read(struct spl_load_info *load, ulong offs, | |
43 | ulong size, void *dst) | |
44 | { | |
9f6a14c4 | 45 | ulong sector; |
84dd1902 | 46 | int err; |
8bd88772 | 47 | |
9f6a14c4 DB |
48 | sector = *(int *)load->priv; |
49 | offs = sector + nand_spl_adjust_offset(sector, offs - sector); | |
84dd1902 DB |
50 | err = nand_spl_load_image(offs, size, dst); |
51 | if (err) | |
8bd88772 | 52 | return 0; |
84dd1902 DB |
53 | |
54 | return size; | |
8bd88772 LV |
55 | } |
56 | ||
2a2ee2ac SG |
57 | static int spl_nand_load_element(struct spl_image_info *spl_image, |
58 | int offset, struct image_header *header) | |
483ab3dc NK |
59 | { |
60 | int err; | |
61 | ||
62 | err = nand_spl_load_image(offset, sizeof(*header), (void *)header); | |
63 | if (err) | |
64 | return err; | |
65 | ||
8bd88772 LV |
66 | if (IS_ENABLED(CONFIG_SPL_LOAD_FIT) && |
67 | image_get_magic(header) == FDT_MAGIC) { | |
68 | struct spl_load_info load; | |
7e0f2267 | 69 | |
8bd88772 LV |
70 | debug("Found FIT\n"); |
71 | load.dev = NULL; | |
9f6a14c4 | 72 | load.priv = &offset; |
8bd88772 LV |
73 | load.filename = NULL; |
74 | load.bl_len = 1; | |
75 | load.read = spl_nand_fit_read; | |
f4d7d859 | 76 | return spl_load_simple_fit(spl_image, &load, offset, header); |
00e180cc PF |
77 | } else if (IS_ENABLED(CONFIG_SPL_LOAD_IMX_CONTAINER)) { |
78 | struct spl_load_info load; | |
79 | ||
80 | load.dev = NULL; | |
81 | load.priv = NULL; | |
82 | load.filename = NULL; | |
83 | load.bl_len = 1; | |
84 | load.read = spl_nand_fit_read; | |
85 | return spl_load_imx_container(spl_image, &load, offset); | |
8bd88772 | 86 | } else { |
2a2ee2ac | 87 | err = spl_parse_image_header(spl_image, header); |
8bd88772 LV |
88 | if (err) |
89 | return err; | |
2a2ee2ac SG |
90 | return nand_spl_load_image(offset, spl_image->size, |
91 | (void *)(ulong)spl_image->load_addr); | |
8bd88772 | 92 | } |
483ab3dc NK |
93 | } |
94 | ||
2a2ee2ac SG |
95 | static int spl_nand_load_image(struct spl_image_info *spl_image, |
96 | struct spl_boot_device *bootdev) | |
9ea5c6ef | 97 | { |
36afd451 | 98 | int err; |
9ea5c6ef | 99 | struct image_header *header; |
df163a59 SS |
100 | int *src __attribute__((unused)); |
101 | int *dst __attribute__((unused)); | |
102 | ||
8122d216 ASK |
103 | #ifdef CONFIG_SPL_NAND_SOFTECC |
104 | debug("spl: nand - using sw ecc\n"); | |
105 | #else | |
8082fda9 | 106 | debug("spl: nand - using hw ecc\n"); |
8122d216 | 107 | #endif |
8082fda9 | 108 | nand_init(); |
9ea5c6ef | 109 | |
04ce5427 MV |
110 | header = spl_get_load_buffer(0, sizeof(*header)); |
111 | ||
df163a59 | 112 | #ifdef CONFIG_SPL_OS_BOOT |
379c19ab | 113 | if (!spl_start_uboot()) { |
df163a59 SS |
114 | /* |
115 | * load parameter image | |
116 | * load to temp position since nand_spl_load_image reads | |
117 | * a whole block which is typically larger than | |
b6e95fd4 | 118 | * CONFIG_CMD_SPL_WRITE_SIZE therefore may overwrite |
df163a59 SS |
119 | * following sections like BSS |
120 | */ | |
121 | nand_spl_load_image(CONFIG_CMD_SPL_NAND_OFS, | |
122 | CONFIG_CMD_SPL_WRITE_SIZE, | |
123 | (void *)CONFIG_SYS_TEXT_BASE); | |
124 | /* copy to destintion */ | |
125 | for (dst = (int *)CONFIG_SYS_SPL_ARGS_ADDR, | |
126 | src = (int *)CONFIG_SYS_TEXT_BASE; | |
127 | src < (int *)(CONFIG_SYS_TEXT_BASE + | |
128 | CONFIG_CMD_SPL_WRITE_SIZE); | |
129 | src++, dst++) { | |
130 | writel(readl(src), dst); | |
131 | } | |
9ea5c6ef | 132 | |
df163a59 SS |
133 | /* load linux */ |
134 | nand_spl_load_image(CONFIG_SYS_NAND_SPL_KERNEL_OFFS, | |
c13bb167 | 135 | sizeof(*header), (void *)header); |
2a2ee2ac | 136 | err = spl_parse_image_header(spl_image, header); |
7e0f2267 MV |
137 | if (err) |
138 | return err; | |
379c19ab SS |
139 | if (header->ih_os == IH_OS_LINUX) { |
140 | /* happy - was a linux */ | |
36afd451 NK |
141 | err = nand_spl_load_image( |
142 | CONFIG_SYS_NAND_SPL_KERNEL_OFFS, | |
2a2ee2ac SG |
143 | spl_image->size, |
144 | (void *)spl_image->load_addr); | |
379c19ab | 145 | nand_deselect(); |
36afd451 | 146 | return err; |
379c19ab | 147 | } else { |
d97b4ce8 TR |
148 | puts("The Expected Linux image was not " |
149 | "found. Please check your NAND " | |
379c19ab | 150 | "configuration.\n"); |
d97b4ce8 | 151 | puts("Trying to start u-boot now...\n"); |
379c19ab SS |
152 | } |
153 | } | |
df163a59 | 154 | #endif |
9ea5c6ef | 155 | #ifdef CONFIG_NAND_ENV_DST |
2a2ee2ac | 156 | spl_nand_load_element(spl_image, CONFIG_ENV_OFFSET, header); |
9ea5c6ef | 157 | #ifdef CONFIG_ENV_OFFSET_REDUND |
2a2ee2ac | 158 | spl_nand_load_element(spl_image, CONFIG_ENV_OFFSET_REDUND, header); |
9ea5c6ef SS |
159 | #endif |
160 | #endif | |
379c19ab | 161 | /* Load u-boot */ |
2c79229c | 162 | err = spl_nand_load_element(spl_image, spl_nand_get_uboot_raw_page(), |
2a2ee2ac | 163 | header); |
80ef700f BB |
164 | #ifdef CONFIG_SYS_NAND_U_BOOT_OFFS_REDUND |
165 | #if CONFIG_SYS_NAND_U_BOOT_OFFS != CONFIG_SYS_NAND_U_BOOT_OFFS_REDUND | |
166 | if (err) | |
2a2ee2ac SG |
167 | err = spl_nand_load_element(spl_image, |
168 | CONFIG_SYS_NAND_U_BOOT_OFFS_REDUND, | |
80ef700f BB |
169 | header); |
170 | #endif | |
171 | #endif | |
9ea5c6ef | 172 | nand_deselect(); |
36afd451 | 173 | return err; |
9ea5c6ef | 174 | } |
0c3117b1 | 175 | #endif |
d5c2b11c | 176 | /* Use priorty 1 so that Ubi can override this */ |
ebc4ef61 | 177 | SPL_LOAD_IMAGE_METHOD("NAND", 1, BOOT_DEVICE_NAND, spl_nand_load_image); |