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/mips/rmi/xlr_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) 2003-2009 RMI Corporation
    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  * 3. Neither the name of RMI Corporation, nor the names of its contributors,
   14  *    may be used to endorse or promote products derived from this software
   15  *    without specific prior written permission.
   16  *
   17  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
   18  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   19  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   20  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
   21  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   22  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
   23  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   24  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   25  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
   26  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   27  * SUCH DAMAGE.
   28  *
   29  * RMI_BSD */
   30 
   31 #include <sys/cdefs.h>
   32 __FBSDID("$FreeBSD: releng/9.0/sys/mips/rmi/xlr_i2c.c 216390 2010-12-12 06:00:26Z jchandra $");
   33 
   34 /*
   35  * I2C driver for the Palm-BK3220 I2C Host adapter on the RMI XLR.
   36  */
   37 
   38 #include <sys/param.h>
   39 #include <sys/systm.h>
   40 #include <sys/kernel.h>
   41 #include <sys/lock.h>
   42 #include <sys/module.h>
   43 #include <sys/mutex.h>
   44 #include <sys/bus.h>
   45 #include <sys/rman.h>
   46 
   47 
   48 #include <dev/iicbus/iiconf.h>
   49 #include <dev/iicbus/iicbus.h>
   50 
   51 #include <mips/rmi/board.h>
   52 #include <mips/rmi/iomap.h>
   53 #include <mips/include/resource.h>
   54 
   55 #include "iicbus_if.h"
   56 
   57 /* XLR I2C REGISTERS */
   58 #define XLR_I2C_CFG            0x00
   59 #define XLR_I2C_CLKDIV         0x01
   60 #define XLR_I2C_DEVADDR        0x02
   61 #define XLR_I2C_ADDR           0x03
   62 #define XLR_I2C_DATAOUT        0x04
   63 #define XLR_I2C_DATAIN         0x05
   64 #define XLR_I2C_STATUS         0x06
   65 #define XLR_I2C_STARTXFR       0x07
   66 #define XLR_I2C_BYTECNT        0x08
   67 #define XLR_I2C_HDSTATIM       0x09
   68 
   69 /* XLR I2C REGISTERS FLAGS */
   70 #define XLR_I2C_BUS_BUSY        0x01
   71 #define XLR_I2C_SDOEMPTY        0x02
   72 #define XLR_I2C_RXRDY           0x04
   73 #define XLR_I2C_ACK_ERR         0x08
   74 #define XLR_I2C_ARB_STARTERR    0x30
   75 
   76 /* Register Programming Values!! Change as required */
   77 #define XLR_I2C_CFG_ADDR        0xF8    /* 8-Bit dev Addr + POR Values */
   78 #define XLR_I2C_CFG_NOADDR      0xFA    /* 8-Bit reg Addr + POR Values  : No dev addr */
   79 #define XLR_I2C_STARTXFR_ND     0x02    /* No data , only addr */
   80 #define XLR_I2C_STARTXFR_RD     0x01    /* Read */
   81 #define XLR_I2C_STARTXFR_WR     0x00    /* Write */
   82 #define XLR_I2C_CLKDIV_DEF      0x14A   /* 0x00000052 */
   83 #define XLR_I2C_HDSTATIM_DEF    0x107   /* 0x00000000 */
   84 
   85 #define MAXTIME 0x10000
   86 #define ARIZONA_I2C_BUS 1
   87 
   88 static devclass_t xlr_i2c_devclass;
   89 
   90 /*
   91  * Device methods
   92  */
   93 static int xlr_i2c_probe(device_t);
   94 static int xlr_i2c_attach(device_t);
   95 static int xlr_i2c_detach(device_t);
   96 
   97 static int xlr_i2c_start(device_t dev, u_char slave, int timeout);
   98 static int xlr_i2c_stop(device_t dev);
   99 static int xlr_i2c_read(device_t dev, char *buf, int len, int *read, int last, int delay);
  100 static int xlr_i2c_write(device_t dev, const char *buf, int len, int *sent, int timeout);
  101 static int xlr_i2c_callback(device_t dev, int index, caddr_t data);
  102 static int xlr_i2c_repeated_start(device_t dev, u_char slave, int timeout);
  103 static int xlr_i2c_transfer(device_t bus, struct iic_msg *msgs, uint32_t nmsgs);
  104 
  105 struct xlr_i2c_softc {
  106         device_t dev;           /* Self */
  107         struct resource *mem_res;       /* Memory resource */
  108         volatile int flags;
  109         int sc_started;
  110         uint8_t i2cdev_addr;
  111         xlr_reg_t *iobase_i2c_regs;
  112         device_t iicbus;
  113         struct mtx sc_mtx;
  114 };
  115 
  116 static void  
  117 set_i2c_base(device_t dev)
  118 {
  119         struct xlr_i2c_softc *sc;
  120 
  121         sc = device_get_softc(dev);
  122         if (device_get_unit(dev) == 0)
  123                 sc->iobase_i2c_regs = xlr_io_mmio(XLR_IO_I2C_0_OFFSET);
  124         else
  125                 sc->iobase_i2c_regs = xlr_io_mmio(XLR_IO_I2C_1_OFFSET);
  126 }
  127 
  128 static void 
  129 xlr_i2c_dev_write(device_t dev, int reg, int value)
  130 {
  131         struct xlr_i2c_softc *sc;
  132 
  133         sc = device_get_softc(dev);
  134         xlr_write_reg(sc->iobase_i2c_regs, reg, value);
  135         return;
  136 }
  137 
  138 
  139 static int 
  140 xlr_i2c_dev_read(device_t dev, int reg)
  141 {
  142         uint32_t val;
  143         struct xlr_i2c_softc *sc;
  144 
  145         sc = device_get_softc(dev);
  146         val = xlr_read_reg(sc->iobase_i2c_regs, reg);
  147         return ((int)val);
  148 }
  149 
  150 
  151 static int
  152 xlr_i2c_probe(device_t dev)
  153 {
  154         device_set_desc(dev, "XLR/XLS I2C bus controller");
  155 
  156         return (0);
  157 }
  158 
  159 
  160 /*
  161  * We add all the devices which we know about.
  162  * The generic attach routine will attach them if they are alive.
  163  */
  164 static int
  165 xlr_i2c_attach(device_t dev)
  166 {
  167         int rid;
  168         struct xlr_i2c_softc *sc;
  169         device_t tmpd;
  170 
  171         if(device_get_unit(dev)!=ARIZONA_I2C_BUS) {
  172                 device_printf(dev, "unused iicbus instance\n");
  173                 return 0;
  174         }
  175 
  176         sc = device_get_softc(dev);
  177         set_i2c_base(dev);
  178 
  179         mtx_init(&sc->sc_mtx, "xlr_i2c", "xlr_i2c", MTX_DEF);
  180 
  181         sc->mem_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &rid, RF_ACTIVE);
  182         if (sc->mem_res == NULL) {
  183                 printf("not able to allocate the bus resource\n");
  184         }
  185         if ((sc->iicbus = device_add_child(dev, "iicbus", -1)) == NULL) {
  186                 printf("could not allocate iicbus instance\n");
  187                 return -1;
  188         }
  189         if(xlr_board_info.xlr_i2c_device[I2C_RTC].enabled == 1) {
  190                 tmpd = device_add_child(sc->iicbus, "ds1374u", 0);
  191                 device_set_ivars(tmpd, &xlr_board_info.xlr_i2c_device[I2C_RTC]);
  192         }
  193         if(xlr_board_info.xlr_i2c_device[I2C_THERMAL].enabled == 1) {
  194                 tmpd = device_add_child(sc->iicbus, "max6657", 0);
  195                 device_set_ivars(tmpd, &xlr_board_info.xlr_i2c_device[I2C_THERMAL]);
  196         }
  197         if(xlr_board_info.xlr_i2c_device[I2C_EEPROM].enabled == 1) {
  198                 tmpd = device_add_child(sc->iicbus, "at24co2n", 0);
  199                 device_set_ivars(tmpd, &xlr_board_info.xlr_i2c_device[I2C_EEPROM]);
  200         }
  201 
  202         bus_generic_attach(dev);
  203 
  204         return (0);
  205 }
  206 
  207 static int
  208 xlr_i2c_detach(device_t dev)
  209 {
  210         bus_generic_detach(dev);
  211 
  212         return (0);
  213 }
  214 
  215 static int 
  216 xlr_i2c_start(device_t dev, u_char slave, int timeout)
  217 {
  218         int error = 0;
  219         struct xlr_i2c_softc *sc;
  220 
  221         sc = device_get_softc(dev);
  222         mtx_lock(&sc->sc_mtx);
  223         sc->sc_started = 1;
  224         sc->i2cdev_addr = (slave >> 1);
  225         return error;
  226 
  227 }
  228 
  229 static int 
  230 xlr_i2c_stop(device_t dev)
  231 {
  232         int error = 0;
  233         struct xlr_i2c_softc *sc;
  234 
  235         sc = device_get_softc(dev);
  236         mtx_unlock(&sc->sc_mtx);
  237         return error;
  238 
  239 }
  240 
  241 static int 
  242 xlr_i2c_read(device_t dev, char *buf, int len, int *read, int last,
  243     int delay)
  244 {
  245         volatile uint32_t i2c_status = 0;
  246         int pos=0;
  247         int timeout = 0;
  248         
  249         xlr_i2c_dev_write(dev, XLR_I2C_CFG, XLR_I2C_CFG_NOADDR);
  250         xlr_i2c_dev_write(dev, XLR_I2C_BYTECNT, len);
  251 
  252 retry:
  253         xlr_i2c_dev_write(dev, XLR_I2C_STARTXFR, XLR_I2C_STARTXFR_RD);
  254 
  255         timeout = 0;
  256         while(1) {
  257                 if(timeout++ > MAXTIME)
  258                         return -1;
  259 
  260                 i2c_status = xlr_i2c_dev_read(dev, XLR_I2C_STATUS);
  261                 if (i2c_status & XLR_I2C_RXRDY)
  262                         buf[pos++] = (uint8_t) xlr_i2c_dev_read(dev, XLR_I2C_DATAIN);
  263 
  264                 /* ACKERR -- bail */
  265                 if (i2c_status & XLR_I2C_ACK_ERR) 
  266                          return -1;      /* ACK_ERROR */
  267 
  268                 /* LOST ARB or STARTERR -- repeat */
  269                 if (i2c_status & XLR_I2C_ARB_STARTERR)
  270                         goto retry;
  271 
  272                 /* Wait for busy bit to go away */
  273                 if (i2c_status & XLR_I2C_BUS_BUSY)
  274                         continue;
  275 
  276                 if (pos == len)
  277                         break;
  278         }       
  279         *read = pos;
  280         return 0;
  281 
  282 }
  283 
  284 static int 
  285 xlr_i2c_write(device_t dev, const char *buf, int len, int *sent, int timeout /* us */ )
  286 {
  287         volatile uint32_t i2c_status = 0x00;
  288         uint8_t devaddr, addr;
  289         struct xlr_i2c_softc *sc;
  290         int pos;
  291 
  292         sc = device_get_softc(dev);
  293 
  294         /* the first byte of write is  addr (of register in device) */
  295         addr = buf[0];
  296         devaddr = sc->i2cdev_addr;
  297         xlr_i2c_dev_write(dev, XLR_I2C_ADDR, addr);
  298         xlr_i2c_dev_write(dev, XLR_I2C_DEVADDR, devaddr);
  299         xlr_i2c_dev_write(dev, XLR_I2C_CFG, XLR_I2C_CFG_ADDR);
  300         xlr_i2c_dev_write(dev, XLR_I2C_BYTECNT, len - 1);
  301 
  302 retry:
  303         pos = 1;
  304         if (len == 1) /* there is no data only address */
  305                 xlr_i2c_dev_write(dev, XLR_I2C_STARTXFR, XLR_I2C_STARTXFR_ND);
  306         else {
  307                 xlr_i2c_dev_write(dev, XLR_I2C_STARTXFR, XLR_I2C_STARTXFR_WR);
  308                 xlr_i2c_dev_write(dev, XLR_I2C_DATAOUT, buf[pos]);
  309         }
  310 
  311         while (1) {
  312                 i2c_status = xlr_i2c_dev_read(dev, XLR_I2C_STATUS);
  313                 
  314                 /* sdo empty send next byte */
  315                 if (i2c_status & XLR_I2C_SDOEMPTY) {
  316                         pos++;
  317                         xlr_i2c_dev_write(dev, XLR_I2C_DATAOUT, buf[pos]);
  318                 }
  319 
  320                 /* LOST ARB or STARTERR -- repeat */
  321                 if (i2c_status & XLR_I2C_ARB_STARTERR) 
  322                         goto retry;
  323 
  324                 /* ACKERR -- bail */
  325                 if (i2c_status & XLR_I2C_ACK_ERR) {
  326                         printf("ACK ERR : exiting\n ");
  327                         return -1;
  328                 }
  329         
  330                 /* busy try again */    
  331                 if (i2c_status & XLR_I2C_BUS_BUSY)
  332                         continue;
  333 
  334                 if (pos >= len)
  335                         break;;
  336         }
  337         *sent = len - 1;
  338         return 0;
  339 }
  340 
  341 
  342 
  343 static int
  344 xlr_i2c_callback(device_t dev, int index, caddr_t data)
  345 {
  346         return 0;
  347 }
  348 
  349 static int
  350 xlr_i2c_repeated_start(device_t dev, u_char slave, int timeout)
  351 {
  352         return 0;
  353 }
  354 
  355 /*
  356  * I2C bus transfer for RMI boards and devices.
  357  * Generic version of iicbus_transfer that calls the appropriate
  358  * routines to accomplish this.  See note above about acceptable
  359  * buffer addresses.
  360  */
  361 int
  362 xlr_i2c_transfer(device_t bus, struct iic_msg *msgs, uint32_t nmsgs)
  363 {       
  364         int i, error, lenread, lenwrote;
  365         u_char addr;
  366  
  367         addr = msgs[0].slave | LSB;
  368         error = xlr_i2c_start(bus, addr, 0);
  369         for (i = 0, error = 0; i < nmsgs && error == 0; i++) {
  370                 if (msgs[i].flags & IIC_M_RD) {
  371                         error = xlr_i2c_read((bus), msgs[i].buf, msgs[i].len, &lenread, IIC_LAST_READ, 0);
  372                 }
  373                 else {    
  374                         error = xlr_i2c_write((bus), msgs[i].buf, msgs[i].len, &lenwrote, 0);
  375                 }
  376         }       
  377         error = xlr_i2c_stop(bus);
  378         return (error);
  379 }
  380 
  381 
  382 static device_method_t xlr_i2c_methods[] = {
  383         /* device interface */
  384         DEVMETHOD(device_probe, xlr_i2c_probe),
  385         DEVMETHOD(device_attach, xlr_i2c_attach),
  386         DEVMETHOD(device_detach, xlr_i2c_detach),
  387 
  388         /* iicbus interface */
  389         DEVMETHOD(iicbus_callback, xlr_i2c_callback),
  390         DEVMETHOD(iicbus_repeated_start, xlr_i2c_repeated_start),
  391         DEVMETHOD(iicbus_start, xlr_i2c_start),
  392         DEVMETHOD(iicbus_stop, xlr_i2c_stop),
  393         DEVMETHOD(iicbus_write, xlr_i2c_write),
  394         DEVMETHOD(iicbus_read, xlr_i2c_read),
  395         DEVMETHOD(iicbus_transfer, xlr_i2c_transfer),
  396         {0, 0}
  397 };
  398 
  399 static driver_t xlr_i2c_driver = {
  400         "xlr_i2c",
  401         xlr_i2c_methods,
  402         sizeof(struct xlr_i2c_softc),
  403 };
  404 
  405 DRIVER_MODULE(xlr_i2c, iodi, xlr_i2c_driver, xlr_i2c_devclass, 0, 0);
  406 DRIVER_MODULE(iicbus, xlr_i2c, iicbus_driver, iicbus_devclass, 0, 0);

Cache object: 63ed00d4023722d48b28a1889204185e


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