1*a38da08aSkettenis /* $OpenBSD: qciic.c,v 1.7 2024/10/02 21:21:32 kettenis Exp $ */ 2032c0695Skettenis /* 3032c0695Skettenis * Copyright (c) 2022 Mark Kettenis <kettenis@openbsd.org> 4032c0695Skettenis * 5032c0695Skettenis * Permission to use, copy, modify, and distribute this software for any 6032c0695Skettenis * purpose with or without fee is hereby granted, provided that the above 7032c0695Skettenis * copyright notice and this permission notice appear in all copies. 8032c0695Skettenis * 9032c0695Skettenis * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 10032c0695Skettenis * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 11032c0695Skettenis * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 12032c0695Skettenis * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 13032c0695Skettenis * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 14032c0695Skettenis * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 15032c0695Skettenis * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 16032c0695Skettenis */ 17032c0695Skettenis 18032c0695Skettenis #include <sys/param.h> 19032c0695Skettenis #include <sys/systm.h> 20032c0695Skettenis #include <sys/device.h> 21032c0695Skettenis 22032c0695Skettenis #include <machine/intr.h> 23032c0695Skettenis #include <machine/bus.h> 24032c0695Skettenis 25032c0695Skettenis #include <dev/acpi/acpireg.h> 26032c0695Skettenis #include <dev/acpi/acpivar.h> 27032c0695Skettenis #include <dev/acpi/acpidev.h> 28032c0695Skettenis #include <dev/acpi/amltypes.h> 29032c0695Skettenis #include <dev/acpi/dsdt.h> 30032c0695Skettenis 31032c0695Skettenis #define _I2C_PRIVATE 32032c0695Skettenis #include <dev/i2c/i2cvar.h> 33032c0695Skettenis 34032c0695Skettenis /* Registers */ 35032c0695Skettenis #define GENI_I2C_TX_TRANS_LEN 0x26c 36032c0695Skettenis #define GENI_I2C_RX_TRANS_LEN 0x270 37032c0695Skettenis #define GENI_M_CMD0 0x600 38032c0695Skettenis #define GENI_M_CMD0_OPCODE_I2C_WRITE (0x1 << 27) 39032c0695Skettenis #define GENI_M_CMD0_OPCODE_I2C_READ (0x2 << 27) 40032c0695Skettenis #define GENI_M_CMD0_SLV_ADDR_SHIFT 9 41032c0695Skettenis #define GENI_M_CMD0_STOP_STRETCH (1 << 2) 42032c0695Skettenis #define GENI_M_IRQ_STATUS 0x610 43032c0695Skettenis #define GENI_M_IRQ_CLEAR 0x618 44032c0695Skettenis #define GENI_M_IRQ_CMD_DONE (1 << 0) 45032c0695Skettenis #define GENI_TX_FIFO 0x700 46032c0695Skettenis #define GENI_RX_FIFO 0x780 47032c0695Skettenis #define GENI_TX_FIFO_STATUS 0x800 48032c0695Skettenis #define GENI_RX_FIFO_STATUS 0x804 49032c0695Skettenis #define GENI_RX_FIFO_STATUS_WC(val) ((val) & 0xffffff) 50032c0695Skettenis 51032c0695Skettenis #define HREAD4(sc, reg) \ 52032c0695Skettenis (bus_space_read_4((sc)->sc_iot, (sc)->sc_ioh, (reg))) 53032c0695Skettenis #define HWRITE4(sc, reg, val) \ 54032c0695Skettenis bus_space_write_4((sc)->sc_iot, (sc)->sc_ioh, (reg), (val)) 55032c0695Skettenis 56032c0695Skettenis struct qciic_softc { 57032c0695Skettenis struct device sc_dev; 58032c0695Skettenis bus_space_tag_t sc_iot; 59032c0695Skettenis bus_space_handle_t sc_ioh; 60032c0695Skettenis 61c0d15c1fSkettenis struct acpi_softc *sc_acpi; 62032c0695Skettenis struct aml_node *sc_node; 63032c0695Skettenis struct device *sc_iic; 64032c0695Skettenis 65032c0695Skettenis struct i2c_controller sc_ic; 66032c0695Skettenis }; 67032c0695Skettenis 68032c0695Skettenis struct qciic_crs { 69032c0695Skettenis uint16_t i2c_addr; 70032c0695Skettenis struct aml_node *i2c_bus; 71032c0695Skettenis int irq_int; 72032c0695Skettenis uint8_t irq_flags; 73032c0695Skettenis struct aml_node *gpio_int_node; 74032c0695Skettenis uint16_t gpio_int_pin; 75032c0695Skettenis uint16_t gpio_int_flags; 76032c0695Skettenis struct aml_node *node; 77*a38da08aSkettenis int skip; 78032c0695Skettenis }; 79032c0695Skettenis 8004270302Spatrick int qciic_acpi_match(struct device *, void *, void *); 8104270302Spatrick void qciic_acpi_attach(struct device *, struct device *, void *); 82032c0695Skettenis 8304270302Spatrick const struct cfattach qciic_acpi_ca = { 8404270302Spatrick sizeof (struct qciic_softc), qciic_acpi_match, qciic_acpi_attach 85032c0695Skettenis }; 86032c0695Skettenis 87032c0695Skettenis struct cfdriver qciic_cd = { 88032c0695Skettenis NULL, "qciic", DV_DULL 89032c0695Skettenis }; 90032c0695Skettenis 91032c0695Skettenis int qciic_acquire_bus(void *, int); 92032c0695Skettenis void qciic_release_bus(void *, int); 93032c0695Skettenis int qciic_exec(void *, i2c_op_t, i2c_addr_t, const void *, size_t, 94032c0695Skettenis void *, size_t, int); 95032c0695Skettenis 96032c0695Skettenis void *qciic_i2c_intr_establish(void *, void *, int, int (*)(void *), 97032c0695Skettenis void *, const char *); 98032c0695Skettenis void qciic_i2c_intr_disestablish(void *, void *); 99032c0695Skettenis const char *qciic_i2c_intr_string(void *, void *); 100032c0695Skettenis 101032c0695Skettenis int qciic_acpi_parse_crs(int, union acpi_resource *, void *); 102032c0695Skettenis void qciic_acpi_bus_scan(struct device *, struct i2cbus_attach_args *, 103032c0695Skettenis void *); 104032c0695Skettenis int qciic_acpi_found_hid(struct aml_node *, void *); 105032c0695Skettenis int qciic_acpi_found_ihidev(struct qciic_softc *, 106032c0695Skettenis struct aml_node *, char *, struct qciic_crs); 107032c0695Skettenis 108032c0695Skettenis const char *qciic_hids[] = { 109032c0695Skettenis "QCOM0610", 110cad3c6c7Skettenis "QCOM0811", 1113c157f7aSpatrick "QCOM0C10", 112032c0695Skettenis NULL 113032c0695Skettenis }; 114032c0695Skettenis 115032c0695Skettenis int 11604270302Spatrick qciic_acpi_match(struct device *parent, void *match, void *aux) 117032c0695Skettenis { 118032c0695Skettenis struct acpi_attach_args *aaa = aux; 119032c0695Skettenis struct cfdata *cf = match; 120032c0695Skettenis 121032c0695Skettenis if (aaa->aaa_naddr < 1) 122032c0695Skettenis return 0; 123032c0695Skettenis return acpi_matchhids(aaa, qciic_hids, cf->cf_driver->cd_name); 124032c0695Skettenis } 125032c0695Skettenis 126032c0695Skettenis void 12704270302Spatrick qciic_acpi_attach(struct device *parent, struct device *self, void *aux) 128032c0695Skettenis { 129032c0695Skettenis struct qciic_softc *sc = (struct qciic_softc *)self; 130032c0695Skettenis struct acpi_attach_args *aaa = aux; 131032c0695Skettenis struct i2cbus_attach_args iba; 132032c0695Skettenis 133c0d15c1fSkettenis sc->sc_acpi = (struct acpi_softc *)parent; 134032c0695Skettenis sc->sc_node = aaa->aaa_node; 135032c0695Skettenis printf(" %s", aaa->aaa_node->name); 136032c0695Skettenis 137032c0695Skettenis printf(" addr 0x%llx/0x%llx", aaa->aaa_addr[0], aaa->aaa_size[0]); 138032c0695Skettenis 139032c0695Skettenis sc->sc_iot = aaa->aaa_bst[0]; 140032c0695Skettenis if (bus_space_map(sc->sc_iot, aaa->aaa_addr[0], aaa->aaa_size[0], 141032c0695Skettenis 0, &sc->sc_ioh)) { 142032c0695Skettenis printf(": can't map registers\n"); 143032c0695Skettenis return; 144032c0695Skettenis } 145032c0695Skettenis 146032c0695Skettenis printf("\n"); 147032c0695Skettenis 148032c0695Skettenis sc->sc_ic.ic_cookie = sc; 149032c0695Skettenis sc->sc_ic.ic_acquire_bus = qciic_acquire_bus; 150032c0695Skettenis sc->sc_ic.ic_release_bus = qciic_release_bus; 151032c0695Skettenis sc->sc_ic.ic_exec = qciic_exec; 152032c0695Skettenis sc->sc_ic.ic_intr_establish = qciic_i2c_intr_establish; 153032c0695Skettenis sc->sc_ic.ic_intr_disestablish = qciic_i2c_intr_disestablish; 154032c0695Skettenis sc->sc_ic.ic_intr_string = qciic_i2c_intr_string; 155032c0695Skettenis 156c0d15c1fSkettenis #ifndef SMALL_KERNEL 157c0d15c1fSkettenis /* 158c0d15c1fSkettenis * XXX Registering the I2C9 node with ACPI leads to AML 159c0d15c1fSkettenis * executing I2C transaction that fail and spin with the 160c0d15c1fSkettenis * kernel lock held until they fail. 161c0d15c1fSkettenis */ 162c0d15c1fSkettenis if (strcmp(aaa->aaa_dev, "QCOM0610") != 0) { 163c0d15c1fSkettenis sc->sc_node->i2c = &sc->sc_ic; 164c0d15c1fSkettenis acpi_register_gsb(sc->sc_acpi, sc->sc_node); 165c0d15c1fSkettenis } 166c0d15c1fSkettenis #endif 167c0d15c1fSkettenis 168032c0695Skettenis memset(&iba, 0, sizeof(iba)); 169032c0695Skettenis iba.iba_name = "iic"; 170032c0695Skettenis iba.iba_tag = &sc->sc_ic; 171032c0695Skettenis iba.iba_bus_scan = qciic_acpi_bus_scan; 172032c0695Skettenis iba.iba_bus_scan_arg = sc; 173032c0695Skettenis config_found(&sc->sc_dev, &iba, iicbus_print); 174032c0695Skettenis } 175032c0695Skettenis 176032c0695Skettenis int 177032c0695Skettenis qciic_acquire_bus(void *cookie, int flags) 178032c0695Skettenis { 179032c0695Skettenis return 0; 180032c0695Skettenis } 181032c0695Skettenis 182032c0695Skettenis void 183032c0695Skettenis qciic_release_bus(void *cookie, int flags) 184032c0695Skettenis { 185032c0695Skettenis } 186032c0695Skettenis 187032c0695Skettenis int 188032c0695Skettenis qciic_wait(struct qciic_softc *sc, uint32_t bits) 189032c0695Skettenis { 190032c0695Skettenis uint32_t stat; 191032c0695Skettenis int timo; 192032c0695Skettenis 193032c0695Skettenis for (timo = 50000; timo > 0; timo--) { 194032c0695Skettenis stat = HREAD4(sc, GENI_M_IRQ_STATUS); 195032c0695Skettenis if (stat & bits) 196032c0695Skettenis break; 197032c0695Skettenis delay(10); 198032c0695Skettenis } 199032c0695Skettenis if (timo == 0) 200032c0695Skettenis return ETIMEDOUT; 201032c0695Skettenis 202032c0695Skettenis return 0; 203032c0695Skettenis } 204032c0695Skettenis 205032c0695Skettenis int 206032c0695Skettenis qciic_read(struct qciic_softc *sc, uint8_t *buf, size_t len) 207032c0695Skettenis { 208032c0695Skettenis uint32_t stat, word; 209032c0695Skettenis int timo, i; 210032c0695Skettenis 211032c0695Skettenis word = 0; 212032c0695Skettenis for (i = 0; i < len; i++) { 213032c0695Skettenis if ((i % 4) == 0) { 214032c0695Skettenis for (timo = 50000; timo > 0; timo--) { 215032c0695Skettenis stat = HREAD4(sc, GENI_RX_FIFO_STATUS); 216032c0695Skettenis if (GENI_RX_FIFO_STATUS_WC(stat) > 0) 217032c0695Skettenis break; 218032c0695Skettenis delay(10); 219032c0695Skettenis } 220032c0695Skettenis if (timo == 0) 221032c0695Skettenis return ETIMEDOUT; 222032c0695Skettenis word = HREAD4(sc, GENI_RX_FIFO); 223032c0695Skettenis } 224032c0695Skettenis buf[i] = word >> ((i % 4) * 8); 225032c0695Skettenis } 226032c0695Skettenis 227032c0695Skettenis return 0; 228032c0695Skettenis } 229032c0695Skettenis 230032c0695Skettenis int 231032c0695Skettenis qciic_write(struct qciic_softc *sc, const uint8_t *buf, size_t len) 232032c0695Skettenis { 233032c0695Skettenis uint32_t stat, word; 234032c0695Skettenis int timo, i; 235032c0695Skettenis 236032c0695Skettenis word = 0; 237032c0695Skettenis for (i = 0; i < len; i++) { 238032c0695Skettenis word |= buf[i] << ((i % 4) * 8); 239032c0695Skettenis if ((i % 4) == 3 || i == (len - 1)) { 240032c0695Skettenis for (timo = 50000; timo > 0; timo--) { 241032c0695Skettenis stat = HREAD4(sc, GENI_TX_FIFO_STATUS); 242032c0695Skettenis if (stat < 16) 243032c0695Skettenis break; 244032c0695Skettenis delay(10); 245032c0695Skettenis } 246032c0695Skettenis if (timo == 0) 247032c0695Skettenis return ETIMEDOUT; 248032c0695Skettenis HWRITE4(sc, GENI_TX_FIFO, word); 249032c0695Skettenis word = 0; 250032c0695Skettenis } 251032c0695Skettenis } 252032c0695Skettenis 253032c0695Skettenis return 0; 254032c0695Skettenis } 255032c0695Skettenis 256032c0695Skettenis int 257032c0695Skettenis qciic_exec(void *cookie, i2c_op_t op, i2c_addr_t addr, const void *cmd, 258032c0695Skettenis size_t cmdlen, void *buf, size_t buflen, int flags) 259032c0695Skettenis { 260032c0695Skettenis struct qciic_softc *sc = cookie; 261032c0695Skettenis uint32_t m_cmd, m_param, stat; 262032c0695Skettenis int error; 263032c0695Skettenis 264032c0695Skettenis m_param = addr << GENI_M_CMD0_SLV_ADDR_SHIFT; 265032c0695Skettenis m_param |= GENI_M_CMD0_STOP_STRETCH; 266032c0695Skettenis 267032c0695Skettenis if (buflen == 0 && I2C_OP_STOP_P(op)) 268032c0695Skettenis m_param &= ~GENI_M_CMD0_STOP_STRETCH; 269032c0695Skettenis 270032c0695Skettenis if (cmdlen > 0) { 271032c0695Skettenis stat = HREAD4(sc, GENI_M_IRQ_STATUS); 272032c0695Skettenis HWRITE4(sc, GENI_M_IRQ_CLEAR, stat); 273032c0695Skettenis HWRITE4(sc, GENI_I2C_TX_TRANS_LEN, cmdlen); 274032c0695Skettenis m_cmd = GENI_M_CMD0_OPCODE_I2C_WRITE | m_param; 275032c0695Skettenis HWRITE4(sc, GENI_M_CMD0, m_cmd); 276032c0695Skettenis 277032c0695Skettenis error = qciic_write(sc, cmd, cmdlen); 278032c0695Skettenis if (error) 279032c0695Skettenis return error; 280032c0695Skettenis 281032c0695Skettenis error = qciic_wait(sc, GENI_M_IRQ_CMD_DONE); 282032c0695Skettenis if (error) 283032c0695Skettenis return error; 284032c0695Skettenis } 285032c0695Skettenis 286032c0695Skettenis if (buflen == 0) 287032c0695Skettenis return 0; 288032c0695Skettenis 289032c0695Skettenis if (I2C_OP_STOP_P(op)) 290032c0695Skettenis m_param &= ~GENI_M_CMD0_STOP_STRETCH; 291032c0695Skettenis 292032c0695Skettenis if (I2C_OP_READ_P(op)) { 293032c0695Skettenis stat = HREAD4(sc, GENI_M_IRQ_STATUS); 294032c0695Skettenis HWRITE4(sc, GENI_M_IRQ_CLEAR, stat); 295032c0695Skettenis HWRITE4(sc, GENI_I2C_RX_TRANS_LEN, buflen); 296032c0695Skettenis m_cmd = GENI_M_CMD0_OPCODE_I2C_READ | m_param; 297032c0695Skettenis HWRITE4(sc, GENI_M_CMD0, m_cmd); 298032c0695Skettenis 299032c0695Skettenis error = qciic_read(sc, buf, buflen); 300032c0695Skettenis if (error) 301032c0695Skettenis return error; 302032c0695Skettenis 303032c0695Skettenis error = qciic_wait(sc, GENI_M_IRQ_CMD_DONE); 304032c0695Skettenis if (error) 305032c0695Skettenis return error; 306032c0695Skettenis } else { 307032c0695Skettenis stat = HREAD4(sc, GENI_M_IRQ_STATUS); 308032c0695Skettenis HWRITE4(sc, GENI_M_IRQ_CLEAR, stat); 309032c0695Skettenis HWRITE4(sc, GENI_I2C_TX_TRANS_LEN, buflen); 310032c0695Skettenis m_cmd = GENI_M_CMD0_OPCODE_I2C_WRITE | m_param; 311032c0695Skettenis HWRITE4(sc, GENI_M_CMD0, m_cmd); 312032c0695Skettenis 313032c0695Skettenis error = qciic_write(sc, buf, buflen); 314032c0695Skettenis if (error) 315032c0695Skettenis return error; 316032c0695Skettenis 317032c0695Skettenis error = qciic_wait(sc, GENI_M_IRQ_CMD_DONE); 318032c0695Skettenis if (error) 319032c0695Skettenis return error; 320032c0695Skettenis } 321032c0695Skettenis 322032c0695Skettenis return 0; 323032c0695Skettenis } 324032c0695Skettenis 325032c0695Skettenis void * 326032c0695Skettenis qciic_i2c_intr_establish(void *cookie, void *ih, int level, 327032c0695Skettenis int (*func)(void *), void *arg, const char *name) 328032c0695Skettenis { 329032c0695Skettenis struct qciic_crs *crs = ih; 330032c0695Skettenis 331032c0695Skettenis if (crs->gpio_int_node) { 332032c0695Skettenis if (!crs->gpio_int_node->gpio) 333032c0695Skettenis /* found ACPI device but no driver for it */ 334032c0695Skettenis return NULL; 335032c0695Skettenis 336032c0695Skettenis struct acpi_gpio *gpio = crs->gpio_int_node->gpio; 337032c0695Skettenis gpio->intr_establish(gpio->cookie, crs->gpio_int_pin, 338032c0695Skettenis crs->gpio_int_flags, func, arg); 339032c0695Skettenis return ih; 340032c0695Skettenis } 341032c0695Skettenis 342032c0695Skettenis return acpi_intr_establish(crs->irq_int, crs->irq_flags, 343032c0695Skettenis level, func, arg, name); 344032c0695Skettenis } 345032c0695Skettenis 346032c0695Skettenis void 347032c0695Skettenis qciic_i2c_intr_disestablish(void *cookie, void *ih) 348032c0695Skettenis { 349032c0695Skettenis /* XXX GPIO interrupts */ 350032c0695Skettenis acpi_intr_disestablish(ih); 351032c0695Skettenis } 352032c0695Skettenis 353032c0695Skettenis const char * 354032c0695Skettenis qciic_i2c_intr_string(void *cookie, void *ih) 355032c0695Skettenis { 356032c0695Skettenis struct qciic_crs *crs = ih; 357032c0695Skettenis static char irqstr[64]; 358032c0695Skettenis 359032c0695Skettenis if (crs->gpio_int_node) { 360032c0695Skettenis if (crs->gpio_int_node->gpio) 361032c0695Skettenis snprintf(irqstr, sizeof(irqstr), "gpio %d", 362032c0695Skettenis crs->gpio_int_pin); 363032c0695Skettenis } else 364032c0695Skettenis snprintf(irqstr, sizeof(irqstr), "irq %d", crs->irq_int); 365032c0695Skettenis 366032c0695Skettenis return irqstr; 367032c0695Skettenis } 368032c0695Skettenis 369032c0695Skettenis int 370032c0695Skettenis qciic_acpi_parse_crs(int crsidx, union acpi_resource *crs, void *arg) 371032c0695Skettenis { 372032c0695Skettenis struct qciic_crs *sc_crs = arg; 373032c0695Skettenis struct aml_node *node; 374032c0695Skettenis uint16_t pin; 375032c0695Skettenis 376032c0695Skettenis switch (AML_CRSTYPE(crs)) { 377*a38da08aSkettenis case LR_MEM32FIXED: 378*a38da08aSkettenis /* An MMIO address means this is not an I2C device. */ 379*a38da08aSkettenis sc_crs->skip = 1; 380*a38da08aSkettenis break; 381*a38da08aSkettenis 382032c0695Skettenis case LR_SERBUS: 383032c0695Skettenis if (crs->lr_serbus.type == LR_SERBUS_I2C) { 384032c0695Skettenis sc_crs->i2c_addr = crs->lr_i2cbus._adr; 385032c0695Skettenis sc_crs->i2c_bus = aml_searchname(sc_crs->node, 386032c0695Skettenis &crs->lr_i2cbus.vdata[crs->lr_i2cbus.tlength - 6]); 387032c0695Skettenis } 388032c0695Skettenis break; 389032c0695Skettenis 390032c0695Skettenis case LR_GPIO: 391032c0695Skettenis node = aml_searchname(sc_crs->node, 392032c0695Skettenis (char *)&crs->pad[crs->lr_gpio.res_off]); 393032c0695Skettenis pin = *(uint16_t *)&crs->pad[crs->lr_gpio.pin_off]; 394032c0695Skettenis if (crs->lr_gpio.type == LR_GPIO_INT) { 395032c0695Skettenis sc_crs->gpio_int_node = node; 396032c0695Skettenis sc_crs->gpio_int_pin = pin; 397032c0695Skettenis sc_crs->gpio_int_flags = crs->lr_gpio.tflags; 398032c0695Skettenis } 399032c0695Skettenis break; 400032c0695Skettenis } 401032c0695Skettenis 402032c0695Skettenis return 0; 403032c0695Skettenis } 404032c0695Skettenis 405032c0695Skettenis void 406032c0695Skettenis qciic_acpi_bus_scan(struct device *iic, struct i2cbus_attach_args *iba, 407032c0695Skettenis void *aux) 408032c0695Skettenis { 409032c0695Skettenis struct qciic_softc *sc = aux; 410032c0695Skettenis 411032c0695Skettenis sc->sc_iic = iic; 412032c0695Skettenis aml_find_node(acpi_softc->sc_root, "_HID", qciic_acpi_found_hid, sc); 413032c0695Skettenis } 414032c0695Skettenis 415032c0695Skettenis int 416032c0695Skettenis qciic_acpi_found_hid(struct aml_node *node, void *arg) 417032c0695Skettenis { 418032c0695Skettenis struct qciic_softc *sc = arg; 419032c0695Skettenis struct qciic_crs crs; 420032c0695Skettenis struct aml_value res; 421032c0695Skettenis int64_t sta; 422032c0695Skettenis char cdev[16], dev[16]; 423032c0695Skettenis struct i2c_attach_args ia; 424032c0695Skettenis 425032c0695Skettenis /* Skip our own _HID. */ 426032c0695Skettenis if (node->parent == sc->sc_node) 427032c0695Skettenis return 0; 428032c0695Skettenis 429032c0695Skettenis if (acpi_parsehid(node, arg, cdev, dev, 16) != 0) 430032c0695Skettenis return 0; 431032c0695Skettenis 432032c0695Skettenis sta = acpi_getsta(acpi_softc, node->parent); 433032c0695Skettenis if ((sta & STA_PRESENT) == 0) 434032c0695Skettenis return 0; 435032c0695Skettenis 436032c0695Skettenis if (aml_evalname(acpi_softc, node->parent, "_CRS", 0, NULL, &res)) 437032c0695Skettenis return 0; 438032c0695Skettenis 439032c0695Skettenis if (res.type != AML_OBJTYPE_BUFFER || res.length < 5) { 440032c0695Skettenis aml_freevalue(&res); 441032c0695Skettenis return 0; 442032c0695Skettenis } 443032c0695Skettenis memset(&crs, 0, sizeof(crs)); 444032c0695Skettenis crs.node = node->parent; 445032c0695Skettenis aml_parse_resource(&res, qciic_acpi_parse_crs, &crs); 446032c0695Skettenis aml_freevalue(&res); 447032c0695Skettenis 448032c0695Skettenis /* Skip if not using this bus. */ 449*a38da08aSkettenis if (crs.skip || crs.i2c_bus != sc->sc_node) 450032c0695Skettenis return 0; 451032c0695Skettenis 452032c0695Skettenis acpi_attach_deps(acpi_softc, node->parent); 453032c0695Skettenis 45435ecc9daSkettenis if (strcmp(dev, "PNP0C50") == 0 || strcmp(cdev, "PNP0C50") == 0) 455032c0695Skettenis return qciic_acpi_found_ihidev(sc, node, dev, crs); 456032c0695Skettenis 457032c0695Skettenis memset(&ia, 0, sizeof(ia)); 458032c0695Skettenis ia.ia_tag = &sc->sc_ic; 459032c0695Skettenis ia.ia_name = dev; 460032c0695Skettenis ia.ia_addr = crs.i2c_addr; 461032c0695Skettenis ia.ia_cookie = node->parent; 462032c0695Skettenis 463032c0695Skettenis config_found(sc->sc_iic, &ia, iic_print); 464032c0695Skettenis node->parent->attached = 1; 465032c0695Skettenis 466032c0695Skettenis return 0; 467032c0695Skettenis } 468032c0695Skettenis 469032c0695Skettenis int 470032c0695Skettenis qciic_acpi_found_ihidev(struct qciic_softc *sc, struct aml_node *node, 471032c0695Skettenis char *dev, struct qciic_crs crs) 472032c0695Skettenis { 473032c0695Skettenis struct i2c_attach_args ia; 474032c0695Skettenis struct aml_value cmd[4], res; 475032c0695Skettenis 476032c0695Skettenis /* 3cdff6f7-4267-4555-ad05-b30a3d8938de */ 477032c0695Skettenis static uint8_t i2c_hid_guid[] = { 478032c0695Skettenis 0xF7, 0xF6, 0xDF, 0x3C, 0x67, 0x42, 0x55, 0x45, 479032c0695Skettenis 0xAD, 0x05, 0xB3, 0x0A, 0x3D, 0x89, 0x38, 0xDE, 480032c0695Skettenis }; 481032c0695Skettenis 482032c0695Skettenis if (!aml_searchname(node->parent, "_DSM")) { 483032c0695Skettenis printf("%s: couldn't find _DSM at %s\n", sc->sc_dev.dv_xname, 484032c0695Skettenis aml_nodename(node->parent)); 485032c0695Skettenis return 0; 486032c0695Skettenis } 487032c0695Skettenis 488032c0695Skettenis memset(&cmd, 0, sizeof(cmd)); 489032c0695Skettenis cmd[0].type = AML_OBJTYPE_BUFFER; 490032c0695Skettenis cmd[0].v_buffer = (uint8_t *)&i2c_hid_guid; 491032c0695Skettenis cmd[0].length = sizeof(i2c_hid_guid); 492032c0695Skettenis /* rev */ 493032c0695Skettenis cmd[1].type = AML_OBJTYPE_INTEGER; 494032c0695Skettenis cmd[1].v_integer = 1; 495032c0695Skettenis cmd[1].length = 1; 496032c0695Skettenis /* func */ 497032c0695Skettenis cmd[2].type = AML_OBJTYPE_INTEGER; 498032c0695Skettenis cmd[2].v_integer = 1; /* HID */ 499032c0695Skettenis cmd[2].length = 1; 500032c0695Skettenis /* not used */ 501032c0695Skettenis cmd[3].type = AML_OBJTYPE_PACKAGE; 502032c0695Skettenis cmd[3].length = 0; 503032c0695Skettenis 504032c0695Skettenis if (aml_evalname(acpi_softc, node->parent, "_DSM", 4, cmd, &res)) { 505032c0695Skettenis printf("%s: eval of _DSM at %s failed\n", 506032c0695Skettenis sc->sc_dev.dv_xname, aml_nodename(node->parent)); 507032c0695Skettenis return 0; 508032c0695Skettenis } 509032c0695Skettenis 510032c0695Skettenis if (res.type != AML_OBJTYPE_INTEGER) { 511032c0695Skettenis printf("%s: bad _DSM result at %s: %d\n", 512032c0695Skettenis sc->sc_dev.dv_xname, aml_nodename(node->parent), res.type); 513032c0695Skettenis aml_freevalue(&res); 514032c0695Skettenis return 0; 515032c0695Skettenis } 516032c0695Skettenis 517032c0695Skettenis memset(&ia, 0, sizeof(ia)); 518032c0695Skettenis ia.ia_tag = &sc->sc_ic; 519032c0695Skettenis ia.ia_name = "ihidev"; 520032c0695Skettenis ia.ia_size = aml_val2int(&res); /* hid descriptor address */ 521032c0695Skettenis ia.ia_addr = crs.i2c_addr; 522032c0695Skettenis ia.ia_cookie = dev; 523032c0695Skettenis 524032c0695Skettenis aml_freevalue(&res); 525032c0695Skettenis 526032c0695Skettenis if (!(crs.irq_int == 0 && crs.gpio_int_node == NULL)) 527032c0695Skettenis ia.ia_intr = &crs; 528032c0695Skettenis 529032c0695Skettenis if (config_found(sc->sc_iic, &ia, iic_print)) { 530032c0695Skettenis node->parent->attached = 1; 531032c0695Skettenis return 0; 532032c0695Skettenis } 533032c0695Skettenis 534032c0695Skettenis return 1; 535032c0695Skettenis } 536