1 /* $OpenBSD: dwiic_acpi.c,v 1.22 2023/07/08 02:43:02 jcs Exp $ */ 2 /* 3 * Synopsys DesignWare I2C controller 4 * 5 * Copyright (c) 2015, 2016 joshua stein <jcs@openbsd.org> 6 * 7 * Permission to use, copy, modify, and/or distribute this software for any 8 * purpose with or without fee is hereby granted, provided that the above 9 * copyright notice and this permission notice appear in all copies. 10 * 11 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 12 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 13 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 14 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 15 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 16 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 17 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 18 */ 19 20 #include "iosf.h" 21 22 #include <sys/param.h> 23 #include <sys/systm.h> 24 #include <sys/kernel.h> 25 26 #include <dev/acpi/acpireg.h> 27 #include <dev/acpi/acpivar.h> 28 #include <dev/acpi/acpidev.h> 29 #include <dev/acpi/amltypes.h> 30 #include <dev/acpi/dsdt.h> 31 32 #include <dev/ic/dwiicvar.h> 33 #include <dev/ic/iosfvar.h> 34 35 struct dwiic_crs { 36 int irq_int; 37 uint8_t irq_flags; 38 uint16_t i2c_addr; 39 struct aml_node *devnode; 40 struct aml_node *gpio_int_node; 41 uint16_t gpio_int_pin; 42 uint16_t gpio_int_flags; 43 }; 44 45 int dwiic_acpi_match(struct device *, void *, void *); 46 void dwiic_acpi_attach(struct device *, struct device *, void *); 47 48 int dwiic_acpi_parse_crs(int, union acpi_resource *, void *); 49 int dwiic_acpi_found_ihidev(struct dwiic_softc *, 50 struct aml_node *, char *, struct dwiic_crs); 51 int dwiic_acpi_found_iatp(struct dwiic_softc *, struct aml_node *, 52 char *, struct dwiic_crs); 53 int dwiic_acpi_found_ietp(struct dwiic_softc *, struct aml_node *, 54 char *, struct dwiic_crs); 55 void dwiic_acpi_get_params(struct dwiic_softc *, char *, uint16_t *, 56 uint16_t *, uint32_t *); 57 void dwiic_acpi_power(struct dwiic_softc *, int); 58 void dwiic_acpi_bus_scan(struct device *, 59 struct i2cbus_attach_args *, void *); 60 61 #if NIOSF > 0 62 int dwiic_acpi_acquire_bus(void *, int); 63 void dwiic_acpi_release_bus(void *, int); 64 #endif 65 66 const struct cfattach dwiic_acpi_ca = { 67 sizeof(struct dwiic_softc), 68 dwiic_acpi_match, 69 dwiic_acpi_attach, 70 NULL, 71 dwiic_activate 72 }; 73 74 const char *dwiic_hids[] = { 75 "AMDI0010", 76 "APMC0D0F", 77 "INT33C2", 78 "INT33C3", 79 "INT3432", 80 "INT3433", 81 "80860F41", 82 "808622C1", 83 NULL 84 }; 85 86 const char *ihidev_hids[] = { 87 "PNP0C50", 88 "ACPI0C50", 89 NULL 90 }; 91 92 const char *ietp_hids[] = { 93 "ELAN0000", 94 "ELAN0100", 95 "ELAN0600", 96 "ELAN0601", 97 "ELAN0602", 98 "ELAN0603", 99 "ELAN0604", 100 "ELAN0605", 101 "ELAN0606", 102 "ELAN0607", 103 "ELAN0608", 104 "ELAN0609", 105 "ELAN060B", 106 "ELAN060C", 107 "ELAN060F", 108 "ELAN0610", 109 "ELAN0611", 110 "ELAN0612", 111 "ELAN0615", 112 "ELAN0616", 113 "ELAN0617", 114 "ELAN0618", 115 "ELAN0619", 116 "ELAN061A", 117 "ELAN061B", 118 "ELAN061C", 119 "ELAN061D", 120 "ELAN061E", 121 "ELAN061F", 122 "ELAN0620", 123 "ELAN0621", 124 "ELAN0622", 125 "ELAN0623", 126 "ELAN0624", 127 "ELAN0625", 128 "ELAN0626", 129 "ELAN0627", 130 "ELAN0628", 131 "ELAN0629", 132 "ELAN062A", 133 "ELAN062B", 134 "ELAN062C", 135 "ELAN062D", 136 "ELAN062E", /* Lenovo V340 Whiskey Lake U */ 137 "ELAN062F", /* Lenovo V340 Comet Lake U */ 138 "ELAN0631", 139 "ELAN0632", 140 "ELAN0633", /* Lenovo S145 */ 141 "ELAN0634", /* Lenovo V340 Ice lake */ 142 "ELAN0635", /* Lenovo V1415-IIL */ 143 "ELAN0636", /* Lenovo V1415-Dali */ 144 "ELAN0637", /* Lenovo V1415-IGLR */ 145 "ELAN1000", 146 NULL 147 }; 148 149 const char *iatp_hids[] = { 150 "ATML0000", 151 "ATML0001", 152 NULL 153 }; 154 155 int 156 dwiic_acpi_match(struct device *parent, void *match, void *aux) 157 { 158 struct acpi_attach_args *aaa = aux; 159 struct cfdata *cf = match; 160 161 if (aaa->aaa_naddr < 1) 162 return 0; 163 return acpi_matchhids(aaa, dwiic_hids, cf->cf_driver->cd_name); 164 } 165 166 void 167 dwiic_acpi_attach(struct device *parent, struct device *self, void *aux) 168 { 169 struct dwiic_softc *sc = (struct dwiic_softc *)self; 170 struct acpi_attach_args *aaa = aux; 171 struct aml_value res; 172 struct dwiic_crs crs; 173 uint64_t sem; 174 175 sc->sc_acpi = (struct acpi_softc *)parent; 176 sc->sc_devnode = aaa->aaa_node; 177 memcpy(&sc->sc_hid, aaa->aaa_dev, sizeof(sc->sc_hid)); 178 179 printf(" %s", sc->sc_devnode->name); 180 181 if (aml_evalname(sc->sc_acpi, sc->sc_devnode, "_CRS", 0, NULL, &res)) { 182 printf(", no _CRS method\n"); 183 return; 184 } 185 if (res.type != AML_OBJTYPE_BUFFER || res.length < 5) { 186 printf(", invalid _CRS object (type %d len %d)\n", 187 res.type, res.length); 188 aml_freevalue(&res); 189 return; 190 } 191 memset(&crs, 0, sizeof(crs)); 192 crs.devnode = sc->sc_devnode; 193 aml_parse_resource(&res, dwiic_acpi_parse_crs, &crs); 194 aml_freevalue(&res); 195 196 printf(" addr 0x%llx/0x%llx", aaa->aaa_addr[0], aaa->aaa_size[0]); 197 198 sc->sc_iot = aaa->aaa_bst[0]; 199 if (bus_space_map(sc->sc_iot, aaa->aaa_addr[0], aaa->aaa_size[0], 200 0, &sc->sc_ioh)) { 201 printf(": can't map registers\n"); 202 return; 203 } 204 205 /* power up the controller */ 206 dwiic_acpi_power(sc, 1); 207 208 /* fetch timing parameters */ 209 dwiic_acpi_get_params(sc, "SSCN", &sc->ss_hcnt, &sc->ss_lcnt, NULL); 210 dwiic_acpi_get_params(sc, "FMCN", &sc->fs_hcnt, &sc->fs_lcnt, 211 &sc->sda_hold_time); 212 213 if (dwiic_init(sc)) { 214 printf(", failed initializing\n"); 215 bus_space_unmap(sc->sc_iot, sc->sc_ioh, aaa->aaa_size[0]); 216 return; 217 } 218 219 /* leave the controller disabled */ 220 dwiic_write(sc, DW_IC_INTR_MASK, 0); 221 dwiic_enable(sc, 0); 222 dwiic_read(sc, DW_IC_CLR_INTR); 223 224 /* try to register interrupt with apic, but not fatal without it */ 225 if (aaa->aaa_nirq > 0) { 226 printf(" irq %d", aaa->aaa_irq[0]); 227 228 sc->sc_ih = acpi_intr_establish(aaa->aaa_irq[0], aaa->aaa_irq_flags[0], 229 IPL_BIO, dwiic_intr, sc, sc->sc_dev.dv_xname); 230 if (sc->sc_ih == NULL) 231 printf(": can't establish interrupt"); 232 } 233 234 if (aml_evalinteger(sc->sc_acpi, sc->sc_devnode, 235 "_SEM", 0, NULL, &sem)) 236 sem = 0; 237 238 if (sem) 239 printf(", sem"); 240 241 printf("\n"); 242 243 rw_init(&sc->sc_i2c_lock, "iiclk"); 244 245 /* setup and attach iic bus */ 246 sc->sc_i2c_tag.ic_cookie = sc; 247 sc->sc_i2c_tag.ic_acquire_bus = dwiic_i2c_acquire_bus; 248 sc->sc_i2c_tag.ic_release_bus = dwiic_i2c_release_bus; 249 sc->sc_i2c_tag.ic_exec = dwiic_i2c_exec; 250 sc->sc_i2c_tag.ic_intr_establish = dwiic_i2c_intr_establish; 251 sc->sc_i2c_tag.ic_intr_disestablish = dwiic_i2c_intr_disestablish; 252 sc->sc_i2c_tag.ic_intr_string = dwiic_i2c_intr_string; 253 254 #if NIOSF > 0 255 if (sem) { 256 sc->sc_i2c_tag.ic_acquire_bus = dwiic_acpi_acquire_bus; 257 sc->sc_i2c_tag.ic_release_bus = dwiic_acpi_release_bus; 258 } 259 #endif 260 261 bzero(&sc->sc_iba, sizeof(sc->sc_iba)); 262 sc->sc_iba.iba_name = "iic"; 263 sc->sc_iba.iba_tag = &sc->sc_i2c_tag; 264 sc->sc_iba.iba_bus_scan = dwiic_acpi_bus_scan; 265 sc->sc_iba.iba_bus_scan_arg = sc; 266 267 config_found((struct device *)sc, &sc->sc_iba, iicbus_print); 268 269 #ifndef SMALL_KERNEL 270 sc->sc_devnode->i2c = &sc->sc_i2c_tag; 271 acpi_register_gsb(sc->sc_acpi, sc->sc_devnode); 272 #endif 273 } 274 275 int 276 dwiic_acpi_parse_crs(int crsidx, union acpi_resource *crs, void *arg) 277 { 278 struct dwiic_crs *sc_crs = arg; 279 struct aml_node *node; 280 uint16_t pin; 281 uint8_t flags; 282 283 switch (AML_CRSTYPE(crs)) { 284 case SR_IRQ: 285 sc_crs->irq_int = ffs(letoh16(crs->sr_irq.irq_mask)) - 1; 286 /* Default is exclusive, active-high, edge triggered. */ 287 if (AML_CRSLEN(crs) < 4) 288 flags = SR_IRQ_MODE; 289 else 290 flags = crs->sr_irq.irq_flags; 291 /* Map flags to those of the extended interrupt descriptor. */ 292 if (flags & SR_IRQ_SHR) 293 sc_crs->irq_flags |= LR_EXTIRQ_SHR; 294 if (flags & SR_IRQ_POLARITY) 295 sc_crs->irq_flags |= LR_EXTIRQ_POLARITY; 296 if (flags & SR_IRQ_MODE) 297 sc_crs->irq_flags |= LR_EXTIRQ_MODE; 298 break; 299 300 case LR_EXTIRQ: 301 sc_crs->irq_int = letoh32(crs->lr_extirq.irq[0]); 302 sc_crs->irq_flags = crs->lr_extirq.flags; 303 break; 304 305 case LR_GPIO: 306 node = aml_searchname(sc_crs->devnode, 307 (char *)&crs->pad[crs->lr_gpio.res_off]); 308 pin = *(uint16_t *)&crs->pad[crs->lr_gpio.pin_off]; 309 if (crs->lr_gpio.type == LR_GPIO_INT) { 310 sc_crs->gpio_int_node = node; 311 sc_crs->gpio_int_pin = pin; 312 sc_crs->gpio_int_flags = crs->lr_gpio.tflags; 313 } 314 break; 315 316 case LR_SERBUS: 317 if (crs->lr_serbus.type == LR_SERBUS_I2C) 318 sc_crs->i2c_addr = letoh16(crs->lr_i2cbus._adr); 319 break; 320 321 case LR_MEM32: 322 case LR_MEM32FIXED: 323 break; 324 325 default: 326 DPRINTF(("%s: unknown resource type %d\n", __func__, 327 AML_CRSTYPE(crs))); 328 } 329 330 return 0; 331 } 332 333 void 334 dwiic_acpi_get_params(struct dwiic_softc *sc, char *method, uint16_t *hcnt, 335 uint16_t *lcnt, uint32_t *sda_hold_time) 336 { 337 struct aml_value res; 338 339 if (!aml_searchname(sc->sc_devnode, method)) 340 return; 341 342 if (aml_evalname(sc->sc_acpi, sc->sc_devnode, method, 0, NULL, &res)) { 343 printf(": eval of %s at %s failed", method, 344 aml_nodename(sc->sc_devnode)); 345 return; 346 } 347 348 if (res.type != AML_OBJTYPE_PACKAGE) { 349 printf(": %s is not a package (%d)", method, res.type); 350 aml_freevalue(&res); 351 return; 352 } 353 354 if (res.length <= 2) { 355 printf(": %s returned package of len %d", method, res.length); 356 aml_freevalue(&res); 357 return; 358 } 359 360 *hcnt = aml_val2int(res.v_package[0]); 361 *lcnt = aml_val2int(res.v_package[1]); 362 if (sda_hold_time) 363 *sda_hold_time = aml_val2int(res.v_package[2]); 364 aml_freevalue(&res); 365 } 366 367 void 368 dwiic_acpi_bus_scan(struct device *iic, struct i2cbus_attach_args *iba, 369 void *aux) 370 { 371 struct dwiic_softc *sc = (struct dwiic_softc *)aux; 372 373 sc->sc_iic = iic; 374 aml_find_node(sc->sc_devnode, "_HID", dwiic_acpi_found_hid, sc); 375 } 376 377 void * 378 dwiic_i2c_intr_establish(void *cookie, void *ih, int level, 379 int (*func)(void *), void *arg, const char *name) 380 { 381 struct dwiic_crs *crs = ih; 382 383 if (crs->gpio_int_node) { 384 if (!crs->gpio_int_node->gpio) 385 /* found ACPI device but no driver for it */ 386 return NULL; 387 388 struct acpi_gpio *gpio = crs->gpio_int_node->gpio; 389 gpio->intr_establish(gpio->cookie, crs->gpio_int_pin, 390 crs->gpio_int_flags, func, arg); 391 return ih; 392 } 393 394 return acpi_intr_establish(crs->irq_int, crs->irq_flags, 395 level, func, arg, name); 396 } 397 398 void 399 dwiic_i2c_intr_disestablish(void *cookie, void *ih) 400 { 401 /* XXX GPIO interrupts */ 402 acpi_intr_disestablish(ih); 403 } 404 405 const char * 406 dwiic_i2c_intr_string(void *cookie, void *ih) 407 { 408 struct dwiic_crs *crs = ih; 409 static char irqstr[64]; 410 411 if (crs->gpio_int_node) { 412 if (crs->gpio_int_node->gpio) 413 snprintf(irqstr, sizeof(irqstr), "gpio %d", 414 crs->gpio_int_pin); 415 } else 416 snprintf(irqstr, sizeof(irqstr), "irq %d", crs->irq_int); 417 418 return irqstr; 419 } 420 421 int 422 dwiic_matchhids(const char *hid, const char *hids[]) 423 { 424 int i; 425 426 for (i = 0; hids[i]; i++) 427 if (!strcmp(hid, hids[i])) 428 return (1); 429 430 return (0); 431 } 432 433 int 434 dwiic_acpi_found_hid(struct aml_node *node, void *arg) 435 { 436 struct dwiic_softc *sc = (struct dwiic_softc *)arg; 437 struct dwiic_crs crs; 438 struct aml_value res; 439 int64_t sta; 440 char cdev[16], dev[16]; 441 struct i2c_attach_args ia; 442 443 /* Skip our own _HID. */ 444 if (node->parent == sc->sc_devnode) 445 return 0; 446 447 if (acpi_parsehid(node, arg, cdev, dev, 16) != 0) 448 return 0; 449 450 if (aml_evalinteger(acpi_softc, node->parent, "_STA", 0, NULL, &sta)) 451 sta = STA_PRESENT | STA_ENABLED | STA_DEV_OK | 0x1000; 452 453 if ((sta & STA_PRESENT) == 0) 454 return 0; 455 456 DPRINTF(("%s: found HID %s at %s\n", sc->sc_dev.dv_xname, dev, 457 aml_nodename(node))); 458 459 if (aml_evalname(acpi_softc, node->parent, "_CRS", 0, NULL, &res)) 460 return 0; 461 462 if (res.type != AML_OBJTYPE_BUFFER || res.length < 5) { 463 printf("%s: invalid _CRS object (type %d len %d)\n", 464 sc->sc_dev.dv_xname, res.type, res.length); 465 aml_freevalue(&res); 466 return (0); 467 } 468 memset(&crs, 0, sizeof(crs)); 469 crs.devnode = sc->sc_devnode; 470 aml_parse_resource(&res, dwiic_acpi_parse_crs, &crs); 471 aml_freevalue(&res); 472 473 acpi_attach_deps(acpi_softc, node->parent); 474 475 if (dwiic_matchhids(cdev, ihidev_hids)) 476 return dwiic_acpi_found_ihidev(sc, node, dev, crs); 477 else if (dwiic_matchhids(dev, iatp_hids)) 478 return dwiic_acpi_found_iatp(sc, node, dev, crs); 479 else if (dwiic_matchhids(dev, ietp_hids) || dwiic_matchhids(cdev, ietp_hids)) 480 return dwiic_acpi_found_ietp(sc, node, dev, crs); 481 482 memset(&ia, 0, sizeof(ia)); 483 ia.ia_tag = sc->sc_iba.iba_tag; 484 ia.ia_name = dev; 485 ia.ia_addr = crs.i2c_addr; 486 ia.ia_cookie = node->parent; 487 488 if (crs.irq_int != 0 || crs.gpio_int_node != NULL) 489 ia.ia_intr = &crs; 490 491 config_found(sc->sc_iic, &ia, dwiic_i2c_print); 492 node->parent->attached = 1; 493 494 return 0; 495 } 496 497 int 498 dwiic_acpi_found_ihidev(struct dwiic_softc *sc, struct aml_node *node, 499 char *dev, struct dwiic_crs crs) 500 { 501 struct i2c_attach_args ia; 502 struct aml_value cmd[4], res; 503 504 /* 3cdff6f7-4267-4555-ad05-b30a3d8938de */ 505 static uint8_t i2c_hid_guid[] = { 506 0xF7, 0xF6, 0xDF, 0x3C, 0x67, 0x42, 0x55, 0x45, 507 0xAD, 0x05, 0xB3, 0x0A, 0x3D, 0x89, 0x38, 0xDE, 508 }; 509 510 if (!aml_searchname(node->parent, "_DSM")) { 511 printf("%s: couldn't find _DSM at %s\n", sc->sc_dev.dv_xname, 512 aml_nodename(node->parent)); 513 return 0; 514 } 515 516 bzero(&cmd, sizeof(cmd)); 517 cmd[0].type = AML_OBJTYPE_BUFFER; 518 cmd[0].v_buffer = (uint8_t *)&i2c_hid_guid; 519 cmd[0].length = sizeof(i2c_hid_guid); 520 /* rev */ 521 cmd[1].type = AML_OBJTYPE_INTEGER; 522 cmd[1].v_integer = 1; 523 cmd[1].length = 1; 524 /* func */ 525 cmd[2].type = AML_OBJTYPE_INTEGER; 526 cmd[2].v_integer = 1; /* HID */ 527 cmd[2].length = 1; 528 /* not used */ 529 cmd[3].type = AML_OBJTYPE_PACKAGE; 530 cmd[3].length = 0; 531 532 if (aml_evalname(acpi_softc, node->parent, "_DSM", 4, cmd, &res)) { 533 printf("%s: eval of _DSM at %s failed\n", 534 sc->sc_dev.dv_xname, aml_nodename(node->parent)); 535 return 0; 536 } 537 538 if (res.type != AML_OBJTYPE_INTEGER) { 539 printf("%s: bad _DSM result at %s: %d\n", 540 sc->sc_dev.dv_xname, aml_nodename(node->parent), res.type); 541 aml_freevalue(&res); 542 return 0; 543 } 544 545 memset(&ia, 0, sizeof(ia)); 546 ia.ia_tag = sc->sc_iba.iba_tag; 547 ia.ia_size = 1; 548 ia.ia_name = "ihidev"; 549 ia.ia_size = aml_val2int(&res); /* hid descriptor address */ 550 ia.ia_addr = crs.i2c_addr; 551 ia.ia_cookie = dev; 552 553 aml_freevalue(&res); 554 555 if (sc->sc_poll_ihidev) 556 ia.ia_poll = 1; 557 if (!(crs.irq_int == 0 && crs.gpio_int_node == NULL)) 558 ia.ia_intr = &crs; 559 560 if (config_found(sc->sc_iic, &ia, dwiic_i2c_print)) { 561 node->parent->attached = 1; 562 return 0; 563 } 564 565 return 1; 566 } 567 568 int 569 dwiic_acpi_found_ietp(struct dwiic_softc *sc, struct aml_node *node, 570 char *dev, struct dwiic_crs crs) 571 { 572 struct i2c_attach_args ia; 573 574 memset(&ia, 0, sizeof(ia)); 575 ia.ia_tag = sc->sc_iba.iba_tag; 576 ia.ia_size = 1; 577 ia.ia_name = "ietp"; 578 ia.ia_addr = crs.i2c_addr; 579 ia.ia_cookie = dev; 580 581 if (sc->sc_poll_ihidev) 582 ia.ia_poll = 1; 583 if (!(crs.irq_int == 0 && crs.gpio_int_node == NULL)) 584 ia.ia_intr = &crs; 585 586 if (config_found(sc->sc_iic, &ia, dwiic_i2c_print)) { 587 node->parent->attached = 1; 588 return 0; 589 } 590 591 return 1; 592 } 593 594 int 595 dwiic_acpi_found_iatp(struct dwiic_softc *sc, struct aml_node *node, char *dev, 596 struct dwiic_crs crs) 597 { 598 struct i2c_attach_args ia; 599 struct aml_value res; 600 601 if (aml_evalname(acpi_softc, node->parent, "GPIO", 0, NULL, &res)) 602 /* no gpio, assume this is the bootloader interface */ 603 return (0); 604 605 memset(&ia, 0, sizeof(ia)); 606 ia.ia_tag = sc->sc_iba.iba_tag; 607 ia.ia_size = 1; 608 ia.ia_name = "iatp"; 609 ia.ia_addr = crs.i2c_addr; 610 ia.ia_cookie = dev; 611 612 if (crs.irq_int <= 0 && crs.gpio_int_node == NULL) { 613 printf("%s: couldn't find irq for %s\n", sc->sc_dev.dv_xname, 614 aml_nodename(node->parent)); 615 return 0; 616 } 617 ia.ia_intr = &crs; 618 619 if (config_found(sc->sc_iic, &ia, dwiic_i2c_print)) { 620 node->parent->attached = 1; 621 return 0; 622 } 623 624 return 1; 625 } 626 627 void 628 dwiic_acpi_power(struct dwiic_softc *sc, int power) 629 { 630 char ps[] = "_PS0"; 631 632 if (!power) 633 ps[3] = '3'; 634 635 if (aml_searchname(sc->sc_devnode, ps)) { 636 if (aml_evalname(sc->sc_acpi, sc->sc_devnode, ps, 0, NULL, 637 NULL)) { 638 printf("%s: failed powering %s with %s\n", 639 sc->sc_dev.dv_xname, power ? "on" : "off", 640 ps); 641 return; 642 } 643 644 DELAY(10000); /* 10 milliseconds */ 645 } else 646 DPRINTF(("%s: no %s method\n", sc->sc_dev.dv_xname, ps)); 647 648 if (strcmp(sc->sc_hid, "INT3432") == 0 || 649 strcmp(sc->sc_hid, "INT3433") == 0) { 650 /* 651 * XXX: broadwell i2c devices may need this for initial power 652 * up and/or after s3 resume. 653 * 654 * linux does this write via LPSS -> clk_register_gate -> 655 * clk_gate_enable -> clk_gate_endisable -> clk_writel 656 */ 657 dwiic_write(sc, 0x800, 1); 658 } 659 } 660 661 #if NIOSF > 0 662 extern int iosf_i2c_acquire(int); 663 extern void iosf_i2c_release(int); 664 665 int 666 dwiic_acpi_acquire_bus(void *cookie, int flags) 667 { 668 int rv; 669 670 rv = dwiic_i2c_acquire_bus(cookie, flags); 671 if (rv != 0) 672 return (rv); 673 674 return (iosf_i2c_acquire(flags)); 675 } 676 677 void 678 dwiic_acpi_release_bus(void *cookie, int flags) 679 { 680 iosf_i2c_release(flags); 681 dwiic_i2c_release_bus(cookie, flags); 682 } 683 #endif /* NIOSF > 0 */ 684