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/mvebu_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  * Copyright (c) 2020 Michal Meloun <mmel@FreeBSD.org>
    3  *
    4  * Redistribution and use in source and binary forms, with or without
    5  * modification, are permitted provided that the following conditions
    6  * are met:
    7  * 1. Redistributions of source code must retain the above copyright
    8  *    notice, this list of conditions and the following disclaimer.
    9  * 2. Redistributions in binary form must reproduce the above copyright
   10  *    notice, this list of conditions and the following disclaimer in the
   11  *    documentation and/or other materials provided with the distribution.
   12  *
   13  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
   14  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   15  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   16  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
   17  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   18  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
   19  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   20  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   21  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
   22  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   23  * SUCH DAMAGE.
   24  */
   25 
   26 #include <sys/cdefs.h>
   27 __FBSDID("$FreeBSD$");
   28 
   29 /*
   30  * ARMADA 8040 GPIO driver.
   31  */
   32 #include "opt_platform.h"
   33 #include <sys/param.h>
   34 #include <sys/systm.h>
   35 #include <sys/bus.h>
   36 #include <sys/gpio.h>
   37 #include <sys/kernel.h>
   38 #include <sys/proc.h>
   39 #include <sys/rman.h>
   40 #include <sys/lock.h>
   41 #include <sys/module.h>
   42 #include <sys/mutex.h>
   43 
   44 #include <machine/bus.h>
   45 #include <machine/intr.h>
   46 #include <machine/resource.h>
   47 
   48 #include <dev/extres/syscon/syscon.h>
   49 
   50 #include <dev/gpio/gpiobusvar.h>
   51 
   52 #include <dev/ofw/openfirm.h>
   53 #include <dev/ofw/ofw_bus.h>
   54 #include <dev/ofw/ofw_bus_subr.h>
   55 
   56 #include "pic_if.h"
   57 #include "syscon_if.h"
   58 
   59 #define GPIO_LOCK(_sc)          mtx_lock(&(_sc)->mtx)
   60 #define GPIO_UNLOCK(_sc)        mtx_unlock(&(_sc)->mtx)
   61 #define GPIO_LOCK_INIT(_sc)     mtx_init(&_sc->mtx,                     \
   62             device_get_nameunit(_sc->dev), "mvebu_gpio", MTX_DEF)
   63 #define GPIO_LOCK_DESTROY(_sc)  mtx_destroy(&_sc->mtx);
   64 #define GPIO_ASSERT_LOCKED(_sc) mtx_assert(&_sc->mtx, MA_OWNED);
   65 #define GPIO_ASSERT_UNLOCKED(_sc) mtx_assert(&_sc->mtx, MA_NOTOWNED);
   66 
   67 #define GPIO_DATA_OUT           0x00
   68 #define GPIO_CONTROL            0x04
   69 #define GPIO_BLINK_ENA          0x08
   70 #define GPIO_DATA_IN_POL        0x0C
   71 #define GPIO_DATA_IN            0x10
   72 #define GPIO_INT_CAUSE          0x14
   73 #define GPIO_INT_MASK           0x18
   74 #define GPIO_INT_LEVEL_MASK     0x1C
   75 #define GPIO_CONTROL_SET        0x28
   76 #define GPIO_CONTROL_CLR        0x2C
   77 #define GPIO_DATA_SET           0x30
   78 #define GPIO_DATA_CLR           0x34
   79 
   80 #define GPIO_BIT(_p)            ((_p) % 32)
   81 #define GPIO_REGNUM(_p)         ((_p) / 32)
   82 
   83 #define MV_GPIO_MAX_NIRQS       4
   84 #define MV_GPIO_MAX_NPINS       32
   85 
   86 struct mvebu_gpio_irqsrc {
   87         struct intr_irqsrc      isrc;
   88         u_int                   irq;
   89         bool                    is_level;
   90         bool                    is_inverted;
   91 };
   92 
   93 struct mvebu_gpio_softc;
   94 struct mvebu_gpio_irq_cookie {
   95         struct mvebu_gpio_softc *sc;
   96         int                     bank_num;
   97 };
   98 
   99 struct mvebu_gpio_softc {
  100         device_t                dev;
  101         device_t                busdev;
  102         struct mtx              mtx;
  103         struct syscon           *syscon;
  104         uint32_t                offset;
  105         struct resource         *irq_res[MV_GPIO_MAX_NIRQS];
  106         void                    *irq_ih[MV_GPIO_MAX_NIRQS];
  107         struct mvebu_gpio_irq_cookie irq_cookies[MV_GPIO_MAX_NIRQS];
  108         int                     gpio_npins;
  109         struct gpio_pin         gpio_pins[MV_GPIO_MAX_NPINS];
  110         struct mvebu_gpio_irqsrc *isrcs;
  111 };
  112 
  113 static struct ofw_compat_data compat_data[] = {
  114         {"marvell,armada-8k-gpio", 1},
  115         {NULL, 0}
  116 };
  117 
  118 /* --------------------------------------------------------------------------
  119  *
  120  * GPIO
  121  *
  122  */
  123 static inline void
  124 gpio_write(struct mvebu_gpio_softc *sc, bus_size_t reg,
  125     struct gpio_pin *pin, uint32_t val)
  126 {
  127         int bit;
  128 
  129         bit = GPIO_BIT(pin->gp_pin);
  130         SYSCON_WRITE_4(sc->syscon, sc->offset + GPIO_REGNUM(pin->gp_pin) + reg,
  131             (val & 1) << bit);
  132 }
  133 
  134 static inline uint32_t
  135 gpio_read(struct mvebu_gpio_softc *sc, bus_size_t reg, struct gpio_pin *pin)
  136 {
  137         int bit;
  138         uint32_t val;
  139 
  140         bit = GPIO_BIT(pin->gp_pin);
  141         val = SYSCON_READ_4(sc->syscon,
  142             sc->offset + GPIO_REGNUM(pin->gp_pin) + reg);
  143 
  144         return (val >> bit) & 1;
  145 }
  146 
  147 static inline void
  148 gpio_modify(struct mvebu_gpio_softc *sc, bus_size_t reg,
  149     struct gpio_pin *pin, uint32_t val)
  150 {
  151         int bit;
  152 
  153         bit = GPIO_BIT(pin->gp_pin);
  154         SYSCON_MODIFY_4(sc->syscon, sc->offset + GPIO_REGNUM(pin->gp_pin) + reg,
  155             1 << bit, (val & 1) << bit);
  156 }
  157 
  158 static void
  159 mvebu_gpio_pin_configure(struct mvebu_gpio_softc *sc, struct gpio_pin *pin,
  160     unsigned int flags)
  161 {
  162 
  163         if ((flags & (GPIO_PIN_INPUT | GPIO_PIN_OUTPUT)) == 0)
  164                 return;
  165 
  166         /* Manage input/output */
  167         pin->gp_flags &= ~(GPIO_PIN_INPUT | GPIO_PIN_OUTPUT);
  168         if (flags & GPIO_PIN_OUTPUT) {
  169                 pin->gp_flags |= GPIO_PIN_OUTPUT;
  170                 gpio_write(sc, GPIO_CONTROL_CLR, pin, 1);
  171         } else {
  172                 pin->gp_flags |= GPIO_PIN_INPUT;
  173                 gpio_write(sc, GPIO_CONTROL_SET, pin, 1);
  174         }
  175 }
  176 
  177 static device_t
  178 mvebu_gpio_get_bus(device_t dev)
  179 {
  180         struct mvebu_gpio_softc *sc;
  181 
  182         sc = device_get_softc(dev);
  183         return (sc->busdev);
  184 }
  185 
  186 static int
  187 mvebu_gpio_pin_max(device_t dev, int *maxpin)
  188 {
  189         struct mvebu_gpio_softc *sc;
  190 
  191         sc = device_get_softc(dev);
  192         *maxpin = sc->gpio_npins - 1;
  193         return (0);
  194 }
  195 
  196 static int
  197 mvebu_gpio_pin_getcaps(device_t dev, uint32_t pin, uint32_t *caps)
  198 {
  199         struct mvebu_gpio_softc *sc;
  200 
  201         sc = device_get_softc(dev);
  202         if (pin >= sc->gpio_npins)
  203                 return (EINVAL);
  204 
  205         *caps = sc->gpio_pins[pin].gp_caps;
  206 
  207         return (0);
  208 }
  209 
  210 static int
  211 mvebu_gpio_pin_getflags(device_t dev, uint32_t pin, uint32_t *flags)
  212 {
  213         struct mvebu_gpio_softc *sc;
  214 
  215         sc = device_get_softc(dev);
  216         if (pin >= sc->gpio_npins)
  217                 return (EINVAL);
  218 
  219         *flags = sc->gpio_pins[pin].gp_flags;
  220 
  221         return (0);
  222 }
  223 
  224 static int
  225 mvebu_gpio_pin_getname(device_t dev, uint32_t pin, char *name)
  226 {
  227         struct mvebu_gpio_softc *sc;
  228 
  229         sc = device_get_softc(dev);
  230         if (pin >= sc->gpio_npins)
  231                 return (EINVAL);
  232 
  233         memcpy(name, sc->gpio_pins[pin].gp_name, GPIOMAXNAME);
  234 
  235         return (0);
  236 }
  237 
  238 static int
  239 mvebu_gpio_pin_setflags(device_t dev, uint32_t pin, uint32_t flags)
  240 {
  241         struct mvebu_gpio_softc *sc;
  242 
  243         sc = device_get_softc(dev);
  244         if (pin >= sc->gpio_npins)
  245                 return (EINVAL);
  246 
  247         mvebu_gpio_pin_configure(sc, &sc->gpio_pins[pin], flags);
  248 
  249         return (0);
  250 }
  251 
  252 static int
  253 mvebu_gpio_pin_set(device_t dev, uint32_t pin, unsigned int value)
  254 {
  255         struct mvebu_gpio_softc *sc;
  256 
  257         sc = device_get_softc(dev);
  258         if (pin >= sc->gpio_npins)
  259                 return (EINVAL);
  260 
  261         if (value != 0)
  262                 gpio_write(sc, GPIO_DATA_SET, &sc->gpio_pins[pin], 1);
  263         else
  264                 gpio_write(sc, GPIO_DATA_CLR, &sc->gpio_pins[pin], 1);
  265 
  266         return (0);
  267 }
  268 
  269 static int
  270 mvebu_gpio_pin_get(device_t dev, uint32_t pin, unsigned int *val)
  271 {
  272         struct mvebu_gpio_softc *sc;
  273 
  274         sc = device_get_softc(dev);
  275         if (pin >= sc->gpio_npins)
  276                 return (EINVAL);
  277 
  278         GPIO_LOCK(sc);
  279         *val = gpio_read(sc, GPIO_DATA_IN, &sc->gpio_pins[pin]);
  280         *val ^= gpio_read(sc, GPIO_DATA_IN_POL, &sc->gpio_pins[pin]);
  281         GPIO_UNLOCK(sc);
  282 
  283         return (0);
  284 }
  285 
  286 static int
  287 mvebu_gpio_pin_toggle(device_t dev, uint32_t pin)
  288 {
  289         struct mvebu_gpio_softc *sc;
  290         uint32_t val;
  291 
  292         sc = device_get_softc(dev);
  293         if (pin >= sc->gpio_npins)
  294                 return (EINVAL);
  295 
  296         GPIO_LOCK(sc);
  297         mvebu_gpio_pin_get(sc->dev, pin, &val);
  298         if (val != 0)
  299                 gpio_write(sc, GPIO_DATA_CLR, &sc->gpio_pins[pin], 1);
  300         else
  301                 gpio_write(sc, GPIO_DATA_SET, &sc->gpio_pins[pin], 1);
  302         GPIO_UNLOCK(sc);
  303 
  304         return (0);
  305 }
  306 
  307 /* --------------------------------------------------------------------------
  308  *
  309  * Interrupts
  310  *
  311  */
  312 static inline void
  313 intr_modify(struct mvebu_gpio_softc *sc, bus_addr_t reg,
  314     struct mvebu_gpio_irqsrc *mgi, uint32_t val)
  315 {
  316         int bit;
  317 
  318         bit = GPIO_BIT(mgi->irq);
  319         SYSCON_MODIFY_4(sc->syscon,
  320             sc->offset + GPIO_REGNUM(mgi->irq) + reg, 1 << bit,
  321             (val & 1) << bit);
  322 }
  323 
  324 static inline void
  325 mvebu_gpio_isrc_mask(struct mvebu_gpio_softc *sc,
  326      struct mvebu_gpio_irqsrc *mgi, uint32_t val)
  327 {
  328 
  329         if (mgi->is_level)
  330                 intr_modify(sc, GPIO_INT_LEVEL_MASK, mgi, val);
  331         else
  332                 intr_modify(sc, GPIO_INT_MASK, mgi, val);
  333 }
  334 
  335 static inline void
  336 mvebu_gpio_isrc_eoi(struct mvebu_gpio_softc *sc,
  337      struct mvebu_gpio_irqsrc *mgi)
  338 {
  339         int bit;
  340 
  341         if (!mgi->is_level) {
  342                 bit = GPIO_BIT(mgi->irq);
  343                 SYSCON_WRITE_4(sc->syscon,
  344                     sc->offset + GPIO_REGNUM(mgi->irq) + GPIO_INT_CAUSE,
  345                     ~(1 << bit));
  346         }
  347 }
  348 
  349 static int
  350 mvebu_gpio_pic_attach(struct mvebu_gpio_softc *sc)
  351 {
  352         int rv;
  353         uint32_t irq;
  354         const char *name;
  355 
  356         sc->isrcs = malloc(sizeof(*sc->isrcs) * sc->gpio_npins, M_DEVBUF,
  357             M_WAITOK | M_ZERO);
  358 
  359         name = device_get_nameunit(sc->dev);
  360         for (irq = 0; irq < sc->gpio_npins; irq++) {
  361                 sc->isrcs[irq].irq = irq;
  362                 sc->isrcs[irq].is_level = false;
  363                 sc->isrcs[irq].is_inverted = false;
  364                 rv = intr_isrc_register(&sc->isrcs[irq].isrc,
  365                     sc->dev, 0, "%s,%u", name, irq);
  366                 if (rv != 0)
  367                         return (rv); /* XXX deregister ISRCs */
  368         }
  369         if (intr_pic_register(sc->dev,
  370             OF_xref_from_node(ofw_bus_get_node(sc->dev))) == NULL)
  371                 return (ENXIO);
  372 
  373         return (0);
  374 }
  375 
  376 static int
  377 mvebu_gpio_pic_detach(struct mvebu_gpio_softc *sc)
  378 {
  379 
  380         /*
  381          *  There has not been established any procedure yet
  382          *  how to detach PIC from living system correctly.
  383          */
  384         device_printf(sc->dev, "%s: not implemented yet\n", __func__);
  385         return (EBUSY);
  386 }
  387 
  388 static void
  389 mvebu_gpio_pic_disable_intr(device_t dev, struct intr_irqsrc *isrc)
  390 {
  391         struct mvebu_gpio_softc *sc;
  392         struct mvebu_gpio_irqsrc *mgi;
  393 
  394         sc = device_get_softc(dev);
  395         mgi = (struct mvebu_gpio_irqsrc *)isrc;
  396         mvebu_gpio_isrc_mask(sc, mgi, 0);
  397 }
  398 
  399 static void
  400 mvebu_gpio_pic_enable_intr(device_t dev, struct intr_irqsrc *isrc)
  401 {
  402         struct mvebu_gpio_softc *sc;
  403         struct mvebu_gpio_irqsrc *mgi;
  404 
  405         sc = device_get_softc(dev);
  406         mgi = (struct mvebu_gpio_irqsrc *)isrc;
  407         mvebu_gpio_isrc_mask(sc, mgi, 1);
  408 }
  409 
  410 static int
  411 mvebu_gpio_pic_map_fdt(struct mvebu_gpio_softc *sc, u_int ncells,
  412     pcell_t *cells, u_int *irqp, bool *invertedp, bool *levelp)
  413 {
  414         bool inverted, level;
  415 
  416         /*
  417          * The first cell is the interrupt number.
  418          * The second cell is used to specify flags:
  419          *      bits[3:0] trigger type and level flags:
  420          *              1 = low-to-high edge triggered.
  421          *              2 = high-to-low edge triggered.
  422          *              4 = active high level-sensitive.
  423          *              8 = active low level-sensitive.
  424          */
  425         if (ncells != 2 || cells[0] >= sc->gpio_npins)
  426                 return (EINVAL);
  427 
  428         switch (cells[1]) {
  429         case 1:
  430                 inverted  = false;
  431                 level  = false;
  432                 break;
  433         case 2:
  434                 inverted  = true;
  435                 level  = false;
  436                 break;
  437         case 4:
  438                 inverted  = false;
  439                 level  = true;
  440                 break;
  441         case 8:
  442                 inverted  = true;
  443                 level  = true;
  444                 break;
  445         default:
  446                 return (EINVAL);
  447         }
  448         *irqp = cells[0];
  449         if (invertedp != NULL)
  450                 *invertedp = inverted;
  451         if (levelp != NULL)
  452                 *levelp = level;
  453         return (0);
  454 }
  455 
  456 static int
  457 mvebu_gpio_pic_map_gpio(struct mvebu_gpio_softc *sc, u_int gpio_pin_num,
  458     u_int gpio_pin_flags, u_int intr_mode, u_int *irqp, bool *invertedp,
  459     bool *levelp)
  460 {
  461         bool inverted, level;
  462 
  463         if (gpio_pin_num >= sc->gpio_npins)
  464                 return (EINVAL);
  465 
  466         switch (intr_mode) {
  467         case GPIO_INTR_LEVEL_LOW:
  468                 inverted  = true;
  469                 level = true;
  470                 break;
  471         case GPIO_INTR_LEVEL_HIGH:
  472                 inverted  = false;
  473                 level = true;
  474                 break;
  475         case GPIO_INTR_CONFORM:
  476         case GPIO_INTR_EDGE_RISING:
  477                 inverted  = false;
  478                 level = false;
  479                 break;
  480         case GPIO_INTR_EDGE_FALLING:
  481                 inverted  = true;
  482                 level = false;
  483                 break;
  484         default:
  485                 return (EINVAL);
  486         }
  487         *irqp = gpio_pin_num;
  488         if (invertedp != NULL)
  489                 *invertedp = inverted;
  490         if (levelp != NULL)
  491                 *levelp = level;
  492         return (0);
  493 }
  494 
  495 static int
  496 mvebu_gpio_pic_map_intr(device_t dev, struct intr_map_data *data,
  497     struct intr_irqsrc **isrcp)
  498 {
  499         int rv;
  500         u_int irq;
  501         struct mvebu_gpio_softc *sc;
  502 
  503         sc = device_get_softc(dev);
  504 
  505         if (data->type == INTR_MAP_DATA_FDT) {
  506                 struct intr_map_data_fdt *daf;
  507 
  508                 daf = (struct intr_map_data_fdt *)data;
  509                 rv = mvebu_gpio_pic_map_fdt(sc, daf->ncells, daf->cells, &irq,
  510                     NULL, NULL);
  511         } else if (data->type == INTR_MAP_DATA_GPIO) {
  512                 struct intr_map_data_gpio *dag;
  513 
  514                 dag = (struct intr_map_data_gpio *)data;
  515                 rv = mvebu_gpio_pic_map_gpio(sc, dag->gpio_pin_num,
  516                    dag->gpio_pin_flags, dag->gpio_intr_mode, &irq, NULL, NULL);
  517         } else
  518                 return (ENOTSUP);
  519 
  520         if (rv == 0)
  521                 *isrcp = &sc->isrcs[irq].isrc;
  522         return (rv);
  523 }
  524 
  525 static void
  526 mvebu_gpio_pic_post_filter(device_t dev, struct intr_irqsrc *isrc)
  527 {
  528         struct mvebu_gpio_softc *sc;
  529         struct mvebu_gpio_irqsrc *mgi;
  530 
  531         sc = device_get_softc(dev);
  532         mgi = (struct mvebu_gpio_irqsrc *)isrc;
  533         if (mgi->is_level)
  534                 mvebu_gpio_isrc_eoi(sc, mgi);
  535 }
  536 
  537 static void
  538 mvebu_gpio_pic_post_ithread(device_t dev, struct intr_irqsrc *isrc)
  539 {
  540         struct mvebu_gpio_softc *sc;
  541         struct mvebu_gpio_irqsrc *mgi;
  542 
  543         sc = device_get_softc(dev);
  544         mgi = (struct mvebu_gpio_irqsrc *)isrc;
  545         mvebu_gpio_isrc_mask(sc, mgi, 1);
  546 }
  547 
  548 static void
  549 mvebu_gpio_pic_pre_ithread(device_t dev, struct intr_irqsrc *isrc)
  550 {
  551         struct mvebu_gpio_softc *sc;
  552         struct mvebu_gpio_irqsrc *mgi;
  553 
  554         sc = device_get_softc(dev);
  555         mgi = (struct mvebu_gpio_irqsrc *)isrc;
  556 
  557         mvebu_gpio_isrc_mask(sc, mgi, 0);
  558         if (mgi->is_level)
  559                 mvebu_gpio_isrc_eoi(sc, mgi);
  560 }
  561 
  562 static int
  563 mvebu_gpio_pic_setup_intr(device_t dev, struct intr_irqsrc *isrc,
  564     struct resource *res, struct intr_map_data *data)
  565 {
  566         u_int irq;
  567         bool inverted, level;
  568         int rv;
  569         struct mvebu_gpio_softc *sc;
  570         struct mvebu_gpio_irqsrc *mgi;
  571 
  572         sc = device_get_softc(dev);
  573         mgi = (struct mvebu_gpio_irqsrc *)isrc;
  574 
  575         if (data == NULL)
  576                 return (ENOTSUP);
  577 
  578         /* Get and check config for an interrupt. */
  579         if (data->type == INTR_MAP_DATA_FDT) {
  580                 struct intr_map_data_fdt *daf;
  581 
  582                 daf = (struct intr_map_data_fdt *)data;
  583                 rv = mvebu_gpio_pic_map_fdt(sc, daf->ncells, daf->cells, &irq,
  584                     &inverted, &level);
  585         } else if (data->type == INTR_MAP_DATA_GPIO) {
  586                 struct intr_map_data_gpio *dag;
  587 
  588                 dag = (struct intr_map_data_gpio *)data;
  589                 rv = mvebu_gpio_pic_map_gpio(sc, dag->gpio_pin_num,
  590                    dag->gpio_pin_flags, dag->gpio_intr_mode, &irq,
  591                    &inverted, &level);
  592         } else
  593                 return (ENOTSUP);
  594 
  595         if (rv != 0)
  596                 return (EINVAL);
  597 
  598         /*
  599          * If this is a setup for another handler,
  600          * only check that its configuration match.
  601          */
  602         if (isrc->isrc_handlers != 0)
  603                 return (
  604                     mgi->is_level == level && mgi->is_inverted == inverted ?
  605                     0 : EINVAL);
  606 
  607         mgi->is_level = level;
  608         mgi->is_inverted = inverted;
  609 
  610         GPIO_LOCK(sc);
  611         intr_modify(sc, GPIO_DATA_IN_POL, mgi, inverted ? 1 : 0);
  612         mvebu_gpio_pic_enable_intr(dev, isrc);
  613         GPIO_UNLOCK(sc);
  614 
  615         return (0);
  616 }
  617 
  618 static int
  619 mvebu_gpio_pic_teardown_intr(device_t dev, struct intr_irqsrc *isrc,
  620     struct resource *res, struct intr_map_data *data)
  621 {
  622         struct mvebu_gpio_softc *sc;
  623         struct mvebu_gpio_irqsrc *mgi;
  624 
  625         sc = device_get_softc(dev);
  626         mgi = (struct mvebu_gpio_irqsrc *)isrc;
  627 
  628         if (isrc->isrc_handlers == 0)
  629                 mvebu_gpio_isrc_mask(sc, mgi, 0);
  630         return (0);
  631 }
  632 
  633 /* --------------------------------------------------------------------------
  634  *
  635  * Bus
  636  *
  637  */
  638 
  639 static int
  640 mvebu_gpio_intr(void *arg)
  641 {
  642         u_int i, lvl, edge;
  643         struct mvebu_gpio_softc *sc;
  644         struct trapframe *tf;
  645         struct mvebu_gpio_irqsrc *mgi;
  646         struct mvebu_gpio_irq_cookie *cookie;
  647 
  648         cookie = (struct mvebu_gpio_irq_cookie *)arg;
  649         sc = cookie->sc;
  650         tf = curthread->td_intr_frame;
  651 
  652         for (i = 0; i < sc->gpio_npins; i++) {
  653                 lvl = gpio_read(sc, GPIO_DATA_IN, &sc->gpio_pins[i]);
  654                 lvl &= gpio_read(sc, GPIO_INT_LEVEL_MASK, &sc->gpio_pins[i]);
  655                 edge = gpio_read(sc, GPIO_DATA_IN, &sc->gpio_pins[i]);
  656                 edge &= gpio_read(sc, GPIO_INT_LEVEL_MASK, &sc->gpio_pins[i]);
  657                 if (edge == 0  && lvl == 0)
  658                         continue;
  659 
  660                 mgi = &sc->isrcs[i];
  661                 if (!mgi->is_level)
  662                         mvebu_gpio_isrc_eoi(sc, mgi);
  663 
  664                 if (intr_isrc_dispatch(&mgi->isrc, tf) != 0) {
  665                         mvebu_gpio_isrc_mask(sc, mgi, 0);
  666                         if (mgi->is_level)
  667                                 mvebu_gpio_isrc_eoi(sc, mgi);
  668                         device_printf(sc->dev,
  669                             "Stray irq %u disabled\n", mgi->irq);
  670                 }
  671         }
  672         return (FILTER_HANDLED);
  673 }
  674 
  675 static int
  676 mvebu_gpio_probe(device_t dev)
  677 {
  678 
  679         if (!ofw_bus_status_okay(dev))
  680                 return (ENXIO);
  681         if (ofw_bus_search_compatible(dev, compat_data)->ocd_data == 0)
  682                 return (ENXIO);
  683 
  684         device_set_desc(dev, "Marvell Integrated GPIO Controller");
  685         return (0);
  686 }
  687 
  688 static int
  689 mvebu_gpio_detach(device_t dev)
  690 {
  691         struct mvebu_gpio_softc *sc;
  692         int i;
  693 
  694         sc = device_get_softc(dev);
  695 
  696         KASSERT(mtx_initialized(&sc->mtx), ("gpio mutex not initialized"));
  697 
  698         for (i = 0; i < MV_GPIO_MAX_NIRQS; i++) {
  699                 if (sc->irq_ih[i] != NULL)
  700                         bus_teardown_intr(dev, sc->irq_res[i], sc->irq_ih[i]);
  701         }
  702 
  703         if (sc->isrcs != NULL)
  704                 mvebu_gpio_pic_detach(sc);
  705 
  706         gpiobus_detach_bus(dev);
  707 
  708         for (i = 0; i < MV_GPIO_MAX_NIRQS; i++) {
  709                 if (sc->irq_res[i] != NULL)
  710                         bus_release_resource(dev, SYS_RES_IRQ, 0,
  711                              sc->irq_res[i]);
  712         }
  713         GPIO_LOCK_DESTROY(sc);
  714 
  715         return(0);
  716 }
  717 
  718 static int
  719 mvebu_gpio_attach(device_t dev)
  720 {
  721         struct mvebu_gpio_softc *sc;
  722         phandle_t node;
  723         struct gpio_pin *pin;
  724         pcell_t pincnt;
  725         int i, rv, rid;
  726 
  727         sc = device_get_softc(dev);
  728         sc->dev = dev;
  729         node = ofw_bus_get_node(dev);
  730 
  731         GPIO_LOCK_INIT(sc);
  732 
  733         pincnt = 0;
  734         rv = OF_getencprop(node, "ngpios", &pincnt, sizeof(pcell_t));
  735         if (rv < 0) {
  736                 device_printf(dev,
  737                     "ERROR: no pin-count or ngpios entry found!\n");
  738                 return (ENXIO);
  739         }
  740 
  741         sc->gpio_npins = MIN(pincnt, MV_GPIO_MAX_NPINS);
  742         if (bootverbose)
  743                 device_printf(dev,
  744                     "%d pins available\n", sc->gpio_npins);
  745 
  746         rv = OF_getencprop(node, "offset", &sc->offset, sizeof(sc->offset));
  747         if (rv == -1) {
  748                 device_printf(dev, "ERROR: no 'offset' property found!\n");
  749                 return (ENXIO);
  750         }
  751 
  752         if (SYSCON_GET_HANDLE(sc->dev, &sc->syscon) != 0 ||
  753             sc->syscon == NULL) {
  754                 device_printf(dev, "ERROR: cannot get syscon handle!\n");
  755                 return (ENXIO);
  756         }
  757 
  758         /* Allocate interrupts. */
  759         for (i = 0; i < MV_GPIO_MAX_NIRQS; i++) {
  760                 sc->irq_cookies[i].sc = sc;
  761                 sc->irq_cookies[i].bank_num = i;
  762                 rid = i;
  763                 sc->irq_res[i] = bus_alloc_resource_any(dev, SYS_RES_IRQ,
  764                     &rid, RF_ACTIVE);
  765                 if (sc->irq_res[i] == NULL)
  766                         break;
  767                 if ((bus_setup_intr(dev, sc->irq_res[i],
  768                     INTR_TYPE_MISC | INTR_MPSAFE, mvebu_gpio_intr, NULL,
  769                     &sc->irq_cookies[i], &sc->irq_ih[i]))) {
  770                         device_printf(dev,
  771                             "WARNING: unable to register interrupt handler\n");
  772                         mvebu_gpio_detach(dev);
  773                         return (ENXIO);
  774                 }
  775         }
  776 
  777         /* Init GPIO pins */
  778         for (i = 0; i < sc->gpio_npins; i++) {
  779                 pin = sc->gpio_pins + i;
  780                 pin->gp_pin = i;
  781                 if (sc->irq_res[0] != NULL)
  782                         pin->gp_caps = GPIO_PIN_INPUT | GPIO_PIN_OUTPUT |
  783                             GPIO_INTR_LEVEL_LOW | GPIO_INTR_LEVEL_HIGH |
  784                             GPIO_INTR_EDGE_RISING | GPIO_INTR_EDGE_FALLING;
  785                 else
  786                         pin->gp_caps = GPIO_PIN_INPUT | GPIO_PIN_OUTPUT;
  787                 pin->gp_flags =
  788                     gpio_read(sc, GPIO_CONTROL, &sc->gpio_pins[i]) == 0 ?
  789                     GPIO_PIN_OUTPUT : GPIO_PIN_INPUT;
  790                 snprintf(pin->gp_name, GPIOMAXNAME, "gpio%d", i);
  791 
  792                 /* Init HW */
  793                 gpio_modify(sc, GPIO_INT_MASK, pin, 0);
  794                 gpio_modify(sc, GPIO_INT_LEVEL_MASK, pin, 0);
  795                 gpio_modify(sc, GPIO_INT_CAUSE, pin, 0);
  796                 gpio_modify(sc, GPIO_DATA_IN_POL, pin, 0);
  797                 gpio_modify(sc, GPIO_BLINK_ENA, pin, 0);
  798         }
  799 
  800         if (sc->irq_res[0] != NULL) {
  801                 rv = mvebu_gpio_pic_attach(sc);
  802                 if (rv != 0) {
  803                         device_printf(dev, "WARNING: unable to attach PIC\n");
  804                         mvebu_gpio_detach(dev);
  805                         return (rv);
  806                 }
  807         }
  808 
  809         sc->busdev = gpiobus_attach_bus(dev);
  810         if (sc->busdev == NULL) {
  811                 mvebu_gpio_detach(dev);
  812                 return (ENXIO);
  813         }
  814 
  815         return (bus_generic_attach(dev));
  816 }
  817 
  818 static int
  819 mvebu_gpio_map_gpios(device_t dev, phandle_t pdev, phandle_t gparent,
  820     int gcells, pcell_t *gpios, uint32_t *pin, uint32_t *flags)
  821 {
  822 
  823         if (gcells != 2)
  824                 return (ERANGE);
  825         *pin = gpios[0];
  826         *flags= gpios[1];
  827         return (0);
  828 }
  829 
  830 static phandle_t
  831 mvebu_gpio_get_node(device_t bus, device_t dev)
  832 {
  833 
  834         /* We only have one child, the GPIO bus, which needs our own node. */
  835         return (ofw_bus_get_node(bus));
  836 }
  837 
  838 static device_method_t mvebu_gpio_methods[] = {
  839         DEVMETHOD(device_probe,         mvebu_gpio_probe),
  840         DEVMETHOD(device_attach,        mvebu_gpio_attach),
  841         DEVMETHOD(device_detach,        mvebu_gpio_detach),
  842 
  843         /* Interrupt controller interface */
  844         DEVMETHOD(pic_disable_intr,     mvebu_gpio_pic_disable_intr),
  845         DEVMETHOD(pic_enable_intr,      mvebu_gpio_pic_enable_intr),
  846         DEVMETHOD(pic_map_intr,         mvebu_gpio_pic_map_intr),
  847         DEVMETHOD(pic_setup_intr,       mvebu_gpio_pic_setup_intr),
  848         DEVMETHOD(pic_teardown_intr,    mvebu_gpio_pic_teardown_intr),
  849         DEVMETHOD(pic_post_filter,      mvebu_gpio_pic_post_filter),
  850         DEVMETHOD(pic_post_ithread,     mvebu_gpio_pic_post_ithread),
  851         DEVMETHOD(pic_pre_ithread,      mvebu_gpio_pic_pre_ithread),
  852 
  853         /* GPIO protocol */
  854         DEVMETHOD(gpio_get_bus,         mvebu_gpio_get_bus),
  855         DEVMETHOD(gpio_pin_max,         mvebu_gpio_pin_max),
  856         DEVMETHOD(gpio_pin_getname,     mvebu_gpio_pin_getname),
  857         DEVMETHOD(gpio_pin_getflags,    mvebu_gpio_pin_getflags),
  858         DEVMETHOD(gpio_pin_getcaps,     mvebu_gpio_pin_getcaps),
  859         DEVMETHOD(gpio_pin_setflags,    mvebu_gpio_pin_setflags),
  860         DEVMETHOD(gpio_pin_get,         mvebu_gpio_pin_get),
  861         DEVMETHOD(gpio_pin_set,         mvebu_gpio_pin_set),
  862         DEVMETHOD(gpio_pin_toggle,      mvebu_gpio_pin_toggle),
  863         DEVMETHOD(gpio_map_gpios,       mvebu_gpio_map_gpios),
  864 
  865         /* ofw_bus interface */
  866         DEVMETHOD(ofw_bus_get_node,     mvebu_gpio_get_node),
  867 
  868         DEVMETHOD_END
  869 };
  870 
  871 static devclass_t mvebu_gpio_devclass;
  872 static DEFINE_CLASS_0(gpio, mvebu_gpio_driver, mvebu_gpio_methods,
  873     sizeof(struct mvebu_gpio_softc));
  874 EARLY_DRIVER_MODULE(mvebu_gpio, simplebus, mvebu_gpio_driver,
  875      mvebu_gpio_devclass, NULL, NULL,
  876      BUS_PASS_TIMER + BUS_PASS_ORDER_LAST);

Cache object: f85413a3edaba65ca4d8813b9c0ce6db


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