Add support for Winbond W39F010/W39L010/W39L020
W39F010 is a 128kB parallel 5V flash chip, 16k bootblocks.
W39L010 is a 128kB parallel 3.3V flash chip, 8k bootblocks.
W39L020 is a 256kB parallel 3.3V flash chip, 64k/16k bootblocks.
The W39F010 code was tested with a satasii programmer. The first write
attempt after an erase returned with verify failure, but the second
write attempt was succesful:
http://paste.flashrom.org/view.php?id=1418
Corresponding to flashrom svn r1620.
Signed-off-by: Kyösti Mälkki <kyosti.malkki@gmail.com>
Acked-by: Stefan Tauner <stefan.tauner@alumni.tuwien.ac.at>
diff --git a/chipdrivers.h b/chipdrivers.h
index f110807..0abc8b9 100644
--- a/chipdrivers.h
+++ b/chipdrivers.h
@@ -143,6 +143,9 @@
int unlock_sst_fwhub(struct flashctx *flash);
/* w39.c */
+int printlock_w39f010(struct flashctx * flash);
+int printlock_w39l010(struct flashctx * flash);
+int printlock_w39l020(struct flashctx * flash);
int printlock_w39l040(struct flashctx * flash);
int printlock_w39v040a(struct flashctx *flash);
int printlock_w39v040b(struct flashctx *flash);
diff --git a/flashchips.c b/flashchips.c
index 937abd3..66411f6 100644
--- a/flashchips.c
+++ b/flashchips.c
@@ -9436,6 +9436,93 @@
{
.vendor = "Winbond",
+ .name = "W39F010",
+ .bustype = BUS_PARALLEL,
+ .manufacture_id = WINBOND_ID,
+ .model_id = WINBOND_W39F010,
+ .total_size = 128,
+ .page_size = 4 * 1024,
+ .feature_bits = FEATURE_EITHER_RESET,
+ .tested = TEST_OK_PREW,
+ .probe = probe_jedec,
+ .probe_timing = 10,
+ .block_erasers =
+ {
+ {
+ .eraseblocks = { {4 * 1024, 32} },
+ .block_erase = erase_block_jedec,
+ }, {
+ .eraseblocks = { {128 * 1024, 1} },
+ .block_erase = erase_chip_block_jedec,
+ }
+ },
+ .printlock = printlock_w39f010,
+ .write = write_jedec_1,
+ .read = read_memmapped,
+ .voltage = {4500, 5500},
+ },
+
+ {
+ .vendor = "Winbond",
+ .name = "W39L010",
+ .bustype = BUS_PARALLEL,
+ .manufacture_id = WINBOND_ID,
+ .model_id = WINBOND_W39L010,
+ .total_size = 128,
+ .page_size = 4 * 1024,
+ .feature_bits = FEATURE_EITHER_RESET,
+ .tested = TEST_UNTESTED,
+ .probe = probe_jedec,
+ .probe_timing = 10,
+ .block_erasers =
+ {
+ {
+ .eraseblocks = { {4 * 1024, 32} },
+ .block_erase = erase_block_jedec,
+ }, {
+ .eraseblocks = { {128 * 1024, 1} },
+ .block_erase = erase_chip_block_jedec,
+ }
+ },
+ .printlock = printlock_w39l010,
+ .write = write_jedec_1,
+ .read = read_memmapped,
+ .voltage = {3000, 3600},
+ },
+
+ {
+ .vendor = "Winbond",
+ .name = "W39L020",
+ .bustype = BUS_PARALLEL,
+ .manufacture_id = WINBOND_ID,
+ .model_id = WINBOND_W39L020,
+ .total_size = 256,
+ .page_size = 4 * 1024,
+ .feature_bits = FEATURE_EITHER_RESET,
+ .tested = TEST_UNTESTED,
+ .probe = probe_jedec,
+ .probe_timing = 10,
+ .block_erasers =
+ {
+ {
+ .eraseblocks = { {4 * 1024, 64} },
+ .block_erase = erase_block_jedec,
+ }, {
+ .eraseblocks = { {64 * 1024, 4} },
+ .block_erase = erase_sector_jedec,
+ }, {
+ .eraseblocks = { {256 * 1024, 1} },
+ .block_erase = erase_chip_block_jedec,
+ }
+ },
+ .printlock = printlock_w39l020,
+ .write = write_jedec_1,
+ .read = read_memmapped,
+ .voltage = {3000, 3600},
+ },
+
+ {
+ .vendor = "Winbond",
.name = "W39L040",
.bustype = BUS_PARALLEL,
.manufacture_id = WINBOND_ID,
diff --git a/flashchips.h b/flashchips.h
index 100d95a..f10fbae 100644
--- a/flashchips.h
+++ b/flashchips.h
@@ -653,6 +653,7 @@
#define WINBOND_W29C020 0x45 /* Same as W29C020C, W29C022 and ASD AE29F2008 */
#define WINBOND_W29C040 0x46 /* Same as W29C040P */
#define WINBOND_W29C512A 0xC8 /* Same as W29EE512 */
+#define WINBOND_W39F010 0xA1
#define WINBOND_W39L010 0x31
#define WINBOND_W39L020 0xB5
#define WINBOND_W39L040 0xB6
diff --git a/w39.c b/w39.c
index da61d23..9dcb06a 100644
--- a/w39.c
+++ b/w39.c
@@ -115,6 +115,15 @@
return 0;
}
+static int printlock_w39_single_bootblock(uint8_t lock, uint16_t kB)
+{
+ msg_cdbg("Software %d kB bootblock locking is %sactive.\n", kB, (lock & 0x03) ? "" : "not ");
+ if (lock & 0x03)
+ return -1;
+
+ return 0;
+}
+
static int printlock_w39_bootblock_64k16k(uint8_t lock)
{
msg_cdbg("Software 64 kB bootblock locking is %sactive.\n",
@@ -160,6 +169,54 @@
return 0;
}
+int printlock_w39f010(struct flashctx *flash)
+{
+ uint8_t lock;
+ int ret;
+
+ lock = w39_idmode_readb(flash, 0x00002);
+ msg_cdbg("Bottom boot block:\n");
+ ret = printlock_w39_single_bootblock(lock, 16);
+
+ lock = w39_idmode_readb(flash, 0x1fff2);
+ msg_cdbg("Top boot block:\n");
+ ret |= printlock_w39_single_bootblock(lock, 16);
+
+ return ret;
+}
+
+int printlock_w39l010(struct flashctx *flash)
+{
+ uint8_t lock;
+ int ret;
+
+ lock = w39_idmode_readb(flash, 0x00002);
+ msg_cdbg("Bottom boot block:\n");
+ ret = printlock_w39_single_bootblock(lock, 8);
+
+ lock = w39_idmode_readb(flash, 0x1fff2);
+ msg_cdbg("Top boot block:\n");
+ ret |= printlock_w39_single_bootblock(lock, 8);
+
+ return ret;
+}
+
+int printlock_w39l020(struct flashctx *flash)
+{
+ uint8_t lock;
+ int ret;
+
+ lock = w39_idmode_readb(flash, 0x00002);
+ msg_cdbg("Bottom boot block:\n");
+ ret = printlock_w39_bootblock_64k16k(lock);
+
+ lock = w39_idmode_readb(flash, 0x3fff2);
+ msg_cdbg("Top boot block:\n");
+ ret |= printlock_w39_bootblock_64k16k(lock);
+
+ return ret;
+}
+
int printlock_w39l040(struct flashctx *flash)
{
uint8_t lock;