@ -25,168 +25,23 @@
# if defined(CONFIG_MX25) || defined(CONFIG_MX27) || defined(CONFIG_MX35)
# include <asm/arch/imx-regs.h>
# endif
# include <fsl_nfc.h>
# define DRIVER_NAME "mxc_nand"
/*
* TODO : Use same register defs here as nand_spl mxc nand driver .
*/
/*
* Register map and bit definitions for the Freescale NAND Flash Controller
* present in various i . MX devices .
*
* MX31 and MX27 have version 1 which has
* 4 512 byte main buffers and
* 4 16 byte spare buffers
* to support up to 2 K byte pagesize nand .
* Reading or writing a 2 K page requires 4 FDI / FDO cycles .
*
* MX25 has version 1.1 which has
* 8 512 byte main buffers and
* 8 64 byte spare buffers
* to support up to 4 K byte pagesize nand .
* Reading or writing a 2 K or 4 K page requires only 1 FDI / FDO cycle .
* Also some of registers are moved and / or changed meaning as seen below .
*/
# if defined(CONFIG_MX31) || defined(CONFIG_MX27)
# define MXC_NFC_V1
# elif defined(CONFIG_MX25) || defined(CONFIG_MX35)
# define MXC_NFC_V1_1
# else
# warning "MXC NFC version not defined"
# endif
# if defined(MXC_NFC_V1)
# define NAND_MXC_NR_BUFS 4
# define NAND_MXC_SPARE_BUF_SIZE 16
# define NAND_MXC_REG_OFFSET 0xe00
# define is_mxc_nfc_11() 0
# elif defined(MXC_NFC_V1_1)
# define NAND_MXC_NR_BUFS 8
# define NAND_MXC_SPARE_BUF_SIZE 64
# define NAND_MXC_REG_OFFSET 0x1e00
# define is_mxc_nfc_11() 1
# else
# error "define CONFIG_NAND_MXC_VXXX to use mtd mxc nand driver"
# endif
struct nfc_regs {
uint8_t main_area [ NAND_MXC_NR_BUFS ] [ 0x200 ] ;
uint8_t spare_area [ NAND_MXC_NR_BUFS ] [ NAND_MXC_SPARE_BUF_SIZE ] ;
/*
* reserved size is offset of nfc registers
* minus total main and spare sizes
*/
uint8_t reserved1 [ NAND_MXC_REG_OFFSET
- NAND_MXC_NR_BUFS * ( 512 + NAND_MXC_SPARE_BUF_SIZE ) ] ;
# if defined(MXC_NFC_V1)
uint16_t nfc_buf_size ;
uint16_t reserved2 ;
uint16_t nfc_buf_addr ;
uint16_t nfc_flash_addr ;
uint16_t nfc_flash_cmd ;
uint16_t nfc_config ;
uint16_t nfc_ecc_status_result ;
uint16_t nfc_rsltmain_area ;
uint16_t nfc_rsltspare_area ;
uint16_t nfc_wrprot ;
uint16_t nfc_unlockstart_blkaddr ;
uint16_t nfc_unlockend_blkaddr ;
uint16_t nfc_nf_wrprst ;
uint16_t nfc_config1 ;
uint16_t nfc_config2 ;
# elif defined(MXC_NFC_V1_1)
uint16_t reserved2 [ 2 ] ;
uint16_t nfc_buf_addr ;
uint16_t nfc_flash_addr ;
uint16_t nfc_flash_cmd ;
uint16_t nfc_config ;
uint16_t nfc_ecc_status_result ;
uint16_t nfc_ecc_status_result2 ;
uint16_t nfc_spare_area_size ;
uint16_t nfc_wrprot ;
uint16_t reserved3 [ 2 ] ;
uint16_t nfc_nf_wrprst ;
uint16_t nfc_config1 ;
uint16_t nfc_config2 ;
uint16_t reserved4 ;
uint16_t nfc_unlockstart_blkaddr ;
uint16_t nfc_unlockend_blkaddr ;
uint16_t nfc_unlockstart_blkaddr1 ;
uint16_t nfc_unlockend_blkaddr1 ;
uint16_t nfc_unlockstart_blkaddr2 ;
uint16_t nfc_unlockend_blkaddr2 ;
uint16_t nfc_unlockstart_blkaddr3 ;
uint16_t nfc_unlockend_blkaddr3 ;
# endif
} ;
/*
* Set INT to 0 , FCMD to 1 , rest to 0 in NFC_CONFIG2 Register
* for Command operation
*/
# define NFC_CMD 0x1
/*
* Set INT to 0 , FADD to 1 , rest to 0 in NFC_CONFIG2 Register
* for Address operation
*/
# define NFC_ADDR 0x2
/*
* Set INT to 0 , FDI to 1 , rest to 0 in NFC_CONFIG2 Register
* for Input operation
*/
# define NFC_INPUT 0x4
/*
* Set INT to 0 , FDO to 001 , rest to 0 in NFC_CONFIG2 Register
* for Data Output operation
*/
# define NFC_OUTPUT 0x8
/*
* Set INT to 0 , FD0 to 010 , rest to 0 in NFC_CONFIG2 Register
* for Read ID operation
*/
# define NFC_ID 0x10
/*
* Set INT to 0 , FDO to 100 , rest to 0 in NFC_CONFIG2 Register
* for Read Status operation
*/
# define NFC_STATUS 0x20
/*
* Set INT to 1 , rest to 0 in NFC_CONFIG2 Register for Read
* Status operation
*/
# define NFC_INT 0x8000
# ifdef MXC_NFC_V1_1
# define NFC_4_8N_ECC (1 << 0)
# else
# define NFC_4_8N_ECC 0
# endif
# define NFC_SP_EN (1 << 2)
# define NFC_ECC_EN (1 << 3)
# define NFC_BIG (1 << 5)
# define NFC_RST (1 << 6)
# define NFC_CE (1 << 7)
# define NFC_ONE_CYCLE (1 << 8)
typedef enum { false , true } bool ;
struct mxc_nand_host {
struct mtd_info mtd ;
struct nand_chip * nand ;
struct nfc_regs __iomem * regs ;
int spare_only ;
int status_request ;
int pagesize_2k ;
int clk_act ;
uint16_t col_addr ;
unsigned int page_addr ;
struct mtd_info mtd ;
struct nand_chip * nand ;
struct fsl_nfc_regs __iomem * regs ;
int spare_only ;
int status_request ;
int pagesize_2k ;
int clk_act ;
uint16_t col_addr ;
unsigned int page_addr ;
} ;
static struct mxc_nand_host mxc_host ;
@ -304,10 +159,10 @@ static void wait_op_done(struct mxc_nand_host *host, int max_retries,
uint32_t tmp ;
while ( max_retries - - > 0 ) {
if ( readw ( & host - > regs - > nfc_ config2) & NFC_INT ) {
tmp = readw ( & host - > regs - > nfc_ config2) ;
if ( readw ( & host - > regs - > config2 ) & NFC_INT ) {
tmp = readw ( & host - > regs - > config2 ) ;
tmp & = ~ NFC_INT ;
writew ( tmp , & host - > regs - > nfc_ config2) ;
writew ( tmp , & host - > regs - > config2 ) ;
break ;
}
udelay ( 1 ) ;
@ -326,8 +181,8 @@ static void send_cmd(struct mxc_nand_host *host, uint16_t cmd)
{
MTDDEBUG ( MTD_DEBUG_LEVEL3 , " send_cmd(host, 0x%x) \n " , cmd ) ;
writew ( cmd , & host - > regs - > nfc_ flash_cmd) ;
writew ( NFC_CMD , & host - > regs - > nfc_ config2) ;
writew ( cmd , & host - > regs - > flash_cmd ) ;
writew ( NFC_CMD , & host - > regs - > config2 ) ;
/* Wait for operation to complete */
wait_op_done ( host , TROP_US_DELAY , cmd ) ;
@ -342,8 +197,8 @@ static void send_addr(struct mxc_nand_host *host, uint16_t addr)
{
MTDDEBUG ( MTD_DEBUG_LEVEL3 , " send_addr(host, 0x%x) \n " , addr ) ;
writew ( addr , & host - > regs - > nfc_ flash_addr) ;
writew ( NFC_ADDR , & host - > regs - > nfc_ config2) ;
writew ( addr , & host - > regs - > flash_addr ) ;
writew ( NFC_ADDR , & host - > regs - > config2 ) ;
/* Wait for operation to complete */
wait_op_done ( host , TROP_US_DELAY , addr ) ;
@ -375,19 +230,19 @@ static void send_prog_page(struct mxc_nand_host *host, uint8_t buf_id,
}
}
writew ( buf_id , & host - > regs - > nfc_ buf_addr) ;
writew ( buf_id , & host - > regs - > buf_addr ) ;
/* Configure spare or page+spare access */
if ( ! host - > pagesize_2k ) {
uint16_t config1 = readw ( & host - > regs - > nfc_ config1) ;
uint16_t config1 = readw ( & host - > regs - > config1 ) ;
if ( spare_only )
config1 | = NFC_SP_EN ;
else
config1 & = ~ ( NFC_SP_EN ) ;
writew ( config1 , & host - > regs - > nfc_ config1) ;
writew ( config1 , & host - > regs - > config1 ) ;
}
writew ( NFC_INPUT , & host - > regs - > nfc_ config2) ;
writew ( NFC_INPUT , & host - > regs - > config2 ) ;
/* Wait for operation to complete */
wait_op_done ( host , TROP_US_DELAY , spare_only ) ;
@ -402,19 +257,19 @@ static void send_read_page(struct mxc_nand_host *host, uint8_t buf_id,
{
MTDDEBUG ( MTD_DEBUG_LEVEL3 , " send_read_page (%d) \n " , spare_only ) ;
writew ( buf_id , & host - > regs - > nfc_ buf_addr) ;
writew ( buf_id , & host - > regs - > buf_addr ) ;
/* Configure spare or page+spare access */
if ( ! host - > pagesize_2k ) {
uint32_t config1 = readw ( & host - > regs - > nfc_ config1) ;
uint32_t config1 = readw ( & host - > regs - > config1 ) ;
if ( spare_only )
config1 | = NFC_SP_EN ;
else
config1 & = ~ NFC_SP_EN ;
writew ( config1 , & host - > regs - > nfc_ config1) ;
writew ( config1 , & host - > regs - > config1 ) ;
}
writew ( NFC_OUTPUT , & host - > regs - > nfc_ config2) ;
writew ( NFC_OUTPUT , & host - > regs - > config2 ) ;
/* Wait for operation to complete */
wait_op_done ( host , TROP_US_DELAY , spare_only ) ;
@ -442,14 +297,14 @@ static void send_read_id(struct mxc_nand_host *host)
uint16_t tmp ;
/* NANDFC buffer 0 is used for device ID output */
writew ( 0x0 , & host - > regs - > nfc_ buf_addr) ;
writew ( 0x0 , & host - > regs - > buf_addr ) ;
/* Read ID into main buffer */
tmp = readw ( & host - > regs - > nfc_ config1) ;
tmp = readw ( & host - > regs - > config1 ) ;
tmp & = ~ NFC_SP_EN ;
writew ( tmp , & host - > regs - > nfc_ config1) ;
writew ( tmp , & host - > regs - > config1 ) ;
writew ( NFC_ID , & host - > regs - > nfc_ config2) ;
writew ( NFC_ID , & host - > regs - > config2 ) ;
/* Wait for operation to complete */
wait_op_done ( host , TROP_US_DELAY , 0 ) ;
@ -469,14 +324,14 @@ static uint16_t get_dev_status(struct mxc_nand_host *host)
/* store the main area1 first word, later do recovery */
store = readl ( main_buf ) ;
/* NANDFC buffer 1 is used for device status */
writew ( 1 , & host - > regs - > nfc_ buf_addr) ;
writew ( 1 , & host - > regs - > buf_addr ) ;
/* Read status into main buffer */
tmp = readw ( & host - > regs - > nfc_ config1) ;
tmp = readw ( & host - > regs - > config1 ) ;
tmp & = ~ NFC_SP_EN ;
writew ( tmp , & host - > regs - > nfc_ config1) ;
writew ( tmp , & host - > regs - > config1 ) ;
writew ( NFC_STATUS , & host - > regs - > nfc_ config2) ;
writew ( NFC_STATUS , & host - > regs - > config2 ) ;
/* Wait for operation to complete */
wait_op_done ( host , TROP_US_DELAY , 0 ) ;
@ -515,13 +370,13 @@ static void _mxc_nand_enable_hwecc(struct mtd_info *mtd, int on)
{
struct nand_chip * nand_chip = mtd - > priv ;
struct mxc_nand_host * host = nand_chip - > priv ;
uint16_t tmp = readw ( & host - > regs - > nfc_ config1) ;
uint16_t tmp = readw ( & host - > regs - > config1 ) ;
if ( on )
tmp | = NFC_ECC_EN ;
else
tmp & = ~ NFC_ECC_EN ;
writew ( tmp , & host - > regs - > nfc_ config1) ;
writew ( tmp , & host - > regs - > config1 ) ;
}
static int mxc_nand_read_oob_syndrome ( struct mtd_info * mtd ,
@ -799,7 +654,7 @@ static int mxc_nand_correct_data(struct mtd_info *mtd, u_char *dat,
{
struct nand_chip * nand_chip = mtd - > priv ;
struct mxc_nand_host * host = nand_chip - > priv ;
uint16_t ecc_status = readw ( & host - > regs - > nfc_ ecc_status_result) ;
uint16_t ecc_status = readw ( & host - > regs - > ecc_status_result ) ;
int subpages = mtd - > writesize / nand_chip - > subpagesize ;
int pg2blk_shift = nand_chip - > phys_erase_shift -
nand_chip - > page_shift ;
@ -845,7 +700,7 @@ static int mxc_nand_correct_data(struct mtd_info *mtd, u_char *dat,
* additional correction . 2 - Bit errors cannot be corrected by
* HW ECC , so we need to return failure
*/
uint16_t ecc_status = readw ( & host - > regs - > nfc_ ecc_status_result) ;
uint16_t ecc_status = readw ( & host - > regs - > ecc_status_result ) ;
if ( ( ( ecc_status & 0x3 ) = = 2 ) | | ( ( ecc_status > > 2 ) = = 2 ) ) {
MTDDEBUG ( MTD_DEBUG_LEVEL0 ,
@ -1289,14 +1144,14 @@ static void mxc_setup_config1(void)
{
uint16_t tmp ;
tmp = readw ( & host - > regs - > nfc_ config1) ;
tmp = readw ( & host - > regs - > config1 ) ;
tmp | = NFC_ONE_CYCLE ;
tmp | = NFC_4_8N_ECC ;
writew ( tmp , & host - > regs - > nfc_ config1) ;
writew ( tmp , & host - > regs - > config1 ) ;
if ( host - > pagesize_2k )
writew ( 64 / 2 , & host - > regs - > nfc_ spare_area_size) ;
writew ( 64 / 2 , & host - > regs - > spare_area_size ) ;
else
writew ( 16 / 2 , & host - > regs - > nfc_ spare_area_size) ;
writew ( 16 / 2 , & host - > regs - > spare_area_size ) ;
}
# else
# define mxc_setup_config1()
@ -1359,7 +1214,7 @@ int board_nand_init(struct nand_chip *this)
this - > read_buf = mxc_nand_read_buf ;
this - > verify_buf = mxc_nand_verify_buf ;
host - > regs = ( struct nfc_regs __iomem * ) CONFIG_MXC_NAND_REGS_BASE ;
host - > regs = ( struct fsl_ nfc_regs __iomem * ) CONFIG_MXC_NAND_REGS_BASE ;
host - > clk_act = 1 ;
# ifdef CONFIG_MXC_NAND_HWECC
@ -1383,15 +1238,15 @@ int board_nand_init(struct nand_chip *this)
host - > pagesize_2k = 0 ;
this - > ecc . size = 512 ;
tmp = readw ( & host - > regs - > nfc_ config1) ;
tmp = readw ( & host - > regs - > config1 ) ;
tmp | = NFC_ECC_EN ;
writew ( tmp , & host - > regs - > nfc_ config1) ;
writew ( tmp , & host - > regs - > config1 ) ;
# else
this - > ecc . layout = & nand_soft_eccoob ;
this - > ecc . mode = NAND_ECC_SOFT ;
tmp = readw ( & host - > regs - > nfc_ config1) ;
tmp = readw ( & host - > regs - > config1 ) ;
tmp & = ~ NFC_ECC_EN ;
writew ( tmp , & host - > regs - > nfc_ config1) ;
writew ( tmp , & host - > regs - > config1 ) ;
# endif
/* Reset NAND */
this - > cmdfunc ( mtd , NAND_CMD_RESET , - 1 , - 1 ) ;
@ -1400,10 +1255,10 @@ int board_nand_init(struct nand_chip *this)
* preset operation
* Unlock the internal RAM Buffer
*/
writew ( 0x2 , & host - > regs - > nfc_ config) ;
writew ( 0x2 , & host - > regs - > config ) ;
/* Blocks to be unlocked */
writew ( 0x0 , & host - > regs - > nfc_ unlockstart_blkaddr) ;
writew ( 0x0 , & host - > regs - > unlockstart_blkaddr ) ;
/* Originally (Freescale LTIB 2.6.21) 0x4000 was written to the
* unlockend_blkaddr , but the magic 0x4000 does not always work
* when writing more than some 32 megabytes ( on 2 k page nands )
@ -1415,10 +1270,10 @@ int board_nand_init(struct nand_chip *this)
* This might be NAND chip specific and the i . MX31 datasheet is
* extremely vague about the semantics of this register .
*/
writew ( 0xFFFF , & host - > regs - > nfc_ unlockend_blkaddr) ;
writew ( 0xFFFF , & host - > regs - > unlockend_blkaddr ) ;
/* Unlock Block Command for given address range */
writew ( 0x4 , & host - > regs - > nfc_ wrprot) ;
writew ( 0x4 , & host - > regs - > wrprot ) ;
/* NAND bus width determines access functions used by upper layer */
if ( is_16bit_nand ( ) )