Simplify host event processing

Now both copies of the event state live in host_event_commands.c, and
lpc / memmap just shadows the main copy.

BUG=chrome-os-partner:11172
TEST=manual

Boot system.  should see events 0x2000, 0x80, 0x08 get set and then cleared.

At U-boot prompt, type on keyboard.  Should set event 0x1000 get set,
but only on the first keypress (because U-boot doesn't consume that
event).

Then from EC console,
hostevent clear 0x1000 -> see event 0x1000 clear
hostevent clear 0x1000 -> no debug output (it's already clear)
hostevent clearb 0x1000 -> see event copy B 0x1000 clear
hostevent clearb 0x1000 -> no debug output (copy B is already clear)

Change-Id: I855c035865649ba1490cd9027157d5bcdcc9895f
Signed-off-by: Randall Spangler <rspangler@chromium.org>
Reviewed-on: https://gerrit.chromium.org/gerrit/27321
This commit is contained in:
Randall Spangler
2012-07-12 14:26:20 -07:00
parent 89049421a6
commit 7946a3eb3d
5 changed files with 65 additions and 62 deletions

View File

@@ -248,15 +248,13 @@ void lpc_comx_put_char(int c)
}
/* Update the host event status.
* Sends a pulse if masked event status becomes non-zero:
* SMI pulse via EC_SMIn GPIO
* SCI pulse via LPC0SCI
/**
* Update the host event status. Sends a pulse if masked event status becomes
* non-zero:
* - SMI pulse via EC_SMIn GPIO
* - SCI pulse via LPC0SCI
*/
static void update_host_event_status(void) {
uint32_t *mapped_raw_events =
(uint32_t *)host_get_memmap(EC_MEMMAP_HOST_EVENTS);
int need_sci = 0;
int need_smi = 0;
@@ -279,7 +277,7 @@ static void update_host_event_status(void) {
LM4_LPC_ST(LPC_CH_ACPI) &= ~LPC_STATUS_MASK_SCI;
/* Copy host events to mapped memory */
*mapped_raw_events = host_events;
*(uint32_t *)host_get_memmap(EC_MEMMAP_HOST_EVENTS) = host_events;
task_enable_irq(LM4_IRQ_LPC);
@@ -298,48 +296,25 @@ static void update_host_event_status(void) {
lpc_generate_sci();
}
void lpc_set_host_events(uint32_t mask)
void lpc_set_host_event_state(uint32_t mask)
{
if ((host_events & mask) == mask)
return;
host_events |= mask;
CPRINTF("[%T event set 0x%08x -> %08x]\n", mask, host_events);
update_host_event_status();
if (mask != host_events) {
host_events = mask;
update_host_event_status();
}
}
void lpc_clear_host_events(uint32_t mask)
{
if (!(host_events & mask))
return;
host_events &= ~mask;
CPRINTF("[%T event clear 0x%08x -> %08x]\n", mask, host_events);
update_host_event_status();
}
uint32_t lpc_get_host_events(void)
{
return host_events;
}
void lpc_set_host_event_mask(enum lpc_host_event_type type, uint32_t mask)
{
event_mask[type] = mask;
update_host_event_status();
}
uint32_t lpc_get_host_event_mask(enum lpc_host_event_type type)
{
return event_mask[type];
}
/* Handle an ACPI command */
static void handle_acpi_command(void)
{
@@ -361,7 +336,7 @@ static void handle_acpi_command(void)
case EC_CMD_ACPI_QUERY_EVENT:
for (i = 0; i < 32; i++) {
if (host_events & (1 << i)) {
lpc_clear_host_events(1 << i);
host_clear_events(1 << i);
result = i + 1; /* Events are 1-based */
break;
}

View File

@@ -22,6 +22,7 @@ static const char *channel_names[CC_CHANNEL_COUNT] = {
"charger",
"chipset",
"dma",
"events",
"gpio",
"hostcmd",
"i2c",

View File

@@ -12,41 +12,59 @@
#include "lpc.h"
#include "util.h"
/* Copy B of current events mask.
/* Console output macros */
#define CPUTS(outstr) cputs(CC_EVENTS, outstr)
#define CPRINTF(format, args...) cprintf(CC_EVENTS, format, ## args)
/*
* Maintain two copies of the events that are set.
*
* This is separate from the main copy, which affects ACPI/SCI/SMI/wake.
* The primary copy is mirrored in mapped memory and used to trigger interrupts
* on the host via ACPI/SCI/SMI/GPIO.
*
* Setting an event sets both copies. Copies are cleared separately. */
* The secondary (B) copy is used to track events at a non-interrupt level (for
* example, so a user-level process can find out what events have happened
* since the last call, even though a kernel-level process is consuming events
* from the first copy).
*
* Setting an event sets both copies. Copies are cleared separately.
*/
static uint32_t events;
static uint32_t events_copy_b;
uint32_t host_get_events(void)
{
#ifdef CONFIG_LPC
return lpc_get_host_events();
#else
uint32_t *mapped_raw_events =
(uint32_t *)host_get_memmap(EC_MEMMAP_HOST_EVENTS);
return *mapped_raw_events;
#endif
return events;
}
void host_set_events(uint32_t mask)
{
/* Only print if something's about to change */
if ((events & mask) != mask || (events_copy_b & mask) != mask)
CPRINTF("[%T event set 0x%08x]\n", mask);
atomic_or(&events, mask);
atomic_or(&events_copy_b, mask);
#ifdef CONFIG_LPC
lpc_set_host_events(mask);
lpc_set_host_event_state(events);
#else
*(uint32_t *)host_get_memmap(EC_MEMMAP_HOST_EVENTS) |= mask;
*(uint32_t *)host_get_memmap(EC_MEMMAP_HOST_EVENTS) = events;
#endif
}
void host_clear_events(uint32_t mask)
{
/* Only print if something's about to change */
if (events & mask)
CPRINTF("[%T event clear 0x%08x]\n", mask);
atomic_clear(&events, mask);
#ifdef CONFIG_LPC
lpc_clear_host_events(mask);
lpc_set_host_event_state(events);
#else
*(uint32_t *)host_get_memmap(EC_MEMMAP_HOST_EVENTS) &= ~mask;
*(uint32_t *)host_get_memmap(EC_MEMMAP_HOST_EVENTS) = events;
#endif
}
@@ -58,6 +76,10 @@ void host_clear_events(uint32_t mask)
*/
static void host_clear_events_b(uint32_t mask)
{
/* Only print if something's about to change */
if (events_copy_b & mask)
CPRINTF("[%T event clear B 0x%08x]\n", mask);
atomic_clear(&events_copy_b, mask);
}

View File

@@ -33,6 +33,7 @@ enum console_channel {
CC_CHARGER,
CC_CHIPSET,
CC_DMA,
CC_EVENTS,
CC_GPIO,
CC_HOSTCMD,
CC_I2C,

View File

@@ -10,13 +10,16 @@
#include "common.h"
/* Manually generate an IRQ to host.
/*
* Manually generate an IRQ to host.
* Note that the irq_num == 0 would set the AH bit (Active High).
*/
void lpc_manual_irq(int irq_num);
/* Return a pointer to the memory-mapped buffer. This buffer is writable at
* any time, and the host can read it at any time. */
/*
* Return a pointer to the memory-mapped buffer. This buffer is writable at
* any time, and the host can read it at any time.
*/
uint8_t *lpc_get_memmap_range(void);
/* Return true if the TOH is still set */
@@ -40,6 +43,13 @@ int lpc_comx_get_char(void);
/* Put a character to the COMx LPC interface. */
void lpc_comx_put_char(int c);
/*
* Low-level LPC interface for host events.
*
* For use by host_event_commands.c. Other modules should use the methods
* provided in host_command.h.
*/
/* Types of host events */
enum lpc_host_event_type {
LPC_HOST_EVENT_SMI = 0,
@@ -47,14 +57,8 @@ enum lpc_host_event_type {
LPC_HOST_EVENT_WAKE,
};
/* Set one or more SCI/SMI event bits. */
void lpc_set_host_events(uint32_t mask);
/* Clear one or more SCI/SMI event bits. Write 1 to a bit to clear it. */
void lpc_clear_host_events(uint32_t mask);
/* Return the raw SCI/SMI event state. */
uint32_t lpc_get_host_events(void);
/* Set the event state */
void lpc_set_host_event_state(uint32_t mask);
/* Set the event mask for the specified event type. */
void lpc_set_host_event_mask(enum lpc_host_event_type type, uint32_t mask);