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/broadcom/bcm2835/bcm2835_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) 2012 Oleksandr Tymoshenko <gonzo@FreeBSD.org>
    5  * Copyright (c) 2012-2015 Luiz Otavio O Souza <loos@FreeBSD.org>
    6  * All rights reserved.
    7  *
    8  * Redistribution and use in source and binary forms, with or without
    9  * modification, are permitted provided that the following conditions
   10  * are met:
   11  * 1. Redistributions of source code must retain the above copyright
   12  *    notice, this list of conditions and the following disclaimer.
   13  * 2. Redistributions in binary form must reproduce the above copyright
   14  *    notice, this list of conditions and the following disclaimer in the
   15  *    documentation and/or other materials provided with the distribution.
   16  *
   17  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
   18  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   19  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   20  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
   21  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   22  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
   23  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   24  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   25  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
   26  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   27  * SUCH DAMAGE.
   28  *
   29  */
   30 #include <sys/cdefs.h>
   31 __FBSDID("$FreeBSD$");
   32 
   33 #include "opt_platform.h"
   34 
   35 #include <sys/param.h>
   36 #include <sys/systm.h>
   37 #include <sys/bus.h>
   38 #include <sys/gpio.h>
   39 #include <sys/interrupt.h>
   40 #include <sys/kernel.h>
   41 #include <sys/lock.h>
   42 #include <sys/module.h>
   43 #include <sys/mutex.h>
   44 #include <sys/proc.h>
   45 #include <sys/rman.h>
   46 #include <sys/sysctl.h>
   47 
   48 #include <machine/bus.h>
   49 #include <machine/intr.h>
   50 
   51 #include <dev/fdt/fdt_pinctrl.h>
   52 #include <dev/gpio/gpiobusvar.h>
   53 #include <dev/ofw/ofw_bus.h>
   54 
   55 #include "gpio_if.h"
   56 
   57 #include "pic_if.h"
   58 
   59 #ifdef DEBUG
   60 #define dprintf(fmt, args...) do { printf("%s(): ", __func__);   \
   61     printf(fmt,##args); } while (0)
   62 #else
   63 #define dprintf(fmt, args...)
   64 #endif
   65 
   66 #define BCM_GPIO_IRQS           4
   67 #define BCM_GPIO_PINS           54
   68 #define BCM_GPIO_PINS_PER_BANK  32
   69 
   70 #define BCM_GPIO_DEFAULT_CAPS   (GPIO_PIN_INPUT | GPIO_PIN_OUTPUT |     \
   71     GPIO_PIN_PULLUP | GPIO_PIN_PULLDOWN | GPIO_INTR_LEVEL_LOW |         \
   72     GPIO_INTR_LEVEL_HIGH | GPIO_INTR_EDGE_RISING |                      \
   73     GPIO_INTR_EDGE_FALLING | GPIO_INTR_EDGE_BOTH)
   74 
   75 #define BCM2835_FSEL_GPIO_IN    0
   76 #define BCM2835_FSEL_GPIO_OUT   1
   77 #define BCM2835_FSEL_ALT5       2
   78 #define BCM2835_FSEL_ALT4       3
   79 #define BCM2835_FSEL_ALT0       4
   80 #define BCM2835_FSEL_ALT1       5
   81 #define BCM2835_FSEL_ALT2       6
   82 #define BCM2835_FSEL_ALT3       7
   83 
   84 #define BCM2835_PUD_OFF         0
   85 #define BCM2835_PUD_DOWN        1
   86 #define BCM2835_PUD_UP          2
   87 
   88 static struct resource_spec bcm_gpio_res_spec[] = {
   89         { SYS_RES_MEMORY, 0, RF_ACTIVE },
   90         { SYS_RES_IRQ, 0, RF_ACTIVE },  /* bank 0 interrupt */
   91         { SYS_RES_IRQ, 1, RF_ACTIVE },  /* bank 1 interrupt */
   92         { -1, 0, 0 }
   93 };
   94 
   95 struct bcm_gpio_sysctl {
   96         struct bcm_gpio_softc   *sc;
   97         uint32_t                pin;
   98 };
   99 
  100 struct bcm_gpio_irqsrc {
  101         struct intr_irqsrc      bgi_isrc;
  102         uint32_t                bgi_irq;
  103         uint32_t                bgi_mode;
  104         uint32_t                bgi_mask;
  105 };
  106 
  107 struct bcm_gpio_softc {
  108         device_t                sc_dev;
  109         device_t                sc_busdev;
  110         struct mtx              sc_mtx;
  111         struct resource *       sc_res[BCM_GPIO_IRQS + 1];
  112         bus_space_tag_t         sc_bst;
  113         bus_space_handle_t      sc_bsh;
  114         void *                  sc_intrhand[BCM_GPIO_IRQS];
  115         int                     sc_gpio_npins;
  116         int                     sc_ro_npins;
  117         int                     sc_ro_pins[BCM_GPIO_PINS];
  118         struct gpio_pin         sc_gpio_pins[BCM_GPIO_PINS];
  119         struct bcm_gpio_sysctl  sc_sysctl[BCM_GPIO_PINS];
  120         struct bcm_gpio_irqsrc  sc_isrcs[BCM_GPIO_PINS];
  121 };
  122 
  123 enum bcm_gpio_pud {
  124         BCM_GPIO_NONE,
  125         BCM_GPIO_PULLDOWN,
  126         BCM_GPIO_PULLUP,
  127 };
  128 
  129 #define BCM_GPIO_LOCK(_sc)      mtx_lock_spin(&(_sc)->sc_mtx)
  130 #define BCM_GPIO_UNLOCK(_sc)    mtx_unlock_spin(&(_sc)->sc_mtx)
  131 #define BCM_GPIO_LOCK_ASSERT(_sc)       mtx_assert(&(_sc)->sc_mtx, MA_OWNED)
  132 #define BCM_GPIO_WRITE(_sc, _off, _val)         \
  133     bus_space_write_4((_sc)->sc_bst, (_sc)->sc_bsh, _off, _val)
  134 #define BCM_GPIO_READ(_sc, _off)                \
  135     bus_space_read_4((_sc)->sc_bst, (_sc)->sc_bsh, _off)
  136 #define BCM_GPIO_CLEAR_BITS(_sc, _off, _bits)   \
  137     BCM_GPIO_WRITE(_sc, _off, BCM_GPIO_READ(_sc, _off) & ~(_bits))
  138 #define BCM_GPIO_SET_BITS(_sc, _off, _bits)     \
  139     BCM_GPIO_WRITE(_sc, _off, BCM_GPIO_READ(_sc, _off) | _bits)
  140 #define BCM_GPIO_BANK(a)        (a / BCM_GPIO_PINS_PER_BANK)
  141 #define BCM_GPIO_MASK(a)        (1U << (a % BCM_GPIO_PINS_PER_BANK))
  142 
  143 #define BCM_GPIO_GPFSEL(_bank)  (0x00 + _bank * 4)      /* Function Select */
  144 #define BCM_GPIO_GPSET(_bank)   (0x1c + _bank * 4)      /* Pin Out Set */
  145 #define BCM_GPIO_GPCLR(_bank)   (0x28 + _bank * 4)      /* Pin Out Clear */
  146 #define BCM_GPIO_GPLEV(_bank)   (0x34 + _bank * 4)      /* Pin Level */
  147 #define BCM_GPIO_GPEDS(_bank)   (0x40 + _bank * 4)      /* Event Status */
  148 #define BCM_GPIO_GPREN(_bank)   (0x4c + _bank * 4)      /* Rising Edge irq */
  149 #define BCM_GPIO_GPFEN(_bank)   (0x58 + _bank * 4)      /* Falling Edge irq */
  150 #define BCM_GPIO_GPHEN(_bank)   (0x64 + _bank * 4)      /* High Level irq */
  151 #define BCM_GPIO_GPLEN(_bank)   (0x70 + _bank * 4)      /* Low Level irq */
  152 #define BCM_GPIO_GPAREN(_bank)  (0x7c + _bank * 4)      /* Async Rising Edge */
  153 #define BCM_GPIO_GPAFEN(_bank)  (0x88 + _bank * 4)      /* Async Falling Egde */
  154 #define BCM_GPIO_GPPUD(_bank)   (0x94)                  /* Pin Pull up/down */
  155 #define BCM_GPIO_GPPUDCLK(_bank) (0x98 + _bank * 4)     /* Pin Pull up clock */
  156 
  157 static struct ofw_compat_data compat_data[] = {
  158         {"broadcom,bcm2835-gpio",       1},
  159         {"brcm,bcm2835-gpio",           1},
  160         {"brcm,bcm2711-gpio",           1},
  161         {NULL,                          0}
  162 };
  163 
  164 static struct bcm_gpio_softc *bcm_gpio_sc = NULL;
  165 
  166 static int bcm_gpio_intr_bank0(void *arg);
  167 static int bcm_gpio_intr_bank1(void *arg);
  168 static int bcm_gpio_pic_attach(struct bcm_gpio_softc *sc);
  169 static int bcm_gpio_pic_detach(struct bcm_gpio_softc *sc);
  170 
  171 static int
  172 bcm_gpio_pin_is_ro(struct bcm_gpio_softc *sc, int pin)
  173 {
  174         int i;
  175 
  176         for (i = 0; i < sc->sc_ro_npins; i++)
  177                 if (pin == sc->sc_ro_pins[i])
  178                         return (1);
  179         return (0);
  180 }
  181 
  182 static uint32_t
  183 bcm_gpio_get_function(struct bcm_gpio_softc *sc, uint32_t pin)
  184 {
  185         uint32_t bank, func, offset;
  186 
  187         /* Five banks, 10 pins per bank, 3 bits per pin. */
  188         bank = pin / 10;
  189         offset = (pin - bank * 10) * 3;
  190 
  191         BCM_GPIO_LOCK(sc);
  192         func = (BCM_GPIO_READ(sc, BCM_GPIO_GPFSEL(bank)) >> offset) & 7;
  193         BCM_GPIO_UNLOCK(sc);
  194 
  195         return (func);
  196 }
  197 
  198 static void
  199 bcm_gpio_func_str(uint32_t nfunc, char *buf, int bufsize)
  200 {
  201 
  202         switch (nfunc) {
  203         case BCM2835_FSEL_GPIO_IN:
  204                 strncpy(buf, "input", bufsize);
  205                 break;
  206         case BCM2835_FSEL_GPIO_OUT:
  207                 strncpy(buf, "output", bufsize);
  208                 break;
  209         case BCM2835_FSEL_ALT0:
  210                 strncpy(buf, "alt0", bufsize);
  211                 break;
  212         case BCM2835_FSEL_ALT1:
  213                 strncpy(buf, "alt1", bufsize);
  214                 break;
  215         case BCM2835_FSEL_ALT2:
  216                 strncpy(buf, "alt2", bufsize);
  217                 break;
  218         case BCM2835_FSEL_ALT3:
  219                 strncpy(buf, "alt3", bufsize);
  220                 break;
  221         case BCM2835_FSEL_ALT4:
  222                 strncpy(buf, "alt4", bufsize);
  223                 break;
  224         case BCM2835_FSEL_ALT5:
  225                 strncpy(buf, "alt5", bufsize);
  226                 break;
  227         default:
  228                 strncpy(buf, "invalid", bufsize);
  229         }
  230 }
  231 
  232 static int
  233 bcm_gpio_str_func(char *func, uint32_t *nfunc)
  234 {
  235 
  236         if (strcasecmp(func, "input") == 0)
  237                 *nfunc = BCM2835_FSEL_GPIO_IN;
  238         else if (strcasecmp(func, "output") == 0)
  239                 *nfunc = BCM2835_FSEL_GPIO_OUT;
  240         else if (strcasecmp(func, "alt0") == 0)
  241                 *nfunc = BCM2835_FSEL_ALT0;
  242         else if (strcasecmp(func, "alt1") == 0)
  243                 *nfunc = BCM2835_FSEL_ALT1;
  244         else if (strcasecmp(func, "alt2") == 0)
  245                 *nfunc = BCM2835_FSEL_ALT2;
  246         else if (strcasecmp(func, "alt3") == 0)
  247                 *nfunc = BCM2835_FSEL_ALT3;
  248         else if (strcasecmp(func, "alt4") == 0)
  249                 *nfunc = BCM2835_FSEL_ALT4;
  250         else if (strcasecmp(func, "alt5") == 0)
  251                 *nfunc = BCM2835_FSEL_ALT5;
  252         else
  253                 return (-1);
  254 
  255         return (0);
  256 }
  257 
  258 static uint32_t
  259 bcm_gpio_func_flag(uint32_t nfunc)
  260 {
  261 
  262         switch (nfunc) {
  263         case BCM2835_FSEL_GPIO_IN:
  264                 return (GPIO_PIN_INPUT);
  265         case BCM2835_FSEL_GPIO_OUT:
  266                 return (GPIO_PIN_OUTPUT);
  267         }
  268         return (0);
  269 }
  270 
  271 static void
  272 bcm_gpio_set_function(struct bcm_gpio_softc *sc, uint32_t pin, uint32_t f)
  273 {
  274         uint32_t bank, data, offset;
  275 
  276         /* Must be called with lock held. */
  277         BCM_GPIO_LOCK_ASSERT(sc);
  278 
  279         /* Five banks, 10 pins per bank, 3 bits per pin. */
  280         bank = pin / 10;
  281         offset = (pin - bank * 10) * 3;
  282 
  283         data = BCM_GPIO_READ(sc, BCM_GPIO_GPFSEL(bank));
  284         data &= ~(7 << offset);
  285         data |= (f << offset);
  286         BCM_GPIO_WRITE(sc, BCM_GPIO_GPFSEL(bank), data);
  287 }
  288 
  289 static void
  290 bcm_gpio_set_pud(struct bcm_gpio_softc *sc, uint32_t pin, uint32_t state)
  291 {
  292         uint32_t bank;
  293 
  294         /* Must be called with lock held. */
  295         BCM_GPIO_LOCK_ASSERT(sc);
  296 
  297         bank = BCM_GPIO_BANK(pin);
  298         BCM_GPIO_WRITE(sc, BCM_GPIO_GPPUD(0), state);
  299         BCM_GPIO_WRITE(sc, BCM_GPIO_GPPUDCLK(bank), BCM_GPIO_MASK(pin));
  300         BCM_GPIO_WRITE(sc, BCM_GPIO_GPPUD(0), 0);
  301         BCM_GPIO_WRITE(sc, BCM_GPIO_GPPUDCLK(bank), 0);
  302 }
  303 
  304 static void
  305 bcm_gpio_set_alternate(device_t dev, uint32_t pin, uint32_t nfunc)
  306 {
  307         struct bcm_gpio_softc *sc;
  308         int i;
  309 
  310         sc = device_get_softc(dev);
  311         BCM_GPIO_LOCK(sc);
  312 
  313         /* Set the pin function. */
  314         bcm_gpio_set_function(sc, pin, nfunc);
  315 
  316         /* Update the pin flags. */
  317         for (i = 0; i < sc->sc_gpio_npins; i++) {
  318                 if (sc->sc_gpio_pins[i].gp_pin == pin)
  319                         break;
  320         }
  321         if (i < sc->sc_gpio_npins)
  322                 sc->sc_gpio_pins[i].gp_flags = bcm_gpio_func_flag(nfunc);
  323 
  324         BCM_GPIO_UNLOCK(sc);
  325 }
  326 
  327 static void
  328 bcm_gpio_pin_configure(struct bcm_gpio_softc *sc, struct gpio_pin *pin,
  329     unsigned int flags)
  330 {
  331 
  332         BCM_GPIO_LOCK(sc);
  333 
  334         /*
  335          * Manage input/output.
  336          */
  337         if (flags & (GPIO_PIN_INPUT|GPIO_PIN_OUTPUT)) {
  338                 pin->gp_flags &= ~(GPIO_PIN_INPUT|GPIO_PIN_OUTPUT);
  339                 if (flags & GPIO_PIN_OUTPUT) {
  340                         pin->gp_flags |= GPIO_PIN_OUTPUT;
  341                         bcm_gpio_set_function(sc, pin->gp_pin,
  342                             BCM2835_FSEL_GPIO_OUT);
  343                 } else {
  344                         pin->gp_flags |= GPIO_PIN_INPUT;
  345                         bcm_gpio_set_function(sc, pin->gp_pin,
  346                             BCM2835_FSEL_GPIO_IN);
  347                 }
  348         }
  349 
  350         /* Manage Pull-up/pull-down. */
  351         pin->gp_flags &= ~(GPIO_PIN_PULLUP|GPIO_PIN_PULLDOWN);
  352         if (flags & (GPIO_PIN_PULLUP|GPIO_PIN_PULLDOWN)) {
  353                 if (flags & GPIO_PIN_PULLUP) {
  354                         pin->gp_flags |= GPIO_PIN_PULLUP;
  355                         bcm_gpio_set_pud(sc, pin->gp_pin, BCM_GPIO_PULLUP);
  356                 } else {
  357                         pin->gp_flags |= GPIO_PIN_PULLDOWN;
  358                         bcm_gpio_set_pud(sc, pin->gp_pin, BCM_GPIO_PULLDOWN);
  359                 }
  360         } else 
  361                 bcm_gpio_set_pud(sc, pin->gp_pin, BCM_GPIO_NONE);
  362 
  363         BCM_GPIO_UNLOCK(sc);
  364 }
  365 
  366 static device_t
  367 bcm_gpio_get_bus(device_t dev)
  368 {
  369         struct bcm_gpio_softc *sc;
  370 
  371         sc = device_get_softc(dev);
  372 
  373         return (sc->sc_busdev);
  374 }
  375 
  376 static int
  377 bcm_gpio_pin_max(device_t dev, int *maxpin)
  378 {
  379 
  380         *maxpin = BCM_GPIO_PINS - 1;
  381         return (0);
  382 }
  383 
  384 static int
  385 bcm_gpio_pin_getcaps(device_t dev, uint32_t pin, uint32_t *caps)
  386 {
  387         struct bcm_gpio_softc *sc = device_get_softc(dev);
  388         int i;
  389 
  390         for (i = 0; i < sc->sc_gpio_npins; i++) {
  391                 if (sc->sc_gpio_pins[i].gp_pin == pin)
  392                         break;
  393         }
  394 
  395         if (i >= sc->sc_gpio_npins)
  396                 return (EINVAL);
  397 
  398         BCM_GPIO_LOCK(sc);
  399         *caps = sc->sc_gpio_pins[i].gp_caps;
  400         BCM_GPIO_UNLOCK(sc);
  401 
  402         return (0);
  403 }
  404 
  405 static int
  406 bcm_gpio_pin_getflags(device_t dev, uint32_t pin, uint32_t *flags)
  407 {
  408         struct bcm_gpio_softc *sc = device_get_softc(dev);
  409         int i;
  410 
  411         for (i = 0; i < sc->sc_gpio_npins; i++) {
  412                 if (sc->sc_gpio_pins[i].gp_pin == pin)
  413                         break;
  414         }
  415 
  416         if (i >= sc->sc_gpio_npins)
  417                 return (EINVAL);
  418 
  419         BCM_GPIO_LOCK(sc);
  420         *flags = sc->sc_gpio_pins[i].gp_flags;
  421         BCM_GPIO_UNLOCK(sc);
  422 
  423         return (0);
  424 }
  425 
  426 static int
  427 bcm_gpio_pin_getname(device_t dev, uint32_t pin, char *name)
  428 {
  429         struct bcm_gpio_softc *sc = device_get_softc(dev);
  430         int i;
  431 
  432         for (i = 0; i < sc->sc_gpio_npins; i++) {
  433                 if (sc->sc_gpio_pins[i].gp_pin == pin)
  434                         break;
  435         }
  436 
  437         if (i >= sc->sc_gpio_npins)
  438                 return (EINVAL);
  439 
  440         BCM_GPIO_LOCK(sc);
  441         memcpy(name, sc->sc_gpio_pins[i].gp_name, GPIOMAXNAME);
  442         BCM_GPIO_UNLOCK(sc);
  443 
  444         return (0);
  445 }
  446 
  447 static int
  448 bcm_gpio_pin_setflags(device_t dev, uint32_t pin, uint32_t flags)
  449 {
  450         struct bcm_gpio_softc *sc = device_get_softc(dev);
  451         int i;
  452 
  453         for (i = 0; i < sc->sc_gpio_npins; i++) {
  454                 if (sc->sc_gpio_pins[i].gp_pin == pin)
  455                         break;
  456         }
  457 
  458         if (i >= sc->sc_gpio_npins)
  459                 return (EINVAL);
  460 
  461         /* We never touch on read-only/reserved pins. */
  462         if (bcm_gpio_pin_is_ro(sc, pin))
  463                 return (EINVAL);
  464 
  465         bcm_gpio_pin_configure(sc, &sc->sc_gpio_pins[i], flags);
  466 
  467         return (0);
  468 }
  469 
  470 static int
  471 bcm_gpio_pin_set(device_t dev, uint32_t pin, unsigned int value)
  472 {
  473         struct bcm_gpio_softc *sc = device_get_softc(dev);
  474         uint32_t bank, reg;
  475         int i;
  476 
  477         for (i = 0; i < sc->sc_gpio_npins; i++) {
  478                 if (sc->sc_gpio_pins[i].gp_pin == pin)
  479                         break;
  480         }
  481         if (i >= sc->sc_gpio_npins)
  482                 return (EINVAL);
  483         /* We never write to read-only/reserved pins. */
  484         if (bcm_gpio_pin_is_ro(sc, pin))
  485                 return (EINVAL);
  486         BCM_GPIO_LOCK(sc);
  487         bank = BCM_GPIO_BANK(pin);
  488         if (value)
  489                 reg = BCM_GPIO_GPSET(bank);
  490         else
  491                 reg = BCM_GPIO_GPCLR(bank);
  492         BCM_GPIO_WRITE(sc, reg, BCM_GPIO_MASK(pin));
  493         BCM_GPIO_UNLOCK(sc);
  494 
  495         return (0);
  496 }
  497 
  498 static int
  499 bcm_gpio_pin_get(device_t dev, uint32_t pin, unsigned int *val)
  500 {
  501         struct bcm_gpio_softc *sc = device_get_softc(dev);
  502         uint32_t bank, reg_data;
  503         int i;
  504 
  505         for (i = 0; i < sc->sc_gpio_npins; i++) {
  506                 if (sc->sc_gpio_pins[i].gp_pin == pin)
  507                         break;
  508         }
  509         if (i >= sc->sc_gpio_npins)
  510                 return (EINVAL);
  511         bank = BCM_GPIO_BANK(pin);
  512         BCM_GPIO_LOCK(sc);
  513         reg_data = BCM_GPIO_READ(sc, BCM_GPIO_GPLEV(bank));
  514         BCM_GPIO_UNLOCK(sc);
  515         *val = (reg_data & BCM_GPIO_MASK(pin)) ? 1 : 0;
  516 
  517         return (0);
  518 }
  519 
  520 static int
  521 bcm_gpio_pin_toggle(device_t dev, uint32_t pin)
  522 {
  523         struct bcm_gpio_softc *sc = device_get_softc(dev);
  524         uint32_t bank, data, reg;
  525         int i;
  526 
  527         for (i = 0; i < sc->sc_gpio_npins; i++) {
  528                 if (sc->sc_gpio_pins[i].gp_pin == pin)
  529                         break;
  530         }
  531         if (i >= sc->sc_gpio_npins)
  532                 return (EINVAL);
  533         /* We never write to read-only/reserved pins. */
  534         if (bcm_gpio_pin_is_ro(sc, pin))
  535                 return (EINVAL);
  536         BCM_GPIO_LOCK(sc);
  537         bank = BCM_GPIO_BANK(pin);
  538         data = BCM_GPIO_READ(sc, BCM_GPIO_GPLEV(bank));
  539         if (data & BCM_GPIO_MASK(pin))
  540                 reg = BCM_GPIO_GPCLR(bank);
  541         else
  542                 reg = BCM_GPIO_GPSET(bank);
  543         BCM_GPIO_WRITE(sc, reg, BCM_GPIO_MASK(pin));
  544         BCM_GPIO_UNLOCK(sc);
  545 
  546         return (0);
  547 }
  548 
  549 static int
  550 bcm_gpio_func_proc(SYSCTL_HANDLER_ARGS)
  551 {
  552         char buf[16];
  553         struct bcm_gpio_softc *sc;
  554         struct bcm_gpio_sysctl *sc_sysctl;
  555         uint32_t nfunc;
  556         int error;
  557 
  558         sc_sysctl = arg1;
  559         sc = sc_sysctl->sc;
  560 
  561         /* Get the current pin function. */
  562         nfunc = bcm_gpio_get_function(sc, sc_sysctl->pin);
  563         bcm_gpio_func_str(nfunc, buf, sizeof(buf));
  564 
  565         error = sysctl_handle_string(oidp, buf, sizeof(buf), req);
  566         if (error != 0 || req->newptr == NULL)
  567                 return (error);
  568         /* Ignore changes on read-only pins. */
  569         if (bcm_gpio_pin_is_ro(sc, sc_sysctl->pin))
  570                 return (0);
  571         /* Parse the user supplied string and check for a valid pin function. */
  572         if (bcm_gpio_str_func(buf, &nfunc) != 0)
  573                 return (EINVAL);
  574 
  575         /* Update the pin alternate function. */
  576         bcm_gpio_set_alternate(sc->sc_dev, sc_sysctl->pin, nfunc);
  577 
  578         return (0);
  579 }
  580 
  581 static void
  582 bcm_gpio_sysctl_init(struct bcm_gpio_softc *sc)
  583 {
  584         char pinbuf[3];
  585         struct bcm_gpio_sysctl *sc_sysctl;
  586         struct sysctl_ctx_list *ctx;
  587         struct sysctl_oid *tree_node, *pin_node, *pinN_node;
  588         struct sysctl_oid_list *tree, *pin_tree, *pinN_tree;
  589         int i;
  590 
  591         /*
  592          * Add per-pin sysctl tree/handlers.
  593          */
  594         ctx = device_get_sysctl_ctx(sc->sc_dev);
  595         tree_node = device_get_sysctl_tree(sc->sc_dev);
  596         tree = SYSCTL_CHILDREN(tree_node);
  597         pin_node = SYSCTL_ADD_NODE(ctx, tree, OID_AUTO, "pin",
  598             CTLFLAG_RD | CTLFLAG_MPSAFE, NULL, "GPIO Pins");
  599         pin_tree = SYSCTL_CHILDREN(pin_node);
  600 
  601         for (i = 0; i < sc->sc_gpio_npins; i++) {
  602                 snprintf(pinbuf, sizeof(pinbuf), "%d", i);
  603                 pinN_node = SYSCTL_ADD_NODE(ctx, pin_tree, OID_AUTO, pinbuf,
  604                     CTLFLAG_RD | CTLFLAG_MPSAFE, NULL, "GPIO Pin");
  605                 pinN_tree = SYSCTL_CHILDREN(pinN_node);
  606 
  607                 sc->sc_sysctl[i].sc = sc;
  608                 sc_sysctl = &sc->sc_sysctl[i];
  609                 sc_sysctl->sc = sc;
  610                 sc_sysctl->pin = sc->sc_gpio_pins[i].gp_pin;
  611                 SYSCTL_ADD_PROC(ctx, pinN_tree, OID_AUTO, "function",
  612                     CTLFLAG_RW | CTLTYPE_STRING | CTLFLAG_NEEDGIANT, sc_sysctl,
  613                     sizeof(struct bcm_gpio_sysctl), bcm_gpio_func_proc,
  614                     "A", "Pin Function");
  615         }
  616 }
  617 
  618 static int
  619 bcm_gpio_get_ro_pins(struct bcm_gpio_softc *sc, phandle_t node,
  620         const char *propname, const char *label)
  621 {
  622         int i, need_comma, npins, range_start, range_stop;
  623         pcell_t *pins;
  624 
  625         /* Get the property data. */
  626         npins = OF_getencprop_alloc_multi(node, propname, sizeof(*pins),
  627             (void **)&pins);
  628         if (npins < 0)
  629                 return (-1);
  630         if (npins == 0) {
  631                 OF_prop_free(pins);
  632                 return (0);
  633         }
  634         for (i = 0; i < npins; i++)
  635                 sc->sc_ro_pins[i + sc->sc_ro_npins] = pins[i];
  636         sc->sc_ro_npins += npins;
  637         need_comma = 0;
  638         device_printf(sc->sc_dev, "%s pins: ", label);
  639         range_start = range_stop = pins[0];
  640         for (i = 1; i < npins; i++) {
  641                 if (pins[i] != range_stop + 1) {
  642                         if (need_comma)
  643                                 printf(",");
  644                         if (range_start != range_stop)
  645                                 printf("%d-%d", range_start, range_stop);
  646                         else
  647                                 printf("%d", range_start);
  648                         range_start = range_stop = pins[i];
  649                         need_comma = 1;
  650                 } else
  651                         range_stop++;
  652         }
  653         if (need_comma)
  654                 printf(",");
  655         if (range_start != range_stop)
  656                 printf("%d-%d.\n", range_start, range_stop);
  657         else
  658                 printf("%d.\n", range_start);
  659         OF_prop_free(pins);
  660 
  661         return (0);
  662 }
  663 
  664 static int
  665 bcm_gpio_get_reserved_pins(struct bcm_gpio_softc *sc)
  666 {
  667         char *name;
  668         phandle_t gpio, node, reserved;
  669         ssize_t len;
  670 
  671         /* Get read-only pins if they're provided */
  672         gpio = ofw_bus_get_node(sc->sc_dev);
  673         if (bcm_gpio_get_ro_pins(sc, gpio, "broadcom,read-only",
  674             "read-only") != 0)
  675                 return (0);
  676         /* Traverse the GPIO subnodes to find the reserved pins node. */
  677         reserved = 0;
  678         node = OF_child(gpio);
  679         while ((node != 0) && (reserved == 0)) {
  680                 len = OF_getprop_alloc(node, "name", (void **)&name);
  681                 if (len == -1)
  682                         return (-1);
  683                 if (strcmp(name, "reserved") == 0)
  684                         reserved = node;
  685                 OF_prop_free(name);
  686                 node = OF_peer(node);
  687         }
  688         if (reserved == 0)
  689                 return (-1);
  690         /* Get the reserved pins. */
  691         if (bcm_gpio_get_ro_pins(sc, reserved, "broadcom,pins",
  692             "reserved") != 0)
  693                 return (-1);
  694 
  695         return (0);
  696 }
  697 
  698 static int
  699 bcm_gpio_probe(device_t dev)
  700 {
  701 
  702         if (!ofw_bus_status_okay(dev))
  703                 return (ENXIO);
  704 
  705         if (ofw_bus_search_compatible(dev, compat_data)->ocd_data == 0)
  706                 return (ENXIO);
  707 
  708         device_set_desc(dev, "BCM2708/2835 GPIO controller");
  709         return (BUS_PROBE_DEFAULT);
  710 }
  711 
  712 static int
  713 bcm_gpio_intr_attach(device_t dev)
  714 {
  715         struct bcm_gpio_softc *sc;
  716 
  717         /*
  718          *  Only first two interrupt lines are used. Third line is
  719          *  mirrored second line and forth line is common for all banks.
  720          */
  721         sc = device_get_softc(dev);
  722         if (sc->sc_res[1] == NULL || sc->sc_res[2] == NULL)
  723                 return (-1);
  724 
  725         if (bcm_gpio_pic_attach(sc) != 0) {
  726                 device_printf(dev, "unable to attach PIC\n");
  727                 return (-1);
  728         }
  729         if (bus_setup_intr(dev, sc->sc_res[1], INTR_TYPE_MISC | INTR_MPSAFE,
  730             bcm_gpio_intr_bank0, NULL, sc, &sc->sc_intrhand[0]) != 0)
  731                 return (-1);
  732         if (bus_setup_intr(dev, sc->sc_res[2], INTR_TYPE_MISC | INTR_MPSAFE,
  733             bcm_gpio_intr_bank1, NULL, sc, &sc->sc_intrhand[1]) != 0)
  734                 return (-1);
  735 
  736         return (0);
  737 }
  738 
  739 static void
  740 bcm_gpio_intr_detach(device_t dev)
  741 {
  742         struct bcm_gpio_softc *sc;
  743 
  744         sc = device_get_softc(dev);
  745         if (sc->sc_intrhand[0] != NULL)
  746                 bus_teardown_intr(dev, sc->sc_res[1], sc->sc_intrhand[0]);
  747         if (sc->sc_intrhand[1] != NULL)
  748                 bus_teardown_intr(dev, sc->sc_res[2], sc->sc_intrhand[1]);
  749 
  750         bcm_gpio_pic_detach(sc);
  751 }
  752 
  753 static int
  754 bcm_gpio_attach(device_t dev)
  755 {
  756         int i, j;
  757         phandle_t gpio;
  758         struct bcm_gpio_softc *sc;
  759         uint32_t func;
  760 
  761         if (bcm_gpio_sc != NULL)
  762                 return (ENXIO);
  763 
  764         bcm_gpio_sc = sc = device_get_softc(dev);
  765         sc->sc_dev = dev;
  766         mtx_init(&sc->sc_mtx, "bcm gpio", "gpio", MTX_SPIN);
  767         if (bus_alloc_resources(dev, bcm_gpio_res_spec, sc->sc_res) != 0) {
  768                 device_printf(dev, "cannot allocate resources\n");
  769                 goto fail;
  770         }
  771         sc->sc_bst = rman_get_bustag(sc->sc_res[0]);
  772         sc->sc_bsh = rman_get_bushandle(sc->sc_res[0]);
  773         /* Setup the GPIO interrupt handler. */
  774         if (bcm_gpio_intr_attach(dev)) {
  775                 device_printf(dev, "unable to setup the gpio irq handler\n");
  776                 goto fail;
  777         }
  778         /* Find our node. */
  779         gpio = ofw_bus_get_node(sc->sc_dev);
  780         if (!OF_hasprop(gpio, "gpio-controller"))
  781                 /* Node is not a GPIO controller. */
  782                 goto fail;
  783         /*
  784          * Find the read-only pins.  These are pins we never touch or bad
  785          * things could happen.
  786          */
  787         if (bcm_gpio_get_reserved_pins(sc) == -1)
  788                 goto fail;
  789         /* Initialize the software controlled pins. */
  790         for (i = 0, j = 0; j < BCM_GPIO_PINS; j++) {
  791                 snprintf(sc->sc_gpio_pins[i].gp_name, GPIOMAXNAME,
  792                     "pin %d", j);
  793                 func = bcm_gpio_get_function(sc, j);
  794                 sc->sc_gpio_pins[i].gp_pin = j;
  795                 sc->sc_gpio_pins[i].gp_caps = BCM_GPIO_DEFAULT_CAPS;
  796                 sc->sc_gpio_pins[i].gp_flags = bcm_gpio_func_flag(func);
  797                 i++;
  798         }
  799         sc->sc_gpio_npins = i;
  800         bcm_gpio_sysctl_init(sc);
  801         sc->sc_busdev = gpiobus_attach_bus(dev);
  802         if (sc->sc_busdev == NULL)
  803                 goto fail;
  804 
  805         fdt_pinctrl_register(dev, "brcm,pins");
  806         fdt_pinctrl_configure_tree(dev);
  807 
  808         return (0);
  809 
  810 fail:
  811         bcm_gpio_intr_detach(dev);
  812         bus_release_resources(dev, bcm_gpio_res_spec, sc->sc_res);
  813         mtx_destroy(&sc->sc_mtx);
  814 
  815         return (ENXIO);
  816 }
  817 
  818 static int
  819 bcm_gpio_detach(device_t dev)
  820 {
  821 
  822         return (EBUSY);
  823 }
  824 
  825 static inline void
  826 bcm_gpio_modify(struct bcm_gpio_softc *sc, uint32_t reg, uint32_t mask,
  827     bool set_bits)
  828 {
  829 
  830         if (set_bits)
  831                 BCM_GPIO_SET_BITS(sc, reg, mask);
  832         else
  833                 BCM_GPIO_CLEAR_BITS(sc, reg, mask);
  834 }
  835 
  836 static inline void
  837 bcm_gpio_isrc_eoi(struct bcm_gpio_softc *sc, struct bcm_gpio_irqsrc *bgi)
  838 {
  839         uint32_t bank;
  840 
  841         /* Write 1 to clear. */
  842         bank = BCM_GPIO_BANK(bgi->bgi_irq);
  843         BCM_GPIO_WRITE(sc, BCM_GPIO_GPEDS(bank), bgi->bgi_mask);
  844 }
  845 
  846 static inline bool
  847 bcm_gpio_isrc_is_level(struct bcm_gpio_irqsrc *bgi)
  848 {
  849 
  850         return (bgi->bgi_mode ==  GPIO_INTR_LEVEL_LOW ||
  851             bgi->bgi_mode == GPIO_INTR_LEVEL_HIGH);
  852 }
  853 
  854 static inline void
  855 bcm_gpio_isrc_mask(struct bcm_gpio_softc *sc, struct bcm_gpio_irqsrc *bgi)
  856 {
  857         uint32_t bank;
  858 
  859         bank = BCM_GPIO_BANK(bgi->bgi_irq);
  860         BCM_GPIO_LOCK(sc);
  861         switch (bgi->bgi_mode) {
  862         case GPIO_INTR_LEVEL_LOW:
  863                 BCM_GPIO_CLEAR_BITS(sc, BCM_GPIO_GPLEN(bank), bgi->bgi_mask);
  864                 break;
  865         case GPIO_INTR_LEVEL_HIGH:
  866                 BCM_GPIO_CLEAR_BITS(sc, BCM_GPIO_GPHEN(bank), bgi->bgi_mask);
  867                 break;
  868         case GPIO_INTR_EDGE_RISING:
  869                 BCM_GPIO_CLEAR_BITS(sc, BCM_GPIO_GPREN(bank), bgi->bgi_mask);
  870                 break;
  871         case GPIO_INTR_EDGE_FALLING:
  872                 BCM_GPIO_CLEAR_BITS(sc, BCM_GPIO_GPFEN(bank), bgi->bgi_mask);
  873                 break;
  874         case GPIO_INTR_EDGE_BOTH:
  875                 BCM_GPIO_CLEAR_BITS(sc, BCM_GPIO_GPREN(bank), bgi->bgi_mask);
  876                 BCM_GPIO_CLEAR_BITS(sc, BCM_GPIO_GPFEN(bank), bgi->bgi_mask);
  877                 break;
  878         }
  879         BCM_GPIO_UNLOCK(sc);
  880 }
  881 
  882 static inline void
  883 bcm_gpio_isrc_unmask(struct bcm_gpio_softc *sc, struct bcm_gpio_irqsrc *bgi)
  884 {
  885         uint32_t bank;
  886 
  887         bank = BCM_GPIO_BANK(bgi->bgi_irq);
  888         BCM_GPIO_LOCK(sc);
  889         switch (bgi->bgi_mode) {
  890         case GPIO_INTR_LEVEL_LOW:
  891                 BCM_GPIO_SET_BITS(sc, BCM_GPIO_GPLEN(bank), bgi->bgi_mask);
  892                 break;
  893         case GPIO_INTR_LEVEL_HIGH:
  894                 BCM_GPIO_SET_BITS(sc, BCM_GPIO_GPHEN(bank), bgi->bgi_mask);
  895                 break;
  896         case GPIO_INTR_EDGE_RISING:
  897                 BCM_GPIO_SET_BITS(sc, BCM_GPIO_GPREN(bank), bgi->bgi_mask);
  898                 break;
  899         case GPIO_INTR_EDGE_FALLING:
  900                 BCM_GPIO_SET_BITS(sc, BCM_GPIO_GPFEN(bank), bgi->bgi_mask);
  901                 break;
  902         case GPIO_INTR_EDGE_BOTH:
  903                 BCM_GPIO_SET_BITS(sc, BCM_GPIO_GPREN(bank), bgi->bgi_mask);
  904                 BCM_GPIO_SET_BITS(sc, BCM_GPIO_GPFEN(bank), bgi->bgi_mask);
  905                 break;
  906         }
  907         BCM_GPIO_UNLOCK(sc);
  908 }
  909 
  910 static int
  911 bcm_gpio_intr_internal(struct bcm_gpio_softc *sc, uint32_t bank)
  912 {
  913         u_int irq;
  914         struct bcm_gpio_irqsrc *bgi;
  915         uint32_t reg;
  916 
  917         /* Do not care of spurious interrupt on GPIO. */
  918         reg = BCM_GPIO_READ(sc, BCM_GPIO_GPEDS(bank));
  919         while (reg != 0) {
  920                 irq = BCM_GPIO_PINS_PER_BANK * bank + ffs(reg) - 1;
  921                 bgi = sc->sc_isrcs + irq;
  922                 if (!bcm_gpio_isrc_is_level(bgi))
  923                         bcm_gpio_isrc_eoi(sc, bgi);
  924                 if (intr_isrc_dispatch(&bgi->bgi_isrc,
  925                     curthread->td_intr_frame) != 0) {
  926                         bcm_gpio_isrc_mask(sc, bgi);
  927                         if (bcm_gpio_isrc_is_level(bgi))
  928                                 bcm_gpio_isrc_eoi(sc, bgi);
  929                         device_printf(sc->sc_dev, "Stray irq %u disabled\n",
  930                             irq);
  931                 }
  932                 reg &= ~bgi->bgi_mask;
  933         }
  934         return (FILTER_HANDLED);
  935 }
  936 
  937 static int
  938 bcm_gpio_intr_bank0(void *arg)
  939 {
  940 
  941         return (bcm_gpio_intr_internal(arg, 0));
  942 }
  943 
  944 static int
  945 bcm_gpio_intr_bank1(void *arg)
  946 {
  947 
  948         return (bcm_gpio_intr_internal(arg, 1));
  949 }
  950 
  951 static int
  952 bcm_gpio_pic_attach(struct bcm_gpio_softc *sc)
  953 {
  954         int error;
  955         uint32_t irq;
  956         const char *name;
  957 
  958         name = device_get_nameunit(sc->sc_dev);
  959         for (irq = 0; irq < BCM_GPIO_PINS; irq++) {
  960                 sc->sc_isrcs[irq].bgi_irq = irq;
  961                 sc->sc_isrcs[irq].bgi_mask = BCM_GPIO_MASK(irq);
  962                 sc->sc_isrcs[irq].bgi_mode = GPIO_INTR_CONFORM;
  963 
  964                 error = intr_isrc_register(&sc->sc_isrcs[irq].bgi_isrc,
  965                     sc->sc_dev, 0, "%s,%u", name, irq);
  966                 if (error != 0)
  967                         return (error); /* XXX deregister ISRCs */
  968         }
  969         if (intr_pic_register(sc->sc_dev,
  970             OF_xref_from_node(ofw_bus_get_node(sc->sc_dev))) == NULL)
  971                 return (ENXIO);
  972 
  973         return (0);
  974 }
  975 
  976 static int
  977 bcm_gpio_pic_detach(struct bcm_gpio_softc *sc)
  978 {
  979 
  980         /*
  981          *  There has not been established any procedure yet
  982          *  how to detach PIC from living system correctly.
  983          */
  984         device_printf(sc->sc_dev, "%s: not implemented yet\n", __func__);
  985         return (EBUSY);
  986 }
  987 
  988 static void
  989 bcm_gpio_pic_config_intr(struct bcm_gpio_softc *sc, struct bcm_gpio_irqsrc *bgi,
  990     uint32_t mode)
  991 {
  992         uint32_t bank;
  993 
  994         bank = BCM_GPIO_BANK(bgi->bgi_irq);
  995         BCM_GPIO_LOCK(sc);
  996         bcm_gpio_modify(sc, BCM_GPIO_GPREN(bank), bgi->bgi_mask,
  997             mode == GPIO_INTR_EDGE_RISING || mode == GPIO_INTR_EDGE_BOTH);
  998         bcm_gpio_modify(sc, BCM_GPIO_GPFEN(bank), bgi->bgi_mask,
  999             mode == GPIO_INTR_EDGE_FALLING || mode == GPIO_INTR_EDGE_BOTH);
 1000         bcm_gpio_modify(sc, BCM_GPIO_GPHEN(bank), bgi->bgi_mask,
 1001             mode == GPIO_INTR_LEVEL_HIGH);
 1002         bcm_gpio_modify(sc, BCM_GPIO_GPLEN(bank), bgi->bgi_mask,
 1003             mode == GPIO_INTR_LEVEL_LOW);
 1004         bgi->bgi_mode = mode;
 1005         BCM_GPIO_UNLOCK(sc);
 1006 }
 1007 
 1008 static void
 1009 bcm_gpio_pic_disable_intr(device_t dev, struct intr_irqsrc *isrc)
 1010 {
 1011         struct bcm_gpio_softc *sc = device_get_softc(dev);
 1012         struct bcm_gpio_irqsrc *bgi = (struct bcm_gpio_irqsrc *)isrc;
 1013 
 1014         bcm_gpio_isrc_mask(sc, bgi);
 1015 }
 1016 
 1017 static void
 1018 bcm_gpio_pic_enable_intr(device_t dev, struct intr_irqsrc *isrc)
 1019 {
 1020         struct bcm_gpio_softc *sc = device_get_softc(dev);
 1021         struct bcm_gpio_irqsrc *bgi = (struct bcm_gpio_irqsrc *)isrc;
 1022 
 1023         arm_irq_memory_barrier(bgi->bgi_irq);
 1024         bcm_gpio_isrc_unmask(sc, bgi);
 1025 }
 1026 
 1027 static int
 1028 bcm_gpio_pic_map_fdt(struct bcm_gpio_softc *sc, struct intr_map_data_fdt *daf,
 1029     u_int *irqp, uint32_t *modep)
 1030 {
 1031         u_int irq;
 1032         uint32_t mode;
 1033 
 1034         /*
 1035          * The first cell is the interrupt number.
 1036          * The second cell is used to specify flags:
 1037          *      bits[3:0] trigger type and level flags:
 1038          *              1 = low-to-high edge triggered.
 1039          *              2 = high-to-low edge triggered.
 1040          *              4 = active high level-sensitive.
 1041          *              8 = active low level-sensitive.
 1042          */
 1043         if (daf->ncells != 2)
 1044                 return (EINVAL);
 1045 
 1046         irq = daf->cells[0];
 1047         if (irq >= BCM_GPIO_PINS || bcm_gpio_pin_is_ro(sc, irq))
 1048                 return (EINVAL);
 1049 
 1050         /* Only reasonable modes are supported. */
 1051         if (daf->cells[1] == 1)
 1052                 mode = GPIO_INTR_EDGE_RISING;
 1053         else if (daf->cells[1] == 2)
 1054                 mode = GPIO_INTR_EDGE_FALLING;
 1055         else if (daf->cells[1] == 3)
 1056                 mode = GPIO_INTR_EDGE_BOTH;
 1057         else if (daf->cells[1] == 4)
 1058                 mode = GPIO_INTR_LEVEL_HIGH;
 1059         else if (daf->cells[1] == 8)
 1060                 mode = GPIO_INTR_LEVEL_LOW;
 1061         else
 1062                 return (EINVAL);
 1063 
 1064         *irqp = irq;
 1065         if (modep != NULL)
 1066                 *modep = mode;
 1067         return (0);
 1068 }
 1069 
 1070 static int
 1071 bcm_gpio_pic_map_gpio(struct bcm_gpio_softc *sc, struct intr_map_data_gpio *dag,
 1072     u_int *irqp, uint32_t *modep)
 1073 {
 1074         u_int irq;
 1075         uint32_t mode;
 1076 
 1077         irq = dag->gpio_pin_num;
 1078         if (irq >= BCM_GPIO_PINS || bcm_gpio_pin_is_ro(sc, irq))
 1079                 return (EINVAL);
 1080 
 1081         mode = dag->gpio_intr_mode;
 1082         if (mode != GPIO_INTR_LEVEL_LOW && mode != GPIO_INTR_LEVEL_HIGH &&
 1083             mode != GPIO_INTR_EDGE_RISING && mode != GPIO_INTR_EDGE_FALLING &&
 1084             mode != GPIO_INTR_EDGE_BOTH)
 1085                 return (EINVAL);
 1086 
 1087         *irqp = irq;
 1088         if (modep != NULL)
 1089                 *modep = mode;
 1090         return (0);
 1091 }
 1092 
 1093 static int
 1094 bcm_gpio_pic_map(struct bcm_gpio_softc *sc, struct intr_map_data *data,
 1095     u_int *irqp, uint32_t *modep)
 1096 {
 1097 
 1098         switch (data->type) {
 1099         case INTR_MAP_DATA_FDT:
 1100                 return (bcm_gpio_pic_map_fdt(sc,
 1101                     (struct intr_map_data_fdt *)data, irqp, modep));
 1102         case INTR_MAP_DATA_GPIO:
 1103                 return (bcm_gpio_pic_map_gpio(sc,
 1104                     (struct intr_map_data_gpio *)data, irqp, modep));
 1105         default:
 1106                 return (ENOTSUP);
 1107         }
 1108 }
 1109 
 1110 static int
 1111 bcm_gpio_pic_map_intr(device_t dev, struct intr_map_data *data,
 1112     struct intr_irqsrc **isrcp)
 1113 {
 1114         int error;
 1115         u_int irq;
 1116         struct bcm_gpio_softc *sc = device_get_softc(dev);
 1117 
 1118         error = bcm_gpio_pic_map(sc, data, &irq, NULL);
 1119         if (error == 0)
 1120                 *isrcp = &sc->sc_isrcs[irq].bgi_isrc;
 1121         return (error);
 1122 }
 1123 
 1124 static void
 1125 bcm_gpio_pic_post_filter(device_t dev, struct intr_irqsrc *isrc)
 1126 {
 1127         struct bcm_gpio_softc *sc = device_get_softc(dev);
 1128         struct bcm_gpio_irqsrc *bgi = (struct bcm_gpio_irqsrc *)isrc;
 1129 
 1130         if (bcm_gpio_isrc_is_level(bgi))
 1131                 bcm_gpio_isrc_eoi(sc, bgi);
 1132 }
 1133 
 1134 static void
 1135 bcm_gpio_pic_post_ithread(device_t dev, struct intr_irqsrc *isrc)
 1136 {
 1137 
 1138         bcm_gpio_pic_enable_intr(dev, isrc);
 1139 }
 1140 
 1141 static void
 1142 bcm_gpio_pic_pre_ithread(device_t dev, struct intr_irqsrc *isrc)
 1143 {
 1144         struct bcm_gpio_softc *sc = device_get_softc(dev);
 1145         struct bcm_gpio_irqsrc *bgi = (struct bcm_gpio_irqsrc *)isrc;
 1146 
 1147         bcm_gpio_isrc_mask(sc, bgi);
 1148         if (bcm_gpio_isrc_is_level(bgi))
 1149                 bcm_gpio_isrc_eoi(sc, bgi);
 1150 }
 1151 
 1152 static int
 1153 bcm_gpio_pic_setup_intr(device_t dev, struct intr_irqsrc *isrc,
 1154     struct resource *res, struct intr_map_data *data)
 1155 {
 1156         u_int irq;
 1157         uint32_t mode;
 1158         struct bcm_gpio_softc *sc;
 1159         struct bcm_gpio_irqsrc *bgi;
 1160 
 1161         if (data == NULL)
 1162                 return (ENOTSUP);
 1163 
 1164         sc = device_get_softc(dev);
 1165         bgi = (struct bcm_gpio_irqsrc *)isrc;
 1166 
 1167         /* Get and check config for an interrupt. */
 1168         if (bcm_gpio_pic_map(sc, data, &irq, &mode) != 0 || bgi->bgi_irq != irq)
 1169                 return (EINVAL);
 1170 
 1171         /*
 1172          * If this is a setup for another handler,
 1173          * only check that its configuration match.
 1174          */
 1175         if (isrc->isrc_handlers != 0)
 1176                 return (bgi->bgi_mode == mode ? 0 : EINVAL);
 1177 
 1178         bcm_gpio_pic_config_intr(sc, bgi, mode);
 1179         return (0);
 1180 }
 1181 
 1182 static int
 1183 bcm_gpio_pic_teardown_intr(device_t dev, struct intr_irqsrc *isrc,
 1184     struct resource *res, struct intr_map_data *data)
 1185 {
 1186         struct bcm_gpio_softc *sc = device_get_softc(dev);
 1187         struct bcm_gpio_irqsrc *bgi = (struct bcm_gpio_irqsrc *)isrc;
 1188 
 1189         if (isrc->isrc_handlers == 0)
 1190                 bcm_gpio_pic_config_intr(sc, bgi, GPIO_INTR_CONFORM);
 1191         return (0);
 1192 }
 1193 
 1194 static phandle_t
 1195 bcm_gpio_get_node(device_t bus, device_t dev)
 1196 {
 1197 
 1198         /* We only have one child, the GPIO bus, which needs our own node. */
 1199         return (ofw_bus_get_node(bus));
 1200 }
 1201 
 1202 static int
 1203 bcm_gpio_configure_pins(device_t dev, phandle_t cfgxref)
 1204 {
 1205         phandle_t cfgnode;
 1206         int i, pintuples, pulltuples;
 1207         uint32_t pin;
 1208         uint32_t *pins;
 1209         uint32_t *pulls;
 1210         uint32_t function;
 1211 
 1212         cfgnode = OF_node_from_xref(cfgxref);
 1213 
 1214         pins = NULL;
 1215         pintuples = OF_getencprop_alloc_multi(cfgnode, "brcm,pins",
 1216             sizeof(*pins), (void **)&pins);
 1217 
 1218         char name[32];
 1219         OF_getprop(cfgnode, "name", &name, sizeof(name));
 1220 
 1221         if (pintuples < 0)
 1222                 return (ENOENT);
 1223 
 1224         if (pintuples == 0)
 1225                 return (0); /* Empty property is not an error. */
 1226 
 1227         if (OF_getencprop(cfgnode, "brcm,function", &function,
 1228             sizeof(function)) <= 0) {
 1229                 OF_prop_free(pins);
 1230                 return (EINVAL);
 1231         }
 1232 
 1233         pulls = NULL;
 1234         pulltuples = OF_getencprop_alloc_multi(cfgnode, "brcm,pull",
 1235             sizeof(*pulls), (void **)&pulls);
 1236 
 1237         if ((pulls != NULL) && (pulltuples != pintuples)) {
 1238                 OF_prop_free(pins);
 1239                 OF_prop_free(pulls);
 1240                 return (EINVAL);
 1241         }
 1242 
 1243         for (i = 0; i < pintuples; i++) {
 1244                 pin = pins[i];
 1245                 bcm_gpio_set_alternate(dev, pin, function);
 1246                 if (bootverbose)
 1247                         device_printf(dev, "set pin %d to func %d", pin, function);
 1248                 if (pulls) {
 1249                         if (bootverbose)
 1250                                 printf(", pull %d", pulls[i]);
 1251                         switch (pulls[i]) {
 1252                         /* Convert to gpio(4) flags */
 1253                         case BCM2835_PUD_OFF:
 1254                                 bcm_gpio_pin_setflags(dev, pin, 0);
 1255                                 break;
 1256                         case BCM2835_PUD_UP:
 1257                                 bcm_gpio_pin_setflags(dev, pin, GPIO_PIN_PULLUP);
 1258                                 break;
 1259                         case BCM2835_PUD_DOWN:
 1260                                 bcm_gpio_pin_setflags(dev, pin, GPIO_PIN_PULLDOWN);
 1261                                 break;
 1262                         default:
 1263                                 printf("%s: invalid pull value for pin %d: %d\n",
 1264                                     name, pin, pulls[i]);
 1265                         }
 1266                 }
 1267                 if (bootverbose)
 1268                         printf("\n");
 1269         }
 1270 
 1271         OF_prop_free(pins);
 1272         if (pulls)
 1273                 OF_prop_free(pulls);
 1274 
 1275         return (0);
 1276 }
 1277 
 1278 static device_method_t bcm_gpio_methods[] = {
 1279         /* Device interface */
 1280         DEVMETHOD(device_probe,         bcm_gpio_probe),
 1281         DEVMETHOD(device_attach,        bcm_gpio_attach),
 1282         DEVMETHOD(device_detach,        bcm_gpio_detach),
 1283 
 1284         /* GPIO protocol */
 1285         DEVMETHOD(gpio_get_bus,         bcm_gpio_get_bus),
 1286         DEVMETHOD(gpio_pin_max,         bcm_gpio_pin_max),
 1287         DEVMETHOD(gpio_pin_getname,     bcm_gpio_pin_getname),
 1288         DEVMETHOD(gpio_pin_getflags,    bcm_gpio_pin_getflags),
 1289         DEVMETHOD(gpio_pin_getcaps,     bcm_gpio_pin_getcaps),
 1290         DEVMETHOD(gpio_pin_setflags,    bcm_gpio_pin_setflags),
 1291         DEVMETHOD(gpio_pin_get,         bcm_gpio_pin_get),
 1292         DEVMETHOD(gpio_pin_set,         bcm_gpio_pin_set),
 1293         DEVMETHOD(gpio_pin_toggle,      bcm_gpio_pin_toggle),
 1294 
 1295         /* Interrupt controller interface */
 1296         DEVMETHOD(pic_disable_intr,     bcm_gpio_pic_disable_intr),
 1297         DEVMETHOD(pic_enable_intr,      bcm_gpio_pic_enable_intr),
 1298         DEVMETHOD(pic_map_intr,         bcm_gpio_pic_map_intr),
 1299         DEVMETHOD(pic_post_filter,      bcm_gpio_pic_post_filter),
 1300         DEVMETHOD(pic_post_ithread,     bcm_gpio_pic_post_ithread),
 1301         DEVMETHOD(pic_pre_ithread,      bcm_gpio_pic_pre_ithread),
 1302         DEVMETHOD(pic_setup_intr,       bcm_gpio_pic_setup_intr),
 1303         DEVMETHOD(pic_teardown_intr,    bcm_gpio_pic_teardown_intr),
 1304 
 1305         /* ofw_bus interface */
 1306         DEVMETHOD(ofw_bus_get_node,     bcm_gpio_get_node),
 1307 
 1308         /* fdt_pinctrl interface */
 1309         DEVMETHOD(fdt_pinctrl_configure, bcm_gpio_configure_pins),
 1310 
 1311         DEVMETHOD_END
 1312 };
 1313 
 1314 static driver_t bcm_gpio_driver = {
 1315         "gpio",
 1316         bcm_gpio_methods,
 1317         sizeof(struct bcm_gpio_softc),
 1318 };
 1319 
 1320 EARLY_DRIVER_MODULE(bcm_gpio, simplebus, bcm_gpio_driver, 0, 0,
 1321     BUS_PASS_INTERRUPT + BUS_PASS_ORDER_LATE);

Cache object: b9657790a43671564f577572aa93495f


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