Patchwork Unify non-shifted and shifted JEDEC access.

login
register
about
Submitter Stefan Tauner
Date 2014-08-07 21:49:57
Message ID <1407448197-9814-1-git-send-email-stefan.tauner@alumni.tuwien.ac.at>
Download mbox | patch
Permalink /patch/4227/
State Accepted
Headers show

Comments

Stefan Tauner - 2014-08-07 21:49:57
Some Parallel bus chips have a 16-bit mode and an 8-bit mode. They use
normal JEDEC addresses for 16-bit mode and shifted addresses (by 1 bit)
for 8-bit mode. Some programmers can access them in 16-bit mode, but on
all flashrom-supported programmers so far, we access them in 8-bit mode.
This means we have to shift the addresses but apart from the addresses
we can share the code.

This patch makes this possible by checking the chip's FEATURE_ADDR_SHIFTED
flag in common JEDEC functions and applying the right addresses respectively.

Signed-off-by: Carl-Daniel Hailfinger <c-d.hailfinger.devel.2006@gmx.net>
Signed-off-by: Stefan Tauner <stefan.tauner@alumni.tuwien.ac.at>
---

I have removed the obsolete code, changed the probe_timing field to 10
plus a comment explaining it where relevant, applied the changes to a
few other chips that probably were not there before, and refined the
shift handling as discussed on IRC.

 82802ab.c     |  2 +-
 Makefile      |  2 +-
 chipdrivers.h |  6 -----
 en29lv640b.c  | 48 ---------------------------------
 flashchips.c  | 74 +++++++++++++++++++++++++-------------------------
 flashchips.h  |  2 ++
 jedec.c       | 75 ++++++++++++++++++++++++++++-----------------------
 m29f400bt.c   | 87 -----------------------------------------------------------
 8 files changed, 83 insertions(+), 213 deletions(-)
 delete mode 100644 m29f400bt.c
Stefan Tauner - 2014-08-08 09:18:16
On Thu,  7 Aug 2014 23:49:57 +0200
Stefan Tauner <stefan.tauner@alumni.tuwien.ac.at> wrote:

> Some Parallel bus chips have a 16-bit mode and an 8-bit mode. They use
> normal JEDEC addresses for 16-bit mode and shifted addresses (by 1 bit)
> for 8-bit mode. Some programmers can access them in 16-bit mode, but on
> all flashrom-supported programmers so far, we access them in 8-bit mode.
> This means we have to shift the addresses but apart from the addresses
> we can share the code.
> 
> This patch makes this possible by checking the chip's FEATURE_ADDR_SHIFTED
> flag in common JEDEC functions and applying the right addresses respectively.
> 
> Signed-off-by: Carl-Daniel Hailfinger <c-d.hailfinger.devel.2006@gmx.net>
> Signed-off-by: Stefan Tauner <stefan.tauner@alumni.tuwien.ac.at>
> ---
> 
> I have removed the obsolete code, changed the probe_timing field to 10
> plus a comment explaining it where relevant, applied the changes to a
> few other chips that probably were not there before, and refined the
> shift handling as discussed on IRC.

Acked by Carl-Daniel and committed in r1840.

Patch

