17126bd8be4ee009c56c4ec037f07f2c0884413fcAkinobu Mita#include <linux/kernel.h>
27126bd8be4ee009c56c4ec037f07f2c0884413fcAkinobu Mita#include <linux/module.h>
37126bd8be4ee009c56c4ec037f07f2c0884413fcAkinobu Mita#include <linux/list.h>
47126bd8be4ee009c56c4ec037f07f2c0884413fcAkinobu Mita#include <linux/random.h>
57126bd8be4ee009c56c4ec037f07f2c0884413fcAkinobu Mita#include <linux/string.h>
67126bd8be4ee009c56c4ec037f07f2c0884413fcAkinobu Mita#include <linux/bitops.h>
77126bd8be4ee009c56c4ec037f07f2c0884413fcAkinobu Mita#include <linux/jiffies.h>
87126bd8be4ee009c56c4ec037f07f2c0884413fcAkinobu Mita#include <linux/mtd/nand_ecc.h>
97126bd8be4ee009c56c4ec037f07f2c0884413fcAkinobu Mita
107126bd8be4ee009c56c4ec037f07f2c0884413fcAkinobu Mita#if defined(CONFIG_MTD_NAND) || defined(CONFIG_MTD_NAND_MODULE)
117126bd8be4ee009c56c4ec037f07f2c0884413fcAkinobu Mita
127126bd8be4ee009c56c4ec037f07f2c0884413fcAkinobu Mitastatic void inject_single_bit_error(void *data, size_t size)
137126bd8be4ee009c56c4ec037f07f2c0884413fcAkinobu Mita{
147126bd8be4ee009c56c4ec037f07f2c0884413fcAkinobu Mita	unsigned long offset = random32() % (size * BITS_PER_BYTE);
157126bd8be4ee009c56c4ec037f07f2c0884413fcAkinobu Mita
167126bd8be4ee009c56c4ec037f07f2c0884413fcAkinobu Mita	__change_bit(offset, data);
177126bd8be4ee009c56c4ec037f07f2c0884413fcAkinobu Mita}
187126bd8be4ee009c56c4ec037f07f2c0884413fcAkinobu Mita
197126bd8be4ee009c56c4ec037f07f2c0884413fcAkinobu Mitastatic unsigned char data[512];
207126bd8be4ee009c56c4ec037f07f2c0884413fcAkinobu Mitastatic unsigned char error_data[512];
217126bd8be4ee009c56c4ec037f07f2c0884413fcAkinobu Mita
227126bd8be4ee009c56c4ec037f07f2c0884413fcAkinobu Mitastatic int nand_ecc_test(const size_t size)
237126bd8be4ee009c56c4ec037f07f2c0884413fcAkinobu Mita{
247126bd8be4ee009c56c4ec037f07f2c0884413fcAkinobu Mita	unsigned char code[3];
257126bd8be4ee009c56c4ec037f07f2c0884413fcAkinobu Mita	unsigned char error_code[3];
267126bd8be4ee009c56c4ec037f07f2c0884413fcAkinobu Mita	char testname[30];
277126bd8be4ee009c56c4ec037f07f2c0884413fcAkinobu Mita
287126bd8be4ee009c56c4ec037f07f2c0884413fcAkinobu Mita	BUG_ON(sizeof(data) < size);
297126bd8be4ee009c56c4ec037f07f2c0884413fcAkinobu Mita
307126bd8be4ee009c56c4ec037f07f2c0884413fcAkinobu Mita	sprintf(testname, "nand-ecc-%zu", size);
317126bd8be4ee009c56c4ec037f07f2c0884413fcAkinobu Mita
327126bd8be4ee009c56c4ec037f07f2c0884413fcAkinobu Mita	get_random_bytes(data, size);
337126bd8be4ee009c56c4ec037f07f2c0884413fcAkinobu Mita
347126bd8be4ee009c56c4ec037f07f2c0884413fcAkinobu Mita	memcpy(error_data, data, size);
357126bd8be4ee009c56c4ec037f07f2c0884413fcAkinobu Mita	inject_single_bit_error(error_data, size);
367126bd8be4ee009c56c4ec037f07f2c0884413fcAkinobu Mita
377126bd8be4ee009c56c4ec037f07f2c0884413fcAkinobu Mita	__nand_calculate_ecc(data, size, code);
387126bd8be4ee009c56c4ec037f07f2c0884413fcAkinobu Mita	__nand_calculate_ecc(error_data, size, error_code);
397126bd8be4ee009c56c4ec037f07f2c0884413fcAkinobu Mita	__nand_correct_data(error_data, code, error_code, size);
407126bd8be4ee009c56c4ec037f07f2c0884413fcAkinobu Mita
417126bd8be4ee009c56c4ec037f07f2c0884413fcAkinobu Mita	if (!memcmp(data, error_data, size)) {
427126bd8be4ee009c56c4ec037f07f2c0884413fcAkinobu Mita		printk(KERN_INFO "mtd_nandecctest: ok - %s\n", testname);
437126bd8be4ee009c56c4ec037f07f2c0884413fcAkinobu Mita		return 0;
447126bd8be4ee009c56c4ec037f07f2c0884413fcAkinobu Mita	}
457126bd8be4ee009c56c4ec037f07f2c0884413fcAkinobu Mita
467126bd8be4ee009c56c4ec037f07f2c0884413fcAkinobu Mita	printk(KERN_ERR "mtd_nandecctest: not ok - %s\n", testname);
477126bd8be4ee009c56c4ec037f07f2c0884413fcAkinobu Mita
487126bd8be4ee009c56c4ec037f07f2c0884413fcAkinobu Mita	printk(KERN_DEBUG "hexdump of data:\n");
497126bd8be4ee009c56c4ec037f07f2c0884413fcAkinobu Mita	print_hex_dump(KERN_DEBUG, "", DUMP_PREFIX_OFFSET, 16, 4,
507126bd8be4ee009c56c4ec037f07f2c0884413fcAkinobu Mita			data, size, false);
517126bd8be4ee009c56c4ec037f07f2c0884413fcAkinobu Mita	printk(KERN_DEBUG "hexdump of error data:\n");
527126bd8be4ee009c56c4ec037f07f2c0884413fcAkinobu Mita	print_hex_dump(KERN_DEBUG, "", DUMP_PREFIX_OFFSET, 16, 4,
537126bd8be4ee009c56c4ec037f07f2c0884413fcAkinobu Mita			error_data, size, false);
547126bd8be4ee009c56c4ec037f07f2c0884413fcAkinobu Mita
557126bd8be4ee009c56c4ec037f07f2c0884413fcAkinobu Mita	return -1;
567126bd8be4ee009c56c4ec037f07f2c0884413fcAkinobu Mita}
577126bd8be4ee009c56c4ec037f07f2c0884413fcAkinobu Mita
587126bd8be4ee009c56c4ec037f07f2c0884413fcAkinobu Mita#else
597126bd8be4ee009c56c4ec037f07f2c0884413fcAkinobu Mita
607126bd8be4ee009c56c4ec037f07f2c0884413fcAkinobu Mitastatic int nand_ecc_test(const size_t size)
617126bd8be4ee009c56c4ec037f07f2c0884413fcAkinobu Mita{
627126bd8be4ee009c56c4ec037f07f2c0884413fcAkinobu Mita	return 0;
637126bd8be4ee009c56c4ec037f07f2c0884413fcAkinobu Mita}
647126bd8be4ee009c56c4ec037f07f2c0884413fcAkinobu Mita
657126bd8be4ee009c56c4ec037f07f2c0884413fcAkinobu Mita#endif
667126bd8be4ee009c56c4ec037f07f2c0884413fcAkinobu Mita
677126bd8be4ee009c56c4ec037f07f2c0884413fcAkinobu Mitastatic int __init ecc_test_init(void)
687126bd8be4ee009c56c4ec037f07f2c0884413fcAkinobu Mita{
697126bd8be4ee009c56c4ec037f07f2c0884413fcAkinobu Mita	srandom32(jiffies);
707126bd8be4ee009c56c4ec037f07f2c0884413fcAkinobu Mita
717126bd8be4ee009c56c4ec037f07f2c0884413fcAkinobu Mita	nand_ecc_test(256);
727126bd8be4ee009c56c4ec037f07f2c0884413fcAkinobu Mita	nand_ecc_test(512);
737126bd8be4ee009c56c4ec037f07f2c0884413fcAkinobu Mita
747126bd8be4ee009c56c4ec037f07f2c0884413fcAkinobu Mita	return 0;
757126bd8be4ee009c56c4ec037f07f2c0884413fcAkinobu Mita}
767126bd8be4ee009c56c4ec037f07f2c0884413fcAkinobu Mita
777126bd8be4ee009c56c4ec037f07f2c0884413fcAkinobu Mitastatic void __exit ecc_test_exit(void)
787126bd8be4ee009c56c4ec037f07f2c0884413fcAkinobu Mita{
797126bd8be4ee009c56c4ec037f07f2c0884413fcAkinobu Mita}
807126bd8be4ee009c56c4ec037f07f2c0884413fcAkinobu Mita
817126bd8be4ee009c56c4ec037f07f2c0884413fcAkinobu Mitamodule_init(ecc_test_init);
827126bd8be4ee009c56c4ec037f07f2c0884413fcAkinobu Mitamodule_exit(ecc_test_exit);
837126bd8be4ee009c56c4ec037f07f2c0884413fcAkinobu Mita
847126bd8be4ee009c56c4ec037f07f2c0884413fcAkinobu MitaMODULE_DESCRIPTION("NAND ECC function test module");
857126bd8be4ee009c56c4ec037f07f2c0884413fcAkinobu MitaMODULE_AUTHOR("Akinobu Mita");
867126bd8be4ee009c56c4ec037f07f2c0884413fcAkinobu MitaMODULE_LICENSE("GPL");
87