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