[BACK]Return to gpio.c CVS log [TXT][DIR] Up to [cvs.NetBSD.org] / src / sys / dev / gpio

Annotation of src/sys/dev/gpio/gpio.c, Revision 1.64.10.9

1.64.10.9! thorpej     1: /* $NetBSD: gpio.c,v 1.64.10.8 2021/04/04 22:01:22 thorpej 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.64.10.9! thorpej    22: __KERNEL_RCSID(0, "$NetBSD: gpio.c,v 1.64.10.8 2021/04/04 22:01:22 thorpej 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.60      riastrad   46: #include "ioconf.h"
1.3       drochner   47: #include "locators.h"
                     48:
1.19      mbalmer    49: #ifdef GPIO_DEBUG
1.21      cegger     50: #define DPRINTFN(n, x) do { if (gpiodebug > (n)) printf x; } while (0)
1.19      mbalmer    51: int gpiodebug = 0;
                     52: #else
                     53: #define DPRINTFN(n, x)
                     54: #endif
                     55: #define DPRINTF(x)     DPRINTFN(0, x)
                     56:
1.1       jmcneill   57: struct gpio_softc {
1.19      mbalmer    58:        device_t                 sc_dev;
1.1       jmcneill   59:
1.19      mbalmer    60:        gpio_chipset_tag_t       sc_gc;         /* GPIO controller */
                     61:        gpio_pin_t              *sc_pins;       /* pins array */
                     62:        int                      sc_npins;      /* number of pins */
                     63:
1.36      mbalmer    64:        kmutex_t                 sc_mtx;
                     65:        kcondvar_t               sc_ioctl;      /* ioctl in progress */
                     66:        int                      sc_ioctl_busy; /* ioctl is busy */
1.39      mbalmer    67:        kcondvar_t               sc_attach;     /* attach/detach in progress */
                     68:        int                      sc_attach_busy;/* busy in attach/detach */
1.45      mbalmer    69: #ifdef COMPAT_50
1.19      mbalmer    70:        LIST_HEAD(, gpio_dev)    sc_devs;       /* devices */
1.45      mbalmer    71: #endif
1.19      mbalmer    72:        LIST_HEAD(, gpio_name)   sc_names;      /* named pins */
1.1       jmcneill   73: };
                     74:
1.35      mbalmer    75: static int     gpio_match(device_t, cfdata_t, void *);
                     76: int            gpio_submatch(device_t, cfdata_t, const int *, void *);
                     77: static void    gpio_attach(device_t, device_t, void *);
                     78: static int     gpio_rescan(device_t, const char *, const int *);
                     79: static void    gpio_childdetached(device_t, device_t);
                     80: static bool    gpio_resume(device_t, const pmf_qual_t *);
                     81: static int     gpio_detach(device_t, int);
                     82: static int     gpio_search(device_t, cfdata_t, const int *, void *);
                     83: static int     gpio_print(void *, const char *);
                     84: static int     gpio_pinbyname(struct gpio_softc *, char *);
1.36      mbalmer    85: static int     gpio_ioctl(struct gpio_softc *, u_long, void *, int,
                     86:     struct lwp *);
1.19      mbalmer    87:
1.42      mbalmer    88: #ifdef COMPAT_50
1.19      mbalmer    89: /* Old API */
1.35      mbalmer    90: static int     gpio_ioctl_oapi(struct gpio_softc *, u_long, void *, int,
                     91:     kauth_cred_t);
1.42      mbalmer    92: #endif
1.1       jmcneill   93:
1.18      dyoung     94: CFATTACH_DECL3_NEW(gpio, sizeof(struct gpio_softc),
1.29      dyoung     95:     gpio_match, gpio_attach, gpio_detach, NULL, gpio_rescan,
                     96:     gpio_childdetached, DVF_DETACH_SHUTDOWN);
1.1       jmcneill   97:
                     98: dev_type_open(gpioopen);
                     99: dev_type_close(gpioclose);
                    100: dev_type_ioctl(gpioioctl);
1.36      mbalmer   101: dev_type_ioctl(gpioioctl_locked);
1.1       jmcneill  102:
                    103: const struct cdevsw gpio_cdevsw = {
1.53      dholland  104:        .d_open = gpioopen,
                    105:        .d_close = gpioclose,
                    106:        .d_read = noread,
                    107:        .d_write = nowrite,
                    108:        .d_ioctl = gpioioctl,
                    109:        .d_stop = nostop,
                    110:        .d_tty = notty,
                    111:        .d_poll = nopoll,
                    112:        .d_mmap = nommap,
                    113:        .d_kqfilter = nokqfilter,
1.57      dholland  114:        .d_discard = nodiscard,
1.53      dholland  115:        .d_flag = D_OTHER | D_MPSAFE
1.1       jmcneill  116: };
                    117:
1.35      mbalmer   118: static int
1.17      cegger    119: gpio_match(device_t parent, cfdata_t cf, void *aux)
1.1       jmcneill  120: {
1.19      mbalmer   121:        return 1;
                    122: }
                    123:
                    124: int
                    125: gpio_submatch(device_t parent, cfdata_t cf, const int *ip, void *aux)
                    126: {
                    127:        struct gpio_attach_args *ga = aux;
1.1       jmcneill  128:
1.19      mbalmer   129:        if (ga->ga_offset == -1)
                    130:                return 0;
                    131:
                    132:        return strcmp(ga->ga_dvname, cf->cf_name) == 0;
1.1       jmcneill  133: }
                    134:
1.35      mbalmer   135: static bool
1.32      dyoung    136: gpio_resume(device_t self, const pmf_qual_t *qual)
1.13      dyoung    137: {
                    138:        struct gpio_softc *sc = device_private(self);
                    139:        int pin;
                    140:
                    141:        for (pin = 0; pin < sc->sc_npins; pin++) {
                    142:                gpiobus_pin_ctl(sc->sc_gc, pin, sc->sc_pins[pin].pin_flags);
                    143:                gpiobus_pin_write(sc->sc_gc, pin, sc->sc_pins[pin].pin_state);
                    144:        }
                    145:        return true;
                    146: }
                    147:
1.35      mbalmer   148: static void
1.29      dyoung    149: gpio_childdetached(device_t self, device_t child)
                    150: {
1.45      mbalmer   151: #ifdef COMPAT_50
1.39      mbalmer   152:        struct gpio_dev *gdev;
                    153:        struct gpio_softc *sc;
                    154:        int error;
                    155:
                    156:        /*
                    157:         * gpio_childetached is serialized because it can be entered in
                    158:         * different ways concurrently, e.g. via the GPIODETACH ioctl and
                    159:         * drvctl(8) or modunload(8).
                    160:         */
                    161:        sc = device_private(self);
                    162:        error = 0;
                    163:        mutex_enter(&sc->sc_mtx);
                    164:        while (sc->sc_attach_busy) {
                    165:                error = cv_wait_sig(&sc->sc_attach, &sc->sc_mtx);
                    166:                if (error)
                    167:                        break;
                    168:        }
                    169:        if (!error)
                    170:                sc->sc_attach_busy = 1;
                    171:        mutex_exit(&sc->sc_mtx);
                    172:        if (error)
                    173:                return;
                    174:
                    175:        LIST_FOREACH(gdev, &sc->sc_devs, sc_next)
                    176:                if (gdev->sc_dev == child) {
                    177:                        LIST_REMOVE(gdev, sc_next);
                    178:                        kmem_free(gdev, sizeof(struct gpio_dev));
                    179:                        break;
                    180:                }
                    181:
                    182:        mutex_enter(&sc->sc_mtx);
                    183:        sc->sc_attach_busy = 0;
                    184:        cv_signal(&sc->sc_attach);
                    185:        mutex_exit(&sc->sc_mtx);
1.45      mbalmer   186: #endif
1.29      dyoung    187: }
                    188:
