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-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) 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/10.4/sys/arm/xscale/ixp425/cambria_gpio.c 278786 2015-02-14 21:16:19Z loos $");
   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         uint8_t                 sc_val;
   88 };
   89 
   90 struct cambria_gpio_pin {
   91         const char *name;
   92         int pin;
   93         int flags;
   94 };
   95 
   96 extern struct ixp425_softc *ixp425_softc;
   97 
   98 static struct cambria_gpio_pin cambria_gpio_pins[GPIO_PINS] = {
   99         { "PLD0", 0, GPIO_PIN_OUTPUT },
  100         { "PLD1", 1, GPIO_PIN_OUTPUT },
  101         { "PLD2", 2, GPIO_PIN_OUTPUT },
  102         { "PLD3", 3, GPIO_PIN_OUTPUT },
  103         { "PLD4", 4, GPIO_PIN_OUTPUT },
  104 };
  105 
  106 /*
  107  * Helpers
  108  */
  109 static int cambria_gpio_read(struct cambria_gpio_softc *, uint32_t, unsigned int *);
  110 static int cambria_gpio_write(struct cambria_gpio_softc *);
  111 
  112 /*
  113  * Driver stuff
  114  */
  115 static int cambria_gpio_probe(device_t dev);
  116 static int cambria_gpio_attach(device_t dev);
  117 static int cambria_gpio_detach(device_t dev);
  118 
  119 /*
  120  * GPIO interface
  121  */
  122 static int cambria_gpio_pin_max(device_t dev, int *maxpin);
  123 static int cambria_gpio_pin_getcaps(device_t dev, uint32_t pin, uint32_t *caps);
  124 static int cambria_gpio_pin_getflags(device_t dev, uint32_t pin, uint32_t
  125     *flags);
  126 static int cambria_gpio_pin_getname(device_t dev, uint32_t pin, char *name);
  127 static int cambria_gpio_pin_setflags(device_t dev, uint32_t pin, uint32_t flags);
  128 static int cambria_gpio_pin_set(device_t dev, uint32_t pin, unsigned int value);
  129 static int cambria_gpio_pin_get(device_t dev, uint32_t pin, unsigned int *val);
  130 static int cambria_gpio_pin_toggle(device_t dev, uint32_t pin);
  131 
  132 static int
  133 i2c_getsda(struct cambria_gpio_softc *sc)
  134 {
  135         uint32_t reg;
  136 
  137         IXP4XX_GPIO_LOCK();
  138         GPIO_CONF_SET(sc, IXP425_GPIO_GPOER, GPIO_I2C_SDA_BIT);
  139 
  140         reg = GPIO_CONF_READ_4(sc, IXP425_GPIO_GPINR);
  141         IXP4XX_GPIO_UNLOCK();
  142         return (reg & GPIO_I2C_SDA_BIT);
  143 }
  144 
  145 static void
  146 i2c_setsda(struct cambria_gpio_softc *sc, int val)
  147 {
  148 
  149         IXP4XX_GPIO_LOCK();
  150         GPIO_CONF_CLR(sc, IXP425_GPIO_GPOUTR, GPIO_I2C_SDA_BIT);
  151         if (val)
  152                 GPIO_CONF_SET(sc, IXP425_GPIO_GPOER, GPIO_I2C_SDA_BIT);
  153         else
  154                 GPIO_CONF_CLR(sc, IXP425_GPIO_GPOER, GPIO_I2C_SDA_BIT);
  155         IXP4XX_GPIO_UNLOCK();
  156         DELAY(I2C_DELAY);
  157 }
  158 
  159 static void
  160 i2c_setscl(struct cambria_gpio_softc *sc, int val)
  161 {
  162 
  163         IXP4XX_GPIO_LOCK();
  164         GPIO_CONF_CLR(sc, IXP425_GPIO_GPOUTR, GPIO_I2C_SCL_BIT);
  165         if (val)
  166                 GPIO_CONF_SET(sc, IXP425_GPIO_GPOER, GPIO_I2C_SCL_BIT);
  167         else
  168                 GPIO_CONF_CLR(sc, IXP425_GPIO_GPOER, GPIO_I2C_SCL_BIT);
  169         IXP4XX_GPIO_UNLOCK();
  170         DELAY(I2C_DELAY);
  171 }
  172 
  173 static void
  174 i2c_sendstart(struct cambria_gpio_softc *sc)
  175 {
  176         i2c_setsda(sc, 1);
  177         i2c_setscl(sc, 1);
  178         i2c_setsda(sc, 0);
  179         i2c_setscl(sc, 0);
  180 }
  181 
  182 static void
  183 i2c_sendstop(struct cambria_gpio_softc *sc)
  184 {
  185         i2c_setscl(sc, 1);
  186         i2c_setsda(sc, 1);
  187         i2c_setscl(sc, 0);
  188         i2c_setsda(sc, 0);
  189 }
  190 
  191 static void
  192 i2c_sendbyte(struct cambria_gpio_softc *sc, u_char data)
  193 {
  194         int i;
  195 
  196         for (i=7; i>=0; i--) {
  197                 i2c_setsda(sc, data & (1<<i));
  198                 i2c_setscl(sc, 1);
  199                 i2c_setscl(sc, 0);
  200         }
  201         i2c_setscl(sc, 1);
  202         i2c_getsda(sc);
  203         i2c_setscl(sc, 0);
  204 }
  205 
  206 static u_char
  207 i2c_readbyte(struct cambria_gpio_softc *sc)
  208 {
  209         int i;
  210         unsigned char data=0;
  211 
  212         for (i=7; i>=0; i--)
  213         {
  214                 i2c_setscl(sc, 1);
  215                 if (i2c_getsda(sc))
  216                         data |= (1<<i);
  217                 i2c_setscl(sc, 0);
  218         }
  219         return data;
  220 }
  221 
  222 static int
  223 cambria_gpio_read(struct cambria_gpio_softc *sc, uint32_t pin, unsigned int *val)
  224 {
  225         device_t dev = sc->sc_dev;
  226         int error;
  227 
  228         error = iicbus_request_bus(device_get_parent(dev), dev,
  229             IIC_DONTWAIT);
  230         if (error)
  231                 return (error);
  232 
  233         i2c_sendstart(sc);
  234         i2c_sendbyte(sc, PLD_ADDR | LSB);
  235         *val = (i2c_readbyte(sc) & (1 << pin)) != 0;
  236         i2c_sendstop(sc);
  237 
  238         iicbus_release_bus(device_get_parent(dev), dev);
  239 
  240         return (0);
  241 }
  242 
  243 static int
  244 cambria_gpio_write(struct cambria_gpio_softc *sc)
  245 {
  246         device_t dev = sc->sc_dev;
  247         int error;
  248 
  249         error = iicbus_request_bus(device_get_parent(dev), dev,
  250             IIC_DONTWAIT);
  251         if (error)
  252                 return (error);
  253 
  254         i2c_sendstart(sc);
  255         i2c_sendbyte(sc, PLD_ADDR & ~LSB);
  256         i2c_sendbyte(sc, sc->sc_latch);
  257         i2c_sendstop(sc);
  258 
  259         iicbus_release_bus(device_get_parent(dev), dev);
  260 
  261         return (0);
  262 }
  263 
  264 static int
  265 cambria_gpio_pin_max(device_t dev, int *maxpin)
  266 {
  267 
  268         *maxpin = GPIO_PINS - 1;
  269         return (0);
  270 }
  271 
  272 static int
  273 cambria_gpio_pin_getcaps(device_t dev, uint32_t pin, uint32_t *caps)
  274 {
  275         struct cambria_gpio_softc *sc = device_get_softc(dev);
  276 
  277         if (pin >= GPIO_PINS)
  278                 return (EINVAL);
  279 
  280         *caps = sc->sc_pins[pin].gp_caps;
  281         return (0);
  282 }
  283 
  284 static int
  285 cambria_gpio_pin_getflags(device_t dev, uint32_t pin, uint32_t *flags)
  286 {
  287         struct cambria_gpio_softc *sc = device_get_softc(dev);
  288 
  289         if (pin >= GPIO_PINS)
  290                 return (EINVAL);
  291 
  292         *flags = sc->sc_pins[pin].gp_flags;
  293         return (0);
  294 }
  295 
  296 static int
  297 cambria_gpio_pin_getname(device_t dev, uint32_t pin, char *name)
  298 {
  299         struct cambria_gpio_softc *sc = device_get_softc(dev);
  300 
  301         if (pin >= GPIO_PINS)
  302                 return (EINVAL);
  303 
  304         memcpy(name, sc->sc_pins[pin].gp_name, GPIOMAXNAME);
  305         return (0);
  306 }
  307 
  308 static int
  309 cambria_gpio_pin_setflags(device_t dev, uint32_t pin, uint32_t flags)
  310 {
  311         struct cambria_gpio_softc *sc = device_get_softc(dev);
  312         int error;
  313         uint8_t mask;
  314 
  315         mask = 1 << pin;
  316 
  317         if (pin >= GPIO_PINS)
  318                 return (EINVAL);
  319 
  320         GPIO_LOCK(sc);
  321         sc->sc_pins[pin].gp_flags = flags;
  322 
  323         /*
  324          * Writing a logical one sets the signal high and writing a logical
  325          * zero sets the signal low. To configure a digital I/O signal as an
  326          * input, a logical one must first be written to the data bit to
  327          * three-state the associated output.
  328          */
  329         if (flags & GPIO_PIN_INPUT || sc->sc_val & mask)
  330                 sc->sc_latch |= mask; /* input or output & high */
  331         else
  332                 sc->sc_latch &= ~mask;
  333         error = cambria_gpio_write(sc);
  334         GPIO_UNLOCK(sc);
  335 
  336         return (error);
  337 }
  338 
  339 static int
  340 cambria_gpio_pin_set(device_t dev, uint32_t pin, unsigned int value)
  341 {
  342         struct cambria_gpio_softc *sc = device_get_softc(dev);
  343         int error;
  344         uint8_t mask;
  345 
  346         mask = 1 << pin;
  347 
  348         if (pin >= GPIO_PINS)
  349                 return (EINVAL);
  350         GPIO_LOCK(sc);
  351         if (value)
  352                 sc->sc_val |= mask;
  353         else
  354                 sc->sc_val &= ~mask;
  355 
  356         if (sc->sc_pins[pin].gp_flags != GPIO_PIN_OUTPUT) {
  357                 /* just save, altering the latch will disable input */
  358                 GPIO_UNLOCK(sc);
  359                 return (0);
  360         }
  361 
  362         if (value)
  363                 sc->sc_latch |= mask;
  364         else
  365                 sc->sc_latch &= ~mask;
  366         error = cambria_gpio_write(sc);
  367         GPIO_UNLOCK(sc);
  368 
  369         return (error);
  370 }
  371 
  372 static int
  373 cambria_gpio_pin_get(device_t dev, uint32_t pin, unsigned int *val)
  374 {
  375         struct cambria_gpio_softc *sc = device_get_softc(dev);
  376         int error = 0;
  377 
  378         if (pin >= GPIO_PINS)
  379                 return (EINVAL);
  380 
  381         GPIO_LOCK(sc);
  382         if (sc->sc_pins[pin].gp_flags == GPIO_PIN_OUTPUT)
  383                 *val = (sc->sc_latch & (1 << pin)) ? 1 : 0;
  384         else
  385                 error = cambria_gpio_read(sc, pin, val);
  386         GPIO_UNLOCK(sc);
  387 
  388         return (error);
  389 }
  390 
  391 static int
  392 cambria_gpio_pin_toggle(device_t dev, uint32_t pin)
  393 {
  394         struct cambria_gpio_softc *sc = device_get_softc(dev);
  395         int error = 0;
  396 
  397         if (pin >= GPIO_PINS)
  398                 return (EINVAL);
  399 
  400         GPIO_LOCK(sc);
  401         sc->sc_val ^= (1 << pin);
  402         if (sc->sc_pins[pin].gp_flags == GPIO_PIN_OUTPUT) {
  403                 sc->sc_latch ^= (1 << pin);
  404                 error = cambria_gpio_write(sc);
  405         }
  406         GPIO_UNLOCK(sc);
  407 
  408         return (error);
  409 }
  410 
  411 static int
  412 cambria_gpio_probe(device_t dev)
  413 {
  414 
  415         device_set_desc(dev, "Gateworks Cambria GPIO driver");
  416         return (0);
  417 }
  418 
  419 static int
  420 cambria_gpio_attach(device_t dev)
  421 {
  422         struct cambria_gpio_softc *sc = device_get_softc(dev);
  423         int pin;
  424 
  425         sc->sc_dev = dev;
  426         sc->sc_iot = ixp425_softc->sc_iot;
  427         sc->sc_gpio_ioh = ixp425_softc->sc_gpio_ioh;
  428 
  429         mtx_init(&sc->sc_mtx, device_get_nameunit(dev), NULL, MTX_DEF);
  430 
  431         for (pin = 0; pin < GPIO_PINS; pin++) {
  432                 struct cambria_gpio_pin *p = &cambria_gpio_pins[pin];
  433 
  434                 strncpy(sc->sc_pins[pin].gp_name, p->name, GPIOMAXNAME);
  435                 sc->sc_pins[pin].gp_pin = pin;
  436                 sc->sc_pins[pin].gp_caps = GPIO_PIN_INPUT|GPIO_PIN_OUTPUT;
  437                 sc->sc_pins[pin].gp_flags = 0;
  438                 cambria_gpio_pin_setflags(dev, pin, p->flags);
  439         }
  440 
  441         device_add_child(dev, "gpioc", -1);
  442         device_add_child(dev, "gpiobus", -1);
  443 
  444         return (bus_generic_attach(dev));
  445 }
  446 
  447 static int
  448 cambria_gpio_detach(device_t dev)
  449 {
  450         struct cambria_gpio_softc *sc = device_get_softc(dev);
  451 
  452         KASSERT(mtx_initialized(&sc->sc_mtx), ("gpio mutex not initialized"));
  453 
  454         bus_generic_detach(dev);
  455 
  456         mtx_destroy(&sc->sc_mtx);
  457 
  458         return(0);
  459 }
  460 
  461 static device_method_t cambria_gpio_methods[] = {
  462         DEVMETHOD(device_probe, cambria_gpio_probe),
  463         DEVMETHOD(device_attach, cambria_gpio_attach),
  464         DEVMETHOD(device_detach, cambria_gpio_detach),
  465 
  466         /* GPIO protocol */
  467         DEVMETHOD(gpio_pin_max, cambria_gpio_pin_max),
  468         DEVMETHOD(gpio_pin_getname, cambria_gpio_pin_getname),
  469         DEVMETHOD(gpio_pin_getflags, cambria_gpio_pin_getflags),
  470         DEVMETHOD(gpio_pin_getcaps, cambria_gpio_pin_getcaps),
  471         DEVMETHOD(gpio_pin_setflags, cambria_gpio_pin_setflags),
  472         DEVMETHOD(gpio_pin_get, cambria_gpio_pin_get),
  473         DEVMETHOD(gpio_pin_set, cambria_gpio_pin_set),
  474         DEVMETHOD(gpio_pin_toggle, cambria_gpio_pin_toggle),
  475         {0, 0},
  476 };
  477 
  478 static driver_t cambria_gpio_driver = {
  479         "gpio_cambria",
  480         cambria_gpio_methods,
  481         sizeof(struct cambria_gpio_softc),
  482 };
  483 static devclass_t cambria_gpio_devclass;
  484 extern devclass_t gpiobus_devclass, gpioc_devclass;
  485 extern driver_t gpiobus_driver, gpioc_driver;
  486 
  487 DRIVER_MODULE(gpio_cambria, iicbus, cambria_gpio_driver, cambria_gpio_devclass, 0, 0);
  488 DRIVER_MODULE(gpiobus, gpio_cambria, gpiobus_driver, gpiobus_devclass, 0, 0);
  489 DRIVER_MODULE(gpioc, gpio_cambria, gpioc_driver, gpioc_devclass, 0, 0);
  490 MODULE_VERSION(gpio_cambria, 1);
  491 MODULE_DEPEND(gpio_cambria, iicbus, 1, 1, 1);

Cache object: c2b0a2c74e91c64ae7bc0c8d09f8d9b0


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