summaryrefslogtreecommitdiff
path: root/board
diff options
context:
space:
mode:
authorAseda Aboagye <aaboagye@google.com>2017-02-07 18:52:13 -0800
committerchrome-bot <chrome-bot@chromium.org>2017-02-09 22:50:50 -0800
commitb889e47410698986822712078ec232c1715b4845 (patch)
tree8d3ec71d39f90e60fb3f2ba00fc0d1e2f9350ad0 /board
parent4ce529e25acd4683f7232dc627c72cb7f3f84d77 (diff)
downloadchrome-ec-b889e47410698986822712078ec232c1715b4845.tar.gz
cr50: Use BATT_PRES_L as source of write protect.
This commit changes the Cr50 write protect behaviour to simply follow the state of the battery present pin. The state can still be overridden both ways by using the `wp` console command. A user can either force write protect enabled or force write protect disabled. Additionally, the behaviour can be reset to follow the state of the battery pin by issuing `wp follow_batt_pres`. However, the ability to force the write protect state requires an unlocked console. BUG=chrome-os-partner:62726 BRANCH=None TEST=Plug in battery, verify that WP is enabled. Plug in AC and unplug battery, verify that WP is disabled. TEST=Unplug battery, unplug AC, plug in AC, verify that WP is disabled. TEST=Unplug battery, verify that WP is disabled. Use `wp' command to enable WP, verify that it is enabled. TEST=Plug in battery, disable WP using `wp` command, put cr50 into deep sleep, wake it up, verify that WP is still disabled. TEST=Plug in AC, plug in battery, disable WP using `wp` command, unplug and plug battery connector, verify that WP is still disabled. Change-Id: I83d9820067800801ddbde311eab0853c3c2216d3 Signed-off-by: Aseda Aboagye <aaboagye@google.com> Reviewed-on: https://chromium-review.googlesource.com/439485 Commit-Ready: Aseda Aboagye <aaboagye@chromium.org> Tested-by: Aseda Aboagye <aaboagye@chromium.org> Reviewed-by: Vadim Bendebury <vbendeb@chromium.org>
Diffstat (limited to 'board')
-rw-r--r--board/cr50/board.c32
-rw-r--r--board/cr50/board.h1
-rw-r--r--board/cr50/scratch_reg1.h1
-rw-r--r--board/cr50/wp.c58
-rw-r--r--board/cr50/wp.h13
5 files changed, 95 insertions, 10 deletions
diff --git a/board/cr50/board.c b/board/cr50/board.c
index ece5b27875..074bfd7c17 100644
--- a/board/cr50/board.c
+++ b/board/cr50/board.c
@@ -35,6 +35,7 @@
#include "usb_spi.h"
#include "usb_i2c.h"
#include "util.h"
+#include "wp.h"
/* Define interrupt and gpio structs */
#include "gpio_list.h"
@@ -773,6 +774,11 @@ struct device_config device_states[] = {
.detect = GPIO_DETECT_EC,
.name = "EC"
},
+ [DEVICE_BATTERY_PRESENT] = {
+ .deferred = NULL,
+ .detect = GPIO_BATT_PRES_L,
+ .name = "BattPrsnt"
+ },
};
BUILD_ASSERT(ARRAY_SIZE(device_states) == DEVICE_COUNT);
@@ -816,6 +822,32 @@ void device_state_on(enum gpio_signal signal)
void board_update_device_state(enum device_type device)
{
+ if (device == DEVICE_BATTERY_PRESENT) {
+ /* The battery presence pin is active low. */
+ int bp = !gpio_get_level(device_states[device].detect);
+
+ /*
+ * We use BATT_PRES_L as the source for write protect. However,
+ * since it can be overridden by a console command, only change
+ * the write protect state when the battery presence pin has
+ * changed and we're not forcing it.
+ */
+ if (device_set_state(device,
+ bp ?
+ DEVICE_STATE_ON : DEVICE_STATE_OFF)) {
+ CPRINTS("battery %spresent", bp ? "" : "NOT ");
+
+ /*
+ * Only update the write protect state if we're not
+ * forcing it.
+ */
+ if ((GREG32(PMU, LONG_LIFE_SCRATCH1) & BOARD_FORCING_WP)
+ == 0)
+ set_wp_state(bp);
+ }
+ return;
+ }
+
if (device == DEVICE_SERVO && servo_state_unknown())
return;
diff --git a/board/cr50/board.h b/board/cr50/board.h
index bc48b31d26..5f1bc82cde 100644
--- a/board/cr50/board.h
+++ b/board/cr50/board.h
@@ -144,6 +144,7 @@ enum device_type {
DEVICE_AP = 0,
DEVICE_EC,
DEVICE_SERVO,
+ DEVICE_BATTERY_PRESENT,
DEVICE_COUNT
};
diff --git a/board/cr50/scratch_reg1.h b/board/cr50/scratch_reg1.h
index 2fb47601a8..0383766dc2 100644
--- a/board/cr50/scratch_reg1.h
+++ b/board/cr50/scratch_reg1.h
@@ -33,6 +33,7 @@
*/
#define BOARD_CONSOLE_UNLOCKED (1 << 7)
#define BOARD_WP_ASSERTED (1 << 8)
+#define BOARD_FORCING_WP (1 << 9)
/*
* Macro to capture all properties related to board strapping pins. This must be
diff --git a/board/cr50/wp.c b/board/cr50/wp.c
index 493f617aab..01fdf2e116 100644
--- a/board/cr50/wp.c
+++ b/board/cr50/wp.c
@@ -15,11 +15,12 @@
#include "task.h"
#include "timer.h"
#include "tpm_registers.h"
+#include "util.h"
#define CPRINTS(format, args...) cprints(CC_RBOX, format, ## args)
#define CPRINTF(format, args...) cprintf(CC_RBOX, format, ## args)
-static void set_wp_state(int asserted)
+void set_wp_state(int asserted)
{
/* Enable writing to the long life register */
GWRITE_FIELD(PMU, LONG_LIFE_SCRATCH_WR_EN, REG1, 1);
@@ -36,30 +37,67 @@ static void set_wp_state(int asserted)
GWRITE_FIELD(PMU, LONG_LIFE_SCRATCH_WR_EN, REG1, 0);
}
+/**
+ * Force write protect state or follow battery presence.
+ *
+ * @param force: Force write protect to wp_en if non-zero, otherwise use battery
+ * presence as the source.
+ * @param wp_en: 0: Deassert WP. 1: Assert WP.
+ */
+static void force_write_protect(int force, int wp_en)
+{
+ /* Enable writing to the long life register */
+ GWRITE_FIELD(PMU, LONG_LIFE_SCRATCH_WR_EN, REG1, 1);
+
+ if (force) {
+ /* Force WP regardless of battery presence. */
+ GREG32(PMU, LONG_LIFE_SCRATCH1) |= BOARD_FORCING_WP;
+ } else {
+ /* Stop forcing write protect. */
+ GREG32(PMU, LONG_LIFE_SCRATCH1) &= ~BOARD_FORCING_WP;
+ /*
+ * Use battery presence as the value for write protect.
+ * Inverted because the signal is active low.
+ */
+ wp_en = !gpio_get_level(GPIO_BATT_PRES_L);
+ }
+
+ /* Disable writing to the long life register */
+ GWRITE_FIELD(PMU, LONG_LIFE_SCRATCH_WR_EN, REG1, 0);
+
+ /* Update the WP state. */
+ set_wp_state(!!wp_en);
+}
+
static int command_wp(int argc, char **argv)
{
int val;
+ int forced;
if (argc > 1) {
if (console_is_restricted()) {
ccprintf("Console is locked, no parameters allowed\n");
} else {
- if (!parse_bool(argv[1], &val))
+ if (strncasecmp(argv[1], "follow_batt_pres", 16) == 0)
+ force_write_protect(0, -1);
+ else if (parse_bool(argv[1], &val))
+ force_write_protect(1, val);
+ else
return EC_ERROR_PARAM1;
-
- set_wp_state(!!val);
}
}
/* Invert, because active low */
val = !GREG32(RBOX, EC_WP_L);
- ccprintf("Flash WP is %s\n", val ? "enabled" : "disabled");
+ forced = GREG32(PMU, LONG_LIFE_SCRATCH1) & BOARD_FORCING_WP;
+ ccprintf("Flash WP is %s%s\n", forced ? "forced " : "",
+ val ? "enabled" : "disabled");
return EC_SUCCESS;
}
DECLARE_SAFE_CONSOLE_COMMAND(wp, command_wp,
- "[<BOOLEAN>]",
+ "[<BOOLEAN>/follow_batt_pres]",
"Get/set the flash HW write-protect signal");
/* When the system is locked down, provide a means to unlock it */
@@ -132,16 +170,16 @@ static void unlock_the_console(void)
static void init_console_lock_and_wp(void)
{
/*
- * On an unexpected reboot or a system rollback reset the console and
- * write protect states.
+ * On an unexpected reboot or a system rollback reset the console lock
+ * and write protect states.
*/
if (system_rollback_detected() ||
!(system_get_reset_flags() & RESET_FLAG_HIBERNATE)) {
/* Reset the console lock to the default value */
set_console_lock_state(console_restricted_state);
- /* Always assert WP on H1 cold resets, reboots or fallbacks. */
- set_wp_state(1);
+ /* Use BATT_PRES_L as the source for write protect. */
+ set_wp_state(!gpio_get_level(GPIO_BATT_PRES_L));
return;
}
diff --git a/board/cr50/wp.h b/board/cr50/wp.h
new file mode 100644
index 0000000000..e2ae172df8
--- /dev/null
+++ b/board/cr50/wp.h
@@ -0,0 +1,13 @@
+/* Copyright 2017 The Chromium OS Authors. All rights reserved.
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#include "common.h"
+
+/**
+ * Set the current write protect state in RBOX and long life scratch register.
+ *
+ * @param asserted: 0 to disable write protect, otherwise enable write protect.
+ */
+void set_wp_state(int asserted);