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

Cache object: e8689e988f7a4c1cf96e219ffbd8f06f


[ 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.