acpi_ec.c revision 1.52.12.2 1 /* $NetBSD: acpi_ec.c,v 1.52.12.2 2009/07/23 23:31:45 jym Exp $ */
2
3 /*-
4 * Copyright (c) 2007 Joerg Sonnenberger <joerg (at) NetBSD.org>.
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 *
11 * 1. Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in
15 * the documentation and/or other materials provided with the
16 * distribution.
17 *
18 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
19 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
20 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
21 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
22 * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
23 * INCIDENTAL, SPECIAL, EXEMPLARY OR CONSEQUENTIAL DAMAGES (INCLUDING,
24 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
25 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
26 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
27 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
28 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
30 */
31
32 /*
33 * The ACPI Embedded Controller (EC) driver serves two different purposes:
34 * - read and write access from ASL, e.g. to read battery state
35 * - notification of ASL of System Control Interrupts.
36 *
37 * Access to the EC is serialised by sc_access_mtx and optionally the
38 * ACPI global mutex. Both locks are held until the request is fulfilled.
39 * All access to the softc has to hold sc_mtx to serialise against the GPE
40 * handler and the callout. sc_mtx is also used for wakeup conditions.
41 *
42 * SCIs are processed in a kernel thread. Handling gets a bit complicated
43 * by the lock order (sc_mtx must be acquired after sc_access_mtx and the
44 * ACPI global mutex).
45 *
46 * Read and write requests spin around for a short time as many requests
47 * can be handled instantly by the EC. During normal processing interrupt
48 * mode is used exclusively. At boot and resume time interrupts are not
49 * working and the handlers just busy loop.
50 *
51 * A callout is scheduled to compensate for missing interrupts on some
52 * hardware. If the EC doesn't process a request for 5s, it is most likely
53 * in a wedged state. No method to reset the EC is currently known.
54 *
55 * Special care has to be taken to not poll the EC in a busy loop without
56 * delay. This can prevent processing of Power Button events. At least some
57 * Lenovo Thinkpads seem to be implement the Power Button Override in the EC
58 * and the only option to recover on those models is to cut off all power.
59 */
60
61 #include <sys/cdefs.h>
62 __KERNEL_RCSID(0, "$NetBSD: acpi_ec.c,v 1.52.12.2 2009/07/23 23:31:45 jym Exp $");
63
64 #include <sys/param.h>
65 #include <sys/systm.h>
66 #include <sys/condvar.h>
67 #include <sys/device.h>
68 #include <sys/kernel.h>
69 #include <sys/kthread.h>
70 #include <sys/mutex.h>
71
72 #include <sys/bus.h>
73
74 #include <dev/acpi/acpivar.h>
75 #include <dev/acpi/acpi_ecvar.h>
76
77 /* Maximum time to wait for global ACPI lock in ms */
78 #define EC_LOCK_TIMEOUT 5
79
80 /* Maximum time to poll for completion of a command in ms */
81 #define EC_POLL_TIMEOUT 5
82
83 /* Maximum time to give a single EC command in s */
84 #define EC_CMD_TIMEOUT 10
85
86 /* From ACPI 3.0b, chapter 12.3 */
87 #define EC_COMMAND_READ 0x80
88 #define EC_COMMAND_WRITE 0x81
89 #define EC_COMMAND_BURST_EN 0x82
90 #define EC_COMMAND_BURST_DIS 0x83
91 #define EC_COMMAND_QUERY 0x84
92
93 /* From ACPI 3.0b, chapter 12.2.1 */
94 #define EC_STATUS_OBF 0x01
95 #define EC_STATUS_IBF 0x02
96 #define EC_STATUS_CMD 0x08
97 #define EC_STATUS_BURST 0x10
98 #define EC_STATUS_SCI 0x20
99 #define EC_STATUS_SMI 0x40
100
101 static const char *ec_hid[] = {
102 "PNP0C09",
103 NULL,
104 };
105
106 enum ec_state_t {
107 EC_STATE_QUERY,
108 EC_STATE_QUERY_VAL,
109 EC_STATE_READ,
110 EC_STATE_READ_ADDR,
111 EC_STATE_READ_VAL,
112 EC_STATE_WRITE,
113 EC_STATE_WRITE_ADDR,
114 EC_STATE_WRITE_VAL,
115 EC_STATE_FREE
116 };
117
118 struct acpiec_softc {
119 ACPI_HANDLE sc_ech;
120
121 ACPI_HANDLE sc_gpeh;
122 UINT8 sc_gpebit;
123
124 bus_space_tag_t sc_data_st;
125 bus_space_handle_t sc_data_sh;
126
127 bus_space_tag_t sc_csr_st;
128 bus_space_handle_t sc_csr_sh;
129
130 bool sc_need_global_lock;
131 UINT32 sc_global_lock;
132
133 kmutex_t sc_mtx, sc_access_mtx;
134 kcondvar_t sc_cv, sc_cv_sci;
135 enum ec_state_t sc_state;
136 bool sc_got_sci;
137 callout_t sc_pseudo_intr;
138
139 uint8_t sc_cur_addr, sc_cur_val;
140 };
141
142 static int acpiecdt_match(device_t, cfdata_t, void *);
143 static void acpiecdt_attach(device_t, device_t, void *);
144
145 static int acpiec_match(device_t, cfdata_t, void *);
146 static void acpiec_attach(device_t, device_t, void *);
147
148 static void acpiec_common_attach(device_t, device_t, ACPI_HANDLE,
149 bus_addr_t, bus_addr_t, ACPI_HANDLE, uint8_t);
150
151 static bool acpiec_suspend(device_t PMF_FN_PROTO);
152 static bool acpiec_resume(device_t PMF_FN_PROTO);
153 static bool acpiec_shutdown(device_t, int);
154
155 static bool acpiec_parse_gpe_package(device_t, ACPI_HANDLE,
156 ACPI_HANDLE *, uint8_t *);
157
158 static void acpiec_callout(void *);
159 static void acpiec_gpe_query(void *);
160 static UINT32 acpiec_gpe_handler(void *);
161 static ACPI_STATUS acpiec_space_setup(ACPI_HANDLE, UINT32, void *, void **);
162 static ACPI_STATUS acpiec_space_handler(UINT32, ACPI_PHYSICAL_ADDRESS,
163 UINT32, ACPI_INTEGER *, void *, void *);
164
165 static void acpiec_gpe_state_machine(device_t);
166
167 CFATTACH_DECL_NEW(acpiec, sizeof(struct acpiec_softc),
168 acpiec_match, acpiec_attach, NULL, NULL);
169
170 CFATTACH_DECL_NEW(acpiecdt, sizeof(struct acpiec_softc),
171 acpiecdt_match, acpiecdt_attach, NULL, NULL);
172
173 static device_t ec_singleton = NULL;
174 static bool acpiec_cold = false;
175
176 static bool
177 acpiecdt_find(device_t parent, ACPI_HANDLE *ec_handle,
178 bus_addr_t *cmd_reg, bus_addr_t *data_reg, uint8_t *gpebit)
179 {
180 ACPI_TABLE_ECDT *ecdt;
181 ACPI_STATUS rv;
182
183 rv = AcpiGetTable(ACPI_SIG_ECDT, 1, (ACPI_TABLE_HEADER **)&ecdt);
184 if (ACPI_FAILURE(rv))
185 return false;
186
187 if (ecdt->Control.BitWidth != 8 || ecdt->Data.BitWidth != 8) {
188 aprint_error_dev(parent,
189 "ECDT register width invalid (%d/%d)\n",
190 ecdt->Control.BitWidth, ecdt->Data.BitWidth);
191 return false;
192 }
193
194 rv = AcpiGetHandle(ACPI_ROOT_OBJECT, ecdt->Id, ec_handle);
195 if (ACPI_FAILURE(rv)) {
196 aprint_error_dev(parent,
197 "failed to look up EC object %s: %s\n",
198 ecdt->Id, AcpiFormatException(rv));
199 return false;
200 }
201
202 *cmd_reg = ecdt->Control.Address;
203 *data_reg = ecdt->Data.Address;
204 *gpebit = ecdt->Gpe;
205
206 return true;
207 }
208
209 static int
210 acpiecdt_match(device_t parent, cfdata_t match, void *aux)
211 {
212 ACPI_HANDLE ec_handle;
213 bus_addr_t cmd_reg, data_reg;
214 uint8_t gpebit;
215
216 if (acpiecdt_find(parent, &ec_handle, &cmd_reg, &data_reg, &gpebit))
217 return 1;
218 else
219 return 0;
220 }
221
222 static void
223 acpiecdt_attach(device_t parent, device_t self, void *aux)
224 {
225 ACPI_HANDLE ec_handle;
226 bus_addr_t cmd_reg, data_reg;
227 uint8_t gpebit;
228
229 if (!acpiecdt_find(parent, &ec_handle, &cmd_reg, &data_reg, &gpebit))
230 panic("ECDT disappeared");
231
232 aprint_naive("\n");
233 aprint_normal(": ACPI Embedded Controller via ECDT\n");
234
235 acpiec_common_attach(parent, self, ec_handle, cmd_reg, data_reg,
236 NULL, gpebit);
237 }
238
239 static int
240 acpiec_match(device_t parent, cfdata_t match, void *aux)
241 {
242 struct acpi_attach_args *aa = aux;
243
244 if (aa->aa_node->ad_type != ACPI_TYPE_DEVICE)
245 return 0;
246
247 return acpi_match_hid(aa->aa_node->ad_devinfo, ec_hid);
248 }
249
250 static void
251 acpiec_attach(device_t parent, device_t self, void *aux)
252 {
253 struct acpi_attach_args *aa = aux;
254 struct acpi_resources ec_res;
255 struct acpi_io *io0, *io1;
256 ACPI_HANDLE gpe_handle;
257 uint8_t gpebit;
258 ACPI_STATUS rv;
259
260 if (ec_singleton != NULL) {
261 aprint_naive(": using %s\n", device_xname(ec_singleton));
262 aprint_normal(": using %s\n", device_xname(ec_singleton));
263 if (!pmf_device_register(self, NULL, NULL))
264 aprint_error_dev(self, "couldn't establish power handler\n");
265 return;
266 }
267
268 if (!acpiec_parse_gpe_package(self, aa->aa_node->ad_handle,
269 &gpe_handle, &gpebit))
270 return;
271
272 rv = acpi_resource_parse(self, aa->aa_node->ad_handle, "_CRS",
273 &ec_res, &acpi_resource_parse_ops_default);
274 if (rv != AE_OK) {
275 aprint_error_dev(self, "resource parsing failed: %s\n",
276 AcpiFormatException(rv));
277 return;
278 }
279
280 if ((io0 = acpi_res_io(&ec_res, 0)) == NULL) {
281 aprint_error_dev(self, "no data register resource\n");
282 goto free_res;
283 }
284 if ((io1 = acpi_res_io(&ec_res, 1)) == NULL) {
285 aprint_error_dev(self, "no CSR register resource\n");
286 goto free_res;
287 }
288
289 acpiec_common_attach(parent, self, aa->aa_node->ad_handle,
290 io1->ar_base, io0->ar_base, gpe_handle, gpebit);
291
292 free_res:
293 acpi_resource_cleanup(&ec_res);
294 }
295
296 static void
297 acpiec_common_attach(device_t parent, device_t self,
298 ACPI_HANDLE ec_handle, bus_addr_t cmd_reg, bus_addr_t data_reg,
299 ACPI_HANDLE gpe_handle, uint8_t gpebit)
300 {
301 struct acpiec_softc *sc = device_private(self);
302 ACPI_STATUS rv;
303 ACPI_INTEGER val;
304
305 sc->sc_ech = ec_handle;
306 sc->sc_gpeh = gpe_handle;
307 sc->sc_gpebit = gpebit;
308
309 sc->sc_state = EC_STATE_FREE;
310 mutex_init(&sc->sc_mtx, MUTEX_DRIVER, IPL_TTY);
311 mutex_init(&sc->sc_access_mtx, MUTEX_DEFAULT, IPL_NONE);
312 cv_init(&sc->sc_cv, "eccv");
313 cv_init(&sc->sc_cv_sci, "ecsci");
314
315 if (bus_space_map(sc->sc_data_st, data_reg, 1, 0,
316 &sc->sc_data_sh) != 0) {
317 aprint_error_dev(self, "unable to map data register\n");
318 return;
319 }
320
321 if (bus_space_map(sc->sc_csr_st, cmd_reg, 1, 0, &sc->sc_csr_sh) != 0) {
322 aprint_error_dev(self, "unable to map CSR register\n");
323 goto post_data_map;
324 }
325
326 rv = acpi_eval_integer(sc->sc_ech, "_GLK", &val);
327 if (rv == AE_OK) {
328 sc->sc_need_global_lock = val != 0;
329 } else if (rv != AE_NOT_FOUND) {
330 aprint_error_dev(self, "unable to evaluate _GLK: %s\n",
331 AcpiFormatException(rv));
332 goto post_csr_map;
333 } else {
334 sc->sc_need_global_lock = false;
335 }
336 if (sc->sc_need_global_lock)
337 aprint_normal_dev(self, "using global ACPI lock\n");
338
339 callout_init(&sc->sc_pseudo_intr, CALLOUT_MPSAFE);
340 callout_setfunc(&sc->sc_pseudo_intr, acpiec_callout, self);
341
342 rv = AcpiInstallAddressSpaceHandler(sc->sc_ech, ACPI_ADR_SPACE_EC,
343 acpiec_space_handler, acpiec_space_setup, self);
344 if (rv != AE_OK) {
345 aprint_error_dev(self,
346 "unable to install address space handler: %s\n",
347 AcpiFormatException(rv));
348 goto post_csr_map;
349 }
350
351 rv = AcpiInstallGpeHandler(sc->sc_gpeh, sc->sc_gpebit,
352 ACPI_GPE_EDGE_TRIGGERED, acpiec_gpe_handler, self);
353 if (rv != AE_OK) {
354 aprint_error_dev(self, "unable to install GPE handler: %s\n",
355 AcpiFormatException(rv));
356 goto post_csr_map;
357 }
358
359 rv = AcpiSetGpeType(sc->sc_gpeh, sc->sc_gpebit, ACPI_GPE_TYPE_RUNTIME);
360 if (rv != AE_OK) {
361 aprint_error_dev(self, "unable to set GPE type: %s\n",
362 AcpiFormatException(rv));
363 goto post_csr_map;
364 }
365
366 rv = AcpiEnableGpe(sc->sc_gpeh, sc->sc_gpebit, ACPI_ISR);
367 if (rv != AE_OK) {
368 aprint_error_dev(self, "unable to enable GPE: %s\n",
369 AcpiFormatException(rv));
370 goto post_csr_map;
371 }
372
373 if (kthread_create(PRI_NONE, KTHREAD_MPSAFE, NULL, acpiec_gpe_query,
374 self, NULL, "acpiec sci thread")) {
375 aprint_error_dev(self, "unable to create query kthread\n");
376 goto post_csr_map;
377 }
378
379 ec_singleton = self;
380
381 if (!pmf_device_register1(self, acpiec_suspend, acpiec_resume,
382 acpiec_shutdown))
383 aprint_error_dev(self, "couldn't establish power handler\n");
384
385 return;
386
387 post_csr_map:
388 (void)AcpiRemoveGpeHandler(sc->sc_gpeh, sc->sc_gpebit,
389 acpiec_gpe_handler);
390 (void)AcpiRemoveAddressSpaceHandler(sc->sc_ech,
391 ACPI_ADR_SPACE_EC, acpiec_space_handler);
392 bus_space_unmap(sc->sc_csr_st, sc->sc_csr_sh, 1);
393 post_data_map:
394 bus_space_unmap(sc->sc_data_st, sc->sc_data_sh, 1);
395 }
396
397 static bool
398 acpiec_suspend(device_t dv PMF_FN_ARGS)
399 {
400 acpiec_cold = true;
401
402 return true;
403 }
404
405 static bool
406 acpiec_resume(device_t dv PMF_FN_ARGS)
407 {
408 acpiec_cold = false;
409
410 return true;
411 }
412
413 static bool
414 acpiec_shutdown(device_t dv, int how)
415 {
416
417 acpiec_cold = true;
418 return true;
419 }
420
421 static bool
422 acpiec_parse_gpe_package(device_t self, ACPI_HANDLE ec_handle,
423 ACPI_HANDLE *gpe_handle, uint8_t *gpebit)
424 {
425 ACPI_BUFFER buf;
426 ACPI_OBJECT *p, *c;
427 ACPI_STATUS rv;
428
429 rv = acpi_eval_struct(ec_handle, "_GPE", &buf);
430 if (rv != AE_OK) {
431 aprint_error_dev(self, "unable to evaluate _GPE: %s\n",
432 AcpiFormatException(rv));
433 return false;
434 }
435
436 p = buf.Pointer;
437
438 if (p->Type == ACPI_TYPE_INTEGER) {
439 *gpe_handle = NULL;
440 *gpebit = p->Integer.Value;
441 AcpiOsFree(p);
442 return true;
443 }
444
445 if (p->Type != ACPI_TYPE_PACKAGE) {
446 aprint_error_dev(self, "_GPE is neither integer nor package\n");
447 AcpiOsFree(p);
448 return false;
449 }
450
451 if (p->Package.Count != 2) {
452 aprint_error_dev(self, "_GPE package does not contain 2 elements\n");
453 AcpiOsFree(p);
454 return false;
455 }
456
457 c = &p->Package.Elements[0];
458 switch (c->Type) {
459 case ACPI_TYPE_LOCAL_REFERENCE:
460 case ACPI_TYPE_ANY:
461 *gpe_handle = c->Reference.Handle;
462 break;
463 case ACPI_TYPE_STRING:
464 /* XXX should be using real scope here */
465 rv = AcpiGetHandle(NULL, p->String.Pointer, gpe_handle);
466 if (rv != AE_OK) {
467 aprint_error_dev(self,
468 "_GPE device reference unresolvable\n");
469 AcpiOsFree(p);
470 return false;
471 }
472 break;
473 default:
474 aprint_error_dev(self, "_GPE device reference incorrect\n");
475 AcpiOsFree(p);
476 return false;
477 }
478 c = &p->Package.Elements[1];
479 if (c->Type != ACPI_TYPE_INTEGER) {
480 aprint_error_dev(self,
481 "_GPE package needs integer as 2nd field\n");
482 AcpiOsFree(p);
483 return false;
484 }
485 *gpebit = c->Integer.Value;
486 AcpiOsFree(p);
487 return true;
488 }
489
490 static uint8_t
491 acpiec_read_data(struct acpiec_softc *sc)
492 {
493 return bus_space_read_1(sc->sc_data_st, sc->sc_data_sh, 0);
494 }
495
496 static void
497 acpiec_write_data(struct acpiec_softc *sc, uint8_t val)
498 {
499 bus_space_write_1(sc->sc_data_st, sc->sc_data_sh, 0, val);
500 }
501
502 static uint8_t
503 acpiec_read_status(struct acpiec_softc *sc)
504 {
505 return bus_space_read_1(sc->sc_csr_st, sc->sc_csr_sh, 0);
506 }
507
508 static void
509 acpiec_write_command(struct acpiec_softc *sc, uint8_t cmd)
510 {
511 bus_space_write_1(sc->sc_csr_st, sc->sc_csr_sh, 0, cmd);
512 }
513
514 static ACPI_STATUS
515 acpiec_space_setup(ACPI_HANDLE region, UINT32 func, void *arg,
516 void **region_arg)
517 {
518 if (func == ACPI_REGION_DEACTIVATE)
519 *region_arg = NULL;
520 else
521 *region_arg = arg;
522
523 return AE_OK;
524 }
525
526 static void
527 acpiec_lock(device_t dv)
528 {
529 struct acpiec_softc *sc = device_private(dv);
530 ACPI_STATUS rv;
531
532 mutex_enter(&sc->sc_access_mtx);
533
534 if (sc->sc_need_global_lock) {
535 rv = AcpiAcquireGlobalLock(EC_LOCK_TIMEOUT, &sc->sc_global_lock);
536 if (rv != AE_OK) {
537 aprint_error_dev(dv, "failed to acquire global lock: %s\n",
538 AcpiFormatException(rv));
539 return;
540 }
541 }
542 }
543
544 static void
545 acpiec_unlock(device_t dv)
546 {
547 struct acpiec_softc *sc = device_private(dv);
548 ACPI_STATUS rv;
549
550 if (sc->sc_need_global_lock) {
551 rv = AcpiReleaseGlobalLock(sc->sc_global_lock);
552 if (rv != AE_OK) {
553 aprint_error_dev(dv, "failed to release global lock: %s\n",
554 AcpiFormatException(rv));
555 }
556 }
557 mutex_exit(&sc->sc_access_mtx);
558 }
559
560 static ACPI_STATUS
561 acpiec_read(device_t dv, uint8_t addr, uint8_t *val)
562 {
563 struct acpiec_softc *sc = device_private(dv);
564 int i, timeo = 1000 * EC_CMD_TIMEOUT;
565
566 acpiec_lock(dv);
567 mutex_enter(&sc->sc_mtx);
568
569 sc->sc_cur_addr = addr;
570 sc->sc_state = EC_STATE_READ;
571
572 for (i = 0; i < EC_POLL_TIMEOUT; ++i) {
573 acpiec_gpe_state_machine(dv);
574 if (sc->sc_state == EC_STATE_FREE)
575 goto done;
576 delay(1);
577 }
578
579 if (cold || acpiec_cold) {
580 while (sc->sc_state != EC_STATE_FREE && timeo-- > 0) {
581 delay(1000);
582 acpiec_gpe_state_machine(dv);
583 }
584 if (sc->sc_state != EC_STATE_FREE) {
585 mutex_exit(&sc->sc_mtx);
586 AcpiClearGpe(sc->sc_gpeh, sc->sc_gpebit, ACPI_NOT_ISR);
587 acpiec_unlock(dv);
588 aprint_error_dev(dv, "command timed out, state %d\n",
589 sc->sc_state);
590 return AE_ERROR;
591 }
592 } else if (cv_timedwait(&sc->sc_cv, &sc->sc_mtx, EC_CMD_TIMEOUT * hz)) {
593 mutex_exit(&sc->sc_mtx);
594 AcpiClearGpe(sc->sc_gpeh, sc->sc_gpebit, ACPI_NOT_ISR);
595 acpiec_unlock(dv);
596 aprint_error_dev(dv, "command takes over %d sec...\n", EC_CMD_TIMEOUT);
597 return AE_ERROR;
598 }
599
600 done:
601 *val = sc->sc_cur_val;
602
603 mutex_exit(&sc->sc_mtx);
604 acpiec_unlock(dv);
605 return AE_OK;
606 }
607
608 static ACPI_STATUS
609 acpiec_write(device_t dv, uint8_t addr, uint8_t val)
610 {
611 struct acpiec_softc *sc = device_private(dv);
612 int i, timeo = 1000 * EC_CMD_TIMEOUT;
613
614 acpiec_lock(dv);
615 mutex_enter(&sc->sc_mtx);
616
617 sc->sc_cur_addr = addr;
618 sc->sc_cur_val = val;
619 sc->sc_state = EC_STATE_WRITE;
620
621 for (i = 0; i < EC_POLL_TIMEOUT; ++i) {
622 acpiec_gpe_state_machine(dv);
623 if (sc->sc_state == EC_STATE_FREE)
624 goto done;
625 delay(1);
626 }
627
628 if (cold || acpiec_cold) {
629 while (sc->sc_state != EC_STATE_FREE && timeo-- > 0) {
630 delay(1000);
631 acpiec_gpe_state_machine(dv);
632 }
633 if (sc->sc_state != EC_STATE_FREE) {
634 mutex_exit(&sc->sc_mtx);
635 AcpiClearGpe(sc->sc_gpeh, sc->sc_gpebit, ACPI_NOT_ISR);
636 acpiec_unlock(dv);
637 aprint_error_dev(dv, "command timed out, state %d\n",
638 sc->sc_state);
639 return AE_ERROR;
640 }
641 } else if (cv_timedwait(&sc->sc_cv, &sc->sc_mtx, EC_CMD_TIMEOUT * hz)) {
642 mutex_exit(&sc->sc_mtx);
643 AcpiClearGpe(sc->sc_gpeh, sc->sc_gpebit, ACPI_NOT_ISR);
644 acpiec_unlock(dv);
645 aprint_error_dev(dv, "command takes over %d sec...\n", EC_CMD_TIMEOUT);
646 return AE_ERROR;
647 }
648
649 done:
650 mutex_exit(&sc->sc_mtx);
651 acpiec_unlock(dv);
652 return AE_OK;
653 }
654
655 static ACPI_STATUS
656 acpiec_space_handler(UINT32 func, ACPI_PHYSICAL_ADDRESS paddr,
657 UINT32 width, ACPI_INTEGER *value, void *arg, void *region_arg)
658 {
659 device_t dv;
660 struct acpiec_softc *sc;
661 ACPI_STATUS rv;
662 uint8_t addr, reg;
663 unsigned int i;
664
665 if (paddr > 0xff || width % 8 != 0 || value == NULL || arg == NULL ||
666 paddr + width / 8 > 0xff)
667 return AE_BAD_PARAMETER;
668
669 addr = paddr;
670 dv = arg;
671 sc = device_private(dv);
672
673 rv = AE_OK;
674
675 switch (func) {
676 case ACPI_READ:
677 *value = 0;
678 for (i = 0; i < width; i += 8, ++addr) {
679 rv = acpiec_read(dv, addr, ®);
680 if (rv != AE_OK)
681 break;
682 *value |= (ACPI_INTEGER)reg << i;
683 }
684 break;
685 case ACPI_WRITE:
686 for (i = 0; i < width; i += 8, ++addr) {
687 reg = (*value >>i) & 0xff;
688 rv = acpiec_write(dv, addr, reg);
689 if (rv != AE_OK)
690 break;
691 }
692 break;
693 default:
694 aprint_error("%s: invalid Address Space function called: %x\n",
695 device_xname(dv), (unsigned int)func);
696 return AE_BAD_PARAMETER;
697 }
698
699 return rv;
700 }
701
702 static void
703 acpiec_gpe_query(void *arg)
704 {
705 device_t dv = arg;
706 struct acpiec_softc *sc = device_private(dv);
707 uint8_t reg;
708 char qxx[5];
709 ACPI_STATUS rv;
710 int i;
711
712 loop:
713 mutex_enter(&sc->sc_mtx);
714
715 if (sc->sc_got_sci == false)
716 cv_wait(&sc->sc_cv_sci, &sc->sc_mtx);
717 mutex_exit(&sc->sc_mtx);
718
719 acpiec_lock(dv);
720 mutex_enter(&sc->sc_mtx);
721
722 /* The Query command can always be issued, so be defensive here. */
723 sc->sc_got_sci = false;
724 sc->sc_state = EC_STATE_QUERY;
725
726 for (i = 0; i < EC_POLL_TIMEOUT; ++i) {
727 acpiec_gpe_state_machine(dv);
728 if (sc->sc_state == EC_STATE_FREE)
729 goto done;
730 delay(1);
731 }
732
733 cv_wait(&sc->sc_cv, &sc->sc_mtx);
734
735 done:
736 reg = sc->sc_cur_val;
737
738 mutex_exit(&sc->sc_mtx);
739 acpiec_unlock(dv);
740
741 if (reg == 0)
742 goto loop; /* Spurious query result */
743
744 /*
745 * Evaluate _Qxx to respond to the controller.
746 */
747 snprintf(qxx, sizeof(qxx), "_Q%02X", (unsigned int)reg);
748 rv = AcpiEvaluateObject(sc->sc_ech, qxx, NULL, NULL);
749 if (rv != AE_OK && rv != AE_NOT_FOUND) {
750 aprint_error("%s: GPE query method %s failed: %s",
751 device_xname(dv), qxx, AcpiFormatException(rv));
752 }
753
754 goto loop;
755 }
756
757 static void
758 acpiec_gpe_state_machine(device_t dv)
759 {
760 struct acpiec_softc *sc = device_private(dv);
761 uint8_t reg;
762
763 reg = acpiec_read_status(sc);
764
765 if (reg & EC_STATUS_SCI)
766 sc->sc_got_sci = true;
767
768 switch (sc->sc_state) {
769 case EC_STATE_QUERY:
770 if ((reg & EC_STATUS_IBF) != 0)
771 break; /* Nothing of interest here. */
772 acpiec_write_command(sc, EC_COMMAND_QUERY);
773 sc->sc_state = EC_STATE_QUERY_VAL;
774 break;
775
776 case EC_STATE_QUERY_VAL:
777 if ((reg & EC_STATUS_OBF) == 0)
778 break; /* Nothing of interest here. */
779
780 sc->sc_cur_val = acpiec_read_data(sc);
781 sc->sc_state = EC_STATE_FREE;
782
783 cv_signal(&sc->sc_cv);
784 break;
785
786 case EC_STATE_READ:
787 if ((reg & EC_STATUS_IBF) != 0)
788 break; /* Nothing of interest here. */
789
790 acpiec_write_command(sc, EC_COMMAND_READ);
791 sc->sc_state = EC_STATE_READ_ADDR;
792 break;
793
794 case EC_STATE_READ_ADDR:
795 if ((reg & EC_STATUS_IBF) != 0)
796 break; /* Nothing of interest here. */
797
798 acpiec_write_data(sc, sc->sc_cur_addr);
799 sc->sc_state = EC_STATE_READ_VAL;
800 break;
801
802 case EC_STATE_READ_VAL:
803 if ((reg & EC_STATUS_OBF) == 0)
804 break; /* Nothing of interest here. */
805 sc->sc_cur_val = acpiec_read_data(sc);
806 sc->sc_state = EC_STATE_FREE;
807
808 cv_signal(&sc->sc_cv);
809 break;
810
811 case EC_STATE_WRITE:
812 if ((reg & EC_STATUS_IBF) != 0)
813 break; /* Nothing of interest here. */
814
815 acpiec_write_command(sc, EC_COMMAND_WRITE);
816 sc->sc_state = EC_STATE_WRITE_ADDR;
817 break;
818
819 case EC_STATE_WRITE_ADDR:
820 if ((reg & EC_STATUS_IBF) != 0)
821 break; /* Nothing of interest here. */
822 acpiec_write_data(sc, sc->sc_cur_addr);
823 sc->sc_state = EC_STATE_WRITE_VAL;
824 break;
825
826 case EC_STATE_WRITE_VAL:
827 if ((reg & EC_STATUS_IBF) != 0)
828 break; /* Nothing of interest here. */
829 sc->sc_state = EC_STATE_FREE;
830 cv_signal(&sc->sc_cv);
831
832 acpiec_write_data(sc, sc->sc_cur_val);
833 break;
834
835 case EC_STATE_FREE:
836 if (sc->sc_got_sci)
837 cv_signal(&sc->sc_cv_sci);
838 break;
839 default:
840 panic("invalid state");
841 }
842
843 if (sc->sc_state != EC_STATE_FREE)
844 callout_schedule(&sc->sc_pseudo_intr, 1);
845 }
846
847 static void
848 acpiec_callout(void *arg)
849 {
850 device_t dv = arg;
851 struct acpiec_softc *sc = device_private(dv);
852
853 AcpiClearGpe(sc->sc_gpeh, sc->sc_gpebit, ACPI_NOT_ISR);
854
855 mutex_enter(&sc->sc_mtx);
856 acpiec_gpe_state_machine(dv);
857 mutex_exit(&sc->sc_mtx);
858 }
859
860 static UINT32
861 acpiec_gpe_handler(void *arg)
862 {
863 device_t dv = arg;
864 struct acpiec_softc *sc = device_private(dv);
865
866 AcpiClearGpe(sc->sc_gpeh, sc->sc_gpebit, ACPI_ISR);
867
868 mutex_enter(&sc->sc_mtx);
869 acpiec_gpe_state_machine(dv);
870 mutex_exit(&sc->sc_mtx);
871
872 return 0;
873 }
874
875 ACPI_STATUS
876 acpiec_bus_read(device_t dv, u_int addr, ACPI_INTEGER *val, int width)
877 {
878 return acpiec_space_handler(ACPI_READ, addr, width * 8, val, dv, NULL);
879 }
880
881 ACPI_STATUS
882 acpiec_bus_write(device_t dv, u_int addr, ACPI_INTEGER val, int width)
883 {
884 return acpiec_space_handler(ACPI_WRITE, addr, width * 8, &val, dv, NULL);
885 }
886
887 ACPI_HANDLE
888 acpiec_get_handle(device_t dv)
889 {
890 struct acpiec_softc *sc = device_private(dv);
891
892 return sc->sc_ech;
893 }
894