mirror of
https://github.com/u-boot/u-boot.git
synced 2025-04-16 09:54:35 +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>
121 lines
2.8 KiB
C
121 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);
|