>From beef2e6a1fc2142e5ddd5f4681ebae48f0fac4e6 Mon Sep 17 00:00:00 2001
From: Stefan Tauner <stefan.tauner@alumni.tuwien.ac.at>
Date: Thu, 1 May 2014 11:05:04 +0200
Subject: [PATCH] Add support for ESMT F25L32PA.

Signed-off-by: Stefan Tauner <stefan.tauner@alumni.tuwien.ac.at>
---
 chipdrivers.h     |  1 +
 flashchips.c      | 35 +++++++++++++++++++++++++++++++++++
 flashchips.h      |  1 +
 spi25_statusreg.c | 13 +++++++++++++
 4 files changed, 50 insertions(+)

diff --git a/chipdrivers.h b/chipdrivers.h
index 851e90a..5adc58c 100644
--- a/chipdrivers.h
+++ b/chipdrivers.h
@@ -39,70 +39,71 @@ int probe_spi_rems(struct flashctx *flash);
 int probe_spi_res1(struct flashctx *flash);
 int probe_spi_res2(struct flashctx *flash);
 int probe_spi_res3(struct flashctx *flash);
 int probe_spi_at25f(struct flashctx *flash);
 int spi_write_enable(struct flashctx *flash);
 int spi_write_disable(struct flashctx *flash);
 int spi_block_erase_20(struct flashctx *flash, unsigned int addr, unsigned int blocklen);
 int spi_block_erase_50(struct flashctx *flash, unsigned int addr, unsigned int blocklen);
 int spi_block_erase_52(struct flashctx *flash, unsigned int addr, unsigned int blocklen);
 int spi_block_erase_60(struct flashctx *flash, unsigned int addr, unsigned int blocklen);
 int spi_block_erase_62(struct flashctx *flash, unsigned int addr, unsigned int blocklen);
 int spi_block_erase_81(struct flashctx *flash, unsigned int addr, unsigned int blocklen);
 int spi_block_erase_c4(struct flashctx *flash, unsigned int addr, unsigned int blocklen);
 int spi_block_erase_c7(struct flashctx *flash, unsigned int addr, unsigned int blocklen);
 int spi_block_erase_d7(struct flashctx *flash, unsigned int addr, unsigned int blocklen);
 int spi_block_erase_d8(struct flashctx *flash, unsigned int addr, unsigned int blocklen);
 int spi_block_erase_db(struct flashctx *flash, unsigned int addr, unsigned int blocklen);
 erasefunc_t *spi_get_erasefn_from_opcode(uint8_t opcode);
 int spi_chip_write_1(struct flashctx *flash, uint8_t *buf, unsigned int start, unsigned int len);
 int spi_byte_program(struct flashctx *flash, unsigned int addr, uint8_t databyte);
 int spi_nbyte_program(struct flashctx *flash, unsigned int addr, uint8_t *bytes, unsigned int len);
 int spi_nbyte_read(struct flashctx *flash, unsigned int addr, uint8_t *bytes, unsigned int len);
 int spi_read_chunked(struct flashctx *flash, uint8_t *buf, unsigned int start, unsigned int len, unsigned int chunksize);
 int spi_write_chunked(struct flashctx *flash, uint8_t *buf, unsigned int start, unsigned int len, unsigned int chunksize);
 
 /* spi25_statusreg.c */
 uint8_t spi_read_status_register(struct flashctx *flash);
 int spi_write_status_register(struct flashctx *flash, int status);
 void spi_prettyprint_status_register_bit(uint8_t status, int bit);
 int spi_prettyprint_status_register_plain(struct flashctx *flash);
 int spi_prettyprint_status_register_default_welwip(struct flashctx *flash);
 int spi_prettyprint_status_register_default_bp1(struct flashctx *flash);
 int spi_prettyprint_status_register_default_bp2(struct flashctx *flash);
 int spi_prettyprint_status_register_default_bp3(struct flashctx *flash);
 int spi_prettyprint_status_register_default_bp4(struct flashctx *flash);
