1 /* $OpenBSD: dwiic_acpi.c,v 1.8 2018/07/01 11:37:11 kettenis 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 <sys/param.h> 21 #include <sys/systm.h> 22 #include <sys/kernel.h> 23 #include <sys/kthread.h> 24 25 #include <dev/acpi/acpireg.h> 26 #include <dev/acpi/acpivar.h> 27 #include <dev/acpi/acpidev.h> 28 #include <dev/acpi/amltypes.h> 29 #include <dev/acpi/dsdt.h> 30 31 #include <dev/ic/dwiicvar.h> 32 33 struct dwiic_crs { 34 int irq_int; 35 uint8_t irq_flags; 36 uint32_t addr_min; 37 uint32_t addr_bas; 38 uint32_t addr_len; 39 uint16_t i2c_addr; 40 struct aml_node *devnode; 41 struct aml_node *gpio_int_node; 42 uint16_t gpio_int_pin; 43 uint16_t gpio_int_flags; 44 }; 45 46 int dwiic_acpi_match(struct device *, void *, void *); 47 void dwiic_acpi_attach(struct device *, struct device *, void *); 48 49 int dwiic_acpi_parse_crs(int, union acpi_resource *, void *); 50 int dwiic_acpi_found_ihidev(struct dwiic_softc *, 51 struct aml_node *, char *, struct dwiic_crs); 52 int dwiic_acpi_found_iatp(struct dwiic_softc *, struct aml_node *, 53 char *, struct dwiic_crs); 54 void dwiic_acpi_get_params(struct dwiic_softc *, char *, uint16_t *, 55 uint16_t *, uint32_t *); 56 void dwiic_acpi_power(struct dwiic_softc *, int); 57 void dwiic_acpi_bus_scan(struct device *, 58 struct i2cbus_attach_args *, void *); 59 60 struct cfattach dwiic_acpi_ca = { 61 sizeof(struct dwiic_softc), 62 dwiic_acpi_match, 63 dwiic_acpi_attach, 64 NULL, 65 dwiic_activate 66 }; 67 68 const char *dwiic_hids[] = { 69 "INT33C2", 70 "INT33C3", 71 "INT3432", 72 "INT3433", 73 "80860F41", 74 "808622C1", 75 NULL 76 }; 77 78 const char *ihidev_hids[] = { 79 "PNP0C50", 80 "ACPI0C50", 81 NULL 82 }; 83 84 const char *iatp_hids[] = { 85 "ATML0000", 86 "ATML0001", 87 NULL 88 }; 89 90 int 91 dwiic_acpi_match(struct device *parent, void *match, void *aux) 92 { 93 struct acpi_attach_args *aaa = aux; 94 struct cfdata *cf = match; 95 96 return acpi_matchhids(aaa, dwiic_hids, cf->cf_driver->cd_name); 97 } 98 99 void 100 dwiic_acpi_attach(struct device *parent, struct device *self, void *aux) 101 { 102 struct dwiic_softc *sc = (struct dwiic_softc *)self; 103 struct acpi_attach_args *aa = aux; 104 struct aml_value res; 105 struct dwiic_crs crs; 106 107 sc->sc_acpi = (struct acpi_softc *)parent; 108 sc->sc_devnode = aa->aaa_node; 109 memcpy(&sc->sc_hid, aa->aaa_dev, sizeof(sc->sc_hid)); 110 111 printf(" %s", sc->sc_devnode->name); 112 113 if (aml_evalname(sc->sc_acpi, sc->sc_devnode, "_CRS", 0, NULL, &res)) { 114 printf(", no _CRS method\n"); 115 return; 116 } 117 if (res.type != AML_OBJTYPE_BUFFER || res.length < 5) { 118 printf(", invalid _CRS object (type %d len %d)\n", 119 res.type, res.length); 120 aml_freevalue(&res); 121 return; 122 } 123 memset(&crs, 0, sizeof(crs)); 124 crs.devnode = sc->sc_devnode; 125 aml_parse_resource(&res, dwiic_acpi_parse_crs, &crs); 126 aml_freevalue(&res); 127 128 if (crs.addr_bas == 0) { 129 printf(", can't find address\n"); 130 return; 131 } 132 133 printf(" addr 0x%x/0x%x", crs.addr_bas, crs.addr_len); 134 135 sc->sc_iot = aa->aaa_memt; 136 if (bus_space_map(sc->sc_iot, crs.addr_bas, crs.addr_len, 0, 137 &sc->sc_ioh)) { 138 printf(", failed mapping at 0x%x\n", crs.addr_bas); 139 return; 140 } 141 142 /* power up the controller */ 143 dwiic_acpi_power(sc, 1); 144 145 /* fetch timing parameters */ 146 sc->ss_hcnt = dwiic_read(sc, DW_IC_SS_SCL_HCNT); 147 sc->ss_lcnt = dwiic_read(sc, DW_IC_SS_SCL_LCNT); 148 sc->fs_hcnt = dwiic_read(sc, DW_IC_FS_SCL_HCNT); 149 sc->fs_lcnt = dwiic_read(sc, DW_IC_FS_SCL_LCNT); 150 sc->sda_hold_time = dwiic_read(sc, DW_IC_SDA_HOLD); 151 dwiic_acpi_get_params(sc, "SSCN", &sc->ss_hcnt, &sc->ss_lcnt, NULL); 152 dwiic_acpi_get_params(sc, "FMCN", &sc->fs_hcnt, &sc->fs_lcnt, 153 &sc->sda_hold_time); 154 155 if (dwiic_init(sc)) { 156 printf(", failed initializing\n"); 157 bus_space_unmap(sc->sc_iot, sc->sc_ioh, crs.addr_len); 158 return; 159 } 160 161 /* leave the controller disabled */ 162 dwiic_write(sc, DW_IC_INTR_MASK, 0); 163 dwiic_enable(sc, 0); 164 dwiic_read(sc, DW_IC_CLR_INTR); 165 166 /* try to register interrupt with apic, but not fatal without it */ 167 if (crs.irq_int > 0) { 168 printf(" irq %d", crs.irq_int); 169 170 sc->sc_ih = acpi_intr_establish(crs.irq_int, crs.irq_flags, 171 IPL_BIO, dwiic_intr, sc, sc->sc_dev.dv_xname); 172 if (sc->sc_ih == NULL) 173 printf(", can't establish interrupt"); 174 } 175 176 printf("\n"); 177 178 rw_init(&sc->sc_i2c_lock, "iiclk"); 179 180 /* setup and attach iic bus */ 181 sc->sc_i2c_tag.ic_cookie = sc; 182 sc->sc_i2c_tag.ic_acquire_bus = dwiic_i2c_acquire_bus; 183 sc->sc_i2c_tag.ic_release_bus = dwiic_i2c_release_bus; 184 sc->sc_i2c_tag.ic_exec = dwiic_i2c_exec; 185 sc->sc_i2c_tag.ic_intr_establish = dwiic_i2c_intr_establish; 186 sc->sc_i2c_tag.ic_intr_string = dwiic_i2c_intr_string; 187 188 bzero(&sc->sc_iba, sizeof(sc->sc_iba)); 189 sc->sc_iba.iba_name = "iic"; 190 sc->sc_iba.iba_tag = &sc->sc_i2c_tag; 191 sc->sc_iba.iba_bus_scan = dwiic_acpi_bus_scan; 192 sc->sc_iba.iba_bus_scan_arg = sc; 193 194 config_found((struct device *)sc, &sc->sc_iba, iicbus_print); 195 196 #ifndef SMALL_KERNEL 197 sc->sc_devnode->i2c = &sc->sc_i2c_tag; 198 acpi_register_gsb(sc->sc_acpi, sc->sc_devnode); 199 #endif 200 201 return; 202 } 203 204 int 205 dwiic_acpi_parse_crs(int crsidx, union acpi_resource *crs, void *arg) 206 { 207 struct dwiic_crs *sc_crs = arg; 208 struct aml_node *node; 209 uint16_t pin; 210 211 switch (AML_CRSTYPE(crs)) { 212 case SR_IRQ: 213 sc_crs->irq_int = ffs(letoh16(crs->sr_irq.irq_mask)) - 1; 214 sc_crs->irq_flags = crs->sr_irq.irq_flags; 215 break; 216 217 case LR_EXTIRQ: 218 sc_crs->irq_int = letoh32(crs->lr_extirq.irq[0]); 219 sc_crs->irq_flags = crs->lr_extirq.flags; 220 break; 221 222 case LR_GPIO: 223 node = aml_searchname(sc_crs->devnode, 224 (char *)&crs->pad[crs->lr_gpio.res_off]); 225 pin = *(uint16_t *)&crs->pad[crs->lr_gpio.pin_off]; 226 if (crs->lr_gpio.type == LR_GPIO_INT) { 227 sc_crs->gpio_int_node = node; 228 sc_crs->gpio_int_pin = pin; 229 sc_crs->gpio_int_flags = crs->lr_gpio.tflags; 230 } 231 break; 232 233 case LR_MEM32: 234 sc_crs->addr_min = letoh32(crs->lr_m32._min); 235 sc_crs->addr_len = letoh32(crs->lr_m32._len); 236 break; 237 238 case LR_MEM32FIXED: 239 sc_crs->addr_bas = letoh32(crs->lr_m32fixed._bas); 240 sc_crs->addr_len = letoh32(crs->lr_m32fixed._len); 241 break; 242 243 case LR_SERBUS: 244 if (crs->lr_serbus.type == LR_SERBUS_I2C) 245 sc_crs->i2c_addr = letoh16(crs->lr_i2cbus._adr); 246 break; 247 248 default: 249 DPRINTF(("%s: unknown resource type %d\n", __func__, 250 AML_CRSTYPE(crs))); 251 } 252 253 return 0; 254 } 255 256 void 257 dwiic_acpi_get_params(struct dwiic_softc *sc, char *method, uint16_t *hcnt, 258 uint16_t *lcnt, uint32_t *sda_hold_time) 259 { 260 struct aml_value res; 261 262 if (!aml_searchname(sc->sc_devnode, method)) 263 return; 264 265 if (aml_evalname(sc->sc_acpi, sc->sc_devnode, method, 0, NULL, &res)) { 266 printf(": eval of %s at %s failed", method, 267 aml_nodename(sc->sc_devnode)); 268 return; 269 } 270 271 if (res.type != AML_OBJTYPE_PACKAGE) { 272 printf(": %s is not a package (%d)", method, res.type); 273 aml_freevalue(&res); 274 return; 275 } 276 277 if (res.length <= 2) { 278 printf(": %s returned package of len %d", method, res.length); 279 aml_freevalue(&res); 280 return; 281 } 282 283 *hcnt = aml_val2int(res.v_package[0]); 284 *lcnt = aml_val2int(res.v_package[1]); 285 if (sda_hold_time) 286 *sda_hold_time = aml_val2int(res.v_package[2]); 287 aml_freevalue(&res); 288 } 289 290 void 291 dwiic_acpi_bus_scan(struct device *iic, struct i2cbus_attach_args *iba, 292 void *aux) 293 { 294 struct dwiic_softc *sc = (struct dwiic_softc *)aux; 295 296 sc->sc_iic = iic; 297 aml_find_node(sc->sc_devnode, "_HID", dwiic_acpi_found_hid, sc); 298 } 299 300 void * 301 dwiic_i2c_intr_establish(void *cookie, void *ih, int level, 302 int (*func)(void *), void *arg, const char *name) 303 { 304 struct dwiic_crs *crs = ih; 305 306 if (crs->gpio_int_node && crs->gpio_int_node->gpio) { 307 struct acpi_gpio *gpio = crs->gpio_int_node->gpio; 308 gpio->intr_establish(gpio->cookie, crs->gpio_int_pin, 309 crs->gpio_int_flags, func, arg); 310 return ih; 311 } 312 313 return acpi_intr_establish(crs->irq_int, crs->irq_flags, 314 level, func, arg, name); 315 } 316 317 const char * 318 dwiic_i2c_intr_string(void *cookie, void *ih) 319 { 320 struct dwiic_crs *crs = ih; 321 static char irqstr[64]; 322 323 if (crs->gpio_int_node && crs->gpio_int_node->gpio) 324 snprintf(irqstr, sizeof(irqstr), "gpio %d", crs->gpio_int_pin); 325 else 326 snprintf(irqstr, sizeof(irqstr), "irq %d", crs->irq_int); 327 328 return irqstr; 329 } 330 331 int 332 dwiic_matchhids(const char *hid, const char *hids[]) 333 { 334 int i; 335 336 for (i = 0; hids[i]; i++) 337 if (!strcmp(hid, hids[i])) 338 return (1); 339 340 return (0); 341 } 342 343 int 344 dwiic_acpi_found_hid(struct aml_node *node, void *arg) 345 { 346 struct dwiic_softc *sc = (struct dwiic_softc *)arg; 347 struct dwiic_crs crs; 348 struct aml_value res; 349 int64_t sta; 350 char cdev[16], dev[16]; 351 struct i2c_attach_args ia; 352 353 /* Skip our own _HID. */ 354 if (node->parent == sc->sc_devnode) 355 return 0; 356 357 if (acpi_parsehid(node, arg, cdev, dev, 16) != 0) 358 return 0; 359 360 if (aml_evalinteger(acpi_softc, node->parent, "_STA", 0, NULL, &sta)) 361 sta = STA_PRESENT | STA_ENABLED | STA_DEV_OK | 0x1000; 362 363 if ((sta & STA_PRESENT) == 0) 364 return 0; 365 366 DPRINTF(("%s: found HID %s at %s\n", sc->sc_dev.dv_xname, dev, 367 aml_nodename(node))); 368 369 if (aml_evalname(acpi_softc, node->parent, "_CRS", 0, NULL, &res)) { 370 printf("%s: no _CRS method at %s\n", sc->sc_dev.dv_xname, 371 aml_nodename(node->parent)); 372 return (0); 373 } 374 if (res.type != AML_OBJTYPE_BUFFER || res.length < 5) { 375 printf("%s: invalid _CRS object (type %d len %d)\n", 376 sc->sc_dev.dv_xname, res.type, res.length); 377 aml_freevalue(&res); 378 return (0); 379 } 380 memset(&crs, 0, sizeof(crs)); 381 crs.devnode = sc->sc_devnode; 382 aml_parse_resource(&res, dwiic_acpi_parse_crs, &crs); 383 aml_freevalue(&res); 384 385 acpi_attach_deps(acpi_softc, node->parent); 386 387 if (dwiic_matchhids(cdev, ihidev_hids)) 388 return dwiic_acpi_found_ihidev(sc, node, dev, crs); 389 else if (dwiic_matchhids(dev, iatp_hids)) 390 return dwiic_acpi_found_iatp(sc, node, dev, crs); 391 392 memset(&ia, 0, sizeof(ia)); 393 ia.ia_tag = sc->sc_iba.iba_tag; 394 ia.ia_name = dev; 395 ia.ia_addr = crs.i2c_addr; 396 ia.ia_cookie = node->parent; 397 398 if (crs.irq_int != 0 || crs.gpio_int_node != NULL) 399 ia.ia_intr = &crs; 400 401 config_found(sc->sc_iic, &ia, dwiic_i2c_print); 402 node->parent->attached = 1; 403 404 return 0; 405 } 406 407 int 408 dwiic_acpi_found_ihidev(struct dwiic_softc *sc, struct aml_node *node, 409 char *dev, struct dwiic_crs crs) 410 { 411 struct i2c_attach_args ia; 412 struct aml_value cmd[4], res; 413 414 /* 3cdff6f7-4267-4555-ad05-b30a3d8938de */ 415 static uint8_t i2c_hid_guid[] = { 416 0xF7, 0xF6, 0xDF, 0x3C, 0x67, 0x42, 0x55, 0x45, 417 0xAD, 0x05, 0xB3, 0x0A, 0x3D, 0x89, 0x38, 0xDE, 418 }; 419 420 if (!aml_searchname(node->parent, "_DSM")) { 421 printf("%s: couldn't find _DSM at %s\n", sc->sc_dev.dv_xname, 422 aml_nodename(node->parent)); 423 return 0; 424 } 425 426 bzero(&cmd, sizeof(cmd)); 427 cmd[0].type = AML_OBJTYPE_BUFFER; 428 cmd[0].v_buffer = (uint8_t *)&i2c_hid_guid; 429 cmd[0].length = sizeof(i2c_hid_guid); 430 /* rev */ 431 cmd[1].type = AML_OBJTYPE_INTEGER; 432 cmd[1].v_integer = 1; 433 cmd[1].length = 1; 434 /* func */ 435 cmd[2].type = AML_OBJTYPE_INTEGER; 436 cmd[2].v_integer = 1; /* HID */ 437 cmd[2].length = 1; 438 /* not used */ 439 cmd[3].type = AML_OBJTYPE_PACKAGE; 440 cmd[3].length = 0; 441 442 if (aml_evalname(acpi_softc, node->parent, "_DSM", 4, cmd, &res)) { 443 printf("%s: eval of _DSM at %s failed\n", 444 sc->sc_dev.dv_xname, aml_nodename(node->parent)); 445 return 0; 446 } 447 448 if (res.type != AML_OBJTYPE_INTEGER) { 449 printf("%s: bad _DSM result at %s: %d\n", 450 sc->sc_dev.dv_xname, aml_nodename(node->parent), res.type); 451 aml_freevalue(&res); 452 return 0; 453 } 454 455 memset(&ia, 0, sizeof(ia)); 456 ia.ia_tag = sc->sc_iba.iba_tag; 457 ia.ia_size = 1; 458 ia.ia_name = "ihidev"; 459 ia.ia_size = aml_val2int(&res); /* hid descriptor address */ 460 ia.ia_addr = crs.i2c_addr; 461 ia.ia_cookie = dev; 462 463 aml_freevalue(&res); 464 465 if (!sc->sc_poll_ihidev && 466 !(crs.irq_int == 0 && crs.gpio_int_node == NULL)) 467 ia.ia_intr = &crs; 468 469 if (config_found(sc->sc_iic, &ia, dwiic_i2c_print)) { 470 node->parent->attached = 1; 471 return 0; 472 } 473 474 return 1; 475 } 476 477 int 478 dwiic_acpi_found_iatp(struct dwiic_softc *sc, struct aml_node *node, char *dev, 479 struct dwiic_crs crs) 480 { 481 struct i2c_attach_args ia; 482 struct aml_value res; 483 484 if (aml_evalname(acpi_softc, node->parent, "GPIO", 0, NULL, &res)) 485 /* no gpio, assume this is the bootloader interface */ 486 return (0); 487 488 memset(&ia, 0, sizeof(ia)); 489 ia.ia_tag = sc->sc_iba.iba_tag; 490 ia.ia_size = 1; 491 ia.ia_name = "iatp"; 492 ia.ia_addr = crs.i2c_addr; 493 ia.ia_cookie = dev; 494 495 if (crs.irq_int <= 0 && crs.gpio_int_node == NULL) { 496 printf("%s: couldn't find irq for %s\n", sc->sc_dev.dv_xname, 497 aml_nodename(node->parent)); 498 return 0; 499 } 500 ia.ia_intr = &crs; 501 502 if (config_found(sc->sc_iic, &ia, dwiic_i2c_print)) { 503 node->parent->attached = 1; 504 return 0; 505 } 506 507 return 1; 508 } 509 510 void 511 dwiic_acpi_power(struct dwiic_softc *sc, int power) 512 { 513 char ps[] = "_PS0"; 514 515 if (!power) 516 ps[3] = '3'; 517 518 if (aml_searchname(sc->sc_devnode, ps)) { 519 if (aml_evalname(sc->sc_acpi, sc->sc_devnode, ps, 0, NULL, 520 NULL)) { 521 printf("%s: failed powering %s with %s\n", 522 sc->sc_dev.dv_xname, power ? "on" : "off", 523 ps); 524 return; 525 } 526 527 DELAY(10000); /* 10 milliseconds */ 528 } else 529 DPRINTF(("%s: no %s method\n", sc->sc_dev.dv_xname, ps)); 530 531 if (strcmp(sc->sc_hid, "INT3432") == 0 || 532 strcmp(sc->sc_hid, "INT3433") == 0) { 533 /* 534 * XXX: broadwell i2c devices may need this for initial power 535 * up and/or after s3 resume. 536 * 537 * linux does this write via LPSS -> clk_register_gate -> 538 * clk_gate_enable -> clk_gate_endisable -> clk_writel 539 */ 540 dwiic_write(sc, 0x800, 1); 541 } 542 } 543