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 #include <sys/cdefs.h> 55 56 #include <sys/param.h> 57 #include <sys/conf.h> 58 #include <sys/kernel.h> 59 #include <sys/systm.h> 60 #include <sys/limits.h> 61 #include <sys/thread.h> 62 #include <sys/thread2.h> 63 #include <sys/malloc.h> 64 #include <sys/ctype.h> 65 #include <sys/sbuf.h> 66 #include <sys/queue.h> 67 #include <sys/uio.h> 68 #include <sys/lock.h> 69 #include <sys/ioccom.h> 70 #include <dev/misc/gpio/gpio.h> 71 #include <sys/devfs.h> 72 73 struct gpio_driver { 74 char *name; 75 struct devfs_bitmap unit_bitmap; 76 LIST_ENTRY(gpio_driver) link; 77 }; 78 79 static LIST_HEAD(, gpio_consumer) gpio_conslist = LIST_HEAD_INITIALIZER(&gpio_conslist); 80 static LIST_HEAD(, gpio_driver) gpio_driverlist = LIST_HEAD_INITIALIZER(&gpio_driverlist); 81 DEVFS_DECLARE_CLONE_BITMAP(gpio); 82 static struct lock gpio_lock; 83 84 void 85 gpio_consumer_register(struct gpio_consumer *gcp) 86 { 87 lockmgr(&gpio_lock, LK_EXCLUSIVE); 88 LIST_INSERT_HEAD(&gpio_conslist, gcp, link); 89 lockmgr(&gpio_lock, LK_RELEASE); 90 } 91 92 void 93 gpio_consumer_unregister(struct gpio_consumer *gcp) 94 { 95 lockmgr(&gpio_lock, LK_EXCLUSIVE); 96 LIST_REMOVE(gcp, link); 97 lockmgr(&gpio_lock, LK_RELEASE); 98 } 99 100 int 101 gpio_consumer_attach(const char *consumer, void *arg, struct gpio *gp, 102 int pin, u_int32_t mask) 103 { 104 struct gpio_consumer *gcp; 105 int error = -1; 106 int locked = 0; 107 108 /* Check if it is locked already. if not, we acquire the lock */ 109 if (!(lockstatus(&gpio_lock, curthread)) == LK_EXCLUSIVE) { 110 lockmgr(&gpio_lock, LK_EXCLUSIVE); 111 locked = 1; 112 } 113 114 LIST_FOREACH(gcp, &gpio_conslist, link) { 115 if (strcmp(gcp->consumer_name, consumer) != 0) 116 continue; 117 118 if (gcp->consumer_attach) 119 error = gcp->consumer_attach(gp, arg, pin, mask); 120 if (error) { 121 kprintf("gpio: Attach of consumer %s to gpio %s%d pin %d failed " 122 "(consumer error %d)\n", consumer, gp->driver_name, 123 gp->driver_unit, pin, error); 124 goto end; 125 } 126 127 kprintf("gpio: Attached consumer %s to gpio %s%d pin %d\n", 128 consumer, gp->driver_name, gp->driver_unit, pin); 129 goto end; 130 } 131 132 kprintf("gpio: Attach of consumer %s to gpio %s%d pin %d failed " 133 "(unknown consumer)\n", consumer, gp->driver_name, gp->driver_unit, pin); 134 135 end: 136 /* If we acquired the lock, we also get rid of it */ 137 if (locked) 138 lockmgr(&gpio_lock, LK_RELEASE); 139 return error; 140 } 141 142 int 143 gpio_consumer_detach(const char *consumer, struct gpio *gp, 144 int pin) 145 { 146 struct gpio_consumer *gcp; 147 int error = -1; 148 int locked = 0; 149 150 /* Check if it is locked already. if not, we acquire the lock */ 151 if (!(lockstatus(&gpio_lock, curthread)) == LK_EXCLUSIVE) { 152 lockmgr(&gpio_lock, LK_EXCLUSIVE); 153 locked = 1; 154 } 155 156 LIST_FOREACH(gcp, &gpio_conslist, link) { 157 if (strcmp(gcp->consumer_name, consumer) != 0) 158 continue; 159 160 if (gcp->consumer_detach) 161 error = gcp->consumer_detach(gp, NULL, pin); 162 if (error) { 163 kprintf("gpio: Detach of consumer %s from gpio %s%d pin %d failed " 164 "(consumer error %d)\n", consumer, gp->driver_name, 165 gp->driver_unit, pin, error); 166 goto end; 167 } 168 169 kprintf("gpio: Detached consumer %s from gpio %s%d pin %d\n", 170 consumer, gp->driver_name, gp->driver_unit, pin); 171 goto end; 172 } 173 174 kprintf("gpio: Detach of consumer %s from gpio %s%d pin %d failed " 175 "(unknown consumer)\n", consumer, gp->driver_name, gp->driver_unit, pin); 176 177 end: 178 /* If we acquired the lock, we also get rid of it */ 179 if (locked) 180 lockmgr(&gpio_lock, LK_RELEASE); 181 return error; 182 } 183 184 struct gpio_mapping * 185 gpio_map(struct gpio *gp, int *map, int offset, u_int32_t mask) 186 { 187 struct gpio_mapping *gmp; 188 int npins, pin, i; 189 int locked = 0; 190 191 npins = gpio_npins(mask); 192 if (npins > gp->npins) 193 return NULL; 194 if (npins == 0) 195 return NULL; 196 197 /* Check if it is locked already. if not, we acquire the lock */ 198 if (!(lockstatus(&gpio_lock, curthread)) == LK_EXCLUSIVE) { 199 lockmgr(&gpio_lock, LK_EXCLUSIVE); 200 locked = 1; 201 } 202 203 gmp = kmalloc(sizeof(struct gpio_mapping), M_TEMP, M_WAITOK); 204 gmp->gp = gp; 205 if (map) { 206 gmp->map = map; 207 gmp->map_alloced = 0; 208 } else { 209 gmp->map = kmalloc(sizeof(int) * npins, M_TEMP, M_WAITOK); 210 gmp->map_alloced = 1; 211 } 212 213 for (npins = 0, i = 0; i < 32; i++) 214 if (mask & (1 << i)) { 215 pin = offset + i; 216 if (pin < 0 || pin >= gp->npins || 217 gp->pins[pin].pin_mapped || gp->pins[pin].pin_opened) { 218 if (map == NULL) 219 kfree(gmp->map, M_TEMP); 220 kfree(gmp, M_TEMP); 221 /* If we acquired the lock, we also get rid of it */ 222 if (locked) 223 lockmgr(&gpio_lock, LK_RELEASE); 224 return NULL; 225 } 226 gp->pins[pin].pin_mapped = 1; 227 gmp->map[npins++] = pin; 228 } 229 gmp->size = npins; 230 231 /* If we acquired the lock, we also get rid of it */ 232 if (locked) 233 lockmgr(&gpio_lock, LK_RELEASE); 234 235 return gmp; 236 } 237 238 void 239 gpio_unmap(struct gpio_mapping *gmp) 240 { 241 int pin, i; 242 int locked = 0; 243 244 /* Check if it is locked already. if not, we acquire the lock */ 245 if (!(lockstatus(&gpio_lock, curthread)) == LK_EXCLUSIVE) { 246 lockmgr(&gpio_lock, LK_EXCLUSIVE); 247 locked = 1; 248 } 249 250 for (i = 0; i < gmp->size; i++) { 251 pin = gmp->map[i]; 252 gmp->gp->pins[pin].pin_mapped = 0; 253 } 254 255 if (gmp->map_alloced) 256 kfree(gmp->map, M_TEMP); 257 kfree(gmp, M_TEMP); 258 259 /* If we acquired the lock, we also get rid of it */ 260 if (locked) 261 lockmgr(&gpio_lock, LK_RELEASE); 262 } 263 264 int 265 gpio_npins(u_int32_t mask) 266 { 267 int npins, i; 268 269 for (npins = 0, i = 0; i < 32; i++) 270 if (mask & (1 << i)) 271 npins++; 272 273 return (npins); 274 } 275 276 int 277 gpio_pin_read(struct gpio *gp, struct gpio_mapping *map, int pin) 278 { 279 return gp->pin_read(gp->arg, map->map[pin]); 280 } 281 282 void 283 gpio_pin_write(struct gpio *gp, struct gpio_mapping *map, int pin, int data) 284 { 285 return gp->pin_write(gp->arg, map->map[pin], data); 286 } 287 288 void 289 gpio_pin_ctl(struct gpio *gp, struct gpio_mapping *map, int pin, int flags) 290 { 291 return gp->pin_ctl(gp->arg, map->map[pin], flags); 292 } 293 294 int 295 gpio_pin_caps(struct gpio *gp, struct gpio_mapping *map, int pin) 296 { 297 return (gp->pins[map->map[pin]].pin_caps); 298 } 299 300 static int 301 gpio_open(struct dev_open_args *ap) 302 { 303 struct gpio *gp; 304 gpio_pin_t *pin; 305 cdev_t dev; 306 307 dev = ap->a_head.a_dev; 308 gp = dev->si_drv1; 309 pin = dev->si_drv2; 310 311 if (pin->pin_opened || pin->pin_mapped) 312 return EBUSY; 313 314 pin->pin_opened = 1; 315 316 return 0; 317 } 318 319 static int 320 gpio_close(struct dev_close_args *ap) 321 { 322 struct gpio *gp; 323 gpio_pin_t *pin; 324 cdev_t dev; 325 326 dev = ap->a_head.a_dev; 327 gp = dev->si_drv1; 328 pin = dev->si_drv2; 329 330 if (pin->pin_opened) 331 pin->pin_opened = 0; 332 333 return 0; 334 } 335 336 static int 337 gpio_write(struct dev_write_args *ap) 338 { 339 struct gpio *gp; 340 gpio_pin_t *pin; 341 cdev_t dev; 342 int error; 343 int data = 0; 344 345 dev = ap->a_head.a_dev; 346 gp = dev->si_drv1; 347 pin = dev->si_drv2; 348 349 if (ap->a_uio->uio_resid > sizeof(int)) 350 return EINVAL; 351 352 error = uiomove((void *)&data, ap->a_uio->uio_resid, ap->a_uio); 353 if (error) 354 return error; 355 356 if (data != GPIO_PIN_LOW && data != GPIO_PIN_HIGH) 357 return EINVAL; 358 359 gp->pin_write(gp->arg, pin->pin_num, data); 360 pin->pin_state = data; 361 362 return 0; 363 } 364 365 static int 366 gpio_read(struct dev_read_args *ap) 367 { 368 struct gpio *gp; 369 gpio_pin_t *pin; 370 cdev_t dev; 371 int error; 372 int data = 0; 373 374 dev = ap->a_head.a_dev; 375 gp = dev->si_drv1; 376 pin = dev->si_drv2; 377 378 if (ap->a_uio->uio_resid < sizeof(char)) 379 return EINVAL; 380 381 data = gp->pin_read(gp->arg, pin->pin_num); 382 383 error = uiomove((void *)&data, 384 (ap->a_uio->uio_resid > sizeof(int))?(sizeof(int)):(ap->a_uio->uio_resid), 385 ap->a_uio); 386 387 return error; 388 } 389 390 static int 391 gpio_ioctl(struct dev_ioctl_args *ap) 392 { 393 struct gpio_pin_set_args *gpsa; 394 struct gpio *gp; 395 gpio_pin_t *pin; 396 cdev_t dev; 397 int error = 0; 398 399 dev = ap->a_head.a_dev; 400 gp = dev->si_drv1; 401 pin = dev->si_drv2; 402 403 switch(ap->a_cmd) { 404 case GPIOPINSET: 405 gpsa = (struct gpio_pin_set_args *)ap->a_data; 406 if (pin->pin_opened || pin->pin_mapped) 407 return EBUSY; 408 409 gpsa->caps = pin->pin_caps; 410 gpsa->flags = pin->pin_flags; 411 412 if ((gpsa->flags & pin->pin_caps) != gpsa->flags) 413 return ENODEV; 414 415 if (gpsa->flags > 0) { 416 gp->pin_ctl(gp->arg, pin->pin_num, gpsa->flags); 417 pin->pin_flags = gpsa->flags | GPIO_PIN_SET; 418 } 419 break; 420 421 case GPIOPINUNSET: 422 gpsa = (struct gpio_pin_set_args *)ap->a_data; 423 error = EINVAL; 424 break; 425 426 default: 427 return EINVAL; 428 } 429 return 0; 430 } 431 432 static int 433 gpio_master_ioctl(struct dev_ioctl_args *ap) 434 { 435 struct gpio_pin_set_args *gpsa; 436 struct gpio_info *gpi; 437 struct gpio_attach_args *gpaa; 438 struct gpio *gp; 439 cdev_t dev; 440 gpio_pin_t *pin; 441 int error = 0; 442 443 dev = ap->a_head.a_dev; 444 gp = dev->si_drv1; 445 446 switch(ap->a_cmd) { 447 case GPIOINFO: 448 gpi = (struct gpio_info *)ap->a_data; 449 gpi->npins = gp->npins; 450 if (gpi->pins != NULL) { 451 error = copyout(gp->pins, gpi->pins, 452 sizeof(struct gpio_pin)*gp->npins); 453 } 454 break; 455 456 case GPIOATTACH: 457 gpaa = (struct gpio_attach_args *)ap->a_data; 458 error = gpio_consumer_attach(gpaa->consumer_name, 459 (gpaa->arg_type == GPIO_TYPE_INT)? 460 ((void *)gpaa->consumer_arg.lint): 461 (gpaa->consumer_arg.string), 462 gp, gpaa->pin_offset, gpaa->pin_mask); 463 break; 464 465 case GPIODETACH: 466 gpaa = (struct gpio_attach_args *)ap->a_data; 467 error = gpio_consumer_detach(gpaa->consumer_name, gp, 468 gpaa->pin_offset); 469 break; 470 471 case GPIOPINSET: 472 gpsa = (struct gpio_pin_set_args *)ap->a_data; 473 if (gpsa->pin < 0 || gpsa->pin >= gp->npins) 474 return EINVAL; 475 476 pin = &gp->pins[gpsa->pin]; 477 478 if (pin->pin_opened || pin->pin_mapped) 479 return EBUSY; 480 481 gpsa->caps = pin->pin_caps; 482 gpsa->flags = pin->pin_flags; 483 484 if ((gpsa->flags & pin->pin_caps) != gpsa->flags) 485 return ENODEV; 486 487 if (gpsa->flags > 0) { 488 gp->pin_ctl(gp->arg, gpsa->pin, gpsa->flags); 489 pin->pin_flags = gpsa->flags | GPIO_PIN_SET; 490 } 491 break; 492 493 case GPIOPINUNSET: 494 gpsa = (struct gpio_pin_set_args *)ap->a_data; 495 error = EINVAL; 496 break; 497 498 default: 499 return EINVAL; 500 } 501 502 return error; 503 } 504 505 static struct dev_ops gpio_ops = { 506 { "gpio", 0, 0 }, 507 .d_open = gpio_open, 508 .d_close = gpio_close, 509 .d_write = gpio_write, 510 .d_read = gpio_read, 511 .d_ioctl = gpio_ioctl, 512 }; 513 514 static struct dev_ops gpio_master_ops = { 515 { "gpio", 0, 0 }, 516 .d_ioctl = gpio_master_ioctl, 517 }; 518 519 void 520 gpio_register(struct gpio *gp) 521 { 522 struct gpio_driver *gpd; 523 int i, unit, master_unit = -1; 524 525 KKASSERT(gp->npins > 0); 526 KKASSERT(gp->pins); 527 528 lockmgr(&gpio_lock, LK_EXCLUSIVE); 529 LIST_FOREACH(gpd, &gpio_driverlist, link) { 530 if (strcmp(gpd->name, gp->driver_name) != 0) 531 continue; 532 533 master_unit = devfs_clone_bitmap_get(&gpd->unit_bitmap, 0); 534 break; 535 } 536 if (master_unit == -1) { 537 gpd = kmalloc(sizeof(struct gpio_driver), 538 M_TEMP, M_WAITOK | M_ZERO); 539 gpd->name = kstrdup(gp->driver_name, M_TEMP); 540 devfs_clone_bitmap_init(&gpd->unit_bitmap); 541 master_unit = devfs_clone_bitmap_get(&gpd->unit_bitmap, 0); 542 LIST_INSERT_HEAD(&gpio_driverlist, gpd, link); 543 } 544 lockmgr(&gpio_lock, LK_RELEASE); 545 546 gp->driver_unit = master_unit; 547 kprintf("gpio: GPIO driver %s%d registered, npins = %d\n", 548 gp->driver_name, master_unit, gp->npins); 549 550 unit = devfs_clone_bitmap_get(&DEVFS_CLONE_BITMAP(gpio), 0); 551 gp->master_dev = make_dev(&gpio_master_ops, unit, UID_ROOT, GID_WHEEL, 0600, 552 "gpio/%s%d/master", gp->driver_name, master_unit); 553 gp->master_dev->si_drv1 = gp; 554 555 for (i = 0; i < gp->npins; i++) { 556 unit = devfs_clone_bitmap_get(&DEVFS_CLONE_BITMAP(gpio), 0); 557 gp->pins[i].dev = make_dev(&gpio_ops, unit, UID_ROOT, GID_WHEEL, 0600, 558 "gpio/%s%d/%d", gp->driver_name, master_unit, gp->pins[i].pin_num); 559 gp->pins[i].dev->si_drv1 = gp; 560 gp->pins[i].dev->si_drv2 = &gp->pins[i]; 561 } 562 } 563 564 void 565 gpio_unregister(struct gpio *gp) 566 { 567 struct gpio_driver *gpd; 568 int i; 569 570 KKASSERT(gp->npins > 0); 571 KKASSERT(gp->pins); 572 573 for (i = 0; i < gp->npins; i++) { 574 devfs_clone_bitmap_get(&DEVFS_CLONE_BITMAP(gpio), 575 minor(gp->pins[i].dev)); 576 destroy_dev(gp->pins[i].dev); 577 } 578 579 destroy_dev(gp->master_dev); 580 581 lockmgr(&gpio_lock, LK_EXCLUSIVE); 582 LIST_FOREACH(gpd, &gpio_driverlist, link) { 583 if (strcmp(gpd->name, gp->driver_name) != 0) 584 continue; 585 586 devfs_clone_bitmap_put(&gpd->unit_bitmap, gp->driver_unit); 587 LIST_REMOVE(gpd, link); 588 break; 589 } 590 lockmgr(&gpio_lock, LK_RELEASE); 591 592 kprintf("gpio: GPIO driver %s%d unregistered\n", 593 gp->driver_name, gp->driver_unit); 594 } 595 596 static void 597 gpio_drvinit(void *unused) 598 { 599 lockinit(&gpio_lock, "gpio_lock", 0, 0); 600 devfs_clone_bitmap_init(&DEVFS_CLONE_BITMAP(gpio)); 601 } 602 603 SYSINIT(gpio, SI_SUB_PRE_DRIVERS, SI_ORDER_FIRST, gpio_drvinit, NULL); 604