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

Cache object: 6e6bbd611ade6593e3be3dde284aba6b


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