aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/i2c
diff options
context:
space:
mode:
authorEric Brower <ebrower@gmail.com>2008-07-14 16:38:31 -0400
committerJean Delvare <khali@mahadeva.delvare>2008-07-14 16:38:31 -0400
commit0573d11b2bbd0e4774f33f4c1959c1939c055e96 (patch)
treef78451f46dc192ec90f7d30e531633104dc7ae93 /drivers/i2c
parent8a56ce1033073657572bd993595a56498baa4800 (diff)
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: Eric Brower <ebrower@gmail.com> Acked-by: Dan Smolik <marvin@mydatex.cz> Signed-off-by: Jean Delvare <khali@linux-fr.org>
Diffstat (limited to 'drivers/i2c')
-rw-r--r--drivers/i2c/algos/i2c-algo-pcf.c48
1 files changed, 31 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