summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorCHLin <CHLIN56@nuvoton.com>2016-10-19 14:21:37 +0800
committerchrome-bot <chrome-bot@chromium.org>2016-10-26 01:44:21 -0700
commit8d1a958263c806acee343d8b449e39cbddc99dc5 (patch)
tree69586327e04031e3e9b47a2da3cd11b30e86cb7e
parent5cfa02b03c2b90918fbbb238ab736758bd601281 (diff)
downloadchrome-ec-8d1a958263c806acee343d8b449e39cbddc99dc5.tar.gz
npcx: espi: Fix SMI/SCI virtual wire handling
When GPIOC6/GPIO76 are not selected as SMI/SCI function(ie. selected as GPIO), the reading of SMIB/SCIB will be a fixed value. This means it cannot reflect the actul SMI/SCI status. As a reault, use SET_BIT/ CLEAR_BIT macro to toggle SMIB/SCIB is not feasible. Firmware should read the SMI/SCI status from VWEVSM(2) register before setting it. This CL defines some macros to achieve it. In the previous CL, SMI/SCI negative polarity is conditionally disabled. However, the negative polarity is not used in current firmware design. Set the SMI/SCI polarity as postive unconditionly by default. Modified drivers: 1. lpc.c: use macro NPCX_VW_SMI/NPCX_VW_SCI to generate Virtual wire. use SMI/SCI postive polarity uncontionally by default. 2. register.h : define macro to handle SMI/SCI virtual wire. BUG=chrome-os-partner:34346 BRANCH=none TEST=make buildall; try hostevent on Wheatley and check virtual wire signal is correct on logical analyzer. Change-Id: Id4a7748addeaa3b35f280ff29f6fcd8a08b9894b Signed-off-by: CHLin <CHLIN56@nuvoton.com> Reviewed-on: https://chromium-review.googlesource.com/400161 Commit-Ready: CH Lin <chlin56@nuvoton.com> Tested-by: CH Lin <chlin56@nuvoton.com> Tested-by: Duncan Laurie <dlaurie@chromium.org> Reviewed-by: Duncan Laurie <dlaurie@chromium.org>
-rw-r--r--chip/npcx/lpc.c43
-rw-r--r--chip/npcx/registers.h15
2 files changed, 56 insertions, 2 deletions
diff --git a/chip/npcx/lpc.c b/chip/npcx/lpc.c
index 7c08062e1e..d893218640 100644
--- a/chip/npcx/lpc.c
+++ b/chip/npcx/lpc.c
@@ -138,6 +138,21 @@ static void lpc_generate_smi(void)
udelay(65);
/* Set signal high, now that we've generated the edge */
gpio_set_level(GPIO_PCH_SMI_L, 1);
+#elif defined(CONFIG_ESPI)
+ /*
+ * Don't use SET_BIT/CLEAR_BIT macro to toggle SMIB/SCIB to generate
+ * virtual wire. Use NPCX_VW_SMI/NPCX_VW_SCI macro instead.
+ * The reason is - if GPIOC6/CPIO76 are not selected as SMI/SCI, reading
+ * from SMIB/SCIB doesn't really reflect the SMI/SCI status. SMI/SCI
+ * status should be read from bit 1/0 in eSPI VMEVSM(2) register.
+ */
+ NPCX_HIPMIC(PMC_ACPI) = NPCX_VW_SMI(1);
+ udelay(65);
+ /* Generate a falling edge */
+ NPCX_HIPMIC(PMC_ACPI) = NPCX_VW_SMI(0);
+ udelay(65);
+ /* Set signal high */
+ NPCX_HIPMIC(PMC_ACPI) = NPCX_VW_SMI(1);
#else
/* SET SMIB bit to pull SMI_L to high.*/
SET_BIT(NPCX_HIPMIC(PMC_ACPI), NPCX_HIPMIC_SMIB);
@@ -167,6 +182,21 @@ static void lpc_generate_sci(void)
udelay(65);
/* Set signal high, now that we've generated the edge */
gpio_set_level(CONFIG_SCI_GPIO, 1);
+#elif defined(CONFIG_ESPI)
+ /*
+ * Don't use SET_BIT/CLEAR_BIT macro to toggle SMIB/SCIB to generate
+ * virtual wire. Use NPCX_VW_SMI/NPCX_VW_SCI macro instead.
+ * The reason is - if GPIOC6/CPIO76 are not selected as SMI/SCI, reading
+ * from SMIB/SCIB doesn't really reflect the SMI/SCI status. SMI/SCI
+ * status should be read from bit 1/0 in eSPI VMEVSM(2) register.
+ */
+ NPCX_HIPMIC(PMC_ACPI) = NPCX_VW_SCI(1);
+ udelay(65);
+ /* Generate a falling edge */
+ NPCX_HIPMIC(PMC_ACPI) = NPCX_VW_SCI(0);
+ udelay(65);
+ /* Set signal high */
+ NPCX_HIPMIC(PMC_ACPI) = NPCX_VW_SCI(1);
#else
/* Set SCIB bit to pull SCI_L to high.*/
SET_BIT(NPCX_HIPMIC(PMC_ACPI), NPCX_HIPMIC_SCIB);
@@ -984,10 +1014,19 @@ static void lpc_init(void)
SET_BIT(NPCX_GLUE_SDP_CTS, 0);
#endif
-#ifndef CONFIG_SCI_GPIO
- /* Disable SMI/SCI Negative Polarity */
+ /*
+ * Use SMI/SCI postive polarity as default.
+ * Negative polarity must be enabled in the case that SMI/SCI is
+ * generated automatically by hardware. In current design,
+ * SMI/SCI is conntrolled by FW. Use postive polarity is more
+ * intuitive.
+ */
CLEAR_BIT(NPCX_HIPMCTL(PMC_ACPI), NPCX_HIPMCTL_SCIPOL);
CLEAR_BIT(NPCX_HIPMIC(PMC_ACPI), NPCX_HIPMIC_SMIPOL);
+ /* Set SMIB/SCIB to make sure SMI/SCI are high at init */
+ NPCX_HIPMIC(PMC_ACPI) = NPCX_HIPMIC(PMC_ACPI)
+ | (1 << NPCX_HIPMIC_SMIB) | (1 << NPCX_HIPMIC_SCIB);
+#ifndef CONFIG_SCI_GPIO
/*
* Allow SMI/SCI generated from PM module.
* Either hardware autimatically generates,
diff --git a/chip/npcx/registers.h b/chip/npcx/registers.h
index 2889837b3b..4b85b9f228 100644
--- a/chip/npcx/registers.h
+++ b/chip/npcx/registers.h
@@ -1412,6 +1412,21 @@ enum ITIM16_MODULE_T {
#define VWGPMS_FIELD(n, m, p, e) (VMGPMS_INX_EN(n) | VWGPMS_MODIFIED(m) | \
VWGPMS_PLTRST_EN(p) | VWGPMS_INT_EN(e))
+/* define macro to handle SMI/SCI Virtual Wire */
+/* Read SMI VWire status from VWEVSM(offset 2) register. */
+#define SMI_STATUS_MASK ((uint8_t) (NPCX_VWEVSM(2) & 0x00000002))
+/*
+ * Read SCI VWire status from VWEVSM(offset 2) register.
+ * Left shift 2 to meet the SCIB filed in HIPMIC register.
+ */
+#define SCI_STATUS_MASK (((uint8_t) (NPCX_VWEVSM(2) & 0x00000001)) << 2)
+#define SCIB_MASK(v) (v << NPCX_HIPMIC_SCIB)
+#define SMIB_MASK(v) (v << NPCX_HIPMIC_SMIB)
+#define NPCX_VW_SCI(level) ((NPCX_HIPMIC(PM_CHAN_1) & 0xF9) | \
+ SMI_STATUS_MASK | SCIB_MASK(level))
+#define NPCX_VW_SMI(level) ((NPCX_HIPMIC(PM_CHAN_1) & 0xF9) | \
+ SCI_STATUS_MASK | SMIB_MASK(level))
+
/* eSPI enumeration */
/* eSPI channels */
enum {