Logo Search packages:      
Sourcecode: i2c version File versions

i2c-algo-biths.c

/* ------------------------------------------------------------------------- */
/* i2c-algo-biths.c i2c driver algorithms for bit-shift adapters       */
/* ------------------------------------------------------------------------- */
/*   Copyright (C) 1995-2000 Simon G. Vogl
     Copyright (C) 2002-2003 Kyösti Mälkki

    This program is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation; either version 2 of the License, or
    (at your option) any later version.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with this program; if not, write to the Free Software
    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.                */
/* ------------------------------------------------------------------------- */

/* $Id: i2c-algo-biths.c,v 1.16 2005/03/11 20:37:33 khali Exp $ */

#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/delay.h>
#include <linux/slab.h>
#include <linux/init.h>
#include <linux/errno.h>
#include <linux/sched.h>
#include "i2c.h"
#include "i2c-algo-biths.h"

/* ----- global defines ----------------------------------------------- */

/* If non-zero, adapter code written for original i2c-algo-bit can be used unmodified. 
 * As this export same symbols, you should either remove i2c-algo-bit.o from depmod
 * directories, or load this module manually.
 */
#ifndef ALGO_BIT_COMPATIBILITY
#define ALGO_BIT_COMPATIBILITY 0
#endif

#define FATAL_BUS 0
#define MODULE_STATUS   1
#define FATAL_MSG 2
#define FATAL_PROTOCOL  3
#define ALL_MSG         4
#define ALL_PROTOCOL    5
#define BIT_LEVEL 9

#define DEB1(x)         if (i2c_debug>=MODULE_STATUS) (x);
static void proto_s(char *d, const char *s) { strcat(d, s); }
static void proto_x(char *d, const char *x, unsigned char y) { while (*d) d++; sprintf(d, x, y); }
#define PROTO_S(x)      if (adap->dstr) proto_s(adap->dstr, x)
#define PROTO_B(x)      if ((adap->dstr) && (i2c_debug>=BIT_LEVEL)) proto_s(adap->dstr, x)
#define PROTO_X(x,y)    if (adap->dstr) proto_x(adap->dstr, x, y)

#define PROTO_MAX_DUMP 1024  // 50 x ".oooooooo [xx] .i[xx]"

/* ----- global variables --------------------------------------------- */

/* module parameters:
 */
static int i2c_debug; 
static int bit_test;    /* see if the line-setting functions work */

/* Bus timing for 50/50 duty cycle :  T_setup + T_hold = T_scllo = T_sclhi */
/* Run setscl/setsda with a special flag */
#define T_min   0       /* after any SCL SDA change   */
#define T_sclhi _HS_DBL_DT    /* SCL high             */
#define T_scllo   _HS_DBL_DT  /* SCL low              */
#define T_setup 0       /* SDA change to SCL rise     */
#define T_hold  0       /* SCL fall to SDA change     */

#define _sf(a)          adap->ctrl|=(a)
#define _cf(a)          adap->ctrl&=~(a)
#define ___setscl(b)    if (b) _sf(_HS_SCL); else _cf(_HS_SCL); i2c_setscl(adap)
#define ___setsda(b)    if (b) _sf(_HS_SDA); else _cf(_HS_SDA); i2c_setsda(adap)

#define __setdt(x,dt)   if (dt) _sf(dt); x; if (dt) _cf(dt)
#define __setscl(b,dt)  __setdt(___setscl(b),dt)
#define __setsda(b,dt)  __setdt(___setsda(b),dt)
#define __getscl()      i2c_getscl(adap)
#define __getsda()      i2c_getsda(adap)

#define RETURN_ON_FAILURE(x)        x; if (adap->errors) return
#define TRY(x) RETURN_ON_FAILURE(x)

#define _setscl(b,dt)   RETURN_ON_FAILURE(__setscl(b,dt))
#define _setsda(b,dt)   RETURN_ON_FAILURE(__setsda(b,dt))
#define _getscl         __getscl
#define _getsda         __getsda

#define _sclhi(dt)      _setscl(1,dt)
#define _scllo(dt)      _setscl(0,dt)
#define _sdahi(dt)      _setsda(1,dt)
#define _sdalo(dt)      _setsda(0,dt)

/* --- setting states on the bus with the right timing: --------------- */