1.35      mbalmer   189: static int
1.29      dyoung    190: gpio_rescan(device_t self, const char *ifattr, const int *locators)
                    191: {
                    192:
1.64.10.2  thorpej   193:        config_search(self, NULL,
1.64.10.8  thorpej   194:            CFARG_SEARCH, gpio_search,
1.64.10.1  thorpej   195:            CFARG_EOL);
1.29      dyoung    196:
                    197:        return 0;
                    198: }
                    199:
1.35      mbalmer   200: static void
1.14      dyoung    201: gpio_attach(device_t parent, device_t self, void *aux)
1.1       jmcneill  202: {
1.7       thorpej   203:        struct gpio_softc *sc = device_private(self);
1.1       jmcneill  204:        struct gpiobus_attach_args *gba = aux;
1.59      jmcneill  205:        struct gpio_name *nm;
                    206:        int pin;
1.47      mbalmer   207:
1.17      cegger    208:        sc->sc_dev = self;
1.1       jmcneill  209:        sc->sc_gc = gba->gba_gc;
                    210:        sc->sc_pins = gba->gba_pins;
                    211:        sc->sc_npins = gba->gba_npins;
                    212:
1.51      dyoung    213:        aprint_normal(": %d pins\n", sc->sc_npins);
1.55      msaitoh   214:        aprint_naive("\n");
1.1       jmcneill  215:
1.59      jmcneill  216:        /* Configure default pin names */
                    217:        for (pin = 0; pin < sc->sc_npins; pin++) {
                    218:                if (sc->sc_pins[pin].pin_defname[0] == '\0')
                    219:                        continue;
                    220:                nm = kmem_alloc(sizeof(*nm), KM_SLEEP);
                    221:                strlcpy(nm->gp_name, sc->sc_pins[pin].pin_defname,
                    222:                    sizeof(nm->gp_name));
                    223:                nm->gp_pin = pin;
                    224:                LIST_INSERT_HEAD(&sc->sc_names, nm, gp_next);
                    225:        }
                    226:
1.13      dyoung    227:        if (!pmf_device_register(self, NULL, gpio_resume))
                    228:                aprint_error_dev(self, "couldn't establish power handler\n");
1.36      mbalmer   229:        mutex_init(&sc->sc_mtx, MUTEX_DEFAULT, IPL_VM);
                    230:        cv_init(&sc->sc_ioctl, "gpioctl");
1.39      mbalmer   231:        cv_init(&sc->sc_attach, "gpioatch");
1.1       jmcneill  232:        /*
                    233:         * Attach all devices that can be connected to the GPIO pins
                    234:         * described in the kernel configuration file.
                    235:         */
1.29      dyoung    236:        gpio_rescan(self, "gpio", NULL);
1.1       jmcneill  237: }
                    238:
1.35      mbalmer   239: static int
1.14      dyoung    240: gpio_detach(device_t self, int flags)
1.1       jmcneill  241: {
1.36      mbalmer   242:        struct gpio_softc *sc;
1.47      mbalmer   243:        int rc;
1.36      mbalmer   244:
                    245:        sc = device_private(self);
                    246:
1.29      dyoung    247:        if ((rc = config_detach_children(self, flags)) != 0)
                    248:                return rc;
1.36      mbalmer   249:        mutex_destroy(&sc->sc_mtx);
                    250:        cv_destroy(&sc->sc_ioctl);
1.1       jmcneill  251: #if 0
                    252:        int maj, mn;
                    253:
                    254:        /* Locate the major number */
                    255:        for (maj = 0; maj < nchrdev; maj++)
                    256:                if (cdevsw[maj].d_open == gpioopen)
                    257:                        break;
                    258:
                    259:        /* Nuke the vnodes for any open instances (calls close) */
1.6       thorpej   260:        mn = device_unit(self);
1.1       jmcneill  261:        vdevgone(maj, mn, mn, VCHR);
                    262: #endif
1.19      mbalmer   263:        return 0;
1.1       jmcneill  264: }
                    265:
1.35      mbalmer   266: static int
1.31      mbalmer   267: gpio_search(device_t parent, cfdata_t cf, const int *ldesc, void *aux)
1.1       jmcneill  268: {
                    269:        struct gpio_attach_args ga;
1.49      mbalmer   270:        size_t namlen;
1.1       jmcneill  271:
1.64.10.2  thorpej   272:        ga.ga_gpio = device_private(parent);
1.5       riz       273:        ga.ga_offset = cf->cf_loc[GPIOCF_OFFSET];
1.3       drochner  274:        ga.ga_mask = cf->cf_loc[GPIOCF_MASK];
1.42      mbalmer   275:        ga.ga_flags = cf->cf_loc[GPIOCF_FLAG];
1.49      mbalmer   276:        namlen = strlen(cf->cf_name) + 1;
1.63      chs       277:        ga.ga_dvname = kmem_alloc(namlen, KM_SLEEP);
1.49      mbalmer   278:        strcpy(ga.ga_dvname, cf->cf_name);
1.1       jmcneill  279:
1.64.10.9! thorpej   280:        if (config_probe(parent, cf, &ga) > 0)
1.64.10.6  thorpej   281:                config_attach(parent, cf, &ga, gpio_print, CFARG_EOL);
1.49      mbalmer   282:        kmem_free(ga.ga_dvname, namlen);
1.19      mbalmer   283:        return 0;
1.1       jmcneill  284: }
                    285:
                    286: int
1.11      christos  287: gpio_print(void *aux, const char *pnp)
1.1       jmcneill  288: {
                    289:        struct gpio_attach_args *ga = aux;
                    290:        int i;
                    291:
1.54      christos  292:        aprint_normal(" pins");
1.1       jmcneill  293:        for (i = 0; i < 32; i++)
                    294:                if (ga->ga_mask & (1 << i))
1.54      christos  295:                        aprint_normal(" %d", ga->ga_offset + i);
1.1       jmcneill  296:
1.19      mbalmer   297:        return UNCONF;
1.1       jmcneill  298: }
                    299:
                    300: int
1.11      christos  301: gpiobus_print(void *aux, const char *pnp)
1.1       jmcneill  302: {
1.3       drochner  303: #if 0
1.1       jmcneill  304:        struct gpiobus_attach_args *gba = aux;
1.3       drochner  305: #endif
1.1       jmcneill  306:        if (pnp != NULL)
1.33      ad        307:                aprint_normal("gpiobus at %s", pnp);
1.1       jmcneill  308:
1.19      mbalmer   309:        return UNCONF;
1.1       jmcneill  310: }
                    311:
