spi: Use bus probing for REMS, RES and AT25F
Change-Id: Ic5d2a5283c5fb5e52c58c0b5937922371f56249f
Signed-off-by: Nico Huber <nico.h@gmx.de>
Reviewed-on: https://review.sourcearcade.org/c/flashprog/+/417
diff --git a/flashchips.c b/flashchips.c
index aed54e6..1722bc3 100644
--- a/flashchips.c
+++ b/flashchips.c
@@ -2072,7 +2072,7 @@
.page_size = 256,
.feature_bits = FEATURE_WRSR_WREN,
.tested = TEST_OK_PREW,
- .probe = probe_spi_at25f,
+ .probe = probe_buses,
.probe_timing = TIMING_ZERO,
.block_erasers =
{
@@ -2102,7 +2102,7 @@
.page_size = 256,
.feature_bits = FEATURE_WRSR_WREN,
.tested = TEST_UNTESTED,
- .probe = probe_spi_at25f,
+ .probe = probe_buses,
.probe_timing = TIMING_ZERO,
.block_erasers =
{
@@ -2132,7 +2132,7 @@
.page_size = 256,
.feature_bits = FEATURE_WRSR_WREN,
.tested = TEST_OK_PREW,
- .probe = probe_spi_at25f,
+ .probe = probe_buses,
.probe_timing = TIMING_ZERO,
.block_erasers =
{
@@ -2163,7 +2163,7 @@
.page_size = 256,
.feature_bits = FEATURE_WRSR_WREN,
.tested = TEST_OK_PREW,
- .probe = probe_spi_at25f,
+ .probe = probe_buses,
.probe_timing = TIMING_ZERO,
.block_erasers =
{
@@ -2193,7 +2193,7 @@
.page_size = 128,
.feature_bits = FEATURE_WRSR_WREN,
.tested = TEST_OK_PREW,
- .probe = probe_spi_at25f,
+ .probe = probe_buses,
.probe_timing = TIMING_ZERO,
.block_erasers =
{
@@ -13727,7 +13727,7 @@
/* The ST M25P05 is a bit of a problem. It has the same ID as the
* ST M25P05-A in RES mode, but supports only 128 byte writes instead
- * of 256 byte writes. We rely heavily on the fact that probe_spi_res1
+ * of 256 byte writes. We rely heavily on the fact that probe_spi_res(1)
* only is successful if RDID does not work.
*/
{
@@ -13741,7 +13741,7 @@
.page_size = 256,
.feature_bits = FEATURE_WRSR_WREN,
.tested = TEST_UNTESTED,
- .probe = probe_spi_res1,
+ .probe = probe_buses,
.probe_timing = TIMING_ZERO,
.block_erasers =
{
@@ -13802,7 +13802,7 @@
.page_size = 256,
.feature_bits = FEATURE_WRSR_WREN,
.tested = TEST_UNTESTED,
- .probe = probe_spi_res1,
+ .probe = probe_buses,
.probe_timing = TIMING_ZERO,
.block_erasers =
{
@@ -13952,7 +13952,7 @@
.page_size = 256,
.feature_bits = FEATURE_WRSR_WREN,
.tested = TEST_OK_PREW,
- .probe = probe_spi_res1,
+ .probe = probe_buses,
.probe_timing = TIMING_ZERO,
.block_erasers =
{
@@ -14042,7 +14042,7 @@
.page_size = 256,
.feature_bits = FEATURE_WRSR_WREN,
.tested = TEST_UNTESTED,
- .probe = probe_spi_res1,
+ .probe = probe_buses,
.probe_timing = TIMING_ZERO,
.block_erasers =
{
@@ -16441,7 +16441,7 @@
.page_size = 256,
.feature_bits = FEATURE_WRSR_WREN,
.tested = TEST_OK_PREW,
- .probe = probe_spi_res2, /* The continuation code is transferred as the 3rd byte m( */
+ .probe = probe_buses,
.probe_timing = TIMING_ZERO,
.block_erasers =
{
@@ -16651,7 +16651,7 @@
.page_size = 256,
.feature_bits = FEATURE_WRSR_WREN,
.tested = TEST_OK_PREW,
- .probe = probe_spi_res2, /* The continuation code is transferred as the 3rd byte m( */
+ .probe = probe_buses,
.probe_timing = TIMING_ZERO,
.block_erasers =
{
@@ -18786,7 +18786,7 @@
.page_size = 256,
.feature_bits = FEATURE_WRSR_EWSR,
.tested = TEST_OK_PREW,
- .probe = probe_spi_rems,
+ .probe = probe_buses,
.probe_timing = TIMING_ZERO,
.block_erasers =
{
@@ -18819,7 +18819,7 @@
.page_size = 256,
.feature_bits = FEATURE_WRSR_EWSR,
.tested = TEST_OK_PREW,
- .probe = probe_spi_res2,
+ .probe = probe_buses,
.probe_timing = TIMING_ZERO,
.block_erasers =
{
@@ -18852,7 +18852,7 @@
.page_size = 256,
.feature_bits = FEATURE_WRSR_EITHER,
.tested = TEST_UNTESTED,
- .probe = probe_spi_res2,
+ .probe = probe_buses,
.probe_timing = TIMING_ZERO,
.block_erasers =
{
@@ -18885,7 +18885,7 @@
.page_size = 256,
.feature_bits = FEATURE_WRSR_EWSR,
.tested = TEST_OK_PREW,
- .probe = probe_spi_rems,
+ .probe = probe_buses,
.probe_timing = TIMING_ZERO,
.block_erasers =
{
@@ -18963,7 +18963,7 @@
.page_size = 256,
.feature_bits = FEATURE_WRSR_EWSR,
.tested = TEST_UNTESTED,
- .probe = probe_spi_rems,
+ .probe = probe_buses,
.probe_timing = TIMING_ZERO,
.block_erasers =
{
@@ -19074,7 +19074,7 @@
.page_size = 256,
.feature_bits = FEATURE_WRSR_EWSR,
.tested = TEST_OK_PR,
- .probe = probe_spi_rems,
+ .probe = probe_buses,
.probe_timing = TIMING_ZERO,
.block_erasers =
{
@@ -19146,7 +19146,7 @@
.page_size = 256,
.feature_bits = FEATURE_WRSR_EWSR,
.tested = TEST_OK_PREW,
- .probe = probe_spi_rems,
+ .probe = probe_buses,
.probe_timing = TIMING_ZERO,
.block_erasers =
{
@@ -19263,7 +19263,7 @@
.page_size = 256,
.feature_bits = FEATURE_WRSR_EWSR,
.tested = TEST_OK_PREW,
- .probe = probe_spi_rems,
+ .probe = probe_buses,
.probe_timing = TIMING_ZERO,
.block_erasers =
{
@@ -21306,7 +21306,7 @@
.page_size = 256,
.feature_bits = FEATURE_WRSR_WREN,
.tested = TEST_UNTESTED,
- .probe = probe_spi_res2,
+ .probe = probe_buses,
.probe_timing = TIMING_ZERO,
.block_erasers =
{
@@ -21341,7 +21341,7 @@
.page_size = 256,
.feature_bits = FEATURE_WRSR_WREN,
.tested = TEST_UNTESTED,
- .probe = probe_spi_res2,
+ .probe = probe_buses,
.probe_timing = TIMING_ZERO,
.block_erasers =
{
@@ -21412,7 +21412,7 @@
.page_size = 256,
.feature_bits = FEATURE_WRSR_WREN,
.tested = TEST_OK_PREW,
- .probe = probe_spi_res2,
+ .probe = probe_buses,
.probe_timing = TIMING_ZERO,
.block_erasers =
{
@@ -21484,7 +21484,7 @@
.page_size = 256,
.feature_bits = FEATURE_WRSR_WREN,
.tested = TEST_OK_PREW,
- .probe = probe_spi_res2,
+ .probe = probe_buses,
.probe_timing = TIMING_ZERO,
.block_erasers =
{
@@ -21581,7 +21581,7 @@
.page_size = 256,
.feature_bits = FEATURE_WRSR_WREN,
.tested = TEST_OK_PREW,
- .probe = probe_spi_res2,
+ .probe = probe_buses,
.probe_timing = TIMING_ZERO,
.block_erasers =
{
@@ -21614,7 +21614,7 @@
.page_size = 256,
.feature_bits = FEATURE_WRSR_WREN,
.tested = TEST_UNTESTED,
- .probe = probe_spi_res2,
+ .probe = probe_buses,
.probe_timing = TIMING_ZERO,
.block_erasers =
{
@@ -21647,7 +21647,7 @@
.page_size = 256,
.feature_bits = FEATURE_WRSR_WREN,
.tested = TEST_UNTESTED,
- .probe = probe_spi_res2,
+ .probe = probe_buses,
.probe_timing = TIMING_ZERO,
.block_erasers =
{
@@ -21683,7 +21683,7 @@
.page_size = 256,
.feature_bits = FEATURE_WRSR_WREN,
.tested = TEST_UNTESTED,
- .probe = probe_spi_res2,
+ .probe = probe_buses,
.probe_timing = TIMING_ZERO,
.block_erasers =
{
@@ -27534,7 +27534,7 @@
.total_size = 0,
.page_size = 256,
.tested = TEST_BAD_PREW,
- .probe = probe_spi_rems,
+ .probe = probe_buses,
.write = NULL,
},
diff --git a/include/chipdrivers/spi.h b/include/chipdrivers/spi.h
index 9b14342..1646561 100644
--- a/include/chipdrivers/spi.h
+++ b/include/chipdrivers/spi.h
@@ -29,13 +29,11 @@
/* spi25.c */
struct found_id *probe_spi_rdid(const struct bus_probe *, const struct master_common *);
+struct found_id *probe_spi_rems(const struct bus_probe *, const struct master_common *);
+struct found_id *probe_spi_res(const struct bus_probe *, const struct master_common *);
+struct found_id *probe_spi_at25f(const struct bus_probe *, const struct master_common *);
int spi_simple_write_cmd(struct flashprog_flashctx *, uint8_t op, unsigned int poll_delay);
-int probe_spi_rems(struct flashprog_flashctx *);
-int probe_spi_res1(struct flashprog_flashctx *);
-int probe_spi_res2(struct flashprog_flashctx *);
-int probe_spi_res3(struct flashprog_flashctx *);
-int probe_spi_at25f(struct flashprog_flashctx *);
int spi_write_enable(struct flashprog_flashctx *);
int spi_write_disable(struct flashprog_flashctx *);
int spi_block_erase_20(struct flashprog_flashctx *, unsigned int addr, unsigned int blocklen);
diff --git a/spi.c b/spi.c
index fee3aee..8d07ed1 100644
--- a/spi.c
+++ b/spi.c
@@ -165,6 +165,11 @@
static const struct bus_probe spi_probes[] = {
/* type function function argument */
{ ID_SPI_RDID, probe_spi_rdid, NULL },
+ { ID_SPI_AT25F, probe_spi_at25f, NULL },
+ { ID_SPI_REMS, probe_spi_rems, NULL },
+ { ID_SPI_RES3, probe_spi_res, NULL },
+ { ID_SPI_RES2, probe_spi_res, NULL },
+ { ID_SPI_RES1, probe_spi_res, NULL },
};
static bool spi_probe_match(const struct flashchip *chip, const struct id_info_ext *found)
diff --git a/spi25.c b/spi25.c
index b22c8a8..d1ce38e 100644
--- a/spi25.c
+++ b/spi25.c
@@ -46,25 +46,25 @@
return 0;
}
-static int spi_rems(struct flashctx *flash, unsigned char *readarr)
+static int spi_rems(const struct spi_master *spi, unsigned char *readarr)
{
static const unsigned char cmd[JEDEC_REMS_OUTSIZE] = { JEDEC_REMS, };
int ret;
- ret = spi_send_command(flash, sizeof(cmd), JEDEC_REMS_INSIZE, cmd, readarr);
+ ret = spi->command(spi, sizeof(cmd), JEDEC_REMS_INSIZE, cmd, readarr);
if (ret)
return ret;
msg_cspew("REMS returned 0x%02x 0x%02x. ", readarr[0], readarr[1]);
return 0;
}
-static int spi_res(struct flashctx *flash, unsigned char *readarr, int bytes)
+static int spi_res(const struct spi_master *spi, unsigned char *readarr, int bytes)
{
static const unsigned char cmd[JEDEC_RES_OUTSIZE] = { JEDEC_RES, };
int ret;
int i;
- ret = spi_send_command(flash, sizeof(cmd), bytes, cmd, readarr);
+ ret = spi->command(spi, sizeof(cmd), bytes, cmd, readarr);
if (ret)
return ret;
msg_cspew("RES returned");
@@ -147,136 +147,114 @@
return found;
}
-int probe_spi_rems(struct flashctx *flash)
+struct found_id *probe_spi_rems(const struct bus_probe *probe, const struct master_common *mst)
{
- const struct flashchip *chip = flash->chip;
+ const struct spi_master *const spi = (const struct spi_master *)mst;
unsigned char readarr[JEDEC_REMS_INSIZE];
- uint32_t id1, id2;
- if (spi_rems(flash, readarr)) {
- return 0;
+ if (spi_rems(spi, readarr) || flashprog_no_data(readarr, sizeof(readarr))) {
+ return NULL;
}
- id1 = readarr[0];
- id2 = readarr[1];
+ struct found_id *const found = calloc(1, sizeof(*found));
+ if (!found) {
+ msg_cerr("Out of memory!\n");
+ return NULL;
+ }
- msg_cdbg("%s: id1 0x%x, id2 0x%x\n", __func__, id1, id2);
+ struct id_info *const id = &found->info.id;
- if (id1 == chip->id.manufacture && id2 == chip->id.model)
- return 1;
+ id->manufacture = readarr[0];
+ id->model = readarr[1];
+ id->type = ID_SPI_REMS;
- /* Test if this is a pure vendor match. */
- if (id1 == chip->id.manufacture && GENERIC_DEVICE_ID == chip->id.model)
- return 1;
+ msg_cdbg("%s: id1 0x%02x, id2 0x%02x\n", __func__, id->id1, id->id2);
- /* Test if there is any vendor ID. */
- if (GENERIC_MANUF_ID == chip->id.manufacture && id1 != 0xff && id1 != 0x00)
- return 1;
-
- return 0;
+ return found;
}
-int probe_spi_res1(struct flashctx *flash)
+struct found_id *probe_spi_res(const struct bus_probe *probe, const struct master_common *mst)
{
- static const unsigned char allff[] = {0xff, 0xff, 0xff};
- static const unsigned char all00[] = {0x00, 0x00, 0x00};
+ const struct spi_master *const spi = (const struct spi_master *)mst;
+ const unsigned int res_len = probe->type == ID_SPI_RES3 ? 3 :
+ (probe->type == ID_SPI_RES2 ? 2 : 1);
unsigned char readarr[3];
- uint32_t id2;
- /* We only want one-byte RES if RDID and REMS are unusable. */
+ if (res_len == 1) {
+ /* We only want one-byte RES if RDID and REMS are unusable. */
- /* Check if RDID is usable and does not return 0xff 0xff 0xff or
- * 0x00 0x00 0x00. In that case, RES is pointless.
- */
- if (!spi_rdid(flash->mst.spi, readarr, 3) && memcmp(readarr, allff, 3) &&
- memcmp(readarr, all00, 3)) {
- msg_cdbg("Ignoring RES in favour of RDID.\n");
- return 0;
- }
- /* Check if REMS is usable and does not return 0xff 0xff or
- * 0x00 0x00. In that case, RES is pointless.
- */
- if (!spi_rems(flash, readarr) &&
- memcmp(readarr, allff, JEDEC_REMS_INSIZE) &&
- memcmp(readarr, all00, JEDEC_REMS_INSIZE)) {
- msg_cdbg("Ignoring RES in favour of REMS.\n");
- return 0;
+ if (!spi_rdid(spi, readarr, 3) && !flashprog_no_data(readarr, 3)) {
+ msg_cdbg("Ignoring RES in favour of RDID.\n");
+ return NULL;
+ }
+
+ if (!spi_rems(spi, readarr) && !flashprog_no_data(readarr, JEDEC_REMS_INSIZE)) {
+ msg_cdbg("Ignoring RES in favour of REMS.\n");
+ return NULL;
+ }
}
- if (spi_res(flash, readarr, 1)) {
- return 0;
+ if (spi_res(spi, readarr, res_len) || flashprog_no_data(readarr, res_len)) {
+ return NULL;
}
- id2 = readarr[0];
-
- msg_cdbg("%s: id 0x%x\n", __func__, id2);
-
- if (id2 != flash->chip->id.model)
- return 0;
-
- return 1;
-}
-
-int probe_spi_res2(struct flashctx *flash)
-{
- unsigned char readarr[2];
- uint32_t id1, id2;
-
- if (spi_res(flash, readarr, 2)) {
- return 0;
+ struct found_id *const found = calloc(1, sizeof(*found));
+ if (!found) {
+ msg_cerr("Out of memory!\n");
+ return NULL;
}
- id1 = readarr[0];
- id2 = readarr[1];
+ struct id_info *const id = &found->info.id;
- msg_cdbg("%s: id1 0x%x, id2 0x%x\n", __func__, id1, id2);
-
- if (id1 != flash->chip->id.manufacture || id2 != flash->chip->id.model)
- return 0;
-
- return 1;
-}
-
-int probe_spi_res3(struct flashctx *flash)
-{
- unsigned char readarr[3];
- uint32_t id1, id2;
-
- if (spi_res(flash, readarr, 3)) {
- return 0;
+ switch (res_len) {
+ case 1:
+ id->manufacture = 0;
+ id->model = readarr[0];
+ msg_cdbg("%s: id 0x%02x\n", __func__, id->model);
+ break;
+ case 2:
+ id->manufacture = readarr[0];
+ id->model = readarr[1];
+ msg_cdbg("%s: id1 0x%02x, id2 0x%02x\n", __func__, id->id1, id->id2);
+ break;
+ case 3:
+ id->manufacture = (readarr[0] << 8) | readarr[1];
+ id->model = readarr[2];
+ msg_cdbg("%s: id1 0x%04x, id2 0x%02x\n", __func__, id->id1, id->id2);
+ break;
}
+ id->type = probe->type;
- id1 = (readarr[0] << 8) | readarr[1];
- id2 = readarr[2];
-
- msg_cdbg("%s: id1 0x%x, id2 0x%x\n", __func__, id1, id2);
-
- if (id1 != flash->chip->id.manufacture || id2 != flash->chip->id.model)
- return 0;
-
- return 1;
+ return found;
}
/* Only used for some Atmel chips. */
-int probe_spi_at25f(struct flashctx *flash)
+struct found_id *probe_spi_at25f(const struct bus_probe *probe, const struct master_common *mst)
{
static const unsigned char cmd[AT25F_RDID_OUTSIZE] = { AT25F_RDID };
+ const struct spi_master *const spi = (const struct spi_master *)mst;
unsigned char readarr[AT25F_RDID_INSIZE];
- uint32_t id1;
- uint32_t id2;
- if (spi_send_command(flash, sizeof(cmd), sizeof(readarr), cmd, readarr))
- return 0;
+ if (spi->command(spi, sizeof(cmd), sizeof(readarr), cmd, readarr))
+ return NULL;
+ if (flashprog_no_data(readarr, sizeof(readarr)))
+ return NULL;
- id1 = readarr[0];
- id2 = readarr[1];
+ struct found_id *const found = calloc(1, sizeof(*found));
+ if (!found) {
+ msg_cerr("Out of memory!\n");
+ return NULL;
+ }
- msg_cdbg("%s: id1 0x%02x, id2 0x%02x\n", __func__, id1, id2);
+ struct id_info *const id = &found->info.id;
- if (id1 == flash->chip->id.manufacture && id2 == flash->chip->id.model)
- return 1;
+ id->manufacture = readarr[0];
+ id->model = readarr[1];
+ id->type = ID_SPI_AT25F;
- return 0;
+ msg_cdbg("%s: id1 0x%02x, id2 0x%02x\n", __func__, id->id1, id->id2);
+
+ return found;
}
static int spi_poll_wip(struct flashctx *const flash, const unsigned int poll_delay)