This commit was manufactured by cvs2svn to create tag
[linux-2.6.git] / drivers / mtd / maps / sa1100-flash.c
index 0a6f861..bb9c077 100644 (file)
@@ -3,8 +3,9 @@
  * 
  * (C) 2000 Nicolas Pitre <nico@cam.org>
  * 
- * $Id: sa1100-flash.c,v 1.47 2004/11/01 13:44:36 rmk Exp $
+ * $Id: sa1100-flash.c,v 1.39 2004/07/12 21:59:44 dwmw2 Exp $
  */
+
 #include <linux/config.h>
 #include <linux/module.h>
 #include <linux/types.h>
 #include <linux/init.h>
 #include <linux/errno.h>
 #include <linux/slab.h>
-#include <linux/device.h>
-#include <linux/err.h>
 
 #include <linux/mtd/mtd.h>
 #include <linux/mtd/map.h>
 #include <linux/mtd/partitions.h>
 #include <linux/mtd/concat.h>
 
+#include <asm/hardware.h>
 #include <asm/mach-types.h>
 #include <asm/io.h>
 #include <asm/sizes.h>
-#include <asm/mach/flash.h>
 
-#if 0
+#include <asm/arch/h3600.h>
+
+#ifndef CONFIG_ARCH_SA1100
+#error This is for SA1100 architecture only
+#endif
+
+/*
+ * This isnt complete yet, so...
+ */
+#define CONFIG_MTD_SA1100_STATICMAP 1
+
+#ifdef CONFIG_MTD_SA1100_STATICMAP
 /*
- * This is here for documentation purposes only - until these people
- * submit their machine types.  It will be gone January 2005.
+ * Here are partition information for all known SA1100-based devices.
+ * See include/linux/mtd/partitions.h for definition of the mtd_partition
+ * structure.
+ *
+ * Please note:
+ *  1. We no longer support static flash mappings via the machine io_desc
+ *     structure.
+ *  2. The flash size given should be the largest flash size that can
+ *     be accommodated.
+ *
+ * The MTD layer will detect flash chip aliasing and reduce the size of
+ * the map accordingly.
+ *
+ * Please keep these in alphabetical order, and formatted as per existing
+ * entries.  Thanks.
  */
