summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBill Richardson <wfrichar@chromium.org>2013-12-09 15:54:12 -0800
committerchrome-internal-fetch <chrome-internal-fetch@google.com>2013-12-12 18:21:56 +0000
commite6588c803f93c421970eb7b7220e05074922b096 (patch)
tree4dafad5857709a37b6b26851e6b2de1b935ffe76
parent878f29330b8855a31ffcf6222ef3db2ed2451307 (diff)
downloadchrome-ec-e6588c803f93c421970eb7b7220e05074922b096.tar.gz
Move ACPI stuff out of chip/lm4 and into common
The port 62/66 ACPI commands were implemented in chip/lm4/lpc.c. They should be handled in common instead of being tied to a particular EC. BUG=chrome-os-partner:23774 BRANCH=none TEST=manual read EC_ACPI_MEM_VERSION # iotools io_write8 0x66 0x80; iotools io_write8 0x62 0; iotools io_read8 0x62 0x01 write & read EC_ACPI_MEM_TEST # iotools io_write8 0x66 0x81; iotools io_write8 0x62 1; iotools io_write8 0x62 0xa5 # iotools io_write8 0x66 0x80; iotools io_write8 0x62 1; iotools io_read8 0x62 0xa5 # iotools io_write8 0x66 0x80; iotools io_write8 0x62 2; iotools io_read8 0x62 0x5a # iotools io_write8 0x66 0x81; iotools io_write8 0x62 1; iotools io_write8 0x62 0xbb # iotools io_write8 0x66 0x80; iotools io_write8 0x62 1; iotools io_read8 0x62 0xbb # iotools io_write8 0x66 0x80; iotools io_write8 0x62 2; iotools io_read8 0x62 0x44 read & write EC_ACPI_MEM_KEYBOARD_BACKLIGHT # iotools io_write8 0x66 0x81; iotools io_write8 0x62 3; iotools io_write8 0x62 100 (keyboard lights up) # iotools io_write8 0x66 0x80; iotools io_write8 0x62 3; iotools io_read8 0x62 0x64 # iotools io_write8 0x66 0x81; iotools io_write8 0x62 3; iotools io_write8 0x62 50 (keyboard dimmer) # iotools io_write8 0x66 0x80; iotools io_write8 0x62 3; iotools io_read8 0x62 0x32 # iotools io_write8 0x66 0x81; iotools io_write8 0x62 3; iotools io_write8 0x62 0 (keyboard goes dark) # iotools io_write8 0x66 0x80; iotools io_write8 0x62 3; iotools io_read8 0x62 0x00 read & write EC_ACPI_MEM_FAN_DUTY # iotools io_write8 0x66 0x81; iotools io_write8 0x62 4; iotools io_write8 0x62 100 (fan on full) # iotools io_write8 0x66 0x80; iotools io_write8 0x62 4; iotools io_read8 0x62 0x64 # iotools io_write8 0x66 0x81; iotools io_write8 0x62 4; iotools io_write8 0x62 50 (fan on half speed) # iotools io_write8 0x66 0x80; iotools io_write8 0x62 4; iotools io_read8 0x62 0x32 # iotools io_write8 0x66 0x81; iotools io_write8 0x62 4; iotools io_write8 0x62 0 (fan off) # iotools io_write8 0x66 0x80; iotools io_write8 0x62 4; iotools io_read8 0x62 0x00 # iotools io_write8 0x66 0x81; iotools io_write8 0x62 4; iotools io_write8 0x62 0xff (fan back to EC control) # iotools io_write8 0x66 0x80; iotools io_write8 0x62 4; iotools io_read8 0x62 0xff test EC_CMD_ACPI_QUERY_EVENT # iotools io_write8 0x66 0x84; iotools io_read8 0x62 0x00 On EC console: > hostevent set 0x0f000000 # ectool eventget Current host events: 0x0f000000 # iotools io_write8 0x66 0x84; iotools io_read8 0x62 0x19 # iotools io_write8 0x66 0x84; iotools io_read8 0x62 0x1a # iotools io_write8 0x66 0x84; iotools io_read8 0x62 0x1b # iotools io_write8 0x66 0x84; iotools io_read8 0x62 0x1c # iotools io_write8 0x66 0x84; iotools io_read8 0x62 0x00 # ectool eventget Current host events: 0x00000000 Change-Id: I011a5a2051171ec1d37e55ce03e1ce74b93a7e14 Signed-off-by: Bill Richardson <wfrichar@chromium.org> Reviewed-on: https://chromium-review.googlesource.com/179692
-rw-r--r--chip/lm4/lpc.c128
-rw-r--r--chip/mec1322/lpc.c6
-rw-r--r--common/acpi.c132
-rw-r--r--common/build.mk2
-rw-r--r--include/acpi.h23
-rw-r--r--include/lpc.h5
6 files changed, 190 insertions, 106 deletions
diff --git a/chip/lm4/lpc.c b/chip/lm4/lpc.c
index 0b9ec2771a..f8fd54e55f 100644
--- a/chip/lm4/lpc.c
+++ b/chip/lm4/lpc.c
@@ -5,6 +5,7 @@
/* LPC module for Chrome EC */
+#include "acpi.h"
#include "clock.h"
#include "common.h"
#include "console.h"
@@ -56,11 +57,6 @@
#define LPC_SYSJUMP_TAG 0x4c50 /* "LP" */
-static uint8_t acpi_cmd; /* Last received ACPI command */
-static uint8_t acpi_addr; /* First byte of data after ACPI command */
-static int acpi_data_count; /* Number of data writes after command */
-static uint8_t acpi_mem_test; /* Test byte in ACPI memory space */
-
static uint32_t host_events; /* Currently pending SCI/SMI events */
static uint32_t event_mask[3]; /* Event masks for each type */
static struct host_packet lpc_packet;
@@ -373,6 +369,23 @@ void lpc_set_host_event_state(uint32_t mask)
}
}
+int lpc_query_host_event_state(void)
+{
+ int evt_index = 0;
+ int i;
+
+ for (i = 0; i < 32; i++) {
+ if (host_events & (1 << i)) {
+ host_clear_events(1 << i);
+ evt_index = i + 1; /* Events are 1-based */
+ break;
+ }
+ }
+
+ return evt_index;
+}
+
+
void lpc_set_host_event_mask(enum lpc_host_event_type type, uint32_t mask)
{
event_mask[type] = mask;
@@ -389,116 +402,21 @@ uint32_t lpc_get_host_event_mask(enum lpc_host_event_type type)
*
* @param is_cmd Is write command (is_cmd=1) or data (is_cmd=0)
*/
+__attribute__((noinline)) /* TODO(crosbug.com/p/24515) */
static void handle_acpi_write(int is_cmd)
{
- int data = 0;
+ uint8_t value, result;
/* Set the busy bit */
LM4_LPC_ST(LPC_CH_ACPI) |= LM4_LPC_ST_BUSY;
/* Read command/data; this clears the FRMH status bit. */
- if (is_cmd) {
- acpi_cmd = LPC_POOL_ACPI[0];
- acpi_data_count = 0;
- } else {
- data = LPC_POOL_ACPI[0];
- /*
- * The first data byte is the ACPI memory address for
- * read/write commands.
- */
- if (!acpi_data_count++)
- acpi_addr = data;
- }
-
- /* Process complete commands */
- if (acpi_cmd == EC_CMD_ACPI_READ && acpi_data_count == 1) {
- /* ACPI read cmd + addr */
- int result = 0xff; /* value for bogus read */
-
- switch (acpi_addr) {
- case EC_ACPI_MEM_VERSION:
- result = EC_ACPI_MEM_VERSION_CURRENT;
- break;
- case EC_ACPI_MEM_TEST:
- result = acpi_mem_test;
- break;
- case EC_ACPI_MEM_TEST_COMPLIMENT:
- result = 0xff - acpi_mem_test;
- break;
-#ifdef CONFIG_PWM_KBLIGHT
- case EC_ACPI_MEM_KEYBOARD_BACKLIGHT:
- /*
- * TODO(crosbug.com/p/23774): not very satisfying that
- * LPC knows directly about the keyboard backlight, but
- * for now this is good enough and less code than
- * defining a new API for ACPI commands. If we start
- * adding more commands, or need to support LPC on more
- * than just LM4, fix this.
- */
- result = pwm_get_duty(PWM_CH_KBLIGHT);
- break;
-#endif
-#ifdef CONFIG_FANS
- case EC_ACPI_MEM_FAN_DUTY:
- /** TODO(crosbug.com/p/23774): Fix this too */
- result = dptf_get_fan_duty_target();
- break;
-#endif
- default:
- break;
- }
+ value = LPC_POOL_ACPI[0];
- /* Send the result byte */
- CPRINTF("[%T ACPI read 0x%02x = 0x%02x]\n", acpi_addr, result);
+ /* Handle whatever this was. */
+ if (acpi_ap_to_ec(is_cmd, value, &result))
LPC_POOL_ACPI[1] = result;
- } else if (acpi_cmd == EC_CMD_ACPI_WRITE && acpi_data_count == 2) {
- /* ACPI write cmd + addr + data */
- switch (acpi_addr) {
- case EC_ACPI_MEM_TEST:
- CPRINTF("[%T ACPI mem test 0x%02x]\n", data);
- acpi_mem_test = data;
- break;
-#ifdef CONFIG_PWM_KBLIGHT
- case EC_ACPI_MEM_KEYBOARD_BACKLIGHT:
- /*
- * Debug output with CR not newline, because the host
- * does a lot of keyboard backlights and it scrolls the
- * debug console.
- */
- CPRINTF("\r[%T ACPI kblight %d]", data);
- pwm_set_duty(PWM_CH_KBLIGHT, data);
- break;
-#endif
-#ifdef CONFIG_FANS
- case EC_ACPI_MEM_FAN_DUTY:
- /** TODO(crosbug.com/p/23774): Fix this too */
- dptf_set_fan_duty_target(data);
- break;
-#endif
- default:
- CPRINTF("[%T ACPI write 0x%02x = 0x%02x]\n",
- acpi_addr, data);
- break;
- }
-
- } else if (acpi_cmd == EC_CMD_ACPI_QUERY_EVENT && !acpi_data_count) {
- /* Clear and return the lowest host event */
- int evt_index = 0;
- int i;
-
- for (i = 0; i < 32; i++) {
- if (host_events & (1 << i)) {
- host_clear_events(1 << i);
- evt_index = i + 1; /* Events are 1-based */
- break;
- }
- }
-
- CPRINTF("[%T ACPI query = %d]\n", evt_index);
- LPC_POOL_ACPI[1] = evt_index;
- }
-
/* Clear the busy bit */
LM4_LPC_ST(LPC_CH_ACPI) &= ~LM4_LPC_ST_BUSY;
diff --git a/chip/mec1322/lpc.c b/chip/mec1322/lpc.c
index 5ccd7cb43f..7b71eb2d09 100644
--- a/chip/mec1322/lpc.c
+++ b/chip/mec1322/lpc.c
@@ -148,6 +148,12 @@ void lpc_set_host_event_state(uint32_t mask)
/* TODO(crosbug.com/p/24107): Host event */
}
+int lpc_query_host_event_state(void)
+{
+ /* TODO(crosbug.com/p/24107): Host event */
+ return 0;
+}
+
void lpc_set_host_event_mask(enum lpc_host_event_type type, uint32_t mask)
{
/* TODO(crosbug.com/p/24107): Host event */
diff --git a/common/acpi.c b/common/acpi.c
new file mode 100644
index 0000000000..942dd21dd2
--- /dev/null
+++ b/common/acpi.c
@@ -0,0 +1,132 @@
+/* Copyright (c) 2013 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.
+ */
+
+#include "acpi.h"
+#include "common.h"
+#include "console.h"
+#include "dptf.h"
+#include "lpc.h"
+#include "ec_commands.h"
+#include "pwm.h"
+
+/* Console output macros */
+#define CPUTS(outstr) cputs(CC_LPC, outstr)
+#define CPRINTF(format, args...) cprintf(CC_LPC, format, ## args)
+
+static uint8_t acpi_cmd; /* Last received ACPI command */
+static uint8_t acpi_addr; /* First byte of data after ACPI command */
+static int acpi_data_count; /* Number of data writes after command */
+static uint8_t acpi_mem_test; /* Test byte in ACPI memory space */
+
+/* This handles AP writes to the EC via the ACPI I/O port. There are only a few
+ * ACPI commands (EC_CMD_ACPI_*), but they are all handled here.
+ */
+int acpi_ap_to_ec(int is_cmd, uint8_t value, uint8_t *resultptr)
+{
+ int data = 0;
+ int retval = 0;
+
+ CPRINTF("[HEY: %T %s(%d, 0x%x)]\n", is_cmd, value);
+
+ /* Read command/data; this clears the FRMH status bit. */
+ if (is_cmd) {
+ acpi_cmd = value;
+ acpi_data_count = 0;
+ } else {
+ data = value;
+ /*
+ * The first data byte is the ACPI memory address for
+ * read/write commands.
+ */
+ if (!acpi_data_count++)
+ acpi_addr = data;
+ }
+
+ /* Process complete commands */
+ if (acpi_cmd == EC_CMD_ACPI_READ && acpi_data_count == 1) {
+ /* ACPI read cmd + addr */
+ int result = 0xff; /* value for bogus read */
+
+ switch (acpi_addr) {
+ case EC_ACPI_MEM_VERSION:
+ result = EC_ACPI_MEM_VERSION_CURRENT;
+ break;
+ case EC_ACPI_MEM_TEST:
+ result = acpi_mem_test;
+ break;
+ case EC_ACPI_MEM_TEST_COMPLIMENT:
+ result = 0xff - acpi_mem_test;
+ break;
+#ifdef CONFIG_PWM_KBLIGHT
+ case EC_ACPI_MEM_KEYBOARD_BACKLIGHT:
+ /*
+ * TODO(crosbug.com/p/23774): not very satisfying that
+ * LPC knows directly about the keyboard backlight, but
+ * for now this is good enough and less code than
+ * defining a new API for ACPI commands. If we start
+ * adding more commands, or need to support LPC on more
+ * than just LM4, fix this.
+ */
+ result = pwm_get_duty(PWM_CH_KBLIGHT);
+ break;
+#endif
+#ifdef CONFIG_FANS
+ case EC_ACPI_MEM_FAN_DUTY:
+ /** TODO(crosbug.com/p/23774): Fix this too */
+ result = dptf_get_fan_duty_target();
+ break;
+#endif
+ default:
+ break;
+ }
+
+ /* Send the result byte */
+ CPRINTF("[%T ACPI read 0x%02x = 0x%02x]\n", acpi_addr, result);
+ *resultptr = result;
+ retval = 1;
+
+ } else if (acpi_cmd == EC_CMD_ACPI_WRITE && acpi_data_count == 2) {
+ /* ACPI write cmd + addr + data */
+ switch (acpi_addr) {
+ case EC_ACPI_MEM_TEST:
+ CPRINTF("[%T ACPI mem test 0x%02x]\n", data);
+ acpi_mem_test = data;
+ break;
+#ifdef CONFIG_PWM_KBLIGHT
+ case EC_ACPI_MEM_KEYBOARD_BACKLIGHT:
+ /*
+ * Debug output with CR not newline, because the host
+ * does a lot of keyboard backlights and it scrolls the
+ * debug console.
+ */
+ CPRINTF("\r[%T ACPI kblight %d]", data);
+ pwm_set_duty(PWM_CH_KBLIGHT, data);
+ break;
+#endif
+#ifdef CONFIG_FANS
+ case EC_ACPI_MEM_FAN_DUTY:
+ /** TODO(crosbug.com/p/23774): Fix this too */
+ dptf_set_fan_duty_target(data);
+ break;
+#endif
+ default:
+ CPRINTF("[%T ACPI write 0x%02x = 0x%02x]\n",
+ acpi_addr, data);
+ break;
+ }
+
+/* At the moment, ACPI implies LPC. */
+#ifdef CONFIG_LPC
+ } else if (acpi_cmd == EC_CMD_ACPI_QUERY_EVENT && !acpi_data_count) {
+ /* Clear and return the lowest host event */
+ int evt_index = lpc_query_host_event_state();
+ CPRINTF("[%T ACPI query = %d]\n", evt_index);
+ *resultptr = evt_index;
+ retval = 1;
+#endif
+ }
+
+ return retval;
+}
diff --git a/common/build.mk b/common/build.mk
index 18da04ae78..8fef36f1a6 100644
--- a/common/build.mk
+++ b/common/build.mk
@@ -55,7 +55,7 @@ common-$(CONFIG_USB_PORT_POWER_SMART)+=usb_port_power_smart.o
common-$(CONFIG_WIRELESS)+=wireless.o
common-$(HAS_TASK_CHIPSET)+=chipset.o throttle_ap.o
common-$(HAS_TASK_CONSOLE)+=console.o
-common-$(HAS_TASK_HOSTCMD)+=host_command.o host_event_commands.o
+common-$(HAS_TASK_HOSTCMD)+=acpi.o host_command.o host_event_commands.o
common-$(HAS_TASK_KEYSCAN)+=keyboard_scan.o
common-$(HAS_TASK_LIGHTBAR)+=lightbar.o
common-$(HAS_TASK_VBOOTHASH)+=sha256.o vboot_hash.o
diff --git a/include/acpi.h b/include/acpi.h
new file mode 100644
index 0000000000..0ffc8d9f10
--- /dev/null
+++ b/include/acpi.h
@@ -0,0 +1,23 @@
+/* Copyright (c) 2013 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.
+ */
+
+/* ACPI EC interface block. */
+
+#ifndef __CROS_EC_ACPI_H
+#define __CROS_EC_ACPI_H
+
+#include <stdint.h>
+
+/**
+ * Handle AP write to EC via the ACPI I/O port.
+ *
+ * @param is_cmd Is write command (is_cmd=1) or data (is_cmd=0)
+ * @param value Value written to cmd or data register by AP
+ * @param result Value for AP to read from data port, if any
+ * @return True if *result was updated by this call
+ */
+int acpi_ap_to_ec(int is_cmd, uint8_t value, uint8_t *result);
+
+#endif /* __CROS_EC_ACPI_H */
diff --git a/include/lpc.h b/include/lpc.h
index 9ecef5027b..0ecaa6b822 100644
--- a/include/lpc.h
+++ b/include/lpc.h
@@ -79,6 +79,11 @@ enum lpc_host_event_type {
void lpc_set_host_event_state(uint32_t mask);
/**
+ * Clear and return the lowest host event.
+ */
+int lpc_query_host_event_state(void);
+
+/**
* Set the event mask for the specified event type.
*
* @param type Event type