summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authormkarthik <mkarthik@nvidia.com>2018-08-16 05:13:16 -0400
committermobile promotions <svcmobile_promotions@nvidia.com>2018-08-27 09:22:31 -0400
commit5276e80d92d168243b7c348fa921e7c8d68eccda (patch)
treefb3b8a1454adb13263a73941b8ef0acb7f7e53bf
parente0b3e59770dfaf8cdd4c1e5a6ea92cdea6afbc2b (diff)
i2c: tegra-slave: Add support for timeout during read
Add the support for timeout in slave driver during read from slave to master Bug 200376118 Change-Id: I87f93890d4b121b4d966bc20e4fea5dfef84362c Signed-off-by: mkarthik <mkarthik@nvidia.com> Reviewed-on: https://git-master.nvidia.com/r/1800968 Reviewed-by: Shardar Mohammed <smohammed@nvidia.com> GVS: Gerrit_Virtual_Submit Reviewed-by: Bibek Basu <bbasu@nvidia.com> Reviewed-by: mobile promotions <svcmobile_promotions@nvidia.com> Tested-by: mobile promotions <svcmobile_promotions@nvidia.com>
-rw-r--r--drivers/i2c/busses/i2c-tegra194-slave.c24
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
149static inline u32 tegra_i2cslv_readl(struct tegra_i2cslv_dev *i2cslv_dev, 152static 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
493static 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
491static irqreturn_t tegra_i2cslv_isr(int irq, void *dev_id) 509static 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