2005-04-16 15:20:36 -07:00
/*
* drivers / mtd / nand / spia . c
*
* Copyright ( C ) 2000 Steven J . Hill ( sjhill @ realitydiluted . com )
*
*
* 10 - 29 - 2001 TG change to support hardwarespecific access
* to controllines ( due to change in nand . c )
* page_cache added
*
2005-11-07 11:15:49 +00:00
* $ Id : spia . c , v 1.25 2005 / 11 / 07 11 : 14 : 31 gleixner Exp $
2005-04-16 15:20:36 -07: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
* SPIA board which utilizes the Toshiba TC58V64AFT part . This is
* a 64 Mibit ( 8 MiB x 8 bits ) NAND flash device .
*/
# include <linux/kernel.h>
# include <linux/init.h>
# include <linux/slab.h>
# include <linux/module.h>
# include <linux/mtd/mtd.h>
# include <linux/mtd/nand.h>
# include <linux/mtd/partitions.h>
# include <asm/io.h>
/*
* MTD structure for SPIA board
*/
static struct mtd_info * spia_mtd = NULL ;
/*
* Values specific to the SPIA board ( used with EP7212 processor )
*/
# define SPIA_IO_BASE 0xd0000000 /* Start of EP7212 IO address space */
# define SPIA_FIO_BASE 0xf0000000 /* Address where flash is mapped */
2006-05-13 18:07:53 +01:00
# define SPIA_PEDR 0x0080 / *
* IO offset to Port E data register
* where the CLE , ALE and NCE pins
* are wired to .
*/
# define SPIA_PEDDR 0x00c0 / *
* IO offset to Port E data direction
* register so we can control the IO
* lines .
*/
2005-04-16 15:20:36 -07:00
/*
* Module stuff
*/
static int spia_io_base = SPIA_IO_BASE ;
static int spia_fio_base = SPIA_FIO_BASE ;
static int spia_pedr = SPIA_PEDR ;
static int spia_peddr = SPIA_PEDDR ;
module_param ( spia_io_base , int , 0 ) ;
module_param ( spia_fio_base , int , 0 ) ;
module_param ( spia_pedr , int , 0 ) ;
module_param ( spia_peddr , int , 0 ) ;
/*
* Define partitions for flash device
*/
2006-01-09 20:54:01 -08:00
static const struct mtd_partition partition_info [ ] = {
2005-04-16 15:20:36 -07:00
{
2006-05-13 18:07:53 +01:00
. name = " SPIA flash partition 1 " ,
. offset = 0 ,
. size = 2 * 1024 * 1024 } ,
2005-04-16 15:20:36 -07:00
{
2006-05-13 18:07:53 +01:00
. name = " SPIA flash partition 2 " ,
. offset = 2 * 1024 * 1024 ,
. size = 6 * 1024 * 1024 }
2005-04-16 15:20:36 -07:00
} ;
2006-05-13 18:07:53 +01:00
# define NUM_PARTITIONS 2
2005-04-16 15:20:36 -07:00
2005-11-07 11:15:49 +00:00
/*
2005-04-16 15:20:36 -07:00
* hardware specific access to control - lines
2006-05-23 23:25:53 +02:00
*
* ctrl :
* NAND_CNE : bit 0 - > bit 2
* NAND_CLE : bit 1 - > bit 0
* NAND_ALE : bit 2 - > bit 1
*/
2006-05-13 18:07:53 +01:00
static void spia_hwcontrol ( struct mtd_info * mtd , int cmd )
{
2006-05-23 23:25:53 +02:00
struct nand_chip * chip = mtd - > priv ;
2005-04-16 15:20:36 -07:00
2006-05-23 23:25:53 +02:00
if ( ctrl & NAND_CTRL_CHANGE ) {
void __iomem * addr = spia_io_base + spia_pedr ;
unsigned char bits ;
2005-04-16 15:20:36 -07:00
2006-05-23 23:25:53 +02:00
bits = ( ctrl & NAND_CNE ) < < 2 ;
bits | = ( ctrl & NAND_CLE | NAND_ALE ) > > 1 ;
writeb ( ( readb ( addr ) & ~ 0x7 ) | bits , addr ) ;
2006-05-13 18:07:53 +01:00
}
2006-05-23 23:25:53 +02:00
if ( cmd ! = NAND_CMD_NONE )
writeb ( cmd , chip - > IO_ADDR_W ) ;
2005-04-16 15:20:36 -07:00
}
/*
* Main initialization routine
*/
2006-05-16 13:54:50 +01:00
static int __init spia_init ( void )
2005-04-16 15:20:36 -07:00
{
struct nand_chip * this ;
/* Allocate memory for MTD device structure and private data */
2006-05-13 18:07:53 +01:00
spia_mtd = kmalloc ( sizeof ( struct mtd_info ) + sizeof ( struct nand_chip ) , GFP_KERNEL ) ;
2005-04-16 15:20:36 -07:00
if ( ! spia_mtd ) {
2006-05-13 18:07:53 +01:00
printk ( " Unable to allocate SPIA NAND MTD device structure. \n " ) ;
2005-04-16 15:20:36 -07:00
return - ENOMEM ;
}
/* Get pointer to private data */
2006-05-13 18:07:53 +01:00
this = ( struct nand_chip * ) ( & spia_mtd [ 1 ] ) ;
2005-04-16 15:20:36 -07:00
/* Initialize structures */
2006-05-13 18:07:53 +01:00
memset ( spia_mtd , 0 , sizeof ( struct mtd_info ) ) ;
memset ( this , 0 , sizeof ( struct nand_chip ) ) ;
2005-04-16 15:20:36 -07:00
/* Link the private data with the MTD structure */
spia_mtd - > priv = this ;
2006-05-14 01:20:46 +01:00
spia_mtd - > owner = THIS_MODULE ;
2005-04-16 15:20:36 -07:00
/*
* Set GPIO Port E control register so that the pins are configured
* to be outputs for controlling the NAND flash .
*/
2006-05-13 18:07:53 +01:00
( * ( volatile unsigned char * ) ( spia_io_base + spia_peddr ) ) = 0x07 ;
2005-04-16 15:20:36 -07:00
/* Set address of NAND IO lines */
2006-05-13 18:07:53 +01:00
this - > IO_ADDR_R = ( void __iomem * ) spia_fio_base ;
this - > IO_ADDR_W = ( void __iomem * ) spia_fio_base ;
2005-04-16 15:20:36 -07:00
/* Set address of hardware control function */
2006-05-23 23:25:53 +02:00
this - > cmd_ctrl = spia_hwcontrol ;
2005-04-16 15:20:36 -07:00
/* 15 us command delay time */
2005-11-07 11:15:49 +00:00
this - > chip_delay = 15 ;
2005-04-16 15:20:36 -07:00
/* Scan to find existence of the device */
2006-05-13 18:07:53 +01:00
if ( nand_scan ( spia_mtd , 1 ) ) {
kfree ( spia_mtd ) ;
2005-04-16 15:20:36 -07:00
return - ENXIO ;
}
/* Register the partitions */
add_mtd_partitions ( spia_mtd , partition_info , NUM_PARTITIONS ) ;
/* Return happy */
return 0 ;
}
2006-05-13 18:07:53 +01:00
2005-04-16 15:20:36 -07:00
module_init ( spia_init ) ;
/*
* Clean up routine
*/
2006-05-13 18:07:53 +01:00
static void __exit spia_cleanup ( void )
2005-04-16 15:20:36 -07:00
{
/* Release resources, unregister device */
2006-05-13 18:07:53 +01:00
nand_release ( spia_mtd ) ;
2005-04-16 15:20:36 -07:00
/* Free the MTD device structure */
2006-05-13 18:07:53 +01:00
kfree ( spia_mtd ) ;
2005-04-16 15:20:36 -07:00
}
2006-05-13 18:07:53 +01:00
2005-04-16 15:20:36 -07:00
module_exit ( spia_cleanup ) ;
MODULE_LICENSE ( " GPL " ) ;
MODULE_AUTHOR ( " Steven J. Hill <sjhill@realitydiluted.com " ) ;
MODULE_DESCRIPTION ( " Board-specific glue layer for NAND flash on SPIA board " ) ;