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/allwinner/aw_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) 2013 Ganbold Tsagaankhuu <ganbold@freebsd.org>
    5  * Copyright (c) 2012 Oleksandr Tymoshenko <gonzo@freebsd.org>
    6  * Copyright (c) 2012 Luiz Otavio O Souza.
    7  * All rights reserved.
    8  *
    9  * Redistribution and use in source and binary forms, with or without
   10  * modification, are permitted provided that the following conditions
   11  * are met:
   12  * 1. Redistributions of source code must retain the above copyright
   13  *    notice, this list of conditions and the following disclaimer.
   14  * 2. Redistributions in binary form must reproduce the above copyright
   15  *    notice, this list of conditions and the following disclaimer in the
   16  *    documentation and/or other materials provided with the distribution.
   17  *
   18  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
   19  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   20  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   21  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
   22  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   23  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
   24  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   25  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   26  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
   27  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   28  * SUCH DAMAGE.
   29  *
   30  */
   31 #include <sys/cdefs.h>
   32 __FBSDID("$FreeBSD$");
   33 
   34 #include <sys/param.h>
   35 #include <sys/systm.h>
   36 #include <sys/bus.h>
   37 
   38 #include <sys/kernel.h>
   39 #include <sys/module.h>
   40 #include <sys/rman.h>
   41 #include <sys/lock.h>
   42 #include <sys/mutex.h>
   43 #include <sys/gpio.h>
   44 #include <sys/proc.h>
   45 
   46 #include <machine/bus.h>
   47 #include <machine/resource.h>
   48 #include <machine/intr.h>
   49 
   50 #include <dev/gpio/gpiobusvar.h>
   51 #include <dev/ofw/ofw_bus.h>
   52 #include <dev/ofw/ofw_bus_subr.h>
   53 #include <dev/fdt/fdt_pinctrl.h>
   54 
   55 #include <arm/allwinner/aw_machdep.h>
   56 #include <arm/allwinner/allwinner_pinctrl.h>
   57 #include <dev/extres/clk/clk.h>
   58 #include <dev/extres/hwreset/hwreset.h>
   59 #include <dev/extres/regulator/regulator.h>
   60 
   61 #if defined(__aarch64__)
   62 #include "opt_soc.h"
   63 #endif
   64 
   65 #include "pic_if.h"
   66 #include "gpio_if.h"
   67 
   68 #define AW_GPIO_DEFAULT_CAPS    (GPIO_PIN_INPUT | GPIO_PIN_OUTPUT |     \
   69           GPIO_PIN_PULLUP | GPIO_PIN_PULLDOWN);
   70 
   71 #define AW_GPIO_INTR_CAPS       (GPIO_INTR_LEVEL_LOW | GPIO_INTR_LEVEL_HIGH |   \
   72           GPIO_INTR_EDGE_RISING | GPIO_INTR_EDGE_FALLING | GPIO_INTR_EDGE_BOTH)
   73 
   74 #define AW_GPIO_NONE            0
   75 #define AW_GPIO_PULLUP          1
   76 #define AW_GPIO_PULLDOWN        2
   77 
   78 #define AW_GPIO_INPUT           0
   79 #define AW_GPIO_OUTPUT          1
   80 
   81 #define AW_GPIO_DRV_MASK        0x3
   82 #define AW_GPIO_PUD_MASK        0x3
   83 
   84 #define AW_PINCTRL      1
   85 #define AW_R_PINCTRL    2
   86 
   87 struct aw_gpio_conf {
   88         struct allwinner_padconf *padconf;
   89         const char *banks;
   90 };
   91 
   92 /* Defined in aw_padconf.c */
   93 #ifdef SOC_ALLWINNER_A10
   94 extern struct allwinner_padconf a10_padconf;
   95 struct aw_gpio_conf a10_gpio_conf = {
   96         .padconf = &a10_padconf,
   97         .banks = "abcdefghi",
   98 };
   99 #endif
  100 
  101 /* Defined in a13_padconf.c */
  102 #ifdef SOC_ALLWINNER_A13
  103 extern struct allwinner_padconf a13_padconf;
  104 struct aw_gpio_conf a13_gpio_conf = {
  105         .padconf = &a13_padconf,
  106         .banks = "bcdefg",
  107 };
  108 #endif
  109 
  110 /* Defined in a20_padconf.c */
  111 #ifdef SOC_ALLWINNER_A20
  112 extern struct allwinner_padconf a20_padconf;
  113 struct aw_gpio_conf a20_gpio_conf = {
  114         .padconf = &a20_padconf,
  115         .banks = "abcdefghi",
  116 };
  117 #endif
  118 
  119 /* Defined in a31_padconf.c */
  120 #ifdef SOC_ALLWINNER_A31
  121 extern struct allwinner_padconf a31_padconf;
  122 struct aw_gpio_conf a31_gpio_conf = {
  123         .padconf = &a31_padconf,
  124         .banks = "abcdefgh",
  125 };
  126 #endif
  127 
  128 /* Defined in a31s_padconf.c */
  129 #ifdef SOC_ALLWINNER_A31S
  130 extern struct allwinner_padconf a31s_padconf;
  131 struct aw_gpio_conf a31s_gpio_conf = {
  132         .padconf = &a31s_padconf,
  133         .banks = "abcdefgh",
  134 };
  135 #endif
  136 
  137 #if defined(SOC_ALLWINNER_A31) || defined(SOC_ALLWINNER_A31S)
  138 extern struct allwinner_padconf a31_r_padconf;
  139 struct aw_gpio_conf a31_r_gpio_conf = {
  140         .padconf = &a31_r_padconf,
  141         .banks = "lm",
  142 };
  143 #endif
  144 
  145 /* Defined in a33_padconf.c */
  146 #ifdef SOC_ALLWINNER_A33
  147 extern struct allwinner_padconf a33_padconf;
  148 struct aw_gpio_conf a33_gpio_conf = {
  149         .padconf = &a33_padconf,
  150         .banks = "bcdefgh",
  151 };
  152 #endif
  153 
  154 /* Defined in h3_padconf.c */
  155 #if defined(SOC_ALLWINNER_H3) || defined(SOC_ALLWINNER_H5)
  156 extern struct allwinner_padconf h3_padconf;
  157 extern struct allwinner_padconf h3_r_padconf;
  158 struct aw_gpio_conf h3_gpio_conf = {
  159         .padconf = &h3_padconf,
  160         .banks = "acdefg",
  161 };
  162 struct aw_gpio_conf h3_r_gpio_conf = {
  163         .padconf = &h3_r_padconf,
  164         .banks = "l",
  165 };
  166 #endif
  167 
  168 /* Defined in a83t_padconf.c */
  169 #ifdef SOC_ALLWINNER_A83T
  170 extern struct allwinner_padconf a83t_padconf;
  171 extern struct allwinner_padconf a83t_r_padconf;
  172 struct aw_gpio_conf a83t_gpio_conf = {
  173         .padconf = &a83t_padconf,
  174         .banks = "bcdefgh"
  175 };
  176 struct aw_gpio_conf a83t_r_gpio_conf = {
  177         .padconf = &a83t_r_padconf,
  178         .banks = "l",
  179 };
  180 #endif
  181 
  182 /* Defined in a64_padconf.c */
  183 #ifdef SOC_ALLWINNER_A64
  184 extern struct allwinner_padconf a64_padconf;
  185 extern struct allwinner_padconf a64_r_padconf;
  186 struct aw_gpio_conf a64_gpio_conf = {
  187         .padconf = &a64_padconf,
  188         .banks = "bcdefgh",
  189 };
  190 struct aw_gpio_conf a64_r_gpio_conf = {
  191         .padconf = &a64_r_padconf,
  192         .banks = "l",
  193 };
  194 #endif
  195 
  196 /* Defined in h6_padconf.c */
  197 #ifdef SOC_ALLWINNER_H6
  198 extern struct allwinner_padconf h6_padconf;
  199 extern struct allwinner_padconf h6_r_padconf;
  200 struct aw_gpio_conf h6_gpio_conf = {
  201         .padconf = &h6_padconf,
  202         .banks = "cdfgh",
  203 };
  204 struct aw_gpio_conf h6_r_gpio_conf = {
  205         .padconf = &h6_r_padconf,
  206         .banks = "lm",
  207 };
  208 #endif
  209 
  210 static struct ofw_compat_data compat_data[] = {
  211 #ifdef SOC_ALLWINNER_A10
  212         {"allwinner,sun4i-a10-pinctrl",         (uintptr_t)&a10_gpio_conf},
  213 #endif
  214 #ifdef SOC_ALLWINNER_A13
  215         {"allwinner,sun5i-a13-pinctrl",         (uintptr_t)&a13_gpio_conf},
  216 #endif
  217 #ifdef SOC_ALLWINNER_A20
  218         {"allwinner,sun7i-a20-pinctrl",         (uintptr_t)&a20_gpio_conf},
  219 #endif
  220 #ifdef SOC_ALLWINNER_A31
  221         {"allwinner,sun6i-a31-pinctrl",         (uintptr_t)&a31_gpio_conf},
  222 #endif
  223 #ifdef SOC_ALLWINNER_A31S
  224         {"allwinner,sun6i-a31s-pinctrl",        (uintptr_t)&a31s_gpio_conf},
  225 #endif
  226 #if defined(SOC_ALLWINNER_A31) || defined(SOC_ALLWINNER_A31S)
  227         {"allwinner,sun6i-a31-r-pinctrl",       (uintptr_t)&a31_r_gpio_conf},
  228 #endif
  229 #ifdef SOC_ALLWINNER_A33
  230         {"allwinner,sun6i-a33-pinctrl",         (uintptr_t)&a33_gpio_conf},
  231 #endif
  232 #ifdef SOC_ALLWINNER_A83T
  233         {"allwinner,sun8i-a83t-pinctrl",        (uintptr_t)&a83t_gpio_conf},
  234         {"allwinner,sun8i-a83t-r-pinctrl",      (uintptr_t)&a83t_r_gpio_conf},
  235 #endif
  236 #if defined(SOC_ALLWINNER_H3) || defined(SOC_ALLWINNER_H5)
  237         {"allwinner,sun8i-h3-pinctrl",          (uintptr_t)&h3_gpio_conf},
  238         {"allwinner,sun50i-h5-pinctrl",         (uintptr_t)&h3_gpio_conf},
  239         {"allwinner,sun8i-h3-r-pinctrl",        (uintptr_t)&h3_r_gpio_conf},
  240 #endif
  241 #ifdef SOC_ALLWINNER_A64
  242         {"allwinner,sun50i-a64-pinctrl",        (uintptr_t)&a64_gpio_conf},
  243         {"allwinner,sun50i-a64-r-pinctrl",      (uintptr_t)&a64_r_gpio_conf},
  244 #endif
  245 #ifdef SOC_ALLWINNER_H6
  246         {"allwinner,sun50i-h6-pinctrl", (uintptr_t)&h6_gpio_conf},
  247         {"allwinner,sun50i-h6-r-pinctrl",       (uintptr_t)&h6_r_gpio_conf},
  248 #endif
  249         {NULL,  0}
  250 };
  251 
  252 struct clk_list {
  253         TAILQ_ENTRY(clk_list)   next;
  254         clk_t                   clk;
  255 };
  256 
  257 struct gpio_irqsrc {
  258         struct intr_irqsrc      isrc;
  259         u_int                   irq;
  260         uint32_t                mode;
  261         uint32_t                pin;
  262         uint32_t                bank;
  263         uint32_t                intnum;
  264         uint32_t                intfunc;
  265         uint32_t                oldfunc;
  266         bool                    enabled;
  267 };
  268 
  269 #define AW_GPIO_MEMRES          0
  270 #define AW_GPIO_IRQRES          1
  271 #define AW_GPIO_RESSZ           2
  272 
  273 struct aw_gpio_softc {
  274         device_t                sc_dev;
  275         device_t                sc_busdev;
  276         struct resource *       sc_res[AW_GPIO_RESSZ];
  277         struct mtx              sc_mtx;
  278         struct resource *       sc_mem_res;
  279         struct resource *       sc_irq_res;
  280         void *                  sc_intrhand;
  281         struct aw_gpio_conf     *conf;
  282         TAILQ_HEAD(, clk_list)          clk_list;
  283 
  284         struct gpio_irqsrc      *gpio_pic_irqsrc;
  285         int                     nirqs;
  286 };
  287 
  288 static struct resource_spec aw_gpio_res_spec[] = {
  289         { SYS_RES_MEMORY,       0,      RF_ACTIVE },
  290         { SYS_RES_IRQ,          0,      RF_ACTIVE | RF_SHAREABLE },
  291         { -1,                   0,      0 }
  292 };
  293 
  294 #define AW_GPIO_LOCK(_sc)               mtx_lock_spin(&(_sc)->sc_mtx)
  295 #define AW_GPIO_UNLOCK(_sc)             mtx_unlock_spin(&(_sc)->sc_mtx)
  296 #define AW_GPIO_LOCK_ASSERT(_sc)        mtx_assert(&(_sc)->sc_mtx, MA_OWNED)
  297 
  298 #define AW_GPIO_GP_CFG(_bank, _idx)     0x00 + ((_bank) * 0x24) + ((_idx) << 2)
  299 #define AW_GPIO_GP_DAT(_bank)           0x10 + ((_bank) * 0x24)
  300 #define AW_GPIO_GP_DRV(_bank, _idx)     0x14 + ((_bank) * 0x24) + ((_idx) << 2)
  301 #define AW_GPIO_GP_PUL(_bank, _idx)     0x1c + ((_bank) * 0x24) + ((_idx) << 2)
  302 
  303 #define AW_GPIO_GP_INT_BASE(_bank)      (0x200 + 0x20 * _bank)
  304 
  305 #define AW_GPIO_GP_INT_CFG(_bank, _pin) (AW_GPIO_GP_INT_BASE(_bank) + (0x4 * ((_pin) / 8)))
  306 #define AW_GPIO_GP_INT_CTL(_bank)       (AW_GPIO_GP_INT_BASE(_bank) + 0x10)
  307 #define AW_GPIO_GP_INT_STA(_bank)       (AW_GPIO_GP_INT_BASE(_bank) + 0x14)
  308 #define AW_GPIO_GP_INT_DEB(_bank)       (AW_GPIO_GP_INT_BASE(_bank) + 0x18)
  309 
  310 #define AW_GPIO_INT_EDGE_POSITIVE       0x0
  311 #define AW_GPIO_INT_EDGE_NEGATIVE       0x1
  312 #define AW_GPIO_INT_LEVEL_HIGH          0x2
  313 #define AW_GPIO_INT_LEVEL_LOW           0x3
  314 #define AW_GPIO_INT_EDGE_BOTH           0x4
  315 
  316 static char *aw_gpio_parse_function(phandle_t node);
  317 static const char **aw_gpio_parse_pins(phandle_t node, int *pins_nb);
  318 static uint32_t aw_gpio_parse_bias(phandle_t node);
  319 static int aw_gpio_parse_drive_strength(phandle_t node, uint32_t *drive);
  320 
  321 static int aw_gpio_pin_get(device_t dev, uint32_t pin, unsigned int *value);
  322 static int aw_gpio_pin_set(device_t dev, uint32_t pin, unsigned int value);
  323 static int aw_gpio_pin_get_locked(struct aw_gpio_softc *sc, uint32_t pin, unsigned int *value);
  324 static int aw_gpio_pin_set_locked(struct aw_gpio_softc *sc, uint32_t pin, unsigned int value);
  325 
  326 static void aw_gpio_intr(void *arg);
  327 static void aw_gpio_pic_disable_intr(device_t dev, struct intr_irqsrc *isrc);
  328 static void aw_gpio_pic_disable_intr_locked(struct aw_gpio_softc *sc, struct intr_irqsrc *isrc);
  329 static void aw_gpio_pic_post_filter(device_t dev, struct intr_irqsrc *isrc);
  330 static int aw_gpio_register_isrcs(struct aw_gpio_softc *sc);
  331 
  332 #define AW_GPIO_WRITE(_sc, _off, _val)          \
  333         bus_write_4((_sc)->sc_res[AW_GPIO_MEMRES], _off, _val)
  334 #define AW_GPIO_READ(_sc, _off)         \
  335         bus_read_4((_sc)->sc_res[AW_GPIO_MEMRES], _off)
  336 
  337 static uint32_t
  338 aw_gpio_get_function(struct aw_gpio_softc *sc, uint32_t pin)
  339 {
  340         uint32_t bank, func, offset;
  341 
  342         /* Must be called with lock held. */
  343         AW_GPIO_LOCK_ASSERT(sc);
  344 
  345         if (pin > sc->conf->padconf->npins)
  346                 return (0);
  347         bank = sc->conf->padconf->pins[pin].port;
  348         pin = sc->conf->padconf->pins[pin].pin;
  349         offset = ((pin & 0x07) << 2);
  350 
  351         func = AW_GPIO_READ(sc, AW_GPIO_GP_CFG(bank, pin >> 3));
  352 
  353         return ((func >> offset) & 0x7);
  354 }
  355 
  356 static int
  357 aw_gpio_set_function(struct aw_gpio_softc *sc, uint32_t pin, uint32_t f)
  358 {
  359         uint32_t bank, data, offset;
  360 
  361         /* Check if the function exists in the padconf data */
  362         if (sc->conf->padconf->pins[pin].functions[f] == NULL)
  363                 return (EINVAL);
  364 
  365         /* Must be called with lock held. */
  366         AW_GPIO_LOCK_ASSERT(sc);
  367 
  368         bank = sc->conf->padconf->pins[pin].port;
  369         pin = sc->conf->padconf->pins[pin].pin;
  370         offset = ((pin & 0x07) << 2);
  371 
  372         data = AW_GPIO_READ(sc, AW_GPIO_GP_CFG(bank, pin >> 3));
  373         data &= ~(7 << offset);
  374         data |= (f << offset);
  375         AW_GPIO_WRITE(sc, AW_GPIO_GP_CFG(bank, pin >> 3), data);
  376 
  377         return (0);
  378 }
  379 
  380 static uint32_t
  381 aw_gpio_get_pud(struct aw_gpio_softc *sc, uint32_t pin)
  382 {
  383         uint32_t bank, offset, val;
  384 
  385         /* Must be called with lock held. */
  386         AW_GPIO_LOCK_ASSERT(sc);
  387 
  388         bank = sc->conf->padconf->pins[pin].port;
  389         pin = sc->conf->padconf->pins[pin].pin;
  390         offset = ((pin & 0x0f) << 1);
  391 
  392         val = AW_GPIO_READ(sc, AW_GPIO_GP_PUL(bank, pin >> 4));
  393 
  394         return ((val >> offset) & AW_GPIO_PUD_MASK);
  395 }
  396 
  397 static void
  398 aw_gpio_set_pud(struct aw_gpio_softc *sc, uint32_t pin, uint32_t state)
  399 {
  400         uint32_t bank, offset, val;
  401 
  402         if (aw_gpio_get_pud(sc, pin) == state)
  403                 return;
  404 
  405         /* Must be called with lock held. */
  406         AW_GPIO_LOCK_ASSERT(sc);
  407 
  408         bank = sc->conf->padconf->pins[pin].port;
  409         pin = sc->conf->padconf->pins[pin].pin;
  410         offset = ((pin & 0x0f) << 1);
  411 
  412         val = AW_GPIO_READ(sc, AW_GPIO_GP_PUL(bank, pin >> 4));
  413         val &= ~(AW_GPIO_PUD_MASK << offset);
  414         val |= (state << offset);
  415         AW_GPIO_WRITE(sc, AW_GPIO_GP_PUL(bank, pin >> 4), val);
  416 }
  417 
  418 static uint32_t
  419 aw_gpio_get_drv(struct aw_gpio_softc *sc, uint32_t pin)
  420 {
  421         uint32_t bank, offset, val;
  422 
  423         /* Must be called with lock held. */
  424         AW_GPIO_LOCK_ASSERT(sc);
  425 
  426         bank = sc->conf->padconf->pins[pin].port;
  427         pin = sc->conf->padconf->pins[pin].pin;
  428         offset = ((pin & 0x0f) << 1);
  429 
  430         val = AW_GPIO_READ(sc, AW_GPIO_GP_DRV(bank, pin >> 4));
  431 
  432         return ((val >> offset) & AW_GPIO_DRV_MASK);
  433 }
  434 
  435 static void
  436 aw_gpio_set_drv(struct aw_gpio_softc *sc, uint32_t pin, uint32_t drive)
  437 {
  438         uint32_t bank, offset, val;
  439 
  440         if (aw_gpio_get_drv(sc, pin) == drive)
  441                 return;
  442 
  443         /* Must be called with lock held. */
  444         AW_GPIO_LOCK_ASSERT(sc);
  445 
  446         bank = sc->conf->padconf->pins[pin].port;
  447         pin = sc->conf->padconf->pins[pin].pin;
  448         offset = ((pin & 0x0f) << 1);
  449 
  450         val = AW_GPIO_READ(sc, AW_GPIO_GP_DRV(bank, pin >> 4));
  451         val &= ~(AW_GPIO_DRV_MASK << offset);
  452         val |= (drive << offset);
  453         AW_GPIO_WRITE(sc, AW_GPIO_GP_DRV(bank, pin >> 4), val);
  454 }
  455 
  456 static int
  457 aw_gpio_pin_configure(struct aw_gpio_softc *sc, uint32_t pin, uint32_t flags)
  458 {
  459         u_int val;
  460         int err = 0;
  461 
  462         /* Must be called with lock held. */
  463         AW_GPIO_LOCK_ASSERT(sc);
  464 
  465         if (pin > sc->conf->padconf->npins)
  466                 return (EINVAL);
  467 
  468         /* Manage input/output. */
  469         if (flags & GPIO_PIN_INPUT) {
  470                 err = aw_gpio_set_function(sc, pin, AW_GPIO_INPUT);
  471         } else if ((flags & GPIO_PIN_OUTPUT) &&
  472             aw_gpio_get_function(sc, pin) != AW_GPIO_OUTPUT) {
  473                 if (flags & GPIO_PIN_PRESET_LOW) {
  474                         aw_gpio_pin_set_locked(sc, pin, 0);
  475                 } else if (flags & GPIO_PIN_PRESET_HIGH) {
  476                         aw_gpio_pin_set_locked(sc, pin, 1);
  477                 } else {
  478                         /* Read the pin and preset output to current state. */
  479                         err = aw_gpio_set_function(sc, pin, AW_GPIO_INPUT);
  480                         if (err == 0) {
  481                                 aw_gpio_pin_get_locked(sc, pin, &val);
  482                                 aw_gpio_pin_set_locked(sc, pin, val);
  483                         }
  484                 }
  485                 if (err == 0)
  486                         err = aw_gpio_set_function(sc, pin, AW_GPIO_OUTPUT);
  487         }
  488 
  489         if (err)
  490                 return (err);
  491 
  492         /* Manage Pull-up/pull-down. */
  493         if (flags & GPIO_PIN_PULLUP)
  494                 aw_gpio_set_pud(sc, pin, AW_GPIO_PULLUP);
  495         else if (flags & GPIO_PIN_PULLDOWN)
  496                 aw_gpio_set_pud(sc, pin, AW_GPIO_PULLDOWN);
  497         else
  498                 aw_gpio_set_pud(sc, pin, AW_GPIO_NONE);
  499 
  500         return (0);
  501 }
  502 
  503 static device_t
  504 aw_gpio_get_bus(device_t dev)
  505 {
  506         struct aw_gpio_softc *sc;
  507 
  508         sc = device_get_softc(dev);
  509 
  510         return (sc->sc_busdev);
  511 }
  512 
  513 static int
  514 aw_gpio_pin_max(device_t dev, int *maxpin)
  515 {
  516         struct aw_gpio_softc *sc;
  517 
  518         sc = device_get_softc(dev);
  519 
  520         *maxpin = sc->conf->padconf->npins - 1;
  521         return (0);
  522 }
  523 
  524 static int
  525 aw_gpio_pin_getcaps(device_t dev, uint32_t pin, uint32_t *caps)
  526 {
  527         struct aw_gpio_softc *sc;
  528 
  529         sc = device_get_softc(dev);
  530         if (pin >= sc->conf->padconf->npins)
  531                 return (EINVAL);
  532 
  533         *caps = AW_GPIO_DEFAULT_CAPS;
  534         if (sc->conf->padconf->pins[pin].eint_func != 0)
  535                 *caps |= AW_GPIO_INTR_CAPS;
  536 
  537         return (0);
  538 }
  539 
  540 static int
  541 aw_gpio_pin_getflags(device_t dev, uint32_t pin, uint32_t *flags)
  542 {
  543         struct aw_gpio_softc *sc;
  544         uint32_t func;
  545         uint32_t pud;
  546 
  547         sc = device_get_softc(dev);
  548         if (pin >= sc->conf->padconf->npins)
  549                 return (EINVAL);
  550 
  551         AW_GPIO_LOCK(sc);
  552         func = aw_gpio_get_function(sc, pin);
  553         switch (func) {
  554         case AW_GPIO_INPUT:
  555                 *flags = GPIO_PIN_INPUT;
  556                 break;
  557         case AW_GPIO_OUTPUT:
  558                 *flags = GPIO_PIN_OUTPUT;
  559                 break;
  560         default:
  561                 *flags = 0;
  562                 break;
  563         }
  564 
  565         pud = aw_gpio_get_pud(sc, pin);
  566         switch (pud) {
  567         case AW_GPIO_PULLDOWN:
  568                 *flags |= GPIO_PIN_PULLDOWN;
  569                 break;
  570         case AW_GPIO_PULLUP:
  571                 *flags |= GPIO_PIN_PULLUP;
  572                 break;
  573         default:
  574                 break;
  575         }
  576 
  577         AW_GPIO_UNLOCK(sc);
  578 
  579         return (0);
  580 }
  581 
  582 static int
  583 aw_gpio_pin_getname(device_t dev, uint32_t pin, char *name)
  584 {
  585         struct aw_gpio_softc *sc;
  586 
  587         sc = device_get_softc(dev);
  588         if (pin >= sc->conf->padconf->npins)
  589                 return (EINVAL);
  590 
  591         snprintf(name, GPIOMAXNAME - 1, "%s",
  592             sc->conf->padconf->pins[pin].name);
  593         name[GPIOMAXNAME - 1] = '\0';
  594 
  595         return (0);
  596 }
  597 
  598 static int
  599 aw_gpio_pin_setflags(device_t dev, uint32_t pin, uint32_t flags)
  600 {
  601         struct aw_gpio_softc *sc;
  602         int err;
  603 
  604         sc = device_get_softc(dev);
  605         if (pin > sc->conf->padconf->npins)
  606                 return (EINVAL);
  607 
  608         AW_GPIO_LOCK(sc);
  609         err = aw_gpio_pin_configure(sc, pin, flags);
  610         AW_GPIO_UNLOCK(sc);
  611 
  612         return (err);
  613 }
  614 
  615 static int
  616 aw_gpio_pin_set_locked(struct aw_gpio_softc *sc, uint32_t pin,
  617     unsigned int value)
  618 {
  619         uint32_t bank, data;
  620 
  621         AW_GPIO_LOCK_ASSERT(sc);
  622 
  623         if (pin > sc->conf->padconf->npins)
  624                 return (EINVAL);
  625 
  626         bank = sc->conf->padconf->pins[pin].port;
  627         pin = sc->conf->padconf->pins[pin].pin;
  628 
  629         data = AW_GPIO_READ(sc, AW_GPIO_GP_DAT(bank));
  630         if (value)
  631                 data |= (1 << pin);
  632         else
  633                 data &= ~(1 << pin);
  634         AW_GPIO_WRITE(sc, AW_GPIO_GP_DAT(bank), data);
  635 
  636         return (0);
  637 }
  638 
  639 static int
  640 aw_gpio_pin_set(device_t dev, uint32_t pin, unsigned int value)
  641 {
  642         struct aw_gpio_softc *sc;
  643         int ret;
  644 
  645         sc = device_get_softc(dev);
  646 
  647         AW_GPIO_LOCK(sc);
  648         ret = aw_gpio_pin_set_locked(sc, pin, value);
  649         AW_GPIO_UNLOCK(sc);
  650 
  651         return (ret);
  652 }
  653 
  654 static int
  655 aw_gpio_pin_get_locked(struct aw_gpio_softc *sc,uint32_t pin,
  656     unsigned int *val)
  657 {
  658         uint32_t bank, reg_data;
  659 
  660         AW_GPIO_LOCK_ASSERT(sc);
  661 
  662         if (pin > sc->conf->padconf->npins)
  663                 return (EINVAL);
  664 
  665         bank = sc->conf->padconf->pins[pin].port;
  666         pin = sc->conf->padconf->pins[pin].pin;
  667 
  668         reg_data = AW_GPIO_READ(sc, AW_GPIO_GP_DAT(bank));
  669         *val = (reg_data & (1 << pin)) ? 1 : 0;
  670 
  671         return (0);
  672 }
  673 
  674 static char *
  675 aw_gpio_parse_function(phandle_t node)
  676 {
  677         char *function;
  678 
  679         if (OF_getprop_alloc(node, "function",
  680             (void **)&function) != -1)
  681                 return (function);
  682         if (OF_getprop_alloc(node, "allwinner,function",
  683             (void **)&function) != -1)
  684                 return (function);
  685 
  686         return (NULL);
  687 }
  688 
  689 static const char **
  690 aw_gpio_parse_pins(phandle_t node, int *pins_nb)
  691 {
  692         const char **pinlist;
  693 
  694         *pins_nb = ofw_bus_string_list_to_array(node, "pins", &pinlist);
  695         if (*pins_nb > 0)
  696                 return (pinlist);
  697 
  698         *pins_nb = ofw_bus_string_list_to_array(node, "allwinner,pins",
  699             &pinlist);
  700         if (*pins_nb > 0)
  701                 return (pinlist);
  702 
  703         return (NULL);
  704 }
  705 
  706 static uint32_t
  707 aw_gpio_parse_bias(phandle_t node)
  708 {
  709         uint32_t bias;
  710 
  711         if (OF_getencprop(node, "pull", &bias, sizeof(bias)) != -1)
  712                 return (bias);
  713         if (OF_getencprop(node, "allwinner,pull", &bias, sizeof(bias)) != -1)
  714                 return (bias);
  715         if (OF_hasprop(node, "bias-disable"))
  716                 return (AW_GPIO_NONE);
  717         if (OF_hasprop(node, "bias-pull-up"))
  718                 return (AW_GPIO_PULLUP);
  719         if (OF_hasprop(node, "bias-pull-down"))
  720                 return (AW_GPIO_PULLDOWN);
  721 
  722         return (AW_GPIO_NONE);
  723 }
  724 
  725 static int
  726 aw_gpio_parse_drive_strength(phandle_t node, uint32_t *drive)
  727 {
  728         uint32_t drive_str;
  729 
  730         if (OF_getencprop(node, "drive", drive, sizeof(*drive)) != -1)
  731                 return (0);
  732         if (OF_getencprop(node, "allwinner,drive", drive, sizeof(*drive)) != -1)
  733                 return (0);
  734         if (OF_getencprop(node, "drive-strength", &drive_str,
  735             sizeof(drive_str)) != -1) {
  736                 *drive = (drive_str / 10) - 1;
  737                 return (0);
  738         }
  739 
  740         return (1);
  741 }
  742 
  743 static int
  744 aw_gpio_pin_get(device_t dev, uint32_t pin, unsigned int *val)
  745 {
  746         struct aw_gpio_softc *sc;
  747         int ret;
  748 
  749         sc = device_get_softc(dev);
  750 
  751         AW_GPIO_LOCK(sc);
  752         ret = aw_gpio_pin_get_locked(sc, pin, val);
  753         AW_GPIO_UNLOCK(sc);
  754 
  755         return (ret);
  756 }
  757 
  758 static int
  759 aw_gpio_pin_toggle(device_t dev, uint32_t pin)
  760 {
  761         struct aw_gpio_softc *sc;
  762         uint32_t bank, data;
  763 
  764         sc = device_get_softc(dev);
  765         if (pin > sc->conf->padconf->npins)
  766                 return (EINVAL);
  767 
  768         bank = sc->conf->padconf->pins[pin].port;
  769         pin = sc->conf->padconf->pins[pin].pin;
  770 
  771         AW_GPIO_LOCK(sc);
  772         data = AW_GPIO_READ(sc, AW_GPIO_GP_DAT(bank));
  773         if (data & (1 << pin))
  774                 data &= ~(1 << pin);
  775         else
  776                 data |= (1 << pin);
  777         AW_GPIO_WRITE(sc, AW_GPIO_GP_DAT(bank), data);
  778         AW_GPIO_UNLOCK(sc);
  779 
  780         return (0);
  781 }
  782 
  783 static int
  784 aw_gpio_pin_access_32(device_t dev, uint32_t first_pin, uint32_t clear_pins,
  785     uint32_t change_pins, uint32_t *orig_pins)
  786 {
  787         struct aw_gpio_softc *sc;
  788         uint32_t bank, data, pin;
  789 
  790         sc = device_get_softc(dev);
  791         if (first_pin > sc->conf->padconf->npins)
  792                 return (EINVAL);
  793 
  794         /*
  795          * We require that first_pin refers to the first pin in a bank, because
  796          * this API is not about convenience, it's for making a set of pins
  797          * change simultaneously (required) with reasonably high performance
  798          * (desired); we need to do a read-modify-write on a single register.
  799          */
  800         bank = sc->conf->padconf->pins[first_pin].port;
  801         pin = sc->conf->padconf->pins[first_pin].pin;
  802         if (pin != 0)
  803                 return (EINVAL);
  804 
  805         AW_GPIO_LOCK(sc);
  806         data = AW_GPIO_READ(sc, AW_GPIO_GP_DAT(bank));
  807         if ((clear_pins | change_pins) != 0) 
  808                 AW_GPIO_WRITE(sc, AW_GPIO_GP_DAT(bank),
  809                     (data & ~clear_pins) ^ change_pins);
  810         AW_GPIO_UNLOCK(sc);
  811 
  812         if (orig_pins != NULL)
  813                 *orig_pins = data;
  814 
  815         return (0);
  816 }
  817 
  818 static int
  819 aw_gpio_pin_config_32(device_t dev, uint32_t first_pin, uint32_t num_pins,
  820     uint32_t *pin_flags)
  821 {
  822         struct aw_gpio_softc *sc;
  823         uint32_t bank, pin;
  824         int err;
  825 
  826         sc = device_get_softc(dev);
  827         if (first_pin > sc->conf->padconf->npins)
  828                 return (EINVAL);
  829 
  830         bank = sc->conf->padconf->pins[first_pin].port;
  831         if (sc->conf->padconf->pins[first_pin].pin != 0)
  832                 return (EINVAL);
  833 
  834         /*
  835          * The configuration for a bank of pins is scattered among several
  836          * registers; we cannot g'tee to simultaneously change the state of all
  837          * the pins in the flags array.  So just loop through the array
  838          * configuring each pin for now.  If there was a strong need, it might
  839          * be possible to support some limited simultaneous config, such as
  840          * adjacent groups of 8 pins that line up the same as the config regs.
  841          */
  842         for (err = 0, pin = first_pin; err == 0 && pin < num_pins; ++pin) {
  843                 if (pin_flags[pin] & (GPIO_PIN_INPUT | GPIO_PIN_OUTPUT))
  844                         err = aw_gpio_pin_configure(sc, pin, pin_flags[pin]);
  845         }
  846 
  847         return (err);
  848 }
  849 
  850 static int
  851 aw_gpio_map_gpios(device_t bus, phandle_t dev, phandle_t gparent, int gcells,
  852     pcell_t *gpios, uint32_t *pin, uint32_t *flags)
  853 {
  854         struct aw_gpio_softc *sc;
  855         int i;
  856 
  857         sc = device_get_softc(bus);
  858 
  859         /* The GPIO pins are mapped as: <gpio-phandle bank pin flags>. */
  860         for (i = 0; i < sc->conf->padconf->npins; i++)
  861                 if (sc->conf->padconf->pins[i].port == gpios[0] &&
  862                     sc->conf->padconf->pins[i].pin == gpios[1]) {
  863                         *pin = i;
  864                         break;
  865                 }
  866         *flags = gpios[gcells - 1];
  867 
  868         return (0);
  869 }
  870 
  871 static int
  872 aw_find_pinnum_by_name(struct aw_gpio_softc *sc, const char *pinname)
  873 {
  874         int i;
  875 
  876         for (i = 0; i < sc->conf->padconf->npins; i++)
  877                 if (!strcmp(pinname, sc->conf->padconf->pins[i].name))
  878                         return i;
  879 
  880         return (-1);
  881 }
  882 
  883 static int
  884 aw_find_pin_func(struct aw_gpio_softc *sc, int pin, const char *func)
  885 {
  886         int i;
  887 
  888         for (i = 0; i < AW_MAX_FUNC_BY_PIN; i++)
  889                 if (sc->conf->padconf->pins[pin].functions[i] &&
  890                     !strcmp(func, sc->conf->padconf->pins[pin].functions[i]))
  891                         return (i);
  892 
  893         return (-1);
  894 }
  895 
  896 static int
  897 aw_fdt_configure_pins(device_t dev, phandle_t cfgxref)
  898 {
  899         struct aw_gpio_softc *sc;
  900         phandle_t node;
  901         const char **pinlist = NULL;
  902         char *pin_function = NULL;
  903         uint32_t pin_drive, pin_pull;
  904         int pins_nb, pin_num, pin_func, i, ret;
  905         bool set_drive;
  906 
  907         sc = device_get_softc(dev);
  908         node = OF_node_from_xref(cfgxref);
  909         ret = 0;
  910         set_drive = false;
  911 
  912         /* Getting all prop for configuring pins */
  913         pinlist = aw_gpio_parse_pins(node, &pins_nb);
  914         if (pinlist == NULL)
  915                 return (ENOENT);
  916 
  917         pin_function = aw_gpio_parse_function(node);
  918         if (pin_function == NULL) {
  919                 ret = ENOENT;
  920                 goto out;
  921         }
  922 
  923         if (aw_gpio_parse_drive_strength(node, &pin_drive) == 0)
  924                 set_drive = true;
  925 
  926         pin_pull = aw_gpio_parse_bias(node);
  927 
  928         /* Configure each pin to the correct function, drive and pull */
  929         for (i = 0; i < pins_nb; i++) {
  930                 pin_num = aw_find_pinnum_by_name(sc, pinlist[i]);
  931                 if (pin_num == -1) {
  932                         ret = ENOENT;
  933                         goto out;
  934                 }
  935                 pin_func = aw_find_pin_func(sc, pin_num, pin_function);
  936                 if (pin_func == -1) {
  937                         ret = ENOENT;
  938                         goto out;
  939                 }
  940 
  941                 AW_GPIO_LOCK(sc);
  942 
  943                 if (aw_gpio_get_function(sc, pin_num) != pin_func)
  944                         aw_gpio_set_function(sc, pin_num, pin_func);
  945                 if (set_drive)
  946                         aw_gpio_set_drv(sc, pin_num, pin_drive);
  947                 if (pin_pull != AW_GPIO_NONE)
  948                         aw_gpio_set_pud(sc, pin_num, pin_pull);
  949 
  950                 AW_GPIO_UNLOCK(sc);
  951         }
  952 
  953  out:
  954         OF_prop_free(pinlist);
  955         OF_prop_free(pin_function);
  956         return (ret);
  957 }
  958 
  959 static void
  960 aw_gpio_enable_bank_supply(void *arg)
  961 {
  962         struct aw_gpio_softc *sc = arg;
  963         regulator_t vcc_supply;
  964         char bank_reg_name[16];
  965         int i, nbanks;
  966 
  967         nbanks = strlen(sc->conf->banks);
  968         for (i = 0; i < nbanks; i++) {
  969                 snprintf(bank_reg_name, sizeof(bank_reg_name), "vcc-p%c-supply",
  970                     sc->conf->banks[i]);
  971 
  972                 if (regulator_get_by_ofw_property(sc->sc_dev, 0, bank_reg_name, &vcc_supply) == 0) {
  973                         if (bootverbose)
  974                                 device_printf(sc->sc_dev,
  975                                     "Enabling regulator for gpio bank %c\n",
  976                                     sc->conf->banks[i]);
  977                         if (regulator_enable(vcc_supply) != 0) {
  978                                 device_printf(sc->sc_dev,
  979                                     "Cannot enable regulator for bank %c\n",
  980                                     sc->conf->banks[i]);
  981                         }
  982                 }
  983         }
  984 }
  985 
  986 static int
  987 aw_gpio_probe(device_t dev)
  988 {
  989 
  990         if (!ofw_bus_status_okay(dev))
  991                 return (ENXIO);
  992 
  993         if (ofw_bus_search_compatible(dev, compat_data)->ocd_data == 0)
  994                 return (ENXIO);
  995 
  996         device_set_desc(dev, "Allwinner GPIO/Pinmux controller");
  997         return (BUS_PROBE_DEFAULT);
  998 }
  999 
 1000 static int
 1001 aw_gpio_attach(device_t dev)
 1002 {
 1003         int error;
 1004         phandle_t gpio;
 1005         struct aw_gpio_softc *sc;
 1006         struct clk_list *clkp, *clkp_tmp;
 1007         clk_t clk;
 1008         hwreset_t rst = NULL;
 1009         int off, err, clkret;
 1010 
 1011         sc = device_get_softc(dev);
 1012         sc->sc_dev = dev;
 1013 
 1014         mtx_init(&sc->sc_mtx, "aw gpio", "gpio", MTX_SPIN);
 1015 
 1016         if (bus_alloc_resources(dev, aw_gpio_res_spec, sc->sc_res) != 0) {
 1017                 device_printf(dev, "cannot allocate device resources\n");
 1018                 return (ENXIO);
 1019         }
 1020 
 1021         if (bus_setup_intr(dev, sc->sc_res[AW_GPIO_IRQRES],
 1022             INTR_TYPE_CLK | INTR_MPSAFE, NULL, aw_gpio_intr, sc,
 1023             &sc->sc_intrhand)) {
 1024                 device_printf(dev, "cannot setup interrupt handler\n");
 1025                 goto fail;
 1026         }
 1027 
 1028         /* Find our node. */
 1029         gpio = ofw_bus_get_node(sc->sc_dev);
 1030         if (!OF_hasprop(gpio, "gpio-controller"))
 1031                 /* Node is not a GPIO controller. */
 1032                 goto fail;
 1033 
 1034         /* Use the right pin data for the current SoC */
 1035         sc->conf = (struct aw_gpio_conf *)ofw_bus_search_compatible(dev,
 1036             compat_data)->ocd_data;
 1037 
 1038         if (hwreset_get_by_ofw_idx(dev, 0, 0, &rst) == 0) {
 1039                 error = hwreset_deassert(rst);
 1040                 if (error != 0) {
 1041                         device_printf(dev, "cannot de-assert reset\n");
 1042                         goto fail;
 1043                 }
 1044         }
 1045 
 1046         TAILQ_INIT(&sc->clk_list);
 1047         for (off = 0, clkret = 0; clkret == 0; off++) {
 1048                 clkret = clk_get_by_ofw_index(dev, 0, off, &clk);
 1049                 if (clkret != 0)
 1050                         break;
 1051                 err = clk_enable(clk);
 1052                 if (err != 0) {
 1053                         device_printf(dev, "Could not enable clock %s\n",
 1054                             clk_get_name(clk));
 1055                         goto fail;
 1056                 }
 1057                 clkp = malloc(sizeof(*clkp), M_DEVBUF, M_WAITOK | M_ZERO);
 1058                 clkp->clk = clk;
 1059                 TAILQ_INSERT_TAIL(&sc->clk_list, clkp, next);
 1060         }
 1061         if (clkret != 0 && clkret != ENOENT) {
 1062                 device_printf(dev, "Could not find clock at offset %d (%d)\n",
 1063                     off, clkret);
 1064                 goto fail;
 1065         }
 1066 
 1067         aw_gpio_register_isrcs(sc);
 1068         intr_pic_register(dev, OF_xref_from_node(ofw_bus_get_node(dev)));
 1069 
 1070         sc->sc_busdev = gpiobus_attach_bus(dev);
 1071         if (sc->sc_busdev == NULL)
 1072                 goto fail;
 1073 
 1074         /*
 1075          * Register as a pinctrl device
 1076          */
 1077         fdt_pinctrl_register(dev, "pins");
 1078         fdt_pinctrl_configure_tree(dev);
 1079         fdt_pinctrl_register(dev, "allwinner,pins");
 1080         fdt_pinctrl_configure_tree(dev);
 1081 
 1082         config_intrhook_oneshot(aw_gpio_enable_bank_supply, sc);
 1083 
 1084         return (0);
 1085 
 1086 fail:
 1087         if (sc->sc_irq_res)
 1088                 bus_release_resource(dev, SYS_RES_IRQ, 0, sc->sc_irq_res);
 1089         if (sc->sc_mem_res)
 1090                 bus_release_resource(dev, SYS_RES_MEMORY, 0, sc->sc_mem_res);
 1091         mtx_destroy(&sc->sc_mtx);
 1092 
 1093         /* Disable clock */
 1094         TAILQ_FOREACH_SAFE(clkp, &sc->clk_list, next, clkp_tmp) {
 1095                 err = clk_disable(clkp->clk);
 1096                 if (err != 0)
 1097                         device_printf(dev, "Could not disable clock %s\n",
 1098                             clk_get_name(clkp->clk));
 1099                 err = clk_release(clkp->clk);
 1100                 if (err != 0)
 1101                         device_printf(dev, "Could not release clock %s\n",
 1102                             clk_get_name(clkp->clk));
 1103                 TAILQ_REMOVE(&sc->clk_list, clkp, next);
 1104                 free(clkp, M_DEVBUF);
 1105         }
 1106 
 1107         /* Assert resets */
 1108         if (rst) {
 1109                 hwreset_assert(rst);
 1110                 hwreset_release(rst);
 1111         }
 1112 
 1113         return (ENXIO);
 1114 }
 1115 
 1116 static int
 1117 aw_gpio_detach(device_t dev)
 1118 {
 1119 
 1120         return (EBUSY);
 1121 }
 1122 
 1123 static void
 1124 aw_gpio_intr(void *arg)
 1125 {
 1126         struct aw_gpio_softc *sc;
 1127         struct intr_irqsrc *isrc;
 1128         uint32_t reg;
 1129         int irq;
 1130 
 1131         sc = (struct aw_gpio_softc *)arg;
 1132 
 1133         AW_GPIO_LOCK(sc);
 1134         for (irq = 0; irq < sc->nirqs; irq++) {
 1135                 if (!sc->gpio_pic_irqsrc[irq].enabled)
 1136                         continue;
 1137 
 1138                 reg = AW_GPIO_READ(sc, AW_GPIO_GP_INT_STA(sc->gpio_pic_irqsrc[irq].bank));
 1139                 if (!(reg & (1 << sc->gpio_pic_irqsrc[irq].intnum)))
 1140                         continue;
 1141 
 1142                 isrc = &sc->gpio_pic_irqsrc[irq].isrc;
 1143                 if (intr_isrc_dispatch(isrc, curthread->td_intr_frame) != 0) {
 1144                         aw_gpio_pic_disable_intr_locked(sc, isrc);
 1145                         aw_gpio_pic_post_filter(sc->sc_dev, isrc);
 1146                         device_printf(sc->sc_dev, "Stray irq %u disabled\n", irq);
 1147                 }
 1148         }
 1149         AW_GPIO_UNLOCK(sc);
 1150 }
 1151 
 1152 /*
 1153  * Interrupts support
 1154  */
 1155 
 1156 static int
 1157 aw_gpio_register_isrcs(struct aw_gpio_softc *sc)
 1158 {
 1159         const char *name;
 1160         int nirqs;
 1161         int pin;
 1162         int err;
 1163 
 1164         name = device_get_nameunit(sc->sc_dev);
 1165 
 1166         for (nirqs = 0, pin = 0; pin < sc->conf->padconf->npins; pin++) {
 1167                 if (sc->conf->padconf->pins[pin].eint_func == 0)
 1168                         continue;
 1169 
 1170                 nirqs++;
 1171         }
 1172 
 1173         sc->gpio_pic_irqsrc = malloc(sizeof(*sc->gpio_pic_irqsrc) * nirqs,
 1174             M_DEVBUF, M_WAITOK | M_ZERO);
 1175         for (nirqs = 0, pin = 0; pin < sc->conf->padconf->npins; pin++) {
 1176                 if (sc->conf->padconf->pins[pin].eint_func == 0)
 1177                         continue;
 1178 
 1179                 sc->gpio_pic_irqsrc[nirqs].pin = pin;
 1180                 sc->gpio_pic_irqsrc[nirqs].bank = sc->conf->padconf->pins[pin].eint_bank;
 1181                 sc->gpio_pic_irqsrc[nirqs].intnum = sc->conf->padconf->pins[pin].eint_num;
 1182                 sc->gpio_pic_irqsrc[nirqs].intfunc = sc->conf->padconf->pins[pin].eint_func;
 1183                 sc->gpio_pic_irqsrc[nirqs].irq = nirqs;
 1184                 sc->gpio_pic_irqsrc[nirqs].mode = GPIO_INTR_CONFORM;
 1185 
 1186                 err = intr_isrc_register(&sc->gpio_pic_irqsrc[nirqs].isrc,
 1187                     sc->sc_dev, 0, "%s,%s", name,
 1188                     sc->conf->padconf->pins[pin].functions[sc->conf->padconf->pins[pin].eint_func]);
 1189                 if (err) {
 1190                         device_printf(sc->sc_dev, "intr_isrs_register failed for irq %d\n", nirqs);
 1191                 }
 1192 
 1193                 nirqs++;
 1194         }
 1195 
 1196         sc->nirqs = nirqs;
 1197 
 1198         return (0);
 1199 }
 1200 
 1201 static void
 1202 aw_gpio_pic_disable_intr_locked(struct aw_gpio_softc *sc, struct intr_irqsrc *isrc)
 1203 {
 1204         u_int irq;
 1205         uint32_t reg;
 1206 
 1207         AW_GPIO_LOCK_ASSERT(sc);
 1208         irq = ((struct gpio_irqsrc *)isrc)->irq;
 1209         reg = AW_GPIO_READ(sc, AW_GPIO_GP_INT_CTL(sc->gpio_pic_irqsrc[irq].bank));
 1210         reg &= ~(1 << sc->gpio_pic_irqsrc[irq].intnum);
 1211         AW_GPIO_WRITE(sc, AW_GPIO_GP_INT_CTL(sc->gpio_pic_irqsrc[irq].bank), reg);
 1212 
 1213         sc->gpio_pic_irqsrc[irq].enabled = false;
 1214 }
 1215 
 1216 static void
 1217 aw_gpio_pic_disable_intr(device_t dev, struct intr_irqsrc *isrc)
 1218 {
 1219         struct aw_gpio_softc *sc;
 1220 
 1221         sc = device_get_softc(dev);
 1222 
 1223         AW_GPIO_LOCK(sc);
 1224         aw_gpio_pic_disable_intr_locked(sc, isrc);
 1225         AW_GPIO_UNLOCK(sc);
 1226 }
 1227 
 1228 static void
 1229 aw_gpio_pic_enable_intr(device_t dev, struct intr_irqsrc *isrc)
 1230 {
 1231         struct aw_gpio_softc *sc;
 1232         u_int irq;
 1233         uint32_t reg;
 1234 
 1235         sc = device_get_softc(dev);
 1236         irq = ((struct gpio_irqsrc *)isrc)->irq;
 1237         AW_GPIO_LOCK(sc);
 1238         reg = AW_GPIO_READ(sc, AW_GPIO_GP_INT_CTL(sc->gpio_pic_irqsrc[irq].bank));
 1239         reg |= 1 << sc->gpio_pic_irqsrc[irq].intnum;
 1240         AW_GPIO_WRITE(sc, AW_GPIO_GP_INT_CTL(sc->gpio_pic_irqsrc[irq].bank), reg);
 1241         AW_GPIO_UNLOCK(sc);
 1242 
 1243         sc->gpio_pic_irqsrc[irq].enabled = true;
 1244 }
 1245 
 1246 static int
 1247 aw_gpio_pic_map_gpio(struct aw_gpio_softc *sc, struct intr_map_data_gpio *dag,
 1248     u_int *irqp, u_int *mode)
 1249 {
 1250         u_int irq;
 1251         int pin;
 1252 
 1253         irq = dag->gpio_pin_num;
 1254 
 1255         for (pin = 0; pin < sc->nirqs; pin++)
 1256                 if (sc->gpio_pic_irqsrc[pin].pin == irq)
 1257                         break;
 1258         if (pin == sc->nirqs) {
 1259                 device_printf(sc->sc_dev, "Invalid interrupt number %u\n", irq);
 1260                 return (EINVAL);
 1261         }
 1262 
 1263         switch (dag->gpio_intr_mode) {
 1264         case GPIO_INTR_LEVEL_LOW:
 1265         case GPIO_INTR_LEVEL_HIGH:
 1266         case GPIO_INTR_EDGE_RISING:
 1267         case GPIO_INTR_EDGE_FALLING:
 1268         case GPIO_INTR_EDGE_BOTH:
 1269                 break;
 1270         default:
 1271                 device_printf(sc->sc_dev, "Unsupported interrupt mode 0x%8x\n",
 1272                     dag->gpio_intr_mode);
 1273                 return (EINVAL);
 1274         }
 1275 
 1276         *irqp = pin;
 1277         if (mode != NULL)
 1278                 *mode = dag->gpio_intr_mode;
 1279 
 1280         return (0);
 1281 }
 1282 
 1283 static int
 1284 aw_gpio_pic_map_intr(device_t dev, struct intr_map_data *data,
 1285     struct intr_irqsrc **isrcp)
 1286 {
 1287         struct aw_gpio_softc *sc;
 1288         u_int irq;
 1289         int err;
 1290 
 1291         sc = device_get_softc(dev);
 1292         switch (data->type) {
 1293         case INTR_MAP_DATA_GPIO:
 1294                 err = aw_gpio_pic_map_gpio(sc,
 1295                     (struct intr_map_data_gpio *)data,
 1296                   &irq, NULL);
 1297                 break;
 1298         default:
 1299                 return (ENOTSUP);
 1300         };
 1301 
 1302         if (err == 0)
 1303                 *isrcp = &sc->gpio_pic_irqsrc[irq].isrc;
 1304         return (0);
 1305 }
 1306 
 1307 static int
 1308 aw_gpio_pic_setup_intr(device_t dev, struct intr_irqsrc *isrc,
 1309     struct resource *res, struct intr_map_data *data)
 1310 {
 1311         struct aw_gpio_softc *sc;
 1312         struct gpio_irqsrc *gi;
 1313         uint32_t irqcfg;
 1314         uint32_t pinidx, reg;
 1315         u_int irq, mode;
 1316         int err;
 1317 
 1318         sc = device_get_softc(dev);
 1319         gi = (struct gpio_irqsrc *)isrc;
 1320 
 1321         switch (data->type) {
 1322         case INTR_MAP_DATA_GPIO:
 1323                 err = aw_gpio_pic_map_gpio(sc,
 1324                     (struct intr_map_data_gpio *)data,
 1325                   &irq, &mode);
 1326                 break;
 1327         default:
 1328                 return (ENOTSUP);
 1329         };
 1330 
 1331         pinidx = (sc->gpio_pic_irqsrc[irq].intnum % 8) * 4;
 1332 
 1333         AW_GPIO_LOCK(sc);
 1334         switch (mode) {
 1335         case GPIO_INTR_LEVEL_LOW:
 1336                 irqcfg = AW_GPIO_INT_LEVEL_LOW << pinidx;
 1337                 break;
 1338         case GPIO_INTR_LEVEL_HIGH:
 1339                 irqcfg = AW_GPIO_INT_LEVEL_HIGH << pinidx;
 1340                 break;
 1341         case GPIO_INTR_EDGE_RISING:
 1342                 irqcfg = AW_GPIO_INT_EDGE_POSITIVE << pinidx;
 1343                 break;
 1344         case GPIO_INTR_EDGE_FALLING:
 1345                 irqcfg = AW_GPIO_INT_EDGE_NEGATIVE << pinidx;
 1346                 break;
 1347         case GPIO_INTR_EDGE_BOTH:
 1348                 irqcfg = AW_GPIO_INT_EDGE_BOTH << pinidx;
 1349                 break;
 1350         }
 1351 
 1352         /* Switch the pin to interrupt mode */
 1353         sc->gpio_pic_irqsrc[irq].oldfunc = aw_gpio_get_function(sc,
 1354             sc->gpio_pic_irqsrc[irq].pin);
 1355         aw_gpio_set_function(sc, sc->gpio_pic_irqsrc[irq].pin,
 1356             sc->gpio_pic_irqsrc[irq].intfunc);
 1357 
 1358         /* Write interrupt mode */
 1359         reg = AW_GPIO_READ(sc, 
 1360             AW_GPIO_GP_INT_CFG(sc->gpio_pic_irqsrc[irq].bank,
 1361             sc->gpio_pic_irqsrc[irq].intnum));
 1362         reg &= ~(0xF << pinidx);
 1363         reg |= irqcfg;
 1364         AW_GPIO_WRITE(sc,
 1365             AW_GPIO_GP_INT_CFG(sc->gpio_pic_irqsrc[irq].bank,
 1366             sc->gpio_pic_irqsrc[irq].intnum),
 1367             reg);
 1368 
 1369         AW_GPIO_UNLOCK(sc);
 1370 
 1371         return (0);
 1372 }
 1373 
 1374 static int
 1375 aw_gpio_pic_teardown_intr(device_t dev, struct intr_irqsrc *isrc,
 1376     struct resource *res, struct intr_map_data *data)
 1377 {
 1378         struct aw_gpio_softc *sc;
 1379         struct gpio_irqsrc *gi;
 1380 
 1381         sc = device_get_softc(dev);
 1382         gi = (struct gpio_irqsrc *)isrc;
 1383 
 1384         /* Switch back the pin to it's original function */
 1385         AW_GPIO_LOCK(sc);
 1386         aw_gpio_set_function(sc, gi->pin, gi->oldfunc);
 1387         AW_GPIO_UNLOCK(sc);
 1388 
 1389         return (0);
 1390 }
 1391 
 1392 static void
 1393 aw_gpio_pic_post_filter(device_t dev, struct intr_irqsrc *isrc)
 1394 {
 1395         struct aw_gpio_softc *sc;
 1396         struct gpio_irqsrc *gi;
 1397 
 1398         sc = device_get_softc(dev);
 1399         gi = (struct gpio_irqsrc *)isrc;
 1400 
 1401         arm_irq_memory_barrier(0);
 1402         AW_GPIO_WRITE(sc, AW_GPIO_GP_INT_STA(gi->bank), 1 << gi->intnum);
 1403 }
 1404 
 1405 static void
 1406 aw_gpio_pic_post_ithread(device_t dev, struct intr_irqsrc *isrc)
 1407 {
 1408         struct aw_gpio_softc *sc;
 1409         struct gpio_irqsrc *gi;
 1410 
 1411         sc = device_get_softc(dev);
 1412         gi = (struct gpio_irqsrc *)isrc;
 1413 
 1414         arm_irq_memory_barrier(0);
 1415         AW_GPIO_WRITE(sc, AW_GPIO_GP_INT_STA(gi->bank), 1 << gi->intnum);
 1416         aw_gpio_pic_enable_intr(dev, isrc);
 1417 }
 1418 
 1419 static void
 1420 aw_gpio_pic_pre_ithread(device_t dev, struct intr_irqsrc *isrc)
 1421 {
 1422         struct aw_gpio_softc *sc;
 1423 
 1424         sc = device_get_softc(dev);
 1425         aw_gpio_pic_disable_intr_locked(sc, isrc);
 1426 }
 1427 
 1428 /*
 1429  * OFWBUS Interface
 1430  */
 1431 static phandle_t
 1432 aw_gpio_get_node(device_t dev, device_t bus)
 1433 {
 1434 
 1435         /* We only have one child, the GPIO bus, which needs our own node. */
 1436         return (ofw_bus_get_node(dev));
 1437 }
 1438 
 1439 static device_method_t aw_gpio_methods[] = {
 1440         /* Device interface */
 1441         DEVMETHOD(device_probe,         aw_gpio_probe),
 1442         DEVMETHOD(device_attach,        aw_gpio_attach),
 1443         DEVMETHOD(device_detach,        aw_gpio_detach),
 1444 
 1445         /* Interrupt controller interface */
 1446         DEVMETHOD(pic_disable_intr,     aw_gpio_pic_disable_intr),
 1447         DEVMETHOD(pic_enable_intr,      aw_gpio_pic_enable_intr),
 1448         DEVMETHOD(pic_map_intr,         aw_gpio_pic_map_intr),
 1449         DEVMETHOD(pic_setup_intr,       aw_gpio_pic_setup_intr),
 1450         DEVMETHOD(pic_teardown_intr,    aw_gpio_pic_teardown_intr),
 1451         DEVMETHOD(pic_post_filter,      aw_gpio_pic_post_filter),
 1452         DEVMETHOD(pic_post_ithread,     aw_gpio_pic_post_ithread),
 1453         DEVMETHOD(pic_pre_ithread,      aw_gpio_pic_pre_ithread),
 1454 
 1455         /* GPIO protocol */
 1456         DEVMETHOD(gpio_get_bus,         aw_gpio_get_bus),
 1457         DEVMETHOD(gpio_pin_max,         aw_gpio_pin_max),
 1458         DEVMETHOD(gpio_pin_getname,     aw_gpio_pin_getname),
 1459         DEVMETHOD(gpio_pin_getflags,    aw_gpio_pin_getflags),
 1460         DEVMETHOD(gpio_pin_getcaps,     aw_gpio_pin_getcaps),
 1461         DEVMETHOD(gpio_pin_setflags,    aw_gpio_pin_setflags),
 1462         DEVMETHOD(gpio_pin_get,         aw_gpio_pin_get),
 1463         DEVMETHOD(gpio_pin_set,         aw_gpio_pin_set),
 1464         DEVMETHOD(gpio_pin_toggle,      aw_gpio_pin_toggle),
 1465         DEVMETHOD(gpio_pin_access_32,   aw_gpio_pin_access_32),
 1466         DEVMETHOD(gpio_pin_config_32,   aw_gpio_pin_config_32),
 1467         DEVMETHOD(gpio_map_gpios,       aw_gpio_map_gpios),
 1468 
 1469         /* ofw_bus interface */
 1470         DEVMETHOD(ofw_bus_get_node,     aw_gpio_get_node),
 1471 
 1472         /* fdt_pinctrl interface */
 1473         DEVMETHOD(fdt_pinctrl_configure,aw_fdt_configure_pins),
 1474 
 1475         DEVMETHOD_END
 1476 };
 1477 
 1478 static devclass_t aw_gpio_devclass;
 1479 
 1480 static driver_t aw_gpio_driver = {
 1481         "gpio",
 1482         aw_gpio_methods,
 1483         sizeof(struct aw_gpio_softc),
 1484 };
 1485 
 1486 EARLY_DRIVER_MODULE(aw_gpio, simplebus, aw_gpio_driver, aw_gpio_devclass, 0, 0,
 1487     BUS_PASS_INTERRUPT + BUS_PASS_ORDER_LATE);

Cache object: 63dfd35540c62304519a6ad4347bca39


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