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