+int spi_prettyprint_status_register_bp2_bpl(struct flashctx *flash);
 int spi_disable_blockprotect(struct flashctx *flash);
 int spi_disable_blockprotect_bp2_srwd(struct flashctx *flash);
 int spi_disable_blockprotect_bp3_srwd(struct flashctx *flash);
 int spi_disable_blockprotect_bp4_srwd(struct flashctx *flash);
 int spi_prettyprint_status_register_amic_a25l032(struct flashctx *flash);
 int spi_prettyprint_status_register_at25df(struct flashctx *flash);
 int spi_prettyprint_status_register_at25df_sec(struct flashctx *flash);
 int spi_prettyprint_status_register_at25f(struct flashctx *flash);
 int spi_prettyprint_status_register_at25f512a(struct flashctx *flash);
 int spi_prettyprint_status_register_at25f512b(struct flashctx *flash);
 int spi_prettyprint_status_register_at25f4096(struct flashctx *flash);
 int spi_prettyprint_status_register_at25fs010(struct flashctx *flash);
 int spi_prettyprint_status_register_at25fs040(struct flashctx *flash);
 int spi_prettyprint_status_register_at26df081a(struct flashctx *flash);
 int spi_disable_blockprotect_at2x_global_unprotect(struct flashctx *flash);
 int spi_disable_blockprotect_at2x_global_unprotect_sec(struct flashctx *flash);
 int spi_disable_blockprotect_at25f(struct flashctx *flash);
 int spi_disable_blockprotect_at25f512a(struct flashctx *flash);
 int spi_disable_blockprotect_at25f512b(struct flashctx *flash);
 int spi_disable_blockprotect_at25fs010(struct flashctx *flash);
 int spi_disable_blockprotect_at25fs040(struct flashctx *flash);
 int spi_prettyprint_status_register_en25s_wp(struct flashctx *flash);
 int spi_prettyprint_status_register_n25q(struct flashctx *flash);
 int spi_disable_blockprotect_n25q(struct flashctx *flash);
 int spi_prettyprint_status_register_bp2_ep_srwd(struct flashctx *flash);
 int spi_disable_blockprotect_bp2_ep_srwd(struct flashctx *flash);
 int spi_prettyprint_status_register_sst25(struct flashctx *flash);
 int spi_prettyprint_status_register_sst25vf016(struct flashctx *flash);
 int spi_prettyprint_status_register_sst25vf040b(struct flashctx *flash);
 
 /* sfdp.c */
 int probe_spi_sfdp(struct flashctx *flash);
 
 /* opaque.c */
 int probe_opaque(struct flashctx *flash);
