diff --git a/en29f002a.c b/en29f002a.c
new file mode 100644
index 0000000000000000000000000000000000000000..e2b4f9b09bb4b1eb8c7dbea41df189ca2365f9fe
--- /dev/null
+++ b/en29f002a.c
@@ -0,0 +1,85 @@
+/*
+ * This file is part of the flashrom project.
+ *
+ * Copyright (C) 2007 Carl-Daniel Hailfinger
+ *
+ * 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
+ */
+
+/*
+   EN29F512 has 1C,21
+   EN29F010 has 1C,20
+   EN29F040A has 1C,04
+   EN29LV010 has 1C,6E and uses short F0 reset sequence
+   EN29LV040(A) has 1C,4F and uses short F0 reset sequence
+ */
+int probe_en29f512(struct flashchip *flash)
+{
+	volatile uint8_t *bios = flash->virtual_memory;
+	uint8_t id1, id2;
+
+	*(volatile uint8_t *)(bios + 0x555) = 0xAA;
+	*(volatile uint8_t *)(bios + 0x2AA) = 0x55;
+	*(volatile uint8_t *)(bios + 0x555) = 0x90;
+
+	myusec_delay(10);
+
+	id1 = *(volatile uint8_t *)(bios + 0x100);
+	id2 = *(volatile uint8_t *)(bios + 0x101);
+
+	/* exit by writing F0 anywhere? or the code below */
+	*(volatile uint8_t *)(bios + 0x555) = 0xAA;
+	*(volatile uint8_t *)(bios + 0x2AA) = 0x55;
+	*(volatile uint8_t *)(bios + 0x555) = 0xF0;
+
+	printf_debug("%s: id1 0x%x, id2 0x%x\n", __FUNCTION__, id1, id2);
+
+	if (id1 == flash->manufacture_id && id2 == flash->model_id)
+		return 1;
+
+	return 0;
+}
+
+/*
+   EN29F002AT has 1C,92
+   EN29F002AB has 1C,97
+ */
+int probe_en29f002a(struct flashchip *flash)
+{
+	volatile uint8_t *bios = flash->virtual_memory;
+	uint8_t id1, id2;
+
+	*(volatile uint8_t *)(bios + 0x555) = 0xAA;
+	*(volatile uint8_t *)(bios + 0xAAA) = 0x55;
+	*(volatile uint8_t *)(bios + 0x555) = 0x90;
+
+	myusec_delay(10);
+
+	id1 = *(volatile uint8_t *)(bios + 0x100);
+	id2 = *(volatile uint8_t *)(bios + 0x101);
+
+	/* exit by writing F0 anywhere? or the code below */
+	*(volatile uint8_t *)(bios + 0x555) = 0xAA;
+	*(volatile uint8_t *)(bios + 0xAAA) = 0x55;
+	*(volatile uint8_t *)(bios + 0x555) = 0xF0;
+
+	printf_debug("%s: id1 0x%x, id2 0x%x\n", __FUNCTION__, id1, id2);
+
+	if (id1 == flash->manufacture_id && id2 == flash->model_id)
+		return 1;
+
+	return 0;
+}
+
diff --git a/flash.h b/flash.h
index d8a86dd05691fff91787dac251274f9d231e3f5a..d7c659791d7d540a1e4da86b1a523a3faae737f0 100644
--- a/flash.h
+++ b/flash.h
@@ -32,8 +32,12 @@
 
 struct flashchip {
 	const char *name;
-	int manufacture_id;
-	int model_id;
+	/* With 32bit manufacture_id and model_id we can cover IDs up to
+	 * (including) the 4th bank of JEDEC JEP106W Standard Manufacturer's
+	 * Identification code.
+	 */
+	uint32_t manufacture_id;
+	uint32_t model_id;
 
 	int total_size;
 	int page_size;
@@ -85,8 +89,14 @@ extern struct flashchip flashchips[];
 /*
  * EN25 chips are SPI, first byte of device ID is memory type,
  * second byte of device ID is log(bitsize)-9.
+ * Vendor and device ID of EN29 series are both prefixed with 0x7F, which
+ * is the continuation code for IDs in bank 2.
+ * Vendor ID of EN25 series is NOT prefixed with 0x7F, this results in
+ * a collision with Mitsubishi. Mitsubishi once manufactured flash chips.
+ * Let's hope they are not manufacturing SPI flash chips as well.
  */
-#define EON_ID			0x1C	/* EON Silicon Devices */
+#define EON_ID			0x7F1C	/* EON Silicon Devices */
+#define EON_ID_NOPREFIX		0x1C	/* EON, missing 0x7F prefix */
 #define EN_25B05		0x2010	/* 2^19 kbit or 2^16 kByte */
 #define EN_25B10		0x2011
 #define EN_25B20		0x2012
@@ -94,6 +104,13 @@ extern struct flashchip flashchips[];
 #define EN_25B80		0x2014
 #define EN_25B16		0x2015
 #define EN_25B32		0x2016
+#define EN_29F512		0x7F21
+#define EN_29F010		0x7F20
+#define EN_29F040A		0x7F04
+#define EN_29LV010		0x7F6E
+#define EN_29LV040A		0x7F4F	/* EN_29LV040(A) */
+#define EN_29F002AT		0x7F92
+#define EN_29F002AB		0x7F97
 
 #define FUJITSU_ID		0x04	/* Fujitsu */
 /* MBM29F400TC_STRANGE has a value not mentioned in the data sheet and we
diff --git a/flashchips.c b/flashchips.c
index 2bd039d72596e9c132a99cab5845c8f9ebf6f8fb..71f2d8ef9b49fe80a61c60d51b5ab4cdd4645939 100644
--- a/flashchips.c
+++ b/flashchips.c
@@ -42,6 +42,9 @@ struct flashchip flashchips[] = {
 	 probe_jedec,	erase_chip_jedec, write_jedec},
 	{"At49F002(N)T",ATMEL_ID,	AT_49F002NT,	256, 256,
 	 probe_jedec,	erase_chip_jedec, write_jedec},
+	/* The EN29F002AT can do byte program at arbitrary boundaries. */
+	{"EN29F002AT",	EON_ID,		EN_29F002AT,	256, 256,
+	 probe_jedec,	erase_chip_jedec, write_jedec},
 	{"MBM29F400TC",	FUJITSU_ID,	MBM29F400TC_STRANGE,	512, 64 * 1024,
 	 probe_m29f400bt, erase_m29f400bt, write_linuxbios_m29f400bt},
 	{"MX29F002",	MX_ID,		MX_29F002,	256, 64 * 1024,
diff --git a/jedec.c b/jedec.c
index 30d0cdadd2a97ef077ea067f59be8c84a5443bde..958875194a272b0d872c13090219fc2037a93505 100644
--- a/jedec.c
+++ b/jedec.c
@@ -4,6 +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 Carl-Daniel Hailfinger
  *
  * 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
@@ -82,6 +83,7 @@ int probe_jedec(struct flashchip *flash)
 {
 	volatile uint8_t *bios = flash->virtual_memory;
 	uint8_t id1, id2;
+	uint32_t largeid1, largeid2;
 
 	/* Issue JEDEC Product ID Entry command */
 	*(volatile uint8_t *)(bios + 0x5555) = 0xAA;
@@ -98,6 +100,20 @@ int probe_jedec(struct flashchip *flash)
 	/* Read product ID */
 	id1 = *(volatile uint8_t *)bios;
 	id2 = *(volatile uint8_t *)(bios + 0x01);
+	largeid1 = id1;
+	largeid2 = id2;
+
+	/* Check if it is a continuation ID, this should be a while loop. */
+	if (id1 == 0x7F) {
+		largeid1 <<= 8;
+		id1 = *(volatile uint8_t *)(bios + 0x100);
+		largeid1 |= id1;
+	}
+	if (id2 == 0x7F) {
+		largeid2 <<= 8;
+		id2 = *(volatile uint8_t *)(bios + 0x101);
+		largeid2 |= id2;
+	}
 
 	/* Issue JEDEC Product ID Exit command */
 	*(volatile uint8_t *)(bios + 0x5555) = 0xAA;
@@ -107,8 +123,8 @@ int probe_jedec(struct flashchip *flash)
 	*(volatile uint8_t *)(bios + 0x5555) = 0xF0;
 	myusec_delay(40);
 
-	printf_debug("%s: id1 0x%x, id2 0x%x\n", __FUNCTION__, id1, id2);
-	if (id1 == flash->manufacture_id && id2 == flash->model_id)
+	printf_debug("%s: id1 0x%x, id2 0x%x\n", __FUNCTION__, largeid1, largeid2);
+	if (largeid1 == flash->manufacture_id && largeid2 == flash->model_id)
 		return 1;
 
 	return 0;