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