1.58      bouyer    312: void *
                    313: gpio_find_device(const char *name)
                    314: {
                    315:        device_t gpio_dev;
                    316:        gpio_dev = device_find_by_xname(name);
                    317:        if (gpio_dev == NULL)
                    318:                return NULL;
                    319:        return device_private(gpio_dev);
                    320: }
                    321:
                    322: const char *
                    323: gpio_get_name(void *gpio)
                    324: {
                    325:        struct gpio_softc *sc = gpio;
                    326:        return device_xname(sc->sc_dev);
                    327: }
                    328:
1.27      mbalmer   329: /* return 1 if all pins can be mapped, 0 if not */
                    330: int
1.36      mbalmer   331: gpio_pin_can_map(void *gpio, int offset, uint32_t mask)
1.27      mbalmer   332: {
                    333:        struct gpio_softc *sc = gpio;
                    334:        int npins, pin, i;
                    335:
                    336:        npins = gpio_npins(mask);
                    337:        if (npins > sc->sc_npins)
                    338:                return 0;
                    339:
                    340:        for (npins = 0, i = 0; i < 32; i++)
                    341:                if (mask & (1 << i)) {
                    342:                        pin = offset + i;
                    343:                        if (pin < 0 || pin >= sc->sc_npins)
                    344:                                return 0;
                    345:                        if (sc->sc_pins[pin].pin_mapped)
                    346:                                return 0;
                    347:                }
                    348:
                    349:        return 1;
                    350: }
                    351:
1.8       uwe       352: int
1.36      mbalmer   353: gpio_pin_map(void *gpio, int offset, uint32_t mask, struct gpio_pinmap *map)
1.5       riz       354: {
                    355:        struct gpio_softc *sc = gpio;
                    356:        int npins, pin, i;
                    357:
                    358:        npins = gpio_npins(mask);
                    359:        if (npins > sc->sc_npins)
1.19      mbalmer   360:                return 1;
1.5       riz       361:
                    362:        for (npins = 0, i = 0; i < 32; i++)
                    363:                if (mask & (1 << i)) {
                    364:                        pin = offset + i;
                    365:                        if (pin < 0 || pin >= sc->sc_npins)
1.19      mbalmer   366:                                return 1;
1.5       riz       367:                        if (sc->sc_pins[pin].pin_mapped)
1.19      mbalmer   368:                                return 1;
1.5       riz       369:                        sc->sc_pins[pin].pin_mapped = 1;
                    370:                        map->pm_map[npins++] = pin;
                    371:                }
                    372:        map->pm_size = npins;
                    373:
1.19      mbalmer   374:        return 0;
1.5       riz       375: }
                    376:
                    377: void
                    378: gpio_pin_unmap(void *gpio, struct gpio_pinmap *map)
                    379: {
                    380:        struct gpio_softc *sc = gpio;
                    381:        int pin, i;
                    382:
                    383:        for (i = 0; i < map->pm_size; i++) {
                    384:                pin = map->pm_map[i];
                    385:                sc->sc_pins[pin].pin_mapped = 0;
                    386:        }
                    387: }
                    388:
                    389: int
                    390: gpio_pin_read(void *gpio, struct gpio_pinmap *map, int pin)
                    391: {
                    392:        struct gpio_softc *sc = gpio;
                    393:
1.19      mbalmer   394:        return gpiobus_pin_read(sc->sc_gc, map->pm_map[pin]);
1.5       riz       395: }
                    396:
                    397: void
                    398: gpio_pin_write(void *gpio, struct gpio_pinmap *map, int pin, int value)
                    399: {
                    400:        struct gpio_softc *sc = gpio;
                    401:
1.13      dyoung    402:        gpiobus_pin_write(sc->sc_gc, map->pm_map[pin], value);
                    403:        sc->sc_pins[map->pm_map[pin]].pin_state = value;
1.5       riz       404: }
                    405:
1.61      thorpej   406: int
                    407: gpio_pin_get_conf(void *gpio, struct gpio_pinmap *map, int pin)
                    408: {
                    409:        struct gpio_softc *sc = gpio;
                    410:        int rv;
                    411:
                    412:        mutex_enter(&sc->sc_mtx);
                    413:        rv = sc->sc_pins[map->pm_map[pin]].pin_flags;
                    414:        mutex_exit(&sc->sc_mtx);
                    415:
                    416:        return (rv);
                    417: }
                    418:
                    419: bool
                    420: gpio_pin_set_conf(void *gpio, struct gpio_pinmap *map, int pin, int flags)
                    421: {
                    422:        struct gpio_softc *sc = gpio;
                    423:        int checkflags = flags & GPIO_PIN_HWCAPS;
                    424:
                    425:        if ((sc->sc_pins[map->pm_map[pin]].pin_caps & checkflags) != checkflags)
                    426:                return (false);
                    427:
                    428:        gpio_pin_ctl(gpio, map, pin, flags);
                    429:
                    430:        return (true);
                    431: }
                    432:
1.5       riz       433: void
                    434: gpio_pin_ctl(void *gpio, struct gpio_pinmap *map, int pin, int flags)
                    435: {
                    436:        struct gpio_softc *sc = gpio;
                    437:
1.61      thorpej   438:        /* loosey-goosey version of gpio_pin_set_conf(). */
                    439:
1.58      bouyer    440:        mutex_enter(&sc->sc_mtx);
                    441:        gpiobus_pin_ctl(sc->sc_gc, map->pm_map[pin], flags);
1.61      thorpej   442:        sc->sc_pins[map->pm_map[pin]].pin_flags = flags;
1.58      bouyer    443:        mutex_exit(&sc->sc_mtx);
                    444: }
                    445:
                    446: int
