MOXA linux-2.6.x / linux-2.6.9-uc0 from sdlinux-moxaart.tgz
[linux-2.6.9-moxart.git] / drivers / mtd / maps / sa1100-flash.c
blobbb9c0778083f6c437dcca2f4b9ada05d5090270d
1 /*
2 * Flash memory access on SA11x0 based devices
3 *
4 * (C) 2000 Nicolas Pitre <nico@cam.org>
5 *
6 * $Id: sa1100-flash.c,v 1.39 2004/07/12 21:59:44 dwmw2 Exp $
7 */
9 #include <linux/config.h>
10 #include <linux/module.h>
11 #include <linux/types.h>
12 #include <linux/ioport.h>
13 #include <linux/kernel.h>
14 #include <linux/init.h>
15 #include <linux/errno.h>
16 #include <linux/slab.h>
18 #include <linux/mtd/mtd.h>
19 #include <linux/mtd/map.h>
20 #include <linux/mtd/partitions.h>
21 #include <linux/mtd/concat.h>
23 #include <asm/hardware.h>
24 #include <asm/mach-types.h>
25 #include <asm/io.h>
26 #include <asm/sizes.h>
28 #include <asm/arch/h3600.h>
30 #ifndef CONFIG_ARCH_SA1100
31 #error This is for SA1100 architecture only
32 #endif
35 * This isnt complete yet, so...
37 #define CONFIG_MTD_SA1100_STATICMAP 1
39 #ifdef CONFIG_MTD_SA1100_STATICMAP
41 * Here are partition information for all known SA1100-based devices.
42 * See include/linux/mtd/partitions.h for definition of the mtd_partition
43 * structure.
45 * Please note:
46 * 1. We no longer support static flash mappings via the machine io_desc
47 * structure.
48 * 2. The flash size given should be the largest flash size that can
49 * be accommodated.
51 * The MTD layer will detect flash chip aliasing and reduce the size of
52 * the map accordingly.
54 * Please keep these in alphabetical order, and formatted as per existing
55 * entries. Thanks.
58 #ifdef CONFIG_SA1100_ADSBITSY
59 static struct mtd_partition adsbitsy_partitions[] = {
61 .name = "bootROM",
62 .size = 0x80000,
63 .offset = 0,
64 .mask_flags = MTD_WRITEABLE, /* force read-only */
65 }, {
66 .name = "zImage",
67 .size = 0x100000,
68 .offset = MTDPART_OFS_APPEND,
69 .mask_flags = MTD_WRITEABLE, /* force read-only */
70 }, {
71 .name = "ramdisk.gz",
72 .size = 0x300000,
73 .offset = MTDPART_OFS_APPEND,
74 .mask_flags = MTD_WRITEABLE, /* force read-only */
75 }, {
76 .name = "User FS",
77 .size = MTDPART_SIZ_FULL,
78 .offset = MTDPART_OFS_APPEND,
81 #endif
83 #ifdef CONFIG_SA1100_ASSABET
84 /* Phase 4 Assabet has two 28F160B3 flash parts in bank 0: */
85 static struct mtd_partition assabet4_partitions[] = {
87 .name = "bootloader",
88 .size = 0x00020000,
89 .offset = 0,
90 .mask_flags = MTD_WRITEABLE,
91 }, {
92 .name = "bootloader params",
93 .size = 0x00020000,
94 .offset = MTDPART_OFS_APPEND,
95 .mask_flags = MTD_WRITEABLE,
96 }, {
97 .name = "jffs",
98 .size = MTDPART_SIZ_FULL,
99 .offset = MTDPART_OFS_APPEND,
103 /* Phase 5 Assabet has two 28F128J3A flash parts in bank 0: */
104 static struct mtd_partition assabet5_partitions[] = {
106 .name = "bootloader",
107 .size = 0x00040000,
108 .offset = 0,
109 .mask_flags = MTD_WRITEABLE,
110 }, {
111 .name = "bootloader params",
112 .size = 0x00040000,
113 .offset = MTDPART_OFS_APPEND,
114 .mask_flags = MTD_WRITEABLE,
115 }, {
116 .name = "jffs",
117 .size = MTDPART_SIZ_FULL,
118 .offset = MTDPART_OFS_APPEND,
122 #define assabet_partitions assabet5_partitions
123 #endif
125 #ifdef CONFIG_SA1100_BADGE4
127 * 1 x Intel 28F320C3 Advanced+ Boot Block Flash (32 Mi bit)
128 * Eight 4 KiW Parameter Bottom Blocks (64 KiB)
129 * Sixty-three 32 KiW Main Blocks (4032 Ki b)
131 * <or>
133 * 1 x Intel 28F640C3 Advanced+ Boot Block Flash (64 Mi bit)
134 * Eight 4 KiW Parameter Bottom Blocks (64 KiB)
135 * One-hundred-twenty-seven 32 KiW Main Blocks (8128 Ki b)
137 static struct mtd_partition badge4_partitions[] = {
139 .name = "BLOB boot loader",
140 .offset = 0,
141 .size = 0x0000A000
142 }, {
143 .name = "params",
144 .offset = MTDPART_OFS_APPEND,
145 .size = 0x00006000
146 }, {
147 .name = "root",
148 .offset = MTDPART_OFS_APPEND,
149 .size = MTDPART_SIZ_FULL
152 #endif
155 #ifdef CONFIG_SA1100_CERF
156 #ifdef CONFIG_SA1100_CERF_FLASH_32MB
157 # define CERF_FLASH_SIZE 0x02000000
158 #elif defined CONFIG_SA1100_CERF_FLASH_16MB
159 # define CERF_FLASH_SIZE 0x01000000
160 #elif defined CONFIG_SA1100_CERF_FLASH_8MB
161 # define CERF_FLASH_SIZE 0x00800000
162 #else
163 # error "Undefined flash size for CERF in sa1100-flash.c"
164 #endif
166 static struct mtd_partition cerf_partitions[] = {
168 .name = "Bootloader",
169 .size = 0x00020000,
170 .offset = 0x00000000,
171 }, {
172 .name = "Params",
173 .size = 0x00040000,
174 .offset = 0x00020000,
175 }, {
176 .name = "Kernel",
177 .size = 0x00100000,
178 .offset = 0x00060000,
179 }, {
180 .name = "Filesystem",
181 .size = CERF_FLASH_SIZE-0x00160000,
182 .offset = 0x00160000,
185 #endif
187 #ifdef CONFIG_SA1100_CONSUS
188 static struct mtd_partition consus_partitions[] = {
190 .name = "Consus boot firmware",
191 .offset = 0,
192 .size = 0x00040000,
193 .mask_flags = MTD_WRITABLE, /* force read-only */
194 }, {
195 .name = "Consus kernel",
196 .offset = 0x00040000,
197 .size = 0x00100000,
198 .mask_flags = 0,
199 }, {
200 .name = "Consus disk",
201 .offset = 0x00140000,
202 /* The rest (up to 16M) for jffs. We could put 0 and
203 make it find the size automatically, but right now
204 i have 32 megs. jffs will use all 32 megs if given
205 the chance, and this leads to horrible problems
206 when you try to re-flash the image because blob
207 won't erase the whole partition. */
208 .size = 0x01000000 - 0x00140000,
209 .mask_flags = 0,
210 }, {
211 /* this disk is a secondary disk, which can be used as
212 needed, for simplicity, make it the size of the other
213 consus partition, although realistically it could be
214 the remainder of the disk (depending on the file
215 system used) */
216 .name = "Consus disk2",
217 .offset = 0x01000000,
218 .size = 0x01000000 - 0x00140000,
219 .mask_flags = 0,
222 #endif
224 #ifdef CONFIG_SA1100_FLEXANET
225 /* Flexanet has two 28F128J3A flash parts in bank 0: */
226 #define FLEXANET_FLASH_SIZE 0x02000000
227 static struct mtd_partition flexanet_partitions[] = {
229 .name = "bootloader",
230 .size = 0x00040000,
231 .offset = 0,
232 .mask_flags = MTD_WRITEABLE,
233 }, {
234 .name = "bootloader params",
235 .size = 0x00040000,
236 .offset = MTDPART_OFS_APPEND,
237 .mask_flags = MTD_WRITEABLE,
238 }, {
239 .name = "kernel",
240 .size = 0x000C0000,
241 .offset = MTDPART_OFS_APPEND,
242 .mask_flags = MTD_WRITEABLE,
243 }, {
244 .name = "altkernel",
245 .size = 0x000C0000,
246 .offset = MTDPART_OFS_APPEND,
247 .mask_flags = MTD_WRITEABLE,
248 }, {
249 .name = "root",
250 .size = 0x00400000,
251 .offset = MTDPART_OFS_APPEND,
252 .mask_flags = MTD_WRITEABLE,
253 }, {
254 .name = "free1",
255 .size = 0x00300000,
256 .offset = MTDPART_OFS_APPEND,
257 .mask_flags = MTD_WRITEABLE,
258 }, {
259 .name = "free2",
260 .size = 0x00300000,
261 .offset = MTDPART_OFS_APPEND,
262 .mask_flags = MTD_WRITEABLE,
263 }, {
264 .name = "free3",
265 .size = MTDPART_SIZ_FULL,
266 .offset = MTDPART_OFS_APPEND,
267 .mask_flags = MTD_WRITEABLE,
270 #endif
272 #ifdef CONFIG_SA1100_FREEBIRD
273 static struct mtd_partition freebird_partitions[] = {
274 #ifdef CONFIG_SA1100_FREEBIRD_NEW
276 .name = "firmware",
277 .size = 0x00040000,
278 .offset = 0,
279 .mask_flags = MTD_WRITEABLE, /* force read-only */
280 }, {
281 .name = "kernel",
282 .size = 0x00080000,
283 .offset = 0x00040000,
284 }, {
285 .name = "params",
286 .size = 0x00040000,
287 .offset = 0x000C0000,
288 }, {
289 .name = "initrd",
290 .size = 0x00100000,
291 .offset = 0x00100000,
292 }, {
293 .name = "root cramfs",
294 .size = 0x00300000,
295 .offset = 0x00200000,
296 }, {
297 .name = "usr cramfs",
298 .size = 0x00C00000,
299 .offset = 0x00500000,
300 }, {
301 .name = "local",
302 .size = MTDPART_SIZ_FULL,
303 .offset = 0x01100000,
305 #else
307 .size = 0x00040000,
308 .offset = 0,
309 }, {
310 .size = 0x000c0000,
311 .offset = MTDPART_OFS_APPEND,
312 }, {
313 .size = 0x00400000,
314 .offset = MTDPART_OFS_APPEND,
315 }, {
316 .size = MTDPART_SIZ_FULL,
317 .offset = MTDPART_OFS_APPEND,
319 #endif
321 #endif
323 #ifdef CONFIG_SA1100_FRODO
324 /* Frodo has 2 x 16M 28F128J3A flash chips in bank 0: */
325 static struct mtd_partition frodo_partitions[] =
328 .name = "bootloader",
329 .size = 0x00040000,
330 .offset = 0x00000000,
331 .mask_flags = MTD_WRITEABLE
332 }, {
333 .name = "bootloader params",
334 .size = 0x00040000,
335 .offset = MTDPART_OFS_APPEND,
336 .mask_flags = MTD_WRITEABLE
337 }, {
338 .name = "kernel",
339 .size = 0x00100000,
340 .offset = MTDPART_OFS_APPEND,
341 .mask_flags = MTD_WRITEABLE
342 }, {
343 .name = "ramdisk",
344 .size = 0x00400000,
345 .offset = MTDPART_OFS_APPEND,
346 .mask_flags = MTD_WRITEABLE
347 }, {
348 .name = "file system",
349 .size = MTDPART_SIZ_FULL,
350 .offset = MTDPART_OFS_APPEND
353 #endif
355 #ifdef CONFIG_SA1100_GRAPHICSCLIENT
356 static struct mtd_partition graphicsclient_partitions[] = {
358 .name = "zImage",
359 .size = 0x100000,
360 .offset = 0,
361 .mask_flags = MTD_WRITEABLE, /* force read-only */
362 }, {
363 .name = "ramdisk.gz",
364 .size = 0x300000,
365 .offset = MTDPART_OFS_APPEND,
366 .mask_flags = MTD_WRITEABLE, /* force read-only */
367 }, {
368 .name = "User FS",
369 .size = MTDPART_SIZ_FULL,
370 .offset = MTDPART_OFS_APPEND,
373 #endif
375 #ifdef CONFIG_SA1100_GRAPHICSMASTER
376 static struct mtd_partition graphicsmaster_partitions[] = {
378 .name = "zImage",
379 .size = 0x100000,
380 .offset = 0,
381 .mask_flags = MTD_WRITEABLE, /* force read-only */
384 .name = "ramdisk.gz",
385 .size = 0x300000,
386 .offset = MTDPART_OFS_APPEND,
387 .mask_flags = MTD_WRITEABLE, /* force read-only */
390 .name = "User FS",
391 .size = MTDPART_SIZ_FULL,
392 .offset = MTDPART_OFS_APPEND,
395 #endif
397 #ifdef CONFIG_SA1100_H3XXX
398 static struct mtd_partition h3xxx_partitions[] = {
400 .name = "H3XXX boot firmware",
401 .size = 0x00040000,
402 .offset = 0,
403 .mask_flags = MTD_WRITEABLE, /* force read-only */
404 }, {
405 #ifdef CONFIG_MTD_2PARTS_IPAQ
406 .name = "H3XXX root jffs2",
407 .size = MTDPART_SIZ_FULL,
408 .offset = 0x00040000,
409 #else
410 .name = "H3XXX kernel",
411 .size = 0x00080000,
412 .offset = 0x00040000,
413 }, {
414 .name = "H3XXX params",
415 .size = 0x00040000,
416 .offset = 0x000C0000,
417 }, {
418 #ifdef CONFIG_JFFS2_FS
419 .name = "H3XXX root jffs2",
420 .size = MTDPART_SIZ_FULL,
421 .offset = 0x00100000,
422 #else
423 .name = "H3XXX initrd",
424 .size = 0x00100000,
425 .offset = 0x00100000,
426 }, {
427 .name = "H3XXX root cramfs",
428 .size = 0x00300000,
429 .offset = 0x00200000,
430 }, {
431 .name = "H3XXX usr cramfs",
432 .size = 0x00800000,
433 .offset = 0x00500000,
434 }, {
435 .name = "H3XXX usr local",
436 .size = MTDPART_SIZ_FULL,
437 .offset = 0x00d00000,
438 #endif
439 #endif
443 static void h3xxx_set_vpp(struct map_info *map, int vpp)
445 assign_h3600_egpio(IPAQ_EGPIO_VPP_ON, vpp);
447 #else
448 #define h3xxx_set_vpp NULL
449 #endif
451 #ifdef CONFIG_SA1100_HACKKIT
452 static struct mtd_partition hackkit_partitions[] = {
454 .name = "BLOB",
455 .size = 0x00040000,
456 .offset = 0x00000000,
457 .mask_flags = MTD_WRITEABLE, /* force read-only */
458 }, {
459 .name = "config",
460 .size = 0x00040000,
461 .offset = MTDPART_OFS_APPEND,
462 }, {
463 .name = "kernel",
464 .size = 0x00100000,
465 .offset = MTDPART_OFS_APPEND,
466 }, {
467 .name = "initrd",
468 .size = 0x00180000,
469 .offset = MTDPART_OFS_APPEND,
470 }, {
471 .name = "rootfs",
472 .size = 0x700000,
473 .offset = MTDPART_OFS_APPEND,
474 }, {
475 .name = "data",
476 .size = MTDPART_SIZ_FULL,
477 .offset = MTDPART_OFS_APPEND,
480 #endif
482 #ifdef CONFIG_SA1100_HUW_WEBPANEL
483 static struct mtd_partition huw_webpanel_partitions[] = {
485 .name = "Loader",
486 .size = 0x00040000,
487 .offset = 0,
488 }, {
489 .name = "Sector 1",
490 .size = 0x00040000,
491 .offset = MTDPART_OFS_APPEND,
492 }, {
493 .size = MTDPART_SIZ_FULL,
494 .offset = MTDPART_OFS_APPEND,
497 #endif
499 #ifdef CONFIG_SA1100_JORNADA720
500 static struct mtd_partition jornada720_partitions[] = {
502 .name = "JORNADA720 boot firmware",
503 .size = 0x00040000,
504 .offset = 0,
505 .mask_flags = MTD_WRITEABLE, /* force read-only */
506 }, {
507 .name = "JORNADA720 kernel",
508 .size = 0x000c0000,
509 .offset = 0x00040000,
510 }, {
511 .name = "JORNADA720 params",
512 .size = 0x00040000,
513 .offset = 0x00100000,
514 }, {
515 .name = "JORNADA720 initrd",
516 .size = 0x00100000,
517 .offset = 0x00140000,
518 }, {
519 .name = "JORNADA720 root cramfs",
520 .size = 0x00300000,
521 .offset = 0x00240000,
522 }, {
523 .name = "JORNADA720 usr cramfs",
524 .size = 0x00800000,
525 .offset = 0x00540000,
526 }, {
527 .name = "JORNADA720 usr local",
528 .size = 0, /* will expand to the end of the flash */
529 .offset = 0x00d00000,
533 static void jornada720_set_vpp(struct map_info *map, int vpp)
535 if (vpp)
536 PPSR |= 0x80;
537 else
538 PPSR &= ~0x80;
539 PPDR |= 0x80;
541 #else
542 #define jornada720_set_vpp NULL
543 #endif
545 #ifdef CONFIG_SA1100_PANGOLIN
546 static struct mtd_partition pangolin_partitions[] = {
548 .name = "boot firmware",
549 .size = 0x00080000,
550 .offset = 0x00000000,
551 .mask_flags = MTD_WRITEABLE, /* force read-only */
552 }, {
553 .name = "kernel",
554 .size = 0x00100000,
555 .offset = 0x00080000,
556 }, {
557 .name = "initrd",
558 .size = 0x00280000,
559 .offset = 0x00180000,
560 }, {
561 .name = "initrd-test",
562 .size = 0x03C00000,
563 .offset = 0x00400000,
566 #endif
568 #ifdef CONFIG_SA1100_PT_SYSTEM3
569 /* erase size is 0x40000 == 256k partitions have to have this boundary */
570 static struct mtd_partition system3_partitions[] = {
572 .name = "BLOB",
573 .size = 0x00040000,
574 .offset = 0x00000000,
575 .mask_flags = MTD_WRITEABLE, /* force read-only */
576 }, {
577 .name = "config",
578 .size = 0x00040000,
579 .offset = MTDPART_OFS_APPEND,
580 }, {
581 .name = "kernel",
582 .size = 0x00100000,
583 .offset = MTDPART_OFS_APPEND,
584 }, {
585 .name = "root",
586 .size = MTDPART_SIZ_FULL,
587 .offset = MTDPART_OFS_APPEND,
590 #endif
592 #ifdef CONFIG_SA1100_SHANNON
593 static struct mtd_partition shannon_partitions[] = {
595 .name = "BLOB boot loader",
596 .offset = 0,
597 .size = 0x20000
600 .name = "kernel",
601 .offset = MTDPART_OFS_APPEND,
602 .size = 0xe0000
605 .name = "initrd",
606 .offset = MTDPART_OFS_APPEND,
607 .size = MTDPART_SIZ_FULL
611 #endif
613 #ifdef CONFIG_SA1100_SHERMAN
614 static struct mtd_partition sherman_partitions[] = {
616 .size = 0x50000,
617 .offset = 0,
618 }, {
619 .size = 0x70000,
620 .offset = MTDPART_OFS_APPEND,
621 }, {
622 .size = 0x600000,
623 .offset = MTDPART_OFS_APPEND,
624 }, {
625 .size = 0xA0000,
626 .offset = MTDPART_OFS_APPEND,
629 #endif
631 #ifdef CONFIG_SA1100_SIMPAD
632 static struct mtd_partition simpad_partitions[] = {
634 .name = "SIMpad boot firmware",
635 .size = 0x00080000,
636 .offset = 0,
637 .mask_flags = MTD_WRITEABLE, /* force read-only */
638 }, {
639 .name = "SIMpad kernel",
640 .size = 0x00100000,
641 .offset = MTDPART_OFS_APPEND,
642 }, {
643 #ifdef CONFIG_ROOT_CRAMFS
644 .name = "SIMpad root cramfs",
645 .size =0x00D80000,
646 .offset = MTDPART_OFS_APPEND
648 }, {
649 .name = "SIMpad local jffs2",
650 .size = MTDPART_SIZ_FULL,
651 .offset = MTDPART_OFS_APPEND
652 #else
653 .name = "SIMpad root jffs2",
654 .size = MTDPART_SIZ_FULL,
655 .offset = MTDPART_OFS_APPEND
656 #endif
659 #endif /* CONFIG_SA1100_SIMPAD */
661 #ifdef CONFIG_SA1100_STORK
662 static struct mtd_partition stork_partitions[] = {
664 .name = "STORK boot firmware",
665 .size = 0x00040000,
666 .offset = 0,
667 .mask_flags = MTD_WRITEABLE, /* force read-only */
668 }, {
669 .name = "STORK params",
670 .size = 0x00040000,
671 .offset = 0x00040000,
672 }, {
673 .name = "STORK kernel",
674 .size = 0x00100000,
675 .offset = 0x00080000,
676 }, {
677 #ifdef CONFIG_JFFS2_FS
678 .name = "STORK root jffs2",
679 .offset = 0x00180000,
680 .size = MTDPART_SIZ_FULL,
681 #else
682 .name = "STORK initrd",
683 .size = 0x00100000,
684 .offset = 0x00180000,
685 }, {
686 .name = "STORK root cramfs",
687 .size = 0x00300000,
688 .offset = 0x00280000,
689 }, {
690 .name = "STORK usr cramfs",
691 .size = 0x00800000,
692 .offset = 0x00580000,
693 }, {
694 .name = "STORK usr local",
695 .offset = 0x00d80000,
696 .size = MTDPART_SIZ_FULL,
697 #endif
700 #endif
702 #ifdef CONFIG_SA1100_TRIZEPS
703 static struct mtd_partition trizeps_partitions[] = {
705 .name = "Bootloader",
706 .size = 0x00100000,
707 .offset = 0,
708 }, {
709 .name = "Kernel",
710 .size = 0x00100000,
711 .offset = MTDPART_OFS_APPEND,
712 }, {
713 .name = "root",
714 .size = MTDPART_SIZ_FULL,
715 .offset = MTDPART_OFS_APPEND,
718 #endif
720 #ifdef CONFIG_SA1100_YOPY
721 static struct mtd_partition yopy_partitions[] = {
723 .name = "boot firmware",
724 .size = 0x00040000,
725 .offset = 0x00000000,
726 .mask_flags = MTD_WRITEABLE, /* force read-only */
727 }, {
728 .name = "kernel",
729 .size = 0x00080000,
730 .offset = 0x00080000,
731 }, {
732 .name = "initrd",
733 .size = 0x00300000,
734 .offset = 0x00100000,
735 }, {
736 .name = "root",
737 .size = 0x01000000,
738 .offset = 0x00400000,
741 #endif
743 static int __init sa1100_static_partitions(struct mtd_partition **parts)
745 int nb_parts = 0;
747 #ifdef CONFIG_SA1100_ADSBITSY
748 if (machine_is_adsbitsy()) {
749 *parts = adsbitsy_partitions;
750 nb_parts = ARRAY_SIZE(adsbitsy_partitions);
752 #endif
753 #ifdef CONFIG_SA1100_ASSABET
754 if (machine_is_assabet()) {
755 *parts = assabet_partitions;
756 nb_parts = ARRAY_SIZE(assabet_partitions);
758 #endif
759 #ifdef CONFIG_SA1100_BADGE4
760 if (machine_is_badge4()) {
761 *parts = badge4_partitions;
762 nb_parts = ARRAY_SIZE(badge4_partitions);
764 #endif
765 #ifdef CONFIG_SA1100_CERF
766 if (machine_is_cerf()) {
767 *parts = cerf_partitions;
768 nb_parts = ARRAY_SIZE(cerf_partitions);
770 #endif
771 #ifdef CONFIG_SA1100_CONSUS
772 if (machine_is_consus()) {
773 *parts = consus_partitions;
774 nb_parts = ARRAY_SIZE(consus_partitions);
776 #endif
777 #ifdef CONFIG_SA1100_FLEXANET
778 if (machine_is_flexanet()) {
779 *parts = flexanet_partitions;
780 nb_parts = ARRAY_SIZE(flexanet_partitions);
782 #endif
783 #ifdef CONFIG_SA1100_FREEBIRD
784 if (machine_is_freebird()) {
785 *parts = freebird_partitions;
786 nb_parts = ARRAY_SIZE(freebird_partitions);
788 #endif
789 #ifdef CONFIG_SA1100_FRODO
790 if (machine_is_frodo()) {
791 *parts = frodo_partitions;
792 nb_parts = ARRAY_SIZE(frodo_partitions);
794 #endif
795 #ifdef CONFIG_SA1100_GRAPHICSCLIENT
796 if (machine_is_graphicsclient()) {
797 *parts = graphicsclient_partitions;
798 nb_parts = ARRAY_SIZE(graphicsclient_partitions);
800 #endif
801 #ifdef CONFIG_SA1100_GRAPHICSMASTER
802 if (machine_is_graphicsmaster()) {
803 *parts = graphicsmaster_partitions;
804 nb_parts = ARRAY_SIZE(graphicsmaster_partitions);
806 #endif
807 #ifdef CONFIG_SA1100_H3XXX
808 if (machine_is_h3xxx()) {
809 *parts = h3xxx_partitions;
810 nb_parts = ARRAY_SIZE(h3xxx_partitions);
812 #endif
813 #ifdef CONFIG_SA1100_HACKKIT
814 if (machine_is_hackkit()) {
815 *parts = hackkit_partitions;
816 nb_parts = ARRAY_SIZE(hackkit_partitions);
818 #endif
819 #ifdef CONFIG_SA1100_HUW_WEBPANEL
820 if (machine_is_huw_webpanel()) {
821 *parts = huw_webpanel_partitions;
822 nb_parts = ARRAY_SIZE(huw_webpanel_partitions);
824 #endif
825 #ifdef CONFIG_SA1100_JORNADA720
826 if (machine_is_jornada720()) {
827 *parts = jornada720_partitions;
828 nb_parts = ARRAY_SIZE(jornada720_partitions);
830 #endif
831 #ifdef CONFIG_SA1100_PANGOLIN
832 if (machine_is_pangolin()) {
833 *parts = pangolin_partitions;
834 nb_parts = ARRAY_SIZE(pangolin_partitions);
836 #endif
837 #ifdef CONFIG_SA1100_PT_SYSTEM3
838 if (machine_is_pt_system3()) {
839 *parts = system3_partitions;
840 nb_parts = ARRAY_SIZE(system3_partitions);
842 #endif
843 #ifdef CONFIG_SA1100_SHANNON
844 if (machine_is_shannon()) {
845 *parts = shannon_partitions;
846 nb_parts = ARRAY_SIZE(shannon_partitions);
848 #endif
849 #ifdef CONFIG_SA1100_SHERMAN
850 if (machine_is_sherman()) {
851 *parts = sherman_partitions;
852 nb_parts = ARRAY_SIZE(sherman_partitions);
854 #endif
855 #ifdef CONFIG_SA1100_SIMPAD
856 if (machine_is_simpad()) {
857 *parts = simpad_partitions;
858 nb_parts = ARRAY_SIZE(simpad_partitions);
860 #endif
861 #ifdef CONFIG_SA1100_STORK
862 if (machine_is_stork()) {
863 *parts = stork_partitions;
864 nb_parts = ARRAY_SIZE(stork_partitions);
866 #endif
867 #ifdef CONFIG_SA1100_TRIZEPS
868 if (machine_is_trizeps()) {
869 *parts = trizeps_partitions;
870 nb_parts = ARRAY_SIZE(trizeps_partitions);
872 #endif
873 #ifdef CONFIG_SA1100_YOPY
874 if (machine_is_yopy()) {
875 *parts = yopy_partitions;
876 nb_parts = ARRAY_SIZE(yopy_partitions);
878 #endif
880 return nb_parts;
882 #endif
884 struct sa_info {
885 unsigned long base;
886 unsigned long size;
887 int width;
888 void __iomem *vbase;
889 void (*set_vpp)(struct map_info *, int);
890 struct map_info *map;
891 struct mtd_info *mtd;
892 struct resource *res;
895 #define NR_SUBMTD 4
897 static struct sa_info info[NR_SUBMTD];
899 static int __init sa1100_setup_mtd(struct sa_info *sa, int nr, struct mtd_info **rmtd)
901 struct mtd_info *subdev[nr];
902 struct map_info *maps;
903 int i, found = 0, ret = 0;
906 * Allocate the map_info structs in one go.
908 maps = kmalloc(sizeof(struct map_info) * nr, GFP_KERNEL);
909 if (!maps)
910 return -ENOMEM;
912 memset(maps, 0, sizeof(struct map_info) * nr);
915 * Claim and then map the memory regions.
917 for (i = 0; i < nr; i++) {
918 if (sa[i].base == (unsigned long)-1)
919 break;
921 sa[i].res = request_mem_region(sa[i].base, sa[i].size, "sa1100 flash");
922 if (!sa[i].res) {
923 ret = -EBUSY;
924 break;
927 sa[i].map = maps + i;
929 sa[i].vbase = ioremap(sa[i].base, sa[i].size);
930 if (!sa[i].vbase) {
931 ret = -ENOMEM;
932 break;
935 sa[i].map->virt = sa[i].vbase;
936 sa[i].map->phys = sa[i].base;
937 sa[i].map->set_vpp = sa[i].set_vpp;
938 sa[i].map->bankwidth = sa[i].width;
939 sa[i].map->size = sa[i].size;
941 simple_map_init(sa[i].map);
944 * Now let's probe for the actual flash. Do it here since
945 * specific machine settings might have been set above.
947 sa[i].mtd = do_map_probe("cfi_probe", sa[i].map);
948 if (sa[i].mtd == NULL) {
949 ret = -ENXIO;
950 break;
952 sa[i].mtd->owner = THIS_MODULE;
953 subdev[i] = sa[i].mtd;
955 printk(KERN_INFO "SA1100 flash: CFI device at 0x%08lx, %dMiB, "
956 "%d-bit\n", sa[i].base, sa[i].mtd->size >> 20,
957 sa[i].width * 8);
958 found += 1;
962 * ENXIO is special. It means we didn't find a chip when
963 * we probed. We need to tear down the mapping, free the
964 * resource and mark it as such.
966 if (ret == -ENXIO) {
967 iounmap(sa[i].vbase);
968 sa[i].vbase = NULL;
969 release_resource(sa[i].res);
970 sa[i].res = NULL;
974 * If we found one device, don't bother with concat support.
975 * If we found multiple devices, use concat if we have it
976 * available, otherwise fail.
978 if (ret == 0 || ret == -ENXIO) {
979 if (found == 1) {
980 *rmtd = subdev[0];
981 ret = 0;
982 } else if (found > 1) {
984 * We detected multiple devices. Concatenate
985 * them together.
987 #ifdef CONFIG_MTD_CONCAT
988 *rmtd = mtd_concat_create(subdev, found,
989 "sa1100 flash");
990 if (*rmtd == NULL)
991 ret = -ENXIO;
992 #else
993 printk(KERN_ERR "SA1100 flash: multiple devices "
994 "found but MTD concat support disabled.\n");
995 ret = -ENXIO;
996 #endif
1001 * If we failed, clean up.
1003 if (ret) {
1004 do {
1005 if (sa[i].mtd)
1006 map_destroy(sa[i].mtd);
1007 if (sa[i].vbase)
1008 iounmap(sa[i].vbase);
1009 if (sa[i].res)
1010 release_resource(sa[i].res);
1011 } while (i--);
1013 kfree(maps);
1016 return ret;
1019 static void __exit sa1100_destroy_mtd(struct sa_info *sa, struct mtd_info *mtd)
1021 int i;
1023 del_mtd_partitions(mtd);
1025 #ifdef CONFIG_MTD_CONCAT
1026 if (mtd != sa[0].mtd)
1027 mtd_concat_destroy(mtd);
1028 #endif
1030 for (i = NR_SUBMTD; i >= 0; i--) {
1031 if (sa[i].mtd)
1032 map_destroy(sa[i].mtd);
1033 if (sa[i].vbase)
1034 iounmap(sa[i].vbase);
1035 if (sa[i].res)
1036 release_resource(sa[i].res);
1038 kfree(sa[0].map);
1042 * A Thought: can we automatically detect the flash?
1043 * - Check to see if the region is busy (yes -> failure)
1044 * - Is the MSC setup for flash (no -> failure)
1045 * - Probe for flash
1048 static struct map_info sa1100_probe_map __initdata = {
1049 .name = "SA1100-flash",
1052 static void __init sa1100_probe_one_cs(unsigned int msc, unsigned long phys)
1054 struct mtd_info *mtd;
1056 printk(KERN_INFO "* Probing 0x%08lx: MSC = 0x%04x %d bit ",
1057 phys, msc & 0xffff, msc & MSC_RBW ? 16 : 32);
1059 if (check_mem_region(phys, 0x08000000)) {
1060 printk("busy\n");
1061 return;
1064 if ((msc & 3) == 1) {
1065 printk("wrong type\n");
1066 return;
1069 sa1100_probe_map.bankwidth = msc & MSC_RBW ? 2 : 4;
1070 sa1100_probe_map.size = SZ_1M;
1071 sa1100_probe_map.phys = phys;
1072 sa1100_probe_map.virt = (unsigned long)ioremap(phys, SZ_1M);
1073 if (sa1100_probe_map.virt == 0)
1074 goto fail;
1075 simple_map_init(&sa1100_probe_map);
1077 /* Shame cfi_probe blurts out kernel messages... */
1078 mtd = do_map_probe("cfi_probe", &sa1100_probe_map);
1079 if (mtd)
1080 map_destroy(mtd);
1081 iounmap((void *)sa1100_probe_map.virt);
1083 if (!mtd)
1084 goto fail;
1086 printk("pass\n");
1087 return;
1089 fail:
1090 printk("failed\n");
1093 static void __init sa1100_probe_flash(void)
1095 printk(KERN_INFO "-- SA11xx Flash probe. Please report results.\n");
1096 sa1100_probe_one_cs(MSC0, SA1100_CS0_PHYS);
1097 sa1100_probe_one_cs(MSC0 >> 16, SA1100_CS1_PHYS);
1098 sa1100_probe_one_cs(MSC1, SA1100_CS2_PHYS);
1099 sa1100_probe_one_cs(MSC1 >> 16, SA1100_CS3_PHYS);
1100 sa1100_probe_one_cs(MSC2, SA1100_CS4_PHYS);
1101 sa1100_probe_one_cs(MSC2 >> 16, SA1100_CS5_PHYS);
1102 printk(KERN_INFO "-- SA11xx Flash probe complete.\n");
1105 static int __init sa1100_locate_flash(void)
1107 int i, nr = -ENODEV;
1109 sa1100_probe_flash();
1111 if (machine_is_adsbitsy()) {
1112 info[0].base = SA1100_CS1_PHYS;
1113 info[0].size = SZ_32M;
1114 nr = 1;
1116 if (machine_is_assabet()) {
1117 info[0].base = SA1100_CS0_PHYS;
1118 info[0].size = SZ_32M;
1119 info[1].base = SA1100_CS1_PHYS; /* neponset */
1120 info[1].size = SZ_32M;
1121 nr = 2;
1123 if (machine_is_badge4()) {
1124 info[0].base = SA1100_CS0_PHYS;
1125 info[0].size = SZ_64M;
1126 nr = 1;
1128 if (machine_is_cerf()) {
1129 info[0].base = SA1100_CS0_PHYS;
1130 info[0].size = SZ_32M;
1131 nr = 1;
1133 if (machine_is_consus()) {
1134 info[0].base = SA1100_CS0_PHYS;
1135 info[0].size = SZ_32M;
1136 nr = 1;
1138 if (machine_is_flexanet()) {
1139 info[0].base = SA1100_CS0_PHYS;
1140 info[0].size = SZ_32M;
1141 nr = 1;
1143 if (machine_is_freebird()) {
1144 info[0].base = SA1100_CS0_PHYS;
1145 info[0].size = SZ_32M;
1146 nr = 1;
1148 if (machine_is_frodo()) {
1149 info[0].base = SA1100_CS0_PHYS;
1150 info[0].size = SZ_32M;
1151 nr = 1;
1153 if (machine_is_graphicsclient()) {
1154 info[0].base = SA1100_CS1_PHYS;
1155 info[0].size = SZ_32M;
1156 nr = 1;
1158 if (machine_is_graphicsmaster()) {
1159 info[0].base = SA1100_CS1_PHYS;
1160 info[0].size = SZ_16M;
1161 nr = 1;
1163 if (machine_is_h3xxx()) {
1164 info[0].set_vpp = h3xxx_set_vpp;
1165 info[0].base = SA1100_CS0_PHYS;
1166 info[0].size = SZ_32M;
1167 nr = 1;
1169 if (machine_is_huw_webpanel()) {
1170 info[0].base = SA1100_CS0_PHYS;
1171 info[0].size = SZ_16M;
1172 nr = 1;
1174 if (machine_is_itsy()) {
1175 info[0].base = SA1100_CS0_PHYS;
1176 info[0].size = SZ_32M;
1177 nr = 1;
1179 if (machine_is_jornada720()) {
1180 info[0].set_vpp = jornada720_set_vpp;
1181 info[0].base = SA1100_CS0_PHYS;
1182 info[0].size = SZ_32M;
1183 nr = 1;
1185 if (machine_is_nanoengine()) {
1186 info[0].base = SA1100_CS0_PHYS;
1187 info[1].size = SZ_32M;
1188 nr = 1;
1190 if (machine_is_pangolin()) {
1191 info[0].base = SA1100_CS0_PHYS;
1192 info[0].size = SZ_64M;
1193 nr = 1;
1195 if (machine_is_pfs168()) {
1196 info[0].base = SA1100_CS0_PHYS;
1197 info[0].size = SZ_32M;
1198 nr = 1;
1200 if (machine_is_pleb()) {
1201 info[0].base = SA1100_CS0_PHYS;
1202 info[0].size = SZ_4M;
1203 info[1].base = SA1100_CS1_PHYS;
1204 info[1].size = SZ_4M;
1205 nr = 2;
1207 if (machine_is_pt_system3()) {
1208 info[0].base = SA1100_CS0_PHYS;
1209 info[0].size = SZ_16M;
1210 nr = 1;
1212 if (machine_is_shannon()) {
1213 info[0].base = SA1100_CS0_PHYS;
1214 info[0].size = SZ_4M;
1215 nr = 1;
1217 if (machine_is_sherman()) {
1218 info[0].base = SA1100_CS0_PHYS;
1219 info[0].size = SZ_32M;
1220 nr = 1;
1222 if (machine_is_simpad()) {
1223 info[0].base = SA1100_CS0_PHYS;
1224 info[0].size = SZ_16M;
1225 info[1].base = SA1100_CS1_PHYS;
1226 info[1].size = SZ_16M;
1227 nr = 2;
1229 if (machine_is_stork()) {
1230 info[0].base = SA1100_CS0_PHYS;
1231 info[0].size = SZ_32M;
1232 nr = 1;
1234 if (machine_is_trizeps()) {
1235 info[0].base = SA1100_CS0_PHYS;
1236 info[0].size = SZ_16M;
1237 nr = 1;
1239 if (machine_is_victor()) {
1240 info[0].base = SA1100_CS0_PHYS;
1241 info[0].size = SZ_2M;
1242 nr = 1;
1244 if (machine_is_yopy()) {
1245 info[0].base = SA1100_CS0_PHYS;
1246 info[0].size = SZ_64M;
1247 info[1].base = SA1100_CS1_PHYS;
1248 info[1].size = SZ_64M;
1249 nr = 2;
1252 if (nr < 0)
1253 return nr;
1256 * Retrieve the bankwidth from the MSC registers.
1257 * We currently only implement CS0 and CS1 here.
1259 for (i = 0; i < nr; i++) {
1260 switch (info[i].base) {
1261 default:
1262 printk(KERN_WARNING "SA1100 flash: unknown base address "
1263 "0x%08lx, assuming CS0\n", info[i].base);
1264 case SA1100_CS0_PHYS:
1265 info[i].width = (MSC0 & MSC_RBW) ? 2 : 4;
1266 break;
1268 case SA1100_CS1_PHYS:
1269 info[i].width = ((MSC0 >> 16) & MSC_RBW) ? 2 : 4;
1270 break;
1274 return nr;
1277 static struct mtd_partition *parsed_parts;
1278 const char *part_probes[] = { "cmdlinepart", "RedBoot", NULL };
1280 static void __init sa1100_locate_partitions(struct mtd_info *mtd)
1282 const char *part_type = NULL;
1283 int nr_parts = 0;
1285 do {
1287 * Partition selection stuff.
1289 #ifdef CONFIG_MTD_PARTITIONS
1290 nr_parts = parse_mtd_partitions(mtd, part_probes, &parsed_parts, 0);
1291 if (nr_parts > 0) {
1292 part_type = "dynamic";
1293 break;
1295 #endif
1296 #ifdef CONFIG_MTD_SA1100_STATICMAP
1297 nr_parts = sa1100_static_partitions(&parsed_parts);
1298 if (nr_parts > 0) {
1299 part_type = "static";
1300 break;
1302 #endif
1303 } while (0);
1305 if (nr_parts == 0) {
1306 printk(KERN_NOTICE "SA1100 flash: no partition info "
1307 "available, registering whole flash\n");
1308 add_mtd_device(mtd);
1309 } else {
1310 printk(KERN_NOTICE "SA1100 flash: using %s partition "
1311 "definition\n", part_type);
1312 add_mtd_partitions(mtd, parsed_parts, nr_parts);
1315 /* Always succeeds. */
1318 static void __exit sa1100_destroy_partitions(void)
1320 if (parsed_parts)
1321 kfree(parsed_parts);
1324 static struct mtd_info *mymtd;
1326 static int __init sa1100_mtd_init(void)
1328 int ret;
1329 int nr;
1331 nr = sa1100_locate_flash();
1332 if (nr < 0)
1333 return nr;
1335 ret = sa1100_setup_mtd(info, nr, &mymtd);
1336 if (ret == 0)
1337 sa1100_locate_partitions(mymtd);
1339 return ret;
1342 static void __exit sa1100_mtd_cleanup(void)
1344 sa1100_destroy_mtd(info, mymtd);
1345 sa1100_destroy_partitions();
1348 module_init(sa1100_mtd_init);
1349 module_exit(sa1100_mtd_cleanup);
1351 MODULE_AUTHOR("Nicolas Pitre");
1352 MODULE_DESCRIPTION("SA1100 CFI map driver");
1353 MODULE_LICENSE("GPL");