MOXA linux-2.6.x / linux-2.6.19-uc1 from UC-7110-LX-BOOTLOADER-1.9_VERSION-4.2.tgz
[linux-2.6.19-moxart.git] / drivers / mtd / maps / snapgear-uc.c
blobf8a729242b3b67348c79821f6f16323d944455c7
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/module.h>
9 #include <linux/types.h>
10 #include <linux/kernel.h>
11 #include <linux/reboot.h>
13 #include <linux/mtd/mtd.h>
14 #include <linux/mtd/nftl.h>
15 #include <linux/mtd/map.h>
16 #include <linux/mtd/partitions.h>
17 #include <linux/mtd/cfi.h>
19 #include <linux/fs.h>
21 #include <linux/major.h>
22 #include <linux/root_dev.h>
24 #include <linux/init.h>
25 #include <asm/io.h>
26 #include <asm/delay.h>
27 #include <asm/sections.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->bankwidth = 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 = ioremap_nocache(map_ptr->map_priv_2, map_ptr->size);
240 if (!map_ptr->virt) {
241 printk("Failed to ioremap_nocache\n");
242 return -EIO;
245 simple_map_init(map_ptr);
246 if (!ram) {
247 mymtd = do_map_probe("cfi_probe", map_ptr);
248 if (!mymtd)
249 mymtd = do_map_probe("jedec_probe", map_ptr);
250 } else
251 mymtd = do_map_probe("map_ram", map_ptr);
253 if (!mymtd) {
254 iounmap((void *)map_ptr->map_priv_1);
255 return -ENXIO;
258 mymtd->owner = THIS_MODULE;
259 mymtd->point = nettel_point;
260 mymtd->priv = map_ptr;
262 if (ram) {
263 ram_mtdinfo = mymtd;
264 add_mtd_partitions(mymtd, nettel_romfs, NB_OF(nettel_romfs));
265 return(0);
268 flash_mtdinfo = mymtd;
269 switch (size) {
270 case SIZE_128K:
271 add_mtd_partitions(mymtd, nettel_128k, NB_OF(nettel_128k));
272 break;
273 case SIZE_1MB:
274 add_mtd_partitions(mymtd, nettel_1mb, NB_OF(nettel_1mb));
275 break;
276 case SIZE_2MB:
277 add_mtd_partitions(mymtd, nettel_2mb, NB_OF(nettel_2mb));
278 break;
279 case SIZE_4MB:
280 add_mtd_partitions(mymtd, nettel_4mb, NB_OF(nettel_4mb));
281 break;
282 case SIZE_8MB:
283 add_mtd_partitions(mymtd, nettel_8mb, NB_OF(nettel_8mb));
284 break;
285 case SIZE_16MB:
286 add_mtd_partitions(mymtd, nettel_16mb, NB_OF(nettel_16mb));
287 break;
290 return 0;
293 /****************************************************************************/
295 int __init nettel_mtd_init(void)
297 int rc = -1;
298 struct mtd_info *mtd;
299 #ifdef CONFIG_COLDFIRE
300 extern char _ebss;
301 #endif
304 * I hate this ifdef stuff, but our HW doesn't always have
305 * the same chipsize as the map that we use
307 #if defined(CONFIG_FLASH16MB) || defined(CONFIG_FLASHAUTO)
308 if (rc != 0)
309 rc = nettel_probe(0, FLASH_BASE, SIZE_16MB, BUS_WIDTH);
310 #endif
312 #if defined(CONFIG_FLASH8MB) || defined(CONFIG_FLASHAUTO)
313 if (rc != 0)
314 rc = nettel_probe(0, FLASH_BASE, SIZE_8MB, BUS_WIDTH);
315 #endif
317 #if defined(CONFIG_FLASH4MB) || defined(CONFIG_FLASHAUTO)
318 if (rc != 0)
319 rc = nettel_probe(0, FLASH_BASE, SIZE_4MB, BUS_WIDTH);
320 #endif
322 #if defined(CONFIG_FLASH2MB) || defined(CONFIG_FLASHAUTO)
323 if (rc != 0)
324 rc = nettel_probe(0, FLASH_BASE, SIZE_2MB, BUS_WIDTH);
325 #endif
327 #if defined(CONFIG_FLASH1MB) || defined(CONFIG_FLASHAUTO)
328 if (rc != 0)
329 rc = nettel_probe(0, FLASH_BASE, SIZE_1MB, BUS_WIDTH);
330 #endif
332 #if defined(CONFIG_FLASH128K) || defined(CONFIG_FLASHAUTO)
333 if (rc != 0)
334 rc = nettel_probe(0, FLASH_BASE, SIZE_128K, BUS_WIDTH);
335 #endif
337 #ifdef CONFIG_COLDFIRE
339 * Map in the filesystem from RAM last so that, if the filesystem
340 * is not in RAM for some reason we do not change the minor/major
341 * for the flash devices
343 #ifndef CONFIG_ROMFS_FROM_ROM
344 if (0 != nettel_probe(1, (unsigned long) &_ebss,
345 PAGE_ALIGN(* (unsigned long *)((&_ebss) + 8)), 4))
346 printk("Failed to probe RAM filesystem\n");
347 #else
349 unsigned long start_area;
350 unsigned char *sp, *ep;
351 size_t len;
353 start_area = (unsigned long) &_ebss;
355 if (strncmp((char *) start_area, "-rom1fs-", 8) != 0) {
356 mtd = get_mtd_named("Image");
357 if (mtd && mtd->point) {
358 if ((*mtd->point)(mtd, 0, mtd->size, &len, &sp) == 0) {
359 ep = sp + len;
360 while (sp < ep && strncmp(sp, "-rom1fs-", 8) != 0)
361 sp++;
362 if (sp < ep)
363 start_area = (unsigned long) sp;
366 if (mtd)
367 put_mtd_device(mtd);
369 if (0 != nettel_probe(1, start_area,
370 PAGE_ALIGN(* (unsigned long *)(start_area + 8)), 4))
371 printk("Failed to probe RAM filesystem\n");
373 #endif
375 mtd = get_mtd_named("Romfs");
376 if (mtd) {
377 ROOT_DEV = MKDEV(MTD_BLOCK_MAJOR, mtd->index);
378 put_mtd_device(mtd);
379 } else
380 printk("%s: Failed to find & make root filesystem\n", __FUNCTION__);
381 #endif
383 #ifdef CONFIG_SH_SECUREEDGE5410
384 #if defined(CONFIG_NFTL) || defined(CONFIG_INFTL)
385 ROOT_DEV = MKDEV(NFTL_MAJOR, 1);
386 #else
387 mtd = get_mtd_named("Image");
388 if (mtd) {
389 ROOT_DEV = MKDEV(MTD_BLOCK_MAJOR, mtd->index);
390 put_mtd_device(mtd);
392 #endif
393 #endif
395 #ifdef CONFIG_MTD_CFI_INTELEXT
396 register_reboot_notifier(&nettel_notifier_block);
397 #endif
399 return(rc);
402 /****************************************************************************/
404 static void __exit nettel_mtd_cleanup(void)
406 if (flash_mtdinfo) {
407 del_mtd_partitions(flash_mtdinfo);
408 map_destroy(flash_mtdinfo);
409 flash_mtdinfo = NULL;
411 if (ram_mtdinfo) {
412 del_mtd_partitions(ram_mtdinfo);
413 map_destroy(ram_mtdinfo);
414 ram_mtdinfo = NULL;
416 if (nettel_ram_map.map_priv_1) {
417 iounmap((void *)nettel_ram_map.map_priv_1);
418 nettel_ram_map.map_priv_1 = 0;
420 if (nettel_flash_map.map_priv_1) {
421 iounmap((void *)nettel_flash_map.map_priv_1);
422 nettel_flash_map.map_priv_1 = 0;
426 /****************************************************************************/
428 module_init(nettel_mtd_init);
429 module_exit(nettel_mtd_cleanup);
431 MODULE_LICENSE("GPL");
432 MODULE_AUTHOR("David McCullough <davidm@snapgear.com>");
433 MODULE_DESCRIPTION("SnapGear/SecureEdge FLASH support for uClinux");
435 /****************************************************************************/