fedora core 6 1.2949 + vserver 2.2.0
[linux-2.6.git] / drivers / mtd / chips / jedec_probe.c
index 8fb85f0..58e561e 100644 (file)
@@ -1,14 +1,13 @@
-/* 
+/*
    Common Flash Interface probe code.
    (C) 2000 Red Hat. GPL'd.
-   $Id: jedec_probe.c,v 1.51 2004/07/14 14:44:30 thayne Exp $
+   $Id: jedec_probe.c,v 1.66 2005/11/07 11:14:23 gleixner Exp $
    See JEDEC (http://www.jedec.org/) standard JESD21C (section 3.5)
    for the standard this probe goes back to.
 
    Occasionally maintained by Thayne Harbaugh tharbaugh at lnxi dot com
 */
 
-#include <linux/config.h>
 #include <linux/module.h>
 #include <linux/init.h>
 #include <linux/types.h>
@@ -32,7 +31,9 @@
 #define MANUFACTURER_HYUNDAI   0x00AD
 #define MANUFACTURER_INTEL     0x0089
 #define MANUFACTURER_MACRONIX  0x00C2
+#define MANUFACTURER_NEC       0x0010
 #define MANUFACTURER_PMC       0x009D
+#define MANUFACTURER_SHARP     0x00b0
 #define MANUFACTURER_SST       0x00BF
 #define MANUFACTURER_ST                0x0020
 #define MANUFACTURER_TOSHIBA   0x0098
 #define I82802AC       0x00ac
 
 /* Macronix */
+#define MX29LV040C     0x004F
 #define MX29LV160T     0x22C4
 #define MX29LV160B     0x2249
+#define MX29F040       0x00A4
 #define MX29F016       0x00AD
 #define MX29F002T      0x00B0
 #define MX29F004T      0x0045
 #define MX29F004B      0x0046
 
+/* NEC */
+#define UPD29F064115   0x221C
+
 /* PMC */
 #define PM49FL002      0x006D
 #define PM49FL004      0x006E
 #define PM49FL008      0x006A
 
+/* Sharp */
+#define LH28F640BF     0x00b0
+
 /* ST - www.st.com */
 #define M29W800DT      0x00D7
 #define M29W800DB      0x005B
 #define M50FW040       0x002C
 #define M50FW080       0x002D
 #define M50FW016       0x002E
+#define M50LPW080       0x002F
 
 /* SST */
 #define SST29EE020     0x0010
 #define SST29LE512     0x003d
 #define SST39LF800     0x2781
 #define SST39LF160     0x2782
+#define SST39VF1601    0x234b
 #define SST39LF512     0x00D4
 #define SST39LF010     0x00D5
 #define SST39LF020     0x00D6
 #define SST39SF010A    0x00B5
 #define SST39SF020A    0x00B6
 #define SST49LF004B    0x0060
+#define SST49LF040B    0x0050
 #define SST49LF008A    0x005a
 #define SST49LF030A    0x001C
 #define SST49LF040A    0x0051
