blob: e81279aa1b981bc5920cd46d4b8de90f4f8d3e22 [file] [log] [blame]
Tom Rini10e47792018-05-06 17:58:06 -04001// SPDX-License-Identifier: GPL-2.0+
Simon Schwarze21d2d82011-09-14 15:33:34 -04002/*
3 * Copyright (C) 2011
4 * Corscience GmbH & Co. KG - Simon Schwarz <schwarz@corscience.de>
Simon Schwarze21d2d82011-09-14 15:33:34 -04005 */
6#include <common.h>
Tom Rini9ef51bd2012-08-14 14:33:02 -07007#include <config.h>
Simon Glass2dc9c342020-05-10 11:40:01 -06008#include <fdt_support.h>
9#include <image.h>
Tom Rini28591df2012-08-13 12:03:19 -070010#include <spl.h>
Simon Schwarz6c3ddde2012-03-15 04:01:36 +000011#include <asm/io.h>
Simon Schwarze21d2d82011-09-14 15:33:34 -040012#include <nand.h>
Masahiro Yamada75f82d02018-03-05 01:20:11 +090013#include <linux/libfdt_env.h>
Lokesh Vutla12c49222016-05-24 10:34:42 +053014#include <fdt.h>
Simon Schwarze21d2d82011-09-14 15:33:34 -040015
Peng Fan59a62732019-09-23 10:18:43 +080016uint32_t __weak spl_nand_get_uboot_raw_page(void)
17{
18 return CONFIG_SYS_NAND_U_BOOT_OFFS;
19}
20
Heiko Schochercf000272014-10-31 08:31:00 +010021#if defined(CONFIG_SPL_NAND_RAW_ONLY)
Michael Trimarchi93e88022018-07-04 15:53:37 +020022static int spl_nand_load_image(struct spl_image_info *spl_image,
Simon Glassee306792016-09-24 18:20:13 -060023 struct spl_boot_device *bootdev)
Simon Schwarze21d2d82011-09-14 15:33:34 -040024{
Heiko Schochercf000272014-10-31 08:31:00 +010025 nand_init();
26
Stefan Roese438b6cd2019-03-26 13:04:00 +010027 printf("Loading U-Boot from 0x%08x (size 0x%08x) to 0x%08x\n",
28 CONFIG_SYS_NAND_U_BOOT_OFFS, CONFIG_SYS_NAND_U_BOOT_SIZE,
29 CONFIG_SYS_NAND_U_BOOT_DST);
30
Peng Fan59a62732019-09-23 10:18:43 +080031 nand_spl_load_image(spl_nand_get_uboot_raw_page(),
Heiko Schochercf000272014-10-31 08:31:00 +010032 CONFIG_SYS_NAND_U_BOOT_SIZE,
33 (void *)CONFIG_SYS_NAND_U_BOOT_DST);
Simon Glassee306792016-09-24 18:20:13 -060034 spl_set_header_raw_uboot(spl_image);
Heiko Schochercf000272014-10-31 08:31:00 +010035 nand_deselect();
Nikita Kiryanov33eefe42015-11-08 17:11:49 +020036
37 return 0;
Heiko Schochercf000272014-10-31 08:31:00 +010038}
39#else
Lokesh Vutla12c49222016-05-24 10:34:42 +053040
41static ulong spl_nand_fit_read(struct spl_load_info *load, ulong offs,
42 ulong size, void *dst)
43{
44 int ret;
45
46 ret = nand_spl_load_image(offs, size, dst);
47 if (!ret)
48 return size;
49 else
50 return 0;
51}
52
Simon Glassee306792016-09-24 18:20:13 -060053static int spl_nand_load_element(struct spl_image_info *spl_image,
54 int offset, struct image_header *header)
Nikita Kiryanov08fb32e62015-11-08 17:11:42 +020055{
56 int err;
57
58 err = nand_spl_load_image(offset, sizeof(*header), (void *)header);
59 if (err)
60 return err;
61
Lokesh Vutla12c49222016-05-24 10:34:42 +053062 if (IS_ENABLED(CONFIG_SPL_LOAD_FIT) &&
63 image_get_magic(header) == FDT_MAGIC) {
64 struct spl_load_info load;
Marek Vasut02266e22016-04-29 00:44:54 +020065
Lokesh Vutla12c49222016-05-24 10:34:42 +053066 debug("Found FIT\n");
67 load.dev = NULL;
68 load.priv = NULL;
69 load.filename = NULL;
70 load.bl_len = 1;
71 load.read = spl_nand_fit_read;
Simon Glass43a734f2016-09-24 18:20:16 -060072 return spl_load_simple_fit(spl_image, &load, offset, header);
Peng Fan519ce8d2019-09-23 10:18:46 +080073 } else if (IS_ENABLED(CONFIG_SPL_LOAD_IMX_CONTAINER)) {
74 struct spl_load_info load;
75
76 load.dev = NULL;
77 load.priv = NULL;
78 load.filename = NULL;
79 load.bl_len = 1;
80 load.read = spl_nand_fit_read;
81 return spl_load_imx_container(spl_image, &load, offset);
Lokesh Vutla12c49222016-05-24 10:34:42 +053082 } else {
Simon Glassee306792016-09-24 18:20:13 -060083 err = spl_parse_image_header(spl_image, header);
Lokesh Vutla12c49222016-05-24 10:34:42 +053084 if (err)
85 return err;
Simon Glassee306792016-09-24 18:20:13 -060086 return nand_spl_load_image(offset, spl_image->size,
87 (void *)(ulong)spl_image->load_addr);
Lokesh Vutla12c49222016-05-24 10:34:42 +053088 }
Nikita Kiryanov08fb32e62015-11-08 17:11:42 +020089}
90
Simon Glassee306792016-09-24 18:20:13 -060091static int spl_nand_load_image(struct spl_image_info *spl_image,
92 struct spl_boot_device *bootdev)
Heiko Schochercf000272014-10-31 08:31:00 +010093{
Nikita Kiryanov33eefe42015-11-08 17:11:49 +020094 int err;
Simon Schwarze21d2d82011-09-14 15:33:34 -040095 struct image_header *header;
Simon Schwarz6c3ddde2012-03-15 04:01:36 +000096 int *src __attribute__((unused));
97 int *dst __attribute__((unused));
98
Ahmed Samir Khalilb976eb22016-03-25 13:13:17 +010099#ifdef CONFIG_SPL_NAND_SOFTECC
100 debug("spl: nand - using sw ecc\n");
101#else
Tom Rini09ebf1a2012-08-13 14:11:06 -0700102 debug("spl: nand - using hw ecc\n");
Ahmed Samir Khalilb976eb22016-03-25 13:13:17 +0100103#endif
Tom Rini09ebf1a2012-08-13 14:11:06 -0700104 nand_init();
Simon Schwarze21d2d82011-09-14 15:33:34 -0400105
Marek Vasut1dda46f2018-08-14 11:27:02 +0200106 header = spl_get_load_buffer(0, sizeof(*header));
107
Simon Schwarz6c3ddde2012-03-15 04:01:36 +0000108#ifdef CONFIG_SPL_OS_BOOT
Simon Schwarz305bc4c2012-03-15 04:01:38 +0000109 if (!spl_start_uboot()) {
Simon Schwarz6c3ddde2012-03-15 04:01:36 +0000110 /*
111 * load parameter image
112 * load to temp position since nand_spl_load_image reads
113 * a whole block which is typically larger than
Marek Vasut6d016762012-03-31 07:47:17 +0000114 * CONFIG_CMD_SPL_WRITE_SIZE therefore may overwrite
Simon Schwarz6c3ddde2012-03-15 04:01:36 +0000115 * following sections like BSS
116 */
117 nand_spl_load_image(CONFIG_CMD_SPL_NAND_OFS,
118 CONFIG_CMD_SPL_WRITE_SIZE,
119 (void *)CONFIG_SYS_TEXT_BASE);
120 /* copy to destintion */
121 for (dst = (int *)CONFIG_SYS_SPL_ARGS_ADDR,
122 src = (int *)CONFIG_SYS_TEXT_BASE;
123 src < (int *)(CONFIG_SYS_TEXT_BASE +
124 CONFIG_CMD_SPL_WRITE_SIZE);
125 src++, dst++) {
126 writel(readl(src), dst);
127 }
Simon Schwarze21d2d82011-09-14 15:33:34 -0400128
Simon Schwarz6c3ddde2012-03-15 04:01:36 +0000129 /* load linux */
130 nand_spl_load_image(CONFIG_SYS_NAND_SPL_KERNEL_OFFS,
Masahiro Yamadaeac6cd62014-07-10 20:43:16 +0900131 sizeof(*header), (void *)header);
Simon Glassee306792016-09-24 18:20:13 -0600132 err = spl_parse_image_header(spl_image, header);
Marek Vasut02266e22016-04-29 00:44:54 +0200133 if (err)
134 return err;
Simon Schwarz305bc4c2012-03-15 04:01:38 +0000135 if (header->ih_os == IH_OS_LINUX) {
136 /* happy - was a linux */
Nikita Kiryanov33eefe42015-11-08 17:11:49 +0200137 err = nand_spl_load_image(
138 CONFIG_SYS_NAND_SPL_KERNEL_OFFS,
Simon Glassee306792016-09-24 18:20:13 -0600139 spl_image->size,
140 (void *)spl_image->load_addr);
Simon Schwarz305bc4c2012-03-15 04:01:38 +0000141 nand_deselect();
Nikita Kiryanov33eefe42015-11-08 17:11:49 +0200142 return err;
Simon Schwarz305bc4c2012-03-15 04:01:38 +0000143 } else {
Tom Rini9ef51bd2012-08-14 14:33:02 -0700144 puts("The Expected Linux image was not "
145 "found. Please check your NAND "
Simon Schwarz305bc4c2012-03-15 04:01:38 +0000146 "configuration.\n");
Tom Rini9ef51bd2012-08-14 14:33:02 -0700147 puts("Trying to start u-boot now...\n");
Simon Schwarz305bc4c2012-03-15 04:01:38 +0000148 }
149 }
Simon Schwarz6c3ddde2012-03-15 04:01:36 +0000150#endif
Simon Schwarze21d2d82011-09-14 15:33:34 -0400151#ifdef CONFIG_NAND_ENV_DST
Simon Glassee306792016-09-24 18:20:13 -0600152 spl_nand_load_element(spl_image, CONFIG_ENV_OFFSET, header);
Simon Schwarze21d2d82011-09-14 15:33:34 -0400153#ifdef CONFIG_ENV_OFFSET_REDUND
Simon Glassee306792016-09-24 18:20:13 -0600154 spl_nand_load_element(spl_image, CONFIG_ENV_OFFSET_REDUND, header);
Simon Schwarze21d2d82011-09-14 15:33:34 -0400155#endif
156#endif
Simon Schwarz305bc4c2012-03-15 04:01:38 +0000157 /* Load u-boot */
Peng Fan59a62732019-09-23 10:18:43 +0800158 err = spl_nand_load_element(spl_image, spl_nand_get_uboot_raw_page(),
Simon Glassee306792016-09-24 18:20:13 -0600159 header);
Boris Brezillon4f238e72016-06-06 10:16:58 +0200160#ifdef CONFIG_SYS_NAND_U_BOOT_OFFS_REDUND
161#if CONFIG_SYS_NAND_U_BOOT_OFFS != CONFIG_SYS_NAND_U_BOOT_OFFS_REDUND
162 if (err)
Simon Glassee306792016-09-24 18:20:13 -0600163 err = spl_nand_load_element(spl_image,
164 CONFIG_SYS_NAND_U_BOOT_OFFS_REDUND,
Boris Brezillon4f238e72016-06-06 10:16:58 +0200165 header);
166#endif
167#endif
Simon Schwarze21d2d82011-09-14 15:33:34 -0400168 nand_deselect();
Nikita Kiryanov33eefe42015-11-08 17:11:49 +0200169 return err;
Simon Schwarze21d2d82011-09-14 15:33:34 -0400170}
Heiko Schochercf000272014-10-31 08:31:00 +0100171#endif
Simon Glass6cf82c92016-09-24 18:20:02 -0600172/* Use priorty 1 so that Ubi can override this */
Simon Glass4fc1f252016-11-30 15:30:50 -0700173SPL_LOAD_IMAGE_METHOD("NAND", 1, BOOT_DEVICE_NAND, spl_nand_load_image);