summaryrefslogtreecommitdiffstats
path: root/spi25.c
diff options
context:
space:
mode:
authorNico Huber <nico.h@gmx.de>2017-10-14 18:00:20 +0200
committerNico Huber <nico.h@gmx.de>2017-12-28 10:45:46 +0000
commita1672f829328e877d9b8dea7777f25e2eba52d0e (patch)
tree8f90cab7e18bc875241ff66eef153b80e7c4a71b /spi25.c
parentf43c654ad0dcb11b2738bbfac9246d09bb1949e5 (diff)
downloadflashrom-a1672f829328e877d9b8dea7777f25e2eba52d0e.tar.gz
flashrom-a1672f829328e877d9b8dea7777f25e2eba52d0e.tar.bz2
flashrom-a1672f829328e877d9b8dea7777f25e2eba52d0e.zip
spi25: Enable native 4BA read and write using feature bits
Prefer the native 4BA instruction when they are supported. In this case, override our logic to decide to use a 4BA address. Change-Id: I2f6817ca198bf923671a7aa67e956e5477d71848 Signed-off-by: Nico Huber <nico.h@gmx.de> Reviewed-on: https://review.coreboot.org/22385 Reviewed-by: Stefan Reinauer <stefan.reinauer@coreboot.org> Tested-by: build bot (Jenkins) <no-reply@coreboot.org>
Diffstat (limited to 'spi25.c')
-rw-r--r--spi25.c41
1 files changed, 23 insertions, 18 deletions
diff --git a/spi25.c b/spi25.c
index 6940394c7..ce3d184aa 100644
--- a/spi25.c
+++ b/spi25.c
@@ -24,6 +24,7 @@
#include <stddef.h>
#include <string.h>
+#include <stdbool.h>
#include "flash.h"
#include "flashchips.h"
#include "chipdrivers.h"
@@ -372,10 +373,10 @@ static int spi_set_extended_address(struct flashctx *const flash, const uint8_t
return 0;
}
-static int spi_prepare_address(struct flashctx *const flash,
- uint8_t cmd_buf[], const unsigned int addr)
+static int spi_prepare_address(struct flashctx *const flash, uint8_t cmd_buf[],
+ const bool native_4ba, const unsigned int addr)
{
- if (flash->in_4ba_mode) {
+ if (native_4ba || flash->in_4ba_mode) {
cmd_buf[1] = (addr >> 24) & 0xff;
cmd_buf[2] = (addr >> 16) & 0xff;
cmd_buf[3] = (addr >> 8) & 0xff;
@@ -402,6 +403,7 @@ static int spi_prepare_address(struct flashctx *const flash,
*
* @param flash the flash chip's context
* @param op the operation to execute
+ * @param native_4ba whether `op` always takes a 4-byte address
* @param addr the address parameter to `op`
* @param out_bytes bytes to send after the address,
* may be NULL if and only if `out_bytes` is 0
@@ -409,8 +411,8 @@ static int spi_prepare_address(struct flashctx *const flash,
* @param poll_delay interval in us for polling WIP
* @return 0 on success, non-zero otherwise
*/
-static int spi_write_cmd(struct flashctx *const flash,
- const uint8_t op, const unsigned int addr,
+static int spi_write_cmd(struct flashctx *const flash, const uint8_t op,
+ const bool native_4ba, const unsigned int addr,
const uint8_t *const out_bytes, const size_t out_len,
const unsigned int poll_delay)
{
@@ -426,7 +428,7 @@ static int spi_write_cmd(struct flashctx *const flash,
};
cmd[0] = op;
- const int addr_len = spi_prepare_address(flash, cmd, addr);
+ const int addr_len = spi_prepare_address(flash, cmd, native_4ba, addr);
if (addr_len < 0)
return 1;
@@ -469,7 +471,7 @@ int spi_block_erase_52(struct flashctx *flash, unsigned int addr,
unsigned int blocklen)
{
/* This usually takes 100-4000ms, so wait in 100ms steps. */
- return spi_write_cmd(flash, 0x52, addr, NULL, 0, 100 * 1000);
+ return spi_write_cmd(flash, 0x52, false, addr, NULL, 0, 100 * 1000);
}
/* Block size is usually
@@ -478,7 +480,7 @@ int spi_block_erase_52(struct flashctx *flash, unsigned int addr,
int spi_block_erase_c4(struct flashctx *flash, unsigned int addr, unsigned int blocklen)
{
/* This usually takes 240-480s, so wait in 500ms steps. */
- return spi_write_cmd(flash, 0xc4, addr, NULL, 0, 500 * 1000);
+ return spi_write_cmd(flash, 0xc4, false, addr, NULL, 0, 500 * 1000);
}
/* Block size is usually
@@ -490,7 +492,7 @@ int spi_block_erase_d8(struct flashctx *flash, unsigned int addr,
unsigned int blocklen)
{
/* This usually takes 100-4000ms, so wait in 100ms steps. */
- return spi_write_cmd(flash, 0xd8, addr, NULL, 0, 100 * 1000);
+ return spi_write_cmd(flash, 0xd8, false, addr, NULL, 0, 100 * 1000);
}
/* Block size is usually
@@ -500,7 +502,7 @@ int spi_block_erase_d7(struct flashctx *flash, unsigned int addr,
unsigned int blocklen)
{
/* This usually takes 100-4000ms, so wait in 100ms steps. */
- return spi_write_cmd(flash, 0xd7, addr, NULL, 0, 100 * 1000);
+ return spi_write_cmd(flash, 0xd7, false, addr, NULL, 0, 100 * 1000);
}
/* Page erase (usually 256B blocks) */
@@ -508,7 +510,7 @@ int spi_block_erase_db(struct flashctx *flash, unsigned int addr, unsigned int b
{
/* This takes up to 20ms usually (on worn out devices
up to the 0.5s range), so wait in 1ms steps. */
- return spi_write_cmd(flash, 0xdb, addr, NULL, 0, 1 * 1000);
+ return spi_write_cmd(flash, 0xdb, false, addr, NULL, 0, 1 * 1000);
}
/* Sector size is usually 4k, though Macronix eliteflash has 64k */
@@ -516,19 +518,19 @@ int spi_block_erase_20(struct flashctx *flash, unsigned int addr,
unsigned int blocklen)
{
/* This usually takes 15-800ms, so wait in 10ms steps. */
- return spi_write_cmd(flash, 0x20, addr, NULL, 0, 10 * 1000);
+ return spi_write_cmd(flash, 0x20, false, addr, NULL, 0, 10 * 1000);
}
int spi_block_erase_50(struct flashctx *flash, unsigned int addr, unsigned int blocklen)
{
/* This usually takes 10ms, so wait in 1ms steps. */
- return spi_write_cmd(flash, 0x50, addr, NULL, 0, 1 * 1000);
+ return spi_write_cmd(flash, 0x50, false, addr, NULL, 0, 1 * 1000);
}
int spi_block_erase_81(struct flashctx *flash, unsigned int addr, unsigned int blocklen)
{
/* This usually takes 8ms, so wait in 1ms steps. */
- return spi_write_cmd(flash, 0x81, addr, NULL, 0, 1 * 1000);
+ return spi_write_cmd(flash, 0x81, false, addr, NULL, 0, 1 * 1000);
}
int spi_block_erase_60(struct flashctx *flash, unsigned int addr,
@@ -601,15 +603,18 @@ erasefunc_t *spi_get_erasefn_from_opcode(uint8_t opcode)
static int spi_nbyte_program(struct flashctx *flash, unsigned int addr, const uint8_t *bytes, unsigned int len)
{
- return spi_write_cmd(flash, JEDEC_BYTE_PROGRAM, addr, bytes, len, 10);
+ const bool native_4ba = !!(flash->chip->feature_bits & FEATURE_4BA_WRITE);
+ const uint8_t op = native_4ba ? JEDEC_BYTE_PROGRAM_4BA : JEDEC_BYTE_PROGRAM;
+ return spi_write_cmd(flash, op, native_4ba, addr, bytes, len, 10);
}
int spi_nbyte_read(struct flashctx *flash, unsigned int address, uint8_t *bytes,
unsigned int len)
{
- uint8_t cmd[1 + JEDEC_MAX_ADDR_LEN] = { JEDEC_READ, };
+ const bool native_4ba = !!(flash->chip->feature_bits & FEATURE_4BA_READ);
+ uint8_t cmd[1 + JEDEC_MAX_ADDR_LEN] = { native_4ba ? JEDEC_READ_4BA : JEDEC_READ, };
- const int addr_len = spi_prepare_address(flash, cmd, address);
+ const int addr_len = spi_prepare_address(flash, cmd, native_4ba, address);
if (addr_len < 0)
return 1;
@@ -781,7 +786,7 @@ int default_spi_write_aai(struct flashctx *flash, const uint8_t *buf, unsigned i
//return SPI_GENERIC_ERROR;
}
- result = spi_write_cmd(flash, JEDEC_AAI_WORD_PROGRAM, start, buf + pos - start, 2, 10);
+ result = spi_write_cmd(flash, JEDEC_AAI_WORD_PROGRAM, false, start, buf + pos - start, 2, 10);
if (result)
goto bailout;