summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChaitanya Bandi <bandik@nvidia.com>2014-02-19 17:18:18 +0530
committerChaitanya Bandi <bandik@nvidia.com>2014-03-03 22:01:39 -0800
commitf2785d20e476c1bdd8477d9239fddf354200b507 (patch)
treee3a1ee7038b58b688f2cc2c126f4c57e7ab9dc03
parent8c64249aa15b87dc519906e5affb88688299bfd4 (diff)
i2c: tegra: Enable PACKET_MODE_EN only during xfer
Enabled the PACKET_MODE_EN bit only during transfer. This helps MTS to check whether any I2C transaction is in progress. Bug 1454386 Change-Id: I62ce2f4ec69bcfd0472e6a01bc5282e74b48f54d Signed-off-by: Chaitanya Bandi <bandik@nvidia.com> Reviewed-on: http://git-master/r/374850 Reviewed-by: Aleksandr Frid <afrid@nvidia.com> Reviewed-by: Automatic_Commit_Validation_User Reviewed-by: Venkat Moganty <vmoganty@nvidia.com>
-rw-r--r--drivers/i2c/busses/i2c-tegra.c48
1 files changed, 46 insertions, 2 deletions
diff --git a/drivers/i2c/busses/i2c-tegra.c b/drivers/i2c/busses/i2c-tegra.c
index a7531f82b9a8..b1e69f0966df 100644
--- a/drivers/i2c/busses/i2c-tegra.c
+++ b/drivers/i2c/busses/i2c-tegra.c
@@ -4,7 +4,7 @@
* Copyright (C) 2010 Google, Inc.
* Author: Colin Cross <ccross@android.com>
*
- * Copyright (C) 2010-2013 NVIDIA Corporation. All rights reserved.
+ * Copyright (C) 2010-2014 NVIDIA Corporation. All rights reserved.
*
* This software is licensed under the terms of the GNU General Public
* License version 2, as published by the Free Software Foundation, and
@@ -669,7 +669,7 @@ static int tegra_i2c_init(struct tegra_i2c_dev *i2c_dev)
if (i2c_dev->is_dvc)
tegra_dvc_init(i2c_dev);
- val = I2C_CNFG_NEW_MASTER_FSM | I2C_CNFG_PACKET_MODE_EN |
+ val = I2C_CNFG_NEW_MASTER_FSM |
(0x2 << I2C_CNFG_DEBOUNCE_CNT_SHIFT);
i2c_writel(i2c_dev, val, I2C_CNFG);
i2c_writel(i2c_dev, 0, I2C_INT_MASK);
@@ -950,6 +950,8 @@ static int tegra_i2c_xfer_msg(struct tegra_i2c_dev *i2c_dev,
int ret;
unsigned long flags = 0;
unsigned long timeout = jiffies + HZ;
+ u32 cnfg;
+ u32 val;
if (msg->len == 0)
return -EINVAL;
@@ -966,6 +968,28 @@ static int tegra_i2c_xfer_msg(struct tegra_i2c_dev *i2c_dev,
if (!i2c_dev->chipdata->has_xfer_complete_interrupt)
spin_lock_irqsave(&i2c_dev->fifo_lock, flags);
+ cnfg = I2C_CNFG_NEW_MASTER_FSM | I2C_CNFG_PACKET_MODE_EN
+ | (0x2 << I2C_CNFG_DEBOUNCE_CNT_SHIFT);
+ i2c_writel(i2c_dev, cnfg, I2C_CNFG);
+
+ if (i2c_dev->chipdata->has_config_load_reg) {
+ i2c_writel(i2c_dev, I2C_MSTR_CONFIG_LOAD,
+ I2C_CONFIG_LOAD);
+ while (i2c_readl(i2c_dev, I2C_CONFIG_LOAD) != 0) {
+ if (time_after(jiffies, timeout)) {
+ dev_warn(i2c_dev->dev,
+ "timeout config_load");
+ return -ETIMEDOUT;
+ }
+ udelay(2);
+ }
+ }
+ i2c_writel(i2c_dev, 0, I2C_INT_MASK);
+
+ val = 7 << I2C_FIFO_CONTROL_TX_TRIG_SHIFT |
+ 0 << I2C_FIFO_CONTROL_RX_TRIG_SHIFT;
+ i2c_writel(i2c_dev, val, I2C_FIFO_CONTROL);
+
i2c_dev->msg_add = msg->addr;
i2c_dev->packet_header = (0 << PACKET_HEADER0_HEADER_SIZE_SHIFT) |
@@ -1078,6 +1102,26 @@ static int tegra_i2c_xfer_msg(struct tegra_i2c_dev *i2c_dev,
if (i2c_dev->is_dvc)
dvc_i2c_mask_irq(i2c_dev, DVC_CTRL_REG3_I2C_DONE_INTR_EN);
+ cnfg = i2c_readl(i2c_dev, I2C_CNFG);
+ if (cnfg & I2C_CNFG_PACKET_MODE_EN)
+ i2c_writel(i2c_dev, cnfg & (~I2C_CNFG_PACKET_MODE_EN),
+ I2C_CNFG);
+ else
+ dev_err(i2c_dev->dev, "i2c_cnfg PACKET_MODE_EN not set\n");
+
+ if (i2c_dev->chipdata->has_config_load_reg) {
+ i2c_writel(i2c_dev, I2C_MSTR_CONFIG_LOAD,
+ I2C_CONFIG_LOAD);
+ while (i2c_readl(i2c_dev, I2C_CONFIG_LOAD) != 0) {
+ if (time_after(jiffies, timeout)) {
+ dev_warn(i2c_dev->dev,
+ "timeout config_load");
+ return -ETIMEDOUT;
+ }
+ udelay(2);
+ }
+ }
+
if (ret == 0) {
dev_err(i2c_dev->dev,
"i2c transfer timed out, addr 0x%04x, data 0x%02x\n",