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