The MINI2440 Development Board uses the =2k of 8bit,256m blocksize= 128k,pagesize Nandflash.
Broadband is 8bit, by s3c2440 datasheet know hardware production of ECC is 4byte.
s3c2440 Hardware ECC Operation Flow:
1. Read the ECC data produced by the hardware in the NFMECC0 register first.
2. After processing the read-out ECC data, write the NFMECCD0 and NFMECCD1 registers separately,
Hardware automatic detection, the test results can be read from the NFESTAT0 register.
3. Read the NFESTAT0 register to determine the error category.
4. Data error >2bit cannot be corrected if 1bit error is corrected.
In the previous article on "Support Nandflash Read and write", we have done a good job of reading and writing u-boot to Nandflash, but this read and write is software ECC, that is, using software programming method to implement ECC. We know that S3c24x0 's Nandflash controller supports hardware ECC, so here we explain how to implement hardware ECC.
Each page of the Nandflash is divided into the main and spare areas, and the s3c24x0 Nandflash controller supports the hardware ECC for these two zones, but only the hardware ECC in the main area is implemented.
In order to implement hardware ECC, you first need to define the macro CONFIG_S3C2410_NAND_HWECC in the Include/configs/smdk2410.h file, so that drivers/mtd/nand/s3c2440_ The three functions required for hardware ECC are defined in the NAND.C file: s3c24x0_nand_enable_hwecc function, S3C24X0_NAND_CALCULATE_ECC function, and s3c24x0_nand_correct_ Data function, and in the Board_nand_init function, the three functions are assigned to the corresponding structure of the three members, so that when the Nandflash read and write, the three functions will be called, thus implementing the hardware ECC. The S3C24X0_NAND_ENABLE_HWECC function is responsible for enabling the hardware ECC,S3C24X0_NAND_CALCULATE_ECC function to compute ECC (which is, of course, done by hardware), s3c24x0_nand_correct_ The data function is responsible for ECC validation (again, this check is done automatically by the hardware).
To understand how U-boot is doing hardware ECC, let's start by briefly analyzing the related functions. Nandflash is to read and write in the smallest units of the page, the support of the hardware ECC reading operation is ultimately done by the NAND_READ_PAGE_HWECC function (in the Drivers/mtd/nand directory), the support of hardware ECC write operation is ultimately by the Nand_ The WRITE_PAGE_HWECC function (under the Drivers/mtd/nand directory) is completed. The flow of the NAND_READ_PAGE_HWECC function is to read the main area data first, and to obtain the hardware ECC by calling the S3C24X0_NAND_CALCULATE_ECC function, and then reading the spare area data. And then extracts the main area of ECC, which is stored in the spare area, and finally verifies the main area data just read by calling the S3c24x0_nand_correct_data function. The flow of the NAND_WRITE_PAGE_HWECC function is simple, it writes the main area data first, and the hardware ECC is obtained by invoking the S3C24X0_NAND_CALCULATE_ECC function, then the hardware ECC is written to the spare zone.
Both the NAND_WRITE_PAGE_HWECC function and the NAND_WRITE_PAGE_HWECC function have a for loop body inside:
for (i = 0; eccsteps; eccsteps--, i + = eccbytes, p + = eccsize) {
...... ......
}
Three of the main variables are defined as:
Eccsize= chip->ecc.size;
eccbytes= chip->ecc.bytes;
eccsteps= chip->ecc.steps;
Let's introduce the function of this loop: the number of hardware ECC bytes that the Nandflash controller of different CPUs can complete at a time is not the same, for example, some CPUs can only complete 512 bytes of hardware ECC at a time, But what if the Nandflash on the Development Board have 2048 bytes per page? A loop body is used to get a page of hardware ECC through multiple loops. For example, in this case, it is necessary to loop 4 times (2048÷512=4) to get the complete hardware ECC for the data in this page. In addition to each hardware ECC, the number of ECC bytes generated by different CPUs is different, some 3 bytes, some 4 bytes.
So, the three variables above have the following meanings:
Ecc.size: The number of bytes tested per hardware ECC
Ecc.bytes: The number of bytes generated per hardware ECC
Ecc.steps: Number of hardware ECC required per page
For s3c2440, a hardware ECC can test 2048 bytes and generate 4-byte ECC, so ecc.size should be 2048,ecc.bytes 4. And ecc.steps is calculated, that is, the system can know the nandflash of the size of each page, with this value divided by ecc.size is equal to Ecc.steps.
Include/configs/smdk2410.h in-file definition
#define CONFIG_SYS_NAND_ECCSIZE 2048
#define Config_sys_nand_eccbytes 4
Now you are ready to start porting, open the Drivers/mtd/nand/s3c2410_nand.c file, and modify the function as follows
void S3c24x0_nand_enable_hwecc (struct mtd_info *mtd, int mode)
{
struct S3c24x0_nand *nand = S3c24x0_get_base_nand ();
Debug ("S3c24x0_nand_enable_hwecc (%p,%d) \ n", MTD, mode);
Writel (Readl (&nand->nfcont) | S3C2440_NFCONT_INITECC, &nand->nfcont);
}
static int s3c24x0_nand_calculate_ecc (struct mtd_info *mtd, const U_char *dat,
U_char *ecc_code)
{
struct S3c24x0_nand *nand = S3c24x0_get_base_nand ();
unsigned int mecc0;
Writel (Readl (&nand->nfcont) | S3c2440_nfcont_meccl,&nand->nfcont);
mecc0 = Readl (&nand->nfmecc0);
ecc_code[0] = mecc0 & 0xFF;
ecc_code[1] = (mecc0 >> 8) & 0xFF;
ecc_code[2] = (mecc0 >>16) & 0xFF;
ecc_code[3] = (mecc0 >>24) & 0xFF;
Debug ("S3c24x0_nand_calculate_hwecc (%p,): 0x%02x 0x%02x 0x%02x 0x%02x\n",
MTD, Ecc_code[0], ecc_code[1], ecc_code[2],ecc_code[3]);
return 0;
}
static int s3c24x0_nand_correct_data (struct mtd_info *mtd, U_char *dat,
U_char *READ_ECC, U_char *CALC_ECC)
{
struct S3c24x0_nand *nand = S3c24x0_get_base_nand ();
u32 meccdata0,meccdata1,estat0,err_byte_addr;
int ret=-1;
U8 repaired;
meccdata0 = (read_ecc[1] <<) | read_ecc[0];
meccdata1 = (read_ecc[3] <<) | read_ecc[2];
Writel (meccdata0,&nand->nfeccd0);
Writel (MECCDATA1,&NAND->NFECCD1);
/*read ECC status*/
estat0 = Readl (&nand->nfstat0);
switch (estat0 &0x3) {
Case 0:/*no error*/
ret =0;
Break ;
Case 1:
/*
*1bit Error (correctable)
* (Nfestat0 >>7) & 0x7ff error byte number
* (Nfestat0 >>4) & 0x7 Error bit number
*/
err_byte_addr = (estat0 >>7) & 0x7ff;
repaired = dat[err_byte_addr]^ (1<< (estat0 >>4) & 0x7);
printf ("s3c nand:1 bit error detected at byte%ld." )
"Correcting from 0x%02x to0x%02x ... Ok\n ",
err_byte_addr, dat[err_byte_addr],repaired);
dat[err_byte_addr]= repaired;
ret= 1;
Break ;
Case 2:/* Multiple error */
Case 3:/* ECC Area Error * /
printf ("s3c nand:ecc uncorrectable errordetected."
"Not correctable.\n");
ret=-1;
Break
}
return ret;
}
u-boot-2016.03 Nandflash hardware ECC on mini2440