Merge master.kernel.org:/pub/scm/linux/kernel/git/herbert/crypto-2.6
[linux-drm-fsl-dcu.git] / drivers / i2c / algos / i2c-algo-bit.c
index 21c36bfb5e6bf1b25522e7492bef978e29a8bde0..8a5f5825bb7294ea3056695748bd824df089d4f2 100644 (file)
 
 
 /* ----- global defines ----------------------------------------------- */
-#define DEB(x) if (i2c_debug>=1) x;
-#define DEB2(x) if (i2c_debug>=2) x;
-#define DEBSTAT(x) if (i2c_debug>=3) x; /* print several statistical values*/
-#define DEBPROTO(x) if (i2c_debug>=9) { x; }
-       /* debug the protocol by showing transferred bits */
 
+#ifdef DEBUG
+#define bit_dbg(level, dev, format, args...) \
+       do { \
+               if (i2c_debug >= level) \
+                       dev_dbg(dev, format, ##args); \
+       } while (0)
+#else
+#define bit_dbg(level, dev, format, args...) \
+       do {} while (0)
+#endif /* DEBUG */
 
 /* ----- global variables ---------------------------------------------        */
 
-/* module parameters:
- */
-static int i2c_debug;
 static int bit_test;   /* see if the line-setting functions work       */
+module_param(bit_test, bool, 0);
+MODULE_PARM_DESC(bit_test, "Test the lines of the bus to see if it is stuck");
+
+#ifdef DEBUG
+static int i2c_debug = 1;
+module_param(i2c_debug, int, S_IRUGO | S_IWUSR);
+MODULE_PARM_DESC(i2c_debug,
+                "debug level - 0 off; 1 normal; 2 verbose; 3 very verbose");
+#endif
 
 /* --- setting states on the bus with the right timing: ---------------        */
 
@@ -57,19 +68,19 @@ static int bit_test;        /* see if the line-setting functions work       */
 static inline void sdalo(struct i2c_algo_bit_data *adap)
 {
        setsda(adap,0);
-       udelay(adap->udelay);
+       udelay((adap->udelay + 1) / 2);
 }
 
 static inline void sdahi(struct i2c_algo_bit_data *adap)
 {
        setsda(adap,1);
-       udelay(adap->udelay);
+       udelay((adap->udelay + 1) / 2);
 }
 
 static inline void scllo(struct i2c_algo_bit_data *adap)
 {
        setscl(adap,0);
-       udelay(adap->udelay);
+       udelay(adap->udelay / 2);
 }
 
 /*
@@ -98,7 +109,11 @@ static int sclhi(struct i2c_algo_bit_data *adap)
                }
                cond_resched();
        }
-       DEBSTAT(printk(KERN_DEBUG "needed %ld jiffies\n", jiffies-start));
+#ifdef DEBUG
+       if (jiffies != start && i2c_debug >= 3)
+               pr_debug("i2c-algo-bit: needed %ld jiffies for SCL to go "
+                        "high\n", jiffies - start);
+#endif
 
 done:
        udelay(adap->udelay);
@@ -110,30 +125,29 @@ done:
 static void i2c_start(struct i2c_algo_bit_data *adap) 
 {
        /* assert: scl, sda are high */
-       DEBPROTO(printk("S "));
-       sdalo(adap);
+       setsda(adap, 0);
+       udelay(adap->udelay);
        scllo(adap);
 }
 
 static void i2c_repstart(struct i2c_algo_bit_data *adap) 
 {
-       /* scl, sda may not be high */
-       DEBPROTO(printk(" Sr "));
-       setsda(adap,1);
+       /* assert: scl is low */
+       sdahi(adap);
        sclhi(adap);
-       
-       sdalo(adap);
+       setsda(adap, 0);
+       udelay(adap->udelay);
        scllo(adap);
 }
 
 
 static void i2c_stop(struct i2c_algo_bit_data *adap) 
 {
-       DEBPROTO(printk("P\n"));
        /* assert: scl is low */
        sdalo(adap);
        sclhi(adap); 
-       sdahi(adap);
+       setsda(adap, 1);
+       udelay(adap->udelay);
 }
 
 
