test: spl: Add a test for NAND

Add a SPL test for the NAND load method. We use some different functions to
do the writing from the main test since things like nand_write_skip_bad
aren't available in SPL.

We disable BBT scanning, since scan_bbt is only populated when not in SPL.
We use nand_spl_loaders.c as it seems to be common to at least a few boards
already. However, we do not use nand_spl_simple.c because it would require
us to implement cmd_ctrl.  The various nand load functions are adapted from
omap_gpmc. However, they have been modified for simplicity/correctness.

Signed-off-by: Sean Anderson <seanga2@gmail.com>
This commit is contained in:
Sean Anderson
2023-11-04 16:37:53 -04:00
committed by Tom Rini
parent bc8e8a4bfa
commit 8502b5bf20
7 changed files with 109 additions and 1 deletions

View File

@@ -15,6 +15,7 @@ enum {
BOOT_DEVICE_CPGMAC, BOOT_DEVICE_CPGMAC,
BOOT_DEVICE_NOR, BOOT_DEVICE_NOR,
BOOT_DEVICE_SPI, BOOT_DEVICE_SPI,
BOOT_DEVICE_NAND,
}; };
/** /**

View File

@@ -51,6 +51,13 @@ CONFIG_SPL_ETH=y
CONFIG_SPL_FS_EXT4=y CONFIG_SPL_FS_EXT4=y
CONFIG_SPL_I2C=y CONFIG_SPL_I2C=y
CONFIG_SPL_MMC_WRITE=y CONFIG_SPL_MMC_WRITE=y
CONFIG_SPL_MTD=y
CONFIG_SPL_NAND_SUPPORT=y
CONFIG_SPL_NAND_DRIVERS=y
CONFIG_SPL_NAND_ECC=y
CONFIG_SPL_NAND_SOFTECC=y
CONFIG_SPL_NAND_BASE=y
CONFIG_SPL_NAND_IDENT=y
CONFIG_SPL_DM_SPI_FLASH=y CONFIG_SPL_DM_SPI_FLASH=y
CONFIG_SPL_NET=y CONFIG_SPL_NET=y
CONFIG_SPL_NOR_SUPPORT=y CONFIG_SPL_NOR_SUPPORT=y
@@ -183,12 +190,16 @@ CONFIG_FS_LOADER=y
CONFIG_MMC_SANDBOX=y CONFIG_MMC_SANDBOX=y
CONFIG_MTD=y CONFIG_MTD=y
CONFIG_DM_MTD=y CONFIG_DM_MTD=y
CONFIG_MTD_CONCAT=y
CONFIG_MTD_RAW_NAND=y CONFIG_MTD_RAW_NAND=y
CONFIG_SYS_MAX_NAND_DEVICE=8 CONFIG_SYS_MAX_NAND_DEVICE=8
CONFIG_SYS_NAND_USE_FLASH_BBT=y CONFIG_SYS_NAND_USE_FLASH_BBT=y
CONFIG_NAND_SANDBOX=y CONFIG_NAND_SANDBOX=y
CONFIG_SYS_NAND_BLOCK_SIZE=0x2000
CONFIG_SYS_NAND_ONFI_DETECTION=y CONFIG_SYS_NAND_ONFI_DETECTION=y
CONFIG_SYS_NAND_PAGE_SIZE=0x200 CONFIG_SYS_NAND_PAGE_SIZE=0x200
CONFIG_SYS_NAND_U_BOOT_LOCATIONS=y
CONFIG_SYS_NAND_U_BOOT_OFFS=0x0
CONFIG_SPI_FLASH_SANDBOX=y CONFIG_SPI_FLASH_SANDBOX=y
CONFIG_SPI_FLASH_ATMEL=y CONFIG_SPI_FLASH_ATMEL=y
CONFIG_SPI_FLASH_EON=y CONFIG_SPI_FLASH_EON=y

View File

@@ -451,6 +451,8 @@ config NAND_SANDBOX
bool "Support for NAND in sandbox" bool "Support for NAND in sandbox"
depends on SANDBOX depends on SANDBOX
select SYS_NAND_SELF_INIT select SYS_NAND_SELF_INIT
select SPL_SYS_NAND_SELF_INIT
select SPL_NAND_INIT
select SYS_NAND_SOFT_ECC select SYS_NAND_SOFT_ECC
select BCH select BCH
select NAND_ECC_BCH select NAND_ECC_BCH
@@ -678,7 +680,8 @@ config SYS_NAND_PAGE_SIZE
depends on ARCH_SUNXI || NAND_OMAP_GPMC || NAND_LPC32XX_SLC || \ depends on ARCH_SUNXI || NAND_OMAP_GPMC || NAND_LPC32XX_SLC || \
SPL_NAND_SIMPLE || (NAND_MXC && SPL_NAND_SUPPORT) || \ SPL_NAND_SIMPLE || (NAND_MXC && SPL_NAND_SUPPORT) || \
MVEBU_SPL_BOOT_DEVICE_NAND || \ MVEBU_SPL_BOOT_DEVICE_NAND || \
(NAND_ATMEL && SPL_NAND_SUPPORT) || SPL_GENERATE_ATMEL_PMECC_HEADER (NAND_ATMEL && SPL_NAND_SUPPORT) || \
SPL_GENERATE_ATMEL_PMECC_HEADER || NAND_SANDBOX
depends on !NAND_MXS && !NAND_DENALI_DT && !NAND_LPC32XX_MLC && !NAND_MT7621 depends on !NAND_MXS && !NAND_DENALI_DT && !NAND_LPC32XX_MLC && !NAND_MT7621
help help
Number of data bytes in one page for the NAND chip on the Number of data bytes in one page for the NAND chip on the

View File

@@ -10,6 +10,8 @@
#include <nand.h> #include <nand.h>
#include <os.h> #include <os.h>
#include <rand.h> #include <rand.h>
#include <spl.h>
#include <system-constants.h>
#include <dm/device_compat.h> #include <dm/device_compat.h>
#include <dm/read.h> #include <dm/read.h>
#include <dm/uclass.h> #include <dm/uclass.h>
@@ -599,6 +601,7 @@ static int sand_nand_probe(struct udevice *dev)
} }
nand = &chip->nand; nand = &chip->nand;
nand->options = spl_in_proper() ? 0 : NAND_SKIP_BBTSCAN;
nand->flash_node = np; nand->flash_node = np;
nand->dev_ready = sand_nand_dev_ready; nand->dev_ready = sand_nand_dev_ready;
nand->cmdfunc = sand_nand_command; nand->cmdfunc = sand_nand_command;
@@ -676,3 +679,29 @@ void board_nand_init(void)
if (err && err != -ENODEV) if (err && err != -ENODEV)
log_info("Failed to get sandbox NAND: %d\n", err); log_info("Failed to get sandbox NAND: %d\n", err);
} }
#if IS_ENABLED(CONFIG_SPL_BUILD) && IS_ENABLED(CONFIG_SPL_NAND_INIT)
void nand_deselect(void)
{
nand_chip->select_chip(nand_to_mtd(nand_chip), -1);
}
static int nand_is_bad_block(int block)
{
struct mtd_info *mtd = nand_to_mtd(nand_chip);
return mtd_block_isbad(mtd, block << mtd->erasesize_shift);
}
static int nand_read_page(int block, int page, uchar *dst)
{
struct mtd_info *mtd = nand_to_mtd(nand_chip);
loff_t ofs = ((loff_t)block << mtd->erasesize_shift) +
((loff_t)page << mtd->writesize_shift);
size_t len = mtd->writesize;
return nand_read(mtd, ofs, &len, dst);
}
#include "nand_spl_loaders.c"
#endif /* CONFIG_SPL_NAND_INIT */

