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 <sys/ioccom.h> 69 #include <dev/misc/gpio/gpio.h> 70 #include <sys/devfs.h> 71 72 struct gpio_driver { 73 char *name; 74 struct devfs_bitmap unit_bitmap; 75 LIST_ENTRY(gpio_driver) link; 76 }; 77 78 static LIST_HEAD(, gpio_consumer) gpio_conslist = LIST_HEAD_INITIALIZER(&gpio_conslist); 79 static LIST_HEAD(, gpio_driver) gpio_driverlist = LIST_HEAD_INITIALIZER(&gpio_driverlist); 80 DEVFS_DECLARE_CLONE_BITMAP(gpio); 81 static struct lock gpio_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 return 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 return 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 struct gpio *gp; 303 gpio_pin_t *pin; 304 cdev_t dev; 305 306 dev = ap->a_head.a_dev; 307 gp = dev->si_drv1; 308 pin = dev->si_drv2; 309 310 if (pin->pin_opened || pin->pin_mapped) 311 return EBUSY; 312 313 pin->pin_opened = 1; 314 315 return 0; 316 } 317 318 static int 319 gpio_close(struct dev_close_args *ap) 320 { 321 struct gpio *gp; 322 gpio_pin_t *pin; 323 cdev_t dev; 324 325 dev = ap->a_head.a_dev; 326 gp = dev->si_drv1; 327 pin = dev->si_drv2; 328 329 if (pin->pin_opened) 330 pin->pin_opened = 0; 331 332 return 0; 333 } 334 335 static int 336 gpio_write(struct dev_write_args *ap) 337 { 338 struct gpio *gp; 339 gpio_pin_t *pin; 340 cdev_t dev; 341 int error; 342 int data = 0; 343 344 dev = ap->a_head.a_dev; 345 gp = dev->si_drv1; 346 pin = dev->si_drv2; 347 348 if (ap->a_uio->uio_resid > sizeof(int)) 349 return EINVAL; 350 351 error = uiomove((void *)&data, ap->a_uio->uio_resid, ap->a_uio); 352 if (error) 353 return error; 354 355 if (data != GPIO_PIN_LOW && data != GPIO_PIN_HIGH) 356 return EINVAL; 357 358 gp->pin_write(gp->arg, pin->pin_num, data); 359 pin->pin_state = data; 360 361 return 0; 362 } 363 364 static int 365 gpio_read(struct dev_read_args *ap) 366 { 367 struct gpio *gp; 368 gpio_pin_t *pin; 369 cdev_t dev; 370 int error; 371 int data = 0; 372 373 dev = ap->a_head.a_dev; 374 gp = dev->si_drv1; 375 pin = dev->si_drv2; 376 377 if (ap->a_uio->uio_resid < sizeof(char)) 378 return EINVAL; 379 380 data = gp->pin_read(gp->arg, pin->pin_num); 381 382 error = uiomove((void *)&data, 383 (ap->a_uio->uio_resid > sizeof(int))?(sizeof(int)):(ap->a_uio->uio_resid), 384 ap->a_uio); 385 386 return error; 387 } 388 389 static int 390 gpio_ioctl(struct dev_ioctl_args *ap) 391 { 392 struct gpio_pin_set_args *gpsa; 393 struct gpio *gp; 394 gpio_pin_t *pin; 395 cdev_t dev; 396 int error = 0; 397 398 dev = ap->a_head.a_dev; 399 gp = dev->si_drv1; 400 pin = dev->si_drv2; 401 402 switch(ap->a_cmd) { 403 case GPIOPINSET: 404 gpsa = (struct gpio_pin_set_args *)ap->a_data; 405 if (pin->pin_opened || pin->pin_mapped) 406 return EBUSY; 407 408 gpsa->caps = pin->pin_caps; 409 gpsa->flags = pin->pin_flags; 410 411 if ((gpsa->flags & pin->pin_caps) != gpsa->flags) 412 return ENODEV; 413 414 if (gpsa->flags > 0) { 415 gp->pin_ctl(gp->arg, pin->pin_num, gpsa->flags); 416 pin->pin_flags = gpsa->flags | GPIO_PIN_SET; 417 } 418 break; 419 420 case GPIOPINUNSET: 421 gpsa = (struct gpio_pin_set_args *)ap->a_data; 422 error = EINVAL; 423 break; 424 425 default: 426 return EINVAL; 427 } 428 return 0; 429 } 430 431 static int 432 gpio_master_ioctl(struct dev_ioctl_args *ap) 433 { 434 struct gpio_pin_set_args *gpsa; 435 struct gpio_info *gpi; 436 struct gpio_attach_args *gpaa; 437 struct gpio *gp; 438 cdev_t dev; 439 gpio_pin_t *pin; 440 int error = 0; 441 442 dev = ap->a_head.a_dev; 443 gp = dev->si_drv1; 444 445 switch(ap->a_cmd) { 446 case GPIOINFO: 447 gpi = (struct gpio_info *)ap->a_data; 448 gpi->npins = gp->npins; 449 if (gpi->pins != NULL) { 450 error = copyout(gp->pins, gpi->pins, 451 sizeof(struct gpio_pin)*gp->npins); 452 } 453 break; 454 455 case GPIOATTACH: 456 gpaa = (struct gpio_attach_args *)ap->a_data; 457 error = gpio_consumer_attach(gpaa->consumer_name, 458 (gpaa->arg_type == GPIO_TYPE_INT)? 459 ((void *)gpaa->consumer_arg.lint): 460 (gpaa->consumer_arg.string), 461 gp, gpaa->pin_offset, gpaa->pin_mask); 462 break; 463 464 case GPIODETACH: 465 gpaa = (struct gpio_attach_args *)ap->a_data; 466 error = gpio_consumer_detach(gpaa->consumer_name, gp, 467 gpaa->pin_offset); 468 break; 469 470 case GPIOPINSET: 471 gpsa = (struct gpio_pin_set_args *)ap->a_data; 472 if (gpsa->pin < 0 || gpsa->pin >= gp->npins) 473 return EINVAL; 474 475 pin = &gp->pins[gpsa->pin]; 476 477 if (pin->pin_opened || pin->pin_mapped) 478 return EBUSY; 479 480 gpsa->caps = pin->pin_caps; 481 gpsa->flags = pin->pin_flags; 482 483 if ((gpsa->flags & pin->pin_caps) != gpsa->flags) 484 return ENODEV; 485 486 if (gpsa->flags > 0) { 487 gp->pin_ctl(gp->arg, gpsa->pin, gpsa->flags); 488 pin->pin_flags = gpsa->flags | GPIO_PIN_SET; 489 } 490 break; 491 492 case GPIOPINUNSET: 493 gpsa = (struct gpio_pin_set_args *)ap->a_data; 494 error = EINVAL; 495 break; 496 497 default: 498 return EINVAL; 499 } 500 501 return error; 502 } 503 504 static struct dev_ops gpio_ops = { 505 { "gpio", 0, 0 }, 506 .d_open = gpio_open, 507 .d_close = gpio_close, 508 .d_write = gpio_write, 509 .d_read = gpio_read, 510 .d_ioctl = gpio_ioctl, 511 }; 512 513 static struct dev_ops gpio_master_ops = { 514 { "gpio", 0, 0 }, 515 .d_ioctl = gpio_master_ioctl, 516 }; 517 518 void 519 gpio_register(struct gpio *gp) 520 { 521 struct gpio_driver *gpd; 522 int i, unit, master_unit = -1; 523 524 KKASSERT(gp->npins > 0); 525 KKASSERT(gp->pins); 526 527 lockmgr(&gpio_lock, LK_EXCLUSIVE); 528 LIST_FOREACH(gpd, &gpio_driverlist, link) { 529 if (strcmp(gpd->name, gp->driver_name) != 0) 530 continue; 531 532 master_unit = devfs_clone_bitmap_get(&gpd->unit_bitmap, 0); 533 break; 534 } 535 if (master_unit == -1) { 536 gpd = kmalloc(sizeof(struct gpio_driver), 537 M_TEMP, M_WAITOK | M_ZERO); 538 gpd->name = kstrdup(gp->driver_name, M_TEMP); 539 devfs_clone_bitmap_init(&gpd->unit_bitmap); 540 master_unit = devfs_clone_bitmap_get(&gpd->unit_bitmap, 0); 541 LIST_INSERT_HEAD(&gpio_driverlist, gpd, link); 542 } 543 lockmgr(&gpio_lock, LK_RELEASE); 544 545 gp->driver_unit = master_unit; 546 kprintf("gpio: GPIO driver %s%d registered, npins = %d\n", 547 gp->driver_name, master_unit, gp->npins); 548 549 unit = devfs_clone_bitmap_get(&DEVFS_CLONE_BITMAP(gpio), 0); 550 gp->master_dev = make_dev(&gpio_master_ops, unit, UID_ROOT, GID_WHEEL, 0600, 551 "gpio/%s%d/master", gp->driver_name, master_unit); 552 gp->master_dev->si_drv1 = gp; 553 554 for (i = 0; i < gp->npins; i++) { 555 unit = devfs_clone_bitmap_get(&DEVFS_CLONE_BITMAP(gpio), 0); 556 gp->pins[i].dev = make_dev(&gpio_ops, unit, UID_ROOT, GID_WHEEL, 0600, 557 "gpio/%s%d/%d", gp->driver_name, master_unit, gp->pins[i].pin_num); 558 gp->pins[i].dev->si_drv1 = gp; 559 gp->pins[i].dev->si_drv2 = &gp->pins[i]; 560 } 561 } 562 563 void 564 gpio_unregister(struct gpio *gp) 565 { 566 struct gpio_driver *gpd; 567 int i; 568 569 KKASSERT(gp->npins > 0); 570 KKASSERT(gp->pins); 571 572 for (i = 0; i < gp->npins; i++) { 573 devfs_clone_bitmap_get(&DEVFS_CLONE_BITMAP(gpio), 574 minor(gp->pins[i].dev)); 575 destroy_dev(gp->pins[i].dev); 576 } 577 578 destroy_dev(gp->master_dev); 579 580 lockmgr(&gpio_lock, LK_EXCLUSIVE); 581 LIST_FOREACH(gpd, &gpio_driverlist, link) { 582 if (strcmp(gpd->name, gp->driver_name) != 0) 583 continue; 584 585 devfs_clone_bitmap_put(&gpd->unit_bitmap, gp->driver_unit); 586 LIST_REMOVE(gpd, link); 587 break; 588 } 589 lockmgr(&gpio_lock, LK_RELEASE); 590 591 kprintf("gpio: GPIO driver %s%d unregistered\n", 592 gp->driver_name, gp->driver_unit); 593 } 594 595 static void 596 gpio_drvinit(void *unused) 597 { 598 lockinit(&gpio_lock, "gpio_lock", 0, 0); 599 devfs_clone_bitmap_init(&DEVFS_CLONE_BITMAP(gpio)); 600 } 601 602 SYSINIT(gpio, SI_SUB_PRE_DRIVERS, SI_ORDER_FIRST, gpio_drvinit, NULL); 603