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/freescale/vybrid/vf_i2c.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) 2014 Ruslan Bukin <br@bsdpad.com>
    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 
   27 /*
   28  * Vybrid Family Inter-Integrated Circuit (I2C)
   29  * Chapter 48, Vybrid Reference Manual, Rev. 5, 07/2013
   30  */
   31 
   32 /*
   33  * This driver is based on the I2C driver for i.MX
   34  */
   35 
   36 #include <sys/cdefs.h>
   37 __FBSDID("$FreeBSD$");
   38 
   39 #include <sys/param.h>
   40 #include <sys/systm.h>
   41 #include <sys/bus.h>
   42 #include <sys/kernel.h>
   43 #include <sys/module.h>
   44 #include <sys/malloc.h>
   45 #include <sys/rman.h>
   46 #include <sys/timeet.h>
   47 #include <sys/timetc.h>
   48 
   49 #include <dev/iicbus/iiconf.h>
   50 #include <dev/iicbus/iicbus.h>
   51 
   52 #include "iicbus_if.h"
   53 
   54 #include <dev/fdt/fdt_common.h>
   55 #include <dev/ofw/openfirm.h>
   56 #include <dev/ofw/ofw_bus.h>
   57 #include <dev/ofw/ofw_bus_subr.h>
   58 
   59 #include <machine/bus.h>
   60 #include <machine/cpu.h>
   61 #include <machine/intr.h>
   62 
   63 #include <arm/freescale/vybrid/vf_common.h>
   64 
   65 #define I2C_IBAD        0x0     /* I2C Bus Address Register */
   66 #define I2C_IBFD        0x1     /* I2C Bus Frequency Divider Register */
   67 #define I2C_IBCR        0x2     /* I2C Bus Control Register */
   68 #define  IBCR_MDIS              (1 << 7) /* Module disable. */
   69 #define  IBCR_IBIE              (1 << 6) /* I-Bus Interrupt Enable. */
   70 #define  IBCR_MSSL              (1 << 5) /* Master/Slave mode select. */
   71 #define  IBCR_TXRX              (1 << 4) /* Transmit/Receive mode select. */
   72 #define  IBCR_NOACK             (1 << 3) /* Data Acknowledge disable. */
   73 #define  IBCR_RSTA              (1 << 2) /* Repeat Start. */
   74 #define  IBCR_DMAEN             (1 << 1) /* DMA Enable. */
   75 #define I2C_IBSR        0x3     /* I2C Bus Status Register */
   76 #define  IBSR_TCF               (1 << 7) /* Transfer complete. */
   77 #define  IBSR_IAAS              (1 << 6) /* Addressed as a slave. */
   78 #define  IBSR_IBB               (1 << 5) /* Bus busy. */
   79 #define  IBSR_IBAL              (1 << 4) /* Arbitration Lost. */
   80 #define  IBSR_SRW               (1 << 2) /* Slave Read/Write. */
   81 #define  IBSR_IBIF              (1 << 1) /* I-Bus Interrupt Flag. */
   82 #define  IBSR_RXAK              (1 << 0) /* Received Acknowledge. */
   83 #define I2C_IBDR        0x4     /* I2C Bus Data I/O Register */
   84 #define I2C_IBIC        0x5     /* I2C Bus Interrupt Config Register */
   85 #define  IBIC_BIIE              (1 << 7) /* Bus Idle Interrupt Enable bit. */
   86 #define I2C_IBDBG       0x6     /* I2C Bus Debug Register */
   87 
   88 #ifdef DEBUG
   89 #define vf_i2c_dbg(_sc, fmt, args...) \
   90         device_printf((_sc)->dev, fmt, ##args)
   91 #else
   92 #define vf_i2c_dbg(_sc, fmt, args...)
   93 #endif
   94 
   95 static int i2c_repeated_start(device_t, u_char, int);
   96 static int i2c_start(device_t, u_char, int);
   97 static int i2c_stop(device_t);
   98 static int i2c_reset(device_t, u_char, u_char, u_char *);
   99 static int i2c_read(device_t, char *, int, int *, int, int);
  100 static int i2c_write(device_t, const char *, int, int *, int);
  101 
  102 struct i2c_softc {
  103         struct resource         *res[2];
  104         bus_space_tag_t         bst;
  105         bus_space_handle_t      bsh;
  106         device_t                dev;
  107         device_t                iicbus;
  108         struct mtx              mutex;
  109 };
  110 
  111 static struct resource_spec i2c_spec[] = {
  112         { SYS_RES_MEMORY,       0,      RF_ACTIVE },
  113         { SYS_RES_IRQ,          0,      RF_ACTIVE },
  114         { -1, 0 }
  115 };
  116 
  117 static int
  118 i2c_probe(device_t dev)
  119 {
  120 
  121         if (!ofw_bus_status_okay(dev))
  122                 return (ENXIO);
  123 
  124         if (!ofw_bus_is_compatible(dev, "fsl,mvf600-i2c"))
  125                 return (ENXIO);
  126 
  127         device_set_desc(dev, "Vybrid Family Inter-Integrated Circuit (I2C)");
  128         return (BUS_PROBE_DEFAULT);
  129 }
  130 
  131 static int
  132 i2c_attach(device_t dev)
  133 {
  134         struct i2c_softc *sc;
  135 
  136         sc = device_get_softc(dev);
  137         sc->dev = dev;
  138 
  139         mtx_init(&sc->mutex, device_get_nameunit(dev), "I2C", MTX_DEF);
  140 
  141         if (bus_alloc_resources(dev, i2c_spec, sc->res)) {
  142                 device_printf(dev, "could not allocate resources\n");
  143                 return (ENXIO);
  144         }
  145 
  146         /* Memory interface */
  147         sc->bst = rman_get_bustag(sc->res[0]);
  148         sc->bsh = rman_get_bushandle(sc->res[0]);
  149 
  150         WRITE1(sc, I2C_IBIC, IBIC_BIIE);
  151 
  152         sc->iicbus = device_add_child(dev, "iicbus", -1);
  153         if (sc->iicbus == NULL) {
  154                 device_printf(dev, "could not add iicbus child");
  155                 mtx_destroy(&sc->mutex);
  156                 return (ENXIO);
  157         }
  158 
  159         bus_generic_attach(dev);
  160 
  161         return (0);
  162 }
  163 
  164 /* Wait for transfer interrupt flag */
  165 static int
  166 wait_for_iif(struct i2c_softc *sc)
  167 {
  168         int retry;
  169 
  170         retry = 1000;
  171         while (retry --) {
  172                 if (READ1(sc, I2C_IBSR) & IBSR_IBIF) {
  173                         WRITE1(sc, I2C_IBSR, IBSR_IBIF);
  174                         return (IIC_NOERR);
  175                 }
  176                 DELAY(10);
  177         }
  178 
  179         return (IIC_ETIMEOUT);
  180 }
  181 
  182 /* Wait for free bus */
  183 static int
  184 wait_for_nibb(struct i2c_softc *sc)
  185 {
  186         int retry;
  187 
  188         retry = 1000;
  189         while (retry --) {
  190                 if ((READ1(sc, I2C_IBSR) & IBSR_IBB) == 0)
  191                         return (IIC_NOERR);
  192                 DELAY(10);
  193         }
  194 
  195         return (IIC_ETIMEOUT);
  196 }
  197 
  198 /* Wait for transfer complete+interrupt flag */
  199 static int
  200 wait_for_icf(struct i2c_softc *sc)
  201 {
  202         int retry;
  203 
  204         retry = 1000;
  205         while (retry --) {
  206                 if (READ1(sc, I2C_IBSR) & IBSR_TCF) {
  207                         if (READ1(sc, I2C_IBSR) & IBSR_IBIF) {
  208                                 WRITE1(sc, I2C_IBSR, IBSR_IBIF);
  209                                 return (IIC_NOERR);
  210                         }
  211                 }
  212                 DELAY(10);
  213         }
  214 
  215         return (IIC_ETIMEOUT);
  216 }
  217 
  218 static int
  219 i2c_repeated_start(device_t dev, u_char slave, int timeout)
  220 {
  221         struct i2c_softc *sc;
  222         int error;
  223         int reg;
  224 
  225         sc = device_get_softc(dev);
  226 
  227         vf_i2c_dbg(sc, "i2c repeated start\n");
  228 
  229         mtx_lock(&sc->mutex);
  230 
  231         WRITE1(sc, I2C_IBAD, slave);
  232 
  233         if ((READ1(sc, I2C_IBSR) & IBSR_IBB) == 0) {
  234                 mtx_unlock(&sc->mutex);
  235                 return (IIC_EBUSERR);
  236         }
  237 
  238         /* Set repeated start condition */
  239         DELAY(10);
  240 
  241         reg = READ1(sc, I2C_IBCR);
  242         reg |= (IBCR_RSTA | IBCR_IBIE);
  243         WRITE1(sc, I2C_IBCR, reg);
  244 
  245         DELAY(10);
  246 
  247         /* Write target address - LSB is R/W bit */
  248         WRITE1(sc, I2C_IBDR, slave);
  249 
  250         error = wait_for_iif(sc);
  251 
  252         mtx_unlock(&sc->mutex);
  253 
  254         if (error)
  255                 return (error);
  256 
  257         return (IIC_NOERR);
  258 }
  259 
  260 static int
  261 i2c_start(device_t dev, u_char slave, int timeout)
  262 {
  263         struct i2c_softc *sc;
  264         int error;
  265         int reg;
  266 
  267         sc = device_get_softc(dev);
  268 
  269         vf_i2c_dbg(sc, "i2c start\n");
  270 
  271         mtx_lock(&sc->mutex);
  272 
  273         WRITE1(sc, I2C_IBAD, slave);
  274 
  275         if (READ1(sc, I2C_IBSR) & IBSR_IBB) {
  276                 mtx_unlock(&sc->mutex);
  277                 vf_i2c_dbg(sc, "cant i2c start: IIC_EBUSBSY\n");
  278                 return (IIC_EBUSERR);
  279         }
  280 
  281         /* Set start condition */
  282         reg = (IBCR_MSSL | IBCR_NOACK | IBCR_IBIE);
  283         WRITE1(sc, I2C_IBCR, reg);
  284 
  285         DELAY(100);
  286 
  287         reg |= (IBCR_TXRX);
  288         WRITE1(sc, I2C_IBCR, reg);
  289 
  290         /* Write target address - LSB is R/W bit */
  291         WRITE1(sc, I2C_IBDR, slave);
  292 
  293         error = wait_for_iif(sc);
  294 
  295         mtx_unlock(&sc->mutex);
  296         if (error) {
  297                 vf_i2c_dbg(sc, "cant i2c start: iif error\n");
  298                 return (error);
  299         }
  300 
  301         return (IIC_NOERR);
  302 }
  303 
  304 static int
  305 i2c_stop(device_t dev)
  306 {
  307         struct i2c_softc *sc;
  308 
  309         sc = device_get_softc(dev);
  310 
  311         vf_i2c_dbg(sc, "i2c stop\n");
  312 
  313         mtx_lock(&sc->mutex);
  314 
  315         WRITE1(sc, I2C_IBCR, IBCR_NOACK | IBCR_IBIE);
  316 
  317         DELAY(100);
  318 
  319         /* Reset controller if bus still busy after STOP */
  320         if (wait_for_nibb(sc) == IIC_ETIMEOUT) {
  321                 WRITE1(sc, I2C_IBCR, IBCR_MDIS);
  322                 DELAY(1000);
  323                 WRITE1(sc, I2C_IBCR, IBCR_NOACK);
  324         }
  325         mtx_unlock(&sc->mutex);
  326 
  327         return (IIC_NOERR);
  328 }
  329 
  330 static int
  331 i2c_reset(device_t dev, u_char speed, u_char addr, u_char *oldadr)
  332 {
  333         struct i2c_softc *sc;
  334 
  335         sc = device_get_softc(dev);
  336 
  337         vf_i2c_dbg(sc, "i2c reset\n");
  338 
  339         switch (speed) {
  340         case IIC_FAST:
  341         case IIC_SLOW:
  342         case IIC_UNKNOWN:
  343         case IIC_FASTEST:
  344         default:
  345                 break;
  346         }
  347 
  348         mtx_lock(&sc->mutex);
  349         WRITE1(sc, I2C_IBCR, IBCR_MDIS);
  350 
  351         DELAY(1000);
  352 
  353         WRITE1(sc, I2C_IBFD, 20);
  354         WRITE1(sc, I2C_IBCR, 0x0); /* Enable i2c */
  355 
  356         DELAY(1000);
  357 
  358         mtx_unlock(&sc->mutex);
  359 
  360         return (IIC_NOERR);
  361 }
  362 
  363 static int
  364 i2c_read(device_t dev, char *buf, int len, int *read, int last, int delay)
  365 {
  366         struct i2c_softc *sc;
  367         int error;
  368 
  369         sc = device_get_softc(dev);
  370 
  371         vf_i2c_dbg(sc, "i2c read\n");
  372 
  373         *read = 0;
  374 
  375         mtx_lock(&sc->mutex);
  376 
  377         if (len) {
  378                 if (len == 1)
  379                         WRITE1(sc, I2C_IBCR, IBCR_IBIE | IBCR_MSSL |    \
  380                             IBCR_NOACK);
  381                 else
  382                         WRITE1(sc, I2C_IBCR, IBCR_IBIE | IBCR_MSSL);
  383 
  384                 /* dummy read */
  385                 READ1(sc, I2C_IBDR);
  386                 DELAY(1000);
  387         }
  388 
  389         while (*read < len) {
  390                 error = wait_for_icf(sc);
  391                 if (error) {
  392                         mtx_unlock(&sc->mutex);
  393                         return (error);
  394                 }
  395 
  396                 if ((*read == len - 2) && last) {
  397                         /* NO ACK on last byte */
  398                         WRITE1(sc, I2C_IBCR, IBCR_IBIE | IBCR_MSSL |    \
  399                             IBCR_NOACK);
  400                 }
  401 
  402                 if ((*read == len - 1) && last) {
  403                         /* Transfer done, remove master bit */
  404                         WRITE1(sc, I2C_IBCR, IBCR_IBIE | IBCR_NOACK);
  405                 }
  406 
  407                 *buf++ = READ1(sc, I2C_IBDR);
  408                 (*read)++;
  409         }
  410         mtx_unlock(&sc->mutex);
  411 
  412         return (IIC_NOERR);
  413 }
  414 
  415 static int
  416 i2c_write(device_t dev, const char *buf, int len, int *sent, int timeout)
  417 {
  418         struct i2c_softc *sc;
  419         int error;
  420 
  421         sc = device_get_softc(dev);
  422 
  423         vf_i2c_dbg(sc, "i2c write\n");
  424 
  425         *sent = 0;
  426 
  427         mtx_lock(&sc->mutex);
  428         while (*sent < len) {
  429 
  430                 WRITE1(sc, I2C_IBDR, *buf++);
  431 
  432                 error = wait_for_iif(sc);
  433                 if (error) {
  434                         mtx_unlock(&sc->mutex);
  435                         return (error);
  436                 }
  437 
  438                 (*sent)++;
  439         }
  440         mtx_unlock(&sc->mutex);
  441 
  442         return (IIC_NOERR);
  443 }
  444 
  445 static device_method_t i2c_methods[] = {
  446         DEVMETHOD(device_probe,         i2c_probe),
  447         DEVMETHOD(device_attach,        i2c_attach),
  448 
  449         DEVMETHOD(iicbus_callback,              iicbus_null_callback),
  450         DEVMETHOD(iicbus_repeated_start,        i2c_repeated_start),
  451         DEVMETHOD(iicbus_start,                 i2c_start),
  452         DEVMETHOD(iicbus_stop,                  i2c_stop),
  453         DEVMETHOD(iicbus_reset,                 i2c_reset),
  454         DEVMETHOD(iicbus_read,                  i2c_read),
  455         DEVMETHOD(iicbus_write,                 i2c_write),
  456         DEVMETHOD(iicbus_transfer,              iicbus_transfer_gen),
  457 
  458         { 0, 0 }
  459 };
  460 
  461 static driver_t i2c_driver = {
  462         "i2c",
  463         i2c_methods,
  464         sizeof(struct i2c_softc),
  465 };
  466 
  467 static devclass_t i2c_devclass;
  468 
  469 DRIVER_MODULE(i2c, simplebus, i2c_driver, i2c_devclass, 0, 0);
  470 DRIVER_MODULE(iicbus, i2c, iicbus_driver, iicbus_devclass, 0, 0);

Cache object: 6928e808eac143b97849882b375104ba


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