2005-04-16 15:20:36 -07:00
/* fortunet.c memory map
*
*/
# include <linux/module.h>
# include <linux/types.h>
# include <linux/kernel.h>
# include <linux/init.h>
2005-10-30 15:03:48 -08:00
# include <linux/string.h>
2005-04-16 15:20:36 -07:00
# include <linux/mtd/mtd.h>
# include <linux/mtd/map.h>
# include <linux/mtd/partitions.h>
2005-10-30 15:03:48 -08:00
# include <asm/io.h>
2005-04-16 15:20:36 -07:00
# define MAX_NUM_REGIONS 4
# define MAX_NUM_PARTITIONS 8
# define DEF_WINDOW_ADDR_PHY 0x00000000
# define DEF_WINDOW_SIZE 0x00800000 // 8 Mega Bytes
# define MTD_FORTUNET_PK "MTD FortuNet: "
# define MAX_NAME_SIZE 128
struct map_region
{
int window_addr_physical ;
int altbankwidth ;
struct map_info map_info ;
struct mtd_info * mymtd ;
struct mtd_partition parts [ MAX_NUM_PARTITIONS ] ;
char map_name [ MAX_NAME_SIZE ] ;
char parts_name [ MAX_NUM_PARTITIONS ] [ MAX_NAME_SIZE ] ;
} ;
static struct map_region map_regions [ MAX_NUM_REGIONS ] ;
static int map_regions_set [ MAX_NUM_REGIONS ] = { 0 , 0 , 0 , 0 } ;
static int map_regions_parts [ MAX_NUM_REGIONS ] = { 0 , 0 , 0 , 0 } ;
struct map_info default_map = {
. size = DEF_WINDOW_SIZE ,
. bankwidth = 4 ,
} ;
static char * __init get_string_option ( char * dest , int dest_size , char * sor )
{
if ( ! dest_size )
return sor ;
dest_size - - ;
while ( * sor )
{
if ( * sor = = ' , ' )
{
sor + + ;
break ;
}
else if ( * sor = = ' \" ' )
{
sor + + ;
while ( * sor )
{
if ( * sor = = ' \" ' )
{
sor + + ;
break ;
}
* dest = * sor ;
dest + + ;
sor + + ;
dest_size - - ;
if ( ! dest_size )
{
* dest = 0 ;
return sor ;
}
}
}
else
{
* dest = * sor ;
dest + + ;
sor + + ;
dest_size - - ;
if ( ! dest_size )
{
* dest = 0 ;
return sor ;
}
}
}
* dest = 0 ;
return sor ;
}
static int __init MTD_New_Region ( char * line )
{
char string [ MAX_NAME_SIZE ] ;
int params [ 6 ] ;
get_options ( get_string_option ( string , sizeof ( string ) , line ) , 6 , params ) ;
if ( params [ 0 ] < 1 )
{
printk ( MTD_FORTUNET_PK " Bad parameters for MTD Region "
" name,region-number[,base,size,bankwidth,altbankwidth] \n " ) ;
return 1 ;
}
if ( ( params [ 1 ] < 0 ) | | ( params [ 1 ] > = MAX_NUM_REGIONS ) )
{
printk ( MTD_FORTUNET_PK " Bad region index of %d only have 0..%u regions \n " ,
params [ 1 ] , MAX_NUM_REGIONS - 1 ) ;
return 1 ;
}
memset ( & map_regions [ params [ 1 ] ] , 0 , sizeof ( map_regions [ params [ 1 ] ] ) ) ;
memcpy ( & map_regions [ params [ 1 ] ] . map_info ,
& default_map , sizeof ( map_regions [ params [ 1 ] ] . map_info ) ) ;
map_regions_set [ params [ 1 ] ] = 1 ;
map_regions [ params [ 1 ] ] . window_addr_physical = DEF_WINDOW_ADDR_PHY ;
map_regions [ params [ 1 ] ] . altbankwidth = 2 ;
map_regions [ params [ 1 ] ] . mymtd = NULL ;
map_regions [ params [ 1 ] ] . map_info . name = map_regions [ params [ 1 ] ] . map_name ;
strcpy ( map_regions [ params [ 1 ] ] . map_info . name , string ) ;
if ( params [ 0 ] > 1 )
{
map_regions [ params [ 1 ] ] . window_addr_physical = params [ 2 ] ;
}
if ( params [ 0 ] > 2 )
{
map_regions [ params [ 1 ] ] . map_info . size = params [ 3 ] ;
}
if ( params [ 0 ] > 3 )
{
map_regions [ params [ 1 ] ] . map_info . bankwidth = params [ 4 ] ;
}
if ( params [ 0 ] > 4 )
{
map_regions [ params [ 1 ] ] . altbankwidth = params [ 5 ] ;
}
return 1 ;
}
static int __init MTD_New_Partition ( char * line )
{
char string [ MAX_NAME_SIZE ] ;
int params [ 4 ] ;
get_options ( get_string_option ( string , sizeof ( string ) , line ) , 4 , params ) ;
if ( params [ 0 ] < 3 )
{
printk ( MTD_FORTUNET_PK " Bad parameters for MTD Partition "
" name,region-number,size,offset \n " ) ;
return 1 ;
}
if ( ( params [ 1 ] < 0 ) | | ( params [ 1 ] > = MAX_NUM_REGIONS ) )
{
printk ( MTD_FORTUNET_PK " Bad region index of %d only have 0..%u regions \n " ,
params [ 1 ] , MAX_NUM_REGIONS - 1 ) ;
return 1 ;
}
if ( map_regions_parts [ params [ 1 ] ] > = MAX_NUM_PARTITIONS )
{
printk ( MTD_FORTUNET_PK " Out of space for partition in this region \n " ) ;
return 1 ;
}
map_regions [ params [ 1 ] ] . parts [ map_regions_parts [ params [ 1 ] ] ] . name =
map_regions [ params [ 1 ] ] . parts_name [ map_regions_parts [ params [ 1 ] ] ] ;
strcpy ( map_regions [ params [ 1 ] ] . parts [ map_regions_parts [ params [ 1 ] ] ] . name , string ) ;
map_regions [ params [ 1 ] ] . parts [ map_regions_parts [ params [ 1 ] ] ] . size =
params [ 2 ] ;
map_regions [ params [ 1 ] ] . parts [ map_regions_parts [ params [ 1 ] ] ] . offset =
params [ 3 ] ;
map_regions [ params [ 1 ] ] . parts [ map_regions_parts [ params [ 1 ] ] ] . mask_flags = 0 ;
map_regions_parts [ params [ 1 ] ] + + ;
return 1 ;
}
__setup ( " MTD_Region= " , MTD_New_Region ) ;
__setup ( " MTD_Partition= " , MTD_New_Partition ) ;
/* Backwards-spelling-compatibility */
__setup ( " MTD_Partion= " , MTD_New_Partition ) ;
2008-11-25 02:54:57 +02:00
static int __init init_fortunet ( void )
2005-04-16 15:20:36 -07:00
{
int ix , iy ;
for ( iy = ix = 0 ; ix < MAX_NUM_REGIONS ; ix + + )
{
if ( map_regions_parts [ ix ] & & ( ! map_regions_set [ ix ] ) )
{
printk ( MTD_FORTUNET_PK " Region %d is not setup (Setting to default) \n " ,
ix ) ;
memset ( & map_regions [ ix ] , 0 , sizeof ( map_regions [ ix ] ) ) ;
memcpy ( & map_regions [ ix ] . map_info , & default_map ,
sizeof ( map_regions [ ix ] . map_info ) ) ;
map_regions_set [ ix ] = 1 ;
map_regions [ ix ] . window_addr_physical = DEF_WINDOW_ADDR_PHY ;
map_regions [ ix ] . altbankwidth = 2 ;
map_regions [ ix ] . mymtd = NULL ;
map_regions [ ix ] . map_info . name = map_regions [ ix ] . map_name ;
strcpy ( map_regions [ ix ] . map_info . name , " FORTUNET " ) ;
}
if ( map_regions_set [ ix ] )
{
iy + + ;
printk ( KERN_NOTICE MTD_FORTUNET_PK " %s flash device at physically "
" address %x size %x \n " ,
map_regions [ ix ] . map_info . name ,
map_regions [ ix ] . window_addr_physical ,
map_regions [ ix ] . map_info . size ) ;
map_regions [ ix ] . map_info . phys = map_regions [ ix ] . window_addr_physical ,
2005-11-07 11:15:40 +00:00
map_regions [ ix ] . map_info . virt =
2005-04-16 15:20:36 -07:00
ioremap_nocache (
map_regions [ ix ] . window_addr_physical ,
map_regions [ ix ] . map_info . size ) ;
if ( ! map_regions [ ix ] . map_info . virt )
{
2006-09-21 18:12:43 +05:30
int j = 0 ;
2005-04-16 15:20:36 -07:00
printk ( MTD_FORTUNET_PK " %s flash failed to ioremap! \n " ,
map_regions [ ix ] . map_info . name ) ;
2006-09-21 18:12:43 +05:30
for ( j = 0 ; j < ix ; j + + )
iounmap ( map_regions [ j ] . map_info . virt ) ;
2005-04-16 15:20:36 -07:00
return - ENXIO ;
}
simple_map_init ( & map_regions [ ix ] . map_info ) ;
printk ( KERN_NOTICE MTD_FORTUNET_PK " %s flash is virtually at: %x \n " ,
map_regions [ ix ] . map_info . name ,
map_regions [ ix ] . map_info . virt ) ;
map_regions [ ix ] . mymtd = do_map_probe ( " cfi_probe " ,
& map_regions [ ix ] . map_info ) ;
if ( ( ! map_regions [ ix ] . mymtd ) & & (
map_regions [ ix ] . altbankwidth ! = map_regions [ ix ] . map_info . bankwidth ) )
{
printk ( KERN_NOTICE MTD_FORTUNET_PK " Trying alternate bankwidth "
" for %s flash. \n " ,
map_regions [ ix ] . map_info . name ) ;
map_regions [ ix ] . map_info . bankwidth =
map_regions [ ix ] . altbankwidth ;
map_regions [ ix ] . mymtd = do_map_probe ( " cfi_probe " ,
& map_regions [ ix ] . map_info ) ;
}
map_regions [ ix ] . mymtd - > owner = THIS_MODULE ;
add_mtd_partitions ( map_regions [ ix ] . mymtd ,
map_regions [ ix ] . parts , map_regions_parts [ ix ] ) ;
}
}
if ( iy )
return 0 ;
return - ENXIO ;
}
static void __exit cleanup_fortunet ( void )
{
int ix ;
for ( ix = 0 ; ix < MAX_NUM_REGIONS ; ix + + )
{
if ( map_regions_set [ ix ] )
{
if ( map_regions [ ix ] . mymtd )
{
del_mtd_partitions ( map_regions [ ix ] . mymtd ) ;
map_destroy ( map_regions [ ix ] . mymtd ) ;
}
iounmap ( ( void * ) map_regions [ ix ] . map_info . virt ) ;
}
}
}
module_init ( init_fortunet ) ;
module_exit ( cleanup_fortunet ) ;
MODULE_AUTHOR ( " FortuNet, Inc. " ) ;
MODULE_DESCRIPTION ( " MTD map driver for FortuNet boards " ) ;