special usb hub handling, IDE disks, and retries all over the place
[linux-2.4.git] / drivers / mtd / maps / fortunet.c
1 /* fortunet.c memory map
2  *
3  * $Id: fortunet.c,v 1.2 2002/10/14 12:50:22 rmk Exp $
4  */
5
6 #include <linux/module.h>
7 #include <linux/types.h>
8 #include <linux/kernel.h>
9 #include <asm/io.h>
10 #include <linux/mtd/mtd.h>
11 #include <linux/mtd/map.h>
12 #include <linux/mtd/partitions.h>
13
14 #define MAX_NUM_REGIONS         4
15 #define MAX_NUM_PARTITIONS      8
16
17 #define DEF_WINDOW_ADDR_PHY     0x00000000
18 #define DEF_WINDOW_SIZE         0x00800000              // 8 Mega Bytes
19
20 #define MTD_FORTUNET_PK         "MTD FortuNet: "
21
22 #define MAX_NAME_SIZE           128
23
24 struct map_region
25 {
26         int                     window_addr_phyical;
27         int                     altbuswidth;
28         struct map_info         map_info;
29         struct mtd_info         *mymtd;
30         struct mtd_partition    parts[MAX_NUM_PARTITIONS];
31         char                    map_name[MAX_NAME_SIZE];
32         char                    parts_name[MAX_NUM_PARTITIONS][MAX_NAME_SIZE];
33 };
34
35 static struct map_region        map_regions[MAX_NUM_REGIONS];
36 static int                      map_regions_set[MAX_NUM_REGIONS] = {0,0,0,0};
37 static int                      map_regions_parts[MAX_NUM_REGIONS] = {0,0,0,0};
38
39
40 __u8 fortunet_read8(struct map_info *map, unsigned long ofs)
41 {
42         return *(__u8 *)(map->map_priv_1 + ofs);
43 }
44
45 __u16 fortunet_read16(struct map_info *map, unsigned long ofs)
46 {
47         return *(__u16 *)(map->map_priv_1 + ofs);
48 }
49
50 __u32 fortunet_read32(struct map_info *map, unsigned long ofs)
51 {
52         return *(__u32 *)(map->map_priv_1 + ofs);
53 }
54
55 void fortunet_copy_from(struct map_info *map, void *to, unsigned long from, ssize_t len)
56 {
57         memcpy(to, (void *)(map->map_priv_1 + from), len);
58 }
59
60 void fortunet_write8(struct map_info *map, __u8 d, unsigned long adr)
61 {
62         *(__u8 *)(map->map_priv_1 + adr) = d;
63 }
64
65 void fortunet_write16(struct map_info *map, __u16 d, unsigned long adr)
66 {
67         *(__u16 *)(map->map_priv_1 + adr) = d;
68 }
69
70 void fortunet_write32(struct map_info *map, __u32 d, unsigned long adr)
71 {
72         *(__u32 *)(map->map_priv_1 + adr) = d;
73 }
74
75 void fortunet_copy_to(struct map_info *map, unsigned long to, const void *from, ssize_t len)
76 {
77         memcpy((void *)(map->map_priv_1 + to), from, len);
78 }
79
80 struct map_info default_map = {
81         size: DEF_WINDOW_SIZE,
82         buswidth: 4,
83         read8: fortunet_read8,
84         read16: fortunet_read16,
85         read32: fortunet_read32,
86         copy_from: fortunet_copy_from,
87         write8: fortunet_write8,
88         write16: fortunet_write16,
89         write32: fortunet_write32,
90         copy_to: fortunet_copy_to
91 };
92
93 static char * __init get_string_option(char *dest,int dest_size,char *sor)
94 {
95         if(!dest_size)
96                 return sor;
97         dest_size--;
98         while(*sor)
99         {
100                 if(*sor==',')
101                 {
102                         sor++;
103                         break;
104                 }
105                 else if(*sor=='\"')
106                 {
107                         sor++;
108                         while(*sor)
109                         {
110                                 if(*sor=='\"')
111                                 {
112                                         sor++;
113                                         break;
114                                 }
115                                 *dest = *sor;
116                                 dest++;
117                                 sor++;
118                                 dest_size--;
119                                 if(!dest_size)
120                                 {
121                                         *dest = 0;
122                                         return sor;
123                                 }
124                         }
125                 }
126                 else
127                 {
128                         *dest = *sor;
129                         dest++;
130                         sor++;
131                         dest_size--;
132                         if(!dest_size)
133                         {
134                                 *dest = 0;
135                                 return sor;
136                         }
137                 }
138         }
139         *dest = 0;
140         return sor;
141 }
142
143 static int __init MTD_New_Region(char *line)
144 {
145         char    string[MAX_NAME_SIZE];
146         int     params[6];
147         get_options (get_string_option(string,sizeof(string),line),6,params);
148         if(params[0]<1)
149         {
150                 printk(MTD_FORTUNET_PK "Bad paramters for MTD Region "
151                         " name,region-number[,base,size,buswidth,altbuswidth]\n");
152                 return 1;
153         }
154         if((params[1]<0)||(params[1]>=MAX_NUM_REGIONS))
155         {
156                 printk(MTD_FORTUNET_PK "Bad region index of %d only have 0..%u regions\n",
157                         params[1],MAX_NUM_REGIONS-1);
158                 return 1;
159         }
160         memset(&map_regions[params[1]],0,sizeof(map_regions[params[1]]));
161         memcpy(&map_regions[params[1]].map_info,
162                 &default_map,sizeof(map_regions[params[1]].map_info));
163         map_regions_set[params[1]] = 1;
164         map_regions[params[1]].window_addr_phyical = DEF_WINDOW_ADDR_PHY;
165         map_regions[params[1]].altbuswidth = 2;
166         map_regions[params[1]].mymtd = NULL;
167         map_regions[params[1]].map_info.name = map_regions[params[1]].map_name;
168         strcpy(map_regions[params[1]].map_info.name,string);
169         if(params[0]>1)
170         {
171                 map_regions[params[1]].window_addr_phyical = params[2];
172         }
173         if(params[0]>2)
174         {
175                 map_regions[params[1]].map_info.size = params[3];
176         }
177         if(params[0]>3)
178         {
179                 map_regions[params[1]].map_info.buswidth = params[4];
180         }
181         if(params[0]>4)
182         {
183                 map_regions[params[1]].altbuswidth = params[5];
184         }
185         return 1;
186 }
187
188 static int __init MTD_New_Partion(char *line)
189 {
190         char    string[MAX_NAME_SIZE];
191         int     params[4];
192         get_options (get_string_option(string,sizeof(string),line),4,params);
193         if(params[0]<3)
194         {
195                 printk(MTD_FORTUNET_PK "Bad paramters for MTD Partion "
196                         " name,region-number,size,offset\n");
197                 return 1;
198         }
199         if((params[1]<0)||(params[1]>=MAX_NUM_REGIONS))
200         {
201                 printk(MTD_FORTUNET_PK "Bad region index of %d only have 0..%u regions\n",
202                         params[1],MAX_NUM_REGIONS-1);
203                 return 1;
204         }
205         if(map_regions_parts[params[1]]>=MAX_NUM_PARTITIONS)
206         {
207                 printk(MTD_FORTUNET_PK "Out of space for partion in this region\n");
208                 return 1;
209         }
210         map_regions[params[1]].parts[map_regions_parts[params[1]]].name =
211                 map_regions[params[1]]. parts_name[map_regions_parts[params[1]]];
212         strcpy(map_regions[params[1]].parts[map_regions_parts[params[1]]].name,string);
213         map_regions[params[1]].parts[map_regions_parts[params[1]]].size =
214                 params[2];
215         map_regions[params[1]].parts[map_regions_parts[params[1]]].offset =
216                 params[3];
217         map_regions[params[1]].parts[map_regions_parts[params[1]]].mask_flags = 0;
218         map_regions_parts[params[1]]++;
219         return 1;
220 }
221
222 __setup("MTD_Region=", MTD_New_Region);
223 __setup("MTD_Partion=", MTD_New_Partion);
224
225 int __init init_fortunet(void)
226 {
227         int     ix,iy;
228         for(iy=ix=0;ix<MAX_NUM_REGIONS;ix++)
229         {
230                 if(map_regions_parts[ix]&&(!map_regions_set[ix]))
231                 {
232                         printk(MTD_FORTUNET_PK "Region %d is not setup (Seting to default)\n",
233                                 ix);
234                         memset(&map_regions[ix],0,sizeof(map_regions[ix]));
235                         memcpy(&map_regions[ix].map_info,&default_map,
236                                 sizeof(map_regions[ix].map_info));
237                         map_regions_set[ix] = 1;
238                         map_regions[ix].window_addr_phyical = DEF_WINDOW_ADDR_PHY;
239                         map_regions[ix].altbuswidth = 2;
240                         map_regions[ix].mymtd = NULL;
241                         map_regions[ix].map_info.name = map_regions[ix].map_name;
242                         strcpy(map_regions[ix].map_info.name,"FORTUNET");
243                 }
244                 if(map_regions_set[ix])
245                 {
246                         iy++;
247                         printk(KERN_NOTICE MTD_FORTUNET_PK "%s flash device at phyicaly "
248                                 " address %x size %x\n",
249                                 map_regions[ix].map_info.name,
250                                 map_regions[ix].window_addr_phyical,
251                                 map_regions[ix].map_info.size);
252                         map_regions[ix].map_info.map_priv_1 =
253                                 (int)ioremap_nocache(
254                                 map_regions[ix].window_addr_phyical,
255                                 map_regions[ix].map_info.size);
256                         if(!map_regions[ix].map_info.map_priv_1)
257                         {
258                                 printk(MTD_FORTUNET_PK "%s flash failed to ioremap!\n",
259                                         map_regions[ix].map_info.name);
260                                 return -ENXIO;
261                         }
262                         printk(KERN_NOTICE MTD_FORTUNET_PK "%s flash is veritualy at: %x\n",
263                                 map_regions[ix].map_info.name,
264                                 map_regions[ix].map_info.map_priv_1);
265                         map_regions[ix].mymtd = do_map_probe("cfi_probe",
266                                 &map_regions[ix].map_info);
267                         if((!map_regions[ix].mymtd)&&(
268                                 map_regions[ix].altbuswidth!=map_regions[ix].map_info.buswidth))
269                         {
270                                 printk(KERN_NOTICE MTD_FORTUNET_PK "Trying alternet buswidth "
271                                         "for %s flash.\n",
272                                         map_regions[ix].map_info.name);
273                                 map_regions[ix].map_info.buswidth =
274                                         map_regions[ix].altbuswidth;
275                                 map_regions[ix].mymtd = do_map_probe("cfi_probe",
276                                         &map_regions[ix].map_info);
277                         }
278                         map_regions[ix].mymtd->module = THIS_MODULE;
279                         add_mtd_partitions(map_regions[ix].mymtd,
280                                 map_regions[ix].parts,map_regions_parts[ix]);
281                 }
282         }
283         if(iy)
284                 return 0;
285         return -ENXIO;
286 }
287
288 static void __exit cleanup_fortunet(void)
289 {
290         int     ix;
291         for(ix=0;ix<MAX_NUM_REGIONS;ix++)
292         {
293                 if(map_regions_set[ix])
294                 {
295                         if( map_regions[ix].mymtd )
296                         {
297                                 del_mtd_partitions( map_regions[ix].mymtd );
298                                 map_destroy( map_regions[ix].mymtd );
299                         }
300                         iounmap((void *)map_regions[ix].map_info.map_priv_1);
301                 }
302         }
303 }
304
305 module_init(init_fortunet);
306 module_exit(cleanup_fortunet);
307
308 MODULE_AUTHOR("FortuNet, Inc.");
309 MODULE_DESCRIPTION("MTD map driver for FortuNet boards");