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/module.h>
   42 #include <sys/bus.h>
   43 #include <sys/rman.h>
   44 
   45 
   46 #include <dev/iicbus/iiconf.h>
   47 #include <dev/iicbus/iicbus.h>
   48 
   49 #include <mips/rmi/iomap.h>
   50 #include <mips/include/resource.h>
   51 
   52 #include "iicbus_if.h"
   53 
   54 #define DEVTOIICBUS(dev) ((struct iicbus_device*)device_get_ivars(dev))
   55 
   56 #define I2C_PALM_CFG            0x00
   57 #define I2C_PALM_CLKDIV         0x01
   58 #define I2C_PALM_DEVADDR        0x02
   59 #define I2C_PALM_ADDR           0x03
   60 #define I2C_PALM_DATAOUT        0x04
   61 #define I2C_PALM_DATAIN         0x05
   62 #define I2C_PALM_STATUS         0x06
   63 #define I2C_PALM_STARTXFR       0x07
   64 #define I2C_PALM_BYTECNT        0x08
   65 #define I2C_PALM_HDSTATIM       0x09
   66 
   67 /* TEST Values!! Change as required */
   68 #define I2C_PALM_CFG_DEF        0x000000F8      /* 8-Bit Addr + POR Values */
   69 #define I2C_PALM_CLKDIV_DEF     0x14A //0x00000052
   70 #define I2C_PALM_HDSTATIM_DEF       0x107 //0x00000000
   71 
   72 #define I2C_PALM_STARTXFR_RD        0x00000001
   73 #define I2C_PALM_STARTXFR_WR        0x00000000
   74 
   75 
   76 #define PHOENIX_IO_I2C_0_OFFSET           0x16000
   77 #define PHOENIX_IO_I2C_1_OFFSET           0x17000
   78 
   79 #define ARIZONA_I2c_BUS 1
   80 
   81 int bus = 1;
   82 
   83 
   84 uint8_t current_slave;
   85 uint8_t read_address;
   86 static xlr_reg_t *iobase_i2c_regs;
   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, char *buf, int len, int *sent, int timeout);
  101 
  102 
  103 struct xlr_i2c_softc {
  104         device_t dev;           /* Myself */
  105         struct resource *mem_res;       /* Memory resource */
  106         volatile int flags;
  107 #define RXRDY       4
  108 #define TXRDY       0x10
  109         int sc_started;
  110         int twi_addr;
  111         device_t iicbus;
  112 };
  113 
  114 
  115 #define MDELAY(a){ \
  116     unsigned long  local_loop = 0xfffff; \
  117     while(local_loop--); \
  118 }\
  119 
  120 static void 
  121 get_i2c_base(void)
  122 {
  123         if (bus == 0)
  124                 iobase_i2c_regs = xlr_io_mmio(PHOENIX_IO_I2C_0_OFFSET);
  125         else
  126                 iobase_i2c_regs = xlr_io_mmio(PHOENIX_IO_I2C_1_OFFSET);
  127         return;
  128 }
  129 
  130 static void 
  131 palm_write(int reg, int value)
  132 {
  133         get_i2c_base();
  134         xlr_write_reg(iobase_i2c_regs, reg, value);
  135         return;
  136 }
  137 
  138 
  139 static int 
  140 palm_read(int reg)
  141 {
  142         uint32_t val;
  143 
  144         get_i2c_base();
  145         val = xlr_read_reg(iobase_i2c_regs, reg);
  146         return ((int)val);
  147 }
  148 
  149 static int 
  150 palm_addr_only(uint8_t addr, uint8_t offset)
  151 {
  152         volatile uint32_t regVal = 0x00;
  153 
  154         palm_write(I2C_PALM_ADDR, offset);
  155         palm_write(I2C_PALM_DEVADDR, addr);
  156         palm_write(I2C_PALM_CFG, 0xfa);
  157         palm_write(I2C_PALM_STARTXFR, 0x02);
  158         regVal = palm_read(I2C_PALM_STATUS);
  159         if (regVal & 0x0008) {
  160                 printf("palm_addr_only: ACKERR. Aborting...\n");
  161                 return -1;
  162         }
  163         return 0;
  164 }
  165 
  166 
  167 static int 
  168 palm_rx(uint8_t addr, uint8_t offset, uint8_t len,
  169     uint8_t * buf)
  170 {
  171         volatile uint32_t regVal = 0x00, ctr = 0x00;
  172         int timeOut, numBytes = 0x00;
  173 
  174         palm_write(I2C_PALM_CFG, 0xfa);
  175         palm_write(I2C_PALM_BYTECNT, len);
  176         palm_write(I2C_PALM_DEVADDR, addr);
  177         //DEVADDR = 0x4c, 0x68
  178             MDELAY(1);
  179 
  180         for (numBytes = 0x00; numBytes < len; numBytes++) {
  181                 palm_write(I2C_PALM_ADDR, offset + numBytes);
  182 //I2C_PALM_ADDR:offset
  183                     MDELAY(1);
  184                 if (!ctr) {
  185                         /* Trigger a READ Transaction */
  186                         palm_write(I2C_PALM_STARTXFR, I2C_PALM_STARTXFR_RD);
  187                         ctr++;
  188                 }
  189                 /* Error Conditions [Begin] */
  190                 regVal = palm_read(I2C_PALM_STATUS);
  191                 MDELAY(1);
  192                 if (regVal & 0x0008) {
  193                         printf("palm_rx: ACKERR. Aborting...\n");
  194                         return -1;
  195                 }
  196                 timeOut = 10;
  197                 while ((regVal & 0x0030) && timeOut--) {
  198                         palm_write(I2C_PALM_STARTXFR, I2C_PALM_STARTXFR_RD);
  199                         regVal = palm_read(I2C_PALM_STATUS);
  200                 }
  201                 if (timeOut == 0x00) {
  202                         printf("palm_rx: TimedOut on Valid STARTXFR/Arbitration\n");
  203                         return -1;
  204                 }
  205                 timeOut = 10;
  206                 /* Do we have valid data from the device yet..? */
  207                 regVal &= 0x0004;
  208                 while (!regVal && timeOut--) {
  209                         regVal = palm_read(I2C_PALM_STATUS) & 0x0004;
  210                 }
  211                 if (timeOut == 0x00) {
  212                         printf("palm_rx: TimedOut Waiting for Valid Data\n");
  213                         return -1;
  214                 }
  215                 /* Error Conditions [End] */
  216                 /* Read the data */
  217                 buf[numBytes] = (uint8_t) palm_read(I2C_PALM_DATAIN);
  218         }
  219         return 0;
  220 }
  221 
  222 
  223 
  224 static int 
  225 wait_for_idle(void)
  226 {
  227         int timeOut = 0x1000;
  228         volatile uint32_t regVal = 0x00;
  229 
  230         regVal = palm_read(I2C_PALM_STATUS) & 0x0001;
  231         while (regVal && timeOut--) {
  232                 regVal = palm_read(I2C_PALM_STATUS) & 0x0001;
  233         }
  234         if (timeOut == 0x00)
  235                 return -1;      /* Timed Out */
  236         else
  237                 return 0;
  238 }
  239 
  240 
  241 static int 
  242 palm_tx(uint8_t addr, uint8_t offset, uint8_t * buf, uint8_t len)
  243 {
  244         volatile uint32_t regVal = 0x00;
  245         int timeOut, ctr = 0x00, numBytes = len;
  246 
  247         for (ctr = 0x00; ctr < len; ctr++) {
  248                 if (wait_for_idle() < 0) {
  249                         printf("TimedOut on Waiting for I2C Bus Idle.\n");
  250                         return -EIO;
  251                 }
  252                 palm_write(I2C_PALM_CFG, 0xF8);
  253                 palm_write(I2C_PALM_BYTECNT, 0x00);
  254                 palm_write(I2C_PALM_DEVADDR, addr);
  255                 //0x4c, 0x68
  256                     palm_write(I2C_PALM_ADDR, offset + numBytes - 1);
  257                 //offset
  258                     palm_write(I2C_PALM_DATAOUT, buf[ctr]);
  259                 palm_write(I2C_PALM_STARTXFR, I2C_PALM_STARTXFR_WR);
  260                 MDELAY(1);
  261 
  262                 regVal = palm_read(I2C_PALM_STATUS);
  263                 MDELAY(1);
  264                 if (regVal & 0x0008) {
  265                         printf("palm_tx: ACKERR. Aborting...\n");
  266                         return -1;
  267                 }
  268                 timeOut = 0x1000;
  269                 while (!(regVal & 0x0002) && timeOut) {
  270                         regVal = palm_read(I2C_PALM_STATUS);
  271                         timeOut--;
  272                 }
  273                 if (timeOut == 0x00) {
  274                         printf("palm_tx: [TimeOut] SDOEMPTY Not Set\n");
  275                         return -1;
  276                 }
  277                 timeOut = 1000;
  278                 while ((regVal & 0x0030) && timeOut) {
  279                         palm_write(I2C_PALM_STARTXFR, I2C_PALM_STARTXFR_WR);
  280                         regVal = palm_read(I2C_PALM_STATUS);
  281                         timeOut--;
  282                 }
  283                 if (timeOut == 0x00) {
  284                         printf("palm_rx: TimedOut on Valid STARTXFR/Arbitration\n");
  285                         return -1;
  286                 }
  287                 numBytes--;
  288         }
  289         return 0;
  290 }
  291 
  292 
  293 
  294 
  295 
  296 static int
  297 xlr_i2c_probe(device_t dev)
  298 {
  299         device_set_desc(dev, "I2C bus controller");
  300 
  301         return (0);
  302 }
  303 
  304 
  305 /*
  306  * We add all the devices which we know about.
  307  * The generic attach routine will attach them if they are alive.
  308  */
  309 static int
  310 xlr_i2c_attach(device_t dev)
  311 {
  312         struct xlr_i2c_softc *sc;
  313         int rid;
  314 
  315         sc = device_get_softc(dev);
  316         sc->mem_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &rid,
  317             RF_ACTIVE);
  318         if (sc->mem_res == NULL) {
  319                 printf("not able to allocate the bus resource\n");
  320         }
  321         if ((sc->iicbus = device_add_child(dev, "iicbus", -1)) == NULL)
  322                 printf("could not allocate iicbus instance\n");
  323 
  324         bus_generic_attach(dev);
  325 
  326         return (0);
  327 }
  328 
  329 static int
  330 xlr_i2c_detach(device_t dev)
  331 {
  332         bus_generic_detach(dev);
  333 
  334         return (0);
  335 }
  336 
  337 /*
  338 static int
  339 xlr_i2c_add_child(device_t dev, int order, const char *name, int unit)
  340 {
  341     printf("********* %s ********  \n", __FUNCTION__);
  342         device_add_child_ordered(dev, order, name, unit);
  343 
  344         bus_generic_attach(dev);
  345 
  346         return (0);
  347 }
  348 */
  349 
  350 static int 
  351 xlr_i2c_start(device_t dev, u_char slave, int timeout)
  352 {
  353         int error = 0;
  354         struct xlr_i2c_softc *sc;
  355 
  356         sc = device_get_softc(dev);
  357         sc->sc_started = 1;
  358 
  359         current_slave = (slave >> 1);
  360         return error;
  361 
  362 }
  363 
  364 static int 
  365 xlr_i2c_stop(device_t dev)
  366 {
  367         int error = 0;
  368 
  369         return error;
  370 
  371 }
  372 
  373 static int 
  374 xlr_i2c_read(device_t dev, char *buf, int len, int *read, int last,
  375     int delay)
  376 {
  377         int error = 0;
  378 
  379         if (palm_addr_only(current_slave, read_address) == -1) {
  380                 printf("I2C ADDRONLY Phase Fail.\n");
  381                 return -1;
  382         }
  383         if (palm_rx(current_slave, read_address, len, buf) == -1) {
  384                 printf("I2C Read Fail.\n");
  385                 return -1;
  386         }
  387         *read = len;
  388         return error;
  389 
  390 }
  391 
  392 
  393 static int 
  394 xlr_i2c_write(device_t dev, char *buf, int len, int *sent, int timeout /* us */ )
  395 {
  396 
  397         int error = 0;
  398         uint8_t write_address;
  399 
  400         if (len == 1) {
  401                 /* address for the next read */
  402                 read_address = buf[0];
  403                 return error;
  404         }
  405         if (len < 2)
  406                 return (-1);
  407 
  408         write_address = buf[0];
  409 
  410         /*
  411          * for write operation, buf[0] contains the register offset and
  412          * buf[1] onwards contains the value
  413          */
  414         palm_tx(current_slave, write_address, &buf[1], len - 1);
  415 
  416         return error;
  417 
  418 }
  419 
  420 static int
  421 xlr_i2c_callback(device_t dev, int index, caddr_t *data)
  422 {
  423         return 0;
  424 }
  425 
  426 static int
  427 xlr_i2c_repeated_start(device_t dev, u_char slave, int timeout)
  428 {
  429         return 0;
  430 }
  431 
  432 
  433 static device_method_t xlr_i2c_methods[] = {
  434         /* device interface */
  435         DEVMETHOD(device_probe, xlr_i2c_probe),
  436         DEVMETHOD(device_attach, xlr_i2c_attach),
  437         DEVMETHOD(device_detach, xlr_i2c_detach),
  438 
  439         /* iicbus interface */
  440         DEVMETHOD(iicbus_callback, xlr_i2c_callback),
  441         DEVMETHOD(iicbus_repeated_start, xlr_i2c_repeated_start),
  442         DEVMETHOD(iicbus_start, xlr_i2c_start),
  443         DEVMETHOD(iicbus_stop, xlr_i2c_stop),
  444         DEVMETHOD(iicbus_write, xlr_i2c_write),
  445         DEVMETHOD(iicbus_read, xlr_i2c_read),
  446         {0, 0}
  447 };
  448 
  449 static driver_t xlr_i2c_driver = {
  450         "xlr_i2c",
  451         xlr_i2c_methods,
  452         sizeof(struct xlr_i2c_softc),
  453 };
  454 
  455 DRIVER_MODULE(xlr_i2c, iodi, xlr_i2c_driver, xlr_i2c_devclass, 0, 0);

Cache object: d389ea24ba9f28295db78a9750bc524d


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