1 /* $OpenBSD: chvgpio.c,v 1.10 2021/05/16 08:50:59 jsg 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 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 int chvgpio_intr(void *); 150 int chvgpio_opreg_handler(void *, int, uint64_t, int, uint64_t *); 151 152 int 153 chvgpio_match(struct device *parent, void *match, void *aux) 154 { 155 struct acpi_attach_args *aaa = aux; 156 struct cfdata *cf = match; 157 158 return acpi_matchhids(aaa, chvgpio_hids, cf->cf_driver->cd_name); 159 } 160 161 void 162 chvgpio_attach(struct device *parent, struct device *self, void *aux) 163 { 164 struct chvgpio_softc *sc = (struct chvgpio_softc *)self; 165 struct acpi_attach_args *aaa = aux; 166 int64_t uid; 167 int i; 168 169 sc->sc_acpi = (struct acpi_softc *)parent; 170 sc->sc_node = aaa->aaa_node; 171 printf(" %s", sc->sc_node->name); 172 173 if (aaa->aaa_naddr < 1) { 174 printf(": no registers\n"); 175 return; 176 } 177 178 if (aaa->aaa_nirq < 1) { 179 printf(": no interrupt\n"); 180 return; 181 } 182 183 if (aml_evalinteger(sc->sc_acpi, sc->sc_node, "_UID", 0, NULL, &uid)) { 184 printf(": can't find uid\n"); 185 return; 186 } 187 188 printf(" uid %lld", uid); 189 190 switch (uid) { 191 case 1: 192 sc->sc_pins = chv_southwest_pins; 193 break; 194 case 2: 195 sc->sc_pins = chv_north_pins; 196 break; 197 case 3: 198 sc->sc_pins = chv_east_pins; 199 break; 200 case 4: 201 sc->sc_pins = chv_southeast_pins; 202 break; 203 default: 204 printf("\n"); 205 return; 206 } 207 208 for (i = 0; sc->sc_pins[i] >= 0; i++) { 209 sc->sc_npins += sc->sc_pins[i]; 210 sc->sc_ngroups++; 211 } 212 213 printf(" addr 0x%llx/0x%llx", aaa->aaa_addr[0], aaa->aaa_size[0]); 214 printf(" irq %d", aaa->aaa_irq[0]); 215 216 sc->sc_memt = aaa->aaa_bst[0]; 217 sc->sc_size = aaa->aaa_size[0]; 218 if (bus_space_map(sc->sc_memt, aaa->aaa_addr[0], aaa->aaa_size[0], 219 0, &sc->sc_memh)) { 220 printf(": can't map registers\n"); 221 return; 222 } 223 224 sc->sc_ih = acpi_intr_establish(aaa->aaa_irq[0], aaa->aaa_irq_flags[0], 225 IPL_BIO, chvgpio_intr, sc, sc->sc_dev.dv_xname); 226 if (sc->sc_ih == NULL) { 227 printf(": can't establish interrupt\n"); 228 goto unmap; 229 } 230 231 sc->sc_gpio.cookie = sc; 232 sc->sc_gpio.read_pin = chvgpio_read_pin; 233 sc->sc_gpio.write_pin = chvgpio_write_pin; 234 sc->sc_gpio.intr_establish = chvgpio_intr_establish; 235 sc->sc_node->gpio = &sc->sc_gpio; 236 237 /* Mask and ack all interrupts. */ 238 bus_space_write_4(sc->sc_memt, sc->sc_memh, 239 CHVGPIO_INTERRUPT_MASK, 0); 240 bus_space_write_4(sc->sc_memt, sc->sc_memh, 241 CHVGPIO_INTERRUPT_STATUS, 0xffff); 242 243 printf(", %d pins\n", sc->sc_npins); 244 245 /* Register OEM defined address space. */ 246 aml_register_regionspace(sc->sc_node, CHVGPIO_REGIONSPACE_BASE + uid, 247 sc, chvgpio_opreg_handler); 248 249 acpi_register_gpio(sc->sc_acpi, sc->sc_node); 250 return; 251 252 unmap: 253 bus_space_unmap(sc->sc_memt, sc->sc_memh, sc->sc_size); 254 } 255 256 int 257 chvgpio_check_pin(struct chvgpio_softc *sc, int pin) 258 { 259 if (pin < 0) 260 return EINVAL; 261 if ((pin / 15) >= sc->sc_ngroups) 262 return EINVAL; 263 if ((pin % 15) >= sc->sc_pins[pin / 15]) 264 return EINVAL; 265 266 return 0; 267 } 268 269 int 270 chvgpio_read_pin(void *cookie, int pin) 271 { 272 struct chvgpio_softc *sc = cookie; 273 uint32_t reg; 274 275 KASSERT(chvgpio_check_pin(sc, pin) == 0); 276 277 reg = chvgpio_read_pad_cfg0(sc, pin); 278 return (reg & CHVGPIO_PAD_CFG0_GPIORXSTATE); 279 } 280 281 void 282 chvgpio_write_pin(void *cookie, int pin, int value) 283 { 284 struct chvgpio_softc *sc = cookie; 285 uint32_t reg; 286 287 KASSERT(chvgpio_check_pin(sc, pin) == 0); 288 289 reg = chvgpio_read_pad_cfg0(sc, pin); 290 if (value) 291 reg |= CHVGPIO_PAD_CFG0_GPIOTXSTATE; 292 else 293 reg &= ~CHVGPIO_PAD_CFG0_GPIOTXSTATE; 294 chvgpio_write_pad_cfg0(sc, pin, reg); 295 } 296 297 void 298 chvgpio_intr_establish(void *cookie, int pin, int flags, 299 int (*func)(void *), void *arg) 300 { 301 struct chvgpio_softc *sc = cookie; 302 uint32_t reg; 303 int line; 304 305 KASSERT(chvgpio_check_pin(sc, pin) == 0); 306 307 reg = chvgpio_read_pad_cfg0(sc, pin); 308 reg &= CHVGPIO_PAD_CFG0_INTSEL_MASK; 309 line = reg >> CHVGPIO_PAD_CFG0_INTSEL_SHIFT; 310 311 sc->sc_pin_ih[line].ih_func = func; 312 sc->sc_pin_ih[line].ih_arg = arg; 313 314 reg = chvgpio_read_pad_cfg1(sc, pin); 315 reg &= ~CHVGPIO_PAD_CFG1_INTWAKECFG_MASK; 316 reg &= ~CHVGPIO_PAD_CFG1_INVRXTX_MASK; 317 switch (flags & (LR_GPIO_MODE | LR_GPIO_POLARITY)) { 318 case LR_GPIO_LEVEL | LR_GPIO_ACTLO: 319 reg |= CHVGPIO_PAD_CFG1_INVRXTX_RXDATA; 320 /* FALLTHROUGH */ 321 case LR_GPIO_LEVEL | LR_GPIO_ACTHI: 322 reg |= CHVGPIO_PAD_CFG1_INTWAKECFG_LEVEL; 323 break; 324 case LR_GPIO_EDGE | LR_GPIO_ACTLO: 325 reg |= CHVGPIO_PAD_CFG1_INTWAKECFG_FALLING; 326 break; 327 case LR_GPIO_EDGE | LR_GPIO_ACTHI: 328 reg |= CHVGPIO_PAD_CFG1_INTWAKECFG_RISING; 329 break; 330 case LR_GPIO_EDGE | LR_GPIO_ACTBOTH: 331 reg |= CHVGPIO_PAD_CFG1_INTWAKECFG_BOTH; 332 break; 333 default: 334 printf("%s: unsupported interrupt mode/polarity\n", 335 sc->sc_dev.dv_xname); 336 break; 337 } 338 chvgpio_write_pad_cfg1(sc, pin, reg); 339 340 reg = bus_space_read_4(sc->sc_memt, sc->sc_memh, 341 CHVGPIO_INTERRUPT_MASK); 342 bus_space_write_4(sc->sc_memt, sc->sc_memh, 343 CHVGPIO_INTERRUPT_MASK, reg | (1 << line)); 344 } 345 346 int 347 chvgpio_intr(void *arg) 348 { 349 struct chvgpio_softc *sc = arg; 350 uint32_t reg; 351 int rc = 0; 352 int line; 353 354 reg = bus_space_read_4(sc->sc_memt, sc->sc_memh, 355 CHVGPIO_INTERRUPT_STATUS); 356 for (line = 0; line < 16; line++) { 357 if ((reg & (1 << line)) == 0) 358 continue; 359 360 bus_space_write_4(sc->sc_memt,sc->sc_memh, 361 CHVGPIO_INTERRUPT_STATUS, 1 << line); 362 if (sc->sc_pin_ih[line].ih_func) 363 sc->sc_pin_ih[line].ih_func(sc->sc_pin_ih[line].ih_arg); 364 rc = 1; 365 } 366 367 return rc; 368 } 369 370 int 371 chvgpio_opreg_handler(void *cookie, int iodir, uint64_t address, int size, 372 uint64_t *value) 373 { 374 struct chvgpio_softc *sc = cookie; 375 376 /* Only allow 32-bit access. */ 377 if (size != 4 || address > sc->sc_size - size) 378 return -1; 379 380 if (iodir == ACPI_IOREAD) 381 *value = bus_space_read_4(sc->sc_memt, sc->sc_memh, address); 382 else 383 bus_space_write_4(sc->sc_memt, sc->sc_memh, address, *value); 384 385 return 0; 386 } 387