summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRandall Spangler <rspangler@chromium.org>2016-09-14 16:48:23 -0700
committerchrome-bot <chrome-bot@chromium.org>2016-09-23 12:21:51 -0700
commit818dea4a07337b96a696f805a207860abf979c8f (patch)
tree6d564d3e0a304360f95e0d3e200796845a83cff4
parent5818cdc7286a37cf06d2f2c0d79b0f4ae5ee664c (diff)
downloadchrome-ec-818dea4a07337b96a696f805a207860abf979c8f.tar.gz
flash: Add command to get SPI flash chip info
Previously, there was no way to identify which flash chip was used by the EC, for ECs using an external SPI flash. Now, 'ectool flashinfo' will print more information about the SPI flash chip in these cases. BUG=chrome-os-partner:56765 BRANCH=any EC with MEC1322 or NPCX still going through factory TEST=define CONFIG_HOSTCMD_FLASH_SPI_INFO, then 'ectool flashspiinfo' on samus indicates no SPI flash info, and prints additional info on chell and kevin. Without the config defined, all platforms report no spi flash info. CQ-DEPEND=CL:386368 Change-Id: I3c162f7ad12ed4b30ab951c03f24476683382114 Signed-off-by: Randall Spangler <rspangler@chromium.org> Reviewed-on: https://chromium-review.googlesource.com/385702 Reviewed-by: Shawn N <shawnn@chromium.org>
-rw-r--r--chip/npcx/flash.c59
-rw-r--r--chip/npcx/registers.h1
-rw-r--r--common/spi_flash.c79
-rw-r--r--include/config.h7
-rw-r--r--include/ec_commands.h18
-rw-r--r--include/spi_flash.h22
-rw-r--r--util/ectool.c30
7 files changed, 181 insertions, 35 deletions
diff --git a/chip/npcx/flash.c b/chip/npcx/flash.c
index 2387a3a958..31e4c60f1a 100644
--- a/chip/npcx/flash.c
+++ b/chip/npcx/flash.c
@@ -6,6 +6,7 @@
/* Flash memory module for Chrome EC */
#include "flash.h"
+#include "host_command.h"
#include "registers.h"
#include "switch.h"
#include "system.h"
@@ -160,6 +161,39 @@ uint8_t flash_get_status2(void)
return NPCX_UMA_DB0;
}
+#ifdef CONFIG_HOSTCMD_FLASH_SPI_INFO
+
+void flash_get_mfr_dev_id(uint8_t *dest)
+{
+ /* Disable tri-state */
+ TRISTATE_FLASH(0);
+ /* Read manufacturer and device ID. Send cmd=0x90 + 24-bit address=0 */
+ flash_set_address(0);
+ flash_execute_cmd(CMD_READ_MAN_DEV_ID,
+ MASK_CMD_RD_2BYTE | MASK(A_SIZE));
+ /* Enable tri-state */
+ TRISTATE_FLASH(1);
+
+ dest[0] = NPCX_UMA_DB0;
+ dest[1] = NPCX_UMA_DB1;
+}
+
+void flash_get_jedec_id(uint8_t *dest)
+{
+ /* Disable tri-state */
+ TRISTATE_FLASH(0);
+ /* Read manufacturer and device ID */
+ flash_execute_cmd(CMD_READ_ID, MASK_CMD_RD_3BYTE);
+ /* Enable tri-state */
+ TRISTATE_FLASH(1);
+
+ dest[0] = NPCX_UMA_DB0;
+ dest[1] = NPCX_UMA_DB1;
+ dest[2] = NPCX_UMA_DB2;
+}
+
+#endif /* CONFIG_HOSTCMD_FLASH_SPI_INFO */
+
/*****************************************************************************/
/* flash protection functions */
/* Use a copy function of spi_flash.c in flash driver */
@@ -742,6 +776,31 @@ void flash_lock_mapped_storage(int lock)
}
/*****************************************************************************/
+/* Host commands */
+
+#if defined(CONFIG_HOSTCMD_FLASH_SPI_INFO) && !defined(BOARD_NPCX_EVB)
+/* NPCX EVB uses implementation from spi_flash.c */
+
+static int flash_command_spi_info(struct host_cmd_handler_args *args)
+{
+ struct ec_response_flash_spi_info *r = args->response;
+
+ flash_get_jedec_id(r->jedec);
+ r->reserved0 = 0;
+ flash_get_mfr_dev_id(r->mfr_dev_id);
+ r->sr1 = flash_get_status1();
+ r->sr2 = flash_get_status2();
+
+ args->response_size = sizeof(*r);
+ return EC_RES_SUCCESS;
+}
+DECLARE_HOST_COMMAND(EC_CMD_FLASH_SPI_INFO,
+ flash_command_spi_info,
+ EC_VER_MASK(0));
+
+#endif
+
+/*****************************************************************************/
/* Console commands */
static int command_flash_spi_sel_lock(int argc, char **argv)
diff --git a/chip/npcx/registers.h b/chip/npcx/registers.h
index 2154f8efa3..34188f58e9 100644
--- a/chip/npcx/registers.h
+++ b/chip/npcx/registers.h
@@ -1492,6 +1492,7 @@ enum {
* Flash commands for the W25Q16CV SPI flash
*/
#define CMD_READ_ID 0x9F
+#define CMD_READ_MAN_DEV_ID 0x90
#define CMD_WRITE_EN 0x06
#define CMD_WRITE_STATUS 0x50
#define CMD_READ_STATUS_REG 0x05
diff --git a/common/spi_flash.c b/common/spi_flash.c
index 2b2e821e71..c49215a3f4 100644
--- a/common/spi_flash.c
+++ b/common/spi_flash.c
@@ -8,6 +8,7 @@
#include "common.h"
#include "console.h"
+#include "host_command.h"
#include "shared_mem.h"
#include "spi.h"
#include "spi_flash.h"
@@ -311,37 +312,42 @@ int spi_flash_write(unsigned int offset, unsigned int bytes,
}
/**
- * Returns the SPI flash JEDEC ID (manufacturer ID, memory type, and capacity)
+ * Gets the SPI flash JEDEC ID (manufacturer ID, memory type, and capacity)
*
- * @return flash JEDEC ID or -1 on error
+ * @param dest Destination buffer; must be 3 bytes long
+ * @return EC_SUCCESS or non-zero on error
*/
-uint32_t spi_flash_get_jedec_id(void)
+int spi_flash_get_jedec_id(uint8_t *dest)
{
uint8_t cmd = SPI_FLASH_JEDEC_ID;
- uint32_t resp;
- if (spi_transaction(SPI_FLASH_DEVICE,
- &cmd, 1, (uint8_t *)&resp, 4) != EC_SUCCESS)
- return -1;
+ return spi_transaction(SPI_FLASH_DEVICE, &cmd, 1, dest, 3);
+}
- return resp;
+/**
+ * Gets the SPI flash manufacturer and device ID
+ *
+ * @param dest Destination buffer; must be 2 bytes long
+ * @return EC_SUCCESS or non-zero on error
+ */
+int spi_flash_get_mfr_dev_id(uint8_t *dest)
+{
+ uint8_t cmd[4] = {SPI_FLASH_MFR_DEV_ID, 0, 0, 0};
+
+ return spi_transaction(SPI_FLASH_DEVICE, cmd, sizeof(cmd), dest, 2);
}
/**
- * Returns the SPI flash unique ID (serial)
+ * Gets the SPI flash unique ID (serial)
*
- * @return flash unique ID or -1 on error
+ * @param dest Destination buffer; must be 8 bytes long
+ * @return EC_SUCCESS or non-zero on error
*/
-uint64_t spi_flash_get_unique_id(void)
+int spi_flash_get_unique_id(uint8_t *dest)
{
uint8_t cmd[5] = {SPI_FLASH_UNIQUE_ID, 0, 0, 0, 0};
- uint64_t resp;
- if (spi_transaction(SPI_FLASH_DEVICE,
- cmd, 5, (uint8_t *)&resp, 8) != EC_SUCCESS)
- return -1;
-
- return resp;
+ return spi_transaction(SPI_FLASH_DEVICE, cmd, sizeof(cmd), dest, 8);
}
/**
@@ -461,8 +467,8 @@ int spi_flash_set_protect(unsigned int offset, unsigned int bytes)
static int command_spi_flashinfo(int argc, char **argv)
{
- uint32_t jedec;
- uint64_t unique;
+ uint8_t jedec[3];
+ uint8_t unique[8];
int rv;
spi_enable(CONFIG_SPI_FLASH_PORT, 1);
@@ -472,19 +478,15 @@ static int command_spi_flashinfo(int argc, char **argv)
if (rv)
return rv;
- jedec = spi_flash_get_jedec_id();
- unique = spi_flash_get_unique_id();
+ spi_flash_get_jedec_id(jedec);
+ spi_flash_get_unique_id(unique);
ccprintf("Manufacturer ID: %02x\nDevice ID: %02x %02x\n",
- ((uint8_t *)&jedec)[0], ((uint8_t *)&jedec)[1],
- ((uint8_t *)&jedec)[2]);
+ jedec[0], jedec[1], jedec[2]);
ccprintf("Unique ID: %02x %02x %02x %02x %02x %02x %02x %02x\n",
- ((uint8_t *)&unique)[0], ((uint8_t *)&unique)[1],
- ((uint8_t *)&unique)[2], ((uint8_t *)&unique)[3],
- ((uint8_t *)&unique)[4], ((uint8_t *)&unique)[5],
- ((uint8_t *)&unique)[6], ((uint8_t *)&unique)[7]);
- ccprintf("Capacity: %4d kB\n",
- SPI_FLASH_SIZE(((uint8_t *)&jedec)[2]) / 1024);
+ unique[0], unique[1], unique[2], unique[3],
+ unique[4], unique[5], unique[6], unique[7]);
+ ccprintf("Capacity: %4d kB\n", SPI_FLASH_SIZE(jedec[2]) / 1024);
return rv;
}
@@ -492,6 +494,25 @@ DECLARE_CONSOLE_COMMAND(spi_flashinfo, command_spi_flashinfo,
NULL,
"Print SPI flash info");
+#ifdef CONFIG_HOSTCMD_FLASH_SPI_INFO
+static int flash_command_spi_info(struct host_cmd_handler_args *args)
+{
+ struct ec_response_flash_spi_info *r = args->response;
+
+ spi_flash_get_jedec_id(r->jedec);
+ r->reserved0 = 0;
+ spi_flash_get_mfr_dev_id(r->mfr_dev_id);
+ r->sr1 = spi_flash_get_status1();
+ r->sr2 = spi_flash_get_status2();
+
+ args->response_size = sizeof(*r);
+ return EC_RES_SUCCESS;
+}
+DECLARE_HOST_COMMAND(EC_CMD_FLASH_SPI_INFO,
+ flash_command_spi_info,
+ EC_VER_MASK(0));
+#endif /* CONFIG_HOSTCMD_FLASH_SPI_INFO */
+
#ifdef CONFIG_CMD_SPI_FLASH
static int command_spi_flasherase(int argc, char **argv)
{
diff --git a/include/config.h b/include/config.h
index edfc610614..5ec402d8a6 100644
--- a/include/config.h
+++ b/include/config.h
@@ -1136,6 +1136,13 @@
#endif
/*
+ * Board supports host command to get EC SPI flash info. This is typically
+ * only needed if the factory needs to determine which of several possible SPI
+ * flash chips is attached to the EC on a given board.
+ */
+#undef CONFIG_HOSTCMD_FLASH_SPI_INFO
+
+/*
* For ECs where the host command interface is I2C, slave
* address which the EC will respond to.
*/
diff --git a/include/ec_commands.h b/include/ec_commands.h
index 6591fcb10d..ada096d8eb 100644
--- a/include/ec_commands.h
+++ b/include/ec_commands.h
@@ -1171,6 +1171,24 @@ struct ec_response_vbnvcontext {
uint8_t block[EC_VBNV_BLOCK_SIZE];
} __packed;
+
+/* Get SPI flash information */
+#define EC_CMD_FLASH_SPI_INFO 0x18
+
+struct ec_response_flash_spi_info {
+ /* JEDEC info from command 0x9F (manufacturer, memory type, size) */
+ uint8_t jedec[3];
+
+ /* Pad byte; currently always contains 0 */
+ uint8_t reserved0;
+
+ /* Manufacturer / device ID from command 0x90 */
+ uint8_t mfr_dev_id[2];
+
+ /* Status registers from command 0x05 and 0x35 */
+ uint8_t sr1, sr2;
+} __packed;
+
/*****************************************************************************/
/* PWM commands */
diff --git a/include/spi_flash.h b/include/spi_flash.h
index 9b8a0a64d5..4e4dd96381 100644
--- a/include/spi_flash.h
+++ b/include/spi_flash.h
@@ -123,18 +123,28 @@ int spi_flash_write(unsigned int offset, unsigned int bytes,
const uint8_t const *data);
/**
- * Returns the SPI flash JEDEC ID (manufacturer ID, memory type, and capacity)
+ * Gets the SPI flash JEDEC ID (manufacturer ID, memory type, and capacity)
*
- * @return flash JEDEC ID
+ * @param dest Destination buffer; must be 3 bytes long
+ * @return EC_SUCCESS or non-zero on error
*/
-uint32_t spi_flash_get_jedec_id(void);
+int spi_flash_get_jedec_id(uint8_t *dest);
/**
- * Returns the SPI flash unique ID (serial)
+ * Gets the SPI flash manufacturer and device ID
*
- * @return flash unique ID
+ * @param dest Destination buffer; must be 2 bytes long
+ * @return EC_SUCCESS or non-zero on error
*/
-uint64_t spi_flash_get_unique_id(void);
+int spi_flash_get_mfr_dev_id(uint8_t *dest);
+
+/**
+ * Gets the SPI flash unique ID (serial)
+ *
+ * @param dest Destination buffer; must be 8 bytes long
+ * @return EC_SUCCESS or non-zero on error
+ */
+int spi_flash_get_unique_id(uint8_t *dest);
/**
* Check for SPI flash status register write protection.
diff --git a/util/ectool.c b/util/ectool.c
index b8e5415c22..ac9357dda0 100644
--- a/util/ectool.c
+++ b/util/ectool.c
@@ -100,6 +100,8 @@ const char help_str[] =
" Erases EC flash\n"
" flashinfo\n"
" Prints information on the EC flash\n"
+ " flashspiinfo\n"
+ " Prints information on EC SPI flash, if present\n"
" flashpd <dev_id> <port> <filename>\n"
" Flash commands over PD\n"
" flashprotect [now] [enable | disable]\n"
@@ -750,6 +752,33 @@ int cmd_flash_info(int argc, char *argv[])
return 0;
}
+int cmd_flash_spi_info(int argc, char *argv[])
+{
+ struct ec_response_flash_spi_info r;
+ int rv;
+
+ memset(&r, 0, sizeof(r));
+
+ /* Print SPI flash info if available */
+ if (!ec_cmd_version_supported(EC_CMD_FLASH_SPI_INFO, 0)) {
+ printf("EC has no info (does not use SPI flash?)\n");
+ return -1;
+ }
+
+ rv = ec_command(EC_CMD_FLASH_SPI_INFO, 0, NULL, 0, &r, sizeof(r));
+ if (rv < 0)
+ return rv;
+
+ printf("JEDECManufacturerID 0x%02x\n", r.jedec[0]);
+ printf("JEDECDeviceID 0x%02x 0x%02x\n", r.jedec[1], r.jedec[2]);
+ printf("JEDECCapacity %d\n", 1 << r.jedec[2]);
+ printf("ManufacturerID 0x%02x\n", r.mfr_dev_id[0]);
+ printf("DeviceID 0x%02x\n", r.mfr_dev_id[1]);
+ printf("StatusRegister1 0x%02x\n", r.sr1);
+ printf("StatusRegister2 0x%02x\n", r.sr2);
+ return 0;
+}
+
int cmd_flash_read(int argc, char *argv[])
{
int offset, size;
@@ -6800,6 +6829,7 @@ const struct command commands[] = {
{"flashread", cmd_flash_read},
{"flashwrite", cmd_flash_write},
{"flashinfo", cmd_flash_info},
+ {"flashspiinfo", cmd_flash_spi_info},
{"flashpd", cmd_flash_pd},
{"forcelidopen", cmd_force_lid_open},
{"gpioget", cmd_gpio_get},