// SPDX-License-Identifier: GPL-2.0-or-later/* * ec.c - ACPI Embedded Controller Driver (v3) * * Copyright (C) 2001-2015 Intel Corporation * Author: 2014, 2015 Lv Zheng <lv.zheng@intel.com> * 2006, 2007 Alexey Starikovskiy <alexey.y.starikovskiy@intel.com> * 2006 Denis Sadykov <denis.m.sadykov@intel.com> * 2004 Luming Yu <luming.yu@intel.com> * 2001, 2002 Andy Grover <andrew.grover@intel.com> * 2001, 2002 Paul Diefenbaugh <paul.s.diefenbaugh@intel.com> * Copyright (C) 2008 Alexey Starikovskiy <astarikovskiy@suse.de> */ /* Uncomment next line to get verbose printout *//* #define DEBUG */#define pr_fmt(fmt) "ACPI: EC: " fmt #include <linux/kernel.h>#include <linux/module.h>#include <linux/init.h>#include <linux/types.h>#include <linux/delay.h>#include <linux/interrupt.h>#include <linux/list.h>#include <linux/platform_device.h>#include <linux/printk.h>#include <linux/spinlock.h>#include <linux/slab.h>#include <linux/string.h>#include <linux/suspend.h>#include <linux/acpi.h>#include <linux/dmi.h>#include <asm/io.h> #include "internal.h" /* EC status register */#define ACPI_EC_FLAG_OBF 0x01 /* Output buffer full */#define ACPI_EC_FLAG_IBF 0x02 /* Input buffer full */#define ACPI_EC_FLAG_CMD 0x08 /* Input buffer contains a command */#define ACPI_EC_FLAG_BURST 0x10 /* burst mode */#define ACPI_EC_FLAG_SCI 0x20 /* EC-SCI occurred */ /* * The SCI_EVT clearing timing is not defined by the ACPI specification. * This leads to lots of practical timing issues for the host EC driver. * The following variations are defined (from the target EC firmware's * perspective): * STATUS: After indicating SCI_EVT edge triggered IRQ to the host, the * target can clear SCI_EVT at any time so long as the host can see * the indication by reading the status register (EC_SC). So the * host should re-check SCI_EVT after the first time the SCI_EVT * indication is seen, which is the same time the query request * (QR_EC) is written to the command register (EC_CMD). SCI_EVT set * at any later time could indicate another event. Normally such * kind of EC firmware has implemented an event queue and will * return 0x00 to indicate "no outstanding event". * QUERY: After seeing the query request (QR_EC) written to the command * register (EC_CMD) by the host and having prepared the responding * event value in the data register (EC_DATA), the target can safely * clear SCI_EVT because the target can confirm that the current * event is being handled by the host. The host then should check * SCI_EVT right after reading the event response from the data * register (EC_DATA). * EVENT: After seeing the event response read from the data register * (EC_DATA) by the host, the target can clear SCI_EVT. As the * target requires time to notice the change in the data register * (EC_DATA), the host may be required to wait additional guarding * time before checking the SCI_EVT again. Such guarding may not be * necessary if the host is notified via another IRQ. */#define ACPI_EC_EVT_TIMING_STATUS 0x00#define ACPI_EC_EVT_TIMING_QUERY 0x01#define ACPI_EC_EVT_TIMING_EVENT 0x02 /* EC commands */enum ec_command { ACPI_EC_COMMAND_READ = 0x80, ACPI_EC_COMMAND_WRITE = 0x81, ACPI_EC_BURST_ENABLE = 0x82, ACPI_EC_BURST_DISABLE = 0x83, ACPI_EC_COMMAND_QUERY = 0x84,}; #define ACPI_EC_DELAY 500 /* Wait 500ms max. during EC ops */#define ACPI_EC_UDELAY_GLK 1000 /* Wait 1ms max. to get global lock */#define ACPI_EC_UDELAY_POLL 550 /* Wait 1ms for EC transaction polling */#define ACPI_EC_CLEAR_MAX 100 /* Maximum number of events to query * when trying to clear the EC */#define ACPI_EC_MAX_QUERIES 16 /* Maximum number of parallel queries */ enum { EC_FLAGS_QUERY_ENABLED, /* Query is enabled */ EC_FLAGS_EVENT_HANDLER_INSTALLED, /* Event handler installed */ EC_FLAGS_EC_HANDLER_INSTALLED, /* OpReg handler installed */ EC_FLAGS_EC_REG_CALLED, /* OpReg ACPI _REG method called */ EC_FLAGS_QUERY_METHODS_INSTALLED, /* _Qxx handlers installed */ EC_FLAGS_STARTED, /* Driver is started */ EC_FLAGS_STOPPED, /* Driver is stopped */ EC_FLAGS_EVENTS_MASKED, /* Events masked */}; #define ACPI_EC_COMMAND_POLL 0x01 /* Available for command byte */#define ACPI_EC_COMMAND_COMPLETE 0x02 /* Completed last byte */ /* ec.c is compiled in acpi namespace so this shows up as acpi.ec_delay param */static unsigned int ec_delay __read_mostly = ACPI_EC_DELAY;module_param(ec_delay, uint, 0644);MODULE_PARM_DESC(ec_delay, "Timeout(ms) waited until an EC command completes"); static unsigned int ec_max_queries __read_mostly = ACPI_EC_MAX_QUERIES;module_param(ec_max_queries, uint, 0644);MODULE_PARM_DESC(ec_max_queries, "Maximum parallel _Qxx evaluations"); static bool ec_busy_polling __read_mostly;module_param(ec_busy_polling, bool, 0644);MODULE_PARM_DESC(ec_busy_polling, "Use busy polling to advance EC transaction"); static unsigned int ec_polling_guard __read_mostly = ACPI_EC_UDELAY_POLL;module_param(ec_polling_guard, uint, 0644);MODULE_PARM_DESC(ec_polling_guard, "Guard time(us) between EC accesses in polling modes"); static unsigned int ec_event_clearing __read_mostly = ACPI_EC_EVT_TIMING_QUERY; /* * If the number of false interrupts per one transaction exceeds * this threshold, will think there is a GPE storm happened and * will disable the GPE for normal transaction. */static unsigned int ec_storm_threshold __read_mostly = 8;module_param(ec_storm_threshold, uint, 0644);MODULE_PARM_DESC(ec_storm_threshold, "Maxim false GPE numbers not considered as GPE storm"); static bool ec_freeze_events __read_mostly;module_param(ec_freeze_events, bool, 0644);MODULE_PARM_DESC(ec_freeze_events, "Disabling event handling during suspend/resume"); static bool ec_no_wakeup __read_mostly;module_param(ec_no_wakeup, bool, 0644);MODULE_PARM_DESC(ec_no_wakeup, "Do not wake up from suspend-to-idle"); struct acpi_ec_query_handler { struct list_head node; acpi_ec_query_func func; acpi_handle handle; void *data; u8 query_bit; struct kref kref;}; struct transaction { const u8 *wdata; u8 *rdata; unsigned short irq_count; u8 command; u8 wi; u8 ri; u8 wlen; u8 rlen; u8 flags;}; struct acpi_ec_query { struct transaction transaction; struct work_struct work; struct acpi_ec_query_handler *handler; struct acpi_ec *ec;}; static int acpi_ec_submit_query(struct acpi_ec *ec);static void advance_transaction(struct acpi_ec *ec, bool interrupt);static void acpi_ec_event_handler(struct work_struct *work); struct acpi_ec *first_ec;EXPORT_SYMBOL(first_ec); static struct acpi_ec *boot_ec;static bool boot_ec_is_ecdt;static struct workqueue_struct *ec_wq;static struct workqueue_struct *ec_query_wq; static int EC_FLAGS_CORRECT_ECDT; /* Needs ECDT port address correction */static int EC_FLAGS_TRUST_DSDT_GPE; /* Needs DSDT GPE as correction setting */static int EC_FLAGS_CLEAR_ON_RESUME; /* Needs acpi_ec_clear() on boot/resume */ /* -------------------------------------------------------------------------- * Logging/Debugging * -------------------------------------------------------------------------- */ /* * Splitters used by the developers to track the boundary of the EC * handling processes. */#ifdef DEBUG#define EC_DBG_SEP " "#define EC_DBG_DRV "+++++"#define EC_DBG_STM "====="#define EC_DBG_REQ "*****"#define EC_DBG_EVT "#####"#else#define EC_DBG_SEP ""#define EC_DBG_DRV#define EC_DBG_STM#define EC_DBG_REQ#define EC_DBG_EVT#endif #define ec_log_raw(fmt, ...) \ pr_info(fmt "\n", ##__VA_ARGS__)#define ec_dbg_raw(fmt, ...) \ pr_debug(fmt "\n", ##__VA_ARGS__)#define ec_log(filter, fmt, ...) \ ec_log_raw(filter EC_DBG_SEP fmt EC_DBG_SEP filter, ##__VA_ARGS__)#define ec_dbg(filter, fmt, ...) \ ec_dbg_raw(filter EC_DBG_SEP fmt EC_DBG_SEP filter, ##__VA_ARGS__) #define ec_log_drv(fmt, ...) \ ec_log(EC_DBG_DRV, fmt, ##__VA_ARGS__)#define ec_dbg_drv(fmt, ...) \ ec_dbg(EC_DBG_DRV, fmt, ##__VA_ARGS__)#define ec_dbg_stm(fmt, ...) \ ec_dbg(EC_DBG_STM, fmt, ##__VA_ARGS__)#define ec_dbg_req(fmt, ...) \ ec_dbg(EC_DBG_REQ, fmt, ##__VA_ARGS__)#define ec_dbg_evt(fmt, ...) \ ec_dbg(EC_DBG_EVT, fmt, ##__VA_ARGS__)#define ec_dbg_ref(ec, fmt, ...) \ ec_dbg_raw("%lu: " fmt, ec->reference_count, ## __VA_ARGS__) /* -------------------------------------------------------------------------- * Device Flags * -------------------------------------------------------------------------- */ static bool acpi_ec_started(struct acpi_ec *ec){ return test_bit(EC_FLAGS_STARTED, &ec->flags) && !test_bit(EC_FLAGS_STOPPED, &ec->flags);} static bool acpi_ec_event_enabled(struct acpi_ec *ec){ /* * There is an OSPM early stage logic. During the early stages * (boot/resume), OSPMs shouldn't enable the event handling, only * the EC transactions are allowed to be performed. */ if (!test_bit(EC_FLAGS_QUERY_ENABLED, &ec->flags)) return false; /* * However, disabling the event handling is experimental for late * stage (suspend), and is controlled by the boot parameter of * "ec_freeze_events": * 1. true: The EC event handling is disabled before entering * the noirq stage. * 2. false: The EC event handling is automatically disabled as * soon as the EC driver is stopped. */ if (ec_freeze_events) return acpi_ec_started(ec); else return test_bit(EC_FLAGS_STARTED, &ec->flags);} static bool acpi_ec_flushed(struct acpi_ec *ec){ return ec->reference_count == 1;} /* -------------------------------------------------------------------------- * EC Registers * -------------------------------------------------------------------------- */ static inline u8 acpi_ec_read_status(struct acpi_ec *ec){ u8 x = inb(ec->command_addr); ec_dbg_raw("EC_SC(R) = 0x%2.2x " "SCI_EVT=%d BURST=%d CMD=%d IBF=%d OBF=%d", x, !!(x & ACPI_EC_FLAG_SCI), !!(x & ACPI_EC_FLAG_BURST), !!(x & ACPI_EC_FLAG_CMD), !!(x & ACPI_EC_FLAG_IBF), !!(x & ACPI_EC_FLAG_OBF)); return x;} static inline u8 acpi_ec_read_data(struct acpi_ec *ec){ u8 x = inb(ec->data_addr); ec->timestamp = jiffies; ec_dbg_raw("EC_DATA(R) = 0x%2.2x", x); return x;} static inline void acpi_ec_write_cmd(struct acpi_ec *ec, u8 command){ ec_dbg_raw("EC_SC(W) = 0x%2.2x", command); outb(command, ec->command_addr); ec->timestamp = jiffies;} static inline void acpi_ec_write_data(struct acpi_ec *ec, u8 data){ ec_dbg_raw("EC_DATA(W) = 0x%2.2x", data); outb(data, ec->data_addr); ec->timestamp = jiffies;} #if defined(DEBUG) || defined(CONFIG_DYNAMIC_DEBUG)static const char *acpi_ec_cmd_string(u8 cmd){ switch (cmd) { case 0x80: return "RD_EC"; case 0x81: return "WR_EC"; case 0x82: return "BE_EC"; case 0x83: return "BD_EC"; case 0x84: return "QR_EC"; } return "UNKNOWN";}#else#define acpi_ec_cmd_string(cmd) "UNDEF"#endif /* -------------------------------------------------------------------------- * GPE Registers * -------------------------------------------------------------------------- */ static inline bool acpi_ec_gpe_status_set(struct acpi_ec *ec){ acpi_event_status gpe_status = 0; (void)acpi_get_gpe_status(NULL, ec->gpe, &gpe_status); return !!(gpe_status & ACPI_EVENT_FLAG_STATUS_SET);} static inline void acpi_ec_enable_gpe(struct acpi_ec *ec, bool open){ if (open) acpi_enable_gpe(NULL, ec->gpe); else { BUG_ON(ec->reference_count < 1); acpi_set_gpe(NULL, ec->gpe, ACPI_GPE_ENABLE); } if (acpi_ec_gpe_status_set(ec)) { /* * On some platforms, EN=1 writes cannot trigger GPE. So * software need to manually trigger a pseudo GPE event on * EN=1 writes. */ ec_dbg_raw("Polling quirk"); advance_transaction(ec, false); }} static inline void acpi_ec_disable_gpe(struct acpi_ec *ec, bool close){ if (close) acpi_disable_gpe(NULL, ec->gpe); else { BUG_ON(ec->reference_count < 1); acpi_set_gpe(NULL, ec->gpe, ACPI_GPE_DISABLE); }} /* -------------------------------------------------------------------------- * Transaction Management * -------------------------------------------------------------------------- */ static void acpi_ec_submit_request(struct acpi_ec *ec){ ec->reference_count++; if (test_bit(EC_FLAGS_EVENT_HANDLER_INSTALLED, &ec->flags) && ec->gpe >= 0 && ec->reference_count == 1) acpi_ec_enable_gpe(ec, true);} static void acpi_ec_complete_request(struct acpi_ec *ec){ bool flushed = false; ec->reference_count--; if (test_bit(EC_FLAGS_EVENT_HANDLER_INSTALLED, &ec->flags) && ec->gpe >= 0 && ec->reference_count == 0) acpi_ec_disable_gpe(ec, true); flushed = acpi_ec_flushed(ec); if (flushed) wake_up(&ec->wait);} static void acpi_ec_mask_events(struct acpi_ec *ec){ if (!test_bit(EC_FLAGS_EVENTS_MASKED, &ec->flags)) { if (ec->gpe >= 0) acpi_ec_disable_gpe(ec, false); else disable_irq_nosync(ec->irq); ec_dbg_drv("Polling enabled"); set_bit(EC_FLAGS_EVENTS_MASKED, &ec->flags); }} static void acpi_ec_unmask_events(struct acpi_ec *ec){ if (test_bit(EC_FLAGS_EVENTS_MASKED, &ec->flags)) { clear_bit(EC_FLAGS_EVENTS_MASKED, &ec->flags); if (ec->gpe >= 0) acpi_ec_enable_gpe(ec, false); else enable_irq(ec->irq); ec_dbg_drv("Polling disabled"); }} /* * acpi_ec_submit_flushable_request() - Increase the reference count unless * the flush operation is not in * progress * @ec: the EC device * * This function must be used before taking a new action that should hold * the reference count. If this function returns false, then the action * must be discarded or it will prevent the flush operation from being * completed. */static bool acpi_ec_submit_flushable_request(struct acpi_ec *ec){ if (!acpi_ec_started(ec)) return false; acpi_ec_submit_request(ec); return true;} static void acpi_ec_submit_event(struct acpi_ec *ec){ /* * It is safe to mask the events here, because acpi_ec_close_event() * will run at least once after this. */ acpi_ec_mask_events(ec); if (!acpi_ec_event_enabled(ec)) return; if (ec->event_state != EC_EVENT_READY) return; ec_dbg_evt("Command(%s) submitted/blocked", acpi_ec_cmd_string(ACPI_EC_COMMAND_QUERY)); ec->event_state = EC_EVENT_IN_PROGRESS; /* * If events_to_process is greater than 0 at this point, the while () * loop in acpi_ec_event_handler() is still running and incrementing * events_to_process will cause it to invoke acpi_ec_submit_query() once * more, so it is not necessary to queue up the event work to start the * same loop again. */ if (ec->events_to_process++ > 0) return; ec->events_in_progress++; queue_work(ec_wq, &ec->work);} static void acpi_ec_complete_event(struct acpi_ec *ec){ if (ec->event_state == EC_EVENT_IN_PROGRESS) ec->event_state = EC_EVENT_COMPLETE;} static void acpi_ec_close_event(struct acpi_ec *ec){ if (ec->event_state != EC_EVENT_READY) ec_dbg_evt("Command(%s) unblocked", acpi_ec_cmd_string(ACPI_EC_COMMAND_QUERY)); ec->event_state = EC_EVENT_READY; acpi_ec_unmask_events(ec);} static inline void __acpi_ec_enable_event(struct acpi_ec *ec){ if (!test_and_set_bit(EC_FLAGS_QUERY_ENABLED, &ec->flags)) ec_log_drv("event unblocked"); /* * Unconditionally invoke this once after enabling the event * handling mechanism to detect the pending events. */ advance_transaction(ec, false);}Lines 1–500 of 2390. Load more
// SPDX-License-Identifier: GPL-2.0-or-later /* * ec.c - ACPI Embedded Controller Driver (v3) * * Copyright (C) 2001-2015 Intel Corporation * Author: 2014, 2015 Lv Zheng <lv.zheng@intel.com> * 2006, 2007 Alexey Starikovskiy <alexey.y.starikovskiy@intel.com> * 2006 Denis Sadykov <denis.m.sadykov@intel.com> * 2004 Luming Yu <luming.yu@intel.com> * 2001, 2002 Andy Grover <andrew.grover@intel.com> * 2001, 2002 Paul Diefenbaugh <paul.s.diefenbaugh@intel.com> * Copyright (C) 2008 Alexey Starikovskiy <astarikovskiy@suse.de> */ /* Uncomment next line to get verbose printout */ /* #define DEBUG */ #define pr_fmt(fmt) "ACPI: EC: " fmt #include <linux/kernel.h> #include <linux/module.h> #include <linux/init.h> #include <linux/types.h> #include <linux/delay.h> #include <linux/interrupt.h> #include <linux/list.h> #include <linux/platform_device.h> #include <linux/printk.h> #include <linux/spinlock.h> #include <linux/slab.h> #include <linux/string.h> #include <linux/suspend.h> #include <linux/acpi.h> #include <linux/dmi.h> #include <asm/io.h> #include "internal.h" /* EC status register */ #define ACPI_EC_FLAG_OBF 0x01 /* Output buffer full */ #define ACPI_EC_FLAG_IBF 0x02 /* Input buffer full */ #define ACPI_EC_FLAG_CMD 0x08 /* Input buffer contains a command */ #define ACPI_EC_FLAG_BURST 0x10 /* burst mode */ #define ACPI_EC_FLAG_SCI 0x20 /* EC-SCI occurred */ /* * The SCI_EVT clearing timing is not defined by the ACPI specification. * This leads to lots of practical timing issues for the host EC driver. * The following variations are defined (from the target EC firmware's * perspective): * STATUS: After indicating SCI_EVT edge triggered IRQ to the host, the * target can clear SCI_EVT at any time so long as the host can see * the indication by reading the status register (EC_SC). So the * host should re-check SCI_EVT after the first time the SCI_EVT * indication is seen, which is the same time the query request * (QR_EC) is written to the command register (EC_CMD). SCI_EVT set * at any later time could indicate another event. Normally such * kind of EC firmware has implemented an event queue and will * return 0x00 to indicate "no outstanding event". * QUERY: After seeing the query request (QR_EC) written to the command * register (EC_CMD) by the host and having prepared the responding * event value in the data register (EC_DATA), the target can safely * clear SCI_EVT because the target can confirm that the current * event is being handled by the host. The host then should check * SCI_EVT right after reading the event response from the data * register (EC_DATA). * EVENT: After seeing the event response read from the data register * (EC_DATA) by the host, the target can clear SCI_EVT. As the * target requires time to notice the change in the data register * (EC_DATA), the host may be required to wait additional guarding * time before checking the SCI_EVT again. Such guarding may not be * necessary if the host is notified via another IRQ. */ #define ACPI_EC_EVT_TIMING_STATUS 0x00 #define ACPI_EC_EVT_TIMING_QUERY 0x01 #define ACPI_EC_EVT_TIMING_EVENT 0x02 /* EC commands */ enum ec_command { ACPI_EC_COMMAND_READ = 0x80, ACPI_EC_COMMAND_WRITE = 0x81, ACPI_EC_BURST_ENABLE = 0x82, ACPI_EC_BURST_DISABLE = 0x83, ACPI_EC_COMMAND_QUERY = 0x84, }; #define ACPI_EC_DELAY 500 /* Wait 500ms max. during EC ops */ #define ACPI_EC_UDELAY_GLK 1000 /* Wait 1ms max. to get global lock */ #define ACPI_EC_UDELAY_POLL 550 /* Wait 1ms for EC transaction polling */ #define ACPI_EC_CLEAR_MAX 100 /* Maximum number of events to query * when trying to clear the EC */ #define ACPI_EC_MAX_QUERIES 16 /* Maximum number of parallel queries */ enum { EC_FLAGS_QUERY_ENABLED, /* Query is enabled */ EC_FLAGS_EVENT_HANDLER_INSTALLED, /* Event handler installed */ EC_FLAGS_EC_HANDLER_INSTALLED, /* OpReg handler installed */ EC_FLAGS_EC_REG_CALLED, /* OpReg ACPI _REG method called */ EC_FLAGS_QUERY_METHODS_INSTALLED, /* _Qxx handlers installed */ EC_FLAGS_STARTED, /* Driver is started */ EC_FLAGS_STOPPED, /* Driver is stopped */ EC_FLAGS_EVENTS_MASKED, /* Events masked */ }; #define ACPI_EC_COMMAND_POLL 0x01 /* Available for command byte */ #define ACPI_EC_COMMAND_COMPLETE 0x02 /* Completed last byte */ /* ec.c is compiled in acpi namespace so this shows up as acpi.ec_delay param */ static unsigned int ec_delay __read_mostly = ACPI_EC_DELAY; module_param(ec_delay, uint, 0644); MODULE_PARM_DESC(ec_delay, "Timeout(ms) waited until an EC command completes"); static unsigned int ec_max_queries __read_mostly = ACPI_EC_MAX_QUERIES; module_param(ec_max_queries, uint, 0644); MODULE_PARM_DESC(ec_max_queries, "Maximum parallel _Qxx evaluations"); static bool ec_busy_polling __read_mostly; module_param(ec_busy_polling, bool, 0644); MODULE_PARM_DESC(ec_busy_polling, "Use busy polling to advance EC transaction"); static unsigned int ec_polling_guard __read_mostly = ACPI_EC_UDELAY_POLL; module_param(ec_polling_guard, uint, 0644); MODULE_PARM_DESC(ec_polling_guard, "Guard time(us) between EC accesses in polling modes"); static unsigned int ec_event_clearing __read_mostly = ACPI_EC_EVT_TIMING_QUERY; /* * If the number of false interrupts per one transaction exceeds * this threshold, will think there is a GPE storm happened and * will disable the GPE for normal transaction. */ static unsigned int ec_storm_threshold __read_mostly = 8; module_param(ec_storm_threshold, uint, 0644); MODULE_PARM_DESC(ec_storm_threshold, "Maxim false GPE numbers not considered as GPE storm"); static bool ec_freeze_events __read_mostly; module_param(ec_freeze_events, bool, 0644); MODULE_PARM_DESC(ec_freeze_events, "Disabling event handling during suspend/resume"); static bool ec_no_wakeup __read_mostly; module_param(ec_no_wakeup, bool, 0644); MODULE_PARM_DESC(ec_no_wakeup, "Do not wake up from suspend-to-idle"); struct acpi_ec_query_handler { struct list_head node; acpi_ec_query_func func; acpi_handle handle; void *data; u8 query_bit; struct kref kref; }; struct transaction { const u8 *wdata; u8 *rdata; unsigned short irq_count; u8 command; u8 wi; u8 ri; u8 wlen; u8 rlen; u8 flags; }; struct acpi_ec_query { struct transaction transaction; struct work_struct work; struct acpi_ec_query_handler *handler; struct acpi_ec *ec; }; static int acpi_ec_submit_query(struct acpi_ec *ec); static void advance_transaction(struct acpi_ec *ec, bool interrupt); static void acpi_ec_event_handler(struct work_struct *work); struct acpi_ec *first_ec; EXPORT_SYMBOL(first_ec); static struct acpi_ec *boot_ec; static bool boot_ec_is_ecdt; static struct workqueue_struct *ec_wq; static struct workqueue_struct *ec_query_wq; static int EC_FLAGS_CORRECT_ECDT; /* Needs ECDT port address correction */ static int EC_FLAGS_TRUST_DSDT_GPE; /* Needs DSDT GPE as correction setting */ static int EC_FLAGS_CLEAR_ON_RESUME; /* Needs acpi_ec_clear() on boot/resume */ /* -------------------------------------------------------------------------- * Logging/Debugging * -------------------------------------------------------------------------- */ /* * Splitters used by the developers to track the boundary of the EC * handling processes. */ #ifdef DEBUG #define EC_DBG_SEP " " #define EC_DBG_DRV "+++++" #define EC_DBG_STM "=====" #define EC_DBG_REQ "*****" #define EC_DBG_EVT "#####" #else #define EC_DBG_SEP "" #define EC_DBG_DRV #define EC_DBG_STM #define EC_DBG_REQ #define EC_DBG_EVT #endif #define ec_log_raw(fmt, ...) \ pr_info(fmt "\n", ##__VA_ARGS__) #define ec_dbg_raw(fmt, ...) \ pr_debug(fmt "\n", ##__VA_ARGS__) #define ec_log(filter, fmt, ...) \ ec_log_raw(filter EC_DBG_SEP fmt EC_DBG_SEP filter, ##__VA_ARGS__) #define ec_dbg(filter, fmt, ...) \ ec_dbg_raw(filter EC_DBG_SEP fmt EC_DBG_SEP filter, ##__VA_ARGS__) #define ec_log_drv(fmt, ...) \ ec_log(EC_DBG_DRV, fmt, ##__VA_ARGS__) #define ec_dbg_drv(fmt, ...) \ ec_dbg(EC_DBG_DRV, fmt, ##__VA_ARGS__) #define ec_dbg_stm(fmt, ...) \ ec_dbg(EC_DBG_STM, fmt, ##__VA_ARGS__) #define ec_dbg_req(fmt, ...) \ ec_dbg(EC_DBG_REQ, fmt, ##__VA_ARGS__) #define ec_dbg_evt(fmt, ...) \ ec_dbg(EC_DBG_EVT, fmt, ##__VA_ARGS__) #define ec_dbg_ref(ec, fmt, ...) \ ec_dbg_raw("%lu: " fmt, ec->reference_count, ## __VA_ARGS__) /* -------------------------------------------------------------------------- * Device Flags * -------------------------------------------------------------------------- */ static bool acpi_ec_started(struct acpi_ec *ec) { return test_bit(EC_FLAGS_STARTED, &ec->flags) && !test_bit(EC_FLAGS_STOPPED, &ec->flags); } static bool acpi_ec_event_enabled(struct acpi_ec *ec) { /* * There is an OSPM early stage logic. During the early stages * (boot/resume), OSPMs shouldn't enable the event handling, only * the EC transactions are allowed to be performed. */ if (!test_bit(EC_FLAGS_QUERY_ENABLED, &ec->flags)) return false; /* * However, disabling the event handling is experimental for late * stage (suspend), and is controlled by the boot parameter of * "ec_freeze_events": * 1. true: The EC event handling is disabled before entering * the noirq stage. * 2. false: The EC event handling is automatically disabled as * soon as the EC driver is stopped. */ if (ec_freeze_events) return acpi_ec_started(ec); else return test_bit(EC_FLAGS_STARTED, &ec->flags); } static bool acpi_ec_flushed(struct acpi_ec *ec) { return ec->reference_count == 1; } /* -------------------------------------------------------------------------- * EC Registers * -------------------------------------------------------------------------- */ static inline u8 acpi_ec_read_status(struct acpi_ec *ec) { u8 x = inb(ec->command_addr); ec_dbg_raw("EC_SC(R) = 0x%2.2x " "SCI_EVT=%d BURST=%d CMD=%d IBF=%d OBF=%d", x, !!(x & ACPI_EC_FLAG_SCI), !!(x & ACPI_EC_FLAG_BURST), !!(x & ACPI_EC_FLAG_CMD), !!(x & ACPI_EC_FLAG_IBF), !!(x & ACPI_EC_FLAG_OBF)); return x; } static inline u8 acpi_ec_read_data(struct acpi_ec *ec) { u8 x = inb(ec->data_addr); ec->timestamp = jiffies; ec_dbg_raw("EC_DATA(R) = 0x%2.2x", x); return x; } static inline void acpi_ec_write_cmd(struct acpi_ec *ec, u8 command) { ec_dbg_raw("EC_SC(W) = 0x%2.2x", command); outb(command, ec->command_addr); ec->timestamp = jiffies; } static inline void acpi_ec_write_data(struct acpi_ec *ec, u8 data) { ec_dbg_raw("EC_DATA(W) = 0x%2.2x", data); outb(data, ec->data_addr); ec->timestamp = jiffies; } #if defined(DEBUG) || defined(CONFIG_DYNAMIC_DEBUG) static const char *acpi_ec_cmd_string(u8 cmd) { switch (cmd) { case 0x80: return "RD_EC"; case 0x81: return "WR_EC"; case 0x82: return "BE_EC"; case 0x83: return "BD_EC"; case 0x84: return "QR_EC"; } return "UNKNOWN"; } #else #define acpi_ec_cmd_string(cmd) "UNDEF" #endif /* -------------------------------------------------------------------------- * GPE Registers * -------------------------------------------------------------------------- */ static inline bool acpi_ec_gpe_status_set(struct acpi_ec *ec) { acpi_event_status gpe_status = 0; (void)acpi_get_gpe_status(NULL, ec->gpe, &gpe_status); return !!(gpe_status & ACPI_EVENT_FLAG_STATUS_SET); } static inline void acpi_ec_enable_gpe(struct acpi_ec *ec, bool open) { if (open) acpi_enable_gpe(NULL, ec->gpe); else { BUG_ON(ec->reference_count < 1); acpi_set_gpe(NULL, ec->gpe, ACPI_GPE_ENABLE); } if (acpi_ec_gpe_status_set(ec)) { /* * On some platforms, EN=1 writes cannot trigger GPE. So * software need to manually trigger a pseudo GPE event on * EN=1 writes. */ ec_dbg_raw("Polling quirk"); advance_transaction(ec, false); } } static inline void acpi_ec_disable_gpe(struct acpi_ec *ec, bool close) { if (close) acpi_disable_gpe(NULL, ec->gpe); else { BUG_ON(ec->reference_count < 1); acpi_set_gpe(NULL, ec->gpe, ACPI_GPE_DISABLE); } } /* -------------------------------------------------------------------------- * Transaction Management * -------------------------------------------------------------------------- */ static void acpi_ec_submit_request(struct acpi_ec *ec) { ec->reference_count++; if (test_bit(EC_FLAGS_EVENT_HANDLER_INSTALLED, &ec->flags) && ec->gpe >= 0 && ec->reference_count == 1) acpi_ec_enable_gpe(ec, true); } static void acpi_ec_complete_request(struct acpi_ec *ec) { bool flushed = false; ec->reference_count--; if (test_bit(EC_FLAGS_EVENT_HANDLER_INSTALLED, &ec->flags) && ec->gpe >= 0 && ec->reference_count == 0) acpi_ec_disable_gpe(ec, true); flushed = acpi_ec_flushed(ec); if (flushed) wake_up(&ec->wait); } static void acpi_ec_mask_events(struct acpi_ec *ec) { if (!test_bit(EC_FLAGS_EVENTS_MASKED, &ec->flags)) { if (ec->gpe >= 0) acpi_ec_disable_gpe(ec, false); else disable_irq_nosync(ec->irq); ec_dbg_drv("Polling enabled"); set_bit(EC_FLAGS_EVENTS_MASKED, &ec->flags); } } static void acpi_ec_unmask_events(struct acpi_ec *ec) { if (test_bit(EC_FLAGS_EVENTS_MASKED, &ec->flags)) { clear_bit(EC_FLAGS_EVENTS_MASKED, &ec->flags); if (ec->gpe >= 0) acpi_ec_enable_gpe(ec, false); else enable_irq(ec->irq); ec_dbg_drv("Polling disabled"); } } /* * acpi_ec_submit_flushable_request() - Increase the reference count unless * the flush operation is not in * progress * @ec: the EC device * * This function must be used before taking a new action that should hold * the reference count. If this function returns false, then the action * must be discarded or it will prevent the flush operation from being * completed. */ static bool acpi_ec_submit_flushable_request(struct acpi_ec *ec) { if (!acpi_ec_started(ec)) return false; acpi_ec_submit_request(ec); return true; } static void acpi_ec_submit_event(struct acpi_ec *ec) { /* * It is safe to mask the events here, because acpi_ec_close_event() * will run at least once after this. */ acpi_ec_mask_events(ec); if (!acpi_ec_event_enabled(ec)) return; if (ec->event_state != EC_EVENT_READY) return; ec_dbg_evt("Command(%s) submitted/blocked", acpi_ec_cmd_string(ACPI_EC_COMMAND_QUERY)); ec->event_state = EC_EVENT_IN_PROGRESS; /* * If events_to_process is greater than 0 at this point, the while () * loop in acpi_ec_event_handler() is still running and incrementing * events_to_process will cause it to invoke acpi_ec_submit_query() once * more, so it is not necessary to queue up the event work to start the * same loop again. */ if (ec->events_to_process++ > 0) return; ec->events_in_progress++; queue_work(ec_wq, &ec->work); } static void acpi_ec_complete_event(struct acpi_ec *ec) { if (ec->event_state == EC_EVENT_IN_PROGRESS) ec->event_state = EC_EVENT_COMPLETE; } static void acpi_ec_close_event(struct acpi_ec *ec) { if (ec->event_state != EC_EVENT_READY) ec_dbg_evt("Command(%s) unblocked", acpi_ec_cmd_string(ACPI_EC_COMMAND_QUERY)); ec->event_state = EC_EVENT_READY; acpi_ec_unmask_events(ec); } static inline void __acpi_ec_enable_event(struct acpi_ec *ec) { if (!test_and_set_bit(EC_FLAGS_QUERY_ENABLED, &ec->flags)) ec_log_drv("event unblocked"); /* * Unconditionally invoke this once after enabling the event * handling mechanism to detect the pending events. */ advance_transaction(ec, false); }