mirror of
https://github.com/Telecominfraproject/OpenCellular.git
synced 2025-12-29 01:50:53 +00:00
Host command interface has only one slot now
Now that ACPI events are handled directly in the LPC interrupt handler, we can simplify the host event code. BUG=chrome-os-partner:11240 TEST=boot system; should boot close lid; should send SMI and suspend system Change-Id: I8c73ea31a66e94310e4460a008635a103220413e Signed-off-by: Randall Spangler <rspangler@chromium.org> Reviewed-on: https://gerrit.chromium.org/gerrit/27100 Reviewed-by: Bill Richardson <wfrichar@chromium.org>
This commit is contained in:
@@ -43,7 +43,7 @@
|
||||
/* TODO: these should really only be used inside lpc.c; once they are, remove
|
||||
* from board header files. */
|
||||
/* LPC channels */
|
||||
#define LPC_CH_KERNEL 0 /* Kernel commands */
|
||||
#define LPC_CH_ACPI 0 /* ACPI commands */
|
||||
#define LPC_CH_PORT80 1 /* Port 80 debug output */
|
||||
#define LPC_CH_CMD_DATA 2 /* Data for kernel/user-mode commands */
|
||||
#define LPC_CH_KEYBOARD 3 /* 8042 keyboard emulation */
|
||||
@@ -51,15 +51,15 @@
|
||||
#define LPC_CH_MEMMAP 5 /* Data for kernel/user-mode commands */
|
||||
#define LPC_CH_COMX 7 /* UART emulation */
|
||||
/* LPC pool offsets */
|
||||
#define LPC_POOL_OFFS_KERNEL 0 /* Kernel commands - 0=in, 1=out */
|
||||
#define LPC_POOL_OFFS_ACPI 0 /* ACPI commands - 0=in, 1=out */
|
||||
#define LPC_POOL_OFFS_PORT80 4 /* Port 80 - 4=in, 5=out */
|
||||
#define LPC_POOL_OFFS_COMX 8 /* UART emulation range - 8-15 */
|
||||
#define LPC_POOL_OFFS_KEYBOARD 16 /* Keyboard - 16=in, 17=out */
|
||||
#define LPC_POOL_OFFS_USER 20 /* User commands - 20=in, 21=out */
|
||||
#define LPC_POOL_OFFS_CMD_DATA 512 /* Data range for commands - 512-767 */
|
||||
#define LPC_POOL_OFFS_MEMMAP 768 /* Data range for commands - 768-1023 */
|
||||
#define LPC_POOL_OFFS_CMD_DATA 512 /* Data range for user commands - 512-639 */
|
||||
#define LPC_POOL_OFFS_MEMMAP 768 /* Memory-mapped data - 768-1023 */
|
||||
/* LPC pool data pointers */
|
||||
#define LPC_POOL_KERNEL (LM4_LPC_LPCPOOL + LPC_POOL_OFFS_KERNEL)
|
||||
#define LPC_POOL_ACPI (LM4_LPC_LPCPOOL + LPC_POOL_OFFS_ACPI)
|
||||
#define LPC_POOL_PORT80 (LM4_LPC_LPCPOOL + LPC_POOL_OFFS_PORT80)
|
||||
#define LPC_POOL_COMX (LM4_LPC_LPCPOOL + LPC_POOL_OFFS_COMX)
|
||||
#define LPC_POOL_KEYBOARD (LM4_LPC_LPCPOOL + LPC_POOL_OFFS_KEYBOARD)
|
||||
|
||||
173
chip/lm4/lpc.c
173
chip/lm4/lpc.c
@@ -5,14 +5,14 @@
|
||||
|
||||
/* LPC module for Chrome EC */
|
||||
|
||||
#include "board.h"
|
||||
#include "common.h"
|
||||
#include "console.h"
|
||||
#include "ec_commands.h"
|
||||
#include "gpio.h"
|
||||
#include "hooks.h"
|
||||
#include "host_command.h"
|
||||
#include "i8042.h"
|
||||
#include "lpc.h"
|
||||
#include "ec_commands.h"
|
||||
#include "port80.h"
|
||||
#include "registers.h"
|
||||
#include "system.h"
|
||||
@@ -114,9 +114,9 @@ static void lpc_generate_sci(void)
|
||||
}
|
||||
|
||||
|
||||
uint8_t *host_get_buffer(int slot)
|
||||
uint8_t *host_get_buffer(void)
|
||||
{
|
||||
return (uint8_t *)LPC_POOL_CMD_DATA + EC_PARAM_SIZE * slot;
|
||||
return (uint8_t *)LPC_POOL_CMD_DATA;
|
||||
}
|
||||
|
||||
|
||||
@@ -125,36 +125,9 @@ uint8_t *lpc_get_memmap_range(void)
|
||||
return (uint8_t *)LPC_POOL_MEMMAP;
|
||||
}
|
||||
|
||||
|
||||
static void send_result(int slot, enum ec_status result)
|
||||
void host_send_response(enum ec_status result, const uint8_t *data, int size)
|
||||
{
|
||||
int ch = slot ? LPC_CH_USER : LPC_CH_KERNEL;
|
||||
|
||||
/* Write result to the data byte. This sets the TOH bit in the
|
||||
* status byte and triggers an IRQ on the host so the host can read
|
||||
* the result. */
|
||||
/* TODO: (crosbug.com/p/7496) or it would, if we actually set up host
|
||||
* IRQs */
|
||||
if (slot)
|
||||
LPC_POOL_USER[1] = result;
|
||||
else
|
||||
LPC_POOL_KERNEL[1] = result;
|
||||
|
||||
/* Clear the busy bit */
|
||||
task_disable_irq(LM4_IRQ_LPC);
|
||||
LM4_LPC_ST(ch) &= ~(1 << 12);
|
||||
task_enable_irq(LM4_IRQ_LPC);
|
||||
|
||||
/* ACPI 5.0-12.6.1: Generate SCI for Output Buffer Full
|
||||
* condition on the kernel channel. */
|
||||
if (ch == LPC_CH_KERNEL)
|
||||
lpc_generate_sci();
|
||||
}
|
||||
|
||||
void host_send_response(int slot, enum ec_status result, const uint8_t *data,
|
||||
int size)
|
||||
{
|
||||
uint8_t *out = host_get_buffer(slot);
|
||||
uint8_t *out = host_get_buffer();
|
||||
|
||||
/* Fail if response doesn't fit in the param buffer */
|
||||
if (size < 0 || size > EC_PARAM_SIZE)
|
||||
@@ -162,17 +135,32 @@ void host_send_response(int slot, enum ec_status result, const uint8_t *data,
|
||||
else if (data != out)
|
||||
memcpy(out, data, size);
|
||||
|
||||
send_result(slot, result);
|
||||
/*
|
||||
* Write result to the data byte. This sets the TOH bit in the
|
||||
* status byte and triggers an IRQ on the host so the host can read
|
||||
* the result.
|
||||
*
|
||||
* TODO: (crosbug.com/p/7496) or it would, if we actually set up host
|
||||
* IRQs
|
||||
*/
|
||||
LPC_POOL_USER[1] = result;
|
||||
|
||||
/* Clear the busy bit */
|
||||
task_disable_irq(LM4_IRQ_LPC);
|
||||
LM4_LPC_ST(LPC_CH_USER) &= ~(1 << 12);
|
||||
task_enable_irq(LM4_IRQ_LPC);
|
||||
}
|
||||
|
||||
/* Return true if the TOH is still set */
|
||||
int lpc_keyboard_has_char(void) {
|
||||
int lpc_keyboard_has_char(void)
|
||||
{
|
||||
return (LM4_LPC_ST(LPC_CH_KEYBOARD) & TOH) ? 1 : 0;
|
||||
}
|
||||
|
||||
|
||||
/* Put a char to host buffer and send IRQ if specified. */
|
||||
void lpc_keyboard_put_char(uint8_t chr, int send_irq) {
|
||||
void lpc_keyboard_put_char(uint8_t chr, int send_irq)
|
||||
{
|
||||
LPC_POOL_KEYBOARD[1] = chr;
|
||||
if (send_irq) {
|
||||
lpc_manual_irq(1); /* IRQ#1 */
|
||||
@@ -237,25 +225,18 @@ static void update_host_event_status(void) {
|
||||
|
||||
if (host_events & event_mask[LPC_HOST_EVENT_SMI]) {
|
||||
/* Only generate SMI for first event */
|
||||
if (!(LM4_LPC_ST(LPC_CH_USER) & (1 << 10)) ||
|
||||
!(LM4_LPC_ST(LPC_CH_KERNEL) & (1 << 10)))
|
||||
if (!(LM4_LPC_ST(LPC_CH_ACPI) & (1 << 10)))
|
||||
need_smi = 1;
|
||||
LM4_LPC_ST(LPC_CH_USER) |= (1 << 10);
|
||||
LM4_LPC_ST(LPC_CH_KERNEL) |= (1 << 10);
|
||||
} else {
|
||||
LM4_LPC_ST(LPC_CH_USER) &= ~(1 << 10);
|
||||
LM4_LPC_ST(LPC_CH_KERNEL) &= ~(1 << 10);
|
||||
}
|
||||
LM4_LPC_ST(LPC_CH_ACPI) |= (1 << 10);
|
||||
} else
|
||||
LM4_LPC_ST(LPC_CH_ACPI) &= ~(1 << 10);
|
||||
|
||||
if (host_events & event_mask[LPC_HOST_EVENT_SCI]) {
|
||||
/* Generate SCI for every event */
|
||||
need_sci = 1;
|
||||
LM4_LPC_ST(LPC_CH_USER) |= (1 << 9);
|
||||
LM4_LPC_ST(LPC_CH_KERNEL) |= (1 << 9);
|
||||
} else {
|
||||
LM4_LPC_ST(LPC_CH_USER) &= ~(1 << 9);
|
||||
LM4_LPC_ST(LPC_CH_KERNEL) &= ~(1 << 9);
|
||||
}
|
||||
LM4_LPC_ST(LPC_CH_ACPI) |= (1 << 9);
|
||||
} else
|
||||
LM4_LPC_ST(LPC_CH_ACPI) &= ~(1 << 9);
|
||||
|
||||
/* Copy host events to mapped memory */
|
||||
*mapped_raw_events = host_events;
|
||||
@@ -319,7 +300,7 @@ uint32_t lpc_get_host_event_mask(enum lpc_host_event_type type)
|
||||
}
|
||||
|
||||
|
||||
/* Handle an ACPI command on the kernel channel */
|
||||
/* Handle an ACPI command */
|
||||
static void handle_acpi_command(void)
|
||||
{
|
||||
int cmd;
|
||||
@@ -327,13 +308,13 @@ static void handle_acpi_command(void)
|
||||
int i;
|
||||
|
||||
/* Set the busy bit */
|
||||
LM4_LPC_ST(LPC_CH_KERNEL) |= (1 << 12);
|
||||
LM4_LPC_ST(LPC_CH_ACPI) |= (1 << 12);
|
||||
|
||||
/*
|
||||
* Read the command byte and pass to the host command handler.
|
||||
* This clears the FRMH bit in the status byte.
|
||||
*/
|
||||
cmd = LPC_POOL_KERNEL[0];
|
||||
cmd = LPC_POOL_ACPI[0];
|
||||
|
||||
/* Process the command */
|
||||
switch (cmd) {
|
||||
@@ -353,10 +334,10 @@ static void handle_acpi_command(void)
|
||||
}
|
||||
|
||||
/* Write the response */
|
||||
LPC_POOL_KERNEL[1] = result;
|
||||
LPC_POOL_ACPI[1] = result;
|
||||
|
||||
/* Clear the busy bit */
|
||||
LM4_LPC_ST(LPC_CH_KERNEL) &= ~(1 << 12);
|
||||
LM4_LPC_ST(LPC_CH_ACPI) &= ~(1 << 12);
|
||||
|
||||
/*
|
||||
* ACPI 5.0-12.6.1: Generate SCI for Input Buffer Empty / Output Buffer
|
||||
@@ -375,17 +356,20 @@ static void lpc_interrupt(void)
|
||||
LM4_LPC_LPCIC = mis;
|
||||
|
||||
#ifdef CONFIG_TASK_HOSTCMD
|
||||
/* Handle host kernel/user command writes */
|
||||
if (mis & LM4_LPC_INT_MASK(LPC_CH_KERNEL, 4))
|
||||
/* Handle ACPI command writes */
|
||||
if (mis & LM4_LPC_INT_MASK(LPC_CH_ACPI, 4))
|
||||
handle_acpi_command();
|
||||
|
||||
/* Handle user command writes */
|
||||
if (mis & LM4_LPC_INT_MASK(LPC_CH_USER, 4)) {
|
||||
/* Set the busy bit */
|
||||
LM4_LPC_ST(LPC_CH_USER) |= (1 << 12);
|
||||
|
||||
/* Read the command byte and pass to the host command handler.
|
||||
* This clears the FRMH bit in the status byte. */
|
||||
host_command_received(1, LPC_POOL_USER[0]);
|
||||
/*
|
||||
* Read the command byte and pass to the host command handler.
|
||||
* This clears the FRMH bit in the status byte.
|
||||
*/
|
||||
host_command_received(LPC_POOL_USER[0]);
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -472,35 +456,41 @@ static int lpc_init(void)
|
||||
/* Configure GPIOs */
|
||||
configure_gpio();
|
||||
|
||||
/* Set LPC channel 0 to I/O address 0x62 (data) / 0x66 (command),
|
||||
/*
|
||||
* Set LPC channel 0 to I/O address 0x62 (data) / 0x66 (command),
|
||||
* single endpoint, offset 0 for host command/writes and 1 for EC
|
||||
* data writes, pool bytes 0(data)/1(cmd) */
|
||||
LM4_LPC_ADR(LPC_CH_KERNEL) = EC_LPC_ADDR_KERNEL_DATA;
|
||||
LM4_LPC_CTL(LPC_CH_KERNEL) = (LPC_POOL_OFFS_KERNEL << (5 - 1));
|
||||
* data writes, pool bytes 0(data)/1(cmd)
|
||||
*/
|
||||
LM4_LPC_ADR(LPC_CH_ACPI) = EC_LPC_ADDR_ACPI_DATA;
|
||||
LM4_LPC_CTL(LPC_CH_ACPI) = (LPC_POOL_OFFS_ACPI << (5 - 1));
|
||||
/* Unmask interrupt for host command writes */
|
||||
LM4_LPC_LPCIM |= LM4_LPC_INT_MASK(LPC_CH_KERNEL, 4);
|
||||
LM4_LPC_LPCIM |= LM4_LPC_INT_MASK(LPC_CH_ACPI, 4);
|
||||
|
||||
/* Set LPC channel 1 to I/O address 0x80 (data), single endpoint,
|
||||
* pool bytes 4(data)/5(cmd). */
|
||||
/*
|
||||
* Set LPC channel 1 to I/O address 0x80 (data), single endpoint,
|
||||
* pool bytes 4(data)/5(cmd).
|
||||
*/
|
||||
LM4_LPC_ADR(LPC_CH_PORT80) = 0x80;
|
||||
LM4_LPC_CTL(LPC_CH_PORT80) = (LPC_POOL_OFFS_PORT80 << (5 - 1));
|
||||
/* Unmask interrupt for host data writes */
|
||||
LM4_LPC_LPCIM |= LM4_LPC_INT_MASK(LPC_CH_PORT80, 2);
|
||||
|
||||
|
||||
/* Set LPC channel 2 to I/O address 0x800, range endpoint,
|
||||
* arbitration disabled, pool bytes 512-767. To access this from
|
||||
/*
|
||||
* Set LPC channel 2 to I/O address 0x880, range endpoint,
|
||||
* arbitration disabled, pool bytes 512-639. To access this from
|
||||
* x86, use the following command to set GEN_LPC2:
|
||||
*
|
||||
* pci_write32 0 0x1f 0 0x88 0x007c0801
|
||||
*/
|
||||
LM4_LPC_ADR(LPC_CH_CMD_DATA) = EC_LPC_ADDR_KERNEL_PARAM;
|
||||
LM4_LPC_CTL(LPC_CH_CMD_DATA) = 0x8019 |
|
||||
LM4_LPC_ADR(LPC_CH_CMD_DATA) = EC_LPC_ADDR_USER_PARAM;
|
||||
LM4_LPC_CTL(LPC_CH_CMD_DATA) = 0x8015 |
|
||||
(LPC_POOL_OFFS_CMD_DATA << (5 - 1));
|
||||
|
||||
/* Set LPC channel 3 to I/O address 0x60 (data) / 0x64 (command),
|
||||
/*
|
||||
* Set LPC channel 3 to I/O address 0x60 (data) / 0x64 (command),
|
||||
* single endpoint, offset 0 for host command/writes and 1 for EC
|
||||
* data writes, pool bytes 0(data)/1(cmd) */
|
||||
* data writes, pool bytes 0(data)/1(cmd)
|
||||
*/
|
||||
LM4_LPC_ADR(LPC_CH_KEYBOARD) = 0x60;
|
||||
LM4_LPC_CTL(LPC_CH_KEYBOARD) = (1 << 24/* IRQSEL1 */) |
|
||||
(0 << 18/* IRQEN1 */) | (LPC_POOL_OFFS_KEYBOARD << (5 - 1));
|
||||
@@ -508,15 +498,18 @@ static int lpc_init(void)
|
||||
/* Unmask interrupt for host command/data writes and data reads */
|
||||
LM4_LPC_LPCIM |= LM4_LPC_INT_MASK(LPC_CH_KEYBOARD, 7);
|
||||
|
||||
/* Set LPC channel 4 to I/O address 0x200 (data) / 0x204 (command),
|
||||
/*
|
||||
* Set LPC channel 4 to I/O address 0x200 (data) / 0x204 (command),
|
||||
* single endpoint, offset 0 for host command/writes and 1 for EC
|
||||
* data writes, pool bytes 0(data)/1(cmd) */
|
||||
* data writes, pool bytes 0(data)/1(cmd)
|
||||
*/
|
||||
LM4_LPC_ADR(LPC_CH_USER) = EC_LPC_ADDR_USER_DATA;
|
||||
LM4_LPC_CTL(LPC_CH_USER) = (LPC_POOL_OFFS_USER << (5 - 1));
|
||||
/* Unmask interrupt for host command writes */
|
||||
LM4_LPC_LPCIM |= LM4_LPC_INT_MASK(LPC_CH_USER, 4);
|
||||
|
||||
/* Set LPC channel 5 to I/O address 0x900, range endpoint,
|
||||
/*
|
||||
* Set LPC channel 5 to I/O address 0x900, range endpoint,
|
||||
* arbitration enabled, pool bytes 768-1023. To access this from
|
||||
* x86, use the following command to set GEN_LPC3:
|
||||
*
|
||||
@@ -525,27 +518,35 @@ static int lpc_init(void)
|
||||
LM4_LPC_ADR(LPC_CH_MEMMAP) = EC_LPC_ADDR_MEMMAP;
|
||||
LM4_LPC_CTL(LPC_CH_MEMMAP) = 0x0019 | (LPC_POOL_OFFS_MEMMAP << (5 - 1));
|
||||
|
||||
/* Set LPC channel 7 to COM port I/O address. Note that channel 7
|
||||
* ignores the TYPE bit and is always an 8-byte range. */
|
||||
/*
|
||||
* Set LPC channel 7 to COM port I/O address. Note that channel 7
|
||||
* ignores the TYPE bit and is always an 8-byte range.
|
||||
*/
|
||||
LM4_LPC_ADR(LPC_CH_COMX) = LPC_COMX_ADDR;
|
||||
/* TODO: could configure IRQSELs and set IRQEN2/CX, and then the host
|
||||
* can enable IRQs on its own. */
|
||||
/*
|
||||
* TODO: could configure IRQSELs and set IRQEN2/CX, and then the host
|
||||
* can enable IRQs on its own.
|
||||
*/
|
||||
LM4_LPC_CTL(LPC_CH_COMX) = 0x0004 | (LPC_POOL_OFFS_COMX << (5 - 1));
|
||||
/* Enable COMx emulation for reads and writes. */
|
||||
LM4_LPC_LPCDMACX = 0x00310000;
|
||||
/* Unmask interrupt for host data writes. We don't need interrupts for
|
||||
/*
|
||||
* Unmask interrupt for host data writes. We don't need interrupts for
|
||||
* reads, because there's no flow control in that direction; LPC is
|
||||
* much faster than the UART, and the UART doesn't have anywhere
|
||||
* sensible to buffer input anyway. */
|
||||
* sensible to buffer input anyway.
|
||||
*/
|
||||
LM4_LPC_LPCIM |= LM4_LPC_INT_MASK(LPC_CH_COMX, 2);
|
||||
|
||||
/* Unmaksk LPC bus reset interrupt. This lets us monitor the PCH
|
||||
* PLTRST# signal for debugging. */
|
||||
/*
|
||||
* Unmaksk LPC bus reset interrupt. This lets us monitor the PCH
|
||||
* PLTRST# signal for debugging.
|
||||
*/
|
||||
LM4_LPC_LPCIM |= (1 << 31);
|
||||
|
||||
/* Enable LPC channels */
|
||||
LM4_LPC_LPCCTL = LM4_LPC_SCI_CLK_1 |
|
||||
(1 << LPC_CH_KERNEL) |
|
||||
(1 << LPC_CH_ACPI) |
|
||||
(1 << LPC_CH_PORT80) |
|
||||
(1 << LPC_CH_CMD_DATA) |
|
||||
(1 << LPC_CH_KEYBOARD) |
|
||||
|
||||
@@ -121,13 +121,11 @@ static int i2c_write_raw(int port, void *buf, int len)
|
||||
return len;
|
||||
}
|
||||
|
||||
void host_send_response(int slot, enum ec_status result, const uint8_t *data,
|
||||
int size)
|
||||
void host_send_response(enum ec_status result, const uint8_t *data, int size)
|
||||
{
|
||||
uint8_t *out = host_buffer;
|
||||
int sum, i;
|
||||
|
||||
ASSERT(slot == 0);
|
||||
*out++ = result;
|
||||
for (i = 0, sum = 0; i < size; i++, data++, out++) {
|
||||
if (data != out)
|
||||
@@ -140,9 +138,8 @@ void host_send_response(int slot, enum ec_status result, const uint8_t *data,
|
||||
i2c_write_raw(I2C2, host_buffer, out - host_buffer);
|
||||
}
|
||||
|
||||
uint8_t *host_get_buffer(int slot)
|
||||
uint8_t *host_get_buffer(void)
|
||||
{
|
||||
ASSERT(slot == 0);
|
||||
return host_buffer + 1 /* skip room for error code */;
|
||||
}
|
||||
|
||||
@@ -180,7 +177,7 @@ static void i2c_event_handler(int port)
|
||||
if (port == I2C2) { /* AP is waiting for EC response */
|
||||
if (rx_index) {
|
||||
/* we have an available command : execute it */
|
||||
host_command_received(0, host_buffer[0]);
|
||||
host_command_received(host_buffer[0]);
|
||||
/* reset host buffer after end of transfer */
|
||||
rx_index = 0;
|
||||
} else {
|
||||
|
||||
@@ -5,11 +5,12 @@
|
||||
|
||||
/* Host command module for Chrome EC */
|
||||
|
||||
#include "common.h"
|
||||
#include "console.h"
|
||||
#include "ec_commands.h"
|
||||
#include "host_command.h"
|
||||
#include "link_defs.h"
|
||||
#include "lpc.h"
|
||||
#include "ec_commands.h"
|
||||
#include "system.h"
|
||||
#include "task.h"
|
||||
#include "timer.h"
|
||||
@@ -19,9 +20,9 @@
|
||||
#define CPUTS(outstr) cputs(CC_SYSTEM, outstr)
|
||||
#define CPRINTF(format, args...) cprintf(CC_SYSTEM, format, ## args)
|
||||
|
||||
#define TASK_EVENT_SLOT(n) TASK_EVENT_CUSTOM(1 << n)
|
||||
#define TASK_EVENT_CMD_PENDING TASK_EVENT_CUSTOM(1)
|
||||
|
||||
static int host_command[2];
|
||||
static int pending_cmd;
|
||||
|
||||
#ifndef CONFIG_LPC
|
||||
static uint8_t host_memmap[EC_MEMMAP_SIZE];
|
||||
@@ -36,25 +37,27 @@ uint8_t *host_get_memmap(int offset)
|
||||
#endif
|
||||
}
|
||||
|
||||
void host_command_received(int slot, int command)
|
||||
void host_command_received(int command)
|
||||
{
|
||||
/* TODO: should warn if we already think we're in a command */
|
||||
|
||||
/* If this is the reboot command, reboot immediately. This gives
|
||||
* the host processor a way to unwedge the EC even if it's busy with
|
||||
* some other command. */
|
||||
/*
|
||||
* If this is the reboot command, reboot immediately. This gives the
|
||||
* host processor a way to unwedge the EC even if it's busy with some
|
||||
* other command.
|
||||
*/
|
||||
if (command == EC_CMD_REBOOT) {
|
||||
system_reset(1);
|
||||
/* Reset should never return; if it does, post an error */
|
||||
host_send_response(slot, EC_RES_ERROR, NULL, 0);
|
||||
host_send_response(EC_RES_ERROR, NULL, 0);
|
||||
return;
|
||||
}
|
||||
|
||||
/* Save the command */
|
||||
host_command[slot] = command;
|
||||
pending_cmd = command;
|
||||
|
||||
/* Wake up the task to handle the command for the slot */
|
||||
task_set_event(TASK_ID_HOSTCMD, TASK_EVENT_SLOT(slot), 0);
|
||||
/* Wake up the task to handle the command */
|
||||
task_set_event(TASK_ID_HOSTCMD, TASK_EVENT_CMD_PENDING, 0);
|
||||
}
|
||||
|
||||
|
||||
@@ -146,14 +149,13 @@ static const struct host_command *find_host_command(int command)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
enum ec_status host_command_process(int slot, int command, uint8_t *data,
|
||||
enum ec_status host_command_process(int command, uint8_t *data,
|
||||
int *response_size)
|
||||
{
|
||||
const struct host_command *cmd = find_host_command(command);
|
||||
enum ec_status res = EC_RES_INVALID_COMMAND;
|
||||
|
||||
CPRINTF("[%T hostcmd%d 0x%02x]\n", slot, command);
|
||||
CPRINTF("[%T hostcmd 0x%02x]\n", command);
|
||||
|
||||
*response_size = 0;
|
||||
if (cmd)
|
||||
@@ -162,24 +164,12 @@ enum ec_status host_command_process(int slot, int command, uint8_t *data,
|
||||
return res;
|
||||
}
|
||||
|
||||
/* Handle a host command */
|
||||
static void command_process(int slot)
|
||||
{
|
||||
int size;
|
||||
int res;
|
||||
|
||||
res = host_command_process(slot, host_command[slot],
|
||||
host_get_buffer(slot), &size);
|
||||
|
||||
host_send_response(slot, res, host_get_buffer(slot), size);
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
/* Initialization / task */
|
||||
|
||||
static int host_command_init(void)
|
||||
{
|
||||
host_command[0] = host_command[1] = -1;
|
||||
pending_cmd = -1;
|
||||
host_set_single_event(EC_HOST_EVENT_INTERFACE_READY);
|
||||
CPRINTF("[%T hostcmd init 0x%x]\n", host_get_events());
|
||||
|
||||
@@ -194,9 +184,13 @@ void host_command_task(void)
|
||||
/* wait for the next command event */
|
||||
int evt = task_wait_event(-1);
|
||||
/* process it */
|
||||
if (evt & TASK_EVENT_SLOT(0))
|
||||
command_process(0);
|
||||
if (evt & TASK_EVENT_SLOT(1))
|
||||
command_process(1);
|
||||
if (evt & TASK_EVENT_CMD_PENDING) {
|
||||
int size = 0; /* Default to no response data */
|
||||
int res = host_command_process(pending_cmd,
|
||||
host_get_buffer(),
|
||||
&size);
|
||||
|
||||
host_send_response(res, host_get_buffer(), size);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -782,13 +782,8 @@ int host_command_reboot(uint8_t *data, int *resp_size)
|
||||
/* TODO: (crosbug.com/p/9040) handle EC_REBOOT_FLAG_POWER_ON */
|
||||
|
||||
#ifdef CONFIG_TASK_HOSTCMD
|
||||
#ifdef CONFIG_LPC
|
||||
/* Clean busy bits on host */
|
||||
host_send_response(0, EC_RES_SUCCESS, NULL, 0);
|
||||
host_send_response(1, EC_RES_SUCCESS, NULL, 0);
|
||||
#elif defined CONFIG_I2C
|
||||
host_send_response(0, EC_RES_SUCCESS, NULL, 0);
|
||||
#endif
|
||||
host_send_response(EC_RES_SUCCESS, NULL, 0);
|
||||
#endif
|
||||
|
||||
CPUTS("[Executing host reboot command]\n");
|
||||
|
||||
@@ -31,13 +31,12 @@
|
||||
#define EC_PROTO_VERSION 0x00000002
|
||||
|
||||
/* I/O addresses for LPC commands */
|
||||
#define EC_LPC_ADDR_KERNEL_DATA 0x62
|
||||
#define EC_LPC_ADDR_KERNEL_CMD 0x66
|
||||
#define EC_LPC_ADDR_KERNEL_PARAM 0x800
|
||||
#define EC_LPC_ADDR_USER_DATA 0x200
|
||||
#define EC_LPC_ADDR_USER_CMD 0x204
|
||||
#define EC_LPC_ADDR_USER_PARAM 0x880
|
||||
#define EC_PARAM_SIZE 128 /* Size of each param area in bytes */
|
||||
#define EC_LPC_ADDR_ACPI_DATA 0x62
|
||||
#define EC_LPC_ADDR_ACPI_CMD 0x66
|
||||
#define EC_LPC_ADDR_USER_DATA 0x200
|
||||
#define EC_LPC_ADDR_USER_CMD 0x204
|
||||
#define EC_LPC_ADDR_USER_PARAM 0x880
|
||||
#define EC_PARAM_SIZE 128 /* Size of param area in bytes */
|
||||
|
||||
/* EC command register bit functions */
|
||||
#define EC_LPC_CMDR_DATA (1 << 0)
|
||||
|
||||
@@ -35,15 +35,13 @@ uint8_t *host_get_memmap(int offset);
|
||||
/**
|
||||
* Process a host command and return its response
|
||||
*
|
||||
* @param slot is 0 for kernel-originated commands,
|
||||
* 1 for usermode-originated commands.
|
||||
* @param command The command code
|
||||
* @param data Buffer holding the command, and used for the
|
||||
* response payload.
|
||||
* @param response_size Returns the size of the response
|
||||
* @return resulting status
|
||||
*/
|
||||
enum ec_status host_command_process(int slot, int command, uint8_t *data,
|
||||
enum ec_status host_command_process(int command, uint8_t *data,
|
||||
int *response_size);
|
||||
|
||||
/**
|
||||
@@ -77,25 +75,23 @@ void host_clear_events(uint32_t mask);
|
||||
uint32_t host_get_events(void);
|
||||
|
||||
/**
|
||||
* Called by host interface module when a command is written to one of the
|
||||
* command slots (0=kernel, 1=user).
|
||||
* Called by host interface module when a command is received.
|
||||
*/
|
||||
void host_command_received(int slot, int command);
|
||||
void host_command_received(int command);
|
||||
|
||||
/* Send a successful result code along with response data to a host command.
|
||||
* <slot> is 0 for kernel-originated commands,
|
||||
* 1 for usermode-originated commands.
|
||||
* <result> is the result code for the command (EC_RES_...)
|
||||
* <data> is the buffer with the response payload.
|
||||
* <size> is the size of the response buffer. */
|
||||
void host_send_response(int slot, enum ec_status result, const uint8_t *data,
|
||||
int size);
|
||||
/**
|
||||
* Send a successful result code along with response data to a host command.
|
||||
*
|
||||
* @param result Result code for the command (EC_RES_...)
|
||||
* @param data Buffer with the response payload.
|
||||
* @param size Size of the response buffer.
|
||||
*/
|
||||
void host_send_response(enum ec_status result, const uint8_t *data, int size);
|
||||
|
||||
/* Return a pointer to the host command data buffer. This buffer must
|
||||
* only be accessed between a notification to host_command_received()
|
||||
* and a subsequent call to lpc_SendHostResponse(). <slot> is 0 for
|
||||
* kernel-originated commands, 1 for usermode-originated commands. */
|
||||
uint8_t *host_get_buffer(int slot);
|
||||
* and a subsequent call to lpc_SendHostResponse(). */
|
||||
uint8_t *host_get_buffer(void);
|
||||
|
||||
/* Register a host command handler */
|
||||
#define DECLARE_HOST_COMMAND(command, routine) \
|
||||
|
||||
Reference in New Issue
Block a user