// SPDX-License-Identifier: GPL-2.0-or-later /* * This file contains an ECC algorithm that detects and corrects 1 bit * errors in a 256 byte block of data. * * Copyright © 2008 Koninklijke Philips Electronics NV. * Author: Frans Meulenbroeks * * Completely replaces the previous ECC implementation which was written by: * Steven J. Hill ([email protected]) * Thomas Gleixner ([email protected]) * * Information on how this algorithm works and how it was developed * can be found in Documentation/driver-api/mtd/nand_ecc.rst */ #include <linux/types.h> #include <linux/kernel.h> #include <linux/module.h> #include <linux/mtd/nand.h> #include <linux/mtd/nand-ecc-sw-hamming.h> #include <linux/slab.h> #include <asm/byteorder.h> /* * invparity is a 256 byte table that contains the odd parity * for each byte. So if the number of bits in a byte is even, * the array element is 1, and when the number of bits is odd * the array eleemnt is 0. */ static const char invparity[256] = …; /* * bitsperbyte contains the number of bits per byte * this is only used for testing and repairing parity * (a precalculated value slightly improves performance) */ static const char bitsperbyte[256] = …; /* * addressbits is a lookup table to filter out the bits from the xor-ed * ECC data that identify the faulty location. * this is only used for repairing parity * see the comments in nand_ecc_sw_hamming_correct for more details */ static const char addressbits[256] = …; int ecc_sw_hamming_calculate(const unsigned char *buf, unsigned int step_size, unsigned char *code, bool sm_order) { … } EXPORT_SYMBOL(…); /** * nand_ecc_sw_hamming_calculate - Calculate 3-byte ECC for 256/512-byte block * @nand: NAND device * @buf: Input buffer with raw data * @code: Output buffer with ECC */ int nand_ecc_sw_hamming_calculate(struct nand_device *nand, const unsigned char *buf, unsigned char *code) { … } EXPORT_SYMBOL(…); int ecc_sw_hamming_correct(unsigned char *buf, unsigned char *read_ecc, unsigned char *calc_ecc, unsigned int step_size, bool sm_order) { … } EXPORT_SYMBOL(…); /** * nand_ecc_sw_hamming_correct - Detect and correct bit error(s) * @nand: NAND device * @buf: Raw data read from the chip * @read_ecc: ECC bytes read from the chip * @calc_ecc: ECC calculated from the raw data * * Detect and correct up to 1 bit error per 256/512-byte block. */ int nand_ecc_sw_hamming_correct(struct nand_device *nand, unsigned char *buf, unsigned char *read_ecc, unsigned char *calc_ecc) { … } EXPORT_SYMBOL(…); int nand_ecc_sw_hamming_init_ctx(struct nand_device *nand) { … } EXPORT_SYMBOL(…); void nand_ecc_sw_hamming_cleanup_ctx(struct nand_device *nand) { … } EXPORT_SYMBOL(…); static int nand_ecc_sw_hamming_prepare_io_req(struct nand_device *nand, struct nand_page_io_req *req) { … } static int nand_ecc_sw_hamming_finish_io_req(struct nand_device *nand, struct nand_page_io_req *req) { … } static struct nand_ecc_engine_ops nand_ecc_sw_hamming_engine_ops = …; static struct nand_ecc_engine nand_ecc_sw_hamming_engine = …; struct nand_ecc_engine *nand_ecc_sw_hamming_get_engine(void) { … } EXPORT_SYMBOL(…); MODULE_LICENSE(…) …; MODULE_AUTHOR(…) …; MODULE_DESCRIPTION(…) …;