root/dev/gpio/gpioiic.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. gpioiic_match
  2. gpioiic_attach
  3. gpioiic_detach
  4. gpioiic_i2c_acquire_bus
  5. gpioiic_i2c_release_bus
  6. gpioiic_i2c_send_start
  7. gpioiic_i2c_send_stop
  8. gpioiic_i2c_initiate_xfer
  9. gpioiic_i2c_read_byte
  10. gpioiic_i2c_write_byte
  11. gpioiic_bb_set_bits
  12. gpioiic_bb_set_dir
  13. gpioiic_bb_read_bits

    1 /*      $OpenBSD: gpioiic.c,v 1.7 2007/06/05 08:37:20 jsg Exp $ */
    2 
    3 /*
    4  * Copyright (c) 2006 Alexander Yurchenko <grange@openbsd.org>
    5  *
    6  * Permission to use, copy, modify, and distribute this software for any
    7  * purpose with or without fee is hereby granted, provided that the above
    8  * copyright notice and this permission notice appear in all copies.
    9  *
   10  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
   11  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
   12  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
   13  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
   14  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
   15  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
   16  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
   17  */
   18 
   19 /*
   20  * I2C bus bit-banging through GPIO pins.
   21  */
   22 
   23 #include <sys/param.h>
   24 #include <sys/systm.h>
   25 #include <sys/device.h>
   26 #include <sys/gpio.h>
   27 #include <sys/rwlock.h>
   28 
   29 #include <dev/gpio/gpiovar.h>
   30 
   31 #include <dev/i2c/i2cvar.h>
   32 #include <dev/i2c/i2c_bitbang.h>
   33 
   34 #define GPIOIIC_PIN_SDA         0
   35 #define GPIOIIC_PIN_SCL         1
   36 #define GPIOIIC_NPINS           2
   37 
   38 #define GPIOIIC_SDA             0x01
   39 #define GPIOIIC_SCL             0x02
   40 
   41 struct gpioiic_softc {
   42         struct device           sc_dev;
   43 
   44         void *                  sc_gpio;
   45         struct gpio_pinmap      sc_map;
   46         int                     __map[GPIOIIC_NPINS];
   47 
   48         struct i2c_controller   sc_i2c_tag;
   49         struct rwlock           sc_i2c_lock;
   50 
   51         int                     sc_sda;
   52         int                     sc_scl;
   53 };
   54 
   55 int             gpioiic_match(struct device *, void *, void *);
   56 void            gpioiic_attach(struct device *, struct device *, void *);
   57 int             gpioiic_detach(struct device *, int);
   58 
   59 int             gpioiic_i2c_acquire_bus(void *, int);
   60 void            gpioiic_i2c_release_bus(void *, int);
   61 int             gpioiic_i2c_send_start(void *, int);
   62 int             gpioiic_i2c_send_stop(void *, int);
   63 int             gpioiic_i2c_initiate_xfer(void *, i2c_addr_t, int);
   64 int             gpioiic_i2c_read_byte(void *, u_int8_t *, int);
   65 int             gpioiic_i2c_write_byte(void *, u_int8_t, int);
   66 
   67 void            gpioiic_bb_set_bits(void *, u_int32_t);
   68 void            gpioiic_bb_set_dir(void *, u_int32_t);
   69 u_int32_t       gpioiic_bb_read_bits(void *);
   70 
   71 struct cfattach gpioiic_ca = {
   72         sizeof(struct gpioiic_softc),
   73         gpioiic_match,
   74         gpioiic_attach,
   75         gpioiic_detach
   76 };
   77 
   78 struct cfdriver gpioiic_cd = {
   79         NULL, "gpioiic", DV_DULL
   80 };
   81 
   82 static const struct i2c_bitbang_ops gpioiic_bbops = {
   83         gpioiic_bb_set_bits,
   84         gpioiic_bb_set_dir,
   85         gpioiic_bb_read_bits,
   86         { GPIOIIC_SDA, GPIOIIC_SCL, GPIOIIC_SDA, 0 }
   87 };
   88 
   89 int
   90 gpioiic_match(struct device *parent, void *match, void *aux)
   91 {
   92         struct cfdata *cf = match;
   93 
   94         return (strcmp(cf->cf_driver->cd_name, "gpioiic") == 0);
   95 }
   96 
   97 void
   98 gpioiic_attach(struct device *parent, struct device *self, void *aux)
   99 {
  100         struct gpioiic_softc *sc = (struct gpioiic_softc *)self;
  101         struct gpio_attach_args *ga = aux;
  102         struct i2cbus_attach_args iba;
  103         int caps;
  104 
  105         /* Check that we have enough pins */
  106         if (gpio_npins(ga->ga_mask) != GPIOIIC_NPINS) {
  107                 printf(": invalid pin mask\n");
  108                 return;
  109         }
  110 
  111         /* Map pins */
  112         sc->sc_gpio = ga->ga_gpio;
  113         sc->sc_map.pm_map = sc->__map;
  114         if (gpio_pin_map(sc->sc_gpio, ga->ga_offset, ga->ga_mask,
  115             &sc->sc_map)) {
  116                 printf(": can't map pins\n");
  117                 return;
  118         }
  119 
  120         /* Configure SDA pin */
  121         caps = gpio_pin_caps(sc->sc_gpio, &sc->sc_map, GPIOIIC_PIN_SDA);
  122         if (!(caps & GPIO_PIN_OUTPUT)) {
  123                 printf(": SDA pin is unable to drive output\n");
  124                 goto fail;
  125         }
  126         if (!(caps & GPIO_PIN_INPUT)) {
  127                 printf(": SDA pin is unable to read input\n");
  128                 goto fail;
  129         }
  130         printf(": SDA[%d]", sc->sc_map.pm_map[GPIOIIC_PIN_SDA]);
  131         sc->sc_sda = GPIO_PIN_OUTPUT;
  132         if (caps & GPIO_PIN_OPENDRAIN) {
  133                 printf(" open-drain");
  134                 sc->sc_sda |= GPIO_PIN_OPENDRAIN;
  135         } else if ((caps & GPIO_PIN_PUSHPULL) && (caps & GPIO_PIN_TRISTATE)) {
  136                 printf(" push-pull tri-state");
  137                 sc->sc_sda |= GPIO_PIN_PUSHPULL;
  138         }
  139         if (caps & GPIO_PIN_PULLUP) {
  140                 printf(" pull-up");
  141                 sc->sc_sda |= GPIO_PIN_PULLUP;
  142         }
  143         gpio_pin_ctl(sc->sc_gpio, &sc->sc_map, GPIOIIC_PIN_SDA, sc->sc_sda);
  144 
  145         /* Configure SCL pin */
  146         caps = gpio_pin_caps(sc->sc_gpio, &sc->sc_map, GPIOIIC_PIN_SCL);
  147         if (!(caps & GPIO_PIN_OUTPUT)) {
  148                 printf(": SCL pin is unable to drive output\n");
  149                 goto fail;
  150         }
  151         printf(", SCL[%d]", sc->sc_map.pm_map[GPIOIIC_PIN_SCL]);
  152         sc->sc_scl = GPIO_PIN_OUTPUT;
  153         if (caps & GPIO_PIN_OPENDRAIN) {
  154                 printf(" open-drain");
  155                 sc->sc_scl |= GPIO_PIN_OPENDRAIN;
  156                 if (caps & GPIO_PIN_PULLUP) {
  157                         printf(" pull-up");
  158                         sc->sc_scl |= GPIO_PIN_PULLUP;
  159                 }
  160         } else if (caps & GPIO_PIN_PUSHPULL) {
  161                 printf(" push-pull");
  162                 sc->sc_scl |= GPIO_PIN_PUSHPULL;
  163         }
  164         gpio_pin_ctl(sc->sc_gpio, &sc->sc_map, GPIOIIC_PIN_SCL, sc->sc_scl);
  165 
  166         printf("\n");
  167 
  168         /* Attach I2C bus */
  169         rw_init(&sc->sc_i2c_lock, "iiclk");
  170         sc->sc_i2c_tag.ic_cookie = sc;
  171         sc->sc_i2c_tag.ic_acquire_bus = gpioiic_i2c_acquire_bus;
  172         sc->sc_i2c_tag.ic_release_bus = gpioiic_i2c_release_bus;
  173         sc->sc_i2c_tag.ic_send_start = gpioiic_i2c_send_start;
  174         sc->sc_i2c_tag.ic_send_stop = gpioiic_i2c_send_stop;
  175         sc->sc_i2c_tag.ic_initiate_xfer = gpioiic_i2c_initiate_xfer;
  176         sc->sc_i2c_tag.ic_read_byte = gpioiic_i2c_read_byte;
  177         sc->sc_i2c_tag.ic_write_byte = gpioiic_i2c_write_byte;
  178 
  179         bzero(&iba, sizeof(iba));
  180         iba.iba_name = "iic";
  181         iba.iba_tag = &sc->sc_i2c_tag;
  182         config_found(self, &iba, iicbus_print);
  183 
  184         return;
  185 
  186 fail:
  187         gpio_pin_unmap(sc->sc_gpio, &sc->sc_map);
  188 }
  189 
  190 int
  191 gpioiic_detach(struct device *self, int flags)
  192 {
  193         return (0);
  194 }
  195 
  196 int
  197 gpioiic_i2c_acquire_bus(void *cookie, int flags)
  198 {
  199         struct gpioiic_softc *sc = cookie;
  200 
  201         if (cold || (flags & I2C_F_POLL))
  202                 return (0);
  203 
  204         return (rw_enter(&sc->sc_i2c_lock, RW_WRITE | RW_INTR));
  205 }
  206 
  207 void
  208 gpioiic_i2c_release_bus(void *cookie, int flags)
  209 {
  210         struct gpioiic_softc *sc = cookie;
  211 
  212         if (cold || (flags & I2C_F_POLL))
  213                 return;
  214 
  215         rw_exit(&sc->sc_i2c_lock);
  216 }
  217 
  218 int
  219 gpioiic_i2c_send_start(void *cookie, int flags)
  220 {
  221         return (i2c_bitbang_send_start(cookie, flags, &gpioiic_bbops));
  222 }
  223 
  224 int
  225 gpioiic_i2c_send_stop(void *cookie, int flags)
  226 {
  227         return (i2c_bitbang_send_stop(cookie, flags, &gpioiic_bbops));
  228 }
  229 
  230 int
  231 gpioiic_i2c_initiate_xfer(void *cookie, i2c_addr_t addr, int flags)
  232 {
  233         return (i2c_bitbang_initiate_xfer(cookie, addr, flags, &gpioiic_bbops));
  234 }
  235 
  236 int
  237 gpioiic_i2c_read_byte(void *cookie, u_int8_t *bytep, int flags)
  238 {
  239         return (i2c_bitbang_read_byte(cookie, bytep, flags, &gpioiic_bbops));
  240 }
  241 
  242 int
  243 gpioiic_i2c_write_byte(void *cookie, u_int8_t byte, int flags)
  244 {
  245         return (i2c_bitbang_write_byte(cookie, byte, flags, &gpioiic_bbops));
  246 }
  247 
  248 void
  249 gpioiic_bb_set_bits(void *cookie, u_int32_t bits)
  250 {
  251         struct gpioiic_softc *sc = cookie;
  252 
  253         gpio_pin_write(sc->sc_gpio, &sc->sc_map, GPIOIIC_PIN_SDA,
  254             bits & GPIOIIC_SDA ? GPIO_PIN_HIGH : GPIO_PIN_LOW);
  255         gpio_pin_write(sc->sc_gpio, &sc->sc_map, GPIOIIC_PIN_SCL,
  256             bits & GPIOIIC_SCL ? GPIO_PIN_HIGH : GPIO_PIN_LOW);
  257 }
  258 
  259 void
  260 gpioiic_bb_set_dir(void *cookie, u_int32_t bits)
  261 {
  262         struct gpioiic_softc *sc = cookie;
  263         int sda = sc->sc_sda;
  264 
  265         sda &= ~(GPIO_PIN_INPUT | GPIO_PIN_OUTPUT | GPIO_PIN_TRISTATE);
  266         sda |= (bits & GPIOIIC_SDA ? GPIO_PIN_OUTPUT : GPIO_PIN_INPUT);
  267         if ((sda & GPIO_PIN_PUSHPULL) && !(bits & GPIOIIC_SDA))
  268                 sda |= GPIO_PIN_TRISTATE;
  269         if (sc->sc_sda != sda) {
  270                 sc->sc_sda = sda;
  271                 gpio_pin_ctl(sc->sc_gpio, &sc->sc_map, GPIOIIC_PIN_SDA,
  272                     sc->sc_sda);
  273         }
  274 }
  275 
  276 u_int32_t
  277 gpioiic_bb_read_bits(void *cookie)
  278 {
  279         struct gpioiic_softc *sc = cookie;
  280 
  281         return (gpio_pin_read(sc->sc_gpio, &sc->sc_map,
  282             GPIOIIC_PIN_SDA) == GPIO_PIN_HIGH ? GPIOIIC_SDA : 0);
  283 }

/* [<][>][^][v][top][bottom][index][help] */