]> www.pilppa.org Git - linux-2.6-omap-h63xx.git/blobdiff - drivers/i2c/algos/i2c-algo-pcf.c
Merge git://git.kernel.org/pub/scm/linux/kernel/git/lethal/sh-2.6
[linux-2.6-omap-h63xx.git] / drivers / i2c / algos / i2c-algo-pcf.c
index ab2e6f3498b4a585cafcb84952bfa0113e27d123..3e01992230b8bb3214ff424a3923b72da1606e10 100644 (file)
@@ -78,6 +78,36 @@ static void i2c_stop(struct i2c_algo_pcf_data *adap)
        set_pcf(adap, 1, I2C_PCF_STOP);
 }
 
+static void handle_lab(struct i2c_algo_pcf_data *adap, const int *status)
+{
+       DEB2(printk(KERN_INFO
+               "i2c-algo-pcf.o: lost arbitration (CSR 0x%02x)\n",
+                *status));
+
+       /* Cleanup from LAB -- reset and enable ESO.
+        * This resets the PCF8584; since we've lost the bus, no
+        * further attempts should be made by callers to clean up
+        * (no i2c_stop() etc.)
+        */
+       set_pcf(adap, 1, I2C_PCF_PIN);
+       set_pcf(adap, 1, I2C_PCF_ESO);
+
+       /* We pause for a time period sufficient for any running
+        * I2C transaction to complete -- the arbitration logic won't
+        * work properly until the next START is seen.
+        * It is assumed the bus driver or client has set a proper value.
+        *
+        * REVISIT: should probably use msleep instead of mdelay if we
+        * know we can sleep.
+        */
+       if (adap->lab_mdelay)
+               mdelay(adap->lab_mdelay);
+
+       DEB2(printk(KERN_INFO
+               "i2c-algo-pcf.o: reset LAB condition (CSR 0x%02x)\n",
+               get_pcf(adap, 1)));
+}
+
 static int wait_for_bb(struct i2c_algo_pcf_data *adap) {
 
        int timeout = DEF_TIMEOUT;
@@ -105,27 +135,11 @@ static int wait_for_pin(struct i2c_algo_pcf_data *adap, int *status) {
        *status = get_pcf(adap, 1);
 #ifndef STUB_I2C
        while (timeout-- && (*status & I2C_PCF_PIN)) {
-               adap->waitforpin();
+               adap->waitforpin(adap->data);
                *status = get_pcf(adap, 1);
        }
        if (*status & I2C_PCF_LAB) {
-               DEB2(printk(KERN_INFO 
-                       "i2c-algo-pcf.o: lost arbitration (CSR 0x%02x)\n",
-                        *status));
-               /* Cleanup from LAB-- reset and enable ESO.
-                * This resets the PCF8584; since we've lost the bus, no
-                * further attempts should be made by callers to clean up 
-                * (no i2c_stop() etc.)
-                */
-               set_pcf(adap, 1, I2C_PCF_PIN);
-               set_pcf(adap, 1, I2C_PCF_ESO);
-               /* TODO: we should pause for a time period sufficient for any
-                * running I2C transaction to complete-- the arbitration
-                * logic won't work properly until the next START is seen.
-                */
-               DEB2(printk(KERN_INFO 
-                       "i2c-algo-pcf.o: reset LAB condition (CSR 0x%02x)\n", 
-                       get_pcf(adap,1)));
+               handle_lab(adap, status);
                return(-EINTR);
        }
 #endif
@@ -194,7 +208,7 @@ static int pcf_init_8584 (struct i2c_algo_pcf_data *adap)
                return -ENXIO;
        }
        
-       printk(KERN_DEBUG "i2c-algo-pcf.o: deteted and initialized PCF8584.\n");
+       printk(KERN_DEBUG "i2c-algo-pcf.o: detected and initialized PCF8584.\n");
 
        return 0;
 }
@@ -203,35 +217,6 @@ static int pcf_init_8584 (struct i2c_algo_pcf_data *adap)
 /* ----- Utility functions
  */
 
