linux/drivers/mtd/maps/fortunet.c
<<
>>
Prefs
   1/* fortunet.c memory map
   2 *
   3 * $Id: fortunet.c,v 1.11 2005/11/07 11:14:27 gleixner Exp $
   4 */
   5
   6#include <linux/module.h>
   7#include <linux/types.h>
   8#include <linux/kernel.h>
   9#include <linux/init.h>
  10#include <linux/string.h>
  11
  12#include <linux/mtd/mtd.h>
  13#include <linux/mtd/map.h>
  14#include <linux/mtd/partitions.h>
  15
  16#include <asm/io.h>
  17
  18#define MAX_NUM_REGIONS         4
  19#define MAX_NUM_PARTITIONS      8
  20
  21#define DEF_WINDOW_ADDR_PHY     0x00000000
  22#define DEF_WINDOW_SIZE         0x00800000              // 8 Mega Bytes
  23
  24#define MTD_FORTUNET_PK         "MTD FortuNet: "
  25
  26#define MAX_NAME_SIZE           128
  27
  28struct map_region
  29{
  30        int                     window_addr_physical;
  31        int                     altbankwidth;
  32        struct map_info         map_info;
  33        struct mtd_info         *mymtd;
  34        struct mtd_partition    parts[MAX_NUM_PARTITIONS];
  35        char                    map_name[MAX_NAME_SIZE];
  36        char                    parts_name[MAX_NUM_PARTITIONS][MAX_NAME_SIZE];
  37};
  38
  39static struct map_region        map_regions[MAX_NUM_REGIONS];
  40static int                      map_regions_set[MAX_NUM_REGIONS] = {0,0,0,0};
  41static int                      map_regions_parts[MAX_NUM_REGIONS] = {0,0,0,0};
  42
  43
  44
  45struct map_info default_map = {
  46        .size = DEF_WINDOW_SIZE,
  47        .bankwidth = 4,
  48};
  49
  50static char * __init get_string_option(char *dest,int dest_size,char *sor)
  51{
  52        if(!dest_size)
  53                return sor;
  54        dest_size--;
  55        while(*sor)
  56        {
  57                if(*sor==',')
  58                {
  59                        sor++;
  60                        break;
  61                }
  62                else if(*sor=='\"')
  63                {
  64                        sor++;
  65                        while(*sor)
  66                        {
  67                                if(*sor=='\"')
  68                                {
  69                                        sor++;
  70                                        break;
  71                                }
  72                                *dest = *sor;
  73                                dest++;
  74                                sor++;
  75                                dest_size--;
  76                                if(!dest_size)
  77                                {
  78                                        *dest = 0;
  79                                        return sor;
  80                                }
  81                        }
  82                }
  83                else
  84                {
  85                        *dest = *sor;
  86                        dest++;
  87                        sor++;
  88                        dest_size--;
  89                        if(!dest_size)
  90                        {
  91                                *dest = 0;
  92                                return sor;
  93                        }
  94                }
  95        }
  96        *dest = 0;
  97        return sor;
  98}
  99
 100static int __init MTD_New_Region(char *line)
 101{
 102        char    string[MAX_NAME_SIZE];
 103        int     params[6];
 104        get_options (get_string_option(string,sizeof(string),line),6,params);
 105        if(params[0]<1)
 106        {
 107                printk(MTD_FORTUNET_PK "Bad parameters for MTD Region "
 108                        " name,region-number[,base,size,bankwidth,altbankwidth]\n");
 109                return 1;
 110        }
 111        if((params[1]<0)||(params[1]>=MAX_NUM_REGIONS))
 112        {
 113                printk(MTD_FORTUNET_PK "Bad region index of %d only have 0..%u regions\n",
 114                        params[1],MAX_NUM_REGIONS-1);
 115                return 1;
 116        }
 117        memset(&map_regions[params[1]],0,sizeof(map_regions[params[1]]));
 118        memcpy(&map_regions[params[1]].map_info,
 119                &default_map,sizeof(map_regions[params[1]].map_info));
 120        map_regions_set[params[1]] = 1;
 121        map_regions[params[1]].window_addr_physical = DEF_WINDOW_ADDR_PHY;
 122        map_regions[params[1]].altbankwidth = 2;
 123        map_regions[params[1]].mymtd = NULL;
 124        map_regions[params[1]].map_info.name = map_regions[params[1]].map_name;
 125        strcpy(map_regions[params[1]].map_info.name,string);
 126        if(params[0]>1)
 127        {
 128                map_regions[params[1]].window_addr_physical = params[2];
 129        }
 130        if(params[0]>2)
 131        {
 132                map_regions[params[1]].map_info.size = params[3];
 133        }
 134        if(params[0]>3)
 135        {
 136                map_regions[params[1]].map_info.bankwidth = params[4];
 137        }
 138        if(params[0]>4)
 139        {
 140                map_regions[params[1]].altbankwidth = params[5];
 141        }
 142        return 1;
 143}
 144
 145static int __init MTD_New_Partition(char *line)
 146{
 147        char    string[MAX_NAME_SIZE];
 148        int     params[4];
 149        get_options (get_string_option(string,sizeof(string),line),4,params);
 150        if(params[0]<3)
 151        {
 152                printk(MTD_FORTUNET_PK "Bad parameters for MTD Partition "
 153                        " name,region-number,size,offset\n");
 154                return 1;
 155        }
 156        if((params[1]<0)||(params[1]>=MAX_NUM_REGIONS))
 157        {
 158                printk(MTD_FORTUNET_PK "Bad region index of %d only have 0..%u regions\n",
 159                        params[1],MAX_NUM_REGIONS-1);
 160                return 1;
 161        }
 162        if(map_regions_parts[params[1]]>=MAX_NUM_PARTITIONS)
 163        {
 164                printk(MTD_FORTUNET_PK "Out of space for partition in this region\n");
 165                return 1;
 166        }
 167        map_regions[params[1]].parts[map_regions_parts[params[1]]].name =
 168                map_regions[params[1]]. parts_name[map_regions_parts[params[1]]];
 169        strcpy(map_regions[params[1]].parts[map_regions_parts[params[1]]].name,string);
 170        map_regions[params[1]].parts[map_regions_parts[params[1]]].size =
 171                params[2];
 172        map_regions[params[1]].parts[map_regions_parts[params[1]]].offset =
 173                params[3];
 174        map_regions[params[1]].parts[map_regions_parts[params[1]]].mask_flags = 0;
 175        map_regions_parts[params[1]]++;
 176        return 1;
 177}
 178
 179__setup("MTD_Region=", MTD_New_Region);
 180__setup("MTD_Partition=", MTD_New_Partition);
 181
 182/* Backwards-spelling-compatibility */
 183__setup("MTD_Partion=", MTD_New_Partition);
 184
 185int __init init_fortunet(void)
 186{
 187        int     ix,iy;
 188        for(iy=ix=0;ix<MAX_NUM_REGIONS;ix++)
 189        {
 190                if(map_regions_parts[ix]&&(!map_regions_set[ix]))
 191                {
 192                        printk(MTD_FORTUNET_PK "Region %d is not setup (Setting to default)\n",
 193                                ix);
 194                        memset(&map_regions[ix],0,sizeof(map_regions[ix]));
 195                        memcpy(&map_regions[ix].map_info,&default_map,
 196                                sizeof(map_regions[ix].map_info));
 197                        map_regions_set[ix] = 1;
 198                        map_regions[ix].window_addr_physical = DEF_WINDOW_ADDR_PHY;
 199                        map_regions[ix].altbankwidth = 2;
 200                        map_regions[ix].mymtd = NULL;
 201                        map_regions[ix].map_info.name = map_regions[ix].map_name;
 202                        strcpy(map_regions[ix].map_info.name,"FORTUNET");
 203                }
 204                if(map_regions_set[ix])
 205                {
 206                        iy++;
 207                        printk(KERN_NOTICE MTD_FORTUNET_PK "%s flash device at physically "
 208                                " address %x size %x\n",
 209                                map_regions[ix].map_info.name,
 210                                map_regions[ix].window_addr_physical,
 211                                map_regions[ix].map_info.size);
 212
 213                        map_regions[ix].map_info.phys = map_regions[ix].window_addr_physical,
 214
 215                        map_regions[ix].map_info.virt =
 216                                ioremap_nocache(
 217                                map_regions[ix].window_addr_physical,
 218                                map_regions[ix].map_info.size);
 219                        if(!map_regions[ix].map_info.virt)
 220                        {
 221                                int j = 0;
 222                                printk(MTD_FORTUNET_PK "%s flash failed to ioremap!\n",
 223                                        map_regions[ix].map_info.name);
 224                                for (j = 0 ; j < ix; j++)
 225                                        iounmap(map_regions[j].map_info.virt);
 226                                return -ENXIO;
 227                        }
 228                        simple_map_init(&map_regions[ix].map_info);
 229
 230                        printk(KERN_NOTICE MTD_FORTUNET_PK "%s flash is virtually at: %x\n",
 231                                map_regions[ix].map_info.name,
 232                                map_regions[ix].map_info.virt);
 233                        map_regions[ix].mymtd = do_map_probe("cfi_probe",
 234                                &map_regions[ix].map_info);
 235                        if((!map_regions[ix].mymtd)&&(
 236                                map_regions[ix].altbankwidth!=map_regions[ix].map_info.bankwidth))
 237                        {
 238                                printk(KERN_NOTICE MTD_FORTUNET_PK "Trying alternate bankwidth "
 239                                        "for %s flash.\n",
 240                                        map_regions[ix].map_info.name);
 241                                map_regions[ix].map_info.bankwidth =
 242                                        map_regions[ix].altbankwidth;
 243                                map_regions[ix].mymtd = do_map_probe("cfi_probe",
 244                                        &map_regions[ix].map_info);
 245                        }
 246                        map_regions[ix].mymtd->owner = THIS_MODULE;
 247                        add_mtd_partitions(map_regions[ix].mymtd,
 248                                map_regions[ix].parts,map_regions_parts[ix]);
 249                }
 250        }
 251        if(iy)
 252                return 0;
 253        return -ENXIO;
 254}
 255
 256static void __exit cleanup_fortunet(void)
 257{
 258        int     ix;
 259        for(ix=0;ix<MAX_NUM_REGIONS;ix++)
 260        {
 261                if(map_regions_set[ix])
 262                {
 263                        if( map_regions[ix].mymtd )
 264                        {
 265                                del_mtd_partitions( map_regions[ix].mymtd );
 266                                map_destroy( map_regions[ix].mymtd );
 267                        }
 268                        iounmap((void *)map_regions[ix].map_info.virt);
 269                }
 270        }
 271}
 272
 273module_init(init_fortunet);
 274module_exit(cleanup_fortunet);
 275
 276MODULE_AUTHOR("FortuNet, Inc.");
 277MODULE_DESCRIPTION("MTD map driver for FortuNet boards");
 278