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/ar531x/ar5315_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) 2016, Hiroki Mori
    3  * Copyright (c) 2009, Oleksandr Tymoshenko <gonzo@FreeBSD.org>
    4  * Copyright (c) 2009, Luiz Otavio O Souza. 
    5  * All rights reserved.
    6  *
    7  * Redistribution and use in source and binary forms, with or without
    8  * modification, are permitted provided that the following conditions
    9  * are met:
   10  * 1. Redistributions of source code must retain the above copyright
   11  *    notice unmodified, this list of conditions, and the following
   12  *    disclaimer.
   13  * 2. Redistributions in binary form must reproduce the above copyright
   14  *    notice, this list of conditions and the following disclaimer in the
   15  *    documentation and/or other materials provided with the distribution.
   16  *
   17  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
   18  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   19  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   20  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
   21  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   22  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
   23  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   24  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   25  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
   26  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   27  * SUCH DAMAGE.
   28  */
   29 
   30 /*
   31  * GPIO driver for AR5315 
   32  */
   33 
   34 #include <sys/cdefs.h>
   35 __FBSDID("$FreeBSD$");
   36 
   37 #include <sys/param.h>
   38 #include <sys/systm.h>
   39 #include <sys/bus.h>
   40 
   41 #include <sys/kernel.h>
   42 #include <sys/module.h>
   43 #include <sys/rman.h>
   44 #include <sys/lock.h>
   45 #include <sys/malloc.h>
   46 #include <sys/mutex.h>
   47 #include <sys/gpio.h>
   48 
   49 #include <machine/bus.h>
   50 #include <machine/resource.h>
   51 #include <mips/atheros/ar531x/ar5315reg.h>
   52 #include <mips/atheros/ar531x/ar5315_cpudef.h>
   53 #include <mips/atheros/ar531x/ar5315_gpiovar.h>
   54 #include <dev/gpio/gpiobusvar.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 ar5315_gpio_function_enable(struct ar5315_gpio_softc *sc, 
   64     uint32_t mask);
   65 static void ar5315_gpio_function_disable(struct ar5315_gpio_softc *sc, 
   66     uint32_t mask);
   67 static void ar5315_gpio_pin_configure(struct ar5315_gpio_softc *sc, 
   68     struct gpio_pin *pin, uint32_t flags);
   69 
   70 /*
   71  * Driver stuff
   72  */
   73 static int ar5315_gpio_probe(device_t dev);
   74 static int ar5315_gpio_attach(device_t dev);
   75 static int ar5315_gpio_detach(device_t dev);
   76 static int ar5315_gpio_filter(void *arg);
   77 static void ar5315_gpio_intr(void *arg);
   78 
   79 /*
   80  * GPIO interface
   81  */
   82 static device_t ar5315_gpio_get_bus(device_t);
   83 static int ar5315_gpio_pin_max(device_t dev, int *maxpin);
   84 static int ar5315_gpio_pin_getcaps(device_t dev, uint32_t pin, uint32_t *caps);
   85 static int ar5315_gpio_pin_getflags(device_t dev, uint32_t pin, uint32_t
   86     *flags);
   87 static int ar5315_gpio_pin_getname(device_t dev, uint32_t pin, char *name);
   88 static int ar5315_gpio_pin_setflags(device_t dev, uint32_t pin, uint32_t flags);
   89 static int ar5315_gpio_pin_set(device_t dev, uint32_t pin, unsigned int value);
   90 static int ar5315_gpio_pin_get(device_t dev, uint32_t pin, unsigned int *val);
   91 static int ar5315_gpio_pin_toggle(device_t dev, uint32_t pin);
   92 
   93 /*
   94  * Enable/disable the GPIO function control space.
   95  *
   96  * This is primarily for the AR5315, which has SPI CS1/CS2, UART, SLIC, I2S
   97  * as GPIO pin options.
   98  */
   99 static void
  100 ar5315_gpio_function_enable(struct ar5315_gpio_softc *sc, uint32_t mask)
  101 {
  102 //              GPIO_SET_BITS(sc, AR5315_GPIO_FUNCTION, mask);
  103 }
  104 
  105 static void
  106 ar5315_gpio_function_disable(struct ar5315_gpio_softc *sc, uint32_t mask)
  107 {
  108 //              GPIO_CLEAR_BITS(sc, AR5315_GPIO_FUNCTION, mask);
  109 }
  110 
  111 static void
  112 ar5315_gpio_pin_configure(struct ar5315_gpio_softc *sc, struct gpio_pin *pin,
  113     unsigned int flags)
  114 {
  115         uint32_t mask;
  116 
  117         mask = 1 << pin->gp_pin;
  118 
  119         /*
  120          * Manage input/output
  121          */
  122         if (flags & (GPIO_PIN_INPUT|GPIO_PIN_OUTPUT)) {
  123                 pin->gp_flags &= ~(GPIO_PIN_INPUT|GPIO_PIN_OUTPUT);
  124                 if (flags & GPIO_PIN_OUTPUT) {
  125                         pin->gp_flags |= GPIO_PIN_OUTPUT;
  126                         GPIO_SET_BITS(sc, ar531x_gpio_cr(), mask);
  127                 }
  128                 else {
  129                         pin->gp_flags |= GPIO_PIN_INPUT;
  130                         GPIO_CLEAR_BITS(sc, ar531x_gpio_cr(), mask);
  131                 }
  132         }
  133 }
  134 
  135 static device_t
  136 ar5315_gpio_get_bus(device_t dev)
  137 {
  138         struct ar5315_gpio_softc *sc;
  139 
  140         sc = device_get_softc(dev);
  141 
  142         return (sc->busdev);
  143 }
  144 
  145 static int
  146 ar5315_gpio_pin_max(device_t dev, int *maxpin)
  147 {
  148 
  149         *maxpin = ar531x_gpio_pins() - 1;
  150         return (0);
  151 }
  152 
  153 static int
  154 ar5315_gpio_pin_getcaps(device_t dev, uint32_t pin, uint32_t *caps)
  155 {
  156         struct ar5315_gpio_softc *sc = device_get_softc(dev);
  157         int i;
  158 
  159         for (i = 0; i < sc->gpio_npins; i++) {
  160                 if (sc->gpio_pins[i].gp_pin == pin)
  161                         break;
  162         }
  163 
  164         if (i >= sc->gpio_npins)
  165                 return (EINVAL);
  166 
  167         GPIO_LOCK(sc);
  168         *caps = sc->gpio_pins[i].gp_caps;
  169         GPIO_UNLOCK(sc);
  170 
  171         return (0);
  172 }
  173 
  174 static int
  175 ar5315_gpio_pin_getflags(device_t dev, uint32_t pin, uint32_t *flags)
  176 {
  177         struct ar5315_gpio_softc *sc = device_get_softc(dev);
  178         int i;
  179         int dir;
  180 
  181         for (i = 0; i < sc->gpio_npins; i++) {
  182                 if (sc->gpio_pins[i].gp_pin == pin)
  183                         break;
  184         }
  185 
  186         if (i >= sc->gpio_npins)
  187                 return (EINVAL);
  188 
  189         dir = GPIO_READ(sc, ar531x_gpio_cr()) & (1 << pin);
  190 
  191         *flags = dir ? GPIO_PIN_OUTPUT : GPIO_PIN_INPUT;
  192 
  193 /*
  194         GPIO_LOCK(sc);
  195         *flags = sc->gpio_pins[i].gp_flags;
  196         GPIO_UNLOCK(sc);
  197 */
  198 
  199         return (0);
  200 }
  201 
  202 static int
  203 ar5315_gpio_pin_getname(device_t dev, uint32_t pin, char *name)
  204 {
  205         struct ar5315_gpio_softc *sc = device_get_softc(dev);
  206         int i;
  207 
  208         for (i = 0; i < sc->gpio_npins; i++) {
  209                 if (sc->gpio_pins[i].gp_pin == pin)
  210                         break;
  211         }
  212 
  213         if (i >= sc->gpio_npins)
  214                 return (EINVAL);
  215 
  216         GPIO_LOCK(sc);
  217         memcpy(name, sc->gpio_pins[i].gp_name, GPIOMAXNAME);
  218         GPIO_UNLOCK(sc);
  219 
  220         return (0);
  221 }
  222 
  223 static int
  224 ar5315_gpio_pin_setflags(device_t dev, uint32_t pin, uint32_t flags)
  225 {
  226         int i;
  227         struct ar5315_gpio_softc *sc = device_get_softc(dev);
  228 
  229         for (i = 0; i < sc->gpio_npins; i++) {
  230                 if (sc->gpio_pins[i].gp_pin == pin)
  231                         break;
  232         }
  233 
  234         if (i >= sc->gpio_npins)
  235                 return (EINVAL);
  236 
  237         ar5315_gpio_pin_configure(sc, &sc->gpio_pins[i], flags);
  238 
  239         return (0);
  240 }
  241 
  242 static int
  243 ar5315_gpio_pin_set(device_t dev, uint32_t pin, unsigned int value)
  244 {
  245         struct ar5315_gpio_softc *sc = device_get_softc(dev);
  246         uint32_t state;
  247 
  248         state = GPIO_READ(sc, ar531x_gpio_do());
  249 
  250         if(value == 1) {
  251                 state |= (1 << pin);
  252         } else {
  253                 state &= ~(1 << pin);
  254         }
  255 
  256         GPIO_WRITE(sc, ar531x_gpio_do(), state);
  257 
  258         return (0);
  259 }
  260 
  261 static int
  262 ar5315_gpio_pin_get(device_t dev, uint32_t pin, unsigned int *val)
  263 {
  264         struct ar5315_gpio_softc *sc = device_get_softc(dev);
  265         int i;
  266 
  267         for (i = 0; i < sc->gpio_npins; i++) {
  268                 if (sc->gpio_pins[i].gp_pin == pin)
  269                         break;
  270         }
  271 
  272         if (i >= sc->gpio_npins)
  273                 return (EINVAL);
  274 
  275         *val = (GPIO_READ(sc, ar531x_gpio_di()) & (1 << pin)) ? 1 : 0;
  276 
  277         return (0);
  278 }
  279 
  280 static int
  281 ar5315_gpio_pin_toggle(device_t dev, uint32_t pin)
  282 {
  283         int res, i;
  284         struct ar5315_gpio_softc *sc = device_get_softc(dev);
  285 
  286         for (i = 0; i < sc->gpio_npins; i++) {
  287                 if (sc->gpio_pins[i].gp_pin == pin)
  288                         break;
  289         }
  290 
  291         if (i >= sc->gpio_npins)
  292                 return (EINVAL);
  293 
  294         res = (GPIO_READ(sc, ar531x_gpio_do()) & (1 << pin)) ? 1 : 0;
  295         if (res)
  296                 GPIO_CLEAR_BITS(sc, ar531x_gpio_do(), pin);
  297         else
  298                 GPIO_SET_BITS(sc, ar531x_gpio_do(), pin);
  299 
  300         return (0);
  301 }
  302 
  303 static int
  304 ar5315_gpio_filter(void *arg)
  305 {
  306 
  307         /* TODO: something useful */
  308         return (FILTER_STRAY);
  309 }
  310 
  311 
  312 
  313 static void
  314 ar5315_gpio_intr(void *arg)
  315 {
  316         struct ar5315_gpio_softc *sc = arg;
  317         GPIO_LOCK(sc);
  318         /* TODO: something useful */
  319         GPIO_UNLOCK(sc);
  320 }
  321 
  322 static int
  323 ar5315_gpio_probe(device_t dev)
  324 {
  325 
  326         device_set_desc(dev, "Atheros AR531x GPIO driver");
  327         return (0);
  328 }
  329 
  330 static int
  331 ar5315_gpio_attach(device_t dev)
  332 {
  333         struct ar5315_gpio_softc *sc = device_get_softc(dev);
  334         int i, j, maxpin;
  335         int mask, pinon;
  336         uint32_t oe;
  337 
  338         KASSERT((device_get_unit(dev) == 0),
  339             ("ar5315_gpio: Only one gpio module supported"));
  340 
  341         mtx_init(&sc->gpio_mtx, device_get_nameunit(dev), NULL, MTX_DEF);
  342 
  343         /* Map control/status registers. */
  344         sc->gpio_mem_rid = 0;
  345         sc->gpio_mem_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY,
  346             &sc->gpio_mem_rid, RF_ACTIVE);
  347 
  348         if (sc->gpio_mem_res == NULL) {
  349                 device_printf(dev, "couldn't map memory\n");
  350                 ar5315_gpio_detach(dev);
  351                 return (ENXIO);
  352         }
  353 
  354         if ((sc->gpio_irq_res = bus_alloc_resource_any(dev, SYS_RES_IRQ, 
  355             &sc->gpio_irq_rid, RF_SHAREABLE | RF_ACTIVE)) == NULL) {
  356                 device_printf(dev, "unable to allocate IRQ resource\n");
  357                 ar5315_gpio_detach(dev);
  358                 return (ENXIO);
  359         }
  360 
  361         if ((bus_setup_intr(dev, sc->gpio_irq_res, INTR_TYPE_MISC, 
  362             ar5315_gpio_filter, ar5315_gpio_intr, sc, &sc->gpio_ih))) {
  363                 device_printf(dev,
  364                     "WARNING: unable to register interrupt handler\n");
  365                 ar5315_gpio_detach(dev);
  366                 return (ENXIO);
  367         }
  368 
  369         sc->dev = dev;
  370 
  371         /* Enable function bits that are required */
  372         if (resource_int_value(device_get_name(dev), device_get_unit(dev),
  373             "function_set", &mask) == 0) {
  374                 device_printf(dev, "function_set: 0x%x\n", mask);
  375                 ar5315_gpio_function_enable(sc, mask);
  376         }
  377         /* Disable function bits that are required */
  378         if (resource_int_value(device_get_name(dev), device_get_unit(dev),
  379             "function_clear", &mask) == 0) {
  380                 device_printf(dev, "function_clear: 0x%x\n", mask);
  381                 ar5315_gpio_function_disable(sc, mask);
  382         }
  383 
  384         /* Initialise all pins specified in the mask, up to the pin count */
  385         (void) ar5315_gpio_pin_max(dev, &maxpin);
  386         if (resource_int_value(device_get_name(dev), device_get_unit(dev),
  387             "pinmask", &mask) != 0)
  388                 mask = 0;
  389         if (resource_int_value(device_get_name(dev), device_get_unit(dev),
  390             "pinon", &pinon) != 0)
  391                 pinon = 0;
  392         device_printf(dev, "gpio pinmask=0x%x\n", mask);
  393         for (j = 0; j <= maxpin; j++) {
  394                 if ((mask & (1 << j)) == 0)
  395                         continue;
  396                 sc->gpio_npins++;
  397         }
  398 
  399         /* Iniatilize the GPIO pins, keep the loader settings. */
  400         oe = GPIO_READ(sc, ar531x_gpio_cr());
  401         sc->gpio_pins = malloc(sizeof(struct gpio_pin) * sc->gpio_npins,
  402             M_DEVBUF, M_WAITOK | M_ZERO);
  403         for (i = 0, j = 0; j <= maxpin; j++) {
  404                 if ((mask & (1 << j)) == 0)
  405                         continue;
  406                 snprintf(sc->gpio_pins[i].gp_name, GPIOMAXNAME,
  407                     "pin %d", j);
  408                 sc->gpio_pins[i].gp_pin = j;
  409                 sc->gpio_pins[i].gp_caps = DEFAULT_CAPS;
  410                 if (oe & (1 << j))
  411                         sc->gpio_pins[i].gp_flags = GPIO_PIN_OUTPUT;
  412                 else
  413                         sc->gpio_pins[i].gp_flags = GPIO_PIN_INPUT;
  414                 i++;
  415         }
  416 
  417 #if 0
  418         /* Turn on the hinted pins. */
  419         for (i = 0; i < sc->gpio_npins; i++) {
  420                 j = sc->gpio_pins[i].gp_pin;
  421                 if ((pinon & (1 << j)) != 0) {
  422                         ar5315_gpio_pin_setflags(dev, j, GPIO_PIN_OUTPUT);
  423                         ar5315_gpio_pin_set(dev, j, 1);
  424                 }
  425         }
  426 
  427         /*
  428          * Search through the function hints, in case there's some
  429          * overrides such as LNA control.
  430          *
  431          * hint.gpio.X.func.<pin>.gpiofunc=<func value>
  432          * hint.gpio.X.func.<pin>.gpiomode=1 (for output, default low)
  433          */
  434         for (i = 0; i <= maxpin; i++) {
  435                 char buf[32];
  436                 int gpiofunc, gpiomode;
  437 
  438                 snprintf(buf, 32, "func.%d.gpiofunc", i);
  439                 if (resource_int_value(device_get_name(dev),
  440                     device_get_unit(dev),
  441                     buf,
  442                     &gpiofunc) != 0)
  443                         continue;
  444                 /* Get the mode too */
  445                 snprintf(buf, 32, "func.%d.gpiomode", i);
  446                 if (resource_int_value(device_get_name(dev),
  447                     device_get_unit(dev),
  448                     buf,
  449                     &gpiomode) != 0)
  450                         continue;
  451 
  452                 /* We only handle mode=1 for now */
  453                 if (gpiomode != 1)
  454                         continue;
  455 
  456                 device_printf(dev, "%s: GPIO %d: func=%d, mode=%d\n",
  457                     __func__,
  458                     i,
  459                     gpiofunc,
  460                     gpiomode);
  461 
  462                 /* Set output (bit == 0) */
  463                 oe = GPIO_READ(sc, ar531x_gpio_cr());
  464                 oe &= ~ (1 << i);
  465                 GPIO_WRITE(sc, ar531x_gpio_cr(), oe);
  466 
  467                 /* Set pin value = 0, so it stays low by default */
  468                 oe = GPIO_READ(sc, ar531x_gpio_do());
  469                 oe &= ~ (1 << i);
  470                 GPIO_WRITE(sc, ar531x_gpio_do(), oe);
  471 
  472                 /* Finally: Set the output config */
  473 //              ar5315_gpio_ouput_configure(i, gpiofunc);
  474         }
  475 #endif
  476 
  477         sc->busdev = gpiobus_attach_bus(dev);
  478         if (sc->busdev == NULL) {
  479                 ar5315_gpio_detach(dev);
  480                 return (ENXIO);
  481         }
  482 
  483         return (0);
  484 }
  485 
  486 static int
  487 ar5315_gpio_detach(device_t dev)
  488 {
  489         struct ar5315_gpio_softc *sc = device_get_softc(dev);
  490 
  491         KASSERT(mtx_initialized(&sc->gpio_mtx), ("gpio mutex not initialized"));
  492 
  493         gpiobus_detach_bus(dev);
  494         if (sc->gpio_ih)
  495                 bus_teardown_intr(dev, sc->gpio_irq_res, sc->gpio_ih);
  496         if (sc->gpio_irq_res)
  497                 bus_release_resource(dev, SYS_RES_IRQ, sc->gpio_irq_rid,
  498                     sc->gpio_irq_res);
  499         if (sc->gpio_mem_res)
  500                 bus_release_resource(dev, SYS_RES_MEMORY, sc->gpio_mem_rid,
  501                     sc->gpio_mem_res);
  502         if (sc->gpio_pins)
  503                 free(sc->gpio_pins, M_DEVBUF);
  504         mtx_destroy(&sc->gpio_mtx);
  505 
  506         return(0);
  507 }
  508 
  509 static device_method_t ar5315_gpio_methods[] = {
  510         DEVMETHOD(device_probe, ar5315_gpio_probe),
  511         DEVMETHOD(device_attach, ar5315_gpio_attach),
  512         DEVMETHOD(device_detach, ar5315_gpio_detach),
  513 
  514         /* GPIO protocol */
  515         DEVMETHOD(gpio_get_bus, ar5315_gpio_get_bus),
  516         DEVMETHOD(gpio_pin_max, ar5315_gpio_pin_max),
  517         DEVMETHOD(gpio_pin_getname, ar5315_gpio_pin_getname),
  518         DEVMETHOD(gpio_pin_getflags, ar5315_gpio_pin_getflags),
  519         DEVMETHOD(gpio_pin_getcaps, ar5315_gpio_pin_getcaps),
  520         DEVMETHOD(gpio_pin_setflags, ar5315_gpio_pin_setflags),
  521         DEVMETHOD(gpio_pin_get, ar5315_gpio_pin_get),
  522         DEVMETHOD(gpio_pin_set, ar5315_gpio_pin_set),
  523         DEVMETHOD(gpio_pin_toggle, ar5315_gpio_pin_toggle),
  524         {0, 0},
  525 };
  526 
  527 static driver_t ar5315_gpio_driver = {
  528         "gpio",
  529         ar5315_gpio_methods,
  530         sizeof(struct ar5315_gpio_softc),
  531 };
  532 static devclass_t ar5315_gpio_devclass;
  533 
  534 DRIVER_MODULE(ar5315_gpio, apb, ar5315_gpio_driver, ar5315_gpio_devclass, 0, 0);

Cache object: b7e65363e95f0523e29f29a7e64083b8


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