blob: 00f7bbe5479e47d74aa5570e6d85d103d26f750d [file] [log] [blame]
Linus Torvalds1da177e2005-04-16 15:20:36 -07001/* fortunet.c memory map
2 *
3 * $Id: fortunet.c,v 1.9 2004/11/04 13:24:14 gleixner Exp $
4 */
5
6#include <linux/module.h>
7#include <linux/types.h>
8#include <linux/kernel.h>
9#include <linux/init.h>
Tim Schmielau4e57b682005-10-30 15:03:48 -080010#include <linux/string.h>
11
Linus Torvalds1da177e2005-04-16 15:20:36 -070012#include <linux/mtd/mtd.h>
13#include <linux/mtd/map.h>
14#include <linux/mtd/partitions.h>
15
Tim Schmielau4e57b682005-10-30 15:03:48 -080016#include <asm/io.h>
17
Linus Torvalds1da177e2005-04-16 15:20:36 -070018#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 printk(MTD_FORTUNET_PK "%s flash failed to ioremap!\n",
222 map_regions[ix].map_info.name);
223 return -ENXIO;
224 }
225 simple_map_init(&map_regions[ix].map_info);
226
227 printk(KERN_NOTICE MTD_FORTUNET_PK "%s flash is virtually at: %x\n",
228 map_regions[ix].map_info.name,
229 map_regions[ix].map_info.virt);
230 map_regions[ix].mymtd = do_map_probe("cfi_probe",
231 &map_regions[ix].map_info);
232 if((!map_regions[ix].mymtd)&&(
233 map_regions[ix].altbankwidth!=map_regions[ix].map_info.bankwidth))
234 {
235 printk(KERN_NOTICE MTD_FORTUNET_PK "Trying alternate bankwidth "
236 "for %s flash.\n",
237 map_regions[ix].map_info.name);
238 map_regions[ix].map_info.bankwidth =
239 map_regions[ix].altbankwidth;
240 map_regions[ix].mymtd = do_map_probe("cfi_probe",
241 &map_regions[ix].map_info);
242 }
243 map_regions[ix].mymtd->owner = THIS_MODULE;
244 add_mtd_partitions(map_regions[ix].mymtd,
245 map_regions[ix].parts,map_regions_parts[ix]);
246 }
247 }
248 if(iy)
249 return 0;
250 return -ENXIO;
251}
252
253static void __exit cleanup_fortunet(void)
254{
255 int ix;
256 for(ix=0;ix<MAX_NUM_REGIONS;ix++)
257 {
258 if(map_regions_set[ix])
259 {
260 if( map_regions[ix].mymtd )
261 {
262 del_mtd_partitions( map_regions[ix].mymtd );
263 map_destroy( map_regions[ix].mymtd );
264 }
265 iounmap((void *)map_regions[ix].map_info.virt);
266 }
267 }
268}
269
270module_init(init_fortunet);
271module_exit(cleanup_fortunet);
272
273MODULE_AUTHOR("FortuNet, Inc.");
274MODULE_DESCRIPTION("MTD map driver for FortuNet boards");