+
+#ifdef CONFIG_SA1100_ADSBITSY
+static struct mtd_partition adsbitsy_partitions[] = {
+       {
+               .name           = "bootROM",
+               .size           = 0x80000,
+               .offset         = 0,
+               .mask_flags     = MTD_WRITEABLE,  /* force read-only */
+       }, {
+               .name           = "zImage",
+               .size           = 0x100000,
+               .offset         = MTDPART_OFS_APPEND,
+               .mask_flags     = MTD_WRITEABLE,  /* force read-only */
+       }, {
+               .name           = "ramdisk.gz",
+               .size           = 0x300000,
+               .offset         = MTDPART_OFS_APPEND,
+               .mask_flags     = MTD_WRITEABLE,  /* force read-only */
+       }, {
+               .name           = "User FS",
+               .size           = MTDPART_SIZ_FULL,
+               .offset         = MTDPART_OFS_APPEND,
+       }
+};
+#endif
+
+#ifdef CONFIG_SA1100_ASSABET
+/* Phase 4 Assabet has two 28F160B3 flash parts in bank 0: */
+static struct mtd_partition assabet4_partitions[] = {
+       {
+               .name           = "bootloader",
+               .size           = 0x00020000,
+               .offset         = 0,
+               .mask_flags     = MTD_WRITEABLE,
+       }, {
+               .name           = "bootloader params",
+               .size           = 0x00020000,
+               .offset         = MTDPART_OFS_APPEND,
+               .mask_flags     = MTD_WRITEABLE,
+       }, {
+               .name           = "jffs",
+               .size           = MTDPART_SIZ_FULL,
+               .offset         = MTDPART_OFS_APPEND,
+       }
+};
+
+/* Phase 5 Assabet has two 28F128J3A flash parts in bank 0: */
+static struct mtd_partition assabet5_partitions[] = {
+       {
+               .name           = "bootloader",
+               .size           = 0x00040000,
+               .offset         = 0,
+               .mask_flags     = MTD_WRITEABLE,
+       }, {
+               .name           = "bootloader params",
+               .size           = 0x00040000,
+               .offset         = MTDPART_OFS_APPEND,
+               .mask_flags     = MTD_WRITEABLE,
+       }, {
+               .name           = "jffs",
+               .size           = MTDPART_SIZ_FULL,
+               .offset         = MTDPART_OFS_APPEND,
+       }
+};
+
+#define assabet_partitions     assabet5_partitions
+#endif
+
+#ifdef CONFIG_SA1100_BADGE4
+/*
+ * 1 x Intel 28F320C3 Advanced+ Boot Block Flash (32 Mi bit)
+ *   Eight 4 KiW Parameter Bottom Blocks (64 KiB)
+ *   Sixty-three 32 KiW Main Blocks (4032 Ki b)
+ *
+ * <or>
+ *
+ * 1 x Intel 28F640C3 Advanced+ Boot Block Flash (64 Mi bit)
+ *   Eight 4 KiW Parameter Bottom Blocks (64 KiB)
+ *   One-hundred-twenty-seven 32 KiW Main Blocks (8128 Ki b)
+ */
+static struct mtd_partition badge4_partitions[] = {
+       {
+               .name           = "BLOB boot loader",
+               .offset         = 0,
+               .size           = 0x0000A000
+       }, {
+               .name           = "params",
+               .offset         = MTDPART_OFS_APPEND,
+               .size           = 0x00006000
+       }, {
+               .name           = "root",
+               .offset         = MTDPART_OFS_APPEND,
+               .size           = MTDPART_SIZ_FULL
+       }
+};
+#endif
+
+
+#ifdef CONFIG_SA1100_CERF
+#ifdef CONFIG_SA1100_CERF_FLASH_32MB
+#  define CERF_FLASH_SIZE      0x02000000
+#elif defined CONFIG_SA1100_CERF_FLASH_16MB
+#  define CERF_FLASH_SIZE      0x01000000
+#elif defined CONFIG_SA1100_CERF_FLASH_8MB
+#  define CERF_FLASH_SIZE      0x00800000
+#else
+#  error "Undefined flash size for CERF in sa1100-flash.c"
+#endif
+
+static struct mtd_partition cerf_partitions[] = {
+       {
+               .name           = "Bootloader",
+               .size           = 0x00020000,
+               .offset         = 0x00000000,
+       }, {
+               .name           = "Params",
+               .size           = 0x00040000,
+               .offset         = 0x00020000,
+       }, {
+               .name           = "Kernel",
+               .size           = 0x00100000,
+               .offset         = 0x00060000,
+       }, {
+               .name           = "Filesystem",
+               .size           = CERF_FLASH_SIZE-0x00160000,
+               .offset         = 0x00160000,
+       }
+};
+#endif
+
+#ifdef CONFIG_SA1100_CONSUS
 static struct mtd_partition consus_partitions[] = {
        {
-               .name           = "Consus boot firmware",
-               .offset         = 0,
+               .name           = "Consus boot firmware",
+               .offset         = 0,
+               .size           = 0x00040000,
+               .mask_flags     = MTD_WRITABLE, /* force read-only */
+       }, {
+               .name           = "Consus kernel",
+               .offset         = 0x00040000,
+               .size           = 0x00100000,
+               .mask_flags     = 0,
+       }, {
+               .name           = "Consus disk",
+               .offset         = 0x00140000,
+               /* The rest (up to 16M) for jffs.  We could put 0 and
+                  make it find the size automatically, but right now
+                  i have 32 megs.  jffs will use all 32 megs if given
+                  the chance, and this leads to horrible problems
+                  when you try to re-flash the image because blob
+                  won't erase the whole partition. */
+               .size           = 0x01000000 - 0x00140000,
+               .mask_flags     = 0,
+       }, {
+               /* this disk is a secondary disk, which can be used as
+                  needed, for simplicity, make it the size of the other
+                  consus partition, although realistically it could be
+                  the remainder of the disk (depending on the file
+                  system used) */
+                .name          = "Consus disk2",
+                .offset        = 0x01000000,
+                .size          = 0x01000000 - 0x00140000,
+                .mask_flags    = 0,
+       }
+};
+#endif
+
+#ifdef CONFIG_SA1100_FLEXANET
+/* Flexanet has two 28F128J3A flash parts in bank 0: */
+#define FLEXANET_FLASH_SIZE            0x02000000
+static struct mtd_partition flexanet_partitions[] = {
+       {
+               .name           = "bootloader",
+               .size           = 0x00040000,
+               .offset         = 0,
+               .mask_flags     = MTD_WRITEABLE,
+       }, {
+               .name           = "bootloader params",
+               .size           = 0x00040000,
+               .offset         = MTDPART_OFS_APPEND,
+               .mask_flags     = MTD_WRITEABLE,
+       }, {
+               .name           = "kernel",
+               .size           = 0x000C0000,
+               .offset         = MTDPART_OFS_APPEND,
+               .mask_flags     = MTD_WRITEABLE,
+       }, {
+               .name           = "altkernel",
+               .size           = 0x000C0000,
+               .offset         = MTDPART_OFS_APPEND,
+               .mask_flags     = MTD_WRITEABLE,
+       }, {
+               .name           = "root",
+               .size           = 0x00400000,
+               .offset         = MTDPART_OFS_APPEND,
+               .mask_flags     = MTD_WRITEABLE,
+       }, {
+               .name           = "free1",
+               .size           = 0x00300000,
+               .offset         = MTDPART_OFS_APPEND,
+               .mask_flags     = MTD_WRITEABLE,
+       }, {
+               .name           = "free2",
+               .size           = 0x00300000,
+               .offset         = MTDPART_OFS_APPEND,
+               .mask_flags     = MTD_WRITEABLE,
+       }, {
+               .name           = "free3",
+               .size           = MTDPART_SIZ_FULL,
+               .offset         = MTDPART_OFS_APPEND,
+               .mask_flags     = MTD_WRITEABLE,
+       }
+};
+#endif
+
+#ifdef CONFIG_SA1100_FREEBIRD
+static struct mtd_partition freebird_partitions[] = {
+#ifdef CONFIG_SA1100_FREEBIRD_NEW
+       {
+               .name           = "firmware",
+               .size           = 0x00040000,
+               .offset         = 0,
+               .mask_flags     = MTD_WRITEABLE,  /* force read-only */
+       }, {
+               .name           = "kernel",
+               .size           = 0x00080000,
+               .offset         = 0x00040000,
+       }, {
+               .name           = "params",
+               .size           = 0x00040000,
+               .offset         = 0x000C0000,
+       }, {
+               .name           = "initrd",
+               .size           = 0x00100000,
+               .offset         = 0x00100000,
+       }, {
+               .name           = "root cramfs",
+               .size           = 0x00300000,
+               .offset         = 0x00200000,
+       }, {
+               .name           = "usr cramfs",
+               .size           = 0x00C00000,
+               .offset         = 0x00500000,
+       }, {
+               .name           = "local",
+               .size           = MTDPART_SIZ_FULL,
+               .offset         = 0x01100000,
+       }
+#else
+       {
+               .size           = 0x00040000,
+               .offset         = 0,
+       }, {
+               .size           = 0x000c0000,
+               .offset         = MTDPART_OFS_APPEND,
+       }, {
+               .size           = 0x00400000,
+               .offset         = MTDPART_OFS_APPEND,
+       }, {
+               .size           = MTDPART_SIZ_FULL,
+               .offset         = MTDPART_OFS_APPEND,
+       }
+#endif
+};
+#endif
+
+#ifdef CONFIG_SA1100_FRODO
+/* Frodo has 2 x 16M 28F128J3A flash chips in bank 0: */
+static struct mtd_partition frodo_partitions[] =
+{
+       {
+               .name           = "bootloader",
+               .size           = 0x00040000,
+               .offset         = 0x00000000,
+               .mask_flags     = MTD_WRITEABLE
+       }, {
+               .name           = "bootloader params",
+               .size           = 0x00040000,
+               .offset         = MTDPART_OFS_APPEND,
+               .mask_flags     = MTD_WRITEABLE
+       }, {
+               .name           = "kernel",
+               .size           = 0x00100000,
+               .offset         = MTDPART_OFS_APPEND,
+               .mask_flags     = MTD_WRITEABLE
+       }, {
+               .name           = "ramdisk",
+               .size           = 0x00400000,
+               .offset         = MTDPART_OFS_APPEND,
+               .mask_flags     = MTD_WRITEABLE
+       }, {
+               .name           = "file system",
+               .size           = MTDPART_SIZ_FULL,
+               .offset         = MTDPART_OFS_APPEND
+       }
+};
+#endif
+
+#ifdef CONFIG_SA1100_GRAPHICSCLIENT
+static struct mtd_partition graphicsclient_partitions[] = {
+       {
+               .name           = "zImage",
+               .size           = 0x100000,
+               .offset         = 0,
+               .mask_flags     = MTD_WRITEABLE,  /* force read-only */
+       }, {
+               .name           = "ramdisk.gz",
+               .size           = 0x300000,
+               .offset         = MTDPART_OFS_APPEND,
+               .mask_flags     = MTD_WRITEABLE,  /* force read-only */
+       }, {
+               .name           = "User FS",
+               .size           = MTDPART_SIZ_FULL,
+               .offset         = MTDPART_OFS_APPEND,
+       }
+};
+#endif
+
+#ifdef CONFIG_SA1100_GRAPHICSMASTER
+static struct mtd_partition graphicsmaster_partitions[] = {
+       {
+               .name           = "zImage",
+               .size           = 0x100000,
+               .offset         = 0,
+               .mask_flags     = MTD_WRITEABLE,  /* force read-only */
+       },
+       {
+               .name           = "ramdisk.gz",
+               .size           = 0x300000,
+               .offset         = MTDPART_OFS_APPEND,
+               .mask_flags     = MTD_WRITEABLE,  /* force read-only */
+       },
+       {
+               .name           = "User FS",
+               .size           = MTDPART_SIZ_FULL,
+               .offset         = MTDPART_OFS_APPEND,
+       }
+};
+#endif
+
+#ifdef CONFIG_SA1100_H3XXX
+static struct mtd_partition h3xxx_partitions[] = {
+       {
+               .name           = "H3XXX boot firmware",
+               .size           = 0x00040000,
+               .offset         = 0,
+               .mask_flags     = MTD_WRITEABLE,  /* force read-only */
+       }, {
+#ifdef CONFIG_MTD_2PARTS_IPAQ
+               .name           = "H3XXX root jffs2",
+               .size           = MTDPART_SIZ_FULL,
+               .offset         = 0x00040000,
+#else
+               .name           = "H3XXX kernel",
+               .size           = 0x00080000,
+               .offset         = 0x00040000,
+       }, {
+               .name           = "H3XXX params",
+               .size           = 0x00040000,
+               .offset         = 0x000C0000,
+       }, {
+#ifdef CONFIG_JFFS2_FS
+               .name           = "H3XXX root jffs2",
+               .size           = MTDPART_SIZ_FULL,
+               .offset         = 0x00100000,
+#else
+               .name           = "H3XXX initrd",
+               .size           = 0x00100000,
+               .offset         = 0x00100000,
+       }, {
+               .name           = "H3XXX root cramfs",
+               .size           = 0x00300000,
+               .offset         = 0x00200000,
+       }, {
+               .name           = "H3XXX usr cramfs",
+               .size           = 0x00800000,
+               .offset         = 0x00500000,
+       }, {
+               .name           = "H3XXX usr local",
+               .size           = MTDPART_SIZ_FULL,
+               .offset         = 0x00d00000,
+#endif
+#endif
+       }
+};
+
+static void h3xxx_set_vpp(struct map_info *map, int vpp)
+{
+       assign_h3600_egpio(IPAQ_EGPIO_VPP_ON, vpp);
+}
+#else
+#define h3xxx_set_vpp NULL
+#endif
+
+#ifdef CONFIG_SA1100_HACKKIT
+static struct mtd_partition hackkit_partitions[] = {
+       {
+               .name           = "BLOB",
+               .size           = 0x00040000,
+               .offset         = 0x00000000,
+               .mask_flags     = MTD_WRITEABLE,  /* force read-only */
+       }, {
+               .name           = "config",
+               .size           = 0x00040000,
+               .offset         = MTDPART_OFS_APPEND,
+       }, {
+               .name           = "kernel",
+               .size           = 0x00100000,
+               .offset         = MTDPART_OFS_APPEND,
+       }, {
+               .name           = "initrd",
+               .size           = 0x00180000,
+               .offset         = MTDPART_OFS_APPEND,
+       }, {
+               .name           = "rootfs",
+               .size           = 0x700000,
+               .offset         = MTDPART_OFS_APPEND,
+       }, {
+               .name           = "data",
+               .size           = MTDPART_SIZ_FULL,
+               .offset         = MTDPART_OFS_APPEND,
+       }
+};
+#endif
+
+#ifdef CONFIG_SA1100_HUW_WEBPANEL
+static struct mtd_partition huw_webpanel_partitions[] = {
+       {
+               .name           = "Loader",
+               .size           = 0x00040000,
+               .offset         = 0,
+       }, {
+               .name           = "Sector 1",
+               .size           = 0x00040000,
+               .offset         = MTDPART_OFS_APPEND,
+       }, {
+               .size           = MTDPART_SIZ_FULL,
+               .offset         = MTDPART_OFS_APPEND,
+       }
+};
+#endif
+
+#ifdef CONFIG_SA1100_JORNADA720
+static struct mtd_partition jornada720_partitions[] = {
+       {
+               .name           = "JORNADA720 boot firmware",
+               .size           = 0x00040000,
+               .offset         = 0,
+               .mask_flags     = MTD_WRITEABLE,  /* force read-only */
+       }, {
+               .name           = "JORNADA720 kernel",
+               .size           = 0x000c0000,
+               .offset         = 0x00040000,
+       }, {
+               .name           = "JORNADA720 params",
+               .size           = 0x00040000,
+               .offset         = 0x00100000,
+       }, {
+               .name           = "JORNADA720 initrd",
+               .size           = 0x00100000,
+               .offset         = 0x00140000,
+       }, {
+               .name           = "JORNADA720 root cramfs",
+               .size           = 0x00300000,
+               .offset         = 0x00240000,
+       }, {
+               .name           = "JORNADA720 usr cramfs",
+               .size           = 0x00800000,
+               .offset         = 0x00540000,
+       }, {
+               .name           = "JORNADA720 usr local",
+               .size           = 0,  /* will expand to the end of the flash */
+               .offset         = 0x00d00000,
+       }
+};
+
+static void jornada720_set_vpp(struct map_info *map, int vpp)
+{
+       if (vpp)
+               PPSR |= 0x80;
+       else
+               PPSR &= ~0x80;
+       PPDR |= 0x80;
+}
+#else
+#define jornada720_set_vpp NULL
+#endif
+
+#ifdef CONFIG_SA1100_PANGOLIN
+static struct mtd_partition pangolin_partitions[] = {
+       {
+               .name           = "boot firmware",
+               .size           = 0x00080000,
+               .offset         = 0x00000000,
+               .mask_flags     = MTD_WRITEABLE,  /* force read-only */
+       }, {
+               .name           = "kernel",
+               .size           = 0x00100000,
+               .offset         = 0x00080000,
+       }, {
+               .name           = "initrd",
+               .size           = 0x00280000,
+               .offset         = 0x00180000,
+       }, {
+               .name           = "initrd-test",
+               .size           = 0x03C00000,
+               .offset         = 0x00400000,
+       }
+};
+#endif
+
+#ifdef CONFIG_SA1100_PT_SYSTEM3
+/* erase size is 0x40000 == 256k partitions have to have this boundary */
+static struct mtd_partition system3_partitions[] = {
+       {
+               .name           = "BLOB",
+               .size           = 0x00040000,
+               .offset         = 0x00000000,
+               .mask_flags     = MTD_WRITEABLE,  /* force read-only */
+       }, {
+               .name           = "config",
+               .size           = 0x00040000,
+               .offset         = MTDPART_OFS_APPEND,
+       }, {
+               .name           = "kernel",
+               .size           = 0x00100000,
+               .offset         = MTDPART_OFS_APPEND,
+       }, {
+               .name           = "root",
+               .size           = MTDPART_SIZ_FULL,
+               .offset         = MTDPART_OFS_APPEND,
+       }
+};
+#endif
+
+#ifdef CONFIG_SA1100_SHANNON
+static struct mtd_partition shannon_partitions[] = {
+       {
+               .name           = "BLOB boot loader",
+               .offset         = 0,
+               .size           = 0x20000
+       },
+       {
+               .name           = "kernel",
+               .offset         = MTDPART_OFS_APPEND,
+               .size           = 0xe0000
+       },
+       { 
+               .name           = "initrd",
+               .offset         = MTDPART_OFS_APPEND,   
+               .size           = MTDPART_SIZ_FULL
+       }
+};
+
+#endif
+
+#ifdef CONFIG_SA1100_SHERMAN
+static struct mtd_partition sherman_partitions[] = {
+       {
+               .size           = 0x50000,
+               .offset         = 0,
+       }, {
+               .size           = 0x70000,
+               .offset         = MTDPART_OFS_APPEND,
+       }, {
+               .size           = 0x600000,
+               .offset         = MTDPART_OFS_APPEND,
+       }, {
+               .size           = 0xA0000,
+               .offset         = MTDPART_OFS_APPEND,
+       }
+};
+#endif
+
+#ifdef CONFIG_SA1100_SIMPAD
+static struct mtd_partition simpad_partitions[] = {
+       {
+               .name           = "SIMpad boot firmware",
+               .size           = 0x00080000,
+               .offset         = 0,
+               .mask_flags     = MTD_WRITEABLE,  /* force read-only */
+       }, {
+               .name           = "SIMpad kernel",
+               .size           = 0x00100000,
+               .offset         = MTDPART_OFS_APPEND,
+       }, {
+#ifdef CONFIG_ROOT_CRAMFS
+               .name           = "SIMpad root cramfs",
+               .size           =0x00D80000,
+               .offset         = MTDPART_OFS_APPEND
+
+       }, {
+               .name           = "SIMpad local jffs2",
+               .size           = MTDPART_SIZ_FULL,
+               .offset         = MTDPART_OFS_APPEND
+#else
+               .name           = "SIMpad root jffs2",
+               .size           = MTDPART_SIZ_FULL,
+               .offset         = MTDPART_OFS_APPEND
+#endif
+       }
+};
+#endif /* CONFIG_SA1100_SIMPAD */
+
+#ifdef CONFIG_SA1100_STORK
+static struct mtd_partition stork_partitions[] = {
+       {
+               .name           = "STORK boot firmware",
                .size           = 0x00040000,
-               .mask_flags     = MTD_WRITABLE, /* force read-only */
+               .offset         = 0,
+               .mask_flags     = MTD_WRITEABLE,  /* force read-only */
        }, {
-               .name           = "Consus kernel",
+               .name           = "STORK params",
+               .size           = 0x00040000,
                .offset         = 0x00040000,
+       }, {
+               .name           = "STORK kernel",
                .size           = 0x00100000,
-               .mask_flags     = 0,
+               .offset         = 0x00080000,
        }, {
-               .name           = "Consus disk",
-               .offset         = 0x00140000,
-               /* The rest (up to 16M) for jffs.  We could put 0 and
-                  make it find the size automatically, but right now
-                  i have 32 megs.  jffs will use all 32 megs if given
-                  the chance, and this leads to horrible problems
-                  when you try to re-flash the image because blob
-                  won't erase the whole partition. */
-               .size           = 0x01000000 - 0x00140000,
-               .mask_flags     = 0,
+#ifdef CONFIG_JFFS2_FS
+               .name           = "STORK root jffs2",
+               .offset         = 0x00180000,
+               .size           = MTDPART_SIZ_FULL,
+#else
+               .name           = "STORK initrd",
+               .size           = 0x00100000,
+               .offset         = 0x00180000,
        }, {
-               /* this disk is a secondary disk, which can be used as
-                  needed, for simplicity, make it the size of the other
-                  consus partition, although realistically it could be
-                  the remainder of the disk (depending on the file
-                  system used) */
-                .name          = "Consus disk2",
-                .offset        = 0x01000000,
-                .size          = 0x01000000 - 0x00140000,
-                .mask_flags    = 0,
+               .name           = "STORK root cramfs",
+               .size           = 0x00300000,
+               .offset         = 0x00280000,
+       }, {
+               .name           = "STORK usr cramfs",
+               .size           = 0x00800000,
+               .offset         = 0x00580000,
+       }, {
+               .name           = "STORK usr local",
+               .offset         = 0x00d80000,
+               .size           = MTDPART_SIZ_FULL,
+#endif
        }
 };
