summaryrefslogtreecommitdiffstats
path: root/ichspi.c
diff options
context:
space:
mode:
authorNikolai Artemiev <nartemiev@google.com>2022-11-04 14:21:39 +1100
committerEdward O'Callaghan <quasisec@chromium.org>2022-12-16 03:32:09 +0000
commit0741727925b841c2479b993204ce58c5eb75185a (patch)
treecbe7a30bb410cddcf24f05103acd12b73caf827c /ichspi.c
parent9394b84c00909354175e46550d454d4a26f7ca23 (diff)
downloadflashrom-0741727925b841c2479b993204ce58c5eb75185a.tar.gz
flashrom-0741727925b841c2479b993204ce58c5eb75185a.tar.bz2
flashrom-0741727925b841c2479b993204ce58c5eb75185a.zip
ichspi.c: Read chip ID and use it to populate `flash->chip`
Read the flash chip vendor/device ID using hardware sequencing, find the corresponding flashchip entry, and copy it over to `flash->chip`. Identifying the chip was not previously required as ICH hardware sequencing handles chip-level details related to read/write/erase ops. However writeprotect operations require the chip entry to be identified so that chip->reg_bits can be used to compute status register values. BUG=b:253715389,b:253713774 BRANCH=none TEST=flashrom on dedede (JSL) identifies "W25Q128.V..M" chip TEST=flashrom -{r,v} on dedede TEST=write/erase bios region on dedede: flashrom -{E,w} --layout <(echo '0x381000:0xffffff bios') -i bios Change-Id: Ia408e1e45dc6f53c0934afd6558e301abfa48ee6 Signed-off-by: Nikolai Artemiev <nartemiev@google.com> Reviewed-on: https://review.coreboot.org/c/flashrom/+/69195 Reviewed-by: Subrata Banik <subratabanik@google.com> Tested-by: build bot (Jenkins) <no-reply@coreboot.org> Reviewed-by: Damien Zammit Reviewed-by: Edward O'Callaghan <quasisec@chromium.org>
Diffstat (limited to 'ichspi.c')
-rw-r--r--ichspi.c75
1 files changed, 75 insertions, 0 deletions
diff --git a/ichspi.c b/ichspi.c
index 0b8867201..bc5252218 100644
--- a/ichspi.c
+++ b/ichspi.c
@@ -1401,6 +1401,22 @@ static int ich_exec_sync_hwseq_xfer(const struct flashctx *flash, uint32_t hsfc_
return ich_hwseq_wait_for_cycle_complete(len, ich_gen, addr_mask);
}
+/* Given RDID info, return pointer to entry in flashchips[] */
+static const struct flashchip *flash_id_to_entry(uint32_t mfg_id, uint32_t model_id)
+{
+ const struct flashchip *chip;
+
+ for (chip = &flashchips[0]; chip->vendor; chip++) {
+ if ((chip->manufacture_id == mfg_id) &&
+ (chip->model_id == model_id) &&
+ (chip->probe == PROBE_SPI_RDID) &&
+ ((chip->bustype & BUS_SPI) == BUS_SPI))
+ return chip;
+ }
+
+ return NULL;
+}
+
static int ich_hwseq_read_status(const struct flashctx *flash, enum flash_reg reg, uint8_t *value)
{
const int len = 1;
@@ -1452,6 +1468,60 @@ static int ich_hwseq_write_status(const struct flashctx *flash, enum flash_reg r
return 0;
}
+static void ich_hwseq_get_flash_id(struct flashctx *flash, enum ich_chipset ich_gen)
+{
+ const struct hwseq_data *hwseq_data = get_hwseq_data_from_context(flash);
+ if (hwseq_data->size_comp1 != 0) {
+ msg_pinfo("Multiple flash components detected, skipping flash identification.\n");
+ return;
+ }
+
+ /* PCH100 or above is required for RDID, ICH9 does not support it. */
+ if (hwseq_data->hsfc_fcycle != PCH100_HSFC_FCYCLE) {
+ msg_pinfo("RDID cycle not supported, skipping flash identification.\n");
+ return;
+ }
+
+ /*
+ * RDID gives 3 byte output:
+ * Byte 0: Manufacturer ID
+ * Byte 1: Model ID (MSB)
+ * Byte 2: Model ID (LSB)
+ */
+ const int len = 3;
+ uint8_t data[len];
+
+ if (ich_exec_sync_hwseq_xfer(flash, HSFC_CYCLE_RDID, 1, len, ich_gen,
+ hwseq_data->addr_mask)) {
+ msg_perr("Timed out waiting for RDID to complete.\n");
+ }
+
+ ich_read_data(data, len, ICH9_REG_FDATA0);
+ uint32_t mfg_id = data[0];
+ uint32_t model_id = (data[1] << 8) | data[2];
+
+ const struct flashchip *entry = flash_id_to_entry(mfg_id, model_id);
+ if (!entry) {
+ msg_pwarn("Unable to identify chip, mfg_id: 0x%02x, "
+ "model_id: 0x%02x\n", mfg_id, model_id);
+ }
+
+ msg_pdbg("Chip identified: %s\n", entry->name);
+
+ /* Update informational flash chip entries only */
+ flash->chip->vendor = entry->vendor;
+ flash->chip->name = entry->name;
+ flash->chip->manufacture_id = entry->manufacture_id;
+ flash->chip->model_id = entry->model_id;
+ /* total_size read from flash descriptor */
+ flash->chip->page_size = entry->page_size;
+ flash->chip->feature_bits = entry->feature_bits;
+ flash->chip->tested = entry->tested;
+ /* Support writeprotect */
+ flash->chip->reg_bits = entry->reg_bits;
+ flash->chip->decode_range = entry->decode_range;
+}
+
static int ich_hwseq_probe(struct flashctx *flash)
{
uint32_t total_size, boundary;
@@ -1504,7 +1574,12 @@ static int ich_hwseq_probe(struct flashctx *flash)
msg_cdbg("In that range are %d erase blocks with %d B each.\n",
size_high / erase_size_high, erase_size_high);
}
+
+ /* May be overwritten by ich_hwseq_get_flash_id(). */
flash->chip->tested = TEST_OK_PREWB;
+
+ ich_hwseq_get_flash_id(flash, ich_generation);
+
return 1;
}