@@ -145,7 +159,7 @@ static void i2c_stop(struct i2c_algo_bit_data *adap)
  * 0 if the device did not ack
  * -ETIMEDOUT if an error occurred (while raising the scl line)
  */
-static int i2c_outb(struct i2c_adapter *i2c_adap, char c)
+static int i2c_outb(struct i2c_adapter *i2c_adap, unsigned char c)
 {
        int i;
        int sb;
@@ -154,34 +168,32 @@ static int i2c_outb(struct i2c_adapter *i2c_adap, char c)
 
        /* assert: scl is low */
        for ( i=7 ; i>=0 ; i-- ) {
-               sb = c & ( 1 << i );
+               sb = (c >> i) & 1;
                setsda(adap,sb);
-               udelay(adap->udelay);
-               DEBPROTO(printk(KERN_DEBUG "%d",sb!=0));
+               udelay((adap->udelay + 1) / 2);
                if (sclhi(adap)<0) { /* timed out */
-                       sdahi(adap); /* we don't want to block the net */
-                       DEB2(printk(KERN_DEBUG " i2c_outb: 0x%02x, timeout at bit #%d\n", c&0xff, i));
+                       bit_dbg(1, &i2c_adap->dev, "i2c_outb: 0x%02x, "
+                               "timeout at bit #%d\n", (int)c, i);
                        return -ETIMEDOUT;
                };
                /* do arbitration here: 
                 * if ( sb && ! getsda(adap) ) -> ouch! Get out of here.
                 */
-               setscl(adap, 0 );
-               udelay(adap->udelay);
+               scllo(adap);
        }
        sdahi(adap);
        if (sclhi(adap)<0){ /* timeout */
-           DEB2(printk(KERN_DEBUG " i2c_outb: 0x%02x, timeout at ack\n", c&0xff));
-           return -ETIMEDOUT;
+               bit_dbg(1, &i2c_adap->dev, "i2c_outb: 0x%02x, "
+                       "timeout at ack\n", (int)c);
+               return -ETIMEDOUT;
        };
        /* read ack: SDA should be pulled down by slave */
-       ack=getsda(adap);       /* ack: sda is pulled low ->success.     */
-       DEB2(printk(KERN_DEBUG " i2c_outb: 0x%02x , getsda() = %d\n", c & 0xff, ack));
+       ack = !getsda(adap);    /* ack: sda is pulled low -> success */
+       bit_dbg(2, &i2c_adap->dev, "i2c_outb: 0x%02x %s\n", (int)c,
+               ack ? "A" : "NA");
 
-       DEBPROTO( printk(KERN_DEBUG "[%2.2x]",c&0xff) );
-       DEBPROTO(if (0==ack){ printk(KERN_DEBUG " A ");} else printk(KERN_DEBUG " NA ") );
        scllo(adap);
-       return 0==ack;          /* return 1 if device acked      */
+       return ack;
        /* assert: scl is low (sda undef) */
 }
 
@@ -198,19 +210,18 @@ static int i2c_inb(struct i2c_adapter *i2c_adap)
        sdahi(adap);
        for (i=0;i<8;i++) {
                if (sclhi(adap)<0) { /* timeout */
-                       DEB2(printk(KERN_DEBUG " i2c_inb: timeout at bit #%d\n", 7-i));
+                       bit_dbg(1, &i2c_adap->dev, "i2c_inb: timeout at bit "
+                               "#%d\n", 7 - i);
                        return -ETIMEDOUT;
                };
                indata *= 2;
                if ( getsda(adap) ) 
                        indata |= 0x01;
-               scllo(adap);
+               setscl(adap, 0);
+               udelay(i == 7 ? adap->udelay / 2 : adap->udelay);
        }
        /* assert: scl is low */
