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-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-2  -  FREEBSD-11-1  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-4  -  FREEBSD-10-3  -  FREEBSD-10-2  -  FREEBSD-10-1  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-3  -  FREEBSD-9-2  -  FREEBSD-9-1  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-4  -  FREEBSD-8-3  -  FREEBSD-8-2  -  FREEBSD-8-1  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-4  -  FREEBSD-7-3  -  FREEBSD-7-2  -  FREEBSD-7-1  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-4  -  FREEBSD-6-3  -  FREEBSD-6-2  -  FREEBSD-6-1  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-5  -  FREEBSD-5-4  -  FREEBSD-5-3  -  FREEBSD-5-2  -  FREEBSD-5-1  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  linux-2.6  -  linux-2.4.22  -  MK83  -  MK84  -  PLAN9  -  DFBSD  -  NETBSD  -  NETBSD5  -  NETBSD4  -  NETBSD3  -  NETBSD20  -  OPENBSD  -  xnu-517  -  xnu-792  -  xnu-792.6.70  -  xnu-1228  -  xnu-1456.1.26  -  xnu-1699.24.8  -  xnu-2050.18.24  -  OPENSOLARIS  -  minix-3-1-1 
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: stable/8/sys/mips/atheros/ar71xx_gpio.c 249557 2013-04-16 17:50:20Z dim $");
   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/mutex.h>
   45 #include <sys/gpio.h>
   46 
   47 #include <machine/bus.h>
   48 #include <machine/resource.h>
   49 #include <mips/atheros/ar71xxreg.h>
   50 #include <mips/atheros/ar71xx_gpiovar.h>
   51 
   52 #include "gpio_if.h"
   53 
   54 #define DEFAULT_CAPS    (GPIO_PIN_INPUT | GPIO_PIN_OUTPUT)
   55 
   56 struct ar71xx_gpio_pin {
   57         const char *name;
   58         int pin;
   59         int flags;
   60 };
   61 
   62 static struct ar71xx_gpio_pin ar71xx_gpio_pins[] = {
   63         { "RFled", 2, GPIO_PIN_OUTPUT},
   64         { "SW4", 8,  GPIO_PIN_INPUT},
   65         { NULL, 0, 0},
   66 };
   67 
   68 /*
   69  * Helpers
   70  */
   71 static void ar71xx_gpio_function_enable(struct ar71xx_gpio_softc *sc, 
   72     uint32_t mask);
   73 static void ar71xx_gpio_function_disable(struct ar71xx_gpio_softc *sc, 
   74     uint32_t mask);
   75 static void ar71xx_gpio_pin_configure(struct ar71xx_gpio_softc *sc, 
   76     struct gpio_pin *pin, uint32_t flags);
   77 
   78 /*
   79  * Driver stuff
   80  */
   81 static int ar71xx_gpio_probe(device_t dev);
   82 static int ar71xx_gpio_attach(device_t dev);
   83 static int ar71xx_gpio_detach(device_t dev);
   84 static int ar71xx_gpio_filter(void *arg);
   85 static void ar71xx_gpio_intr(void *arg);
   86 
   87 /*
   88  * GPIO interface
   89  */
   90 static int ar71xx_gpio_pin_max(device_t dev, int *maxpin);
   91 static int ar71xx_gpio_pin_getcaps(device_t dev, uint32_t pin, uint32_t *caps);
   92 static int ar71xx_gpio_pin_getflags(device_t dev, uint32_t pin, uint32_t
   93     *flags);
   94 static int ar71xx_gpio_pin_getname(device_t dev, uint32_t pin, char *name);
   95 static int ar71xx_gpio_pin_setflags(device_t dev, uint32_t pin, uint32_t flags);
   96 static int ar71xx_gpio_pin_set(device_t dev, uint32_t pin, unsigned int value);
   97 static int ar71xx_gpio_pin_get(device_t dev, uint32_t pin, unsigned int *val);
   98 static int ar71xx_gpio_pin_toggle(device_t dev, uint32_t pin);
   99 
  100 static void
  101 ar71xx_gpio_function_enable(struct ar71xx_gpio_softc *sc, uint32_t mask)
  102 {
  103         GPIO_LOCK(sc);
  104         GPIO_SET_BITS(sc, AR71XX_GPIO_FUNCTION, mask);
  105         GPIO_UNLOCK(sc);
  106 }
  107 
  108 static void
  109 ar71xx_gpio_function_disable(struct ar71xx_gpio_softc *sc, uint32_t mask)
  110 {
  111         GPIO_LOCK(sc);
  112         GPIO_CLEAR_BITS(sc, AR71XX_GPIO_FUNCTION, mask);
  113         GPIO_UNLOCK(sc);
  114 }
  115 
  116 static void
  117 ar71xx_gpio_pin_configure(struct ar71xx_gpio_softc *sc, struct gpio_pin *pin,
  118     unsigned int flags)
  119 {
  120         uint32_t mask;
  121 
  122         mask = 1 << pin->gp_pin;
  123         GPIO_LOCK(sc);
  124 
  125         /*
  126          * Manage input/output
  127          */
  128         if (flags & (GPIO_PIN_INPUT|GPIO_PIN_OUTPUT)) {
  129                 pin->gp_flags &= ~(GPIO_PIN_INPUT|GPIO_PIN_OUTPUT);
  130                 if (flags & GPIO_PIN_OUTPUT) {
  131                         pin->gp_flags |= GPIO_PIN_OUTPUT;
  132                         GPIO_SET_BITS(sc, AR71XX_GPIO_OE, mask);
  133                 }
  134                 else {
  135                         pin->gp_flags |= GPIO_PIN_INPUT;
  136                         GPIO_CLEAR_BITS(sc, AR71XX_GPIO_OE, mask);
  137                 }
  138         }
  139 
  140         GPIO_UNLOCK(sc);
  141 }
  142 
  143 static int
  144 ar71xx_gpio_pin_max(device_t dev, int *maxpin)
  145 {
  146 
  147         *maxpin = AR71XX_GPIO_PINS - 1;
  148         return (0);
  149 }
  150 
  151 static int
  152 ar71xx_gpio_pin_getcaps(device_t dev, uint32_t pin, uint32_t *caps)
  153 {
  154         struct ar71xx_gpio_softc *sc = device_get_softc(dev);
  155         int i;
  156 
  157         for (i = 0; i < sc->gpio_npins; i++) {
  158                 if (sc->gpio_pins[i].gp_pin == pin)
  159                         break;
  160         }
  161 
  162         if (i >= sc->gpio_npins)
  163                 return (EINVAL);
  164 
  165         GPIO_LOCK(sc);
  166         *caps = sc->gpio_pins[i].gp_caps;
  167         GPIO_UNLOCK(sc);
  168 
  169         return (0);
  170 }
  171 
  172 static int
  173 ar71xx_gpio_pin_getflags(device_t dev, uint32_t pin, uint32_t *flags)
  174 {
  175         struct ar71xx_gpio_softc *sc = device_get_softc(dev);
  176         int i;
  177 
  178         for (i = 0; i < sc->gpio_npins; i++) {
  179                 if (sc->gpio_pins[i].gp_pin == pin)
  180                         break;
  181         }
  182 
  183         if (i >= sc->gpio_npins)
  184                 return (EINVAL);
  185 
  186         GPIO_LOCK(sc);
  187         *flags = sc->gpio_pins[i].gp_flags;
  188         GPIO_UNLOCK(sc);
  189 
  190         return (0);
  191 }
  192 
  193 static int
  194 ar71xx_gpio_pin_getname(device_t dev, uint32_t pin, char *name)
  195 {
  196         struct ar71xx_gpio_softc *sc = device_get_softc(dev);
  197         int i;
  198 
  199         for (i = 0; i < sc->gpio_npins; i++) {
  200                 if (sc->gpio_pins[i].gp_pin == pin)
  201                         break;
  202         }
  203 
  204         if (i >= sc->gpio_npins)
  205                 return (EINVAL);
  206 
  207         GPIO_LOCK(sc);
  208         memcpy(name, sc->gpio_pins[i].gp_name, GPIOMAXNAME);
  209         GPIO_UNLOCK(sc);
  210 
  211         return (0);
  212 }
  213 
  214 static int
  215 ar71xx_gpio_pin_setflags(device_t dev, uint32_t pin, uint32_t flags)
  216 {
  217         int i;
  218         struct ar71xx_gpio_softc *sc = device_get_softc(dev);
  219 
  220         for (i = 0; i < sc->gpio_npins; i++) {
  221                 if (sc->gpio_pins[i].gp_pin == pin)
  222                         break;
  223         }
  224 
  225         if (i >= sc->gpio_npins)
  226                 return (EINVAL);
  227 
  228         /* Check for unwanted flags. */
  229         if ((flags & sc->gpio_pins[i].gp_caps) != flags)
  230                 return (EINVAL);
  231 
  232         /* Can't mix input/output together */
  233         if ((flags & (GPIO_PIN_INPUT|GPIO_PIN_OUTPUT)) ==
  234             (GPIO_PIN_INPUT|GPIO_PIN_OUTPUT))
  235                 return (EINVAL);
  236 
  237         ar71xx_gpio_pin_configure(sc, &sc->gpio_pins[i], flags);
  238         return (0);
  239 }
  240 
  241 static int
  242 ar71xx_gpio_pin_set(device_t dev, uint32_t pin, unsigned int value)
  243 {
  244         struct ar71xx_gpio_softc *sc = device_get_softc(dev);
  245         int i;
  246 
  247         for (i = 0; i < sc->gpio_npins; i++) {
  248                 if (sc->gpio_pins[i].gp_pin == pin)
  249                         break;
  250         }
  251 
  252         if (i >= sc->gpio_npins)
  253                 return (EINVAL);
  254 
  255         GPIO_LOCK(sc);
  256         if (value)
  257                 GPIO_WRITE(sc, AR71XX_GPIO_SET, (1 << pin));
  258         else
  259                 GPIO_WRITE(sc, AR71XX_GPIO_CLEAR, (1 << pin));
  260         GPIO_UNLOCK(sc);
  261 
  262         return (0);
  263 }
  264 
  265 static int
  266 ar71xx_gpio_pin_get(device_t dev, uint32_t pin, unsigned int *val)
  267 {
  268         struct ar71xx_gpio_softc *sc = device_get_softc(dev);
  269         int i;
  270 
  271         for (i = 0; i < sc->gpio_npins; i++) {
  272                 if (sc->gpio_pins[i].gp_pin == pin)
  273                         break;
  274         }
  275 
  276         if (i >= sc->gpio_npins)
  277                 return (EINVAL);
  278 
  279         GPIO_LOCK(sc);
  280         *val = (GPIO_READ(sc, AR71XX_GPIO_IN) & (1 << pin)) ? 1 : 0;
  281         GPIO_UNLOCK(sc);
  282 
  283         return (0);
  284 }
  285 
  286 static int
  287 ar71xx_gpio_pin_toggle(device_t dev, uint32_t pin)
  288 {
  289         int res, i;
  290         struct ar71xx_gpio_softc *sc = device_get_softc(dev);
  291 
  292         for (i = 0; i < sc->gpio_npins; i++) {
  293                 if (sc->gpio_pins[i].gp_pin == pin)
  294                         break;
  295         }
  296 
  297         if (i >= sc->gpio_npins)
  298                 return (EINVAL);
  299 
  300         GPIO_LOCK(sc);
  301         res = (GPIO_READ(sc, AR71XX_GPIO_IN) & (1 << pin)) ? 1 : 0;
  302         if (res)
  303                 GPIO_WRITE(sc, AR71XX_GPIO_CLEAR, (1 << pin));
  304         else
  305                 GPIO_WRITE(sc, AR71XX_GPIO_SET, (1 << pin));
  306         GPIO_UNLOCK(sc);
  307 
  308         return (0);
  309 }
  310 
  311 static int
  312 ar71xx_gpio_filter(void *arg)
  313 {
  314 
  315         /* TODO: something useful */
  316         return (FILTER_STRAY);
  317 }
  318 
  319 
  320 
  321 static void
  322 ar71xx_gpio_intr(void *arg)
  323 {
  324         struct ar71xx_gpio_softc *sc = arg;
  325         GPIO_LOCK(sc);
  326         /* TODO: something useful */
  327         GPIO_UNLOCK(sc);
  328 }
  329 
  330 static int
  331 ar71xx_gpio_probe(device_t dev)
  332 {
  333 
  334         device_set_desc(dev, "Atheros AR71XX GPIO driver");
  335         return (0);
  336 }
  337 
  338 static int
  339 ar71xx_gpio_attach(device_t dev)
  340 {
  341         struct ar71xx_gpio_softc *sc = device_get_softc(dev);
  342         int error = 0;
  343         struct ar71xx_gpio_pin *pinp;
  344         int i;
  345 
  346         KASSERT((device_get_unit(dev) == 0),
  347             ("ar71xx_gpio: Only one gpio module supported"));
  348 
  349         mtx_init(&sc->gpio_mtx, device_get_nameunit(dev), MTX_NETWORK_LOCK,
  350             MTX_DEF);
  351 
  352         /* Map control/status registers. */
  353         sc->gpio_mem_rid = 0;
  354         sc->gpio_mem_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY,
  355             &sc->gpio_mem_rid, RF_ACTIVE);
  356 
  357         if (sc->gpio_mem_res == NULL) {
  358                 device_printf(dev, "couldn't map memory\n");
  359                 error = ENXIO;
  360                 ar71xx_gpio_detach(dev);
  361                 return(error);
  362         }
  363 
  364         if ((sc->gpio_irq_res = bus_alloc_resource_any(dev, SYS_RES_IRQ, 
  365             &sc->gpio_irq_rid, RF_SHAREABLE | RF_ACTIVE)) == NULL) {
  366                 device_printf(dev, "unable to allocate IRQ resource\n");
  367                 return (ENXIO);
  368         }
  369 
  370         if ((bus_setup_intr(dev, sc->gpio_irq_res, INTR_TYPE_MISC, 
  371             ar71xx_gpio_filter, ar71xx_gpio_intr, sc, &sc->gpio_ih))) {
  372                 device_printf(dev,
  373                     "WARNING: unable to register interrupt handler\n");
  374                 return (ENXIO);
  375         }
  376 
  377         sc->dev = dev;
  378         ar71xx_gpio_function_enable(sc, GPIO_FUNC_SPI_CS1_EN);
  379         ar71xx_gpio_function_enable(sc, GPIO_FUNC_SPI_CS2_EN);
  380         /* Configure all pins as input */
  381         /* disable interrupts for all pins */
  382         GPIO_WRITE(sc, AR71XX_GPIO_INT_MASK, 0);
  383         pinp = ar71xx_gpio_pins;
  384         i = 0;
  385         while (pinp->name) {
  386                 strncpy(sc->gpio_pins[i].gp_name, pinp->name, GPIOMAXNAME);
  387                 sc->gpio_pins[i].gp_pin = pinp->pin;
  388                 sc->gpio_pins[i].gp_caps = DEFAULT_CAPS;
  389                 sc->gpio_pins[i].gp_flags = 0;
  390                 ar71xx_gpio_pin_configure(sc, &sc->gpio_pins[i], pinp->flags);
  391                 pinp++;
  392                 i++;
  393         }
  394 
  395         sc->gpio_npins = i;
  396 
  397         device_add_child(dev, "gpioc", device_get_unit(dev));
  398         device_add_child(dev, "gpiobus", device_get_unit(dev));
  399         return (bus_generic_attach(dev));
  400 }
  401 
  402 static int
  403 ar71xx_gpio_detach(device_t dev)
  404 {
  405         struct ar71xx_gpio_softc *sc = device_get_softc(dev);
  406 
  407         KASSERT(mtx_initialized(&sc->gpio_mtx), ("gpio mutex not initialized"));
  408 
  409         ar71xx_gpio_function_disable(sc, GPIO_FUNC_SPI_CS1_EN);
  410         ar71xx_gpio_function_disable(sc, GPIO_FUNC_SPI_CS2_EN);
  411         bus_generic_detach(dev);
  412 
  413         if (sc->gpio_mem_res)
  414                 bus_release_resource(dev, SYS_RES_MEMORY, sc->gpio_mem_rid,
  415                     sc->gpio_mem_res);
  416 
  417         mtx_destroy(&sc->gpio_mtx);
  418 
  419         return(0);
  420 }
  421 
  422 static device_method_t ar71xx_gpio_methods[] = {
  423         DEVMETHOD(device_probe, ar71xx_gpio_probe),
  424         DEVMETHOD(device_attach, ar71xx_gpio_attach),
  425         DEVMETHOD(device_detach, ar71xx_gpio_detach),
  426 
  427         /* GPIO protocol */
  428         DEVMETHOD(gpio_pin_max, ar71xx_gpio_pin_max),
  429         DEVMETHOD(gpio_pin_getname, ar71xx_gpio_pin_getname),
  430         DEVMETHOD(gpio_pin_getflags, ar71xx_gpio_pin_getflags),
  431         DEVMETHOD(gpio_pin_getcaps, ar71xx_gpio_pin_getcaps),
  432         DEVMETHOD(gpio_pin_setflags, ar71xx_gpio_pin_setflags),
  433         DEVMETHOD(gpio_pin_get, ar71xx_gpio_pin_get),
  434         DEVMETHOD(gpio_pin_set, ar71xx_gpio_pin_set),
  435         DEVMETHOD(gpio_pin_toggle, ar71xx_gpio_pin_toggle),
  436         {0, 0},
  437 };
  438 
  439 static driver_t ar71xx_gpio_driver = {
  440         "gpio",
  441         ar71xx_gpio_methods,
  442         sizeof(struct ar71xx_gpio_softc),
  443 };
  444 static devclass_t ar71xx_gpio_devclass;
  445 
  446 DRIVER_MODULE(ar71xx_gpio, apb, ar71xx_gpio_driver, ar71xx_gpio_devclass, 0, 0);

Cache object: 4105140ef31c375847bc57455beecdac


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