mirror of
https://github.com/AsahiLinux/u-boot
synced 2024-11-28 15:41:40 +00:00
105 lines
2.6 KiB
C
105 lines
2.6 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 dm_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;
|
||
|
}
|
||
|
|
||
|
#define DM_NAND_TEST(dev) \
|
||
|
static int dm_test_nand##dev##_start(struct unit_test_state *uts) \
|
||
|
{ \
|
||
|
return dm_test_nand(uts, dev, false); \
|
||
|
} \
|
||
|
DM_TEST(dm_test_nand##dev##_start, UT_TESTF_SCAN_FDT); \
|
||
|
static int dm_test_nand##dev##_end(struct unit_test_state *uts) \
|
||
|
{ \
|
||
|
return dm_test_nand(uts, dev, true); \
|
||
|
} \
|
||
|
DM_TEST(dm_test_nand##dev##_end, UT_TESTF_SCAN_FDT)
|
||
|
|
||
|
DM_NAND_TEST(0);
|
||
|
DM_NAND_TEST(1);
|