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