The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/arm/mv/gpio.c

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

    1 /*-
    2  * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
    3  *
    4  * Copyright (c) 2006 Benno Rice.
    5  * Copyright (C) 2008 MARVELL INTERNATIONAL LTD.
    6  * Copyright (c) 2017 Semihalf.
    7  * All rights reserved.
    8  *
    9  * Adapted and extended for Marvell SoCs by Semihalf.
   10  *
   11  * Redistribution and use in source and binary forms, with or without
   12  * modification, are permitted provided that the following conditions
   13  * are met:
   14  * 1. Redistributions of source code must retain the above copyright
   15  *    notice, this list of conditions and the following disclaimer.
   16  * 2. Redistributions in binary form must reproduce the above copyright
   17  *    notice, this list of conditions and the following disclaimer in the
   18  *    documentation and/or other materials provided with the distribution.
   19  *
   20  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
   21  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
   22  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
   23  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
   24  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
   25  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
   26  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
   27  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
   28  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
   29  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
   30  *
   31  * from: FreeBSD: //depot/projects/arm/src/sys/arm/xscale/pxa2x0/pxa2x0_gpio.c, rev 1
   32  */
   33 
   34 #include <sys/cdefs.h>
   35 __FBSDID("$FreeBSD$");
   36 
   37 #include <sys/param.h>
   38 #include <sys/systm.h>
   39 #include <sys/bus.h>
   40 #include <sys/kernel.h>
   41 #include <sys/lock.h>
   42 #include <sys/interrupt.h>
   43 #include <sys/module.h>
   44 #include <sys/malloc.h>
   45 #include <sys/mutex.h>
   46 #include <sys/rman.h>
   47 #include <sys/queue.h>
   48 #include <sys/timetc.h>
   49 #include <sys/callout.h>
   50 #include <sys/gpio.h>
   51 #include <machine/bus.h>
   52 #include <machine/intr.h>
   53 
   54 #include <dev/gpio/gpiobusvar.h>
   55 #include <dev/ofw/ofw_bus.h>
   56 #include <dev/ofw/ofw_bus_subr.h>
   57 
   58 #include <arm/mv/mvvar.h>
   59 #include <arm/mv/mvreg.h>
   60 
   61 #include "gpio_if.h"
   62 
   63 #define GPIO_MAX_INTR_COUNT     8
   64 #define GPIO_PINS_PER_REG       32
   65 #define GPIO_GENERIC_CAP        (GPIO_PIN_INPUT | GPIO_PIN_OUTPUT |             \
   66                                 GPIO_PIN_OPENDRAIN | GPIO_PIN_PUSHPULL |        \
   67                                 GPIO_PIN_TRISTATE | GPIO_PIN_PULLUP |           \
   68                                 GPIO_PIN_PULLDOWN | GPIO_PIN_INVIN |            \
   69                                 GPIO_PIN_INVOUT)
   70 
   71 #define DEBOUNCE_CHECK_MS       1
   72 #define DEBOUNCE_LO_HI_MS       2
   73 #define DEBOUNCE_HI_LO_MS       2
   74 #define DEBOUNCE_CHECK_TICKS    ((hz / 1000) * DEBOUNCE_CHECK_MS)
   75 
   76 struct mv_gpio_softc {
   77         device_t                dev;
   78         device_t                sc_busdev;
   79         struct resource *       mem_res;
   80         int                     mem_rid;
   81         struct resource *       irq_res[GPIO_MAX_INTR_COUNT];
   82         int                     irq_rid[GPIO_MAX_INTR_COUNT];
   83         struct intr_event *     gpio_events[MV_GPIO_MAX_NPINS];
   84         void                    *ih_cookie[GPIO_MAX_INTR_COUNT];
   85         bus_space_tag_t         bst;
   86         bus_space_handle_t      bsh;
   87         uint32_t                offset;
   88         struct mtx              mutex;
   89         uint8_t                 pin_num;        /* number of GPIO pins */
   90         uint8_t                 irq_num;        /* number of real IRQs occupied by GPIO controller */
   91         struct gpio_pin         gpio_setup[MV_GPIO_MAX_NPINS];
   92 
   93         /* Used for debouncing. */
   94         uint32_t                debounced_state_lo;
   95         uint32_t                debounced_state_hi;
   96         struct callout          **debounce_callouts;
   97         int                     *debounce_counters;
   98 };
   99 
  100 struct mv_gpio_pindev {
  101         device_t dev;
  102         int pin;
  103 };
  104 
  105 static int      mv_gpio_probe(device_t);
  106 static int      mv_gpio_attach(device_t);
  107 static int      mv_gpio_intr(device_t, void *);
  108 
  109 static void     mv_gpio_double_edge_init(device_t, int);
  110 
  111 static int      mv_gpio_debounce_setup(device_t, int);
  112 static int      mv_gpio_debounce_prepare(device_t, int);
  113 static int      mv_gpio_debounce_init(device_t, int);
  114 static void     mv_gpio_debounce_start(device_t, int);
  115 static void     mv_gpio_debounce(void *);
  116 static void     mv_gpio_debounced_state_set(device_t, int, uint8_t);
  117 static uint32_t mv_gpio_debounced_state_get(device_t, int);
  118 
  119 static void     mv_gpio_exec_intr_handlers(device_t, uint32_t, int);
  120 static void     mv_gpio_intr_handler(device_t, int);
  121 static uint32_t mv_gpio_reg_read(device_t, uint32_t);
  122 static void     mv_gpio_reg_write(device_t, uint32_t, uint32_t);
  123 static void     mv_gpio_reg_set(device_t, uint32_t, uint32_t);
  124 static void     mv_gpio_reg_clear(device_t, uint32_t, uint32_t);
  125 
  126 static void     mv_gpio_blink(device_t, uint32_t, uint8_t);
  127 static void     mv_gpio_polarity(device_t, uint32_t, uint8_t, uint8_t);
  128 static void     mv_gpio_level(device_t, uint32_t, uint8_t);
  129 static void     mv_gpio_edge(device_t, uint32_t, uint8_t);
  130 static void     mv_gpio_out_en(device_t, uint32_t, uint8_t);
  131 static void     mv_gpio_int_ack(struct mv_gpio_pindev *);
  132 static void     mv_gpio_value_set(device_t, uint32_t, uint8_t);
  133 static uint32_t mv_gpio_value_get(device_t, uint32_t, uint8_t);
  134 
  135 static void     mv_gpio_intr_mask(struct mv_gpio_pindev *);
  136 static void     mv_gpio_intr_unmask(struct mv_gpio_pindev *);
  137 
  138 void mv_gpio_finish_intrhandler(struct mv_gpio_pindev *);
  139 int mv_gpio_setup_intrhandler(device_t, const char *,
  140     driver_filter_t *, void (*)(void *), void *,
  141     int, int, void **);
  142 int mv_gpio_configure(device_t, uint32_t, uint32_t, uint32_t);
  143 void mv_gpio_out(device_t, uint32_t, uint8_t, uint8_t);
  144 uint8_t mv_gpio_in(device_t, uint32_t);
  145 
  146 /*
  147  * GPIO interface
  148  */
  149 static device_t mv_gpio_get_bus(device_t);
  150 static int mv_gpio_pin_max(device_t, int *);
  151 static int mv_gpio_pin_getcaps(device_t, uint32_t, uint32_t *);
  152 static int mv_gpio_pin_getflags(device_t, uint32_t, uint32_t *);
  153 static int mv_gpio_pin_getname(device_t, uint32_t, char *);
  154 static int mv_gpio_pin_setflags(device_t, uint32_t, uint32_t);
  155 static int mv_gpio_pin_set(device_t, uint32_t, unsigned int);
  156 static int mv_gpio_pin_get(device_t, uint32_t, unsigned int *);
  157 static int mv_gpio_pin_toggle(device_t, uint32_t);
  158 static int mv_gpio_map_gpios(device_t, phandle_t, phandle_t,
  159     int, pcell_t *, uint32_t *, uint32_t *);
  160 
  161 #define MV_GPIO_LOCK()          mtx_lock_spin(&sc->mutex)
  162 #define MV_GPIO_UNLOCK()        mtx_unlock_spin(&sc->mutex)
  163 #define MV_GPIO_ASSERT_LOCKED() mtx_assert(&sc->mutex, MA_OWNED)
  164 
  165 static device_method_t mv_gpio_methods[] = {
  166         DEVMETHOD(device_probe,         mv_gpio_probe),
  167         DEVMETHOD(device_attach,        mv_gpio_attach),
  168 
  169         /* GPIO protocol */
  170         DEVMETHOD(gpio_get_bus,         mv_gpio_get_bus),
  171         DEVMETHOD(gpio_pin_max,         mv_gpio_pin_max),
  172         DEVMETHOD(gpio_pin_getname,     mv_gpio_pin_getname),
  173         DEVMETHOD(gpio_pin_getflags,    mv_gpio_pin_getflags),
  174         DEVMETHOD(gpio_pin_getcaps,     mv_gpio_pin_getcaps),
  175         DEVMETHOD(gpio_pin_setflags,    mv_gpio_pin_setflags),
  176         DEVMETHOD(gpio_pin_get,         mv_gpio_pin_get),
  177         DEVMETHOD(gpio_pin_set,         mv_gpio_pin_set),
  178         DEVMETHOD(gpio_pin_toggle,      mv_gpio_pin_toggle),
  179         DEVMETHOD(gpio_map_gpios,       mv_gpio_map_gpios),
  180 
  181         DEVMETHOD_END
  182 };
  183 
  184 static driver_t mv_gpio_driver = {
  185         "gpio",
  186         mv_gpio_methods,
  187         sizeof(struct mv_gpio_softc),
  188 };
  189 
  190 static devclass_t mv_gpio_devclass;
  191 
  192 EARLY_DRIVER_MODULE(mv_gpio, simplebus, mv_gpio_driver, mv_gpio_devclass, 0, 0,
  193     BUS_PASS_INTERRUPT + BUS_PASS_ORDER_LAST);
  194 
  195 struct ofw_compat_data compat_data[] = {
  196         { "mrvl,gpio", 1 },
  197         { "marvell,orion-gpio", 1 },
  198         { NULL, 0 }
  199 };
  200 
  201 static int
  202 mv_gpio_probe(device_t dev)
  203 {
  204         if (!ofw_bus_status_okay(dev))
  205                 return (ENXIO);
  206 
  207         if (ofw_bus_search_compatible(dev, compat_data)->ocd_data == 0)
  208                 return (ENXIO);
  209 
  210         device_set_desc(dev, "Marvell Integrated GPIO Controller");
  211         return (0);
  212 }
  213 
  214 static int
  215 mv_gpio_setup_interrupts(struct mv_gpio_softc *sc, phandle_t node)
  216 {
  217         phandle_t iparent;
  218         pcell_t irq_cells;
  219         int i, size;
  220 
  221         /* Find root interrupt controller */
  222         iparent = ofw_bus_find_iparent(node);
  223         if (iparent == 0) {
  224                 device_printf(sc->dev, "No interrupt-parrent found. "
  225                                 "Error in DTB\n");
  226                 return (ENXIO);
  227         } else {
  228                 /* While at parent - store interrupt cells prop */
  229                 if (OF_searchencprop(OF_node_from_xref(iparent),
  230                     "#interrupt-cells", &irq_cells, sizeof(irq_cells)) == -1) {
  231                         device_printf(sc->dev, "DTB: Missing #interrupt-cells "
  232                             "property in interrupt parent node\n");
  233                         return (ENXIO);
  234                 }
  235         }
  236 
  237         size = OF_getproplen(node, "interrupts");
  238         if (size != -1) {
  239                 size = size / sizeof(pcell_t);
  240                 size = size / irq_cells;
  241                 sc->irq_num = size;
  242                 device_printf(sc->dev, "%d IRQs available\n", sc->irq_num);
  243         } else {
  244                 device_printf(sc->dev, "ERROR: no interrupts entry found!\n");
  245                 return (ENXIO);
  246         }
  247 
  248         for (i = 0; i < sc->irq_num; i++) {
  249                 sc->irq_rid[i] = i;
  250                 sc->irq_res[i] = bus_alloc_resource_any(sc->dev, SYS_RES_IRQ,
  251                         &sc->irq_rid[i], RF_ACTIVE);
  252                 if (!sc->irq_res[i]) {
  253                         mtx_destroy(&sc->mutex);
  254                         device_printf(sc->dev,
  255                             "could not allocate gpio%d interrupt\n", i+1);
  256                         return (ENXIO);
  257                 }
  258         }
  259 
  260         device_printf(sc->dev, "Disable interrupts (offset = %x + EDGE(0x18)\n", sc->offset);
  261         /* Disable all interrupts */
  262         bus_space_write_4(sc->bst, sc->bsh, sc->offset + GPIO_INT_EDGE_MASK, 0);
  263         device_printf(sc->dev, "Disable interrupts (offset = %x + LEV(0x1C))\n", sc->offset);
  264         bus_space_write_4(sc->bst, sc->bsh, sc->offset + GPIO_INT_LEV_MASK, 0);
  265 
  266         for (i = 0; i < sc->irq_num; i++) {
  267                 device_printf(sc->dev, "Setup intr %d\n", i);
  268                 if (bus_setup_intr(sc->dev, sc->irq_res[i],
  269                     INTR_TYPE_MISC,
  270                     (driver_filter_t *)mv_gpio_intr, NULL,
  271                     sc, &sc->ih_cookie[i]) != 0) {
  272                         mtx_destroy(&sc->mutex);
  273                         bus_release_resource(sc->dev, SYS_RES_IRQ,
  274                                 sc->irq_rid[i], sc->irq_res[i]);
  275                         device_printf(sc->dev, "could not set up intr %d\n", i);
  276                         return (ENXIO);
  277                 }
  278         }
  279 
  280         /* Clear interrupt status. */
  281         device_printf(sc->dev, "Clear int status (offset = %x)\n", sc->offset);
  282         bus_space_write_4(sc->bst, sc->bsh, sc->offset + GPIO_INT_CAUSE, 0);
  283 
  284         sc->debounce_callouts = (struct callout **)malloc(sc->pin_num *
  285             sizeof(struct callout *), M_DEVBUF, M_WAITOK | M_ZERO);
  286         if (sc->debounce_callouts == NULL)
  287                 return (ENOMEM);
  288 
  289         sc->debounce_counters = (int *)malloc(sc->pin_num * sizeof(int),
  290             M_DEVBUF, M_WAITOK);
  291         if (sc->debounce_counters == NULL)
  292                 return (ENOMEM);
  293 
  294         return (0);
  295 }
  296 
  297 static int
  298 mv_gpio_attach(device_t dev)
  299 {
  300         int i, rv;
  301         struct mv_gpio_softc *sc;
  302         phandle_t node;
  303         pcell_t pincnt = 0;
  304 
  305         sc = (struct mv_gpio_softc *)device_get_softc(dev);
  306         if (sc == NULL)
  307                 return (ENXIO);
  308 
  309         node = ofw_bus_get_node(dev);
  310         sc->dev = dev;
  311 
  312         if (OF_getencprop(node, "pin-count", &pincnt, sizeof(pcell_t)) >= 0 ||
  313             OF_getencprop(node, "ngpios", &pincnt, sizeof(pcell_t)) >= 0) {
  314                 sc->pin_num = MIN(pincnt, MV_GPIO_MAX_NPINS);
  315                 if (bootverbose)
  316                         device_printf(dev, "%d pins available\n", sc->pin_num);
  317         } else {
  318                 device_printf(dev, "ERROR: no pin-count or ngpios entry found!\n");
  319                 return (ENXIO);
  320         }
  321 
  322         if (OF_getencprop(node, "offset", &sc->offset, sizeof(sc->offset)) == -1)
  323                 sc->offset = 0;
  324 
  325         /* Assign generic capabilities to every gpio pin */
  326         for(i = 0; i < sc->pin_num; i++)
  327                 sc->gpio_setup[i].gp_caps = GPIO_GENERIC_CAP;
  328 
  329         mtx_init(&sc->mutex, device_get_nameunit(dev), NULL, MTX_SPIN);
  330 
  331         sc->mem_rid = 0;
  332         sc->mem_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &sc->mem_rid,
  333                  RF_ACTIVE | RF_SHAREABLE );
  334 
  335         if (!sc->mem_res) {
  336                 mtx_destroy(&sc->mutex);
  337                 device_printf(dev, "could not allocate memory window\n");
  338                 return (ENXIO);
  339         }
  340 
  341         sc->bst = rman_get_bustag(sc->mem_res);
  342         sc->bsh = rman_get_bushandle(sc->mem_res);
  343 
  344         rv = mv_gpio_setup_interrupts(sc, node);
  345         if (rv != 0)
  346                 return (rv);
  347 
  348         sc->sc_busdev = gpiobus_attach_bus(dev);
  349         if (sc->sc_busdev == NULL) {
  350                 mtx_destroy(&sc->mutex);
  351                 bus_release_resource(dev, SYS_RES_IRQ,
  352                         sc->irq_rid[i], sc->irq_res[i]);
  353                 return (ENXIO);
  354         }
  355 
  356         return (0);
  357 }
  358 
  359 static int
  360 mv_gpio_intr(device_t dev, void *arg)
  361 {
  362         uint32_t int_cause, gpio_val;
  363         struct mv_gpio_softc *sc;
  364         sc = (struct mv_gpio_softc *)device_get_softc(dev);
  365 
  366         MV_GPIO_LOCK();
  367 
  368         /*
  369          * According to documentation, edge sensitive interrupts are asserted
  370          * when unmasked GPIO_INT_CAUSE register bits are set.
  371          */
  372         int_cause = mv_gpio_reg_read(dev, GPIO_INT_CAUSE);
  373         int_cause &= mv_gpio_reg_read(dev, GPIO_INT_EDGE_MASK);
  374 
  375         /*
  376          * Level sensitive interrupts are asserted when unmasked GPIO_DATA_IN
  377          * register bits are set.
  378          */
  379         gpio_val = mv_gpio_reg_read(dev, GPIO_DATA_IN);
  380         gpio_val &= mv_gpio_reg_read(dev, GPIO_INT_LEV_MASK);
  381 
  382         mv_gpio_exec_intr_handlers(dev, int_cause | gpio_val, 0);
  383 
  384         MV_GPIO_UNLOCK();
  385 
  386         return (FILTER_HANDLED);
  387 }
  388 
  389 /*
  390  * GPIO interrupt handling
  391  */
  392 
  393 void
  394 mv_gpio_finish_intrhandler(struct mv_gpio_pindev *s)
  395 {
  396         /* When we acheive full interrupt support
  397          * This function will be opposite to
  398          * mv_gpio_setup_intrhandler
  399          */
  400 
  401         /* Now it exists only to remind that
  402          * there should be place to free mv_gpio_pindev
  403          * allocated by mv_gpio_setup_intrhandler
  404          */
  405         free(s, M_DEVBUF);
  406 }
  407 
  408 int
  409 mv_gpio_setup_intrhandler(device_t dev, const char *name, driver_filter_t *filt,
  410     void (*hand)(void *), void *arg, int pin, int flags, void **cookiep)
  411 {
  412         struct  intr_event *event;
  413         int     error;
  414         struct mv_gpio_pindev *s;
  415         struct mv_gpio_softc *sc;
  416         sc = (struct mv_gpio_softc *)device_get_softc(dev);
  417         s = malloc(sizeof(struct mv_gpio_pindev), M_DEVBUF, M_NOWAIT | M_ZERO);
  418 
  419         if (pin < 0 || pin >= sc->pin_num)
  420                 return (ENXIO);
  421         event = sc->gpio_events[pin];
  422         if (event == NULL) {
  423                 MV_GPIO_LOCK();
  424                 if (sc->gpio_setup[pin].gp_flags & MV_GPIO_IN_DEBOUNCE) {
  425                         error = mv_gpio_debounce_init(dev, pin);
  426                         if (error != 0) {
  427                                 MV_GPIO_UNLOCK();
  428                                 return (error);
  429                         }
  430                 } else if (sc->gpio_setup[pin].gp_flags & MV_GPIO_IN_IRQ_DOUBLE_EDGE)
  431                         mv_gpio_double_edge_init(dev, pin);
  432                 MV_GPIO_UNLOCK();
  433                 error = intr_event_create(&event, (void *)s, 0, pin,
  434                     (void (*)(void *))mv_gpio_intr_mask,
  435                     (void (*)(void *))mv_gpio_intr_unmask,
  436                     (void (*)(void *))mv_gpio_int_ack,
  437                     NULL,
  438                     "gpio%d:", pin);
  439                 if (error != 0)
  440                         return (error);
  441                 sc->gpio_events[pin] = event;
  442         }
  443 
  444         intr_event_add_handler(event, name, filt, hand, arg,
  445             intr_priority(flags), flags, cookiep);
  446         return (0);
  447 }
  448 
  449 static void
  450 mv_gpio_intr_mask(struct mv_gpio_pindev *s)
  451 {
  452         struct mv_gpio_softc *sc;
  453         sc = (struct mv_gpio_softc *)device_get_softc(s->dev);
  454 
  455         if (s->pin >= sc->pin_num)
  456                 return;
  457 
  458         MV_GPIO_LOCK();
  459 
  460         if (sc->gpio_setup[s->pin].gp_flags & (MV_GPIO_IN_IRQ_EDGE |
  461             MV_GPIO_IN_IRQ_DOUBLE_EDGE))
  462                 mv_gpio_edge(s->dev, s->pin, 0);
  463         else
  464                 mv_gpio_level(s->dev, s->pin, 0);
  465 
  466         /*
  467          * The interrupt has to be acknowledged before scheduling an interrupt
  468          * thread. This way we allow for interrupt source to trigger again
  469          * (which can happen with shared IRQs e.g. PCI) while processing the
  470          * current event.
  471          */
  472         mv_gpio_int_ack(s);
  473 
  474         MV_GPIO_UNLOCK();
  475 
  476         return;
  477 }
  478 
  479 static void
  480 mv_gpio_intr_unmask(struct mv_gpio_pindev *s)
  481 {
  482         struct mv_gpio_softc *sc;
  483         sc = (struct mv_gpio_softc *)device_get_softc(s->dev);
  484 
  485         if (s->pin >= sc->pin_num)
  486                 return;
  487 
  488         MV_GPIO_LOCK();
  489 
  490         if (sc->gpio_setup[s->pin].gp_flags & (MV_GPIO_IN_IRQ_EDGE |
  491             MV_GPIO_IN_IRQ_DOUBLE_EDGE))
  492                 mv_gpio_edge(s->dev, s->pin, 1);
  493         else
  494                 mv_gpio_level(s->dev, s->pin, 1);
  495 
  496         MV_GPIO_UNLOCK();
  497 
  498         return;
  499 }
  500 
  501 static void
  502 mv_gpio_exec_intr_handlers(device_t dev, uint32_t status, int high)
  503 {
  504         int i, pin;
  505         struct mv_gpio_softc *sc;
  506         sc = (struct mv_gpio_softc *)device_get_softc(dev);
  507 
  508         MV_GPIO_ASSERT_LOCKED();
  509 
  510         i = 0;
  511         while (status != 0) {
  512                 if (status & 1) {
  513                         pin = (high ? (i + GPIO_PINS_PER_REG) : i);
  514                         if (sc->gpio_setup[pin].gp_flags & MV_GPIO_IN_DEBOUNCE)
  515                                 mv_gpio_debounce_start(dev, pin);
  516                         else if (sc->gpio_setup[pin].gp_flags & MV_GPIO_IN_IRQ_DOUBLE_EDGE) {
  517                                 mv_gpio_polarity(dev, pin, 0, 1);
  518                                 mv_gpio_intr_handler(dev, pin);
  519                         } else
  520                                 mv_gpio_intr_handler(dev, pin);
  521                 }
  522                 status >>= 1;
  523                 i++;
  524         }
  525 }
  526 
  527 static void
  528 mv_gpio_intr_handler(device_t dev, int pin)
  529 {
  530         struct intr_irqsrc isrc;
  531         struct mv_gpio_softc *sc;
  532         sc = (struct mv_gpio_softc *)device_get_softc(dev);
  533 
  534         MV_GPIO_ASSERT_LOCKED();
  535 
  536 #ifdef INTR_SOLO
  537         isrc.isrc_filter = NULL;
  538 #endif
  539         isrc.isrc_event = sc->gpio_events[pin];
  540 
  541         if (isrc.isrc_event == NULL ||
  542             CK_SLIST_EMPTY(&isrc.isrc_event->ie_handlers))
  543                 return;
  544 
  545         intr_isrc_dispatch(&isrc, NULL);
  546 }
  547 
  548 int
  549 mv_gpio_configure(device_t dev, uint32_t pin, uint32_t flags, uint32_t mask)
  550 {
  551         int error;
  552         struct mv_gpio_softc *sc;
  553         sc = (struct mv_gpio_softc *)device_get_softc(dev);
  554         error = 0;
  555 
  556         if (pin >= sc->pin_num)
  557                 return (EINVAL);
  558 
  559         /* check flags consistency */
  560         if (((flags & mask) & (GPIO_PIN_INPUT | GPIO_PIN_OUTPUT)) ==
  561             (GPIO_PIN_INPUT | GPIO_PIN_OUTPUT))
  562                 return (EINVAL);
  563 
  564         if (mask & MV_GPIO_IN_DEBOUNCE) {
  565                 if (sc->irq_num == 0)
  566                         return (EINVAL);
  567                 error = mv_gpio_debounce_prepare(dev, pin);
  568                 if (error != 0)
  569                         return (error);
  570         }
  571 
  572         MV_GPIO_LOCK();
  573 
  574         if ((mask & flags) & GPIO_PIN_INPUT)
  575                 mv_gpio_out_en(dev, pin, 0);
  576         if ((mask & flags) & GPIO_PIN_OUTPUT) {
  577                 if ((flags & mask) & GPIO_PIN_OPENDRAIN)
  578                         mv_gpio_value_set(dev, pin, 0);
  579                 else
  580                         mv_gpio_value_set(dev, pin, 1);
  581                 mv_gpio_out_en(dev, pin, 1);
  582         }
  583 
  584         if (mask & MV_GPIO_OUT_BLINK)
  585                 mv_gpio_blink(dev, pin, flags & MV_GPIO_OUT_BLINK);
  586         if (mask & MV_GPIO_IN_POL_LOW)
  587                 mv_gpio_polarity(dev, pin, flags & MV_GPIO_IN_POL_LOW, 0);
  588         if (mask & MV_GPIO_IN_DEBOUNCE) {
  589                 error = mv_gpio_debounce_setup(dev, pin);
  590                 if (error) {
  591                         MV_GPIO_UNLOCK();
  592                         return (error);
  593                 }
  594         }
  595 
  596         sc->gpio_setup[pin].gp_flags &= ~(mask);
  597         sc->gpio_setup[pin].gp_flags |= (flags & mask);
  598 
  599         MV_GPIO_UNLOCK();
  600 
  601         return (0);
  602 }
  603 
  604 static void
  605 mv_gpio_double_edge_init(device_t dev, int pin)
  606 {
  607         uint8_t raw_read;
  608         struct mv_gpio_softc *sc;
  609         sc = (struct mv_gpio_softc *)device_get_softc(dev);
  610 
  611         MV_GPIO_ASSERT_LOCKED();
  612 
  613         raw_read = (mv_gpio_value_get(dev, pin, 1) ? 1 : 0);
  614 
  615         if (raw_read)
  616                 mv_gpio_polarity(dev, pin, 1, 0);
  617         else
  618                 mv_gpio_polarity(dev, pin, 0, 0);
  619 }
  620 
  621 static int
  622 mv_gpio_debounce_setup(device_t dev, int pin)
  623 {
  624         struct callout *c;
  625         struct mv_gpio_softc *sc;
  626 
  627         sc = (struct mv_gpio_softc *)device_get_softc(dev);
  628 
  629         MV_GPIO_ASSERT_LOCKED();
  630 
  631         c = sc->debounce_callouts[pin];
  632         if (c == NULL)
  633                 return (ENXIO);
  634 
  635         if (callout_active(c))
  636                 callout_deactivate(c);
  637 
  638         callout_stop(c);
  639 
  640         return (0);
  641 }
  642 
  643 static int
  644 mv_gpio_debounce_prepare(device_t dev, int pin)
  645 {
  646         struct callout *c;
  647         struct mv_gpio_softc *sc;
  648 
  649         sc = (struct mv_gpio_softc *)device_get_softc(dev);
  650 
  651         c = sc->debounce_callouts[pin];
  652         if (c == NULL) {
  653                 c = (struct callout *)malloc(sizeof(struct callout),
  654                     M_DEVBUF, M_WAITOK);
  655                 sc->debounce_callouts[pin] = c;
  656                 if (c == NULL)
  657                         return (ENOMEM);
  658                 callout_init(c, 1);
  659         }
  660 
  661         return (0);
  662 }
  663 
  664 static int
  665 mv_gpio_debounce_init(device_t dev, int pin)
  666 {
  667         uint8_t raw_read;
  668         int *cnt;
  669         struct mv_gpio_softc *sc;
  670 
  671         sc = (struct mv_gpio_softc *)device_get_softc(dev);
  672 
  673         MV_GPIO_ASSERT_LOCKED();
  674 
  675         cnt = &sc->debounce_counters[pin];
  676         raw_read = (mv_gpio_value_get(dev, pin, 1) ? 1 : 0);
  677         if (raw_read) {
  678                 mv_gpio_polarity(dev, pin, 1, 0);
  679                 *cnt = DEBOUNCE_HI_LO_MS / DEBOUNCE_CHECK_MS;
  680         } else {
  681                 mv_gpio_polarity(dev, pin, 0, 0);
  682                 *cnt = DEBOUNCE_LO_HI_MS / DEBOUNCE_CHECK_MS;
  683         }
  684 
  685         mv_gpio_debounced_state_set(dev, pin, raw_read);
  686 
  687         return (0);
  688 }
  689 
  690 static void
  691 mv_gpio_debounce_start(device_t dev, int pin)
  692 {
  693         struct callout *c;
  694         struct mv_gpio_pindev s = {dev, pin};
  695         struct mv_gpio_pindev *sd;
  696         struct mv_gpio_softc *sc;
  697         sc = (struct mv_gpio_softc *)device_get_softc(dev);
  698 
  699         MV_GPIO_ASSERT_LOCKED();
  700 
  701         c = sc->debounce_callouts[pin];
  702         if (c == NULL) {
  703                 mv_gpio_int_ack(&s);
  704                 return;
  705         }
  706 
  707         if (callout_pending(c) || callout_active(c)) {
  708                 mv_gpio_int_ack(&s);
  709                 return;
  710         }
  711 
  712         sd = (struct mv_gpio_pindev *)malloc(sizeof(struct mv_gpio_pindev),
  713             M_DEVBUF, M_WAITOK);
  714         if (sd == NULL) {
  715                 mv_gpio_int_ack(&s);
  716                 return;
  717         }
  718         sd->pin = pin;
  719         sd->dev = dev;
  720 
  721         callout_reset(c, DEBOUNCE_CHECK_TICKS, mv_gpio_debounce, sd);
  722 }
  723 
  724 static void
  725 mv_gpio_debounce(void *arg)
  726 {
  727         uint8_t raw_read, last_state;
  728         int pin;
  729         device_t dev;
  730         int *debounce_counter;
  731         struct mv_gpio_softc *sc;
  732         struct mv_gpio_pindev *s;
  733 
  734         s = (struct mv_gpio_pindev *)arg;
  735         dev = s->dev;
  736         pin = s->pin;
  737         sc = (struct mv_gpio_softc *)device_get_softc(dev);
  738 
  739         MV_GPIO_LOCK();
  740 
  741         raw_read = (mv_gpio_value_get(dev, pin, 1) ? 1 : 0);
  742         last_state = (mv_gpio_debounced_state_get(dev, pin) ? 1 : 0);
  743         debounce_counter = &sc->debounce_counters[pin];
  744 
  745         if (raw_read == last_state) {
  746                 if (last_state)
  747                         *debounce_counter = DEBOUNCE_HI_LO_MS /
  748                             DEBOUNCE_CHECK_MS;
  749                 else
  750                         *debounce_counter = DEBOUNCE_LO_HI_MS /
  751                             DEBOUNCE_CHECK_MS;
  752 
  753                 callout_reset(sc->debounce_callouts[pin],
  754                     DEBOUNCE_CHECK_TICKS, mv_gpio_debounce, arg);
  755         } else {
  756                 *debounce_counter = *debounce_counter - 1;
  757                 if (*debounce_counter != 0)
  758                         callout_reset(sc->debounce_callouts[pin],
  759                             DEBOUNCE_CHECK_TICKS, mv_gpio_debounce, arg);
  760                 else {
  761                         mv_gpio_debounced_state_set(dev, pin, raw_read);
  762 
  763                         if (last_state)
  764                                 *debounce_counter = DEBOUNCE_HI_LO_MS /
  765                                     DEBOUNCE_CHECK_MS;
  766                         else
  767                                 *debounce_counter = DEBOUNCE_LO_HI_MS /
  768                                     DEBOUNCE_CHECK_MS;
  769 
  770                         if (((sc->gpio_setup[pin].gp_flags & MV_GPIO_IN_POL_LOW) &&
  771                             (raw_read == 0)) ||
  772                             (((sc->gpio_setup[pin].gp_flags & MV_GPIO_IN_POL_LOW) == 0) &&
  773                             raw_read) ||
  774                             (sc->gpio_setup[pin].gp_flags & MV_GPIO_IN_IRQ_DOUBLE_EDGE))
  775                                 mv_gpio_intr_handler(dev, pin);
  776 
  777                         /* Toggle polarity for next edge. */
  778                         mv_gpio_polarity(dev, pin, 0, 1);
  779 
  780                         free(arg, M_DEVBUF);
  781                         callout_deactivate(sc->debounce_callouts[pin]);
  782                 }
  783         }
  784 
  785         MV_GPIO_UNLOCK();
  786 }
  787 
  788 static void
  789 mv_gpio_debounced_state_set(device_t dev, int pin, uint8_t new_state)
  790 {
  791         uint32_t *old_state;
  792         struct mv_gpio_softc *sc;
  793         sc = (struct mv_gpio_softc *)device_get_softc(dev);
  794 
  795         MV_GPIO_ASSERT_LOCKED();
  796 
  797         if (pin >= GPIO_PINS_PER_REG) {
  798                 old_state = &sc->debounced_state_hi;
  799                 pin -= GPIO_PINS_PER_REG;
  800         } else
  801                 old_state = &sc->debounced_state_lo;
  802 
  803         if (new_state)
  804                 *old_state |= (1 << pin);
  805         else
  806                 *old_state &= ~(1 << pin);
  807 }
  808 
  809 static uint32_t
  810 mv_gpio_debounced_state_get(device_t dev, int pin)
  811 {
  812         uint32_t *state;
  813         struct mv_gpio_softc *sc;
  814         sc = (struct mv_gpio_softc *)device_get_softc(dev);
  815 
  816         MV_GPIO_ASSERT_LOCKED();
  817 
  818         if (pin >= GPIO_PINS_PER_REG) {
  819                 state = &sc->debounced_state_hi;
  820                 pin -= GPIO_PINS_PER_REG;
  821         } else
  822                 state = &sc->debounced_state_lo;
  823 
  824         return (*state & (1 << pin));
  825 }
  826 
  827 void
  828 mv_gpio_out(device_t dev, uint32_t pin, uint8_t val, uint8_t enable)
  829 {
  830         struct mv_gpio_softc *sc;
  831         sc = (struct mv_gpio_softc *)device_get_softc(dev);
  832 
  833         MV_GPIO_LOCK();
  834 
  835         mv_gpio_value_set(dev, pin, val);
  836         mv_gpio_out_en(dev, pin, enable);
  837 
  838         MV_GPIO_UNLOCK();
  839 }
  840 
  841 uint8_t
  842 mv_gpio_in(device_t dev, uint32_t pin)
  843 {
  844         uint8_t state;
  845         struct mv_gpio_softc *sc;
  846         sc = (struct mv_gpio_softc *)device_get_softc(dev);
  847 
  848         MV_GPIO_ASSERT_LOCKED();
  849 
  850         if (sc->gpio_setup[pin].gp_flags & MV_GPIO_IN_DEBOUNCE) {
  851                 if (sc->gpio_setup[pin].gp_flags & MV_GPIO_IN_POL_LOW)
  852                         state = (mv_gpio_debounced_state_get(dev, pin) ? 0 : 1);
  853                 else
  854                         state = (mv_gpio_debounced_state_get(dev, pin) ? 1 : 0);
  855         } else if (sc->gpio_setup[pin].gp_flags & MV_GPIO_IN_IRQ_DOUBLE_EDGE) {
  856                 if (sc->gpio_setup[pin].gp_flags & MV_GPIO_IN_POL_LOW)
  857                         state = (mv_gpio_value_get(dev, pin, 1) ? 0 : 1);
  858                 else
  859                         state = (mv_gpio_value_get(dev, pin, 1) ? 1 : 0);
  860         } else
  861                 state = (mv_gpio_value_get(dev, pin, 0) ? 1 : 0);
  862 
  863         return (state);
  864 }
  865 
  866 static uint32_t
  867 mv_gpio_reg_read(device_t dev, uint32_t reg)
  868 {
  869         struct mv_gpio_softc *sc;
  870         sc = (struct mv_gpio_softc *)device_get_softc(dev);
  871 
  872         return (bus_space_read_4(sc->bst, sc->bsh, sc->offset + reg));
  873 }
  874 
  875 static void
  876 mv_gpio_reg_write(device_t dev, uint32_t reg, uint32_t val)
  877 {
  878         struct mv_gpio_softc *sc;
  879         sc = (struct mv_gpio_softc *)device_get_softc(dev);
  880 
  881         bus_space_write_4(sc->bst, sc->bsh, sc->offset + reg, val);
  882 }
  883 
  884 static void
  885 mv_gpio_reg_set(device_t dev, uint32_t reg, uint32_t pin)
  886 {
  887         uint32_t reg_val;
  888 
  889         reg_val = mv_gpio_reg_read(dev, reg);
  890         reg_val |= GPIO(pin);
  891         mv_gpio_reg_write(dev, reg, reg_val);
  892 }
  893 
  894 static void
  895 mv_gpio_reg_clear(device_t dev, uint32_t reg, uint32_t pin)
  896 {
  897         uint32_t reg_val;
  898 
  899         reg_val = mv_gpio_reg_read(dev, reg);
  900         reg_val &= ~(GPIO(pin));
  901         mv_gpio_reg_write(dev, reg, reg_val);
  902 }
  903 
  904 static void
  905 mv_gpio_out_en(device_t dev, uint32_t pin, uint8_t enable)
  906 {
  907         uint32_t reg;
  908         struct mv_gpio_softc *sc;
  909         sc = (struct mv_gpio_softc *)device_get_softc(dev);
  910 
  911         if (pin >= sc->pin_num)
  912                 return;
  913 
  914         reg = GPIO_DATA_OUT_EN_CTRL;
  915 
  916         if (enable)
  917                 mv_gpio_reg_clear(dev, reg, pin);
  918         else
  919                 mv_gpio_reg_set(dev, reg, pin);
  920 }
  921 
  922 static void
  923 mv_gpio_blink(device_t dev, uint32_t pin, uint8_t enable)
  924 {
  925         uint32_t reg;
  926         struct mv_gpio_softc *sc;
  927         sc = (struct mv_gpio_softc *)device_get_softc(dev);
  928 
  929         if (pin >= sc->pin_num)
  930                 return;
  931 
  932         reg = GPIO_BLINK_EN;
  933 
  934         if (enable)
  935                 mv_gpio_reg_set(dev, reg, pin);
  936         else
  937                 mv_gpio_reg_clear(dev, reg, pin);
  938 }
  939 
  940 static void
  941 mv_gpio_polarity(device_t dev, uint32_t pin, uint8_t enable, uint8_t toggle)
  942 {
  943         uint32_t reg, reg_val;
  944         struct mv_gpio_softc *sc;
  945         sc = (struct mv_gpio_softc *)device_get_softc(dev);
  946 
  947         if (pin >= sc->pin_num)
  948                 return;
  949 
  950         reg = GPIO_DATA_IN_POLAR;
  951 
  952         if (toggle) {
  953                 reg_val = mv_gpio_reg_read(dev, reg) & GPIO(pin);
  954                 if (reg_val)
  955                         mv_gpio_reg_clear(dev, reg, pin);
  956                 else
  957                         mv_gpio_reg_set(dev, reg, pin);
  958         } else if (enable)
  959                 mv_gpio_reg_set(dev, reg, pin);
  960         else
  961                 mv_gpio_reg_clear(dev, reg, pin);
  962 }
  963 
  964 static void
  965 mv_gpio_level(device_t dev, uint32_t pin, uint8_t enable)
  966 {
  967         uint32_t reg;
  968         struct mv_gpio_softc *sc;
  969         sc = (struct mv_gpio_softc *)device_get_softc(dev);
  970 
  971         if (pin >= sc->pin_num)
  972                 return;
  973 
  974         reg = GPIO_INT_LEV_MASK;
  975 
  976         if (enable)
  977                 mv_gpio_reg_set(dev, reg, pin);
  978         else
  979                 mv_gpio_reg_clear(dev, reg, pin);
  980 }
  981 
  982 static void
  983 mv_gpio_edge(device_t dev, uint32_t pin, uint8_t enable)
  984 {
  985         uint32_t reg;
  986         struct mv_gpio_softc *sc;
  987         sc = (struct mv_gpio_softc *)device_get_softc(dev);
  988 
  989         if (pin >= sc->pin_num)
  990                 return;
  991 
  992         reg = GPIO_INT_EDGE_MASK;
  993 
  994         if (enable)
  995                 mv_gpio_reg_set(dev, reg, pin);
  996         else
  997                 mv_gpio_reg_clear(dev, reg, pin);
  998 }
  999 
 1000 static void
 1001 mv_gpio_int_ack(struct mv_gpio_pindev *s)
 1002 {
 1003         uint32_t reg, pin;
 1004         struct mv_gpio_softc *sc;
 1005         sc = (struct mv_gpio_softc *)device_get_softc(s->dev);
 1006         pin = s->pin;
 1007 
 1008         if (pin >= sc->pin_num)
 1009                 return;
 1010 
 1011         reg = GPIO_INT_CAUSE;
 1012 
 1013         mv_gpio_reg_clear(s->dev, reg, pin);
 1014 }
 1015 
 1016 static uint32_t
 1017 mv_gpio_value_get(device_t dev, uint32_t pin, uint8_t exclude_polar)
 1018 {
 1019         uint32_t reg, polar_reg, reg_val, polar_reg_val;
 1020         struct mv_gpio_softc *sc;
 1021         sc = (struct mv_gpio_softc *)device_get_softc(dev);
 1022 
 1023         if (pin >= sc->pin_num)
 1024                 return (0);
 1025 
 1026         reg = GPIO_DATA_IN;
 1027         polar_reg = GPIO_DATA_IN_POLAR;
 1028 
 1029         reg_val = mv_gpio_reg_read(dev, reg);
 1030 
 1031         if (exclude_polar) {
 1032                 polar_reg_val = mv_gpio_reg_read(dev, polar_reg);
 1033                 return ((reg_val & GPIO(pin)) ^ (polar_reg_val & GPIO(pin)));
 1034         } else
 1035                 return (reg_val & GPIO(pin));
 1036 }
 1037 
 1038 static void
 1039 mv_gpio_value_set(device_t dev, uint32_t pin, uint8_t val)
 1040 {
 1041         uint32_t reg;
 1042         struct mv_gpio_softc *sc;
 1043         sc = (struct mv_gpio_softc *)device_get_softc(dev);
 1044 
 1045         MV_GPIO_ASSERT_LOCKED();
 1046 
 1047         if (pin >= sc->pin_num)
 1048                 return;
 1049 
 1050         reg = GPIO_DATA_OUT;
 1051 
 1052         if (val)
 1053                 mv_gpio_reg_set(dev, reg, pin);
 1054         else
 1055                 mv_gpio_reg_clear(dev, reg, pin);
 1056 }
 1057 
 1058 /*
 1059  * GPIO interface methods
 1060  */
 1061 
 1062 static int
 1063 mv_gpio_pin_max(device_t dev, int *maxpin)
 1064 {
 1065         struct mv_gpio_softc *sc;
 1066         if (maxpin == NULL)
 1067                 return (EINVAL);
 1068 
 1069         sc = device_get_softc(dev);
 1070         *maxpin = sc->pin_num;
 1071 
 1072         return (0);
 1073 }
 1074 
 1075 static int
 1076 mv_gpio_pin_getcaps(device_t dev, uint32_t pin, uint32_t *caps)
 1077 {
 1078         struct mv_gpio_softc *sc = device_get_softc(dev);
 1079         if (caps == NULL)
 1080                 return (EINVAL);
 1081 
 1082         if (pin >= sc->pin_num)
 1083                 return (EINVAL);
 1084 
 1085         MV_GPIO_LOCK();
 1086         *caps = sc->gpio_setup[pin].gp_caps;
 1087         MV_GPIO_UNLOCK();
 1088 
 1089         return (0);
 1090 }
 1091 
 1092 static int
 1093 mv_gpio_pin_getflags(device_t dev, uint32_t pin, uint32_t *flags)
 1094 {
 1095         struct mv_gpio_softc *sc = device_get_softc(dev);
 1096         if (flags == NULL)
 1097                 return (EINVAL);
 1098 
 1099         if (pin >= sc->pin_num)
 1100                 return (EINVAL);
 1101 
 1102         MV_GPIO_LOCK();
 1103         *flags = sc->gpio_setup[pin].gp_flags;
 1104         MV_GPIO_UNLOCK();
 1105 
 1106         return (0);
 1107 }
 1108 
 1109 static int
 1110 mv_gpio_pin_getname(device_t dev, uint32_t pin, char *name)
 1111 {
 1112         struct mv_gpio_softc *sc = device_get_softc(dev);
 1113         if (name == NULL)
 1114                 return (EINVAL);
 1115 
 1116         if (pin >= sc->pin_num)
 1117                 return (EINVAL);
 1118 
 1119         MV_GPIO_LOCK();
 1120         memcpy(name, sc->gpio_setup[pin].gp_name, GPIOMAXNAME);
 1121         MV_GPIO_UNLOCK();
 1122 
 1123         return (0);
 1124 }
 1125 
 1126 static int
 1127 mv_gpio_pin_setflags(device_t dev, uint32_t pin, uint32_t flags)
 1128 {
 1129         int ret;
 1130         struct mv_gpio_softc *sc = device_get_softc(dev);
 1131         if (pin >= sc->pin_num)
 1132                 return (EINVAL);
 1133 
 1134         /* Check for unwanted flags. */
 1135         if ((flags & sc->gpio_setup[pin].gp_caps) != flags)
 1136                 return (EINVAL);
 1137 
 1138         ret = mv_gpio_configure(dev, pin, flags, ~0);
 1139 
 1140         return (ret);
 1141 }
 1142 
 1143 static int
 1144 mv_gpio_pin_set(device_t dev, uint32_t pin, unsigned int value)
 1145 {
 1146         struct mv_gpio_softc *sc = device_get_softc(dev);
 1147         if (pin >= sc->pin_num)
 1148                 return (EINVAL);
 1149 
 1150         MV_GPIO_LOCK();
 1151         mv_gpio_value_set(dev, pin, value);
 1152         MV_GPIO_UNLOCK();
 1153 
 1154         return (0);
 1155 }
 1156 
 1157 static int
 1158 mv_gpio_pin_get(device_t dev, uint32_t pin, unsigned int *value)
 1159 {
 1160         struct mv_gpio_softc *sc = device_get_softc(dev);
 1161         if (value == NULL)
 1162                 return (EINVAL);
 1163 
 1164         if (pin >= sc->pin_num)
 1165                 return (EINVAL);
 1166 
 1167         MV_GPIO_LOCK();
 1168         *value = mv_gpio_in(dev, pin);
 1169         MV_GPIO_UNLOCK();
 1170 
 1171         return (0);
 1172 }
 1173 
 1174 static int
 1175 mv_gpio_pin_toggle(device_t dev, uint32_t pin)
 1176 {
 1177         struct mv_gpio_softc *sc = device_get_softc(dev);
 1178         uint32_t value;
 1179         if (pin >= sc->pin_num)
 1180                 return (EINVAL);
 1181 
 1182         MV_GPIO_LOCK();
 1183         value = mv_gpio_in(dev, pin);
 1184         value = (~value) & 1;
 1185         mv_gpio_value_set(dev, pin, value);
 1186         MV_GPIO_UNLOCK();
 1187 
 1188         return (0);
 1189 }
 1190 
 1191 static device_t
 1192 mv_gpio_get_bus(device_t dev)
 1193 {
 1194         struct mv_gpio_softc *sc = device_get_softc(dev);
 1195 
 1196         return (sc->sc_busdev);
 1197 }
 1198 
 1199 static int
 1200 mv_gpio_map_gpios(device_t bus, phandle_t dev, phandle_t gparent, int gcells,
 1201     pcell_t *gpios, uint32_t *pin, uint32_t *flags)
 1202 {
 1203         struct mv_gpio_softc *sc = device_get_softc(bus);
 1204 
 1205         if (gpios[0] >= sc->pin_num)
 1206                 return (EINVAL);
 1207 
 1208         *pin = gpios[0];
 1209         *flags = gpios[1];
 1210         mv_gpio_configure(bus, *pin, *flags, ~0);
 1211 
 1212         return (0);
 1213 }

Cache object: 54f81ca87ca55a234f027ae3b1e3b79c


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.