summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLaxman Dewangan <ldewangan@nvidia.com>2012-08-21 15:16:38 +0530
committerSimone Willett <swillett@nvidia.com>2012-08-21 16:20:50 -0700
commite989e28fc764651d6b222a058ea1777cf5896446 (patch)
tree51005b2bf586ad0e8b70064fbcf320fe68dadca7
parent6e32ab70de901e3a30fc269a2758f958c2c40abb (diff)
i2c: tegra: I2_M_NOSTART functionality not supported in Tegra20
Tegra20 i2c controller does not support the continue transfer which implements the I2C_M_NOSTART functionality of i2c protocol mangling. Removing the I2C_M_NOSTART functionality support for Tegra20. Signed-off-by: Laxman Dewangan <ldewangan@nvidia.com> Reviewed-by: Wolfram Sang <w.sang@pengutronix.de> Signed-off-by: Stephen Warren <swarren@nvidia.com> Cherry-picked from mainline 72dedc2fb12ff31cc2da977d0c40c3ac58f554cf Change-Id: I461342749a834ff2eae056f1c6616a8d7693a32c Signed-off-by: Laxman Dewangan <ldewangan@nvidia.com> Reviewed-on: http://git-master/r/124875 Reviewed-by: Simone Willett <swillett@nvidia.com> Tested-by: Simone Willett <swillett@nvidia.com>
-rw-r--r--drivers/i2c/busses/i2c-tegra.c58
1 files changed, 49 insertions, 9 deletions
diff --git a/drivers/i2c/busses/i2c-tegra.c b/drivers/i2c/busses/i2c-tegra.c
index 735780fdf40f..43ca5c0e5639 100644
--- a/drivers/i2c/busses/i2c-tegra.c
+++ b/drivers/i2c/busses/i2c-tegra.c
@@ -129,6 +129,15 @@ enum msg_end_type {
struct tegra_i2c_dev;
+/**
+ * struct tegra_i2c_hw_feature : Different HW support on Tegra
+ * @has_continue_xfer_support: Continue transfer supports.
+ */
+
+struct tegra_i2c_hw_feature {
+ bool has_continue_xfer_support;
+};
+
struct tegra_i2c_bus {
struct tegra_i2c_dev *dev;
const struct tegra_pingroup_config *mux;
@@ -142,6 +151,7 @@ struct tegra_i2c_bus {
/**
* struct tegra_i2c_dev - per device i2c context
* @dev: device reference for power management
+ * @hw: Tegra i2c hw feature.
* @adapter: core i2c layer adapter information
* @clk: clock reference for i2c controller
* @i2c_clk: clock reference for i2c bus
@@ -159,6 +169,7 @@ struct tegra_i2c_bus {
*/
struct tegra_i2c_dev {
struct device *dev;
+ struct tegra_i2c_hw_feature *hw;
struct clk *div_clk;
struct clk *fast_clk;
struct rt_mutex dev_lock;
@@ -778,6 +789,17 @@ static int tegra_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msgs[],
return -EBUSY;
}
+ /* Support I2C_M_NOSTART only if HW support continue xfer. */
+ for (i = 0; i < num - 1; i++) {
+ if ((msgs[i + 1].flags & I2C_M_NOSTART) &&
+ !i2c_dev->hw->has_continue_xfer_support) {
+ dev_err(i2c_dev->dev,
+ "mesg %d have illegal flag\n", i + 1);
+ rt_mutex_unlock(&i2c_dev->dev_lock);
+ return -EINVAL;
+ }
+ }
+
if (i2c_dev->last_mux != i2c_bus->mux) {
tegra_pinmux_set_safe_pinmux_table(i2c_dev->last_mux,
i2c_dev->last_mux_len);
@@ -831,6 +853,23 @@ static const struct i2c_algorithm tegra_i2c_algo = {
.functionality = tegra_i2c_func,
};
+static struct tegra_i2c_hw_feature tegra20_i2c_hw = {
+ .has_continue_xfer_support = false,
+};
+
+static struct tegra_i2c_hw_feature tegra30_i2c_hw = {
+ .has_continue_xfer_support = true,
+};
+
+#if defined(CONFIG_OF)
+/* Match table for of_platform binding */
+static const struct of_device_id tegra_i2c_of_match[] __devinitconst = {
+ { .compatible = "nvidia,tegra20-i2c", .data = &tegra20_i2c_hw, },
+ {},
+};
+MODULE_DEVICE_TABLE(of, tegra_i2c_of_match);
+#endif
+
static int __devinit tegra_i2c_probe(struct platform_device *pdev)
{
struct tegra_i2c_dev *i2c_dev;
@@ -904,6 +943,13 @@ static int __devinit tegra_i2c_probe(struct platform_device *pdev)
i2c_dev->dev = &pdev->dev;
i2c_dev->is_clkon_always = plat->is_clkon_always;
+
+#ifdef ARCH_TEGRA_2x_SOC
+ i2c_dev->hw = &tegra20_i2c_hw;
+#else
+ i2c_dev->hw = &tegra30_i2c_hw;
+#endif
+
i2c_dev->last_bus_clk_rate = 100000; /* default clock rate */
if (plat) {
i2c_dev->last_bus_clk_rate = plat->bus_clk_rate[0];
@@ -914,6 +960,9 @@ static int __devinit tegra_i2c_probe(struct platform_device *pdev)
"clock-frequency", NULL);
if (prop)
i2c_dev->last_bus_clk_rate = be32_to_cpup(prop);
+
+ /* FIXME! Populate the Tegra30 and then support M_NOSTART */
+ i2c_dev->hw = &tegra20_i2c_hw;
}
i2c_dev->is_high_speed_enable = plat->is_high_speed_enable;
@@ -1058,15 +1107,6 @@ static const struct dev_pm_ops tegra_i2c_pm = {
#define TEGRA_I2C_PM NULL
#endif
-#if defined(CONFIG_OF)
-/* Match table for of_platform binding */
-static const struct of_device_id tegra_i2c_of_match[] __devinitconst = {
- { .compatible = "nvidia,tegra20-i2c", },
- {},
-};
-MODULE_DEVICE_TABLE(of, tegra_i2c_of_match);
-#endif
-
static struct platform_driver tegra_i2c_driver = {
.probe = tegra_i2c_probe,
.remove = __devexit_p(tegra_i2c_remove),