2006-01-08 13:34:22 -08:00
/*
* Atmel AT45xxx DataFlash MTD driver for lightweight SPI framework
*
* Largely derived from at91_dataflash . c :
* Copyright ( C ) 2003 - 2005 SAN People ( Pty ) Ltd
*
* 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 .
*/
# include <linux/module.h>
# include <linux/init.h>
# include <linux/slab.h>
# include <linux/delay.h>
# include <linux/device.h>
2007-06-28 22:58:42 +01:00
# include <linux/mutex.h>
2008-07-29 22:22:40 -07:00
# include <linux/err.h>
2008-12-18 14:09:56 +02:00
# include <linux/math64.h>
2011-07-15 16:38:56 +08:00
# include <linux/of.h>
# include <linux/of_device.h>
2008-07-29 22:22:40 -07:00
2006-01-08 13:34:22 -08:00
# include <linux/spi/spi.h>
# include <linux/spi/flash.h>
# include <linux/mtd/mtd.h>
# include <linux/mtd/partitions.h>
/*
* DataFlash is a kind of SPI flash . Most AT45 chips have two buffers in
* each chip , which may be used for double buffered I / O ; but this driver
* doesn ' t ( yet ) use these for any kind of i / o overlap or prefetching .
*
* Sometimes DataFlash is packaged in MMC - format cards , although the
2008-08-06 21:55:14 -07:00
* MMC stack can ' t ( yet ? ) distinguish between MMC and DataFlash
2006-01-08 13:34:22 -08:00
* protocols during enumeration .
*/
/* reads can bypass the buffers */
# define OP_READ_CONTINUOUS 0xE8
# define OP_READ_PAGE 0xD2
/* group B requests can run even while status reports "busy" */
# define OP_READ_STATUS 0xD7 /* group B */
/* move data between host and buffer */
# define OP_READ_BUFFER1 0xD4 /* group B */
# define OP_READ_BUFFER2 0xD6 /* group B */
# define OP_WRITE_BUFFER1 0x84 /* group B */
# define OP_WRITE_BUFFER2 0x87 /* group B */
/* erasing flash */
# define OP_ERASE_PAGE 0x81
# define OP_ERASE_BLOCK 0x50
/* move data between buffer and flash */
# define OP_TRANSFER_BUF1 0x53
# define OP_TRANSFER_BUF2 0x55
# define OP_MREAD_BUFFER1 0xD4
# define OP_MREAD_BUFFER2 0xD6
# define OP_MWERASE_BUFFER1 0x83
# define OP_MWERASE_BUFFER2 0x86
# define OP_MWRITE_BUFFER1 0x88 /* sector must be pre-erased */
# define OP_MWRITE_BUFFER2 0x89 /* sector must be pre-erased */
/* write to buffer, then write-erase to flash */
# define OP_PROGRAM_VIA_BUF1 0x82
# define OP_PROGRAM_VIA_BUF2 0x85
/* compare buffer to flash */
# define OP_COMPARE_BUF1 0x60
# define OP_COMPARE_BUF2 0x61
/* read flash to buffer, then write-erase to flash */
# define OP_REWRITE_VIA_BUF1 0x58
# define OP_REWRITE_VIA_BUF2 0x59
/* newer chips report JEDEC manufacturer and device IDs; chip
* serial number and OTP bits ; and per - sector writeprotect .
*/
# define OP_READ_ID 0x9F
# define OP_READ_SECURITY 0x77
2008-07-30 12:35:05 -07:00
# define OP_WRITE_SECURITY_REVC 0x9A
# define OP_WRITE_SECURITY 0x9B /* revision D */
2006-01-08 13:34:22 -08:00
struct dataflash {
2008-06-04 17:43:22 +01:00
uint8_t command [ 4 ] ;
2006-01-08 13:34:22 -08:00
char name [ 24 ] ;
unsigned partitioned : 1 ;
unsigned short page_offset ; /* offset in flash address */
unsigned int page_size ; /* of bytes per page */
2007-06-28 22:58:42 +01:00
struct mutex lock ;
2006-01-08 13:34:22 -08:00
struct spi_device * spi ;
struct mtd_info mtd ;
} ;
2011-07-15 16:38:56 +08:00
# ifdef CONFIG_OF
static const struct of_device_id dataflash_dt_ids [ ] = {
{ . compatible = " atmel,at45 " , } ,
{ . compatible = " atmel,dataflash " , } ,
{ /* sentinel */ }
} ;
# endif
2006-01-08 13:34:22 -08:00
/* ......................................................................... */
/*
* Return the status of the DataFlash device .
*/
static inline int dataflash_status ( struct spi_device * spi )
{
/* NOTE: at45db321c over 25 MHz wants to write
* a dummy byte after the opcode . . .
*/
return spi_w8r8 ( spi , OP_READ_STATUS ) ;
}
/*
* Poll the DataFlash device until it is READY .
* This usually takes 5 - 20 msec or so ; more for sector erase .
*/
static int dataflash_waitready ( struct spi_device * spi )
{
int status ;
for ( ; ; ) {
status = dataflash_status ( spi ) ;
if ( status < 0 ) {
2011-07-19 10:06:09 -07:00
pr_debug ( " %s: status %d? \n " ,
2008-12-23 10:00:14 +00:00
dev_name ( & spi - > dev ) , status ) ;
2006-01-08 13:34:22 -08:00
status = 0 ;
}
if ( status & ( 1 < < 7 ) ) /* RDY/nBSY */
return status ;
msleep ( 3 ) ;
}
}
/* ......................................................................... */
/*
* Erase pages of flash .
*/
static int dataflash_erase ( struct mtd_info * mtd , struct erase_info * instr )
{
2010-06-29 14:15:13 +04:00
struct dataflash * priv = mtd - > priv ;
2006-01-08 13:34:22 -08:00
struct spi_device * spi = priv - > spi ;
2006-01-08 13:34:28 -08:00
struct spi_transfer x = { . tx_dma = 0 , } ;
2006-01-08 13:34:22 -08:00
struct spi_message msg ;
unsigned blocksize = priv - > page_size < < 3 ;
2008-06-04 17:43:22 +01:00
uint8_t * command ;
2008-12-18 14:09:56 +02:00
uint32_t rem ;
2006-01-08 13:34:22 -08:00
2011-07-19 10:06:09 -07:00
pr_debug ( " %s: erase addr=0x%llx len 0x%llx \n " ,
2008-12-23 10:00:14 +00:00
dev_name ( & spi - > dev ) , ( long long ) instr - > addr ,
( long long ) instr - > len ) ;
2006-01-08 13:34:22 -08:00
2008-12-18 14:09:56 +02:00
div_u64_rem ( instr - > len , priv - > page_size , & rem ) ;
if ( rem )
return - EINVAL ;
div_u64_rem ( instr - > addr , priv - > page_size , & rem ) ;
if ( rem )
2006-01-08 13:34:22 -08:00
return - EINVAL ;
2006-01-08 13:34:28 -08:00
spi_message_init ( & msg ) ;
x . tx_buf = command = priv - > command ;
x . len = 4 ;
spi_message_add_tail ( & x , & msg ) ;
2006-01-08 13:34:22 -08:00
2007-06-28 22:58:42 +01:00
mutex_lock ( & priv - > lock ) ;
2006-01-08 13:34:22 -08:00
while ( instr - > len > 0 ) {
unsigned int pageaddr ;
int status ;
int do_block ;
/* Calculate flash page address; use block erase (for speed) if
* we ' re at a block boundary and need to erase the whole block .
*/
2009-05-18 11:13:54 +01:00
pageaddr = div_u64 ( instr - > addr , priv - > page_size ) ;
2006-03-13 21:20:40 -08:00
do_block = ( pageaddr & 0x7 ) = = 0 & & instr - > len > = blocksize ;
2006-01-08 13:34:22 -08:00
pageaddr = pageaddr < < priv - > page_offset ;
command [ 0 ] = do_block ? OP_ERASE_BLOCK : OP_ERASE_PAGE ;
2008-06-04 17:43:22 +01:00
command [ 1 ] = ( uint8_t ) ( pageaddr > > 16 ) ;
command [ 2 ] = ( uint8_t ) ( pageaddr > > 8 ) ;
2006-01-08 13:34:22 -08:00
command [ 3 ] = 0 ;
2011-07-19 10:06:09 -07:00
pr_debug ( " ERASE %s: (%x) %x %x %x [%i] \n " ,
2006-01-08 13:34:22 -08:00
do_block ? " block " : " page " ,
command [ 0 ] , command [ 1 ] , command [ 2 ] , command [ 3 ] ,
pageaddr ) ;
status = spi_sync ( spi , & msg ) ;
( void ) dataflash_waitready ( spi ) ;
if ( status < 0 ) {
printk ( KERN_ERR " %s: erase %x, err %d \n " ,
2008-12-23 10:00:14 +00:00
dev_name ( & spi - > dev ) , pageaddr , status ) ;
2006-01-08 13:34:22 -08:00
/* REVISIT: can retry instr->retries times; or
* giveup and instr - > fail_addr = instr - > addr ;
*/
continue ;
}
if ( do_block ) {
instr - > addr + = blocksize ;
instr - > len - = blocksize ;
} else {
instr - > addr + = priv - > page_size ;
instr - > len - = priv - > page_size ;
}
}
2007-06-28 22:58:42 +01:00
mutex_unlock ( & priv - > lock ) ;
2006-01-08 13:34:22 -08:00
/* Inform MTD subsystem that erase is complete */
instr - > state = MTD_ERASE_DONE ;
mtd_erase_callback ( instr ) ;
return 0 ;
}
/*
* Read from the DataFlash device .
* from : Start offset in flash device
* len : Amount to read
* retlen : About of data actually read
* buf : Buffer containing the data
*/
static int dataflash_read ( struct mtd_info * mtd , loff_t from , size_t len ,
size_t * retlen , u_char * buf )
{
2010-06-29 14:15:13 +04:00
struct dataflash * priv = mtd - > priv ;
2006-01-08 13:34:22 -08:00
struct spi_transfer x [ 2 ] = { { . tx_dma = 0 , } , } ;
struct spi_message msg ;
unsigned int addr ;
2008-06-04 17:43:22 +01:00
uint8_t * command ;
2006-01-08 13:34:22 -08:00
int status ;
2011-07-19 10:06:10 -07:00
pr_debug ( " %s: read 0x%x..0x%x \n " , dev_name ( & priv - > spi - > dev ) ,
( unsigned ) from , ( unsigned ) ( from + len ) ) ;
2006-01-08 13:34:22 -08:00
/* Calculate flash page/byte address */
addr = ( ( ( unsigned ) from / priv - > page_size ) < < priv - > page_offset )
+ ( ( unsigned ) from % priv - > page_size ) ;
command = priv - > command ;
2011-07-19 10:06:09 -07:00
pr_debug ( " READ: (%x) %x %x %x \n " ,
2006-01-08 13:34:22 -08:00
command [ 0 ] , command [ 1 ] , command [ 2 ] , command [ 3 ] ) ;
2006-01-08 13:34:28 -08:00
spi_message_init ( & msg ) ;
2006-01-08 13:34:22 -08:00
x [ 0 ] . tx_buf = command ;
x [ 0 ] . len = 8 ;
2006-01-08 13:34:28 -08:00
spi_message_add_tail ( & x [ 0 ] , & msg ) ;
2006-01-08 13:34:22 -08:00
x [ 1 ] . rx_buf = buf ;
x [ 1 ] . len = len ;
2006-01-08 13:34:28 -08:00
spi_message_add_tail ( & x [ 1 ] , & msg ) ;
2006-01-08 13:34:22 -08:00
2007-06-28 22:58:42 +01:00
mutex_lock ( & priv - > lock ) ;
2006-01-08 13:34:22 -08:00
/* Continuous read, max clock = f(car) which may be less than
* the peak rate available . Some chips support commands with
* fewer " don't care " bytes . Both buffers stay unchanged .
*/
command [ 0 ] = OP_READ_CONTINUOUS ;
2008-06-04 17:43:22 +01:00
command [ 1 ] = ( uint8_t ) ( addr > > 16 ) ;
command [ 2 ] = ( uint8_t ) ( addr > > 8 ) ;
command [ 3 ] = ( uint8_t ) ( addr > > 0 ) ;
2006-01-08 13:34:22 -08:00
/* plus 4 "don't care" bytes */
status = spi_sync ( priv - > spi , & msg ) ;
2007-06-28 22:58:42 +01:00
mutex_unlock ( & priv - > lock ) ;
2006-01-08 13:34:22 -08:00
if ( status > = 0 ) {
* retlen = msg . actual_length - 8 ;
status = 0 ;
} else
2011-07-19 10:06:09 -07:00
pr_debug ( " %s: read %x..%x --> %d \n " ,
2008-12-23 10:00:14 +00:00
dev_name ( & priv - > spi - > dev ) ,
2006-01-08 13:34:22 -08:00
( unsigned ) from , ( unsigned ) ( from + len ) ,
status ) ;
return status ;
}
/*
* Write to the DataFlash device .
* to : Start offset in flash device
* len : Amount to write
* retlen : Amount of data actually written
* buf : Buffer containing the data
*/
static int dataflash_write ( struct mtd_info * mtd , loff_t to , size_t len ,
size_t * retlen , const u_char * buf )
{
2010-06-29 14:15:13 +04:00
struct dataflash * priv = mtd - > priv ;
2006-01-08 13:34:22 -08:00
struct spi_device * spi = priv - > spi ;
struct spi_transfer x [ 2 ] = { { . tx_dma = 0 , } , } ;
struct spi_message msg ;
unsigned int pageaddr , addr , offset , writelen ;
size_t remaining = len ;
u_char * writebuf = ( u_char * ) buf ;
int status = - EINVAL ;
2008-06-04 17:43:22 +01:00
uint8_t * command ;
2006-01-08 13:34:22 -08:00
2011-07-19 10:06:09 -07:00
pr_debug ( " %s: write 0x%x..0x%x \n " ,
2008-12-23 10:00:14 +00:00
dev_name ( & spi - > dev ) , ( unsigned ) to , ( unsigned ) ( to + len ) ) ;
2006-01-08 13:34:22 -08:00
2006-01-08 13:34:28 -08:00
spi_message_init ( & msg ) ;
2006-01-08 13:34:22 -08:00
x [ 0 ] . tx_buf = command = priv - > command ;
x [ 0 ] . len = 4 ;
2006-01-08 13:34:28 -08:00
spi_message_add_tail ( & x [ 0 ] , & msg ) ;
2006-01-08 13:34:22 -08:00
pageaddr = ( ( unsigned ) to / priv - > page_size ) ;
offset = ( ( unsigned ) to % priv - > page_size ) ;
if ( offset + len > priv - > page_size )
writelen = priv - > page_size - offset ;
else
writelen = len ;
2007-06-28 22:58:42 +01:00
mutex_lock ( & priv - > lock ) ;
2006-01-08 13:34:22 -08:00
while ( remaining > 0 ) {
2011-07-19 10:06:09 -07:00
pr_debug ( " write @ %i:%i len=%i \n " ,
2006-01-08 13:34:22 -08:00
pageaddr , offset , writelen ) ;
/* REVISIT:
* ( a ) each page in a sector must be rewritten at least
* once every 10 K sibling erase / program operations .
* ( b ) for pages that are already erased , we could
* use WRITE + MWRITE not PROGRAM for ~ 30 % speedup .
* ( c ) WRITE to buffer could be done while waiting for
* a previous MWRITE / MWERASE to complete . . .
* ( d ) error handling here seems to be mostly missing .
*
* Two persistent bits per page , plus a per - sector counter ,
* could support ( a ) and ( b ) . . . we might consider using
* the second half of sector zero , which is just one block ,
* to track that state . ( On AT91 , that sector should also
* support boot - from - DataFlash . )
*/
addr = pageaddr < < priv - > page_offset ;
/* (1) Maybe transfer partial page to Buffer1 */
if ( writelen ! = priv - > page_size ) {
command [ 0 ] = OP_TRANSFER_BUF1 ;
command [ 1 ] = ( addr & 0x00FF0000 ) > > 16 ;
command [ 2 ] = ( addr & 0x0000FF00 ) > > 8 ;
command [ 3 ] = 0 ;
2011-07-19 10:06:09 -07:00
pr_debug ( " TRANSFER: (%x) %x %x %x \n " ,
2006-01-08 13:34:22 -08:00
command [ 0 ] , command [ 1 ] , command [ 2 ] , command [ 3 ] ) ;
status = spi_sync ( spi , & msg ) ;
if ( status < 0 )
2011-07-19 10:06:10 -07:00
pr_debug ( " %s: xfer %u -> %d \n " ,
2008-12-23 10:00:14 +00:00
dev_name ( & spi - > dev ) , addr , status ) ;
2006-01-08 13:34:22 -08:00
( void ) dataflash_waitready ( priv - > spi ) ;
}
/* (2) Program full page via Buffer1 */
addr + = offset ;
command [ 0 ] = OP_PROGRAM_VIA_BUF1 ;
command [ 1 ] = ( addr & 0x00FF0000 ) > > 16 ;
command [ 2 ] = ( addr & 0x0000FF00 ) > > 8 ;
command [ 3 ] = ( addr & 0x000000FF ) ;
2011-07-19 10:06:09 -07:00
pr_debug ( " PROGRAM: (%x) %x %x %x \n " ,
2006-01-08 13:34:22 -08:00
command [ 0 ] , command [ 1 ] , command [ 2 ] , command [ 3 ] ) ;
x [ 1 ] . tx_buf = writebuf ;
x [ 1 ] . len = writelen ;
2006-01-08 13:34:28 -08:00
spi_message_add_tail ( x + 1 , & msg ) ;
2006-01-08 13:34:22 -08:00
status = spi_sync ( spi , & msg ) ;
2006-01-08 13:34:28 -08:00
spi_transfer_del ( x + 1 ) ;
2006-01-08 13:34:22 -08:00
if ( status < 0 )
2011-07-19 10:06:10 -07:00
pr_debug ( " %s: pgm %u/%u -> %d \n " ,
2008-12-23 10:00:14 +00:00
dev_name ( & spi - > dev ) , addr , writelen , status ) ;
2006-01-08 13:34:22 -08:00
( void ) dataflash_waitready ( priv - > spi ) ;
2006-01-08 13:34:28 -08:00
2009-07-19 21:19:08 -04:00
# ifdef CONFIG_MTD_DATAFLASH_WRITE_VERIFY
2006-01-08 13:34:22 -08:00
/* (3) Compare to Buffer1 */
addr = pageaddr < < priv - > page_offset ;
command [ 0 ] = OP_COMPARE_BUF1 ;
command [ 1 ] = ( addr & 0x00FF0000 ) > > 16 ;
command [ 2 ] = ( addr & 0x0000FF00 ) > > 8 ;
command [ 3 ] = 0 ;
2011-07-19 10:06:09 -07:00
pr_debug ( " COMPARE: (%x) %x %x %x \n " ,
2006-01-08 13:34:22 -08:00
command [ 0 ] , command [ 1 ] , command [ 2 ] , command [ 3 ] ) ;
status = spi_sync ( spi , & msg ) ;
if ( status < 0 )
2011-07-19 10:06:10 -07:00
pr_debug ( " %s: compare %u -> %d \n " ,
2008-12-23 10:00:14 +00:00
dev_name ( & spi - > dev ) , addr , status ) ;
2006-01-08 13:34:22 -08:00
status = dataflash_waitready ( priv - > spi ) ;
/* Check result of the compare operation */
2007-11-19 15:37:23 +02:00
if ( status & ( 1 < < 6 ) ) {
2006-01-08 13:34:22 -08:00
printk ( KERN_ERR " %s: compare page %u, err %d \n " ,
2008-12-23 10:00:14 +00:00
dev_name ( & spi - > dev ) , pageaddr , status ) ;
2006-01-08 13:34:22 -08:00
remaining = 0 ;
status = - EIO ;
break ;
} else
status = 0 ;
2009-07-19 21:19:08 -04:00
# endif /* CONFIG_MTD_DATAFLASH_WRITE_VERIFY */
2006-01-08 13:34:22 -08:00
remaining = remaining - writelen ;
pageaddr + + ;
offset = 0 ;
writebuf + = writelen ;
* retlen + = writelen ;
if ( remaining > priv - > page_size )
writelen = priv - > page_size ;
else
writelen = remaining ;
}
2007-06-28 22:58:42 +01:00
mutex_unlock ( & priv - > lock ) ;
2006-01-08 13:34:22 -08:00
return status ;
}
/* ......................................................................... */
2008-07-30 12:35:05 -07:00
# ifdef CONFIG_MTD_DATAFLASH_OTP
static int dataflash_get_otp_info ( struct mtd_info * mtd ,
struct otp_info * info , size_t len )
{
/* Report both blocks as identical: bytes 0..64, locked.
* Unless the user block changed from all - ones , we can ' t
* tell whether it ' s still writable ; so we assume it isn ' t .
*/
info - > start = 0 ;
info - > length = 64 ;
info - > locked = 1 ;
return sizeof ( * info ) ;
}
static ssize_t otp_read ( struct spi_device * spi , unsigned base ,
uint8_t * buf , loff_t off , size_t len )
{
struct spi_message m ;
size_t l ;
uint8_t * scratch ;
struct spi_transfer t ;
int status ;
if ( off > 64 )
return - EINVAL ;
if ( ( off + len ) > 64 )
len = 64 - off ;
spi_message_init ( & m ) ;
l = 4 + base + off + len ;
scratch = kzalloc ( l , GFP_KERNEL ) ;
if ( ! scratch )
return - ENOMEM ;
/* OUT: OP_READ_SECURITY, 3 don't-care bytes, zeroes
* IN : ignore 4 bytes , data bytes 0. . N ( max 127 )
*/
scratch [ 0 ] = OP_READ_SECURITY ;
memset ( & t , 0 , sizeof t ) ;
t . tx_buf = scratch ;
t . rx_buf = scratch ;
t . len = l ;
spi_message_add_tail ( & t , & m ) ;
dataflash_waitready ( spi ) ;
status = spi_sync ( spi , & m ) ;
if ( status > = 0 ) {
memcpy ( buf , scratch + 4 + base + off , len ) ;
status = len ;
}
kfree ( scratch ) ;
return status ;
}
static int dataflash_read_fact_otp ( struct mtd_info * mtd ,
loff_t from , size_t len , size_t * retlen , u_char * buf )
{
2010-06-29 14:15:13 +04:00
struct dataflash * priv = mtd - > priv ;
2008-07-30 12:35:05 -07:00
int status ;
/* 64 bytes, from 0..63 ... start at 64 on-chip */
mutex_lock ( & priv - > lock ) ;
status = otp_read ( priv - > spi , 64 , buf , from , len ) ;
mutex_unlock ( & priv - > lock ) ;
if ( status < 0 )
return status ;
* retlen = status ;
return 0 ;
}
static int dataflash_read_user_otp ( struct mtd_info * mtd ,
loff_t from , size_t len , size_t * retlen , u_char * buf )
{
2010-06-29 14:15:13 +04:00
struct dataflash * priv = mtd - > priv ;
2008-07-30 12:35:05 -07:00
int status ;
/* 64 bytes, from 0..63 ... start at 0 on-chip */
mutex_lock ( & priv - > lock ) ;
status = otp_read ( priv - > spi , 0 , buf , from , len ) ;
mutex_unlock ( & priv - > lock ) ;
if ( status < 0 )
return status ;
* retlen = status ;
return 0 ;
}
static int dataflash_write_user_otp ( struct mtd_info * mtd ,
loff_t from , size_t len , size_t * retlen , u_char * buf )
{
struct spi_message m ;
const size_t l = 4 + 64 ;
uint8_t * scratch ;
struct spi_transfer t ;
2010-06-29 14:15:13 +04:00
struct dataflash * priv = mtd - > priv ;
2008-07-30 12:35:05 -07:00
int status ;
if ( len > 64 )
return - EINVAL ;
/* Strictly speaking, we *could* truncate the write ... but
* let ' s not do that for the only write that ' s ever possible .
*/
if ( ( from + len ) > 64 )
return - EINVAL ;
/* OUT: OP_WRITE_SECURITY, 3 zeroes, 64 data-or-zero bytes
* IN : ignore all
*/
scratch = kzalloc ( l , GFP_KERNEL ) ;
if ( ! scratch )
return - ENOMEM ;
scratch [ 0 ] = OP_WRITE_SECURITY ;
memcpy ( scratch + 4 + from , buf , len ) ;
spi_message_init ( & m ) ;
memset ( & t , 0 , sizeof t ) ;
t . tx_buf = scratch ;
t . len = l ;
spi_message_add_tail ( & t , & m ) ;
/* Write the OTP bits, if they've not yet been written.
* This modifies SRAM buffer1 .
*/
mutex_lock ( & priv - > lock ) ;
dataflash_waitready ( priv - > spi ) ;
status = spi_sync ( priv - > spi , & m ) ;
mutex_unlock ( & priv - > lock ) ;
kfree ( scratch ) ;
if ( status > = 0 ) {
status = 0 ;
* retlen = len ;
}
return status ;
}
static char * otp_setup ( struct mtd_info * device , char revision )
{
2012-01-30 14:58:32 +02:00
device - > _get_fact_prot_info = dataflash_get_otp_info ;
device - > _read_fact_prot_reg = dataflash_read_fact_otp ;
device - > _get_user_prot_info = dataflash_get_otp_info ;
device - > _read_user_prot_reg = dataflash_read_user_otp ;
2008-07-30 12:35:05 -07:00
/* rev c parts (at45db321c and at45db1281 only!) use a
* different write procedure ; not ( yet ? ) implemented .
*/
if ( revision > ' c ' )
2012-01-30 14:58:32 +02:00
device - > _write_user_prot_reg = dataflash_write_user_otp ;
2008-07-30 12:35:05 -07:00
return " , OTP " ;
}
# else
2008-08-06 13:12:04 -07:00
static char * otp_setup ( struct mtd_info * device , char revision )
2008-07-30 12:35:05 -07:00
{
return " (OTP) " ;
}
# endif
/* ......................................................................... */
2006-01-08 13:34:22 -08:00
/*
* Register DataFlash device with MTD subsystem .
*/
2012-12-21 13:19:05 -08:00
static int add_dataflash_otp ( struct spi_device * spi , char * name , int nr_pages ,
int pagesize , int pageoffset , char revision )
2006-01-08 13:34:22 -08:00
{
struct dataflash * priv ;
struct mtd_info * device ;
2011-07-15 16:38:56 +08:00
struct mtd_part_parser_data ppdata ;
2006-01-08 13:34:22 -08:00
struct flash_platform_data * pdata = spi - > dev . platform_data ;
2008-07-30 12:35:05 -07:00
char * otp_tag = " " ;
2009-10-07 17:08:08 -04:00
int err = 0 ;
2006-01-08 13:34:22 -08:00
2006-12-13 00:35:56 -08:00
priv = kzalloc ( sizeof * priv , GFP_KERNEL ) ;
2006-01-08 13:34:22 -08:00
if ( ! priv )
return - ENOMEM ;
2007-06-28 22:58:42 +01:00
mutex_init ( & priv - > lock ) ;
2006-01-08 13:34:22 -08:00
priv - > spi = spi ;
priv - > page_size = pagesize ;
priv - > page_offset = pageoffset ;
/* name must be usable with cmdlinepart */
sprintf ( priv - > name , " spi%d.%d-%s " ,
spi - > master - > bus_num , spi - > chip_select ,
name ) ;
device = & priv - > mtd ;
device - > name = ( pdata & & pdata - > name ) ? pdata - > name : priv - > name ;
device - > size = nr_pages * pagesize ;
device - > erasesize = pagesize ;
2006-06-22 18:15:48 +04:00
device - > writesize = pagesize ;
2006-01-08 13:34:22 -08:00
device - > owner = THIS_MODULE ;
device - > type = MTD_DATAFLASH ;
2006-11-29 14:26:07 +01:00
device - > flags = MTD_WRITEABLE ;
2012-01-30 14:58:32 +02:00
device - > _erase = dataflash_erase ;
device - > _read = dataflash_read ;
device - > _write = dataflash_write ;
2006-01-08 13:34:22 -08:00
device - > priv = priv ;
2009-03-26 00:42:50 -07:00
device - > dev . parent = & spi - > dev ;
2008-07-30 12:35:05 -07:00
if ( revision > = ' c ' )
otp_tag = otp_setup ( device , revision ) ;
2008-12-18 14:09:56 +02:00
dev_info ( & spi - > dev , " %s (%lld KBytes) pagesize %d bytes%s \n " ,
name , ( long long ) ( ( device - > size + 1023 ) > > 10 ) ,
2008-07-30 12:35:05 -07:00
pagesize , otp_tag ) ;
2013-04-06 15:41:03 +09:00
spi_set_drvdata ( spi , priv ) ;
2006-01-08 13:34:22 -08:00
2011-07-15 16:38:56 +08:00
ppdata . of_node = spi - > dev . of_node ;
err = mtd_device_parse_register ( device , NULL , & ppdata ,
2011-06-02 17:59:18 +04:00
pdata ? pdata - > parts : NULL ,
pdata ? pdata - > nr_parts : 0 ) ;
2006-01-08 13:34:22 -08:00
2009-10-07 17:08:08 -04:00
if ( ! err )
return 0 ;
2013-04-06 15:41:03 +09:00
spi_set_drvdata ( spi , NULL ) ;
2009-10-07 17:08:08 -04:00
kfree ( priv ) ;
return err ;
2006-01-08 13:34:22 -08:00
}
2012-12-21 13:19:05 -08:00
static inline int add_dataflash ( struct spi_device * spi , char * name ,
int nr_pages , int pagesize , int pageoffset )
2008-07-30 12:35:05 -07:00
{
return add_dataflash_otp ( spi , name , nr_pages , pagesize ,
pageoffset , 0 ) ;
}
2008-06-03 12:26:05 +08:00
struct flash_info {
char * name ;
2008-07-29 22:22:40 -07:00
/* JEDEC id has a high byte of zero plus three data bytes:
* the manufacturer id , then a two byte device id .
2008-06-03 12:26:05 +08:00
*/
2008-06-04 17:43:22 +01:00
uint32_t jedec_id ;
2008-06-03 12:26:05 +08:00
2008-07-29 22:22:40 -07:00
/* The size listed here is what works with OP_ERASE_PAGE. */
2008-06-03 12:26:05 +08:00
unsigned nr_pages ;
2008-06-04 17:43:22 +01:00
uint16_t pagesize ;
uint16_t pageoffset ;
2008-06-03 12:26:05 +08:00
2008-06-04 17:43:22 +01:00
uint16_t flags ;
2008-07-29 22:22:40 -07:00
# define SUP_POW2PS 0x0002 /* supports 2^N byte pages */
# define IS_POW2PS 0x0001 /* uses 2^N byte pages */
2008-06-03 12:26:05 +08:00
} ;
2012-11-22 12:16:28 +02:00
static struct flash_info dataflash_data [ ] = {
2008-06-03 12:26:05 +08:00
2008-07-29 22:22:40 -07:00
/*
* NOTE : chips with SUP_POW2PS ( rev D and up ) need two entries ,
* one with IS_POW2PS and the other without . The entry with the
* non - 2 ^ N byte page size can ' t name exact chip revisions without
* losing backwards compatibility for cmdlinepart .
*
* These newer chips also support 128 - byte security registers ( with
* 64 bytes one - time - programmable ) and software write - protection .
*/
{ " AT45DB011B " , 0x1f2200 , 512 , 264 , 9 , SUP_POW2PS } ,
2008-06-03 12:26:05 +08:00
{ " at45db011d " , 0x1f2200 , 512 , 256 , 8 , SUP_POW2PS | IS_POW2PS } ,
2008-07-29 22:22:40 -07:00
{ " AT45DB021B " , 0x1f2300 , 1024 , 264 , 9 , SUP_POW2PS } ,
2008-06-03 12:26:05 +08:00
{ " at45db021d " , 0x1f2300 , 1024 , 256 , 8 , SUP_POW2PS | IS_POW2PS } ,
2008-07-29 22:22:40 -07:00
{ " AT45DB041x " , 0x1f2400 , 2048 , 264 , 9 , SUP_POW2PS } ,
2008-06-03 12:26:05 +08:00
{ " at45db041d " , 0x1f2400 , 2048 , 256 , 8 , SUP_POW2PS | IS_POW2PS } ,
2008-07-29 22:22:40 -07:00
{ " AT45DB081B " , 0x1f2500 , 4096 , 264 , 9 , SUP_POW2PS } ,
2008-06-03 12:26:05 +08:00
{ " at45db081d " , 0x1f2500 , 4096 , 256 , 8 , SUP_POW2PS | IS_POW2PS } ,
2008-07-29 22:22:40 -07:00
{ " AT45DB161x " , 0x1f2600 , 4096 , 528 , 10 , SUP_POW2PS } ,
2008-06-03 12:26:05 +08:00
{ " at45db161d " , 0x1f2600 , 4096 , 512 , 9 , SUP_POW2PS | IS_POW2PS } ,
2008-07-29 22:22:40 -07:00
{ " AT45DB321x " , 0x1f2700 , 8192 , 528 , 10 , 0 } , /* rev C */
2008-06-03 12:26:05 +08:00
2008-07-29 22:22:40 -07:00
{ " AT45DB321x " , 0x1f2701 , 8192 , 528 , 10 , SUP_POW2PS } ,
2008-06-03 12:26:05 +08:00
{ " at45db321d " , 0x1f2701 , 8192 , 512 , 9 , SUP_POW2PS | IS_POW2PS } ,
2008-07-29 22:22:40 -07:00
{ " AT45DB642x " , 0x1f2800 , 8192 , 1056 , 11 , SUP_POW2PS } ,
{ " at45db642d " , 0x1f2800 , 8192 , 1024 , 10 , SUP_POW2PS | IS_POW2PS } ,
2008-06-03 12:26:05 +08:00
} ;
2012-11-19 13:23:07 -05:00
static struct flash_info * jedec_probe ( struct spi_device * spi )
2008-06-03 12:26:05 +08:00
{
int tmp ;
2008-06-04 17:43:22 +01:00
uint8_t code = OP_READ_ID ;
uint8_t id [ 3 ] ;
uint32_t jedec ;
2008-06-03 12:26:05 +08:00
struct flash_info * info ;
int status ;
/* JEDEC also defines an optional "extended device information"
* string for after vendor - specific data , after the three bytes
* we use here . Supporting some chips might require using it .
2008-07-29 22:22:40 -07:00
*
* If the vendor ID isn ' t Atmel ' s ( 0x1f ) , assume this call failed .
* That ' s not an error ; only rev C and newer chips handle it , and
* only Atmel sells these chips .
2008-06-03 12:26:05 +08:00
*/
tmp = spi_write_then_read ( spi , & code , 1 , id , 3 ) ;
if ( tmp < 0 ) {
2011-07-19 10:06:09 -07:00
pr_debug ( " %s: error %d reading JEDEC ID \n " ,
2008-12-23 10:00:14 +00:00
dev_name ( & spi - > dev ) , tmp ) ;
2008-07-29 22:22:40 -07:00
return ERR_PTR ( tmp ) ;
2008-06-03 12:26:05 +08:00
}
2008-07-29 22:22:40 -07:00
if ( id [ 0 ] ! = 0x1f )
return NULL ;
2008-06-03 12:26:05 +08:00
jedec = id [ 0 ] ;
jedec = jedec < < 8 ;
jedec | = id [ 1 ] ;
jedec = jedec < < 8 ;
jedec | = id [ 2 ] ;
for ( tmp = 0 , info = dataflash_data ;
tmp < ARRAY_SIZE ( dataflash_data ) ;
tmp + + , info + + ) {
if ( info - > jedec_id = = jedec ) {
2011-07-19 10:06:09 -07:00
pr_debug ( " %s: OTP, sector protect%s \n " ,
2008-07-29 22:22:40 -07:00
dev_name ( & spi - > dev ) ,
( info - > flags & SUP_POW2PS )
? " , binary pagesize " : " "
) ;
2008-06-03 12:26:05 +08:00
if ( info - > flags & SUP_POW2PS ) {
status = dataflash_status ( spi ) ;
2008-07-29 22:22:40 -07:00
if ( status < 0 ) {
2011-07-19 10:06:09 -07:00
pr_debug ( " %s: status error %d \n " ,
2008-07-29 22:22:40 -07:00
dev_name ( & spi - > dev ) , status ) ;
return ERR_PTR ( status ) ;
}
if ( status & 0x1 ) {
if ( info - > flags & IS_POW2PS )
return info ;
} else {
if ( ! ( info - > flags & IS_POW2PS ) )
return info ;
}
2009-03-10 12:55:53 -07:00
} else
return info ;
2008-06-03 12:26:05 +08:00
}
}
2008-07-29 22:22:40 -07:00
/*
* Treat other chips as errors . . . we won ' t know the right page
* size ( it might be binary ) even when we can tell which density
* class is involved ( legacy chip id scheme ) .
*/
dev_warn ( & spi - > dev , " JEDEC id %06x not handled \n " , jedec ) ;
return ERR_PTR ( - ENODEV ) ;
2008-06-03 12:26:05 +08:00
}
2008-07-29 22:22:40 -07:00
/*
* Detect and initialize DataFlash device , using JEDEC IDs on newer chips
* or else the ID code embedded in the status bits :
*
* Device Density ID code # Pages PageSize Offset
* AT45DB011B 1 Mbit ( 128 K ) xx0011xx ( 0x0c ) 512 264 9
* AT45DB021B 2 Mbit ( 256 K ) xx0101xx ( 0x14 ) 1024 264 9
* AT45DB041B 4 Mbit ( 512 K ) xx0111xx ( 0x1c ) 2048 264 9
* AT45DB081B 8 Mbit ( 1 M ) xx1001xx ( 0x24 ) 4096 264 9
* AT45DB0161B 16 Mbit ( 2 M ) xx1011xx ( 0x2c ) 4096 528 10
* AT45DB0321B 32 Mbit ( 4 M ) xx1101xx ( 0x34 ) 8192 528 10
* AT45DB0642 64 Mbit ( 8 M ) xx111xxx ( 0x3c ) 8192 1056 11
* AT45DB1282 128 Mbit ( 16 M ) xx0100xx ( 0x10 ) 16384 1056 11
*/
2012-11-19 13:23:07 -05:00
static int dataflash_probe ( struct spi_device * spi )
2006-01-08 13:34:22 -08:00
{
int status ;
2008-06-03 12:26:05 +08:00
struct flash_info * info ;
/*
* Try to detect dataflash by JEDEC ID .
* If it succeeds we know we have either a C or D part .
* D will support power of 2 pagesize option .
2008-07-30 12:35:05 -07:00
* Both support the security register , though with different
* write procedures .
2008-06-03 12:26:05 +08:00
*/
info = jedec_probe ( spi ) ;
2008-07-29 22:22:40 -07:00
if ( IS_ERR ( info ) )
return PTR_ERR ( info ) ;
2008-06-03 12:26:05 +08:00
if ( info ! = NULL )
2008-07-30 12:35:05 -07:00
return add_dataflash_otp ( spi , info - > name , info - > nr_pages ,
info - > pagesize , info - > pageoffset ,
( info - > flags & SUP_POW2PS ) ? ' d ' : ' c ' ) ;
2008-06-03 12:26:05 +08:00
2008-07-29 22:22:40 -07:00
/*
* Older chips support only legacy commands , identifing
* capacity using bits in the status byte .
*/
2006-01-08 13:34:22 -08:00
status = dataflash_status ( spi ) ;
if ( status < = 0 | | status = = 0xff ) {
2011-07-19 10:06:09 -07:00
pr_debug ( " %s: status error %d \n " ,
2008-12-23 10:00:14 +00:00
dev_name ( & spi - > dev ) , status ) ;
2006-12-29 16:48:47 -08:00
if ( status = = 0 | | status = = 0xff )
2006-01-08 13:34:22 -08:00
status = - ENODEV ;
return status ;
}
/* if there's a device there, assume it's dataflash.
* board setup should have set spi - > max_speed_max to
* match f ( car ) for continuous reads , mode 0 or 3.
*/
switch ( status & 0x3c ) {
case 0x0c : /* 0 0 1 1 x x */
status = add_dataflash ( spi , " AT45DB011B " , 512 , 264 , 9 ) ;
break ;
case 0x14 : /* 0 1 0 1 x x */
2008-06-03 12:26:05 +08:00
status = add_dataflash ( spi , " AT45DB021B " , 1024 , 264 , 9 ) ;
2006-01-08 13:34:22 -08:00
break ;
case 0x1c : /* 0 1 1 1 x x */
2008-07-29 22:22:40 -07:00
status = add_dataflash ( spi , " AT45DB041x " , 2048 , 264 , 9 ) ;
2006-01-08 13:34:22 -08:00
break ;
case 0x24 : /* 1 0 0 1 x x */
status = add_dataflash ( spi , " AT45DB081B " , 4096 , 264 , 9 ) ;
break ;
case 0x2c : /* 1 0 1 1 x x */
2008-07-29 22:22:40 -07:00
status = add_dataflash ( spi , " AT45DB161x " , 4096 , 528 , 10 ) ;
2006-01-08 13:34:22 -08:00
break ;
case 0x34 : /* 1 1 0 1 x x */
status = add_dataflash ( spi , " AT45DB321x " , 8192 , 528 , 10 ) ;
break ;
case 0x38 : /* 1 1 1 x x x */
case 0x3c :
status = add_dataflash ( spi , " AT45DB642x " , 8192 , 1056 , 11 ) ;
break ;
/* obsolete AT45DB1282 not (yet?) supported */
default :
2011-07-19 10:06:10 -07:00
pr_debug ( " %s: unsupported device (%x) \n " , dev_name ( & spi - > dev ) ,
status & 0x3c ) ;
2006-01-08 13:34:22 -08:00
status = - ENODEV ;
}
if ( status < 0 )
2011-07-19 10:06:10 -07:00
pr_debug ( " %s: add_dataflash --> %d \n " , dev_name ( & spi - > dev ) ,
status ) ;
2006-01-08 13:34:22 -08:00
return status ;
}
2012-11-19 13:26:04 -05:00
static int dataflash_remove ( struct spi_device * spi )
2006-01-08 13:34:22 -08:00
{
2013-04-06 15:41:03 +09:00
struct dataflash * flash = spi_get_drvdata ( spi ) ;
2006-01-08 13:34:22 -08:00
int status ;
2011-07-19 10:06:09 -07:00
pr_debug ( " %s: remove \n " , dev_name ( & spi - > dev ) ) ;
2006-01-08 13:34:22 -08:00
2011-05-23 10:22:58 +01:00
status = mtd_device_unregister ( & flash - > mtd ) ;
2009-10-07 17:08:08 -04:00
if ( status = = 0 ) {
2013-04-06 15:41:03 +09:00
spi_set_drvdata ( spi , NULL ) ;
2006-01-08 13:34:22 -08:00
kfree ( flash ) ;
2009-10-07 17:08:08 -04:00
}
2006-01-08 13:34:22 -08:00
return status ;
}
static struct spi_driver dataflash_driver = {
. driver = {
. name = " mtd_dataflash " ,
. owner = THIS_MODULE ,
2013-03-14 15:37:00 +05:30
. of_match_table = of_match_ptr ( dataflash_dt_ids ) ,
2006-01-08 13:34:22 -08:00
} ,
. probe = dataflash_probe ,
2012-11-19 13:21:24 -05:00
. remove = dataflash_remove ,
2006-01-08 13:34:22 -08:00
/* FIXME: investigate suspend and resume... */
} ;
2012-01-27 15:45:20 +08:00
module_spi_driver ( dataflash_driver ) ;
2006-01-08 13:34:22 -08:00
MODULE_LICENSE ( " GPL " ) ;
MODULE_AUTHOR ( " Andrew Victor, David Brownell " ) ;
MODULE_DESCRIPTION ( " MTD DataFlash driver " ) ;
2009-09-22 16:46:08 -07:00
MODULE_ALIAS ( " spi:mtd_dataflash " ) ;