ACPI: EC: Remove unnecessary delay added by previous transation patch.
[deliverable/linux.git] / drivers / acpi / ec.c
CommitLineData
1da177e4
LT
1/*
2 * acpi_ec.c - ACPI Embedded Controller Driver ($Revision: 38 $)
3 *
4 * Copyright (C) 2004 Luming Yu <luming.yu@intel.com>
5 * Copyright (C) 2001, 2002 Andy Grover <andrew.grover@intel.com>
6 * Copyright (C) 2001, 2002 Paul Diefenbaugh <paul.s.diefenbaugh@intel.com>
7 *
8 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
9 *
10 * This program is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License as published by
12 * the Free Software Foundation; either version 2 of the License, or (at
13 * your option) any later version.
14 *
15 * This program is distributed in the hope that it will be useful, but
16 * WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
18 * General Public License for more details.
19 *
20 * You should have received a copy of the GNU General Public License along
21 * with this program; if not, write to the Free Software Foundation, Inc.,
22 * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
23 *
24 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
25 */
26
27#include <linux/kernel.h>
28#include <linux/module.h>
29#include <linux/init.h>
30#include <linux/types.h>
31#include <linux/delay.h>
32#include <linux/proc_fs.h>
33#include <linux/seq_file.h>
451566f4 34#include <linux/interrupt.h>
1da177e4
LT
35#include <asm/io.h>
36#include <acpi/acpi_bus.h>
37#include <acpi/acpi_drivers.h>
38#include <acpi/actypes.h>
39
40#define _COMPONENT ACPI_EC_COMPONENT
50526df6 41ACPI_MODULE_NAME("acpi_ec")
1da177e4
LT
42#define ACPI_EC_COMPONENT 0x00100000
43#define ACPI_EC_CLASS "embedded_controller"
44#define ACPI_EC_HID "PNP0C09"
45#define ACPI_EC_DRIVER_NAME "ACPI Embedded Controller Driver"
46#define ACPI_EC_DEVICE_NAME "Embedded Controller"
47#define ACPI_EC_FILE_INFO "info"
1da177e4
LT
48#define ACPI_EC_FLAG_OBF 0x01 /* Output buffer full */
49#define ACPI_EC_FLAG_IBF 0x02 /* Input buffer full */
451566f4 50#define ACPI_EC_FLAG_BURST 0x10 /* burst mode */
1da177e4 51#define ACPI_EC_FLAG_SCI 0x20 /* EC-SCI occurred */
1da177e4
LT
52#define ACPI_EC_EVENT_OBF 0x01 /* Output buffer full */
53#define ACPI_EC_EVENT_IBE 0x02 /* Input buffer empty */
451566f4 54#define ACPI_EC_DELAY 50 /* Wait 50ms max. during EC ops */
1da177e4 55#define ACPI_EC_UDELAY_GLK 1000 /* Wait 1ms max. to get global lock */
50526df6
LB
56#define ACPI_EC_UDELAY 100 /* Poll @ 100us increments */
57#define ACPI_EC_UDELAY_COUNT 1000 /* Wait 10ms max. during EC ops */
1da177e4
LT
58#define ACPI_EC_COMMAND_READ 0x80
59#define ACPI_EC_COMMAND_WRITE 0x81
451566f4
DT
60#define ACPI_EC_BURST_ENABLE 0x82
61#define ACPI_EC_BURST_DISABLE 0x83
1da177e4 62#define ACPI_EC_COMMAND_QUERY 0x84
02b28a33
LB
63#define EC_POLL 0xFF
64#define EC_INTR 0x00
50526df6
LB
65static int acpi_ec_remove(struct acpi_device *device, int type);
66static int acpi_ec_start(struct acpi_device *device);
67static int acpi_ec_stop(struct acpi_device *device, int type);
02b28a33
LB
68static int acpi_ec_intr_add(struct acpi_device *device);
69static int acpi_ec_poll_add(struct acpi_device *device);
1da177e4
LT
70
71static struct acpi_driver acpi_ec_driver = {
50526df6
LB
72 .name = ACPI_EC_DRIVER_NAME,
73 .class = ACPI_EC_CLASS,
74 .ids = ACPI_EC_HID,
75 .ops = {
53f11d4f 76 .add = acpi_ec_intr_add,
50526df6
LB
77 .remove = acpi_ec_remove,
78 .start = acpi_ec_start,
79 .stop = acpi_ec_stop,
80 },
1da177e4 81};
45bea155
LY
82union acpi_ec {
83 struct {
50526df6
LB
84 u32 mode;
85 acpi_handle handle;
86 unsigned long uid;
87 unsigned long gpe_bit;
88 struct acpi_generic_address status_addr;
89 struct acpi_generic_address command_addr;
90 struct acpi_generic_address data_addr;
91 unsigned long global_lock;
45bea155
LY
92 } common;
93
94 struct {
50526df6
LB
95 u32 mode;
96 acpi_handle handle;
97 unsigned long uid;
98 unsigned long gpe_bit;
99 struct acpi_generic_address status_addr;
100 struct acpi_generic_address command_addr;
101 struct acpi_generic_address data_addr;
102 unsigned long global_lock;
7c6db5e5 103 u8 expect_event;
50526df6
LB
104 atomic_t leaving_burst; /* 0 : No, 1 : Yes, 2: abort */
105 atomic_t pending_gpe;
106 struct semaphore sem;
107 wait_queue_head_t wait;
02b28a33 108 } intr;
45bea155
LY
109
110 struct {
50526df6
LB
111 u32 mode;
112 acpi_handle handle;
113 unsigned long uid;
114 unsigned long gpe_bit;
115 struct acpi_generic_address status_addr;
116 struct acpi_generic_address command_addr;
117 struct acpi_generic_address data_addr;
118 unsigned long global_lock;
f9a6ee1a 119 struct semaphore sem;
02b28a33 120 } poll;
1da177e4
LT
121};
122
02b28a33 123static int acpi_ec_poll_wait(union acpi_ec *ec, u8 event);
7c6db5e5 124static int acpi_ec_intr_wait(union acpi_ec *ec, u8 event);
d7a76e4c
LP
125static int acpi_ec_poll_transaction(union acpi_ec *ec, u8 command,
126 const u8 *wdata, unsigned wdata_len,
127 u8 *rdata, unsigned rdata_len);
128static int acpi_ec_intr_transaction(union acpi_ec *ec, u8 command,
129 const u8 *wdata, unsigned wdata_len,
130 u8 *rdata, unsigned rdata_len);
02b28a33
LB
131static void acpi_ec_gpe_poll_query(void *ec_cxt);
132static void acpi_ec_gpe_intr_query(void *ec_cxt);
133static u32 acpi_ec_gpe_poll_handler(void *data);
134static u32 acpi_ec_gpe_intr_handler(void *data);
45bea155 135static acpi_status __init
02b28a33 136acpi_fake_ecdt_poll_callback(acpi_handle handle,
50526df6 137 u32 Level, void *context, void **retval);
45bea155
LY
138
139static acpi_status __init
02b28a33 140acpi_fake_ecdt_intr_callback(acpi_handle handle,
50526df6
LB
141 u32 Level, void *context, void **retval);
142
02b28a33
LB
143static int __init acpi_ec_poll_get_real_ecdt(void);
144static int __init acpi_ec_intr_get_real_ecdt(void);
1da177e4 145/* If we find an EC via the ECDT, we need to keep a ptr to its context */
50526df6 146static union acpi_ec *ec_ecdt;
1da177e4
LT
147
148/* External interfaces use first EC only, so remember */
149static struct acpi_device *first_ec;
53f11d4f 150static int acpi_ec_poll_mode = EC_INTR;
1da177e4
LT
151
152/* --------------------------------------------------------------------------
153 Transaction Management
154 -------------------------------------------------------------------------- */
155
858119e1 156static u32 acpi_ec_read_status(union acpi_ec *ec)
1da177e4 157{
50526df6 158 u32 status = 0;
1da177e4 159
45bea155 160 acpi_hw_low_level_read(8, &status, &ec->common.status_addr);
451566f4
DT
161 return status;
162}
163
7c6db5e5
DS
164static int acpi_ec_check_status(u32 status, u8 event) {
165
166 switch (event) {
167 case ACPI_EC_EVENT_OBF:
168 if (status & ACPI_EC_FLAG_OBF)
169 return 1;
170 case ACPI_EC_EVENT_IBE:
171 if (!(status & ACPI_EC_FLAG_IBF))
172 return 1;
173 default:
174 break;
175 }
176
177 return 0;
178}
179
50526df6 180static int acpi_ec_wait(union acpi_ec *ec, u8 event)
45bea155 181{
02b28a33
LB
182 if (acpi_ec_poll_mode)
183 return acpi_ec_poll_wait(ec, event);
45bea155 184 else
02b28a33 185 return acpi_ec_intr_wait(ec, event);
45bea155
LY
186}
187
02b28a33 188static int acpi_ec_poll_wait(union acpi_ec *ec, u8 event)
45bea155 189{
50526df6
LB
190 u32 acpi_ec_status = 0;
191 u32 i = ACPI_EC_UDELAY_COUNT;
45bea155
LY
192
193 if (!ec)
194 return -EINVAL;
195
196 /* Poll the EC status register waiting for the event to occur. */
197 switch (event) {
198 case ACPI_EC_EVENT_OBF:
199 do {
50526df6
LB
200 acpi_hw_low_level_read(8, &acpi_ec_status,
201 &ec->common.status_addr);
45bea155
LY
202 if (acpi_ec_status & ACPI_EC_FLAG_OBF)
203 return 0;
204 udelay(ACPI_EC_UDELAY);
50526df6 205 } while (--i > 0);
45bea155
LY
206 break;
207 case ACPI_EC_EVENT_IBE:
208 do {
50526df6
LB
209 acpi_hw_low_level_read(8, &acpi_ec_status,
210 &ec->common.status_addr);
45bea155
LY
211 if (!(acpi_ec_status & ACPI_EC_FLAG_IBF))
212 return 0;
213 udelay(ACPI_EC_UDELAY);
50526df6 214 } while (--i > 0);
45bea155
LY
215 break;
216 default:
217 return -EINVAL;
218 }
219
220 return -ETIME;
221}
451566f4 222
7c6db5e5
DS
223static int acpi_ec_intr_wait(union acpi_ec *ec, u8 event)
224{
225 long time_left;
1da177e4 226
02b28a33 227 ec->intr.expect_event = event;
451566f4 228
7c6db5e5 229 if (acpi_ec_check_status(acpi_ec_read_status(ec), event)) {
02b28a33 230 ec->intr.expect_event = 0;
d550d98d 231 return 0;
716e084e
LY
232 }
233
7c6db5e5
DS
234 time_left = wait_event_timeout(ec->intr.wait, !ec->intr.expect_event,
235 msecs_to_jiffies(ACPI_EC_DELAY));
50526df6 236
02b28a33 237 ec->intr.expect_event = 0;
7c6db5e5
DS
238 if (time_left <= 0) {
239 if (acpi_ec_check_status(acpi_ec_read_status(ec), event)) {
240 return 0;
241 }
242 } else {
243 return 0;
1da177e4
LT
244 }
245
d550d98d 246 return -ETIME;
1da177e4
LT
247}
248
02b28a33 249#ifdef ACPI_FUTURE_USAGE
06a2a385
LY
250/*
251 * Note: samsung nv5000 doesn't work with ec burst mode.
252 * http://bugzilla.kernel.org/show_bug.cgi?id=4980
253 */
254int acpi_ec_enter_burst_mode(union acpi_ec *ec)
451566f4 255{
50526df6
LB
256 u32 tmp = 0;
257 int status = 0;
451566f4 258
451566f4
DT
259
260 status = acpi_ec_read_status(ec);
50526df6 261 if (status != -EINVAL && !(status & ACPI_EC_FLAG_BURST)) {
716e084e 262 status = acpi_ec_wait(ec, ACPI_EC_EVENT_IBE);
50526df6 263 if (status)
716e084e 264 goto end;
50526df6
LB
265 acpi_hw_low_level_write(8, ACPI_EC_BURST_ENABLE,
266 &ec->common.command_addr);
451566f4 267 status = acpi_ec_wait(ec, ACPI_EC_EVENT_OBF);
45bea155 268 acpi_hw_low_level_read(8, &tmp, &ec->common.data_addr);
50526df6 269 if (tmp != 0x90) { /* Burst ACK byte */
d550d98d 270 return -EINVAL;
451566f4 271 }
668d74c0
LY
272 }
273
02b28a33 274 atomic_set(&ec->intr.leaving_burst, 0);
d550d98d 275 return 0;
50526df6 276 end:
a6fc6720 277 ACPI_EXCEPTION ((AE_INFO, status, "EC wait, burst mode");
d550d98d 278 return -1;
451566f4
DT
279}
280
06a2a385 281int acpi_ec_leave_burst_mode(union acpi_ec *ec)
451566f4 282{
06a2a385 283 int status = 0;
451566f4 284
451566f4 285
06a2a385
LY
286 status = acpi_ec_read_status(ec);
287 if (status != -EINVAL && (status & ACPI_EC_FLAG_BURST)){
288 status = acpi_ec_wait(ec, ACPI_EC_FLAG_IBF);
289 if(status)
290 goto end;
291 acpi_hw_low_level_write(8, ACPI_EC_BURST_DISABLE, &ec->common.command_addr);
292 acpi_ec_wait(ec, ACPI_EC_FLAG_IBF);
7c6db5e5 293 }
02b28a33 294 atomic_set(&ec->intr.leaving_burst, 1);
d550d98d 295 return 0;
06a2a385 296end:
a6fc6720 297 ACPI_EXCEPTION((AE_INFO, status, "EC leave burst mode");
d550d98d 298 return -1;
451566f4 299}
02b28a33 300#endif /* ACPI_FUTURE_USAGE */
451566f4 301
d7a76e4c
LP
302static int acpi_ec_transaction(union acpi_ec *ec, u8 command,
303 const u8 *wdata, unsigned wdata_len,
304 u8 *rdata, unsigned rdata_len)
45bea155 305{
02b28a33 306 if (acpi_ec_poll_mode)
d7a76e4c 307 return acpi_ec_poll_transaction(ec, command, wdata, wdata_len, rdata, rdata_len);
45bea155 308 else
d7a76e4c
LP
309 return acpi_ec_intr_transaction(ec, command, wdata, wdata_len, rdata, rdata_len);
310}
311static int acpi_ec_read(union acpi_ec *ec, u8 address, u32 * data)
312{
313 int result;
314 u8 d;
315 result = acpi_ec_transaction(ec, ACPI_EC_COMMAND_READ, &address, 1, &d, 1);
316 *data = d;
317 return result;
45bea155 318}
50526df6 319static int acpi_ec_write(union acpi_ec *ec, u8 address, u8 data)
45bea155 320{
d7a76e4c
LP
321 u8 wdata[2] = { address, data };
322 return acpi_ec_transaction(ec, ACPI_EC_COMMAND_WRITE, wdata, 2, NULL, 0);
45bea155 323}
d7a76e4c
LP
324
325static int acpi_ec_transaction_unlocked(union acpi_ec *ec, u8 command,
326 const u8 *wdata, unsigned wdata_len,
327 u8 *rdata, unsigned rdata_len)
45bea155 328{
d7a76e4c 329 int result;
45bea155 330
d7a76e4c 331 acpi_hw_low_level_write(8, command, &ec->common.command_addr);
45bea155 332
7c6db5e5
DS
333 for (; wdata_len > 0; wdata_len --) {
334 result = acpi_ec_wait(ec, ACPI_EC_EVENT_IBE);
335 if (result)
336 return result;
45bea155 337
7c6db5e5 338 acpi_hw_low_level_write(8, *(wdata++), &ec->common.data_addr);
d7a76e4c 339 }
45bea155 340
7c6db5e5
DS
341 if (command == ACPI_EC_COMMAND_WRITE) {
342 result = acpi_ec_wait(ec, ACPI_EC_EVENT_IBE);
343 if (result)
344 return result;
345 }
45bea155 346
7c6db5e5
DS
347 for (; rdata_len > 0; rdata_len --) {
348 u32 d;
45bea155 349
7c6db5e5
DS
350 result = acpi_ec_wait(ec, ACPI_EC_EVENT_OBF);
351 if (result)
352 return result;
50526df6 353
7c6db5e5
DS
354 acpi_hw_low_level_read(8, &d, &ec->common.data_addr);
355 *(rdata++) = (u8) d;
356 }
45bea155 357
7c6db5e5 358 return 0;
45bea155
LY
359}
360
d7a76e4c
LP
361static int acpi_ec_poll_transaction(union acpi_ec *ec, u8 command,
362 const u8 *wdata, unsigned wdata_len,
363 u8 *rdata, unsigned rdata_len)
45bea155 364{
50526df6 365 acpi_status status = AE_OK;
d7a76e4c 366 int result;
50526df6 367 u32 glk = 0;
45bea155 368
d7a76e4c 369 if (!ec || (wdata_len && !wdata) || (rdata_len && !rdata))
d550d98d 370 return -EINVAL;
45bea155 371
d7a76e4c
LP
372 if (rdata)
373 memset(rdata, 0, rdata_len);
374
45bea155
LY
375 if (ec->common.global_lock) {
376 status = acpi_acquire_global_lock(ACPI_EC_UDELAY_GLK, &glk);
377 if (ACPI_FAILURE(status))
d550d98d 378 return -ENODEV;
d7a76e4c 379 }
45bea155 380
f9a6ee1a
RT
381 if (down_interruptible(&ec->poll.sem)) {
382 result = -ERESTARTSYS;
383 goto end_nosem;
384 }
45bea155 385
d7a76e4c
LP
386 result = acpi_ec_transaction_unlocked(ec, command,
387 wdata, wdata_len,
388 rdata, rdata_len);
f9a6ee1a 389 up(&ec->poll.sem);
d7a76e4c 390
f9a6ee1a 391end_nosem:
45bea155
LY
392 if (ec->common.global_lock)
393 acpi_release_global_lock(glk);
394
d550d98d 395 return result;
45bea155
LY
396}
397
d7a76e4c
LP
398static int acpi_ec_intr_transaction(union acpi_ec *ec, u8 command,
399 const u8 *wdata, unsigned wdata_len,
400 u8 *rdata, unsigned rdata_len)
1da177e4 401{
d7a76e4c 402 int status;
50526df6 403 u32 glk;
1da177e4 404
d7a76e4c 405 if (!ec || (wdata_len && !wdata) || (rdata_len && !rdata))
d550d98d 406 return -EINVAL;
1da177e4 407
d7a76e4c
LP
408 if (rdata)
409 memset(rdata, 0, rdata_len);
1da177e4 410
45bea155 411 if (ec->common.global_lock) {
1da177e4
LT
412 status = acpi_acquire_global_lock(ACPI_EC_UDELAY_GLK, &glk);
413 if (ACPI_FAILURE(status))
d550d98d 414 return -ENODEV;
1da177e4 415 }
451566f4
DT
416
417 WARN_ON(in_interrupt());
02b28a33 418 down(&ec->intr.sem);
451566f4 419
716e084e
LY
420 status = acpi_ec_wait(ec, ACPI_EC_EVENT_IBE);
421 if (status) {
1e8df53c 422 printk(KERN_DEBUG PREFIX "read EC, IB not empty\n");
451566f4 423 goto end;
716e084e 424 }
1da177e4 425
d7a76e4c
LP
426 status = acpi_ec_transaction_unlocked(ec, command,
427 wdata, wdata_len,
428 rdata, rdata_len);
1da177e4 429
d7a76e4c 430end:
02b28a33 431 up(&ec->intr.sem);
1da177e4 432
45bea155 433 if (ec->common.global_lock)
1da177e4
LT
434 acpi_release_global_lock(glk);
435
d550d98d 436 return status;
1da177e4
LT
437}
438
439/*
440 * Externally callable EC access functions. For now, assume 1 EC only
441 */
50526df6 442int ec_read(u8 addr, u8 * val)
1da177e4 443{
45bea155 444 union acpi_ec *ec;
1da177e4
LT
445 int err;
446 u32 temp_data;
447
448 if (!first_ec)
449 return -ENODEV;
450
451 ec = acpi_driver_data(first_ec);
452
453 err = acpi_ec_read(ec, addr, &temp_data);
454
455 if (!err) {
456 *val = temp_data;
457 return 0;
50526df6 458 } else
1da177e4
LT
459 return err;
460}
50526df6 461
1da177e4
LT
462EXPORT_SYMBOL(ec_read);
463
50526df6 464int ec_write(u8 addr, u8 val)
1da177e4 465{
45bea155 466 union acpi_ec *ec;
1da177e4
LT
467 int err;
468
469 if (!first_ec)
470 return -ENODEV;
471
472 ec = acpi_driver_data(first_ec);
473
474 err = acpi_ec_write(ec, addr, val);
475
476 return err;
477}
50526df6 478
1da177e4
LT
479EXPORT_SYMBOL(ec_write);
480
d7a76e4c
LP
481extern int ec_transaction(u8 command,
482 const u8 *wdata, unsigned wdata_len,
483 u8 *rdata, unsigned rdata_len)
45bea155 484{
d7a76e4c 485 union acpi_ec *ec;
45bea155 486
d7a76e4c
LP
487 if (!first_ec)
488 return -ENODEV;
45bea155 489
d7a76e4c 490 ec = acpi_driver_data(first_ec);
45bea155 491
d7a76e4c 492 return acpi_ec_transaction(ec, command, wdata, wdata_len, rdata, rdata_len);
45bea155 493}
1da177e4 494
d7a76e4c 495EXPORT_SYMBOL(ec_transaction);
1da177e4 496
d7a76e4c
LP
497static int acpi_ec_query(union acpi_ec *ec, u32 * data) {
498 int result;
499 u8 d;
1da177e4 500
d7a76e4c
LP
501 if (!ec || !data)
502 return -EINVAL;
1da177e4 503
d7a76e4c
LP
504 /*
505 * Query the EC to find out which _Qxx method we need to evaluate.
506 * Note that successful completion of the query causes the ACPI_EC_SCI
507 * bit to be cleared (and thus clearing the interrupt source).
508 */
716e084e 509
d7a76e4c
LP
510 result = acpi_ec_transaction(ec, ACPI_EC_COMMAND_QUERY, NULL, 0, &d, 1);
511 if (result)
512 return result;
1da177e4 513
d7a76e4c
LP
514 if (!d)
515 return -ENODATA;
1da177e4 516
d7a76e4c
LP
517 *data = d;
518 return 0;
1da177e4
LT
519}
520
1da177e4
LT
521/* --------------------------------------------------------------------------
522 Event Management
523 -------------------------------------------------------------------------- */
524
45bea155 525union acpi_ec_query_data {
50526df6
LB
526 acpi_handle handle;
527 u8 data;
1da177e4
LT
528};
529
50526df6 530static void acpi_ec_gpe_query(void *ec_cxt)
1da177e4 531{
02b28a33
LB
532 if (acpi_ec_poll_mode)
533 acpi_ec_gpe_poll_query(ec_cxt);
45bea155 534 else
02b28a33 535 acpi_ec_gpe_intr_query(ec_cxt);
45bea155
LY
536}
537
02b28a33 538static void acpi_ec_gpe_poll_query(void *ec_cxt)
45bea155 539{
50526df6
LB
540 union acpi_ec *ec = (union acpi_ec *)ec_cxt;
541 u32 value = 0;
50526df6
LB
542 static char object_name[5] = { '_', 'Q', '0', '0', '\0' };
543 const char hex[] = { '0', '1', '2', '3', '4', '5', '6', '7',
544 '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'
545 };
45bea155 546
45bea155
LY
547
548 if (!ec_cxt)
549 goto end;
550
f9a6ee1a 551 if (down_interruptible (&ec->poll.sem)) {
d550d98d 552 return;
f9a6ee1a 553 }
45bea155 554 acpi_hw_low_level_read(8, &value, &ec->common.command_addr);
f9a6ee1a 555 up(&ec->poll.sem);
45bea155
LY
556
557 /* TBD: Implement asynch events!
558 * NOTE: All we care about are EC-SCI's. Other EC events are
559 * handled via polling (yuck!). This is because some systems
560 * treat EC-SCIs as level (versus EDGE!) triggered, preventing
561 * a purely interrupt-driven approach (grumble, grumble).
562 */
563 if (!(value & ACPI_EC_FLAG_SCI))
564 goto end;
565
566 if (acpi_ec_query(ec, &value))
567 goto end;
568
569 object_name[2] = hex[((value >> 4) & 0x0F)];
570 object_name[3] = hex[(value & 0x0F)];
571
572 ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Evaluating %s\n", object_name));
573
574 acpi_evaluate_object(ec->common.handle, object_name, NULL, NULL);
575
50526df6 576 end:
45bea155
LY
577 acpi_enable_gpe(NULL, ec->common.gpe_bit, ACPI_NOT_ISR);
578}
02b28a33 579static void acpi_ec_gpe_intr_query(void *ec_cxt)
45bea155 580{
50526df6
LB
581 union acpi_ec *ec = (union acpi_ec *)ec_cxt;
582 u32 value;
583 int result = -ENODATA;
584 static char object_name[5] = { '_', 'Q', '0', '0', '\0' };
585 const char hex[] = { '0', '1', '2', '3', '4', '5', '6', '7',
586 '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'
587 };
1da177e4 588
1da177e4 589
451566f4
DT
590 if (acpi_ec_read_status(ec) & ACPI_EC_FLAG_SCI)
591 result = acpi_ec_query(ec, &value);
1da177e4 592
451566f4 593 if (result)
1da177e4
LT
594 goto end;
595
1da177e4
LT
596 object_name[2] = hex[((value >> 4) & 0x0F)];
597 object_name[3] = hex[(value & 0x0F)];
598
599 ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Evaluating %s\n", object_name));
600
45bea155 601 acpi_evaluate_object(ec->common.handle, object_name, NULL, NULL);
50526df6 602 end:
02b28a33 603 atomic_dec(&ec->intr.pending_gpe);
451566f4 604 return;
1da177e4
LT
605}
606
50526df6 607static u32 acpi_ec_gpe_handler(void *data)
45bea155 608{
02b28a33
LB
609 if (acpi_ec_poll_mode)
610 return acpi_ec_gpe_poll_handler(data);
45bea155 611 else
02b28a33 612 return acpi_ec_gpe_intr_handler(data);
45bea155 613}
02b28a33 614static u32 acpi_ec_gpe_poll_handler(void *data)
45bea155 615{
50526df6
LB
616 acpi_status status = AE_OK;
617 union acpi_ec *ec = (union acpi_ec *)data;
45bea155
LY
618
619 if (!ec)
620 return ACPI_INTERRUPT_NOT_HANDLED;
621
622 acpi_disable_gpe(NULL, ec->common.gpe_bit, ACPI_ISR);
623
b8d35192 624 status = acpi_os_execute(OSL_EC_POLL_HANDLER, acpi_ec_gpe_query, ec);
45bea155
LY
625
626 if (status == AE_OK)
627 return ACPI_INTERRUPT_HANDLED;
628 else
629 return ACPI_INTERRUPT_NOT_HANDLED;
630}
02b28a33 631static u32 acpi_ec_gpe_intr_handler(void *data)
1da177e4 632{
50526df6
LB
633 acpi_status status = AE_OK;
634 u32 value;
635 union acpi_ec *ec = (union acpi_ec *)data;
1da177e4
LT
636
637 if (!ec)
638 return ACPI_INTERRUPT_NOT_HANDLED;
639
716e084e 640 acpi_clear_gpe(NULL, ec->common.gpe_bit, ACPI_ISR);
451566f4 641 value = acpi_ec_read_status(ec);
1da177e4 642
02b28a33 643 switch (ec->intr.expect_event) {
716e084e
LY
644 case ACPI_EC_EVENT_OBF:
645 if (!(value & ACPI_EC_FLAG_OBF))
646 break;
49fee981
VL
647 ec->intr.expect_event = 0;
648 wake_up(&ec->intr.wait);
649 break;
716e084e
LY
650 case ACPI_EC_EVENT_IBE:
651 if ((value & ACPI_EC_FLAG_IBF))
652 break;
02b28a33
LB
653 ec->intr.expect_event = 0;
654 wake_up(&ec->intr.wait);
49fee981 655 break;
716e084e
LY
656 default:
657 break;
451566f4
DT
658 }
659
50526df6 660 if (value & ACPI_EC_FLAG_SCI) {
02b28a33 661 atomic_add(1, &ec->intr.pending_gpe);
b8d35192 662 status = acpi_os_execute(OSL_EC_BURST_HANDLER,
50526df6 663 acpi_ec_gpe_query, ec);
17e9c78a 664 return status == AE_OK ?
50526df6
LB
665 ACPI_INTERRUPT_HANDLED : ACPI_INTERRUPT_NOT_HANDLED;
666 }
45bea155 667 acpi_enable_gpe(NULL, ec->common.gpe_bit, ACPI_ISR);
451566f4 668 return status == AE_OK ?
50526df6 669 ACPI_INTERRUPT_HANDLED : ACPI_INTERRUPT_NOT_HANDLED;
1da177e4
LT
670}
671
672/* --------------------------------------------------------------------------
673 Address Space Management
674 -------------------------------------------------------------------------- */
675
676static acpi_status
50526df6
LB
677acpi_ec_space_setup(acpi_handle region_handle,
678 u32 function, void *handler_context, void **return_context)
1da177e4
LT
679{
680 /*
681 * The EC object is in the handler context and is needed
682 * when calling the acpi_ec_space_handler.
683 */
50526df6
LB
684 *return_context = (function != ACPI_REGION_DEACTIVATE) ?
685 handler_context : NULL;
1da177e4
LT
686
687 return AE_OK;
688}
689
1da177e4 690static acpi_status
50526df6
LB
691acpi_ec_space_handler(u32 function,
692 acpi_physical_address address,
693 u32 bit_width,
694 acpi_integer * value,
695 void *handler_context, void *region_context)
1da177e4 696{
50526df6
LB
697 int result = 0;
698 union acpi_ec *ec = NULL;
699 u64 temp = *value;
700 acpi_integer f_v = 0;
701 int i = 0;
1da177e4 702
1da177e4
LT
703
704 if ((address > 0xFF) || !value || !handler_context)
d550d98d 705 return AE_BAD_PARAMETER;
1da177e4 706
fa9cd547 707 if (bit_width != 8 && acpi_strict) {
50526df6
LB
708 printk(KERN_WARNING PREFIX
709 "acpi_ec_space_handler: bit_width should be 8\n");
d550d98d 710 return AE_BAD_PARAMETER;
1da177e4
LT
711 }
712
50526df6 713 ec = (union acpi_ec *)handler_context;
1da177e4 714
50526df6 715 next_byte:
1da177e4
LT
716 switch (function) {
717 case ACPI_READ:
fa9cd547 718 temp = 0;
50526df6 719 result = acpi_ec_read(ec, (u8) address, (u32 *) & temp);
1da177e4
LT
720 break;
721 case ACPI_WRITE:
fa9cd547 722 result = acpi_ec_write(ec, (u8) address, (u8) temp);
1da177e4
LT
723 break;
724 default:
725 result = -EINVAL;
726 goto out;
727 break;
728 }
729
730 bit_width -= 8;
fa9cd547
LY
731 if (bit_width) {
732 if (function == ACPI_READ)
733 f_v |= temp << 8 * i;
734 if (function == ACPI_WRITE)
735 temp >>= 8;
1da177e4 736 i++;
83ea7445 737 address++;
1da177e4
LT
738 goto next_byte;
739 }
740
fa9cd547
LY
741 if (function == ACPI_READ) {
742 f_v |= temp << 8 * i;
1da177e4
LT
743 *value = f_v;
744 }
745
50526df6 746 out:
1da177e4
LT
747 switch (result) {
748 case -EINVAL:
d550d98d 749 return AE_BAD_PARAMETER;
1da177e4
LT
750 break;
751 case -ENODEV:
d550d98d 752 return AE_NOT_FOUND;
1da177e4
LT
753 break;
754 case -ETIME:
d550d98d 755 return AE_TIME;
1da177e4
LT
756 break;
757 default:
d550d98d 758 return AE_OK;
1da177e4 759 }
1da177e4
LT
760}
761
1da177e4
LT
762/* --------------------------------------------------------------------------
763 FS Interface (/proc)
764 -------------------------------------------------------------------------- */
765
50526df6 766static struct proc_dir_entry *acpi_ec_dir;
1da177e4 767
50526df6 768static int acpi_ec_read_info(struct seq_file *seq, void *offset)
1da177e4 769{
50526df6 770 union acpi_ec *ec = (union acpi_ec *)seq->private;
1da177e4 771
1da177e4
LT
772
773 if (!ec)
774 goto end;
775
776 seq_printf(seq, "gpe bit: 0x%02x\n",
50526df6 777 (u32) ec->common.gpe_bit);
1da177e4 778 seq_printf(seq, "ports: 0x%02x, 0x%02x\n",
50526df6
LB
779 (u32) ec->common.status_addr.address,
780 (u32) ec->common.data_addr.address);
1da177e4 781 seq_printf(seq, "use global lock: %s\n",
50526df6 782 ec->common.global_lock ? "yes" : "no");
45bea155 783 acpi_enable_gpe(NULL, ec->common.gpe_bit, ACPI_NOT_ISR);
1da177e4 784
50526df6 785 end:
d550d98d 786 return 0;
1da177e4
LT
787}
788
789static int acpi_ec_info_open_fs(struct inode *inode, struct file *file)
790{
791 return single_open(file, acpi_ec_read_info, PDE(inode)->data);
792}
793
d7508032 794static const struct file_operations acpi_ec_info_ops = {
50526df6
LB
795 .open = acpi_ec_info_open_fs,
796 .read = seq_read,
797 .llseek = seq_lseek,
798 .release = single_release,
1da177e4
LT
799 .owner = THIS_MODULE,
800};
801
50526df6 802static int acpi_ec_add_fs(struct acpi_device *device)
1da177e4 803{
50526df6 804 struct proc_dir_entry *entry = NULL;
1da177e4 805
1da177e4
LT
806
807 if (!acpi_device_dir(device)) {
808 acpi_device_dir(device) = proc_mkdir(acpi_device_bid(device),
50526df6 809 acpi_ec_dir);
1da177e4 810 if (!acpi_device_dir(device))
d550d98d 811 return -ENODEV;
1da177e4
LT
812 }
813
814 entry = create_proc_entry(ACPI_EC_FILE_INFO, S_IRUGO,
50526df6 815 acpi_device_dir(device));
1da177e4 816 if (!entry)
d550d98d 817 return -ENODEV;
1da177e4
LT
818 else {
819 entry->proc_fops = &acpi_ec_info_ops;
820 entry->data = acpi_driver_data(device);
821 entry->owner = THIS_MODULE;
822 }
823
d550d98d 824 return 0;
1da177e4
LT
825}
826
50526df6 827static int acpi_ec_remove_fs(struct acpi_device *device)
1da177e4 828{
1da177e4
LT
829
830 if (acpi_device_dir(device)) {
831 remove_proc_entry(ACPI_EC_FILE_INFO, acpi_device_dir(device));
832 remove_proc_entry(acpi_device_bid(device), acpi_ec_dir);
833 acpi_device_dir(device) = NULL;
834 }
835
d550d98d 836 return 0;
1da177e4
LT
837}
838
1da177e4
LT
839/* --------------------------------------------------------------------------
840 Driver Interface
841 -------------------------------------------------------------------------- */
842
02b28a33 843static int acpi_ec_poll_add(struct acpi_device *device)
1da177e4 844{
50526df6
LB
845 int result = 0;
846 acpi_status status = AE_OK;
847 union acpi_ec *ec = NULL;
45bea155 848
45bea155
LY
849
850 if (!device)
d550d98d 851 return -EINVAL;
45bea155
LY
852
853 ec = kmalloc(sizeof(union acpi_ec), GFP_KERNEL);
854 if (!ec)
d550d98d 855 return -ENOMEM;
45bea155
LY
856 memset(ec, 0, sizeof(union acpi_ec));
857
858 ec->common.handle = device->handle;
859 ec->common.uid = -1;
f9a6ee1a 860 init_MUTEX(&ec->poll.sem);
45bea155
LY
861 strcpy(acpi_device_name(device), ACPI_EC_DEVICE_NAME);
862 strcpy(acpi_device_class(device), ACPI_EC_CLASS);
863 acpi_driver_data(device) = ec;
864
865 /* Use the global lock for all EC transactions? */
50526df6
LB
866 acpi_evaluate_integer(ec->common.handle, "_GLK", NULL,
867 &ec->common.global_lock);
45bea155 868
ff2fc3e9
JS
869 /* XXX we don't test uids, because on some boxes ecdt uid = 0, see:
870 http://bugzilla.kernel.org/show_bug.cgi?id=6111 */
871 if (ec_ecdt) {
45bea155 872 acpi_remove_address_space_handler(ACPI_ROOT_OBJECT,
50526df6
LB
873 ACPI_ADR_SPACE_EC,
874 &acpi_ec_space_handler);
875
876 acpi_remove_gpe_handler(NULL, ec_ecdt->common.gpe_bit,
877 &acpi_ec_gpe_handler);
45bea155
LY
878
879 kfree(ec_ecdt);
880 }
881
882 /* Get GPE bit assignment (EC events). */
883 /* TODO: Add support for _GPE returning a package */
50526df6
LB
884 status =
885 acpi_evaluate_integer(ec->common.handle, "_GPE", NULL,
886 &ec->common.gpe_bit);
45bea155 887 if (ACPI_FAILURE(status)) {
a6fc6720 888 ACPI_EXCEPTION((AE_INFO, status, "Obtaining GPE bit"));
45bea155
LY
889 result = -ENODEV;
890 goto end;
891 }
892
893 result = acpi_ec_add_fs(device);
894 if (result)
895 goto end;
896
02b28a33 897 printk(KERN_INFO PREFIX "%s [%s] (gpe %d) polling mode.\n",
50526df6
LB
898 acpi_device_name(device), acpi_device_bid(device),
899 (u32) ec->common.gpe_bit);
45bea155
LY
900
901 if (!first_ec)
902 first_ec = device;
903
50526df6 904 end:
45bea155
LY
905 if (result)
906 kfree(ec);
907
d550d98d 908 return result;
45bea155 909}
02b28a33 910static int acpi_ec_intr_add(struct acpi_device *device)
45bea155 911{
50526df6
LB
912 int result = 0;
913 acpi_status status = AE_OK;
914 union acpi_ec *ec = NULL;
1da177e4 915
1da177e4
LT
916
917 if (!device)
d550d98d 918 return -EINVAL;
1da177e4 919
45bea155 920 ec = kmalloc(sizeof(union acpi_ec), GFP_KERNEL);
1da177e4 921 if (!ec)
d550d98d 922 return -ENOMEM;
45bea155
LY
923 memset(ec, 0, sizeof(union acpi_ec));
924
925 ec->common.handle = device->handle;
926 ec->common.uid = -1;
02b28a33
LB
927 atomic_set(&ec->intr.pending_gpe, 0);
928 atomic_set(&ec->intr.leaving_burst, 1);
929 init_MUTEX(&ec->intr.sem);
930 init_waitqueue_head(&ec->intr.wait);
1da177e4
LT
931 strcpy(acpi_device_name(device), ACPI_EC_DEVICE_NAME);
932 strcpy(acpi_device_class(device), ACPI_EC_CLASS);
933 acpi_driver_data(device) = ec;
934
935 /* Use the global lock for all EC transactions? */
50526df6
LB
936 acpi_evaluate_integer(ec->common.handle, "_GLK", NULL,
937 &ec->common.global_lock);
1da177e4 938
ff2fc3e9
JS
939 /* XXX we don't test uids, because on some boxes ecdt uid = 0, see:
940 http://bugzilla.kernel.org/show_bug.cgi?id=6111 */
941 if (ec_ecdt) {
1da177e4 942 acpi_remove_address_space_handler(ACPI_ROOT_OBJECT,
50526df6
LB
943 ACPI_ADR_SPACE_EC,
944 &acpi_ec_space_handler);
451566f4 945
50526df6
LB
946 acpi_remove_gpe_handler(NULL, ec_ecdt->common.gpe_bit,
947 &acpi_ec_gpe_handler);
1da177e4
LT
948
949 kfree(ec_ecdt);
950 }
951
952 /* Get GPE bit assignment (EC events). */
953 /* TODO: Add support for _GPE returning a package */
50526df6
LB
954 status =
955 acpi_evaluate_integer(ec->common.handle, "_GPE", NULL,
956 &ec->common.gpe_bit);
1da177e4 957 if (ACPI_FAILURE(status)) {
6468463a 958 printk(KERN_ERR PREFIX "Obtaining GPE bit assignment\n");
1da177e4
LT
959 result = -ENODEV;
960 goto end;
961 }
962
963 result = acpi_ec_add_fs(device);
964 if (result)
965 goto end;
966
02b28a33 967 printk(KERN_INFO PREFIX "%s [%s] (gpe %d) interrupt mode.\n",
50526df6
LB
968 acpi_device_name(device), acpi_device_bid(device),
969 (u32) ec->common.gpe_bit);
1da177e4
LT
970
971 if (!first_ec)
972 first_ec = device;
973
50526df6 974 end:
1da177e4
LT
975 if (result)
976 kfree(ec);
977
d550d98d 978 return result;
1da177e4
LT
979}
980
50526df6 981static int acpi_ec_remove(struct acpi_device *device, int type)
1da177e4 982{
50526df6 983 union acpi_ec *ec = NULL;
1da177e4 984
1da177e4
LT
985
986 if (!device)
d550d98d 987 return -EINVAL;
1da177e4
LT
988
989 ec = acpi_driver_data(device);
990
991 acpi_ec_remove_fs(device);
992
993 kfree(ec);
994
d550d98d 995 return 0;
1da177e4
LT
996}
997
1da177e4 998static acpi_status
50526df6 999acpi_ec_io_ports(struct acpi_resource *resource, void *context)
1da177e4 1000{
50526df6 1001 union acpi_ec *ec = (union acpi_ec *)context;
1da177e4
LT
1002 struct acpi_generic_address *addr;
1003
50eca3eb 1004 if (resource->type != ACPI_RESOURCE_TYPE_IO) {
1da177e4
LT
1005 return AE_OK;
1006 }
1007
1008 /*
1009 * The first address region returned is the data port, and
1010 * the second address region returned is the status/command
1011 * port.
1012 */
45bea155
LY
1013 if (ec->common.data_addr.register_bit_width == 0) {
1014 addr = &ec->common.data_addr;
1015 } else if (ec->common.command_addr.register_bit_width == 0) {
1016 addr = &ec->common.command_addr;
1da177e4
LT
1017 } else {
1018 return AE_CTRL_TERMINATE;
1019 }
1020
1021 addr->address_space_id = ACPI_ADR_SPACE_SYSTEM_IO;
1022 addr->register_bit_width = 8;
1023 addr->register_bit_offset = 0;
50eca3eb 1024 addr->address = resource->data.io.minimum;
1da177e4
LT
1025
1026 return AE_OK;
1027}
1028
50526df6 1029static int acpi_ec_start(struct acpi_device *device)
1da177e4 1030{
50526df6
LB
1031 acpi_status status = AE_OK;
1032 union acpi_ec *ec = NULL;
1da177e4 1033
1da177e4
LT
1034
1035 if (!device)
d550d98d 1036 return -EINVAL;
1da177e4
LT
1037
1038 ec = acpi_driver_data(device);
1039
1040 if (!ec)
d550d98d 1041 return -EINVAL;
1da177e4
LT
1042
1043 /*
1044 * Get I/O port addresses. Convert to GAS format.
1045 */
45bea155 1046 status = acpi_walk_resources(ec->common.handle, METHOD_NAME__CRS,
50526df6
LB
1047 acpi_ec_io_ports, ec);
1048 if (ACPI_FAILURE(status)
1049 || ec->common.command_addr.register_bit_width == 0) {
6468463a 1050 printk(KERN_ERR PREFIX "Error getting I/O port addresses\n");
d550d98d 1051 return -ENODEV;
1da177e4
LT
1052 }
1053
45bea155 1054 ec->common.status_addr = ec->common.command_addr;
1da177e4
LT
1055
1056 ACPI_DEBUG_PRINT((ACPI_DB_INFO, "gpe=0x%02x, ports=0x%2x,0x%2x\n",
50526df6
LB
1057 (u32) ec->common.gpe_bit,
1058 (u32) ec->common.command_addr.address,
1059 (u32) ec->common.data_addr.address));
1da177e4
LT
1060
1061 /*
1062 * Install GPE handler
1063 */
45bea155 1064 status = acpi_install_gpe_handler(NULL, ec->common.gpe_bit,
50526df6
LB
1065 ACPI_GPE_EDGE_TRIGGERED,
1066 &acpi_ec_gpe_handler, ec);
1da177e4 1067 if (ACPI_FAILURE(status)) {
d550d98d 1068 return -ENODEV;
1da177e4 1069 }
50526df6
LB
1070 acpi_set_gpe_type(NULL, ec->common.gpe_bit, ACPI_GPE_TYPE_RUNTIME);
1071 acpi_enable_gpe(NULL, ec->common.gpe_bit, ACPI_NOT_ISR);
1da177e4 1072
50526df6
LB
1073 status = acpi_install_address_space_handler(ec->common.handle,
1074 ACPI_ADR_SPACE_EC,
1075 &acpi_ec_space_handler,
1076 &acpi_ec_space_setup, ec);
1da177e4 1077 if (ACPI_FAILURE(status)) {
50526df6
LB
1078 acpi_remove_gpe_handler(NULL, ec->common.gpe_bit,
1079 &acpi_ec_gpe_handler);
d550d98d 1080 return -ENODEV;
1da177e4
LT
1081 }
1082
d550d98d 1083 return AE_OK;
1da177e4
LT
1084}
1085
50526df6 1086static int acpi_ec_stop(struct acpi_device *device, int type)
1da177e4 1087{
50526df6
LB
1088 acpi_status status = AE_OK;
1089 union acpi_ec *ec = NULL;
1da177e4 1090
1da177e4
LT
1091
1092 if (!device)
d550d98d 1093 return -EINVAL;
1da177e4
LT
1094
1095 ec = acpi_driver_data(device);
1096
45bea155 1097 status = acpi_remove_address_space_handler(ec->common.handle,
50526df6
LB
1098 ACPI_ADR_SPACE_EC,
1099 &acpi_ec_space_handler);
1da177e4 1100 if (ACPI_FAILURE(status))
d550d98d 1101 return -ENODEV;
1da177e4 1102
50526df6
LB
1103 status =
1104 acpi_remove_gpe_handler(NULL, ec->common.gpe_bit,
1105 &acpi_ec_gpe_handler);
1da177e4 1106 if (ACPI_FAILURE(status))
d550d98d 1107 return -ENODEV;
1da177e4 1108
d550d98d 1109 return 0;
1da177e4
LT
1110}
1111
1112static acpi_status __init
50526df6
LB
1113acpi_fake_ecdt_callback(acpi_handle handle,
1114 u32 Level, void *context, void **retval)
1da177e4 1115{
45bea155 1116
02b28a33
LB
1117 if (acpi_ec_poll_mode)
1118 return acpi_fake_ecdt_poll_callback(handle,
50526df6 1119 Level, context, retval);
45bea155 1120 else
02b28a33 1121 return acpi_fake_ecdt_intr_callback(handle,
50526df6 1122 Level, context, retval);
45bea155
LY
1123}
1124
1125static acpi_status __init
02b28a33 1126acpi_fake_ecdt_poll_callback(acpi_handle handle,
50526df6 1127 u32 Level, void *context, void **retval)
45bea155 1128{
50526df6 1129 acpi_status status;
45bea155
LY
1130
1131 status = acpi_walk_resources(handle, METHOD_NAME__CRS,
50526df6 1132 acpi_ec_io_ports, ec_ecdt);
45bea155
LY
1133 if (ACPI_FAILURE(status))
1134 return status;
1135 ec_ecdt->common.status_addr = ec_ecdt->common.command_addr;
1136
1137 ec_ecdt->common.uid = -1;
1138 acpi_evaluate_integer(handle, "_UID", NULL, &ec_ecdt->common.uid);
1139
50526df6
LB
1140 status =
1141 acpi_evaluate_integer(handle, "_GPE", NULL,
1142 &ec_ecdt->common.gpe_bit);
45bea155
LY
1143 if (ACPI_FAILURE(status))
1144 return status;
f9a6ee1a 1145 init_MUTEX(&ec_ecdt->poll.sem);
45bea155
LY
1146 ec_ecdt->common.global_lock = TRUE;
1147 ec_ecdt->common.handle = handle;
1148
50526df6
LB
1149 printk(KERN_INFO PREFIX "GPE=0x%02x, ports=0x%2x, 0x%2x\n",
1150 (u32) ec_ecdt->common.gpe_bit,
1151 (u32) ec_ecdt->common.command_addr.address,
1152 (u32) ec_ecdt->common.data_addr.address);
45bea155
LY
1153
1154 return AE_CTRL_TERMINATE;
1155}
1156
1157static acpi_status __init
02b28a33 1158acpi_fake_ecdt_intr_callback(acpi_handle handle,
50526df6 1159 u32 Level, void *context, void **retval)
45bea155 1160{
50526df6 1161 acpi_status status;
1da177e4 1162
02b28a33
LB
1163 init_MUTEX(&ec_ecdt->intr.sem);
1164 init_waitqueue_head(&ec_ecdt->intr.wait);
1da177e4 1165 status = acpi_walk_resources(handle, METHOD_NAME__CRS,
50526df6 1166 acpi_ec_io_ports, ec_ecdt);
1da177e4
LT
1167 if (ACPI_FAILURE(status))
1168 return status;
45bea155 1169 ec_ecdt->common.status_addr = ec_ecdt->common.command_addr;
1da177e4 1170
45bea155
LY
1171 ec_ecdt->common.uid = -1;
1172 acpi_evaluate_integer(handle, "_UID", NULL, &ec_ecdt->common.uid);
1da177e4 1173
50526df6
LB
1174 status =
1175 acpi_evaluate_integer(handle, "_GPE", NULL,
1176 &ec_ecdt->common.gpe_bit);
1da177e4
LT
1177 if (ACPI_FAILURE(status))
1178 return status;
45bea155
LY
1179 ec_ecdt->common.global_lock = TRUE;
1180 ec_ecdt->common.handle = handle;
1da177e4 1181
50526df6
LB
1182 printk(KERN_INFO PREFIX "GPE=0x%02x, ports=0x%2x, 0x%2x\n",
1183 (u32) ec_ecdt->common.gpe_bit,
1184 (u32) ec_ecdt->common.command_addr.address,
1185 (u32) ec_ecdt->common.data_addr.address);
1da177e4
LT
1186
1187 return AE_CTRL_TERMINATE;
1188}
1189
1190/*
1191 * Some BIOS (such as some from Gateway laptops) access EC region very early
1192 * such as in BAT0._INI or EC._INI before an EC device is found and
1193 * do not provide an ECDT. According to ACPI spec, ECDT isn't mandatorily
1194 * required, but if EC regison is accessed early, it is required.
1195 * The routine tries to workaround the BIOS bug by pre-scan EC device
1196 * It assumes that _CRS, _HID, _GPE, _UID methods of EC don't touch any
1197 * op region (since _REG isn't invoked yet). The assumption is true for
1198 * all systems found.
1199 */
50526df6 1200static int __init acpi_ec_fake_ecdt(void)
1da177e4 1201{
50526df6
LB
1202 acpi_status status;
1203 int ret = 0;
1da177e4
LT
1204
1205 printk(KERN_INFO PREFIX "Try to make an fake ECDT\n");
1206
45bea155 1207 ec_ecdt = kmalloc(sizeof(union acpi_ec), GFP_KERNEL);
1da177e4
LT
1208 if (!ec_ecdt) {
1209 ret = -ENOMEM;
1210 goto error;
1211 }
45bea155 1212 memset(ec_ecdt, 0, sizeof(union acpi_ec));
1da177e4 1213
50526df6
LB
1214 status = acpi_get_devices(ACPI_EC_HID,
1215 acpi_fake_ecdt_callback, NULL, NULL);
1da177e4
LT
1216 if (ACPI_FAILURE(status)) {
1217 kfree(ec_ecdt);
1218 ec_ecdt = NULL;
1219 ret = -ENODEV;
1220 goto error;
1221 }
1222 return 0;
50526df6 1223 error:
1da177e4
LT
1224 printk(KERN_ERR PREFIX "Can't make an fake ECDT\n");
1225 return ret;
1226}
1227
50526df6 1228static int __init acpi_ec_get_real_ecdt(void)
45bea155 1229{
02b28a33
LB
1230 if (acpi_ec_poll_mode)
1231 return acpi_ec_poll_get_real_ecdt();
45bea155 1232 else
02b28a33 1233 return acpi_ec_intr_get_real_ecdt();
45bea155
LY
1234}
1235
02b28a33 1236static int __init acpi_ec_poll_get_real_ecdt(void)
45bea155 1237{
50526df6
LB
1238 acpi_status status;
1239 struct acpi_table_ecdt *ecdt_ptr;
45bea155 1240
50526df6
LB
1241 status = acpi_get_firmware_table("ECDT", 1, ACPI_LOGICAL_ADDRESSING,
1242 (struct acpi_table_header **)
1243 &ecdt_ptr);
45bea155
LY
1244 if (ACPI_FAILURE(status))
1245 return -ENODEV;
1246
1247 printk(KERN_INFO PREFIX "Found ECDT\n");
1248
1249 /*
1250 * Generate a temporary ec context to use until the namespace is scanned
1251 */
1252 ec_ecdt = kmalloc(sizeof(union acpi_ec), GFP_KERNEL);
1253 if (!ec_ecdt)
1254 return -ENOMEM;
1255 memset(ec_ecdt, 0, sizeof(union acpi_ec));
1256
1257 ec_ecdt->common.command_addr = ecdt_ptr->ec_control;
1258 ec_ecdt->common.status_addr = ecdt_ptr->ec_control;
1259 ec_ecdt->common.data_addr = ecdt_ptr->ec_data;
1260 ec_ecdt->common.gpe_bit = ecdt_ptr->gpe_bit;
f9a6ee1a 1261 init_MUTEX(&ec_ecdt->poll.sem);
45bea155
LY
1262 /* use the GL just to be safe */
1263 ec_ecdt->common.global_lock = TRUE;
1264 ec_ecdt->common.uid = ecdt_ptr->uid;
1265
50526df6
LB
1266 status =
1267 acpi_get_handle(NULL, ecdt_ptr->ec_id, &ec_ecdt->common.handle);
45bea155
LY
1268 if (ACPI_FAILURE(status)) {
1269 goto error;
1270 }
1271
1272 return 0;
50526df6 1273 error:
45bea155
LY
1274 printk(KERN_ERR PREFIX "Could not use ECDT\n");
1275 kfree(ec_ecdt);
1276 ec_ecdt = NULL;
1277
1278 return -ENODEV;
1279}
1280
02b28a33 1281static int __init acpi_ec_intr_get_real_ecdt(void)
1da177e4 1282{
50526df6
LB
1283 acpi_status status;
1284 struct acpi_table_ecdt *ecdt_ptr;
1da177e4 1285
451566f4 1286 status = acpi_get_firmware_table("ECDT", 1, ACPI_LOGICAL_ADDRESSING,
50526df6
LB
1287 (struct acpi_table_header **)
1288 &ecdt_ptr);
1da177e4
LT
1289 if (ACPI_FAILURE(status))
1290 return -ENODEV;
1291
1292 printk(KERN_INFO PREFIX "Found ECDT\n");
1293
1294 /*
1295 * Generate a temporary ec context to use until the namespace is scanned
1296 */
45bea155 1297 ec_ecdt = kmalloc(sizeof(union acpi_ec), GFP_KERNEL);
1da177e4
LT
1298 if (!ec_ecdt)
1299 return -ENOMEM;
45bea155
LY
1300 memset(ec_ecdt, 0, sizeof(union acpi_ec));
1301
02b28a33
LB
1302 init_MUTEX(&ec_ecdt->intr.sem);
1303 init_waitqueue_head(&ec_ecdt->intr.wait);
45bea155
LY
1304 ec_ecdt->common.command_addr = ecdt_ptr->ec_control;
1305 ec_ecdt->common.status_addr = ecdt_ptr->ec_control;
1306 ec_ecdt->common.data_addr = ecdt_ptr->ec_data;
1307 ec_ecdt->common.gpe_bit = ecdt_ptr->gpe_bit;
1da177e4 1308 /* use the GL just to be safe */
45bea155
LY
1309 ec_ecdt->common.global_lock = TRUE;
1310 ec_ecdt->common.uid = ecdt_ptr->uid;
1da177e4 1311
50526df6
LB
1312 status =
1313 acpi_get_handle(NULL, ecdt_ptr->ec_id, &ec_ecdt->common.handle);
1da177e4
LT
1314 if (ACPI_FAILURE(status)) {
1315 goto error;
1316 }
1317
1318 return 0;
50526df6 1319 error:
1da177e4
LT
1320 printk(KERN_ERR PREFIX "Could not use ECDT\n");
1321 kfree(ec_ecdt);
1322 ec_ecdt = NULL;
1323
1324 return -ENODEV;
1325}
1326
1327static int __initdata acpi_fake_ecdt_enabled;
50526df6 1328int __init acpi_ec_ecdt_probe(void)
1da177e4 1329{
50526df6
LB
1330 acpi_status status;
1331 int ret;
1da177e4
LT
1332
1333 ret = acpi_ec_get_real_ecdt();
1334 /* Try to make a fake ECDT */
1335 if (ret && acpi_fake_ecdt_enabled) {
1336 ret = acpi_ec_fake_ecdt();
1337 }
1338
1339 if (ret)
1340 return 0;
1341
1342 /*
1343 * Install GPE handler
1344 */
45bea155 1345 status = acpi_install_gpe_handler(NULL, ec_ecdt->common.gpe_bit,
50526df6
LB
1346 ACPI_GPE_EDGE_TRIGGERED,
1347 &acpi_ec_gpe_handler, ec_ecdt);
1da177e4
LT
1348 if (ACPI_FAILURE(status)) {
1349 goto error;
1350 }
50526df6
LB
1351 acpi_set_gpe_type(NULL, ec_ecdt->common.gpe_bit, ACPI_GPE_TYPE_RUNTIME);
1352 acpi_enable_gpe(NULL, ec_ecdt->common.gpe_bit, ACPI_NOT_ISR);
1353
1354 status = acpi_install_address_space_handler(ACPI_ROOT_OBJECT,
1355 ACPI_ADR_SPACE_EC,
1356 &acpi_ec_space_handler,
1357 &acpi_ec_space_setup,
1358 ec_ecdt);
1da177e4 1359 if (ACPI_FAILURE(status)) {
45bea155 1360 acpi_remove_gpe_handler(NULL, ec_ecdt->common.gpe_bit,
50526df6 1361 &acpi_ec_gpe_handler);
1da177e4
LT
1362 goto error;
1363 }
1364
1365 return 0;
1366
50526df6 1367 error:
1da177e4
LT
1368 printk(KERN_ERR PREFIX "Could not use ECDT\n");
1369 kfree(ec_ecdt);
1370 ec_ecdt = NULL;
1371
1372 return -ENODEV;
1373}
1374
50526df6 1375static int __init acpi_ec_init(void)
1da177e4 1376{
50526df6 1377 int result = 0;
1da177e4 1378
1da177e4
LT
1379
1380 if (acpi_disabled)
d550d98d 1381 return 0;
1da177e4
LT
1382
1383 acpi_ec_dir = proc_mkdir(ACPI_EC_CLASS, acpi_root_dir);
1384 if (!acpi_ec_dir)
d550d98d 1385 return -ENODEV;
1da177e4
LT
1386
1387 /* Now register the driver for the EC */
1388 result = acpi_bus_register_driver(&acpi_ec_driver);
1389 if (result < 0) {
1390 remove_proc_entry(ACPI_EC_CLASS, acpi_root_dir);
d550d98d 1391 return -ENODEV;
1da177e4
LT
1392 }
1393
d550d98d 1394 return result;
1da177e4
LT
1395}
1396
1397subsys_initcall(acpi_ec_init);
1398
1399/* EC driver currently not unloadable */
1400#if 0
50526df6 1401static void __exit acpi_ec_exit(void)
1da177e4 1402{
1da177e4
LT
1403
1404 acpi_bus_unregister_driver(&acpi_ec_driver);
1405
1406 remove_proc_entry(ACPI_EC_CLASS, acpi_root_dir);
1407
d550d98d 1408 return;
1da177e4 1409}
50526df6 1410#endif /* 0 */
1da177e4
LT
1411
1412static int __init acpi_fake_ecdt_setup(char *str)
1413{
1414 acpi_fake_ecdt_enabled = 1;
9b41046c 1415 return 1;
1da177e4 1416}
7b15f5e7 1417
1da177e4 1418__setup("acpi_fake_ecdt", acpi_fake_ecdt_setup);
02b28a33 1419static int __init acpi_ec_set_intr_mode(char *str)
45bea155 1420{
02b28a33 1421 int intr;
7b15f5e7 1422
02b28a33 1423 if (!get_option(&str, &intr))
7b15f5e7
LY
1424 return 0;
1425
02b28a33
LB
1426 if (intr) {
1427 acpi_ec_poll_mode = EC_INTR;
1428 acpi_ec_driver.ops.add = acpi_ec_intr_add;
7b15f5e7 1429 } else {
02b28a33
LB
1430 acpi_ec_poll_mode = EC_POLL;
1431 acpi_ec_driver.ops.add = acpi_ec_poll_add;
7b15f5e7 1432 }
02b28a33 1433 printk(KERN_INFO PREFIX "EC %s mode.\n", intr ? "interrupt" : "polling");
9b41046c 1434 return 1;
45bea155 1435}
50526df6 1436
53f11d4f 1437__setup("ec_intr=", acpi_ec_set_intr_mode);
This page took 0.311259 seconds and 5 git commands to generate.