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