U-boot-2014.10 port 21st days ---- add nand flash command support (3), u-boot-2014.10nand
Hardware Platform: tq2440
Development Environment: Ubuntu-3.11
U-boot: 2014.10
This article allows reprint, please indicate the source: http://blog.csdn.net/fulinus
Although the nand flash read/write operation is acceptable, the following error occurs when I use the nand markbad command to mark a block as a bad block and use the nand scrub command to restore the factory settings:
nand0: MTD Erase failure: -5
It indicates that the transplantation of nand flash is not completely correct.
Find the cause below
Only these macros are left in the first part of the drivers/mtd/nand/s3c2440_nand.c file. As mentioned above, all the 2410 words in the file have been changed to 2440, so don't be surprised at the following changes:
#define S3C2440_NFCONF_TACLS(x) ((x)<<12)#define S3C2440_NFCONF_TWRPH0(x) ((x)<<8)#define S3C2440_NFCONF_TWRPH1(x) ((x)<<4)#define S3C2440_NFCONT_EN (1<<0)#define S3C2440_NFCONT_INITECC (1<<4)#define S3C2440_NFCONT_nFCE (1<<1)#define S3C2440_NFCONT_MAINECCLOCK (1<<5)#define S3C2440_ADDR_NALE 8#define S3C2440_ADDR_NCLE 0x0c
In the past, many macros defined the 2410 nand flash register bit, and there were many differences on 2440. For example, the content in the NFCONF register was moved to the NFCONT register.
Modify the s3c2440_hwcontrol function, instead of the S3C2440_NFCONF_nFCE macro, but the S3C2440_NFCONT_nFCE macro:
Static void s3c2440_hwcontrol (struct mtd_info * mtd, int cmd, unsigned int ctrl) {struct nand_chip * chip = mtd-> priv; struct s3c2440_nand * nand = s3c2440_get_base_nand (); debug ("hwcontrol (): 0x % 02x 0x % 02x \ n", cmd, ctrl); if (ctrl & NAND_CTRL_CHANGE) {ulong IO_ADDR_W = (ulong) nand; if (! (Ctrl & NAND_CLE) IO_ADDR_W | = S3C2440_ADDR_NCLE; if (! (Ctrl & NAND_ALE) IO_ADDR_W | = bytes; if (cmd = NAND_CMD_NONE) records = (ulong) & nand-> nfdata; chip-> IO_ADDR_W = (void *) IO_ADDR_W; if (ctrl & NAND_NCE)/* enable Select */writel (readl (& nand-> nfconf )&~ S3C2440_NFCONT_nFCE, & nand-> nfconf); else/* deselect */writel (readl (& nand-> nfconf) | S3C2440_NFCONT_nFCE, & nand-> nfconf );} if (cmd! = Nand_assist_none) writeb (cmd, chip-> IO_ADDR_W );}
In the s3c2440_nand_enable_hwecc function, modify:
void s3c2440_nand_enable_hwecc(struct mtd_info *mtd, int mode){ struct s3c2440_nand *nand = s3c2440_get_base_nand(); debug("s3c2440_nand_enable_hwecc(%p, %d)\n", mtd, mode); writel(((readl(&nand->nfconf) | S3C2440_NFCONT_INITECC) & (~S3C2440_NFCONT_MAINECCLOCK)), &nand->nfconf);}
Modify the following in the arch/arm/include/asm/arch-s3c24x0/s3c24x0. h file:
/* NAND FLASH (see S3C2440 manual chapter 6) */struct s3c2440_nand { u32 nfconf; u32 nfcont; u32 nfcmd; u32 nfaddr; u32 nfdata; u32 nfeccd0; u32 nfeccd1; u32 nfeccd; u32 nfstat; u32 nfstat0; u32 nfstat1; u32 nfmecc0; u32 nfmecc1; u32 nfsecc; u32 nfsblk; u32 nfeblk;};
Note: The arch directory under the arch/arm/include/asm/directory is actually the symbolic link of the arch/arm/include/asm/arch-s3c24x0/directory.
In the s3c2440_nand_calculate_ecc function, modify:
static int s3c2440_nand_calculate_ecc(struct mtd_info *mtd, const u_char *dat, u_char *ecc_code){ struct s3c2440_nand *nand = s3c2440_get_base_nand(); ecc_code[0] = readb(&nand->nfmecc0); ecc_code[1] = readb(&nand->nfmecc0 + 1); ecc_code[2] = readb(&nand->nfmecc0 + 2); ecc_code[3] = readb(&nand->nfmecc0 + 3); debug("s3c2440_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; }
In the s3c2440_nand_correct_data function, modify:
static int s3c2440_nand_correct_data(struct mtd_info *mtd, u_char *dat, u_char *read_ecc, u_char *calc_ecc){ struct s3c2440_nand *nand = s3c2440_get_base_nand(); u32 estat0,err_byte_addr; int ret = -1; u8 repaired; writel((read_ecc[1] << 16) | read_ecc[0],&nand->nfeccd0); writel((read_ecc[3] << 16) | read_ecc[2],&nand->nfeccd1); /* Read ecc status */ estat0= readl(&nand->nfstat); switch(estat0 & 0x3) { case 0: /* No error */ ret= 0; break; case 1: /* * 1 bit 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%d. " "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;}
Delete the s3c2440_nand_select function:
Static void s3c2440_nand_select (struct mtd_info * mtd, int chipnr) {struct s3c2440_nand * nand = s3c2440_get_base_nand (); switch (chipnr) {case-1: /* deselect */nand-> nfcont | = (1 <1); break; case 0:/* select */nand-> nfcont & = ~ (1 <1); break; default: BUG ();} return ;}
Modify the following in the board_nand_init function:
Int round (struct nand_chip * nand) {u_int32_t cfg; u_int8_t tacls, twrph0, twrph1; struct round * clk_power = round (); struct s3c2440_nand * nand_reg = round (); debug ("board_nand_init () \ n"); writel (readl (& clk_power-> clkcon) | (1 <4), & clk_power-> clkcon ); /* initialize hardware */tacls = CONFIG_S3C24XX_TACLS; twrph0 = CONFIG_S3C24XX_TWRPH0; twrph1 = success; cfg = 0; cfg | = S3C2440_NFCONF_TACLS (tacls-1 ); cfg | = S3C2440_NFCONF_TWRPH0 (twrph0-1); cfg | = S3C2440_NFCONF_TWRPH1 (twrph1-1); writel (cfg, & nand_reg-> nfconf ); /* initialize ECC, disable chip selection, enable nand flash Controller */cfg = (0 <13) | (0 <12) | (0 <10) | (0 <9) | (0 <8) | (0 <6) | (0 <5) | (1 <4) | (0 <1) | (1 <0); writel (cfg, & nand_reg-> nfcont ); /* initialize nand_chip data structure */nand-> IO_ADDR_R = (void *) & nand_reg-> nfdata; nand-> IO_ADDR_W = (void *) & nand_reg-> nfdata; nand-> select_chip = NULL;/* read_buf and write_buf are default * // * read_byte and write_byte are default */# ifdef CONFIG_NAND_SPL nand-> read_buf = nand_read_buf; # endif/* hwcontrol always must be implemented */nand-> export _ctrl = s3c2440_hwcontrol; nand-> dev_ready = s3c2440_dev_ready; # ifdef CONFIG_S3C2440_NAND_HWECC nand-> ecc. hwctl = s3c2440_nand_enable_hwecc; nand-> ecc. calculate = s3c2440_nand_calculate_ecc; nand-> ecc. correct = s3c2440_nand_correct_data; nand-> ecc. mode = NAND_ECC_HW; nand-> ecc. size = CONFIG_SYS_NAND_ECCSIZE; nand-> ecc. bytes = CONFIG_SYS_NAND_ECCBYTES; nand-> ecc. strength = 1; # else nand-> ecc. mode = NAND_ECC_SOFT; # endif # ifdef CONFIG_S3C2440_NAND_BBT nand-> bbt_options | = NAND_BBT_USE_FLASH; # endif debug ("end of nand_init \ n"); return 0 ;}
Several macros involved in the board_nand_init function need to be defined in the include/configs/tq2440.h file:
Refer to blog UBOOT porting (support for nand flash)-initial transplantation (1)
The previously defined CONFIG_SYS_S3C2440_NAND_HWECC macro name is in the s3c2440_nand.c file, but it is the CONFIG_S3C2440_NAND_HWECC macro name. It is found that the CONFIG_NAND_S3C2440 macro is not useful in any way.
Modify the File include/configs/tq2440.h as follows:
/* * NAND configuration */#ifdef CONFIG_CMD_NAND#define CONFIG_NAND_S3C2440#define CONFIG_MTD_DEVICE#define CONFIG_MTD_NAND_VERIFY_WRITE#define CONFIG_SYS_NAND_MAX_CHIPS 1#define CONFIG_SYS_MAX_NAND_DEVICE 1#define CONFIG_SYS_NAND_BASE 0x4E000000#define CONFIG_S3C24XX_CUSTOM_NAND_TIMING#ifdef CONFIG_S3C24XX_CUSTOM_NAND_TIMING#define CONFIG_S3C24XX_TACLS 0#define CONFIG_S3C24XX_TWRPH0 4#define CONFIG_S3C24XX_TWRPH1 2#endif#define CONFIG_S3C2440_NAND_HWECC#ifdef CONFIG_S3C2440_NAND_HWECC#define CONFIG_SYS_NAND_PAGE_SIZE 512#define CONFIG_SYS_NAND_ECCSIZE CONFIG_SYS_NAND_PAGE_SIZE#define CONFIG_SYS_NAND_ECCBYTES 4#endif#endif /* end CONFIG_CMD_NAND */
Modify the nand_select_chip function in the drivers/mtd/nand/nand_base.c file:
Static void nand_select_chip (struct mtd_info * mtd, int chipnr) {struct nand_chip * chip = mtd-> priv; switch (chipnr) {case-1: chip-> cmd_ctrl (mtd, nand_1__none, 0 | NAND_CTRL_CHANGE); break; case 0:/* select * // chip-> mtd, nand_1__none, NAND_CTRL_CLE | NAND_CTRL_CHANGE; break; default: BUG ();}}
Compile and run
The situation persists:
Nand0: MTD Erase failure:-5
Continue tomorrow!