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: releng/11.0/sys/powerpc/mpc85xx/i2c.c 297572 2016-04-05 02:27:01Z jhibbits $");
   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 <sys/rman.h>
   40 
   41 #include <sys/lock.h>
   42 #include <sys/mutex.h>
   43 
   44 #include <dev/iicbus/iiconf.h>
   45 #include <dev/iicbus/iicbus.h>
   46 #include "iicbus_if.h"
   47 
   48 #include <dev/ofw/ofw_bus.h>
   49 #include <dev/ofw/ofw_bus_subr.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 #ifdef  DEBUG
   76 #define debugf(fmt, args...) do { printf("%s(): ", __func__); printf(fmt,##args); } while (0)
   77 #else
   78 #define debugf(fmt, args...)
   79 #endif
   80 
   81 struct i2c_softc {
   82         device_t                dev;
   83         device_t                iicbus;
   84         struct resource         *res;
   85         struct mtx              mutex;
   86         int                     rid;
   87         bus_space_handle_t      bsh;
   88         bus_space_tag_t         bst;
   89 };
   90 
   91 static int i2c_probe(device_t);
   92 static int i2c_attach(device_t);
   93 
   94 static int i2c_repeated_start(device_t dev, u_char slave, int timeout);
   95 static int i2c_start(device_t dev, u_char slave, int timeout);
   96 static int i2c_stop(device_t dev);
   97 static int i2c_reset(device_t dev, u_char speed, u_char addr, u_char *oldaddr);
   98 static int i2c_read(device_t dev, char *buf, int len, int *read, int last, int delay);
   99 static int i2c_write(device_t dev, const char *buf, int len, int *sent, int timeout);
  100 static phandle_t i2c_get_node(device_t bus, device_t dev);
  101 
  102 static device_method_t i2c_methods[] = {
  103         DEVMETHOD(device_probe,                 i2c_probe),
  104         DEVMETHOD(device_attach,                i2c_attach),
  105 
  106         DEVMETHOD(iicbus_callback,              iicbus_null_callback),
  107         DEVMETHOD(iicbus_repeated_start,        i2c_repeated_start),
  108         DEVMETHOD(iicbus_start,                 i2c_start),
  109         DEVMETHOD(iicbus_stop,                  i2c_stop),
  110         DEVMETHOD(iicbus_reset,                 i2c_reset),
  111         DEVMETHOD(iicbus_read,                  i2c_read),
  112         DEVMETHOD(iicbus_write,                 i2c_write),
  113         DEVMETHOD(iicbus_transfer,              iicbus_transfer_gen),
  114         DEVMETHOD(ofw_bus_get_node,             i2c_get_node),
  115 
  116         { 0, 0 }
  117 };
  118 
  119 static driver_t i2c_driver = {
  120         "iichb",
  121         i2c_methods,
  122         sizeof(struct i2c_softc),
  123 };
  124 static devclass_t  i2c_devclass;
  125 
  126 DRIVER_MODULE(i2c, simplebus, i2c_driver, i2c_devclass, 0, 0);
  127 DRIVER_MODULE(iicbus, i2c, iicbus_driver, iicbus_devclass, 0, 0);
  128 
  129 static __inline void
  130 i2c_write_reg(struct i2c_softc *sc, bus_size_t off, uint8_t val)
  131 {
  132 
  133         bus_space_write_1(sc->bst, sc->bsh, off, val);
  134 }
  135 
  136 static __inline uint8_t
  137 i2c_read_reg(struct i2c_softc *sc, bus_size_t off)
  138 {
  139 
  140         return (bus_space_read_1(sc->bst, sc->bsh, off));
  141 }
  142 
  143 static __inline void
  144 i2c_flag_set(struct i2c_softc *sc, bus_size_t off, uint8_t mask)
  145 {
  146         uint8_t status;
  147 
  148         status = i2c_read_reg(sc, off);
  149         status |= mask;
  150         i2c_write_reg(sc, off, status);
  151 }
  152 
  153 static int
  154 i2c_do_wait(device_t dev, struct i2c_softc *sc, int write, int start)
  155 {
  156         int err;
  157         uint8_t status;
  158 
  159         status = i2c_read_reg(sc, I2C_STATUS_REG);
  160         if (status & I2CSR_MIF) {
  161                 if (write && start && (status & I2CSR_RXAK)) {
  162                         debugf("no ack %s", start ?
  163                             "after sending slave address" : "");
  164                         err = IIC_ENOACK;
  165                         goto error;
  166                 }
  167                 if (status & I2CSR_MAL) {
  168                         debugf("arbitration lost");
  169                         err = IIC_EBUSERR;
  170                         goto error;
  171                 }
  172                 if (!write && !(status & I2CSR_MCF)) {
  173                         debugf("transfer unfinished");
  174                         err = IIC_EBUSERR;
  175                         goto error;
  176                 }
  177         }
  178 
  179         return (IIC_NOERR);
  180 
  181 error:
  182         i2c_write_reg(sc, I2C_STATUS_REG, 0x0);
  183         i2c_write_reg(sc, I2C_CONTROL_REG, I2CCR_MEN | I2CCR_TXAK);
  184         return (err);
  185 }
  186 
  187 static int
  188 i2c_probe(device_t dev)
  189 {
  190         struct i2c_softc *sc;
  191 
  192         if (!ofw_bus_is_compatible(dev, "fsl-i2c"))
  193                 return (ENXIO);
  194 
  195         sc = device_get_softc(dev);
  196         sc->rid = 0;
  197 
  198         sc->res = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &sc->rid,
  199             RF_ACTIVE);
  200         if (sc->res == NULL) {
  201                 device_printf(dev, "could not allocate resources\n");
  202                 return (ENXIO);
  203         }
  204 
  205         sc->bst = rman_get_bustag(sc->res);
  206         sc->bsh = rman_get_bushandle(sc->res);
  207 
  208         /* Enable I2C */
  209         i2c_write_reg(sc, I2C_CONTROL_REG, I2C_ENABLE);
  210         bus_release_resource(dev, SYS_RES_MEMORY, sc->rid, sc->res);
  211         device_set_desc(dev, "I2C bus controller");
  212 
  213         return (BUS_PROBE_DEFAULT);
  214 }
  215 
  216 static int
  217 i2c_attach(device_t dev)
  218 {
  219         struct i2c_softc *sc;
  220         sc = device_get_softc(dev);
  221 
  222         sc->dev = dev;
  223         sc->rid = 0;
  224 
  225         mtx_init(&sc->mutex, device_get_nameunit(dev), "I2C", MTX_DEF);
  226 
  227         sc->res = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &sc->rid,
  228             RF_ACTIVE);
  229         if (sc->res == NULL) {
  230                 device_printf(dev, "could not allocate resources");
  231                 mtx_destroy(&sc->mutex);
  232                 return (ENXIO);
  233         }
  234 
  235         sc->bst = rman_get_bustag(sc->res);
  236         sc->bsh = rman_get_bushandle(sc->res);
  237 
  238         sc->iicbus = device_add_child(dev, "iicbus", -1);
  239         if (sc->iicbus == NULL) {
  240                 device_printf(dev, "could not add iicbus child");
  241                 mtx_destroy(&sc->mutex);
  242                 return (ENXIO);
  243         }
  244 
  245         bus_generic_attach(dev);
  246         return (IIC_NOERR);
  247 }
  248 static int
  249 i2c_repeated_start(device_t dev, u_char slave, int timeout)
  250 {
  251         struct i2c_softc *sc;
  252         int error;
  253         
  254         sc = device_get_softc(dev);
  255 
  256         mtx_lock(&sc->mutex);
  257         /* Set repeated start condition */
  258         i2c_flag_set(sc, I2C_CONTROL_REG ,I2CCR_RSTA);
  259         /* Write target address - LSB is R/W bit */
  260         i2c_write_reg(sc, I2C_DATA_REG, slave);
  261         DELAY(1250);
  262 
  263         error = i2c_do_wait(dev, sc, 1, 1);
  264         mtx_unlock(&sc->mutex);
  265 
  266         if (error)
  267                 return (error);
  268 
  269         return (IIC_NOERR);
  270 }
  271 
  272 static int
  273 i2c_start(device_t dev, u_char slave, int timeout)
  274 {
  275         struct i2c_softc *sc;
  276         uint8_t status;
  277         int error;
  278 
  279         sc = device_get_softc(dev);
  280         DELAY(1000);
  281 
  282         mtx_lock(&sc->mutex);
  283         status = i2c_read_reg(sc, I2C_STATUS_REG);
  284         /* Check if bus is idle or busy */
  285         if (status & I2CSR_MBB) {
  286                 debugf("bus busy");
  287                 mtx_unlock(&sc->mutex);
  288                 i2c_stop(dev);
  289                 return (IIC_EBUSERR);
  290         }
  291 
  292         /* Set start condition */
  293         i2c_write_reg(sc, I2C_CONTROL_REG, I2CCR_MEN | I2CCR_MSTA | I2CCR_MTX);
  294         /* Write target address - LSB is R/W bit */
  295         i2c_write_reg(sc, I2C_DATA_REG, slave);
  296         DELAY(1250);
  297 
  298         error = i2c_do_wait(dev, sc, 1, 1);
  299 
  300         mtx_unlock(&sc->mutex);
  301         if (error)
  302                 return (error);
  303 
  304         return (IIC_NOERR);
  305 }
  306 
  307 static int
  308 i2c_stop(device_t dev)
  309 {
  310         struct i2c_softc *sc;
  311 
  312         sc = device_get_softc(dev);
  313         mtx_lock(&sc->mutex);
  314         i2c_write_reg(sc, I2C_CONTROL_REG, I2CCR_MEN | I2CCR_TXAK);
  315         DELAY(1000);
  316         mtx_unlock(&sc->mutex);
  317 
  318         return (IIC_NOERR);
  319 }
  320 
  321 static int
  322 i2c_reset(device_t dev, u_char speed, u_char addr, u_char *oldadr)
  323 {
  324         struct i2c_softc *sc;
  325         uint8_t baud_rate;
  326 
  327         sc = device_get_softc(dev);
  328 
  329         switch (speed) {
  330         case IIC_FAST:
  331                 baud_rate = I2C_BAUD_RATE_FAST;
  332                 break;
  333         case IIC_SLOW:
  334         case IIC_UNKNOWN:
  335         case IIC_FASTEST:
  336         default:
  337                 baud_rate = I2C_BAUD_RATE_DEF;
  338                 break;
  339         }
  340 
  341         mtx_lock(&sc->mutex);
  342         i2c_write_reg(sc, I2C_CONTROL_REG, 0x0);
  343         i2c_write_reg(sc, I2C_STATUS_REG, 0x0);
  344         DELAY(1000);
  345         i2c_write_reg(sc, I2C_FDR_REG, baud_rate);
  346         i2c_write_reg(sc, I2C_DFSRR_REG, I2C_DFSSR_DIV);
  347         i2c_write_reg(sc, I2C_CONTROL_REG, I2C_ENABLE);
  348         DELAY(1000);
  349         mtx_unlock(&sc->mutex);
  350 
  351         return (IIC_NOERR);
  352 }
  353 
  354 static int
  355 i2c_read(device_t dev, char *buf, int len, int *read, int last, int delay)
  356 {
  357         struct i2c_softc *sc;
  358         int error;
  359 
  360         sc = device_get_softc(dev);
  361         *read = 0;
  362 
  363         mtx_lock(&sc->mutex);
  364         if (len) {
  365                 if (len == 1)
  366                         i2c_write_reg(sc, I2C_CONTROL_REG, I2CCR_MEN |
  367                             I2CCR_MSTA | I2CCR_TXAK);
  368 
  369                 else
  370                         i2c_write_reg(sc, I2C_CONTROL_REG, I2CCR_MEN |
  371                             I2CCR_MSTA);
  372 
  373                 /* dummy read */
  374                 i2c_read_reg(sc, I2C_DATA_REG);
  375                 DELAY(1000);
  376         }
  377 
  378         while (*read < len) {
  379                 DELAY(1000);
  380                 error = i2c_do_wait(dev, sc, 0, 0);
  381                 if (error) {
  382                         mtx_unlock(&sc->mutex);
  383                         return (error);
  384                 }
  385                 if ((*read == len - 2) && last) {
  386                         i2c_write_reg(sc, I2C_CONTROL_REG, I2CCR_MEN |
  387                             I2CCR_MSTA | I2CCR_TXAK);
  388                 }
  389 
  390                 if ((*read == len - 1) && last) {
  391                         i2c_write_reg(sc, I2C_CONTROL_REG,  I2CCR_MEN |
  392                             I2CCR_TXAK);
  393                 }
  394 
  395                 *buf++ = i2c_read_reg(sc, I2C_DATA_REG);
  396                 (*read)++;
  397                 DELAY(1250);
  398         }
  399         mtx_unlock(&sc->mutex);
  400 
  401         return (IIC_NOERR);
  402 }
  403 
  404 static int
  405 i2c_write(device_t dev, const char *buf, int len, int *sent, int timeout)
  406 {
  407         struct i2c_softc *sc;
  408         int error;
  409 
  410         sc = device_get_softc(dev);
  411         *sent = 0;
  412 
  413         mtx_lock(&sc->mutex);
  414         while (*sent < len) {
  415                 i2c_write_reg(sc, I2C_DATA_REG, *buf++);
  416                 DELAY(1250);
  417 
  418                 error = i2c_do_wait(dev, sc, 1, 0);
  419                 if (error) {
  420                         mtx_unlock(&sc->mutex);
  421                         return (error);
  422                 }
  423 
  424                 (*sent)++;
  425         }
  426         mtx_unlock(&sc->mutex);
  427 
  428         return (IIC_NOERR);
  429 }
  430 
  431 static phandle_t
  432 i2c_get_node(device_t bus, device_t dev)
  433 {
  434 
  435         /* Share controller node with iibus device. */
  436         return (ofw_bus_get_node(bus));
  437 }

Cache object: 47bd1ca7a9d5c31de44affdc3ce6a25f


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