diff -u flashrom/chipdrivers.h flashrom-patched/chipdrivers.h
--- flashrom/chipdrivers.h	2011-06-27 15:21:57.000000000 +0200
+++ flashrom-patched/chipdrivers.h	2011-06-28 14:38:54.000000000 +0200
@@ -31,9 +31,11 @@
 int probe_spi_rems(struct flashchip *flash);
 int probe_spi_res1(struct flashchip *flash);
 int probe_spi_res2(struct flashchip *flash);
+int probe_spi_mx_2017(struct flashchip *flash);
 int spi_write_enable(void);
 int spi_write_disable(void);
 int spi_block_erase_20(struct flashchip *flash, unsigned int addr, unsigned int blocklen);
+int spi_block_erase_20_4or64k(struct flashchip *flash, unsigned int addr, unsigned int blocklen);
 int spi_block_erase_52(struct flashchip *flash, unsigned int addr, unsigned int blocklen);
 int spi_block_erase_d7(struct flashchip *flash, unsigned int addr, unsigned int blocklen);
 int spi_block_erase_d8(struct flashchip *flash, unsigned int addr, unsigned int blocklen);
diff -u flashrom/flashchips.c flashrom-patched/flashchips.c
--- flashrom/flashchips.c	2011-06-27 15:21:57.000000000 +0200
+++ flashrom-patched/flashchips.c	2011-06-29 13:22:51.000000000 +0200
@@ -3959,14 +3959,14 @@
 		.total_size	= 2048,
 		.page_size	= 256,
 		.feature_bits	= FEATURE_WRSR_WREN,
