Port the nandflash driver to enable U-boot to support the NAND operation.
U-boot version: U-boot 2008.10 target board: mini2440 nandflash model: k9f2g08u0c 256 m
Another two directories under U-boot Drivers/MTD are NAND and nand_leagcy. Among them, nand_legacy also contains the relevant operation commands of NAND implementation, but this is reserved to support some old versions. This migration uses the NAND directory.
Modify include/configs/mini2440.h.
1) added command support:
# Define config_assist_elf
# Define config_assist_nand
2) Add the NAND Flash parameter settings:
/* NAND flashsettings ************************************ **************************************** **************/
# Define ipv_nand_base 0/* NAND controller base address */
# Define ipv_max_nand_device 1/* max NAND flash device */
# Define nand_max_chips 1/* Number of nandflash chips */
# Define sectorsize 2048/* volume of 1 sector */
# Define addr_column 2/* 2 byte column address */
# Define addr_page 3
# Define addr_column_page 4
# Define nand_chipid_unknown 0x00
# Define nand_max_floors 4
# Define config_mtd_nand_verify_write 1
3) The initialization sequence of NAND is:
Lib_arm/board. in C, start_armboot ()-> Drivers/MTD/NAND. in C, nand_init ()-> nand_init_chip ()-> CPU/ARM920T/s3c24x0/NAND. in C, board_nand_init () completes nandflash initialization.
In Drivers/MTD/NAND. C, nand_init ()-> nand_scan ()-> in drivers/MTD/NAND/nand_base.c
Nand_scan_ident ()-> nand_set_defaults ()
Nand_scan_ident ()-> nand_get_flash_type ()
Nand_scan ()-> nand_scan_tail () in drivers/MTD/NAND/nand_base.c ()
Nand_scan_ident (): NAND flash device Scan
Nand_scan_tail (): called in nand_scan () to fill in all initialization function pointers and to scan bad block tables.
Note: This version of U-boot has built-in board_nand_init (), which is defined in CPU/ARM920T/s3c24x0/NAND. C.
Because of the differences between S3C2410 and S3C2440 on the flash controller, the driver code needs to be improved, mainly in CPU, ARM920T, s3c24x0, and NAND. C.
CPU/ARM920T/s3c24x0/NAND. C:
First, add the address definition of the S3C2440 nandflash controller. The modification is as follows:
''''''
# If! Defined (config_s3c2440)
# Define nf_base0x4e000000
# Define nfconf _ Regi (nf_base + 0x0)
# Define nfcmd _ regb (nf_base + 0x4)
# Define nfaddr _ regb (nf_base + 0x8)
# Define nfdata _ regb (nf_base + 0xc)
# Define nfstat _ regb (nf_base + 0x10)
# Define nfecc0 _ regb (nf_base + 0x14)
# Define nfecc1 _ regb (nf_base + 0x15)
# Define nfecc2 _ regb (nf_base + 0x16)
# Else
# Define nf_base 0x4e000000
# Define nfconf _ Regi (nf_base + 0x0)
# Define nfcont _ Regi (nf_base + 0x4)
# Define nfcmd _ regb (nf_base + 0x8)
# Define nfaddr _ regb (nf_base + 0xc)
# Define nfdata _ regb (nf_base + 0x10)
# Define nfmeccd0 _ Regi (nf_base + 0x14)
# Define nfmeccd1 _ Regi (nf_base + 0x18)
# Define nfseccd _ Regi (nf_base + 0x1c)
# Define nfstat _ regb (nf_base + 0x20)
# Define nfstat0 _ Regi (nf_base + 0x24)
# Define nfstat1 _ Regi (nf_base + 0x28)
# Define nfmecc0 _ Regi (nf_base + 0x2c)
# Define nfmecc1 _ Regi (nf_base + 0x30)
# Define nfsecc _ Regi (nf_base + 0x34)
# Define nfsblk _ Regi (nf_base + 0x38)
# Define nfeblk _ Regi (nf_base + 0x3c)
# Define s3c2440_nfcont_nce (1 <1)
# Define s3c2440_addr_nale 0x0c
# Define s3c2440_addr_ncle 0x08
# Endif
''''''
The s3c2410_hwcontrol function of S3C2410 which comes with U-Boot.2008.10 is wrong. In this function, the value of chip-> io_addr_w is rewritten, causing an error during data writing. The solution is to replace chip-> io_addr_w with a global variable. Define the global variable in the previous line of the s3c2410_hwcontrol function, and modify the s3c2410_hwcontrol function to support the S3C2440 function. The modification is as follows:
''''
Ulong io_addr_w = nf_base;
Static void s3c2410_hwcontrol (structmtd_info * MTD, int cmd, unsigned int CTRL)
{
Struct nand_chip * chip = MTD-> priv;
Debugn ("hwcontrol (): 0x % 02x 0x % 02x \ n", CMD, CTRL );
/* Modified by XXX, for 2440 ************************************** *******************/
# If! Defined (config_s3c2440)
If (CTRL & nand_ctrl_change ){
/* Modified by XXX, for2440 *************************************** ******************/
/* Ulong io_addr_w = nf_base; * // * Delete ulong, by XXX ********/
Io_addr_w = nf_base;
If (! (CTRL & nand_cle ))
Io_addr_w | = s3c2410_addr_ncle;
If (! (CTRL & nand_ale ))
Io_addr_w | = s3c2410_addr_nale;
/* Chip-> io_addr_w = (void *) io_addr_w; * // * bug, delete byxxx ******/
If (CTRL & nand_nce)
Nfconf & = ~ S3c2410_nfconf_nfce;
Else
Nfconf | = s3c2410_nfconf_nfce;
}
If (CMD! = Nand_assist_none)
/* Writeb (CMD, chip-> io_addr_w); * // * modified by XXX ************/
Writeb (CMD, (void *) chip-> io_addr_w );
# Else
If (CTRL & nand_ctrl_change ){
Io_addr_w = nf_base;
If (! (CTRL & nand_cle ))
Io_addr_w | = s3c2440_addr_nale;
If (! (CTRL & nand_ale ))
Io_addr_w | = s3c2440_addr_ncle;
/* Chip-> io_addr_w = (void *) io_addr_w; * // * bug, delete by XXX ******/
If (CTRL & nand_nce)
Nfcont & = ~ S3c2440_nfcont_nce;/* becareful there is nfcont **********/
Else
Nfcont | = s3c2440_nfcont_nce;
}
If (CMD! = Nand_assist_none)
/* Writeb (CMD, chip-> io_addr_w); * // * modified by XXX ************/
Writeb (CMD, (void *) io_addr_w );
# Endif
}
The modified board_nand_init is as follows:
····
Clk_power-> clkcon | = (1 <4 );
/* Add by XXX, for 2440 ************************************** ****************/
# If! Defined (config_s3c2440)
Debugn ("config_s3c2410 \ n ");
/* Initialize hardware */
Twrph0 = 3; twrph1 = 0; tacls = 0;
CFG = s3c2410_nfconf_en;
CFG | = s3c2410_nfconf_tacls (tacls-1 );
CFG | = s3c2410_nfconf_twrph0 (twrph0-1 );
CFG | = s3c2410_nfconf_twrph1 (twrph1-1 );
Nfconf = CFG;
/* Initialize nand_chip Data Structure */
Nand-> io_addr_r = NAND-> io_addr_w = (void *) 0x4e00000c;
/* Read_buf and write_buf are default */
/* Read_byte and write_byte are default */
/* Hwcontrol always must be implemented */
Nand-> export _ctrl = s3c2410_hwcontrol;
Nand-> dev_ready = s3c2410_dev_ready;
# Else
Debugn ("config_s3c2440 \ n ");
/* Initialize hardware */
Twrph0 = 4; twrph1 = 2; tacls = 0;/* modified by dazhi, for 2440 *****/
/* Modified by XXX, for 2440 ************************************** ***********/
CFG = (tacls <12) | (twrph0 <8) | (twrph1 <4 );
Nfconf = CFG;
CFG = (1 <6) | (1 <4) | (0 <1) | (1 <0 );
Nfcont = CFG;
/* Initialize nand_chip Data Structure */
Nand-> io_addr_r = NAND-> io_addr_w = (void *) 0x4e000010;
/* Read_buf and write_buf are default */
/* Read_byte and write_byte are default */
/* Hwcontrol always must be implemented */
Nand-> export _ctrl = s3c2410_hwcontrol;
Nand-> dev_ready = s3c2410_dev_ready;
# Endif
To display the chip model, end the nand_get_flash_type function in drivers/MTD/NAND/nand_base.c and change mtddebug to printf.
Save the U-boot parameter in NAND Flash (saveenv function)
Add/include/configs/mini2440.h:
'''''
# Define config_assist_nand
# Define config_assist_env
'''''
/* # Define config_env_is_in_flash 1 */
# Define config_env_is_in_nand 1
# Define config_env_offset 0x40000/* the start position of the parameter in NAND Flash is 256 K */
# Define config_env_size 0x20000/* Total Environment Variable Size, 128 K */
So far, the modification is complete, and you can recompile it.
You may encounter USB-boot serial port printing no NAND device found !!! Generally, the reason for this error is that the initialization of NAND Flash is not completed properly. Note that the 3c2410_hwcontrol () function is being modified.
If (CTRL & nand_nce)
Nfcont & = ~ S3c2440_nfcont_nce;/* becareful there is nfcont **********/
Else
Nfcont | = s3c2440_nfcont_nce;
Do not write it as nfconf by mistake.
Reference from: http://www.docin.com/p-26158679.html pages 10-15