From cb4b9f9facb2f264fc13e180a5f060f80d4122e7 Mon Sep 17 00:00:00 2001 From: Furquan Shaikh Date: Tue, 16 Aug 2016 20:06:46 -0700 Subject: [PATCH] chip/npcx/lpc: Fix SCI and SMI generation Following steps need to be followed for SCI/SMI generation: 1. If automatic mode is being used, set SCIE/SMIE bit in HIPMIE register during lpc_init. This step needs to be performed only once. 2. If SCI/SMI generation is required, set ST1/ST2 bit in HIPMST register during update_host_event_status. 3. In lpc_generate_sci/smi, if automatic mode is being used, set SCIB/SMIB bit in HIPMIC register. BUG=chrome-os-partner:55489 BRANCH=None TEST=lidclose behavior verified in kernel. Change-Id: Ib6e0ee32bc06a8c51297010ac4843a7de45a99bd Signed-off-by: Furquan Shaikh Reviewed-on: https://chromium-review.googlesource.com/371059 Commit-Ready: Furquan Shaikh Tested-by: Furquan Shaikh Reviewed-by: Randall Spangler Reviewed-by: Mulin Chao --- chip/npcx/lpc.c | 30 ++++++++++++++++++++++++------ chip/npcx/registers.h | 13 +++++++++++++ 2 files changed, 37 insertions(+), 6 deletions(-) diff --git a/chip/npcx/lpc.c b/chip/npcx/lpc.c index 6f4a08364a..4523ff032a 100644 --- a/chip/npcx/lpc.c +++ b/chip/npcx/lpc.c @@ -139,7 +139,14 @@ static void lpc_generate_smi(void) /* Set signal high, now that we've generated the edge */ gpio_set_level(GPIO_PCH_SMI_L, 1); #else - NPCX_HIPMIE(PMC_ACPI) |= NPCX_HIPMIE_SMIE; + /* Since SMIPOL is 1, clear SCIB bit means set SCI_L to high.*/ + CLEAR_BIT(NPCX_HIPMIC(PMC_ACPI), NPCX_HIPMIC_SMIB); + udelay(65); + /* Generate a falling edge */ + SET_BIT(NPCX_HIPMIC(PMC_ACPI), NPCX_HIPMIC_SMIB); + udelay(65); + /* Set signal high */ + CLEAR_BIT(NPCX_HIPMIC(PMC_ACPI), NPCX_HIPMIC_SMIB); #endif if (host_events & event_mask[LPC_HOST_EVENT_SMI]) CPRINTS("smi 0x%08x", @@ -161,7 +168,14 @@ static void lpc_generate_sci(void) /* Set signal high, now that we've generated the edge */ gpio_set_level(CONFIG_SCI_GPIO, 1); #else - SET_BIT(NPCX_HIPMIE(PMC_ACPI), NPCX_HIPMIE_SCIE); + /* Since SCIPOL is 1, clear SCIB bit means set SCI_L to high.*/ + CLEAR_BIT(NPCX_HIPMIC(PMC_ACPI), NPCX_HIPMIC_SCIB); + udelay(65); + /* Generate a falling edge */ + SET_BIT(NPCX_HIPMIC(PMC_ACPI), NPCX_HIPMIC_SCIB); + udelay(65); + /* Set signal high */ + CLEAR_BIT(NPCX_HIPMIC(PMC_ACPI), NPCX_HIPMIC_SCIB); #endif if (host_events & event_mask[LPC_HOST_EVENT_SCI]) @@ -309,16 +323,16 @@ static void update_host_event_status(void) /* Only generate SMI for first event */ if (!(NPCX_HIPMIE(PMC_ACPI) & NPCX_HIPMIE_SMIE)) need_smi = 1; - SET_BIT(NPCX_HIPMIE(PMC_ACPI), NPCX_HIPMIE_SMIE); + SET_BIT(NPCX_HIPMST(PMC_ACPI), NPCX_HIPMST_ST2); } else - CLEAR_BIT(NPCX_HIPMIE(PMC_ACPI), NPCX_HIPMIE_SMIE); + CLEAR_BIT(NPCX_HIPMST(PMC_ACPI), NPCX_HIPMST_ST2); if (host_events & event_mask[LPC_HOST_EVENT_SCI]) { /* Generate SCI for every event */ need_sci = 1; - SET_BIT(NPCX_HIPMIE(PMC_ACPI), NPCX_HIPMIE_SCIE); + SET_BIT(NPCX_HIPMST(PMC_ACPI), NPCX_HIPMST_ST1); } else - CLEAR_BIT(NPCX_HIPMIE(PMC_ACPI), NPCX_HIPMIE_SCIE); + CLEAR_BIT(NPCX_HIPMST(PMC_ACPI), NPCX_HIPMST_ST1); /* Copy host events to mapped memory */ *(uint32_t *)host_get_memmap(EC_MEMMAP_HOST_EVENTS) = host_events; @@ -902,6 +916,10 @@ static void lpc_init(void) SET_BIT(NPCX_GLUE_SDP_CTS, 0); #endif +#ifndef CONFIG_SCI_GPIO + SET_BIT(NPCX_HIPMIE(PMC_ACPI), NPCX_HIPMIE_SCIE); + SET_BIT(NPCX_HIPMIE(PMC_ACPI), NPCX_HIPMIE_SMIE); +#endif lpc_task_enable_irq(); /* Initialize host args and memory map to all zero */ diff --git a/chip/npcx/registers.h b/chip/npcx/registers.h index e21f164269..67fceaf5d4 100644 --- a/chip/npcx/registers.h +++ b/chip/npcx/registers.h @@ -939,10 +939,23 @@ enum NPCX_PMC_PWDWN_CTL_T { #define NPCX_HIPMIE(n) REG8(NPCX_PM_CH_BASE_ADDR(n) + 0x010) /* PM Channel register field */ + +/* NPCX_HIPMIE */ #define NPCX_HIPMIE_SCIE 1 #define NPCX_HIPMIE_SMIE 2 + +/* NPCX_HIPMCTL */ #define NPCX_HIPMCTL_IBFIE 0 +/* NPCX_HIPMST */ +#define NPCX_HIPMST_ST0 4 +#define NPCX_HIPMST_ST1 5 +#define NPCX_HIPMST_ST2 6 + +/* NPCX_HIPMIC */ +#define NPCX_HIPMIC_SMIB 1 +#define NPCX_HIPMIC_SCIB 2 + /* * PM Channel enumeration */