From b37a7b7166e2408f3a4e25abadea00e3dff4a864 Mon Sep 17 00:00:00 2001 From: Vadim Bendebury Date: Thu, 11 Feb 2016 15:00:55 -0800 Subject: [PATCH] cr50: improve flash driver error reporting It is difficult to tell what went wrong if a flash operation failed. This patch adds printouts in cases of failure. The extension command console channel is used. BRANCH=none BUG=chrome-os-partner:37754 TEST=observed error messages reported while debugging firmware update code. Change-Id: I73d509ac5088249e8d34e32e760f3d2f063c91cd Signed-off-by: Vadim Bendebury Reviewed-on: https://chromium-review.googlesource.com/327411 Reviewed-by: Bill Richardson --- chip/g/flash.c | 30 +++++++++++++++++++++++------- 1 file changed, 23 insertions(+), 7 deletions(-) diff --git a/chip/g/flash.c b/chip/g/flash.c index f27ebb20d8..06cd2304ed 100644 --- a/chip/g/flash.c +++ b/chip/g/flash.c @@ -39,11 +39,14 @@ */ #include "common.h" +#include "console.h" #include "flash.h" #include "registers.h" #include "timer.h" #include "watchdog.h" +#define CPRINTF(format, args...) cprintf(CC_EXTENSION, format, ## args) + int flash_pre_init(void) { /* Enable access to the upper half of the flash */ @@ -104,10 +107,12 @@ static int do_flash_op(enum flash_op op, int byte_offset, int words) uint32_t opcode, tmp, errors; int retry_count, max_attempts, extra_prog_pulse, i; int timedelay_us = 100; + uint32_t prev_error = 0; /* Make sure the smart program/erase algorithms are enabled. */ if (!GREAD(FLASH, FSH_TIMING_PROG_SMART_ALGO_ON) || !GREAD(FLASH, FSH_TIMING_ERASE_SMART_ALGO_ON)) { + CPRINTF("%s:%d\n", __func__, __LINE__); return EC_ERROR_UNIMPLEMENTED; } @@ -120,8 +125,10 @@ static int do_flash_op(enum flash_op op, int byte_offset, int words) } /* If we can't clear the error status register then something is wrong. */ - if (tmp) + if (tmp) { + CPRINTF("%s:%d\n", __func__, __LINE__); return EC_ERROR_UNKNOWN; + } /* We have two flash banks. Adjust offset and registers accordingly. */ if (byte_offset >= CONFIG_FLASH_SIZE / 2) { @@ -176,12 +183,18 @@ static int do_flash_op(enum flash_op op, int byte_offset, int words) } /* Timed out waiting for control register to clear */ - if (tmp) + if (tmp) { + CPRINTF("%s:%d\n", __func__, __LINE__); return EC_ERROR_UNKNOWN; - + } /* Check error status */ errors = GREAD(FLASH, FSH_ERROR); + if (errors && (errors != prev_error)) { + prev_error = errors; + CPRINTF("%s:%d errors %x fsh_pe_control %p\n", + __func__, __LINE__, errors, fsh_pe_control); + } /* Error status is self-clearing. Read it until it does * (we hope). */ @@ -194,9 +207,10 @@ static int do_flash_op(enum flash_op op, int byte_offset, int words) /* If we can't clear the error status register then something * is wrong. */ - if (tmp) + if (tmp) { + CPRINTF("%s:%d\n", __func__, __LINE__); return EC_ERROR_UNKNOWN; - + } /* The operation was successful. */ if (!errors) { /* From the spec: @@ -213,7 +227,7 @@ static int do_flash_op(enum flash_op op, int byte_offset, int words) /* If there were errors after completion retry. */ watchdog_reload(); } - + CPRINTF("%s:%d, retry count %d\n", __func__, __LINE__, retry_count); return EC_ERROR_UNKNOWN; } @@ -282,8 +296,10 @@ int flash_physical_erase(int byte_offset, int num_bytes) ret = do_flash_op(OP_ERASE_BLOCK, byte_offset, num_bytes / 4); /* word count */ - if (ret) + if (ret) { + CPRINTF("Failed to erase block at %x\n", byte_offset); return ret; + } num_bytes -= CONFIG_FLASH_ERASE_SIZE; byte_offset += CONFIG_FLASH_ERASE_SIZE;