Annotation of src/sys/dev/gpio/gpio.c, Revision 1.50
1.50 ! mbalmer 1: /* $NetBSD: gpio.c,v 1.49 2011/11/14 07:45:54 mbalmer Exp $ */
1.5 riz 2: /* $OpenBSD: gpio.c,v 1.6 2006/01/14 12:33:49 grange Exp $ */
3:
1.1 jmcneill 4: /*
1.35 mbalmer 5: * Copyright (c) 2008, 2009, 2010, 2011 Marc Balmer <marc@msys.ch>
1.5 riz 6: * Copyright (c) 2004, 2006 Alexander Yurchenko <grange@openbsd.org>
1.1 jmcneill 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 USE, DATA OR PROFITS, WHETHER IN AN
17: * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
18: * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
19: */
20:
1.2 cube 21: #include <sys/cdefs.h>
1.50 ! mbalmer 22: __KERNEL_RCSID(0, "$NetBSD: gpio.c,v 1.49 2011/11/14 07:45:54 mbalmer Exp $");
1.2 cube 23:
1.1 jmcneill 24: /*
25: * General Purpose Input/Output framework.
26: */
27:
28: #include <sys/param.h>
1.36 mbalmer 29: #include <sys/callout.h>
1.1 jmcneill 30: #include <sys/systm.h>
31: #include <sys/conf.h>
32: #include <sys/device.h>
1.19 mbalmer 33: #include <sys/fcntl.h>
1.1 jmcneill 34: #include <sys/ioctl.h>
35: #include <sys/gpio.h>
1.36 mbalmer 36: #include <sys/kernel.h>
1.1 jmcneill 37: #include <sys/vnode.h>
1.19 mbalmer 38: #include <sys/kmem.h>
1.36 mbalmer 39: #include <sys/mutex.h>
40: #include <sys/condvar.h>
1.19 mbalmer 41: #include <sys/queue.h>
42: #include <sys/kauth.h>
1.35 mbalmer 43: #include <sys/module.h>
1.1 jmcneill 44: #include <dev/gpio/gpiovar.h>
45:
1.3 drochner 46: #include "locators.h"
47:
1.19 mbalmer 48: #ifdef GPIO_DEBUG
1.21 cegger 49: #define DPRINTFN(n, x) do { if (gpiodebug > (n)) printf x; } while (0)
1.19 mbalmer 50: int gpiodebug = 0;
51: #else
52: #define DPRINTFN(n, x)
53: #endif
54: #define DPRINTF(x) DPRINTFN(0, x)
55:
1.1 jmcneill 56: struct gpio_softc {
1.19 mbalmer 57: device_t sc_dev;
1.1 jmcneill 58:
1.19 mbalmer 59: gpio_chipset_tag_t sc_gc; /* GPIO controller */
60: gpio_pin_t *sc_pins; /* pins array */
61: int sc_npins; /* number of pins */
62:
1.36 mbalmer 63: kmutex_t sc_mtx;
64: kcondvar_t sc_ioctl; /* ioctl in progress */
65: int sc_ioctl_busy; /* ioctl is busy */
1.39 mbalmer 66: kcondvar_t sc_attach; /* attach/detach in progress */
67: int sc_attach_busy;/* busy in attach/detach */
1.45 mbalmer 68: #ifdef COMPAT_50
1.19 mbalmer 69: LIST_HEAD(, gpio_dev) sc_devs; /* devices */
1.45 mbalmer 70: #endif
1.19 mbalmer 71: LIST_HEAD(, gpio_name) sc_names; /* named pins */
1.1 jmcneill 72: };
73:
1.35 mbalmer 74: static int gpio_match(device_t, cfdata_t, void *);
75: int gpio_submatch(device_t, cfdata_t, const int *, void *);
76: static void gpio_attach(device_t, device_t, void *);
77: static int gpio_rescan(device_t, const char *, const int *);
78: static void gpio_childdetached(device_t, device_t);
79: static bool gpio_resume(device_t, const pmf_qual_t *);
80: static int gpio_detach(device_t, int);
81: static int gpio_search(device_t, cfdata_t, const int *, void *);
82: static int gpio_print(void *, const char *);
83: static int gpio_pinbyname(struct gpio_softc *, char *);
1.36 mbalmer 84: static int gpio_ioctl(struct gpio_softc *, u_long, void *, int,
85: struct lwp *);
1.19 mbalmer 86:
1.42 mbalmer 87: #ifdef COMPAT_50
1.19 mbalmer 88: /* Old API */
1.35 mbalmer 89: static int gpio_ioctl_oapi(struct gpio_softc *, u_long, void *, int,
90: kauth_cred_t);
1.42 mbalmer 91: #endif
1.1 jmcneill 92:
1.18 dyoung 93: CFATTACH_DECL3_NEW(gpio, sizeof(struct gpio_softc),
1.29 dyoung 94: gpio_match, gpio_attach, gpio_detach, NULL, gpio_rescan,
95: gpio_childdetached, DVF_DETACH_SHUTDOWN);
1.1 jmcneill 96:
97: dev_type_open(gpioopen);
98: dev_type_close(gpioclose);
99: dev_type_ioctl(gpioioctl);
1.36 mbalmer 100: dev_type_ioctl(gpioioctl_locked);
1.1 jmcneill 101:
102: const struct cdevsw gpio_cdevsw = {
103: gpioopen, gpioclose, noread, nowrite, gpioioctl,
1.36 mbalmer 104: nostop, notty, nopoll, nommap, nokqfilter, D_OTHER | D_MPSAFE
1.1 jmcneill 105: };
106:
107: extern struct cfdriver gpio_cd;
108:
1.35 mbalmer 109: static int
1.17 cegger 110: gpio_match(device_t parent, cfdata_t cf, void *aux)
1.1 jmcneill 111: {
1.19 mbalmer 112: return 1;
113: }
114:
115: int
116: gpio_submatch(device_t parent, cfdata_t cf, const int *ip, void *aux)
117: {
118: struct gpio_attach_args *ga = aux;
1.1 jmcneill 119:
1.19 mbalmer 120: if (ga->ga_offset == -1)
121: return 0;
122:
123: return strcmp(ga->ga_dvname, cf->cf_name) == 0;
1.1 jmcneill 124: }
125:
1.35 mbalmer 126: static bool
1.32 dyoung 127: gpio_resume(device_t self, const pmf_qual_t *qual)
1.13 dyoung 128: {
129: struct gpio_softc *sc = device_private(self);
130: int pin;
131:
132: for (pin = 0; pin < sc->sc_npins; pin++) {
133: gpiobus_pin_ctl(sc->sc_gc, pin, sc->sc_pins[pin].pin_flags);
134: gpiobus_pin_write(sc->sc_gc, pin, sc->sc_pins[pin].pin_state);
135: }
136: return true;
137: }
138:
1.35 mbalmer 139: static void
1.29 dyoung 140: gpio_childdetached(device_t self, device_t child)
141: {
1.45 mbalmer 142: #ifdef COMPAT_50
1.39 mbalmer 143: struct gpio_dev *gdev;
144: struct gpio_softc *sc;
145: int error;
146:
147: /*
148: * gpio_childetached is serialized because it can be entered in
149: * different ways concurrently, e.g. via the GPIODETACH ioctl and
150: * drvctl(8) or modunload(8).
151: */
152: sc = device_private(self);
153: error = 0;
154: mutex_enter(&sc->sc_mtx);
155: while (sc->sc_attach_busy) {
156: error = cv_wait_sig(&sc->sc_attach, &sc->sc_mtx);
157: if (error)
158: break;
159: }
160: if (!error)
161: sc->sc_attach_busy = 1;
162: mutex_exit(&sc->sc_mtx);
163: if (error)
164: return;
165:
166: LIST_FOREACH(gdev, &sc->sc_devs, sc_next)
167: if (gdev->sc_dev == child) {
168: LIST_REMOVE(gdev, sc_next);
169: kmem_free(gdev, sizeof(struct gpio_dev));
170: break;
171: }
172:
173: mutex_enter(&sc->sc_mtx);
174: sc->sc_attach_busy = 0;
175: cv_signal(&sc->sc_attach);
176: mutex_exit(&sc->sc_mtx);
1.45 mbalmer 177: #endif
1.29 dyoung 178: }
179:
1.35 mbalmer 180: static int
1.29 dyoung 181: gpio_rescan(device_t self, const char *ifattr, const int *locators)
182: {
183: struct gpio_softc *sc = device_private(self);
184:
185: config_search_loc(gpio_search, self, ifattr, locators, sc);
186:
187: return 0;
188: }
189:
1.35 mbalmer 190: static void
1.14 dyoung 191: gpio_attach(device_t parent, device_t self, void *aux)
1.1 jmcneill 192: {
1.7 thorpej 193: struct gpio_softc *sc = device_private(self);
1.1 jmcneill 194: struct gpiobus_attach_args *gba = aux;
1.47 mbalmer 195:
1.17 cegger 196: sc->sc_dev = self;
1.1 jmcneill 197: sc->sc_gc = gba->gba_gc;
198: sc->sc_pins = gba->gba_pins;
199: sc->sc_npins = gba->gba_npins;
200:
201: printf(": %d pins\n", sc->sc_npins);
202:
1.13 dyoung 203: if (!pmf_device_register(self, NULL, gpio_resume))
204: aprint_error_dev(self, "couldn't establish power handler\n");
1.36 mbalmer 205: mutex_init(&sc->sc_mtx, MUTEX_DEFAULT, IPL_VM);
206: cv_init(&sc->sc_ioctl, "gpioctl");
1.39 mbalmer 207: cv_init(&sc->sc_attach, "gpioatch");
1.1 jmcneill 208: /*
209: * Attach all devices that can be connected to the GPIO pins
210: * described in the kernel configuration file.
211: */
1.29 dyoung 212: gpio_rescan(self, "gpio", NULL);
1.1 jmcneill 213: }
214:
1.35 mbalmer 215: static int
1.14 dyoung 216: gpio_detach(device_t self, int flags)
1.1 jmcneill 217: {
1.36 mbalmer 218: struct gpio_softc *sc;
1.47 mbalmer 219: int rc;
1.36 mbalmer 220:
221: sc = device_private(self);
222:
1.29 dyoung 223: if ((rc = config_detach_children(self, flags)) != 0)
224: return rc;
1.36 mbalmer 225: mutex_destroy(&sc->sc_mtx);
226: cv_destroy(&sc->sc_ioctl);
1.1 jmcneill 227: #if 0
228: int maj, mn;
229:
230: /* Locate the major number */
231: for (maj = 0; maj < nchrdev; maj++)
232: if (cdevsw[maj].d_open == gpioopen)
233: break;
234:
235: /* Nuke the vnodes for any open instances (calls close) */
1.6 thorpej 236: mn = device_unit(self);
1.1 jmcneill 237: vdevgone(maj, mn, mn, VCHR);
238: #endif
1.19 mbalmer 239: return 0;
1.1 jmcneill 240: }
241:
1.35 mbalmer 242: static int
1.31 mbalmer 243: gpio_search(device_t parent, cfdata_t cf, const int *ldesc, void *aux)
1.1 jmcneill 244: {
245: struct gpio_attach_args ga;
1.49 mbalmer 246: size_t namlen;
1.1 jmcneill 247:
1.5 riz 248: ga.ga_gpio = aux;
249: ga.ga_offset = cf->cf_loc[GPIOCF_OFFSET];
1.3 drochner 250: ga.ga_mask = cf->cf_loc[GPIOCF_MASK];
1.42 mbalmer 251: ga.ga_flags = cf->cf_loc[GPIOCF_FLAG];
1.49 mbalmer 252: namlen = strlen(cf->cf_name) + 1;
253: ga.ga_dvname = kmem_alloc(namlen, KM_NOSLEEP);
254: if (ga.ga_dvname == NULL)
255: return 0;
256: strcpy(ga.ga_dvname, cf->cf_name);
1.1 jmcneill 257:
258: if (config_match(parent, cf, &ga) > 0)
259: config_attach(parent, cf, &ga, gpio_print);
1.49 mbalmer 260: kmem_free(ga.ga_dvname, namlen);
1.19 mbalmer 261: return 0;
1.1 jmcneill 262: }
263:
264: int
1.11 christos 265: gpio_print(void *aux, const char *pnp)
1.1 jmcneill 266: {
267: struct gpio_attach_args *ga = aux;
268: int i;
269:
270: printf(" pins");
271: for (i = 0; i < 32; i++)
272: if (ga->ga_mask & (1 << i))
1.5 riz 273: printf(" %d", ga->ga_offset + i);
1.1 jmcneill 274:
1.19 mbalmer 275: return UNCONF;
1.1 jmcneill 276: }
277:
278: int
1.11 christos 279: gpiobus_print(void *aux, const char *pnp)
1.1 jmcneill 280: {
1.3 drochner 281: #if 0
1.1 jmcneill 282: struct gpiobus_attach_args *gba = aux;
1.3 drochner 283: #endif
1.1 jmcneill 284: if (pnp != NULL)
1.33 ad 285: aprint_normal("gpiobus at %s", pnp);
1.1 jmcneill 286:
1.19 mbalmer 287: return UNCONF;
1.1 jmcneill 288: }
289:
1.27 mbalmer 290: /* return 1 if all pins can be mapped, 0 if not */
291: int
1.36 mbalmer 292: gpio_pin_can_map(void *gpio, int offset, uint32_t mask)
1.27 mbalmer 293: {
294: struct gpio_softc *sc = gpio;
295: int npins, pin, i;
296:
297: npins = gpio_npins(mask);
298: if (npins > sc->sc_npins)
299: return 0;
300:
301: for (npins = 0, i = 0; i < 32; i++)
302: if (mask & (1 << i)) {
303: pin = offset + i;
304: if (pin < 0 || pin >= sc->sc_npins)
305: return 0;
306: if (sc->sc_pins[pin].pin_mapped)
307: return 0;
308: }
309:
310: return 1;
311: }
312:
1.8 uwe 313: int
1.36 mbalmer 314: gpio_pin_map(void *gpio, int offset, uint32_t mask, struct gpio_pinmap *map)
1.5 riz 315: {
316: struct gpio_softc *sc = gpio;
317: int npins, pin, i;
318:
319: npins = gpio_npins(mask);
320: if (npins > sc->sc_npins)
1.19 mbalmer 321: return 1;
1.5 riz 322:
323: for (npins = 0, i = 0; i < 32; i++)
324: if (mask & (1 << i)) {
325: pin = offset + i;
326: if (pin < 0 || pin >= sc->sc_npins)
1.19 mbalmer 327: return 1;
1.5 riz 328: if (sc->sc_pins[pin].pin_mapped)
1.19 mbalmer 329: return 1;
1.5 riz 330: sc->sc_pins[pin].pin_mapped = 1;
331: map->pm_map[npins++] = pin;
332: }
333: map->pm_size = npins;
334:
1.19 mbalmer 335: return 0;
1.5 riz 336: }
337:
338: void
339: gpio_pin_unmap(void *gpio, struct gpio_pinmap *map)
340: {
341: struct gpio_softc *sc = gpio;
342: int pin, i;
343:
344: for (i = 0; i < map->pm_size; i++) {
345: pin = map->pm_map[i];
346: sc->sc_pins[pin].pin_mapped = 0;
347: }
348: }
349:
350: int
351: gpio_pin_read(void *gpio, struct gpio_pinmap *map, int pin)
352: {
353: struct gpio_softc *sc = gpio;
354:
1.19 mbalmer 355: return gpiobus_pin_read(sc->sc_gc, map->pm_map[pin]);
1.5 riz 356: }
357:
358: void
359: gpio_pin_write(void *gpio, struct gpio_pinmap *map, int pin, int value)
360: {
361: struct gpio_softc *sc = gpio;
362:
1.13 dyoung 363: gpiobus_pin_write(sc->sc_gc, map->pm_map[pin], value);
364: sc->sc_pins[map->pm_map[pin]].pin_state = value;
1.5 riz 365: }
366:
367: void
368: gpio_pin_ctl(void *gpio, struct gpio_pinmap *map, int pin, int flags)
369: {
370: struct gpio_softc *sc = gpio;
371:
1.19 mbalmer 372: return gpiobus_pin_ctl(sc->sc_gc, map->pm_map[pin], flags);
1.5 riz 373: }
374:
375: int
376: gpio_pin_caps(void *gpio, struct gpio_pinmap *map, int pin)
377: {
378: struct gpio_softc *sc = gpio;
379:
1.19 mbalmer 380: return sc->sc_pins[map->pm_map[pin]].pin_caps;
1.5 riz 381: }
382:
383: int
1.36 mbalmer 384: gpio_npins(uint32_t mask)
1.5 riz 385: {
386: int npins, i;
387:
388: for (npins = 0, i = 0; i < 32; i++)
389: if (mask & (1 << i))
390: npins++;
391:
1.19 mbalmer 392: return npins;
1.5 riz 393: }
394:
1.1 jmcneill 395: int
1.36 mbalmer 396: gpio_lock(void *data)
397: {
398: struct gpio_softc *sc;
399: int error;
400:
401: error = 0;
1.43 mbalmer 402: sc = data;
1.36 mbalmer 403: mutex_enter(&sc->sc_mtx);
404: while (sc->sc_ioctl_busy) {
405: error = cv_wait_sig(&sc->sc_ioctl, &sc->sc_mtx);
406: if (error)
407: break;
408: }
409: if (!error)
410: sc->sc_ioctl_busy = 1;
411: mutex_exit(&sc->sc_mtx);
412: return error;
413: }
414:
415: void
416: gpio_unlock(void *data)
417: {
418: struct gpio_softc *sc;
419:
1.43 mbalmer 420: sc = data;
1.36 mbalmer 421: mutex_enter(&sc->sc_mtx);
422: sc->sc_ioctl_busy = 0;
423: cv_signal(&sc->sc_ioctl);
424: mutex_exit(&sc->sc_mtx);
425: }
426:
427: int
1.26 mbalmer 428: gpioopen(dev_t dev, int flag, int mode, struct lwp *l)
1.1 jmcneill 429: {
430: struct gpio_softc *sc;
431:
1.17 cegger 432: sc = device_lookup_private(&gpio_cd, minor(dev));
1.1 jmcneill 433: if (sc == NULL)
1.19 mbalmer 434: return ENXIO;
1.1 jmcneill 435:
1.36 mbalmer 436: return gpiobus_open(sc->sc_gc, sc->sc_dev);
1.1 jmcneill 437: }
438:
439: int
1.26 mbalmer 440: gpioclose(dev_t dev, int flag, int mode, struct lwp *l)
1.1 jmcneill 441: {
442: struct gpio_softc *sc;
443:
1.17 cegger 444: sc = device_lookup_private(&gpio_cd, minor(dev));
1.50 ! mbalmer 445: return gpiobus_close(sc->sc_gc, sc->sc_dev);
1.19 mbalmer 446: }
447:
1.35 mbalmer 448: static int
1.19 mbalmer 449: gpio_pinbyname(struct gpio_softc *sc, char *gp_name)
450: {
451: struct gpio_name *nm;
452:
453: LIST_FOREACH(nm, &sc->sc_names, gp_next)
454: if (!strcmp(nm->gp_name, gp_name))
455: return nm->gp_pin;
456: return -1;
1.1 jmcneill 457: }
458:
459: int
1.26 mbalmer 460: gpioioctl(dev_t dev, u_long cmd, void *data, int flag, struct lwp *l)
1.1 jmcneill 461: {
1.36 mbalmer 462: int error;
1.1 jmcneill 463: struct gpio_softc *sc;
1.36 mbalmer 464:
465: sc = device_lookup_private(&gpio_cd, minor(dev));
466:
467: error = gpio_lock(sc);
468: if (error)
469: return error;
470:
471: error = gpio_ioctl(sc, cmd, data, flag, l);
472: gpio_unlock(sc);
473: return error;
474: }
475:
476: static int
477: gpio_ioctl(struct gpio_softc *sc, u_long cmd, void *data, int flag,
478: struct lwp *l)
479: {
1.1 jmcneill 480: gpio_chipset_tag_t gc;
481: struct gpio_info *info;
1.19 mbalmer 482: struct gpio_attach *attach;
483: struct gpio_attach_args ga;
1.45 mbalmer 484: struct gpio_req *req;
1.19 mbalmer 485: struct gpio_name *nm;
486: struct gpio_set *set;
1.46 mbalmer 487: #ifdef COMPAT_50
488: struct gpio_dev *gdev;
489: #endif
1.20 mbalmer 490: device_t dv;
1.24 mbalmer 491: cfdata_t cf;
1.19 mbalmer 492: kauth_cred_t cred;
493: int locs[GPIOCF_NLOCS];
1.39 mbalmer 494: int error, pin, value, flags, npins;
1.1 jmcneill 495:
496: gc = sc->sc_gc;
1.42 mbalmer 497: ga.ga_flags = 0;
1.1 jmcneill 498:
1.19 mbalmer 499: if (cmd != GPIOINFO && !device_is_active(sc->sc_dev)) {
1.26 mbalmer 500: DPRINTF(("%s: device is not active\n",
501: device_xname(sc->sc_dev)));
1.13 dyoung 502: return EBUSY;
1.19 mbalmer 503: }
1.35 mbalmer 504:
1.19 mbalmer 505: cred = kauth_cred_get();
1.13 dyoung 506:
1.1 jmcneill 507: switch (cmd) {
508: case GPIOINFO:
1.43 mbalmer 509: info = data;
1.19 mbalmer 510: if (!kauth_authorize_device(cred, KAUTH_DEVICE_GPIO_PINSET,
511: NULL, NULL, NULL, NULL))
512: info->gpio_npins = sc->sc_npins;
513: else {
514: for (pin = npins = 0; pin < sc->sc_npins; pin++)
515: if (sc->sc_pins[pin].pin_flags & GPIO_PIN_SET)
516: ++npins;
517: info->gpio_npins = npins;
518: }
519: break;
520: case GPIOREAD:
1.43 mbalmer 521: req = data;
1.19 mbalmer 522:
1.36 mbalmer 523: if (req->gp_name[0] != '\0')
1.19 mbalmer 524: pin = gpio_pinbyname(sc, req->gp_name);
1.36 mbalmer 525: else
1.19 mbalmer 526: pin = req->gp_pin;
527:
528: if (pin < 0 || pin >= sc->sc_npins)
529: return EINVAL;
530:
531: if (!(sc->sc_pins[pin].pin_flags & GPIO_PIN_SET) &&
532: kauth_authorize_device(cred, KAUTH_DEVICE_GPIO_PINSET,
533: NULL, NULL, NULL, NULL))
534: return EPERM;
535:
536: /* return read value */
537: req->gp_value = gpiobus_pin_read(gc, pin);
538: break;
539: case GPIOWRITE:
540: if ((flag & FWRITE) == 0)
541: return EBADF;
542:
1.43 mbalmer 543: req = data;
1.19 mbalmer 544:
1.36 mbalmer 545: if (req->gp_name[0] != '\0')
1.19 mbalmer 546: pin = gpio_pinbyname(sc, req->gp_name);
1.36 mbalmer 547: else
1.19 mbalmer 548: pin = req->gp_pin;
549:
550: if (pin < 0 || pin >= sc->sc_npins)
551: return EINVAL;
552:
553: if (sc->sc_pins[pin].pin_mapped)
554: return EBUSY;
555:
556: if (!(sc->sc_pins[pin].pin_flags & GPIO_PIN_SET) &&
557: kauth_authorize_device(cred, KAUTH_DEVICE_GPIO_PINSET,
558: NULL, NULL, NULL, NULL))
559: return EPERM;
1.1 jmcneill 560:
1.19 mbalmer 561: value = req->gp_value;
562: if (value != GPIO_PIN_LOW && value != GPIO_PIN_HIGH)
563: return EINVAL;
564:
565: gpiobus_pin_write(gc, pin, value);
566: /* return old value */
567: req->gp_value = sc->sc_pins[pin].pin_state;
568: /* update current value */
569: sc->sc_pins[pin].pin_state = value;
1.1 jmcneill 570: break;
1.19 mbalmer 571: case GPIOTOGGLE:
572: if ((flag & FWRITE) == 0)
573: return EBADF;
574:
1.43 mbalmer 575: req = data;
1.19 mbalmer 576:
1.36 mbalmer 577: if (req->gp_name[0] != '\0')
1.19 mbalmer 578: pin = gpio_pinbyname(sc, req->gp_name);
1.36 mbalmer 579: else
1.19 mbalmer 580: pin = req->gp_pin;
581:
582: if (pin < 0 || pin >= sc->sc_npins)
583: return EINVAL;
584:
585: if (sc->sc_pins[pin].pin_mapped)
586: return EBUSY;
587:
588: if (!(sc->sc_pins[pin].pin_flags & GPIO_PIN_SET) &&
589: kauth_authorize_device(cred, KAUTH_DEVICE_GPIO_PINSET,
590: NULL, NULL, NULL, NULL))
591: return EPERM;
592:
593: value = (sc->sc_pins[pin].pin_state == GPIO_PIN_LOW ?
594: GPIO_PIN_HIGH : GPIO_PIN_LOW);
595: gpiobus_pin_write(gc, pin, value);
596: /* return old value */
597: req->gp_value = sc->sc_pins[pin].pin_state;
598: /* update current value */
599: sc->sc_pins[pin].pin_state = value;
600: break;
601: case GPIOATTACH:
1.43 mbalmer 602: attach = data;
1.42 mbalmer 603: ga.ga_flags = attach->ga_flags;
604: #ifdef COMPAT_50
605: /* FALLTHROUGH */
606: case GPIOATTACH50:
607: /*
608: * The double assignment to 'attach' in case of GPIOATTACH
609: * and COMPAT_50 is on purpose. It ensures backward
610: * compatability in case we are called through the old
611: * GPIOATTACH50 ioctl(2), which had not the ga_flags field
612: * in struct gpio_attach.
613: */
1.43 mbalmer 614: attach = data;
1.42 mbalmer 615: #endif
1.19 mbalmer 616: if (kauth_authorize_device(cred, KAUTH_DEVICE_GPIO_PINSET,
617: NULL, NULL, NULL, NULL))
618: return EPERM;
1.27 mbalmer 619:
620: /* do not try to attach if the pins are already mapped */
621: if (!gpio_pin_can_map(sc, attach->ga_offset, attach->ga_mask))
622: return EBUSY;
623:
1.39 mbalmer 624: error = 0;
625: mutex_enter(&sc->sc_mtx);
626: while (sc->sc_attach_busy) {
627: error = cv_wait_sig(&sc->sc_attach, &sc->sc_mtx);
628: if (error)
629: break;
630: }
631: if (!error)
632: sc->sc_attach_busy = 1;
633: mutex_exit(&sc->sc_mtx);
634: if (error)
635: return EBUSY;
636:
1.19 mbalmer 637: ga.ga_gpio = sc;
1.42 mbalmer 638: /* Don't access attach->ga_flags here. */
1.19 mbalmer 639: ga.ga_dvname = attach->ga_dvname;
640: ga.ga_offset = attach->ga_offset;
641: ga.ga_mask = attach->ga_mask;
1.42 mbalmer 642: DPRINTF(("%s: attach %s with offset %d, mask "
643: "0x%02x, and flags 0x%02x\n", device_xname(sc->sc_dev),
644: ga.ga_dvname, ga.ga_offset, ga.ga_mask, ga.ga_flags));
1.19 mbalmer 645:
646: locs[GPIOCF_OFFSET] = ga.ga_offset;
647: locs[GPIOCF_MASK] = ga.ga_mask;
1.42 mbalmer 648: locs[GPIOCF_FLAG] = ga.ga_flags;
1.19 mbalmer 649:
1.24 mbalmer 650: cf = config_search_loc(NULL, sc->sc_dev, "gpio", locs, &ga);
651: if (cf != NULL) {
652: dv = config_attach_loc(sc->sc_dev, cf, locs, &ga,
653: gpiobus_print);
1.45 mbalmer 654: #ifdef COMPAT_50
1.24 mbalmer 655: if (dv != NULL) {
656: gdev = kmem_alloc(sizeof(struct gpio_dev),
657: KM_SLEEP);
658: gdev->sc_dev = dv;
659: LIST_INSERT_HEAD(&sc->sc_devs, gdev, sc_next);
660: } else
1.39 mbalmer 661: error = EINVAL;
1.45 mbalmer 662: #else
663: if (dv == NULL)
664: error = EINVAL;
665: #endif
1.19 mbalmer 666: } else
1.39 mbalmer 667: error = EINVAL;
668: mutex_enter(&sc->sc_mtx);
669: sc->sc_attach_busy = 0;
670: cv_signal(&sc->sc_attach);
671: mutex_exit(&sc->sc_mtx);
672: return error;
1.19 mbalmer 673: case GPIOSET:
674: if (kauth_authorize_device(cred, KAUTH_DEVICE_GPIO_PINSET,
675: NULL, NULL, NULL, NULL))
676: return EPERM;
677:
1.43 mbalmer 678: set = data;
1.19 mbalmer 679:
1.36 mbalmer 680: if (set->gp_name[0] != '\0')
1.19 mbalmer 681: pin = gpio_pinbyname(sc, set->gp_name);
1.36 mbalmer 682: else
1.19 mbalmer 683: pin = set->gp_pin;
1.36 mbalmer 684:
1.19 mbalmer 685: if (pin < 0 || pin >= sc->sc_npins)
686: return EINVAL;
687: flags = set->gp_flags;
688:
689: /* check that the controller supports all requested flags */
690: if ((flags & sc->sc_pins[pin].pin_caps) != flags)
691: return ENODEV;
692: flags = set->gp_flags | GPIO_PIN_SET;
693:
694: set->gp_caps = sc->sc_pins[pin].pin_caps;
695: /* return old value */
696: set->gp_flags = sc->sc_pins[pin].pin_flags;
697: if (flags > 0) {
698: gpiobus_pin_ctl(gc, pin, flags);
699: /* update current value */
700: sc->sc_pins[pin].pin_flags = flags;
701: }
702:
703: /* rename pin or new pin? */
704: if (set->gp_name2[0] != '\0') {
1.28 mbalmer 705: struct gpio_name *gnm;
706:
707: gnm = NULL;
708: LIST_FOREACH(nm, &sc->sc_names, gp_next) {
709: if (!strcmp(nm->gp_name, set->gp_name2) &&
710: nm->gp_pin != pin)
711: return EINVAL; /* duplicate name */
712: if (nm->gp_pin == pin)
713: gnm = nm;
714: }
715: if (gnm != NULL)
716: strlcpy(gnm->gp_name, set->gp_name2,
717: sizeof(gnm->gp_name));
718: else {
1.19 mbalmer 719: nm = kmem_alloc(sizeof(struct gpio_name),
720: KM_SLEEP);
721: strlcpy(nm->gp_name, set->gp_name2,
722: sizeof(nm->gp_name));
723: nm->gp_pin = set->gp_pin;
724: LIST_INSERT_HEAD(&sc->sc_names, nm, gp_next);
725: }
726: }
727: break;
728: case GPIOUNSET:
729: if (kauth_authorize_device(cred, KAUTH_DEVICE_GPIO_PINSET,
730: NULL, NULL, NULL, NULL))
731: return EPERM;
732:
1.43 mbalmer 733: set = data;
1.36 mbalmer 734: if (set->gp_name[0] != '\0')
1.19 mbalmer 735: pin = gpio_pinbyname(sc, set->gp_name);
1.36 mbalmer 736: else
1.19 mbalmer 737: pin = set->gp_pin;
1.35 mbalmer 738:
1.19 mbalmer 739: if (pin < 0 || pin >= sc->sc_npins)
740: return EINVAL;
741: if (sc->sc_pins[pin].pin_mapped)
742: return EBUSY;
743: if (!(sc->sc_pins[pin].pin_flags & GPIO_PIN_SET))
744: return EINVAL;
745:
746: LIST_FOREACH(nm, &sc->sc_names, gp_next) {
747: if (nm->gp_pin == pin) {
748: LIST_REMOVE(nm, gp_next);
749: kmem_free(nm, sizeof(struct gpio_name));
750: break;
751: }
752: }
753: sc->sc_pins[pin].pin_flags &= ~GPIO_PIN_SET;
754: break;
755: default:
1.42 mbalmer 756: #ifdef COMPAT_50
1.19 mbalmer 757: /* Try the old API */
1.22 cegger 758: DPRINTF(("%s: trying the old API\n", device_xname(sc->sc_dev)));
1.19 mbalmer 759: return gpio_ioctl_oapi(sc, cmd, data, flag, cred);
1.42 mbalmer 760: #else
761: return ENOTTY;
762: #endif
1.19 mbalmer 763: }
764: return 0;
765: }
766:
1.42 mbalmer 767: #ifdef COMPAT_50
1.35 mbalmer 768: static int
1.19 mbalmer 769: gpio_ioctl_oapi(struct gpio_softc *sc, u_long cmd, void *data, int flag,
770: kauth_cred_t cred)
771: {
772: gpio_chipset_tag_t gc;
773: struct gpio_pin_op *op;
774: struct gpio_pin_ctl *ctl;
1.45 mbalmer 775: struct gpio_attach *attach;
776: struct gpio_dev *gdev;
777:
778: int error, pin, value, flags;
1.19 mbalmer 779:
780: gc = sc->sc_gc;
781:
782: switch (cmd) {
1.1 jmcneill 783: case GPIOPINREAD:
1.43 mbalmer 784: op = data;
1.1 jmcneill 785:
786: pin = op->gp_pin;
1.19 mbalmer 787:
1.1 jmcneill 788: if (pin < 0 || pin >= sc->sc_npins)
1.19 mbalmer 789: return EINVAL;
790:
791: if (!(sc->sc_pins[pin].pin_flags & GPIO_PIN_SET) &&
792: kauth_authorize_device(cred, KAUTH_DEVICE_GPIO_PINSET,
793: NULL, NULL, NULL, NULL))
794: return EPERM;
1.1 jmcneill 795:
796: /* return read value */
797: op->gp_value = gpiobus_pin_read(gc, pin);
798: break;
799: case GPIOPINWRITE:
1.19 mbalmer 800: if ((flag & FWRITE) == 0)
801: return EBADF;
802:
1.43 mbalmer 803: op = data;
1.1 jmcneill 804:
805: pin = op->gp_pin;
1.19 mbalmer 806:
1.1 jmcneill 807: if (pin < 0 || pin >= sc->sc_npins)
1.19 mbalmer 808: return EINVAL;
809:
1.5 riz 810: if (sc->sc_pins[pin].pin_mapped)
1.19 mbalmer 811: return EBUSY;
812:
813: if (!(sc->sc_pins[pin].pin_flags & GPIO_PIN_SET) &&
814: kauth_authorize_device(cred, KAUTH_DEVICE_GPIO_PINSET,
815: NULL, NULL, NULL, NULL))
816: return EPERM;
1.1 jmcneill 817:
818: value = op->gp_value;
819: if (value != GPIO_PIN_LOW && value != GPIO_PIN_HIGH)
1.19 mbalmer 820: return EINVAL;
1.1 jmcneill 821:
822: gpiobus_pin_write(gc, pin, value);
823: /* return old value */
824: op->gp_value = sc->sc_pins[pin].pin_state;
825: /* update current value */
826: sc->sc_pins[pin].pin_state = value;
827: break;
828: case GPIOPINTOGGLE:
1.19 mbalmer 829: if ((flag & FWRITE) == 0)
830: return EBADF;
831:
1.43 mbalmer 832: op = data;
1.1 jmcneill 833:
834: pin = op->gp_pin;
1.19 mbalmer 835:
1.1 jmcneill 836: if (pin < 0 || pin >= sc->sc_npins)
1.19 mbalmer 837: return EINVAL;
838:
1.5 riz 839: if (sc->sc_pins[pin].pin_mapped)
1.19 mbalmer 840: return EBUSY;
841:
842: if (!(sc->sc_pins[pin].pin_flags & GPIO_PIN_SET) &&
843: kauth_authorize_device(cred, KAUTH_DEVICE_GPIO_PINSET,
844: NULL, NULL, NULL, NULL))
845: return EPERM;
1.1 jmcneill 846:
847: value = (sc->sc_pins[pin].pin_state == GPIO_PIN_LOW ?
848: GPIO_PIN_HIGH : GPIO_PIN_LOW);
849: gpiobus_pin_write(gc, pin, value);
850: /* return old value */
851: op->gp_value = sc->sc_pins[pin].pin_state;
852: /* update current value */
853: sc->sc_pins[pin].pin_state = value;
854: break;
855: case GPIOPINCTL:
1.43 mbalmer 856: ctl = data;
1.19 mbalmer 857:
858: if (kauth_authorize_device(cred, KAUTH_DEVICE_GPIO_PINSET,
859: NULL, NULL, NULL, NULL))
860: return EPERM;
1.1 jmcneill 861:
862: pin = ctl->gp_pin;
1.19 mbalmer 863:
1.1 jmcneill 864: if (pin < 0 || pin >= sc->sc_npins)
1.19 mbalmer 865: return EINVAL;
1.5 riz 866: if (sc->sc_pins[pin].pin_mapped)
1.19 mbalmer 867: return EBUSY;
868: flags = ctl->gp_flags;
1.1 jmcneill 869:
870: /* check that the controller supports all requested flags */
871: if ((flags & sc->sc_pins[pin].pin_caps) != flags)
1.19 mbalmer 872: return ENODEV;
1.1 jmcneill 873:
874: ctl->gp_caps = sc->sc_pins[pin].pin_caps;
875: /* return old value */
876: ctl->gp_flags = sc->sc_pins[pin].pin_flags;
877: if (flags > 0) {
878: gpiobus_pin_ctl(gc, pin, flags);
879: /* update current value */
880: sc->sc_pins[pin].pin_flags = flags;
881: }
882: break;
1.44 mbalmer 883: case GPIODETACH50:
884: /* FALLTHOUGH */
885: case GPIODETACH:
886: if (kauth_authorize_device(cred, KAUTH_DEVICE_GPIO_PINSET,
887: NULL, NULL, NULL, NULL))
888: return EPERM;
889:
890: error = 0;
891: mutex_enter(&sc->sc_mtx);
892: while (sc->sc_attach_busy) {
893: error = cv_wait_sig(&sc->sc_attach, &sc->sc_mtx);
894: if (error)
895: break;
896: }
897: if (!error)
898: sc->sc_attach_busy = 1;
899: mutex_exit(&sc->sc_mtx);
900: if (error)
901: return EBUSY;
902:
903: attach = data;
904: LIST_FOREACH(gdev, &sc->sc_devs, sc_next) {
905: if (strcmp(device_xname(gdev->sc_dev),
906: attach->ga_dvname) == 0) {
907: mutex_enter(&sc->sc_mtx);
908: sc->sc_attach_busy = 0;
909: cv_signal(&sc->sc_attach);
910: mutex_exit(&sc->sc_mtx);
911:
912: if (config_detach(gdev->sc_dev, 0) == 0)
913: return 0;
914: break;
915: }
916: }
917: if (gdev == NULL) {
918: mutex_enter(&sc->sc_mtx);
919: sc->sc_attach_busy = 0;
920: cv_signal(&sc->sc_attach);
921: mutex_exit(&sc->sc_mtx);
922: }
923: return EINVAL;
924:
1.1 jmcneill 925: default:
1.19 mbalmer 926: return ENOTTY;
1.1 jmcneill 927: }
1.19 mbalmer 928: return 0;
1.1 jmcneill 929: }
1.42 mbalmer 930: #endif /* COMPAT_50 */
1.35 mbalmer 931:
932: MODULE(MODULE_CLASS_DRIVER, gpio, NULL);
933:
1.37 mbalmer 934: #ifdef _MODULE
1.35 mbalmer 935: #include "ioconf.c"
1.37 mbalmer 936: #endif
1.35 mbalmer 937:
938: static int
939: gpio_modcmd(modcmd_t cmd, void *opaque)
940: {
1.37 mbalmer 941: #ifdef _MODULE
1.35 mbalmer 942: devmajor_t cmajor = NODEVMAJOR, bmajor = NODEVMAJOR;
943: int error;
1.37 mbalmer 944: #endif
1.35 mbalmer 945: switch (cmd) {
946: case MODULE_CMD_INIT:
1.37 mbalmer 947: #ifdef _MODULE
1.35 mbalmer 948: error = config_init_component(cfdriver_ioconf_gpio,
949: cfattach_ioconf_gpio, cfdata_ioconf_gpio);
950: if (error) {
951: aprint_error("%s: unable to init component\n",
952: gpio_cd.cd_name);
953: return error;
954: }
955: error = devsw_attach(gpio_cd.cd_name, NULL, &bmajor,
956: &gpio_cdevsw, &cmajor);
957: if (error) {
958: aprint_error("%s: unable to register devsw\n",
959: gpio_cd.cd_name);
960: return config_fini_component(cfdriver_ioconf_gpio,
961: cfattach_ioconf_gpio, cfdata_ioconf_gpio);
962: }
1.37 mbalmer 963: #endif
1.35 mbalmer 964: return 0;
965: case MODULE_CMD_FINI:
1.37 mbalmer 966: #ifdef _MODULE
1.35 mbalmer 967: config_fini_component(cfdriver_ioconf_gpio,
968: cfattach_ioconf_gpio, cfdata_ioconf_gpio);
969: devsw_detach(NULL, &gpio_cdevsw);
1.37 mbalmer 970: #endif
1.35 mbalmer 971: return 0;
972: default:
973: return ENOTTY;
974: }
975: }
CVSweb <webmaster@jp.NetBSD.org>