static int i2c_sda_set(struct i2c_algo_biths_data *adap, int rdcount)
{
      int sda;
      /* allow some rise/fall time */
      while ( rdcount-- ) {
            sda = adap->getsda(adap->hw_data);
            if (adap->ctrl & _HS_SDA) {
                  if (sda)
                        return 0;
                  if (!rdcount) {
                        adap->errors |= _HS_SDA_ARB;
                        return -1;
                  }
            } else { /* !(adap->ctrl & _HS_SDA) */
                  if (!sda)
                        return 0;
                  if (!rdcount) {
                        adap->errors |= _HS_HW_FAIL;
                        return -1;
                  }
            }
      }
      return 0;
}

static void i2c_setsda(struct i2c_algo_biths_data *adap)
{
      adap->setstate(adap); 
      adap->setsda(adap->hw_data, adap->hw_state);
      if ( !(adap->ctrl & _HS_SDA_FREE) && ! i2c_sda_set(adap, 10)) {
            return;
      }
      adap->set_timer(adap);
      adap->run_timer(adap);
}

static int i2c_getscl(struct i2c_algo_biths_data *adap)
{
      return adap->getscl(adap->hw_data);
}

static int i2c_getsda(struct i2c_algo_biths_data *adap)
{
      return adap->getsda(adap->hw_data);
}
/*
 * Raise scl line, and do check for delays. This is necessary for slower
 * devices.
 */

static void i2c_setscl(struct i2c_algo_biths_data *adap)
{
#ifndef HW_CANNOT_READ_SCL /* Not all adapters have scl sense line... */
      int rdcount = 10;
      adap->setstate(adap);
      adap->setscl(adap->hw_data, adap->hw_state);
      if (adap->ctrl & _HS_SCL) {
            unsigned long start;
            /* allow some rise time */
            while (rdcount && !adap->getscl(adap->hw_data)) rdcount--;
            /* else clock synchronisation, give more time */
            start = jiffies;
            while (!rdcount && !adap->getscl(adap->hw_data)) {
                  if ( time_after(jiffies, start+adap->timeout) ) {
                        adap->errors |= _HS_TIMEOUT; /* scl undef */
                        return;
                  }
#ifdef cond_resched
                  cond_resched();
#else
                  if (current->need_resched) {
                        set_current_state(TASK_UNINTERRUPTIBLE);
                        schedule_timeout(1);
                  }
#endif
            }
            adap->set_timer(adap);
            /* test for SDA arbitration when SCL is high */
            if ( !(adap->ctrl & _HS_SDA_FREE) && ! i2c_sda_set(adap, 1)) {
                  return;
            }
      } else {
            /* allow some fall time */
            while (rdcount && adap->getscl(adap->hw_data)) rdcount--;
            if ( !rdcount ) {
                  adap->errors |= _HS_HW_FAIL;
                  return;
            }
            adap->set_timer(adap);
      }
#else
      adap->setstate(adap);
      adap->setscl(adap->hw_data, adap->hw_state);
      adap->set_timer(adap);
#endif /* HW_CANNOT_READ_SCL */
      adap->run_timer(adap);
}


/* start, repstart */
static void i2c_start(struct i2c_algo_biths_data *adap)
{
      PROTO_S("S");
      /* assert: scl, sda undef */
      adap->errors = 0;
      _sdahi(T_setup);
      _sclhi(T_min);
      _sdalo(T_min);
      _scllo(T_hold);
      /* assert: scl, sda low */
}

static void i2c_stop(struct i2c_algo_biths_data *adap)
{
      PROTO_S(" P");
      /* scl undef after error, sda, scl freedom unknown */
      adap->ctrl &= ~(_HS_SDA_FREE | _HS_DBL_DT);
      if (adap->errors) {
            adap->errors = 0;
            _scllo(T_hold);
      }
      /* assert: scl low, sda undef */
      _sdalo(T_setup);
      _sclhi(T_min);
      _sdahi(T_min);
      /* assert: scl, sda high */
}


static void i2c_outbits(struct i2c_algo_biths_data *adap, int i) 
{
      /* assert: scl is low */
      PROTO_B(".");
      while  (i--) {
            PROTO_B("o");
            _setsda(adap->shiftreg & 0x80, T_setup);
            _sclhi(T_sclhi);
            _scllo(T_hold);
            adap->shiftreg<<=1;
      }
      /* assert: scl is low */
}

