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$");
   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, "ds13rtc", 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         /*
  203          * The old ds1374 rtc driver only handled one chip type.  The new
  204          * ds13rtc driver handles all ds13xx chips, but must be told the chip
  205          * type via hints.  XLR historically hasn't had a standard hints file,
  206          * so set up the hint now if it isn't already there.
  207          */
  208 #define HINTNAME "hint.ds13rtc.0.compatible"
  209         if (!testenv(HINTNAME))
  210                 kern_setenv(HINTNAME, "dallas,ds1374");
  211 
  212         bus_generic_attach(dev);
  213 
  214         return (0);
  215 }
  216 
  217 static int
  218 xlr_i2c_detach(device_t dev)
  219 {
  220         bus_generic_detach(dev);
  221 
  222         return (0);
  223 }
  224 
  225 static int 
  226 xlr_i2c_start(device_t dev, u_char slave, int timeout)
  227 {
  228         int error = 0;
  229         struct xlr_i2c_softc *sc;
  230 
  231         sc = device_get_softc(dev);
  232         mtx_lock(&sc->sc_mtx);
  233         sc->sc_started = 1;
  234         sc->i2cdev_addr = (slave >> 1);
  235         return error;
  236 
  237 }
  238 
  239 static int 
  240 xlr_i2c_stop(device_t dev)
  241 {
  242         int error = 0;
  243         struct xlr_i2c_softc *sc;
  244 
  245         sc = device_get_softc(dev);
  246         mtx_unlock(&sc->sc_mtx);
  247         return error;
  248 
  249 }
  250 
  251 static int 
  252 xlr_i2c_read(device_t dev, char *buf, int len, int *read, int last,
  253     int delay)
  254 {
  255         volatile uint32_t i2c_status = 0;
  256         int pos=0;
  257         int timeout = 0;
  258         
  259         xlr_i2c_dev_write(dev, XLR_I2C_CFG, XLR_I2C_CFG_NOADDR);
  260         xlr_i2c_dev_write(dev, XLR_I2C_BYTECNT, len);
  261 
  262 retry:
  263         xlr_i2c_dev_write(dev, XLR_I2C_STARTXFR, XLR_I2C_STARTXFR_RD);
  264 
  265         timeout = 0;
  266         while(1) {
  267                 if(timeout++ > MAXTIME)
  268                         return -1;
  269 
  270                 i2c_status = xlr_i2c_dev_read(dev, XLR_I2C_STATUS);
  271                 if (i2c_status & XLR_I2C_RXRDY)
  272                         buf[pos++] = (uint8_t) xlr_i2c_dev_read(dev, XLR_I2C_DATAIN);
  273 
  274                 /* ACKERR -- bail */
  275                 if (i2c_status & XLR_I2C_ACK_ERR) 
  276                          return -1;      /* ACK_ERROR */
  277 
  278                 /* LOST ARB or STARTERR -- repeat */
  279                 if (i2c_status & XLR_I2C_ARB_STARTERR)
  280                         goto retry;
  281 
  282                 /* Wait for busy bit to go away */
  283                 if (i2c_status & XLR_I2C_BUS_BUSY)
  284                         continue;
  285 
  286                 if (pos == len)
  287                         break;
  288         }       
  289         *read = pos;
  290         return 0;
  291 
  292 }
  293 
  294 static int 
  295 xlr_i2c_write(device_t dev, const char *buf, int len, int *sent, int timeout /* us */ )
  296 {
  297         volatile uint32_t i2c_status = 0x00;
  298         uint8_t devaddr, addr;
  299         struct xlr_i2c_softc *sc;
  300         int pos;
  301 
  302         sc = device_get_softc(dev);
  303 
  304         /* the first byte of write is  addr (of register in device) */
  305         addr = buf[0];
  306         devaddr = sc->i2cdev_addr;
  307         xlr_i2c_dev_write(dev, XLR_I2C_ADDR, addr);
  308         xlr_i2c_dev_write(dev, XLR_I2C_DEVADDR, devaddr);
  309         xlr_i2c_dev_write(dev, XLR_I2C_CFG, XLR_I2C_CFG_ADDR);
  310         xlr_i2c_dev_write(dev, XLR_I2C_BYTECNT, len - 1);
  311 
  312 retry:
  313         pos = 1;
  314         if (len == 1) /* there is no data only address */
  315                 xlr_i2c_dev_write(dev, XLR_I2C_STARTXFR, XLR_I2C_STARTXFR_ND);
  316         else {
  317                 xlr_i2c_dev_write(dev, XLR_I2C_STARTXFR, XLR_I2C_STARTXFR_WR);
  318                 xlr_i2c_dev_write(dev, XLR_I2C_DATAOUT, buf[pos]);
  319         }
  320 
  321         while (1) {
  322                 i2c_status = xlr_i2c_dev_read(dev, XLR_I2C_STATUS);
  323                 
  324                 /* sdo empty send next byte */
  325                 if (i2c_status & XLR_I2C_SDOEMPTY) {
  326                         pos++;
  327                         xlr_i2c_dev_write(dev, XLR_I2C_DATAOUT, buf[pos]);
  328                 }
  329 
  330                 /* LOST ARB or STARTERR -- repeat */
  331                 if (i2c_status & XLR_I2C_ARB_STARTERR) 
  332                         goto retry;
  333 
  334                 /* ACKERR -- bail */
  335                 if (i2c_status & XLR_I2C_ACK_ERR) {
  336                         printf("ACK ERR : exiting\n ");
  337                         return -1;
  338                 }
  339         
  340                 /* busy try again */    
  341                 if (i2c_status & XLR_I2C_BUS_BUSY)
  342                         continue;
  343 
  344                 if (pos >= len)
  345                         break;
  346         }
  347         *sent = len - 1;
  348         return 0;
  349 }
  350 
  351 
  352 
  353 static int
  354 xlr_i2c_callback(device_t dev, int index, caddr_t data)
  355 {
  356         return 0;
  357 }
  358 
  359 static int
  360 xlr_i2c_repeated_start(device_t dev, u_char slave, int timeout)
  361 {
  362         return 0;
  363 }
  364 
  365 /*
  366  * I2C bus transfer for RMI boards and devices.
  367  * Generic version of iicbus_transfer that calls the appropriate
  368  * routines to accomplish this.  See note above about acceptable
  369  * buffer addresses.
  370  */
  371 int
  372 xlr_i2c_transfer(device_t bus, struct iic_msg *msgs, uint32_t nmsgs)
  373 {       
  374         int i, error, lenread, lenwrote;
  375         u_char addr;
  376  
  377         addr = msgs[0].slave | LSB;
  378         error = xlr_i2c_start(bus, addr, 0);
  379         for (i = 0, error = 0; i < nmsgs && error == 0; i++) {
  380                 if (msgs[i].flags & IIC_M_RD) {
  381                         error = xlr_i2c_read((bus), msgs[i].buf, msgs[i].len, &lenread, IIC_LAST_READ, 0);
  382                 }
  383                 else {    
  384                         error = xlr_i2c_write((bus), msgs[i].buf, msgs[i].len, &lenwrote, 0);
  385                 }
  386         }       
  387         error = xlr_i2c_stop(bus);
  388         return (error);
  389 }
  390 
  391 
  392 static device_method_t xlr_i2c_methods[] = {
  393         /* device interface */
  394         DEVMETHOD(device_probe, xlr_i2c_probe),
  395         DEVMETHOD(device_attach, xlr_i2c_attach),
  396         DEVMETHOD(device_detach, xlr_i2c_detach),
  397 
  398         /* iicbus interface */
  399         DEVMETHOD(iicbus_callback, xlr_i2c_callback),
  400         DEVMETHOD(iicbus_repeated_start, xlr_i2c_repeated_start),
  401         DEVMETHOD(iicbus_start, xlr_i2c_start),
  402         DEVMETHOD(iicbus_stop, xlr_i2c_stop),
  403         DEVMETHOD(iicbus_write, xlr_i2c_write),
  404         DEVMETHOD(iicbus_read, xlr_i2c_read),
  405         DEVMETHOD(iicbus_transfer, xlr_i2c_transfer),
  406         {0, 0}
  407 };
  408 
  409 static driver_t xlr_i2c_driver = {
  410         "xlr_i2c",
  411         xlr_i2c_methods,
  412         sizeof(struct xlr_i2c_softc),
  413 };
  414 
  415 DRIVER_MODULE(xlr_i2c, iodi, xlr_i2c_driver, xlr_i2c_devclass, 0, 0);
  416 DRIVER_MODULE(iicbus, xlr_i2c, iicbus_driver, iicbus_devclass, 0, 0);

Cache object: afdd001b65c0fb20bd3bbf99cb7403c0


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