diff options
Diffstat (limited to 'drivers/i2c/algos')
| -rw-r--r-- | drivers/i2c/algos/i2c-algo-bit.c | 4 | ||||
| -rw-r--r-- | drivers/i2c/algos/i2c-algo-pca.c | 2 | ||||
| -rw-r--r-- | drivers/i2c/algos/i2c-algo-pcf.c | 48 |
3 files changed, 34 insertions, 20 deletions
diff --git a/drivers/i2c/algos/i2c-algo-bit.c b/drivers/i2c/algos/i2c-algo-bit.c index 35812823787b..eb8f72ca02f4 100644 --- a/drivers/i2c/algos/i2c-algo-bit.c +++ b/drivers/i2c/algos/i2c-algo-bit.c | |||
| @@ -320,7 +320,7 @@ static int try_address(struct i2c_adapter *i2c_adap, | |||
| 320 | unsigned char addr, int retries) | 320 | unsigned char addr, int retries) |
| 321 | { | 321 | { |
| 322 | struct i2c_algo_bit_data *adap = i2c_adap->algo_data; | 322 | struct i2c_algo_bit_data *adap = i2c_adap->algo_data; |
| 323 | int i, ret = -1; | 323 | int i, ret = 0; |
| 324 | 324 | ||
| 325 | for (i = 0; i <= retries; i++) { | 325 | for (i = 0; i <= retries; i++) { |
| 326 | ret = i2c_outb(i2c_adap, addr); | 326 | ret = i2c_outb(i2c_adap, addr); |
| @@ -508,7 +508,7 @@ static int bit_doAddress(struct i2c_adapter *i2c_adap, struct i2c_msg *msg) | |||
| 508 | addr ^= 1; | 508 | addr ^= 1; |
| 509 | ret = try_address(i2c_adap, addr, retries); | 509 | ret = try_address(i2c_adap, addr, retries); |
| 510 | if ((ret != 1) && !nak_ok) | 510 | if ((ret != 1) && !nak_ok) |
| 511 | return -EREMOTEIO; | 511 | return -ENXIO; |
| 512 | } | 512 | } |
| 513 | 513 | ||
| 514 | return 0; | 514 | return 0; |
diff --git a/drivers/i2c/algos/i2c-algo-pca.c b/drivers/i2c/algos/i2c-algo-pca.c index e954a20b97a6..d50b329a3c94 100644 --- a/drivers/i2c/algos/i2c-algo-pca.c +++ b/drivers/i2c/algos/i2c-algo-pca.c | |||
| @@ -182,7 +182,7 @@ static int pca_xfer(struct i2c_adapter *i2c_adap, | |||
| 182 | } | 182 | } |
| 183 | if (state != 0xf8) { | 183 | if (state != 0xf8) { |
| 184 | dev_dbg(&i2c_adap->dev, "bus is not idle. status is %#04x\n", state); | 184 | dev_dbg(&i2c_adap->dev, "bus is not idle. status is %#04x\n", state); |
| 185 | return -EIO; | 185 | return -EAGAIN; |
| 186 | } | 186 | } |
| 187 | 187 | ||
| 188 | DEB1("{{{ XFER %d messages\n", num); | 188 | DEB1("{{{ XFER %d messages\n", num); |
diff --git a/drivers/i2c/algos/i2c-algo-pcf.c b/drivers/i2c/algos/i2c-algo-pcf.c index 8907b0191677..1e328d19cd6d 100644 --- a/drivers/i2c/algos/i2c-algo-pcf.c +++ b/drivers/i2c/algos/i2c-algo-pcf.c | |||
| @@ -78,6 +78,36 @@ static void i2c_stop(struct i2c_algo_pcf_data *adap) | |||
| 78 | set_pcf(adap, 1, I2C_PCF_STOP); | 78 | set_pcf(adap, 1, I2C_PCF_STOP); |
| 79 | } | 79 | } |
| 80 | 80 | ||
| 81 | static void handle_lab(struct i2c_algo_pcf_data *adap, const int *status) | ||
| 82 | { | ||
| 83 | DEB2(printk(KERN_INFO | ||
| 84 | "i2c-algo-pcf.o: lost arbitration (CSR 0x%02x)\n", | ||
| 85 | *status)); | ||
| 86 | |||
| 87 | /* Cleanup from LAB -- reset and enable ESO. | ||
| 88 | * This resets the PCF8584; since we've lost the bus, no | ||
| 89 | * further attempts should be made by callers to clean up | ||
| 90 | * (no i2c_stop() etc.) | ||
| 91 | */ | ||
| 92 | set_pcf(adap, 1, I2C_PCF_PIN); | ||
| 93 | set_pcf(adap, 1, I2C_PCF_ESO); | ||
| 94 | |||
| 95 | /* We pause for a time period sufficient for any running | ||
| 96 | * I2C transaction to complete -- the arbitration logic won't | ||
| 97 | * work properly until the next START is seen. | ||
| 98 | * It is assumed the bus driver or client has set a proper value. | ||
| 99 | * | ||
| 100 | * REVISIT: should probably use msleep instead of mdelay if we | ||
| 101 | * know we can sleep. | ||
| 102 | */ | ||
| 103 | if (adap->lab_mdelay) | ||
| 104 | mdelay(adap->lab_mdelay); | ||
| 105 | |||
| 106 | DEB2(printk(KERN_INFO | ||
| 107 | "i2c-algo-pcf.o: reset LAB condition (CSR 0x%02x)\n", | ||
| 108 | get_pcf(adap, 1))); | ||
| 109 | } | ||
| 110 | |||
| 81 | static int wait_for_bb(struct i2c_algo_pcf_data *adap) { | 111 | static int wait_for_bb(struct i2c_algo_pcf_data *adap) { |
| 82 | 112 | ||
| 83 | int timeout = DEF_TIMEOUT; | 113 | int timeout = DEF_TIMEOUT; |
| @@ -109,23 +139,7 @@ static int wait_for_pin(struct i2c_algo_pcf_data *adap, int *status) { | |||
| 109 | *status = get_pcf(adap, 1); | 139 | *status = get_pcf(adap, 1); |
| 110 | } | 140 | } |
| 111 | if (*status & I2C_PCF_LAB) { | 141 | if (*status & I2C_PCF_LAB) { |
| 112 | DEB2(printk(KERN_INFO | 142 | handle_lab(adap, status); |
| 113 | "i2c-algo-pcf.o: lost arbitration (CSR 0x%02x)\n", | ||
| 114 | *status)); | ||
| 115 | /* Cleanup from LAB-- reset and enable ESO. | ||
| 116 | * This resets the PCF8584; since we've lost the bus, no | ||
| 117 | * further attempts should be made by callers to clean up | ||
| 118 | * (no i2c_stop() etc.) | ||
| 119 | */ | ||
| 120 | set_pcf(adap, 1, I2C_PCF_PIN); | ||
| 121 | set_pcf(adap, 1, I2C_PCF_ESO); | ||
| 122 | /* TODO: we should pause for a time period sufficient for any | ||
| 123 | * running I2C transaction to complete-- the arbitration | ||
| 124 | * logic won't work properly until the next START is seen. | ||
| 125 | */ | ||
| 126 | DEB2(printk(KERN_INFO | ||
| 127 | "i2c-algo-pcf.o: reset LAB condition (CSR 0x%02x)\n", | ||
| 128 | get_pcf(adap,1))); | ||
| 129 | return(-EINTR); | 143 | return(-EINTR); |
| 130 | } | 144 | } |
| 131 | #endif | 145 | #endif |
