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