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