xref: /rk3399_rockchip-uboot/common/spl/spl_nand.c (revision d5c2b11ce40f8ca849008938515e742e6b7efc18)
1d97b4ce8STom Rini /*
2d97b4ce8STom Rini  * Copyright (C) 2011
3d97b4ce8STom Rini  * Corscience GmbH & Co. KG - Simon Schwarz <schwarz@corscience.de>
4d97b4ce8STom Rini  *
51a459660SWolfgang Denk  * SPDX-License-Identifier:	GPL-2.0+
6d97b4ce8STom Rini  */
7d97b4ce8STom Rini #include <common.h>
8d97b4ce8STom Rini #include <config.h>
9d97b4ce8STom Rini #include <spl.h>
10d97b4ce8STom Rini #include <asm/io.h>
11d97b4ce8STom Rini #include <nand.h>
128bd88772SLokesh Vutla #include <libfdt_env.h>
138bd88772SLokesh Vutla #include <fdt.h>
14d97b4ce8STom Rini 
150c3117b1SHeiko Schocher #if defined(CONFIG_SPL_NAND_RAW_ONLY)
16ecdfd69aSSimon Glass int spl_nand_load_image(struct spl_boot_device *bootdev)
170c3117b1SHeiko Schocher {
180c3117b1SHeiko Schocher 	nand_init();
190c3117b1SHeiko Schocher 
200c3117b1SHeiko Schocher 	nand_spl_load_image(CONFIG_SYS_NAND_U_BOOT_OFFS,
210c3117b1SHeiko Schocher 			    CONFIG_SYS_NAND_U_BOOT_SIZE,
220c3117b1SHeiko Schocher 			    (void *)CONFIG_SYS_NAND_U_BOOT_DST);
23d95ceb97SSimon Glass 	spl_set_header_raw_uboot(&spl_image);
240c3117b1SHeiko Schocher 	nand_deselect();
2536afd451SNikita Kiryanov 
2636afd451SNikita Kiryanov 	return 0;
270c3117b1SHeiko Schocher }
280c3117b1SHeiko Schocher #else
298bd88772SLokesh Vutla 
308bd88772SLokesh Vutla static ulong spl_nand_fit_read(struct spl_load_info *load, ulong offs,
318bd88772SLokesh Vutla 			       ulong size, void *dst)
328bd88772SLokesh Vutla {
338bd88772SLokesh Vutla 	int ret;
348bd88772SLokesh Vutla 
358bd88772SLokesh Vutla 	ret = nand_spl_load_image(offs, size, dst);
368bd88772SLokesh Vutla 	if (!ret)
378bd88772SLokesh Vutla 		return size;
388bd88772SLokesh Vutla 	else
398bd88772SLokesh Vutla 		return 0;
408bd88772SLokesh Vutla }
418bd88772SLokesh Vutla 
42483ab3dcSNikita Kiryanov static int spl_nand_load_element(int offset, struct image_header *header)
43483ab3dcSNikita Kiryanov {
44483ab3dcSNikita Kiryanov 	int err;
45483ab3dcSNikita Kiryanov 
46483ab3dcSNikita Kiryanov 	err = nand_spl_load_image(offset, sizeof(*header), (void *)header);
47483ab3dcSNikita Kiryanov 	if (err)
48483ab3dcSNikita Kiryanov 		return err;
49483ab3dcSNikita Kiryanov 
508bd88772SLokesh Vutla 	if (IS_ENABLED(CONFIG_SPL_LOAD_FIT) &&
518bd88772SLokesh Vutla 	    image_get_magic(header) == FDT_MAGIC) {
528bd88772SLokesh Vutla 		struct spl_load_info load;
538bd88772SLokesh Vutla 
548bd88772SLokesh Vutla 		debug("Found FIT\n");
558bd88772SLokesh Vutla 		load.dev = NULL;
568bd88772SLokesh Vutla 		load.priv = NULL;
578bd88772SLokesh Vutla 		load.filename = NULL;
588bd88772SLokesh Vutla 		load.bl_len = 1;
598bd88772SLokesh Vutla 		load.read = spl_nand_fit_read;
608bd88772SLokesh Vutla 		return spl_load_simple_fit(&load, offset, header);
618bd88772SLokesh Vutla 	} else {
6271316c1dSSimon Glass 		err = spl_parse_image_header(&spl_image, header);
637e0f2267SMarek Vasut 		if (err)
647e0f2267SMarek Vasut 			return err;
65483ab3dcSNikita Kiryanov 		return nand_spl_load_image(offset, spl_image.size,
668bd88772SLokesh Vutla 					   (void *)(ulong)spl_image.load_addr);
678bd88772SLokesh Vutla 	}
68483ab3dcSNikita Kiryanov }
69483ab3dcSNikita Kiryanov 
70*d5c2b11cSSimon Glass static int spl_nand_load_image(struct spl_boot_device *bootdev)
71d97b4ce8STom Rini {
7236afd451SNikita Kiryanov 	int err;
73d97b4ce8STom Rini 	struct image_header *header;
74d97b4ce8STom Rini 	int *src __attribute__((unused));
75d97b4ce8STom Rini 	int *dst __attribute__((unused));
76d97b4ce8STom Rini 
778122d216SAhmed Samir Khalil #ifdef CONFIG_SPL_NAND_SOFTECC
788122d216SAhmed Samir Khalil 	debug("spl: nand - using sw ecc\n");
798122d216SAhmed Samir Khalil #else
80d97b4ce8STom Rini 	debug("spl: nand - using hw ecc\n");
818122d216SAhmed Samir Khalil #endif
82d97b4ce8STom Rini 	nand_init();
83d97b4ce8STom Rini 
84d97b4ce8STom Rini 	/*use CONFIG_SYS_TEXT_BASE as temporary storage area */
85d97b4ce8STom Rini 	header = (struct image_header *)(CONFIG_SYS_TEXT_BASE);
86d97b4ce8STom Rini #ifdef CONFIG_SPL_OS_BOOT
87d97b4ce8STom Rini 	if (!spl_start_uboot()) {
88d97b4ce8STom Rini 		/*
89d97b4ce8STom Rini 		 * load parameter image
90d97b4ce8STom Rini 		 * load to temp position since nand_spl_load_image reads
91d97b4ce8STom Rini 		 * a whole block which is typically larger than
92d97b4ce8STom Rini 		 * CONFIG_CMD_SPL_WRITE_SIZE therefore may overwrite
93d97b4ce8STom Rini 		 * following sections like BSS
94d97b4ce8STom Rini 		 */
95d97b4ce8STom Rini 		nand_spl_load_image(CONFIG_CMD_SPL_NAND_OFS,
96d97b4ce8STom Rini 			CONFIG_CMD_SPL_WRITE_SIZE,
97d97b4ce8STom Rini 			(void *)CONFIG_SYS_TEXT_BASE);
98d97b4ce8STom Rini 		/* copy to destintion */
99d97b4ce8STom Rini 		for (dst = (int *)CONFIG_SYS_SPL_ARGS_ADDR,
100d97b4ce8STom Rini 				src = (int *)CONFIG_SYS_TEXT_BASE;
101d97b4ce8STom Rini 				src < (int *)(CONFIG_SYS_TEXT_BASE +
102d97b4ce8STom Rini 				CONFIG_CMD_SPL_WRITE_SIZE);
103d97b4ce8STom Rini 				src++, dst++) {
104d97b4ce8STom Rini 			writel(readl(src), dst);
105d97b4ce8STom Rini 		}
106d97b4ce8STom Rini 
107d97b4ce8STom Rini 		/* load linux */
108d97b4ce8STom Rini 		nand_spl_load_image(CONFIG_SYS_NAND_SPL_KERNEL_OFFS,
109c13bb167SMasahiro Yamada 			sizeof(*header), (void *)header);
11071316c1dSSimon Glass 		err = spl_parse_image_header(&spl_image, header);
1117e0f2267SMarek Vasut 		if (err)
1127e0f2267SMarek Vasut 			return err;
113d97b4ce8STom Rini 		if (header->ih_os == IH_OS_LINUX) {
114d97b4ce8STom Rini 			/* happy - was a linux */
11536afd451SNikita Kiryanov 			err = nand_spl_load_image(
11636afd451SNikita Kiryanov 				CONFIG_SYS_NAND_SPL_KERNEL_OFFS,
11736afd451SNikita Kiryanov 				spl_image.size,
11836afd451SNikita Kiryanov 				(void *)spl_image.load_addr);
119d97b4ce8STom Rini 			nand_deselect();
12036afd451SNikita Kiryanov 			return err;
121d97b4ce8STom Rini 		} else {
122d97b4ce8STom Rini 			puts("The Expected Linux image was not "
123d97b4ce8STom Rini 				"found. Please check your NAND "
124d97b4ce8STom Rini 				"configuration.\n");
125d97b4ce8STom Rini 			puts("Trying to start u-boot now...\n");
126d97b4ce8STom Rini 		}
127d97b4ce8STom Rini 	}
128d97b4ce8STom Rini #endif
129d97b4ce8STom Rini #ifdef CONFIG_NAND_ENV_DST
130483ab3dcSNikita Kiryanov 	spl_nand_load_element(CONFIG_ENV_OFFSET, header);
131d97b4ce8STom Rini #ifdef CONFIG_ENV_OFFSET_REDUND
132483ab3dcSNikita Kiryanov 	spl_nand_load_element(CONFIG_ENV_OFFSET_REDUND, header);
133d97b4ce8STom Rini #endif
134d97b4ce8STom Rini #endif
135d97b4ce8STom Rini 	/* Load u-boot */
13636afd451SNikita Kiryanov 	err = spl_nand_load_element(CONFIG_SYS_NAND_U_BOOT_OFFS, header);
13780ef700fSBoris Brezillon #ifdef CONFIG_SYS_NAND_U_BOOT_OFFS_REDUND
13880ef700fSBoris Brezillon #if CONFIG_SYS_NAND_U_BOOT_OFFS != CONFIG_SYS_NAND_U_BOOT_OFFS_REDUND
13980ef700fSBoris Brezillon 	if (err)
14080ef700fSBoris Brezillon 		err = spl_nand_load_element(CONFIG_SYS_NAND_U_BOOT_OFFS_REDUND,
14180ef700fSBoris Brezillon 					    header);
14280ef700fSBoris Brezillon #endif
14380ef700fSBoris Brezillon #endif
144d97b4ce8STom Rini 	nand_deselect();
14536afd451SNikita Kiryanov 	return err;
146d97b4ce8STom Rini }
1470c3117b1SHeiko Schocher #endif
148*d5c2b11cSSimon Glass /* Use priorty 1 so that Ubi can override this */
149*d5c2b11cSSimon Glass SPL_LOAD_IMAGE_METHOD(1, BOOT_DEVICE_NAND, spl_nand_load_image);
150