2005-04-17 02:20:36 +04:00
/*
* drivers / mtd / nand / ppchameleonevb . c
*
* Copyright ( C ) 2003 DAVE Srl ( info @ wawnet . biz )
*
* Derived from drivers / mtd / nand / edb7312 . c
*
*
* 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 devices found on the
* PPChameleon / PPChameleonEVB system .
* PPChameleon options ( autodetected ) :
* - BA model : no NAND
* - ME model : 32 MB ( Samsung K9F5608U0B )
* - HI model : 128 MB ( Samsung K9F1G08UOM )
* PPChameleonEVB options :
* - 32 MB ( Samsung K9F5608U0B )
*/
# 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>
# include <platforms/PPChameleonEVB.h>
# undef USE_READY_BUSY_PIN
# define USE_READY_BUSY_PIN
/* see datasheets (tR) */
# define NAND_BIG_DELAY_US 25
# define NAND_SMALL_DELAY_US 10
/* handy sizes */
# define SZ_4M 0x00400000
# define NAND_SMALL_SIZE 0x02000000
# define NAND_MTD_NAME "ppchameleon-nand"
# define NAND_EVB_MTD_NAME "ppchameleonevb-nand"
/* GPIO pins used to drive NAND chip mounted on processor module */
# define NAND_nCE_GPIO_PIN (0x80000000 >> 1)
# define NAND_CLE_GPIO_PIN (0x80000000 >> 2)
# define NAND_ALE_GPIO_PIN (0x80000000 >> 3)
# define NAND_RB_GPIO_PIN (0x80000000 >> 4)
/* GPIO pins used to drive NAND chip mounted on EVB */
# define NAND_EVB_nCE_GPIO_PIN (0x80000000 >> 14)
# define NAND_EVB_CLE_GPIO_PIN (0x80000000 >> 15)
# define NAND_EVB_ALE_GPIO_PIN (0x80000000 >> 16)
# define NAND_EVB_RB_GPIO_PIN (0x80000000 >> 31)
/*
* MTD structure for PPChameleonEVB board
*/
2006-05-13 21:07:53 +04:00
static struct mtd_info * ppchameleon_mtd = NULL ;
2005-04-17 02:20:36 +04:00
static struct mtd_info * ppchameleonevb_mtd = NULL ;
/*
* Module stuff
*/
2006-05-13 21:07:53 +04:00
static unsigned long ppchameleon_fio_pbase = CFG_NAND0_PADDR ;
2005-04-17 02:20:36 +04:00
static unsigned long ppchameleonevb_fio_pbase = CFG_NAND1_PADDR ;
# ifdef MODULE
module_param ( ppchameleon_fio_pbase , ulong , 0 ) ;
module_param ( ppchameleonevb_fio_pbase , ulong , 0 ) ;
# else
2006-05-13 21:07:53 +04:00
__setup ( " ppchameleon_fio_pbase= " , ppchameleon_fio_pbase ) ;
__setup ( " ppchameleonevb_fio_pbase= " , ppchameleonevb_fio_pbase ) ;
2005-04-17 02:20:36 +04:00
# endif
# ifdef CONFIG_MTD_PARTITIONS
/*
* Define static partitions for flash devices
*/
static struct mtd_partition partition_info_hi [ ] = {
2006-05-13 21:07:53 +04:00
{ . name = " PPChameleon HI Nand Flash " ,
2007-06-01 11:46:35 +04:00
. offset = 0 ,
2006-05-13 21:07:53 +04:00
. size = 128 * 1024 * 1024
}
2005-04-17 02:20:36 +04:00
} ;
static struct mtd_partition partition_info_me [ ] = {
2006-05-13 21:07:53 +04:00
{ . name = " PPChameleon ME Nand Flash " ,
. offset = 0 ,
. size = 32 * 1024 * 1024
}
2005-04-17 02:20:36 +04:00
} ;
static struct mtd_partition partition_info_evb [ ] = {
2006-05-13 21:07:53 +04:00
{ . name = " PPChameleonEVB Nand Flash " ,
. offset = 0 ,
. size = 32 * 1024 * 1024
}
2005-04-17 02:20:36 +04:00
} ;
# define NUM_PARTITIONS 1
2006-05-13 21:07:53 +04:00
extern int parse_cmdline_partitions ( struct mtd_info * master , struct mtd_partition * * pparts , const char * mtd_id ) ;
2005-04-17 02:20:36 +04:00
# endif
/*
* hardware specific access to control - lines
*/
2006-05-24 01:25:53 +04:00
static void ppchameleon_hwcontrol ( struct mtd_info * mtdinfo , 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 ;
if ( ctrl & NAND_CTRL_CHANGE ) {
# error Missing headerfiles. No way to fix this. -tglx
switch ( cmd ) {
case NAND_CTL_SETCLE :
MACRO_NAND_CTL_SETCLE ( ( unsigned long ) CFG_NAND0_PADDR ) ;
break ;
case NAND_CTL_CLRCLE :
MACRO_NAND_CTL_CLRCLE ( ( unsigned long ) CFG_NAND0_PADDR ) ;
break ;
case NAND_CTL_SETALE :
MACRO_NAND_CTL_SETALE ( ( unsigned long ) CFG_NAND0_PADDR ) ;
break ;
case NAND_CTL_CLRALE :
MACRO_NAND_CTL_CLRALE ( ( unsigned long ) CFG_NAND0_PADDR ) ;
break ;
case NAND_CTL_SETNCE :
MACRO_NAND_ENABLE_CE ( ( unsigned long ) CFG_NAND0_PADDR ) ;
break ;
case NAND_CTL_CLRNCE :
MACRO_NAND_DISABLE_CE ( ( unsigned long ) CFG_NAND0_PADDR ) ;
break ;
}
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
static void ppchameleonevb_hwcontrol ( struct mtd_info * mtdinfo , 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 ;
if ( ctrl & NAND_CTRL_CHANGE ) {
# error Missing headerfiles. No way to fix this. -tglx
switch ( cmd ) {
case NAND_CTL_SETCLE :
MACRO_NAND_CTL_SETCLE ( ( unsigned long ) CFG_NAND1_PADDR ) ;
break ;
case NAND_CTL_CLRCLE :
MACRO_NAND_CTL_CLRCLE ( ( unsigned long ) CFG_NAND1_PADDR ) ;
break ;
case NAND_CTL_SETALE :
MACRO_NAND_CTL_SETALE ( ( unsigned long ) CFG_NAND1_PADDR ) ;
break ;
case NAND_CTL_CLRALE :
MACRO_NAND_CTL_CLRALE ( ( unsigned long ) CFG_NAND1_PADDR ) ;
break ;
case NAND_CTL_SETNCE :
MACRO_NAND_ENABLE_CE ( ( unsigned long ) CFG_NAND1_PADDR ) ;
break ;
case NAND_CTL_CLRNCE :
MACRO_NAND_DISABLE_CE ( ( unsigned long ) CFG_NAND1_PADDR ) ;
break ;
}
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
}
# ifdef USE_READY_BUSY_PIN
/*
* read device ready pin
*/
static int ppchameleon_device_ready ( struct mtd_info * minfo )
{
2006-05-13 21:07:53 +04:00
if ( in_be32 ( ( volatile unsigned * ) GPIO0_IR ) & NAND_RB_GPIO_PIN )
2005-04-17 02:20:36 +04:00
return 1 ;
return 0 ;
}
static int ppchameleonevb_device_ready ( struct mtd_info * minfo )
{
2006-05-13 21:07:53 +04:00
if ( in_be32 ( ( volatile unsigned * ) GPIO0_IR ) & NAND_EVB_RB_GPIO_PIN )
return 1 ;
2005-04-17 02:20:36 +04:00
return 0 ;
}
# endif
# ifdef CONFIG_MTD_PARTITIONS
const char * part_probes [ ] = { " cmdlinepart " , NULL } ;
const char * part_probes_evb [ ] = { " cmdlinepart " , NULL } ;
# endif
/*
* Main initialization routine
*/
2006-05-13 21:07:53 +04:00
static int __init ppchameleonevb_init ( void )
2005-04-17 02:20:36 +04:00
{
struct nand_chip * this ;
const char * part_type = 0 ;
int mtd_parts_nb = 0 ;
struct mtd_partition * mtd_parts = 0 ;
void __iomem * ppchameleon_fio_base ;
void __iomem * ppchameleonevb_fio_base ;
/*********************************
* Processor module NAND ( if any ) *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
/* Allocate memory for MTD device structure and private data */
2006-05-13 21:07:53 +04:00
ppchameleon_mtd = kmalloc ( sizeof ( struct mtd_info ) + sizeof ( struct nand_chip ) , GFP_KERNEL ) ;
2005-04-17 02:20:36 +04:00
if ( ! ppchameleon_mtd ) {
printk ( " Unable to allocate PPChameleon NAND MTD device structure. \n " ) ;
return - ENOMEM ;
}
/* map physical address */
ppchameleon_fio_base = ioremap ( ppchameleon_fio_pbase , SZ_4M ) ;
2006-05-13 21:07:53 +04:00
if ( ! ppchameleon_fio_base ) {
2005-04-17 02:20:36 +04:00
printk ( " ioremap PPChameleon NAND flash failed \n " ) ;
kfree ( ppchameleon_mtd ) ;
return - EIO ;
}
/* Get pointer to private data */
2006-05-13 21:07:53 +04:00
this = ( struct nand_chip * ) ( & ppchameleon_mtd [ 1 ] ) ;
2005-04-17 02:20:36 +04:00
/* Initialize structures */
2006-05-13 21:07:53 +04:00
memset ( ppchameleon_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 */
ppchameleon_mtd - > priv = this ;
2006-05-14 04:20:46 +04:00
ppchameleon_mtd - > owner = THIS_MODULE ;
2005-04-17 02:20:36 +04:00
2006-05-13 21:07:53 +04:00
/* Initialize GPIOs */
2005-04-17 02:20:36 +04:00
/* Pin mapping for NAND chip */
/*
2006-05-13 21:07:53 +04:00
CE GPIO_01
CLE GPIO_02
ALE GPIO_03
R / B GPIO_04
*/
2005-04-17 02:20:36 +04:00
/* output select */
2006-05-13 21:07:53 +04:00
out_be32 ( ( volatile unsigned * ) GPIO0_OSRH , in_be32 ( ( volatile unsigned * ) GPIO0_OSRH ) & 0xC0FFFFFF ) ;
2005-04-17 02:20:36 +04:00
/* three-state select */
2006-05-13 21:07:53 +04:00
out_be32 ( ( volatile unsigned * ) GPIO0_TSRH , in_be32 ( ( volatile unsigned * ) GPIO0_TSRH ) & 0xC0FFFFFF ) ;
2005-04-17 02:20:36 +04:00
/* enable output driver */
2006-05-13 21:07:53 +04:00
out_be32 ( ( volatile unsigned * ) GPIO0_TCR ,
in_be32 ( ( volatile unsigned * ) GPIO0_TCR ) | NAND_nCE_GPIO_PIN | NAND_CLE_GPIO_PIN | NAND_ALE_GPIO_PIN ) ;
2005-04-17 02:20:36 +04:00
# ifdef USE_READY_BUSY_PIN
/* three-state select */
2006-05-13 21:07:53 +04:00
out_be32 ( ( volatile unsigned * ) GPIO0_TSRH , in_be32 ( ( volatile unsigned * ) GPIO0_TSRH ) & 0xFF3FFFFF ) ;
2005-04-17 02:20:36 +04:00
/* high-impedecence */
2006-05-13 21:07:53 +04:00
out_be32 ( ( volatile unsigned * ) GPIO0_TCR , in_be32 ( ( volatile unsigned * ) GPIO0_TCR ) & ( ~ NAND_RB_GPIO_PIN ) ) ;
2005-04-17 02:20:36 +04:00
/* input select */
2006-05-13 21:07:53 +04:00
out_be32 ( ( volatile unsigned * ) GPIO0_ISR1H ,
( in_be32 ( ( volatile unsigned * ) GPIO0_ISR1H ) & 0xFF3FFFFF ) | 0x00400000 ) ;
2005-04-17 02:20:36 +04:00
# endif
/* insert callbacks */
this - > IO_ADDR_R = ppchameleon_fio_base ;
this - > IO_ADDR_W = ppchameleon_fio_base ;
2006-05-24 01:25:53 +04:00
this - > cmd_ctrl = ppchameleon_hwcontrol ;
2005-04-17 02:20:36 +04:00
# ifdef USE_READY_BUSY_PIN
this - > dev_ready = ppchameleon_device_ready ;
# endif
this - > chip_delay = NAND_BIG_DELAY_US ;
/* ECC mode */
2006-05-23 14:00:46 +04:00
this - > ecc . mode = NAND_ECC_SOFT ;
2005-04-17 02:20:36 +04:00
/* Scan to find existence of the device (it could not be mounted) */
2006-05-13 21:07:53 +04:00
if ( nand_scan ( ppchameleon_mtd , 1 ) ) {
2005-04-17 02:20:36 +04:00
iounmap ( ( void * ) ppchameleon_fio_base ) ;
2006-09-21 16:42:43 +04:00
ppchameleon_fio_base = NULL ;
2006-05-13 21:07:53 +04:00
kfree ( ppchameleon_mtd ) ;
2005-04-17 02:20:36 +04:00
goto nand_evb_init ;
}
# ifndef USE_READY_BUSY_PIN
/* Adjust delay if necessary */
if ( ppchameleon_mtd - > size = = NAND_SMALL_SIZE )
this - > chip_delay = NAND_SMALL_DELAY_US ;
# endif
# ifdef CONFIG_MTD_PARTITIONS
ppchameleon_mtd - > name = " ppchameleon-nand " ;
mtd_parts_nb = parse_mtd_partitions ( ppchameleon_mtd , part_probes , & mtd_parts , 0 ) ;
if ( mtd_parts_nb > 0 )
2006-05-13 21:07:53 +04:00
part_type = " command line " ;
2005-04-17 02:20:36 +04:00
else
2006-05-13 21:07:53 +04:00
mtd_parts_nb = 0 ;
2005-04-17 02:20:36 +04:00
# endif
2006-05-13 21:07:53 +04:00
if ( mtd_parts_nb = = 0 ) {
2005-04-17 02:20:36 +04:00
if ( ppchameleon_mtd - > size = = NAND_SMALL_SIZE )
mtd_parts = partition_info_me ;
else
mtd_parts = partition_info_hi ;
mtd_parts_nb = NUM_PARTITIONS ;
part_type = " static " ;
}
/* Register the partitions */
printk ( KERN_NOTICE " Using %s partition definition \n " , part_type ) ;
add_mtd_partitions ( ppchameleon_mtd , mtd_parts , mtd_parts_nb ) ;
2006-05-13 21:07:53 +04:00
nand_evb_init :
2005-04-17 02:20:36 +04:00
/****************************
* EVB NAND ( always present ) *
* * * * * * * * * * * * * * * * * * * * * * * * * * * */
/* Allocate memory for MTD device structure and private data */
2006-05-13 21:07:53 +04:00
ppchameleonevb_mtd = kmalloc ( sizeof ( struct mtd_info ) + sizeof ( struct nand_chip ) , GFP_KERNEL ) ;
2005-04-17 02:20:36 +04:00
if ( ! ppchameleonevb_mtd ) {
printk ( " Unable to allocate PPChameleonEVB NAND MTD device structure. \n " ) ;
2006-09-21 16:42:43 +04:00
if ( ppchameleon_fio_base )
iounmap ( ppchameleon_fio_base ) ;
2005-04-17 02:20:36 +04:00
return - ENOMEM ;
}
/* map physical address */
ppchameleonevb_fio_base = ioremap ( ppchameleonevb_fio_pbase , SZ_4M ) ;
2006-05-13 21:07:53 +04:00
if ( ! ppchameleonevb_fio_base ) {
2005-04-17 02:20:36 +04:00
printk ( " ioremap PPChameleonEVB NAND flash failed \n " ) ;
kfree ( ppchameleonevb_mtd ) ;
2006-09-21 16:42:43 +04:00
if ( ppchameleon_fio_base )
iounmap ( ppchameleon_fio_base ) ;
2005-04-17 02:20:36 +04:00
return - EIO ;
}
/* Get pointer to private data */
2006-05-13 21:07:53 +04:00
this = ( struct nand_chip * ) ( & ppchameleonevb_mtd [ 1 ] ) ;
2005-04-17 02:20:36 +04:00
/* Initialize structures */
2006-05-13 21:07:53 +04:00
memset ( ppchameleonevb_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 */
ppchameleonevb_mtd - > priv = this ;
2006-05-13 21:07:53 +04:00
/* Initialize GPIOs */
2005-04-17 02:20:36 +04:00
/* Pin mapping for NAND chip */
/*
2006-05-13 21:07:53 +04:00
CE GPIO_14
CLE GPIO_15
ALE GPIO_16
R / B GPIO_31
*/
2005-04-17 02:20:36 +04:00
/* output select */
2006-05-13 21:07:53 +04:00
out_be32 ( ( volatile unsigned * ) GPIO0_OSRH , in_be32 ( ( volatile unsigned * ) GPIO0_OSRH ) & 0xFFFFFFF0 ) ;
out_be32 ( ( volatile unsigned * ) GPIO0_OSRL , in_be32 ( ( volatile unsigned * ) GPIO0_OSRL ) & 0x3FFFFFFF ) ;
2005-04-17 02:20:36 +04:00
/* three-state select */
2006-05-13 21:07:53 +04:00
out_be32 ( ( volatile unsigned * ) GPIO0_TSRH , in_be32 ( ( volatile unsigned * ) GPIO0_TSRH ) & 0xFFFFFFF0 ) ;
out_be32 ( ( volatile unsigned * ) GPIO0_TSRL , in_be32 ( ( volatile unsigned * ) GPIO0_TSRL ) & 0x3FFFFFFF ) ;
2005-04-17 02:20:36 +04:00
/* enable output driver */
2006-05-13 21:07:53 +04:00
out_be32 ( ( volatile unsigned * ) GPIO0_TCR , in_be32 ( ( volatile unsigned * ) GPIO0_TCR ) | NAND_EVB_nCE_GPIO_PIN |
2005-04-17 02:20:36 +04:00
NAND_EVB_CLE_GPIO_PIN | NAND_EVB_ALE_GPIO_PIN ) ;
# ifdef USE_READY_BUSY_PIN
/* three-state select */
2006-05-13 21:07:53 +04:00
out_be32 ( ( volatile unsigned * ) GPIO0_TSRL , in_be32 ( ( volatile unsigned * ) GPIO0_TSRL ) & 0xFFFFFFFC ) ;
2005-04-17 02:20:36 +04:00
/* high-impedecence */
2006-05-13 21:07:53 +04:00
out_be32 ( ( volatile unsigned * ) GPIO0_TCR , in_be32 ( ( volatile unsigned * ) GPIO0_TCR ) & ( ~ NAND_EVB_RB_GPIO_PIN ) ) ;
2005-04-17 02:20:36 +04:00
/* input select */
2006-05-13 21:07:53 +04:00
out_be32 ( ( volatile unsigned * ) GPIO0_ISR1L ,
( in_be32 ( ( volatile unsigned * ) GPIO0_ISR1L ) & 0xFFFFFFFC ) | 0x00000001 ) ;
2005-04-17 02:20:36 +04:00
# endif
/* insert callbacks */
this - > IO_ADDR_R = ppchameleonevb_fio_base ;
this - > IO_ADDR_W = ppchameleonevb_fio_base ;
2006-05-24 01:25:53 +04:00
this - > cmd_ctrl = ppchameleonevb_hwcontrol ;
2005-04-17 02:20:36 +04:00
# ifdef USE_READY_BUSY_PIN
this - > dev_ready = ppchameleonevb_device_ready ;
# endif
this - > chip_delay = NAND_SMALL_DELAY_US ;
/* ECC mode */
2006-05-23 14:00:46 +04:00
this - > ecc . mode = NAND_ECC_SOFT ;
2005-04-17 02:20:36 +04:00
/* Scan to find existence of the device */
2006-05-13 21:07:53 +04:00
if ( nand_scan ( ppchameleonevb_mtd , 1 ) ) {
2005-04-17 02:20:36 +04:00
iounmap ( ( void * ) ppchameleonevb_fio_base ) ;
2006-05-13 21:07:53 +04:00
kfree ( ppchameleonevb_mtd ) ;
2006-09-21 16:42:43 +04:00
if ( ppchameleon_fio_base )
iounmap ( ppchameleon_fio_base ) ;
2005-04-17 02:20:36 +04:00
return - ENXIO ;
}
# ifdef CONFIG_MTD_PARTITIONS
ppchameleonevb_mtd - > name = NAND_EVB_MTD_NAME ;
mtd_parts_nb = parse_mtd_partitions ( ppchameleonevb_mtd , part_probes_evb , & mtd_parts , 0 ) ;
if ( mtd_parts_nb > 0 )
2006-05-13 21:07:53 +04:00
part_type = " command line " ;
2005-04-17 02:20:36 +04:00
else
2006-05-13 21:07:53 +04:00
mtd_parts_nb = 0 ;
2005-04-17 02:20:36 +04:00
# endif
2006-05-13 21:07:53 +04:00
if ( mtd_parts_nb = = 0 ) {
2005-04-17 02:20:36 +04:00
mtd_parts = partition_info_evb ;
mtd_parts_nb = NUM_PARTITIONS ;
part_type = " static " ;
}
/* Register the partitions */
printk ( KERN_NOTICE " Using %s partition definition \n " , part_type ) ;
add_mtd_partitions ( ppchameleonevb_mtd , mtd_parts , mtd_parts_nb ) ;
/* Return happy */
return 0 ;
}
2006-05-13 21:07:53 +04:00
2005-04-17 02:20:36 +04:00
module_init ( ppchameleonevb_init ) ;
/*
* Clean up routine
*/
2006-05-13 21:07:53 +04:00
static void __exit ppchameleonevb_cleanup ( void )
2005-04-17 02:20:36 +04:00
{
struct nand_chip * this ;
/* Release resources, unregister device(s) */
2006-05-13 21:07:53 +04:00
nand_release ( ppchameleon_mtd ) ;
nand_release ( ppchameleonevb_mtd ) ;
2005-11-07 14:15:49 +03:00
2005-04-17 02:20:36 +04:00
/* Release iomaps */
this = ( struct nand_chip * ) & ppchameleon_mtd [ 1 ] ;
2007-06-01 11:46:36 +04:00
iounmap ( ( void * ) this - > IO_ADDR_R ) ;
2005-04-17 02:20:36 +04:00
this = ( struct nand_chip * ) & ppchameleonevb_mtd [ 1 ] ;
2007-06-01 11:46:36 +04:00
iounmap ( ( void * ) this - > IO_ADDR_R ) ;
2005-04-17 02:20:36 +04:00
/* Free the MTD device structure */
kfree ( ppchameleon_mtd ) ;
kfree ( ppchameleonevb_mtd ) ;
}
module_exit ( ppchameleonevb_cleanup ) ;
MODULE_LICENSE ( " GPL " ) ;
MODULE_AUTHOR ( " DAVE Srl <support-ppchameleon@dave-tech.it> " ) ;
MODULE_DESCRIPTION ( " MTD map driver for DAVE Srl PPChameleonEVB board " ) ;