aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/i2c/algos/i2c-algo-pcf.c48
-rw-r--r--include/linux/i2c-algo-pcf.h6
2 files changed, 37 insertions, 17 deletions
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
81static 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
81static int wait_for_bb(struct i2c_algo_pcf_data *adap) { 111static 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
diff --git a/include/linux/i2c-algo-pcf.h b/include/linux/i2c-algo-pcf.h
index 77afbb60fd11..74fb6f889a77 100644
--- a/include/linux/i2c-algo-pcf.h
+++ b/include/linux/i2c-algo-pcf.h
@@ -36,6 +36,12 @@ struct i2c_algo_pcf_data {
36 /* local settings */ 36 /* local settings */
37 int udelay; 37 int udelay;
38 int timeout; 38 int timeout;
39
40 /* Multi-master lost arbitration back-off delay (msecs)
41 * This should be set by the bus adapter or knowledgable client
42 * if bus is multi-mastered, else zero
43 */
44 unsigned long lab_mdelay;
39}; 45};
40 46
41int i2c_pcf_add_bus(struct i2c_adapter *); 47int i2c_pcf_add_bus(struct i2c_adapter *);