xref: /openbmc/u-boot/common/spl/spl_nand.c (revision c7ba7bdc)
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
114