-       DEB2(printk(KERN_DEBUG "i2c_inb: 0x%02x\n", indata & 0xff));
-
-       DEBPROTO(printk(KERN_DEBUG " 0x%02x", indata & 0xff));
-       return (int) (indata & 0xff);
+       return indata;
 }
 
 /*
@@ -221,73 +232,67 @@ static int test_bus(struct i2c_algo_bit_data *adap, char* name) {
        int scl,sda;
 
        if (adap->getscl==NULL)
-               printk(KERN_INFO "i2c-algo-bit.o: Testing SDA only, "
-                       "SCL is not readable.\n");
+               pr_info("%s: Testing SDA only, SCL is not readable\n", name);
 
        sda=getsda(adap);
        scl=(adap->getscl==NULL?1:getscl(adap));
-       printk(KERN_DEBUG "i2c-algo-bit.o: (0) scl=%d, sda=%d\n",scl,sda);
        if (!scl || !sda ) {
-               printk(KERN_WARNING "i2c-algo-bit.o: %s seems to be busy.\n", name);
+               printk(KERN_WARNING "%s: bus seems to be busy\n", name);
                goto bailout;
        }
 
        sdalo(adap);
        sda=getsda(adap);
        scl=(adap->getscl==NULL?1:getscl(adap));
-       printk(KERN_DEBUG "i2c-algo-bit.o: (1) scl=%d, sda=%d\n",scl,sda);
        if ( 0 != sda ) {
-               printk(KERN_WARNING "i2c-algo-bit.o: SDA stuck high!\n");
+               printk(KERN_WARNING "%s: SDA stuck high!\n", name);
                goto bailout;
        }
        if ( 0 == scl ) {
-               printk(KERN_WARNING "i2c-algo-bit.o: SCL unexpected low "
-                       "while pulling SDA low!\n");
+               printk(KERN_WARNING "%s: SCL unexpected low "
+                      "while pulling SDA low!\n", name);
                goto bailout;
        }               
 
        sdahi(adap);
        sda=getsda(adap);
        scl=(adap->getscl==NULL?1:getscl(adap));
-       printk(KERN_DEBUG "i2c-algo-bit.o: (2) scl=%d, sda=%d\n",scl,sda);
        if ( 0 == sda ) {
-               printk(KERN_WARNING "i2c-algo-bit.o: SDA stuck low!\n");
+               printk(KERN_WARNING "%s: SDA stuck low!\n", name);
                goto bailout;
        }
        if ( 0 == scl ) {
-               printk(KERN_WARNING "i2c-algo-bit.o: SCL unexpected low "
-                       "while pulling SDA high!\n");
+               printk(KERN_WARNING "%s: SCL unexpected low "
+                      "while pulling SDA high!\n", name);
                goto bailout;
        }
 
        scllo(adap);
        sda=getsda(adap);
        scl=(adap->getscl==NULL?0:getscl(adap));
-       printk(KERN_DEBUG "i2c-algo-bit.o: (3) scl=%d, sda=%d\n",scl,sda);
        if ( 0 != scl ) {
-               printk(KERN_WARNING "i2c-algo-bit.o: SCL stuck high!\n");
+               printk(KERN_WARNING "%s: SCL stuck high!\n", name);
                goto bailout;
        }
        if ( 0 == sda ) {
-               printk(KERN_WARNING "i2c-algo-bit.o: SDA unexpected low "
-                       "while pulling SCL low!\n");
+               printk(KERN_WARNING "%s: SDA unexpected low "
+                      "while pulling SCL low!\n", name);
                goto bailout;
        }
        
        sclhi(adap);
        sda=getsda(adap);
        scl=(adap->getscl==NULL?1:getscl(adap));
-       printk(KERN_DEBUG "i2c-algo-bit.o: (4) scl=%d, sda=%d\n",scl,sda);
        if ( 0 == scl ) {
-               printk(KERN_WARNING "i2c-algo-bit.o: SCL stuck low!\n");
+               printk(KERN_WARNING "%s: SCL stuck low!\n", name);
                goto bailout;
        }
        if ( 0 == sda ) {
-               printk(KERN_WARNING "i2c-algo-bit.o: SDA unexpected low "
-                       "while pulling SCL high!\n");
+               printk(KERN_WARNING "%s: SDA unexpected low "
+                      "while pulling SCL high!\n", name);
                goto bailout;
        }
-       printk(KERN_INFO "i2c-algo-bit.o: %s passed test.\n",name);
+       pr_info("%s: Test OK\n", name);
        return 0;
 bailout:
        sdahi(adap);
@@ -312,44 +317,39 @@ static int try_address(struct i2c_adapter *i2c_adap,
        int i,ret = -1;
        for (i=0;i<=retries;i++) {
                ret = i2c_outb(i2c_adap,addr);
-               if (ret==1)
-                       break;  /* success! */
-               i2c_stop(adap);
-               udelay(5/*adap->udelay*/);
-               if (i==retries)  /* no success */
+               if (ret == 1 || i == retries)
                        break;
