diff options
author | Shawn Nematbakhsh <shawnn@chromium.org> | 2015-03-23 18:27:22 -0700 |
---|---|---|
committer | ChromeOS Commit Bot <chromeos-commit-bot@chromium.org> | 2015-03-25 20:09:52 +0000 |
commit | 6ee7b1e34eecd585074b4aae0347ed12f632ead0 (patch) | |
tree | ace73f958495a83b836505941318325fa71c71e7 /common/acpi.c | |
parent | 0f18989ef58a77800c1b393cf8223455f793d543 (diff) | |
download | chrome-ec-stabilize-6915.B.tar.gz |
ACPI: Support accessing memmap data over ACPI CMD / DATA portsstabilize-6915.B
Some platforms are unable to access the 900h-9ffh region over LPC and
must instead access memmap data through the ACPI CMD / DATA ports. To
avoid racing with data updates, disallow changes to multi-byte memmap
data while in burst mode.
Linux currently enables burst mode when accessing multi-byte data and
disables it immediately afterward, though the ACPI spec defines burst mode
in a more general way.
BUG=chrome-os-partner:38224
TEST=Manual on Samus. Undefine LPC_MEMMAP and modify asl to move memmap
data to ERAM at offset 0x20. Verify system boots cleanly and battery
status is updated immediately on plug / unplug.
BRANCH=None
Change-Id: Ib848bdb491fdfece96ad0cee7a44ba85b4a1a50b
Signed-off-by: Shawn Nematbakhsh <shawnn@chromium.org>
Reviewed-on: https://chromium-review.googlesource.com/262072
Reviewed-by: Randall Spangler <rspangler@chromium.org>
Reviewed-by: Duncan Laurie <dlaurie@chromium.org>
Diffstat (limited to 'common/acpi.c')
-rw-r--r-- | common/acpi.c | 51 |
1 files changed, 45 insertions, 6 deletions
diff --git a/common/acpi.c b/common/acpi.c index 88c0a8351e..425f7e2337 100644 --- a/common/acpi.c +++ b/common/acpi.c @@ -7,9 +7,12 @@ #include "common.h" #include "console.h" #include "dptf.h" +#include "hooks.h" +#include "host_command.h" #include "lpc.h" #include "ec_commands.h" #include "pwm.h" +#include "timer.h" /* Console output macros */ #define CPUTS(outstr) cputs(CC_LPC, outstr) @@ -26,7 +29,20 @@ static int dptf_temp_sensor_id; /* last sensor ID written */ static int dptf_temp_threshold; /* last threshold written */ #endif -/* This handles AP writes to the EC via the ACPI I/O port. There are only a few +/* + * Deferred function to ensure that ACPI burst mode doesn't remain enabled + * indefinitely. + */ +static void acpi_unlock_memmap_deferred(void) +{ + lpc_clear_acpi_status_mask(EC_LPC_STATUS_BURST_MODE); + host_unlock_memmap(); + CPUTS("ACPI force unlock mutex, missed burst disable?"); +} +DECLARE_DEFERRED(acpi_unlock_memmap_deferred); + +/* + * 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) @@ -87,7 +103,15 @@ int acpi_ap_to_ec(int is_cmd, uint8_t value, uint8_t *resultptr) break; #endif default: - CPRINTS("ACPI read 0x%02x (ignored)", acpi_addr); + if (acpi_addr >= EC_ACPI_MEM_MAPPED_BEGIN && + acpi_addr < + EC_ACPI_MEM_MAPPED_BEGIN + EC_ACPI_MEM_MAPPED_SIZE) + result = *((uint8_t *)(lpc_get_memmap_range() + + acpi_addr - + EC_ACPI_MEM_MAPPED_BEGIN)); + else + CPRINTS("ACPI read 0x%02x (ignored)", + acpi_addr); break; } @@ -149,16 +173,31 @@ int acpi_ap_to_ec(int is_cmd, uint8_t value, uint8_t *resultptr) 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(); CPRINTS("ACPI query = %d", evt_index); *resultptr = evt_index; retval = 1; -#endif + } else if (acpi_cmd == EC_CMD_ACPI_BURST_ENABLE && !acpi_data_count) { + /* Enter burst mode */ + host_lock_memmap(); + lpc_set_acpi_status_mask(EC_LPC_STATUS_BURST_MODE); + + /* + * Unlock from deferred function in case burst mode is enabled + * for an extremely long time (ex. kernel bug / crash). + */ + hook_call_deferred(acpi_unlock_memmap_deferred, 1*SECOND); + + /* ACPI 5.0-12.3.3: Burst ACK */ + *resultptr = 0x90; + retval = 1; + } else if (acpi_cmd == EC_CMD_ACPI_BURST_DISABLE && !acpi_data_count) { + /* Leave burst mode */ + hook_call_deferred(acpi_unlock_memmap_deferred, -1); + lpc_clear_acpi_status_mask(EC_LPC_STATUS_BURST_MODE); + host_unlock_memmap(); } return retval; |