static void i2c_inbits(struct i2c_algo_biths_data *adap, int i)
{
      /* assert: scl is low, sda undef */
      adap->ctrl |= _HS_SDA_FREE;
      PROTO_B(".");
      while  (i--) {
            PROTO_B("i");
            _sdahi(T_setup); 
            _sclhi(T_sclhi);  
            adap->shiftreg<<=1;
            if (_getsda())
                  adap->shiftreg |= 0x01;
            _scllo(T_hold);
      }
      adap->ctrl &= ~_HS_SDA_FREE;
      /* assert: scl is low */
}

static void i2c_outb(struct i2c_algo_biths_data *adap, unsigned short flags,
                 char *buf, int *count) 
{
      while (*count) {
            adap->shiftreg = *buf;
            TRY(i2c_outbits(adap, 8));
            PROTO_X(" %02X ", *buf);
            buf++;
          
            /* read ack: SDA should be pulled down by slave */
            TRY(i2c_inbits(adap, 1));
          
            if (! (adap->shiftreg & 0x01)) { 
                  PROTO_S("[A]");
            } else if (flags & I2C_M_IGNORE_NAK) {
                  PROTO_S("[NA]");
            } else {
                  PROTO_S("[NA]");
                  adap->errors |= _HS_NAK;
            }
            if (adap->errors) return;
            (*count)--;
      }
}

static void i2c_inb(struct i2c_algo_biths_data *adap, unsigned short flags,
                char *buf, int *count) 
{
      while (*count) {
            TRY(i2c_inbits(adap, 8));
            *buf = adap->shiftreg;
            PROTO_X(" [%02X] ", *buf);
            buf++;
          
            if (! (flags & I2C_M_NO_RD_ACK)) {
                  if (*count == 1) /* was last */
                        adap->shiftreg = 0x80;
                  else
                        adap->shiftreg = 0x00;
                  TRY(i2c_outbits(adap,1));

                  if (*count == 1) {
                        PROTO_S("NA");
                  } else {
                        PROTO_S("A");
                  }
            }
            (*count)--;
      }
}


static void debug_protocol(struct i2c_algo_biths_data *adap, int retval)
{
      if (! adap->dstr) return;

      if ( ((retval<0) && (i2c_debug>=FATAL_PROTOCOL)) || 
           (i2c_debug>=ALL_PROTOCOL) ) {
            printk(KERN_DEBUG "i2c-algo-biths.o: %s: %s\n", adap->name, adap->dstr); 
      }
      *adap->dstr = 0;
}

static const char * i2c_strerr(int retval)
{ 
      switch (retval) {
          case 2:
                return "ack";
            
          case 1:
                return "no ack (ignored)";

          case 0:
                return "not reached";

          case -EREMOTEIO:
                return "no ack";

          case -ETIMEDOUT:
                return "SCL rise timeout";
       
          case -ECOMM:
                return "SDA arbitration";

          case -ENODEV:
                return "SCL/SDA failure";

          default:
                return "unknown";
      }
}

static int errflag(int flags)
{
      if (! flags)
            return 2;
      if (flags & _HS_HW_FAIL)
            return -ENODEV;
      if (flags & _HS_SDA_ARB)
            return -ECOMM;
      if (flags & _HS_TIMEOUT)
            return -ETIMEDOUT;
      if (flags & _HS_NAK)
            return -EREMOTEIO;

      return -1;
}

static void debug_printout(struct i2c_adapter *i2c_adap, int num, int retval)
{ 
      if ( ((retval<0) && (i2c_debug>=FATAL_MSG)) ||
           (i2c_debug>=ALL_MSG) ) {
            printk(KERN_ERR "i2c-algo-biths.o: %s: msg #%d %s\n", i2c_adap->name, num, i2c_strerr(retval));
      }
}

/*
 * Sanity check for the adapter hardware
 */
