1 /* 2 * Copyright (c) 2009 The DragonFly Project. All rights reserved. 3 * 4 * This code is derived from software contributed to The DragonFly Project 5 * by Alex Hornung <ahornung@gmail.com> 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 11 * 1. Redistributions of source code must retain the above copyright 12 * notice, this list of conditions and the following disclaimer. 13 * 2. Redistributions in binary form must reproduce the above copyright 14 * notice, this list of conditions and the following disclaimer in 15 * the documentation and/or other materials provided with the 16 * distribution. 17 * 3. Neither the name of The DragonFly Project nor the names of its 18 * contributors may be used to endorse or promote products derived 19 * from this software without specific, prior written permission. 20 * 21 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 22 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 23 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 24 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE 25 * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 26 * INCIDENTAL, SPECIAL, EXEMPLARY OR CONSEQUENTIAL DAMAGES (INCLUDING, 27 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 28 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED 29 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 30 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT 31 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 32 * SUCH DAMAGE. 33 * 34 * 35 * Copyright (c) 2008 Marc Balmer <mbalmer@openbsd.org> 36 * Copyright (c) 2004, 2006 Alexander Yurchenko <grange@openbsd.org> 37 * 38 * Permission to use, copy, modify, and distribute this software for any 39 * purpose with or without fee is hereby granted, provided that the above 40 * copyright notice and this permission notice appear in all copies. 41 * 42 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 43 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 44 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 45 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 46 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 47 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 48 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 49 */ 50 /* 51 * XXX: consumer_detach stuff. 52 * XXX: userland stuff. 53 */ 54 55 #include <sys/param.h> 56 #include <sys/conf.h> 57 #include <sys/kernel.h> 58 #include <sys/systm.h> 59 #include <sys/limits.h> 60 #include <sys/thread.h> 61 #include <sys/thread2.h> 62 #include <sys/malloc.h> 63 #include <sys/ctype.h> 64 #include <sys/sbuf.h> 65 #include <sys/queue.h> 66 #include <sys/uio.h> 67 #include <sys/lock.h> 68 #include <dev/misc/gpio/gpio.h> 69 #include <sys/devfs.h> 70 71 struct gpio_driver { 72 char *name; 73 struct devfs_bitmap unit_bitmap; 74 LIST_ENTRY(gpio_driver) link; 75 }; 76 77 static LIST_HEAD(, gpio_consumer) gpio_conslist = LIST_HEAD_INITIALIZER(&gpio_conslist); 78 static LIST_HEAD(, gpio_driver) gpio_driverlist = LIST_HEAD_INITIALIZER(&gpio_driverlist); 79 DEVFS_DEFINE_CLONE_BITMAP(gpio); 80 static struct lock gpio_lock; 81 static struct lock gpiodev_lock; 82 83 void 84 gpio_consumer_register(struct gpio_consumer *gcp) 85 { 86 lockmgr(&gpio_lock, LK_EXCLUSIVE); 87 LIST_INSERT_HEAD(&gpio_conslist, gcp, link); 88 lockmgr(&gpio_lock, LK_RELEASE); 89 } 90 91 void 92 gpio_consumer_unregister(struct gpio_consumer *gcp) 93 { 94 lockmgr(&gpio_lock, LK_EXCLUSIVE); 95 LIST_REMOVE(gcp, link); 96 lockmgr(&gpio_lock, LK_RELEASE); 97 } 98 99 int 100 gpio_consumer_attach(const char *consumer, void *arg, struct gpio *gp, 101 int pin, u_int32_t mask) 102 { 103 struct gpio_consumer *gcp; 104 int error = -1; 105 int locked = 0; 106 107 /* Check if it is locked already. if not, we acquire the lock */ 108 if ((lockstatus(&gpio_lock, curthread)) != LK_EXCLUSIVE) { 109 lockmgr(&gpio_lock, LK_EXCLUSIVE); 110 locked = 1; 111 } 112 113 LIST_FOREACH(gcp, &gpio_conslist, link) { 114 if (strcmp(gcp->consumer_name, consumer) != 0) 115 continue; 116 117 if (gcp->consumer_attach) 118 error = gcp->consumer_attach(gp, arg, pin, mask); 119 if (error) { 120 kprintf("gpio: Attach of consumer %s to gpio %s%d pin %d failed " 121 "(consumer error %d)\n", consumer, gp->driver_name, 122 gp->driver_unit, pin, error); 123 goto end; 124 } 125 126 kprintf("gpio: Attached consumer %s to gpio %s%d pin %d\n", 127 consumer, gp->driver_name, gp->driver_unit, pin); 128 goto end; 129 } 130 131 kprintf("gpio: Attach of consumer %s to gpio %s%d pin %d failed " 132 "(unknown consumer)\n", consumer, gp->driver_name, gp->driver_unit, pin); 133 134 end: 135 /* If we acquired the lock, we also get rid of it */ 136 if (locked) 137 lockmgr(&gpio_lock, LK_RELEASE); 138 return error; 139 } 140 141 int 142 gpio_consumer_detach(const char *consumer, struct gpio *gp, 143 int pin) 144 { 145 struct gpio_consumer *gcp; 146 int error = -1; 147 int locked = 0; 148 149 /* Check if it is locked already. if not, we acquire the lock */ 150 if ((lockstatus(&gpio_lock, curthread)) != LK_EXCLUSIVE) { 151 lockmgr(&gpio_lock, LK_EXCLUSIVE); 152 locked = 1; 153 } 154 155 LIST_FOREACH(gcp, &gpio_conslist, link) { 156 if (strcmp(gcp->consumer_name, consumer) != 0) 157 continue; 158 159 if (gcp->consumer_detach) 160 error = gcp->consumer_detach(gp, NULL, pin); 161 if (error) { 162 kprintf("gpio: Detach of consumer %s from gpio %s%d pin %d failed " 163 "(consumer error %d)\n", consumer, gp->driver_name, 164 gp->driver_unit, pin, error); 165 goto end; 166 } 167 168 kprintf("gpio: Detached consumer %s from gpio %s%d pin %d\n", 169 consumer, gp->driver_name, gp->driver_unit, pin); 170 goto end; 171 } 172 173 kprintf("gpio: Detach of consumer %s from gpio %s%d pin %d failed " 174 "(unknown consumer)\n", consumer, gp->driver_name, gp->driver_unit, pin); 175 176 end: 177 /* If we acquired the lock, we also get rid of it */ 178 if (locked) 179 lockmgr(&gpio_lock, LK_RELEASE); 180 return error; 181 } 182 183 struct gpio_mapping * 184 gpio_map(struct gpio *gp, int *map, int offset, u_int32_t mask) 185 { 186 struct gpio_mapping *gmp; 187 int npins, pin, i; 188 int locked = 0; 189 190 npins = gpio_npins(mask); 191 if (npins > gp->npins) 192 return NULL; 193 if (npins == 0) 194 return NULL; 195 196 /* Check if it is locked already. if not, we acquire the lock */ 197 if ((lockstatus(&gpio_lock, curthread)) != LK_EXCLUSIVE) { 198 lockmgr(&gpio_lock, LK_EXCLUSIVE); 199 locked = 1; 200 } 201 202 gmp = kmalloc(sizeof(struct gpio_mapping), M_TEMP, M_WAITOK); 203 gmp->gp = gp; 204 if (map) { 205 gmp->map = map; 206 gmp->map_alloced = 0; 207 } else { 208 gmp->map = kmalloc(sizeof(int) * npins, M_TEMP, M_WAITOK); 209 gmp->map_alloced = 1; 210 } 211 212 for (npins = 0, i = 0; i < 32; i++) 213 if (mask & (1 << i)) { 214 pin = offset + i; 215 if (pin < 0 || pin >= gp->npins || 216 gp->pins[pin].pin_mapped || gp->pins[pin].pin_opened) { 217 if (map == NULL) 218 kfree(gmp->map, M_TEMP); 219 kfree(gmp, M_TEMP); 220 /* If we acquired the lock, we also get rid of it */ 221 if (locked) 222 lockmgr(&gpio_lock, LK_RELEASE); 223 return NULL; 224 } 225 gp->pins[pin].pin_mapped = 1; 226 gmp->map[npins++] = pin; 227 } 228 gmp->size = npins; 229 230 /* If we acquired the lock, we also get rid of it */ 231 if (locked) 232 lockmgr(&gpio_lock, LK_RELEASE); 233 234 return gmp; 235 } 236 237 void 238 gpio_unmap(struct gpio_mapping *gmp) 239 { 240 int pin, i; 241 int locked = 0; 242 243 /* Check if it is locked already. if not, we acquire the lock */ 244 if ((lockstatus(&gpio_lock, curthread)) != LK_EXCLUSIVE) { 245 lockmgr(&gpio_lock, LK_EXCLUSIVE); 246 locked = 1; 247 } 248 249 for (i = 0; i < gmp->size; i++) { 250 pin = gmp->map[i]; 251 gmp->gp->pins[pin].pin_mapped = 0; 252 } 253 254 if (gmp->map_alloced) 255 kfree(gmp->map, M_TEMP); 256 kfree(gmp, M_TEMP); 257 258 /* If we acquired the lock, we also get rid of it */ 259 if (locked) 260 lockmgr(&gpio_lock, LK_RELEASE); 261 } 262 263 int 264 gpio_npins(u_int32_t mask) 265 { 266 int npins, i; 267 268 for (npins = 0, i = 0; i < 32; i++) 269 if (mask & (1 << i)) 270 npins++; 271 272 return (npins); 273 } 274 275 int 276 gpio_pin_read(struct gpio *gp, struct gpio_mapping *map, int pin) 277 { 278 return gp->pin_read(gp->arg, map->map[pin]); 279 } 280 281 void 282 gpio_pin_write(struct gpio *gp, struct gpio_mapping *map, int pin, int data) 283 { 284 gp->pin_write(gp->arg, map->map[pin], data); 285 } 286 287 void 288 gpio_pin_ctl(struct gpio *gp, struct gpio_mapping *map, int pin, int flags) 289 { 290 gp->pin_ctl(gp->arg, map->map[pin], flags); 291 } 292 293 int 294 gpio_pin_caps(struct gpio *gp, struct gpio_mapping *map, int pin) 295 { 296 return (gp->pins[map->map[pin]].pin_caps); 297 } 298 299 static int 300 gpio_open(struct dev_open_args *ap) 301 { 302 gpio_pin_t *pin; 303 cdev_t dev; 304 305 lockmgr(&gpiodev_lock, LK_EXCLUSIVE); 306 dev = ap->a_head.a_dev; 307 pin = dev->si_drv2; 308 309 if (pin->pin_opened || pin->pin_mapped) { 310 lockmgr(&gpiodev_lock, LK_RELEASE); 311 return EBUSY; 312 } 313 314 pin->pin_opened = 1; 315 lockmgr(&gpiodev_lock, LK_RELEASE); 316 317 return 0; 318 } 319 320 static int 321 gpio_close(struct dev_close_args *ap) 322 { 323 gpio_pin_t *pin; 324 cdev_t dev; 325 326 lockmgr(&gpiodev_lock, LK_EXCLUSIVE); 327 dev = ap->a_head.a_dev; 328 pin = dev->si_drv2; 329 330 if (pin->pin_opened) 331 pin->pin_opened = 0; 332 lockmgr(&gpiodev_lock, LK_RELEASE); 333 334 return 0; 335 } 336 337 static int 338 gpio_write(struct dev_write_args *ap) 339 { 340 struct gpio *gp; 341 gpio_pin_t *pin; 342 cdev_t dev; 343 int error; 344 int data = 0; 345 346 dev = ap->a_head.a_dev; 347 gp = dev->si_drv1; 348 pin = dev->si_drv2; 349 350 if (ap->a_uio->uio_resid > sizeof(int)) 351 return EINVAL; 352 353 error = uiomove((void *)&data, ap->a_uio->uio_resid, ap->a_uio); 354 if (error) 355 return error; 356 357 if (data != GPIO_PIN_LOW && data != GPIO_PIN_HIGH) 358 return EINVAL; 359 360 lockmgr(&gpiodev_lock, LK_EXCLUSIVE); 361 gp->pin_write(gp->arg, pin->pin_num, data); 362 pin->pin_state = data; 363 lockmgr(&gpiodev_lock, LK_RELEASE); 364 365 return 0; 366 } 367 368 static int 369 gpio_read(struct dev_read_args *ap) 370 { 371 struct gpio *gp; 372 gpio_pin_t *pin; 373 cdev_t dev; 374 int error; 375 int data = 0; 376 377 dev = ap->a_head.a_dev; 378 gp = dev->si_drv1; 379 pin = dev->si_drv2; 380 381 if (ap->a_uio->uio_resid < sizeof(char)) 382 return EINVAL; 383 384 lockmgr(&gpiodev_lock, LK_EXCLUSIVE); 385 data = gp->pin_read(gp->arg, pin->pin_num); 386 lockmgr(&gpiodev_lock, LK_RELEASE); 387 388 error = uiomove((void *)&data, 389 (ap->a_uio->uio_resid > sizeof(int))?(sizeof(int)):(ap->a_uio->uio_resid), 390 ap->a_uio); 391 392 return error; 393 } 394 395 static int 396 gpio_ioctl(struct dev_ioctl_args *ap) 397 { 398 struct gpio_pin_set_args *gpsa; 399 struct gpio *gp; 400 gpio_pin_t *pin; 401 cdev_t dev; 402 int error; 403 404 dev = ap->a_head.a_dev; 405 gpsa = (struct gpio_pin_set_args *)ap->a_data; 406 gp = dev->si_drv1; 407 pin = dev->si_drv2; 408 error = 0; 409 410 lockmgr(&gpiodev_lock, LK_EXCLUSIVE); 411 412 switch(ap->a_cmd) { 413 case GPIOPINSET: 414 if (pin->pin_opened || pin->pin_mapped) { 415 error = EBUSY; 416 break; 417 } 418 419 gpsa->caps = pin->pin_caps; 420 gpsa->flags = pin->pin_flags; 421 422 if ((gpsa->flags & pin->pin_caps) != gpsa->flags) { 423 error = ENODEV; 424 break; 425 } 426 427 if (gpsa->flags > 0) { 428 gp->pin_ctl(gp->arg, pin->pin_num, gpsa->flags); 429 pin->pin_flags = gpsa->flags | GPIO_PIN_SET; 430 } 431 break; 432 433 case GPIOPINUNSET: 434 error = EINVAL; 435 break; 436 437 default: 438 error = EINVAL; 439 break; 440 } 441 lockmgr(&gpiodev_lock, LK_RELEASE); 442 443 return error; 444 } 445 446 static int 447 gpio_master_ioctl(struct dev_ioctl_args *ap) 448 { 449 struct gpio_pin_set_args *gpsa; 450 struct gpio_info *gpi; 451 struct gpio_attach_args *gpaa; 452 struct gpio *gp; 453 cdev_t dev; 454 gpio_pin_t *pin; 455 int error = 0; 456 457 dev = ap->a_head.a_dev; 458 gp = dev->si_drv1; 459 460 lockmgr(&gpiodev_lock, LK_EXCLUSIVE); 461 462 switch(ap->a_cmd) { 463 case GPIOINFO: 464 gpi = (struct gpio_info *)ap->a_data; 465 gpi->npins = gp->npins; 466 if (gpi->pins != NULL) { 467 error = copyout(gp->pins, gpi->pins, 468 sizeof(struct gpio_pin)*gp->npins); 469 } 470 break; 471 472 case GPIOATTACH: 473 gpaa = (struct gpio_attach_args *)ap->a_data; 474 error = gpio_consumer_attach(gpaa->consumer_name, 475 (gpaa->arg_type == GPIO_TYPE_INT)? 476 ((void *)gpaa->consumer_arg.lint): 477 (gpaa->consumer_arg.string), 478 gp, gpaa->pin_offset, gpaa->pin_mask); 479 break; 480 481 case GPIODETACH: 482 gpaa = (struct gpio_attach_args *)ap->a_data; 483 error = gpio_consumer_detach(gpaa->consumer_name, gp, 484 gpaa->pin_offset); 485 break; 486 487 case GPIOPINSET: 488 gpsa = (struct gpio_pin_set_args *)ap->a_data; 489 if (gpsa->pin < 0 || gpsa->pin >= gp->npins) { 490 error = EINVAL; 491 break; 492 } 493 494 pin = &gp->pins[gpsa->pin]; 495 496 if (pin->pin_opened || pin->pin_mapped) { 497 error = EBUSY; 498 break; 499 } 500 501 gpsa->caps = pin->pin_caps; 502 gpsa->flags = pin->pin_flags; 503 504 if ((gpsa->flags & pin->pin_caps) != gpsa->flags) { 505 error = ENODEV; 506 break; 507 } 508 509 if (gpsa->flags > 0) { 510 gp->pin_ctl(gp->arg, gpsa->pin, gpsa->flags); 511 pin->pin_flags = gpsa->flags | GPIO_PIN_SET; 512 } 513 break; 514 515 case GPIOPINUNSET: 516 gpsa = (struct gpio_pin_set_args *)ap->a_data; 517 error = EINVAL; 518 break; 519 520 default: 521 error = EINVAL; 522 break; 523 } 524 lockmgr(&gpiodev_lock, LK_RELEASE); 525 526 return error; 527 } 528 529 static struct dev_ops gpio_ops = { 530 { "gpio", 0, D_MPSAFE }, 531 .d_open = gpio_open, 532 .d_close = gpio_close, 533 .d_write = gpio_write, 534 .d_read = gpio_read, 535 .d_ioctl = gpio_ioctl, 536 }; 537 538 static struct dev_ops gpio_master_ops = { 539 { "gpio", 0, D_MPSAFE }, 540 .d_ioctl = gpio_master_ioctl, 541 }; 542 543 void 544 gpio_register(struct gpio *gp) 545 { 546 struct gpio_driver *gpd; 547 int i, unit, master_unit = -1; 548 549 KKASSERT(gp->npins > 0); 550 KKASSERT(gp->pins); 551 552 lockmgr(&gpio_lock, LK_EXCLUSIVE); 553 LIST_FOREACH(gpd, &gpio_driverlist, link) { 554 if (strcmp(gpd->name, gp->driver_name) != 0) 555 continue; 556 557 master_unit = devfs_clone_bitmap_get(&gpd->unit_bitmap, 0); 558 break; 559 } 560 if (master_unit == -1) { 561 gpd = kmalloc(sizeof(struct gpio_driver), 562 M_TEMP, M_WAITOK | M_ZERO); 563 gpd->name = kstrdup(gp->driver_name, M_TEMP); 564 devfs_clone_bitmap_init(&gpd->unit_bitmap); 565 master_unit = devfs_clone_bitmap_get(&gpd->unit_bitmap, 0); 566 LIST_INSERT_HEAD(&gpio_driverlist, gpd, link); 567 } 568 lockmgr(&gpio_lock, LK_RELEASE); 569 570 gp->driver_unit = master_unit; 571 kprintf("gpio: GPIO driver %s%d registered, npins = %d\n", 572 gp->driver_name, master_unit, gp->npins); 573 574 unit = devfs_clone_bitmap_get(&DEVFS_CLONE_BITMAP(gpio), 0); 575 gp->master_dev = make_dev(&gpio_master_ops, unit, UID_ROOT, GID_WHEEL, 0600, 576 "gpio/%s%d/master", gp->driver_name, master_unit); 577 gp->master_dev->si_drv1 = gp; 578 579 for (i = 0; i < gp->npins; i++) { 580 unit = devfs_clone_bitmap_get(&DEVFS_CLONE_BITMAP(gpio), 0); 581 gp->pins[i].dev = make_dev(&gpio_ops, unit, UID_ROOT, GID_WHEEL, 0600, 582 "gpio/%s%d/%d", gp->driver_name, master_unit, gp->pins[i].pin_num); 583 gp->pins[i].dev->si_drv1 = gp; 584 gp->pins[i].dev->si_drv2 = &gp->pins[i]; 585 } 586 } 587 588 void 589 gpio_unregister(struct gpio *gp) 590 { 591 struct gpio_driver *gpd; 592 int i; 593 594 KKASSERT(gp->npins > 0); 595 KKASSERT(gp->pins); 596 597 for (i = 0; i < gp->npins; i++) { 598 devfs_clone_bitmap_get(&DEVFS_CLONE_BITMAP(gpio), 599 minor(gp->pins[i].dev)); 600 destroy_dev(gp->pins[i].dev); 601 } 602 603 destroy_dev(gp->master_dev); 604 605 lockmgr(&gpio_lock, LK_EXCLUSIVE); 606 LIST_FOREACH(gpd, &gpio_driverlist, link) { 607 if (strcmp(gpd->name, gp->driver_name) != 0) 608 continue; 609 610 devfs_clone_bitmap_put(&gpd->unit_bitmap, gp->driver_unit); 611 LIST_REMOVE(gpd, link); 612 break; 613 } 614 lockmgr(&gpio_lock, LK_RELEASE); 615 616 kprintf("gpio: GPIO driver %s%d unregistered\n", 617 gp->driver_name, gp->driver_unit); 618 } 619 620 static void 621 gpio_drvinit(void *unused) 622 { 623 lockinit(&gpio_lock, "gpio_lock", 0, 0); 624 lockinit(&gpiodev_lock, "gpiodev_lock", 0, 0); 625 devfs_clone_bitmap_init(&DEVFS_CLONE_BITMAP(gpio)); 626 } 627 628 SYSINIT(gpio, SI_SUB_PRE_DRIVERS, SI_ORDER_FIRST, gpio_drvinit, NULL); 629