summaryrefslogtreecommitdiff
path: root/chip/mchp
diff options
context:
space:
mode:
authorscott worley <scott.worley@microchip.corp-partner.google.com>2018-05-10 15:47:14 -0400
committerchrome-bot <chrome-bot@chromium.org>2018-06-14 01:31:51 -0700
commited30a9ea110f18d19fad3e9ece1f47e0c7019140 (patch)
tree8a71827635986d4d841017ce307b894fcd951404 /chip/mchp
parentfe921e8ea12abfaf889e8bdbf60666ce1c870f2b (diff)
downloadchrome-ec-ed30a9ea110f18d19fad3e9ece1f47e0c7019140.tar.gz
ec_chip_mchp: Fix LPC bugs configuring logical devices
LPC and eSPI logical device configuration is mostly common. Create common subroutines for LD configuration. Fix bugs in LPC LD configuration for ACPI, EMI, Port80. Add work- around for APL LRESET# changing when LPC clock is not running. BRANCH=none BUG=None TEST=Build all boards using chip mchp. Test LPC and eSPI communication with host chipset via EC/Host UART logs. CQ-DEPEND=CL:1053576,CL:1053827,CL:1053880,CL:1053949 Change-Id: Ie40245c20627178a0e518eafc028d194c1f176a6 Signed-off-by: scott worley <scott.worley@microchip.corp-partner.google.com> Reviewed-on: https://chromium-review.googlesource.com/1053884 Commit-Ready: ChromeOS CL Exonerator Bot <chromiumos-cl-exonerator@appspot.gserviceaccount.com> Tested-by: Randall Spangler <rspangler@chromium.org> Reviewed-by: Randall Spangler <rspangler@chromium.org>
Diffstat (limited to 'chip/mchp')
-rw-r--r--chip/mchp/config_chip.h5
-rw-r--r--chip/mchp/espi.c82
-rw-r--r--chip/mchp/lpc.c445
-rw-r--r--chip/mchp/lpc_chip.h14
4 files changed, 312 insertions, 234 deletions
diff --git a/chip/mchp/config_chip.h b/chip/mchp/config_chip.h
index 8c1cab81a5..7a0008958c 100644
--- a/chip/mchp/config_chip.h
+++ b/chip/mchp/config_chip.h
@@ -144,6 +144,11 @@
#undef CONFIG_MCHP_ESPI_EC_CMD
/*
+ * Enable CPRINT debug messages in LPC module
+ */
+#undef CONFIG_MCHP_DEBUG_LPC
+
+/*
* Define this to use MEC1701 ROM SPI read API
* in little firmware module instead of SPI code
* from this module
diff --git a/chip/mchp/espi.c b/chip/mchp/espi.c
index 03f9365df4..6622dd15c5 100644
--- a/chip/mchp/espi.c
+++ b/chip/mchp/espi.c
@@ -509,89 +509,19 @@ static void espi_host_init(void)
MCHP_ESPI_IO_BAR_VALID(MCHP_ESPI_IO_BAR_ID_CFG_PORT) = 1;
/* Set up ACPI0 for 0x62/0x66 */
- MCHP_ESPI_IO_BAR_CTL_MASK(MCHP_ESPI_IO_BAR_ID_ACPI_EC0) = 0x04;
- MCHP_ESPI_IO_BAR(MCHP_ESPI_IO_BAR_ID_ACPI_EC0) =
- (0x62ul << 16) + 0x01ul;
- MCHP_INT_ENABLE(MCHP_ACPI_EC_GIRQ) =
- MCHP_ACPI_EC_IBF_GIRQ_BIT(0);
- /* Clear STATUS_PROCESSING bit in case it was set during sysjump */
- MCHP_ACPI_EC_STATUS(0) &= ~EC_LPC_STATUS_PROCESSING;
- task_enable_irq(MCHP_IRQ_ACPIEC0_IBF);
+ chip_acpi_ec_config(0, 0x62, 0x04);
/* Set up ACPI1 for 0x200-0x203, 0x204-0x207 */
- MCHP_ESPI_IO_BAR_CTL_MASK(MCHP_ESPI_IO_BAR_ID_ACPI_EC1) = 0x07;
- MCHP_ESPI_IO_BAR(MCHP_ESPI_IO_BAR_ID_ACPI_EC1) =
- (0x200ul << 16) + 0x01ul;
- MCHP_INT_ENABLE(MCHP_ACPI_EC_GIRQ) =
- MCHP_ACPI_EC_IBF_GIRQ_BIT(1);
- MCHP_ACPI_EC_STATUS(1) &= ~EC_LPC_STATUS_PROCESSING;
- task_enable_irq(MCHP_IRQ_ACPIEC1_IBF);
+ chip_acpi_ec_config(1, 0x200, 0x07);
/* Set up 8042 interface at 0x60/0x64 */
- MCHP_ESPI_IO_BAR_CTL_MASK(MCHP_ESPI_IO_BAR_ID_8042) = 0x04;
- MCHP_ESPI_IO_BAR(MCHP_ESPI_IO_BAR_ID_8042) =
- (0x64ul << 16) + 0x01ul;
-
- /* Set up indication of Auxiliary sts */
- MCHP_8042_KB_CTRL |= 1 << 7;
-
- MCHP_8042_ACT |= 1;
- MCHP_INT_ENABLE(MCHP_8042_GIRQ) = MCHP_8042_OBE_GIRQ_BIT +
- MCHP_8042_IBF_GIRQ_BIT;
- task_enable_irq(MCHP_IRQ_8042EM_IBF);
- task_enable_irq(MCHP_IRQ_8042EM_OBE);
-
-#ifndef CONFIG_KEYBOARD_IRQ_GPIO
- /* Set up SERIRQ for keyboard */
- MCHP_8042_KB_CTRL |= (1 << 5);
- MCHP_ESPI_IO_SERIRQ_REG(MCHP_ESPI_8042_SIRQ0) = 1;
-#endif
-
- /* Set up EMI module for memory mapped region,
- * IO range 0x800-0x80f
- */
- MCHP_ESPI_IO_BAR_CTL_MASK(MCHP_ESPI_IO_BAR_ID_EMI0) = 0x0F;
- MCHP_ESPI_IO_BAR(MCHP_ESPI_IO_BAR_ID_EMI0) =
- (0x800ul << 16) + 0x01ul;
- MCHP_INT_ENABLE(MCHP_EMI_GIRQ) = MCHP_EMI_GIRQ_BIT(0);
- task_enable_irq(MCHP_IRQ_EMI0);
+ chip_8042_config(0x60);
- /*
- * Access data RAM
- * MCHP EMI Base address register = physical address in
- * SRAM of buffer.
- * EMI hardware adds 16-bit offset Host programs into
- * EC_Address_LSB/MSB registers.
- */
- MCHP_EMI_MBA0(0) = lpc_mem_mapped_addr();
-
- /*
- * Limit EMI read / write range. First 256 bytes are RW for host
- * commands. Second 256 bytes are RO for mem-mapped data.
- */
- MCHP_EMI_MRL0(0) = 0x200;
- MCHP_EMI_MWL0(0) = 0x100;
+ /* EMI at 0x800 for accessing shared memory */
+ chip_emi0_config(0x800);
/* Setup Port80 Debug Hardware for I/O 80h */
- MCHP_P80_CFG(0) = MCHP_P80_FLUSH_FIFO_WO +
- MCHP_P80_RESET_TIMESTAMP_WO;
-
- /* IO 0x80 only, mask = 0 */
- MCHP_ESPI_IO_BAR_CTL_MASK(MCHP_ESPI_IO_BAR_P80_0) = 0x00;
- MCHP_ESPI_IO_BAR(MCHP_ESPI_IO_BAR_P80_0) =
- (0x80ul << 16) + 0x01ul;
-
- MCHP_P80_CFG(0) = MCHP_P80_FIFO_THRHOLD_1 +
- MCHP_P80_TIMEBASE_1500KHZ +
- MCHP_P80_TIMER_ENABLE;
-
-
- MCHP_P80_ACTIVATE(0) = 1;
-
- MCHP_INT_SOURCE(15) = (1ul << 22);
- MCHP_INT_ENABLE(15) = (1ul << 22);
-
- task_enable_irq(MCHP_IRQ_PORT80DBG0);
+ chip_port80_config(0x80);
lpc_mem_mapped_init();
diff --git a/chip/mchp/lpc.c b/chip/mchp/lpc.c
index 57553ed200..b14a7d3b90 100644
--- a/chip/mchp/lpc.c
+++ b/chip/mchp/lpc.c
@@ -25,9 +25,13 @@
#include "tfdp_chip.h"
/* Console output macros */
-
+#ifdef CONFIG_MCHP_DEBUG_LPC
#define CPUTS(outstr) cputs(CC_LPC, outstr)
#define CPRINTS(format, args...) cprints(CC_LPC, format, ## args)
+#else
+#define CPUTS(...)
+#define CPRINTS(...)
+#endif
static uint8_t
mem_mapped[0x200] __attribute__((section(".bss.big_align")));
@@ -83,8 +87,7 @@ static void keyboard_irq_assert(void)
*/
static void lpc_generate_smi(void)
{
- /* CPRINTS("LPC Pulse SMI"); */
- trace0(0, LPC, 0, "LPC Pulse SMI");
+ CPUTS("LPC Pulse SMI");
#ifdef CONFIG_HOSTCMD_ESPI
/* eSPI: pulse SMI# Virtual Wire low */
espi_vw_pulse_wire(VW_SMI_L, 0);
@@ -97,8 +100,7 @@ static void lpc_generate_smi(void)
static void lpc_generate_sci(void)
{
- /* CPRINTS("LPC Pulse SCI"); */
- trace0(0, LPC, 0, "LPC Pulse SCI");
+ CPUTS("LPC Pulse SCI");
#ifdef CONFIG_SCI_GPIO
gpio_set_level(CONFIG_SCI_GPIO, 0);
udelay(65);
@@ -122,8 +124,8 @@ static void lpc_generate_sci(void)
static void lpc_update_wake(host_event_t wake_events)
{
/*
- * Mask off power button event, since the AP gets that through a
- * separate dedicated GPIO.
+ * Mask off power button event, since the AP gets that
+ * through a separate dedicated GPIO.
*/
wake_events &= ~EC_HOST_EVENT_MASK(EC_HOST_EVENT_POWER_BUTTON);
@@ -153,8 +155,7 @@ void lpc_update_host_event_status(void)
int need_sci = 0;
int need_smi = 0;
- CPRINTS("LPC update_host_event_status");
- trace0(0, LPC, 0, "LPC update_host_event_status");
+ CPUTS("LPC update_host_event_status");
if (!init_done)
return;
@@ -216,7 +217,7 @@ static void lpc_send_response(struct host_cmd_handler_args *args)
/* New-style response */
lpc_host_args->flags =
- (host_cmd_flags & ~EC_HOST_ARGS_FLAG_FROM_HOST) |
+ (host_cmd_flags & ~EC_HOST_ARGS_FLAG_FROM_HOST) |
EC_HOST_ARGS_FLAG_TO_HOST;
lpc_host_args->data_size = size;
@@ -237,7 +238,7 @@ static void lpc_send_response(struct host_cmd_handler_args *args)
/* Write result to the data byte. */
MCHP_ACPI_EC_EC2OS(1, 0) = args->result;
- /*
+ /*
* Clear processing flag in hardware and
* sticky status in interrupt aggregator.
*/
@@ -249,23 +250,15 @@ static void lpc_send_response(struct host_cmd_handler_args *args)
static void lpc_send_response_packet(struct host_packet *pkt)
{
- int i;
- uint8_t *p8;
-
- /* Ignore in-progress on LPC since interface is synchronous anyway */
+ /* Ignore in-progress on LPC since interface is
+ * synchronous anyway
+ */
if (pkt->driver_result == EC_RES_IN_PROGRESS) {
/* CPRINTS("LPC EC_RES_IN_PROGRESS"); */
return;
}
- /* CPRINTS("LPC Set EC2OS(1,0)=0x%02x",pkt->driver_result); */
- trace1(0, LPC, 0, "LPC Set EC2OS(1,0)=0x%02x", pkt->driver_result);
-
- p8 = (uint8_t *)pkt->response;
- if (p8 != NULL) {
- for (i = 0; i < pkt->response_size; i++)
- trace2(0, LPC, 0, "response[%d] = 0x%02x", i, *p8++);
- }
+ CPRINTS("LPC Set EC2OS(1,0)=0x%02x", pkt->driver_result);
/* Write result to the data byte. */
MCHP_ACPI_EC_EC2OS(1, 0) = pkt->driver_result;
@@ -281,11 +274,6 @@ uint8_t *lpc_get_memmap_range(void)
return mem_mapped + 0x100;
}
-uint32_t lpc_mem_mapped_addr(void)
-{
- return (uint32_t)mem_mapped;
-}
-
void lpc_mem_mapped_init(void)
{
/* We support LPC args and version 3 protocol */
@@ -294,51 +282,71 @@ void lpc_mem_mapped_init(void)
EC_HOST_CMD_FLAG_VERSION_3;
}
+const int acpi_ec_pcr_slp[MCHP_ACPI_EC_MAX] = {
+ MCHP_PCR_ACPI_EC0,
+ MCHP_PCR_ACPI_EC1,
+ MCHP_PCR_ACPI_EC2,
+ MCHP_PCR_ACPI_EC3,
+ MCHP_PCR_ACPI_EC4,
+};
-/*
- * Most registers in LPC module are reset when the host is off. We need to
- * set up LPC again when the host is starting up.
- * MCHP does not appear to connect LRESET# to an interrupt!
- * MCHP LRESET# can be one of two pins
- * GPIO_0052 Func 2
- * GPIO_0064 Func 1
- * Use GPIO interrupt to detect LRESET# changes.
- * Use GPIO_0064 for LRESET#. Must update board/board_name/gpio.inc
- *
- * For eSPI PLATFORM_RESET# virtual wire is used as LRESET#
- *
- */
-#ifndef CONFIG_HOSTCMD_ESPI
-static void setup_lpc(void)
-{
- gpio_config_module(MODULE_LPC, 1);
-
- /*
- * MCHP LRESET# interrupt is GPIO interrupt
- * and configured by GPIO table in board level gpio.inc
- * Refer to lpcrst_interrupt() in this file.
- */
+const int acpi_ec_nvic_ibf[MCHP_ACPI_EC_MAX] = {
+ MCHP_IRQ_ACPIEC0_IBF,
+ MCHP_IRQ_ACPIEC1_IBF,
+ MCHP_IRQ_ACPIEC2_IBF,
+ MCHP_IRQ_ACPIEC3_IBF,
+ MCHP_IRQ_ACPIEC4_IBF,
+};
- /* Set up ACPI0 for 0x62/0x66 */
- MCHP_LPC_ACPI_EC0_BAR = 0x00628304;
+#ifdef CONFIG_HOSTCMD_ESPI
+const int acpi_ec_espi_bar_id[MCHP_ACPI_EC_MAX] = {
+ MCHP_ESPI_IO_BAR_ID_ACPI_EC0,
+ MCHP_ESPI_IO_BAR_ID_ACPI_EC1,
+ MCHP_ESPI_IO_BAR_ID_ACPI_EC2,
+ MCHP_ESPI_IO_BAR_ID_ACPI_EC3,
+ MCHP_ESPI_IO_BAR_ID_ACPI_EC4,
+};
+#endif
- /* Clear STATUS_PROCESSING bit in case it was set during sysjump */
- MCHP_ACPI_EC_STATUS(0) &= ~EC_LPC_STATUS_PROCESSING;
- MCHP_INT_ENABLE(MCHP_ACPI_EC_GIRQ) =
- MCHP_ACPI_EC_IBF_GIRQ_BIT(0);
- task_enable_irq(MCHP_IRQ_ACPIEC0_IBF);
+void chip_acpi_ec_config(int instance, uint32_t io_base, uint8_t mask)
+{
+ if (instance >= MCHP_ACPI_EC_MAX)
+ CPUTS("ACPI EC CFG invalid");
- /* Set up ACPI1 for 0x200/0x204 */
- MCHP_LPC_ACPI_EC1_BAR = 0x02008407;
+ MCHP_PCR_SLP_DIS_DEV(acpi_ec_pcr_slp[instance]);
- MCHP_ACPI_EC_STATUS(1) &= ~EC_LPC_STATUS_PROCESSING;
+#ifdef CONFIG_HOSTCMD_ESPI
+ MCHP_ESPI_IO_BAR_CTL_MASK(acpi_ec_espi_bar_id[instance]) =
+ mask;
+ MCHP_ESPI_IO_BAR(acpi_ec_espi_bar_id[instance]) =
+ (io_base << 16) + 0x01ul;
+#else
+ MCHP_LPC_ACPI_EC_BAR(instance) = (io_base << 16) +
+ (1ul << 15) + mask;
+#endif
+ MCHP_ACPI_EC_STATUS(instance) &= ~EC_LPC_STATUS_PROCESSING;
MCHP_INT_ENABLE(MCHP_ACPI_EC_GIRQ) =
- MCHP_ACPI_EC_IBF_GIRQ_BIT(1);
- task_enable_irq(MCHP_IRQ_ACPIEC1_IBF);
+ MCHP_ACPI_EC_IBF_GIRQ_BIT(instance);
+ task_enable_irq(acpi_ec_nvic_ibf[instance]);
+}
- /* Set up 8042 interface at 0x60/0x64 */
- MCHP_LPC_8042_BAR = 0x00608104;
+/*
+ * 8042EM hardware decodes with fixed mask of 0x04
+ * Example: io_base == 0x60 -> decodes 0x60/0x64
+ * Enable both IBF and OBE interrupts.
+ */
+void chip_8042_config(uint32_t io_base)
+{
+ MCHP_PCR_SLP_DIS_DEV(MCHP_PCR_8042);
+#ifdef CONFIG_HOSTCMD_ESPI
+ MCHP_ESPI_IO_BAR_CTL_MASK(MCHP_ESPI_IO_BAR_ID_8042) = 0x04;
+ MCHP_ESPI_IO_BAR(MCHP_ESPI_IO_BAR_ID_8042) =
+ (io_base << 16) + 0x01ul;
+#else
+ /* Set up 8042 interface at 0x60/0x64 */
+ MCHP_LPC_8042_BAR = (io_base << 16) + (1ul << 15);
+#endif
/* Set up indication of Auxiliary sts */
MCHP_8042_KB_CTRL |= 1 << 7;
@@ -355,58 +363,136 @@ static void setup_lpc(void)
MCHP_8042_KB_CTRL |= (1 << 5);
MCHP_LPC_SIRQ(1) = 0x01;
#endif
+}
- /* Set up EMI module for memory mapped region, base address 0x800 */
- MCHP_LPC_EMI0_BAR = 0x0800800f;
-
- MCHP_INT_ENABLE(MCHP_EMI_GIRQ) = MCHP_EMI_GIRQ_BIT(0);
- task_enable_irq(MCHP_IRQ_EMI0);
+/*
+ * Access data RAM
+ * MCHP EMI Base address register = physical address of buffer
+ * in SRAM. EMI hardware adds 16-bit offset Host programs into
+ * EC_Address_LSB/MSB registers.
+ * Limit EMI read / write range. First 256 bytes are RW for host
+ * commands. Second 256 bytes are RO for mem-mapped data.
+ * Hardware decodes a fixed 16 byte IO range.
+ */
+void chip_emi0_config(uint32_t io_base)
+{
+#ifdef CONFIG_HOSTCMD_ESPI
+ MCHP_ESPI_IO_BAR_CTL_MASK(MCHP_ESPI_IO_BAR_ID_EMI0) = 0x0F;
+ MCHP_ESPI_IO_BAR(MCHP_ESPI_IO_BAR_ID_EMI0) =
+ (io_base << 16) + 0x01ul;
+#else
+ MCHP_LPC_EMI0_BAR = (io_base << 16) + (1ul << 15);
+#endif
- /*
- * Access data RAM
- * MCHP EMI Base address register = physical address of buffer
- * in SRAM. EMI hardware adds 16-bit offset Host programs into
- * EC_Address_LSB/MSB registers.
- */
MCHP_EMI_MBA0(0) = (uint32_t)mem_mapped;
- /*
- * Limit EMI read / write range. First 256 bytes are RW for host
- * commands. Second 256 bytes are RO for mem-mapped data.
- */
MCHP_EMI_MRL0(0) = 0x200;
MCHP_EMI_MWL0(0) = 0x100;
- /* Setup Port80 Debug Hardware ports.
- * First instance for I/O 80h only.
- * Set FIFO interrupt threshold to maximum of 14 bytes.
- */
+ MCHP_INT_ENABLE(MCHP_EMI_GIRQ) = MCHP_EMI_GIRQ_BIT(0);
+ task_enable_irq(MCHP_IRQ_EMI0);
+}
+
+/* Setup Port80 Debug Hardware ports.
+ * First instance for I/O 80h only.
+ * Clear FIFO's and timestamp.
+ * Set FIFO interrupt threshold to maximum of 14 bytes.
+ */
+void chip_port80_config(uint32_t io_base)
+{
+ MCHP_PCR_SLP_DIS_DEV(MCHP_PCR_P80CAP0);
+
MCHP_P80_CFG(0) = MCHP_P80_FLUSH_FIFO_WO +
MCHP_P80_RESET_TIMESTAMP_WO;
- MCHP_LPC_P80DBG0_BAR = (0x80ul << 16) + 0x01ul;
-
+#ifdef CONFIG_HOSTCMD_ESPI
+ MCHP_ESPI_IO_BAR_CTL_MASK(MCHP_ESPI_IO_BAR_P80_0) = 0x00;
+ MCHP_ESPI_IO_BAR(MCHP_ESPI_IO_BAR_P80_0) =
+ (io_base << 16) + 0x01ul;
+#else
+ MCHP_LPC_P80DBG0_BAR = (io_base << 16) + (1ul << 15);
+#endif
MCHP_P80_CFG(0) = MCHP_P80_FIFO_THRHOLD_14 +
MCHP_P80_TIMEBASE_1500KHZ +
MCHP_P80_TIMER_ENABLE;
+ MCHP_P80_ACTIVATE(0) = 1;
+
+ MCHP_INT_SOURCE(15) = MCHP_INT15_P80(0);
+ MCHP_INT_ENABLE(15) = MCHP_INT15_P80(0);
task_enable_irq(MCHP_IRQ_PORT80DBG0);
+}
+
+#ifdef CONFIG_MCHP_DEBUG_LPC
+static void chip_lpc_iobar_debug(void)
+{
+ CPRINTS("LPC ACPI EC0 IO BAR = 0x%08x", MCHP_LPC_ACPI_EC_BAR(0));
+ CPRINTS("LPC ACPI EC1 IO BAR = 0x%08x", MCHP_LPC_ACPI_EC_BAR(1));
+ CPRINTS("LPC 8042EM IO BAR = 0x%08x", MCHP_LPC_8042_BAR);
+ CPRINTS("LPC EMI0 IO BAR = 0x%08x", MCHP_LPC_EMI0_BAR);
+ CPRINTS("LPC Port80Dbg0 IO BAR = 0x%08x", MCHP_LPC_P80DBG0_BAR);
+}
+#endif
+
+/*
+ * Most registers in LPC module are reset when the host is off.
+ * We need to set up LPC again when the host is starting up.
+ * MCHP LRESET# can be one of two pins
+ * GPIO_0052 Func 2
+ * GPIO_0064 Func 1
+ * Use GPIO interrupt to detect LRESET# changes.
+ * Use GPIO_0064 for LRESET#. Must update board/board_name/gpio.inc
+ *
+ * For eSPI PLATFORM_RESET# virtual wire is used as LRESET#
+ *
+ */
+#ifndef CONFIG_HOSTCMD_ESPI
+static void setup_lpc(void)
+{
+ TRACE0(55, LPC, 0, "setup_lpc");
+
+ MCHP_LPC_CFG_BAR |= (1ul << 15);
+
+ /* Set up ACPI0 for 0x62/0x66 */
+ chip_acpi_ec_config(0, 0x62, 0x04);
+
+ /* Set up ACPI1 for 0x200 - 0x207 */
+ chip_acpi_ec_config(1, 0x200, 0x07);
+
+ /* Set up 8042 interface at 0x60/0x64 */
+ chip_8042_config(0x60);
+
+#ifndef CONFIG_KEYBOARD_IRQ_GPIO
+ /* Set up SERIRQ for keyboard */
+ MCHP_8042_KB_CTRL |= (1 << 5);
+ MCHP_LPC_SIRQ(1) = 0x01;
+#endif
+ /* EMI0 at IO 0x800 */
+ chip_emi0_config(0x800);
+
+ chip_port80_config(0x80);
lpc_mem_mapped_init();
+ /* Activate LPC interface */
+ MCHP_LPC_ACT |= 1;
+
/* Sufficiently initialized */
init_done = 1;
/* Update host events now that we can copy them to memmap */
lpc_update_host_event_status();
+
+#ifdef CONFIG_MCHP_DEBUG_LPC
+ chip_lpc_iobar_debug();
+#endif
}
DECLARE_HOOK(HOOK_CHIPSET_STARTUP, setup_lpc, HOOK_PRIO_FIRST);
#endif
static void lpc_init(void)
{
- CPRINTS("LPC HOOK_INIT");
- trace0(0, HOOK, 0, "HOOK_INIT - lpc_init");
+ CPUTS("LPC HOOK_INIT");
/* Initialize host args and memory map to all zero */
memset(lpc_host_args, 0, sizeof(*lpc_host_args));
@@ -420,7 +506,8 @@ static void lpc_init(void)
* NOTE: EMI doesn't have a sleep enable.
*/
MCHP_PCR_SLP_DIS_DEV_MASK(2, MCHP_PCR_SLP_EN2_GCFG +
- MCHP_PCR_SLP_EN2_ACPI_EC0 + MCHP_PCR_SLP_EN2_ACPI_EC0 +
+ MCHP_PCR_SLP_EN2_ACPI_EC0 +
+ MCHP_PCR_SLP_EN2_ACPI_EC0 +
MCHP_PCR_SLP_EN2_MIF8042);
MCHP_PCR_SLP_DIS_DEV(MCHP_PCR_P80CAP0);
@@ -433,27 +520,37 @@ static void lpc_init(void)
/* Clear PCR LPC sleep enable */
MCHP_PCR_SLP_DIS_DEV(MCHP_PCR_LPC);
+ /* configure pins */
+ gpio_config_module(MODULE_LPC, 1);
+
+ /*
+ * MCHP LRESET# interrupt is GPIO interrupt
+ * and configured by GPIO table in board level gpio.inc
+ * Refer to lpcrst_interrupt() in this file.
+ */
+ gpio_enable_interrupt(GPIO_PCH_PLTRST_L);
+
/*
* b[8]=1(LRESET# is platform reset), b[0]=0 VCC_PWRGD is
* asserted when LRESET# is 1(inactive)
*/
MCHP_PCR_PWR_RST_CTL = 0x100ul;
- /* Activate LPC interface */
- MCHP_LPC_ACT |= 1;
-
/*
- * Ring Oscillator not permitted to shut down
- * until LPC activate bit is cleared
+ * Allow LPC sleep if Host CLKRUN# signals
+ * clock stop and there are no pending SERIRQ
+ * or LPC DMA.
*/
- MCHP_LPC_EC_CLK_CTRL |= 3;
+ MCHP_LPC_EC_CLK_CTRL =
+ (MCHP_LPC_EC_CLK_CTRL & ~(0x03ul)) | 0x01ul;
setup_lpc();
#endif
}
/*
- * Set priority to higher than default; this way LPC memory mapped data
- * is ready before other inits try to initialize their memmap data.
+ * Set priority to higher than default; this way LPC memory mapped
+ * data is ready before other inits try to initialize their
+ * memmap data.
*/
DECLARE_HOOK(HOOK_INIT, lpc_init, HOOK_PRIO_INIT_LPC);
@@ -466,6 +563,27 @@ DECLARE_DEFERRED(lpc_chipset_reset);
#endif
+#ifdef CONFIG_HOSTCMD_ESPI
+/*
+ * Called from power/skylake.c chipset_reset()
+ * For LPC it doesn't call here, instead it pulses RCIN# low
+ * for 10 us
+ */
+void lpc_host_reset(void)
+{
+ /* Host Reset Control will assert KBRST# (LPC) or
+ * RCIN# VW (eSPI)
+ */
+#ifdef CONFIG_HOSTCMD_ESPI_VW_SIGNALS
+ espi_vw_pulse_wire(VW_RCIN_L, 0);
+#else
+ gpio_set_level(GPIO_SYS_RESET_L, 0);
+ udelay(10);
+ gpio_set_level(GPIO_SYS_RESET_L, 1);
+#endif
+}
+#endif /* #ifdef CONFIG_HOSTCMD_ESPI */
+
void lpc_set_init_done(int val)
{
init_done = val;
@@ -474,8 +592,10 @@ void lpc_set_init_done(int val)
/*
* MCHP MCHP family allows selecting one of two GPIO pins alternate
* functions as LRESET#.
- * LRESET# can be monitored as bit[1](read-only) of the LPC Bus Monitor
- * register.
+ * LRESET# can be monitored as bit[1](read-only) of the
+ * LPC Bus Monitor register. NOTE: Bus Monitor is synchronized with
+ * LPC clock. We have observed APL configurations where LRESET#
+ * changes while LPC clock is not running!
* bit[1]==0 -> LRESET# is high
* bit[1]==1 -> LRESET# is low (active)
* LRESET# active causes the EC to activate internal signal RESET_HOST.
@@ -503,20 +623,24 @@ void lpcrst_interrupt(enum gpio_signal signal)
hook_call_deferred(&lpc_chipset_reset_data, MSEC);
#endif
}
-
+#ifdef CONFIG_MCHP_DEBUG_LPC
CPRINTS("LPC RESET# %sasserted",
lpc_get_pltrst_asserted() ? "" : "de");
#endif
+#endif
}
-
+/*
+ * TODO - Is this only for debug of EMI host communication
+ * or logging of EMI host communication? We don't observe
+ * this ISR so Host is not writing to MCHP_EMI_H2E_MBX(0).
+ */
void emi0_interrupt(void)
{
uint8_t h2e;
h2e = MCHP_EMI_H2E_MBX(0);
CPRINTS("LPC Host 0x%02x -> EMI0 H2E(0)", h2e);
- trace1(0, LPC, 0, "EMI0 H2E = 0x%02x", h2e);
port_80_write(h2e);
}
DECLARE_IRQ(MCHP_IRQ_EMI0, emi0_interrupt, 1);
@@ -543,7 +667,8 @@ int port_80_read(void)
* Some chipset's CoreBoot will send read board ID command expecting
* a two byte response.
*/
-static int acpi_ec0_custom(int is_cmd, uint8_t value, uint8_t *resultptr)
+static int acpi_ec0_custom(int is_cmd, uint8_t value,
+ uint8_t *resultptr)
{
int rval;
@@ -556,21 +681,18 @@ static int acpi_ec0_custom(int is_cmd, uint8_t value, uint8_t *resultptr)
MCHP_ACPI_EC_OBE_GIRQ_BIT(0);
/* Write two bytes sequence 0xC2, 0x04 to Host */
if (MCHP_ACPI_EC_BYTE_CTL(0) & 0x01) {
- trace0(0, LPC, 0,
- "AEC0 ISR: Cmd 0x0d 4-byte mode. Result=0x04c2");
/* Host enabled 4-byte mode */
- MCHP_ACPI_EC_EC2OS(0, 0) = 0x02; /* was 0xc2 */
+ MCHP_ACPI_EC_EC2OS(0, 0) = 0x02;
MCHP_ACPI_EC_EC2OS(0, 1) = 0x04;
MCHP_ACPI_EC_EC2OS(0, 2) = 0x00;
- MCHP_ACPI_EC_EC2OS(0, 3) = 0x00; /* OBF is set */
+ /* Sets OBF */
+ MCHP_ACPI_EC_EC2OS(0, 3) = 0x00;
} else {
- trace0(0, LPC, 0,
- "AEC0 ISR: Cmd 0x0d 1-byte mode. Result=0xc2,0x04");
/* single byte mode */
- *resultptr = 0x02; /* was 0xc2 */
+ *resultptr = 0x02;
custom_acpi_ec2os_cnt = 1;
custom_apci_ec2os[0] = 0x04;
- MCHP_ACPI_EC_EC2OS(0, 0) = 0x02; /* was 0xc2 */
+ MCHP_ACPI_EC_EC2OS(0, 0) = 0x02;
MCHP_INT_ENABLE(MCHP_ACPI_EC_GIRQ) =
MCHP_ACPI_EC_OBE_GIRQ_BIT(0);
task_enable_irq(MCHP_IRQ_ACPIEC0_OBE);
@@ -597,11 +719,6 @@ void acpi_0_interrupt(void)
/* Read command/data; this clears the FRMH bit. */
value = MCHP_ACPI_EC_OS2EC(0, 0);
- /* CPRINTS("ACPI EC0 ISR sts=0x%02x OS2EC=0x%02x ",is_cmd,value); */
- trace3(0, LPC, 0,
- "AEC0 ISR: sts=0x%02x O2SEC=0x%02x byte_ctrl=0x%02x",
- is_cmd, value, result);
-
is_cmd &= EC_LPC_STATUS_LAST_CMD;
/* Handle whatever this was. */
@@ -620,8 +737,8 @@ void acpi_0_interrupt(void)
MCHP_ACPI_EC_IBF_GIRQ_BIT(0);
/*
- * ACPI 5.0-12.6.1: Generate SCI for Input Buffer Empty / Output Buffer
- * Full condition on the kernel channel.
+ * ACPI 5.0-12.6.1: Generate SCI for Input Buffer Empty /
+ * Output Buffer Full condition on the kernel channel/
*/
lpc_generate_sci();
}
@@ -642,17 +759,10 @@ void acpi_0_obe_isr(void)
sts = MCHP_ACPI_EC_STATUS(0);
data = MCHP_ACPI_EC_BYTE_CTL(0);
- trace3(0, LPC, 0,
- "AEC0 OBE ISR: sts=0x%02x bytectrl=0x%02x ec2os_cnt=0x%02x",
- sts, data, custom_acpi_ec2os_cnt);
-
data = sts;
if (custom_acpi_ec2os_cnt) {
custom_acpi_ec2os_cnt--;
data = custom_apci_ec2os[custom_acpi_ec2os_cnt];
- trace1(0, LPC, 0,
- "AEC0 OBE ISR: write EC2OS(0,0)=0x%02x", data);
- MCHP_ACPI_EC_EC2OS(0, 0) = data;
}
if (custom_acpi_ec2os_cnt == 0) { /* was last byte? */
@@ -667,13 +777,8 @@ DECLARE_IRQ(MCHP_IRQ_ACPIEC0_OBE, acpi_0_obe_isr, 1);
void acpi_1_interrupt(void)
{
- const struct ec_host_request *r;
-
uint8_t st = MCHP_ACPI_EC_STATUS(1);
- CPRINTS("ACPI EC1 ISR: sts=0x%02x", st);
- trace1(0, LPC, 0, "ACPI EC1 ISR: sts=0x%02x", st);
-
if (!(st & EC_LPC_STATUS_FROM_HOST) ||
!(st & EC_LPC_STATUS_LAST_CMD))
return;
@@ -686,49 +791,40 @@ void acpi_1_interrupt(void)
* the status byte.
*/
host_cmd_args.command = MCHP_ACPI_EC_OS2EC(1, 0);
- CPRINTS("ACPI EC1 ISR: OS2EC0=0x%02x", host_cmd_args.command);
- trace1(0, LPC, 0,
- "ACPI EC1 ISR OS2EC[0]=0x%02x", host_cmd_args.command);
host_cmd_args.result = EC_RES_SUCCESS;
host_cmd_args.send_response = lpc_send_response;
host_cmd_flags = lpc_host_args->flags;
-
+
/* We only support new style command (v3) now */
if (host_cmd_args.command == EC_COMMAND_PROTOCOL_3) {
lpc_packet.send_response = lpc_send_response_packet;
- lpc_packet.request = (const void *)lpc_get_hostcmd_data_range();
+ lpc_packet.request =
+ (const void *)lpc_get_hostcmd_data_range();
lpc_packet.request_temp = params_copy;
lpc_packet.request_max = sizeof(params_copy);
- /* Don't know the request size so pass in the entire buffer */
+ /* Don't know the request size so
+ * pass in the entire buffer
+ */
lpc_packet.request_size = EC_LPC_HOST_PACKET_SIZE;
- lpc_packet.response = (void *)lpc_get_hostcmd_data_range();
+ lpc_packet.response =
+ (void *)lpc_get_hostcmd_data_range();
lpc_packet.response_max = EC_LPC_HOST_PACKET_SIZE;
lpc_packet.response_size = 0;
lpc_packet.driver_result = EC_RES_SUCCESS;
- r = lpc_packet.request;
- CPRINTS("ACPI EC1 Packet Command=0x%04x", r->command);
- trace1(0, LPC, 0,
- "ACPI EC1 ISR: Packet Cmd = 0x%04x", r->command);
-
host_packet_receive(&lpc_packet);
} else {
- CPRINTS("ACPI EC1 ISR: Invalid protocol");
- trace0(0, LPC, 0, "ACPI EC1 ISR: Invalid protocol");
/* Old style command unsupported */
host_cmd_args.result = EC_RES_INVALID_COMMAND;
/* Hand off to host command handler */
host_command_received(&host_cmd_args);
}
-
- CPRINTS("ACPI EC1 ISR: Exit");
- trace0(0, LPC, 0, "ACPI EC1 ISR: Exit");
}
DECLARE_IRQ(MCHP_IRQ_ACPIEC1_IBF, acpi_1_interrupt, 1);
@@ -749,10 +845,11 @@ void kb_ibf_interrupt(void)
DECLARE_IRQ(MCHP_IRQ_8042EM_IBF, kb_ibf_interrupt, 1);
/*
- * Interrupt generated when Host reads data byte from 8042EM output buffer.
- * The 8042EM STATUS.OBF bit will clear when the Host reads the data and
- * assert its OBE signal to interrupt aggregator.
- * Clear aggregator 8042EM OBE R/WC status bit before invoking task.
+ * Interrupt generated when Host reads data byte from 8042EM
+ * output buffer. The 8042EM STATUS.OBF bit will clear when the
+ * Host reads the data and assert its OBE signal to interrupt
+ * aggregator. Clear aggregator 8042EM OBE R/WC status bit before
+ * invoking task.
*/
void kb_obe_interrupt(void)
{
@@ -763,8 +860,9 @@ DECLARE_IRQ(MCHP_IRQ_8042EM_OBE, kb_obe_interrupt, 1);
#endif
/*
- * Bit 0 of 8042EM STATUS register is OBF meaning EC has written data
- * to EC2HOST data register. OBF is cleared when the host reads the data.
+ * Bit 0 of 8042EM STATUS register is OBF meaning EC has written
+ * data to EC2HOST data register. OBF is cleared when the host
+ * reads the data.
*/
int lpc_keyboard_has_char(void)
{
@@ -811,6 +909,15 @@ void lpc_clear_acpi_status_mask(uint8_t mask)
MCHP_ACPI_EC_STATUS(0) &= ~mask;
}
+/*
+ * Read hardware to determine state of platform reset signal.
+ * LPC issue: Observed APL chipset changing LRESET# while LPC
+ * clock is not running. This violates original LPC specification.
+ * Unable to find information in APL chipset documentation
+ * stating APL can change LRESET# with LPC clock not running.
+ * Could this be a CoreBoot issue during CB LPC configuration?
+ * We work-around this issue by reading the GPIO state.
+ */
int lpc_get_pltrst_asserted(void)
{
#ifdef CONFIG_HOSTCMD_ESPI
@@ -818,11 +925,17 @@ int lpc_get_pltrst_asserted(void)
* eSPI PLTRST# a VWire or side-band signal
* Controlled by CONFIG_HOSTCMD_ESPI_PLTRST_IS_VWIRE
*/
- return espi_vw_get_wire(VW_PLTRST_L);
+ return !espi_vw_get_wire(VW_PLTRST_L);
#else
/* returns 1 if LRESET# pin is asserted(low) else 0 */
+#ifdef CONFIG_CHIPSET_APL_GLK
+ /* Use GPIO */
+ return !gpio_get_level(GPIO_PCH_PLTRST_L);
+#else
+ /* assumes LPC clock is running when host changes LRESET# */
return (MCHP_LPC_BUS_MONITOR & (1<<1)) ? 1 : 0;
#endif
+#endif
}
/* Enable LPC ACPI-EC0 interrupts */
@@ -850,8 +963,7 @@ static int lpc_get_protocol_info(struct host_cmd_handler_args *args)
{
struct ec_response_get_protocol_info *r = args->response;
- CPRINTS("MEC1701 Handler EC_CMD_GET_PROTOCOL_INFO");
- trace0(0, LPC, 0, "Handler EC_CMD_GET_PROTOCOL_INFO");
+ CPUTS("MEC1701 Handler EC_CMD_GET_PROTOCOL_INFO");
memset(r, 0, sizeof(*r));
r->protocol_versions = (1 << 3);
@@ -866,3 +978,24 @@ static int lpc_get_protocol_info(struct host_cmd_handler_args *args)
DECLARE_HOST_COMMAND(EC_CMD_GET_PROTOCOL_INFO,
lpc_get_protocol_info,
EC_VER_MASK(0));
+
+#ifdef CONFIG_MCHP_DEBUG_LPC
+static int command_lpc(int argc, char **argv)
+{
+ if (argc == 1)
+ return EC_ERROR_PARAM1;
+
+ if (!strcasecmp(argv[1], "sci"))
+ lpc_generate_sci();
+ else if (!strcasecmp(argv[1], "smi"))
+ lpc_generate_smi();
+ else if (!strcasecmp(argv[1], "wake"))
+ lpc_update_wake(-1);
+ else
+ return EC_ERROR_PARAM1;
+ return EC_SUCCESS;
+}
+DECLARE_CONSOLE_COMMAND(lpc, command_lpc, "[sci|smi|wake]",
+ "Trigger SCI/SMI");
+#endif
+
diff --git a/chip/mchp/lpc_chip.h b/chip/mchp/lpc_chip.h
index 8d4caa3a7c..dcb5577fc1 100644
--- a/chip/mchp/lpc_chip.h
+++ b/chip/mchp/lpc_chip.h
@@ -12,6 +12,9 @@
#include "espi.h"
+#define MCHP_HOST_IF_LPC (0)
+#define MCHP_HOST_IF_ESPI (1)
+
/* eSPI Initialization functions */
void espi_init(void);
@@ -32,8 +35,15 @@ void lpcrst_interrupt(enum gpio_signal signal);
void lpc_set_init_done(int val);
-uint32_t lpc_mem_mapped_addr(void);
-
void lpc_mem_mapped_init(void);
+#ifndef CONFIG_HOSTCMD_ESPI
+void lpcrst_interrupt(enum gpio_signal signal);
+#endif
+
+void chip_acpi_ec_config(int instance, uint32_t io_base, uint8_t mask);
+void chip_8042_config(uint32_t io_base);
+void chip_emi0_config(uint32_t io_base);
+void chip_port80_config(uint32_t io_base);
+
#endif /* __CROS_EC_LPC_CHIP_H */