2009-03-04 23:01:37 +03:00
/*
* davinci_nand . c - NAND Flash Driver for DaVinci family chips
*
* Copyright © 2006 Texas Instruments .
*
* Port to 2.6 .23 Copyright © 2008 by :
* Sander Huijsen < Shuijsen @ optelecom - nkf . com >
* Troy Kisky < troy . kisky @ boundarydevices . com >
* Dirk Behme < Dirk . Behme @ gmail . com >
*
* This program is free software ; you can redistribute it and / or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation ; either version 2 of the License , or
* ( at your option ) any later version .
*
* This program is distributed in the hope that it will be useful ,
* but WITHOUT ANY WARRANTY ; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE . See the
* GNU General Public License for more details .
*
* You should have received a copy of the GNU General Public License
* along with this program ; if not , write to the Free Software
* Foundation , Inc . , 675 Mass Ave , Cambridge , MA 0213 9 , USA .
*/
# include <linux/kernel.h>
# include <linux/init.h>
# include <linux/module.h>
# include <linux/platform_device.h>
# include <linux/err.h>
# include <linux/clk.h>
# include <linux/io.h>
# include <linux/mtd/nand.h>
# include <linux/mtd/partitions.h>
# include <mach/nand.h>
# include <asm/mach-types.h>
/*
* This is a device driver for the NAND flash controller found on the
* various DaVinci family chips . It handles up to four SoC chipselects ,
* and some flavors of secondary chipselect ( e . g . based on A12 ) as used
* with multichip packages .
*
2009-04-22 06:58:13 +04:00
* The 1 - bit ECC hardware is supported , as well as the newer 4 - bit ECC
2009-03-04 23:01:37 +03:00
* available on chips like the DM355 and OMAP - L137 and needed with the
* more error - prone MLC NAND chips .
*
* This driver assumes EM_WAIT connects all the NAND devices ' RDY / nBUSY
* outputs in a " wire-AND " configuration , with no per - chip signals .
*/
struct davinci_nand_info {
struct mtd_info mtd ;
struct nand_chip chip ;
2009-04-22 06:58:13 +04:00
struct nand_ecclayout ecclayout ;
2009-03-04 23:01:37 +03:00
struct device * dev ;
struct clk * clk ;
bool partitioned ;
2009-04-22 06:58:13 +04:00
bool is_readmode ;
2009-03-04 23:01:37 +03:00
void __iomem * base ;
void __iomem * vaddr ;
uint32_t ioaddr ;
uint32_t current_cs ;
uint32_t mask_chipsel ;
uint32_t mask_ale ;
uint32_t mask_cle ;
uint32_t core_chipsel ;
} ;
static DEFINE_SPINLOCK ( davinci_nand_lock ) ;
2009-04-22 06:58:13 +04:00
static bool ecc4_busy ;
2009-03-04 23:01:37 +03:00
# define to_davinci_nand(m) container_of(m, struct davinci_nand_info, mtd)
static inline unsigned int davinci_nand_readl ( struct davinci_nand_info * info ,
int offset )
{
return __raw_readl ( info - > base + offset ) ;
}
static inline void davinci_nand_writel ( struct davinci_nand_info * info ,
int offset , unsigned long value )
{
__raw_writel ( value , info - > base + offset ) ;
}
/*----------------------------------------------------------------------*/
/*
* Access to hardware control lines : ALE , CLE , secondary chipselect .
*/
static void nand_davinci_hwcontrol ( struct mtd_info * mtd , int cmd ,
unsigned int ctrl )
{
struct davinci_nand_info * info = to_davinci_nand ( mtd ) ;
uint32_t addr = info - > current_cs ;
struct nand_chip * nand = mtd - > priv ;
/* Did the control lines change? */
if ( ctrl & NAND_CTRL_CHANGE ) {
if ( ( ctrl & NAND_CTRL_CLE ) = = NAND_CTRL_CLE )
addr | = info - > mask_cle ;
else if ( ( ctrl & NAND_CTRL_ALE ) = = NAND_CTRL_ALE )
addr | = info - > mask_ale ;
nand - > IO_ADDR_W = ( void __iomem __force * ) addr ;
}
if ( cmd ! = NAND_CMD_NONE )
iowrite8 ( cmd , nand - > IO_ADDR_W ) ;
}
static void nand_davinci_select_chip ( struct mtd_info * mtd , int chip )
{
struct davinci_nand_info * info = to_davinci_nand ( mtd ) ;
uint32_t addr = info - > ioaddr ;
/* maybe kick in a second chipselect */
if ( chip > 0 )
addr | = info - > mask_chipsel ;
info - > current_cs = addr ;
info - > chip . IO_ADDR_W = ( void __iomem __force * ) addr ;
info - > chip . IO_ADDR_R = info - > chip . IO_ADDR_W ;
}
/*----------------------------------------------------------------------*/
/*
* 1 - bit hardware ECC . . . context maintained for each core chipselect
*/
static inline uint32_t nand_davinci_readecc_1bit ( struct mtd_info * mtd )
{
struct davinci_nand_info * info = to_davinci_nand ( mtd ) ;
return davinci_nand_readl ( info , NANDF1ECC_OFFSET
+ 4 * info - > core_chipsel ) ;
}
static void nand_davinci_hwctl_1bit ( struct mtd_info * mtd , int mode )
{
struct davinci_nand_info * info ;
uint32_t nandcfr ;
unsigned long flags ;
info = to_davinci_nand ( mtd ) ;
/* Reset ECC hardware */
nand_davinci_readecc_1bit ( mtd ) ;
spin_lock_irqsave ( & davinci_nand_lock , flags ) ;
/* Restart ECC hardware */
nandcfr = davinci_nand_readl ( info , NANDFCR_OFFSET ) ;
nandcfr | = BIT ( 8 + info - > core_chipsel ) ;
davinci_nand_writel ( info , NANDFCR_OFFSET , nandcfr ) ;
spin_unlock_irqrestore ( & davinci_nand_lock , flags ) ;
}
/*
* Read hardware ECC value and pack into three bytes
*/
static int nand_davinci_calculate_1bit ( struct mtd_info * mtd ,
const u_char * dat , u_char * ecc_code )
{
unsigned int ecc_val = nand_davinci_readecc_1bit ( mtd ) ;
unsigned int ecc24 = ( ecc_val & 0x0fff ) | ( ( ecc_val & 0x0fff0000 ) > > 4 ) ;
/* invert so that erased block ecc is correct */
ecc24 = ~ ecc24 ;
ecc_code [ 0 ] = ( u_char ) ( ecc24 ) ;
ecc_code [ 1 ] = ( u_char ) ( ecc24 > > 8 ) ;
ecc_code [ 2 ] = ( u_char ) ( ecc24 > > 16 ) ;
return 0 ;
}
static int nand_davinci_correct_1bit ( struct mtd_info * mtd , u_char * dat ,
u_char * read_ecc , u_char * calc_ecc )
{
struct nand_chip * chip = mtd - > priv ;
uint32_t eccNand = read_ecc [ 0 ] | ( read_ecc [ 1 ] < < 8 ) |
( read_ecc [ 2 ] < < 16 ) ;
uint32_t eccCalc = calc_ecc [ 0 ] | ( calc_ecc [ 1 ] < < 8 ) |
( calc_ecc [ 2 ] < < 16 ) ;
uint32_t diff = eccCalc ^ eccNand ;
if ( diff ) {
if ( ( ( ( diff > > 12 ) ^ diff ) & 0xfff ) = = 0xfff ) {
/* Correctable error */
if ( ( diff > > ( 12 + 3 ) ) < chip - > ecc . size ) {
dat [ diff > > ( 12 + 3 ) ] ^ = BIT ( ( diff > > 12 ) & 7 ) ;
return 1 ;
} else {
return - 1 ;
}
} else if ( ! ( diff & ( diff - 1 ) ) ) {
/* Single bit ECC error in the ECC itself,
* nothing to fix */
return 1 ;
} else {
/* Uncorrectable error */
return - 1 ;
}
}
return 0 ;
}
/*----------------------------------------------------------------------*/
2009-04-22 06:58:13 +04:00
/*
* 4 - bit hardware ECC . . . context maintained over entire AEMIF
*
* This is a syndrome engine , but we avoid NAND_ECC_HW_SYNDROME
* since that forces use of a problematic " infix OOB " layout .
* Among other things , it trashes manufacturer bad block markers .
* Also , and specific to this hardware , it ECC - protects the " prepad "
* in the OOB . . . while having ECC protection for parts of OOB would
* seem useful , the current MTD stack sometimes wants to update the
* OOB without recomputing ECC .
*/
static void nand_davinci_hwctl_4bit ( struct mtd_info * mtd , int mode )
{
struct davinci_nand_info * info = to_davinci_nand ( mtd ) ;
unsigned long flags ;
u32 val ;
spin_lock_irqsave ( & davinci_nand_lock , flags ) ;
/* Start 4-bit ECC calculation for read/write */
val = davinci_nand_readl ( info , NANDFCR_OFFSET ) ;
val & = ~ ( 0x03 < < 4 ) ;
val | = ( info - > core_chipsel < < 4 ) | BIT ( 12 ) ;
davinci_nand_writel ( info , NANDFCR_OFFSET , val ) ;
info - > is_readmode = ( mode = = NAND_ECC_READ ) ;
spin_unlock_irqrestore ( & davinci_nand_lock , flags ) ;
}
/* Read raw ECC code after writing to NAND. */
static void
nand_davinci_readecc_4bit ( struct davinci_nand_info * info , u32 code [ 4 ] )
{
const u32 mask = 0x03ff03ff ;
code [ 0 ] = davinci_nand_readl ( info , NAND_4BIT_ECC1_OFFSET ) & mask ;
code [ 1 ] = davinci_nand_readl ( info , NAND_4BIT_ECC2_OFFSET ) & mask ;
code [ 2 ] = davinci_nand_readl ( info , NAND_4BIT_ECC3_OFFSET ) & mask ;
code [ 3 ] = davinci_nand_readl ( info , NAND_4BIT_ECC4_OFFSET ) & mask ;
}
/* Terminate read ECC; or return ECC (as bytes) of data written to NAND. */
static int nand_davinci_calculate_4bit ( struct mtd_info * mtd ,
const u_char * dat , u_char * ecc_code )
{
struct davinci_nand_info * info = to_davinci_nand ( mtd ) ;
u32 raw_ecc [ 4 ] , * p ;
unsigned i ;
/* After a read, terminate ECC calculation by a dummy read
* of some 4 - bit ECC register . ECC covers everything that
* was read ; correct ( ) just uses the hardware state , so
* ecc_code is not needed .
*/
if ( info - > is_readmode ) {
davinci_nand_readl ( info , NAND_4BIT_ECC1_OFFSET ) ;
return 0 ;
}
/* Pack eight raw 10-bit ecc values into ten bytes, making
* two passes which each convert four values ( in upper and
* lower halves of two 32 - bit words ) into five bytes . The
* ROM boot loader uses this same packing scheme .
*/
nand_davinci_readecc_4bit ( info , raw_ecc ) ;
for ( i = 0 , p = raw_ecc ; i < 2 ; i + + , p + = 2 ) {
* ecc_code + + = p [ 0 ] & 0xff ;
* ecc_code + + = ( ( p [ 0 ] > > 8 ) & 0x03 ) | ( ( p [ 0 ] > > 14 ) & 0xfc ) ;
* ecc_code + + = ( ( p [ 0 ] > > 22 ) & 0x0f ) | ( ( p [ 1 ] < < 4 ) & 0xf0 ) ;
* ecc_code + + = ( ( p [ 1 ] > > 4 ) & 0x3f ) | ( ( p [ 1 ] > > 10 ) & 0xc0 ) ;
* ecc_code + + = ( p [ 1 ] > > 18 ) & 0xff ;
}
return 0 ;
}
/* Correct up to 4 bits in data we just read, using state left in the
* hardware plus the ecc_code computed when it was first written .
*/
static int nand_davinci_correct_4bit ( struct mtd_info * mtd ,
u_char * data , u_char * ecc_code , u_char * null )
{
int i ;
struct davinci_nand_info * info = to_davinci_nand ( mtd ) ;
unsigned short ecc10 [ 8 ] ;
unsigned short * ecc16 ;
u32 syndrome [ 4 ] ;
unsigned num_errors , corrected ;
/* All bytes 0xff? It's an erased page; ignore its ECC. */
for ( i = 0 ; i < 10 ; i + + ) {
if ( ecc_code [ i ] ! = 0xff )
goto compare ;
}
return 0 ;
compare :
/* Unpack ten bytes into eight 10 bit values. We know we're
* little - endian , and use type punning for less shifting / masking .
*/
if ( WARN_ON ( 0x01 & ( unsigned ) ecc_code ) )
return - EINVAL ;
ecc16 = ( unsigned short * ) ecc_code ;
ecc10 [ 0 ] = ( ecc16 [ 0 ] > > 0 ) & 0x3ff ;
ecc10 [ 1 ] = ( ( ecc16 [ 0 ] > > 10 ) & 0x3f ) | ( ( ecc16 [ 1 ] < < 6 ) & 0x3c0 ) ;
ecc10 [ 2 ] = ( ecc16 [ 1 ] > > 4 ) & 0x3ff ;
ecc10 [ 3 ] = ( ( ecc16 [ 1 ] > > 14 ) & 0x3 ) | ( ( ecc16 [ 2 ] < < 2 ) & 0x3fc ) ;
ecc10 [ 4 ] = ( ecc16 [ 2 ] > > 8 ) | ( ( ecc16 [ 3 ] < < 8 ) & 0x300 ) ;
ecc10 [ 5 ] = ( ecc16 [ 3 ] > > 2 ) & 0x3ff ;
ecc10 [ 6 ] = ( ( ecc16 [ 3 ] > > 12 ) & 0xf ) | ( ( ecc16 [ 4 ] < < 4 ) & 0x3f0 ) ;
ecc10 [ 7 ] = ( ecc16 [ 4 ] > > 6 ) & 0x3ff ;
/* Tell ECC controller about the expected ECC codes. */
for ( i = 7 ; i > = 0 ; i - - )
davinci_nand_writel ( info , NAND_4BIT_ECC_LOAD_OFFSET , ecc10 [ i ] ) ;
/* Allow time for syndrome calculation ... then read it.
* A syndrome of all zeroes 0 means no detected errors .
*/
davinci_nand_readl ( info , NANDFSR_OFFSET ) ;
nand_davinci_readecc_4bit ( info , syndrome ) ;
if ( ! ( syndrome [ 0 ] | syndrome [ 1 ] | syndrome [ 2 ] | syndrome [ 3 ] ) )
return 0 ;
2009-09-18 23:51:48 +04:00
/*
* Clear any previous address calculation by doing a dummy read of an
* error address register .
*/
davinci_nand_readl ( info , NAND_ERR_ADD1_OFFSET ) ;
2009-04-22 06:58:13 +04:00
/* Start address calculation, and wait for it to complete.
* We _could_ start reading more data while this is working ,
* to speed up the overall page read .
*/
davinci_nand_writel ( info , NANDFCR_OFFSET ,
davinci_nand_readl ( info , NANDFCR_OFFSET ) | BIT ( 13 ) ) ;
for ( ; ; ) {
u32 fsr = davinci_nand_readl ( info , NANDFSR_OFFSET ) ;
switch ( ( fsr > > 8 ) & 0x0f ) {
case 0 : /* no error, should not happen */
2009-09-18 23:51:48 +04:00
davinci_nand_readl ( info , NAND_ERR_ERRVAL1_OFFSET ) ;
2009-04-22 06:58:13 +04:00
return 0 ;
case 1 : /* five or more errors detected */
2009-09-18 23:51:48 +04:00
davinci_nand_readl ( info , NAND_ERR_ERRVAL1_OFFSET ) ;
2009-04-22 06:58:13 +04:00
return - EIO ;
case 2 : /* error addresses computed */
case 3 :
num_errors = 1 + ( ( fsr > > 16 ) & 0x03 ) ;
goto correct ;
default : /* still working on it */
cpu_relax ( ) ;
continue ;
}
}
correct :
/* correct each error */
for ( i = 0 , corrected = 0 ; i < num_errors ; i + + ) {
int error_address , error_value ;
if ( i > 1 ) {
error_address = davinci_nand_readl ( info ,
NAND_ERR_ADD2_OFFSET ) ;
error_value = davinci_nand_readl ( info ,
NAND_ERR_ERRVAL2_OFFSET ) ;
} else {
error_address = davinci_nand_readl ( info ,
NAND_ERR_ADD1_OFFSET ) ;
error_value = davinci_nand_readl ( info ,
NAND_ERR_ERRVAL1_OFFSET ) ;
}
if ( i & 1 ) {
error_address > > = 16 ;
error_value > > = 16 ;
}
error_address & = 0x3ff ;
error_address = ( 512 + 7 ) - error_address ;
if ( error_address < 512 ) {
data [ error_address ] ^ = error_value ;
corrected + + ;
}
}
return corrected ;
}
/*----------------------------------------------------------------------*/
2009-03-04 23:01:37 +03:00
/*
* NOTE : NAND boot requires ALE = = EM_A [ 1 ] , CLE = = EM_A [ 2 ] , so that ' s
* how these chips are normally wired . This translates to both 8 and 16
* bit busses using ALE = = BIT ( 3 ) in byte addresses , and CLE = = BIT ( 4 ) .
*
* For now we assume that configuration , or any other one which ignores
* the two LSBs for NAND access . . . so we can issue 32 - bit reads / writes
* and have that transparently morphed into multiple NAND operations .
*/
static void nand_davinci_read_buf ( struct mtd_info * mtd , uint8_t * buf , int len )
{
struct nand_chip * chip = mtd - > priv ;
if ( ( 0x03 & ( ( unsigned ) buf ) ) = = 0 & & ( 0x03 & len ) = = 0 )
ioread32_rep ( chip - > IO_ADDR_R , buf , len > > 2 ) ;
else if ( ( 0x01 & ( ( unsigned ) buf ) ) = = 0 & & ( 0x01 & len ) = = 0 )
ioread16_rep ( chip - > IO_ADDR_R , buf , len > > 1 ) ;
else
ioread8_rep ( chip - > IO_ADDR_R , buf , len ) ;
}
static void nand_davinci_write_buf ( struct mtd_info * mtd ,
const uint8_t * buf , int len )
{
struct nand_chip * chip = mtd - > priv ;
if ( ( 0x03 & ( ( unsigned ) buf ) ) = = 0 & & ( 0x03 & len ) = = 0 )
iowrite32_rep ( chip - > IO_ADDR_R , buf , len > > 2 ) ;
else if ( ( 0x01 & ( ( unsigned ) buf ) ) = = 0 & & ( 0x01 & len ) = = 0 )
iowrite16_rep ( chip - > IO_ADDR_R , buf , len > > 1 ) ;
else
iowrite8_rep ( chip - > IO_ADDR_R , buf , len ) ;
}
/*
* Check hardware register for wait status . Returns 1 if device is ready ,
* 0 if it is still busy .
*/
static int nand_davinci_dev_ready ( struct mtd_info * mtd )
{
struct davinci_nand_info * info = to_davinci_nand ( mtd ) ;
return davinci_nand_readl ( info , NANDFSR_OFFSET ) & BIT ( 0 ) ;
}
static void __init nand_dm6446evm_flash_init ( struct davinci_nand_info * info )
{
uint32_t regval , a1cr ;
/*
* NAND FLASH timings @ PLL1 = = 459 MHz
* - AEMIF . CLK freq = PLL1 / 6 = 459 / 6 = 76.5 MHz
* - AEMIF . CLK period = 1 / 76.5 MHz = 13.1 ns
*/
regval = 0
| ( 0 < < 31 ) /* selectStrobe */
| ( 0 < < 30 ) /* extWait (never with NAND) */
| ( 1 < < 26 ) /* writeSetup 10 ns */
| ( 3 < < 20 ) /* writeStrobe 40 ns */
| ( 1 < < 17 ) /* writeHold 10 ns */
| ( 0 < < 13 ) /* readSetup 10 ns */
| ( 3 < < 7 ) /* readStrobe 60 ns */
| ( 0 < < 4 ) /* readHold 10 ns */
| ( 3 < < 2 ) /* turnAround ?? ns */
| ( 0 < < 0 ) /* asyncSize 8-bit bus */
;
a1cr = davinci_nand_readl ( info , A1CR_OFFSET ) ;
if ( a1cr ! = regval ) {
dev_dbg ( info - > dev , " Warning: NAND config: Set A1CR " \
" reg to 0x%08x, was 0x%08x, should be done by " \
" bootloader. \n " , regval , a1cr ) ;
davinci_nand_writel ( info , A1CR_OFFSET , regval ) ;
}
}
/*----------------------------------------------------------------------*/
2009-04-22 06:58:13 +04:00
/* An ECC layout for using 4-bit ECC with small-page flash, storing
* ten ECC bytes plus the manufacturer ' s bad block marker byte , and
* and not overlapping the default BBT markers .
*/
static struct nand_ecclayout hwecc4_small __initconst = {
. eccbytes = 10 ,
. eccpos = { 0 , 1 , 2 , 3 , 4 ,
/* offset 5 holds the badblock marker */
6 , 7 ,
13 , 14 , 15 , } ,
. oobfree = {
{ . offset = 8 , . length = 5 , } ,
{ . offset = 16 , } ,
} ,
} ;
2009-09-18 23:51:48 +04:00
/* An ECC layout for using 4-bit ECC with large-page (2048bytes) flash,
* storing ten ECC bytes plus the manufacturer ' s bad block marker byte ,
* and not overlapping the default BBT markers .
*/
static struct nand_ecclayout hwecc4_2048 __initconst = {
. eccbytes = 40 ,
. eccpos = {
/* at the end of spare sector */
24 , 25 , 26 , 27 , 28 , 29 , 30 , 31 , 32 , 33 ,
34 , 35 , 36 , 37 , 38 , 39 , 40 , 41 , 42 , 43 ,
44 , 45 , 46 , 47 , 48 , 49 , 50 , 51 , 52 , 53 ,
54 , 55 , 56 , 57 , 58 , 59 , 60 , 61 , 62 , 63 ,
} ,
. oobfree = {
/* 2 bytes at offset 0 hold manufacturer badblock markers */
{ . offset = 2 , . length = 22 , } ,
/* 5 bytes at offset 8 hold BBT markers */
/* 8 bytes at offset 16 hold JFFS2 clean markers */
} ,
} ;
2009-04-22 06:58:13 +04:00
2009-03-04 23:01:37 +03:00
static int __init nand_davinci_probe ( struct platform_device * pdev )
{
struct davinci_nand_pdata * pdata = pdev - > dev . platform_data ;
struct davinci_nand_info * info ;
struct resource * res1 ;
struct resource * res2 ;
void __iomem * vaddr ;
void __iomem * base ;
int ret ;
uint32_t val ;
nand_ecc_modes_t ecc_mode ;
2009-04-22 06:51:31 +04:00
/* insist on board-specific configuration */
if ( ! pdata )
return - ENODEV ;
2009-03-04 23:01:37 +03:00
/* which external chipselect will we be managing? */
if ( pdev - > id < 0 | | pdev - > id > 3 )
return - ENODEV ;
info = kzalloc ( sizeof ( * info ) , GFP_KERNEL ) ;
if ( ! info ) {
dev_err ( & pdev - > dev , " unable to allocate memory \n " ) ;
ret = - ENOMEM ;
goto err_nomem ;
}
platform_set_drvdata ( pdev , info ) ;
res1 = platform_get_resource ( pdev , IORESOURCE_MEM , 0 ) ;
res2 = platform_get_resource ( pdev , IORESOURCE_MEM , 1 ) ;
if ( ! res1 | | ! res2 ) {
dev_err ( & pdev - > dev , " resource missing \n " ) ;
ret = - EINVAL ;
goto err_nomem ;
}
vaddr = ioremap ( res1 - > start , res1 - > end - res1 - > start ) ;
base = ioremap ( res2 - > start , res2 - > end - res2 - > start ) ;
if ( ! vaddr | | ! base ) {
dev_err ( & pdev - > dev , " ioremap failed \n " ) ;
ret = - EINVAL ;
goto err_ioremap ;
}
info - > dev = & pdev - > dev ;
info - > base = base ;
info - > vaddr = vaddr ;
info - > mtd . priv = & info - > chip ;
info - > mtd . name = dev_name ( & pdev - > dev ) ;
info - > mtd . owner = THIS_MODULE ;
2009-03-26 10:42:50 +03:00
info - > mtd . dev . parent = & pdev - > dev ;
2009-03-04 23:01:37 +03:00
info - > chip . IO_ADDR_R = vaddr ;
info - > chip . IO_ADDR_W = vaddr ;
info - > chip . chip_delay = 0 ;
info - > chip . select_chip = nand_davinci_select_chip ;
/* options such as NAND_USE_FLASH_BBT or 16-bit widths */
2009-04-22 06:51:31 +04:00
info - > chip . options = pdata - > options ;
2009-03-04 23:01:37 +03:00
info - > ioaddr = ( uint32_t __force ) vaddr ;
info - > current_cs = info - > ioaddr ;
info - > core_chipsel = pdev - > id ;
info - > mask_chipsel = pdata - > mask_chipsel ;
/* use nandboot-capable ALE/CLE masks by default */
2009-10-01 18:25:06 +04:00
info - > mask_ale = pdata - > mask_ale ? : MASK_ALE ;
2009-04-22 06:51:31 +04:00
info - > mask_cle = pdata - > mask_cle ? : MASK_CLE ;
2009-03-04 23:01:37 +03:00
/* Set address of hardware control function */
info - > chip . cmd_ctrl = nand_davinci_hwcontrol ;
info - > chip . dev_ready = nand_davinci_dev_ready ;
/* Speed up buffer I/O */
info - > chip . read_buf = nand_davinci_read_buf ;
info - > chip . write_buf = nand_davinci_write_buf ;
2009-04-22 06:51:31 +04:00
/* Use board-specific ECC config */
ecc_mode = pdata - > ecc_mode ;
2009-03-04 23:01:37 +03:00
2009-04-22 06:58:13 +04:00
ret = - EINVAL ;
2009-03-04 23:01:37 +03:00
switch ( ecc_mode ) {
case NAND_ECC_NONE :
case NAND_ECC_SOFT :
2009-04-22 06:58:13 +04:00
pdata - > ecc_bits = 0 ;
2009-03-04 23:01:37 +03:00
break ;
case NAND_ECC_HW :
2009-04-22 06:58:13 +04:00
if ( pdata - > ecc_bits = = 4 ) {
/* No sanity checks: CPUs must support this,
* and the chips may not use NAND_BUSWIDTH_16 .
*/
/* No sharing 4-bit hardware between chipselects yet */
spin_lock_irq ( & davinci_nand_lock ) ;
if ( ecc4_busy )
ret = - EBUSY ;
else
ecc4_busy = true ;
spin_unlock_irq ( & davinci_nand_lock ) ;
if ( ret = = - EBUSY )
goto err_ecc ;
info - > chip . ecc . calculate = nand_davinci_calculate_4bit ;
info - > chip . ecc . correct = nand_davinci_correct_4bit ;
info - > chip . ecc . hwctl = nand_davinci_hwctl_4bit ;
info - > chip . ecc . bytes = 10 ;
} else {
info - > chip . ecc . calculate = nand_davinci_calculate_1bit ;
info - > chip . ecc . correct = nand_davinci_correct_1bit ;
info - > chip . ecc . hwctl = nand_davinci_hwctl_1bit ;
info - > chip . ecc . bytes = 3 ;
}
2009-03-04 23:01:37 +03:00
info - > chip . ecc . size = 512 ;
break ;
default :
ret = - EINVAL ;
goto err_ecc ;
}
info - > chip . ecc . mode = ecc_mode ;
2009-06-05 21:48:08 +04:00
info - > clk = clk_get ( & pdev - > dev , " aemif " ) ;
2009-03-04 23:01:37 +03:00
if ( IS_ERR ( info - > clk ) ) {
ret = PTR_ERR ( info - > clk ) ;
2009-06-05 21:48:08 +04:00
dev_dbg ( & pdev - > dev , " unable to get AEMIF clock, err %d \n " , ret ) ;
2009-03-04 23:01:37 +03:00
goto err_clk ;
}
ret = clk_enable ( info - > clk ) ;
if ( ret < 0 ) {
2009-06-05 21:48:08 +04:00
dev_dbg ( & pdev - > dev , " unable to enable AEMIF clock, err %d \n " ,
ret ) ;
2009-03-04 23:01:37 +03:00
goto err_clk_enable ;
}
/* EMIF timings should normally be set by the boot loader,
* especially after boot - from - NAND . The * only * reason to
* have this special casing for the DM6446 EVM is to work
* with boot - from - NOR . . . with CS0 manually re - jumpered
* ( after startup ) so it addresses the NAND flash , not NOR .
* Even for dev boards , that ' s unusually rude . . .
*/
if ( machine_is_davinci_evm ( ) )
nand_dm6446evm_flash_init ( info ) ;
spin_lock_irq ( & davinci_nand_lock ) ;
/* put CSxNAND into NAND mode */
val = davinci_nand_readl ( info , NANDFCR_OFFSET ) ;
val | = BIT ( info - > core_chipsel ) ;
davinci_nand_writel ( info , NANDFCR_OFFSET , val ) ;
spin_unlock_irq ( & davinci_nand_lock ) ;
/* Scan to find existence of the device(s) */
2009-04-22 06:58:13 +04:00
ret = nand_scan_ident ( & info - > mtd , pdata - > mask_chipsel ? 2 : 1 ) ;
2009-03-04 23:01:37 +03:00
if ( ret < 0 ) {
dev_dbg ( & pdev - > dev , " no NAND chip(s) found \n " ) ;
goto err_scan ;
}
2009-04-22 06:58:13 +04:00
/* Update ECC layout if needed ... for 1-bit HW ECC, the default
* is OK , but it allocates 6 bytes when only 3 are needed ( for
* each 512 bytes ) . For the 4 - bit HW ECC , that default is not
* usable : 10 bytes are needed , not 6.
*/
if ( pdata - > ecc_bits = = 4 ) {
int chunks = info - > mtd . writesize / 512 ;
if ( ! chunks | | info - > mtd . oobsize < 16 ) {
dev_dbg ( & pdev - > dev , " too small \n " ) ;
ret = - EINVAL ;
goto err_scan ;
}
/* For small page chips, preserve the manufacturer's
* badblock marking data . . . and make sure a flash BBT
* table marker fits in the free bytes .
*/
if ( chunks = = 1 ) {
info - > ecclayout = hwecc4_small ;
info - > ecclayout . oobfree [ 1 ] . length =
info - > mtd . oobsize - 16 ;
goto syndrome_done ;
}
2009-09-18 23:51:48 +04:00
if ( chunks = = 4 ) {
info - > ecclayout = hwecc4_2048 ;
info - > chip . ecc . mode = NAND_ECC_HW_OOB_FIRST ;
goto syndrome_done ;
}
2009-04-22 06:58:13 +04:00
2009-09-18 23:51:48 +04:00
/* 4KiB page chips are not yet supported. The eccpos from
* nand_ecclayout cannot hold 80 bytes and change to eccpos [ ]
* breaks userspace ioctl interface with mtd - utils . Once we
* resolve this issue , NAND_ECC_HW_OOB_FIRST mode can be used
* for the 4 KiB page chips .
2009-04-22 06:58:13 +04:00
*/
dev_warn ( & pdev - > dev , " no 4-bit ECC support yet "
2009-09-18 23:51:48 +04:00
" for 4KiB-page NAND \n " ) ;
2009-04-22 06:58:13 +04:00
ret = - EIO ;
goto err_scan ;
syndrome_done :
info - > chip . ecc . layout = & info - > ecclayout ;
}
ret = nand_scan_tail ( & info - > mtd ) ;
if ( ret < 0 )
goto err_scan ;
2009-03-04 23:01:37 +03:00
if ( mtd_has_partitions ( ) ) {
struct mtd_partition * mtd_parts = NULL ;
int mtd_parts_nb = 0 ;
if ( mtd_has_cmdlinepart ( ) ) {
static const char * probes [ ] __initconst =
{ " cmdlinepart " , NULL } ;
mtd_parts_nb = parse_mtd_partitions ( & info - > mtd , probes ,
& mtd_parts , 0 ) ;
}
2009-04-22 06:51:31 +04:00
if ( mtd_parts_nb < = 0 ) {
2009-03-04 23:01:37 +03:00
mtd_parts = pdata - > parts ;
mtd_parts_nb = pdata - > nr_parts ;
}
/* Register any partitions */
if ( mtd_parts_nb > 0 ) {
ret = add_mtd_partitions ( & info - > mtd ,
mtd_parts , mtd_parts_nb ) ;
if ( ret = = 0 )
info - > partitioned = true ;
}
2009-04-22 06:51:31 +04:00
} else if ( pdata - > nr_parts ) {
2009-03-04 23:01:37 +03:00
dev_warn ( & pdev - > dev , " ignoring %d default partitions on %s \n " ,
pdata - > nr_parts , info - > mtd . name ) ;
}
/* If there's no partition info, just package the whole chip
* as a single MTD device .
*/
if ( ! info - > partitioned )
ret = add_mtd_device ( & info - > mtd ) ? - ENODEV : 0 ;
if ( ret < 0 )
goto err_scan ;
val = davinci_nand_readl ( info , NRCSR_OFFSET ) ;
dev_info ( & pdev - > dev , " controller rev. %d.%d \n " ,
( val > > 8 ) & 0xff , val & 0xff ) ;
return 0 ;
err_scan :
clk_disable ( info - > clk ) ;
err_clk_enable :
clk_put ( info - > clk ) ;
2009-04-22 06:58:13 +04:00
spin_lock_irq ( & davinci_nand_lock ) ;
if ( ecc_mode = = NAND_ECC_HW_SYNDROME )
ecc4_busy = false ;
spin_unlock_irq ( & davinci_nand_lock ) ;
2009-03-04 23:01:37 +03:00
err_ecc :
err_clk :
err_ioremap :
if ( base )
iounmap ( base ) ;
if ( vaddr )
iounmap ( vaddr ) ;
err_nomem :
kfree ( info ) ;
return ret ;
}
static int __exit nand_davinci_remove ( struct platform_device * pdev )
{
struct davinci_nand_info * info = platform_get_drvdata ( pdev ) ;
int status ;
if ( mtd_has_partitions ( ) & & info - > partitioned )
status = del_mtd_partitions ( & info - > mtd ) ;
else
status = del_mtd_device ( & info - > mtd ) ;
2009-04-22 06:58:13 +04:00
spin_lock_irq ( & davinci_nand_lock ) ;
if ( info - > chip . ecc . mode = = NAND_ECC_HW_SYNDROME )
ecc4_busy = false ;
spin_unlock_irq ( & davinci_nand_lock ) ;
2009-03-04 23:01:37 +03:00
iounmap ( info - > base ) ;
iounmap ( info - > vaddr ) ;
nand_release ( & info - > mtd ) ;
clk_disable ( info - > clk ) ;
clk_put ( info - > clk ) ;
kfree ( info ) ;
return 0 ;
}
static struct platform_driver nand_davinci_driver = {
. remove = __exit_p ( nand_davinci_remove ) ,
. driver = {
. name = " davinci_nand " ,
} ,
} ;
MODULE_ALIAS ( " platform:davinci_nand " ) ;
static int __init nand_davinci_init ( void )
{
return platform_driver_probe ( & nand_davinci_driver , nand_davinci_probe ) ;
}
module_init ( nand_davinci_init ) ;
static void __exit nand_davinci_exit ( void )
{
platform_driver_unregister ( & nand_davinci_driver ) ;
}
module_exit ( nand_davinci_exit ) ;
MODULE_LICENSE ( " GPL " ) ;
MODULE_AUTHOR ( " Texas Instruments " ) ;
MODULE_DESCRIPTION ( " Davinci NAND flash driver " ) ;