summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRandall Spangler <rspangler@chromium.org>2012-07-12 14:26:20 -0700
committerRandall Spangler <rspangler@chromium.org>2012-07-12 18:22:24 -0700
commit7946a3eb3d982cd489c35f9cfb16f3e61a27d197 (patch)
treea064fe2ae64ea57a376192ff964355d67f1ebd5a
parent89049421a6f2681f517373338a0f601beae7c737 (diff)
downloadchrome-ec-7946a3eb3d982cd489c35f9cfb16f3e61a27d197.tar.gz
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
-rw-r--r--chip/lm4/lpc.c49
-rw-r--r--common/console_output.c1
-rw-r--r--common/host_event_commands.c50
-rw-r--r--include/console.h1
-rw-r--r--include/lpc.h26
5 files changed, 65 insertions, 62 deletions
diff --git a/chip/lm4/lpc.c b/chip/lm4/lpc.c
index 993208679d..597eb80f71 100644
--- a/chip/lm4/lpc.c
+++ b/chip/lm4/lpc.c
@@ -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)
-{
- if ((host_events & mask) == mask)
- return;
-
- host_events |= mask;
- CPRINTF("[%T event set 0x%08x -> %08x]\n", mask, host_events);
- 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)
+void lpc_set_host_event_state(uint32_t mask)
{
- return host_events;
+ if (mask != host_events) {
+ host_events = mask;
+ update_host_event_status();
+ }
}
-
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;
}
diff --git a/common/console_output.c b/common/console_output.c
index e9f7bf0d97..e3334ee20d 100644
--- a/common/console_output.c
+++ b/common/console_output.c
@@ -22,6 +22,7 @@ static const char *channel_names[CC_CHANNEL_COUNT] = {
"charger",
"chipset",
"dma",
+ "events",
"gpio",
"hostcmd",
"i2c",
diff --git a/common/host_event_commands.c b/common/host_event_commands.c
index b4a161068a..670212c430 100644
--- a/common/host_event_commands.c
+++ b/common/host_event_commands.c
@@ -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.
+ *
+ * The primary copy is mirrored in mapped memory and used to trigger interrupts
+ * on the host via ACPI/SCI/SMI/GPIO.
*
- * This is separate from the main copy, which affects ACPI/SCI/SMI/wake.
+ * 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. */
+ * 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);
}
diff --git a/include/console.h b/include/console.h
index 37d44bfc55..66bc5ba8e3 100644
--- a/include/console.h
+++ b/include/console.h
@@ -33,6 +33,7 @@ enum console_channel {
CC_CHARGER,
CC_CHIPSET,
CC_DMA,
+ CC_EVENTS,
CC_GPIO,
CC_HOSTCMD,
CC_I2C,
diff --git a/include/lpc.h b/include/lpc.h
index e9f5cad690..8c33b401b2 100644
--- a/include/lpc.h
+++ b/include/lpc.h
@@ -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);