static int test_bus(struct i2c_algo_biths_data *adap)
{

      int sscl, ssda, gscl, gsda, i=0;
      int errors;
      int test[][2] = {{1,1}, {0,1}, {1,1}, {1,0}, {1,1}, {-1,-1}}; // SDA, SCL pair

      printk(KERN_INFO "i2c-algo-biths.o: %s bus test\n", adap->name);

      while ( test[i][0]!=-1 ) {
            ssda = test[i][0];
            sscl = test[i][1];

            adap->errors = 0;
            __setsda(ssda, T_min);
            gsda = __getsda() ? 1 : 0;
            errors = adap->errors & (_HS_HW_FAIL | _HS_SDA_ARB);
            if (errors)
                  printk(KERN_WARNING "i2c-algo-biths.o: %s %s\n", adap->name,
                         i2c_strerr(errflag(errors)));
          
            __setscl(sscl, T_min);
            gscl = __getscl() ? 1 : 0;
            errors = adap->errors & (_HS_HW_FAIL | _HS_TIMEOUT);
            if (errors)
                  printk(KERN_WARNING "i2c-algo-biths.o: %s %s\n", adap->name,
                         i2c_strerr(errflag(errors)));

            printk(KERN_DEBUG "i2c-algo-biths.o: %s SCL: %d  SDA: %d\n", adap->name, gscl, gsda);
            if ( sscl!=gscl )
                  printk(KERN_WARNING "i2c-algo-biths.o: %s SCL set %d, got %d!\n", adap->name, sscl, gscl);
            if ( ssda!=gsda )
                  printk(KERN_WARNING "i2c-algo-biths.o: %s SDA set %d, got %d!\n", adap->name, ssda, gsda);
            if ( (adap->errors) || sscl!=gscl || ssda!=gsda )
                  break;
            i++;
      }
    
      __setsda(1,0);
      __setscl(1,0);
      adap->errors = 0;

      if (test[i][0]==-1) {
            printk(KERN_INFO "i2c-algo-biths.o: %s passed bus test.\n",adap->name);
            return 0;
      } else {
            printk(KERN_INFO "i2c-algo-biths.o: %s failed bus test.\n",adap->name);
            return -ENODEV;
      }
}


/* doAddress transmits the address in the necessary format to handle
 * reads, writes as well as 10bit-addresses.
 */

static void doAddress(struct i2c_algo_biths_data *adap, struct i2c_msg *msg) 
{
      unsigned char addr[2];
      int count;

      if ( msg->flags & I2C_M_TEN ) { 
            /* a ten bit address */
            count = 2;
            addr[0] = 0xf0 | (( msg->addr >> 7) & 0x03);
            addr[1] = msg->addr & 0x7f;

            /* try extended address code ... and the remaining 8 bit address */
            TRY(i2c_outb(adap, msg->flags, addr, &count));

            if ( msg->flags & I2C_M_RD ) {
                  TRY(i2c_start(adap));
                  
                  /* okay, now switch into reading mode */
                  count = 1;
                  addr[0] |= 0x01;
                  TRY(i2c_outb(adap, msg->flags, addr, &count));
            }
      } else {          /* normal 7bit address  */
            count = 1;
            addr[0] = ( msg->addr << 1 );
            if (msg->flags & I2C_M_RD )
                  addr[0] |= 1;
            if (msg->flags & I2C_M_REV_DIR_ADDR )
                  addr[0] ^= 1;
            TRY(i2c_outb(adap, msg->flags, addr, &count));
      }
}

/*
 * return values:
 * 1 ACK
 * 0 IGNORED client NAK
 * -EREMOTEIO  client NAK
 * -ETIMEDOUT  from sclhi()
 */


static int bit_xfer(struct i2c_adapter *i2c_adap,
                struct i2c_msg msgs[], int num)
{
      struct i2c_msg *msg = msgs;
      struct i2c_algo_biths_data *adap = i2c_adap->algo_data;
      int mn, j, state;
      enum { MSG_INIT, MSG_START, MSG_ADDRESS, MSG_DATA, MSG_READY, MSG_STOP, MSG_EXIT };

      state = MSG_INIT;
      mn=0;

      adap->dstr=NULL;
      if (i2c_debug>=FATAL_PROTOCOL) {
            adap->dstr = kmalloc(PROTO_MAX_DUMP, GFP_KERNEL);
            if (adap->dstr) {
                  *adap->dstr = 0;
            } else {
                  printk(KERN_DEBUG "i2c-algo-biths.o %s: missing protocol dump (-ENOMEM)\n", adap->name);
            }
      }

