Commit 0573d11b authored by Eric Brower's avatar Eric Brower Committed by Jean Delvare

i2c-algo-pcf: Multi-master lost-arbitration improvement

Improve lost-arbitration handling of PCF8584.  This is necessary for
support of a currently out-of-kernel driver for Sun Microsystems E250
environmental management; perhaps others.
Signed-off-by: default avatarEric Brower <ebrower@gmail.com>
Acked-by: default avatarDan Smolik <marvin@mydatex.cz>
Signed-off-by: default avatarJean Delvare <khali@linux-fr.org>
parent 8a56ce10
...@@ -78,6 +78,36 @@ static void i2c_stop(struct i2c_algo_pcf_data *adap) ...@@ -78,6 +78,36 @@ static void i2c_stop(struct i2c_algo_pcf_data *adap)
set_pcf(adap, 1, I2C_PCF_STOP); 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) { static int wait_for_bb(struct i2c_algo_pcf_data *adap) {
int timeout = DEF_TIMEOUT; int timeout = DEF_TIMEOUT;
...@@ -109,23 +139,7 @@ static int wait_for_pin(struct i2c_algo_pcf_data *adap, int *status) { ...@@ -109,23 +139,7 @@ static int wait_for_pin(struct i2c_algo_pcf_data *adap, int *status) {
*status = get_pcf(adap, 1); *status = get_pcf(adap, 1);
} }
if (*status & I2C_PCF_LAB) { if (*status & I2C_PCF_LAB) {
DEB2(printk(KERN_INFO handle_lab(adap, status);
"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); return(-EINTR);
} }
#endif #endif
......
...@@ -36,6 +36,12 @@ struct i2c_algo_pcf_data { ...@@ -36,6 +36,12 @@ struct i2c_algo_pcf_data {
/* local settings */ /* local settings */
int udelay; int udelay;
int timeout; int timeout;
/* Multi-master lost arbitration back-off delay (msecs)
* This should be set by the bus adapter or knowledgable client
* if bus is multi-mastered, else zero
*/
unsigned long lab_mdelay;
}; };
int i2c_pcf_add_bus(struct i2c_adapter *); int i2c_pcf_add_bus(struct i2c_adapter *);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment