summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRandall Spangler <rspangler@chromium.org>2013-07-17 11:09:58 -0700
committerChromeBot <chrome-bot@google.com>2013-07-18 16:47:00 -0700
commit5691ac816805781a27b5da84cab9c600b77b9dcb (patch)
tree3eebef9a3ee371367b47eae0654c0487ba865fcf
parent7189a9762e1ec8a35dd27e6efc19cd54275eb855 (diff)
downloadchrome-ec-5691ac816805781a27b5da84cab9c600b77b9dcb.tar.gz
Add EC_CMD_GET_FLASH_INFO version 1
This adds two new fields: the ideal write size for best EC flashing performance (e.g., page mode instead of word mode), and a flags field with a flag to indicate whether the EC erases its bits to 0 or 1. The EC still supports the old version 0 command, since u-boot and flashrom expect that to work. BUG=chrome-os-partner:20973 BRANCH=(all haswell); this will speed up flashing and software sync TEST=ectool flashinfo 1. old EC, new ectool -> only reports version 0 info 2. new EC, old ectool -> only reports version 0 info 3. new EC, new ectool -> reports new fields Change-Id: I484327fe22a58d2b69d7f6ac767b2d3e81b3e0b7 Signed-off-by: Randall Spangler <rspangler@chromium.org> Reviewed-on: https://gerrit.chromium.org/gerrit/62378 Reviewed-by: David Hendricks <dhendrix@chromium.org>
-rw-r--r--chip/host/config_chip.h1
-rw-r--r--chip/lm4/config_chip.h3
-rw-r--r--chip/stm32/config-stm32f100.h4
-rw-r--r--chip/stm32/config-stm32f10x.h4
-rw-r--r--chip/stm32/config-stm32l15x.h12
-rw-r--r--common/flash_common.c44
-rw-r--r--include/ec_commands.h32
-rw-r--r--util/ectool.c20
8 files changed, 113 insertions, 7 deletions
diff --git a/chip/host/config_chip.h b/chip/host/config_chip.h
index 44ed02841a..1cbf7710d4 100644
--- a/chip/host/config_chip.h
+++ b/chip/host/config_chip.h
@@ -17,6 +17,7 @@ extern char __host_flash[CONFIG_FLASH_PHYSICAL_SIZE];
#define CONFIG_FLASH_BANK_SIZE 0x1000
#define CONFIG_FLASH_ERASE_SIZE 0x0400 /* erase bank size */
#define CONFIG_FLASH_WRITE_SIZE 0x0002 /* minimum write size */
+#define CONFIG_FLASH_WRITE_IDEAL_SIZE 0x0080 /* ideal write size */
#define CONFIG_RAM_BASE 0x0 /* Not supported */
#define CONFIG_RAM_SIZE 0x0 /* Not supported */
diff --git a/chip/lm4/config_chip.h b/chip/lm4/config_chip.h
index 1c7fdfb48b..8d1077f12c 100644
--- a/chip/lm4/config_chip.h
+++ b/chip/lm4/config_chip.h
@@ -45,6 +45,9 @@
#define CONFIG_FLASH_ERASE_SIZE 0x00000400 /* erase bank size */
#define CONFIG_FLASH_WRITE_SIZE 0x00000004 /* minimum write size */
+/* Ideal flash write size fills the 32-entry flash write buffer */
+#define CONFIG_FLASH_WRITE_IDEAL_SIZE (32 * 4)
+
/* This is the physical size of the flash on the chip. We'll reserve one bank
* in order to emulate per-bank write-protection UNTIL REBOOT. The hardware
* doesn't support a write-protect pin, and if we make the write-protection
diff --git a/chip/stm32/config-stm32f100.h b/chip/stm32/config-stm32f100.h
index b23814f4ad..ab4440f34d 100644
--- a/chip/stm32/config-stm32f100.h
+++ b/chip/stm32/config-stm32f100.h
@@ -10,6 +10,10 @@
#define CONFIG_FLASH_BANK_SIZE 0x1000
#define CONFIG_FLASH_ERASE_SIZE 0x0400 /* erase bank size */
#define CONFIG_FLASH_WRITE_SIZE 0x0002 /* minimum write size */
+
+/* No page mode on STM32F, so no benefit to larger write sizes */
+#define CONFIG_FLASH_WRITE_IDEAL_SIZE 0x0002
+
#define CONFIG_RAM_BASE 0x20000000
#define CONFIG_RAM_SIZE 0x00002000
diff --git a/chip/stm32/config-stm32f10x.h b/chip/stm32/config-stm32f10x.h
index 71c512618c..a201f52c4f 100644
--- a/chip/stm32/config-stm32f10x.h
+++ b/chip/stm32/config-stm32f10x.h
@@ -10,6 +10,10 @@
#define CONFIG_FLASH_BANK_SIZE 0x1000
#define CONFIG_FLASH_ERASE_SIZE 0x0400 /* erase bank size */
#define CONFIG_FLASH_WRITE_SIZE 0x0002 /* minimum write size */
+
+/* No page mode on STM32F, so no benefit to larger write sizes */
+#define CONFIG_FLASH_WRITE_IDEAL_SIZE 0x0002
+
#define CONFIG_RAM_BASE 0x20000000
#define CONFIG_RAM_SIZE (10 * 1024)
diff --git a/chip/stm32/config-stm32l15x.h b/chip/stm32/config-stm32l15x.h
index c03ff5d8e9..ad3e95e099 100644
--- a/chip/stm32/config-stm32l15x.h
+++ b/chip/stm32/config-stm32l15x.h
@@ -9,8 +9,20 @@
#define CONFIG_FLASH_SIZE CONFIG_FLASH_PHYSICAL_SIZE
#define CONFIG_FLASH_BANK_SIZE 0x1000
#define CONFIG_FLASH_ERASE_SIZE 0x0100 /* erase bank size */
+
+/*
+ * TODO(rspangler): Technically we can write in word-mode (4 bytes at a time),
+ * but that's really slow, and older host interfaces which can't ask about the
+ * ideal size would then end up writing in that mode instead of the faster page
+ * mode. So lie about the write size for now. Once all software (flashrom,
+ * u-boot, ectool) which cares has been updated to know about ver.1 of
+ * EC_CMD_GET_FLASH_INFO, we can remove this workaround.
+ */
#define CONFIG_FLASH_WRITE_SIZE 0x0080
+/* Ideal write size in page-mode */
+#define CONFIG_FLASH_WRITE_IDEAL_SIZE 0x0080
+
#define CONFIG_RAM_BASE 0x20000000
#define CONFIG_RAM_SIZE 0x00004000
diff --git a/common/flash_common.c b/common/flash_common.c
index 16ad911594..6f79f544a0 100644
--- a/common/flash_common.c
+++ b/common/flash_common.c
@@ -340,8 +340,10 @@ static int command_flash_info(int argc, char **argv)
ccprintf("Physical:%4d KB\n", CONFIG_FLASH_PHYSICAL_SIZE / 1024);
ccprintf("Usable: %4d KB\n", CONFIG_FLASH_SIZE / 1024);
- ccprintf("Write: %4d B\n", CONFIG_FLASH_WRITE_SIZE);
- ccprintf("Erase: %4d B\n", CONFIG_FLASH_ERASE_SIZE);
+ ccprintf("Write: %4d B (ideal %d B)\n", CONFIG_FLASH_WRITE_SIZE,
+ CONFIG_FLASH_WRITE_IDEAL_SIZE);
+ ccprintf("Erase: %4d B (to %d-bits)\n", CONFIG_FLASH_ERASE_SIZE,
+ CONFIG_FLASH_ERASED_VALUE32 ? 1 : 0);
ccprintf("Protect: %4d B\n", CONFIG_FLASH_BANK_SIZE);
i = flash_get_protect();
@@ -472,18 +474,50 @@ DECLARE_CONSOLE_COMMAND(flashwp, command_flash_wp,
static int flash_command_get_info(struct host_cmd_handler_args *args)
{
- struct ec_response_flash_info *r = args->response;
+ struct ec_response_flash_info_1 *r = args->response;
r->flash_size = CONFIG_FLASH_SIZE;
r->write_block_size = CONFIG_FLASH_WRITE_SIZE;
r->erase_block_size = CONFIG_FLASH_ERASE_SIZE;
r->protect_block_size = CONFIG_FLASH_BANK_SIZE;
- args->response_size = sizeof(*r);
+
+ if (args->version == 0) {
+ /* Only version 0 fields returned */
+ args->response_size = sizeof(struct ec_response_flash_info);
+ } else {
+ /* Fill in full version 1 struct */
+
+ /*
+ * Compute the ideal amount of data for the host to send us,
+ * based on the maximum response size and the ideal write size.
+ */
+ r->write_ideal_size =
+ (args->response_max -
+ sizeof(struct ec_params_flash_write)) &
+ ~(CONFIG_FLASH_WRITE_IDEAL_SIZE - 1);
+ /*
+ * If we can't get at least one ideal block, then just want
+ * as high a multiple of the minimum write size as possible.
+ */
+ if (!r->write_ideal_size)
+ r->write_ideal_size =
+ (args->response_max -
+ sizeof(struct ec_params_flash_write)) &
+ ~(CONFIG_FLASH_WRITE_SIZE - 1);
+
+ r->flags = 0;
+
+#if (CONFIG_FLASH_ERASED_VALUE32 == 0)
+ r->flags |= EC_FLASH_INFO_ERASE_TO_0;
+#endif
+
+ args->response_size = sizeof(*r);
+ }
return EC_RES_SUCCESS;
}
DECLARE_HOST_COMMAND(EC_CMD_FLASH_INFO,
flash_command_get_info,
- EC_VER_MASK(0));
+ EC_VER_MASK(0) | EC_VER_MASK(1));
static int flash_command_read(struct host_cmd_handler_args *args)
{
diff --git a/include/ec_commands.h b/include/ec_commands.h
index c4ac2b5721..f725b0b784 100644
--- a/include/ec_commands.h
+++ b/include/ec_commands.h
@@ -572,6 +572,7 @@ struct ec_response_get_protocol_info {
/* Get flash info */
#define EC_CMD_FLASH_INFO 0x10
+/* Version 0 returns these fields */
struct ec_response_flash_info {
/* Usable flash size, in bytes */
uint32_t flash_size;
@@ -592,6 +593,37 @@ struct ec_response_flash_info {
uint32_t protect_block_size;
} __packed;
+/* Flags for version 1+ flash info command */
+/* EC flash erases bits to 0 instead of 1 */
+#define EC_FLASH_INFO_ERASE_TO_0 (1 << 0)
+
+/*
+ * Version 1 returns the same initial fields as version 0, with additional
+ * fields following.
+ *
+ * gcc anonymous structs don't seem to get along with the __packed directive;
+ * if they did we'd define the version 0 struct as a sub-struct of this one.
+ */
+struct ec_response_flash_info_1 {
+ /* Version 0 fields; see above for description */
+ uint32_t flash_size;
+ uint32_t write_block_size;
+ uint32_t erase_block_size;
+ uint32_t protect_block_size;
+
+ /* Version 1 adds these fields: */
+ /*
+ * Ideal write size in bytes. Writes will be fastest if size is
+ * exactly this and offset is a multiple of this. For example, an EC
+ * may have a write buffer which can do half-page operations if data is
+ * aligned, and a slower word-at-a-time write mode.
+ */
+ uint32_t write_ideal_size;
+
+ /* Flags; see EC_FLASH_INFO_* */
+ uint32_t flags;
+} __packed;
+
/*
* Read flash
*
diff --git a/util/ectool.c b/util/ectool.c
index 1faf78f814..b68b5007a3 100644
--- a/util/ectool.c
+++ b/util/ectool.c
@@ -485,10 +485,20 @@ int cmd_reboot_ec(int argc, char *argv[])
int cmd_flash_info(int argc, char *argv[])
{
- struct ec_response_flash_info r;
+ struct ec_response_flash_info_1 r;
+ int cmdver = 1;
+ int rsize = sizeof(r);
int rv;
- rv = ec_command(EC_CMD_FLASH_INFO, 0, NULL, 0, &r, sizeof(r));
+ memset(&r, 0, sizeof(r));
+
+ if (!ec_cmd_version_supported(EC_CMD_FLASH_INFO, cmdver)) {
+ /* Fall back to version 0 command */
+ cmdver = 0;
+ rsize = sizeof(struct ec_response_flash_info);
+ }
+
+ rv = ec_command(EC_CMD_FLASH_INFO, cmdver, NULL, 0, &r, rsize);
if (rv < 0)
return rv;
@@ -496,6 +506,12 @@ int cmd_flash_info(int argc, char *argv[])
r.flash_size, r.write_block_size, r.erase_block_size,
r.protect_block_size);
+ if (cmdver >= 1) {
+ /* Fields added in ver.1 available */
+ printf("WriteIdealSize %d\nFlags 0x%x\n",
+ r.write_ideal_size, r.flags);
+ }
+
return 0;
}