diff options
| -rw-r--r-- | drivers/i2c/busses/i2c-tegra194-slave.c | 24 |
1 files changed, 23 insertions, 1 deletions
diff --git a/drivers/i2c/busses/i2c-tegra194-slave.c b/drivers/i2c/busses/i2c-tegra194-slave.c index 5381f51b9..60d6d61ea 100644 --- a/drivers/i2c/busses/i2c-tegra194-slave.c +++ b/drivers/i2c/busses/i2c-tegra194-slave.c | |||
| @@ -29,7 +29,9 @@ | |||
| 29 | #include <linux/delay.h> | 29 | #include <linux/delay.h> |
| 30 | #include <linux/i2c.h> | 30 | #include <linux/i2c.h> |
| 31 | #include <linux/iopoll.h> | 31 | #include <linux/iopoll.h> |
| 32 | #include <linux/workqueue.h> | ||
| 32 | 33 | ||
| 34 | #define I2C_SLV_TIMEOUT (msecs_to_jiffies(10000)) | ||
| 33 | #define I2C_SL_CNFG 0x20 | 35 | #define I2C_SL_CNFG 0x20 |
| 34 | #define I2C_SL_CNFG_RESP BIT(0) | 36 | #define I2C_SL_CNFG_RESP BIT(0) |
| 35 | #define I2C_SL_CNFG_NACK BIT(1) | 37 | #define I2C_SL_CNFG_NACK BIT(1) |
| @@ -144,6 +146,7 @@ struct tegra_i2cslv_dev { | |||
| 144 | bool rx_in_progress; | 146 | bool rx_in_progress; |
| 145 | bool tx_in_progress; | 147 | bool tx_in_progress; |
| 146 | u32 buffer_size; | 148 | u32 buffer_size; |
| 149 | struct delayed_work work; | ||
| 147 | }; | 150 | }; |
| 148 | 151 | ||
| 149 | static inline u32 tegra_i2cslv_readl(struct tegra_i2cslv_dev *i2cslv_dev, | 152 | static inline u32 tegra_i2cslv_readl(struct tegra_i2cslv_dev *i2cslv_dev, |
| @@ -442,7 +445,6 @@ static int tegra_i2cslv_init(struct tegra_i2cslv_dev *i2cslv_dev) | |||
| 442 | i2cslv_dev->buffer_size = i2cslv_dev->slave->buffer_size; | 445 | i2cslv_dev->buffer_size = i2cslv_dev->slave->buffer_size; |
| 443 | i2cslv_dev->rx_count = 0; | 446 | i2cslv_dev->rx_count = 0; |
| 444 | 447 | ||
| 445 | |||
| 446 | if (i2cslv_dev->slave->flags & I2C_CLIENT_TEN) { | 448 | if (i2cslv_dev->slave->flags & I2C_CLIENT_TEN) { |
| 447 | /* Program the 10-bit slave address */ | 449 | /* Program the 10-bit slave address */ |
| 448 | tegra_i2cslv_writel(i2cslv_dev, i2cslv_dev->slave->addr & | 450 | tegra_i2cslv_writel(i2cslv_dev, i2cslv_dev->slave->addr & |
| @@ -488,6 +490,22 @@ static int tegra_i2cslv_init(struct tegra_i2cslv_dev *i2cslv_dev) | |||
| 488 | return tegra_i2cslv_load_config(i2cslv_dev); | 490 | return tegra_i2cslv_load_config(i2cslv_dev); |
| 489 | } | 491 | } |
| 490 | 492 | ||
| 493 | static void tegra_i2cslv_handle_timeout(struct work_struct *work) | ||
| 494 | { | ||
| 495 | struct tegra_i2cslv_dev *i2cslv_dev = container_of(work, | ||
| 496 | struct tegra_i2cslv_dev, work.work); | ||
| 497 | unsigned long flags; | ||
| 498 | |||
| 499 | dev_err(i2cslv_dev->dev, "Slave Xfer timeout\n"); | ||
| 500 | |||
| 501 | raw_spin_lock_irqsave(&i2cslv_dev->xfer_lock, flags); | ||
| 502 | tegra_i2cslv_dump_reg(i2cslv_dev); | ||
| 503 | raw_spin_unlock_irqrestore(&i2cslv_dev->xfer_lock, flags); | ||
| 504 | |||
| 505 | reset_control_reset(i2cslv_dev->rstc); | ||
| 506 | tegra_i2cslv_init(i2cslv_dev); | ||
| 507 | } | ||
| 508 | |||
| 491 | static irqreturn_t tegra_i2cslv_isr(int irq, void *dev_id) | 509 | static irqreturn_t tegra_i2cslv_isr(int irq, void *dev_id) |
| 492 | { | 510 | { |
| 493 | struct tegra_i2cslv_dev *i2cslv_dev = dev_id; | 511 | struct tegra_i2cslv_dev *i2cslv_dev = dev_id; |
| @@ -512,6 +530,7 @@ static irqreturn_t tegra_i2cslv_isr(int irq, void *dev_id) | |||
| 512 | } | 530 | } |
| 513 | 531 | ||
| 514 | if (i2c_int_src & I2C_INTERRUPT_SLV_TX_BUFFER_REQ) { | 532 | if (i2c_int_src & I2C_INTERRUPT_SLV_TX_BUFFER_REQ) { |
| 533 | schedule_delayed_work(&i2cslv_dev->work, I2C_SLV_TIMEOUT); | ||
| 515 | tegra_i2cslv_handle_tx(i2cslv_dev, i2c_int_src, i2c_slv_sts); | 534 | tegra_i2cslv_handle_tx(i2cslv_dev, i2c_int_src, i2c_slv_sts); |
| 516 | goto done; | 535 | goto done; |
| 517 | } | 536 | } |
| @@ -529,6 +548,7 @@ static irqreturn_t tegra_i2cslv_isr(int irq, void *dev_id) | |||
| 529 | /* STOP: End of transfer */ | 548 | /* STOP: End of transfer */ |
| 530 | if (i2c_slv_sts & I2C_SL_STATUS_END_TRANS) { | 549 | if (i2c_slv_sts & I2C_SL_STATUS_END_TRANS) { |
| 531 | tegra_i2cslv_handle_stop(i2cslv_dev, i2c_int_src, i2c_slv_sts); | 550 | tegra_i2cslv_handle_stop(i2cslv_dev, i2c_int_src, i2c_slv_sts); |
| 551 | cancel_delayed_work(&i2cslv_dev->work); | ||
| 532 | goto done; | 552 | goto done; |
| 533 | } | 553 | } |
| 534 | 554 | ||
| @@ -693,6 +713,8 @@ static int tegra_i2cslv_probe(struct platform_device *pdev) | |||
| 693 | return ret; | 713 | return ret; |
| 694 | } | 714 | } |
| 695 | 715 | ||
| 716 | INIT_DELAYED_WORK(&i2cslv_dev->work, tegra_i2cslv_handle_timeout); | ||
| 717 | |||
| 696 | return 0; | 718 | return 0; |
| 697 | } | 719 | } |
| 698 | 720 | ||
