1 /* $OpenBSD: chvgpio.c,v 1.13 2022/10/20 20:40:57 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 CHVGPIO_INTERRUPT_STATUS 0x0300 29 #define CHVGPIO_INTERRUPT_MASK 0x0380 30 #define CHVGPIO_PAD_CFG0 0x4400 31 #define CHVGPIO_PAD_CFG1 0x4404 32 33 #define CHVGPIO_PAD_CFG0_GPIORXSTATE 0x00000001 34 #define CHVGPIO_PAD_CFG0_GPIOTXSTATE 0x00000002 35 #define CHVGPIO_PAD_CFG0_INTSEL_MASK 0xf0000000 36 #define CHVGPIO_PAD_CFG0_INTSEL_SHIFT 28 37 38 #define CHVGPIO_PAD_CFG1_INTWAKECFG_MASK 0x00000007 39 #define CHVGPIO_PAD_CFG1_INTWAKECFG_FALLING 0x00000001 40 #define CHVGPIO_PAD_CFG1_INTWAKECFG_RISING 0x00000002 41 #define CHVGPIO_PAD_CFG1_INTWAKECFG_BOTH 0x00000003 42 #define CHVGPIO_PAD_CFG1_INTWAKECFG_LEVEL 0x00000004 43 #define CHVGPIO_PAD_CFG1_INVRXTX_MASK 0x000000f0 44 #define CHVGPIO_PAD_CFG1_INVRXTX_RXDATA 0x00000040 45 46 /* OEM defined RegionSpace. */ 47 #define CHVGPIO_REGIONSPACE_BASE 0x90 48 49 struct chvgpio_intrhand { 50 int (*ih_func)(void *); 51 void *ih_arg; 52 }; 53 54 struct chvgpio_softc { 55 struct device sc_dev; 56 struct acpi_softc *sc_acpi; 57 struct aml_node *sc_node; 58 59 bus_space_tag_t sc_memt; 60 bus_space_handle_t sc_memh; 61 bus_size_t sc_size; 62 void *sc_ih; 63 64 const int *sc_pins; 65 int sc_npins; 66 int sc_ngroups; 67 68 struct chvgpio_intrhand sc_pin_ih[16]; 69 70 struct acpi_gpio sc_gpio; 71 }; 72 73 static inline int 74 chvgpio_pad_cfg0_offset(int pin) 75 { 76 return (CHVGPIO_PAD_CFG0 + 1024 * (pin / 15) + 8 * (pin % 15)); 77 } 78 79 static inline int 80 chvgpio_read_pad_cfg0(struct chvgpio_softc *sc, int pin) 81 { 82 return bus_space_read_4(sc->sc_memt, sc->sc_memh, 83 chvgpio_pad_cfg0_offset(pin)); 84 } 85 86 static inline void 87 chvgpio_write_pad_cfg0(struct chvgpio_softc *sc, int pin, uint32_t val) 88 { 89 bus_space_write_4(sc->sc_memt, sc->sc_memh, 90 chvgpio_pad_cfg0_offset(pin), val); 91 } 92 93 static inline int 94 chvgpio_read_pad_cfg1(struct chvgpio_softc *sc, int pin) 95 { 96 return bus_space_read_4(sc->sc_memt, sc->sc_memh, 97 chvgpio_pad_cfg0_offset(pin) + 4); 98 } 99 100 static inline void 101 chvgpio_write_pad_cfg1(struct chvgpio_softc *sc, int pin, uint32_t val) 102 { 103 bus_space_write_4(sc->sc_memt, sc->sc_memh, 104 chvgpio_pad_cfg0_offset(pin) + 4, val); 105 } 106 107 int chvgpio_match(struct device *, void *, void *); 108 void chvgpio_attach(struct device *, struct device *, void *); 109 110 const struct cfattach chvgpio_ca = { 111 sizeof(struct chvgpio_softc), chvgpio_match, chvgpio_attach 112 }; 113 114 struct cfdriver chvgpio_cd = { 115 NULL, "chvgpio", DV_DULL 116 }; 117 118 const char *chvgpio_hids[] = { 119 "INT33FF", 120 NULL 121 }; 122 123 /* 124 * The pads for the pins are arranged in groups of maximal 15 pins. 125 * The arrays below give the number of pins per group, such that we 126 * can validate the (untrusted) pin numbers from ACPI. 127 */ 128 129 const int chv_southwest_pins[] = { 130 8, 8, 8, 8, 8, 8, 8, -1 131 }; 132 133 const int chv_north_pins[] = { 134 9, 13, 12, 12, 13, -1 135 }; 136 137 const int chv_east_pins[] = { 138 12, 12, -1 139 }; 140 141 const int chv_southeast_pins[] = { 142 8, 12, 6, 8, 10, 11, -1 143 }; 144 145 int chvgpio_check_pin(struct chvgpio_softc *, int); 146 int chvgpio_read_pin(void *, int); 147 void chvgpio_write_pin(void *, int, int); 148 void chvgpio_intr_establish(void *, int, int, int (*)(void *), void *); 149 void chvgpio_intr_enable(void *, int); 150 void chvgpio_intr_disable(void *, int); 151 int chvgpio_intr(void *); 152 int chvgpio_opreg_handler(void *, int, uint64_t, int, uint64_t *); 153 154 int 155 chvgpio_match(struct device *parent, void *match, void *aux) 156 { 157 struct acpi_attach_args *aaa = aux; 158 struct cfdata *cf = match; 159 160 if (aaa->aaa_naddr < 1 || aaa->aaa_nirq < 1) 161 return 0; 162 return acpi_matchhids(aaa, chvgpio_hids, cf->cf_driver->cd_name); 163 } 164 165 void 166 chvgpio_attach(struct device *parent, struct device *self, void *aux) 167 { 168 struct chvgpio_softc *sc = (struct chvgpio_softc *)self; 169 struct acpi_attach_args *aaa = aux; 170 int64_t uid; 171 int i; 172 173 sc->sc_acpi = (struct acpi_softc *)parent; 174 sc->sc_node = aaa->aaa_node; 175 printf(" %s", sc->sc_node->name); 176 177 if (aml_evalinteger(sc->sc_acpi, sc->sc_node, "_UID", 0, NULL, &uid)) { 178 printf(": can't find uid\n"); 179 return; 180 } 181 182 printf(" uid %lld", uid); 183 184 switch (uid) { 185 case 1: 186 sc->sc_pins = chv_southwest_pins; 187 break; 188 case 2: 189 sc->sc_pins = chv_north_pins; 190 break; 191 case 3: 192 sc->sc_pins = chv_east_pins; 193 break; 194 case 4: 195 sc->sc_pins = chv_southeast_pins; 196 break; 197 default: 198 printf("\n"); 199 return; 200 } 201 202 for (i = 0; sc->sc_pins[i] >= 0; i++) { 203 sc->sc_npins += sc->sc_pins[i]; 204 sc->sc_ngroups++; 205 } 206 207 printf(" addr 0x%llx/0x%llx", aaa->aaa_addr[0], aaa->aaa_size[0]); 208 printf(" irq %d", aaa->aaa_irq[0]); 209 210 sc->sc_memt = aaa->aaa_bst[0]; 211 sc->sc_size = aaa->aaa_size[0]; 212 if (bus_space_map(sc->sc_memt, aaa->aaa_addr[0], aaa->aaa_size[0], 213 0, &sc->sc_memh)) { 214 printf(": can't map registers\n"); 215 return; 216 } 217 218 sc->sc_ih = acpi_intr_establish(aaa->aaa_irq[0], aaa->aaa_irq_flags[0], 219 IPL_BIO, chvgpio_intr, sc, sc->sc_dev.dv_xname); 220 if (sc->sc_ih == NULL) { 221 printf(": can't establish interrupt\n"); 222 goto unmap; 223 } 224 225 sc->sc_gpio.cookie = sc; 226 sc->sc_gpio.read_pin = chvgpio_read_pin; 227 sc->sc_gpio.write_pin = chvgpio_write_pin; 228 sc->sc_gpio.intr_establish = chvgpio_intr_establish; 229 sc->sc_gpio.intr_enable = chvgpio_intr_enable; 230 sc->sc_gpio.intr_disable = chvgpio_intr_disable; 231 sc->sc_node->gpio = &sc->sc_gpio; 232 233 /* Mask and ack all interrupts. */ 234 bus_space_write_4(sc->sc_memt, sc->sc_memh, 235 CHVGPIO_INTERRUPT_MASK, 0); 236 bus_space_write_4(sc->sc_memt, sc->sc_memh, 237 CHVGPIO_INTERRUPT_STATUS, 0xffff); 238 239 printf(", %d pins\n", sc->sc_npins); 240 241 /* Register OEM defined address space. */ 242 aml_register_regionspace(sc->sc_node, CHVGPIO_REGIONSPACE_BASE + uid, 243 sc, chvgpio_opreg_handler); 244 245 acpi_register_gpio(sc->sc_acpi, sc->sc_node); 246 return; 247 248 unmap: 249 bus_space_unmap(sc->sc_memt, sc->sc_memh, sc->sc_size); 250 } 251 252 int 253 chvgpio_check_pin(struct chvgpio_softc *sc, int pin) 254 { 255 if (pin < 0) 256 return EINVAL; 257 if ((pin / 15) >= sc->sc_ngroups) 258 return EINVAL; 259 if ((pin % 15) >= sc->sc_pins[pin / 15]) 260 return EINVAL; 261 262 return 0; 263 } 264 265 int 266 chvgpio_read_pin(void *cookie, int pin) 267 { 268 struct chvgpio_softc *sc = cookie; 269 uint32_t reg; 270 271 KASSERT(chvgpio_check_pin(sc, pin) == 0); 272 273 reg = chvgpio_read_pad_cfg0(sc, pin); 274 return (reg & CHVGPIO_PAD_CFG0_GPIORXSTATE); 275 } 276 277 void 278 chvgpio_write_pin(void *cookie, int pin, int value) 279 { 280 struct chvgpio_softc *sc = cookie; 281 uint32_t reg; 282 283 KASSERT(chvgpio_check_pin(sc, pin) == 0); 284 285 reg = chvgpio_read_pad_cfg0(sc, pin); 286 if (value) 287 reg |= CHVGPIO_PAD_CFG0_GPIOTXSTATE; 288 else 289 reg &= ~CHVGPIO_PAD_CFG0_GPIOTXSTATE; 290 chvgpio_write_pad_cfg0(sc, pin, reg); 291 } 292 293 void 294 chvgpio_intr_establish(void *cookie, int pin, int flags, 295 int (*func)(void *), void *arg) 296 { 297 struct chvgpio_softc *sc = cookie; 298 uint32_t reg; 299 int line; 300 301 KASSERT(chvgpio_check_pin(sc, pin) == 0); 302 303 reg = chvgpio_read_pad_cfg0(sc, pin); 304 reg &= CHVGPIO_PAD_CFG0_INTSEL_MASK; 305 line = reg >> CHVGPIO_PAD_CFG0_INTSEL_SHIFT; 306 307 sc->sc_pin_ih[line].ih_func = func; 308 sc->sc_pin_ih[line].ih_arg = arg; 309 310 reg = chvgpio_read_pad_cfg1(sc, pin); 311 reg &= ~CHVGPIO_PAD_CFG1_INTWAKECFG_MASK; 312 reg &= ~CHVGPIO_PAD_CFG1_INVRXTX_MASK; 313 switch (flags & (LR_GPIO_MODE | LR_GPIO_POLARITY)) { 314 case LR_GPIO_LEVEL | LR_GPIO_ACTLO: 315 reg |= CHVGPIO_PAD_CFG1_INVRXTX_RXDATA; 316 /* FALLTHROUGH */ 317 case LR_GPIO_LEVEL | LR_GPIO_ACTHI: 318 reg |= CHVGPIO_PAD_CFG1_INTWAKECFG_LEVEL; 319 break; 320 case LR_GPIO_EDGE | LR_GPIO_ACTLO: 321 reg |= CHVGPIO_PAD_CFG1_INTWAKECFG_FALLING; 322 break; 323 case LR_GPIO_EDGE | LR_GPIO_ACTHI: 324 reg |= CHVGPIO_PAD_CFG1_INTWAKECFG_RISING; 325 break; 326 case LR_GPIO_EDGE | LR_GPIO_ACTBOTH: 327 reg |= CHVGPIO_PAD_CFG1_INTWAKECFG_BOTH; 328 break; 329 default: 330 printf("%s: unsupported interrupt mode/polarity\n", 331 sc->sc_dev.dv_xname); 332 break; 333 } 334 chvgpio_write_pad_cfg1(sc, pin, reg); 335 336 reg = bus_space_read_4(sc->sc_memt, sc->sc_memh, 337 CHVGPIO_INTERRUPT_MASK); 338 bus_space_write_4(sc->sc_memt, sc->sc_memh, 339 CHVGPIO_INTERRUPT_MASK, reg | (1 << line)); 340 } 341 342 void 343 chvgpio_intr_enable(void *cookie, int pin) 344 { 345 struct chvgpio_softc *sc = cookie; 346 uint32_t reg; 347 int line; 348 349 KASSERT(chvgpio_check_pin(sc, pin) == 0); 350 351 reg = chvgpio_read_pad_cfg0(sc, pin); 352 reg &= CHVGPIO_PAD_CFG0_INTSEL_MASK; 353 line = reg >> CHVGPIO_PAD_CFG0_INTSEL_SHIFT; 354 355 reg = bus_space_read_4(sc->sc_memt, sc->sc_memh, 356 CHVGPIO_INTERRUPT_MASK); 357 bus_space_write_4(sc->sc_memt, sc->sc_memh, 358 CHVGPIO_INTERRUPT_MASK, reg | (1 << line)); 359 } 360 361 void 362 chvgpio_intr_disable(void *cookie, int pin) 363 { 364 struct chvgpio_softc *sc = cookie; 365 uint32_t reg; 366 int line; 367 368 KASSERT(chvgpio_check_pin(sc, pin) == 0); 369 370 reg = chvgpio_read_pad_cfg0(sc, pin); 371 reg &= CHVGPIO_PAD_CFG0_INTSEL_MASK; 372 line = reg >> CHVGPIO_PAD_CFG0_INTSEL_SHIFT; 373 374 reg = bus_space_read_4(sc->sc_memt, sc->sc_memh, 375 CHVGPIO_INTERRUPT_MASK); 376 bus_space_write_4(sc->sc_memt, sc->sc_memh, 377 CHVGPIO_INTERRUPT_MASK, reg & ~(1 << line)); 378 } 379 380 int 381 chvgpio_intr(void *arg) 382 { 383 struct chvgpio_softc *sc = arg; 384 uint32_t reg; 385 int rc = 0; 386 int line; 387 388 reg = bus_space_read_4(sc->sc_memt, sc->sc_memh, 389 CHVGPIO_INTERRUPT_STATUS); 390 for (line = 0; line < 16; line++) { 391 if ((reg & (1 << line)) == 0) 392 continue; 393 394 bus_space_write_4(sc->sc_memt,sc->sc_memh, 395 CHVGPIO_INTERRUPT_STATUS, 1 << line); 396 if (sc->sc_pin_ih[line].ih_func) 397 sc->sc_pin_ih[line].ih_func(sc->sc_pin_ih[line].ih_arg); 398 rc = 1; 399 } 400 401 return rc; 402 } 403 404 int 405 chvgpio_opreg_handler(void *cookie, int iodir, uint64_t address, int size, 406 uint64_t *value) 407 { 408 struct chvgpio_softc *sc = cookie; 409 410 /* Only allow 32-bit access. */ 411 if (size != 4 || address > sc->sc_size - size) 412 return -1; 413 414 if (iodir == ACPI_IOREAD) 415 *value = bus_space_read_4(sc->sc_memt, sc->sc_memh, address); 416 else 417 bus_space_write_4(sc->sc_memt, sc->sc_memh, address, *value); 418 419 return 0; 420 } 421