summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorShawn Nematbakhsh <shawnn@chromium.org>2017-02-16 14:26:46 -0800
committerChromeOS Commit Bot <chromeos-commit-bot@chromium.org>2017-02-27 19:17:28 +0000
commit841076f725473e3b650985b0443558173108807f (patch)
treed7289bfbaaef360b0a205dbe6ffe9646cdda3667
parentf114dc5ebf38504b0b74b42badef16327480474a (diff)
downloadchrome-ec-841076f725473e3b650985b0443558173108807f.tar.gz
system: Add generic bbram read / write routines
Add generic routines to read or write a byte to battery-backed RAM, and implement vbnvcontext get/set using these routines. BUG=chrome-os-partner:62952 BRANCH=reef TEST=On reef, with subsequent commit, run "cutoff" on the console, reattach AC, and verify device successfully wakes. Also verify Rp is dropped on console 'reboot' and F3 + power from RW. Signed-off-by: Shawn Nematbakhsh <shawnn@chromium.org> Change-Id: I14691923f2e5198e901b6b5199e92c58c68cd18d Reviewed-on: https://chromium-review.googlesource.com/444444 Commit-Ready: Shawn N <shawnn@chromium.org> Tested-by: Shawn N <shawnn@chromium.org> Reviewed-by: Randall Spangler <rspangler@chromium.org> (cherry picked from commit f0b564b4a031fdc974a98a13308a62a460ae4a69) Reviewed-on: https://chromium-review.googlesource.com/446715
-rw-r--r--chip/g/system.c4
-rw-r--r--chip/host/system.c4
-rw-r--r--chip/ish/system.c6
-rw-r--r--chip/it83xx/system.c28
-rw-r--r--chip/lm4/system.c4
-rw-r--r--chip/mec1322/system.c26
-rw-r--r--chip/npcx/system.c115
-rw-r--r--chip/nrf51/system.c4
-rw-r--r--chip/stm32/system.c55
-rw-r--r--common/system.c13
-rw-r--r--include/system.h31
11 files changed, 182 insertions, 108 deletions
diff --git a/chip/g/system.c b/chip/g/system.c
index 85fcf63774..02ccb7eea7 100644
--- a/chip/g/system.c
+++ b/chip/g/system.c
@@ -171,12 +171,12 @@ const char *system_get_chip_revision(void)
}
/* TODO(crosbug.com/p/33822): Where can we store stuff persistently? */
-int system_get_vbnvcontext(uint8_t *block)
+int system_get_bbram(enum system_bbram_idx idx, uint8_t *value)
{
return 0;
}
-int system_set_vbnvcontext(const uint8_t *block)
+int system_set_bbram(enum system_bbram_idx idx, uint8_t value)
{
return 0;
}
diff --git a/chip/host/system.c b/chip/host/system.c
index 757d00fc51..26965c5d16 100644
--- a/chip/host/system.c
+++ b/chip/host/system.c
@@ -188,12 +188,12 @@ const char *system_get_chip_revision(void)
return "";
}
-int system_get_vbnvcontext(uint8_t *block)
+int system_get_bbram(enum system_bbram_idx idx, uint8_t *value)
{
return EC_ERROR_UNIMPLEMENTED;
}
-int system_set_vbnvcontext(const uint8_t *block)
+int system_set_bbram(enum system_bbram_idx idx, uint8_t value)
{
return EC_ERROR_UNIMPLEMENTED;
}
diff --git a/chip/ish/system.c b/chip/ish/system.c
index 75f1d5a4a8..7110e85645 100644
--- a/chip/ish/system.c
+++ b/chip/ish/system.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2016 The Chromium OS Authors. All rights reserved.
+/* Copyright 2016 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.
*/
@@ -76,12 +76,12 @@ const char *system_get_chip_revision(void)
return buf;
}
-int system_get_vbnvcontext(uint8_t *block)
+int system_get_bbram(enum system_bbram_idx idx, uint8_t *value)
{
return EC_ERROR_UNIMPLEMENTED;
}
-int system_set_vbnvcontext(const uint8_t *block)
+int system_set_bbram(enum system_bbram_idx idx, uint8_t value)
{
return EC_ERROR_UNIMPLEMENTED;
}
diff --git a/chip/it83xx/system.c b/chip/it83xx/system.c
index 32ab43231f..055c586cd8 100644
--- a/chip/it83xx/system.c
+++ b/chip/it83xx/system.c
@@ -226,25 +226,37 @@ const char *system_get_chip_revision(void)
return buf;
}
-int system_get_vbnvcontext(uint8_t *block)
+static int bram_idx_lookup(enum system_bbram_idx idx)
{
- int i;
+ if (idx >= SYSTEM_BBRAM_IDX_VBNVBLOCK0 &&
+ idx <= SYSTEM_BBRAM_IDX_VBNVBLOCK15)
+ return BRAM_IDX_NVCONTEXT +
+ idx - SYSTEM_BBRAM_IDX_VBNVBLOCK0;
+ return -1;
+}
+
+int system_get_bbram(enum system_bbram_idx idx, uint8_t *value)
+{
+ int bram_idx = bram_idx_lookup(idx);
- for (i = 0; i < EC_VBNV_BLOCK_SIZE; i++)
- block[i] = IT83XX_BRAM_BANK0((BRAM_IDX_NVCONTEXT + i));
+ if (bram_idx < 0)
+ return EC_ERROR_INVAL;
+ *value = IT83XX_BRAM_BANK0(bram_idx);
return EC_SUCCESS;
}
-int system_set_vbnvcontext(const uint8_t *block)
+int system_set_bbram(enum system_bbram_idx idx, uint8_t value)
{
- int i;
+ int bram_idx = bram_idx_lookup(idx);
- for (i = 0; i < EC_VBNV_BLOCK_SIZE; i++)
- IT83XX_BRAM_BANK0((BRAM_IDX_NVCONTEXT + i)) = block[i];
+ if (bram_idx < 0)
+ return EC_ERROR_INVAL;
+ IT83XX_BRAM_BANK0(bram_idx) = value;
return EC_SUCCESS;
}
+
#define BRAM_NVCONTEXT_SIZE (BRAM_IDX_NVCONTEXT_END - BRAM_IDX_NVCONTEXT + 1)
BUILD_ASSERT(EC_VBNV_BLOCK_SIZE <= BRAM_NVCONTEXT_SIZE);
diff --git a/chip/lm4/system.c b/chip/lm4/system.c
index cb1cf8cef0..684b520dae 100644
--- a/chip/lm4/system.c
+++ b/chip/lm4/system.c
@@ -600,12 +600,12 @@ const char *system_get_chip_name(void)
}
}
-int system_get_vbnvcontext(uint8_t *block)
+int system_get_bbram(enum system_bbram_idx idx, uint8_t *value)
{
return EC_ERROR_UNIMPLEMENTED;
}
-int system_set_vbnvcontext(const uint8_t *block)
+int system_set_bbram(enum system_bbram_idx idx, uint8_t value)
{
return EC_ERROR_UNIMPLEMENTED;
}
diff --git a/chip/mec1322/system.c b/chip/mec1322/system.c
index 26d89c10e3..54ff2f45c8 100644
--- a/chip/mec1322/system.c
+++ b/chip/mec1322/system.c
@@ -23,7 +23,7 @@
/* Indices for hibernate data registers (RAM backed by VBAT) */
enum hibdata_index {
HIBDATA_INDEX_SCRATCHPAD = 0, /* General-purpose scratchpad */
- HIBDATA_INDEX_SAVED_RESET_FLAGS /* Saved reset flags */
+ HIBDATA_INDEX_SAVED_RESET_FLAGS, /* Saved reset flags */
};
static void check_reset_cause(void)
@@ -166,14 +166,30 @@ const char *system_get_chip_revision(void)
return buf;
}
-int system_get_vbnvcontext(uint8_t *block)
+int system_get_bbram(enum system_bbram_idx idx, uint8_t *value)
{
- return EC_ERROR_UNIMPLEMENTED;
+ enum hibdata_index hibdata;
+
+ switch (idx) {
+ default:
+ return EC_ERROR_UNIMPLEMENTED;
+ }
+
+ *value = MEC1322_VBAT_RAM(hibdata);
+ return EC_SUCCESS;
}
-int system_set_vbnvcontext(const uint8_t *block)
+int system_set_bbram(enum system_bbram_idx idx, uint8_t value)
{
- return EC_ERROR_UNIMPLEMENTED;
+ enum hibdata_index hibdata;
+
+ switch (idx) {
+ default:
+ return EC_ERROR_UNIMPLEMENTED;
+ }
+
+ MEC1322_VBAT_RAM(hibdata) = value;
+ return EC_SUCCESS;
}
int system_set_scratchpad(uint32_t value)
diff --git a/chip/npcx/system.c b/chip/npcx/system.c
index 2d11217f5b..a747cbf866 100644
--- a/chip/npcx/system.c
+++ b/chip/npcx/system.c
@@ -6,21 +6,21 @@
/* System module for Chrome EC : NPCX hardware specific implementation */
#include "clock.h"
+#include "clock_chip.h"
#include "common.h"
#include "console.h"
#include "cpu.h"
+#include "gpio.h"
+#include "hooks.h"
#include "host_command.h"
+#include "hwtimer_chip.h"
#include "registers.h"
+#include "rom_chip.h"
#include "system.h"
-#include "hooks.h"
+#include "system_chip.h"
#include "task.h"
#include "timer.h"
#include "util.h"
-#include "gpio.h"
-#include "hwtimer_chip.h"
-#include "system_chip.h"
-#include "clock_chip.h"
-#include "rom_chip.h"
/* Flags for BBRM_DATA_INDEX_WAKE */
#define HIBERNATE_WAKE_MTC (1 << 0) /* MTC alarm */
@@ -83,6 +83,13 @@ void system_watchdog_reset(void)
interrupt_enable();
}
+/* Return true if index is stored as a single byte in bbram */
+static int bbram_is_byte_access(enum bbram_data_index index)
+{
+ return (index >= BBRM_DATA_INDEX_VBNVCNTXT &&
+ index < BBRM_DATA_INDEX_RAMLOG);
+}
+
/**
* Read battery-backed ram (BBRAM) at specified index.
*
@@ -91,8 +98,10 @@ void system_watchdog_reset(void)
static uint32_t bbram_data_read(enum bbram_data_index index)
{
uint32_t value = 0;
+ int bytes = bbram_is_byte_access(index) ? 1 : 4;
+
/* Check index */
- if (index < 0 || index >= NPCX_BBRAM_SIZE)
+ if (index < 0 || index + bytes >= NPCX_BBRAM_SIZE)
return 0;
/* BBRAM is valid */
@@ -100,12 +109,14 @@ static uint32_t bbram_data_read(enum bbram_data_index index)
return 0;
/* Read BBRAM */
- value += NPCX_BBRAM(index + 3);
- value = value << 8;
- value += NPCX_BBRAM(index + 2);
- value = value << 8;
- value += NPCX_BBRAM(index + 1);
- value = value << 8;
+ if (bytes == 4) {
+ value += NPCX_BBRAM(index + 3);
+ value = value << 8;
+ value += NPCX_BBRAM(index + 2);
+ value = value << 8;
+ value += NPCX_BBRAM(index + 1);
+ value = value << 8;
+ }
value += NPCX_BBRAM(index);
return value;
@@ -118,6 +129,8 @@ static uint32_t bbram_data_read(enum bbram_data_index index)
*/
static int bbram_data_write(enum bbram_data_index index, uint32_t value)
{
+ int bytes = bbram_is_byte_access(index) ? 1 : 4;
+
/* Check index */
if (index < 0 || index >= NPCX_BBRAM_SIZE)
return EC_ERROR_INVAL;
@@ -127,15 +140,48 @@ static int bbram_data_write(enum bbram_data_index index, uint32_t value)
return EC_ERROR_INVAL;
/* Write BBRAM */
- NPCX_BBRAM(index) = value & 0xFF;
- NPCX_BBRAM(index + 1) = (value >> 8) & 0xFF;
- NPCX_BBRAM(index + 2) = (value >> 16) & 0xFF;
- NPCX_BBRAM(index + 3) = (value >> 24) & 0xFF;
+ NPCX_BBRAM(index) = value & 0xFF;
+ if (bytes == 4) {
+ NPCX_BBRAM(index + 1) = (value >> 8) & 0xFF;
+ NPCX_BBRAM(index + 2) = (value >> 16) & 0xFF;
+ NPCX_BBRAM(index + 3) = (value >> 24) & 0xFF;
+ }
/* Wait for write-complete */
return EC_SUCCESS;
}
+/* Map idx to a returned BBRM_DATA_INDEX_*, or return -1 on invalid idx */
+static int bbram_idx_lookup(enum system_bbram_idx idx)
+{
+ if (idx >= SYSTEM_BBRAM_IDX_VBNVBLOCK0 &&
+ idx <= SYSTEM_BBRAM_IDX_VBNVBLOCK15)
+ return BBRM_DATA_INDEX_VBNVCNTXT +
+ idx - SYSTEM_BBRAM_IDX_VBNVBLOCK0;
+ return -1;
+}
+
+int system_get_bbram(enum system_bbram_idx idx, uint8_t *value)
+{
+ int bbram_idx = bbram_idx_lookup(idx);
+
+ if (bbram_idx < 0)
+ return EC_ERROR_INVAL;
+
+ *value = bbram_data_read(bbram_idx);
+ return EC_SUCCESS;
+}
+
+int system_set_bbram(enum system_bbram_idx idx, uint8_t value)
+{
+ int bbram_idx = bbram_idx_lookup(idx);
+
+ if (bbram_idx < 0)
+ return EC_ERROR_INVAL;
+
+ return bbram_data_write(bbram_idx, value);
+}
+
/* MTC functions */
uint32_t system_get_rtc_sec(void)
{
@@ -673,41 +719,6 @@ const char *system_get_chip_revision(void)
BUILD_ASSERT(BBRM_DATA_INDEX_VBNVCNTXT + EC_VBNV_BLOCK_SIZE <= NPCX_BBRAM_SIZE);
/**
- * Get/Set VbNvContext in non-volatile storage. The block should be 16 bytes
- * long, which is the current size of VbNvContext block.
- *
- * @param block Pointer to a buffer holding VbNvContext.
- * @return 0 on success, !0 on error.
- */
-int system_get_vbnvcontext(uint8_t *block)
-{
- int i;
-
- if (IS_BIT_SET(NPCX_BKUP_STS, NPCX_BKUP_STS_IBBR)) {
- memset(block, 0, EC_VBNV_BLOCK_SIZE);
- return EC_SUCCESS;
- }
-
- for (i = 0; i < EC_VBNV_BLOCK_SIZE; ++i)
- block[i] = NPCX_BBRAM(BBRM_DATA_INDEX_VBNVCNTXT + i);
-
- return EC_SUCCESS;
-}
-
-int system_set_vbnvcontext(const uint8_t *block)
-{
- int i;
-
- if (IS_BIT_SET(NPCX_BKUP_STS, NPCX_BKUP_STS_IBBR))
- return EC_ERROR_INVAL;
-
- for (i = 0; i < EC_VBNV_BLOCK_SIZE; i++)
- NPCX_BBRAM(BBRM_DATA_INDEX_VBNVCNTXT + i) = block[i];
-
- return EC_SUCCESS;
-}
-
-/**
* Set a scratchpad register to the specified value.
*
* The scratchpad register must maintain its contents across a
diff --git a/chip/nrf51/system.c b/chip/nrf51/system.c
index 94c36202e4..61bd2311a8 100644
--- a/chip/nrf51/system.c
+++ b/chip/nrf51/system.c
@@ -107,13 +107,13 @@ void system_reset(int flags)
;
}
-int system_get_vbnvcontext(uint8_t *block)
+int system_get_bbram(enum system_bbram_idx idx, uint8_t *value)
{
CPRINTS("TODO: implement %s()", __func__);
return EC_ERROR_UNIMPLEMENTED;
}
-int system_set_vbnvcontext(const uint8_t *block)
+int system_set_bbram(enum system_bbram_idx idx, uint8_t value)
{
CPRINTS("TODO: implement %s()", __func__);
return EC_ERROR_UNIMPLEMENTED;
diff --git a/chip/stm32/system.c b/chip/stm32/system.c
index 605f095f95..466ebc50c9 100644
--- a/chip/stm32/system.c
+++ b/chip/stm32/system.c
@@ -336,36 +336,47 @@ const char *system_get_chip_revision(void)
return "";
}
-int system_get_vbnvcontext(uint8_t *block)
+static int bkpdata_index_lookup(enum system_bbram_idx idx, int *msb)
{
- enum bkpdata_index i;
- uint16_t value;
-
- for (i = BKPDATA_INDEX_VBNV_CONTEXT0;
- i <= BKPDATA_INDEX_VBNV_CONTEXT7; i++) {
- value = bkpdata_read(i);
- *block++ = (uint8_t)(value & 0xff);
- *block++ = (uint8_t)(value >> 8);
+ *msb = 0;
+
+ if (idx >= SYSTEM_BBRAM_IDX_VBNVBLOCK0 &&
+ idx <= SYSTEM_BBRAM_IDX_VBNVBLOCK15) {
+ *msb = (idx - SYSTEM_BBRAM_IDX_VBNVBLOCK0) % 2;
+ return BKPDATA_INDEX_VBNV_CONTEXT0 +
+ (idx - SYSTEM_BBRAM_IDX_VBNVBLOCK0) / 2;
}
+ return -1;
+}
+
+int system_get_bbram(enum system_bbram_idx idx, uint8_t *value)
+{
+ int msb = 0;
+ int bkpdata_index = bkpdata_index_lookup(idx, &msb);
+
+ if (bkpdata_index < 0)
+ return EC_ERROR_INVAL;
+ *value = (bkpdata_read(bkpdata_index) >> (8 * msb)) & 0xff;
return EC_SUCCESS;
}
-int system_set_vbnvcontext(const uint8_t *block)
+int system_set_bbram(enum system_bbram_idx idx, uint8_t value)
{
- enum bkpdata_index i;
- uint16_t value;
- int err;
-
- for (i = BKPDATA_INDEX_VBNV_CONTEXT0;
- i <= BKPDATA_INDEX_VBNV_CONTEXT7; i++) {
- value = *block++;
- value |= ((uint16_t)*block++) << 8;
- err = bkpdata_write(i, value);
- if (err)
- return err;
- }
+ uint16_t read;
+ int msb = 0;
+ int bkpdata_index = bkpdata_index_lookup(idx, &msb);
+
+ if (bkpdata_index < 0)
+ return EC_ERROR_INVAL;
+
+ read = bkpdata_read(bkpdata_index);
+ if (msb)
+ read = (read & 0xff) | (value << 8);
+ else
+ read = (read & 0xff00) | value;
+ bkpdata_write(bkpdata_index, read);
return EC_SUCCESS;
}
diff --git a/common/system.c b/common/system.c
index 5baea57c95..963ce2ff52 100644
--- a/common/system.c
+++ b/common/system.c
@@ -1227,17 +1227,22 @@ int host_command_vbnvcontext(struct host_cmd_handler_args *args)
{
const struct ec_params_vbnvcontext *p = args->params;
struct ec_response_vbnvcontext *r;
+ int i;
switch (p->op) {
case EC_VBNV_CONTEXT_OP_READ:
r = args->response;
- if (system_get_vbnvcontext(r->block))
- return EC_RES_ERROR;
+ for (i = 0; i < EC_VBNV_BLOCK_SIZE; ++i)
+ if (system_get_bbram(SYSTEM_BBRAM_IDX_VBNVBLOCK0 + i,
+ r->block + i))
+ return EC_RES_ERROR;
args->response_size = sizeof(*r);
break;
case EC_VBNV_CONTEXT_OP_WRITE:
- if (system_set_vbnvcontext(p->block))
- return EC_RES_ERROR;
+ for (i = 0; i < EC_VBNV_BLOCK_SIZE; ++i)
+ if (system_set_bbram(SYSTEM_BBRAM_IDX_VBNVBLOCK0 + i,
+ p->block[i]))
+ return EC_RES_ERROR;
break;
default:
return EC_RES_ERROR;
diff --git a/include/system.h b/include/system.h
index fa16846303..76db18053c 100644
--- a/include/system.h
+++ b/include/system.h
@@ -263,15 +263,34 @@ const char *system_get_chip_vendor(void);
const char *system_get_chip_name(void);
const char *system_get_chip_revision(void);
+/*
+ * Common bbram entries. Chips don't necessarily need to implement
+ * all of these, error will be returned from system_get/set_bbram if
+ * not implemented.
+ */
+enum system_bbram_idx {
+ /*
+ * TODO(crbug.com/693210): Consider boards without vbnvcontext
+ * host command.
+ */
+ SYSTEM_BBRAM_IDX_VBNVBLOCK0 = 0,
+ /*
+ * ...
+ * 16 total bytes of VB NVRAM.
+ * ...
+ */
+ SYSTEM_BBRAM_IDX_VBNVBLOCK15 = 15,
+};
+
/**
- * Get/Set VbNvContext in non-volatile storage. The block should be 16 bytes
- * long, which is the current size of VbNvContext block.
+ * Get/Set byte in battery-backed storage.
*
- * @param block Pointer to a buffer holding VbNvContext.
- * @return 0 on success, !0 on error.
+ * @param idx bbram byte to get / set.
+ * @param value byte to read / write from / to bbram.
+ * @return 0 on success, !0 on error.
*/
-int system_get_vbnvcontext(uint8_t *block);
-int system_set_vbnvcontext(const uint8_t *block);
+int system_get_bbram(enum system_bbram_idx idx, uint8_t *value);
+int system_set_bbram(enum system_bbram_idx idx, uint8_t value);
/**
* Put the EC in hibernate (lowest EC power state).