aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/i2c/busses/i2c-rcar.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/i2c/busses/i2c-rcar.c')
-rw-r--r--drivers/i2c/busses/i2c-rcar.c41
1 files changed, 33 insertions, 8 deletions
diff --git a/drivers/i2c/busses/i2c-rcar.c b/drivers/i2c/busses/i2c-rcar.c
index f3c7139dfa25..e506fcd3ca04 100644
--- a/drivers/i2c/busses/i2c-rcar.c
+++ b/drivers/i2c/busses/i2c-rcar.c
@@ -34,6 +34,7 @@
34#include <linux/platform_device.h> 34#include <linux/platform_device.h>
35#include <linux/pm_runtime.h> 35#include <linux/pm_runtime.h>
36#include <linux/slab.h> 36#include <linux/slab.h>
37#include <linux/spinlock.h>
37 38
38/* register offsets */ 39/* register offsets */
39#define ICSCR 0x00 /* slave ctrl */ 40#define ICSCR 0x00 /* slave ctrl */
@@ -75,8 +76,8 @@
75#define RCAR_IRQ_RECV (MNR | MAL | MST | MAT | MDR) 76#define RCAR_IRQ_RECV (MNR | MAL | MST | MAT | MDR)
76#define RCAR_IRQ_STOP (MST) 77#define RCAR_IRQ_STOP (MST)
77 78
78#define RCAR_IRQ_ACK_SEND (~(MAT | MDE)) 79#define RCAR_IRQ_ACK_SEND (~(MAT | MDE) & 0xFF)
79#define RCAR_IRQ_ACK_RECV (~(MAT | MDR)) 80#define RCAR_IRQ_ACK_RECV (~(MAT | MDR) & 0xFF)
80 81
81#define ID_LAST_MSG (1 << 0) 82#define ID_LAST_MSG (1 << 0)
82#define ID_IOERROR (1 << 1) 83#define ID_IOERROR (1 << 1)
@@ -95,6 +96,7 @@ struct rcar_i2c_priv {
95 struct i2c_msg *msg; 96 struct i2c_msg *msg;
96 struct clk *clk; 97 struct clk *clk;
97 98
99 spinlock_t lock;
98 wait_queue_head_t wait; 100 wait_queue_head_t wait;
99 101
100 int pos; 102 int pos;
@@ -365,20 +367,20 @@ static irqreturn_t rcar_i2c_irq(int irq, void *ptr)
365 struct rcar_i2c_priv *priv = ptr; 367 struct rcar_i2c_priv *priv = ptr;
366 u32 msr; 368 u32 msr;
367 369
370 /*-------------- spin lock -----------------*/
371 spin_lock(&priv->lock);
372
368 msr = rcar_i2c_read(priv, ICMSR); 373 msr = rcar_i2c_read(priv, ICMSR);
369 374
375 /* Only handle interrupts that are currently enabled */
376 msr &= rcar_i2c_read(priv, ICMIER);
377
370 /* Arbitration lost */ 378 /* Arbitration lost */
371 if (msr & MAL) { 379 if (msr & MAL) {
372 rcar_i2c_flags_set(priv, (ID_DONE | ID_ARBLOST)); 380 rcar_i2c_flags_set(priv, (ID_DONE | ID_ARBLOST));
373 goto out; 381 goto out;
374 } 382 }
375 383
376 /* Stop */
377 if (msr & MST) {
378 rcar_i2c_flags_set(priv, ID_DONE);
379 goto out;
380 }
381
382 /* Nack */ 384 /* Nack */
383 if (msr & MNR) { 385 if (msr & MNR) {
384 /* go to stop phase */ 386 /* go to stop phase */
@@ -388,6 +390,12 @@ static irqreturn_t rcar_i2c_irq(int irq, void *ptr)
388 goto out; 390 goto out;
389 } 391 }
390 392
393 /* Stop */
394 if (msr & MST) {
395 rcar_i2c_flags_set(priv, ID_DONE);
396 goto out;
397 }
398
391 if (rcar_i2c_is_recv(priv)) 399 if (rcar_i2c_is_recv(priv))
392 rcar_i2c_flags_set(priv, rcar_i2c_irq_recv(priv, msr)); 400 rcar_i2c_flags_set(priv, rcar_i2c_irq_recv(priv, msr));
393 else 401 else
@@ -400,6 +408,9 @@ out:
400 wake_up(&priv->wait); 408 wake_up(&priv->wait);
401 } 409 }
402 410
411 spin_unlock(&priv->lock);
412 /*-------------- spin unlock -----------------*/
413
403 return IRQ_HANDLED; 414 return IRQ_HANDLED;
404} 415}
405 416
@@ -409,14 +420,21 @@ static int rcar_i2c_master_xfer(struct i2c_adapter *adap,
409{ 420{
410 struct rcar_i2c_priv *priv = i2c_get_adapdata(adap); 421 struct rcar_i2c_priv *priv = i2c_get_adapdata(adap);
411 struct device *dev = rcar_i2c_priv_to_dev(priv); 422 struct device *dev = rcar_i2c_priv_to_dev(priv);
423 unsigned long flags;
412 int i, ret, timeout; 424 int i, ret, timeout;
413 425
414 pm_runtime_get_sync(dev); 426 pm_runtime_get_sync(dev);
415 427
428 /*-------------- spin lock -----------------*/
429 spin_lock_irqsave(&priv->lock, flags);
430
416 rcar_i2c_init(priv); 431 rcar_i2c_init(priv);
417 /* start clock */ 432 /* start clock */
418 rcar_i2c_write(priv, ICCCR, priv->icccr); 433 rcar_i2c_write(priv, ICCCR, priv->icccr);
419 434
435 spin_unlock_irqrestore(&priv->lock, flags);
436 /*-------------- spin unlock -----------------*/
437
420 ret = rcar_i2c_bus_barrier(priv); 438 ret = rcar_i2c_bus_barrier(priv);
421 if (ret < 0) 439 if (ret < 0)
422 goto out; 440 goto out;
@@ -428,6 +446,9 @@ static int rcar_i2c_master_xfer(struct i2c_adapter *adap,
428 break; 446 break;
429 } 447 }
430 448
449 /*-------------- spin lock -----------------*/
450 spin_lock_irqsave(&priv->lock, flags);
451
431 /* init each data */ 452 /* init each data */
432 priv->msg = &msgs[i]; 453 priv->msg = &msgs[i];
433 priv->pos = 0; 454 priv->pos = 0;
@@ -437,6 +458,9 @@ static int rcar_i2c_master_xfer(struct i2c_adapter *adap,
437 458
438 ret = rcar_i2c_prepare_msg(priv); 459 ret = rcar_i2c_prepare_msg(priv);
439 460
461 spin_unlock_irqrestore(&priv->lock, flags);
462 /*-------------- spin unlock -----------------*/
463
440 if (ret < 0) 464 if (ret < 0)
441 break; 465 break;
442 466
@@ -540,6 +564,7 @@ static int rcar_i2c_probe(struct platform_device *pdev)
540 564
541 irq = platform_get_irq(pdev, 0); 565 irq = platform_get_irq(pdev, 0);
542 init_waitqueue_head(&priv->wait); 566 init_waitqueue_head(&priv->wait);
567 spin_lock_init(&priv->lock);
543 568
544 adap = &priv->adap; 569 adap = &priv->adap;
545 adap->nr = pdev->id; 570 adap->nr = pdev->id;