satip-axe/kernel/drivers/mtd/nand/stm_nand_ecc.h

152 lines
4.5 KiB
C
Raw Permalink Normal View History

/*
* Synopsis : Error Correction Codes (ECC) Algorithms.
*
* Copyright (c) 2008 STMicroelectronics Limited. All right reserved.
*
* May be copied or modified under the terms of the GNU General Public
* License Version 2.0 only. See linux/COPYING for more information.
*
* An ECC is a 3-byte code which can be used to detect and correct 1-bit
* errors (perhaps introduced by NAND flash defects) in a 128, 256, or
* 512-byte block of data.
*
* Features:
* - Correction of any 1-bit error in the data.
* - Detection of any 1-bit error in the ECC and whether the data is OK.
* - Detection of any 2-bit error in the data.
*
* Limitations:
* - CANNOT correct 2-bit errors.
* - Results for 3-bit errors (or worse) are UNDEFINED.
*
* This algorithm is only intended for use with data corrupted by a NAND
* flash - in which anything more than a 1-bit error is highly unlikely.
*
* DO NOT attempt to use it where the data may be more seriously corrupted.
* The algorithm WILL NOT always correct serious defects and may even report
* that the data is good.
*
* Usage
* =====
*
* Writing flash:
*
* 1) Prepare the data.
* 2) Generate an ECC for each 128, 256, or 512 bytes.
* stm_ecc_gen (data, ecc, ECC_256)
* 3) Write both to flash.
*
* Reading flash:
*
* 1) Read both data and ECC from flash.
* 2) Generate a fresh ECC for the read data.
* ecc_gen (read_data, new_ecc, ECC_256)
* 3) Compare the two ECCs and correct the data, if necessary.
* ecc_correct (read_data, read_ecc, new_ecc, ECC_256)
* 4) Check the return code:
* E_UN_CHK
* Data cannot be used - too badly corrupted.
* E_NO_CHK
* All is well.
* E_D1_CHK
* Data has been corrected, but the flash block contains an error.
* E_C1_CHK
* Data is OK, but the flash block contains an error in the ECC.
*
* If a read error occurs then you may want to consider moving the data to
* another flash block. If the read error is in the ECC then don't forget
* to generate a correct ECC before rewriting.
*
* ECC Format
* ==========
*
* Basic Format:
*
* byte 0 byte 1 byte2
*
* bit 0 LP0 LP8 LP16
* bit 1 LP1 LP9 LP17
* bit 2 LP2 LP10 ` CP0
* bit 3 LP3 LP11 CP1
* bit 4 LP4 LP12 CP2
* bit 5 LP5 LP13 CP3
* bit 6 LP6 LP14 CP4
* bit 7 LP7 LP15 CP5
*
* CP = Column parity
* LP = Line parity
*
* ECC_128:
*
* LP14-17 are not used. The unused bits are set to zero.
*
* This format is designed to match the format used by the error
* correcting EMI NAND Controller. It may NOT be compatible with other
* 128 byte ECCs.
*
* ECC_256:
*
* LP16-17 are not used. The unused bits are set to zero.
*
* ECC_512:
*
* All bits are used.
*
* This format is NOT compatible with the 512 byte ECC used by OSPlus.
* (At the time of writing, this can be resolved merely by inverting each
* bit in the ECC, but this may not be the case in future.)
*
* Changelog:
* 2009-02-25 Angus Clark <angus.clark@st.com>
* - Renamed, formatted, and edited for linux compatibility
*
*/
#ifndef STM_NAND_ECC_H
#define STM_NAND_ECC_H
#include <linux/types.h>
/* The ECC algorithms support three different data sizes. */
enum ecc_size
{
ECC_128 = 128,
ECC_256 = 256,
ECC_512 = 512
};
/* Return values from check function */
enum ecc_check
{
E_UN_CHK = -1, /* uncorrectable error. */
E_NO_CHK = 0, /* No Errors. */
E_D1_CHK = 1, /* 1-bit data error. */
E_C1_CHK = 2 /* 1-bit code error. */
};
/* Generate 3 byte ECC code for ecc_size block p_data.
"p_data" is a pointer to the date and must be 4-byte aligned.
"size" gives length of "p_data" - one of enum ecc_size.
*/
void stm_ecc_gen(const uint8_t *p_data, uint8_t *ecc,
enum ecc_size size);
/* Detect and correct a 1 bit error in a 128, 256 or 512 byte block.
"p_data" is a pointer to the data.
"old_ecc" is the proper ECC for the data.
"new_ecc" is the ECC generated from the (possibly) corrupted data.
The size of the block is given in "size".
Returns whether the data needed correcting, or was not correctable.
If the result code is E_D1_CHK, then the data will have been modified.
*/
enum ecc_check stm_ecc_correct(uint8_t *p_data,
uint8_t *old_ecc,
uint8_t *new_ecc,
enum ecc_size size);
unsigned char stm_afm_lp1617(const unsigned char *buf);
#endif /* ifndef STM_NAND_ECC_H */