acpi_ec.c revision 1.16 1 /* $NetBSD: acpi_ec.c,v 1.16 2003/11/03 06:03:47 kochi Exp $ */
2
3 /*
4 * Copyright 2001 Wasabi Systems, Inc.
5 * All rights reserved.
6 *
7 * Written by Jason R. Thorpe for Wasabi Systems, Inc.
8 *
9 * Redistribution and use in source and binary forms, with or without
10 * modification, are permitted provided that the following conditions
11 * are met:
12 * 1. Redistributions of source code must retain the above copyright
13 * notice, this list of conditions and the following disclaimer.
14 * 2. Redistributions in binary form must reproduce the above copyright
15 * notice, this list of conditions and the following disclaimer in the
16 * documentation and/or other materials provided with the distribution.
17 * 3. All advertising materials mentioning features or use of this software
18 * must display the following acknowledgement:
19 * This product includes software developed for the NetBSD Project by
20 * Wasabi Systems, Inc.
21 * 4. The name of Wasabi Systems, Inc. may not be used to endorse
22 * or promote products derived from this software without specific prior
23 * written permission.
24 *
25 * THIS SOFTWARE IS PROVIDED BY WASABI SYSTEMS, INC. ``AS IS'' AND
26 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
27 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
28 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL WASABI SYSTEMS, INC
29 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
30 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
31 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
32 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
33 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
34 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
35 * POSSIBILITY OF SUCH DAMAGE.
36 */
37
38 /*-
39 * Copyright (c) 2000 Michael Smith
40 * Copyright (c) 2000 BSDi
41 * All rights reserved.
42 *
43 * Redistribution and use in source and binary forms, with or without
44 * modification, are permitted provided that the following conditions
45 * are met:
46 * 1. Redistributions of source code must retain the above copyright
47 * notice, this list of conditions and the following disclaimer.
48 * 2. Redistributions in binary form must reproduce the above copyright
49 * notice, this list of conditions and the following disclaimer in the
50 * documentation and/or other materials provided with the distribution.
51 *
52 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
53 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
54 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
55 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
56 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
57 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
58 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
59 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
60 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
61 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
62 * SUCH DAMAGE.
63 */
64
65 /******************************************************************************
66 *
67 * 1. Copyright Notice
68 *
69 * Some or all of this work - Copyright (c) 1999, Intel Corp. All rights
70 * reserved.
71 *
72 * 2. License
73 *
74 * 2.1. This is your license from Intel Corp. under its intellectual property
75 * rights. You may have additional license terms from the party that provided
76 * you this software, covering your right to use that party's intellectual
77 * property rights.
78 *
79 * 2.2. Intel grants, free of charge, to any person ("Licensee") obtaining a
80 * copy of the source code appearing in this file ("Covered Code") an
81 * irrevocable, perpetual, worldwide license under Intel's copyrights in the
82 * base code distributed originally by Intel ("Original Intel Code") to copy,
83 * make derivatives, distribute, use and display any portion of the Covered
84 * Code in any form, with the right to sublicense such rights; and
85 *
86 * 2.3. Intel grants Licensee a non-exclusive and non-transferable patent
87 * license (with the right to sublicense), under only those claims of Intel
88 * patents that are infringed by the Original Intel Code, to make, use, sell,
89 * offer to sell, and import the Covered Code and derivative works thereof
90 * solely to the minimum extent necessary to exercise the above copyright
91 * license, and in no event shall the patent license extend to any additions
92 * to or modifications of the Original Intel Code. No other license or right
93 * is granted directly or by implication, estoppel or otherwise;
94 *
95 * The above copyright and patent license is granted only if the following
96 * conditions are met:
97 *
98 * 3. Conditions
99 *
100 * 3.1. Redistribution of Source with Rights to Further Distribute Source.
101 * Redistribution of source code of any substantial portion of the Covered
102 * Code or modification with rights to further distribute source must include
103 * the above Copyright Notice, the above License, this list of Conditions,
104 * and the following Disclaimer and Export Compliance provision. In addition,
105 * Licensee must cause all Covered Code to which Licensee contributes to
106 * contain a file documenting the changes Licensee made to create that Covered
107 * Code and the date of any change. Licensee must include in that file the
108 * documentation of any changes made by any predecessor Licensee. Licensee
109 * must include a prominent statement that the modification is derived,
110 * directly or indirectly, from Original Intel Code.
111 *
112 * 3.2. Redistribution of Source with no Rights to Further Distribute Source.
113 * Redistribution of source code of any substantial portion of the Covered
114 * Code or modification without rights to further distribute source must
115 * include the following Disclaimer and Export Compliance provision in the
116 * documentation and/or other materials provided with distribution. In
117 * addition, Licensee may not authorize further sublicense of source of any
118 * portion of the Covered Code, and must include terms to the effect that the
119 * license from Licensee to its licensee is limited to the intellectual
120 * property embodied in the software Licensee provides to its licensee, and
121 * not to intellectual property embodied in modifications its licensee may
122 * make.
123 *
124 * 3.3. Redistribution of Executable. Redistribution in executable form of any
125 * substantial portion of the Covered Code or modification must reproduce the
126 * above Copyright Notice, and the following Disclaimer and Export Compliance
127 * provision in the documentation and/or other materials provided with the
128 * distribution.
129 *
130 * 3.4. Intel retains all right, title, and interest in and to the Original
131 * Intel Code.
132 *
133 * 3.5. Neither the name Intel nor any other trademark owned or controlled by
134 * Intel shall be used in advertising or otherwise to promote the sale, use or
135 * other dealings in products derived from or relating to the Covered Code
136 * without prior written authorization from Intel.
137 *
138 * 4. Disclaimer and Export Compliance
139 *
140 * 4.1. INTEL MAKES NO WARRANTY OF ANY KIND REGARDING ANY SOFTWARE PROVIDED
141 * HERE. ANY SOFTWARE ORIGINATING FROM INTEL OR DERIVED FROM INTEL SOFTWARE
142 * IS PROVIDED "AS IS," AND INTEL WILL NOT PROVIDE ANY SUPPORT, ASSISTANCE,
143 * INSTALLATION, TRAINING OR OTHER SERVICES. INTEL WILL NOT PROVIDE ANY
144 * UPDATES, ENHANCEMENTS OR EXTENSIONS. INTEL SPECIFICALLY DISCLAIMS ANY
145 * IMPLIED WARRANTIES OF MERCHANTABILITY, NONINFRINGEMENT AND FITNESS FOR A
146 * PARTICULAR PURPOSE.
147 *
148 * 4.2. IN NO EVENT SHALL INTEL HAVE ANY LIABILITY TO LICENSEE, ITS LICENSEES
149 * OR ANY OTHER THIRD PARTY, FOR ANY LOST PROFITS, LOST DATA, LOSS OF USE OR
150 * COSTS OF PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, OR FOR ANY INDIRECT,
151 * SPECIAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THIS AGREEMENT, UNDER ANY
152 * CAUSE OF ACTION OR THEORY OF LIABILITY, AND IRRESPECTIVE OF WHETHER INTEL
153 * HAS ADVANCE NOTICE OF THE POSSIBILITY OF SUCH DAMAGES. THESE LIMITATIONS
154 * SHALL APPLY NOTWITHSTANDING THE FAILURE OF THE ESSENTIAL PURPOSE OF ANY
155 * LIMITED REMEDY.
156 *
157 * 4.3. Licensee shall not export, either directly or indirectly, any of this
158 * software or system incorporating such software without first obtaining any
159 * required license or other approval from the U. S. Department of Commerce or
160 * any other agency or department of the United States Government. In the
161 * event Licensee exports any such software from the United States or
162 * re-exports any such software from a foreign destination, Licensee shall
163 * ensure that the distribution and export/re-export of the software is in
164 * compliance with all laws, regulations, orders, or other restrictions of the
165 * U.S. Export Administration Regulations. Licensee agrees that neither it nor
166 * any of its subsidiaries will export/re-export any technical data, process,
167 * software, or service, directly or indirectly, to any country for which the
168 * United States government or any agency thereof requires an export license,
169 * other governmental approval, or letter of assurance, without first obtaining
170 * such license, approval or letter.
171 *
172 *****************************************************************************/
173
174 #include <sys/cdefs.h>
175 __KERNEL_RCSID(0, "$NetBSD: acpi_ec.c,v 1.16 2003/11/03 06:03:47 kochi Exp $");
176
177 #include <sys/param.h>
178 #include <sys/systm.h>
179 #include <sys/device.h>
180 #include <sys/proc.h>
181 #include <sys/kernel.h>
182
183 #include <machine/bus.h>
184
185 #include <dev/acpi/acpica.h>
186 #include <dev/acpi/acpireg.h>
187 #include <dev/acpi/acpivar.h>
188 #include <dev/acpi/acpi_ecreg.h>
189
190 #define _COMPONENT ACPI_EC_COMPONENT
191 ACPI_MODULE_NAME("EC")
192
193 struct acpi_ec_softc {
194 struct device sc_dev; /* base device glue */
195 struct acpi_devnode *sc_node; /* our ACPI devnode */
196
197 struct acpi_resources sc_res; /* our bus resources */
198
199 UINT32 sc_gpebit; /* our GPE interrupt bit */
200
201 bus_space_tag_t sc_data_st; /* space tag for data register */
202 bus_space_handle_t sc_data_sh; /* space handle for data register */
203
204 bus_space_tag_t sc_csr_st; /* space tag for control register */
205 bus_space_handle_t sc_csr_sh; /* space handle for control register */
206
207 int sc_flags; /* see below */
208
209 uint32_t sc_csrvalue; /* saved control register */
210 };
211
212 static const char * const ec_hid[] = {
213 "PNP0C09",
214 NULL
215 };
216
217 #define EC_F_LOCKED 0x01 /* EC is locked */
218 #define EC_F_PENDQUERY 0x02 /* query is pending */
219
220 #define EC_DATA_READ(sc) \
221 bus_space_read_1((sc)->sc_data_st, (sc)->sc_data_sh, 0)
222 #define EC_DATA_WRITE(sc, v) \
223 bus_space_write_1((sc)->sc_data_st, (sc)->sc_data_sh, 0, (v))
224
225 #define EC_CSR_READ(sc) \
226 bus_space_read_1((sc)->sc_csr_st, (sc)->sc_csr_sh, 0)
227 #define EC_CSR_WRITE(sc, v) \
228 bus_space_write_1((sc)->sc_csr_st, (sc)->sc_csr_sh, 0, (v))
229
230 static __inline int
231 EcIsLocked(struct acpi_ec_softc *sc)
232 {
233
234 return (sc->sc_flags & EC_F_LOCKED);
235 }
236
237 static __inline void
238 EcLock(struct acpi_ec_softc *sc)
239 {
240
241 sc->sc_flags |= EC_F_LOCKED;
242 AcpiOsAcquireLock (AcpiGbl_GpeLock, ACPI_NOT_ISR);
243 }
244
245 static __inline void
246 EcUnlock(struct acpi_ec_softc *sc)
247 {
248
249 AcpiOsReleaseLock (AcpiGbl_GpeLock, ACPI_NOT_ISR);
250 sc->sc_flags &= ~EC_F_LOCKED;
251 }
252
253 typedef struct {
254 EC_COMMAND Command;
255 UINT8 Address;
256 UINT8 Data;
257 } EC_REQUEST;
258
259 static void EcGpeHandler(void *Context);
260 static ACPI_STATUS EcSpaceSetup(ACPI_HANDLE Region, UINT32 Function,
261 void *Context, void **return_Context);
262 static ACPI_STATUS EcSpaceHandler(UINT32 Function,
263 ACPI_PHYSICAL_ADDRESS Address, UINT32 width,
264 ACPI_INTEGER *Value, void *Context,
265 void *RegionContext);
266
267 static ACPI_STATUS EcWaitEvent(struct acpi_ec_softc *sc, EC_EVENT Event);
268 static ACPI_STATUS EcQuery(struct acpi_ec_softc *sc, UINT8 *Data);
269 static ACPI_STATUS EcTransaction(struct acpi_ec_softc *sc,
270 EC_REQUEST *EcRequest);
271 static ACPI_STATUS EcRead(struct acpi_ec_softc *sc, UINT8 Address,
272 UINT8 *Data);
273 static ACPI_STATUS EcWrite(struct acpi_ec_softc *sc, UINT8 Address,
274 UINT8 *Data);
275
276 int acpiec_match(struct device *, struct cfdata *, void *);
277 void acpiec_attach(struct device *, struct device *, void *);
278
279 CFATTACH_DECL(acpiec, sizeof(struct acpi_ec_softc),
280 acpiec_match, acpiec_attach, NULL, NULL);
281
282 /*
283 * acpiec_match:
284 *
285 * Autoconfiguration `match' routine.
286 */
287 int
288 acpiec_match(struct device *parent, struct cfdata *match, void *aux)
289 {
290 struct acpi_attach_args *aa = aux;
291
292 if (aa->aa_node->ad_type != ACPI_TYPE_DEVICE)
293 return (0);
294
295 return (acpi_match_hid(aa->aa_node->ad_devinfo, ec_hid));
296 }
297
298 /*
299 * acpiec_attach:
300 *
301 * Autoconfiguration `attach' routine.
302 */
303 void
304 acpiec_attach(struct device *parent, struct device *self, void *aux)
305 {
306 struct acpi_ec_softc *sc = (void *) self;
307 struct acpi_attach_args *aa = aux;
308 struct acpi_io *io0, *io1;
309 ACPI_STATUS rv;
310
311 ACPI_FUNCTION_TRACE(__FUNCTION__);
312
313 printf(": ACPI Embedded Controller\n");
314
315 sc->sc_node = aa->aa_node;
316
317 /* Parse our resources. */
318 ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES, "parsing EC resources\n"));
319 rv = acpi_resource_parse(&sc->sc_dev, sc->sc_node, &sc->sc_res,
320 &acpi_resource_parse_ops_default);
321 if (rv != AE_OK) {
322 printf("%s: unable to parse resources: %d\n",
323 sc->sc_dev.dv_xname, rv);
324 return;
325 }
326
327 sc->sc_data_st = aa->aa_iot;
328 io0 = acpi_res_io(&sc->sc_res, 0);
329 if (io0 == NULL) {
330 printf("%s: unable to find data register resource\n",
331 sc->sc_dev.dv_xname);
332 return;
333 }
334 if (bus_space_map(sc->sc_data_st, io0->ar_base, io0->ar_length,
335 0, &sc->sc_data_sh) != 0) {
336 printf("%s: unable to map data register\n",
337 sc->sc_dev.dv_xname);
338 return;
339 }
340
341 sc->sc_csr_st = aa->aa_iot;
342 io1 = acpi_res_io(&sc->sc_res, 1);
343 if (io1 == NULL) {
344 printf("%s: unable to find csr register resource\n",
345 sc->sc_dev.dv_xname);
346 return;
347 }
348 if (bus_space_map(sc->sc_csr_st, io1->ar_base, io1->ar_length,
349 0, &sc->sc_csr_sh) != 0) {
350 printf("%s: unable to map csr register\n",
351 sc->sc_dev.dv_xname);
352 return;
353 }
354
355 /*
356 * Install GPE handler.
357 *
358 * We evaluate the _GPE method to find the GPE bit used by the
359 * Embedded Controller to signal status (SCI).
360 */
361 if ((rv = acpi_eval_integer(sc->sc_node->ad_handle, "_GPE",
362 &sc->sc_gpebit)) != AE_OK) {
363 printf("%s: unable to evaluate _GPE: %d\n",
364 sc->sc_dev.dv_xname, rv);
365 return;
366 }
367
368 /*
369 * Install a handler for this EC's GPE bit. Note that EC SCIs are
370 * treated as both edge- and level-triggered interrupts; in other words
371 * we clear the status bit immediately after getting an EC-SCI, then
372 * again after we're done processing the event. This guarantees that
373 * events we cause while performing a transaction (e.g. IBE/OBF) get
374 * cleared before re-enabling the GPE.
375 */
376 if ((rv = AcpiInstallGpeHandler(NULL, sc->sc_gpebit,
377 ACPI_EVENT_EDGE_TRIGGERED, EcGpeHandler, sc)) != AE_OK) {
378 printf("%s: unable to install GPE handler: %d\n",
379 sc->sc_dev.dv_xname, rv);
380 return;
381 }
382
383 /* Install address space handler. */
384 if ((rv = AcpiInstallAddressSpaceHandler(sc->sc_node->ad_handle,
385 ACPI_ADR_SPACE_EC, EcSpaceHandler, EcSpaceSetup, sc)) != AE_OK) {
386 printf("%s: unable to install address space handler: %d\n",
387 sc->sc_dev.dv_xname, rv);
388 return;
389 }
390
391 return_VOID;
392 }
393
394 static void
395 EcGpeQueryHandler(void *Context)
396 {
397 struct acpi_ec_softc *sc = Context;
398 UINT8 Data;
399 ACPI_STATUS Status;
400 char qxx[5];
401
402 ACPI_FUNCTION_TRACE(__FUNCTION__);
403
404 for (;;) {
405 /*
406 * Check EC_SCI.
407 *
408 * Bail out if the EC_SCI bit of the status register is not
409 * set. Note that this function should only be called when
410 * this bit is set (polling is used to detect IBE/OBF events).
411 *
412 * It is safe to do this without locking the controller, as
413 * it's OK to call EcQuery when there's no data ready; in the
414 * worst case we should just find nothing waiting for us and
415 * bail.
416 */
417 if ((EC_CSR_READ(sc) & EC_EVENT_SCI) == 0)
418 break;
419
420 /*
421 * Find out why the EC is signalling us
422 */
423 Status = EcQuery(sc, &Data);
424
425 /*
426 * If we failed to get anything from the EC, give up.
427 */
428 if (Status != AE_OK) {
429 printf("%s: GPE query failed: %d\n",
430 sc->sc_dev.dv_xname, Status);
431 break;
432 }
433
434 /*
435 * Evaluate _Qxx to respond to the controller.
436 */
437 sprintf(qxx, "_Q%02x", Data);
438 strupr(qxx);
439 Status = AcpiEvaluateObject(sc->sc_node->ad_handle, qxx,
440 NULL, NULL);
441
442 /*
443 * Ignore spurious query requests.
444 */
445 if (Status != AE_OK &&
446 (Data != 0 || Status != AE_NOT_FOUND)) {
447 printf("%s: evaluation of GPE query method %s "
448 "failed: %d\n", sc->sc_dev.dv_xname, qxx, Status);
449 }
450 }
451
452 /* I know I request Level trigger cleanup */
453 if (AcpiClearGpe(NULL, sc->sc_gpebit, ACPI_NOT_ISR) != AE_OK)
454 printf("%s: AcpiClearGpe failed\n", sc->sc_dev.dv_xname);
455
456 return_VOID;
457 }
458
459 static void
460 EcGpeHandler(void *Context)
461 {
462 struct acpi_ec_softc *sc = Context;
463 uint32_t csrvalue;
464
465 /*
466 * If EC is locked, the intr must process EcRead/Write wait only.
467 * Query request must be pending.
468 */
469 if (EcIsLocked(sc)) {
470 csrvalue = EC_CSR_READ(sc);
471 if (csrvalue & EC_EVENT_SCI)
472 sc->sc_flags |= EC_F_PENDQUERY;
473
474 if ((csrvalue & EC_FLAG_OUTPUT_BUFFER) != 0 ||
475 (csrvalue & EC_FLAG_INPUT_BUFFER) == 0) {
476 sc->sc_csrvalue = csrvalue;
477 wakeup(&sc->sc_csrvalue);
478 }
479 } else {
480 /* Enqueue GpeQuery handler. */
481 if (AcpiOsQueueForExecution(OSD_PRIORITY_HIGH,
482 EcGpeQueryHandler, Context) != AE_OK) {
483 printf("%s: failed to enqueue query handler\n",
484 sc->sc_dev.dv_xname);
485 }
486 }
487 }
488
489 static ACPI_STATUS
490 EcSpaceSetup(ACPI_HANDLE Region, UINT32 Function, void *Context,
491 void **RegionContext)
492 {
493
494 ACPI_FUNCTION_TRACE(__FUNCTION__);
495
496 /*
497 * Just pass the context through, there's nothing to do here.
498 */
499 *RegionContext = Context;
500
501 return_ACPI_STATUS(AE_OK);
502 }
503
504 static ACPI_STATUS
505 EcSpaceHandler(UINT32 Function, ACPI_PHYSICAL_ADDRESS Address, UINT32 width,
506 ACPI_INTEGER *Value, void *Context, void *RegionContext)
507 {
508 struct acpi_ec_softc *sc = Context;
509 ACPI_STATUS Status = AE_OK;
510 EC_REQUEST EcRequest;
511 int i;
512
513 ACPI_FUNCTION_TRACE_U32(__FUNCTION__, (UINT32)Address);
514
515 if ((Address > 0xFF) || (width % 8 != 0) || (Value == NULL) ||
516 (Context == NULL))
517 return_ACPI_STATUS(AE_BAD_PARAMETER);
518
519 switch (Function) {
520 case ACPI_READ:
521 EcRequest.Command = EC_COMMAND_READ;
522 EcRequest.Address = Address;
523 (*Value) = 0;
524 break;
525
526 case ACPI_WRITE:
527 EcRequest.Command = EC_COMMAND_WRITE;
528 EcRequest.Address = Address;
529 break;
530
531 default:
532 printf("%s: invalid Address Space function: %d\n",
533 sc->sc_dev.dv_xname, Function);
534 return_ACPI_STATUS(AE_BAD_PARAMETER);
535 }
536
537 /*
538 * Perform the transaction.
539 */
540 for (i = 0; i < width; i += 8) {
541 if (Function == ACPI_READ)
542 EcRequest.Data = 0;
543 else
544 EcRequest.Data = (UINT8)((*Value) >> i);
545
546 if ((Status = EcTransaction(sc, &EcRequest)) != AE_OK)
547 break;
548
549 (*Value) |= (UINT32)EcRequest.Data << i;
550 if (++EcRequest.Address == 0)
551 return_ACPI_STATUS(AE_BAD_PARAMETER);
552 }
553
554 return_ACPI_STATUS(Status);
555 }
556
557 static ACPI_STATUS
558 EcWaitEventIntr(struct acpi_ec_softc *sc, EC_EVENT Event)
559 {
560 EC_STATUS EcStatus;
561 int i;
562
563 ACPI_FUNCTION_TRACE_U32(__FUNCTION__, (UINT32)Event);
564
565 /* XXX Need better test for "yes, you have interrupts". */
566 if (cold)
567 return_ACPI_STATUS(EcWaitEvent(sc, Event));
568
569 if (EcIsLocked(sc) == 0)
570 printf("%s: EcWaitEventIntr called without EC lock!\n",
571 sc->sc_dev.dv_xname);
572
573 EcStatus = EC_CSR_READ(sc);
574
575 /* Too long? */
576 for (i = 0; i < 10; i++) {
577 /* Check EC status against the desired event. */
578 if ((Event == EC_EVENT_OUTPUT_BUFFER_FULL) &&
579 (EcStatus & EC_FLAG_OUTPUT_BUFFER) != 0)
580 return_ACPI_STATUS(AE_OK);
581
582 if ((Event == EC_EVENT_INPUT_BUFFER_EMPTY) &&
583 (EcStatus & EC_FLAG_INPUT_BUFFER) == 0)
584 return_ACPI_STATUS(AE_OK);
585
586 sc->sc_csrvalue = 0;
587 /* XXXJRT Sleeping with a lock held? */
588 if (tsleep(&sc->sc_csrvalue, 0, "EcWait", 1) != EWOULDBLOCK)
589 EcStatus = sc->sc_csrvalue;
590 else
591 EcStatus = EC_CSR_READ(sc);
592 }
593 return_ACPI_STATUS(AE_ERROR);
594 }
595
596 static ACPI_STATUS
597 EcWaitEvent(struct acpi_ec_softc *sc, EC_EVENT Event)
598 {
599 EC_STATUS EcStatus;
600 UINT32 i = 0;
601
602 if (EcIsLocked(sc) == 0)
603 printf("%s: EcWaitEvent called without EC lock!\n",
604 sc->sc_dev.dv_xname);
605
606 /*
607 * Stall 1us:
608 * ----------
609 * Stall for 1 microsecond before reading the status register
610 * for the first time. This allows the EC to set the IBF/OBF
611 * bit to its proper state.
612 *
613 * XXX it is not clear why we read the CSR twice.
614 */
615 AcpiOsStall(1);
616 EcStatus = EC_CSR_READ(sc);
617
618 /*
619 * Wait For Event:
620 * ---------------
621 * Poll the EC status register to detect completion of the last
622 * command. Wait up to 10ms (in 100us chunks) for this to occur.
623 */
624 for (i = 0; i < 100; i++) {
625 EcStatus = EC_CSR_READ(sc);
626
627 if ((Event == EC_EVENT_OUTPUT_BUFFER_FULL) &&
628 (EcStatus & EC_FLAG_OUTPUT_BUFFER) != 0)
629 return (AE_OK);
630
631 if ((Event == EC_EVENT_INPUT_BUFFER_EMPTY) &&
632 (EcStatus & EC_FLAG_INPUT_BUFFER) == 0)
633 return (AE_OK);
634
635 AcpiOsStall(10);
636 }
637
638 return (AE_ERROR);
639 }
640
641 static ACPI_STATUS
642 EcQuery(struct acpi_ec_softc *sc, UINT8 *Data)
643 {
644 ACPI_STATUS Status;
645
646 EcLock(sc);
647
648 EC_CSR_WRITE(sc, EC_COMMAND_QUERY);
649 Status = EcWaitEvent(sc, EC_EVENT_OUTPUT_BUFFER_FULL);
650 if (Status == AE_OK)
651 *Data = EC_DATA_READ(sc);
652
653 EcUnlock(sc);
654
655 if (Status != AE_OK)
656 printf("%s: timed out waiting for EC to respond to "
657 "EC_COMMAND_QUERY\n", sc->sc_dev.dv_xname);
658
659 return (Status);
660 }
661
662 static ACPI_STATUS
663 EcTransaction(struct acpi_ec_softc *sc, EC_REQUEST *EcRequest)
664 {
665 ACPI_STATUS Status;
666
667 EcLock(sc);
668
669 /*
670 * Perform the transaction.
671 */
672 switch (EcRequest->Command) {
673 case EC_COMMAND_READ:
674 Status = EcRead(sc, EcRequest->Address, &(EcRequest->Data));
675 break;
676
677 case EC_COMMAND_WRITE:
678 Status = EcWrite(sc, EcRequest->Address, &(EcRequest->Data));
679 break;
680
681 default:
682 Status = AE_SUPPORT;
683 break;
684 }
685
686 /*
687 * Clear & Re-Enable the EC GPE:
688 * -----------------------------
689 * 'Consume' any EC GPE events that we generated while performing
690 * the transaction (e.g. IBF/OBF). Clearing the GPE here shouldn't
691 * have an adverse affect on outstanding EC-SCI's, as the source
692 * (EC-SCI) will still be high and thus should trigger the GPE
693 * immediately after we re-enabling it.
694 */
695 if (sc->sc_flags & EC_F_PENDQUERY) {
696 if (AcpiOsQueueForExecution(OSD_PRIORITY_HIGH,
697 EcGpeQueryHandler, sc) != AE_OK)
698 printf("%s: unable to queue pending query\n",
699 sc->sc_dev.dv_xname);
700 sc->sc_flags &= ~EC_F_PENDQUERY;
701 }
702
703 EcUnlock(sc);
704
705 return(Status);
706 }
707
708 static ACPI_STATUS
709 EcRead(struct acpi_ec_softc *sc, UINT8 Address, UINT8 *Data)
710 {
711 ACPI_STATUS Status;
712
713 if (EcIsLocked(sc) == 0)
714 printf("%s: EcRead called without EC lock!\n",
715 sc->sc_dev.dv_xname);
716
717 /* EcBurstEnable(EmbeddedController); */
718
719 EC_CSR_WRITE(sc, EC_COMMAND_READ);
720 if ((Status = EcWaitEventIntr(sc, EC_EVENT_INPUT_BUFFER_EMPTY)) !=
721 AE_OK) {
722 printf("%s: EcRead: timeout waiting for EC to process "
723 "read command\n", sc->sc_dev.dv_xname);
724 return (Status);
725 }
726
727 EC_DATA_WRITE(sc, Address);
728 if ((Status = EcWaitEventIntr(sc, EC_EVENT_OUTPUT_BUFFER_FULL)) !=
729 AE_OK) {
730 printf("%s: EcRead: timeout waiting for EC to send data\n",
731 sc->sc_dev.dv_xname);
732 return (Status);
733 }
734
735 (*Data) = EC_DATA_READ(sc);
736
737 /* EcBurstDisable(EmbeddedController); */
738
739 return (AE_OK);
740 }
741
742 static ACPI_STATUS
743 EcWrite(struct acpi_ec_softc *sc, UINT8 Address, UINT8 *Data)
744 {
745 ACPI_STATUS Status;
746
747 if (EcIsLocked(sc) == 0)
748 printf("%s: EcWrite called without EC lock!\n",
749 sc->sc_dev.dv_xname);
750
751 /* EcBurstEnable(EmbeddedController); */
752
753 EC_CSR_WRITE(sc, EC_COMMAND_WRITE);
754 if ((Status = EcWaitEventIntr(sc, EC_EVENT_INPUT_BUFFER_EMPTY)) !=
755 AE_OK) {
756 printf("%s: EcWrite: timeout waiting for EC to process "
757 "write command\n", sc->sc_dev.dv_xname);
758 return (Status);
759 }
760
761 EC_DATA_WRITE(sc, Address);
762 if ((Status = EcWaitEventIntr(sc, EC_EVENT_INPUT_BUFFER_EMPTY)) !=
763 AE_OK) {
764 printf("%s: EcWrite: timeout waiting for EC to process "
765 "address\n", sc->sc_dev.dv_xname);
766 return (Status);
767 }
768
769 EC_DATA_WRITE(sc, *Data);
770 if ((Status = EcWaitEventIntr(sc, EC_EVENT_INPUT_BUFFER_EMPTY)) !=
771 AE_OK) {
772 printf("%s: EcWrite: timeout waiting for EC to process "
773 "data\n", sc->sc_dev.dv_xname);
774 return (Status);
775 }
776
777 /* EcBurstDisable(EmbeddedController); */
778
779 return (AE_OK);
780 }
781