diff options
author | Alok Chauhan <alokc@nvidia.com> | 2011-07-26 16:08:21 +0530 |
---|---|---|
committer | Varun Colbert <vcolbert@nvidia.com> | 2011-08-09 16:02:05 -0700 |
commit | efc6e2c49a4b387feaaa88b44a16fe12d34dc4c2 (patch) | |
tree | 5ea534a5dca6ffc5c3a0f06713d9b09f077d9756 | |
parent | c7f57cc760411c030dd0fae88e2b78bf8439791f (diff) |
i2c: tegra: Added arbitration lost error recovery
Added the arbitration lost error recovery code into
i2c driver.
bug 854305
Change-Id: Ib855f3541d139c01ea34fd9070feef7969eed395
Reviewed-on: http://git-master/r/43201
Reviewed-by: Bandi Krishna Chaitanya <bandik@nvidia.com>
Tested-by: Bandi Krishna Chaitanya <bandik@nvidia.com>
Reviewed-by: Alok Chauhan <alokc@nvidia.com>
Reviewed-by: Laxman Dewangan <ldewangan@nvidia.com>
-rw-r--r--[-rwxr-xr-x] | drivers/i2c/busses/i2c-tegra.c | 18 | ||||
-rw-r--r-- | include/linux/i2c-tegra.h | 3 |
2 files changed, 21 insertions, 0 deletions
diff --git a/drivers/i2c/busses/i2c-tegra.c b/drivers/i2c/busses/i2c-tegra.c index 3064fc4863ad..6eac092deb4a 100755..100644 --- a/drivers/i2c/busses/i2c-tegra.c +++ b/drivers/i2c/busses/i2c-tegra.c @@ -111,6 +111,8 @@ #define SL_ADDR1(addr) (addr & 0xff) #define SL_ADDR2(addr) ((addr >> 8) & 0xff) + + struct tegra_i2c_dev; struct tegra_i2c_bus { @@ -154,6 +156,9 @@ struct tegra_i2c_dev { u16 slave_addr; bool is_clkon_always; struct tegra_i2c_bus busses[1]; + int scl_gpio; + int sda_gpio; + int (*arb_recovery)(int scl_gpio, int sda_gpio); }; static void dvc_writel(struct tegra_i2c_dev *i2c_dev, u32 val, unsigned long reg) @@ -553,6 +558,7 @@ static int tegra_i2c_xfer_msg(struct tegra_i2c_bus *i2c_bus, u32 int_mask; int ret; unsigned long flags; + int arb_stat; tegra_i2c_flush_fifos(i2c_dev); @@ -628,6 +634,15 @@ static int tegra_i2c_xfer_msg(struct tegra_i2c_bus *i2c_bus, if (likely(i2c_dev->msg_err == I2C_ERR_NONE)) return 0; + /* Arbitration Lost occurs, Start recovery */ + if (i2c_dev->msg_err == I2C_ERR_ARBITRATION_LOST) { + if (i2c_dev->arb_recovery) { + arb_stat = i2c_dev->arb_recovery(i2c_dev->scl_gpio, i2c_dev->sda_gpio); + if (!arb_stat) + return -EAGAIN; + } + } + spin_lock_irqsave(&i2c_dev->clk_lock, flags); i2c_dev->controller_enabled = false; tegra_i2c_init(i2c_dev); @@ -799,6 +814,9 @@ static int tegra_i2c_probe(struct platform_device *pdev) i2c_dev->slave_addr = plat->slave_addr; i2c_dev->is_dvc = plat->is_dvc; + i2c_dev->scl_gpio = plat->scl_gpio; + i2c_dev->sda_gpio = plat->sda_gpio; + i2c_dev->arb_recovery = plat->arb_recovery; init_completion(&i2c_dev->msg_complete); if (irq == INT_I2C || irq == INT_I2C2 || irq == INT_I2C3) diff --git a/include/linux/i2c-tegra.h b/include/linux/i2c-tegra.h index d48db31cb9bb..c9fc57b7f67b 100644 --- a/include/linux/i2c-tegra.h +++ b/include/linux/i2c-tegra.h @@ -35,6 +35,9 @@ struct tegra_i2c_platform_data { int retries; int timeout; /* in jiffies */ u16 slave_addr; + int scl_gpio; + int sda_gpio; + int (*arb_recovery)(void); }; struct tegra_i2c_slave_platform_data { |