+#endif
 
-/* Frodo has 2 x 16M 28F128J3A flash chips in bank 0: */
-static struct mtd_partition frodo_partitions[] =
-{
+#ifdef CONFIG_SA1100_TRIZEPS
+static struct mtd_partition trizeps_partitions[] = {
        {
-               .name           = "bootloader",
-               .size           = 0x00040000,
-               .offset         = 0x00000000,
-               .mask_flags     = MTD_WRITEABLE
-       }, {
-               .name           = "bootloader params",
-               .size           = 0x00040000,
-               .offset         = MTDPART_OFS_APPEND,
-               .mask_flags     = MTD_WRITEABLE
-       }, {
-               .name           = "kernel",
+               .name           = "Bootloader",
                .size           = 0x00100000,
-               .offset         = MTDPART_OFS_APPEND,
-               .mask_flags     = MTD_WRITEABLE
+               .offset         = 0,
        }, {
-               .name           = "ramdisk",
-               .size           = 0x00400000,
+               .name           = "Kernel",
+               .size           = 0x00100000,
                .offset         = MTDPART_OFS_APPEND,
-               .mask_flags     = MTD_WRITEABLE
        }, {
-               .name           = "file system",
+               .name           = "root",
                .size           = MTDPART_SIZ_FULL,
-               .offset         = MTDPART_OFS_APPEND
+               .offset         = MTDPART_OFS_APPEND,
        }
 };
+#endif
 
-static struct mtd_partition jornada56x_partitions[] = {
+#ifdef CONFIG_SA1100_YOPY
+static struct mtd_partition yopy_partitions[] = {
        {
-               .name           = "bootldr",
+               .name           = "boot firmware",
                .size           = 0x00040000,
-               .offset         = 0,
-               .mask_flags     = MTD_WRITEABLE,
+               .offset         = 0x00000000,
+               .mask_flags     = MTD_WRITEABLE,  /* force read-only */
        }, {
-               .name           = "rootfs",
-               .size           = MTDPART_SIZ_FULL,
-               .offset         = MTDPART_OFS_APPEND,
+               .name           = "kernel",
+               .size           = 0x00080000,
+               .offset         = 0x00080000,
+       }, {
+               .name           = "initrd",
+               .size           = 0x00300000,
+               .offset         = 0x00100000,
+       }, {
+               .name           = "root",
+               .size           = 0x01000000,
+               .offset         = 0x00400000,
        }
 };
+#endif
 
-static void jornada56x_set_vpp(int vpp)
+static int __init sa1100_static_partitions(struct mtd_partition **parts)
 {
-       if (vpp)
-               GPSR = GPIO_GPIO26;
-       else
-               GPCR = GPIO_GPIO26;
-       GPDR |= GPIO_GPIO26;
-}
+       int nb_parts = 0;
 
-/*
- * Machine        Phys          Size    set_vpp
- * Consus    : SA1100_CS0_PHYS SZ_32M
- * Frodo     : SA1100_CS0_PHYS SZ_32M
- * Jornada56x: SA1100_CS0_PHYS SZ_32M jornada56x_set_vpp
- */
+#ifdef CONFIG_SA1100_ADSBITSY
+       if (machine_is_adsbitsy()) {
+               *parts       = adsbitsy_partitions;
+               nb_parts     = ARRAY_SIZE(adsbitsy_partitions);
+       }
+#endif
+#ifdef CONFIG_SA1100_ASSABET
+       if (machine_is_assabet()) {
+               *parts       = assabet_partitions;
+               nb_parts     = ARRAY_SIZE(assabet_partitions);
+       }
+#endif
+#ifdef CONFIG_SA1100_BADGE4
+       if (machine_is_badge4()) {
+               *parts       = badge4_partitions;
+               nb_parts     = ARRAY_SIZE(badge4_partitions);
+       }
+#endif
+#ifdef CONFIG_SA1100_CERF
+       if (machine_is_cerf()) {
+               *parts       = cerf_partitions;
+               nb_parts     = ARRAY_SIZE(cerf_partitions);
+       }
+#endif
+#ifdef CONFIG_SA1100_CONSUS
+       if (machine_is_consus()) {
+               *parts       = consus_partitions;
+               nb_parts     = ARRAY_SIZE(consus_partitions);
+       }
+#endif
+#ifdef CONFIG_SA1100_FLEXANET
+       if (machine_is_flexanet()) {
+               *parts       = flexanet_partitions;
+               nb_parts     = ARRAY_SIZE(flexanet_partitions);
+       }
+#endif
+#ifdef CONFIG_SA1100_FREEBIRD
+       if (machine_is_freebird()) {
+               *parts       = freebird_partitions;
+               nb_parts     = ARRAY_SIZE(freebird_partitions);
+       }
+#endif
+#ifdef CONFIG_SA1100_FRODO
+       if (machine_is_frodo()) {
+               *parts       = frodo_partitions;
+               nb_parts     = ARRAY_SIZE(frodo_partitions);
+       }
+#endif 
+#ifdef CONFIG_SA1100_GRAPHICSCLIENT
+       if (machine_is_graphicsclient()) {
+               *parts       = graphicsclient_partitions;
+               nb_parts     = ARRAY_SIZE(graphicsclient_partitions);
+       }
+#endif
+#ifdef CONFIG_SA1100_GRAPHICSMASTER
+       if (machine_is_graphicsmaster()) {
+               *parts       = graphicsmaster_partitions;
+               nb_parts     = ARRAY_SIZE(graphicsmaster_partitions);
+       }
+#endif
+#ifdef CONFIG_SA1100_H3XXX
+       if (machine_is_h3xxx()) {
+               *parts       = h3xxx_partitions;
+               nb_parts     = ARRAY_SIZE(h3xxx_partitions);
+       }
+#endif
+#ifdef CONFIG_SA1100_HACKKIT
+       if (machine_is_hackkit()) {
+               *parts = hackkit_partitions;
+               nb_parts = ARRAY_SIZE(hackkit_partitions);
+       }
+#endif
+#ifdef CONFIG_SA1100_HUW_WEBPANEL
+       if (machine_is_huw_webpanel()) {
+               *parts       = huw_webpanel_partitions;
+               nb_parts     = ARRAY_SIZE(huw_webpanel_partitions);
+       }
+#endif
+#ifdef CONFIG_SA1100_JORNADA720
+       if (machine_is_jornada720()) {
+               *parts       = jornada720_partitions;
+               nb_parts     = ARRAY_SIZE(jornada720_partitions);
+       }
+#endif
+#ifdef CONFIG_SA1100_PANGOLIN
+       if (machine_is_pangolin()) {
+               *parts       = pangolin_partitions;
+               nb_parts     = ARRAY_SIZE(pangolin_partitions);
+       }
+#endif
+#ifdef CONFIG_SA1100_PT_SYSTEM3
+       if (machine_is_pt_system3()) {
+               *parts       = system3_partitions;
+               nb_parts     = ARRAY_SIZE(system3_partitions);
+       }
+#endif
+#ifdef CONFIG_SA1100_SHANNON
+       if (machine_is_shannon()) {
+               *parts       = shannon_partitions;
+               nb_parts     = ARRAY_SIZE(shannon_partitions);
+       }
+#endif
+#ifdef CONFIG_SA1100_SHERMAN
+       if (machine_is_sherman()) {
+               *parts       = sherman_partitions;
+               nb_parts     = ARRAY_SIZE(sherman_partitions);
+       }
+#endif
+#ifdef CONFIG_SA1100_SIMPAD
+       if (machine_is_simpad()) {
+               *parts       = simpad_partitions;
+               nb_parts     = ARRAY_SIZE(simpad_partitions);
+       }
+#endif
+#ifdef CONFIG_SA1100_STORK
+       if (machine_is_stork()) {
+               *parts       = stork_partitions;
+               nb_parts     = ARRAY_SIZE(stork_partitions);
+       }
+#endif
+#ifdef CONFIG_SA1100_TRIZEPS
+       if (machine_is_trizeps()) {
+               *parts       = trizeps_partitions;
+               nb_parts     = ARRAY_SIZE(trizeps_partitions);
+       }
+#endif
+#ifdef CONFIG_SA1100_YOPY
+       if (machine_is_yopy()) {
+               *parts       = yopy_partitions;
+               nb_parts     = ARRAY_SIZE(yopy_partitions);
+       }
 #endif
 
-struct sa_subdev_info {
-       char name[16];
-       struct map_info map;
-       struct mtd_info *mtd;
-       struct flash_platform_data *data;
-};
+       return nb_parts;
+}
+#endif
 
 struct sa_info {
-       struct mtd_partition    *parts;
-       struct mtd_info         *mtd;
-       int                     num_subdev;
-       struct sa_subdev_info   subdev[0];
+       unsigned long base;
+       unsigned long size;
+       int width;
+       void __iomem *vbase;
+        void (*set_vpp)(struct map_info *, int);
+       struct map_info *map;
+       struct mtd_info *mtd;
+       struct resource *res;
 };
 
-static void sa1100_set_vpp(struct map_info *map, int on)
-{
-       struct sa_subdev_info *subdev = container_of(map, struct sa_subdev_info, map);
-       subdev->data->set_vpp(on);
-}
+#define NR_SUBMTD 4
 
-static void sa1100_destroy_subdev(struct sa_subdev_info *subdev)
-{
-       if (subdev->mtd)
-               map_destroy(subdev->mtd);
-       if (subdev->map.virt)
-               iounmap(subdev->map.virt);
-       release_mem_region(subdev->map.phys, subdev->map.size);
-}
+static struct sa_info info[NR_SUBMTD];
 
-static int sa1100_probe_subdev(struct sa_subdev_info *subdev, struct resource *res)
+static int __init sa1100_setup_mtd(struct sa_info *sa, int nr, struct mtd_info **rmtd)
 {
-       unsigned long phys;
-       unsigned int size;
-       int ret;
+       struct mtd_info *subdev[nr];
+       struct map_info *maps;
+       int i, found = 0, ret = 0;
+
+       /*
+        * Allocate the map_info structs in one go.
+        */
+       maps = kmalloc(sizeof(struct map_info) * nr, GFP_KERNEL);
+       if (!maps)
+               return -ENOMEM;
 
-       phys = res->start;
-       size = res->end - phys + 1;
+       memset(maps, 0, sizeof(struct map_info) * nr);
 
        /*
-        * Retrieve the bankwidth from the MSC registers.
-        * We currently only implement CS0 and CS1 here.
+        * Claim and then map the memory regions.
         */
-       switch (phys) {
-       default:
-               printk(KERN_WARNING "SA1100 flash: unknown base address "
-                      "0x%08lx, assuming CS0\n", phys);
+       for (i = 0; i < nr; i++) {
+               if (sa[i].base == (unsigned long)-1)
+                       break;
 
-       case SA1100_CS0_PHYS:
-               subdev->map.bankwidth = (MSC0 & MSC_RBW) ? 2 : 4;
-               break;
+               sa[i].res = request_mem_region(sa[i].base, sa[i].size, "sa1100 flash");
+               if (!sa[i].res) {
+                       ret = -EBUSY;
+                       break;
+               }
 
-       case SA1100_CS1_PHYS:
-               subdev->map.bankwidth = ((MSC0 >> 16) & MSC_RBW) ? 2 : 4;
-               break;
-       }
+               sa[i].map = maps + i;
 
-       if (!request_mem_region(phys, size, subdev->name)) {
-               ret = -EBUSY;
-               goto out;
-       }
+               sa[i].vbase = ioremap(sa[i].base, sa[i].size);
+               if (!sa[i].vbase) {
+                       ret = -ENOMEM;
+                       break;
+               }
+
+               sa[i].map->virt = sa[i].vbase;
+               sa[i].map->phys = sa[i].base;
+               sa[i].map->set_vpp = sa[i].set_vpp;
+               sa[i].map->bankwidth = sa[i].width;
+               sa[i].map->size = sa[i].size;
+
+               simple_map_init(sa[i].map);
 
-       if (subdev->data->set_vpp)
-               subdev->map.set_vpp = sa1100_set_vpp;
+               /*
+                * Now let's probe for the actual flash.  Do it here since
+                * specific machine settings might have been set above.
+                */
+               sa[i].mtd = do_map_probe("cfi_probe", sa[i].map);
+               if (sa[i].mtd == NULL) {
+                       ret = -ENXIO;
+                       break;
+               }
+               sa[i].mtd->owner = THIS_MODULE;
+               subdev[i] = sa[i].mtd;
 
-       subdev->map.phys = phys;
-       subdev->map.size = size;
-       subdev->map.virt = ioremap(phys, size);
-       if (!subdev->map.virt) {
-               ret = -ENOMEM;
-               goto err;
+               printk(KERN_INFO "SA1100 flash: CFI device at 0x%08lx, %dMiB, "
+                       "%d-bit\n", sa[i].base, sa[i].mtd->size >> 20,
+                       sa[i].width * 8);
+               found += 1;
        }
 
-       simple_map_init(&subdev->map);
+       /*
+        * ENXIO is special.  It means we didn't find a chip when
+        * we probed.  We need to tear down the mapping, free the
+        * resource and mark it as such.
+        */
+       if (ret == -ENXIO) {
+               iounmap(sa[i].vbase);
+               sa[i].vbase = NULL;
+               release_resource(sa[i].res);
+               sa[i].res = NULL;
+       }
 
        /*
-        * Now let's probe for the actual flash.  Do it here since
-        * specific machine settings might have been set above.
+        * If we found one device, don't bother with concat support.
+        * If we found multiple devices, use concat if we have it
+        * available, otherwise fail.
         */
-       subdev->mtd = do_map_probe(subdev->data->map_name, &subdev->map);
-       if (subdev->mtd == NULL) {
-               ret = -ENXIO;
-               goto err;
+       if (ret == 0 || ret == -ENXIO) {
+               if (found == 1) {
+                       *rmtd = subdev[0];
+                       ret = 0;
+               } else if (found > 1) {
+                       /*
+                        * We detected multiple devices.  Concatenate
+                        * them together.
+                        */
+#ifdef CONFIG_MTD_CONCAT
+                       *rmtd = mtd_concat_create(subdev, found,
+                                                 "sa1100 flash");
+                       if (*rmtd == NULL)
+                               ret = -ENXIO;
+#else
+                       printk(KERN_ERR "SA1100 flash: multiple devices "
+                              "found but MTD concat support disabled.\n");
+                       ret = -ENXIO;
+#endif
+               }
        }
-       subdev->mtd->owner = THIS_MODULE;
 
-       printk(KERN_INFO "SA1100 flash: CFI device at 0x%08lx, %dMiB, "
-               "%d-bit\n", phys, subdev->mtd->size >> 20,
-               subdev->map.bankwidth * 8);
+       /*
+        * If we failed, clean up.
+        */
+       if (ret) {
+               do {
+                       if (sa[i].mtd)
+                               map_destroy(sa[i].mtd);
+                       if (sa[i].vbase)
+                               iounmap(sa[i].vbase);
+                       if (sa[i].res)
+                               release_resource(sa[i].res);
+               } while (i--);
 
-       return 0;
+               kfree(maps);
+       }
 
- err:
-       sa1100_destroy_subdev(subdev);
- out:
        return ret;
 }
 
-static void sa1100_destroy(struct sa_info *info)
+static void __exit sa1100_destroy_mtd(struct sa_info *sa, struct mtd_info *mtd)
 {
        int i;
 
-       if (info->mtd) {
-               del_mtd_partitions(info->mtd);
+       del_mtd_partitions(mtd);
 
 #ifdef CONFIG_MTD_CONCAT
-               if (info->mtd != info->subdev[0].mtd)
-                       mtd_concat_destroy(info->mtd);
+       if (mtd != sa[0].mtd)
+               mtd_concat_destroy(mtd);
 #endif
+
+       for (i = NR_SUBMTD; i >= 0; i--) {
+               if (sa[i].mtd)
+                       map_destroy(sa[i].mtd);
+               if (sa[i].vbase)
+                       iounmap(sa[i].vbase);
+               if (sa[i].res)
+                       release_resource(sa[i].res);
        }
+       kfree(sa[0].map);
+}
 
-       if (info->parts)
-               kfree(info->parts);
+/*
+ * A Thought: can we automatically detect the flash?
+ *  - Check to see if the region is busy (yes -> failure)
+ *  - Is the MSC setup for flash (no -> failure)
+ *  - Probe for flash
+ */
 
-       for (i = info->num_subdev - 1; i >= 0; i--)
-               sa1100_destroy_subdev(&info->subdev[i]);
-       kfree(info);
-}
+static struct map_info sa1100_probe_map __initdata = {
+       .name           = "SA1100-flash",
+};
 
-static struct sa_info *__init
-sa1100_setup_mtd(struct platform_device *pdev, struct flash_platform_data *flash)
+static void __init sa1100_probe_one_cs(unsigned int msc, unsigned long phys)
 {
-       struct sa_info *info;
-       int nr, size, i, ret = 0;
+       struct mtd_info *mtd;
 
-       /*
-        * Count number of devices.
-        */
-       for (nr = 0; ; nr++)
-               if (!platform_get_resource(pdev, IORESOURCE_MEM, nr))
-                       break;
+       printk(KERN_INFO "* Probing 0x%08lx: MSC = 0x%04x %d bit ",
+               phys, msc & 0xffff, msc & MSC_RBW ? 16 : 32);
 
-       if (nr == 0) {
-               ret = -ENODEV;
-               goto out;
+       if (check_mem_region(phys, 0x08000000)) {
+               printk("busy\n");
+               return;
        }
 
-       size = sizeof(struct sa_info) + sizeof(struct sa_subdev_info) * nr;
-
-       /*
-        * Allocate the map_info structs in one go.
-        */
-       info = kmalloc(size, GFP_KERNEL);
-       if (!info) {
-               ret = -ENOMEM;
-               goto out;
+       if ((msc & 3) == 1) {
+               printk("wrong type\n");
+               return;
        }
 
-       memset(info, 0, size);
+       sa1100_probe_map.bankwidth = msc & MSC_RBW ? 2 : 4;
+       sa1100_probe_map.size = SZ_1M;
+       sa1100_probe_map.phys = phys;
+       sa1100_probe_map.virt = (unsigned long)ioremap(phys, SZ_1M);
+       if (sa1100_probe_map.virt == 0)
+               goto fail;
+       simple_map_init(&sa1100_probe_map);
 
-       /*
-        * Claim and then map the memory regions.
-        */
-       for (i = 0; i < nr; i++) {
-               struct sa_subdev_info *subdev = &info->subdev[i];
-               struct resource *res;
+       /* Shame cfi_probe blurts out kernel messages... */
+       mtd = do_map_probe("cfi_probe", &sa1100_probe_map);
+       if (mtd)
+               map_destroy(mtd);
+       iounmap((void *)sa1100_probe_map.virt);
 
-               res = platform_get_resource(pdev, IORESOURCE_MEM, i);
-               if (!res)
-                       break;
+       if (!mtd)
+               goto fail;
 
-               subdev->map.name = subdev->name;
-               sprintf(subdev->name, "sa1100-%d", i);
-               subdev->data = flash;
+       printk("pass\n");
+       return;
 
-               ret = sa1100_probe_subdev(subdev, res);
-               if (ret)
-                       break;
-       }
+ fail:
+       printk("failed\n");
+}
 
-       info->num_subdev = i;
+static void __init sa1100_probe_flash(void)
+{
+       printk(KERN_INFO "-- SA11xx Flash probe.  Please report results.\n");
+       sa1100_probe_one_cs(MSC0, SA1100_CS0_PHYS);
+       sa1100_probe_one_cs(MSC0 >> 16, SA1100_CS1_PHYS);
+       sa1100_probe_one_cs(MSC1, SA1100_CS2_PHYS);
+       sa1100_probe_one_cs(MSC1 >> 16, SA1100_CS3_PHYS);
+       sa1100_probe_one_cs(MSC2, SA1100_CS4_PHYS);
+       sa1100_probe_one_cs(MSC2 >> 16, SA1100_CS5_PHYS);
+       printk(KERN_INFO "-- SA11xx Flash probe complete.\n");
+}
 
-       /*
-        * ENXIO is special.  It means we didn't find a chip when we probed.
-        */
-       if (ret != 0 && !(ret == -ENXIO && info->num_subdev > 0))
-               goto err;
+static int __init sa1100_locate_flash(void)
+{
+       int i, nr = -ENODEV;
+
+       sa1100_probe_flash();
+
+       if (machine_is_adsbitsy()) {
+               info[0].base = SA1100_CS1_PHYS;
+               info[0].size = SZ_32M;
+               nr = 1;
+       }
+       if (machine_is_assabet()) {
+               info[0].base = SA1100_CS0_PHYS;
+               info[0].size = SZ_32M;
+               info[1].base = SA1100_CS1_PHYS; /* neponset */
+               info[1].size = SZ_32M;
+               nr = 2;
+       }
+       if (machine_is_badge4()) {
+               info[0].base = SA1100_CS0_PHYS;
+               info[0].size = SZ_64M;
+               nr = 1;
+       }
+       if (machine_is_cerf()) {
+               info[0].base = SA1100_CS0_PHYS;
+               info[0].size = SZ_32M;
+               nr = 1;
+       }
+       if (machine_is_consus()) {
+               info[0].base = SA1100_CS0_PHYS;
+               info[0].size = SZ_32M;
+               nr = 1;
+       }
+       if (machine_is_flexanet()) {
+               info[0].base = SA1100_CS0_PHYS;
+               info[0].size = SZ_32M;
+               nr = 1;
+       }
+       if (machine_is_freebird()) {
+               info[0].base = SA1100_CS0_PHYS;
+               info[0].size = SZ_32M;
+               nr = 1;
+       }
+       if (machine_is_frodo()) {
+               info[0].base = SA1100_CS0_PHYS;
+               info[0].size = SZ_32M;
+               nr = 1;
+       }
+       if (machine_is_graphicsclient()) {
+               info[0].base = SA1100_CS1_PHYS;
+               info[0].size = SZ_32M;
+               nr = 1;
+       }
+       if (machine_is_graphicsmaster()) {
+               info[0].base = SA1100_CS1_PHYS;
+               info[0].size = SZ_16M;
+               nr = 1;
+       }
+       if (machine_is_h3xxx()) {
+               info[0].set_vpp = h3xxx_set_vpp;
+               info[0].base = SA1100_CS0_PHYS;
+               info[0].size = SZ_32M;
+               nr = 1;
+       }
+       if (machine_is_huw_webpanel()) {
+               info[0].base = SA1100_CS0_PHYS;
+               info[0].size = SZ_16M;
+               nr = 1;
+       }
+       if (machine_is_itsy()) {
+               info[0].base = SA1100_CS0_PHYS;
+               info[0].size = SZ_32M;
+               nr = 1;
+       }
+       if (machine_is_jornada720()) {
+               info[0].set_vpp = jornada720_set_vpp;
+               info[0].base = SA1100_CS0_PHYS;
+               info[0].size = SZ_32M;
+               nr = 1;
+       }
+       if (machine_is_nanoengine()) {
+               info[0].base = SA1100_CS0_PHYS;
+               info[1].size = SZ_32M;
+               nr = 1;
+       }
+       if (machine_is_pangolin()) {
+               info[0].base = SA1100_CS0_PHYS;
+               info[0].size = SZ_64M;
+               nr = 1;
+       }
+       if (machine_is_pfs168()) {
+               info[0].base = SA1100_CS0_PHYS;
+               info[0].size = SZ_32M;
+               nr = 1;
+       }
+       if (machine_is_pleb()) {
+               info[0].base = SA1100_CS0_PHYS;
+               info[0].size = SZ_4M;
+               info[1].base = SA1100_CS1_PHYS;
+               info[1].size = SZ_4M;
+               nr = 2;
+       }
+       if (machine_is_pt_system3()) {
+               info[0].base = SA1100_CS0_PHYS;
+               info[0].size = SZ_16M;
+               nr = 1;
+       }
+       if (machine_is_shannon()) {
+               info[0].base = SA1100_CS0_PHYS;
+               info[0].size = SZ_4M;
+               nr = 1;
+       }
+       if (machine_is_sherman()) {
+               info[0].base = SA1100_CS0_PHYS;
+               info[0].size = SZ_32M;
+               nr = 1;
+       }
+       if (machine_is_simpad()) {
+               info[0].base = SA1100_CS0_PHYS;
+               info[0].size = SZ_16M;
+               info[1].base = SA1100_CS1_PHYS;
+               info[1].size = SZ_16M;
+               nr = 2;
+       }
+       if (machine_is_stork()) {
+               info[0].base = SA1100_CS0_PHYS;
+               info[0].size = SZ_32M;
+               nr = 1;
+       }
+       if (machine_is_trizeps()) {
+               info[0].base = SA1100_CS0_PHYS;
+               info[0].size = SZ_16M;
+               nr = 1;
+       }
+       if (machine_is_victor()) {
+               info[0].base = SA1100_CS0_PHYS;
+               info[0].size = SZ_2M;
+               nr = 1;
+       }
+       if (machine_is_yopy()) {
+               info[0].base = SA1100_CS0_PHYS;
+               info[0].size = SZ_64M;
+               info[1].base = SA1100_CS1_PHYS;
+               info[1].size = SZ_64M;
+               nr = 2;
+       }
+
+       if (nr < 0)
+               return nr;
 
        /*
-        * If we found one device, don't bother with concat support.  If
-        * we found multiple devices, use concat if we have it available,
-        * otherwise fail.  Either way, it'll be called "sa1100".
+        * Retrieve the bankwidth from the MSC registers.
+        * We currently only implement CS0 and CS1 here.
         */
-       if (info->num_subdev == 1) {
-               strcpy(info->subdev[0].name, "sa1100");
-               info->mtd = info->subdev[0].mtd;
-               ret = 0;
-       } else if (info->num_subdev > 1) {
-#ifdef CONFIG_MTD_CONCAT
-               struct mtd_info *cdev[nr];
-               /*
-                * We detected multiple devices.  Concatenate them together.
-                */
-               for (i = 0; i < info->num_subdev; i++)
-                       cdev[i] = info->subdev[i].mtd;
+       for (i = 0; i < nr; i++) {
+               switch (info[i].base) {
+               default:
+                       printk(KERN_WARNING "SA1100 flash: unknown base address "
+                               "0x%08lx, assuming CS0\n", info[i].base);
+               case SA1100_CS0_PHYS:
+                       info[i].width = (MSC0 & MSC_RBW) ? 2 : 4;
+                       break;
 
-               info->mtd = mtd_concat_create(cdev, info->num_subdev,
-                                             "sa1100");
-               if (info->mtd == NULL)
-                       ret = -ENXIO;
-#else
-               printk(KERN_ERR "SA1100 flash: multiple devices "
-                      "found but MTD concat support disabled.\n");
-               ret = -ENXIO;
-#endif
+               case SA1100_CS1_PHYS:
+                       info[i].width = ((MSC0 >> 16) & MSC_RBW) ? 2 : 4;
+                       break;
+               }
        }
 
-       if (ret == 0)
-               return info;
-
- err:
-       sa1100_destroy(info);
- out:
-       return ERR_PTR(ret);
+       return nr;
 }
 
-static const char *part_probes[] = { "cmdlinepart", "RedBoot", NULL };
+static struct mtd_partition *parsed_parts;
+const char *part_probes[] = { "cmdlinepart", "RedBoot", NULL };
 
-static int __init sa1100_mtd_probe(struct device *dev)
+static void __init sa1100_locate_partitions(struct mtd_info *mtd)
 {
-       struct platform_device *pdev = to_platform_device(dev);
-       struct flash_platform_data *flash = pdev->dev.platform_data;
-       struct mtd_partition *parts;
        const char *part_type = NULL;
-       struct sa_info *info;
-       int err, nr_parts = 0;
-
-       if (!flash)
-               return -ENODEV;
+       int nr_parts = 0;
 
-       info = sa1100_setup_mtd(pdev, flash);
-       if (IS_ERR(info)) {
-               err = PTR_ERR(info);
-               goto out;
-       }
-
-       /*
-        * Partition selection stuff.
-        */
+       do {
+               /*
+                * Partition selection stuff.
+                */
 #ifdef CONFIG_MTD_PARTITIONS
-       nr_parts = parse_mtd_partitions(info->mtd, part_probes, &parts, 0);
-       if (nr_parts > 0) {
-               info->parts = parts;
-               part_type = "dynamic";
-       } else
+               nr_parts = parse_mtd_partitions(mtd, part_probes, &parsed_parts, 0);
+               if (nr_parts > 0) {
+                       part_type = "dynamic";
+                       break;
+               }
 #endif
-       {
-               parts = flash->parts;
-               nr_parts = flash->nr_parts;
-               part_type = "static";
-       }
+#ifdef CONFIG_MTD_SA1100_STATICMAP
+               nr_parts = sa1100_static_partitions(&parsed_parts);
+               if (nr_parts > 0) {
+                       part_type = "static";
+                       break;
+               }
+#endif
+       } while (0);
 
        if (nr_parts == 0) {
                printk(KERN_NOTICE "SA1100 flash: no partition info "
                        "available, registering whole flash\n");
-               add_mtd_device(info->mtd);
+               add_mtd_device(mtd);
        } else {
                printk(KERN_NOTICE "SA1100 flash: using %s partition "
                        "definition\n", part_type);
-               add_mtd_partitions(info->mtd, parts, nr_parts);
+               add_mtd_partitions(mtd, parsed_parts, nr_parts);
        }
 
-       dev_set_drvdata(dev, info);
-       err = 0;
-
- out:
-       return err;
+       /* Always succeeds. */
 }
 
-static int __exit sa1100_mtd_remove(struct device *dev)
+static void __exit sa1100_destroy_partitions(void)
 {
-       struct sa_info *info = dev_get_drvdata(dev);
-       dev_set_drvdata(dev, NULL);
-       sa1100_destroy(info);
-       return 0;
+       if (parsed_parts)
+               kfree(parsed_parts);
 }
 
-#ifdef CONFIG_PM
-static int sa1100_mtd_suspend(struct device *dev, u32 state, u32 level)
-{
-       struct sa_info *info = dev_get_drvdata(dev);
-       int ret = 0;
-
-       if (info && level == SUSPEND_SAVE_STATE)
-               ret = info->mtd->suspend(info->mtd);
-
-       return ret;
-}
+static struct mtd_info *mymtd;
 
-static int sa1100_mtd_resume(struct device *dev, u32 level)
+static int __init sa1100_mtd_init(void)
 {
-       struct sa_info *info = dev_get_drvdata(dev);
-       if (info && level == RESUME_RESTORE_STATE)
-               info->mtd->resume(info->mtd);
-       return 0;
-}
-#else
-#define sa1100_mtd_suspend NULL
-#define sa1100_mtd_resume  NULL
-#endif
+       int ret;
+       int nr;
 
-static struct device_driver sa1100_mtd_driver = {
-       .name           = "flash",
-       .bus            = &platform_bus_type,
-       .probe          = sa1100_mtd_probe,
-       .remove         = __exit_p(sa1100_mtd_remove),
-       .suspend        = sa1100_mtd_suspend,
-       .resume         = sa1100_mtd_resume,
-};
+       nr = sa1100_locate_flash();
+       if (nr < 0)
+               return nr;
 
-static int __init sa1100_mtd_init(void)
-{
-       return driver_register(&sa1100_mtd_driver);
+       ret = sa1100_setup_mtd(info, nr, &mymtd);
+       if (ret == 0)
+               sa1100_locate_partitions(mymtd);
+
+       return ret;
 }
 
-static void __exit sa1100_mtd_exit(void)
+static void __exit sa1100_mtd_cleanup(void)
 {
-       driver_unregister(&sa1100_mtd_driver);
+       sa1100_destroy_mtd(info, mymtd);
+       sa1100_destroy_partitions();
 }
 
 module_init(sa1100_mtd_init);
-module_exit(sa1100_mtd_exit);
+module_exit(sa1100_mtd_cleanup);
 
 MODULE_AUTHOR("Nicolas Pitre");
 MODULE_DESCRIPTION("SA1100 CFI map driver");