2005-04-17 02:20:36 +04:00
/*
* drivers / mtd / autcpu12 . c
*
* Copyright ( c ) 2002 Thomas Gleixner < tgxl @ linutronix . de >
*
* Derived from drivers / mtd / spia . c
2006-05-24 01:25:53 +04:00
* Copyright ( C ) 2000 Steven J . Hill ( sjhill @ realitydiluted . com )
2005-11-07 14:15:49 +03:00
*
2005-04-17 02:20:36 +04:00
* This program is free software ; you can redistribute it and / or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation .
*
* Overview :
* This is a device driver for the NAND flash device found on the
2005-11-07 14:15:49 +03:00
* autronix autcpu12 board , which is a SmartMediaCard . It supports
2005-04-17 02:20:36 +04:00
* 16 MiB , 32 MiB and 64 MiB cards .
*
*
* 02 - 12 - 2002 TG Cleanup of module params
*
2008-02-03 18:22:34 +03:00
* 02 - 20 - 2002 TG adjusted for different rd / wr address support
2005-04-17 02:20:36 +04:00
* added support for read device ready / busy line
* added page_cache
*
* 10 - 06 - 2002 TG 128 K card support added
*/
# include <linux/slab.h>
# include <linux/init.h>
# include <linux/module.h>
# include <linux/mtd/mtd.h>
# include <linux/mtd/nand.h>
# include <linux/mtd/partitions.h>
# include <asm/io.h>
2008-08-05 19:14:15 +04:00
# include <mach/hardware.h>
2005-04-17 02:20:36 +04:00
# include <asm/sizes.h>
2008-08-05 19:14:15 +04:00
# include <mach/autcpu12.h>
2005-04-17 02:20:36 +04:00
/*
* MTD structure for AUTCPU12 board
*/
static struct mtd_info * autcpu12_mtd = NULL ;
2006-05-13 21:07:53 +04:00
static void __iomem * autcpu12_fio_base ;
2005-04-17 02:20:36 +04:00
/*
* Define partitions for flash devices
*/
static struct mtd_partition partition_info16k [ ] = {
{ . name = " AUTCPU12 flash partition 1 " ,
. offset = 0 ,
. size = 8 * SZ_1M } ,
{ . name = " AUTCPU12 flash partition 2 " ,
. offset = 8 * SZ_1M ,
. size = 8 * SZ_1M } ,
} ;
static struct mtd_partition partition_info32k [ ] = {
{ . name = " AUTCPU12 flash partition 1 " ,
. offset = 0 ,
. size = 8 * SZ_1M } ,
{ . name = " AUTCPU12 flash partition 2 " ,
. offset = 8 * SZ_1M ,
. size = 24 * SZ_1M } ,
} ;
static struct mtd_partition partition_info64k [ ] = {
{ . name = " AUTCPU12 flash partition 1 " ,
. offset = 0 ,
. size = 16 * SZ_1M } ,
{ . name = " AUTCPU12 flash partition 2 " ,
. offset = 16 * SZ_1M ,
. size = 48 * SZ_1M } ,
} ;
static struct mtd_partition partition_info128k [ ] = {
{ . name = " AUTCPU12 flash partition 1 " ,
. offset = 0 ,
. size = 16 * SZ_1M } ,
{ . name = " AUTCPU12 flash partition 2 " ,
. offset = 16 * SZ_1M ,
. size = 112 * SZ_1M } ,
} ;
# define NUM_PARTITIONS16K 2
# define NUM_PARTITIONS32K 2
# define NUM_PARTITIONS64K 2
# define NUM_PARTITIONS128K 2
2005-11-07 14:15:49 +03:00
/*
2005-04-17 02:20:36 +04:00
* hardware specific access to control - lines
2006-05-24 01:25:53 +04:00
*
* ALE bit 4 autcpu12_pedr
* CLE bit 5 autcpu12_pedr
* NCE bit 0 fio_ctrl
*
*/
static void autcpu12_hwcontrol ( struct mtd_info * mtd , int cmd ,
unsigned int ctrl )
2005-04-17 02:20:36 +04:00
{
2006-05-24 01:25:53 +04:00
struct nand_chip * chip = mtd - > priv ;
2005-04-17 02:20:36 +04:00
2006-05-24 01:25:53 +04:00
if ( ctrl & NAND_CTRL_CHANGE ) {
2007-06-01 11:46:35 +04:00
void __iomem * addr ;
2006-05-24 01:25:53 +04:00
unsigned char bits ;
2005-04-17 02:20:36 +04:00
2006-05-24 01:25:53 +04:00
addr = CS89712_VIRT_BASE + AUTCPU12_SMC_PORT_OFFSET ;
bits = ( ctrl & NAND_CLE ) < < 4 ;
bits | = ( ctrl & NAND_ALE ) < < 2 ;
writeb ( ( readb ( addr ) & ~ 0x30 ) | bits , addr ) ;
2005-04-17 02:20:36 +04:00
2006-05-24 01:25:53 +04:00
addr = autcpu12_fio_base + AUTCPU12_SMC_SELECT_OFFSET ;
writeb ( ( readb ( addr ) & ~ 0x1 ) | ( ctrl & NAND_NCE ) , addr ) ;
2005-04-17 02:20:36 +04:00
}
2006-05-24 01:25:53 +04:00
if ( cmd ! = NAND_CMD_NONE )
writeb ( cmd , chip - > IO_ADDR_W ) ;
2005-04-17 02:20:36 +04:00
}
/*
2006-05-24 01:25:53 +04:00
* read device ready pin
*/
2005-04-17 02:20:36 +04:00
int autcpu12_device_ready ( struct mtd_info * mtd )
{
2006-05-24 01:25:53 +04:00
void __iomem * addr = CS89712_VIRT_BASE + AUTCPU12_SMC_PORT_OFFSET ;
2005-04-17 02:20:36 +04:00
2006-05-24 01:25:53 +04:00
return readb ( addr ) & AUTCPU12_SMC_RDY ;
2005-04-17 02:20:36 +04:00
}
/*
* Main initialization routine
*/
2006-05-16 16:54:50 +04:00
static int __init autcpu12_init ( void )
2005-04-17 02:20:36 +04:00
{
struct nand_chip * this ;
int err = 0 ;
/* Allocate memory for MTD device structure and private data */
2006-05-24 01:25:53 +04:00
autcpu12_mtd = kmalloc ( sizeof ( struct mtd_info ) + sizeof ( struct nand_chip ) ,
GFP_KERNEL ) ;
2005-04-17 02:20:36 +04:00
if ( ! autcpu12_mtd ) {
2006-05-13 21:07:53 +04:00
printk ( " Unable to allocate AUTCPU12 NAND MTD device structure. \n " ) ;
2005-04-17 02:20:36 +04:00
err = - ENOMEM ;
goto out ;
}
2008-02-03 18:22:34 +03:00
/* map physical address */
2006-05-24 01:25:53 +04:00
autcpu12_fio_base = ioremap ( AUTCPU12_PHYS_SMC , SZ_1K ) ;
2006-05-13 21:07:53 +04:00
if ( ! autcpu12_fio_base ) {
2005-04-17 02:20:36 +04:00
printk ( " Ioremap autcpu12 SmartMedia Card failed \n " ) ;
err = - EIO ;
goto out_mtd ;
}
/* Get pointer to private data */
2006-05-13 21:07:53 +04:00
this = ( struct nand_chip * ) ( & autcpu12_mtd [ 1 ] ) ;
2005-04-17 02:20:36 +04:00
/* Initialize structures */
2006-05-13 21:07:53 +04:00
memset ( autcpu12_mtd , 0 , sizeof ( struct mtd_info ) ) ;
memset ( this , 0 , sizeof ( struct nand_chip ) ) ;
2005-04-17 02:20:36 +04:00
/* Link the private data with the MTD structure */
autcpu12_mtd - > priv = this ;
2006-05-14 04:20:46 +04:00
autcpu12_mtd - > owner = THIS_MODULE ;
2005-04-17 02:20:36 +04:00
/* Set address of NAND IO lines */
this - > IO_ADDR_R = autcpu12_fio_base ;
this - > IO_ADDR_W = autcpu12_fio_base ;
2006-05-24 01:25:53 +04:00
this - > cmd_ctrl = autcpu12_hwcontrol ;
2005-04-17 02:20:36 +04:00
this - > dev_ready = autcpu12_device_ready ;
/* 20 us command delay time */
2005-11-07 14:15:49 +03:00
this - > chip_delay = 20 ;
2006-05-23 14:00:46 +04:00
this - > ecc . mode = NAND_ECC_SOFT ;
2005-04-17 02:20:36 +04:00
/* Enable the following for a flash based bad block table */
/*
2006-05-13 21:07:53 +04:00
this - > options = NAND_USE_FLASH_BBT ;
*/
2005-04-17 02:20:36 +04:00
this - > options = NAND_USE_FLASH_BBT ;
2005-11-07 14:15:49 +03:00
2005-04-17 02:20:36 +04:00
/* Scan to find existance of the device */
2006-05-13 21:07:53 +04:00
if ( nand_scan ( autcpu12_mtd , 1 ) ) {
2005-04-17 02:20:36 +04:00
err = - ENXIO ;
goto out_ior ;
}
2005-11-07 14:15:49 +03:00
2005-04-17 02:20:36 +04:00
/* Register the partitions */
2006-05-13 21:07:53 +04:00
switch ( autcpu12_mtd - > size ) {
2006-05-24 01:25:53 +04:00
case SZ_16M :
add_mtd_partitions ( autcpu12_mtd , partition_info16k ,
NUM_PARTITIONS16K ) ;
break ;
case SZ_32M :
add_mtd_partitions ( autcpu12_mtd , partition_info32k ,
NUM_PARTITIONS32K ) ;
break ;
case SZ_64M :
add_mtd_partitions ( autcpu12_mtd , partition_info64k ,
NUM_PARTITIONS64K ) ;
break ;
case SZ_128M :
add_mtd_partitions ( autcpu12_mtd , partition_info128k ,
NUM_PARTITIONS128K ) ;
break ;
2006-05-13 21:07:53 +04:00
default :
printk ( " Unsupported SmartMedia device \n " ) ;
2005-04-17 02:20:36 +04:00
err = - ENXIO ;
goto out_ior ;
}
goto out ;
2006-05-13 21:07:53 +04:00
out_ior :
2006-05-24 01:25:53 +04:00
iounmap ( autcpu12_fio_base ) ;
2006-05-13 21:07:53 +04:00
out_mtd :
kfree ( autcpu12_mtd ) ;
out :
2005-04-17 02:20:36 +04:00
return err ;
}
module_init ( autcpu12_init ) ;
/*
* Clean up routine
*/
2006-05-13 21:07:53 +04:00
static void __exit autcpu12_cleanup ( void )
2005-04-17 02:20:36 +04:00
{
/* Release resources, unregister device */
2006-05-13 21:07:53 +04:00
nand_release ( autcpu12_mtd ) ;
2005-04-17 02:20:36 +04:00
2008-02-03 18:22:34 +03:00
/* unmap physical address */
2006-05-24 01:25:53 +04:00
iounmap ( autcpu12_fio_base ) ;
2005-11-07 14:15:49 +03:00
2005-04-17 02:20:36 +04:00
/* Free the MTD device structure */
2006-05-13 21:07:53 +04:00
kfree ( autcpu12_mtd ) ;
2005-04-17 02:20:36 +04:00
}
2006-05-13 21:07:53 +04:00
2005-04-17 02:20:36 +04:00
module_exit ( autcpu12_cleanup ) ;
MODULE_LICENSE ( " GPL " ) ;
MODULE_AUTHOR ( " Thomas Gleixner <tglx@linutronix.de> " ) ;
MODULE_DESCRIPTION ( " Glue layer for SmartMediaCard on autronix autcpu12 " ) ;