summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDivya Jyothi <divya.jyothi@intel.com>2015-02-04 16:44:39 -0800
committerChromeOS Commit Bot <chromeos-commit-bot@chromium.org>2015-02-09 18:33:55 +0000
commitb9c7de0f76d772645123ee11478659e3f68138a6 (patch)
tree83301a15fd28ccac8fd4a86223d65434db911f85
parent70afa3898ca1f28dc7e254b63f2d5fb12ad6b273 (diff)
downloadchrome-ec-b9c7de0f76d772645123ee11478659e3f68138a6.tar.gz
Strago: Support added for spi flash external to chip
BUG=None TEST=make -j buildall BRANCH=strago-mec Change-Id: I5376416ee7377bd455762424dd08f23fc36c5835 Signed-off-by: Divya Jyothi <divya.jyothi@intel.com> Reviewed-on: https://chromium-review.googlesource.com/246211 Reviewed-by: Shawn N <shawnn@chromium.org> Commit-Queue: Shawn N <shawnn@chromium.org> Tested-by: Shawn N <shawnn@chromium.org>
-rw-r--r--common/build.mk3
-rw-r--r--common/flash.c103
-rw-r--r--common/flash_internal.c112
-rw-r--r--common/flash_spi.c258
-rw-r--r--include/flash.h73
5 files changed, 445 insertions, 104 deletions
diff --git a/common/build.mk b/common/build.mk
index 2f15725682..141693b937 100644
--- a/common/build.mk
+++ b/common/build.mk
@@ -44,7 +44,8 @@ common-$(CONFIG_EXTPOWER_GPIO)+=extpower_gpio.o
common-$(CONFIG_EXTPOWER_SNOW)+=extpower_snow.o
common-$(CONFIG_EXTPOWER_SPRING)+=extpower_spring.o
common-$(CONFIG_FANS)+=fan.o
-common-$(CONFIG_FLASH)+=flash.o
+common-$(CONFIG_FLASH)+=flash.o flash_internal.o
+common-$(CONFIG_FLASH_SPI)+=flash.o flash_spi.o
common-$(CONFIG_FMAP)+=fmap.o
common-$(CONFIG_GESTURE_DETECTION)+=gesture.o
common-$(CONFIG_HOSTCMD_EVENTS)+=host_event_commands.o
diff --git a/common/flash.c b/common/flash.c
index 3b269deb46..e3419d53e2 100644
--- a/common/flash.c
+++ b/common/flash.c
@@ -23,86 +23,10 @@
#define CONFIG_FLASH_ERASED_VALUE32 (-1U)
#endif
-/* Persistent protection state - emulates a SPI status register for flashrom */
-struct persist_state {
- uint8_t version; /* Version of this struct */
- uint8_t flags; /* Lock flags (PERSIST_FLAG_*) */
- uint8_t reserved[2]; /* Reserved; set 0 */
-};
-
-#define PERSIST_STATE_VERSION 2 /* Expected persist_state.version */
-
/* Flags for persist_state.flags */
/* Protect persist state and RO firmware at boot */
#define PERSIST_FLAG_PROTECT_RO 0x02
-/**
- * Get the physical memory address of a flash offset
- *
- * This is used for direct flash access. We assume that the flash is
- * contiguous from this start address through to the end of the usable
- * flash.
- *
- * @param offset Flash offset to get address of
- * @param dataptrp Returns pointer to memory address of flash offset
- * @return pointer to flash memory offset, if ok, else NULL
- */
-static const char *flash_physical_dataptr(int offset)
-{
- return (char *)((uintptr_t)CONFIG_FLASH_BASE + offset);
-}
-
-/**
- * Read persistent state into pstate.
- *
- * @param pstate Destination for persistent state
- */
-static void flash_read_pstate(struct persist_state *pstate)
-{
- memcpy(pstate, flash_physical_dataptr(PSTATE_OFFSET), sizeof(*pstate));
-
- /* Sanity-check data and initialize if necessary */
- if (pstate->version != PERSIST_STATE_VERSION) {
- memset(pstate, 0, sizeof(*pstate));
- pstate->version = PERSIST_STATE_VERSION;
-#ifdef CONFIG_WP_ALWAYS
- pstate->flags |= PERSIST_FLAG_PROTECT_RO;
-#endif
- }
-}
-
-/**
- * Write persistent state from pstate, erasing if necessary.
- *
- * @param pstate Source persistent state
- * @return EC_SUCCESS, or nonzero if error.
- */
-static int flash_write_pstate(const struct persist_state *pstate)
-{
- struct persist_state current_pstate;
- int rv;
-
- /* Check if pstate has actually changed */
- flash_read_pstate(&current_pstate);
- if (!memcmp(&current_pstate, pstate, sizeof(*pstate)))
- return EC_SUCCESS;
-
- /* Erase pstate */
- rv = flash_physical_erase(PSTATE_OFFSET, PSTATE_SIZE);
- if (rv)
- return rv;
-
- /*
- * Note that if we lose power in here, we'll lose the pstate contents.
- * That's ok, because it's only possible to write the pstate before
- * it's protected.
- */
-
- /* Rewrite the data */
- return flash_physical_write(PSTATE_OFFSET, sizeof(*pstate),
- (const char *)pstate);
-}
-
int flash_dataptr(int offset, int size_req, int align, const char **ptrp)
{
if (offset < 0 || size_req < 0 ||
@@ -647,31 +571,4 @@ DECLARE_HOST_COMMAND(EC_CMD_FLASH_PROTECT,
flash_command_protect,
EC_VER_MASK(0) | EC_VER_MASK(1));
-static int flash_command_region_info(struct host_cmd_handler_args *args)
-{
- const struct ec_params_flash_region_info *p = args->params;
- struct ec_response_flash_region_info *r = args->response;
-
- switch (p->region) {
- case EC_FLASH_REGION_RO:
- r->offset = CONFIG_FW_RO_OFF;
- r->size = CONFIG_FW_RO_SIZE;
- break;
- case EC_FLASH_REGION_RW:
- r->offset = CONFIG_FW_RW_OFF;
- r->size = CONFIG_FW_RW_SIZE;
- break;
- case EC_FLASH_REGION_WP_RO:
- r->offset = CONFIG_FW_WP_RO_OFF;
- r->size = CONFIG_FW_WP_RO_SIZE;
- break;
- default:
- return EC_RES_INVALID_PARAM;
- }
- args->response_size = sizeof(*r);
- return EC_RES_SUCCESS;
-}
-DECLARE_HOST_COMMAND(EC_CMD_FLASH_REGION_INFO,
- flash_command_region_info,
- EC_VER_MASK(EC_VER_FLASH_REGION_INFO));
diff --git a/common/flash_internal.c b/common/flash_internal.c
new file mode 100644
index 0000000000..89a5508b5f
--- /dev/null
+++ b/common/flash_internal.c
@@ -0,0 +1,112 @@
+/* Copyright (c) 2012 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.
+ */
+
+/* Flash memory module for Flash internal to Chrome EC - common functions */
+
+#include "common.h"
+#include "console.h"
+#include "flash.h"
+#include "gpio.h"
+#include "host_command.h"
+#include "shared_mem.h"
+#include "system.h"
+#include "util.h"
+#include "vboot_hash.h"
+
+/**
+ * Get the physical memory address of a flash offset
+ *
+ * This is used for direct flash access. We assume that the flash is
+ * contiguous from this start address through to the end of the usable
+ * flash.
+ *
+ * @param offset Flash offset to get address of
+ * @param dataptrp Returns pointer to memory address of flash offset
+ * @return pointer to flash memory offset, if ok, else NULL
+ */
+const char *flash_physical_dataptr(int offset)
+{
+ return (char *)((uintptr_t)CONFIG_FLASH_BASE + offset);
+}
+
+/**
+ * Read persistent state into pstate.
+ *
+ * @param pstate Destination for persistent state
+ */
+void flash_read_pstate(struct persist_state *pstate)
+{
+ memcpy(pstate, flash_physical_dataptr(PSTATE_OFFSET), sizeof(*pstate));
+
+ /* Sanity-check data and initialize if necessary */
+ if (pstate->version != PERSIST_STATE_VERSION) {
+ memset(pstate, 0, sizeof(*pstate));
+ pstate->version = PERSIST_STATE_VERSION;
+#ifdef CONFIG_WP_ALWAYS
+ pstate->flags |= PERSIST_FLAG_PROTECT_RO;
+#endif
+ }
+}
+
+/**
+ * Write persistent state from pstate, erasing if necessary.
+ *
+ * @param pstate Source persistent state
+ * @return EC_SUCCESS, or nonzero if error.
+ */
+int flash_write_pstate(const struct persist_state *pstate)
+{
+ struct persist_state current_pstate;
+ int rv;
+
+ /* Check if pstate has actually changed */
+ flash_read_pstate(&current_pstate);
+ if (!memcmp(&current_pstate, pstate, sizeof(*pstate)))
+ return EC_SUCCESS;
+
+ /* Erase pstate */
+ rv = flash_physical_erase(PSTATE_OFFSET, PSTATE_SIZE);
+ if (rv)
+ return rv;
+
+ /*
+ * Note that if we lose power in here, we'll lose the pstate contents.
+ * That's ok, because it's only possible to write the pstate before
+ * it's protected.
+ */
+
+ /* Rewrite the data */
+ return flash_physical_write(PSTATE_OFFSET, sizeof(*pstate),
+ (const char *)pstate);
+}
+
+static int flash_command_region_info(struct host_cmd_handler_args *args)
+{
+ const struct ec_params_flash_region_info *p = args->params;
+ struct ec_response_flash_region_info *r = args->response;
+
+ switch (p->region) {
+ case EC_FLASH_REGION_RO:
+ r->offset = CONFIG_FW_RO_OFF;
+ r->size = CONFIG_FW_RO_SIZE;
+ break;
+ case EC_FLASH_REGION_RW:
+ r->offset = CONFIG_FW_RW_OFF;
+ r->size = CONFIG_FW_RW_SIZE;
+ break;
+ case EC_FLASH_REGION_WP_RO:
+ r->offset = CONFIG_FW_WP_RO_OFF;
+ r->size = CONFIG_FW_WP_RO_SIZE;
+ break;
+ default:
+ return EC_RES_INVALID_PARAM;
+ }
+
+ args->response_size = sizeof(*r);
+ return EC_RES_SUCCESS;
+}
+DECLARE_HOST_COMMAND(EC_CMD_FLASH_REGION_INFO,
+ flash_command_region_info,
+ EC_VER_MASK(EC_VER_FLASH_REGION_INFO));
diff --git a/common/flash_spi.c b/common/flash_spi.c
new file mode 100644
index 0000000000..319d25bdf4
--- /dev/null
+++ b/common/flash_spi.c
@@ -0,0 +1,258 @@
+/* Copyright (c) 2012 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.
+ */
+
+/* Flash memory module for Chrome EC - common functions */
+
+#include "common.h"
+#include "console.h"
+#include "flash.h"
+#include "host_command.h"
+#include "spi.h"
+#include "spi_flash.h"
+#include "system.h"
+#include "util.h"
+#include "watchdog.h"
+
+/*
+ * Buffer allocated to read data from spi Flash
+ *
+ */
+#define FLASH_EXT_DATACHUNK_SIZE 256
+static uint8_t flash_data[FLASH_EXT_DATACHUNK_SIZE];
+
+
+/**
+ * Return the base pointer of the SPI Flash addr for the image copy, or 0xffffffff if error.
+ */
+uintptr_t flash_get_image_base_spi(enum system_image_copy_t copy)
+{
+ switch (copy) {
+ case SYSTEM_IMAGE_RO:
+ return CONFIG_RO_IMAGE_FLASHADDR;
+ case SYSTEM_IMAGE_RW:
+ return CONFIG_RW_IMAGE_FLASHADDR;
+ default:
+ return 0xffffffff;
+ }
+}
+
+
+uint32_t flash_get_image_used_spi(enum system_image_copy_t copy)
+{
+ uint32_t image;
+ int size = 0;
+ uint32_t data_size = 0;
+ uint16_t i = 0;
+
+ image = flash_get_image_base_spi(copy);
+ size = system_get_image_size(copy);
+
+ CPRINTS("image addr %x\n!!!", image);
+
+ /*
+ * Scan backwards looking for 0xea byte, which is by definition the
+ * last byte of the image. See ec.lds.S for how this is inserted at
+ * the end of the image.
+ */
+ while (size > 0) {
+
+ watchdog_reload();
+ data_size = MIN(FLASH_EXT_DATACHUNK_SIZE, size);
+
+ flash_physical_read((image + size - data_size), data_size,
+ (uint8_t *)flash_data);
+
+
+ for (i = data_size; i > 0; i--) {
+
+ if (flash_data[i - 1] == 0xea) {
+
+ /* 0xea byte IS part of the image */
+ image -= (data_size - i);
+ CPRINTS("size = 0x%x\n",
+ size);
+ return size;
+ }
+ }
+
+ size -= data_size;
+ }
+
+ CPRINTS("Did not find 0xea size = 0x%x\n", size);
+ return size;
+}
+
+/*****************************************************************************/
+/* Physical layer APIs */
+
+/**
+ * Get the physical memory address of a flash offset
+ *
+ * This is used for direct flash access. We assume that the flash is
+ * contiguous from this start address through to the end of the usable
+ * flash.
+ *
+ * @param offset Flash offset to get address of
+ * @param dataptrp Returns pointer to memory address of flash offset
+ * @return pointer to flash memory offset, if ok, else NULL
+ */
+const char *flash_physical_dataptr(int offset)
+{
+ return (char *)((uintptr_t)CONFIG_FLASH_BASE_SPI + offset);
+}
+
+int flash_physical_write(int offset, int size, const char *data)
+{
+ int i;
+
+ offset += CONFIG_FLASH_BASE_SPI;
+
+ /* Fail if offset, size, and data aren't at least word-aligned */
+ if ((offset | size | (uint32_t)(uintptr_t)data) & 3)
+ return EC_ERROR_INVAL;
+
+ spi_enable(1);
+
+ for (i = 0; i < size; i += 16)
+ spi_flash_write(offset+i, 16, &data[i]);
+
+ spi_enable(0);
+
+ return EC_SUCCESS;
+}
+
+int flash_physical_read(int offset, int size, char *data)
+{
+
+ offset += CONFIG_FLASH_BASE_SPI;
+
+ /* Fail if offset, size, and data aren't at least word-aligned */
+ if ((offset | size | (uint32_t)(uintptr_t)data) & 3)
+ return EC_ERROR_INVAL;
+
+ spi_enable(1);
+
+ spi_flash_read((uint8_t *)data, offset, size);
+
+ spi_enable(0);
+
+ return EC_SUCCESS;
+}
+
+
+int flash_physical_erase(int offset, int size)
+{
+
+
+ offset += CONFIG_FLASH_BASE_SPI;
+
+ spi_enable(1);
+
+ for (; size > 0; size -= CONFIG_FLASH_ERASE_SIZE,
+ offset += CONFIG_FLASH_ERASE_SIZE) {
+
+ /* Do nothing if already erased */
+ if (spi_flash_erase(offset, CONFIG_FLASH_ERASE_SIZE))
+ return EC_ERROR_UNKNOWN;
+
+ /*
+ * Reload the watchdog timer, so that erasing many flash pages
+ * doesn't cause a watchdog reset. May not need this now that
+ * we're using msleep() below.
+ */
+ watchdog_reload();
+ }
+ spi_enable(0);
+
+ return EC_SUCCESS;
+}
+
+/**
+ * Read persistent state into pstate.
+ *
+ * @param pstate Destination for persistent state
+ */
+void flash_read_pstate(struct persist_state *pstate)
+{
+ /* TODO(crosbug.com/p/36076): IMPLEMENT ME ! */
+}
+
+/**
+ * Write persistent state from pstate, erasing if necessary.
+ *
+ * @param pstate Source persistent state
+ * @return EC_SUCCESS, or nonzero if error.
+ */
+int flash_write_pstate(const struct persist_state *pstate)
+{
+
+ /* TODO(crosbug.com/p/36076): IMPLEMENT ME ! */
+ return 1;
+}
+
+int flash_physical_get_protect(int bank)
+{
+ /* TODO(crosbug.com/p/36076): IMPLEMENT ME ! */
+ return 1;
+}
+
+int flash_physical_protect_now(int bank)
+{
+ /* TODO(crosbug.com/p/36076): IMPLEMENT ME ! */
+ return 1;
+}
+
+uint32_t flash_physical_get_protect_flags(void)
+{
+ /* TODO(crosbug.com/p/36076): IMPLEMENT ME ! */
+ return 1;
+
+}
+
+uint32_t flash_physical_get_valid_flags(void)
+{
+ /* TODO(crosbug.com/p/36076): IMPLEMENT ME ! */
+ return 1;
+
+}
+
+uint32_t flash_physical_get_writable_flags(uint32_t cur_flags)
+{
+ /* TODO(crosbug.com/p/36076): IMPLEMENT ME ! */
+ return 1;
+
+}
+
+/*****************************************************************************/
+/* Host commands */
+
+static int flash_command_region_info(struct host_cmd_handler_args *args)
+{
+ const struct ec_params_flash_region_info *p = args->params;
+ struct ec_response_flash_region_info *r = args->response;
+
+ switch (p->region) {
+ case EC_FLASH_REGION_RO:
+ r->offset = CONFIG_RO_SPI_OFF;
+ r->size = CONFIG_FW_RO_SIZE;
+ break;
+ case EC_FLASH_REGION_RW:
+ r->offset = CONFIG_RW_SPI_OFF;
+ r->size = CONFIG_FW_RW_SIZE;
+ break;
+ case EC_FLASH_REGION_WP_RO:
+ r->offset = CONFIG_RO_WP_SPI_OFF;
+ r->size = CONFIG_FW_WP_RO_SIZE;
+ break;
+ default:
+ return EC_RES_INVALID_PARAM;
+ }
+
+ args->response_size = sizeof(*r);
+ return EC_RES_SUCCESS;
+}
+DECLARE_HOST_COMMAND(EC_CMD_FLASH_REGION_INFO,
+ flash_command_region_info,
+ EC_VER_MASK(EC_VER_FLASH_REGION_INFO));
diff --git a/include/flash.h b/include/flash.h
index a77d5a1cb2..b5ea1afa89 100644
--- a/include/flash.h
+++ b/include/flash.h
@@ -10,6 +10,7 @@
#include "common.h"
#include "ec_commands.h" /* For EC_FLASH_PROTECT_* flags */
+#include "system.h" /* For System Image Info */
/* Number of physical flash banks */
#define PHYSICAL_BANKS (CONFIG_FLASH_PHYSICAL_SIZE / CONFIG_FLASH_BANK_SIZE)
@@ -35,8 +36,64 @@ enum flash_wp_range {
FLASH_WP_ALL,
};
+/* Persistent protection state - emulates a SPI status register for flashrom */
+struct persist_state {
+ uint8_t version; /* Version of this struct */
+ uint8_t flags; /* Lock flags (PERSIST_FLAG_*) */
+ uint8_t reserved[2]; /* Reserved; set 0 */
+};
+
+#define PERSIST_STATE_VERSION 2 /* Expected persist_state.version */
+
+#ifdef CONFIG_FLASH_SPI
+/**
+ * Get the memory address of a SPI flash offset where code is loaded
+ *
+ * @param copy system image type
+ * @return pointer to flash address offset, if ok, else 0xffffffff
+ */
+uintptr_t flash_get_image_base_spi(enum system_image_copy_t copy);
+
+/**
+ * Calculate the actual size of the image loaded in the SPI flash
+ *
+ * @param copy system image type
+ * @return pointer to flash address offset, if ok, else 0
+ */
+uint32_t flash_get_image_used_spi(enum system_image_copy_t copy);
+#else
+/**
+ * Calculate the actual size of the image loaded in the internal flash
+ *
+ * @param copy system image type
+ * @return pointer to flash address offset, if ok, else 0
+ */
+uint32_t flash_get_image_used_internal(enum system_image_copy_t copy);
+
+#endif
+
/*****************************************************************************/
/* Low-level methods, for use by flash_common. */
+/**
+ * Get the physical memory address of a flash offset
+ *
+ * @param offset Flash offset to get address of
+ * @param dataptrp Returns pointer to memory address of flash offset
+ * @return pointer to flash memory offset, if ok, else NULL
+ */
+
+const char *flash_physical_dataptr(int offset);
+/**
+ * Read from physical flash.
+ *
+ * Offset and size must be a multiple of CONFIG_FLASH_READ_SIZE.
+ *
+ * @param offset Flash offset to read from.
+ * @param size Number of bytes to read.
+ * @param data Data buffer to read from flash. Must be 32-bit aligned.
+ */
+int flash_physical_read(int offset, int size, char *data);
+
/**
* Write to physical flash.
@@ -85,6 +142,22 @@ uint32_t flash_physical_get_protect_flags(void);
int flash_physical_protect_at_boot(enum flash_wp_range range);
/**
+ * Read persistent state into pstate.
+ *
+ * @param pstate Destination for persistent state
+ */
+void flash_read_pstate(struct persist_state *pstate);
+
+/**
+ * Write persistent state from pstate, erasing if necessary.
+ *
+ * @param pstate Source persistent state
+ * @return EC_SUCCESS, or nonzero if error.
+ */
+int flash_write_pstate(const struct persist_state *pstate);
+
+
+/**
* Protect flash now.
*
* @param all Protect all (=1) or just read-only and pstate (=0).