diff --git a/82802ab.c b/82802ab.c
index e450b5d..70c6af0 100644
--- a/82802ab.c
+++ b/82802ab.c
@@ -44,7 +44,7 @@  int probe_82802ab(struct flashctx *flash)
 {
 	chipaddr bios = flash->virtual_memory;
 	uint8_t id1, id2, flashcontent1, flashcontent2;
-	int shifted = (flash->chip->feature_bits & FEATURE_ADDR_SHIFTED) != 0;
+	int shifted = (flash->chip->feature_bits & FEATURE_ADDR_SHIFTED) ? 1 : 0;
 
 	/* Reset to get a clean state */
 	chip_writeb(flash, 0xFF, bios);
diff --git a/Makefile b/Makefile
index 8f2d68d..d0d6454 100644
--- a/Makefile
+++ b/Makefile
@@ -351,7 +351,7 @@  endif
 # Flash chip drivers and bus support infrastructure.
 
 CHIP_OBJS = jedec.o stm50.o w39.o w29ee011.o \
-	sst28sf040.o m29f400bt.o 82802ab.o \
+	sst28sf040.o 82802ab.o \
 	sst49lfxxxc.o sst_fwhub.o flashchips.o spi.o spi25.o spi25_statusreg.o \
 	opaque.o sfdp.o en29lv640b.o at45db.o
 
diff --git a/chipdrivers.h b/chipdrivers.h
index dbe45b8..8529c74 100644
--- a/chipdrivers.h
+++ b/chipdrivers.h
@@ -155,10 +155,6 @@  int printlock_regspace2_uniform_64k(struct flashctx *flash);
 int printlock_regspace2_block_eraser_0(struct flashctx *flash);
 int printlock_regspace2_block_eraser_1(struct flashctx *flash);
 
-/* m29f400bt.c */
-int probe_m29f400bt(struct flashctx *flash);
-int write_m29f400bt(struct flashctx *flash, const uint8_t *buf, unsigned int start, unsigned int len);
-
 /* sst28sf040.c */
 int erase_chip_28sf040(struct flashctx *flash, unsigned int addr, unsigned int blocklen);
 int erase_sector_28sf040(struct flashctx *flash, unsigned int address, unsigned int sector_size);
@@ -197,8 +193,6 @@  int erase_sector_stm50(struct flashctx *flash, unsigned int block, unsigned int
 
 /* en29lv640b.c */
 int probe_en29lv640b(struct flashctx *flash);
-int erase_block_shifted_jedec(struct flashctx *flash, unsigned int start, unsigned int len);
-int erase_chip_block_shifted_jedec(struct flashctx *flash, unsigned int start, unsigned int len);
 int write_en29lv640b(struct flashctx *flash, const uint8_t *buf, unsigned int start, unsigned int len);
 
 #endif /* !__CHIPDRIVERS_H__ */
diff --git a/en29lv640b.c b/en29lv640b.c
index a274f62..3a5f611 100644
--- a/en29lv640b.c
+++ b/en29lv640b.c
@@ -85,51 +85,3 @@  int probe_en29lv640b(struct flashctx *flash)
 
 	return 0;
 }
-
-static int erase_chip_shifted_jedec(struct flashctx *flash)
-{
-	chipaddr bios = flash->virtual_memory;
-
-	chip_writeb(flash, 0xAA, bios + 0xAAA);
-	chip_writeb(flash, 0x55, bios + 0x555);
-	chip_writeb(flash, 0x80, bios + 0xAAA);
-
-	chip_writeb(flash, 0xAA, bios + 0xAAA);
-	chip_writeb(flash, 0x55, bios + 0x555);
-	chip_writeb(flash, 0x10, bios + 0xAAA);
-
-	programmer_delay(10);
-	toggle_ready_jedec(flash, bios);
-
-	/* FIXME: Check the status register for errors. */
-	return 0;
-}
-
-int erase_block_shifted_jedec(struct flashctx *flash, unsigned int start, unsigned int len)
-{
-	chipaddr bios = flash->virtual_memory;
-	chipaddr dst = bios + start;
-
-	chip_writeb(flash, 0xAA, bios + 0xAAA);
-	chip_writeb(flash, 0x55, bios + 0x555);
-	chip_writeb(flash, 0x80, bios + 0xAAA);
-
-	chip_writeb(flash, 0xAA, bios + 0xAAA);
-	chip_writeb(flash, 0x55, bios + 0x555);
-	chip_writeb(flash, 0x30, dst);
-
-	programmer_delay(10);
-	toggle_ready_jedec(flash, bios);
-
-	/* FIXME: Check the status register for errors. */
-	return 0;
-}
-
-int erase_chip_block_shifted_jedec(struct flashctx *flash, unsigned int address, unsigned int blocklen)
-{
-	if ((address != 0) || (blocklen != flash->chip->total_size * 1024)) {
-		msg_cerr("%s called with incorrect arguments\n", __func__);
-		return -1;
-	}
-	return erase_chip_shifted_jedec(flash);
-}
diff --git a/flashchips.c b/flashchips.c
index 68b5dcf..74b58ba 100644
--- a/flashchips.c
+++ b/flashchips.c
@@ -4869,7 +4869,7 @@  const struct flashchip flashchips[] = {
 		.model_id	= EON_EN29LV640B,
 		.total_size	= 8192,
 		.page_size	= 8192,
-		.feature_bits	= 0,
+		.feature_bits	= FEATURE_ADDR_SHIFTED,
 		.tested		= TEST_OK_PREW,
 		.probe		= probe_en29lv640b,
 		.probe_timing	= TIMING_ZERO,	/* Datasheet has no timing info specified */
@@ -4880,10 +4880,10 @@  const struct flashchip flashchips[] = {
 					{8 * 1024, 8},
 					{64 * 1024, 127},
 				},
-				.block_erase = erase_block_shifted_jedec,
+				.block_erase = erase_block_jedec,
 			}, {
 				.eraseblocks = { {8 * 1024 * 1024, 1} },
-				.block_erase = erase_chip_block_shifted_jedec,
+				.block_erase = erase_chip_block_jedec,
 			},
 		},
 		.write		= write_en29lv640b,
