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 / snaparm.c
blob8c47b8c4cdf6a18b34d90a63a4e81aee846d814c
1 /****************************************************************************/
3 /*
4 * snaparm.c -- mappings for SnapGear ARM based boards
6 * (C) Copyright 2000-2005, Greg Ungerer (gerg@snapgear.com)
7 * (C) Copyright 2001-2005, SnapGear (www.snapgear.com)
9 * I expect most SnapGear ARM based boards will have similar
10 * flash arrangements. So this map driver can handle them all.
13 /****************************************************************************/
15 #include <linux/module.h>
16 #include <linux/types.h>
17 #include <linux/init.h>
18 #include <linux/kernel.h>
19 #include <linux/fs.h>
20 #include <linux/major.h>
21 #include <linux/root_dev.h>
22 #include <linux/mtd/mtd.h>
23 #include <linux/mtd/map.h>
24 #include <linux/mtd/partitions.h>
25 #include <linux/mtd/cfi.h>
26 #include <linux/reboot.h>
27 #include <linux/ioport.h>
28 #include <asm/io.h>
29 #include <asm/mach-types.h>
31 /****************************************************************************/
33 static struct mtd_info *sg_mtd;
34 static struct resource *sg_res;
37 * This is the ARM method of setting up the initrd memory region now.
39 extern unsigned long phys_initrd_start;
41 /****************************************************************************/
43 /* First the fixed-configuration platforms */
44 #if defined(CONFIG_MACH_SE5100)
45 #define FLASH_ADDR 0x50000000
46 #define FLASH_SIZE 0x02000000
47 #define FLASH_WIDTH 2
49 #define BOOT_OFFSET 0x00000000
50 #define BOOT_SIZE 0x00040000
52 #define RECOVER_OFFSET 0x00040000
53 #define RECOVER_SIZE 0x00800000
55 #define KERNEL_OFFSET (BOOT_SIZE + RECOVER_SIZE)
56 #define KERNEL_SIZE 0x00180000
57 #define CONFIG_SIZE 0x00020000
58 #define NG_CONFIG_SIZE 0x00200000
59 #define NG_VAR_SIZE 0x00200000
61 #define ROOTFS_SIZE (FLASH_SIZE - BOOT_SIZE - KERNEL_SIZE - CONFIG_SIZE - \
62 NG_CONFIG_SIZE - NG_VAR_SIZE - RECOVER_SIZE)
64 static struct mtd_partition sg_partitions[] = {
66 * if you change the names of these, check the table below
67 * for unlocking the flash as well
70 name: "SnapGear kernel",
71 offset: KERNEL_OFFSET,
72 size: KERNEL_SIZE,
75 name: "SnapGear filesystem",
76 offset: KERNEL_OFFSET + KERNEL_SIZE,
77 size: ROOTFS_SIZE,
80 name: "SnapGear config",
81 offset: KERNEL_OFFSET + KERNEL_SIZE + ROOTFS_SIZE,
82 size: CONFIG_SIZE
85 name: "SnapGear Extra config",
86 offset: KERNEL_OFFSET + KERNEL_SIZE + ROOTFS_SIZE + CONFIG_SIZE,
87 size: NG_CONFIG_SIZE
90 name: "SnapGear Extra var",
91 offset: KERNEL_OFFSET + KERNEL_SIZE + ROOTFS_SIZE + CONFIG_SIZE + NG_CONFIG_SIZE,
92 size: NG_VAR_SIZE
95 name: "SnapGear image partition",
96 offset: KERNEL_OFFSET,
97 size: KERNEL_SIZE + ROOTFS_SIZE,
100 name: "SnapGear BIOS config",
101 offset: BOOT_SIZE / 2,
102 size: BOOT_SIZE / 2,
105 name: "SnapGear BIOS",
106 offset: 0,
107 size: BOOT_SIZE,
110 name: "SnapGear Recover",
111 offset: RECOVER_OFFSET,
112 size: RECOVER_SIZE,
115 name: "SnapGear Intel/StrataFlash",
116 offset: 0
120 #elif defined(CONFIG_MACH_IPD)
122 #define FLASH_ADDR 0x00000000
123 #define FLASH_SIZE 0x01000000
124 #define FLASH_WIDTH 2
126 static struct mtd_partition sg_partitions[] = {
128 name: "SnapGear Boot Loader",
129 offset: 0,
130 size: 0x00020000
133 name: "SnapGear System Data",
134 offset: 0x00020000,
135 size: 0x00020000
138 name: "SnapGear non-volatile configuration",
139 offset: 0x00040000,
140 size: 0x00020000
143 name: "SnapGear image",
144 offset: 0x00060000,
147 name: "SnapGear Intel/StrataFlash",
148 offset: 0
152 #elif defined(CONFIG_MACH_CM4008)
154 #define FLASH_ADDR 0x02000000
155 #define FLASH_SIZE 0x00800000
156 #define FLASH_WIDTH 1
158 #elif defined(CONFIG_MACH_CM41xx)
160 #define FLASH_ADDR 0x02000000
161 #define FLASH_SIZE 0x01000000
162 #define FLASH_WIDTH 1
164 #else
166 /* Now the dynamic-configuration platforms (based on machine_arch_type) */
167 #define DYNAMIC_SGARM_CONFIG
169 typedef struct {
170 unsigned long type; /* machine_arch_type */
171 unsigned long addr; /* Physical flash address */
172 unsigned long size; /* Maximum flash size */
173 unsigned long configsize; /* Size of the config partition */
174 unsigned width; /* Flash bus width */
175 } flash_layout_t;
177 static const flash_layout_t flash_layout[] = {
178 #if defined(CONFIG_MACH_SE4000)
179 { .type = MACH_TYPE_SE4000, .addr = 0x50000000, .size = 0x01000000, .width = 2, .configsize = 0x20000 },
180 #endif
181 #if defined(CONFIG_MACH_IVPN)
182 { .type = MACH_TYPE_IVPN, .addr = 0x50000000, .size = 0x01000000, .width = 2, .configsize = 0x20000 },
183 #endif
184 #if defined(CONFIG_MACH_SG560) || defined (CONFIG_MACH_SGARMAUTO)
185 { .type = MACH_TYPE_SG560, .addr = 0x50000000, .size = 0x01000000, .width = 2, .configsize = 0x80000 },
186 #endif
187 #if defined(CONFIG_MACH_SG580) || defined (CONFIG_MACH_SGARMAUTO)
188 { .type = MACH_TYPE_SG580, .addr = 0x50000000, .size = 0x01000000, .width = 2, .configsize = 0x100000 },
189 #endif
190 #if defined(CONFIG_MACH_SG590) || defined (CONFIG_MACH_SGARMAUTO)
191 { .type = MACH_TYPE_SG590, .addr = 0x50000000, .size = 0x01000000, .width = 2, .configsize = 0x100000 },
192 #endif
193 #if defined(CONFIG_MACH_SG640) || defined (CONFIG_MACH_SGARMAUTO)
194 { .type = MACH_TYPE_SG640, .addr = 0x50000000, .size = 0x01000000, .width = 2, .configsize = 0x100000 },
195 #endif
196 #if defined(CONFIG_MACH_SG565) || defined (CONFIG_MACH_SGARMAUTO)
197 { .type = MACH_TYPE_SG565, .addr = 0x50000000, .size = 0x01000000, .width = 1, .configsize = 0x100000 },
198 #endif
199 #if defined(CONFIG_MACH_SG720)
200 { .type = MACH_TYPE_SG720, .addr = 0x50000000, .size = 0x01000000, .width = 1, .configsize = 0 },
201 #endif
202 #if defined(CONFIG_MACH_SG8100)
203 { .type = MACH_TYPE_SG8100, .addr = 0x50000000, .size = 0x02000000, .width = 2, .configsize = 0x100000 },
204 #endif
205 #if defined(CONFIG_MACH_SHIVA1100)
206 { .type = MACH_TYPE_SHIVA1100, .addr = 0x50000000, .size = 0x01000000, .width = 1, .configsize = 0x20000 },
207 #endif
208 #if defined(CONFIG_MACH_LITE300)
209 { .type = MACH_TYPE_LITE300, .addr = 0x02000000, .size = 0x00800000, .width = 1, .configsize = 0x20000 },
210 #endif
211 #if defined(CONFIG_MACH_SE4200)
212 { .type = MACH_TYPE_SE4200, .addr = 0x02000000, .size = 0x00800000, .width = 1, .configsize = 0x20000 },
213 #endif
214 #if defined(CONFIG_MACH_EP9312)
215 { .type = MACH_TYPE_EP9312, .addr = 0x60000000, .size = 0x00800000, .width = 2, .configsize = 0x20000 },
216 #endif
219 #endif
221 /****************************************************************************/
223 //#define SNAPARM_DEBUG 1
224 #ifdef SNAPARM_DEBUG
225 #define DPRINTK printk
226 #else
227 #define DPRINTK(...)
228 #endif
230 /****************************************************************************/
233 * Define some access helper macros. On different architectures
234 * we have to deal with multi-byte quanitites, read/write buffers,
235 * and other architectural details a little differently. These
236 * macros try to abstract that as much as possible to keep the
237 * code clean.
240 #ifdef CONFIG_ARCH_KS8695
241 #include <asm/cacheflush.h>
243 * The bus read and write buffers can potenitially coalesce read and
244 * write bus cycles to the same address, thus dropping real cycles
245 * when talking to IO type devices. We need to flush those buffers
246 * when doing flash reading/writing.
248 * Walk through a small section of memory avoiding the cache so that we
249 * can keep the flash running smoothly. Using the write buffer enable
250 * disable seems tocause nasty bus junk, sodon't use them.
252 static void invalidate_buffer(void)
254 static unsigned char buf[32];
255 unsigned char cpy[sizeof(buf)];
257 memset(buf, 0, sizeof(buf));
258 clean_dcache_area(buf, sizeof(buf));
259 memcpy(cpy, buf, sizeof(buf));
260 clean_dcache_area(buf, sizeof(buf));
262 #define readpreflush(x) invalidate_buffer()
263 #define writepreflush(x) invalidate_buffer()
265 #define CONFIG_LOCK_MULTIBYTE
266 static DEFINE_SPINLOCK(multibyte_lock);
267 #define initlock() unsigned long flags;
268 #define getlock() spin_lock_irqsave(&multibyte_lock, flags)
269 #define releaselock() spin_unlock_irqrestore(&multibyte_lock, flags)
270 #endif /* CONFIG_ARCH_KS8695 */
274 * We are not entirely sure why, but on the iVPN the timing _between_
275 * access to the flash causes problems with other bus activity on the
276 * expansion bus. Namely the CompactFlash WiFi card. Delaying 1us
277 * is enough to clean up the cycles.
279 #ifdef CONFIG_MACH_IVPN
280 #define readpreflush(x) udelay(1)
281 #define readpostflush(x) udelay(1)
282 #define writepreflush(x) udelay(1)
283 #define writepostflush(x) udelay(1)
285 #define CONFIG_LOCK_MULTIBYTE
286 static DEFINE_SPINLOCK(multibyte_lock);
287 #define initlock() unsigned long flags;
288 #define getlock() spin_lock_irqsave(&multibyte_lock, flags)
289 #define releaselock() spin_unlock_irqrestore(&multibyte_lock, flags)
290 #endif /* CONFIG_MACH_IVPN */
294 * Now default any macros that are not used.
296 #ifndef readpreflush
297 #define readpreflush(x)
298 #endif
299 #ifndef readpostflush
300 #define readpostflush(x)
301 #endif
302 #ifndef writepreflush
303 #define writepreflush(x)
304 #endif
305 #ifndef writepostflush
306 #define writepostflush(x)
307 #endif
308 #ifndef initlock
309 #define initlock()
310 #endif
311 #ifndef getlock
312 #define getlock()
313 #endif
314 #ifndef releaselock
315 #define releaselock()
316 #endif
318 /****************************************************************************/
320 static map_word sg_read(struct map_info *map, unsigned long ofs)
322 map_word res;
323 readpreflush(map->virt + ofs);
324 if (map_bankwidth(map) == 1)
325 res.x[0] = __raw_readb(map->virt + ofs);
326 else
327 res.x[0] = __raw_readw(map->virt + ofs);
328 readpostflush(map->virt + ofs);
329 DPRINTK("%s(0x%x) = 0x%x\n", __FUNCTION__, (u32)ofs, (u32)res.x[0]);
330 return res;
333 static void sg_copy_from(struct map_info *map, void *to, unsigned long from, ssize_t len)
335 void __iomem *p8;
336 union {
337 __u32 l;
338 __u8 c[4];
339 } data;
340 __u8 *dp;
341 initlock();
343 DPRINTK("%s(to=0x%x, from=0x%x, len=%d)\n", __FUNCTION__,
344 (__u32)to, (__u32)from, (__u32)len);
346 if (len <= 0)
347 return;
349 getlock();
351 p8 = (map->virt + from);
352 dp = (__u8 *) to;
355 * read until the pointer to flash is on a 32 bit boundary
357 while (len > 0 && (((unsigned long) p8) & 3)) {
358 readpreflush(p8);
359 *dp++ = __raw_readb(p8);
360 readpostflush(p8);
361 p8++;
362 len--;
365 * The Xscale will do a back-to-back cycle on flash if we read
366 * 2 16bit values as a single 32 bit quantity, this is much faster
367 * than two normal 16bit cycles
369 while (len & ~3) {
370 readpreflush(p8);
371 data.l = __raw_readl(p8);
372 *dp++ = data.c[0];
373 *dp++ = data.c[1];
374 *dp++ = data.c[2];
375 *dp++ = data.c[3];
376 readpostflush(p8);
377 p8 += sizeof(__u32);
378 len -= sizeof(__u32);
381 * clean up and non-aligned reads at the end
383 while (len > 0) {
384 readpreflush(p8);
385 *dp++ = __raw_readb(p8);
386 readpostflush(p8);
387 p8++;
388 len--;
391 releaselock();
394 static void sg_write(struct map_info *map, map_word d, unsigned long adr)
396 DPRINTK("%s(0x%x,0x%x)\n", __FUNCTION__, (u32)d.x[0], (u32)adr);
397 writepreflush(map->virt + adr);
398 if (map_bankwidth(map) == 1)
399 __raw_writeb(d.x[0], map->virt + adr);
400 else
401 __raw_writew(d.x[0], map->virt + adr);
402 writepostflush(map->virt + adr);
405 static void sg_copy_to(struct map_info *map, unsigned long to, const void *from, ssize_t len)
407 unsigned int i;
408 initlock();
410 DPRINTK("%s(to=0x%x,from=0x%x,len=%d)\n", __FUNCTION__,
411 (u32)to, (u32)from, len);
413 getlock();
414 if (map_bankwidth(map) == 1) {
415 u8 *src8;
416 for (src8 = (u8 *) from, i = 0; (i < len); i++) {
417 writepreflush(map->virt + to + i);
418 __raw_writeb(*src8++, map->virt + to + i);
419 writepostflush(map->virt + to + i);
421 } else {
422 u16 *src16;
423 for (src16 = (u16 *) from, i = 0; (i < len); i += 2) {
424 writepreflush(map->virt + to + i);
425 __raw_writew(*src16++, map->virt + to + i);
426 writepostflush(map->virt + to + i);
429 releaselock();
432 /****************************************************************************/
433 /* OPENGEAR FLASH */
434 /****************************************************************************/
435 #if defined(CONFIG_MACH_CM4008) || defined(CONFIG_MACH_CM41xx)
437 #define VENDOR "OpenGear"
440 * Intel FLASH setup. This is the only flash device, it is the entire
441 * non-volatile storage (no IDE CF or hard drive or anything else).
443 static struct map_info sg_map = {
444 .name = "OpenGear Intel/StrataFlash",
445 .size = FLASH_SIZE,
446 .bankwidth = FLASH_WIDTH,
447 .read = sg_read,
448 .copy_from = sg_copy_from,
449 .write = sg_write,
450 .copy_to = sg_copy_to
453 static struct mtd_partition sg_partitions[] = {
455 .name = "U-Boot Loader",
456 .offset = 0,
457 .size = 0x00020000
460 .name = "OpenGear non-volatile configuration",
461 .offset = 0x00020000,
462 .size = 0x001e0000
465 .name = "OpenGear image",
466 .offset = 0x200000,
469 .name = "OpenGear Intel/StrataFlash",
470 .offset = 0
474 #else
475 /****************************************************************************/
476 /* SNAPGEAR FLASH */
477 /****************************************************************************/
479 #define VENDOR "SnapGear"
481 #if defined(CONFIG_MACH_SE5100)
482 #define VENDOR_ROOTFS "SnapGear filesystem"
483 #else
484 #define VENDOR_ROOTFS "SnapGear image"
485 #endif
488 * Intel FLASH setup. This is the only flash device, it is the entire
489 * non-volatile storage (no IDE CF or hard drive or anything else).
491 static struct map_info sg_map = {
492 name: "SnapGear Intel/StrataFlash",
493 #ifndef DYNAMIC_SGARM_CONFIG
494 size: FLASH_SIZE,
495 bankwidth: FLASH_WIDTH,
496 #endif
497 read: sg_read,
498 copy_from: sg_copy_from,
499 write: sg_write,
500 copy_to: sg_copy_to
503 #ifdef DYNAMIC_SGARM_CONFIG
504 static unsigned long flash_addr;
505 #define FLASH_ADDR flash_addr
506 #endif
508 /* Define the flash layout */
509 #if defined(CONFIG_MACH_SE5100)
510 static struct mtd_partition sg_partitions[] = {
512 * if you change the names of these, check the table below
513 * for unlocking the flash as well
516 name: "SnapGear kernel",
517 offset: KERNEL_OFFSET,
518 size: KERNEL_SIZE,
521 name: "SnapGear filesystem",
522 offset: KERNEL_OFFSET + KERNEL_SIZE,
523 size: ROOTFS_SIZE,
526 name: "SnapGear config",
527 offset: KERNEL_OFFSET + KERNEL_SIZE + ROOTFS_SIZE,
528 size: CONFIG_SIZE
531 name: "SnapGear Extra config",
532 offset: KERNEL_OFFSET + KERNEL_SIZE + ROOTFS_SIZE + CONFIG_SIZE,
533 size: NG_CONFIG_SIZE
536 name: "SnapGear Extra var",
537 offset: KERNEL_OFFSET + KERNEL_SIZE + ROOTFS_SIZE + CONFIG_SIZE + NG_CONFIG_SIZE,
538 size: NG_VAR_SIZE
541 name: "SnapGear image partition",
542 offset: KERNEL_OFFSET,
543 size: KERNEL_SIZE + ROOTFS_SIZE,
546 name: "SnapGear BIOS config",
547 offset: BOOT_SIZE / 2,
548 size: BOOT_SIZE / 2,
551 name: "SnapGear BIOS",
552 offset: 0,
553 size: BOOT_SIZE,
556 name: "SnapGear Recover",
557 offset: RECOVER_OFFSET,
558 size: RECOVER_SIZE,
561 name: "SnapGear Intel/StrataFlash",
562 offset: 0
565 #elif defined(CONFIG_MACH_IPD)
566 static struct mtd_partition sg_partitions[] = {
568 name: "SnapGear Boot Loader",
569 offset: 0,
570 size: 0x00020000
573 name: "SnapGear System Data",
574 offset: 0x00020000,
575 size: 0x00020000
578 name: "SnapGear non-volatile configuration",
579 offset: 0x00040000,
580 size: 0x00020000
583 name: "SnapGear image",
584 offset: 0x00060000,
587 name: "SnapGear Intel/StrataFlash",
588 offset: 0
591 #elif defined(CONFIG_MACH_SG720)
592 static struct mtd_partition sg_partitions[] = {
594 name: "SnapGear Boot Loader",
595 offset: 0,
596 size: 0x00080000
599 name: "SnapGear Tags",
600 offset: 0x00080000,
601 size: 0x00080000
604 name: "SnapGear Log",
605 offset: 0x00100000,
606 size: 0x00100000
609 name: "SnapGear Intel/StrataFlash",
610 offset: 0
613 name: "SnapGear Unused",
614 offset: 0x00200000,
617 #else
618 /* We use a dynamic structure */
619 static struct mtd_partition sg_partitions[] = {
621 name: "SnapGear Boot Loader",
622 offset: 0,
623 size: 0x00020000
626 name: "SnapGear non-volatile configuration",
627 offset: 0x00020000,
628 /*size: CONFIG_SIZE -- filled in when we know the config size */
631 name: "SnapGear image",
632 offset: 0x00020000, /* +CONFIG_SIZE, -- filled in when we know the config size */
635 name: "SnapGear Intel/StrataFlash",
636 offset: 0
639 #endif
641 /****************************************************************************/
642 #endif
643 /****************************************************************************/
645 #define NUM_PARTITIONS (sizeof(sg_partitions)/sizeof(sg_partitions[0]))
647 /****************************************************************************/
650 * Set the Intel flash back to read mode. Sometimes MTD leaves the
651 * flash in status mode, and if you reboot there is no code to
652 * execute (the flash devices do not get a RESET) :-(
654 static int sg_reboot_notifier(struct notifier_block *nb, unsigned long val, void *v)
656 struct cfi_private *cfi = sg_map.fldrv_priv;
657 int i;
659 /* Make sure all FLASH chips are put back into read mode */
660 for (i = 0; cfi && i < cfi->numchips; i++) {
661 cfi_send_gen_cmd(0xff, 0x55, cfi->chips[i].start, &sg_map,
662 cfi, cfi->device_type, NULL);
664 return NOTIFY_OK;
667 static struct notifier_block sg_notifier_block = {
668 sg_reboot_notifier, NULL, 0
671 /****************************************************************************/
674 * Find the MTD device with the given name.
677 static int sg_getmtdindex(char *name)
679 struct mtd_info *mtd;
680 int i, index;
682 index = -1;
683 for (i = 0; (i < MAX_MTD_DEVICES); i++) {
684 mtd = get_mtd_device(NULL, i);
685 if (mtd) {
686 if (strcmp(mtd->name, name) == 0)
687 index = mtd->index;
688 put_mtd_device(mtd);
689 if (index >= 0)
690 break;
693 return index;
696 /****************************************************************************/
698 int __init sg_init(void)
700 int index, rc;
702 printk(VENDOR ": MTD flash setup\n");
705 #ifdef DYNAMIC_SGARM_CONFIG
706 /* Find the matching entry in the flash_layout table.
707 * Note that for almost *all* devices, there will be only 1
709 for (index = 0; index < sizeof(flash_layout) / sizeof(*flash_layout); index++) {
710 if (flash_layout[index].type == machine_arch_type) {
711 break;
714 if (index == sizeof(flash_layout) / sizeof(*flash_layout)) {
715 printk(KERN_WARNING VENDOR ": No matching flash layout for mach type %d, using mach type %lu\n",
716 machine_arch_type, flash_layout[0].type);
717 index = 0;
720 /* Fix up the entries in sg_map */
721 sg_map.size = flash_layout[index].size;
722 sg_map.bankwidth = flash_layout[index].width;
723 flash_addr = flash_layout[index].addr;
725 /* And also fix up the partition table if we have a config partition */
726 if (flash_layout[index].configsize) {
727 sg_partitions[1].size += flash_layout[index].configsize;
728 sg_partitions[2].offset += flash_layout[index].configsize;
730 #endif
732 #if defined(CONFIG_ARCH_IXP4XX)
734 u32 val;
736 * enable fast CS0 (Intel flash J3 and P30 compatible values)
737 * T1=0, T2=2, T3=1, T4=0, T5=0
738 * NOTE: a value of "0" implies 1 cycle
739 * we preserve all the bootloader set values for size etc of the CS
740 * and only change T1-5
742 val = *IXP4XX_EXP_CS0;
743 val = (val & 0xffff) | 0x80c00000;
744 /* Enable flash writes */
745 val |= IXP4XX_FLASH_WRITABLE;
746 *IXP4XX_EXP_CS0 = val;
748 #endif
750 sg_res = request_mem_region(FLASH_ADDR, sg_map.size, VENDOR " FLASH");
751 if (sg_res == NULL) {
752 printk(VENDOR ": failed memory resource request?\n");
753 return -EIO;
757 * Map flash into our virtual address space.
759 sg_map.virt = ioremap(FLASH_ADDR, sg_map.size);
760 if (!sg_map.virt) {
761 release_mem_region(FLASH_ADDR, sg_map.size);
762 sg_res = NULL;
763 printk(VENDOR ": failed to ioremap() flash\n");
764 return -EIO;
767 if ((sg_mtd = do_map_probe("cfi_probe", &sg_map)) == NULL) {
768 iounmap(sg_map.virt);
769 release_mem_region(FLASH_ADDR, sg_map.size);
770 sg_res = NULL;
771 sg_map.virt = NULL;
772 printk(VENDOR ": probe failed\n");
773 return -ENXIO;
776 printk(KERN_NOTICE VENDOR ": %s device size = %dK\n",
777 sg_mtd->name, sg_mtd->size>>10);
779 sg_mtd->owner = THIS_MODULE;
780 sg_mtd->priv = &sg_map;
781 register_reboot_notifier(&sg_notifier_block);
782 rc = add_mtd_partitions(sg_mtd, sg_partitions, NUM_PARTITIONS);
783 if (rc < 0)
784 printk(KERN_NOTICE VENDOR ": add_mtd_partitions() failed?\n");
786 #ifdef CONFIG_BLK_DEV_INITRD
787 if (phys_initrd_start == 0)
788 #endif
790 /* Mark mtd partition as root device */
791 index = sg_getmtdindex(VENDOR " image");
792 if (index >= 0)
793 ROOT_DEV = MKDEV(MTD_BLOCK_MAJOR, index);
796 return rc;
799 /****************************************************************************/
801 void __exit sg_cleanup(void)
803 unregister_reboot_notifier(&sg_notifier_block);
804 if (sg_mtd) {
805 del_mtd_partitions(sg_mtd);
806 map_destroy(sg_mtd);
808 if (sg_map.virt) {
809 iounmap(sg_map.virt);
810 sg_map.virt = NULL;
812 if (sg_res) {
813 release_mem_region(FLASH_ADDR, sg_map.size);
814 sg_res = NULL;
818 /****************************************************************************/
820 module_init(sg_init);
821 module_exit(sg_cleanup);
823 MODULE_LICENSE("GPL");
824 MODULE_AUTHOR("Greg Ungerer <gerg@snapgear.com>");
825 MODULE_DESCRIPTION("SnapGear/ARM flash support");
827 /****************************************************************************/