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.3/sys/mips/atheros/ar71xx_gpio.c 278786 2015-02-14 21:16:19Z 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         ar71xx_gpio_pin_configure(sc, &sc->gpio_pins[i], flags);
  245 
  246         return (0);
  247 }
  248 
  249 static int
  250 ar71xx_gpio_pin_set(device_t dev, uint32_t pin, unsigned int value)
  251 {
  252         struct ar71xx_gpio_softc *sc = device_get_softc(dev);
  253         int i;
  254 
  255         for (i = 0; i < sc->gpio_npins; i++) {
  256                 if (sc->gpio_pins[i].gp_pin == pin)
  257                         break;
  258         }
  259 
  260         if (i >= sc->gpio_npins)
  261                 return (EINVAL);
  262 
  263         if (value)
  264                 GPIO_WRITE(sc, AR71XX_GPIO_SET, (1 << pin));
  265         else
  266                 GPIO_WRITE(sc, AR71XX_GPIO_CLEAR, (1 << pin));
  267 
  268         return (0);
  269 }
  270 
  271 static int
  272 ar71xx_gpio_pin_get(device_t dev, uint32_t pin, unsigned int *val)
  273 {
  274         struct ar71xx_gpio_softc *sc = device_get_softc(dev);
  275         int i;
  276 
  277         for (i = 0; i < sc->gpio_npins; i++) {
  278                 if (sc->gpio_pins[i].gp_pin == pin)
  279                         break;
  280         }
  281 
  282         if (i >= sc->gpio_npins)
  283                 return (EINVAL);
  284 
  285         *val = (GPIO_READ(sc, AR71XX_GPIO_IN) & (1 << pin)) ? 1 : 0;
  286 
  287         return (0);
  288 }
  289 
  290 static int
  291 ar71xx_gpio_pin_toggle(device_t dev, uint32_t pin)
  292 {
  293         int res, i;
  294         struct ar71xx_gpio_softc *sc = device_get_softc(dev);
  295 
  296         for (i = 0; i < sc->gpio_npins; i++) {
  297                 if (sc->gpio_pins[i].gp_pin == pin)
  298                         break;
  299         }
  300 
  301         if (i >= sc->gpio_npins)
  302                 return (EINVAL);
  303 
  304         res = (GPIO_READ(sc, AR71XX_GPIO_IN) & (1 << pin)) ? 1 : 0;
  305         if (res)
  306                 GPIO_WRITE(sc, AR71XX_GPIO_CLEAR, (1 << pin));
  307         else
  308                 GPIO_WRITE(sc, AR71XX_GPIO_SET, (1 << pin));
  309 
  310         return (0);
  311 }
  312 
  313 static int
  314 ar71xx_gpio_filter(void *arg)
  315 {
  316 
  317         /* TODO: something useful */
  318         return (FILTER_STRAY);
  319 }
  320 
  321 
  322 
  323 static void
  324 ar71xx_gpio_intr(void *arg)
  325 {
  326         struct ar71xx_gpio_softc *sc = arg;
  327         GPIO_LOCK(sc);
  328         /* TODO: something useful */
  329         GPIO_UNLOCK(sc);
  330 }
  331 
  332 static int
  333 ar71xx_gpio_probe(device_t dev)
  334 {
  335 
  336         device_set_desc(dev, "Atheros AR71XX GPIO driver");
  337         return (0);
  338 }
  339 
  340 static int
  341 ar71xx_gpio_attach(device_t dev)
  342 {
  343         struct ar71xx_gpio_softc *sc = device_get_softc(dev);
  344         int error = 0;
  345         int i, j, maxpin;
  346         int mask, pinon;
  347         int old = 0;
  348 
  349         KASSERT((device_get_unit(dev) == 0),
  350             ("ar71xx_gpio: Only one gpio module supported"));
  351 
  352         mtx_init(&sc->gpio_mtx, device_get_nameunit(dev), NULL, MTX_DEF);
  353 
  354         /* Map control/status registers. */
  355         sc->gpio_mem_rid = 0;
  356         sc->gpio_mem_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY,
  357             &sc->gpio_mem_rid, RF_ACTIVE);
  358 
  359         if (sc->gpio_mem_res == NULL) {
  360                 device_printf(dev, "couldn't map memory\n");
  361                 error = ENXIO;
  362                 ar71xx_gpio_detach(dev);
  363                 return(error);
  364         }
  365 
  366         if ((sc->gpio_irq_res = bus_alloc_resource_any(dev, SYS_RES_IRQ, 
  367             &sc->gpio_irq_rid, RF_SHAREABLE | RF_ACTIVE)) == NULL) {
  368                 device_printf(dev, "unable to allocate IRQ resource\n");
  369                 return (ENXIO);
  370         }
  371 
  372         if ((bus_setup_intr(dev, sc->gpio_irq_res, INTR_TYPE_MISC, 
  373             ar71xx_gpio_filter, ar71xx_gpio_intr, sc, &sc->gpio_ih))) {
  374                 device_printf(dev,
  375                     "WARNING: unable to register interrupt handler\n");
  376                 return (ENXIO);
  377         }
  378 
  379         sc->dev = dev;
  380 
  381         /* Enable function bits that are required */
  382         if (resource_int_value(device_get_name(dev), device_get_unit(dev),
  383             "function_set", &mask) == 0) {
  384                 device_printf(dev, "function_set: 0x%x\n", mask);
  385                 ar71xx_gpio_function_enable(sc, mask);
  386                 old = 1;
  387         }
  388         /* Disable function bits that are required */
  389         if (resource_int_value(device_get_name(dev), device_get_unit(dev),
  390             "function_clear", &mask) == 0) {
  391                 device_printf(dev, "function_clear: 0x%x\n", mask);
  392                 ar71xx_gpio_function_disable(sc, mask);
  393                 old = 1;
  394         }
  395         /* Handle previous behaviour */
  396         if (old == 0) {
  397                 ar71xx_gpio_function_enable(sc, GPIO_FUNC_SPI_CS1_EN);
  398                 ar71xx_gpio_function_enable(sc, GPIO_FUNC_SPI_CS2_EN);
  399         }
  400 
  401         /* Configure all pins as input */
  402         /* disable interrupts for all pins */
  403         GPIO_WRITE(sc, AR71XX_GPIO_INT_MASK, 0);
  404 
  405         /* Initialise all pins specified in the mask, up to the pin count */
  406         (void) ar71xx_gpio_pin_max(dev, &maxpin);
  407         if (resource_int_value(device_get_name(dev), device_get_unit(dev),
  408             "pinmask", &mask) != 0)
  409                 mask = 0;
  410         if (resource_int_value(device_get_name(dev), device_get_unit(dev),
  411             "pinon", &pinon) != 0)
  412                 pinon = 0;
  413         device_printf(dev, "gpio pinmask=0x%x\n", mask);
  414         for (j = 0; j <= maxpin; j++) {
  415                 if ((mask & (1 << j)) == 0)
  416                         continue;
  417                 sc->gpio_npins++;
  418         }
  419         sc->gpio_pins = malloc(sizeof(*sc->gpio_pins) * sc->gpio_npins,
  420             M_DEVBUF, M_WAITOK | M_ZERO);
  421         for (i = 0, j = 0; j <= maxpin; j++) {
  422                 if ((mask & (1 << j)) == 0)
  423                         continue;
  424                 snprintf(sc->gpio_pins[i].gp_name, GPIOMAXNAME,
  425                     "pin %d", j);
  426                 sc->gpio_pins[i].gp_pin = j;
  427                 sc->gpio_pins[i].gp_caps = DEFAULT_CAPS;
  428                 sc->gpio_pins[i].gp_flags = 0;
  429                 ar71xx_gpio_pin_configure(sc, &sc->gpio_pins[i], DEFAULT_CAPS);
  430                 i++;
  431         }
  432         for (i = 0; i < sc->gpio_npins; i++) {
  433                 j = sc->gpio_pins[i].gp_pin;
  434                 if ((pinon & (1 << j)) != 0)
  435                         ar71xx_gpio_pin_set(dev, j, 1);
  436         }
  437         device_add_child(dev, "gpioc", -1);
  438         device_add_child(dev, "gpiobus", -1);
  439 
  440         return (bus_generic_attach(dev));
  441 }
  442 
  443 static int
  444 ar71xx_gpio_detach(device_t dev)
  445 {
  446         struct ar71xx_gpio_softc *sc = device_get_softc(dev);
  447 
  448         KASSERT(mtx_initialized(&sc->gpio_mtx), ("gpio mutex not initialized"));
  449 
  450         ar71xx_gpio_function_disable(sc, GPIO_FUNC_SPI_CS1_EN);
  451         ar71xx_gpio_function_disable(sc, GPIO_FUNC_SPI_CS2_EN);
  452         bus_generic_detach(dev);
  453 
  454         if (sc->gpio_mem_res)
  455                 bus_release_resource(dev, SYS_RES_MEMORY, sc->gpio_mem_rid,
  456                     sc->gpio_mem_res);
  457 
  458         free(sc->gpio_pins, M_DEVBUF);
  459         mtx_destroy(&sc->gpio_mtx);
  460 
  461         return(0);
  462 }
  463 
  464 static device_method_t ar71xx_gpio_methods[] = {
  465         DEVMETHOD(device_probe, ar71xx_gpio_probe),
  466         DEVMETHOD(device_attach, ar71xx_gpio_attach),
  467         DEVMETHOD(device_detach, ar71xx_gpio_detach),
  468 
  469         /* GPIO protocol */
  470         DEVMETHOD(gpio_pin_max, ar71xx_gpio_pin_max),
  471         DEVMETHOD(gpio_pin_getname, ar71xx_gpio_pin_getname),
  472         DEVMETHOD(gpio_pin_getflags, ar71xx_gpio_pin_getflags),
  473         DEVMETHOD(gpio_pin_getcaps, ar71xx_gpio_pin_getcaps),
  474         DEVMETHOD(gpio_pin_setflags, ar71xx_gpio_pin_setflags),
  475         DEVMETHOD(gpio_pin_get, ar71xx_gpio_pin_get),
  476         DEVMETHOD(gpio_pin_set, ar71xx_gpio_pin_set),
  477         DEVMETHOD(gpio_pin_toggle, ar71xx_gpio_pin_toggle),
  478         {0, 0},
  479 };
  480 
  481 static driver_t ar71xx_gpio_driver = {
  482         "gpio",
  483         ar71xx_gpio_methods,
  484         sizeof(struct ar71xx_gpio_softc),
  485 };
  486 static devclass_t ar71xx_gpio_devclass;
  487 
  488 DRIVER_MODULE(ar71xx_gpio, apb, ar71xx_gpio_driver, ar71xx_gpio_devclass, 0, 0);

Cache object: de871270dab68b34a3c1cc85432a3c21


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