1 /* $OpenBSD: bytgpio.c,v 1.14 2020/05/22 10:16:37 kettenis Exp $ */ 2 /* 3 * Copyright (c) 2016 Mark Kettenis 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/malloc.h> 20 #include <sys/systm.h> 21 22 #include <dev/acpi/acpireg.h> 23 #include <dev/acpi/acpivar.h> 24 #include <dev/acpi/acpidev.h> 25 #include <dev/acpi/amltypes.h> 26 #include <dev/acpi/dsdt.h> 27 28 #define BYTGPIO_CONF_GD_LEVEL 0x01000000 29 #define BYTGPIO_CONF_GD_TPE 0x02000000 30 #define BYTGPIO_CONF_GD_TNE 0x04000000 31 #define BYTGPIO_CONF_GD_MASK 0x07000000 32 #define BYTGPIO_CONF_DIRECT_IRQ_EN 0x08000000 33 34 #define BYTGPIO_PAD_VAL 0x00000001 35 36 #define BYTGPIO_IRQ_TS_0 0x800 37 #define BYTGPIO_IRQ_TS_1 0x804 38 #define BYTGPIO_IRQ_TS_2 0x808 39 40 struct bytgpio_intrhand { 41 int (*ih_func)(void *); 42 void *ih_arg; 43 }; 44 45 struct bytgpio_softc { 46 struct device sc_dev; 47 struct acpi_softc *sc_acpi; 48 struct aml_node *sc_node; 49 50 bus_space_tag_t sc_memt; 51 bus_space_handle_t sc_memh; 52 void *sc_ih; 53 54 const int *sc_pins; 55 int sc_npins; 56 struct bytgpio_intrhand *sc_pin_ih; 57 58 struct acpi_gpio sc_gpio; 59 }; 60 61 int bytgpio_match(struct device *, void *, void *); 62 void bytgpio_attach(struct device *, struct device *, void *); 63 64 struct cfattach bytgpio_ca = { 65 sizeof(struct bytgpio_softc), bytgpio_match, bytgpio_attach 66 }; 67 68 struct cfdriver bytgpio_cd = { 69 NULL, "bytgpio", DV_DULL 70 }; 71 72 const char *bytgpio_hids[] = { 73 "INT33FC", 74 NULL 75 }; 76 77 /* 78 * The pads for the pins are randomly ordered. 79 */ 80 81 const int byt_score_pins[] = { 82 85, 89, 93, 96, 99, 102, 98, 101, 34, 37, 36, 38, 39, 35, 40, 83 84, 62, 61, 64, 59, 54, 56, 60, 55, 63, 57, 51, 50, 53, 47, 84 52, 49, 48, 43, 46, 41, 45, 42, 58, 44, 95, 105, 70, 68, 67, 85 66, 69, 71, 65, 72, 86, 90, 88, 92, 103, 77, 79, 83, 78, 81, 86 80, 82, 13, 12, 15, 14, 17, 18, 19, 16, 2, 1, 0, 4, 6, 7, 9, 87 8, 33, 32, 31, 30, 29, 27, 25, 28, 26, 23, 21, 20, 24, 22, 5, 88 3, 10, 11, 106, 87, 91, 104, 97, 100 89 }; 90 91 const int byt_ncore_pins[] = { 92 19, 18, 17, 20, 21, 22, 24, 25, 23, 16, 14, 15, 12, 26, 27, 93 1, 4, 8, 11, 0, 3, 6, 10, 13, 2, 5, 9, 7 94 }; 95 96 const int byt_sus_pins[] = { 97 29, 33, 30, 31, 32, 34, 36, 35, 38, 37, 18, 7, 11, 20, 17, 1, 98 8, 10, 19, 12, 0, 2, 23, 39, 28, 27, 22, 21, 24, 25, 26, 51, 99 56, 54, 49, 55, 48, 57, 50, 58, 52, 53, 59, 40 100 }; 101 102 int bytgpio_read_pin(void *, int); 103 void bytgpio_write_pin(void *, int, int); 104 void bytgpio_intr_establish(void *, int, int, int (*)(), void *); 105 int bytgpio_intr(void *); 106 107 int 108 bytgpio_match(struct device *parent, void *match, void *aux) 109 { 110 struct acpi_attach_args *aaa = aux; 111 struct cfdata *cf = match; 112 113 return acpi_matchhids(aaa, bytgpio_hids, cf->cf_driver->cd_name); 114 } 115 116 void 117 bytgpio_attach(struct device *parent, struct device *self, void *aux) 118 { 119 struct bytgpio_softc *sc = (struct bytgpio_softc *)self; 120 struct acpi_attach_args *aaa = aux; 121 int64_t uid; 122 uint32_t reg; 123 int i; 124 125 sc->sc_acpi = (struct acpi_softc *)parent; 126 sc->sc_node = aaa->aaa_node; 127 printf(" %s", sc->sc_node->name); 128 129 if (aaa->aaa_naddr < 1) { 130 printf(": no registers\n"); 131 return; 132 } 133 134 if (aaa->aaa_nirq < 1) { 135 printf(": no interrupt\n"); 136 return; 137 } 138 139 if (aml_evalinteger(sc->sc_acpi, sc->sc_node, "_UID", 0, NULL, &uid)) { 140 printf(": can't find uid\n"); 141 return; 142 } 143 144 printf(" uid %lld", uid); 145 146 switch (uid) { 147 case 1: 148 sc->sc_pins = byt_score_pins; 149 sc->sc_npins = nitems(byt_score_pins); 150 break; 151 case 2: 152 sc->sc_pins = byt_ncore_pins; 153 sc->sc_npins = nitems(byt_ncore_pins); 154 break; 155 case 3: 156 sc->sc_pins = byt_sus_pins; 157 sc->sc_npins = nitems(byt_sus_pins); 158 break; 159 default: 160 printf("\n"); 161 return; 162 } 163 164 printf(" addr 0x%llx/0x%llx", aaa->aaa_addr[0], aaa->aaa_size[0]); 165 printf(" irq %d", aaa->aaa_irq[0]); 166 167 sc->sc_memt = aaa->aaa_bst[0]; 168 if (bus_space_map(sc->sc_memt, aaa->aaa_addr[0], aaa->aaa_size[0], 169 0, &sc->sc_memh)) { 170 printf(": can't map registers\n"); 171 return; 172 } 173 174 sc->sc_pin_ih = mallocarray(sc->sc_npins, sizeof(*sc->sc_pin_ih), 175 M_DEVBUF, M_WAITOK | M_ZERO); 176 177 sc->sc_ih = acpi_intr_establish(aaa->aaa_irq[0], aaa->aaa_irq_flags[0], 178 IPL_BIO, bytgpio_intr, sc, sc->sc_dev.dv_xname); 179 if (sc->sc_ih == NULL) { 180 printf(": can't establish interrupt\n"); 181 goto unmap; 182 } 183 184 sc->sc_gpio.cookie = sc; 185 sc->sc_gpio.read_pin = bytgpio_read_pin; 186 sc->sc_gpio.write_pin = bytgpio_write_pin; 187 sc->sc_gpio.intr_establish = bytgpio_intr_establish; 188 sc->sc_node->gpio = &sc->sc_gpio; 189 190 /* Mask all interrupts. */ 191 for (i = 0; i < sc->sc_npins; i++) { 192 reg = bus_space_read_4(sc->sc_memt, sc->sc_memh, sc->sc_pins[i] * 16); 193 194 /* 195 * Skip pins configured as direct IRQ. Those are tied 196 * directly to the APIC. 197 */ 198 if (reg & BYTGPIO_CONF_DIRECT_IRQ_EN) 199 continue; 200 201 reg &= ~BYTGPIO_CONF_GD_MASK; 202 bus_space_write_4(sc->sc_memt, sc->sc_memh, sc->sc_pins[i] * 16, reg); 203 } 204 205 printf(", %d pins\n", sc->sc_npins); 206 207 acpi_register_gpio(sc->sc_acpi, sc->sc_node); 208 return; 209 210 unmap: 211 free(sc->sc_pin_ih, M_DEVBUF, sc->sc_npins * sizeof(*sc->sc_pin_ih)); 212 bus_space_unmap(sc->sc_memt, sc->sc_memh, aaa->aaa_size[0]); 213 } 214 215 int 216 bytgpio_read_pin(void *cookie, int pin) 217 { 218 struct bytgpio_softc *sc = cookie; 219 uint32_t reg; 220 221 reg = bus_space_read_4(sc->sc_memt, sc->sc_memh, sc->sc_pins[pin] * 16 + 8); 222 return (reg & BYTGPIO_PAD_VAL); 223 } 224 225 void 226 bytgpio_write_pin(void *cookie, int pin, int value) 227 { 228 struct bytgpio_softc *sc = cookie; 229 uint32_t reg; 230 231 reg = bus_space_read_4(sc->sc_memt, sc->sc_memh, sc->sc_pins[pin] * 16 + 8); 232 if (value) 233 reg |= BYTGPIO_PAD_VAL; 234 else 235 reg &= ~BYTGPIO_PAD_VAL; 236 bus_space_write_4(sc->sc_memt, sc->sc_memh, sc->sc_pins[pin] * 16 + 8, reg); 237 } 238 239 void 240 bytgpio_intr_establish(void *cookie, int pin, int flags, 241 int (*func)(void *), void *arg) 242 { 243 struct bytgpio_softc *sc = cookie; 244 uint32_t reg; 245 246 KASSERT(pin >= 0 && pin < sc->sc_npins); 247 248 sc->sc_pin_ih[pin].ih_func = func; 249 sc->sc_pin_ih[pin].ih_arg = arg; 250 251 reg = bus_space_read_4(sc->sc_memt, sc->sc_memh, sc->sc_pins[pin] * 16); 252 reg &= ~BYTGPIO_CONF_GD_MASK; 253 if ((flags & LR_GPIO_MODE) == 0) 254 reg |= BYTGPIO_CONF_GD_LEVEL; 255 if ((flags & LR_GPIO_POLARITY) == LR_GPIO_ACTLO) 256 reg |= BYTGPIO_CONF_GD_TNE; 257 if ((flags & LR_GPIO_POLARITY) == LR_GPIO_ACTHI) 258 reg |= BYTGPIO_CONF_GD_TPE; 259 if ((flags & LR_GPIO_POLARITY) == LR_GPIO_ACTBOTH) 260 reg |= BYTGPIO_CONF_GD_TNE | BYTGPIO_CONF_GD_TPE; 261 bus_space_write_4(sc->sc_memt, sc->sc_memh, sc->sc_pins[pin] * 16, reg); 262 } 263 264 int 265 bytgpio_intr(void *arg) 266 { 267 struct bytgpio_softc *sc = arg; 268 uint32_t reg; 269 int rc = 0; 270 int pin; 271 272 for (pin = 0; pin < sc->sc_npins; pin++) { 273 if (pin % 32 == 0) { 274 reg = bus_space_read_4(sc->sc_memt, sc->sc_memh, 275 BYTGPIO_IRQ_TS_0 + (pin / 8)); 276 bus_space_write_4(sc->sc_memt, sc->sc_memh, 277 BYTGPIO_IRQ_TS_0 + (pin / 8), reg); 278 } 279 if (reg & (1 << (pin % 32))) { 280 if (sc->sc_pin_ih[pin].ih_func) 281 sc->sc_pin_ih[pin].ih_func(sc->sc_pin_ih[pin].ih_arg); 282 rc = 1; 283 } 284 } 285 286 return rc; 287 } 288