bbd95469870f29ee07edfbf860349d598991ed3f
[oweals/u-boot.git] / common / spl / spl_nand.c
1 /*
2  * Copyright (C) 2011
3  * Corscience GmbH & Co. KG - Simon Schwarz <schwarz@corscience.de>
4  *
5  * SPDX-License-Identifier:     GPL-2.0+
6  */
7 #include <common.h>
8 #include <config.h>
9 #include <spl.h>
10 #include <asm/io.h>
11 #include <nand.h>
12
13 #if defined(CONFIG_SPL_NAND_RAW_ONLY)
14 int spl_nand_load_image(void)
15 {
16         nand_init();
17
18         nand_spl_load_image(CONFIG_SYS_NAND_U_BOOT_OFFS,
19                             CONFIG_SYS_NAND_U_BOOT_SIZE,
20                             (void *)CONFIG_SYS_NAND_U_BOOT_DST);
21         spl_set_header_raw_uboot();
22         nand_deselect();
23
24         return 0;
25 }
26 #else
27 static int spl_nand_load_element(int offset, struct image_header *header)
28 {
29         int err;
30
31         err = nand_spl_load_image(offset, sizeof(*header), (void *)header);
32         if (err)
33                 return err;
34
35         err = spl_parse_image_header(header);
36         if (err)
37                 return err;
38
39         return nand_spl_load_image(offset, spl_image.size,
40                                    (void *)(unsigned long)spl_image.load_addr);
41 }
42
43 int spl_nand_load_image(void)
44 {
45         int err;
46         struct image_header *header;
47         int *src __attribute__((unused));
48         int *dst __attribute__((unused));
49
50 #ifdef CONFIG_SPL_NAND_SOFTECC
51         debug("spl: nand - using sw ecc\n");
52 #else
53         debug("spl: nand - using hw ecc\n");
54 #endif
55         nand_init();
56
57         /*use CONFIG_SYS_TEXT_BASE as temporary storage area */
58         header = (struct image_header *)(CONFIG_SYS_TEXT_BASE);
59 #ifdef CONFIG_SPL_OS_BOOT
60         if (!spl_start_uboot()) {
61                 /*
62                  * load parameter image
63                  * load to temp position since nand_spl_load_image reads
64                  * a whole block which is typically larger than
65                  * CONFIG_CMD_SPL_WRITE_SIZE therefore may overwrite
66                  * following sections like BSS
67                  */
68                 nand_spl_load_image(CONFIG_CMD_SPL_NAND_OFS,
69                         CONFIG_CMD_SPL_WRITE_SIZE,
70                         (void *)CONFIG_SYS_TEXT_BASE);
71                 /* copy to destintion */
72                 for (dst = (int *)CONFIG_SYS_SPL_ARGS_ADDR,
73                                 src = (int *)CONFIG_SYS_TEXT_BASE;
74                                 src < (int *)(CONFIG_SYS_TEXT_BASE +
75                                 CONFIG_CMD_SPL_WRITE_SIZE);
76                                 src++, dst++) {
77                         writel(readl(src), dst);
78                 }
79
80                 /* load linux */
81                 nand_spl_load_image(CONFIG_SYS_NAND_SPL_KERNEL_OFFS,
82                         sizeof(*header), (void *)header);
83                 err = spl_parse_image_header(header);
84                 if (err)
85                         return err;
86                 if (header->ih_os == IH_OS_LINUX) {
87                         /* happy - was a linux */
88                         err = nand_spl_load_image(
89                                 CONFIG_SYS_NAND_SPL_KERNEL_OFFS,
90                                 spl_image.size,
91                                 (void *)spl_image.load_addr);
92                         nand_deselect();
93                         return err;
94                 } else {
95                         puts("The Expected Linux image was not "
96                                 "found. Please check your NAND "
97                                 "configuration.\n");
98                         puts("Trying to start u-boot now...\n");
99                 }
100         }
101 #endif
102 #ifdef CONFIG_NAND_ENV_DST
103         spl_nand_load_element(CONFIG_ENV_OFFSET, header);
104 #ifdef CONFIG_ENV_OFFSET_REDUND
105         spl_nand_load_element(CONFIG_ENV_OFFSET_REDUND, header);
106 #endif
107 #endif
108         /* Load u-boot */
109         err = spl_nand_load_element(CONFIG_SYS_NAND_U_BOOT_OFFS, header);
110         nand_deselect();
111         return err;
112 }
113 #endif