diff options
author | Pai Peng <paipeng@google.com> | 2019-07-03 10:44:14 -0700 |
---|---|---|
committer | Commit Bot <commit-bot@chromium.org> | 2019-07-17 20:18:55 +0000 |
commit | 3811a28a607e40f5291e45d7c57da6b0700fb821 (patch) | |
tree | 0c7c0dc2777940a600c55aded6df4d8b542f80d3 /common/spi_nor.c | |
parent | e425f0d7ef7f6e56b783e20a35709fbb1cc2e2b7 (diff) | |
download | chrome-ec-3811a28a607e40f5291e45d7c57da6b0700fb821.tar.gz |
Add the functions to read and write EAR.
EAR (extended address register) is used to access addresses above
16MiB when 3-byte address mode is used. These two functions allow to
write to and read from EAR to set up what addresses to access in
3-byte mode. For example, for a 64MiB EEPROM:
EAR value Addresses to access
0 0x0000000 - 0x0FFFFFF
1 0x1000000 - 0x1FFFFFF
2 0x2000000 - 0x2FFFFFF
3 0x3000000 - 0x3FFFFFF
BUG=b:132252340
BRANCH=none
TEST=manual
Testing:
1. Writing to EAR returns successfully.
2. Writing different values to EAR, verify that accessing EERPOM
in 3-byte mode is to the correct address, e.g., when EAR=2,
accessing 0x0FFFFFF is actually to 0x2FFFFFF.
Change-Id: I2a8bde7fc4b9069afc80a81042fb47359bffa015
Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/platform/ec/+/1688150
Reviewed-by: Daisuke Nojiri <dnojiri@chromium.org>
Tested-by: Pai Peng <paipeng@google.com>
Commit-Queue: Pai Peng <paipeng@google.com>
Diffstat (limited to 'common/spi_nor.c')
-rw-r--r-- | common/spi_nor.c | 97 |
1 files changed, 74 insertions, 23 deletions
diff --git a/common/spi_nor.c b/common/spi_nor.c index 3bec5cd6a6..09f5b28bdd 100644 --- a/common/spi_nor.c +++ b/common/spi_nor.c @@ -17,10 +17,10 @@ #include "watchdog.h" #ifdef CONFIG_SPI_NOR_DEBUG -#define DEBUG_CPRINTS_DEVICE(spi_nor_device, string, args...) \ - cprints(CC_SPI, "SPI NOR %s: " string, spi_nor_device->name, ## args) +#define CPRINTS(dev, string, args...) \ + cprints(CC_SPI, "SPI NOR %s: " string, (dev)->name, ## args) #else -#define DEBUG_CPRINTS_DEVICE(spi_nor_device, string, args...) +#define CPRINTS(dev, string, args...) #endif /* Time to sleep while serial NOR flash write is in progress. */ @@ -90,6 +90,62 @@ static int spi_nor_write_enable(const struct spi_nor_device_t *spi_nor_device) } /** + * Read from the extended address register. + * @param spi_nor_device The Serial NOR Flash device to use. + * @param value The value to read to. + * @return ec_error_list (non-zero on error and timeout). + */ +static int spi_nor_read_ear(const struct spi_nor_device_t *spi_nor_device, + uint8_t *value) +{ + uint8_t command = SPI_NOR_OPCODE_RDEAR; + + return spi_transaction(&spi_devices[spi_nor_device->spi_master], + &command, sizeof(command), value, 1); +} + +int spi_nor_write_ear(const struct spi_nor_device_t *spi_nor_device, + const uint8_t value) +{ + uint8_t buf[2]; + int rv; + uint8_t ear; + + mutex_lock(&driver_mutex); + + rv = spi_nor_write_enable(spi_nor_device); + if (rv) { + CPRINTS(spi_nor_device, "Failed to write enable"); + goto err_free; + } + + buf[0] = SPI_NOR_OPCODE_WREAR; + buf[1] = value; + + rv = spi_transaction(&spi_devices[spi_nor_device->spi_master], + buf, sizeof(buf), NULL, 0); + if (rv) { + CPRINTS(spi_nor_device, "Failed to write EAR, rv=%d", rv); + goto err_free; + } + + rv = spi_nor_read_ear(spi_nor_device, &ear); + if (rv) + goto err_free; + + if (ear != value) { + CPRINTS(spi_nor_device, + "Write EAR error: write=%d, read=%d", value, ear); + rv = EC_ERROR_UNKNOWN; /* WEL not set but should be. */ + goto err_free; + } + +err_free: + mutex_unlock(&driver_mutex); + return rv; +} + +/** * Block until the Serial NOR Flash clears the BUSY/WIP bit in its status reg. */ static int spi_nor_wait(const struct spi_nor_device_t *spi_nor_device) @@ -232,7 +288,7 @@ static int locate_sfdp_basic_parameter_table( * compatible, older basic parameter tables which are compatible with * this driver in the parameter headers. */ if (!SFDP_HEADER_DW1_SFDP_SIGNATURE_VALID(dw1)) { - DEBUG_CPRINTS_DEVICE(spi_nor_device, "SFDP signature invalid"); + CPRINTS(spi_nor_device, "SFDP signature invalid"); return EC_ERROR_UNKNOWN; } @@ -240,15 +296,14 @@ static int locate_sfdp_basic_parameter_table( SFDP_GET_BITFIELD(SFDP_HEADER_DW2_SFDP_MAJOR, dw2); *out_sfdp_minor_rev = SFDP_GET_BITFIELD(SFDP_HEADER_DW2_SFDP_MINOR, dw2); - DEBUG_CPRINTS_DEVICE(spi_nor_device, "SFDP v%d.%d discovered", - *out_sfdp_major_rev, *out_sfdp_minor_rev); + CPRINTS(spi_nor_device, "SFDP v%d.%d discovered", + *out_sfdp_major_rev, *out_sfdp_minor_rev); /* NPH is 0-based, so add 1. */ number_parameter_headers = SFDP_GET_BITFIELD(SFDP_HEADER_DW2_NPH, dw2) + 1; - DEBUG_CPRINTS_DEVICE(spi_nor_device, - "There are %d SFDP parameter headers", - number_parameter_headers); + CPRINTS(spi_nor_device, "There are %d SFDP parameter headers", + number_parameter_headers); /* Search for the newest, compatible basic flash parameter table. */ *out_table_major_rev = 0; @@ -302,15 +357,13 @@ static int locate_sfdp_basic_parameter_table( } if (!table_found) { - DEBUG_CPRINTS_DEVICE( - spi_nor_device, + CPRINTS(spi_nor_device, "No compatible Basic Flash Parameter Table found"); return EC_ERROR_UNKNOWN; } - DEBUG_CPRINTS_DEVICE(spi_nor_device, - "Using Basic Flash Parameter Table v%d.%d", - *out_sfdp_major_rev, *out_sfdp_minor_rev); + CPRINTS(spi_nor_device, "Using Basic Flash Parameter Table v%d.%d", + *out_sfdp_major_rev, *out_sfdp_minor_rev); return EC_SUCCESS; } @@ -489,8 +542,7 @@ int spi_nor_init(void) mutex_lock(&driver_mutex); spi_nor_device->capacity = capacity; spi_nor_device->page_size = page_size; - DEBUG_CPRINTS_DEVICE( - spi_nor_device, + CPRINTS(spi_nor_device, "Updated to SFDP params: %dKiB w/ %dB pages", spi_nor_device->capacity >> 10, spi_nor_device->page_size); @@ -549,9 +601,8 @@ int spi_nor_set_4b_mode(struct spi_nor_device_t *spi_nor_device, enter_4b_addressing_mode; } - DEBUG_CPRINTS_DEVICE(spi_nor_device, - "Entered %s Addressing Mode", - enter_4b_addressing_mode ? "4-Byte" : "3-Byte"); + CPRINTS(spi_nor_device, "Entered %s Addressing Mode", + enter_4b_addressing_mode ? "4-Byte" : "3-Byte"); /* Release the driver mutex. */ mutex_unlock(&driver_mutex); @@ -681,10 +732,10 @@ int spi_nor_erase(const struct spi_nor_device_t *spi_nor_device, } if (!read_left) { /* Sector/block already erased. */ - DEBUG_CPRINTS_DEVICE(spi_nor_device, - "Skipping erase [%x:%x] " - "(already erased)", - offset, erase_size); + CPRINTS(spi_nor_device, + "Skipping erase [%x:%x] " + "(already erased)", + offset, erase_size); offset += erase_size; size -= erase_size; continue; |