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