1.61      thorpej   447: gpio_pin_caps(void *gpio, struct gpio_pinmap *map, int pin)
1.58      bouyer    448: {
                    449:        struct gpio_softc *sc = gpio;
1.61      thorpej   450:
                    451:        return sc->sc_pins[map->pm_map[pin]].pin_caps;
                    452: }
                    453:
                    454: int
                    455: gpio_pin_intrcaps(void *gpio, struct gpio_pinmap *map, int pin)
                    456: {
                    457:        struct gpio_softc *sc = gpio;
                    458:
                    459:        return sc->sc_pins[map->pm_map[pin]].pin_intrcaps;
                    460: }
                    461:
                    462: static int
                    463: gpio_irqmode_sanitize(int irqmode)
                    464: {
                    465:        int has_edge, has_level;
                    466:
                    467:        has_edge  = irqmode & GPIO_INTR_EDGE_MASK;
                    468:        has_level = irqmode & GPIO_INTR_LEVEL_MASK;
                    469:
                    470:        /* Must specify an interrupt mode. */
                    471:        if ((irqmode & GPIO_INTR_MODE_MASK) == 0)
                    472:                return (0);
                    473:
                    474:        /* Can't specify edge and level together */
                    475:        if (has_level && has_edge)
                    476:                return (0);
                    477:
                    478:        /* "Be liberal in what you accept..." */
                    479:        if (has_edge) {
                    480:                if (irqmode & GPIO_INTR_DOUBLE_EDGE) {
                    481:                        /* if DOUBLE is set, just pass through DOUBLE */
                    482:                        irqmode = (irqmode & ~GPIO_INTR_EDGE_MASK) |
                    483:                            GPIO_INTR_DOUBLE_EDGE;
                    484:                } else if ((irqmode ^
                    485:                            (GPIO_INTR_POS_EDGE | GPIO_INTR_NEG_EDGE)) == 0) {
                    486:                        /* both POS and NEG set; treat as DOUBLE */
                    487:                        irqmode = (irqmode & ~GPIO_INTR_EDGE_MASK) |
                    488:                            GPIO_INTR_DOUBLE_EDGE;
                    489:                }
                    490:        } else {
                    491:                /* Can't specify both levels together. */
                    492:                if (has_level == GPIO_INTR_LEVEL_MASK)
                    493:                        return (0);
                    494:        }
                    495:
                    496:        return (irqmode);
                    497: }
                    498:
                    499: bool
                    500: gpio_pin_irqmode_issupported(void *gpio, struct gpio_pinmap *map,
                    501:                             int pin, int irqmode)
                    502: {
                    503:        struct gpio_softc *sc = gpio;
                    504:        int match;
                    505:
                    506:        irqmode = gpio_irqmode_sanitize(irqmode) & GPIO_INTR_MODE_MASK;
                    507:
                    508:        /* Make sure the pin can do what is being asked. */
                    509:        match = sc->sc_pins[map->pm_map[pin]].pin_intrcaps & irqmode;
                    510:
                    511:        return (irqmode && irqmode == match);
                    512: }
                    513:
                    514: void *
                    515: gpio_intr_establish(void *gpio, struct gpio_pinmap *map, int pin, int ipl,
                    516:                    int irqmode, int (*func)(void *), void *arg)
                    517: {
                    518:        struct gpio_softc *sc = gpio;
                    519:
                    520:        if (sc->sc_gc->gp_intr_establish == NULL)
                    521:                return (NULL);
                    522:
                    523:        irqmode = gpio_irqmode_sanitize(irqmode);
                    524:        if (irqmode == 0)
                    525:                return (NULL);
                    526:
                    527:        if (! gpio_pin_irqmode_issupported(gpio, map, pin, irqmode))
                    528:                return (NULL);
                    529:
                    530:        /* XXX Right now, everything has to be at IPL_VM. */
1.58      bouyer    531:        if (ipl != IPL_VM)
1.61      thorpej   532:                return (NULL);
                    533:
                    534:        return ((*sc->sc_gc->gp_intr_establish)(sc->sc_gc->gp_cookie,
                    535:            sc->sc_pins[map->pm_map[pin]].pin_num, ipl, irqmode, func, arg));
1.58      bouyer    536: }
                    537:
                    538: void
1.61      thorpej   539: gpio_intr_disestablish(void *gpio, void *ih)
1.58      bouyer    540: {
                    541:        struct gpio_softc *sc = gpio;
1.61      thorpej   542:
                    543:        if (sc->sc_gc->gp_intr_disestablish != NULL && ih != NULL)
                    544:                (*sc->sc_gc->gp_intr_disestablish)(sc->sc_gc->gp_cookie, ih);
1.5       riz       545: }
                    546:
1.61      thorpej   547: bool
                    548: gpio_intr_str(void *gpio, struct gpio_pinmap *map, int pin, int irqmode,
                    549:              char *intrstr, size_t intrstrlen)
1.5       riz       550: {
                    551:        struct gpio_softc *sc = gpio;
1.61      thorpej   552:        const char *mode;
                    553:        char hwstr[64];
1.5       riz       554:
1.61      thorpej   555:        if (sc->sc_gc->gp_intr_str == NULL)
                    556:                return (false);
                    557:
                    558:        irqmode = gpio_irqmode_sanitize(irqmode);
                    559:        if (irqmode == 0)
                    560:                return (false);
                    561:
                    562:        if (irqmode & GPIO_INTR_DOUBLE_EDGE)
                    563:                mode = "double edge";
                    564:        else if (irqmode & GPIO_INTR_POS_EDGE)
                    565:                mode = "positive edge";
                    566:        else if (irqmode & GPIO_INTR_NEG_EDGE)
                    567:                mode = "negative edge";
                    568:        else if (irqmode & GPIO_INTR_HIGH_LEVEL)
                    569:                mode = "high level";
                    570:        else if (irqmode & GPIO_INTR_LOW_LEVEL)
                    571:                mode = "low level";
                    572:        else
                    573:                return (false);
                    574:
                    575:        if (! (*sc->sc_gc->gp_intr_str)(sc->sc_gc->gp_cookie,
                    576:                                        sc->sc_pins[map->pm_map[pin]].pin_num,
                    577:                                        irqmode, hwstr, sizeof(hwstr)))
                    578:                return (false);
                    579:
                    580:        (void) snprintf(intrstr, intrstrlen, "%s (%s)", hwstr, mode);
                    581:
                    582:        return (true);
1.5       riz       583: }
                    584:
                    585: int
1.36      mbalmer   586: gpio_npins(uint32_t mask)
1.5       riz       587: {
                    588:        int npins, i;
                    589:
                    590:        for (npins = 0, i = 0; i < 32; i++)
                    591:                if (mask & (1 << i))
                    592:                        npins++;
                    593:
1.19      mbalmer   594:        return npins;
1.5       riz       595: }
                    596:
1.1       jmcneill  597: int
1.36      mbalmer   598: gpio_lock(void *data)
                    599: {
                    600:        struct gpio_softc *sc;
                    601:        int error;
                    602:
                    603:        error = 0;
1.43      mbalmer   604:        sc = data;
1.36      mbalmer   605:        mutex_enter(&sc->sc_mtx);
                    606:        while (sc->sc_ioctl_busy) {
                    607:                error = cv_wait_sig(&sc->sc_ioctl, &sc->sc_mtx);
                    608:                if (error)
                    609:                        break;
                    610:        }
                    611:        if (!error)
                    612:                sc->sc_ioctl_busy = 1;
                    613:        mutex_exit(&sc->sc_mtx);
                    614:        return error;
                    615: }
                    616:
                    617: void
                    618: gpio_unlock(void *data)
                    619: {
                    620:        struct gpio_softc *sc;
                    621:
1.43      mbalmer   622:        sc = data;
1.36      mbalmer   623:        mutex_enter(&sc->sc_mtx);
                    624:        sc->sc_ioctl_busy = 0;
                    625:        cv_signal(&sc->sc_ioctl);
                    626:        mutex_exit(&sc->sc_mtx);
                    627: }
                    628:
                    629: int
1.26      mbalmer   630: gpioopen(dev_t dev, int flag, int mode, struct lwp *l)
1.1       jmcneill  631: {
                    632:        struct gpio_softc *sc;
                    633:
1.17      cegger    634:        sc = device_lookup_private(&gpio_cd, minor(dev));
1.1       jmcneill  635:        if (sc == NULL)
1.19      mbalmer   636:                return ENXIO;
1.1       jmcneill  637:
1.36      mbalmer   638:        return gpiobus_open(sc->sc_gc, sc->sc_dev);
1.1       jmcneill  639: }
                    640:
                    641: int
