Besides the definitions of the the chips in flashchips.c this includes
- a probing method (probe_spi_at25f)
- a pretty printing method (spi_prettyprint_status_register_at25f), and
- an unlocking method (spi_disable_blockprotect_at25f)
Signed-off-by: Stefan Tauner <stefan.tauner(a)student.tuwien.ac.at>
---
at25.c | 97 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++
chipdrivers.h | 3 ++
flashchips.c | 90 ++++++++++++++++++++++++++++++++++++++++++++++++++++
flashchips.h | 10 ++---
spi.h | 9 +++--
5 files changed, 199 insertions(+), 10 deletions(-)
diff --git a/at25.c b/at25.c
index e4bd729..de2a9b7 100644
--- a/at25.c
+++ b/at25.c
@@ -63,6 +63,24 @@ static void spi_prettyprint_status_register_atmel_at25_swp(uint8_t status)
}
}
+/* used for AT25F512(A), AT25F1024(A) */
+int spi_prettyprint_status_register_at25f(struct flashchip *flash)
+{
+ uint8_t status;
+
+ status = spi_read_status_register();
+ msg_cdbg("Chip status register is %02x\n", status);
+
+ spi_prettyprint_status_register_atmel_at25_wpen(status);
+ spi_prettyprint_status_register_bit(status, 6);
+ spi_prettyprint_status_register_bit(status, 5);
+ spi_prettyprint_status_register_bit(status, 4);
+ /* FIXME: Bit 3 is undefined on AT25F512A */
+ spi_prettyprint_status_register_bp(status, 1);
+ spi_prettyprint_status_register_welwip(status);
+ return 0;
+}
+
int spi_prettyprint_status_register_at25df(struct flashchip *flash)
{
uint8_t status;
@@ -154,6 +172,57 @@ int spi_prettyprint_status_register_atmel_at26df081a(struct flashchip *flash)
return 0;
}
+int spi_disable_blockprotect_at25f(struct flashchip *flash)
+{
+ uint8_t status;
+ int result;
+
+ status = spi_read_status_register();
+ /* If block protection is disabled (BP0 and BP1 are 0), stop here. */
+ if ((status & (3 << 2)) == 0)
+ return 0;
+
+ msg_cdbg("Some block protection in effect, disabling\n");
+ if (status & (1 << 7)) {
+ msg_cdbg("Need to disable Write Protect Enable (WPEN)\n");
+ /* The following is used in spi_disable_blockprotect_at25df
+ * to check the state of the hardware lock pin. This is not
+ * possible with this chip, so we have to try.
+ if ((status & (1 << 4)) == 0) {
+ msg_cerr("WP# pin is active, disabling "
+ "write protection is impossible.\n");
+ return 1;
+ }
+ */
+ /* All bits except bit 7 (WPEN) are readonly. If the WP pin is
+ * low, WPEN is readonly and this will fail. */
+ result = spi_write_status_register(flash, status & ~(1 << 7));
+ if (result) {
+ msg_cerr("spi_write_status_register failed\n");
+ return result;
+ }
+ status = spi_read_status_register();
+ if (status & (1 << 7)) {
+ msg_cerr("WP# pin is probably active, disabling "
+ "write protection is impossible.\n");
+ return 1;
+ }
+
+ }
+ /* Global unprotect. Make sure to mask WPEN as well. */
+ result = spi_write_status_register(flash, status & ~0x8c);
+ if (result) {
+ msg_cerr("spi_write_status_register failed\n");
+ return result;
+ }
+ status = spi_read_status_register();
+ if ((status & (3 << 2)) != 0) {
+ msg_cerr("Block protection could not be disabled!\n");
+ return 1;
+ }
+ return 0;
+}
+
int spi_disable_blockprotect_at25df(struct flashchip *flash)
{
uint8_t status;
@@ -276,3 +345,31 @@ int spi_disable_blockprotect_at25fs040(struct flashchip *flash)
}
return 0;
}
+
+int probe_spi_at25f(struct flashchip *flash)
+{
+ static const unsigned char cmd[AT25F_RDID_OUTSIZE] = { AT25F_RDID };
+ unsigned char readarr[AT25F_RDID_INSIZE];
+ uint32_t id1;
+ uint32_t id2;
+
+ if (spi_send_command(sizeof(cmd), sizeof(readarr), cmd, readarr)) {
+ msg_cdbg("\n");
+ return 0;
+ }
+ id1 = readarr[0];
+ id2 = readarr[1];
+
+ msg_cdbg("%s: id1 0x%02x, id2 0x%02x\n", __func__, id1, id2);
+
+ if (id1 == flash->manufacture_id && id2 == flash->model_id) {
+ /* Print the status register to tell the
+ * user about possible write protection.
+ */
+ spi_prettyprint_status_register_at25f(flash);
+
+ return 1;
+ }
+
+ return 0;
+}
diff --git a/chipdrivers.h b/chipdrivers.h
index 7918308..7de17a4 100644
--- a/chipdrivers.h
+++ b/chipdrivers.h
@@ -66,6 +66,7 @@ int spi_prettyprint_status_register_amic_a25lq032(struct flashchip *flash);
/* at25.c */
int spi_prettyprint_status_register_at25df(struct flashchip *flash);
int spi_prettyprint_status_register_at25df_sec(struct flashchip *flash);
+int spi_prettyprint_status_register_at25f(struct flashchip *flash);
int spi_prettyprint_status_register_at25f512b(struct flashchip *flash);
int spi_prettyprint_status_register_at25fs010(struct flashchip *flash);
int spi_prettyprint_status_register_at25fs040(struct flashchip *flash);
@@ -73,8 +74,10 @@ int spi_prettyprint_status_register_atmel_at26df081a(struct flashchip *flash);
int spi_disable_blockprotect_at25df(struct flashchip *flash);
int spi_disable_blockprotect_at25df_sec(struct flashchip *flash);
int spi_disable_blockprotect_at25f512b(struct flashchip *flash);
+int spi_disable_blockprotect_at25f(struct flashchip *flash);
int spi_disable_blockprotect_at25fs010(struct flashchip *flash);
int spi_disable_blockprotect_at25fs040(struct flashchip *flash);
+int probe_spi_at25f(struct flashchip *flash);
/* 82802ab.c */
uint8_t wait_82802ab(struct flashchip *flash);
diff --git a/flashchips.c b/flashchips.c
index e021cbc..b3813a0 100644
--- a/flashchips.c
+++ b/flashchips.c
@@ -1651,6 +1651,65 @@ const struct flashchip flashchips[] = {
{
.vendor = "Atmel",
+ .name = "AT25F512",
+ .bustype = BUS_SPI,
+ .manufacture_id = ATMEL_ID,
+ .model_id = ATMEL_AT25F512,
+ .total_size = 64,
+ .page_size = 256,
+ .feature_bits = FEATURE_WRSR_WREN,
+ .tested = TEST_UNTESTED,
+ .probe = probe_spi_at25f,
+ .probe_timing = TIMING_ZERO,
+ .block_erasers =
+ {
+ {
+ .eraseblocks = { {32 * 1024, 2} },
+ .block_erase = spi_block_erase_52,
+ }, {
+ .eraseblocks = { {64 * 1024, 1} },
+ .block_erase = spi_block_erase_62,
+ }
+ },
+ .printlock = spi_prettyprint_status_register_at25f,
+ .unlock = spi_disable_blockprotect_at25f,
+ .write = spi_chip_write_256,
+ .read = spi_chip_read,
+ .voltage = {2700, 3600},
+ },
+
+ {
+ .vendor = "Atmel",
+ .name = "AT25F512A",
+ .bustype = BUS_SPI,
+ .manufacture_id = ATMEL_ID,
+ .model_id = ATMEL_AT25F512A,
+ .total_size = 64,
+ .page_size = 128,
+ .feature_bits = FEATURE_WRSR_WREN,
+ .tested = TEST_UNTESTED,
+ .probe = probe_spi_at25f,
+ .probe_timing = TIMING_ZERO,
+ .block_erasers =
+ {
+ {
+ .eraseblocks = { {32 * 1024, 2} },
+ .block_erase = spi_block_erase_52,
+ }, {
+ .eraseblocks = { {64 * 1024, 1} },
+ .block_erase = spi_block_erase_62,
+ }
+ },
+ .printlock = spi_prettyprint_status_register_at25f,
+ /* Not correct to use this one, because the BP1 bit is N/A. */
+ .unlock = spi_disable_blockprotect_at25f,
+ .write = spi_chip_write_256,
+ .read = spi_chip_read,
+ .voltage = {2700, 3600},
+ },
+
+ {
+ .vendor = "Atmel",
.name = "AT25F512B",
.bustype = BUS_SPI,
.manufacture_id = ATMEL_ID,
@@ -1693,6 +1752,37 @@ const struct flashchip flashchips[] = {
{
.vendor = "Atmel",
+ /* The A suffix indicates 33MHz instead of 20MHz clock rate.
+ * All other properties seem to be the same.*/
+ .name = "AT25F1024(A)",
+ .bustype = BUS_SPI,
+ .manufacture_id = ATMEL_ID,
+ .model_id = ATMEL_AT25F1024,
+ .total_size = 128,
+ .page_size = 256,
+ .feature_bits = FEATURE_WRSR_WREN,
+ .tested = TEST_OK_PREW,
+ .probe = probe_spi_at25f,
+ .probe_timing = TIMING_ZERO,
+ .block_erasers =
+ {
+ {
+ .eraseblocks = { {32 * 1024, 4} },
+ .block_erase = spi_block_erase_52,
+ }, {
+ .eraseblocks = { {128 * 1024, 1} },
+ .block_erase = spi_block_erase_62,
+ }
+ },
+ .printlock = spi_prettyprint_status_register_at25f,
+ .unlock = spi_disable_blockprotect_at25f,
+ .write = spi_chip_write_256,
+ .read = spi_chip_read,
+ .voltage = {2700, 3600},
+ },
+
+ {
+ .vendor = "Atmel",
.name = "AT25FS010",
.bustype = BUS_SPI,
.manufacture_id = ATMEL_ID,
diff --git a/flashchips.h b/flashchips.h
index ff49d31..6470614 100644
--- a/flashchips.h
+++ b/flashchips.h
@@ -134,13 +134,11 @@
#define ATMEL_AT25DF321A 0x4701
#define ATMEL_AT25DF641 0x4800
#define ATMEL_AT25DQ161 0x8600
-#define ATMEL_AT25F512 /* No device ID found in datasheet. Vendor ID
- * can be read with AT25F512A_RDID */
-#define ATMEL_AT25F512A 0x65 /* Needs AT25F512A_RDID */
+#define ATMEL_AT25F512 0x65 /* guessed, no device ID in datasheet.
+ * Vendor ID can be read with AT25F_RDID */
+#define ATMEL_AT25F512A 0x65 /* Needs AT25F_RDID */
#define ATMEL_AT25F512B 0x6500
-#define ATMEL_AT25F1024 /* No device ID found in datasheet. Vendor ID
- * can be read with AT25F512A_RDID */
-#define ATMEL_AT25F1024A 0x60 /* Needs AT25F512A_RDID */
+#define ATMEL_AT25F1024 0x60 /* Needs AT25F_RDID */
#define ATMEL_AT25FS010 0x6601
#define ATMEL_AT25FS040 0x6604
#define ATMEL_AT26DF041 0x4400
diff --git a/spi.h b/spi.h
index adb9109..a5c3406 100644
--- a/spi.h
+++ b/spi.h
@@ -30,10 +30,11 @@
/* INSIZE may be 0x04 for some chips*/
#define JEDEC_RDID_INSIZE 0x03
-/* AT25F512A has bit 3 as don't care bit in commands */
-#define AT25F512A_RDID 0x15 /* 0x15 or 0x1d */
-#define AT25F512A_RDID_OUTSIZE 0x01
-#define AT25F512A_RDID_INSIZE 0x02
+/* Some Atmel AT25F* models have bit 3 as don't care bit in commands */
+/* 0x15 or 0x1d */
+#define AT25F_RDID 0x15
+#define AT25F_RDID_OUTSIZE 0x01
+#define AT25F_RDID_INSIZE 0x02
/* Read Electronic Manufacturer Signature */
#define JEDEC_REMS 0x90
--
1.7.1