aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDavid Miller <davem@davemloft.net>2008-10-22 14:21:30 -0400
committerJean Delvare <khali@linux-fr.org>2008-10-22 14:21:30 -0400
commit30091404af5a7cd515e7b565df76932e295d8f6f (patch)
tree6ce6ecb5707aca55aff260ff3a1ce8a3453be3de
parent08e5338d119daeb3c7746fa80fa916b8d3d48e89 (diff)
i2c-algo-pcf: Add adapter hooks around xfer begin and end
Some I2C bus implementations need to synchronize with external entities, such as system firmware, which might also be programming the same I2C bus. In order to facilitate this add ->xfer_begin() and ->xfer_end() hooks which are invoked around pcf_xfer(). [JD: Make these hooks optional.] Signed-off-by: David S. Miller <davem@davemloft.net> Signed-off-by: Jean Delvare <khali@linux-fr.org>
-rw-r--r--drivers/i2c/algos/i2c-algo-pcf.c17
-rw-r--r--include/linux/i2c-algo-pcf.h3
2 files changed, 16 insertions, 4 deletions
diff --git a/drivers/i2c/algos/i2c-algo-pcf.c b/drivers/i2c/algos/i2c-algo-pcf.c
index a8a5b6d1dd88..b8a6f3bcbae3 100644
--- a/drivers/i2c/algos/i2c-algo-pcf.c
+++ b/drivers/i2c/algos/i2c-algo-pcf.c
@@ -331,13 +331,16 @@ static int pcf_xfer(struct i2c_adapter *i2c_adap,
331 int i; 331 int i;
332 int ret=0, timeout, status; 332 int ret=0, timeout, status;
333 333
334 if (adap->xfer_begin)
335 adap->xfer_begin(adap->data);
334 336
335 /* Check for bus busy */ 337 /* Check for bus busy */
336 timeout = wait_for_bb(adap); 338 timeout = wait_for_bb(adap);
337 if (timeout) { 339 if (timeout) {
338 DEB2(printk(KERN_ERR "i2c-algo-pcf.o: " 340 DEB2(printk(KERN_ERR "i2c-algo-pcf.o: "
339 "Timeout waiting for BB in pcf_xfer\n");) 341 "Timeout waiting for BB in pcf_xfer\n");)
340 return -EIO; 342 i = -EIO;
343 goto out;
341 } 344 }
342 345
343 for (i = 0;ret >= 0 && i < num; i++) { 346 for (i = 0;ret >= 0 && i < num; i++) {
@@ -359,12 +362,14 @@ static int pcf_xfer(struct i2c_adapter *i2c_adap,
359 if (timeout) { 362 if (timeout) {
360 if (timeout == -EINTR) { 363 if (timeout == -EINTR) {
361 /* arbitration lost */ 364 /* arbitration lost */
362 return (-EINTR); 365 i = -EINTR;
366 goto out;
363 } 367 }
364 i2c_stop(adap); 368 i2c_stop(adap);
365 DEB2(printk(KERN_ERR "i2c-algo-pcf.o: Timeout waiting " 369 DEB2(printk(KERN_ERR "i2c-algo-pcf.o: Timeout waiting "
366 "for PIN(1) in pcf_xfer\n");) 370 "for PIN(1) in pcf_xfer\n");)
367 return (-EREMOTEIO); 371 i = -EREMOTEIO;
372 goto out;
368 } 373 }
369 374
370#ifndef STUB_I2C 375#ifndef STUB_I2C
@@ -372,7 +377,8 @@ static int pcf_xfer(struct i2c_adapter *i2c_adap,
372 if (status & I2C_PCF_LRB) { 377 if (status & I2C_PCF_LRB) {
373 i2c_stop(adap); 378 i2c_stop(adap);
374 DEB2(printk(KERN_ERR "i2c-algo-pcf.o: No LRB(1) in pcf_xfer\n");) 379 DEB2(printk(KERN_ERR "i2c-algo-pcf.o: No LRB(1) in pcf_xfer\n");)
375 return (-EREMOTEIO); 380 i = -EREMOTEIO;
381 goto out;
376 } 382 }
377#endif 383#endif
378 384
@@ -404,6 +410,9 @@ static int pcf_xfer(struct i2c_adapter *i2c_adap,
404 } 410 }
405 } 411 }
406 412
413out:
414 if (adap->xfer_end)
415 adap->xfer_end(adap->data);
407 return (i); 416 return (i);
408} 417}
409 418
diff --git a/include/linux/i2c-algo-pcf.h b/include/linux/i2c-algo-pcf.h
index 5de8a319bf14..0f91a957a690 100644
--- a/include/linux/i2c-algo-pcf.h
+++ b/include/linux/i2c-algo-pcf.h
@@ -33,6 +33,9 @@ struct i2c_algo_pcf_data {
33 int (*getclock) (void *data); 33 int (*getclock) (void *data);
34 void (*waitforpin) (void *data); 34 void (*waitforpin) (void *data);
35 35
36 void (*xfer_begin) (void *data);
37 void (*xfer_end) (void *data);
38
36 /* Multi-master lost arbitration back-off delay (msecs) 39 /* Multi-master lost arbitration back-off delay (msecs)
37 * This should be set by the bus adapter or knowledgable client 40 * This should be set by the bus adapter or knowledgable client
38 * if bus is multi-mastered, else zero 41 * if bus is multi-mastered, else zero