summaryrefslogtreecommitdiff
path: root/chip/lm4/flash.c
diff options
context:
space:
mode:
authorRandall Spangler <rspangler@chromium.org>2012-07-16 14:19:59 -0700
committerGerrit <chrome-bot@google.com>2012-07-16 17:49:10 -0700
commitacf6f963a160f045d6b4c58f0ee3e249ded76b4e (patch)
tree1c724e7480104f9fa1284f6a3f013cbd44501c12 /chip/lm4/flash.c
parenta42edb86c59cbc145eb99bd5b65bbd1f5567320e (diff)
downloadchrome-ec-acf6f963a160f045d6b4c58f0ee3e249ded76b4e.tar.gz
Flash pre-init reboots if it needs to clear protection registers
BUG=chrome-os-partner:11171 TEST=manual 1. Clear some of the writable-bits in the flash registers > ww 0x400fe40c 0xffff1234 write 0x400fe40c = 0xffff1234 > rw 0x400fe40c read 0x400fe40c = 0xffff1234 2. Reset using power+refresh 3. Register should be clear again > rw 0x400fe40c read 0x400fe40c = 0xffffffff 4. Sysinfo should indicate reset-pin reason AND hard-reset reason > sysinfo Reset flags: 0x0000000a (reset-pin power-on) 5. Reset using power+refresh 6. Sysinfo should indicate reset-pin reason only > sysinfo Reset flags: 0x00000002 (reset-pin) 7. Clear writable-bits again > ww 0x400fe40c 0xffff1234 write 0x400fe40c = 0xffff1234 8. Jump to another image. This should NOT trigger a hard reset. > sysjump A > sysinfo Reset flags: 0x00000402 (reset-pin sysjump) Change-Id: Ie1d6af2acc68217bb82faae464798ee85d63d1ea Signed-off-by: Randall Spangler <rspangler@chromium.org> Reviewed-on: https://gerrit.chromium.org/gerrit/27540 Reviewed-by: Bill Richardson <wfrichar@chromium.org>
Diffstat (limited to 'chip/lm4/flash.c')
-rw-r--r--chip/lm4/flash.c41
1 files changed, 41 insertions, 0 deletions
diff --git a/chip/lm4/flash.c b/chip/lm4/flash.c
index 99289b4280..20c90793bd 100644
--- a/chip/lm4/flash.c
+++ b/chip/lm4/flash.c
@@ -7,6 +7,7 @@
#include "flash.h"
#include "registers.h"
+#include "system.h"
#include "timer.h"
#include "util.h"
#include "watchdog.h"
@@ -180,3 +181,43 @@ void flash_physical_set_protect(int block)
{
LM4_FLASH_FMPPE[F_BANK(block)] &= ~F_BIT(block);
}
+
+int flash_physical_pre_init(void)
+{
+ int reset_flags = system_get_reset_flags();
+ int any_wp = 0;
+ int i;
+
+ /*
+ * If we have already jumped between images, an earlier image could
+ * have applied write protection. Nothing additional needs to be done.
+ */
+ if (reset_flags & RESET_FLAG_SYSJUMP)
+ return EC_SUCCESS;
+
+ /* Check if any blocks are currently physically write-protected */
+ for (i = 0; i < (LM4_FLASH_FSIZE + 1) / 32; i++) {
+ if (LM4_FLASH_FMPPE[i] != 0xffffffff) {
+ any_wp = 1;
+ break;
+ }
+ }
+
+ /* If nothing is write-protected, done. */
+ if (!any_wp)
+ return EC_SUCCESS;
+
+ /*
+ * If the last reboot was a power-on reset, it should have cleared
+ * write-protect. If it didn't, then the flash write protect registers
+ * have been permanently committed and we can't fix that.
+ */
+ if (reset_flags & RESET_FLAG_POWER_ON)
+ return EC_ERROR_ACCESS_DENIED;
+
+ /* Otherwise, do a hard boot to clear the flash protection registers */
+ system_reset(SYSTEM_RESET_HARD | SYSTEM_RESET_PRESERVE_FLAGS);
+
+ /* That doesn't return, so if we're still here that's an error */
+ return EC_ERROR_UNKNOWN;
+}