blob: 824f3e85023e5c12557e8da91ec39c6a8ac41fe7 [file] [log] [blame]
Linus Torvalds1da177e2005-04-16 15:20:36 -07001/*
Lv Zhenga8d4fc22015-02-05 16:27:35 +08002 * ec.c - ACPI Embedded Controller Driver (v3)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003 *
Lv Zhenga8d4fc22015-02-05 16:27:35 +08004 * Copyright (C) 2001-2015 Intel Corporation
5 * Author: 2014, 2015 Lv Zheng <lv.zheng@intel.com>
Lv Zheng4a3f6b52014-06-15 08:42:19 +08006 * 2006, 2007 Alexey Starikovskiy <alexey.y.starikovskiy@intel.com>
7 * 2006 Denis Sadykov <denis.m.sadykov@intel.com>
8 * 2004 Luming Yu <luming.yu@intel.com>
9 * 2001, 2002 Andy Grover <andrew.grover@intel.com>
10 * 2001, 2002 Paul Diefenbaugh <paul.s.diefenbaugh@intel.com>
11 * Copyright (C) 2008 Alexey Starikovskiy <astarikovskiy@suse.de>
Linus Torvalds1da177e2005-04-16 15:20:36 -070012 *
13 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
14 *
15 * This program is free software; you can redistribute it and/or modify
16 * it under the terms of the GNU General Public License as published by
17 * the Free Software Foundation; either version 2 of the License, or (at
18 * your option) any later version.
19 *
20 * This program is distributed in the hope that it will be useful, but
21 * WITHOUT ANY WARRANTY; without even the implied warranty of
22 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
23 * General Public License for more details.
24 *
25 * You should have received a copy of the GNU General Public License along
26 * with this program; if not, write to the Free Software Foundation, Inc.,
27 * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
28 *
29 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
30 */
31
Alexey Starikovskiy7c6db4e2008-09-25 21:00:31 +040032/* Uncomment next line to get verbose printout */
Márton Némethd772b3b2008-01-23 22:34:09 -050033/* #define DEBUG */
Lan Tianyu16a26e82013-09-12 03:32:04 -040034#define pr_fmt(fmt) "ACPI : EC: " fmt
Márton Némethd772b3b2008-01-23 22:34:09 -050035
Linus Torvalds1da177e2005-04-16 15:20:36 -070036#include <linux/kernel.h>
37#include <linux/module.h>
38#include <linux/init.h>
39#include <linux/types.h>
40#include <linux/delay.h>
Dmitry Torokhov451566f2005-03-19 01:10:05 -050041#include <linux/interrupt.h>
Alexey Starikovskiy837012e2007-05-29 16:43:02 +040042#include <linux/list.h>
Alexey Starikovskiy7c6db4e2008-09-25 21:00:31 +040043#include <linux/spinlock.h>
Tejun Heo5a0e3ad2010-03-24 17:04:11 +090044#include <linux/slab.h>
Lv Zheng8b484632013-12-03 08:49:16 +080045#include <linux/acpi.h>
Len Browneb27cae2009-07-06 23:40:19 -040046#include <linux/dmi.h>
Lv Zheng8b484632013-12-03 08:49:16 +080047#include <asm/io.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070048
Thomas Renninger1195a092010-07-16 13:11:31 +020049#include "internal.h"
50
Linus Torvalds1da177e2005-04-16 15:20:36 -070051#define ACPI_EC_CLASS "embedded_controller"
Linus Torvalds1da177e2005-04-16 15:20:36 -070052#define ACPI_EC_DEVICE_NAME "Embedded Controller"
53#define ACPI_EC_FILE_INFO "info"
Alexey Starikovskiy837012e2007-05-29 16:43:02 +040054
Denis M. Sadykov703959d2006-09-26 19:50:33 +040055/* EC status register */
Linus Torvalds1da177e2005-04-16 15:20:36 -070056#define ACPI_EC_FLAG_OBF 0x01 /* Output buffer full */
57#define ACPI_EC_FLAG_IBF 0x02 /* Input buffer full */
Lv Zhengdd43de22014-06-15 08:42:42 +080058#define ACPI_EC_FLAG_CMD 0x08 /* Input buffer contains a command */
Dmitry Torokhov451566f2005-03-19 01:10:05 -050059#define ACPI_EC_FLAG_BURST 0x10 /* burst mode */
Linus Torvalds1da177e2005-04-16 15:20:36 -070060#define ACPI_EC_FLAG_SCI 0x20 /* EC-SCI occurred */
Alexey Starikovskiy43509332007-05-29 16:42:57 +040061
Denis M. Sadykov703959d2006-09-26 19:50:33 +040062/* EC commands */
Alexey Starikovskiy3261ff42006-12-07 18:42:17 +030063enum ec_command {
Alexey Starikovskiy6ccedb12006-12-07 18:42:17 +030064 ACPI_EC_COMMAND_READ = 0x80,
65 ACPI_EC_COMMAND_WRITE = 0x81,
66 ACPI_EC_BURST_ENABLE = 0x82,
67 ACPI_EC_BURST_DISABLE = 0x83,
68 ACPI_EC_COMMAND_QUERY = 0x84,
Alexey Starikovskiy3261ff42006-12-07 18:42:17 +030069};
Alexey Starikovskiy837012e2007-05-29 16:43:02 +040070
Alexey Starikovskiy5c406412006-12-07 18:42:16 +030071#define ACPI_EC_DELAY 500 /* Wait 500ms max. during EC ops */
Denis M. Sadykov703959d2006-09-26 19:50:33 +040072#define ACPI_EC_UDELAY_GLK 1000 /* Wait 1ms max. to get global lock */
Lv Zhengd8d031a2015-05-15 14:16:42 +080073#define ACPI_EC_UDELAY_POLL 550 /* Wait 1ms for EC transaction polling */
Kieran Clancyad332c82014-03-01 00:42:28 +103074#define ACPI_EC_CLEAR_MAX 100 /* Maximum number of events to query
75 * when trying to clear the EC */
Denis M. Sadykov703959d2006-09-26 19:50:33 +040076
Alexey Starikovskiy080e4122007-10-22 14:18:30 +040077enum {
Rafael J. Wysocki37d11392015-02-11 17:35:05 +010078 EC_FLAGS_QUERY_PENDING, /* Query is pending */
Rafael J. Wysockif6bb13a2010-03-04 01:52:58 +010079 EC_FLAGS_HANDLERS_INSTALLED, /* Handlers for GPE and
Alexey Starikovskiy7c6db4e2008-09-25 21:00:31 +040080 * OpReg are installed */
Lv Zhengad479e72015-02-06 08:57:52 +080081 EC_FLAGS_STARTED, /* Driver is started */
82 EC_FLAGS_STOPPED, /* Driver is stopped */
Lv Zhenge1d4d902015-02-06 08:58:05 +080083 EC_FLAGS_COMMAND_STORM, /* GPE storms occurred to the
84 * current command processing */
Linus Torvalds1da177e2005-04-16 15:20:36 -070085};
Denis M. Sadykov6ffb2212006-09-26 19:50:33 +040086
Lv Zhengf92fca02014-06-15 08:41:35 +080087#define ACPI_EC_COMMAND_POLL 0x01 /* Available for command byte */
88#define ACPI_EC_COMMAND_COMPLETE 0x02 /* Completed last byte */
89
Thomas Renninger7a18e962010-10-21 18:24:57 +020090/* ec.c is compiled in acpi namespace so this shows up as acpi.ec_delay param */
91static unsigned int ec_delay __read_mostly = ACPI_EC_DELAY;
92module_param(ec_delay, uint, 0644);
93MODULE_PARM_DESC(ec_delay, "Timeout(ms) waited until an EC command completes");
94
Lv Zheng15de6032015-05-15 14:16:48 +080095static bool ec_busy_polling __read_mostly;
96module_param(ec_busy_polling, bool, 0644);
97MODULE_PARM_DESC(ec_busy_polling, "Use busy polling to advance EC transaction");
98
99static unsigned int ec_polling_guard __read_mostly = ACPI_EC_UDELAY_POLL;
100module_param(ec_polling_guard, uint, 0644);
101MODULE_PARM_DESC(ec_polling_guard, "Guard time(us) between EC accesses in polling modes");
102
Feng Tanga520d522012-09-28 15:22:00 +0800103/*
104 * If the number of false interrupts per one transaction exceeds
105 * this threshold, will think there is a GPE storm happened and
106 * will disable the GPE for normal transaction.
107 */
108static unsigned int ec_storm_threshold __read_mostly = 8;
109module_param(ec_storm_threshold, uint, 0644);
110MODULE_PARM_DESC(ec_storm_threshold, "Maxim false GPE numbers not considered as GPE storm");
111
Alexey Starikovskiy837012e2007-05-29 16:43:02 +0400112struct acpi_ec_query_handler {
113 struct list_head node;
114 acpi_ec_query_func func;
115 acpi_handle handle;
116 void *data;
117 u8 query_bit;
Lv Zheng01305d42015-01-14 19:28:28 +0800118 struct kref kref;
Alexey Starikovskiy837012e2007-05-29 16:43:02 +0400119};
120
Alexey Starikovskiy84632002008-09-26 00:54:28 +0400121struct transaction {
Alexey Starikovskiy7c6db4e2008-09-25 21:00:31 +0400122 const u8 *wdata;
123 u8 *rdata;
124 unsigned short irq_count;
Alexey Starikovskiy84632002008-09-26 00:54:28 +0400125 u8 command;
Alexey Starikovskiya2f93ae2008-11-12 01:40:19 +0300126 u8 wi;
127 u8 ri;
Alexey Starikovskiy7c6db4e2008-09-25 21:00:31 +0400128 u8 wlen;
129 u8 rlen;
Lv Zhengf92fca02014-06-15 08:41:35 +0800130 u8 flags;
Alexey Starikovskiy7c6db4e2008-09-25 21:00:31 +0400131};
132
Lv Zheng550b3aac2015-01-14 19:28:53 +0800133static int acpi_ec_query(struct acpi_ec *ec, u8 *data);
Lv Zhengca37bfd2015-02-05 16:27:22 +0800134static void advance_transaction(struct acpi_ec *ec);
Lv Zheng74443bb2015-01-14 19:28:47 +0800135
Thomas Renninger1195a092010-07-16 13:11:31 +0200136struct acpi_ec *boot_ec, *first_ec;
137EXPORT_SYMBOL(first_ec);
Denis M. Sadykov703959d2006-09-26 19:50:33 +0400138
Alexey Starikovskiy0adf3c72009-10-02 20:21:33 +0400139static int EC_FLAGS_VALIDATE_ECDT; /* ASUStec ECDTs need to be validated */
Alexey Starikovskiy478fa032009-10-02 20:21:40 +0400140static int EC_FLAGS_SKIP_DSDT_SCAN; /* Not all BIOS survive early DSDT scan */
Kieran Clancyad332c82014-03-01 00:42:28 +1030141static int EC_FLAGS_CLEAR_ON_RESUME; /* Needs acpi_ec_clear() on boot/resume */
Lv Zheng79149002014-10-29 11:33:49 +0800142static int EC_FLAGS_QUERY_HANDSHAKE; /* Needs QR_EC issued when SCI_EVT set */
Alexey Starikovskiy5423a0c2009-02-21 12:18:13 -0500143
Linus Torvalds1da177e2005-04-16 15:20:36 -0700144/* --------------------------------------------------------------------------
Lv Zheng3535a3c2015-02-27 14:48:15 +0800145 * Logging/Debugging
146 * -------------------------------------------------------------------------- */
147
148/*
149 * Splitters used by the developers to track the boundary of the EC
150 * handling processes.
151 */
152#ifdef DEBUG
153#define EC_DBG_SEP " "
154#define EC_DBG_DRV "+++++"
155#define EC_DBG_STM "====="
156#define EC_DBG_REQ "*****"
157#define EC_DBG_EVT "#####"
158#else
159#define EC_DBG_SEP ""
160#define EC_DBG_DRV
161#define EC_DBG_STM
162#define EC_DBG_REQ
163#define EC_DBG_EVT
164#endif
165
166#define ec_log_raw(fmt, ...) \
167 pr_info(fmt "\n", ##__VA_ARGS__)
168#define ec_dbg_raw(fmt, ...) \
169 pr_debug(fmt "\n", ##__VA_ARGS__)
170#define ec_log(filter, fmt, ...) \
171 ec_log_raw(filter EC_DBG_SEP fmt EC_DBG_SEP filter, ##__VA_ARGS__)
172#define ec_dbg(filter, fmt, ...) \
173 ec_dbg_raw(filter EC_DBG_SEP fmt EC_DBG_SEP filter, ##__VA_ARGS__)
174
175#define ec_log_drv(fmt, ...) \
176 ec_log(EC_DBG_DRV, fmt, ##__VA_ARGS__)
177#define ec_dbg_drv(fmt, ...) \
178 ec_dbg(EC_DBG_DRV, fmt, ##__VA_ARGS__)
179#define ec_dbg_stm(fmt, ...) \
180 ec_dbg(EC_DBG_STM, fmt, ##__VA_ARGS__)
181#define ec_dbg_req(fmt, ...) \
182 ec_dbg(EC_DBG_REQ, fmt, ##__VA_ARGS__)
183#define ec_dbg_evt(fmt, ...) \
184 ec_dbg(EC_DBG_EVT, fmt, ##__VA_ARGS__)
Lv Zheng770970f2015-02-27 14:48:24 +0800185#define ec_dbg_ref(ec, fmt, ...) \
186 ec_dbg_raw("%lu: " fmt, ec->reference_count, ## __VA_ARGS__)
Lv Zheng3535a3c2015-02-27 14:48:15 +0800187
188/* --------------------------------------------------------------------------
Lv Zhengad479e72015-02-06 08:57:52 +0800189 * Device Flags
190 * -------------------------------------------------------------------------- */
191
192static bool acpi_ec_started(struct acpi_ec *ec)
193{
194 return test_bit(EC_FLAGS_STARTED, &ec->flags) &&
195 !test_bit(EC_FLAGS_STOPPED, &ec->flags);
196}
197
Lv Zheng9887d222015-02-06 08:57:59 +0800198static bool acpi_ec_flushed(struct acpi_ec *ec)
199{
200 return ec->reference_count == 1;
201}
202
Lv Zhengad479e72015-02-06 08:57:52 +0800203/* --------------------------------------------------------------------------
Lv Zhengca37bfd2015-02-05 16:27:22 +0800204 * EC Registers
Lv Zheng7a73e602014-10-14 14:24:01 +0800205 * -------------------------------------------------------------------------- */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700206
Denis M. Sadykov6ffb2212006-09-26 19:50:33 +0400207static inline u8 acpi_ec_read_status(struct acpi_ec *ec)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700208{
Márton Németh3ebe08a2007-11-21 03:23:26 +0300209 u8 x = inb(ec->command_addr);
Lv Zheng7a73e602014-10-14 14:24:01 +0800210
Lv Zheng3535a3c2015-02-27 14:48:15 +0800211 ec_dbg_raw("EC_SC(R) = 0x%2.2x "
212 "SCI_EVT=%d BURST=%d CMD=%d IBF=%d OBF=%d",
213 x,
214 !!(x & ACPI_EC_FLAG_SCI),
215 !!(x & ACPI_EC_FLAG_BURST),
216 !!(x & ACPI_EC_FLAG_CMD),
217 !!(x & ACPI_EC_FLAG_IBF),
218 !!(x & ACPI_EC_FLAG_OBF));
Márton Németh3ebe08a2007-11-21 03:23:26 +0300219 return x;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700220}
221
Denis M. Sadykov6ffb2212006-09-26 19:50:33 +0400222static inline u8 acpi_ec_read_data(struct acpi_ec *ec)
Denis M. Sadykov703959d2006-09-26 19:50:33 +0400223{
Márton Németh3ebe08a2007-11-21 03:23:26 +0300224 u8 x = inb(ec->data_addr);
Lv Zheng7a73e602014-10-14 14:24:01 +0800225
Lv Zhengd8d031a2015-05-15 14:16:42 +0800226 ec->timestamp = jiffies;
Lv Zheng3535a3c2015-02-27 14:48:15 +0800227 ec_dbg_raw("EC_DATA(R) = 0x%2.2x", x);
Alexey Starikovskiy7c6db4e2008-09-25 21:00:31 +0400228 return x;
Denis M. Sadykov703959d2006-09-26 19:50:33 +0400229}
230
Denis M. Sadykov6ffb2212006-09-26 19:50:33 +0400231static inline void acpi_ec_write_cmd(struct acpi_ec *ec, u8 command)
Denis M. Sadykov703959d2006-09-26 19:50:33 +0400232{
Lv Zheng3535a3c2015-02-27 14:48:15 +0800233 ec_dbg_raw("EC_SC(W) = 0x%2.2x", command);
Denis M. Sadykov6ffb2212006-09-26 19:50:33 +0400234 outb(command, ec->command_addr);
Lv Zhengd8d031a2015-05-15 14:16:42 +0800235 ec->timestamp = jiffies;
Denis M. Sadykov703959d2006-09-26 19:50:33 +0400236}
237
Denis M. Sadykov6ffb2212006-09-26 19:50:33 +0400238static inline void acpi_ec_write_data(struct acpi_ec *ec, u8 data)
Denis M. Sadykov703959d2006-09-26 19:50:33 +0400239{
Lv Zheng3535a3c2015-02-27 14:48:15 +0800240 ec_dbg_raw("EC_DATA(W) = 0x%2.2x", data);
Denis M. Sadykov6ffb2212006-09-26 19:50:33 +0400241 outb(data, ec->data_addr);
Lv Zhengd8d031a2015-05-15 14:16:42 +0800242 ec->timestamp = jiffies;
Denis M. Sadykov703959d2006-09-26 19:50:33 +0400243}
244
Lv Zhenge34c0e22014-10-14 14:23:49 +0800245#ifdef DEBUG
246static const char *acpi_ec_cmd_string(u8 cmd)
247{
248 switch (cmd) {
249 case 0x80:
250 return "RD_EC";
251 case 0x81:
252 return "WR_EC";
253 case 0x82:
254 return "BE_EC";
255 case 0x83:
256 return "BD_EC";
257 case 0x84:
258 return "QR_EC";
259 }
260 return "UNKNOWN";
261}
262#else
263#define acpi_ec_cmd_string(cmd) "UNDEF"
264#endif
265
Lv Zhengca37bfd2015-02-05 16:27:22 +0800266/* --------------------------------------------------------------------------
267 * GPE Registers
268 * -------------------------------------------------------------------------- */
269
270static inline bool acpi_ec_is_gpe_raised(struct acpi_ec *ec)
271{
272 acpi_event_status gpe_status = 0;
273
274 (void)acpi_get_gpe_status(NULL, ec->gpe, &gpe_status);
Lv Zheng7c0b2592015-05-15 14:16:17 +0800275 return (gpe_status & ACPI_EVENT_FLAG_STATUS_SET) ? true : false;
Lv Zhengca37bfd2015-02-05 16:27:22 +0800276}
277
278static inline void acpi_ec_enable_gpe(struct acpi_ec *ec, bool open)
279{
280 if (open)
281 acpi_enable_gpe(NULL, ec->gpe);
Lv Zhenge1d4d902015-02-06 08:58:05 +0800282 else {
283 BUG_ON(ec->reference_count < 1);
Lv Zhengca37bfd2015-02-05 16:27:22 +0800284 acpi_set_gpe(NULL, ec->gpe, ACPI_GPE_ENABLE);
Lv Zhenge1d4d902015-02-06 08:58:05 +0800285 }
Lv Zhengca37bfd2015-02-05 16:27:22 +0800286 if (acpi_ec_is_gpe_raised(ec)) {
287 /*
288 * On some platforms, EN=1 writes cannot trigger GPE. So
289 * software need to manually trigger a pseudo GPE event on
290 * EN=1 writes.
291 */
Lv Zheng3535a3c2015-02-27 14:48:15 +0800292 ec_dbg_raw("Polling quirk");
Lv Zhengca37bfd2015-02-05 16:27:22 +0800293 advance_transaction(ec);
294 }
295}
296
297static inline void acpi_ec_disable_gpe(struct acpi_ec *ec, bool close)
298{
299 if (close)
300 acpi_disable_gpe(NULL, ec->gpe);
Lv Zhenge1d4d902015-02-06 08:58:05 +0800301 else {
302 BUG_ON(ec->reference_count < 1);
Lv Zhengca37bfd2015-02-05 16:27:22 +0800303 acpi_set_gpe(NULL, ec->gpe, ACPI_GPE_DISABLE);
Lv Zhenge1d4d902015-02-06 08:58:05 +0800304 }
Lv Zhengca37bfd2015-02-05 16:27:22 +0800305}
306
307static inline void acpi_ec_clear_gpe(struct acpi_ec *ec)
308{
309 /*
310 * GPE STS is a W1C register, which means:
311 * 1. Software can clear it without worrying about clearing other
312 * GPEs' STS bits when the hardware sets them in parallel.
313 * 2. As long as software can ensure only clearing it when it is
314 * set, hardware won't set it in parallel.
315 * So software can clear GPE in any contexts.
316 * Warning: do not move the check into advance_transaction() as the
317 * EC commands will be sent without GPE raised.
318 */
319 if (!acpi_ec_is_gpe_raised(ec))
320 return;
321 acpi_clear_gpe(NULL, ec->gpe);
322}
323
324/* --------------------------------------------------------------------------
325 * Transaction Management
326 * -------------------------------------------------------------------------- */
327
Lv Zheng9887d222015-02-06 08:57:59 +0800328static void acpi_ec_submit_request(struct acpi_ec *ec)
329{
330 ec->reference_count++;
331 if (ec->reference_count == 1)
332 acpi_ec_enable_gpe(ec, true);
333}
334
335static void acpi_ec_complete_request(struct acpi_ec *ec)
336{
337 bool flushed = false;
338
339 ec->reference_count--;
340 if (ec->reference_count == 0)
341 acpi_ec_disable_gpe(ec, true);
342 flushed = acpi_ec_flushed(ec);
343 if (flushed)
344 wake_up(&ec->wait);
345}
346
Lv Zhenge1d4d902015-02-06 08:58:05 +0800347static void acpi_ec_set_storm(struct acpi_ec *ec, u8 flag)
348{
349 if (!test_bit(flag, &ec->flags)) {
350 acpi_ec_disable_gpe(ec, false);
Lv Zheng3535a3c2015-02-27 14:48:15 +0800351 ec_dbg_drv("Polling enabled");
Lv Zhenge1d4d902015-02-06 08:58:05 +0800352 set_bit(flag, &ec->flags);
353 }
354}
355
356static void acpi_ec_clear_storm(struct acpi_ec *ec, u8 flag)
357{
358 if (test_bit(flag, &ec->flags)) {
359 clear_bit(flag, &ec->flags);
360 acpi_ec_enable_gpe(ec, false);
Lv Zheng3535a3c2015-02-27 14:48:15 +0800361 ec_dbg_drv("Polling disabled");
Lv Zhenge1d4d902015-02-06 08:58:05 +0800362 }
363}
364
Lv Zheng9887d222015-02-06 08:57:59 +0800365/*
366 * acpi_ec_submit_flushable_request() - Increase the reference count unless
367 * the flush operation is not in
368 * progress
369 * @ec: the EC device
370 *
371 * This function must be used before taking a new action that should hold
372 * the reference count. If this function returns false, then the action
373 * must be discarded or it will prevent the flush operation from being
374 * completed.
375 */
Rafael J. Wysocki37d11392015-02-11 17:35:05 +0100376static bool acpi_ec_submit_flushable_request(struct acpi_ec *ec)
Lv Zheng9887d222015-02-06 08:57:59 +0800377{
Rafael J. Wysocki37d11392015-02-11 17:35:05 +0100378 if (!acpi_ec_started(ec))
379 return false;
Lv Zheng9887d222015-02-06 08:57:59 +0800380 acpi_ec_submit_request(ec);
381 return true;
382}
383
Rafael J. Wysocki37d11392015-02-11 17:35:05 +0100384static void acpi_ec_submit_query(struct acpi_ec *ec)
Lv Zheng74443bb2015-01-14 19:28:47 +0800385{
Rafael J. Wysocki37d11392015-02-11 17:35:05 +0100386 if (!test_and_set_bit(EC_FLAGS_QUERY_PENDING, &ec->flags)) {
Lv Zheng9d8993b2015-06-11 13:21:32 +0800387 ec_dbg_evt("Command(%s) submitted/blocked",
388 acpi_ec_cmd_string(ACPI_EC_COMMAND_QUERY));
389 ec->nr_pending_queries++;
Lv Zheng74443bb2015-01-14 19:28:47 +0800390 schedule_work(&ec->work);
Lv Zhengf252cb02015-02-06 08:58:10 +0800391 }
Lv Zhengf252cb02015-02-06 08:58:10 +0800392}
393
Rafael J. Wysocki37d11392015-02-11 17:35:05 +0100394static void acpi_ec_complete_query(struct acpi_ec *ec)
Lv Zhengf252cb02015-02-06 08:58:10 +0800395{
Lv Zhengf8b8eb72015-06-11 13:21:23 +0800396 if (test_bit(EC_FLAGS_QUERY_PENDING, &ec->flags)) {
Rafael J. Wysocki37d11392015-02-11 17:35:05 +0100397 clear_bit(EC_FLAGS_QUERY_PENDING, &ec->flags);
Lv Zheng9d8993b2015-06-11 13:21:32 +0800398 ec_dbg_evt("Command(%s) unblocked",
399 acpi_ec_cmd_string(ACPI_EC_COMMAND_QUERY));
Lv Zheng74443bb2015-01-14 19:28:47 +0800400 }
401}
402
Lv Zhengd8d031a2015-05-15 14:16:42 +0800403static int ec_transaction_polled(struct acpi_ec *ec)
404{
405 unsigned long flags;
406 int ret = 0;
407
408 spin_lock_irqsave(&ec->lock, flags);
409 if (ec->curr && (ec->curr->flags & ACPI_EC_COMMAND_POLL))
410 ret = 1;
411 spin_unlock_irqrestore(&ec->lock, flags);
412 return ret;
413}
414
Lv Zhengf92fca02014-06-15 08:41:35 +0800415static int ec_transaction_completed(struct acpi_ec *ec)
Denis M. Sadykov6ffb2212006-09-26 19:50:33 +0400416{
Alexey Starikovskiy7c6db4e2008-09-25 21:00:31 +0400417 unsigned long flags;
418 int ret = 0;
Lv Zheng7a73e602014-10-14 14:24:01 +0800419
Feng Tangf351d022012-10-23 01:29:27 +0200420 spin_lock_irqsave(&ec->lock, flags);
Lv Zhengc0d65342014-06-15 08:42:07 +0800421 if (ec->curr && (ec->curr->flags & ACPI_EC_COMMAND_COMPLETE))
Alexey Starikovskiy7c6db4e2008-09-25 21:00:31 +0400422 ret = 1;
Feng Tangf351d022012-10-23 01:29:27 +0200423 spin_unlock_irqrestore(&ec->lock, flags);
Alexey Starikovskiy7c6db4e2008-09-25 21:00:31 +0400424 return ret;
425}
Denis M. Sadykov7c6db5e2006-09-26 19:50:33 +0400426
Lv Zhengf8b8eb72015-06-11 13:21:23 +0800427static inline void ec_transaction_transition(struct acpi_ec *ec, unsigned long flag)
428{
429 ec->curr->flags |= flag;
430 if (ec->curr->command == ACPI_EC_COMMAND_QUERY) {
431 if (flag == ACPI_EC_COMMAND_POLL)
432 acpi_ec_complete_query(ec);
433 }
434}
435
Lv Zheng0c788082015-01-14 19:28:22 +0800436static void advance_transaction(struct acpi_ec *ec)
Alexey Starikovskiy7c6db4e2008-09-25 21:00:31 +0400437{
Puneet Kumar36b15872013-11-15 11:41:29 -0800438 struct transaction *t;
Lv Zheng66b42b72014-06-15 08:41:17 +0800439 u8 status;
Lv Zhengc0d65342014-06-15 08:42:07 +0800440 bool wakeup = false;
Feng Tangb76b51b2012-10-23 01:29:38 +0200441
Lv Zheng3535a3c2015-02-27 14:48:15 +0800442 ec_dbg_stm("%s (%d)", in_interrupt() ? "IRQ" : "TASK",
443 smp_processor_id());
Lv Zhengca37bfd2015-02-05 16:27:22 +0800444 /*
445 * By always clearing STS before handling all indications, we can
446 * ensure a hardware STS 0->1 change after this clearing can always
447 * trigger a GPE interrupt.
448 */
449 acpi_ec_clear_gpe(ec);
Lv Zheng66b42b72014-06-15 08:41:17 +0800450 status = acpi_ec_read_status(ec);
Puneet Kumar36b15872013-11-15 11:41:29 -0800451 t = ec->curr;
Feng Tangb76b51b2012-10-23 01:29:38 +0200452 if (!t)
Lv Zhengf92fca02014-06-15 08:41:35 +0800453 goto err;
454 if (t->flags & ACPI_EC_COMMAND_POLL) {
455 if (t->wlen > t->wi) {
456 if ((status & ACPI_EC_FLAG_IBF) == 0)
457 acpi_ec_write_data(ec, t->wdata[t->wi++]);
458 else
459 goto err;
460 } else if (t->rlen > t->ri) {
461 if ((status & ACPI_EC_FLAG_OBF) == 1) {
462 t->rdata[t->ri++] = acpi_ec_read_data(ec);
Lv Zhengc0d65342014-06-15 08:42:07 +0800463 if (t->rlen == t->ri) {
Lv Zhengf8b8eb72015-06-11 13:21:23 +0800464 ec_transaction_transition(ec, ACPI_EC_COMMAND_COMPLETE);
Lv Zheng3afcf2e2014-08-21 14:41:13 +0800465 if (t->command == ACPI_EC_COMMAND_QUERY)
Lv Zheng9d8993b2015-06-11 13:21:32 +0800466 ec_dbg_evt("Command(%s) completed by hardware",
467 acpi_ec_cmd_string(ACPI_EC_COMMAND_QUERY));
Lv Zhengc0d65342014-06-15 08:42:07 +0800468 wakeup = true;
469 }
Lv Zhengf92fca02014-06-15 08:41:35 +0800470 } else
471 goto err;
472 } else if (t->wlen == t->wi &&
Lv Zhengc0d65342014-06-15 08:42:07 +0800473 (status & ACPI_EC_FLAG_IBF) == 0) {
Lv Zhengf8b8eb72015-06-11 13:21:23 +0800474 ec_transaction_transition(ec, ACPI_EC_COMMAND_COMPLETE);
Lv Zhengc0d65342014-06-15 08:42:07 +0800475 wakeup = true;
476 }
Lv Zheng0c788082015-01-14 19:28:22 +0800477 goto out;
Lv Zhengf92fca02014-06-15 08:41:35 +0800478 } else {
Lv Zheng79149002014-10-29 11:33:49 +0800479 if (EC_FLAGS_QUERY_HANDSHAKE &&
480 !(status & ACPI_EC_FLAG_SCI) &&
Lv Zheng3afcf2e2014-08-21 14:41:13 +0800481 (t->command == ACPI_EC_COMMAND_QUERY)) {
Lv Zhengf8b8eb72015-06-11 13:21:23 +0800482 ec_transaction_transition(ec, ACPI_EC_COMMAND_POLL);
Lv Zheng3afcf2e2014-08-21 14:41:13 +0800483 t->rdata[t->ri++] = 0x00;
Lv Zhengf8b8eb72015-06-11 13:21:23 +0800484 ec_transaction_transition(ec, ACPI_EC_COMMAND_COMPLETE);
Lv Zheng9d8993b2015-06-11 13:21:32 +0800485 ec_dbg_evt("Command(%s) completed by software",
486 acpi_ec_cmd_string(ACPI_EC_COMMAND_QUERY));
Lv Zheng3afcf2e2014-08-21 14:41:13 +0800487 wakeup = true;
488 } else if ((status & ACPI_EC_FLAG_IBF) == 0) {
Lv Zhengf92fca02014-06-15 08:41:35 +0800489 acpi_ec_write_cmd(ec, t->command);
Lv Zhengf8b8eb72015-06-11 13:21:23 +0800490 ec_transaction_transition(ec, ACPI_EC_COMMAND_POLL);
Alexey Starikovskiy7c6db4e2008-09-25 21:00:31 +0400491 } else
Alexey Starikovskiydd15f8c2008-11-08 21:42:30 +0300492 goto err;
Lv Zheng0c788082015-01-14 19:28:22 +0800493 goto out;
Lv Zhengf92fca02014-06-15 08:41:35 +0800494 }
Alexey Starikovskiydd15f8c2008-11-08 21:42:30 +0300495err:
Feng Tanga3cd8d22012-10-23 01:30:12 +0200496 /*
497 * If SCI bit is set, then don't think it's a false IRQ
498 * otherwise will take a not handled IRQ as a false one.
499 */
Lv Zhengf92fca02014-06-15 08:41:35 +0800500 if (!(status & ACPI_EC_FLAG_SCI)) {
Lv Zhenge1d4d902015-02-06 08:58:05 +0800501 if (in_interrupt() && t) {
502 if (t->irq_count < ec_storm_threshold)
503 ++t->irq_count;
504 /* Allow triggering on 0 threshold */
505 if (t->irq_count == ec_storm_threshold)
506 acpi_ec_set_storm(ec, EC_FLAGS_COMMAND_STORM);
507 }
Lv Zhengf92fca02014-06-15 08:41:35 +0800508 }
Lv Zheng0c788082015-01-14 19:28:22 +0800509out:
Lv Zheng74443bb2015-01-14 19:28:47 +0800510 if (status & ACPI_EC_FLAG_SCI)
Rafael J. Wysocki37d11392015-02-11 17:35:05 +0100511 acpi_ec_submit_query(ec);
Lv Zheng0c788082015-01-14 19:28:22 +0800512 if (wakeup && in_interrupt())
513 wake_up(&ec->wait);
Lv Zhengf92fca02014-06-15 08:41:35 +0800514}
Feng Tanga3cd8d22012-10-23 01:30:12 +0200515
Lv Zhengf92fca02014-06-15 08:41:35 +0800516static void start_transaction(struct acpi_ec *ec)
517{
518 ec->curr->irq_count = ec->curr->wi = ec->curr->ri = 0;
519 ec->curr->flags = 0;
Lv Zhengd8d031a2015-05-15 14:16:42 +0800520}
521
522static int ec_guard(struct acpi_ec *ec)
523{
Lv Zheng15de6032015-05-15 14:16:48 +0800524 unsigned long guard = usecs_to_jiffies(ec_polling_guard);
Lv Zhengd8d031a2015-05-15 14:16:42 +0800525 unsigned long timeout = ec->timestamp + guard;
526
527 do {
Lv Zheng15de6032015-05-15 14:16:48 +0800528 if (ec_busy_polling) {
Lv Zhengd8d031a2015-05-15 14:16:42 +0800529 /* Perform busy polling */
530 if (ec_transaction_completed(ec))
531 return 0;
532 udelay(jiffies_to_usecs(guard));
533 } else {
534 /*
535 * Perform wait polling
536 *
537 * The following check is there to keep the old
538 * logic - no inter-transaction guarding for the
539 * wait polling mode.
540 */
541 if (!ec_transaction_polled(ec))
542 break;
543 if (wait_event_timeout(ec->wait,
544 ec_transaction_completed(ec),
545 guard))
546 return 0;
547 }
548 /* Guard the register accesses for the polling modes */
549 } while (time_before(jiffies, timeout));
550 return -ETIME;
Alexey Starikovskiy7c6db4e2008-09-25 21:00:31 +0400551}
552
Alexey Starikovskiy7c6db4e2008-09-25 21:00:31 +0400553static int ec_poll(struct acpi_ec *ec)
Alexey Starikovskiy845625c2008-03-21 17:07:03 +0300554{
Alexey Starikovskiy2a84cb92009-08-30 03:06:14 +0400555 unsigned long flags;
Lan Tianyu28fe5c82013-05-06 03:23:40 +0000556 int repeat = 5; /* number of command restarts */
Lv Zheng7a73e602014-10-14 14:24:01 +0800557
Alexey Starikovskiy2a84cb92009-08-30 03:06:14 +0400558 while (repeat--) {
559 unsigned long delay = jiffies +
Thomas Renninger7a18e962010-10-21 18:24:57 +0200560 msecs_to_jiffies(ec_delay);
Alexey Starikovskiy2a84cb92009-08-30 03:06:14 +0400561 do {
Lv Zhengd8d031a2015-05-15 14:16:42 +0800562 if (!ec_guard(ec))
563 return 0;
Lv Zhengf92fca02014-06-15 08:41:35 +0800564 spin_lock_irqsave(&ec->lock, flags);
Lv Zhengd8d031a2015-05-15 14:16:42 +0800565 advance_transaction(ec);
Lv Zhengf92fca02014-06-15 08:41:35 +0800566 spin_unlock_irqrestore(&ec->lock, flags);
Alexey Starikovskiy2a84cb92009-08-30 03:06:14 +0400567 } while (time_before(jiffies, delay));
Lan Tianyu16a26e82013-09-12 03:32:04 -0400568 pr_debug("controller reset, restart transaction\n");
Feng Tangf351d022012-10-23 01:29:27 +0200569 spin_lock_irqsave(&ec->lock, flags);
Alexey Starikovskiy2a84cb92009-08-30 03:06:14 +0400570 start_transaction(ec);
Feng Tangf351d022012-10-23 01:29:27 +0200571 spin_unlock_irqrestore(&ec->lock, flags);
Alexey Starikovskiyaf3fd142006-12-07 18:42:16 +0300572 }
Alexey Starikovskiyb77d81b2008-03-21 17:07:15 +0300573 return -ETIME;
Dmitry Torokhov451566f2005-03-19 01:10:05 -0500574}
575
Alexey Starikovskiy84632002008-09-26 00:54:28 +0400576static int acpi_ec_transaction_unlocked(struct acpi_ec *ec,
Alexey Starikovskiy2a84cb92009-08-30 03:06:14 +0400577 struct transaction *t)
Lennart Poetteringd7a76e42006-09-05 12:12:24 -0400578{
Alexey Starikovskiy7c6db4e2008-09-25 21:00:31 +0400579 unsigned long tmp;
Alexey Starikovskiy7c6db4e2008-09-25 21:00:31 +0400580 int ret = 0;
Lv Zheng7a73e602014-10-14 14:24:01 +0800581
Alexey Starikovskiy7c6db4e2008-09-25 21:00:31 +0400582 /* start transaction */
Feng Tangf351d022012-10-23 01:29:27 +0200583 spin_lock_irqsave(&ec->lock, tmp);
Lv Zheng9887d222015-02-06 08:57:59 +0800584 /* Enable GPE for command processing (IBF=0/OBF=1) */
Rafael J. Wysocki37d11392015-02-11 17:35:05 +0100585 if (!acpi_ec_submit_flushable_request(ec)) {
Lv Zhengad479e72015-02-06 08:57:52 +0800586 ret = -EINVAL;
587 goto unlock;
588 }
Lv Zheng770970f2015-02-27 14:48:24 +0800589 ec_dbg_ref(ec, "Increase command");
Alexey Starikovskiy7c6db4e2008-09-25 21:00:31 +0400590 /* following two actions should be kept atomic */
Alexey Starikovskiy84632002008-09-26 00:54:28 +0400591 ec->curr = t;
Lv Zheng3535a3c2015-02-27 14:48:15 +0800592 ec_dbg_req("Command(%s) started", acpi_ec_cmd_string(t->command));
Alexey Starikovskiya2f93ae2008-11-12 01:40:19 +0300593 start_transaction(ec);
Lv Zhengdf9ff912014-10-29 11:33:43 +0800594 spin_unlock_irqrestore(&ec->lock, tmp);
Lv Zhengd8d031a2015-05-15 14:16:42 +0800595
Lv Zhengdf9ff912014-10-29 11:33:43 +0800596 ret = ec_poll(ec);
Lv Zhengd8d031a2015-05-15 14:16:42 +0800597
Lv Zhengdf9ff912014-10-29 11:33:43 +0800598 spin_lock_irqsave(&ec->lock, tmp);
Lv Zhenge1d4d902015-02-06 08:58:05 +0800599 if (t->irq_count == ec_storm_threshold)
600 acpi_ec_clear_storm(ec, EC_FLAGS_COMMAND_STORM);
Lv Zheng3535a3c2015-02-27 14:48:15 +0800601 ec_dbg_req("Command(%s) stopped", acpi_ec_cmd_string(t->command));
Alexey Starikovskiy84632002008-09-26 00:54:28 +0400602 ec->curr = NULL;
Lv Zheng9887d222015-02-06 08:57:59 +0800603 /* Disable GPE for command processing (IBF=0/OBF=1) */
604 acpi_ec_complete_request(ec);
Lv Zheng770970f2015-02-27 14:48:24 +0800605 ec_dbg_ref(ec, "Decrease command");
Lv Zhengad479e72015-02-06 08:57:52 +0800606unlock:
Feng Tangf351d022012-10-23 01:29:27 +0200607 spin_unlock_irqrestore(&ec->lock, tmp);
Alexey Starikovskiy7c6db4e2008-09-25 21:00:31 +0400608 return ret;
Lennart Poetteringd7a76e42006-09-05 12:12:24 -0400609}
610
Alexey Starikovskiy2a84cb92009-08-30 03:06:14 +0400611static int acpi_ec_transaction(struct acpi_ec *ec, struct transaction *t)
Luming Yu45bea152005-07-23 04:08:00 -0400612{
Lennart Poetteringd7a76e42006-09-05 12:12:24 -0400613 int status;
Len Brown50526df2005-08-11 17:32:05 -0400614 u32 glk;
Lv Zheng7a73e602014-10-14 14:24:01 +0800615
Alexey Starikovskiy84632002008-09-26 00:54:28 +0400616 if (!ec || (!t) || (t->wlen && !t->wdata) || (t->rlen && !t->rdata))
Patrick Mocheld550d982006-06-27 00:41:40 -0400617 return -EINVAL;
Alexey Starikovskiy84632002008-09-26 00:54:28 +0400618 if (t->rdata)
619 memset(t->rdata, 0, t->rlen);
Lv Zhengd8d031a2015-05-15 14:16:42 +0800620
Feng Tangf351d022012-10-23 01:29:27 +0200621 mutex_lock(&ec->mutex);
Denis M. Sadykov703959d2006-09-26 19:50:33 +0400622 if (ec->global_lock) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700623 status = acpi_acquire_global_lock(ACPI_EC_UDELAY_GLK, &glk);
Alexey Starikovskiyc24e9122007-02-15 23:16:18 +0300624 if (ACPI_FAILURE(status)) {
Alexey Starikovskiy7c6db4e2008-09-25 21:00:31 +0400625 status = -ENODEV;
626 goto unlock;
Alexey Starikovskiyc24e9122007-02-15 23:16:18 +0300627 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700628 }
Alexey Starikovskiya62e8f12009-12-24 11:34:16 +0300629
Alexey Starikovskiy2a84cb92009-08-30 03:06:14 +0400630 status = acpi_ec_transaction_unlocked(ec, t);
Alexey Starikovskiya62e8f12009-12-24 11:34:16 +0300631
Denis M. Sadykov703959d2006-09-26 19:50:33 +0400632 if (ec->global_lock)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700633 acpi_release_global_lock(glk);
Alexey Starikovskiy7c6db4e2008-09-25 21:00:31 +0400634unlock:
Feng Tangf351d022012-10-23 01:29:27 +0200635 mutex_unlock(&ec->mutex);
Patrick Mocheld550d982006-06-27 00:41:40 -0400636 return status;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700637}
638
Roel Kluin8a383ef2008-12-09 20:45:30 +0100639static int acpi_ec_burst_enable(struct acpi_ec *ec)
Alexey Starikovskiyc45aac42007-03-07 22:28:00 +0300640{
641 u8 d;
Alexey Starikovskiy84632002008-09-26 00:54:28 +0400642 struct transaction t = {.command = ACPI_EC_BURST_ENABLE,
643 .wdata = NULL, .rdata = &d,
644 .wlen = 0, .rlen = 1};
645
Alexey Starikovskiy2a84cb92009-08-30 03:06:14 +0400646 return acpi_ec_transaction(ec, &t);
Alexey Starikovskiyc45aac42007-03-07 22:28:00 +0300647}
648
Roel Kluin8a383ef2008-12-09 20:45:30 +0100649static int acpi_ec_burst_disable(struct acpi_ec *ec)
Alexey Starikovskiyc45aac42007-03-07 22:28:00 +0300650{
Alexey Starikovskiy84632002008-09-26 00:54:28 +0400651 struct transaction t = {.command = ACPI_EC_BURST_DISABLE,
652 .wdata = NULL, .rdata = NULL,
653 .wlen = 0, .rlen = 0};
654
Alexey Starikovskiy7c6db4e2008-09-25 21:00:31 +0400655 return (acpi_ec_read_status(ec) & ACPI_EC_FLAG_BURST) ?
Alexey Starikovskiy2a84cb92009-08-30 03:06:14 +0400656 acpi_ec_transaction(ec, &t) : 0;
Alexey Starikovskiyc45aac42007-03-07 22:28:00 +0300657}
658
Lv Zheng7a73e602014-10-14 14:24:01 +0800659static int acpi_ec_read(struct acpi_ec *ec, u8 address, u8 *data)
Denis M. Sadykov3576cf62006-09-26 19:50:33 +0400660{
661 int result;
662 u8 d;
Alexey Starikovskiy84632002008-09-26 00:54:28 +0400663 struct transaction t = {.command = ACPI_EC_COMMAND_READ,
664 .wdata = &address, .rdata = &d,
665 .wlen = 1, .rlen = 1};
Denis M. Sadykov3576cf62006-09-26 19:50:33 +0400666
Alexey Starikovskiy2a84cb92009-08-30 03:06:14 +0400667 result = acpi_ec_transaction(ec, &t);
Denis M. Sadykov3576cf62006-09-26 19:50:33 +0400668 *data = d;
669 return result;
670}
Denis M. Sadykov6ffb2212006-09-26 19:50:33 +0400671
Denis M. Sadykov3576cf62006-09-26 19:50:33 +0400672static int acpi_ec_write(struct acpi_ec *ec, u8 address, u8 data)
673{
Alexey Starikovskiy6ccedb12006-12-07 18:42:17 +0300674 u8 wdata[2] = { address, data };
Alexey Starikovskiy84632002008-09-26 00:54:28 +0400675 struct transaction t = {.command = ACPI_EC_COMMAND_WRITE,
676 .wdata = wdata, .rdata = NULL,
677 .wlen = 2, .rlen = 0};
678
Alexey Starikovskiy2a84cb92009-08-30 03:06:14 +0400679 return acpi_ec_transaction(ec, &t);
Denis M. Sadykov3576cf62006-09-26 19:50:33 +0400680}
681
Feng Tangb76b51b2012-10-23 01:29:38 +0200682int ec_read(u8 addr, u8 *val)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700683{
Linus Torvalds1da177e2005-04-16 15:20:36 -0700684 int err;
Denis M. Sadykov6ffb2212006-09-26 19:50:33 +0400685 u8 temp_data;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700686
687 if (!first_ec)
688 return -ENODEV;
689
Alexey Starikovskiyd0338792007-03-07 22:28:00 +0300690 err = acpi_ec_read(first_ec, addr, &temp_data);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700691
692 if (!err) {
693 *val = temp_data;
694 return 0;
Lv Zheng7a73e602014-10-14 14:24:01 +0800695 }
696 return err;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700697}
698EXPORT_SYMBOL(ec_read);
699
Len Brown50526df2005-08-11 17:32:05 -0400700int ec_write(u8 addr, u8 val)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700701{
Linus Torvalds1da177e2005-04-16 15:20:36 -0700702 int err;
703
704 if (!first_ec)
705 return -ENODEV;
706
Alexey Starikovskiyd0338792007-03-07 22:28:00 +0300707 err = acpi_ec_write(first_ec, addr, val);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700708
709 return err;
710}
711EXPORT_SYMBOL(ec_write);
712
Randy Dunlap616362d2006-10-27 01:47:34 -0400713int ec_transaction(u8 command,
Lv Zheng7a73e602014-10-14 14:24:01 +0800714 const u8 *wdata, unsigned wdata_len,
715 u8 *rdata, unsigned rdata_len)
Luming Yu45bea152005-07-23 04:08:00 -0400716{
Alexey Starikovskiy84632002008-09-26 00:54:28 +0400717 struct transaction t = {.command = command,
718 .wdata = wdata, .rdata = rdata,
719 .wlen = wdata_len, .rlen = rdata_len};
Lv Zheng7a73e602014-10-14 14:24:01 +0800720
Lennart Poetteringd7a76e42006-09-05 12:12:24 -0400721 if (!first_ec)
722 return -ENODEV;
723
Alexey Starikovskiy2a84cb92009-08-30 03:06:14 +0400724 return acpi_ec_transaction(first_ec, &t);
Luming Yu45bea152005-07-23 04:08:00 -0400725}
Lennart Poetteringab9e43c2006-10-03 22:49:00 -0400726EXPORT_SYMBOL(ec_transaction);
727
Seth Forshee3e2abc52012-01-18 13:44:08 -0600728/* Get the handle to the EC device */
729acpi_handle ec_get_handle(void)
730{
731 if (!first_ec)
732 return NULL;
733 return first_ec->handle;
734}
Seth Forshee3e2abc52012-01-18 13:44:08 -0600735EXPORT_SYMBOL(ec_get_handle);
736
Kieran Clancyad332c82014-03-01 00:42:28 +1030737/*
Kieran Clancy3eba5632014-04-30 00:21:20 +0930738 * Process _Q events that might have accumulated in the EC.
Kieran Clancyad332c82014-03-01 00:42:28 +1030739 * Run with locked ec mutex.
740 */
741static void acpi_ec_clear(struct acpi_ec *ec)
742{
743 int i, status;
744 u8 value = 0;
745
746 for (i = 0; i < ACPI_EC_CLEAR_MAX; i++) {
Lv Zheng550b3aac2015-01-14 19:28:53 +0800747 status = acpi_ec_query(ec, &value);
Kieran Clancyad332c82014-03-01 00:42:28 +1030748 if (status || !value)
749 break;
750 }
751
752 if (unlikely(i == ACPI_EC_CLEAR_MAX))
753 pr_warn("Warning: Maximum of %d stale EC events cleared\n", i);
754 else
755 pr_info("%d stale EC events cleared\n", i);
756}
757
Lv Zhengad479e72015-02-06 08:57:52 +0800758static void acpi_ec_start(struct acpi_ec *ec, bool resuming)
759{
760 unsigned long flags;
761
762 spin_lock_irqsave(&ec->lock, flags);
763 if (!test_and_set_bit(EC_FLAGS_STARTED, &ec->flags)) {
Lv Zheng3535a3c2015-02-27 14:48:15 +0800764 ec_dbg_drv("Starting EC");
Lv Zheng9887d222015-02-06 08:57:59 +0800765 /* Enable GPE for event processing (SCI_EVT=1) */
Lv Zheng770970f2015-02-27 14:48:24 +0800766 if (!resuming) {
Lv Zheng9887d222015-02-06 08:57:59 +0800767 acpi_ec_submit_request(ec);
Lv Zheng770970f2015-02-27 14:48:24 +0800768 ec_dbg_ref(ec, "Increase driver");
769 }
Lv Zheng3535a3c2015-02-27 14:48:15 +0800770 ec_log_drv("EC started");
Lv Zhengad479e72015-02-06 08:57:52 +0800771 }
772 spin_unlock_irqrestore(&ec->lock, flags);
773}
774
Lv Zheng9887d222015-02-06 08:57:59 +0800775static bool acpi_ec_stopped(struct acpi_ec *ec)
776{
777 unsigned long flags;
778 bool flushed;
779
780 spin_lock_irqsave(&ec->lock, flags);
781 flushed = acpi_ec_flushed(ec);
782 spin_unlock_irqrestore(&ec->lock, flags);
783 return flushed;
784}
785
Lv Zhengad479e72015-02-06 08:57:52 +0800786static void acpi_ec_stop(struct acpi_ec *ec, bool suspending)
787{
788 unsigned long flags;
789
790 spin_lock_irqsave(&ec->lock, flags);
791 if (acpi_ec_started(ec)) {
Lv Zheng3535a3c2015-02-27 14:48:15 +0800792 ec_dbg_drv("Stopping EC");
Lv Zhengad479e72015-02-06 08:57:52 +0800793 set_bit(EC_FLAGS_STOPPED, &ec->flags);
Lv Zheng9887d222015-02-06 08:57:59 +0800794 spin_unlock_irqrestore(&ec->lock, flags);
795 wait_event(ec->wait, acpi_ec_stopped(ec));
796 spin_lock_irqsave(&ec->lock, flags);
797 /* Disable GPE for event processing (SCI_EVT=1) */
Lv Zheng770970f2015-02-27 14:48:24 +0800798 if (!suspending) {
Lv Zheng9887d222015-02-06 08:57:59 +0800799 acpi_ec_complete_request(ec);
Lv Zheng770970f2015-02-27 14:48:24 +0800800 ec_dbg_ref(ec, "Decrease driver");
801 }
Lv Zhengad479e72015-02-06 08:57:52 +0800802 clear_bit(EC_FLAGS_STARTED, &ec->flags);
803 clear_bit(EC_FLAGS_STOPPED, &ec->flags);
Lv Zheng3535a3c2015-02-27 14:48:15 +0800804 ec_log_drv("EC stopped");
Lv Zhengad479e72015-02-06 08:57:52 +0800805 }
806 spin_unlock_irqrestore(&ec->lock, flags);
807}
808
Rafael J. Wysockife955682010-04-09 01:40:38 +0200809void acpi_ec_block_transactions(void)
Rafael J. Wysockif6bb13a2010-03-04 01:52:58 +0100810{
811 struct acpi_ec *ec = first_ec;
812
813 if (!ec)
814 return;
815
Feng Tangf351d022012-10-23 01:29:27 +0200816 mutex_lock(&ec->mutex);
Rafael J. Wysockif6bb13a2010-03-04 01:52:58 +0100817 /* Prevent transactions from being carried out */
Lv Zhengad479e72015-02-06 08:57:52 +0800818 acpi_ec_stop(ec, true);
Feng Tangf351d022012-10-23 01:29:27 +0200819 mutex_unlock(&ec->mutex);
Rafael J. Wysockif6bb13a2010-03-04 01:52:58 +0100820}
821
Rafael J. Wysockife955682010-04-09 01:40:38 +0200822void acpi_ec_unblock_transactions(void)
Rafael J. Wysockif6bb13a2010-03-04 01:52:58 +0100823{
824 struct acpi_ec *ec = first_ec;
825
826 if (!ec)
827 return;
828
Rafael J. Wysockif6bb13a2010-03-04 01:52:58 +0100829 /* Allow transactions to be carried out again */
Lv Zhengad479e72015-02-06 08:57:52 +0800830 acpi_ec_start(ec, true);
Kieran Clancyad332c82014-03-01 00:42:28 +1030831
832 if (EC_FLAGS_CLEAR_ON_RESUME)
833 acpi_ec_clear(ec);
Rafael J. Wysockif6bb13a2010-03-04 01:52:58 +0100834}
835
Rafael J. Wysockife955682010-04-09 01:40:38 +0200836void acpi_ec_unblock_transactions_early(void)
Rafael J. Wysockid5a64512010-04-09 01:39:40 +0200837{
838 /*
839 * Allow transactions to happen again (this function is called from
840 * atomic context during wakeup, so we don't need to acquire the mutex).
841 */
842 if (first_ec)
Lv Zhengad479e72015-02-06 08:57:52 +0800843 acpi_ec_start(first_ec, true);
Rafael J. Wysockid5a64512010-04-09 01:39:40 +0200844}
845
Linus Torvalds1da177e2005-04-16 15:20:36 -0700846/* --------------------------------------------------------------------------
847 Event Management
848 -------------------------------------------------------------------------- */
Lv Zheng01305d42015-01-14 19:28:28 +0800849static struct acpi_ec_query_handler *
850acpi_ec_get_query_handler(struct acpi_ec_query_handler *handler)
851{
852 if (handler)
853 kref_get(&handler->kref);
854 return handler;
855}
856
857static void acpi_ec_query_handler_release(struct kref *kref)
858{
859 struct acpi_ec_query_handler *handler =
860 container_of(kref, struct acpi_ec_query_handler, kref);
861
862 kfree(handler);
863}
864
865static void acpi_ec_put_query_handler(struct acpi_ec_query_handler *handler)
866{
867 kref_put(&handler->kref, acpi_ec_query_handler_release);
868}
869
Alexey Starikovskiy837012e2007-05-29 16:43:02 +0400870int acpi_ec_add_query_handler(struct acpi_ec *ec, u8 query_bit,
871 acpi_handle handle, acpi_ec_query_func func,
872 void *data)
873{
874 struct acpi_ec_query_handler *handler =
875 kzalloc(sizeof(struct acpi_ec_query_handler), GFP_KERNEL);
Lv Zheng7a73e602014-10-14 14:24:01 +0800876
Alexey Starikovskiy837012e2007-05-29 16:43:02 +0400877 if (!handler)
878 return -ENOMEM;
879
880 handler->query_bit = query_bit;
881 handler->handle = handle;
882 handler->func = func;
883 handler->data = data;
Feng Tangf351d022012-10-23 01:29:27 +0200884 mutex_lock(&ec->mutex);
Lv Zheng01305d42015-01-14 19:28:28 +0800885 kref_init(&handler->kref);
Alexey Starikovskiy30c08572007-09-26 19:43:22 +0400886 list_add(&handler->node, &ec->list);
Feng Tangf351d022012-10-23 01:29:27 +0200887 mutex_unlock(&ec->mutex);
Alexey Starikovskiy837012e2007-05-29 16:43:02 +0400888 return 0;
889}
Alexey Starikovskiy837012e2007-05-29 16:43:02 +0400890EXPORT_SYMBOL_GPL(acpi_ec_add_query_handler);
891
892void acpi_ec_remove_query_handler(struct acpi_ec *ec, u8 query_bit)
893{
Adrian Bunk1544fdb2007-10-24 18:26:00 +0200894 struct acpi_ec_query_handler *handler, *tmp;
Lv Zheng01305d42015-01-14 19:28:28 +0800895 LIST_HEAD(free_list);
Lv Zheng7a73e602014-10-14 14:24:01 +0800896
Feng Tangf351d022012-10-23 01:29:27 +0200897 mutex_lock(&ec->mutex);
Adrian Bunk1544fdb2007-10-24 18:26:00 +0200898 list_for_each_entry_safe(handler, tmp, &ec->list, node) {
Alexey Starikovskiy837012e2007-05-29 16:43:02 +0400899 if (query_bit == handler->query_bit) {
Lv Zheng01305d42015-01-14 19:28:28 +0800900 list_del_init(&handler->node);
901 list_add(&handler->node, &free_list);
Alexey Starikovskiy837012e2007-05-29 16:43:02 +0400902 }
903 }
Feng Tangf351d022012-10-23 01:29:27 +0200904 mutex_unlock(&ec->mutex);
Chris Bainbridge6b5eab52015-04-22 00:25:36 +0100905 list_for_each_entry_safe(handler, tmp, &free_list, node)
Lv Zheng01305d42015-01-14 19:28:28 +0800906 acpi_ec_put_query_handler(handler);
Alexey Starikovskiy837012e2007-05-29 16:43:02 +0400907}
Alexey Starikovskiy837012e2007-05-29 16:43:02 +0400908EXPORT_SYMBOL_GPL(acpi_ec_remove_query_handler);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700909
Alexey Starikovskiya62e8f12009-12-24 11:34:16 +0300910static void acpi_ec_run(void *cxt)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700911{
Alexey Starikovskiya62e8f12009-12-24 11:34:16 +0300912 struct acpi_ec_query_handler *handler = cxt;
Lv Zheng7a73e602014-10-14 14:24:01 +0800913
Alexey Starikovskiya62e8f12009-12-24 11:34:16 +0300914 if (!handler)
Alexey Starikovskiye41334c2006-12-07 18:42:16 +0300915 return;
Lv Zheng3535a3c2015-02-27 14:48:15 +0800916 ec_dbg_evt("Query(0x%02x) started", handler->query_bit);
Alexey Starikovskiya62e8f12009-12-24 11:34:16 +0300917 if (handler->func)
918 handler->func(handler->data);
919 else if (handler->handle)
920 acpi_evaluate_object(handler->handle, NULL, NULL, NULL);
Lv Zheng3535a3c2015-02-27 14:48:15 +0800921 ec_dbg_evt("Query(0x%02x) stopped", handler->query_bit);
Lv Zheng01305d42015-01-14 19:28:28 +0800922 acpi_ec_put_query_handler(handler);
Alexey Starikovskiya62e8f12009-12-24 11:34:16 +0300923}
924
Lv Zheng550b3aac2015-01-14 19:28:53 +0800925static int acpi_ec_query(struct acpi_ec *ec, u8 *data)
Alexey Starikovskiya62e8f12009-12-24 11:34:16 +0300926{
927 u8 value = 0;
Lv Zhengc2cf5762015-01-14 19:28:33 +0800928 int result;
929 acpi_status status;
Lv Zheng01305d42015-01-14 19:28:28 +0800930 struct acpi_ec_query_handler *handler;
Lv Zheng550b3aac2015-01-14 19:28:53 +0800931 struct transaction t = {.command = ACPI_EC_COMMAND_QUERY,
932 .wdata = NULL, .rdata = &value,
933 .wlen = 0, .rlen = 1};
Kieran Clancy3eba5632014-04-30 00:21:20 +0930934
Lv Zheng550b3aac2015-01-14 19:28:53 +0800935 /*
936 * Query the EC to find out which _Qxx method we need to evaluate.
937 * Note that successful completion of the query causes the ACPI_EC_SCI
938 * bit to be cleared (and thus clearing the interrupt source).
939 */
940 result = acpi_ec_transaction(ec, &t);
Lv Zhengc2cf5762015-01-14 19:28:33 +0800941 if (result)
942 return result;
Lv Zheng550b3aac2015-01-14 19:28:53 +0800943 if (data)
944 *data = value;
945 if (!value)
946 return -ENODATA;
Kieran Clancy3eba5632014-04-30 00:21:20 +0930947
Lv Zheng550b3aac2015-01-14 19:28:53 +0800948 mutex_lock(&ec->mutex);
Alexey Starikovskiy837012e2007-05-29 16:43:02 +0400949 list_for_each_entry(handler, &ec->list, node) {
950 if (value == handler->query_bit) {
951 /* have custom handler for this bit */
Lv Zheng01305d42015-01-14 19:28:28 +0800952 handler = acpi_ec_get_query_handler(handler);
Lv Zheng3535a3c2015-02-27 14:48:15 +0800953 ec_dbg_evt("Query(0x%02x) scheduled",
954 handler->query_bit);
Lv Zhengc2cf5762015-01-14 19:28:33 +0800955 status = acpi_os_execute((handler->func) ?
Alexey Starikovskiyf5347862009-12-30 15:53:03 +0300956 OSL_NOTIFY_HANDLER : OSL_GPE_HANDLER,
Lv Zheng01305d42015-01-14 19:28:28 +0800957 acpi_ec_run, handler);
Lv Zhengc2cf5762015-01-14 19:28:33 +0800958 if (ACPI_FAILURE(status))
959 result = -EBUSY;
960 break;
Alexey Starikovskiy837012e2007-05-29 16:43:02 +0400961 }
962 }
Lv Zheng550b3aac2015-01-14 19:28:53 +0800963 mutex_unlock(&ec->mutex);
Lv Zhengc2cf5762015-01-14 19:28:33 +0800964 return result;
Alexey Starikovskiya62e8f12009-12-24 11:34:16 +0300965}
966
Lv Zheng9d8993b2015-06-11 13:21:32 +0800967static void acpi_ec_event_handler(struct work_struct *work)
Alexey Starikovskiya62e8f12009-12-24 11:34:16 +0300968{
Lv Zheng9d8993b2015-06-11 13:21:32 +0800969 unsigned long flags;
Lv Zheng74443bb2015-01-14 19:28:47 +0800970 struct acpi_ec *ec = container_of(work, struct acpi_ec, work);
Lv Zheng7a73e602014-10-14 14:24:01 +0800971
Lv Zheng9d8993b2015-06-11 13:21:32 +0800972 ec_dbg_evt("Event started");
973
974 spin_lock_irqsave(&ec->lock, flags);
975 while (ec->nr_pending_queries) {
976 spin_unlock_irqrestore(&ec->lock, flags);
977 (void)acpi_ec_query(ec, NULL);
978 spin_lock_irqsave(&ec->lock, flags);
979 ec->nr_pending_queries--;
980 }
981 spin_unlock_irqrestore(&ec->lock, flags);
982
983 ec_dbg_evt("Event stopped");
Luming Yu45bea152005-07-23 04:08:00 -0400984}
Linus Torvalds1da177e2005-04-16 15:20:36 -0700985
Lin Ming8b6cd8a2010-12-13 13:38:46 +0800986static u32 acpi_ec_gpe_handler(acpi_handle gpe_device,
987 u32 gpe_number, void *data)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700988{
Lv Zhengf92fca02014-06-15 08:41:35 +0800989 unsigned long flags;
Alexey Starikovskiy3d02b902007-03-07 22:28:00 +0300990 struct acpi_ec *ec = data;
Lennart Poettering00eb43a2007-05-04 14:16:19 +0200991
Lv Zhengf92fca02014-06-15 08:41:35 +0800992 spin_lock_irqsave(&ec->lock, flags);
Lv Zheng0c788082015-01-14 19:28:22 +0800993 advance_transaction(ec);
Lv Zhengc0d65342014-06-15 08:42:07 +0800994 spin_unlock_irqrestore(&ec->lock, flags);
Lv Zhengca37bfd2015-02-05 16:27:22 +0800995 return ACPI_INTERRUPT_HANDLED;
Alexey Starikovskiy845625c2008-03-21 17:07:03 +0300996}
997
Linus Torvalds1da177e2005-04-16 15:20:36 -0700998/* --------------------------------------------------------------------------
Lv Zheng7a73e602014-10-14 14:24:01 +0800999 * Address Space Management
1000 * -------------------------------------------------------------------------- */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001001
1002static acpi_status
Alexey Starikovskiy5b7734b2007-05-29 16:42:52 +04001003acpi_ec_space_handler(u32 function, acpi_physical_address address,
Alexey Starikovskiydadf28a2010-03-17 13:14:13 -04001004 u32 bits, u64 *value64,
Len Brown50526df2005-08-11 17:32:05 -04001005 void *handler_context, void *region_context)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001006{
Alexey Starikovskiy3d02b902007-03-07 22:28:00 +03001007 struct acpi_ec *ec = handler_context;
Alexey Starikovskiydadf28a2010-03-17 13:14:13 -04001008 int result = 0, i, bytes = bits / 8;
1009 u8 *value = (u8 *)value64;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001010
Linus Torvalds1da177e2005-04-16 15:20:36 -07001011 if ((address > 0xFF) || !value || !handler_context)
Patrick Mocheld550d982006-06-27 00:41:40 -04001012 return AE_BAD_PARAMETER;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001013
Alexey Starikovskiy5b7734b2007-05-29 16:42:52 +04001014 if (function != ACPI_READ && function != ACPI_WRITE)
Patrick Mocheld550d982006-06-27 00:41:40 -04001015 return AE_BAD_PARAMETER;
Alexey Starikovskiy5b7734b2007-05-29 16:42:52 +04001016
Lv Zheng15de6032015-05-15 14:16:48 +08001017 if (ec_busy_polling || bits > 8)
Alexey Starikovskiy6a63b06f2009-08-28 23:29:44 +04001018 acpi_ec_burst_enable(ec);
Alexey Starikovskiyb3b233c2008-01-11 02:42:57 +03001019
Alexey Starikovskiydadf28a2010-03-17 13:14:13 -04001020 for (i = 0; i < bytes; ++i, ++address, ++value)
1021 result = (function == ACPI_READ) ?
1022 acpi_ec_read(ec, address, value) :
1023 acpi_ec_write(ec, address, *value);
Alexey Starikovskiy3e71a872008-01-11 02:42:51 +03001024
Lv Zheng15de6032015-05-15 14:16:48 +08001025 if (ec_busy_polling || bits > 8)
Alexey Starikovskiy6a63b06f2009-08-28 23:29:44 +04001026 acpi_ec_burst_disable(ec);
Alexey Starikovskiyb3b233c2008-01-11 02:42:57 +03001027
Linus Torvalds1da177e2005-04-16 15:20:36 -07001028 switch (result) {
1029 case -EINVAL:
Patrick Mocheld550d982006-06-27 00:41:40 -04001030 return AE_BAD_PARAMETER;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001031 case -ENODEV:
Patrick Mocheld550d982006-06-27 00:41:40 -04001032 return AE_NOT_FOUND;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001033 case -ETIME:
Patrick Mocheld550d982006-06-27 00:41:40 -04001034 return AE_TIME;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001035 default:
Patrick Mocheld550d982006-06-27 00:41:40 -04001036 return AE_OK;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001037 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001038}
1039
Linus Torvalds1da177e2005-04-16 15:20:36 -07001040/* --------------------------------------------------------------------------
Lv Zheng7a73e602014-10-14 14:24:01 +08001041 * Driver Interface
1042 * -------------------------------------------------------------------------- */
1043
Alexey Starikovskiyc0900c32007-03-07 22:28:00 +03001044static acpi_status
1045ec_parse_io_ports(struct acpi_resource *resource, void *context);
1046
Alexey Starikovskiyc0900c32007-03-07 22:28:00 +03001047static struct acpi_ec *make_acpi_ec(void)
1048{
1049 struct acpi_ec *ec = kzalloc(sizeof(struct acpi_ec), GFP_KERNEL);
Lv Zheng7a73e602014-10-14 14:24:01 +08001050
Alexey Starikovskiyc0900c32007-03-07 22:28:00 +03001051 if (!ec)
1052 return NULL;
Rafael J. Wysocki37d11392015-02-11 17:35:05 +01001053 ec->flags = 1 << EC_FLAGS_QUERY_PENDING;
Feng Tangf351d022012-10-23 01:29:27 +02001054 mutex_init(&ec->mutex);
Alexey Starikovskiyc0900c32007-03-07 22:28:00 +03001055 init_waitqueue_head(&ec->wait);
Alexey Starikovskiy837012e2007-05-29 16:43:02 +04001056 INIT_LIST_HEAD(&ec->list);
Feng Tangf351d022012-10-23 01:29:27 +02001057 spin_lock_init(&ec->lock);
Lv Zheng9d8993b2015-06-11 13:21:32 +08001058 INIT_WORK(&ec->work, acpi_ec_event_handler);
Lv Zhengd8d031a2015-05-15 14:16:42 +08001059 ec->timestamp = jiffies;
Alexey Starikovskiyc0900c32007-03-07 22:28:00 +03001060 return ec;
1061}
Linus Torvalds1da177e2005-04-16 15:20:36 -07001062
Alexey Starikovskiy837012e2007-05-29 16:43:02 +04001063static acpi_status
Alexey Starikovskiyc019b192007-08-14 01:03:42 -04001064acpi_ec_register_query_methods(acpi_handle handle, u32 level,
1065 void *context, void **return_value)
1066{
Lin Ming0175d562008-12-16 16:46:12 +08001067 char node_name[5];
1068 struct acpi_buffer buffer = { sizeof(node_name), node_name };
Alexey Starikovskiyc019b192007-08-14 01:03:42 -04001069 struct acpi_ec *ec = context;
1070 int value = 0;
Lin Ming0175d562008-12-16 16:46:12 +08001071 acpi_status status;
1072
1073 status = acpi_get_name(handle, ACPI_SINGLE_NAME, &buffer);
1074
Lv Zheng7a73e602014-10-14 14:24:01 +08001075 if (ACPI_SUCCESS(status) && sscanf(node_name, "_Q%x", &value) == 1)
Alexey Starikovskiyc019b192007-08-14 01:03:42 -04001076 acpi_ec_add_query_handler(ec, value, handle, NULL, NULL);
Alexey Starikovskiyc019b192007-08-14 01:03:42 -04001077 return AE_OK;
1078}
1079
1080static acpi_status
Alexey Starikovskiycd8c93a2007-08-03 17:52:48 -04001081ec_parse_device(acpi_handle handle, u32 Level, void *context, void **retval)
Alexey Starikovskiy837012e2007-05-29 16:43:02 +04001082{
Alexey Starikovskiycd8c93a2007-08-03 17:52:48 -04001083 acpi_status status;
Alexey Starikovskiyd21cf3c2008-11-03 14:26:40 -05001084 unsigned long long tmp = 0;
Alexey Starikovskiycd8c93a2007-08-03 17:52:48 -04001085 struct acpi_ec *ec = context;
Alexey Starikovskiya5032bf2009-04-01 01:33:15 -04001086
1087 /* clear addr values, ec_parse_io_ports depend on it */
1088 ec->command_addr = ec->data_addr = 0;
1089
Alexey Starikovskiycd8c93a2007-08-03 17:52:48 -04001090 status = acpi_walk_resources(handle, METHOD_NAME__CRS,
1091 ec_parse_io_ports, ec);
1092 if (ACPI_FAILURE(status))
1093 return status;
Alexey Starikovskiy837012e2007-05-29 16:43:02 +04001094
1095 /* Get GPE bit assignment (EC events). */
1096 /* TODO: Add support for _GPE returning a package */
Matthew Wilcox27663c52008-10-10 02:22:59 -04001097 status = acpi_evaluate_integer(handle, "_GPE", NULL, &tmp);
Alexey Starikovskiycd8c93a2007-08-03 17:52:48 -04001098 if (ACPI_FAILURE(status))
1099 return status;
Matthew Wilcox27663c52008-10-10 02:22:59 -04001100 ec->gpe = tmp;
Alexey Starikovskiy837012e2007-05-29 16:43:02 +04001101 /* Use the global lock for all EC transactions? */
Alexey Starikovskiyd21cf3c2008-11-03 14:26:40 -05001102 tmp = 0;
Matthew Wilcox27663c52008-10-10 02:22:59 -04001103 acpi_evaluate_integer(handle, "_GLK", NULL, &tmp);
1104 ec->global_lock = tmp;
Alexey Starikovskiy837012e2007-05-29 16:43:02 +04001105 ec->handle = handle;
Alexey Starikovskiycd8c93a2007-08-03 17:52:48 -04001106 return AE_CTRL_TERMINATE;
Alexey Starikovskiy837012e2007-05-29 16:43:02 +04001107}
1108
Alexey Starikovskiye8284322007-03-07 22:28:00 +03001109static int ec_install_handlers(struct acpi_ec *ec)
1110{
Alexey Starikovskiyc0900c32007-03-07 22:28:00 +03001111 acpi_status status;
Lv Zheng7a73e602014-10-14 14:24:01 +08001112
Alexey Starikovskiy7c6db4e2008-09-25 21:00:31 +04001113 if (test_bit(EC_FLAGS_HANDLERS_INSTALLED, &ec->flags))
Alexey Starikovskiy4c611062007-09-05 19:56:38 -04001114 return 0;
Lv Zhengca37bfd2015-02-05 16:27:22 +08001115 status = acpi_install_gpe_raw_handler(NULL, ec->gpe,
Alexey Starikovskiy7c6db4e2008-09-25 21:00:31 +04001116 ACPI_GPE_EDGE_TRIGGERED,
1117 &acpi_ec_gpe_handler, ec);
Alexey Starikovskiye8284322007-03-07 22:28:00 +03001118 if (ACPI_FAILURE(status))
1119 return -ENODEV;
Rafael J. Wysocki9630bdd2010-02-17 23:41:07 +01001120
Lv Zhengad479e72015-02-06 08:57:52 +08001121 acpi_ec_start(ec, false);
Alexey Starikovskiye8284322007-03-07 22:28:00 +03001122 status = acpi_install_address_space_handler(ec->handle,
1123 ACPI_ADR_SPACE_EC,
1124 &acpi_ec_space_handler,
Alexey Starikovskiy6d9e1122008-03-24 23:22:29 +03001125 NULL, ec);
Alexey Starikovskiye8284322007-03-07 22:28:00 +03001126 if (ACPI_FAILURE(status)) {
Zhao Yakui20edd742008-10-17 02:02:44 -04001127 if (status == AE_NOT_FOUND) {
1128 /*
1129 * Maybe OS fails in evaluating the _REG object.
1130 * The AE_NOT_FOUND error will be ignored and OS
1131 * continue to initialize EC.
1132 */
Lan Tianyu16a26e82013-09-12 03:32:04 -04001133 pr_err("Fail in evaluating the _REG object"
Zhao Yakui20edd742008-10-17 02:02:44 -04001134 " of EC device. Broken bios is suspected.\n");
1135 } else {
Lv Zhengad479e72015-02-06 08:57:52 +08001136 acpi_ec_stop(ec, false);
Zhao Yakui20edd742008-10-17 02:02:44 -04001137 acpi_remove_gpe_handler(NULL, ec->gpe,
1138 &acpi_ec_gpe_handler);
1139 return -ENODEV;
1140 }
Alexey Starikovskiye8284322007-03-07 22:28:00 +03001141 }
1142
Alexey Starikovskiy7c6db4e2008-09-25 21:00:31 +04001143 set_bit(EC_FLAGS_HANDLERS_INSTALLED, &ec->flags);
Alexey Starikovskiye8284322007-03-07 22:28:00 +03001144 return 0;
1145}
1146
Linus Torvalds1da177e2005-04-16 15:20:36 -07001147static void ec_remove_handlers(struct acpi_ec *ec)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001148{
Lv Zheng1741acea2014-12-15 08:47:52 +08001149 if (!test_bit(EC_FLAGS_HANDLERS_INSTALLED, &ec->flags))
1150 return;
Lv Zhengad479e72015-02-06 08:57:52 +08001151 acpi_ec_stop(ec, false);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001152 if (ACPI_FAILURE(acpi_remove_address_space_handler(ec->handle,
1153 ACPI_ADR_SPACE_EC, &acpi_ec_space_handler)))
Lan Tianyu16a26e82013-09-12 03:32:04 -04001154 pr_err("failed to remove space handler\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001155 if (ACPI_FAILURE(acpi_remove_gpe_handler(NULL, ec->gpe,
1156 &acpi_ec_gpe_handler)))
Lan Tianyu16a26e82013-09-12 03:32:04 -04001157 pr_err("failed to remove gpe handler\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001158 clear_bit(EC_FLAGS_HANDLERS_INSTALLED, &ec->flags);
1159}
Linus Torvalds1da177e2005-04-16 15:20:36 -07001160
Linus Torvalds1da177e2005-04-16 15:20:36 -07001161static int acpi_ec_add(struct acpi_device *device)
1162{
1163 struct acpi_ec *ec = NULL;
Bjorn Helgaasd02be042009-06-22 20:41:35 +00001164 int ret;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001165
Linus Torvalds1da177e2005-04-16 15:20:36 -07001166 strcpy(acpi_device_name(device), ACPI_EC_DEVICE_NAME);
1167 strcpy(acpi_device_class(device), ACPI_EC_CLASS);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001168
Linus Torvalds1da177e2005-04-16 15:20:36 -07001169 /* Check for boot EC */
1170 if (boot_ec &&
1171 (boot_ec->handle == device->handle ||
1172 boot_ec->handle == ACPI_ROOT_OBJECT)) {
1173 ec = boot_ec;
1174 boot_ec = NULL;
1175 } else {
1176 ec = make_acpi_ec();
1177 if (!ec)
1178 return -ENOMEM;
1179 }
1180 if (ec_parse_device(device->handle, 0, ec, NULL) !=
1181 AE_CTRL_TERMINATE) {
1182 kfree(ec);
1183 return -EINVAL;
1184 }
1185
Linus Torvalds1da177e2005-04-16 15:20:36 -07001186 /* Find and register all query methods */
1187 acpi_walk_namespace(ACPI_TYPE_METHOD, ec->handle, 1,
Lin Ming22635762009-11-13 10:06:08 +08001188 acpi_ec_register_query_methods, NULL, ec, NULL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001189
1190 if (!first_ec)
1191 first_ec = ec;
1192 device->driver_data = ec;
Thomas Renningerde4f1042010-07-29 22:08:44 +02001193
Andi Kleend6795fe2012-02-06 08:17:08 -08001194 ret = !!request_region(ec->data_addr, 1, "EC data");
1195 WARN(!ret, "Could not request EC data io port 0x%lx", ec->data_addr);
1196 ret = !!request_region(ec->command_addr, 1, "EC cmd");
1197 WARN(!ret, "Could not request EC cmd io port 0x%lx", ec->command_addr);
Thomas Renningerde4f1042010-07-29 22:08:44 +02001198
Lan Tianyu16a26e82013-09-12 03:32:04 -04001199 pr_info("GPE = 0x%lx, I/O: command/status = 0x%lx, data = 0x%lx\n",
Linus Torvalds1da177e2005-04-16 15:20:36 -07001200 ec->gpe, ec->command_addr, ec->data_addr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001201
Alexey Starikovskiy4c611062007-09-05 19:56:38 -04001202 ret = ec_install_handlers(ec);
Alexey Starikovskiyc0900c32007-03-07 22:28:00 +03001203
Lan Tianyu1c832b32015-04-01 09:47:18 +08001204 /* Reprobe devices depending on the EC */
1205 acpi_walk_dep_device_list(ec->handle);
1206
Alexey Starikovskiy837012e2007-05-29 16:43:02 +04001207 /* EC is fully operational, allow queries */
Rafael J. Wysocki37d11392015-02-11 17:35:05 +01001208 clear_bit(EC_FLAGS_QUERY_PENDING, &ec->flags);
Kieran Clancyad332c82014-03-01 00:42:28 +10301209
1210 /* Clear stale _Q events if hardware might require that */
Lv Zheng550b3aac2015-01-14 19:28:53 +08001211 if (EC_FLAGS_CLEAR_ON_RESUME)
Kieran Clancyad332c82014-03-01 00:42:28 +10301212 acpi_ec_clear(ec);
Alexey Starikovskiy837012e2007-05-29 16:43:02 +04001213 return ret;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001214}
1215
Rafael J. Wysocki51fac832013-01-24 00:24:48 +01001216static int acpi_ec_remove(struct acpi_device *device)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001217{
Alexey Starikovskiyc0900c32007-03-07 22:28:00 +03001218 struct acpi_ec *ec;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001219 struct acpi_ec_query_handler *handler, *tmp;
1220
Linus Torvalds1da177e2005-04-16 15:20:36 -07001221 if (!device)
Patrick Mocheld550d982006-06-27 00:41:40 -04001222 return -EINVAL;
Alexey Starikovskiyf9319f92007-08-24 08:10:11 +04001223
Linus Torvalds1da177e2005-04-16 15:20:36 -07001224 ec = acpi_driver_data(device);
Bjorn Helgaascf745ec2009-06-22 20:41:40 +00001225 ec_remove_handlers(ec);
Feng Tangf351d022012-10-23 01:29:27 +02001226 mutex_lock(&ec->mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001227 list_for_each_entry_safe(handler, tmp, &ec->list, node) {
1228 list_del(&handler->node);
1229 kfree(handler);
1230 }
Feng Tangf351d022012-10-23 01:29:27 +02001231 mutex_unlock(&ec->mutex);
Thomas Renningerde4f1042010-07-29 22:08:44 +02001232 release_region(ec->data_addr, 1);
1233 release_region(ec->command_addr, 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001234 device->driver_data = NULL;
1235 if (ec == first_ec)
1236 first_ec = NULL;
1237 kfree(ec);
Patrick Mocheld550d982006-06-27 00:41:40 -04001238 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001239}
1240
Linus Torvalds1da177e2005-04-16 15:20:36 -07001241static acpi_status
1242ec_parse_io_ports(struct acpi_resource *resource, void *context)
1243{
1244 struct acpi_ec *ec = context;
1245
1246 if (resource->type != ACPI_RESOURCE_TYPE_IO)
1247 return AE_OK;
1248
1249 /*
1250 * The first address region returned is the data port, and
1251 * the second address region returned is the status/command
1252 * port.
1253 */
Thomas Renningerde4f1042010-07-29 22:08:44 +02001254 if (ec->data_addr == 0)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001255 ec->data_addr = resource->data.io.minimum;
Thomas Renningerde4f1042010-07-29 22:08:44 +02001256 else if (ec->command_addr == 0)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001257 ec->command_addr = resource->data.io.minimum;
1258 else
1259 return AE_CTRL_TERMINATE;
1260
1261 return AE_OK;
1262}
1263
Alexey Starikovskiyc04209a2008-01-01 14:12:55 -05001264int __init acpi_boot_ec_enable(void)
1265{
Alexey Starikovskiy7c6db4e2008-09-25 21:00:31 +04001266 if (!boot_ec || test_bit(EC_FLAGS_HANDLERS_INSTALLED, &boot_ec->flags))
Alexey Starikovskiyc04209a2008-01-01 14:12:55 -05001267 return 0;
1268 if (!ec_install_handlers(boot_ec)) {
1269 first_ec = boot_ec;
1270 return 0;
1271 }
1272 return -EFAULT;
1273}
1274
Alexey Starikovskiy223883b2008-03-21 17:07:21 +03001275static const struct acpi_device_id ec_device_ids[] = {
1276 {"PNP0C09", 0},
1277 {"", 0},
1278};
1279
Alexey Starikovskiy478fa032009-10-02 20:21:40 +04001280/* Some BIOS do not survive early DSDT scan, skip it */
1281static int ec_skip_dsdt_scan(const struct dmi_system_id *id)
1282{
1283 EC_FLAGS_SKIP_DSDT_SCAN = 1;
1284 return 0;
1285}
1286
Alexey Starikovskiy0adf3c72009-10-02 20:21:33 +04001287/* ASUStek often supplies us with broken ECDT, validate it */
1288static int ec_validate_ecdt(const struct dmi_system_id *id)
1289{
1290 EC_FLAGS_VALIDATE_ECDT = 1;
1291 return 0;
1292}
1293
Feng Tang67bfa9b2012-09-28 15:22:01 +08001294/*
Lv Zheng79149002014-10-29 11:33:49 +08001295 * Acer EC firmware refuses to respond QR_EC when SCI_EVT is not set, for
1296 * which case, we complete the QR_EC without issuing it to the firmware.
1297 * https://bugzilla.kernel.org/show_bug.cgi?id=86211
1298 */
1299static int ec_flag_query_handshake(const struct dmi_system_id *id)
1300{
1301 pr_debug("Detected the EC firmware requiring QR_EC issued when SCI_EVT set\n");
1302 EC_FLAGS_QUERY_HANDSHAKE = 1;
1303 return 0;
1304}
1305
1306/*
Kieran Clancyad332c82014-03-01 00:42:28 +10301307 * On some hardware it is necessary to clear events accumulated by the EC during
1308 * sleep. These ECs stop reporting GPEs until they are manually polled, if too
1309 * many events are accumulated. (e.g. Samsung Series 5/9 notebooks)
1310 *
1311 * https://bugzilla.kernel.org/show_bug.cgi?id=44161
1312 *
1313 * Ideally, the EC should also be instructed NOT to accumulate events during
1314 * sleep (which Windows seems to do somehow), but the interface to control this
1315 * behaviour is not known at this time.
1316 *
1317 * Models known to be affected are Samsung 530Uxx/535Uxx/540Uxx/550Pxx/900Xxx,
1318 * however it is very likely that other Samsung models are affected.
1319 *
1320 * On systems which don't accumulate _Q events during sleep, this extra check
1321 * should be harmless.
1322 */
1323static int ec_clear_on_resume(const struct dmi_system_id *id)
1324{
1325 pr_debug("Detected system needing EC poll on resume.\n");
1326 EC_FLAGS_CLEAR_ON_RESUME = 1;
1327 return 0;
1328}
1329
Sachin Kamat6cef7492013-08-07 17:16:55 +05301330static struct dmi_system_id ec_dmi_table[] __initdata = {
Alexey Starikovskiy0adf3c72009-10-02 20:21:33 +04001331 {
Alexey Starikovskiy478fa032009-10-02 20:21:40 +04001332 ec_skip_dsdt_scan, "Compal JFL92", {
1333 DMI_MATCH(DMI_BIOS_VENDOR, "COMPAL"),
1334 DMI_MATCH(DMI_BOARD_NAME, "JFL92") }, NULL},
1335 {
Lv Zheng3174abc2015-05-15 14:37:11 +08001336 ec_validate_ecdt, "MSI MS-171F", {
1337 DMI_MATCH(DMI_SYS_VENDOR, "Micro-Star"),
1338 DMI_MATCH(DMI_PRODUCT_NAME, "MS-171F"),}, NULL},
Lan Tianyu777cb382014-08-29 10:50:08 +08001339 {
Alexey Starikovskiy0adf3c72009-10-02 20:21:33 +04001340 ec_validate_ecdt, "ASUS hardware", {
1341 DMI_MATCH(DMI_BIOS_VENDOR, "ASUS") }, NULL},
Peter Collingbourneaf986d12011-04-24 22:09:32 +01001342 {
1343 ec_validate_ecdt, "ASUS hardware", {
1344 DMI_MATCH(DMI_BOARD_VENDOR, "ASUSTeK Computer Inc.") }, NULL},
Feng Tang67bfa9b2012-09-28 15:22:01 +08001345 {
Lan Tianyueff9a4b2013-06-05 02:27:51 +00001346 ec_skip_dsdt_scan, "HP Folio 13", {
1347 DMI_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"),
1348 DMI_MATCH(DMI_PRODUCT_NAME, "HP Folio 13"),}, NULL},
Lan Tianyu524f42f2013-08-26 10:19:18 +08001349 {
1350 ec_validate_ecdt, "ASUS hardware", {
1351 DMI_MATCH(DMI_SYS_VENDOR, "ASUSTek Computer Inc."),
1352 DMI_MATCH(DMI_PRODUCT_NAME, "L4R"),}, NULL},
Kieran Clancyad332c82014-03-01 00:42:28 +10301353 {
1354 ec_clear_on_resume, "Samsung hardware", {
1355 DMI_MATCH(DMI_SYS_VENDOR, "SAMSUNG ELECTRONICS CO., LTD.")}, NULL},
Lv Zheng79149002014-10-29 11:33:49 +08001356 {
1357 ec_flag_query_handshake, "Acer hardware", {
1358 DMI_MATCH(DMI_SYS_VENDOR, "Acer"), }, NULL},
Alexey Starikovskiy0adf3c72009-10-02 20:21:33 +04001359 {},
1360};
1361
Len Brown50526df2005-08-11 17:32:05 -04001362int __init acpi_ec_ecdt_probe(void)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001363{
Alexey Starikovskiyc0900c32007-03-07 22:28:00 +03001364 acpi_status status;
Alexey Starikovskiyc6cb0e82009-01-14 02:57:53 +03001365 struct acpi_ec *saved_ec = NULL;
Alexey Starikovskiyc0900c32007-03-07 22:28:00 +03001366 struct acpi_table_ecdt *ecdt_ptr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001367
Alexey Starikovskiyd66d9692007-03-07 22:28:00 +03001368 boot_ec = make_acpi_ec();
1369 if (!boot_ec)
Alexey Starikovskiyc0900c32007-03-07 22:28:00 +03001370 return -ENOMEM;
1371 /*
1372 * Generate a boot ec context
1373 */
Alexey Starikovskiy0adf3c72009-10-02 20:21:33 +04001374 dmi_check_system(ec_dmi_table);
Alexey Starikovskiyc0900c32007-03-07 22:28:00 +03001375 status = acpi_get_table(ACPI_SIG_ECDT, 1,
1376 (struct acpi_table_header **)&ecdt_ptr);
Alexey Starikovskiycd8c93a2007-08-03 17:52:48 -04001377 if (ACPI_SUCCESS(status)) {
Lan Tianyu16a26e82013-09-12 03:32:04 -04001378 pr_info("EC description table is found, configuring boot EC\n");
Alexey Starikovskiycd8c93a2007-08-03 17:52:48 -04001379 boot_ec->command_addr = ecdt_ptr->control.address;
1380 boot_ec->data_addr = ecdt_ptr->data.address;
1381 boot_ec->gpe = ecdt_ptr->gpe;
Len Brown4af8e102008-03-11 00:27:16 -04001382 boot_ec->handle = ACPI_ROOT_OBJECT;
Lv Zheng7a73e602014-10-14 14:24:01 +08001383 acpi_get_handle(ACPI_ROOT_OBJECT, ecdt_ptr->id,
1384 &boot_ec->handle);
Alexey Starikovskiyc6cb0e82009-01-14 02:57:53 +03001385 /* Don't trust ECDT, which comes from ASUSTek */
Alexey Starikovskiy0adf3c72009-10-02 20:21:33 +04001386 if (!EC_FLAGS_VALIDATE_ECDT)
Alexey Starikovskiyc5279de2008-11-26 17:11:53 -05001387 goto install;
Julia Lawalld6bd5352010-05-15 23:16:21 +02001388 saved_ec = kmemdup(boot_ec, sizeof(struct acpi_ec), GFP_KERNEL);
Alexey Starikovskiyc6cb0e82009-01-14 02:57:53 +03001389 if (!saved_ec)
1390 return -ENOMEM;
Alexey Starikovskiyc5279de2008-11-26 17:11:53 -05001391 /* fall through */
Alexey Starikovskiycd8c93a2007-08-03 17:52:48 -04001392 }
Alexey Starikovskiy0adf3c72009-10-02 20:21:33 +04001393
Colin Ian Kinged4b1972014-07-03 00:35:09 +01001394 if (EC_FLAGS_SKIP_DSDT_SCAN) {
1395 kfree(saved_ec);
Alexey Starikovskiy478fa032009-10-02 20:21:40 +04001396 return -ENODEV;
Colin Ian Kinged4b1972014-07-03 00:35:09 +01001397 }
Alexey Starikovskiy478fa032009-10-02 20:21:40 +04001398
Alexey Starikovskiyc5279de2008-11-26 17:11:53 -05001399 /* This workaround is needed only on some broken machines,
1400 * which require early EC, but fail to provide ECDT */
Lan Tianyu16a26e82013-09-12 03:32:04 -04001401 pr_debug("Look up EC in DSDT\n");
Alexey Starikovskiyc5279de2008-11-26 17:11:53 -05001402 status = acpi_get_devices(ec_device_ids[0].id, ec_parse_device,
1403 boot_ec, NULL);
1404 /* Check that acpi_get_devices actually find something */
1405 if (ACPI_FAILURE(status) || !boot_ec->handle)
1406 goto error;
Alexey Starikovskiyc6cb0e82009-01-14 02:57:53 +03001407 if (saved_ec) {
1408 /* try to find good ECDT from ASUSTek */
1409 if (saved_ec->command_addr != boot_ec->command_addr ||
1410 saved_ec->data_addr != boot_ec->data_addr ||
1411 saved_ec->gpe != boot_ec->gpe ||
1412 saved_ec->handle != boot_ec->handle)
Lan Tianyu16a26e82013-09-12 03:32:04 -04001413 pr_info("ASUSTek keeps feeding us with broken "
Alexey Starikovskiyc6cb0e82009-01-14 02:57:53 +03001414 "ECDT tables, which are very hard to workaround. "
1415 "Trying to use DSDT EC info instead. Please send "
1416 "output of acpidump to linux-acpi@vger.kernel.org\n");
1417 kfree(saved_ec);
1418 saved_ec = NULL;
1419 } else {
1420 /* We really need to limit this workaround, the only ASUS,
1421 * which needs it, has fake EC._INI method, so use it as flag.
1422 * Keep boot_ec struct as it will be needed soon.
1423 */
Alexey Starikovskiyc6cb0e82009-01-14 02:57:53 +03001424 if (!dmi_name_in_vendors("ASUS") ||
Jiang Liu952c63e2013-06-29 00:24:38 +08001425 !acpi_has_method(boot_ec->handle, "_INI"))
Alexey Starikovskiyc6cb0e82009-01-14 02:57:53 +03001426 return -ENODEV;
1427 }
Alexey Starikovskiyc5279de2008-11-26 17:11:53 -05001428install:
1429 if (!ec_install_handlers(boot_ec)) {
Alexey Starikovskiyd0338792007-03-07 22:28:00 +03001430 first_ec = boot_ec;
Alexey Starikovskiye8284322007-03-07 22:28:00 +03001431 return 0;
Alexey Starikovskiyd0338792007-03-07 22:28:00 +03001432 }
Alexey Starikovskiyc5279de2008-11-26 17:11:53 -05001433error:
Alexey Starikovskiyd66d9692007-03-07 22:28:00 +03001434 kfree(boot_ec);
Colin Ian Kinged4b1972014-07-03 00:35:09 +01001435 kfree(saved_ec);
Alexey Starikovskiyd66d9692007-03-07 22:28:00 +03001436 boot_ec = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001437 return -ENODEV;
1438}
1439
Alexey Starikovskiy223883b2008-03-21 17:07:21 +03001440static struct acpi_driver acpi_ec_driver = {
1441 .name = "ec",
1442 .class = ACPI_EC_CLASS,
1443 .ids = ec_device_ids,
1444 .ops = {
1445 .add = acpi_ec_add,
1446 .remove = acpi_ec_remove,
Alexey Starikovskiy223883b2008-03-21 17:07:21 +03001447 },
1448};
1449
Bjorn Helgaasa5f820f2009-03-24 16:49:48 -06001450int __init acpi_ec_init(void)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001451{
Len Brown50526df2005-08-11 17:32:05 -04001452 int result = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001453
Linus Torvalds1da177e2005-04-16 15:20:36 -07001454 /* Now register the driver for the EC */
1455 result = acpi_bus_register_driver(&acpi_ec_driver);
Thomas Renninger49c6c5f2010-07-16 13:11:34 +02001456 if (result < 0)
Patrick Mocheld550d982006-06-27 00:41:40 -04001457 return -ENODEV;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001458
Patrick Mocheld550d982006-06-27 00:41:40 -04001459 return result;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001460}
1461
Linus Torvalds1da177e2005-04-16 15:20:36 -07001462/* EC driver currently not unloadable */
1463#if 0
Len Brown50526df2005-08-11 17:32:05 -04001464static void __exit acpi_ec_exit(void)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001465{
Linus Torvalds1da177e2005-04-16 15:20:36 -07001466
1467 acpi_bus_unregister_driver(&acpi_ec_driver);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001468}
Alexey Starikovskiy78439322007-10-22 14:18:43 +04001469#endif /* 0 */