-               i2c_start(adap);
+               bit_dbg(3, &i2c_adap->dev, "emitting stop condition\n");
+               i2c_stop(adap);
                udelay(adap->udelay);
+               yield();
+               bit_dbg(3, &i2c_adap->dev, "emitting start condition\n");
+               i2c_start(adap);
        }
-       DEB2(if (i)
-            printk(KERN_DEBUG "i2c-algo-bit.o: Used %d tries to %s client at 0x%02x : %s\n",
-                   i+1, addr & 1 ? "read" : "write", addr>>1,
-                   ret==1 ? "success" : ret==0 ? "no ack" : "failed, timeout?" )
-           );
+       if (i && ret)
+               bit_dbg(1, &i2c_adap->dev, "Used %d tries to %s client at "
+                       "0x%02x: %s\n", i + 1,
+                       addr & 1 ? "read from" : "write to", addr >> 1,
+                       ret == 1 ? "success" : "failed, timeout?");
        return ret;
 }
 
 static int sendbytes(struct i2c_adapter *i2c_adap, struct i2c_msg *msg)
 {
-       struct i2c_algo_bit_data *adap = i2c_adap->algo_data;
-       char c;
-       const char *temp = msg->buf;
+       const unsigned char *temp = msg->buf;
        int count = msg->len;
        unsigned short nak_ok = msg->flags & I2C_M_IGNORE_NAK; 
        int retval;
        int wrcount=0;
 
        while (count > 0) {
-               c = *temp;
-               DEB2(dev_dbg(&i2c_adap->dev, "sendbytes: writing %2.2X\n", c&0xff));
-               retval = i2c_outb(i2c_adap,c);
+               retval = i2c_outb(i2c_adap, *temp);
                if ((retval>0) || (nak_ok && (retval==0)))  { /* ok or ignored NAK */
                        count--; 
                        temp++;
                        wrcount++;
                } else { /* arbitration or no acknowledge */
                        dev_err(&i2c_adap->dev, "sendbytes: error - bailout.\n");
-                       i2c_stop(adap);
                        return (retval<0)? retval : -EFAULT;
                                /* got a better one ?? */
                }
@@ -362,7 +362,7 @@ static int readbytes(struct i2c_adapter *i2c_adap, struct i2c_msg *msg)
        int inval;
        int rdcount=0;          /* counts bytes read */
        struct i2c_algo_bit_data *adap = i2c_adap->algo_data;
-       char *temp = msg->buf;
+       unsigned char *temp = msg->buf;
        int count = msg->len;
 
        while (count > 0) {
@@ -371,30 +371,44 @@ static int readbytes(struct i2c_adapter *i2c_adap, struct i2c_msg *msg)
                        *temp = inval;
                        rdcount++;
                } else {   /* read timed out */
-                       printk(KERN_ERR "i2c-algo-bit.o: readbytes: i2c_inb timed out.\n");
                        break;
                }
 
                temp++;
                count--;
 
-               if (msg->flags & I2C_M_NO_RD_ACK)
+               if (msg->flags & I2C_M_NO_RD_ACK) {
+                       bit_dbg(2, &i2c_adap->dev, "i2c_inb: 0x%02x\n",
+                               inval);
                        continue;
-
-               if ( count > 0 ) {              /* send ack */
-                       sdalo(adap);
-                       DEBPROTO(printk(" Am "));
-               } else {
-                       sdahi(adap);    /* neg. ack on last byte */
-                       DEBPROTO(printk(" NAm "));
                }
+
+               /* assert: sda is high */
+               if (count)              /* send ack */
+                       setsda(adap, 0);
+               udelay((adap->udelay + 1) / 2);
+               bit_dbg(2, &i2c_adap->dev, "i2c_inb: 0x%02x %s\n", inval,
+                       count ? "A" : "NA");
                if (sclhi(adap)<0) {    /* timeout */
-                       sdahi(adap);
-                       printk(KERN_ERR "i2c-algo-bit.o: readbytes: Timeout at ack\n");
+                       dev_err(&i2c_adap->dev, "readbytes: timeout at ack\n");
                        return -ETIMEDOUT;
                };
                scllo(adap);
-               sdahi(adap);
+
+               /* Some SMBus transactions require that we receive the
+                  transaction length as the first read byte. */
+               if (rdcount == 1 && (msg->flags & I2C_M_RECV_LEN)) {
+                       if (inval <= 0 || inval > I2C_SMBUS_BLOCK_MAX) {
+                               dev_err(&i2c_adap->dev, "readbytes: invalid "
+                                       "block length (%d)\n", inval);
+                               return -EREMOTEIO;
+                       }
+                       /* The original count value accounts for the extra
+                          bytes, that is, either 1 for a regular transaction,
+                          or 2 for a PEC transaction. */
+                       count += inval;
+                       msg->len += inval;
+               }
        }
        return rdcount;
 }
@@ -421,27 +435,31 @@ static int bit_doAddress(struct i2c_adapter *i2c_adap, struct i2c_msg *msg)
        if ( (flags & I2C_M_TEN)  ) { 
                /* a ten bit address */
                addr = 0xf0 | (( msg->addr >> 7) & 0x03);
-               DEB2(printk(KERN_DEBUG "addr0: %d\n",addr));
+               bit_dbg(2, &i2c_adap->dev, "addr0: %d\n", addr);
                /* try extended address code...*/
                ret = try_address(i2c_adap, addr, retries);
                if ((ret != 1) && !nak_ok)  {
-                       printk(KERN_ERR "died at extended address code.\n");
+                       dev_err(&i2c_adap->dev,
+                               "died at extended address code\n");
                        return -EREMOTEIO;
                }
                /* the remaining 8 bit address */
                ret = i2c_outb(i2c_adap,msg->addr & 0x7f);
                if ((ret != 1) && !nak_ok) {
                        /* the chip did not ack / xmission error occurred */
-                       printk(KERN_ERR "died at 2nd address code.\n");
+                       dev_err(&i2c_adap->dev, "died at 2nd address code\n");
                        return -EREMOTEIO;
                }
                if ( flags & I2C_M_RD ) {
+                       bit_dbg(3, &i2c_adap->dev, "emitting repeated "
+                               "start condition\n");
                        i2c_repstart(adap);
                        /* okay, now switch into reading mode */
                        addr |= 0x01;
                        ret = try_address(i2c_adap, addr, retries);
                        if ((ret!=1) && !nak_ok) {
-                               printk(KERN_ERR "died at extended address code.\n");
+                               dev_err(&i2c_adap->dev,
+                                       "died at repeated address code\n");
                                return -EREMOTEIO;
                        }
                }
@@ -468,44 +486,62 @@ static int bit_xfer(struct i2c_adapter *i2c_adap,
        int i,ret;
        unsigned short nak_ok;
 
+       bit_dbg(3, &i2c_adap->dev, "emitting start condition\n");
        i2c_start(adap);
        for (i=0;i<num;i++) {
                pmsg = &msgs[i];
                nak_ok = pmsg->flags & I2C_M_IGNORE_NAK; 
                if (!(pmsg->flags & I2C_M_NOSTART)) {
                        if (i) {
+                               bit_dbg(3, &i2c_adap->dev, "emitting "
+                                       "repeated start condition\n");
                                i2c_repstart(adap);
                        }
                        ret = bit_doAddress(i2c_adap, pmsg);
                        if ((ret != 0) && !nak_ok) {
-                           DEB2(printk(KERN_DEBUG "i2c-algo-bit.o: NAK from device addr %2.2x msg #%d\n"
-                                       ,msgs[i].addr,i));
-                           return (ret<0) ? ret : -EREMOTEIO;
+                               bit_dbg(1, &i2c_adap->dev, "NAK from "
+                                       "device addr 0x%02x msg #%d\n",
+                                       msgs[i].addr, i);
+                               goto bailout;
                        }
                }
                if (pmsg->flags & I2C_M_RD ) {
                        /* read bytes into buffer*/
                        ret = readbytes(i2c_adap, pmsg);
-                       DEB2(printk(KERN_DEBUG "i2c-algo-bit.o: read %d bytes.\n",ret));
-                       if (ret < pmsg->len ) {
-                               return (ret<0)? ret : -EREMOTEIO;
+                       if (ret >= 1)
+                               bit_dbg(2, &i2c_adap->dev, "read %d byte%s\n",
+                                       ret, ret == 1 ? "" : "s");
+                       if (ret < pmsg->len) {
+                               if (ret >= 0)
+                                       ret = -EREMOTEIO;
+                               goto bailout;
                        }
                } else {
                        /* write bytes from buffer */
                        ret = sendbytes(i2c_adap, pmsg);
-                       DEB2(printk(KERN_DEBUG "i2c-algo-bit.o: wrote %d bytes.\n",ret));
-                       if (ret < pmsg->len ) {
-                               return (ret<0) ? ret : -EREMOTEIO;
+                       if (ret >= 1)
+                               bit_dbg(2, &i2c_adap->dev, "wrote %d byte%s\n",
+                                       ret, ret == 1 ? "" : "s");
+                       if (ret < pmsg->len) {
+                               if (ret >= 0)
+                                       ret = -EREMOTEIO;
+                               goto bailout;
                        }
                }
        }
+       ret = i;
+
+bailout:
+       bit_dbg(3, &i2c_adap->dev, "emitting stop condition\n");
        i2c_stop(adap);
-       return num;
+       return ret;
 }
 
 static u32 bit_func(struct i2c_adapter *adap)
 {
        return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL | 
+              I2C_FUNC_SMBUS_READ_BLOCK_DATA |
+              I2C_FUNC_SMBUS_BLOCK_PROC_CALL |
               I2C_FUNC_10BIT_ADDR | I2C_FUNC_PROTOCOL_MANGLING;
 }
 
@@ -520,7 +556,7 @@ static const struct i2c_algorithm i2c_bit_algo = {
 /* 
  * registering functions to load algorithms at runtime 
  */
-int i2c_bit_add_bus(struct i2c_adapter *adap)
+static int i2c_bit_prepare_bus(struct i2c_adapter *adap)
 {
        struct i2c_algo_bit_data *bit_adap = adap->algo_data;
 
@@ -530,33 +566,39 @@ int i2c_bit_add_bus(struct i2c_adapter *adap)
                        return -ENODEV;
        }
 
-       DEB2(dev_dbg(&adap->dev, "hw routines registered.\n"));
-
        /* register new adapter to i2c module... */
        adap->algo = &i2c_bit_algo;
 
        adap->timeout = 100;    /* default values, should       */
        adap->retries = 3;      /* be replaced by defines       */
 
-       return i2c_add_adapter(adap);
+       return 0;
 }
 
-
-int i2c_bit_del_bus(struct i2c_adapter *adap)
+int i2c_bit_add_bus(struct i2c_adapter *adap)
 {
-       return i2c_del_adapter(adap);
-}
+       int err;
+
+       err = i2c_bit_prepare_bus(adap);
+       if (err)
+               return err;
 
+       return i2c_add_adapter(adap);
+}
 EXPORT_SYMBOL(i2c_bit_add_bus);
-EXPORT_SYMBOL(i2c_bit_del_bus);
+
+int i2c_bit_add_numbered_bus(struct i2c_adapter *adap)
+{
+       int err;
+
+       err = i2c_bit_prepare_bus(adap);
+       if (err)
+               return err;
+
+       return i2c_add_numbered_adapter(adap);
+}
+EXPORT_SYMBOL(i2c_bit_add_numbered_bus);
 
 MODULE_AUTHOR("Simon G. Vogl <simon@tk.uni-linz.ac.at>");
 MODULE_DESCRIPTION("I2C-Bus bit-banging algorithm");
 MODULE_LICENSE("GPL");
-
-module_param(bit_test, bool, 0);
-module_param(i2c_debug, int, S_IRUGO | S_IWUSR);
-
-MODULE_PARM_DESC(bit_test, "Test the lines of the bus to see if it is stuck");
-MODULE_PARM_DESC(i2c_debug,
-                "debug level - 0 off; 1 normal; 2,3 more verbose; 9 bit-protocol");