1.26      mbalmer   642: gpioclose(dev_t dev, int flag, int mode, struct lwp *l)
1.1       jmcneill  643: {
                    644:        struct gpio_softc *sc;
                    645:
1.17      cegger    646:        sc = device_lookup_private(&gpio_cd, minor(dev));
1.50      mbalmer   647:        return gpiobus_close(sc->sc_gc, sc->sc_dev);
1.19      mbalmer   648: }
                    649:
1.35      mbalmer   650: static int
1.19      mbalmer   651: gpio_pinbyname(struct gpio_softc *sc, char *gp_name)
                    652: {
                    653:         struct gpio_name *nm;
                    654:
                    655:         LIST_FOREACH(nm, &sc->sc_names, gp_next)
                    656:                 if (!strcmp(nm->gp_name, gp_name))
                    657:                         return nm->gp_pin;
                    658:         return -1;
1.1       jmcneill  659: }
                    660:
                    661: int
1.26      mbalmer   662: gpioioctl(dev_t dev, u_long cmd, void *data, int flag, struct lwp *l)
1.1       jmcneill  663: {
1.36      mbalmer   664:        int error;
1.1       jmcneill  665:        struct gpio_softc *sc;
1.36      mbalmer   666:
                    667:        sc = device_lookup_private(&gpio_cd, minor(dev));
                    668:
                    669:        error = gpio_lock(sc);
                    670:        if (error)
                    671:                return error;
                    672:
                    673:        error = gpio_ioctl(sc, cmd, data, flag, l);
                    674:        gpio_unlock(sc);
                    675:        return error;
                    676: }
                    677:
                    678: static int
                    679: gpio_ioctl(struct gpio_softc *sc, u_long cmd, void *data, int flag,
                    680:     struct lwp *l)
                    681: {
1.1       jmcneill  682:        gpio_chipset_tag_t gc;
                    683:        struct gpio_info *info;
1.19      mbalmer   684:        struct gpio_attach *attach;
                    685:        struct gpio_attach_args ga;
1.45      mbalmer   686:        struct gpio_req *req;
1.19      mbalmer   687:        struct gpio_name *nm;
                    688:        struct gpio_set *set;
1.46      mbalmer   689: #ifdef COMPAT_50
                    690:        struct gpio_dev *gdev;
                    691: #endif
1.20      mbalmer   692:        device_t dv;
1.24      mbalmer   693:        cfdata_t cf;
1.19      mbalmer   694:        kauth_cred_t cred;
                    695:        int locs[GPIOCF_NLOCS];
1.39      mbalmer   696:        int error, pin, value, flags, npins;
1.1       jmcneill  697:
                    698:        gc = sc->sc_gc;
1.42      mbalmer   699:        ga.ga_flags = 0;
1.1       jmcneill  700:
1.19      mbalmer   701:        if (cmd != GPIOINFO && !device_is_active(sc->sc_dev)) {
1.26      mbalmer   702:                DPRINTF(("%s: device is not active\n",
                    703:                    device_xname(sc->sc_dev)));
1.13      dyoung    704:                return EBUSY;
1.19      mbalmer   705:        }
1.35      mbalmer   706:
1.19      mbalmer   707:        cred = kauth_cred_get();
1.13      dyoung    708:
1.1       jmcneill  709:        switch (cmd) {
                    710:        case GPIOINFO:
1.43      mbalmer   711:                info = data;
1.19      mbalmer   712:                if (!kauth_authorize_device(cred, KAUTH_DEVICE_GPIO_PINSET,
                    713:                    NULL, NULL, NULL, NULL))
                    714:                        info->gpio_npins = sc->sc_npins;
                    715:                else {
                    716:                        for (pin = npins = 0; pin < sc->sc_npins; pin++)
                    717:                                if (sc->sc_pins[pin].pin_flags & GPIO_PIN_SET)
                    718:                                        ++npins;
                    719:                        info->gpio_npins = npins;
                    720:                }
                    721:                break;
                    722:        case GPIOREAD:
1.43      mbalmer   723:                req = data;
1.19      mbalmer   724:
1.36      mbalmer   725:                if (req->gp_name[0] != '\0')
1.64      tnn       726:                        req->gp_pin = gpio_pinbyname(sc, req->gp_name);
                    727:                pin = req->gp_pin;
1.19      mbalmer   728:
                    729:                if (pin < 0 || pin >= sc->sc_npins)
                    730:                        return EINVAL;
                    731:
                    732:                if (!(sc->sc_pins[pin].pin_flags & GPIO_PIN_SET) &&
                    733:                    kauth_authorize_device(cred, KAUTH_DEVICE_GPIO_PINSET,
                    734:                    NULL, NULL, NULL, NULL))
                    735:                        return EPERM;
                    736:
                    737:                /* return read value */
                    738:                req->gp_value = gpiobus_pin_read(gc, pin);
1.64      tnn       739:                LIST_FOREACH(nm, &sc->sc_names, gp_next)
                    740:                        if (nm->gp_pin == pin) {
                    741:                                strlcpy(req->gp_name, nm->gp_name, GPIOMAXNAME);
                    742:                                break;
                    743:                        }
1.19      mbalmer   744:                break;
                    745:        case GPIOWRITE:
                    746:                if ((flag & FWRITE) == 0)
                    747:                        return EBADF;
                    748:
1.43      mbalmer   749:                req = data;
1.19      mbalmer   750:
1.36      mbalmer   751:                if (req->gp_name[0] != '\0')
1.19      mbalmer   752:                        pin = gpio_pinbyname(sc, req->gp_name);
1.36      mbalmer   753:                else
1.19      mbalmer   754:                        pin = req->gp_pin;
                    755:
                    756:                if (pin < 0 || pin >= sc->sc_npins)
                    757:                        return EINVAL;
                    758:
                    759:                if (sc->sc_pins[pin].pin_mapped)
                    760:                        return EBUSY;
                    761:
                    762:                if (!(sc->sc_pins[pin].pin_flags & GPIO_PIN_SET) &&
                    763:                    kauth_authorize_device(cred, KAUTH_DEVICE_GPIO_PINSET,
                    764:                    NULL, NULL, NULL, NULL))
                    765:                        return EPERM;
1.1       jmcneill  766:
1.19      mbalmer   767:                value = req->gp_value;
                    768:                if (value != GPIO_PIN_LOW && value != GPIO_PIN_HIGH)
                    769:                        return EINVAL;
                    770:
1.52      mbalmer   771:                /* return old value */
                    772:                req->gp_value = gpiobus_pin_read(gc, pin);
1.19      mbalmer   773:                gpiobus_pin_write(gc, pin, value);
                    774:                /* update current value */
                    775:                sc->sc_pins[pin].pin_state = value;
1.1       jmcneill  776:                break;
1.19      mbalmer   777:        case GPIOTOGGLE:
                    778:                if ((flag & FWRITE) == 0)
                    779:                        return EBADF;
                    780:
1.43      mbalmer   781:                req = data;
1.19      mbalmer   782:
1.36      mbalmer   783:                if (req->gp_name[0] != '\0')
1.19      mbalmer   784:                        pin = gpio_pinbyname(sc, req->gp_name);
1.36      mbalmer   785:                else
1.19      mbalmer   786:                        pin = req->gp_pin;
                    787:
                    788:                if (pin < 0 || pin >= sc->sc_npins)
                    789:                        return EINVAL;
                    790:
                    791:                if (sc->sc_pins[pin].pin_mapped)
                    792:                        return EBUSY;
                    793:
                    794:                if (!(sc->sc_pins[pin].pin_flags & GPIO_PIN_SET) &&
                    795:                    kauth_authorize_device(cred, KAUTH_DEVICE_GPIO_PINSET,
                    796:                    NULL, NULL, NULL, NULL))
                    797:                        return EPERM;
                    798:
                    799:                value = (sc->sc_pins[pin].pin_state == GPIO_PIN_LOW ?
                    800:                    GPIO_PIN_HIGH : GPIO_PIN_LOW);
                    801:                gpiobus_pin_write(gc, pin, value);
                    802:                /* return old value */
                    803:                req->gp_value = sc->sc_pins[pin].pin_state;
                    804:                /* update current value */
                    805:                sc->sc_pins[pin].pin_state = value;
                    806:                break;
                    807:        case GPIOATTACH:
1.43      mbalmer   808:                attach = data;
1.42      mbalmer   809:                ga.ga_flags = attach->ga_flags;
                    810: #ifdef COMPAT_50
                    811:                /* FALLTHROUGH */
                    812:        case GPIOATTACH50:
                    813:                /*
                    814:                 * The double assignment to 'attach' in case of GPIOATTACH
                    815:                 * and COMPAT_50 is on purpose. It ensures backward
                    816:                 * compatability in case we are called through the old
                    817:                 * GPIOATTACH50 ioctl(2), which had not the ga_flags field
                    818:                 * in struct gpio_attach.
                    819:                 */
1.43      mbalmer   820:                attach = data;
1.42      mbalmer   821: #endif
1.19      mbalmer   822:                if (kauth_authorize_device(cred, KAUTH_DEVICE_GPIO_PINSET,
                    823:                    NULL, NULL, NULL, NULL))
                    824:                        return EPERM;
1.27      mbalmer   825:
                    826:                /* do not try to attach if the pins are already mapped */
                    827:                if (!gpio_pin_can_map(sc, attach->ga_offset, attach->ga_mask))
                    828:                        return EBUSY;
                    829:
1.39      mbalmer   830:                error = 0;
                    831:                mutex_enter(&sc->sc_mtx);
                    832:                while (sc->sc_attach_busy) {
                    833:                        error = cv_wait_sig(&sc->sc_attach, &sc->sc_mtx);
                    834:                        if (error)
                    835:                                break;
                    836:                }
                    837:                if (!error)
                    838:                        sc->sc_attach_busy = 1;
                    839:                mutex_exit(&sc->sc_mtx);
                    840:                if (error)
                    841:                        return EBUSY;
                    842:
1.19      mbalmer   843:                ga.ga_gpio = sc;
1.42      mbalmer   844:                /* Don't access attach->ga_flags here. */
1.19      mbalmer   845:                ga.ga_dvname = attach->ga_dvname;
                    846:                ga.ga_offset = attach->ga_offset;
                    847:                ga.ga_mask = attach->ga_mask;
1.42      mbalmer   848:                DPRINTF(("%s: attach %s with offset %d, mask "
                    849:                    "0x%02x, and flags 0x%02x\n", device_xname(sc->sc_dev),
                    850:                    ga.ga_dvname, ga.ga_offset, ga.ga_mask, ga.ga_flags));
1.19      mbalmer   851:
                    852:                locs[GPIOCF_OFFSET] = ga.ga_offset;
                    853:                locs[GPIOCF_MASK] = ga.ga_mask;
1.42      mbalmer   854:                locs[GPIOCF_FLAG] = ga.ga_flags;
1.19      mbalmer   855:
1.64.10.1  thorpej   856:                cf = config_search(sc->sc_dev, &ga,
                    857:                    CFARG_LOCATORS, locs,
                    858:                    CFARG_EOL);
1.24      mbalmer   859:                if (cf != NULL) {
1.64.10.7  thorpej   860:                        dv = config_attach(sc->sc_dev, cf, &ga,
                    861:                            gpiobus_print,
                    862:                            CFARG_LOCATORS, locs,
                    863:                            CFARG_EOL);
1.45      mbalmer   864: #ifdef COMPAT_50
1.24      mbalmer   865:                        if (dv != NULL) {
                    866:                                gdev = kmem_alloc(sizeof(struct gpio_dev),
                    867:                                    KM_SLEEP);
                    868:                                gdev->sc_dev = dv;
                    869:                                LIST_INSERT_HEAD(&sc->sc_devs, gdev, sc_next);
                    870:                        } else
1.39      mbalmer   871:                                error = EINVAL;
1.45      mbalmer   872: #else
                    873:                        if (dv == NULL)
                    874:                                error = EINVAL;
                    875: #endif
1.19      mbalmer   876:                } else
1.39      mbalmer   877:                        error = EINVAL;
                    878:                mutex_enter(&sc->sc_mtx);
                    879:                sc->sc_attach_busy = 0;
                    880:                cv_signal(&sc->sc_attach);
                    881:                mutex_exit(&sc->sc_mtx);
                    882:                return error;
1.19      mbalmer   883:        case GPIOSET:
                    884:                if (kauth_authorize_device(cred, KAUTH_DEVICE_GPIO_PINSET,
                    885:                    NULL, NULL, NULL, NULL))
                    886:                        return EPERM;
                    887:
1.43      mbalmer   888:                set = data;
1.19      mbalmer   889:
1.36      mbalmer   890:                if (set->gp_name[0] != '\0')
1.19      mbalmer   891:                        pin = gpio_pinbyname(sc, set->gp_name);
1.36      mbalmer   892:                else
1.19      mbalmer   893:                        pin = set->gp_pin;
1.36      mbalmer   894:
1.19      mbalmer   895:                if (pin < 0 || pin >= sc->sc_npins)
                    896:                        return EINVAL;
                    897:                flags = set->gp_flags;
                    898:
                    899:                /* check that the controller supports all requested flags */
                    900:                if ((flags & sc->sc_pins[pin].pin_caps) != flags)
                    901:                        return ENODEV;
1.56      kardel    902:                flags = set->gp_flags;
1.19      mbalmer   903:
                    904:                set->gp_caps = sc->sc_pins[pin].pin_caps;
                    905:                /* return old value */
                    906:                set->gp_flags = sc->sc_pins[pin].pin_flags;
1.56      kardel    907:
1.19      mbalmer   908:                if (flags > 0) {
1.56      kardel    909:                        flags |= GPIO_PIN_SET;
1.19      mbalmer   910:                        gpiobus_pin_ctl(gc, pin, flags);
                    911:                        /* update current value */
                    912:                        sc->sc_pins[pin].pin_flags = flags;
                    913:                }
                    914:
                    915:                /* rename pin or new pin? */
                    916:                if (set->gp_name2[0] != '\0') {
1.28      mbalmer   917:                        struct gpio_name *gnm;
                    918:
                    919:                        gnm = NULL;
                    920:                        LIST_FOREACH(nm, &sc->sc_names, gp_next) {
                    921:                                if (!strcmp(nm->gp_name, set->gp_name2) &&
                    922:                                    nm->gp_pin != pin)
                    923:                                        return EINVAL;  /* duplicate name */
                    924:                                if (nm->gp_pin == pin)
                    925:                                        gnm = nm;
                    926:                        }
                    927:                        if (gnm != NULL)
                    928:                                strlcpy(gnm->gp_name, set->gp_name2,
                    929:                                    sizeof(gnm->gp_name));
                    930:                        else  {
1.19      mbalmer   931:                                nm = kmem_alloc(sizeof(struct gpio_name),
                    932:                                    KM_SLEEP);
                    933:                                strlcpy(nm->gp_name, set->gp_name2,
                    934:                                    sizeof(nm->gp_name));
                    935:                                nm->gp_pin = set->gp_pin;
                    936:                                LIST_INSERT_HEAD(&sc->sc_names, nm, gp_next);
                    937:                        }
                    938:                }
                    939:                break;
                    940:        case GPIOUNSET:
                    941:                if (kauth_authorize_device(cred, KAUTH_DEVICE_GPIO_PINSET,
                    942:                    NULL, NULL, NULL, NULL))
                    943:                        return EPERM;
                    944:
1.43      mbalmer   945:                set = data;
1.36      mbalmer   946:                if (set->gp_name[0] != '\0')
1.19      mbalmer   947:                        pin = gpio_pinbyname(sc, set->gp_name);
1.36      mbalmer   948:                else
1.19      mbalmer   949:                        pin = set->gp_pin;
1.35      mbalmer   950:
1.19      mbalmer   951:                if (pin < 0 || pin >= sc->sc_npins)
                    952:                        return EINVAL;
                    953:                if (sc->sc_pins[pin].pin_mapped)
                    954:                        return EBUSY;
                    955:                if (!(sc->sc_pins[pin].pin_flags & GPIO_PIN_SET))
                    956:                        return EINVAL;
                    957:
                    958:                LIST_FOREACH(nm, &sc->sc_names, gp_next) {
                    959:                        if (nm->gp_pin == pin) {
                    960:                                LIST_REMOVE(nm, gp_next);
                    961:                                kmem_free(nm, sizeof(struct gpio_name));
                    962:                                break;
                    963:                        }
                    964:                }
                    965:                sc->sc_pins[pin].pin_flags &= ~GPIO_PIN_SET;
                    966:                break;
                    967:        default:
1.42      mbalmer   968: #ifdef COMPAT_50
1.19      mbalmer   969:                /* Try the old API */
1.22      cegger    970:                DPRINTF(("%s: trying the old API\n", device_xname(sc->sc_dev)));
1.19      mbalmer   971:                return gpio_ioctl_oapi(sc, cmd, data, flag, cred);
1.42      mbalmer   972: #else
                    973:                return ENOTTY;
                    974: #endif
1.19      mbalmer   975:        }
                    976:        return 0;
                    977: }
                    978:
