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/powerpc/mpc85xx/qoriq_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) 2015 Justin Hibbits
    3  * All rights reserved.
    4  *
    5  * Redistribution and use in source and binary forms, with or without
    6  * modification, are permitted provided that the following conditions
    7  * are met:
    8  * 1. Redistributions of source code must retain the above copyright
    9  *    notice, this list of conditions and the following disclaimer.
   10  * 2. Redistributions in binary form must reproduce the above copyright
   11  *    notice, this list of conditions and the following disclaimer in the
   12  *    documentation and/or other materials provided with the distribution.
   13  *
   14  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
   15  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   16  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   17  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
   18  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   19  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
   20  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   21  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   22  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
   23  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   24  * SUCH DAMAGE.
   25  *
   26  * $FreeBSD: releng/11.0/sys/powerpc/mpc85xx/qoriq_gpio.c 296251 2016-03-01 03:41:48Z jhibbits $
   27  */
   28 
   29 #include <sys/cdefs.h>
   30 __FBSDID("$FreeBSD: releng/11.0/sys/powerpc/mpc85xx/qoriq_gpio.c 296251 2016-03-01 03:41:48Z jhibbits $");
   31 
   32 #include <sys/param.h>
   33 #include <sys/systm.h>
   34 #include <sys/conf.h>
   35 #include <sys/bus.h>
   36 #include <sys/kernel.h>
   37 #include <sys/module.h>
   38 #include <sys/mutex.h>
   39 #include <sys/rman.h>
   40 #include <sys/gpio.h>
   41 
   42 #include <machine/bus.h>
   43 #include <machine/resource.h>
   44 #include <machine/stdarg.h>
   45 
   46 #include <dev/gpio/gpiobusvar.h>
   47 #include <dev/ofw/ofw_bus.h>
   48 #include <dev/ofw/ofw_bus_subr.h>
   49 
   50 #include "gpio_if.h"
   51 
   52 #define MAXPIN          (31)
   53 
   54 #define VALID_PIN(u)    ((u) >= 0 && (u) <= MAXPIN)
   55 
   56 #define GPIO_LOCK(sc)                   mtx_lock(&(sc)->sc_mtx)
   57 #define GPIO_UNLOCK(sc)         mtx_unlock(&(sc)->sc_mtx)
   58 #define GPIO_LOCK_INIT(sc) \
   59         mtx_init(&(sc)->sc_mtx, device_get_nameunit((sc)->dev), \
   60             "gpio", MTX_DEF)
   61 #define GPIO_LOCK_DESTROY(_sc)  mtx_destroy(&_sc->sc_mtx);
   62 
   63 #define GPIO_GPDIR      0x0
   64 #define GPIO_GPODR      0x4
   65 #define GPIO_GPDAT      0x8
   66 #define GPIO_GPIER      0xc
   67 #define GPIO_GPIMR      0x10
   68 #define GPIO_GPICR      0x14
   69 
   70 
   71 struct qoriq_gpio_softc {
   72         device_t        dev;
   73         device_t        busdev;
   74         struct mtx      sc_mtx;
   75         struct resource *sc_mem;        /* Memory resource */
   76 };
   77 
   78 static device_t
   79 qoriq_gpio_get_bus(device_t dev)
   80 {
   81         struct qoriq_gpio_softc *sc;
   82 
   83         sc = device_get_softc(dev);
   84 
   85         return (sc->busdev);
   86 }
   87 
   88 static int
   89 qoriq_gpio_pin_max(device_t dev, int *maxpin)
   90 {
   91 
   92         *maxpin = MAXPIN;
   93         return (0);
   94 }
   95 
   96 /* Get a specific pin's capabilities. */
   97 static int
   98 qoriq_gpio_pin_getcaps(device_t dev, uint32_t pin, uint32_t *caps)
   99 {
  100 
  101         if (!VALID_PIN(pin))
  102                 return (EINVAL);
  103 
  104         *caps = (GPIO_PIN_INPUT | GPIO_PIN_OUTPUT | GPIO_PIN_OPENDRAIN);
  105 
  106         return (0);
  107 }
  108 
  109 /* Get a specific pin's name. */
  110 static int
  111 qoriq_gpio_pin_getname(device_t dev, uint32_t pin, char *name)
  112 {
  113 
  114         if (!VALID_PIN(pin))
  115                 return (EINVAL);
  116 
  117         snprintf(name, GPIOMAXNAME, "qoriq_gpio%d.%d",
  118             device_get_unit(dev), pin);
  119         name[GPIOMAXNAME-1] = '\0';
  120 
  121         return (0);
  122 }
  123 
  124 /* Set flags for the pin. */
  125 static int
  126 qoriq_gpio_pin_setflags(device_t dev, uint32_t pin, uint32_t flags)
  127 {
  128         struct qoriq_gpio_softc *sc = device_get_softc(dev);
  129         uint32_t reg;
  130 
  131         if (!VALID_PIN(pin))
  132                 return (EINVAL);
  133 
  134         if ((flags & (GPIO_PIN_INPUT | GPIO_PIN_OUTPUT)) ==
  135             (GPIO_PIN_INPUT | GPIO_PIN_OUTPUT))
  136                 return (EINVAL);
  137 
  138         GPIO_LOCK(sc);
  139         if (flags & GPIO_PIN_INPUT) {
  140                 reg = bus_read_4(sc->sc_mem, GPIO_GPDIR);
  141                 reg &= ~(1 << (31 - pin));
  142                 bus_write_4(sc->sc_mem, GPIO_GPDIR, reg);
  143         }
  144         else if (flags & GPIO_PIN_OUTPUT) {
  145                 reg = bus_read_4(sc->sc_mem, GPIO_GPDIR);
  146                 reg |= (1 << (31 - pin));
  147                 bus_write_4(sc->sc_mem, GPIO_GPDIR, reg);
  148                 reg = bus_read_4(sc->sc_mem, GPIO_GPODR);
  149                 if (flags & GPIO_PIN_OPENDRAIN)
  150                         reg |= (1 << (31 - pin));
  151                 else
  152                         reg &= ~(1 << (31 - pin));
  153                 bus_write_4(sc->sc_mem, GPIO_GPODR, reg);
  154         }
  155         GPIO_UNLOCK(sc);
  156         return (0);
  157 }
  158 
  159 /* Set a specific output pin's value. */
  160 static int
  161 qoriq_gpio_pin_set(device_t dev, uint32_t pin, unsigned int value)
  162 {
  163         struct qoriq_gpio_softc *sc = device_get_softc(dev);
  164         uint32_t outvals;
  165         uint8_t pinbit;
  166 
  167         if (!VALID_PIN(pin) || value > 1)
  168                 return (EINVAL);
  169 
  170         GPIO_LOCK(sc);
  171         pinbit = 31 - pin;
  172 
  173         outvals = bus_read_4(sc->sc_mem, GPIO_GPDAT);
  174         outvals &= ~(1 << pinbit);
  175         outvals |= (value << pinbit);
  176         bus_write_4(sc->sc_mem, 0, outvals);
  177 
  178         GPIO_UNLOCK(sc);
  179 
  180         return (0);
  181 }
  182 
  183 /* Get a specific pin's input value. */
  184 static int
  185 qoriq_gpio_pin_get(device_t dev, uint32_t pin, unsigned int *value)
  186 {
  187         struct qoriq_gpio_softc *sc = device_get_softc(dev);
  188 
  189         if (!VALID_PIN(pin))
  190                 return (EINVAL);
  191 
  192         *value = (bus_read_4(sc->sc_mem, GPIO_GPDAT) >> (31 - pin)) & 1;
  193 
  194         return (0);
  195 }
  196 
  197 /* Toggle a pin's output value. */
  198 static int
  199 qoriq_gpio_pin_toggle(device_t dev, uint32_t pin)
  200 {
  201         struct qoriq_gpio_softc *sc = device_get_softc(dev);
  202         uint32_t val;
  203 
  204         if (!VALID_PIN(pin))
  205                 return (EINVAL);
  206 
  207         GPIO_LOCK(sc);
  208 
  209         val = bus_read_4(sc->sc_mem, GPIO_GPDAT);
  210         val ^= (1 << (31 - pin));
  211         bus_write_4(sc->sc_mem, 0, val);
  212         
  213         GPIO_UNLOCK(sc);
  214 
  215         return (0);
  216 }
  217 
  218 static int
  219 qoriq_gpio_probe(device_t dev)
  220 {
  221 
  222         if (!ofw_bus_is_compatible(dev, "fsl,qoriq-gpio") &&
  223             !ofw_bus_is_compatible(dev, "fsl,mpc8572-gpio"))
  224                 return (ENXIO);
  225 
  226         device_set_desc(dev, "Freescale QorIQ GPIO driver");
  227 
  228         return (0);
  229 }
  230 
  231 static int qoriq_gpio_detach(device_t dev);
  232 
  233 static int
  234 qoriq_gpio_attach(device_t dev)
  235 {
  236         struct qoriq_gpio_softc *sc = device_get_softc(dev);
  237         int rid;
  238 
  239         sc->dev = dev;
  240 
  241         GPIO_LOCK_INIT(sc);
  242 
  243         /* Allocate memory. */
  244         rid = 0;
  245         sc->sc_mem = bus_alloc_resource_any(dev,
  246                      SYS_RES_MEMORY, &rid, RF_ACTIVE);
  247         if (sc->sc_mem == NULL) {
  248                 device_printf(dev, "Can't allocate memory for device output port");
  249                 qoriq_gpio_detach(dev);
  250                 return (ENOMEM);
  251         }
  252 
  253         sc->busdev = gpiobus_attach_bus(dev);
  254         if (sc->busdev == NULL) {
  255                 qoriq_gpio_detach(dev);
  256                 return (ENOMEM);
  257         }
  258 
  259         OF_device_register_xref(OF_xref_from_node(ofw_bus_get_node(dev)), dev);
  260 
  261         return (0);
  262 }
  263 
  264 static int
  265 qoriq_gpio_detach(device_t dev)
  266 {
  267         struct qoriq_gpio_softc *sc = device_get_softc(dev);
  268 
  269         gpiobus_detach_bus(dev);
  270 
  271         if (sc->sc_mem != NULL) {
  272                 /* Release output port resource. */
  273                 bus_release_resource(dev, SYS_RES_MEMORY,
  274                                      rman_get_rid(sc->sc_mem), sc->sc_mem);
  275         }
  276 
  277         GPIO_LOCK_DESTROY(sc);
  278 
  279         return (0);
  280 }
  281 
  282 static device_method_t qoriq_gpio_methods[] = {
  283         /* device_if */
  284         DEVMETHOD(device_probe,         qoriq_gpio_probe),
  285         DEVMETHOD(device_attach,        qoriq_gpio_attach),
  286         DEVMETHOD(device_detach,        qoriq_gpio_detach),
  287 
  288         /* GPIO protocol */
  289         DEVMETHOD(gpio_get_bus,         qoriq_gpio_get_bus),
  290         DEVMETHOD(gpio_pin_max,         qoriq_gpio_pin_max),
  291         DEVMETHOD(gpio_pin_getname,     qoriq_gpio_pin_getname),
  292         DEVMETHOD(gpio_pin_getcaps,     qoriq_gpio_pin_getcaps),
  293         DEVMETHOD(gpio_pin_get,         qoriq_gpio_pin_get),
  294         DEVMETHOD(gpio_pin_set,         qoriq_gpio_pin_set),
  295         DEVMETHOD(gpio_pin_setflags,    qoriq_gpio_pin_setflags),
  296         DEVMETHOD(gpio_pin_toggle,      qoriq_gpio_pin_toggle),
  297 
  298         DEVMETHOD_END
  299 };
  300 
  301 static driver_t qoriq_gpio_driver = {
  302         "gpio",
  303         qoriq_gpio_methods,
  304         sizeof(struct qoriq_gpio_softc),
  305 };
  306 static devclass_t qoriq_gpio_devclass;
  307 
  308 EARLY_DRIVER_MODULE(qoriq_gpio, simplebus, qoriq_gpio_driver,
  309     qoriq_gpio_devclass, NULL, NULL,
  310     BUS_PASS_RESOURCE + BUS_PASS_ORDER_MIDDLE);

Cache object: 61ae4073522d8559942726fc317e7107


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