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

Cache object: b59231bd264d64926864117c8f7b3b09


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