-static inline int try_address(struct i2c_algo_pcf_data *adap,
-                      unsigned char addr, int retries)
-{
-       int i, status, ret = -1;
-       int wfp;
-       for (i=0;i<retries;i++) {
-               i2c_outb(adap, addr);
-               i2c_start(adap);
-               status = get_pcf(adap, 1);
-               if ((wfp = wait_for_pin(adap, &status)) >= 0) {
-                       if ((status & I2C_PCF_LRB) == 0) { 
-                               i2c_stop(adap);
-                               break;  /* success! */
-                       }
-               }
-               if (wfp == -EINTR) {
-                       /* arbitration lost */
-                       udelay(adap->udelay);
-                       return -EINTR;
-               }
-               i2c_stop(adap);
-               udelay(adap->udelay);
-       }
-       DEB2(if (i) printk(KERN_DEBUG "i2c-algo-pcf.o: needed %d retries for %d\n",i,
-                          addr));
-       return ret;
-}
-
-
 static int pcf_sendbytes(struct i2c_adapter *i2c_adap, const char *buf,
                          int count, int last)
 {
@@ -321,47 +306,19 @@ static int pcf_readbytes(struct i2c_adapter *i2c_adap, char *buf,
 }
 
 
-static inline int pcf_doAddress(struct i2c_algo_pcf_data *adap,
-                                struct i2c_msg *msg, int retries) 
+static int pcf_doAddress(struct i2c_algo_pcf_data *adap,
+                        struct i2c_msg *msg)
 {
        unsigned short flags = msg->flags;
        unsigned char addr;
-       int ret;
-       if ( (flags & I2C_M_TEN)  ) { 
-               /* a ten bit address */
-               addr = 0xf0 | (( msg->addr >> 7) & 0x03);
-               DEB2(printk(KERN_DEBUG "addr0: %d\n",addr));
-               /* try extended address code...*/
-               ret = try_address(adap, addr, retries);
-               if (ret!=1) {
-                       printk(KERN_ERR "died at extended address code.\n");
-                       return -EREMOTEIO;
-               }
-               /* the remaining 8 bit address */
-               i2c_outb(adap,msg->addr & 0x7f);
-/* Status check comes here */
-               if (ret != 1) {
-                       printk(KERN_ERR "died at 2nd address code.\n");
-                       return -EREMOTEIO;
-               }
-               if ( flags & I2C_M_RD ) {
-                       i2c_repstart(adap);
-                       /* okay, now switch into reading mode */
-                       addr |= 0x01;
-                       ret = try_address(adap, addr, retries);
-                       if (ret!=1) {
-                               printk(KERN_ERR "died at extended address code.\n");
-                               return -EREMOTEIO;
-                       }
-               }
-       } else {                /* normal 7bit address  */
-               addr = ( msg->addr << 1 );
-               if (flags & I2C_M_RD )
-                       addr |= 1;
-               if (flags & I2C_M_REV_DIR_ADDR )
-                       addr ^= 1;
-               i2c_outb(adap, addr);
-       }
+
+       addr = msg->addr << 1;
+       if (flags & I2C_M_RD)
+               addr |= 1;
+       if (flags & I2C_M_REV_DIR_ADDR)
+               addr ^= 1;
+       i2c_outb(adap, addr);
+
        return 0;
 }
 
@@ -374,13 +331,16 @@ static int pcf_xfer(struct i2c_adapter *i2c_adap,
        int i;
        int ret=0, timeout, status;
     
+       if (adap->xfer_begin)
+               adap->xfer_begin(adap->data);
 
        /* Check for bus busy */
        timeout = wait_for_bb(adap);
        if (timeout) {
                DEB2(printk(KERN_ERR "i2c-algo-pcf.o: "
                            "Timeout waiting for BB in pcf_xfer\n");)
-               return -EIO;
+               i = -EIO;
+               goto out;
        }
        
        for (i = 0;ret >= 0 && i < num; i++) {
@@ -390,7 +350,7 @@ static int pcf_xfer(struct i2c_adapter *i2c_adap,
                     pmsg->flags & I2C_M_RD ? "read" : "write",
                      pmsg->len, pmsg->addr, i + 1, num);)
     
-               ret = pcf_doAddress(adap, pmsg, i2c_adap->retries);
+               ret = pcf_doAddress(adap, pmsg);
 
                /* Send START */
                if (i == 0) {
@@ -402,12 +362,14 @@ static int pcf_xfer(struct i2c_adapter *i2c_adap,
                if (timeout) {
                        if (timeout == -EINTR) {
                                /* arbitration lost */
-                               return (-EINTR);
+                               i = -EINTR;
+                               goto out;
                        }
                        i2c_stop(adap);
                        DEB2(printk(KERN_ERR "i2c-algo-pcf.o: Timeout waiting "
                                    "for PIN(1) in pcf_xfer\n");)
-                       return (-EREMOTEIO);
+                       i = -EREMOTEIO;
+                       goto out;
                }
     
 #ifndef STUB_I2C
@@ -415,7 +377,8 @@ static int pcf_xfer(struct i2c_adapter *i2c_adap,
                if (status & I2C_PCF_LRB) {
                        i2c_stop(adap);
                        DEB2(printk(KERN_ERR "i2c-algo-pcf.o: No LRB(1) in pcf_xfer\n");)
-                       return (-EREMOTEIO);
+                       i = -EREMOTEIO;
+                       goto out;
                }
 #endif
     
@@ -447,13 +410,16 @@ static int pcf_xfer(struct i2c_adapter *i2c_adap,
                }
        }
 
+out:
+       if (adap->xfer_end)
+               adap->xfer_end(adap->data);
        return (i);
 }
 
 static u32 pcf_func(struct i2c_adapter *adap)
 {
        return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL | 
-              I2C_FUNC_10BIT_ADDR | I2C_FUNC_PROTOCOL_MANGLING; 
+              I2C_FUNC_PROTOCOL_MANGLING;
 }
 
 /* -----exported algorithm data: ------------------------------------- */
@@ -475,9 +441,7 @@ int i2c_pcf_add_bus(struct i2c_adapter *adap)
 
        /* register new adapter to i2c module... */
        adap->algo = &pcf_algo;
-
-       adap->timeout = 100;            /* default values, should       */
-       adap->retries = 3;              /* be replaced by defines       */
+       adap->timeout = 100;
 
        if ((rval = pcf_init_8584(pcf_adap)))
                return rval;