@@ -181,8 +193,8 @@ enum uaddr {
 
 
 struct unlock_addr {
-       int addr1;
-       int addr2;
+       u32 addr1;
+       u32 addr2;
 };
 
 
@@ -225,6 +237,11 @@ static const struct unlock_addr  unlock_addrs[] = {
        [MTD_UADDR_DONT_CARE] = {
                .addr1 = 0x0000,      /* Doesn't matter which address */
                .addr2 = 0x0000       /* is used - must be last entry */
+       },
+
+       [MTD_UADDR_UNNECESSARY] = {
+               .addr1 = 0x0000,
+               .addr2 = 0x0000
        }
 };
 
@@ -512,15 +529,20 @@ static const struct amd_flash_info jedec_table[] = {
                        ERASEINFO(0x10000,8),
                }
        }, {
-               .mfr_id = MANUFACTURER_AMD,
-               .dev_id = AM29F002T,
-               .name = "AMD AM29F002T",
-               .DevSize = SIZE_256KiB,
-               .NumEraseRegions = 4,
-               .regions = {ERASEINFO(0x10000,3),
-                         ERASEINFO(0x08000,1),
-                         ERASEINFO(0x02000,2),
-                         ERASEINFO(0x04000,1)
+               .mfr_id         = MANUFACTURER_AMD,
+               .dev_id         = AM29F002T,
+               .name           = "AMD AM29F002T",
+               .uaddr          = {
+                       [0] = MTD_UADDR_0x0555_0x02AA /* x8 */
+               },
+               .DevSize        = SIZE_256KiB,
+               .CmdSet         = P_ID_AMD_STD,
+               .NumEraseRegions= 4,
+               .regions        = {
+                       ERASEINFO(0x10000,3),
+                       ERASEINFO(0x08000,1),
+                       ERASEINFO(0x02000,2),
+                       ERASEINFO(0x04000,1),
                }
        }, {
                .mfr_id         = MANUFACTURER_ATMEL,
@@ -768,15 +790,20 @@ static const struct amd_flash_info jedec_table[] = {
                        ERASEINFO(0x04000,1)
                }
        }, {
-               .mfr_id = MANUFACTURER_HYUNDAI,
-               .dev_id = HY29F002T,
-               .name = "Hyundai HY29F002T",
-               .DevSize = SIZE_256KiB,
-               .NumEraseRegions = 4,
-               .regions = {ERASEINFO(0x10000,3),
-                         ERASEINFO(0x08000,1),
-                         ERASEINFO(0x02000,2),
-                         ERASEINFO(0x04000,1)
+               .mfr_id         = MANUFACTURER_HYUNDAI,
+               .dev_id         = HY29F002T,
+               .name           = "Hyundai HY29F002T",
+               .uaddr          = {
+                       [0] = MTD_UADDR_0x0555_0x02AA /* x8 */
+               },
+               .DevSize        = SIZE_256KiB,
+               .CmdSet         = P_ID_AMD_STD,
+               .NumEraseRegions= 4,
+               .regions        = {
+                       ERASEINFO(0x10000,3),
+                       ERASEINFO(0x08000,1),
+                       ERASEINFO(0x02000,2),
+                       ERASEINFO(0x04000,1),
                }
        }, {
                .mfr_id         = MANUFACTURER_INTEL,
@@ -1082,6 +1109,19 @@ static const struct amd_flash_info jedec_table[] = {
                .regions        = {
                        ERASEINFO(0x10000,16),
                }
+       }, {
+               .mfr_id         = MANUFACTURER_MACRONIX,
+               .dev_id         = MX29LV040C,
+               .name           = "Macronix MX29LV040C",
+               .uaddr          = {
+                       [0] = MTD_UADDR_0x0555_0x02AA,  /* x8 */
+               },
+               .DevSize        = SIZE_512KiB,
+               .CmdSet         = P_ID_AMD_STD,
+               .NumEraseRegions= 1,
+               .regions        = {
+                       ERASEINFO(0x10000,8),
+               }
        }, {
                .mfr_id         = MANUFACTURER_MACRONIX,
                .dev_id         = MX29LV160T,
@@ -1099,6 +1139,22 @@ static const struct amd_flash_info jedec_table[] = {
                        ERASEINFO(0x02000,2),
                        ERASEINFO(0x04000,1)
                }
+       }, {
+               .mfr_id         = MANUFACTURER_NEC,
+               .dev_id         = UPD29F064115,
+               .name           = "NEC uPD29F064115",
+               .uaddr          = {
+                       [0] = MTD_UADDR_0x0555_0x02AA,  /* x8 */
+                       [1] = MTD_UADDR_0x0555_0x02AA,  /* x16 */
+               },
+               .DevSize        = SIZE_8MiB,
+               .CmdSet         = P_ID_AMD_STD,
+               .NumEraseRegions= 3,
+               .regions        = {
+                       ERASEINFO(0x2000,8),
+                       ERASEINFO(0x10000,126),
+                       ERASEINFO(0x2000,8),
+               }
        }, {
                .mfr_id         = MANUFACTURER_MACRONIX,
                .dev_id         = MX29LV160B,
@@ -1117,6 +1173,19 @@ static const struct amd_flash_info jedec_table[] = {
                        ERASEINFO(0x10000,31)
                }
        }, {
+               .mfr_id         = MANUFACTURER_MACRONIX,
+               .dev_id         = MX29F040,
+               .name           = "Macronix MX29F040",
+               .uaddr          = {
+                       [0] = MTD_UADDR_0x0555_0x02AA /* x8 */
+               },
+               .DevSize        = SIZE_512KiB,
+               .CmdSet         = P_ID_AMD_STD,
+               .NumEraseRegions= 1,
+               .regions        = {
+                       ERASEINFO(0x10000,8),
+               }
+        }, {
                .mfr_id         = MANUFACTURER_MACRONIX,
                .dev_id         = MX29F016,
                .name           = "Macronix MX29F016",
@@ -1162,15 +1231,20 @@ static const struct amd_flash_info jedec_table[] = {
                        ERASEINFO(0x10000,7),
                }
        }, {
-               .mfr_id = MANUFACTURER_MACRONIX,
-               .dev_id = MX29F002T,
-               .name = "Macronix MX29F002T",
-               .DevSize = SIZE_256KiB,
-               .NumEraseRegions = 4,
-               .regions = {ERASEINFO(0x10000,3),
-                         ERASEINFO(0x08000,1),
-                         ERASEINFO(0x02000,2),
-                         ERASEINFO(0x04000,1)
+               .mfr_id         = MANUFACTURER_MACRONIX,
+               .dev_id         = MX29F002T,
+               .name           = "Macronix MX29F002T",
+               .uaddr          = {
+                       [0] = MTD_UADDR_0x0555_0x02AA /* x8 */
+               },
+               .DevSize        = SIZE_256KiB,
+               .CmdSet         = P_ID_AMD_STD,
+               .NumEraseRegions= 4,
+               .regions        = {
+                       ERASEINFO(0x10000,3),
+                       ERASEINFO(0x08000,1),
+                       ERASEINFO(0x02000,2),
+                       ERASEINFO(0x04000,1),
                }
        }, {
                .mfr_id         = MANUFACTURER_PMC,
@@ -1211,6 +1285,19 @@ static const struct amd_flash_info jedec_table[] = {
                .regions        = {
                        ERASEINFO( 0x01000, 256 )
                }
+       }, {
+               .mfr_id         = MANUFACTURER_SHARP,
+               .dev_id         = LH28F640BF,
+               .name           = "LH28F640BF",
+               .uaddr          = {
+                       [0] = MTD_UADDR_UNNECESSARY,    /* x8 */
+               },
+               .DevSize        = SIZE_4MiB,
+               .CmdSet         = P_ID_INTEL_STD,
+               .NumEraseRegions= 1,
+               .regions        = {
+                       ERASEINFO(0x40000,16),
+               }
         }, {
                .mfr_id         = MANUFACTURER_SST,
                .dev_id         = SST39LF512,
@@ -1314,6 +1401,20 @@ static const struct amd_flash_info jedec_table[] = {
                        ERASEINFO(0x01000,64),
                }
        }, {
+               .mfr_id         = MANUFACTURER_SST,
+               .dev_id         = SST49LF040B,
+               .name           = "SST 49LF040B",
+               .uaddr          = {
+                       [0] = MTD_UADDR_0x5555_0x2AAA /* x8 */
+               },
+               .DevSize        = SIZE_512KiB,
+               .CmdSet         = P_ID_AMD_STD,
+               .NumEraseRegions= 1,
+               .regions        = {
+                       ERASEINFO(0x01000,128),
+               }
+       }, {
+
                .mfr_id         = MANUFACTURER_SST,
                .dev_id         = SST49LF004B,
                .name           = "SST 49LF004B",
@@ -1379,6 +1480,37 @@ static const struct amd_flash_info jedec_table[] = {
                        ERASEINFO(0x01000,256),
                }
        }, {
+               .mfr_id         = MANUFACTURER_SST,     /* should be CFI */
+               .dev_id         = SST39LF160,
+               .name           = "SST 39LF160",
+               .uaddr          = {
+                       [0] = MTD_UADDR_0x5555_0x2AAA,  /* x8 */
+                       [1] = MTD_UADDR_0x5555_0x2AAA   /* x16 */
+               },
+               .DevSize        = SIZE_2MiB,
+               .CmdSet         = P_ID_AMD_STD,
+               .NumEraseRegions= 2,
+               .regions        = {
+                       ERASEINFO(0x1000,256),
+                       ERASEINFO(0x1000,256)
+               }
+       }, {
+               .mfr_id         = MANUFACTURER_SST,     /* should be CFI */
+               .dev_id         = SST39VF1601,
+               .name           = "SST 39VF1601",
+               .uaddr          = {
+                       [0] = MTD_UADDR_0x5555_0x2AAA,  /* x8 */
+                       [1] = MTD_UADDR_0x5555_0x2AAA   /* x16 */
+               },
+               .DevSize        = SIZE_2MiB,
+               .CmdSet         = P_ID_AMD_STD,
+               .NumEraseRegions= 2,
+               .regions        = {
+                       ERASEINFO(0x1000,256),
+                       ERASEINFO(0x1000,256)
+               }
+
+       }, {
                .mfr_id         = MANUFACTURER_ST,      /* FIXME - CFI device? */
                .dev_id         = M29W800DT,
                .name           = "ST M29W800DT",
@@ -1498,6 +1630,19 @@ static const struct amd_flash_info jedec_table[] = {
                .regions        = {
                        ERASEINFO(0x10000,32),
                }
+       }, {
+               .mfr_id         = MANUFACTURER_ST,
+               .dev_id         = M50LPW080,
+               .name           = "ST M50LPW080",
+               .uaddr          = {
+                       [0] = MTD_UADDR_UNNECESSARY,    /* x8 */
+               },
+               .DevSize        = SIZE_1MiB,
+               .CmdSet         = P_ID_INTEL_EXT,
+               .NumEraseRegions= 1,
+               .regions        = {
+                       ERASEINFO(0x10000,16),
+               }
        }, {
                .mfr_id         = MANUFACTURER_TOSHIBA,
                .dev_id         = TC58FVT160,
@@ -1617,31 +1762,31 @@ static int cfi_jedec_setup(struct cfi_private *p_cfi, int index);
 static int jedec_probe_chip(struct map_info *map, __u32 base,
                            unsigned long *chip_map, struct cfi_private *cfi);
 
-struct mtd_info *jedec_probe(struct map_info *map);
+static struct mtd_info *jedec_probe(struct map_info *map);
 
-static inline u32 jedec_read_mfr(struct map_info *map, __u32 base, 
+static inline u32 jedec_read_mfr(struct map_info *map, __u32 base,
        struct cfi_private *cfi)
 {
        map_word result;
        unsigned long mask;
+       u32 ofs = cfi_build_cmd_addr(0, cfi_interleave(cfi), cfi->device_type);
        mask = (1 << (cfi->device_type * 8)) -1;
-       result = map_read(map, base);
+       result = map_read(map, base + ofs);
        return result.x[0] & mask;
 }
 
-static inline u32 jedec_read_id(struct map_info *map, __u32 base, 
+static inline u32 jedec_read_id(struct map_info *map, __u32 base,
        struct cfi_private *cfi)
 {
-       int osf;
        map_word result;
        unsigned long mask;
-       osf = cfi->interleave *cfi->device_type;
+       u32 ofs = cfi_build_cmd_addr(1, cfi_interleave(cfi), cfi->device_type);
        mask = (1 << (cfi->device_type * 8)) -1;
-       result = map_read(map, base + osf);
+       result = map_read(map, base + ofs);
        return result.x[0] & mask;
 }
 
-static inline void jedec_reset(u32 base, struct map_info *map, 
+static inline void jedec_reset(u32 base, struct map_info *map,
        struct cfi_private *cfi)
 {
        /* Reset */
@@ -1653,9 +1798,11 @@ static inline void jedec_reset(u32 base, struct map_info *map,
         * as they will ignore the writes and dont care what address
         * the F0 is written to */
        if(cfi->addr_unlock1) {
-               /*printk("reset unlock called %x %x \n",cfi->addr_unlock1,cfi->addr_unlock2);*/
-               cfi_send_gen_cmd(0xaa, cfi->addr_unlock1, base, map, cfi, CFI_DEVICETYPE_X8, NULL);
-               cfi_send_gen_cmd(0x55, cfi->addr_unlock2, base, map, cfi, CFI_DEVICETYPE_X8, NULL);
+               DEBUG( MTD_DEBUG_LEVEL3,
+                      "reset unlock called %x %x \n",
+                      cfi->addr_unlock1,cfi->addr_unlock2);
+               cfi_send_gen_cmd(0xaa, cfi->addr_unlock1, base, map, cfi, cfi->device_type, NULL);
+               cfi_send_gen_cmd(0x55, cfi->addr_unlock2, base, map, cfi, cfi->device_type, NULL);
        }
 
        cfi_send_gen_cmd(0xF0, cfi->addr_unlock1, base, map, cfi, cfi->device_type, NULL);
@@ -1663,7 +1810,7 @@ static inline void jedec_reset(u32 base, struct map_info *map,
         * so ensure we're in read mode.  Send both the Intel and the AMD command
         * for this.  Intel uses 0xff for this, AMD uses 0xff for NOP, so
         * this should be safe.
-        */ 
+        */
        cfi_send_gen_cmd(0xFF, 0, base, map, cfi, cfi->device_type, NULL);
        /* FIXME - should have reset delay before continuing */
 }
@@ -1700,20 +1847,19 @@ static inline __u8 finfo_uaddr(const struct amd_flash_info *finfo, int device_ty
 static int cfi_jedec_setup(struct cfi_private *p_cfi, int index)
 {
        int i,num_erase_regions;
-       unsigned long mask;
        __u8 uaddr;
 
        printk("Found: %s\n",jedec_table[index].name);
 
        num_erase_regions = jedec_table[index].NumEraseRegions;
-       
+
        p_cfi->cfiq = kmalloc(sizeof(struct cfi_ident) + num_erase_regions * 4, GFP_KERNEL);
        if (!p_cfi->cfiq) {
                //xx printk(KERN_WARNING "%s: kmalloc failed for CFI ident structure\n", map->name);
                return 0;
        }
 
-       memset(p_cfi->cfiq,0,sizeof(struct cfi_ident)); 
+       memset(p_cfi->cfiq,0,sizeof(struct cfi_ident));
 
        p_cfi->cfiq->P_ID = jedec_table[index].CmdSet;
        p_cfi->cfiq->NumEraseRegions = jedec_table[index].NumEraseRegions;
@@ -1735,17 +1881,15 @@ static int cfi_jedec_setup(struct cfi_private *p_cfi, int index)
                return 0;
        }
 
-       /* Mask out address bits which are smaller than the device type */
-       mask = ~(p_cfi->device_type-1);
-       p_cfi->addr_unlock1 = unlock_addrs[uaddr].addr1 & mask;
-       p_cfi->addr_unlock2 = unlock_addrs[uaddr].addr2 & mask;
+       p_cfi->addr_unlock1 = unlock_addrs[uaddr].addr1;
+       p_cfi->addr_unlock2 = unlock_addrs[uaddr].addr2;
 
        return 1;       /* ok */
 }
 
 
 /*
- * There is a BIG problem properly ID'ing the JEDEC devic and guaranteeing
+ * There is a BIG problem properly ID'ing the JEDEC device and guaranteeing
  * the mapped address, unlock addresses, and proper chip ID.  This function
  * attempts to minimize errors.  It is doubtfull that this probe will ever
  * be perfect - consequently there should be some module parameters that
@@ -1759,7 +1903,6 @@ static inline int jedec_match( __u32 base,
        int rc = 0;           /* failure until all tests pass */
        u32 mfr, id;
        __u8 uaddr;
-       unsigned long mask;
 
        /*
         * The IDs must match.  For X16 and X32 devices operating in
@@ -1774,6 +1917,16 @@ static inline int jedec_match( __u32 base,
        case CFI_DEVICETYPE_X8:
                mfr = (__u8)finfo->mfr_id;
                id = (__u8)finfo->dev_id;
+
+               /* bjd: it seems that if we do this, we can end up
+                * detecting 16bit flashes as an 8bit device, even though
+                * there aren't.
+                */
+               if (finfo->dev_id > 0xff) {
+                       DEBUG( MTD_DEBUG_LEVEL3, "%s(): ID is not 8bit\n",
+                              __func__);
+                       goto match_done;
+               }
                break;
        case CFI_DEVICETYPE_X16:
                mfr = (__u16)finfo->mfr_id;
@@ -1797,7 +1950,7 @@ static inline int jedec_match( __u32 base,
        DEBUG( MTD_DEBUG_LEVEL3,
               "MTD %s(): Check fit 0x%.8x + 0x%.8x = 0x%.8x\n",
               __func__, base, 1 << finfo->DevSize, base + (1 << finfo->DevSize) );
-       if ( base + cfi->interleave * ( 1 << finfo->DevSize ) > map->size ) {
+       if ( base + cfi_interleave(cfi) * ( 1 << finfo->DevSize ) > map->size ) {
                DEBUG( MTD_DEBUG_LEVEL3,
                       "MTD %s(): 0x%.4x 0x%.4x %dKiB doesn't fit\n",
                       __func__, finfo->mfr_id, finfo->dev_id,
@@ -1810,18 +1963,16 @@ static inline int jedec_match( __u32 base,
                goto match_done;
        }
 
-       mask = ~(cfi->device_type-1);
-
        DEBUG( MTD_DEBUG_LEVEL3, "MTD %s(): check unlock addrs 0x%.4x 0x%.4x\n",
               __func__, cfi->addr_unlock1, cfi->addr_unlock2 );
        if ( MTD_UADDR_UNNECESSARY != uaddr && MTD_UADDR_DONT_CARE != uaddr
-            && ( (unlock_addrs[uaddr].addr1 & mask) != cfi->addr_unlock1 ||
-                 (unlock_addrs[uaddr].addr2 & mask) != cfi->addr_unlock2 ) ) {
+            && ( unlock_addrs[uaddr].addr1 != cfi->addr_unlock1 ||
+                 unlock_addrs[uaddr].addr2 != cfi->addr_unlock2 ) ) {
                DEBUG( MTD_DEBUG_LEVEL3,
-                      "MTD %s(): 0x%.4lx 0x%.4lx did not match\n",
-                      __func__,
-                      unlock_addrs[uaddr].addr1 & mask,
-                      unlock_addrs[uaddr].addr2 & mask);
+                       "MTD %s(): 0x%.4x 0x%.4x did not match\n",
+                       __func__,
+                       unlock_addrs[uaddr].addr1,
+                       unlock_addrs[uaddr].addr2);
                goto match_done;
        }
 
@@ -1857,13 +2008,13 @@ static inline int jedec_match( __u32 base,
         */
        DEBUG( MTD_DEBUG_LEVEL3, "MTD %s(): return to ID mode\n", __func__ );
        if(cfi->addr_unlock1) {
-               cfi_send_gen_cmd(0xaa, cfi->addr_unlock1, base, map, cfi, CFI_DEVICETYPE_X8, NULL);
-               cfi_send_gen_cmd(0x55, cfi->addr_unlock2, base, map, cfi, CFI_DEVICETYPE_X8, NULL);
+               cfi_send_gen_cmd(0xaa, cfi->addr_unlock1, base, map, cfi, cfi->device_type, NULL);
+               cfi_send_gen_cmd(0x55, cfi->addr_unlock2, base, map, cfi, cfi->device_type, NULL);
        }
-       cfi_send_gen_cmd(0x90, cfi->addr_unlock1, base, map, cfi, CFI_DEVICETYPE_X8, NULL);
+       cfi_send_gen_cmd(0x90, cfi->addr_unlock1, base, map, cfi, cfi->device_type, NULL);
        /* FIXME - should have a delay before continuing */
 
- match_done:   
+ match_done:
        return rc;
 }
 
@@ -1873,19 +2024,17 @@ static int jedec_probe_chip(struct map_info *map, __u32 base,
 {
        int i;
        enum uaddr uaddr_idx = MTD_UADDR_NOT_SUPPORTED;
+       u32 probe_offset1, probe_offset2;
 
  retry:
        if (!cfi->numchips) {
-               unsigned long mask = ~(cfi->device_type-1);
-
                uaddr_idx++;
 
                if (MTD_UADDR_UNNECESSARY == uaddr_idx)
                        return 0;
 
-               /* Mask out address bits which are smaller than the device type */
-               cfi->addr_unlock1 = unlock_addrs[uaddr_idx].addr1 & mask;
-               cfi->addr_unlock2 = unlock_addrs[uaddr_idx].addr2 & mask;
+               cfi->addr_unlock1 = unlock_addrs[uaddr_idx].addr1;
+               cfi->addr_unlock2 = unlock_addrs[uaddr_idx].addr2;
        }
 
        /* Make certain we aren't probing past the end of map */
@@ -1894,21 +2043,21 @@ static int jedec_probe_chip(struct map_info *map, __u32 base,
                        "Probe at base(0x%08x) past the end of the map(0x%08lx)\n",
                        base, map->size -1);
                return 0;
-               
-       }
-       if ((base + cfi->addr_unlock1) >= map->size) {
-               printk(KERN_NOTICE
-                       "Probe at addr_unlock1(0x%08x + 0x%08x) past the end of the map(0x%08lx)\n",
-                       base, cfi->addr_unlock1, map->size -1);
 
-               return 0;
        }
-       if ((base + cfi->addr_unlock2) >= map->size) {
-               printk(KERN_NOTICE
-                       "Probe at addr_unlock2(0x%08x + 0x%08x) past the end of the map(0x%08lx)\n",
-                       base, cfi->addr_unlock2, map->size -1);
-               return 0;
-               
+       /* Ensure the unlock addresses we try stay inside the map */
+       probe_offset1 = cfi_build_cmd_addr(
+               cfi->addr_unlock1,
+               cfi_interleave(cfi),
+               cfi->device_type);
+       probe_offset2 = cfi_build_cmd_addr(
+               cfi->addr_unlock1,
+               cfi_interleave(cfi),
+               cfi->device_type);
+       if (    ((base + probe_offset1 + map_bankwidth(map)) >= map->size) ||
+               ((base + probe_offset2 + map_bankwidth(map)) >= map->size))
+       {
+               goto retry;
        }
 
        /* Reset */
@@ -1916,22 +2065,22 @@ static int jedec_probe_chip(struct map_info *map, __u32 base,
 
        /* Autoselect Mode */
        if(cfi->addr_unlock1) {
-               cfi_send_gen_cmd(0xaa, cfi->addr_unlock1, base, map, cfi, CFI_DEVICETYPE_X8, NULL);
-               cfi_send_gen_cmd(0x55, cfi->addr_unlock2, base, map, cfi, CFI_DEVICETYPE_X8, NULL);
+               cfi_send_gen_cmd(0xaa, cfi->addr_unlock1, base, map, cfi, cfi->device_type, NULL);
+               cfi_send_gen_cmd(0x55, cfi->addr_unlock2, base, map, cfi, cfi->device_type, NULL);
        }
-       cfi_send_gen_cmd(0x90, cfi->addr_unlock1, base, map, cfi, CFI_DEVICETYPE_X8, NULL);
+       cfi_send_gen_cmd(0x90, cfi->addr_unlock1, base, map, cfi, cfi->device_type, NULL);
        /* FIXME - should have a delay before continuing */
 
        if (!cfi->numchips) {
-               /* This is the first time we're called. Set up the CFI 
+               /* This is the first time we're called. Set up the CFI
                   stuff accordingly and return */
-               
+
                cfi->mfr = jedec_read_mfr(map, base, cfi);
                cfi->id = jedec_read_id(map, base, cfi);
                DEBUG(MTD_DEBUG_LEVEL3,
-                     "Search for id:(%02x %02x) interleave(%d) type(%d)\n", 
-                       cfi->mfr, cfi->id, cfi->interleave, cfi->device_type);
-               for (i=0; i<sizeof(jedec_table)/sizeof(jedec_table[0]); i++) {
+                     "Search for id:(%02x %02x) interleave(%d) type(%d)\n",
+                       cfi->mfr, cfi->id, cfi_interleave(cfi), cfi->device_type);
+               for (i = 0; i < ARRAY_SIZE(jedec_table); i++) {
                        if ( jedec_match( base, map, cfi, &jedec_table[i] ) ) {
                                DEBUG( MTD_DEBUG_LEVEL3,
                                       "MTD %s(): matched device 0x%x,0x%x unlock_addrs: 0x%.4x 0x%.4x\n",
@@ -1958,7 +2107,7 @@ static int jedec_probe_chip(struct map_info *map, __u32 base,
                        return 0;
                }
        }
-       
+
        /* Check each previous chip locations to see if it's an alias */
        for (i=0; i < (base >> cfi->chipshift); i++) {
                unsigned long start;
@@ -1979,7 +2128,7 @@ static int jedec_probe_chip(struct map_info *map, __u32 base,
                                       map->name, base, start);
                                return 0;
                        }
-                       
+
                        /* Yes, it's actually got the device IDs as data. Most
                         * unfortunate. Stick the new chip in read mode
                         * too and if it's the same, assume it's an alias. */
@@ -1993,20 +2142,20 @@ static int jedec_probe_chip(struct map_info *map, __u32 base,
                        }
                }
        }
-               
+
        /* OK, if we got to here, then none of the previous chips appear to
           be aliases for the current one. */
        set_bit((base >> cfi->chipshift), chip_map); /* Update chip map */
        cfi->numchips++;
-               
+
 ok_out:
        /* Put it back into Read Mode */
        jedec_reset(base, map, cfi);
 
        printk(KERN_INFO "%s: Found %d x%d devices at 0x%x in %d-bit bank\n",
-              map->name, cfi->interleave, cfi->device_type*8, base, 
+              map->name, cfi_interleave(cfi), cfi->device_type*8, base,
               map->bankwidth*8);
-       
+
        return 1;
 }
 
@@ -2015,7 +2164,7 @@ static struct chip_probe jedec_chip_probe = {
        .probe_chip = jedec_probe_chip
 };
 
-struct mtd_info *jedec_probe(struct map_info *map)
+static struct mtd_info *jedec_probe(struct map_info *map)
 {
        /*
         * Just use the generic probe stuff to call our CFI-specific
@@ -2030,7 +2179,7 @@ static struct mtd_chip_driver jedec_chipdrv = {
        .module = THIS_MODULE
 };
 
-int __init jedec_probe_init(void)
+static int __init jedec_probe_init(void)
 {
        register_mtd_chip_driver(&jedec_chipdrv);
        return 0;