mirror of
				https://github.com/smaeul/u-boot.git
				synced 2025-11-03 21:48:15 +00:00 
			
		
		
		
	Write out the tests in full to allow the test to be found more easily when there is a failure. We could use a single test function with a for() loop but this would stop at the first failure, and some variations might while other pass. Signed-off-by: Simon Glass <sjg@chromium.org>
		
			
				
	
	
		
			122 lines
		
	
	
		
			2.8 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			122 lines
		
	
	
		
			2.8 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
// SPDX-License-Identifier: GPL-2.0+
 | 
						|
/*
 | 
						|
 * Copyright (C) 2023 Sean Anderson <seanga2@gmail.com>
 | 
						|
 */
 | 
						|
 | 
						|
#include <nand.h>
 | 
						|
#include <part.h>
 | 
						|
#include <rand.h>
 | 
						|
#include <dm/test.h>
 | 
						|
#include <test/test.h>
 | 
						|
#include <test/ut.h>
 | 
						|
#include <linux/mtd/mtd.h>
 | 
						|
#include <linux/mtd/rawnand.h>
 | 
						|
 | 
						|
static int run_test_nand(struct unit_test_state *uts, int dev, bool end)
 | 
						|
{
 | 
						|
	nand_erase_options_t opts = { };
 | 
						|
	struct mtd_info *mtd;
 | 
						|
	size_t length;
 | 
						|
	loff_t size;
 | 
						|
	char *buf;
 | 
						|
	int *gold;
 | 
						|
	u8 oob[NAND_MAX_OOBSIZE];
 | 
						|
	int i;
 | 
						|
	loff_t off = 0;
 | 
						|
	mtd_oob_ops_t ops = { };
 | 
						|
 | 
						|
	/* Seed RNG for bit errors */
 | 
						|
	srand((off >> 32) ^ off ^ ~dev);
 | 
						|
 | 
						|
	mtd = get_nand_dev_by_index(dev);
 | 
						|
	ut_assertnonnull(mtd);
 | 
						|
	size = mtd->erasesize * 4;
 | 
						|
	length = size;
 | 
						|
 | 
						|
	buf = malloc(size);
 | 
						|
	ut_assertnonnull(buf);
 | 
						|
	gold = malloc(size);
 | 
						|
	ut_assertnonnull(gold);
 | 
						|
 | 
						|
	/* Mark a block as bad */
 | 
						|
	ut_assertok(mtd_block_markbad(mtd, off + mtd->erasesize));
 | 
						|
 | 
						|
	/* Erase some stuff */
 | 
						|
	if (end)
 | 
						|
		off = mtd->size - size - mtd->erasesize;
 | 
						|
	opts.offset = off;
 | 
						|
	opts.length = size;
 | 
						|
	opts.spread = 1;
 | 
						|
	opts.lim = U32_MAX;
 | 
						|
	ut_assertok(nand_erase_opts(mtd, &opts));
 | 
						|
 | 
						|
	/* Make sure everything is erased */
 | 
						|
	memset(gold, 0xff, size);
 | 
						|
	ut_assertok(nand_read_skip_bad(mtd, off, &length, NULL, U64_MAX, buf));
 | 
						|
	ut_asserteq(size, length);
 | 
						|
	ut_asserteq_mem(gold, buf, size);
 | 
						|
 | 
						|
	/* ...but our bad block marker is still there */
 | 
						|
	ops.oobbuf = oob;
 | 
						|
	ops.ooblen = mtd->oobsize;
 | 
						|
	ut_assertok(mtd_read_oob(mtd, mtd->erasesize, &ops));
 | 
						|
	ut_asserteq(0, oob[mtd_to_nand(mtd)->badblockpos]);
 | 
						|
 | 
						|
	/* Generate some data and write it */
 | 
						|
	for (i = 0; i < size / sizeof(int); i++)
 | 
						|
		gold[i] = rand();
 | 
						|
	ut_assertok(nand_write_skip_bad(mtd, off, &length, NULL, U64_MAX,
 | 
						|
					(void *)gold, 0));
 | 
						|
	ut_asserteq(size, length);
 | 
						|
 | 
						|
	/* Verify */
 | 
						|
	ut_assertok(nand_read_skip_bad(mtd, off, &length, NULL, U64_MAX, buf));
 | 
						|
	ut_asserteq(size, length);
 | 
						|
	ut_asserteq_mem(gold, buf, size);
 | 
						|
 | 
						|
	/* Erase some blocks */
 | 
						|
	memset(((char *)gold) + mtd->erasesize, 0xff, mtd->erasesize * 2);
 | 
						|
	opts.offset = off + mtd->erasesize;
 | 
						|
	opts.length = mtd->erasesize * 2;
 | 
						|
	ut_assertok(nand_erase_opts(mtd, &opts));
 | 
						|
 | 
						|
	/* Verify */
 | 
						|
	ut_assertok(nand_read_skip_bad(mtd, off, &length, NULL, U64_MAX, buf));
 | 
						|
	ut_asserteq(size, length);
 | 
						|
	ut_asserteq_mem(gold, buf, size);
 | 
						|
 | 
						|
	return 0;
 | 
						|
}
 | 
						|
 | 
						|
static int dm_test_nand0_start(struct unit_test_state *uts)
 | 
						|
{
 | 
						|
	ut_assertok(run_test_nand(uts, 0, false));
 | 
						|
 | 
						|
	return 0;
 | 
						|
}
 | 
						|
DM_TEST(dm_test_nand0_start, UTF_SCAN_FDT);
 | 
						|
 | 
						|
static int dm_test_nand1_start(struct unit_test_state *uts)
 | 
						|
{
 | 
						|
	ut_assertok(run_test_nand(uts, 1, false));
 | 
						|
 | 
						|
	return 0;
 | 
						|
}
 | 
						|
DM_TEST(dm_test_nand1_start, UTF_SCAN_FDT);
 | 
						|
 | 
						|
static int dm_test_nand0_end(struct unit_test_state *uts)
 | 
						|
{
 | 
						|
	ut_assertok(run_test_nand(uts, 0, true));
 | 
						|
 | 
						|
	return 0;
 | 
						|
}
 | 
						|
DM_TEST(dm_test_nand0_end, UTF_SCAN_FDT);
 | 
						|
 | 
						|
static int dm_test_nand1_end(struct unit_test_state *uts)
 | 
						|
{
 | 
						|
	ut_assertok(run_test_nand(uts, 1, true));
 | 
						|
 | 
						|
	return 0;
 | 
						|
}
 | 
						|
DM_TEST(dm_test_nand1_end, UTF_SCAN_FDT);
 |