@ -3,7 +3,7 @@
* Platform independend driver for NDFC ( NanD Flash Controller )
* integrated into EP440 cores
*
* ( C ) Copyright 2006
* ( C ) Copyright 2006 - 2007
* Stefan Roese , DENX Software Engineering , sr @ denx . de .
*
* Based on original work by
@ -37,7 +37,9 @@
# include <nand.h>
# include <linux/mtd/ndfc.h>
# include <linux/mtd/nand_ecc.h>
# include <asm/processor.h>
# include <asm/io.h>
# include <ppc440.h>
static u8 hwctl = 0 ;
@ -69,11 +71,11 @@ static void ndfc_write_byte(struct mtd_info *mtdinfo, u_char byte)
ulong base = ( ulong ) this - > IO_ADDR_W & 0xfffffffc ;
if ( hwctl & 0x1 )
out8 ( base + NDFC_CMD , byte ) ;
out_ 8 ( ( u8 * ) ( base + NDFC_CMD ) , byte ) ;
else if ( hwctl & 0x2 )
out8 ( base + NDFC_ALE , byte ) ;
out_ 8 ( ( u8 * ) ( base + NDFC_ALE ) , byte ) ;
else
out8 ( base + NDFC_DATA , byte ) ;
out_ 8 ( ( u8 * ) ( base + NDFC_DATA ) , byte ) ;
}
static u_char ndfc_read_byte ( struct mtd_info * mtdinfo )
@ -81,7 +83,7 @@ static u_char ndfc_read_byte(struct mtd_info *mtdinfo)
struct nand_chip * this = mtdinfo - > priv ;
ulong base = ( ulong ) this - > IO_ADDR_W & 0xfffffffc ;
return ( in8 ( base + NDFC_DATA ) ) ;
return ( in_ 8 ( ( u8 * ) ( base + NDFC_DATA ) ) ) ;
}
static int ndfc_dev_ready ( struct mtd_info * mtdinfo )
@ -89,17 +91,41 @@ static int ndfc_dev_ready(struct mtd_info *mtdinfo)
struct nand_chip * this = mtdinfo - > priv ;
ulong base = ( ulong ) this - > IO_ADDR_W & 0xfffffffc ;
while ( ! ( in32 ( base + NDFC_STAT ) & NDFC_STAT_IS_READY ) )
while ( ! ( in_be 32 ( ( u32 * ) ( base + NDFC_STAT ) ) & NDFC_STAT_IS_READY ) )
;
return 1 ;
}
# ifndef CONFIG_NAND_SPL
/*
* Don ' t use these speedup functions in NAND boot image , since the image
* has to fit into 4 kByte .
*/
static void ndfc_enable_hwecc ( struct mtd_info * mtdinfo , int mode )
{
struct nand_chip * this = mtdinfo - > priv ;
ulong base = ( ulong ) this - > IO_ADDR_W & 0xfffffffc ;
u32 ccr ;
ccr = in_be32 ( ( u32 * ) ( base + NDFC_CCR ) ) ;
ccr | = NDFC_CCR_RESET_ECC ;
out_be32 ( ( u32 * ) ( base + NDFC_CCR ) , ccr ) ;
}
static int ndfc_calculate_ecc ( struct mtd_info * mtdinfo ,
const u_char * dat , u_char * ecc_code )
{
struct nand_chip * this = mtdinfo - > priv ;
ulong base = ( ulong ) this - > IO_ADDR_W & 0xfffffffc ;
u32 ecc ;
u8 * p = ( u8 * ) & ecc ;
ecc = in_be32 ( ( u32 * ) ( base + NDFC_ECC ) ) ;
/* The NDFC uses Smart Media (SMC) bytes order
*/
ecc_code [ 0 ] = p [ 2 ] ;
ecc_code [ 1 ] = p [ 1 ] ;
ecc_code [ 2 ] = p [ 3 ] ;
return 0 ;
}
/*
* Speedups for buffer read / write / verify
@ -115,9 +141,14 @@ static void ndfc_read_buf(struct mtd_info *mtdinfo, uint8_t *buf, int len)
uint32_t * p = ( uint32_t * ) buf ;
for ( ; len > 0 ; len - = 4 )
* p + + = in32 ( base + NDFC_DATA ) ;
* p + + = in_be 32 ( ( u32 * ) ( base + NDFC_DATA ) ) ;
}
# ifndef CONFIG_NAND_SPL
/*
* Don ' t use these speedup functions in NAND boot image , since the image
* has to fit into 4 kByte .
*/
static void ndfc_write_buf ( struct mtd_info * mtdinfo , const uint8_t * buf , int len )
{
struct nand_chip * this = mtdinfo - > priv ;
@ -125,7 +156,7 @@ static void ndfc_write_buf(struct mtd_info *mtdinfo, const uint8_t *buf, int len
uint32_t * p = ( uint32_t * ) buf ;
for ( ; len > 0 ; len - = 4 )
out32 ( base + NDFC_DATA , * p + + ) ;
out_be 32 ( ( u32 * ) ( base + NDFC_DATA ) , * p + + ) ;
}
static int ndfc_verify_buf ( struct mtd_info * mtdinfo , const uint8_t * buf , int len )
@ -135,7 +166,7 @@ static int ndfc_verify_buf(struct mtd_info *mtdinfo, const uint8_t *buf, int len
uint32_t * p = ( uint32_t * ) buf ;
for ( ; len > 0 ; len - = 4 )
if ( * p + + ! = in32 ( base + NDFC_DATA ) )
if ( * p + + ! = in_be 32 ( ( u32 * ) ( base + NDFC_DATA ) ) )
return - 1 ;
return 0 ;
@ -152,8 +183,8 @@ void board_nand_select_device(struct nand_chip *nand, int chip)
ulong base = ( ulong ) nand - > IO_ADDR_W & 0xfffffffc ;
/* Set NandFlash Core Configuration Register */
/* 1col x 2 rows */
out32 ( base + NDFC_CCR , 0x00000000 | ( cs < < 24 ) ) ;
/* 1 col x 2 rows */
out_be 32 ( ( u32 * ) ( base + NDFC_CCR ) , 0x00000000 | ( cs < < 24 ) ) ;
}
int board_nand_init ( struct nand_chip * nand )
@ -161,16 +192,19 @@ int board_nand_init(struct nand_chip *nand)
int cs = ( ulong ) nand - > IO_ADDR_W & 0x00000003 ;
ulong base = ( ulong ) nand - > IO_ADDR_W & 0xfffffffc ;
nand - > eccmode = NAND_ECC_SOFT ;
nand - > hwcontrol = ndfc_hwcontrol ;
nand - > read_byte = ndfc_read_byte ;
nand - > read_buf = ndfc_read_buf ;
nand - > write_byte = ndfc_write_byte ;
nand - > dev_ready = ndfc_dev_ready ;
nand - > eccmode = NAND_ECC_HW3_256 ;
nand - > enable_hwecc = ndfc_enable_hwecc ;
nand - > calculate_ecc = ndfc_calculate_ecc ;
nand - > correct_data = nand_correct_data ;
# ifndef CONFIG_NAND_SPL
nand - > write_buf = ndfc_write_buf ;
nand - > read_buf = ndfc_read_buf ;
nand - > verify_buf = ndfc_verify_buf ;
# else
/*
@ -187,7 +221,7 @@ int board_nand_init(struct nand_chip *nand)
* Select required NAND chip in NDFC
*/
board_nand_select_device ( nand , cs ) ;
out32 ( base + NDFC_BCFG0 + ( cs < < 2 ) , 0x80002222 ) ;
out_be 32 ( ( u32 * ) ( base + NDFC_BCFG0 + ( cs < < 2 ) ) , 0x80002222 ) ;
return 0 ;
}