diff --git a/flashchips.c b/flashchips.c
index a6db11e..f10f0f9 100644
--- a/flashchips.c
+++ b/flashchips.c
@@ -3086,70 +3086,105 @@ const struct flashchip flashchips[] = {
 		.vendor		= "ESMT",
 		.name		= "F25L008A",
 		.bustype	= BUS_SPI,
 		.manufacture_id	= ESMT_ID,
 		.model_id	= ESMT_F25L008A,
 		.total_size	= 1024,
 		.page_size	= 256,
 		.feature_bits	= FEATURE_WRSR_EITHER,
 		.tested		= TEST_OK_PREW,
 		.probe		= probe_spi_rdid,
 		.probe_timing	= TIMING_ZERO,
 		.block_erasers	=
 		{
 			{
 				.eraseblocks = { {4 * 1024, 256} },
 				.block_erase = spi_block_erase_20,
 			}, {
 				.eraseblocks = { {64 * 1024, 16} },
 				.block_erase = spi_block_erase_d8,
 			}, {
 				.eraseblocks = { {1024 * 1024, 1} },
 				.block_erase = spi_block_erase_60,
 			}, {
 				.eraseblocks = { {1024 * 1024, 1} },
 				.block_erase = spi_block_erase_c7,
 			}
 		},
 		.printlock	= spi_prettyprint_status_register_plain, /* TODO: improve */
 		.unlock		= spi_disable_blockprotect,
 		.write		= spi_chip_write_1,
 		.read		= spi_chip_read,
 		.voltage	= {2700, 3600},
 	},
 
 	{
+		.vendor		= "ESMT",
+		.name		= "F25L32PA",
+		.bustype	= BUS_SPI,
+		.manufacture_id	= ESMT_ID,
+		.model_id	= ESMT_F25L32PA,
+		.total_size	= 4096,
+		.page_size	= 256,
+		.feature_bits	= FEATURE_WRSR_EITHER | FEATURE_OTP,
+		.tested		= TEST_UNTESTED,
+		.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_d8,
+			}, {
+				.eraseblocks = { {4 * 1024 * 1024, 1} },
+				.block_erase = spi_block_erase_60,
+			}, {
+				.eraseblocks = { {4 * 1024 * 1024, 1} },
+				.block_erase = spi_block_erase_c7,
+			}
+		},
+		.printlock	= spi_prettyprint_status_register_bp2_bpl,
+		.unlock		= spi_disable_blockprotect,
+		.write		= spi_chip_write_256,
+		.read		= spi_chip_read,
+		.voltage	= {2700, 3600},
+	},
+
+	{
 		.vendor		= "Eon",
 		.name		= "EN25B05",
 		.bustype	= BUS_SPI,
 		.manufacture_id	= EON_ID_NOPREFIX,
 		.model_id	= EON_EN25B05,
 		.total_size	= 64,
 		.page_size	= 256,
 		.feature_bits	= FEATURE_WRSR_WREN,
 		.tested		= TEST_UNTESTED,
 		.probe		= probe_spi_rdid,
 		.probe_timing	= TIMING_ZERO,
 		.block_erasers	=
 		{
 			{
 				.eraseblocks = {
 					{4 * 1024, 2},
 					{8 * 1024, 1},
 					{16 * 1024, 1},
 					{32 * 1024, 1},
 				},
 				.block_erase = spi_block_erase_d8,
 			}, {
 				.eraseblocks = { {64 * 1024, 1} },
 				.block_erase = spi_block_erase_c7,
 			}
 		},
 		.printlock	= spi_prettyprint_status_register_plain, /* TODO: improve */
 		.unlock		= spi_disable_blockprotect,
 		.write		= spi_chip_write_256,
 		.read		= spi_chip_read,
 		.voltage	= {2700, 3600},
 	},
 
 	{
 		.vendor		= "Eon",
diff --git a/flashchips.h b/flashchips.h
index e6e5e8a..a12e470 100644
--- a/flashchips.h
+++ b/flashchips.h
@@ -176,70 +176,71 @@
 #define ATMEL_AT45DB041D	0x2400
 #define ATMEL_AT45DB041E	/* same as above but with EDI 0x0100 */
 #define ATMEL_AT45DB081		/* No ID (opcode) available for AT45DB081, AT45DB081A, AT45DB081B */
 #define ATMEL_AT45DB081D	0x2500
 #define ATMEL_AT45DB081E	/* same as above but with EDI 0x0100 */
 #define ATMEL_AT45DB161		/* No ID (opcode) available for AT45DB161, AT45DB161B */
 #define ATMEL_AT45DB161D	0x2600
 #define ATMEL_AT45DB161E	/* same as above but with EDI 0x0100 */
 #define ATMEL_AT45DB321		/* No ID (opcode) available for AT45DB321, AT45DB321B */
 #define ATMEL_AT45DB321C	0x2700
 #define ATMEL_AT45DB321E	/* same as above but with EDI 0x0100 */
 #define ATMEL_AT45DB321D	0x2701 /* Buggy data sheet */
 #define ATMEL_AT45DB642		/* No ID (opcode) available for AT45DB642 */
 #define ATMEL_AT45DB642D	0x2800
 #define ATMEL_AT49BV512		0x03
 #define ATMEL_AT49F002N		0x07	/* for AT49F002(N)  */
 #define ATMEL_AT49LH002		0xE9
 #define ATMEL_AT49F002NT	0x08	/* for AT49F002(N)T */
 #define ATMEL_AT49F010		0x17	/* Same as AT49HF010 */
 #define ATMEL_AT49F020		0x0B
 #define ATMEL_AT49F040		0x13
 #define ATMEL_AT49F080		0x23
 #define ATMEL_AT49F080T		0x27
 
 /* Bright Microelectronics has the same manufacturer ID as Hyundai... */
 #define BRIGHT_ID		0xAD	/* Bright Microelectronics */
 #define BRIGHT_BM29F040		0x40
 #define BRIGHT_BM29F400B	0xAB
 #define BRIGHT_BM29F400T	0xAD
 
 #define CATALYST_ID		0x31	/* Catalyst */
 #define CATALYST_CAT28F512	0xB8
 
 #define ESMT_ID			0x8C	/* Elite Semiconductor Memory Technology (ESMT) / EFST Elite Flash Storage */
 #define ESMT_F25L008A		0x2014
+#define ESMT_F25L32PA		0x2016
 #define ESMT_F25D08QA		0x2534
 #define ESMT_F25L16QA2S		0x4015
 #define ESMT_F25L32QA		0x4016
 #define ESMT_F25L32QA2S		0x4116
 #define ESMT_F25L64QA		0x4117
 #define ESMT_F25L128QA		0x4118
 #define ESMT_F49B002UA		0x00
 
 /*
  * 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			0x7F1C	/* EON Silicon Devices */
 #define EON_ID_NOPREFIX		0x1C	/* EON, missing 0x7F prefix */
 #define EON_EN25B05		0x2010	/* Same as P05, 2^19 kbit or 2^16 kByte */
 #define EON_EN25B05T		0x25
 #define EON_EN25B05B		0x95
 #define EON_EN25B10		0x2011	/* Same as P10 */
 #define EON_EN25B10T		0x40
 #define EON_EN25B10B		0x30
 #define EON_EN25B20		0x2012	/* Same as P20 */
 #define EON_EN25B20T		0x41
 #define EON_EN25B20B		0x31
 #define EON_EN25B40		0x2013	/* Same as P40 */
 #define EON_EN25B40T		0x42
 #define EON_EN25B40B		0x32
 #define EON_EN25B80		0x2014	/* Same as P80 */
 #define EON_EN25B80T		0x43
 #define EON_EN25B80B		0x33
 #define EON_EN25B16		0x2015	/* Same as P16 */
diff --git a/spi25_statusreg.c b/spi25_statusreg.c
index 48fceb0..4505b82 100644
--- a/spi25_statusreg.c
+++ b/spi25_statusreg.c
@@ -322,70 +322,83 @@ int spi_prettyprint_status_register_default_bp2(struct flashctx *flash)
 	spi_prettyprint_status_register_srwd(status);
 	spi_prettyprint_status_register_bit(status, 6);
 	spi_prettyprint_status_register_bit(status, 5);
 	spi_prettyprint_status_register_bp(status, 2);
 	spi_prettyprint_status_register_welwip(status);
 	return 0;
 }
 
 /* Works for many chips of the
  * ST M25P series
  * MX MX25L series
  */
 int spi_prettyprint_status_register_default_bp3(struct flashctx *flash)
 {
 	uint8_t status = spi_read_status_register(flash);
 	spi_prettyprint_status_register_hex(status);
 
 	spi_prettyprint_status_register_srwd(status);
 	spi_prettyprint_status_register_bit(status, 6);
 	spi_prettyprint_status_register_bp(status, 3);
 	spi_prettyprint_status_register_welwip(status);
 	return 0;
 }
 
 int spi_prettyprint_status_register_default_bp4(struct flashctx *flash)
 {
 	uint8_t status = spi_read_status_register(flash);
 	spi_prettyprint_status_register_hex(status);
 
 	spi_prettyprint_status_register_srwd(status);
 	spi_prettyprint_status_register_bp(status, 4);
 	spi_prettyprint_status_register_welwip(status);
 	return 0;
 }
 
