X-Git-Url: http://git.onelab.eu/?a=blobdiff_plain;f=drivers%2Fi2c%2Falgos%2Fi2c-algo-pcf.c;h=ecb2c2d7d540241745e27137f45da6b1cf52c081;hb=refs%2Fheads%2Fvserver;hp=fbbe1d2bdcc42205cba823a28e0793c2fb7120a5;hpb=6a77f38946aaee1cd85eeec6cf4229b204c15071;p=linux-2.6.git diff --git a/drivers/i2c/algos/i2c-algo-pcf.c b/drivers/i2c/algos/i2c-algo-pcf.c index fbbe1d2bd..ecb2c2d7d 100644 --- a/drivers/i2c/algos/i2c-algo-pcf.c +++ b/drivers/i2c/algos/i2c-algo-pcf.c @@ -78,7 +78,6 @@ static void i2c_stop(struct i2c_algo_pcf_data *adap) set_pcf(adap, 1, I2C_PCF_STOP); } - static int wait_for_bb(struct i2c_algo_pcf_data *adap) { int timeout = DEF_TIMEOUT; @@ -109,6 +108,26 @@ static int wait_for_pin(struct i2c_algo_pcf_data *adap, int *status) { adap->waitforpin(); *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))); + return(-EINTR); + } #endif if (timeout <= 0) return(-1); @@ -188,16 +207,22 @@ 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= 0) { + 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); } @@ -219,6 +244,10 @@ static int pcf_sendbytes(struct i2c_adapter *i2c_adap, const char *buf, i2c_outb(adap, buf[wrcount]); timeout = wait_for_pin(adap, &status); if (timeout) { + if (timeout == -EINTR) { + /* arbitration lost */ + return -EINTR; + } i2c_stop(adap); dev_err(&i2c_adap->dev, "i2c_write: error - timeout.\n"); return -EREMOTEIO; /* got a better one ?? */ @@ -247,11 +276,16 @@ static int pcf_readbytes(struct i2c_adapter *i2c_adap, char *buf, { int i, status; struct i2c_algo_pcf_data *adap = i2c_adap->algo_data; + int wfp; /* increment number of bytes to read by one -- read dummy byte */ for (i = 0; i <= count; i++) { - if (wait_for_pin(adap, &status)) { + if ((wfp = wait_for_pin(adap, &status))) { + if (wfp == -EINTR) { + /* arbitration lost */ + return -EINTR; + } i2c_stop(adap); dev_err(&i2c_adap->dev, "pcf_readbytes timed out.\n"); return (-1); @@ -332,7 +366,7 @@ static inline int pcf_doAddress(struct i2c_algo_pcf_data *adap, } static int pcf_xfer(struct i2c_adapter *i2c_adap, - struct i2c_msg msgs[], + struct i2c_msg *msgs, int num) { struct i2c_algo_pcf_data *adap = i2c_adap->algo_data; @@ -366,6 +400,10 @@ static int pcf_xfer(struct i2c_adapter *i2c_adap, /* Wait for PIN (pending interrupt NOT) */ timeout = wait_for_pin(adap, &status); if (timeout) { + if (timeout == -EINTR) { + /* arbitration lost */ + return (-EINTR); + } i2c_stop(adap); DEB2(printk(KERN_ERR "i2c-algo-pcf.o: Timeout waiting " "for PIN(1) in pcf_xfer\n");) @@ -420,9 +458,7 @@ static u32 pcf_func(struct i2c_adapter *adap) /* -----exported algorithm data: ------------------------------------- */ -static struct i2c_algorithm pcf_algo = { - .name = "PCF8584 algorithm", - .id = I2C_ALGO_PCF, +static const struct i2c_algorithm pcf_algo = { .master_xfer = pcf_xfer, .functionality = pcf_func, }; @@ -438,27 +474,19 @@ int i2c_pcf_add_bus(struct i2c_adapter *adap) DEB2(dev_dbg(&adap->dev, "hw routines registered.\n")); /* register new adapter to i2c module... */ - - adap->id |= pcf_algo.id; adap->algo = &pcf_algo; adap->timeout = 100; /* default values, should */ adap->retries = 3; /* be replaced by defines */ - rval = pcf_init_8584(pcf_adap); - if (!rval) - i2c_add_adapter(adap); - return rval; -} + if ((rval = pcf_init_8584(pcf_adap))) + return rval; + rval = i2c_add_adapter(adap); -int i2c_pcf_del_bus(struct i2c_adapter *adap) -{ - return i2c_del_adapter(adap); + return rval; } - EXPORT_SYMBOL(i2c_pcf_add_bus); -EXPORT_SYMBOL(i2c_pcf_del_bus); MODULE_AUTHOR("Hans Berglund "); MODULE_DESCRIPTION("I2C-Bus PCF8584 algorithm");