      for (j=0; j<num; j++) msgs[j].err = 0; // unprocessed

      do switch (state) {
          
          case MSG_INIT:
                msg = &msgs[mn];
                if ((msg->flags & I2C_M_NOSTART) && (mn)) {
                      state = MSG_DATA;
                      break;
                }

          case MSG_START:     
                i2c_start(adap);
                if (adap->errors) {
                      state = MSG_STOP;   
                      break;
                } 
                
          case MSG_ADDRESS:
                doAddress(adap, msg);
                if (adap->errors) {
                      state = MSG_STOP;
                      break;
                }

          case MSG_DATA:
                j = msg->len;
                if ( msg->flags & I2C_M_RD ) {
                      i2c_inb(adap, msg->flags, msg->buf, &j);
                } else {
                      i2c_outb(adap, msg->flags, msg->buf, &j);
                }
                msg->done = msg->len - j;
                if (adap->errors) {
                      state = MSG_STOP;
                      break;
                }
      
          case MSG_READY:
                mn++;
                if (mn<num) {
                      msg->err = errflag(adap->errors);
                      debug_protocol(adap, msg->err);
                      state = MSG_INIT;
                      break;
                }

          case MSG_STOP:
                msg->err = errflag(adap->errors);
                i2c_stop(adap);
                j = 0;
                while (adap->errors) {
                      if ( ++j > 10) {
                            msg->err = -ENODEV;
                            break;
                      }
                      i2c_stop(adap);
                }
                debug_protocol(adap, msg->err);
                state = MSG_EXIT;
                break;

          default: /* not reached */
                state = MSG_EXIT;
                msg->err = -EINVAL;
                break;
                          
      } while (state != MSG_EXIT);
      
      if (adap->dstr) kfree(adap->dstr);

      for (j=0; j<num; j++)
            debug_printout(i2c_adap, j, msgs[j].err);

      return (msg->err < 0) ? msg->err : mn;
}

static u32 bit_func(struct i2c_adapter *i2c_adap)
{
      return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL |
             I2C_FUNC_10BIT_ADDR | I2C_FUNC_PROTOCOL_MANGLING;
}


/* -----exported algorithm data: -------------------------------------  */

static struct i2c_algorithm i2c_algo_biths = {
      .name       = "Bit-shift algorithm",
      .id         = I2C_ALGO_BIT,
      .master_xfer      = bit_xfer,
      .functionality    = bit_func,
};


#if ALGO_BIT_COMPATIBILITY 
#include "i2c-algo-bit.h"

static _HS_ATTR_ void _old_setscl(void *hw_data, int hw_state)
{
      struct i2c_algo_bit_data *old = hw_data;
      old->setscl(old->data, hw_state & _HS_SCL);
}
static _HS_ATTR_ void _old_setsda(void *hw_data, int hw_state)
{
      struct i2c_algo_bit_data *old = hw_data;
      old->setsda(old->data, hw_state & _HS_SDA);
}
static _HS_ATTR_ int _old_getscl(void *hw_data)
{
      struct i2c_algo_bit_data *old = hw_data;
      return old->getscl(old->data);
}
static _HS_ATTR_ int _old_getsda(void *hw_data)
{
      struct i2c_algo_bit_data *old = hw_data;
      return old->getsda(old->data);
}

static _HS_ATTR_ void _old_setstate(struct i2c_algo_biths_data *adap)
{
      adap->hw_state = adap->ctrl;
}

static struct i2c_algo_biths_data _old_template = {
      .setstate   = _old_setstate,
      .setsda           = _old_setsda,
      .setscl           = _old_setscl,
      .getsda           = _old_getsda,
      .getscl           = _old_getscl,
};

/* 
 * registering functions to load algorithms at runtime 
 */
int i2c_bit_add_bus(struct i2c_adapter *i2c_adap)
{
      int i;
      struct i2c_algo_bit_data *old_adap = i2c_adap->algo_data;
      struct i2c_algo_biths_data *adap;

      adap = kmalloc(sizeof(struct i2c_algo_biths_data), GFP_KERNEL);
      if (adap==NULL)
            return -ENOMEM;

      memcpy(adap, &_old_template, sizeof(struct i2c_algo_biths_data));
      adap->hw_data = old_adap;
      adap->xloops = old_adap->udelay * 0x0863; /* 1/4 vs 1/2 cycle, 0x10c6 / 2 */
      adap->timeout = old_adap->timeout;
      i2c_adap->algo_data = adap;

      return i2c_biths_add_bus(i2c_adap);
}


