2005-04-17 02:20:36 +04:00
/*
* MTD map driver for flash on the DC21285 ( the StrongARM - 110 companion chip )
*
2009-09-14 11:25:28 +04:00
* ( C ) 2000 Nicolas Pitre < nico @ fluxnic . net >
2005-04-17 02:20:36 +04:00
*
* This code is GPL
*/
# include <linux/module.h>
# include <linux/types.h>
# include <linux/kernel.h>
# include <linux/init.h>
# include <linux/delay.h>
2005-10-31 02:03:48 +03:00
# include <linux/slab.h>
2005-04-17 02:20:36 +04:00
# include <linux/mtd/mtd.h>
# include <linux/mtd/map.h>
# include <linux/mtd/partitions.h>
# include <asm/io.h>
# include <asm/hardware/dec21285.h>
# include <asm/mach-types.h>
static struct mtd_info * dc21285_mtd ;
# ifdef CONFIG_ARCH_NETWINDER
2005-11-07 14:15:40 +03:00
/*
2005-04-17 02:20:36 +04:00
* This is really ugly , but it seams to be the only
2005-11-07 14:15:40 +03:00
* realiable way to do it , as the cpld state machine
2005-04-17 02:20:36 +04:00
* is unpredictible . So we have a 25u s penalty per
* write access .
*/
static void nw_en_write ( void )
{
unsigned long flags ;
/*
* we want to write a bit pattern XXX1 to Xilinx to enable
* the write gate , which will be open for about the next 2 ms .
*/
mtd: dc21285: use raw spinlock functions for nw_gpio_lock
Since commit bd31b85960a7 (which is in 3.2-rc1) nw_gpio_lock is a raw spinlock
that needs usage of the corresponding raw functions.
This fixes:
drivers/mtd/maps/dc21285.c: In function 'nw_en_write':
drivers/mtd/maps/dc21285.c:41:340: warning: passing argument 1 of 'spinlock_check' from incompatible pointer type
spin_lock_irqsave(&nw_gpio_lock, flags);
In file included from include/linux/seqlock.h:35:0,
from include/linux/time.h:5,
from include/linux/stat.h:18,
from include/linux/module.h:10,
from drivers/mtd/maps/dc21285.c:8:
include/linux/spinlock.h:299:102: note: expected 'struct spinlock_t *' but argument is of type 'struct raw_spinlock_t *'
static inline raw_spinlock_t *spinlock_check(spinlock_t *lock)
^
drivers/mtd/maps/dc21285.c:43:25: warning: passing argument 1 of 'spin_unlock_irqrestore' from incompatible pointer type
spin_unlock_irqrestore(&nw_gpio_lock, flags);
^
In file included from include/linux/seqlock.h:35:0,
from include/linux/time.h:5,
from include/linux/stat.h:18,
from include/linux/module.h:10,
from drivers/mtd/maps/dc21285.c:8:
include/linux/spinlock.h:370:91: note: expected 'struct spinlock_t *' but argument is of type 'struct raw_spinlock_t *'
static inline void spin_unlock_irqrestore(spinlock_t *lock, unsigned long flags)
Fixes: bd31b85960a7 ("locking, ARM: Annotate low level hw locks as raw")
Signed-off-by: Uwe Kleine-König <u.kleine-koenig@pengutronix.de>
Signed-off-by: Brian Norris <computersforpeace@gmail.com>
2015-05-28 11:22:10 +03:00
raw_spin_lock_irqsave ( & nw_gpio_lock , flags ) ;
2008-12-06 11:25:16 +03:00
nw_cpld_modify ( CPLD_FLASH_WR_ENABLE , CPLD_FLASH_WR_ENABLE ) ;
mtd: dc21285: use raw spinlock functions for nw_gpio_lock
Since commit bd31b85960a7 (which is in 3.2-rc1) nw_gpio_lock is a raw spinlock
that needs usage of the corresponding raw functions.
This fixes:
drivers/mtd/maps/dc21285.c: In function 'nw_en_write':
drivers/mtd/maps/dc21285.c:41:340: warning: passing argument 1 of 'spinlock_check' from incompatible pointer type
spin_lock_irqsave(&nw_gpio_lock, flags);
In file included from include/linux/seqlock.h:35:0,
from include/linux/time.h:5,
from include/linux/stat.h:18,
from include/linux/module.h:10,
from drivers/mtd/maps/dc21285.c:8:
include/linux/spinlock.h:299:102: note: expected 'struct spinlock_t *' but argument is of type 'struct raw_spinlock_t *'
static inline raw_spinlock_t *spinlock_check(spinlock_t *lock)
^
drivers/mtd/maps/dc21285.c:43:25: warning: passing argument 1 of 'spin_unlock_irqrestore' from incompatible pointer type
spin_unlock_irqrestore(&nw_gpio_lock, flags);
^
In file included from include/linux/seqlock.h:35:0,
from include/linux/time.h:5,
from include/linux/stat.h:18,
from include/linux/module.h:10,
from drivers/mtd/maps/dc21285.c:8:
include/linux/spinlock.h:370:91: note: expected 'struct spinlock_t *' but argument is of type 'struct raw_spinlock_t *'
static inline void spin_unlock_irqrestore(spinlock_t *lock, unsigned long flags)
Fixes: bd31b85960a7 ("locking, ARM: Annotate low level hw locks as raw")
Signed-off-by: Uwe Kleine-König <u.kleine-koenig@pengutronix.de>
Signed-off-by: Brian Norris <computersforpeace@gmail.com>
2015-05-28 11:22:10 +03:00
raw_spin_unlock_irqrestore ( & nw_gpio_lock , flags ) ;
2005-04-17 02:20:36 +04:00
/*
* let the ISA bus to catch on . . .
*/
udelay ( 25 ) ;
}
# else
# define nw_en_write() do { } while (0)
# endif
static map_word dc21285_read8 ( struct map_info * map , unsigned long ofs )
{
map_word val ;
val . x [ 0 ] = * ( uint8_t * ) ( map - > virt + ofs ) ;
return val ;
}
static map_word dc21285_read16 ( struct map_info * map , unsigned long ofs )
{
map_word val ;
val . x [ 0 ] = * ( uint16_t * ) ( map - > virt + ofs ) ;
return val ;
}
static map_word dc21285_read32 ( struct map_info * map , unsigned long ofs )
{
map_word val ;
val . x [ 0 ] = * ( uint32_t * ) ( map - > virt + ofs ) ;
return val ;
}
static void dc21285_copy_from ( struct map_info * map , void * to , unsigned long from , ssize_t len )
{
memcpy ( to , ( void * ) ( map - > virt + from ) , len ) ;
}
static void dc21285_write8 ( struct map_info * map , const map_word d , unsigned long adr )
{
if ( machine_is_netwinder ( ) )
nw_en_write ( ) ;
* CSR_ROMWRITEREG = adr & 3 ;
adr & = ~ 3 ;
* ( uint8_t * ) ( map - > virt + adr ) = d . x [ 0 ] ;
}
static void dc21285_write16 ( struct map_info * map , const map_word d , unsigned long adr )
{
if ( machine_is_netwinder ( ) )
nw_en_write ( ) ;
* CSR_ROMWRITEREG = adr & 3 ;
adr & = ~ 3 ;
* ( uint16_t * ) ( map - > virt + adr ) = d . x [ 0 ] ;
}
static void dc21285_write32 ( struct map_info * map , const map_word d , unsigned long adr )
{
if ( machine_is_netwinder ( ) )
nw_en_write ( ) ;
* ( uint32_t * ) ( map - > virt + adr ) = d . x [ 0 ] ;
}
static void dc21285_copy_to_32 ( struct map_info * map , unsigned long to , const void * from , ssize_t len )
{
while ( len > 0 ) {
map_word d ;
2006-02-03 14:03:47 +03:00
d . x [ 0 ] = * ( ( uint32_t * ) from ) ;
2005-04-17 02:20:36 +04:00
dc21285_write32 ( map , d , to ) ;
2006-02-03 14:03:47 +03:00
from + = 4 ;
2005-04-17 02:20:36 +04:00
to + = 4 ;
len - = 4 ;
}
}
static void dc21285_copy_to_16 ( struct map_info * map , unsigned long to , const void * from , ssize_t len )
{
while ( len > 0 ) {
map_word d ;
2006-02-03 14:03:47 +03:00
d . x [ 0 ] = * ( ( uint16_t * ) from ) ;
2005-04-17 02:20:36 +04:00
dc21285_write16 ( map , d , to ) ;
2006-02-03 14:03:47 +03:00
from + = 2 ;
2005-04-17 02:20:36 +04:00
to + = 2 ;
len - = 2 ;
}
}
static void dc21285_copy_to_8 ( struct map_info * map , unsigned long to , const void * from , ssize_t len )
{
map_word d ;
2006-02-03 14:03:47 +03:00
d . x [ 0 ] = * ( ( uint8_t * ) from ) ;
2005-04-17 02:20:36 +04:00
dc21285_write8 ( map , d , to ) ;
2006-02-03 14:03:47 +03:00
from + + ;
2005-04-17 02:20:36 +04:00
to + + ;
len - - ;
}
static struct map_info dc21285_map = {
. name = " DC21285 flash " ,
. phys = NO_XIP ,
. size = 16 * 1024 * 1024 ,
. copy_from = dc21285_copy_from ,
} ;
/* Partition stuff */
2013-03-12 12:46:37 +04:00
static const char * const probes [ ] = { " RedBoot " , " cmdlinepart " , NULL } ;
2005-11-07 14:15:40 +03:00
2005-04-17 02:20:36 +04:00
static int __init init_dc21285 ( void )
{
/* Determine bankwidth */
switch ( * CSR_SA110_CNTL & ( 3 < < 14 ) ) {
2005-11-07 14:15:40 +03:00
case SA110_CNTL_ROMWIDTH_8 :
2005-04-17 02:20:36 +04:00
dc21285_map . bankwidth = 1 ;
dc21285_map . read = dc21285_read8 ;
dc21285_map . write = dc21285_write8 ;
dc21285_map . copy_to = dc21285_copy_to_8 ;
break ;
2005-11-07 14:15:40 +03:00
case SA110_CNTL_ROMWIDTH_16 :
dc21285_map . bankwidth = 2 ;
2005-04-17 02:20:36 +04:00
dc21285_map . read = dc21285_read16 ;
dc21285_map . write = dc21285_write16 ;
dc21285_map . copy_to = dc21285_copy_to_16 ;
break ;
2005-11-07 14:15:40 +03:00
case SA110_CNTL_ROMWIDTH_32 :
dc21285_map . bankwidth = 4 ;
2005-04-17 02:20:36 +04:00
dc21285_map . read = dc21285_read32 ;
dc21285_map . write = dc21285_write32 ;
dc21285_map . copy_to = dc21285_copy_to_32 ;
break ;
default :
printk ( KERN_ERR " DC21285 flash: undefined bankwidth \n " ) ;
return - ENXIO ;
}
printk ( KERN_NOTICE " DC21285 flash support (%d-bit bankwidth) \n " ,
dc21285_map . bankwidth * 8 ) ;
/* Let's map the flash area */
dc21285_map . virt = ioremap ( DC21285_FLASH , 16 * 1024 * 1024 ) ;
if ( ! dc21285_map . virt ) {
printk ( " Failed to ioremap \n " ) ;
return - EIO ;
}
if ( machine_is_ebsa285 ( ) ) {
dc21285_mtd = do_map_probe ( " cfi_probe " , & dc21285_map ) ;
} else {
dc21285_mtd = do_map_probe ( " jedec_probe " , & dc21285_map ) ;
}
if ( ! dc21285_mtd ) {
iounmap ( dc21285_map . virt ) ;
return - ENXIO ;
2005-11-07 14:15:40 +03:00
}
2005-04-17 02:20:36 +04:00
dc21285_mtd - > owner = THIS_MODULE ;
mtd: do not use plain 0 as NULL
The first 3 arguments of 'mtd_device_parse_register()' are pointers,
but many callers pass '0' instead of 'NULL'. Fix this globally. Thanks
to coccinelle for making it easy to do with the following semantic patch:
@@
expression mtd, types, parser_data, parts, nr_parts;
@@
(
-mtd_device_parse_register(mtd, 0, parser_data, parts, nr_parts)
+mtd_device_parse_register(mtd, NULL, parser_data, parts, nr_parts)
|
-mtd_device_parse_register(mtd, types, 0, parts, nr_parts)
+mtd_device_parse_register(mtd, types, NULL, parts, nr_parts)
|
-mtd_device_parse_register(mtd, types, parser_data, 0, nr_parts)
+mtd_device_parse_register(mtd, types, parser_data, NULL, nr_parts)
)
Signed-off-by: Artem Bityutskiy <artem.bityutskiy@linux.intel.com>
Signed-off-by: David Woodhouse <David.Woodhouse@intel.com>
2012-03-09 21:24:26 +04:00
mtd_device_parse_register ( dc21285_mtd , probes , NULL , NULL , 0 ) ;
2005-11-07 14:15:40 +03:00
2005-04-17 02:20:36 +04:00
if ( machine_is_ebsa285 ( ) ) {
2005-11-07 14:15:40 +03:00
/*
2005-04-17 02:20:36 +04:00
* Flash timing is determined with bits 19 - 16 of the
* CSR_SA110_CNTL . The value is the number of wait cycles , or
* 0 for 16 cycles ( the default ) . Cycles are 20 ns .
* Here we use 7 for 140 ns flash chips .
*/
/* access time */
* CSR_SA110_CNTL = ( ( * CSR_SA110_CNTL & ~ 0x000f0000 ) | ( 7 < < 16 ) ) ;
/* burst time */
* CSR_SA110_CNTL = ( ( * CSR_SA110_CNTL & ~ 0x00f00000 ) | ( 7 < < 20 ) ) ;
/* tristate time */
* CSR_SA110_CNTL = ( ( * CSR_SA110_CNTL & ~ 0x0f000000 ) | ( 7 < < 24 ) ) ;
}
2005-11-07 14:15:40 +03:00
2005-04-17 02:20:36 +04:00
return 0 ;
}
static void __exit cleanup_dc21285 ( void )
{
2011-05-23 13:23:00 +04:00
mtd_device_unregister ( dc21285_mtd ) ;
2005-04-17 02:20:36 +04:00
map_destroy ( dc21285_mtd ) ;
iounmap ( dc21285_map . virt ) ;
}
module_init ( init_dc21285 ) ;
module_exit ( cleanup_dc21285 ) ;
MODULE_LICENSE ( " GPL " ) ;
2009-09-14 11:25:28 +04:00
MODULE_AUTHOR ( " Nicolas Pitre <nico@fluxnic.net> " ) ;
2005-04-17 02:20:36 +04:00
MODULE_DESCRIPTION ( " MTD map driver for DC21285 boards " ) ;