summaryrefslogtreecommitdiff
path: root/spi25.c
diff options
context:
space:
mode:
authorhailfinger <hailfinger@2b7e53f0-3cfb-0310-b3e9-8179ed1497e1>2010-10-08 00:37:55 +0000
committerhailfinger <hailfinger@2b7e53f0-3cfb-0310-b3e9-8179ed1497e1>2010-10-08 00:37:55 +0000
commitb0c20a1c46d95bb067a88378e3fa2b6081da35b3 (patch)
treeee72939ddee85b2483d90ca0d4f2706482a30433 /spi25.c
parentfe68989222cdfec46443116aa48b456fce3b97ac (diff)
downloadflashrom-b0c20a1c46d95bb067a88378e3fa2b6081da35b3.tar.gz
SPI write status register (WRSR) may take longer than 100 ms, and it
makes sense to poll for completion in 10 ms steps until 5 s are over. This patch complements r1115. Signed-off-by: Carl-Daniel Hailfinger <c-d.hailfinger.devel.2006@gmx.net> Acked-by: Joshua Roys <roysjosh@gmail.com> git-svn-id: https://code.coreboot.org/svn/flashrom/trunk@1201 2b7e53f0-3cfb-0310-b3e9-8179ed1497e1
Diffstat (limited to 'spi25.c')
-rw-r--r--spi25.c40
1 files changed, 36 insertions, 4 deletions
diff --git a/spi25.c b/spi25.c
index 688a329..9aaefc4 100644
--- a/spi25.c
+++ b/spi25.c
@@ -856,6 +856,7 @@ int spi_write_status_enable(void)
static int spi_write_status_register_ewsr(struct flashchip *flash, int status)
{
int result;
+ int i = 0;
struct spi_command cmds[] = {
{
/* WRSR requires either EWSR or WREN depending on chip type. */
@@ -879,15 +880,31 @@ static int spi_write_status_register_ewsr(struct flashchip *flash, int status)
if (result) {
msg_cerr("%s failed during command execution\n",
__func__);
+ /* No point in waiting for the command to complete if execution
+ * failed.
+ */
+ return result;
}
- /* WRSR performs a self-timed erase before the changes take effect. */
+ /* WRSR performs a self-timed erase before the changes take effect.
+ * This may take 50-85 ms in most cases, and some chips apparently
+ * allow running RDSR only once. Therefore pick an initial delay of
+ * 100 ms, then wait in 10 ms steps until a total of 5 s have elapsed.
+ */
programmer_delay(100 * 1000);
- return result;
+ while (spi_read_status_register() & JEDEC_RDSR_BIT_WIP) {
+ if (++i > 490) {
+ msg_cerr("Error: WIP bit after WRSR never cleared\n");
+ return TIMEOUT_ERROR;
+ }
+ programmer_delay(10 * 1000);
+ }
+ return 0;
}
static int spi_write_status_register_wren(struct flashchip *flash, int status)
{
int result;
+ int i = 0;
struct spi_command cmds[] = {
{
/* WRSR requires either EWSR or WREN depending on chip type. */
@@ -911,10 +928,25 @@ static int spi_write_status_register_wren(struct flashchip *flash, int status)
if (result) {
msg_cerr("%s failed during command execution\n",
__func__);
+ /* No point in waiting for the command to complete if execution
+ * failed.
+ */
+ return result;
}
- /* WRSR performs a self-timed erase before the changes take effect. */
+ /* WRSR performs a self-timed erase before the changes take effect.
+ * This may take 50-85 ms in most cases, and some chips apparently
+ * allow running RDSR only once. Therefore pick an initial delay of
+ * 100 ms, then wait in 10 ms steps until a total of 5 s have elapsed.
+ */
programmer_delay(100 * 1000);
- return result;
+ while (spi_read_status_register() & JEDEC_RDSR_BIT_WIP) {
+ if (++i > 490) {
+ msg_cerr("Error: WIP bit after WRSR never cleared\n");
+ return TIMEOUT_ERROR;
+ }
+ programmer_delay(10 * 1000);
+ }
+ return 0;
}
static int spi_write_status_register(struct flashchip *flash, int status)