aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/i2c/busses/i2c-tegra.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/i2c/busses/i2c-tegra.c')
-rw-r--r--drivers/i2c/busses/i2c-tegra.c26
1 files changed, 24 insertions, 2 deletions
diff --git a/drivers/i2c/busses/i2c-tegra.c b/drivers/i2c/busses/i2c-tegra.c
index 5f1b92c74bd9..c0b9aa7df0e2 100644
--- a/drivers/i2c/busses/i2c-tegra.c
+++ b/drivers/i2c/busses/i2c-tegra.c
@@ -37,6 +37,7 @@
37#define I2C_CNFG 0x000 37#define I2C_CNFG 0x000
38#define I2C_CNFG_PACKET_MODE_EN (1<<10) 38#define I2C_CNFG_PACKET_MODE_EN (1<<10)
39#define I2C_CNFG_NEW_MASTER_FSM (1<<11) 39#define I2C_CNFG_NEW_MASTER_FSM (1<<11)
40#define I2C_STATUS 0x01C
40#define I2C_SL_CNFG 0x020 41#define I2C_SL_CNFG 0x020
41#define I2C_SL_CNFG_NEWSL (1<<2) 42#define I2C_SL_CNFG_NEWSL (1<<2)
42#define I2C_SL_ADDR1 0x02c 43#define I2C_SL_ADDR1 0x02c
@@ -77,6 +78,7 @@
77#define I2C_ERR_NONE 0x00 78#define I2C_ERR_NONE 0x00
78#define I2C_ERR_NO_ACK 0x01 79#define I2C_ERR_NO_ACK 0x01
79#define I2C_ERR_ARBITRATION_LOST 0x02 80#define I2C_ERR_ARBITRATION_LOST 0x02
81#define I2C_ERR_UNKNOWN_INTERRUPT 0x04
80 82
81#define PACKET_HEADER0_HEADER_SIZE_SHIFT 28 83#define PACKET_HEADER0_HEADER_SIZE_SHIFT 28
82#define PACKET_HEADER0_PACKET_ID_SHIFT 16 84#define PACKET_HEADER0_PACKET_ID_SHIFT 16
@@ -121,6 +123,7 @@ struct tegra_i2c_dev {
121 void __iomem *base; 123 void __iomem *base;
122 int cont_id; 124 int cont_id;
123 int irq; 125 int irq;
126 bool irq_disabled;
124 int is_dvc; 127 int is_dvc;
125 struct completion msg_complete; 128 struct completion msg_complete;
126 int msg_err; 129 int msg_err;
@@ -343,6 +346,12 @@ static int tegra_i2c_init(struct tegra_i2c_dev *i2c_dev)
343 err = -ETIMEDOUT; 346 err = -ETIMEDOUT;
344 347
345 clk_disable(i2c_dev->clk); 348 clk_disable(i2c_dev->clk);
349
350 if (i2c_dev->irq_disabled) {
351 i2c_dev->irq_disabled = 0;
352 enable_irq(i2c_dev->irq);
353 }
354
346 return err; 355 return err;
347} 356}
348 357
@@ -355,8 +364,19 @@ static irqreturn_t tegra_i2c_isr(int irq, void *dev_id)
355 status = i2c_readl(i2c_dev, I2C_INT_STATUS); 364 status = i2c_readl(i2c_dev, I2C_INT_STATUS);
356 365
357 if (status == 0) { 366 if (status == 0) {
358 dev_warn(i2c_dev->dev, "interrupt with no status\n"); 367 dev_warn(i2c_dev->dev, "irq status 0 %08x %08x %08x\n",
359 return IRQ_NONE; 368 i2c_readl(i2c_dev, I2C_PACKET_TRANSFER_STATUS),
369 i2c_readl(i2c_dev, I2C_STATUS),
370 i2c_readl(i2c_dev, I2C_CNFG));
371 i2c_dev->msg_err |= I2C_ERR_UNKNOWN_INTERRUPT;
372
373 if (!i2c_dev->irq_disabled) {
374 disable_irq_nosync(i2c_dev->irq);
375 i2c_dev->irq_disabled = 1;
376 }
377
378 complete(&i2c_dev->msg_complete);
379 goto err;
360 } 380 }
361 381
362 if (unlikely(status & status_err)) { 382 if (unlikely(status & status_err)) {
@@ -396,6 +416,8 @@ err:
396 I2C_INT_PACKET_XFER_COMPLETE | I2C_INT_TX_FIFO_DATA_REQ | 416 I2C_INT_PACKET_XFER_COMPLETE | I2C_INT_TX_FIFO_DATA_REQ |
397 I2C_INT_RX_FIFO_DATA_REQ); 417 I2C_INT_RX_FIFO_DATA_REQ);
398 i2c_writel(i2c_dev, status, I2C_INT_STATUS); 418 i2c_writel(i2c_dev, status, I2C_INT_STATUS);
419 if (i2c_dev->is_dvc)
420 dvc_writel(i2c_dev, DVC_STATUS_I2C_DONE_INTR, DVC_STATUS);
399 return IRQ_HANDLED; 421 return IRQ_HANDLED;
400} 422}
401 423