2 * Flash memory access on SA11x0 based devices
4 * (C) 2000 Nicolas Pitre <nico@cam.org>
6 * $Id: sa1100-flash.c,v 1.36 2003/05/29 08:59:35 dwmw2 Exp $
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>
26 #include <asm/sizes.h>
28 #include <asm/arch/h3600.h>
30 #ifndef CONFIG_ARCH_SA1100
31 #error This is for SA1100 architecture only
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
46 * 1. We no longer support static flash mappings via the machine io_desc
48 * 2. The flash size given should be the largest flash size that can
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
58 #ifdef CONFIG_SA1100_ADSBITSY
59 static struct mtd_partition adsbitsy_partitions[] = {
64 .mask_flags = MTD_WRITEABLE, /* force read-only */
68 .offset = MTDPART_OFS_APPEND,
69 .mask_flags = MTD_WRITEABLE, /* force read-only */
73 .offset = MTDPART_OFS_APPEND,
74 .mask_flags = MTD_WRITEABLE, /* force read-only */
77 .size = MTDPART_SIZ_FULL,
78 .offset = MTDPART_OFS_APPEND,
83 #ifdef CONFIG_SA1100_ASSABET
84 /* Phase 4 Assabet has two 28F160B3 flash parts in bank 0: */
85 static struct mtd_partition assabet4_partitions[] = {
90 .mask_flags = MTD_WRITEABLE,
92 .name = "bootloader params",
94 .offset = MTDPART_OFS_APPEND,
95 .mask_flags = MTD_WRITEABLE,
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",
109 .mask_flags = MTD_WRITEABLE,
111 .name = "bootloader params",
113 .offset = MTDPART_OFS_APPEND,
114 .mask_flags = MTD_WRITEABLE,
117 .size = MTDPART_SIZ_FULL,
118 .offset = MTDPART_OFS_APPEND,
122 #define assabet_partitions assabet5_partitions
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)
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",
144 .offset = MTDPART_OFS_APPEND,
148 .offset = MTDPART_OFS_APPEND,
149 .size = MTDPART_SIZ_FULL
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
163 # error "Undefined flash size for CERF in sa1100-flash.c"
166 static struct mtd_partition cerf_partitions[] = {
168 .name = "Bootloader",
170 .offset = 0x00000000,
174 .offset = 0x00020000,
178 .offset = 0x00060000,
180 .name = "Filesystem",
181 .size = CERF_FLASH_SIZE-0x00160000,
182 .offset = 0x00160000,
187 #ifdef CONFIG_SA1100_CONSUS
188 static struct mtd_partition consus_partitions[] = {
190 .name = "Consus boot firmware",
193 .mask_flags = MTD_WRITABLE, /* force read-only */
195 .name = "Consus kernel",
196 .offset = 0x00040000,
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,
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
216 .name = "Consus disk2",
217 .offset = 0x01000000,
218 .size = 0x01000000 - 0x00140000,
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",
232 .mask_flags = MTD_WRITEABLE,
234 .name = "bootloader params",
236 .offset = MTDPART_OFS_APPEND,
237 .mask_flags = MTD_WRITEABLE,
241 .offset = MTDPART_OFS_APPEND,
242 .mask_flags = MTD_WRITEABLE,
246 .offset = MTDPART_OFS_APPEND,
247 .mask_flags = MTD_WRITEABLE,
251 .offset = MTDPART_OFS_APPEND,
252 .mask_flags = MTD_WRITEABLE,
256 .offset = MTDPART_OFS_APPEND,
257 .mask_flags = MTD_WRITEABLE,
261 .offset = MTDPART_OFS_APPEND,
262 .mask_flags = MTD_WRITEABLE,
265 .size = MTDPART_SIZ_FULL,
266 .offset = MTDPART_OFS_APPEND,
267 .mask_flags = MTD_WRITEABLE,
272 #ifdef CONFIG_SA1100_FREEBIRD
273 static struct mtd_partition freebird_partitions[] = {
274 #ifdef CONFIG_SA1100_FREEBIRD_NEW
279 .mask_flags = MTD_WRITEABLE, /* force read-only */
283 .offset = 0x00040000,
287 .offset = 0x000C0000,
291 .offset = 0x00100000,
293 .name = "root cramfs",
295 .offset = 0x00200000,
297 .name = "usr cramfs",
299 .offset = 0x00500000,
302 .size = MTDPART_SIZ_FULL,
303 .offset = 0x01100000,
311 .offset = MTDPART_OFS_APPEND,
314 .offset = MTDPART_OFS_APPEND,
316 .size = MTDPART_SIZ_FULL,
317 .offset = MTDPART_OFS_APPEND,
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",
330 .offset = 0x00000000,
331 .mask_flags = MTD_WRITEABLE
333 .name = "bootloader params",
335 .offset = MTDPART_OFS_APPEND,
336 .mask_flags = MTD_WRITEABLE
340 .offset = MTDPART_OFS_APPEND,
341 .mask_flags = MTD_WRITEABLE
345 .offset = MTDPART_OFS_APPEND,
346 .mask_flags = MTD_WRITEABLE
348 .name = "file system",
349 .size = MTDPART_SIZ_FULL,
350 .offset = MTDPART_OFS_APPEND
355 #ifdef CONFIG_SA1100_GRAPHICSCLIENT
356 static struct mtd_partition graphicsclient_partitions[] = {
361 .mask_flags = MTD_WRITEABLE, /* force read-only */
363 .name = "ramdisk.gz",
365 .offset = MTDPART_OFS_APPEND,
366 .mask_flags = MTD_WRITEABLE, /* force read-only */
369 .size = MTDPART_SIZ_FULL,
370 .offset = MTDPART_OFS_APPEND,
375 #ifdef CONFIG_SA1100_GRAPHICSMASTER
376 static struct mtd_partition graphicsmaster_partitions[] = {
381 .mask_flags = MTD_WRITEABLE, /* force read-only */
384 .name = "ramdisk.gz",
386 .offset = MTDPART_OFS_APPEND,
387 .mask_flags = MTD_WRITEABLE, /* force read-only */
391 .size = MTDPART_SIZ_FULL,
392 .offset = MTDPART_OFS_APPEND,
397 #ifdef CONFIG_SA1100_H3XXX
398 static struct mtd_partition h3xxx_partitions[] = {
400 .name = "H3XXX boot firmware",
403 .mask_flags = MTD_WRITEABLE, /* force read-only */
405 #ifdef CONFIG_MTD_2PARTS_IPAQ
406 .name = "H3XXX root jffs2",
407 .size = MTDPART_SIZ_FULL,
408 .offset = 0x00040000,
410 .name = "H3XXX kernel",
412 .offset = 0x00040000,
414 .name = "H3XXX params",
416 .offset = 0x000C0000,
418 #ifdef CONFIG_JFFS2_FS
419 .name = "H3XXX root jffs2",
420 .size = MTDPART_SIZ_FULL,
421 .offset = 0x00100000,
423 .name = "H3XXX initrd",
425 .offset = 0x00100000,
427 .name = "H3XXX root cramfs",
429 .offset = 0x00200000,
431 .name = "H3XXX usr cramfs",
433 .offset = 0x00500000,
435 .name = "H3XXX usr local",
436 .size = MTDPART_SIZ_FULL,
437 .offset = 0x00d00000,
443 static void h3xxx_set_vpp(struct map_info *map, int vpp)
445 assign_h3600_egpio(IPAQ_EGPIO_VPP_ON, vpp);
448 #define h3xxx_set_vpp NULL
451 #ifdef CONFIG_SA1100_HACKKIT
452 static struct mtd_partition hackkit_partitions[] = {
456 .offset = 0x00000000,
457 .mask_flags = MTD_WRITEABLE, /* force read-only */
461 .offset = MTDPART_OFS_APPEND,
465 .offset = MTDPART_OFS_APPEND,
469 .offset = MTDPART_OFS_APPEND,
473 .offset = MTDPART_OFS_APPEND,
476 .size = MTDPART_SIZ_FULL,
477 .offset = MTDPART_OFS_APPEND,
482 #ifdef CONFIG_SA1100_HUW_WEBPANEL
483 static struct mtd_partition huw_webpanel_partitions[] = {
491 .offset = MTDPART_OFS_APPEND,
493 .size = MTDPART_SIZ_FULL,
494 .offset = MTDPART_OFS_APPEND,
499 #ifdef CONFIG_SA1100_JORNADA720
500 static struct mtd_partition jornada720_partitions[] = {
502 .name = "JORNADA720 boot firmware",
505 .mask_flags = MTD_WRITEABLE, /* force read-only */
507 .name = "JORNADA720 kernel",
509 .offset = 0x00040000,
511 .name = "JORNADA720 params",
513 .offset = 0x00100000,
515 .name = "JORNADA720 initrd",
517 .offset = 0x00140000,
519 .name = "JORNADA720 root cramfs",
521 .offset = 0x00240000,
523 .name = "JORNADA720 usr cramfs",
525 .offset = 0x00540000,
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)
542 #define jornada720_set_vpp NULL
545 #ifdef CONFIG_SA1100_PANGOLIN
546 static struct mtd_partition pangolin_partitions[] = {
548 .name = "boot firmware",
550 .offset = 0x00000000,
551 .mask_flags = MTD_WRITEABLE, /* force read-only */
555 .offset = 0x00080000,
559 .offset = 0x00180000,
561 .name = "initrd-test",
563 .offset = 0x00400000,
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[] = {
574 .offset = 0x00000000,
575 .mask_flags = MTD_WRITEABLE, /* force read-only */
579 .offset = MTDPART_OFS_APPEND,
583 .offset = MTDPART_OFS_APPEND,
586 .size = MTDPART_SIZ_FULL,
587 .offset = MTDPART_OFS_APPEND,
592 #ifdef CONFIG_SA1100_SHANNON
593 static struct mtd_partition shannon_partitions[] = {
595 .name = "BLOB boot loader",
601 .offset = MTDPART_OFS_APPEND,
606 .offset = MTDPART_OFS_APPEND,
607 .size = MTDPART_SIZ_FULL
613 #ifdef CONFIG_SA1100_SHERMAN
614 static struct mtd_partition sherman_partitions[] = {
620 .offset = MTDPART_OFS_APPEND,
623 .offset = MTDPART_OFS_APPEND,
626 .offset = MTDPART_OFS_APPEND,
631 #ifdef CONFIG_SA1100_SIMPAD
632 static struct mtd_partition simpad_partitions[] = {
634 .name = "SIMpad boot firmware",
637 .mask_flags = MTD_WRITEABLE, /* force read-only */
639 .name = "SIMpad kernel",
641 .offset = MTDPART_OFS_APPEND,
643 #ifdef CONFIG_ROOT_CRAMFS
644 .name = "SIMpad root cramfs",
646 .offset = MTDPART_OFS_APPEND
649 .name = "SIMpad local jffs2",
650 .size = MTDPART_SIZ_FULL,
651 .offset = MTDPART_OFS_APPEND
653 .name = "SIMpad root jffs2",
654 .size = MTDPART_SIZ_FULL,
655 .offset = MTDPART_OFS_APPEND
659 #endif /* CONFIG_SA1100_SIMPAD */
661 #ifdef CONFIG_SA1100_STORK
662 static struct mtd_partition stork_partitions[] = {
664 .name = "STORK boot firmware",
667 .mask_flags = MTD_WRITEABLE, /* force read-only */
669 .name = "STORK params",
671 .offset = 0x00040000,
673 .name = "STORK kernel",
675 .offset = 0x00080000,
677 #ifdef CONFIG_JFFS2_FS
678 .name = "STORK root jffs2",
679 .offset = 0x00180000,
680 .size = MTDPART_SIZ_FULL,
682 .name = "STORK initrd",
684 .offset = 0x00180000,
686 .name = "STORK root cramfs",
688 .offset = 0x00280000,
690 .name = "STORK usr cramfs",
692 .offset = 0x00580000,
694 .name = "STORK usr local",
695 .offset = 0x00d80000,
696 .size = MTDPART_SIZ_FULL,
702 #ifdef CONFIG_SA1100_TRIZEPS
703 static struct mtd_partition trizeps_partitions[] = {
705 .name = "Bootloader",
711 .offset = MTDPART_OFS_APPEND,
714 .size = MTDPART_SIZ_FULL,
715 .offset = MTDPART_OFS_APPEND,
720 #ifdef CONFIG_SA1100_YOPY
721 static struct mtd_partition yopy_partitions[] = {
723 .name = "boot firmware",
725 .offset = 0x00000000,
726 .mask_flags = MTD_WRITEABLE, /* force read-only */
730 .offset = 0x00080000,
734 .offset = 0x00100000,
738 .offset = 0x00400000,
743 static int __init sa1100_static_partitions(struct mtd_partition **parts)
747 #ifdef CONFIG_SA1100_ADSBITSY
748 if (machine_is_adsbitsy()) {
749 *parts = adsbitsy_partitions;
750 nb_parts = ARRAY_SIZE(adsbitsy_partitions);
753 #ifdef CONFIG_SA1100_ASSABET
754 if (machine_is_assabet()) {
755 *parts = assabet_partitions;
756 nb_parts = ARRAY_SIZE(assabet_partitions);
759 #ifdef CONFIG_SA1100_BADGE4
760 if (machine_is_badge4()) {
761 *parts = badge4_partitions;
762 nb_parts = ARRAY_SIZE(badge4_partitions);
765 #ifdef CONFIG_SA1100_CERF
766 if (machine_is_cerf()) {
767 *parts = cerf_partitions;
768 nb_parts = ARRAY_SIZE(cerf_partitions);
771 #ifdef CONFIG_SA1100_CONSUS
772 if (machine_is_consus()) {
773 *parts = consus_partitions;
774 nb_parts = ARRAY_SIZE(consus_partitions);
777 #ifdef CONFIG_SA1100_FLEXANET
778 if (machine_is_flexanet()) {
779 *parts = flexanet_partitions;
780 nb_parts = ARRAY_SIZE(flexanet_partitions);
783 #ifdef CONFIG_SA1100_FREEBIRD
784 if (machine_is_freebird()) {
785 *parts = freebird_partitions;
786 nb_parts = ARRAY_SIZE(freebird_partitions);
789 #ifdef CONFIG_SA1100_FRODO
790 if (machine_is_frodo()) {
791 *parts = frodo_partitions;
792 nb_parts = ARRAY_SIZE(frodo_partitions);
795 #ifdef CONFIG_SA1100_GRAPHICSCLIENT
796 if (machine_is_graphicsclient()) {
797 *parts = graphicsclient_partitions;
798 nb_parts = ARRAY_SIZE(graphicsclient_partitions);
801 #ifdef CONFIG_SA1100_GRAPHICSMASTER
802 if (machine_is_graphicsmaster()) {
803 *parts = graphicsmaster_partitions;
804 nb_parts = ARRAY_SIZE(graphicsmaster_partitions);
807 #ifdef CONFIG_SA1100_H3XXX
808 if (machine_is_h3xxx()) {
809 *parts = h3xxx_partitions;
810 nb_parts = ARRAY_SIZE(h3xxx_partitions);
813 #ifdef CONFIG_SA1100_HACKKIT
814 if (machine_is_hackkit()) {
815 *parts = hackkit_partitions;
816 nb_parts = ARRAY_SIZE(hackkit_partitions);
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);
825 #ifdef CONFIG_SA1100_JORNADA720
826 if (machine_is_jornada720()) {
827 *parts = jornada720_partitions;
828 nb_parts = ARRAY_SIZE(jornada720_partitions);
831 #ifdef CONFIG_SA1100_PANGOLIN
832 if (machine_is_pangolin()) {
833 *parts = pangolin_partitions;
834 nb_parts = ARRAY_SIZE(pangolin_partitions);
837 #ifdef CONFIG_SA1100_PT_SYSTEM3
838 if (machine_is_pt_system3()) {
839 *parts = system3_partitions;
840 nb_parts = ARRAY_SIZE(system3_partitions);
843 #ifdef CONFIG_SA1100_SHANNON
844 if (machine_is_shannon()) {
845 *parts = shannon_partitions;
846 nb_parts = ARRAY_SIZE(shannon_partitions);
849 #ifdef CONFIG_SA1100_SHERMAN
850 if (machine_is_sherman()) {
851 *parts = sherman_partitions;
852 nb_parts = ARRAY_SIZE(sherman_partitions);
855 #ifdef CONFIG_SA1100_SIMPAD
856 if (machine_is_simpad()) {
857 *parts = simpad_partitions;
858 nb_parts = ARRAY_SIZE(simpad_partitions);
861 #ifdef CONFIG_SA1100_STORK
862 if (machine_is_stork()) {
863 *parts = stork_partitions;
864 nb_parts = ARRAY_SIZE(stork_partitions);
867 #ifdef CONFIG_SA1100_TRIZEPS
868 if (machine_is_trizeps()) {
869 *parts = trizeps_partitions;
870 nb_parts = ARRAY_SIZE(trizeps_partitions);
873 #ifdef CONFIG_SA1100_YOPY
874 if (machine_is_yopy()) {
875 *parts = yopy_partitions;
876 nb_parts = ARRAY_SIZE(yopy_partitions);
889 void (*set_vpp)(struct map_info *, int);
890 struct map_info *map;
891 struct mtd_info *mtd;
892 struct resource *res;
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);
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)
921 sa[i].res = request_mem_region(sa[i].base, sa[i].size, "sa1100 flash");
927 sa[i].map = maps + i;
929 sa[i].vbase = ioremap(sa[i].base, sa[i].size);
935 sa[i].map->virt = (unsigned long)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->buswidth = 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) {
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,
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.
967 iounmap(sa[i].vbase);
969 release_resource(sa[i].res);
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) {
982 } else if (found > 1) {
984 * We detected multiple devices. Concatenate
987 #ifdef CONFIG_MTD_CONCAT
988 *rmtd = mtd_concat_create(subdev, found,
993 printk(KERN_ERR "SA1100 flash: multiple devices "
994 "found but MTD concat support disabled.\n");
1001 * If we failed, clean up.
1006 map_destroy(sa[i].mtd);
1008 iounmap(sa[i].vbase);
1010 release_resource(sa[i].res);
1019 static void __exit sa1100_destroy_mtd(struct sa_info *sa, struct mtd_info *mtd)
1023 del_mtd_partitions(mtd);
1025 #ifdef CONFIG_MTD_CONCAT
1026 if (mtd != sa[0].mtd)
1027 mtd_concat_destroy(mtd);
1030 for (i = NR_SUBMTD; i >= 0; i--) {
1032 map_destroy(sa[i].mtd);
1034 iounmap(sa[i].vbase);
1036 release_resource(sa[i].res);
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)
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)) {
1064 if ((msc & 3) == 1) {
1065 printk("wrong type\n");
1069 sa1100_probe_map.buswidth = 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)
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);
1081 iounmap((void *)sa1100_probe_map.virt);
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;
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;
1123 if (machine_is_badge4()) {
1124 info[0].base = SA1100_CS0_PHYS;
1125 info[0].size = SZ_64M;
1128 if (machine_is_cerf()) {
1129 info[0].base = SA1100_CS0_PHYS;
1130 info[0].size = SZ_32M;
1133 if (machine_is_consus()) {
1134 info[0].base = SA1100_CS0_PHYS;
1135 info[0].size = SZ_32M;
1138 if (machine_is_flexanet()) {
1139 info[0].base = SA1100_CS0_PHYS;
1140 info[0].size = SZ_32M;
1143 if (machine_is_freebird()) {
1144 info[0].base = SA1100_CS0_PHYS;
1145 info[0].size = SZ_32M;
1148 if (machine_is_frodo()) {
1149 info[0].base = SA1100_CS0_PHYS;
1150 info[0].size = SZ_32M;
1153 if (machine_is_graphicsclient()) {
1154 info[0].base = SA1100_CS1_PHYS;
1155 info[0].size = SZ_32M;
1158 if (machine_is_graphicsmaster()) {
1159 info[0].base = SA1100_CS1_PHYS;
1160 info[0].size = SZ_16M;
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;
1169 if (machine_is_huw_webpanel()) {
1170 info[0].base = SA1100_CS0_PHYS;
1171 info[0].size = SZ_16M;
1174 if (machine_is_itsy()) {
1175 info[0].base = SA1100_CS0_PHYS;
1176 info[0].size = SZ_32M;
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;
1185 if (machine_is_nanoengine()) {
1186 info[0].base = SA1100_CS0_PHYS;
1187 info[1].size = SZ_32M;
1190 if (machine_is_pangolin()) {
1191 info[0].base = SA1100_CS0_PHYS;
1192 info[0].size = SZ_64M;
1195 if (machine_is_pfs168()) {
1196 info[0].base = SA1100_CS0_PHYS;
1197 info[0].size = SZ_32M;
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;
1207 if (machine_is_pt_system3()) {
1208 info[0].base = SA1100_CS0_PHYS;
1209 info[0].size = SZ_16M;
1212 if (machine_is_shannon()) {
1213 info[0].base = SA1100_CS0_PHYS;
1214 info[0].size = SZ_4M;
1217 if (machine_is_sherman()) {
1218 info[0].base = SA1100_CS0_PHYS;
1219 info[0].size = SZ_32M;
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;
1229 if (machine_is_stork()) {
1230 info[0].base = SA1100_CS0_PHYS;
1231 info[0].size = SZ_32M;
1234 if (machine_is_trizeps()) {
1235 info[0].base = SA1100_CS0_PHYS;
1236 info[0].size = SZ_16M;
1239 if (machine_is_victor()) {
1240 info[0].base = SA1100_CS0_PHYS;
1241 info[0].size = SZ_2M;
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;
1256 * Retrieve the buswidth 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) {
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;
1268 case SA1100_CS1_PHYS:
1269 info[i].width = ((MSC0 >> 16) & MSC_RBW) ? 2 : 4;
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;
1287 * Partition selection stuff.
1289 #ifdef CONFIG_MTD_PARTITIONS
1290 nr_parts = parse_mtd_partitions(mtd, part_probes, &parsed_parts, 0);
1292 part_type = "dynamic";
1296 #ifdef CONFIG_MTD_SA1100_STATICMAP
1297 nr_parts = sa1100_static_partitions(&parsed_parts);
1299 part_type = "static";
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);
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)
1321 kfree(parsed_parts);
1324 static struct mtd_info *mymtd;
1326 static int __init sa1100_mtd_init(void)
1331 nr = sa1100_locate_flash();
1335 ret = sa1100_setup_mtd(info, nr, &mymtd);
1337 sa1100_locate_partitions(mymtd);
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");