1 /****************************************************************************/
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>
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>
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
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
,
75 name
: "SnapGear filesystem",
76 offset
: KERNEL_OFFSET
+ KERNEL_SIZE
,
80 name
: "SnapGear config",
81 offset
: KERNEL_OFFSET
+ KERNEL_SIZE
+ ROOTFS_SIZE
,
85 name
: "SnapGear Extra config",
86 offset
: KERNEL_OFFSET
+ KERNEL_SIZE
+ ROOTFS_SIZE
+ CONFIG_SIZE
,
90 name
: "SnapGear Extra var",
91 offset
: KERNEL_OFFSET
+ KERNEL_SIZE
+ ROOTFS_SIZE
+ CONFIG_SIZE
+ NG_CONFIG_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,
105 name
: "SnapGear BIOS",
110 name
: "SnapGear Recover",
111 offset
: RECOVER_OFFSET
,
115 name
: "SnapGear Intel/StrataFlash",
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",
133 name
: "SnapGear System Data",
138 name
: "SnapGear non-volatile configuration",
143 name
: "SnapGear image",
147 name
: "SnapGear Intel/StrataFlash",
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
166 /* Now the dynamic-configuration platforms (based on machine_arch_type) */
167 #define DYNAMIC_SGARM_CONFIG
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 */
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 },
181 #if defined(CONFIG_MACH_IVPN)
182 { .type
= MACH_TYPE_IVPN
, .addr
= 0x50000000, .size
= 0x01000000, .width
= 2, .configsize
= 0x20000 },
184 #if defined(CONFIG_MACH_SG560) || defined (CONFIG_MACH_SGARMAUTO)
185 { .type
= MACH_TYPE_SG560
, .addr
= 0x50000000, .size
= 0x01000000, .width
= 2, .configsize
= 0x80000 },
187 #if defined(CONFIG_MACH_SG580) || defined (CONFIG_MACH_SGARMAUTO)
188 { .type
= MACH_TYPE_SG580
, .addr
= 0x50000000, .size
= 0x01000000, .width
= 2, .configsize
= 0x100000 },
190 #if defined(CONFIG_MACH_SG590) || defined (CONFIG_MACH_SGARMAUTO)
191 { .type
= MACH_TYPE_SG590
, .addr
= 0x50000000, .size
= 0x01000000, .width
= 2, .configsize
= 0x100000 },
193 #if defined(CONFIG_MACH_SG640) || defined (CONFIG_MACH_SGARMAUTO)
194 { .type
= MACH_TYPE_SG640
, .addr
= 0x50000000, .size
= 0x01000000, .width
= 2, .configsize
= 0x100000 },
196 #if defined(CONFIG_MACH_SG565) || defined (CONFIG_MACH_SGARMAUTO)
197 { .type
= MACH_TYPE_SG565
, .addr
= 0x50000000, .size
= 0x01000000, .width
= 1, .configsize
= 0x100000 },
199 #if defined(CONFIG_MACH_SG720)
200 { .type
= MACH_TYPE_SG720
, .addr
= 0x50000000, .size
= 0x01000000, .width
= 1, .configsize
= 0 },
202 #if defined(CONFIG_MACH_SG8100)
203 { .type
= MACH_TYPE_SG8100
, .addr
= 0x50000000, .size
= 0x02000000, .width
= 2, .configsize
= 0x100000 },
205 #if defined(CONFIG_MACH_SHIVA1100)
206 { .type
= MACH_TYPE_SHIVA1100
, .addr
= 0x50000000, .size
= 0x01000000, .width
= 1, .configsize
= 0x20000 },
208 #if defined(CONFIG_MACH_LITE300)
209 { .type
= MACH_TYPE_LITE300
, .addr
= 0x02000000, .size
= 0x00800000, .width
= 1, .configsize
= 0x20000 },
211 #if defined(CONFIG_MACH_SE4200)
212 { .type
= MACH_TYPE_SE4200
, .addr
= 0x02000000, .size
= 0x00800000, .width
= 1, .configsize
= 0x20000 },
214 #if defined(CONFIG_MACH_EP9312)
215 { .type
= MACH_TYPE_EP9312
, .addr
= 0x60000000, .size
= 0x00800000, .width
= 2, .configsize
= 0x20000 },
221 /****************************************************************************/
223 //#define SNAPARM_DEBUG 1
225 #define DPRINTK printk
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
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.
297 #define readpreflush(x)
299 #ifndef readpostflush
300 #define readpostflush(x)
302 #ifndef writepreflush
303 #define writepreflush(x)
305 #ifndef writepostflush
306 #define writepostflush(x)
315 #define releaselock()
318 /****************************************************************************/
320 static map_word
sg_read(struct map_info
*map
, unsigned long ofs
)
323 readpreflush(map
->virt
+ ofs
);
324 if (map_bankwidth(map
) == 1)
325 res
.x
[0] = __raw_readb(map
->virt
+ ofs
);
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]);
333 static void sg_copy_from(struct map_info
*map
, void *to
, unsigned long from
, ssize_t len
)
343 DPRINTK("%s(to=0x%x, from=0x%x, len=%d)\n", __FUNCTION__
,
344 (__u32
)to
, (__u32
)from
, (__u32
)len
);
351 p8
= (map
->virt
+ from
);
355 * read until the pointer to flash is on a 32 bit boundary
357 while (len
> 0 && (((unsigned long) p8
) & 3)) {
359 *dp
++ = __raw_readb(p8
);
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
371 data
.l
= __raw_readl(p8
);
378 len
-= sizeof(__u32
);
381 * clean up and non-aligned reads at the end
385 *dp
++ = __raw_readb(p8
);
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
);
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
)
410 DPRINTK("%s(to=0x%x,from=0x%x,len=%d)\n", __FUNCTION__
,
411 (u32
)to
, (u32
)from
, len
);
414 if (map_bankwidth(map
) == 1) {
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
);
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
);
432 /****************************************************************************/
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",
446 .bankwidth
= FLASH_WIDTH
,
448 .copy_from
= sg_copy_from
,
450 .copy_to
= sg_copy_to
453 static struct mtd_partition sg_partitions
[] = {
455 .name
= "U-Boot Loader",
460 .name
= "OpenGear non-volatile configuration",
461 .offset
= 0x00020000,
465 .name
= "OpenGear image",
469 .name
= "OpenGear Intel/StrataFlash",
475 /****************************************************************************/
477 /****************************************************************************/
479 #define VENDOR "SnapGear"
481 #if defined(CONFIG_MACH_SE5100)
482 #define VENDOR_ROOTFS "SnapGear filesystem"
484 #define VENDOR_ROOTFS "SnapGear image"
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
495 bankwidth
: FLASH_WIDTH
,
498 copy_from
: sg_copy_from
,
503 #ifdef DYNAMIC_SGARM_CONFIG
504 static unsigned long flash_addr
;
505 #define FLASH_ADDR flash_addr
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
,
521 name
: "SnapGear filesystem",
522 offset
: KERNEL_OFFSET
+ KERNEL_SIZE
,
526 name
: "SnapGear config",
527 offset
: KERNEL_OFFSET
+ KERNEL_SIZE
+ ROOTFS_SIZE
,
531 name
: "SnapGear Extra config",
532 offset
: KERNEL_OFFSET
+ KERNEL_SIZE
+ ROOTFS_SIZE
+ CONFIG_SIZE
,
536 name
: "SnapGear Extra var",
537 offset
: KERNEL_OFFSET
+ KERNEL_SIZE
+ ROOTFS_SIZE
+ CONFIG_SIZE
+ NG_CONFIG_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,
551 name
: "SnapGear BIOS",
556 name
: "SnapGear Recover",
557 offset
: RECOVER_OFFSET
,
561 name
: "SnapGear Intel/StrataFlash",
565 #elif defined(CONFIG_MACH_IPD)
566 static struct mtd_partition sg_partitions
[] = {
568 name
: "SnapGear Boot Loader",
573 name
: "SnapGear System Data",
578 name
: "SnapGear non-volatile configuration",
583 name
: "SnapGear image",
587 name
: "SnapGear Intel/StrataFlash",
591 #elif defined(CONFIG_MACH_SG720)
592 static struct mtd_partition sg_partitions
[] = {
594 name
: "SnapGear Boot Loader",
599 name
: "SnapGear Tags",
604 name
: "SnapGear Log",
609 name
: "SnapGear Intel/StrataFlash",
613 name
: "SnapGear Unused",
618 /* We use a dynamic structure */
619 static struct mtd_partition sg_partitions
[] = {
621 name
: "SnapGear Boot Loader",
626 name
: "SnapGear non-volatile configuration",
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",
641 /****************************************************************************/
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
;
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
);
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
;
683 for (i
= 0; (i
< MAX_MTD_DEVICES
); i
++) {
684 mtd
= get_mtd_device(NULL
, i
);
686 if (strcmp(mtd
->name
, name
) == 0)
696 /****************************************************************************/
698 int __init
sg_init(void)
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
) {
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
);
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
;
732 #if defined(CONFIG_ARCH_IXP4XX)
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
;
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");
757 * Map flash into our virtual address space.
759 sg_map
.virt
= ioremap(FLASH_ADDR
, sg_map
.size
);
761 release_mem_region(FLASH_ADDR
, sg_map
.size
);
763 printk(VENDOR
": failed to ioremap() flash\n");
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
);
772 printk(VENDOR
": probe failed\n");
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
);
784 printk(KERN_NOTICE VENDOR
": add_mtd_partitions() failed?\n");
786 #ifdef CONFIG_BLK_DEV_INITRD
787 if (phys_initrd_start
== 0)
790 /* Mark mtd partition as root device */
791 index
= sg_getmtdindex(VENDOR
" image");
793 ROOT_DEV
= MKDEV(MTD_BLOCK_MAJOR
, index
);
799 /****************************************************************************/
801 void __exit
sg_cleanup(void)
803 unregister_reboot_notifier(&sg_notifier_block
);
805 del_mtd_partitions(sg_mtd
);
809 iounmap(sg_map
.virt
);
813 release_mem_region(FLASH_ADDR
, sg_map
.size
);
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 /****************************************************************************/