Merge branch 'master' of git://git.denx.de/u-boot-fsl-qoriq
[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         spl_parse_image_header(header);
36         return nand_spl_load_image(offset, spl_image.size,
37                                    (void *)(unsigned long)spl_image.load_addr);
38 }
39
40 int spl_nand_load_image(void)
41 {
42         int err;
43         struct image_header *header;
44         int *src __attribute__((unused));
45         int *dst __attribute__((unused));
46
47         debug("spl: nand - using hw ecc\n");
48         nand_init();
49
50         /*use CONFIG_SYS_TEXT_BASE as temporary storage area */
51         header = (struct image_header *)(CONFIG_SYS_TEXT_BASE);
52 #ifdef CONFIG_SPL_OS_BOOT
53         if (!spl_start_uboot()) {
54                 /*
55                  * load parameter image
56                  * load to temp position since nand_spl_load_image reads
57                  * a whole block which is typically larger than
58                  * CONFIG_CMD_SPL_WRITE_SIZE therefore may overwrite
59                  * following sections like BSS
60                  */
61                 nand_spl_load_image(CONFIG_CMD_SPL_NAND_OFS,
62                         CONFIG_CMD_SPL_WRITE_SIZE,
63                         (void *)CONFIG_SYS_TEXT_BASE);
64                 /* copy to destintion */
65                 for (dst = (int *)CONFIG_SYS_SPL_ARGS_ADDR,
66                                 src = (int *)CONFIG_SYS_TEXT_BASE;
67                                 src < (int *)(CONFIG_SYS_TEXT_BASE +
68                                 CONFIG_CMD_SPL_WRITE_SIZE);
69                                 src++, dst++) {
70                         writel(readl(src), dst);
71                 }
72
73                 /* load linux */
74                 nand_spl_load_image(CONFIG_SYS_NAND_SPL_KERNEL_OFFS,
75                         sizeof(*header), (void *)header);
76                 spl_parse_image_header(header);
77                 if (header->ih_os == IH_OS_LINUX) {
78                         /* happy - was a linux */
79                         err = nand_spl_load_image(
80                                 CONFIG_SYS_NAND_SPL_KERNEL_OFFS,
81                                 spl_image.size,
82                                 (void *)spl_image.load_addr);
83                         nand_deselect();
84                         return err;
85                 } else {
86                         puts("The Expected Linux image was not "
87                                 "found. Please check your NAND "
88                                 "configuration.\n");
89                         puts("Trying to start u-boot now...\n");
90                 }
91         }
92 #endif
93 #ifdef CONFIG_NAND_ENV_DST
94         spl_nand_load_element(CONFIG_ENV_OFFSET, header);
95 #ifdef CONFIG_ENV_OFFSET_REDUND
96         spl_nand_load_element(CONFIG_ENV_OFFSET_REDUND, header);
97 #endif
98 #endif
99         /* Load u-boot */
100         err = spl_nand_load_element(CONFIG_SYS_NAND_U_BOOT_OFFS, header);
101         nand_deselect();
102         return err;
103 }
104 #endif