-		.tested		= TEST_OK_PREW,
+		.tested		= TEST_OK_PRW,
 		.probe		= probe_spi_rdid,
 		.probe_timing	= TIMING_ZERO,
 		.block_erasers	=
 		{
 			{
-				.eraseblocks = { {4 * 1024, 512} },
-				.block_erase = spi_block_erase_20,	/* This erase function has 64k blocksize for eLiteFlash */
+				.eraseblocks = { {64 * 1024, 32} },
+				.block_erase = spi_block_erase_20_4or64k,	/* This erase function has 64k blocksize for eLiteFlash */
 			}, {
 				.eraseblocks = { {64 * 1024, 32} },	/* Not supported in MX25L1605 (eLiteFlash) and MX25L1605D */
 				.block_erase = spi_block_erase_52,
@@ -4063,16 +4063,16 @@
 		.total_size	= 4096,
 		.page_size	= 256,
 		.feature_bits	= FEATURE_WRSR_WREN,
-		.tested		= TEST_OK_PREW,
+		.tested		= TEST_OK_PRW,
 		.probe		= probe_spi_rdid,
 		.probe_timing	= TIMING_ZERO,
 		.block_erasers	=
 		{
 			{
-				.eraseblocks = { {4 * 1024, 1024} },
-				.block_erase = spi_block_erase_20,
+				.eraseblocks = { {64 * 1024, 64} },
+				.block_erase = spi_block_erase_20_4or64k,
 			}, {
-				.eraseblocks = { {4 * 1024, 1024} },
+				.eraseblocks = { {64 * 1024, 64} },
 				.block_erase = spi_block_erase_d8,
 			}, {
 				.eraseblocks = { {4 * 1024 * 1024, 1} },
@@ -4132,12 +4132,46 @@
 		.page_size	= 256,
 		.feature_bits	= FEATURE_WRSR_WREN,
 		.tested		= TEST_OK_PROBE,
-		.probe		= probe_spi_rdid,
+		.probe		= probe_spi_mx_2017,
 		.probe_timing	= TIMING_ZERO,
 		.block_erasers	=
 		{
 			{
 				.eraseblocks = { {64 * 1024, 128} },
+				.block_erase = spi_block_erase_20_4or64k,
+			}, {
+				.eraseblocks = { {64 * 1024, 128} },
+				.block_erase = spi_block_erase_d8,
+			}, {
+				.eraseblocks = { {8 * 1024 * 1024, 1} },
+				.block_erase = spi_block_erase_60,
+			}, {
+				.eraseblocks = { {8 * 1024 * 1024, 1} },
+				.block_erase = spi_block_erase_c7,
+			}
+		},
+		.unlock		= spi_disable_blockprotect,
+		.write		= spi_chip_write_256,
+		.read		= spi_chip_read,
+		.voltage	= {2700, 3600},
+	},
+
+	{
+		.vendor		= "Macronix",
+		.name		= "MX25L6445E",
+		.bustype	= CHIP_BUSTYPE_SPI,
+		.manufacture_id	= MACRONIX_ID,
+		.model_id	= MACRONIX_MX25L6445E,
+		.total_size	= 8192,
+		.page_size	= 256,
+		.feature_bits	= FEATURE_WRSR_WREN,
+		.tested		= TEST_OK_PREW,
+		.probe		= probe_spi_mx_2017,
+		.probe_timing	= TIMING_ZERO,
+		.block_erasers	=
+		{
+			{
+				.eraseblocks = { {4 * 1024, 2048} },
 				.block_erase = spi_block_erase_20,
 			}, {
 				.eraseblocks = { {64 * 1024, 128} },
diff -u flashrom/flashchips.h flashrom-patched/flashchips.h
--- flashrom/flashchips.h	2011-06-27 15:21:57.000000000 +0200
+++ flashrom-patched/flashchips.h	2011-06-28 16:24:07.000000000 +0200
@@ -356,7 +356,8 @@
 #define MACRONIX_MX25L8005	0x2014	/* Same as MX25V8005 */
 #define MACRONIX_MX25L1605	0x2015	/* MX25L1605{,A,D} */
 #define MACRONIX_MX25L3205	0x2016	/* MX25L3205{,A} */
-#define MACRONIX_MX25L6405	0x2017	/* MX25L3205{,D} */
+#define MACRONIX_MX25L6405	0x2017	/* MX25L6405, MX25L6406E */ 
+#define MACRONIX_MX25L6445E	0x16	/* MX25L6445E, MX25L6405D ID = REMS2 answer */
 #define MACRONIX_MX25L12805	0x2018	/* MX25L12805 */
 #define MACRONIX_MX25L1635D	0x2415
 #define MACRONIX_MX25L1635E	0x2515	/* MX25L1635{E} */
diff -u flashrom/spi.h flashrom-patched/spi.h
--- flashrom/spi.h	2011-06-27 15:21:57.000000000 +0200
+++ flashrom-patched/spi.h	2011-06-29 13:32:55.000000000 +0200
@@ -40,6 +40,21 @@
 #define JEDEC_REMS_OUTSIZE	0x04
 #define JEDEC_REMS_INSIZE	0x02
 
+/* Read Electronic Manufacturer Signature for 2x I/O mode */
+#define JEDEC_REMS2		0xef
+#define JEDEC_REMS2_OUTSIZE	0x04
+#define JEDEC_REMS2_INSIZE	0x02
+
+/* Read Electronic Manufacturer Signature for 4x I/O mode */
+#define JEDEC_REMS4		0xdf
+#define JEDEC_REMS4_OUTSIZE	0x04
+#define JEDEC_REMS4_INSIZE	0x02
+
+/* Read Electronic Manufacturer Signature for 4x I/O DT mode */
+#define JEDEC_REMS4D		0xcf
+#define JEDEC_REMS4D_OUTSIZE	0x04
+#define JEDEC_REMS4D_INSIZE	0x02
+
 /* Read Electronic Signature */
 #define JEDEC_RES		0xab
 #define JEDEC_RES_OUTSIZE	0x04
diff -u flashrom/spi25.c flashrom-patched/spi25.c
--- flashrom/spi25.c	2011-06-27 15:21:57.000000000 +0200
+++ flashrom-patched/spi25.c	2011-06-29 13:09:59.000000000 +0200
@@ -22,6 +22,7 @@
  * Contains the common SPI chip driver functions
  */
 
+#include <stdlib.h>
 #include <string.h>
 #include "flash.h"
 #include "flashchips.h"
@@ -66,6 +67,27 @@
 	return 0;
 }
 
+static int spi_rems2(unsigned char *readarr)
+{
+	unsigned char cmd[JEDEC_REMS2_OUTSIZE] = { JEDEC_REMS2, 0, 0, 0 };
+	uint32_t readaddr;
+	int ret;
+
+	ret = spi_send_command(sizeof(cmd), JEDEC_REMS2_INSIZE, cmd, readarr);
+	if (ret == SPI_INVALID_ADDRESS) {
+		/* Find the lowest even address allowed for reads. */
+		readaddr = (spi_get_valid_read_addr() + 1) & ~1;
+		cmd[1] = (readaddr >> 16) & 0xff,
+		cmd[2] = (readaddr >> 8) & 0xff,
+		cmd[3] = (readaddr >> 0) & 0xff,
+		ret = spi_send_command(sizeof(cmd), JEDEC_REMS2_INSIZE, cmd, readarr);
+	}
+	if (ret)
+		return ret;
+	msg_cspew("REMS2 returned %02x %02x. ", readarr[0], readarr[1]);
+	return 0;
+}
+
 static int spi_res(unsigned char *readarr, int bytes)
 {
 	unsigned char cmd[JEDEC_RES_OUTSIZE] = { JEDEC_RES, 0, 0, 0 };
@@ -173,6 +195,58 @@
 	return probe_spi_rdid_generic(flash, 3);
 }
 
+int probe_spi_mx_2017(struct flashchip *flash)
+{
+	unsigned char readarr[4];
+	uint32_t id1;
+	uint32_t id2;
+	uint32_t id3;
+	uint32_t id4;
+
+	if (spi_rdid(readarr, 3)) {
+		msg_cdbg("\n");
+		return 0;
+	}
+	id1 = readarr[0];
+	id2 = (readarr[1] << 8) | readarr[2];
+
+	if (id1 == MACRONIX_ID && id2 == MACRONIX_MX25L6405) {
+	/* Now we have detected the 2017h class of Macronix flash devices.
+	 * We can further differentiate two classes:
+	 * -those who support the REMS2 function do always have 4KB sector size
+	 *  (at least i have not found one with 64KB yet),
+	 * and
+	 * -those who don't support the REMS2 function might have 4KB or 64KB
+	 *  (some have 4KB, e.g. MX25L6406E, some have 64KB, e.g. MX25L6405 (not D))
+	 *  for erase function 20h.
+	 */
+		if (spi_rems2(readarr)) {
+			msg_cdbg("\n");
+			return 0;
+		}
+		id3 = readarr[0];
+		id4 = readarr[1];
+		msg_cdbg("%s: id1 0x%02x, id2 0x%02x, id3 0x%02x, id4 0x%02x\n", __func__, id1, id2, id3, id4);
+		if (id3 == MACRONIX_ID && id4 == MACRONIX_MX25L6445E) {
+		/* MACRONIX_MX25L6445E class, always 4KB sector */
+			if (flash->model_id == MACRONIX_MX25L6445E)
+				return 1;
+			else
+				return 0;
+		} else {
+		/* MACRONIX_MX25L6405 class, might have 4KB or 64KB sector */
+			if (flash->model_id == MACRONIX_MX25L6405)
+				return 1;
+			else
+				return 0;
+		}
+	} else {
+		msg_cdbg("%s: id1 0x%02x, id2 0x%02x\n", __func__, id1, id2);
+	}
+	/* neither MACRONIX_MX25L6405 nor MACRONIX_MX25L6445E */
+	return 0;
+}
+
 int probe_spi_rdid4(struct flashchip *flash)
 {
 	/* Some SPI controllers do not support commands with writecnt=1 and
@@ -694,6 +768,79 @@
 	return 0;
 }
 
+/* Sector size might be 4KB or 64KB, but on call to this function this is unknown.
+ * So we do a first erase command and then check if mem in the complete 64KB sector is erased.
+ * If not we assume 4KB and so we repeat the erase for each 4KB sector in the 64KB block
+ * (which is not erased already).
+ * PLEASE NOTE: the .eraseblocks block size must be set to 64KB if you use this function.
+ */
+int spi_block_erase_20_4or64k(struct flashchip *flash, unsigned int addr, unsigned int blocklen)
+{
+	int result, i, j, fully_erased, sector_erased;
+	unsigned int curraddr, currblocklen;
+	uint8_t *readbuf;
+
+	if (blocklen != (64 * 1024)) {
+		msg_gerr("%s: blocklen not 64KB! Please report a bug at "
+			 "flashrom@flashrom.org\n", __func__);
+		return 1;
+	}
+
+	readbuf = malloc(blocklen); 
+	if (!readbuf) {
+		msg_gerr("Out of memory!\n");
+		exit(1);
+	} 
+
+        for (i = 0; i < 16; i++) {	/* there are 16 4KB sectors in 64KB */
+
+		curraddr = addr + (i * (4 * 1024));
+
+		if (i > 0) {
+			/* Skip the sector erase if the sector is already erased */
+			sector_erased = 1;
+			result = flash->read(flash, readbuf, curraddr, (4 * 1024));
+			if (result) {
+				msg_gerr("Erase impossible because read failed "
+					 "at 0x%x (len 0x%x)\n", curraddr, (4 * 1024));
+				break;
+			}
+			for (j = 0; j < currblocklen; j++)
+				if (readbuf[j] != 0xFF)
+					sector_erased = 0;
+			if (sector_erased)
+				continue;	/* Sector is already erased */
+		}
+
+		result = spi_block_erase_20 (flash, curraddr, (4 * 1024)); /* last parameter (blocklen) is unused */
+		if (result) break;
+
+		if (0 == i) {
+			curraddr += 4 * 1024;
+			currblocklen = (64*1024)-(4*1024);
+			fully_erased = 1;
+			result = flash->read(flash, readbuf, curraddr, currblocklen);
+			if (result) {
+				msg_gerr("Erase impossible because read failed "
+					 "at 0x%x (len 0x%x)\n", curraddr, currblocklen);
+				break;
+			}
+			for (j = 0; j < currblocklen; j++)
+				if (readbuf[j] != 0xFF)
+					fully_erased = 0;
+			if (fully_erased) {
+			/* This means either that the SE command has erased the full 64KB
+			 * or that the remaining 64KB sector was already erased before.
+			 * Anyhow, we can now exit without calling the SE command again.
+			 */
+				break;
+			}
+		}
+        }
+	free(readbuf);
+        return result;
+}
+
 int spi_block_erase_60(struct flashchip *flash, unsigned int addr, unsigned int blocklen)
 {
 	if ((addr != 0) || (blocklen != flash->total_size * 1024)) {
