From: Mark Kettenis Subject: Re: qcgpio(4) X1E support based on ACPI tables To: Marcus Glocker Cc: tech@openbsd.org Date: Sun, 22 Dec 2024 18:21:45 +0100 > Date: Sun, 22 Dec 2024 10:51:35 +0100 > From: Marcus Glocker > > patrick@ found a NetBSD commit which figured out how to map the GPIO > pins based on the ACPI tables for X1E devices: > > https://github.com/NetBSD/src/commit/575554bd388d93cfff9174abadf2aab93fbfdf8e > > Currently we're only using hard coded mapping in qcgpio(4), which > might not do the correct mapping, or miss some mappings. > > Following a diff which tries to adapt the NetBSD implementation in > qcpgio(4) for X1E devices. > > Before I throw this diff in my attic, maybe some X1E users want to > regression test it, or see if it even fixes some GPIO mappings. > > On my Samsung Galaxy Book4 Edge it causes no regression (keyboard and > touch-pad still work). Unfortunately the touch-screen still doesn't > work. I guess there is another issue with that. I think this is useful to have. Tested this on my x13s (no change) and my vivobook (no change apart from debug output). ok kettenis@ --- dmesg.acpi.before Sun Dec 22 17:58:49 2024 +++ dmesg.acpi.after Sun Dec 22 18:16:37 2024 @@ -1,5 +1,5 @@ -OpenBSD 7.6-current (GENERIC.MP) #266: Fri Dec 20 22:58:05 MST 2024 - deraadt@arm64.openbsd.org:/usr/src/sys/arch/arm64/compile/GENERIC.MP +OpenBSD 7.6-current (GENERIC.MP) #1: Sun Dec 22 18:14:20 CET 2024 + kettenis@massenet.sibelius.xs4all.nl:/home/kettenis/src/acpi/sys/arch/arm64/compile/GENERIC.MP real mem = 16449925120 (15687MB) avail mem = 15806259200 (15074MB) random: good seed from bootblocks @@ -100,7 +100,131 @@ qciic0 at acpi0 I2C6 addr 0xb94000/0x4000 iic0 at qciic0 ### AML PARSE ERROR (0x3077d): Undefined name: OSYS error evaluating: \\_SB_.WMIT._STA -qcgpio0 at acpi0 GIO0 addr 0xf100000/0xf00000 irq 240 +qcgpio0 at acpi0 GIO0 addr 0xf100000/0xf00000 +qcgpio_acpi_attach: npdcmap=14 +qcgpio_get_irqs: irq index 0: irq 240 +qcgpio_get_irqs: irq index 1: irq 240 +qcgpio_get_irqs: irq index 2: irq 240 +qcgpio_get_irqs: irq index 3: irq 240 +qcgpio_get_irqs: irq index 4: irq 598 +qcgpio_get_irqs: irq index 5: irq 760 +qcgpio_get_irqs: irq index 6: irq 595 +qcgpio_get_irqs: irq index 7: irq 659 +qcgpio_get_irqs: irq index 8: irq 602 +qcgpio_get_irqs: irq index 9: irq 604 +qcgpio_get_irqs: irq index 10: irq 645 +qcgpio_get_irqs: irq index 11: irq 642 +qcgpio_get_irqs: irq index 12: irq 649 +qcgpio_get_irqs: irq index 13: irq 756 +qcgpio_fill_pdcmap: pdc index 0: probing irq 655, pin 38 +qcgpio_fill_pdcmap: pdc index 1: probing irq 654, pin 166 +qcgpio_fill_pdcmap: pdc index 2: probing irq 653, pin 221 +qcgpio_fill_pdcmap: pdc index 3: probing irq 652, pin 220 +qcgpio_fill_pdcmap: pdc index 4: probing irq 651, pin 217 +qcgpio_fill_pdcmap: pdc index 5: probing irq 650, pin 196 +qcgpio_fill_pdcmap: pdc index 6: probing irq 649, pin 157 +qcgpio_fill_pdcmap: pdc index 7: probing irq 648, pin 65 +qcgpio_fill_pdcmap: pdc index 8: probing irq 647, pin 156 +qcgpio_fill_pdcmap: pdc index 9: probing irq 646, pin 153 +qcgpio_fill_pdcmap: pdc index 10: probing irq 645, pin 151 +qcgpio_fill_pdcmap: pdc index 11: probing irq 644, pin 150 +qcgpio_fill_pdcmap: pdc index 12: probing irq 643, pin 181 +qcgpio_fill_pdcmap: pdc index 13: probing irq 642, pin 154 +qcgpio_fill_pdcmap: pdc index 14: probing irq 641, pin 172 +qcgpio_fill_pdcmap: pdc index 15: probing irq 605, pin 163 +qcgpio_fill_pdcmap: pdc index 16: probing irq 604, pin 148 +qcgpio_fill_pdcmap: pdc index 17: probing irq 603, pin 147 +qcgpio_fill_pdcmap: pdc index 18: probing irq 602, pin 145 +qcgpio_fill_pdcmap: pdc index 19: probing irq 601, pin 144 +qcgpio_fill_pdcmap: pdc index 20: probing irq 600, pin 141 +qcgpio_fill_pdcmap: pdc index 21: probing irq 599, pin 30 +qcgpio_fill_pdcmap: pdc index 22: probing irq 598, pin 71 +qcgpio_fill_pdcmap: pdc index 23: probing irq 597, pin 64 +qcgpio_fill_pdcmap: pdc index 24: probing irq 596, pin 53 +qcgpio_fill_pdcmap: pdc index 25: probing irq 595, pin 67 +qcgpio_fill_pdcmap: pdc index 26: probing irq 594, pin 59 +qcgpio_fill_pdcmap: pdc index 27: probing irq 593, pin 13 +qcgpio_fill_pdcmap: pdc index 28: probing irq 592, pin 11 +qcgpio_fill_pdcmap: pdc index 29: probing irq 591, pin 113 +qcgpio_fill_pdcmap: pdc index 30: probing irq 590, pin 134 +qcgpio_fill_pdcmap: pdc index 31: probing irq 589, pin 131 +qcgpio_fill_pdcmap: pdc index 32: probing irq 588, pin 55 +qcgpio_fill_pdcmap: pdc index 33: probing irq 587, pin 39 +qcgpio_fill_pdcmap: pdc index 34: probing irq 586, pin 51 +qcgpio_fill_pdcmap: pdc index 35: probing irq 585, pin 29 +qcgpio_fill_pdcmap: pdc index 36: probing irq 584, pin 28 +qcgpio_fill_pdcmap: pdc index 37: probing irq 583, pin 129 +qcgpio_fill_pdcmap: pdc index 38: probing irq 582, pin 125 +qcgpio_fill_pdcmap: pdc index 39: probing irq 581, pin 123 +qcgpio_fill_pdcmap: pdc index 40: probing irq 580, pin 121 +qcgpio_fill_pdcmap: pdc index 41: probing irq 579, pin 0 +qcgpio_fill_pdcmap: pdc index 42: probing irq 578, pin 3 +qcgpio_fill_pdcmap: pdc index 43: probing irq 577, pin 2 +qcgpio_fill_pdcmap: pdc index 44: probing irq 576, pin 19 +qcgpio_fill_pdcmap: pdc index 45: probing irq 575, pin 15 +qcgpio_fill_pdcmap: pdc index 46: probing irq 574, pin 7 +qcgpio_fill_pdcmap: pdc index 47: probing irq 850, pin 32 +qcgpio_fill_pdcmap: pdc index 48: probing irq 849, pin 27 +qcgpio_fill_pdcmap: pdc index 49: probing irq 848, pin 23 +qcgpio_fill_pdcmap: pdc index 50: probing irq 760, pin 66 +qcgpio_fill_pdcmap: pdc index 51: probing irq 759, pin 95 +qcgpio_fill_pdcmap: pdc index 52: probing irq 758, pin 94 +qcgpio_fill_pdcmap: pdc index 53: probing irq 757, pin 93 +qcgpio_fill_pdcmap: pdc index 54: probing irq 756, pin 92 +qcgpio_fill_pdcmap: pdc index 55: probing irq 755, pin 84 +qcgpio_fill_pdcmap: pdc index 56: probing irq 754, pin 230 +qcgpio_fill_pdcmap: pdc index 57: probing irq 753, pin 228 +qcgpio_fill_pdcmap: pdc index 58: probing irq 752, pin 208 +qcgpio_fill_pdcmap: pdc index 59: probing irq 751, pin 203 +qcgpio_fill_pdcmap: pdc index 60: probing irq 750, pin 225 +qcgpio_fill_pdcmap: pdc index 61: probing irq 749, pin 224 +qcgpio_fill_pdcmap: pdc index 62: probing irq 672, pin 34 +qcgpio_fill_pdcmap: pdc index 63: probing irq 671, pin 26 +qcgpio_fill_pdcmap: pdc index 64: probing irq 670, pin 81 +qcgpio_fill_pdcmap: pdc index 65: probing irq 668, pin 24 +qcgpio_fill_pdcmap: pdc index 66: probing irq 667, pin 80 +qcgpio_fill_pdcmap: pdc index 67: probing irq 666, pin 222 +qcgpio_fill_pdcmap: pdc index 68: probing irq 665, pin 6 +qcgpio_fill_pdcmap: pdc index 69: probing irq 664, pin 18 +qcgpio_fill_pdcmap: pdc index 70: probing irq 663, pin 214 +qcgpio_fill_pdcmap: pdc index 71: probing irq 662, pin 212 +qcgpio_fill_pdcmap: pdc index 72: probing irq 661, pin 219 +qcgpio_fill_pdcmap: pdc index 73: probing irq 660, pin 215 +qcgpio_fill_pdcmap: pdc index 74: probing irq 659, pin 193 +qcgpio_fill_pdcmap: pdc index 75: probing irq 658, pin 184 +qcgpio_fill_pdcmap: pdc index 76: probing irq 657, pin 33 +qcgpio_fill_pdcmap: pdc index 77: probing irq 656, pin 175 +qcgpio_fill_pdcmap: pdc index 78: probing irq 862, pin 91 +qcgpio_fill_pdcmap: pdc index 79: probing irq 861, pin 87 +qcgpio_fill_pdcmap: pdc index 80: probing irq 860, pin 85 +qcgpio_fill_pdcmap: pdc index 81: probing irq 859, pin 83 +qcgpio_fill_pdcmap: pdc index 82: probing irq 858, pin 79 +qcgpio_fill_pdcmap: pdc index 83: probing irq 857, pin 75 +qcgpio_fill_pdcmap: pdc index 84: probing irq 856, pin 68 +qcgpio_fill_pdcmap: pdc index 85: probing irq 855, pin 213 +qcgpio_fill_pdcmap: pdc index 86: probing irq 854, pin 47 +qcgpio_fill_pdcmap: pdc index 87: probing irq 853, pin 43 +qcgpio_fill_pdcmap: pdc index 88: probing irq 852, pin 36 +qcgpio_fill_pdcmap: pdc index 89: probing irq 851, pin 35 +qcgpio_fill_pdcmap: pdc index 90: probing irq 867, pin 232 +qcgpio_fill_pdcmap: pdc index 91: probing irq 864, pin 31 +qcgpio_fill_pdcmap: pdc index 92: probing irq 863, pin 21 +qcgpio_fill_pdcmap: irq index 0: irq=240, pin=-1 +qcgpio_fill_pdcmap: irq index 1: irq=240, pin=-1 +qcgpio_fill_pdcmap: irq index 2: irq=240, pin=-1 +qcgpio_fill_pdcmap: irq index 3: irq=240, pin=-1 +qcgpio_fill_pdcmap: irq index 4: irq=598, pin=71 +qcgpio_fill_pdcmap: irq index 5: irq=760, pin=66 +qcgpio_fill_pdcmap: irq index 6: irq=595, pin=67 +qcgpio_fill_pdcmap: irq index 7: irq=659, pin=193 +qcgpio_fill_pdcmap: irq index 8: irq=602, pin=145 +qcgpio_fill_pdcmap: irq index 9: irq=604, pin=148 +qcgpio_fill_pdcmap: irq index 10: irq=645, pin=151 +qcgpio_fill_pdcmap: irq index 11: irq=642, pin=154 +qcgpio_fill_pdcmap: irq index 12: irq=649, pin=157 +qcgpio_fill_pdcmap: irq index 13: irq=756, pin=92 +qcgpio_acpi_attach: npins=238 + irq 240 ihidev0 at iic0 addr 0x3a gpio 384, vendor 0xb05 product 0x4543, QTEC0001 ihidev0: 90 report ids hid at ihidev0 reportid 6 not configured > > > Index: sys/dev/acpi/qcgpio.c > =================================================================== > RCS file: /cvs/src/sys/dev/acpi/qcgpio.c,v > diff -u -p -u -p -r1.11 qcgpio.c > --- sys/dev/acpi/qcgpio.c 15 Jul 2024 15:33:54 -0000 1.11 > +++ sys/dev/acpi/qcgpio.c 15 Dec 2024 19:03:25 -0000 > @@ -25,6 +25,14 @@ > #include > #include > > +#define QCGPIO_DEBUG > +#ifdef QCGPIO_DEBUG > +int qcgpio_debug = 1; > +#define DPRINTF(l, x...) do { if ((l) <= qcgpio_debug) printf(x); } while (0) > +#else > +#define DPRINTF(l, x...) > +#endif > + > /* Registers. */ > #define TLMM_GPIO_IN_OUT(pin) (0x0004 + 0x1000 * (pin)) > #define TLMM_GPIO_IN_OUT_GPIO_IN (1 << 0) > @@ -62,6 +70,11 @@ struct qcgpio_intrhand { > void *ih_arg; > }; > > +struct qcgpio_pdcmap { > + int pm_pin; > + uint32_t pm_irq; > +}; > + > struct qcgpio_softc { > struct device sc_dev; > struct acpi_softc *sc_acpi; > @@ -73,10 +86,15 @@ struct qcgpio_softc { > void *sc_ih; > > uint32_t sc_npins; > - int (*sc_pin_map)(int, bus_size_t *); > + int (*sc_pin_map)(struct qcgpio_softc *, int, > + bus_size_t *); > struct qcgpio_intrhand *sc_pin_ih; > > struct acpi_gpio sc_gpio; > + > + struct qcgpio_pdcmap *sc_pdcmap; > + uint32_t sc_npdcmap; > + uint32_t sc_ipdcmap; > }; > > int qcgpio_acpi_match(struct device *, void *, void *); > @@ -97,9 +115,29 @@ const char *qcgpio_hids[] = { > NULL > }; > > -int qcgpio_sc7180_pin_map(int, bus_size_t *); > -int qcgpio_sc8280xp_pin_map(int, bus_size_t *); > -int qcgpio_x1e80100_pin_map(int, bus_size_t *); > +/* 98b9b2a4-1663-4a5f-82f2-c6c99a394726 */ > +static uint8_t qcgpio_gpio_dsm_uuid[] = { > + 0xa4, 0xb2, 0xb9, 0x98, 0x63, 0x16, 0x5f, 0x4a, > + 0x82, 0xf2, 0xc6, 0xc9, 0x9a, 0x39, 0x47, 0x26 > +}; > +#define QCGPIO_GPIO_DSM_REV 0 > +#define QCGPIO_GPIO_DSM_FUNC_NUM_PINS 2 > + > +/* 921b0fd4-567c-43a0-bb14-2648f7b2a18c */ > +static uint8_t qcgpio_pdc_dsm_uuid[] = { > + 0xd4, 0x0f, 0x1b, 0x92, 0x7c, 0x56, 0xa0, 0x43, > + 0xbb, 0x14, 0x26, 0x48, 0xf7, 0xb2, 0xa1, 0x8c > +}; > +#define QCGPIO_PDC_DSM_REV 0 > +#define QCGPIO_PDC_DSM_FUNC_CIPR 2 > + > +int qcgpio_get_nirq(int, union acpi_resource *, void *); > +int qcgpio_get_irqs(int, union acpi_resource *, void *); > +void qcgpio_fill_pdcmap(struct qcgpio_softc *); > +int qcgpio_get_pin_count(struct acpi_softc *, struct aml_node *); > +int qcgpio_sc7180_pin_map(struct qcgpio_softc *, int, bus_size_t *); > +int qcgpio_sc8280xp_pin_map(struct qcgpio_softc *, int, bus_size_t *); > +int qcgpio_x1e80100_pin_map(struct qcgpio_softc *, int, bus_size_t *); > > int qcgpio_read_pin(void *, int); > void qcgpio_write_pin(void *, int, int); > @@ -109,6 +147,137 @@ void qcgpio_intr_disable(void *, int); > int qcgpio_intr(void *); > > int > +qcgpio_get_nirq(int crsidx, union acpi_resource *crs, void *arg) > +{ > + struct qcgpio_softc *sc = arg; > + int typ; > + > + typ = AML_CRSTYPE(crs); > + > + switch (typ) { > + case LR_EXTIRQ: > + sc->sc_npdcmap++; > + break; > + } > + > + return 0; > +} > + > +int > +qcgpio_get_irqs(int crsidx, union acpi_resource *crs, void *arg) > +{ > + struct qcgpio_softc *sc = arg; > + int typ; > + > + typ = AML_CRSTYPE(crs); > + > + switch (typ) { > + case LR_EXTIRQ: > + sc->sc_pdcmap[sc->sc_ipdcmap].pm_irq = crs->lr_extirq.irq[0]; > + sc->sc_pdcmap[sc->sc_ipdcmap].pm_pin = -1; > + DPRINTF(1, "%s: irq index %d: irq %d\n", > + __func__, sc->sc_ipdcmap, > + sc->sc_pdcmap[sc->sc_ipdcmap].pm_irq); > + sc->sc_ipdcmap++; > + break; > + } > + > + return 0; > +} > + > +void > +qcgpio_fill_pdcmap(struct qcgpio_softc *sc) > +{ > + struct aml_value cmd[4], res, *ref; > + int i, j, pin; > + uint32_t irq; > + > + bzero(&cmd, sizeof(cmd)); > + cmd[0].type = AML_OBJTYPE_BUFFER; > + cmd[0].v_buffer = (uint8_t *)&qcgpio_pdc_dsm_uuid; > + cmd[0].length = sizeof(qcgpio_pdc_dsm_uuid); > + /* rev */ > + cmd[1].type = AML_OBJTYPE_INTEGER; > + cmd[1].v_integer = QCGPIO_PDC_DSM_REV; > + cmd[1].length = 1; > + /* func */ > + cmd[2].type = AML_OBJTYPE_INTEGER; > + cmd[2].v_integer = QCGPIO_PDC_DSM_FUNC_CIPR; > + cmd[2].length = 1; > + /* not used */ > + cmd[3].type = AML_OBJTYPE_PACKAGE; > + cmd[3].v_integer = 0; > + cmd[3].length = 0; > + > + if (aml_evalname(sc->sc_acpi, sc->sc_node, "_DSM", 4, cmd, &res)) { > + printf("%s: PDC _DSM failed\n", __func__); > + return; > + } > + > + for (i = 0; i < res.length; i++) { > + ref = res.v_package[i]; > + > + if (ref->type != AML_OBJTYPE_PACKAGE || > + ref->length < 3 || > + ref->v_package[0]->type != AML_OBJTYPE_INTEGER || > + ref->v_package[1]->type != AML_OBJTYPE_INTEGER || > + ref->v_package[2]->type != AML_OBJTYPE_INTEGER) { > + continue; > + } > + > + irq = ref->v_package[2]->v_integer; > + pin = ref->v_package[1]->v_integer; > + DPRINTF(1, "%s: pdc index %d: probing irq %d, pin %d\n", > + __func__, i, irq, pin); > + > + for (j = 0; j < sc->sc_npdcmap; j++) { > + if (sc->sc_pdcmap[j].pm_irq == irq) { > + sc->sc_pdcmap[j].pm_pin = pin; > + break; > + } > + } > + } > +#ifdef QCGPIO_DEBUG > + for (i = 0; i < sc->sc_npdcmap; i++) { > + printf("%s: irq index %d: irq=%d, pin=%d\n", > + __func__, i, sc->sc_pdcmap[i].pm_irq, > + sc->sc_pdcmap[i].pm_pin); > + } > +#endif > +} > + > +int > +qcgpio_get_pin_count(struct acpi_softc *sc, struct aml_node *node) > +{ > + struct aml_value cmd[4]; > + int64_t npins; > + > + bzero(&cmd, sizeof(cmd)); > + cmd[0].type = AML_OBJTYPE_BUFFER; > + cmd[0].v_buffer = (uint8_t *)&qcgpio_gpio_dsm_uuid; > + cmd[0].length = sizeof(qcgpio_gpio_dsm_uuid); > + /* rev */ > + cmd[1].type = AML_OBJTYPE_INTEGER; > + cmd[1].v_integer = QCGPIO_GPIO_DSM_REV; > + cmd[1].length = 1; > + /* func */ > + cmd[2].type = AML_OBJTYPE_INTEGER; > + cmd[2].v_integer = QCGPIO_GPIO_DSM_FUNC_NUM_PINS; > + cmd[2].length = 1; > + /* not used */ > + cmd[3].type = AML_OBJTYPE_PACKAGE; > + cmd[3].v_integer = 0; > + cmd[3].length = 0; > + > + if (aml_evalinteger(sc, node, "_DSM", 4, cmd, &npins)) { > + printf("%s: GPIO _DSM failed\n", __func__); > + return 0; > + } > + > + return (uint32_t)npins; > +} > + > +int > qcgpio_acpi_match(struct device *parent, void *match, void *aux) > { > struct acpi_attach_args *aaa = aux; > @@ -124,6 +293,7 @@ qcgpio_acpi_attach(struct device *parent > { > struct acpi_attach_args *aaa = aux; > struct qcgpio_softc *sc = (struct qcgpio_softc *)self; > + struct aml_value res; > > sc->sc_acpi = (struct acpi_softc *)parent; > sc->sc_node = aaa->aaa_node; > @@ -145,7 +315,25 @@ qcgpio_acpi_attach(struct device *parent > sc->sc_npins = 228; > sc->sc_pin_map = qcgpio_sc8280xp_pin_map; > } else if (strcmp(aaa->aaa_dev, "QCOM0C0C") == 0) { > - sc->sc_npins = 239; > + if (aml_evalname(sc->sc_acpi, sc->sc_node, "_CRS", 0, NULL, > + &res)) { > + printf("no _CRS method\n"); > + return; > + } > + if (res.type != AML_OBJTYPE_BUFFER || res.length < 5) { > + printf("invalid _CRS object\n"); > + aml_freevalue(&res); > + return; > + } > + aml_parse_resource(&res, qcgpio_get_nirq, sc); > + DPRINTF(1, "\n%s: npdcmap=%d\n", __func__, sc->sc_npdcmap); > + sc->sc_pdcmap = mallocarray(sc->sc_npdcmap, > + sizeof(*sc->sc_pdcmap), M_DEVBUF, M_WAITOK | M_ZERO); > + aml_parse_resource(&res, qcgpio_get_irqs, sc); > + aml_freevalue(&res); > + qcgpio_fill_pdcmap(sc); > + sc->sc_npins = qcgpio_get_pin_count(sc->sc_acpi, sc->sc_node); > + DPRINTF(1, "%s: npins=%d\n", __func__, sc->sc_npins); > sc->sc_pin_map = qcgpio_x1e80100_pin_map; > } > KASSERT(sc->sc_npins != 0); > @@ -180,11 +368,12 @@ unmap: > if (sc->sc_ih) > acpi_intr_disestablish(sc->sc_ih); > free(sc->sc_pin_ih, M_DEVBUF, sc->sc_npins * sizeof(*sc->sc_pin_ih)); > + free(sc->sc_pdcmap, M_DEVBUF, sc->sc_npdcmap * sizeof(*sc->sc_pdcmap)); > bus_space_unmap(sc->sc_iot, sc->sc_ioh, aaa->aaa_size[0]); > } > > int > -qcgpio_sc7180_pin_map(int pin, bus_size_t *off) > +qcgpio_sc7180_pin_map(struct qcgpio_softc *sc, int pin, bus_size_t *off) > { > switch (pin) { > case 30: > @@ -211,7 +400,7 @@ qcgpio_sc7180_pin_map(int pin, bus_size_ > } > > int > -qcgpio_sc8280xp_pin_map(int pin, bus_size_t *off) > +qcgpio_sc8280xp_pin_map(struct qcgpio_softc *sc, int pin, bus_size_t *off) > { > switch (pin) { > case 107: > @@ -229,21 +418,19 @@ qcgpio_sc8280xp_pin_map(int pin, bus_siz > } > > int > -qcgpio_x1e80100_pin_map(int pin, bus_size_t *off) > +qcgpio_x1e80100_pin_map(struct qcgpio_softc *sc, int pin, bus_size_t *off) > { > - switch (pin) { > - case 3: > - case 51: > - return pin; > - case 0x180: > - return 67; > - case 0x380: > - return 33; > - case 0x3c0: > - return 3; > - default: > - return -1; > + int real_pin = -1; > + > + if (pin < sc->sc_npins) { > + real_pin = pin; > + } else if (pin / 64 < sc->sc_npdcmap) { > + real_pin = sc->sc_pdcmap[pin / 64].pm_pin; > } > + > + DPRINTF(2, "%s: map pin %d to real_pin %d\n", __func__, pin, real_pin); > + > + return real_pin; > } > > int > @@ -253,7 +440,7 @@ qcgpio_read_pin(void *cookie, int pin) > bus_size_t off = 0; > uint32_t reg; > > - pin = sc->sc_pin_map(pin, &off); > + pin = sc->sc_pin_map(sc, pin, &off); > if (pin < 0 || pin >= sc->sc_npins) > return 0; > > @@ -267,7 +454,7 @@ qcgpio_write_pin(void *cookie, int pin, > struct qcgpio_softc *sc = cookie; > bus_size_t off = 0; > > - pin = sc->sc_pin_map(pin, &off); > + pin = sc->sc_pin_map(sc, pin, &off); > if (pin < 0 || pin >= sc->sc_npins) > return; > > @@ -288,7 +475,7 @@ qcgpio_intr_establish(void *cookie, int > bus_size_t off = 0; > uint32_t reg; > > - pin = sc->sc_pin_map(pin, &off); > + pin = sc->sc_pin_map(sc, pin, &off); > if (pin < 0 || pin >= sc->sc_npins) > return; > > @@ -335,7 +522,7 @@ qcgpio_intr_enable(void *cookie, int pin > struct qcgpio_softc *sc = cookie; > bus_size_t off = 0; > > - pin = sc->sc_pin_map(pin, &off); > + pin = sc->sc_pin_map(sc, pin, &off); > if (pin < 0 || pin >= sc->sc_npins) > return; > > @@ -349,7 +536,7 @@ qcgpio_intr_disable(void *cookie, int pi > struct qcgpio_softc *sc = cookie; > bus_size_t off = 0; > > - pin = sc->sc_pin_map(pin, &off); > + pin = sc->sc_pin_map(sc, pin, &off); > if (pin < 0 || pin >= sc->sc_npins) > return; > > @@ -369,7 +556,7 @@ qcgpio_intr(void *arg) > if (sc->sc_pin_ih[pin].ih_func == NULL) > continue; > > - sc->sc_pin_map(pin, &off); > + sc->sc_pin_map(sc, pin, &off); > > stat = HREAD4(sc, off + TLMM_GPIO_INTR_STATUS(pin)); > if (stat & TLMM_GPIO_INTR_STATUS_INTR_STATUS) { > >