@@ -5078,10 +5078,10 @@  const struct flashchip flashchips[] = {
 		.model_id	= FUJITSU_MBM29F400BC,
 		.total_size	= 512,
 		.page_size	= 64 * 1024,
-		.feature_bits	= FEATURE_ADDR_SHIFTED | FEATURE_EITHER_RESET,
+		.feature_bits	= FEATURE_ADDR_SHIFTED | FEATURE_ADDR_2AA | FEATURE_EITHER_RESET,
 		.tested		= TEST_UNTESTED,
-		.probe		= probe_m29f400bt,
-		.probe_timing	= TIMING_IGNORED, /* routine doesn't use probe_timing (m29f400bt.c) */
+		.probe		= probe_jedec,
+		.probe_timing	= 10, // FIXME: check datasheet. Using the 10 us from probe_m29f400bt
 		.block_erasers	=
 		{
 			{
@@ -5091,13 +5091,13 @@  const struct flashchip flashchips[] = {
 					{32 * 1024, 1},
 					{64 * 1024, 7},
 				},
-				.block_erase = erase_block_shifted_jedec,
+				.block_erase = erase_sector_jedec,
 			}, {
 				.eraseblocks = { {512 * 1024, 1} },
-				.block_erase = erase_chip_block_shifted_jedec,
+				.block_erase = erase_chip_block_jedec,
 			},
 		},
-		.write		= write_m29f400bt,
+		.write		= write_jedec_1,
 		.read		= read_memmapped,
 		.voltage	= {4750, 5250}, /* 4.75-5.25V for type -55, others 4.5-5.5V */
 	},
@@ -5110,10 +5110,10 @@  const struct flashchip flashchips[] = {
 		.model_id	= FUJITSU_MBM29F400TC,
 		.total_size	= 512,
 		.page_size	= 64 * 1024,
-		.feature_bits	= FEATURE_ADDR_SHIFTED | FEATURE_EITHER_RESET,
+		.feature_bits	= FEATURE_ADDR_SHIFTED | FEATURE_ADDR_AAA | FEATURE_EITHER_RESET,
 		.tested		= TEST_UNTESTED,
-		.probe		= probe_m29f400bt,
-		.probe_timing	= TIMING_IGNORED, /* routine doesn't use probe_timing (m29f400bt.c) */
+		.probe		= probe_jedec,
+		.probe_timing	= 10, // FIXME: check datasheet. Using the 10 us from probe_m29f400bt
 		.block_erasers	=
 		{
 			{
@@ -5123,13 +5123,13 @@  const struct flashchip flashchips[] = {
 					{8 * 1024, 2},
 					{16 * 1024, 1},
 				},
-				.block_erase = erase_block_shifted_jedec,
+				.block_erase = erase_sector_jedec,
 			}, {
 				.eraseblocks = { {512 * 1024, 1} },
-				.block_erase = erase_chip_block_shifted_jedec,
+				.block_erase = erase_chip_block_jedec,
 			},
 		},
-		.write		= write_m29f400bt,
+		.write		= write_jedec_1,
 		.read		= read_memmapped,
 		.voltage	= {4750, 5250}, /* 4.75-5.25V for type -55, others 4.5-5.5V */
 	},
