summaryrefslogtreecommitdiff
path: root/chip/it83xx/lpc.c
diff options
context:
space:
mode:
Diffstat (limited to 'chip/it83xx/lpc.c')
-rw-r--r--chip/it83xx/lpc.c770
1 files changed, 0 insertions, 770 deletions
diff --git a/chip/it83xx/lpc.c b/chip/it83xx/lpc.c
deleted file mode 100644
index 867d9e024f..0000000000
--- a/chip/it83xx/lpc.c
+++ /dev/null
@@ -1,770 +0,0 @@
-/* Copyright 2014 The Chromium OS Authors. All rights reserved.
- * Use of this source code is governed by a BSD-style license that can be
- * found in the LICENSE file.
- */
-
-/* LPC module for Chrome EC */
-
-#include "acpi.h"
-#include "chipset.h"
-#include "clock.h"
-#include "common.h"
-#include "console.h"
-#include "ec2i_chip.h"
-#include "espi.h"
-#include "gpio.h"
-#include "hooks.h"
-#include "host_command.h"
-#include "intc.h"
-#include "irq_chip.h"
-#include "keyboard_protocol.h"
-#include "lpc.h"
-#include "port80.h"
-#include "pwm.h"
-#include "registers.h"
-#include "system.h"
-#include "task.h"
-#include "timer.h"
-#include "uart.h"
-#include "util.h"
-
-/* Console output macros */
-#define CPUTS(outstr) cputs(CC_LPC, outstr)
-#define CPRINTS(format, args...) cprints(CC_LPC, format, ## args)
-
-/* LPC PM channels */
-enum lpc_pm_ch {
- LPC_PM1 = 0,
- LPC_PM2,
- LPC_PM3,
- LPC_PM4,
- LPC_PM5,
-};
-
-enum pm_ctrl_mask {
- /* Input Buffer Full Interrupt Enable. */
- PM_CTRL_IBFIE = 0x01,
- /* Output Buffer Empty Interrupt Enable. */
- PM_CTRL_OBEIE = 0x02,
-};
-
-#define LPC_ACPI_CMD LPC_PM1 /* ACPI commands 62h/66h port */
-#define LPC_HOST_CMD LPC_PM2 /* Host commands 200h/204h port */
-#define LPC_HOST_PORT_80H LPC_PM3 /* Host 80h port */
-
-static uint8_t acpi_ec_memmap[EC_MEMMAP_SIZE]
- __attribute__((section(".h2ram.pool.acpiec")));
-static uint8_t host_cmd_memmap[256]
- __attribute__((section(".h2ram.pool.hostcmd")));
-
-static struct host_packet lpc_packet;
-static struct host_cmd_handler_args host_cmd_args;
-static uint8_t host_cmd_flags; /* Flags from host command */
-
-/* Params must be 32-bit aligned */
-static uint8_t params_copy[EC_LPC_HOST_PACKET_SIZE] __aligned(4);
-static int init_done;
-static int p80l_index;
-
-static struct ec_lpc_host_args * const lpc_host_args =
- (struct ec_lpc_host_args *)host_cmd_memmap;
-
-static void pm_set_ctrl(enum lpc_pm_ch ch, enum pm_ctrl_mask ctrl, int set)
-{
- if (set)
- IT83XX_PMC_PMCTL(ch) |= ctrl;
- else
- IT83XX_PMC_PMCTL(ch) &= ~ctrl;
-}
-
-static void pm_set_status(enum lpc_pm_ch ch, uint8_t status, int set)
-{
- if (set)
- IT83XX_PMC_PMSTS(ch) |= status;
- else
- IT83XX_PMC_PMSTS(ch) &= ~status;
-}
-
-static uint8_t pm_get_status(enum lpc_pm_ch ch)
-{
- return IT83XX_PMC_PMSTS(ch);
-}
-
-static uint8_t pm_get_data_in(enum lpc_pm_ch ch)
-{
- return IT83XX_PMC_PMDI(ch);
-}
-
-static void pm_put_data_out(enum lpc_pm_ch ch, uint8_t out)
-{
- IT83XX_PMC_PMDO(ch) = out;
-}
-
-static void pm_clear_ibf(enum lpc_pm_ch ch)
-{
- /* bit7, write-1 clear IBF */
- IT83XX_PMC_PMIE(ch) |= BIT(7);
-}
-
-#ifdef CONFIG_KEYBOARD_IRQ_GPIO
-static void keyboard_irq_assert(void)
-{
- /*
- * Enforce signal-high for long enough for the signal to be pulled high
- * by the external pullup resistor. This ensures the host will see the
- * following falling edge, regardless of the line state before this
- * function call.
- */
- gpio_set_level(CONFIG_KEYBOARD_IRQ_GPIO, 1);
- udelay(4);
- /* Generate a falling edge */
- gpio_set_level(CONFIG_KEYBOARD_IRQ_GPIO, 0);
- udelay(4);
-
- /* Set signal high, now that we've generated the edge */
- gpio_set_level(CONFIG_KEYBOARD_IRQ_GPIO, 1);
-}
-#endif
-
-/**
- * Generate SMI pulse to the host chipset via GPIO.
- *
- * If the x86 is in S0, SMI# is sampled at 33MHz, so minimum pulse length is
- * 60ns. If the x86 is in S3, SMI# is sampled at 32.768KHz, so we need pulse
- * length >61us. Both are short enough and events are infrequent, so just
- * delay for 65us.
- */
-static void lpc_generate_smi(void)
-{
-#ifdef CONFIG_HOSTCMD_ESPI
- espi_vw_set_wire(VW_SMI_L, 0);
- udelay(65);
- espi_vw_set_wire(VW_SMI_L, 1);
-#else
- gpio_set_level(GPIO_PCH_SMI_L, 0);
- udelay(65);
- gpio_set_level(GPIO_PCH_SMI_L, 1);
-#endif
-}
-
-static void lpc_generate_sci(void)
-{
-#ifdef CONFIG_HOSTCMD_ESPI
- espi_vw_set_wire(VW_SCI_L, 0);
- udelay(65);
- espi_vw_set_wire(VW_SCI_L, 1);
-#else
- gpio_set_level(GPIO_PCH_SCI_L, 0);
- udelay(65);
- gpio_set_level(GPIO_PCH_SCI_L, 1);
-#endif
-}
-
-/**
- * Update the level-sensitive wake signal to the AP.
- *
- * @param wake_events Currently asserted wake events
- */
-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.
- */
- wake_events &= ~EC_HOST_EVENT_MASK(EC_HOST_EVENT_POWER_BUTTON);
-
- /* Signal is asserted low when wake events is non-zero */
- gpio_set_level(GPIO_PCH_WAKE_L, !wake_events);
-}
-
-static void lpc_send_response(struct host_cmd_handler_args *args)
-{
- uint8_t *out;
- int size = args->response_size;
- int csum;
- int i;
-
- /* Ignore in-progress on LPC since interface is synchronous anyway */
- if (args->result == EC_RES_IN_PROGRESS)
- return;
-
- /* Handle negative size */
- if (size < 0) {
- args->result = EC_RES_INVALID_RESPONSE;
- size = 0;
- }
-
- /* New-style response */
- lpc_host_args->flags =
- (host_cmd_flags & ~EC_HOST_ARGS_FLAG_FROM_HOST) |
- EC_HOST_ARGS_FLAG_TO_HOST;
-
- lpc_host_args->data_size = size;
-
- csum = args->command + lpc_host_args->flags +
- lpc_host_args->command_version +
- lpc_host_args->data_size;
-
- for (i = 0, out = (uint8_t *)args->response; i < size; i++, out++)
- csum += *out;
-
- lpc_host_args->checksum = (uint8_t)csum;
-
- /* Fail if response doesn't fit in the param buffer */
- if (size > EC_PROTO2_MAX_PARAM_SIZE)
- args->result = EC_RES_INVALID_RESPONSE;
-
- /* Write result to the data byte. This sets the OBF status bit. */
- pm_put_data_out(LPC_HOST_CMD, args->result);
-
- /* Clear the busy bit, so the host knows the EC is done. */
- pm_set_status(LPC_HOST_CMD, EC_LPC_STATUS_PROCESSING, 0);
-}
-
-void lpc_update_host_event_status(void)
-{
- int need_sci = 0;
- int need_smi = 0;
-
- if (!init_done)
- return;
-
- /* Disable PMC1 interrupt while updating status register */
- task_disable_irq(IT83XX_IRQ_PMC_IN);
-
- if (lpc_get_host_events_by_type(LPC_HOST_EVENT_SMI)) {
- /* Only generate SMI for first event */
- if (!(pm_get_status(LPC_ACPI_CMD) & EC_LPC_STATUS_SMI_PENDING))
- need_smi = 1;
- pm_set_status(LPC_ACPI_CMD, EC_LPC_STATUS_SMI_PENDING, 1);
- } else {
- pm_set_status(LPC_ACPI_CMD, EC_LPC_STATUS_SMI_PENDING, 0);
- }
-
- if (lpc_get_host_events_by_type(LPC_HOST_EVENT_SCI)) {
- /* Generate SCI for every event */
- need_sci = 1;
- pm_set_status(LPC_ACPI_CMD, EC_LPC_STATUS_SCI_PENDING, 1);
- } else {
- pm_set_status(LPC_ACPI_CMD, EC_LPC_STATUS_SCI_PENDING, 0);
- }
-
- /* Copy host events to mapped memory */
- *(host_event_t *)host_get_memmap(EC_MEMMAP_HOST_EVENTS) =
- lpc_get_host_events();
-
- task_enable_irq(IT83XX_IRQ_PMC_IN);
-
- /* Process the wake events. */
- lpc_update_wake(lpc_get_host_events_by_type(LPC_HOST_EVENT_WAKE));
-
- /* Send pulse on SMI signal if needed */
- if (need_smi)
- lpc_generate_smi();
-
- /* ACPI 5.0-12.6.1: Generate SCI for SCI_EVT=1. */
- if (need_sci)
- lpc_generate_sci();
-}
-
-static void lpc_send_response_packet(struct host_packet *pkt)
-{
- /* Ignore in-progress on LPC since interface is synchronous anyway */
- if (pkt->driver_result == EC_RES_IN_PROGRESS)
- return;
-
- /* Write result to the data byte. */
- pm_put_data_out(LPC_HOST_CMD, pkt->driver_result);
-
- /* Clear the busy bit, so the host knows the EC is done. */
- pm_set_status(LPC_HOST_CMD, EC_LPC_STATUS_PROCESSING, 0);
-}
-
-uint8_t *lpc_get_memmap_range(void)
-{
- return (uint8_t *)acpi_ec_memmap;
-}
-
-int lpc_keyboard_has_char(void)
-{
- /* OBE or OBF */
- return IT83XX_KBC_KBHISR & 0x01;
-}
-
-int lpc_keyboard_input_pending(void)
-{
- /* IBE or IBF */
- return IT83XX_KBC_KBHISR & 0x02;
-}
-
-void lpc_keyboard_put_char(uint8_t chr, int send_irq)
-{
- /* Clear programming data bit 7-4 */
- IT83XX_KBC_KBHISR &= 0x0F;
-
- /* keyboard */
- IT83XX_KBC_KBHISR |= 0x10;
-
-#ifdef CONFIG_KEYBOARD_IRQ_GPIO
- task_clear_pending_irq(IT83XX_IRQ_KBC_OUT);
- /* The data output to the KBC Data Output Register. */
- IT83XX_KBC_KBHIKDOR = chr;
- task_enable_irq(IT83XX_IRQ_KBC_OUT);
- if (send_irq)
- keyboard_irq_assert();
-#else
- /*
- * bit0 = 0, The IRQ1 is controlled by the IRQ1B bit in KBIRQR.
- * bit1 = 0, The IRQ12 is controlled by the IRQ12B bit in KBIRQR.
- */
- IT83XX_KBC_KBHICR &= 0x3C;
-
- /*
- * Enable the interrupt to keyboard driver in the host processor
- * via SERIRQ when the output buffer is full.
- */
- if (send_irq)
- IT83XX_KBC_KBHICR |= 0x01;
-
- udelay(16);
-
- task_clear_pending_irq(IT83XX_IRQ_KBC_OUT);
- /* The data output to the KBC Data Output Register. */
- IT83XX_KBC_KBHIKDOR = chr;
- task_enable_irq(IT83XX_IRQ_KBC_OUT);
-#endif
-}
-
-void lpc_keyboard_clear_buffer(void)
-{
- uint32_t int_mask = read_clear_int_mask();
-
- /* bit6, write-1 clear OBF */
- IT83XX_KBC_KBHICR |= BIT(6);
- IT83XX_KBC_KBHICR &= ~BIT(6);
- set_int_mask(int_mask);
-}
-
-void lpc_keyboard_resume_irq(void)
-{
- if (lpc_keyboard_has_char()) {
-#ifdef CONFIG_KEYBOARD_IRQ_GPIO
- keyboard_irq_assert();
-#else
- /* The IRQ1 is controlled by the IRQ1B bit in KBIRQR. */
- IT83XX_KBC_KBHICR &= ~0x01;
-
- /*
- * When the OBFKIE bit in KBC Host Interface Control Register
- * (KBHICR) is 0, the bit directly controls the IRQ1 signal.
- */
- IT83XX_KBC_KBIRQR |= 0x01;
-#endif
-
- task_clear_pending_irq(IT83XX_IRQ_KBC_OUT);
-
- task_enable_irq(IT83XX_IRQ_KBC_OUT);
- }
-}
-
-void lpc_set_acpi_status_mask(uint8_t mask)
-{
- pm_set_status(LPC_ACPI_CMD, mask, 1);
-}
-
-void lpc_clear_acpi_status_mask(uint8_t mask)
-{
- pm_set_status(LPC_ACPI_CMD, mask, 0);
-}
-
-#ifndef CONFIG_HOSTCMD_ESPI
-int lpc_get_pltrst_asserted(void)
-{
- return !gpio_get_level(GPIO_PCH_PLTRST_L);
-}
-#endif
-
-#ifdef HAS_TASK_KEYPROTO
-/* KBC and PMC control modules */
-void lpc_kbc_ibf_interrupt(void)
-{
- if (lpc_keyboard_input_pending()) {
- keyboard_host_write(IT83XX_KBC_KBHIDIR,
- (IT83XX_KBC_KBHISR & 0x08) ? 1 : 0);
- /* bit7, write-1 clear IBF */
- IT83XX_KBC_KBHICR |= BIT(7);
- IT83XX_KBC_KBHICR &= ~BIT(7);
- }
-
- task_clear_pending_irq(IT83XX_IRQ_KBC_IN);
-
- task_wake(TASK_ID_KEYPROTO);
-}
-
-void lpc_kbc_obe_interrupt(void)
-{
- task_disable_irq(IT83XX_IRQ_KBC_OUT);
-
- task_clear_pending_irq(IT83XX_IRQ_KBC_OUT);
-
-#ifndef CONFIG_KEYBOARD_IRQ_GPIO
- if (!(IT83XX_KBC_KBHICR & 0x01)) {
- IT83XX_KBC_KBIRQR &= ~0x01;
-
- IT83XX_KBC_KBHICR |= 0x01;
- }
-#endif
-
- task_wake(TASK_ID_KEYPROTO);
-}
-#endif /* HAS_TASK_KEYPROTO */
-
-void pm1_ibf_interrupt(void)
-{
- int is_cmd;
- uint8_t value, result;
-
- if (pm_get_status(LPC_ACPI_CMD) & EC_LPC_STATUS_FROM_HOST) {
- /* Set the busy bit */
- pm_set_status(LPC_ACPI_CMD, EC_LPC_STATUS_PROCESSING, 1);
-
- /* data from command port or data port */
- is_cmd = pm_get_status(LPC_ACPI_CMD) & EC_LPC_STATUS_LAST_CMD;
-
- /* Get command or data */
- value = pm_get_data_in(LPC_ACPI_CMD);
-
- /* Handle whatever this was. */
- if (acpi_ap_to_ec(is_cmd, value, &result))
- pm_put_data_out(LPC_ACPI_CMD, result);
-
- pm_clear_ibf(LPC_ACPI_CMD);
-
- /* Clear the busy bit */
- pm_set_status(LPC_ACPI_CMD, EC_LPC_STATUS_PROCESSING, 0);
-
- /*
- * ACPI 5.0-12.6.1: Generate SCI for Input Buffer Empty
- * Output Buffer Full condition on the kernel channel.
- */
- lpc_generate_sci();
- }
-
- task_clear_pending_irq(IT83XX_IRQ_PMC_IN);
-}
-
-void pm2_ibf_interrupt(void)
-{
- uint8_t value __attribute__((unused)) = 0;
- uint8_t status;
-
- status = pm_get_status(LPC_HOST_CMD);
- /* IBE */
- if (!(status & EC_LPC_STATUS_FROM_HOST)) {
- task_clear_pending_irq(IT83XX_IRQ_PMC2_IN);
- return;
- }
-
- /* IBF and data port */
- if (!(status & EC_LPC_STATUS_LAST_CMD)) {
- /* R/C IBF*/
- value = pm_get_data_in(LPC_HOST_CMD);
- pm_clear_ibf(LPC_HOST_CMD);
- task_clear_pending_irq(IT83XX_IRQ_PMC2_IN);
- return;
- }
-
- /* Set the busy bit */
- pm_set_status(LPC_HOST_CMD, EC_LPC_STATUS_PROCESSING, 1);
-
- /*
- * Read the command byte. This clears the FRMH bit in
- * the status byte.
- */
- host_cmd_args.command = pm_get_data_in(LPC_HOST_CMD);
-
- host_cmd_args.result = EC_RES_SUCCESS;
- if (host_cmd_args.command != EC_COMMAND_PROTOCOL_3)
- 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 *)host_cmd_memmap;
- 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 */
- lpc_packet.request_size = EC_LPC_HOST_PACKET_SIZE;
-
- lpc_packet.response = (void *)host_cmd_memmap;
- lpc_packet.response_max = EC_LPC_HOST_PACKET_SIZE;
- lpc_packet.response_size = 0;
-
- lpc_packet.driver_result = EC_RES_SUCCESS;
- host_packet_receive(&lpc_packet);
-
- pm_clear_ibf(LPC_HOST_CMD);
- task_clear_pending_irq(IT83XX_IRQ_PMC2_IN);
- return;
- } else {
- /* Old style command, now unsupported */
- host_cmd_args.result = EC_RES_INVALID_COMMAND;
- }
-
- /* Hand off to host command handler */
- host_command_received(&host_cmd_args);
-
- pm_clear_ibf(LPC_HOST_CMD);
- task_clear_pending_irq(IT83XX_IRQ_PMC2_IN);
-}
-
-void pm3_ibf_interrupt(void)
-{
- int new_p80_idx, i;
- enum ec2i_message ec2i_r;
-
- /* set LDN */
- if (ec2i_write(HOST_INDEX_LDN, LDN_RTCT) == EC2I_WRITE_SUCCESS) {
- /* get P80L current index */
- ec2i_r = ec2i_read(HOST_INDEX_DSLDC6);
- /* clear IBF */
- pm_clear_ibf(LPC_HOST_PORT_80H);
- /* read OK */
- if ((ec2i_r & 0xff00) == EC2I_READ_SUCCESS) {
- new_p80_idx = ec2i_r & P80L_BRAM_BANK1_SIZE_MASK;
- for (i = 0; i < (P80L_P80LE - P80L_P80LB + 1); i++) {
- if (++p80l_index > P80L_P80LE)
- p80l_index = P80L_P80LB;
- port_80_write(IT83XX_BRAM_BANK1(p80l_index));
- if (p80l_index == new_p80_idx)
- break;
- }
- }
- } else {
- pm_clear_ibf(LPC_HOST_PORT_80H);
- }
-
- task_clear_pending_irq(IT83XX_IRQ_PMC3_IN);
-}
-
-void pm4_ibf_interrupt(void)
-{
- pm_clear_ibf(LPC_PM4);
- task_clear_pending_irq(IT83XX_IRQ_PMC4_IN);
-}
-
-void pm5_ibf_interrupt(void)
-{
- pm_clear_ibf(LPC_PM5);
- task_clear_pending_irq(IT83XX_IRQ_PMC5_IN);
-}
-
-static void lpc_init(void)
-{
- enum ec2i_message ec2i_r;
-
- /* SPI peripheral interface is disabled */
- IT83XX_GCTRL_SSCR = 0;
- /*
- * DLM 52k~56k size select enable.
- * For mapping LPC I/O cycle 800h ~ 9FFh to DLM 8D800 ~ 8D9FF.
- */
- IT83XX_GCTRL_MCCR2 |= 0x10;
-
- /* The register pair to access PNPCFG is 004Eh and 004Fh */
- IT83XX_GCTRL_BADRSEL = 0x01;
-
- /* Disable KBC IRQ */
- IT83XX_KBC_KBIRQR = 0x00;
-
- /*
- * bit2, Output Buffer Empty CPU Interrupt Enable.
- * bit3, Input Buffer Full CPU Interrupt Enable.
- * bit5, IBF/OBF EC clear mode.
- * 0b: IBF cleared if EC read data register, EC reset, or host reset.
- * OBF cleared if host read data register, or EC reset.
- * 1b: IBF cleared if EC write-1 to bit7 at related registers,
- * EC reset, or host reset.
- * OBF cleared if host read data register, EC write-1 to bit6 at
- * related registers, or EC reset.
- */
- IT83XX_KBC_KBHICR |= 0x2C;
-
- /* PM1 Input Buffer Full Interrupt Enable for 62h/66 port */
- pm_set_ctrl(LPC_ACPI_CMD, PM_CTRL_IBFIE, 1);
-
- /* PM2 Input Buffer Full Interrupt Enable for 200h/204 port */
- pm_set_ctrl(LPC_HOST_CMD, PM_CTRL_IBFIE, 1);
-
- memset(lpc_get_memmap_range(), 0, EC_MEMMAP_SIZE);
- memset(lpc_host_args, 0, sizeof(*lpc_host_args));
-
- /* Host LPC I/O cycle mapping to RAM */
-#ifdef IT83XX_H2RAM_REMAPPING
- /*
- * On it8xxx2 series, host I/O cycles are mapped to the first block
- * (0x80080000~0x80080fff) at default, and it is adjustable.
- * We should set the correct offset depends on the base address of
- * H2RAM section, so EC will be able to receive/handle commands from
- * host.
- */
- IT83XX_GCTRL_H2ROFSR =
- (CONFIG_H2RAM_BASE - CONFIG_RAM_BASE) / CONFIG_H2RAM_SIZE;
-#endif
- /*
- * bit[4], H2RAM through LPC IO cycle.
- * bit[1], H2RAM window 1 enabled.
- * bit[0], H2RAM window 0 enabled.
- */
- IT83XX_SMFI_HRAMWC |= 0x13;
-
- /*
- * bit[7:6]
- * Host RAM Window[x] Read Protect Enable
- * 00b: Disabled
- * 01b: Lower half of RAM window protected
- * 10b: Upper half of RAM window protected
- * 11b: All protected
- *
- * bit[5:4]
- * Host RAM Window[x] Write Protect Enable
- * 00b: Disabled
- * 01b: Lower half of RAM window protected
- * 10b: Upper half of RAM window protected
- * 11b: All protected
- *
- * bit[2:0]
- * Host RAM Window 1 Size (HRAMW1S)
- * 0h: 16 bytes
- * 1h: 32 bytes
- * 2h: 64 bytes
- * 3h: 128 bytes
- * 4h: 256 bytes
- * 5h: 512 bytes
- * 6h: 1024 bytes
- * 7h: 2048 bytes
- */
-
- /* H2RAM Win 0 Base Address 800h allow r/w for host_cmd_memmap */
- IT83XX_SMFI_HRAMW0BA = 0x80;
- IT83XX_SMFI_HRAMW0AAS = 0x04;
-
- /* H2RAM Win 1 Base Address 900h allow r for acpi_ec_memmap */
- IT83XX_SMFI_HRAMW1BA = 0x90;
- IT83XX_SMFI_HRAMW1AAS = 0x34;
-
- /* We support LPC args and version 3 protocol */
- *(lpc_get_memmap_range() + EC_MEMMAP_HOST_CMD_FLAGS) =
- EC_HOST_CMD_FLAG_LPC_ARGS_SUPPORTED |
- EC_HOST_CMD_FLAG_VERSION_3;
-
- /*
- * bit[5], Dedicated interrupt
- * INT3: PMC1 Output Buffer Empty Int
- * INT25: PMC1 Input Buffer Full Int
- * INT26: PMC2 Output Buffer Empty Int
- * INT27: PMC2 Input Buffer Full Int
- */
- IT83XX_PMC_MBXCTRL |= 0x20;
-
- /* PM3 Input Buffer Full Interrupt Enable for 80h port */
- pm_set_ctrl(LPC_HOST_PORT_80H, PM_CTRL_IBFIE, 1);
-
- p80l_index = P80L_P80LC;
- if (ec2i_write(HOST_INDEX_LDN, LDN_RTCT) == EC2I_WRITE_SUCCESS) {
- /* get P80L current index */
- ec2i_r = ec2i_read(HOST_INDEX_DSLDC6);
- /* read OK */
- if ((ec2i_r & 0xff00) == EC2I_READ_SUCCESS)
- p80l_index = ec2i_r & P80L_BRAM_BANK1_SIZE_MASK;
- }
-
- /*
- * bit[7], enable P80L function.
- * bit[6], accept port 80h cycle.
- * bit[1-0], 10b: I2EC is read-only.
- */
- IT83XX_GCTRL_SPCTRL1 |= 0xC2;
-
-#ifndef CONFIG_HOSTCMD_ESPI
- gpio_enable_interrupt(GPIO_PCH_PLTRST_L);
-#endif
-
-#ifdef HAS_TASK_KEYPROTO
- task_clear_pending_irq(IT83XX_IRQ_KBC_OUT);
- task_disable_irq(IT83XX_IRQ_KBC_OUT);
-
- task_clear_pending_irq(IT83XX_IRQ_KBC_IN);
- task_enable_irq(IT83XX_IRQ_KBC_IN);
-#endif
-
- task_clear_pending_irq(IT83XX_IRQ_PMC_IN);
- pm_set_status(LPC_ACPI_CMD, EC_LPC_STATUS_PROCESSING, 0);
- task_enable_irq(IT83XX_IRQ_PMC_IN);
-
- task_clear_pending_irq(IT83XX_IRQ_PMC2_IN);
- pm_set_status(LPC_HOST_CMD, EC_LPC_STATUS_PROCESSING, 0);
- task_enable_irq(IT83XX_IRQ_PMC2_IN);
-
- task_clear_pending_irq(IT83XX_IRQ_PMC3_IN);
- task_enable_irq(IT83XX_IRQ_PMC3_IN);
-
-#ifdef CONFIG_HOSTCMD_ESPI
- espi_init();
-#endif
- /* Sufficiently initialized */
- init_done = 1;
-
- /* Update host events now that we can copy them to memmap */
- lpc_update_host_event_status();
-}
-/*
- * Set prio 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);
-
-#ifndef CONFIG_HOSTCMD_ESPI
-void lpcrst_interrupt(enum gpio_signal signal)
-{
- if (lpc_get_pltrst_asserted())
- /* Store port 80 reset event */
- port_80_write(PORT_80_EVENT_RESET);
-
- CPRINTS("LPC RESET# %sasserted",
- lpc_get_pltrst_asserted() ? "" : "de");
-}
-#endif
-
-/* Enable LPC ACPI-EC interrupts */
-void lpc_enable_acpi_interrupts(void)
-{
- task_enable_irq(IT83XX_IRQ_PMC_IN);
-}
-
-/* Disable LPC ACPI-EC interrupts */
-void lpc_disable_acpi_interrupts(void)
-{
- task_disable_irq(IT83XX_IRQ_PMC_IN);
-}
-
-/* Get protocol information */
-static enum ec_status lpc_get_protocol_info(struct host_cmd_handler_args *args)
-{
- struct ec_response_get_protocol_info *r = args->response;
-
- memset(r, 0, sizeof(*r));
- r->protocol_versions = BIT(3);
- r->max_request_packet_size = EC_LPC_HOST_PACKET_SIZE;
- r->max_response_packet_size = EC_LPC_HOST_PACKET_SIZE;
- r->flags = 0;
-
- args->response_size = sizeof(*r);
-
- return EC_SUCCESS;
-}
-DECLARE_HOST_COMMAND(EC_CMD_GET_PROTOCOL_INFO,
- lpc_get_protocol_info,
- EC_VER_MASK(0));