1.42      mbalmer   979: #ifdef COMPAT_50
1.35      mbalmer   980: static int
1.19      mbalmer   981: gpio_ioctl_oapi(struct gpio_softc *sc, u_long cmd, void *data, int flag,
                    982:     kauth_cred_t cred)
                    983: {
                    984:        gpio_chipset_tag_t gc;
                    985:        struct gpio_pin_op *op;
                    986:        struct gpio_pin_ctl *ctl;
1.45      mbalmer   987:        struct gpio_attach *attach;
                    988:        struct gpio_dev *gdev;
                    989:
                    990:        int error, pin, value, flags;
1.19      mbalmer   991:
                    992:        gc = sc->sc_gc;
                    993:
                    994:        switch (cmd) {
1.1       jmcneill  995:        case GPIOPINREAD:
1.43      mbalmer   996:                op = data;
1.1       jmcneill  997:
                    998:                pin = op->gp_pin;
1.19      mbalmer   999:
1.1       jmcneill 1000:                if (pin < 0 || pin >= sc->sc_npins)
1.19      mbalmer  1001:                        return EINVAL;
                   1002:
                   1003:                if (!(sc->sc_pins[pin].pin_flags & GPIO_PIN_SET) &&
                   1004:                    kauth_authorize_device(cred, KAUTH_DEVICE_GPIO_PINSET,
                   1005:                    NULL, NULL, NULL, NULL))
                   1006:                        return EPERM;
1.1       jmcneill 1007:
                   1008:                /* return read value */
                   1009:                op->gp_value = gpiobus_pin_read(gc, pin);
                   1010:                break;
                   1011:        case GPIOPINWRITE:
1.19      mbalmer  1012:                if ((flag & FWRITE) == 0)
                   1013:                        return EBADF;
                   1014:
1.43      mbalmer  1015:                op = data;
1.1       jmcneill 1016:
                   1017:                pin = op->gp_pin;
1.19      mbalmer  1018:
1.1       jmcneill 1019:                if (pin < 0 || pin >= sc->sc_npins)
1.19      mbalmer  1020:                        return EINVAL;
                   1021:
1.5       riz      1022:                if (sc->sc_pins[pin].pin_mapped)
1.19      mbalmer  1023:                        return EBUSY;
                   1024:
                   1025:                if (!(sc->sc_pins[pin].pin_flags & GPIO_PIN_SET) &&
                   1026:                    kauth_authorize_device(cred, KAUTH_DEVICE_GPIO_PINSET,
                   1027:                    NULL, NULL, NULL, NULL))
                   1028:                        return EPERM;
1.1       jmcneill 1029:
                   1030:                value = op->gp_value;
                   1031:                if (value != GPIO_PIN_LOW && value != GPIO_PIN_HIGH)
1.19      mbalmer  1032:                        return EINVAL;
1.1       jmcneill 1033:
                   1034:                gpiobus_pin_write(gc, pin, value);
                   1035:                /* return old value */
                   1036:                op->gp_value = sc->sc_pins[pin].pin_state;
                   1037:                /* update current value */
                   1038:                sc->sc_pins[pin].pin_state = value;
                   1039:                break;
                   1040:        case GPIOPINTOGGLE:
1.19      mbalmer  1041:                if ((flag & FWRITE) == 0)
                   1042:                        return EBADF;
                   1043:
1.43      mbalmer  1044:                op = data;
1.1       jmcneill 1045:
                   1046:                pin = op->gp_pin;
1.19      mbalmer  1047:
1.1       jmcneill 1048:                if (pin < 0 || pin >= sc->sc_npins)
1.19      mbalmer  1049:                        return EINVAL;
                   1050:
1.5       riz      1051:                if (sc->sc_pins[pin].pin_mapped)
1.19      mbalmer  1052:                        return EBUSY;
                   1053:
                   1054:                if (!(sc->sc_pins[pin].pin_flags & GPIO_PIN_SET) &&
                   1055:                    kauth_authorize_device(cred, KAUTH_DEVICE_GPIO_PINSET,
                   1056:                    NULL, NULL, NULL, NULL))
                   1057:                        return EPERM;
1.1       jmcneill 1058:
                   1059:                value = (sc->sc_pins[pin].pin_state == GPIO_PIN_LOW ?
                   1060:                    GPIO_PIN_HIGH : GPIO_PIN_LOW);
                   1061:                gpiobus_pin_write(gc, pin, value);
                   1062:                /* return old value */
                   1063:                op->gp_value = sc->sc_pins[pin].pin_state;
                   1064:                /* update current value */
                   1065:                sc->sc_pins[pin].pin_state = value;
                   1066:                break;
                   1067:        case GPIOPINCTL:
1.43      mbalmer  1068:                ctl = data;
1.19      mbalmer  1069:
                   1070:                if (kauth_authorize_device(cred, KAUTH_DEVICE_GPIO_PINSET,
                   1071:                    NULL, NULL, NULL, NULL))
                   1072:                        return EPERM;
1.1       jmcneill 1073:
                   1074:                pin = ctl->gp_pin;
1.19      mbalmer  1075:
1.1       jmcneill 1076:                if (pin < 0 || pin >= sc->sc_npins)
1.19      mbalmer  1077:                        return EINVAL;
1.5       riz      1078:                if (sc->sc_pins[pin].pin_mapped)
1.19      mbalmer  1079:                        return EBUSY;
                   1080:                flags = ctl->gp_flags;
1.1       jmcneill 1081:
                   1082:                /* check that the controller supports all requested flags */
                   1083:                if ((flags & sc->sc_pins[pin].pin_caps) != flags)
1.19      mbalmer  1084:                        return ENODEV;
1.1       jmcneill 1085:
                   1086:                ctl->gp_caps = sc->sc_pins[pin].pin_caps;
                   1087:                /* return old value */
                   1088:                ctl->gp_flags = sc->sc_pins[pin].pin_flags;
                   1089:                if (flags > 0) {
                   1090:                        gpiobus_pin_ctl(gc, pin, flags);
                   1091:                        /* update current value */
                   1092:                        sc->sc_pins[pin].pin_flags = flags;
                   1093:                }
                   1094:                break;
1.44      mbalmer  1095:        case GPIODETACH50:
                   1096:                /* FALLTHOUGH */
                   1097:        case GPIODETACH:
                   1098:                if (kauth_authorize_device(cred, KAUTH_DEVICE_GPIO_PINSET,
                   1099:                    NULL, NULL, NULL, NULL))
                   1100:                        return EPERM;
                   1101:
                   1102:                error = 0;
                   1103:                mutex_enter(&sc->sc_mtx);
                   1104:                while (sc->sc_attach_busy) {
                   1105:                        error = cv_wait_sig(&sc->sc_attach, &sc->sc_mtx);
                   1106:                        if (error)
                   1107:                                break;
                   1108:                }
                   1109:                if (!error)
                   1110:                        sc->sc_attach_busy = 1;
                   1111:                mutex_exit(&sc->sc_mtx);
                   1112:                if (error)
                   1113:                        return EBUSY;
                   1114:
                   1115:                attach = data;
                   1116:                LIST_FOREACH(gdev, &sc->sc_devs, sc_next) {
                   1117:                        if (strcmp(device_xname(gdev->sc_dev),
                   1118:                            attach->ga_dvname) == 0) {
                   1119:                                mutex_enter(&sc->sc_mtx);
                   1120:                                sc->sc_attach_busy = 0;
                   1121:                                cv_signal(&sc->sc_attach);
                   1122:                                mutex_exit(&sc->sc_mtx);
                   1123:
                   1124:                                if (config_detach(gdev->sc_dev, 0) == 0)
                   1125:                                        return 0;
                   1126:                                break;
                   1127:                        }
                   1128:                }
                   1129:                if (gdev == NULL) {
                   1130:                        mutex_enter(&sc->sc_mtx);
                   1131:                        sc->sc_attach_busy = 0;
                   1132:                        cv_signal(&sc->sc_attach);
                   1133:                        mutex_exit(&sc->sc_mtx);
                   1134:                }
                   1135:                return EINVAL;
                   1136:
1.1       jmcneill 1137:        default:
1.19      mbalmer  1138:                return ENOTTY;
1.1       jmcneill 1139:        }
1.19      mbalmer  1140:        return 0;
1.1       jmcneill 1141: }
1.42      mbalmer  1142: #endif /* COMPAT_50 */
1.35      mbalmer  1143:
                   1144: MODULE(MODULE_CLASS_DRIVER, gpio, NULL);
                   1145:
