diff options
author | Chaitanya Bandi <bandik@nvidia.com> | 2012-08-17 21:07:06 +0530 |
---|---|---|
committer | Varun Colbert <vcolbert@nvidia.com> | 2012-08-22 17:33:32 -0700 |
commit | 2925aeea0965d77e2eb0dd9044a315ef12cb0747 (patch) | |
tree | 57971f9b8b66fdf4e1b61588942ff034784adfd5 /drivers/i2c | |
parent | 1ee27d967c401fb0241bd412d98f140ea4f8bc3a (diff) |
i2c: tegra: Add support for clk divisor in standard/fast mode
Added support for clk divisor in standard/fast mode.
Change-Id: I2cd8a6ee80979a4967d032d064babaea2978aab3
Signed-off-by: Chaitanya Bandi <bandik@nvidia.com>
Reviewed-on: http://git-master/r/124399
Reviewed-by: Automatic_Commit_Validation_User
Reviewed-by: Laxman Dewangan <ldewangan@nvidia.com>
Diffstat (limited to 'drivers/i2c')
-rw-r--r-- | drivers/i2c/busses/i2c-tegra.c | 46 |
1 files changed, 37 insertions, 9 deletions
diff --git a/drivers/i2c/busses/i2c-tegra.c b/drivers/i2c/busses/i2c-tegra.c index 7dc9fa17a862..be2cfa407a6b 100644 --- a/drivers/i2c/busses/i2c-tegra.c +++ b/drivers/i2c/busses/i2c-tegra.c @@ -80,7 +80,10 @@ #define I2C_INT_ARBITRATION_LOST (1<<2) #define I2C_INT_TX_FIFO_DATA_REQ (1<<1) #define I2C_INT_RX_FIFO_DATA_REQ (1<<0) + #define I2C_CLK_DIVISOR 0x06c +#define I2C_CLK_DIVISOR_STD_FAST_MODE_SHIFT 16 +#define I2C_CLK_MULTIPLIER_STD_FAST_MODE 8 #define DVC_CTRL_REG1 0x000 #define DVC_CTRL_REG1_INTR_EN (1<<10) @@ -139,9 +142,12 @@ enum msg_end_type { struct tegra_i2c_chipdata { bool timeout_irq_occurs_before_bus_inactive; bool has_xfer_complete_interrupt; - u16 i2c_clock_multiplier; bool has_hw_arb_support; bool has_fast_clock; + bool has_clk_divisor_std_fast_mode; + u16 clk_divisor_std_fast_mode; + u16 clk_divisor_hs_mode; + int clk_multiplier_hs_mode; }; struct tegra_i2c_dev; @@ -485,10 +491,25 @@ static inline void tegra_i2c_clock_disable(struct tegra_i2c_dev *i2c_dev) clk_disable(i2c_dev->fast_clk); } +static void tegra_i2c_set_clk_rate(struct tegra_i2c_dev *i2c_dev) +{ + u32 clk_multiplier; + if (i2c_dev->is_high_speed_enable) + clk_multiplier = i2c_dev->chipdata->clk_multiplier_hs_mode + * (i2c_dev->chipdata->clk_divisor_hs_mode + 1); + else + clk_multiplier = I2C_CLK_MULTIPLIER_STD_FAST_MODE + * (i2c_dev->chipdata->clk_divisor_std_fast_mode + 1); + + clk_set_rate(i2c_dev->div_clk, i2c_dev->last_bus_clk_rate + * clk_multiplier); +} + static int tegra_i2c_init(struct tegra_i2c_dev *i2c_dev) { u32 val; int err = 0; + u32 clk_divisor = 0; tegra_i2c_clock_enable(i2c_dev); @@ -504,10 +525,13 @@ static int tegra_i2c_init(struct tegra_i2c_dev *i2c_dev) i2c_writel(i2c_dev, val, I2C_CNFG); i2c_writel(i2c_dev, 0, I2C_INT_MASK); - clk_set_rate(i2c_dev->div_clk, i2c_dev->last_bus_clk_rate - * i2c_dev->chipdata->i2c_clock_multiplier); + tegra_i2c_set_clk_rate(i2c_dev); - i2c_writel(i2c_dev, 0x3, I2C_CLK_DIVISOR); + clk_divisor |= i2c_dev->chipdata->clk_divisor_hs_mode; + if (i2c_dev->chipdata->has_clk_divisor_std_fast_mode) + clk_divisor |= i2c_dev->chipdata->clk_divisor_std_fast_mode + << I2C_CLK_DIVISOR_STD_FAST_MODE_SHIFT; + i2c_writel(i2c_dev, clk_divisor, I2C_CLK_DIVISOR); if (!i2c_dev->is_dvc) { u32 sl_cfg = i2c_readl(i2c_dev, I2C_SL_CNFG); @@ -853,9 +877,7 @@ static int tegra_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msgs[], } if (i2c_dev->last_bus_clk_rate != i2c_bus->bus_clk_rate) { - clk_set_rate(i2c_dev->div_clk, i2c_dev->last_bus_clk_rate - * i2c_dev->chipdata->i2c_clock_multiplier); - + tegra_i2c_set_clk_rate(i2c_dev); i2c_dev->last_bus_clk_rate = i2c_bus->bus_clk_rate; } @@ -901,17 +923,23 @@ static const struct i2c_algorithm tegra_i2c_algo = { static struct tegra_i2c_chipdata tegra20_i2c_chipdata = { .timeout_irq_occurs_before_bus_inactive = true, .has_xfer_complete_interrupt = false, - .i2c_clock_multiplier = 8, .has_hw_arb_support = false, .has_fast_clock = true, + .has_clk_divisor_std_fast_mode = false, + .clk_divisor_std_fast_mode = 0, + .clk_divisor_hs_mode = 3, + .clk_multiplier_hs_mode = 12, }; static struct tegra_i2c_chipdata tegra11_i2c_chipdata = { .timeout_irq_occurs_before_bus_inactive = false, .has_xfer_complete_interrupt = true, - .i2c_clock_multiplier = 200, .has_hw_arb_support = true, .has_fast_clock = false, + .has_clk_divisor_std_fast_mode = true, + .clk_divisor_std_fast_mode = 0x19, + .clk_divisor_hs_mode = 1, + .clk_multiplier_hs_mode = 3, }; /* Match table for of_platform binding */ |