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/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) 2008-2009 Semihalf, Michal Hajduk
    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 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 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 #include <sys/cdefs.h>
   28 __FBSDID("$FreeBSD$");
   29 
   30 #include <sys/param.h>
   31 #include <sys/systm.h>
   32 #include <sys/bus.h>
   33 #include <sys/kernel.h>
   34 #include <sys/module.h>
   35 #include <sys/resource.h>
   36 
   37 #include <machine/bus.h>
   38 #include <machine/resource.h>
   39 #include <machine/ocpbus.h>
   40 #include <sys/rman.h>
   41 
   42 #include <sys/lock.h>
   43 #include <sys/mutex.h>
   44 
   45 #include <dev/iicbus/iiconf.h>
   46 #include <dev/iicbus/iicbus.h>
   47 #include "iicbus_if.h"
   48 
   49 #include <powerpc/mpc85xx/ocpbus.h>
   50 
   51 #define I2C_ADDR_REG            0x00 /* I2C slave address register */
   52 #define I2C_FDR_REG             0x04 /* I2C frequency divider register */
   53 #define I2C_CONTROL_REG         0x08 /* I2C control register */
   54 #define I2C_STATUS_REG          0x0C /* I2C status register */
   55 #define I2C_DATA_REG            0x10 /* I2C data register */
   56 #define I2C_DFSRR_REG           0x14 /* I2C Digital Filter Sampling rate */
   57 #define I2C_ENABLE              0x80 /* Module enable - interrupt disable */
   58 #define I2CSR_RXAK              0x01 /* Received acknowledge */
   59 #define I2CSR_MCF               (1<<7) /* Data transfer */
   60 #define I2CSR_MASS              (1<<6) /* Addressed as a slave */
   61 #define I2CSR_MBB               (1<<5) /* Bus busy */
   62 #define I2CSR_MAL               (1<<4) /* Arbitration lost */
   63 #define I2CSR_SRW               (1<<2) /* Slave read/write */
   64 #define I2CSR_MIF               (1<<1) /* Module interrupt */
   65 #define I2CCR_MEN               (1<<7) /* Module enable */
   66 #define I2CCR_MSTA              (1<<5) /* Master/slave mode */
   67 #define I2CCR_MTX               (1<<4) /* Transmit/receive mode */
   68 #define I2CCR_TXAK              (1<<3) /* Transfer acknowledge */
   69 #define I2CCR_RSTA              (1<<2) /* Repeated START */
   70 
   71 #define I2C_BAUD_RATE_FAST      0x31
   72 #define I2C_BAUD_RATE_DEF       0x3F
   73 #define I2C_DFSSR_DIV           0x10
   74 
   75 #define DEBUG
   76 #undef DEBUG
   77 
   78 #ifdef  DEBUG
   79 #define debugf(fmt, args...) do { printf("%s(): ", __func__); printf(fmt,##args); } while (0)
   80 #else
   81 #define debugf(fmt, args...)
   82 #endif
   83 
   84 struct i2c_softc {
   85         device_t                dev;
   86         device_t                iicbus;
   87         struct resource         *res;
   88         struct mtx              mutex;
   89         int                     rid;
   90         bus_space_handle_t      bsh;
   91         bus_space_tag_t         bst;
   92 };
   93 
   94 static int i2c_probe(device_t);
   95 static int i2c_attach(device_t);
   96 
   97 static int i2c_repeated_start(device_t dev, u_char slave, int timeout);
   98 static int i2c_start(device_t dev, u_char slave, int timeout);
   99 static int i2c_stop(device_t dev);
  100 static int i2c_reset(device_t dev, u_char speed, u_char addr, u_char *oldaddr);
  101 static int i2c_read(device_t dev, char *buf, int len, int *read, int last, int delay);
  102 static int i2c_write(device_t dev, const char *buf, int len, int *sent, int timeout);
  103 
  104 static device_method_t i2c_methods[] = {
  105         DEVMETHOD(device_probe,                 i2c_probe),
  106         DEVMETHOD(device_attach,                i2c_attach),
  107 
  108         DEVMETHOD(iicbus_callback,              iicbus_null_callback),
  109         DEVMETHOD(iicbus_repeated_start,        i2c_repeated_start),
  110         DEVMETHOD(iicbus_start,                 i2c_start),
  111         DEVMETHOD(iicbus_stop,                  i2c_stop),
  112         DEVMETHOD(iicbus_reset,                 i2c_reset),
  113         DEVMETHOD(iicbus_read,                  i2c_read),
  114         DEVMETHOD(iicbus_write,                 i2c_write),
  115         DEVMETHOD(iicbus_transfer,              iicbus_transfer_gen),
  116 
  117         { 0, 0 }
  118 };
  119 
  120 static driver_t i2c_driver = {
  121         "i2c",
  122         i2c_methods,
  123         sizeof(struct i2c_softc),
  124 };
  125 static devclass_t  i2c_devclass;
  126 
  127 DRIVER_MODULE(i2c, ocpbus, i2c_driver, i2c_devclass, 0, 0);
  128 DRIVER_MODULE(iicbus, i2c, iicbus_driver, iicbus_devclass, 0, 0);
  129 
  130 static __inline void
  131 i2c_write_reg(struct i2c_softc *sc, bus_size_t off, uint8_t val)
  132 {
  133 
  134         bus_space_write_1(sc->bst, sc->bsh, off, val);
  135 }
  136 
  137 static __inline uint8_t
  138 i2c_read_reg(struct i2c_softc *sc, bus_size_t off)
  139 {
  140 
  141         return (bus_space_read_1(sc->bst, sc->bsh, off));
  142 }
  143 
  144 static __inline void
  145 i2c_flag_set(struct i2c_softc *sc, bus_size_t off, uint8_t mask)
  146 {
  147         uint8_t status;
  148 
  149         status = i2c_read_reg(sc, off);
  150         status |= mask;
  151         i2c_write_reg(sc, off, status);
  152 }
  153 
  154 static int
  155 i2c_do_wait(device_t dev, struct i2c_softc *sc, int write, int start)
  156 {
  157         int err;
  158         uint8_t status;
  159 
  160         status = i2c_read_reg(sc,I2C_STATUS_REG);
  161         if (status & I2CSR_MIF) {
  162                 if (write && start && (status & I2CSR_RXAK)) {
  163                         debugf("no ack %s", start ?
  164                             "after sending slave address" : "");
  165                         err = IIC_ENOACK;
  166                         goto error;
  167                 }
  168                 if (status & I2CSR_MAL) {
  169                         debugf("arbitration lost");
  170                         err = IIC_EBUSERR;
  171                         goto error;
  172                 }
  173                 if (!write && !(status & I2CSR_MCF)) {
  174                         debugf("transfer unfinished");
  175                         err = IIC_EBUSERR;
  176                         goto error;
  177                 }
  178         }
  179 
  180         return (IIC_NOERR);
  181 
  182 error:
  183         i2c_write_reg(sc, I2C_STATUS_REG, 0x0);
  184         i2c_write_reg(sc, I2C_CONTROL_REG, I2CCR_MEN | I2CCR_TXAK);
  185         return (err);
  186 }
  187 
  188 static int
  189 i2c_probe(device_t dev)
  190 {
  191         device_t parent;
  192         struct i2c_softc *sc;
  193         uintptr_t devtype;
  194         int error;
  195 
  196         parent = device_get_parent(dev);
  197 
  198         error = BUS_READ_IVAR(parent, dev, OCPBUS_IVAR_DEVTYPE, &devtype);
  199 
  200         if (error)
  201                 return (error);
  202 
  203         if (devtype != OCPBUS_DEVTYPE_I2C)
  204                 return (ENXIO);
  205 
  206         sc = device_get_softc(dev);
  207         sc->rid = 0;
  208 
  209         sc->res = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &sc->rid,
  210             RF_ACTIVE);
  211         if (sc->res == NULL) {
  212                 device_printf(dev, "could not allocate resources");
  213                 return (ENXIO);
  214         }
  215 
  216         sc->bst = rman_get_bustag(sc->res);
  217         sc->bsh = rman_get_bushandle(sc->res);
  218 
  219         /* Enable I2C */
  220         i2c_write_reg(sc, I2C_CONTROL_REG, I2C_ENABLE);
  221         bus_release_resource(dev, SYS_RES_MEMORY, sc->rid, sc->res);
  222         device_set_desc(dev, "I2C bus controller");
  223 
  224         return (BUS_PROBE_DEFAULT);
  225 }
  226 
  227 static int
  228 i2c_attach(device_t dev)
  229 {
  230         struct i2c_softc *sc;
  231         sc = device_get_softc(dev);
  232 
  233         sc->dev = dev;
  234         sc->rid = 0;
  235 
  236         mtx_init(&sc->mutex, device_get_nameunit(dev), "I2C", MTX_DEF);
  237 
  238         sc->res = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &sc->rid,
  239             RF_ACTIVE);
  240         if (sc->res == NULL) {
  241                 device_printf(dev, "could not allocate resources");
  242                 mtx_destroy(&sc->mutex);
  243                 return (ENXIO);
  244         }
  245 
  246         sc->bst = rman_get_bustag(sc->res);
  247         sc->bsh = rman_get_bushandle(sc->res);
  248 
  249         sc->iicbus = device_add_child(dev, "iicbus", -1);
  250         if (sc->iicbus == NULL) {
  251                 device_printf(dev, "could not add iicbus child");
  252                 mtx_destroy(&sc->mutex);
  253                 return (ENXIO);
  254         }
  255 
  256         bus_generic_attach(dev);
  257         return (IIC_NOERR);
  258 }
  259 static int
  260 i2c_repeated_start(device_t dev, u_char slave, int timeout)
  261 {
  262         struct i2c_softc *sc;
  263         int error;
  264         
  265         sc = device_get_softc(dev);
  266 
  267         mtx_lock(&sc->mutex);
  268         /* Set repeated start condition */
  269         i2c_flag_set(sc, I2C_CONTROL_REG ,I2CCR_RSTA);
  270         /* Write target address - LSB is R/W bit */
  271         i2c_write_reg(sc, I2C_DATA_REG, slave);
  272         DELAY(1250);
  273 
  274         error = i2c_do_wait(dev, sc, 1, 1);
  275         mtx_unlock(&sc->mutex);
  276 
  277         if (error)
  278                 return (error);
  279 
  280         return (IIC_NOERR);
  281 }
  282 
  283 static int
  284 i2c_start(device_t dev, u_char slave, int timeout)
  285 {
  286         struct i2c_softc *sc;
  287         uint8_t status;
  288         int error;
  289 
  290         sc = device_get_softc(dev);
  291         DELAY(1000);
  292 
  293         mtx_lock(&sc->mutex);
  294         status = i2c_read_reg(sc, I2C_STATUS_REG);
  295         /* Check if bus is idle or busy */
  296         if (status & I2CSR_MBB) {
  297                 debugf("bus busy");
  298                 mtx_unlock(&sc->mutex);
  299                 i2c_stop(dev);
  300                 return (IIC_EBUSBSY);
  301         }
  302 
  303         /* Set start condition */
  304         i2c_write_reg(sc, I2C_CONTROL_REG, I2CCR_MEN | I2CCR_MSTA | I2CCR_MTX);
  305         /* Write target address - LSB is R/W bit */
  306         i2c_write_reg(sc, I2C_DATA_REG, slave);
  307         DELAY(1250);
  308 
  309         error = i2c_do_wait(dev, sc, 1, 1);
  310 
  311         mtx_unlock(&sc->mutex);
  312         if (error)
  313                 return (error);
  314 
  315         return (IIC_NOERR);
  316 }
  317 
  318 static int
  319 i2c_stop(device_t dev)
  320 {
  321         struct i2c_softc *sc;
  322 
  323         sc = device_get_softc(dev);
  324         mtx_lock(&sc->mutex);
  325         i2c_write_reg(sc, I2C_CONTROL_REG, I2CCR_MEN | I2CCR_TXAK);
  326         DELAY(1000);
  327         mtx_unlock(&sc->mutex);
  328 
  329         return (IIC_NOERR);
  330 }
  331 
  332 static int
  333 i2c_reset(device_t dev, u_char speed, u_char addr, u_char *oldadr)
  334 {
  335         struct i2c_softc *sc;
  336         uint8_t baud_rate;
  337 
  338         sc = device_get_softc(dev);
  339 
  340         switch (speed) {
  341         case IIC_FAST:
  342                 baud_rate = I2C_BAUD_RATE_FAST;
  343                 break;
  344         case IIC_SLOW:
  345         case IIC_UNKNOWN:
  346         case IIC_FASTEST:
  347         default:
  348                 baud_rate = I2C_BAUD_RATE_DEF;
  349                 break;
  350         }
  351 
  352         mtx_lock(&sc->mutex);
  353         i2c_write_reg(sc, I2C_CONTROL_REG, 0x0);
  354         i2c_write_reg(sc, I2C_STATUS_REG, 0x0);
  355         DELAY(1000);
  356         i2c_write_reg(sc, I2C_FDR_REG, baud_rate);
  357         i2c_write_reg(sc, I2C_DFSRR_REG, I2C_DFSSR_DIV);
  358         i2c_write_reg(sc, I2C_CONTROL_REG, I2C_ENABLE);
  359         DELAY(1000);
  360         mtx_unlock(&sc->mutex);
  361 
  362         return (IIC_NOERR);
  363 }
  364 
  365 static int
  366 i2c_read(device_t dev, char *buf, int len, int *read, int last, int delay)
  367 {
  368         struct i2c_softc *sc;
  369         int error;
  370 
  371         sc = device_get_softc(dev);
  372         *read = 0;
  373 
  374         mtx_lock(&sc->mutex);
  375         if (len) {
  376                 if (len == 1)
  377                         i2c_write_reg(sc, I2C_CONTROL_REG, I2CCR_MEN |
  378                             I2CCR_MSTA | I2CCR_TXAK);
  379 
  380                 else
  381                         i2c_write_reg(sc, I2C_CONTROL_REG, I2CCR_MEN |
  382                             I2CCR_MSTA);
  383 
  384                 /* dummy read */
  385                 i2c_read_reg(sc, I2C_DATA_REG);
  386                 DELAY(1000);
  387         }
  388 
  389         while (*read < len) {
  390                 DELAY(1000);
  391                 error = i2c_do_wait(dev, sc, 0, 0);
  392                 if (error) {
  393                         mtx_unlock(&sc->mutex);
  394                         return (error);
  395                 }
  396                 if ((*read == len - 2) && last) {
  397                         i2c_write_reg(sc, I2C_CONTROL_REG, I2CCR_MEN |
  398                             I2CCR_MSTA | I2CCR_TXAK);
  399                 }
  400 
  401                 if ((*read == len - 1) && last) {
  402                         i2c_write_reg(sc, I2C_CONTROL_REG,  I2CCR_MEN |
  403                             I2CCR_TXAK);
  404                 }
  405 
  406                 *buf++ = i2c_read_reg(sc, I2C_DATA_REG);
  407                 (*read)++;
  408                 DELAY(1250);
  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         *sent = 0;
  423 
  424         mtx_lock(&sc->mutex);
  425         while (*sent < len) {
  426                 i2c_write_reg(sc, I2C_DATA_REG, *buf++);
  427                 DELAY(1250);
  428 
  429                 error = i2c_do_wait(dev, sc, 1, 0);
  430                 if (error) {
  431                         mtx_unlock(&sc->mutex);
  432                         return (error);
  433                 }
  434 
  435                 (*sent)++;
  436         }
  437         mtx_unlock(&sc->mutex);
  438 
  439         return (IIC_NOERR);
  440 }

Cache object: f7dcdcaedd29167dbc36b2bf85ad9d7a


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