1 /* $NetBSD: acpi_ec.c,v 1.3 2001/11/13 13:01:57 lukem 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.3 2001/11/13 13:01:57 lukem 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/acpivar.h> 187 #include <dev/acpi/acpi_ecreg.h> 188 189 #define _COMPONENT ACPI_EC 190 MODULE_NAME("EC") 191 192 struct acpi_ec_softc { 193 struct device sc_dev; /* base device glue */ 194 struct acpi_devnode *sc_node; /* our ACPI devnode */ 195 196 struct acpi_resources sc_res; /* our bus resources */ 197 198 UINT32 sc_gpebit; /* our GPE interrupt bit */ 199 200 bus_space_tag_t sc_data_st; /* space tag for data register */ 201 bus_space_handle_t sc_data_sh; /* space handle for data register */ 202 203 bus_space_tag_t sc_csr_st; /* space tag for control register */ 204 bus_space_handle_t sc_csr_sh; /* space handle for control register */ 205 206 int sc_flags; /* see below */ 207 208 uint32_t sc_csrvalue; /* saved control register */ 209 }; 210 211 #define EC_F_LOCKED 0x01 /* EC is locked */ 212 #define EC_F_PENDQUERY 0x02 /* query is pending */ 213 214 #define EC_LOCK_TIMEOUT 1000 /* 1ms */ 215 216 #define EC_DATA_READ(sc) \ 217 bus_space_read_1((sc)->sc_data_st, (sc)->sc_data_sh, 0) 218 #define EC_DATA_WRITE(sc, v) \ 219 bus_space_write_1((sc)->sc_data_st, (sc)->sc_data_sh, 0, (v)) 220 221 #define EC_CSR_READ(sc) \ 222 bus_space_read_1((sc)->sc_csr_st, (sc)->sc_csr_sh, 0) 223 #define EC_CSR_WRITE(sc, v) \ 224 bus_space_write_1((sc)->sc_csr_st, (sc)->sc_csr_sh, 0, (v)) 225 226 static __inline ACPI_STATUS 227 EcLock(struct acpi_ec_softc *sc) 228 { 229 ACPI_STATUS status; 230 231 status = AcpiAcquireGlobalLock(); 232 if (status == AE_OK) 233 (sc)->sc_flags |= EC_F_LOCKED; 234 return (status); 235 } 236 237 static __inline void 238 EcUnlock(struct acpi_ec_softc *sc) 239 { 240 241 (sc)->sc_flags &= ~EC_F_LOCKED; 242 AcpiReleaseGlobalLock(); 243 } 244 245 static __inline int 246 EcIsLocked(struct acpi_ec_softc *sc) 247 { 248 249 return (((sc)->sc_flags & EC_F_LOCKED) != 0); 250 } 251 252 typedef struct { 253 EC_COMMAND Command; 254 UINT8 Address; 255 UINT8 Data; 256 } EC_REQUEST; 257 258 static void EcGpeHandler(void *Context); 259 static ACPI_STATUS EcSpaceSetup(ACPI_HANDLE Region, UINT32 Function, 260 void *Context, void **return_Context); 261 static ACPI_STATUS EcSpaceHandler(UINT32 Function, 262 ACPI_PHYSICAL_ADDRESS Address, UINT32 width, 263 UINT32 *Value, void *Context, void *RegionContext); 264 265 static ACPI_STATUS EcWaitEvent(struct acpi_ec_softc *sc, EC_EVENT Event); 266 static ACPI_STATUS EcQuery(struct acpi_ec_softc *sc, UINT8 *Data); 267 static ACPI_STATUS EcTransaction(struct acpi_ec_softc *sc, 268 EC_REQUEST *EcRequest); 269 static ACPI_STATUS EcRead(struct acpi_ec_softc *sc, UINT8 Address, 270 UINT8 *Data); 271 static ACPI_STATUS EcWrite(struct acpi_ec_softc *sc, UINT8 Address, 272 UINT8 *Data); 273 274 int acpiec_match(struct device *, struct cfdata *, void *); 275 void acpiec_attach(struct device *, struct device *, void *); 276 277 struct cfattach acpiec_ca = { 278 sizeof(struct acpi_ec_softc), acpiec_match, acpiec_attach, 279 }; 280 281 /* 282 * acpiec_match: 283 * 284 * Autoconfiguration `match' routine. 285 */ 286 int 287 acpiec_match(struct device *parent, struct cfdata *match, void *aux) 288 { 289 struct acpi_attach_args *aa = aux; 290 291 if (aa->aa_node->ad_type != ACPI_TYPE_DEVICE) 292 return (0); 293 294 if (strcmp(aa->aa_node->ad_devinfo.HardwareId, "PNP0C09") == 0) 295 return (1); 296 297 return (0); 298 } 299 300 /* 301 * acpiec_attach: 302 * 303 * Autoconfiguration `attach' routine. 304 */ 305 void 306 acpiec_attach(struct device *parent, struct device *self, void *aux) 307 { 308 struct acpi_ec_softc *sc = (void *) self; 309 struct acpi_attach_args *aa = aux; 310 struct acpi_io *io0, *io1; 311 ACPI_STATUS rv; 312 313 FUNCTION_TRACE(__FUNCTION__); 314 315 printf(": ACPI Embedded Controller\n"); 316 317 sc->sc_node = aa->aa_node; 318 319 /* Parse our resources. */ 320 ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES, "parsing EC resources\n")); 321 rv = acpi_resource_parse(&sc->sc_dev, sc->sc_node, &sc->sc_res, 322 &acpi_resource_parse_ops_default); 323 if (rv != AE_OK) { 324 printf("%s: unable to parse resources: %d\n", 325 sc->sc_dev.dv_xname, rv); 326 return; 327 } 328 329 sc->sc_data_st = aa->aa_iot; 330 io0 = acpi_res_io(&sc->sc_res, 0); 331 if (io0 == NULL) { 332 printf("%s: unable to find data register resource\n", 333 sc->sc_dev.dv_xname); 334 return; 335 } 336 if (bus_space_map(sc->sc_data_st, io0->ar_base, io0->ar_length, 337 0, &sc->sc_data_sh) != 0) { 338 printf("%s: unable to map data register\n", 339 sc->sc_dev.dv_xname); 340 return; 341 } 342 343 sc->sc_csr_st = aa->aa_iot; 344 io1 = acpi_res_io(&sc->sc_res, 1); 345 if (io1 == NULL) { 346 printf("%s: unable to find csr register resource\n", 347 sc->sc_dev.dv_xname); 348 return; 349 } 350 if (bus_space_map(sc->sc_csr_st, io1->ar_base, io1->ar_length, 351 0, &sc->sc_csr_sh) != 0) { 352 printf("%s: unable to map csr register\n", 353 sc->sc_dev.dv_xname); 354 return; 355 } 356 357 /* 358 * Install GPE handler. 359 * 360 * We evaluate the _GPE method to find the GPE bit used by the 361 * Embedded Controller to signal status (SCI). 362 */ 363 if ((rv = acpi_eval_integer(sc->sc_node->ad_handle, "_GPE", 364 &sc->sc_gpebit)) != AE_OK) { 365 printf("%s: unable to evaluate _GPE: %d\n", 366 sc->sc_dev.dv_xname, rv); 367 return; 368 } 369 370 /* 371 * Install a handler for this EC's GPE bit. Note that EC SCIs are 372 * treated as both edge- and level-triggered interrupts; in other words 373 * we clear the status bit immediately after getting an EC-SCI, then 374 * again after we're done processing the event. This guarantees that 375 * events we cause while performing a transaction (e.g. IBE/OBF) get 376 * cleared before re-enabling the GPE. 377 */ 378 if ((rv = AcpiInstallGpeHandler(sc->sc_gpebit, 379 ACPI_EVENT_LEVEL_TRIGGERED | ACPI_EVENT_EDGE_TRIGGERED, 380 EcGpeHandler, sc)) != AE_OK) { 381 printf("%s: unable to install GPE handler: %d\n", 382 sc->sc_dev.dv_xname, rv); 383 return; 384 } 385 386 /* Install address space handler. */ 387 if ((rv = AcpiInstallAddressSpaceHandler(sc->sc_node->ad_handle, 388 ACPI_ADR_SPACE_EC, EcSpaceHandler, EcSpaceSetup, sc)) != AE_OK) { 389 printf("%s: unable to install address space handler: %d\n", 390 sc->sc_dev.dv_xname, rv); 391 return; 392 } 393 394 return_VOID; 395 } 396 397 static void 398 EcGpeQueryHandler(void *Context) 399 { 400 struct acpi_ec_softc *sc = Context; 401 UINT8 Data; 402 ACPI_STATUS Status; 403 char qxx[5]; 404 405 FUNCTION_TRACE(__FUNCTION__); 406 407 for (;;) { 408 /* 409 * Check EC_SCI. 410 * 411 * Bail out if the EC_SCI bit of the status register is not 412 * set. Note that this function should only be called when 413 * this bit is set (polling is used to detect IBE/OBF events). 414 * 415 * It is safe to do this without locking the controller, as 416 * it's OK to call EcQuery when there's no data ready; in the 417 * worst case we should just find nothing waiting for us and 418 * bail. 419 */ 420 if ((EC_CSR_READ(sc) & EC_EVENT_SCI) == 0) 421 break; 422 423 /* 424 * Find out why the EC is signalling us 425 */ 426 Status = EcQuery(sc, &Data); 427 428 /* 429 * If we failed to get anything from the EC, give up. 430 */ 431 if (Status != AE_OK) { 432 printf("%s: GPE query failed: %d\n", 433 sc->sc_dev.dv_xname, Status); 434 break; 435 } 436 437 /* 438 * Evaluate _Qxx to respond to the controller. 439 */ 440 sprintf(qxx, "_Q%02x", Data); 441 strupr(qxx); 442 Status = AcpiEvaluateObject(sc->sc_node->ad_handle, qxx, 443 NULL, NULL); 444 445 /* 446 * Ignore spurious query requests. 447 */ 448 if (Status != AE_OK && 449 (Data != 0 || Status != AE_NOT_FOUND)) { 450 printf("%s: evaluation of GPE query method %s " 451 "failed: %d\n", sc->sc_dev.dv_xname, qxx, Status); 452 } 453 } 454 455 /* I know I request Level trigger cleanup */ 456 if (AcpiClearEvent(sc->sc_gpebit, ACPI_EVENT_GPE) != AE_OK) 457 printf("%s: AcpiClearEvent failed\n", sc->sc_dev.dv_xname); 458 if (AcpiEnableEvent(sc->sc_gpebit, ACPI_EVENT_GPE) != AE_OK) 459 printf("%s: AcpiEnableEvent failed\n", sc->sc_dev.dv_xname); 460 461 return_VOID; 462 } 463 464 static void 465 EcGpeHandler(void *Context) 466 { 467 struct acpi_ec_softc *sc = Context; 468 uint32_t csrvalue; 469 470 /* 471 * If EC is locked, the intr must process EcRead/Write wait only. 472 * Query request must be pending. 473 */ 474 if (EcIsLocked(sc)) { 475 csrvalue = EC_CSR_READ(sc); 476 if (csrvalue & EC_EVENT_SCI) 477 sc->sc_flags |= EC_F_PENDQUERY; 478 479 if ((csrvalue & EC_FLAG_OUTPUT_BUFFER) != 0 || 480 (csrvalue & EC_FLAG_INPUT_BUFFER) == 0) { 481 sc->sc_csrvalue = csrvalue; 482 wakeup(&sc->sc_csrvalue); 483 } 484 } else { 485 /* Enqueue GpeQuery handler. */ 486 if (AcpiOsQueueForExecution(OSD_PRIORITY_HIGH, 487 EcGpeQueryHandler, Context) != AE_OK) { 488 printf("%s: failed to enqueue query handler\n", 489 sc->sc_dev.dv_xname); 490 } 491 } 492 } 493 494 static ACPI_STATUS 495 EcSpaceSetup(ACPI_HANDLE Region, UINT32 Function, void *Context, 496 void **RegionContext) 497 { 498 499 FUNCTION_TRACE(__FUNCTION__); 500 501 /* 502 * Just pass the context through, there's nothing to do here. 503 */ 504 *RegionContext = Context; 505 506 return_ACPI_STATUS(AE_OK); 507 } 508 509 static ACPI_STATUS 510 EcSpaceHandler(UINT32 Function, ACPI_PHYSICAL_ADDRESS Address, UINT32 width, 511 UINT32 *Value, void *Context, void *RegionContext) 512 { 513 struct acpi_ec_softc *sc = Context; 514 ACPI_STATUS Status = AE_OK; 515 EC_REQUEST EcRequest; 516 int i; 517 518 FUNCTION_TRACE_U32(__FUNCTION__, (UINT32)Address); 519 520 if ((Address > 0xFF) || (width % 8 != 0) || (Value == NULL) || 521 (Context == NULL)) 522 return_ACPI_STATUS(AE_BAD_PARAMETER); 523 524 switch (Function) { 525 case ACPI_READ_ADR_SPACE: 526 EcRequest.Command = EC_COMMAND_READ; 527 EcRequest.Address = Address; 528 (*Value) = 0; 529 break; 530 531 case ACPI_WRITE_ADR_SPACE: 532 EcRequest.Command = EC_COMMAND_WRITE; 533 EcRequest.Address = Address; 534 break; 535 536 default: 537 printf("%s: invalid Address Space function: %d\n", 538 sc->sc_dev.dv_xname, Function); 539 return_ACPI_STATUS(AE_BAD_PARAMETER); 540 } 541 542 /* 543 * Perform the transaction. 544 */ 545 (*Value) = 0; 546 for (i = 0; i < width; i += 8) { 547 if (Function == ACPI_READ_ADR_SPACE) 548 EcRequest.Data = 0; 549 else 550 EcRequest.Data = (UINT8)((*Value) >> i); 551 552 if ((Status = EcTransaction(sc, &EcRequest)) != AE_OK) 553 break; 554 555 (*Value) |= (UINT32)EcRequest.Data << i; 556 if (++EcRequest.Address == 0) 557 return_ACPI_STATUS(AE_BAD_PARAMETER); 558 } 559 560 return_ACPI_STATUS(Status); 561 } 562 563 static ACPI_STATUS 564 EcWaitEventIntr(struct acpi_ec_softc *sc, EC_EVENT Event) 565 { 566 EC_STATUS EcStatus; 567 int i; 568 569 FUNCTION_TRACE_U32(__FUNCTION__, (UINT32)Event); 570 571 /* XXX Need better test for "yes, you have interrupts". */ 572 if (cold) 573 return_ACPI_STATUS(EcWaitEvent(sc, Event)); 574 575 if (EcIsLocked(sc) == 0) 576 printf("%s: EcWaitEventIntr called without EC lock!\n", 577 sc->sc_dev.dv_xname); 578 579 EcStatus = EC_CSR_READ(sc); 580 581 /* Too long? */ 582 for (i = 0; i < 10; i++) { 583 /* Check EC status against the desired event. */ 584 if ((Event == EC_EVENT_OUTPUT_BUFFER_FULL) && 585 (EcStatus & EC_FLAG_OUTPUT_BUFFER) != 0) 586 return_ACPI_STATUS(AE_OK); 587 588 if ((Event == EC_EVENT_INPUT_BUFFER_EMPTY) && 589 (EcStatus & EC_FLAG_INPUT_BUFFER) == 0) 590 return_ACPI_STATUS(AE_OK); 591 592 sc->sc_csrvalue = 0; 593 /* XXXJRT Sleeping with a lock held? */ 594 if (tsleep(&sc->sc_csrvalue, 0, "EcWait", 1) != EWOULDBLOCK) 595 EcStatus = sc->sc_csrvalue; 596 else 597 EcStatus = EC_CSR_READ(sc); 598 } 599 return_ACPI_STATUS(AE_ERROR); 600 } 601 602 static ACPI_STATUS 603 EcWaitEvent(struct acpi_ec_softc *sc, EC_EVENT Event) 604 { 605 EC_STATUS EcStatus; 606 UINT32 i = 0; 607 608 if (EcIsLocked(sc) == 0) 609 printf("%s: EcWaitEvent called without EC lock!\n", 610 sc->sc_dev.dv_xname); 611 612 /* 613 * Stall 1us: 614 * ---------- 615 * Stall for 1 microsecond before reading the status register 616 * for the first time. This allows the EC to set the IBF/OBF 617 * bit to its proper state. 618 * 619 * XXX it is not clear why we read the CSR twice. 620 */ 621 AcpiOsStall(1); 622 EcStatus = EC_CSR_READ(sc); 623 624 /* 625 * Wait For Event: 626 * --------------- 627 * Poll the EC status register to detect completion of the last 628 * command. Wait up to 10ms (in 100us chunks) for this to occur. 629 */ 630 for (i = 0; i < 100; i++) { 631 EcStatus = EC_CSR_READ(sc); 632 633 if ((Event == EC_EVENT_OUTPUT_BUFFER_FULL) && 634 (EcStatus & EC_FLAG_OUTPUT_BUFFER) != 0) 635 return (AE_OK); 636 637 if ((Event == EC_EVENT_INPUT_BUFFER_EMPTY) && 638 (EcStatus & EC_FLAG_INPUT_BUFFER) == 0) 639 return (AE_OK); 640 641 AcpiOsStall(10); 642 } 643 644 return (AE_ERROR); 645 } 646 647 static ACPI_STATUS 648 EcQuery(struct acpi_ec_softc *sc, UINT8 *Data) 649 { 650 ACPI_STATUS Status; 651 652 if ((Status = EcLock(sc)) != AE_OK) 653 return (Status); 654 655 EC_CSR_WRITE(sc, EC_COMMAND_QUERY); 656 Status = EcWaitEvent(sc, EC_EVENT_OUTPUT_BUFFER_FULL); 657 if (Status == AE_OK) 658 *Data = EC_DATA_READ(sc); 659 660 EcUnlock(sc); 661 662 if (Status != AE_OK) 663 printf("%s: timed out waiting for EC to respond to " 664 "EC_COMMAND_QUERY\n", sc->sc_dev.dv_xname); 665 666 return (Status); 667 } 668 669 static ACPI_STATUS 670 EcTransaction(struct acpi_ec_softc *sc, EC_REQUEST *EcRequest) 671 { 672 ACPI_STATUS Status; 673 674 if ((Status = EcLock(sc)) != AE_OK) 675 return (Status); 676 677 /* 678 * Perform the transaction. 679 */ 680 switch (EcRequest->Command) { 681 case EC_COMMAND_READ: 682 Status = EcRead(sc, EcRequest->Address, &(EcRequest->Data)); 683 break; 684 685 case EC_COMMAND_WRITE: 686 Status = EcWrite(sc, EcRequest->Address, &(EcRequest->Data)); 687 break; 688 689 default: 690 Status = AE_SUPPORT; 691 break; 692 } 693 694 /* 695 * Clear & Re-Enable the EC GPE: 696 * ----------------------------- 697 * 'Consume' any EC GPE events that we generated while performing 698 * the transaction (e.g. IBF/OBF). Clearing the GPE here shouldn't 699 * have an adverse affect on outstanding EC-SCI's, as the source 700 * (EC-SCI) will still be high and thus should trigger the GPE 701 * immediately after we re-enabling it. 702 */ 703 if (sc->sc_flags & EC_F_PENDQUERY) { 704 if (AcpiOsQueueForExecution(OSD_PRIORITY_HIGH, 705 EcGpeQueryHandler, sc) != AE_OK) 706 printf("%s: unable to queue pending query\n", 707 sc->sc_dev.dv_xname); 708 sc->sc_flags &= ~EC_F_PENDQUERY; 709 } 710 711 if (AcpiClearEvent(sc->sc_gpebit, ACPI_EVENT_GPE) != AE_OK) 712 printf("%s: EcRequest: unable to clear EC GPE\n", 713 sc->sc_dev.dv_xname); 714 if (AcpiEnableEvent(sc->sc_gpebit, ACPI_EVENT_GPE) != AE_OK) 715 printf("%s: EcRequest: unable to reenable EC GPE\n", 716 sc->sc_dev.dv_xname); 717 718 EcUnlock(sc); 719 720 return(Status); 721 } 722 723 static ACPI_STATUS 724 EcRead(struct acpi_ec_softc *sc, UINT8 Address, UINT8 *Data) 725 { 726 ACPI_STATUS Status; 727 728 if (EcIsLocked(sc) == 0) 729 printf("%s: EcRead called without EC lock!\n", 730 sc->sc_dev.dv_xname); 731 732 /* EcBurstEnable(EmbeddedController); */ 733 734 EC_CSR_WRITE(sc, EC_COMMAND_READ); 735 if ((Status = EcWaitEventIntr(sc, EC_EVENT_INPUT_BUFFER_EMPTY)) != 736 AE_OK) { 737 printf("%s: EcRead: timeout waiting for EC to process " 738 "read command\n", sc->sc_dev.dv_xname); 739 return (Status); 740 } 741 742 EC_DATA_WRITE(sc, Address); 743 if ((Status = EcWaitEventIntr(sc, EC_EVENT_OUTPUT_BUFFER_FULL)) != 744 AE_OK) { 745 printf("%s: EcRead: timeout waiting for EC to send data\n", 746 sc->sc_dev.dv_xname); 747 return (Status); 748 } 749 750 (*Data) = EC_DATA_READ(sc); 751 752 /* EcBurstDisable(EmbeddedController); */ 753 754 return (AE_OK); 755 } 756 757 static ACPI_STATUS 758 EcWrite(struct acpi_ec_softc *sc, UINT8 Address, UINT8 *Data) 759 { 760 ACPI_STATUS Status; 761 762 if (EcIsLocked(sc) == 0) 763 printf("%s: EcWrite called without EC lock!\n", 764 sc->sc_dev.dv_xname); 765 766 /* EcBurstEnable(EmbeddedController); */ 767 768 EC_CSR_WRITE(sc, EC_COMMAND_WRITE); 769 if ((Status = EcWaitEventIntr(sc, EC_EVENT_INPUT_BUFFER_EMPTY)) != 770 AE_OK) { 771 printf("%s: EcWrite: timeout waiting for EC to process " 772 "write command\n", sc->sc_dev.dv_xname); 773 return (Status); 774 } 775 776 EC_DATA_WRITE(sc, Address); 777 if ((Status = EcWaitEventIntr(sc, EC_EVENT_INPUT_BUFFER_EMPTY)) != 778 AE_OK) { 779 printf("%s: EcWrite: timeout waiting for EC to process " 780 "address\n", sc->sc_dev.dv_xname); 781 return (Status); 782 } 783 784 EC_DATA_WRITE(sc, *Data); 785 if ((Status = EcWaitEventIntr(sc, EC_EVENT_INPUT_BUFFER_EMPTY)) != 786 AE_OK) { 787 printf("%s: EcWrite: timeout waiting for EC to process " 788 "data\n", sc->sc_dev.dv_xname); 789 return (Status); 790 } 791 792 /* EcBurstDisable(EmbeddedController); */ 793 794 return (AE_OK); 795 } 796