1 /* $OpenBSD: qciic.c,v 1.5 2022/11/06 15:36:13 patrick Exp $ */ 2 /* 3 * Copyright (c) 2022 Mark Kettenis <kettenis@openbsd.org> 4 * 5 * Permission to use, copy, modify, and distribute this software for any 6 * purpose with or without fee is hereby granted, provided that the above 7 * copyright notice and this permission notice appear in all copies. 8 * 9 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 10 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 11 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 12 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 13 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 14 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 15 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 16 */ 17 18 #include <sys/param.h> 19 #include <sys/systm.h> 20 #include <sys/device.h> 21 22 #include <machine/intr.h> 23 #include <machine/bus.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 #define _I2C_PRIVATE 32 #include <dev/i2c/i2cvar.h> 33 34 /* Registers */ 35 #define GENI_I2C_TX_TRANS_LEN 0x26c 36 #define GENI_I2C_RX_TRANS_LEN 0x270 37 #define GENI_M_CMD0 0x600 38 #define GENI_M_CMD0_OPCODE_I2C_WRITE (0x1 << 27) 39 #define GENI_M_CMD0_OPCODE_I2C_READ (0x2 << 27) 40 #define GENI_M_CMD0_SLV_ADDR_SHIFT 9 41 #define GENI_M_CMD0_STOP_STRETCH (1 << 2) 42 #define GENI_M_IRQ_STATUS 0x610 43 #define GENI_M_IRQ_CLEAR 0x618 44 #define GENI_M_IRQ_CMD_DONE (1 << 0) 45 #define GENI_TX_FIFO 0x700 46 #define GENI_RX_FIFO 0x780 47 #define GENI_TX_FIFO_STATUS 0x800 48 #define GENI_RX_FIFO_STATUS 0x804 49 #define GENI_RX_FIFO_STATUS_WC(val) ((val) & 0xffffff) 50 51 #define HREAD4(sc, reg) \ 52 (bus_space_read_4((sc)->sc_iot, (sc)->sc_ioh, (reg))) 53 #define HWRITE4(sc, reg, val) \ 54 bus_space_write_4((sc)->sc_iot, (sc)->sc_ioh, (reg), (val)) 55 56 struct qciic_softc { 57 struct device sc_dev; 58 bus_space_tag_t sc_iot; 59 bus_space_handle_t sc_ioh; 60 61 struct acpi_softc *sc_acpi; 62 struct aml_node *sc_node; 63 struct device *sc_iic; 64 65 struct i2c_controller sc_ic; 66 }; 67 68 struct qciic_crs { 69 uint16_t i2c_addr; 70 struct aml_node *i2c_bus; 71 int irq_int; 72 uint8_t irq_flags; 73 struct aml_node *gpio_int_node; 74 uint16_t gpio_int_pin; 75 uint16_t gpio_int_flags; 76 struct aml_node *node; 77 }; 78 79 int qciic_acpi_match(struct device *, void *, void *); 80 void qciic_acpi_attach(struct device *, struct device *, void *); 81 82 const struct cfattach qciic_acpi_ca = { 83 sizeof (struct qciic_softc), qciic_acpi_match, qciic_acpi_attach 84 }; 85 86 struct cfdriver qciic_cd = { 87 NULL, "qciic", DV_DULL 88 }; 89 90 int qciic_acquire_bus(void *, int); 91 void qciic_release_bus(void *, int); 92 int qciic_exec(void *, i2c_op_t, i2c_addr_t, const void *, size_t, 93 void *, size_t, int); 94 95 void *qciic_i2c_intr_establish(void *, void *, int, int (*)(void *), 96 void *, const char *); 97 void qciic_i2c_intr_disestablish(void *, void *); 98 const char *qciic_i2c_intr_string(void *, void *); 99 100 int qciic_acpi_parse_crs(int, union acpi_resource *, void *); 101 void qciic_acpi_bus_scan(struct device *, struct i2cbus_attach_args *, 102 void *); 103 int qciic_acpi_found_hid(struct aml_node *, void *); 104 int qciic_acpi_found_ihidev(struct qciic_softc *, 105 struct aml_node *, char *, struct qciic_crs); 106 107 const char *qciic_hids[] = { 108 "QCOM0610", 109 "QCOM0811", 110 NULL 111 }; 112 113 int 114 qciic_acpi_match(struct device *parent, void *match, void *aux) 115 { 116 struct acpi_attach_args *aaa = aux; 117 struct cfdata *cf = match; 118 119 if (aaa->aaa_naddr < 1) 120 return 0; 121 return acpi_matchhids(aaa, qciic_hids, cf->cf_driver->cd_name); 122 } 123 124 void 125 qciic_acpi_attach(struct device *parent, struct device *self, void *aux) 126 { 127 struct qciic_softc *sc = (struct qciic_softc *)self; 128 struct acpi_attach_args *aaa = aux; 129 struct i2cbus_attach_args iba; 130 131 sc->sc_acpi = (struct acpi_softc *)parent; 132 sc->sc_node = aaa->aaa_node; 133 printf(" %s", aaa->aaa_node->name); 134 135 printf(" addr 0x%llx/0x%llx", aaa->aaa_addr[0], aaa->aaa_size[0]); 136 137 sc->sc_iot = aaa->aaa_bst[0]; 138 if (bus_space_map(sc->sc_iot, aaa->aaa_addr[0], aaa->aaa_size[0], 139 0, &sc->sc_ioh)) { 140 printf(": can't map registers\n"); 141 return; 142 } 143 144 printf("\n"); 145 146 sc->sc_ic.ic_cookie = sc; 147 sc->sc_ic.ic_acquire_bus = qciic_acquire_bus; 148 sc->sc_ic.ic_release_bus = qciic_release_bus; 149 sc->sc_ic.ic_exec = qciic_exec; 150 sc->sc_ic.ic_intr_establish = qciic_i2c_intr_establish; 151 sc->sc_ic.ic_intr_disestablish = qciic_i2c_intr_disestablish; 152 sc->sc_ic.ic_intr_string = qciic_i2c_intr_string; 153 154 #ifndef SMALL_KERNEL 155 /* 156 * XXX Registering the I2C9 node with ACPI leads to AML 157 * executing I2C transaction that fail and spin with the 158 * kernel lock held until they fail. 159 */ 160 if (strcmp(aaa->aaa_dev, "QCOM0610") != 0) { 161 sc->sc_node->i2c = &sc->sc_ic; 162 acpi_register_gsb(sc->sc_acpi, sc->sc_node); 163 } 164 #endif 165 166 memset(&iba, 0, sizeof(iba)); 167 iba.iba_name = "iic"; 168 iba.iba_tag = &sc->sc_ic; 169 iba.iba_bus_scan = qciic_acpi_bus_scan; 170 iba.iba_bus_scan_arg = sc; 171 config_found(&sc->sc_dev, &iba, iicbus_print); 172 } 173 174 int 175 qciic_acquire_bus(void *cookie, int flags) 176 { 177 return 0; 178 } 179 180 void 181 qciic_release_bus(void *cookie, int flags) 182 { 183 } 184 185 int 186 qciic_wait(struct qciic_softc *sc, uint32_t bits) 187 { 188 uint32_t stat; 189 int timo; 190 191 for (timo = 50000; timo > 0; timo--) { 192 stat = HREAD4(sc, GENI_M_IRQ_STATUS); 193 if (stat & bits) 194 break; 195 delay(10); 196 } 197 if (timo == 0) 198 return ETIMEDOUT; 199 200 return 0; 201 } 202 203 int 204 qciic_read(struct qciic_softc *sc, uint8_t *buf, size_t len) 205 { 206 uint32_t stat, word; 207 int timo, i; 208 209 word = 0; 210 for (i = 0; i < len; i++) { 211 if ((i % 4) == 0) { 212 for (timo = 50000; timo > 0; timo--) { 213 stat = HREAD4(sc, GENI_RX_FIFO_STATUS); 214 if (GENI_RX_FIFO_STATUS_WC(stat) > 0) 215 break; 216 delay(10); 217 } 218 if (timo == 0) 219 return ETIMEDOUT; 220 word = HREAD4(sc, GENI_RX_FIFO); 221 } 222 buf[i] = word >> ((i % 4) * 8); 223 } 224 225 return 0; 226 } 227 228 int 229 qciic_write(struct qciic_softc *sc, const uint8_t *buf, size_t len) 230 { 231 uint32_t stat, word; 232 int timo, i; 233 234 word = 0; 235 for (i = 0; i < len; i++) { 236 word |= buf[i] << ((i % 4) * 8); 237 if ((i % 4) == 3 || i == (len - 1)) { 238 for (timo = 50000; timo > 0; timo--) { 239 stat = HREAD4(sc, GENI_TX_FIFO_STATUS); 240 if (stat < 16) 241 break; 242 delay(10); 243 } 244 if (timo == 0) 245 return ETIMEDOUT; 246 HWRITE4(sc, GENI_TX_FIFO, word); 247 word = 0; 248 } 249 } 250 251 return 0; 252 } 253 254 int 255 qciic_exec(void *cookie, i2c_op_t op, i2c_addr_t addr, const void *cmd, 256 size_t cmdlen, void *buf, size_t buflen, int flags) 257 { 258 struct qciic_softc *sc = cookie; 259 uint32_t m_cmd, m_param, stat; 260 int error; 261 262 m_param = addr << GENI_M_CMD0_SLV_ADDR_SHIFT; 263 m_param |= GENI_M_CMD0_STOP_STRETCH; 264 265 if (buflen == 0 && I2C_OP_STOP_P(op)) 266 m_param &= ~GENI_M_CMD0_STOP_STRETCH; 267 268 if (cmdlen > 0) { 269 stat = HREAD4(sc, GENI_M_IRQ_STATUS); 270 HWRITE4(sc, GENI_M_IRQ_CLEAR, stat); 271 HWRITE4(sc, GENI_I2C_TX_TRANS_LEN, cmdlen); 272 m_cmd = GENI_M_CMD0_OPCODE_I2C_WRITE | m_param; 273 HWRITE4(sc, GENI_M_CMD0, m_cmd); 274 275 error = qciic_write(sc, cmd, cmdlen); 276 if (error) 277 return error; 278 279 error = qciic_wait(sc, GENI_M_IRQ_CMD_DONE); 280 if (error) 281 return error; 282 } 283 284 if (buflen == 0) 285 return 0; 286 287 if (I2C_OP_STOP_P(op)) 288 m_param &= ~GENI_M_CMD0_STOP_STRETCH; 289 290 if (I2C_OP_READ_P(op)) { 291 stat = HREAD4(sc, GENI_M_IRQ_STATUS); 292 HWRITE4(sc, GENI_M_IRQ_CLEAR, stat); 293 HWRITE4(sc, GENI_I2C_RX_TRANS_LEN, buflen); 294 m_cmd = GENI_M_CMD0_OPCODE_I2C_READ | m_param; 295 HWRITE4(sc, GENI_M_CMD0, m_cmd); 296 297 error = qciic_read(sc, buf, buflen); 298 if (error) 299 return error; 300 301 error = qciic_wait(sc, GENI_M_IRQ_CMD_DONE); 302 if (error) 303 return error; 304 } else { 305 stat = HREAD4(sc, GENI_M_IRQ_STATUS); 306 HWRITE4(sc, GENI_M_IRQ_CLEAR, stat); 307 HWRITE4(sc, GENI_I2C_TX_TRANS_LEN, buflen); 308 m_cmd = GENI_M_CMD0_OPCODE_I2C_WRITE | m_param; 309 HWRITE4(sc, GENI_M_CMD0, m_cmd); 310 311 error = qciic_write(sc, buf, buflen); 312 if (error) 313 return error; 314 315 error = qciic_wait(sc, GENI_M_IRQ_CMD_DONE); 316 if (error) 317 return error; 318 } 319 320 return 0; 321 } 322 323 void * 324 qciic_i2c_intr_establish(void *cookie, void *ih, int level, 325 int (*func)(void *), void *arg, const char *name) 326 { 327 struct qciic_crs *crs = ih; 328 329 if (crs->gpio_int_node) { 330 if (!crs->gpio_int_node->gpio) 331 /* found ACPI device but no driver for it */ 332 return NULL; 333 334 struct acpi_gpio *gpio = crs->gpio_int_node->gpio; 335 gpio->intr_establish(gpio->cookie, crs->gpio_int_pin, 336 crs->gpio_int_flags, func, arg); 337 return ih; 338 } 339 340 return acpi_intr_establish(crs->irq_int, crs->irq_flags, 341 level, func, arg, name); 342 } 343 344 void 345 qciic_i2c_intr_disestablish(void *cookie, void *ih) 346 { 347 /* XXX GPIO interrupts */ 348 acpi_intr_disestablish(ih); 349 } 350 351 const char * 352 qciic_i2c_intr_string(void *cookie, void *ih) 353 { 354 struct qciic_crs *crs = ih; 355 static char irqstr[64]; 356 357 if (crs->gpio_int_node) { 358 if (crs->gpio_int_node->gpio) 359 snprintf(irqstr, sizeof(irqstr), "gpio %d", 360 crs->gpio_int_pin); 361 } else 362 snprintf(irqstr, sizeof(irqstr), "irq %d", crs->irq_int); 363 364 return irqstr; 365 } 366 367 int 368 qciic_acpi_parse_crs(int crsidx, union acpi_resource *crs, void *arg) 369 { 370 struct qciic_crs *sc_crs = arg; 371 struct aml_node *node; 372 uint16_t pin; 373 374 switch (AML_CRSTYPE(crs)) { 375 case LR_SERBUS: 376 if (crs->lr_serbus.type == LR_SERBUS_I2C) { 377 sc_crs->i2c_addr = crs->lr_i2cbus._adr; 378 sc_crs->i2c_bus = aml_searchname(sc_crs->node, 379 &crs->lr_i2cbus.vdata[crs->lr_i2cbus.tlength - 6]); 380 } 381 break; 382 383 case LR_GPIO: 384 node = aml_searchname(sc_crs->node, 385 (char *)&crs->pad[crs->lr_gpio.res_off]); 386 pin = *(uint16_t *)&crs->pad[crs->lr_gpio.pin_off]; 387 if (crs->lr_gpio.type == LR_GPIO_INT) { 388 sc_crs->gpio_int_node = node; 389 sc_crs->gpio_int_pin = pin; 390 sc_crs->gpio_int_flags = crs->lr_gpio.tflags; 391 } 392 break; 393 } 394 395 return 0; 396 } 397 398 void 399 qciic_acpi_bus_scan(struct device *iic, struct i2cbus_attach_args *iba, 400 void *aux) 401 { 402 struct qciic_softc *sc = aux; 403 404 sc->sc_iic = iic; 405 aml_find_node(acpi_softc->sc_root, "_HID", qciic_acpi_found_hid, sc); 406 } 407 408 int 409 qciic_acpi_found_hid(struct aml_node *node, void *arg) 410 { 411 struct qciic_softc *sc = arg; 412 struct qciic_crs crs; 413 struct aml_value res; 414 int64_t sta; 415 char cdev[16], dev[16]; 416 struct i2c_attach_args ia; 417 418 /* Skip our own _HID. */ 419 if (node->parent == sc->sc_node) 420 return 0; 421 422 if (acpi_parsehid(node, arg, cdev, dev, 16) != 0) 423 return 0; 424 425 sta = acpi_getsta(acpi_softc, node->parent); 426 if ((sta & STA_PRESENT) == 0) 427 return 0; 428 429 if (aml_evalname(acpi_softc, node->parent, "_CRS", 0, NULL, &res)) 430 return 0; 431 432 if (res.type != AML_OBJTYPE_BUFFER || res.length < 5) { 433 aml_freevalue(&res); 434 return 0; 435 } 436 memset(&crs, 0, sizeof(crs)); 437 crs.node = node->parent; 438 aml_parse_resource(&res, qciic_acpi_parse_crs, &crs); 439 aml_freevalue(&res); 440 441 /* Skip if not using this bus. */ 442 if (crs.i2c_bus != sc->sc_node) 443 return 0; 444 445 acpi_attach_deps(acpi_softc, node->parent); 446 447 if (strcmp(dev, "PNP0C50") == 0 || strcmp(cdev, "PNP0C50") == 0) 448 return qciic_acpi_found_ihidev(sc, node, dev, crs); 449 450 memset(&ia, 0, sizeof(ia)); 451 ia.ia_tag = &sc->sc_ic; 452 ia.ia_name = dev; 453 ia.ia_addr = crs.i2c_addr; 454 ia.ia_cookie = node->parent; 455 456 config_found(sc->sc_iic, &ia, iic_print); 457 node->parent->attached = 1; 458 459 return 0; 460 } 461 462 int 463 qciic_acpi_found_ihidev(struct qciic_softc *sc, struct aml_node *node, 464 char *dev, struct qciic_crs crs) 465 { 466 struct i2c_attach_args ia; 467 struct aml_value cmd[4], res; 468 469 /* 3cdff6f7-4267-4555-ad05-b30a3d8938de */ 470 static uint8_t i2c_hid_guid[] = { 471 0xF7, 0xF6, 0xDF, 0x3C, 0x67, 0x42, 0x55, 0x45, 472 0xAD, 0x05, 0xB3, 0x0A, 0x3D, 0x89, 0x38, 0xDE, 473 }; 474 475 if (!aml_searchname(node->parent, "_DSM")) { 476 printf("%s: couldn't find _DSM at %s\n", sc->sc_dev.dv_xname, 477 aml_nodename(node->parent)); 478 return 0; 479 } 480 481 memset(&cmd, 0, sizeof(cmd)); 482 cmd[0].type = AML_OBJTYPE_BUFFER; 483 cmd[0].v_buffer = (uint8_t *)&i2c_hid_guid; 484 cmd[0].length = sizeof(i2c_hid_guid); 485 /* rev */ 486 cmd[1].type = AML_OBJTYPE_INTEGER; 487 cmd[1].v_integer = 1; 488 cmd[1].length = 1; 489 /* func */ 490 cmd[2].type = AML_OBJTYPE_INTEGER; 491 cmd[2].v_integer = 1; /* HID */ 492 cmd[2].length = 1; 493 /* not used */ 494 cmd[3].type = AML_OBJTYPE_PACKAGE; 495 cmd[3].length = 0; 496 497 if (aml_evalname(acpi_softc, node->parent, "_DSM", 4, cmd, &res)) { 498 printf("%s: eval of _DSM at %s failed\n", 499 sc->sc_dev.dv_xname, aml_nodename(node->parent)); 500 return 0; 501 } 502 503 if (res.type != AML_OBJTYPE_INTEGER) { 504 printf("%s: bad _DSM result at %s: %d\n", 505 sc->sc_dev.dv_xname, aml_nodename(node->parent), res.type); 506 aml_freevalue(&res); 507 return 0; 508 } 509 510 memset(&ia, 0, sizeof(ia)); 511 ia.ia_tag = &sc->sc_ic; 512 ia.ia_name = "ihidev"; 513 ia.ia_size = aml_val2int(&res); /* hid descriptor address */ 514 ia.ia_addr = crs.i2c_addr; 515 ia.ia_cookie = dev; 516 517 aml_freevalue(&res); 518 519 if (!(crs.irq_int == 0 && crs.gpio_int_node == NULL)) 520 ia.ia_intr = &crs; 521 522 if (config_found(sc->sc_iic, &ia, iic_print)) { 523 node->parent->attached = 1; 524 return 0; 525 } 526 527 return 1; 528 } 529