@@ -5144,8 +5144,8 @@  const struct flashchip flashchips[] = {
 		.page_size	= 0,
 		.feature_bits	= FEATURE_ADDR_SHIFTED | FEATURE_SHORT_RESET,
 		.tested		= TEST_UNTESTED,
-		.probe		= probe_m29f400bt,
-		.probe_timing	= TIMING_IGNORED,
+		.probe		= probe_jedec,
+		.probe_timing	= 10, // FIXME: check datasheet. Using the 10 us from probe_m29f400bt
 		.block_erasers	=
 		{
 			{
@@ -5155,13 +5155,13 @@  const struct flashchip flashchips[] = {
 					{32 * 1024, 1},
 					{64 * 1024, 31},
 				},
-				.block_erase = erase_block_shifted_jedec,
+				.block_erase = erase_block_jedec,
 			}, {
 				.eraseblocks = { {2048 * 1024, 1} },
-				.block_erase = erase_chip_block_shifted_jedec,
+				.block_erase = erase_chip_block_jedec,
 			},
 		},
-		.write		= write_m29f400bt, /* Supports a fast mode too */
+		.write		= write_jedec_1, /* Supports a fast mode too */
 		.read		= read_memmapped,
 		.voltage	= {3000, 3600}, /* 3.0-3.6V for type -70, others 2.7-3.6V */
 	},
@@ -5176,8 +5176,8 @@  const struct flashchip flashchips[] = {
 		.page_size	= 0,
 		.feature_bits	= FEATURE_ADDR_SHIFTED | FEATURE_SHORT_RESET,
 		.tested		= TEST_UNTESTED,
-		.probe		= probe_m29f400bt,
-		.probe_timing	= TIMING_IGNORED,
+		.probe		= probe_jedec,
+		.probe_timing	= 10, // FIXME: check datasheet. Using the 10 us from probe_m29f400bt
 		.block_erasers	=
 		{
 			{
@@ -5187,13 +5187,13 @@  const struct flashchip flashchips[] = {
 					{8 * 1024, 2},
 					{16 * 1024, 1},
 				},
-				.block_erase = erase_block_shifted_jedec,
+				.block_erase = erase_block_jedec,
 			}, {
 				.eraseblocks = { {2048 * 1024, 1} },
-				.block_erase = erase_chip_block_shifted_jedec,
+				.block_erase = erase_chip_block_jedec,
 			},
 		},
-		.write		= write_m29f400bt, /* Supports a fast mode too */
+		.write		= write_jedec_1, /* Supports a fast mode too */
 		.read		= read_memmapped,
 		.voltage	= {3000, 3600}, /* 3.0-3.6V for type -70, others 2.7-3.6V */
 	},
@@ -12178,10 +12178,10 @@  const struct flashchip flashchips[] = {
 		.model_id	= ST_M29F400BB,
 		.total_size	= 512,
 		.page_size	= 64 * 1024,
-		.feature_bits	= FEATURE_ADDR_SHIFTED | FEATURE_EITHER_RESET,
+		.feature_bits	= FEATURE_ADDR_SHIFTED | FEATURE_ADDR_2AA | FEATURE_EITHER_RESET,
 		.tested		= TEST_UNTESTED,
-		.probe		= probe_m29f400bt,
-		.probe_timing	= TIMING_IGNORED, /* routine doesn't use probe_timing (m29f400bt.c) */
+		.probe		= probe_jedec,
+		.probe_timing	= 10, // FIXME: check datasheet. Using the 10 us from probe_m29f400bt
 		.block_erasers	=
 		{
 			{
@@ -12191,13 +12191,13 @@  const struct flashchip flashchips[] = {
 					{32 * 1024, 1},
 					{64 * 1024, 7},
 				},
-				.block_erase = erase_block_shifted_jedec,
+				.block_erase = erase_sector_jedec,
 			}, {
 				.eraseblocks = { {512 * 1024, 1} },
-				.block_erase = erase_chip_block_shifted_jedec,
+				.block_erase = erase_chip_block_jedec,
 			}
 		},
-		.write		= write_m29f400bt,
+		.write		= write_jedec_1,
 		.read		= read_memmapped,
 		.voltage	= {4500, 5500},
 	},
