diff --git a/drivers/mtd/devices/m25p80.c b/drivers/mtd/devices/m25p80.c
index 3fb981d..9dd3af4 100644
--- a/drivers/mtd/devices/m25p80.c
+++ b/drivers/mtd/devices/m25p80.c
@@ -25,8 +25,10 @@
 #include <linux/math64.h>
 #include <linux/slab.h>
 #include <linux/sched.h>
+#include <linux/kernel.h>
 #include <linux/mod_devicetable.h>
 
+#include <linux/mtd/cfi.h>
 #include <linux/mtd/mtd.h>
 #include <linux/mtd/partitions.h>
 
@@ -68,6 +70,11 @@
 #define	MAX_READY_WAIT_JIFFIES	(40 * HZ)	/* M25P16 specs 40s max chip erase */
 #define	MAX_CMD_SIZE		5
 
+#define	SPI_CFI_OFFSET		0x10	/* Start of CFI data in RDID result */
+#define	SPI_CFI_ERASE_REGIONS	2	/* Max EraseRegionInfo's supported */
+#define	SPI_CFI_LEN		(sizeof(struct cfi_ident) + \
+				 SPI_CFI_ERASE_REGIONS * 4)
+
 #ifdef CONFIG_M25PXX_USE_FAST_READ
 #define OPCODE_READ 	OPCODE_FAST_READ
 #define FAST_READ_DUMMY_BYTE 1
