summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNitin Kumbhar <nkumbhar@nvidia.com>2011-03-24 16:21:21 +0530
committerVarun Colbert <vcolbert@nvidia.com>2011-03-24 16:58:10 -0700
commit64a6e1d5a555be1c330de80cfb477563ae061452 (patch)
treeaee34f858841a580a2d93ed864fbd754b8f134ce
parentc2dfdb05051e950b764c374227938982ad808e9e (diff)
i2c: buses: tegra: use new i2c slave controller
tegra2 has an improved new i2c slave controller. This should be used instead of the old i2c slave controller. With old i2c slave controller, occasionally it generates spurious slave interrupts causing disruptions in master i2c transfers. BUG 788286 BUG 804545 Change-Id: I6a74d8e474ed80db097f43c215afcb0b2d1ff45e (cherry picked from commit 198622c27396dffdf7f99635fc3c6a54b4bb2e61) Reviewed-on: http://git-master/r/24107 Reviewed-by: Yu-Huan Hsu <yhsu@nvidia.com> Tested-by: Yu-Huan Hsu <yhsu@nvidia.com>
-rw-r--r--drivers/i2c/busses/i2c-tegra.c15
1 files changed, 15 insertions, 0 deletions
diff --git a/drivers/i2c/busses/i2c-tegra.c b/drivers/i2c/busses/i2c-tegra.c
index 49880008d5b5..30ffa65671dd 100644
--- a/drivers/i2c/busses/i2c-tegra.c
+++ b/drivers/i2c/busses/i2c-tegra.c
@@ -42,6 +42,7 @@
#define I2C_STATUS 0x01C
#define I2C_STATUS_BUSY (1<<8)
#define I2C_SL_CNFG 0x020
+#define I2C_SL_CNFG_NACK (1<<1)
#define I2C_SL_CNFG_NEWSL (1<<2)
#define I2C_SL_ADDR1 0x02c
#define I2C_TX_FIFO 0x050
@@ -120,6 +121,7 @@ struct tegra_i2c_dev {
int irq;
bool irq_disabled;
int is_dvc;
+ bool is_slave;
struct completion msg_complete;
int msg_err;
u8 *msg_buf;
@@ -307,6 +309,13 @@ static void tegra_dvc_init(struct tegra_i2c_dev *i2c_dev)
dvc_writel(i2c_dev, val, DVC_CTRL_REG1);
}
+static void tegra_i2c_slave_init(struct tegra_i2c_dev *i2c_dev)
+{
+ u32 val = I2C_SL_CNFG_NEWSL | I2C_SL_CNFG_NACK;
+
+ i2c_writel(i2c_dev, val, I2C_SL_CNFG);
+}
+
static int tegra_i2c_init(struct tegra_i2c_dev *i2c_dev)
{
u32 val;
@@ -330,6 +339,9 @@ static int tegra_i2c_init(struct tegra_i2c_dev *i2c_dev)
0 << I2C_FIFO_CONTROL_RX_TRIG_SHIFT;
i2c_writel(i2c_dev, val, I2C_FIFO_CONTROL);
+ if (i2c_dev->is_slave)
+ tegra_i2c_slave_init(i2c_dev);
+
if (tegra_i2c_flush_fifos(i2c_dev))
err = -ETIMEDOUT;
@@ -688,6 +700,9 @@ static int tegra_i2c_probe(struct platform_device *pdev)
i2c_dev->is_dvc = plat->is_dvc;
init_completion(&i2c_dev->msg_complete);
+ if (irq == INT_I2C || irq == INT_I2C3)
+ i2c_dev->is_slave = true;
+
platform_set_drvdata(pdev, i2c_dev);
ret = tegra_i2c_init(i2c_dev);