aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/i2c/busses/i2c-uniphier-f.c17
1 files changed, 16 insertions, 1 deletions
diff --git a/drivers/i2c/busses/i2c-uniphier-f.c b/drivers/i2c/busses/i2c-uniphier-f.c
index a403e8579b65..200dfd1771af 100644
--- a/drivers/i2c/busses/i2c-uniphier-f.c
+++ b/drivers/i2c/busses/i2c-uniphier-f.c
@@ -98,6 +98,7 @@ struct uniphier_fi2c_priv {
98 unsigned int flags; 98 unsigned int flags;
99 unsigned int busy_cnt; 99 unsigned int busy_cnt;
100 unsigned int clk_cycle; 100 unsigned int clk_cycle;
101 spinlock_t lock; /* IRQ synchronization */
101}; 102};
102 103
103static void uniphier_fi2c_fill_txfifo(struct uniphier_fi2c_priv *priv, 104static void uniphier_fi2c_fill_txfifo(struct uniphier_fi2c_priv *priv,
@@ -162,7 +163,10 @@ static irqreturn_t uniphier_fi2c_interrupt(int irq, void *dev_id)
162 struct uniphier_fi2c_priv *priv = dev_id; 163 struct uniphier_fi2c_priv *priv = dev_id;
163 u32 irq_status; 164 u32 irq_status;
164 165
166 spin_lock(&priv->lock);
167
165 irq_status = readl(priv->membase + UNIPHIER_FI2C_INT); 168 irq_status = readl(priv->membase + UNIPHIER_FI2C_INT);
169 irq_status &= priv->enabled_irqs;
166 170
167 dev_dbg(&priv->adap.dev, 171 dev_dbg(&priv->adap.dev,
168 "interrupt: enabled_irqs=%04x, irq_status=%04x\n", 172 "interrupt: enabled_irqs=%04x, irq_status=%04x\n",
@@ -230,6 +234,8 @@ static irqreturn_t uniphier_fi2c_interrupt(int irq, void *dev_id)
230 goto handled; 234 goto handled;
231 } 235 }
232 236
237 spin_unlock(&priv->lock);
238
233 return IRQ_NONE; 239 return IRQ_NONE;
234 240
235data_done: 241data_done:
@@ -246,6 +252,8 @@ complete:
246handled: 252handled:
247 uniphier_fi2c_clear_irqs(priv); 253 uniphier_fi2c_clear_irqs(priv);
248 254
255 spin_unlock(&priv->lock);
256
249 return IRQ_HANDLED; 257 return IRQ_HANDLED;
250} 258}
251 259
@@ -311,7 +319,7 @@ static int uniphier_fi2c_master_xfer_one(struct i2c_adapter *adap,
311{ 319{
312 struct uniphier_fi2c_priv *priv = i2c_get_adapdata(adap); 320 struct uniphier_fi2c_priv *priv = i2c_get_adapdata(adap);
313 bool is_read = msg->flags & I2C_M_RD; 321 bool is_read = msg->flags & I2C_M_RD;
314 unsigned long time_left; 322 unsigned long time_left, flags;
315 323
316 dev_dbg(&adap->dev, "%s: addr=0x%02x, len=%d, stop=%d\n", 324 dev_dbg(&adap->dev, "%s: addr=0x%02x, len=%d, stop=%d\n",
317 is_read ? "receive" : "transmit", msg->addr, msg->len, stop); 325 is_read ? "receive" : "transmit", msg->addr, msg->len, stop);
@@ -342,6 +350,12 @@ static int uniphier_fi2c_master_xfer_one(struct i2c_adapter *adap,
342 priv->membase + UNIPHIER_FI2C_CR); 350 priv->membase + UNIPHIER_FI2C_CR);
343 351
344 time_left = wait_for_completion_timeout(&priv->comp, adap->timeout); 352 time_left = wait_for_completion_timeout(&priv->comp, adap->timeout);
353
354 spin_lock_irqsave(&priv->lock, flags);
355 priv->enabled_irqs = 0;
356 uniphier_fi2c_set_irqs(priv);
357 spin_unlock_irqrestore(&priv->lock, flags);
358
345 if (!time_left) { 359 if (!time_left) {
346 dev_err(&adap->dev, "transaction timeout.\n"); 360 dev_err(&adap->dev, "transaction timeout.\n");
347 uniphier_fi2c_recover(priv); 361 uniphier_fi2c_recover(priv);
@@ -529,6 +543,7 @@ static int uniphier_fi2c_probe(struct platform_device *pdev)
529 543
530 priv->clk_cycle = clk_rate / bus_speed; 544 priv->clk_cycle = clk_rate / bus_speed;
531 init_completion(&priv->comp); 545 init_completion(&priv->comp);
546 spin_lock_init(&priv->lock);
532 priv->adap.owner = THIS_MODULE; 547 priv->adap.owner = THIS_MODULE;
533 priv->adap.algo = &uniphier_fi2c_algo; 548 priv->adap.algo = &uniphier_fi2c_algo;
534 priv->adap.dev.parent = dev; 549 priv->adap.dev.parent = dev;