@@ -12210,10 +12210,10 @@  const struct flashchip flashchips[] = {
 		.model_id	= ST_M29F400BT,
 		.total_size	= 512,
 		.page_size	= 64 * 1024,
-		.feature_bits	= FEATURE_ADDR_SHIFTED | FEATURE_EITHER_RESET,
+		.feature_bits	= FEATURE_ADDR_SHIFTED | FEATURE_ADDR_2AA | FEATURE_EITHER_RESET,
 		.tested		= TEST_UNTESTED,
-		.probe		= probe_m29f400bt,
-		.probe_timing	= TIMING_IGNORED, /* routine doesn't use probe_timing (m29f400bt.c) */
+		.probe		= probe_jedec,
+		.probe_timing	= 10, // FIXME: check datasheet. Using the 10 us from probe_m29f400bt
 		.block_erasers	=
 		{
 			{
@@ -12223,13 +12223,13 @@  const struct flashchip flashchips[] = {
 					{8 * 1024, 2},
 					{16 * 1024, 1},
 				},
-				.block_erase = erase_block_shifted_jedec,
+				.block_erase = erase_sector_jedec,
 			}, {
 				.eraseblocks = { {512 * 1024, 1} },
-				.block_erase = erase_chip_block_shifted_jedec,
+				.block_erase = erase_chip_block_jedec,
 			}
 		},
-		.write		= write_m29f400bt,
+		.write		= write_jedec_1,
 		.read		= read_memmapped,
 		.voltage	= {4500, 5500},
 	},
diff --git a/flashchips.h b/flashchips.h
index f0fbf4b..93daeb4 100644
--- a/flashchips.h
+++ b/flashchips.h
@@ -295,6 +295,8 @@ 
 #define EON_EN29LV010		0x7F6E
 #define EON_EN29LV040A		0x7F4F	/* EN29LV040(A) */
 #define EON_EN29LV640B		0xCB
+#define EON_EN29LV640T		0xC9
+#define EON_EN29LV640U		0x7E
 #define EON_EN29F002T		0x7F92	/* Same as EN29F002A */
 #define EON_EN29F002B		0x7F97	/* Same as EN29F002AN */
 #define EON_EN29GL064HL		0x7E0C01	/* Uniform Sectors, WP protects Top OR Bottom sector */
diff --git a/jedec.c b/jedec.c
index 59bec6f..358b850 100644
--- a/jedec.c
+++ b/jedec.c
@@ -4,7 +4,7 @@ 
  * Copyright (C) 2000 Silicon Integrated System Corporation
  * Copyright (C) 2006 Giampiero Giancipoli <gianci@email.it>
  * Copyright (C) 2006 coresystems GmbH <info@coresystems.de>
- * Copyright (C) 2007, 2011 Carl-Daniel Hailfinger
+ * Copyright (C) 2007-2012 Carl-Daniel Hailfinger
  * Copyright (C) 2009 Sean Nelson <audiohacked@gmail.com>
  * Copyright (C) 2014 Stefan Tauner
  *
@@ -116,9 +116,11 @@  static unsigned int getaddrmask(const struct flashchip *chip)
 static void start_program_jedec_common(const struct flashctx *flash, unsigned int mask)
 {
 	chipaddr bios = flash->virtual_memory;
-	chip_writeb(flash, 0xAA, bios + (0x5555 & mask));
-	chip_writeb(flash, 0x55, bios + (0x2AAA & mask));
-	chip_writeb(flash, 0xA0, bios + (0x5555 & mask));
+	bool shifted = (flash->chip->feature_bits & FEATURE_ADDR_SHIFTED);
+
+	chip_writeb(flash, 0xAA, bios + ((shifted ? 0x2AAA : 0x5555) & mask));
+	chip_writeb(flash, 0x55, bios + ((shifted ? 0x5555 : 0x2AAA) & mask));
+	chip_writeb(flash, 0xA0, bios + ((shifted ? 0x2AAA : 0x5555) & mask));
 }
 
 int probe_jedec_29gl(struct flashctx *flash)
