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/mips/atheros/ar71xx_gpio.c

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

    1 /*-
    2  * Copyright (c) 2009, Oleksandr Tymoshenko <gonzo@FreeBSD.org>
    3  * Copyright (c) 2009, Luiz Otavio O Souza. 
    4  * All rights reserved.
    5  *
    6  * Redistribution and use in source and binary forms, with or without
    7  * modification, are permitted provided that the following conditions
    8  * are met:
    9  * 1. Redistributions of source code must retain the above copyright
   10  *    notice unmodified, this list of conditions, and the following
   11  *    disclaimer.
   12  * 2. Redistributions in binary form must reproduce the above copyright
   13  *    notice, this list of conditions and the following disclaimer in the
   14  *    documentation and/or other materials provided with the distribution.
   15  *
   16  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
   17  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   18  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   19  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
   20  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   21  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
   22  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   23  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   24  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
   25  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   26  * SUCH DAMAGE.
   27  */
   28 
   29 /*
   30  * GPIO driver for AR71xx 
   31  */
   32 
   33 #include <sys/cdefs.h>
   34 __FBSDID("$FreeBSD: releng/10.0/sys/mips/atheros/ar71xx_gpio.c 255335 2013-09-06 23:47:50Z loos $");
   35 
   36 #include <sys/param.h>
   37 #include <sys/systm.h>
   38 #include <sys/bus.h>
   39 
   40 #include <sys/kernel.h>
   41 #include <sys/module.h>
   42 #include <sys/rman.h>
   43 #include <sys/lock.h>
   44 #include <sys/malloc.h>
   45 #include <sys/mutex.h>
   46 #include <sys/gpio.h>
   47 
   48 #include <machine/bus.h>
   49 #include <machine/resource.h>
   50 #include <mips/atheros/ar71xxreg.h>
   51 #include <mips/atheros/ar71xx_setup.h>
   52 #include <mips/atheros/ar71xx_gpiovar.h>
   53 #include <mips/atheros/ar933xreg.h>
   54 #include <mips/atheros/ar934xreg.h>
   55 
   56 #include "gpio_if.h"
   57 
   58 #define DEFAULT_CAPS    (GPIO_PIN_INPUT | GPIO_PIN_OUTPUT)
   59 
   60 /*
   61  * Helpers
   62  */
   63 static void ar71xx_gpio_function_enable(struct ar71xx_gpio_softc *sc, 
   64     uint32_t mask);
   65 static void ar71xx_gpio_function_disable(struct ar71xx_gpio_softc *sc, 
   66     uint32_t mask);
   67 static void ar71xx_gpio_pin_configure(struct ar71xx_gpio_softc *sc, 
   68     struct gpio_pin *pin, uint32_t flags);
   69 
   70 /*
   71  * Driver stuff
   72  */
   73 static int ar71xx_gpio_probe(device_t dev);
   74 static int ar71xx_gpio_attach(device_t dev);
   75 static int ar71xx_gpio_detach(device_t dev);
   76 static int ar71xx_gpio_filter(void *arg);
   77 static void ar71xx_gpio_intr(void *arg);
   78 
   79 /*
   80  * GPIO interface
   81  */
   82 static int ar71xx_gpio_pin_max(device_t dev, int *maxpin);
   83 static int ar71xx_gpio_pin_getcaps(device_t dev, uint32_t pin, uint32_t *caps);
   84 static int ar71xx_gpio_pin_getflags(device_t dev, uint32_t pin, uint32_t
   85     *flags);
   86 static int ar71xx_gpio_pin_getname(device_t dev, uint32_t pin, char *name);
   87 static int ar71xx_gpio_pin_setflags(device_t dev, uint32_t pin, uint32_t flags);
   88 static int ar71xx_gpio_pin_set(device_t dev, uint32_t pin, unsigned int value);
   89 static int ar71xx_gpio_pin_get(device_t dev, uint32_t pin, unsigned int *val);
   90 static int ar71xx_gpio_pin_toggle(device_t dev, uint32_t pin);
   91 
   92 static void
   93 ar71xx_gpio_function_enable(struct ar71xx_gpio_softc *sc, uint32_t mask)
   94 {
   95         if (ar71xx_soc == AR71XX_SOC_AR9341 ||
   96             ar71xx_soc == AR71XX_SOC_AR9342 ||
   97             ar71xx_soc == AR71XX_SOC_AR9344)
   98                 GPIO_SET_BITS(sc, AR934X_GPIO_REG_FUNC, mask);
   99         else
  100                 GPIO_SET_BITS(sc, AR71XX_GPIO_FUNCTION, mask);
  101 }
  102 
  103 static void
  104 ar71xx_gpio_function_disable(struct ar71xx_gpio_softc *sc, uint32_t mask)
  105 {
  106         if (ar71xx_soc == AR71XX_SOC_AR9341 ||
  107             ar71xx_soc == AR71XX_SOC_AR9342 ||
  108             ar71xx_soc == AR71XX_SOC_AR9344)
  109                 GPIO_CLEAR_BITS(sc, AR934X_GPIO_REG_FUNC, mask);
  110         else
  111                 GPIO_CLEAR_BITS(sc, AR71XX_GPIO_FUNCTION, mask);
  112 }
  113 
  114 static void
  115 ar71xx_gpio_pin_configure(struct ar71xx_gpio_softc *sc, struct gpio_pin *pin,
  116     unsigned int flags)
  117 {
  118         uint32_t mask;
  119 
  120         mask = 1 << pin->gp_pin;
  121 
  122         /*
  123          * Manage input/output
  124          */
  125         if (flags & (GPIO_PIN_INPUT|GPIO_PIN_OUTPUT)) {
  126                 pin->gp_flags &= ~(GPIO_PIN_INPUT|GPIO_PIN_OUTPUT);
  127                 if (flags & GPIO_PIN_OUTPUT) {
  128                         pin->gp_flags |= GPIO_PIN_OUTPUT;
  129                         GPIO_SET_BITS(sc, AR71XX_GPIO_OE, mask);
  130                 }
  131                 else {
  132                         pin->gp_flags |= GPIO_PIN_INPUT;
  133                         GPIO_CLEAR_BITS(sc, AR71XX_GPIO_OE, mask);
  134                 }
  135         }
  136 }
  137 
  138 static int
  139 ar71xx_gpio_pin_max(device_t dev, int *maxpin)
  140 {
  141 
  142         switch (ar71xx_soc) {
  143                 case AR71XX_SOC_AR9130:
  144                 case AR71XX_SOC_AR9132:
  145                         *maxpin = AR91XX_GPIO_PINS - 1;
  146                         break;
  147                 case AR71XX_SOC_AR7240:
  148                 case AR71XX_SOC_AR7241:
  149                 case AR71XX_SOC_AR7242:
  150                         *maxpin = AR724X_GPIO_PINS - 1;
  151                         break;
  152                 case AR71XX_SOC_AR9330:
  153                 case AR71XX_SOC_AR9331:
  154                         *maxpin = AR933X_GPIO_COUNT - 1;
  155                         break;
  156                 case AR71XX_SOC_AR9341:
  157                 case AR71XX_SOC_AR9342:
  158                 case AR71XX_SOC_AR9344:
  159                         *maxpin = AR934X_GPIO_COUNT - 1;
  160                         break;
  161                 default:
  162                         *maxpin = AR71XX_GPIO_PINS - 1;
  163         }
  164         return (0);
  165 }
  166 
  167 static int
  168 ar71xx_gpio_pin_getcaps(device_t dev, uint32_t pin, uint32_t *caps)
  169 {
  170         struct ar71xx_gpio_softc *sc = device_get_softc(dev);
  171         int i;
  172 
  173         for (i = 0; i < sc->gpio_npins; i++) {
  174                 if (sc->gpio_pins[i].gp_pin == pin)
  175                         break;
  176         }
  177 
  178         if (i >= sc->gpio_npins)
  179                 return (EINVAL);
  180 
  181         GPIO_LOCK(sc);
  182         *caps = sc->gpio_pins[i].gp_caps;
  183         GPIO_UNLOCK(sc);
  184 
  185         return (0);
  186 }
  187 
  188 static int
  189 ar71xx_gpio_pin_getflags(device_t dev, uint32_t pin, uint32_t *flags)
  190 {
  191         struct ar71xx_gpio_softc *sc = device_get_softc(dev);
  192         int i;
  193 
  194         for (i = 0; i < sc->gpio_npins; i++) {
  195                 if (sc->gpio_pins[i].gp_pin == pin)
  196                         break;
  197         }
  198 
  199         if (i >= sc->gpio_npins)
  200                 return (EINVAL);
  201 
  202         GPIO_LOCK(sc);
  203         *flags = sc->gpio_pins[i].gp_flags;
  204         GPIO_UNLOCK(sc);
  205 
  206         return (0);
  207 }
  208 
  209 static int
  210 ar71xx_gpio_pin_getname(device_t dev, uint32_t pin, char *name)
  211 {
  212         struct ar71xx_gpio_softc *sc = device_get_softc(dev);
  213         int i;
  214 
  215         for (i = 0; i < sc->gpio_npins; i++) {
  216                 if (sc->gpio_pins[i].gp_pin == pin)
  217                         break;
  218         }
  219 
  220         if (i >= sc->gpio_npins)
  221                 return (EINVAL);
  222 
  223         GPIO_LOCK(sc);
  224         memcpy(name, sc->gpio_pins[i].gp_name, GPIOMAXNAME);
  225         GPIO_UNLOCK(sc);
  226 
  227         return (0);
  228 }
  229 
  230 static int
  231 ar71xx_gpio_pin_setflags(device_t dev, uint32_t pin, uint32_t flags)
  232 {
  233         int i;
  234         struct ar71xx_gpio_softc *sc = device_get_softc(dev);
  235 
  236         for (i = 0; i < sc->gpio_npins; i++) {
  237                 if (sc->gpio_pins[i].gp_pin == pin)
  238                         break;
  239         }
  240 
  241         if (i >= sc->gpio_npins)
  242                 return (EINVAL);
  243 
  244         /* Check for unwanted flags. */
  245         if ((flags & sc->gpio_pins[i].gp_caps) != flags)
  246                 return (EINVAL);
  247 
  248         /* Can't mix input/output together */
  249         if ((flags & (GPIO_PIN_INPUT|GPIO_PIN_OUTPUT)) ==
  250             (GPIO_PIN_INPUT|GPIO_PIN_OUTPUT))
  251                 return (EINVAL);
  252 
  253         ar71xx_gpio_pin_configure(sc, &sc->gpio_pins[i], flags);
  254         return (0);
  255 }
  256 
  257 static int
  258 ar71xx_gpio_pin_set(device_t dev, uint32_t pin, unsigned int value)
  259 {
  260         struct ar71xx_gpio_softc *sc = device_get_softc(dev);
  261         int i;
  262 
  263         for (i = 0; i < sc->gpio_npins; i++) {
  264                 if (sc->gpio_pins[i].gp_pin == pin)
  265                         break;
  266         }
  267 
  268         if (i >= sc->gpio_npins)
  269                 return (EINVAL);
  270 
  271         if (value)
  272                 GPIO_WRITE(sc, AR71XX_GPIO_SET, (1 << pin));
  273         else
  274                 GPIO_WRITE(sc, AR71XX_GPIO_CLEAR, (1 << pin));
  275 
  276         return (0);
  277 }
  278 
  279 static int
  280 ar71xx_gpio_pin_get(device_t dev, uint32_t pin, unsigned int *val)
  281 {
  282         struct ar71xx_gpio_softc *sc = device_get_softc(dev);
  283         int i;
  284 
  285         for (i = 0; i < sc->gpio_npins; i++) {
  286                 if (sc->gpio_pins[i].gp_pin == pin)
  287                         break;
  288         }
  289 
  290         if (i >= sc->gpio_npins)
  291                 return (EINVAL);
  292 
  293         *val = (GPIO_READ(sc, AR71XX_GPIO_IN) & (1 << pin)) ? 1 : 0;
  294 
  295         return (0);
  296 }
  297 
  298 static int
  299 ar71xx_gpio_pin_toggle(device_t dev, uint32_t pin)
  300 {
  301         int res, i;
  302         struct ar71xx_gpio_softc *sc = device_get_softc(dev);
  303 
  304         for (i = 0; i < sc->gpio_npins; i++) {
  305                 if (sc->gpio_pins[i].gp_pin == pin)
  306                         break;
  307         }
  308 
  309         if (i >= sc->gpio_npins)
  310                 return (EINVAL);
  311 
  312         res = (GPIO_READ(sc, AR71XX_GPIO_IN) & (1 << pin)) ? 1 : 0;
  313         if (res)
  314                 GPIO_WRITE(sc, AR71XX_GPIO_CLEAR, (1 << pin));
  315         else
  316                 GPIO_WRITE(sc, AR71XX_GPIO_SET, (1 << pin));
  317 
  318         return (0);
  319 }
  320 
  321 static int
  322 ar71xx_gpio_filter(void *arg)
  323 {
  324 
  325         /* TODO: something useful */
  326         return (FILTER_STRAY);
  327 }
  328 
  329 
  330 
  331 static void
  332 ar71xx_gpio_intr(void *arg)
  333 {
  334         struct ar71xx_gpio_softc *sc = arg;
  335         GPIO_LOCK(sc);
  336         /* TODO: something useful */
  337         GPIO_UNLOCK(sc);
  338 }
  339 
  340 static int
  341 ar71xx_gpio_probe(device_t dev)
  342 {
  343 
  344         device_set_desc(dev, "Atheros AR71XX GPIO driver");
  345         return (0);
  346 }
  347 
  348 static int
  349 ar71xx_gpio_attach(device_t dev)
  350 {
  351         struct ar71xx_gpio_softc *sc = device_get_softc(dev);
  352         int error = 0;
  353         int i, j, maxpin;
  354         int mask, pinon;
  355         int old = 0;
  356 
  357         KASSERT((device_get_unit(dev) == 0),
  358             ("ar71xx_gpio: Only one gpio module supported"));
  359 
  360         mtx_init(&sc->gpio_mtx, device_get_nameunit(dev), NULL, MTX_DEF);
  361 
  362         /* Map control/status registers. */
  363         sc->gpio_mem_rid = 0;
  364         sc->gpio_mem_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY,
  365             &sc->gpio_mem_rid, RF_ACTIVE);
  366 
  367         if (sc->gpio_mem_res == NULL) {
  368                 device_printf(dev, "couldn't map memory\n");
  369                 error = ENXIO;
  370                 ar71xx_gpio_detach(dev);
  371                 return(error);
  372         }
  373 
  374         if ((sc->gpio_irq_res = bus_alloc_resource_any(dev, SYS_RES_IRQ, 
  375             &sc->gpio_irq_rid, RF_SHAREABLE | RF_ACTIVE)) == NULL) {
  376                 device_printf(dev, "unable to allocate IRQ resource\n");
  377                 return (ENXIO);
  378         }
  379 
  380         if ((bus_setup_intr(dev, sc->gpio_irq_res, INTR_TYPE_MISC, 
  381             ar71xx_gpio_filter, ar71xx_gpio_intr, sc, &sc->gpio_ih))) {
  382                 device_printf(dev,
  383                     "WARNING: unable to register interrupt handler\n");
  384                 return (ENXIO);
  385         }
  386 
  387         sc->dev = dev;
  388 
  389         /* Enable function bits that are required */
  390         if (resource_int_value(device_get_name(dev), device_get_unit(dev),
  391             "function_set", &mask) == 0) {
  392                 device_printf(dev, "function_set: 0x%x\n", mask);
  393                 ar71xx_gpio_function_enable(sc, mask);
  394                 old = 1;
  395         }
  396         /* Disable function bits that are required */
  397         if (resource_int_value(device_get_name(dev), device_get_unit(dev),
  398             "function_clear", &mask) == 0) {
  399                 device_printf(dev, "function_clear: 0x%x\n", mask);
  400                 ar71xx_gpio_function_disable(sc, mask);
  401                 old = 1;
  402         }
  403         /* Handle previous behaviour */
  404         if (old == 0) {
  405                 ar71xx_gpio_function_enable(sc, GPIO_FUNC_SPI_CS1_EN);
  406                 ar71xx_gpio_function_enable(sc, GPIO_FUNC_SPI_CS2_EN);
  407         }
  408 
  409         /* Configure all pins as input */
  410         /* disable interrupts for all pins */
  411         GPIO_WRITE(sc, AR71XX_GPIO_INT_MASK, 0);
  412 
  413         /* Initialise all pins specified in the mask, up to the pin count */
  414         (void) ar71xx_gpio_pin_max(dev, &maxpin);
  415         if (resource_int_value(device_get_name(dev), device_get_unit(dev),
  416             "pinmask", &mask) != 0)
  417                 mask = 0;
  418         if (resource_int_value(device_get_name(dev), device_get_unit(dev),
  419             "pinon", &pinon) != 0)
  420                 pinon = 0;
  421         device_printf(dev, "gpio pinmask=0x%x\n", mask);
  422         for (j = 0; j <= maxpin; j++) {
  423                 if ((mask & (1 << j)) == 0)
  424                         continue;
  425                 sc->gpio_npins++;
  426         }
  427         sc->gpio_pins = malloc(sizeof(*sc->gpio_pins) * sc->gpio_npins,
  428             M_DEVBUF, M_WAITOK | M_ZERO);
  429         for (i = 0, j = 0; j <= maxpin; j++) {
  430                 if ((mask & (1 << j)) == 0)
  431                         continue;
  432                 snprintf(sc->gpio_pins[i].gp_name, GPIOMAXNAME,
  433                     "pin %d", j);
  434                 sc->gpio_pins[i].gp_pin = j;
  435                 sc->gpio_pins[i].gp_caps = DEFAULT_CAPS;
  436                 sc->gpio_pins[i].gp_flags = 0;
  437                 ar71xx_gpio_pin_configure(sc, &sc->gpio_pins[i], DEFAULT_CAPS);
  438                 i++;
  439         }
  440         for (i = 0; i < sc->gpio_npins; i++) {
  441                 j = sc->gpio_pins[i].gp_pin;
  442                 if ((pinon & (1 << j)) != 0)
  443                         ar71xx_gpio_pin_set(dev, j, 1);
  444         }
  445         device_add_child(dev, "gpioc", device_get_unit(dev));
  446         device_add_child(dev, "gpiobus", device_get_unit(dev));
  447         return (bus_generic_attach(dev));
  448 }
  449 
  450 static int
  451 ar71xx_gpio_detach(device_t dev)
  452 {
  453         struct ar71xx_gpio_softc *sc = device_get_softc(dev);
  454 
  455         KASSERT(mtx_initialized(&sc->gpio_mtx), ("gpio mutex not initialized"));
  456 
  457         ar71xx_gpio_function_disable(sc, GPIO_FUNC_SPI_CS1_EN);
  458         ar71xx_gpio_function_disable(sc, GPIO_FUNC_SPI_CS2_EN);
  459         bus_generic_detach(dev);
  460 
  461         if (sc->gpio_mem_res)
  462                 bus_release_resource(dev, SYS_RES_MEMORY, sc->gpio_mem_rid,
  463                     sc->gpio_mem_res);
  464 
  465         free(sc->gpio_pins, M_DEVBUF);
  466         mtx_destroy(&sc->gpio_mtx);
  467 
  468         return(0);
  469 }
  470 
  471 static device_method_t ar71xx_gpio_methods[] = {
  472         DEVMETHOD(device_probe, ar71xx_gpio_probe),
  473         DEVMETHOD(device_attach, ar71xx_gpio_attach),
  474         DEVMETHOD(device_detach, ar71xx_gpio_detach),
  475 
  476         /* GPIO protocol */
  477         DEVMETHOD(gpio_pin_max, ar71xx_gpio_pin_max),
  478         DEVMETHOD(gpio_pin_getname, ar71xx_gpio_pin_getname),
  479         DEVMETHOD(gpio_pin_getflags, ar71xx_gpio_pin_getflags),
  480         DEVMETHOD(gpio_pin_getcaps, ar71xx_gpio_pin_getcaps),
  481         DEVMETHOD(gpio_pin_setflags, ar71xx_gpio_pin_setflags),
  482         DEVMETHOD(gpio_pin_get, ar71xx_gpio_pin_get),
  483         DEVMETHOD(gpio_pin_set, ar71xx_gpio_pin_set),
  484         DEVMETHOD(gpio_pin_toggle, ar71xx_gpio_pin_toggle),
  485         {0, 0},
  486 };
  487 
  488 static driver_t ar71xx_gpio_driver = {
  489         "gpio",
  490         ar71xx_gpio_methods,
  491         sizeof(struct ar71xx_gpio_softc),
  492 };
  493 static devclass_t ar71xx_gpio_devclass;
  494 
  495 DRIVER_MODULE(ar71xx_gpio, apb, ar71xx_gpio_driver, ar71xx_gpio_devclass, 0, 0);

Cache object: 515f44348aa6faba9067e4ef40cc9d8d


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