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