diff options
author | Divya Jyothi <divya.jyothi@intel.com> | 2015-02-04 16:44:39 -0800 |
---|---|---|
committer | ChromeOS Commit Bot <chromeos-commit-bot@chromium.org> | 2015-02-09 18:33:55 +0000 |
commit | b9c7de0f76d772645123ee11478659e3f68138a6 (patch) | |
tree | 83301a15fd28ccac8fd4a86223d65434db911f85 | |
parent | 70afa3898ca1f28dc7e254b63f2d5fb12ad6b273 (diff) | |
download | chrome-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.mk | 3 | ||||
-rw-r--r-- | common/flash.c | 103 | ||||
-rw-r--r-- | common/flash_internal.c | 112 | ||||
-rw-r--r-- | common/flash_spi.c | 258 | ||||
-rw-r--r-- | include/flash.h | 73 |
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(¤t_pstate); - if (!memcmp(¤t_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(¤t_pstate); + if (!memcmp(¤t_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). |