@@ -174,6 +176,7 @@  static int probe_jedec_common(struct flashctx *flash, unsigned int mask)
 {
 	chipaddr bios = flash->virtual_memory;
 	const struct flashchip *chip = flash->chip;
+	bool shifted = (flash->chip->feature_bits & FEATURE_ADDR_SHIFTED);
 	uint8_t id1, id2;
 	uint32_t largeid1, largeid2;
 	uint32_t flashcontent1, flashcontent2;
@@ -203,31 +206,31 @@  static int probe_jedec_common(struct flashctx *flash, unsigned int mask)
 	/* Reset chip to a clean slate */
 	if ((chip->feature_bits & FEATURE_RESET_MASK) == FEATURE_LONG_RESET)
 	{
-		chip_writeb(flash, 0xAA, bios + (0x5555 & mask));
+		chip_writeb(flash, 0xAA, bios + ((shifted ? 0x2AAA : 0x5555) & mask));
 		if (probe_timing_exit)
 			programmer_delay(10);
-		chip_writeb(flash, 0x55, bios + (0x2AAA & mask));
+		chip_writeb(flash, 0x55, bios + ((shifted ? 0x5555 : 0x2AAA) & mask));
 		if (probe_timing_exit)
 			programmer_delay(10);
 	}
-	chip_writeb(flash, 0xF0, bios + (0x5555 & mask));
+	chip_writeb(flash, 0xF0, bios + ((shifted ? 0x2AAA : 0x5555) & mask));
 	if (probe_timing_exit)
 		programmer_delay(probe_timing_exit);
 
 	/* Issue JEDEC Product ID Entry command */
-	chip_writeb(flash, 0xAA, bios + (0x5555 & mask));
+	chip_writeb(flash, 0xAA, bios + ((shifted ? 0x2AAA : 0x5555) & mask));
 	if (probe_timing_enter)
 		programmer_delay(10);
-	chip_writeb(flash, 0x55, bios + (0x2AAA & mask));
+	chip_writeb(flash, 0x55, bios + ((shifted ? 0x5555 : 0x2AAA) & mask));
 	if (probe_timing_enter)
 		programmer_delay(10);
-	chip_writeb(flash, 0x90, bios + (0x5555 & mask));
+	chip_writeb(flash, 0x90, bios + ((shifted ? 0x2AAA : 0x5555) & mask));
 	if (probe_timing_enter)
 		programmer_delay(probe_timing_enter);
 
 	/* Read product ID */
-	id1 = chip_readb(flash, bios);
-	id2 = chip_readb(flash, bios + 0x01);
+	id1 = chip_readb(flash, bios + (0x00 << shifted));
+	id2 = chip_readb(flash, bios + (0x01 << shifted));
 	largeid1 = id1;
 	largeid2 = id2;
 
@@ -246,14 +249,14 @@  static int probe_jedec_common(struct flashctx *flash, unsigned int mask)
 	/* Issue JEDEC Product ID Exit command */
 	if ((chip->feature_bits & FEATURE_RESET_MASK) == FEATURE_LONG_RESET)
 	{
-		chip_writeb(flash, 0xAA, bios + (0x5555 & mask));
+		chip_writeb(flash, 0xAA, bios + ((shifted ? 0x2AAA : 0x5555) & mask));
 		if (probe_timing_exit)
 			programmer_delay(10);
-		chip_writeb(flash, 0x55, bios + (0x2AAA & mask));
+		chip_writeb(flash, 0x55, bios + ((shifted ? 0x5555 : 0x2AAA) & mask));
 		if (probe_timing_exit)
 			programmer_delay(10);
 	}
-	chip_writeb(flash, 0xF0, bios + (0x5555 & mask));
+	chip_writeb(flash, 0xF0, bios + ((shifted ? 0x2AAA : 0x5555) & mask));
 	if (probe_timing_exit)
 		programmer_delay(probe_timing_exit);
 
@@ -262,8 +265,8 @@  static int probe_jedec_common(struct flashctx *flash, unsigned int mask)
 		msg_cdbg(", id1 parity violation");
 
 	/* Read the product ID location again. We should now see normal flash contents. */
-	flashcontent1 = chip_readb(flash, bios);
-	flashcontent2 = chip_readb(flash, bios + 0x01);
+	flashcontent1 = chip_readb(flash, bios + (0x00 << shifted));
+	flashcontent2 = chip_readb(flash, bios + (0x01 << shifted));
 
 	/* Check if it is a continuation ID, this should be a while loop. */
 	if (flashcontent1 == 0x7F) {
@@ -294,21 +297,23 @@  static int erase_sector_jedec_common(struct flashctx *flash, unsigned int page,
 				     unsigned int pagesize, unsigned int mask)
 {
 	chipaddr bios = flash->virtual_memory;
+	bool shifted = (flash->chip->feature_bits & FEATURE_ADDR_SHIFTED);
 	unsigned int delay_us = 0;
+
 	if(flash->chip->probe_timing != TIMING_ZERO)
 		delay_us = 10;
 
 	/*  Issue the Sector Erase command   */
-	chip_writeb(flash, 0xAA, bios + (0x5555 & mask));
+	chip_writeb(flash, 0xAA, bios + ((shifted ? 0x2AAA : 0x5555) & mask));
 	programmer_delay(delay_us);
-	chip_writeb(flash, 0x55, bios + (0x2AAA & mask));
+	chip_writeb(flash, 0x55, bios + ((shifted ? 0x5555 : 0x2AAA) & mask));
 	programmer_delay(delay_us);
-	chip_writeb(flash, 0x80, bios + (0x5555 & mask));
+	chip_writeb(flash, 0x80, bios + ((shifted ? 0x2AAA : 0x5555) & mask));
 	programmer_delay(delay_us);
 
-	chip_writeb(flash, 0xAA, bios + (0x5555 & mask));
+	chip_writeb(flash, 0xAA, bios + ((shifted ? 0x2AAA : 0x5555) & mask));
 	programmer_delay(delay_us);
-	chip_writeb(flash, 0x55, bios + (0x2AAA & mask));
+	chip_writeb(flash, 0x55, bios + ((shifted ? 0x5555 : 0x2AAA) & mask));
 	programmer_delay(delay_us);
 	chip_writeb(flash, 0x30, bios + page);
 	programmer_delay(delay_us);
@@ -324,21 +329,23 @@  static int erase_block_jedec_common(struct flashctx *flash, unsigned int block,
 				    unsigned int blocksize, unsigned int mask)
 {
 	chipaddr bios = flash->virtual_memory;
+	bool shifted = (flash->chip->feature_bits & FEATURE_ADDR_SHIFTED);
 	unsigned int delay_us = 0;
+
 	if(flash->chip->probe_timing != TIMING_ZERO)
 		delay_us = 10;
 
 	/*  Issue the Sector Erase command   */
-	chip_writeb(flash, 0xAA, bios + (0x5555 & mask));
+	chip_writeb(flash, 0xAA, bios + ((shifted ? 0x2AAA : 0x5555) & mask));
 	programmer_delay(delay_us);
-	chip_writeb(flash, 0x55, bios + (0x2AAA & mask));
+	chip_writeb(flash, 0x55, bios + ((shifted ? 0x5555 : 0x2AAA) & mask));
 	programmer_delay(delay_us);
-	chip_writeb(flash, 0x80, bios + (0x5555 & mask));
+	chip_writeb(flash, 0x80, bios + ((shifted ? 0x2AAA : 0x5555) & mask));
 	programmer_delay(delay_us);
 
-	chip_writeb(flash, 0xAA, bios + (0x5555 & mask));
+	chip_writeb(flash, 0xAA, bios + ((shifted ? 0x2AAA : 0x5555) & mask));
 	programmer_delay(delay_us);
-	chip_writeb(flash, 0x55, bios + (0x2AAA & mask));
+	chip_writeb(flash, 0x55, bios + ((shifted ? 0x5555 : 0x2AAA) & mask));
 	programmer_delay(delay_us);
 	chip_writeb(flash, 0x50, bios + block);
 	programmer_delay(delay_us);
@@ -353,23 +360,25 @@  static int erase_block_jedec_common(struct flashctx *flash, unsigned int block,
 static int erase_chip_jedec_common(struct flashctx *flash, unsigned int mask)
 {
 	chipaddr bios = flash->virtual_memory;
+	bool shifted = (flash->chip->feature_bits & FEATURE_ADDR_SHIFTED);
 	unsigned int delay_us = 0;
+
 	if(flash->chip->probe_timing != TIMING_ZERO)
 		delay_us = 10;
 
 	/*  Issue the JEDEC Chip Erase command   */
-	chip_writeb(flash, 0xAA, bios + (0x5555 & mask));
+	chip_writeb(flash, 0xAA, bios + ((shifted ? 0x2AAA : 0x5555) & mask));
 	programmer_delay(delay_us);
-	chip_writeb(flash, 0x55, bios + (0x2AAA & mask));
+	chip_writeb(flash, 0x55, bios + ((shifted ? 0x5555 : 0x2AAA) & mask));
 	programmer_delay(delay_us);
-	chip_writeb(flash, 0x80, bios + (0x5555 & mask));
+	chip_writeb(flash, 0x80, bios + ((shifted ? 0x2AAA : 0x5555) & mask));
 	programmer_delay(delay_us);
 
-	chip_writeb(flash, 0xAA, bios + (0x5555 & mask));
+	chip_writeb(flash, 0xAA, bios + ((shifted ? 0x2AAA : 0x5555) & mask));
 	programmer_delay(delay_us);
-	chip_writeb(flash, 0x55, bios + (0x2AAA & mask));
+	chip_writeb(flash, 0x55, bios + ((shifted ? 0x5555 : 0x2AAA) & mask));
 	programmer_delay(delay_us);
-	chip_writeb(flash, 0x10, bios + (0x5555 & mask));
+	chip_writeb(flash, 0x10, bios + ((shifted ? 0x2AAA : 0x5555) & mask));
 	programmer_delay(delay_us);
 
 	toggle_ready_jedec_slow(flash, bios);
diff --git a/m29f400bt.c b/m29f400bt.c
deleted file mode 100644
index 399a7e0..0000000
--- a/m29f400bt.c
+++ /dev/null
@@ -1,87 +0,0 @@ 
-/*
- * This file is part of the flashrom project.
- *
- * Copyright (C) 2000 Silicon Integrated System Corporation
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301 USA
- */
-
-#include "flash.h"
-#include "chipdrivers.h"
-
-/* WARNING! 
-   This chip uses the standard JEDEC Addresses in 16-bit mode as word
-   addresses. In byte mode, 0xAAA has to be used instead of 0x555 and
-   0x555 instead of 0x2AA. Do *not* blindly replace with standard JEDEC
-   functions. */
-
-/* chunksize is 1 */
-int write_m29f400bt(struct flashctx *flash, const uint8_t *src, unsigned int start, unsigned int len)
-{
-	int i;
-	chipaddr bios = flash->virtual_memory;
-	chipaddr dst = flash->virtual_memory + start;
-
-	for (i = 0; i < len; i++) {
-		chip_writeb(flash, 0xAA, bios + 0xAAA);
-		chip_writeb(flash, 0x55, bios + 0x555);
-		chip_writeb(flash, 0xA0, bios + 0xAAA);
-
-		/* transfer data from source to destination */
-		chip_writeb(flash, *src, dst);
-		toggle_ready_jedec(flash, dst);
-#if 0
-		/* We only want to print something in the error case. */
-		msg_cerr("Value in the flash at address 0x%lx = %#x, want %#x\n",
-		     (dst - bios), chip_readb(flash, dst), *src);
-#endif
-		dst++;
-		src++;
-	}
-
-	/* FIXME: Ignore errors for now. */
-	return 0;
-}
-
-int probe_m29f400bt(struct flashctx *flash)
-{
-	chipaddr bios = flash->virtual_memory;
-	uint8_t id1, id2;
-
-	chip_writeb(flash, 0xAA, bios + 0xAAA);
-	chip_writeb(flash, 0x55, bios + 0x555);
-	chip_writeb(flash, 0x90, bios + 0xAAA);
-
-	programmer_delay(10);
-
-	id1 = chip_readb(flash, bios);
-	/* The data sheet says id2 is at (bios + 0x01) and id2 listed in
-	 * flash.h does not match. It should be possible to use JEDEC probe.
-	 */
-	id2 = chip_readb(flash, bios + 0x02);
-
-	chip_writeb(flash, 0xAA, bios + 0xAAA);
-	chip_writeb(flash, 0x55, bios + 0x555);
-	chip_writeb(flash, 0xF0, bios + 0xAAA);
-
-	programmer_delay(10);
-
-	msg_cdbg("%s: id1 0x%02x, id2 0x%02x\n", __func__, id1, id2);
-
-	if (id1 == flash->chip->manufacture_id && id2 == flash->chip->model_id)
-		return 1;
-
-	return 0;
-}