1
2
3
4
5
6#include <common.h>
7#include <config.h>
8#include <fdt_support.h>
9#include <image.h>
10#include <log.h>
11#include <spl.h>
12#include <asm/io.h>
13#include <nand.h>
14#include <linux/libfdt_env.h>
15#include <fdt.h>
16
17uint32_t __weak spl_nand_get_uboot_raw_page(void)
18{
19 return CONFIG_SYS_NAND_U_BOOT_OFFS;
20}
21
22#if defined(CONFIG_SPL_NAND_RAW_ONLY)
23static int spl_nand_load_image(struct spl_image_info *spl_image,
24 struct spl_boot_device *bootdev)
25{
26 nand_init();
27
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
32 nand_spl_load_image(spl_nand_get_uboot_raw_page(),
33 CONFIG_SYS_NAND_U_BOOT_SIZE,
34 (void *)CONFIG_SYS_NAND_U_BOOT_DST);
35 spl_set_header_raw_uboot(spl_image);
36 nand_deselect();
37
38 return 0;
39}
40#else
41
42static ulong spl_nand_fit_read(struct spl_load_info *load, ulong offs,
43 ulong size, void *dst)
44{
45 ulong sector;
46 int err;
47
48 sector = *(int *)load->priv;
49 offs = sector + nand_spl_adjust_offset(sector, offs - sector);
50 err = nand_spl_load_image(offs, size, dst);
51 if (err)
52 return 0;
53
54 return size;
55}
56
57static int spl_nand_load_element(struct spl_image_info *spl_image,
58 int offset, struct image_header *header)
59{
60 int err;
61
62 err = nand_spl_load_image(offset, sizeof(*header), (void *)header);
63 if (err)
64 return err;
65
66 if (IS_ENABLED(CONFIG_SPL_LOAD_FIT) &&
67 image_get_magic(header) == FDT_MAGIC) {
68 struct spl_load_info load;
69
70 debug("Found FIT\n");
71 load.dev = NULL;
72 load.priv = &offset;
73 load.filename = NULL;
74 load.bl_len = 1;
75 load.read = spl_nand_fit_read;
76 return spl_load_simple_fit(spl_image, &load, offset, header);
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);
86 } else {
87 err = spl_parse_image_header(spl_image, header);
88 if (err)
89 return err;
90 return nand_spl_load_image(offset, spl_image->size,
91 (void *)(ulong)spl_image->load_addr);
92 }
93}
94
95static int spl_nand_load_image(struct spl_image_info *spl_image,
96 struct spl_boot_device *bootdev)
97{
98 int err;
99 struct image_header *header;
100 int *src __attribute__((unused));
101 int *dst __attribute__((unused));
102
103#ifdef CONFIG_SPL_NAND_SOFTECC
104 debug("spl: nand - using sw ecc\n");
105#else
106 debug("spl: nand - using hw ecc\n");
107#endif
108 nand_init();
109
110 header = spl_get_load_buffer(0, sizeof(*header));
111
112#ifdef CONFIG_SPL_OS_BOOT
113 if (!spl_start_uboot()) {
114
115
116
117
118
119
120
121 nand_spl_load_image(CONFIG_CMD_SPL_NAND_OFS,
122 CONFIG_CMD_SPL_WRITE_SIZE,
123 (void *)CONFIG_SYS_TEXT_BASE);
124
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 }
132
133
134 nand_spl_load_image(CONFIG_SYS_NAND_SPL_KERNEL_OFFS,
135 sizeof(*header), (void *)header);
136 err = spl_parse_image_header(spl_image, header);
137 if (err)
138 return err;
139 if (header->ih_os == IH_OS_LINUX) {
140
141 err = nand_spl_load_image(
142 CONFIG_SYS_NAND_SPL_KERNEL_OFFS,
143 spl_image->size,
144 (void *)spl_image->load_addr);
145 nand_deselect();
146 return err;
147 } else {
148 puts("The Expected Linux image was not "
149 "found. Please check your NAND "
150 "configuration.\n");
151 puts("Trying to start u-boot now...\n");
152 }
153 }
154#endif
155#ifdef CONFIG_NAND_ENV_DST
156 spl_nand_load_element(spl_image, CONFIG_ENV_OFFSET, header);
157#ifdef CONFIG_ENV_OFFSET_REDUND
158 spl_nand_load_element(spl_image, CONFIG_ENV_OFFSET_REDUND, header);
159#endif
160#endif
161
162 err = spl_nand_load_element(spl_image, spl_nand_get_uboot_raw_page(),
163 header);
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)
167 err = spl_nand_load_element(spl_image,
168 CONFIG_SYS_NAND_U_BOOT_OFFS_REDUND,
169 header);
170#endif
171#endif
172 nand_deselect();
173 return err;
174}
175#endif
176
177SPL_LOAD_IMAGE_METHOD("NAND", 1, BOOT_DEVICE_NAND, spl_nand_load_image);
178