diff options
Diffstat (limited to 'common/acpi.c')
-rw-r--r-- | common/acpi.c | 435 |
1 files changed, 0 insertions, 435 deletions
diff --git a/common/acpi.c b/common/acpi.c deleted file mode 100644 index 941a8b2e56..0000000000 --- a/common/acpi.c +++ /dev/null @@ -1,435 +0,0 @@ -/* Copyright 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 "battery.h" -#include "common.h" -#include "console.h" -#include "dptf.h" -#include "ec_commands.h" -#include "fan.h" -#include "gpio.h" -#include "hooks.h" -#include "host_command.h" -#include "keyboard_backlight.h" -#include "lpc.h" -#include "pwm.h" -#include "timer.h" -#include "tablet_mode.h" -#include "usb_charge.h" -#include "usb_common.h" -#include "util.h" - -/* Console output macros */ -#define CPUTS(outstr) cputs(CC_LPC, outstr) -#define CPRINTF(format, args...) cprintf(CC_LPC, format, ## args) -#define CPRINTS(format, args...) cprints(CC_LPC, format, ## args) - -/* Last received ACPI command */ -static uint8_t __bss_slow acpi_cmd; -/* First byte of data after ACPI command */ -static uint8_t __bss_slow acpi_addr; -/* Number of data writes after command */ -static int __bss_slow acpi_data_count; -/* Test byte in ACPI memory space */ -static uint8_t __bss_slow acpi_mem_test; - -#ifdef CONFIG_DPTF -static int __bss_slow dptf_temp_sensor_id; /* last sensor ID written */ -static int __bss_slow dptf_temp_threshold; /* last threshold written */ - -/* - * Current DPTF profile number. - * This is by default initialized to 1 if multi-profile DPTF is not supported. - * If multi-profile DPTF is supported, this is by default initialized to 2 under - * the assumption that profile #2 corresponds to lower thresholds and is a safer - * profile to use until board or some EC driver sets the appropriate profile for - * device mode. - */ -static int current_dptf_profile = DPTF_PROFILE_DEFAULT; - -#endif - -/* - * Keep a read cache of four bytes when burst mode is enabled, which is the - * size of the largest non-string memmap data type. - */ -#define ACPI_READ_CACHE_SIZE 4 - -/* Start address that indicates read cache is flushed. */ -#define ACPI_READ_CACHE_FLUSHED (EC_ACPI_MEM_MAPPED_BEGIN - 1) - -/* Calculate size of valid cache based upon end of memmap data. */ -#define ACPI_VALID_CACHE_SIZE(addr) (MIN( \ - EC_ACPI_MEM_MAPPED_SIZE + EC_ACPI_MEM_MAPPED_BEGIN - (addr), \ - ACPI_READ_CACHE_SIZE)) - -/* - * In burst mode, read the requested memmap data and the data immediately - * following it into a cache. For future reads in burst mode, try to grab - * data from the cache. This ensures the continuity of multi-byte reads, - * which is important when dealing with data types > 8 bits. - */ -static struct { - int enabled; - uint8_t start_addr; - uint8_t data[ACPI_READ_CACHE_SIZE]; -} acpi_read_cache; - -/* - * Deferred function to ensure that ACPI burst mode doesn't remain enabled - * indefinitely. - */ -static void acpi_disable_burst_deferred(void) -{ - acpi_read_cache.enabled = 0; - lpc_clear_acpi_status_mask(EC_LPC_STATUS_BURST_MODE); - CPUTS("ACPI missed burst disable?"); -} -DECLARE_DEFERRED(acpi_disable_burst_deferred); - -#ifdef CONFIG_DPTF - -static int acpi_dptf_is_profile_valid(int n) -{ -#ifdef CONFIG_DPTF_MULTI_PROFILE - if ((n < DPTF_PROFILE_VALID_FIRST) || (n > DPTF_PROFILE_VALID_LAST)) - return EC_ERROR_INVAL; -#else - if (n != DPTF_PROFILE_DEFAULT) - return EC_ERROR_INVAL; -#endif - - return EC_SUCCESS; -} - -int acpi_dptf_set_profile_num(int n) -{ - int ret = acpi_dptf_is_profile_valid(n); - - if (ret == EC_SUCCESS) { - current_dptf_profile = n; - if (IS_ENABLED(CONFIG_DPTF_MULTI_PROFILE) && - IS_ENABLED(CONFIG_HOSTCMD_EVENTS)) { - /* Notify kernel to update DPTF profile */ - host_set_single_event(EC_HOST_EVENT_MODE_CHANGE); - } - } - return ret; -} - -int acpi_dptf_get_profile_num(void) -{ - return current_dptf_profile; -} - -#endif - -/* Read memmapped data, returns read data or 0xff on error. */ -static int acpi_read(uint8_t addr) -{ - uint8_t *memmap_addr = (uint8_t *)(lpc_get_memmap_range() + addr - - EC_ACPI_MEM_MAPPED_BEGIN); - - /* Check for out-of-range read. */ - if (addr < EC_ACPI_MEM_MAPPED_BEGIN || - addr >= EC_ACPI_MEM_MAPPED_BEGIN + EC_ACPI_MEM_MAPPED_SIZE) { - CPRINTS("ACPI read 0x%02x (ignored)", - acpi_addr); - return 0xff; - } - - /* Read from cache if enabled (burst mode). */ - if (acpi_read_cache.enabled) { - /* Fetch to cache on miss. */ - if (acpi_read_cache.start_addr == ACPI_READ_CACHE_FLUSHED || - acpi_read_cache.start_addr > addr || - addr - acpi_read_cache.start_addr >= - ACPI_READ_CACHE_SIZE) { - memcpy(acpi_read_cache.data, - memmap_addr, - ACPI_VALID_CACHE_SIZE(addr)); - acpi_read_cache.start_addr = addr; - } - /* Return data from cache. */ - return acpi_read_cache.data[addr - acpi_read_cache.start_addr]; - } else { - /* Read directly from memmap data. */ - return *memmap_addr; - } -} - -/* - * 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; - int result = 0xff; /* value for bogus read */ - - /* 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 */ - 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_KEYBOARD_BACKLIGHT - case EC_ACPI_MEM_KEYBOARD_BACKLIGHT: - result = kblight_get(); - break; -#endif -#ifdef CONFIG_FANS - case EC_ACPI_MEM_FAN_DUTY: - result = dptf_get_fan_duty_target(); - break; -#endif -#ifdef CONFIG_DPTF - case EC_ACPI_MEM_TEMP_ID: - result = dptf_query_next_sensor_event(); - break; -#endif -#ifdef CONFIG_CHARGER - case EC_ACPI_MEM_CHARGING_LIMIT: - result = dptf_get_charging_current_limit(); - if (result >= 0) - result /= EC_ACPI_MEM_CHARGING_LIMIT_STEP_MA; - else - result = EC_ACPI_MEM_CHARGING_LIMIT_DISABLED; - break; -#endif - - case EC_ACPI_MEM_DEVICE_ORIENTATION: - result = 0; - -#ifdef CONFIG_TABLET_MODE - result = tablet_get_mode() << EC_ACPI_MEM_TBMD_SHIFT; -#endif - -#ifdef CONFIG_DPTF - result |= (acpi_dptf_get_profile_num() & - EC_ACPI_MEM_DDPN_MASK) - << EC_ACPI_MEM_DDPN_SHIFT; -#endif - break; - - case EC_ACPI_MEM_DEVICE_FEATURES0: - case EC_ACPI_MEM_DEVICE_FEATURES1: - case EC_ACPI_MEM_DEVICE_FEATURES2: - case EC_ACPI_MEM_DEVICE_FEATURES3: { - int off = acpi_addr - EC_ACPI_MEM_DEVICE_FEATURES0; - uint32_t val = get_feature_flags0(); - - /* Flush EC_FEATURE_LIMITED bit. Having it reset to 0 - * means that FEATURES[0-3] are supported in the first - * place, and the other bits are valid. - */ - val &= ~1; - - result = val >> (8 * off); - break; - } - case EC_ACPI_MEM_DEVICE_FEATURES4: - case EC_ACPI_MEM_DEVICE_FEATURES5: - case EC_ACPI_MEM_DEVICE_FEATURES6: - case EC_ACPI_MEM_DEVICE_FEATURES7: { - int off = acpi_addr - EC_ACPI_MEM_DEVICE_FEATURES4; - uint32_t val = get_feature_flags1(); - - result = val >> (8 * off); - break; - } - -#ifdef CONFIG_USB_PORT_POWER_DUMB - case EC_ACPI_MEM_USB_PORT_POWER: { - int i; - const int port_count = MIN(8, USB_PORT_COUNT); - - /* - * Convert each USB port power GPIO signal to a bit - * field with max size 8 bits. USB port ID (index) 0 is - * the least significant bit. - */ - result = 0; - for (i = 0; i < port_count; ++i) { - if (gpio_get_level(usb_port_enable[i]) != 0) - result |= 1 << i; - } - break; - } -#endif -#ifdef CONFIG_USBC_RETIMER_FW_UPDATE - case EC_ACPI_MEM_USB_RETIMER_FW_UPDATE: - result = usb_retimer_fw_update_get_result(); - break; -#endif - default: - result = acpi_read(acpi_addr); - break; - } - - /* Send the result byte */ - *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: - acpi_mem_test = data; - break; -#ifdef CONFIG_BATTERY_V2 - case EC_ACPI_MEM_BATTERY_INDEX: - CPRINTS("ACPI battery %d", data); - battery_memmap_set_index(data); - break; -#endif -#ifdef CONFIG_KEYBOARD_BACKLIGHT - 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[%pT ACPI kblight %d]", - PRINTF_TIMESTAMP_NOW, data); - kblight_set(data); - kblight_enable(data > 0); - break; -#endif -#ifdef CONFIG_FANS - case EC_ACPI_MEM_FAN_DUTY: - dptf_set_fan_duty_target(data); - break; -#endif -#ifdef CONFIG_DPTF - case EC_ACPI_MEM_TEMP_ID: - dptf_temp_sensor_id = data; - break; - case EC_ACPI_MEM_TEMP_THRESHOLD: - dptf_temp_threshold = data + EC_TEMP_SENSOR_OFFSET; - break; - case EC_ACPI_MEM_TEMP_COMMIT: - { - int idx = data & EC_ACPI_MEM_TEMP_COMMIT_SELECT_MASK; - int enable = data & EC_ACPI_MEM_TEMP_COMMIT_ENABLE_MASK; - dptf_set_temp_threshold(dptf_temp_sensor_id, - dptf_temp_threshold, - idx, enable); - break; - } -#endif -#ifdef CONFIG_CHARGER - case EC_ACPI_MEM_CHARGING_LIMIT: - if (data == EC_ACPI_MEM_CHARGING_LIMIT_DISABLED) { - dptf_set_charging_current_limit(-1); - } else { - data *= EC_ACPI_MEM_CHARGING_LIMIT_STEP_MA; - dptf_set_charging_current_limit(data); - } - break; -#endif - -#ifdef CONFIG_USB_PORT_POWER_DUMB - case EC_ACPI_MEM_USB_PORT_POWER: { - int i; - int mode_field = data; - const int port_count = MIN(8, USB_PORT_COUNT); - - /* - * Read the port power bit field (with max size 8 bits) - * and set the charge mode of each USB port accordingly. - * USB port ID 0 is the least significant bit. - */ - for (i = 0; i < port_count; ++i) { - int mode = USB_CHARGE_MODE_DISABLED; - - if (mode_field & 1) - mode = USB_CHARGE_MODE_ENABLED; - - if (usb_charge_set_mode(i, mode, - USB_ALLOW_SUSPEND_CHARGE)) { - CPRINTS("ERROR: could not set charge " - "mode of USB port p%d to %d", - i, mode); - } - mode_field >>= 1; - } - break; - } -#endif -#ifdef CONFIG_USBC_RETIMER_FW_UPDATE - case EC_ACPI_MEM_USB_RETIMER_FW_UPDATE: - usb_retimer_fw_update_process_op( - EC_ACPI_MEM_USB_RETIMER_PORT(data), - EC_ACPI_MEM_USB_RETIMER_OP(data)); - break; -#endif - default: - CPRINTS("ACPI write 0x%02x = 0x%02x (ignored)", - 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 = lpc_get_next_host_event(); - CPRINTS("ACPI query = %d", evt_index); - *resultptr = evt_index; - retval = 1; - } else if (acpi_cmd == EC_CMD_ACPI_BURST_ENABLE && !acpi_data_count) { - /* - * TODO: The kernel only enables BURST when doing multi-byte - * value reads over the ACPI port. We don't do such reads - * when our memmap data can be accessed directly over LPC, - * so on LM4, for example, this is dead code. We might want - * to add a config to skip this code for certain chips. - */ - acpi_read_cache.enabled = 1; - acpi_read_cache.start_addr = ACPI_READ_CACHE_FLUSHED; - - /* Enter burst mode */ - lpc_set_acpi_status_mask(EC_LPC_STATUS_BURST_MODE); - - /* - * Disable from deferred function in case burst mode is enabled - * for an extremely long time (ex. kernel bug / crash). - */ - hook_call_deferred(&acpi_disable_burst_deferred_data, 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) { - acpi_read_cache.enabled = 0; - - /* Leave burst mode */ - hook_call_deferred(&acpi_disable_burst_deferred_data, -1); - lpc_clear_acpi_status_mask(EC_LPC_STATUS_BURST_MODE); - } - - return retval; -} |