View File

@@ -23,6 +23,15 @@ config SPL_UT_LOAD_FS
help help
Test filesystems and the various load methods which use them. Test filesystems and the various load methods which use them.
config SPL_UT_LOAD_NAND
bool "Test loading from NAND flash"
depends on SANDBOX && SPL_OF_REAL
depends on SPL_NAND_SUPPORT
depends on SPL_MTD
default y
help
Test the NAND flash load method.
config SPL_UT_LOAD_NET config SPL_UT_LOAD_NET
bool "Test loading over TFTP" bool "Test loading over TFTP"
depends on SANDBOX && SPL_OF_REAL depends on SANDBOX && SPL_OF_REAL

View File

@@ -4,6 +4,7 @@
obj-y += spl_load.o obj-y += spl_load.o
obj-$(CONFIG_SPL_UT_LOAD_FS) += spl_load_fs.o obj-$(CONFIG_SPL_UT_LOAD_FS) += spl_load_fs.o
obj-$(CONFIG_SPL_UT_LOAD_NAND) += spl_load_nand.o
obj-$(CONFIG_SPL_UT_LOAD_NET) += spl_load_net.o obj-$(CONFIG_SPL_UT_LOAD_NET) += spl_load_net.o
obj-$(CONFIG_SPL_NOR_SUPPORT) += spl_load_nor.o obj-$(CONFIG_SPL_NOR_SUPPORT) += spl_load_nor.o
obj-$(CONFIG_SPL_UT_LOAD_OS) += spl_load_os.o obj-$(CONFIG_SPL_UT_LOAD_OS) += spl_load_os.o

View File

@@ -0,0 +1,54 @@
// SPDX-License-Identifier: GPL-2.0+
/*
* Copyright (C) 2023 Sean Anderson <seanga2@gmail.com>
*/
#include <nand.h>
#include <spl.h>
#include <test/spl.h>
#include <test/ut.h>
uint32_t spl_nand_get_uboot_raw_page(void);
static int spl_test_nand_write_image(struct unit_test_state *uts, void *img,
size_t img_size)
{
uint32_t off = spl_nand_get_uboot_raw_page();
struct mtd_info *mtd;
struct erase_info erase = { };
size_t length;
nand_reinit();
mtd = get_nand_dev_by_index(0);
ut_assertnonnull(mtd);
/* Mark the first block as bad to test that it gets skipped */
ut_assertok(mtd_block_markbad(mtd, off & ~mtd->erasesize_mask));
off += mtd->erasesize;
erase.mtd = mtd;
erase.len = img_size + (off & mtd->erasesize_mask);
erase.len += mtd->erasesize_mask;
erase.len &= ~mtd->erasesize_mask;
erase.addr = off & ~mtd->erasesize_mask;
erase.scrub = 1;
ut_assertok(mtd_erase(mtd, &erase));
ut_assertok(mtd_write(mtd, off, img_size, &length, img));
return 0;
}
static int spl_test_nand(struct unit_test_state *uts, const char *test_name,
enum spl_test_image type)
{
return do_spl_test_load(uts, test_name, type,
SPL_LOAD_IMAGE_GET(1, BOOT_DEVICE_NAND,
spl_nand_load_image),
spl_test_nand_write_image);
}
SPL_IMG_TEST(spl_test_nand, LEGACY, DM_FLAGS);
SPL_IMG_TEST(spl_test_nand, LEGACY_LZMA, DM_FLAGS);
SPL_IMG_TEST(spl_test_nand, IMX8, DM_FLAGS);
SPL_IMG_TEST(spl_test_nand, FIT_INTERNAL, DM_FLAGS);
SPL_IMG_TEST(spl_test_nand, FIT_EXTERNAL, DM_FLAGS);