+int spi_prettyprint_status_register_bp2_bpl(struct flashctx *flash)
+{
+	uint8_t status = spi_read_status_register(flash);
+	spi_prettyprint_status_register_hex(status);
+
+	spi_prettyprint_status_register_bpl(status);
+	spi_prettyprint_status_register_bit(status, 6);
+	spi_prettyprint_status_register_bit(status, 5);
+	spi_prettyprint_status_register_bp(status, 2);
+	spi_prettyprint_status_register_welwip(status);
+	return 0;
+}
+
 /* === Amic ===
  * FIXME: spi_disable_blockprotect is incorrect but works fine for chips using
  * spi_prettyprint_status_register_default_bp1 or
  * spi_prettyprint_status_register_default_bp2.
  * FIXME: spi_disable_blockprotect is incorrect and will fail for chips using
  * spi_prettyprint_status_register_amic_a25l032 if those have locks controlled
  * by the second status register.
  */
 
 int spi_prettyprint_status_register_amic_a25l032(struct flashctx *flash)
 {
 	uint8_t status = spi_read_status_register(flash);
 	spi_prettyprint_status_register_hex(status);
 
 	spi_prettyprint_status_register_srwd(status);
 	msg_cdbg("Chip status register: Sector Protect Size (SEC) is %i KB\n", (status & (1 << 6)) ? 4 : 64);
 	msg_cdbg("Chip status register: Top/Bottom (TB) is %s\n", (status & (1 << 5)) ? "bottom" : "top");
 	spi_prettyprint_status_register_bp(status, 2);
 	spi_prettyprint_status_register_welwip(status);
 	msg_cdbg("Chip status register 2 is NOT decoded!\n");
 	return 0;
 }
 
 /* === Atmel === */
 
 static void spi_prettyprint_status_register_atmel_at25_wpen(uint8_t status)
 {
 	msg_cdbg("Chip status register: Write Protect Enable (WPEN) is %sset\n",
 		 (status & (1 << 7)) ? "" : "not ");
 }
 
 static void spi_prettyprint_status_register_atmel_at25_srpl(uint8_t status)
 {
 	msg_cdbg("Chip status register: Sector Protection Register Lock (SRPL) is %sset\n",
 		 (status & (1 << 7)) ? "" : "not ");
-- 
Kind regards, Stefan Tauner

