1 /* $NetBSD: acpi_ec.c,v 1.39 2006/10/12 01:30:54 christos 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.39 2006/10/12 01:30:54 christos Exp $"); 176 177 #include <sys/param.h> 178 #include <sys/systm.h> 179 #include <sys/device.h> 180 #include <sys/malloc.h> 181 #include <sys/proc.h> 182 #include <sys/kernel.h> 183 184 #include <machine/bus.h> 185 186 #include <dev/acpi/acpica.h> 187 #include <dev/acpi/acpireg.h> 188 #include <dev/acpi/acpivar.h> 189 #include <dev/acpi/acpi_ecreg.h> 190 191 MALLOC_DECLARE(M_ACPI); 192 193 #define _COMPONENT ACPI_EC_COMPONENT 194 ACPI_MODULE_NAME("EC") 195 196 struct acpi_ec_softc { 197 struct device sc_dev; /* base device glue */ 198 ACPI_HANDLE sc_handle; /* ACPI handle */ 199 200 UINT32 sc_gpebit; /* our GPE interrupt bit */ 201 202 bus_space_tag_t sc_data_st; /* space tag for data register */ 203 bus_space_handle_t sc_data_sh; /* space handle for data register */ 204 205 bus_space_tag_t sc_csr_st; /* space tag for control register */ 206 bus_space_handle_t sc_csr_sh; /* space handle for control register */ 207 208 int sc_flags; /* see below */ 209 210 uint32_t sc_csrvalue; /* saved control register */ 211 uint32_t sc_uid; /* _UID in namespace (ECDT only) */ 212 213 struct lock sc_lock; /* serialize operations to this EC */ 214 struct simplelock sc_slock; /* protect against interrupts */ 215 UINT32 sc_glkhandle; /* global lock handle */ 216 UINT32 sc_glk; /* need global lock? */ 217 }; 218 219 static const char * const ec_hid[] = { 220 "PNP0C09", 221 NULL 222 }; 223 224 #define EC_F_TRANSACTION 0x01 /* doing transaction */ 225 #define EC_F_PENDQUERY 0x02 /* query is pending */ 226 227 /* 228 * how long to wait to acquire global lock. 229 * the value is taken from FreeBSD driver. 230 */ 231 #define EC_LOCK_TIMEOUT 1000 232 233 #define EC_DATA_READ(sc) \ 234 bus_space_read_1((sc)->sc_data_st, (sc)->sc_data_sh, 0) 235 #define EC_DATA_WRITE(sc, v) \ 236 bus_space_write_1((sc)->sc_data_st, (sc)->sc_data_sh, 0, (v)) 237 238 #define EC_CSR_READ(sc) \ 239 bus_space_read_1((sc)->sc_csr_st, (sc)->sc_csr_sh, 0) 240 #define EC_CSR_WRITE(sc, v) \ 241 bus_space_write_1((sc)->sc_csr_st, (sc)->sc_csr_sh, 0, (v)) 242 243 typedef struct { 244 EC_COMMAND Command; 245 UINT8 Address; 246 UINT8 Data; 247 } EC_REQUEST; 248 249 static UINT32 EcGpeHandler(void *); 250 static ACPI_STATUS EcSpaceSetup(ACPI_HANDLE, UINT32, void *, void **); 251 static ACPI_STATUS EcSpaceHandler(UINT32, ACPI_PHYSICAL_ADDRESS, UINT32, 252 ACPI_INTEGER *, void *, void *); 253 254 static ACPI_STATUS EcWaitEvent(struct acpi_ec_softc *, EC_EVENT); 255 static ACPI_STATUS EcQuery(struct acpi_ec_softc *, UINT8 *); 256 static ACPI_STATUS EcTransaction(struct acpi_ec_softc *, EC_REQUEST *); 257 static ACPI_STATUS EcRead(struct acpi_ec_softc *, UINT8, UINT8 *); 258 static ACPI_STATUS EcWrite(struct acpi_ec_softc *, UINT8, UINT8 *); 259 static void EcGpeQueryHandler(void *); 260 static inline int EcIsLocked(struct acpi_ec_softc *); 261 static inline void EcLock(struct acpi_ec_softc *); 262 static inline void EcUnlock(struct acpi_ec_softc *); 263 264 265 static int acpiec_match(struct device *, struct cfdata *, void *); 266 static void acpiec_attach(struct device *, struct device *, void *); 267 268 CFATTACH_DECL(acpiec, sizeof(struct acpi_ec_softc), 269 acpiec_match, acpiec_attach, NULL, NULL); 270 271 static struct acpi_ec_softc *ecdt_sc; 272 273 static inline int 274 EcIsLocked(struct acpi_ec_softc *sc) 275 { 276 277 return (lockstatus(&sc->sc_lock) == LK_EXCLUSIVE); 278 } 279 280 static inline void 281 EcLock(struct acpi_ec_softc *sc) 282 { 283 ACPI_STATUS rv; 284 int s; 285 286 lockmgr(&sc->sc_lock, LK_EXCLUSIVE, NULL); 287 if (sc->sc_glk) { 288 rv = AcpiAcquireGlobalLock(EC_LOCK_TIMEOUT, 289 &sc->sc_glkhandle); 290 if (ACPI_FAILURE(rv)) { 291 printf("%s: failed to acquire global lock\n", 292 sc->sc_dev.dv_xname); 293 lockmgr(&sc->sc_lock, LK_RELEASE, NULL); 294 return; 295 } 296 } 297 298 s = splvm(); /* XXX */ 299 simple_lock(&sc->sc_slock); 300 sc->sc_flags |= EC_F_TRANSACTION; 301 simple_unlock(&sc->sc_slock); 302 splx(s); 303 } 304 305 static inline void 306 EcUnlock(struct acpi_ec_softc *sc) 307 { 308 ACPI_STATUS rv; 309 int s; 310 311 /* 312 * Clear & Re-Enable the EC GPE: 313 * ----------------------------- 314 * 'Consume' any EC GPE events that we generated while performing 315 * the transaction (e.g. IBF/OBF). Clearing the GPE here shouldn't 316 * have an adverse affect on outstanding EC-SCI's, as the source 317 * (EC-SCI) will still be high and thus should trigger the GPE 318 * immediately after we re-enabling it. 319 */ 320 s = splvm(); /* XXX */ 321 simple_lock(&sc->sc_slock); 322 if (sc->sc_flags & EC_F_PENDQUERY) { 323 ACPI_STATUS rv2; 324 325 rv2 = AcpiOsQueueForExecution(OSD_PRIORITY_HIGH, 326 EcGpeQueryHandler, sc); 327 if (ACPI_FAILURE(rv2)) 328 printf("%s: unable to queue pending query: %s\n", 329 sc->sc_dev.dv_xname, AcpiFormatException(rv2)); 330 sc->sc_flags &= ~EC_F_PENDQUERY; 331 } 332 sc->sc_flags &= ~EC_F_TRANSACTION; 333 simple_unlock(&sc->sc_slock); 334 splx(s); 335 336 if (sc->sc_glk) { 337 rv = AcpiReleaseGlobalLock(sc->sc_glkhandle); 338 if (ACPI_FAILURE(rv)) 339 printf("%s: failed to release global lock\n", 340 sc->sc_dev.dv_xname); 341 } 342 lockmgr(&sc->sc_lock, LK_RELEASE, NULL); 343 } 344 345 /* 346 * acpiec_match: 347 * 348 * Autoconfiguration `match' routine. 349 */ 350 static int 351 acpiec_match(struct device *parent __unused, struct cfdata *match __unused, 352 void *aux) 353 { 354 struct acpi_attach_args *aa = aux; 355 356 if (aa->aa_node->ad_type != ACPI_TYPE_DEVICE) 357 return 0; 358 359 return acpi_match_hid(aa->aa_node->ad_devinfo, ec_hid); 360 } 361 362 void 363 acpiec_early_attach(struct device *parent) 364 { 365 struct acpi_softc *sc = (struct acpi_softc *)parent; 366 EC_BOOT_RESOURCES *ep; 367 ACPI_HANDLE handle; 368 ACPI_STATUS rv; 369 ACPI_INTEGER tmp; 370 371 rv = AcpiGetFirmwareTable("ECDT", 1, ACPI_LOGICAL_ADDRESSING, 372 (void *)&ep); 373 if (ACPI_FAILURE(rv)) 374 return; 375 376 if (ep->EcControl.RegisterBitWidth != 8 || 377 ep->EcData.RegisterBitWidth != 8) { 378 printf("%s: ECDT data is invalid, RegisterBitWidth=%d/%d\n", 379 parent->dv_xname, 380 ep->EcControl.RegisterBitWidth, 381 ep->EcData.RegisterBitWidth); 382 return; 383 } 384 385 rv = AcpiGetHandle(ACPI_ROOT_OBJECT, ep->EcId, &handle); 386 if (ACPI_FAILURE(rv)) { 387 printf("%s: failed to look up EC object %s: %s\n", 388 parent->dv_xname, 389 ep->EcId, AcpiFormatException(rv)); 390 return; 391 } 392 393 ecdt_sc = malloc(sizeof(*ecdt_sc), M_ACPI, M_ZERO); 394 395 strcpy(ecdt_sc->sc_dev.dv_xname, "acpiecdt0"); /* XXX */ 396 ecdt_sc->sc_handle = handle; 397 398 ecdt_sc->sc_gpebit = ep->GpeBit; 399 ecdt_sc->sc_uid = ep->Uid; 400 401 ecdt_sc->sc_data_st = sc->sc_iot; 402 if (bus_space_map(ecdt_sc->sc_data_st, 403 (bus_addr_t)(ep->EcData.Address), 1, 0, 404 &ecdt_sc->sc_data_sh) != 0) { 405 printf("%s: bus_space_map failed for EC data.\n", 406 parent->dv_xname); 407 goto out1; 408 } 409 410 ecdt_sc->sc_csr_st = sc->sc_iot; 411 if (bus_space_map(ecdt_sc->sc_csr_st, 412 (bus_addr_t)(ep->EcControl.Address), 1, 0, 413 &ecdt_sc->sc_csr_sh) != 0) { 414 printf("%s: bus_space_map failed for EC control.\n", 415 parent->dv_xname); 416 goto out2; 417 } 418 419 rv = acpi_eval_integer(handle, "_GLK", &tmp); 420 if (ACPI_SUCCESS(rv) && tmp == 1) 421 ecdt_sc->sc_glk = 1; 422 423 rv = AcpiInstallGpeHandler(NULL, ecdt_sc->sc_gpebit, 424 ACPI_GPE_EDGE_TRIGGERED, EcGpeHandler, ecdt_sc); 425 if (ACPI_FAILURE(rv)) { 426 printf("%s: unable to install GPE handler: %s\n", 427 parent->dv_xname, AcpiFormatException(rv)); 428 goto out3; 429 } 430 431 rv = AcpiSetGpeType(NULL, ecdt_sc->sc_gpebit, ACPI_GPE_TYPE_RUNTIME); 432 if (ACPI_FAILURE(rv)) { 433 printf("%s: unable to set GPE type: %s\n", 434 parent->dv_xname, AcpiFormatException(rv)); 435 goto out4; 436 } 437 438 rv = AcpiEnableGpe(NULL, ecdt_sc->sc_gpebit, ACPI_NOT_ISR); 439 if (ACPI_FAILURE(rv)) { 440 printf("%s: unable to enable GPE: %s\n", 441 parent->dv_xname, AcpiFormatException(rv)); 442 goto out4; 443 } 444 445 rv = AcpiInstallAddressSpaceHandler(ACPI_ROOT_OBJECT, 446 ACPI_ADR_SPACE_EC, EcSpaceHandler, EcSpaceSetup, ecdt_sc); 447 if (ACPI_FAILURE(rv)) { 448 printf("%s: unable to install address space handler: %s\n", 449 parent->dv_xname, 450 AcpiFormatException(rv)); 451 goto out4; 452 } 453 454 printf("%s: found ECDT, GPE %d\n", parent->dv_xname, 455 ecdt_sc->sc_gpebit); 456 457 lockinit(&ecdt_sc->sc_lock, PWAIT, "eclock", 0, 0); 458 simple_lock_init(&ecdt_sc->sc_slock); 459 460 AcpiOsUnmapMemory(ep, ep->Length); 461 return; 462 463 out4: 464 AcpiRemoveGpeHandler(NULL, ecdt_sc->sc_gpebit, EcGpeHandler); 465 out3: 466 bus_space_unmap(ecdt_sc->sc_csr_st, ecdt_sc->sc_csr_sh, 1); 467 out2: 468 bus_space_unmap(ecdt_sc->sc_data_st, ecdt_sc->sc_data_sh, 1); 469 out1: 470 free(ecdt_sc, M_ACPI); 471 ecdt_sc = NULL; 472 473 AcpiOsUnmapMemory(ep, ep->Length); 474 475 return; 476 } 477 478 /* 479 * acpiec_attach: 480 * 481 * Autoconfiguration `attach' routine. 482 */ 483 static void 484 acpiec_attach(struct device *parent __unused, struct device *self, void *aux) 485 { 486 struct acpi_ec_softc *sc = (void *) self; 487 struct acpi_attach_args *aa = aux; 488 struct acpi_io *io0, *io1; 489 struct acpi_resources res; 490 ACPI_STATUS rv; 491 ACPI_INTEGER v; 492 493 ACPI_FUNCTION_TRACE(__FUNCTION__); 494 495 aprint_naive(": ACPI Embedded Controller\n"); 496 aprint_normal(": ACPI Embedded Controller\n"); 497 498 lockinit(&sc->sc_lock, PWAIT, "eclock", 0, 0); 499 simple_lock_init(&sc->sc_slock); 500 501 sc->sc_handle = aa->aa_node->ad_handle; 502 503 /* Parse our resources. */ 504 ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES, "parsing EC resources\n")); 505 rv = acpi_resource_parse(&sc->sc_dev, sc->sc_handle, "_CRS", 506 &res, &acpi_resource_parse_ops_default); 507 if (ACPI_FAILURE(rv)) 508 return; 509 510 #define adi aa->aa_node->ad_devinfo 511 512 /* check if we already attached EC via ECDT */ 513 if (ecdt_sc && 514 ((adi->Valid & ACPI_VALID_UID) == ACPI_VALID_UID) && 515 ecdt_sc->sc_uid == strtoul(adi->UniqueId.Value, NULL, 10)) { 516 /* detach all ECDT handles */ 517 rv = AcpiRemoveAddressSpaceHandler(ACPI_ROOT_OBJECT, 518 ACPI_ADR_SPACE_EC, EcSpaceHandler); 519 if (ACPI_FAILURE(rv)) 520 aprint_error("ERROR: RemoveAddressSpaceHandler: %s\n", 521 AcpiFormatException(rv)); 522 rv = AcpiRemoveGpeHandler(NULL, ecdt_sc->sc_gpebit, 523 EcGpeHandler); 524 if (ACPI_FAILURE(rv)) 525 aprint_error("ERROR: RemoveAddressSpaceHandler: %s\n", 526 AcpiFormatException(rv)); 527 528 bus_space_unmap(ecdt_sc->sc_csr_st, 529 ecdt_sc->sc_csr_sh, 1); 530 bus_space_unmap(ecdt_sc->sc_data_st, 531 ecdt_sc->sc_data_sh, 1); 532 533 free(ecdt_sc, M_ACPI); 534 ecdt_sc = NULL; 535 } 536 537 #undef adi 538 539 sc->sc_data_st = aa->aa_iot; 540 io0 = acpi_res_io(&res, 0); 541 if (io0 == NULL) { 542 aprint_error("%s: unable to find data register resource\n", 543 sc->sc_dev.dv_xname); 544 goto out; 545 } 546 if (bus_space_map(sc->sc_data_st, io0->ar_base, io0->ar_length, 547 0, &sc->sc_data_sh) != 0) { 548 aprint_error("%s: unable to map data register\n", 549 sc->sc_dev.dv_xname); 550 goto out; 551 } 552 553 sc->sc_csr_st = aa->aa_iot; 554 io1 = acpi_res_io(&res, 1); 555 if (io1 == NULL) { 556 aprint_error("%s: unable to find csr register resource\n", 557 sc->sc_dev.dv_xname); 558 goto out; 559 } 560 if (bus_space_map(sc->sc_csr_st, io1->ar_base, io1->ar_length, 561 0, &sc->sc_csr_sh) != 0) { 562 aprint_error("%s: unable to map csr register\n", 563 sc->sc_dev.dv_xname); 564 goto out; 565 } 566 567 /* 568 * evaluate _GLK to see if we should acquire global lock 569 * when accessing the EC. 570 */ 571 rv = acpi_eval_integer(sc->sc_handle, "_GLK", &v); 572 if (ACPI_FAILURE(rv)) { 573 if (rv != AE_NOT_FOUND) 574 aprint_error("%s: unable to evaluate _GLK: %s\n", 575 sc->sc_dev.dv_xname, 576 AcpiFormatException(rv)); 577 sc->sc_glk = 0; 578 } else 579 sc->sc_glk = v; 580 581 /* 582 * Install GPE handler. 583 * 584 * We evaluate the _GPE method to find the GPE bit used by the 585 * Embedded Controller to signal status (SCI). 586 */ 587 rv = acpi_eval_integer(sc->sc_handle, "_GPE", &v); 588 if (ACPI_FAILURE(rv)) { 589 aprint_error("%s: unable to evaluate _GPE: %s\n", 590 sc->sc_dev.dv_xname, AcpiFormatException(rv)); 591 goto out; 592 } 593 sc->sc_gpebit = v; 594 595 /* 596 * Install a handler for this EC's GPE bit. Note that EC SCIs are 597 * treated as both edge- and level-triggered interrupts; in other words 598 * we clear the status bit immediately after getting an EC-SCI, then 599 * again after we're done processing the event. This guarantees that 600 * events we cause while performing a transaction (e.g. IBE/OBF) get 601 * cleared before re-enabling the GPE. 602 */ 603 rv = AcpiInstallGpeHandler(NULL, sc->sc_gpebit, 604 ACPI_GPE_EDGE_TRIGGERED, EcGpeHandler, sc); 605 if (ACPI_FAILURE(rv)) { 606 aprint_error("%s: unable to install GPE handler: %s\n", 607 sc->sc_dev.dv_xname, AcpiFormatException(rv)); 608 goto out; 609 } 610 611 rv = AcpiSetGpeType(NULL, sc->sc_gpebit, ACPI_GPE_TYPE_RUNTIME); 612 if (ACPI_FAILURE(rv)) { 613 aprint_error("%s: unable to set GPE type: %s\n", 614 sc->sc_dev.dv_xname, AcpiFormatException(rv)); 615 goto out2; 616 } 617 618 rv = AcpiEnableGpe(NULL, sc->sc_gpebit, ACPI_NOT_ISR); 619 if (ACPI_FAILURE(rv)) { 620 aprint_error("%s: unable to enable GPE: %s\n", 621 sc->sc_dev.dv_xname, AcpiFormatException(rv)); 622 goto out2; 623 } 624 625 /* Install address space handler. */ 626 rv = AcpiInstallAddressSpaceHandler(sc->sc_handle, 627 ACPI_ADR_SPACE_EC, EcSpaceHandler, EcSpaceSetup, sc); 628 if (ACPI_FAILURE(rv)) { 629 aprint_error("%s: unable to install address space handler: %s\n", 630 sc->sc_dev.dv_xname, AcpiFormatException(rv)); 631 goto out2; 632 } 633 634 return_VOID; 635 out2: 636 (void)AcpiRemoveGpeHandler(NULL, sc->sc_gpebit, EcGpeHandler); 637 638 out: 639 acpi_resource_cleanup(&res); 640 return_VOID; 641 } 642 643 static void 644 EcGpeQueryHandler(void *Context) 645 { 646 struct acpi_ec_softc *sc = Context; 647 UINT8 Data = 0; 648 ACPI_STATUS rv; 649 char qxx[5]; 650 651 ACPI_FUNCTION_TRACE(__FUNCTION__); 652 653 for (;;) { 654 /* 655 * Check EC_SCI. 656 * 657 * Bail out if the EC_SCI bit of the status register is not 658 * set. Note that this function should only be called when 659 * this bit is set (polling is used to detect IBE/OBF events). 660 * 661 * It is safe to do this without locking the controller, as 662 * it's OK to call EcQuery when there's no data ready; in the 663 * worst case we should just find nothing waiting for us and 664 * bail. 665 */ 666 if ((EC_CSR_READ(sc) & EC_EVENT_SCI) == 0) 667 break; 668 669 EcLock(sc); 670 671 /* 672 * Find out why the EC is signalling us 673 */ 674 rv = EcQuery(sc, &Data); 675 676 EcUnlock(sc); 677 678 /* 679 * If we failed to get anything from the EC, give up. 680 */ 681 if (ACPI_FAILURE(rv)) { 682 printf("%s: GPE query failed: %s\n", 683 sc->sc_dev.dv_xname, AcpiFormatException(rv)); 684 break; 685 } 686 687 /* 688 * Evaluate _Qxx to respond to the controller. 689 */ 690 snprintf(qxx, sizeof(qxx), "_Q%02X", Data); 691 rv = AcpiEvaluateObject(sc->sc_handle, qxx, 692 NULL, NULL); 693 694 /* 695 * Ignore spurious query requests. 696 */ 697 if (ACPI_FAILURE(rv) && 698 (Data != 0 || rv != AE_NOT_FOUND)) { 699 printf("%s: evaluation of GPE query method %s " 700 "failed: %s\n", sc->sc_dev.dv_xname, qxx, 701 AcpiFormatException(rv)); 702 } 703 } 704 705 /* I know I request Level trigger cleanup */ 706 rv = AcpiClearGpe(NULL, sc->sc_gpebit, ACPI_NOT_ISR); 707 if (ACPI_FAILURE(rv)) 708 printf("%s: AcpiClearGpe failed: %s\n", sc->sc_dev.dv_xname, 709 AcpiFormatException(rv)); 710 711 return_VOID; 712 } 713 714 static UINT32 715 EcGpeHandler(void *Context) 716 { 717 struct acpi_ec_softc *sc = Context; 718 uint32_t csrvalue; 719 ACPI_STATUS rv; 720 721 /* 722 * If EC is locked, the intr must process EcRead/Write wait only. 723 * Query request must be pending. 724 */ 725 simple_lock(&sc->sc_slock); 726 if (sc->sc_flags & EC_F_TRANSACTION) { 727 csrvalue = EC_CSR_READ(sc); 728 sc->sc_flags |= EC_F_PENDQUERY; 729 730 if ((csrvalue & EC_FLAG_OUTPUT_BUFFER) != 0 || 731 (csrvalue & EC_FLAG_INPUT_BUFFER) == 0) { 732 sc->sc_csrvalue = csrvalue; 733 wakeup(&sc->sc_csrvalue); 734 } 735 simple_unlock(&sc->sc_slock); 736 } else { 737 simple_unlock(&sc->sc_slock); 738 /* Enqueue GpeQuery handler. */ 739 rv = AcpiOsQueueForExecution(OSD_PRIORITY_HIGH, 740 EcGpeQueryHandler, Context); 741 if (ACPI_FAILURE(rv)) 742 printf("%s: failed to enqueue query handler: %s\n", 743 sc->sc_dev.dv_xname, AcpiFormatException(rv)); 744 } 745 746 return 0; /* XXX not yet used in ACPI-CA */ 747 } 748 749 static ACPI_STATUS 750 EcSpaceSetup(ACPI_HANDLE Region __unused, UINT32 Function, void *Context, 751 void **RegionContext) 752 { 753 754 ACPI_FUNCTION_TRACE(__FUNCTION__); 755 756 /* 757 * Just pass the context through, there's nothing to do here. 758 */ 759 if (Function == ACPI_REGION_DEACTIVATE) 760 *RegionContext = NULL; 761 else 762 *RegionContext = Context; 763 764 return_ACPI_STATUS(AE_OK); 765 } 766 767 static ACPI_STATUS 768 EcSpaceHandler(UINT32 Function, ACPI_PHYSICAL_ADDRESS Address, UINT32 width, 769 ACPI_INTEGER *Value, void *Context, void *RegionContext __unused) 770 { 771 struct acpi_ec_softc *sc = Context; 772 ACPI_STATUS rv = AE_OK; 773 EC_REQUEST EcRequest; 774 int i; 775 776 ACPI_FUNCTION_TRACE_U32(__FUNCTION__, (UINT32)Address); 777 778 if ((Address > 0xFF) || (width % 8 != 0) || (Value == NULL) || 779 (Context == NULL)) 780 return_ACPI_STATUS(AE_BAD_PARAMETER); 781 782 switch (Function) { 783 case ACPI_READ: 784 EcRequest.Command = EC_COMMAND_READ; 785 EcRequest.Address = Address; 786 (*Value) = 0; 787 break; 788 789 case ACPI_WRITE: 790 EcRequest.Command = EC_COMMAND_WRITE; 791 EcRequest.Address = Address; 792 break; 793 794 default: 795 printf("%s: invalid Address Space function: %d\n", 796 sc->sc_dev.dv_xname, Function); 797 return_ACPI_STATUS(AE_BAD_PARAMETER); 798 } 799 800 /* 801 * Perform the transaction. 802 */ 803 for (i = 0; i < width; i += 8) { 804 if (Function == ACPI_READ) 805 EcRequest.Data = 0; 806 else 807 EcRequest.Data = (UINT8)((*Value) >> i); 808 809 rv = EcTransaction(sc, &EcRequest); 810 if (ACPI_FAILURE(rv)) 811 break; 812 813 (*Value) |= (UINT32)EcRequest.Data << i; 814 if (++EcRequest.Address == 0) 815 return_ACPI_STATUS(AE_BAD_PARAMETER); 816 } 817 818 return_ACPI_STATUS(rv); 819 } 820 821 static ACPI_STATUS 822 EcWaitEventIntr(struct acpi_ec_softc *sc, EC_EVENT Event) 823 { 824 EC_STATUS EcStatus; 825 int i; 826 827 ACPI_FUNCTION_TRACE_U32(__FUNCTION__, (UINT32)Event); 828 829 /* XXX Need better test for "yes, you have interrupts". */ 830 if (cold) 831 return_ACPI_STATUS(EcWaitEvent(sc, Event)); 832 833 if (EcIsLocked(sc) == 0) 834 printf("%s: EcWaitEventIntr called without EC lock!\n", 835 sc->sc_dev.dv_xname); 836 837 EcStatus = EC_CSR_READ(sc); 838 839 /* Too long? */ 840 for (i = 0; i < 10; i++) { 841 /* Check EC status against the desired event. */ 842 if ((Event == EC_EVENT_OUTPUT_BUFFER_FULL) && 843 (EcStatus & EC_FLAG_OUTPUT_BUFFER) != 0) 844 return_ACPI_STATUS(AE_OK); 845 846 if ((Event == EC_EVENT_INPUT_BUFFER_EMPTY) && 847 (EcStatus & EC_FLAG_INPUT_BUFFER) == 0) 848 return_ACPI_STATUS(AE_OK); 849 850 sc->sc_csrvalue = 0; 851 /* XXXJRT Sleeping with a lock held? */ 852 if (tsleep(&sc->sc_csrvalue, 0, "EcWait", (hz + 99) / 100) 853 != EWOULDBLOCK) 854 EcStatus = sc->sc_csrvalue; 855 else 856 EcStatus = EC_CSR_READ(sc); 857 } 858 return_ACPI_STATUS(AE_ERROR); 859 } 860 861 static ACPI_STATUS 862 EcWaitEvent(struct acpi_ec_softc *sc, EC_EVENT Event) 863 { 864 EC_STATUS EcStatus; 865 UINT32 i = 0; 866 867 if (EcIsLocked(sc) == 0) 868 printf("%s: EcWaitEvent called without EC lock!\n", 869 sc->sc_dev.dv_xname); 870 871 /* 872 * Stall 1us: 873 * ---------- 874 * Stall for 1 microsecond before reading the status register 875 * for the first time. This allows the EC to set the IBF/OBF 876 * bit to its proper state. 877 * 878 * XXX it is not clear why we read the CSR twice. 879 */ 880 AcpiOsStall(1); 881 EcStatus = EC_CSR_READ(sc); 882 883 /* 884 * Wait For Event: 885 * --------------- 886 * Poll the EC status register to detect completion of the last 887 * command. Wait up to 10ms (in 100us chunks) for this to occur. 888 */ 889 for (i = 0; i < 100; i++) { 890 EcStatus = EC_CSR_READ(sc); 891 892 if ((Event == EC_EVENT_OUTPUT_BUFFER_FULL) && 893 (EcStatus & EC_FLAG_OUTPUT_BUFFER) != 0) 894 return AE_OK; 895 896 if ((Event == EC_EVENT_INPUT_BUFFER_EMPTY) && 897 (EcStatus & EC_FLAG_INPUT_BUFFER) == 0) 898 return AE_OK; 899 900 AcpiOsStall(10); 901 } 902 903 return AE_ERROR; 904 } 905 906 static ACPI_STATUS 907 EcQuery(struct acpi_ec_softc *sc, UINT8 *Data) 908 { 909 ACPI_STATUS rv; 910 911 if (EcIsLocked(sc) == 0) 912 printf("%s: EcQuery called without EC lock!\n", 913 sc->sc_dev.dv_xname); 914 915 EC_CSR_WRITE(sc, EC_COMMAND_QUERY); 916 rv = EcWaitEventIntr(sc, EC_EVENT_OUTPUT_BUFFER_FULL); 917 if (ACPI_SUCCESS(rv)) 918 *Data = EC_DATA_READ(sc); 919 920 if (ACPI_FAILURE(rv)) 921 printf("%s: timed out waiting for EC to respond to " 922 "EC_COMMAND_QUERY\n", sc->sc_dev.dv_xname); 923 924 return rv; 925 } 926 927 static ACPI_STATUS 928 EcTransaction(struct acpi_ec_softc *sc, EC_REQUEST *EcRequest) 929 { 930 ACPI_STATUS rv; 931 932 EcLock(sc); 933 934 /* 935 * Perform the transaction. 936 */ 937 switch (EcRequest->Command) { 938 case EC_COMMAND_READ: 939 rv = EcRead(sc, EcRequest->Address, &(EcRequest->Data)); 940 break; 941 942 case EC_COMMAND_WRITE: 943 rv = EcWrite(sc, EcRequest->Address, &(EcRequest->Data)); 944 break; 945 946 default: 947 rv = AE_SUPPORT; 948 break; 949 } 950 951 EcUnlock(sc); 952 953 return rv; 954 } 955 956 static ACPI_STATUS 957 EcRead(struct acpi_ec_softc *sc, UINT8 Address, UINT8 *Data) 958 { 959 ACPI_STATUS rv; 960 961 if (EcIsLocked(sc) == 0) 962 printf("%s: EcRead called without EC lock!\n", 963 sc->sc_dev.dv_xname); 964 965 /* EcBurstEnable(EmbeddedController); */ 966 967 EC_CSR_WRITE(sc, EC_COMMAND_READ); 968 if ((rv = EcWaitEventIntr(sc, EC_EVENT_INPUT_BUFFER_EMPTY)) != 969 AE_OK) { 970 printf("%s: EcRead: timeout waiting for EC to process " 971 "read command\n", sc->sc_dev.dv_xname); 972 return rv; 973 } 974 975 EC_DATA_WRITE(sc, Address); 976 if ((rv = EcWaitEventIntr(sc, EC_EVENT_OUTPUT_BUFFER_FULL)) != 977 AE_OK) { 978 printf("%s: EcRead: timeout waiting for EC to send data\n", 979 sc->sc_dev.dv_xname); 980 return rv; 981 } 982 983 (*Data) = EC_DATA_READ(sc); 984 985 /* EcBurstDisable(EmbeddedController); */ 986 987 return AE_OK; 988 } 989 990 static ACPI_STATUS 991 EcWrite(struct acpi_ec_softc *sc, UINT8 Address, UINT8 *Data) 992 { 993 ACPI_STATUS rv; 994 995 if (EcIsLocked(sc) == 0) 996 printf("%s: EcWrite called without EC lock!\n", 997 sc->sc_dev.dv_xname); 998 999 /* EcBurstEnable(EmbeddedController); */ 1000 1001 EC_CSR_WRITE(sc, EC_COMMAND_WRITE); 1002 if ((rv = EcWaitEventIntr(sc, EC_EVENT_INPUT_BUFFER_EMPTY)) != 1003 AE_OK) { 1004 printf("%s: EcWrite: timeout waiting for EC to process " 1005 "write command\n", sc->sc_dev.dv_xname); 1006 return rv; 1007 } 1008 1009 EC_DATA_WRITE(sc, Address); 1010 if ((rv = EcWaitEventIntr(sc, EC_EVENT_INPUT_BUFFER_EMPTY)) != 1011 AE_OK) { 1012 printf("%s: EcWrite: timeout waiting for EC to process " 1013 "address\n", sc->sc_dev.dv_xname); 1014 return rv; 1015 } 1016 1017 EC_DATA_WRITE(sc, *Data); 1018 if ((rv = EcWaitEventIntr(sc, EC_EVENT_INPUT_BUFFER_EMPTY)) != 1019 AE_OK) { 1020 printf("%s: EcWrite: timeout waiting for EC to process " 1021 "data\n", sc->sc_dev.dv_xname); 1022 return rv; 1023 } 1024 1025 /* EcBurstDisable(EmbeddedController); */ 1026 1027 return AE_OK; 1028 } 1029