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/dev/iicbus/iicbb.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  * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
    3  *
    4  * Copyright (c) 1998, 2001 Nicolas Souchu
    5  * All rights reserved.
    6  *
    7  * Redistribution and use in source and binary forms, with or without
    8  * modification, are permitted provided that the following conditions
    9  * are met:
   10  * 1. Redistributions of source code must retain the above copyright
   11  *    notice, this list of conditions and the following disclaimer.
   12  * 2. Redistributions in binary form must reproduce the above copyright
   13  *    notice, this list of conditions and the following disclaimer in the
   14  *    documentation and/or other materials provided with the distribution.
   15  *
   16  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
   17  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   18  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   19  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
   20  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   21  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
   22  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   23  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   24  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
   25  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   26  * SUCH DAMAGE.
   27  */
   28 
   29 #include <sys/cdefs.h>
   30 __FBSDID("$FreeBSD$");
   31 
   32 /*
   33  * Generic I2C bit-banging code
   34  *
   35  * Example:
   36  *
   37  *      iicbus
   38  *       /  \ 
   39  *    iicbb pcf
   40  *     |  \
   41  *   bti2c lpbb
   42  *
   43  * From Linux I2C generic interface
   44  * (c) 1998 Gerd Knorr <kraxel@cs.tu-berlin.de>
   45  *
   46  */
   47 
   48 #include "opt_platform.h"
   49 
   50 #include <sys/param.h>
   51 #include <sys/kernel.h>
   52 #include <sys/systm.h>
   53 #include <sys/module.h>
   54 #include <sys/bus.h>
   55 #include <sys/sysctl.h>
   56 #include <sys/uio.h>
   57 
   58 #ifdef FDT
   59 #include <dev/ofw/ofw_bus.h>
   60 #include <dev/ofw/ofw_bus_subr.h>
   61 #include <dev/fdt/fdt_common.h>
   62 #endif
   63 
   64 #include <dev/iicbus/iiconf.h>
   65 #include <dev/iicbus/iicbus.h>
   66 
   67 #include <dev/smbus/smbconf.h>
   68 
   69 #include "iicbus_if.h"
   70 #include "iicbb_if.h"
   71 
   72 /* Based on the SMBus specification. */
   73 #define DEFAULT_SCL_LOW_TIMEOUT (25 * 1000)
   74 
   75 struct iicbb_softc {
   76         device_t iicbus;
   77         u_int udelay;           /* signal toggle delay in usec */
   78         u_int io_latency;       /* approximate pin toggling latency */
   79         u_int scl_low_timeout;
   80 };
   81 
   82 static int iicbb_attach(device_t);
   83 static void iicbb_child_detached(device_t, device_t);
   84 static int iicbb_detach(device_t);
   85 static int iicbb_print_child(device_t, device_t);
   86 static int iicbb_probe(device_t);
   87 
   88 static int iicbb_callback(device_t, int, caddr_t);
   89 static int iicbb_start(device_t, u_char, int);
   90 static int iicbb_repstart(device_t, u_char, int);
   91 static int iicbb_stop(device_t);
   92 static int iicbb_write(device_t, const char *, int, int *, int);
   93 static int iicbb_read(device_t, char *, int, int *, int, int);
   94 static int iicbb_reset(device_t, u_char, u_char, u_char *);
   95 static int iicbb_transfer(device_t dev, struct iic_msg *msgs, uint32_t nmsgs);
   96 static void iicbb_set_speed(struct iicbb_softc *sc, u_char);
   97 #ifdef FDT
   98 static phandle_t iicbb_get_node(device_t, device_t);
   99 #endif
  100 
  101 static device_method_t iicbb_methods[] = {
  102         /* device interface */
  103         DEVMETHOD(device_probe,         iicbb_probe),
  104         DEVMETHOD(device_attach,        iicbb_attach),
  105         DEVMETHOD(device_detach,        iicbb_detach),
  106 
  107         /* bus interface */
  108         DEVMETHOD(bus_child_detached,   iicbb_child_detached),
  109         DEVMETHOD(bus_print_child,      iicbb_print_child),
  110 
  111         /* iicbus interface */
  112         DEVMETHOD(iicbus_callback,      iicbb_callback),
  113         DEVMETHOD(iicbus_start,         iicbb_start),
  114         DEVMETHOD(iicbus_repeated_start, iicbb_repstart),
  115         DEVMETHOD(iicbus_stop,          iicbb_stop),
  116         DEVMETHOD(iicbus_write,         iicbb_write),
  117         DEVMETHOD(iicbus_read,          iicbb_read),
  118         DEVMETHOD(iicbus_reset,         iicbb_reset),
  119         DEVMETHOD(iicbus_transfer,      iicbb_transfer),
  120 
  121 #ifdef FDT
  122         /* ofw_bus interface */
  123         DEVMETHOD(ofw_bus_get_node,     iicbb_get_node),
  124 #endif
  125 
  126         { 0, 0 }
  127 };
  128 
  129 driver_t iicbb_driver = {
  130         "iicbb",
  131         iicbb_methods,
  132         sizeof(struct iicbb_softc),
  133 };
  134 
  135 static int
  136 iicbb_probe(device_t dev)
  137 {
  138         device_set_desc(dev, "I2C bit-banging driver");
  139 
  140         return (0);
  141 }
  142 
  143 static int
  144 iicbb_attach(device_t dev)
  145 {
  146         struct iicbb_softc *sc = (struct iicbb_softc *)device_get_softc(dev);
  147 
  148         sc->iicbus = device_add_child(dev, "iicbus", -1);
  149         if (!sc->iicbus)
  150                 return (ENXIO);
  151 
  152         sc->scl_low_timeout = DEFAULT_SCL_LOW_TIMEOUT;
  153 
  154         SYSCTL_ADD_UINT(device_get_sysctl_ctx(dev),
  155             SYSCTL_CHILDREN(device_get_sysctl_tree(dev)), OID_AUTO,
  156             "delay", CTLFLAG_RD, &sc->udelay,
  157             0, "Signal change delay controlled by bus frequency, microseconds");
  158 
  159         SYSCTL_ADD_UINT(device_get_sysctl_ctx(dev),
  160             SYSCTL_CHILDREN(device_get_sysctl_tree(dev)), OID_AUTO,
  161             "scl_low_timeout", CTLFLAG_RWTUN, &sc->scl_low_timeout,
  162             0, "SCL low timeout, microseconds");
  163         SYSCTL_ADD_UINT(device_get_sysctl_ctx(dev),
  164             SYSCTL_CHILDREN(device_get_sysctl_tree(dev)), OID_AUTO,
  165             "io_latency", CTLFLAG_RWTUN, &sc->io_latency,
  166             0, "Estimate of pin toggling latency, microseconds");
  167 
  168         bus_generic_attach(dev);
  169         return (0);
  170 }
  171 
  172 static int
  173 iicbb_detach(device_t dev)
  174 {
  175 
  176         bus_generic_detach(dev);
  177         device_delete_children(dev);
  178 
  179         return (0);
  180 }
  181 
  182 #ifdef FDT
  183 static phandle_t
  184 iicbb_get_node(device_t bus, device_t dev)
  185 {
  186 
  187         /* We only have one child, the I2C bus, which needs our own node. */
  188         return (ofw_bus_get_node(bus));
  189 }
  190 #endif
  191 
  192 static void
  193 iicbb_child_detached( device_t dev, device_t child )
  194 {
  195         struct iicbb_softc *sc = (struct iicbb_softc *)device_get_softc(dev);
  196 
  197         if (child == sc->iicbus)
  198                 sc->iicbus = NULL;
  199 }
  200 
  201 static int
  202 iicbb_print_child(device_t bus, device_t dev)
  203 {
  204         int error;
  205         int retval = 0;
  206         u_char oldaddr;
  207 
  208         retval += bus_print_child_header(bus, dev);
  209         /* retrieve the interface I2C address */
  210         error = IICBB_RESET(device_get_parent(bus), IIC_FASTEST, 0, &oldaddr);
  211         if (error == IIC_ENOADDR) {
  212                 retval += printf(" on %s master-only\n",
  213                                  device_get_nameunit(bus));
  214         } else {
  215                 /* restore the address */
  216                 IICBB_RESET(device_get_parent(bus), IIC_FASTEST, oldaddr, NULL);
  217 
  218                 retval += printf(" on %s addr 0x%x\n",
  219                                  device_get_nameunit(bus), oldaddr & 0xff);
  220         }
  221 
  222         return (retval);
  223 }
  224 
  225 #define IICBB_DEBUG
  226 #ifdef IICBB_DEBUG
  227 static int i2c_debug = 0;
  228 
  229 SYSCTL_DECL(_hw_i2c);
  230 SYSCTL_INT(_hw_i2c, OID_AUTO, iicbb_debug, CTLFLAG_RWTUN,
  231     &i2c_debug, 0, "Enable i2c bit-banging driver debug");
  232 
  233 #define I2C_DEBUG(x)    do {            \
  234                 if (i2c_debug) (x);     \
  235         } while (0)
  236 #else
  237 #define I2C_DEBUG(x)
  238 #endif
  239 
  240 #define I2C_GETSDA(dev)         (IICBB_GETSDA(device_get_parent(dev)))
  241 #define I2C_SETSDA(dev, x)      (IICBB_SETSDA(device_get_parent(dev), x))
  242 #define I2C_GETSCL(dev)         (IICBB_GETSCL(device_get_parent(dev)))
  243 #define I2C_SETSCL(dev, x)      (IICBB_SETSCL(device_get_parent(dev), x))
  244 
  245 static int
  246 iicbb_waitforscl(device_t dev)
  247 {
  248         struct iicbb_softc *sc = device_get_softc(dev);
  249         sbintime_t fast_timeout;
  250         sbintime_t now, timeout;
  251 
  252         /* Spin for up to 1 ms, then switch to pause. */
  253         now = sbinuptime();
  254         fast_timeout = now + SBT_1MS;
  255         timeout = now + sc->scl_low_timeout * SBT_1US;
  256         do {
  257                 if (I2C_GETSCL(dev))
  258                         return (0);
  259                 now = sbinuptime();
  260         } while (now < fast_timeout);
  261         do {
  262                 I2C_DEBUG(printf("."));
  263                 pause_sbt("iicbb-scl-low", SBT_1MS, C_PREL(8), 0);
  264                 if (I2C_GETSCL(dev))
  265                         return (0);
  266                 now = sbinuptime();
  267         } while (now < timeout);
  268 
  269         I2C_DEBUG(printf("*"));
  270         return (IIC_ETIMEOUT);
  271 }
  272 
  273 /* Start the high phase of the clock. */
  274 static int
  275 iicbb_clockin(device_t dev, int sda)
  276 {
  277 
  278         /*
  279          * Precondition: SCL is low.
  280          * Action:
  281          * - set SDA to the value;
  282          * - release SCL and wait until it's high.
  283          * The caller is responsible for keeping SCL high for udelay.
  284          *
  285          * There should be a data set-up time, 250 ns minimum, between setting
  286          * SDA and raising SCL.  It's expected that the I/O access latency will
  287          * naturally provide that delay.
  288          */
  289         I2C_SETSDA(dev, sda);
  290         I2C_SETSCL(dev, 1);
  291         return (iicbb_waitforscl(dev));
  292 }
  293 
  294 /*
  295  * End the high phase of the clock and wait out the low phase
  296  * as nothing interesting happens during it anyway.
  297  */
  298 static void
  299 iicbb_clockout(device_t dev)
  300 {
  301         struct iicbb_softc *sc = device_get_softc(dev);
  302 
  303         /*
  304          * Precondition: SCL is high.
  305          * Action:
  306          * - pull SCL low and hold for udelay.
  307          */
  308         I2C_SETSCL(dev, 0);
  309         DELAY(sc->udelay);
  310 }
  311 
  312 static int
  313 iicbb_sendbit(device_t dev, int bit)
  314 {
  315         struct iicbb_softc *sc = device_get_softc(dev);
  316         int err;
  317 
  318         err = iicbb_clockin(dev, bit);
  319         if (err != 0)
  320                 return (err);
  321         DELAY(sc->udelay);
  322         iicbb_clockout(dev);
  323         return (0);
  324 }
  325 
  326 /*
  327  * Waiting for ACKNOWLEDGE.
  328  *
  329  * When a chip is being addressed or has received data it will issue an
  330  * ACKNOWLEDGE pulse. Therefore the MASTER must release the DATA line
  331  * (set it to high level) and then release the CLOCK line.
  332  * Now it must wait for the SLAVE to pull the DATA line low.
  333  * Actually on the bus this looks like a START condition so nothing happens
  334  * because of the fact that the IC's that have not been addressed are doing
  335  * nothing.
  336  *
  337  * When the SLAVE has pulled this line low the MASTER will take the CLOCK
  338  * line low and then the SLAVE will release the SDA (data) line.
  339  */
  340 static int
  341 iicbb_getack(device_t dev)
  342 {
  343         struct iicbb_softc *sc = device_get_softc(dev);
  344         int noack, err;
  345         int t;
  346 
  347         /* Release SDA so that the slave can drive it. */
  348         err = iicbb_clockin(dev, 1);
  349         if (err != 0) {
  350                 I2C_DEBUG(printf("! "));
  351                 return (err);
  352         }
  353 
  354         /* Sample SDA until ACK (low) or udelay runs out. */
  355         for (t = 0; t < sc->udelay; t++) {
  356                 noack = I2C_GETSDA(dev);
  357                 if (!noack)
  358                         break;
  359                 DELAY(1);
  360         }
  361 
  362         DELAY(sc->udelay - t);
  363         iicbb_clockout(dev);
  364 
  365         I2C_DEBUG(printf("%c ", noack ? '-' : '+'));
  366         return (noack ? IIC_ENOACK : 0);
  367 }
  368 
  369 static int
  370 iicbb_sendbyte(device_t dev, uint8_t data)
  371 {
  372         int err, i;
  373 
  374         for (i = 7; i >= 0; i--) {
  375                 err = iicbb_sendbit(dev, (data & (1 << i)) != 0);
  376                 if (err != 0) {
  377                         I2C_DEBUG(printf("w!"));
  378                         return (err);
  379                 }
  380         }
  381         I2C_DEBUG(printf("w%02x", data));
  382         return (0);
  383 }
  384 
  385 static int
  386 iicbb_readbyte(device_t dev, bool last, uint8_t *data)
  387 {
  388         struct iicbb_softc *sc = device_get_softc(dev);
  389         int i, err;
  390 
  391         /*
  392          * Release SDA so that the slave can drive it.
  393          * We do not use iicbb_clockin() here because we need to release SDA
  394          * only once and then we just pulse the SCL.
  395          */
  396         *data = 0;
  397         I2C_SETSDA(dev, 1);
  398         for (i = 7; i >= 0; i--) {
  399                 I2C_SETSCL(dev, 1);
  400                 err = iicbb_waitforscl(dev);
  401                 if (err != 0) {
  402                         I2C_DEBUG(printf("r! "));
  403                         return (err);
  404                 }
  405                 DELAY((sc->udelay + 1) / 2);
  406                 if (I2C_GETSDA(dev))
  407                         *data |= 1 << i;
  408                 DELAY((sc->udelay + 1) / 2);
  409                 iicbb_clockout(dev);
  410         }
  411 
  412         /*
  413          * Send master->slave ACK (low) for more data,
  414          * NoACK (high) otherwise.
  415          */
  416         iicbb_sendbit(dev, last);
  417         I2C_DEBUG(printf("r%02x%c ", *data, last ? '-' : '+'));
  418         return (0);
  419 }
  420 
  421 static int
  422 iicbb_callback(device_t dev, int index, caddr_t data)
  423 {
  424         return (IICBB_CALLBACK(device_get_parent(dev), index, data));
  425 }
  426 
  427 static int
  428 iicbb_reset(device_t dev, u_char speed, u_char addr, u_char *oldaddr)
  429 {
  430         iicbb_set_speed(device_get_softc(dev), speed);
  431         return (IICBB_RESET(device_get_parent(dev), speed, addr, oldaddr));
  432 }
  433 
  434 static int
  435 iicbb_start_impl(device_t dev, u_char slave, bool repstart)
  436 {
  437         struct iicbb_softc *sc = device_get_softc(dev);
  438         int error;
  439 
  440         if (!repstart) {
  441                 I2C_DEBUG(printf("<<"));
  442 
  443                 /* SCL must be high on the idle bus. */
  444                 if (iicbb_waitforscl(dev) != 0) {
  445                         I2C_DEBUG(printf("C!\n"));
  446                         return (IIC_EBUSERR);
  447                 }
  448         } else {
  449                 I2C_DEBUG(printf("<"));
  450                 error = iicbb_clockin(dev, 1);
  451                 if (error != 0)
  452                         return (error);
  453 
  454                 /* SDA will go low in the middle of the SCL high phase. */
  455                 DELAY((sc->udelay + 1) / 2);
  456         }
  457 
  458         /*
  459          * SDA must be high after the earlier stop condition or the end
  460          * of Ack/NoAck pulse.
  461          */
  462         if (!I2C_GETSDA(dev)) {
  463                 I2C_DEBUG(printf("D!\n"));
  464                 return (IIC_EBUSERR);
  465         }
  466 
  467         /* Start: SDA high->low. */
  468         I2C_SETSDA(dev, 0);
  469 
  470         /* Wait the second half of the SCL high phase. */
  471         DELAY((sc->udelay + 1) / 2);
  472 
  473         /* Pull SCL low to keep the bus reserved. */
  474         iicbb_clockout(dev);
  475 
  476         /* send address */
  477         error = iicbb_sendbyte(dev, slave);
  478 
  479         /* check for ack */
  480         if (error == 0)
  481                 error = iicbb_getack(dev);
  482         if (error != 0)
  483                 (void)iicbb_stop(dev);
  484         return (error);
  485 }
  486 
  487 /* NB: the timeout is ignored. */
  488 static int
  489 iicbb_start(device_t dev, u_char slave, int timeout)
  490 {
  491         return (iicbb_start_impl(dev, slave, false));
  492 }
  493 
  494 /* NB: the timeout is ignored. */
  495 static int
  496 iicbb_repstart(device_t dev, u_char slave, int timeout)
  497 {
  498         return (iicbb_start_impl(dev, slave, true));
  499 }
  500 
  501 static int
  502 iicbb_stop(device_t dev)
  503 {
  504         struct iicbb_softc *sc = device_get_softc(dev);
  505         int err = 0;
  506 
  507         /*
  508          * Stop: SDA goes from low to high in the middle of the SCL high phase.
  509          */
  510         err = iicbb_clockin(dev, 0);
  511         if (err != 0)
  512                 return (err);
  513         DELAY((sc->udelay + 1) / 2);
  514         I2C_SETSDA(dev, 1);
  515         DELAY((sc->udelay + 1) / 2);
  516 
  517         I2C_DEBUG(printf("%s>>", err != 0 ? "!" : ""));
  518         I2C_DEBUG(printf("\n"));
  519         return (err);
  520 }
  521 
  522 /* NB: the timeout is ignored. */
  523 static int
  524 iicbb_write(device_t dev, const char *buf, int len, int *sent, int timeout)
  525 {
  526         int bytes, error = 0;
  527 
  528         bytes = 0;
  529         while (len > 0) {
  530                 /* send byte */
  531                 iicbb_sendbyte(dev, (uint8_t)*buf++);
  532 
  533                 /* check for ack */
  534                 error = iicbb_getack(dev);
  535                 if (error != 0)
  536                         break;
  537                 bytes++;
  538                 len--;
  539         }
  540 
  541         *sent = bytes;
  542         return (error);
  543 }
  544 
  545 /* NB: whatever delay is, it's ignored. */
  546 static int
  547 iicbb_read(device_t dev, char *buf, int len, int *read, int last, int delay)
  548 {
  549         int bytes = 0;
  550         int err = 0;
  551 
  552         while (len > 0) {
  553                 err = iicbb_readbyte(dev, (len == 1) ? last : 0,
  554                     (uint8_t *)buf);
  555                 if (err != 0)
  556                         break;
  557                 buf++;
  558                 bytes++;
  559                 len--;
  560         }
  561 
  562         *read = bytes;
  563         return (err);
  564 }
  565 
  566 static int
  567 iicbb_transfer(device_t dev, struct iic_msg *msgs, uint32_t nmsgs)
  568 {
  569         int error;
  570 
  571         error = IICBB_PRE_XFER(device_get_parent(dev));
  572         if (error)
  573                 return (error);
  574 
  575         error = iicbus_transfer_gen(dev, msgs, nmsgs);
  576 
  577         IICBB_POST_XFER(device_get_parent(dev));
  578         return (error);
  579 }
  580 
  581 static void
  582 iicbb_set_speed(struct iicbb_softc *sc, u_char speed)
  583 {
  584         u_int busfreq;
  585         int period;
  586 
  587         /*
  588          * udelay is half a period, the clock is held high or low for this long.
  589          */
  590         busfreq = IICBUS_GET_FREQUENCY(sc->iicbus, speed);
  591         period = 1000000 / 2 / busfreq; /* Hz -> uS */
  592         period -= sc->io_latency;
  593         sc->udelay = MAX(period, 1);
  594 }
  595 
  596 DRIVER_MODULE(iicbus, iicbb, iicbus_driver, 0, 0);
  597 
  598 MODULE_DEPEND(iicbb, iicbus, IICBUS_MINVER, IICBUS_PREFVER, IICBUS_MAXVER);
  599 MODULE_VERSION(iicbb, IICBB_MODVER);

Cache object: 4de7a22e315c07e587e65c1b55249942


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