diff options
author | Laxman Dewangan <ldewangan@nvidia.com> | 2012-08-21 15:16:38 +0530 |
---|---|---|
committer | Simone Willett <swillett@nvidia.com> | 2012-08-21 16:20:50 -0700 |
commit | e989e28fc764651d6b222a058ea1777cf5896446 (patch) | |
tree | 51005b2bf586ad0e8b70064fbcf320fe68dadca7 | |
parent | 6e32ab70de901e3a30fc269a2758f958c2c40abb (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.c | 58 |
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), |