diff options
author | Aseda Aboagye <aaboagye@google.com> | 2017-02-07 18:52:13 -0800 |
---|---|---|
committer | chrome-bot <chrome-bot@chromium.org> | 2017-02-09 22:50:50 -0800 |
commit | b889e47410698986822712078ec232c1715b4845 (patch) | |
tree | 8d3ec71d39f90e60fb3f2ba00fc0d1e2f9350ad0 /board | |
parent | 4ce529e25acd4683f7232dc627c72cb7f3f84d77 (diff) | |
download | chrome-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.c | 32 | ||||
-rw-r--r-- | board/cr50/board.h | 1 | ||||
-rw-r--r-- | board/cr50/scratch_reg1.h | 1 | ||||
-rw-r--r-- | board/cr50/wp.c | 58 | ||||
-rw-r--r-- | board/cr50/wp.h | 13 |
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); |