1.37      mbalmer  1146: #ifdef _MODULE
1.35      mbalmer  1147: #include "ioconf.c"
1.37      mbalmer  1148: #endif
1.35      mbalmer  1149:
                   1150: static int
                   1151: gpio_modcmd(modcmd_t cmd, void *opaque)
                   1152: {
1.37      mbalmer  1153: #ifdef _MODULE
1.35      mbalmer  1154:        devmajor_t cmajor = NODEVMAJOR, bmajor = NODEVMAJOR;
                   1155:        int error;
1.37      mbalmer  1156: #endif
1.35      mbalmer  1157:        switch (cmd) {
                   1158:        case MODULE_CMD_INIT:
1.37      mbalmer  1159: #ifdef _MODULE
1.35      mbalmer  1160:                error = config_init_component(cfdriver_ioconf_gpio,
                   1161:                    cfattach_ioconf_gpio, cfdata_ioconf_gpio);
                   1162:                if (error) {
                   1163:                        aprint_error("%s: unable to init component\n",
                   1164:                            gpio_cd.cd_name);
                   1165:                        return error;
                   1166:                }
                   1167:                error = devsw_attach(gpio_cd.cd_name, NULL, &bmajor,
                   1168:                    &gpio_cdevsw, &cmajor);
                   1169:                if (error) {
                   1170:                        aprint_error("%s: unable to register devsw\n",
                   1171:                            gpio_cd.cd_name);
                   1172:                        return config_fini_component(cfdriver_ioconf_gpio,
                   1173:                            cfattach_ioconf_gpio, cfdata_ioconf_gpio);
                   1174:                }
1.37      mbalmer  1175: #endif
1.35      mbalmer  1176:                return 0;
                   1177:        case MODULE_CMD_FINI:
1.37      mbalmer  1178: #ifdef _MODULE
1.35      mbalmer  1179:                config_fini_component(cfdriver_ioconf_gpio,
                   1180:                    cfattach_ioconf_gpio, cfdata_ioconf_gpio);
                   1181:                devsw_detach(NULL, &gpio_cdevsw);
1.37      mbalmer  1182: #endif
1.35      mbalmer  1183:                return 0;
                   1184:        default:
                   1185:                return ENOTTY;
                   1186:        }
                   1187: }

CVSweb <webmaster@jp.NetBSD.org>