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-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-2  -  FREEBSD-11-1  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-4  -  FREEBSD-10-3  -  FREEBSD-10-2  -  FREEBSD-10-1  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-3  -  FREEBSD-9-2  -  FREEBSD-9-1  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-4  -  FREEBSD-8-3  -  FREEBSD-8-2  -  FREEBSD-8-1  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-4  -  FREEBSD-7-3  -  FREEBSD-7-2  -  FREEBSD-7-1  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-4  -  FREEBSD-6-3  -  FREEBSD-6-2  -  FREEBSD-6-1  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-5  -  FREEBSD-5-4  -  FREEBSD-5-3  -  FREEBSD-5-2  -  FREEBSD-5-1  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  linux-2.6  -  linux-2.4.22  -  MK83  -  MK84  -  PLAN9  -  DFBSD  -  NETBSD  -  NETBSD5  -  NETBSD4  -  NETBSD3  -  NETBSD20  -  OPENBSD  -  xnu-517  -  xnu-792  -  xnu-792.6.70  -  xnu-1228  -  xnu-1456.1.26  -  xnu-1699.24.8  -  xnu-2050.18.24  -  OPENSOLARIS  -  minix-3-1-1 
SearchContext: -  none  -  3  -  10 

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

Cache object: 51fd2999eb7d7585983c091d7c864d2c


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