1 /* $NetBSD: gpiosim.c,v 1.26 2023/11/24 15:13:35 brad Exp $ */ 2 /* $OpenBSD: gpiosim.c,v 1.1 2008/11/23 18:46:49 mbalmer Exp $ */ 3 4 /* 5 * Copyright (c) 2007 - 2011, 2013 Marc Balmer <marc@msys.ch> 6 * All rights reserved. 7 * 8 * Permission to use, copy, modify, and distribute this software for any 9 * purpose with or without fee is hereby granted, provided that the above 10 * copyright notice and this permission notice appear in all copies. 11 * 12 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 13 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 14 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 15 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 16 * WHATSOEVER RESULTING FROM LOSS OF MIND, USE, DATA OR PROFITS, WHETHER IN 17 * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT 18 * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 19 */ 20 21 /* 64 bit wide GPIO simulator */ 22 23 #include <sys/param.h> 24 #include <sys/systm.h> 25 #include <sys/device.h> 26 #include <sys/gpio.h> 27 #include <sys/malloc.h> 28 #include <sys/module.h> 29 #include <sys/sysctl.h> 30 #include <sys/ioccom.h> 31 #include <dev/gpio/gpiovar.h> 32 #include <sys/callout.h> 33 #include <sys/workqueue.h> 34 35 #include "gpiosim.h" 36 #include "ioconf.h" 37 38 #define GPIOSIM_NPINS 64 39 40 struct gpiosim_irq { 41 int (*sc_gpio_irqfunc)(void *); 42 void *sc_gpio_irqarg; 43 int sc_gpio_irqmode; 44 bool sc_gpio_irqtriggered; 45 }; 46 47 struct gpiosim_softc { 48 device_t sc_dev; 49 device_t sc_gdev; /* gpio that attaches here */ 50 uint64_t sc_state; 51 struct gpio_chipset_tag sc_gpio_gc; 52 gpio_pin_t sc_gpio_pins[GPIOSIM_NPINS]; 53 struct gpiosim_irq sc_gpio_irqs[GPIOSIM_NPINS]; 54 55 struct sysctllog *sc_log; 56 struct workqueue *sc_wq; 57 callout_t sc_co; 58 bool sc_co_init; 59 bool sc_co_running; 60 int sc_ms; 61 kmutex_t sc_intr_mutex; 62 }; 63 64 static int gpiosim_match(device_t, cfdata_t, void *); 65 static void gpiosim_attach(device_t, device_t, void *); 66 static int gpiosim_detach(device_t, int); 67 static int gpiosim_sysctl(SYSCTLFN_PROTO); 68 static int gpiosim_ms_sysctl(SYSCTLFN_PROTO); 69 70 static int gpiosim_pin_read(void *, int); 71 static void gpiosim_pin_write(void *, int, int); 72 static void gpiosim_pin_ctl(void *, int, int); 73 74 static void * gpiosim_intr_establish(void *, int, int, int, 75 int (*)(void *), void *); 76 static void gpiosim_intr_disestablish(void *, void *); 77 static bool gpiosim_gpio_intrstr(void *, int, int, char *, size_t); 78 79 void gpiosim_wq(struct work *, void *); 80 void gpiosim_co(void *); 81 82 CFATTACH_DECL_NEW(gpiosim, sizeof(struct gpiosim_softc), gpiosim_match, 83 gpiosim_attach, gpiosim_detach, NULL); 84 85 int gpiosim_work; 86 87 #ifndef GPIOSIM_MS 88 #define GPIOSIM_MS 1000 89 #endif 90 91 static int 92 gpiosim_match(device_t parent, cfdata_t match, void *aux) 93 { 94 return 1; 95 } 96 97 void 98 gpiosimattach(int num __unused) 99 { 100 cfdata_t cf; 101 int n, err; 102 103 err = config_cfattach_attach(gpiosim_cd.cd_name, &gpiosim_ca); 104 if (err) 105 printf("%s: unable to register cfattach\n", gpiosim_cd.cd_name); 106 107 for (n = 0; n < NGPIOSIM; n++) { 108 cf = malloc(sizeof(*cf), M_DEVBUF, M_WAITOK); 109 cf->cf_name = "gpiosim"; 110 cf->cf_atname = "gpiosim"; 111 cf->cf_unit = n; 112 cf->cf_fstate = FSTATE_NOTFOUND; 113 config_attach_pseudo(cf); 114 } 115 } 116 117 static void 118 gpiosim_attach(device_t parent, device_t self, void *aux) 119 { 120 struct gpiosim_softc *sc = device_private(self); 121 struct gpiobus_attach_args gba; 122 const struct sysctlnode *node; 123 int i; 124 int error = 0; 125 126 sc->sc_dev = self; 127 128 printf("%s", device_xname(sc->sc_dev)); 129 130 /* initialize pin array */ 131 for (i = 0; i < GPIOSIM_NPINS; i++) { 132 sc->sc_gpio_pins[i].pin_num = i; 133 sc->sc_gpio_pins[i].pin_caps = GPIO_PIN_INPUT | 134 GPIO_PIN_OUTPUT | GPIO_PIN_OPENDRAIN | 135 GPIO_PIN_PULLUP | GPIO_PIN_PULLDOWN | 136 GPIO_PIN_INVIN | GPIO_PIN_INVOUT; 137 138 /* Set up what interrupt types are allowed */ 139 sc->sc_gpio_pins[i].pin_intrcaps = 140 GPIO_INTR_POS_EDGE | 141 GPIO_INTR_NEG_EDGE | 142 GPIO_INTR_DOUBLE_EDGE | 143 GPIO_INTR_HIGH_LEVEL | 144 GPIO_INTR_LOW_LEVEL | 145 GPIO_INTR_MPSAFE; 146 sc->sc_gpio_irqs[i].sc_gpio_irqfunc = NULL; 147 sc->sc_gpio_irqs[i].sc_gpio_irqarg = NULL; 148 sc->sc_gpio_irqs[i].sc_gpio_irqmode = 0; 149 sc->sc_gpio_irqs[i].sc_gpio_irqtriggered = false; 150 151 /* read initial state */ 152 sc->sc_gpio_pins[i].pin_flags = GPIO_PIN_INPUT; 153 } 154 155 sc->sc_state = 0; 156 sc->sc_ms = GPIOSIM_MS; 157 sc->sc_co_init = false; 158 159 mutex_init(&sc->sc_intr_mutex, MUTEX_DEFAULT, IPL_VM); 160 161 /* create controller tag */ 162 sc->sc_gpio_gc.gp_cookie = sc; 163 sc->sc_gpio_gc.gp_pin_read = gpiosim_pin_read; 164 sc->sc_gpio_gc.gp_pin_write = gpiosim_pin_write; 165 sc->sc_gpio_gc.gp_pin_ctl = gpiosim_pin_ctl; 166 sc->sc_gpio_gc.gp_intr_establish = gpiosim_intr_establish; 167 sc->sc_gpio_gc.gp_intr_disestablish = gpiosim_intr_disestablish; 168 sc->sc_gpio_gc.gp_intr_str = gpiosim_gpio_intrstr; 169 170 /* gba.gba_name = "gpio"; */ 171 gba.gba_gc = &sc->sc_gpio_gc; 172 gba.gba_pins = sc->sc_gpio_pins; 173 gba.gba_npins = GPIOSIM_NPINS; 174 175 if (!pmf_device_register(self, NULL, NULL)) 176 aprint_error_dev(self, "couldn't establish power handler\n"); 177 178 sysctl_createv(&sc->sc_log, 0, NULL, &node, 179 0, 180 CTLTYPE_NODE, device_xname(sc->sc_dev), 181 SYSCTL_DESCR("GPIO simulator"), 182 NULL, 0, NULL, 0, 183 CTL_HW, CTL_CREATE, CTL_EOL); 184 185 if (node == NULL) { 186 aprint_error(": can't create sysctl node\n"); 187 return; 188 } 189 190 sysctl_createv(&sc->sc_log, 0, &node, NULL, 191 CTLFLAG_READWRITE, 192 CTLTYPE_QUAD, "value", 193 SYSCTL_DESCR("Current GPIO simulator value"), 194 gpiosim_sysctl, 0, (void *)sc, 0, 195 CTL_CREATE, CTL_EOL); 196 197 sysctl_createv(&sc->sc_log, 0, &node, NULL, 198 CTLFLAG_READWRITE, 199 CTLTYPE_INT, "ms", 200 SYSCTL_DESCR("Number of ms for level interrupts"), 201 gpiosim_ms_sysctl, 0, &sc->sc_ms, 0, 202 CTL_CREATE, CTL_EOL); 203 204 error = workqueue_create(&sc->sc_wq, 205 "gsimwq", 206 gpiosim_wq, 207 sc, 208 PRI_NONE, 209 IPL_VM, 210 WQ_MPSAFE); 211 if (error != 0) { 212 aprint_error(": can't create workqueue for interrupts\n"); 213 return; 214 } 215 216 callout_init(&sc->sc_co, CALLOUT_MPSAFE); 217 callout_setfunc(&sc->sc_co, gpiosim_co, sc); 218 sc->sc_co_running = false; 219 sc->sc_co_init = true; 220 221 aprint_normal(": simulating %d pins\n", GPIOSIM_NPINS); 222 sc->sc_gdev = config_found(self, &gba, gpiobus_print, CFARGS_NONE); 223 } 224 225 static int 226 gpiosim_detach(device_t self, int flags) 227 { 228 struct gpiosim_softc *sc = device_private(self); 229 int error; 230 231 /* Detach the gpio driver that attached here */ 232 error = config_detach_children(self, flags); 233 if (error) 234 return error; 235 236 pmf_device_deregister(self); 237 238 if (sc->sc_log != NULL) { 239 sysctl_teardown(&sc->sc_log); 240 sc->sc_log = NULL; 241 } 242 243 /* Destroy the workqueue, hope that it is empty */ 244 if (sc->sc_wq != NULL) { 245 workqueue_destroy(sc->sc_wq); 246 } 247 248 sc->sc_co_running = false; 249 250 /* Destroy any callouts */ 251 if (sc->sc_co_init) { 252 callout_halt(&sc->sc_co, NULL); 253 callout_destroy(&sc->sc_co); 254 } 255 return 0; 256 } 257 258 static int 259 gpiosim_sysctl(SYSCTLFN_ARGS) 260 { 261 struct sysctlnode node; 262 struct gpiosim_softc *sc; 263 uint64_t val, error; 264 uint64_t previous_val; 265 int i; 266 struct gpiosim_irq *irq; 267 int t = 0; 268 269 node = *rnode; 270 sc = node.sysctl_data; 271 272 node.sysctl_data = &val; 273 274 val = sc->sc_state; 275 error = sysctl_lookup(SYSCTLFN_CALL(&node)); 276 if (error || newp == NULL) 277 return error; 278 279 mutex_enter(&sc->sc_intr_mutex); 280 previous_val = sc->sc_state; 281 sc->sc_state = val; 282 for (i = 0; i < GPIOSIM_NPINS; i++) { 283 irq = &sc->sc_gpio_irqs[i]; 284 /* Simulate edge interrupts ... */ 285 if ((previous_val & (1LL << i)) == 0 && (sc->sc_state & (1LL << i)) && 286 irq->sc_gpio_irqfunc != NULL && 287 (irq->sc_gpio_irqmode & (GPIO_INTR_POS_EDGE | GPIO_INTR_DOUBLE_EDGE))) { 288 irq->sc_gpio_irqtriggered = true; 289 t++; 290 } 291 if ((previous_val & (1LL << i)) && (sc->sc_state & (1LL << i)) == 0 && 292 irq->sc_gpio_irqfunc != NULL && 293 (irq->sc_gpio_irqmode & (GPIO_INTR_NEG_EDGE | GPIO_INTR_DOUBLE_EDGE))) { 294 irq->sc_gpio_irqtriggered = true; 295 t++; 296 } 297 /* Simulate level interrupts ... */ 298 if ((sc->sc_state & (1LL << i)) && irq->sc_gpio_irqfunc != NULL && 299 (irq->sc_gpio_irqmode & GPIO_INTR_HIGH_LEVEL)) { 300 irq->sc_gpio_irqtriggered = true; 301 } 302 if ((sc->sc_state & (1LL << i)) == 0 && irq->sc_gpio_irqfunc != NULL && 303 (irq->sc_gpio_irqmode & GPIO_INTR_LOW_LEVEL)) { 304 irq->sc_gpio_irqtriggered = true; 305 } 306 if ((sc->sc_state & (1LL << i)) && irq->sc_gpio_irqfunc != NULL && 307 (irq->sc_gpio_irqmode & GPIO_INTR_LOW_LEVEL)) { 308 irq->sc_gpio_irqtriggered = false; 309 } 310 if ((sc->sc_state & (1LL << i)) == 0 && irq->sc_gpio_irqfunc != NULL && 311 (irq->sc_gpio_irqmode & GPIO_INTR_HIGH_LEVEL)) { 312 irq->sc_gpio_irqtriggered = false; 313 } 314 } 315 mutex_exit(&sc->sc_intr_mutex); 316 317 if (t > 0) { 318 workqueue_enqueue(sc->sc_wq, (struct work *)&gpiosim_work, NULL); 319 } 320 321 return 0; 322 } 323 324 int 325 gpiosim_ms_sysctl(SYSCTLFN_ARGS) 326 { 327 int error, t; 328 struct sysctlnode node; 329 330 node = *rnode; 331 t = *(int*)rnode->sysctl_data; 332 node.sysctl_data = &t; 333 error = sysctl_lookup(SYSCTLFN_CALL(&node)); 334 if (error || newp == NULL) 335 return (error); 336 337 /* Make sure that this can not be zero */ 338 if (t < 1) 339 return (EINVAL); 340 341 *(int*)rnode->sysctl_data = t; 342 343 return (0); 344 } 345 346 /* Interrupts though the read and write path are not simulated, 347 * that is, an interrupt on the setting of an output or an 348 * interrupt on a pin read. It is not at all clear that it makes 349 * any sense to do any of that, although real hardware in some cases 350 * might trigger an interrupt on an output pin. 351 */ 352 353 static int 354 gpiosim_pin_read(void *arg, int pin) 355 { 356 struct gpiosim_softc *sc = arg; 357 358 if (sc->sc_state & (1LL << pin)) 359 return GPIO_PIN_HIGH; 360 else 361 return GPIO_PIN_LOW; 362 } 363 364 static void 365 gpiosim_pin_write(void *arg, int pin, int value) 366 { 367 struct gpiosim_softc *sc = arg; 368 369 if (value == 0) 370 sc->sc_state &= ~(1LL << pin); 371 else 372 sc->sc_state |= (1LL << pin); 373 } 374 375 static void 376 gpiosim_pin_ctl(void *arg, int pin, int flags) 377 { 378 struct gpiosim_softc *sc = arg; 379 380 sc->sc_gpio_pins[pin].pin_flags = flags; 381 } 382 383 static void * 384 gpiosim_intr_establish(void *vsc, int pin, int ipl, int irqmode, 385 int (*func)(void *), void *arg) 386 { 387 struct gpiosim_softc * const sc = vsc; 388 struct gpiosim_irq *irq; 389 390 mutex_enter(&sc->sc_intr_mutex); 391 irq = &sc->sc_gpio_irqs[pin]; 392 irq->sc_gpio_irqfunc = func; 393 irq->sc_gpio_irqmode = irqmode; 394 irq->sc_gpio_irqarg = arg; 395 396 /* The first level interrupt starts the callout if it is not running */ 397 if (((irqmode & GPIO_INTR_HIGH_LEVEL) || 398 (irqmode & GPIO_INTR_LOW_LEVEL)) && 399 (sc->sc_co_running == false)) { 400 callout_schedule(&sc->sc_co, mstohz(sc->sc_ms)); 401 sc->sc_co_running = true; 402 } 403 404 /* Level interrupts can start as soon as a IRQ handler is installed */ 405 if (((irqmode & GPIO_INTR_HIGH_LEVEL) && (sc->sc_state & (1LL << pin))) || 406 ((irqmode & GPIO_INTR_LOW_LEVEL) && ((sc->sc_state & (1LL << pin)) == 0))) { 407 irq->sc_gpio_irqtriggered = true; 408 } 409 410 mutex_exit(&sc->sc_intr_mutex); 411 412 return(irq); 413 } 414 415 static void 416 gpiosim_intr_disestablish(void *vsc, void *ih) 417 { 418 struct gpiosim_softc * const sc = vsc; 419 struct gpiosim_irq *irq = ih; 420 struct gpiosim_irq *lirq; 421 int i; 422 bool has_level = false; 423 424 mutex_enter(&sc->sc_intr_mutex); 425 irq->sc_gpio_irqfunc = NULL; 426 irq->sc_gpio_irqmode = 0; 427 irq->sc_gpio_irqarg = NULL; 428 irq->sc_gpio_irqtriggered = false; 429 430 /* Check for any level interrupts and stop the callout 431 * if there are none. 432 */ 433 for (i = 0;i < GPIOSIM_NPINS; i++) { 434 lirq = &sc->sc_gpio_irqs[i]; 435 if (lirq->sc_gpio_irqmode & (GPIO_INTR_HIGH_LEVEL | GPIO_INTR_LOW_LEVEL)) { 436 has_level = true; 437 break; 438 } 439 } 440 if (has_level == false) { 441 sc->sc_co_running = false; 442 } 443 mutex_exit(&sc->sc_intr_mutex); 444 } 445 446 static bool 447 gpiosim_gpio_intrstr(void *vsc, int pin, int irqmode, char *buf, size_t buflen) 448 { 449 450 if (pin < 0 || pin >= GPIOSIM_NPINS) 451 return (false); 452 453 snprintf(buf, buflen, "GPIO %d", pin); 454 455 return (true); 456 } 457 458 /* The workqueue handles edge the simulation of edge interrupts */ 459 void 460 gpiosim_wq(struct work *wk, void *arg) 461 { 462 struct gpiosim_softc *sc = arg; 463 struct gpiosim_irq *irq; 464 int i; 465 466 mutex_enter(&sc->sc_intr_mutex); 467 for (i = 0; i < GPIOSIM_NPINS; i++) { 468 irq = &sc->sc_gpio_irqs[i]; 469 if (irq->sc_gpio_irqtriggered && 470 irq->sc_gpio_irqfunc != NULL && 471 (irq->sc_gpio_irqmode & (GPIO_INTR_POS_EDGE | GPIO_INTR_NEG_EDGE | GPIO_INTR_DOUBLE_EDGE))) { 472 (*irq->sc_gpio_irqfunc)(irq->sc_gpio_irqarg); 473 irq->sc_gpio_irqtriggered = false; 474 } 475 } 476 mutex_exit(&sc->sc_intr_mutex); 477 } 478 479 /* This runs as long as there are level interrupts to simulate */ 480 void 481 gpiosim_co(void *arg) 482 { 483 struct gpiosim_softc *sc = arg; 484 struct gpiosim_irq *irq; 485 int i; 486 487 mutex_enter(&sc->sc_intr_mutex); 488 for (i = 0; i < GPIOSIM_NPINS; i++) { 489 irq = &sc->sc_gpio_irqs[i]; 490 if (irq->sc_gpio_irqtriggered && 491 irq->sc_gpio_irqfunc != NULL && 492 (irq->sc_gpio_irqmode & (GPIO_INTR_HIGH_LEVEL | GPIO_INTR_LOW_LEVEL))) { 493 (*irq->sc_gpio_irqfunc)(irq->sc_gpio_irqarg); 494 } 495 } 496 mutex_exit(&sc->sc_intr_mutex); 497 498 if (sc->sc_co_running == true) { 499 callout_schedule(&sc->sc_co, mstohz(sc->sc_ms)); 500 } 501 } 502 503 504 MODULE(MODULE_CLASS_DRIVER, gpiosim, "gpio"); 505 506 #ifdef _MODULE 507 static const struct cfiattrdata gpiobus_iattrdata = { 508 "gpiobus", 0, { { NULL, NULL, 0 }, } 509 }; 510 static const struct cfiattrdata *const gpiosim_attrs[] = { 511 &gpiobus_iattrdata, NULL 512 }; 513 CFDRIVER_DECL(gpiosim, DV_DULL, gpiosim_attrs); 514 extern struct cfattach gpiosim_ca; 515 static int gpiosimloc[] = { 516 -1, 517 -1, 518 -1 519 }; 520 static struct cfdata gpiosim_cfdata[] = { 521 { 522 .cf_name = "gpiosim", 523 .cf_atname = "gpiosim", 524 .cf_unit = 0, 525 .cf_fstate = FSTATE_STAR, 526 .cf_loc = gpiosimloc, 527 .cf_flags = 0, 528 .cf_pspec = NULL, 529 }, 530 { NULL, NULL, 0, FSTATE_NOTFOUND, NULL, 0, NULL } 531 }; 532 #endif 533 534 static int 535 gpiosim_modcmd(modcmd_t cmd, void *opaque) 536 { 537 #ifdef _MODULE 538 int error = 0; 539 #endif 540 switch (cmd) { 541 case MODULE_CMD_INIT: 542 #ifdef _MODULE 543 error = config_cfdriver_attach(&gpiosim_cd); 544 if (error) 545 return error; 546 547 error = config_cfattach_attach(gpiosim_cd.cd_name, 548 &gpiosim_ca); 549 if (error) { 550 config_cfdriver_detach(&gpiosim_cd); 551 aprint_error("%s: unable to register cfattach\n", 552 gpiosim_cd.cd_name); 553 return error; 554 } 555 error = config_cfdata_attach(gpiosim_cfdata, 1); 556 if (error) { 557 config_cfattach_detach(gpiosim_cd.cd_name, 558 &gpiosim_ca); 559 config_cfdriver_detach(&gpiosim_cd); 560 aprint_error("%s: unable to register cfdata\n", 561 gpiosim_cd.cd_name); 562 return error; 563 } 564 config_attach_pseudo(gpiosim_cfdata); 565 #endif 566 return 0; 567 case MODULE_CMD_FINI: 568 #ifdef _MODULE 569 error = config_cfdata_detach(gpiosim_cfdata); 570 if (error) 571 return error; 572 573 config_cfattach_detach(gpiosim_cd.cd_name, &gpiosim_ca); 574 config_cfdriver_detach(&gpiosim_cd); 575 #endif 576 return 0; 577 case MODULE_CMD_AUTOUNLOAD: 578 /* no auto-unload */ 579 return EBUSY; 580 default: 581 return ENOTTY; 582 } 583 } 584