summaryrefslogtreecommitdiff
path: root/chip
diff options
context:
space:
mode:
authorDino Li <Dino.Li@ite.com.tw>2018-07-18 17:42:21 +0800
committerchrome-bot <chrome-bot@chromium.org>2018-07-20 15:10:14 -0700
commit8a6674329235c0446aa1ce8b7ac36371c40308fe (patch)
tree833f7d63183db1acdc84153ff724bbcc8d62fa52 /chip
parentea1e1d667ae46556f86f072223030e9a57fe32cc (diff)
downloadchrome-ec-8a6674329235c0446aa1ce8b7ac36371c40308fe.tar.gz
IT8320DX: espi: reset espi module by FW
There is a bug on DX's espi_reset# pin. So we can't enable hardware mechanism of espi_reset#. To workaround this issue, this CL introduces a new macro to config_chip.h IT83XX_ESPI_RESET_MODULE_BY_FW which is defined when CHIP_VRAIANT is IT8320DX. When this macro is defined, the epsi hw reset pin function is disabled. Instead, the interrupt handler for this espi reset pin uses the GCTRL_RSTS register to force a reset of VCC domain logic in the EC which resets the eSPI and LPC modules. BUG=b:111480168 BRANCH=none TEST=The eSPI module is reset when EC's espi_reset# pin is asserted. Change-Id: Id7dfe746e7463c95735dde9a17777f3fce1030d0 Signed-off-by: Dino Li <Dino.Li@ite.com.tw> Reviewed-on: https://chromium-review.googlesource.com/1138134 Commit-Ready: Scott Collyer <scollyer@chromium.org> Tested-by: Scott Collyer <scollyer@chromium.org> Reviewed-by: Jett Rink <jettrink@chromium.org>
Diffstat (limited to 'chip')
-rw-r--r--chip/it83xx/config_chip.h5
-rw-r--r--chip/it83xx/espi.c53
-rw-r--r--chip/it83xx/registers.h4
3 files changed, 58 insertions, 4 deletions
diff --git a/chip/it83xx/config_chip.h b/chip/it83xx/config_chip.h
index 9da6944a36..d719c3e834 100644
--- a/chip/it83xx/config_chip.h
+++ b/chip/it83xx/config_chip.h
@@ -79,6 +79,11 @@
#define CONFIG_FLASH_SIZE 0x00080000
/* The slave frequency is adjustable (bit[2-0] at register IT83XX_ESPI_GCAC1) */
#define IT83XX_ESPI_SLAVE_MAX_FREQ_CONFIGURABLE
+/*
+ * TODO(b/111480168): eSPI HW reset can't be used because the DMA address
+ * gets set incorrectly resulting in a memory access exception.
+ */
+#define IT83XX_ESPI_RESET_MODULE_BY_FW
/* Watchdog reset supports hardware reset. */
/* TODO(b/111264984): watchdog hardware reset function failed. */
#undef IT83XX_ETWD_HW_RESET_SUPPORT
diff --git a/chip/it83xx/espi.c b/chip/it83xx/espi.c
index c31326f386..a38cab9f3f 100644
--- a/chip/it83xx/espi.c
+++ b/chip/it83xx/espi.c
@@ -417,17 +417,42 @@ static void espi_reset_vw_index_flags(void)
vw_index_flag[i] = IT83XX_ESPI_VWIDX(vw_isr_list[i].vw_index);
}
+#ifdef IT83XX_ESPI_RESET_MODULE_BY_FW
+void __ram_code espi_fw_reset_module(void)
+{
+ /*
+ * (b/111480168): Force a reset of logic VCC domain in EC. This will
+ * reset both LPC and eSPI blocks. The IT8320DX spec describes the
+ * purpose of these bits as deciding whether VCC power status is used as
+ * an internal "power good" signal. However, toggling this field while
+ * VCC is applied results in resettig VCC domain logic in EC. This code
+ * must reside in SRAM to prevent DMA address corruption.
+ *
+ * bit[7-6]:
+ * 00b: The VCC power status is treated as power-off.
+ * 01b: The VCC power status is treated as power-on.
+ */
+ IT83XX_GCTRL_RSTS = (IT83XX_GCTRL_RSTS & ~0xc0);
+ IT83XX_GCTRL_RSTS = (IT83XX_GCTRL_RSTS & ~0xc0) | (1 << 6);
+}
+#endif
+
void espi_reset_pin_asserted_interrupt(enum gpio_signal signal)
{
+#ifdef IT83XX_ESPI_RESET_MODULE_BY_FW
+ espi_fw_reset_module();
+#endif
/* reset vw_index_flag when espi_reset# asserted. */
espi_reset_vw_index_flags();
}
-static void espi_enable_reset(void)
+static int espi_get_reset_enable_config(void)
{
+ uint8_t config;
const struct gpio_info *espi_rst = gpio_list + GPIO_ESPI_RESET_L;
/*
+ * Determine if eSPI HW reset is connected to eiter B7 or D2.
* bit[2-1]:
* 00b: reserved.
* 01b: espi_reset# is enabled on GPB7.
@@ -435,14 +460,34 @@ static void espi_enable_reset(void)
* 11b: reset is disabled.
*/
if (espi_rst->port == GPIO_D && espi_rst->mask == (1 << 2)) {
- IT83XX_GPIO_GCR = (IT83XX_GPIO_GCR & ~0x6) | (1 << 2);
+ config = IT83XX_GPIO_GCR_LPC_RST_D2;
} else if (espi_rst->port == GPIO_B && espi_rst->mask == (1 << 7)) {
- IT83XX_GPIO_GCR = (IT83XX_GPIO_GCR & ~0x6) | (1 << 1);
+ config = IT83XX_GPIO_GCR_LPC_RST_B7;
} else {
- IT83XX_GPIO_GCR |= 0x6;
+ config = IT83XX_GPIO_GCR_LPC_RST_DISABLE;
CPRINTS("EC's espi_reset pin is not enabled correctly");
}
+ return config;
+}
+
+static void espi_enable_reset(void)
+{
+ int config = espi_get_reset_enable_config();
+
+#ifdef IT83XX_ESPI_RESET_MODULE_BY_FW
+ /*
+ * Need to overwrite the config to ensure that eSPI HW reset is
+ * disabled. The reset function is instead handled by FW in the
+ * interrupt handler.
+ */
+ config = IT83XX_GPIO_GCR_LPC_RST_DISABLE;
+ CPRINTS("EC's espi_reset pin hw auto reset is disabled");
+
+#endif
+ IT83XX_GPIO_GCR = (IT83XX_GPIO_GCR & ~0x6) |
+ (config << IT83XX_GPIO_GCR_LPC_RST_POS);
+
/* enable interrupt of EC's espi_reset pin */
gpio_clear_pending_interrupt(GPIO_ESPI_RESET_L);
gpio_enable_interrupt(GPIO_ESPI_RESET_L);
diff --git a/chip/it83xx/registers.h b/chip/it83xx/registers.h
index b91c18817e..227cdc2f99 100644
--- a/chip/it83xx/registers.h
+++ b/chip/it83xx/registers.h
@@ -538,6 +538,10 @@
#define IT83XX_GPIO_BASE 0x00F01600
#define IT83XX_GPIO_GCR REG8(IT83XX_GPIO_BASE+0x00)
+#define IT83XX_GPIO_GCR_LPC_RST_B7 0x1
+#define IT83XX_GPIO_GCR_LPC_RST_D2 0x2
+#define IT83XX_GPIO_GCR_LPC_RST_DISABLE 0x3
+#define IT83XX_GPIO_GCR_LPC_RST_POS 1
#define IT83XX_GPIO_GPDRA REG8(IT83XX_GPIO_BASE+0x01)
#define IT83XX_GPIO_GPDRB REG8(IT83XX_GPIO_BASE+0x02)