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/arm/xscale/ixp425/cambria_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) 2010, Andrew Thompson <thompsa@FreeBSD.org>
    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 unmodified, this list of conditions, and the following
   10  *    disclaimer.
   11  * 2. Redistributions in binary form must reproduce the above copyright
   12  *    notice, this list of conditions and the following disclaimer in the
   13  *    documentation and/or other materials provided with the distribution.
   14  *
   15  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
   16  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   17  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   18  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
   19  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   20  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
   21  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   22  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   23  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
   24  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   25  * SUCH DAMAGE.
   26  */
   27 
   28 /*
   29  * GPIO driver for Gateworks Cambria
   30  *
   31  * Note:
   32  * The Cambria PLD does not set the i2c ack bit after each write, if we used the
   33  * regular iicbus interface it would abort the xfer after the address byte
   34  * times out and not write our latch. To get around this we grab the iicbus and
   35  * then do our own bit banging. This is a comprimise to changing all the iicbb
   36  * device methods to allow a flag to be passed down and is similir to how Linux
   37  * does it.
   38  *
   39  */
   40 
   41 #include <sys/cdefs.h>
   42 __FBSDID("$FreeBSD: releng/9.0/sys/arm/xscale/ixp425/cambria_gpio.c 215319 2010-11-14 20:41:22Z thompsa $");
   43 
   44 #include <sys/param.h>
   45 #include <sys/systm.h>
   46 #include <sys/bus.h>
   47 
   48 #include <sys/kernel.h>
   49 #include <sys/module.h>
   50 #include <sys/rman.h>
   51 #include <sys/lock.h>
   52 #include <sys/mutex.h>
   53 #include <sys/gpio.h>
   54 
   55 #include <arm/xscale/ixp425/ixp425reg.h>
   56 #include <arm/xscale/ixp425/ixp425var.h>
   57 #include <arm/xscale/ixp425/ixdp425reg.h>
   58 
   59 #include <dev/iicbus/iiconf.h>
   60 #include <dev/iicbus/iicbus.h>
   61 
   62 #include "iicbb_if.h"
   63 #include "gpio_if.h"
   64 
   65 #define IIC_M_WR        0       /* write operation */
   66 #define PLD_ADDR        0xac    /* slave address */
   67 
   68 #define I2C_DELAY       10
   69 
   70 #define GPIO_CONF_CLR(sc, reg, mask)    \
   71         GPIO_CONF_WRITE_4(sc, reg, GPIO_CONF_READ_4(sc, reg) &~ (mask))
   72 #define GPIO_CONF_SET(sc, reg, mask)    \
   73         GPIO_CONF_WRITE_4(sc, reg, GPIO_CONF_READ_4(sc, reg) | (mask))
   74 
   75 #define GPIO_LOCK(_sc)          mtx_lock(&(_sc)->sc_mtx)
   76 #define GPIO_UNLOCK(_sc)        mtx_unlock(&(_sc)->sc_mtx)
   77 #define GPIO_LOCK_ASSERT(_sc)   mtx_assert(&(_sc)->sc_mtx, MA_OWNED)
   78 
   79 #define GPIO_PINS               5
   80 struct cambria_gpio_softc {
   81         device_t                sc_dev;
   82         bus_space_tag_t         sc_iot;
   83         bus_space_handle_t      sc_gpio_ioh;
   84         struct mtx              sc_mtx;
   85         struct gpio_pin         sc_pins[GPIO_PINS];
   86         uint8_t                 sc_latch;
   87 };
   88 
   89 struct cambria_gpio_pin {
   90         const char *name;
   91         int pin;
   92         int flags;
   93 };
   94 
   95 extern struct ixp425_softc *ixp425_softc;
   96 
   97 static struct cambria_gpio_pin cambria_gpio_pins[GPIO_PINS] = {
   98         { "GPIO0", 0, GPIO_PIN_OUTPUT },
   99         { "GPIO1", 1, GPIO_PIN_OUTPUT },
  100         { "GPIO2", 2, GPIO_PIN_OUTPUT },
  101         { "GPIO3", 3, GPIO_PIN_OUTPUT },
  102         { "GPIO4", 4, GPIO_PIN_OUTPUT },
  103 };
  104 
  105 /*
  106  * Helpers
  107  */
  108 static int cambria_gpio_read(struct cambria_gpio_softc *, uint32_t, unsigned int *);
  109 static int cambria_gpio_write(struct cambria_gpio_softc *);
  110 
  111 /*
  112  * Driver stuff
  113  */
  114 static int cambria_gpio_probe(device_t dev);
  115 static int cambria_gpio_attach(device_t dev);
  116 static int cambria_gpio_detach(device_t dev);
  117 
  118 /*
  119  * GPIO interface
  120  */
  121 static int cambria_gpio_pin_max(device_t dev, int *maxpin);
  122 static int cambria_gpio_pin_getcaps(device_t dev, uint32_t pin, uint32_t *caps);
  123 static int cambria_gpio_pin_getflags(device_t dev, uint32_t pin, uint32_t
  124     *flags);
  125 static int cambria_gpio_pin_getname(device_t dev, uint32_t pin, char *name);
  126 static int cambria_gpio_pin_setflags(device_t dev, uint32_t pin, uint32_t flags);
  127 static int cambria_gpio_pin_set(device_t dev, uint32_t pin, unsigned int value);
  128 static int cambria_gpio_pin_get(device_t dev, uint32_t pin, unsigned int *val);
  129 static int cambria_gpio_pin_toggle(device_t dev, uint32_t pin);
  130 
  131 static int
  132 i2c_getsda(struct cambria_gpio_softc *sc)
  133 {
  134         uint32_t reg;
  135 
  136         IXP4XX_GPIO_LOCK();
  137         GPIO_CONF_SET(sc, IXP425_GPIO_GPOER, GPIO_I2C_SDA_BIT);
  138 
  139         reg = GPIO_CONF_READ_4(sc, IXP425_GPIO_GPINR);
  140         IXP4XX_GPIO_UNLOCK();
  141         return (reg & GPIO_I2C_SDA_BIT);
  142 }
  143 
  144 static void
  145 i2c_setsda(struct cambria_gpio_softc *sc, int val)
  146 {
  147 
  148         IXP4XX_GPIO_LOCK();
  149         GPIO_CONF_CLR(sc, IXP425_GPIO_GPOUTR, GPIO_I2C_SDA_BIT);
  150         if (val)
  151                 GPIO_CONF_SET(sc, IXP425_GPIO_GPOER, GPIO_I2C_SDA_BIT);
  152         else
  153                 GPIO_CONF_CLR(sc, IXP425_GPIO_GPOER, GPIO_I2C_SDA_BIT);
  154         IXP4XX_GPIO_UNLOCK();
  155         DELAY(I2C_DELAY);
  156 }
  157 
  158 static void
  159 i2c_setscl(struct cambria_gpio_softc *sc, int val)
  160 {
  161 
  162         IXP4XX_GPIO_LOCK();
  163         GPIO_CONF_CLR(sc, IXP425_GPIO_GPOUTR, GPIO_I2C_SCL_BIT);
  164         if (val)
  165                 GPIO_CONF_SET(sc, IXP425_GPIO_GPOER, GPIO_I2C_SCL_BIT);
  166         else
  167                 GPIO_CONF_CLR(sc, IXP425_GPIO_GPOER, GPIO_I2C_SCL_BIT);
  168         IXP4XX_GPIO_UNLOCK();
  169         DELAY(I2C_DELAY);
  170 }
  171 
  172 static void
  173 i2c_sendstart(struct cambria_gpio_softc *sc)
  174 {
  175         i2c_setsda(sc, 1);
  176         i2c_setscl(sc, 1);
  177         i2c_setsda(sc, 0);
  178         i2c_setscl(sc, 0);
  179 }
  180 
  181 static void
  182 i2c_sendstop(struct cambria_gpio_softc *sc)
  183 {
  184         i2c_setscl(sc, 1);
  185         i2c_setsda(sc, 1);
  186         i2c_setscl(sc, 0);
  187         i2c_setsda(sc, 0);
  188 }
  189 
  190 static void
  191 i2c_sendbyte(struct cambria_gpio_softc *sc, u_char data)
  192 {
  193         int i;
  194 
  195         for (i=7; i>=0; i--) {
  196                 i2c_setsda(sc, data & (1<<i));
  197                 i2c_setscl(sc, 1);
  198                 i2c_setscl(sc, 0);
  199         }
  200         i2c_setscl(sc, 1);
  201         i2c_getsda(sc);
  202         i2c_setscl(sc, 0);
  203 }
  204 
  205 static u_char
  206 i2c_readbyte(struct cambria_gpio_softc *sc)
  207 {
  208         int i;
  209         unsigned char data=0;
  210 
  211         for (i=7; i>=0; i--)
  212         {
  213                 i2c_setscl(sc, 1);
  214                 if (i2c_getsda(sc))
  215                         data |= (1<<i);
  216                 i2c_setscl(sc, 0);
  217         }
  218         return data;
  219 }
  220 
  221 static int
  222 cambria_gpio_read(struct cambria_gpio_softc *sc, uint32_t pin, unsigned int *val)
  223 {
  224         device_t dev = sc->sc_dev;
  225         int error;
  226 
  227         error = iicbus_request_bus(device_get_parent(dev), dev,
  228             IIC_DONTWAIT);
  229         if (error)
  230                 return (error);
  231 
  232         i2c_sendstart(sc);
  233         i2c_sendbyte(sc, PLD_ADDR | LSB);
  234         *val = (i2c_readbyte(sc) & (1 << pin)) != 0;
  235         i2c_sendstop(sc);
  236 
  237         iicbus_release_bus(device_get_parent(dev), dev);
  238 
  239         return (0);
  240 }
  241 
  242 static int
  243 cambria_gpio_write(struct cambria_gpio_softc *sc)
  244 {
  245         device_t dev = sc->sc_dev;
  246         int error;
  247 
  248         error = iicbus_request_bus(device_get_parent(dev), dev,
  249             IIC_DONTWAIT);
  250         if (error)
  251                 return (error);
  252 
  253         i2c_sendstart(sc);
  254         i2c_sendbyte(sc, PLD_ADDR & ~LSB);
  255         i2c_sendbyte(sc, sc->sc_latch);
  256         i2c_sendstop(sc);
  257 
  258         iicbus_release_bus(device_get_parent(dev), dev);
  259 
  260         return (0);
  261 }
  262 
  263 static int
  264 cambria_gpio_pin_max(device_t dev, int *maxpin)
  265 {
  266 
  267         *maxpin = GPIO_PINS - 1;
  268         return (0);
  269 }
  270 
  271 static int
  272 cambria_gpio_pin_getcaps(device_t dev, uint32_t pin, uint32_t *caps)
  273 {
  274         struct cambria_gpio_softc *sc = device_get_softc(dev);
  275 
  276         if (pin >= GPIO_PINS)
  277                 return (EINVAL);
  278 
  279         *caps = sc->sc_pins[pin].gp_caps;
  280         return (0);
  281 }
  282 
  283 static int
  284 cambria_gpio_pin_getflags(device_t dev, uint32_t pin, uint32_t *flags)
  285 {
  286         struct cambria_gpio_softc *sc = device_get_softc(dev);
  287 
  288         if (pin >= GPIO_PINS)
  289                 return (EINVAL);
  290 
  291         *flags = sc->sc_pins[pin].gp_flags;
  292         return (0);
  293 }
  294 
  295 static int
  296 cambria_gpio_pin_getname(device_t dev, uint32_t pin, char *name)
  297 {
  298         struct cambria_gpio_softc *sc = device_get_softc(dev);
  299 
  300         if (pin >= GPIO_PINS)
  301                 return (EINVAL);
  302 
  303         memcpy(name, sc->sc_pins[pin].gp_name, GPIOMAXNAME);
  304         return (0);
  305 }
  306 
  307 static int
  308 cambria_gpio_pin_setflags(device_t dev, uint32_t pin, uint32_t flags)
  309 {
  310         struct cambria_gpio_softc *sc = device_get_softc(dev);
  311         int error;
  312 
  313         if (pin >= GPIO_PINS)
  314                 return (EINVAL);
  315 
  316         /* Filter out unwanted flags */
  317         if ((flags &= sc->sc_pins[pin].gp_caps) != flags)
  318                 return (EINVAL);
  319 
  320         /* Can't mix input/output together */
  321         if ((flags & (GPIO_PIN_INPUT|GPIO_PIN_OUTPUT)) ==
  322             (GPIO_PIN_INPUT|GPIO_PIN_OUTPUT))
  323                 return (EINVAL);
  324 
  325         GPIO_LOCK(sc);
  326         sc->sc_pins[pin].gp_flags = flags;
  327 
  328         sc->sc_latch |= (1 << pin);
  329         error = cambria_gpio_write(sc);
  330         GPIO_UNLOCK(sc);
  331 
  332         return (error);
  333 }
  334 
  335 static int
  336 cambria_gpio_pin_set(device_t dev, uint32_t pin, unsigned int value)
  337 {
  338         struct cambria_gpio_softc *sc = device_get_softc(dev);
  339         int error;
  340 
  341         if (pin >= GPIO_PINS || sc->sc_pins[pin].gp_flags != GPIO_PIN_OUTPUT)
  342                 return (EINVAL);
  343 
  344         GPIO_LOCK(sc);
  345         if (value)
  346                 sc->sc_latch |= (1 << pin);
  347         else
  348                 sc->sc_latch &= ~(1 << pin);
  349         error = cambria_gpio_write(sc);
  350         GPIO_UNLOCK(sc);
  351 
  352         return (error);
  353 }
  354 
  355 static int
  356 cambria_gpio_pin_get(device_t dev, uint32_t pin, unsigned int *val)
  357 {
  358         struct cambria_gpio_softc *sc = device_get_softc(dev);
  359         int error = 0;
  360 
  361         if (pin >= GPIO_PINS)
  362                 return (EINVAL);
  363 
  364         GPIO_LOCK(sc);
  365         if (sc->sc_pins[pin].gp_flags == GPIO_PIN_OUTPUT)
  366                 *val = (sc->sc_latch & (1 << pin)) ? 1 : 0;
  367         else
  368                 error = cambria_gpio_read(sc, pin, val);
  369         GPIO_UNLOCK(sc);
  370 
  371         return (error);
  372 }
  373 
  374 static int
  375 cambria_gpio_pin_toggle(device_t dev, uint32_t pin)
  376 {
  377         struct cambria_gpio_softc *sc = device_get_softc(dev);
  378         int error;
  379 
  380         if (pin >= GPIO_PINS || sc->sc_pins[pin].gp_flags != GPIO_PIN_OUTPUT)
  381                 return (EINVAL);
  382 
  383         GPIO_LOCK(sc);
  384         sc->sc_latch ^= (1 << pin);
  385         error = cambria_gpio_write(sc);
  386         GPIO_UNLOCK(sc);
  387 
  388         return (error);
  389 }
  390 
  391 static int
  392 cambria_gpio_probe(device_t dev)
  393 {
  394 
  395         device_set_desc(dev, "Gateworks Cambria GPIO driver");
  396         return (0);
  397 }
  398 
  399 static int
  400 cambria_gpio_attach(device_t dev)
  401 {
  402         struct cambria_gpio_softc *sc = device_get_softc(dev);
  403         int pin;
  404 
  405         sc->sc_dev = dev;
  406         sc->sc_iot = ixp425_softc->sc_iot;
  407         sc->sc_gpio_ioh = ixp425_softc->sc_gpio_ioh;
  408 
  409         mtx_init(&sc->sc_mtx, device_get_nameunit(dev), MTX_NETWORK_LOCK,
  410             MTX_DEF);
  411 
  412         for (pin = 0; pin < GPIO_PINS; pin++) {
  413                 struct cambria_gpio_pin *p = &cambria_gpio_pins[pin];
  414 
  415                 strncpy(sc->sc_pins[pin].gp_name, p->name, GPIOMAXNAME);
  416                 sc->sc_pins[pin].gp_pin = pin;
  417                 sc->sc_pins[pin].gp_caps = GPIO_PIN_INPUT|GPIO_PIN_OUTPUT;
  418                 sc->sc_pins[pin].gp_flags = 0;
  419                 cambria_gpio_pin_setflags(dev, pin, p->flags);
  420         }
  421 
  422         device_add_child(dev, "gpioc", device_get_unit(dev));
  423         device_add_child(dev, "gpiobus", device_get_unit(dev));
  424         return (bus_generic_attach(dev));
  425 }
  426 
  427 static int
  428 cambria_gpio_detach(device_t dev)
  429 {
  430         struct cambria_gpio_softc *sc = device_get_softc(dev);
  431 
  432         KASSERT(mtx_initialized(&sc->sc_mtx), ("gpio mutex not initialized"));
  433 
  434         bus_generic_detach(dev);
  435 
  436         mtx_destroy(&sc->sc_mtx);
  437 
  438         return(0);
  439 }
  440 
  441 static device_method_t cambria_gpio_methods[] = {
  442         DEVMETHOD(device_probe, cambria_gpio_probe),
  443         DEVMETHOD(device_attach, cambria_gpio_attach),
  444         DEVMETHOD(device_detach, cambria_gpio_detach),
  445 
  446         /* GPIO protocol */
  447         DEVMETHOD(gpio_pin_max, cambria_gpio_pin_max),
  448         DEVMETHOD(gpio_pin_getname, cambria_gpio_pin_getname),
  449         DEVMETHOD(gpio_pin_getflags, cambria_gpio_pin_getflags),
  450         DEVMETHOD(gpio_pin_getcaps, cambria_gpio_pin_getcaps),
  451         DEVMETHOD(gpio_pin_setflags, cambria_gpio_pin_setflags),
  452         DEVMETHOD(gpio_pin_get, cambria_gpio_pin_get),
  453         DEVMETHOD(gpio_pin_set, cambria_gpio_pin_set),
  454         DEVMETHOD(gpio_pin_toggle, cambria_gpio_pin_toggle),
  455         {0, 0},
  456 };
  457 
  458 static driver_t cambria_gpio_driver = {
  459         "gpio_cambria",
  460         cambria_gpio_methods,
  461         sizeof(struct cambria_gpio_softc),
  462 };
  463 static devclass_t cambria_gpio_devclass;
  464 extern devclass_t gpiobus_devclass, gpioc_devclass;
  465 extern driver_t gpiobus_driver, gpioc_driver;
  466 
  467 DRIVER_MODULE(gpio_cambria, iicbus, cambria_gpio_driver, cambria_gpio_devclass, 0, 0);
  468 DRIVER_MODULE(gpiobus, gpio_cambria, gpiobus_driver, gpiobus_devclass, 0, 0);
  469 DRIVER_MODULE(gpioc, gpio_cambria, gpioc_driver, gpioc_devclass, 0, 0);
  470 MODULE_VERSION(gpio_cambria, 1);
  471 MODULE_DEPEND(gpio_cambria, iicbus, 1, 1, 1);

Cache object: 40d0578870cddb9ccbd30875cac8dc7c


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