@@ -639,8 +646,8 @@ struct flash_info {
 	})
 
 /* NOTE: double check command sets and memory organization when you add
- * more flash chips.  This current list focusses on newer chips, which
- * have been converging on command sets which including JEDEC ID.
+ * new flash chips.  This current list focuses on newer chips, which
+ * have been converging on command sets which include JEDEC ID.
  */
 static const struct spi_device_id m25p_ids[] = {
 	/* Atmel -- some are (confusingly) marketed as "DataFlash" */
@@ -752,45 +759,87 @@ static const struct spi_device_id m25p_ids[] = {
 };
 MODULE_DEVICE_TABLE(spi, m25p_ids);
 
-static const struct spi_device_id *__devinit jedec_probe(struct spi_device *spi)
+static int __devinit cfi_probe(struct spi_device *spi, struct flash_info *det)
 {
 	int			tmp;
 	u8			code = OPCODE_RDID;
-	u8			id[5];
-	u32			jedec;
-	u16                     ext_jedec;
+	u8			id[SPI_CFI_OFFSET + SPI_CFI_LEN];
 	struct flash_info	*info;
+	struct cfi_ident	*cfi;
+	u32			device_size;
+
+	memset(det, 0, sizeof(*det));
 
-	/* JEDEC also defines an optional "extended device information"
-	 * string for after vendor-specific data, after the three bytes
-	 * we use here.  Supporting some chips might require using it.
+	/*
+	 * Read JEDEC 3-byte ID + extended 2-byte manufacturer ID + any
+	 * CFI data that might be present.  Then look for a match with
+	 * known devices.
 	 */
-	tmp = spi_write_then_read(spi, &code, 1, id, 5);
+
+	tmp = spi_write_then_read(spi, &code, 1, id, sizeof(id));
 	if (tmp < 0) {
 		DEBUG(MTD_DEBUG_LEVEL0, "%s: error %d reading JEDEC ID\n",
 			dev_name(&spi->dev), tmp);
-		return ERR_PTR(tmp);
+		return tmp;
 	}
-	jedec = id[0];
-	jedec = jedec << 8;
-	jedec |= id[1];
-	jedec = jedec << 8;
-	jedec |= id[2];
 
-	ext_jedec = id[3] << 8 | id[4];
+	det->jedec_id = id[0] << 16 | id[1] << 8 | id[2];
+	det->ext_id = id[3] << 8 | id[4];
 
 	for (tmp = 0; tmp < ARRAY_SIZE(m25p_ids) - 1; tmp++) {
 		info = (void *)m25p_ids[tmp].driver_data;
-		if (info->jedec_id == jedec) {
-			if (info->ext_id != 0 && info->ext_id != ext_jedec)
+		if (info->jedec_id == det->jedec_id) {
+			if (info->ext_id != 0 && info->ext_id != det->ext_id)
 				continue;
-			return &m25p_ids[tmp];
+			*det = *info;
+			dev_info(&spi->dev,
+				 "identified known JEDEC device %s (%d KiB)\n",
+				 m25p_ids[tmp].name,
+				 det->sector_size * det->n_sectors / 1024);
+			return 0;
 		}
 	}
-	dev_err(&spi->dev, "unrecognized JEDEC id %06x\n", jedec);
-	return ERR_PTR(-ENODEV);
-}
 
+	/* No match in the table; try obtaining the params via CFI instead. */
+
+	cfi = (struct cfi_ident *)&id[SPI_CFI_OFFSET];
+	if (cfi->qry[0] != 'Q' || cfi->qry[1] != 'R' || cfi->qry[2] != 'Y') {
+		dev_err(&spi->dev, "unrecognized JEDEC id %06x\n",
+			det->jedec_id);
+		return -ENODEV;
+	}
+
+	/*
+	 * m25p80.c always uses "uniform sector" mode.  If multiple regions
+	 * are defined, find the first >4KiB region and then calculate the
+	 * number of sectors from the reported device size.
+	 */
+
+	device_size = 1 << cfi->DevSize;
+	cfi->NumEraseRegions = min(cfi->NumEraseRegions,
+		(uint8_t)SPI_CFI_ERASE_REGIONS);
+
+	for (tmp = 0; tmp < cfi->NumEraseRegions; tmp++) {
+		det->sector_size =
+			(le32_to_cpu(cfi->EraseRegionInfo[tmp]) >> 8) & ~0xff;
+
+		if ((cfi->NumEraseRegions == 1 || det->sector_size > 4096) &&
+		    det->sector_size != 0 && device_size != 0 &&
+		    device_size >= det->sector_size &&
+		    device_size % det->sector_size == 0) {
+			det->n_sectors = device_size / det->sector_size;
+			dev_info(&spi->dev,
+				"found CFI device (%d KiB, id %06x-%04x)\n",
+				det->sector_size * det->n_sectors / 1024,
+				det->jedec_id, det->ext_id);
+			return 0;
+		}
+	}
+
+	dev_err(&spi->dev, "device id %06x has invalid CFI data\n",
+		det->jedec_id);
+	return -ENODEV;
+}
 
 /*
  * board specific setup should have ensured the SPI clock used here
@@ -802,52 +851,67 @@ static int __devinit m25p_probe(struct spi_device *spi)
 	const struct spi_device_id	*id = spi_get_device_id(spi);
 	struct flash_platform_data	*data;
 	struct m25p			*flash;
-	struct flash_info		*info;
+	struct flash_info		*info, cfi_info;
 	unsigned			i;
+	int				autodetect = 0;
 
-	/* Platform data helps sort out which chip type we have, as
-	 * well as how this board partitions it.  If we don't have
-	 * a chip ID, try the JEDEC id commands; they'll work for most
-	 * newer chips, even if we don't recognize the particular chip.
+	/*
+	 * "id" currently points to the m25p_ids[] entry matching
+	 * spi_board_info.modalias.  This could be a specific chip name
+	 * (ala "s25fl129p1") or it could just be our driver name ("m25p80").
+	 *
+	 * If a specific chip name is set in platform_data->type, try to look
+	 * up that name instead of using the modalias as the chip name.
+	 *
+	 * If platform_data->type says "auto", assume "id" is meaningless,
+	 * and just probe via JEDEC/CFI.
 	 */
+
 	data = spi->dev.platform_data;
 	if (data && data->type) {
 		const struct spi_device_id *plat_id;
 
-		for (i = 0; i < ARRAY_SIZE(m25p_ids) - 1; i++) {
-			plat_id = &m25p_ids[i];
-			if (strcmp(data->type, plat_id->name))
-				continue;
-			break;
-		}
+		if (strcmp(data->type, "auto") == 0)
+			autodetect = 1;
+		else {
+			for (i = 0; i < ARRAY_SIZE(m25p_ids) - 1; i++) {
+				plat_id = &m25p_ids[i];
+				if (strcmp(data->type, plat_id->name))
+					continue;
+				break;
+			}
 
-		if (i < ARRAY_SIZE(m25p_ids) - 1)
-			id = plat_id;
-		else
-			dev_warn(&spi->dev, "unrecognized id %s\n", data->type);
+			if (i < ARRAY_SIZE(m25p_ids) - 1)
+				id = plat_id;
+			else
+				dev_warn(&spi->dev, "unrecognized chip %s\n",
+					data->type);
+		}
 	}
 
 	info = (void *)id->driver_data;
 
-	if (info->jedec_id) {
-		const struct spi_device_id *jid;
-
-		jid = jedec_probe(spi);
-		if (IS_ERR(jid)) {
-			return PTR_ERR(jid);
-		} else if (jid != id) {
-			/*
-			 * JEDEC knows better, so overwrite platform ID. We
-			 * can't trust partitions any longer, but we'll let
-			 * mtd apply them anyway, since some partitions may be
-			 * marked read-only, and we don't want to lose that
-			 * information, even if it's not 100% accurate.
-			 */
-			dev_warn(&spi->dev, "found %s, expected %s\n",
-				 jid->name, id->name);
-			id = jid;
-			info = (void *)jid->driver_data;
-		}
+	/*
+	 * If we found an entry that claims to be JEDEC-compliant, read
+	 * the ID and make sure it matches.  (If not, print a warning but
+	 * continue anyway.)
+	 *
+	 * If we were asked to autodetect the chip type, go ahead and do so.
+	 */
+
+	if (info->jedec_id || autodetect) {
+		int rc = cfi_probe(spi, &cfi_info);
+		if (rc)
+			return rc;
+
+		if (!autodetect &&
+		    (info->jedec_id != cfi_info.jedec_id ||
+		     info->ext_id != cfi_info.ext_id))
+			dev_warn(&spi->dev,
+				"found id %06x, expected %06x (%s)\n",
+				cfi_info.jedec_id, info->jedec_id,
+				id->name);
+		info = &cfi_info;
 	}
 
 	flash = kzalloc(sizeof *flash, GFP_KERNEL);
@@ -919,9 +983,6 @@ static int __devinit m25p_probe(struct spi_device *spi)
 			flash->addr_width = 3;
 	}
 
-	dev_info(&spi->dev, "%s (%lld Kbytes)\n", id->name,
-			(long long)flash->mtd.size >> 10);
-
 	DEBUG(MTD_DEBUG_LEVEL2,
 		"mtd .name = %s, .size = 0x%llx (%lldMiB) "
 			".erasesize = 0x%.8x (%uKiB) .numeraseregions = %d\n",
