diff options
-rw-r--r-- | drivers/i2c/busses/i2c-bfin-twi.c | 125 |
1 files changed, 66 insertions, 59 deletions
diff --git a/drivers/i2c/busses/i2c-bfin-twi.c b/drivers/i2c/busses/i2c-bfin-twi.c index f1e14dd590c9..441134a1df92 100644 --- a/drivers/i2c/busses/i2c-bfin-twi.c +++ b/drivers/i2c/busses/i2c-bfin-twi.c | |||
@@ -25,8 +25,6 @@ | |||
25 | #include <asm/portmux.h> | 25 | #include <asm/portmux.h> |
26 | #include <asm/irq.h> | 26 | #include <asm/irq.h> |
27 | 27 | ||
28 | #define POLL_TIMEOUT (2 * HZ) | ||
29 | |||
30 | /* SMBus mode*/ | 28 | /* SMBus mode*/ |
31 | #define TWI_I2C_MODE_STANDARD 1 | 29 | #define TWI_I2C_MODE_STANDARD 1 |
32 | #define TWI_I2C_MODE_STANDARDSUB 2 | 30 | #define TWI_I2C_MODE_STANDARDSUB 2 |
@@ -44,8 +42,6 @@ struct bfin_twi_iface { | |||
44 | int cur_mode; | 42 | int cur_mode; |
45 | int manual_stop; | 43 | int manual_stop; |
46 | int result; | 44 | int result; |
47 | int timeout_count; | ||
48 | struct timer_list timeout_timer; | ||
49 | struct i2c_adapter adap; | 45 | struct i2c_adapter adap; |
50 | struct completion complete; | 46 | struct completion complete; |
51 | struct i2c_msg *pmsg; | 47 | struct i2c_msg *pmsg; |
@@ -169,16 +165,13 @@ static void bfin_twi_handle_interrupt(struct bfin_twi_iface *iface) | |||
169 | write_INT_MASK(iface, 0); | 165 | write_INT_MASK(iface, 0); |
170 | write_MASTER_CTL(iface, 0); | 166 | write_MASTER_CTL(iface, 0); |
171 | SSYNC(); | 167 | SSYNC(); |
172 | /* If it is a quick transfer, only address bug no data, | 168 | /* If it is a quick transfer, only address without data, |
173 | * not an err, return 1. | 169 | * not an err, return 1. |
170 | * If address is acknowledged return 1. | ||
174 | */ | 171 | */ |
175 | if (iface->writeNum == 0 && (mast_stat & BUFRDERR)) | 172 | if ((iface->writeNum == 0 && (mast_stat & BUFRDERR)) |
173 | || !(mast_stat & ANAK)) | ||
176 | iface->result = 1; | 174 | iface->result = 1; |
177 | /* If address not acknowledged return -1, | ||
178 | * else return 0. | ||
179 | */ | ||
180 | else if (!(mast_stat & ANAK)) | ||
181 | iface->result = 0; | ||
182 | } | 175 | } |
183 | complete(&iface->complete); | 176 | complete(&iface->complete); |
184 | return; | 177 | return; |
@@ -250,9 +243,9 @@ static void bfin_twi_handle_interrupt(struct bfin_twi_iface *iface) | |||
250 | write_INT_MASK(iface, 0); | 243 | write_INT_MASK(iface, 0); |
251 | write_MASTER_CTL(iface, 0); | 244 | write_MASTER_CTL(iface, 0); |
252 | SSYNC(); | 245 | SSYNC(); |
253 | complete(&iface->complete); | ||
254 | } | 246 | } |
255 | } | 247 | } |
248 | complete(&iface->complete); | ||
256 | } | 249 | } |
257 | 250 | ||
258 | /* Interrupt handler */ | 251 | /* Interrupt handler */ |
@@ -262,36 +255,15 @@ static irqreturn_t bfin_twi_interrupt_entry(int irq, void *dev_id) | |||
262 | unsigned long flags; | 255 | unsigned long flags; |
263 | 256 | ||
264 | spin_lock_irqsave(&iface->lock, flags); | 257 | spin_lock_irqsave(&iface->lock, flags); |
265 | del_timer(&iface->timeout_timer); | ||
266 | bfin_twi_handle_interrupt(iface); | 258 | bfin_twi_handle_interrupt(iface); |
267 | spin_unlock_irqrestore(&iface->lock, flags); | 259 | spin_unlock_irqrestore(&iface->lock, flags); |
268 | return IRQ_HANDLED; | 260 | return IRQ_HANDLED; |
269 | } | 261 | } |
270 | 262 | ||
271 | static void bfin_twi_timeout(unsigned long data) | ||
272 | { | ||
273 | struct bfin_twi_iface *iface = (struct bfin_twi_iface *)data; | ||
274 | unsigned long flags; | ||
275 | |||
276 | spin_lock_irqsave(&iface->lock, flags); | ||
277 | bfin_twi_handle_interrupt(iface); | ||
278 | if (iface->result == 0) { | ||
279 | iface->timeout_count--; | ||
280 | if (iface->timeout_count > 0) { | ||
281 | iface->timeout_timer.expires = jiffies + POLL_TIMEOUT; | ||
282 | add_timer(&iface->timeout_timer); | ||
283 | } else { | ||
284 | iface->result = -1; | ||
285 | complete(&iface->complete); | ||
286 | } | ||
287 | } | ||
288 | spin_unlock_irqrestore(&iface->lock, flags); | ||
289 | } | ||
290 | |||
291 | /* | 263 | /* |
292 | * Generic i2c master transfer entrypoint | 264 | * One i2c master transfer |
293 | */ | 265 | */ |
294 | static int bfin_twi_master_xfer(struct i2c_adapter *adap, | 266 | static int bfin_twi_do_master_xfer(struct i2c_adapter *adap, |
295 | struct i2c_msg *msgs, int num) | 267 | struct i2c_msg *msgs, int num) |
296 | { | 268 | { |
297 | struct bfin_twi_iface *iface = adap->algo_data; | 269 | struct bfin_twi_iface *iface = adap->algo_data; |
@@ -319,7 +291,6 @@ static int bfin_twi_master_xfer(struct i2c_adapter *adap, | |||
319 | iface->transPtr = pmsg->buf; | 291 | iface->transPtr = pmsg->buf; |
320 | iface->writeNum = iface->readNum = pmsg->len; | 292 | iface->writeNum = iface->readNum = pmsg->len; |
321 | iface->result = 0; | 293 | iface->result = 0; |
322 | iface->timeout_count = 10; | ||
323 | init_completion(&(iface->complete)); | 294 | init_completion(&(iface->complete)); |
324 | /* Set Transmit device address */ | 295 | /* Set Transmit device address */ |
325 | write_MASTER_ADDR(iface, pmsg->addr); | 296 | write_MASTER_ADDR(iface, pmsg->addr); |
@@ -358,30 +329,49 @@ static int bfin_twi_master_xfer(struct i2c_adapter *adap, | |||
358 | iface->manual_stop = 1; | 329 | iface->manual_stop = 1; |
359 | } | 330 | } |
360 | 331 | ||
361 | iface->timeout_timer.expires = jiffies + POLL_TIMEOUT; | ||
362 | add_timer(&iface->timeout_timer); | ||
363 | |||
364 | /* Master enable */ | 332 | /* Master enable */ |
365 | write_MASTER_CTL(iface, read_MASTER_CTL(iface) | MEN | | 333 | write_MASTER_CTL(iface, read_MASTER_CTL(iface) | MEN | |
366 | ((iface->read_write == I2C_SMBUS_READ) ? MDIR : 0) | | 334 | ((iface->read_write == I2C_SMBUS_READ) ? MDIR : 0) | |
367 | ((CONFIG_I2C_BLACKFIN_TWI_CLK_KHZ > 100) ? FAST : 0)); | 335 | ((CONFIG_I2C_BLACKFIN_TWI_CLK_KHZ > 100) ? FAST : 0)); |
368 | SSYNC(); | 336 | SSYNC(); |
369 | 337 | ||
370 | wait_for_completion(&iface->complete); | 338 | while (!iface->result) { |
371 | 339 | if (!wait_for_completion_timeout(&iface->complete, | |
372 | rc = iface->result; | 340 | adap->timeout)) { |
341 | iface->result = -1; | ||
342 | dev_err(&adap->dev, "master transfer timeout\n"); | ||
343 | } | ||
344 | } | ||
373 | 345 | ||
374 | if (rc == 1) | 346 | if (iface->result == 1) |
375 | return num; | 347 | rc = iface->cur_msg + 1; |
376 | else | 348 | else |
377 | return rc; | 349 | rc = iface->result; |
350 | |||
351 | return rc; | ||
378 | } | 352 | } |
379 | 353 | ||
380 | /* | 354 | /* |
381 | * SMBus type transfer entrypoint | 355 | * Generic i2c master transfer entrypoint |
382 | */ | 356 | */ |
357 | static int bfin_twi_master_xfer(struct i2c_adapter *adap, | ||
358 | struct i2c_msg *msgs, int num) | ||
359 | { | ||
360 | int i, ret = 0; | ||
383 | 361 | ||
384 | int bfin_twi_smbus_xfer(struct i2c_adapter *adap, u16 addr, | 362 | for (i = 0; i < adap->retries; i++) { |
363 | ret = bfin_twi_do_master_xfer(adap, msgs, num); | ||
364 | if (ret > 0) | ||
365 | break; | ||
366 | } | ||
367 | |||
368 | return ret; | ||
369 | } | ||
370 | |||
371 | /* | ||
372 | * One I2C SMBus transfer | ||
373 | */ | ||
374 | int bfin_twi_do_smbus_xfer(struct i2c_adapter *adap, u16 addr, | ||
385 | unsigned short flags, char read_write, | 375 | unsigned short flags, char read_write, |
386 | u8 command, int size, union i2c_smbus_data *data) | 376 | u8 command, int size, union i2c_smbus_data *data) |
387 | { | 377 | { |
@@ -469,7 +459,6 @@ int bfin_twi_smbus_xfer(struct i2c_adapter *adap, u16 addr, | |||
469 | iface->manual_stop = 0; | 459 | iface->manual_stop = 0; |
470 | iface->read_write = read_write; | 460 | iface->read_write = read_write; |
471 | iface->command = command; | 461 | iface->command = command; |
472 | iface->timeout_count = 10; | ||
473 | init_completion(&(iface->complete)); | 462 | init_completion(&(iface->complete)); |
474 | 463 | ||
475 | /* FIFO Initiation. Data in FIFO should be discarded before | 464 | /* FIFO Initiation. Data in FIFO should be discarded before |
@@ -486,9 +475,6 @@ int bfin_twi_smbus_xfer(struct i2c_adapter *adap, u16 addr, | |||
486 | write_MASTER_ADDR(iface, addr); | 475 | write_MASTER_ADDR(iface, addr); |
487 | SSYNC(); | 476 | SSYNC(); |
488 | 477 | ||
489 | iface->timeout_timer.expires = jiffies + POLL_TIMEOUT; | ||
490 | add_timer(&iface->timeout_timer); | ||
491 | |||
492 | switch (iface->cur_mode) { | 478 | switch (iface->cur_mode) { |
493 | case TWI_I2C_MODE_STANDARDSUB: | 479 | case TWI_I2C_MODE_STANDARDSUB: |
494 | write_XMT_DATA8(iface, iface->command); | 480 | write_XMT_DATA8(iface, iface->command); |
@@ -550,10 +536,8 @@ int bfin_twi_smbus_xfer(struct i2c_adapter *adap, u16 addr, | |||
550 | else if (iface->readNum > 255) { | 536 | else if (iface->readNum > 255) { |
551 | write_MASTER_CTL(iface, 0xff << 6); | 537 | write_MASTER_CTL(iface, 0xff << 6); |
552 | iface->manual_stop = 1; | 538 | iface->manual_stop = 1; |
553 | } else { | 539 | } else |
554 | del_timer(&iface->timeout_timer); | ||
555 | break; | 540 | break; |
556 | } | ||
557 | } | 541 | } |
558 | } | 542 | } |
559 | write_INT_MASK(iface, MCOMP | MERR | | 543 | write_INT_MASK(iface, MCOMP | MERR | |
@@ -569,7 +553,13 @@ int bfin_twi_smbus_xfer(struct i2c_adapter *adap, u16 addr, | |||
569 | } | 553 | } |
570 | SSYNC(); | 554 | SSYNC(); |
571 | 555 | ||
572 | wait_for_completion(&iface->complete); | 556 | while (!iface->result) { |
557 | if (!wait_for_completion_timeout(&iface->complete, | ||
558 | adap->timeout)) { | ||
559 | iface->result = -1; | ||
560 | dev_err(&adap->dev, "smbus transfer timeout\n"); | ||
561 | } | ||
562 | } | ||
573 | 563 | ||
574 | rc = (iface->result >= 0) ? 0 : -1; | 564 | rc = (iface->result >= 0) ? 0 : -1; |
575 | 565 | ||
@@ -577,6 +567,25 @@ int bfin_twi_smbus_xfer(struct i2c_adapter *adap, u16 addr, | |||
577 | } | 567 | } |
578 | 568 | ||
579 | /* | 569 | /* |
570 | * Generic I2C SMBus transfer entrypoint | ||
571 | */ | ||
572 | int bfin_twi_smbus_xfer(struct i2c_adapter *adap, u16 addr, | ||
573 | unsigned short flags, char read_write, | ||
574 | u8 command, int size, union i2c_smbus_data *data) | ||
575 | { | ||
576 | int i, ret = 0; | ||
577 | |||
578 | for (i = 0; i < adap->retries; i++) { | ||
579 | ret = bfin_twi_do_smbus_xfer(adap, addr, flags, | ||
580 | read_write, command, size, data); | ||
581 | if (ret == 0) | ||
582 | break; | ||
583 | } | ||
584 | |||
585 | return ret; | ||
586 | } | ||
587 | |||
588 | /* | ||
580 | * Return what the adapter supports | 589 | * Return what the adapter supports |
581 | */ | 590 | */ |
582 | static u32 bfin_twi_functionality(struct i2c_adapter *adap) | 591 | static u32 bfin_twi_functionality(struct i2c_adapter *adap) |
@@ -667,10 +676,6 @@ static int i2c_bfin_twi_probe(struct platform_device *pdev) | |||
667 | goto out_error_no_irq; | 676 | goto out_error_no_irq; |
668 | } | 677 | } |
669 | 678 | ||
670 | init_timer(&(iface->timeout_timer)); | ||
671 | iface->timeout_timer.function = bfin_twi_timeout; | ||
672 | iface->timeout_timer.data = (unsigned long)iface; | ||
673 | |||
674 | p_adap = &iface->adap; | 679 | p_adap = &iface->adap; |
675 | p_adap->nr = pdev->id; | 680 | p_adap->nr = pdev->id; |
676 | strlcpy(p_adap->name, pdev->name, sizeof(p_adap->name)); | 681 | strlcpy(p_adap->name, pdev->name, sizeof(p_adap->name)); |
@@ -678,6 +683,8 @@ static int i2c_bfin_twi_probe(struct platform_device *pdev) | |||
678 | p_adap->algo_data = iface; | 683 | p_adap->algo_data = iface; |
679 | p_adap->class = I2C_CLASS_HWMON | I2C_CLASS_SPD; | 684 | p_adap->class = I2C_CLASS_HWMON | I2C_CLASS_SPD; |
680 | p_adap->dev.parent = &pdev->dev; | 685 | p_adap->dev.parent = &pdev->dev; |
686 | p_adap->timeout = 5 * HZ; | ||
687 | p_adap->retries = 3; | ||
681 | 688 | ||
682 | rc = peripheral_request_list(pin_req[pdev->id], "i2c-bfin-twi"); | 689 | rc = peripheral_request_list(pin_req[pdev->id], "i2c-bfin-twi"); |
683 | if (rc) { | 690 | if (rc) { |