diff options
author | David Miller <davem@davemloft.net> | 2008-10-22 14:21:30 -0400 |
---|---|---|
committer | Jean Delvare <khali@linux-fr.org> | 2008-10-22 14:21:30 -0400 |
commit | 30091404af5a7cd515e7b565df76932e295d8f6f (patch) | |
tree | 6ce6ecb5707aca55aff260ff3a1ce8a3453be3de | |
parent | 08e5338d119daeb3c7746fa80fa916b8d3d48e89 (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.c | 17 | ||||
-rw-r--r-- | include/linux/i2c-algo-pcf.h | 3 |
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 | ||
413 | out: | ||
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 |