MOXA linux-2.6.x / linux-2.6.9-uc0 from sdlinux-moxaart.tgz
[linux-2.6.9-moxart.git] / drivers / mtd / maps / snapgear-uc.c
blobe8756f04f3d74e7ab6910d763d567f1a825827e6
1 /****************************************************************************/
2 /*
3 * Flash memory access on uClinux SnapGear like devices
4 * Copyright (C) 2001-2002, David McCullough <davidm@snapgear.com>
5 */
6 /****************************************************************************/
8 #include <linux/config.h>
9 #include <linux/module.h>
10 #include <linux/types.h>
11 #include <linux/kernel.h>
12 #include <linux/reboot.h>
14 #include <linux/mtd/mtd.h>
15 #include <linux/mtd/nftl.h>
16 #include <linux/mtd/map.h>
17 #include <linux/mtd/partitions.h>
18 #include <linux/mtd/cfi.h>
20 #include <linux/fs.h>
22 #include <linux/major.h>
23 #include <linux/root_dev.h>
25 #include <linux/init.h>
26 #include <asm/io.h>
27 #include <asm/delay.h>
29 /****************************************************************************/
31 #define NB_OF(x) (sizeof(x)/sizeof(x[0]))
33 #define SIZE_128K (1 * 128 * 1024)
34 #define SIZE_1MB (1 * 1024 * 1024)
35 #define SIZE_2MB (2 * 1024 * 1024)
36 #define SIZE_4MB (4 * 1024 * 1024)
37 #define SIZE_8MB (8 * 1024 * 1024)
38 #define SIZE_16MB (16 * 1024 * 1024)
40 #ifdef CONFIG_COLDFIRE
41 #define FLASH_BASE 0xf0000000
42 #define BUS_WIDTH 2
43 #endif
45 #ifdef CONFIG_SUPERH
46 #define FLASH_BASE 0x00000000
47 #define BUS_WIDTH 1
48 #endif
50 /****************************************************************************/
52 static struct map_info nettel_flash_map = {
53 .name = "Flash",
56 static struct map_info nettel_ram_map = {
57 .name = "RAM",
60 static struct mtd_info *ram_mtdinfo;
61 static struct mtd_info *flash_mtdinfo;
63 /****************************************************************************/
65 static struct mtd_partition nettel_romfs[] = {
66 { .name = "Romfs" }
69 #define NUM_PARTITIONS (sizeof(nettel_romfs) / sizeof(nettel_romfs[0]))
71 /****************************************************************************/
73 * The layout of our flash, note the order of the names, this
74 * means we use the same major/minor for the same purpose on all
75 * layouts (when possible)
78 static struct mtd_partition nettel_128k[] = {
79 { .name = "Bootloader", .offset = 0x00000000, .size = 0x00004000 },
80 { .name = "Bootargs", .offset = 0x00004000, .size = 0x00004000 },
81 { .name = "MAC", .offset = 0x00008000, .size = 0x00004000 },
82 { .name = "Config", .offset = 0x00010000, .size = 0x00010000 },
83 { .name = "Spare", .offset = 0x0000c000, .size = 0x00004000 },
84 { .name = "Flash", .offset = 0 }
87 static struct mtd_partition nettel_1mb[] = {
88 { .name = "Bootloader", .offset = 0x00000000, .size = 0x00004000 },
89 { .name = "Bootargs", .offset = 0x00004000, .size = 0x00002000 },
90 { .name = "MAC", .offset = 0x00006000, .size = 0x00002000 },
91 { .name = "Config", .offset = 0x000f0000, .size = 0x00010000 },
92 { .name = "Spare", .offset = 0x00008000, .size = 0x00008000 },
93 { .name = "Image", .offset = 0x00010000, .size = 0x000e0000 },
94 { .name = "Flash", .offset = 0 }
97 static struct mtd_partition nettel_2mb[] = {
98 { .name = "Bootloader", .offset = 0x00000000, .size = 0x00004000 },
99 { .name = "Bootargs", .offset = 0x00004000, .size = 0x00002000 },
100 { .name = "MAC", .offset = 0x00006000, .size = 0x00002000 },
101 { .name = "Config", .offset = 0x00010000, .size = 0x00010000 },
102 { .name = "Spare", .offset = 0x00008000, .size = 0x00008000 },
103 { .name = "Image", .offset = 0x00020000, .size = 0x001e0000 },
104 { .name = "Flash", .offset = 0 }
107 #ifdef CONFIG_SH_SECUREEDGE5410
109 static struct mtd_partition nettel_4mb[] = {
110 { .name = "Boot data", .offset = 0x00000000, .size = 0x00020000 },
111 { .name = "Config", .offset = 0x00020000, .size = 0x00040000 },
112 { .name = "Image", .offset = 0x00060000, .size = 0x00000000 },
113 { .name = "Flash", .offset = 0 }
116 static struct mtd_partition nettel_8mb[] = {
117 { .name = "Boot data", .offset = 0x00000000, .size = 0x00020000 },
118 { .name = "Config", .offset = 0x00020000, .size = 0x00080000 },
119 { .name = "Image", .offset = 0x000a0000, .size = 0x00000000 },
120 { .name = "Flash", .offset = 0 }
123 #else
125 static struct mtd_partition nettel_4mb[] = {
126 { .name = "Bootloader", .offset = 0x00000000, .size = 0x00004000 },
127 { .name = "Bootargs", .offset = 0x00004000, .size = 0x00002000 },
128 { .name = "MAC", .offset = 0x00006000, .size = 0x00002000 },
129 { .name = "Config", .offset = 0x00010000, .size = 0x00010000 },
130 { .name = "Spare", .offset = 0x00008000, .size = 0x00008000 },
131 { .name = "Image", .offset = 0x00020000, .size = 0x001e0000 },
132 { .name = "Flash", .offset = 0x00000000, .size = 0x00200000 },
133 { .name = "Image2", .offset = 0x00220000, .size = 0x001e0000 },
134 { .name = "Flash2", .offset = 0 }
137 static struct mtd_partition nettel_8mb[] = {
138 { .name = "Bootloader", .offset = 0x00000000, .size = 0x00020000 },
139 { .name = "Bootargs", .offset = 0x00020000, .size = 0x00020000 },
140 { .name = "MAC", .offset = 0x00040000, .size = 0x00020000 },
141 { .name = "Config", .offset = 0x00080000, .size = 0x00080000 },
142 { .name = "Spare", .offset = 0x00060000, .size = 0x00020000 },
143 { .name = "Image", .offset = 0x00100000, .size = 0x00700000 },
144 { .name = "Flash", .offset = 0 }
147 #endif
149 static struct mtd_partition nettel_16mb[] = {
150 { .name = "Boot data", .offset = 0x00000000, .size = 0x00020000 },
151 { .name = "Config", .offset = 0x00020000, .size = 0x00100000 },
152 { .name = "Image", .offset = 0x00120000, .size = 0x00000000 },
153 { .name = "Flash", .offset = 0 }
156 /****************************************************************************/
158 * Find the MTD device with the given name
161 static struct mtd_info *get_mtd_named(char *name)
163 int i;
164 struct mtd_info *mtd;
166 for (i = 0; i < MAX_MTD_DEVICES; i++) {
167 mtd = get_mtd_device(NULL, i);
168 if (mtd) {
169 if (strcmp(mtd->name, name) == 0)
170 return(mtd);
171 put_mtd_device(mtd);
174 return(NULL);
177 /****************************************************************************/
178 #ifdef CONFIG_MTD_CFI_INTELEXT
180 * Set the Intel flash back to read mode as MTD may leave it in command mode
183 static int nettel_reboot_notifier(
184 struct notifier_block *nb,
185 unsigned long val,
186 void *v)
188 struct cfi_private *cfi = nettel_flash_map.fldrv_priv;
189 int i;
191 for (i = 0; cfi && i < cfi->numchips; i++)
192 cfi_send_gen_cmd(0xff, 0x55, cfi->chips[i].start, &nettel_flash_map,
193 cfi, cfi->device_type, NULL);
195 return(NOTIFY_OK);
198 static struct notifier_block nettel_notifier_block = {
199 nettel_reboot_notifier, NULL, 0
202 #endif
204 /****************************************************************************/
206 static int
207 nettel_point(struct mtd_info *mtd, loff_t from, size_t len,
208 size_t *retlen, u_char **mtdbuf)
210 struct map_info *map = (struct map_info *) mtd->priv;
211 *mtdbuf = (u_char *) (map->map_priv_1 + (int)from);
212 *retlen = len;
213 return(0);
216 /****************************************************************************/
218 static int __init
219 nettel_probe(int ram, unsigned long addr, int size, int buswidth)
221 struct mtd_info *mymtd;
222 struct map_info *map_ptr;
224 if (ram)
225 map_ptr = &nettel_ram_map;
226 else
227 map_ptr = &nettel_flash_map;
229 map_ptr->buswidth = buswidth;
230 map_ptr->map_priv_2 = addr;
231 map_ptr->phys = addr;
232 map_ptr->size = size;
234 printk(KERN_NOTICE "SnapGear %s probe(0x%lx,%d,%d): %lx at %lx\n",
235 ram ? "ram" : "flash",
236 addr, size, buswidth, map_ptr->size, map_ptr->map_priv_2);
238 map_ptr->virt = (unsigned long)
239 ioremap_nocache(map_ptr->map_priv_2, map_ptr->size);
241 if (!map_ptr->virt) {
242 printk("Failed to ioremap_nocache\n");
243 return -EIO;
246 simple_map_init(map_ptr);
247 if (!ram) {
248 mymtd = do_map_probe("cfi_probe", map_ptr);
249 if (!mymtd)
250 mymtd = do_map_probe("jedec_probe", map_ptr);
251 } else
252 mymtd = do_map_probe("map_ram", map_ptr);
254 if (!mymtd) {
255 iounmap((void *)map_ptr->map_priv_1);
256 return -ENXIO;
259 mymtd->owner = THIS_MODULE;
260 mymtd->point = nettel_point;
261 mymtd->priv = map_ptr;
263 if (ram) {
264 ram_mtdinfo = mymtd;
265 add_mtd_partitions(mymtd, nettel_romfs, NB_OF(nettel_romfs));
266 return(0);
269 flash_mtdinfo = mymtd;
270 switch (size) {
271 case SIZE_128K:
272 add_mtd_partitions(mymtd, nettel_128k, NB_OF(nettel_128k));
273 break;
274 case SIZE_1MB:
275 add_mtd_partitions(mymtd, nettel_1mb, NB_OF(nettel_1mb));
276 break;
277 case SIZE_2MB:
278 add_mtd_partitions(mymtd, nettel_2mb, NB_OF(nettel_2mb));
279 break;
280 case SIZE_4MB:
281 add_mtd_partitions(mymtd, nettel_4mb, NB_OF(nettel_4mb));
282 break;
283 case SIZE_8MB:
284 add_mtd_partitions(mymtd, nettel_8mb, NB_OF(nettel_8mb));
285 break;
286 case SIZE_16MB:
287 add_mtd_partitions(mymtd, nettel_16mb, NB_OF(nettel_16mb));
288 break;
291 return 0;
294 /****************************************************************************/
296 int __init nettel_mtd_init(void)
298 int rc = -1;
299 struct mtd_info *mtd;
300 #ifdef CONFIG_COLDFIRE
301 extern char _ebss;
302 #endif
305 * I hate this ifdef stuff, but our HW doesn't always have
306 * the same chipsize as the map that we use
308 #if defined(CONFIG_FLASH16MB) || defined(CONFIG_FLASHAUTO)
309 if (rc != 0)
310 rc = nettel_probe(0, FLASH_BASE, SIZE_16MB, BUS_WIDTH);
311 #endif
313 #if defined(CONFIG_FLASH8MB) || defined(CONFIG_FLASHAUTO)
314 if (rc != 0)
315 rc = nettel_probe(0, FLASH_BASE, SIZE_8MB, BUS_WIDTH);
316 #endif
318 #if defined(CONFIG_FLASH4MB) || defined(CONFIG_FLASHAUTO)
319 if (rc != 0)
320 rc = nettel_probe(0, FLASH_BASE, SIZE_4MB, BUS_WIDTH);
321 #endif
323 #if defined(CONFIG_FLASH2MB) || defined(CONFIG_FLASHAUTO)
324 if (rc != 0)
325 rc = nettel_probe(0, FLASH_BASE, SIZE_2MB, BUS_WIDTH);
326 #endif
328 #if defined(CONFIG_FLASH1MB) || defined(CONFIG_FLASHAUTO)
329 if (rc != 0)
330 rc = nettel_probe(0, FLASH_BASE, SIZE_1MB, BUS_WIDTH);
331 #endif
333 #if defined(CONFIG_FLASH128K) || defined(CONFIG_FLASHAUTO)
334 if (rc != 0)
335 rc = nettel_probe(0, FLASH_BASE, SIZE_128K, BUS_WIDTH);
336 #endif
338 #ifdef CONFIG_COLDFIRE
340 * Map in the filesystem from RAM last so that, if the filesystem
341 * is not in RAM for some reason we do not change the minor/major
342 * for the flash devices
344 #ifndef CONFIG_ROMFS_FROM_ROM
345 if (0 != nettel_probe(1, (unsigned long) &_ebss,
346 PAGE_ALIGN(* (unsigned long *)((&_ebss) + 8)), 4))
347 printk("Failed to probe RAM filesystem\n");
348 #else
350 unsigned long start_area;
351 unsigned char *sp, *ep;
352 size_t len;
354 start_area = (unsigned long) &_ebss;
356 if (strncmp((char *) start_area, "-rom1fs-", 8) != 0) {
357 mtd = get_mtd_named("Image");
358 if (mtd && mtd->point) {
359 if ((*mtd->point)(mtd, 0, mtd->size, &len, &sp) == 0) {
360 ep = sp + len;
361 while (sp < ep && strncmp(sp, "-rom1fs-", 8) != 0)
362 sp++;
363 if (sp < ep)
364 start_area = (unsigned long) sp;
367 if (mtd)
368 put_mtd_device(mtd);
370 if (0 != nettel_probe(1, start_area,
371 PAGE_ALIGN(* (unsigned long *)(start_area + 8)), 4))
372 printk("Failed to probe RAM filesystem\n");
374 #endif
376 mtd = get_mtd_named("Romfs");
377 if (mtd) {
378 ROOT_DEV = MKDEV(MTD_BLOCK_MAJOR, mtd->index);
379 put_mtd_device(mtd);
380 } else
381 printk("%s: Failed to find & make root filesystem\n", __FUNCTION__);
382 #endif
384 #ifdef CONFIG_SH_SECUREEDGE5410
386 extern int _end;
387 unsigned long magic;
388 char *cp = (char *) &_end;
390 memcpy(&magic, cp, sizeof(magic));
391 if (memcmp(cp, "-rom1fs-", 8) == 0) {
392 /* romfs */ ;
393 nettel_probe(1, (unsigned long) cp,
394 PAGE_ALIGN(* (unsigned long *)(cp + 8)), 4);
395 mtd = get_mtd_named("Romfs");
396 if (mtd) {
397 ROOT_DEV = MKDEV(MTD_BLOCK_MAJOR, mtd->index);
398 put_mtd_device(mtd);
399 } else
400 printk("%s: Failed to find & make romfs root filesystem\n",
401 __FUNCTION__);
402 } else if (magic == 0x28cd3d45) {
403 /* cramfs */ ;
404 nettel_probe(1, (unsigned long) cp,
405 PAGE_ALIGN(* (unsigned long *)(cp + 4)), 4);
406 mtd = get_mtd_named("Romfs");
407 if (mtd) {
408 ROOT_DEV = MKDEV(MTD_BLOCK_MAJOR, mtd->index);
409 put_mtd_device(mtd);
410 } else
411 printk("%s: Failed to find & make cramfs root filesystem\n",
412 __FUNCTION__);
413 } else {
414 #if defined(CONFIG_NFTL) || defined(CONFIG_INFTL)
415 ROOT_DEV = MKDEV(NFTL_MAJOR, 1);
416 #else
417 mtd = get_mtd_named("Image");
418 if (mtd) {
419 ROOT_DEV = MKDEV(MTD_BLOCK_MAJOR, mtd->index);
420 put_mtd_device(mtd);
422 #endif
425 #endif
427 #ifdef CONFIG_MTD_CFI_INTELEXT
428 register_reboot_notifier(&nettel_notifier_block);
429 #endif
431 return(rc);
434 /****************************************************************************/
436 static void __exit nettel_mtd_cleanup(void)
438 if (flash_mtdinfo) {
439 del_mtd_partitions(flash_mtdinfo);
440 map_destroy(flash_mtdinfo);
441 flash_mtdinfo = NULL;
443 if (ram_mtdinfo) {
444 del_mtd_partitions(ram_mtdinfo);
445 map_destroy(ram_mtdinfo);
446 ram_mtdinfo = NULL;
448 if (nettel_ram_map.map_priv_1) {
449 iounmap((void *)nettel_ram_map.map_priv_1);
450 nettel_ram_map.map_priv_1 = 0;
452 if (nettel_flash_map.map_priv_1) {
453 iounmap((void *)nettel_flash_map.map_priv_1);
454 nettel_flash_map.map_priv_1 = 0;
458 /****************************************************************************/
460 module_init(nettel_mtd_init);
461 module_exit(nettel_mtd_cleanup);
463 MODULE_LICENSE("GPL");
464 MODULE_AUTHOR("David McCullough <davidm@snapgear.com>");
465 MODULE_DESCRIPTION("SnapGear/SecureEdge FLASH support for uClinux");
467 /****************************************************************************/