int i2c_bit_del_bus(struct i2c_adapter *i2c_adap)
{
      int res;

      if ((res = i2c_biths_del_bus(i2c_adap)) < 0)
            return res;

      kfree(i2c_adap->algo_data);
      return 0;
}

EXPORT_SYMBOL(i2c_bit_add_bus);
EXPORT_SYMBOL(i2c_bit_del_bus);

#endif

#ifdef rdtscl
/* TSC stuff from arch/i386/lib/delay.c */

static _HS_ATTR_ void i2c_tsc_set(struct i2c_algo_biths_data *adap)
{
      rdtscl(adap->bclock);
}

static _HS_ATTR_ void i2c_tsc_run(struct i2c_algo_biths_data *adap)
{
      unsigned long now, loops;
      loops = ((long long) adap->xloops * current_cpu_data.loops_per_jiffy) >> 32; 
      loops *= HZ;
      do
      {
            rep_nop();
            rdtscl(now);
      } while ( (now - adap->bclock) < loops );
}

#else 

static _HS_ATTR_ void i2c_udelay_set(struct i2c_algo_biths_data *adap) {}

static _HS_ATTR_ void i2c_udelay_run(struct i2c_algo_biths_data *adap)
{
      int usecs;
      /* adap->xloops = usecs * 0x000010c6 / 2; */
      usecs = ((adap->xloops + 0x0863) >> 12); 
      if (adap->ctrl & _HS_DBL_DT)
            usecs<<=1;
      udelay(usecs);
}

#endif /* rdtscl */


/* 
 * registering functions to load algorithms at runtime 
 */
int i2c_biths_add_bus(struct i2c_adapter *i2c_adap)
{
      struct i2c_algo_biths_data *adap = i2c_adap->algo_data;

      /* get name */
      adap->name = i2c_adap->name;
      adap->dstr = 0; // no protocol dump buffer

      if (adap->set_timer == NULL) {
#ifdef rdtscl     /* if (x86_udelay_tsc) here instead ? */
            adap->set_timer = i2c_tsc_set;
            adap->run_timer = i2c_tsc_run;
#else
            adap->set_timer = i2c_udelay_set;
            adap->run_timer = i2c_udelay_run;
#endif
      }

      if (bit_test) {
            int ret = test_bus(adap);
            if (ret<0)
                  return ret;
      }

      DEB1(printk(KERN_DEBUG "i2c-algo-biths.o: hw routines for %s registered.\n",
                  i2c_adap->name));
#ifdef rdtscl
      DEB1(printk(KERN_DEBUG "i2c-algo-biths.o:  ... will use rdtscl() for bus clock\n"));
#else
      DEB1(printk(KERN_DEBUG "i2c-algo-biths.o:  ... will use udelay() for bus clock\n"));
#endif
      
      /* register new adapter to i2c module... */

      i2c_adap->id |= i2c_algo_biths.id;
      i2c_adap->algo = &i2c_algo_biths;

      i2c_adap->timeout = HZ; /* default values, should     */
      i2c_adap->retries = 3;  /* be replaced by defines     */

      i2c_add_adapter(i2c_adap);
      return 0;
}


int i2c_biths_del_bus(struct i2c_adapter *i2c_adap)
{
      return i2c_del_adapter(i2c_adap);
}

EXPORT_SYMBOL(i2c_biths_add_bus);
EXPORT_SYMBOL(i2c_biths_del_bus);

MODULE_AUTHOR("Kyösti Mälkki <kmalkki@cc.hut.fi>");
MODULE_DESCRIPTION("I2C-Bus bit-banging algorithm");
MODULE_LICENSE("GPL");

MODULE_PARM(bit_test, "i");
MODULE_PARM(i2c_debug,"i");

MODULE_PARM_DESC(bit_test, "Test the lines of the bus to see if it is stuck");
MODULE_PARM_DESC(i2c_debug, "debug level - 1 use; 2 fatal, 3 +proto; 4 all, 5 +proto");

Generated by  Doxygen 1.6.0   Back to index